familia 0.6.1 → 0.6.2
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/CHANGES.txt +15 -0
- data/Rakefile +3 -3
- data/VERSION.yml +1 -1
- data/familia.gemspec +11 -11
- data/lib/familia/core_ext.rb +85 -84
- data/lib/familia/object.rb +123 -83
- data/lib/familia/redisobject.rb +224 -53
- data/lib/familia/test_helpers.rb +0 -2
- data/lib/familia.rb +38 -43
- data/try/21_redis_object_zset_try.rb +1 -1
- data/try/24_redis_object_string_try.rb +1 -1
- data/try/30_familia_object_try.rb +2 -2
- metadata +13 -13
data/CHANGES.txt
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
FAMILIA, CHANGES
|
|
2
2
|
|
|
3
|
+
#### 0.6.2 (2010-12-29) ###############################
|
|
4
|
+
|
|
5
|
+
* FIXED: Familia::ClassMethods.ttl=
|
|
6
|
+
* FIXED: Familia.class_lists (etc) methods.
|
|
7
|
+
* FIXED: Redis objects check if parent is a Module
|
|
8
|
+
* CHANGE: redis_objects, class_redis_objects maintain order they're defined in. (See Bluth::Queue)
|
|
9
|
+
* CHANGE: Depends on Storable 0.8.4
|
|
10
|
+
* CHANGE: FamiliaObject.instances is now a sorted set
|
|
11
|
+
* ADDED: InstanceMethods#initialize calls init if available
|
|
12
|
+
* ADDED: Can set index values via InstanceMethods#index=
|
|
13
|
+
* ADDED: empty? method for List, Set, et al
|
|
14
|
+
* ADDED: :extend option for RedisObject instances
|
|
15
|
+
* ADDED: :reference option for storing the index value instead of the marshaled value
|
|
16
|
+
|
|
17
|
+
|
|
3
18
|
#### 0.6.1 (2010-12-18) ###############################
|
|
4
19
|
|
|
5
20
|
* CHANGE: Default initialize method calls initialize_redis_objects before super
|
data/Rakefile
CHANGED
|
@@ -26,9 +26,9 @@ begin
|
|
|
26
26
|
gem.homepage = "http://github.com/delano/familia"
|
|
27
27
|
gem.authors = ["Delano Mandelbaum"]
|
|
28
28
|
gem.add_dependency("redis", ">= 2.1.0")
|
|
29
|
-
gem.add_dependency("uri-redis", ">= 0.4.
|
|
30
|
-
gem.add_dependency("gibbler", ">= 0.8.
|
|
31
|
-
gem.add_dependency("storable", ">= 0.8.
|
|
29
|
+
gem.add_dependency("uri-redis", ">= 0.4.2")
|
|
30
|
+
gem.add_dependency("gibbler", ">= 0.8.6")
|
|
31
|
+
gem.add_dependency("storable", ">= 0.8.5")
|
|
32
32
|
|
|
33
33
|
#gem.add_development_dependency("rspec", ">= 1.2.9")
|
|
34
34
|
#gem.add_development_dependency("mocha", ">= 0.9.8")
|
data/VERSION.yml
CHANGED
data/familia.gemspec
CHANGED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |s|
|
|
7
7
|
s.name = %q{familia}
|
|
8
|
-
s.version = "0.6.
|
|
8
|
+
s.version = "0.6.2"
|
|
9
9
|
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
11
11
|
s.authors = ["Delano Mandelbaum"]
|
|
12
|
-
s.date = %q{2010-12-
|
|
12
|
+
s.date = %q{2010-12-30}
|
|
13
13
|
s.description = %q{Organize and store ruby objects in Redis}
|
|
14
14
|
s.email = %q{delano@solutious.com}
|
|
15
15
|
s.extra_rdoc_files = [
|
|
@@ -53,20 +53,20 @@ Gem::Specification.new do |s|
|
|
|
53
53
|
|
|
54
54
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
|
55
55
|
s.add_runtime_dependency(%q<redis>, [">= 2.1.0"])
|
|
56
|
-
s.add_runtime_dependency(%q<uri-redis>, [">= 0.4.
|
|
57
|
-
s.add_runtime_dependency(%q<gibbler>, [">= 0.8.
|
|
58
|
-
s.add_runtime_dependency(%q<storable>, [">= 0.8.
|
|
56
|
+
s.add_runtime_dependency(%q<uri-redis>, [">= 0.4.2"])
|
|
57
|
+
s.add_runtime_dependency(%q<gibbler>, [">= 0.8.6"])
|
|
58
|
+
s.add_runtime_dependency(%q<storable>, [">= 0.8.5"])
|
|
59
59
|
else
|
|
60
60
|
s.add_dependency(%q<redis>, [">= 2.1.0"])
|
|
61
|
-
s.add_dependency(%q<uri-redis>, [">= 0.4.
|
|
62
|
-
s.add_dependency(%q<gibbler>, [">= 0.8.
|
|
63
|
-
s.add_dependency(%q<storable>, [">= 0.8.
|
|
61
|
+
s.add_dependency(%q<uri-redis>, [">= 0.4.2"])
|
|
62
|
+
s.add_dependency(%q<gibbler>, [">= 0.8.6"])
|
|
63
|
+
s.add_dependency(%q<storable>, [">= 0.8.5"])
|
|
64
64
|
end
|
|
65
65
|
else
|
|
66
66
|
s.add_dependency(%q<redis>, [">= 2.1.0"])
|
|
67
|
-
s.add_dependency(%q<uri-redis>, [">= 0.4.
|
|
68
|
-
s.add_dependency(%q<gibbler>, [">= 0.8.
|
|
69
|
-
s.add_dependency(%q<storable>, [">= 0.8.
|
|
67
|
+
s.add_dependency(%q<uri-redis>, [">= 0.4.2"])
|
|
68
|
+
s.add_dependency(%q<gibbler>, [">= 0.8.6"])
|
|
69
|
+
s.add_dependency(%q<storable>, [">= 0.8.5"])
|
|
70
70
|
end
|
|
71
71
|
end
|
|
72
72
|
|
data/lib/familia/core_ext.rb
CHANGED
|
@@ -17,102 +17,103 @@ class String
|
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
unless defined?(Time::Units)
|
|
21
|
+
class Time
|
|
22
|
+
module Units
|
|
23
|
+
PER_MICROSECOND = 0.000001.freeze
|
|
24
|
+
PER_MILLISECOND = 0.001.freeze
|
|
25
|
+
PER_MINUTE = 60.0.freeze
|
|
26
|
+
PER_HOUR = 3600.0.freeze
|
|
27
|
+
PER_DAY = 86400.0.freeze
|
|
27
28
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
29
|
+
def microseconds() seconds * PER_MICROSECOND end
|
|
30
|
+
def milliseconds() seconds * PER_MILLISECOND end
|
|
31
|
+
def seconds() self end
|
|
32
|
+
def minutes() seconds * PER_MINUTE end
|
|
33
|
+
def hours() seconds * PER_HOUR end
|
|
34
|
+
def days() seconds * PER_DAY end
|
|
35
|
+
def weeks() seconds * PER_DAY * 7 end
|
|
36
|
+
def years() seconds * PER_DAY * 365 end
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
38
|
+
def in_years() seconds / PER_DAY / 365 end
|
|
39
|
+
def in_weeks() seconds / PER_DAY / 7 end
|
|
40
|
+
def in_days() seconds / PER_DAY end
|
|
41
|
+
def in_hours() seconds / PER_HOUR end
|
|
42
|
+
def in_minutes() seconds / PER_MINUTE end
|
|
43
|
+
def in_milliseconds() seconds / PER_MILLISECOND end
|
|
44
|
+
def in_microseconds() seconds / PER_MICROSECOND end
|
|
44
45
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
def in_time
|
|
47
|
+
Time.at(self).utc
|
|
48
|
+
end
|
|
48
49
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
50
|
+
def in_seconds(u=nil)
|
|
51
|
+
case u.to_s
|
|
52
|
+
when /\A(y)|(years?)\z/
|
|
53
|
+
years
|
|
54
|
+
when /\A(w)|(weeks?)\z/
|
|
55
|
+
weeks
|
|
56
|
+
when /\A(d)|(days?)\z/
|
|
57
|
+
days
|
|
58
|
+
when /\A(h)|(hours?)\z/
|
|
59
|
+
hours
|
|
60
|
+
when /\A(m)|(minutes?)\z/
|
|
61
|
+
minutes
|
|
62
|
+
when /\A(ms)|(milliseconds?)\z/
|
|
63
|
+
milliseconds
|
|
64
|
+
when /\A(us)|(microseconds?)|(μs)\z/
|
|
65
|
+
microseconds
|
|
66
|
+
else
|
|
67
|
+
self
|
|
68
|
+
end
|
|
67
69
|
end
|
|
68
|
-
end
|
|
69
70
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
71
|
+
## JRuby doesn't like using instance_methods.select here.
|
|
72
|
+
## It could be a bug or something quirky with Attic
|
|
73
|
+
## (although it works in 1.8 and 1.9). The error:
|
|
74
|
+
##
|
|
75
|
+
## lib/attic.rb:32:in `select': yield called out of block (LocalJumpError)
|
|
76
|
+
## lib/stella/mixins/numeric.rb:24
|
|
77
|
+
##
|
|
78
|
+
## Create singular methods, like hour and day.
|
|
79
|
+
# instance_methods.select.each do |plural|
|
|
80
|
+
# singular = plural.to_s.chop
|
|
81
|
+
# alias_method singular, plural
|
|
82
|
+
# end
|
|
82
83
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
84
|
+
alias_method :ms, :milliseconds
|
|
85
|
+
alias_method :'μs', :microseconds
|
|
86
|
+
alias_method :second, :seconds
|
|
87
|
+
alias_method :minute, :minutes
|
|
88
|
+
alias_method :hour, :hours
|
|
89
|
+
alias_method :day, :days
|
|
90
|
+
alias_method :week, :weeks
|
|
91
|
+
alias_method :year, :years
|
|
91
92
|
|
|
93
|
+
end
|
|
92
94
|
end
|
|
93
|
-
end
|
|
94
95
|
|
|
95
|
-
class Numeric
|
|
96
|
-
|
|
96
|
+
class Numeric
|
|
97
|
+
include Time::Units
|
|
97
98
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
99
|
+
def to_ms
|
|
100
|
+
(self*1000.to_f)
|
|
101
|
+
end
|
|
101
102
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
103
|
+
# TODO: Use 1024?
|
|
104
|
+
def to_bytes
|
|
105
|
+
args = case self.abs.to_i
|
|
106
|
+
when (1000)..(1000**2)
|
|
107
|
+
'%3.2f%s' % [(self / 1000.to_f).to_s, 'KB']
|
|
108
|
+
when (1000**2)..(1000**3)
|
|
109
|
+
'%3.2f%s' % [(self / (1000**2).to_f).to_s, 'MB']
|
|
110
|
+
when (1000**3)..(1000**4)
|
|
111
|
+
'%3.2f%s' % [(self / (1000**3).to_f).to_s, 'GB']
|
|
112
|
+
when (1000**4)..(1000**6)
|
|
113
|
+
'%3.2f%s' % [(self / (1000**4).to_f).to_s, 'TB']
|
|
114
|
+
else
|
|
115
|
+
[self.to_i, 'B'].join
|
|
116
|
+
end
|
|
115
117
|
end
|
|
116
118
|
end
|
|
117
119
|
end
|
|
118
|
-
|
data/lib/familia/object.rb
CHANGED
|
@@ -23,7 +23,7 @@ module Familia
|
|
|
23
23
|
!obj.nil? && klass == obj.klass
|
|
24
24
|
end
|
|
25
25
|
define_method :"#{kind}s" do
|
|
26
|
-
names =
|
|
26
|
+
names = redis_objects_order.select { |name| send(:"#{kind}?", name) }
|
|
27
27
|
names.collect! { |name| redis_objects[name] }
|
|
28
28
|
names
|
|
29
29
|
end
|
|
@@ -42,7 +42,12 @@ module Familia
|
|
|
42
42
|
!obj.nil? && klass == obj.klass
|
|
43
43
|
end
|
|
44
44
|
define_method :"class_#{kind}s" do
|
|
45
|
-
names =
|
|
45
|
+
names = class_redis_objects_order.select { |name| ret = send(:"class_#{kind}?", name) }
|
|
46
|
+
# TODO: This returns instances of the RedisObject class which
|
|
47
|
+
# also contain the options. This is different from the instance
|
|
48
|
+
# RedisObjects defined above which returns the OpenStruct of name, klass, and opts.
|
|
49
|
+
#names.collect! { |name| self.send name }
|
|
50
|
+
# OR NOT:
|
|
46
51
|
names.collect! { |name| class_redis_objects[name] }
|
|
47
52
|
names
|
|
48
53
|
end
|
|
@@ -50,10 +55,15 @@ module Familia
|
|
|
50
55
|
|
|
51
56
|
def inherited(obj)
|
|
52
57
|
obj.db = self.db
|
|
53
|
-
obj.ttl = self.ttl
|
|
54
58
|
obj.uri = self.uri
|
|
59
|
+
obj.ttl = self.ttl
|
|
55
60
|
obj.parent = self
|
|
56
|
-
obj.
|
|
61
|
+
obj.class_zset :instances, :class => obj, :reference => true
|
|
62
|
+
# :object is a special redis object because its reserved
|
|
63
|
+
# for storing the marshaled instance data (e.g. to_json).
|
|
64
|
+
# When it isn't defined explicitly we define it here b/c
|
|
65
|
+
# it's assumed to exist in other places (see #save).
|
|
66
|
+
obj.string :object, :class => obj unless obj.redis_object? :object
|
|
57
67
|
Familia.classes << obj
|
|
58
68
|
super(obj)
|
|
59
69
|
end
|
|
@@ -62,15 +72,17 @@ module Familia
|
|
|
62
72
|
obj.ttl = self.ttl
|
|
63
73
|
obj.uri = self.uri
|
|
64
74
|
obj.parent = self
|
|
65
|
-
obj.
|
|
75
|
+
obj.class_zset :instances, :class => obj, :reference => true
|
|
66
76
|
Familia.classes << obj
|
|
67
77
|
end
|
|
68
78
|
|
|
69
79
|
# Creates an instance method called +name+ that
|
|
70
80
|
# returns an instance of the RedisObject +klass+
|
|
71
81
|
def install_redis_object name, klass, opts
|
|
82
|
+
raise ArgumentError, "Name is blank" if name.to_s.empty?
|
|
72
83
|
name = name.to_s.to_sym
|
|
73
84
|
opts ||= {}
|
|
85
|
+
redis_objects_order << name
|
|
74
86
|
redis_objects[name] = OpenStruct.new
|
|
75
87
|
redis_objects[name].name = name
|
|
76
88
|
redis_objects[name].klass = klass
|
|
@@ -79,17 +91,22 @@ module Familia
|
|
|
79
91
|
define_method "#{name}=" do |v|
|
|
80
92
|
self.send(name).replace v
|
|
81
93
|
end
|
|
94
|
+
define_method "#{name}?" do
|
|
95
|
+
!self.send(name).empty?
|
|
96
|
+
end
|
|
82
97
|
redis_objects[name]
|
|
83
98
|
end
|
|
84
99
|
|
|
85
100
|
# Creates a class method called +name+ that
|
|
86
101
|
# returns an instance of the RedisObject +klass+
|
|
87
102
|
def install_class_redis_object name, klass, opts
|
|
103
|
+
raise ArgumentError, "Name is blank" if name.to_s.empty?
|
|
88
104
|
name = name.to_s.to_sym
|
|
89
105
|
opts ||= {}
|
|
90
106
|
opts[:suffix] ||= nil
|
|
91
107
|
opts[:parent] ||= self
|
|
92
|
-
# TODO: investigate metaclass.redis_objects
|
|
108
|
+
# TODO: investigate using metaclass.redis_objects
|
|
109
|
+
class_redis_objects_order << name
|
|
93
110
|
class_redis_objects[name] = OpenStruct.new
|
|
94
111
|
class_redis_objects[name].name = name
|
|
95
112
|
class_redis_objects[name].klass = klass
|
|
@@ -100,6 +117,9 @@ module Familia
|
|
|
100
117
|
metaclass.send :define_method, "#{name}=" do |v|
|
|
101
118
|
send(name).replace v
|
|
102
119
|
end
|
|
120
|
+
metaclass.send :define_method, "#{name}?" do
|
|
121
|
+
!send(name).empty?
|
|
122
|
+
end
|
|
103
123
|
redis_object = klass.new name, opts
|
|
104
124
|
redis_object.freeze
|
|
105
125
|
self.instance_variable_set("@#{name}", redis_object)
|
|
@@ -114,6 +134,7 @@ module Familia
|
|
|
114
134
|
@ttl = v unless v.nil?
|
|
115
135
|
@ttl || (parent ? parent.ttl : nil)
|
|
116
136
|
end
|
|
137
|
+
def ttl=(v) @ttl = v end
|
|
117
138
|
def db v=nil
|
|
118
139
|
@db = v unless v.nil?
|
|
119
140
|
@db || (parent ? parent.db : nil)
|
|
@@ -128,15 +149,13 @@ module Familia
|
|
|
128
149
|
@uri = uri
|
|
129
150
|
end
|
|
130
151
|
def uri(uri=nil)
|
|
131
|
-
self.uri = uri
|
|
132
|
-
|
|
133
|
-
@uri =
|
|
134
|
-
@uri
|
|
135
|
-
Familia.connect @uri #unless Familia.connected?(@uri)
|
|
136
|
-
@uri || (parent ? parent.uri : Familia.uri)
|
|
152
|
+
self.uri = uri if !uri.to_s.empty?
|
|
153
|
+
@uri ||= (parent ? parent.uri : Familia.uri)
|
|
154
|
+
@uri.db = @db if @db && @uri.db.to_s != @db.to_s
|
|
155
|
+
@uri
|
|
137
156
|
end
|
|
138
157
|
def redis
|
|
139
|
-
Familia.redis
|
|
158
|
+
Familia.redis uri
|
|
140
159
|
end
|
|
141
160
|
def flushdb
|
|
142
161
|
Familia.info "flushing #{uri}"
|
|
@@ -145,7 +164,7 @@ module Familia
|
|
|
145
164
|
def keys(suffix=nil)
|
|
146
165
|
self.redis.keys(rediskey('*',suffix)) || []
|
|
147
166
|
end
|
|
148
|
-
def all(suffix
|
|
167
|
+
def all(suffix=:object)
|
|
149
168
|
# objects that could not be parsed will be nil
|
|
150
169
|
keys(suffix).collect { |k| from_key(k) }.compact
|
|
151
170
|
end
|
|
@@ -170,6 +189,10 @@ module Familia
|
|
|
170
189
|
def suffixes
|
|
171
190
|
redis_objects.keys.uniq
|
|
172
191
|
end
|
|
192
|
+
def class_redis_objects_order
|
|
193
|
+
@class_redis_objects_order ||= []
|
|
194
|
+
@class_redis_objects_order
|
|
195
|
+
end
|
|
173
196
|
def class_redis_objects
|
|
174
197
|
@class_redis_objects ||= {}
|
|
175
198
|
@class_redis_objects
|
|
@@ -180,26 +203,20 @@ module Familia
|
|
|
180
203
|
def redis_object? name
|
|
181
204
|
redis_objects.has_key? name.to_s.to_sym
|
|
182
205
|
end
|
|
206
|
+
def redis_objects_order
|
|
207
|
+
@redis_objects_order ||= []
|
|
208
|
+
@redis_objects_order
|
|
209
|
+
end
|
|
183
210
|
def redis_objects
|
|
184
211
|
@redis_objects ||= {}
|
|
185
212
|
@redis_objects
|
|
186
213
|
end
|
|
187
|
-
def create
|
|
188
|
-
me =
|
|
189
|
-
raise "#{self} exists: #{me.
|
|
214
|
+
def create *args
|
|
215
|
+
me = from_array *args
|
|
216
|
+
raise "#{self} exists: #{me.rediskey}" if me.exists?
|
|
190
217
|
me.save
|
|
191
218
|
me
|
|
192
219
|
end
|
|
193
|
-
def load_or_create(id)
|
|
194
|
-
if exists?(id)
|
|
195
|
-
from_redis(id)
|
|
196
|
-
else
|
|
197
|
-
me = new id
|
|
198
|
-
me.save
|
|
199
|
-
me
|
|
200
|
-
end
|
|
201
|
-
end
|
|
202
|
-
|
|
203
220
|
def multiget(*ids)
|
|
204
221
|
ids = rawmultiget(*ids)
|
|
205
222
|
ids.compact.collect { |json| self.from_json(json) }.compact
|
|
@@ -211,49 +228,56 @@ module Familia
|
|
|
211
228
|
ids = self.redis.mget *ids
|
|
212
229
|
end
|
|
213
230
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
231
|
+
# Returns an instance based on +idx+ otherwise it
|
|
232
|
+
# creates and saves a new instance base on +idx+.
|
|
233
|
+
# See from_index
|
|
234
|
+
def load_or_create idx
|
|
235
|
+
return from_redis(idx) if exists?(idx)
|
|
236
|
+
obj = from_index idx
|
|
237
|
+
obj.save
|
|
238
|
+
obj
|
|
239
|
+
end
|
|
240
|
+
# Note +idx+ needs to be an appropriate index for
|
|
241
|
+
# the given class. If the index is multi-value it
|
|
242
|
+
# must be passed as an Array in the proper order.
|
|
243
|
+
# Does not call save.
|
|
244
|
+
def from_index idx
|
|
245
|
+
obj = new
|
|
246
|
+
obj.index = idx
|
|
247
|
+
obj
|
|
248
|
+
end
|
|
249
|
+
def from_key objkey
|
|
250
|
+
raise ArgumentError, "Null key" if objkey.to_s.empty?
|
|
251
|
+
Familia.trace :LOAD, redis, "#{self.uri}/#{objkey}", caller if Familia.debug?
|
|
252
|
+
obj = Familia::String.new objkey, :class => self
|
|
253
|
+
obj.exists? ? obj.value : nil
|
|
254
|
+
end
|
|
255
|
+
def from_redis idx, suffix=:object
|
|
256
|
+
return nil if idx.to_s.empty?
|
|
257
|
+
objkey = rediskey idx, suffix
|
|
258
|
+
Familia.trace :FROMREDIS, Familia.redis(self.uri), objkey, caller.first
|
|
259
|
+
me = from_key objkey
|
|
238
260
|
me
|
|
239
261
|
end
|
|
240
|
-
def exists?
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
ret = Familia.redis(self.uri).exists
|
|
244
|
-
Familia.trace :EXISTS, Familia.redis(self.uri), "#{rediskey(
|
|
262
|
+
def exists? idx, suffix=:object
|
|
263
|
+
return false if idx.to_s.empty?
|
|
264
|
+
objkey = rediskey idx, suffix
|
|
265
|
+
ret = Familia.redis(self.uri).exists objkey
|
|
266
|
+
Familia.trace :EXISTS, Familia.redis(self.uri), "#{rediskey(obj.index, suffix)} #{ret}", caller.first
|
|
245
267
|
ret
|
|
246
268
|
end
|
|
247
|
-
def destroy!
|
|
248
|
-
ret = Familia.redis(self.uri).del rediskey(
|
|
249
|
-
Familia.trace :DELETED, Familia.redis(self.uri), "#{rediskey(
|
|
269
|
+
def destroy! idx, suffix=:object
|
|
270
|
+
ret = Familia.redis(self.uri).del rediskey(idx, suffix)
|
|
271
|
+
Familia.trace :DELETED, Familia.redis(self.uri), "#{rediskey(idx, suffix)}: #{ret}", caller.first
|
|
250
272
|
ret
|
|
251
273
|
end
|
|
252
|
-
def find
|
|
274
|
+
def find suffix='*'
|
|
253
275
|
list = Familia.redis(self.uri).keys(rediskey('*', suffix)) || []
|
|
254
276
|
end
|
|
255
|
-
|
|
277
|
+
# idx can be a value or an Array of values used to create the index.
|
|
278
|
+
def rediskey idx, suffix=nil
|
|
256
279
|
raise RuntimeError, "No index for #{self}" if idx.to_s.empty?
|
|
280
|
+
idx = Familia.join *idx if Array === idx
|
|
257
281
|
idx &&= idx.to_s
|
|
258
282
|
Familia.rediskey(prefix, idx, suffix)
|
|
259
283
|
end
|
|
@@ -271,12 +295,6 @@ module Familia
|
|
|
271
295
|
raise Familia::NonUniqueKey, "Short key returned more than 1 match"
|
|
272
296
|
end
|
|
273
297
|
end
|
|
274
|
-
## TODO: Investigate
|
|
275
|
-
##def float
|
|
276
|
-
## Proc.new do |v|
|
|
277
|
-
## v.nil? ? 0 : v.to_f
|
|
278
|
-
## end
|
|
279
|
-
##end
|
|
280
298
|
end
|
|
281
299
|
|
|
282
300
|
|
|
@@ -288,23 +306,17 @@ module Familia
|
|
|
288
306
|
# must call initialize_redis_objects.
|
|
289
307
|
def initialize *args
|
|
290
308
|
initialize_redis_objects
|
|
291
|
-
|
|
309
|
+
from_array *args if respond_to? :from_array
|
|
310
|
+
init *args if respond_to? :init
|
|
292
311
|
end
|
|
293
312
|
|
|
294
313
|
# This needs to be called in the initialize method of
|
|
295
314
|
# any class that includes Familia.
|
|
296
315
|
def initialize_redis_objects
|
|
297
|
-
# :object is a special redis object because its reserved
|
|
298
|
-
# for storing the marshaled instance data (e.g. to_json).
|
|
299
|
-
# When it isn't defined explicitly we define it here b/c
|
|
300
|
-
# it's assumed to exist in other places (see #save).
|
|
301
|
-
unless self.class.redis_object? :object
|
|
302
|
-
self.class.string :object, :class => self.class
|
|
303
|
-
end
|
|
304
|
-
|
|
305
316
|
# Generate instances of each RedisObject. These need to be
|
|
306
317
|
# unique for each instance of this class so they can refer
|
|
307
|
-
# to the index of this specific instance.
|
|
318
|
+
# to the index of this specific instance.
|
|
319
|
+
#
|
|
308
320
|
# i.e.
|
|
309
321
|
# familia_object.rediskey == v1:bone:INDEXVALUE:object
|
|
310
322
|
# familia_object.redis_object.rediskey == v1:bone:INDEXVALUE:name
|
|
@@ -326,7 +338,8 @@ module Familia
|
|
|
326
338
|
|
|
327
339
|
def redisinfo
|
|
328
340
|
info = {
|
|
329
|
-
:
|
|
341
|
+
:uri => self.class.uri,
|
|
342
|
+
:db => self.class.db,
|
|
330
343
|
:key => rediskey,
|
|
331
344
|
:type => redistype,
|
|
332
345
|
:ttl => realttl
|
|
@@ -363,9 +376,11 @@ module Familia
|
|
|
363
376
|
#Familia.trace :SAVE, Familia.redis(self.class.uri), redisuri, caller.first
|
|
364
377
|
preprocess if respond_to?(:preprocess)
|
|
365
378
|
self.update_time if self.respond_to?(:update_time)
|
|
379
|
+
# TODO: Check here (run checkup)
|
|
366
380
|
ret = self.object.set self # object is a name reserved by Familia
|
|
367
381
|
unless ret.nil?
|
|
368
|
-
|
|
382
|
+
now = Time.now.utc.to_i
|
|
383
|
+
self.class.instances.add now, self # use this set instead of Klass.keys
|
|
369
384
|
self.object.update_expiration self.ttl # does nothing unless if not specified
|
|
370
385
|
end
|
|
371
386
|
true
|
|
@@ -375,7 +390,7 @@ module Familia
|
|
|
375
390
|
if Familia.debug?
|
|
376
391
|
Familia.trace :DELETED, Familia.redis(self.class.uri), "#{rediskey}: #{ret}", caller.first
|
|
377
392
|
end
|
|
378
|
-
self.class.instances.rem
|
|
393
|
+
self.class.instances.rem self if ret > 0
|
|
379
394
|
ret
|
|
380
395
|
end
|
|
381
396
|
def index
|
|
@@ -397,14 +412,39 @@ module Familia
|
|
|
397
412
|
unless self.respond_to? self.class.index
|
|
398
413
|
raise NoIndex, "No such method: `#{self.class.index}' for #{self.class}"
|
|
399
414
|
end
|
|
400
|
-
self.send self.class.index
|
|
415
|
+
self.send( self.class.index)
|
|
401
416
|
end
|
|
402
417
|
else
|
|
403
418
|
raise Familia::NoIndex, self
|
|
404
419
|
end
|
|
405
420
|
end
|
|
406
|
-
def index=(
|
|
407
|
-
|
|
421
|
+
def index=(v)
|
|
422
|
+
case self.class.index
|
|
423
|
+
when Proc
|
|
424
|
+
raise ArgumentError, "Cannot set a Proc index"
|
|
425
|
+
when Array
|
|
426
|
+
unless Array === v && v.size == self.class.index.size
|
|
427
|
+
raise ArgumentError, "Index mismatch (#{v.size} for #{self.class.index.size})"
|
|
428
|
+
end
|
|
429
|
+
parts = self.class.index.each_with_index { |meth,idx|
|
|
430
|
+
unless self.respond_to? "#{meth}="
|
|
431
|
+
raise NoIndex, "No such method: `#{meth}=' for #{self.class}"
|
|
432
|
+
end
|
|
433
|
+
self.send("#{meth}=", v[idx])
|
|
434
|
+
}
|
|
435
|
+
when Symbol, String
|
|
436
|
+
if self.class.redis_object?(self.class.index.to_sym)
|
|
437
|
+
raise Familia::NoIndex, "Cannot use a RedisObject as an index"
|
|
438
|
+
else
|
|
439
|
+
unless self.respond_to? "#{self.class.index}="
|
|
440
|
+
raise NoIndex, "No such method: `#{self.class.index}=' for #{self.class}"
|
|
441
|
+
end
|
|
442
|
+
self.send("#{self.class.index}=", v)
|
|
443
|
+
end
|
|
444
|
+
else
|
|
445
|
+
raise Familia::NoIndex, self
|
|
446
|
+
end
|
|
447
|
+
|
|
408
448
|
end
|
|
409
449
|
def expire(ttl=nil)
|
|
410
450
|
ttl ||= self.class.ttl
|