【问题标题】:How to do an if/else in HAML without repeating indented code如何在 HAML 中执行 if/else 而不重复缩进代码
【发布时间】:2011-03-28 12:09:11
【问题描述】:

根据用户是否登录,我想打印不同类型的 %body-tag。

这是我目前的做法:

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

如您所见,其中有很多重复的代码。我怎样才能消除这个?我已经尝试了以下方法:

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

不幸的是,这不起作用,因为 HAML 将其解释为 %h1 和内容是 else 语句的一部分,当然它们不是。

关于如何解决这个问题的任何想法?我一直遇到这个问题,所以我无法想象没有简单的解决方案。

【问题讨论】:

  • 第二个%body 是否应该在else 内?
  • 是的,应该。但 %h1 和内容不应该。

标签: ruby haml


【解决方案1】:

我认为您无法避免缩进问题,因为 HAML 自动分配“end”语句的方式,但您可以将 if 语句推送到正文标记本身 -

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

相对于

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

不是超级漂亮,但比重复整个块更丑!

【讨论】:

  • 我无法想象 HAML 为这样一个常见的用例提供了一个优雅的解决方案。如果真的是这样,我可能不得不考虑再次使用常规 HTML。无论如何,谢谢你的建议。如果未定义@user,是否可以完全省略“数据帐户”属性?
  • 这段代码会这样做 - 设置 :data_account => nil (间接地这样做)将导致 HAML 忽略该属性并生成一个普通的正文标记。
  • 代码返回以下内容: 所以不是执行表达式并返回它的值,它只显示单词'expression'。 (不,@user.account != 'expression')
  • 原来解决方案是使用括号来定义?方法。
【解决方案2】:
!!!
 - @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

【讨论】:

  • Marc - 在我发布之前没有看到@bahabil 的其他答案,他也可以工作,或者当你问@user.nil 时不设置数据帐户属性? ,如果字符串为零,它就不会输入密钥。 string 可以是视图助手中的助手方法调用。
  • 谢谢,效果很好! defined?-method 的括号实际上解决了我在 bhaibel 的回答中遇到的问题。
  • 在哪里可以定义辅助方法?
  • @Lokesh 在应用程序助手或控制器的关联助手中:mixandgo.com/blog/the-beginner-s-guide-to-rails-helpers
【解决方案3】:

HAML 优雅的解决方案是 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

上面描述的三元运算符对于这种特殊情况已经绰绰有余,但对于更复杂的事情,请打破助手。

哦,要使用它,请在您的视图中将 %body(...) 更改为 = body_for_user @user do

【讨论】:

  • 我忘了在开篇文章中明确提及它,但我使用的不是 Rails,而是 Sinatra,它没有 content_tag 方法。我可能可以模仿它,但我宁愿让它尽可能简单。 (还是)感谢你的建议。它将在我的 Rails 项目中很有用。
【解决方案4】:

这样写一个助手:

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

然后从body元素调用helper:

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

【讨论】:

  • 有关属性方法的更多信息,请参阅haml-lang.com/docs/yardoc/…
  • 我可能做错了什么,但这只是返回:
  • 更新示例。您需要在方法名称周围加上花括号(我使用了括号)。
【解决方案5】:

对于任何寻找 HAML 的 Ruby if/else 问题的答案的人,这就是我解决它的方法:

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

【讨论】:

    【解决方案6】:

    我通常在控制器上设置@@menu 变量,然后在启用引导的 layout.haml 中定义:

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

    当我将@@menu 设置为“关于”时,它将呈现:

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

    【讨论】:

    • 我没有看到 'about' 类被应用...你确定这是在你设置 @@menu 变量之后吗?
    • @v_mitchell: 如果@@menu 等于 'about' 字符串,则有 "@@menu == 'about' && :active" 三元运算符返回 :active。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多