在Rails模型中包含一个lib - 是否需要“require”?

时间:2013-11-20 18:12:06

标签: ruby-on-rails model require

我有一个现在看起来像这样的模型:

class Logo < ActiveRecord::Base
  include ImageManipulation
  ...
end

ImageManipulation是一个名为image_manipulation.rb的库,位于/lib/我可以毫无问题地使用该模型,但今天我必须通过rails控制台进行一些操作,当试图做Logo.delete_all,我收到了这个错误:

NameError: uninitialized constant Logo::ImageManipulation

所以,我改变模型看起来像这样:

require 'image_manipulation'
class Logo < ActiveRecord::Base
  include ImageManipulation
  ...
end

我的问题是......当我想在rails控制台中使用Logo模型时,为什么需要这些,但是在启动rails s并通过我的应用程序操作模型时不需要?

2 个答案:

答案 0 :(得分:0)

我建议rails s在开发模式和图书馆位置找到的自动加载类中开始。通过rails console运行应用时,此自动加载可能不会发生相同的程度。

答案 1 :(得分:0)

这是因为您的自动加载设置。

当您加载Rails控制台时,Rails不会立即require您应用中的每个文件,因为这需要很长时间。相反,它使用&#34;延迟加载&#34; - 在实际需要它之前,它不会将类加载到内存中。

这种方法的工作方式是,当您在代码中使用常量(即类或模块)时,解释器还没有看到它,它将智能地猜测它需要加载哪个文件找到该常量的代码。例如。对于User,它会查找名为user.rb的文件,对于ImageManipulation,它会查找image_manipulation.rb,并查找名称空间常量,例如Image::Manipulation它会查找image/manipulation.rb

它在哪里查找这些文件?在您的&#34;自动加载路径&#34;中,这是存储在Rails应用的config设置中的目录列表。因此,对于文件user.rb,它会查找app/models/user.rbapp/controllers/user.rbapp/helpers/user.rb等,直到a)它找到一个文件并加载它或b)它用完的地方到看,在这种情况下它会引发NameError

因此,有两种情况需要明确require文件:

  1. ImageManipulation在Rails无法自动识别的文件中定义(即名为image_manipulation.rb的文件。)
  2. image_manipulation.rb不在自动加载路径中的目录中。
  3. 默认情况下,您的autoload_paths包含所有标准app目录,例如modelscontrollers,但包含lib (据我所知......它可能取决于你的Rails版本)。因此,如果您希望能够自动加载ImageManipulation,则应将其置于可自动加载的位置,或将lib添加到自动加载路径,方法是将以下行添加到config/application.rb

    config.autoload_paths.push(Rails.root.join("lib"))
    

    我不知道为什么ImageManipulationrails s下被自动加载,但不在rails c下,但我怀疑你是否正在运行这两个rails命令在不同的环境下(例如,一个处于开发模式,另一个处于生产环境中),并且环境具有不同的自动加载设置。尝试在您的应用目录中搜索autoloadautoload_paths,看看您是否能发现任何异常情况。