堆栈级别在创建时太深

时间:2015-10-23 07:38:25

标签: ruby-on-rails

出于某种原因,我的群组#create的堆栈级别太深了,我不记得在它开始显示此错误之前进行了任何更改。

class GroupsController < ApplicationController

 def new
  @group = current_user.company.groups.new
 end

 def create
    @group = current_user.company.groups.new(group_params)
    if @group.save
      flash[:success] = 'saved'
      redirect_to groups_path
    else
      render 'new'
    end
  end

  private

  def group_params
    params.require(:group).permit(:name, user_ids: [])
  end
end



class Group < ActiveRecord::Base
  belongs_to :company

  has_many :group_memberships
  has_many :users, through: :group_memberships
  # questions
  has_many :question_participants, as: :questionable
  has_many :questions, through: :question_participants

  accepts_nested_attributes_for :group_memberships

  validates :name, presence: true, length: { maximum: 255 }
end

和group_memberships:

class GroupMembership < ActiveRecord::Base
  belongs_to :group
  belongs_to :user
  validates :user_id, uniqueness: { scope: :group_id }
end

和用户:

# User model
class User < ActiveRecord::Base
  belongs_to :company
  # groups
  has_many :group_memberships
  has_many :group_questions, through: :groups, source: :questions
  has_many :groups, through: :group_memberships

表格:

<%= form_for @group do |f| %>

    <%= f.label :name %>
    <%= f.text_field :name, class: 'form-control', autofocus: true %>

    <%= f.label :user_ids %>
    <%= f.collection_select :user_ids, User.order(:first_name), :id, :first_name, {},
      { multiple: true } %>


  <%= f.submit class: 'btn btn-primary' %>
<% end %>

当我提交时会发生这种情况,如果有任何数据则无关紧要。

Started POST "/groups" for ::1 at 2015-10-23 09:37:08 +0200
Processing by GroupsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"5OCDQ27Aepg4ptjJdj9TF5kZkNcqE2GjnEh3OqH6gftOKLp+uIeLI3KDycImSM4WvUIRELghyVdqhURy7tLsWg==", "group"=>{"name"=>"", "user_ids"=>[""]}, "commit"=>"create"}
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 1]]
  Company Load (0.3ms)  SELECT  "companies".* FROM "companies" WHERE "companies"."id" = $1 LIMIT 1  [["id", 1]]
Completed 500 Internal Server Error in 9ms (ActiveRecord: 0.7ms)

