Есть ли в Rails функция для проверки существования партиала?

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

    <% begin %>
      <%= render :partial => "#{dynamic_partial}" %>
    <% rescue ActionView::MissingTemplate %>
      Can't show this data!
    <% end %>

person Daniel Cukier    schedule 24.08.2010    source источник
comment
Ответ, в котором используется rescue, рискован. Я бы посмотрел на другие решения, прежде чем использовать его.   -  person Grant Hutchins    schedule 11.01.2012


Ответы (7)


В настоящее время я использую в своих проектах на Rails 3 / 3.1 следующее:

lookup_context.find_all('posts/_form').any?

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

Это также работает в Rails 4.

person Rein    schedule 18.11.2011
comment
lookup_context.exists? ('posts / find') у меня не сработало. Вместо этого я использовал lookup_context.exists? (Имя, префикс, частичное) или lookup_content.exists? ('Find', 'posts', true) в этом примере. - person Jenn; 12.06.2012
comment
Это текущий (rails ›= 3.2) способ проверки шаблонов (источник apidock) - person maček; 12.12.2012
comment
Если партиал находится в той же папке, что и текущий шаблон представления, вы можете использовать lookup_context.exists?("find", lookup_context.prefixes, true). Таким образом, вам не нужно жестко закодировать каталог просмотра в вызове. Обратите внимание, это для частичных файлов. Для non-partials опустите последний аргумент (или используйте false вместо true) - person Nathan Wallace; 12.06.2017

Я тоже боролся с этим. Это метод, который я в итоге использовал:

<%= render :partial => "#{dynamic_partial}" rescue nil %>

В принципе, если частичное не существует, ничего не делайте. Вы хотели что-то напечатать, если часть отсутствует?

Редактировать 1: Я не понимаю прочитанное. Вы сказали, что хотите отрендерить что-то еще. В таком случае, как насчет этого?

<%= render :partial => "#{dynamic_partial}" rescue render :partial => 'partial_that_actually_exists' %>

or

<%= render :partial => "#{dynamic_partial}" rescue "Can't show this data!" %>

Изменить 2:

Альтернатива: проверка существования частичного файла:

<%= render :partial => "#{dynamic_partial}" if File.exists?(Rails.root.join("app", "views", params[:controller], "_#{dynamic_partial}.html.erb")) %>
person Jeff    schedule 24.08.2010
comment
Мой вопрос в том, что я не хочу использовать исключения для управления потоком, что является анти-шаблоном: stackoverflow.com/questions/1546514/ - person Daniel Cukier; 26.08.2010
comment
Исключение - это тип управления потоком, используемый для обработки вещей, которые происходят за пределами нормальной работы программы. Если предполагается, что динамический партиал присутствует, но что-то идет не так, и его там нет, то это разумное использование исключения (IMO, конечно - правильное использование исключений - это сама священная война). Я бы сказал, что ваша альтернатива - проверить файловую систему, существует ли фактический файл. Я обновлю свой ответ этим кодом. - person Jeff; 27.08.2010
comment
Мне нравится решение, тем не менее, оно проглатывает любые исключения, возникающие в партиале. ИМХО, это затрудняет отслеживание ошибок. - person Matt; 27.08.2011
comment
Если у вас есть другой тип исключения, методы rescue nil и ... rescue ... скроют его. Это приводит к ошибкам, которые трудно отладить. - person nicholaides; 23.12.2011
comment
Мне очень не нравится это решение. спасение дорого, а File.exists? предполагает, что партиал может находиться только в одном месте. Я считаю, что решение @Rein с использованием lookup_context - это правильный путь. - person Bert Goethals; 14.02.2012
comment
Да, LookupContext следует использовать в Rails 3. Имейте в виду, что этот вопрос из эпохи 2.3.x. - person Jeff; 14.02.2012

Изнутри представления template_exists? работает, но соглашение о вызовах не работает с одной строкой частичного имени, вместо этого используется template_exists? (имя, префикс, частичное)

Чтобы проверить частичный путь по пути: app / views / posts / _form.html.slim

Использовать:

