<?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>Michael Schuerig</title>
	<atom:link href="http://www.schuerig.de/michael/blog/index.php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.schuerig.de/michael/blog</link>
	<description>Sentenced to making sense</description>
	<lastBuildDate>Fri, 19 Apr 2013 21:29:26 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Copying tags between music files</title>
		<link>http://www.schuerig.de/michael/blog/index.php/2013/04/19/copying-tags-between-music-files/</link>
		<comments>http://www.schuerig.de/michael/blog/index.php/2013/04/19/copying-tags-between-music-files/#comments</comments>
		<pubDate>Fri, 19 Apr 2013 21:28:05 +0000</pubDate>
		<dc:creator>michael</dc:creator>
				<category><![CDATA[Music]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.schuerig.de/michael/blog/?p=86</guid>
		<description><![CDATA[Over the years, I&#8217;ve ripped CDs in various formats. In the beginning, it was MP3, but I soon switched to OGG. A few years ago I, it made the switch to FLAC. Unfortunately, that leaves me with a large &#8220;sediment&#8221; of files in lossy formats and I&#8217;ve started to rip those again &#8212; for the [...]]]></description>
				<content:encoded><![CDATA[<p>Over the years, I&#8217;ve ripped CDs in various formats. In the beginning, it was MP3, but I soon switched to OGG. A few years ago I, it made the switch to FLAC. Unfortunately, that leaves me with a large &#8220;sediment&#8221; of files in lossy formats and I&#8217;ve started to rip those again &#8212; for the last time, I hope.</p>
<p>The ripping is tedious, but redoing the tags would be far worse. So here&#8217;s a script to help avoid the drudgery.</p>
<p>This is how it is used:</p>
<p><code>
<pre>
$ copytags.rb --help
Usage: copytags [options] from_pattern to_pattern
    -n, --dry-run                    Don't run any commands, just print them
    -t, --tag                        copy tags from matching files (default)
    -T, --no-tag                     do not copy tags from matching files
    -r, --rename                     rename from matching files
    -R, --no-rename                  do not rename from matching files (default)
    -q, --quiet                      Display less information
    -v, --verbose                    Display extra information
    -h, --help                       Show this message

Examples
    # Copy tags from 1.Track.ogg to 1.Track.flac
    copytags '%.1d.*.ogg' '%.1d.*.flac'

    # Copy tags from 01.Track.ogg to 01.Track.flac
    copytags '%.2d.*.ogg' '%.2d.*.flac'
                                                                                                                                                    
    # Assuming 1.Song.ogg, rename 1.Track.flac to 1.Song.flac                                                                                       
    copytags -rT '%.1d.*.ogg' '%.1d.*.flac'                                                                                                         
</pre>
<p></code></p>
<p>And this is the script:</p>
<p><script src="https://gist.github.com/mschuerig/5322030.js"> </script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.schuerig.de/michael/blog/index.php/2013/04/19/copying-tags-between-music-files/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Scripted Screenshots</title>
		<link>http://www.schuerig.de/michael/blog/index.php/2012/08/27/scripted-screenshots/</link>
		<comments>http://www.schuerig.de/michael/blog/index.php/2012/08/27/scripted-screenshots/#comments</comments>
		<pubDate>Mon, 27 Aug 2012 05:01:28 +0000</pubDate>
		<dc:creator>michael</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.schuerig.de/michael/blog/?p=80</guid>
		<description><![CDATA[I recently needed to make a screenshot of an entire web page, i.e. not just the part the fits on the screen (or in the viewport), but the whole thing from top to bottom. Somehow I missed the possibility that there might be a zillion browser extensions for just this purpose. From writing features (acceptance [...]]]></description>
				<content:encoded><![CDATA[<p>I recently needed to make a screenshot of an entire web page, i.e. not just the part the fits on the screen (or in the viewport), but the whole thing from top to bottom.</p>
<p>Somehow I missed the possibility that there might be a zillion browser extensions for just this purpose. From writing <em>features</em> (acceptance tests) with <a href="http://cukes.info/">Cucumber</a> I&#8217;m familiar with <a href="http://phantomjs.org/">PhantomJS</a>, a &#8220;headless&#8221;, scriptable browser based on WebKit.</p>
<p>Here&#8217;s how it works:</p>
<p><code>
<pre>
$ webshot --help
Usage: webshot [OPTIONS]... URL IMAGE_FILE

Options:
          -j|--jquery           Inject jQuery into the page.
         +-e|--exec «value»     Execute script in page context.
         +-f|--file «value»     Execute script file in page context.
          -v|--viewport «value» Viewport size WxH; default 1280x800.

          (* mandatory option)
          (+ repeatable option)
</pre>
<p></code></p>
<p><script src="https://gist.github.com/3481306.js"> </script></p>
<p>Luckily, I didn&#8217;t have to write the commandline parsing myself. But it was fun to figure out how <code><em>Deferreds</em></code> might be implemented.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.schuerig.de/michael/blog/index.php/2012/08/27/scripted-screenshots/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting a view at views</title>
		<link>http://www.schuerig.de/michael/blog/index.php/2012/06/08/getting-a-view-at-views/</link>
		<comments>http://www.schuerig.de/michael/blog/index.php/2012/06/08/getting-a-view-at-views/#comments</comments>
		<pubDate>Fri, 08 Jun 2012 16:36:02 +0000</pubDate>
		<dc:creator>michael</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.schuerig.de/michael/blog/?p=75</guid>
		<description><![CDATA[The structure of Rails views can become rather complicated with templates, layouts and partials inclusions multiple levels deep. Here are two tools for disentangling views. The first one adds HTML comments to generated markup. These comments identify the file where the markup originated. Place it in config/initializers/show_view_structure.rb The second tool works offline. It prints the [...]]]></description>
				<content:encoded><![CDATA[<p>The structure of Rails views can become rather complicated with templates, layouts and partials inclusions multiple levels deep. Here are two tools for disentangling views.</p>
<p>The first one adds HTML comments to generated markup. These comments identify the file where the markup originated. Place it in <code>config/initializers/show_view_structure.rb</code></p>
<p><script src="https://gist.github.com/2893986.js?file=show_view_structure.rb"></script></p>
<p>The second tool works offline. It prints the hierarchical structure of template inclusions</p>
<p><script src="https://gist.github.com/2894015.js?file=view_structure.rb"></script></p>
<p>There&#8217;s a limitation in that only explicit partial renderings are recognized. Layouts are not taken into account and partials rendered from helpers are not recognized either.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.schuerig.de/michael/blog/index.php/2012/06/08/getting-a-view-at-views/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Better Rake Bash completion</title>
		<link>http://www.schuerig.de/michael/blog/index.php/2012/06/08/better-rake-bash-completion/</link>
		<comments>http://www.schuerig.de/michael/blog/index.php/2012/06/08/better-rake-bash-completion/#comments</comments>
		<pubDate>Fri, 08 Jun 2012 16:09:55 +0000</pubDate>
		<dc:creator>michael</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Shell]]></category>
		<category><![CDATA[Tools]]></category>

		<guid isPermaLink="false">http://www.schuerig.de/michael/blog/?p=71</guid>
		<description><![CDATA[What&#8217;s new? Rake tasks are cached (thanks to turadb). If there is no Rakefile in the current directory, ancestor directories are searched in the way Rake itself does. Installation Copy the file to /etc/bash_completion.d or possibly /usr/share/bash-completion/completions or to another place where it is loaded when your Bash shell is started.]]></description>
				<content:encoded><![CDATA[<h2>What&#8217;s new?</h2>
<ol>
<li>Rake tasks are cached (thanks to <a href="http://turadg.aleahmad.net/2011/02/bash-completion-for-rake-tasks/">turadb</a>).</li>
<li>If there is no Rakefile in the current directory, ancestor directories are searched in the way Rake itself does.</li>
</ol>
<h2>Installation</h2>
<p>Copy the file to <code>/etc/bash_completion.d</code> or possibly <code>/usr/share/bash-completion/completions</code> or to another place where it is loaded when your Bash shell is started.</p>
<p><script src="https://gist.github.com/2892103.js?file=rake.sh"></script></p>
]]></content:encoded>
			<wfw:commentRss>http://www.schuerig.de/michael/blog/index.php/2012/06/08/better-rake-bash-completion/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Humble HATEOAS</title>
		<link>http://www.schuerig.de/michael/blog/index.php/2009/06/04/humble-hateoas/</link>
		<comments>http://www.schuerig.de/michael/blog/index.php/2009/06/04/humble-hateoas/#comments</comments>
		<pubDate>Thu, 04 Jun 2009 01:52:57 +0000</pubDate>
		<dc:creator>michael</dc:creator>
				<category><![CDATA[REST]]></category>
		<category><![CDATA[SOA]]></category>

		<guid isPermaLink="false">http://www.schuerig.de/michael/blog/?p=64</guid>
		<description><![CDATA[HATEOAS is an acronym coined in the context of RESTful web services. It stands for Hypermedia as the engine of application state. Imagine the client, human or machine, in a conversation with the server. They take it in turns, the client asks (requests) something of the server, who promptly responds. Of course, a polite client [...]]]></description>
				<content:encoded><![CDATA[<p><em>HATEOAS</em> is an acronym coined in the context of <a href="http://en.wikipedia.org/wiki/Representational_State_Transfer">RESTful web services</a>. It stands for <em>Hypermedia as the engine of application state</em>. Imagine the client, human or machine, in a conversation with the server.</p>
<p>They take it in turns, the client asks (<em>requests</em>) something of the server, who promptly responds. Of course, a polite client <a href="http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven">doesn&#8217;t ask just anything of the humble server</a>. Rather, in keeping with protocol, the client only follows the leads (<em>links</em>) suggested by the server. Thus, the conversation is advanced by following link after link.</p>
<p>That&#8217;s as good as it is, no diplomatic incidents caused by a client stepping out of line. But does it make for a good conversation? Hardly, with a client who only knows how to be polite, but has no idea what he is talking about. Talking <em>about</em> something presupposes semantics, in this case, an agreement about the <em>meaning</em> of following a particular lead (link).</p>
<p>Talking about something becomes a lot easier when you have an idea what the topic is supposed to be. Enter <a href="http://en.wikipedia.org/wiki/Internet_media_type"><em>Media Types</em></a>. Not any old <code>text/plain</code>, <code>application/xml</code> &#8212; that&#8217;s like talking about the weather, only for machines. You want something with substance, something fitting your own conversational niche:</p>
<pre>
  application/x.mytopic+xml
</pre>
<p>There, <code>application</code> indicates a &#8220;multipurpose&#8221; file, not specifically geared towards human consumption. <code>x.</code> indicates that it is an experimental media type, not registered with IANA. If you&#8217;ve got more clout, maybe you&#8217;ll be able to officially register a <code>vnd.</code> (vendor) or <code>.prs</code> (personal) type. Finally, the <code>+xml</code> suffix says that the media type is based on <tt>XML</tt>.</p>
<p>Now for the dénouement: That&#8217;s it.</p>
<p>No magic RESTful pixie dust. No script for successfully chatting up every server. Nothing. You could use <tt>XML Schema</tt> or a relative to specify the data contents of the media types you are using. You could even write some nice prose explaining in so many words what lies ahead when someone follows a link with, say, <code>rel="payment"</code>. If you fancy arcane arts, you might write pre- and postconditions in <a href="http://en.wikipedia.org/wiki/Object_Constraint_Language"><tt>OCL</tt></a>.</p>
<p>In summary, HATEOAS doesn&#8217;t imbue client software with more intelligence. It inserts a (useful) level of indirection by offering the client a choice of transitions. Thereby achieving two things: The client is ignorant of the concrete <tt>URI</tt>s associated with transitions; for all it knows they can be different each time. The client doesn&#8217;t have to figure out which transitions are applicable, because the server only offers those to begin with.</p>
<p>What it <em>means</em> to effect a particular transition must still be explicitly coded. So, if the client-side workflow stipulates that a payment transaction is to be started at some point, someone, somewhere has to know of the agreement that such a transition is indicated by a link with <code>rel="payment"</code> and write code to look for and follow such a link.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.schuerig.de/michael/blog/index.php/2009/06/04/humble-hateoas/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Creative Associations</title>
		<link>http://www.schuerig.de/michael/blog/index.php/2009/05/29/creative-associations/</link>
		<comments>http://www.schuerig.de/michael/blog/index.php/2009/05/29/creative-associations/#comments</comments>
		<pubDate>Fri, 29 May 2009 14:01:58 +0000</pubDate>
		<dc:creator>michael</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.schuerig.de/michael/blog/?p=62</guid>
		<description><![CDATA[A presentation I held on May 28 at Düsseldorf on Rails about interesting and useful things you can do with ActiveRecord, SQL, and a smart database. german english .]]></description>
				<content:encoded><![CDATA[<p>A presentation I held on May 28 at <a href="http://groups.google.de/group/duesseldorf-on-rails">Düsseldorf on Rails</a> about interesting and useful things you can do with <tt>ActiveRecord</tt>, <tt>SQL</tt>, and a smart database.</p>
<ul>
<li><a href="http://www.schuerig.de/michael/pres/kreative-assoziationen/index.html">german</a></li>
<li><a href="http://www.schuerig.de/michael/pres/kreative-assoziationen/index.html.en">english</a></li>
</ul>
<p>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.schuerig.de/michael/blog/index.php/2009/05/29/creative-associations/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>No database to rule them all. Branch databases for Rails and git</title>
		<link>http://www.schuerig.de/michael/blog/index.php/2009/04/09/branch-db/</link>
		<comments>http://www.schuerig.de/michael/blog/index.php/2009/04/09/branch-db/#comments</comments>
		<pubDate>Wed, 08 Apr 2009 23:04:37 +0000</pubDate>
		<dc:creator>michael</dc:creator>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[git]]></category>

		<guid isPermaLink="false">http://www.schuerig.de/michael/blog/?p=59</guid>
		<description><![CDATA[You&#8217;re using git to manage your Ruby on Rails projects? Then you&#8217;ve probably come to appreciate topic branches as a kind of transaction facility for programmers. If you need to implement a non-trivial or just try something, the way to go is onto a new &#8220;topic&#8221; branch. There you can mangle the code all you [...]]]></description>
				<content:encoded><![CDATA[<p>You&#8217;re using <em><code>git</code></em> to manage your <em>Ruby on Rails</em> projects? Then you&#8217;ve probably come to appreciate topic branches as a kind of transaction facility for programmers. If you need to implement a non-trivial or just try something, the way to go is onto a new &#8220;topic&#8221; branch. There you can mangle the code all you like, without fearing to cause any lasting harm. In case everything works out fine, you merge the branch into the master branch and discard it. If you come to a dead end &#8212; well, you <em>just</em> discard the misbegotten branch.</p>
<p>But what about the database? If moving along your branch involves changes to the database, structural changes in particular, you can&#8217;t easily switch to another branch without these changes. In other words, your development database is really only suitable for a single branch.</p>
<p>Up to now, that is. Install the <code>branch_db</code> gem and what you get is a private database for your branch that you can mutilate without interfering with work on the other branches.</p>
<p>For details and installation instructions see the <a href="http://github.com/mschuerig/branch_db/blob/master/README.rdoc">README</a>. Here&#8217;s just an appetizer. Say you&#8217;re on branch &#8220;feature&#8221; and want a private copy of the &#8220;master&#8221; database. Here&#8217;s how you do it:</p>
<p><code>
<pre>
$ rake db:branches:copy ORIG_BRANCH=master
</pre>
<p></code></p>
<h2>Getting it</h2>
<ul>
<li><a href="http://github.com/mschuerig/branch_db">github</a></li>
<li>$ sudo gem install mschuerig-branch_db</li>
</ul>
<h2>Let your Rails app know about it</h2>
<p>In the appropriate place in <code>config/environment.rb</code> add</p>
<p><code>
<pre>
config.gem "mschuerig-branch_db", :lib =&gt; 'branch_db'
</pre>
<p></code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.schuerig.de/michael/blog/index.php/2009/04/09/branch-db/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Ruby as a language for Rails views</title>
		<link>http://www.schuerig.de/michael/blog/index.php/2009/04/02/ruby-views/</link>
		<comments>http://www.schuerig.de/michael/blog/index.php/2009/04/02/ruby-views/#comments</comments>
		<pubDate>Thu, 02 Apr 2009 22:55:31 +0000</pubDate>
		<dc:creator>michael</dc:creator>
				<category><![CDATA[Rails]]></category>
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.schuerig.de/michael/blog/?p=57</guid>
		<description><![CDATA[Didn&#8217;t you always want to write your Rails views as plain Ruby objects? &#8212; &#8220;What?&#8221;, I hear you say. No, I haven&#8217;t lost my mind and the idea is quite sensible (or so I hope), once you add the restriction that it is JSON-formatted data that you want to return. Say you need to set [...]]]></description>
				<content:encoded><![CDATA[<p>Didn&#8217;t you always want to write your Rails views as plain Ruby objects? &#8212; <em>&#8220;What?&#8221;</em>, I hear you say. No, I haven&#8217;t lost my mind and the idea is quite sensible (or so I hope), once you add the restriction that it is JSON-formatted data that you want to return.</p>
<p>Say you need to set up some hashes or arrays for rendering to JSON. This is best done in Ruby and it is clearly a view concern. So let&#8217;s do it in the views. Like this:</p>
<p><code>
<pre>
  # app/controllers/movies_controller.rb
  def index
    respond_to do |format|
      format.json do
        @movies = Movie.all
        @count = Movie.count
        render :template =&gt; 'movies/index.json.rb'
      end
    end
  end
</pre>
<p></code></p>
<p><code>
<pre>
  # app/views/movies/index.json.rb
  {
    :identifier =&gt; Movie.primary_key,
    :totalCount =&gt; @count,
    # render @movies does not work as it insists on returning a string
    :items =&gt; @movies.map { |m| render(m) }
  }
</pre>
<p></code></p>
<p><code>
<pre>
  # app/views/movies/_movie.json.rb
  {
    :id =&gt; movie.to_param,
    :title =&gt; movie.title,
    :releaseDate =&gt; movie.release_date
  }
</pre>
<p></code></p>
<h2>Getting it</h2>
<ul>
<li><a href="http://github.com/mschuerig/ruby_template_handler">github</a></li>
<li>$ sudo gem install mschuerig-ruby_template_handler</li>
</ul>
<h2>Let your Rails app know about it</h2>
<p>In the appropriate place in <code>config/environment.rb</code> add</p>
<p><code>
<pre>
config.gem "mschuerig-ruby_template_handler", :lib =&gt; 'ruby_template_handler'
</pre>
<p></code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.schuerig.de/michael/blog/index.php/2009/04/02/ruby-views/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simplistic Enumerations for ActiveRecord</title>
		<link>http://www.schuerig.de/michael/blog/index.php/2009/04/02/simplistic-enums/</link>
		<comments>http://www.schuerig.de/michael/blog/index.php/2009/04/02/simplistic-enums/#comments</comments>
		<pubDate>Thu, 02 Apr 2009 19:49:03 +0000</pubDate>
		<dc:creator>michael</dc:creator>
				<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://www.schuerig.de/michael/blog/?p=55</guid>
		<description><![CDATA[Invariably, in almost every application there happen to be lists of data items that are immutable, just for reference. It could be colors, the four seasons, continents, the states of your country, kinds or types of this and that. These items are almost like constants. As accessible as they are through the ordinary ActiveRecord API, [...]]]></description>
				<content:encoded><![CDATA[<p>Invariably, in almost every application there happen to be lists of data items that are immutable, just for reference. It could be colors, the four seasons, continents, the states of your country, kinds or types of this and that. These items are <em>almost</em> like constants. As accessible as they are through the ordinary ActiveRecord API, it seems an utter waste to hit the database again and again, for data that won&#8217;t change however often you request it.</p>
<p>Of course, the Rails community recognized early on that some data are more constant than others and over the years several plugins have been published that add cached and easily accessible enumerations to ActiveRecord. Some of these additions are quite complicated or befuddle ActiveRecord by not backing the enumeration values with real database objects. My experience has been that these attempted optimizations result in bizarre behavior when I did interesting things with ActiveRecord such as multiply nested named scopes plus custom SQL.</p>
<p>So, I thought a basic, no, simplistic, version of enumerations is called for. Here&#8217;s how it looks:</p>
<p><code>
<pre>
class Color &lt; ActiveRecord::Base
  enumerates do |e|
    e.value :name =&gt; 'red'
    e.value :name =&gt; 'green'
    e.value :name =&gt; 'blue'
  end
end

Color[:green]
Color.find_by_name('red')
Color.find_by_name!(:red)
Color.all
Color.count
Color.reload
</pre>
<p></code></p>
<p><code>
<pre>
e.value :name =&gt; 'red'
</pre>
<p></code></p>
<p>ensures that a Color object with name &#8216;red&#8217; exists, if it does not, one is created.</p>
<h2>Caveats</h2>
<p>Although there is a <code>#reload</code> method defined on enumeration models, i.e. <code>Color.reload</code>, it is very unwise to use it. The point is that this method only affects a single server process and you most likely have many of them.</p>
<p>So, if you need to change enumeration values, the only way to do it is to treat it like an update to your application code.</p>
<h2>Getting it</h2>
<ul>
<li><a href="http://github.com/mschuerig/easy_enums">github</a></li>
<li>$ sudo gem install mschuerig-easy_enums</li>
</ul>
<h2>Let your Rails app know about it</h2>
<p>In the appropriate place in <code>config/environment.rb</code> add</p>
<p><code>
<pre>
config.gem "mschuerig-easy_enums", :lib => 'easy_enums'
</pre>
<p></code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.schuerig.de/michael/blog/index.php/2009/04/02/simplistic-enums/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Lifting indexes with ActiveRecord</title>
		<link>http://www.schuerig.de/michael/blog/index.php/2009/04/02/lifting-indexes/</link>
		<comments>http://www.schuerig.de/michael/blog/index.php/2009/04/02/lifting-indexes/#comments</comments>
		<pubDate>Thu, 02 Apr 2009 16:40:22 +0000</pubDate>
		<dc:creator>michael</dc:creator>
				<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://www.schuerig.de/michael/blog/?p=49</guid>
		<description><![CDATA[On a Rails project I&#8217;m currently working on I need to fill the database with test data to have something to play with. Apart from large imports, that&#8217;s the time when indexes may slow down operation severely instead of speeding things up. Consider: The indexes are not used, but have to be updated again and [...]]]></description>
				<content:encoded><![CDATA[<p>On a Rails project I&#8217;m currently working on I need to fill the database with test data to have something to play with. Apart from large imports, that&#8217;s the time when indexes may slow down operation severely instead of speeding things up. Consider: The indexes are not used, but have to be updated again and again for each new record that is inserted into the database. It is <em>much</em> cheaper, to <em>lift</em> &#8212; well, really <em>drop</em> &#8212; the indexes during mass operation and recreate them afterwards.</p>
<p>Here&#8217;s an example:</p>
<p><code>
<pre>
namespace :db do
  desc "Populate the database with sample data"
  task :populate =&gt; :environment do

    retained_indexes = [
      'index_people_on_lastname_and_firstname',
      { :table =&gt; :movies, :columns =&gt; :title }
      { :table =&gt; 'people', :columns =&gt; ['lastname', :firstname] }
    ]

    ActiveRecord::Base.transaction do
      IndexLifter.without_indexes(
        # Only consider indexes on these tables;
        # all tables by default.
        :movies,
        :people,
        # Don't lift these indexes
        :except =&gt; retained_indexes,
        # Don't lift unique indexes; default: false.
        :except_unique =&gt; true
      ) do
        ActiveRecord::Base.silence do

          # import or generate large amounts of data here

        end
      end
    end
  end
end
</pre>
<p></code></p>
<p>Please bear in mind that dropping and creating of indexes is a rather intrusive operation on the structure of your database. You should only perform it while no other users (or processes) are accessing it.</p>
<p>Also, consider that some indexes may be important for the proper function of your database. If you have <em>unique indexes</em>, i.e. indexes that enforce that particular columns or combinations of columns are unique, and if you are handling violations of this constraint in your application code, then you might need to retain these indexes even during data generation.</p>
<h2>Getting it</h2>
<ul>
<li><a href="http://github.com/mschuerig/index_lifter">github</a></li>
<li>$ sudo gem install mschuerig-index_lifter</li>
</ul>
<h2>Let your Rails app know about it</h2>
<p>In the appropriate place in <code>config/environment.rb</code> add</p>
<p><code>
<pre>
config.gem "mschuerig-index_lifter", :lib => 'index_lifter'
</pre>
<p></code></p>
]]></content:encoded>
			<wfw:commentRss>http://www.schuerig.de/michael/blog/index.php/2009/04/02/lifting-indexes/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
