Rails Metal and ActiveRecord Sessions
I was playing around in Rails 2.3 and wanted to mess with Metal for a very simple API. The release notes say that it supports sessions — and that may be true for memcache and cookie stores, but I couldn’t get it working with ActiveRecord.
I sniffed around and noticed that abstract stores aren’t getting loaded as of this version (RC1).
# action_controller/session/abstract_store.rb def get_session(env, sid) raise '#get_session needs to be implemented.' end def set_session(env, sid, session_data) raise '#set_session needs to be implemented.' end
So, to work around that, I grabbed the actual get_session code from actioncontroller’s SqlBypass class and got it working within metal:
def self.call(env)
if env["PATH_INFO"] =~ /^\/test/
request = Rack::Request.new(env)
session_options = env['rack.session.options']
sid = request.cookies[session_options[:key]]
session = ActiveRecord::SessionStore::Session.find_by_session_id(sid)
session ||= ActiveRecord::SessionStore::Session.new(:session_id => sid, :data => {})
[200, {"Content-Type" => "text/html"}, session.data.inspect]
else
[404, {"Content-Type" => "text/html"}, ["Not Found"]]
end
end
This has worked so far as I can get the user_id necessary. I’m not sure there is a “just works” way of doing this — but I couldn’t find it and Google didn’t help much.
Hopefully someone out there can make use of this, I scratched me head for a while before just loading the session by hand.
Using Middleware
I just hacked this together and it seems to work (for my testing at least):
# lib/force_active_record_session.rb
module Rack
class ForceActiveRecordSession
def initialize(app, options = {})
@app = app
end
def call(env)
request = Rack::Request.new(env)
sid = request.cookies[env['rack.session.options'][:key]]
env['rack.session.record'] = \
ActiveRecord::SessionStore::Session.find_by_session_id(sid) || \
ActiveRecord::SessionStore::Session.new(:session_id => sid, :data => {})
@app.call(env)
end
end
end
# environment.rb
require 'lib/force_active_record_session.rb'
# environment.rb -- inside Initializer block
config.middleware.insert 5, Rack::ForceActiveRecordSession
# in your metal action
session = env['rack.session.record'].data rescue {}
[200, {"Content-Type" => "text/html"}, session.inspect]







Add Yours
YOU