2010-08-11 4 views
16

Abhängig davon, ob ein Benutzer angemeldet ist oder nicht, möchte ich eine andere Art von% Body-Tag drucken.Wie mache ich eine if/else in HAML ohne wiederholten eingerückten Code?

Dies ist, wie ich es zur Zeit:

- if defined? @user 
    %body(data-account="#{@user.account}") 
    %h1 Welcome 
    -# all my content 
- else 
    %body 
    %h1 Welcome 
    -# all my content 

Wie Sie es viel duplizierten Code gibt es zu sehen. Wie kann ich das beseitigen? Ich habe bereits versucht, die folgende:

- if defined? @user 
    %body(data-account="#{@user.account}") 
- else 
    %body 
    %h1 Welcome 
    -# all my content 

Leider ist dies nicht funktioniert, da HAML es, als ob das% h1 interpretiert und der Inhalt ist Teil der Else-Anweisung, das natürlich sind sie nicht.

Irgendwelche Ideen, wie man das löst? Ich laufe die ganze Zeit in diesem Problem, daher kann ich mir nicht vorstellen, dass es dafür keine einfache Lösung gibt.

+0

Ist der zweite '% Körper' innerhalb des 'else' oder nicht? –

+0

Ja, sollte es. Aber das% h1 und der Inhalt sollten nicht. – Marc

Antwort

12
!!! 
- @user = "jed" #=> stubbing out an instance 
%html 
    %head 
    - string = defined?(@user) ? "#{@user}" : nil #=> for demo only, wrap this in a helper method 
    %title{'data-account' => string} 
    %body 
    =yield 
+0

Marc - ohne die andere Antwort von @bahabil zu sehen, bevor ich gepostet habe, wird sein Wille auch funktionieren, oder wie Sie gefragt haben, das Datenkonto-Attribut bei @ user.nil nicht zu setzen, wird dies tun, es wird einfach nicht den Schlüssel setzen Wenn String null ist. string könnte ein Hilfsmethodenaufruf in Ihrem View-Helper sein. –

+0

Danke, funktioniert super! Die Klammern für die definierte? -Methode lösten tatsächlich das Problem, auf das ich bei Bhaibels Antwort gestoßen bin. – Marc

+0

Wo kann ich die Hilfsmethode definieren? – Lokesh

13

Ich glaube nicht, dass Sie die Vertiefung Problem vermeiden kann, wegen der Art und Weise HAML autoassigns die Aussage „Ende“, aber Sie können die if-Anweisung in den Körper Tag selbst statt Push -

%body{:data_account => (defined? @user ? @user.account : nil)} 

wie zu

Gegensatz
%body(data-account="#{@user.account}") 

Nicht super-schön, aber weniger hässlich als den gesamten Block zu wiederholen!

+1

Ich kann mir nicht vorstellen, dass HAML eine elegante Lösung für solch einen gewöhnlichen Anwendungsfall hat. Wenn es wirklich der Fall ist, muss ich möglicherweise erwägen, wieder zu normalem HTML zu wechseln. Wie auch immer, danke für Ihren Vorschlag. Ist es möglich, das 'Datenkonto'-Attribut komplett wegzulassen, wenn @user nicht definiert ist? – Marc

+0

Dieser Code wird das tun - Einstellung: data_account => nil (was dies indirekt tut) wird HAML dazu bringen, das Attribut zu ignorieren und ein einfaches body-Tag zu generieren. – bhaibel

+0

Der Code gibt Folgendes zurück: Anstatt den Ausdruck auszuführen und seinen Wert zurückzugeben, wird nur das Wort 'Ausdruck' angezeigt. (Und nein, der @ user.account! = 'Ausdruck') – Marc

4

HAML die elegante Lösung ist Helfer

class ApplicationHelper... 

    def body_for_user(user, &blk) 
    return content_tag(:body, :'data-account' => user.account, &blk) if user 
    content_tag(:body, &blk) 
    end 

end 

