# Problem with a setter that converts euros to cents

**URL:** <https://www.ruby-forum.com/t/problem-with-a-setter-that-converts-euros-to-cents/62713>\
**Category:** Rails\
**Created:** [June 7, 2006, 3:00pm UTC](https://www.ruby-forum.com/t/problem-with-a-setter-that-converts-euros-to-cents/62713 "2006-06-07T15:00:28Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![carlosparamio](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/f1d935/32.png) [@carlosparamio](https://www.ruby-forum.com/u/carlosparamio)\
**Post date:** [June 7, 2006, 3:00pm UTC](https://www.ruby-forum.com/t/problem-with-a-setter-that-converts-euros-to-cents/62713/1 "2006-06-07T15:00:28Z")

</div>

Hi,

I have some problems with an application where I’m using custom  
accessors to do currency conversions. In my model, I have a price  
attribute in the database that stores the value in cents, to avoid  
future problems with float arithmetic and round. But at the views, I  
would like to show the price in euros, with decimal for the cents. So  
I defined a new attribute called price\_in\_euros, and the corresponding  
accesors:

class Report \< ActiveRecord::Base  
validates\_numericality\_of :price, :only\_integer =\> true

```
attr_accessor :price_in_euros

def price_in_euros
	if self.price
		self.price / 100.0
	else
		# default price is 1 euro
		1
	end
end

def price_in_euros=(euros)
	self.price = (euros * 100).to_i
end

```

end

If I test this model with the rails console, all is working fine:

$ script/console  
Loading development environment.

> > r = Report.new  
> > =\> #\<Report:0xb74a53c0 @new\_record=true, @attributes={“precio”=\>nil}\>  
> > r.price\_in\_euros = 2.45  
> > =\> 2.45  
> > r.save  
> > =\> true  
> > r  
> > =\> #\<Report:0xb74a53c0 @new\_record\_before\_save=true,  
> > @new\_record=false, @errors=#\<ActiveRecord::Errors:0xb7813264  
> > @errors={}, @base=#\<Report:0xb74a53c0 …\>\>, @attributes={“id”=\>20,  
> > “price”=\>245}\>

The attribute “price” has been set to 245 cents. Ok, let’s check the  
database:

mysql\> select id, price from reports;  
±—±------+  
| id | price |  
±—±------+  
| 20 | 245 |  
±—±------+  
1 row in set (0.00 sec)

It seems that all is ok. Well, let’s prepare a controller with a  
couple of actions, insert and edit:

class ReportController \< ApplicationController  
def insert  
@report = Report.new(params[:report])  
if @request.post? and @report.save  
redirect\_to :action =\> ‘list’  
end  
end

```
def edit
	@report = Report.find(params[:id])
	@report.attributes = params[:report]
	if @request.post? and @report.save
		redirect_to :action => 'list'
	end
end

```

end

Here is part of the view for the insert action:

\<% form\_for :report, :url =\> { :action =\> ‘insert’ } do |form| %\>  
Price: \<%= form.text\_field :price\_in\_euros -%\>  
\<%= submit\_tag ‘Insert’ -%\>

Here is part of the view for the edit action:

\<% form\_for :report, :url =\> { :action =\> ‘edit’ } do |form| %\>  
Price: \<%= form.text\_field :price\_in\_euros -%\>  
\<%= submit\_tag ‘Save’ -%\>

Ok. Now I use that views to insert a couple of new reports, giving a  
value of 2.45 for the first one and 1 for the second one. Here is what  
it appears at the database:

mysql\> select id,price from reports;  
±—±-----------+  
| id | price |  
±—±-----------+  
| 24 | 2 |  
| 25 | 2147483647 |  
±—±-----------+  
2 rows in set (0.00 sec)

Ouch! That’s really strange.

And if I try to edit them, I can see a value of 0.02 on the price  
field for the first one, and 21474836.47 for the second one (the price  
at the database divided by 100), so the getter accesor seems to be  
working well, but not the setter. If I click ‘Save’ on the edit form,  
I then get:

mysql\> select id,price from reports;  
±—±---------+  
| id | price |  
±—±---------+  
| 24 | 0 |  
| 25 | 21474836 |  
±—±---------+  
2 rows in set (0.00 sec)

## What in the hell I’m doing bad? Thanks in advance.

Carlos Alberto Paramio Danta .–.  
[http://www.sinfoniadebits.com/](http://www.sinfoniadebits.com/) |o\_o |  
email : carlosparamio @ [gmail.com](http://gmail.com) |:\_/ |  
jabber: parax @ jaim.at // \   
----------------------------------------( | | )–  
Fingerprint 41C6 D2BE 7DE7 AB61 C23F /'\_ _/`  
F697 5A1D 1849 01B8 D318 \_**)=(**_/

---

<div class="post-metadata">

**Author:** ![carlosparamio](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/f1d935/32.png) [@carlosparamio](https://www.ruby-forum.com/u/carlosparamio)\
**Post date:** [June 7, 2006, 3:50pm UTC](https://www.ruby-forum.com/t/problem-with-a-setter-that-converts-euros-to-cents/62713/2 "2006-06-07T15:50:32Z")

</div>

I think you may find that the problem is that you are getting a string  
from  
the html form. Hence it works in irb when you pass a float, but coming  
from  
the web form it’s unreliable.

There are a couple of things that you could do. Probably one of the  
more  
robust is to convert the incoming parameter to a float inside the  
method.  
eg

def price\_in\_euros=(ammt)  
self.price = (ammt.to\_f \* 100 ).to\_i  
end

There are issues with this tho… If the user enters some dodgy input  
eg.  
“abcd” the method will set your price to zero, or if they don’t enter  
anything there is a problem as well.

One solution to this is to put in a callback hook to the before\_save  
callback that checks this value and sets it to a default if it’s zero  
There  
are shortcommings with this as well tho particularly with validations  
They  
will spit back errors if set for price \> 0

def before\_save  
self.price = 100 if (self.price.nil? or self.price \< 1)  
end

This way you can use an int or a string for the operation. and you know  
that  
if the value is not specified then one euro (100 in the price field) is  
set  
in the database.

Also since you are specifying these getter and setter methods the call  
to  
attr\_accessor :price\_in\_euros  
is redundant since your over-writing the methods that this sets up.

---

<div class="post-metadata">

**Author:** ![carlosparamio](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/f1d935/32.png) [@carlosparamio](https://www.ruby-forum.com/u/carlosparamio)\
**Post date:** [June 8, 2006, 8:33am UTC](https://www.ruby-forum.com/t/problem-with-a-setter-that-converts-euros-to-cents/62713/3 "2006-06-08T08:33:54Z")

</div>

Hi Daniel,

> I think you may find that the problem is that you are getting a string from  
> the html form. Hence it works in irb when you pass a float, but coming from  
> the web form it’s unreliable.

Yes! That was. Now works really well.

> One solution to this is to put in a callback hook to the before\_save  
> callback that checks this value and sets it to a default if it’s zero There  
> are shortcommings with this as well tho particularly with validations They  
> will spit back errors if set for price \> 0
> 
> def before\_save  
> self.price = 100 if (self.price.nil? or self.price \< 1)  
> end

Great, this warranties a sensible value for the price attribute.

> Also since you are specifying these getter and setter methods the call to
> 
> attr\_accessor :price\_in\_euros  
> is redundant since your over-writing the methods that this sets up.

I supossed it, but I had some other error message in my view, and I  
thinked that it was due to the attribute name used in the new way of  
form definitions:

form.text\_field :price\_in\_euros

I’ve removed the attr\_accessor line and all works like a charm, so  
finally it was some other thing that gets fixed.

## Thanks!

Carlos A. Paramio  
[http://www.sinfoniadebits.com/](http://www.sinfoniadebits.com/)
