rubymoney / money-rails Goto Github PK
View Code? Open in Web Editor NEWIntegration of RubyMoney - Money with Rails
License: MIT License
Integration of RubyMoney - Money with Rails
License: MIT License
This ticket turned into something I had not anticipated when I wrote 'in a sec' in the other ticket <:)
So - to spare you all my ramblings - I'll cut to the chase :)
exchange_rates could be implemented in a table and the bank (nordea gem eg.) could update_rates and be tweaked to save rates to this table
converting amounts using these exchange_rates would require us to open either the bank or the Money class and add methods to them in order to do something like
exchange_with_rate(currency, rate)
with rate being either :sell, :buy, :middle or perhaps nil (using the default exchange_to method) or perhaps a String '1.12314' or a Float 1.12314
I am using money-rails from github master. On Rails 3.2.6 Ruby 1.9.3p194.
I am using money-rails as outlined in the README.
monetize :price_cents, :with_model_currency => :currency_code, :allow_nil => true
<%= pp.text_field :price %>
<%= pp.error_message_on :price %>
However, I have form inputs where if I input a value like '56,12' where the currency is EUR, i still get an error telling me it is not a number.
The other issue is if I use put in something that is definitely not a number like "foo", the update fails properly, the error message is clear, but the value in the input box is now 0.00.
I am poking around myself to see if i can come up with a patch, but just in case I am missing something obvious...
Hi,
I'm trying to use this gem with a Rails 3.0.X application. Bundler installed v ( 0.4.0 ) originally against rails v ( 3.0.3 ) and I get the following exception when trying to load a model class using the 'monetize' method:
ree-1.8.7-2011.03 :001 > f = Fee.new
NoMethodError: undefined method `attribute_names' for #<Class:0x1e61f58>
from /home/bshaver/.rvm/gems/ree-1.8.7-2011.03@handyworks-r3/gems/activerecord-3.0.5/lib/active_record/base.rb:1008:in `method_missing'
from /home/bshaver/.rvm/gems/ree-1.8.7-2011.03@handyworks-r3/gems/money-rails-0.4.0/lib/money-rails/active_record/monetizable.rb:50:in `monetize'
from /home/bshaver/Documents/Projects/Schram/handyworks-r3a/app/models/fee.rb:2
from /home/bshaver/.rvm/gems/ree-1.8.7-2011.03@handyworks-r3/gems/activesupport-3.0.5/lib/active_support/dependencies.rb:454:in `load'
I tried changing Ruby versions to MRI 1.9.3, also tried updating to Rails v (3.0.5) and get the same results.
I can reproduce the error in a brand new application using a single model and only adding the money-rails gem / monetize method.
However, when I do the same with either Rails 3.1.X or Rails 3.2.X it works as expected. So it definitely seems to be a compatibility issue with Rails 3.0 versions.
I'm wondering if either there's an older version that would be compatible with Rails 3.0.X, and if so perhaps there's something that can be modified in the gem packaging to encourage bundler to install a compatible version.
Worst case, then I'd suggest listing Rails 3.1 as a minimum requirement for the gem.
Is there a simple way to remove the cents on a whole number within form inputs? I set the no_cents_if_whole
option in the initializer, but that didn't seem to do it...
config/initializers/money.rb
config.no_cents_if_whole = true
I can use the humanized_money
helper and manually set the value in the view or presenter, but I thought a global config might do it automatically.
= f.text_field :unit_cost, :value => humanized_money(f.object.unit_cost)
It will be very nice if the Currency objects could be loaded (and stored, if modified) from a table in DB via ActiveRecord (currently they are loaded only from the config JSON files I think), is something like that possible to be implemented in the near future?
Sample app reproducing error: https://github.com/morgoth/money-rails-bug
money-rails from master assigns Money::Currency object to currency column, which later is serialized by rails and saved in database.
This fails with version from master: https://github.com/morgoth/money-rails-bug/blob/master/test/unit/order_test.rb
Discussion: 5c42a95#commitcomment-1555186
I'd suggest releasing a 1.0.0
soon. I often see a much better adoption when a 1.0 is released. Once it shows as 1.0.0
, I'd also feel comfortable listing it as the defacto way to work with money/rails on the Money README.
Hello.
Not sure if it should be considered a bug or a feature request but here we go:
Please consider this example:
monetize :core_charge_amount_cents,
:allow_nil => true,
:numericality => { :greater_than_or_equal_to => 0,
:less_than_or_equal_to => 10000,
:message => "Only amounts in the range 0 to $10000.00 are allowed or leave this value blank." }
According to this line of code - https://github.com/RubyMoney/money-rails/blob/master/lib/money-rails/active_record/monetizable.rb#L58
, it only allows for one option, and checks for numericality, but it doesn't allow to override that with some options. Right now I sidestep the issue but doing a custom validation via another method
validate :core_charge_amount_is_within_limits
but it seems to be it shouldn't be like that.
Hi!
I'm trying to use the humanized_money_with_symbol helper in a functional test, and when I add the require "money-rails/test_helpers" in my test_helper.rb, it's giving me this error:
/Users/myuser/.rvm/rubies/ruby-1.9.3-p194/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require': cannot load such file -- money-rails/test_helpers (LoadError)
In development it works ok when I use it from my application_helper.rb
Thanks in advance!
It seems like the spec helper is not included in the current gem hosted on https://rubygems.org/gems/money-rails
Cheers, Jakob
My migration with a nullable money field
class CreateProducts < ActiveRecord::Migration
def change
create_table :product do |t|
t.string :name
t.money :price
t.money :price_optional, :null => true
end
end
end
creates this schema.rb, ignoring the :null option.
create_table "product", :force => true do |t|
t.string "name"
t.integer "price_cents", :default => 0, :null => false
t.string "price_currency", :default => "USD", :null => false
t.integer "price_optional_cents", :default => 0, :null => false
t.string "price_optional_currency", :default => "USD", :null => false
end
This is causing the monetize :allow_nil to fail at the SQL level when saving a model with a nil value.
Am I passing through the null option incorrectly?
Instead of this:
monetize :price_in_cents, :target_name => :price, :field_currency => 'USD'
It's better to use something like this:
monetize :price_in_cents, :as => :price, :with_currency => 'USD'
Validations are skipped if attribute is a Money object
validations only work on primitives ie. Integer and String
https://github.com/RubyMoney/money-rails/blob/master/lib/money-rails/active_model/validator.rb#L17
Is the attribute converted from a human readable string to Money Object here ?
Right now am writing a custom validation that the object has to be a money object
and that the subunit is non-negative ?
When I try to use the test helpers in rspec according to the documentation I get the following LoadError cannot load such file -- money-rails/test_helpers (LoadError)
:
/Users/anthony/.rbenv/versions/1.9.3-p374/gemsets/career_starter/gems/activesupport-3.2.11/lib/active_support/dependencies.rb:251:in `require': cannot load such file -- money-rails/test_helpers (LoadError)
from /Users/anthony/.rbenv/versions/1.9.3-p374/gemsets/career_starter/gems/activesupport-3.2.11/lib/active_support/dependencies.rb:251:in `block in require'
from /Users/anthony/.rbenv/versions/1.9.3-p374/gemsets/career_starter/gems/activesupport-3.2.11/lib/active_support/dependencies.rb:236:in `load_dependency'
from /Users/anthony/.rbenv/versions/1.9.3-p374/gemsets/career_starter/gems/activesupport-3.2.11/lib/active_support/dependencies.rb:251:in `require'
from /Users/anthony/Documents/Projects/clients/career_starter/spec/spec_helper.rb:11:in `<top (required)>'
from /Users/anthony/Documents/Projects/clients/career_starter/spec/controllers/employers_controller_spec.rb:1:in `require'
from /Users/anthony/Documents/Projects/clients/career_starter/spec/controllers/employers_controller_spec.rb:1:in `<top (required)>'
from /Users/anthony/.rbenv/versions/1.9.3-p374/gemsets/career_starter/gems/rspec-core-2.12.2/lib/rspec/core/configuration.rb:789:in `load'
from /Users/anthony/.rbenv/versions/1.9.3-p374/gemsets/career_starter/gems/rspec-core-2.12.2/lib/rspec/core/configuration.rb:789:in `block in load_spec_files'
from /Users/anthony/.rbenv/versions/1.9.3-p374/gemsets/career_starter/gems/rspec-core-2.12.2/lib/rspec/core/configuration.rb:789:in `each'
from /Users/anthony/.rbenv/versions/1.9.3-p374/gemsets/career_starter/gems/rspec-core-2.12.2/lib/rspec/core/configuration.rb:789:in `load_spec_files'
from /Users/anthony/.rbenv/versions/1.9.3-p374/gemsets/career_starter/gems/rspec-core-2.12.2/lib/rspec/core/command_line.rb:22:in `run'
from /Users/anthony/.rbenv/versions/1.9.3-p374/gemsets/career_starter/gems/rspec-core-2.12.2/lib/rspec/core/runner.rb:80:in `run'
from /Users/anthony/.rbenv/versions/1.9.3-p374/gemsets/career_starter/gems/rspec-core-2.12.2/lib/rspec/core/runner.rb:17:in `block in autorun'
My spec_helper.rb:
require 'simplecov'
SimpleCov.start
# This file is copied to spec/ when you run 'rails generate rspec:install'
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
require 'paperclip/matchers'
require 'email_spec'
require 'money-rails/test_helpers'
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
RSpec.configure do |config|
# ## Mock Framework
#
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
#
# config.mock_with :mocha
# config.mock_with :flexmock
# config.mock_with :rr
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
config.fixture_path = "#{::Rails.root}/spec/fixtures"
# If you're not using ActiveRecord, or you'd prefer not to run each of your
# examples within a transaction, remove the following line or assign false
# instead of true.
config.use_transactional_fixtures = true
# If true, the base class of anonymous controllers will be inferred
# automatically. This will be the default behavior in future versions of
# rspec-rails.
config.infer_base_class_for_anonymous_controllers = false
# Run specs in random order to surface order dependencies. If you find an
# order dependency and want to debug it, you can fix the order by providing
# the seed, which is printed after each run.
# --seed 1234
config.order = "random"
config.include Paperclip::Shoulda::Matchers
config.include Sorcery::TestHelpers::Rails
config.include EmailSpec::Helpers
config.include EmailSpec::Matchers
end
I can use money-rails just fine otherwise.
I'm on Rails 3.2.11 and Ruby 1.9.3p374.
Based on the docs, it seems that when using mongoid, money-rails will automatically store a hash with amount and currency to represent the money object. That's great in some instances, and I will be using it that way for some things, but I also need to use it another way.
I want to implement bookkeeping accounts, where each account is denominated in a single currency, and will contain a list of debit and credit amounts. Storing the currency alongside each amount is redundant, since the entire account is in a uniform currency. It wouldn't break anything to have it there, but it seems inelegant.
However, even if I modify money-rails to let me tell it not to store the currency alongside the amount in those instances, it still would be nice to have the existing interface work in the usual way, so given a record from the account (which contains a money object), you could evaluate record.amount.currency and it would defer to the account's currency attribute. Of course, that may be way beyond the scope of this gem...
What I'm really trying to say is: Do you have any design suggestions? :)
Rails is going to remove composed_of, so it might be a good idea to rethink the active_record integration.
http://blog.plataformatec.com.br/2012/06/about-the-composed_of-removal/
I have a model
class Foo
include Mongoid::Document
include Mongoid::Timestamps
field :name, type: String
field :email, type: String
field :address, type: String
field :country, type: String
field :price, type: Money, default: Money.new(0)
field :tax_amount, type: Money , default: Money.new(0)
When instantiating a new Foo based on existing Foo
# params[:existing_foo]
# => {:price=>{"cents"=>"0", "currency_iso"=>"EUR"}, :tax_amount=>{"cents"=>"0", "currency_iso"=>"EUR"}}
Foo.new(params[:existing_foo])
It produces the following error
NoMethodError: undefined method `iso_code' for nil:NilClass
activesupport-3.1.3/lib/active_support/whiny_nil.rb:48:in `method_missing'
money-rails-0.7.0/lib/money-rails/mongoid/three.rb:7:in `mongoize'
money-rails-0.7.0/lib/money-rails/mongoid/three.rb:31:in `mongoize'
mongoid-3.0.13/lib/mongoid/fields/standard.rb:10:in `mongoize'
I know that Money.new {"cents"=>"0", "currency_iso"=>"EUR"}
correctly builds the Money object, so there seems to be some problem with the mongoid instantiator?
As the to_s method of a float returns a number formatted with a point as the decimal mark (e.g. "973.24") the validation executed in the MoneyValidator fails, if the active currency has a different decimal mark and/or thousands separator.
I think the best way is to skip the format validations for number objects (especially floats).
Is there a fork or a branch that has Rails 2 support for money-rails? or maybe a release I could bump down to?
If not, how hard would it be to backport it? I'd be willing to give it a stab.
I've got a database column named price_in_cents
, and so I'd like to create a :composed_of
attribute named price
. Normally, I would do this:
composed_of :price,
:class_name => 'Money',
:mapping => [%w(price_in_cents cents), %w(currency currency_as_string)],
:constructor => proc { |cents, currency| Money.new(cents || 0, currency || Money.default_currency) },
:converter => proc { |value| value.respond_to?(:to_money) ? value.to_money : raise(ArgumentError, "Can't convert #{value.class} to Money") }
In an attempt to mimic this with money-rails, I tried this:
monetize :price, :target_name => "price_in_cents"
However, that seems to generates this code:
composed_of :price_in_cents,
:class_name => "Money",
:mapping => [['price', 'cents'], ['currency', 'currency_as_string']],
:constructor => Proc.new { |cents, currency| Money.new(cents || 0, currency || Money.default_currency) },
:converter => Proc.new { |value|
if value.respond_to?(:to_money)
if field_currency_name
value.to_money(field_currency_name)
else
value.to_money
end
else
raise(ArgumentError, "Can't convert #{value.class} to Money")
end
}
You can see the name of the composed_of attribute is different, as well as the mapping values with regards to the cents column. Am I doing something wrong, or is this an issue with the money-rails gem?
Is it possible to set :no_cents_if_whole => false globally?\
I can't see that option. I might be missing something.
Hi
now my forms (with money fields) fails due to this commit <:)
I've left a comment on the commit with my two cents pertaining to the reasoning of disallowing input
Cheers
E
The link to Code Climate is broken. It's linking to https://codeclimate.com/github/Robymoney/money-rails. Note the "RobyMoney" instead of "RubyMoney".
Any idea what's happening here?
This is with Mongoid 3.0.6, money-rails 0.6.0, and ruby 1.9.3. Thanks!
irb(main):015:0> er = ExchangeRate.last
=> #<ExchangeRate _id: 50610d3ef8182b88a0000001, _type: nil, time: 2012-09-25 01:47:41 UTC, rate: {"cents"=>1202, "currency_iso"=>"USD"}>
irb(main):016:0> er.rate
NoMethodError: undefined method `round' for nil:NilClass
from /Users/barmstrong/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/money-5.0.0/lib/money/money.rb:194:in `initialize'
from /Users/barmstrong/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/money-rails-0.6.0/lib/money-rails/mongoid/three.rb:18:in `new'
from /Users/barmstrong/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/money-rails-0.6.0/lib/money-rails/mongoid/three.rb:18:in `demongoize'
from /Users/barmstrong/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/mongoid-3.0.6/lib/mongoid/fields/standard.rb:10:in `demongoize'
from /Users/barmstrong/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/mongoid-3.0.6/lib/mongoid/fields.rb:338:in `block (2 levels) in create_field_getter'
from (irb):16
from /Users/barmstrong/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/railties-3.2.6/lib/rails/commands/console.rb:47:in `start'
from /Users/barmstrong/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/railties-3.2.6/lib/rails/commands/console.rb:8:in `start'
from /Users/barmstrong/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/railties-3.2.6/lib/rails/commands.rb:41:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
irb(main):017:0> er.rate = 12.03.to_money('USD')
=> #<Money cents:1203 currency:USD>
irb(main):018:0> er
=> #<ExchangeRate _id: 50610d3ef8182b88a0000001, _type: nil, time: 2012-09-25 01:47:41 UTC, rate: {:cents=>1203, :currency_iso=>"USD"}>
irb(main):019:0> er.rate
=> #<Money cents:1203 currency:USD>
irb(main):020:0> er.save!
=> true
irb(main):021:0> er
=> #<ExchangeRate _id: 50610d3ef8182b88a0000001, _type: nil, time: 2012-09-25 01:47:41 UTC, rate: {:cents=>1203, :currency_iso=>"USD"}>
irb(main):022:0> er.rate
=> #<Money cents:1203 currency:USD>
irb(main):023:0> er.reload
=> #<ExchangeRate _id: 50610d3ef8182b88a0000001, _type: nil, time: 2012-09-25 01:47:41 UTC, rate: {"cents"=>1203, "currency_iso"=>"USD"}>
irb(main):024:0> er.rate
NoMethodError: undefined method `round' for nil:NilClass
from /Users/barmstrong/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/money-5.0.0/lib/money/money.rb:194:in `initialize'
from /Users/barmstrong/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/money-rails-0.6.0/lib/money-rails/mongoid/three.rb:18:in `new'
from /Users/barmstrong/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/money-rails-0.6.0/lib/money-rails/mongoid/three.rb:18:in `demongoize'
from /Users/barmstrong/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/mongoid-3.0.6/lib/mongoid/fields/standard.rb:10:in `demongoize'
from /Users/barmstrong/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/mongoid-3.0.6/lib/mongoid/fields.rb:338:in `block (2 levels) in create_field_getter'
from (irb):24
from /Users/barmstrong/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/railties-3.2.6/lib/rails/commands/console.rb:47:in `start'
from /Users/barmstrong/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/railties-3.2.6/lib/rails/commands/console.rb:8:in `start'
from /Users/barmstrong/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/railties-3.2.6/lib/rails/commands.rb:41:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
irb(main):025:0>
Maybe something with HashWithIndifferentAccess?
this code:
transaction.update_attributes(amount: nil)
rise error:
NoMethodError: undefined method `to_money' for nil:NilClass
this is not real problem, but it perhaps should be handle
Thank you
When using the <%= humanized_money_with_symbol @money_object %>
there's no space between the currency and the value output.
I think it would be great if there's a space between them for readability.
I'm seeing the following error with a rails app:
Unknown currency 'false'
money (5.0.0) lib/money/currency.rb:165:in 'initialize'
backtrace:
money (5.0.0) lib/money/currency.rb:165:in `initialize'
money (5.0.0) lib/money/currency.rb:52:in `new'
money (5.0.0) lib/money/currency.rb:52:in `wrap'
money (5.0.0) lib/money/money/parsing.rb:65:in `parse'
money (5.0.0) lib/money/core_extensions.rb:46:in `to_money'
money-rails (0.3.0) lib/money-rails/active_record/monetizable.rb:72:in `block in monetize'
activerecord (3.2.5) lib/active_record/aggregations.rb:244:in `call'
....
It would appear that there is some kind of a problem with detecting the application default currency. The application in my case uses :eur as the default currency, which is set in the initializer. The workaround in this case is to call register currency in every model that uses monetize.
for example:
register_currency :eur
monetize :total_price_cents
it 'has price cents' do
monetize(:price_cents).should be_true
end
This returns always true for me, regardless of an existing call of monetize in the corresponding model and even on other model attributes.
money-rails: 0.8.0
rails: 4.0.0.beta1
rspec: 2.13.0
Is it possible to get error for:
transaction.update_attributes(amount: "some text")
instead save 0
UPDATE "transactions" SET "amount_cents" = 0, "updated_at" = '2012-09-10 19:32:41.434442' WHERE "transactions"."id" = 5
?
It's not useful when user input some wrong value in form and service save it as 0 instead return alert with error message
Thank you!
I'm making a bare-metal API service project, which requires using money-rails gem. But when I try to attach it, it tries to uses "delegate" method, that belongs to ActiveSupport, and ActiveSupport is not required for my project.
It spits the following error:
money-rails-0.4.0/lib/money-rails/configuration.rb:35:in `<module:Configuration>': undefined method `delegate' for MoneyRails::Configuration:Module (NoMethodError)
from money-rails-0.4.0/lib/money-rails/configuration.rb:5:in `<module:MoneyRails>'
Possible solution:
# in money-rails
require 'active_support/core_ext/module/delegation'
require 'active_support/core_ext/module/attribute_accessors'
Possible workaround:
# in your app :)
require 'active_support/core_ext/module/delegation'
require 'active_support/core_ext/module/attribute_accessors'
Hi,
I read the instructions and it says to use humanized_money_with_symbol
for something like $1, but I'd like to show $1.00. Which method do I use?
I'm using money-rails
for the first time and am running into a problem.
I've set :eur
as the default currency in the initializer.
MoneyRails.configure do |config|
# To set the default currency
#
config.default_currency = :eur
end
My ReceiptItem
model:
class ReceiptItem < ActiveRecord::Base
attr_accessible :original_text
belongs_to :email
monetize :price_cents
end
From rails c
:
r = ReceiptItem.first
r.price = Money.new(140.00, 'EUR')
r.save!
The ReceiptItem
now looks like this ( USD in stead of EUR ):
<ReceiptItem id: 1, original_text: nil, price_cents: 140, price_currency: "USD", created_at: "2013-01-24 19:09:49", updated_at: "2013-01-24 19:14:00">
Server gives me data in JSON where i can't find balance value in money format: "99.12", i get only value in cents: 9912.
I use workaround:
class Account < ActiveRecord::Base
.....
monetize :balance_cents
.....
def balance_as_str
self.balance.to_s
end
def as_json options=nil
options ||= {}
options[:methods] = ((options[:methods] || []) + [:balance_as_str])
super options
end
end
But, maybe you will implement it in gem better
Thank you!
In the following example, the currency of the assigned money object is just silently ignored:
class Item < ActiveRecord::Base
monetize :price_cents
end
i = Item.new
i.price = Money.new(500, 'AUD')
i.price # => <Money fractional:500 currency:USD>
That's totally confusing and not the way I've expected it to work. What's the idea behind this behaviour?
If you have a price field and someone types in e.g. "COMING SOON" the money gem tries to parse the COM as a currency and blows up. I'm not sure if this is a problem of money-rails or money..suggestions on handling are much welcome. Adding a numericality validation does not seem to help as monetize tries to intercept the field before it hits normal validations (?)
Failure/Error: product.update_attribute(:price, "COMING SOON")
NoMethodError:
undefined method `id' for "COM":String
# ./spec/models/product_spec.rb:178:in `block (3 levels) in <top (required)>'
class Product
validate :price_cents, :numericality => true
monetize :price_cents
end
failing spec - sets no_cents_if_whole value for formatted output globally
stacktrace:
1) configuration initializer sets no_cents_if_whole value for formatted output globally
Failure/Error: value.format.should_not =~ /#{mark}/
expected not: =~ /,/
got: "€123,456"
Diff:
@@ -1,2 +1,2 @@
-/,/
+"€123,456"
# ./spec/configuration_spec.rb:26:in `block (3 levels) in <top (required)>'
field :amount, type: Money
I get this when trying to instantiate a new object with that Money field on it (with Mongoid):
NoMethodError: undefined method `instantiate' for Money:Class
from /Users/barmstrong/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/attr_encrypted-1.2.0/lib/attr_encrypted.rb:229:in `method_missing'
from /Users/barmstrong/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/mongoid-2.4.10/lib/mongoid/fields.rb:284:in `add_field'
from /Users/barmstrong/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/mongoid-2.4.10/lib/mongoid/fields.rb:195:in `field'
My work around for now is I created a new file in lib/money_field.rb
with this:
# custom Mongoid field to store any Money object
class MoneyField
include Mongoid::Fields::Serializable
def deserialize(object)
return nil if object.blank?
object.symbolize_keys!
Money.new(object[:cents], object[:currency])
end
def serialize(object)
return nil if object.blank?
{cents: object.cents, currency: object.currency_as_string}
end
end
Then I just do field :amount, type: MoneyField
instead. This seems to work but is a hack obviously. If anyone has any ideas much appreciated. Thanks for the awesome gem overall!
Hello,
I don't know how to identify it but the thing is: after add the 'monetize' method for my model attributes i'm getting:
running rake spec:
/Users/guilherme/.rvm/gems/ruby-1.9.3-p194@gemset/gems/rspec-core-2.11.1/lib/rspec/core/configuration.rb:780: stack level too deep (SystemStackError)
rake aborted!
running spork:
Using RSpec
Preloading Rails environment
Loading Spork.prefork block...
stack level too deep (SystemStackError)
/Users/guilherme/.rvm/gems/ruby-1.9.3-p194@gemset/gems/activesupport-3.2.3/lib/active_support/dependencies.rb:240
I'm using:
There's something wrong with compatibility with 3.2.3 ?
So I have a model which has a Hash field type as I want to pair money objects to keys.
Now when I create a model with {5 => Money.new(500)}
it actually is created as #<Foo .., scheme: {5=>{:cents=>500, :currency_iso=>"EUR"}}>
I'm not sure if this is intended behaviour or not, but I'd like to this to work :)
Relating to issue #79, at https://github.com/RubyMoney/money-rails/blob/master/lib/money-rails/active_model/validator.rb#L17 we have:
return if raw_value.is_a?(Money) || raw_value.nil?
However, this stops https://github.com/RubyMoney/money-rails/blob/master/lib/money-rails/active_model/validator.rb#L60 from getting run:
super(record, attr, raw_value)
This is unexpected behavior, since it may skip numericality validations passed in as options. The example below shows numericality validations requiring that the price is greater than or equal to 0. In the last case, when we have a Money
object, those validations never run.
# Model
monetize :price_cents, numericality: { greater_than_or_equal_to: 0 }
# Console
> obj.price = "-100"
=> "-100"
> obj.valid?; obj.errors[:price]
=> ["must be greater than or equal to 0"]
> obj.price = -100
=> -100
> obj.valid?; obj.errors[:price]
=> ["must be greater than or equal to 0"]
> obj.price = Money.new(-100)
=> #<Money fractional:-100 currency:USD>
> obj.valid?; obj.errors[:price]
=> []
Provide integration for Mongoid just like ActiveRecord
Working on some validation specs I noticed that they're fairly brittle and require manual attention to generate sqlite3 db's (which actually live in the repo).
I propose that the sqlite3 files be removed from the repo at a minimum - either being generated on-demand by the spec task, or removing the whole dummy application entirely in favor of testing validations using something more like:
require 'spec_helper'
describe MoneyRails::ActiveModel::MoneyValidator do
let(:model_class) do
Struct.new(:price_cents, :price_currency) do
include ActiveModel::Validations
include ActiveModel::Validations::Callbacks
include ActiveModel::Dirty
include MoneyRails::ActiveRecord::Monetizable
## ActiveModel::Dirty stuff
define_attribute_methods [:price_cents]
def price_cents=(price)
price_cents_will_change! unless price == @price_cents
@price_cents = price
end
end
end
subject(:model) { validation_class.new }
before(:each) do
stub_const('BaseModel', model_class)
stub_const('ExampleModel', validation_class)
end
context "default validation" do
let(:validation_class) do
Class.new(model_class) do
monetize :price_cents
end
end
it "validates numericality" do
model.price = "asdfasdf"
model.should_not be_valid
end
end
end
The downside is that it doesn't look as much like it would actually be used, but it doesn't require a db and is far simpler to maintain than a whole rails app. Another downside is that the mongoid integration would need to get pulled out as well to be able to get rid of the whole app.
Would love to hear some feedback before such a potentially large refactor.
Hello,
i wondering why thousands_separator doesn't affect with money_without_cents_and_with_symbol method..
is there a way to show value without cents and separate thousands?
Hey,
I assumed that the view helpers were available to mounted apps like rails_admin.
Is this is a problem of money-rails or rails_admin?
New version does not work properly with standard text_field method:
Old version:
1.9.3p194 :001 > u = User.first 1.9.3p194 :003 > helper.instance_variable_set :@t, u.transaction.first 1.9.3p194 :004 > helper.text_field(:t,:amount) => "<input id=\"t_amount\" name=\"t[amount]\" size=\"30\" type=\"text\" value=\"10.00\" />"
New Version:
1.9.3p194 :001 > u = User.first 1.9.3p194 :003 > helper.instance_variable_set :@t, u.transaction.first 1.9.3p194 :004 > helper.text_field(:t,:amount) => "<input id=\"t_amount\" name=\"t[amount]\" size=\"30\" type=\"text\" />"
Right now to use per-instance currencies you need to use a db column. I wanted to use a method instead because I have the following use-case:
class Brand
has_many :products
def currency
read_attribute :currency
end
end
class Product
belongs_to :brand
monetize :price_cents
def currency
brand.currency
end
end
I gave extending the current codebase a quick try but it looks like there is a conflict with the implementation of model level currencies.
In principle, I don't see any reason to require that instance currencies require a db column, but it seems like the current codebase would need a bit of refactoring to remove that requirement. On the other hand, it seems like the way the current implementation handles delegation is a bit wonky. Why for instance, are attribute and instance currencies incompatible. Logically, it seems like the latter would simply be a greater degree of specificity, and thus would take precedence over the former.
Thoughts?
Money values should be delocalized before validations occur. This would relieve some of the headache from supporting localized (5,000 vs 5000) user input.
Hello
Thank you for great job, new improvements!
With new version one my test does not work:
describe "when amount is big (99 999 999.99)" do before { @t.amount = "99 999 999.99" } it { should be_valid } it { @t.amount_cents.should == 9999999999 } end
> t => # > t.amount = "99 999 999.99" => "99 999 999.99" > t => # > t.valid? => false > t.errors => #, @messages={:amount=>["is not a number"]}>
I think it's because of validator.rb(25): Kernel.Float(raw_value)
Is it possible clean up input value before validate (remove spaces)?
When I use the migration helper, for example t.money :price
, it adds two fields to my database table: price_cents
and price_currency
.
However the price_currency
column just stores the default currency (USD) and doesn't seem to be used in any way. Initially I expected it work like the currency
column, but that's not the case. It is only used when I explicitly say so with: monetize :price_cents, with_model_currency: :price_currency
.
I'm confused to what the purpose of a column like price_currency
is. Is it a per-attribute version of currency
and when/how does it work?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.