RubyMoney/money-rails

[Bug] On Ruby 3, migration helper `monetize` fails (wrong number of arguments (given 3, expected 2))

Closed this issue · 10 comments

Steps to reproduce:

  1. create a fresh rails project via rails new my_project
  2. Add gem 'money-rails' to project and run bundle
  3. Create a migration of this form
class AddMoneytizeToUser < ActiveRecord::Migration[6.1]
  def change
    create_table :users do |t|
      t.monetize :amount
      t.timestamps
    end
  end
end
  1. Run bundle exec rake db:create db:migrate

Expected result: Successfully migrating
Observed result: An error has occurred, this and all later migrations canceled
Stack trace:

wrong number of arguments (given 3, expected 2)
/path/to/gems/installs/ruby/3.0.0/lib/ruby/gems/3.0.0/gems/activerecord-6.1.3/lib/active_record/connection_adapters/abstract/schema_definitions.rb:401:in `column'
/path/to/gems/installs/ruby/3.0.0/lib/ruby/gems/3.0.0/gems/money-rails-1.13.4/lib/money-rails/active_record/migration_extensions/table_pg_rails4.rb:8:in `block in monetize'
/path/to/gems/installs/ruby/3.0.0/lib/ruby/gems/3.0.0/gems/money-rails-1.13.4/lib/money-rails/active_record/migration_extensions/table_pg_rails4.rb:6:in `each'
/path/to/gems/installs/ruby/3.0.0/lib/ruby/gems/3.0.0/gems/money-rails-1.13.4/lib/money-rails/active_record/migration_extensions/table_pg_rails4.rb:6:in `monetize'
/path/to/my_project/db/migrate/20210301105700_add_moneytize_to_user.rb:4:in `block in change'
  • With Ruby 2.7.2 this works
  • it fails with ActiveRecord 6.1 similiarily

@johannesluedke care to dig in and solve this?

@semmons99 Actually I saw that a new version was released today - https://github.com/RubyMoney/money-rails/releases/tag/v1.14.0 - and with that it worked for me 😀 - So I would close it

kule commented

Hmm I'm getting the same issue with Rails 6.0 & Ruby 2.7.2 it appears this line isn't doing what I'd expect:

For example:

# in migration:
...
add_monetize :courses, :price, currency: { present: false }

...
# in schema_statements_pg_rails4.rb
add_column(*opts, **constraints) if column_present

Is failing as it's missing the table name. The values from above are:

# opts => ["price_cents"]
# constraints => {}
# column_present => :courses
kule commented

Ah found the issue. Incase someone else hits this - in my initializer I'd done this:

MoneyRails.configure do |config|
  config.amount_column = { postfix: "_pennies" }
end

This replaces all the column attributes and breaks things. You need to write all the attributes for it to work e.g.

MoneyRails.configure do |config|
  config.amount_column = {
    postfix: "_pennies",
    type:    :integer,
    null:    false,
    default: 0,
    present: true
  }
end

ruby 3.0.1
money-rails 1.7.0

And I get the same error

class CreateRules < ActiveRecord::Migration[6.1]
  def change
    create_table :rules do |t|
      t.references :user
      t.text    :schedule
      t.string   :type
      t.monetize :low_price
      t.monetize :high_price

      t.timestamps
    end
  end
end
wrong number of arguments (given 3, expected 2)
/Users/orestkostiuk/RubymineProjects/EngineMoney/db/migrate/20210707131419_create_rules.rb:7:in `block in change'
/Users/orestkostiuk/RubymineProjects/EngineMoney/db/migrate/20210707131419_create_rules.rb:3:in `change'
/Users/orestkostiuk/RubymineProjects/EngineMoney/bin/rails:5:in `<top (required)>'
/Users/orestkostiuk/RubymineProjects/EngineMoney/bin/spring:10:in `block in <top (required)>'
/Users/orestkostiuk/RubymineProjects/EngineMoney/bin/spring:7:in `<top (required)>'

ruby 3.0.1
money-rails 1.7.0

I closed it because it was fixed in 1.14.0, so it's not unexpected that with earlier version like 1.7.0 it doesn't work
#624 (comment)

FYI, I just ran into this. Using

  • ruby 3.2.2
  • rails 7.0.6
  • money-rails 1.15.0

with

 config.amount_column = { postfix: '_subunits' }

in my config/initializers/money.rb.

The suggestion by @kule fixed the migration for me.

I actually got the migration to work with slightly less.

config.amount_column = { postfix: '_subunits',
                         type: :integer,
                         present: true
                       }

I fixed this by merging my overrides into the original config hash when setting them. This way, my config is synced with the gem's defaults if they change in a future release.

config.amount_column = config.amount_column.merge({ postfix: '_pence' })

☝️ I think this should probably be the gem's default behaviour.

we welcome a PR