2010-08-24 3 views
86

Wenn ich eine partielle, die nicht existiert, rendern, erhalte ich eine Ausnahme. Ich möchte prüfen, ob ein Teil vorhanden ist, bevor es gerendert wird, und falls es nicht existiert, werde ich etwas anderes rendern. Ich habe den folgenden Code in meiner .erb Datei, aber ich denke, es sollte ein besserer Weg, dies zu tun:Gibt es eine Rails-Funktion, um zu prüfen, ob eine partielle existiert?

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

Die Antwort, die verwendet 'rescue' riskant ist. Ich würde mir die anderen Lösungen ansehen, bevor ich sie benutze. – nertzy

Antwort

89

Derzeit bin ich folgendes in meiner Rails 3/3.1 Projekte mit:

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

Der Vorteil gegenüber o Die Lösungen, die ich gesehen habe, sind, dass dies in allen Ansichtspfaden und nicht nur in Ihrem roots root aussehen wird. Dies ist wichtig für mich, da ich viele Schienenmotoren habe.

Dies funktioniert auch in Rails 4.

+19

lookup_context.exists ('posts/find') sollte auch funktionieren –

+7

lookup_context.exists ('posts/find') funktionierte nicht für mich. Stattdessen habe ich lookup_context.exists verwendet?(name, prefix, partial) oder lookup_content.exists ('find', 'posts', true) in diesem Beispiel. – Jenn

+2

Dies ist die aktuelle (rails> = 3.2) Möglichkeit, nach Vorlagen zu suchen (Quelle [apidock] (http://apidock.com/rails/ActionView/LookupContext/ViewPaths/template_exists%3F)) –

65

Ich war zu sehr damit zu kämpfen. Dies ist die Methode, die ich am Ende mit:

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

Grundsätzlich, wenn die teilweise nicht vorhanden ist, nichts zu tun. Wolltest du etwas drucken, wenn das Teil fehlt?

Edit 1: Oh, ich scheitere beim Leseverstehen. Du hast gesagt, dass du etwas anderes rendern willst. In diesem Fall, wie wäre es damit?

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

oder

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

Edit 2:

Alternative: Prüfung auf Existenz der Teildatei:

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

Meine Frage ist, dass ich keine Ausnahmen verwenden möchte, um die Ablaufsteuerung zu tun, die ein Anti-Muster ist: http://stackoverflow.com/questions/1546514/java-exceptions-as-control-flow –

+6

Eine Ausnahme ist eine Art von Flusskontrolle, die verwendet wird, um Dinge zu behandeln, die außerhalb des normalen Betriebs eines Programms auftreten. Wenn das dynamische Partial dort sein soll, aber etwas schief läuft und es nicht da ist, dann ist das eine vernünftige Verwendung für eine Ausnahme (IMO, natürlich - die richtige Verwendung von Ausnahmen ist ein heiliger Krieg selbst). Ich würde sagen, Ihre Alternative besteht darin, das Dateisystem zu überprüfen, ob die tatsächliche Datei existiert oder nicht. Ich werde meine Antwort mit diesem Code aktualisieren. – Jeff

+3

Ich mag die Lösung, trotzdem schluckt sie jede Art von Ausnahme in den Teil geworfen. IMHO macht es schwieriger, Fehler aufzuspüren. – Matt

49

Aus dem Inneren Blick, template_exists? funktioniert, aber die Aufrufkonvention funktioniert nicht mit der einzelnen Teilnamen-Zeichenfolge, stattdessen dauert es template_exists? (Name, Präfix, teilweise)

Um nach partiellen Pfad zu suchen: app/views/posts/_form.html .slim

Verwendung:

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

On Rails 3.0.10 Ich fand, dass ich, wenn ich eine alternative Erweiterung habe, wie app/views/posts/_foo.txt.erb, musste ich das zu dem Argument hinzufügen als: template_exists? ("Foo.txt", "posts ", true) –

+0

Dies ist in Rails veraltet 3.2 –

+0

Es scheint nicht in Rails 3.2.x delegiert zu sein, das zweite Argument ist jedoch ein Array von Präfixen. Außerdem existiert es auf dem aktuellen Controller. – Brendan

29

In Rails 3.2.13, wenn Sie in einem Controller sind, können Sie diese verwenden:

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

template_exists? zu lookupcontext delegiert wird, wie Sie können, siehe AbstractController::ViewPaths

_prefixes gibt den Kontext der Vererbungskette des Controllers an.

true weil Sie nach einer partiellen suchen (Sie können dieses Argument weglassen, wenn Sie eine normale Vorlage wünschen).

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

+0

Upvoted. Modernere und bessere Erklärung der Parameter. – jacobsimeon

+4

Aus einer Ansicht (wie einem Layout) funktioniert dies: 'lookup_context.template_exists? (" Navbar ", controller._prefixes,: partially)'. Dies sagt mir, wenn das aktuelle Template Rendering dieses Layout hat die angegebene "navbar" teilweise, und wenn ja, kann ich es rendern. Ich übergebe ': partially', um explizit zu erklären, was dieser boolesche Wert ist -': partially' ist truthy. Danke für das '_prefixes' Bit, @Flackou! – pdobb

+0

Ersetzen Sie '_prefixes' durch' nil', wenn Sie einen Teil aufrufen, der sich in einem anderen übergeordneten Verzeichnis befindet. – ben

8

Ich weiß, das beantwortet wurde und ist eine Million Jahre alt, aber hier ist, wie ich das für mich Festsetzung endete ...

Rails 4.2

Zuerst legte ich dies in meinem 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 

und jetzt statt Aufruf

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

ich nenne nur <%= render_if_exists "#{dynamic_path}" %>

Hoffnung das hilft. (Nicht in rails3 versucht)

+1

Dies funktioniert nicht, wenn Sie einen Fallback bereitstellen möchten. Es berücksichtigt auch keine lokalen Variablen. – phillyslick

+0

Genau das habe ich gesucht. Sehr saubere Antwort. – Sunny

+1

@BenPolinsky Ich nehme an, Sie können 'def verwenden render_if_exists (* args); render (* args) wenn ... 'dafür – juanpastas

5

ich verwendet habe, um dieses Paradigma bei vielen Gelegenheiten mit großem Erfolg:

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

Der Vorteil des obigen Code ist, dass wir Schlepptau spezifische Fälle behandeln können:

  • Die teilweise in der Tat fehlt
  • Die teilweise vorhanden ist, aber es warf einen Fehler aus irgendeinem Grund

Wenn wir nur den Code <%= render :partial => "#{dynamic_partial}" rescue nil %> oder eine Ableitung verwenden, kann die partielle existieren, aber eine Ausnahme auslösen, die still gegessen wird und eine Quelle des Schmerzes zum Debuggen wird.

1

Was ist mit Ihrem eigenen Helfer:

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