redis-session-store 0.4.2 → 0.5.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +103 -0
- data/README.md +34 -10
- data/lib/redis-session-store.rb +37 -17
- data/spec/redis_session_store_spec.rb +46 -9
- metadata +23 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9148a3bedfc1ab56951717dccdaed7c30e33e356
|
4
|
+
data.tar.gz: ca00490849f6276f4262ddfa100fa8d90c819087
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fdbe30259d8e8eb71a650a73c59f613f830276f913d0e5bd062b5212db29704aa3ff56d7b5d443e95fabdd441085065a5ca8b02aa0c4b998264c3efeb4685cd9
|
7
|
+
data.tar.gz: ad31abd62bb1eb5b093aa03ba1e0f2c11bc197e3e3ff395bb78dabfb1d7659ef2a06f05435cd03a3db060510700a8a1f4ca509cd6561849e017de2014f2e068c
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
redis-session-store history
|
2
|
+
===========================
|
3
|
+
|
4
|
+
## v0.5.0 (2014-03-16)
|
5
|
+
|
6
|
+
* Keep generating session IDs until one is found that doesn't collide
|
7
|
+
with existing session IDs
|
8
|
+
* Add support for `on_sid_collision` handler option
|
9
|
+
* Add support for `on_redis_down` handler option
|
10
|
+
* **BACKWARD INCOMPATIBLE** Drop support for `:raise_errors` option
|
11
|
+
|
12
|
+
## v0.4.2 (2014-03-14)
|
13
|
+
|
14
|
+
* Renaming `load_session` method to not conflict with AbstractStore
|
15
|
+
|
16
|
+
## v0.4.1 (yanked) (2014-03-13)
|
17
|
+
|
18
|
+
* Regenerate session ID when session is missing
|
19
|
+
|
20
|
+
## v0.4.0 (2014-02-19)
|
21
|
+
|
22
|
+
* Add support for `ENV_SESSION_OPTIONS_KEY` rack env option
|
23
|
+
* Add support for `:raise_errors` session option (kinda like Dalli)
|
24
|
+
* Increasing test coverage
|
25
|
+
|
26
|
+
## v0.3.1 (2014-02-19)
|
27
|
+
|
28
|
+
* Add `#destroy_session` method
|
29
|
+
* Clean up remaining RuboCop offenses
|
30
|
+
* Documentation updates
|
31
|
+
|
32
|
+
## v0.3.0 (2014-02-13)
|
33
|
+
|
34
|
+
* Rails 3 compatibility
|
35
|
+
* Switch from minitest to rspec
|
36
|
+
* Add test coverage
|
37
|
+
* RuboCop cleanup
|
38
|
+
|
39
|
+
## v0.2.4 (2014-03-16)
|
40
|
+
|
41
|
+
* Keep generating session IDs until one is found that doesn't collide
|
42
|
+
with existing session IDs
|
43
|
+
|
44
|
+
## v0.2.3 (2014-03-14)
|
45
|
+
|
46
|
+
* Renaming `load_session` method to not conflict with AbstractStore
|
47
|
+
|
48
|
+
## v0.2.2 (yanked) (2014-03-13)
|
49
|
+
|
50
|
+
* Regenerate session ID when session is missing
|
51
|
+
|
52
|
+
## v0.2.1 (2013-09-17)
|
53
|
+
|
54
|
+
* Add explicit MIT license metadata in gemspec
|
55
|
+
|
56
|
+
## v0.2.0 (2013-09-13)
|
57
|
+
|
58
|
+
* Use `@redis.setex` when expiry provided, else `@redis.set`
|
59
|
+
* Gemfile, gemspec, and git updates
|
60
|
+
* Nest redis-specific options inside a `:redis` key of session options
|
61
|
+
* Add `#destroy` method
|
62
|
+
* Rescue only `Errno::ECONNREFUSED` exceptions
|
63
|
+
* Handle `nil` cookies during `#destroy`
|
64
|
+
* Add Travis integration
|
65
|
+
* Add some minimal tests to ensure backward compatibility session options
|
66
|
+
|
67
|
+
## v0.1.9 (2012-03-06)
|
68
|
+
|
69
|
+
## v0.1.8 (2010-12-09)
|
70
|
+
|
71
|
+
* Remove use of `@redis.pipelined`
|
72
|
+
|
73
|
+
## v0.1.7 (2010-12-08)
|
74
|
+
|
75
|
+
* Using latest redis gem API
|
76
|
+
|
77
|
+
## v0.1.6 (2010-04-18)
|
78
|
+
|
79
|
+
* Using pipelined format with `set` and `expire`
|
80
|
+
* Changing default port from 6370 to 6379
|
81
|
+
|
82
|
+
## v0.1.5 (2010-04-07)
|
83
|
+
|
84
|
+
## v0.1.4 (2010-03-26)
|
85
|
+
|
86
|
+
* Changed redis parameter from `:server` to `:host`
|
87
|
+
|
88
|
+
## v0.1.3 (2009-12-30)
|
89
|
+
|
90
|
+
* Documentation updates
|
91
|
+
|
92
|
+
## v0.1.2 (2009-12-30)
|
93
|
+
|
94
|
+
* Documentation updates
|
95
|
+
|
96
|
+
## v0.1.1 (2009-12-30)
|
97
|
+
|
98
|
+
* library file renamed to `redis-session-store.rb` to play nicely with
|
99
|
+
rails require
|
100
|
+
|
101
|
+
## v0.1 (2009-12-30)
|
102
|
+
|
103
|
+
* first working version
|
data/README.md
CHANGED
@@ -19,8 +19,8 @@ only suitable for Rails applications. For other frameworks or
|
|
19
19
|
drop-in support for caching, check out
|
20
20
|
[redis-store](http://github.com/jodosha/redis-store/)
|
21
21
|
|
22
|
-
Compatibility
|
23
|
-
|
22
|
+
Rails 2 Compatibility
|
23
|
+
---------------------
|
24
24
|
|
25
25
|
This gem is currently only compatible with Rails 3+. If you need
|
26
26
|
Rails 2 compatibility, be sure to pin to a lower version like so:
|
@@ -44,17 +44,41 @@ In your Rails app, throw in an initializer with the following contents:
|
|
44
44
|
|
45
45
|
``` ruby
|
46
46
|
My::Application.config.session_store = :redis_session_store, {
|
47
|
-
:
|
48
|
-
:
|
49
|
-
:
|
50
|
-
:
|
51
|
-
:
|
52
|
-
:
|
53
|
-
:
|
47
|
+
key: 'your_session_key',
|
48
|
+
redis: {
|
49
|
+
db: 2,
|
50
|
+
expire_after: 120.minutes,
|
51
|
+
key_prefix: 'myapp:session:',
|
52
|
+
host: 'host', # Redis host name, default is localhost
|
53
|
+
port: 12345 # Redis port, default is 6379
|
54
54
|
}
|
55
55
|
}
|
56
56
|
```
|
57
|
-
|
57
|
+
|
58
|
+
### Session ID collision handling
|
59
|
+
|
60
|
+
If you want to handle cases where the generated session ID (sid)
|
61
|
+
collides with an existing session ID, a custom callable handler may be
|
62
|
+
provided as `on_sid_collision`:
|
63
|
+
|
64
|
+
``` ruby
|
65
|
+
My::Application.config.session_store = :redis_session_store, {
|
66
|
+
# ... other options ...
|
67
|
+
on_sid_collision: ->(sid) { Rails.logger.warn("SID collision! #{sid}") }
|
68
|
+
}
|
69
|
+
```
|
70
|
+
|
71
|
+
### Redis unavailability handling
|
72
|
+
|
73
|
+
If you want to handle cases where Redis is unavailable, a custom
|
74
|
+
callable handler may be provided as `on_redis_down`:
|
75
|
+
|
76
|
+
``` ruby
|
77
|
+
My::Application.config.session_store = :redis_session_store, {
|
78
|
+
# ... other options ...
|
79
|
+
on_redis_down: ->(e, env, sid) { do_something_will_ya!(e) }
|
80
|
+
}
|
81
|
+
```
|
58
82
|
|
59
83
|
Contributing, Authors, & License
|
60
84
|
--------------------------------
|
data/lib/redis-session-store.rb
CHANGED
@@ -4,7 +4,7 @@ require 'redis'
|
|
4
4
|
# Redis session storage for Rails, and for Rails only. Derived from
|
5
5
|
# the MemCacheStore code, simply dropping in Redis instead.
|
6
6
|
class RedisSessionStore < ActionDispatch::Session::AbstractStore
|
7
|
-
VERSION = '0.
|
7
|
+
VERSION = '0.5.0'
|
8
8
|
|
9
9
|
# ==== Options
|
10
10
|
# * +:key+ - Same as with the other cookie stores, key name
|
@@ -14,18 +14,22 @@ class RedisSessionStore < ActionDispatch::Session::AbstractStore
|
|
14
14
|
# * +:db+ - Database number, defaults to 0.
|
15
15
|
# * +:key_prefix+ - Prefix for keys used in Redis, e.g. +myapp:+
|
16
16
|
# * +:expire_after+ - A number in seconds for session timeout
|
17
|
+
# * +:on_sid_collision:+ - Called with SID string when generated SID collides
|
18
|
+
# * +:on_redis_down:+ - Called with err, env, and SID on Errno::ECONNREFUSED
|
17
19
|
#
|
18
20
|
# ==== Examples
|
19
21
|
#
|
20
22
|
# My::Application.config.session_store = :redis_session_store, {
|
21
|
-
# :
|
22
|
-
# :
|
23
|
-
# :
|
24
|
-
# :
|
25
|
-
# :
|
26
|
-
# :
|
27
|
-
# :
|
28
|
-
# }
|
23
|
+
# key: 'your_session_key',
|
24
|
+
# redis: {
|
25
|
+
# db: 2,
|
26
|
+
# expire_after: 120.minutes,
|
27
|
+
# key_prefix: 'myapp:session:',
|
28
|
+
# host: 'host', # Redis host name, default is localhost
|
29
|
+
# port: 12345 # Redis port, default is 6379
|
30
|
+
# },
|
31
|
+
# on_sid_collision: ->(sid) { logger.warn("SID collision! #{sid}") },
|
32
|
+
# on_redis_down: ->(*a) { logger.error("Redis down! #{a.inspect}") }
|
29
33
|
# }
|
30
34
|
#
|
31
35
|
def initialize(app, options = {})
|
@@ -36,17 +40,33 @@ class RedisSessionStore < ActionDispatch::Session::AbstractStore
|
|
36
40
|
@default_options.merge!(namespace: 'rack:session')
|
37
41
|
@default_options.merge!(redis_options)
|
38
42
|
@redis = Redis.new(redis_options)
|
39
|
-
@
|
43
|
+
@on_sid_collision = options[:on_sid_collision]
|
44
|
+
@on_redis_down = options[:on_redis_down]
|
40
45
|
end
|
41
46
|
|
47
|
+
attr_accessor :on_sid_collision, :on_redis_down
|
48
|
+
|
42
49
|
private
|
43
50
|
|
44
|
-
attr_reader :redis, :key, :default_options
|
51
|
+
attr_reader :redis, :key, :default_options
|
45
52
|
|
46
53
|
def prefixed(sid)
|
47
54
|
"#{default_options[:key_prefix]}#{sid}"
|
48
55
|
end
|
49
56
|
|
57
|
+
def generate_sid
|
58
|
+
loop do
|
59
|
+
sid = super
|
60
|
+
break sid unless sid_collision?(sid)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def sid_collision?(sid)
|
65
|
+
!!redis.get(prefixed(sid)).tap do |value| # rubocop: disable DoubleNegation
|
66
|
+
on_sid_collision.call(sid) if value && on_sid_collision
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
50
70
|
def get_session(env, sid)
|
51
71
|
unless sid && (session = load_session_from_redis(sid))
|
52
72
|
sid = generate_sid
|
@@ -55,7 +75,7 @@ class RedisSessionStore < ActionDispatch::Session::AbstractStore
|
|
55
75
|
|
56
76
|
[sid, session]
|
57
77
|
rescue Errno::ECONNREFUSED => e
|
58
|
-
|
78
|
+
on_redis_down.call(e, env, sid) if on_redis_down
|
59
79
|
[generate_sid, {}]
|
60
80
|
end
|
61
81
|
|
@@ -73,7 +93,7 @@ class RedisSessionStore < ActionDispatch::Session::AbstractStore
|
|
73
93
|
end
|
74
94
|
return sid
|
75
95
|
rescue Errno::ECONNREFUSED => e
|
76
|
-
|
96
|
+
on_redis_down.call(e, env, sid) if on_redis_down
|
77
97
|
return false
|
78
98
|
end
|
79
99
|
|
@@ -84,12 +104,12 @@ class RedisSessionStore < ActionDispatch::Session::AbstractStore
|
|
84
104
|
end
|
85
105
|
|
86
106
|
def destroy(env)
|
87
|
-
if env['rack.request.cookie_hash'] &&
|
88
|
-
|
107
|
+
if env['rack.request.cookie_hash'] &&
|
108
|
+
(sid = env['rack.request.cookie_hash'][key])
|
109
|
+
redis.del(prefixed(sid))
|
89
110
|
end
|
90
111
|
rescue Errno::ECONNREFUSED => e
|
91
|
-
|
92
|
-
Rails.logger.warn("RedisSessionStore#destroy: #{e.message}")
|
112
|
+
on_redis_down.call(e, env, sid) if on_redis_down
|
93
113
|
false
|
94
114
|
end
|
95
115
|
end
|
@@ -135,15 +135,23 @@ describe RedisSessionStore do
|
|
135
135
|
end
|
136
136
|
|
137
137
|
context 'when redis is down' do
|
138
|
-
before
|
138
|
+
before do
|
139
|
+
store.stub(:redis).and_raise(Errno::ECONNREFUSED)
|
140
|
+
store.on_redis_down = ->(*a) { @redis_down_handled = true }
|
141
|
+
end
|
139
142
|
|
140
143
|
it 'returns false' do
|
141
144
|
store.send(:set_session, env, session_id, session_data, options)
|
142
145
|
.should eq(false)
|
143
146
|
end
|
144
147
|
|
145
|
-
|
146
|
-
|
148
|
+
it 'calls the on_redis_down handler' do
|
149
|
+
store.send(:set_session, env, session_id, session_data, options)
|
150
|
+
expect(@redis_down_handled).to be_true
|
151
|
+
end
|
152
|
+
|
153
|
+
context 'when :on_redis_down re-raises' do
|
154
|
+
before { store.on_redis_down = ->(e, *) { fail e } }
|
147
155
|
|
148
156
|
it 'explodes' do
|
149
157
|
expect do
|
@@ -160,11 +168,13 @@ describe RedisSessionStore do
|
|
160
168
|
key_prefix: 'customprefix::'
|
161
169
|
}
|
162
170
|
end
|
171
|
+
|
163
172
|
let(:fake_key) { 'thisisarediskey' }
|
164
173
|
|
165
174
|
it 'should retrieve the prefixed key from redis' do
|
166
175
|
redis = double('redis')
|
167
176
|
store.stub(redis: redis)
|
177
|
+
store.stub(generate_sid: fake_key)
|
168
178
|
expect(redis).to receive(:get).with("#{options[:key_prefix]}#{fake_key}")
|
169
179
|
|
170
180
|
store.send(:get_session, double('env'), fake_key)
|
@@ -186,8 +196,8 @@ describe RedisSessionStore do
|
|
186
196
|
.to eq('foop')
|
187
197
|
end
|
188
198
|
|
189
|
-
context 'when :
|
190
|
-
|
199
|
+
context 'when :on_redis_down re-raises' do
|
200
|
+
before { store.on_redis_down = ->(e, *) { fail e } }
|
191
201
|
|
192
202
|
it 'explodes' do
|
193
203
|
expect do
|
@@ -224,8 +234,8 @@ describe RedisSessionStore do
|
|
224
234
|
expect(store.send(:destroy, env)).to be_false
|
225
235
|
end
|
226
236
|
|
227
|
-
context 'when :
|
228
|
-
|
237
|
+
context 'when :on_redis_down re-raises' do
|
238
|
+
before { store.on_redis_down = ->(e, *) { fail e } }
|
229
239
|
|
230
240
|
it 'explodes' do
|
231
241
|
expect do
|
@@ -238,13 +248,40 @@ describe RedisSessionStore do
|
|
238
248
|
|
239
249
|
context 'when destroyed via #destroy_session' do
|
240
250
|
it 'deletes the prefixed key from redis' do
|
241
|
-
redis = double('redis')
|
242
|
-
sid = store.send(:generate_sid)
|
251
|
+
redis = double('redis', get: nil)
|
243
252
|
store.stub(redis: redis)
|
253
|
+
sid = store.send(:generate_sid)
|
244
254
|
expect(redis).to receive(:del).with("#{options[:key_prefix]}#{sid}")
|
245
255
|
|
246
256
|
store.send(:destroy_session, {}, sid, nil)
|
247
257
|
end
|
248
258
|
end
|
249
259
|
end
|
260
|
+
|
261
|
+
describe 'generating a sid' do
|
262
|
+
before { store.on_sid_collision = ->(sid) { @sid = sid } }
|
263
|
+
|
264
|
+
context 'when the generated sid is unique' do
|
265
|
+
before do
|
266
|
+
redis = double('redis', get: nil)
|
267
|
+
store.stub(redis: redis)
|
268
|
+
end
|
269
|
+
|
270
|
+
it 'returns the sid' do
|
271
|
+
expect(store.send(:generate_sid)).to_not be_nil
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
context 'when there is a generated sid collision' do
|
276
|
+
before do
|
277
|
+
redis = double('redis', get: 'herp a derp')
|
278
|
+
store.stub(redis: redis)
|
279
|
+
end
|
280
|
+
|
281
|
+
it 'passes the colliding sid to the collision handler' do
|
282
|
+
store.send(:sid_collision?, 'whatever')
|
283
|
+
expect(@sid).to eql('whatever')
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
250
287
|
end
|
metadata
CHANGED
@@ -1,97 +1,97 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis-session-store
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mathias Meyer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-03-
|
11
|
+
date: 2014-03-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: fakeredis
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- -
|
45
|
+
- - ">="
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- -
|
52
|
+
- - ">="
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rspec
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- -
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- -
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rubocop
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: simplecov
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- -
|
87
|
+
- - ">="
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- -
|
94
|
+
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
description: A drop-in replacement for e.g. MemCacheStore to store Rails sessions
|
@@ -105,12 +105,13 @@ extra_rdoc_files:
|
|
105
105
|
- AUTHORS.md
|
106
106
|
- CONTRIBUTING.md
|
107
107
|
files:
|
108
|
-
- .gitignore
|
109
|
-
- .rspec
|
110
|
-
- .rubocop.yml
|
111
|
-
- .simplecov
|
112
|
-
- .travis.yml
|
108
|
+
- ".gitignore"
|
109
|
+
- ".rspec"
|
110
|
+
- ".rubocop.yml"
|
111
|
+
- ".simplecov"
|
112
|
+
- ".travis.yml"
|
113
113
|
- AUTHORS.md
|
114
|
+
- CHANGELOG.md
|
114
115
|
- CONTRIBUTING.md
|
115
116
|
- Gemfile
|
116
117
|
- LICENSE
|
@@ -131,17 +132,17 @@ require_paths:
|
|
131
132
|
- lib
|
132
133
|
required_ruby_version: !ruby/object:Gem::Requirement
|
133
134
|
requirements:
|
134
|
-
- -
|
135
|
+
- - ">="
|
135
136
|
- !ruby/object:Gem::Version
|
136
137
|
version: '0'
|
137
138
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
138
139
|
requirements:
|
139
|
-
- -
|
140
|
+
- - ">="
|
140
141
|
- !ruby/object:Gem::Version
|
141
142
|
version: '0'
|
142
143
|
requirements: []
|
143
144
|
rubyforge_project:
|
144
|
-
rubygems_version: 2.
|
145
|
+
rubygems_version: 2.2.2
|
145
146
|
signing_key:
|
146
147
|
specification_version: 4
|
147
148
|
summary: A drop-in replacement for e.g. MemCacheStore to store Rails sessions (and
|