Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions README.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ A session store that avoids the pitfalls usually associated with concurrent acce

Derived from SqlSessionStore, see http://railsexpress.de/blog/articles/2005/12/19/roll-your-own-sql-session-store

Requires rails 3 or higher.
Requires rails 3 or 4. Rails 5 support coming soon.

Installation
==========
Expand All @@ -18,7 +18,24 @@ gem 'smart_session'

Step 2
-------
Generate your sessions table using rake db:sessions:create

Generate a migration like below (Assuming you have configured your session table named as "sessions":

```ruby
class xxx_migration_name < ActiveRecord::Migration
def change
create_table :sessions do |t|
t.string :session_id, :null => false
t.text :data
t.integer :lock_version
t.timestamps
end

add_index :sessions, :session_id, :unique => true
add_index :sessions, :updated_at
end
end
```

Step 3
-------
Expand Down
4 changes: 2 additions & 2 deletions gemfiles/Gemfile.ci
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
source 'https://rubygems.org'

gem "actionpack", "3.2.13"
gem "activerecord", "3.2.13"
gem "actionpack", "4.2.6"
gem "activerecord", "4.2.6"
gem "mysql2"
gem "sqlite3"
gem "pg"
Expand Down
12 changes: 6 additions & 6 deletions lib/smart_session/postgresql.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ def create_session(session_id, data)
# caller's responsibility to pass a valid sql condition
def delete_all(condition=nil)
if condition
session_connection.query("DELETE FROM #{SmartSession::SqlSession.table_name} WHERE #{condition}")
session_connection.execute("DELETE FROM #{SmartSession::SqlSession.table_name} WHERE #{condition}")
else
session_connection.query("DELETE FROM #{SmartSession::SqlSession.table_name}")
session_connection.execute("DELETE FROM #{SmartSession::SqlSession.table_name}")
end
end

Expand All @@ -91,15 +91,15 @@ def update_session(data)
# if @id is not nil, this is a session already stored in the database
# update the relevant field using @id as key
if SmartSession::SqlSession.locking_enabled?
connection.query("UPDATE #{SmartSession::SqlSession.table_name} SET \"updated_at\"=NOW(), \"data\"=#{quoted_data}, lock_version=lock_version+1 WHERE id=#{@id}")
connection.execute("UPDATE #{SmartSession::SqlSession.table_name} SET \"updated_at\"=NOW(), \"data\"=#{quoted_data}, lock_version=lock_version+1 WHERE id=#{@id}")
@lock_version += 1 #if we are here then we hold a lock on the table - we know our version is up to date
else
connection.query("UPDATE #{SmartSession::SqlSession.table_name} SET \"updated_at\"=NOW(), \"data\"=#{quoted_data} WHERE id=#{@id}")
connection.execute("UPDATE #{SmartSession::SqlSession.table_name} SET \"updated_at\"=NOW(), \"data\"=#{quoted_data} WHERE id=#{@id}")
end
else
# if @id is nil, we need to create a new session in the database
# and set @id to the primary key of the inserted record
connection.query("INSERT INTO #{SmartSession::SqlSession.table_name} (\"created_at\", \"updated_at\", \"session_id\", \"data\") VALUES (NOW(), NOW(), #{@quoted_session_id}, #{quoted_data})")
connection.execute("INSERT INTO #{SmartSession::SqlSession.table_name} (\"created_at\", \"updated_at\", \"session_id\", \"data\") VALUES (NOW(), NOW(), #{@quoted_session_id}, #{quoted_data})")
@id = connection.lastval rescue connection.query("select lastval()")[0][0].to_i
@lock_version = 0
end
Expand All @@ -111,7 +111,7 @@ def update_session_optimistically(data)
connection = self.class.session_connection
quoted_data = connection.quote(data)
result = connection.execute("UPDATE #{SmartSession::SqlSession.table_name} SET \"updated_at\"=NOW(), \"data\"=#{quoted_data}, lock_version=lock_version+1 WHERE id=#{@id} AND lock_version=#{@lock_version}")
if result.cmd_tuples == 1
if (result.class == Fixnum and result == 1) or (result.class != Fixnum and result.cmd_tuples == 1)
@lock_version += 1
true
else
Expand Down
4 changes: 2 additions & 2 deletions lib/smart_session/store.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def self.session_class= symbol_or_class
private

def get_session(env, sid)
ActiveRecord::Base.silence do
ActiveRecord::Base.logger.silence_logger do
sid ||= generate_sid
session = find_session(sid)
env[SESSION_RECORD_KEY] = session
Expand All @@ -54,7 +54,7 @@ def get_session(env, sid)
end

def set_session(env, sid, session_data, options)
ActiveRecord::Base.silence do
ActiveRecord::Base.logger.silence_logger do
record = get_session_model(env, sid)

data, session = save_session(record, session_data)
Expand Down
4 changes: 2 additions & 2 deletions smart_session.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ Gem::Specification.new do |gem|
gem.description = %q{A session store that avoids the pitfalls usually associated with concurrent access to the session}
gem.summary = %q{A session store that avoids the pitfalls usually associated with concurrent access to the session}
gem.homepage = ""
gem.add_dependency "actionpack", '>=3.0.0', '< 4.0.0'
gem.add_dependency "activerecord", '>=3.0.0', '< 4.0.0'
gem.add_dependency "actionpack", '>=3.0.0', '< 5.0.0'
gem.add_dependency "activerecord", '>=3.0.0', '< 5.0.0'
gem.add_development_dependency "mysql2"
gem.add_development_dependency "sqlite3"
gem.add_development_dependency "pg"
Expand Down