2010-08-11 6 views
16

Dependiendo de si un usuario está registrado o no, me gustaría imprimir un tipo diferente de% body-tag.Cómo hacer un if/else en HAML sin repetir el código sangrado

Esto es como actualmente lo hago:

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

Como se puede ver que hay una gran cantidad de código duplicado en ese país. ¿Cómo puedo eliminar esto? Ya he intentado lo siguiente:

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

Desafortunadamente, esto no funciona ya HAML lo interpreta como si el h1% y el contenido es parte de la cosa-declaración, que por supuesto no lo son.

¿Alguna idea sobre cómo solucionar esto? Corro en este problema todo el tiempo, así que no puedo imaginar que no haya una solución simple para eso.

+0

¿El segundo '% body' se supone que está dentro del' else' o no? –

+0

Sí, debería. Pero el% h1 y el contenido no deberían. – Marc

Respuesta

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 - sin ver la otra respuesta de @bahabil antes de publicar, la suya también funcionará, o como preguntaste sobre no configurar el atributo de cuenta de datos cuando @ user.nil ?, esto hará eso, simplemente no colocará la clave en si la cadena es nula. string podría ser una llamada de método auxiliar en su vista helper. –

+0

¡Gracias, funciona genial! Los paréntesis para el? Método definido realmente resolvieron el problema que encontré con la respuesta de bhaibel. – Marc

+0

¿Dónde puedo definir el método de ayuda? – Lokesh

13

No creo que se puede evitar el problema de sangrado, debido a la forma HAML autoassigns el "fin" declaración, pero en su lugar puede empujar la sentencia if en el cuerpo de la etiqueta en sí -

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

a diferencia de

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

¡No es súper bonito, pero es menos feo que repetir el bloque completo!

+1

No puedo imaginar que HAML tenga una solución elegante para un caso de uso tan común. Si es realmente el caso, debería considerar cambiar de nuevo al HTML normal. De todos modos, gracias por su sugerencia. ¿Es posible omitir el atributo 'cuenta de datos' por completo si @user no está definido? – Marc

+0

Este código hará eso - setting: data_account => nil (que esto hace, indirectamente) conducirá a HAML a ignorar el atributo y generar una etiqueta de cuerpo simple. – bhaibel

+0

El código devuelve lo siguiente: De modo que en lugar de ejecutar la expresión y devolver su valor, simplemente muestra la palabra 'expresión'. (Y no, el @ user.account! = 'Expresión') – Marc

4

solución elegante de HAML es ayudantes

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 

Los operadores ternarios descritos anteriormente son más que suficientes para esta situación particular, pero para cosas más complejas, estallan los ayudantes.

Oh, a usar esto, en su cambio de vista %body(...) a = body_for_user @user do

+0

Olvidé mencionarlo explícitamente en mi publicación inicial, pero no estoy usando Rails sino Sinatra, que no tiene el método content_tag. Probablemente pueda imitarlo, pero prefiero mantenerlo lo más simple posible. Gracias por la sugerencia. Será útil en mis proyectos de Rails. – Marc

1

Escribir un ayudante así:

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 

a continuación, llamar al ayudante del elemento del cuerpo:

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

Consulte http://haml-lang.com/docs/yardoc/file.HAML_REFERENCE.html#attribute_methods para obtener más información sobre los métodos de atributo. –

+0

Probablemente estoy haciendo algo mal, pero esto simplemente devuelve: – Marc

+0

Ejemplo actualizado. Necesitas llaves alrededor del nombre del método (yo usé parens). –

1

Para cualquiera que esté buscando una respuesta al problema Ruby if/else con HAML, así es como trabajé a su alrededor:

%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

I general establecer la variable @@ menú en el controlador, a continuación, en layout.haml arranque habilitado defino:

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

cuando me puse a @@ menú 'sobre' va a proporcionar:

<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

No veo que se aplique la clase 'sobre' ... ¿está seguro de que esto es después de establecer @@ variable de menú? –

+0

@v_mitchell: hay "@@ menu == 'sobre' &&: active" operador ternario que regresa: activo si @@ menu es igual a 'about' string. – andrej

Cuestiones relacionadas