【问题标题】:Rails using included helpers inside class methodsRails 在类方法中使用包含的帮助器
【发布时间】:2011-06-09 23:30:58
【问题描述】:

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

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 >

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    如果没有看到您的帮助代码就很难判断,但是include 会将该模块中的所有方法插入到您包含的类的instances 中。 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 还有很多其他有用的功能,例如允许您定义在包含模块时回调的块。

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

    【讨论】:

    • 如果我们需要这些功能,我们可以用帮助器扩展类吗?
    【解决方案2】:

    对于任何想要在类级别库或模型中使用一些自定义助手的人,有时不值得包含所有助手。而是直接调用它:

    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

    【讨论】:

      【解决方案3】:

      我遇到了同样的问题。这是我的解决方法,

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

      感谢RailsForum

      【讨论】:

      • 非常直接的解决方案.. 谢谢 :)
      • 这不是我的问题,所以我不能接受你的回答。 :(
      【解决方案4】:

      我也遇到了同样的问题。就我而言,将include 替换为extend 就可以了。

      class MyClass
        extend ActionView::Helpers::NumberHelper
        ...
      end
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-09-06
        • 1970-01-01
        • 1970-01-01
        • 2020-04-24
        • 1970-01-01
        • 2011-08-14
        • 1970-01-01
        • 2018-11-06
        相关资源
        最近更新 更多