Определены? метода в Ruby and Rails
У меня есть довольно старая система шаблонов, написанная поверх ERB. Он опирается на шаблоны ERB, хранящиеся в базе данных. Те читаются и визуализируются. Когда я хочу передавать данные из одного шаблона в другой, я использую параметр locals для метода рендеринга Rails. Для установки переменных по умолчанию этих переменных в некоторых шаблонах я использую определенные? метод, который просто говорит мне, была ли определена локальная переменная, и если я не инициализирую ее значением по умолчанию следующим образом:
unless defined?(perex)
perex = true
end
Я обновляю приложение до последних Rails, и я вижу какое-то странное поведение. В основном это иногда работает (иногда perex undefined), а иногда нет (perex определяется и устанавливается на nil). Это происходит без изменений.
У меня есть два вопроса:
Есть ли лучший способ, кроме использования определенных? которая оказалась ненадежной (была надежной в течение нескольких лет на вершине Rails 1.6)? Такой способ не должен приводить к тому, что я переписываю все шаблоны.
Я проходил через Ruby docs и не мог найти что-либо о определенных? метод. Было ли это устаревшим или я просто слепой?
Изменить: фактическая проблема была вызвана тем, что кажется ошибкой Ruby/eRB. Иногда инструкция if будет работать, но иногда нет. Странно то, что даже если бы вторая линия была исполнена, perex stil остался ноль остальному миру. Удаление определено? разрешил это.
Ответы
Ответ 1
Во-первых: на самом деле defined?
является оператором.
Во-вторых: если я правильно понимаю ваш вопрос, способ сделать это с помощью этой идиомы Ruby:
perex ||= true
Это будет присвоено значение true для perex
, если оно undefined или nil
. Это не совсем то, что делает ваш пример, так как ваш не оценивает присвоение, когда значение nil
, но если вы полагаетесь на это, то, на мой взгляд, не видя его, вы не пишете чистый код.
Изменить: Как отметил Хонза, приведенное выше выражение заменит значение perex
, когда оно false
. Затем я предлагаю следующее переписать минимальное количество строк:
perex ||= perex.nil? # Assign true only when perex is undefined or nil
Ответ 2
Самый безопасный способ тестирования, если локаль определяется в шаблоне Rails:
local_assigns[:perex]
Это описано в Rails API вместе с объяснением того, что defined?
не может использоваться из-за ограничения реализации.
Ответ 3
В ответ на mislav я пошел искать эту документацию в Rails API и нашел ее в Class ActionView:: Base (под заголовком "Передача локальных переменных в под шаблоны" ). Это вряд ли стоило поиска, хотя, поскольку он едва сказал что-то большее, чем сделал миц. За исключением того, что он рекомендует этот шаблон:
if local_assigns.has_key? :perex
Ответ 4
Принимая во внимание g mislav оригинальный ответ и разработку KenB, я считаю, что следующий абсолютный лучший подход (хотя я открыт для мнения). Он использует метод Ruby Hash # fetch для резервного копирования на альтернативное значение, если ключ не существует в исходном хеше.
perex = local_assigns.fetch(:perex, true)
Это даже лучше, чем метод ||=
, который будет предлагать большинство пользователей, поскольку иногда вы хотите разрешить значения false
. Например, следующий код никогда не позволит передать значение false
:
perex = local_assigns[:perex] || true