Чи є якась функція Rails для перевірки наявності часткової?


98

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

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

1
Відповідь, яку використовує rescue, ризикована. Я б переглянув інші рішення, перш ніж використовувати його.
Грант Хатчінс

Відповіді:


98

В даний час я використовую наступне у своїх проектах Rails 3 / 3.1:

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

Перевага перед іншими рішеннями, які я бачив, полягає в тому, що це буде виглядати у всіх контурах огляду, а не лише у вашому корені рейки. Це важливо для мене, оскільки у мене багато рейок двигунів.

Це також працює в Rails 4.


9
lookup_context.exists? ('posts / find') не працював для мене. Натомість я використовував lookup_context.exists? (Ім'я, префікс, частковий) або lookup_content.exists? ("Знайти", "повідомлення", правда) у цьому прикладі.
Дженн

2
Це поточний (рейки> = 3.2) спосіб перевірити шаблони (джерело apidock )
maček

1
Якщо частка знаходиться в тій же папці, що і шаблон поточного перегляду, ви можете використовувати lookup_context.exists?("find", lookup_context.prefixes, true). Таким чином, вам не потрібно жорстко кодувати каталог перегляду у виклик. Зауважте, це стосується партизалів. Для неупереджених опустіть останні аргументи (або використовуйте помилкові замість істинного)
Натан Уоллес

71

Я теж боровся з цим. Це метод, який я закінчив, використовуючи:

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

В основному, якщо часткової не існує, нічого не робіть. Чи хотіли ви надрукувати щось, якщо частка відсутня?

Правка 1: О, я не можу зрозуміти читання. Ви сказали, що хочете зробити щось інше. У такому випадку, як щодо цього?

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

або

<%= 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")) %>

6
Моє питання полягає в тому , що я не хочу використовувати виключення , щоб зробити управління потоком, який є анти-модель: stackoverflow.com/questions/1546514 / ...
Daniel Cukier

6
Виняток - тип управління потоком, який використовується для обробки речей, які відбуваються поза звичайною роботою програми. Якщо динамічна частка повинна бути там, але щось піде не так, і в кінцевому підсумку це не є, то це виправдане використання виключення (ІМО, звичайно, правильне використання винятків - це сама свята війна). Я б сказав, що ваша альтернатива полягає в тому, щоб перевірити файлову систему на наявність чи не існує фактичного файлу. Я оновлю свою відповідь цим кодом.
Джефф

3
Мені подобається рішення, проте воно проковтує будь-який виняток, кинутий частково. IMHO це ускладнює відстеження помилок.
Метт

5
Якщо у вас є інший тип винятку, rescue nilі ... rescue ...методи його приховатимуть. Це призводить до помилок, які важко налагодити.
nicholaides

8
Мені дуже не подобається це рішення. рятувати дорого, а File.exists? припускає, що часткова може бути лише в одному місці. @ Я вважаю, рішення Рейна з використанням lookup_context - це шлях.
Берт Ґетхельс

52

Зсередини представлення "template_exists"? працює, але конвенція виклику не працює з єдиним рядком часткового імені, замість цього потрібен template_exists? (ім'я, префікс, частковий)

Щоб перевірити частковість шляху: app / views / posts / _form.html.slim

Використання:

lookup_context.template_exists?("form", "posts", true)

На Rails 3.0.10 я виявив, що якщо у мене є альтернативне розширення, наприклад, app / views / posts / _foo.txt.erb, мені потрібно було додати це до аргументу як: template_exists? ("Foo.txt", "posts" , правда)
Габе Мартін-Демпесі

Це застаріло в рейках 3.2.
12:45

Схоже, він не делегований у Rails 3.2.x, проте другий аргумент - це масив префіксів. Далі він існує на поточному контролері.
Брендан

2
Ви можете використовувати lookup_context.prefixes як другий аргумент: lookup_context.template_exists? ("Форма", lookup_context.prefixes, правда)
lion.vollnhals

Це краща відповідь щодо доступу до цієї інформації з рівня перегляду.
Брендон Муїр

30

У Rails 3.2.13, якщо ви перебуваєте в контролері, ви можете використовувати це:

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

template_exists?делеговано lookupcontext, як ви бачите вAbstractController::ViewPaths

_prefixes дає контекст ланцюга успадкування контролера.

true тому що ви шукаєте часткове (ви можете опустити цей аргумент, якщо хочете звичайного шаблону).

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


Отримано. Більш сучасні та кращі пояснення параметрів.
jacobsimeon

4
З точки зору (наприклад, макета) це працює: lookup_context.template_exists?("navbar", controller._prefixes, :partial) . Це підказує мені, чи має поточний шаблон, що відображає цей макет, вказаний "навбар" частковий, і якщо так, я можу його надати. Я проходжу :partialлише для того, щоб бути ясним щодо того, що це булевий - :partialправда. Дякую за _prefixesтрохи, @Flackou!
pdobb

Замініть _prefixesна, nilякщо ви викликаєте частку, яка знаходиться в іншому батьківському каталозі.
бен

8

Я знаю, що на це відповіли і мені мільйон років, але ось, як я закінчила це, щоб виправити це для мене ...

Рейки 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}" %>

сподівання, що допомагає. (не пробували в рейках3)


1
Це не спрацює, якщо ви хочете надати резервний запас. Він також не враховує локальні змінні.
phillyslick

Це саме те, що я шукав. Дуже чиста відповідь.
Сонячний

1
@BenPolinsky Я думаю, ви можете використовувати def render_if_exists(*args); render(*args) if ...для цього
сайти

6

Я багато разів використовував цю парадигму з великим успіхом:

<%=
  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 %>або якусь похідну, часткова може існувати, але створити виняток, який буде мовчки з'їдений і стане джерелом болю для налагодження.


4

Як щодо власного помічника:

def render_if_exists(path, *args)
  render path, *args
rescue ActionView::MissingTemplate
  nil
end
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.