class ActionDispatch::Session::ActiveRecordStore
use it as a basis for high-performance database-specific stores.
The example SqlBypass class is a generic SQL session store. You may
destroy
save
attr_accessor :data
attr_reader :session_id
initialize(hash_of_session_id_and_data, options_hash = {})
self.find_by_session_id(session_id)
You must implement these methods:
ActionDispatch::Session::ActiveRecordStore.session_class = MySessionClass
store, by setting
feature-packed Active Record or a bare-metal high-performance SQL
You may provide your own session class implementation, whether a
the sessions
table, making periodic session expiration a snap.
for free if you add created_at
and updated_at
datetime columns to
Since the default class is a simple Active Record, you get timestamps
on ApplicationController is a good place.
set session.model.id = session.session_id
by hand! A before filter
having a separate id
column if you don’t want it. However, you must
Note that setting the primary key to the session_id
frees you from
ActiveRecord::SessionStore::Session.data_column_name = ‘legacy_session_data’
ActiveRecord::SessionStore::Session.primary_key = ‘session_id’
ActiveRecord::SessionStore::Session.table_name = ‘legacy_session_table’
For example, at the end of config/application.rb
:
You may configure the table name, primary key, and data column.
ActionController::SessionOverflowError will be raised.
If the data you write is larger than the column’s size limit,
Session data is marshaled to the data
column in Base64 format.
The session_id
column should always be indexed for speedy lookups.data
(text or longtext; careful if your session data exceeds 65KB).session_id
(string, usually varchar; maximum length is 255), andid
(numeric primary key),
The default assumes a sessions
tables with columns:
with text session_id
and data
attributes is sufficient.
provided, but any object duck-typing to an Active Record Session class
A session store backed by an Active Record class. A default class is
= Active Record Session Store
def delete_session(request, session_id, options)
def delete_session(request, session_id, options) logger.silence_logger do if sid = current_session_id(request) if model = get_session_model(request, sid) data = model.data model.destroy end end request.env[SESSION_RECORD_KEY] = nil unless options[:drop] new_sid = generate_sid if options[:renew] new_model = @@session_class.new(:session_id => new_sid, :data => data) new_model.save request.env[SESSION_RECORD_KEY] = new_model end new_sid end end end
def find_session(request, id)
def find_session(request, id) model = get_session_model(request, id) [model.session_id, model.data] end
def get_session(request, sid)
def get_session(request, sid) logger.silence_logger do unless sid and session = @@session_class.find_by_session_id(sid) # If the sid was nil or if there is no pre-existing session under the sid, # force the generation of a new sid and associate a new session associated with the new sid sid = generate_sid session = @@session_class.new(:session_id => sid, :data => {}) end request.env[SESSION_RECORD_KEY] = session [sid, session.data] end end
def get_session_model(request, id)
def get_session_model(request, id) logger.silence_logger do model = @@session_class.find_by_session_id(id) if !model id = generate_sid model = @@session_class.new(:session_id => id, :data => {}) model.save end if request.env[ENV_SESSION_OPTIONS_KEY][:id].nil? request.env[SESSION_RECORD_KEY] = model else request.env[SESSION_RECORD_KEY] ||= model end model end end
def logger
def logger ActiveRecord::Base.logger || ActiveRecord::SessionStore::NilLogger end
def write_session(request, sid, session_data, options)
def write_session(request, sid, session_data, options) logger.silence_logger do record = get_session_model(request, sid) record.data = session_data return false unless record.save session_data = record.data if session_data && session_data.respond_to?(:each_value) session_data.each_value do |obj| obj.clear_association_cache if obj.respond_to?(:clear_association_cache) end end sid end end