Rails/lib模块和

Man*_*tas 81 ruby module ruby-on-rails class

我正在为open_flash_chart插件编写自定义包装器.它被放入/lib并作为模块加载ApplicationController.

但是,我有一些类层次结构或smth问题.

从任何控制器我可以访问open_flash_chart的功能OpenFlashChart,Line等等

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

有任何想法吗?

Yeh*_*atz 146

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

  • 它在自动加载过程中注册,并引用与文件名对应的常量.例如,如果你有app/controllers/pages_controller.rb和引用PagesController,app/controllers/pages_controller.rb将自动加载.对于加载路径中的预设目录列表,会发生这种情况.这是Rails的一个特性,并不是普通Ruby加载过程的一部分.
  • 文件是明确的required.如果一个文件被require剐,红宝石看起来通过在负载路径路径的整个列表,并找到你的文件,第一种情况下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>
Run Code Online (Sandbox Code Playgroud)

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

class AnotherClass
  include MyModule
end

AnotherClass.new.im_awesome
# AnotherClass is so awesome
Run Code Online (Sandbox Code Playgroud)

当然,为了能够首先包含该模块,您需要将其提供(使用上述任一技术).

  • 只想添加:如果/ lib(或其中一个自动加载目录)中的某个模块已经定义; 例如,您重载ActiveRecord或String,您必须明确要求它或它将不会被加载 (2认同)

die*_*pau 85

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

这是因为该行:

# config.autoload_paths += %W(#{config.root}/extras)
Run Code Online (Sandbox Code Playgroud)

内部config/application.rb被评论.

您可以尝试取消注释此行或(对我来说效果更好),留下此注释(以供将来参考)并添加以下两行:

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

  • 为什么后一种选择对你有用?此外,为什么默认情况发生了变化......尽管有很多人找到工作,但必须有理由. (4认同)

Fer*_*eti 22

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

#config/initializers/myapp_init.rb
require 'my_module'    
include MyModule
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

#config/initializers/myapp_init.rb
require ‘my_module’
Run Code Online (Sandbox Code Playgroud)

在需要的地方包含模块,如下所示:

1)如果要将其用作"类方法",请使用"extend":

class Myclass < ActiveRecord::Base
   extend MyModule
   def self.method1
      Myclass.my_module_method
   end
end
Run Code Online (Sandbox Code Playgroud)

2)如果要将其用作"实例方法",请在Class定义中包含它:

class Myclass < ActiveRecord::Base
include MyModule
   def method1
      self.my_module_method 
   end
end
Run Code Online (Sandbox Code Playgroud)

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

  • 我在`lib`文件夹上创建了我的模块,因此我在`config/application.rb`文件中添加了`config.autoload_paths + =%W(#{config.root}/lib)`.之后,我按照你的建议添加`config/initializers/myapp_init.rb`文件及其内容.一切都是好的.非常感谢 :) (3认同)