Using webrat's contain(text) matcher with haml - ruby-on-rails

I'm using the following webrat matcher:
response.should contain(text)
With the following haml:
%p
You have
= current_user.credits
credits
I've written the cucumber step 'Then I should see "You have 10 credits"', which uses the webrat matcher above. The step fails, webrat does not find the text in the response because the haml actually produces
<p>You have
10
credits</p>
How can I get the matcher to match the output that haml produces?
Note: the above is a simplified example to the situation i'm dealing with. Writing the following haml is not an acceptable solution:
%p= "You have #{current_user.credits} credits"

You're right, this is a pain. I've found Webrat to be annoyingly touchy too much of the time.
Two ideas:
Fix your test. In this case you want it to be blind to newlines, so get rid of them all: response.tr("\n","").should contain(text)
Fix your Haml. This is probably the better option. You can use the multiline terminator | to tell Haml not to put line breaks in:
%p
You have |
= current_user.credits |
credits
See the Haml reference for more obscure stuff like this. (A surprising amount of which has to do with whitespace.)

Better than
%p= "You have #{current_user.credits} credits"
would be
%p You have #{current_user.credits} credits
since Haml automatically interpolates text nodes.

I've found that something like:
response.should contain(/You have 10 credits/m)
will often give me the match I want without me having to goof with my Haml. Given the choice between mucking with my markup, which I really want to be readable, and changing my matcher to a regular expression, the latter seems a small price to pay for the more straightforward coding of the view.

There are various facilities in Haml for manipulating whitespace, but the correct thing to do here is to either revise the matcher to be whitespace-independent or to use a filter for writing your inline content. For example:
%p
:plain
You have #{current_user.credits} credits
Or if you need more complex logic:
%p
:erb
You have <%= current_user.credits %> credits
Haml is designed for efficiently expressing the structure of a document, but it's not so good at expressing inline content. When you want to do fancy inline stuff (as here), it makes sense to drop into ERB/HTML rather than going purely Haml. For more details see this blog post.

Related

Can Haml omit tags where the Ruby content evaluates to nil?

