Вопрос

У меня есть довольно старая система шаблонов, написанная поверх ERB.Он опирается на шаблоны ERB, хранящиеся в базе данных.Они считываются и визуализируются.Когда я хочу передать данные из одного шаблона в другой, я использую параметр:locals для метода Rails render.Для установки переменных по умолчанию для этих переменных в некоторых шаблонах я использую определенный?метод, который просто сообщает мне, была ли определена локальная переменная, и если нет, я инициализирую ее значением по умолчанию следующим образом:

unless defined?(perex)
  perex = true
end

Я обновляю приложение до последней версии Rails и вижу какое-то странное поведение.В принципе, это иногда работает (иногда perex не определено), а иногда и нет (perex определен и имеет значение nil).Это происходит без каких-либо изменений.

У меня есть два вопроса:Есть ли какой-нибудь лучший способ, кроме использования defined?что доказывает свою ненадежность (было надежным в течение нескольких лет на top Rails 1.6)?Такой способ не должен приводить к тому, что я буду переписывать все шаблоны.Я просматривал документы Ruby и не смог найти ничего о defined?способ.Было ли это устаревшим, или я просто слепой?

Редактировать: Фактическая проблема была вызвана тем, что, по-видимому, является ошибкой Ruby / eRB.Иногда если не утверждение могло бы сработать, но иногда нет.Самое странное, что даже если вторая строка была выполнена перекс по-прежнему оставался нулем для остального мира.Удаление определено?решил это.

Это было полезно?

Решение

Первый:на самом деле, defined? является оператором.

Второй:если я правильно понимаю ваш вопрос, способ сделать это - использовать эту идиому Ruby:

perex ||= true

Это присвоит true значение perex если это не определено или nil.Это не совсем то, что делает ваш пример, поскольку ваш не оценивает присваивание, когда значение равно nil, но если вы полагаетесь на это, то, на мой взгляд, не видя этого, вы не пишете понятный код.

Редактировать:Как отметил Хонза, приведенное выше утверждение заменит значение perex когда это false.Тогда я предлагаю переписать минимальное количество строк следующим образом:

perex ||= perex.nil?  # Assign true only when perex is undefined or nil

Другие советы

Самый безопасный способ проверить, определен ли локальный файл в шаблоне Rails, - это:

local_assigns[:perex]

Это задокументировано в Rails API вместе с объяснением, что defined? не может быть использован из-за ограничения реализации.

Согласно ответу мислава, я искал эту документацию в Rails API и нашел ее в Класс ActionView::База (под заголовком "Передача локальных переменных во вложенные шаблоны").Однако вряд ли стоило искать, поскольку в нем говорилось едва ли больше, чем в миславе.За исключением того, что он рекомендует этот шаблон:

if local_assigns.has_key? :perex

Принимая во внимание оригинальный ответ мислава и Разработка Кенба, Я думаю, что следующий подход является абсолютно лучшим (хотя я открыт для мнений).Он использует Ruby's Хэш#выборка метод резервного копирования альтернативного значения, если ключ не существует в исходном хэше.

perex = local_assigns.fetch(:perex, true)

Это даже лучше, чем ||= метод, который предложит большинство пользователей, поскольку иногда вам захочется разрешить false ценности.Например, следующий код будет никогда разрешить false значение, которое должно быть передано в:

perex = local_assigns[:perex] || true
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top