Move to version 2.3.2 of rails.
authorTom Hughes <tom@compton.nu>
Thu, 4 Jun 2009 08:08:24 +0000 (08:08 +0000)
committerTom Hughes <tom@compton.nu>
Thu, 4 Jun 2009 08:08:24 +0000 (08:08 +0000)
47 files changed:
app/controllers/amf_controller.rb
app/controllers/api_controller.rb
app/controllers/application_controller.rb [moved from app/controllers/application.rb with 99% similarity]
app/controllers/changeset_controller.rb
app/controllers/node_controller.rb
app/controllers/old_node_controller.rb
app/controllers/old_relation_controller.rb
app/controllers/old_way_controller.rb
app/controllers/relation_controller.rb
app/controllers/swf_controller.rb
app/controllers/way_controller.rb
config/boot.rb
config/environment.rb
test/test_helper.rb
test/unit/changeset_tag_test.rb
test/unit/changeset_test.rb
test/unit/diary_comment_test.rb
test/unit/diary_entry_test.rb
test/unit/friend_test.rb
test/unit/message_test.rb
test/unit/node_tag_test.rb
test/unit/node_test.rb
test/unit/old_node_tag_test.rb
test/unit/old_node_test.rb
test/unit/old_relation_tag_test.rb
test/unit/old_way_tag_test.rb
test/unit/relation_member_test.rb
test/unit/relation_tag_test.rb
test/unit/relation_test.rb
test/unit/trace_test.rb
test/unit/tracepoint_test.rb
test/unit/tracetag_test.rb
test/unit/user_test.rb
test/unit/user_token_test.rb
test/unit/way_node_test.rb
test/unit/way_tag_test.rb
test/unit/way_test.rb
vendor/plugins/sql_session_store/LICENSE
vendor/plugins/sql_session_store/README
vendor/plugins/sql_session_store/init.rb
vendor/plugins/sql_session_store/lib/abstract_session.rb [new file with mode: 0644]
vendor/plugins/sql_session_store/lib/mysql_session.rb
vendor/plugins/sql_session_store/lib/oracle_session.rb
vendor/plugins/sql_session_store/lib/postgresql_session.rb
vendor/plugins/sql_session_store/lib/sql_session.rb
vendor/plugins/sql_session_store/lib/sql_session_store.rb
vendor/plugins/sql_session_store/lib/sqlite_session.rb

index 94b09c6fcc084154c22c127c602fa9128562a911..dd04382187e7c760af923c4fc9d8d3d8430fe665 100644 (file)
@@ -43,7 +43,6 @@ class AmfController < ApplicationController
   # Help methods for checking boundary sanity and area size
   include MapBoundary
 
-  session :off
   before_filter :check_api_writable
 
   # Main AMF handlers: process the raw AMF string (using AMF library) and
index 31871921949c6f4c9fb6985f54903d60a6a05648..564f718993d2642433a7a44bbdfe7f4385f5f9a6 100644 (file)
@@ -1,6 +1,5 @@
 class ApiController < ApplicationController
 
-  session :off
   before_filter :check_api_readable, :except => [:capabilities]
   after_filter :compress_output
   around_filter :api_call_handle_error, :api_call_timeout
similarity index 99%
rename from app/controllers/application.rb
rename to app/controllers/application_controller.rb
index 6ead2d6685f260f32665bd321958ad5b81dfd66d..d7debcb6d43ffb7e40c48e29f352fff930da9198 100644 (file)
@@ -113,7 +113,7 @@ class ApplicationController < ActionController::Base
 
     I18n.locale = request.compatible_language_from(I18n.available_locales)
 
-    response.headers['Content-Language'] = I18n.locale
+    response.headers['Content-Language'] = I18n.locale.to_s
   end
 
   def api_call_handle_error
index 469d45f35daac89b945dbf82a4952ddfdd22795e..ca42751d37ac670c4504d5a492e9012af6826f00 100644 (file)
@@ -4,7 +4,6 @@ class ChangesetController < ApplicationController
   layout 'site'
   require 'xml/libxml'
 
-  session :off, :except => [:list, :list_user, :list_bbox]
   before_filter :authorize_web, :only => [:list, :list_user, :list_bbox]
   before_filter :set_locale, :only => [:list, :list_user, :list_bbox]
   before_filter :authorize, :only => [:create, :update, :delete, :upload, :include, :close]
index eeaba6199a9ad346970e0688e7bcd70907534045..19add265d02823d2ca9178bf78968feee3edd4ed 100644 (file)
@@ -3,7 +3,6 @@
 class NodeController < ApplicationController
   require 'xml/libxml'
 
-  session :off
   before_filter :authorize, :only => [:create, :update, :delete]
   before_filter :require_public_data, :only => [:create, :update, :delete]
   before_filter :check_api_writable, :only => [:create, :update, :delete]
index 5de39fdb60a1f5ddb45a125b36c4b83e1749518c..c20dacf4800620f851577e6d146fe2d8fb5d4bde 100644 (file)
@@ -1,7 +1,6 @@
 class OldNodeController < ApplicationController
   require 'xml/libxml'
 
-  session :off
   before_filter :check_api_readable
   after_filter :compress_output
   around_filter :api_call_handle_error, :api_call_timeout
index 5bde0fe6c9367c7c11b0fedf1632383dd0e7d23d..eb274c4de32bf2e7c0e0b8dd8e7ba9ab13e9295e 100644 (file)
@@ -1,7 +1,6 @@
 class OldRelationController < ApplicationController
   require 'xml/libxml'
 
-  session :off
   before_filter :check_api_readable
   after_filter :compress_output
   around_filter :api_call_handle_error, :api_call_timeout
index 1e3546a0d0f09b3bdf6e25b6de67ae6a0952cb83..96c88d492dc777f7bb5f61c63dea885ddf83a462 100644 (file)
@@ -1,7 +1,6 @@
 class OldWayController < ApplicationController
   require 'xml/libxml'
 
-  session :off
   before_filter :check_api_readable
   after_filter :compress_output
   around_filter :api_call_handle_error, :api_call_timeout
index e1f23ac74b7301c3207930530bd30352f56e12e8..4f8e2d0b52a344af8cda070bf6db60df938c51c8 100644 (file)
@@ -1,7 +1,6 @@
 class RelationController < ApplicationController
   require 'xml/libxml'
 
-  session :off
   before_filter :authorize, :only => [:create, :update, :delete]
   before_filter :require_public_data, :only => [:create, :update, :delete]
   before_filter :check_api_writable, :only => [:create, :update, :delete]
index 6400bd1fb0bb4ae6fbe081a44b67378ca551cadd..262662c7af45880d939d9ec93731e1ea109d74ed 100644 (file)
@@ -1,5 +1,4 @@
 class SwfController < ApplicationController
-       session :off
        before_filter :check_api_readable
 
 # to log:
