Quick question on updating attributes on the join model in a has_many :through relationship

The question is this: how are you supposed to do it?

I’ve seen a lot of blog posts that say that HM:T has beaten HABTM and
that
we can now all easily have data on the join model and go on to show how
to
enter that data into the join model but don’t show a recommended way of
modifying it later.

I’ve checked against a pile of books, too, as well as the AR api and
Google’s exhaustive collection of blogs. Neither The Rails Way nor Agile
Web
Development show an example that I can find.

Obviously this is something really simple that I have missed so if
someone
could please post a link to the place where it is actually demonstrated
that
would be wonderful.

Taking the example from
has_many :through - New on edge: Magic join model creation if
you’re
unsure what I mean:

That automagically creates the join record with the role attribute set
to

has_many :contributors, :through => :contributions, :uniq => true
end

That’s brilliant (although I suspect it will break now because at some
point
with_scope got removed from public so I’m not sure what people suggest
nowadays).

What if you added another field to contributions? Let’s say, for lack of
a
better example, time_spent. This is how you are supposed to find it, as
far
as I can tell:

dave = Contributor.find_by_name “Dave”
book = Book.find_by_title “Agile Web D. with Rails”

contribution = Contribution.find_by_book_id_and_author_id book.id,
dave.id

And then you can now go

contribution.time_spent = 9.months

But surely there is a way to get that contribution object out of the
collection proxy? Something like:

contribution = dave.books.proxy_object(dave.books.first)
or
contribution = dave.books.proxy_objects.first

(Yes, I realise this would be essentially the same thing, but the method
I
showed first strikes me as being very non-rails).

So, is there some wonderful resource where this has been demonstrated
that
I’ve just missed?

Cheers,
Morgan.

Morgan G. - Just Landed
General Tel: +34 91 590 2611
[email protected]

http://www.justlanded.com - Helping people abroad!
30 countries, in up to 8 languages, more to come…

Is this question too confusing or too obvious to warrant a response from
somebody?

Morgan.

2008/6/16 Morgan G. [email protected]:

Obviously this is something really simple that I have missed so if someone
could please post a link to the place where it is actually demonstrated that
would be wonderful.

Morgan G. - Just Landed
General Tel: +34 91 590 2611
[email protected]

http://www.justlanded.com - Helping people abroad!
30 countries, in up to 8 languages, more to come…

Thanks for that.

The basic answer is that you just have to manually find the join model
and
then modify that as necessary. Which is what I was doing but which I
thought
was silly because hey, this is Rails, there has to be an easier way to
do
it. :slight_smile:

Cheers.

2008/6/16 Pardee, Roy [email protected]:

railscasts on “complex forms” for the gory details.

HTH,

-Roy


**

Morgan G. - Just Landed
General Tel: +34 91 590 2611
[email protected]

http://www.justlanded.com - Helping people abroad!
30 countries, in up to 8 languages, more to come…

Well, with HM:T, you’ve got an actual model to work with–so you can do
all the regular things you do w/models–.new them, .update them, etc.
In a view, you’d do a form_for & pass in a reference to an instance o
your join model. The things you’re joining can be represented via say,
collection_select’s modifying the respective <>_id fields in
your join model.

If the goal is allowing create/edit on views devoted to one or both of
the joined models, you can treat those exactly as if they were just a
regular has_many–so, field_for, w/an appropriately engineered name.
See the railscasts on “complex forms” for the gory details.

HTH,

-Roy


From: [email protected]
[mailto:[email protected]] On Behalf Of Morgan G.
Sent: Monday, June 16, 2008 9:02 AM
To: [email protected]
Subject: [Rails] Re: Quick question on updating attributes on the join
model in a has_many :through relationship

Is this question too confusing or too obvious to warrant a response from
somebody?

Morgan.

2008/6/16 Morgan G. [email protected]:

The question is this: how are you supposed to do it?

I’ve seen a lot of blog posts that say that HM:T has beaten
HABTM and that we can now all easily have data on the join model and go
on to show how to enter that data into the join model but don’t show a
recommended way of modifying it later.

I’ve checked against a pile of books, too, as well as the AR api
and Google’s exhaustive collection of blogs. Neither The Rails Way nor
Agile Web D. show an example that I can find.

Obviously this is something really simple that I have missed so
if someone could please post a link to the place where it is actually
demonstrated that would be wonderful.


Morgan G. - Just Landed
General Tel: +34 91 590 2611
[email protected]


http://www.justlanded.com - Helping people abroad!
30 countries, in up to 8 languages, more to come…

Well, not necessarily–in those railscasts I mentioned, they show how to
use pseudo-attributes on one of the ‘parent’ models to
create/update/delete associated instances of a join model. For example,
here’s a bit of my Project model class (which represents research
projects) that manages the associations between projects and research
areas:
class Project < ActiveRecord::Base
has_many :projects_research_areas, :dependent => :delete_all
has_many :research_areas, :through => :projects_research_areas
def new_research_area_attributes=(raa)
raa.each do |ra|
projects_research_areas.build(ra)
end
end
def existing_research_area_attributes=(raa)
projects_research_areas.each do |ra|
attributes = raa[ra.id.to_s]
if attributes
ra.attributes = attributes
ra.save
else
projects_research_areas.delete(ra)
end
end
end
end # class Project
Those *research_area_attributes=() methods get called (as if by magic
:wink: when the project controller says e.g., Project.new(params[:project])
and they create/update/delete associated instances of the join model as
necessary. You direct a given instance of a join model to either the
new
or existing_ version by setting the first argument to fields_for()
to the right string. Check out railscasts 73-75 (IIRC) for the full
story. See especially the updated code posted on the episode 75 page.

HTH,

-Roy


From: [email protected]
[mailto:[email protected]] On Behalf Of Morgan G.
Sent: Tuesday, June 17, 2008 2:48 AM
To: [email protected]
Subject: [Rails] Re: Quick question on updating attributes on the join
model in a has_many :through relationship

Thanks for that.

The basic answer is that you just have to manually find the join model
and then modify that as necessary. Which is what I was doing but which I
thought was silly because hey, this is Rails, there has to be an easier
way to do it. :slight_smile:

Cheers.

2008/6/16 Pardee, Roy [email protected]:

Well, with HM:T, you’ve got an actual model to work with–so you
can do all the regular things you do w/models–.new them, .update them,
etc. In a view, you’d do a form_for & pass in a reference to an
instance o your join model. The things you’re joining can be
represented via say, collection_select’s modifying the respective
<>_id fields in your join model.

If the goal is allowing create/edit on views devoted to one or
both of the joined models, you can treat those exactly as if they were
just a regular has_many–so, field_for, w/an appropriately engineered
name. See the railscasts on “complex forms” for the gory details.

HTH,

-Roy



Morgan G. - Just Landed
General Tel: +34 91 590 2611
[email protected]


http://www.justlanded.com - Helping people abroad!
30 countries, in up to 8 languages, more to come…