minting-rails 0.4.5 → 0.5.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/README.md +62 -0
- data/lib/minting/money_attribute/configuration.rb +4 -9
- data/lib/minting/money_attribute/money_attribute.rb +18 -22
- data/lib/minting/money_attribute/money_type.rb +19 -7
- data/lib/minting/money_attribute/parser.rb +28 -0
- data/lib/minting/money_attribute/version.rb +1 -1
- data/lib/minting/rails.rb +2 -1
- metadata +3 -2
- /data/lib/minting/{money_attribute/core_ext.rb → core_ext.rb} +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bebeb146f003c49cd0f1c667648090a35f96d5d22edfec3c6616f5f45d812988
|
|
4
|
+
data.tar.gz: f6084d3f41dce76e7b437505566a1a606f54a92419cac641e017d33a9a2d0400
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 46539fbf075c057d2fb2727320975b13dd20f5efbe5a0ad2955d51f78f1720ecb4e9a3e7f52c9428f798dabf13a04a258403df6fe0735fff901a0c8e6e2ccf08
|
|
7
|
+
data.tar.gz: 66528813c392c867719ea9dcecf24fbc78a8bdd9fe9b234d6ca82c201b6d6da533ebd3058b0610223def05344e10843505a3c30fe13d65acd5593717b2d8fce2
|
data/README.md
CHANGED
|
@@ -166,6 +166,68 @@ offer.price_currency
|
|
|
166
166
|
# => "EUR"
|
|
167
167
|
```
|
|
168
168
|
|
|
169
|
+
### Integer storage
|
|
170
|
+
|
|
171
|
+
By default, money attributes are stored as `decimal` columns. If you prefer to store amounts as integer subunits (cents, pence, etc.), use a `bigint` or `integer` column instead. Minting::Rails detects the column type automatically and adapts serialization accordingly.
|
|
172
|
+
|
|
173
|
+
Migration:
|
|
174
|
+
|
|
175
|
+
```ruby
|
|
176
|
+
class CreateOrders < ActiveRecord::Migration[7.1]
|
|
177
|
+
def change
|
|
178
|
+
create_table :orders do |t|
|
|
179
|
+
t.bigint :total_amount
|
|
180
|
+
t.string :total_currency
|
|
181
|
+
|
|
182
|
+
t.timestamps
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
Model:
|
|
189
|
+
|
|
190
|
+
```ruby
|
|
191
|
+
class Order < ApplicationRecord
|
|
192
|
+
money_attribute :total
|
|
193
|
+
end
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
The amount is stored and retrieved in subunits:
|
|
197
|
+
|
|
198
|
+
```ruby
|
|
199
|
+
order = Order.new(total: 19.99.to_money(:USD))
|
|
200
|
+
|
|
201
|
+
order.total
|
|
202
|
+
# => #<Mint::Money ... USD 19.99>
|
|
203
|
+
|
|
204
|
+
order.total_amount
|
|
205
|
+
# => 1999
|
|
206
|
+
|
|
207
|
+
order.total_currency
|
|
208
|
+
# => "USD"
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
The same applies to single-column fixed-currency attributes:
|
|
212
|
+
|
|
213
|
+
```ruby
|
|
214
|
+
class Ticket < ApplicationRecord
|
|
215
|
+
money_attribute :price, currency: 'USD'
|
|
216
|
+
end
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Migration:
|
|
220
|
+
|
|
221
|
+
```ruby
|
|
222
|
+
t.bigint :price
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
No model change is needed. The column type drives the behavior.
|
|
226
|
+
|
|
227
|
+
> **Note:** Integer storage avoids decimal rounding issues and is more efficient for large tables.
|
|
228
|
+
|
|
229
|
+
### Default Currency
|
|
230
|
+
|
|
169
231
|
When you assign a plain number or string, Minting::Rails uses `Mint.default_currency`:
|
|
170
232
|
|
|
171
233
|
```ruby
|
|
@@ -27,11 +27,10 @@ module Mint
|
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def self.assert_valid_currency!(currency)
|
|
30
|
-
|
|
31
|
-
currency = Mint.currency(code)
|
|
30
|
+
currency = Mint.currency(currency)
|
|
32
31
|
return currency if Mint.valid_currency?(currency)
|
|
33
32
|
|
|
34
|
-
raise ArgumentError, "Invalid currency '#{
|
|
33
|
+
raise ArgumentError, "Invalid currency '#{currency}'. Please select a registered currency"
|
|
35
34
|
end
|
|
36
35
|
|
|
37
36
|
def self.default_currency
|
|
@@ -39,11 +38,7 @@ module Mint
|
|
|
39
38
|
end
|
|
40
39
|
|
|
41
40
|
def self.valid_currency?(currency)
|
|
42
|
-
|
|
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)
|
|
41
|
+
enabled = config.enabled_currencies
|
|
42
|
+
currency && (enabled == :all || enabled.include?(currency.code))
|
|
48
43
|
end
|
|
49
44
|
end
|
|
@@ -9,7 +9,7 @@ module Mint
|
|
|
9
9
|
# Money attribute
|
|
10
10
|
def money_attribute(name, currency: Mint.default_currency, mapping: nil)
|
|
11
11
|
currency = Mint.assert_valid_currency!(currency)
|
|
12
|
-
parser =
|
|
12
|
+
parser = Parser.new(currency)
|
|
13
13
|
if attribute_names.include? name.to_s
|
|
14
14
|
attribute(name, :mint_money, currency:)
|
|
15
15
|
normalizes(name, with: parser)
|
|
@@ -18,12 +18,28 @@ module Mint
|
|
|
18
18
|
options = {
|
|
19
19
|
allow_nil: true, class_name: 'Mint::Money',
|
|
20
20
|
constructor: parser, converter: parser,
|
|
21
|
-
mapping: {
|
|
21
|
+
mapping: {
|
|
22
|
+
aggregated[:amount] => amount_extractor_for(aggregated[:amount]),
|
|
23
|
+
aggregated[:currency] => :currency_code
|
|
24
|
+
}
|
|
22
25
|
}
|
|
23
26
|
composed_of(name, options)
|
|
24
27
|
end
|
|
25
28
|
end
|
|
26
29
|
|
|
30
|
+
def amount_extractor_for(column_name)
|
|
31
|
+
col = columns.find { |c| c.name == column_name.to_s }
|
|
32
|
+
|
|
33
|
+
case col&.type
|
|
34
|
+
when :bigint, :integer
|
|
35
|
+
:fractional
|
|
36
|
+
when :decimal, :numeric
|
|
37
|
+
:to_d
|
|
38
|
+
else
|
|
39
|
+
:to_d # :decimal, :numeric, unknown
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
27
43
|
def find_money_attributes(name, mapping:)
|
|
28
44
|
composite = if mapping.present?
|
|
29
45
|
{ amount: mapping.key(:amount).to_s, currency: mapping.key(:currency).to_s }
|
|
@@ -37,25 +53,5 @@ module Mint
|
|
|
37
53
|
composite
|
|
38
54
|
end
|
|
39
55
|
end
|
|
40
|
-
|
|
41
|
-
def self.parse(amount, currency)
|
|
42
|
-
money = case amount
|
|
43
|
-
when NilClass
|
|
44
|
-
nil
|
|
45
|
-
when Mint::Money
|
|
46
|
-
amount
|
|
47
|
-
when Numeric
|
|
48
|
-
Mint.money(amount, currency)
|
|
49
|
-
else
|
|
50
|
-
if amount.respond_to? :to_money
|
|
51
|
-
amount.to_money(currency)
|
|
52
|
-
else
|
|
53
|
-
Mint.money(amount.to_s.split[0].to_r, currency)
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
# puts "parse(#{amount}, #{currency.inspect}) => #{money.inspect}"
|
|
57
|
-
Mint.assert_valid_currency!(currency)
|
|
58
|
-
money
|
|
59
|
-
end
|
|
60
56
|
end
|
|
61
57
|
end
|
|
@@ -3,31 +3,43 @@
|
|
|
3
3
|
module Mint
|
|
4
4
|
# MintMoneyType
|
|
5
5
|
class MintMoneyType < ActiveRecord::Type::Value
|
|
6
|
-
def initialize(currency:)
|
|
7
|
-
@currency =
|
|
6
|
+
def initialize(currency:, column_type: ActiveRecord::Type::Decimal.new)
|
|
7
|
+
@currency = currency
|
|
8
|
+
@column_type = column_type
|
|
8
9
|
super()
|
|
9
10
|
end
|
|
10
11
|
|
|
11
12
|
def assert_valid_value(value)
|
|
12
13
|
case value
|
|
13
|
-
when NilClass, Numeric, String
|
|
14
|
-
return
|
|
14
|
+
when NilClass, Numeric, String then return
|
|
15
15
|
when Mint::Money
|
|
16
16
|
return if value.currency == @currency
|
|
17
17
|
|
|
18
18
|
message = "'#{value.inspect}' has different currency. Only #{@currency.code} allowed."
|
|
19
19
|
else
|
|
20
|
-
message = "'#{value}' is not a valid type for the attribute."
|
|
20
|
+
message = "'#{value.inspect}' is not a valid type for the attribute."
|
|
21
21
|
end
|
|
22
22
|
raise ArgumentError, message
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def deserialize(value)
|
|
26
|
-
|
|
26
|
+
return nil unless value
|
|
27
|
+
|
|
28
|
+
if @column_type.is_a?(ActiveRecord::Type::Integer)
|
|
29
|
+
Mint.money(value * @currency.multiplier, @currency)
|
|
30
|
+
else
|
|
31
|
+
Mint.money(value, @currency)
|
|
32
|
+
end
|
|
27
33
|
end
|
|
28
34
|
|
|
29
35
|
def serialize(value)
|
|
30
|
-
value
|
|
36
|
+
return nil unless value
|
|
37
|
+
|
|
38
|
+
if @column_type.is_a?(ActiveRecord::Type::Integer)
|
|
39
|
+
value.fractional
|
|
40
|
+
else
|
|
41
|
+
value.to_d
|
|
42
|
+
end
|
|
31
43
|
end
|
|
32
44
|
|
|
33
45
|
def self.type
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Mint
|
|
4
|
+
# MoneyAttribute
|
|
5
|
+
module MoneyAttribute
|
|
6
|
+
class Parser
|
|
7
|
+
def initialize(currency)
|
|
8
|
+
@default_currency = currency
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def call(amount, currency = @default_currency)
|
|
12
|
+
currency = Mint.assert_valid_currency!(currency)
|
|
13
|
+
case amount
|
|
14
|
+
when NilClass then nil
|
|
15
|
+
when Mint::Money then amount
|
|
16
|
+
when Numeric then Mint::Money.create(amount, currency)
|
|
17
|
+
when String then Mint::Money.create(amount.to_r, currency)
|
|
18
|
+
else
|
|
19
|
+
if amount.respond_to? :to_money
|
|
20
|
+
amount.to_money(currency)
|
|
21
|
+
else
|
|
22
|
+
Mint.parse(amount, currency)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
data/lib/minting/rails.rb
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'minting'
|
|
4
|
-
require 'minting/
|
|
4
|
+
require 'minting/core_ext'
|
|
5
5
|
require 'minting/money_attribute/configuration'
|
|
6
6
|
require 'minting/money_attribute/money_attribute'
|
|
7
7
|
require 'minting/money_attribute/money_type'
|
|
8
|
+
require 'minting/money_attribute/parser'
|
|
8
9
|
require 'minting/money_attribute/version'
|
|
9
10
|
require 'minting/railties'
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: minting-rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Gilson Ferraz
|
|
@@ -49,10 +49,11 @@ files:
|
|
|
49
49
|
- Rakefile
|
|
50
50
|
- lib/generators/minting/initializer_generator.rb
|
|
51
51
|
- lib/generators/templates/minting.rb
|
|
52
|
+
- lib/minting/core_ext.rb
|
|
52
53
|
- lib/minting/money_attribute/configuration.rb
|
|
53
|
-
- lib/minting/money_attribute/core_ext.rb
|
|
54
54
|
- lib/minting/money_attribute/money_attribute.rb
|
|
55
55
|
- lib/minting/money_attribute/money_type.rb
|
|
56
|
+
- lib/minting/money_attribute/parser.rb
|
|
56
57
|
- lib/minting/money_attribute/version.rb
|
|
57
58
|
- lib/minting/rails.rb
|
|
58
59
|
- lib/minting/railties.rb
|
|
File without changes
|