ohm-contrib 0.0.2 → 0.0.3

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.markdown CHANGED
@@ -48,6 +48,17 @@ Example usage
48
48
  Post.create.created_at
49
49
  Post.create.updated_at
50
50
 
51
+ # Casting example
52
+ class Product
53
+ include Ohm::Typecast
54
+
55
+ attribute :price, :decimal
56
+ attribute :start_of_sale, :time
57
+ attribute :end_of_sale, :time
58
+ attribute :priority, :integer
59
+ attribute :rating, :float
60
+ end
61
+
51
62
  Credits
52
63
  -------
53
64
  Thanks to github user gnrfan for the web validations.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.2
1
+ 0.0.3
@@ -0,0 +1,48 @@
1
+ require 'bigdecimal'
2
+ require 'time'
3
+ require 'date'
4
+
5
+ module Ohm
6
+ module Typecast
7
+ def self.included(base)
8
+ base.extend Macros
9
+ end
10
+
11
+ module Macros
12
+ def attribute(name, type = :string)
13
+ define_method(name) do
14
+ typecast(read_local(name), type)
15
+ end
16
+
17
+ define_method(:"#{name}=") do |value|
18
+ write_local(name, value && value.to_s)
19
+ end
20
+
21
+ attributes << name unless attributes.include?(name)
22
+ end
23
+ end
24
+
25
+ protected
26
+ def typecast(val, type)
27
+ return val if val.to_s.empty?
28
+
29
+ case type
30
+ when :integer then Integer(val)
31
+ when :float then Float(val)
32
+ when :decimal then BigDecimal(val)
33
+ when :time
34
+ ret = Time.parse(val)
35
+ ret.to_s == val ? ret : val
36
+
37
+ when :date then Date.parse(val)
38
+ when :string then val
39
+ end
40
+
41
+ # All of the casting methods used above raises an ArgumentError
42
+ # if it fails to parse the value properly. If this happens,
43
+ # the least surprising behavior is to return the original value
44
+ rescue ArgumentError
45
+ val
46
+ end
47
+ end
48
+ end
data/lib/ohm/contrib.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  module Ohm
2
2
  module Contrib
3
- VERSION = '0.0.1'
3
+ VERSION = '0.0.3'
4
4
  end
5
5
 
6
6
  autoload :Boundaries, "ohm/contrib/boundaries"
@@ -8,4 +8,5 @@ module Ohm
8
8
  autoload :ToHash, "ohm/contrib/to_hash"
9
9
  autoload :WebValidations, "ohm/contrib/web_validations"
10
10
  autoload :NumberValidations, "ohm/contrib/number_validations"
11
+ autoload :Typecast, "ohm/contrib/typecast"
11
12
  end
data/ohm-contrib.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ohm-contrib}
8
- s.version = "0.0.2"
8
+ s.version = "0.0.3"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Cyril David"]
@@ -28,6 +28,7 @@ Gem::Specification.new do |s|
28
28
  "lib/ohm/contrib/number_validations.rb",
29
29
  "lib/ohm/contrib/timestamping.rb",
30
30
  "lib/ohm/contrib/to_hash.rb",
31
+ "lib/ohm/contrib/typecast.rb",
31
32
  "lib/ohm/contrib/web_validations.rb",
32
33
  "ohm-contrib.gemspec",
33
34
  "test/helper.rb",
@@ -36,6 +37,7 @@ Gem::Specification.new do |s|
36
37
  "test/test_ohm_number_validations.rb",
37
38
  "test/test_ohm_timestamping.rb",
38
39
  "test/test_ohm_to_hash.rb",
40
+ "test/test_ohm_typecast.rb",
39
41
  "test/test_ohm_web_validations.rb"
40
42
  ]
41
43
  s.homepage = %q{http://github.com/sinefunc/ohm-contrib}
@@ -50,6 +52,7 @@ Gem::Specification.new do |s|
50
52
  "test/test_ohm_number_validations.rb",
51
53
  "test/test_ohm_timestamping.rb",
52
54
  "test/test_ohm_to_hash.rb",
55
+ "test/test_ohm_typecast.rb",
53
56
  "test/test_ohm_web_validations.rb"
54
57
  ]
55
58
 
@@ -30,5 +30,10 @@ class TestOhmContrib < Test::Unit::TestCase
30
30
  Ohm::NumberValidations
31
31
  end
32
32
  end
33
-
33
+
34
+ test "autoloading of Typecast" do
35
+ assert_nothing_raised NameError, LoadError do
36
+ Ohm::Typecast
37
+ end
38
+ end
34
39
  end
