<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Mad Marmot: Tag ActiveRecordStore</title>
    <link>http://www.lukeludwig.com/blog/articles/tag/activerecordstore</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>A blog about programming, ruby, rails, and my crazy outdoor pursuits</description>
    <item>
      <title>How to add a new column to Rails' sessions</title>
      <description>&lt;p&gt;For a rails app at work we store user access privileges in the session.&amp;nbsp; This is done as an optimization to avoid an extra sql query that would need to be done for every page view to determine if the user has edit privileges.&amp;nbsp; Security-minded people may see this as a security hole.&amp;nbsp; For this application I don&amp;#39;t see this as a big deal.&amp;nbsp; Its not like our rails app is controlling the launch of nuclear missiles.&amp;nbsp;&amp;nbsp; &lt;/p&gt;&lt;p&gt;The problem is that when an admin goes to modify the user access privileges for someone, the changes won&amp;#39;t take affect until the user next logs in since the user access privileges are stored in the session. So if the user is already logged in this is a problem. They will have to log out and log back in for the changes to take affect. The solution to this problem is to modify the session of the user who&amp;#39;s access privileges were modified.&amp;nbsp; &lt;/p&gt;&lt;p&gt;To do this we need to add a user_id column to the sessions table. This can be done like any other migration. The tricky part is accessing the user_id column. We will want to set the user_id of the session when someone logs in. This of course will not work:&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; session.user_id = @user.id&lt;/font&gt; &lt;/p&gt;

&lt;p&gt;The session we are so familiar with is not like other ActiveRecord objects. If you are using ActiveRecordStore for your session storage (the rails built-in database session storage mechanism), this is easy. For ActiveRecordStore, the session has a model attribute allowing you to access the ActiveRecord session object. First you need to make a session model class which extends ActiveRecord. Mine looked lke this:&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; class Session &amp;lt; ActiveRecord::Base &lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; end&lt;/font&gt; &lt;/p&gt;&lt;p&gt;Then inside your &amp;quot;login&amp;quot; action you can do:&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; session.model.user_id = @user.id&lt;/font&gt;&lt;/p&gt;&lt;p&gt;Then just rely on the automatic session saving built into rails to save the user_id to the database.&amp;nbsp;&lt;/p&gt;&lt;p&gt;If you are using SqlSessionStore, you don&amp;#39;t have access to the model attribute. Instead you can do this to set the user_id:&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; my_session = Session.find_by_session_id(session.session_id)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; my_session.update_attribute(:user_id, current_user.id)&lt;/font&gt;&lt;/p&gt;&lt;p&gt;Now presumably at some point in your application you will need to access and make use of the user_id column. For me this is when the user access privileges are modified. Since we created a session.rb model class, we can use the built in rails find method to find all sessions for the user. &lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; sessions = Session.find(:all, :conditions =&amp;gt; &amp;quot;user_id = #{user.id}&amp;quot;, :select =&amp;gt; &amp;quot;session_id&amp;quot;)&amp;nbsp;&lt;/font&gt;&lt;/p&gt;&lt;p&gt;To take advantage of the built-in session data marshaling in rails, we need to access the session like this:&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; user_session = &lt;span class="caps"&gt;CGI&lt;/span&gt;::Session::ActiveRecordStore::Session.find_by_session_id(sess.session_id)&lt;/font&gt;&lt;/p&gt;&lt;p&gt;Then we can set a session value using the data attribute and save the session off.&amp;nbsp; Here is the full code for updating the sessions:&lt;/p&gt;&lt;p&gt;&lt;font color="#ff0000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; sessions.each do |sess|&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; user_session = &lt;span class="caps"&gt;CGI&lt;/span&gt;::Session::ActiveRecordStore::Session.find_by_session_id(sess.session_id)&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; user_session.data[:access_privileges] = new_access_privileges&lt;br /&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; user_session.save&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; end &lt;br /&gt;&lt;/font&gt;&lt;/p&gt;</description>
      <pubDate>Mon, 26 Nov 2007 17:59:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:bb8cf08e-09a7-4b7b-a2ee-302495c3108e</guid>
      <author>Luke Ludwig</author>
      <link>http://www.lukeludwig.com/blog/articles/2007/11/26/how-to-add-a-new-column-to-rails-sessions</link>
      <category>Programming</category>
      <category>rails</category>
      <category>sessions</category>
      <category>ActiveRecordStore</category>
      <category>SqlSessionStore</category>
      <trackback:ping>http://www.lukeludwig.com/blog/articles/trackback/5</trackback:ping>
    </item>
  </channel>
</rss>
