ohm 1.0.0.rc1 → 1.0.0.rc2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +1 -1
- data/Rakefile +1 -1
- data/lib/ohm.rb +99 -81
- data/lib/ohm/transaction.rb +21 -17
- data/test/association.rb +1 -1
- data/test/connection.rb +1 -1
- data/test/counters.rb +1 -1
- data/test/extensibility.rb +1 -1
- data/test/filtering.rb +19 -19
- data/test/helper.rb +1 -0
- data/test/indices.rb +5 -5
- data/test/json.rb +9 -9
- data/test/lua-save.rb +34 -34
- data/test/lua.rb +5 -5
- data/test/model.rb +16 -16
- data/test/pipeline-performance.rb +13 -11
- data/test/transactions.rb +32 -45
- data/test/uniques.rb +9 -9
- data/test/validations.rb +4 -4
- metadata +10 -10
data/README.md
CHANGED
@@ -588,7 +588,7 @@ Ohm is rather small and can be extended in many ways.
|
|
588
588
|
A lot of amazing contributions are available at [Ohm Contrib][contrib]
|
589
589
|
make sure to check them if you need to extend Ohm's functionality.
|
590
590
|
|
591
|
-
[contrib]: http://cyx.github.com/ohm-contrib/doc
|
591
|
+
[contrib]: http://cyx.github.com/ohm-contrib/doc/
|
592
592
|
|
593
593
|
Tutorials
|
594
594
|
=========
|
data/Rakefile
CHANGED
@@ -102,7 +102,7 @@ task :paste_lua_inline do
|
|
102
102
|
# save = "foo"
|
103
103
|
# del = "bar"
|
104
104
|
|
105
|
-
ohm = File.read("./lib/ohm.rb", encoding
|
105
|
+
ohm = File.read("./lib/ohm.rb", :encoding => "utf-8")
|
106
106
|
ohm.gsub!(/SAVE =(.*?)$(.*?)EOT/m, wrap("SAVE", save))
|
107
107
|
ohm.gsub!(/DELETE =(.*?)$(.*?)EOT/m, wrap("DELETE", del))
|
108
108
|
|
data/lib/ohm.rb
CHANGED
@@ -20,7 +20,7 @@ module Ohm
|
|
20
20
|
#
|
21
21
|
# IndexNotFound:
|
22
22
|
#
|
23
|
-
# Comment.find(foo
|
23
|
+
# Comment.find(:foo => "Bar") # => Error
|
24
24
|
#
|
25
25
|
# Solution: add an index with `Comment.index :foo`.
|
26
26
|
#
|
@@ -103,8 +103,8 @@ module Ohm
|
|
103
103
|
#
|
104
104
|
# Examples:
|
105
105
|
#
|
106
|
-
# Ohm.connect(port
|
107
|
-
# Ohm.connect(url
|
106
|
+
# Ohm.connect(:port => 6380, :db => 1, :host => "10.0.1.1")
|
107
|
+
# Ohm.connect(:url => "redis://10.0.1.1:6380/1")
|
108
108
|
#
|
109
109
|
# All of the options are simply passed on to `Redis.connect`.
|
110
110
|
#
|
@@ -154,16 +154,16 @@ module Ohm
|
|
154
154
|
# attribute :name
|
155
155
|
# end
|
156
156
|
#
|
157
|
-
# User.all.sort_by(:name, order
|
158
|
-
# User.all.sort_by(:name, order
|
159
|
-
# User.all.sort_by(:name, order
|
157
|
+
# User.all.sort_by(:name, :order => "ALPHA")
|
158
|
+
# User.all.sort_by(:name, :order => "ALPHA DESC")
|
159
|
+
# User.all.sort_by(:name, :order => "ALPHA DESC", :limit => [0, 10])
|
160
160
|
#
|
161
161
|
# Note: This is slower compared to just doing `sort`, specifically
|
162
162
|
# because Redis has to read each individual hash in order to sort
|
163
163
|
# them.
|
164
164
|
#
|
165
165
|
def sort_by(att, options = {})
|
166
|
-
sort(options.merge(by
|
166
|
+
sort(options.merge(:by => namespace["*->%s" % att]))
|
167
167
|
end
|
168
168
|
|
169
169
|
# Allows you to sort your models using their IDs. This is much
|
@@ -177,16 +177,16 @@ module Ohm
|
|
177
177
|
# attribute :name
|
178
178
|
# end
|
179
179
|
#
|
180
|
-
# User.create(name
|
181
|
-
# User.create(name
|
180
|
+
# User.create(:name => "John")
|
181
|
+
# User.create(:name => "Jane")
|
182
182
|
#
|
183
183
|
# User.all.sort.map(&:id) == ["1", "2"]
|
184
184
|
# # => true
|
185
185
|
#
|
186
|
-
# User.all.sort(order
|
186
|
+
# User.all.sort(:order => "ASC").map(&:id) == ["1", "2"]
|
187
187
|
# # => true
|
188
188
|
#
|
189
|
-
# User.all.sort(order
|
189
|
+
# User.all.sort(:order => "DESC").map(&:id) == ["2", "1"]
|
190
190
|
# # => true
|
191
191
|
#
|
192
192
|
def sort(options = {})
|
@@ -225,14 +225,14 @@ module Ohm
|
|
225
225
|
# Example:
|
226
226
|
#
|
227
227
|
# User.all.first ==
|
228
|
-
# User.all.sort(limit
|
228
|
+
# User.all.sort(:limit => [0, 1]).first
|
229
229
|
#
|
230
|
-
# User.all.first(by
|
231
|
-
# User.all.sort_by(:name, order
|
230
|
+
# User.all.first(:by => :name, "ALPHA") ==
|
231
|
+
# User.all.sort_by(:name, :order => "ALPHA", :limit => [0, 1]).first
|
232
232
|
#
|
233
233
|
def first(options = {})
|
234
234
|
opts = options.dup
|
235
|
-
opts.merge!(limit
|
235
|
+
opts.merge!(:limit => [0, 1])
|
236
236
|
|
237
237
|
if opts[:by]
|
238
238
|
sort_by(opts.delete(:by), opts).first
|
@@ -270,11 +270,15 @@ module Ohm
|
|
270
270
|
ids.each { |id| model.db.hgetall(namespace[id]) }
|
271
271
|
end
|
272
272
|
|
273
|
-
|
273
|
+
res = []
|
274
274
|
|
275
|
-
|
276
|
-
|
275
|
+
return res if arr.nil?
|
276
|
+
|
277
|
+
arr.each_with_index do |atts, idx|
|
278
|
+
res << model.new(Hash[*atts].update(:id => ids[idx]))
|
277
279
|
end
|
280
|
+
|
281
|
+
res
|
278
282
|
end
|
279
283
|
end
|
280
284
|
|
@@ -396,11 +400,15 @@ module Ohm
|
|
396
400
|
ids.each { |id| model.db.hgetall(namespace[id]) }
|
397
401
|
end
|
398
402
|
|
399
|
-
|
403
|
+
res = []
|
404
|
+
|
405
|
+
return res if arr.nil?
|
400
406
|
|
401
|
-
arr.
|
402
|
-
model.new(Hash[*atts].update(id
|
407
|
+
arr.each_with_index do |atts, idx|
|
408
|
+
res << model.new(Hash[*atts].update(:id => ids[idx]))
|
403
409
|
end
|
410
|
+
|
411
|
+
res
|
404
412
|
end
|
405
413
|
end
|
406
414
|
|
@@ -411,8 +419,8 @@ module Ohm
|
|
411
419
|
#
|
412
420
|
# Example:
|
413
421
|
#
|
414
|
-
# set = User.find(name
|
415
|
-
# set.find(age
|
422
|
+
# set = User.find(:name => "John")
|
423
|
+
# set.find(:age => 30)
|
416
424
|
#
|
417
425
|
def find(dict)
|
418
426
|
keys = model.filters(dict)
|
@@ -425,11 +433,11 @@ module Ohm
|
|
425
433
|
#
|
426
434
|
# Example:
|
427
435
|
#
|
428
|
-
# set = User.find(name
|
429
|
-
# set.except(country
|
436
|
+
# set = User.find(:name => "John")
|
437
|
+
# set.except(:country => "US")
|
430
438
|
#
|
431
439
|
# # You can also do it in one line.
|
432
|
-
# User.find(name
|
440
|
+
# User.find(:name => "John").except(:country => "US")
|
433
441
|
#
|
434
442
|
def except(dict)
|
435
443
|
MultiSet.new([key], namespace, model).except(dict)
|
@@ -439,11 +447,11 @@ module Ohm
|
|
439
447
|
#
|
440
448
|
# Example:
|
441
449
|
#
|
442
|
-
# set = User.find(name
|
443
|
-
# set.union(name
|
450
|
+
# set = User.find(:name => "John")
|
451
|
+
# set.union(:name => "Jane")
|
444
452
|
#
|
445
453
|
# # You can also do it in one line.
|
446
|
-
# User.find(name
|
454
|
+
# User.find(:name => "John").union(:name => "Jane")
|
447
455
|
#
|
448
456
|
def union(dict)
|
449
457
|
MultiSet.new([key], namespace, model).union(dict)
|
@@ -519,10 +527,10 @@ module Ohm
|
|
519
527
|
# User.all.kind_of?(Ohm::Set)
|
520
528
|
# # => true
|
521
529
|
#
|
522
|
-
# User.find(name
|
530
|
+
# User.find(:name => "John").kind_of?(Ohm::Set)
|
523
531
|
# # => true
|
524
532
|
#
|
525
|
-
# User.find(name
|
533
|
+
# User.find(:name => "John", :age => 30).kind_of?(Ohm::MultiSet)
|
526
534
|
# # => true
|
527
535
|
#
|
528
536
|
class MultiSet < Struct.new(:keys, :namespace, :model)
|
@@ -532,8 +540,8 @@ module Ohm
|
|
532
540
|
#
|
533
541
|
# Example:
|
534
542
|
#
|
535
|
-
# set = User.find(name
|
536
|
-
# set.find(status
|
543
|
+
# set = User.find(:name => "John", :age => 30)
|
544
|
+
# set.find(:status => 'pending')
|
537
545
|
#
|
538
546
|
def find(dict)
|
539
547
|
keys = model.filters(dict)
|
@@ -546,11 +554,11 @@ module Ohm
|
|
546
554
|
#
|
547
555
|
# Example:
|
548
556
|
#
|
549
|
-
# set = User.find(name
|
550
|
-
# set.except(country
|
557
|
+
# set = User.find(:name => "John")
|
558
|
+
# set.except(:country => "US")
|
551
559
|
#
|
552
560
|
# # You can also do it in one line.
|
553
|
-
# User.find(name
|
561
|
+
# User.find(:name => "John").except(:country => "US")
|
554
562
|
#
|
555
563
|
def except(dict)
|
556
564
|
sdiff.push(*model.filters(dict)).uniq!
|
@@ -562,11 +570,11 @@ module Ohm
|
|
562
570
|
#
|
563
571
|
# Example:
|
564
572
|
#
|
565
|
-
# set = User.find(name
|
566
|
-
# set.union(name
|
573
|
+
# set = User.find(:name => "John")
|
574
|
+
# set.union(:name => "Jane")
|
567
575
|
#
|
568
576
|
# # You can also do it in one line.
|
569
|
-
# User.find(name
|
577
|
+
# User.find(:name => "John").union(:name => "Jane")
|
570
578
|
#
|
571
579
|
def union(dict)
|
572
580
|
sunion.push(*model.filters(dict)).uniq!
|
@@ -584,7 +592,7 @@ module Ohm
|
|
584
592
|
end
|
585
593
|
|
586
594
|
def execute
|
587
|
-
key = namespace[:temp][SecureRandom.
|
595
|
+
key = namespace[:temp][SecureRandom.hex(32)]
|
588
596
|
key.sinterstore(*keys)
|
589
597
|
key.sdiffstore(key, *sdiff) if sdiff.any?
|
590
598
|
key.sunionstore(key, *sunion) if sunion.any?
|
@@ -615,7 +623,7 @@ module Ohm
|
|
615
623
|
# set :posts, :Post
|
616
624
|
# end
|
617
625
|
#
|
618
|
-
# u = User.create(name
|
626
|
+
# u = User.create(:name => "John", :email => "foo@bar.com")
|
619
627
|
# u.incr :points
|
620
628
|
# u.posts.add(Post.create)
|
621
629
|
#
|
@@ -696,7 +704,7 @@ module Ohm
|
|
696
704
|
# # => true
|
697
705
|
#
|
698
706
|
def self.[](id)
|
699
|
-
new(id
|
707
|
+
new(:id => id).load! if id && exists?(id)
|
700
708
|
end
|
701
709
|
|
702
710
|
# Retrieve a set of models given an array of IDs.
|
@@ -728,7 +736,7 @@ module Ohm
|
|
728
736
|
# unique :email
|
729
737
|
# end
|
730
738
|
#
|
731
|
-
# u = User.create(email
|
739
|
+
# u = User.create(:email => "foo@bar.com")
|
732
740
|
# u == User.with(:email, "foo@bar.com")
|
733
741
|
# # => true
|
734
742
|
#
|
@@ -762,17 +770,17 @@ module Ohm
|
|
762
770
|
# end
|
763
771
|
# end
|
764
772
|
#
|
765
|
-
# u = User.create(name
|
766
|
-
# User.find(provider
|
773
|
+
# u = User.create(:name => "John", :status => "pending", :email => "foo@me.com")
|
774
|
+
# User.find(:provider => "me", :name => "John", :status => "pending").include?(u)
|
767
775
|
# # => true
|
768
776
|
#
|
769
|
-
# User.find(tag
|
777
|
+
# User.find(:tag => "ruby").include?(u)
|
770
778
|
# # => true
|
771
779
|
#
|
772
|
-
# User.find(tag
|
780
|
+
# User.find(:tag => "python").include?(u)
|
773
781
|
# # => true
|
774
782
|
#
|
775
|
-
# User.find(tag
|
783
|
+
# User.find(:tag => ["ruby", "python"]).include?(u)
|
776
784
|
# # => true
|
777
785
|
#
|
778
786
|
def self.find(dict)
|
@@ -871,7 +879,7 @@ module Ohm
|
|
871
879
|
#
|
872
880
|
# class User < Ohm::Model
|
873
881
|
# def posts
|
874
|
-
# Post.find(user_id
|
882
|
+
# Post.find(:user_id => self.id)
|
875
883
|
# end
|
876
884
|
# end
|
877
885
|
#
|
@@ -1024,7 +1032,7 @@ module Ohm
|
|
1024
1032
|
# attribute :name
|
1025
1033
|
# end
|
1026
1034
|
#
|
1027
|
-
# u = User.create(name
|
1035
|
+
# u = User.create(:name => "John")
|
1028
1036
|
# u.key.hget(:name)
|
1029
1037
|
# # => John
|
1030
1038
|
#
|
@@ -1039,7 +1047,7 @@ module Ohm
|
|
1039
1047
|
#
|
1040
1048
|
# Example:
|
1041
1049
|
#
|
1042
|
-
# u = User.new(name
|
1050
|
+
# u = User.new(:name => "John")
|
1043
1051
|
#
|
1044
1052
|
def initialize(atts = {})
|
1045
1053
|
@attributes = {}
|
@@ -1090,7 +1098,7 @@ module Ohm
|
|
1090
1098
|
#
|
1091
1099
|
# Example:
|
1092
1100
|
#
|
1093
|
-
# User.create(name
|
1101
|
+
# User.create(:name => "A")
|
1094
1102
|
#
|
1095
1103
|
# Session 1 | Session 2
|
1096
1104
|
# --------------|------------------------
|
@@ -1160,9 +1168,9 @@ module Ohm
|
|
1160
1168
|
# attribute :name
|
1161
1169
|
# end
|
1162
1170
|
#
|
1163
|
-
# u = User.create(name
|
1171
|
+
# u = User.create(:name => "John")
|
1164
1172
|
# u.to_hash
|
1165
|
-
# # => { id
|
1173
|
+
# # => { :id => "1" }
|
1166
1174
|
#
|
1167
1175
|
# In order to add additional attributes, you can override `to_hash`:
|
1168
1176
|
#
|
@@ -1170,13 +1178,13 @@ module Ohm
|
|
1170
1178
|
# attribute :name
|
1171
1179
|
#
|
1172
1180
|
# def to_hash
|
1173
|
-
# super.merge(name
|
1181
|
+
# super.merge(:name => name)
|
1174
1182
|
# end
|
1175
1183
|
# end
|
1176
1184
|
#
|
1177
|
-
# u = User.create(name
|
1185
|
+
# u = User.create(:name => "John")
|
1178
1186
|
# u.to_hash
|
1179
|
-
# # => { id
|
1187
|
+
# # => { :id => "1", :name => "John" }
|
1180
1188
|
#
|
1181
1189
|
def to_hash
|
1182
1190
|
attrs = {}
|
@@ -1202,10 +1210,10 @@ module Ohm
|
|
1202
1210
|
# end
|
1203
1211
|
# end
|
1204
1212
|
#
|
1205
|
-
# User.new(name
|
1213
|
+
# User.new(:name => nil).save
|
1206
1214
|
# # => nil
|
1207
1215
|
#
|
1208
|
-
# u = User.new(name
|
1216
|
+
# u = User.new(:name => "John").save
|
1209
1217
|
# u.kind_of?(User)
|
1210
1218
|
# # => true
|
1211
1219
|
#
|
@@ -1217,7 +1225,15 @@ module Ohm
|
|
1217
1225
|
# Saves the model without checking for validity. Refer to
|
1218
1226
|
# `Model#save` for more details.
|
1219
1227
|
def save!
|
1220
|
-
|
1228
|
+
t = __save__
|
1229
|
+
yield t if block_given?
|
1230
|
+
t.commit(db)
|
1231
|
+
|
1232
|
+
return self
|
1233
|
+
end
|
1234
|
+
|
1235
|
+
def __save__
|
1236
|
+
Transaction.new do |t|
|
1221
1237
|
t.watch(*_unique_keys)
|
1222
1238
|
t.watch(key) if not new?
|
1223
1239
|
|
@@ -1225,26 +1241,26 @@ module Ohm
|
|
1225
1241
|
_initialize_id if new?
|
1226
1242
|
end
|
1227
1243
|
|
1228
|
-
|
1244
|
+
existing = nil
|
1245
|
+
uniques = nil
|
1246
|
+
indices = nil
|
1247
|
+
|
1248
|
+
t.read do
|
1229
1249
|
_verify_uniques
|
1230
|
-
|
1231
|
-
|
1232
|
-
|
1250
|
+
existing = key.hgetall
|
1251
|
+
uniques = _read_index_type(:uniques)
|
1252
|
+
indices = _read_index_type(:indices)
|
1233
1253
|
end
|
1234
1254
|
|
1235
|
-
t.write do
|
1255
|
+
t.write do
|
1236
1256
|
model.key[:all].sadd(id)
|
1237
|
-
_delete_uniques(
|
1238
|
-
_delete_indices(
|
1257
|
+
_delete_uniques(existing)
|
1258
|
+
_delete_indices(existing)
|
1239
1259
|
_save
|
1240
|
-
_save_indices(
|
1241
|
-
_save_uniques(
|
1260
|
+
_save_indices(indices)
|
1261
|
+
_save_uniques(uniques)
|
1242
1262
|
end
|
1243
|
-
|
1244
|
-
yield t if block_given?
|
1245
1263
|
end
|
1246
|
-
|
1247
|
-
return self
|
1248
1264
|
end
|
1249
1265
|
|
1250
1266
|
# Delete the model, including all the following keys:
|
@@ -1258,12 +1274,12 @@ module Ohm
|
|
1258
1274
|
def delete
|
1259
1275
|
transaction do |t|
|
1260
1276
|
t.read do |store|
|
1261
|
-
store
|
1277
|
+
store[:existing] = key.hgetall
|
1262
1278
|
end
|
1263
1279
|
|
1264
1280
|
t.write do |store|
|
1265
|
-
_delete_uniques(store
|
1266
|
-
_delete_indices(store
|
1281
|
+
_delete_uniques(store[:existing])
|
1282
|
+
_delete_indices(store[:existing])
|
1267
1283
|
model.collections.each { |e| key[e].del }
|
1268
1284
|
model.key[:all].srem(id)
|
1269
1285
|
key[:counters].del
|
@@ -1278,12 +1294,12 @@ module Ohm
|
|
1278
1294
|
#
|
1279
1295
|
# Example:
|
1280
1296
|
#
|
1281
|
-
# User[1].update(name
|
1297
|
+
# User[1].update(:name => "John")
|
1282
1298
|
#
|
1283
1299
|
# # It's the same as:
|
1284
1300
|
#
|
1285
1301
|
# u = User[1]
|
1286
|
-
# u.update_attributes(name
|
1302
|
+
# u.update_attributes(:name => "John")
|
1287
1303
|
# u.save
|
1288
1304
|
#
|
1289
1305
|
def update(attributes)
|
@@ -1376,7 +1392,7 @@ module Ohm
|
|
1376
1392
|
def _save
|
1377
1393
|
catch :empty do
|
1378
1394
|
key.del
|
1379
|
-
key.hmset(*_skip_empty(attributes).flatten)
|
1395
|
+
key.hmset(*_skip_empty(attributes).to_a.flatten)
|
1380
1396
|
end
|
1381
1397
|
end
|
1382
1398
|
|
@@ -1453,10 +1469,12 @@ module Ohm
|
|
1453
1469
|
keys = options[:keys]
|
1454
1470
|
argv = options[:argv]
|
1455
1471
|
|
1472
|
+
params = keys + argv
|
1473
|
+
|
1456
1474
|
begin
|
1457
|
-
redis.evalsha(sha(script), keys.size, *
|
1475
|
+
redis.evalsha(sha(script), keys.size, *params)
|
1458
1476
|
rescue RuntimeError
|
1459
|
-
redis.eval(script, keys.size, *
|
1477
|
+
redis.eval(script, keys.size, *params)
|
1460
1478
|
end
|
1461
1479
|
end
|
1462
1480
|
|