I've got a polymorphic association with a has_one and it gives me an error when trying to create through association.
class User < ActiveRecord::Base
belongs_to :userable, polymorphic: true
end
class Student < ActiveRecord::Base
attr_accessible :gender, :description, :dob
has_one :user, :as => :userable
end
If I try to do:
s = Student.new
s.user.create
I get and error Undefined method create for 'nil'
But! If i change the association to has_many users then I can now preform the same lines above.
Can anyone explain why this is happening? Thanks!
The problem is that user is nil since you haven't assigned a value to it.
You should use something like:
s.build_user(...)
or
s.create_user(...)
Related
I have a polymorphic association as follows
class Attachment < ActiveRecord::Base
belongs_to :attachable, polymorphic: true
has_attached_file :file
end
Then on my user model
class User < ActiveRecord::Base
has_many :attachments, as: :attachable
The I want to be able to do the following
attachment = Attachment.create(:file => params[:attachment])
attachment.user = current_user
But I am getting a
*** NoMethodError Exception: undefined method `user=' for #<Attachment:0x007fee92901ce8>
The attachment belongs to a attachable (which is polymorphic). The proper way to set this is to do so:
attachment.attachable = current_user
I strongly recommend you to rename your relationship to the following:
class Attachment < ActiveRecord::Base
belongs_to :owner, polymorphic: true
class User < ActiveRecord::Base
has_many :attachments, as: :owner
Because the relationship's name owner is way more explicit than attachable. See for yourself:
# What is easier to understan?
attachment.attachable = current_user
# or
attachment.owner = current_user
You can't reference a polymorphic relation that way. It'd have to be
attachment.attachable = current_user
I am trying to do an update_attributes of a nested model and keep running into a mass assignment error. Here are my models:
class Lineup < ActiveRecord::Base
belongs_to :user
has_many :piece_lineups
has_many :pieces, through: :piece_lineups
accepts_nested_attributes_for :piece_lineups
end
class Piece < ActiveRecord::Base
attr_accessible :cost, :description, :name, :category
has_many :piece_lineups
has_many :lineups, through: :piece_lineups
end
class PieceLineup < ActiveRecord::Base
attr_accessible :piece
belongs_to :piece
belongs_to :lineup
end
User has_one lineup by the way. So I thought that by adding accepts_nested_attributes_for to the lineup model that it would work but it is not. Here's my form:
- #lineup.piece_lineups.build(:piece => piece)
= form_for(#lineup) do |f|
= f.fields_for :piece_lineups do |piece_lineup|
= piece_lineup.hidden_field(:piece_id, :value => piece.id)
= f.submit
and my Lineup controller action:
def update
#lineup = current_user.lineup
#lineup.update_attributes(params[:lineup])
and finally, the error:
Can't mass-assign protected attributes: piece_lineups_attributes
What am i missing here? Thanks!
accepts_nested_attributes_for creates an attribute writer -- in your case, piece_lineups_attributes= -- for passing attributes to another model. So, you need to add attr_accessible :piece_lineups_attributes to your Lineup model to make it mass-assignable.
UPDATE
There is a better way of going about this.
If you add attr_accessible :piece_ids to your Lineup model, then change your view to
= form_for(#lineup) do |f|
= f.hidden_field(:piece_ids, :value => piece.id)
= f.submit
You don't need nested attributes at all.
Mass Assignment usually means passing attributes into the call that creates an object as part of an attributes hash. So add piece_lineup's fields to your list of attr_accessors for that model, OR try this:
#lineup = current_user.lineup
#lineup.piece_id = params[:piece_id]
#lineup.save
Also see:
http://api.rubyonrails.org/classes/ActiveModel/MassAssignmentSecurity/ClassMethods.html
I'm trying to validate a model Student like this;
class Student < ActiveRecord::Base
belongs_to :room
end
I want to ensure that Room is a valid model, and with that I can only save a student only if the room is valid.
I tried to change the association to:
belongs_to :room, :validate => true
But it didnt change the behaviour..
API says:
:validate
If false, don’t validate the associated objects when saving the parent object. false by default.
So I changed the validation to room:
class Room < ActiveRecord::Base
has_many :students, :validate => true
end
but neither options solve for me
any ideas???
Give this a try...
class Student < ActiveRecord::Base
belongs_to :room
validates_associated :room
end
I'm looking at this portion of the API docs: http://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html#method-i-validates_associated
Also, be careful not to use that validation on both sides of the association!
I am using Active Record with Rails 3. I have a class User that has_many Categories. I would like to instantiate categories from user that shares the same in-memory user instance.
The default Active record behavior creates a new instance of user for each category. There is any way to change this behavior?
Here are some snippets of my code. You can notice that I tried to use :inverse_of, without success...
class Category < ActiveRecord::Base
attr_accessor :name
attr_accessible :name, :user
belongs_to :user, :inverse_of => :categories
end
class User < ActiveRecord::Base
attr_accessor :key
attr_accessible :categories, :key
has_many :categories, :inverse_of => :user
end
I have the following spec to test the desired behavior:
user = User.first
user.key = #key # key is an :attr_accessor, not mapped to db
category = user.categories.first
category.user.key.should == user.key # saddly, it fails.. :(
Any suggestions?
Thank you for reading my question!
I have two models App and Contact. App has a has_one relationship with Contact. I have declared the accepts_nested_attributes_for clause in the App model for Contact. Now, in the apps_controller, if I use the build method on the app object, I get an error for the the nil class, even though I had declared the relationship.
App.rb
class App < ActiveRecord::Base
has_one :contact_person, :dependent => :destroy
accepts_nested_attributes_for :contact_person
end
ContactPerson.rb
class ContactPerson < ActiveRecord::Base
belongs_to :app
end
apps_controller.rb
def new
#app = App.new
#app.contact_person.build
end
Could you please point me out whether am I doing anything incorrectly. I have used nested models before but have not encountered this error.
I am supposed to use #app.build_contact_person instead of #app.contact_person.build. In this way, it worked :)
Declaring association does not automatically creates it:
class App < ActiveRecord::Base
has_one :contact_person, :dependent => :destroy
accepts_nested_attributes_for :contact_person
# Adding this line should work
after_create { self.contact_person = ContactPerson.new }
end