riot.projects

riot.projects is the tumblelog of Aubrey Holland. You can find me on twitter at @riotpolice

Ruby 1.8 funkyness with Class.new and inherited

I just found a bug in Sinatra where this code will fail with the error “can’t dup NilClass”:

Class.new(Sinatra::Base) do
  get('/') { 'abc' }
end

Sinatra uses the ‘inherited’ method to initialize a number of class variables in new subclasses of Sinatra::Base when they are defined. For normal subclassing, this works great because ‘inherited’ is called before the contents of the class are evaluated. When using Class.new, however, it is called after evaluating the class contents, which means that Sinatra will not have had a chance to set up the variables when ‘get’ is called in this example. Apparently Ruby 1.9 has fixed this issue, but we’re still stuck with it in 1.8.

Run this code and you’ll get:

Inherited!
Some method!
Some method!
Inherited!
class Base
  def self.some_method
    puts 'Some method!'
  end

  def self.inherited(subclass)
    puts 'Inherited!'
  end
end

class Sub < Base some_method end
Class.new(Base) do some_method end

It would be lovely if quick fix for doing this in Sinatra was to call ‘reset!’ as the first line of the class definition, but unfortunately because inherited is called after the class contents are evaluated all of your routes will be wiped out.

Class.new(Sinatra::Base) do
  reset!
  get('/') { 'abc' }
end
Comments (View)
blog comments powered by Disqus