acts_as_priceable 0.2.0 → 0.2.1

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