Rails magic is a widespread term among developers working with Ruby on Rails application. Is it an overstatement? Well, it depends. During day-to-day work, there isn’t usually enough time to study deeply Ruby on Rail source code. Even though it is an effective way to develop programming skills and understand the framework in-depth, sooner or later everybody finds mysterious places in a codebase that may cause frustration. I bet that you have already seen
if Rails.env.production? condition several times. Have you ever thought where it comes from? Today I learned that
ActiveSupport::StringInquirer class is a part of Ruby on Rails codebase and adds some magic powers to
String objects 🙂
Wrapping a string in this class gives you a prettier way to test for equality. In Rails codebase, we can see that the
env method uses the class:
@_env ||= ActiveSupport::StringInquirer.new(ENV["RAILS_ENV"].presence || ENV["RACK_ENV"].presence || "development")
endSurprisingly, the method does not return
String object, but
 pry(main)> Rails.env
 pry(main)> Rails.env.class
=> ActiveSupport::StringInquirerSo now it’s time to go even deeper and check the source code of
class StringInquirer < String
def respond_to_missing?(method_name, include_private = false)
(method_name[-1] == "?") || super
def method_missing(method_name, *arguments)
if method_name[-1] == "?"
self == method_name[0..-2]
endLet’s break its magic down using the
"development", but its class isn’t
ActiveSupport::StringInquirer inherits from
String, so all its methods are available (
"Development" 🙂 ).
development? method is not defined in
String class nor
method_missing one is executed as a fallback.
method_missing checks if a method name ends with
- In our case it ends with
self == method_name[0..-2] comparison is made.
"development" string is equal to
"development?[0..-2]", so the method returns
Even more magic 🙂
which wraps the current string in the
When to use First of all, you need to be brave enough to consciously use Rails magic 😉 Being serious, whenever you do strings comparison the class can be used instead. Please do some benchmarking first, though.
 pry(main)> name = "Johny"
 pry(main)> name.Johny?
NoMethodError: undefined method `Johny?' for "Johny":String
 pry(main)> name.inquiry.Johny?
 pry(main)> name.inquiry.class
 pry(main)> ActiveSupport::StringInquirer.new("Johny").Johny?
Summary Whenever you find a fragment of code you do not understand fully, it’s a good idea to go deeper and try to understand it fully. Thanks to such an approach I explored and understood new fragments of Ruby on Rails source code. As a result, Rails is a bit less magical to me 🧙.