title: Rails Nested Attributes form_for for has_many with unlimited nested models using javascript
body: <p>So I've got a pretty simple model with nested attributes set up:</p>
  
  <pre><code>class Property &lt; ActiveRecord::Base
    has_many :trees
    accepts_nested_attributes for :trees
  end
  </code></pre>
  
  <p>Then I build them in my controller:</p>
  
  <pre><code>class PropertiesController &lt; ApplicationController
  
    def new
      @property = Properties.new
      @trees = @property.trees.build
    end
  end
  </code></pre>
  
  <p>And then in my view (using slim):</p>
  
  <pre><code>= form_for @property |p|
    = p.text_field :name
  
    .tree
      = p.fields_for :trees do |t|
        = t.text_field :fruit
        = t.select :quantity, (1..1000).to_a
  
      = link_to 'Add Another Tree', new_properties_path, id: 'new-tree'
  </code></pre>
  
  <p>And then in my js (coffeescript) file, bound to the click event of the '#new-tree' anchor:</p>
  
  <pre><code>event.preventDefault()
  tree = $(event.target).parents('.tree')
  tree.after tree.clone(true)
  </code></pre>
  
  <p>This works as you would expect, however when I submit the form, only the last tree params get submitted. This is because in the generated html of the form_for I get something like this:</p>
  
  <pre><code>&lt;input type="text" id="property_trees_attributes_0_fruit" name="property[trees_attributes][0][fruit]"&gt;
  &lt;select id="property_trees_attributes_0_quantity" name="property[trees_attributes][0][quantity]" class="valid"&gt;
    &lt;option value="1"&gt;1&lt;/option&gt;
    &lt;option value="2"&gt;2&lt;/option&gt;
    &lt;option value="3"&gt;3&lt;/option&gt;
    ...
  &lt;/select&gt;
  </code></pre>
  
  <p>And when I clone this html I get the name and id with the <code>0</code> in it, though I believe it should be a <code>1</code> to add additional tree params, etc.</p>
  
  <p>I tried to compensate with the js by doing something like this:</p>
  
  <pre><code>event.preventDefault()
  tree = $(event.target).parents('.tree')
  clone = tree.clone()
  number = parseInt(clone.find('input[type=text]').attr('id').match /[0-9]/)
  next = number + 1
  clone = clone.html().replace /_(#{number})_|\[(#{number})\]/, next
  section.after clone
  </code></pre>
  
  <p>The point of the regex is to replace any numbers between two underscores or two brackets, like <code>_0_</code> or <code>[0]</code></p>
  
  <p>My regex doesn't seem to work though. It replaces <code>_0_</code> with just <code>1</code> and this solution seems messy to me anyways. I would make the regex simpler, however then I have to worry about it changing the value of the select menu options.</p>
  
  <p>Any suggestions for cleaning this up? Am I missing something really obvious?</p>