从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" 

条件部分可能是不必要的,但我包括它只是为了确定它的效果只发生在开发中。