How to automatically set all links to nofollow in Rails - ruby-on-rails

I know I can pass :rel => "nofollow" to link_to but is there a way to set that by default so I don't have to make changes in each link_to tag?

In your application helper you can override the link_to method and replace with your own.
def link_to(name, options = {}, html_options = {})
html_options.merge!(:rel => :nofollow)
super(name, options, html_options)
end

You could create an alias to the old link_to then override it so it calls the old alias with the extra parameter. That way, you don't have to change all the existing link_to in your code.

Related

Remove a parameter from URL

I have a link_to method in my Rails app:
link_to t('edit'), edit_building_path(#building, :hidden_action => params[:action])
How do I remove hidden_action from url?
Currently url looks like:
http://localhost:3000/buildings/2/edit?hidden_action=new
My issue is that I need to know from which page user is accessing this link_to.
In rails helper, it depends on you
def edit_the_building_url(building, you_want_the_params_or_not)
if you_want_the_params_or_not
edit_building_path(building, :hidden_action => params[:action])
else
edit_building_path(building)
end
end
then in your controller
link_to t('edit'), edit_the_building_url(#building, true)
or
link_to t('edit'), edit_the_building_url(#building, false)
if above doesn't profit you, just
url = url.chomp("?hidden_action=#{params[:action]}")

sending multiple parameters to another function in ruby

I'm trying to create a function that adds some functionality to the link_to function in rails. What I'd like it to do is simply to add a class to it. What I have so far:
#application_helper.rb
def button_link(*args)
link_to(*args.push(class: 'btn'))
end
Problem is that if I now add another class to the button_link function it doesn't work.
Example:
<td class='button'>
<%= button_link "Show", category_path(item), class: "btn-primary" %>
</td>
I get the following error: wrong number of arguments (4 for 3). How can I do this correctly?
link_to has 4 method signatures.. This is the one used most often.
Below we check to see if a class was already sent in -- and because of how HTML classes work, we want to have multiple classes, which are space-separated values.
def button_link(body, url, html_options={})
html_options[:class] ||= ""
html_options[:class] << " btn"
link_to body, url, html_options
end
The other method signatures can be viewed http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to
Try changing your helper method to this, trying to maintain the link_to form:
def button_link(name, url_options, html_options = {})
if html_options.has_key?(:class)
css_options = html_options.fetch(:class)
css_options << ' current'
html_options.merge!( { :class => css_options } )
else
html_options.merge!( { :class => ' btn' } )
end
link_to(name, url_options, html_options)
end

Rails passing a block to a helper method

Viget Labs posted an article and gist detailing a rails helper method for adding a particular class (like .selected or .active) to a navigation link if it's url matches the current path.
You can use it in your layout like so:
= nav_link "News", articles_path, {class: "btn btn-small"}
<!-- which creates the following html -->
News
Nice. I'm using bootstrap, and want to have an icon in my button, so I need to generate the following html:
<i class="icon-home"> </i> News
I forked the gist and figured out a simple way of doing it. My fork lets the developer pass :inner_html and :inner_class to the helper like so:
= nav_link "News", articles_path, {class: "btn btn-small"}, {inner_html: 'i', inner_class: 'icon-home'}
It works fine, but I don't like my underlying implementation:
def link
if #options[:inner_html]
link_to(#path, html_options) do
content_tag(#options[:inner_html], '', :class => #options[:inner_class]) + " #{#title}"
end
else
link_to(#title, #path, html_options)
end
end
As you can see, I'm passing the new options to content_tag inside the block of a link_to method. I was hoping I would be able to refactor it in a few ways.
First of all, I'd prefer to be able to do this in my view:
= nav_link "News", articles_path, {class: "btn btn-small"} do
%i.icon-home
I want to give the inner html as a block, and not as attributes of the option hash. Can anyone give me any pointers on how to achieve this?
I thought it would a simple case of telling the nav_link method to accept a block:
def nav_link(title, path, html_options = {}, options = {}, &block)
LinkGenerator.new(request, title, path, html_options, options, &block).to_html
end
class LinkGenerator
include ActionView::Helpers::UrlHelper
include ActionView::Context
def initialize(request, title, path, html_options = {}, options = {}, &block)
#request = request
#title = title
#path = path
#html_options = html_options
#options = options
#block = block
end
def link
if #block.present?
link_to #path, html_options do
#block.call
#title
end
end
end
But this fails to output the icon, and instead inserts a number (4). I don't get it clearly. Anyone got any advice. Where can I go to read more about this sort of thing, as I really want to be able to figure stuff like this out without having to ask on stackoverflow.
I tried your problem and the following worked for me perfectly, in the helper:
def my_link(title, path, &block)
if block_given?
link_to path do
block.call
concat(title)
end
else
link_to title, path
end
end
Usage:
my_link "No title", User.first do
%i.icon-home
The solution in the end was as follows:
# capture the output of the block, early on if block_given?
def nav_link(title, path, html_options = {}, options = {}, &block)
LinkGenerator.new(request, title, path, html_options, options, (capture(&block) if block_given?)).to_html
end
I also had to modify my link method:
def link
if #block.present?
link_to(#path, html_options) do
#block.concat(#title)
end
else
link_to(#title, #path, html_options)
end
end
I've updated my gist. You could probably hack it up to accept more complex blocks.

how to create custom helper with class (css) options in rails

I want to create helper that return the avatar linked to the user.
for that i do:
<%= basic_avatar(user)%>
and the helper:
def basic_avatar(user)
link_to image_tag(user.avatar) ,'#', :title => user.name
end
But now, i want to add some options like attributes, classes etc.
for example, i want to do this:
<%= basic_avatar(user, class: 'avatar')%>
or:
<%= basic_avatar(user, class: 'avatar', name: 'avatar')%>
Just add an options hash to helper declaration, and use that when making your image tag. The last argument in the image_tag call is a hash, so you're basically all set.
def basic_avatar(user, options={})
link_to image_tag(user.avatar), "#", options.merge(:title => user.name)
end
This makes it so the options is optional, and then they just get passed along to image_tag, as well as the title you want.

Rail3 - Smart way to Display Menu & add an Active Style Class?

Given a Rails 3 App with a menu like:
<ul>
<li>Home</li>
<li>Books</li>
<li>Pages</li>
</ul>
What is a smart way in Rails to have the app know the breadcrumb,,, or when to make one of the LIs show as:
<li class="active">Books</li>
thx
I'm not sure if I will provide you with a smart way but better something than nothing...
If your menu has some links - it is not in your example but I suppose that real menu should have links, not just the items. For example something like this in HAML: (I'm using HAML as writing ERB in text area is pure hell)
%ul
%li= link_to "Home", :controller => "home"
%li= link_to "Books", :controller => "books"
%li= link_to "Pages", :controller => "pages"
Then this helper (pasted from my project) should come handy:
#
# Shows link with style "current" in case when the target controller is same as
# current
# beware: this helper has some limitation - it only accepts hash as URL parameter
#
def menu_link_to(title, url, html_options = {})
unless url.is_a?(Hash) and url[:controller]
raise "URL parameter has to be Hash and :controller has to be specified"
end
if url[:controller] == controller.controller_path
html_options[:class] = "current"
end
link_to(title, url, html_options)
end
With this helper you can replace your "link_to" in the code above with "menu_link_to" and that's it!
An modified version of Radek Paviensky's helper is a tad simpler and more similar to link_to.
# Shows link with style "current" in case when the target controller is same as
# current.
def menu_link_to(title, options = {}, html_options = {})
if current_page?(options)
html_options[:class] ||= []
html_options[:class] << "active" # #TODO catch cases where the class is passed as string instead of array.
end
link_to(title, options, html_options)
end

Resources