index 2cd7abf604b6a37f13248ba9f1fd2db1661e943e..4d345e06382b99dd37db07bbf874c153a5100bbe 100644 (file)
@@ -1,7 +1,6 @@
 class WayController < ApplicationController
   require 'xml/libxml'
 
-  session :off
   before_filter :authorize, :only => [:create, :update, :delete]
   before_filter :require_public_data, :only => [:create, :update, :delete]
   before_filter :check_api_writable, :only => [:create, :update, :delete]
index 0a516880cadc333d0efc41367a56a09dd0654e87..0ad0f787f865effe8a6bf3d922f3fa4730606bdd 100644 (file)
@@ -44,6 +44,7 @@ module Rails
     def load_initializer
       require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
       Rails::Initializer.run(:install_gem_spec_stubs)
+      Rails::GemDependency.add_frozen_gem_path
     end
   end
 
index 8f38f28bed186c1a9acd23617d96b4a59c98cc9b..c7fa3c483ea0ca64964edd71d03c09f12024232f 100644 (file)
@@ -5,7 +5,7 @@
 ENV['RAILS_ENV'] ||= 'production'
 
 # Specifies gem version of Rails to use when vendor/rails is not present
-RAILS_GEM_VERSION = '2.2.2' unless defined? RAILS_GEM_VERSION
+RAILS_GEM_VERSION = '2.3.2' unless defined? RAILS_GEM_VERSION
 
 # Set the server URL
 SERVER_URL = ENV['OSM_SERVER_URL'] || 'www.openstreetmap.org'
index 95b6e7e6766ba669c6451c5da9e5397d765651fe..c210315a96458a96b9b944e2f6c9d7c002c7e030 100644 (file)
@@ -3,7 +3,7 @@ require File.expand_path(File.dirname(__FILE__) + "/../config/environment")
 require 'test_help'
 load 'composite_primary_keys/fixtures.rb'
 
-class Test::Unit::TestCase
+class ActiveSupport::TestCase
   # Transactional fixtures accelerate your tests by wrapping each test method
   # in a transaction that's rolled back on completion.  This ensures that the
   # test database remains unchanged so your fixtures don't have to be reloaded
index 40f9c5ac30d503340194fbeb7342c1061e575b0c..46194b505ff7dc3a92a5005fc55d2b79aba44063 100644 (file)
@@ -1,6 +1,6 @@
 require File.dirname(__FILE__) + '/../test_helper'
 
-class ChangesetTagTest < Test::Unit::TestCase
+class ChangesetTagTest < ActiveSupport::TestCase
   api_fixtures
 
   def test_changeset_tag_count
@@ -14,7 +14,7 @@ class ChangesetTagTest < Test::Unit::TestCase
       tag.id = 1
       tag.k = key*i
       tag.v = "v"
-      assert_valid tag
+      assert tag.valid?
     end
   end
   
@@ -25,7 +25,7 @@ class ChangesetTagTest < Test::Unit::TestCase
       tag.id = 1
       tag.k = "k"
       tag.v = val*i
-      assert_valid tag
+      assert tag.valid?
     end
   end
   
index bc7abe085f553325c1f66d0015faa0dd2ffad539..bd53efc49465ae00cf4bb9fc820d5cbdc08d8550 100644 (file)
@@ -1,6 +1,6 @@
 require File.dirname(__FILE__) + '/../test_helper'
 
-class ChangesetTest < Test::Unit::TestCase
+class ChangesetTest < ActiveSupport::TestCase
   api_fixtures
   
   def test_changeset_count
index 8e2bbf32c215cf177f5c375b850243404ecf5a5e..8c03d6a36522a076546716ba236b7b2b032a6d91 100644 (file)
@@ -1,6 +1,6 @@
 require File.dirname(__FILE__) + '/../test_helper'
 
-class DiaryCommentTest < Test::Unit::TestCase
+class DiaryCommentTest < ActiveSupport::TestCase
   api_fixtures
   fixtures :diary_comments
   
index b28577b992263bd9395d5c245fae423f5a501d31..54ac0175bcbb14b6c3ea46e551a3060110d78e04 100644 (file)
@@ -1,6 +1,6 @@
 require File.dirname(__FILE__) + '/../test_helper'
 
-class DiaryEntryTest < Test::Unit::TestCase
+class DiaryEntryTest < ActiveSupport::TestCase
   api_fixtures
   fixtures :diary_entries, :languages
   
index 8c93146ae11b2fd3d32dbd03834b9e5972505cb4..6416e38c7db48e1035dc4e27049915e54feb2495 100644 (file)
@@ -1,6 +1,6 @@
 require File.dirname(__FILE__) + '/../test_helper'
 
-class FriendTest < Test::Unit::TestCase
+class FriendTest < ActiveSupport::TestCase
   api_fixtures
   fixtures :friends
 
index a732aa58633d67cc1ad98fca66cbae1a48b3d0ed..d40d85f30b15f4350b457ea1b88baf0a31ef36ac 100644 (file)
@@ -1,6 +1,6 @@
 require File.dirname(__FILE__) + '/../test_helper'
 
-class MessageTest < Test::Unit::TestCase
+class MessageTest < ActiveSupport::TestCase
   api_fixtures
   fixtures :messages
 
index fe0f112bf32edd0c0e75d11672c0fb5e6cf653f8..cfe0b57f22b26ae8a5d90402c2fd4d9deecbec5f 100644 (file)
@@ -1,6 +1,6 @@
 require File.dirname(__FILE__) + '/../test_helper'
 
-class NodeTagTest < Test::Unit::TestCase
+class NodeTagTest < ActiveSupport::TestCase
   api_fixtures
   
   def test_tag_count
@@ -24,7 +24,7 @@ class NodeTagTest < Test::Unit::TestCase
       tag.id = current_node_tags(:t1).id
       tag.k = key*i
       tag.v = "v"
-      assert_valid tag
+      assert tag.valid?
     end
   end
   
@@ -35,7 +35,7 @@ class NodeTagTest < Test::Unit::TestCase
       tag.id = current_node_tags(:t1).id
       tag.k = "k"
       tag.v = val*i
-      assert_valid tag
+      assert tag.valid?
     end
   end
   
index d1ec98e0d1b856f3db787f0e26ae06048ed6e0ae..acad7218ca8fc3fafc2118c2fe650de8917970d0 100644 (file)
@@ -1,6 +1,6 @@
 require File.dirname(__FILE__) + '/../test_helper'
 
-class NodeTest < Test::Unit::TestCase
+class NodeTest < ActiveSupport::TestCase
   api_fixtures
   
   def test_node_count
@@ -56,7 +56,7 @@ class NodeTest < Test::Unit::TestCase
     assert_equal dbnode.version, node.version
     assert_equal dbnode.visible, node.visible
     #assert_equal node.tile, QuadTile.tile_for_point(node.lat, node.lon)
-    assert_valid node
+    assert node.valid?
   end
   
   # This helper method will check to make sure that a node is outwith the world, 
