ohm 1.0.0.rc1 → 1.0.0.rc2
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.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
|
|