определены? метод в Ruby и Rails - PullRequest
27 голосов
/ 27 октября 2008

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

unless defined?(perex)
  perex = true
end

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

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

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

Ответы [ 4 ]

38 голосов
/ 27 октября 2008

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

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

perex ||= true

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

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

perex ||= perex.nil?  # Assign true only when perex is undefined or nil
24 голосов
/ 11 марта 2009

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

local_assigns[:perex]

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

12 голосов
/ 17 декабря 2009

Согласно ответу Мислава, я искал эту документацию в Rails API и нашел ее в Class ActionView :: Base (под заголовком «Передача локальных переменных в под-шаблоны»). Однако вряд ли это стоило поисков, поскольку в нем почти ничего не говорилось, чем сделал Мислав. За исключением того, что он рекомендует этот шаблон:

if local_assigns.has_key? :perex
6 голосов
/ 23 июля 2012

Принимая во внимание первоначальный ответ Мислава и Уточнение КенБ , я думаю, что следующий является абсолютно лучшим подходом (хотя я открыт для мнения). Он использует метод Ruby Hash # fetch для возврата к альтернативному значению, если ключ не существует в исходном хеше.

perex = local_assigns.fetch(:perex, true)

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

perex = local_assigns[:perex] || true
...