I created a association between two Models: User and Task, User has_many Tasks
, and Task belongs_to User
. In theory, this will generate User.tasks
and User.tasks=
these new methods can be used. However, when I execute the tests in the Rails console, I have an inexplicable problem:
> u1 = User.find_by_id(1)
> t1 = Task.new(name:"MY NEW TASK")
> u1.tasks = t1
Traceback (most recent call last):
2: from (irb):7
1: from (irb):7:in `rescue in irb_binding'
NoMethodError (undefined method `each' for #<Task:0x00007f2f0446f570>
Does this mean there is something wrong with the association between the two Models? How should I fix it?
CodePudding user response:
When you declare a has_many
assocation the others=
setter it creates expects the value to be an array, ActiveRecord::Relation or generally any object that responds to #each
. Its is after all an assocation with MANY other objects - not a single object.
It would work if you actually wrote:
u1 = User.find_by_id(1)
t1 = Task.new(name:"MY NEW TASK")
u1.tasks = [t1]
But thats not very idiomatic and will remove any other tasks which you probably don't want.
The idiomatic way to create a unsaved record off a has_many
assocation is:
u1 = User.find_by_id(1)
t1 = u1.tasks.new(name:"MY NEW TASK")
If you want to add a single existing record to an assocation on an object you can use the "shovel" method:
u1 = User.find_by_id(1)
t1 = Task.new(name:"MY NEW TASK")
u1.tasks << t1
This will save the record though.
CodePudding user response:
You can provide the user directly when you create a task:
u1 = User.find_by_id(1)
t1 = Task.new(name:"MY NEW TASK", user: u1)
Alternatively, create a task via u1.tasks
:
u1.tasks.create(name:"MY NEW TASK")
You should consider adding a validator to require a task is always created with a user. I assume that it doesn't make sense to create tasks that aren't assigned to a user. A validator can enforce this so you get an error when you try to create a task without a user.