No_Knead_Bread.rake

#
# Denali's No-Knead Miracle Bread
#
 
require 'cast_iron_dutch_oven'  # sudo gem install dutch_oven --version 3.5 Quart --source KitchenwaresStore
require 'mixing_bowl'
require 'spatula'
 
desc "Step 1. To be performed at night"
task(:at_night) do
 
  ingredients = { 'Warm Water'        => '2 Cups',
                  'Yeast'             => '1/4 tsp', # Yes, that's all
                  'All Purpose Flour' => '1 Cup',   # King Arthur is the best.
                  'Whole Wheat Flour' => '1/4 Cup' }
 
  MixingBowl.contents = ingredients.collect {|ingredient, amount| ingredient.measure(amount) }
 
  MixingBowl.contents.mix_thoroughly(:with => Spatula)
 
  MixingBowl.cover(:with => :cloth, :loosely => true)
 
  sleep 4.hours..8.hours
end
 
desc "Step 2. To be peformed the next morning"
task(:morning => :at_night) do
 
  ingredients = { 'All Purpose Flour' => "#{(2 + 1/2).scant} Cups",
                  'Asiago Cheese'     => '4 oz',
                  'Salt'              => '2 teaspoons' }
 
  ingredients['Asiago Cheese'].dice '3/8" cubes'
 
  MixingBowl.contents << ingredients.collect{ |ingredient, amount| ingredient.measure(amount) }
 
  MixingBowl.contents.mix_thoroughly(:with => Spatula)
 
  MixingBowl.cover(:with => :cloth, :loosely => true)
 
  sleep 6.hours..8.hours
end
 
desc "Step 3. To be performed after work"
task(:after_work => :morning) do
  Oven::MiddleRack.contents << DutchOven
  Oven::MiddleRack.contents.insert(DutchOvenCover, :next_to => DutchOven)
  Oven::PreHeat.new(500.degrees)
 
  case Oven::PreHeat.status
  when done? 
    sleep 20.minutes  # Let DutchOven heat up after oven is at temperature
  end
 
  MixingBowl.contents.sprinkle_with :flour
 
  dutch_oven_cover, dutch_oven = Oven::MiddleRack.contents.pop, Oven::MiddleRack.contents.pop
 
  dutch_oven.inside.spray_with :oil
  MixingBowl.contents.roll_into(dutch_oven, :with => WetSpatula)
 
  Oven::MiddleRack.contents << dutch_oven.cover!(dutch_oven_cover)
 
  Oven::Bake.at(475.degrees, 25.minutes)
  DutchOven.uncover!
  Oven::Bake.at(450.degrees, 12.minutes..16.minutes)
 
  Oven::MiddleRack.contents.pop
 
rescue ThirdDegreeBurnError 
  Oven.turn_off
  raise EmergencyRoomException, "Wear oven mitts next time", caller
end

Installing RMagick2 on CentOS5

I have just gone through hell attempting to install ImageMagick, RMagick2 on our CentOS5 server, and thought others might find this information useful.

It should have been as easy as

yum install ImageMagick
gem install rmagick

But unfortunately it wasn’t. The reason is because yum will install ImageMagick 6.2.8.0, while RMagick2 requires ImageMagick 6.3.0 or higher. Fantastic. My sysadmin friend says, “It’s what is in the distribution, to keep the package base consistent.” I say, “But I need ImageMagick 6.3.0+ and this is a royal pain in the neck.”

These are the steps I took to successfully install ImageMagick 6.4.3 and RMagic2 on CentOS5. It took me an entire morning to figure this out (I am not a Linux expert), but with this guide it should take you 15 minutes or less.

0. Tell Yum to Get a Grip

I wasn’t able to install any of the following RPMs, because Yum had a gripper about them being “unsigned.” You need to tell Yum to shove it. Open up /etc/yum.conf

vi /etc/yum.conf

At the very end of the file, add the following line

gpgcheck=0

That will tell Yum to install packages, regardless if they are “unsigned.”

WARNING: There’s probably a reason why gpgcheck exists. Do this at your own risk, and be sure to flip gpgcheck back to 1 when you are done.

1. Install a couple dependencies for ImageMagick

ImageMagick 6.4.3 requires two dependencies that were not in yum, libjasper.so.1 and libdjvulibre.so.15. Using http://rpm.pbone.net/, I found the RPMs that contained these files:
jasper-libs-1.900.1-7.el5.kb.i386.rpm and djvulibre-3.5.19-4.el5.kb.i386.rpm

