Topic: updating has_many :through collections

Hi!

I have some problems with a has_many :through relationship

has_many :workers, :through => :tasks
has_many :tasks

d = Device.new
d.save  # for id
t = d.tasks.create({:worker => Worker.find(1), :priority => 1})
t.save
d.save
puts d.tasks.inspect  # (a)
puts d.workers.inspect  # (b)
d.reload
puts d.tasks.inspect  # (c)
puts d.workers.inspect  # (d)

(a) and (c) show the expected result, but (b) is empty. This is not correct. After a reload it shows up correctly (d), but this way I loose all unsaved changes to the objects.

How can I get the correct workers collection at point (b)?

Thanks a lot!

Re: updating has_many :through collections

What I've settled on as a pattern for has_many :through is this:

device = Device.new
device.save
task = Task.create(:priority => 1})
device.tasks << task
worker = Worker.new
worker.save
worker.devices << t

Note that by associating in this way, you don't need to know anyone's id.

Re: updating has_many :through collections

Thanks a lot!

I had to think it over for quite a while. Something seemed strange to me, finally I got it:
Doing it your way, the association, which worker is assigned to which task is stated nowhere.

The relationships are:

Devices 1:n Tasks m:1 Workers

e.g. each device can have multiple tasks assigned to it. Every task is only assigned to one device. Each task has to be performed by exactly one worker. Each worker can perform multiple tasks.

Re: updating has_many :through collections

Here's a one liner if you want.

Task.create(:device => Device.create, :worker => Worker.create, :priority => 1)

Railscasts - Free Ruby on Rails Screencasts

Re: updating has_many :through collections

ryanb wrote:

Here's a one liner if you want.

Thanks. That does the same thing as line 3 in my original code.
However, it also does not update the workers collection. I have to call reload to get d.workers != nil.

Re: updating has_many :through collections

Ryan's code works right, but presumes a true hm:t association. Read http://wiki.rubyonrails.org/rails/pages … sociations for how to fake has_one :through.

Re: updating has_many :through collections

At first, I assumed, that the missing hm:t update was a standard error. After your replies, however, I wasn't sure about that any more and created a minimal application. Then I had to realise, that the update worked just fine, even with my initially posted code. I figured out, that a method called by before_save did screw up the device.workers collection (but I haven't dived deeper into it yet). Thanks for your help.