<?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>Crazy Or Genius?: Writing Database Code In Rails: Migrations and Neutrility</title>
    <link>http://www.crazyorgenius.com/articles/2005/11/23/writing-database-code-in-rails-migrations-and-neutrility</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>When You Are Right 90% Of The Time, Why Quible Over The Remaining 3%?</description>
    <item>
      <title>Writing Database Code In Rails: Migrations and Neutrility</title>
      <description>&lt;p&gt;As I &lt;a href="http://torch.cs.dal.ca/~ssmith/?p=40"&gt;recently said&lt;/a&gt;, I switched TigerEvents over from using a MySQL input file to migrations. There were many decisions behind this choice.&lt;/p&gt;


	&lt;ul&gt;
	&lt;li&gt;I wanted the code to be database neutral. Using migrations would allow me to automatically support MySQL, PostgreSQL, and SQLite by making changes to one file instead of 3.&lt;/li&gt;
		&lt;li&gt;I know that the database for TigerEvents is going to change at some point in the near future. Rather than write multiple upgrade scripts manually, I could just use the built in migration functions to do it better.&lt;/li&gt;
		&lt;li&gt;If for some reason I make a mistake and problems occur on the production site, it is easier to roll back to a previous version using migrations than dump the database, roll back the code, reload the database, etc. (Note, we still make sure to back up the database, cause not doing that is just tempting fate)&lt;/li&gt;
		&lt;li&gt;Migrations will, in theory, make development easier. Someone made a change to the schema? Just run &lt;em&gt;&lt;strong&gt;rake migrate&lt;/strong&gt;&lt;/em&gt;, and your database is automatically updated. I think this is easier than reinitializing a database and then loading it with data repeatedly (though the second part of this can be handled with Fixtures).&lt;/li&gt;
	&lt;/ul&gt;&lt;p&gt;While an &lt;a href="http://glu.ttono.us/articles/2005/10/27/the-joy-of-migrations"&gt;awesome introduction&lt;/a&gt; to getting started with Migrations has already been written, I feel that the &amp;#8216;database neutral&amp;#8217; stuff is missing. Using my own experience, several items must be taken into account, mostly due to MySQL usage and certain programming that were being used.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Already Existant Database&lt;/strong&gt;&lt;/p&gt;


	&lt;p&gt;So we already had a database. A somewhat large database with a number of tables. I didn&amp;#8217;t want to spend a lot of time manually creating the migration code from scratch. Was there a quicker way? You betcha. There was a rake task called db_schema_dump which will dump all the table data from your database to a file called schema.rb. So, once we do that, all we have to do is copy this information to the self.up section of a migration and we are done, right? Unfortunatly, it is &lt;strong&gt;&lt;span class="caps"&gt;NOT&lt;/span&gt;&lt;/strong&gt; that easy. The problem is (in my case) that MySQL data types do not necessarily behave the same. Mostly, this deals with constraints, but also has to do with the boolean data type itself.&lt;/p&gt;


	&lt;p&gt;&lt;strong&gt;Constraints&lt;/strong&gt;&lt;/p&gt;


In MySQL, you can do int(8). In rails, this would be translated into something like &lt;code&gt;:integer, :limit =&amp;gt; 8&lt;/code&gt;. However, PostgreSQL only has smallint, integer, and bigint, not constraint values. Therefore, the previous rails code returns an error, as PostgreSQL chokes on the &lt;span class="caps"&gt;SQL&lt;/span&gt; command that rails sends it. Therefore, while it is true that you don&amp;#8217;t need to know specific &lt;span class="caps"&gt;SQL&lt;/span&gt; syntax, you DO need to know what kind of data you can feed various databases. For TigerEvents, I just generalized items and made the following changes:
&lt;code&gt;:integer, :limit =&amp;gt; 8&lt;/code&gt; became &lt;code&gt;:integer&lt;/code&gt;
&lt;code&gt;:integer, :limit =&amp;gt; 1&lt;/code&gt; which translated to tinyint(1) in MySQL became &lt;code&gt;:boolean&lt;/code&gt;
&lt;code&gt;:timestamp&lt;/code&gt; became &lt;code&gt;:datetime&lt;/code&gt; (which gave me extra functionality). Now, I by no means know if these are the optimal solutions, but they did work.

	&lt;p&gt;&lt;strong&gt;Boolean Data&lt;/strong&gt;&lt;/p&gt;


