<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>cameronyule.com &#187; models</title>
	<atom:link href="http://cameronyule.com/tags/models/feed" rel="self" type="application/rss+xml" />
	<link>http://cameronyule.com</link>
	<description>Glasgow based new media developer Cameron Yule.</description>
	<lastBuildDate>Fri, 22 Jan 2010 12:53:38 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Auditing models with user_stamp</title>
		<link>http://cameronyule.com/2008/10/auditing-models-with-user_stamp</link>
		<comments>http://cameronyule.com/2008/10/auditing-models-with-user_stamp#comments</comments>
		<pubDate>Fri, 24 Oct 2008 09:39:01 +0000</pubDate>
		<dc:creator>Cameron</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[audit]]></category>
		<category><![CDATA[models]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://cameronyule.com/?p=277</guid>
		<description><![CDATA[As part of a CMS I&#8217;m building I wanted the ability to audit user interaction with data, to prevent the situation where content is being created, deleted or edited with no record of who did what and when. John Nunemaker recently released his User Stamp plug-in which stamps records with the ID of the users that [...]]]></description>
			<content:encoded><![CDATA[<p>As part of a CMS I&#8217;m building I wanted the ability to audit user interaction with data, to prevent the situation where content is being created, deleted or edited with no record of who did what and when.</p>
<p>John Nunemaker recently released his <a href="http://railstips.org/2008/10/17/who-done-what-a-k-a-user-stamping">User Stamp</a> plug-in which stamps records with the ID of the users that created and last updated. The implementation is quite clever, as he&#8217;s managed to work around the usual hack of storing the current user ID in <code>Thread.current</code> to make it accessible to the model by using a Sweeper, as they have access to controllers (and hence the current_user method).</p>
<p>I&#8217;ve taken his code a bit further by creating a Log model which stores a polymorphic reference to the record affected, the event that occurred (e.g. &#8216;deleted&#8217; or &#8216;updated&#8217;), the current user ID and the time it happened.</p>
<p>The Log model;</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> Log <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Base</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># Relationships</span>
  <span style="color:#5A0A0A; font-weight:bold;">belongs_to</span> <span style="color:#ff3333; font-weight:bold;">:user</span>
  <span style="color:#5A0A0A; font-weight:bold;">belongs_to</span> <span style="color:#ff3333; font-weight:bold;">:loggable</span>, <span style="color:#ff3333; font-weight:bold;">:polymorphic</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> <span style="color:#ff3333; font-weight:bold;">:true</span>
&nbsp;
  <span style="color:#008000; font-style:italic;"># Validations</span>
  <span style="color:#5A0A0A; font-weight:bold;">validates_presence_of</span> <span style="color:#ff3333; font-weight:bold;">:loggable_type</span>
  <span style="color:#5A0A0A; font-weight:bold;">validates_presence_of</span> <span style="color:#ff3333; font-weight:bold;">:loggable_id</span>
  <span style="color:#5A0A0A; font-weight:bold;">validates_presence_of</span> <span style="color:#ff3333; font-weight:bold;">:action</span>
  <span style="color:#5A0A0A; font-weight:bold;">validates_presence_of</span> <span style="color:#ff3333; font-weight:bold;">:user</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>The migration;</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#9966CC; font-weight:bold;">class</span> CreateLogs <span style="color:#006600; font-weight:bold;">&lt;</span> <span style="color:#6666ff; font-weight:bold;">ActiveRecord::Migration</span>
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">up</span>
    create_table <span style="color:#ff3333; font-weight:bold;">:logs</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>t<span style="color:#006600; font-weight:bold;">|</span>
      t.<span style="color:#9900CC;">string</span> <span style="color:#ff3333; font-weight:bold;">:loggable_type</span>
      t.<span style="color:#9900CC;">integer</span> <span style="color:#ff3333; font-weight:bold;">:loggable_id</span>
      t.<span style="color:#9900CC;">string</span> <span style="color:#ff3333; font-weight:bold;">:action</span>
      t.<span style="color:#9900CC;">references</span> <span style="color:#ff3333; font-weight:bold;">:user</span>
      t.<span style="color:#9900CC;">timestamps</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
    add_index <span style="color:#ff3333; font-weight:bold;">:logs</span>, <span style="color:#ff3333; font-weight:bold;">:loggable_id</span>
    add_index <span style="color:#ff3333; font-weight:bold;">:logs</span>, <span style="color:#ff3333; font-weight:bold;">:user_id</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#0000FF; font-weight:bold;">self</span>.<span style="color:#9900CC;">down</span>
    drop_table <span style="color:#ff3333; font-weight:bold;">:logs</span>
  <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Additional callback methods added to <code>UserStampSweeper</code>;</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;">  <span style="color:#9966CC; font-weight:bold;">def</span> <span style="color:#5A0A0A; font-weight:bold;">after_create</span><span style="color:#006600; font-weight:bold;">&#40;</span>record<span style="color:#006600; font-weight:bold;">&#41;</span>
    add_log<span style="color:#006600; font-weight:bold;">&#40;</span>record, <span style="color:#996600;">'created'</span><span style="color:#006600; font-weight:bold;">&#41;</span>    
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> after_update<span style="color:#006600; font-weight:bold;">&#40;</span>record<span style="color:#006600; font-weight:bold;">&#41;</span>
    add_log<span style="color:#006600; font-weight:bold;">&#40;</span>record, <span style="color:#996600;">'updated'</span><span style="color:#006600; font-weight:bold;">&#41;</span>    
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  <span style="color:#9966CC; font-weight:bold;">def</span> after_destroy<span style="color:#006600; font-weight:bold;">&#40;</span>record<span style="color:#006600; font-weight:bold;">&#41;</span>
    add_log<span style="color:#006600; font-weight:bold;">&#40;</span>record, <span style="color:#996600;">'delete'</span><span style="color:#006600; font-weight:bold;">&#41;</span>    
  <span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
  private
  <span style="color:#9966CC; font-weight:bold;">def</span> add_log<span style="color:#006600; font-weight:bold;">&#40;</span>record, action<span style="color:#006600; font-weight:bold;">&#41;</span>
    Log.<span style="color:#9900CC;">create</span><span style="color:#006600; font-weight:bold;">&#40;</span>
      <span style="color:#ff3333; font-weight:bold;">:loggable_type</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> record.<span style="color:#9966CC; font-weight:bold;">class</span>.<span style="color:#5A0A0A; font-weight:bold;">to_s</span>, 
      <span style="color:#ff3333; font-weight:bold;">:loggable_id</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> record.<span style="color:#9900CC;">id</span>, 
      <span style="color:#ff3333; font-weight:bold;">:action</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> action, 
      <span style="color:#ff3333; font-weight:bold;">:user</span> <span style="color:#006600; font-weight:bold;">=&gt;</span> current_user
    <span style="color:#006600; font-weight:bold;">&#41;</span>
  <span style="color:#9966CC; font-weight:bold;">end</span></pre></div></div>

<p>Displaying the logs;</p>

<div class="wp_syntax"><div class="code"><pre class="rails" style="font-family:monospace;"><span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#9966CC; font-weight:bold;">for</span> log <span style="color:#9966CC; font-weight:bold;">in</span> <span style="color:#0066ff; font-weight:bold;">@logs</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>
  &lt;tr&gt;
    &lt;td&gt;<span style="color:#006600; font-weight:bold;">&lt;%</span>= <span style="color:#5A0A0A; font-weight:bold;">link_to</span> <span style="color:#006600; font-weight:bold;">&#40;</span>h log.<span style="color:#9900CC;">loggable</span>.<span style="color:#9900CC;">log_name</span><span style="color:#006600; font-weight:bold;">&#41;</span>, <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:admin</span>, log.<span style="color:#9900CC;">loggable</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>&lt;/td&gt;
    &lt;td&gt;<span style="color:#006600; font-weight:bold;">&lt;%</span>= h log.<span style="color:#9900CC;">loggable_type</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>&lt;/td&gt;
    &lt;td&gt;<span style="color:#006600; font-weight:bold;">&lt;%</span>= h log.<span style="color:#9900CC;">action</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>&lt;/td&gt;
     &lt;td&gt;<span style="color:#006600; font-weight:bold;">&lt;%</span>= <span style="color:#5A0A0A; font-weight:bold;">link_to</span> <span style="color:#006600; font-weight:bold;">&#40;</span>h log.<span style="color:#9900CC;">user</span>.<span style="color:#9900CC;">display_name</span><span style="color:#006600; font-weight:bold;">&#41;</span>, <span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#ff3333; font-weight:bold;">:admin</span>, log.<span style="color:#9900CC;">user</span><span style="color:#006600; font-weight:bold;">&#93;</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>&lt;/td&gt;
    &lt;td&gt;<span style="color:#006600; font-weight:bold;">&lt;%</span>= log.<span style="color:#9900CC;">created_at</span>.<span style="color:#5A0A0A; font-weight:bold;">to_s</span> <span style="color:#006600; font-weight:bold;">%&gt;</span>&lt;/td&gt;
  &lt;/tr&gt;
<span style="color:#006600; font-weight:bold;">&lt;%</span> <span style="color:#9966CC; font-weight:bold;">end</span> <span style="color:#006600; font-weight:bold;">%&gt;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://cameronyule.com/2008/10/auditing-models-with-user_stamp/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
