# Render partials with nested attributes from another model

**URL:** <https://www.ruby-forum.com/t/render-partials-with-nested-attributes-from-another-model/177257>\
**Category:** Rails\
**Created:** [October 14, 2009, 7:50am UTC](https://www.ruby-forum.com/t/render-partials-with-nested-attributes-from-another-model/177257 "2009-10-14T07:50:34Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ryan\_Tinsley](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/r/aeb1de/32.png) [@Ryan\_Tinsley](https://www.ruby-forum.com/u/Ryan_Tinsley)\
**Post date:** [October 14, 2009, 7:50am UTC](https://www.ruby-forum.com/t/render-partials-with-nested-attributes-from-another-model/177257/1 "2009-10-14T07:50:34Z")

</div>

Hi everyone,

My previous question was posted  
here[http://groups.google.com/group/rubyonrails-talk/browse\_thread/thread/dddaeb075789d4b5](http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/dddaeb075789d4b5).  
I’m starting a new topic as the problems have shifted.

I have a rails application that models a house. There is a house model  
that  
has\_many rooms. A room has a house\_id and a name. I’ve also used the  
complex-form-examples to give room nested attributes of lights and  
small\_appliances. complex-form-examples 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  
saves house information and redirects to an add\_rooms page (located in  
app/views/calculator/add\_rooms.html.erb) 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 can get this page to display by  
removing the add\_child\_link links. If I don’t remove them, I get this  
error:

Showing app/views/rooms/\_room\_form.html.erb where line #13 raised:

undefined method `reflect\_on\_association’ for NilClass:Class

With add\_child\_link gone 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 need to get this page working so that rooms can be added to a  
house  
without using the scaffold built pages. Users won’t have access to  
those. I  
also need the house id to be saved as house\_id in the rooms table. Here  
is  
the code:

_app/models/room.rb_

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

_app/models/house.rb_

class House \< ActiveRecord::Base  
has\_many :rooms

# validation code not included

def add\_room(room)  
rooms \<\< room  
end

end

_app/controllers/calculator\_controller.rb_

class CalculatorController \< ApplicationController  
def index  
end

# save\_house is called when submit is

# pressed in app/views/calculator/index.html.erb

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 \"#removed_email_address@domain.invalid}\" 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

_app/views/calculator/add\_rooms.html.erb_  
&lt;div id=“addRooms”&gt;  
 &lt;p&gt;House id is  
&lt;%= @house.id %&gt;&lt;/p&gt;  
  
  
&lt;h3&gt;Your rooms:&lt;/h3&gt;  
 &lt;% if  
@house.rooms %&gt;  
 &lt;ul&gt;  
 &lt;% for room in  
@house.rooms %&gt;  
 &lt;li&gt;  
 &lt;%= h  
room.name%&gt; has &lt;%= h room.number\_of\_bulbs %&gt;  
  
&lt;%= h  
room.wattage\_of\_bulbs %&gt; watt bulbs, in use for  
 &lt;%= h  
room.usage\_hours %&gt; hours per day.  
 &lt;/li&gt;  
  
&lt;% end %&gt;  
 &lt;/ul&gt;  
 &lt;% else  
%&gt;  
 &lt;p&gt;You have not added any rooms  
yet&lt;/p&gt;  
 &lt;% end %&gt;  
  
 &lt;%=  
render  
:partial =&gt; ‘rooms/room\_form’ %&gt;  
  
 &lt;br  
/&gt;  
 &lt;%= button\_to “Continue to report”, :action  
=&gt;  
“report”, :id =&gt; @house %&gt;  
&lt;/div&gt;

_app/views/rooms/\_room\_form.html.erb_

&lt;% form\_for :room, :url =&gt; { :action =&gt;  
:add\_room, :id =&gt; @house } do |form| %&gt;  
&lt;%= form.error\_messages %&gt;  
&lt;p&gt;  
&lt;%= form.label :name %&gt;&lt;br /&gt;  
&lt;%= form.text\_field :name %&gt;  
&lt;/p&gt;

&lt;h3&gt;Lights&lt;/h3&gt;  
&lt;% form.fields\_for :lights do |light\_form| %&gt;  
&lt;%= render :partial =&gt; ‘rooms/light’, :locals  
=&gt; { :form =&gt; light\_form } %&gt;  
&lt;% end %&gt;  
&lt;p class=“addLink”&gt;&lt;%= add\_child\_link “[+] Add  
new light”, form, :lights %&gt;&lt;/p&gt;

&lt;h3&gt;Small Appliances&lt;/h3&gt;  
&lt;% form.fields\_for :small\_appliances do |sm\_appl\_form|  
%&gt;  
&lt;%= render :partial =&gt; ‘rooms/small\_appliance’,  
:locals =&gt; { :form =&gt; sm\_appl\_form } %&gt;  
&lt;% end %&gt;  
&lt;p class=“addLink”&gt;&lt;%= add\_child\_link “[+] Add  
new small appliance”, form, :small\_appliances  
%&gt;&lt;/p&gt;

&lt;p&gt;&lt;%= form.submit “Submit”  
%&gt;&lt;/p&gt;  
&lt;% end %&gt;

_application\_helper.rb_

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

_public/javascripts/application.js_

function insert\_fields(link, method, content) {  
var new\_id = new Date().getTime();  
var regexp = new RegExp(“new\_” + method, “g”)  
$(link).up().insert({  
before: content.replace(regexp, new\_id)  
});  
}

function remove\_fields(link) {  
var hidden\_field = $(link).previous(“input[type=hidden]”);  
if (hidden\_field) {  
hidden\_field.value = ‘1’;  
}  
$(link).up(“.fields”).hide();  
}

Thanks,  
Ryan