index f2203005cc677e119bf0bf7a6cc2a8668e00453a..9acf32bf70837bb132b615b39bcaf79e8570c6ba 100644 (file)
@@ -1,6 +1,6 @@
 require File.dirname(__FILE__) + '/../test_helper'
 
-class OldNodeTest < Test::Unit::TestCase
+class OldNodeTest < ActiveSupport::TestCase
   api_fixtures
 
   def test_old_node_tag_count
@@ -15,7 +15,7 @@ class OldNodeTest < Test::Unit::TestCase
       tag.version = node_tags(:t1).version
       tag.k = key*i
       tag.v = "v"
-      assert_valid tag
+      assert tag.valid?
     end
   end
   
@@ -27,7 +27,7 @@ class OldNodeTest < Test::Unit::TestCase
       tag.version = node_tags(:t1).version
       tag.k = "k"
       tag.v = val*i
-      assert_valid tag
+      assert tag.valid?
     end
   end
   
index eb68baafb26521497c2723f7debdc5bf358fd643..10cb2390096120382450ed55e82efeaf7775fb2d 100644 (file)
@@ -1,6 +1,6 @@
 require File.dirname(__FILE__) + '/../test_helper'
 
-class OldNodeTest < Test::Unit::TestCase
+class OldNodeTest < ActiveSupport::TestCase
   api_fixtures
   
   def test_old_node_count
@@ -56,7 +56,7 @@ class OldNodeTest < Test::Unit::TestCase
     assert_equal dbnode.visible, node.visible
     assert_equal dbnode.timestamp, node.timestamp
     #assert_equal node.tile, QuadTile.tile_for_point(nodes(nod).lat, nodes(nod).lon)
-    assert_valid node
+    assert node.valid?
   end
   
   # This helpermethod will check to make sure that a node is outwith the world, 
index 77874bcc6fd18787bca968082b538525dfa059bd..ece55d8d5da69891f7b876be86d2f46ea3176e23 100644 (file)
@@ -1,6 +1,6 @@
 require File.dirname(__FILE__) + '/../test_helper'
 
-class OldRelationTagTest < Test::Unit::TestCase
+class OldRelationTagTest < ActiveSupport::TestCase
   api_fixtures
   
   def test_tag_count
@@ -15,7 +15,7 @@ class OldRelationTagTest < Test::Unit::TestCase
       tag.version = 1
       tag.k = key*i
       tag.v = "v"
-      assert_valid tag
+      assert tag.valid?
     end
   end
   
@@ -27,7 +27,7 @@ class OldRelationTagTest < Test::Unit::TestCase
       tag.version = 1
       tag.k = "k"
       tag.v = val*i
-      assert_valid tag
+      assert tag.valid?
     end
   end
   
index b2724cb0139c9cf22046ecc3b3e33d2e441b8644..4945c14979392cf43092cac2983f4640f5f201e8 100644 (file)
@@ -1,6 +1,6 @@
 require File.dirname(__FILE__) + '/../test_helper'
 
-class WayTagTest < Test::Unit::TestCase
+class WayTagTest < ActiveSupport::TestCase
   api_fixtures
   
   def test_tag_count
@@ -15,7 +15,7 @@ class WayTagTest < Test::Unit::TestCase
       tag.version = 1
       tag.k = key*i
       tag.v = "v"
-      assert_valid tag
+      assert tag.valid?
     end
   end
   
@@ -27,7 +27,7 @@ class WayTagTest < Test::Unit::TestCase
       tag.version = 1
       tag.k = "k"
       tag.v = val*i
-      assert_valid tag
+      assert tag.valid?
     end
   end
   
index 93fa551800b2dc0277ce82656ac9f9cce88f3b96..b4f817b05c3bd585f89f93de33ad9e9073247dcc 100644 (file)
@@ -1,6 +1,6 @@
 require File.dirname(__FILE__) + '/../test_helper'
 
-class RelationMemberTest < Test::Unit::TestCase
+class RelationMemberTest < ActiveSupport::TestCase
   api_fixtures
   
   def test_relation_member_count
index de31c8da898e03dbb62ee9f4c1e391c88be6e9df..81bcd60acf549f452d5cad3265add0e1df48b0fc 100644 (file)
@@ -1,6 +1,6 @@
 require File.dirname(__FILE__) + '/../test_helper'
 
-class RelationTagTest < Test::Unit::TestCase
+class RelationTagTest < ActiveSupport::TestCase
   api_fixtures
   
   def test_relation_tag_count
@@ -14,7 +14,7 @@ class RelationTagTest < Test::Unit::TestCase
       tag.id = 1
       tag.k = key*i
       tag.v = "v"
-      assert_valid tag
+      assert tag.valid?
     end
   end
   
@@ -25,7 +25,7 @@ class RelationTagTest < Test::Unit::TestCase
       tag.id = 1
       tag.k = "k"
       tag.v = val*i
-      assert_valid tag
+      assert tag.valid?
     end
   end
   
index 6fba2b276eaca76ad11890ecc7ff0aa9d3b82d77..6b23630259a2736f1f4b4a65cf3f72243e6025ba 100644 (file)
@@ -1,6 +1,6 @@
 require File.dirname(__FILE__) + '/../test_helper'
 
-class RelationTest < Test::Unit::TestCase
+class RelationTest < ActiveSupport::TestCase
   api_fixtures
   
   def test_relation_count
index f3fe1b769e133f0bbe4228d9e45ec7e6fb80c158..a39aa4fa2848018c4291d757678671225fe797ba 100644 (file)
@@ -1,6 +1,6 @@
 require File.dirname(__FILE__) + '/../test_helper'
 
-class TraceTest < Test::Unit::TestCase
+class TraceTest < ActiveSupport::TestCase
   api_fixtures
   
   def test_trace_count
index 80534c2cba32edb0b82d06edd9beb1b1e217f8eb..9f85b9c8cfba297fe9e50e16d07de6707c4bcde4 100644 (file)
@@ -1,6 +1,6 @@
 require File.dirname(__FILE__) + '/../test_helper'
 
-class TracepointTest < Test::Unit::TestCase
+class TracepointTest < ActiveSupport::TestCase
   api_fixtures
   
   def test_tracepoint_count
index c61913ff0ff707a74d68eba3f4a3e055c0a02252..41e77dfe47533f206cd740361a98c3727d654069 100644 (file)
@@ -1,6 +1,6 @@
 require File.dirname(__FILE__) + '/../test_helper'
 
-class TracetagTest < Test::Unit::TestCase
+class TracetagTest < ActiveSupport::TestCase
   api_fixtures
   
   def test_tracetag_count
index fb8bab0a5a357f601dbd664eeaa4831fa812457c..184c2436a6d60914b4208d577ab6f9e7b6d0b9d1 100644 (file)
@@ -1,6 +1,6 @@
 require File.dirname(__FILE__) + '/../test_helper'
 
-class UserTest < Test::Unit::TestCase
+class UserTest < ActiveSupport::TestCase
   api_fixtures
   fixtures :friends
 
