Reputation: 1608
For some reason I'm getting stack level too deep on my group#create, and I can't recall making any changes before it started showing this error.
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
and group_memberships:
class GroupMembership < ActiveRecord::Base
belongs_to :group
belongs_to :user
validates :user_id, uniqueness: { scope: :group_id }
end
and user:
# 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:
<%= 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 %>
it happens when I submit, irrelevant if there's any data there or not.
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 `'
my controller:
Upvotes: 1
Views: 877
Reputation: 1608
I finally found a solution, after almost 9 hours straight working on debugging this. I'll try to write this detailed so people in a similar situation can fix this asap, because this is one hell of a bug to fix.
The issue was a problem with my bullet gem. If you have 'gem bullet' to look for N+1 then removing it and the initializer worked for me.
However if you don't have this / or if you do and you want to see how I figured out that it was the problem what I did was:
-
$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
now re-run (and remember to restart your rails server because it's an initializer file) the place where you get the issue, and it will loop over the problem. In my case I got this:
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?'
and for there I was able to use reason and understand that the problem was with bullet. However as seen in my question I had absolutely no error message displaying and no way of telling that this was the issue.
Hope this works for future people!
Upvotes: 0
Reputation: 76784
stack level too deep
basically means infinite loop
You've got an infinitely recursive loop in your groups#create
method somewhere; I'd surmise - like the others - that it's do with 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
I think the problem is that you're calling groups
on a company
belonging to a particular user
, which Rails will automatically assume to have a user
attribute too. IE it will call find groups where id = [company_id] and user_id = [user_id]
If you want to create a group on a company, you don't have to use current_user
(I think this is what's causing the problem):
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
This is not correct (it will be best to call current_user.company
), but it will remove the user
element from your call.
I think that because you're allowing the addition of users to groups, and calling current_user
, Rails is getting might confused.
If you try the above code it should work
Anyway, it's bad practice (law of demeter) to have many different "connections" on a single object. It translates simply into you shouldn't have more than one "dot" in your calls:
current_user.groups
You generally get around this by using alias_attribute
, but that's another story :)
Some observations after looking at your repo:
#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
This should allow you to populate the group
with users as follows:
#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 %>
Upvotes: 1
Reputation: 1132
The problem coming from the many-to-many polymorphic relationship
with questions
and you should indicate that the group has_many users
as shown below:
Update the group.rb
as the following:
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
Upvotes: 0
Reputation: 1601
Please modify the model like:
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
Upvotes: 2