redis_object 1.0 → 1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.coveralls.yml +1 -0
- data/.gitignore +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +4 -0
- data/README.markdown +24 -15
- data/Rakefile +8 -0
- data/lib/redis_object.rb +11 -1
- data/lib/redis_object/base.rb +210 -60
- data/lib/redis_object/collection.rb +130 -100
- data/lib/redis_object/defaults.rb +21 -8
- data/lib/redis_object/{history.rb → experimental/history.rb} +0 -0
- data/lib/redis_object/ext/filters.rb +34 -16
- data/lib/redis_object/ext/script_cache.rb +92 -0
- data/lib/redis_object/ext/shardable.rb +18 -0
- data/lib/redis_object/ext/triggers.rb +75 -13
- data/lib/redis_object/ext/view_caching.rb +258 -0
- data/lib/redis_object/ext/views.rb +102 -0
- data/lib/redis_object/indices.rb +44 -39
- data/lib/redis_object/inheritance_tracking.rb +23 -0
- data/lib/redis_object/keys.rb +4 -4
- data/lib/redis_object/storage.rb +30 -1
- data/lib/redis_object/storage/adapter.rb +6 -3
- data/lib/redis_object/storage/redis.rb +98 -3
- data/lib/redis_object/timestamps.rb +42 -21
- data/lib/redis_object/types.rb +172 -30
- data/lib/redis_object/version.rb +1 -1
- data/redis_object.gemspec +1 -0
- data/spec/adapter_spec.rb +43 -0
- data/spec/base_spec.rb +41 -6
- data/spec/benchmark_spec.rb +46 -0
- data/spec/collections_spec.rb +144 -0
- data/spec/defaults_spec.rb +56 -0
- data/spec/filters_spec.rb +29 -0
- data/spec/indices_spec.rb +45 -0
- data/spec/rename_class_spec.rb +96 -0
- data/spec/spec_helper.rb +32 -1
- data/spec/timestamp_spec.rb +28 -0
- data/spec/trigger_spec.rb +51 -0
- data/spec/types_spec.rb +103 -0
- data/spec/view_caching_spec.rb +130 -0
- data/spec/views_spec.rb +72 -0
- metadata +111 -116
- data/doc/Object.html +0 -185
- data/doc/Seabright.html +0 -181
- data/doc/Seabright/Adapter.html +0 -442
- data/doc/Seabright/Collection.html +0 -797
- data/doc/Seabright/Collections.html +0 -635
- data/doc/Seabright/Collections/ClassMethods.html +0 -212
- data/doc/Seabright/ExternalIndex.html +0 -217
- data/doc/Seabright/History.html +0 -382
- data/doc/Seabright/History/ClassMethods.html +0 -276
- data/doc/Seabright/Indices.html +0 -324
- data/doc/Seabright/Indices/ClassMethods.html +0 -348
- data/doc/Seabright/Keys.html +0 -314
- data/doc/Seabright/Keys/ClassMethods.html +0 -276
- data/doc/Seabright/ObjectBase.html +0 -852
- data/doc/Seabright/ObjectBase/ClassMethods.html +0 -677
- data/doc/Seabright/RedisObject.html +0 -230
- data/doc/Seabright/References.html +0 -280
- data/doc/Seabright/Storage.html +0 -252
- data/doc/Seabright/Storage/ClassMethods.html +0 -276
- data/doc/Seabright/Storage/MySQL.html +0 -442
- data/doc/Seabright/Storage/Redis.html +0 -218
- data/doc/Seabright/Template.html +0 -212
- data/doc/Seabright/Template/ClassMethods.html +0 -166
- data/doc/Seabright/Timestamps.html +0 -292
- data/doc/Seabright/Timestamps/ClassMethods.html +0 -214
- data/doc/Seabright/Types.html +0 -410
- data/doc/Seabright/Types/ClassMethods.html +0 -308
- data/doc/created.rid +0 -17
- data/doc/images/add.png +0 -0
- data/doc/images/brick.png +0 -0
- data/doc/images/brick_link.png +0 -0
- data/doc/images/bug.png +0 -0
- data/doc/images/bullet_black.png +0 -0
- data/doc/images/bullet_toggle_minus.png +0 -0
- data/doc/images/bullet_toggle_plus.png +0 -0
- data/doc/images/date.png +0 -0
- data/doc/images/delete.png +0 -0
- data/doc/images/find.png +0 -0
- data/doc/images/loadingAnimation.gif +0 -0
- data/doc/images/macFFBgHack.png +0 -0
- data/doc/images/package.png +0 -0
- data/doc/images/page_green.png +0 -0
- data/doc/images/page_white_text.png +0 -0
- data/doc/images/page_white_width.png +0 -0
- data/doc/images/plugin.png +0 -0
- data/doc/images/ruby.png +0 -0
- data/doc/images/tag_blue.png +0 -0
- data/doc/images/tag_green.png +0 -0
- data/doc/images/transparent.png +0 -0
- data/doc/images/wrench.png +0 -0
- data/doc/images/wrench_orange.png +0 -0
- data/doc/images/zoom.png +0 -0
- data/doc/index.html +0 -125
- data/doc/js/darkfish.js +0 -153
- data/doc/js/jquery.js +0 -18
- data/doc/js/navigation.js +0 -142
- data/doc/js/search.js +0 -94
- data/doc/js/search_index.js +0 -1
- data/doc/js/searcher.js +0 -228
- data/doc/rdoc.css +0 -543
- data/doc/table_of_contents.html +0 -394
@@ -0,0 +1,102 @@
|
|
1
|
+
module Seabright
|
2
|
+
module Views
|
3
|
+
|
4
|
+
ViewFieldGetter = "local out = {}
|
5
|
+
local key
|
6
|
+
local val
|
7
|
+
for i=1,#ARGV do
|
8
|
+
key = ARGV[i]
|
9
|
+
val = redis.call('HGET',KEYS[1],key)
|
10
|
+
if val then
|
11
|
+
table.insert(out,key)
|
12
|
+
table.insert(out,val)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
return out".gsub(/\t/,'').freeze
|
16
|
+
|
17
|
+
def view_as_hash(name)
|
18
|
+
out = {}
|
19
|
+
if requested_set = self.class.named_views[name]
|
20
|
+
if requested_set.is_a?(Symbol) and self.respond_to?(requested_set)
|
21
|
+
out = send(requested_set)
|
22
|
+
else
|
23
|
+
methods = requested_set[:fields].select {|f| self.respond_to?(f.to_sym) }
|
24
|
+
if methods.count > 0
|
25
|
+
methods.each do |m|
|
26
|
+
out[m.to_s] = send(m.to_sym)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
if requested_set[:fields] && (flds = requested_set[:fields].select {|f| !out.keys.include?(f.to_s) }.map {|f| f.to_s }) && flds.count > 0
|
30
|
+
res = Hash[*store.eval(ViewFieldGetter, [hkey], flds)]
|
31
|
+
out.merge!(res)
|
32
|
+
end
|
33
|
+
if requested_set[:procs]
|
34
|
+
requested_set[:procs].each do |k,proc|
|
35
|
+
out[k.to_s] = proc.call(self)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
if requested_set[:hashes]
|
39
|
+
requested_set[:hashes].each do |k,v|
|
40
|
+
case v
|
41
|
+
when String, Symbol
|
42
|
+
out[k.to_s] = get(v)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
out
|
49
|
+
end
|
50
|
+
|
51
|
+
def view_as_json(name)
|
52
|
+
Yajl::Encoder.encode(view_as_hash(name))
|
53
|
+
end
|
54
|
+
|
55
|
+
module ClassMethods
|
56
|
+
|
57
|
+
def named_view(name,*fields)
|
58
|
+
named_views[name] = normalize_field_options(fields)
|
59
|
+
end
|
60
|
+
|
61
|
+
def named_views
|
62
|
+
@named_views ||= {}
|
63
|
+
end
|
64
|
+
|
65
|
+
def normalize_field_options(fields)
|
66
|
+
fields.flatten!
|
67
|
+
fields.uniq!
|
68
|
+
|
69
|
+
options = {}
|
70
|
+
if fields.last.is_a?(Hash) # assume an option hash
|
71
|
+
options.merge!(fields.slice!(fields.size - 1, 1)[0])
|
72
|
+
end
|
73
|
+
|
74
|
+
# assign a the method as a symbol to be exclusively invoked on view
|
75
|
+
# so instead of returning a hash on view, it will return only what was
|
76
|
+
# produced by calling the method.
|
77
|
+
if options.keys.size > 0 and options[:method]
|
78
|
+
out = options[:method].to_sym
|
79
|
+
else
|
80
|
+
hash = fields.select {|f| f.is_a?(Hash) }.inject({},:merge)
|
81
|
+
out = {}
|
82
|
+
if (h = hash.select {|k,v| !v.is_a?(Proc) }) && h.count > 0
|
83
|
+
out[:hashes] = h
|
84
|
+
end
|
85
|
+
if (h = hash.select {|k,v| v.is_a?(Proc) }) && h.count > 0
|
86
|
+
out[:procs] = h
|
87
|
+
end
|
88
|
+
if (h = fields.select {|o| o.is_a?(String) || o.is_a?(Symbol) }) && h.count > 0
|
89
|
+
out[:fields] = h
|
90
|
+
end
|
91
|
+
end
|
92
|
+
out
|
93
|
+
end
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.included(base)
|
98
|
+
base.extend(ClassMethods)
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
data/lib/redis_object/indices.rb
CHANGED
@@ -1,45 +1,50 @@
|
|
1
1
|
module Seabright
|
2
2
|
module Indices
|
3
3
|
|
4
|
-
# def save_indices
|
5
|
-
# # self.class.indices.each do |indx|
|
6
|
-
# # indx.each do |key,idx|
|
7
|
-
# #
|
8
|
-
# # end
|
9
|
-
# # end
|
10
|
-
# self.class.sort_indices.each do |idx|
|
11
|
-
# store.zadd(index_key(idx), send(idx).to_i, hkey)
|
12
|
-
# end
|
13
|
-
# end
|
14
|
-
|
15
4
|
def index_key(idx)
|
16
5
|
self.class.index_key(idx)
|
17
6
|
end
|
18
7
|
|
19
|
-
# def save
|
20
|
-
# super
|
21
|
-
# save_indices
|
22
|
-
# end
|
23
|
-
|
24
|
-
def mset(dat)
|
25
|
-
super(dat)
|
26
|
-
dat.select {|k,v| self.class.has_sort_index?(k) }.each do |k,v|
|
27
|
-
store.zadd(index_key(k), score_format(k,v), hkey)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def set(k,v)
|
32
|
-
super(k,v)
|
33
|
-
if self.class.has_sort_index?(k)
|
34
|
-
store.zadd(index_key(k), score_format(k,v), hkey)
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
8
|
module ClassMethods
|
39
9
|
|
10
|
+
def intercept_sets_for_indices!
|
11
|
+
return if @intercepted_sets_for_indices
|
12
|
+
self.class_eval do
|
13
|
+
alias_method :unindexed_set, :set unless method_defined?(:unindexed_set)
|
14
|
+
def set(k,v)
|
15
|
+
ret = unindexed_set(k,v)
|
16
|
+
if self.class.has_sort_index?(k)
|
17
|
+
store.zrem(index_key(k), hkey)
|
18
|
+
store.zadd(index_key(k), score_format(k,v), hkey)
|
19
|
+
end
|
20
|
+
ret
|
21
|
+
end
|
22
|
+
alias_method :unindexed_mset, :mset unless method_defined?(:unindexed_mset)
|
23
|
+
def mset(dat)
|
24
|
+
ret = unindexed_mset(dat)
|
25
|
+
dat.select {|k,v| self.class.has_sort_index?(k) }.each do |k,v|
|
26
|
+
store.zrem(index_key(k), hkey)
|
27
|
+
store.zadd(index_key(k), score_format(k,v), hkey)
|
28
|
+
end
|
29
|
+
ret
|
30
|
+
end
|
31
|
+
alias_method :unindexed_setnx, :setnx unless method_defined?(:unindexed_setnx)
|
32
|
+
def setnx(k,v)
|
33
|
+
ret = unindexed_setnx(k,v)
|
34
|
+
if self.class.has_sort_index?(k)
|
35
|
+
store.zrem(index_key(k), hkey)
|
36
|
+
store.zadd(index_key(k), score_format(k,v), hkey)
|
37
|
+
end
|
38
|
+
ret
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
@intercepted_sets_for_indices = true
|
43
|
+
end
|
44
|
+
|
40
45
|
def indexed(idx,num=-1,reverse=false)
|
41
46
|
out = Enumerator.new do |yielder|
|
42
|
-
store.send(reverse ? :zrevrange : :zrange, index_key(idx), 0, num).each do |member|
|
47
|
+
store.send(reverse ? :zrevrange : :zrange, index_key(idx), 0, num-1).each do |member|
|
43
48
|
if a = self.find_by_key(member)
|
44
49
|
yielder << a
|
45
50
|
end
|
@@ -58,20 +63,20 @@ module Seabright
|
|
58
63
|
"#{self.plname}::#{idx}"
|
59
64
|
end
|
60
65
|
|
61
|
-
# def index(opts)
|
62
|
-
# indices << opts
|
63
|
-
# end
|
64
|
-
#
|
65
|
-
# def indices
|
66
|
-
# @@indices ||= []
|
67
|
-
# end
|
68
|
-
|
69
66
|
def sort_indices
|
70
67
|
@@sort_indices ||= []
|
71
68
|
end
|
72
69
|
|
73
70
|
def sort_by(k)
|
74
71
|
sort_indices << k.to_sym
|
72
|
+
intercept_sets_for_indices!
|
73
|
+
end
|
74
|
+
|
75
|
+
def reindex(k)
|
76
|
+
store.del index_key(k)
|
77
|
+
all.each do |obj|
|
78
|
+
obj.set(k,obj.get(k))
|
79
|
+
end
|
75
80
|
end
|
76
81
|
|
77
82
|
def has_sort_index?(k)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Seabright
|
2
|
+
module InheritanceTracking
|
3
|
+
|
4
|
+
module ClassMethods
|
5
|
+
def inherited(child_class)
|
6
|
+
child_classes_set.add(child_class)
|
7
|
+
end
|
8
|
+
|
9
|
+
def child_classes_set
|
10
|
+
@child_classes_set ||= Set.new
|
11
|
+
end
|
12
|
+
|
13
|
+
def child_classes
|
14
|
+
child_classes_set.to_a
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.included(base)
|
19
|
+
base.extend(ClassMethods)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
data/lib/redis_object/keys.rb
CHANGED
@@ -15,15 +15,15 @@ module Seabright
|
|
15
15
|
|
16
16
|
module ClassMethods
|
17
17
|
|
18
|
-
def key(ident)
|
19
|
-
"#{cname}:#{ident.gsub(/^.*:/,'')}"
|
18
|
+
def key(ident=nil)
|
19
|
+
"#{cname}#{ident ? ":#{ident.gsub(/^.*:/,'')}" : ""}"
|
20
20
|
end
|
21
21
|
|
22
|
-
def reserve_key(ident)
|
22
|
+
def reserve_key(ident=nil)
|
23
23
|
"#{key(ident)}_reserve"
|
24
24
|
end
|
25
25
|
|
26
|
-
def hkey(ident =
|
26
|
+
def hkey(ident = nil)
|
27
27
|
"#{key(ident)}_h"
|
28
28
|
end
|
29
29
|
|
data/lib/redis_object/storage.rb
CHANGED
@@ -19,8 +19,12 @@ module Seabright
|
|
19
19
|
adapters[id] ||= const_get(adapter).new(config(id))
|
20
20
|
end
|
21
21
|
|
22
|
-
def configure_store(conf,id=store_name)
|
22
|
+
def configure_store(conf,id=store_name,*ids)
|
23
23
|
configs[id] = conf
|
24
|
+
ids.each do |i|
|
25
|
+
configs[i] = conf
|
26
|
+
end
|
27
|
+
store(id)
|
24
28
|
end
|
25
29
|
|
26
30
|
def use_store(id)
|
@@ -54,6 +58,31 @@ module Seabright
|
|
54
58
|
configs[id]
|
55
59
|
end
|
56
60
|
|
61
|
+
def stores
|
62
|
+
adapters
|
63
|
+
end
|
64
|
+
|
65
|
+
def dump_stores_to_files(path)
|
66
|
+
raise "Directory does not exist!" unless Dir.exists?(File.dirname(path))
|
67
|
+
adapters.each do |name,adptr|
|
68
|
+
if adptr.respond_to? :dump_to_file
|
69
|
+
puts "Dumping #{name} into #{path}/#{name.to_s}.dump"
|
70
|
+
adptr.dump_to_file("#{path}/#{name.to_s}.dump")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def restore_stores_from_files(path)
|
76
|
+
raise "Directory does not exist!" unless Dir.exists?(File.dirname(path))
|
77
|
+
Dir.glob(path + "/*.dump").each do |file|
|
78
|
+
name = file.gsub(/\.[^\.]+$/,'').gsub(/.*\//,'').to_sym
|
79
|
+
if (stor = store(name)) && stor.respond_to?(:restore_from_file)
|
80
|
+
puts "Restoring #{name} from #{file}"
|
81
|
+
stor.restore_from_file(file)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
57
86
|
end
|
58
87
|
|
59
88
|
def self.included(base)
|
@@ -23,15 +23,18 @@ module Seabright
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def reset
|
26
|
-
|
27
|
-
|
26
|
+
connections.each_index do |i|
|
27
|
+
connections[i] = nil
|
28
28
|
end
|
29
29
|
end
|
30
30
|
alias_method :reconnect!, :reset
|
31
31
|
|
32
32
|
def connection(num=0)
|
33
|
+
connections[num] ||= new_connection
|
34
|
+
end
|
35
|
+
|
36
|
+
def connections
|
33
37
|
@connections ||= []
|
34
|
-
@connections[num] ||= new_connection
|
35
38
|
end
|
36
39
|
|
37
40
|
def new_connection
|
@@ -3,6 +3,7 @@ module Seabright
|
|
3
3
|
class Redis < Adapter
|
4
4
|
|
5
5
|
def method_missing(sym, *args, &block)
|
6
|
+
return super unless connection.respond_to?(sym)
|
6
7
|
puts "[Storage::Redis] #{sym}(#{args.inspect.gsub(/\[|\]/m,'')})" if Debug.verbose?
|
7
8
|
begin
|
8
9
|
connection.send(sym,*args, &block)
|
@@ -10,15 +11,109 @@ module Seabright
|
|
10
11
|
puts "Rescued: #{err.inspect}" if DEBUG
|
11
12
|
reset
|
12
13
|
connection.send(sym,*args, &block)
|
14
|
+
rescue ::Redis::TimeoutError => err
|
15
|
+
puts "Rescued connection timeout: #{err.inspect}" if DEBUG
|
16
|
+
reset
|
17
|
+
connection.send(sym,*args, &block)
|
13
18
|
end
|
14
19
|
end
|
15
20
|
|
16
21
|
def new_connection
|
17
22
|
require 'redis'
|
18
|
-
|
19
|
-
::Redis.new(config_opts(:path, :db, :password))
|
23
|
+
puts "Connecting to Redis with: #{config_opts(:path, :db, :password, :host, :port, :timeout, :tcp_keepalive).inspect}" if DEBUG
|
24
|
+
::Redis.new(config_opts(:path, :db, :password, :host, :port, :timeout, :tcp_keepalive))
|
25
|
+
end
|
26
|
+
|
27
|
+
DUMP_SEPARATOR = "---:::RedisObject::DUMP_SEPARATOR:::---"
|
28
|
+
REC_SEPARATOR = "---:::RedisObject::REC_SEPARATOR:::---"
|
29
|
+
|
30
|
+
def dump_to_file(file)
|
31
|
+
File.open(file,'wb') do |f|
|
32
|
+
keys = connection.send(:keys,"*")
|
33
|
+
f.write keys.map {|k|
|
34
|
+
v = connection.dump(k)
|
35
|
+
v.force_encoding(Encoding::BINARY)
|
36
|
+
[k,v].join(DUMP_SEPARATOR)
|
37
|
+
}.join(REC_SEPARATOR)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def restore_from_file(file)
|
42
|
+
str = File.read(file)
|
43
|
+
str.force_encoding(Encoding::BINARY)
|
44
|
+
str.split(REC_SEPARATOR).each do |line|
|
45
|
+
line.force_encoding(Encoding::BINARY)
|
46
|
+
key, val = line.split(DUMP_SEPARATOR)
|
47
|
+
connection.multi do
|
48
|
+
connection.del key
|
49
|
+
connection.restore key, 0, val
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def rename_class old_name, new_name
|
55
|
+
old_name = old_name.to_s#.split('::').last
|
56
|
+
new_name = new_name.to_s#.split('::').last
|
57
|
+
old_collection_name = old_name.split('::').last.underscore.pluralize
|
58
|
+
new_collection_name = new_name.split('::').last.underscore.pluralize
|
59
|
+
|
60
|
+
# references to type in collection data
|
61
|
+
keys("#{old_name}:*:backreferences").each do |backref_key|
|
62
|
+
smembers(backref_key).each do |hashref|
|
63
|
+
# there are two referenes we need to fix: individual references to items
|
64
|
+
# and lists of collection names.
|
65
|
+
#
|
66
|
+
# this updates the item references in collections
|
67
|
+
backref = hashref.sub(/_h$/,'');
|
68
|
+
old_collection = "#{backref}:COLLECTION:#{old_collection_name}"
|
69
|
+
new_collection = "#{backref}:COLLECTION:#{new_collection_name}"
|
70
|
+
zrange(old_collection, 0, 99999, withscores:true).each do |key, score|
|
71
|
+
zadd(new_collection, score, key.sub(/^#{old_name}/, new_name))
|
72
|
+
end
|
73
|
+
del(old_collection)
|
74
|
+
|
75
|
+
# this updates the lists of collection names
|
76
|
+
collection_names = "#{hashref}:collections"
|
77
|
+
smembers(collection_names).each do |collection_name|
|
78
|
+
if collection_name == old_collection_name
|
79
|
+
sadd(collection_names, new_collection_name)
|
80
|
+
srem(collection_names, old_collection_name)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
rename(backref_key, backref_key.sub(/^#{old_name}/, new_name))
|
85
|
+
end
|
86
|
+
|
87
|
+
# type-wide id index
|
88
|
+
smembers(old_name.pluralize).each do |key|
|
89
|
+
sadd(new_name.pluralize, key.sub(/^#{old_name}/, new_name))
|
90
|
+
old_class = hget("#{key}_h", :class)
|
91
|
+
old_key = hget("#{key}_h", :key)
|
92
|
+
hset("#{key}_h", :class, old_class.sub(/#{old_name}$/, new_name))
|
93
|
+
hset("#{key}_h", :key, old_key.sub(/^#{old_name}/, new_name))
|
94
|
+
hset("#{key}_h", "#{new_name.downcase}_id", key.sub(/^#{old_name}:/,''))
|
95
|
+
hdel("#{key}_h", "#{old_name.downcase}_id")
|
96
|
+
end
|
97
|
+
del(old_name.pluralize)
|
98
|
+
|
99
|
+
# column indexes
|
100
|
+
keys("#{old_name.pluralize}::*").each do |old_index|
|
101
|
+
new_index = old_index.sub(/^#{old_name.pluralize}/, new_name.pluralize)
|
102
|
+
zrange(old_index, 0, 99999, withscores:true).each do |key, score|
|
103
|
+
zadd(new_index, score, key.sub(/^#{old_name}/, new_name))
|
104
|
+
end
|
105
|
+
del(old_index)
|
106
|
+
end
|
107
|
+
|
108
|
+
# top-level keys
|
109
|
+
keys("#{old_name}:*").each do |key|
|
110
|
+
rename(key, key.sub(/^#{old_name}/, new_name))
|
111
|
+
end
|
112
|
+
keys("#{old_name.pluralize}:*").each do |key|
|
113
|
+
rename(key, key.sub(/^#{old_name.pluralize}/, new_name.pluralize))
|
114
|
+
end
|
20
115
|
end
|
21
116
|
|
22
117
|
end
|
23
118
|
end
|
24
|
-
end
|
119
|
+
end
|