We have a few boolean flags in our database. However, MySQL does not have a boolean data type. Instead, tinyint(1) is generally used. Well, generally that is ok, as ActiveRecord will automatically use tinyint(1) when connecting to MySQL and boolean when connecting to PostgreSQL and SQLite. However, since we started out with MySQL, there were numerous statements such as 
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;@newgroups = Group.find(:all, :conditions =&amp;gt; [&amp;quot;approved = 0&amp;quot;])&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
where 0 is supposed to indicate false. However, since this does not translate to false with PostgreSQL and SQLite, we have a problem. Solution: use placeholders. You are acually allowed to do this:
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;@newgroups = Group.find(:all, :conditions =&amp;gt; [&amp;quot;approved = ?&amp;quot;, false])&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
ActiveRecord takes the value and automatically translates the value into the proper data type, depending on the database type.

	&lt;p&gt;So once again, while you don&amp;#8217;t need to know specific &lt;span class="caps"&gt;SQL&lt;/span&gt; query usage, it is important to keep data types general, and passed values abstracted if you want to create database code which is database neutral (at least for MySQL, PostgreSQL, and SQLite).&lt;/p&gt;</description>
      <pubDate>Wed, 23 Nov 2005 18:12:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:f22c340f171ad04deddfaaba1bccc54c</guid>
      <author>Sean</author>
      <link>http://www.crazyorgenius.com/articles/2005/11/23/writing-database-code-in-rails-migrations-and-neutrility</link>
      <category>Programming</category>
      <category>ruby</category>
      <category>rails</category>
      <category>migrations</category>
      <trackback:ping>http://www.crazyorgenius.com/articles/trackback/41</trackback:ping>
    </item>
    <item>
      <title>"Writing Database Code In Rails: Migrations and Neutrility" by http://aaalex.myopenid.com</title>
      <description>Hi!&lt;br /&gt;
