Class: CGI::Session::ActiveRecordStore::SqlBypass
- Defined in:
- lib/action_controller/session/active_record_store.rb
Overview
A barebones session store which duck-types with the default session store but bypasses Active Record and issues SQL directly.
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 Base64.encode64(Marshal.dump(data)) and unmarshaling data is Marshal.load(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.
Constant Summary collapse
- @@table_name =
'sessions'
- @@session_id_column =
'session_id'
- @@data_column =
'data'
Instance Attribute Summary collapse
-
#data ⇒ Object
Lazy-unmarshal session state.
-
#session_id ⇒ Object
readonly
Returns the value of attribute session_id.
Class Method Summary collapse
- .connection ⇒ Object
- .create_table! ⇒ Object
- .drop_table! ⇒ Object
-
.find_by_session_id(session_id) ⇒ Object
Look up a session by id and unmarshal its data if found.
- .fingerprint(data) ⇒ Object
- .marshal(data) ⇒ Object
- .unmarshal(data) ⇒ Object
Instance Method Summary collapse
- #destroy ⇒ Object
-
#initialize(attributes) ⇒ SqlBypass
constructor
Look for normal and marshaled data, self.find_by_session_id’s way of telling us to postpone unmarshaling until the data is requested.
- #new_record? ⇒ Boolean
- #save ⇒ Object
Constructor Details
#initialize(attributes) ⇒ SqlBypass
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.
177 178 179 180 |
# File 'lib/action_controller/session/active_record_store.rb', line 177 def initialize(attributes) @session_id, @data, @marshaled_data = attributes[:session_id], attributes[:data], attributes[:marshaled_data] @new_record = @marshaled_data.nil? end |
Instance Attribute Details
#data ⇒ Object
Lazy-unmarshal session state. Take a fingerprint so we can detect whether to save changes later.
188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/action_controller/session/active_record_store.rb', line 188 def data unless @data if @marshaled_data @fingerprint = self.class.fingerprint(@marshaled_data) @data, @marshaled_data = self.class.unmarshal(@marshaled_data), nil else @data = {} @fingerprint = nil end end @data end |
#session_id ⇒ Object (readonly)
Returns the value of attribute session_id.
171 172 173 |
# File 'lib/action_controller/session/active_record_store.rb', line 171 def session_id @session_id end |
Class Method Details
.connection ⇒ Object
128 129 130 |
# File 'lib/action_controller/session/active_record_store.rb', line 128 def self.connection @@connection ||= ActiveRecord::Base.connection end |
.create_table! ⇒ Object
156 157 158 159 160 161 162 163 164 |
# File 'lib/action_controller/session/active_record_store.rb', line 156 def create_table! @@connection.execute <<-end_sql CREATE TABLE #{table_name} ( id INTEGER PRIMARY KEY, #{@@connection.quote_column_name(session_id_column)} TEXT UNIQUE, #{@@connection.quote_column_name(data_column)} TEXT ) end_sql end |
.drop_table! ⇒ Object
166 167 168 |
# File 'lib/action_controller/session/active_record_store.rb', line 166 def drop_table! @@connection.execute "DROP TABLE #{table_name}" end |
.find_by_session_id(session_id) ⇒ Object
Look up a session by id and unmarshal its data if found.
146 147 148 149 150 |
# File 'lib/action_controller/session/active_record_store.rb', line 146 def find_by_session_id(session_id) if record = @@connection.select_one("SELECT * FROM #{@@table_name} WHERE #{@@session_id_column}=#{@@connection.quote(session_id)}") new(:session_id => session_id, :marshaled_data => record['data']) end end |
.fingerprint(data) ⇒ Object
154 |
# File 'lib/action_controller/session/active_record_store.rb', line 154 def fingerprint(data) Digest::MD5.hexdigest(data) end |
.marshal(data) ⇒ Object
152 |
# File 'lib/action_controller/session/active_record_store.rb', line 152 def marshal(data) Base64.encode64(Marshal.dump(data)) end |
.unmarshal(data) ⇒ Object
153 |
# File 'lib/action_controller/session/active_record_store.rb', line 153 def unmarshal(data) Marshal.load(Base64.decode64(data)) end |
Instance Method Details
#destroy ⇒ Object
225 226 227 228 229 230 231 232 |
# File 'lib/action_controller/session/active_record_store.rb', line 225 def destroy unless @new_record @@connection.delete <<-end_sql, 'Destroy session' DELETE FROM #{@@table_name} WHERE #{@@connection.quote_column_name(@@session_id_column)}=#{@@connection.quote(session_id)} end_sql end end |
#new_record? ⇒ Boolean
182 183 184 |
# File 'lib/action_controller/session/active_record_store.rb', line 182 def new_record? @new_record end |
#save ⇒ Object
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/action_controller/session/active_record_store.rb', line 201 def save marshaled_data = self.class.marshal(data) if @new_record @new_record = false @@connection.update <<-end_sql, 'Create session' INSERT INTO #{@@table_name} ( #{@@connection.quote_column_name(@@session_id_column)}, #{@@connection.quote_column_name(@@data_column)} ) VALUES ( #{@@connection.quote(session_id)}, #{@@connection.quote(marshaled_data)} ) end_sql else old_fingerprint, @fingerprint = @fingerprint, self.class.fingerprint(marshaled_data) if old_fingerprint != @fingerprint @@connection.update <<-end_sql, 'Update session' UPDATE #{@@table_name} SET #{@@connection.quote_column_name(@@data_column)}=#{@@connection.quote(marshaled_data)} WHERE #{@@connection.quote_column_name(@@session_id_column)}=#{@@connection.quote(session_id)} end_sql end end end |