rack-session-moped 0.0.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.
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ vendor/bundler
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ -fs
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rack-session-moped.gemspec
4
+ gemspec
5
+ gem 'rake'
6
+ gem 'rspec'
7
+ gem 'yard'
8
+ gem 'redcarpet'
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 aoyagikouhei
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,49 @@
1
+ # Rack::Session::Moped
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'rack-session-moped'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install rack-session-moped
18
+
19
+ ## Usage
20
+
21
+ Simple (localhost:27017 db:rack, collection:sessions)
22
+
23
+ use Rack::Session::Moped
24
+
25
+ Set Moped Session
26
+
27
+ session = Moped::Session.new(['localhost:27017'])
28
+ use Rack::Sessionn::Moped, {
29
+ session: session
30
+ }
31
+
32
+ Set Config
33
+
34
+ use Rack::Sessionn::Moped, {
35
+ seeds: ['127.0.0.1:27017'],
36
+ db: 'rack_test',
37
+ collection: 'sessions_test'
38
+ }
39
+
40
+ ## Contributing
41
+
42
+ 1. Fork it
43
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
44
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
45
+ 4. Push to the branch (`git push origin my-new-feature`)
46
+ 5. Create new Pull Request
47
+
48
+ ## License
49
+ [rack-session-mongo](http://github.com/aoyagikouhei/rack-session-moped) is Copyright (c) 2012 [Kouhei Aoyagi](http://github.com/aoyagikouhei)(@[aoyagikouhei](http://twitter.com/aoyagikouhei)) and distributed under the [MIT license](http://www.opensource.org/licenses/mit-license).
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require 'rspec/core/rake_task'
4
+ require 'yard'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+ task :default => :spec
8
+
9
+ YARD::Rake::YardocTask.new(:doc)
@@ -0,0 +1,2 @@
1
+ require "rack/session/moped"
2
+ require "rack/session/moped/version"
@@ -0,0 +1,127 @@
1
+ require "rack/session/abstract/id"
2
+ require "moped"
3
+
4
+ module Rack
5
+ module Session
6
+ class Moped < Abstract::ID
7
+ attr_reader :mutex, :pool, :marshal_data
8
+ DEFAULT_OPTIONS = Abstract::ID::DEFAULT_OPTIONS.merge(
9
+ db: :rack,
10
+ collection: :sessions,
11
+ drop: false,
12
+ seeds: ["localhost:27017"]
13
+ )
14
+
15
+ def initialize(app, options={})
16
+ super
17
+ @mutex = Mutex.new
18
+ session = @default_options[:session] || ::Moped::Session.new(@default_options[:seeds])
19
+ session.use @default_options[:db]
20
+ @pool = session[@default_options[:collection]]
21
+ @pool.indexes.create(expires: -1)
22
+ @pool.indexes.create({sid: 1}, {unique: true})
23
+ @marshal_data = @default_options[:marshal_data].nil? ? true : @default_options[:marshal_data] == true
24
+ @next_expire_period = nil
25
+ @recheck_expire_period = @default_options[:clear_expired_after].nil? ? 1800 : @default_options[:clear_expired_after].to_i
26
+ end
27
+
28
+ def get_session(env, sid)
29
+ @mutex.lock if env['rack.multithread']
30
+ session = find_session(sid) if sid
31
+ unless sid and session
32
+ env['rack.errors'].puts("Session '#{sid}' not found, initializing...") if $VERBOSE and not sid.nil?
33
+ session = {}
34
+ sid = generate_sid
35
+ save_session(sid)
36
+ end
37
+ session.instance_variable_set('@old', {}.merge(session))
38
+ session.instance_variable_set('@sid', sid)
39
+ return [sid, session]
40
+ ensure
41
+ @mutex.unlock if env['rack.multithread']
42
+ end
43
+
44
+ def set_session(env, sid, new_session, options)
45
+ @mutex.lock if env['rack.multithread']
46
+ expires = Time.now + options[:expire_after] if !options[:expire_after].nil?
47
+ session = find_session(sid) || {}
48
+ if options[:renew] or options[:drop]
49
+ delete_session(sid)
50
+ return false if options[:drop]
51
+ sid = generate_sid
52
+ save_session(sid, session, expires)
53
+ end
54
+ old_session = new_session.instance_variable_get('@old') || {}
55
+ session = merge_sessions(sid, old_session, new_session, session)
56
+ save_session(sid, session, expires)
57
+ return sid
58
+ ensure
59
+ @mutex.unlock if env['rack.multithread']
60
+ end
61
+
62
+ def destroy_session(env, sid, options)
63
+ delete_session(sid)
64
+ generate_sid unless options[:drop]
65
+ end
66
+
67
+ private
68
+
69
+ def find_session(sid)
70
+ time = Time.now
71
+ if @recheck_expire_period != -1 && (@next_expire_period.nil? || @next_expire_period < time)
72
+ @next_expire_period = time + @recheck_expire_period
73
+ @pool.find(expires: {'$lte' => time}).remove_all # clean out expired sessions
74
+ end
75
+ session = @pool.find(sid: sid).first
76
+ #if session is expired but hasn't been cleared yet. don't return it.
77
+ if session && session['expires'] != nil && session['expires'] < time
78
+ session = nil
79
+ end
80
+ session ? unpack(session['data']) : false
81
+ end
82
+
83
+ def delete_session(sid)
84
+ @pool.find(sid: sid).remove
85
+ end
86
+
87
+ def save_session(sid, session={}, expires=nil)
88
+ @pool.find(sid: sid).upsert("$set" => {data: pack(session), expires: expires})
89
+ end
90
+
91
+ def merge_sessions(sid, old, new, current=nil)
92
+ current ||= {}
93
+ unless Hash === old and Hash === new
94
+ warn 'Bad old or new sessions provided.'
95
+ return current
96
+ end
97
+ # delete keys that are not in common
98
+ delete = current.keys - (new.keys & current.keys)
99
+ warn "//@#{sid}: dropping #{delete*','}" if $DEBUG and not delete.empty?
100
+ delete.each{|k| current.delete k }
101
+
102
+ update = new.keys.select{|k| !current.has_key?(k) || new[k] != current[k] || new[k].kind_of?(Hash) || new[k].kind_of?(Array) }
103
+ warn "//@#{sid}: updating #{update*','}" if $DEBUG and not update.empty?
104
+ update.each{|k| current[k] = new[k] }
105
+
106
+ current
107
+ end
108
+
109
+ def pack(data)
110
+ if(@marshal_data)
111
+ [Marshal.dump(data)].pack("m*")
112
+ else
113
+ data
114
+ end
115
+ end
116
+
117
+ def unpack(packed)
118
+ return nil unless packed
119
+ if(@marshal_data)
120
+ Marshal.load(packed.unpack("m*").first)
121
+ else
122
+ packed
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
@@ -0,0 +1,9 @@
1
+ require "rack/session/abstract/id"
2
+
3
+ module Rack
4
+ module Session
5
+ class Moped < Abstract::ID
6
+ VERSION = "0.0.1"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/rack/session/moped/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["aoyagikouhei"]
6
+ gem.email = ["aoyagi.kouhei@gmail.com"]
7
+ gem.description = %q{Rack session store for MongoDB}
8
+ gem.summary = %q{Rack session store for MongoDB}
9
+ gem.homepage = "https://github.com/aoyagikouhei/rack-session-moped"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "rack-session-moped"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Rack::Session::Moped::VERSION
17
+ gem.add_dependency(%q<rack>)
18
+ gem.add_dependency(%q<moped>)
19
+ end
@@ -0,0 +1,260 @@
1
+ require 'spec_helper'
2
+ describe Rack::Session::Moped do
3
+ before(:each) do
4
+ @session_key = Rack::Session::Moped::DEFAULT_OPTIONS[:key]
5
+ @session_match = /#{@session_key}=[0-9a-fA-F]+;/
6
+ @incrementor = lambda do |env|
7
+ env['rack.session']['counter'] ||= 0
8
+ env['rack.session']['counter'] += 1
9
+ Rack::Response.new(env['rack.session'].inspect).to_a
10
+ end
11
+ @drop_session = proc do |env|
12
+ env['rack.session.options'][:drop] = true
13
+ @incrementor.call(env)
14
+ end
15
+ @renew_session = proc do |env|
16
+ env['rack.session.options'][:renew] = true
17
+ @incrementor.call(env)
18
+ end
19
+ @defer_session = proc do |env|
20
+ env['rack.session.options'][:defer] = true
21
+ @incrementor.call(env)
22
+ end
23
+ end
24
+
25
+ it 'should default connection params' do
26
+ mongo = Rack::Session::Moped.new(@incrementor)
27
+ pool = mongo.pool
28
+ pool.database.session.cluster.nodes[0].address.should == 'localhost:27017'
29
+
30
+ pool.should be_kind_of(Moped::Collection)
31
+ pool.database.name.should == :rack
32
+ pool.name.should == :sessions
33
+ end
34
+
35
+ it 'should specify connection params' do
36
+ mongo = Rack::Session::Moped.new(@incrementor,
37
+ seeds: ['127.0.0.1:27017'],
38
+ db: :rack_test,
39
+ collection: :sessions_test)
40
+ pool = mongo.pool
41
+ pool.database.session.cluster.nodes[0].address.should == '127.0.0.1:27017'
42
+
43
+ pool.should be_kind_of(Moped::Collection)
44
+ pool.database.name.should == :rack_test
45
+ pool.name.should == :sessions_test
46
+ end
47
+
48
+ it 'creates a new cookie' do
49
+ pool = Rack::Session::Moped.new(@incrementor)
50
+ res = Rack::MockRequest.new(pool).get('/')
51
+ res['Set-Cookie'].should match(/#{@session_key}=/)
52
+ res.body.should == '{"counter"=>1}'
53
+ end
54
+
55
+ it 'determines session from a cookie' do
56
+ pool = Rack::Session::Moped.new(@incrementor)
57
+ req = Rack::MockRequest.new(pool)
58
+ res = req.get('/')
59
+ cookie = res['Set-Cookie']
60
+ req.get('/', 'HTTP_COOKIE' => cookie).
61
+ body.should == '{"counter"=>2}'
62
+ req.get('/', 'HTTP_COOKIE' => cookie).
63
+ body.should == '{"counter"=>3}'
64
+ end
65
+
66
+ it 'survives nonexistant cookies' do
67
+ bad_cookie = 'rack.session=blarghfasel'
68
+ pool = Rack::Session::Moped.new(@incrementor)
69
+ res = Rack::MockRequest.new(pool).
70
+ get('/', 'HTTP_COOKIE' => bad_cookie)
71
+ res.body.should == '{"counter"=>1}'
72
+ cookie = res['Set-Cookie'][@session_match]
73
+ cookie.should_not match(/#{bad_cookie}/)
74
+ end
75
+
76
+ it 'should maintain freshness' do
77
+ pool = Rack::Session::Moped.new(@incrementor, :expire_after => 3)
78
+ res = Rack::MockRequest.new(pool).get('/')
79
+ res.body.should include('"counter"=>1')
80
+ cookie = res['Set-Cookie']
81
+ res = Rack::MockRequest.new(pool).get('/', 'HTTP_COOKIE' => cookie)
82
+ res['Set-Cookie'].should == cookie
83
+ res.body.should include('"counter"=>2')
84
+ puts 'Sleeping to expire session' if $DEBUG
85
+ sleep 4
86
+ res = Rack::MockRequest.new(pool).get('/', 'HTTP_COOKIE' => cookie)
87
+ res['Set-Cookie'].should_not == cookie
88
+ res.body.should include('"counter"=>1')
89
+ end
90
+
91
+ it 'deletes cookies with :drop option' do
92
+ pool = Rack::Session::Moped.new(@incrementor)
93
+ req = Rack::MockRequest.new(pool)
94
+ drop = Rack::Utils::Context.new(pool, @drop_session)
95
+ dreq = Rack::MockRequest.new(drop)
96
+
97
+ res0 = req.get('/')
98
+ session = (cookie = res0['Set-Cookie'])[@session_match]
99
+ res0.body.should == '{"counter"=>1}'
100
+
101
+ res1 = req.get('/', 'HTTP_COOKIE' => cookie)
102
+ res1['Set-Cookie'].should be_nil
103
+ res1.body.should == '{"counter"=>2}'
104
+
105
+ res2 = dreq.get('/', 'HTTP_COOKIE' => cookie)
106
+ res2['Set-Cookie'].should be_nil
107
+ res2.body.should == '{"counter"=>3}'
108
+
109
+ res3 = req.get('/', 'HTTP_COOKIE' => cookie)
110
+ res3['Set-Cookie'][@session_match].should_not == session
111
+ res3.body.should == '{"counter"=>1}'
112
+ end
113
+
114
+ it 'provides new session id with :renew option' do
115
+ pool = Rack::Session::Moped.new(@incrementor)
116
+ req = Rack::MockRequest.new(pool)
117
+ renew = Rack::Utils::Context.new(pool, @renew_session)
118
+ rreq = Rack::MockRequest.new(renew)
119
+
120
+ res0 = req.get('/')
121
+ session = (cookie = res0['Set-Cookie'])[@session_match]
122
+ res0.body.should == '{"counter"=>1}'
123
+
124
+ res1 = req.get('/', 'HTTP_COOKIE' => cookie)
125
+ res1['Set-Cookie'].should be_nil
126
+ res1.body.should == '{"counter"=>2}'
127
+
128
+ res2 = rreq.get('/', 'HTTP_COOKIE' => cookie)
129
+ new_cookie = res2['Set-Cookie']
130
+ new_session = new_cookie[@session_match]
131
+ new_session.should_not == session
132
+ res2.body.should == '{"counter"=>3}'
133
+
134
+ res3 = req.get('/', 'HTTP_COOKIE' => new_cookie)
135
+ res3['Set-Cookie'].should be_nil
136
+ res3.body.should == '{"counter"=>4}'
137
+ end
138
+
139
+ it 'should default marshal_data to true' do
140
+ pool = Rack::Session::Moped.new(@incrementor)
141
+ pool.marshal_data.should == true
142
+ data = {'test' => true}
143
+ pool.send(:pack, data).should == [Marshal.dump(data)].pack("m*")
144
+ pool.send(:unpack, [Marshal.dump(data)].pack("m*"))['test'] == true
145
+ end
146
+
147
+ it 'should be able to set marshal_data to false' do
148
+ pool = Rack::Session::Moped.new(@incrementor, :marshal_data => false)
149
+ pool.marshal_data.should == false
150
+ data = {'test' => true}
151
+ pool.send(:pack, data).should === data
152
+ pool.send(:unpack, data).should === data
153
+ end
154
+ specify 'omits cookie with :defer option' do
155
+ pool = Rack::Session::Moped.new(@incrementor)
156
+ req = Rack::MockRequest.new(pool)
157
+ defer = Rack::Utils::Context.new(pool, @defer_session)
158
+ dreq = Rack::MockRequest.new(defer)
159
+
160
+ res0 = req.get('/')
161
+ session = (cookie = res0['Set-Cookie'])[@session_match]
162
+ res0.body.should == '{"counter"=>1}'
163
+
164
+ res1 = req.get('/', 'HTTP_COOKIE' => cookie)
165
+ res1['Set-Cookie'].should be_nil
166
+ res1.body.should == '{"counter"=>2}'
167
+
168
+ res2 = dreq.get('/', 'HTTP_COOKIE' => cookie)
169
+ res2['Set-Cookie'].should be_nil
170
+ res2.body.should == '{"counter"=>3}'
171
+
172
+ res3 = req.get('/', 'HTTP_COOKIE' => cookie)
173
+ res3['Set-Cookie'].should be_nil
174
+ res3.body.should == '{"counter"=>4}'
175
+ end
176
+
177
+ # anyone know how to do this better?
178
+ specify 'multithread: should cleanly merge sessions' do
179
+ next unless $DEBUG
180
+ warn 'Running multithread test for Session::Mongo'
181
+ pool = Rack::Session::Moped.new(@incrementor)
182
+ req = Rack::MockRequest.new(pool)
183
+
184
+ res = req.get('/')
185
+ res.body.should == '{"counter"=>1}'
186
+ cookie = res['Set-Cookie']
187
+ sess_id = cookie[/#{pool.key}=([^,;]+)/,1]
188
+
189
+ delta_incrementor = lambda do |env|
190
+ # emulate disconjoinment of threading
191
+ env['rack.session'] = env['rack.session'].dup
192
+ Thread.stop
193
+ env['rack.session'][(Time.now.usec*rand).to_i] = true
194
+ @incrementor.call(env)
195
+ end
196
+ tses = Rack::Utils::Context.new pool, delta_incrementor
197
+ treq = Rack::MockRequest.new(tses)
198
+ tnum = rand(7).to_i+5
199
+ r = Array.new(tnum) do
200
+ Thread.new(treq) do |run|
201
+ run.get('/', 'HTTP_COOKIE' => cookie, 'rack.multithread' => true)
202
+ end
203
+ end.reverse.map{|t| t.run.join.value }
204
+ r.each do |res|
205
+ res['Set-Cookie'].should == cookie
206
+ res.body.should include('"counter"=>2')
207
+ end
208
+
209
+ session = pool.pool.get(sess_id)
210
+ session.size.should == tnum+1 # counter
211
+ session['counter'].should == 2 # meeeh
212
+
213
+ tnum = rand(7).to_i+5
214
+ r = Array.new(tnum) do |i|
215
+ delta_time = proc do |env|
216
+ env['rack.session'][i] = Time.now
217
+ Thread.stop
218
+ env['rack.session'] = env['rack.session'].dup
219
+ env['rack.session'][i] -= Time.now
220
+ @incrementor.call(env)
221
+ end
222
+ app = Rack::Utils::Context.new pool, time_delta
223
+ req = Rack::MockRequest.new app
224
+ Thread.new(req) do |run|
225
+ run.get('/', 'HTTP_COOKIE' => cookie, 'rack.multithread' => true)
226
+ end
227
+ end.reverse.map{|t| t.run.join.value }
228
+ r.each do |res|
229
+ res['Set-Cookie'].should == cookie
230
+ res.body.should include('"counter"=>3')
231
+ end
232
+
233
+ session = pool.pool.get(sess_id)
234
+ session.size.should == tnum+1
235
+ session['counter'].should == 3
236
+
237
+ drop_counter = proc do |env|
238
+ env['rack.session'].delete 'counter'
239
+ env['rack.session']['foo'] = 'bar'
240
+ [200, {'Content-Type'=>'text/plain'}, env['rack.session'].inspect]
241
+ end
242
+ tses = Rack::Utils::Context.new pool, drop_counter
243
+ treq = Rack::MockRequest.new(tses)
244
+ tnum = rand(7).to_i+5
245
+ r = Array.new(tnum) do
246
+ Thread.new(treq) do |run|
247
+ run.get('/', 'HTTP_COOKIE' => cookie, 'rack.multithread' => true)
248
+ end
249
+ end.reverse.map{|t| t.run.join.value }
250
+ r.each do |res|
251
+ res['Set-Cookie'].should == cookie
252
+ res.body.should include('"foo"=>"bar"')
253
+ end
254
+
255
+ session = pool.pool.get(sess_id)
256
+ session.size.should == r.size+1
257
+ session['counter'].should be_nil
258
+ session['foo'].should == 'bar'
259
+ end
260
+ end
@@ -0,0 +1,8 @@
1
+ require 'bundler/setup'
2
+ require 'rack/session/moped'
3
+ require 'rack/mock'
4
+ require 'rack/response'
5
+
6
+ RSpec.configure do |config|
7
+ # some (optional) config here
8
+ end
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rack-session-moped
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - aoyagikouhei
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rack
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: moped
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: Rack session store for MongoDB
47
+ email:
48
+ - aoyagi.kouhei@gmail.com
49
+ executables: []
50
+ extensions: []
51
+ extra_rdoc_files: []
52
+ files:
53
+ - .gitignore
54
+ - .rspec
55
+ - Gemfile
56
+ - LICENSE
57
+ - README.md
58
+ - Rakefile
59
+ - lib/rack-session-moped.rb
60
+ - lib/rack/session/moped.rb
61
+ - lib/rack/session/moped/version.rb
62
+ - rack-session-moped.gemspec
63
+ - spec/rack-session-moped_spec.rb
64
+ - spec/spec_helper.rb
65
+ homepage: https://github.com/aoyagikouhei/rack-session-moped
66
+ licenses: []
67
+ post_install_message:
68
+ rdoc_options: []
69
+ require_paths:
70
+ - lib
71
+ required_ruby_version: !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ segments:
78
+ - 0
79
+ hash: 2177003043025176967
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ segments:
87
+ - 0
88
+ hash: 2177003043025176967
89
+ requirements: []
90
+ rubyforge_project:
91
+ rubygems_version: 1.8.24
92
+ signing_key:
93
+ specification_version: 3
94
+ summary: Rack session store for MongoDB
95
+ test_files:
96
+ - spec/rack-session-moped_spec.rb
97
+ - spec/spec_helper.rb
98
+ has_rdoc: