web-dev-qa-db-fra.com

Existe-t-il une fonction Rails pour vérifier si un partiel existe?

Lorsque je rend un partiel qui n'existe pas, j'obtiens une exception. Je voudrais vérifier si un partiel existe avant de le rendre et au cas où il n'existerait pas, je rendrai autre chose. J'ai fait le code suivant dans mon fichier .erb, mais je pense qu'il devrait y avoir une meilleure façon de le faire:

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

Actuellement, j'utilise ce qui suit dans mes projets Rails 3/3.1:

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

L'avantage par rapport aux autres solutions que j'ai vues est que cela va regarder dans tous les chemins de vue au lieu de juste votre Rails root. Ceci est important pour moi car j'ai beaucoup de Rails moteurs.

Cela fonctionne également dans Rails 4.

97
Rein

Je me débattais aussi avec ça. C'est la méthode que j'ai finalement utilisée:

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

En gros, si le partiel n'existe pas, ne faites rien. Souhaitez-vous toutefois imprimer quelque chose si le partiel est manquant?

Edit 1: Oh, je n'arrive pas à comprendre la lecture. Vous avez dit que vous vouliez rendre quelque chose d'autre. Dans ce cas, qu'en est-il?

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

ou

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

Modifier 2:

Alternative: vérification de l'existence du fichier partiel:

<%= render :partial => "#{dynamic_partial}" if File.exists?(Rails.root.join("app", "views", params[:controller], "_#{dynamic_partial}.html.erb")) %>
69
Jeff

De l'intérieur d'une vue, template_exists? fonctionne, mais la convention d'appel ne fonctionne pas avec la chaîne de nom partielle unique, mais prend plutôt template_exists? (nom, préfixe, partiel)

Pour vérifier le chemin partiel: app/views/posts/_form.html.slim

Utilisation:

lookup_context.template_exists?("form", "posts", true)
52
Luke Imhoff

Dans Rails 3.2.13, si vous êtes dans un contrôleur, vous pouvez utiliser ceci:

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

template_exists? est délégué à lookupcontext, comme vous pouvez le voir dans AbstractController::ViewPaths

_prefixes donne le contexte de la chaîne d'héritage du contrôleur.

true parce que vous recherchez un partiel (vous pouvez omettre cet argument si vous voulez un modèle standard).

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

30
Flackou

Je sais que cela a été répondu et remonte à un million d'années, mais voici comment j'ai fini par résoudre ce problème pour moi ...

Rails 4.2

Tout d'abord, je mets cela dans mon 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

et maintenant au lieu d'appeler

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

je viens d'appeler <%= render_if_exists "#{dynamic_path}" %>

j'espère que ça t'as aidé. (pas essayé dans Rails3)

8
afxjzs

J'ai utilisé ce paradigme à plusieurs reprises avec beaucoup de succès:

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

L'avantage du code ci-dessus est que nous pouvons gérer des cas spécifiques de remorquage:

  • Le partiel manque en effet
  • Le partiel existe, mais il a jeté une erreur pour une raison quelconque

Si nous utilisons simplement le code <%= render :partial => "#{dynamic_partial}" rescue nil %> ou un dérivé, le partiel peut exister mais déclenche une exception qui sera mangée silencieusement et deviendra une source de douleur à déboguer.

5
br3nt

Qu'en est-il de votre propre assistant:

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