从Rails 3项目中的lib目录中访问模型
我在lib目录中有一个文件,它使用模型中定义的一些常量,如:
class User < ActiveRecord::Base MAX_EMAIL_ADDRESS_LENGTH = 255 end
然后我在lib / foo.rb
module Foo LONG_EMAIL_ADDRESS = "foo@bar.com".rjust(User::MAX_EMAIL_ADDRESS_LENGTH, "a") end
由于没有找到类User,它失败了。 如何在lib上的该文件之前加载User?
我正在我的application.rb中加载该文件:
config.autoload_paths += %W(#{config.root}/lib)
第一部分是正确的:
config.autoload_paths += %W(#{config.root}/lib)
接下来,重要的是模块
module Foo ... end
必须放入
lib/foo.rb
文件。
然后,它可以include
在应用程序代码中。
class Comment < ActiveRecord::Base include Foo ... end
如果不打算包含lib目录中的文件foo.rb
(但这可能是一种错误的方式),那么在这段代码中使用Rails模型和其他东西你应该把它放到foo.rb中:
require_relative "../config/environment.rb"
解决方案是,我的/ lib文件实际上是rake文件所要求的,并且在Rails设置整个自动加载系统之前似乎加载了rake文件,因此无法找到模型。 从.rake文件中删除require后,一切都开始工作了。
我知道这是一个老问题,但我刚遇到同样的问题,经过一些搜索,我找到了一个解决方案,所以我认为值得分享。
我想在my / lib目录中的一个必需文件中使用模型“Foo”。 首先,我做了这个,它没有用:
# in my rake file task :foo_task do require /some_path/lib/bar.rb end # in /lib/bar.rb puts "Foo = #{Foo.count} " # => uninitialized constant Foo
经过一些搜索,我发现要访问我的lib文件中的模型,我需要在我的任务中指定环境。 所以我把它添加到我的任务声明中:
task :foo_task => [:environment] do
现在,当我调用我的任务时,它正确地输入了Foo的数量:
# => Foo = 6
默认情况下, YourApplicationNameHere::Application.autoload_paths
为[]
。 我(纯粹出于组织原因)也为我的app/models
目录添加了一个glob。
config.autoload_paths += Dir["#{Rails.root}/app/models/**/"] config.autoload_paths += Dir["#{config.root}/lib"]
通过这种设置,我能够毫无困难地完成你在问题中提出的问题。 这对您也有好处,告诉Rails在lib/
module的实例化中找不到User
模型的位置。
编辑
在您的问题中指定确切的错误消息也会有所帮助。
uninitialized constant Foo::User
意味着Ruby / Rails正在Foo
命名空间中寻找User
。 使用::
前缀User
强制查找全局命名空间。
module Foo LONG_EMAIL_ADDRESS = "foo@bar.com".rjust(::User::MAX_EMAIL_ADDRESS_LENGTH, "a") end
看来你的类User没有被实例化,这看起来很不寻常,除非你在’models’之外的位置有’user.rb’。 通常情况下,类不会在开发中加载,除非它们专门位于该目录中,但我使用的一个解决方案是,您可以将此行放在您希望在违规行之前调用的代码中..
Rails.application.eager_load! if Rails.env == "development"
条件部分可能是不必要的,但我包括它只是为了确定它的效果只发生在开发中。