Rails / lib模块和

时间:2009-07-02 08:00:40

标签: ruby-on-rails ruby class module

我正在为open_flash_chart插件编写自定义包装器。它放在/lib中,并将其加载为ApplicationController中的模块。

但是,我有一些Class层次结构或smth问题。

在任何控制器中,我都可以open_flash_chartOpenFlashChart等访问Line个功能

但是,在/lib模块中的一个类中,它不起作用!

有什么想法吗?

5 个答案:

答案 0 :(得分:145)

有两种方法可以在Rails中加载文件:

  • 它在自动加载过程中注册,您引用与文件名对应的常量。例如,如果您有app/controllers/pages_controller.rb和引用PagesController,则会自动加载app/controllers/pages_controller.rb。对于加载路径中的预设目录列表,会发生这种情况。这是Rails的一个特性,不属于正常的Ruby加载过程。
  • 文件明确require d。如果文件是require d,Ruby会查看加载路径中的整个路径列表,并找到第一种情况,即require d文件位于加载路径中。您可以通过检查$ LOAD_PATH($:的别名)来查看整个加载路径。

由于lib位于加载路径中,因此您有两个选项:使用与常量相同的名称命名文件,因此当您引用相关常量或明确要求时,Rails会自动选择它们模块。

我也注意到你可能会对另一件事情感到困惑。 ApplicationController 系统中的根对象。观察:

module MyModule
  def im_awesome
    puts "#{self} is so awesome"
  end
end

class ApplicationController < ActionController::Base
  include MyModule
end

class AnotherClass
end

AnotherClass.new.im_awesome
# NoMethodError: undefined method `im_awesome' for #<AnotherClass:0x101208ad0>

您需要将模块包含在您想要使用它的任何类中。

class AnotherClass
  include MyModule
end

AnotherClass.new.im_awesome
# AnotherClass is so awesome

当然,为了能够首先包含该模块,您需要使用它(使用上述任何一种技术)。

答案 1 :(得分:84)

在Rails 3 / lib模块中不会自动加载。

这是因为行:

# config.autoload_paths += %W(#{config.root}/extras)

在config / application.rb中注释。

你可以尝试取消注释这一行,或者(对我来说效果更好),留下这个评论(以备将来参考)并添加这两行:

config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]

答案 2 :(得分:21)

除了取消注释config.autoload_paths(我在Rails 3.1.3上)之外,对我有用的是创建一个这样的初始化器:

#config/initializers/myapp_init.rb
require 'my_module'    
include MyModule

这样我就可以从任何地方调用mymodule方法 ,作为类方法Model.mymodule_method或实例方法mymodel.mymodule_method

也许某位专家可能会解释这一点的含义。到现在为止,使用它需要您自担风险。

编辑:之后,我认为更好的approuch将是:

创建一个这样的初始化器:

#config/initializers/myapp_init.rb
require ‘my_module’

在需要的地方加入模块,如下所示:

1)如果你想将它用作“类方法”,请使用“extend”:

class Myclass < ActiveRecord::Base
   extend MyModule
   def self.method1
      Myclass.my_module_method
   end
end

2)如果要将其用作“实例方法”,请将其包含在类定义中:

class Myclass < ActiveRecord::Base
include MyModule
   def method1
      self.my_module_method 
   end
end

3)请记住include MyModule是指您的加载路径中必须首先需要的文件my_module.rb

答案 3 :(得分:2)

在模型和控制器中使用模块lib/my_module.rb

config/application.rb

config.watchable_dirs['lib'] = [:rb]

在你的模型中(对你的控制器来说类似的想法):

require_dependency 'my_module'

class MyModel < ActiveRecord::Base
  include MyModule

  MyModule.some_method
end

此方法在http://hakunin.com/rails3-load-paths

中有更详细的描述

答案 4 :(得分:0)

可能是您希望在应用程序初始化时在lib目录下显式加载文件的情况。
在我的config / application.rb中,我有一个条目, config.autoload_paths += %W(#{config.root}/lib)

也可能是模块名称/层次结构与它位于文件或位置/文件名与该层次结构不同,因此也无法自动加载该文件。所以当我在config / application.rb底部添加一个条目时,为 require "./lib/file_name_without_extention ,它工作正常。