Skip to content

Instantly share code, notes, and snippets.

@fabien
Created September 2, 2008 20:01
Show Gist options
  • Save fabien/8452 to your computer and use it in GitHub Desktop.
Save fabien/8452 to your computer and use it in GitHub Desktop.
if defined?(Merb::Plugins)
dependency "activerecord"
require File.join(File.dirname(__FILE__) / "merb" / "orms" / "active_record" / "connection")
Merb::Plugins.add_rakefiles(File.join(File.dirname(__FILE__) / "active_record" / "merbtasks"))
class Merb::Orms::ActiveRecord::Connect < Merb::BootLoader
after BeforeAppLoads
def self.run
Merb::Orms::ActiveRecord.connect
if Merb::Config.session_stores.include?(:activerecord)
require File.join(File.dirname(__FILE__) / "merb" / "session" / "active_record_session")
end
end
end
generators = File.join(File.dirname(__FILE__), 'generators')
Merb.add_generators generators / :migration
Merb.add_generators generators / :model
Merb.add_generators generators / :resource_controller
Merb.add_generators generators / :session_migration
end
require 'active_record'
require 'merb-core/dispatch/session'
require 'base64'
module Merb
# Sessions stored in ActiveRecord model.
#
# To use ActiveRecord based sessions add the following to config/init.rb:
#
# Merb::Config[:session_store] = 'activerecord'
class ActiveRecordSessionStore < ::ActiveRecord::Base
table_name = (Merb::Plugins.config[:merb_active_record][:session_table_name] || "sessions")
set_table_name table_name
# Customizable data column name. Defaults to 'data'.
cattr_accessor :data_column_name
self.data_column_name = 'data'
before_save :marshal_data!
before_save :raise_on_session_data_overflow!
class << self
# ==== Parameters
# session_id<String>:: ID of the session to retrieve.
#
# ==== Returns
# ContainerSession:: The session corresponding to the ID.
def retrieve_session(session_id)
if item = find_by_session_id(session_id)
item.data
end
end
# ==== Parameters
# session_id<String>:: ID of the session to set.
# data<ContainerSession>:: The session to set.
def store_session(session_id, data)
if item = find_by_session_id(session_id)
item.update_attributes!(:data => data)
else
create(:session_id => session_id, :data => data)
end
end
# ==== Parameters
# session_id<String>:: ID of the session to delete.
def delete_session(session_id)
delete_all(["#{connection.quote_column_name('session_id')} IN (?)", session_id])
end
# ==== Returns
# Integer:: The maximum length of the 'data' column.
def data_column_size_limit
@data_column_size_limit ||= columns_hash[@@data_column_name].limit
end
def marshal(data)
Base64.encode64(Marshal.dump(data)) if data
end
def unmarshal(data)
Marshal.load(Base64.decode64(data)) if data
end
end
# Lazy-unmarshal session state.
def data
@data ||= self.class.unmarshal(read_attribute(@@data_column_name)) || {}
end
# Virtual attribute writer - override.
def data=(hsh)
@data = hsh if hsh.is_a?(Hash)
end
# Has the session been loaded yet?
def loaded?
!!@data
end
private
# Marshals data before saving.
def marshal_data!
return false if !loaded?
write_attribute(@@data_column_name, self.class.marshal(self.data))
end
# Ensures that the data about to be stored in the database is not
# larger than the data storage column.
#
# ==== Raises
# Merb::SessionMixin::SessionOverflow:: raised if there's too much data.
def raise_on_session_data_overflow!
return false if !loaded?
limit = self.class.data_column_size_limit
if loaded? && limit && read_attribute(@@data_column_name).size > limit
raise Merb::SessionMixin::SessionOverflow
end
end
end
class ActiveRecordSession < SessionStoreContainer
# The session store type
self.session_store_type = :activerecord
# The store object is the model class itself
self.store = ActiveRecordSessionStore
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment