# Replacing ActiveRecordStore::Session with a custom model

**URL:** <https://www.ruby-forum.com/t/replacing-activerecordstore-session-with-a-custom-model/138257>\
**Category:** Rails\
**Created:** [May 21, 2008, 1:28pm UTC](https://www.ruby-forum.com/t/replacing-activerecordstore-session-with-a-custom-model/138257 "2008-05-21T13:28:32Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [May 21, 2008, 1:28pm UTC](https://www.ruby-forum.com/t/replacing-activerecordstore-session-with-a-custom-model/138257/1 "2008-05-21T13:28:32Z")

</div>

Has anyone managed to replace ActiveRecordStore::Session with their  
own model?

In the source ([http://dev.rubyonrails.org/browser/trunk/actionpack/lib/](http://dev.rubyonrails.org/browser/trunk/actionpack/lib/)  
action\_controller/session/active\_record\_store.rb) it says you can  
override the default by setting  
CGI::Session::ActiveRecordStore.session\_class = MySessionClass

I have tried doing this in a number of ways but I get all kinds of  
weird errors, as varied as the methods I’ve tried.

Before you shoot me down for trying to do something I shouldn’t let me  
explain why I want to do this.

I’d like a session model that looks something like:

class Session \< ActiveRecord::Base  
has\_many :product\_viewings, :dependent =\> :destroy  
has\_many :products, :through =\> :product\_viewings, :limit =\>  
10, :include =\> :image

belongs\_to :order  
belongs\_to :user  
end

In my controller I would like to do something like

session.model.user = @user

and

@recently\_viewed\_products = session.model.products

Because I cannot replace ActiveRecordStore::Session with my session  
class above I have to do instead:

session.model.user\_id = @user.id

and

@recently\_viewed\_products =  
Session.find\_by\_session\_id(session.session\_id).products

I don’t think it’s unreasonable to want to treat session.model as a  
first class ActiveRecord model, anything else just seems a bit half-  
baked.

Any ideas on how I could make this happen would be greatly  
appreciated.

Paul Odeon

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [May 22, 2008, 1:19am UTC](https://www.ruby-forum.com/t/replacing-activerecordstore-session-with-a-custom-model/138257/2 "2008-05-22T01:19:02Z")

</div>

Ok I finally nailed it…

I found that using CGI::Session::ActiveRecordStore.session\_class =  
Session worked in production mode but not in dev, I could also make it  
work in dev but only by setting config.cache\_classes = true

In dev it would work on the first page load but crash with a stack too  
deep error on the second and subsequent attempt.

Definitely a dependencies issue then…

All the classes are reloaded on every request, including our custom  
Session class. However, CGI::Session::ActiveRecordStore.session\_class  
is only set on application initialization, and the session\_class  
variable is left holding a stale version of the Session class. What we  
need is a way to update ActiveRecordStore with a fresh Session class  
after every request, the magic line of code to do that is at the end  
of this post.

So to create your own session model with all the ActiveRecord goodness  
follow these steps:

1. config/initializers/session.rb  
CGI::Session::ActiveRecordStore.session\_class = Session

2. app/models/session.rb  
class Session \< CGI::Session::ActiveRecordStore::Session  
has\_many :product\_viewings, :dependent =\> :destroy  
has\_many :products, :through =\> :product\_viewings, :limit =\>  
10, :include =\> :image  
#Or whatever ActiveRecord stuff you like  
end

3. config/environment.rb  
Rails::Initializer.run do |config|  
config.action\_controller.session\_store = :active\_record\_store  
config.to\_prepare { CGI::Session::ActiveRecordStore.session\_class =  
Session if ENV[‘RAILS\_ENV’] == ‘development’ } # This is the one  
end

config.to\_prepare executes the block it is passed before each request  
in rails. In it, we pass the freshly reloaded class to the Session  
store but only in dev.

I hope this helps someone struggling with the same problem…

Cheers

On May 21, 12:27 pm, “removed\_email\_address@domain.invalid”

---

<div class="post-metadata">

**Author:** ![casper\_the\_ghost](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/58956e/32.png) [@casper\_the\_ghost](https://www.ruby-forum.com/u/casper_the_ghost)\
**Post date:** [May 22, 2008, 5:52pm UTC](https://www.ruby-forum.com/t/replacing-activerecordstore-session-with-a-custom-model/138257/3 "2008-05-22T17:52:18Z")

</div>

One small glitch with the above solution

Any of the script/\* and rake scripts seem to fail with some sort of  
dependency error

This is a bug ([http://dev.rubyonrails.org/ticket/10520](http://dev.rubyonrails.org/ticket/10520)) and is  
apparently fixed in 2.0.2, although that’s what I am using and I still  
get the error.

As described in the link above, I put the following above the  
config.to\_prepare block and everything worked perfectly.

#fixes rails bug described here:  
[http://dev.rubyonrails.org/ticket/10520](http://dev.rubyonrails.org/ticket/10520)  
#this monkey patch should be removed when problem is fixed in rails  
module Rails  
class Configuration  
def to\_prepare(&callback)  
after\_initialize do  
require ‘dispatcher’ unless defined?(::Dispatcher)  
Dispatcher.to\_prepare(&callback)  
end  
end  
end  
end

On May 22, 12:18 am, “removed\_email\_address@domain.invalid”
