class ActiveRecord::SessionStore::SqlBypass

A barebones session store which duck-types with the default session store but bypasses Active Record and issues SQL directly. This is an example session model class meant as a basis for your own classes.

The database connection, table name, and session id and data columns are configurable class attributes. Serializing and deserializeing are implemented as class methods that you may override. By default, serializing data is

::Base64.encode64(Marshal.dump(data))

and deserializing data is

Marshal.load(::Base64.decode64(data))

This serializing behavior is intended to store the widest range of binary session data in a text column. For higher performance, store in a blob column instead and forgo the Base64 encoding.

Attributes

connection[W]

Use the ActiveRecord::Base.connection by default.

connection_pool[W]

Use the ActiveRecord::Base.connection_pool by default.

data[W]
new_record[R]
new_record?[R]
session_id[R]

Public Class Methods

connection() click to toggle source
# File lib/active_record/session_store/sql_bypass.rb, line 53
def connection
  @connection ||= ActiveRecord::Base.connection
end
connection_pool() click to toggle source
# File lib/active_record/session_store/sql_bypass.rb, line 57
def connection_pool
  @connection_pool ||= ActiveRecord::Base.connection_pool
end
data_column() click to toggle source

The data field defaults to 'data'.

# File lib/active_record/session_store/sql_bypass.rb, line 41
cattr_accessor :data_column
Also aliased as: data_column_name
data_column_name()
Alias for: data_column
find_by_session_id(session_id) click to toggle source

Look up a session by id and deserialize its data if found.

# File lib/active_record/session_store/sql_bypass.rb, line 62
def find_by_session_id(session_id)
  if record = connection.select_one("SELECT #{connection.quote_column_name(data_column)} AS data FROM #{@@table_name} WHERE #{connection.quote_column_name(@@session_id_column)}=#{connection.quote(session_id.to_s)}")
    new(:session_id => session_id, :serialized_data => record['data'])
  end
end
new(attributes) click to toggle source

Look for normal and serialized data, self.find_by_session_id's way of telling us to postpone deserializing until the data is requested. We need to handle a normal data attribute in case of a new record.

# File lib/active_record/session_store/sql_bypass.rb, line 79
def initialize(attributes)
  @session_id     = attributes[:session_id]
  @data           = attributes[:data]
  @serialized_data = attributes[:serialized_data]
  @new_record     = @serialized_data.nil?
end
session_id_column() click to toggle source

The session id field defaults to 'session_id'.

# File lib/active_record/session_store/sql_bypass.rb, line 35
cattr_accessor :session_id_column
table_name() click to toggle source

The table name defaults to 'sessions'.

# File lib/active_record/session_store/sql_bypass.rb, line 29
cattr_accessor :table_name

Public Instance Methods

data() click to toggle source

Lazy-deserialize session state.

# File lib/active_record/session_store/sql_bypass.rb, line 92
def data
  unless @data
    if @serialized_data
      @data, @serialized_data = self.class.deserialize(@serialized_data) || {}, nil
    else
      @data = {}
    end
  end
  @data
end
destroy() click to toggle source
# File lib/active_record/session_store/sql_bypass.rb, line 131
      def destroy
        return if @new_record

        connect = connection
        connect.delete <<-end_sql, 'Destroy session'
          DELETE FROM #{table_name}
          WHERE #{connect.quote_column_name(session_id_column)}=#{connect.quote(session_id.to_s)}
        end_sql
      end
loaded?() click to toggle source
# File lib/active_record/session_store/sql_bypass.rb, line 103
def loaded?
  @data
end
persisted?() click to toggle source

Returns true if the record is persisted, i.e. it's not a new record

# File lib/active_record/session_store/sql_bypass.rb, line 87
def persisted?
  !@new_record
end
save() click to toggle source
# File lib/active_record/session_store/sql_bypass.rb, line 107
      def save
        return false unless loaded?
        serialized_data = self.class.serialize(data)
        connect        = connection

        if @new_record
          @new_record = false
          connect.update <<-end_sql, 'Create session'
            INSERT INTO #{table_name} (
              #{connect.quote_column_name(session_id_column)},
              #{connect.quote_column_name(data_column)} )
            VALUES (
              #{connect.quote(session_id)},
              #{connect.quote(serialized_data)} )
          end_sql
        else
          connect.update <<-end_sql, 'Update session'
            UPDATE #{table_name}
            SET #{connect.quote_column_name(data_column)}=#{connect.quote(serialized_data)}
            WHERE #{connect.quote_column_name(session_id_column)}=#{connect.quote(session_id)}
          end_sql
        end
      end