<?xml version="1.0" encoding="UTF-8"?>
<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
  <title>BillSiggelkow.com - Home</title>
  <id>tag:billsiggelkow.com,2008:mephisto/</id>
  <generator uri="http://mephistoblog.com" version="0.8.0">Mephisto Drax</generator>
  <link href="http://billsiggelkow.com/feed/atom.xml" rel="self" type="application/atom+xml"/>
  <link href="http://billsiggelkow.com/" rel="alternate" type="text/html"/>
  <updated>2008-09-29T15:15:35Z</updated>
  <entry xml:base="http://billsiggelkow.com/">
    <author>
      <name>bsiggelkow</name>
    </author>
    <id>tag:billsiggelkow.com,2008-09-29:11</id>
    <published>2008-09-29T15:14:00Z</published>
    <updated>2008-09-29T15:15:35Z</updated>
    <category term="Ruby and Rails"/>
    <category term="activerecord"/>
    <category term="callback"/>
    <category term="metaprogramming"/>
    <category term="rails"/>
    <category term="ruby"/>
    <link href="http://billsiggelkow.com/2008/9/29/disable-activerecord-callbacks" rel="alternate" type="text/html"/>
    <title>Disable ActiveRecord Callbacks</title>
<content type="html">
            &lt;p&gt;Rails ActiveRecord callbacks are great. Callbacks give you &quot;aspect-oriented&quot; 
behavior that really helps clean up model code and isolate ancillary actions.&lt;/p&gt;

&lt;p&gt;But sometimes those callbacks can get in the way. I am working
on a large, data-intensive application that provides an automated way to import
data from a legacy application
into the  Rails application. In some cases, when uploading large quantities of data,
the callbacks can prove to be a performance hindrance because of the overhead involved.&lt;/p&gt;

&lt;p&gt;It would be nice if it were possible to disable these callbacks programmatically.
I use rake tasks to drive the legacy data import routines. If I had a
way to tell an ActiveRecord model class to ignore callbacks, it would allow 
intensive import routines to run much faster.&lt;/p&gt;

&lt;p&gt;Granted, this is inherently dangerous; Rails rightfully assumes that&lt;br /&gt;
callbacks are there for a purpose and (as far as I can tell) does not provide
a way to disable them. But in my case, it made sense to provide such
an ability.&lt;/p&gt;

&lt;p&gt;My solution was to open up ActiveRecord::Base and use Ruby's
metaprogramming tricks to selectively undefine (disable) and redefine (enable)
a given callbacks. I placed the Ruby file containing this &quot;monkey patch&quot; in
the &lt;code&gt;lib&lt;/code&gt; folder of my Rails app.&lt;/p&gt;

