money-rails 1.15.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +33 -6
- data/LICENSE +1 -1
- data/README.md +182 -152
- data/config/locales/money.pt.yml +4 -0
- data/lib/money-rails/active_job/money_serializer.rb +23 -0
- data/lib/money-rails/active_record/monetizable.rb +39 -19
- data/lib/money-rails/configuration.rb +2 -2
- data/lib/money-rails/helpers/action_view_extension.rb +1 -1
- data/lib/money-rails/hooks.rb +16 -27
- data/lib/money-rails/mongoid/money.rb +4 -14
- data/lib/money-rails/test_helpers.rb +4 -4
- data/lib/money-rails/version.rb +3 -1
- data/lib/money-rails.rb +2 -0
- data/money-rails.gemspec +13 -26
- metadata +18 -228
- data/Rakefile +0 -84
- data/lib/money-rails/mongoid/two.rb +0 -35
- data/spec/active_record/migration_extensions/schema_statements_spec.rb +0 -101
- data/spec/active_record/migration_extensions/table_spec.rb +0 -104
- data/spec/active_record/monetizable_spec.rb +0 -1062
- data/spec/configuration_spec.rb +0 -147
- data/spec/dummy/README.rdoc +0 -261
- data/spec/dummy/Rakefile +0 -7
- data/spec/dummy/app/assets/config/manifest.js +0 -0
- data/spec/dummy/app/assets/javascripts/application.js +0 -15
- data/spec/dummy/app/assets/stylesheets/application.css +0 -13
- data/spec/dummy/app/controllers/application_controller.rb +0 -3
- data/spec/dummy/app/helpers/application_helper.rb +0 -2
- data/spec/dummy/app/models/dummy_product.rb +0 -8
- data/spec/dummy/app/models/priceable.rb +0 -8
- data/spec/dummy/app/models/product.rb +0 -59
- data/spec/dummy/app/models/service.rb +0 -5
- data/spec/dummy/app/models/transaction.rb +0 -13
- data/spec/dummy/app/views/layouts/application.html.erb +0 -14
- data/spec/dummy/config/application.rb +0 -66
- data/spec/dummy/config/boot.rb +0 -13
- data/spec/dummy/config/database.yml +0 -25
- data/spec/dummy/config/environment.rb +0 -5
- data/spec/dummy/config/environments/development.rb +0 -30
- data/spec/dummy/config/environments/production.rb +0 -69
- data/spec/dummy/config/environments/test.rb +0 -36
- data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
- data/spec/dummy/config/initializers/inflections.rb +0 -15
- data/spec/dummy/config/initializers/mime_types.rb +0 -5
- data/spec/dummy/config/initializers/money.rb +0 -31
- data/spec/dummy/config/initializers/secret_token.rb +0 -7
- data/spec/dummy/config/initializers/session_store.rb +0 -8
- data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
- data/spec/dummy/config/locales/en-GB.yml +0 -11
- data/spec/dummy/config/locales/en-US.yml +0 -5
- data/spec/dummy/config/locales/en.yml +0 -5
- data/spec/dummy/config/locales/it.yml +0 -11
- data/spec/dummy/config/mongoid.yml +0 -29
- data/spec/dummy/config/routes.rb +0 -3
- data/spec/dummy/config.ru +0 -4
- data/spec/dummy/db/migrate/20120331190108_create_products.rb +0 -10
- data/spec/dummy/db/migrate/20120402080348_add_bonus_cents_to_product.rb +0 -6
- data/spec/dummy/db/migrate/20120524052716_create_services.rb +0 -10
- data/spec/dummy/db/migrate/20120528181002_create_transactions.rb +0 -11
- data/spec/dummy/db/migrate/20120528210103_create_dummy_products.rb +0 -10
- data/spec/dummy/db/migrate/20120607210247_add_column_that_allows_nil.rb +0 -5
- data/spec/dummy/db/migrate/20120712202655_add_sale_price_cents_to_product.rb +0 -7
- data/spec/dummy/db/migrate/20130124023419_add_price_in_a_range_cents_to_products.rb +0 -5
- data/spec/dummy/db/migrate/20140110194016_add_validates_method_amount_cents_to_products.rb +0 -5
- data/spec/dummy/db/migrate/20141005075025_add_aliased_attr_to_products.rb +0 -5
- data/spec/dummy/db/migrate/20150107061030_add_delivery_fee_cents_and_restock_fee_cents_to_product.rb +0 -6
- data/spec/dummy/db/migrate/20150126231442_add_reduced_price_to_products.rb +0 -6
- data/spec/dummy/db/migrate/20150213234410_add_special_price_to_products.rb +0 -5
- data/spec/dummy/db/migrate/20150217222612_add_lambda_price_to_products.rb +0 -5
- data/spec/dummy/db/migrate/20150303222230_add_skip_validation_price_cents_to_products.rb +0 -5
- data/spec/dummy/db/migrate/20151026220420_add_optional_amount_to_transactions.rb +0 -5
- data/spec/dummy/db/schema.rb +0 -59
- data/spec/dummy/db/structure.sql +0 -21
- data/spec/dummy/public/404.html +0 -26
- data/spec/dummy/public/422.html +0 -26
- data/spec/dummy/public/500.html +0 -25
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +0 -6
- data/spec/helpers/action_view_extension_spec.rb +0 -189
- data/spec/helpers/form_helper_spec.rb +0 -19
- data/spec/money_spec.rb +0 -40
- data/spec/mongoid/mongoid_spec.rb +0 -130
- data/spec/mongoid/two_spec.rb +0 -80
- data/spec/spec_helper.rb +0 -23
- data/spec/support/database_cleaner.rb +0 -14
- data/spec/test_helpers_spec.rb +0 -72
- /data/lib/money-rails/active_record/migration_extensions/{schema_statements_pg_rails4.rb → schema_statements_pg.rb} +0 -0
- /data/lib/money-rails/active_record/migration_extensions/{table_pg_rails4.rb → table_pg.rb} +0 -0
data/README.md
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
# RubyMoney - Money-Rails
|
|
2
2
|
|
|
3
|
-
[](
|
|
4
|
-
[](http://opensource.org/licenses/MIT)
|
|
3
|
+
[](https://rubygems.org/gems/money-rails)
|
|
4
|
+
[](https://github.com/RubyMoney/money-rails/actions/workflows/ruby.yml)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
6
|
|
|
8
7
|
## Introduction
|
|
9
8
|
|
|
10
|
-
This library provides integration of the [money](
|
|
9
|
+
This library provides integration of the [money](https://github.com/Rubymoney/money) gem with Rails.
|
|
11
10
|
|
|
12
|
-
Use
|
|
13
|
-
Money objects and helpers provided by the [money](
|
|
11
|
+
Use `monetize` to specify which fields you want to be backed by
|
|
12
|
+
Money objects and helpers provided by the [money](https://github.com/Rubymoney/money)
|
|
14
13
|
gem.
|
|
15
14
|
|
|
16
15
|
Currently, this library is in active development mode, so if you would
|
|
@@ -20,26 +19,26 @@ welcome to contribute to the project.
|
|
|
20
19
|
|
|
21
20
|
## Installation
|
|
22
21
|
|
|
23
|
-
Add
|
|
22
|
+
Add it to your application’s Gemfile using:
|
|
24
23
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
$ bundle
|
|
24
|
+
```sh
|
|
25
|
+
bundle add money-rails
|
|
26
|
+
```
|
|
30
27
|
|
|
31
28
|
Or install it yourself using:
|
|
32
29
|
|
|
33
|
-
|
|
30
|
+
```sh
|
|
31
|
+
$ gem install money-rails
|
|
32
|
+
```
|
|
34
33
|
|
|
35
34
|
You can also use the money configuration initializer:
|
|
36
35
|
|
|
37
|
-
```
|
|
38
|
-
$ rails
|
|
36
|
+
```sh
|
|
37
|
+
$ bin/rails generate money_rails:initializer
|
|
39
38
|
```
|
|
40
39
|
|
|
41
40
|
There, you can define the default currency value and set other
|
|
42
|
-
configuration parameters for the
|
|
41
|
+
configuration parameters for the Rails app.
|
|
43
42
|
|
|
44
43
|
Without Rails in rack-based applications, call during initialization:
|
|
45
44
|
|
|
@@ -58,47 +57,44 @@ For example, we create a Product model which has an integer column called
|
|
|
58
57
|
|
|
59
58
|
```ruby
|
|
60
59
|
class Product < ActiveRecord::Base
|
|
61
|
-
|
|
62
60
|
monetize :price_cents
|
|
63
|
-
|
|
64
61
|
end
|
|
65
62
|
```
|
|
66
63
|
|
|
67
|
-
Now each Product object will also have an attribute called
|
|
64
|
+
Now each Product object will also have an attribute called `price` which
|
|
68
65
|
is a `Money` object, and can be used for money comparisons, conversions etc.
|
|
69
66
|
|
|
70
67
|
In this case the name of the money attribute is created automagically by removing the
|
|
71
|
-
|
|
68
|
+
`_cents` suffix from the column name.
|
|
72
69
|
|
|
73
|
-
If you are using another
|
|
74
|
-
money attribute, then you can provide an
|
|
75
|
-
|
|
70
|
+
If you are using another database column name, or you prefer another name for the
|
|
71
|
+
money attribute, then you can provide an `as` argument with a string value to the
|
|
72
|
+
`monetize` macro:
|
|
76
73
|
|
|
77
74
|
```ruby
|
|
78
75
|
monetize :discount_subunit, as: "discount"
|
|
79
76
|
```
|
|
80
77
|
|
|
81
|
-
Now the model objects will have a
|
|
82
|
-
object, wrapping the value of the
|
|
78
|
+
Now the model objects will have a `discount` attribute which is a `Money`
|
|
79
|
+
object, wrapping the value of the `discount_subunit` column with a Money
|
|
83
80
|
instance.
|
|
84
81
|
|
|
85
82
|
#### Migration helpers
|
|
86
83
|
|
|
87
|
-
If you want to add a money field to a product model you can use the
|
|
88
|
-
helper can be customized inside a
|
|
89
|
-
|
|
84
|
+
If you want to add a money field to a product model you can use the `add_monetize` helper.
|
|
85
|
+
This helper can be customized inside a `MoneyRails.configure` block. You should customize
|
|
86
|
+
the `add_monetize` helper to match the most common use case and utilize it across all
|
|
87
|
+
migrations.
|
|
90
88
|
|
|
91
89
|
```ruby
|
|
92
90
|
class MonetizeProduct < ActiveRecord::Migration
|
|
93
91
|
def change
|
|
94
|
-
|
|
95
|
-
add_monetize :products, :price # Rails 4x and above
|
|
92
|
+
add_monetize :products, :price
|
|
96
93
|
|
|
97
94
|
# OR
|
|
98
95
|
|
|
99
96
|
change_table :products do |t|
|
|
100
|
-
t.
|
|
101
|
-
t.monetize :price # Rails 4x and above
|
|
97
|
+
t.monetize :price
|
|
102
98
|
end
|
|
103
99
|
end
|
|
104
100
|
end
|
|
@@ -109,28 +105,23 @@ Another example, where the currency column is not included:
|
|
|
109
105
|
```ruby
|
|
110
106
|
class MonetizeItem < ActiveRecord::Migration
|
|
111
107
|
def change
|
|
112
|
-
|
|
108
|
+
add_monetize :items, :price, currency: { present: false }
|
|
113
109
|
end
|
|
114
110
|
end
|
|
115
111
|
```
|
|
116
112
|
|
|
117
|
-
Notice
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
migrations. If you're writing separate ```up``` and ```down``` methods, you
|
|
121
|
-
can use the ```remove_money``` helper.
|
|
113
|
+
Notice: Default value of currency field, generated by migration’s helper, is
|
|
114
|
+
USD. To override these defaults, you need change the `default_currency` in an
|
|
115
|
+
initializer and run migrations.
|
|
122
116
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
will need to use `add_monetize` instead of `add_money` column. If you're adding
|
|
127
|
-
the column within a `create_table` block, use `t.monetize`, and use
|
|
128
|
-
`remove_monetize` to remove the column.
|
|
117
|
+
The `add_monetize` helper is reversible, so you can use it inside `change`
|
|
118
|
+
migrations. If you’re writing separate `up` and `down` methods, you can use the
|
|
119
|
+
`remove_monetize` helper.
|
|
129
120
|
|
|
130
121
|
#### Allow nil values
|
|
131
122
|
|
|
132
|
-
If you want to allow nil and/or blank values to a specific
|
|
133
|
-
|
|
123
|
+
If you want to allow `nil` and/or blank values to a specific monetized field,
|
|
124
|
+
you can use the `:allow_nil` parameter:
|
|
134
125
|
|
|
135
126
|
```ruby
|
|
136
127
|
# in Product model
|
|
@@ -138,7 +129,10 @@ monetize :optional_price_cents, allow_nil: true
|
|
|
138
129
|
|
|
139
130
|
# in Migration
|
|
140
131
|
def change
|
|
141
|
-
|
|
132
|
+
add_monetize :products,
|
|
133
|
+
:optional_price,
|
|
134
|
+
amount: { null: true, default: nil },
|
|
135
|
+
currency: { null: true, default: nil }
|
|
142
136
|
end
|
|
143
137
|
|
|
144
138
|
# now blank assignments are permitted
|
|
@@ -150,7 +144,8 @@ product.optional_price_cents # => nil
|
|
|
150
144
|
|
|
151
145
|
#### Allow large numbers
|
|
152
146
|
|
|
153
|
-
If you foresee that you will be saving large values (range is -2147483648 to
|
|
147
|
+
If you foresee that you will be saving large values (range is -2147483648 to
|
|
148
|
+
+2147483647 for Postgres), increase your integer column limit to `bigint`:
|
|
154
149
|
|
|
155
150
|
```ruby
|
|
156
151
|
def change
|
|
@@ -161,19 +156,21 @@ end
|
|
|
161
156
|
#### Numericality validation options
|
|
162
157
|
|
|
163
158
|
You can also pass along
|
|
164
|
-
[numericality validation options](
|
|
159
|
+
[numericality validation options](https://guides.rubyonrails.org/active_record_validations.html#numericality)
|
|
165
160
|
such as this:
|
|
166
161
|
|
|
167
162
|
```ruby
|
|
168
|
-
monetize :price_in_a_range_cents,
|
|
163
|
+
monetize :price_in_a_range_cents,
|
|
164
|
+
allow_nil: true,
|
|
169
165
|
numericality: {
|
|
170
166
|
greater_than_or_equal_to: 0,
|
|
171
167
|
less_than_or_equal_to: 10000
|
|
172
168
|
}
|
|
173
169
|
```
|
|
174
170
|
|
|
175
|
-
Or, if you prefer, you can skip validations entirely for the attribute. This is
|
|
176
|
-
are aggregate methods and you wish to avoid executing
|
|
171
|
+
Or, if you prefer, you can skip validations entirely for the attribute. This is
|
|
172
|
+
useful if chosen attributes are aggregate methods and you wish to avoid executing
|
|
173
|
+
them on every record save.
|
|
177
174
|
|
|
178
175
|
```ruby
|
|
179
176
|
monetize :price_in_a_range_cents, disable_validation: true
|
|
@@ -186,7 +183,18 @@ to the validation you are willing to skip, like this:
|
|
|
186
183
|
monetize :price_in_a_range_cents, numericality: false
|
|
187
184
|
```
|
|
188
185
|
|
|
189
|
-
|
|
186
|
+
And you can also use `subunit_numericality` for subunit:
|
|
187
|
+
|
|
188
|
+
```ruby
|
|
189
|
+
monetize :price_in_a_range_cents,
|
|
190
|
+
allow_nil: true,
|
|
191
|
+
subunit_numericality: {
|
|
192
|
+
greater_than_or_equal_to: 0,
|
|
193
|
+
less_than_or_equal_to: 100_00
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Mongoid
|
|
190
198
|
|
|
191
199
|
`Money` is available as a field type to supply during a field definition:
|
|
192
200
|
|
|
@@ -231,18 +239,17 @@ Method return values can be monetized in the same way attributes are monetized.
|
|
|
231
239
|
|
|
232
240
|
```ruby
|
|
233
241
|
class Transaction < ActiveRecord::Base
|
|
234
|
-
|
|
235
242
|
monetize :price_cents
|
|
236
243
|
monetize :tax_cents
|
|
237
244
|
monetize :total_cents
|
|
245
|
+
|
|
238
246
|
def total_cents
|
|
239
|
-
|
|
247
|
+
price_cents + tax_cents
|
|
240
248
|
end
|
|
241
|
-
|
|
242
249
|
end
|
|
243
250
|
```
|
|
244
251
|
|
|
245
|
-
Now each Transaction object has a method called `total` which returns a `Money` object.
|
|
252
|
+
Now each `Transaction` object has a method called `total` which returns a `Money` object.
|
|
246
253
|
|
|
247
254
|
### Currencies
|
|
248
255
|
|
|
@@ -254,14 +261,12 @@ initializer of money-rails:
|
|
|
254
261
|
```ruby
|
|
255
262
|
# config/initializers/money.rb
|
|
256
263
|
MoneyRails.configure do |config|
|
|
257
|
-
|
|
258
264
|
# set the default currency
|
|
259
265
|
config.default_currency = :usd
|
|
260
|
-
|
|
261
266
|
end
|
|
262
267
|
```
|
|
263
|
-
For complete list of available currency: [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217)
|
|
264
268
|
|
|
269
|
+
For a complete list of available currencies: [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217)
|
|
265
270
|
|
|
266
271
|
If you need to set the default currency on a per-request basis, such as in a
|
|
267
272
|
multi-tenant application, you may use a lambda to lazy-load the default currency
|
|
@@ -269,10 +274,11 @@ from a field in a configuration model called `Tenant` in this example:
|
|
|
269
274
|
|
|
270
275
|
```ruby
|
|
271
276
|
# config/initializers/money.rb
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
277
|
+
ActiveSupport::Reloader.to_prepare do
|
|
278
|
+
MoneyRails.configure do |config|
|
|
279
|
+
# set the default currency based on client configuration
|
|
280
|
+
config.default_currency = -> { Tenant.current.default_currency }
|
|
281
|
+
end
|
|
276
282
|
end
|
|
277
283
|
```
|
|
278
284
|
|
|
@@ -282,53 +288,56 @@ meet your needs.
|
|
|
282
288
|
#### Model Currency
|
|
283
289
|
|
|
284
290
|
You can override the global default currency within a specific ActiveRecord
|
|
285
|
-
model using the
|
|
291
|
+
model using the `register_currency` macro:
|
|
286
292
|
|
|
287
293
|
```ruby
|
|
288
294
|
# app/models/product.rb
|
|
289
295
|
class Product < ActiveRecord::Base
|
|
290
|
-
|
|
291
296
|
# Use EUR as model level currency
|
|
292
297
|
register_currency :eur
|
|
293
298
|
|
|
294
299
|
monetize :discount_subunit, as: "discount"
|
|
295
300
|
monetize :bonus_cents
|
|
296
|
-
|
|
297
301
|
end
|
|
298
302
|
```
|
|
299
303
|
|
|
300
|
-
Now
|
|
301
|
-
|
|
304
|
+
Now `product.discount` and `product.bonus` will return a `Money` object using
|
|
305
|
+
EUR as their currency, instead of the default USD.
|
|
302
306
|
|
|
303
|
-
(This is not available in
|
|
307
|
+
(This is not available in Mongoid).
|
|
304
308
|
|
|
305
|
-
#### Attribute Currency (
|
|
309
|
+
#### Attribute Currency (`:with_currency`)
|
|
306
310
|
|
|
307
|
-
By passing the option
|
|
308
|
-
with a currency code (symbol or string) or a callable object (object that responds
|
|
309
|
-
|
|
310
|
-
|
|
311
|
+
By passing the option `:with_currency` to the `monetize` macro call,
|
|
312
|
+
with a currency code (symbol or string) or a callable object (object that responds
|
|
313
|
+
to the `call` method) that returns a currency code, as its value, you can define
|
|
314
|
+
a currency in a more granular way. This will let you attach the given currency
|
|
315
|
+
only to the specified monetized model attribute (allowing you to, for example,
|
|
316
|
+
monetize different attributes of the same model with different currencies).
|
|
311
317
|
|
|
312
|
-
This allows you to override both the model level and the global
|
|
313
|
-
|
|
318
|
+
This allows you to override both the model level and the global default
|
|
319
|
+
currencies:
|
|
314
320
|
|
|
315
321
|
```ruby
|
|
316
322
|
# app/models/product.rb
|
|
317
323
|
class Product < ActiveRecord::Base
|
|
318
|
-
|
|
319
324
|
# Use EUR as the model level currency
|
|
320
325
|
register_currency :eur
|
|
321
326
|
|
|
322
327
|
monetize :discount_subunit, as: "discount"
|
|
323
328
|
monetize :bonus_cents, with_currency: :gbp
|
|
324
|
-
|
|
325
329
|
end
|
|
326
330
|
```
|
|
327
331
|
|
|
328
|
-
In this case
|
|
329
|
-
currency, whereas
|
|
332
|
+
In this case `product.bonus` will return a Money object with GBP as its
|
|
333
|
+
currency, whereas `product.discount.currency.to_s # => EUR`
|
|
330
334
|
|
|
331
|
-
As mentioned earlier you can use an object that responds to the method
|
|
335
|
+
As mentioned earlier you can use an object that responds to the method `call`
|
|
336
|
+
and accepts the model instance as a parameter. That means you can use a `Proc`
|
|
337
|
+
or `lambda` (we would recommend `lambda` over `Proc` because of their
|
|
338
|
+
[different control flow characteristics](https://stackoverflow.com/questions/1740046/whats-the-difference-between-a-proc-and-a-lambda-in-ruby))
|
|
339
|
+
or even define a separate `class` with an instance or class method (maybe even a
|
|
340
|
+
`module`) to return the currency code:
|
|
332
341
|
|
|
333
342
|
```ruby
|
|
334
343
|
class DeliveryFee
|
|
@@ -343,9 +352,7 @@ module OptionalPrice
|
|
|
343
352
|
end
|
|
344
353
|
end
|
|
345
354
|
|
|
346
|
-
# app/models/product.rb
|
|
347
355
|
class Product < ActiveRecord::Base
|
|
348
|
-
|
|
349
356
|
monetize :price_cents, with_currency: ->(_product) { :gbp }
|
|
350
357
|
monetize :delivery_fee_cents, with_currency: DeliveryFee.new
|
|
351
358
|
monetize :optional_price_cents, with_currency: OptionalPrice
|
|
@@ -356,9 +363,9 @@ end
|
|
|
356
363
|
|
|
357
364
|
All the previous options do not require any extra model fields to hold
|
|
358
365
|
the currency values. If the currency of a field will vary from
|
|
359
|
-
one model instance to another, then you should add a column called
|
|
360
|
-
to your database table and pass the option
|
|
361
|
-
to the
|
|
366
|
+
one model instance to another, then you should add a column called `currency`
|
|
367
|
+
to your database table and pass the option `with_model_currency`
|
|
368
|
+
to the `monetize` macro.
|
|
362
369
|
|
|
363
370
|
money-rails will use this knowledge to override the model level and global
|
|
364
371
|
default values. Non-nil instance currency values also override attribute
|
|
@@ -366,16 +373,11 @@ currency values, so they have the highest precedence.
|
|
|
366
373
|
|
|
367
374
|
```ruby
|
|
368
375
|
class Transaction < ActiveRecord::Base
|
|
369
|
-
|
|
370
|
-
# This model has a separate currency column
|
|
371
|
-
attr_accessible :amount_cents, :currency, :tax_cents
|
|
372
|
-
|
|
373
376
|
# Use model level currency
|
|
374
377
|
register_currency :gbp
|
|
375
378
|
|
|
376
379
|
monetize :amount_cents, with_model_currency: :currency
|
|
377
380
|
monetize :tax_cents, with_model_currency: :currency
|
|
378
|
-
|
|
379
381
|
end
|
|
380
382
|
|
|
381
383
|
# Now instantiating with a specific currency overrides
|
|
@@ -386,11 +388,10 @@ t.amount == Money.new(2500, "CAD") # true
|
|
|
386
388
|
|
|
387
389
|
### Configuration parameters
|
|
388
390
|
|
|
389
|
-
You can handle a bunch of configuration params through
|
|
391
|
+
You can handle a bunch of configuration params through `money.rb` initializer:
|
|
390
392
|
|
|
391
393
|
```ruby
|
|
392
394
|
MoneyRails.configure do |config|
|
|
393
|
-
|
|
394
395
|
# To set the default currency
|
|
395
396
|
#
|
|
396
397
|
# config.default_currency = :usd
|
|
@@ -414,37 +415,39 @@ MoneyRails.configure do |config|
|
|
|
414
415
|
|
|
415
416
|
# Default ActiveRecord migration configuration values for columns:
|
|
416
417
|
#
|
|
417
|
-
# config.amount_column = {
|
|
418
|
-
#
|
|
419
|
-
#
|
|
420
|
-
#
|
|
421
|
-
#
|
|
422
|
-
#
|
|
423
|
-
#
|
|
424
|
-
#
|
|
418
|
+
# config.amount_column = {
|
|
419
|
+
# prefix: '', # column name prefix
|
|
420
|
+
# postfix: '_cents', # column name postfix
|
|
421
|
+
# column_name: nil, # full column name (overrides prefix, postfix and accessor name)
|
|
422
|
+
# type: :integer, # column type
|
|
423
|
+
# present: true, # column will be created
|
|
424
|
+
# null: false, # other options will be treated as column options
|
|
425
|
+
# default: 0
|
|
426
|
+
# }
|
|
425
427
|
#
|
|
426
|
-
# config.currency_column = {
|
|
427
|
-
#
|
|
428
|
-
#
|
|
429
|
-
#
|
|
430
|
-
#
|
|
431
|
-
#
|
|
432
|
-
#
|
|
433
|
-
#
|
|
428
|
+
# config.currency_column = {
|
|
429
|
+
# prefix: '',
|
|
430
|
+
# postfix: '_currency',
|
|
431
|
+
# column_name: nil,
|
|
432
|
+
# type: :string,
|
|
433
|
+
# present: true,
|
|
434
|
+
# null: false,
|
|
435
|
+
# default: 'USD'
|
|
436
|
+
# }
|
|
434
437
|
|
|
435
438
|
# Register a custom currency
|
|
436
439
|
#
|
|
437
440
|
# Example:
|
|
438
441
|
# config.register_currency = {
|
|
439
|
-
# priority:
|
|
440
|
-
# iso_code:
|
|
441
|
-
# name:
|
|
442
|
-
# symbol:
|
|
443
|
-
# symbol_first:
|
|
444
|
-
# subunit:
|
|
445
|
-
# subunit_to_unit:
|
|
442
|
+
# priority: 1,
|
|
443
|
+
# iso_code: "EU4",
|
|
444
|
+
# name: "Euro with subunit of 4 digits",
|
|
445
|
+
# symbol: "€",
|
|
446
|
+
# symbol_first: true,
|
|
447
|
+
# subunit: "Subcent",
|
|
448
|
+
# subunit_to_unit: 10000,
|
|
446
449
|
# thousands_separator: ".",
|
|
447
|
-
# decimal_mark:
|
|
450
|
+
# decimal_mark: ","
|
|
448
451
|
# }
|
|
449
452
|
|
|
450
453
|
# Specify a rounding mode
|
|
@@ -471,25 +474,32 @@ MoneyRails.configure do |config|
|
|
|
471
474
|
# symbol: nil,
|
|
472
475
|
# sign_before_symbol: nil
|
|
473
476
|
# }
|
|
477
|
+
|
|
478
|
+
# Set whether an error should be raised when parsing money values
|
|
479
|
+
# This includes assigning to a monetized field with the wrong currency
|
|
480
|
+
# Default value is false
|
|
481
|
+
#
|
|
482
|
+
# config.raise_error_on_money_parsing = true
|
|
474
483
|
end
|
|
475
484
|
```
|
|
476
485
|
|
|
477
|
-
*
|
|
478
|
-
*
|
|
486
|
+
* `default_currency`: Set the default (application wide) currency (USD is the default)
|
|
487
|
+
* `include_validations`: Permit the inclusion of a `validates_numericality_of`
|
|
479
488
|
validation for each monetized field (the default is true)
|
|
480
|
-
*
|
|
489
|
+
* `register_currency`: Register one custom currency. This option can be
|
|
481
490
|
used more than once to set more custom currencies. The value should be
|
|
482
|
-
a hash of all the necessary key/value pairs (important keys:
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
*
|
|
486
|
-
|
|
487
|
-
*
|
|
491
|
+
a hash of all the necessary key/value pairs (important keys: `:priority`, `:iso_code`,
|
|
492
|
+
`:name`, `:symbol`, `:symbol_first`, `:subunit`, `:subunit_to_unit`,
|
|
493
|
+
`:thousands_separator`, `:decimal_mark`).
|
|
494
|
+
* `add_rate`: Provide custom exchange rate for currencies in one direction only! This
|
|
495
|
+
rate is added to the attached bank object.
|
|
496
|
+
* `default_bank`: The default bank object holding exchange rates etc.
|
|
488
497
|
(https://github.com/RubyMoney/money#currency-exchange)
|
|
489
|
-
*
|
|
490
|
-
*
|
|
491
|
-
*
|
|
492
|
-
*
|
|
498
|
+
* `default_format`: Force `Money#format` to use these options for formatting.
|
|
499
|
+
* `amount_column`: Provide values for the amount column (holding the fractional part of a money object).
|
|
500
|
+
* `currency_column`: Provide default values or even disable (`present: false`) the currency column.
|
|
501
|
+
* `rounding_mode`: Set `Money.rounding_mode` to one of the BigDecimal constants.
|
|
502
|
+
* `raise_error_on_money_parsing`: Set whether errors should be raised when parsing money values
|
|
493
503
|
|
|
494
504
|
### Helpers
|
|
495
505
|
|
|
@@ -504,7 +514,7 @@ _For examples below, `@money_object == <Money fractional:650 currency:USD>`_
|
|
|
504
514
|
| `money_without_cents_and_with_symbol @money_object` | $6 |
|
|
505
515
|
| `money_only_cents @money_object` | 50 |
|
|
506
516
|
|
|
507
|
-
#### `no_cents_if_whole`
|
|
517
|
+
#### `no_cents_if_whole` configuration param
|
|
508
518
|
|
|
509
519
|
`humanized_money` and `humanized_money_with_symbol` will not render the cents part if it contains only zeros, unless `config.no_cents_if_whole` is set to `false` in the `money.rb` configuration (default: true).
|
|
510
520
|
Note that the `config.default_format` will be overwritten by `config.no_cents_if_whole`.
|
|
@@ -512,24 +522,53 @@ So `humanized_money` will ignore `config.default_format = { no_cents_if_whole: f
|
|
|
512
522
|
|
|
513
523
|
### Testing
|
|
514
524
|
|
|
515
|
-
|
|
516
|
-
|
|
525
|
+
The test helpers work with both RSpec and Minitest.
|
|
526
|
+
|
|
527
|
+
#### RSpec
|
|
517
528
|
|
|
518
|
-
|
|
529
|
+
If you use RSpec, just require the test helpers in `spec_helper.rb`:
|
|
530
|
+
|
|
531
|
+
```ruby
|
|
532
|
+
require "money-rails/test_helpers"
|
|
533
|
+
```
|
|
534
|
+
|
|
535
|
+
The helpers will automatically be included in your RSpec tests.
|
|
536
|
+
|
|
537
|
+
#### Minitest
|
|
538
|
+
|
|
539
|
+
If you use Minitest, require the test helpers and include them in your test class:
|
|
540
|
+
|
|
541
|
+
```ruby
|
|
542
|
+
require "money-rails/test_helpers"
|
|
543
|
+
|
|
544
|
+
class ProductTest < Minitest::Test
|
|
545
|
+
include MoneyRails::TestHelpers
|
|
546
|
+
|
|
547
|
+
def test_monetizes_price
|
|
548
|
+
matcher = monetize(:price_cents)
|
|
549
|
+
assert matcher.matches?(Product)
|
|
550
|
+
end
|
|
551
|
+
end
|
|
552
|
+
```
|
|
553
|
+
|
|
554
|
+
#### The `monetize` matcher
|
|
519
555
|
|
|
520
556
|
```ruby
|
|
521
557
|
is_expected.to monetize(:price)
|
|
522
558
|
```
|
|
559
|
+
|
|
523
560
|
This will ensure that a column called `price_cents` is being monetized.
|
|
524
561
|
|
|
525
562
|
```ruby
|
|
526
563
|
is_expected.to monetize(:price).allow_nil
|
|
527
564
|
```
|
|
565
|
+
|
|
528
566
|
By using `allow_nil` you can specify money attributes that accept nil values.
|
|
529
567
|
|
|
530
568
|
```ruby
|
|
531
569
|
is_expected.to monetize(:price).as(:discount_value)
|
|
532
570
|
```
|
|
571
|
+
|
|
533
572
|
By using `as` chain you can specify the exact name to which a monetized
|
|
534
573
|
column is being mapped.
|
|
535
574
|
|
|
@@ -552,14 +591,15 @@ For examples on using the test_helpers look at
|
|
|
552
591
|
|
|
553
592
|
## Supported ORMs/ODMs
|
|
554
593
|
|
|
555
|
-
* ActiveRecord (>=
|
|
556
|
-
* Mongoid (>=
|
|
594
|
+
* ActiveRecord (>= 7.0)
|
|
595
|
+
* Mongoid (>= 7.x)
|
|
557
596
|
|
|
558
597
|
## Supported Ruby interpreters
|
|
559
598
|
|
|
560
|
-
* MRI Ruby >= 1
|
|
599
|
+
* MRI Ruby >= 3.1
|
|
561
600
|
|
|
562
|
-
You can see a full list of the currently supported interpreters in
|
|
601
|
+
You can see a full list of the currently supported interpreters in
|
|
602
|
+
[ruby.yml](https://github.com/RubyMoney/money-rails/blob/main/.github/workflows/ruby.yml)
|
|
563
603
|
|
|
564
604
|
## Contributing
|
|
565
605
|
|
|
@@ -573,18 +613,8 @@ You can see a full list of the currently supported interpreters in [travis.yml](
|
|
|
573
613
|
|
|
574
614
|
### How to run the tests
|
|
575
615
|
|
|
576
|
-
Our tests are executed with several ORMs - see `Rakefile` for details. To install all required gems run `rake spec:all
|
|
616
|
+
Our tests are executed with several ORMs - see `Rakefile` for details. To install all required gems run `rake spec:all`. That command will take care of installing all required gems for all the different Gemfiles and then running the test suite with the installed bundle.
|
|
577
617
|
|
|
578
618
|
You can also run the test suite against a specific ORM or Rails version, `rake -T` will give you an idea of the possible task (take a look at the tasks under the spec: namespace).
|
|
579
619
|
|
|
580
|
-
If you are testing against mongoid, make sure to have the mongod process running before executing the suite
|
|
581
|
-
|
|
582
|
-
## Maintainers
|
|
583
|
-
|
|
584
|
-
* Andreas Loupasakis (https://github.com/alup)
|
|
585
|
-
* Shane Emmons (https://github.com/semmons99)
|
|
586
|
-
* Simone Carletti (https://github.com/weppos)
|
|
587
|
-
|
|
588
|
-
## License
|
|
589
|
-
|
|
590
|
-
MIT License. Copyright 2021 RubyMoney.
|
|
620
|
+
If you are testing against mongoid, make sure to have the mongod process running before executing the suite. (E.g. `sudo mongod --quiet`)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module MoneyRails
|
|
4
|
+
module ActiveJob
|
|
5
|
+
class MoneySerializer < ::ActiveJob::Serializers::ObjectSerializer
|
|
6
|
+
def serialize?(argument)
|
|
7
|
+
argument.is_a?(Money)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def serialize(money)
|
|
11
|
+
super("cents" => money.cents, "currency" => money.currency.to_s)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def deserialize(hash)
|
|
15
|
+
Money.new(hash["cents"], hash["currency"])
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def klass
|
|
19
|
+
Money
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|