Rails HABTM accepts_nested_attributes_for mapping table

Posted by Rabbott on Stack Overflow See other posts from Stack Overflow or by Rabbott
Published on 2010-03-10T21:19:38Z Indexed on 2010/03/16 18:11 UTC
Read the original article Hit count: 712

Currently I have a habtm relationship between a datastream (stream), and a chart. I want to be able to use the 'typical' jquery "add new stream" method to add a new entry into a mapping table that holds the chart_id, and stream_id.. But I think that most examples out there are made to handle a one to many relationship..

The functionality provided here by Ryan Bates is what I'm looking for, But I dont want to use checkboxes, I want to use a select (drop down) to add new items to the mapping table.

I need THIS and THIS combined

chart.rb

class Chart < ActiveRecord::Base
  has_and_belongs_to_many :streams, :readonly => false, :join_table => 'charts_streams'

  accepts_nested_attributes_for :streams, :reject_if => lambda { |a| a.values.all?(&:blank?) }, :allow_destroy => true

stream.rb

class Stream < ActiveRecord::Base
  has_and_belongs_to_many :charts, :readonly => false, :join_table => 'charts_streams'

application.js

/*
 * Method used to add new child form partials
 */
$('form a.add_child').click(function() {
    var assoc   = $(this).attr('data-association');
    var content = $('#' + assoc + '_fields_template').html();
    var regexp  = new RegExp('new_' + assoc, 'g');
    var new_id  = new Date().getTime();

        var newElements = jQuery(content.replace(regexp, new_id)).hide();
    $(this).parent().before(newElements).prev().slideFadeToggle();

    return false;
});

/*
 * Method used to remove child form partials
 */
$('form a.remove_child').live('click', function() {
    if(confirm('Are you sure?')) {
        var hidden_field = $(this).prev('input[type=hidden]')[0];
        if(hidden_field) {
            hidden_field.value = '1';
        }

        $(this).parents('.fields').slideFadeToggle();
    }

    return false;
});

_form.html.erb

<div id="streams">
    <h4>Streams</h4>
    <% form.fields_for :streams do |stream_form| %>
    <%= render :partial => "stream", :locals => {:f => stream_form} %>
    <% end %>
</div>

<p><%= add_child_link 'Add a stream', :streams %></p>
<%= new_child_fields_template(form, :streams) %>

_stream.html.erb

<div class="fields">
    <p>
        <%= f.label :stream_id %><br />
        <%= select_tag "chart[stream_ids][]", options_for_select(@streams.map {|s| [s.label, s.id]}, f.object.id)  %>
    </p>

    <p><%= remove_child_link 'Remove stream', f %></p>
</div>

This may be overkill and what I am looking to do could be much easier.. Basically when I create a chart I want to be able to add as many streams to it as I want, using the javascript for adding a new entry, and removing an old one... Thanks for the help!

This is 'working' but gives me a ActiveRecord::ReadOnlyRecord error when it hits the chart.update_attributes method.. am I adding the the :readonly => false in the wrong spot? Or am I just doing it completely wrong?

© Stack Overflow or respective owner

Related posts about ruby-on-rails

Related posts about nested-attributes