<?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>H3RALD: Simply On Rails - Part 4: Quick and Easy Default Data Migrations</title>
    <link>http://www.h3rald.com/blog/simply-on-rails-4-default-data-migrations</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Fabio Cevasco's Writings</description>
    <item>
      <title>Simply On Rails - Part 4: Quick and Easy Default Data Migrations</title>
      <description>&lt;p&gt;In the &lt;a href="http://www.h3rald.com/blog/simply-on-rails-3-shared-controller"&gt;last post&lt;/a&gt; of this series I tried to find a &lt;acronym title="Don&amp;#8217;t Repeat Yourself"&gt;DRY&lt;/acronym&gt; solution to deal with tables storing &amp;#8220;ancillary&amp;#8221; data, i.e. names of user roles, predefined categories, page state names and other similar things.
I personally chose to put this kind of data to make my application more dynamic, although I could have decided to use ENUMs or simply ordinary varchar fields&amp;#8212;that would have been easier, but less flexible. For now, I&amp;#8217;m sticking with my original choice.&lt;/p&gt;


	&lt;p&gt;The data in these tables is kind of a prerequisite for the application to run: I must be able to have a status to assign to a user when creating it, and the same applies to roles. Sure, I could spend 20 minutes populating these tables manually, but it would be nice if there was a less tedious way, wouldn&amp;#8217;t it?&lt;/p&gt;


	&lt;p&gt;There is indeed. The inspiration came from a technique described in the book (which I highly recommend) &lt;em&gt;Agile Web Development With Rails&lt;/em&gt;, in which the author outlines how it would be possible to use Rails&amp;#8217; fixtures and migrations to load data in the database automatically from &lt;span class="caps"&gt;YAML&lt;/span&gt; files. 
All you have to do is create a migration to load the specified &lt;span class="caps"&gt;YAML&lt;/span&gt; files and you&amp;#8217;re all set.&lt;/p&gt;


	&lt;p&gt;I wanted to take a little step further, allowing the migration to load data from &lt;em&gt;all &lt;span class="caps"&gt;YAML&lt;/span&gt; files in a specific directory&lt;/em&gt;, automatically.&lt;/p&gt;


	&lt;p&gt;Let&amp;#8217;s start creating the &lt;span class="caps"&gt;YAML&lt;/span&gt; files then and place them all in one directory of the application like &lt;code&gt;/db/migrate/defaults&lt;/code&gt;. Here&amp;#8217;s the one I used for user roles, for example:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_yaml "&gt;&lt;span class="key"&gt;visitor&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
    &lt;span class="key"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; 1
    &lt;span class="key"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; Visitor
    &lt;span class="key"&gt;level&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; 0

&lt;span class="key"&gt;user&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
    &lt;span class="key"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; 2
    &lt;span class="key"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; User
    &lt;span class="key"&gt;level&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; 10

&lt;span class="key"&gt;contributor&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
    &lt;span class="key"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; 3
    &lt;span class="key"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; Contributor
    &lt;span class="key"&gt;level&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; 20

&lt;span class="key"&gt;provider&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
    &lt;span class="key"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; 4
    &lt;span class="key"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; Provider
    &lt;span class="key"&gt;level&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; 50

&lt;span class="key"&gt;operator&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
    &lt;span class="key"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; 5
    &lt;span class="key"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; Operator
    &lt;span class="key"&gt;level&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; 100

&lt;span class="key"&gt;administrator&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
    &lt;span class="key"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; 6
    &lt;span class="key"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; Administrator
    &lt;span class="key"&gt;level&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; 500

&lt;span class="key"&gt;webmaster&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt;
    &lt;span class="key"&gt;id&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; 7
    &lt;span class="key"&gt;name&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; Webmaster
    &lt;span class="key"&gt;level&lt;/span&gt;&lt;span class="punct"&gt;:&lt;/span&gt; 1000&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;The important thing to remember is to provide a unique string to identify each record, before specifying each fiels. The other files look similar, so I won&amp;#8217;t bother listing them here.&lt;/p&gt;


	&lt;p&gt;And here&amp;#8217;s the simple code for the migration:&lt;/p&gt;


&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="ident"&gt;require&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;active_record/fixtures&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;

