Truncate & Simple Format String in Ruby on Rails - ruby-on-rails

I am trying to take a string and render it with simple_format while at the same time truncating it. It works when I just use one or the other, but not when I do both. Why is this not doing simple_format and truncating simultaneously.
Controller
myString = "Apple’s New Laptop"
View
<%= simple_format truncate( myString, :length => 20 ) %>

The way to do this is to truncate after you have used simple_format on the string. Since truncate escapes the string by default, you have to use the escape: false option.
> myString = "Apple’s New Laptop"
> truncate(simple_format(myString), escape: false)
> => "<p>Apple’s New Laptop..."
> truncate(simple_format(myString), escape: false, length: 19)
> => "<p>Apple’s..."
This has the potential to create unbalanced HTML tags by cutting the </p> for example, so use carefully.

There was something changed in the truncate-helper in Rails 4.
The documentation does tells us:
The result is marked as HTML-safe, but it is escaped by default, unless :escape is false.
http://apidock.com/rails/v4.0.2/ActionView/Helpers/TextHelper/truncate
Rails normally escapes all strings. If you just want to put some unicode chars in strings in your code, you can do it by using the \u notation with the hexadecimal code. Then truncate will also count the char as exactly one char.
myString = "Apple\u2019s New Laptop"

This might be late but useful to someone else. This worked for me.
<%= truncate(myString, escape: false, length: 20 ) %>

Related

How to write correctly <%= t('.title_#{Time.now.wday}') %>?

Usually to add a word (for my multilanguage website) I use this system: <%= t('.title') %>
Now in config/locales/en.yml, I added something like this:
en:
home:
title: Title
title_0: Finally Sunday! Watch this title
title_1: Hey! It's monday! This is the Title
And I want to use Time.now.wday and to create something like <%= t('.title_#{Time.now.wday}') %>
But it doesn't work. How to write it correctly?
That's because you need double quotes for string interpolation in Ruby. Just replace
<%= t('.title_#{Time.now.wday}') %>
for
<%= t(".title_#{Time.now.wday}") %>
although it maybe should be
<%= t("home.title_#{Time.now.wday}") %>
because title, title_0 and title_1 are nested under home
Interpolation does not work with single quotes
That means that:
puts "Works in double quoted strings: #{1 + 2}."
puts 'Not not work in single quoted strings: #{1 + 2}.'
will print out:
"Works in double quoted strings: 3."
"Does not work in single quoted strings: #{1 + 2}."
source: http://ruby-for-beginners.rubymonstas.org/bonus/string_interpolation.html

How to replace Space with Line Break in Ruby on Rails?

I am trying to replace Space in a string with Line Break in Ruby on Rails,
name = 'john smith'
i have tried the following so far:
name.gsub!(" ", "\n")
name.gsub!(" ", "<br>")
name.sub(" ", "\n")
name.sub(" ", "<br>")
but none of the above worked.
You have to be careful when marking a string as html_safe, especially if it may contain user input:
name = 'john smith<script>alert("gotcha")</script>'
name.gsub(' ', '<br>').html_safe
#=> "john<br>smith<script>alert(\"gotcha\")</script>"
Rails would output that string as-is, i.e. including the <script> tag.
In order to take advantage of Rails' HTML escaping, you should only mark the trusted parts as being html_safe. For a manually concatenated string:
''.html_safe + 'john' + '<br>'.html_safe + 'smith<script>alert("gotcha")</script>'
#=> "john<br>smith<script>alert("gotcha")</script>"
As you can see, only the <br> tag was left intact, the remaining parts were properly escaped.
There are several helpers for building safe strings as well as for building HTML tags. In your case, I'd use safe_join and tag:
name = 'john smith<script>alert("gotcha")</script>'
safe_join(name.split(' '), tag(:br))
#=> "john<br />smith<script>alert("gotcha")</script>"
While printing it in html you will need to use raw, otherwise rails will escape the tags
= raw name.gsub(" ", "<br>")
Try another one:
<%= name.gsub(" ", "<br>").html_safe %>
html_safe :
Marks a string as trusted safe. It will be inserted into HTML with no additional escaping performed.
"<a>Hello</a>".html_safe
#=> "<a>Hello</a>"
nil.html_safe
#=> NoMethodError: undefined method `html_safe' for nil:NilClass
raw :
raw is just a wrapper around html_safe. Use raw if there are chances that the string will be nil.
raw("<a>Hello</a>")
#=> "<a>Hello</a>"
raw(nil)
#=> ""

Rails truncate helper with link as omit text