index 83a36f8d97c9eee2ed53da7e435ba801057f6692..1fe2634541b89c70e6d09c52d364f06ee2baead1 100644 (file)
@@ -1,6 +1,6 @@
 require File.dirname(__FILE__) + '/../test_helper'
 
-class UserTokenTest < Test::Unit::TestCase
+class UserTokenTest < ActiveSupport::TestCase
   api_fixtures
   fixtures :user_tokens
 
index acc62d3306aeaee8156c7db4bab5b9d86e4255e5..edb6558fab11889fde983cf4ad96524415346de5 100644 (file)
@@ -1,6 +1,6 @@
 require File.dirname(__FILE__) + '/../test_helper'
 
-class WayNodeTest < Test::Unit::TestCase
+class WayNodeTest < ActiveSupport::TestCase
   api_fixtures
   
   def test_way_nodes_count
index 018263da11624800c7fda66ee3dc58e558aa3be1..f5a931f6a322389744c93ff0e22254ba8ab36616 100644 (file)
@@ -1,6 +1,6 @@
 require File.dirname(__FILE__) + '/../test_helper'
 
-class WayTagTest < Test::Unit::TestCase
+class WayTagTest < ActiveSupport::TestCase
   api_fixtures
   
   def test_way_tag_count
@@ -14,7 +14,7 @@ class WayTagTest < Test::Unit::TestCase
       tag.id = current_way_tags(:t1).id
       tag.k = key*i
       tag.v = current_way_tags(:t1).v
-      assert_valid tag
+      assert tag.valid?
     end
   end
   
@@ -25,7 +25,7 @@ class WayTagTest < Test::Unit::TestCase
       tag.id = current_way_tags(:t1).id
       tag.k = "k"
       tag.v = val*i
-      assert_valid tag
+      assert tag.valid?
     end
   end
   
index 55ab092ea62da42bc49da01d973f6e8f613b0979..c173454e48a76c4392aa4f2db7abfb48ca963364 100644 (file)
@@ -1,6 +1,6 @@
 require File.dirname(__FILE__) + '/../test_helper'
 
-class WayTest < Test::Unit::TestCase
+class WayTest < ActiveSupport::TestCase
   api_fixtures
 
   # Check that we have the correct number of currnet ways in the db
index 5cb5c7b956aa6ee589c04602176f37dec5c99756..adab131e299aa00e3fad98778ff74aa5180c3a40 100644 (file)
@@ -1,4 +1,4 @@
-Copyright (c) 2006-2008 Dr.-Ing. Stefan Kaes
+Copyright (c) 2006 Dr.-Ing. Stefan Kaes
 
 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the
index 07b083343b3ad55064964b175f66d93763311bb1..593e957cd967579136f6a20aaff9c35bba59d44a 100755 (executable)
@@ -1,8 +1,20 @@
 == SqlSessionStore
 
-See http://railsexpress.de/blog/articles/2005/12/19/roll-your-own-sql-session-store
+This version of SqlSessionStore properly supports both CGI-based sessions (Rails < 2.3)
+and Rack-based sessions released in Rails 2.3.  For the latest version of +SqlSessionStore+,
+see:
 
