redismodel 0.1.0 → 0.1.1
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/redismodel.rb +211 -214
- data/test/models/person.rb +1 -1
- metadata +3 -3
data/lib/redismodel.rb
CHANGED
@@ -76,244 +76,241 @@ class RedisModel
|
|
76
76
|
end
|
77
77
|
|
78
78
|
|
79
|
-
|
80
|
-
|
81
|
-
attr_accessor :_data
|
79
|
+
# Local cache of the data
|
80
|
+
attr_accessor :_data
|
82
81
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
end
|
82
|
+
def redis
|
83
|
+
self.class.redis
|
84
|
+
end
|
85
|
+
|
86
|
+
|
87
|
+
def generate_uniq_token
|
88
|
+
"#{MD5.hexdigest("#{self.class.to_s.downcase}-#{self.object_id}-#{rand**rand}-#{Time.now.to_f}")}"
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
# Creates a new object. If `{:id => "..."}` is passed, it'll attempt to recover the record
|
93
|
+
# from the redis DB. If it can't find such a record, it'll raise RedisModel::RecordNotFound
|
94
|
+
def initialize(hash={})
|
95
|
+
@_data = {}
|
96
|
+
if hash[:id].nil?
|
97
|
+
|
98
|
+
self.send("id=", generate_uniq_token)
|
99
|
+
unless self.class.properties[:created_at].nil?
|
100
|
+
set :created_at, DateTime.now
|
101
|
+
end
|
102
|
+
hash.to_a.each do |property|
|
103
|
+
begin
|
104
|
+
self.send("#{property[0]}=", property[1])
|
105
|
+
rescue
|
108
106
|
end
|
109
|
-
|
110
|
-
|
111
|
-
|
107
|
+
end
|
108
|
+
redis.set "#{self.class}:#{id}:id", id
|
109
|
+
redis.incr "#{self.class}:_meta:count"
|
110
|
+
|
111
|
+
else
|
112
|
+
|
113
|
+
self.send("id=", hash[:id])
|
114
|
+
if get(:id).nil?
|
115
|
+
raise RedisModel::InvalidRecord
|
112
116
|
else
|
113
|
-
|
114
|
-
self.send("id=", hash[:id])
|
115
|
-
if get(:id).nil?
|
116
|
-
raise RedisModel::InvalidRecord
|
117
|
-
else
|
118
|
-
self.reload
|
119
|
-
end
|
120
|
-
|
117
|
+
self.reload
|
121
118
|
end
|
119
|
+
|
122
120
|
end
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
self
|
121
|
+
end
|
122
|
+
|
123
|
+
|
124
|
+
# Custom model inspect in the format of:
|
125
|
+
# #<MyModel id: "8a80300a9b3251ec4d930f8ab5e381e2", created_at: "2010-08-01T01:32:11+01:00">
|
126
|
+
def inspect
|
127
|
+
"#<#{self.class} #{self.class.properties.to_a.map{|c| "#{c[0].to_s}: #{get(c[0]).inspect}"}.join(", ")}>"
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
# Updates all keys from redis
|
132
|
+
def reload
|
133
|
+
self.class.properties.each do |property|
|
134
|
+
self.get(property)
|
138
135
|
end
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
redis.
|
136
|
+
self
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
# Permamently deletes all traces of the record, and
|
141
|
+
# decrements the model count
|
142
|
+
def destroy
|
143
|
+
redis.keys("#{self.class}:#{id}:*").each do |key|
|
144
|
+
redis.del key
|
148
145
|
end
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
146
|
+
redis.decr "#{self.class}:_meta:count"
|
147
|
+
end
|
148
|
+
|
149
|
+
|
150
|
+
def id
|
151
|
+
@_data['id']
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
# Setter and getter for the config. Example:
|
156
|
+
#
|
157
|
+
# class MyModel < RedisModel
|
158
|
+
# config :host => "1.2.3.4",
|
159
|
+
# :port => 5678
|
160
|
+
# end
|
161
|
+
#
|
162
|
+
def self.config(hash=nil)
|
163
|
+
@_config ||= DEFAULT_CONFIG
|
164
|
+
if hash.nil?
|
165
|
+
return @_config
|
166
|
+
else
|
167
|
+
@_config = @_config.merge(hash)
|
168
|
+
return true
|
153
169
|
end
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
+
end
|
171
|
+
|
172
|
+
|
173
|
+
# Defines a new property. Example:
|
174
|
+
#
|
175
|
+
# class MyModel < RedisModel
|
176
|
+
# property :name, String
|
177
|
+
# property :age, Integer
|
178
|
+
# end
|
179
|
+
#
|
180
|
+
def self.property(name, type)
|
181
|
+
properties[:id] = String unless properties[:id]
|
182
|
+
properties[name] = type
|
183
|
+
class_eval do
|
184
|
+
define_method("#{name}=") do |str|
|
185
|
+
set(name, str)
|
170
186
|
end
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
#
|
181
|
-
def self.property(name, type)
|
182
|
-
properties[:id] = String unless properties[:id]
|
183
|
-
properties[name] = type
|
184
|
-
class_eval do
|
185
|
-
define_method("#{name}=") do |str|
|
186
|
-
set(name, str)
|
187
|
-
end
|
188
|
-
|
189
|
-
if type == Array || type == Hash
|
190
|
-
proxy = (type == Array) ? ArrayProxy : HashProxy
|
191
|
-
define_method(name) do
|
192
|
-
value = get(name)
|
193
|
-
return value if value.is_a?(proxy)
|
194
|
-
value.tap do |value|
|
195
|
-
value.extend(proxy).instance_variable_set(:@__model__, self)
|
196
|
-
value.extend(proxy).instance_variable_set(:@__property__, name)
|
197
|
-
end
|
198
|
-
end
|
199
|
-
else
|
200
|
-
define_method(name) do
|
201
|
-
get(name)
|
187
|
+
|
188
|
+
if type == Array || type == Hash
|
189
|
+
proxy = (type == Array) ? ArrayProxy : HashProxy
|
190
|
+
define_method(name) do
|
191
|
+
value = get(name)
|
192
|
+
return value if value.is_a?(proxy)
|
193
|
+
value.tap do |value|
|
194
|
+
value.extend(proxy).instance_variable_set(:@__model__, self)
|
195
|
+
value.extend(proxy).instance_variable_set(:@__property__, name)
|
202
196
|
end
|
203
197
|
end
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
# Returns all records
|
211
|
-
def self.all
|
212
|
-
arr = []
|
213
|
-
redis.keys("#{klass}:*:id").each do |key|
|
214
|
-
arr << klass.find( key.split(":")[1] )
|
198
|
+
else
|
199
|
+
define_method(name) do
|
200
|
+
get(name)
|
201
|
+
end
|
215
202
|
end
|
216
|
-
|
203
|
+
|
204
|
+
eval "def self.find_by_#{name.to_s}(str); self.search('#{name.to_s}', str); end"
|
217
205
|
end
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
206
|
+
end
|
207
|
+
|
208
|
+
|
209
|
+
# Returns all records
|
210
|
+
def self.all
|
211
|
+
arr = []
|
212
|
+
redis.keys("#{klass}:*:id").each do |key|
|
213
|
+
arr << klass.find( key.split(":")[1] )
|
223
214
|
end
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
215
|
+
arr.sort_by{|m| m.send( DEFAULT_CONFIG[:default_sort] )}
|
216
|
+
end
|
217
|
+
|
218
|
+
|
219
|
+
# Finds a record from it's id
|
220
|
+
def self.find(id)
|
221
|
+
object = klass.new(:id => id)
|
222
|
+
end
|
223
|
+
|
224
|
+
|
225
|
+
# Returns all records where the value of `property` matches `str`
|
226
|
+
def self.search(property, value)
|
227
|
+
arr = []
|
228
|
+
self.all.each do |record|
|
229
|
+
if record.send(property) == value
|
230
|
+
arr << record
|
233
231
|
end
|
234
|
-
arr
|
235
232
|
end
|
236
|
-
|
233
|
+
arr
|
234
|
+
end
|
235
|
+
|
237
236
|
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
end
|
243
|
-
true
|
237
|
+
# Permamently deletes all records for the model
|
238
|
+
def self.destroy_all
|
239
|
+
redis.keys("#{klass}:*").each do |key|
|
240
|
+
redis.del key
|
244
241
|
end
|
242
|
+
true
|
243
|
+
end
|
245
244
|
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
end
|
252
|
-
end
|
253
|
-
|
254
|
-
|
255
|
-
# Returns the number of records for the model
|
256
|
-
def self.count
|
257
|
-
redis.get("#{klass}:_meta:count").to_i
|
245
|
+
|
246
|
+
# Destroys all records with the ids passed
|
247
|
+
def self.destroy(*ids)
|
248
|
+
ids.each do |id|
|
249
|
+
klass.find(id).destroy
|
258
250
|
end
|
251
|
+
end
|
252
|
+
|
253
|
+
|
254
|
+
# Returns the number of records for the model
|
255
|
+
def self.count
|
256
|
+
redis.get("#{klass}:_meta:count").to_i
|
257
|
+
end
|
259
258
|
|
260
259
|
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
260
|
+
# Saves the Redis database to disk
|
261
|
+
def self.save!
|
262
|
+
redis.bgsave == "Background saving started"
|
263
|
+
end
|
265
264
|
|
266
265
|
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
end
|
279
|
-
end
|
280
|
-
|
281
|
-
# Fetches the value of `property` from redis
|
282
|
-
def get(property)
|
283
|
-
c = self.class.type(property)
|
284
|
-
value = RedisModel.cast c, redis.get("#{self.class}:#{id}:#{property}")
|
285
|
-
@_data[property] = value
|
286
|
-
end
|
287
|
-
|
288
|
-
|
289
|
-
# Returns the class of the extended model
|
290
|
-
def self.klass
|
291
|
-
@klass ||= self.ancestors.first
|
292
|
-
end
|
293
|
-
|
294
|
-
|
295
|
-
# Returns the property class declared in #property above
|
296
|
-
def self.type(property)
|
297
|
-
properties[property]
|
298
|
-
end
|
299
|
-
|
300
|
-
|
301
|
-
# Keeps track of the properties declared via #property
|
302
|
-
def self.properties
|
303
|
-
@_properties ||= {}
|
304
|
-
end
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
# Alias for RedisModel#connection
|
309
|
-
def self.redis
|
310
|
-
RedisModel.connection(klass)
|
311
|
-
end
|
312
|
-
|
313
|
-
|
314
|
-
def id=(str)
|
315
|
-
@_data['id'] = str
|
266
|
+
protected
|
267
|
+
|
268
|
+
# Writes a property value to redis, and updates #updated_at if required.
|
269
|
+
def set(property, value)
|
270
|
+
c = self.class.type(property)
|
271
|
+
value = RedisModel.cast c, value
|
272
|
+
redis.set "#{self.class}:#{id}:#{property}", value
|
273
|
+
@_data[property] = value
|
274
|
+
|
275
|
+
unless property == :updated_at && !self.class.properties[:updated_at].nil?
|
276
|
+
set :updated_at, DateTime.now
|
316
277
|
end
|
317
|
-
|
278
|
+
end
|
279
|
+
|
280
|
+
# Fetches the value of `property` from redis
|
281
|
+
def get(property)
|
282
|
+
c = self.class.type(property)
|
283
|
+
value = RedisModel.cast c, redis.get("#{self.class}:#{id}:#{property}")
|
284
|
+
@_data[property] = value
|
285
|
+
end
|
286
|
+
|
287
|
+
|
288
|
+
# Returns the class of the extended model
|
289
|
+
def self.klass
|
290
|
+
@klass ||= self.ancestors.first
|
291
|
+
end
|
292
|
+
|
293
|
+
|
294
|
+
# Returns the property class declared in #property above
|
295
|
+
def self.type(property)
|
296
|
+
properties[property]
|
297
|
+
end
|
298
|
+
|
299
|
+
|
300
|
+
# Keeps track of the properties declared via #property
|
301
|
+
def self.properties
|
302
|
+
@_properties ||= {}
|
303
|
+
end
|
304
|
+
|
305
|
+
|
306
|
+
|
307
|
+
# Alias for RedisModel#connection
|
308
|
+
def self.redis
|
309
|
+
RedisModel.connection(klass)
|
310
|
+
end
|
311
|
+
|
312
|
+
|
313
|
+
def id=(str)
|
314
|
+
@_data['id'] = str
|
318
315
|
end
|
319
316
|
end
|
data/test/models/person.rb
CHANGED
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
|
-
-
|
9
|
-
version: 0.1.
|
8
|
+
- 1
|
9
|
+
version: 0.1.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Ashley Williams
|
@@ -31,7 +31,7 @@ dependencies:
|
|
31
31
|
version: 2.0.4
|
32
32
|
type: :runtime
|
33
33
|
version_requirements: *id001
|
34
|
-
description: Syncs ruby objects
|
34
|
+
description: Syncs you ruby objects to Redis
|
35
35
|
email: a.j.r.williams@gmail.com
|
36
36
|
executables: []
|
37
37
|
|