How to do an if/else in HAML without repeating ind

2019-03-24 03:41发布

Depending on if a user is signed in or not, I'd like to print a different kind of %body-tag.

This is how I currently do it:

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

As you can see there's a lot of duplicated code in there. How can I eliminate this? I already tried the following:

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

Unfortunately, this doesn't work since HAML interprets it as if the %h1 and the content is part of the else-statement, which of course they aren't.

Any ideas on how to solve this? I run in this problem all the time, so I can't imagine there isn't a simple solution for it.

标签: ruby haml
6条回答
爱情/是我丢掉的垃圾
2楼-- · 2019-03-24 03:50

Write a helper like this:

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

Then call the helper from the body element:

%body{ body_attributes }
  %h1 Welcome
  -# all my content
查看更多
对你真心纯属浪费
3楼-- · 2019-03-24 03:53

I usually set the @@menu variable at the controller, then in bootstrap-enabled layout.haml I define:

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

when I set @@menu to 'about' it will render:

  <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>
查看更多
我想做一个坏孩纸
4楼-- · 2019-03-24 03:55
!!!
 - @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
查看更多
Explosion°爆炸
5楼-- · 2019-03-24 04:01

HAML's elegant solution is helpers

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

The ternary operators described above are more than sufficient for this particular situation, but for more complex things, break out the helpers.

Oh, to use this, in your view change %body(...) to = body_for_user @user do

查看更多
劳资没心,怎么记你
6楼-- · 2019-03-24 04:05

I don't think that you can avoid the indentation issue, because of the way HAML autoassigns the "end" statement, but you can instead push the if statement into the body tag itself -

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

as opposed to

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

Not super-pretty, but less ugly than repeating the entire block!

查看更多
Viruses.
7楼-- · 2019-03-24 04:15

For anybody looking for an answer to the Ruby if/else issue with HAML this is how I worked around it:

%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}&times;
  %td= line_item.product.title
  %td.item_price= number_to_currency(line_item.total_price)
查看更多
登录 后发表回答