繁体   English   中英

从Rails 3的lib文件夹加载模块/类的最佳方法?

[英]Best way to load module/class from lib folder in Rails 3?

由于最新的Rails 3版本不再从lib中自动加载模块和类,因此最好的加载方式是什么?

来自github:

 A few changes were done in this commit: Do not autoload code in *lib* for applications (now you need to explicitly require them). This makes an application behave closer to an engine (code in lib is still autoloaded for plugins); 

从Rails 2.3.9开始config/application.rb中存在一个设置,您可以在其中指定包含要自动加载的文件的目录。

从application.rb:

# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)
# Autoload lib/ folder including all subdirectories
config.autoload_paths += Dir["#{config.root}/lib/**/"]

来源: Rails 3快速提示:自动加载包括所有子目录的lib目录,避免延迟加载

请注意,lib文件夹中包含的文件仅在服务器启动时加载。 如果您希望自动重新加载这些文件,请阅读: Rails 3快速提示:在开发模式下自动重新加载lib文件夹 请注意,这并不适合生产环境,因为永久性重新加载会降低机器的速度。

自动加载东西的魔力

我认为其他答案已经充分介绍了控制从中完成自动加载的文件夹的选项。 但是,如果有人根据需要修改了自动加载路径后却加载了麻烦的东西,那么此答案将试图解释自动加载背后的魔力是什么。

因此,从子目录加载内容时,您应该知道一个陷阱或约定。 有时,Ruby / Rails的魔力(这次主要是Rails)可能使人们很难理解为什么发生了事情。 仅当模块名称与父目录名称相对应时,才会加载在自动加载路径中声明的任何模块。 因此,如果您尝试将lib/my_stuff/bar.rb

module Foo
  class Bar
  end
end

它不会自动加载。 再一次,如果您将父目录重命名为foo从而将模块托管在路径: lib/foo/bar.rb 它将为您服务。 另一个选择是使用模块名称来命名要自动加载的文件。 显然,那时只有一个文件具有该名称。 万一您需要将您的内容拆分为多个文件,您当然可以使用一个文件来要求其他文件,但是我不建议这样做,因为在开发模式下修改其他文件时,Rails无法自动进行为您重新加载。 但是,如果您确实想要,则可以在模块名称旁有一个文件,然后指定使用该模块所需的实际文件。 因此,您可能有两个文件: lib/my_stuff/bar.rblib/my_stuff/foo.rb ,前一个与上面相同,而后者只包含一行: require "bar"并且工作原理相同。

附言:我感到不得不添加另一件重要的事情。 最近,每当我想在lib目录中有需要自动加载的内容时,我就会开始思考,如果这是我真正为该项目专门开发的(通常是一天)变成许多项目或git子模块等中使用的“静态”代码段。在这种情况下,它绝对应该在lib文件夹中),那么它的位置可能根本不在lib文件夹中。 也许应该在app文件夹下的子文件夹中。我感觉这是新的Rails处理方式。 显然,无论您在何处放置自动加载路径,同样的魔力都在起作用,因此对这些事情都有利。 无论如何,这只是我对这个问题的想法。 您可以自由地不同意。 :)


更新:关于魔术的类型

正如severin在他的评论中指出的那样,核心“自动加载模块机制”当然是Ruby的一部分,但是自动加载路径的内容却不是。 您不需要Rails来autoload :Foo, File.join(Rails.root, "lib", "my_stuff", "bar") 当您第一次尝试引用模块Foo时,它将为您加载。 但是,Rails所做的是,它为我们提供了一种尝试从注册的文件夹中自动加载内容的方法,并且这种实现方式需要假设一些有关命名约定的方式。 如果尚未实现,则每次引用当前未加载的内容时,都必须遍历所有自动加载文件夹中的所有文件,并检查其中是否包含您要引用的内容。 这反过来会破坏自动加载和自动重新加载的想法。 但是,有了这些约定,它可以从模块/类中扣除您尝试加载可能定义的位置并仅加载该内容的尝试。

警告:如果要从“ lib”文件夹中加载“ monkey patch”或“ open class”,请不要使用“ autoload”方法

  • config.autoload_paths ”方法:仅在加载仅在一个位置定义的类时有效。 如果已经在其他地方定义了某个类,则无法通过这种方法再次加载它。

  • config / initializer / load_rb_file.rb ”方法:总是有效! 无论目标类是新类,还是现有类的“开放类”或“猴子补丁”,它始终有效!

有关更多详细信息,请参阅: https : //stackoverflow.com/a/6797707/445908

非常相似,但是我认为这有点优雅:

config.autoload_paths += Dir["#{config.root}/lib", "#{config.root}/lib/**/"]

就我而言,我试图直接在lib目录下直接加载文件。

在application.rb中...

require '/lib/this_file.rb' 

即使在控制台中也无法正常工作,然后当我尝试

require './lib/this_file.rb' 

Rails会完美加载文件。

我仍然还是个菜鸟,不知道为什么能行,但是行得通。 如果有人想向我解释它,我将不胜感激:DI希望这对任何人都可以有所帮助。

我有同样的问题。 这是我解决的方法。 该解决方案将加载lib目录和所有子目录(不仅是直接目录)。 当然,您可以将其用于所有目录。

# application.rb
config.autoload_paths += %W(#{config.root}/lib)
config.autoload_paths += Dir["#{config.root}/lib/**/"]

config.autoload_paths对我不起作用。 我用其他方式解决

Ruby on Rails 3不会从/ lib文件夹自动重新加载(自动加载)代码。 我通过放入ApplicationController解决它

Dir["lib/**/*.rb"].each do |path|
  require_dependency path
end 

如果只有某些文件需要访问lib中的模块,则只需在需要文件的文件中添加一条require语句即可。 例如,如果一个模型需要访问一个模块,请添加:

require 'mymodule'

在model.rb文件的顶部。

Rails 5 ,建议将lib文件夹放置在app目录下,或者为该文件夹创建其他有意义的名称空间,如servicespresentersfeatures等,并将其放置在app目录下以供Rails自动加载。

请同时查看此GitHub讨论链接

有几种原因可能会导致您从lib加载时遇到问题-有关详细信息,请参见此处-http: //www.williambharding.com/blog/technology/rails-3-autoload-modules-and-classes-in-production/

  • 修复自动加载路径
  • 线程安全相关
  • 命名相关
  • ...

正确拼写文件名。

说真的 我与一个班级竞争了一个小时,因为该班级是Governance :: ArchitectureBoard,并且文件位于lib / governance / architecture_baord.rb中(“ board”中的O和A换位了)

回想起来似乎很明显,但这是魔鬼的追踪。 如果该类未在Rails希望基于修改类名的文件中定义,则根本不会找到它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM