Do not understand what "#" key means with Haml in Rails - ruby-on-rails

I am new to Ruby on Rails, and I setup a starter package on my local machine.
As I looked through it I found this in one of the html.haml files:
%p
Welcome #{#email}!
%p You can confirm your account email through the link below:
%p= link_to 'Confirm my account', confirmation_url(#resource, :confirmation_token => #token)
I think that the ! is part of the message to the user and I believe the #email is a variable with string text and is the person's email address.
However, I don't quite understand what the # does with the email. From the Haml documentation I believe that the # symbol makes a div as show from the example on the Haml site, but this doesn't really make sense so if anyone could explain what it means I would greatly appreciate it.
Haml site example:
#content
.left.column
%h2 Welcome to our site!
%p= print_information
.right.column
= render :partial => "sidebar"

# is for setting the id of an element if it is part of an element, possibly an implicit div.
In plain text (i.e. not in an element definition) the #{...} syntax does interpolation. The contents are evaluated as Ruby, and the result is inserted into the output at this point. In this case, if #email had the value matt#example.com the result would be:
Welcome matt#example.com!
If you want to start a line with some interpolation you can escape the # with \, otherwise it would be interpreted as the start of an element and you would likely get an error.

Related

ruby rails delete space after link_to without HAML

I am programming an app with Ruby on Rails and, in some views, I would like to get rid of the automatic whitespace triggered by the 'link_to' helper.
<%= link_to liker.first_name.capitalize, user_path(liker) %>
<!-- Example of link with a user's firstname (who liked a given content), redirecting to it's user profile -->
I have read this post, which talks about using HAML (that I do not use). Isn't it possible to delete this tiny whitespace only using Ruby on Rails?
You always get a whitespace between inline html elements if you put them in different lines in your html document. For example
<span>foo</span>
<span>bar</span>
would render as "foo bar" on the page. But if you write that html elements next to each other in one line, without a whitespace in between
<span>foo</span><span>bar</span>
it would render as "foobar".
That said: Just write the link_to into the same line with the text that should not be separated with a whitespace:
foo<%= link_to 'bar', '#' %>baz
Would look like "foobarbaz" without any whitespace
As Akshay said you can use .strip or .strip! to remove leading and trailing whitespace.But if you want to remove all whitespace use some tricky hack like .gsub(/\s+/, "") or .gsub(" ","").
<%= link_to liker.first_name.capitalize.to_s.gsub(/\s+/, ""), user_path(liker) %>

Rails and HAML: Mailto link with picture

I am trying to create a mailto link that involves clicking a picture and including some raw content from a text file into the body of the message.
The following doesn't work (haml).
= mail_to "friend#example.com" do
%img{:src=>"#{asset_path 'mail.png'}"}
I don't even know how I'd get the body preloaded in there. I know there is a :body declaration but its usage in this context eludes me.
Thoughts?
The mail_to helper only appears to accept a block in Rails 4, not previous versions. If you're using Rails 3 and can’t upgrade, you could do something like this:
- mail_link_content = capture_haml do
%img{:src=>asset_path('mail.png')}
=mail_to "friend#example.com", mail_link_content
Note that you don’t need to use a string if the contents are all interpolated (you might need to add parentheses though).
To get the body content, you just need to pass an options hash as the last argument to mail_to with a :body key:
Rails 4:
= mail_to "friend#example.com", :body => "Body text here" do
%img{:src=>asset_path('mail.png')}
Rails 3:
=mail_to "friend#example.com", mail_link_content, :body => "Body text here"

Rails escapes HTML in my plain text mails

I am using the rails 3.2.5 ActionMailer to send plain text mails. Given I have a mail view like this:
message_from_user.text.erb:
Hi <%= #recipient.name %>,
You got the following message from <%= #sender.name %>:
<%= #message %>
When #message is "quotes & ampersands", then the plain text mail contains "quotes & ampersands". So it seems like rails just treats this as a HTML view and escapes any html in order to prevent cross site scripting. However this is a plain text mail. The extension is .text.erb and ActionMailer detectes this and sets the MIME to text/plain. So I never want to escape any html in it.
I have quite a few mail templates in my application, they are all plain text. I would consider patching all of them to include <%=raw #message%> or <%= #message.html_safe %> bad style - not very DRY.
I tried varios work-arounds that included money patching Erubis. None of them seem to work. I am looking for some patch or config option or anything to disable escaping html for all .text.erb files.
Any help is greatly appreciated!
After some hours of debugging through the Erubis code, I found the following fix. You can just put it into config/initializers/fix_my_mails.rb. I've tested this with rails 3.2.7. It may work with other versions.
module ActionView
class Template
module Handlers
class ERB
def call(template)
if template.source.encoding_aware?
# First, convert to BINARY, so in case the encoding is
# wrong, we can still find an encoding tag
# (<%# encoding %>) inside the String using a regular
# expression
template_source = template.source.dup.force_encoding("BINARY")
erb = template_source.gsub(ENCODING_TAG, '')
encoding = $2
erb.force_encoding valid_encoding(template.source.dup, encoding)
# Always make sure we return a String in the default_internal
erb.encode!
else
erb = template.source.dup
end
self.class.erb_implementation.new(
erb,
:trim => (self.class.erb_trim_mode == "-"),
:escape => template.identifier =~ /\.text/ # only escape HTML templates
).src
end
end
end
end
end
It just disables HTML entities in every erb file containing .text in the file name.
Try
<%= #message.html_safe %>
You'd found this answer if you had used the search function. If that doesn't suit your needs, maybe check
https://rails.lighthouseapp.com/projects/8994/tickets/4858-actionmailer-is-html-escaping-ampersand-in-urls-in-plain-text-messages
If you haven't seen that yet, some options are discussed there

Rails 3: How to display properly text from "textarea"?

In my Rails 3 application I use textarea to let users to write a new message in a forum.
However, when the message is displayed, all newlines look like spaces (there is no <br />). Maybe there are other mismatch examples, I don't know yet.
I wonder what is the most appropriate way to deal with this.
I guess that the text that is stored in the database is OK (I see for example that < is converted to <), so the main problem is the presentation.
Are there build-in helper methods in Rails for this ?
(simple_format does something that looks similar to what I need, but it adds <p> tags which I don't want to appear.)
Rails got a helper method out of the box, so you dont have to write your own method.
From the documentation:
simple_format(text, html_options={}, options={})
my_text = "Here is some basic text...\n...with a line break."
simple_format(my_text)
# => "<p>Here is some basic text...\n<br />...with a line break.</p>"
more_text = "We want to put a paragraph...\n\n...right there."
simple_format(more_text)
# => "<p>We want to put a paragraph...</p>\n\n<p>...right there.</p>"
simple_format("Look ma! A class!", :class => 'description')
# => "<p class='description'>Look ma! A class!</p>"
You can use style="white-space: pre-wrap;" in the html tag surrounding the text. This respects any line breaks in the text.
Since simple_format does not do what you want, I'd make a simple helper method to convert newlines to <br>s:
def nl2br(s)
s.gsub(/\n/, '<br>')
end
Then in your view you can use it like this:
<%= nl2br(h(#forum_post.message)) %>
If someone still gets redirected here and uses Rails 4:
http://apidock.com/rails/v4.0.2/ActionView/Helpers/TextHelper/simple_format
You can now specify the tag it gets wrapped in (defaults to p) like so:
simple_format(my_text, {}, wrapper_tag: "div")
# => "<div>Here is some basic text...\n<br />...with a line break.</div>"
CSS-only option
I believe one of the easiest options is to use css white-space: pre-line;
Other answers also mentioned using white-space, but I think it needs a little more information:
In most cases you should probably choose pre-line over pre-wrap. View the difference here.
It's very important to keep in mind about white-space that you should not do something like this:
<p style="white-space: pre-line;">
<%= your.text %>
</p>
It will produce extra spaces and line-breaks in the output. Instead, go with this:
<p style="white-space: pre-line;"><%= your.text %></p>
HTML alternative
Another way is to wrap your text in <pre> tags. And last note on my CSS option is true here as well:
<p>
<pre><%= your.text %></pre>
</p>
Don't separate your text from <pre> tags with spaces or line-breaks.
Final thoughts
After googling this matter a little I have a feeling that html-approach is considered less clean than the css one and we should go css-way. However, html-way seems to be more browser-compatible (supports archaic browsers, but who cares):
pre tag
white-space
The following helper preserves new lines as line breaks, and renders any HTML or Script (e.g Javscript) as plain text.
def with_new_lines(string)
(h(string).gsub(/\n/, '<br/>')).html_safe
end
Use as so in views
<%= with_new_lines #object.some_text %>
I just used white-space: pre-line. So next line (\n) will render it.
You'll need to convert the plain text of the textarea to HTML.
At the most basic level you could run a string replacement:
message_content.gsub! /\n/, '<br />'
You could also use a special format like Markdown (Ruby library: BlueCloth) or Textile (Ruby library: RedCloth).
I was using Ace code-editor in my rails app and i had problem, that whenever i update or create the code, it adds always extra TAB on every line (except first). I couldn't solve it with gsub or javascript replace.. But it accidently solved itself when i disabled layout for that template.
So, i solved it with
render :layout => false

Finding a label with Webrat that contains a link

So I'm doing BDD with Cucumber and have a form with checkboxes populated from a database. The labels for the checkboxes contain hyperlinks. So far, not too exotic (note, this is HAML and not Erb, but it should be readable enough for any Rails person):
I would like my donation to support:
%br
- for podcast in #podcasts
= check_box_tag "donation[podcast_ids][]", podcast.id, true
= donation.label "donation[podcast_ids][]", link_to(podcast.name, podcast.url), :value => podcast.id
%br
The problem is that in my Cucumber features, I can't figure out how to find that checkbox to check it. The relevant part of the story is this:
Scenario: Happy path
Given I am on the home page
When I fill in "My email address" with "john#example.org"
# Skipped for brevity...
And I check the "Escape Pod" podcast
And I check the "PodCastle" podcast
And I press "I'm ready!"
Then I should see "Thank you!"
And there should be 2 podcast donation records
If I'm using the bare webrat_steps.rb file I get the following error:
Could not find field: "Escape Pod" (Webrat::NotFoundError)
I'm quite certain it's because of that link_to() method, which I'm using to make "Escape Pod" a hyperlink to the actual Web site. But I can't easily access link_to from my Cucumber step, and I can't figure out any reasonable way of pointing Webrat at the right checkbox short of kludging up a whole bunch of hyperlink code in my step (which makes it very brittle).
My BDD is stalled at this point. I don't want to take out the link just because it's hard to test. And it feels like it shouldn't be hard to test. Webrat is just limiting what I can pass into the checks() method. Can anyone suggest an elegant answer for this?
The short answer is the to use field_by_xpath or one of the other Webrat::Locators methods to select what element to manipulate in your step:
When(/^I check the "(.+?)" podcast$/) do |name|
check(field_by_xpath("//label/a[.=#{name}]")
end
You might need to play with that xpath a little, or use field_by_id instead. Remember it is looking got the html id of the tag not the id from the database.
Can you post what your HTML looks like in the rendered page near the problematic checkbox(es)? Sometimes you have to play with naming the field... I had all sorts of trouble with a login form... I ended up doing this:
<%= submit_tag 'Enter', {:id => "login_button"} %>
So that the following worked:
Given /^I am logged in as admin$/ do
visit login_path
fill_in "login", :with => "admin"
fill_in "password", :with => "password"
# click_button "login_button"
click_button
end
I know it's not a checkbox example, but maybe fiddling with your name/id/etc will work

Resources