質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.51%

  • Ruby on Rails

    8855questions

    Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

【Rubyonrails】ユーザー投稿の呼び出しの際のstacklevel too deepの解決方法について

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 145

ayachika

score 26

現在SNSアプリの作成をしている者です。
各ユーザーのマイページにて各ユーザーの投稿を表示させたいのですが、stack level too deepとなり、サーバーがストップしてしまいます。

こちらが該当のソースコードです。

users/show.html.erb

<% @user.posts.each do |post| %>

            <div class="title"><%= post.title %></div>
            <div class="picture"><%= image_tag post.picture.to_s %></div>
            <div class="user"><%=  link_to post.user.name, post.user %></div>
            <div class="time"><%= post.created_at.to_s(:datetime_base) %></div>
            <div class="postdetail"><%= link_to "詳細" , post,class: 'btn btn-outline-info' %></div>
            <div class="delatebtn"><%= link_to "削除" , post, class: 'btn btn-outline-info', method: :delete, data: {confirm: "投稿記事を削除しますか?", cancel: "キャンセル", commit: "削除する", title: "削除の確認"} %></div>
<% end %>   

posts_controller.rb

class PostsController < ApplicationController
    def index
        @posts = params[:tag_id].present? ? Tag.find(params[:tag_id]).posts : Post.all

        @posts = Post.page(params[:page])

    end


    def new
        @post = Post.new(flash[:board])
    end

     def create
        @post = Post.new(post_params)
        @post.user = current_user
        @Post = Post.new(
            content: params[:content],user_id: @current_user.id )


   if @post.save
      flash[:notice] = "「#{@post.title}」の記事が投稿されました!"
      redirect_to @post
    else
    redirect_to new_post_path, flash: {
      post: @post,
      error_messages: @post.errors.full_messages
    }
   end
     end



    def show
        @post = Post.find(params[:id]) 
        @comment = Comment.new(post_id: @post.id)

    end


    def edit
        @post = Post.find(params[:id])
    end

    def update
        post = Post.find(params[:id])
        post.update(post_params)
        flash[:notice] = "「#{@post.title}」の記事を更新しました!"
        redirect_to @post
    end


    def destroy

        @post = Post.find(params[:id])
        @post.delete

        flash[:notice] = "「#{@post.title}」の記事を削除しました!"
        redirect_to posts_path
    end

    private


    def post_params
        params.require(:post).permit(:title, :content, :picture, tag_ids:[])


    end

    def set_target_post
        @post = Post.find(params[:id])
    end

    def ensure_correct_user
    @post = Post.find_by(id:params[:id])
    if @post.user_id != @current_user.id
      flash[:notice] = "権限がありません"
      redirect_to("/posts/index")
    end
    end
end

users_controller.rb

class UsersController < ApplicationController

  def show
    @user = User.find(params[:id])

  end

  def new
    @user = User.new
  end

  def create

    @user = User.new(user_params)   
    if @user.save
      log_in @user
      flash[:success] = "Tsukutta!へようこそ"
      redirect_to @user
    else
      flash[:error_messages] = @user.errors.full_messages
      render 'new'
    end
  end

  def edit
    @user = User.find(params[:id])
  end


  def update
    @user = User.find(params[:id])
   if @user.update_attributes(user_params)
    flash[:success] = "プロフィールが更新されました!"
    redirect_to @user
   else
      render'edit'
   end  
  end


  private

    def user_params
      params.require(:user).permit(:name, :email, :password,
                                   :password_confirmation)
    end

end

参考にしたサイト

また、以下のサイトも参考にし、確認してみましたが当方と異なるパターンだったため、こちらに質問させていただきました。
stack level too deepのエラーを解決したい

開発環境

AWSのcloud9を使用しています。
rubyのバージョンは 2.4.1p111
railsのバージョンはRails 5.0.7 です。

どなたか解決方法をご存知の方がいらっしゃればご教示いただけないでしょうか。
よろしくお願いします。

【追記】
モデルのコードを掲載します。
user.rb

class User < ApplicationRecord
    attr_accessor :remember_token
    has_many :favorites, through: :favorites, source: :post, dependent: :destroy
    has_many :posts, through: :favorites, dependent: :destroy ,foreign_key: 'user'

    before_save { email.downcase! }
    validates :name,  presence: true, length: { maximum: 50 }
    VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i
    validates :email, presence: true, length: { maximum: 255 },
                            format: { with: VALID_EMAIL_REGEX },
                            uniqueness: { case_sensitive: false }
    has_secure_password
    validates :password, presence: true, length: { minimum: 6 }, allow_nil: true



  def self.digest(string)
    cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
                                                  BCrypt::Engine.cost
    BCrypt::Password.create(string, cost: cost)
  end


  def self.new_token
    SecureRandom.urlsafe_base64
  end


  def remember
    self.remember_token = User.new_token
    update_attribute(:remember_digest, User.digest(remember_token))
  end

  def authenticated?(remember_token)
    return false if remember_digest.nil?
    BCrypt::Password.new(remember_digest).is_password?(remember_token)
  end


  def forget
    update_attribute(:remember_digest, nil)
  end


end

post.rb

class Post < ApplicationRecord

    has_many :posts, dependent: :destroy
    has_many :comments, dependent: :delete_all
    has_many :post_tag_relations, dependent: :delete_all 
    has_many :tags, through: :post_tag_relations  
    belongs_to :user
    validates :user_id, presence: true
    default_scope -> { order(created_at: :desc) }
    # presence -> 
    # length -> 
   # validates :name, presence: true, length: { maximum: 30 }
    validates :title, presence: true, length: { maximum: 30 }
    validates :content, presence: true, length: { maximum: 1000 }


    mount_uploader :picture, PictureUploader
    validates :user, presence:true

    has_many :favorites, dependent: :destroy
    has_many :users, through: :favorites
    validates :user_id,presence: true
    validates :content, presence: true, length: { maximum: 140 }

