Similar to the ArrayInquirer class, which tests if an array contains a value, the ActiveSupport::StringInquirer
class provides a nice way to compare two strings. Use it when you have an internal method that returns a string, and the consumer of that method needs to compare it with another string.
def env
ActiveSupport::StringInquirer.new('production')
end
env.production? # true
env.local? # false
Behind the scenes, implementing this needs some metaprogramming, as Rails can't know the value of the string in advance.
def method_missing(method_name, *arguments)
if method_name.end_with?("?")
self == method_name[0..-2]
else
super
end
end
The Ruby interpreter calls the method_missing
method when it can't find the invoked method. If the method name ends with a ?
, it compares the original string with the method's name minus the ?
.
The 'inquiry' Shortcut
Rails further simplifies it by adding the inquiry
extension method on String
which returns an instance of the StringInquirer
class.
def env
'production'.inquiry
end
env.production? # true
env.local? # false
Here's the implementation of the String#inquiry
method. It instantiates the StringInquirer
class, passing self
which is the string itself.
# activesupport/lib/active_support/core_ext/string/inquiry.rb
class String
def inquiry
ActiveSupport::StringInquirer.new(self)
end
end
I love how much Rails cares about beautiful code and goes above and beyond to simplify its external API.
Hope you learned something new. Let me know if you liked this post or have any feedback. I look forward to hearing from you.