Is this your first visit? You may want to subscribe to the feed.

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 &lt;Money:0x249ef9c @currency="USD", @cents=10000&gt;

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.

Code: plugin, rails Nov 13, 2006 ● updated Jun 19, 2008 22 comments

22 comments

  1. 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 Didizian Haig Didizian January 09, 2007 at 02:33 PM
  2. Haig,

    MIT. I’ll add it to the code.

    Brandon Keepers Brandon Keepers January 09, 2007 at 11:31 PM
  3. 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 Ward John Ward March 16, 2007 at 04:40 PM
  4. 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 Brandon March 16, 2007 at 05:11 PM
  5. 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

    John Ward John Ward March 17, 2007 at 02:49 AM
  6. 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 LBo May 06, 2007 at 06:19 PM
  7. 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 the composed_of plugin 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])
    end
    

    And then in your views:

    text_field_tag 'mymodel[price][dollars]'
    text_field_tag 'mymodel[price][cents]'
    
    Brandon Brandon May 07, 2007 at 10:16 AM
  8. I haven’t tried this myself… does this plugin work with Rails 2.0?

    JM JM January 15, 2008 at 02:16 PM
  9. 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 Srgt PPD February 20, 2008 at 05:37 AM
  10. Srgt PPD,

    The ”$” is coming from the money gem. If you want the amount without it, you can just call #to_s on the money object.

    Brandon Brandon February 20, 2008 at 10:49 PM
  11. 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?

    nathaniel nathaniel March 03, 2008 at 04:45 PM
  12. 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:

    Unknown key(s): converter

    with the App Stacktrace

    vendor/rails/activesupport/lib/active_support/core_ext/hash/keys.rb:47:in `assert_valid_keys'
    vendor/plugins/composed_of_conversion/lib/aggregations.rb:136:in `composed_of'
    vendor/plugins/acts_as_money/lib/acts_as_money.rb:21:in `money'
    app/models/transfer.rb:7
    app/controllers/clients_controller.rb:18:in `show'
    
    Alexander Mikhailian Alexander Mikhailian January 04, 2009 at 05:33 PM
  13. Alexander,

    The plugin should be compatible with edge and 2.2. Use the rails-2.1 tag for 2.1 and prior.

    Brandon Brandon January 04, 2009 at 09:25 PM
  14. 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 Mikhailian Alexander Mikhailian January 04, 2009 at 10:54 PM
  15. 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.

    Brandon Brandon January 04, 2009 at 11:01 PM
  16. 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

    Alexander Mikhailian Alexander Mikhailian February 04, 2009 at 03:13 PM
  17. 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.

    Rob Bazinet Rob Bazinet May 06, 2009 at 11:23 PM
  18. Make sure you have the rails-2.1 tag 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.

    Brandon Brandon May 07, 2009 at 08:55 AM
  19. 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.

    Rob Bazinet Rob Bazinet May 07, 2009 at 11:17 AM
  20. 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,

    stephen stephen March 17, 2010 at 11:59 AM
  21. 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’.

    Brandon Keepers Brandon Keepers March 17, 2010 at 02:46 PM
  22. 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.

    stephen stephen March 17, 2010 at 03:42 PM

Speak your mind:

*

*


* I hate spam and will never sell or publish your email address.

(You may use textile in your comments.)

Subscribe

Browse by Tag