title: Join table attribute updates in Many-to-Many Relation
body: <p>I have a many-to-many relation setup for a data model which deals with a problem domain of Members and Addresses.  Basically a 'member' can have multiple 'addresses', think of like when you have a work address and a home address.  </p>
  
  <p>I want to store additional attributes on the join table and save data, apart from the foreign key attributes.  There are many examples on the net about many-to-many relations, but I've not found details/examples on storing the extra data.</p>
  
  <p>Here is the problem that i'm stuck with.</p>
  
  <p>The models are setup as:</p>
  
  <p><strong>Models</strong></p>
  
  <pre><code>class Member &lt; ActiveRecord::Base
     has_many :member_addresses
     has_many :addresses, :through =&gt; :member_addresses
  end
  
  class MemberAddress &lt; ActiveRecord::Base
     belongs_to :address   # foreign key for address -&gt; address_id
     belongs_to :member    # foreign key for member -&gt;member_id
  end
  
  class Address &lt; ActiveRecord::Base
     has_many :member_addresses
     has_many :members, :through =&gt; :member_addresses
  
     accepts_nested_attributes_for :members, :allow_destroy =&gt; true
  end
  </code></pre>
  
  <p>The 'accepts_nested_attributes' on the Address class is for the nested-forms.</p>
  
  <p><strong>Database Schema/Migrations</strong>
  The tables (simplified for posting) are defined as</p>
  
  <pre><code>create_table "addresses", :force =&gt; true do |t|
      t.string  "firstline"
      t.string  "state"
      ....
  end
  
  create_table "member", :force =&gt; true do |t|
      t.string "name"
      ....
  end
  
  create_table "member_addresses", :force =&gt; true do |t|
     t.integer "member_id"
     t.integer "address_id"
     t.string  "address_type"
  end
  </code></pre>
  
  <p>The field 'address_type' on the join table is intended for flagging the type of the address that is associated with the member (aka; "home" or "work")</p>
  
  <p><em><strong>It is updating this field that is where I'm getting stuck.</em></strong></p>
  
  <p><strong>Controllers &amp; View</strong></p>
  
  <p>The member_controller setups the model like:</p>
  
  <pre><code>members_controller.rb
  def new
     @member = Member.new
     @member.addresses.build    #pre-build the associated address
  end
  </code></pre>
  
  <p>Then the view for the member page <strong>new</strong> action is</p>
  
  <p>&lt;%= form_for @member do |m| %></p>
  
  <pre><code>  &lt;%= m.label :first_name, "First Name"%&gt;
    &lt;%= m.text_field :first_name %&gt;
    &lt;/p&gt;
  
    &lt;%= m.fields_for :addresses do |addrform|%&gt;
      &lt;%= addrform.label :firstline %&gt;
      &lt;%= addrform.text_field :firstline %&gt;
    &lt;% end %&gt;
  
    &lt;br /&gt;
    &lt;%= label_tag 'Type of address' %&gt;
    &lt;%= text_field_tag 'addrtype'    %&gt;
    &lt;br /&gt;
    &lt;%= m.submit "Add" %&gt;&lt;br /&gt;
  </code></pre>
  
  <p>&lt;% end %></p>
  
  <p>The idea is that with the 'accepts_nested_attributes' on the <strong>Member</strong> model I can enter the data on the form to add in the name and address attributes.  The additional <strong>label_tag</strong> is for the data to be posted for the address type that I want to store </p>
  
  <p>So when the form is filled in the post data (form a trap) looks like:</p>
  
  <pre><code>{"utf8"=&gt;"âœ“",
       "authenticity_token"=&gt;"E0R038rcdJmBGjjxQ9nQLHGVbzM4ejA0vsEaIvqkwkE=",
       "member"=&gt;{"first_name"=&gt;"James",
       "last_name"=&gt;"SMith",
       "addresses_attributes"=&gt;{"0"=&gt;{"firstline"=&gt;"this is the first line"}}},
       "addrtype"=&gt;"home",
       "commit"=&gt;"Add"}
  </code></pre>
  
  <p>All good - i'm getting my <strong>Member</strong> data and the <strong>Address</strong> data, as well as the additional field 'addrtype' which is to be used for carrying my additional data</p>
  
  <p>Now how to get the data into the relation or join table ?  On the <strong>member_controller create action</strong> </p>
  
  <pre><code>def create
     # create a member with the params posted 
     @member = Member.new(params[:member])
  
     # get data for 'relation data'
     @addr_type = params[:addrtype]
  
  
  
    if @member.save!
        #update the relation now created with the address type
        @member.member_addresses.first.address_type = @addr_type
  
        # save the relationship (is this necessary?)
        @member.save!
  
        redirect_to members_path
    end
  </code></pre>
  
  <p>As you can see in the <strong>create</strong> I'm attempting to fill in the data on the join table and then force a save again so that the relation or association with the additional attribute is saved.  </p>
  
  <p>This doesn't work, and/or I'm doing it wrong.</p>
  
  <p>Any suggestions would be most appreciated.</p>