@@ -0,0 +1,159 @@
1
+ require "helper"
2
+
3
+ class TestOhmTypecast < Test::Unit::TestCase
4
+ context "decimal typecasting" do
5
+ class Product < Ohm::Model
6
+ include Ohm::Typecast
7
+
8
+ attribute :price, :decimal
9
+ end
10
+
11
+ should "properly preserve the right precision" do
12
+ product = Product.create(:price => 0.0001)
13
+ product = Product[product.id]
14
+ sum = 0
15
+ 1_000.times { sum += product.price }
16
+
17
+ assert_equal 0.1, sum
18
+ end
19
+ end
20
+
21
+ context "time typecasting" do
22
+ class Product < Ohm::Model
23
+ include Ohm::Typecast
24
+
25
+ attribute :start_of_sale, :time
26
+ end
27
+
28
+ test "read / write" do
29
+ @time = Time.now.utc
30
+ product = Product.create(:start_of_sale => @time)
31
+ product = Product[product.id]
32
+
33
+ assert_equal @time, product.start_of_sale
34
+ end
35
+
36
+ test "the retrieved value is a Time object" do
37
+ @time = Time.now.utc
38
+ product = Product.create(:start_of_sale => @time)
39
+ product = Product[product.id]
40
+
41
+ assert_instance_of Time, product.start_of_sale
42
+ end
43
+
44
+ test "an invalid string" do
45
+ product = Product.create(:start_of_sale => "invalid time")
46
+ product = Product[product.id]
47
+
48
+ assert_equal "invalid time", product.start_of_sale
49
+ end
50
+
51
+ test "when nil" do
52
+ product = Product.new(:start_of_sale => nil)
53
+ assert_nil product.start_of_sale
54
+ end
55
+
56
+ test "when empty string" do
57
+ product = Product.new(:start_of_sale => "")
58
+ assert_equal "", product.start_of_sale
59
+ end
60
+ end
61
+
62
+ context "date typecasting" do
63
+ class Product < Ohm::Model
64
+ include Ohm::Typecast
65
+
66
+ attribute :date_bought, :date
67
+ end
68
+
69
+ test "read / write" do
70
+ @date = Date.today
71
+ product = Product.create(:date_bought => @date)
72
+ product = Product[product.id]
73
+
74
+ assert_equal @date, product.date_bought
75
+ end
76
+
77
+ test "the retrieved value is a Date object" do
78
+ @date = Date.today
79
+ product = Product.create(:date_bought => @date)
80
+ product = Product[product.id]
81
+
82
+ assert_instance_of Date, product.date_bought
83
+ end
84
+
85
+ test "assigning a string which is not a valid date before persisting" do
86
+ product = Product.create(:date_bought => "Bla Bla")
87
+
88
+ assert_equal "Bla Bla", product.date_bought
89
+ end
90
+
91
+ test "when nil" do
92
+ assert_nil Product.new.date_bought
93
+ end
94
+
95
+ test "empty string" do
96
+ assert_equal "", Product.new(:date_bought => "").date_bought
97
+ end
98
+ end
99
+
100
+ context "integer typecasting" do
101
+ class Product < Ohm::Model
102
+ include Ohm::Typecast
103
+
104
+ attribute :stock_count, :integer
105
+ end
106
+
107
+ test "when nil" do
108
+ assert_nil Product.new(:stock_count => nil).stock_count
109
+ end
110
+
111
+ test "when empty string" do
112
+ assert_equal "", Product.new(:stock_count => "").stock_count
113
+ end
114
+
115
+ test "when unparseable" do
116
+ assert_equal "FooBar", Product.new(:stock_count => "FooBar").stock_count
117
+ end
118
+
119
+ test "when a float" do
120
+ assert_equal '1.0', Product.new(:stock_count => "1.0").stock_count
121
+ end
122
+
123
+ test "when a real int" do
124
+ assert_equal 1, Product.new(:stock_count => '1').stock_count
125
+ end
126
+ end
127
+
128
+ context "float typecasting" do
129
+ class Product < Ohm::Model
130
+ include Ohm::Typecast
131
+
132
+ attribute :vat, :float
133
+ end
134
+
135
+ test "when nil" do
136
+ assert_nil Product.new(:vat => nil).vat
137
+ end
138
+
139
+ test "when empty string" do
140
+ assert_equal "", Product.new(:vat => "").vat
141
+ end
142
+
143
+ test "when unparseable" do
144
+ assert_equal "FooBar", Product.new(:vat => "FooBar").vat
145
+ end
146
+
147
+ test "when a float" do
148
+ assert_equal 1.0, Product.new(:vat => "1.0").vat
149
+ end
150
+
151
+ test "when an int" do
152
+ assert_equal 1.0, Product.new(:vat => '1').vat
153
+ end
154
+
155
+ test "when a .12 value" do
156
+ assert_equal 0.12, Product.new(:vat => ".12").vat
157
+ end
158
+ end
159
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 2
9
- version: 0.0.2
8
+ - 3
9
+ version: 0.0.3
10
10
  platform: ruby
11
11
  authors:
12
12
  - Cyril David
@@ -86,6 +86,7 @@ files:
86
86
  - lib/ohm/contrib/number_validations.rb
87
87
  - lib/ohm/contrib/timestamping.rb
88
88
  - lib/ohm/contrib/to_hash.rb
89
+ - lib/ohm/contrib/typecast.rb
89
90
  - lib/ohm/contrib/web_validations.rb
90
91
  - ohm-contrib.gemspec
91
92
  - test/helper.rb
@@ -94,6 +95,7 @@ files:
94
95
  - test/test_ohm_number_validations.rb
95
96
  - test/test_ohm_timestamping.rb
96
97
  - test/test_ohm_to_hash.rb
98
+ - test/test_ohm_typecast.rb
97
99
  - test/test_ohm_web_validations.rb
98
100
  has_rdoc: true
99
101
  homepage: http://github.com/sinefunc/ohm-contrib
@@ -132,4 +134,5 @@ test_files:
132
134
  - test/test_ohm_number_validations.rb
133
135
  - test/test_ohm_timestamping.rb
134
136
  - test/test_ohm_to_hash.rb
137
+ - test/test_ohm_typecast.rb
135
138
  - test/test_ohm_web_validations.rb