&lt;pre&gt;
module ActiveRecord
  class Base
    class &amp;lt;&amp;lt; self
      def disable_callback(callback)
        if callback.to_s =~ /^(after|before)_/ &amp;&amp; method_defined?(callback)
          alias_method &quot;__#{callback}&quot;, callback
          undef_method callback
          true
        else
          false
        end
      end
      def enable_callback(callback)
        if callback.to_s =~ /^(after|before)_/ &amp;&amp; 
           !method_defined?(callback) &amp;&amp; 
           method_defined?(&quot;__#{callback}&quot;) 
          alias_method callback, &quot;__#{callback}&quot;
          undef_method &quot;__#{callback}&quot;
          true
        else
          false
        end
      end
    end
  end  
end
&lt;/pre&gt;

&lt;p&gt;Let's take a what this code does. First of all, for those new to Ruby, 
Ruby supports open classes. In other words, a programmer can open any loaded class
and change its implementation. The class that opened up is not replaced;
rather, it is modified on-the-fly (when the monkey patch is loaded). In this 
case, I am opening up the Base class for ActiveRecord models. I want to add a
class method to Base that allows me to disable and reenable callbacks. 
I would like the API to work as follows:&lt;/p&gt;

&lt;pre&gt;
# Disable a given callback
MyModel.disable_callback(:after_save)

# Import the data (or whatever data-intensive operation is to be performed)
MyModel.import_data(...)

# Now reenable the callback
MyModel.enable_callback(:after_save)
&lt;/pre&gt;

&lt;p&gt;Now, back to the implementation. I want to undefine the callback
method when it's disabled, and redefine it what it's enabled. To accomplish this
I can use Ruby's &lt;code&gt;undef&lt;/code&gt; method. But what a second -- I want to add 
&lt;code&gt;disable_callback&lt;/code&gt; and &lt;code&gt;enable_callback&lt;/code&gt; as class methods; but I need
them to undefine instance methods (e.g. &lt;code&gt;after_save&lt;/code&gt;). How is this possible?&lt;/p&gt;

&lt;p&gt;Ruby has the concept of an &lt;em&gt;eigenclass&lt;/em&gt; (aka the &quot;singleton class&quot; and the &quot;metaclass&quot;).
We can open up the eigenclass and then add methods that can affect created instances.
(For an excellent explanation check out &lt;a href=&quot;http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html&quot;&gt;Seeing Metaclasses Clearly&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Using this technique, we can add class methods to any class that extends ActiveRecord::Base, and, within those class methods,
modify the callback methods (which are instance methods). So to disable a callback,
I first alias the method (so that it can be re-enabled) and then undefine it. To re-enable
a callback method I reverse the process ... that is, I find the aliased (original) 
callback method, and re-alias it to its proper name.&lt;/p&gt;

&lt;p&gt;In fact, you could use this approach to disable/enable &lt;strong&gt;any method&lt;/strong&gt; on
an ActiveRecord object. To prevent such encompassing behavior, I put some checks
in place that ensure that the method name conforms to the naming convention for
callback methods.&lt;/p&gt;

&lt;p&gt;Well, this technique should be used carefully, I was pleased that I could
coerce the behavior needed using Ruby's powerful metaprogramming capabilities.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://billsiggelkow.com/">
    <author>
      <name>bsiggelkow</name>
    </author>
    <id>tag:billsiggelkow.com,2008-08-29:9</id>
    <published>2008-08-29T18:12:00Z</published>
    <updated>2008-08-29T18:17:38Z</updated>
    <category term="Ruby and Rails"/>
    <category term="intersection"/>
    <category term="range"/>
    <category term="ruby"/>
    <link href="http://billsiggelkow.com/2008/8/29/ruby-range-intersection" rel="alternate" type="text/html"/>
    <title>Ruby Range Intersection</title>
<content type="html">
            Here's an easy way to intersect two ranges in Ruby. The method will return a range for the range that is common (the overlap) between the two ranges; or &lt;code&gt;nil&lt;/code&gt; if there is no overlap.

&lt;pre&gt;
class Range
  def intersection(range)
    res = self.to_a &amp; range.to_a
    res.empty? ? nil : (res.first..res.last) 
  end
  alias_method :&amp;, :intersection
end
&lt;/pre&gt;
          </content>  </entry>
  <entry xml:base="http://billsiggelkow.com/">
    <author>
      <name>bsiggelkow</name>
    </author>
    <id>tag:billsiggelkow.com,2008-07-13:7</id>
    <published>2008-07-13T21:09:00Z</published>
    <updated>2008-07-13T21:09:43Z</updated>
    <link href="http://billsiggelkow.com/2008/7/13/waking-up-this-morning" rel="alternate" type="text/html"/>
    <title>Waking Up This Morning</title>
<content type="html">
            &lt;p&gt;Once upon  a time I wrote a book. It was hard work, it was frustrating, it was fun, and it was rewarding. Since then I have done very little writing. Now is the time for that to change.&lt;/p&gt;


	&lt;p&gt;I slept in a bit today. The warm shower and the hot coffee called to me “You need us, you need us!”, and I did. Before embarking on my morning ritual of becoming lucid, I said to my son, “Good morning, son!” He’s eight. There are times when raising a child that they say the simplest little things that make you love them so much. All my son said to me was  “Okay. I am going to feed &lt;em&gt;all&lt;/em&gt; the animals, Dad.”  That might not sound like a big thing, but we have a &lt;em&gt;lot&lt;/em&gt; of animals.&lt;/p&gt;


	&lt;p&gt;There’s the 8-year old dog, Precious. Born roughly 3 months before the eight-year old son. Sweet, but a bit of a pain. She seems to enjoy the things that irritate us&#8212;incessantly chewing on her backside, and barking up a storm after she was let outside a minute before. Then there&#8217;s stealing your lunch as it sits on unguarded, and, of course, laying on the couch. With the latter she very consistently favors the love seat, deftly tossing off the throw pillows. She seems to know that they are &lt;em&gt;throw&lt;/em&gt; pillows.&lt;/p&gt;


	&lt;p&gt;There are the two black cats, Pepper and Gulliver. Both sweet and both, well, annoying in their own special ways. Pepper, a.k.a. the &#8220;fat cat&#8221;, enjoys meowing and meowing until he’s fed. Two minutes later, the meowing begins again. Gulliver, on the other hand is much less vocal than his so-called brother. He makes up for this by annoying us in other ways&#8212;hiding in places that we still have no idea of where they are, and tossing up the occasional hair-ball. But, the one thing about Gulliver that sets him apart from the rest of the entire family, humanoids included, is that he has been with me for somewhere around 16 years. Long before I even had a family.&lt;/p&gt;


	&lt;p&gt;So we’ve got the dog and the two cats&#8212;now onto the more interesting critters. My son’s favorite pet, Crush, is a 3-year old Russian Tortoise. A tortoise, mind you, not  a turtle. But it seems like he’s always being referred to as such. Whenever he hears &#8220;feed the turtle&#8221; he thinks to himself, “Stupid humans, I am going to start calling them ‘gorillas’!”  When it comes to maintenance, Crush is the best of the bunch. Lettuce in the morning, a change of water every week, and a change of bedding every few months. If only all the other members of the household were so easy to care for! But, sad to say, we “stupid humans” still tend to neglect this poor creature. We let him walk around outside of his dry aquarium far too infrequently.&lt;/p&gt;


	&lt;p&gt;Okay, so we’re up to 4 animals&#8212;10 to go! The last 10 are actually the newest addition to the family. They’re all tropical fish, and they appear to be quite hardy considering we tend to neglect them as well.&lt;/p&gt;


	&lt;p&gt;So when my son said “I’ll feed all the animals” it was no small task. And the thought that he wanted to do this warmed my heart.&lt;/p&gt;
          </content>  </entry>
  <entry xml:base="http://billsiggelkow.com/">
    <author>
      <name>bsiggelkow</name>
    </author>
    <id>tag:billsiggelkow.com,2008-07-11:6</id>
    <published>2008-07-11T18:41:00Z</published>
    <updated>2008-07-11T18:43:23Z</updated>
    <link href="http://billsiggelkow.com/2008/7/11/bill-s-tweeting-his-ipod-a-to-z" rel="alternate" type="text/html"/>
    <title>Bill's Tweeting His iPOD A to Z!</title>
<content type="html">
            &lt;a href=&quot;http://twitter.com/bsiggelkow&quot;&gt;Check it out!&lt;/a&gt;
          </content>  </entry>
  <entry xml:base="http://billsiggelkow.com/">
    <author>
      <name>bsiggelkow</name>
    </author>
    <id>tag:billsiggelkow.com,2008-06-09:5</id>
    <published>2008-06-09T11:44:00Z</published>
    <updated>2008-07-06T04:29:49Z</updated>
    <category term="Ruby and Rails"/>
    <category term="migrations"/>
    <category term="rails"/>
    <category term="test"/>
    <link href="http://billsiggelkow.com/2008/6/9/rails-2-1-migrations-looking-out-for-you-best-interests" rel="alternate" type="text/html"/>
    <title>Rails 2.1 Migrations - Looking out for your best interests</title>
<content type="html">
            I hit upon a nice new feature of Rails 2.1 (at least, I believe this was introduced in 2.1). I was running my test suite in one terminal window, and in another, I went ahead and created a needed migration. I then went back to the window running the tests, identified and fixed some bugs, and then re-ran &lt;code&gt;rake test:units&lt;/code&gt; whereupon I was greeted with this helpful message.

&lt;pre&gt;
~/dev/projects/resman_machine $ rake test:units
(in /Users/bsiggelkow/dev/projects/foo_bar)
You have 1 pending migrations:
  20080609112303_AddFooToBars
Run &quot;rake db:migrate&quot; to update your database then try again.
&lt;/pre&gt;

This was definitely a problem that I run into numerous times before. Tests would fail simply because I had neglected to run some migrations. Rails just keeps on getting better and better.
          </content>  </entry>
  <entry xml:base="http://billsiggelkow.com/">
    <author>
      <name>bsiggelkow</name>
    </author>
    <id>tag:billsiggelkow.com,2008-05-21:2</id>
    <published>2008-05-21T14:04:00Z</published>
    <updated>2008-05-21T14:18:47Z</updated>
    <category term="Workstyle"/>
    <category term="jelly"/>
    <link href="http://billsiggelkow.com/2008/5/21/jelly-day" rel="alternate" type="text/html"/>
    <title>Jelly Day</title>
<content type="html">
            I am excited about attending my first &lt;a href=&quot;http://wiki.workatjelly.com/JellyInRoswell-May21&quot;&gt;Jelly&lt;/a&gt; today. This particular Jelly was featured on &lt;a href=&quot;http://www.cnn.com/2008/LIVING/worklife/04/07/coworking/index.html&quot;&gt;CNN&lt;/a&gt;. NPR also did a story on Jellies a few months back as well.
          </content>  </entry>
  <entry xml:base="http://billsiggelkow.com/">
    <author>
      <name>admin</name>
    </author>
    <id>tag:billsiggelkow.com,2008-05-19:1</id>
    <published>2008-05-19T20:08:00Z</published>
    <updated>2008-05-19T20:08:47Z</updated>
    <link href="http://billsiggelkow.com/2008/5/19/welcome" rel="alternate" type="text/html"/>
    <title>Welcome!</title>
<content type="html">
            Welcome to the Camp ... I guess you all know why you are here.
          </content>  </entry>
</feed>