... concerning your LARGEBLOB problems.. just use:&lt;br /&gt;&lt;br /&gt;
&lt;p&gt;&lt;b&gt;t.column :data, :binary, :limit =&amp;gt; 10.megabyte&lt;/b&gt;&lt;/p&gt;
in your migration to define bigger BLOBs
&lt;br /&gt;&lt;br /&gt;-aaalex</description>
      <pubDate>Thu, 05 Oct 2006 22:22:54 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:5378c1ed-fad7-41be-a2e1-507549b84083</guid>
      <link>http://www.crazyorgenius.com/articles/2005/11/23/writing-database-code-in-rails-migrations-and-neutrility#comment-202</link>
    </item>
    <item>
      <title>"Writing Database Code In Rails: Migrations and Neutrility" by Hector G. Parra &amp;raquo; Blog Archive &amp;raquo; Migrations</title>
      <description>&lt;p&gt;[...] &lt;a href="http://torch.cs.dal.ca/"&gt;http://torch.cs.dal.ca/&lt;/a&gt;~ssmith/?p=41 [...]&lt;/p&gt;</description>
      <pubDate>Tue, 16 May 2006 19:36:09 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:</guid>
      <link>http://www.crazyorgenius.com/articles/2005/11/23/writing-database-code-in-rails-migrations-and-neutrility#comment-125</link>
    </item>
    <item>
      <title>"Writing Database Code In Rails: Migrations and Neutrility" by Pops</title>
      <description>&lt;p&gt;Nice for the schema. But how to migrate the data from one db to another as well? Say from MySQL to Sqlite?&lt;/p&gt;</description>
      <pubDate>Tue, 11 Apr 2006 15:13:23 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:</guid>
      <link>http://www.crazyorgenius.com/articles/2005/11/23/writing-database-code-in-rails-migrations-and-neutrility#comment-124</link>
    </item>
    <item>
      <title>"Writing Database Code In Rails: Migrations and Neutrility" by Sean</title>
      <description>&lt;p&gt;Eden: I am fairly certain this requires a certain level of familiarity with the database you are using, though a single page which has these items, and ties them in with what is possible for migrations would be nice.&lt;/p&gt;</description>
      <pubDate>Sun, 09 Apr 2006 00:38:13 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:</guid>
      <link>http://www.crazyorgenius.com/articles/2005/11/23/writing-database-code-in-rails-migrations-and-neutrility#comment-123</link>
    </item>
    <item>
      <title>"Writing Database Code In Rails: Migrations and Neutrility" by Eden</title>
      <description>&lt;p&gt;&amp;#8220;However, PostgreSQL only has smallint, integer, and bigint, not constraint values.&amp;#8221;&lt;/p&gt;


	&lt;p&gt;Thanks.  I have been banging my head for a couple of hours trying to figure out why&lt;/p&gt;


	&lt;p&gt;table.column :myint, :integer, :limit =&amp;gt; 10&lt;/p&gt;


	&lt;p&gt;wasn&amp;#8217;t working with Postgresql.  I wonder if these limitations are all documented somewhere or if you just have to figure it out from the DB you are working with.&lt;/p&gt;</description>
      <pubDate>Wed, 05 Apr 2006 14:53:40 +0200</pubDate>
      <guid isPermaLink="false">urn:uuid:</guid>
      <link>http://www.crazyorgenius.com/articles/2005/11/23/writing-database-code-in-rails-migrations-and-neutrility#comment-122</link>
    </item>
    <item>
      <title>"Writing Database Code In Rails: Migrations and Neutrility" by Sean</title>
      <description>&lt;p&gt;heavysixer, like ENUMS, I haven&amp;#8217;t used blob data either. &lt;a href="http://wiki.rubyonrails.com/rails/pages/HowtoStoreFilesInTheDatabase"&gt;http://wiki.rubyonrails.com/rails/pages/HowtoStoreFilesInTheDatabase&lt;/a&gt; indicates they can be used, but isn&amp;#8217;t very verbose. The apidocs seem to indicate that it is binary data (&lt;a href="http://api.rubyonrails.com/classes/ActiveRecord/ConnectionAdapters/MysqlAdapter.html"&gt;http://api.rubyonrails.com/classes/ActiveRecord/ConnectionAdapters/MysqlAdapter.html&lt;/a&gt;) under native_database_types(), but I am not sure if you can use limit. My best guess would be to use :limit =&amp;gt; 4294967300. This is based off reading the MySQL docs on storage size, where longblob storage is L+4 where L&lt;/p&gt;</description>
      <pubDate>Tue, 10 Jan 2006 00:16:16 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:</guid>
      <link>http://www.crazyorgenius.com/articles/2005/11/23/writing-database-code-in-rails-migrations-and-neutrility#comment-121</link>
    </item>
    <item>
      <title>"Writing Database Code In Rails: Migrations and Neutrility" by Sean</title>
      <description>&lt;p&gt;Gary, I unfortunatly haven&amp;#8217;t tried using ENUM datatypes yet. Of course, in the near future, I am most likely going to require them. Ah&amp;#8230;..... refactoring. The following page &lt;a href="http://wiki.rubyonrails.com/rails/pages/HowtoUseSetAndEnumColumns"&gt;http://wiki.rubyonrails.com/rails/pages/HowtoUseSetAndEnumColumns&lt;/a&gt; says that ENUM is not supported, but gives some workarounds (I haven&amp;#8217;t tried them).&lt;/p&gt;</description>
      <pubDate>Tue, 10 Jan 2006 00:13:20 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:</guid>
      <link>http://www.crazyorgenius.com/articles/2005/11/23/writing-database-code-in-rails-migrations-and-neutrility#comment-120</link>
    </item>
    <item>
      <title>"Writing Database Code In Rails: Migrations and Neutrility" by heavysixer</title>
      <description>&lt;p&gt;I am having a similar problem with blob data abstraction. I want to store large-ish files in my database and migration converts it to plain ol &amp;#8220;blob&amp;#8221; which chokes on my files. MySQL is expecting LONGBLOB but I am not sure how/if I can you your limit example to accomplish the same thing.&lt;/p&gt;


	&lt;p&gt;Thanks!&lt;/p&gt;</description>
      <pubDate>Sun, 08 Jan 2006 03:45:41 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:</guid>
      <link>http://www.crazyorgenius.com/articles/2005/11/23/writing-database-code-in-rails-migrations-and-neutrility#comment-119</link>
    </item>
    <item>
      <title>"Writing Database Code In Rails: Migrations and Neutrility" by Gary</title>
      <description>&lt;p&gt;Hey, have you noticed whether the active migration supports ENUM datatypes, or what I should use instead of enums?  I like using enums for status flags.  But when I try to db_schema_dump by table with enums in it, it chokes.&lt;/p&gt;</description>
      <pubDate>Sun, 01 Jan 2006 00:47:09 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:</guid>
      <link>http://www.crazyorgenius.com/articles/2005/11/23/writing-database-code-in-rails-migrations-and-neutrility#comment-118</link>
    </item>
    <item>
      <title>"Writing Database Code In Rails: Migrations and Neutrility" by Jon</title>
      <description>&lt;p&gt;Honey, you&amp;#8217;re every geek&amp;#8217;s dream. And Anne, it&amp;#8217;s cool that you support him.&lt;/p&gt;


	&lt;p&gt;=P&lt;/p&gt;</description>
      <pubDate>Thu, 24 Nov 2005 02:07:00 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:</guid>
      <link>http://www.crazyorgenius.com/articles/2005/11/23/writing-database-code-in-rails-migrations-and-neutrility#comment-117</link>
    </item>
    <item>
      <title>"Writing Database Code In Rails: Migrations and Neutrility" by AnnieB</title>
      <description>&lt;p&gt;I don&amp;#8217;t understand it, but fuck if that isn&amp;#8217;t sexy as hell.&lt;/p&gt;</description>
      <pubDate>Wed, 23 Nov 2005 23:26:42 +0100</pubDate>
      <guid isPermaLink="false">urn:uuid:</guid>
      <link>http://www.crazyorgenius.com/articles/2005/11/23/writing-database-code-in-rails-migrations-and-neutrility#comment-116</link>
    </item>
  </channel>
</rss>
