【问题标题】:Rails passing a block to a helper methodRails 将块传递给辅助方法
【发布时间】:2012-08-07 19:54:09
【问题描述】:

Viget Labs 发布了 an articlegist 详细说明了一个 rails 辅助方法,用于将特定类(如 .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>

很好。我正在使用引导程序,并且希望在我的按钮中有一个图标,所以我需要生成以下 html:

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

forked the gist 想出了一个简单的方法。我的 fork 让开发人员将 :inner_html:inner_class 传递给帮助程序,如下所示:

= nav_link "News", articles_path, {class: "btn btn-small"}, {inner_html: 'i', inner_class: 'icon-home'}

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

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

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

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

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

我想将内部 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

但这无法输出图标,而是插入了一个数字 (4)。我不太清楚。任何人都得到任何建议。我可以去哪里阅读更多关于这类事情的信息,因为我真的希望能够弄清楚这样的事情而不必在 stackoverflow 上询问。

【问题讨论】:

  • do %i.icon-home 你的块让我失望了。你希望它如何工作?

标签: ruby-on-rails


【解决方案1】:

最终解决方案如下:

# 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

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

def link
  if @block.present?
    link_to(@path, html_options) do
      @block.concat(@title)
    end
  else
    link_to(@title, @path, html_options)
  end
end

我更新了我的gist。您可能可以破解它以接受更复杂的块。

【讨论】:

    【解决方案2】:

    我在帮助程序中尝试了您的问题,以下对我来说非常有效:

      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
    

    用法:

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

    【讨论】:

    • 感谢您的回答,很有帮助。我最终会发布我使用的解决方案,但你的回答让我走到了一半。再次感谢。
    猜你喜欢
    • 1970-01-01
    • 2019-05-05
    • 1970-01-01
    • 2012-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多