Breakage in Leopard – RMagick fails to find libdpstk.1.dylib

Some small breakage in Leopard – it seems a couple of parts of X11 have been removed. Starting my rails setup, which has GraphicsMagick installed (read here for how), results in this:

dyld: NSLinkModule() errordyld: Library not loaded: /usr/X11R6/lib/libdpstk.1.dylib  Referenced from: /usr/local/lib/ruby/gems/1.8/gems/rmagick-1.15.9/lib/RMagick.bundle  Reason: image not foundTrace/BPT trap

Those dylib files do not exist any more. But… I have a backup (I hope you do). I ended up doing this:

$ cd /Volumes/BackupDisk/usr/X11R6/lib$ sudo cp libdps*1.0* /usr/X11R6/lib/$ sudo ln -s /usr/X11R6/lib/libdpstk.1.0.dylib /usr/X11R6/lib/libdpstk.1.dylib$ sudo ln -s /usr/X11R6/lib/libdps.1.0.dylib /usr/X11R6/lib/libdps.1.dylib

All fixed.Without a backup you are going to need to find those two files from somewhere. I’m not sure I can legally post them here, but email me if you are stuck.

Exception notifier does not work with Ruby 1.8.6p111

Not only does exception notifier not work, you probably don’t know that it doesn’t work either. All your code has just become super-exception-free all of a sudden.Ah, wishful thinking.If you have installed Ruby 1.8.6p111 then you will want to take note of the comments here.

Just modify the file vendor/plugins/exception_notification/views/_environment.rhtml to say:* <%= "%-*s: %s" % [max.length, key, @request.env[key].to_s.strip] %>instead of* <%= "%*-s: %s" % [max.length, key, @request.env[key].to_s.strip] %>

Rails: wrapping content from a helper

The form_tag method in ActionView uses a nice trick to wrap a block of content in form tags, and you can wrap content the same way yourself.

You want to write something like:

<% yellow_boxed do %>some text and html and stuffit's probably only worth doing it this wayif this bit is longer than a line or two<% end %>

This reads in a very natural way. To do this, I have a helper method called yellow_boxed:

def yellow_boxed(&block)    concat(render(:partial=>"yellow_boxtop"), block.binding)    content = capture(&block)    concat(content, block.binding)    concat(render(:partial=>"yellow_boxbottom"), block.binding)  end

This technique can be used in any situation where it is logical to wrap content.

Note that I render a partial for the top and the bottom of my yellow box. The partials just contain table, tr and td tags and so on, but I wanted to keep the html strings out of my helper. But for short lengths of html it’s not a problem, you can put text strings there instead of the much more expensive calls to render.

Why Ruby is not my favourite programming language

Actually it is my favourite. But the title comes from this article (which itself was inspired and copied from the famous paper about pascal by Brian Kernighan).

On with business though – Ruby has some serious wrinkles that produce counter-intuative and plain strange behaviour. One might say that they violate the Principle of Least Surprise. But POLS is somewhat personal – surprising to whom? (just me maybe!)

Surprising result #1

b=1=> 1a if a=bNameError: undefined local variable or method `a' for main:Object        from (irb):2

This is odd indeed. It seems that the Ruby parser thinks that a is a method at the beginning of the line. But when it parses a=b it will know (and remember) that it is a variable. However, when the condition passes and it comes to execute ‘a’, it does not apply its new found knowledge about the nature of a – it still goes for the method. And hence the error.

Surprising result #2

c=1 unless defined? c=> nilc=> nil

This is a bit easier to explain. Once the parser has seen c=1 it enters c in the symbol table, it knows that c exists as a variable. Hence it is defined (as nil). So c=1 is never executed.

Surprising result #3

class A  attr_accessor :a  def b    @a=0    x=a    a=x+1    puts("a is #{a}")    puts("@a is #{@a}")  endend=&gt nilc = A.new=> #<A:0x32fb7c>c.ba is 1@a is 0

No mystery here really – it’s a nice gotcha though – a= does not call self.a=, it just assigns a local variable. It is just a little confusing unless you think carefully.

Surprising result #4

[0.0, 1/0.0].sort=> [0.0, Infinity][0.0, 0/0.0].sortArgumentError: comparison of Float with Float failed

Thanks to Evan Weaver for pointing this out to me. This is due to 0/0.0 returning the value NaN (as opposed to 1/0.0 which returns Infinity). And the comparison with NaN by sort gives the strange error message.

Let me know if you spot any more oddities.

Rails testing – two gotchas

Gotcha 1

Failing tests. We’d like them to pass of course. But there is something strange going on – the error is not a test error, it seems to come from rails itself:

1) Error:test_searcher_email(OrderMailerTest):NoMethodError: You have a nil object when you didn't expect it!You might have expected an instance of Array.The error occurred while evaluating nil.[]    /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.4/lib/active_record/fixtures.rb:498:in `orders'    ./test/unit/order_mailer_test.rb:22:in `test_searcher_email'1 tests, 0 assertions, 0 failures, 1 errors

What does it mean? The clue here is that the error comes from fixtures.rb. The other thing to note is that I have a setup in my test:

def setup    ActionMailer::Base.delivery_method = :test    ActionMailer::Base.perform_deliveries = true    ActionMailer::Base.deliveries = []   ...  end

Which should be fine, but there is this nasty error. Let’s try something in the setup method – we’ll add a call to super there:

def setup    ActionMailer::Base.delivery_method = :test    ActionMailer::Base.perform_deliveries = true    ActionMailer::Base.deliveries = []    ...    super  end

And the result:

Started.Finished in 0.160284 seconds.1 tests, 1 assertions, 0 failures, 0 errors

Great, that’s fixed it. But why? Well it took me a while to find it. Have a look in /usr/local/lib/ruby/gems/1.8/gems/activerecord-1.15.4/lib/active_record/fixtures.rb – there is your culprit at line 554:

alias_method :setup, :setup_with_fixtures

So the rule is, if you override setup you need to call super otherwise you don’t get your fixtures set up properly.

Gotcha 2

Ever tried to test your routes? You should. But if you have routes that depend on what’s in your database you’ve got a problem. Why? Because the routing is initialised before any fixtures are loaded. In fact none of the test related code is loaded at that point. So your tests just won’t work.

I don’t know a good way to fix this. In the end I opted for a fudge at the beginning of routes.rb:

if ENV['RAILS_ENV'] == "test" && Category.count == 0    Category.create!(:name=>"Families and Friends", :alternative_name=>"Family")  end

And I have a fixture that contains the same information. This isn’t really DRY, but I don’t really see a good way to do this. Maybe we could read the fixtures file ourselves and get the data from there.

But at least the tests run ok now.

Rails logging – config.log_level has no effect

Curiously adding config.log_level = :debug to environment.rb appears to have no effect on the logging performed by ActiveRecord. To get to see the detailed logging and benchmarking of your database queries in production mode you need to place this after the Rails::Initializer.run block in environment.rb:

ActiveRecord::Base.logger.level = Logger::DEBUG