Подтвердить что ты не робот

Определены? метода в 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 остался ноль остальному миру. Удаление определено? разрешил это.

4b9b3361

Ответ 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