sequel-money-fields 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: a94918adeebbe13b0f3a81e9fd4a0a893489c3a4be15456db5b0a4fd30cf01aa
4
+ data.tar.gz: e354f31b9cac26e0d7c18cff39218e91eba9d028fc81f3a9c960c1f202d8924a
5
+ SHA512:
6
+ metadata.gz: ec255f4145ff10166166c065bcfe2fda483390d782d4d1e10f085a5e54ebcb40592257d684b725e554d926a156636204df9502245967ff0f24acbbdd43e10580
7
+ data.tar.gz: 393660b834401798060793a215d5748eb7d462bf30ce9efc97d56471b29fa19befec32b3d3aefe0456ba54eab7576dae8f834d04310ed0029d55d506901785a4
data/README.md ADDED
@@ -0,0 +1,34 @@
1
+ # Sequel::Money::Fields
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/sequel/money/fields`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'sequel_money_fields-money-fields'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle install
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install sequel-money-fields
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+
28
+ ## Contributing
29
+
30
+ Bug reports and pull requests are welcome on GitHub at https://github.com/lithictech/sequel-money-fields.
31
+
32
+ ## License
33
+
34
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,107 @@
1
+ # frozen_string_literal: true
2
+
3
+ # frozen_string_literal: true
4
+
5
+ require "money"
6
+ require "monetize"
7
+
8
+ require "sequel"
9
+ require "sequel/model"
10
+
11
+ # Plugin for adding money fields to a model.
12
+ #
13
+ # == Example
14
+ #
15
+ # Define a model with money values:
16
+ #
17
+ # class ACME::Property < Sequel::Model(:properties)
18
+ #
19
+ # plugin :money_fields, :rent
20
+ #
21
+ # And in the schema:
22
+ #
23
+ # create_table( :properties ) do
24
+ # primary_key :id
25
+ # bigint :rent_cents, null: false
26
+ # text :rent_currency, null: false, default: 'USD'
27
+ # end
28
+ #
29
+ # And used as follows:
30
+ #
31
+ # property = ACME::Property.new(rent: Monetize.parse('$5'))
32
+ # property.rent_cents # 500
33
+ # property.rent # Money object presenting 5 USD
34
+ #
35
+ # Each money field you declare requires two columns: an integer(ish) column that
36
+ # will store the fractional amount called "#{field}_cents", and a text(ish)
37
+ # column for storing the currency name called "#{field}_currency".
38
+ #
39
+ # The plugin generates methods for getting and setting each field. The setter
40
+ # automatically parses the input using the 'monetize' gem into a Money object,
41
+ # and the getter creates a new Money object from the two columns and returns it.
42
+ #
43
+ # If you don't give at least one column to the plugin declaration, the field
44
+ # will be assumed to be called 'money'.
45
+ #
46
+ # See the docs for Money and Monetize for details on what you can do with the
47
+ # Money objects these fields use.
48
+ #
49
+
50
+ module Sequel::Plugins::MoneyFields
51
+ VERSION = "0.1.0"
52
+
53
+ def self.configure(model, *args)
54
+ args << :money if args.empty?
55
+
56
+ args.flatten.each do |field|
57
+ reader = self.make_money_reader(field)
58
+ writer = self.make_money_writer(field)
59
+
60
+ model.send(:define_method, field.to_s, reader)
61
+ model.send(:define_method, "#{field}=", writer)
62
+ end
63
+ end
64
+
65
+ # Return a Proc that can serve as the method body for the Money amount
66
+ # reader for the given +field+.
67
+ def self.make_money_reader(field)
68
+ cents_column = "#{field}_cents".to_sym
69
+ currency_column = "#{field}_currency".to_sym
70
+
71
+ return lambda do
72
+ Money.new(self[cents_column], self[currency_column])
73
+ end
74
+ end
75
+
76
+ # Return a Proc that can serve as the method body for the Money amount
77
+ # writer for the given +field+.
78
+ def self.make_money_writer(field)
79
+ cents_column = "#{field}_cents".to_sym
80
+ currency_column = "#{field}_currency".to_sym
81
+
82
+ return lambda do |value|
83
+ if value.respond_to?(:cents) && value.respond_to?(:currency)
84
+ money = Money.new(value.cents, value.currency)
85
+ else
86
+ begin
87
+ cents = value[:cents] || value["cents"]
88
+ cur = value[:currency] || value["currency"]
89
+ money = Money.new(cents, cur)
90
+ rescue TypeError, NoMethodError
91
+ money = Monetize.parse!(value)
92
+ end
93
+ end
94
+ self[cents_column] = money.cents.to_i
95
+ self[currency_column] = money.currency
96
+ end
97
+ end
98
+
99
+ ### Creates readers and writers that allow assignment to the attributes of
100
+ ### the singleton of the declaring object that correspond to the specified
101
+ ### +symbols+.
102
+ def singleton_attr_accessor(*symbols)
103
+ symbols.each do |sym|
104
+ singleton_class.__send__(:attr_accessor, sym)
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "money"
4
+ require "monetize"
5
+ require "sequel"
6
+ require "sequel/model"
7
+
8
+ require "sequel/plugins/money_fields"
9
+
10
+ RSpec.describe Sequel::Plugins::MoneyFields, :db do
11
+ context "with no fields given" do
12
+ before do
13
+ @db = Sequel.mock
14
+ @c = Class.new(Sequel::Model(@db)) do
15
+ set_columns([:id, :money_cents, :money_currency])
16
+ end
17
+ @c.plugin :money_fields
18
+ @m = @c.new
19
+ end
20
+
21
+ # let(:model_object) { model_class.new }
22
+
23
+ it "uses :money as the high-level accessor" do
24
+ @m.money = "$1800"
25
+ expect(@m.money).to be_a(Money)
26
+ expect(@m.money_cents).to eq(180_000)
27
+ expect(@m.money_currency).to eq("USD")
28
+
29
+ @m.money = {cents: 200, currency: "CAD"}
30
+ expect(@m.money_cents).to eq(200)
31
+ expect(@m.money_currency).to eq("CAD")
32
+
33
+ @m.money = OpenStruct.new(cents: 300, currency: "GBP")
34
+ expect(@m.money_cents).to eq(300)
35
+ expect(@m.money_currency).to eq("GBP")
36
+
37
+ @m.money = {"cents" => 400, "currency" => "EUR"}
38
+ expect(@m.money_cents).to eq(400)
39
+ expect(@m.money_currency).to eq("EUR")
40
+ end
41
+ end
42
+
43
+ context "with fields set to 'rent' and 'deposit'" do
44
+ # let(:model_class) do
45
+ # mc = create_model(:money_fields_test) do
46
+ # primary_key :id
47
+ # integer :rent_cents
48
+ # text :rent_currency
49
+ # integer :deposit_cents
50
+ # text :deposit_currency
51
+ # end
52
+ # mc.plugin(:money_fields, :rent, :deposit)
53
+ # mc
54
+ # end
55
+ #
56
+ # let(:model_object) { model_class.new }
57
+
58
+ before do
59
+ @db = Sequel.mock
60
+ @c = Class.new(Sequel::Model(@db)) do
61
+ set_columns([:id, :rent_cents, :rent_currency, :deposit_cents, :deposit_currency])
62
+ end
63
+ @c.plugin(:money_fields, :rent, :deposit)
64
+ @m = @c.new
65
+ end
66
+
67
+ it "provides high-level accessors for each column" do
68
+ @m.rent = 1250
69
+ expect(@m.rent).to be_a(Money)
70
+ expect(@m.rent.cents).to eq(125_000)
71
+ expect(@m.rent_cents).to eq(125_000)
72
+ expect(@m.rent_currency).to eq("USD")
73
+
74
+ @m.deposit = "CAD 82.50"
75
+ expect(@m.deposit).to be_a(Money)
76
+ expect(@m.deposit.cents).to eq(82_50)
77
+ expect(@m.deposit_cents).to eq(82_50)
78
+ expect(@m.deposit_currency).to eq("CAD")
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rspec"
4
+ require "sequel"
5
+ require "sequel/plugins/money_fields"
6
+
7
+ RSpec.configure do |config|
8
+ # config.full_backtrace = true
9
+
10
+ # RSpec::Support::ObjectFormatter.default_instance.max_formatted_output_length = 600
11
+
12
+ config.expect_with :rspec do |expectations|
13
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
14
+ end
15
+
16
+ config.mock_with :rspec do |mocks|
17
+ mocks.verify_partial_doubles = true
18
+ end
19
+
20
+ config.order = :random
21
+ Kernel.srand config.seed
22
+
23
+ config.filter_run :focus
24
+ config.run_all_when_everything_filtered = true
25
+ config.disable_monkey_patching!
26
+ config.default_formatter = "doc" if config.files_to_run.one?
27
+ end
metadata ADDED
@@ -0,0 +1,187 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sequel-money-fields
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Lithic Tech
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-04-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: monetize
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: money
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sequel
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop-performance
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop-rake
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubocop-rspec
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: rubocop-sequel
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ description:
154
+ email:
155
+ - hello@lithic.tech
156
+ executables: []
157
+ extensions: []
158
+ extra_rdoc_files: []
159
+ files:
160
+ - README.md
161
+ - lib/sequel/plugins/money_fields.rb
162
+ - spec/sequel/plugins/money_fields_spec.rb
163
+ - spec/spec_helper.rb
164
+ homepage:
165
+ licenses:
166
+ - MIT
167
+ metadata: {}
168
+ post_install_message:
169
+ rdoc_options: []
170
+ require_paths:
171
+ - lib
172
+ required_ruby_version: !ruby/object:Gem::Requirement
173
+ requirements:
174
+ - - ">="
175
+ - !ruby/object:Gem::Version
176
+ version: 2.7.2
177
+ required_rubygems_version: !ruby/object:Gem::Requirement
178
+ requirements:
179
+ - - ">="
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ requirements: []
183
+ rubygems_version: 3.1.4
184
+ signing_key:
185
+ specification_version: 4
186
+ summary: Gem for adding money fields to a model
187
+ test_files: []