title: RubyOnRails 2.2 + Jquery UI Sortable & AJAX: This is how I did it. Is there a better way?
body: <p>In a Rails 2.2 project, I'm having users put together a list of projects into a portfolio object (i.e.: <code>PortfolioHasManyProjects</code>). On the page is a Rails form for regular text, titles etc., as well as 2 sortable lists; the lists are used for dragging projects from the global-project-list into your portfolio-project-list.</p>
  
  <p>It is similar to what's done here:
  <a href="http://ui.jquery.com/latest/demos/functional/#ui.sortable" rel="nofollow noreferrer">http://ui.jquery.com/latest/demos/functional/#ui.sortable</a>.</p>
  
  <p>I have the portfolio list (#drag_list) updating on change and submitting its serialized data through an AJAX call. 
  <strong>This is done in the application.js file:</strong></p>
  
  <pre><code>jQuery.ajaxSetup({ 
    'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/javascript")}
  })
  
  jQuery.fn.submitDragWithAjax = function() {
    this.submit(function() {
      $.post(this.action, $("#drag_list").sortable('serialize'), null, "script");
      return false;
    })
    return this;
  };
  
  $(document).ajaxSend(function(event, request, settings) {
    if (typeof(AUTH_TOKEN) == "undefined") return;
    // settings.data is a serialized string like "foo=bar&amp;baz=boink" (or null)
    settings.data = settings.data || "";
    settings.data += (settings.data ? "&amp;" : "") + "authenticity_token=" + encodeURIComponent(AUTH_TOKEN);
  });
  
  
  /-------------------------------------------/
  
  $(document).ready(function(){
  
      $(".ajax_drag").submitDragWithAjax();
  
      $("#drag_list").sortable({
          placeholder: "ui-selected",
          revert: true,
          connectWith:["#add_list"],
          update : function () {
              $("#drag_list").submit();
          }
      });
  
      $("#add_list").sortable({ 
          placeholder: "ui-selected",
          revert: true,
          connectWith:["#drag_list"]
      });
  </code></pre>
  
  <p>Here is where things got tricky. I wasn't sure how to deal with the serialized data and have it submit with the form to the controller in the <code>new.html.erb</code> file. So what I did was have the <code>new.js.erb</code> insert hidden form fields into <code>new.html.erb</code> with the data that I would extract in the controller.</p>
  
  <p><strong>here's the new.js.erb:</strong></p>
  
  <pre><code>$("#projects").html("");
  &lt;% r = params[:proj] %&gt;
  &lt;% order=1 %&gt;
  &lt;% for i in r %&gt;
    $("#projects").append("&lt;input type=hidden name=proj[&lt;%=order%&gt;] value=&lt;%=i%&gt; /&gt;");
    &lt;% order=order+1 %&gt;
  &lt;% end %&gt;
  </code></pre>
  
  <p><strong>which edits new.html.erb:</strong></p>
  
  <pre><code>&lt;h1&gt;New portfolio&lt;/h1&gt;
  &lt;h2&gt;The List&lt;/h2&gt;
  
  &lt;div class="list_box"&gt;
    &lt;h3&gt;All Available Projects&lt;/h3&gt;
    &lt;%= render :partial =&gt; "projects/add_list" %&gt;
  &lt;/div&gt;
  
  &lt;div class="list_box"&gt;
    &lt;h3&gt;Projects currently in your new portfolio&lt;/h3&gt;
    &lt;%= render :partial =&gt; "projects/drag_list" %&gt;
  &lt;/div&gt;
  
  &lt;div style="clear:both"&gt;&lt;/div&gt;
  &lt;br/&gt;
  &lt;br/&gt;
  
  &lt;h2&gt;Portfolio details&lt;/h2&gt;
  &lt;% form_for(@portfolio) do |f| %&gt;
    &lt;%= f.error_messages %&gt;
    &lt;h3&gt;Portfolio Name&lt;/h3&gt;
    &lt;p&gt;
      &lt;%= f.text_field :name %&gt;
    &lt;/p&gt;
    &lt;h3&gt;URL&lt;/h3&gt;
    &lt;p&gt;
      &lt;%= f.text_field :url %&gt;
    &lt;/p&gt;
    &lt;h3&gt;Details&lt;/h3&gt;
    &lt;p&gt;
      &lt;%= f.text_area :details %&gt;
    &lt;/p&gt;
    &lt;p&gt;
  
      &lt;div id="projects"&gt;
      &lt;input type="hidden" name="proj" value="" /&gt;   
      &lt;/div&gt;
  
      &lt;%= f.submit "Create" %&gt;
    &lt;/p&gt;
  &lt;% end %&gt;
  </code></pre>
  
  <p>The form then submits to the create method in the portfolio controller:</p>
  
  <pre><code>  def new
      @projects = Project.find(:all)
      @portfolio = Portfolio.new
      respond_to do |format|
        format.html # new.html.erb
        format.xml  { render :xml =&gt; @portfolio }
        format.js
      end
    end
  
  
  
  
   def create
      @portfolio = Portfolio.new(params[:portfolio])
      proj_ids = params[:proj]
      @portfolio.projects = []
      @portfolio.save
  
      proj_ids.each {|key, value| puts "Key:#{key} , Value:#{value} " }
      proj_ids.each_value {|value| @portfolio.projects &lt;&lt; Project.find_by_id(value) }
  
      respond_to do |format|
        if @portfolio.save
          flash[:notice] = 'Portfolio was successfully created.'
          format.html {  render :action =&gt; "index" }
          format.xml  { render :xml =&gt; @portfolio, :status =&gt; :created, :location =&gt; @portfolio }
        else
          format.html { render :action =&gt; "new" }
          format.xml  { render :xml =&gt; @portfolio.errors, :status =&gt; :unprocessable_entity }
        end
      end
    end
  </code></pre>
  
  <hr>
  
  <p><strong>So finally my question:</strong></p>
  
  <ol>
  <li><p>Is this a proper way of doing this? For some reason I feel it isn't, mostly because doing everything else in Rails seemed so much easier and intuitive. This works, but it was hell to get it to. There has to be a more <em>elegant</em> way of sending serialized data to the controller through AJAX calls.</p></li>
  <li><p>How would I call for different AJAX actions on the same page? Let's say I had a sortable and an autocomplete AJAX call, could I have a <code>sortable.js.erb</code> and <code>autocomplete.js.erb</code> and call them from any file? I'm not sure how to setup the controllers to respond to this.</p></li>
  </ol>