-Only Mysql, Postgres and Oracle are currently supported (others work,
+    http://github.com/nateware/sql_session_store/tree/master
+
+To install, use:
+
+    script/plugin install git://github.com/nateware/sql_session_store.git
+
+This version also includes the "native columns" feature, which enables +session[:xyz]+
+to map directly to column +xyz+ in the sessions table transparently.  For info,
+scroll down to "Step 4".
+
+Note: Only Mysql, PostgreSQL, and Oracle are currently supported (others work,
 but you won't see much performance improvement).
 
 == Step 1
@@ -10,29 +22,33 @@ but you won't see much performance improvement).
 If you have generated your sessions table using rake db:sessions:create, go to Step 2
 
 If you're using an old version of sql_session_store, run
-    script/generate sql_session_store DB
+
+    script/generate sql_session_store [DB]
+
 where DB is mysql, postgresql or oracle
 
 Then run
-    rake migrate
-or
+
     rake db:migrate
-for edge rails.
+
+to create the sessions table.
 
 == Step 2
 
-Add the code below after the initializer config section:
+Add the code below in +config/environment.rb+, inside the initializers section
 
-    ActionController::CgiRequest::DEFAULT_SESSION_OPTIONS.
-      update(:database_manager => SqlSessionStore)
+  # Use SqlSessionStore instead of the standard ActiveRecord store
+  config.action_controller.session_store = :sql_session_store
 
-Finally, depending on your database type, add
+Then, depending on your database type, add
 
     SqlSessionStore.session_class = MysqlSession
 or
 
     SqlSessionStore.session_class = PostgresqlSession
+
 or
+
     SqlSessionStore.session_class = OracleSession
 
 after the initializer section in environment.rb
@@ -46,6 +62,32 @@ environment.rb:
 
    SqlSession.establish_connection :sessions
 
+== Step 4 (optional)
+
+If you want to store certain pieces of data as actual columns in the 
++sessions+ table transparently, simply update the sessions migration
+to include the columns.  For example, if you wanted to store +user_id+
+and +language+ as columns, your migration might look something like:
+
+    create_table :sessions do |t|
+      t.string  :session_id, :null => false, :references => nil, :unique => true
+      t.integer :user_id
+      t.string  :language
+      t.text    :data
+      t.timestamps
+    end
+
+Then, use the "native columns" feature of the specific database driver:
+
+    OracleSession.native_columns = [:user_id, :language]
+
+This will map these columns transparently for you. Simply access them like
+normal columns:
+
+    session[:user_id]  = @user.id
+    session[:language] = @language
+
+And the appropriate columns in the sessions table will be updated for you.
 
 == IMPORTANT NOTES
 
index 956151ea7927beaf40f3231394f5165f9775c7d8..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100755 (executable)
@@ -1 +0,0 @@
-require 'sql_session_store'\r
diff --git a/vendor/plugins/sql_session_store/lib/abstract_session.rb b/vendor/plugins/sql_session_store/lib/abstract_session.rb
new file mode 100644 (file)
index 0000000..eda907b
--- /dev/null
@@ -0,0 +1,88 @@
+#
+# This is a common base class for database-specific session store implementations
+#
+require 'cgi/session'
+require 'base64'
+
+class AbstractSession
+  # if you need Rails components, and you have a pages which create
+  # new sessions, and embed components insides this pages that need
+  # session access, then you *must* set +eager_session_creation+ to
+  # true (as of Rails 1.0).
+  cattr_accessor :eager_session_creation
+  @@eager_session_creation = false
+
+  # Some attributes you may want to store natively in the database
+  # in actual columns. This allows other models and database queries
+  # to get to the data without having to unmarshal the data blob.
+  # One common example is the user_id of the session, so it can be
+  # related to the users table
+  cattr_accessor :native_columns
+  @@native_columns = []
+
+  # Allow the user to change the table name
+  cattr_accessor :table_name
+  @@table_name = 'sessions'
+
+  cattr_reader :timestamp_columns
+  @@timestamp_columns = [:created_at, :updated_at]
+
+  attr_accessor :id, :session_id, :data
+
+  def initialize(session_id, data, id=nil)
+    @session_id = session_id
+    @data = data
+    @id = id
+  end
+
+  class << self
+    # delete all sessions meeting a given +condition+. it is the
+    # caller's responsibility to pass a valid sql condition
+    def delete_all(condition=nil)
+      if condition
+        session_connection.exec("DELETE FROM sessions WHERE #{condition}")
+      else
+        session_connection.exec("DELETE FROM sessions")
+      end
+    end
+
+    # retrieve the session table connection and get the 'raw' driver connection from it
+    def session_connection
+      SqlSession.connection.raw_connection
+    end
+
+    def unmarshalize(data)
+      Marshal.load(Base64.decode64(data))
+    end
+
+    def marshalize(data)
+      Base64.encode64(Marshal.dump(data))
+    end
+  end
+end
+
+__END__
+
+# This software is released under the MIT license
+#
+# Copyright (c) 2005, 2006, 2008 Stefan Kaes
+# Copyright (c) 2008, 2009 Nate Wiger
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
index 8c86384c9b7bd6596c697e1f909d05b14073a7ff..9469c55de68b08a37e5f38653d82b417e9db4850 100755 (executable)
@@ -1,10 +1,5 @@
 require 'mysql'
 
-# allow access to the real Mysql connection
-class ActiveRecord::ConnectionAdapters::MysqlAdapter
-  attr_reader :connection
-end
-
 # MysqlSession is a down to the bare metal session store
 # implementation to be used with +SQLSessionStore+. It is much faster
 # than the default ActiveRecord implementation.
@@ -13,30 +8,8 @@ end
 # 'data', 'created_at' and 'updated_at'. If you want use other names,
 # you will need to change the SQL statments in the code.
 
-class MysqlSession
-
-  # if you need Rails components, and you have a pages which create
-  # new sessions, and embed components insides this pages that need
-  # session access, then you *must* set +eager_session_creation+ to
-  # true (as of Rails 1.0).
-  cattr_accessor :eager_session_creation
-  @@eager_session_creation = false
-
-  attr_accessor :id, :session_id, :data
-
-  def initialize(session_id, data)
-    @session_id = session_id
-    @data = data
-    @id = nil
-  end
-
+class MysqlSession < AbstractSession
   class << self
-
-    # retrieve the session table connection and get the 'raw' Mysql connection from it
-    def session_connection
-      SqlSession.connection.connection
-    end
-
     # try to find a session with a given +session_id+. returns nil if
     # no such session exists. note that we don't retrieve
     # +created_at+ and +updated_at+ as they are not accessed anywhyere
@@ -44,13 +17,12 @@ class MysqlSession
     def find_session(session_id)
       connection = session_connection
       connection.query_with_result = true
-      session_id = Mysql::quote(session_id)
       result = connection.query("SELECT id, data FROM sessions WHERE `session_id`='#{session_id}' LIMIT 1")
       my_session = nil
       # each is used below, as other methods barf on my 64bit linux machine
       # I suspect this to be a bug in mysql-ruby
       result.each do |row|
-        my_session = new(session_id, row[1])
+        my_session = new(session_id, AbstractSession.unmarshalize(row[1]))
         my_session.id = row[0]
       end
       result.free
@@ -59,12 +31,11 @@ class MysqlSession
 
     # create a new session with given +session_id+ and +data+
     # and save it immediately to the database
-    def create_session(session_id, data)
-      session_id = Mysql::quote(session_id)
+    def create_session(session_id, data={})      
       new_session = new(session_id, data)
       if @@eager_session_creation
         connection = session_connection
-        connection.query("INSERT INTO sessions (`created_at`, `updated_at`, `session_id`, `data`) VALUES (NOW(), NOW(), '#{session_id}', '#{Mysql::quote(data)}')")
+        connection.query("INSERT INTO sessions (`created_at`, `updated_at`, `session_id`, `data`) VALUES (NOW(), NOW(), '#{session_id}', '#{Mysql::quote(AbstractSession.marshalize(data))}')")
         new_session.id = connection.insert_id
       end
       new_session
@@ -90,11 +61,11 @@ class MysqlSession
     if @id
       # if @id is not nil, this is a session already stored in the database
       # update the relevant field using @id as key
-      connection.query("UPDATE sessions SET `updated_at`=NOW(), `data`='#{Mysql::quote(data)}' WHERE id=#{@id}")
+      connection.query("UPDATE sessions SET `updated_at`=NOW(), `data`='#{Mysql::quote(AbstractSession.marshalize(data))}' WHERE id=#{@id}")
     else
       # if @id is nil, we need to create a new session in the database
-      # and set @id to the primary key of the inserted record
-      connection.query("INSERT INTO sessions (`created_at`, `updated_at`, `session_id`, `data`) VALUES (NOW(), NOW(), '#{@session_id}', '#{Mysql::quote(data)}')")
+      # and set @id to the primary key of the inserted record     
+      connection.query("INSERT INTO sessions (`created_at`, `updated_at`, `session_id`, `data`) VALUES (NOW(), NOW(), '#{@session_id}', '#{Mysql::quote(AbstractSession.marshalize(data))}')")
       @id = connection.insert_id
     end
   end
@@ -110,7 +81,7 @@ __END__
 
 # This software is released under the MIT license
 #
-# Copyright (c) 2005-2008 Stefan Kaes
+# Copyright (c) 2005,2006 Stefan Kaes
 
 # Permission is hereby granted, free of charge, to any person obtaining
 # a copy of this software and associated documentation files (the
index 0b82f6391133ee674882862d12f7c34f35e4f312..1247de4a2b75e790d8f1bd27255da3600e2836a5 100755 (executable)
@@ -1,10 +1,5 @@
 require 'oci8'
 
-# allow access to the real Oracle connection
-class ActiveRecord::ConnectionAdapters::OracleAdapter
-  attr_reader :connection
-end
-
 # OracleSession is a down to the bare metal session store
 # implementation to be used with +SQLSessionStore+. It is much faster
 # than the default ActiveRecord implementation.
@@ -15,74 +10,81 @@ end
 #
 # This table layout is compatible with ActiveRecordStore.
 
-class OracleSession
-
-  # if you need Rails components, and you have a pages which create
-  # new sessions, and embed components insides these pages that need
-  # session access, then you *must* set +eager_session_creation+ to
-  # true (as of Rails 1.0). Not needed for Rails 1.1 and up.
-  cattr_accessor :eager_session_creation
-  @@eager_session_creation = false
-
-  attr_accessor :id, :session_id, :data
-
-  def initialize(session_id, data)
-    @session_id = session_id
-    @data = data
-    @id = nil
-  end
-
+class OracleSession < AbstractSession
   class << self
-
-    # retrieve the session table connection and get the 'raw' Oracle connection from it
-    def session_connection
-      SqlSession.connection.connection
-    end
-
     # try to find a session with a given +session_id+. returns nil if
     # no such session exists. note that we don't retrieve
     # +created_at+ and +updated_at+ as they are not accessed anywhyere
     # outside this class.
     def find_session(session_id)
       new_session = nil
-      connection = session_connection
-      result = connection.exec("SELECT id, data FROM sessions WHERE session_id = :a and rownum=1", session_id)
 
       # Make sure to save the @id if we find an existing session
-      while row = result.fetch
-        new_session = new(session_id,row[1].read)
-        new_session.id = row[0]
+      cursor = session_connection.exec(find_session_sql, session_id)
+      if row = cursor.fetch_hash
+        new_session = new(session_id, unmarshalize(row['DATA'].read), row['ID'])
+
+        # Pull out native columns
+        native_columns.each do |col|
+          new_session.data[col] = row[col.to_s.upcase]
+          new_session.data[col] = row[col.to_s.upcase]
+        end
       end
-      result.close
+
+      cursor.close
       new_session
     end
 
     # create a new session with given +session_id+ and +data+
     # and save it immediately to the database
-    def create_session(session_id, data)
+    def create_session(session_id, data={})
       new_session = new(session_id, data)
-      if @@eager_session_creation
-        connection = session_connection
-        connection.exec("INSERT INTO sessions (id, created_at, updated_at, session_id, data)"+
-                        " VALUES (sessions_seq.nextval, SYSDATE, SYSDATE, :a, :b)",
-                         session_id, data)
-        result = connection.exec("SELECT sessions_seq.currval FROM dual")
-        row = result.fetch
-        new_session.id = row[0].to_i
+      if eager_session_creation
+        new_session.id = next_id
+        cursor = session_connection.parse(insert_session_sql)
+
+        # Now bind all variables
+        cursor.bind_param(':id', new_session.id)
+        cursor.bind_param(':session_id', session_id)
+        native_columns.each do |col|
+          cursor.bind_param(":#{col}", data.delete(col) || '')
+        end
+        cursor.bind_param(':data', marshalize(data))
+        cursor.exec
+        cursor.close
       end
       new_session
     end
 
-    # delete all sessions meeting a given +condition+. it is the
-    # caller's responsibility to pass a valid sql condition
-    def delete_all(condition=nil)
-      if condition
-        session_connection.exec("DELETE FROM sessions WHERE #{condition}")
-      else
-        session_connection.exec("DELETE FROM sessions")
-      end
+    # Internal methods for generating SQL
+    # Get the next ID from the sequence
+    def next_id
+      cursor = session_connection.exec("SELECT #{table_name}_seq.nextval FROM dual")
+      id = cursor.fetch.first.to_i
+      cursor.close
+      id
+    end
+
+    # Dynamically generate finder SQL so we can include our special columns
+    def find_session_sql
+      @find_session_sql ||=
+        "SELECT " + ([:id, :data] + native_columns).join(', ') +
+        " FROM #{table_name} WHERE session_id = :session_id AND rownum = 1"
+    end
+
+    def insert_session_sql
+      @insert_session_sql ||=
+        "INSERT INTO #{table_name} (" + ([:id, :data, :session_id] + native_columns + [:created_at, :updated_at]).join(', ') + ")" + 
+        " VALUES (" + ([:id, :data, :session_id] + native_columns).collect{|col| ":#{col}" }.join(', ') + 
+        " , SYSDATE, SYSDATE)"
     end
 
+    def update_session_sql
+      @update_session_sql ||=
+        "UPDATE #{table_name} SET "+
+        ([:data] + native_columns).collect{|col| "#{col} = :#{col}"}.join(', ') +
+        " , updated_at = SYSDATE WHERE ID = :id"
+    end
   end # class methods
 
   # update session with given +data+.
@@ -90,26 +92,33 @@ class OracleSession
   # column `updated_at` will be done by the database itself
   def update_session(data)
     connection = self.class.session_connection
+    cursor = nil
     if @id
       # if @id is not nil, this is a session already stored in the database
       # update the relevant field using @id as key
-      connection.exec("UPDATE sessions SET updated_at = SYSDATE, data = :a WHERE id = :b",
-                       data, @id)
+      cursor = connection.parse(self.class.update_session_sql)
     else
       # if @id is nil, we need to create a new session in the database
       # and set @id to the primary key of the inserted record
-      connection.exec("INSERT INTO sessions (id, created_at, updated_at, session_id, data)"+
-                      " VALUES (sessions_seq.nextval, SYSDATE, SYSDATE, :a, :b)",
-                       @session_id, data)
-      result = connection.exec("SELECT sessions_seq.currval FROM dual")
-      row = result.fetch
-      @id = row[0].to_i
+      @id = self.class.next_id
+
+      cursor = connection.parse(self.class.insert_session_sql)
+      cursor.bind_param(':session_id', @session_id)
+    end
+
+    # These are always the same, as @id is set above!
+    cursor.bind_param(':id', @id, Fixnum) 
+    native_columns.each do |col|
+      cursor.bind_param(":#{col}", data.delete(col) || '')
     end
+    cursor.bind_param(':data', self.class.marshalize(data))
+    cursor.exec
+    cursor.close
   end
 
   # destroy the current session
   def destroy
-    self.class.delete_all("session_id='#{session_id}'")
+    self.class.delete_all(["session_id = ?", session_id])
   end
 
 end
@@ -118,9 +127,9 @@ __END__
 
 # This software is released under the MIT license
 #
-# Copyright (c) 2006-2008 Stefan Kaes
-# Copyright (c) 2006-2008 Tiago Macedo
-# Copyright (c) 2007-2008 Nate Wiger
+# Copyright (c) 2006 Stefan Kaes
+# Copyright (c) 2006 Tiago Macedo
+# Copyright (c) 2007 Nate Wiger
 #
 # Permission is hereby granted, free of charge, to any person obtaining
 # a copy of this software and associated documentation files (the
index 53dc04c73cee359363e029c44415a913a6b8de2d..bf7bf633b70d2ce64c187c70bdda634e511fdb46 100755 (executable)
@@ -1,10 +1,5 @@
 require 'pg'
 
-# allow access to the real Posqtgresql connection
-class ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
-  attr_reader :connection
-end
-
 # PostgresqlSession is a down to the bare metal session store
 # implementation to be used with +SQLSessionStore+. It is much faster
 # than the default ActiveRecord implementation.
@@ -15,30 +10,8 @@ end
 #
 # This table layout is compatible with ActiveRecordStore.
 
-class PostgresqlSession
-
-  # if you need Rails components, and you have a pages which create
-  # new sessions, and embed components insides these pages that need
-  # session access, then you *must* set +eager_session_creation+ to
-  # true (as of Rails 1.0). Not needed for Rails 1.1 and up.
-  cattr_accessor :eager_session_creation
-  @@eager_session_creation = false
-
-  attr_accessor :id, :session_id, :data
-
-  def initialize(session_id, data)
-    @session_id = session_id
-    @data = data
-    @id = nil
-  end
-
+class PostgresqlSession < AbstractSession
   class << self
-
-    # retrieve the session table connection and get the 'raw' Postgresql connection from it
-    def session_connection
-      SqlSession.connection.connection
-    end
-
     # try to find a session with a given +session_id+. returns nil if
     # no such session exists. note that we don't retrieve
     # +created_at+ and +updated_at+ as they are not accessed anywhyere
@@ -47,7 +20,7 @@ class PostgresqlSession
       connection = session_connection
       result = connection.query("SELECT id, data FROM sessions WHERE session_id = $1 LIMIT 1", [session_id])
       if result.ntuples > 0
-        my_session = new(session_id, result.getvalue(0, 1))
+        my_session = new(session_id, AbstractSession.unmarshalize(result.getvalue(0, 1)))
         my_session.id = result.getvalue(0, 0)
       else
         my_session = nil
@@ -58,11 +31,11 @@ class PostgresqlSession
 
     # create a new session with given +session_id+ and +data+
     # and save it immediately to the database
-    def create_session(session_id, data)
+    def create_session(session_id, data={})
       new_session = new(session_id, data)
       if @@eager_session_creation
         connection = session_connection
-        connection.query("INSERT INTO sessions (created_at, updated_at, session_id, data) VALUES (NOW(), NOW(), $1, $2)", [session_id, data])
+        connection.query("INSERT INTO sessions (created_at, updated_at, session_id, data) VALUES (NOW(), NOW(), $1, $2)", [session_id, AbstractSession.marshalize(data)])
         new_session.id = connection.lastval
       end
       new_session
@@ -70,9 +43,9 @@ class PostgresqlSession
 
     # delete all sessions meeting a given +condition+. it is the
     # caller's responsibility to pass a valid sql condition
-    def delete_all(id=nil)
-      if id
-        session_connection.query("DELETE FROM sessions WHERE session_id = $1", [id])
+    def delete_all(condition=nil)
+      if condition
+        session_connection.query("DELETE FROM sessions WHERE #{condition}")
       else
         session_connection.query("DELETE FROM sessions")
       end
@@ -88,11 +61,11 @@ class PostgresqlSession
     if @id
       # if @id is not nil, this is a session already stored in the database
       # update the relevant field using @id as key
-      connection.query("UPDATE sessions SET updated_at = NOW(), data = $1 WHERE id = $2", [data, @id])
+      connection.query("UPDATE sessions SET updated_at = NOW(), data = $1 WHERE id = $2", [AbstractSession.marshalize(data), @id])
     else
       # if @id is nil, we need to create a new session in the database
       # and set @id to the primary key of the inserted record
-      result = connection.query("INSERT INTO sessions (created_at,  updated_at, session_id, data) VALUES (NOW(), NOW(), $1, $2) RETURNING id", [@session_id, data])
+      result = connection.query("INSERT INTO sessions (created_at,  updated_at, session_id, data) VALUES (NOW(), NOW(), $1, $2) RETURNING id", [@session_id, AbstractSession.marshalize(data)])
       @id = result.getvalue(0, 0)
       result.clear
     end
@@ -100,7 +73,7 @@ class PostgresqlSession
 
   # destroy the current session
   def destroy
-    self.class.delete_all(session_id)
+    self.class.delete_all("session_id='#{session_id}'")
   end
 
 end
@@ -109,7 +82,7 @@ __END__
 
 # This software is released under the MIT license
 #
-# Copyright (c) 2006-2008 Stefan Kaes
+# Copyright (c) 2006 Stefan Kaes
 
 # Permission is hereby granted, free of charge, to any person obtaining
 # a copy of this software and associated documentation files (the
index 19d2ad51e281b2d27d0a0edf4a40e14116386508..6db551753264a3a6cf659d8b222bb0047353a7d8 100644 (file)
@@ -1,27 +1,27 @@
-# An ActiveRecord class which corresponds to the database table\r
-# +sessions+. Functions +find_session+, +create_session+,\r
-# +update_session+ and +destroy+ constitute the interface to class\r
-# +SqlSessionStore+.\r
-\r
-class SqlSession < ActiveRecord::Base\r
-  # this class should not be reloaded\r
-  def self.reloadable?\r
-    false\r
-  end\r
-\r
-  # retrieve session data for a given +session_id+ from the database,\r
-  # return nil if no such session exists\r
-  def self.find_session(session_id)\r
-    find :first, :conditions => "session_id='#{session_id}'"\r
-  end\r
-\r
-  # create a new session with given +session_id+ and +data+\r
-  def self.create_session(session_id, data)\r
-    new(:session_id => session_id, :data => data)\r
-  end\r
-\r
-  # update session data and store it in the database\r
-  def update_session(data)\r
-    update_attribute('data', data)\r
-  end\r
-end\r
+# An ActiveRecord class which corresponds to the database table
+# +sessions+. Functions +find_session+, +create_session+,
+# +update_session+ and +destroy+ constitute the interface to class
+# +SqlSessionStore+.
+
+class SqlSession < ActiveRecord::Base
+  # this class should not be reloaded
+  def self.reloadable?
+    false
+  end
+
+  # retrieve session data for a given +session_id+ from the database,
+  # return nil if no such session exists
+  def self.find_session(session_id)
+    find :first, :conditions => { :session_id => session_id }
+  end
+
+  # create a new session with given +session_id+ and +data+
+  def self.create_session(session_id, data)
+    new(:session_id => session_id, :data => data)
+  end
+
+  # update session data and store it in the database
+  def update_session(data)
+    update_attribute('data', data)
+  end
+end
index 8b0ff156f2473dc82c6f3e391f58baea510e911f..0a5fab7f0e7af29ab6a205e35cfeaae2c5a876bd 100755 (executable)
@@ -1,47 +1,98 @@
-require 'active_record'
-require 'cgi'
-require 'cgi/session'
-begin
-  require 'base64'
-rescue LoadError
-end
+require 'base64'
 
 # +SqlSessionStore+ is a stripped down, optimized for speed version of
 # class +ActiveRecordStore+.
 
-class SqlSessionStore
+# Hack for older versions of Rails
+unless defined?(ActionController::Session::AbstractStore)
+  module ActionController
+    module Session
+      class AbstractStore
+      end
+    end
+  end
+end
+
+class SqlSessionStore < ActionController::Session::AbstractStore
 
   # The class to be used for creating, retrieving and updating sessions.
-  # Defaults to SqlSessionStore::Session, which is derived from +ActiveRecord::Base+.
+  # Defaults to SqlSessionStore::SqlSession, which is derived from +ActiveRecord::Base+.
   #
   # In order to achieve acceptable performance you should implement
   # your own session class, similar to the one provided for Myqsl.
   #
   # Only functions +find_session+, +create_session+,
-  # +update_session+ and +destroy+ are required. See file +mysql_session.rb+.
-
+  # +update_session+ and +destroy+ are required. The best implementations
+  # are +postgresql_session.rb+ and +oracle_session.rb+.
   cattr_accessor :session_class
-  @@session_class = SqlSession
+  self.session_class = SqlSession
+
+  # Rack-ism for Rails 2.3.0
+  SESSION_RECORD_KEY = 'rack.session.record'.freeze
+
+  # Backwards-compat indicators (booleans for speed)
+  cattr_accessor :use_rack_session, :use_cgi_session
+  self.use_rack_session = false
+  self.use_cgi_session  = false
+
+  # For Rack compatibility (Rails 2.3.0+)
+  def get_session(env, sid)
+    sid ||= generate_sid
+    #puts "get_session(#{sid})"
+    session = find_or_create_session(sid)
+    env[SESSION_RECORD_KEY] = session
+    [sid, session.data]
+  end
 
-  # Create a new SqlSessionStore instance.
-  #
-  # +session+ is the session for which this instance is being created.
-  #
-  # +option+ is currently ignored as no options are recognized.
+  # For Rack compatibility (Rails 2.3.0+)
+  def set_session(env, sid, session_data)
+    #puts "set_session(#{sid})"
+    session = env[SESSION_RECORD_KEY]
+    session.update_session(session_data)
+    return true # indicate ok to Rack
+  end
 
-  def initialize(session, option=nil)
-    if @session = @@session_class.find_session(session.session_id)
-      @data = unmarshalize(@session.data)
+  # Create a new SqlSessionStore instance. This method hooks into
+  # the find/create methods of a given driver class.
+  #
+  # +session_id+ is the session ID for which this instance is being created.
+  def find_or_create_session(session_id)
+    if @session = session_class.find_session(session_id)
+      @data = @session.data
     else
-      @session = @@session_class.create_session(session.session_id, marshalize({}))
+      @session = session_class.create_session(session_id)
       @data = {}
     end
+    @session
+  end
+
+  # Below here is for pre-Rails 2.3.0 and not used in Rack-based servers
+  # The CGI::Session methods are a bit odd in that half are class and half
+  # are instance-based methods
+  # Note that +option+ is currently ignored as no options are recognized.
+  def initialize(session, options={})
+    # This is just some optimization since this is called over and over and over
+    if self.use_rack_session
+      super # MUST call super for Rack sessions
+      return true
+    elsif self.use_cgi_session
+      find_or_create_session(session.session_id)
+    else
+      version ||= Rails.version.split('.')
+      if version[0].to_i == 2 && version[1].to_i < 3
+        find_or_create_session(session.session_id)
+        self.use_cgi_session = true
+      else
+        super # MUST call super for Rack sessions
+        self.use_rack_session = true
+      end
+    end
   end
 
   # Update the database and disassociate the session object
   def close
     if @session
-      @session.update_session(marshalize(@data))
+      @session.update_session(@data)
       @session = nil
     end
   end
@@ -57,43 +108,33 @@ class SqlSessionStore
   # Restore session data from the session object
   def restore
     if @session
-      @data = unmarshalize(@session.data)
+      @data = @session.data
     end
   end
 
   # Save session data in the session object
   def update
     if @session
-      @session.update_session(marshalize(@data))
+      @session.update_session(@data)
     end
   end
-
-  private
-  if defined?(Base64)
-    def unmarshalize(data)
-      Marshal.load(Base64.decode64(data))
-    end
-
-    def marshalize(data)
-      Base64.encode64(Marshal.dump(data))
-    end
-  else
-    def unmarshalize(data)
-      Marshal.load(data.unpack("m").first)
-    end
-
-    def marshalize(data)
-      [Marshal.dump(data)].pack("m")
-    end
+  
+  def id
+    @session.id
   end
-
 end
 
+class CGI::Session
+  def id
+    @dbman.id
+  end
+end
 __END__
 
 # This software is released under the MIT license
 #
-# Copyright (c) 2005-2008 Stefan Kaes
+# Copyright (c) 2008, 2009 Nate Wiger
+# Copyright (c) 2005, 2006 Stefan Kaes
 
 # Permission is hereby granted, free of charge, to any person obtaining
 # a copy of this software and associated documentation files (the
index 822b232319f041bdd918977b8e225e5cfe48ad9f..e675c488dcbcb8123146947cfbe4d337aa64a50c 100755 (executable)
@@ -1,10 +1,5 @@
 require 'sqlite3'
 
-# allow access to the real Sqlite connection
-#class ActiveRecord::ConnectionAdapters::SQLiteAdapter
-#  attr_reader :connection
-#end
-
 # SqliteSession is a down to the bare metal session store
 # implementation to be used with +SQLSessionStore+. It is much faster
 # than the default ActiveRecord implementation.
@@ -13,37 +8,15 @@ require 'sqlite3'
 # 'data', 'created_at' and 'updated_at'. If you want use other names,
 # you will need to change the SQL statments in the code.
 
-class SqliteSession
-
-  # if you need Rails components, and you have a pages which create
-  # new sessions, and embed components insides this pages that need
-  # session access, then you *must* set +eager_session_creation+ to
-  # true (as of Rails 1.0).
-  cattr_accessor :eager_session_creation
-  @@eager_session_creation = false
-
-  attr_accessor :id, :session_id, :data
-
-  def initialize(session_id, data)
-    @session_id = session_id
-    @data = data
-    @id = nil
-  end
+class SqliteSession < AbstractSession
 
   class << self
-
-    # retrieve the session table connection and get the 'raw' Sqlite connection from it
-    def session_connection
-      SqlSession.connection.instance_variable_get(:@connection)
-    end
-
     # try to find a session with a given +session_id+. returns nil if
     # no such session exists. note that we don't retrieve
     # +created_at+ and +updated_at+ as they are not accessed anywhyere
     # outside this class
     def find_session(session_id)
       connection = session_connection
-      session_id = SQLite3::Database.quote(session_id)
       result = connection.execute("SELECT id, data FROM sessions WHERE `session_id`='#{session_id}' LIMIT 1")
       my_session = nil
       # each is used below, as other methods barf on my 64bit linux machine
@@ -59,7 +32,6 @@ class SqliteSession
     # create a new session with given +session_id+ and +data+
     # and save it immediately to the database
     def create_session(session_id, data)
-      session_id = SQLite3::Database.quote(session_id)
       new_session = new(session_id, data)
       if @@eager_session_creation
         connection = session_connection
@@ -110,8 +82,8 @@ __END__
 
 # This software is released under the MIT license
 #
-# Copyright (c) 2005-2008 Stefan Kaes
-# Copyright (c) 2006-2008 Ted X Toth
+# Copyright (c) 2005, 2006 Stefan Kaes
+# Copyright (c) 2006 Ted X Toth
 
 # Permission is hereby granted, free of charge, to any person obtaining
 # a copy of this software and associated documentation files (the