redis-attrs 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +83 -53
- data/lib/redis-attrs.rb +7 -5
- data/lib/redis-attrs/complex.rb +1 -1
- data/lib/redis-attrs/objects_extensions.rb +2 -2
- data/lib/redis-attrs/version.rb +1 -1
- data/redis-attrs.gemspec +2 -1
- data/spec/redis_attrs_spec.rb +67 -62
- data/spec/spec_helper.rb +5 -0
- metadata +25 -3
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Redis::Attrs - Add attributes to Ruby classes backed by Redis
|
2
2
|
|
3
|
+
[![Code Climate](https://codeclimate.com/github/gnapse/redis-attrs.png)](https://codeclimate.com/github/gnapse/redis-attrs)
|
4
|
+
|
3
5
|
This gem is an amalgamation of the ideas found within the [redis_props][redis_props]
|
4
6
|
and [redis-objects][redis-objects] gems, plus a few new ideas here and there. It
|
5
7
|
provides a way to define, on any Ruby class, some attributes that are backed by
|
@@ -33,47 +35,65 @@ Or install it yourself as:
|
|
33
35
|
|
34
36
|
$ gem install redis-attrs
|
35
37
|
|
38
|
+
## Setting up the connection
|
39
|
+
|
40
|
+
You can include some of the following code snippets at the beginning of your
|
41
|
+
app or script. In case you're using Rails, you can use an initializer.
|
42
|
+
|
43
|
+
```ruby
|
44
|
+
# Standard connection
|
45
|
+
Redis::Attrs.redis = Redis.new
|
46
|
+
|
47
|
+
# Connection with specific parameters
|
48
|
+
Redis::Attrs.redis = Redis.new(host: 'hostname', port: 8888, password: 'secret')
|
49
|
+
|
50
|
+
# You can even use a redis namespace
|
51
|
+
Redis::Attrs.redis = Redis::Namespace.new("blah", redis: Redis.new)
|
52
|
+
```
|
53
|
+
|
36
54
|
## Usage
|
37
55
|
|
38
56
|
Start by defining some attributes on your class:
|
39
57
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
58
|
+
```ruby
|
59
|
+
class Film
|
60
|
+
include Redis::Attrs
|
61
|
+
redis_attrs :title => :string, :length => :integer
|
62
|
+
redis_attrs :released_on => :date, :cast => :list
|
44
63
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
64
|
+
# Remember that the objects need an id for this to work
|
65
|
+
attr_reader :id
|
66
|
+
def initialize(id)
|
67
|
+
@id = id
|
68
|
+
end
|
50
69
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
70
|
+
def presentation_title
|
71
|
+
"#{title} (#{released_on.year})"
|
72
|
+
end
|
73
|
+
end
|
74
|
+
```
|
55
75
|
|
56
76
|
Then you can use those attributes as you would regularly, but internally they are
|
57
77
|
reading from and writing to Redis.
|
58
78
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
79
|
+
```ruby
|
80
|
+
>> film = Film.new(3)
|
81
|
+
>> film.title = "Argo"
|
82
|
+
>> film.released_on = "2012-10-12"
|
83
|
+
>> puts film.presentation_title
|
84
|
+
Argo (2012)
|
85
|
+
>> puts film.cast.size
|
86
|
+
0
|
87
|
+
>> film.cast = ["Ben Affleck", "Alan Arkin", "Brian Cranston"]
|
88
|
+
>> puts film.cast.size
|
89
|
+
3
|
90
|
+
>> puts film.cast[-3]
|
91
|
+
Ben Affleck
|
92
|
+
```
|
71
93
|
|
72
94
|
`Redis::Attrs` will work on _any_ class that provides an `id` method that returns
|
73
95
|
a unique value. `Redis::Attrs` will automatically create keys that are unique to
|
74
|
-
each object, in the format:
|
75
|
-
|
76
|
-
class_name:id:attr_name
|
96
|
+
each object, in the format `class_name:id:attr_name`.
|
77
97
|
|
78
98
|
### Supported types
|
79
99
|
|
@@ -97,29 +117,33 @@ The `serialize` and `deserialize` methods define how this process is done. Afte
|
|
97
117
|
registering the type with `Redis::Attrs`, a new attribute is added to the class
|
98
118
|
`Film` defined above.
|
99
119
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
120
|
+
```ruby
|
121
|
+
class JSONScalar < Redis::Attrs::Scalar
|
122
|
+
def serialize(value)
|
123
|
+
value.to_json
|
124
|
+
end
|
104
125
|
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
126
|
+
def deserialize(value)
|
127
|
+
JSON.parse(value)
|
128
|
+
end
|
129
|
+
end
|
109
130
|
|
110
|
-
|
131
|
+
Redis::Attrs.register_type(:json, JSONScalar)
|
111
132
|
|
112
|
-
|
113
|
-
|
114
|
-
|
133
|
+
class Film
|
134
|
+
redis_attrs :director => :json
|
135
|
+
end
|
136
|
+
```
|
115
137
|
|
116
138
|
After the definitions above, more complex data structures could be stored as a single
|
117
139
|
scalar value, by being serialized as JSON.
|
118
140
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
141
|
+
```ruby
|
142
|
+
>> film = Film.new(1)
|
143
|
+
>> film.director = { "first_name" => "Ben", "last_name" => "Affleck" }
|
144
|
+
>> puts Redis::Attrs.redis.get("film:1:director")
|
145
|
+
{"first_name":"Ben","last_name":"Affleck"}
|
146
|
+
```
|
123
147
|
|
124
148
|
### Attribute configuration options
|
125
149
|
|
@@ -127,8 +151,10 @@ The complex attribute types support some configuration options, mostly specific
|
|
127
151
|
each type. When an attribute needs to be configured with some of these options, then
|
128
152
|
it must be declared with the singular version of the method `redis_attrs`, like below:
|
129
153
|
|
130
|
-
|
131
|
-
|
154
|
+
```ruby
|
155
|
+
redis_attr :crawl, :lock, :expiration => 15.minutes
|
156
|
+
redis_attr :cast, :list, :marshal => true
|
157
|
+
```
|
132
158
|
|
133
159
|
For more details about the supported configuration options for each of the complex
|
134
160
|
data types, please refer to the [redis-objects][redis-objects] gem.
|
@@ -139,16 +165,20 @@ There's an attribute configuration option for lists and sets, the `:filter` opti
|
|
139
165
|
that allows the user to define a function that will modify the items upon insertion
|
140
166
|
into the collection.
|
141
167
|
|
142
|
-
|
143
|
-
|
144
|
-
|
168
|
+
```ruby
|
169
|
+
class Film
|
170
|
+
redis_attr :genres, :set, :filter => lambda { |v| v.strip.downcase.gsub(/\s+/, ' ') }
|
171
|
+
end
|
172
|
+
```
|
145
173
|
|
146
174
|
After the above declaration we could do:
|
147
175
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
176
|
+
```ruby
|
177
|
+
>> film = Film.new(1)
|
178
|
+
>> film.genres = ["Action ", " drama", "film Noir", "Drama", "Film noir "]
|
179
|
+
>> puts film.genres.members.sort
|
180
|
+
["action", "drama", "film noir"]
|
181
|
+
```
|
152
182
|
|
153
183
|
## Contributing
|
154
184
|
|
data/lib/redis-attrs.rb
CHANGED
@@ -5,11 +5,11 @@ require "active_support/inflector"
|
|
5
5
|
class Redis
|
6
6
|
module Attrs
|
7
7
|
def self.redis
|
8
|
-
@redis
|
8
|
+
@redis || $redis || Redis.current ||
|
9
|
+
raise(NotConnected, "Redis::Attrs.redis not set to a valid redis connection")
|
9
10
|
end
|
10
11
|
|
11
12
|
def self.redis=(r)
|
12
|
-
raise ArgumentError, "Redis Attrs: Invalid Redis instance" unless r.is_a?(Redis)
|
13
13
|
@redis = r
|
14
14
|
end
|
15
15
|
|
@@ -19,7 +19,7 @@ class Redis
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def redis_key_prefix
|
22
|
-
@redis_key_refix ||= ActiveSupport::Inflector.underscore(
|
22
|
+
@redis_key_refix ||= ActiveSupport::Inflector.underscore(name)
|
23
23
|
end
|
24
24
|
|
25
25
|
def redis_attrs(attrs = nil)
|
@@ -32,7 +32,7 @@ class Redis
|
|
32
32
|
|
33
33
|
def redis_attr(name, type, options = {})
|
34
34
|
@redis_attrs ||= []
|
35
|
-
klass = Redis::Attrs
|
35
|
+
klass = Redis::Attrs.supported_types[type]
|
36
36
|
raise ArgumentError, "Unknown Redis::Attr type #{type}" if klass.nil?
|
37
37
|
attr = klass.new(self, name, type, options)
|
38
38
|
@redis_attrs << attr
|
@@ -73,7 +73,9 @@ class Redis
|
|
73
73
|
def self.register_type(type, klass)
|
74
74
|
type = type.to_sym
|
75
75
|
raise ArgumentError, "Redis attr type #{type} is already defined" if supported_types.include?(type)
|
76
|
-
|
76
|
+
unless klass.ancestors.include?(Scalar)
|
77
|
+
raise ArgumentError, "Class implementing new type #{type} must be a subclass of Redis::Attrs::Scalar"
|
78
|
+
end
|
77
79
|
@supported_types[type] = klass
|
78
80
|
end
|
79
81
|
|
data/lib/redis-attrs/complex.rb
CHANGED
@@ -8,7 +8,7 @@ class Redis
|
|
8
8
|
end
|
9
9
|
|
10
10
|
# Add a member before or after pivot in the list. Redis: LINSERT
|
11
|
-
def insert(where,pivot,value)
|
11
|
+
def insert(where, pivot, value)
|
12
12
|
if options[:filter]
|
13
13
|
value = options[:filter].call(value)
|
14
14
|
pivot = options[:filter].call(pivot)
|
@@ -22,7 +22,7 @@ class Redis
|
|
22
22
|
super
|
23
23
|
end
|
24
24
|
|
25
|
-
def delete(name, count=0)
|
25
|
+
def delete(name, count = 0)
|
26
26
|
name = options[:filter].call(name) if options[:filter]
|
27
27
|
super
|
28
28
|
end
|
data/lib/redis-attrs/version.rb
CHANGED
data/redis-attrs.gemspec
CHANGED
@@ -13,11 +13,12 @@ Gem::Specification.new do |gem|
|
|
13
13
|
gem.homepage = "http://github.com/gnapse/redis-attrs"
|
14
14
|
|
15
15
|
gem.files = `git ls-files`.split($/)
|
16
|
-
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
|
17
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
18
|
gem.require_paths = ["lib"]
|
19
19
|
|
20
20
|
gem.add_development_dependency "rspec"
|
21
|
+
gem.add_development_dependency "rake"
|
21
22
|
gem.add_dependency "redis"
|
22
23
|
gem.add_dependency "activesupport"
|
23
24
|
gem.add_dependency "redis-objects"
|
data/spec/redis_attrs_spec.rb
CHANGED
@@ -26,37 +26,40 @@ describe Redis::Attrs do
|
|
26
26
|
let(:film) { Film.new }
|
27
27
|
|
28
28
|
it "has a version number" do
|
29
|
-
Redis::Attrs::VERSION.
|
29
|
+
expect(Redis::Attrs::VERSION).not_to be_nil
|
30
30
|
end
|
31
31
|
|
32
32
|
context "when included in a class" do
|
33
33
|
it "makes the class respond to .redis_attrs" do
|
34
|
-
Film.
|
34
|
+
expect(Film).to respond_to(:redis_attrs)
|
35
35
|
end
|
36
36
|
|
37
37
|
it "provides the class and its instances with a .redis interface" do
|
38
|
-
Film.
|
39
|
-
film.
|
38
|
+
expect(Film).to respond_to(:redis)
|
39
|
+
expect(film).to respond_to(:redis)
|
40
40
|
|
41
|
-
Film.redis.
|
42
|
-
Film.redis.
|
41
|
+
expect(Film.redis).to be_a(Redis)
|
42
|
+
expect(Film.redis).to equal(film.redis)
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
46
|
describe ".redis_attrs" do
|
47
47
|
it "adds getters and setters for the attributes defined" do
|
48
48
|
%w(title released_on length created_at rating featured).each do |attr|
|
49
|
-
film.
|
50
|
-
film.
|
49
|
+
expect(film).to respond_to(attr)
|
50
|
+
expect(film).to respond_to("#{attr}=")
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
54
|
context "with no paremeters" do
|
55
|
+
let(:attrs) { [:title, :released_on, :length, :created_at, :rating, :featured] }
|
56
|
+
let(:types) { [:string, :date, :integer, :time, :float, :boolean] }
|
57
|
+
|
55
58
|
it "returns a list of all Redis attributes defined for the class" do
|
56
|
-
Film.redis_attrs.
|
57
|
-
Film.redis_attrs.count.
|
58
|
-
Film.redis_attrs.map(&:name).
|
59
|
-
Film.redis_attrs.map(&:type).
|
59
|
+
expect(Film.redis_attrs).to be_a(Array)
|
60
|
+
expect(Film.redis_attrs.count).to eq(6)
|
61
|
+
expect(Film.redis_attrs.map(&:name)).to eq(attrs)
|
62
|
+
expect(Film.redis_attrs.map(&:type)).to eq(types)
|
60
63
|
end
|
61
64
|
end
|
62
65
|
end
|
@@ -64,119 +67,121 @@ describe Redis::Attrs do
|
|
64
67
|
describe "getters" do
|
65
68
|
let(:now) { Time.parse("2013-02-22 22:31:12 -0500") }
|
66
69
|
|
67
|
-
it "
|
68
|
-
film.title.
|
69
|
-
film.released_on.
|
70
|
-
film.length.
|
70
|
+
it "returns nil by default" do
|
71
|
+
expect(film.title).to be_nil
|
72
|
+
expect(film.released_on).to be_nil
|
73
|
+
expect(film.length).to be_nil
|
71
74
|
end
|
72
75
|
|
73
|
-
it "
|
76
|
+
it "returns whatever was last set with the corresponding setter" do
|
74
77
|
film.title = "Argo"
|
75
|
-
film.title.
|
78
|
+
expect(film.title).to eq("Argo")
|
76
79
|
end
|
77
80
|
|
78
|
-
it "
|
81
|
+
it "keeps the original value type" do
|
79
82
|
film.released_on = Date.parse("2012-10-12")
|
80
|
-
film.released_on.
|
83
|
+
expect(film.released_on).to eq(Date.parse("2012-10-12"))
|
81
84
|
film.created_at = now
|
82
|
-
film.created_at.
|
85
|
+
expect(film.created_at).to eq(now)
|
83
86
|
film.length = 135
|
84
|
-
film.length.
|
87
|
+
expect(film.length).to eq(135)
|
85
88
|
film.rating = 8.2
|
86
|
-
film.rating.
|
89
|
+
expect(film.rating).to eq(8.2)
|
87
90
|
film.featured = true
|
88
|
-
film.featured.
|
91
|
+
expect(film.featured).to eq(true)
|
89
92
|
end
|
90
93
|
end
|
91
94
|
|
92
95
|
describe "setters" do
|
93
|
-
it "
|
96
|
+
it "sets the corresponding key in Redis" do
|
94
97
|
film.title = "Argo"
|
95
|
-
redis.get("film:1:title").
|
98
|
+
expect(redis.get("film:1:title")).to eq("Argo")
|
96
99
|
|
97
100
|
film.rating = 8.1
|
98
|
-
redis.get("film:1:rating").
|
101
|
+
expect(redis.get("film:1:rating")).to eq("8.1")
|
99
102
|
end
|
100
103
|
|
101
|
-
it "
|
104
|
+
it "unsets the key when being assigned nil" do
|
102
105
|
film.rating = 8.1
|
103
|
-
redis.keys.
|
106
|
+
expect(redis.keys).to include("film:1:rating")
|
104
107
|
|
105
108
|
film.rating = nil
|
106
|
-
redis.keys.
|
107
|
-
redis.get("film:1:rating").
|
109
|
+
expect(redis.keys).not_to include("film:1:rating")
|
110
|
+
expect(redis.get("film:1:rating")).to be_nil
|
108
111
|
end
|
109
112
|
end
|
110
113
|
|
111
114
|
describe ".register_type" do
|
115
|
+
let(:director) { { first_name: "Ben", last_name: "Affleck" } }
|
116
|
+
|
112
117
|
it "allows to define support for scalar value types not covered by the library" do
|
113
118
|
Redis::Attrs.register_type(:json, JSONScalar)
|
114
119
|
Film.redis_attrs director: :json
|
115
|
-
film.director =
|
116
|
-
redis.keys.
|
117
|
-
redis.get("film:1:director").
|
118
|
-
film.director.
|
120
|
+
film.director = director
|
121
|
+
expect(redis.keys).to include("film:1:director")
|
122
|
+
expect(redis.get("film:1:director")).to eq(director.to_json)
|
123
|
+
expect(film.director).to eq({ "first_name" => "Ben", "last_name" => "Affleck" })
|
119
124
|
end
|
120
125
|
end
|
121
126
|
|
122
127
|
describe "collection attributes" do
|
123
|
-
it "
|
128
|
+
it "supports lists" do
|
124
129
|
Film.redis_attrs cast: :list
|
125
|
-
film.cast.
|
130
|
+
expect(film.cast).to be_empty
|
126
131
|
film.cast = ["Ben Affleck", "Alan Arkin", "John Goodman", "Ben Affleck"]
|
127
|
-
film.cast.size.
|
132
|
+
expect(film.cast.size).to eq(4)
|
128
133
|
end
|
129
134
|
|
130
|
-
it "
|
135
|
+
it "supports hashes" do
|
131
136
|
Film.redis_attrs crew: :hash
|
132
|
-
film.crew.
|
137
|
+
expect(film.crew).to be_empty
|
133
138
|
film.crew = { costume: "John Doe", makeup: "Jane Doe", camera: "James Doe" }
|
134
|
-
film.crew.size.
|
135
|
-
film.crew.keys.
|
139
|
+
expect(film.crew.size).to eq(3)
|
140
|
+
expect(film.crew.keys).to eq(%w(costume makeup camera))
|
136
141
|
end
|
137
142
|
|
138
|
-
it "
|
143
|
+
it "supports sets" do
|
139
144
|
Film.redis_attrs producers: :set
|
140
|
-
film.producers.
|
145
|
+
expect(film.producers).to be_empty
|
141
146
|
film.producers = ["Grant Heslov", "Ben Affleck", "George Clooney", "Ben Affleck"]
|
142
|
-
film.producers.size.
|
147
|
+
expect(film.producers.size).to eq(3)
|
143
148
|
end
|
144
149
|
|
145
|
-
it "
|
150
|
+
it "supports sorted sets" do
|
146
151
|
Film.redis_attrs rankings: :sorted_set
|
147
|
-
film.rankings.
|
152
|
+
expect(film.rankings).to be_empty
|
148
153
|
film.rankings = { "oscars" => 3, "golden globe" => 1, "bafta" => 2 }
|
149
|
-
film.rankings.first.
|
150
|
-
film.rankings.last.
|
151
|
-
film.rankings.members.
|
154
|
+
expect(film.rankings.first).to eq("golden globe")
|
155
|
+
expect(film.rankings.last).to eq("oscars")
|
156
|
+
expect(film.rankings.members).to eq(["golden globe", "bafta", "oscars"])
|
152
157
|
end
|
153
158
|
|
154
|
-
it "
|
159
|
+
it "supports counters" do
|
155
160
|
Film.redis_attrs awards_count: :counter
|
156
|
-
film.awards_count.value.
|
161
|
+
expect(film.awards_count.value).to eq(0)
|
157
162
|
film.awards_count.incr
|
158
|
-
film.awards_count.value.
|
163
|
+
expect(film.awards_count.value).to eq(1)
|
159
164
|
end
|
160
165
|
|
161
|
-
it "
|
166
|
+
it "supports locks" do
|
162
167
|
Film.redis_attrs playing: :lock
|
163
168
|
film.playing.lock { }
|
164
169
|
end
|
165
170
|
|
166
|
-
it "
|
171
|
+
it "supports specifying configuration options" do
|
167
172
|
require "active_support/core_ext/numeric/time"
|
168
|
-
Film.redis_attr :watching, :lock, :
|
169
|
-
film.watching.options[:expiration].
|
173
|
+
Film.redis_attr :watching, :lock, expiration: 3.hours
|
174
|
+
expect(film.watching.options[:expiration]).to eq(3.hours)
|
170
175
|
end
|
171
176
|
|
172
177
|
it "supports filtering the values inserted into a list or set" do
|
173
|
-
Film.redis_attr :genres, :set, filter:
|
178
|
+
Film.redis_attr :genres, :set, filter: ->(genre) { genre.strip.downcase.gsub(/\s+/, ' ') }
|
174
179
|
film.genres = ["Action ", " drama", "film Noir", "Drama", "Film noir "]
|
175
|
-
film.genres.members.sort.
|
180
|
+
expect(film.genres.members.sort).to eq(["action", "drama", "film noir"])
|
176
181
|
film.genres << " ACTION " << "Western"
|
177
|
-
film.genres.
|
178
|
-
film.genres.
|
179
|
-
film.genres.members.sort.
|
182
|
+
expect(film.genres).not_to include("Western")
|
183
|
+
expect(film.genres).to include("western")
|
184
|
+
expect(film.genres.members.sort).to eq(["action", "drama", "film noir", "western"])
|
180
185
|
end
|
181
186
|
end
|
182
187
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis-attrs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-08-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -27,6 +27,22 @@ dependencies:
|
|
27
27
|
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rake
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
30
46
|
- !ruby/object:Gem::Dependency
|
31
47
|
name: redis
|
32
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -118,15 +134,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
118
134
|
- - ! '>='
|
119
135
|
- !ruby/object:Gem::Version
|
120
136
|
version: '0'
|
137
|
+
segments:
|
138
|
+
- 0
|
139
|
+
hash: -3942124308415567947
|
121
140
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
141
|
none: false
|
123
142
|
requirements:
|
124
143
|
- - ! '>='
|
125
144
|
- !ruby/object:Gem::Version
|
126
145
|
version: '0'
|
146
|
+
segments:
|
147
|
+
- 0
|
148
|
+
hash: -3942124308415567947
|
127
149
|
requirements: []
|
128
150
|
rubyforge_project:
|
129
|
-
rubygems_version: 1.8.
|
151
|
+
rubygems_version: 1.8.23
|
130
152
|
signing_key:
|
131
153
|
specification_version: 3
|
132
154
|
summary: Add persistent object attributes backed by redis
|