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. Marshaling and unmarshaling are implemented as class methods that you may override. By default, marshaling data is
ActiveSupport::Base64.encode64(Marshal.dump(data))
and unmarshaling data is
Marshal.load(ActiveSupport::Base64.decode64(data))
This marshaling 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.
- connection
- create_table!
- data
- destroy
- drop_table!
- find_by_session_id
- loaded?
- marshal
- new
- new_record?
- save
- unmarshal
[W] | data | |
[R] | session_id |
[ show source ]
# File activerecord/lib/active_record/session_store.rb, line 182 182: def connection 183: @@connection ||= ActiveRecord::Base.connection 184: end
[ show source ]
# File activerecord/lib/active_record/session_store.rb, line 201 201: def create_table! 202: @@connection.execute "CREATE TABLE \#{table_name} (\nid INTEGER PRIMARY KEY,\n\#{@@connection.quote_column_name(session_id_column)} TEXT UNIQUE,\n\#{@@connection.quote_column_name(data_column)} TEXT\n)\n" 203: end
[ show source ]
# File activerecord/lib/active_record/session_store.rb, line 212 212: def drop_table! 213: @@connection.execute "DROP TABLE #{table_name}" 214: end
[ show source ]
# File activerecord/lib/active_record/session_store.rb, line 187 187: def find_by_session_id(session_id) 188: if record = @@connection.select_one("SELECT * FROM #{@@table_name} WHERE #{@@session_id_column}=#{@@connection.quote(session_id)}") 189: new(:session_id => session_id, :marshaled_data => record['data']) 190: end 191: end
[ show source ]
# File activerecord/lib/active_record/session_store.rb, line 193 193: def marshal(data) 194: ActiveSupport::Base64.encode64(Marshal.dump(data)) if data 195: end
Look for normal and marshaled data, self.find_by_session_id‘s way of telling us to postpone unmarshaling until the data is requested. We need to handle a normal data attribute in case of a new record.
[ show source ]
# File activerecord/lib/active_record/session_store.rb, line 223 223: def initialize(attributes) 224: @session_id, @data, @marshaled_data = attributes[:session_id], attributes[:data], attributes[:marshaled_data] 225: @new_record = @marshaled_data.nil? 226: end
[ show source ]
# File activerecord/lib/active_record/session_store.rb, line 197 197: def unmarshal(data) 198: Marshal.load(ActiveSupport::Base64.decode64(data)) if data 199: end
Lazy-unmarshal session state.
[ show source ]
# File activerecord/lib/active_record/session_store.rb, line 233 233: def data 234: unless @data 235: if @marshaled_data 236: @data, @marshaled_data = self.class.unmarshal(@marshaled_data) || {}, nil 237: else 238: @data = {} 239: end 240: end 241: @data 242: end
[ show source ]
# File activerecord/lib/active_record/session_store.rb, line 273 273: def destroy 274: unless @new_record 275: @@connection.delete "DELETE FROM \#{@@table_name}\nWHERE \#{@@connection.quote_column_name(@@session_id_column)}=\#{@@connection.quote(session_id)}\n", 'Destroy session' 276: end 277: end
[ show source ]
# File activerecord/lib/active_record/session_store.rb, line 244 244: def loaded? 245: !!@data 246: end
[ show source ]
# File activerecord/lib/active_record/session_store.rb, line 228 228: def new_record? 229: @new_record 230: end
[ show source ]
# File activerecord/lib/active_record/session_store.rb, line 248 248: def save 249: return false if !loaded? 250: marshaled_data = self.class.marshal(data) 251: 252: if @new_record 253: @new_record = false 254: @@connection.update "INSERT INTO \#{@@table_name} (\n\#{@@connection.quote_column_name(@@session_id_column)},\n\#{@@connection.quote_column_name(@@data_column)} )\nVALUES (\n\#{@@connection.quote(session_id)},\n\#{@@connection.quote(marshaled_data)} )\n", 'Create session' 255: else 256: @@connection.update "UPDATE \#{@@table_name}\nSET \#{@@connection.quote_column_name(@@data_column)}=\#{@@connection.quote(marshaled_data)}\nWHERE \#{@@connection.quote_column_name(@@session_id_column)}=\#{@@connection.quote(session_id)}\n", 'Update session' 257: end 258: end