使用instance_eval从块访问控制器的实例变量

时间:2014-02-03 23:47:21

标签: ruby-on-rails block

我正在为我的Ruby on Rails应用程序制作一个面包屑模块​​,但我想要一个特定的语法 - 我认为Rails开发人员看起来很好看且更直观。

这是交易:

class WelcomeController < ApplicationController

  breadcrumb_for :index, :text => 'Home', :href => -> { root_path }

  def index
  end
end

看,它很整洁。

您可以安全地忽略除proc之外的所有内容 - 我分配给:href密钥的内容。

我使用instance_eval,以便在评估proc时,它可以访问root_path帮助程序。

它有效。上面的例子没问题。但是,我想使用实例变量,但这不起作用。

像这样:

class WelcomeController < ApplicationController

  breadcrumb_for :index, :text => 'Home', :href => -> { @path }

  def index
    @path = root_path
  end
end

现在,proc上下文@pathnil

我该怎么做才能从块中访问实例变量?

以下是我模块的所有代码。请注意,当我“处理”块并使用instance_eval(也就是调用我的模块的#breadcrumb)时,应该已经评估了操作,因此实例变量@path应该已经存在。

module Breadcrumb
  extend ActiveSupport::Concern

  included do
    cattr_accessor(:_breadcrumb) { [] }

    helper_method :breadcrumb

    def self.breadcrumb_for(*args)
      options = args.pop
      _breadcrumb.push([args, options])
    end
  end

  def breadcrumb
    @breadcrumb ||= self._breadcrumb.map do |item|
      puts item

      if item[0].include?(params[:action]) || item[0][0] == '*'

        text, href = item[1].values_at(:text, :href)

        if text.respond_to?(:call)
          text = instance_eval(&text)
        end

        if href.respond_to?(:call)
          href = instance_eval(&href)
        end

        [text, href]
      end
    end
  end
end

1 个答案:

答案 0 :(得分:0)

哦不。我很惭愧地说,但这是我的错。上面的代码运行得很好,我在我的应用程序中使用了不同的变量名,在我在问题中使用的摘录中没有显示。

非常感谢,我会把它留在这里作为参考。