Как избежать ноля в представлениях Rails - PullRequest
5 голосов
/ 21 августа 2010

Я уверен, что об этом уже спрашивали, но я не могу найти ответ.

У меня есть модель Project, которая имеет отношение belongs_to к моей модели Client. У клиента есть имя, но у проекта не обязательно есть клиент.

На мой взгляд, у меня есть такой код:

<%=h project.client && project.client.name %>

потому что, если у проекта нет клиента, то попытка доступа к project.client.name вызывает NoMethodError (nil не имеет метода с именем name).

Вопрос в том, допустимо ли иметь такую ​​проверку на ноль в представлении, или я должен искать другой способ обойти это?

Ответы [ 6 ]

10 голосов
/ 21 августа 2010

Просто используйте

project.client.try(:name)
3 голосов
/ 21 августа 2010

Я сталкиваюсь с этим все время, и да, это раздражает.Даже если предполагается, что никогда не будет нулевых, грязные данные, которые я унаследовал, иногда вызывают их.

Ваше решение - один из способов обработки.Вы также можете добавить метод к Project с именем client_name, который отображает имя клиента, если оно существует, но затем вы связываете модели вместе, как рекомендуют некоторые люди.вспомогательный метод для этого, но вы можете в конечном итоге написать много из них.:)

Как упомянуто Skilldrick ниже, это также полезно для добавления строки по умолчанию:

def client_name
  client ? client.name : "no client"
end
3 голосов
/ 21 августа 2010

Я думаю, что это вполне приемлемо - это логика представления, вы более или менее решаете, показывать или нет части вашего представления, основываясь на том, есть ли данные.

2 голосов
/ 08 января 2014

Вы можете использовать delegate в вашем Project классе, так что вы будете соблюдать Закон Деметры , который говорит, что вы должны "разговаривать только со своими непосредственными друзьями".».

project.rb

class Project
  delegate :name, to: :client, prefix: true, allow_nil: true    
end

Таким образом, объект проекта будет знать, где спрашивать об имени клиента:

#You can now call
project.client_name

Подробнее о delegate в Документация по Rails.

0 голосов
/ 22 августа 2010

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

Существует как минимум пара сценариев.Допустим, у вас есть действие show, которое зависит от переменной экземпляра.Я бы сказал, что если запись не найдена, контроллер не должен отображать HTML, путем перенаправления или чего-то еще.Если у вас есть цикл в представлении для массива, используйте @array.each do |a| end, чтобы он не оценивал, является ли массив пустым.Если вы действительно хотите приложение по умолчанию в представлении, попробуйте загрузить его из файла конфигурации, например, @page_title || #{@APP_CONFIG['page_title']} (см. Railscasts # 85 ).Помните, что вы можете изменить эти строки позже, например, переводя пользовательский интерфейс.

Это пара сценариев, в которых можно избежать проверки присутствия и использования try.Я постараюсь избежать их, если это возможно.Если вы не можете избежать их, я бы поместил условные проверки в помощник вида и добавил бы вспомогательный тестовый модуль для проверки (и документирования) обоих путей кода.

0 голосов
/ 21 августа 2010

мое хакерское решение - сдать блок и спасти ошибку.Многие скажут, что использование спасения - это очень плохая логика.Просто не используйте это там, где вам действительно нужно знать, когда что-то равно нулю и не должно быть.*

<%= none_on_fail { project.client.name }  %>

Тогда методы могут быть объединены настолько глубоко, насколько это необходимо, и их можно использовать в любом методе, НО они будут покрывать другие потенциальные проблемы с моделями / отношениями / методами, если они существуют.Я бы приравнял это с тем, чтобы вытащить осколок огнеметом.Очень эффективно с болезненными последствиями при неправильном использовании.

...