title: Rails forms: updating collection_select options based on other collection_select value using AJAX
body: <p>I'm just starting to learn Rails and I get along quite well with the built-in tools, Javascript and AJAX however are very new to me. Here's the problem:</p>
  
  <p>I have an order form. Every order belongs to a contact and can have a different billing and shipping address. collection_select boxes are used to set these values. All of this works fine if I wouldn't mind the necessary page reload to trim down the available address options, which should be limited to the addresses that belong to the selected contact.</p>
  
  <p>What is the simplest and easiest to maintain option to make this work without page reloads?</p>
  
  <p>This is what I tried to ajaxify the form before I got stuck. Let's start with an extract from <strong>views/orders/edit.html.erb</strong>:</p>
  
  <pre><code>&lt;%= nested_form_for @order, remote: true do |f| %&gt;
  ...
  &lt;%= f.label :contact_id, "Händler" %&gt;
  &lt;%= f.collection_select(:contact_id, Contact.order(:name), :id, :name) %&gt;
  
  &lt;%= f.label :billing_address_id, "Rechnungsanschrift" %&gt;    
  &lt;%= f.collection_select(:billing_address_id, Address.where(contact_id: @order.contact_id), :id, :name) %&gt;
  ...
  &lt;% end %&gt;
  </code></pre>
  
  <p>I omitted the shipping address select box as it would be same as the billing dropdown. Let's just focus on that for now.</p>
  
  <p>Here's the update action in <strong>controllers/orders_controller.rb</strong>:</p>
  
  <pre><code>def update
    @order = Order.find(params[:id])
  
    respond_to do |format|
  
      if @order.update_attributes(order_params)
        format.html { redirect_to edit_order_path, notice: "Auftrag aktualisiert." }
        format.json { render json: @order }
        format.js
      else
        render 'edit'
      end
    end
  end
  </code></pre>
  
  <p>I try to watch the contact select box for changes in order to save them immediately hoping the address selects would reflect those changes immediately too. This observer is located in <strong>assets/javascript/orders.js.erb</strong>:</p>
  
  <pre><code>$('#order_contact_id').change(function() {
    $(this).parents('form:first').submit();
  });
  </code></pre>
  
  <p>At that point I was hoping that this would be enough and data was saved already, but apparently Rails expects me to define some further instructions in <strong>views/orders/update.js.erb</strong> - here I'm helpless. This is what I came up with:</p>
  
  <pre><code>$('#order_billing_address_id').replaceWith('&lt;%= escape_javascript(collection_select(:order, :billing_address_id, Address.where(contact_id: @order.contact_id), :id, :name)) %&gt;');
  </code></pre>
  
  <p>order_billing_address_id is the id of the collection_select box for the billing addresses and I basically just want to refresh the built-in rails collection_select tag.</p>
  
  <p>This actually kind of works - if I select a different contact the address box is populated with its respective address instantly - however only if the contact doesn't have more than one associated address. When I select a contact with multiple address options the address select box sticks with the options from the last contact that had only one address. If I refresh the page manually though it shows the correct values, even for contacts with multiple addresses. So the data is definitely saved, which tells me that my <strong>update.js.erb</strong> probably is the problem.</p>
  
  <p>I watched the output of the rails dev server while selecting various contacts and the data seems to be processed, saved and retrieved just fine - I can't make out any differences in those server logs between single-address-contacts and multiple-address-contacts. According to those logs the queries and retrieved record IDs and collection match up as expected.</p>
  
  <p>What am I doing wrong here? Or more generally, is there a better approach/practice to what I'm trying to do? Please bear in mind that I'm very new to Rails and even more Javascript. Your help is very much appreciated.</p>