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 +11 -0
- data/VERSION +1 -1
- data/lib/ohm/contrib/typecast.rb +48 -0
- data/lib/ohm/contrib.rb +2 -1
- data/ohm-contrib.gemspec +4 -1
- data/test/test_ohm_contrib.rb +6 -1
- data/test/test_ohm_typecast.rb +159 -0
- metadata +5 -2
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.
|
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.
|
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.
|
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
|
|
data/test/test_ohm_contrib.rb
CHANGED
@@ -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
|
-
-
|
9
|
-
version: 0.0.
|
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
|