I have a rails application that models a house.  There is a house model that has many parameters and it has_many rooms.  A room has a house_id and a name.  I've also used http://github.com/ryanb/complex-form-examples to allow many lights and small_appliances to be added to room. complex-form-example uses RJS and partials to accomplish this.
There is a controller called calculator that is what users will use to access the application.  When the submit button on calculator is pressed, it redirects to an add_rooms page (located in app/views/calculator/add_rooms.html.erb) page where the user can add rooms to the house.  The add_rooms page uses a partial from app/views/rooms/_room_form.html.erb. I haven't been able to get this to display, as rails is always looking for things in the app/views/calculator folder.
How can I get this to display? Note also that I need to save the house's id when saving the room.
Here is all of the relevant code (I hope):
If I comment out the two add_child_link. The page renders. However, when I click submit I get a new error message:
ActiveRecord::AssociationTypeMismatch in CalculatorController#add_room SmallAppliance(#49096610) expected, got Array(#1560620) RAILS_ROOT: C:/Users/ryan/Downloads/react Application Trace | Framework Trace | Full Trace C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/associations/association_proxy.rb:263:in `raise_on_type_mismatch' C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/associations/association_collection.rb:320:in `replace' C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/associations/association_collection.rb:320:in `each' C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/associations/association_collection.rb:320:in `replace' C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/associations.rb:1322:in `small_appliances=' C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:2744:in `send' C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:2744:in `attributes=' C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:2740:in `each' C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:2740:in `attributes=' C:/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.4/lib/active_record/base.rb:2438:in `initialize' C:/Users/ryan/Downloads/react/app/controllers/calculator_controller.rb:31:in `new' C:/Users/ryan/Downloads/react/app/controllers/calculator_controller.rb:31:in `add_room'
If I remove the small_application part, the same thing happens for light.  I think it has something to do with accepts_nested_attributes_for in the room model. I've added the code below. I've also added the house.rb code too.
class Room < ActiveRecord::Base
  belongs_to :house
  has_many :lights, :dependent => :destroy
  has_many :small_appliances, :dependent => :destroy
  validates_presence_of :name
  accepts_nested_attributes_for :lights, :reject_if => lambda { |a| a.values.all?(&:blank?) }, :allow_destroy => true
  accepts_nested_attributes_for :small_appliances, :reject_if => lambda { |a| a.values.all?(&:blank?) }, :allow_destroy => true         
end
class House < ActiveRecord::Base
  has_many :rooms
  # validation code not included
  def add_room(room)
    rooms << room
  end
end
class CalculatorController < ApplicationController
  def index
  end
  def save_house
    @house = House.new(params[:house])
    respond_to do |format|
      if @house.save
        format.html { render :action => 'add_rooms', :id => @house }
        format.xml { render :xml => @house, :status => :created, :location => @house }
      else
        format.html { render :action => 'index' }
        format.xml  { render :xml => @house.errors, :status => :unprocessable_entity }
      end
    end
  end
  def add_rooms
    @house = House.find(params[:id])
    @rooms = Room.find_by_house_id(@house.id)
  rescue ActiveRecord::RecordNotFound
    logger.error("Attempt to access invalid house #{params[:id]}")
    flash[:notice] = "You must create a house before adding rooms"
    redirect_to :action => 'index'
  end
  def add_room
    @house = House.find(params[:id])
    @room = Room.new(params[:room])
    respond_to do |format|
      if @room.save
        @house.add_room(@room)
        @house.save
        flash[:notice] = "Room \"#[email protected]}\" was successfully added."
        format.html { render :action => 'add_rooms' }
        format.xml { render :xml => @room, :status => :created, :location => @room }
      else
        format.html { render :action => 'add_rooms' }
        format.xml  { render :xml => @room.errors, :status => :unprocessable_entity }
      end
    end
  rescue ActiveRecord::RecordNotFound
    logger.error("Attempt to access invalid house #{params[:id]}")
    flash[:notice] = "You must create a house before adding a room"
    redirect_to :action => 'index'
  end
  def report
    flash[:notice] = nil
    @house = House.find(params[:id])
    @rooms = Room.find_by_house_id(@house.id)
  rescue ActiveRecord::RecordNotFound
    logger.error("Attempt to access invalid house #{params[:id]}")
    flash[:notice] = "You must create a house before generating a report"
    redirect_to :action => 'index'
  end
end
<div id="addRooms">
  <p>House id is <%= @house.id %></p>
  <h3>Your rooms:</h3>
  <% if @house.rooms %>
  <ul>
    <% for room in @house.rooms %>
    <li>
      <%= h room.name %> has <%= h room.number_of_bulbs %>
      <%= h room.wattage_of_bulbs %> watt bulbs, in use for
      <%= h room.usage_hours %> hours per day.
    </li>
    <% end %>
  </ul>
  <% else %>
  <p>You have not added any rooms yet</p>
  <% end %>
  <%= render :partial => 'rooms/room_form' %>
  <br />
  <%= button_to "Continue to report", :action => "report", :id => @house %>
</div>
_room_form.html.erb<% form_for :room, :url => { :action => :add_room, :id => @house } do |form| %>
  <%= form.error_messages %>
  <p>
    <%= form.label :name %><br />
    <%= form.text_field :name %>
  </p>
  <h3>Lights</h3>
  <% form.fields_for :lights do |light_form| %>
    <%= render :partial => 'rooms/light', :locals => { :form => light_form } %>
  <% end %>
  <p class="addLink"><%= add_child_link "[+] Add new light", form, :lights %></p>
  <h3>Small Appliances</h3>
  <% form.fields_for :small_appliances do |sm_appl_form| %>
    <%= render :partial => 'rooms/small_appliance', :locals => { :form => sm_appl_form } %>
  <% end %>
  <p class="addLink"><%= add_child_link "[+] Add new small appliance", form, :small_appliances %></p>
  <p><%= form.submit "Submit" %></p>
<% end %>
module ApplicationHelper
  def remove_child_link(name, form)
    form.hidden_field(:_delete) + link_to_function(name, "remove_fields(this)")
  end
  def add_child_link(name, form, method)
    fields = new_child_fields(form, method)
    link_to_function(name, h("insert_fields(this, \"#{method}\", \"#{escape_javascript(fields)}\")"))
  end
  def new_child_fields(form_builder, method, options = {})
    options[:object] ||= form_builder.object.class.reflect_on_association(method).klass.new
    options[:partial] ||= method.to_s.singularize
    options[:form_builder_local] ||= :form
    form_builder.fields_for(method, options[:object], :child_index => "new_#{method}") do |form|
      render(:partial => options[:partial], :locals => { options[:form_builder_local] => form })
    end
  end
end
Thanks,
Ryan 
Very strange — if you write <%= render :partial => 'room_form' %> than rails will assume that it is app/views/calculator/_room_form.html.erb, but in case of <%= render :partial => 'rooms/room_form' %> it will assume that it is app/views/rooms/_room_form.html.erb
Watch your log — there you will see which partials were rendered
The issue is that you don't have a room object defined when you're trying to add a child link. 
render :partial => 'rooms/room_form', :object => Room.new
                        I know this question is old but I ran into the same problem and managed to solve it.
To be specific I too was following ryan bates complex forms examples.
My form was not rendering with the same error:
undefined method `reflect_on_association' for NilClass:Class
I commented out the add_child_link helper and the form rendered but upon submission I got:
ChildModel expected, got Array
After much headscratching I made one simple change that fixed everything:
-- form_for :project
++ form_for @project
That's right, just switching the symbol for an instance variable made it all work.
Hope this helps anyone else who gets stuck
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With