end
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • maisumakun

    2018/11/21 08:22

    UserやPostのモデル内にはどんなコードがありますか?(users/以下の表示で起きているのであれば、PostsControllerはおそらく無関係です)

    キャンセル

  • ayachika

    2018/11/21 18:56

    maisumakun様 いつもありがとうございます。モデルのコードを追加しました。ネット上の情報で似たようなものがないか探すのですがなかなかたどり着きません。お知恵をいただければ幸いです。

    キャンセル

回答 2

checkベストアンサー

0

user.rbのアソシエーション(テーブル同士の関連付け)設定が間違っているのかもしれません。
has_many :favorites, through: :favorites, source: :post, dependent: :destroyのコードをひとまず削除してみてください。
これがstacklevel too deepの直接の原因だと思います。
ただ、この場合@user.postsで ActiveRecord::HasManyThroughAssociationNotFoundError が出ると思うので、
user.rbの
has_many :posts, through: :favorites, dependent: :destroy ,foreign_key: 'user'
has_many :posts, dependent: :destroy ,foreign_key: 'user'
としてみてください。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/21 22:33

    trochさんいつもありがとうございます・・そしてご助言通り試したところなんとアカウントページについにポストが表示されました。。本当にありがとうございます。まさかuser.rbに原因があったとは思いませんでした。ですが、なぜhas_manyのところが直接の原因となっていたのかまだ理解できていません…少しこの質問とはずれているかもしれませんが、なぜここが原因だとtrochさんは分かったのですか!?もしお時間いただけましたらコメントください。勉強したいと思います。。

    キャンセル

  • 2018/11/22 17:54

    エラー解決してよかったです。
    エラーの原因ですが、…まず今回のstacklevel too deepは再帰が深すぎる時に起きるエラーだと思います。
    (再帰とは繰り返しの一種で、関数の中でその関数自身を呼び出す処理のことです。)
    --------------------
    class Hoge
    def deep_stack
    self.deep_stack
    end
    end

    hoge = Hoge.new
    hoge.deep_stack
    --------------------
    ↑のようなコードで、deep_stackというインスタンスメソッドを呼び出すと、そのメソッド内でdeep_stackが再び呼び出され、それが延々と繰り返されてしまいます。こういう風に無限ループに陥っている時にstacklevel too deepというエラーになるのだと思います。無限ループ状態になるとコンピュータのメモリを大量に消費するので、サーバがストップしてしまうこともあります
    (今回、ayachikaさんのサーバが停止状態になったのもそれが原因かと。。。)

    次にayachikaさんはuser.rbに以下のように書いていました。
    --------------------
    has_many :favorites, through: :favorites, source: :post, dependent: :destroy
    has_many :posts, through: :favorites, dependent: :destroy ,foreign_key: 'user'
    --------------------
    has_manyのthroughオプションは多対多のテーブル同士の関連付けを設定する時に使うコードで、
    has_many :テーブル名A, through: :テーブル名B
    と書くと、中間テーブルBを経由して、テーブルAを呼び出すことが出来ます。

    では上記のコードで
    --------------------
    @user = User.find(1)
    @user.posts
    --------------------
    を実行するとどうなるでしょうか。
    @userはUserクラスのインスタンスなので、user.rbが検索されると思います。
    user.rbには
    has_many :posts, through: :favorites ...
    という記載があるので、中間テーブルfavoritesを介してpostsテーブルを所有していることがわかります。
    そこで次にfavoritesについて調べます。
    has_many :favorites, through: :favorites, source: :post, dependent: :destroy
    というコードが見つかります。
    sourceオプションはアソシエーションに別名をつけた際に、throughオプションで中間テーブルを介して最終的にアクセスするモデルを指定します。
    has_many :favorites, through: :favorites, source: :post
    というコードなので、中間テーブルfavoritesを介してpostsテーブルを所有していることがわかります。
    そこでRailsは中間テーブルfavoritesを検索して…
    なんだか同じことを繰り返していますね;
    というわけで延々とループし、stacklevel too deepが出てしまった、のだと思います。。。

    キャンセル

  • 2018/11/22 17:54

    アソシエーションについては
    https://kimuraysp.hatenablog.com/entry/2017/09/05/235816
    この辺りがわかりやすいかもしれません

    キャンセル

  • 2018/11/22 20:47

    お返事が遅くなり申し訳ありません。なるほど…丁寧なご回答本当にありがとうございます。全く想像もつかないところに落とし穴がありました(´;ω;`)今後はそういう観点でも気を付けてコードを書いていきたいとおもいます!ありがとうございます(>_<)

    キャンセル

0

使用しているメソッド(例えばloginなど)やassociationが関係している可能性もありますので、モデルファイルも見せていただけると回答しやすいかと思います。

<div class="user"><%=  link_to post.user.name, post.user %></div>


今の情報ではなんとも言えませんが、の行も怪しいかと思います。(post.user.name@user.nameでオッケーかとも思います。)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/11/21 18:57

    コメントありがとうございます。モデルファイルを掲載しておりませんでした。以前そこの部分については一度削除してサーバーにつないでみたのですが、やはりスタックレベルが深いと出てしまいました。。。

    キャンセル

同じタグがついた質問を見る

  • Ruby on Rails

    8855questions

    Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。