acts_as_money
At Collective Idea, we often try to take pieces of code that we use often and extract them into plugins. We’re trying to get better about making them available, so, here we go:
acts_as_money is a fairly trivial plugin that has proved to be very useful. It just makes it a little easier to work with the money gem.
class Product < ActiveRecord::Base
money :price
end
This assumes that there are 2 columns in the database, cents (integer) and currency (string). These fields can be changed by setting the :cents and :currency options. To use the default currency, you can simple set :currency option to false and not have a currency field.
class Room < ActiveRecord::Base
money :rate, :cents => :rate_in_cents, :currency => :rate_currency
money :discount, :cents => :discount_in_cents, :currency => false
end
acts_as_money also incorporates a patch to composed_of that I submitted to core that allows you to pass a String, Fixnum, Float or Money object as a parameter to the setter, and it will call #to_money to convert it to a Money object. This makes it convenient for using money fields in forms.
r = Room.new :rate => "100.00"
r.rate # returns <Money:0x249ef9c @currency="USD", @cents=10000>
Installation
script/plugin install git://github.com/collectiveidea/acts_as_money.git
Hope you find this useful. I know I’ve been using it in any app that handles money, and it’s been a time saver. Allowing me to use a composed_of field in forms has been extremely helpful.
22 comments
Brandon, can you tell us how you’ve licensed this plugin? I can’t seem to find anything in the code about it… Thanks!!
Haig,
MIT. I’ll add it to the code.
I think it would be a good idea to package the acts_as_money without the composed_of patch.
Had you considered that?
This is not a reflection on the quality or otherwise, just that it would appear separate from the money code.
John,
When I initially released it, acts_as_money actually didn’t use the aggregations patch. But the code was doing some ugly string eval stuff. It was only a couple lines, but ugly none-the-less. I added the aggregations patch to demonstrate its usefulness (no one cared).
I ended up packaging the patch as a plugin, so I could remove it from acts_as_money, but I’m guessing people would find it more annoying to have to install 2 plugins. Unless it’s getting in the way, I think I’m going to leave it as is. Got any good reasons to remove it?
Brandon, Thanks for the reply.
The reasons I was considering were as its been posted as a patch it will eventually end up in core rails.
John
Hi Brandon,
My users have to fill in a price with two seperate input fields. One for a full amount and one for cents. Together it makes the whole price.
What would be the best way to take care of the separate formvalues in combination with this plugin?
LBo,
There’s not exactly a way to do it with the acts_as_money plugin, but if you look at the source for the plugin, it’s very trivial. Mainly, it makes use of a patch to
composed_of, which I have also packaged as a plugin. In your situation, I would just install thecomposed_ofplugin patch, then do something like the following in your model:composed_of :price, :class_name => 'Money', :mapping => [%w(cents cents), %w(currency currency)] do |hash| Money.new("#{hash[:dollars]}.#{hash[:cents]}", hash[:currency]) endAnd then in your views:
I haven’t tried this myself… does this plugin work with Rails 2.0?
How do you remove the dollar sign from the format method? I tried to delete it, but nothing happend. Search within the code of the plugin but couldn’t find any more ”$” signs.
Srgt PPD,
The ”$” is coming from the money gem. If you want the amount without it, you can just call
#to_son the money object.I am having a hell of time with acts_as_money and rails 2.0.2. Everytime I edit a record and click save, whatever price is in my price field gets two extra zeros. I am forced to trim two zeros off of every price field everytime I open a record for editing, even if all I wanted to do was adjust a different field.
I have no idea why this is happening. Has anyone had this sort of issue happen to them?
I just tried your acts_as_money plugin with rails 2.2.2 and rails 2.1.0 and I get in both cases the following exception:
with the App Stacktrace
Alexander,
The plugin should be compatible with edge and 2.2. Use the rails-2.1 tag for 2.1 and prior.
Mea culpa, I just noticed that I did not test it with 2.1.0. Forgot to unfreeze.
Anyway, it is not working with 2.2.2 (the one that installs by default today with gem install rails).
P.S. Thanks for the lib, anyway. It is a nice hack. If only the money gem was not sucking so much…
Alexander,
Check out our fork of the money gem, which incorporates the functionality of this plugin. Install the Rails 2.2 and RSpec gems and run
rake spec. The tests pass for me. Let me know if they don’t pass for you.Aha, it works. 60 seconds running and I have not issues with your fork of the money plugin, yet ;-)
Actually, the 2.1.0 version did not work for me on update of the money fields in the views, but this is already history, I suppose
Brandon,
I am getting the same error as Alexander above, where I get the message:
Unknown key(s): converter
I have Rails 2.1.2 (error originally started with Rails 2.1.0, thought I might upgrade to 2.1.2) and the Rails-2.1 tag of acts_as_money. I am using the “standard” money gem not your forked version.
Any advice? Any clue to what is happening would be great.
Thank you.
Make sure you have the
rails-2.1tag checked out (and that you restarted your server after switching to it). It doesn’t use the :converter option, which was added in Rails 2.2.No, I am getting an error when executing this line:
a.price.format(:no_cents)
Without the format(:no_cents) it works for but with the format I get the error:
undefined method `has_key?’ for [:no_cents]:Array
Is this not an option people are using? I have the 2.1 tag and it works fine w/o the format but I need to not show anything past the decimal point.
Thanks.
trying to get acts_as_money working with little luck. I have tried both the standard money gem, v2.2.0 and collectiveidea’s money gem and neither seem to function with acts_as_money. Quick rundown of the problem…
1. Install money gem and acts_as_money 2. Create a new project and create a basic scaffold 3. Specify one object in the model as money 4. Restart server. 5. New columns in DB for _as_cents 6. Try to create new records using simple forms.
At this point the records are created and data is fed to the database for all fields EXCEPT the object which has been specified as being money. When I check the database both the original value is null and the value_as_cents is 0. I must be doing something stupid but hey, we all do sometimes. Iam running Rails 2.3.4. Thanks,
Hi stephen,
I have moved acts_as_money into the collectiveidea fork of the money gem. You shouldn’t need to install the plugin separately now. If you install our fork of the money gem as a plugin, it should Just Work™. If you install it as a gem, you’ll need to require ‘money/rails’.
hmmm… I removed acts_as_money and added the require ‘money/rails’ (i had require ‘money’) before. I also have config.gem ‘collectiveidea-money’ listed in the environment.rb. When I do a rake gems I see collectiveidea-money listed with an “R” status. In my model I have… money :secured, :cents => :secured_in_cents, :currency => “USD” It still isn’t working though so I must have the syntax wrong. The only difference now is that both the value of “secured” and “secured_in_cents” are both null now where before the value_as_cents was being set to 0.
Speak your mind: