<?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>Virtuous Code &#187; activerecord</title>
	<atom:link href="http://devblog.avdi.org/tag/activerecord/feed/" rel="self" type="application/rss+xml" />
	<link>http://devblog.avdi.org</link>
	<description>&#34;The three virtues of a programmer: laziness, impatience, and hubris&#34; -- Larry Wall</description>
	<lastBuildDate>Wed, 22 May 2013 22:30:50 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>New maintainer needed for NullDB</title>
		<link>http://devblog.avdi.org/2012/04/13/new-maintainer-needed-for-nulldb/</link>
		<comments>http://devblog.avdi.org/2012/04/13/new-maintainer-needed-for-nulldb/#comments</comments>
		<pubDate>Fri, 13 Apr 2012 17:45:18 +0000</pubDate>
		<dc:creator>Avdi Grimm</dc:creator>
				<category><![CDATA[Announcements]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[nulldb]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://devblog.avdi.org/?p=2237</guid>
		<description><![CDATA[NullDB, for those who don&#8217;t know, is a null backend for ActiveRecord. Unlike RSpec&#8217;s stub_object, rather than raise an exception on DB access, will NullDB DB interactions simply become no-ops. This is handy for things like testing after_save hooks in &#8230; <a href="http://devblog.avdi.org/2012/04/13/new-maintainer-needed-for-nulldb/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p><a href="https://github.com/nulldb/nulldb">NullDB</a>, for those who don&#8217;t know, is a null backend for ActiveRecord. Unlike RSpec&#8217;s stub_object, rather than raise an exception on DB access, will NullDB DB interactions simply become no-ops. This is handy for things like testing after_save hooks in isolation.</p>
<p>Myron Marston has done a stellar job shepherding it through the Rails 3 transition, but he&#8217;s busy with <a href="https://github.com/myronmarston/vcr">other awesome projects</a> now and has asked me to look for a new maintainer. So: If you&#8217;re interested in helping keep NullDB up to date with the latest changes to ActiveRecord, please get in touch!</p>
<p>&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://devblog.avdi.org/2012/04/13/new-maintainer-needed-for-nulldb/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ActiveRecord Default Association Extensions</title>
		<link>http://devblog.avdi.org/2012/01/19/activerecord-default-association-extensions/</link>
		<comments>http://devblog.avdi.org/2012/01/19/activerecord-default-association-extensions/#comments</comments>
		<pubDate>Thu, 19 Jan 2012 19:07:00 +0000</pubDate>
		<dc:creator>Avdi Grimm</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[activerecord]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=1991</guid>
		<description><![CDATA[How to add helper methods to all associations of a given type, as well as to the model class. <a href="http://devblog.avdi.org/2012/01/19/activerecord-default-association-extensions/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Let&#8217;s say we want a helper method <code>#build_fuzzy</code> everywhere we have a collection of socks. </p>
<pre class="src src-ruby"><span class="org-type">Sock</span>.build_fuzzy <span class="org-comment-delimiter"># </span><span class="org-comment">=&gt; #&lt;Sock type: "fuzzy" id: nil drawer_id: nil&gt;</span>
sock_drawer.socks.build_fuzzy <span class="org-comment-delimiter"># </span><span class="org-comment">=&gt; #&lt;Sock type: "fuzzy" id: nil drawer_id: 123&gt;</span>
</pre>
<p> At first we might think to put it in an a collection extension module: </p>
<pre class="src src-ruby"><span class="org-keyword">class</span> <span class="org-type">Sock</span> &lt; <span class="org-type">ActiveRecord</span>::<span class="org-type">Base</span>
  <span class="org-keyword">module</span> <span class="org-type">SockCollectionHelpers</span>
    <span class="org-keyword">def</span> <span class="org-function-name">build_fuzzy</span>
      build(type: <span class="org-string">"fuzzy"</span>)
    <span class="org-keyword">end</span>
  <span class="org-keyword">end</span>
  <span class="org-comment-delimiter"># </span><span class="org-comment">...</span>
<span class="org-keyword">end</span>
</pre>
<p> Now we have to remember to add it to every <code>Sock</code> association: </p>
<pre class="src src-ruby"><span class="org-keyword">class</span> <span class="org-type">Drawer</span> &lt; <span class="org-type">ActiveRecord</span>::<span class="org-type">Base</span>
  has_many <span class="org-constant">:socks</span>, extend: <span class="org-type">Sock</span>::<span class="org-type">SockCollectionHelpers</span>
  <span class="org-comment-delimiter"># </span><span class="org-comment">...</span>
<span class="org-keyword">end</span>
</pre>
<p> And we also need to include it in <code>Sock</code>: </p>
<pre class="src src-ruby"><span class="org-keyword">class</span> <span class="org-type">Sock</span> &lt; <span class="org-type">ActiveRecord</span>::<span class="org-type">Base</span>
  <span class="org-comment-delimiter"># </span><span class="org-comment">...</span>
  extend <span class="org-type">SockCollectionHelpers</span>
<span class="org-keyword">end</span>
</pre>
<p> &hellip;but this doesn&#8217;t work: </p>
<pre class="src src-ruby">sock_drawer.socks.build_fuzzy <span class="org-comment-delimiter"># </span><span class="org-comment">=&gt; #&lt;Sock type: "fuzzy" id: nil drawer_id: 123&gt;</span>
<span class="org-type">Sock</span>.build_fuzzy <span class="org-comment-delimiter"># </span><span class="org-comment">=&gt; Raises no method exception for Sock.build()</span>
</pre>
<p> And anyway, we want this to be available globally without explicitly extending associations. </p>
<p> Next, we try adding a class method to the <code>Sock</code> class. Since ActiveRecord association proxies delegate missing methods to the assoication class, it seems like this should work. </p>
<pre class="src src-ruby"><span class="org-keyword">class</span> <span class="org-type">Sock</span> &lt; <span class="org-type">ActiveRecord</span>::<span class="org-type">Base</span>
  <span class="org-keyword">def</span> <span class="org-function-name">self.build_fuzzy</span>
    build(type: <span class="org-string">"fuzzy"</span>)
  <span class="org-keyword">end</span>
  <span class="org-comment-delimiter"># </span><span class="org-comment">...</span>
<span class="org-keyword">end</span>
</pre>
<p> This is a complete failure. While the association does forward the <code>.build_fuzzy</code> call to <code>Sock</code>, once in the call it is operating in the context of the class object, which as we saw before has no <code>#build</code> method. </p>
<pre class="src src-ruby">sock_drawer.socks.build_fuzzy <span class="org-comment-delimiter"># </span><span class="org-comment">Raises no method exception for Sock.build()</span>
<span class="org-type">Sock</span>.build_fuzzy <span class="org-comment-delimiter"># </span><span class="org-comment">=&gt; Raises no method exception for Sock.build()</span>
</pre>
<p> However, a slight change makes everything work as hoped: </p>
<pre class="src src-ruby"><span class="org-keyword">class</span> <span class="org-type">Sock</span> &lt; <span class="org-type">ActiveRecord</span>::<span class="org-type">Base</span>
  <span class="org-keyword">def</span> <span class="org-function-name">self.build_fuzzy</span>
    scoped.build(type: <span class="org-string">"fuzzy"</span>)
  <span class="org-keyword">end</span>
<span class="org-keyword">end</span>
</pre>
<p> Now when we call <code>#build_fuzzy</code> on the class it builds a fuzzy sock unassociated with any drawer, and when we call it on an association it builds a fuzzy sock with the appropriate drawer ID set: </p>
<pre class="src src-ruby"><span class="org-type">Sock</span>.build_fuzzy <span class="org-comment-delimiter"># </span><span class="org-comment">=&gt; #&lt;Sock type: "fuzzy" id: nil drawer_id: nil&gt;</span>
sock_drawer.socks.build_fuzzy <span class="org-comment-delimiter"># </span><span class="org-comment">=&gt; #&lt;Sock type: "fuzzy" id: nil drawer_id: 123&gt;</span>
</pre>
<p> All this thanks to the <a href="http://apidock.com/rails/ActiveRecord/NamedScope/ClassMethods/scoped"><code>#scoped</code></a> method, which is aware of the current scope. </p>
<p> Thank you to <a href="https://github.com/dkubb">Dan Kubb</a> for figuring this out for me. </p>
<p> UPDATE: Fixed <code>def build_fuzzy</code> to be <code>def self.build_fuzzy</code> in the last two examples. </p>
]]></content:encoded>
			<wfw:commentRss>http://devblog.avdi.org/2012/01/19/activerecord-default-association-extensions/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>DRYing up your validations using DB reflection</title>
		<link>http://devblog.avdi.org/2011/10/20/drying-up-your-validations-using-db-reflection/</link>
		<comments>http://devblog.avdi.org/2011/10/20/drying-up-your-validations-using-db-reflection/#comments</comments>
		<pubDate>Thu, 20 Oct 2011 13:00:00 +0000</pubDate>
		<dc:creator>Avdi Grimm</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[validations]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=1884</guid>
		<description><![CDATA[Avoiding silent truncation of your model fields requires putting length validations on them. But this can introduce duplication of knowledge. In this post I demonstrate how to pull limit information directly from the DB into your model validations. <a href="http://devblog.avdi.org/2011/10/20/drying-up-your-validations-using-db-reflection/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>Out of the box, ActiveRecord will silently truncate attribute values which exceed their column width. </p>
<pre class="src src-ruby">require <span class="org-string">'active_record'</span>

<span class="org-keyword">class</span> <span class="org-type">Greeting</span> &lt; <span class="org-type">ActiveRecord</span>::<span class="org-type">Base</span>
  establish_connection(adapter:  <span class="org-string">'mysql'</span>, 
                       database: <span class="org-string">'scratch'</span>, 
                       password: <span class="org-type">ENV</span>[<span class="org-string">'MYSQL_PASSWORD'</span>])

  connection.create_table(<span class="org-constant">:greetings</span>) <span class="org-keyword">do</span> |t|
    t.string <span class="org-constant">:text</span>, limit: 10
  <span class="org-keyword">end</span>
<span class="org-keyword">end</span>

g = <span class="org-type">Greeting</span>.create(text: <span class="org-string">"Greetings and salutations, esteemed world!"</span>)
g.reload
puts g.text <span class="org-comment-delimiter"># </span><span class="org-comment">=&gt; "Greetings "</span>
</pre>
<p> This is potentially surprising to users. To improve usability, we can set a validation: </p>
<pre class="src src-ruby">require <span class="org-string">'active_record'</span>

<span class="org-keyword">class</span> <span class="org-type">Greeting</span> &lt; <span class="org-type">ActiveRecord</span>::<span class="org-type">Base</span>
  validates <span class="org-constant">:text</span>, length: { maximum: 10 }
<span class="org-keyword">end</span>

g = <span class="org-type">Greeting</span>.create(text: <span class="org-string">"Greetings and salutations, esteemed world!"</span>)
g.valid? <span class="org-comment-delimiter"># </span><span class="org-comment">=&gt; false</span>
g.errors.full_messages <span class="org-comment-delimiter"># </span><span class="org-comment">=&gt; ["Text is too long (maximum is 10 characters)"]</span>
</pre>
<p> Now we have a new problem: duplication of the length cap. The number &#8220;10&#8243; now appears in both the database migrations, and the model validations. </p>
<p> We could extract it out into a constant, although referencing models can be problematic in migrations. But that still doesn&#8217;t account for the (many) cases where we don&#8217;t specify an explicit field limit in the migration, and instead rely on the built-in ActiveRecord defaults for field limits. </p>
<p> Here&#8217;s a solution that uses database reflection to validate a field is within its DB column size limit: </p>
<pre class="src src-ruby">validates <span class="org-constant">:text</span>,
          <span class="org-constant">:length</span> =&gt; {
              <span class="org-constant">:maximum</span> =&gt; columns_hash[<span class="org-string">'text'</span>].limit
          },
</pre>
<p> ActiveRecord provides the <code>columns_hash</code> to get at column metadata gathered from the database backend. In the code above we query it for the <code>limit</code> attribute, and use that as the max field length. By pulling the limit from the DB, we avoid duplication of knowledge. </p>
]]></content:encoded>
			<wfw:commentRss>http://devblog.avdi.org/2011/10/20/drying-up-your-validations-using-db-reflection/feed/</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
		<item>
		<title>Fowler on Rails</title>
		<link>http://devblog.avdi.org/2011/07/27/fowler-on-rails/</link>
		<comments>http://devblog.avdi.org/2011/07/27/fowler-on-rails/#comments</comments>
		<pubDate>Wed, 27 Jul 2011 18:35:17 +0000</pubDate>
		<dc:creator>Avdi Grimm</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[datamapper]]></category>
		<category><![CDATA[Martin Fowler]]></category>
		<category><![CDATA[patterns]]></category>
		<category><![CDATA[Ruby on Rails]]></category>
		<category><![CDATA[templates]]></category>
		<category><![CDATA[two step view]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=1490</guid>
		<description><![CDATA[Projects using Ruby on Rails often lack strong distinctions in two main areas: The model/record conflation: Seeing &#8220;models&#8221; as strictly DB-backed resources. The view/template conflation: failing to draw a line between view objects and HTML templates. The conflations are encouraged &#8230; <a href="http://devblog.avdi.org/2011/07/27/fowler-on-rails/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p><img class="alignright" src="http://ecx.images-amazon.com/images/I/511D6FdsbXL._SL160_.jpg" alt="" width="128" height="160" /></p>
<p>Projects using Ruby on Rails often lack strong distinctions in two main areas:</p>
<ul>
<li>The model/record conflation: Seeing &#8220;models&#8221; as strictly DB-backed resources.</li>
<li>The view/template conflation: failing to draw a line between view objects and HTML templates.</li>
</ul>
<p>The conflations are encouraged by Rails&#8217; design decisions. When choosing which enterprise design patterns to translate into code, the Rails developers chose <a href="http://martinfowler.com/eaaCatalog/activeRecord.html">Active Record</a> (a relatively thin, one-to-one take on the ORM idea), and <a href="http://martinfowler.com/eaaCatalog/templateView.html">Template View</a>.</p>
<p>I am not faulting them for this decision. These were both thoroughly pragmatic decisions which mapped well to the kind of applications that Rails was aimed at. By encoding these opinions into the framework and covering them with a sweet coating of convention-over-configuration, Rails saved thousands of projects from pattern analysis paralysis.</p>
<p>But now Rails applications are maturing, and a lot of developers are starting to realize that these patterns may not scale so well to more and more complex applications.  When figuring out how to move forward, we could do much worse than to consult the same book that laid the blueprints for Rails&#8217; architecture, <a title="Patterns of Enterprise Application Architecture (Amazon affiliate link)" href="http://www.amazon.com/Patterns-Enterprise-Application-Architecture-Martin/dp/0321127420%3FSubscriptionId%3DAKIAIRXKO4LLU2ACVMRQ%26tag%3Dthlafa-20%26linkCode%3Dxm2%26camp%3D2025%26creative%3D165953%26creativeASIN%3D0321127420">Patterns of Enterprise Application Architecture</a>.</p>
<p>Here&#8217;s Martin Fowler on <a href="http://martinfowler.com/eaaCatalog/domainModel.html">Domain Models</a>:</p>
<blockquote><p>An OO domain model will often look similar to a database model, yet it will still have a lot of differences. A <em>Domain Model</em> mingles data and process, has multivalued attributes and a complex web of associations, and uses inheritance.</p>
<p>As a result I see two styles of <em>Domain Model</em> in the field. A simple <em>Domain Model</em> looks very much like the database design with mostly one domain object for each database table. A rich <em>Domain Model</em> can look different from the database design, with inheritance, strategies, and other [Gang of Four] patterns, and complex webs of interconnected objects. A rich <em>Domain Model</em> is better for more complex logic, but is harder to map to the database. A simple <em>Domain Model</em> can use <em>Active Record</em>, whereas a rich <em>Domain Model </em>requires <em><a href="http://martinfowler.com/eaaCatalog/dataMapper.html">Data Mapper</a>.</em></p></blockquote>
<p>Note that Fowler is referring to the Active Record and Data Mapper design patterns, not to the Ruby libraries those patterns inspired. There is a correspondence, though: the <a href="http://datamapper.org/">DataMapper</a> library, like the pattern it is based on, puts a higher value on decoupling the domain model from the database schema.</p>
<p>Now on to views. Here&#8217;s Fowler talking about <em><a href="http://martinfowler.com/eaaCatalog/twoStepView.html">Two Step Views</a></em>, an alternative to the <em>Template View</em> pattern:</p>
<blockquote><p>You may&#8230; want to want to make global changes to the appearance of the site easily, but common approaches using <em>Template View</em> or <em>Transform View</em> make this difficult because presentation decisions are often duplicated across multiple pages or transform modules. A global change can force you to change several files.</p>
<p><em>Two Step View</em> deals with this problem by splitting the transformation into two stages. The first transforms the model data into a logical presentation without any special formatting; the second converts that logical presentation with the actual formatting needed.</p></blockquote>
<p>I do a lot of two-step view processing in my projects. I haven&#8217;t had a chance to take a close look at, but I think this process is also what Jeff Casimir is aiming at with <a href="https://github.com/jcasimir/draper">Draper</a>, and I support and applaud his efforts.</p>
<p>And that&#8217;s all I had to say about that&#8230; I just wanted to post those quotes in case anyone else found them noteworthy.</p>
<div class="zemanta-pixie" style="margin-top: 10px; height: 15px;"><a class="zemanta-pixie-a" title="Enhanced by Zemanta" href="http://www.zemanta.com/"><img class="zemanta-pixie-img" style="border: none; float: right;" src="http://img.zemanta.com/zemified_e.png?x-id=460ae14f-a0a9-4b56-b0c2-31f41094dfa9" alt="Enhanced by Zemanta" /></a></div>
]]></content:encoded>
			<wfw:commentRss>http://devblog.avdi.org/2011/07/27/fowler-on-rails/feed/</wfw:commentRss>
		<slash:comments>18</slash:comments>
		</item>
		<item>
		<title>ActiveRecord Golf</title>
		<link>http://devblog.avdi.org/2011/01/14/activerecord-golf/</link>
		<comments>http://devblog.avdi.org/2011/01/14/activerecord-golf/#comments</comments>
		<pubDate>Fri, 14 Jan 2011 23:49:03 +0000</pubDate>
		<dc:creator>Avdi Grimm</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[datamapper]]></category>
		<category><![CDATA[golf]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=949</guid>
		<description><![CDATA[So I was messing around with some scratchpad code today, investigating the use of with_exclusive_scope, and here&#8217;s what I had to write to come up with a minimal working ActiveRecord model: require 'rubygems' require 'active_record' ActiveRecord::Base.establish_connection( :adapter => "sqlite3", :database &#8230; <a href="http://devblog.avdi.org/2011/01/14/activerecord-golf/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>So I was messing around with some scratchpad code today, investigating the use of <a href="http://apidock.com/rails/ActiveRecord/Base/with_exclusive_scope/class">with_exclusive_scope</a>, and here&#8217;s what I had to write to come up with a minimal working ActiveRecord model:</p>
<pre name="code" class="ruby">
require 'rubygems'
require 'active_record'

ActiveRecord::Base.establish_connection(
  :adapter => "sqlite3",
  :database => ":memory:")

ActiveRecord::Base.connection.create_table(:monsters) do |t|
  t.string :name
end

class Monster < ActiveRecord::Base
end

cm = Monster.create(:name => "Cookie Monster")
</pre>
<p>For little one-off demo scripts that seems a bit excessive to me. For comparison, here&#8217;s the equivalent DataMapper:</p>
<pre name="code" class="ruby">
require 'rubygems'
require 'datamapper'

class Monster
  include DataMapper::Resource

  property :name, String, :key => true
end

DataMapper.setup(:default, 'sqlite::memory:')
DataMapper.auto_migrate!

cm = Monster.create(:name => "Cookie Monster")
</pre>
<p>Can anyone golf the ActiveRecord down any smaller?</p>
<p>EDIT: Thanks to <a href="http://about.me/jbr">Jacob Rothstein</a> for this version:</p>
<pre name="code" class="ruby">
require 'active_record'

class Monster < ActiveRecord::Base
  establish_connection :adapter  => 'sqlite3',
                       :database => ':memory:'

  connection.create_table( :monsters ) { |t| t.string :name }

  cm = create :name => 'cookie monster'
end
</pre>
]]></content:encoded>
			<wfw:commentRss>http://devblog.avdi.org/2011/01/14/activerecord-golf/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Looking for a new NullDB maintainer</title>
		<link>http://devblog.avdi.org/2010/02/16/looking-for-a-new-nulldb-maintainer/</link>
		<comments>http://devblog.avdi.org/2010/02/16/looking-for-a-new-nulldb-maintainer/#comments</comments>
		<pubDate>Tue, 16 Feb 2010 14:44:04 +0000</pubDate>
		<dc:creator>Avdi Grimm</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[datamapper]]></category>
		<category><![CDATA[floss]]></category>
		<category><![CDATA[nulldb]]></category>
		<category><![CDATA[oss]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=473</guid>
		<description><![CDATA[I love Open Source. NullDB, a weekend hack that I barely touched after its first version, continues to attract periodic forks and patches. For a long time I&#8217;ve been meaning to sit down and roll in all the contributions that &#8230; <a href="http://devblog.avdi.org/2010/02/16/looking-for-a-new-nulldb-maintainer/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<div id="attachment_474" class="wp-caption aligncenter" style="width: 350px"><a href="http://github.com/avdi/nulldb"><img src="http://virtuouscode.com/wp-content/uploads/2010/02/nulldb-tree.png" alt="NullDB network on Github" title="nulldb-tree" width="342" height="219" class="size-full wp-image-474" /></a><p class="wp-caption-text">NullDB network on Github</p></div>
<p>I love Open Source. <a href="http://nulldb.rubyforge.org/">NullDB</a>, a weekend hack that I barely touched after its first version, continues to attract periodic forks and patches. For a long time I&#8217;ve been meaning to sit down and roll in all the contributions that people have made over the last couple of years.</p>
<p>But I realized something yesterday. I haven&#8217;t used ActiveRecord for anything serious for around a year. And I can&#8217;t imagine choosing to use ActiveRecord for any projects in the future, because I literally can&#8217;t think of a single scenario in which AR is a better choice than <a href="http://datamapper.org">DataMapper</a>. (Just as an example of DataMapper&#8217;s awesomeness: it turns out NullDB isn&#8217;t even needed for DataMapper, because <a href="http://avdi.org/devblog/2009/10/27/nulldb-for-datamapper/">you get it for free</a>).</p>
<p>There isn&#8217;t a foreseeable future in which I&#8217;ll be using NullDB regularly, and if I&#8217;m not using it it&#8217;s never going to be a priority for me. Which, realistically, means it&#8217;s never going to have my attention.</p>
<p>I think the time has come to turn NullDB over to a new maintainer, someone who has a more active interest in testing ActiveRecord-based codebases. The ideal candidate would:</p>
<ol>
<li>Be using NullDB on a daily basis.</li>
<li>Have submitted at least one <strong>tested</strong> NullDB patch.</li>
<li>Be committed to the NullDB philosophy of preferring public APIs to fragile monkeypatching.</li>
</ol>
<p>If you think this describes you and you are interested in becoming the NullDB maintainer, please get in touch.</p>
]]></content:encoded>
			<wfw:commentRss>http://devblog.avdi.org/2010/02/16/looking-for-a-new-nulldb-maintainer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using AlterEgo with ActiveRecord</title>
		<link>http://devblog.avdi.org/2008/12/09/using-alterego-with-activerecord/</link>
		<comments>http://devblog.avdi.org/2008/12/09/using-alterego-with-activerecord/#comments</comments>
		<pubDate>Tue, 09 Dec 2008 18:30:42 +0000</pubDate>
		<dc:creator>Avdi Grimm</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[alter-ego]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/2008/12/09/using-alterego-with-activerecord/</guid>
		<description><![CDATA[François Beausoleil has a nice post up demonstrating &#8220;how to use AlterEgo with ActiveRecord&#8221;:http://blog.teksol.info/2008/12/09/how-to-use-alterego-with-activerecord.html. If you&#8217;re interested in introducing state-specific behaviors to your ActiveRecord objects, check it out!]]></description>
				<content:encoded><![CDATA[<p>François Beausoleil has a nice post up demonstrating &#8220;how to use AlterEgo with ActiveRecord&#8221;:http://blog.teksol.info/2008/12/09/how-to-use-alterego-with-activerecord.html.  If you&#8217;re interested in introducing state-specific behaviors to your ActiveRecord objects, check it out!</p>
]]></content:encoded>
			<wfw:commentRss>http://devblog.avdi.org/2008/12/09/using-alterego-with-activerecord/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Announcing NullDB 0.0.1</title>
		<link>http://devblog.avdi.org/2008/02/17/announcing-nulldb-001/</link>
		<comments>http://devblog.avdi.org/2008/02/17/announcing-nulldb-001/#comments</comments>
		<pubDate>Mon, 18 Feb 2008 06:20:06 +0000</pubDate>
		<dc:creator>Avdi Grimm</dc:creator>
				<category><![CDATA[Uncategorized]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[plugins]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[testing]]></category>

		<guid isPermaLink="false">http://avdi.org/devblog/?p=16</guid>
		<description><![CDATA[I spent the afternoon coding an alternative to the ARBS and UnitRecord database-elimination plugins.  Definitely scratching a personal itch, as I had a project where I wanted to use one of the above-mentioned libraries but i just couldn&#8217;t seem to &#8230; <a href="http://devblog.avdi.org/2008/02/17/announcing-nulldb-001/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
				<content:encoded><![CDATA[<p>I spent the afternoon coding an alternative to the ARBS and UnitRecord database-elimination plugins.  Definitely scratching a personal itch, as I had a project where I wanted to use one of the above-mentioned libraries but i just couldn&#8217;t seem to get them to work.  I&#8217;m releasing it in hopes others will find it useful too.</p>
<p>Here&#8217;s the text of the README:</p>
<h2>What</h2>
<p>NullDB is a Rails database connection adapter that interprets common database operations as no-ops. It is the Null Object pattern as applied to database adapters.</p>
<h2>How</h2>
<p>Once installed, NullDB can be used much like any other <a href="http://avdi.org/projects/nulldb/classes/ActiveRecord.html">ActiveRecord</a> database adapter:</p>
<pre>  ActiveRecord::Base.establish_connection :adapter =&gt; nulldb</pre>
<p>NullDB needs to know where you keep your schema file in order to reflect table metadata. By default it looks in RAILS_ROOT/db/schema.rb. You can override that by setting the <tt>schema</tt> option:</p>
<pre>  ActiveRecord::Base.establish_connection :adapter =&gt; nulldb,

                                          :schema  =&gt; foo/myschema.rb</pre>
<p>There is a helper method included for configuring RSpec sessions to use NullDB. Just put the following in your spec/spec_helper.rb:</p>
<pre>  Spec::Runner.configure do |config|

    ::NullDB.insinuate_into_spec(config)

  end</pre>
<p>You can also experiment with putting NullDB in your database.yml:</p>
<pre>  unit_test:

    adapter: nulldb</pre>
<p>However, due to the way Rails hard-codes specific database adapters into its standard Rake tasks, you may find that this generates unexpected and difficult-to-debug behavior. Workarounds for this are under development.</p>
<h2>Why</h2>
<p>NullDB is intended to assist in writing fast database-independant unit tests for <a href="http://avdi.org/projects/nulldb/classes/ActiveRecord.html">ActiveRecord</a> classes. For why you would want to test your models without the database, see: <a href="http://www.dcmanges.com/blog/rails-unit-record-test-without-the-database">www.dcmanges.com/blog/rails-unit-record-test-without-the-database</a>.</p>
<p>NullDB was inspired by the <a href="http://arbs.rubyforge.org/">ARBS</a> and <a href="http://unit-test-ar.rubyforge.org/">UnitRecord</a> libraries. It differs from them in a couple of ways:</p>
<ol>
<li>It works. At the time of writing both ARBS and UnitRecord were not working for me out of the box with Rails 2.0.</li>
<li>It avoids monkey-patching as much as possible. Rather than re-wiring the secret inner workings of <a href="http://avdi.org/projects/nulldb/classes/ActiveRecord.html">ActiveRecord</a> (and thus being tightly coupled to those inner workings), NullDB implements the same [semi-]well-documented public interface that the other standard database adapters, like MySQL and SQLServer, implement.</li>
<li>UnitRecord takes the approach of eliminating database interaction in tests by turning almost every database interaction into an exception. NullDB recognizes that <a href="http://avdi.org/projects/nulldb/classes/ActiveRecord.html">ActiveRecord</a> objects typically can‘t take two steps without consulting the database, so instead it turns database interactions into no-ops.</li>
</ol>
<p>One concrete advantage of this null-object pattern design is that it is possible with NullDB to test <tt>after_save</tt> hooks. With NullDB, you can call +save+ and all of the usual callbacks will be called &#8211; but nothing will be saved.</p>
<h2>Limitations</h2>
<ul>
<li>It is <strong>not</strong> an in-memory database. Finds will not work. Neither will reload, currently.</li>
<li>It has only the most rudimentery schema/migration support. Complex migrations will probably break it.</li>
<li>Lots of other things probably don‘t work. Patches welcome!</li>
</ul>
<h2>Who</h2>
<p>NullDB was written by Avdi Grimm &lt;<a href="https://mail.google.com/mail?view=cm&amp;tf=0&amp;ui=1&amp;to=avdi@avdi.org" target="_blank">avdi@avdi.org</a>&gt;</p>
<h2>Where</h2>
<ul>
<li>Homepage: <a href="http://avdi.org/projects/nulldb">avdi.org/projects/nulldb</a>/</li>
<li>Public SVN: <a href="http://svn.avdi.org/nulldb">svn.avdi.org/nulldb</a>/</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://devblog.avdi.org/2008/02/17/announcing-nulldb-001/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
