Rails money column with no cents - ruby-on-rails

I have a Rails 3.2 app where I'm asking for next year's budget request. The amount field is money - but, I don't want any decimals.
I will be using the data to display with number_to_currency.
Should I use:
add_column :mytable, :amount, :decimal, :precision => 12, :scale => 0
Or:
add_column :mytable, :amount, :integer
Thanks for the help!

Use
add_column :mytable, :amount, :integer
and number_to_currency(x/100) or number_to_currency(x/100, {options})
This way you avoid any rounding issues.

Related

PostgreSQL: add_column "after" option usage in Rails migration

I'm trying to add a new column, 'latitude', to an existing Postgres table, after the 'location' column.
Using this syntax puts the column in the correct place:
add_column :table, :column, :decimal, :after => :existing_column
And using this syntax ensures that the field is the correct data type
add_column :table, :column, :decimal, {:precision => 10, :scale => 6}
But when I try and combine the two:
add_column :table, :column, :decimal, {:precision => 10, :scale => 6}, :after => :existing_column
I get "ArgumentError: wrong number of arguments (5 for 3..4)"
"Not to worry", I thought, "I'll just combine the arguements!":
add_column :table, :column, :decimal, {:precision => 10, :scale => 6, :after => :existing_column}
But then the columns appear at the end of the table. What am I doing wrong?
Thanks :)
Your last definition is correct. But the problem here isn't with Rails, but with PostgreSQL, which doesn't allow to add a column at specific position. Read more: How can I specify the position for a new column in PostgreSQL?

Query to define a default value in a database migration

In this SO article I can see how to add a default value to a certain table:
Add a default value to a column through a migration
change_column :shops, :currency_id, :integer, :default => 1
I have another table currencies that has an ID and also a ISO_Name. I want the system to use EUR as default value. But it's possible that this has ID 5 or ID 1 or ...
So my question: How can I define a default value that is based on the result of a query? For example Currency.find_by_iso_code('EUR').id
As you have iso_name field in the currencies, you can achieve it by the following code.
change_column :shops, :currency_id, :integer, :default => Currency.find_by_iso_name('EUR').id
How about:
class SetDefaultCurrencyForShops < ActiveRecord::Migration
def up
currency = Currency.find_by_iso_code('EUR')
if currency
change_column :shops, :currency_id, :integer, :default => currency.id
end
end
end

How to use Decimal with precision and scale?

Using rails 3.0.3, I migrated a decimal column in my base using the following migration:
change_table :products do |t|
t.change :price, :decimal, :precision => 10, :scale => 2
# other code
end
The migration works ok, but I can still store value like 4.64564 where it should only store 4.65
On top of that, except in the migration file I created, schema.rb does not contain info about scale/precision.
Why does rails accept precision/scale migration to ignore it?
You should try with
change_column :products, :price, :decimal, :precision => 10, :scale => 2
I had the same problem, please look at that lib:
https://github.com/dmgr/dmg_decimal
With it you can use it in a model like that:
def price= val
self[:price] = Dmg::Decimal.real(val, scale: 2, precision: 10).to_d if val.present?
end

Set a default value in a decimal column

How do you set a default value in a decimal column in Rails? I've tried both the following, using Rails 3 and Postgresql, but after each one the console tells me the default values are still nil. If I set the value from the console, there's no problem, but it doesn't seem to work in the migration.
#Attempt 1
add_column :providers, :commission, :decimal, :precision=>6,:scale=>4,:default=>0.1
and
#Attempt 2
add_column :providers, :commission, :decimal, :precision=>6,:scale=>4,:default=>BigDecimal("0.1")
Many thanks for your help!
It turns out I also need to set :null=>false
The following code worked:
add_column :providers, :commission, :decimal, :precision=>6,:scale=>4,:default=>0.1, :null => false

Rails: Cannot add :precision or :scale options with change_column in a migration?

This seems to have been asked before: rails decimal precision and scale
But when running a change_column migration for :precision or :scale they don't actually affect the schema or database, but db:migrate runs without errors.
My migration file looks like this:
class ChangePrecisionAndScaleOfPaybackPeriodInTags < ActiveRecord::Migration
def self.up
change_column :tags, :payback_period, :decimal, { :scale => 3, :precision => 10 }
end
def self.down
change_column :tags, :payback_period, :decimal
end
end
But my schema (and the data) remains as:
t.decimal "payback_period"
Anybody else have this issue?
Thanks,
Josh
Had a related (but not same) problem. I was just changing scale, so when changing the :scale you need the full line:
change_column :something, :weight, :decimal, :precision => 10, :scale => 2
omitting :decimal (which it already was) and :precision (which already was 10) will cause the migration to fail.
Does Not Work for SQLite3
For this simple test app that I'm running I have SQLite3 setup. Apparently, SQLite3 doesn't rely on column type declarations and is more dynamic, looking at the column's content instead - as was stumbled upon here:
Modify a Column's Type in sqlite3
I haven't tested it but I'm sure that's why the schema wasn't being changed, because change_column doesn't translate to anything in SQLite3.
Thanks for the replies guys.
Delete and regenerate db\schema.rb file.
rake db:schema:dump
A hack, but it should get you where you need to go:
class ChangePrecisionAndScaleOfPaybackPeriodInTags < ActiveRecord::Migration
def self.up
execute "ALTER TABLE tags CHANGE payback_period DECIMAL(3,10)"
end
def self.down
change_column :tags, :payback_period, :decimal
end
end

Resources