af83

Ruby 2.0: respond_to?

It's really quite rare that a new realease of Ruby changes a behavior, and by "rare", I mean really rare. But, there's one change in Ruby 2.0 that is definitely breaking some code.

Let's have a look at this example:

class Lolcat

  protected

  def serious?
    false
  end

  private

  def ohai
    puts "ohai"
  end
end

Lolcat.new.tap do |lolcat|
  puts lolcat.respond_to?(:serious?)
  puts lolcat.respond_to?(:ohai)
end

Running this code with Ruby 1.9.3:

ruby lolcat.rb
# true
# false

Running this code with Ruby 2.0:

ruby lolcat.rb
# false
# false

What is happening here ?

From Ruby 2.0, respond_to? behavior changed to check only public methods. Before that, public and protected methods were checked.

This change makes actually perfect sense, but it can break some code when running 2.0:

respond_to?

respond_to? takes a second argument to check against all methods (protected and private). By default, this second argument is false.

Lolcat.new.tap do |lolcat|
  puts lolcat.respond_to?(:serious?, true)
  puts lolcat.respond_to?(:ohai, true)
end

Running this code with Ruby 1.9.3:

ruby lolcat.rb
# true
# true

Running this code with Ruby 2.0:

ruby lolcat.rb
# true
# true

The other way of making this code run as expected would be to declare this method as public. But, sometimes, you do not want a particular method to be public, and yet, you want to call respond_to, like for instance in an ActiveRecord callback.

blog comments powered by Disqus