aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionpack/CHANGELOG2
-rw-r--r--actionpack/lib/action_controller/session/active_record_store.rb33
2 files changed, 25 insertions, 10 deletions
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index 961a76e54e..7bd651cd48 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -1,5 +1,7 @@
*SVN*
+* Changed ActiveRecordStore to use Marshal instead of YAML as the latter proved troublesome in persisting circular dependencies. Updating existing applications MUST clear their existing session table from data to start using this updated store #739 [Jamis Buck]
+
* Added shortcut :id assignment to render_component and friends (before you had to go through :params) #784 [Lucas Carlson]
* Fixed that map.connect should convert arguments to strings #780 [Nicholas Seckar]
diff --git a/actionpack/lib/action_controller/session/active_record_store.rb b/actionpack/lib/action_controller/session/active_record_store.rb
index 9e0db037d0..6238b8cbee 100644
--- a/actionpack/lib/action_controller/session/active_record_store.rb
+++ b/actionpack/lib/action_controller/session/active_record_store.rb
@@ -3,21 +3,25 @@ begin
require 'active_record'
require 'cgi'
require 'cgi/session'
+require 'base64'
# Contributed by Tim Bates
class CGI
class Session
- # ActiveRecord database based session storage class.
+ # Active Record database-based session storage class.
#
# Implements session storage in a database using the ActiveRecord ORM library. Assumes that the database
# has a table called +sessions+ with columns +id+ (numeric, primary key), +sessid+ and +data+ (text).
- # The session data is stored in the +data+ column in YAML format; the user is responsible for ensuring that
- # only data that can be YAMLized is stored in the session.
+ # The session data is stored in the +data+ column in the binary Marshal format; the user is responsible for ensuring that
+ # only data that can be Marshaled is stored in the session.
+ #
+ # Adding +created_at+ or +updated_at+ datetime columns to the sessions table will enable stamping of the data, which can
+ # be used to clear out old sessions.
+ #
+ # It's highly recommended to have an index on the sessid column to improve performance.
class ActiveRecordStore
# The ActiveRecord class which corresponds to the database table.
class Session < ActiveRecord::Base
- serialize :data
- # Isn't this class definition beautiful?
end
# Create a new ActiveRecordStore instance. This constructor is used internally by CGI::Session.
@@ -30,8 +34,8 @@ class CGI
# This session's ActiveRecord database row will be created if it does not exist, or opened if it does.
def initialize(session, option=nil)
ActiveRecord::Base.silence do
- @session = Session.find_by_sessid(session.session_id) || Session.new("sessid" => session.session_id, "data" => {})
- @data = @session.data
+ @session = Session.find_by_sessid(session.session_id) || Session.new("sessid" => session.session_id, "data" => marshalize({}))
+ @data = unmarshalize(@session.data)
end
end
@@ -52,18 +56,27 @@ class CGI
# Restore session state from the session's ActiveRecord object.
def restore
return unless @session
- @data = @session.data
+ @data = unmarshalize(@session.data)
end
# Save session state in the session's ActiveRecord object.
def update
return unless @session
- ActiveRecord::Base.silence { @session.update_attribute "data", @data }
+ ActiveRecord::Base.silence { @session.update_attribute "data", marshalize(@data) }
end
+
+ private
+ def unmarshalize(data)
+ Marshal.load(Base64.decode64(data))
+ end
+
+ def marshalize(data)
+ Base64.encode64(Marshal.dump(data))
+ end
end #ActiveRecordStore
end #Session
end #CGI
rescue LoadError
# Couldn't load Active Record, so don't make this store available
-end \ No newline at end of file
+end