lookup_context.template_exists?("form", "posts", true)
person Luke Imhoff    schedule 26.08.2011
comment
В Rails 3.0.10 я обнаружил, что если у меня есть альтернативное расширение, например app / views / posts / _foo.txt.erb, мне нужно добавить его к аргументу как: template_exists? (Foo.txt, posts, true) - person Gabe Martin-Dempesy; 28.10.2011
comment
Это устарело в рельсах 3.2. - person maček; 12.12.2012
comment
Похоже, что в Rails 3.2.x он не делегирован, однако второй аргумент - это массив префиксов. Кроме того, он существует на текущем контроллере. - person Brendan; 26.12.2012
comment
Вы можете использовать lookup_context.prefixes в качестве второго аргумента: lookup_context.template_exists? (Form, lookup_context.prefixes, true) - person lion.vollnhals; 11.06.2014
comment
Это лучший ответ с точки зрения доступа к этой информации из уровня представления. - person Brendon Muir; 14.09.2016

В Rails 3.2.13, если вы находитесь в контроллере, вы можете использовать это:

template_exists?("#{dynamic_partial}", _prefixes, true)

template_exists? делегируется lookupcontext, как вы можете видеть в _ 4_

_prefixes дает контекст цепочки наследования контроллера.

true, потому что вы ищете частичное (вы можете опустить этот аргумент, если вам нужен обычный шаблон).

http://api.rubyonrails.org/classes/ActionView/LookupContext/ViewPaths.html#method-i-template_exists-3F

person Flackou    schedule 08.06.2013
comment
Проголосовали. Более актуальное и лучшее объяснение параметров. - person jacobsimeon; 15.10.2013
comment
С точки зрения (например, макета) это работает: lookup_context.template_exists?("navbar", controller._prefixes, :partial). Это говорит мне, имеет ли текущий шаблон, отображающий этот макет, указанную часть навигационной панели, и если да, я могу его отобразить. Я передаю :partial только для того, чтобы четко указать, что это за логическое значение - :partial истинно. Спасибо за бит _prefixes, @Flackou! - person pdobb; 21.12.2013
comment
Замените _prefixes на nil, если вы вызываете партиал, находящийся в другом родительском каталоге. - person ben; 01.05.2015

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

Рельсы 4.2

Сначала я помещаю это в свой application_helper.rb

  def render_if_exists(path_to_partial)
    render path_to_partial if lookup_context.find_all(path_to_partial,[],true).any?
  end

и теперь вместо звонка

<%= render "#{dynamic_path}" if lookup_context.find_all("#{dynamic_path}",[],true).any? %>

я просто звоню <%= render_if_exists "#{dynamic_path}" %>

надеюсь, это поможет. (в rails3 не пробовал)

person afxjzs    schedule 05.08.2015
comment
Это не сработает, если вы хотите предоставить запасной вариант. Он также не принимает во внимание локальные переменные. - person phillyslick; 19.10.2015
comment
Это именно то, что я искал. Очень чистый ответ. - person Sunny; 03.03.2016
comment
@BenPolinsky Я полагаю, вы можете использовать def render_if_exists(*args); render(*args) if ... для этого - person sites; 17.04.2017

Я много раз использовал эту парадигму с большим успехом:

<%=
  begin
    render partial: "#{dynamic_partial}"
  rescue ActionView::MissingTemplate
    # handle the specific case of the partial being missing
  rescue
    # handle any other exception raised while rendering the partial
  end
%>

Преимущество приведенного выше кода заключается в том, что мы можем обрабатывать отдельные случаи:

  • Частичное действительно отсутствует
  • Партиал существует, но по какой-то причине выдает ошибку

Если мы просто используем код <%= render :partial => "#{dynamic_partial}" rescue nil %> или какой-то производный, партиал может существовать, но вызывать исключение, которое будет незаметно съедено и станет источником боли для отладки.

person br3nt    schedule 16.02.2016

А как насчет собственного помощника:

def render_if_exists(path, *args)
  render path, *args
rescue ActionView::MissingTemplate
  nil
end
person Andrey    schedule 07.07.2016