Rails在类方法中使用包含的帮助器

时间:2011-06-09 23:30:58

标签: ruby-on-rails ruby

有人知道为什么包含的方法在类方法中不起作用吗?

class MyClass
  include ActionView::Helpers::NumberHelper

  def test
    puts "Uploading #{number_to_human_size 123}"
  end

  def self.test
    puts "Uploading #{number_to_human_size 123}"
  end
end


ree-1.8.7-2011.03 :004 > MyClass.new.test
Uploading 123 Bytes
 => nil 
ree-1.8.7-2011.03 :005 > MyClass.test
NoMethodError: undefined method `number_to_human_size' for MyClass:Class
    from /path/to/my/code.rb:9:in `test'
    from (irb):5
ree-1.8.7-2011.03 :006 >

4 个答案:

答案 0 :(得分:11)

对于想要在类级别lib或模型中使用某些自定义帮助程序的人来说,有时包含所有帮助程序是不值得的。相反,直接调用它:

class MyClass
  def test
    ::ApplicationController.helpers.number_to_human_size(42)
  end
end

(取自http://makandracards.com/makandra/1307-how-to-use-helper-methods-inside-a-model

答案 1 :(得分:7)

我遇到了同样的问题。这就是我如何解决它,

helper = Object.new.extend(ActionView::Helpers::NumberHelper)
helper.number_to_human_size(1000000)

感谢RailsForum

答案 2 :(得分:6)

在没有看到帮助程序代码的情况下很难判断,但是include会将该模块中的所有方法插入到您包含的类的实例中。 extend用于将方法带入。因此,如果您只是在NumberHelper中定义了方法,那么这些方法将放在MyClass的所有实例上,而不是类。

许多Rails扩展的工作方式是使用已整合到ActiveSupport :: Concern中的技术。 Here是一个很好的概述。

基本上,在模块中扩展ActiveSupport :: Concern将允许您在名为ClassMethods和InstanceMethods的子模块中指定要将哪些函数添加到包含模块的类和实例中。例如:

module Foo
    extend ActiveSupport::Concern
    module ClassMethods
        def bar
            puts "I'm a Bar!"
        end
    end
    module InstanceMethods
        def baz
            puts "I'm a Baz!"
        end
    end
end

class Quox
    include Foo
end

Quox.bar
=> "I'm a Bar"
Quox.new.baz
=> "I'm a Baz"

我之前使用过这个来做类似定义ClassMethods中的bar函数,然后通过定义一个只调用this.class.bar的同名的bar方法使它可用于实例,使它可以从两个调用。 ActiveSupport :: Concern还有很多其他有用的东西,比如允许你定义在包含模块时回调的块。

现在,这发生在这里特别是因为你include你的助手,这可能表明这个功能比助手更通用 - 助手只会自动包含在视图中,因为它们仅用于帮助查看。如果您想在视图中使用帮助器,可以使用类中的helper_method宏来使该方法对您的视图可见,或者更好的是,如上所述制作模块,而不是将其视为帮助器,但是使用include将它混合到你想要使用它的类中。我想我会走那条路 - 没有什么说你不能在NumberHelper中创建一个HumanReadableNumber模块和include来制作它它可以在您的视图中轻松使用。

答案 3 :(得分:0)

我面临着同样的问题。就我而言,将df1 = df.drop_duplicates(['nameid_index', 'projectid_index']).merge(df_copy) 替换为include即可使其工作。

extend