Rails passing the block to the helper method

Viget Labs published an article and gist described in detail the rails helper method for adding a specific class (e.g. .selected or .active ) to a navigation link if it matches the current path.

You can use it in your layout like this:

 = nav_link "News", articles_path, {class: "btn btn-small"} <!-- which creates the following html --> <a href="/articles" class="btn btn-small selected">News</a> 

Nice. I use bootstrap and want to have an icon in my button, so I need to generate the following html:

 <a href="/articles" class="btn btn-small selected"><i class="icon-home"> </i> News</a> 

I branched the gist and figured out a simple way to do this. My fork allows the developer to pass : inner_html and : inner_class to the helper:

 = 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 basic 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 am passing new content_tag parameters inside the link_to method block. I was hoping I could reorganize it in several ways.

First of all, I would prefer to do this in my opinion:

 = nav_link "News", articles_path, {class: "btn btn-small"} do %i.icon-home 

I want to specify the internal html as a block, and not as option hash attributes. Can someone give me any guidance on how to achieve this?

I thought it was a simple case to tell 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 does not display the icon, but instead inserts the number (4). I do not understand this. Anyone got any advice. Where can I go to find out more about this because I really want to be able to draw such things without leaving stackoverflow.

+6
source share
2 answers

The solution at 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 change the 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 updated gist . Perhaps you could hack it to accept more complex blocks.

+2
source

I tried your problem and the following worked fine for me, 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 

Using:

 my_link "No title", User.first do %i.icon-home 
+4
source

Source: https://habr.com/ru/post/922586/


All Articles