&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;LoadDefaults&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;down&lt;/span&gt;
        &lt;span class="ident"&gt;models&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;default_models&lt;/span&gt;
        &lt;span class="ident"&gt;models&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;m&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;   
            &lt;span class="constant"&gt;Fixtures&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;create_fixtures&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;default_directory&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;m&lt;/span&gt;&lt;span class="punct"&gt;)&lt;/span&gt;
        &lt;span class="keyword"&gt;end&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="ident"&gt;models&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;self&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;default_models&lt;/span&gt;
        &lt;span class="ident"&gt;models&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;each&lt;/span&gt; &lt;span class="keyword"&gt;do&lt;/span&gt; &lt;span class="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;m&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt;
            &lt;span class="ident"&gt;eval&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="expr"&gt;#{m.singularize.capitalize}&lt;/span&gt;.delete_all&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;end&lt;/span&gt;

    &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;self.default_directory&lt;/span&gt;
        &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;join&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;dirname&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="constant"&gt;__FILE__&lt;/span&gt;&lt;span class="punct"&gt;),&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;defaults&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;&lt;/span&gt; &lt;span class="punct"&gt;)&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.default_models&lt;/span&gt;
        &lt;span class="ident"&gt;files&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="ident"&gt;names&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="constant"&gt;Dir&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;glob&lt;/span&gt;&lt;span class="punct"&gt;(&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="expr"&gt;#{self.default_directory}&lt;/span&gt;/*.yml&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;),&lt;/span&gt; &lt;span class="punct"&gt;[]&lt;/span&gt;
        &lt;span class="keyword"&gt;unless&lt;/span&gt; &lt;span class="ident"&gt;files&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;blank?&lt;/span&gt;
            &lt;span class="ident"&gt;files&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="punct"&gt;|&lt;/span&gt;&lt;span class="ident"&gt;f&lt;/span&gt;&lt;span class="punct"&gt;|&lt;/span&gt; &lt;span class="ident"&gt;names&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;File&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;basename&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;f&lt;/span&gt;&lt;span class="punct"&gt;,&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;.yml&lt;/span&gt;&lt;span class="punct"&gt;')&lt;/span&gt; &lt;span class="punct"&gt;}&lt;/span&gt;
            &lt;span class="ident"&gt;names&lt;/span&gt;
        &lt;span class="keyword"&gt;else&lt;/span&gt;
            &lt;span class="punct"&gt;[]&lt;/span&gt;
        &lt;span class="keyword"&gt;end&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;

&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

	&lt;p&gt;Basically the migration will look in a directory named &amp;#8220;defaults&amp;#8221; for some &lt;span class="caps"&gt;YAML&lt;/span&gt; files named after a particular database table, and it will attempt to load all the records defined in each one of them. 
The &lt;code&gt;down&lt;/code&gt; method of the migration &lt;em&gt;deletes all the data in the specified tables&lt;/em&gt;, so use with care&amp;#8230;&lt;/p&gt;</description>
      <pubDate>Sat, 15 Sep 2007 13:10:00 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:2e3a8a4c-c087-4c62-842f-5f75299003d5</guid>
      <author>h3rald</author>
      <link>http://www.h3rald.com/blog/simply-on-rails-4-default-data-migrations</link>
      <category>Blog</category>
      <category>Rails</category>
      <category>ruby</category>
      <category>databases</category>
      <trackback:ping>http://www.h3rald.com/trackback/entries/119</trackback:ping>
    </item>
    <item>
      <title>"Simply On Rails - Part 4: Quick and Easy Default Data Migrations" by Electrical Repair</title>
      <description>&lt;p&gt;Migrations would make the application much more flexible in terms of moving it among different DB servers and more.&lt;/p&gt;</description>
      <pubDate>Sat, 22 Dec 2007 02:47:22 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:02d5775a-3ed5-414c-819e-8643ce9a1857</guid>
      <link>http://www.h3rald.com/blog/simply-on-rails-4-default-data-migrations#comment-171</link>
    </item>
    <item>
      <title>"Simply On Rails - Part 4: Quick and Easy Default Data Migrations" by Mike</title>
      <description>&lt;p&gt;Cool code and post. I second the idea of using Migrations with such application.&lt;/p&gt;


	&lt;p&gt;Thanks&lt;/p&gt;</description>
      <pubDate>Tue, 27 Nov 2007 16:36:01 -0700</pubDate>
      <guid isPermaLink="false">urn:uuid:c2d88b1a-3f6f-4763-ab7c-1dfdb364e703</guid>
      <link>http://www.h3rald.com/blog/simply-on-rails-4-default-data-migrations#comment-137</link>
    </item>
    <item>
      <title>"Simply On Rails - Part 4: Quick and Easy Default Data Migrations" by Fabio Cevasco</title>
      <description>&lt;p&gt;Indeed, indeed you are right. You have to be careful when you prepare the YAML files, and in certain situation (and for certain kind of data) a more standard approach is recommendable.&lt;/p&gt;</description>
      <pubDate>Sun, 16 Sep 2007 02:40:48 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:e7f6a561-2fe0-4a3e-836c-b0333b4aa478</guid>
      <link>http://www.h3rald.com/blog/simply-on-rails-4-default-data-migrations#comment-79</link>
    </item>
    <item>
      <title>"Simply On Rails - Part 4: Quick and Easy Default Data Migrations" by Pei Mei</title>
      <description>&lt;p&gt;Very nice. I still prefer to include my migrations as rails code User.create() in my migrations to avoid having developers create dodgy yaml files though, especially with pks.&lt;/p&gt;</description>
      <pubDate>Sat, 15 Sep 2007 23:41:35 -0600</pubDate>
      <guid isPermaLink="false">urn:uuid:f6d0f335-abbc-48d4-8c3c-3206bd320587</guid>
      <link>http://www.h3rald.com/blog/simply-on-rails-4-default-data-migrations#comment-76</link>
    </item>
  </channel>
</rss>
