Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple multi-line HAML blocks

Using the (intentionally) strange multi-line format for HAML, I'd like to have the following lines in my template:

= call_to_helper :foo1 => 'bar1', :foo2 => 'bar2', :foo3 => 'bar3', |
  :foo4 => 'bar4', :foo5 => 'bar5' |

-# and

= call_to_helper :foo1 => 'bar1', :foo2 => 'bar2', :foo3 => 'bar3', |
  :foo4 => 'bar4', :foo5 => 'bar5' |

However, they can not run up against one another, or they are read as one single multi-line block.

-# This fails:
= call_to_helper :foo1 => 'bar1', :foo2 => 'bar2', :foo3 => 'bar3', |
  :foo4 => 'bar4', :foo5 => 'bar5' |
= call_to_helper :foo1 => 'bar1', :foo2 => 'bar2', :foo3 => 'bar3', |
  :foo4 => 'bar4', :foo5 => 'bar5' |

And separating with a line break, interestingly enough, does no better:

-# This fails, too:
= call_to_helper :foo1 => 'bar1', :foo2 => 'bar2', :foo3 => 'bar3', |
  :foo4 => 'bar4', :foo5 => 'bar5' |

= call_to_helper :foo1 => 'bar1', :foo2 => 'bar2', :foo3 => 'bar3', |
  :foo4 => 'bar4', :foo5 => 'bar5' |

The only working solution I have found is to run a blank line of Ruby code between. Which looks really ugly.

= call_to_helper :foo1 => 'bar1', :foo2 => 'bar2', :foo3 => 'bar3', |
  :foo4 => 'bar4', :foo5 => 'bar5' |
-
= call_to_helper :foo1 => 'bar1', :foo2 => 'bar2', :foo3 => 'bar3', |
  :foo4 => 'bar4', :foo5 => 'bar5' |

Is there anything better?

like image 992
Matchu Avatar asked Sep 24 '09 22:09

Matchu


4 Answers

This is a feature, not a bug. Haml multiline blocks are intentionally unwieldy - including hard to follow one after another - because almost all the time it's better to put that Ruby code into a helper. Even if the helper is only called once, it will make your template much easier to read. For instance:

def blatz_link
  call_to_helper :foo1 => 'bar1', :foo2 => 'bar2', :foo3 => 'bar3',
    :foo4 => 'bar4', :foo5 => 'bar5'
end

def blootz_link
  call_to_helper :foo1 => 'bar1', :foo2 => 'bar2', :foo3 => 'bar3',
    :foo4 => 'bar4', :foo5 => 'bar5'
end

Then in your Haml, just do

= blatz_link
= blootz_link

which will be much more readable and easier to understand.


If you absolutely must follow one multiline block with another, just add a comment in between:

= call_to_helper :foo1 => 'bar1', :foo2 => 'bar2', :foo3 => 'bar3', |
  :foo4 => 'bar4', :foo5 => 'bar5' |
-#
= call_to_helper :foo1 => 'bar1', :foo2 => 'bar2', :foo3 => 'bar3', |
  :foo4 => 'bar4', :foo5 => 'bar5' |
like image 183
Natalie Weizenbaum Avatar answered Nov 09 '22 06:11

Natalie Weizenbaum


I've encountered the same problems and workarounds as have been mentioned here, and the weird (and yes, it IS weird) behavior of HAML with regard to multi-line blocks has bitten me quite a few times. I know that it's intentional and that it was probably intended to force the user to make his code easier to read. However, it's a well known fact that every developer has his own preferences when it comes to structuring code. HAML is the only language I know of (c, c++, ruby, python, HTML, etc.) that tries to impose such restrictions.

Calling the weird multi-line handling a feature rather than a bug, just indicates a flawed language design. In the end it will always be a bug in the eyes of the user. Multi-line support is a basic feature of any main stream language and the lack of this feature is just plain annoing - just like the M$ paperclip, which I believe was also an attempt to guide the user.

That being said, HAML is a fantastically compact and useful language for writing HTML. Those of us who (in some cases) prefer multi-line blocks would just love to at least be offered some kind of configuration option to enable/disable decent multi line block support - regardless of the language designer's personal definition of "easy to read code".

Until we get there, I guess we'll have to work around the language using the "-#" hack...

like image 37
Jesper Avatar answered Nov 09 '22 06:11

Jesper


You could use a block on your helper, yielding whatever makes sense.

module SomeHelper
  def call_to_helper
    foo = Foo.new
    yield foo
    # build your html here, using the foo object's attributes
  end

  class Foo
    attr_accessor :foo1, :foo2, :foo3, :foo4, :foo5
  end

end

Now on your haml:

= call_to_helper do |foo|
  -foo.foo1 = 'bar1'
  -foo.foo2 = 'bar2'
  -foo.foo3 = 'bar3'
  -foo.foo4 = 'bar4'
  -foo.foo5 = 'bar5'

= call_to_helper do |foo|
  -foo.foo1 = 'bar1'
  -foo.foo2 = 'bar2'
  -foo.foo3 = 'bar3'
  -foo.foo4 = 'bar4'
  -foo.foo5 = 'bar5'
like image 29
hgmnz Avatar answered Nov 09 '22 07:11

hgmnz


It's a hack (sort-of), but you could always use a "+" instead of a "=" on your 2nd, 3rd, etc. lines in the chain.

= call_to_helper :foo1 => 'bar1', :foo2 => 'bar2', :foo3 => 'bar3', |
  :foo4 => 'bar4', :foo5 => 'bar5' |
+ call_to_helper :foo1 => 'bar1', :foo2 => 'bar2', :foo3 => 'bar3', |
  :foo4 => 'bar4', :foo5 => 'bar5' |
like image 37
jdl Avatar answered Nov 09 '22 08:11

jdl