remodel-h-r19 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
data/test/helper.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ require File.dirname(__FILE__) + '/../lib/remodel-h.rb'
6
+
7
+ class Test::Unit::TestCase
8
+
9
+ def redis
10
+ Remodel.redis
11
+ end
12
+
13
+ end
@@ -0,0 +1,297 @@
1
+ require 'helper'
2
+
3
+ class Foo < Remodel::Entity
4
+ property :x
5
+ property :y
6
+ end
7
+
8
+ class Bar < Remodel::Entity
9
+ property :d, :default => 123
10
+ end
11
+
12
+ class TestEntity < Test::Unit::TestCase
13
+
14
+ context "new" do
15
+ should "set properties" do
16
+ foo = Foo.new('cx', :x => 1, :y => 2)
17
+ assert_equal 1, foo.x
18
+ assert_equal 2, foo.y
19
+ end
20
+
21
+ should "ignore undefined properties" do
22
+ foo = Foo.new('cx', :z => 3)
23
+ assert foo.instance_eval { !@attributes.key? :z }
24
+ end
25
+
26
+ should "not set the key" do
27
+ foo = Foo.new('cx', :x => 23)
28
+ assert_equal nil, foo.key
29
+ end
30
+
31
+ should "not set the id" do
32
+ foo = Foo.new('cx', :x => 23)
33
+ assert_equal nil, foo.id
34
+ end
35
+
36
+ should "use default values for missing properties" do
37
+ bar = Bar.new('cx')
38
+ assert_equal 123, bar.d
39
+ end
40
+
41
+ should "not use default values for given properties" do
42
+ bar = Bar.new('cx', :d => 'cool')
43
+ assert_equal 'cool', bar.d
44
+ end
45
+ end
46
+
47
+ context "create" do
48
+ setup do
49
+ redis.flushdb
50
+ end
51
+
52
+ should "work without attributes" do
53
+ foo = Foo.create('cx')
54
+ assert foo.is_a?(Foo)
55
+ end
56
+
57
+ should "give the entity a key based on the class name" do
58
+ assert_equal 'f1', Foo.create('cx').key
59
+ assert_equal 'b1', Bar.create('cx').key
60
+ assert_equal 'b2', Bar.create('cx').key
61
+ end
62
+
63
+ should "give the entity an id which is unique per entity class" do
64
+ assert_equal 1, Foo.create('cx').id
65
+ assert_equal 1, Bar.create('cx').id
66
+ assert_equal 2, Bar.create('cx').id
67
+ end
68
+
69
+ should "store the entity under its key" do
70
+ foo = Foo.create('cx', :x => 'hello', :y => false)
71
+ assert redis.hexists('cx', foo.key)
72
+ end
73
+
74
+ should "store all properties" do
75
+ foo = Foo.create('cx', :x => 'hello', :y => false)
76
+ foo.reload
77
+ assert_equal 'hello', foo.x
78
+ assert_equal false, foo.y
79
+ end
80
+
81
+ should "not store the key as a property" do
82
+ foo = Foo.create('cx', :x => 'hello', :y => false)
83
+ assert !(/f:1/ =~ redis.hget('cx', foo.key))
84
+ end
85
+
86
+ should "use default values for missing properties" do
87
+ bar = Bar.create('cx')
88
+ assert_equal 123, bar.d
89
+ end
90
+
91
+ should "not use default values for given properties" do
92
+ bar = Bar.create('cx', :d => 'cool')
93
+ assert_equal 'cool', bar.d
94
+ end
95
+ end
96
+
97
+ context "save" do
98
+ setup do
99
+ redis.flushdb
100
+ end
101
+
102
+ should "give the entity a key, if necessary" do
103
+ foo = Foo.new('cx').save
104
+ assert foo.key
105
+ end
106
+
107
+ should "store the entity under its key" do
108
+ foo = Foo.new('cx', :x => 'hello', :y => false)
109
+ foo.save
110
+ assert redis.hexists(foo.context, foo.key)
111
+ end
112
+
113
+ should "store all properties" do
114
+ foo = Foo.new('cx', :x => 'hello', :y => false)
115
+ foo.save
116
+ foo.reload
117
+ assert_equal 'hello', foo.x
118
+ assert_equal false, foo.y
119
+ end
120
+ end
121
+
122
+ context "reload" do
123
+ setup do
124
+ @foo = Foo.create('cx', :x => 'hello', :y => true)
125
+ end
126
+
127
+ should "reload all properties" do
128
+ redis.hset @foo.context, @foo.key, %q({"x":23,"y":"adios"})
129
+ @foo.reload
130
+ assert_equal 23, @foo.x
131
+ assert_equal 'adios', @foo.y
132
+ end
133
+
134
+ should "keep the key" do
135
+ key = @foo.key
136
+ @foo.reload
137
+ assert_equal key, @foo.key
138
+ end
139
+
140
+ should "stay the same object" do
141
+ id = @foo.object_id
142
+ @foo.reload
143
+ assert_equal id, @foo.object_id
144
+ end
145
+
146
+ should "raise EntityNotFound if the entity does not exist any more" do
147
+ redis.hdel @foo.context, @foo.key
148
+ assert_raise(Remodel::EntityNotFound) { @foo.reload }
149
+ end
150
+
151
+ should "raise EntityNotSaved if the entity was never saved" do
152
+ assert_raise(Remodel::EntityNotSaved) { Foo.new('cx').reload }
153
+ end
154
+ end
155
+
156
+ context "update" do
157
+ setup do
158
+ redis.flushdb
159
+ @foo = Foo.create('cx', :x => 'Tim', :y => true)
160
+ end
161
+
162
+ should "set the given properties" do
163
+ @foo.update(:x => 12, :y => 'Jan')
164
+ assert_equal 12, @foo.x
165
+ assert_equal 'Jan', @foo.y
166
+ end
167
+
168
+ should "save the entity" do
169
+ @foo.update(:x => 12, :y => 'Jan')
170
+ @foo.reload
171
+ assert_equal 12, @foo.x
172
+ assert_equal 'Jan', @foo.y
173
+ end
174
+ end
175
+
176
+ context "to_json" do
177
+ should "serialize to json" do
178
+ foo = Foo.new('cx', :x => 42, :y => true)
179
+ assert_match /"x":42/, foo.to_json
180
+ assert_match /"y":true/, foo.to_json
181
+ end
182
+ end
183
+
184
+ context "as_json" do
185
+ should "serialize into a hash" do
186
+ foo = Foo.create('cx', :x => 42, :y => true)
187
+ expected = { :id => foo.id, :x => 42, :y => true }
188
+ assert_equal expected, foo.as_json
189
+ end
190
+ end
191
+
192
+ context "#set_key_prefix" do
193
+ should "use the given key prefix" do
194
+ class Custom < Remodel::Entity; set_key_prefix 'my'; end
195
+ assert_match /^my\d+$/, Custom.create('cx').key
196
+ end
197
+
198
+ should "ensure that the prefix is letters only" do
199
+ assert_raise(Remodel::InvalidKeyPrefix) do
200
+ class InvalidPrefix < Remodel::Entity; set_key_prefix '666'; end
201
+ end
202
+ end
203
+ end
204
+
205
+ context "#find" do
206
+ setup do
207
+ redis.flushdb
208
+ @foo = Foo.create('cx', :x => 'hello', :y => 123)
209
+ Foo.create('cx', :x => 'hallo', :y => 124)
210
+ end
211
+
212
+ should "find and load an entity by key" do
213
+ foo = Foo.find(@foo.context, @foo.key)
214
+ assert_equal foo.x, @foo.x
215
+ assert_equal foo.y, @foo.y
216
+ end
217
+
218
+ should "find and load an entity by id" do
219
+ foo = Foo.find(@foo.context, @foo.id)
220
+ assert_equal foo.x, @foo.x
221
+ assert_equal foo.y, @foo.y
222
+ end
223
+
224
+ should "reject a key which does not exist" do
225
+ assert_raise(Remodel::EntityNotFound) { Foo.find('cx', 'x:66') }
226
+ end
227
+
228
+ should "reject an id which does not exist" do
229
+ assert_raise(Remodel::EntityNotFound) { Foo.find('cx', 66) }
230
+ end
231
+ end
232
+
233
+ context "properties" do
234
+ should "have property x" do
235
+ foo = Foo.new('cx')
236
+ foo.x = 23
237
+ assert_equal 23, foo.x
238
+ foo.x += 10
239
+ assert_equal 33, foo.x
240
+ end
241
+
242
+ should "not have property z" do
243
+ foo = Foo.new('cx')
244
+ assert_raise(NoMethodError) { foo.z }
245
+ assert_raise(NoMethodError) { foo.z = 42 }
246
+ end
247
+
248
+ context "types" do
249
+ should "work with nil" do
250
+ foo = Foo.create('cx', :x => nil)
251
+ assert_equal nil, foo.reload.x
252
+ end
253
+
254
+ should "work with booleans" do
255
+ foo = Foo.create('cx', :x => false)
256
+ assert_equal false, foo.reload.x
257
+ end
258
+
259
+ should "work with integers" do
260
+ foo = Foo.create('cx', :x => -42)
261
+ assert_equal -42, foo.reload.x
262
+ end
263
+
264
+ should "work with floats" do
265
+ foo = Foo.create('cx', :x => 3.141)
266
+ assert_equal 3.141, foo.reload.x
267
+ end
268
+
269
+ should "work with strings" do
270
+ foo = Foo.create('cx', :x => 'hello')
271
+ assert_equal 'hello', foo.reload.x
272
+ end
273
+
274
+ should "work with lists" do
275
+ foo = Foo.create('cx', :x => [1, 2, 3])
276
+ assert_equal [1, 2, 3], foo.reload.x
277
+ end
278
+
279
+ should "work with hashes" do
280
+ hash = { 'a' => 17, 'b' => 'test' }
281
+ foo = Foo.create('cx', :x => hash)
282
+ assert_equal hash, foo.reload.x
283
+ end
284
+ end
285
+ end
286
+
287
+ context "#restore" do
288
+ should "restore an entity from json" do
289
+ before = Foo.create('cx', :x => 42, :y => true)
290
+ after = Foo.restore(before.context, before.key, before.to_json)
291
+ assert_equal before.key, after.key
292
+ assert_equal before.x, after.x
293
+ assert_equal before.y, after.y
294
+ end
295
+ end
296
+
297
+ end
@@ -0,0 +1,45 @@
1
+ require 'helper'
2
+
3
+ class TestEntityDelete < Test::Unit::TestCase
4
+
5
+ class Group < Remodel::Entity
6
+ has_many :members, :class => 'TestEntityDelete::Person'
7
+ has_one :room, :class => 'TestEntityDelete::Room'
8
+ property :name
9
+ end
10
+
11
+ class Person < Remodel::Entity
12
+ property :name
13
+ end
14
+
15
+ class Room < Remodel::Entity
16
+ property :name
17
+ end
18
+
19
+ context "delete" do
20
+ setup do
21
+ redis.flushdb
22
+ @group = Group.create('cx', :name => 'ruby user group')
23
+ @group.members.create(:name => 'Tim')
24
+ @group.members.create(:name => 'Ben')
25
+ @group.room = Room.create(:name => 'some office')
26
+ end
27
+
28
+ should "ensure that the entity is persistent" do
29
+ assert_raise(Remodel::EntityNotSaved) { Group.new('cx').delete }
30
+ end
31
+
32
+ should "delete the given entity" do
33
+ @group.delete
34
+ assert_nil redis.hget(@group.context, @group.key)
35
+ end
36
+
37
+ should "delete any associations in redis" do
38
+ @group.delete
39
+ assert_nil redis.hget(@group.context, "#{@group.key}_members")
40
+ assert_nil redis.hget(@group.context, "#{@group.key}_room")
41
+ end
42
+
43
+ end
44
+
45
+ end
@@ -0,0 +1,77 @@
1
+ require 'helper'
2
+
3
+ class TestManyToMany < Test::Unit::TestCase
4
+
5
+ class Person < Remodel::Entity
6
+ has_many :groups, :class => 'TestManyToMany::Group', :reverse => 'members'
7
+ property :name
8
+ end
9
+
10
+ class Group < Remodel::Entity
11
+ has_many :members, :class => 'TestManyToMany::Person', :reverse => 'groups'
12
+ property :name
13
+ end
14
+
15
+ context "both associations" do
16
+ should "be empty by default" do
17
+ assert_equal [], Person.new('cx').groups
18
+ assert_equal [], Group.new('cx').members
19
+ end
20
+
21
+ context "create" do
22
+ should "add a new group to both associations" do
23
+ tim = Person.create('cx', :name => 'tim')
24
+ rugb = tim.groups.create :name => 'rug-b'
25
+ assert_equal [tim], rugb.members
26
+ end
27
+
28
+ should "add a new person to both associations" do
29
+ rugb = Group.create('cx', :name => 'rug-b')
30
+ tim = rugb.members.create :name => 'tim'
31
+ assert_equal [rugb], tim.groups
32
+ end
33
+ end
34
+
35
+ context "add" do
36
+ setup do
37
+ @tim = Person.create('cx', :name => 'tim')
38
+ @rugb = Group.create('cx', :name => 'rug-b')
39
+ end
40
+
41
+ should "add a new group to both associations" do
42
+ @tim.groups.add(@rugb)
43
+ assert_equal [@tim], @rugb.members
44
+ assert_equal [@rugb], @tim.groups
45
+ end
46
+
47
+ should "add a new person to both associations" do
48
+ @rugb.members.add(@tim)
49
+ assert_equal [@tim], @rugb.members
50
+ assert_equal [@rugb], @tim.groups
51
+ end
52
+ end
53
+
54
+ context "remove" do
55
+ setup do
56
+ @tim = Person.create('cx', :name => 'tim')
57
+ @rugb = @tim.groups.create(:name => 'rug-b')
58
+ @erlang = @tim.groups.create(:name => 'erlang')
59
+ @aws = @tim.groups.create(:name => 'aws')
60
+ end
61
+
62
+ should "remove a group from both associations" do
63
+ @tim.groups.remove(@erlang)
64
+ assert_equal [@rugb, @aws], @tim.groups
65
+ assert_equal [], @erlang.members
66
+ end
67
+
68
+ should "remove a person from both associations" do
69
+ @erlang.members.remove(@tim)
70
+ assert_equal [@rugb, @aws], @tim.groups
71
+ assert_equal [], @erlang.members
72
+ end
73
+
74
+ end
75
+ end
76
+
77
+ end
@@ -0,0 +1,107 @@
1
+ require 'helper'
2
+ require 'json'
3
+
4
+ class TestManyToOne < Test::Unit::TestCase
5
+
6
+ class Puzzle < Remodel::Entity
7
+ has_many :pieces, :class => 'TestManyToOne::Piece', :reverse => 'puzzle'
8
+ property :topic
9
+ end
10
+
11
+ class Piece < Remodel::Entity
12
+ has_one :puzzle, :class => 'TestManyToOne::Puzzle'
13
+ property :color
14
+ end
15
+
16
+ context "has_many" do
17
+ context "association" do
18
+ should "exist" do
19
+ assert Puzzle.create('cx').respond_to?(:pieces)
20
+ end
21
+
22
+ should "return an empty list by default" do
23
+ assert_equal [], Puzzle.create('cx').pieces
24
+ end
25
+
26
+ should "return any existing children" do
27
+ puzzle = Puzzle.create('cx')
28
+ red_piece = Piece.create('cx', :color => 'red')
29
+ blue_piece = Piece.create('cx', :color => 'blue')
30
+ value = JSON.generate([red_piece.key, blue_piece.key])
31
+ redis.hset 'cx', "#{puzzle.key}_pieces", value
32
+ assert_equal 2, puzzle.pieces.size
33
+ assert_equal Piece, puzzle.pieces[0].class
34
+ assert_equal 'red', puzzle.pieces[0].color
35
+ end
36
+
37
+ context "create" do
38
+ should "have a create method" do
39
+ assert Puzzle.create('cx').pieces.respond_to?(:create)
40
+ end
41
+
42
+ should "work without attributes" do
43
+ puzzle = Puzzle.create('cx')
44
+ piece = puzzle.pieces.create
45
+ assert piece.is_a?(Piece)
46
+ end
47
+
48
+ should "create and store a new child" do
49
+ puzzle = Puzzle.create('cx')
50
+ puzzle.pieces.create :color => 'green'
51
+ assert_equal 1, puzzle.pieces.size
52
+ puzzle.reload
53
+ assert_equal 1, puzzle.pieces.size
54
+ assert_equal Piece, puzzle.pieces[0].class
55
+ assert_equal 'green', puzzle.pieces[0].color
56
+ end
57
+
58
+ should "associate the created child with self" do
59
+ puzzle = Puzzle.create('cx', :topic => 'provence')
60
+ piece = puzzle.pieces.create :color => 'green'
61
+ assert_equal 'provence', piece.puzzle.topic
62
+ end
63
+ end
64
+
65
+ context "add" do
66
+ should "add the given entity to the association" do
67
+ puzzle = Puzzle.create('cx')
68
+ piece = Piece.create('cx', :color => 'white')
69
+ puzzle.pieces.add piece
70
+ assert_equal 1, puzzle.pieces.size
71
+ puzzle.reload
72
+ assert_equal 1, puzzle.pieces.size
73
+ assert_equal Piece, puzzle.pieces[0].class
74
+ assert_equal 'white', puzzle.pieces[0].color
75
+ end
76
+ end
77
+
78
+ context "find" do
79
+ setup do
80
+ @puzzle = Puzzle.create('cx')
81
+ 5.times { @puzzle.pieces.create :color => 'blue' }
82
+ end
83
+
84
+ should "find the element with the given id" do
85
+ piece = @puzzle.pieces[2]
86
+ assert_equal piece, @puzzle.pieces.find(piece.id)
87
+ end
88
+
89
+ should "raise an exception if no element with the given id exists" do
90
+ assert_raises(Remodel::EntityNotFound) { @puzzle.pieces.find(-1) }
91
+ end
92
+ end
93
+
94
+ end
95
+ end
96
+
97
+ context "reload" do
98
+ should "reset has_many associations" do
99
+ puzzle = Puzzle.create('cx')
100
+ piece = puzzle.pieces.create :color => 'black'
101
+ redis.hdel 'cx', "#{puzzle.key}_pieces"
102
+ puzzle.reload
103
+ assert_equal [], puzzle.pieces
104
+ end
105
+ end
106
+
107
+ end