redis_assist 0.1.0
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/redis_assist/base.rb +383 -0
- data/lib/redis_assist/config.rb +15 -0
- data/lib/redis_assist/transform.rb +37 -0
- data/lib/redis_assist/transforms/boolean_transform.rb +5 -0
- data/lib/redis_assist/transforms/float_transform.rb +5 -0
- data/lib/redis_assist/transforms/integer_transform.rb +5 -0
- data/lib/redis_assist/transforms/json_transform.rb +9 -0
- data/lib/redis_assist/transforms/time_transform.rb +9 -0
- data/lib/redis_assist/version.rb +3 -0
- data/lib/redis_assist.rb +29 -0
- metadata +144 -0
@@ -0,0 +1,383 @@
|
|
1
|
+
module RedisAssist
|
2
|
+
class Base
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def attr_persist(name, opts={})
|
6
|
+
persisted_attrs[name] = opts
|
7
|
+
|
8
|
+
if opts[:as].eql?(:list)
|
9
|
+
define_list(name)
|
10
|
+
elsif opts[:as].eql?(:hash)
|
11
|
+
define_hash(name)
|
12
|
+
else
|
13
|
+
define_field(name)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def find(ids, opts={})
|
18
|
+
ids.is_a?(Array) ? find_by_ids(ids, opts) : find_by_id(ids, opts)
|
19
|
+
end
|
20
|
+
|
21
|
+
# Deprecated finds
|
22
|
+
def find_by_id(id, opts={})
|
23
|
+
raw_attributes = load_attributes(id)
|
24
|
+
return nil unless raw_attributes[id]
|
25
|
+
obj = new(id: id, raw_attributes: raw_attributes[id])
|
26
|
+
(obj.deleted? && !opts[:deleted].eql?(true)) ? nil : obj
|
27
|
+
end
|
28
|
+
|
29
|
+
def find_by_ids(ids, opts={})
|
30
|
+
attrs = load_attributes(*ids)
|
31
|
+
raw_attributes = attrs
|
32
|
+
ids.each_with_object([]) do |id, instances|
|
33
|
+
instance = new(id: id, raw_attributes: raw_attributes[id]) unless raw_attributes[id].nil?
|
34
|
+
instances << instance if instance && (!instance.deleted? || opts[:deleted].eql?(true))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def create(attrs={})
|
39
|
+
roll = new(attrs)
|
40
|
+
roll.save ? roll : false
|
41
|
+
end
|
42
|
+
|
43
|
+
def exists?(id)
|
44
|
+
redis.exists(key_for(id, :attributes))
|
45
|
+
end
|
46
|
+
|
47
|
+
def update(id, params={})
|
48
|
+
record = find(id)
|
49
|
+
return false unless record
|
50
|
+
|
51
|
+
redis.multi do
|
52
|
+
params.each do |attr, val|
|
53
|
+
if persisted_attrs.include?(attr)
|
54
|
+
if fields.keys.include? attr
|
55
|
+
transform(:to, attr, val)
|
56
|
+
redis.hset(key_for(id, :attributes), attr, transform(:to, attr, val))
|
57
|
+
end
|
58
|
+
|
59
|
+
if lists.keys.include? attr
|
60
|
+
redis.del(key_for(id, attr))
|
61
|
+
redis.rpush(key_for(id, attr), val) unless val.empty?
|
62
|
+
end
|
63
|
+
|
64
|
+
if hashes.keys.include? attr
|
65
|
+
redis.del(key_for(id, attr))
|
66
|
+
redis.hmset(key_for(id, attr), *hash_to_redis(val))
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
record.send(:invoke_callback, :after_update)
|
73
|
+
end
|
74
|
+
|
75
|
+
def transform(direction, attr, val)
|
76
|
+
transformer = RedisAssist.transforms[persisted_attrs[attr][:as]]
|
77
|
+
|
78
|
+
if transformer
|
79
|
+
transformer.transform(direction, val)
|
80
|
+
else
|
81
|
+
val || persisted_attrs[attr][:default]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def fields
|
86
|
+
persisted_attrs.select{|k,v| !(v[:as].eql?(:list) || v[:as].eql?(:hash)) }
|
87
|
+
end
|
88
|
+
|
89
|
+
def lists
|
90
|
+
persisted_attrs.select{|k,v| v[:as].eql?(:list) }
|
91
|
+
end
|
92
|
+
|
93
|
+
def hashes
|
94
|
+
persisted_attrs.select{|k,v| v[:as].eql?(:hash) }
|
95
|
+
end
|
96
|
+
|
97
|
+
# TODO: Attribute class
|
98
|
+
def persisted_attrs
|
99
|
+
@persisted_attrs ||= {}
|
100
|
+
end
|
101
|
+
|
102
|
+
def key_for(id, attribute)
|
103
|
+
"#{key_prefix}:#{id}:#{attribute}"
|
104
|
+
end
|
105
|
+
|
106
|
+
def key_prefix(val=nil)
|
107
|
+
return self.key_prefix = val if val
|
108
|
+
return @key_prefix if @key_prefix
|
109
|
+
return self.key_prefix = StringHelper.underscore(name)
|
110
|
+
end
|
111
|
+
|
112
|
+
def key_prefix=(val)
|
113
|
+
@key_prefix = val
|
114
|
+
end
|
115
|
+
|
116
|
+
def redis
|
117
|
+
RedisAssist::Config.redis_client
|
118
|
+
end
|
119
|
+
|
120
|
+
def load_attributes(*ids)
|
121
|
+
future_attrs = {}
|
122
|
+
attrs = {}
|
123
|
+
|
124
|
+
# Load all the futures into an organized Hash
|
125
|
+
redis.pipelined do |pipe|
|
126
|
+
ids.each_with_object(future_attrs) do |id, futures|
|
127
|
+
future_lists = {}
|
128
|
+
future_hashes = {}
|
129
|
+
future_fields = nil
|
130
|
+
|
131
|
+
lists.each do |name, opts|
|
132
|
+
future_lists[name] = pipe.lrange(key_for(id, name), 0, -1)
|
133
|
+
end
|
134
|
+
|
135
|
+
hashes.each do |name, opts|
|
136
|
+
future_hashes[name] = pipe.hgetall(key_for(id, name))
|
137
|
+
end
|
138
|
+
|
139
|
+
future_fields = pipe.hmget(key_for(id, :attributes), fields.keys)
|
140
|
+
|
141
|
+
futures[id] = { lists: future_lists, hashes: future_hashes, fields: future_fields }
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# Remove the empty futures
|
146
|
+
future_attrs = ids.each_with_object({}) do |id, obj|
|
147
|
+
obj[id] = future_attrs[id] unless future_attrs[id][:fields].value.select{|v| !v.nil? }.empty?
|
148
|
+
end
|
149
|
+
|
150
|
+
# Map futures to attributes
|
151
|
+
future_attrs.each_with_object(attrs) do |kv, obj|
|
152
|
+
lists = kv[1][:lists].each_with_object({}){|kv,obj| obj[kv[0]] = kv[1].value unless kv[1].value.nil? }
|
153
|
+
hashes = kv[1][:hashes].each_with_object({}){|kv,obj| obj[kv[0]] = kv[1].value unless kv[1].value.nil?}
|
154
|
+
fields = Hash[*self.fields.keys.zip(kv[1][:fields].value).flatten]
|
155
|
+
obj[kv[0]] = { lists: lists, hashes: hashes, fields: fields }
|
156
|
+
end
|
157
|
+
|
158
|
+
attrs
|
159
|
+
end
|
160
|
+
|
161
|
+
def hash_to_redis(obj)
|
162
|
+
obj.each_with_object([]) {|kv,args| args<<kv[0]<<kv[1] }
|
163
|
+
end
|
164
|
+
|
165
|
+
private
|
166
|
+
|
167
|
+
def define_list(name)
|
168
|
+
define_method(name) do
|
169
|
+
opts = self.class.persisted_attrs[name]
|
170
|
+
self.send("#{name}=", opts[:default]) if !lists[name] && opts[:default]
|
171
|
+
lists[name]
|
172
|
+
end
|
173
|
+
|
174
|
+
define_method("#{name}=") do |val|
|
175
|
+
raise "RedisAssist: tried to store a #{val.class.name} as Array" unless val.is_a?(Array)
|
176
|
+
lists[name] = val
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def define_hash(name)
|
181
|
+
define_method(name) do
|
182
|
+
opts = self.class.persisted_attrs[name]
|
183
|
+
self.send("#{name}=", opts[:default]) if !hashes[name] && opts[:default]
|
184
|
+
hashes[name]
|
185
|
+
end
|
186
|
+
|
187
|
+
define_method("#{name}=") do |val|
|
188
|
+
raise "RedisAssist: tried to store a #{val.class.name} as Hash" unless val.is_a?(Hash)
|
189
|
+
hashes[name] = val
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def define_field(name)
|
194
|
+
define_method(name) do
|
195
|
+
self.class.transform(:from, name, attributes[name])
|
196
|
+
end
|
197
|
+
|
198
|
+
define_method("#{name}=") do |val|
|
199
|
+
attributes[name] = self.class.transform(:to, name, val)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
attr_accessor :attributes
|
205
|
+
attr_reader :id, :errors
|
206
|
+
|
207
|
+
def initialize(attrs={})
|
208
|
+
@attributes = {}
|
209
|
+
self.lists = {}
|
210
|
+
self.hashes = {}
|
211
|
+
self.errors = []
|
212
|
+
|
213
|
+
if attrs[:id]
|
214
|
+
self.id = attrs[:id]
|
215
|
+
load_attributes(attrs[:raw_attributes])
|
216
|
+
end
|
217
|
+
|
218
|
+
return self if id
|
219
|
+
|
220
|
+
self.new_record = true
|
221
|
+
|
222
|
+
invoke_callback(:on_load)
|
223
|
+
|
224
|
+
self.class.persisted_attrs.keys.each do |name|
|
225
|
+
send("#{name}=", attrs[name]) if attrs[name]
|
226
|
+
attrs.delete(name)
|
227
|
+
end
|
228
|
+
|
229
|
+
raise "RedisAssist: #{self.class.name} does not support fields: #{attrs.keys.join(', ')}" if attrs.length > 0
|
230
|
+
end
|
231
|
+
|
232
|
+
def saved?
|
233
|
+
!!(new_record?.eql?(false) && id)
|
234
|
+
end
|
235
|
+
|
236
|
+
def save
|
237
|
+
return false unless valid?
|
238
|
+
|
239
|
+
invoke_callback(:before_update) unless new_record?
|
240
|
+
invoke_callback(:before_create) if new_record?
|
241
|
+
invoke_callback(:before_save)
|
242
|
+
|
243
|
+
# Assing the record with the next available ID
|
244
|
+
self.id = generate_id
|
245
|
+
|
246
|
+
redis.multi do
|
247
|
+
# build the arguments to pass to redis hmset
|
248
|
+
# and insure the fields are explicitely declared
|
249
|
+
attribute_args = hash_to_redis(attributes)
|
250
|
+
|
251
|
+
redis.hmset(key_for(:attributes), *attribute_args)
|
252
|
+
|
253
|
+
lists.each do |name, val|
|
254
|
+
redis.del(key_for(name))
|
255
|
+
redis.rpush(key_for(name), val) if val && !val.empty?
|
256
|
+
end
|
257
|
+
|
258
|
+
hashes.each do |name, val|
|
259
|
+
hash_as_args = hash_to_redis(val)
|
260
|
+
redis.hmset(key_for(name), *hash_as_args)
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
invoke_callback(:after_save)
|
265
|
+
invoke_callback(:after_update) unless new_record?
|
266
|
+
invoke_callback(:after_create) if new_record?
|
267
|
+
|
268
|
+
self
|
269
|
+
end
|
270
|
+
|
271
|
+
def save!
|
272
|
+
raise "RedisAssist: save! failed with errors" unless save
|
273
|
+
self
|
274
|
+
end
|
275
|
+
|
276
|
+
def valid?
|
277
|
+
invoke_callback(:before_validation)
|
278
|
+
validate
|
279
|
+
errors.empty?
|
280
|
+
end
|
281
|
+
|
282
|
+
def validate; end
|
283
|
+
|
284
|
+
# TODO: should this be a redis-assist feature?
|
285
|
+
def deleted?
|
286
|
+
return false unless respond_to?(:deleted_at)
|
287
|
+
deleted_at && deleted_at.is_a?(Time)
|
288
|
+
end
|
289
|
+
|
290
|
+
def delete
|
291
|
+
if respond_to?(:deleted_at)
|
292
|
+
self.deleted_at = Time.now.to_f if respond_to?(:deleted_at)
|
293
|
+
save
|
294
|
+
else
|
295
|
+
redis.pipelined do |pipe|
|
296
|
+
pipe.del(key_for(:attributes))
|
297
|
+
lists.merge(hashes).each do |name|
|
298
|
+
pipe.del(key_for(name))
|
299
|
+
end
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
invoke_callback(:after_delete)
|
304
|
+
self
|
305
|
+
end
|
306
|
+
|
307
|
+
def new_record?
|
308
|
+
!!new_record
|
309
|
+
end
|
310
|
+
|
311
|
+
def redis
|
312
|
+
self.class.redis
|
313
|
+
end
|
314
|
+
|
315
|
+
def add_error(field, message)
|
316
|
+
errors << { field => message }
|
317
|
+
end
|
318
|
+
|
319
|
+
protected
|
320
|
+
|
321
|
+
|
322
|
+
attr_writer :id, :errors
|
323
|
+
attr_accessor :lists, :hashes, :new_record
|
324
|
+
|
325
|
+
def _on_load; end
|
326
|
+
|
327
|
+
def _before_validation
|
328
|
+
self.errors = []
|
329
|
+
end
|
330
|
+
|
331
|
+
def _before_create
|
332
|
+
self.created_at = Time.now.to_f if respond_to?(:created_at)
|
333
|
+
end
|
334
|
+
|
335
|
+
def _before_update
|
336
|
+
self.updated_at = Time.now.to_f if respond_to?(:updated_at)
|
337
|
+
end
|
338
|
+
|
339
|
+
def _after_delete
|
340
|
+
self.deleted_at = Time.now.to_f if respond_to?(:deleted_at)
|
341
|
+
end
|
342
|
+
|
343
|
+
def _after_create
|
344
|
+
self.new_record = false
|
345
|
+
end
|
346
|
+
|
347
|
+
def _before_save; end
|
348
|
+
def _after_save; end
|
349
|
+
def _after_update; end
|
350
|
+
|
351
|
+
|
352
|
+
private
|
353
|
+
|
354
|
+
|
355
|
+
def invoke_callback(callback)
|
356
|
+
send("_#{callback}")
|
357
|
+
send(callback) if respond_to? callback
|
358
|
+
end
|
359
|
+
|
360
|
+
def generate_id
|
361
|
+
redis.incr("#{self.class.key_prefix}:id_sequence")
|
362
|
+
end
|
363
|
+
|
364
|
+
def key_for(attribute)
|
365
|
+
self.class.key_for(id, attribute)
|
366
|
+
end
|
367
|
+
|
368
|
+
def load_attributes(raw_attributes)
|
369
|
+
return nil unless raw_attributes
|
370
|
+
load_response = self.class.load_attributes(id)
|
371
|
+
self.lists = load_response[id][:lists]
|
372
|
+
self.hashes = load_response[id][:hashes]
|
373
|
+
self.attributes = load_response[id][:fields]
|
374
|
+
self.new_record = false
|
375
|
+
end
|
376
|
+
|
377
|
+
##
|
378
|
+
# This converts a hash into args for a redis hmset
|
379
|
+
def hash_to_redis(obj)
|
380
|
+
self.class.hash_to_redis(obj)
|
381
|
+
end
|
382
|
+
end
|
383
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module RedisAssist
|
2
|
+
class Config
|
3
|
+
class << self
|
4
|
+
def redis_client
|
5
|
+
return @redis_client if @redis_client
|
6
|
+
redis_config = { :host => '127.0.0.1', :driver => :hiredis }
|
7
|
+
self.redis_client = Redis.new(redis_config)
|
8
|
+
end
|
9
|
+
|
10
|
+
def redis_client=(val)
|
11
|
+
@redis_client = val
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module RedisAssist
|
2
|
+
def self.register_transform(transform)
|
3
|
+
transforms[transform.key.to_sym] = transform
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.transforms
|
7
|
+
@transforms ||= {}
|
8
|
+
end
|
9
|
+
|
10
|
+
class Transform
|
11
|
+
def self.inherited(base)
|
12
|
+
base.extend ClassMethods
|
13
|
+
RedisAssist.register_transform base
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
def key
|
18
|
+
StringHelper.underscore(name).gsub(/_transform$/, '').to_sym
|
19
|
+
end
|
20
|
+
|
21
|
+
def from(val)
|
22
|
+
val
|
23
|
+
end
|
24
|
+
|
25
|
+
def to(val)
|
26
|
+
val
|
27
|
+
end
|
28
|
+
|
29
|
+
def transform(direction, val)
|
30
|
+
case direction.to_sym
|
31
|
+
when :to then to(val)
|
32
|
+
when :from then from(val)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/redis_assist.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
$LOAD_PATH << File.dirname(__FILE__) unless $LOAD_PATH.include?(File.dirname(__FILE__))
|
2
|
+
|
3
|
+
require 'time'
|
4
|
+
require 'redis'
|
5
|
+
require 'uuid'
|
6
|
+
require 'json'
|
7
|
+
require 'redis_assist/config'
|
8
|
+
require 'redis_assist/transform'
|
9
|
+
require 'redis_assist/base'
|
10
|
+
|
11
|
+
# == Setup & Configuration
|
12
|
+
# RedisAssist depends on the redis-rb gem to communicate with redis.
|
13
|
+
# To configure your redis connection simply pass `RedisAssist` a `Redis` client instance.
|
14
|
+
# RedisAssist::Config.redis_client = Redis.new(redis_config)
|
15
|
+
module RedisAssist
|
16
|
+
module StringHelper
|
17
|
+
def self.underscore(str)
|
18
|
+
str.gsub(/::/, '/').
|
19
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
20
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
21
|
+
tr("-", "_").
|
22
|
+
downcase
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# require all transforms
|
28
|
+
Dir["#{File.dirname(__FILE__)}/redis_assist/transforms/*.rb"].each {|file| require file }
|
29
|
+
|
metadata
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: redis_assist
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Tyler Love
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-04-16 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: redis
|
16
|
+
requirement: &70264080458040 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.0.1
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70264080458040
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: hiredis
|
27
|
+
requirement: &70264080457500 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.4.5
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70264080457500
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: uuid
|
38
|
+
requirement: &70264080456980 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 2.3.6
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70264080456980
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: base62
|
49
|
+
requirement: &70264080456440 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.1.4
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70264080456440
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: bundler
|
60
|
+
requirement: &70264080455960 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '1.0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70264080455960
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rake
|
71
|
+
requirement: &70264080455360 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ~>
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0.9'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *70264080455360
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: yard
|
82
|
+
requirement: &70264080454760 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ~>
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: 0.8.6.1
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *70264080454760
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: rspec
|
93
|
+
requirement: &70264080453820 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ~>
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '2.3'
|
99
|
+
type: :development
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: *70264080453820
|
102
|
+
description: Redis persistant object oriented programming
|
103
|
+
email:
|
104
|
+
- t@tylr.org
|
105
|
+
executables: []
|
106
|
+
extensions: []
|
107
|
+
extra_rdoc_files: []
|
108
|
+
files:
|
109
|
+
- lib/redis_assist/base.rb
|
110
|
+
- lib/redis_assist/config.rb
|
111
|
+
- lib/redis_assist/transform.rb
|
112
|
+
- lib/redis_assist/transforms/boolean_transform.rb
|
113
|
+
- lib/redis_assist/transforms/float_transform.rb
|
114
|
+
- lib/redis_assist/transforms/integer_transform.rb
|
115
|
+
- lib/redis_assist/transforms/json_transform.rb
|
116
|
+
- lib/redis_assist/transforms/time_transform.rb
|
117
|
+
- lib/redis_assist/version.rb
|
118
|
+
- lib/redis_assist.rb
|
119
|
+
homepage: http://github.com/tylr/redis-assist
|
120
|
+
licenses: []
|
121
|
+
post_install_message:
|
122
|
+
rdoc_options: []
|
123
|
+
require_paths:
|
124
|
+
- lib
|
125
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
126
|
+
none: false
|
127
|
+
requirements:
|
128
|
+
- - ! '>='
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '0'
|
131
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
132
|
+
none: false
|
133
|
+
requirements:
|
134
|
+
- - ! '>='
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '0'
|
137
|
+
requirements: []
|
138
|
+
rubyforge_project: redis_assist
|
139
|
+
rubygems_version: 1.8.10
|
140
|
+
signing_key:
|
141
|
+
specification_version: 3
|
142
|
+
summary: Persistant object oriented programming with redis
|
143
|
+
test_files: []
|
144
|
+
has_rdoc:
|