Robby on Rails: Rails Migrations and PostgreSQL Constraintsthoughts.sort_by{|t| t[:topic]}.collect tag:www.robbyonrails.com,2005:TypoTypo2006-09-05T22:12:44-04:00Robby Russellurn:uuid:f125682d520f030e69dadb4be8913ebe2005-11-11T10:42:00-05:002006-09-05T22:12:44-04:00Rails Migrations and PostgreSQL Constraints<p>A question was posed on the Rails mailing list concerning how one would go about adding CONSTRAINTs to the database tables with <a href="http://api.rubyonrails.org/classes/ActiveRecord/Migration.html">ActiveRecord::Migration</a>.</p>
<p>One argument was raised stating that it is easier to handle these in plain <span class="caps">SQL</span> schema files. I disagree. :-)</p>
<h3>Migrations to the Rescue</h3>
<p>Databases evolve and I have recently found the Migration structure to be perfect for handling iterations and schema changes. Using the <a href="http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/DatabaseStatements.html#M000529">#execute</a> method has helped move more of my code into the Ruby/Rails framework… and that just makes things easier to manage in the long-run. This is the approach that we are using at <a href="http://www.planetargon.com/development.html"><span class="caps">PLANET ARGON</span></a> with some of our current client projects.</p>
<div class="typocode"><pre><code class="typocode_ruby "><span class="comment"># db/migrate/6_add_foreign_key.rb</span>
<span class="keyword">class </span><span class="class">AddForeignKey</span> <span class="punct"><</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Migration</span>
<span class="keyword">def </span><span class="method">self.up</span>
<span class="ident">execute</span> <span class="punct">"</span><span class="string">ALTER TABLE bees ADD CONSTRAINT beehive_id_fkey FOREIGN KEY
(beehive_id) REFERENCES beehives (id);</span><span class="punct">"</span>
<span class="keyword">end</span>
<span class="keyword">def </span><span class="method">self.down</span>
<span class="ident">execute</span> <span class="punct">"</span><span class="string">ALTER TABLE bees DROP CONSTRAINT beehive_id_fkey;</span><span class="punct">"</span>
<span class="keyword">end</span>
<span class="keyword">end</span></code></pre></div>
<p>This gives us an easy way to use the standard, <a href="http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#M000507">#create_table</a> syntax for building our tables with Ruby… and then we can slap these constraints on later.</p>
<p>This would add the constraints…</p>
<code>
<pre>
rake migrate VERSION=6
</pre>
</code>
...run tests…
<code>
<pre>
rake
</pre>
</code>
...roll back…
<code>
<pre>
rake migrate VERSION=5
</pre>
</code>
<p>I have found that this approach is really useful with testing in Rails. When I think that I have everything working great (without <span class="caps">CONSTRAINTS</span> in PostgreSQL), I run another migration to add a bunch of foreign key and data constraints to the tables and… run my tests again.</p>
<h3>Let’s give Active Record a Hug</h3>
<p>This has helped me <a href="http://www.robbyonrails.com/articles/2005/09/27/the-bitter-sweet-taste-of-agnostic-database-schemas">gain some trust</a> in Active Record while still giving me that comforting feeling that <a href="http://www.postgresql.org">PostgreSQL</a> is acting as the <em>body guard for my data</em>.</p>
<p>Even if you don’t end up using Migrations to handle these types of database schema changes, I would highly suggest that you model your implementation after this. I’ve worked with many database schemas and this just makes it easy to add your new change and run one command to commit it to the database.</p>
<p>...and now I go play with beehives…</p><p>A question was posed on the Rails mailing list concerning how one would go about adding CONSTRAINTs to the database tables with <a href="http://api.rubyonrails.org/classes/ActiveRecord/Migration.html">ActiveRecord::Migration</a>.</p>
<p>One argument was raised stating that it is easier to handle these in plain <span class="caps">SQL</span> schema files. I disagree. :-)</p>
<h3>Migrations to the Rescue</h3>
<p>Databases evolve and I have recently found the Migration structure to be perfect for handling iterations and schema changes. Using the <a href="http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/DatabaseStatements.html#M000529">#execute</a> method has helped move more of my code into the Ruby/Rails framework… and that just makes things easier to manage in the long-run. This is the approach that we are using at <a href="http://www.planetargon.com/development.html"><span class="caps">PLANET ARGON</span></a> with some of our current client projects.</p>
<div class="typocode"><pre><code class="typocode_ruby "><span class="comment"># db/migrate/6_add_foreign_key.rb</span>
<span class="keyword">class </span><span class="class">AddForeignKey</span> <span class="punct"><</span> <span class="constant">ActiveRecord</span><span class="punct">::</span><span class="constant">Migration</span>
<span class="keyword">def </span><span class="method">self.up</span>
<span class="ident">execute</span> <span class="punct">"</span><span class="string">ALTER TABLE bees ADD CONSTRAINT beehive_id_fkey FOREIGN KEY
(beehive_id) REFERENCES beehives (id);</span><span class="punct">"</span>
<span class="keyword">end</span>
<span class="keyword">def </span><span class="method">self.down</span>
<span class="ident">execute</span> <span class="punct">"</span><span class="string">ALTER TABLE bees DROP CONSTRAINT beehive_id_fkey;</span><span class="punct">"</span>
<span class="keyword">end</span>
<span class="keyword">end</span></code></pre></div>
<p>This gives us an easy way to use the standard, <a href="http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/SchemaStatements.html#M000507">#create_table</a> syntax for building our tables with Ruby… and then we can slap these constraints on later.</p>
<p>This would add the constraints…</p>
<code>
<pre>
rake migrate VERSION=6
</pre>
</code>
...run tests…
<code>
<pre>
rake
</pre>
</code>
...roll back…
<code>
<pre>
rake migrate VERSION=5
</pre>
</code>
<p>I have found that this approach is really useful with testing in Rails. When I think that I have everything working great (without <span class="caps">CONSTRAINTS</span> in PostgreSQL), I run another migration to add a bunch of foreign key and data constraints to the tables and… run my tests again.</p>
<h3>Let’s give Active Record a Hug</h3>
<p>This has helped me <a href="http://www.robbyonrails.com/articles/2005/09/27/the-bitter-sweet-taste-of-agnostic-database-schemas">gain some trust</a> in Active Record while still giving me that comforting feeling that <a href="http://www.postgresql.org">PostgreSQL</a> is acting as the <em>body guard for my data</em>.</p>
<p>Even if you don’t end up using Migrations to handle these types of database schema changes, I would highly suggest that you model your implementation after this. I’ve worked with many database schemas and this just makes it easy to add your new change and run one command to commit it to the database.</p>
<p>...and now I go play with beehives…</p>