Topic: Common RJS error with multimodel forms ...

This is my first foray into anything to do with RJS. I've been following along with Railscast 74 as well as this very interesting thread here on Rails Forum. My aim is not the creation of multiple models in one form, but an inventory/equipment reservation system where one inventory item can belong to many loans (through orders) and one loan can consist of any number of inventory items (through orders). I therefore don't want to create multiple models in one form, but instead add any number of pre-existing inventory items to the loan.

I'm running into an RJS error that appears fairly common. It's encountered in the comments to the Railscast as well as in this thread on Rails Forum.

I get this error when I go to "Add item" (which corresponds to add_order_link)

RJS error:

TypeError: Element.insert is not a function


Followed by this:

Element.insert("orders", { bottom: "\n\n\n<div class=\"order\">\n\n\n<p>\n  <select id=\"loan_new_order_attributes__item_id\" name=\"loan[new_order_attributes][][item_id]\"><option value=\"\"></option>\n<option value=\"1\">projector</option>\n<option value=\"2\">5-foot network cable</option>\n<option value=\"3\">hammer</option>\n<option value=\"4\">peanut butter</option></select>\n  <a href=\"#\" onclick=\"$(this).up('.order').remove(); return false;\">remove</a>\n</p>\n\n\n</div>" });

Here's some code:

Item model

class Item < ActiveRecord::Base
  has_many :loans, :through => :orders
  has_many :orders
end

Loan model
class Loan < ActiveRecord::Base
  has_many :items, :through => :orders
  has_many :orders
 
  def new_order_attributes=(order_attributes)
    order_attributes.each do |attributes|
      orders.build(attributes)
    end
  end
 
  def existing_order_attributes=(order_attributes)
    orders.reject(&new_record?).each do |order|
      attributes = order_attributes[order.id.to_s]
      if attributes
        order.attributes = attributes
      else
        order.delete(order)
      end
    end
  end
 
  def save_orders
    orders.each do |order|
      order.save(false)
    end
  end
 
end

Order Model
class Order < ActiveRecord::Base
  belongs_to :item
  belongs_to :loan
end

views/loans/new.html.erb
<h1>New loan</h1>

<% form_for(@loan) do |f| %>
  <%= f.error_messages %>

  <p>
    <%= f.label :startdate %><br />
    <%= f.date_select :startdate %>
  </p>
  <p>
    <%= f.label :enddate %><br />
    <%= f.date_select :enddate %>
  </p>
  <p>
  Items:<br />
    <%= add_order_link "Add an item" %>
    <div id="order">
    <%= render :partial => 'order', :collection => @loan.orders %>
    </div>
  </p>   
  <p>
    <%= f.submit "Create" %>
  </p>
<% end %>

<%= link_to 'Back', loans_path %>


Order partial (views/loans/_order.html.erb)
<% new_or_existing = order.new_record? ? 'new' : 'existing' %>
<% prefix = "loan[#{new_or_existing}_order_attributes][]" %>

<div class="order">
<% fields_for prefix, order do |order_form| %>

<p>
  <%= order_form.collection_select(:item_id, Item.find(:all), :id, :name, :include_blank => true) %>
  <%= link_to_function "remove", "$(this).up('.order').remove()" %>
</p>

<% end %>
</div>


Loans helper (helpers/loans_helper.html.erb)
module LoansHelper
  def add_order_link(name)
    link_to_function name do |page|
      page.insert_html :bottom, :orders, :partial => 'order', :object => Order.new
    end
  end
end

Important bits from Loans controller ...
  def new
    @loan = Loan.new
    @loan.orders.build

    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @loan }
    end
  end

  def create
    @loan = Loan.new(params[:loan])

    respond_to do |format|
      if @loan.save
        flash[:notice] = 'Loan was successfully created.'
        format.html { redirect_to(@loan) }
        format.xml  { render :xml => @loan, :status => :created, :location => @loan }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @loan.errors, :status => :unprocessable_entity }
      end
    end
  end


I'm on Rails 2.2.2 and Ruby 1.8.6. I'm sure that's got something to do with it.

Re: Common RJS error with multimodel forms ...

Never mind about this ... As it turns out it's all about the positioning of those div tags, just like everybody else who has posted this problem *Groan*

Re: Common RJS error with multimodel forms ...

Hi
I have just took a look on the code you have given. At first look I couldn't find any error right now so I"ll examine it completely and revert back to you with the solution.

Re: Common RJS error with multimodel forms ...

module LoansHelper
  def add_order_link(name) 
   link_to_function name do |page|
      page.insert_html :bottom, :orders, :partial => 'order', :object => Order.new
    end
  end
end

should it be

module LoansHelper
   def add_order_link(name)
    link_to_function name do |page|
      page.insert_html :bottom, :order, :partial => 'order', :object => Order.new
    end  
  end
end

since the div id is "order"?

By the way you might find railscasts 196 and 197 useful - using accepts_nested_attributes_for in the models for forms with multiple models.

Last edited by Pasted (2010-04-29 11:23:34)

Re: Common RJS error with multimodel forms ...

fldsfslmn, could you clarify what the div problem was exactly as my divs seem to be labeled properly and I'm still experiencing this issue.
Thanks in advance.