ohm-contrib 0.0.31 → 0.0.33
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +2 -1
- data/README.markdown +2 -1
- data/Rakefile +4 -53
- data/lib/ohm/contrib.rb +2 -2
- data/lib/ohm/contrib/boundaries.rb +1 -0
- data/lib/ohm/contrib/callbacks.rb +5 -4
- data/lib/ohm/contrib/date_validations.rb +2 -1
- data/lib/ohm/contrib/extra_validations.rb +1 -0
- data/lib/ohm/contrib/length_validations.rb +1 -0
- data/lib/ohm/contrib/locking.rb +2 -1
- data/lib/ohm/contrib/lunar_macros.rb +5 -4
- data/lib/ohm/contrib/number_validations.rb +1 -0
- data/lib/ohm/contrib/slug.rb +1 -0
- data/lib/ohm/contrib/timestamping.rb +1 -0
- data/lib/ohm/contrib/typecast.rb +1 -0
- data/lib/ohm/contrib/web_validations.rb +2 -1
- data/test/autoload_test.rb +19 -0
- data/test/boundaries_test.rb +45 -0
- data/test/callbacks_lint.rb +105 -0
- data/test/date_validations_test.rb +29 -0
- data/test/helper.rb +19 -10
- data/test/instance_callbacks_test.rb +45 -0
- data/test/length_validations_test.rb +31 -0
- data/test/lunar_macros_test.rb +146 -0
- data/test/macro_callbacks_test.rb +57 -0
- data/test/membership_validation_test.rb +31 -0
- data/test/number_validations_test.rb +37 -0
- data/test/slug_test.rb +30 -0
- data/test/timestamping_test.rb +32 -0
- data/test/typecast_array_test.rb +154 -0
- data/test/typecast_boolean_test.rb +43 -0
- data/test/typecast_date_test.rb +77 -0
- data/test/typecast_decimal_test.rb +77 -0
- data/test/typecast_float_test.rb +52 -0
- data/test/typecast_hash_test.rb +117 -0
- data/test/typecast_integer_test.rb +66 -0
- data/test/typecast_string_test.rb +38 -0
- data/test/typecast_time_test.rb +67 -0
- data/test/typecast_timezone_test.rb +37 -0
- data/test/web_validations_test.rb +79 -0
- metadata +47 -56
- data/.document +0 -5
- data/.gitignore +0 -25
- data/VERSION +0 -1
- data/lib/ohm/contrib/to_hash.rb +0 -39
- data/ohm-contrib.gemspec +0 -103
- data/test/test_ohm_boundaries.rb +0 -74
- data/test/test_ohm_contrib.rb +0 -70
- data/test/test_ohm_contrib_callbacks.rb +0 -375
- data/test/test_ohm_date_validations.rb +0 -30
- data/test/test_ohm_extra_validations.rb +0 -32
- data/test/test_ohm_length_validations.rb +0 -32
- data/test/test_ohm_lunar_macros.rb +0 -165
- data/test/test_ohm_number_validations.rb +0 -59
- data/test/test_ohm_slug.rb +0 -29
- data/test/test_ohm_timestamping.rb +0 -64
- data/test/test_ohm_to_hash.rb +0 -67
- data/test/test_ohm_typecast.rb +0 -707
- data/test/test_ohm_web_validations.rb +0 -114
data/test/helper.rb
CHANGED
@@ -1,16 +1,25 @@
|
|
1
|
-
require '
|
2
|
-
require 'test/unit'
|
3
|
-
require 'contest'
|
1
|
+
require 'cutest'
|
4
2
|
require 'redis'
|
5
3
|
require 'ohm'
|
6
|
-
require '
|
7
|
-
require '
|
4
|
+
require 'ohm/contrib'
|
5
|
+
require 'override'
|
8
6
|
|
9
|
-
Ohm.connect :host => "localhost", :port =>
|
7
|
+
Ohm.connect :host => "localhost", :port => 6379, :db => 1
|
10
8
|
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
NOW = Time.utc(2010, 5, 12)
|
10
|
+
|
11
|
+
include Override
|
14
12
|
|
15
|
-
|
13
|
+
prepare {
|
14
|
+
Ohm.flush
|
15
|
+
override(Time, :now => NOW)
|
16
|
+
}
|
17
|
+
|
18
|
+
def assert_nothing_raised(*exceptions)
|
19
|
+
begin
|
20
|
+
yield
|
21
|
+
rescue *exceptions
|
22
|
+
flunk(caller[1])
|
23
|
+
end
|
16
24
|
end
|
25
|
+
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path("./helper", File.dirname(__FILE__))
|
4
|
+
|
5
|
+
class Post < Ohm::Model
|
6
|
+
include Ohm::Callbacks
|
7
|
+
|
8
|
+
attribute :body
|
9
|
+
|
10
|
+
def validate
|
11
|
+
super
|
12
|
+
|
13
|
+
assert_present :body
|
14
|
+
end
|
15
|
+
|
16
|
+
def did?(action)
|
17
|
+
instance_variable_get("@#{ action }")
|
18
|
+
end
|
19
|
+
|
20
|
+
def count(action)
|
21
|
+
instance_variable_get("@#{ action }")
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
def before_validate() incr(:do_before_validate) end
|
26
|
+
def after_validate() incr(:do_after_validate) end
|
27
|
+
def before_create() incr(:do_before_create) end
|
28
|
+
def after_create() incr(:do_after_create) end
|
29
|
+
def before_save() incr(:do_before_save) end
|
30
|
+
def after_save() incr(:do_after_save) end
|
31
|
+
def before_delete() incr(:do_before_delete) end
|
32
|
+
def after_delete() incr(:do_after_delete) end
|
33
|
+
|
34
|
+
|
35
|
+
def incr(action)
|
36
|
+
val = instance_variable_get("@#{ action }")
|
37
|
+
val ||= 0
|
38
|
+
val += 1
|
39
|
+
|
40
|
+
instance_variable_set("@#{ action }", val)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
load File.expand_path('./callbacks_lint.rb', File.dirname(__FILE__))
|
45
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path("./helper", File.dirname(__FILE__))
|
4
|
+
|
5
|
+
class Person < Ohm::Model
|
6
|
+
include Ohm::LengthValidations
|
7
|
+
|
8
|
+
attribute :name
|
9
|
+
|
10
|
+
def validate
|
11
|
+
assert_min_length :name, 5
|
12
|
+
assert_max_length :name, 10
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
test "valid length name" do
|
17
|
+
assert Person.new(:name => "bob smith").valid?
|
18
|
+
end
|
19
|
+
|
20
|
+
test "also catches short strings" do
|
21
|
+
assert ! Person.new(:name => "bob").valid?
|
22
|
+
end
|
23
|
+
|
24
|
+
test "also catches long strings" do
|
25
|
+
assert ! Person.new(:name => "robert smithson").valid?
|
26
|
+
end
|
27
|
+
|
28
|
+
test "invalid when empty" do
|
29
|
+
assert ! Person.new(:name => "").valid?
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,146 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path("./helper", File.dirname(__FILE__))
|
4
|
+
|
5
|
+
class Post < Ohm::Model
|
6
|
+
include Ohm::LunarMacros
|
7
|
+
end
|
8
|
+
|
9
|
+
test "fuzzy / text / number / sortable" do
|
10
|
+
Post.fuzzy :name
|
11
|
+
assert [:name] == Post.fuzzy
|
12
|
+
|
13
|
+
Post.text :name
|
14
|
+
assert [:name] == Post.text
|
15
|
+
|
16
|
+
Post.number :name
|
17
|
+
assert [:name] == Post.number
|
18
|
+
|
19
|
+
Post.sortable :name
|
20
|
+
assert [:name] == Post.sortable
|
21
|
+
end
|
22
|
+
|
23
|
+
test "fuzzy / text / number / sortable done twice" do
|
24
|
+
Post.fuzzy :name
|
25
|
+
Post.fuzzy :name
|
26
|
+
assert [:name] == Post.fuzzy
|
27
|
+
|
28
|
+
Post.text :name
|
29
|
+
Post.text :name
|
30
|
+
assert [:name] == Post.text
|
31
|
+
|
32
|
+
Post.number :name
|
33
|
+
Post.number :name
|
34
|
+
assert [:name] == Post.number
|
35
|
+
|
36
|
+
Post.sortable :name
|
37
|
+
Post.sortable :name
|
38
|
+
assert [:name] == Post.sortable
|
39
|
+
end
|
40
|
+
|
41
|
+
class Document < Ohm::Model
|
42
|
+
include Ohm::LunarMacros
|
43
|
+
|
44
|
+
fuzzy :filename
|
45
|
+
text :content
|
46
|
+
number :author_id
|
47
|
+
sortable :views
|
48
|
+
|
49
|
+
attribute :filename
|
50
|
+
attribute :content
|
51
|
+
attribute :author_id
|
52
|
+
attribute :views
|
53
|
+
end
|
54
|
+
|
55
|
+
test "fuzzy indexing" do
|
56
|
+
doc = Document.create(:filename => "amazing.mp3")
|
57
|
+
|
58
|
+
strs = %w{a am ama amaz amazi amazin amazing amazing. amazing.m
|
59
|
+
amazing.mp amazing.mp3}
|
60
|
+
|
61
|
+
strs.each do |str|
|
62
|
+
r = Lunar.search(Document, :fuzzy => { :filename => str })
|
63
|
+
assert r.include?(doc)
|
64
|
+
end
|
65
|
+
|
66
|
+
doc.update(:filename => "crazy.mp3")
|
67
|
+
|
68
|
+
strs = %w{c cr cra craz crazy crazy. crazy.m crazy.mp crazy.mp3}
|
69
|
+
|
70
|
+
strs.each do |str|
|
71
|
+
r = Lunar.search(Document, :fuzzy => { :filename => str })
|
72
|
+
assert r.include?(doc)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
test "text indexing" do
|
77
|
+
doc = Document.create(:content => "The quick brown fox")
|
78
|
+
|
79
|
+
queries = ['quick', 'brown', 'fox', 'quick brown' 'quick fox', 'fox brown',
|
80
|
+
'the quick brown fox']
|
81
|
+
|
82
|
+
queries.each do |q|
|
83
|
+
r = Lunar.search(Document, :q => q)
|
84
|
+
assert r.include?(doc)
|
85
|
+
end
|
86
|
+
|
87
|
+
doc.update(:content => "lazy dog jumps over")
|
88
|
+
|
89
|
+
queries = ['lazy', 'dog', 'jumps', 'over', 'lazy dog', 'jumps over']
|
90
|
+
|
91
|
+
queries.each do |q|
|
92
|
+
r = Lunar.search(Document, :q => q)
|
93
|
+
assert r.include?(doc)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
test "number indexing" do
|
98
|
+
doc = Document.create(:author_id => 99)
|
99
|
+
|
100
|
+
[99..100, 98..99, 98..100].each do |range|
|
101
|
+
r = Lunar.search(Document, :author_id => range)
|
102
|
+
assert r.include?(doc)
|
103
|
+
end
|
104
|
+
|
105
|
+
[97..98, 100..101].each do |range|
|
106
|
+
r = Lunar.search(Document, :author_id => range)
|
107
|
+
assert ! r.include?(doc)
|
108
|
+
end
|
109
|
+
|
110
|
+
doc.update(:author_id => 49)
|
111
|
+
|
112
|
+
[49..50, 48..49, 48..50].each do |range|
|
113
|
+
r = Lunar.search(Document, :author_id => range)
|
114
|
+
assert r.include?(doc)
|
115
|
+
end
|
116
|
+
|
117
|
+
[47..48, 50..51].each do |range|
|
118
|
+
r = Lunar.search(Document, :author_id => range)
|
119
|
+
assert ! r.include?(doc)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
test "sortable indexing" do
|
124
|
+
osx = Document.create(:content => "apple mac osx", :views => 500)
|
125
|
+
iphone = Document.create(:content => "apple iphone", :views => 10_000)
|
126
|
+
|
127
|
+
assert [iphone, osx] == Lunar.search(Document, :q => "apple").sort_by(:views, :order => "DESC")
|
128
|
+
assert [osx, iphone] == Lunar.search(Document, :q => "apple").sort_by(:views, :order => "ASC")
|
129
|
+
|
130
|
+
osx.update(:content => "ios mac osx", :views => 1000)
|
131
|
+
iphone.update(:content => "ios iphone", :views => 500)
|
132
|
+
|
133
|
+
assert [osx, iphone] == Lunar.search(Document, :q => "ios").sort_by(:views, :order => "DESC")
|
134
|
+
assert [iphone, osx] == Lunar.search(Document, :q => "ios").sort_by(:views, :order => "ASC")
|
135
|
+
end
|
136
|
+
|
137
|
+
test "on delete" do
|
138
|
+
doc = Document.create(:filename => "amazing.mp3", :content => "apple mac osx",
|
139
|
+
:author_id => 99, :views => 500)
|
140
|
+
|
141
|
+
doc.delete
|
142
|
+
|
143
|
+
assert Lunar.search(Document, :q => "apple").size.zero?
|
144
|
+
assert Lunar.search(Document, :fuzzy => { :filename => "amazing" }).size.zero?
|
145
|
+
end
|
146
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path("./helper", File.dirname(__FILE__))
|
4
|
+
|
5
|
+
class Post < Ohm::Model
|
6
|
+
include Ohm::Callbacks
|
7
|
+
|
8
|
+
attribute :body
|
9
|
+
|
10
|
+
before :validate, :do_before_validate
|
11
|
+
after :validate, :do_after_validate
|
12
|
+
|
13
|
+
before :create, :do_before_create
|
14
|
+
after :create, :do_after_create
|
15
|
+
|
16
|
+
before :save, :do_before_save
|
17
|
+
after :save, :do_after_save
|
18
|
+
|
19
|
+
before :delete, :do_before_delete
|
20
|
+
after :delete, :do_after_delete
|
21
|
+
|
22
|
+
def validate
|
23
|
+
super
|
24
|
+
|
25
|
+
assert_present :body
|
26
|
+
end
|
27
|
+
|
28
|
+
def did?(action)
|
29
|
+
instance_variable_get("@#{ action }")
|
30
|
+
end
|
31
|
+
|
32
|
+
def count(action)
|
33
|
+
instance_variable_get("@#{ action }")
|
34
|
+
end
|
35
|
+
|
36
|
+
protected
|
37
|
+
def do_before_validate() incr(:do_before_validate) end
|
38
|
+
def do_after_validate() incr(:do_after_validate) end
|
39
|
+
def do_before_create() incr(:do_before_create) end
|
40
|
+
def do_after_create() incr(:do_after_create) end
|
41
|
+
def do_before_save() incr(:do_before_save) end
|
42
|
+
def do_after_save() incr(:do_after_save) end
|
43
|
+
def do_before_delete() incr(:do_before_delete) end
|
44
|
+
def do_after_delete() incr(:do_after_delete) end
|
45
|
+
|
46
|
+
|
47
|
+
def incr(action)
|
48
|
+
val = instance_variable_get("@#{ action }")
|
49
|
+
val ||= 0
|
50
|
+
val += 1
|
51
|
+
|
52
|
+
instance_variable_set("@#{ action }", val)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
load File.expand_path('./callbacks_lint.rb', File.dirname(__FILE__))
|
57
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path("./helper", File.dirname(__FILE__))
|
4
|
+
|
5
|
+
class Order < Ohm::Model
|
6
|
+
include Ohm::ExtraValidations
|
7
|
+
|
8
|
+
attribute :state
|
9
|
+
|
10
|
+
def validate
|
11
|
+
assert_member :state, %w(pending authorized declined)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
test "validates for all members" do
|
16
|
+
order = Order.new(:state => 'pending')
|
17
|
+
assert order.valid?
|
18
|
+
|
19
|
+
order = Order.new(:state => 'authorized')
|
20
|
+
assert order.valid?
|
21
|
+
|
22
|
+
order = Order.new(:state => 'declined')
|
23
|
+
assert order.valid?
|
24
|
+
end
|
25
|
+
|
26
|
+
test "fails on a non-member" do
|
27
|
+
order = Order.new(:state => 'foobar')
|
28
|
+
assert ! order.valid?
|
29
|
+
assert [[:state, :not_member]] == order.errors
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path("./helper", File.dirname(__FILE__))
|
4
|
+
|
5
|
+
class Product < Ohm::Model
|
6
|
+
include Ohm::NumberValidations
|
7
|
+
|
8
|
+
attribute :price
|
9
|
+
attribute :optional_price
|
10
|
+
|
11
|
+
def validate
|
12
|
+
assert_decimal :price
|
13
|
+
assert_decimal :optional_price unless optional_price.to_s.empty?
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
test "has error when empty" do
|
18
|
+
product = Product.new(:price => nil)
|
19
|
+
product.valid?
|
20
|
+
|
21
|
+
assert [[:price, :not_decimal]] == product.errors
|
22
|
+
end
|
23
|
+
|
24
|
+
test "validation scenarios" do
|
25
|
+
assert Product.new(:price => 0.10).valid?
|
26
|
+
assert Product.new(:price => 1).valid?
|
27
|
+
|
28
|
+
p = Product.new(:price => '1.')
|
29
|
+
assert ! p.valid?
|
30
|
+
assert [[:price, :not_decimal]] == p.errors
|
31
|
+
end
|
32
|
+
|
33
|
+
test "allows empty values through basic ruby conditions" do
|
34
|
+
assert Product.new(:price => 10.1, :optional_price => nil).valid?
|
35
|
+
assert Product.new(:price => 10.1, :optional_price => '').valid?
|
36
|
+
end
|
37
|
+
|
data/test/slug_test.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path("./helper", File.dirname(__FILE__))
|
4
|
+
|
5
|
+
module Finder
|
6
|
+
def [](id)
|
7
|
+
new(id)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class BaseWithoutToParam < Struct.new(:id)
|
12
|
+
extend Finder
|
13
|
+
|
14
|
+
include Ohm::Slug
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
"A very Unique and Interesting String?'"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
test "to_param" do
|
22
|
+
obj = BaseWithoutToParam.new(1)
|
23
|
+
|
24
|
+
assert '1-a-very-unique-and-interesting-string' == obj.to_param
|
25
|
+
end
|
26
|
+
|
27
|
+
test "finding" do
|
28
|
+
assert 1 == BaseWithoutToParam['1-a-very-unique'].id
|
29
|
+
end
|
30
|
+
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path("./helper", File.dirname(__FILE__))
|
4
|
+
|
5
|
+
class Person < Ohm::Model
|
6
|
+
include Ohm::Timestamping
|
7
|
+
end
|
8
|
+
|
9
|
+
test "a new? record" do
|
10
|
+
assert nil == Person.new.created_at
|
11
|
+
assert nil == Person.new.updated_at
|
12
|
+
end
|
13
|
+
|
14
|
+
test "on create" do
|
15
|
+
person = Person.create
|
16
|
+
person = Person[person.id]
|
17
|
+
|
18
|
+
assert NOW.to_s == person.created_at
|
19
|
+
assert NOW.to_s == person.updated_at
|
20
|
+
end
|
21
|
+
|
22
|
+
test "on update" do
|
23
|
+
person = Person.create
|
24
|
+
|
25
|
+
override(Time, :now => Time.utc(2010, 5, 13))
|
26
|
+
person.save
|
27
|
+
person = Person[person.id]
|
28
|
+
|
29
|
+
assert NOW.to_s == person.created_at
|
30
|
+
assert Time.utc(2010, 5, 13).to_s == person.updated_at
|
31
|
+
end
|
32
|
+
|