Все говорят о Rails одно и то же: «Это волшебство».
Долгое время я тоже так думал. Все просто работало, и я был очень счастливым разработчиком.
Со временем я понял, что большая часть того, что я считаю магией в Rails, - это всего лишь несколько умных людей, которые вносят несколько аккуратных, умных и аккуратных хаков в репозиторий Rails. Шутки в сторону! Это все код. Вот и все.
Здесь я пытаюсь раскрыть магию в Rails и посмотреть, как часто используемые функции Rails работают под капотом.
Давайте начнем.
Если вы работали над Rails, я уверен, что вы встречали такие фрагменты кода, как Rails.env.development?
или Rails.env.production?
.
[1] pry(main)> Rails.env => "development" [2] pry(main)> Rails.env.development? => true
Все хорошо. Но здесь происходит что-то странное.
Rails.env
возвращает development
(строку), но если вы попытаетесь выполнить ‘development’.development?
на консоли rails, на самом деле вы получите NoMethodError
.
[1] pry(main)> "development".development? NoMethodError: undefined method `development?' for "development":String
Итак, как все это работает?
Как и большинство функций Rails, это тоже волшебство. Но давайте попробуем понять, как работает эта магия, покопавшись в коде Rails, не так ли?
Нашей первой точкой проверки, очевидно, будет метод env
, определенный в модуле Rails
. Если вы посмотрите Код Rails, вы увидите определение метода, подобное этому.
Эта функция возвращает значение переменных среды ENV[“RAILS_ENV”]
или ENV[“RACK_ENV”]
или “development”
Но вот что интересно: эта функция возвращает не объект String, а объект ActiveSupport::StringInquirer
.
Итак, давайте погрузимся в класс StringInquirer
и посмотрим, что здесь происходит.
Ага! Как и ожидалось, здесь происходит волшебство. Точнее, внутри функции method_missing
.
Давайте сделаем шаг назад и проанализируем цепочку событий, которые происходят, когда мы выполняем Rails.env.development
Rails.env
возвращает“development”
, но это не строковый объект, а объектActiveSupport::StringInquirer
.- Класс
ActiveSupport::StringInquirer
наследует классString
, поэтому все функции, определенные вString
, также будут работать с этим объектом. - Поскольку для класса
ActiveSupport::StringInquirer
не определен методdevelopment?
(или для классаString
), он попадает вmethod_missing
. - Здесь происходит волшебство. Здесь он проверяет, заканчивается ли вызываемая функция (в нашем случае
development?
) на?
. (Строка 9) - Если это так, он проверяет, равна ли строка (в нашем случае
development
) методу, вызванному для этого объекта, без?
в конце. (Строка 10)
И вуаля! Внезапно все сводится к простому сравнению строк.
Если строки совпадают, возвращается истина.
А волшебство вот в чем:
На самом деле это не
String
, это объектActiveSupport::StringInquirer
Практические примеры использования ActiveSupport::StringInquirer
Если ваша строка является объектом этого класса, проверка равенства будет намного проще и чище. Фактически, вы вызываете метод inquiry
для любой строки в Rails, и он возвращает объект этого класса.
[9] pry(main)> word = "America".inquiry => "America" [10] pry(main)> word.America? => true [11] pry(main)> word.Russia? => false
Теперь вы можете попрощаться с уродливыми сравнениями строк в вашем проекте :)