Die ternären Operatoren oben beschrieben sind mehr als ausreichend für diese besondere Situation, aber für komplexere Dinge, brechen die Helfer aus.

Oh, diese zu verwenden, in der Ansicht ändern %body(...) zu = body_for_user @user do

+0

Ich vergaß es explizit in meinem ersten Beitrag zu erwähnen, aber ich verwende nicht Rails, sondern Sinatra, das nicht über die Methode content_tag verfügt. Ich kann es wahrscheinlich nachahmen, aber ich halte es lieber so einfach wie möglich. Danke für den Vorschlag obwohl. Es wird in meinen Rails-Projekten nützlich sein. – Marc

1

schreiben einen Helfer wie folgt aus:

def body_attributes 
    {}.tap do |hash| 
    hash[:data] = {} 
    hash[:data][:account] = @user.account if @user 
    # add any other attributes for the body tag here 
    end 
end 

dann die Helfer aus dem Körperelement nennen:

%body{ body_attributes } 
    %h1 Welcome 
    -# all my content 
+0

Weitere Informationen zu Attributmethoden finden Sie unter http://haml-lang.com/docs/yardoc/file.HAML_REFERENCE.html#attribute_methods. –

+0

Ich mache wahrscheinlich etwas falsch, aber das gibt nur zurück: – Marc

+0

Aktualisiertes Beispiel. Sie benötigen geschweifte Klammern um den Methodennamen herum (ich habe Parens verwendet). –

1

Für jeden, der eine Antwort auf das Ruby if/else-Problem mit HAML sucht, habe ich so gearbeitet:

%tr{ id: (line_item == @current_item) ? "current_item" : nil } 
    %td= button_to '-', decrement_line_item_path(line_item), method: :put, remote: true 
    %td #{line_item.quantity}× 
    %td= line_item.product.title 
    %td.item_price= number_to_currency(line_item.total_price) 
0

ich in der Regel die @@ Menü Variable in der Steuerung gesetzt, dann in Bootstrap-fähigen layout.haml Ich definiere:

... 
    %body 
    .navbar.navbar-fixed-top 
     .navbar-inner 
     .container 
      %a.btn.btn-navbar{"data-target" => ".nav-collapse", "data-toggle" => "collapse"} 
      %span.icon-bar 
      %span.icon-bar 
      %span.icon-bar 
      %a.brand{:href => "/"} AwesomeApp 
      .nav-collapse 
      %ul.nav 
       %li{:class => @@menu == 'home' && :active} 
       %a{:href => "/"} Home 
       %li{:class => @@menu == 'about' && :active} 
       %a{:href => "/about"} About 
       %li{:class => @@menu == 'contact' && :active} 
       %a{:href => "/contact"} Contact 

wenn ich @@ Menü einstellen 'über' sie machen wird:

<body> 
    <div class='navbar navbar-fixed-top'> 
     <div class='navbar-inner'> 
     <div class='container'> 
      <a class='btn btn-navbar' data-target='.nav-collapse' data-toggle='collapse'> 
      <span class='icon-bar'></span> 
      <span class='icon-bar'></span> 
      <span class='icon-bar'></span> 
      </a> 
      <a class='brand' href='/'>AwesomeApp</a> 
      <div class='nav-collapse'> 
      <ul class='nav'> 
       <li> 
       <a href='/'>Home</a> 
       </li> 
       <li class='active'> 
       <a href='/about'>About</a> 
       </li> 
       <li> 
       <a href='/contact'>Contact</a> 
       </li> 
      </ul> 
      </div> 
     </div> 
     </div> 
    </div> 
+0

Ich sehe nicht, dass "über" die Klasse angewendet wird ... Bist du sicher, dass dies der Fall ist, nachdem du @@ menu variable gesetzt hast? –

+0

@v_mitchell: Es gibt "@@ menu == 'über' &&: active" ternärer Operator, der zurückgibt: aktiv, wenn @@ Menü ist gleich 'über' Zeichenfolge. – andrej

Verwandte Themen