title: Rails 4: How to pass a form builder object to a nested form updated with javascript (jQuery)
body: <p>I am updating (and re-factoring) a working app from Rails 2.3 to Rails 4.0.
  This app includes a feature called "Smart Groups." A smart group builds up a search query that can be saved and re-used to find a set of "people" records.</p>
  
  <p>A Smart Group has_many Smart Group Rules and each Smart Group Rule belongs to a Property which has zero or more Operators.</p>
  
  <p>The form that creates a Smart Group also handles adding Smart Group Rules. When the Rule's Property is selected, the form should be updated to display the selected Property's associated Operators  and the field for entering the Rule's value.</p>
  
  <p>The problem is that the form needs to be updated dynamically when the property is selected in order to display the operators for the selected property. That's the part I can't seem to figure out in Rails 4.0.</p>
  
  <pre><code>class SmartGroup &lt; ActiveRecord::Base
    has_many :rules, :class_name =&gt; "SmartGroupRule", :foreign_key =&gt; "smart_group_id"
  
    accepts_nested_attributes_for :rules, reject_if: :all_blank, allow_destroy: true
  end
  
  class SmartGroupRule &lt; ActiveRecord::Base
    belongs_to :smart_group
    belongs_to :smart_group_property
    belongs_to :operator 
  end
  
  class SmartGroupProperty &lt; ActiveRecord::Base
    has_many :smart_group_rules
    has_many :property_operators
    has_many :operators, through: :property_operators  
  end
  
  class Operator &lt; ActiveRecord::Base
    has_many :property_operators
    has_many :smart_group_properties, through: :property_operators  
  end
  </code></pre>
  
  <p>An example would be:</p>
  
  <p>Smart Group: All 30-Somethings.
  Rule 1: People whose age is greater than 29.
  Rule 2: People whose age is less than 40.</p>
  
  <p>The property is "age." The "age" property has 3 selectable operators: less than, greater than, and exactly. The "value" for Rule 1 is 29 and the "value" for Rule 2 is 31.</p>
  
  <p>I'm using Ryan Bate's technique for adding multiple rules to the form from Railscast episode #196, "Nested Model Form (revised)."</p>
  
  <pre><code>#smart_groups/_form.html.erb
  &lt;%= simple_form_for(@smart_group) do |f| %&gt;
    &lt;%= f.error_notification %&gt;
  
   &lt;%= f.input :name %&gt;
   &lt;%= f.input :definition %&gt;
  
   &lt;%= f.simple_fields_for :rules do |rule_form| %&gt;
    &lt;%= render 'rule_fields', f: rule_form %&gt;
   &lt;% end %&gt;
  
   &lt;%= link_to_add_fields "Add Rule", f, :rules %&gt;
      &lt;%= f.button :submit %&gt;
  &lt;% end %&gt;
  
  #smart_groups/_rule_form.html.erb
   &lt;%= field_set_tag 'Smart Group Rule' do %&gt;
    &lt;%= f.association :smart_group_property, label_method: :prose, input_html: {class: "property_selector"} %&gt;
    &lt;span id="property-fields"&gt;
  
    &lt;/span&gt;
    &lt;%= f.hidden_field :_destroy %&gt;
    &lt;%= link_to "remove this rule", '#', class: "remove_fields" %&gt;
   &lt;% end %&gt;
  
  &lt;script type="text/javascript" charset="utf-8"&gt;
   $(".property_selector").observe_field(1, function( ) {
    var data = {'property_id' : $(this).val()};
    var url = '/smart_groups/property_selected';
    $.get(url, data, function(html) {
     $("#property_operator").html(html);
    });
   });
  &lt;/script&gt;
  #this is inline because I can't figure out how to do it unobtrusively.
  </code></pre>
  
  <p>The helper method from the Railscast.</p>
  
  <pre><code># ApplicationHelper
    def link_to_add_fields(name, f, association)
        new_object = f.object.send(association).klass.new
        id = new_object.object_id
        fields = f.fields_for(association, new_object, child_index: id) do |builder|
          render(association.to_s.singularize + "_fields", f: builder)
        end
        link_to(name, '#', class: "add_fields", data: {id: id, fields: fields.gsub("\n", "")})
    end
  
  # js.coffee
    $('form').on 'click', '.add_fields', (event) -&gt;
      time = new Date().getTime()
      regexp = new RegExp($(this).data('id'), 'g')
      $(this).before($(this).data('fields').replace(regexp, time))
      event.preventDefault()
  </code></pre>
  
  <p>This helper, along with this coffee script, successfully adds multiple smart group rule forms to the page.</p>
  
  <p>Now the problem: When a property value is selected in the rule form, the rest of the form needs to be updated with the operators for the selected property. I am using the inline js above, which uses the jQuery.observe_field plugin, to observe the property selector. The controller action is called and the id of the selected property is sent to the controller as property_id.</p>
  
  <pre><code>class SmartGroupsController &lt; ApplicationController
    def property_selected
      @property = SmartGroupProperty.find(params[:property_id])
      @partial_name = @property.short + "_fields"
    end
  end
  </code></pre>
  
  <p>This allows for a variable to be set, @partial_name.</p>
  
  <p>Then the view is updated (or "should" be updated) with the partial for the selected property's operators:</p>
  
  <pre><code>#property_selected.js.erb
  $("#property-fields").html("&lt;%= j render partial: @partial_name, locals: {f: f} %&gt;");
  </code></pre>
  
  <p>…but I don't know how to send the form builder object to the form… or if it's even possible approaching it this way with Rails 4.</p>
  
  <p>I get this error:</p>
  
  <pre><code>ActionView::Template::Error (undefined local variable or method `f' for #&lt; &lt;Class:0x007f9884088120&gt;:0x007f98824c9e98&gt;):
      1: $("#property-fields").html("&lt;%= j render partial: @partial_name, locals: {f: f} %&gt;");
    app/views/smart_groups/property_selected.js.erb:1:in                                _app_views_smart_groups_property_selected_js_erb__2922231718460238483_70146499765020'
  </code></pre>
  
  <p>How can I get the form's builder object passed from the _rule_form, through the property_selected action, and onto the updated portion of the form? Is there a better way to approach this?</p>
  
  <p>Thanks for any input/direction.</p>