Permalink
Browse files

Changed ActiveRecordStore to use Marshal instead of YAML as the latte…

…r 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]

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@866 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
1 parent 9f7a731 commit 19e8b42a56536e0621097c337546557565579c57 @dhh dhh committed Mar 6, 2005
Showing with 25 additions and 10 deletions.
  1. +2 −0 actionpack/CHANGELOG
  2. +23 −10 actionpack/lib/action_controller/session/active_record_store.rb
View
@@ -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]
@@ -3,21 +3,25 @@
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 Session < ActiveRecord::Base
# 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 @@ def delete
# 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
+end

0 comments on commit 19e8b42

Please sign in to comment.