I found myself struggling when it came to refactor the following (working) code. Since can't be found a lot of documentation about Rails 'accepts_nested_attributes_for' applied to a many-to-many relationship (furthermore, with ancillary data), I figured out it would be interesting to challenge this brave community about it! :-)
The app logic is quite simple, we have a recipe model:
class Recipe < ActiveRecord::Base  
  has_many :quantities, dependent: :destroy
  has_many :ingredients, through: :quantities   
  accepts_nested_attributes_for :quantities, :reject_if => lambda { |dq| dq[:ingredient_id].blank? || dq[:qty].blank? }, :allow_destroy => true 
  attr_accessible :name, :description, :kind  
end          
Which, of course, has many ingredients:
class Ingredient < ActiveRecord::Base 
  has_many :quantities, dependent: :destroy
  has_many :recipes, through: :quantities
  attr_accessible :name, :availability, :unit
end            
Through quantities:
class Quantity < ActiveRecord::Base 
  belongs_to :recipe
  belongs_to :ingredient
  attr_accessible :recipe_id, :ingredient_id, :qty  
  # There can be only one of each ingredient per recipe
  validates_uniqueness_of :ingredient_id, scope: :recipe_id 
  validates_numericality_of :qty, greater_than: 0 
end
Please note: every ingredient has an 'in stock' availability (and a unit of measurement for it), while every recipe needs a given 'quantity.qty*' of some ingredients in order to be prepared.
* Quantity.where(ingredient_id: ingredient.id, recipe_id: recipe.id).qty
By the way, do you know a more concise way to get some ingredient quantity.qty for some recipe?
Back to the main context, it is mainly about the following views. The difficult part regards the fact that the fields are dynamically displayed or removed through jQuery, as in this Railscast: http://railscasts.com/episodes/197-nested-model-form-part-2.
So the next one displays the form to create and edit a recipe:
<%= simple_form_for(@recipe) do |f| %>     
<%= render 'shared/error_messages', object: @recipe %>
<fieldset>
  <legend>Ricetta</legend>
  <%= f.input :name %>
  <%= f.input :description %>
  <%= f.input :kind, collection: Recipe::KINDS, prompt: "Scegli..." %>
  <%= f.input :cooked %>       
  <%= render 'quantities_fields' %>       
  <div class="form-actions">
      <%= f.button :submit, "Confirm" %>
  </div>
</fieldset>
<% end %> 
Where the quantities_fields partial is the following (now it comes the mayhem):
<fieldset class="nested">
    <legend>Ingredienti</legend>
    <ol id='ingredients'> 
        <%= render :partial => 'dummy_hidden_fields' %>
        <% for dq in @recipe.quantities %>  
        <li class="fields">
            <%= select_tag 'recipe[quantities_attributes][][ingredient_id]', 
                options_from_collection_for_select(ingredients_for_select, 'id', 'name_unit', dq.ingredient_id) -%>  
            <%= text_field_tag 'recipe[quantities_attributes][][qty]', ingredient_qty_for_select(dq), size: 3, placeholder: "Q.tà" %> 
            <!-- the id must be POST in order to trigger update instead of create when appropriate! -->
            <%= hidden_field_tag 'recipe[quantities_attributes][][id]', dq.id %>  
            <!-- the following must be changed to '1' via js in order to destroy this quantity -->  
            <%= hidden_field_tag 'recipe[quantities_attributes][][_destroy]', 0  %>
            <%= link_to_function "elimina", "remove_ingredient(this)", :class => 'btn btn-mini' %>       
        </li>   
        <% end %> 
    </ol> 
    <%= link_to_function "Add ingredient", "add_ingredient()" %>
</fieldset>    
Yes, I wasn't able to use 'fields_for' because I couldn't figure out a proper way.
The 'dummy_hidden_field" partial is used to create some initially hidden fields to be displayed through jQuery if a new ingredient is needed:
<li class="fields hidden">
    <%= select_tag 'recipe[quantities_attributes][][ingredient_id]', options_from_collection_for_select(ingredients_for_select, 'id', 'name_unit') -%>  
    <%= text_field_tag 'recipe[quantities_attributes][][qty]', nil, size: 3, placeholder: "Q.tà" %> 
    <%= hidden_field_tag 'recipe[quantities_attributes][][_destroy]', 0  %>
    <%= link_to_function "elimina", "remove_ingredient(this)", :class => 'btn btn-mini' %>  
</li>
And for last the above-mentioned jQuery functions:
function remove_ingredient(link) {
  $(link).prev("input[type=hidden]").val("1");
  $(link).closest(".fields").hide();
}
function add_ingredient() {
    var ol = $('ol#ingredients');
    ol.find('li:first').clone(true).appendTo(ol).removeClass('hidden');
}   
For any further information please don't hesitate to ask!