Ответ 1
!!!
- @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
В зависимости от того, был ли пользователь подписан или нет, я хотел бы напечатать теневой тег другого типа.
Вот как я это делаю сейчас:
- 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-statement, что, конечно же, не так.
Любые идеи о том, как это решить? Я все время сталкиваюсь с этой проблемой, поэтому я не могу себе представить, что для нее нет простого решения.
!!!
- @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
Я не думаю, что вы можете избежать проблемы с отступом из-за того, как HAML автоматически назначает оператор "end", но вы можете вместо этого вставить оператор if в сам тег body -
%body{:data_account => (defined? @user ? @user.account : nil)}
в отличие от
%body(data-account="#{@user.account}")
Не супер-симпатичный, но менее уродливый, чем повторение всего блока!
Элегантное решение HAML - помощники
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
Напишите помощник следующим образом:
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:
%body{ body_attributes }
%h1 Welcome
-# all my content
Для любого, кто ищет ответ на проблему Ruby if/else с HAML, я так и работал над этим:
%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)
Обычно я устанавливаю переменную меню @@на контроллере, а затем в макете с поддержкой начальной загрузки. Я определяю:
...
%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
когда я устанавливаю @@в меню "about", он отобразит:
<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>