rack-session-sequel 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.
- data/.gitignore +5 -0
- data/.travis.yml +7 -0
- data/CHANGES.md +6 -0
- data/Gemfile +4 -0
- data/README.md +43 -0
- data/Rakefile +1 -0
- data/lib/rack-session-sequel.rb +2 -0
- data/lib/rack-session-sequel/version.rb +7 -0
- data/lib/rack/session/sequel.rb +104 -0
- data/lib/rack/session/sequel_org.rb +99 -0
- data/rack-session-sequel.gemspec +24 -0
- data/spec/spec_session_sequel.rb +207 -0
- metadata +91 -0
data/.travis.yml
ADDED
data/CHANGES.md
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
rack-session-sequel
|
2
|
+
====================
|
3
|
+
|
4
|
+
Rack session store for Sequel
|
5
|
+
|
6
|
+
<http://github.com/migrs/rack-session-sequel>
|
7
|
+
|
8
|
+
[](http://travis-ci.org/migrs/rack-session-sequel)
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
gem install rack-session-sequel
|
13
|
+
|
14
|
+
## Usage
|
15
|
+
|
16
|
+
Simple (In-Memory Sequel Database)
|
17
|
+
|
18
|
+
use Rack::Session::Sequel
|
19
|
+
|
20
|
+
Specify DB URI (see [Connecting to a database](http://sequel.rubyforge.org/rdoc/files/doc/opening_databases_rdoc.html))
|
21
|
+
|
22
|
+
use Rack::Session::Sequel, 'sqlite://blog.db'
|
23
|
+
|
24
|
+
Set Sequel DB instance
|
25
|
+
|
26
|
+
DB = Sequel.connect('sqlite://blog.db')
|
27
|
+
use Rack::Session::Sequel, DB
|
28
|
+
|
29
|
+
With some config
|
30
|
+
|
31
|
+
use Rack::Session::Sequel, :db => DB, :expire_after => 600
|
32
|
+
use Rack::Session::Sequel, :db_uri => 'sqlite://blog.db', :expire_after => 600
|
33
|
+
|
34
|
+
Specify session table name
|
35
|
+
|
36
|
+
use Rack::Session::Sequel, :db => DB, :table_name => :tbl_session
|
37
|
+
|
38
|
+
## About Sequel
|
39
|
+
|
40
|
+
- <http://sequel.rubyforge.org/>
|
41
|
+
|
42
|
+
## License
|
43
|
+
[rack-session-sequel](http://github.com/migrs/rack-session-sequel) is Copyright (c) 2012 [Masato Igarashi](http://github.com/migrs)(@[migrs](http://twitter.com/migrs)) and distributed under the [MIT license](http://www.opensource.org/licenses/mit-license).
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'rack/session/abstract/id'
|
2
|
+
require 'sequel'
|
3
|
+
|
4
|
+
module Rack
|
5
|
+
module Session
|
6
|
+
class Sequel < Abstract::ID
|
7
|
+
|
8
|
+
attr_reader :mutex, :pool
|
9
|
+
|
10
|
+
DEFAULT_OPTIONS = Abstract::ID::DEFAULT_OPTIONS.merge \
|
11
|
+
:table_name => :sessions, :db_uri => 'sqlite:/'
|
12
|
+
|
13
|
+
def initialize(app, options={})
|
14
|
+
options = {:db => options } if options.kind_of? ::Sequel::Database
|
15
|
+
options = {:db_uri => options } if options.is_a? String
|
16
|
+
super
|
17
|
+
@pool = setup_database[@default_options[:table_name]]
|
18
|
+
@mutex = Mutex.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def generate_sid
|
22
|
+
loop do
|
23
|
+
sid = super
|
24
|
+
break sid unless _exists? sid
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_session(env, sid)
|
29
|
+
with_lock(env, [nil, {}]) do
|
30
|
+
unless sid and session = _get(sid)
|
31
|
+
sid, session = generate_sid, {}
|
32
|
+
_put sid, session
|
33
|
+
end
|
34
|
+
[sid, session]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def set_session(env, session_id, new_session, options)
|
39
|
+
with_lock(env, false) do
|
40
|
+
_put session_id, new_session
|
41
|
+
session_id
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def destroy_session(env, session_id, options)
|
46
|
+
with_lock(env) do
|
47
|
+
_delete(session_id)
|
48
|
+
generate_sid unless options[:drop]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def with_lock(env, default=nil)
|
53
|
+
@mutex.lock if env['rack.multithread']
|
54
|
+
yield
|
55
|
+
rescue
|
56
|
+
default
|
57
|
+
ensure
|
58
|
+
@mutex.unlock if @mutex.locked?
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
def setup_database
|
63
|
+
(@default_options[:db] || ::Sequel.connect(@default_options[:db_uri])).tap do |db|
|
64
|
+
db.create_table @default_options[:table_name] do
|
65
|
+
#primary_key :id
|
66
|
+
String :sid, :unique => true, :null => false, :primary_key => true
|
67
|
+
text :session, :null => false
|
68
|
+
DateTime :created_at, :null => false
|
69
|
+
DateTime :updated_at
|
70
|
+
end unless db.table_exists?(@default_options[:table_name])
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def _put(sid, session)
|
75
|
+
if _exists?(sid)
|
76
|
+
_record(sid).update :session => [Marshal.dump(session)].pack('m*'), :updated_at => Time.now.utc
|
77
|
+
else
|
78
|
+
@pool.insert :sid => sid, :session => [Marshal.dump(session)].pack('m*'), :created_at => Time.now.utc
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def _get(sid)
|
83
|
+
if _exists?(sid)
|
84
|
+
Marshal.load(_record(sid).first[:session].unpack('m*').first)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def _delete(sid)
|
89
|
+
if _exists?(sid)
|
90
|
+
_record(sid).delete
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def _exists?(sid)
|
95
|
+
!_record(sid).empty?
|
96
|
+
end
|
97
|
+
|
98
|
+
def _record(sid)
|
99
|
+
@pool.filter('sid = ?', sid)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'rack/session/abstract/id'
|
2
|
+
require 'sequel'
|
3
|
+
|
4
|
+
module Rack
|
5
|
+
module Session
|
6
|
+
class Sequel < Abstract::ID
|
7
|
+
attr_reader :mutex, :pool
|
8
|
+
|
9
|
+
DEFAULT_OPTIONS = Abstract::ID::DEFAULT_OPTIONS.merge \
|
10
|
+
:table_name => :sessions, :db_uri => 'sqlite:/'
|
11
|
+
|
12
|
+
def initialize(app, options={})
|
13
|
+
options = {:db => options } if options.kind_of? ::Sequel::Database
|
14
|
+
options = {:db_uri => options } if options.is_a? String
|
15
|
+
super
|
16
|
+
db = @default_options[:db] || ::Sequel.connect(@default_options[:db_uri])
|
17
|
+
db.create_table @default_options[:table_name] do
|
18
|
+
primary_key :id
|
19
|
+
String :sid, :unique => true, :null => false
|
20
|
+
text :session
|
21
|
+
DateTime :updated_at
|
22
|
+
end unless db.table_exists?(@default_options[:table_name])
|
23
|
+
@pool = db[@default_options[:table_name]]
|
24
|
+
@mutex = Mutex.new
|
25
|
+
end
|
26
|
+
|
27
|
+
def generate_sid
|
28
|
+
loop do
|
29
|
+
sid = super
|
30
|
+
break sid unless _exists? sid
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def get_session(env, sid)
|
35
|
+
with_lock(env, [nil, {}]) do
|
36
|
+
unless sid and session = _get(sid)
|
37
|
+
sid, session = generate_sid, {}
|
38
|
+
_put sid, session
|
39
|
+
end
|
40
|
+
[sid, session]
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def set_session(env, session_id, new_session, options)
|
45
|
+
with_lock(env, false) do
|
46
|
+
_put session_id, new_session
|
47
|
+
session_id
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def destroy_session(env, session_id, options)
|
52
|
+
with_lock(env) do
|
53
|
+
_delete(session_id)
|
54
|
+
generate_sid unless options[:drop]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def with_lock(env, default=nil)
|
59
|
+
@mutex.lock if env['rack.multithread']
|
60
|
+
yield
|
61
|
+
rescue
|
62
|
+
default
|
63
|
+
ensure
|
64
|
+
@mutex.unlock if @mutex.locked?
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def _put(sid, session)
|
70
|
+
if _exists?(sid)
|
71
|
+
_record(sid).update :session => [Marshal.dump(session)].pack('m*'), :updated_at => Time.now.utc
|
72
|
+
else
|
73
|
+
@pool.insert :sid => sid, :session => [Marshal.dump(session)].pack('m*'), :updated_at => Time.now.utc
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def _get(sid)
|
78
|
+
if _exists?(sid)
|
79
|
+
Marshal.load(_record(sid).first[:session].unpack('m*').first)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def _delete(sid)
|
84
|
+
if _exists?(sid)
|
85
|
+
_record(sid).delete
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def _exists?(sid)
|
90
|
+
!_record(sid).empty?
|
91
|
+
end
|
92
|
+
|
93
|
+
def _record(sid)
|
94
|
+
@pool.filter('sid = ?', sid)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "rack-session-sequel/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "rack-session-sequel"
|
7
|
+
s.version = Rack::Session::Sequel::VERSION
|
8
|
+
s.authors = ["Masato Igarashi"]
|
9
|
+
s.email = ["m@igrs.jp"]
|
10
|
+
s.homepage = "http://github.com/migrs/rack-session-sequel"
|
11
|
+
s.summary = %q{Rack session store for Sequel}
|
12
|
+
s.description = %q{Rack session store for Sequel}
|
13
|
+
|
14
|
+
#s.rubyforge_project = "rack-session-sequel"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_development_dependency "bacon"
|
22
|
+
s.add_runtime_dependency "rack"
|
23
|
+
s.add_runtime_dependency "sequel"
|
24
|
+
end
|
@@ -0,0 +1,207 @@
|
|
1
|
+
require 'thread'
|
2
|
+
require 'rack/mock'
|
3
|
+
require 'rack/session/sequel'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
describe Rack::Session::Sequel do
|
7
|
+
session_key = Rack::Session::Sequel::DEFAULT_OPTIONS[:key]
|
8
|
+
session_match = /#{session_key}=[0-9a-fA-F]+;/
|
9
|
+
|
10
|
+
incrementor = lambda do |env|
|
11
|
+
env["rack.session"]["counter"] ||= 0
|
12
|
+
env["rack.session"]["counter"] += 1
|
13
|
+
Rack::Response.new(env["rack.session"].inspect).to_a
|
14
|
+
end
|
15
|
+
|
16
|
+
session_id = lambda do |env|
|
17
|
+
Rack::Response.new(env["rack.session"].inspect).to_a
|
18
|
+
end
|
19
|
+
|
20
|
+
nothing = lambda do |env|
|
21
|
+
Rack::Response.new("Nothing").to_a
|
22
|
+
end
|
23
|
+
|
24
|
+
drop_session = lambda do |env|
|
25
|
+
env['rack.session.options'][:drop] = true
|
26
|
+
incrementor.call(env)
|
27
|
+
end
|
28
|
+
|
29
|
+
renew_session = lambda do |env|
|
30
|
+
env['rack.session.options'][:renew] = true
|
31
|
+
incrementor.call(env)
|
32
|
+
end
|
33
|
+
|
34
|
+
defer_session = lambda do |env|
|
35
|
+
env['rack.session.options'][:defer] = true
|
36
|
+
incrementor.call(env)
|
37
|
+
end
|
38
|
+
|
39
|
+
it "creates a new cookie" do
|
40
|
+
pool = Rack::Session::Sequel.new(incrementor)
|
41
|
+
res = Rack::MockRequest.new(pool).get("/")
|
42
|
+
res["Set-Cookie"].should.match session_match
|
43
|
+
res.body.should.equal '{"counter"=>1}'
|
44
|
+
end
|
45
|
+
|
46
|
+
it "determines session from a cookie" do
|
47
|
+
pool = Rack::Session::Sequel.new(incrementor)
|
48
|
+
req = Rack::MockRequest.new(pool)
|
49
|
+
cookie = req.get("/")["Set-Cookie"]
|
50
|
+
req.get("/", "HTTP_COOKIE" => cookie).
|
51
|
+
body.should.equal '{"counter"=>2}'
|
52
|
+
req.get("/", "HTTP_COOKIE" => cookie).
|
53
|
+
body.should.equal '{"counter"=>3}'
|
54
|
+
end
|
55
|
+
|
56
|
+
it "survives nonexistant cookies" do
|
57
|
+
pool = Rack::Session::Sequel.new(incrementor)
|
58
|
+
res = Rack::MockRequest.new(pool).
|
59
|
+
get("/", "HTTP_COOKIE" => "#{session_key}=blarghfasel")
|
60
|
+
res.body.should.equal '{"counter"=>1}'
|
61
|
+
end
|
62
|
+
|
63
|
+
it "does not send the same session id if it did not change" do
|
64
|
+
pool = Rack::Session::Sequel.new(incrementor)
|
65
|
+
req = Rack::MockRequest.new(pool)
|
66
|
+
|
67
|
+
res0 = req.get("/")
|
68
|
+
cookie = res0["Set-Cookie"][session_match]
|
69
|
+
res0.body.should.equal '{"counter"=>1}'
|
70
|
+
pool.pool.count.should.equal 1
|
71
|
+
|
72
|
+
res1 = req.get("/", "HTTP_COOKIE" => cookie)
|
73
|
+
res1["Set-Cookie"].should.be.nil
|
74
|
+
res1.body.should.equal '{"counter"=>2}'
|
75
|
+
pool.pool.count.should.equal 1
|
76
|
+
|
77
|
+
res2 = req.get("/", "HTTP_COOKIE" => cookie)
|
78
|
+
res2["Set-Cookie"].should.be.nil
|
79
|
+
res2.body.should.equal '{"counter"=>3}'
|
80
|
+
pool.pool.count.should.equal 1
|
81
|
+
end
|
82
|
+
|
83
|
+
it "deletes cookies with :drop option" do
|
84
|
+
pool = Rack::Session::Sequel.new(incrementor)
|
85
|
+
req = Rack::MockRequest.new(pool)
|
86
|
+
drop = Rack::Utils::Context.new(pool, drop_session)
|
87
|
+
dreq = Rack::MockRequest.new(drop)
|
88
|
+
|
89
|
+
res1 = req.get("/")
|
90
|
+
session = (cookie = res1["Set-Cookie"])[session_match]
|
91
|
+
res1.body.should.equal '{"counter"=>1}'
|
92
|
+
pool.pool.count.should.equal 1
|
93
|
+
|
94
|
+
res2 = dreq.get("/", "HTTP_COOKIE" => cookie)
|
95
|
+
res2["Set-Cookie"].should.be.nil
|
96
|
+
res2.body.should.equal '{"counter"=>2}'
|
97
|
+
pool.pool.count.should.equal 0
|
98
|
+
|
99
|
+
res3 = req.get("/", "HTTP_COOKIE" => cookie)
|
100
|
+
res3["Set-Cookie"][session_match].should.not.equal session
|
101
|
+
res3.body.should.equal '{"counter"=>1}'
|
102
|
+
pool.pool.count.should.equal 1
|
103
|
+
end
|
104
|
+
|
105
|
+
it "provides new session id with :renew option" do
|
106
|
+
pool = Rack::Session::Sequel.new(incrementor)
|
107
|
+
req = Rack::MockRequest.new(pool)
|
108
|
+
renew = Rack::Utils::Context.new(pool, renew_session)
|
109
|
+
rreq = Rack::MockRequest.new(renew)
|
110
|
+
|
111
|
+
res1 = req.get("/")
|
112
|
+
session = (cookie = res1["Set-Cookie"])[session_match]
|
113
|
+
res1.body.should.equal '{"counter"=>1}'
|
114
|
+
pool.pool.count.should.equal 1
|
115
|
+
|
116
|
+
res2 = rreq.get("/", "HTTP_COOKIE" => cookie)
|
117
|
+
new_cookie = res2["Set-Cookie"]
|
118
|
+
new_session = new_cookie[session_match]
|
119
|
+
new_session.should.not.equal session
|
120
|
+
res2.body.should.equal '{"counter"=>2}'
|
121
|
+
pool.pool.count.should.equal 1
|
122
|
+
|
123
|
+
res3 = req.get("/", "HTTP_COOKIE" => new_cookie)
|
124
|
+
res3.body.should.equal '{"counter"=>3}'
|
125
|
+
pool.pool.count.should.equal 1
|
126
|
+
|
127
|
+
res4 = req.get("/", "HTTP_COOKIE" => cookie)
|
128
|
+
res4.body.should.equal '{"counter"=>1}'
|
129
|
+
pool.pool.count.should.equal 2
|
130
|
+
end
|
131
|
+
|
132
|
+
it "omits cookie with :defer option" do
|
133
|
+
pool = Rack::Session::Sequel.new(incrementor)
|
134
|
+
defer = Rack::Utils::Context.new(pool, defer_session)
|
135
|
+
dreq = Rack::MockRequest.new(defer)
|
136
|
+
|
137
|
+
res1 = dreq.get("/")
|
138
|
+
res1["Set-Cookie"].should.equal nil
|
139
|
+
res1.body.should.equal '{"counter"=>1}'
|
140
|
+
pool.pool.count.should.equal 1
|
141
|
+
end
|
142
|
+
|
143
|
+
# anyone know how to do this better?
|
144
|
+
it "should merge sessions when multithreaded" do
|
145
|
+
unless $DEBUG
|
146
|
+
1.should.equal 1
|
147
|
+
next
|
148
|
+
end
|
149
|
+
|
150
|
+
warn 'Running multithread tests for Session::Sequel'
|
151
|
+
pool = Rack::Session::Sequel.new(incrementor)
|
152
|
+
req = Rack::MockRequest.new(pool)
|
153
|
+
|
154
|
+
res = req.get('/')
|
155
|
+
res.body.should.equal '{"counter"=>1}'
|
156
|
+
cookie = res["Set-Cookie"]
|
157
|
+
sess_id = cookie[/#{pool.key}=([^,;]+)/,1]
|
158
|
+
|
159
|
+
delta_incrementor = lambda do |env|
|
160
|
+
# emulate disconjoinment of threading
|
161
|
+
env['rack.session'] = env['rack.session'].dup
|
162
|
+
Thread.stop
|
163
|
+
env['rack.session'][(Time.now.usec*rand).to_i] = true
|
164
|
+
incrementor.call(env)
|
165
|
+
end
|
166
|
+
tses = Rack::Utils::Context.new pool, delta_incrementor
|
167
|
+
treq = Rack::MockRequest.new(tses)
|
168
|
+
tnum = rand(7).to_i+5
|
169
|
+
r = Array.new(tnum) do
|
170
|
+
Thread.new(treq) do |run|
|
171
|
+
run.get('/', "HTTP_COOKIE" => cookie, 'rack.multithread' => true)
|
172
|
+
end
|
173
|
+
end.reverse.map{|t| t.run.join.value }
|
174
|
+
r.each do |resp|
|
175
|
+
resp['Set-Cookie'].should.equal cookie
|
176
|
+
resp.body.should.include '"counter"=>2'
|
177
|
+
end
|
178
|
+
|
179
|
+
session = pool.pool[sess_id]
|
180
|
+
session.count.should.equal tnum+1 # counter
|
181
|
+
session['counter'].should.equal 2 # meeeh
|
182
|
+
end
|
183
|
+
|
184
|
+
it "does not return a cookie if cookie was not read/written" do
|
185
|
+
app = Rack::Session::Sequel.new(nothing)
|
186
|
+
res = Rack::MockRequest.new(app).get("/")
|
187
|
+
res["Set-Cookie"].should.be.nil
|
188
|
+
end
|
189
|
+
|
190
|
+
it "does not return a cookie if cookie was not written (only read)" do
|
191
|
+
app = Rack::Session::Sequel.new(session_id)
|
192
|
+
res = Rack::MockRequest.new(app).get("/")
|
193
|
+
res["Set-Cookie"].should.be.nil
|
194
|
+
end
|
195
|
+
|
196
|
+
it "returns even if not read/written if :expire_after is set" do
|
197
|
+
app = Rack::Session::Sequel.new(nothing, :expire_after => 3600)
|
198
|
+
res = Rack::MockRequest.new(app).get("/", 'rack.session' => {'not' => 'empty'})
|
199
|
+
res["Set-Cookie"].should.not.be.nil
|
200
|
+
end
|
201
|
+
|
202
|
+
it "returns no cookie if no data was written and no session was created previously, even if :expire_after is set" do
|
203
|
+
app = Rack::Session::Sequel.new(nothing, :expire_after => 3600)
|
204
|
+
res = Rack::MockRequest.new(app).get("/")
|
205
|
+
res["Set-Cookie"].should.be.nil
|
206
|
+
end
|
207
|
+
end
|
metadata
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rack-session-sequel
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Masato Igarashi
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-01-29 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: bacon
|
16
|
+
requirement: &70106969290620 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70106969290620
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rack
|
27
|
+
requirement: &70106962349140 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70106962349140
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: sequel
|
38
|
+
requirement: &70106962348640 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :runtime
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70106962348640
|
47
|
+
description: Rack session store for Sequel
|
48
|
+
email:
|
49
|
+
- m@igrs.jp
|
50
|
+
executables: []
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files: []
|
53
|
+
files:
|
54
|
+
- .gitignore
|
55
|
+
- .travis.yml
|
56
|
+
- CHANGES.md
|
57
|
+
- Gemfile
|
58
|
+
- README.md
|
59
|
+
- Rakefile
|
60
|
+
- lib/rack-session-sequel.rb
|
61
|
+
- lib/rack-session-sequel/version.rb
|
62
|
+
- lib/rack/session/sequel.rb
|
63
|
+
- lib/rack/session/sequel_org.rb
|
64
|
+
- rack-session-sequel.gemspec
|
65
|
+
- spec/spec_session_sequel.rb
|
66
|
+
homepage: http://github.com/migrs/rack-session-sequel
|
67
|
+
licenses: []
|
68
|
+
post_install_message:
|
69
|
+
rdoc_options: []
|
70
|
+
require_paths:
|
71
|
+
- lib
|
72
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
|
+
none: false
|
80
|
+
requirements:
|
81
|
+
- - ! '>='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: '0'
|
84
|
+
requirements: []
|
85
|
+
rubyforge_project:
|
86
|
+
rubygems_version: 1.8.10
|
87
|
+
signing_key:
|
88
|
+
specification_version: 3
|
89
|
+
summary: Rack session store for Sequel
|
90
|
+
test_files:
|
91
|
+
- spec/spec_session_sequel.rb
|