wget ftp://ftp.pbone.net/mirror/centos.karan.org/el5/extras/testing/i386/RPMS/jasper-libs-1.900.1-7.el5.kb.i386.rpm
wget http://centos.karan.org/el5/extras/testing/i386/RPMS/djvulibre-3.5.19-4.el5.kb.i386.rpm
 
yum install jasper-libs-1.900.1-7.el5.kb.i386.rpm
yum install djvulibre-3.5.19-4.el5.kb.i386.rpm

2. Install ImageMagick and Various Development Packages

Next, we need to install ImageMagick. To simply install ImageMagick, it’s a single package. However, to make RMagick happy, we also need to install several development packages.

wget ftp://ftp.imagemagick.org/pub/ImageMagick/linux/fedora/i386/ImageMagick-6.4.3-6.i386.rpm
wget ftp://ftp.imagemagick.org/pub/ImageMagick/linux/fedora/i386/ImageMagick-devel-6.4.3-6.i386.rpm
wget ftp://ftp.imagemagick.org/pub/ImageMagick/linux/fedora/i386/ImageMagick-c++-6.4.3-6.i386.rpm
wget ftp://ftp.imagemagick.org/pub/ImageMagick/linux/fedora/i386/ImageMagick-c++-devel-6.4.3-6.i386.rpm
 
yum install ImageMagick-6.4.3-6.i386.rpm
yum install ImageMagick-devel-6.4.3-6.i386.rpm
yum install ImageMagick-c++-6.4.3-6.i386.rpm
yum install ImageMagick-c++-devel-6.4.3-6.i386.rpm

When you install the first ImageMagick package, yum should do its magic and install a bunch of dependencies, such as ghostscript, lcms, and others.

3. Install RMagick, finally

With all those RPM packages installed, you can install RMagick. If all the ImageMagick stuff is there, this should go smoothly.

gem install rmagick

4. Undo the Change to yum.conf

It’s probably wise to remove or comment-out the modification you made to yum.conf

# gpgcheck=0

Controlling Whitespace with HAML

When displaying certain elements as inline, the whitespace between tags does matter in your layout.

When trying to display some LI tags as inline, I really needed to spit out the tags with no whitespace in between. Unfortunately HAMLs handy-dandy tag indenting was wrecking me. It was so bad, that I resorted to calling a helper method that spat out the HTML as a string, with no whitespace between the tags.

But today, I discovered that if you append the HAML ‘tag’ with a “>“, it will not add any whitespace to the tag.

Example:

%ul.filter_navigation.tabnav
  %li.go.first>= link_to_function 'Gene Ontology', 'Filter.select("go")'
  %li.age>=      link_to_function 'Longevity',     'Filter.select("age")'
  %li.gaz.last>= link_to_function 'Gaz Ontology',  'Filter.select("gaz")'

Results in this HTML:

<ul class='filter_navigation tabnav'><li class="go first"><a onclick='Filter.select("go"); return false;' href="#">Gene Ontology</a></li><li class="age"><a onclick='Filter.select("age"); return false;' href="#">Longevity</a></li><li class="gaz last"><a onclick='Filter.select("gaz"); return false;' href="#">Gaz Ontology</a></li></ul>

No Whitespace! You got a date Wednesday baby!

Using Fixtures with Funky Table Names

If you have an AR Model whose table name does not follow the convention, and you have needed to set it explicitly using set_table_name.

class ChiliDog < ActiveRecord::Base
  set_table_name 'dogs_made_of_chili'
end

Then your test fixtures file must be named the same name as the table, not the model…

dogs_made_of_chili.yml

In your rspec, you must use the table name to call your fixtures, then specify the AR class that models it…

fixtures :dogs_made_of_chili
set_fixture_class :dogs_made_of_chili => 'ChiliDog'

Note that little guy set_fixture_class!! He does not appear in the online Rails API docs (at least not Rails Brain), so I had originally assumed that you would pass in a Constant, not a String to it. I was wrong!!

The class name given to set_fixture_class must be a String and not a Constant like you might assume/think/wish-for/hope/desire. If you put a constant in there, you will get all sorts of weird, will bang your head against your desk repeatedly, pull your hair, tear your clothes, pour ashes on your head, and various other Old-Testament-style lamentations.

So, word of warning, use a String, not a Constant when using set_fixture_class!

Preventing Callbacks from Firing

I have an ActiveRecord class called JournalQuery that performs a large webservice call out to the National Library of Medicine, then caches the result in our local database. Oftentimes, this call can take well over a minute to run, which is not good for the HTTP request/response cycle. In the Rails applicatin got around this limitation of HTTP by using an after_create callback to fork this web-services call into a background process using the library BackgrounDRB. My Rails app creates a new JournalQuery, and after it is saved to the database, the after_create callback launches the BackgrounDRB worker transparently.