SystemStackError - stack level too deep:
  newrelic_rpm (3.14.0.305) lib/new_relic/agent/instrumentation/middleware_tracing.rb:89:in `'

我的控制员:

4 个答案:

答案 0 :(得分:2)

请修改模型,如:

user.rb

class User < ActiveRecord::Base
  has_many :groups, through: :group_memberships
  has_many :group_memberships
end

group.rb

class Group < ActiveRecord::Base
  belongs_to :company

  has_many :group_memberships
  # questions
  has_many :question_participants, as: :questionable
  has_many :questions, through: :question_participants

  accepts_nested_attributes_for :group_memberships

  validates :name, presence: true, length: { maximum: 255 }
end

group_membership.rb

class GroupMemberhip < ActiveRecord::Base
  belongs_to :user
  belongs_to :group
end

答案 1 :(得分:1)

stack level too deep基本上意味着无限循环

你的groups#create方法中有一个无限递归的循环;我猜测 - 就像其他人一样 - 它与current_user.company.groups ...

有关
#app/models/company.rb
class Company < ActiveRecord::Base
  belongs_to :user
  has_many :groups
end

#app/models/group.rb
class Group < ActiveRecord::Base
  belongs_to :company

  has_many :memberships
  has_many :users, through: :memberships
end

#app/models/membership.rb
class Membership < ActiveRecord::Base
  belongs_to :group
  belongs_to :user
end

我认为问题是您在属于特定groups的{​​{1}}上调用company,Rails会自动认为该user属性也属于user 。 IE会调用find groups where id = [company_id] and user_id = [user_id]

如果您想在公司上创建一个群组,必须使用current_user(我认为这是造成问题的原因):

def create
    company = Company.find_by id: current_user.id
    @group  = company.groups.new group_params
    if @group.save
      flash[:success] = 'saved'
      redirect_to groups_path
    else
      render 'new'
    end
end

这不正确(最好拨打current_user.company),但会从您的通话中删除user元素。

我认为,因为您允许将用户添加到组,调用current_user,所以Rails可能会感到困惑。

如果你尝试上面的代码,它应该工作

无论如何,在一个对象上有许多不同的“连接”是不好的做法(law of demeter)。它简单地翻译成你的电话中不应该有一个“点”

current_user.groups

你通常使用alias_attribute解决这个问题,但这是另一个故事:)

更新

查看您的回购后的一些观察结果:

#app/models/user.rb
class User < ActiveRecord::Base
   has_one :company
   has_and_belongs_to_many :groups
end

#app/models/group.rb
class Group < ActiveRecord::Base
   belongs_to :company
   has_and_belongs_to_many :users
end

#app/models/company.rb
class Company < ActiveRecord::Base
    belongs_to :owner, class_name: "User", foreign_key: :user_id
    has_many :groups #-> group.users.each
end

-

#app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
    before_filter :company

    private

    def company
       current_user.company
    end
end

#app/controllers/groups_controller.rb
class GroupsController < ApplicationController
   def index
      @groups = company.groups.all
   end

   def new
      @users = User.where.not(id: current_user.id).order(:first_name)
      @group = company.groups.new
   end

   def create
      @group = company.groups.new group_params
      @group.save
   end
end

这应该允许您使用用户填充group,如下所示:

#app/views/groups/new.html.erb
<%= form_for @group do |f| %>
   <%= f.text_field :name %>
   <%= f.collection_select :user_ids, @users, :id, :first_name %>
   <%= f.submit %>
<% end %>

答案 2 :(得分:0)

问题来自many-to-many polymorphic relationshipquestions,您应该指出group has_many users,如下所示:

按以下方式更新group.rb

class Group < ActiveRecord::Base
  belongs_to :company

  has_many :group_memberships
  has_many :users, through: :group_memberships
  # questions
  has_many :question_participants, as: :questionable
  has_many :questions, through: :question_participants, as: :questionable

  accepts_nested_attributes_for :group_memberships

  validates :name, presence: true, length: { maximum: 255 }
end

答案 3 :(得分:0)

我终于找到了解决方案,经过近9个小时的直接调试工作。我会尝试写下这个详细信息,以便处于类似情况的人可以尽快解决这个问题,因为这是一个需要修复的bug。

问题是我的子弹宝石问题。如果你有宝石子弹&#39;寻找N + 1然后删除它,初始化器为我工作。

但是,如果你没有这个/或者如果你这样做,你想知道我是如何理解这就是我所做的问题:

  1. 在config / initializer /
  2. 中创建一个名为trace.rb的新文件
  3. 将此代码插入其中:
  4. -

    $enable_tracing = false
    #$trace_out = File.open(Rails.root + 'trace.txt', 'w')
    
    set_trace_func proc { |event, file, line, id, binding, classname|
      if $enable_tracing && event == 'call'
        #$trace_out.puts "#{file}:#{line} #{classname}##{id}"
        raise "crash me" if caller_locations.length > 500
      end
    }
    
    $enable_tracing = true
    

    现在重新运行(并记住重新启动rails服务器,因为它是一个初始化程序文件),这是你遇到问题的地方,它将循环解决问题。就我而言,我得到了这个:

      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
      bullet (4.14.9) lib/bullet/active_record42.rb:194:in `has_cached_counter?'
    

    并且在那里我能够使用理由并且理解问题在于子弹。但是,正如我的问题所示,我绝对没有显示错误信息,也没有办法说明这是问题。

    希望这适用于未来的人!