Home > Back-end >  "undefined method `each'" occurs in one-to-many association in Rails console
"undefined method `each'" occurs in one-to-many association in Rails console

Time:03-29

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.

  • Related