sequel-money-fields 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []