<?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>Talk Like A Duck: Tag migrations</title>
    <link>http://talklikeaduck.denhaven2.com/articles/tag/migrations</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>In Ruby, it's not the dog, it's the tricks!</description>
    <item>
      <title>Rails 2.1RC1 and the Enhanced Migrations Plugin</title>
      <description>At work, we use the Revolution on Rails &lt;a href="http://revolutiononrails.blogspot.com/2007/02/plugin-release-enhanced-rails.html"&gt;enhanced_migrations plugin&lt;/a&gt;.
&lt;p&gt;Yesterday I started the work of moving the app to Rails 2.1RC1.&lt;/p&gt;
&lt;p&gt;With version 2.1, Rails is moving to timestamp based migration names, instead of the traditional sequence numbering.  This effectively does the same thing as the enhanced_migrations plugin, but the implementation is slightly different, more on this in a bit.&lt;/p&gt;
&lt;p&gt;After installing or &lt;a href="http://railscasts.com/episodes/105"&gt;&lt;strong&gt;git&lt;/strong&gt;ting&lt;/a&gt; Rails 2.1 into my vendor/rails directory, I ran the rake task to run all of our tests and specs.&lt;/p&gt;
&lt;p&gt;Early on this task does a rake db:migrate, which attempted to run &lt;span class="caps"&gt;ALL&lt;/span&gt; of our migrations since Rails 2.1 looks in a different place to determine if a migration has been already run.&lt;/p&gt;
&lt;h2&gt;Implementation Differences&lt;/h2&gt;
&lt;p&gt;Until now Rails has tracked migrations using a single row, single column table in each database called schema_version. This table holds the number of the latest migration which has been run.&lt;/p&gt;
&lt;p&gt;The enhanced_migrations plugin uses a w table, named migrations_info, with one row for each migration which has been applied to the database.  The key used for this table is the migration number which the migration generator sets to Time.now.to_i. The only column besides the id is created_at. So the enhanced_migration plugin captures the time at which the migration was run against the database, which is different than the time it was generated.&lt;/p&gt;
&lt;p&gt;Rails 2.1 uses a table called schema_migrations, which also has a row per applied migration, but this table has a string key whose value is the migration number, in Rails 2.1, the migration number is also a utc timestamp but is a string in the the form &amp;#8220;yyyymmddhhmmss&amp;#8221;&lt;/p&gt;
&lt;p&gt;Blake Watters and I noticed that the timestamp forms can&amp;#8217;t overlap since enhanced migrations uses a 10-digit timestamp and Rails 2.1 uses a 14-digit one.  So we wrote a new migration 1_convert_migration_schema_to_rails21.rb&lt;/p&gt;
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;ConvertMigrationSchemaToRails21&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ActiveRecord&lt;/span&gt;&lt;span class="punct"&gt;::&lt;/span&gt;&lt;span class="constant"&gt;Migration&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.up&lt;/span&gt;
    &lt;span class="ident"&gt;values&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;select_values&lt;/span&gt;&lt;span class="punct"&gt;('&lt;/span&gt;&lt;span class="string"&gt;select id from migrations_info&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt;
    &lt;span class="ident"&gt;values&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="punct"&gt;{|&lt;/span&gt;&lt;span class="ident"&gt;value&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;execute&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;replace into schema_migrations VALUES('&lt;span class="expr"&gt;#{id}&lt;/span&gt;')&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)}&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.down&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;We then ran rake db:migrate:up &lt;span class="caps"&gt;VERSION&lt;/span&gt;=1&lt;/p&gt;
&lt;p&gt;This populated schema_migrations so that it now &amp;#8220;knew&amp;#8221; that all of our current migrations had already been run.&lt;/p&gt;
&lt;h2&gt;Not quite there&lt;/h2&gt;
&lt;p&gt;For many current users of enhanced_migrations, this might be enough. In our case it wasn&amp;#8217;t.  When I tried to run rake test again, it blew up in the prerequisite task db:test:clone_structure, complaining about bad sql syntax on an insert statement.  The insert statement which was logged looked perfectly fine. It was the second of a series of statements inserting rows into our new friend, the schema_migrations table.
The &lt;span class="caps"&gt;SQL&lt;/span&gt; in question looked like this:&lt;/p&gt; 
&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;INSERT INTO schema_migrations (version) VALUES ('0');
INSERT INTO schema_migrations (version) VALUES ('1');&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Followed by a similar line for each of our 500 or so migrations.&lt;/p&gt;
&lt;p&gt;The rake task for db:test:clone structure, basically breaks the file db/development_structure.sql into chunks delimited by empty lines, and &amp;#8216;plays&amp;#8217; them against the test database using ActiveRecord::Base.connection.execute.  After some head scratching over why this seemingly legal &lt;span class="caps"&gt;SQL&lt;/span&gt; was being rejected, it occurred to us that it was trying to execute all of these lines as one sql statement.&lt;/p&gt;
&lt;p&gt;So the next step was to figure out how to get db/development_structure.sql into a form which would cause the task to execute each sql statement individually.  This was a simple patch to rails, which once made, allowed rake db:test:prepare to run successfully, which in turn allowed me to actually move on to running the test suite and working out the problems caused by the changes to rails.&lt;/p&gt;
&lt;p&gt;I opened up &lt;a href="http://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/201-process-schema_migrations-inserts-individually-during-rake-db-test-clone_structure#ticket-201-2"&gt;ticket #201 on the Rails lighthouse&lt;/a&gt; which contains the Rails patch.&lt;/p&gt;</description>
      <pubDate>Thu, 15 May 2008 15:24:00 -0400</pubDate>
      <guid isPermaLink="false">urn:uuid:1c1affbf-7dca-4705-9248-099bdee52f3e</guid>
      <author>Rick DeNatale</author>
      <link>http://talklikeaduck.denhaven2.com/articles/2008/05/15/rails-2-1rc1-and-the-enhanced-migrations-plugin</link>
      <category>rails</category>
      <category>migrations</category>
      <category>rails2.1</category>
      <trackback:ping>http://talklikeaduck.denhaven2.com/articles/trackback/498</trackback:ping>
    </item>
  </channel>
</rss>
