# Adding to has\_many on create and edit

**URL:** <https://www.ruby-forum.com/t/adding-to-has-many-on-create-and-edit/79333>\
**Category:** Rails\
**Created:** [March 10, 2006, 4:07am UTC](https://www.ruby-forum.com/t/adding-to-has-many-on-create-and-edit/79333 "2006-03-10T04:07:59Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Nicholas\_PSMueller](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/ad7895/32.png) [@Nicholas\_PSMueller](https://www.ruby-forum.com/u/Nicholas_PSMueller)\
**Post date:** [March 10, 2006, 4:07am UTC](https://www.ruby-forum.com/t/adding-to-has-many-on-create-and-edit/79333/1 "2006-03-10T04:07:59Z")

</div>

Hello,

I am fairly new to RoR and I have a question I hope can be solved  
elegantly (so many things are, so why not this one too?). I have a  
working solution, but I want to be sure I am doing things the “rails  
way” (having come from PHP). You could say I am looking for a little  
validation (no flames please).

I have a table of units like so:

CREATE TABLE `units` (  
`id` int(11) NOT NULL auto\_increment,  
`number` varchar(255) NOT NULL default ‘’,  
`description` text NOT NULL,  
PRIMARY KEY (`id`)  
) TYPE=MyISAM;

that has\_many :prices like so:

CREATE TABLE `prices` (  
`id` int(11) NOT NULL auto\_increment,  
`price` decimal(10,2) NOT NULL default ‘0.00’,  
`unit_id` int(11) default NULL,  
`created_at` datetime NOT NULL default ‘0000-00-00 00:00:00’,  
PRIMARY KEY (`id`),  
KEY `unit_id` (`unit_id`)  
) TYPE=MyISAM;

My goal is to be able to create a unit and set its price at the same  
time. Then, when I update a unit, should I change the price, I want  
to add a new row and time stamp to the price table.

My unit model looks like this:

* * *

## class Unit \< ActiveRecord::Base has\_many :prices has\_one :most\_recent\_price, :class\_name =\> “Price”, :order =\> ‘created\_at DESC’ end

The has\_one :most\_recent\_price lets me grab the most recent price for  
display and comparison purposes.

I can currently accomplish my aims in the controller like so:

* * *

class AdminUnitsController \< ApplicationController  
#snip

def create  
@unit = Unit.new(params[:unit])  
@unit.prices.create(“price” =\> params[:price])  
@levels = Level.find(:all, :order =\> “LPAD  
(`levels`.`elevator_number`,5,“0”) ASC”)  
@unit\_types = UnitType.find(:all, :order =\> “`unit_types`.`name`  
ASC”)  
if @unit.save  
Unit.find(@unit.id).update\_attributes(params[:unit])  
flash[:notice] = ‘Unit was successfully created.’  
redirect\_to :action =\> ‘list’  
else  
render :action =\> ‘new’  
end  
end

def update  
@unit = Unit.find(params[:id])  
unless params[:price] == @unit.most\_recent\_price.price.to\_s  
@unit.prices.build(“price” =\> params[:price])  
end  
@levels = Level.find(:all, :order =\> “LPAD  
(`levels`.`elevator_number`,5,“0”) ASC”)  
@unit\_types = UnitType.find(:all, :order =\> “`unit_types`.`name`  
ASC”)  
if @unit.update\_attributes(params[:unit])  
flash[:notice] = ‘Unit was successfully updated.’  
redirect\_to :action =\> ‘show’, :id =\> @unit  
else  
render :action =\> ‘edit’  
end  
end

## #snip end

and a \_form.rhtml like so:

* * *

\<%= error\_messages\_for ‘unit’ %\>

Number  
\<%= text\_field 'unit', 'number' %\>

Description  
\<%= text\_area 'unit', 'description' %\>

Base Price  
$\<%= text\_field\_tag 'price', @unit.most\_recent\_price.nil? ? "0.00" : @unit.most\_recent\_price.price %\>

## 

Is this the “rails way”? Is there a better way?

Specifically, is the text\_field\_tag ‘price’ construct the best way to  
show/capture the price value or is there a “rails way” of showing/  
capturing the price value and capturing it with params[] that I don’t  
know about? If there isn’t, would it be best to move the ternary  
operator statement into the model or is kosher to keep it in the view?

Thanks for any input,

Nick

---

<div class="post-metadata">

**Author:** ![Nicholas\_PSMueller](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/ad7895/32.png) [@Nicholas\_PSMueller](https://www.ruby-forum.com/u/Nicholas_PSMueller)\
**Post date:** [March 10, 2006, 4:23am UTC](https://www.ruby-forum.com/t/adding-to-has-many-on-create-and-edit/79333/2 "2006-03-10T04:23:07Z")

</div>

Hi !

2006/3/9, Nicholas P. Mueller [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> ```
> flash[:notice] = 'Unit was successfully created.'
> redirect_to :action => 'list'
> else
> render :action => 'new'
> end
> 
> ```
> 
> end

Hmm, this is too complicated. If you look at your log, you’ll see two  
updates to the database:

SQL INSERT - corresponds to “if @unit.save”  
SQL UPDATE - corresponds to  
Unit.find(@unit.id).update\_attributes(params[:unit])

You don’t really need the second line - notice you did  
Unit.new(params[:unit]) ? This has the same effect as an  
update\_attributes to an existing object.

> ```
> flash[:notice] = 'Unit was successfully updated.'
> redirect_to :action => 'show', :id => @unit
> else
> render :action => 'edit'
> end
> 
> ```
> 
> end

That looks fine.

> Is this the “rails way”? Is there a better way?

I wouldn’t say there’s a Rails way for this case. Your solution is  
pragmatic, and it works. I would have probably done it the same way.

One thing you might want to investigate. Two times you have this code:

> ```
> @levels = Level.find(:all, :order => "LPAD
> 
> ```
> 
> (`levels`.`elevator_number`,5,"0") ASC")  
> @unit\_types = UnitType.find(:all, :order =\> “`unit_types`.`name`  
> ASC”)

You should extract that to a filter, like this:

class AdminUnitsController \< ApplicationController  
before\_filter :load\_lookup\_data, :except =\> [:index, :list, :destroy]

protected  
def load\_lookup\_data  
@levels = Level.find(:all, :order =\>  
“LPAD(`levels`.`elevator_number`,5,"0") ASC”)  
@unit\_types = UnitType.find(:all, :order =\> “`unit_types`.`name`  
ASC”)  
end  
end

Hope that helps !

---

<div class="post-metadata">

**Author:** ![Nicholas\_PSMueller](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/n/ad7895/32.png) [@Nicholas\_PSMueller](https://www.ruby-forum.com/u/Nicholas_PSMueller)\
**Post date:** [March 10, 2006, 5:29am UTC](https://www.ruby-forum.com/t/adding-to-has-many-on-create-and-edit/79333/3 "2006-03-10T05:29:45Z")

</div>

Thanks for the advice!

RE: the insert followed by update, that was from some code I had cut/  
paste from another project.

RE: the filter - I was looking for a way to do something like that!  
Thanks for pointing it out to me! I’ve written a few projects where  
I was cutting and pasting the same code blocks all over and thought  
there was probably a way to do something, but hadn’t yet bothered to  
look.

Thanks so much,

Nicholas P. Mueller
