Permalink
Browse files

Merged in new-sessions branch

  • Loading branch information...
fabien committed Sep 7, 2008
1 parent dde7edf commit 9e68fba7d4d3f7a560a57e628fd34bd253575b6c
@@ -316,11 +316,6 @@ def local_database?(config, &block)
end
namespace :sessions do
- desc "Create sessions table"
- task :create => :merb_start do
- Merb::ActiveRecordSession.create_table!
- end
-
desc "Clear the sessions table"
task :clear => :merb_start do
session_table = 'session'
@@ -330,10 +325,6 @@ def local_database?(config, &block)
end
end
-def session_table_name
- ActiveRecord::Base.pluralize_table_names ? :sessions : :session
-end
-
def set_firebird_env(config)
ENV["ISC_USER"] = config["username"].to_s if config["username"]
ENV["ISC_PASSWORD"] = config["password"].to_s if config["password"]
@@ -1,4 +1,4 @@
Merb::Generators::SessionMigrationGenerator.template :session_migration_activerecord, :orm => :activerecord do
- source(File.dirname(__FILE__), 'templates/session_migration/schema/migrations/%version%_sessions.rb')
- destination("schema/migrations/#{version}_sessions.rb")
+ source(File.dirname(__FILE__), 'templates/session_migration/schema/migrations/%version%_database_sessions.rb')
+ destination("schema/migrations/#{version}_database_sessions.rb")
end
@@ -3,6 +3,7 @@ def self.up
create_table :sessions do |t|
t.column :session_id, :string
t.column :data, :text
+ t.column :created_at, :datetime
end
add_index :sessions, :session_id
end
@@ -73,13 +73,6 @@ def connect
end
end
- # Registering this ORM lets the user choose active_record as a session
- # in merb.yml's session_store: option.
- def register_session_type
- Merb.register_session_type("activerecord",
- "merb/session/active_record_session",
- "Using ActiveRecord database sessions")
- end
end
end
end
@@ -1,142 +1,65 @@
-require "active_record"
+require 'active_record'
+require 'merb-core/dispatch/session'
+require 'base64'
module Merb
- module SessionMixin
- def setup_session
- before = cookies[_session_id_key]
- request.session, cookies[_session_id_key] = Merb::ActiveRecordSession.persist(cookies[_session_id_key])
- @_fingerprint = Marshal.dump(request.session.data).hash
- @_new_cookie = cookies[_session_id_key] != before
- end
- def finalize_session
- request.session.save if @_fingerprint != Marshal.dump(request.session.data).hash
- set_cookie(_session_id_key, request.session.session_id, Time.now + _session_expiry) if (@_new_cookie || request.session.needs_new_cookie)
- end
+ # 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
- def session_store_type
- "activerecord"
- end
- end # ActiveRecordMixin
-
- class ActiveRecordSession < ::ActiveRecord::Base
- set_table_name 'sessions'
- # 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!
- attr_accessor :needs_new_cookie
-
+ serialize :data
+
class << self
- # Generates a new session ID and creates a row for the new session in the database.
- def generate
- create(:session_id => Merb::SessionMixin::rand_uuid, :data => {})
- end
-
- # Gets the existing session based on the <tt>session_id</tt> available in cookies.
- # If none is found, generates a new session.
- def persist(session_id)
- if session_id
- session = find_by_session_id(session_id)
- end
- unless session
- session = generate
+
+ # ==== 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
- [session, session.session_id]
- end
-
- # Don't try to reload ARStore::Session in dev mode.
- def reloadable?
- false
- end
-
- 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
-
- def create_table!
- connection.execute <<-end_sql
- CREATE TABLE #{table_name} (
- id INTEGER PRIMARY KEY,
- #{connection.quote_column_name('session_id')} TEXT UNIQUE,
- #{connection.quote_column_name(@@data_column_name)} TEXT(255)
- )
- end_sql
+ # ==== 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
- def drop_table!
- connection.execute "DROP TABLE #{table_name}"
+ # ==== 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
- end
-
- # Regenerate the Session ID
- def regenerate
- update_attributes(:session_id => Merb::SessionMixin::rand_uuid)
- self.needs_new_cookie = true
- end
-
- # Recreates the cookie with the default expiration time
- # Useful during log in for pushing back the expiration date
- def refresh_expiration
- self.needs_new_cookie = true
- end
-
- # Lazy-delete of session data
- def delete(key = nil)
- key ? self.data.delete(key) : self.data.clear
- end
-
- def [](key)
- data[key]
- end
-
- def empty?
- data.empty?
- end
-
- def each(&b)
- data.each(&b)
+
end
- def each_with_index(&b)
- data.each_with_index(&b)
- end
+ end
- def []=(key, val)
- data[key] = val
- end
+ class ActiveRecordSession < SessionStoreContainer
- # Lazy-unmarshal session state.
- def data
- @data ||= self.class.unmarshal(read_attribute(@@data_column_name)) || {}
- end
-
- # Has the session been loaded yet?
- def loaded?
- !! @data
- end
-
- private
- attr_writer :data
-
- 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
- # ActionController::SessionOverflowError.
- def raise_on_session_data_overflow!
- return false if !loaded?
- limit = self.class.data_column_size_limit
- if loaded? and limit and read_attribute(@@data_column_name).size > limit
- raise MerbController::SessionOverflowError
- end
- end
- end # ActiveRecordSessionMixin
-end # Merb
+ # The session store type
+ self.session_store_type = :activerecord
+
+ # The store object is the model class itself
+ self.store = ActiveRecordSessionStore
+
+ end
+
+end
@@ -1,5 +1,7 @@
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"))
@@ -9,7 +11,10 @@ class Merb::Orms::ActiveRecord::Connect < Merb::BootLoader
def self.run
Merb::Orms::ActiveRecord.connect
- Merb::Orms::ActiveRecord.register_session_type
+ if Merb::Config.session_stores.include?(:activerecord)
+ Merb.logger.debug "Using ActiveRecord sessions"
+ require File.join(File.dirname(__FILE__) / "merb" / "session" / "active_record_session")
+ end
end
end
@@ -0,0 +1,57 @@
+$:.push File.join(File.dirname(__FILE__), '..', 'lib')
+require 'merb-core'
+require 'merb-core/test'
+require 'merb-core/test/helpers'
+
+Merb::BootLoader.before_app_loads do
+ require "merb/session/active_record_session"
+end
+
+Merb.start_environment( :environment => 'test', :adapter => 'runner',
+ :session_store => 'activerecord')
+
+Spec::Runner.configure do |config|
+ config.include Merb::Test::RequestHelper
+end
+
+require 'merb_activerecord'
+ActiveRecord::Base.establish_connection(:adapter => "sqlite3",
+ :dbfile => ":memory:")
+
+ActiveRecord::Schema.define do
+ create_table :sessions do |t|
+ t.column :session_id, :string
+ t.column :data, :text
+ t.column :created_at, :datetime
+ end
+end
+
+# Load up the shared specs from merb-core
+if (gem_spec = Gem.source_index.search('merb-core').last) &&
+ gem_spec.files.include?('spec/public/session/controllers/sessions.rb')
+ require gem_spec.full_gem_path / 'spec/public/session/controllers/sessions.rb'
+ require gem_spec.full_gem_path / 'spec/public/session/session_spec.rb'
+end
+
+describe Merb::ActiveRecordSession do
+
+ before do
+ @session_class = Merb::ActiveRecordSession
+ @session = @session_class.generate
+ end
+
+ it_should_behave_like "All session-store backends"
+
+ it "should have a session_store_type class attribute" do
+ @session.class.session_store_type.should == :activerecord
+ end
+
+end
+
+describe Merb::ActiveRecordSession, "mixed into Merb::Controller" do
+
+ before(:all) { @session_class = Merb::ActiveRecordSession }
+
+ it_should_behave_like "All session-stores mixed into Merb::Controller"
+
+end
@@ -10,14 +10,12 @@
end
end
-
-
describe "Merb ActiveRecord extension" do
before :all do
@wd = Dir.pwd
Merb.stub!(:dir_for).with(:config).and_return(@wd)
- @config_file_path = @wd / "database.yml"
- @sample_file_path = @wd / "database.yml.sample"
+ @config_file_path = @wd / "config" / "database.yml"
+ @sample_file_path = @wd / "config" / "database.yml.sample"
@sample_source = Merb::Orms::ActiveRecord.sample_source
@config_sample = Erubis.load_yaml_file(@sample_source)
@@ -52,11 +50,6 @@
@config_sample[:development][:encoding].should == "utf8"
end
- it "stores configurations from config file" do
- Erubis.should_receive(:load_yaml_file).with(@config_file_path).and_return(@config_sample)
- Merb::Orms::ActiveRecord.configurations[:development][:database].should == "sample_development"
- end
-
it "provides Rack with a way to start a transcantion" do
Merb::Orms::ActiveRecord.should respond_to(:open_sandbox!)
end
@@ -1,5 +1,4 @@
$TESTING = true
$:.push File.join(File.dirname(__FILE__), '..', 'lib')
require 'merb-core'
-require 'merb_activerecord'
-require 'merb/test/model_helper/active_record'
+require 'merb_activerecord'
Oops, something went wrong.

0 comments on commit 9e68fba

Please sign in to comment.