我知道这个问题被提出已经很久了,但是我有一个额外的答案想要分享。
我有几个由另一个程序员在多年内开发的Ruby应用程序,它们在不同的应用程序中重复使用相同的类,尽管它们可能访问相同的数据库。由于这违反了DRY原则,我决定创建一个类库,供所有Ruby应用程序共享。我本可以把它放在主Ruby库中,但那样会隐藏常规代码中的自定义代码库,这是我不想做的。
我遇到了一个问题,即我已经定义了一个名为“profile.rb”的名称冲突,而我正在使用一个类。这个冲突直到我尝试创建通用代码库才成为问题。通常,Ruby首先搜索应用程序位置,然后转到$LOAD_PATH位置。
application_controller.rb找不到我创建的类,并在原始定义上抛出错误,因为它不是一个类。由于我从应用程序的app/models部分中删除了类定义,Ruby无法在那里找到它,于是去Ruby路径中寻找它。
因此,我修改了$LOAD_PATH变量,将其包含到我正在使用的库目录的路径中。这可以在初始化时的environment.rb文件中完成。
即使将新目录添加到搜索路径中,Ruby仍然会抛出错误,因为它优先选择系统定义的文件。$LOAD_PATH变量中的搜索路径优先搜索Ruby路径。
所以,我需要改变搜索顺序,让Ruby在搜索内置库之前先找到我的公共库中的类。
这段代码在environment.rb文件中实现了这一点:
Rails::Initializer.run do |config|
* * * * *
path = []
path.concat($LOAD_PATH)
$LOAD_PATH.clear
$LOAD_PATH << 'C:\web\common\lib'
$LOAD_PATH << 'C:\web\common'
$LOAD_PATH.concat(path)
* * * * *
end
我认为在这个级别上你不能使用之前提供的任何高级编码结构,但如果你想在应用程序初始化时设置某些东西,那么它完全可以正常工作。在将原始$LOAD_PATH变量添加回新变量时,必须保持原始顺序,否则一些主要的Ruby类会丢失。
在application_controller.rb文件中,我只是简单地使用了一个
require 'profile'
require 'etc'
这将为整个应用程序加载自定义库文件,即我不必在每个控制器中使用 require 命令。
对我来说,这是我正在寻找的解决方案,我想将其添加到此答案中以传递信息。
File.expand_path(File.dirname(__FILE__)).tap {|pwd| $LOAD_PATH.unshift(pwd) unless $LOAD_PATH.include?(pwd)}
- Nathan Long__dir__
(自Ruby 2.0起)可以使这些更加简洁。 - Nathan Long