Rails将块传递给辅助方法

ste*_*och 6 ruby-on-rails

Viget的实验室发布的文章要点,详细说明增加一个特别的类(如导轨辅助方法,.selected.active)的导航链接,如果它的URL当前路径相匹配.

您可以在布局中使用它,如下所示:

= nav_link "News", articles_path, {class: "btn btn-small"}

<!-- which creates the following html -->

<a href="/articles" class="btn btn-small selected">News</a>
Run Code Online (Sandbox Code Playgroud)

尼斯.我正在使用bootstrap,并希望在我的按钮中有一个图标,所以我需要生成以下html:

<a href="/articles" class="btn btn-small selected"><i class="icon-home"> </i> News</a>
Run Code Online (Sandbox Code Playgroud)

分享了要点并想出了一个简单的方法.我的fork允许开发人员将:inner_html:inner_class传递给helper,如下所示:

= nav_link "News", articles_path, {class: "btn btn-small"}, {inner_html: 'i', inner_class: 'icon-home'}
Run Code Online (Sandbox Code Playgroud)

它工作正常,但我不喜欢我的底层实现:

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
Run Code Online (Sandbox Code Playgroud)

如您所见,我将新选项传递content_tag给link_to方法的块内部.我希望我能够通过几种方式重构它.

首先,我希望能够在我看来做到这一点:

= nav_link "News", articles_path, {class: "btn btn-small"} do
  %i.icon-home
Run Code Online (Sandbox Code Playgroud)

我想将内部html作为块,而不是选项哈希的属性.任何人都可以给我任何关于如何实现这一点的指示?

我认为告诉nav_link方法接受一个块是一个简单的例子:

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
Run Code Online (Sandbox Code Playgroud)

但是这无法输出图标,而是插入一个数字(4).我不清楚.任何人都有任何建议.我在哪里可以阅读更多有关此类事情的内容,因为我真的希望能够在不必询问stackoverflow的情况下找出这样的内容.

Mat*_*tzi 5

我尝试了你的问题,并且在助手中以下内容对我来说非常有效:

  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
Run Code Online (Sandbox Code Playgroud)

用法:

my_link "No title", User.first do
  %i.icon-home 
Run Code Online (Sandbox Code Playgroud)


ste*_*och 2

最终解决方案如下:

# 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
Run Code Online (Sandbox Code Playgroud)

我还必须修改我的链接方法:

def link
  if @block.present?
    link_to(@path, html_options) do
      @block.concat(@title)
    end
  else
    link_to(@title, @path, html_options)
  end
end
Run Code Online (Sandbox Code Playgroud)

我已经更新了我的要点。您可能可以对其进行修改以接受更复杂的块。