minting-rails 0.4.0 → 0.4.3
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/README.md +223 -22
- data/lib/minting/money_attribute/configuration.rb +35 -12
- data/lib/minting/money_attribute/money_type.rb +2 -2
- data/lib/minting/money_attribute/version.rb +1 -1
- data/lib/minting/railties.rb +9 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cc64238c2cc33c623696eb7c602c81a1d6c8850495dd2e46f4eaa3039aabb85b
|
|
4
|
+
data.tar.gz: a7f7f743d80954eaa09c919a2cf823c28effcbac266f1e3f1a28a9b5859def15
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2759ac6f5abf6f77effe34aaed92629af1ce4c13ffd712c15db3103406831310cae7fad543329e6f331e135c3778c1b8ce48c4354ccdf01f5a2b655cf660eadf
|
|
7
|
+
data.tar.gz: 0d031ef7e3dcd06fc31d0eba693b9c79396325af96f1e1a6177f818c8fb8a076ca57e7159d113157f8b5451d08a7308b76ff1227124a2ea16cfac1a205165b9f
|
data/README.md
CHANGED
|
@@ -1,65 +1,266 @@
|
|
|
1
1
|
# Minting::Rails
|
|
2
2
|
|
|
3
|
-
Minting::Rails
|
|
3
|
+
Minting::Rails brings [Minting](https://github.com/gferraz/minting) money objects to Active Record models.
|
|
4
|
+
|
|
5
|
+
It adds a `money_attribute` model helper, registers a `:mint_money` Active Record type, and includes small convenience methods such as `12.to_money(:USD)`, `12.dollars`, and `'12.00'.mint(:BRL)`.
|
|
6
|
+
|
|
7
|
+
## What it does
|
|
8
|
+
|
|
9
|
+
- Stores and reads model attributes as `Mint::Money` objects.
|
|
10
|
+
- Supports composed money attributes backed by amount and currency columns.
|
|
11
|
+
- Normalizes numeric, string, and `Mint::Money` assignments.
|
|
12
|
+
- Validates currencies against the currencies enabled in Minting.
|
|
13
|
+
|
|
14
|
+
## Requirements
|
|
15
|
+
|
|
16
|
+
- Ruby 3.3 or newer.
|
|
17
|
+
- Rails 7.1.3.2 or newer.
|
|
18
|
+
- Minting 1.0.0 or newer.
|
|
4
19
|
|
|
5
20
|
## Installation
|
|
6
21
|
|
|
7
|
-
Add
|
|
22
|
+
Add the gem to your Rails application's `Gemfile`:
|
|
8
23
|
|
|
9
24
|
```ruby
|
|
10
25
|
gem 'minting-rails'
|
|
11
26
|
```
|
|
12
27
|
|
|
13
|
-
|
|
28
|
+
Install it:
|
|
14
29
|
|
|
15
|
-
```
|
|
16
|
-
|
|
30
|
+
```sh
|
|
31
|
+
bundle install
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Generate the initializer:
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
bin/rails g mint:initializer
|
|
17
38
|
```
|
|
18
39
|
|
|
19
40
|
## Configuration
|
|
20
41
|
|
|
21
|
-
|
|
42
|
+
Configure Minting in `config/initializers/minting.rb`:
|
|
22
43
|
|
|
23
|
-
```
|
|
24
|
-
|
|
44
|
+
```ruby
|
|
45
|
+
Mint.configure do |config|
|
|
46
|
+
config.enabled_currencies = :all
|
|
47
|
+
config.default_currency = 'USD'
|
|
48
|
+
end
|
|
25
49
|
```
|
|
26
50
|
|
|
27
|
-
You can
|
|
51
|
+
You can limit the currencies that may be used:
|
|
28
52
|
|
|
29
53
|
```ruby
|
|
30
|
-
|
|
31
|
-
config.
|
|
54
|
+
Mint.configure do |config|
|
|
55
|
+
config.enabled_currencies = %w[USD EUR BRL]
|
|
56
|
+
config.default_currency = 'USD'
|
|
32
57
|
end
|
|
33
58
|
```
|
|
34
59
|
|
|
60
|
+
You can also register custom currencies before enabling or using them:
|
|
61
|
+
|
|
62
|
+
```ruby
|
|
63
|
+
Mint.configure do |config|
|
|
64
|
+
config.added_currencies = [
|
|
65
|
+
{ currency: 'CRC', subunit: 2, symbol: 'CRC' },
|
|
66
|
+
{ currency: 'NGN', subunit: 2, symbol: 'NGN' }
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
config.enabled_currencies = :all
|
|
70
|
+
config.default_currency = 'CRC'
|
|
71
|
+
end
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
The default currency must be registered and included in `enabled_currencies`.
|
|
75
|
+
|
|
35
76
|
## Usage
|
|
36
77
|
|
|
37
|
-
|
|
78
|
+
Declare money attributes in your Active Record models with `money_attribute`.
|
|
79
|
+
|
|
80
|
+
### Single-column fixed currency
|
|
81
|
+
|
|
82
|
+
Use this when a column always stores one currency, such as a `price` column that is always USD.
|
|
83
|
+
|
|
84
|
+
Migration:
|
|
85
|
+
|
|
86
|
+
```ruby
|
|
87
|
+
class CreateProducts < ActiveRecord::Migration[7.1]
|
|
88
|
+
def change
|
|
89
|
+
create_table :products do |t|
|
|
90
|
+
t.decimal :price
|
|
91
|
+
t.decimal :discount
|
|
92
|
+
|
|
93
|
+
t.timestamps
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Model:
|
|
38
100
|
|
|
39
101
|
```ruby
|
|
40
|
-
class
|
|
102
|
+
class Product < ApplicationRecord
|
|
41
103
|
money_attribute :price, currency: 'USD'
|
|
42
104
|
money_attribute :discount, currency: 'USD'
|
|
43
105
|
end
|
|
44
106
|
```
|
|
45
107
|
|
|
46
|
-
|
|
108
|
+
Assignments are normalized to `Mint::Money`:
|
|
109
|
+
|
|
110
|
+
```ruby
|
|
111
|
+
product = Product.new(price: 12, discount: '3.50')
|
|
112
|
+
|
|
113
|
+
product.price
|
|
114
|
+
# => #<Mint::Money ... USD 12.00>
|
|
115
|
+
|
|
116
|
+
product.discount
|
|
117
|
+
# => #<Mint::Money ... USD 3.50>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Assigning a `Mint::Money` with a different currency raises `ArgumentError`:
|
|
121
|
+
|
|
122
|
+
```ruby
|
|
123
|
+
Product.new(price: 12.to_money(:EUR))
|
|
124
|
+
# raises ArgumentError because the attribute only accepts USD
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Amount and currency columns
|
|
128
|
+
|
|
129
|
+
Use this when each row can store a different currency per record.
|
|
130
|
+
|
|
131
|
+
Migration:
|
|
132
|
+
|
|
133
|
+
```ruby
|
|
134
|
+
class CreateOffers < ActiveRecord::Migration[7.1]
|
|
135
|
+
def change
|
|
136
|
+
create_table :offers do |t|
|
|
137
|
+
t.decimal :price_amount
|
|
138
|
+
t.string :price_currency
|
|
139
|
+
|
|
140
|
+
t.timestamps
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
Model:
|
|
147
|
+
|
|
148
|
+
```ruby
|
|
149
|
+
class Offer < ApplicationRecord
|
|
150
|
+
money_attribute :price
|
|
151
|
+
end
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
The attribute is composed from `price_amount` and `price_currency`:
|
|
47
155
|
|
|
48
156
|
```ruby
|
|
49
|
-
|
|
50
|
-
|
|
157
|
+
offer = Offer.new(price: 15.to_money(:EUR))
|
|
158
|
+
|
|
159
|
+
offer.price
|
|
160
|
+
# => #<Mint::Money ... EUR 15.00>
|
|
161
|
+
|
|
162
|
+
offer.price_amount
|
|
163
|
+
# => 15.0
|
|
164
|
+
|
|
165
|
+
offer.price_currency
|
|
166
|
+
# => "EUR"
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
When you assign a plain number or string, Minting::Rails uses `Mint.default_currency`:
|
|
170
|
+
|
|
171
|
+
```ruby
|
|
172
|
+
offer = Offer.new(price: '12')
|
|
173
|
+
|
|
174
|
+
offer.price.currency_code
|
|
175
|
+
# => "USD"
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Custom column names
|
|
179
|
+
|
|
180
|
+
If your amount and currency columns do not follow the `<name>_amount` and `<name>_currency` convention, pass a mapping:
|
|
181
|
+
|
|
182
|
+
```ruby
|
|
183
|
+
class Invoice < ApplicationRecord
|
|
184
|
+
money_attribute :total, mapping: {
|
|
185
|
+
total_amount: :amount,
|
|
186
|
+
currency_code: :currency
|
|
187
|
+
}
|
|
188
|
+
end
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
The mapping keys are your database columns. The values must identify which column stores the `:amount` and which stores the `:currency`.
|
|
192
|
+
|
|
193
|
+
## Querying
|
|
194
|
+
|
|
195
|
+
Fixed-currency attributes can be queried with `Mint::Money` values:
|
|
196
|
+
|
|
197
|
+
```ruby
|
|
198
|
+
Product.where(price: 15.to_money(:USD))
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Composed attributes can also be queried with a money object:
|
|
202
|
+
|
|
203
|
+
```ruby
|
|
204
|
+
Offer.where(price: 15.to_money(:EUR))
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
You can still query the backing columns directly when that is clearer:
|
|
208
|
+
|
|
209
|
+
```ruby
|
|
210
|
+
Offer.where(price_amount: 15, price_currency: 'EUR')
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
## Convenience methods
|
|
214
|
+
|
|
215
|
+
Minting::Rails adds a few small helpers:
|
|
216
|
+
|
|
217
|
+
```ruby
|
|
218
|
+
12.to_money(:USD)
|
|
219
|
+
12.mint(:BRL)
|
|
220
|
+
12.dollars
|
|
221
|
+
12.euros
|
|
222
|
+
'12.50'.to_money(:USD)
|
|
223
|
+
'12.50'.mint(:BRL)
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
These return `Mint::Money` instances.
|
|
227
|
+
|
|
228
|
+
## Development
|
|
229
|
+
|
|
230
|
+
Clone the repository and install dependencies:
|
|
231
|
+
|
|
232
|
+
```sh
|
|
233
|
+
bundle install
|
|
51
234
|
```
|
|
52
235
|
|
|
53
|
-
|
|
236
|
+
Run the test suite:
|
|
54
237
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
238
|
+
```sh
|
|
239
|
+
bundle exec rake test
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
The repository includes a dummy Rails application under `test/dummy` for exercising the engine in a Rails environment.
|
|
243
|
+
|
|
244
|
+
## Releasing
|
|
245
|
+
|
|
246
|
+
Update the version in `lib/minting/money_attribute/version.rb`, update release notes, and build the gem:
|
|
247
|
+
|
|
248
|
+
```sh
|
|
249
|
+
gem build minting-rails.gemspec
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Publishing is configured for RubyGems.org.
|
|
58
253
|
|
|
59
254
|
## Contributing
|
|
60
255
|
|
|
61
|
-
|
|
256
|
+
Bug reports and pull requests are welcome on GitHub at [gferraz/minting-rails](https://github.com/gferraz/minting-rails).
|
|
257
|
+
|
|
258
|
+
Before opening a pull request, please run:
|
|
259
|
+
|
|
260
|
+
```sh
|
|
261
|
+
bundle exec rake test
|
|
262
|
+
```
|
|
62
263
|
|
|
63
264
|
## License
|
|
64
265
|
|
|
65
|
-
The gem is available as open source under the terms of the [MIT License](
|
|
266
|
+
The gem is available as open source under the terms of the [MIT License](MIT-LICENSE).
|
|
@@ -1,26 +1,49 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module Mint
|
|
4
|
-
|
|
4
|
+
module MoneyAttribute
|
|
5
|
+
class Configuration
|
|
6
|
+
attr_accessor :added_currencies, :enabled_currencies, :default_currency,
|
|
7
|
+
:rounding_mode, :default_format
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
def initialize
|
|
10
|
+
@added_currencies = []
|
|
11
|
+
@enabled_currencies = :all
|
|
12
|
+
@default_currency = 'USD'
|
|
13
|
+
@rounding_mode = nil
|
|
14
|
+
@default_format = nil
|
|
15
|
+
end
|
|
12
16
|
end
|
|
13
|
-
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.config
|
|
20
|
+
@config ||= MoneyAttribute::Configuration.new
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.configure
|
|
24
|
+
yield config if block_given?
|
|
25
|
+
@default_currency = nil
|
|
26
|
+
config
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.assert_valid_currency!(currency)
|
|
30
|
+
code = currency.is_a?(Mint::Currency) ? currency.code : currency.to_s
|
|
31
|
+
currency = Mint.currency(code)
|
|
32
|
+
return currency if Mint.valid_currency?(currency)
|
|
14
33
|
|
|
15
|
-
raise ArgumentError,
|
|
16
|
-
"Invalid currency '#{code}'. Please select a registered currency: #{valid_currency_codes}"
|
|
34
|
+
raise ArgumentError, "Invalid currency '#{code}'. Please select a registered currency"
|
|
17
35
|
end
|
|
18
36
|
|
|
19
37
|
def self.default_currency
|
|
20
38
|
@default_currency ||= Mint.assert_valid_currency!(config.default_currency)
|
|
21
39
|
end
|
|
22
40
|
|
|
23
|
-
def self.
|
|
24
|
-
|
|
41
|
+
def self.valid_currency?(currency)
|
|
42
|
+
return false if currency.nil?
|
|
43
|
+
|
|
44
|
+
code = currency.is_a?(Mint::Currency) ? currency.code : currency.to_s
|
|
45
|
+
currencies = config.enabled_currencies == :all ? Mint.currencies.keys : config.enabled_currencies
|
|
46
|
+
|
|
47
|
+
currencies.map(&:to_s).include?(code)
|
|
25
48
|
end
|
|
26
49
|
end
|
|
@@ -10,7 +10,7 @@ module Mint
|
|
|
10
10
|
|
|
11
11
|
def assert_valid_value(value)
|
|
12
12
|
case value
|
|
13
|
-
when Numeric, String
|
|
13
|
+
when NilClass, Numeric, String
|
|
14
14
|
return
|
|
15
15
|
when Mint::Money
|
|
16
16
|
return if value.currency == @currency
|
|
@@ -27,7 +27,7 @@ module Mint
|
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def serialize(value)
|
|
30
|
-
value
|
|
30
|
+
value&.to_d
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def self.type
|
data/lib/minting/railties.rb
CHANGED
|
@@ -7,8 +7,15 @@ module Mint
|
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
config.to_prepare do
|
|
10
|
-
Mint.config.added_currencies do |currency_data|
|
|
11
|
-
|
|
10
|
+
Array(Mint.config.added_currencies).each do |currency_data|
|
|
11
|
+
if currency_data.respond_to?(:values_at)
|
|
12
|
+
code = currency_data[:currency] || currency_data['currency']
|
|
13
|
+
subunit = currency_data[:subunit] || currency_data['subunit']
|
|
14
|
+
symbol = currency_data[:symbol] || currency_data['symbol']
|
|
15
|
+
else
|
|
16
|
+
code, subunit, symbol = *currency_data
|
|
17
|
+
end
|
|
18
|
+
Mint.register_currency(code, subunit:, symbol:)
|
|
12
19
|
end
|
|
13
20
|
end
|
|
14
21
|
end
|