Creating a link with link_to and gsub - ruby-on-rails

I have a body of text being fed into a textarea and if any of the text matches URI.regexp, I need to make that link active with a target: '_blank' on the a tag in the textarea.
Here is my current code. I also tried this with .match which would correc
def comment_body(text)
text = auto_link(text)
text.gsub!(URI.regexp) do |match|
link_to(match, match, target: '_blank')
end
end
This outputs:
https://facebook.com">https://facebook.com in my view
and
https://facebook.com in the inspected HTML.
In the gsub docs it says that metacharacters will be interpreted literally, which is what I believe is messing me up here.
Any tips on how to properly construct this URL?
Thanks!

The auto_link gem does exactly what you need.
You can look at its code to see how its using gsub.

EDIT: this solution requires setting sanitize to false, which often is not a good idea!
I've found a solution without using auto_link (I'm using Rails 5 too). I know this is an oldish thread but I've spent some time trying to find a solution that would allow the insertion of target="_blank" and found this. Here I'm creating a helper to search text in a text box for links and then add essentially make them linkable in the view.
def formatted_comment(comment)
comment = comment.body
URI.extract(comment, ['http', 'https']).each do |uri|
comment = comment.gsub( uri, link_to(uri, uri, target: "_blank"))
end
simple_format(comment, {}, class: "comment-body", sanitize: false)
end
The key thing here was simple_format kept sanitizing, so it's important to add both {} and sanitize:false.
***Note that setting sanitize to false may bring up other issues like allowing javascript to run in a comment, but this solution will allow the insertion of target="_blank" into a link.

One solution using just a simple gsub with back references would be something like this: (You can certainly modify the regex to meet your needs.)
str = 'here is some text about https://facebook.com and you really http://www.google.com should check it out.'
linked_str = str.gsub( /((http|https):\/\/(www.|)(\w*).(com|net|org))/,
'\4' )
Example output:
print linked_str
#=> here is some text about facebook and you really google should check it out.

Related

rails 5.x: add nofollow to all links in 'sanitize'

I am working on a Rails application whose HAML templates frequently make use of a routine called sanitize. I have deduced from context that this routine sanitizes user-controlled HTML. Example:
# views/feed_items/_about.html.haml
%h3 Summary:
.description
= sanitize #feed_item.description
I want to make this routine add 'rel=nofollow' to all outbound links, in addition to what it's already doing. What is the most straightforward way to do that?
N.B. I am not having any luck finding the definition of this method, or the official configuration knobs for it. The vendor directory has two different HTML sanitizer gems in it and I can't even figure out which one is being used. This is a large, complicated web application that I did not write, and I barely understand Ruby, let alone all of Rails' extensions to it. Please assume I do not know any of the things that you think are obvious.
The sanitizer will strip out the rel tags if they exist.
I ran into a similar issue and added an additional helper method - clean_links to the ApplicationHelper module, and called it after sanitizing the content.
# application_helper.rb
def clean_links html
html.gsub!(/\\2')
html.html_safe
end
This method looks for all <a> tags, and adds rel="nofollow". The html_safe method is necessary or else the HTML will be displayed as a string (it's already been sanitized).
This solution treats all links equally, so if you only want this for links pointing outside the domain, you'll have to update the REGEX accordingly.
In your view: <%= clean_links sanitize(#something) %>
So, first the content is sanitized, then you add the rel="nofollow" tag before displaying the link.
Actually there's a built-in way:
sanitize "your input", scrubber: Loofah::Scrubbers::NoFollow.new

Rails 4: how to insert line breaks in text_area?

I have created a blog in rails. I'm a beginner and got quite far, but now I'm stuck with a seemingly minor detail: I can't seem to format the posts (articles).
Here's the relevant part of my show.html.erb:
<p>
<strong>Content:</strong>
<%= simple_format (#article.content) %>
</p>
When I write something and insert html-tags, they are not recognized as such. What am I doing wrong?
Rails will automatically remove html tags to prevent someone from injecting code into your webpage (e.g. malicious javascript)
If your users cannot enter data into #article.content and it's always safe then you can flag it as safe usng the html_safe method.
<%= (simple_format (#article.content)).html_safe %>
Can you post the article content for reference? If I had to guess, I'd imagine Rails is escaping the html tags and inserting them as plain text (so the output looks like: Article content !
Take a look at Rails' helper methods like content_tag (http://apidock.com/rails/ActionView/Helpers/TagHelper/content_tag) and concat (http://apidock.com/rails/ActionView/Helpers/TextHelper/concat) and consider using those to help with generating the appropriate html tags.
An issue to be concerned with is who's going to be supplying the content. For example, if you're writing an application that other people will use, you want to make sure any html give you is escaped to avoid XSS attacks. In that case, you'll want to spend some time reading about how to properly sanitize user input.
You can now specify the tag it gets wrapped in (defaults to p) like so:
<%= simple_format (#article.content, {}, wrapper_tag: "div") %>
or
add white-space: pre-line style.
It will display \r or \n (enter) in user input as a new line.
for more info:
http://apidock.com/rails/v4.0.2/ActionView/Helpers/TextHelper/simple_format

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).

Disable XSS and HTML Sanitization in Rails 3

I'm having an issue where when I have the contents of my rich text editor saved into the database using activerecord the html content is stripped of the html contents (I think it fires html_safe on it). I tried overriding the html_safe method on the content string, but nothing works.
content = "<p>hello</p>"
#article.content = content
puts #article.content # "<p>hello</p>"
#article.save
puts #article.content # "<>hello</>"
How can you override the html stripping capabilities in activerecord for a particular column?
As frank blizzard already said in his answer, you make your self vulnerable two XSS-Attacks.
But if you trust your authors, that this columns are safe two display, you can do something like this in your Article model
class Article < ActiveRecord::Base
def content
attributes[:content].html_safe
end
end
You can use the raw(string) method, but it would make you vunlerable against XSS attacks.
Another option would be taking a deeper look into markdown.
Turns out the issue to this problem was nothing todo with Rails or the XSS stripping. The code that I had was modifying a string and then saving the results elsewhere which was causing the original input to be changed. I solved the problem by using string.dup to copy over the original string so that I wasn't affected.
There should be an option for this.
I encourage you to take a look at the docs of the rich text editor that you are using.

rails 3 is printing html tags to screen instead of rendering them

I'm using vhochstein's fork of active_scaffold, which runs quite nicely on rails 3, except for a few small bugs - http://github.com/vhochstein/active_scaffold.
In rails 2.3, the following code disables a link:
return "<a class='disabled'>#{text}</a>" unless authorized
But in Rails 3, it causes the escaped html tags to be printed out instead as in the following photo:
How can I make the content of this return statement render the way it should in rails 3?
The code above, is from the list_column_helpers.rb file in vendor/plugins/active_scaffold/helpers/
UPDATE:
Floatless fixed this by suggesting to add .html_safe to the code.
I have since found that the folowing change also needs to be made as there's more than one bit of code that is respondible for disabling action links in active_Scaffold:
In /plugins/active_scaffold/frontends/default/views/_list_actions.html.erb change:
<%= record.authorized_for?(:crud_type => etc etc etc -%>
By making it use "raw"
i.e.
<%= raw record.authorized_for?(:crud_type => etc etc etc -%>
Anyway, thanks to floatless and hopefully mr hochstein will be able to use this stuff.
Try this:
return "<a class='disabled'>#{text}</a>".html_safe unless authorized

Resources