Let''s say I have the model class Reader and Magazine, connected by join
model Subscription. It looks something like this
class Reader < ActiveRecord::Base
  has_many :subscriptions, :dependent => :delete_all
  has_many :magazines, :through => :subscriptions
  validates_presence_of :name
end
class Magazine < ActiveRecord::Base
  has_many :subscriptions, :dependent => :delete_all
  has_many :readers, :through => :subscriptions
end
class Subscription < ActiveRecord::Base
  belongs_to :reader
  belongs_to :magazine
  validates_presence_of :reader, :magazine
end
Now, the nascent RESTful orthodoxy appears to be that for each of these 
model classes there ought to be a controller that manages its CRUD 
operations. I admit that this has a nice ring to it, alas, it doesn''t 
seem to mesh with what I''d like to do user interface-wise. Simply put, 
I want to edit and update a reader''s name *and* their subscriptions in 
one form. The point is that the user saves (or discards) these changes 
in a single user-level transaction. What I don''t want is that changes 
to subscriptions are saved immediately, whereas changes to attributes, 
such as name, are change only on submitting the form. Also, I don''t 
want to spread editing of attributes and editing of subscriptions over 
separate views.
So, within the editing form (_form.rhtml when spit out by the scaffold 
generator), I display a table of checkboxes and magazines where 
subscriptions are shown and can''t be changed.
<!-- hidden field, to get a request param, even if no checkbox is 
selected -->
<%= hidden_field_tag reader[magazine_ids][]'', ''''
%>
<table>
  <tr>
    <td></td>
  </tr>
<% for magazine in reader.magazines %>
  <tr>
    <td><%= check_box_tag ''reader[magazine_ids][]'',
magazine.id,
              @reader.subscribed_to?(magazine) %></td>
    <td><%=h (magazine.title) %></td>
  </tr>
<% end %>
</table>
As the Rails API docs state, has_many :through associations are 
read-only. Instead, changes are handled through the join model. So, 
let''s ameliorate this shortcoming
class Reader
  def magazine_ids=(ids)
    Reader.transaction do
      subscriptions.clear
      ids.each do |magazine_id|
        subscription.create(:reader_id => id, :magazine_id => _id) 
unless magazine_id.blank?
        magazines(true) # force a reload
      end
    end
  end
  def subscribed_to?(magazine)
    subscriptions.any? { |s| s.magazine_id == magazine.id }
  end
end
Okay, this way it works. Still, surprisingly, it is more effort than 
could be expected as Rails doesn''t support this behavior out of the box
with a suitable helper and <association_singular_name>_ids= methods. 
This *may* be an indication that something is wrong. Is it? Is there a 
better way, more in keeping with CRUD and REST to achieve the same 
ends?
Michael
-- 
Michael Schuerig
mailto:michael@schuerig.de
http://www.schuerig.de/michael/