rails : stack level too deep - ruby-on-rails

Actually i'm on a project for a model many->many. I need to find with a current user all credits/devices/project (and I think it's useless to have a table credit with only two column (id & score) so I merge this table to the join table).
I get this error :
SystemStackError in Users#show
Showing app/views/shared/_credit.html.erb where line # raised:
stack level too deep
And the two model :
class **Credit** < ActiveRecord::Base
attr_accessible :created_at, :credit_id, :device_id, :project_id, :score, :user_id
belongs_to :device
belongs_to :user
belongs_to :project
belongs_to :score
end
class **User** < ActiveRecord::Base
has_many :credit
has_many :credit, :through => :credit, foreign_key: "user_id", dependent: :destroy
end
Thank !
Best.

Stack level to deep points to an infinitive recursive call, and I would say you get that with
has_many :credit, :through => :credit,
which clearly introduces a cycle of some sort.

Related

FactoryGirl with has_many :through associations with capybara

I have the following models:
class Productmainclass < ActiveRecord::Base
attr_accessible :name, :id, :maintext
has_many :producttaggings, :dependent => :destroy
has_many :products, :through => :producttaggings
has_many :productsubclasses
end
class Productsubclass < ActiveRecord::Base
attr_accessible :name, :id, :maintext
has_many :producttaggings, :dependent => :destroy
has_many :products, :through => :producttaggings
belongs_to :productmainclass
end
class Product < ActiveRecord::Base
attr_accessible :name, :productimage, :size, :description, :price
has_many :producttaggings, :dependent => :destroy
has_many :productsubclasses, :through => :meteoritetaggings
has_many :productmainclasses, :through => :meteoritetaggings
mount_uploader :productimage, ProductimageUploader
end
class Producttagging < ActiveRecord::Base
belongs_to :product
belongs_to :productsubclass
belongs_to :productmainclass
attr_accessible :product_id, :productsubclass_id, :productmainclass_id
end
I now want to create a Product with FactoryGirl and Capybara. In the spec I simply have:
product = FactoryGirl.create(:product)
In my factories.rb I have:
factory :product do
name "Blue glass"
description "Description text of product"
productimage File.new(File.join(::Rails.root.to_s, "spec/factories/", "testimage.jpg"), 'rb')
productsubclass
productmainclass
end
factory :productsubclass do
name "Colored glasses"
productmainclass
end
factory :productmainclass do
name "Glasses"
end
Running the test I get:
Failure/Error: product = FactoryGirl.create(:product)
NoMethodError:
undefined method `productsubclass=' for #<Product:0xcd42090>
I think the way you have it setup would work if you were dealing with a situation where :product belonged to productsubclass, then the product and the productsubclass would be created with the product.productsubclass_id nicely inserted and all would be fine, but that's clearly not your structure, so we'd have to use another way. I think the link that #depa noted is the right way to go, specifically the 'Basic has many associations' section in this document: http://robots.thoughtbot.com/aint-no-calla-back-girl although you have the added complexity of a has_many through. But essentially your looking at a situation where you create an object and then after that you trigger another create to make the many's. Hope this makes sense :)
** Update **
Here's another approach which might be a little limited but you could just create the records from the other direction. So, if you just want one record in each object/table how about this:
FactoryGirl.define do
factory :producttagging do
product
productsubclass
productmainclass
end
end

Making sum on join tables

I am creating a Rails 3.2 web app.
In this app I got four tables. Project, Task, Article and Item.
What I want to do is to get all the task values (prices from article) summed up
in a single call.
This is what I tried and it works, but is it the best way of doing it?
#project.tasks.where("status = ?", "completed").joins(:articles).sum(:price)
Task table
class Task < ActiveRecord::Base
has_many :articles
has_many :items, :through => :articles
end
Article Join Table
class Article < ActiveRecord::Base
belongs_to :task
belongs_to :item
attr_accessible :account_id, :amount, :price, :item_id, :task_id
end
Item table
class Item < ActiveRecord::Base
has_many :articles
has_many :tasks, :through => :articles
end
to sum it up it looks ok the way you did it, but also you can prettify your code:
project.rb
has_many :completed_tasks, class: 'Task', :conditions => {:status => 'completed'}
controller
#project.completed_tasks.joins(:articles).sum(:price)

Association through another table "Unknown key: through"(Rails)

I'm creating trips in my rails app and i want to add categories to those trips. The categories are stored in the Categories table in my DB and the user may select which categories are suitable for the trip. So multiple categories a trip can be used.
Although i'm a noob i figured some things out with some help of the RoR guides about this subject. Now, i've got a 3rd table tripcategories which will have to hold the trip_id and the category_id. Right? With that i've got the following models:
trip.rb:
class Trip < ActiveRecord::Base
attr_accessible :description, :title, :user_id, :triplocations_attributes, :photo
has_many :triplocations, :dependent => :destroy
has_many :tripcategories
has_many :categories, :through => :tripcategories
accepts_nested_attributes_for :triplocations, allow_destroy: true
end
category.rb:
class Category < ActiveRecord::Base
attr_accessible :name
has_many :tripcategories
belongs_to :trip, :through => :tripcategories
end
tripcategory.rb:
class Tripcategory < ActiveRecord::Base
attr_accessible :category_id, :trip_id
belongs_to :trip
belongs_to :category
end
When i'm trying it this way and trying to call trip.categories in my trip index it says "Unknown key: through". Am i doing something horribly wrong or am i missing the bigger picture?
Thanks in advance!
class Category < ActiveRecord::Base
attr_accessible :name
has_many :tripcategories
has_many :trips, :through => :tripcategories
end

How to define allow_destroy and :dependent => :destroy in Rails?

Given the following database model, how and where would you define the deletion relationships between the models? I figured out the basic table association setup but when I want to add dependencies to enable the deletion of nested objects I get lost.
Here is the relationship model I created.
class User < ActiveRecord::Base
has_many :studies
end
class Study < ActiveRecord::Base
has_many :internships
belongs_to :student, :class_name => "User", :foreign_key => "user_id"
belongs_to :subject
belongs_to :university, :class_name => "Facility", :foreign_key => "facility_id"
accepts_nested_attributes_for :subject, :university, :locations
end
class Subject < ActiveRecord::Base
has_many :studies
end
class Internship < ActiveRecord::Base
belongs_to :study
belongs_to :company, :class_name => "Facility", :foreign_key => 'facility_id'
accepts_nested_attributes_for :company, :study
end
class Facility < ActiveRecord::Base
has_many :internships
has_many :locations
has_many :studies
accepts_nested_attributes_for :locations
end
class Location < ActiveRecord::Base
belongs_to :facility
end
Where would you put :dependent => :destroy and :allow_destroy => true to enable the following scenarios? I do not want to confuse you. Therefore, I leave out my tryings.
Internship scenario: A user wants to delete an internship.
Its associated company (facility) can be deleted if the company is not related to another internship.
If so, the locations of the associated company can be deleted.
The related study will not be affected.
Study scenario: A user wants to delete a study.
Its associated subject can be deleted if no other study refers to this subject.
Its associated university (facility) can be deleted if no other study refers to this university.
Its associated internships can be deleted. The company can only be deleted if no other internship refers to it.
I am totally unsure whether I can add :dependent => :destroy only after has_one and has_many or also after belongs_to.
Edit: To simplify the problem please stick to the following (reduced) example implementation.
class Study < ActiveRecord::Base
belongs_to :subject
accepts_nested_attributes_for :subject, :allow_destroy => true
end
class Subject < ActiveRecord::Base
has_many :studies, :dependent => :destroy
end
In my view I provide the following link.
<%= link_to "Destroy", study, :method => :delete, :confirm => "Are you sure?" %>
The path is based on the named routes given by a restful configuration in routes.rb.
resources :studies
resources :subjects
The study will be deleted when I click the link - the subjects stays untouched. Why?
I think your relations are the wrong way around here...
The accepts_nested_attributes_for should be declared on the model that has_many for the model that it has_many of. Also, in your example, destroying the subject would enforce dependent_destroy on the many studies, not the other way around.
You can add :dependent => :destroy to all three but I'm not sure if that'll give you enough power to do the checks required before determining whether an associated object should be destroyed.
You have a few options.
Add a before_destroy callback on each model that raises an exception or stops the delete from occurring.
class Facility < ActiveRecord::Base
has_many :internships
has_many :locations
has_many :studies
def before_destroy
raise SomethingException if internships.any? || ...
# or
errors.add(...
end
end
or do it silently by overriding destroy
class Facility < ActiveRecord::Base
has_many :internships
has_many :locations
has_many :studies
def destroy
return false if internships.any || ...
super
end
end
Note: this is basically meant for guidance only and may not be the correct way of overriding destroy etc...

Undefined method when accessing through association and uninitialized constant when trying to destroy with :dependent => :destroy

I've tried persistently googling this error, but to no avail. I currently have these models
app/models/survey.rb
class Survey < ActiveRecord::Base
belongs_to :user
has_attached_file :original, :default_url => "/public/:class/:attachment/:basename.:extension"
has_many :sub_surveys, :dependent => :destroy
end
app/models/sub_survey.rb
class SubSurvey < ActiveRecord::Base
belongs_to :survey
has_many :questions, :dependent => :destroy
end
app/models/question.rb
class Question < ActiveRecord::Base
belongs_to :sub_survey
validates_presence_of :sub_survey
acts_as_list :scope => :sub_survey
#after_destroy :destroy_orphaned_choices
has_many :answers, :dependent => :destroy
has_many :choices, :dependent => :destroy
end
app/models/choice.rb
class Choices < ActiveRecord::Base
belongs_to :question
validates_presence_of :question
end
app/models/answer.rb
class Answer < ActiveRecord::Base
belongs_to :question
belongs_to :user
belongs_to :game
validates_uniqueness_of :question_id, :scope => [:user_id, :game_id]
end
Now when I try to destroy a survey, I get an error
uninitialized constant Question::Choice
That traces through /vendor/rails/active* stuff after the survey.destroy
Then when I try to access choices from question.Choices, I get an error
undefined method `Choices' for #<Question:0xb7224f2c>
which for some reason has this on top of the trace-stack
vendor/rails/activerecord/lib/active_record/attribute_methods.rb:256:in `method_missing'
vendor/plugins/attribute_fu/lib/attribute_fu/associations.rb:28:in `method_missing'
app/views/answers/_answer.html.erb:7:in `_run_erb_47app47views47answers47_answer46html46erb'
I do use attribute_fu when importing surveys in xml-format, but I have no idea why the trace of question.Choices has it.
I also tried renaming choices to choicealternatives, but that didn't have an effect.
Any ideas?
Your Choices table has already got a pluralised name which may be causing problems. Ideally that table should be called Choice otherwise your has_many :choices should specify the class_name option too. E.g.
has_many :choices, :class_name => 'Choices'
Though I'd opt for renaming the class and table Choice if you can.
Attachment_fu is probably appearing in the stack trace because they have overridden or aliased the method_missing method to add their own behaviour. It's not necessarily anything to be concerned about.
I'm not sure why you get the error when destroying a Survey, but you're getting this
undefined method `Choices' for #<Question:0xb7224f2c>
because you should be accessing it like this:
question.choices # No capitalization
I think that should solve one of the problems.

Resources