I'm quite long description that I want to truncate using truncate helper.
So i'm using the:
truncate article.description, :length => 200, :omission => ' ...'
The problem is that I want to use more as a clickable link so in theory I could use this:
truncate article.description, :length => 200, :omission => "... #{link_to('[more]', articles_path(article)}"
Omission text is handled as unsafe so it's escaped. I tried to make it html_safe but it didn't work, instead of link [more] my browser is still showing the html for that link.
Is there any way to force truncate to print omission link instead of omission text?
I would suggest doing this on your own in a helper method, that way you'll have a little more control over the output as well:
def article_description article
output = h truncate(article.description, length: 200, omission: '...')
output += link_to('[more]', article_path(article)) if article.description.size > 200
output.html_safe
end
With Rails 4, you can/should pass in a block for the link:
truncate("Once upon a time in a world far far away",
length: 10,
separator: ' ',
omission: '... ') {
link_to "Read more", "#"
}
Dirty solution... use the method "raw" to unescape it.
you have to be sure of "sanity" of your content.
raw(truncate article.description, :length => 200, :omission => "... #{link_to('[more]', articles_path(article)}")
raw is a helper acting like html_safe .
bye
edit: is not the omission of being escaped , but the result of truncate method.
I encountered a similar situation and this did the trick. Try (line breaks for readability):
(truncate h(article.description),
:length => 200,
:omission => "... #{link_to('[more]',articles_path(article)}")
.html_safe
You can use h to ensure sanity of article description, and since you are setting the link_to to a path you know to not be something potentially nefarious, you can mark the resulting string as html_safe without concern.
TextHelper#truncate has a block form of truncate, which lets you use a link_to that isn't escaped, while still escaping the truncated text:
truncate("<script>alert('hello world')</script>") { link_to "Read More", "#" }
#=> <script>alert('hello world'...Read More
The only one that worked for me :
<%= truncate(#article.content, length: 200, omission: " ... %s") % link_to('read more', article_path(#article)) %>
I had the same problem, in my case i just used :escape => false.
That worked:
truncate article.description, :length => 200, :omission => "... #{link_to('[more]', articles_path(article)}", :escape => false
From documentation :
The result is marked as HTML-safe, but it is escaped by default, unless :escape is false....
link: http://apidock.com/rails/ActionView/Helpers/TextHelper/truncate

How can I limit the amount of words displayed from a Ruby string?

the Ruby code is below:
<%= product.advert_text -%>
What script can limit the amount of words?
Since you are working with Rails, you can use the truncate method.
So, something like:
<%= truncate(product.advert_text, :length => 20) -%>
The :length option sets the # of characters to truncate at & will add ellipses at the end (you can override the default ellipses with the :omission option - see the documentation on my link).
If you want to limit to a certain number of words, the easiest way is going to be to split on space and then join the desired number of words back into a string.
<%=product.advert_text.split.slice(0, limit).join(" ") -%>

Rails escape_javascript creates invalid JSON by escaping single quotes

The escape_javascript method in ActionView escapes the apostrophe ' as backslash apostrophe \', which gives errors when parsing as JSON.
For example, the message "I'm here" is valid JSON when printed as:
{"message": "I'm here"}
But, <%= escape_javascript("I'm here") %> outputs "I\'m here", resulting in invalid JSON:
{"message": "I\'m here"}
Is there a patch to fix this, or an alternate way to escape strings when printing to JSON?
Just call .to_json on a string and it will be escaped properly e.g.
"foo'bar".to_json
I ended up adding a new escape_json method to my application_helper.rb, based on the escape_javascript method found in ActionView::Helpers::JavaScriptHelper:
JSON_ESCAPE_MAP = {
'\\' => '\\\\',
'</' => '<\/',
"\r\n" => '\n',
"\n" => '\n',
"\r" => '\n',
'"' => '\\"' }
def escape_json(json)
json.gsub(/(\\|<\/|\r\n|[\n\r"])/) { JSON_ESCAPE_MAP[$1] }
end
Anyone know of a better workaround than this?
May need more details here, but JSON strings must use double quotes. Single quotes are okay in JavaScript strings, but not in JSON.
I had some issues similar to this, where I needed to put Javascript commands at the bottom of a Rails template, which put strings into jQuery.data for later retrieval and use.
Whenever I had a single-quote in the string I'd get a JavaScript error on loading the page.
Here is what I did:
-content_for :extra_javascript do
:javascript
$('#parent_#{parent.id}').data("jsonized_children", "#{escape_javascript(parent.jsonized_children)}");
Already there is an issue in github/rails
https://github.com/rails/rails/issues/8844
Fix to mark the string as html_safe
<%= escape_javascript("I'm here".html_safe) %>
or even better you can sanitize the string
<%= sanitize(escape_javascript("I'm here")) %>
<%= escape_javascript(sanitize("I'm here")) %>

Resources