If I have a line in a Rails template that evaluates to nil, is there a way to have Haml not bother to generate output for that line rather than create an empty tag? For instance given this:
%h4= #my_hash[:optional]
...imagine that there's no data for that hash-key. I don't want to end up with:
<h4></h4>
I'd like no output at all from that line because empty tags can still affect page layout, particularly if you're using something CSS-heavy like Bootstrap.
I can write this everywhere:
-if #my_hash[:optional]
%h4= #my_hash[:optional]
but it's long-winded and ugly.
(It seems like lots of people would want to do this, but I couldn't find any mention of either a way to do it in the Haml docs, or people on SO or elsewhere asking how it could be done. So clearly everybody already knows how to do it except me, right?)
Update: Thanks for the suggestions. The thing is, it doesn't seem to matter what you put after the equals sign here:
%h4= amazing_intelligent_helper_method_but_sadly_too_late()
because Haml has already decided to output a tag at that point, the only question is what goes in the tag? If the expression after the equals sign evaluates to nil, Haml doesn't put any content in the tag - but it still outputs the tag itself.
%h4= nil #output: <h4></h4>
%h4= '' #output: <h4></h4>
%h4= false #unexpected output: <h4>false</h4>
%h4= #Haml::SyntaxError 'There's no Ruby code for = to evaluate.'
So at the moment, I don't have a one-line way of omitting empty tags. But surely I'm not the only one who wants to do this? When you look at some of the esoteric options Haml supports, I'd have really expected this feature to already be in there somewhere.
Just append the condition to the line ala Ruby statement modifiers:
%h4= #my_hash[:optional] if #my_hash[:optional]
Still long winded but at least its on one line now.
Here are some other techniques that were discussed but they're not any shorter or prettier: HAML: Create container/wrapper element only if condition is true
Try this code
%h4= #my_hash[:optional] unless #my_hash[:optional].blank?
Even though this is my question I thought I'd suggest a semi-OK-ish answer I've just thought of in the hope that someone will look at it and say 'Aha! I can do better than that.'
I could put this in the view
!= h4_if #my_hash[:options]
and I throw this in my helper file:
TAGS_TO_DELETE_WHEN_EMPTY = ['h1', 'h2', 'h3', 'h4', 'p', 'span']
TAGS_TO_DELETE_WHEN_EMPTY.each do |tag|
new_method_name = (tag + '_if').to_sym
define_method new_method_name do |content = nil|
"<#{tag}>#{content}</#{tag}" if content
end
end
then I only get an h4 tag if there's content for it. I can use these little conditional helper methods, coupled with Haml's unescaped ruby evaluator '!=', to get what I'm looking for. Downsides include: even though it's very concise in the view, and easy to extend, it doesn't look much like regular Haml. Also, I'm not 100% sure it won't upset Haml in some way if I use much of it.
Plus I'm still hoping someone will tell me there's an option in Haml to not output empty tags, because then I don't need to write any additional code at all (which is my favourite solution to problems).

How to write variable in haml

I'm trying to use haml on RoR.
I faced some problems in haml.
My sample code is below.
ERB:
<p> <div class="hello"> <%= #sample.val %> <%= #hogehoge.val %> </div> </p>
HAML:
%p
.hello
= #sample.val
= #hogehoge.val
I can write one line in erb file.
But, I have to write 4 lines in haml.
Haml is so smart and beautiful syntacx structure, isn't it?
But I think writing so many lines is not smart.
How do I write in one line in haml in this case.
If you don't like the way haml work, why do you use it? that's how haml work. If you want something different you need something different, there are more template languages.
You complain about the amount of line but think about the amount of characters and readability, maintainability. The amout of line is one of the less important things on your code, or do you write all your html code in one line when you use erb or plain html?
You could save a few line though doing:
%p
.hello= "#{#sample.val} #{#hogehoge.val}"
but is it really THAT important? Well, now you have 2 lines instead of 1, is it "smart" enough? I don't think you can have that in one line using haml.
But, I have to write 4 lines in haml.
Yes, but you've saved a lot of characters and now have compile-time errors if you don't get your nesting right. Don't focus on the lines used, but the clarity.
I think you can do this:
%p %div.hello
= #sample.val + " " + #hogehoge.val
.hello
= #sample.val
= #hogehoge.val
If you're using <p> for styling, you'd be better putting a margin property in your .hello css
You're missing the point of haml - it's less verbose than erb

erb, haml or slim: which one do you suggest? And why? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
I am learning Rails and I have seen these template engines. I have no experience with them (only erb).
But as I am a beginner, I am really confused. Which one do you suggest and why? Erb, Haml or Slim? Please tell your reason for preferring one over the others. And if you have any other recommendations, please let us know.
EDIT:
I am NOT looking for a winner here. I just want to hear your opinions about them, their syntax, speed of execution, and so on.
Two big advantages of using slim over haml:
Slim is currently about eight times faster than haml.
Slim supports HTTP streaming, while HAML doesn't.
Slim has a more natural syntax: a href="foo.html"
ERB is good mainly if you have a web designer that will work on plain HTML and does not know either haml or slim. This way they can write HTML and you can embed ruby logic with the proper tags.
If you work on both HTML and ruby logic, or your designer is ready to learn something new (like HAML) I'd go for HAML. It is a lot more ruby-friendly, reduces char count by much and a lot more readable than ERB.
For example (taken from official HAML site):
In ERB your view will look like this:
<div id="profile">
<div class="left column">
<div id="date"><%= print_date %></div>
<div id="address"><%= current_user.address %></div>
</div>
<div class="right column">
<div id="email"><%= current_user.email %></div>
<div id="bio"><%= current_user.bio %></div>
</div>
</div>
While in HAML it will look like this:
#profile
.left.column
#date= print_date
#address= current_user.address
.right.column
#email= current_user.email
#bio= current_user.bio
A lot cleaner!
As for the difference between HAML and SLIM - I never really worked with SLIM but I guess it is a matter of taste - take a look at both syntaxes and decide which looks better in your eyes. I don't think there is a definite winner between those two (HAML/SLIM).
Off the top of my head this is what I came up with
ERB:
Pros
default out of the box
not white space dependent
lowest barrier of entry (if coming from HTML) as its HTML with Ruby code sprinkled in
most IDE's lexers read it by default
DHH prefers it
legacy apps are probably still using it
Cons
more verbose
content_for tags in helpers and views can get out of hand quickly
content_for tags makes nesting tags harder as erb only returns the last line in the block. so you have to append to a string and then return that.
HAML
Pros
more concise. no closing tags, fits in smaller screens
visually cleaner structure
has built in helpers (haml_concat, haml_capture) to utilize haml in helper methods
class chaining
lots of useful syntactic sugar like # for divs or . for class chaining, or :javascript for JS tags
Cons
whitespace dependent which makes for some hard errors to figure out at times
complex tags usually need to resort to "hash" format. (Although I actually think this is a great example of flexibility to someone starting out it could be a pain.)
added as a gem (again probably a stretch to put this as a con)
designers might have some trouble adjusting
in addition to the general whitespace warning... simple whitespace errors eg. tabs and spaces for indentation, can cause pages to err in production which normal specs/test won't catch. Moral: Expect greater need for view tests and possibly don't use haml for mission critical views, unless you're sure that your tests are testing the actual rendering of the view.
is slower (than erb)
caveat: this is ruby code we're talking about if speed is a blocking issue in your application there are alternatives to ruby, e.g. haskell
The question for me comes down to would you rather put % before every tag or | before every new block of text?
Slim:
tag(attr= "value")
| text
Haml:
%tag{attr: "value"}
text
One more thing to lookout for: haml assumes a white space between new lines (remove whitespace in haml) while slim assumes no space (Add whitespace in Slim here and here)
https://github.com/scalp42/hamlerbslim - is an independent benchmark which shows Slim and Erb as winners, performance wise (slim tends to reduce the HTML output size too.)
My personal opinion is that overall, Slim and Haml will save you time (== money) in terms of maintenance, providing you have Haml/Slim savvy people looking after your views.
If you don't have those people, Erb is definitely the way to go, because despite the best will in the world, there are a lot of very inexpensive people available who can work with HTML/Erb, but find Haml/Slim a complete mystery.
Best of all cases, train these people to use Slim or at least expose them to it, and keep the numbers of the ones who "get it."

how to create a strong element inside a p

In haml, how do I render the following incredibly basic HTML:
<p>Results found for <strong>search term</strong>
where 'search term' is actually a Ruby variable called #query?
I'm trying the following,
%p results found for <strong>= #query</strong>
But that renders = #query literally. If I try:
%p results found for <strong>
= #query
</strong>
then the query term renders correctly, but is on a new line.
Also, I'm wondering if there's a better way to render <strong> in haml, while keeping everything on the same line.
I'm aware of the haml documentation, but as far as I can see there isn't an example of using a simple inline Ruby variable.
-----UPDATE-------
The following code works, and shows how to use a variable that's not within tags:
%p
= #trials_found_count
results found for
%strong= #query
But I find it really unreadable - it's hard to tell that it renders as just one line of HTML without adding a comment above.
Is there a way I can put all this code on a single line? Or is this just how haml works?
HAML is whitespace delimited. Nested tags go on the line below and one level in from the tag above. Embedded Ruby from which you want to display output is opened with an '='. Embedded Ruby which you don't want to display such as the start of loops uses '-' These are equivalent to <%= %> and <% %> respectively in erb.
What you want would look like this:
%p
results found for
%strong= #query
Which would produce the html:
<p>results found for <strong>#query</strong></p>
It should be noted that the '=' to start Ruby evaluation can only come at the beginning of the line or after a tag declaration and that only one tag declaration can occur per line.
The Ruby Evaluation section of the reference you linked covers embedded Ruby in detail and the haml tutorial which covers embedded ruby and many other haml basics is here:
http://haml-lang.com/tutorial.html
Here's how I'd do it:
%p No results found for <strong>#{h #query}</strong>
I'm not sure, but you might need a non-breaking space to preserve the space between the for and the <strong>
%p results found for
%strong= #query

Correct coding convention for embedded code on web page templates

I had come experience with PHP a time ago and now I'm learning to use Ruby on Rails. But one simple question bothered me in both these languages, so I think I can cross-post it to both tags.
As you know, one of the concepts there is that one can embed PHP or Ruby code into web page template. Then these statements are executed and result of its execution is inserted in certain places of the page, marked with "brackets" <%= ... %>.
Or... wait. We program Ruby/PHP, but not HTML. Maybe we should treat template as Ruby/PHP code, into which sometimes HTML markup is inserted? So the process is treated like that HTML are inserted into ruby code into the "brackets" %> ... <%.
These are two different approaches:
HTML page is the primary entity, and it is affected by code execution; or
code is the primary entity, and it is executed, while HTML snippets are inserted in certain places.
This philosophy leads to different possibilities in coding conventions: result of code execution influences the page If we adhere the first insight, then the code would look like this:
<p>
<% (1..10).foreach do |i| %>
Iteration number <strong><%= i %></strong>. <br/>
<% end %>
</p>
But if we stick to the second alternative, the code would be formatted like this:
<%
%><p><%
(1..10).foreach do |i|
%>Iteration number <strong><%
%><%= i %><%
%></strong>. <br/><%
end
%>
How should the concept of templates be construed? What concepts do you, way more experienced Web developers, account for the coding convention?
If this is in your View layer (and it should be), then the HTML is the primary entity. It's the most pertinent part of that layer -- marking up your data to display in meaningful ways to the user.
Even aside from that, your second example is nearly unreadable. I see what you're doing, but it took me a minute to wrap my brain around it. I've also never, ever seen View-layer code like your second example (and I would make it one of my priorities to change it wherever I saw it if it was in a project I was working on).
To be more concise: you're putting the emphasis on the wrong thing. In my opinion, readability trumps just about everything else. The coding style that produces the most readable code is therefore the most superior (ceteris paribus and YMMV, of course).
Maybe you should look into Haml? I don't know if there's a php equivalent, but as far as Rails goes, it's somewhere in between the two schemes. It's not quite code centric. But when used right, all the raw html is prepared programatically.
In short everything is considered text to be directly outputted, unless prefixed with either a %, - or =. Which translate to html-tag, ruby code that doesn't output. Ruby code that does output. Haml then uses whitespacing to nest things properly, much like python does. Raw html outputs untouched but using % to specify a tag handles closing tags.
Sample:
#outer-div
- #items.each do |i|
%span.item
= i
%br
Outputs
<div id="outer-div">
<span class="item">
item
</span>
<br>
</div>
See the haml tutorial for more information.
To answer the central question. The bulk of any page is going to be HTML or raw text. We reduce the bulk of that text with includes and helpers, but it's still there. If there were a truly code centered approach my use of it would depend on the ratio of program logic to html. Personally I'd rather go with the html centered approach.
If you are interested in a code-oriented view, this is something you might try implementing as a pure Ruby DSL:
tag :p, :class => 'iterations-container' do
(1..10).each do |i|
text "Iteration number "
tag :strong { text i }
text "."
tag :br
end
end
Or perhaps instead of tag :p do ... end, you may favor tag.p do ... end.
I recommend doing only very simple logic in your template files. That way designers who can edit HTML can easily edit even those files to alter the layout if need be.

Resources