acts_as_priceable 0.2.0 → 0.2.1

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.
data/README.md CHANGED
@@ -105,8 +105,16 @@ class Product < ActiveRecord::Base
105
105
  end
106
106
  ```
107
107
 
108
+ From version 0.2.1 you can use serialized fields to store your price information. Gem supports serialization to Hash and Hstore
108
109
 
110
+ ```ruby
111
+ class Product
112
+ serialize :data, Hash
113
+
114
+ has_price :price, serialized: :data
109
115
 
116
+ end
117
+ ```
110
118
 
111
119
  ## Contributing
112
120
 
@@ -17,5 +17,6 @@ Gem::Specification.new do |gem|
17
17
  gem.add_dependency "activerecord", ">= 3.0.0"
18
18
  gem.add_development_dependency 'rspec', "~> 2.10.0"
19
19
  gem.add_development_dependency 'rake'
20
- gem.add_development_dependency 'sqlite3'
20
+ gem.add_development_dependency 'pg'
21
+ gem.add_development_dependency 'activerecord-postgres-hstore'
21
22
  end
@@ -14,11 +14,12 @@ module ActsAsPriceable
14
14
  def has_price(name = :price, options = {})
15
15
  scale = options[:scale] || 2
16
16
  without_validations = options[:without_validations] || false
17
+ serialized = options[:serialized]
17
18
 
18
19
  ActsAsPriceable::Schema::COLUMNS.each do |column_name, column_type|
19
20
  raise AttributeError, "#{name}_#{column_name} is not defined" if columns_hash["#{name}_#{column_name}"].nil?
20
21
  raise AttributeError, "#{name}_#{column_name} has wrong column type (is #{columns_hash["#{name}_#{column_name}"].type}) should be #{column_type}" if columns_hash["#{name}_#{column_name}"].type != column_type
21
- end
22
+ end if serialized.nil?
22
23
 
23
24
  gross = "#{name}_gross"
24
25
  net = "#{name}_net"
@@ -26,20 +27,44 @@ module ActsAsPriceable
26
27
  tax = "#{name}_tax"
27
28
  mode = "#{name}_mode"
28
29
 
30
+ send :define_method, "get_#{name}_attribute" do |attribute|
31
+ if serialized.nil?
32
+ self[attribute.to_sym].to_i
33
+ else
34
+ self.send(serialized)[attribute.to_s].to_i
35
+ end
36
+ end
37
+
38
+ send :define_method, "set_#{name}_attribute" do |attribute, value|
39
+ if serialized.nil?
40
+ self[attribute.to_sym] = value
41
+ else
42
+ self.send(serialized)[attribute.to_s] = value
43
+ end
44
+ end
45
+
29
46
  send :define_method, gross do
30
- BigDecimal.new(self[gross.to_sym].to_i) / BigDecimal.new(10**scale.to_i)
47
+ BigDecimal.new(self.send("get_#{name}_attribute", gross)) / BigDecimal.new(10**scale.to_i)
31
48
  end
32
49
 
33
50
  send :define_method, "#{gross}=" do |value|
34
- self[gross.to_sym] = (value.to_s.gsub(',', '.').to_d * (10**scale)).to_i
51
+ self.send "set_#{name}_attribute", gross, (value.to_s.gsub(',', '.').to_d * (10**scale)).to_i
35
52
  end
36
53
 
37
54
  send :define_method, net do
38
- BigDecimal.new(self[net.to_sym].to_i) / BigDecimal.new(10**scale.to_i)
55
+ BigDecimal.new(self.send("get_#{name}_attribute", net)) / BigDecimal.new(10**scale.to_i)
39
56
  end
40
57
 
41
58
  send :define_method, "#{net}=" do |value|
42
- self[net.to_sym] = (value.to_s.gsub(',', '.').to_d * (10**scale)).to_i
59
+ self.send("set_#{name}_attribute", net, (value.to_s.gsub(',', '.').to_d * (10**scale)).to_i)
60
+ end
61
+
62
+ send :define_method, tax do
63
+ self.send "get_#{name}_attribute", tax
64
+ end
65
+
66
+ send :define_method, "#{tax}=" do |value|
67
+ self.send "set_#{name}_attribute", tax, value
43
68
  end
44
69
 
45
70
  send :define_method, tax_value do
@@ -1,3 +1,3 @@
1
1
  module ActsAsPriceable
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
@@ -27,7 +27,7 @@ describe Dummy do
27
27
  @dummy.should respond_to(:price=)
28
28
  end
29
29
 
30
- it 'should have mode attr_accessor' do
30
+ it 'should have price_mode attr_accessor' do
31
31
  @dummy.should respond_to(:price_mode)
32
32
  @dummy.should respond_to(:price_mode=)
33
33
  end
@@ -42,7 +42,7 @@ describe Dummy do
42
42
 
43
43
  it 'price_net should be converted to integer' do
44
44
  @dummy.price_net = @test_value
45
- @dummy[:price_net].should be(1020)
45
+ @dummy.get_price_attribute(:price_net).should be(1020)
46
46
  end
47
47
 
48
48
  it 'price_net should return correct value' do
@@ -52,7 +52,7 @@ describe Dummy do
52
52
 
53
53
  it 'price_gross should be converted to integer' do
54
54
  @dummy.price_gross = @test_value
55
- @dummy[:price_gross].should be(1020)
55
+ @dummy.get_price_attribute(:price_gross).should be(1020)
56
56
  end
57
57
 
58
58
  it 'price_gross should return correct value' do
@@ -115,4 +115,229 @@ describe Dummy do
115
115
  end
116
116
  end
117
117
 
118
+ end
119
+
120
+ describe DummySerialize do
121
+
122
+ describe 'class methods' do
123
+ it 'should have has_price method' do
124
+ DummySerialize.should respond_to(:has_price)
125
+ end
126
+ end
127
+
128
+ describe 'instance' do
129
+
130
+ describe 'hstore' do
131
+
132
+ before(:all) do
133
+ DummySerialize.send :has_price, :price, serialized: :hstore_data
134
+ @test_value = '10.20'
135
+ end
136
+
137
+ describe 'methods' do
138
+
139
+ before(:each) do
140
+ @dummy = DummySerialize.new
141
+ end
142
+
143
+ it 'should have price attr_accessor' do
144
+ @dummy.should respond_to(:price)
145
+ @dummy.should respond_to(:price=)
146
+ end
147
+
148
+ it 'should have price_mode attr_accessor' do
149
+ @dummy.should respond_to(:price_mode)
150
+ @dummy.should respond_to(:price_mode=)
151
+ end
152
+
153
+ it 'should have price_tax_value method' do
154
+ @dummy.should respond_to(:price_tax_value)
155
+ end
156
+
157
+ it 'should have update_price method' do
158
+ @dummy.should respond_to(:update_price)
159
+ end
160
+
161
+ it 'price_net should be converted to integer' do
162
+ @dummy.price_net = @test_value
163
+ @dummy.get_price_attribute(:price_net).should be(1020)
164
+ end
165
+
166
+ it 'price_net should return correct value' do
167
+ @dummy.price_net = @test_value
168
+ @dummy.price_net.should == BigDecimal.new(@test_value)
169
+ end
170
+
171
+ it 'price_gross should be converted to integer' do
172
+ @dummy.price_gross = @test_value
173
+ @dummy.get_price_attribute(:price_gross).should be(1020)
174
+ end
175
+
176
+ it 'price_gross should return correct value' do
177
+ @dummy.price_gross = @test_value
178
+ @dummy.price_gross.should == BigDecimal.new(@test_value)
179
+ end
180
+
181
+ it 'calculates price gross from price_net' do
182
+ @dummy.price = '10.00'
183
+ @dummy.price_tax = 23
184
+ @dummy.price_mode = 'net'
185
+ @dummy.update_price
186
+ @dummy.price_net.should == BigDecimal.new('10.00')
187
+ @dummy.price_gross.should == BigDecimal.new('12.30')
188
+ end
189
+
190
+ it 'calculates price net from price gross' do
191
+ @dummy.price = '12.30'
192
+ @dummy.price_tax = 23
193
+ @dummy.price_mode = 'gross'
194
+ @dummy.update_price
195
+ @dummy.price_net.should == BigDecimal.new('10.00')
196
+ @dummy.price_gross.should == BigDecimal.new('12.30')
197
+ end
198
+
199
+ it 'calculates tax value properly' do
200
+ @dummy.price = '10.00'
201
+ @dummy.price_tax = 23
202
+ @dummy.price_mode = 'net'
203
+ @dummy.update_price
204
+ @dummy.price_tax_value.should == BigDecimal.new('2.30')
205
+ end
206
+
207
+ end
208
+
209
+ describe 'validations' do
210
+
211
+ before(:each) do
212
+ @dummy = DummySerialize.new price_net: '10.00', price_gross: '12.30', price_tax: 23
213
+ end
214
+
215
+ it 'correct should be valid' do
216
+ @dummy.valid?.should be(true)
217
+ end
218
+
219
+ it "price_net can't be negative" do
220
+ @dummy.price_net = -1
221
+ @dummy.valid?.should be(false)
222
+ end
223
+
224
+ it "price_gross can't be negative" do
225
+ @dummy.price_gross = -1
226
+ @dummy.valid?.should be(false)
227
+ end
228
+
229
+ it "price_tax can't be negative" do
230
+ @dummy.price_tax = -1
231
+ @dummy.valid?.should be(false)
232
+ end
233
+ end
234
+ end
235
+
236
+ describe 'hash' do
237
+
238
+ before(:all) do
239
+ DummySerialize.send :has_price, :price, serialized: :hash_data
240
+ @test_value = '10.20'
241
+ end
242
+
243
+ describe 'methods' do
244
+
245
+ before(:each) do
246
+ @dummy = DummySerialize.new
247
+ end
248
+
249
+ it 'should have price attr_accessor' do
250
+ @dummy.should respond_to(:price)
251
+ @dummy.should respond_to(:price=)
252
+ end
253
+
254
+ it 'should have price_mode attr_accessor' do
255
+ @dummy.should respond_to(:price_mode)
256
+ @dummy.should respond_to(:price_mode=)
257
+ end
258
+
259
+ it 'should have price_tax_value method' do
260
+ @dummy.should respond_to(:price_tax_value)
261
+ end
262
+
263
+ it 'should have update_price method' do
264
+ @dummy.should respond_to(:update_price)
265
+ end
266
+
267
+ it 'price_net should be converted to integer' do
268
+ @dummy.price_net = @test_value
269
+ @dummy.get_price_attribute(:price_net).should be(1020)
270
+ end
271
+
272
+ it 'price_net should return correct value' do
273
+ @dummy.price_net = @test_value
274
+ @dummy.price_net.should == BigDecimal.new(@test_value)
275
+ end
276
+
277
+ it 'price_gross should be converted to integer' do
278
+ @dummy.price_gross = @test_value
279
+ @dummy.get_price_attribute(:price_gross).should be(1020)
280
+ end
281
+
282
+ it 'price_gross should return correct value' do
283
+ @dummy.price_gross = @test_value
284
+ @dummy.price_gross.should == BigDecimal.new(@test_value)
285
+ end
286
+
287
+ it 'calculates price gross from price_net' do
288
+ @dummy.price = '10.00'
289
+ @dummy.price_tax = 23
290
+ @dummy.price_mode = 'net'
291
+ @dummy.update_price
292
+ @dummy.price_net.should == BigDecimal.new('10.00')
293
+ @dummy.price_gross.should == BigDecimal.new('12.30')
294
+ end
295
+
296
+ it 'calculates price net from price gross' do
297
+ @dummy.price = '12.30'
298
+ @dummy.price_tax = 23
299
+ @dummy.price_mode = 'gross'
300
+ @dummy.update_price
301
+ @dummy.price_net.should == BigDecimal.new('10.00')
302
+ @dummy.price_gross.should == BigDecimal.new('12.30')
303
+ end
304
+
305
+ it 'calculates tax value properly' do
306
+ @dummy.price = '10.00'
307
+ @dummy.price_tax = 23
308
+ @dummy.price_mode = 'net'
309
+ @dummy.update_price
310
+ @dummy.price_tax_value.should == BigDecimal.new('2.30')
311
+ end
312
+
313
+ end
314
+
315
+ describe 'validations' do
316
+
317
+ before(:each) do
318
+ @dummy = DummySerialize.new price_net: '10.00', price_gross: '12.30', price_tax: 23
319
+ end
320
+
321
+ it 'correct should be valid' do
322
+ @dummy.valid?.should be(true)
323
+ end
324
+
325
+ it "price_net can't be negative" do
326
+ @dummy.price_net = -1
327
+ @dummy.valid?.should be(false)
328
+ end
329
+
330
+ it "price_gross can't be negative" do
331
+ @dummy.price_gross = -1
332
+ @dummy.valid?.should be(false)
333
+ end
334
+
335
+ it "price_tax can't be negative" do
336
+ @dummy.price_tax = -1
337
+ @dummy.valid?.should be(false)
338
+ end
339
+ end
340
+ end
341
+ end
342
+
118
343
  end
@@ -1,3 +1,8 @@
1
1
  test:
2
- adapter: sqlite3
3
- database: ":memory:"
2
+ adapter: postgresql
3
+ database: acts_as_priceable_test
4
+ username: ruby
5
+ password: ruby
6
+ port: 5432
7
+ host: localhost
8
+ min_messages: warning
@@ -0,0 +1,6 @@
1
+ class DummySerialize < ActiveRecord::Base
2
+
3
+ serialize :hash_data, Hash
4
+ serialize :hstore_data, ActiveRecord::Coders::Hstore
5
+
6
+ end
@@ -4,17 +4,27 @@ require 'yaml'
4
4
 
5
5
 
6
6
  def create_tables
7
+ #ActiveRecord::Base.connection.execute "CREATE EXTENSION hstore;"
8
+
7
9
  ActiveRecord::Base.connection.create_table :dummies, force: true do |table|
8
10
  table.column :price_gross, :integer
9
11
  table.column :price_net, :integer
10
12
  table.column :price_tax, :integer
11
13
  end
14
+
15
+ ActiveRecord::Base.connection.create_table :dummy_serializes, force: true do |table|
16
+ table.column :hstore_data, :hstore
17
+ table.column :hash_data, :text
18
+ end
12
19
  end
13
20
 
14
21
  RSpec.configure do |config|
15
22
  ActiveRecord::Base.establish_connection YAML.load_file("#{File.dirname __FILE__}/database.yml")['test']
16
23
  create_tables
24
+ #require 'active_support'
25
+ require 'activerecord-postgres-hstore'
17
26
  require 'models/dummy'
27
+ require 'models/dummy_serialize'
18
28
  config.color_enabled = true
19
29
  #config.formatter = 'documentation'
20
30
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acts_as_priceable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-04-04 00:00:00.000000000 Z
12
+ date: 2013-04-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -60,7 +60,23 @@ dependencies:
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  - !ruby/object:Gem::Dependency
63
- name: sqlite3
63
+ name: pg
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: activerecord-postgres-hstore
64
80
  requirement: !ruby/object:Gem::Requirement
65
81
  none: false
66
82
  requirements:
@@ -95,6 +111,7 @@ files:
95
111
  - spec/base_spec.rb
96
112
  - spec/database.yml
97
113
  - spec/models/dummy.rb
114
+ - spec/models/dummy_serialize.rb
98
115
  - spec/schema_spec.rb
99
116
  - spec/spec_helper.rb
100
117
  homepage: ''
@@ -111,7 +128,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
111
128
  version: '0'
112
129
  segments:
113
130
  - 0
114
- hash: 415468810773993444
131
+ hash: -81614923785070028
115
132
  required_rubygems_version: !ruby/object:Gem::Requirement
116
133
  none: false
117
134
  requirements:
@@ -120,7 +137,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
120
137
  version: '0'
121
138
  segments:
122
139
  - 0
123
- hash: 415468810773993444
140
+ hash: -81614923785070028
124
141
  requirements: []
125
142
  rubyforge_project:
126
143
  rubygems_version: 1.8.25
@@ -131,5 +148,6 @@ test_files:
131
148
  - spec/base_spec.rb
132
149
  - spec/database.yml
133
150
  - spec/models/dummy.rb
151
+ - spec/models/dummy_serialize.rb
134
152
  - spec/schema_spec.rb
135
153
  - spec/spec_helper.rb