ohm 0.0.11 → 0.0.12
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/lib/ohm.rb +67 -32
- data/lib/ohm/redis.rb +1 -1
- data/test/db/redis.pid +1 -1
- data/test/model_test.rb +95 -13
- metadata +2 -2
data/lib/ohm.rb
CHANGED
@@ -4,7 +4,7 @@ require File.join(File.dirname(__FILE__), "ohm", "validations")
|
|
4
4
|
|
5
5
|
module Ohm
|
6
6
|
|
7
|
-
# Provides access to the
|
7
|
+
# Provides access to the Redis database. This is shared accross all models and instances.
|
8
8
|
def redis
|
9
9
|
@redis
|
10
10
|
end
|
@@ -38,18 +38,57 @@ module Ohm
|
|
38
38
|
class Collection
|
39
39
|
include Enumerable
|
40
40
|
|
41
|
-
attr_accessor :key, :db
|
41
|
+
attr_accessor :key, :db, :model
|
42
42
|
|
43
|
-
def initialize(db, key)
|
43
|
+
def initialize(db, key, model = nil)
|
44
44
|
self.db = db
|
45
45
|
self.key = key
|
46
|
+
self.model = model
|
46
47
|
end
|
47
48
|
|
48
49
|
def each(&block)
|
49
50
|
all.each(&block)
|
50
51
|
end
|
51
52
|
|
52
|
-
|
53
|
+
# Return instances of model for all the ids contained in the collection.
|
54
|
+
def all
|
55
|
+
instantiate(raw)
|
56
|
+
end
|
57
|
+
|
58
|
+
# Return the values as model instances, ordered by the options supplied.
|
59
|
+
# Check redis documentation to see what values you can provide to each option.
|
60
|
+
#
|
61
|
+
# @param options [Hash] options to sort the collection.
|
62
|
+
# @option options [#to_s] :by Model attribute to sort the instances by.
|
63
|
+
# @option options [#to_s] :order (ASC) Sorting order, which can be ASC or DESC.
|
64
|
+
# @option options [Integer] :limit (all) Number of items to return.
|
65
|
+
# @option options [Integer] :start (0) An offset from where the limit will be applied.
|
66
|
+
# @example Get the first ten users sorted alphabetically by name:
|
67
|
+
# @event.attendees.sort(User, :by => :name, :order => "ALPHA", :limit => 10)
|
68
|
+
#
|
69
|
+
# @example Get five posts sorted by number of votes and starting from the number 5 (zero based):
|
70
|
+
# @blog.posts.sort(Post, :by => :votes, :start => 5, :limit => 10")
|
71
|
+
def sort(options = {})
|
72
|
+
options[:start] ||= 0
|
73
|
+
options[:limit] = [options[:start], options[:limit]] if options[:limit]
|
74
|
+
instantiate(db.sort(key, options))
|
75
|
+
end
|
76
|
+
|
77
|
+
def sort_by(att, options = {})
|
78
|
+
sort(options.merge(:by => model.key("*", att)))
|
79
|
+
end
|
80
|
+
|
81
|
+
def to_ary
|
82
|
+
all
|
83
|
+
end
|
84
|
+
|
85
|
+
def ==(other)
|
86
|
+
to_ary == other
|
87
|
+
end
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
def instantiate(raw)
|
53
92
|
model ? raw.collect { |id| model[id] } : raw
|
54
93
|
end
|
55
94
|
end
|
@@ -74,7 +113,9 @@ module Ohm
|
|
74
113
|
db.rpush(key, value)
|
75
114
|
end
|
76
115
|
|
77
|
-
|
116
|
+
def empty?
|
117
|
+
db.llen(key).zero?
|
118
|
+
end
|
78
119
|
|
79
120
|
def raw
|
80
121
|
db.list(key)
|
@@ -113,14 +154,16 @@ module Ohm
|
|
113
154
|
db.srem(key, value)
|
114
155
|
end
|
115
156
|
|
157
|
+
def empty?
|
158
|
+
db.scard(key).zero?
|
159
|
+
end
|
160
|
+
|
116
161
|
def include?(value)
|
117
162
|
db.sismember(key, value)
|
118
163
|
end
|
119
164
|
|
120
|
-
private
|
121
|
-
|
122
165
|
def raw
|
123
|
-
db.smembers(key)
|
166
|
+
db.smembers(key)
|
124
167
|
end
|
125
168
|
end
|
126
169
|
end
|
@@ -185,8 +228,8 @@ module Ohm
|
|
185
228
|
# is created.
|
186
229
|
#
|
187
230
|
# @param name [Symbol] Name of the list.
|
188
|
-
def self.list(name)
|
189
|
-
attr_list_reader(name)
|
231
|
+
def self.list(name, model = nil)
|
232
|
+
attr_list_reader(name, model)
|
190
233
|
collections << name
|
191
234
|
end
|
192
235
|
|
@@ -195,8 +238,8 @@ module Ohm
|
|
195
238
|
# operations like union, join, and membership checks are important.
|
196
239
|
#
|
197
240
|
# @param name [Symbol] Name of the set.
|
198
|
-
def self.set(name)
|
199
|
-
attr_set_reader(name)
|
241
|
+
def self.set(name, model = nil)
|
242
|
+
attr_set_reader(name, model)
|
200
243
|
collections << name
|
201
244
|
end
|
202
245
|
|
@@ -225,20 +268,18 @@ module Ohm
|
|
225
268
|
indices << Array(attrs)
|
226
269
|
end
|
227
270
|
|
228
|
-
def self.attr_list_reader(name)
|
229
|
-
|
230
|
-
|
231
|
-
@#{name}
|
232
|
-
|
233
|
-
EOS
|
271
|
+
def self.attr_list_reader(name, model = nil)
|
272
|
+
define_method(name) do
|
273
|
+
instance_variable_get("@#{name}") ||
|
274
|
+
instance_variable_set("@#{name}", Attributes::List.new(db, key(name), model))
|
275
|
+
end
|
234
276
|
end
|
235
277
|
|
236
|
-
def self.attr_set_reader(name)
|
237
|
-
|
238
|
-
|
239
|
-
@#{name}
|
240
|
-
|
241
|
-
EOS
|
278
|
+
def self.attr_set_reader(name, model)
|
279
|
+
define_method(name) do
|
280
|
+
instance_variable_get("@#{name}") ||
|
281
|
+
instance_variable_set("@#{name}", Attributes::Set.new(db, key(name), model))
|
282
|
+
end
|
242
283
|
end
|
243
284
|
|
244
285
|
def self.[](id)
|
@@ -246,7 +287,7 @@ module Ohm
|
|
246
287
|
end
|
247
288
|
|
248
289
|
def self.all
|
249
|
-
|
290
|
+
@all ||= Attributes::Set.new(db, key(:all), self)
|
250
291
|
end
|
251
292
|
|
252
293
|
def self.attributes
|
@@ -272,7 +313,7 @@ module Ohm
|
|
272
313
|
end
|
273
314
|
|
274
315
|
def self.find(attribute, value)
|
275
|
-
|
316
|
+
Attributes::Set.new(db, key(attribute, encode(value)), self)
|
276
317
|
end
|
277
318
|
|
278
319
|
def self.encode(value)
|
@@ -376,12 +417,6 @@ module Ohm
|
|
376
417
|
Ohm.key(*args.unshift(self))
|
377
418
|
end
|
378
419
|
|
379
|
-
def self.filter(name)
|
380
|
-
db.smembers(key(name)).map do |id|
|
381
|
-
new(:id => id)
|
382
|
-
end
|
383
|
-
end
|
384
|
-
|
385
420
|
def self.exists?(id)
|
386
421
|
db.sismember(key(:all), id)
|
387
422
|
end
|
data/lib/ohm/redis.rb
CHANGED
@@ -94,7 +94,7 @@ module Ohm
|
|
94
94
|
cmd << "BY #{opts[:by]}" if opts[:by]
|
95
95
|
cmd << "GET #{[opts[:get]].flatten * ' GET '}" if opts[:get]
|
96
96
|
cmd << "#{opts[:order]}" if opts[:order]
|
97
|
-
cmd << "LIMIT #{opts[:limit].join(' ')}" if opts[:limit]
|
97
|
+
cmd << "LIMIT #{Array(opts[:limit]).join(' ')}" if opts[:limit]
|
98
98
|
call_command(cmd)
|
99
99
|
end
|
100
100
|
|
data/test/db/redis.pid
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
39163
|
data/test/model_test.rb
CHANGED
@@ -1,18 +1,13 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), "test_helper")
|
2
2
|
|
3
|
-
class
|
4
|
-
attribute :
|
5
|
-
|
6
|
-
set :attendees
|
3
|
+
class Post < Ohm::Model
|
4
|
+
attribute :body
|
5
|
+
list :comments
|
7
6
|
end
|
8
7
|
|
9
8
|
class User < Ohm::Model
|
10
9
|
attribute :email
|
11
|
-
|
12
|
-
|
13
|
-
class Post < Ohm::Model
|
14
|
-
attribute :body
|
15
|
-
list :comments
|
10
|
+
set :posts, Post
|
16
11
|
end
|
17
12
|
|
18
13
|
class Person < Ohm::Model
|
@@ -23,6 +18,13 @@ class Person < Ohm::Model
|
|
23
18
|
end
|
24
19
|
end
|
25
20
|
|
21
|
+
class Event < Ohm::Model
|
22
|
+
attribute :name
|
23
|
+
counter :votes
|
24
|
+
set :attendees, Person
|
25
|
+
end
|
26
|
+
|
27
|
+
|
26
28
|
class TestRedis < Test::Unit::TestCase
|
27
29
|
context "An event initialized with a hash of attributes" do
|
28
30
|
should "assign the passed attributes" do
|
@@ -169,6 +171,18 @@ class TestRedis < Test::Unit::TestCase
|
|
169
171
|
end
|
170
172
|
end
|
171
173
|
|
174
|
+
context "Sorting" do
|
175
|
+
should "sort all" do
|
176
|
+
Ohm.flush
|
177
|
+
Person.create :name => "D"
|
178
|
+
Person.create :name => "C"
|
179
|
+
Person.create :name => "B"
|
180
|
+
Person.create :name => "A"
|
181
|
+
|
182
|
+
assert_equal %w[A B C D], Person.all.sort_by(:name, :order => "ALPHA").map { |person| person.name }
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
172
186
|
context "Loading attributes" do
|
173
187
|
setup do
|
174
188
|
event = Event.new
|
@@ -207,9 +221,9 @@ class TestRedis < Test::Unit::TestCase
|
|
207
221
|
@event.attendees << "1"
|
208
222
|
@event.attendees << "2"
|
209
223
|
@event.attendees << "3"
|
210
|
-
assert_equal ["1", "2", "3"], @event.attendees.
|
224
|
+
assert_equal ["1", "2", "3"], @event.attendees.raw.sort
|
211
225
|
@event.attendees.delete("2")
|
212
|
-
assert_equal ["1", "3"], Event[@event.id].attendees.
|
226
|
+
assert_equal ["1", "3"], Event[@event.id].attendees.raw.sort
|
213
227
|
end
|
214
228
|
|
215
229
|
should "return true if the set includes some member" do
|
@@ -226,7 +240,7 @@ class TestRedis < Test::Unit::TestCase
|
|
226
240
|
@person = Person.create :name => "albert"
|
227
241
|
@event.attendees << @person.id
|
228
242
|
|
229
|
-
assert_equal [@person], @event.attendees.all
|
243
|
+
assert_equal [@person], @event.attendees.all
|
230
244
|
end
|
231
245
|
|
232
246
|
should "insert the model instance id instead of the object if using add" do
|
@@ -234,7 +248,7 @@ class TestRedis < Test::Unit::TestCase
|
|
234
248
|
@person = Person.create :name => "albert"
|
235
249
|
@event.attendees.add(@person)
|
236
250
|
|
237
|
-
assert_equal [@person.id.to_s], @event.attendees.
|
251
|
+
assert_equal [@person.id.to_s], @event.attendees.raw
|
238
252
|
end
|
239
253
|
end
|
240
254
|
|
@@ -277,6 +291,74 @@ class TestRedis < Test::Unit::TestCase
|
|
277
291
|
end
|
278
292
|
end
|
279
293
|
|
294
|
+
context "Applying arbitrary transformations" do
|
295
|
+
class Calendar < Ohm::Model
|
296
|
+
list :holidays, lambda { |v| Date.parse(v) }
|
297
|
+
end
|
298
|
+
|
299
|
+
setup do
|
300
|
+
@calendar = Calendar.create
|
301
|
+
@calendar.holidays << "05/25/2009"
|
302
|
+
@calendar.holidays << "07/09/2009"
|
303
|
+
end
|
304
|
+
|
305
|
+
should "apply a transformation" do
|
306
|
+
assert_equal [Date.parse("2009-05-25"), Date.parse("2009-07-09")], @calendar.holidays
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
context "Sorting lists and sets" do
|
311
|
+
setup do
|
312
|
+
@post = Post.create(:body => "Lorem")
|
313
|
+
@post.comments << 2
|
314
|
+
@post.comments << 3
|
315
|
+
@post.comments << 1
|
316
|
+
end
|
317
|
+
|
318
|
+
should "sort values" do
|
319
|
+
assert_equal %w{1 2 3}, @post.comments.sort
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
context "Sorting lists and sets by model attributes" do
|
324
|
+
setup do
|
325
|
+
@event = Event.create(:name => "Ruby Tuesday")
|
326
|
+
@event.attendees << Person.create(:name => "D").id
|
327
|
+
@event.attendees << Person.create(:name => "C").id
|
328
|
+
@event.attendees << Person.create(:name => "B").id
|
329
|
+
@event.attendees << Person.create(:name => "A").id
|
330
|
+
end
|
331
|
+
|
332
|
+
should "sort the model instances by the values provided" do
|
333
|
+
people = @event.attendees.sort_by(:name, :order => "ALPHA")
|
334
|
+
assert_equal %w[A B C D], people.map { |person| person.name }
|
335
|
+
end
|
336
|
+
|
337
|
+
should "accept a number in the limit parameter" do
|
338
|
+
people = @event.attendees.sort_by(:name, :limit => 2, :order => "ALPHA")
|
339
|
+
assert_equal %w[A B], people.map { |person| person.name }
|
340
|
+
end
|
341
|
+
|
342
|
+
should "use the start parameter as an offset if the limit is provided" do
|
343
|
+
people = @event.attendees.sort_by(:name, :limit => 2, :start => 1, :order => "ALPHA")
|
344
|
+
assert_equal %w[B C], people.map { |person| person.name }
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
context "Collections initialized with a Model parameter" do
|
349
|
+
setup do
|
350
|
+
@user = User.create(:email => "albert@example.com")
|
351
|
+
@user.posts.add Post.create(:body => "D")
|
352
|
+
@user.posts.add Post.create(:body => "C")
|
353
|
+
@user.posts.add Post.create(:body => "B")
|
354
|
+
@user.posts.add Post.create(:body => "A")
|
355
|
+
end
|
356
|
+
|
357
|
+
should "return instances of the passed model" do
|
358
|
+
assert_equal Post, @user.posts.all.first.class
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
280
362
|
context "Counters" do
|
281
363
|
setup do
|
282
364
|
@event = Event.create(:name => "Ruby Tuesday")
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ohm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.12
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michel Martens
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2009-07-
|
13
|
+
date: 2009-07-27 00:00:00 -03:00
|
14
14
|
default_executable:
|
15
15
|
dependencies: []
|
16
16
|
|