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

Bri*_*ong 8 ruby ruby-on-rails

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

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

lul*_*ala 11

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

class MyClass
  def test
    ::ApplicationController.helpers.number_to_human_size(42)
  end
end
Run Code Online (Sandbox Code Playgroud)

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


Swa*_*rla 7

我遇到了同样的问题.这就是我解决它的方式,

helper = Object.new.extend(ActionView::Helpers::NumberHelper)
helper.number_to_human_size(1000000)
Run Code Online (Sandbox Code Playgroud)

感谢RailsForum.


Mat*_*att 6

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

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

从本质上讲,在模块中扩展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"
Run Code Online (Sandbox Code Playgroud)

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

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