That’s fine and dandy for the Request-Response cycle, but right now I need to write a Rake task to pre-compute and pre-cache a bunch of canned JournalQueries. I do not want to deal with the overhead and complications of forking into a background process; it’s totally overkill and unnecessary, since this Rake task is going to be fired by a cronjob, and cron obviously has no request-response cycle!

So, what about that callback? How can I avoid tripping it in my Rake task, without changing the code in my Model class?

The Easy but Bad Solution:

I could simply Monkey-Patch my Model class, redefining my callback function to return true, instead of forking off the background process. Monkey patching is the process of writing code that, at runtime, opens up a class, and redefines methods inside that class. Yes, Ruby lets you do that, and yes, it is often as terrible an idea as it sounds (although sometimes extremely handy).

I didn’t want to do this, because this egregious a monkey patch would probably lead to unforeseen and extremely weird behavior at some point down the line. Then I got to thinking…what if I saved the code inside the original callback, applied said egregious monkeypatch, then monkeypatched my monkeypatch with the original callback, thus restoring harmony to the universe?

The Elegant Solution That Took Two Hours Instead of Two Minutes:

…And what if I did it all inside a class method, that accepted a block? Yeah baby! So I wrote this method, which is sitting at the bottom of this post. The method is called allow_skipped_callbacks_on, and accepts a Ruby Constant (assumed to be the name of a Class that you want to violate). This method opens up the victim class with a class_eval, and defines a class method called without_callback. Without_callback accepts a symbol, which is the name of your callback function, and a code block; without_callback saves the original callback method into a local variable, overwrites it with a stub, then executes the code in your block, and finally undoes all the changes it made to your poor little class.

Example:

Let’s say you have an ActiveRecord class called MyTable, and MyTable has a before_create callback method named my_callback. Now let’s say I want to populate the my_table database table with some data, and do not want my_callback to fire. Here’s how to do it

allow_skipped_callbacks_on MyTable
 
MyTable.without_callback(:my_callback) do
 100.times{ |n| MyTable.create(:name => "my_table_#{n}") }
end

Pretty cool huh? The code for allow_skipped_callbacks_on and without_callback is below:

Code

def allow_skipped_callbacks_on(model)
  model.class_eval do 
    def self.without_callback(method_name, &block)
      raise "#{self.name}##{method_name} doesn't exist, Hosehead" unless method_defined?(method_name)
      original_callback = instance_method(method_name)
      remove_method(method_name)
      define_method(method_name){ true }
      begin
        yield
      ensure
        remove_method(method_name)
        define_method(method_name, original_callback)
      end
    end
  end
end

Action Caching with GET Parameters

Ya ever notice how when you do page or action caching in Rails, it ignores the GET query parameters?

Sup with that?

The REST bible says you should include inputs to algorithmic resources as GET query params. Unfortunately, this means that Rails will ignore the inputs to your algorithmic resources, and you can’t cache them. Not so good if you’ve got a big honkin’ algorithm, for instance Gruff sitting on a URL like this:
/species-discoveries/94/graph.png?years=1750-2000

So what do you do? Well, in the words of Rowdy Roddy Piper , “Either you put on these glasses, or start eatin’ that trash can!”1.

While I couldn’t figure out how to modify page caching, and perhaps there isn’t a way I did figure out how to modify action caching to include GET params. It was, in fact, quite trivial. All you need to do is monkey patch ActionController::Caching::Actions::ActionCachePath.initialize. You can simply stick the code at the bottom of this post in your lib, and then require ‘action_cache‘ in your environment.

I have NO idea if there’s a good reason why Rails doesn’t cache get parameters. Perhaps there is, but for now, this is the best I’ve got. I’m sure this could be tweaked further. For instance, you might be able to subclass ActionCachePath with one specific for your algorithmic resources — in the example above, I could write a custom ActionCachePath that only allowed the years parameter through, because that’s the only one we care about.

module ActionController
  module Caching
    module Actions
      class ActionCachePath      
        def initialize(controller, options = {})
          @extension = extract_extension(controller.request.path)
          # path = controller.url_for(options).split('://').last
          host = controller.url_for(options).split('://').last.split('/').first
          path = host + controller.request.path + controller.request.query_string # Booya!
          normalize!(path)
          add_extension!(path, @extension)
          @path = URI.unescape(path)
        end
      end
    end
  end
end
  1. http://www.youtube.com/watch?v=wqKFadyJxwg []