title: Adding\Removing items in a nested form using Rails 4 and JQuery
body: <p>I am using ruby 1.9.3 and rails 4.1.<br>
  I very new to ruby and have no previous javascripting knowledge.  </p>
  
  <p>I have a couple of simple has many relationships and one has many through relationship.  </p>
  
  <pre><code>class Service &lt; ActiveRecord::Base
    has_many :websites,   :dependent =&gt; :destroy
    has_many :timetables, :dependent =&gt; :destroy
    has_many :service_places, :dependent =&gt; :destroy
    has_many :places, through: :service_places
  end
  
  class ServicePlace &lt; ActiveRecord::Base
    belongs_to :service
    belongs_to :place
  end
  
  class Website &lt; ActiveRecord::Base
    belongs_to :service
  end
  
  class Place &lt; ActiveRecord::Base
    has_many :service_places    
    has_many :services, through: :service_places
  end
  
  class Timetable &lt; ActiveRecord::Base
    belongs_to :service
  end
  </code></pre>
  
  <p>I have create nested forms in the service form (_form.html.erb) for each of the associations which render fine, all the CRUD functions work.  </p>
  
  <pre><code>&lt;%= form_for(@service, :html =&gt; {:class =&gt; "form-horizontal", :role =&gt; "form"}) do |f| %&gt;
  
    &lt;%= render 'wcc_style/layouts/error_messages', object: @service %&gt;
  
    &lt;!-- I've skipped some of the html for the service details to just rendering the forms... --&gt;
  
    &lt;!-- Adds the Service_Places associations --&gt;
    &lt;%= f.fields_for :service_places do |service_places| %&gt;
      &lt;%= render "service_place_fields", :f =&gt; service_places %&gt;
    &lt;%end %&gt;
  
    &lt;!-- Adds the website associations via a partial --&gt;
    &lt;%= f.fields_for :websites do |website| %&gt;
      &lt;%= render "website_fields", :f =&gt; website %&gt;
    &lt;%end %&gt;
    &lt;%= link_to_add_fields "Add a website", f, :websites, "btn btn-default", "Add a new website" %&gt;
  
  
    &lt;!-- Adds the timetables associations via a partial --&gt;
    &lt;%=f.fields_for :timetables do |timetable| %&gt;
      &lt;%= render "timetable_fields", :f =&gt; timetable %&gt;
    &lt;%end %&gt;
  
    &lt;%= f.submit 'Save', :class =&gt; 'btn btn-primary' %&gt;
    &lt;%= link_to 'Cancel', services_path, :class =&gt; "btn btn-default", :role =&gt;"button" %&gt;
  
  &lt;% end %&gt;
  </code></pre>
  
  <p>Example of website partial (_website_fields.html.erb)</p>
  
  <pre><code>&lt;!-- This partial holds the websites information for main service form --&gt;
  &lt;div class="form-group"&gt; 
    &lt;%= f.label :website, :class=&gt;'col-sm-2 control-label' %&gt;
    &lt;div class="col-sm-4"&gt;
      &lt;%= f.text_field :url, :class =&gt; "form-control", :placeholder =&gt; "Service Provider Website" %&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  </code></pre>
  
  <p>What I am trying to do now is to add functionality to be able to add and remove items (eg websites, timetables, service_places) related to the service when adding\editing a service record.  I've seen a lot of posts relating to this but nothing with a good working solution using jquery and rails 4.  </p>
  
  <p>Having done some research on this I found the old railcasts 196 and 197.  These were out of date and didn't work in rails 4.  More research indicated a depreciated command.  I saw there was a newer version of the railscasts which I haven't looked at yet.  I did read the comments on the revised version and it indicates that it uses coffeescript, although I can't confirm this.  </p>
  
  <p>I have also seen links to other potential solutions using the cocoon gem and nested_form_fields.  Both seem to use HAML which I am unfamiliar with.  </p>
  
  <p>I am trying to do this using jquery, to help me understand the javascript process more than anything (because I'll need to support the development when it's complete and our standard is to use JQuery where possible).  </p>
  
  <p>I've managed to get the add sort of working in that it renders a website label and checkbox on first press but then on subsequent clicks simply renders this again for about a second before disappearing.  The position isn't where I would expect it to be either, at the top of the page, but I am sure that is down to our own styling gem which deals with the CSS.  I thought that javascript was not supposed to do a POST which is what it appears to do because it clears my other fields on each button click.  </p>
  
  <p>My first question is how can I get the add function to add a new item without clearing the other items in my services form?    </p>
  
  <p>My second question is how do I get a delete function to work.  I am assuming that the delete has to be within the form builder in the partial (eg one delete per item).  </p>
  
  <p>I've included the application helper and javascript below (cobbled together from various posts).  </p>
  
  <p>application_helper.rb
      module ApplicationHelper</p>
  
  <pre><code>  #def link_to_remove_fields(name, f)
    #  f.hidden_field(:destroy) + link_to_function(name, "remove_fields(this)")
    #end
  
    # remove link doesn't work!!!!!!!!!
    def link_to_remove_fields(name, f)
      f.hidden_field(:_destroy) + link_to_function(name, "remove_fields(this)")
    end
  
    # This now sort of works but the field disappears when it is created after about a second.  It also appears at the top of the page.  
    def link_to_add_fields(name, f, association, cssClass, title)  
      new_object = f.object.class.reflect_on_association(association).klass.new  
      fields = f.fields_for(association, new_object, :child_index =&gt; "new_#{association}") do |builder|  
        render(association.to_s.singularize + "_fields", :f =&gt; builder)  
      end  
      link_to name, "#", :onclick =&gt; h("add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")"), :class =&gt; cssClass, :title =&gt; title 
    end 
  
  end
  </code></pre>
  
  <p>application.js</p>
  
  <pre><code>function remove_fields(link) {
      $(link).prev("input[type=hidden]").val("1");
      $(link).closest(".fields").hide();
  }
  
  function add_fields(link, association, content) {
      var new_id = new Date().getTime();
      var regexp = new RegExp("new_" + association, "g")
      $(link).parent().before(content.replace(regexp, new_id));
  }
  </code></pre>
  
  <p>services_controller.rb</p>
  
  <pre><code>class ServicesController &lt; ApplicationController
    # Set the service record before each action
    before_action :set_service, only: [:show, :edit, :update, :destroy]
  
    ################################################################################
    # Create
    ################################################################################
    def create
      @service = Service.new(service_params)
  
      respond_to do |format|
        if @service.save
          format.html { redirect_to @service, notice: 'Service was successfully created.' }
          format.json { render action: 'show', status: :created, location: @service }
        else
          @service.websites.build
          @service.timetables.build
          @service.service_places.build
          format.html { render action: 'new' }
          format.json { render json: @service.errors, status: :unprocessable_entity }
        end
      end
  
    end
  
  
    ################################################################################
    # Delete
    ################################################################################
    def destroy
      @service.destroy
  
      respond_to do |format|
        format.html { redirect_to services_url , notice: 'Service was successfully deleted.' }
        format.json { head :no_content }
      end
    end
  
  
    ################################################################################
    # Edit
    ################################################################################
    def edit
      @service.websites.build
      @service.timetables.build
      @service.service_places.build
    end
  
  
    ################################################################################
    # Index
    ################################################################################
    def index
      @services = Service.order(:service_number).page params[:page]
    end
  
  
    ################################################################################
    # New
    ################################################################################
    def new
      @service = Service.new
      @service.websites.build
      @service.timetables.build
      @service.service_places.build
    end
  
  
    ################################################################################
    # Search
    ################################################################################
    def search
      @search_term = params[:search_term]
      if @search_term &amp;&amp; @search_term.strip.empty?
        redirect_to root_path
      else
        @services = Service.search(@search_term).order(:service_number).page params[:page]
      end
    end
  
  
    ################################################################################
    # Show
    ################################################################################
    def show
    end
  
  
    ################################################################################
    # Update
    ################################################################################
    def update
      respond_to do |format|
        if @service.update(service_params)
          format.html { redirect_to @service, notice: 'Service was successfully updated.' }
          format.json { head :no_content }
        else
          format.html { render action: 'edit' }
          format.json { render json: @service.errors, status: :unprocessable_entity }
        end
      end
    end
  
  
    ################################################################################
    # Private methods
    ################################################################################
    private
  
      # Use callbacks to share common setup or constraints between actions.
      def set_service
        @service = Service.find(params[:id])
      end
  
      # Never trust parameters from the scary internet, only allow the white list through.
      def service_params
        params.require(:service).permit(:service_number, :operator, :monday, :tuesday, :wednesday, :thursday, :friday, :saturday, :sunday, :bank_holiday, :search_term, websites_attributes: [:id, :service_id, :url, :_destroy], timetables_attributes: [:id, :service_id, :url, :_destroy], service_places_attributes: [:id, :service_id, :position, :place_id, :_destroy],  places_attributes: [:id, :place_name, :active, :_destroy])
      end
  
  end
  </code></pre>
  
  <p>Having scoured the internet I can't seem to find any links on how to get this working using jquery and standard ruby\rails.  Does anyone know of any links or resources that would be useful for trying to achieve this?  </p>
  
  <p>I am not adverse to using gems like cocoon or nested_form_fields, assuming I can convert the HAML to ERB and coffeescript to javascript.  Being a newbie to both ruby\rails and javascript having builders doing stuff is great but when it goes wrong I wouldn't have a clue how to fix it.  </p>
  
  <p>I appreciate any help or guidance.  </p>