Cim*_*imm 27 ruby ruby-on-rails
我在Rails中有一个更概念性的问题......或Ruby:
最好在需要它的方法之前调用require,在Rails启动时将我的需要分组在类的开头或初始化器的某个地方?
从性能的角度来看是否重要?从可读性的角度来看?如果我使用Rails 3会有所不同吗?
谢谢!
tad*_*man 22
如果您关注性能,那么您应该在需要它们的上下文中要求使用这些内容,以便在未执行代码的那部分时,不会加载库.任何后续调用require
都不会影响该文件已被加载.这最终看起来像是:
if (user.using_openid?)
require 'openid'
# ... Do OpenID stuff
end
Run Code Online (Sandbox Code Playgroud)
虽然这在资源方面更有效,但它可能使确定应用程序的依赖性变得非常困难.声明这些预先设置使其他人维护该软件变得清晰.请记住,当您忘记申请的某些细节时,"其他人"总是包含您未来的自我.
从技术上讲,您可以在任何时间,迟到或早期要求任何东西,但从设计角度来看,预先声明您的要求会更好.如果您发现某个元素只是间歇性地使用并且需要花费不寻常的时间或内存来加载,那么您应该在需求文件中预先记录该元素.例如:
require 'library1'
require 'library2'
require 'library3'
require 'library4'
require 'library5'
# Other libraries loaded as required:
# * slowimagelibrary
# * slowencryptionlibrary
# * openid
Run Code Online (Sandbox Code Playgroud)
可以说这对捆绑器来说不是一个问题,因为你可以更正式地预告你的宝石,实际的require
调用可以在以后进行.
如果您考虑使用香草Ruby,则“ require”通常在第一行中使用,因为这样您就可以确保可以访问所需的内容,并且更容易查找和读取所需的依赖项。
在某些情况下,您只想在一种方法中加载gem,因为脚本实际上并不需要这样做(例如:可选的可视化)。
对于Rails,我相信这取决于您要做什么。
如果使用Bundler,则可以假定您的宝石是“必需的”(当然,您可以使用:require选项覆盖所需的宝石)。
如果您想在服务器启动时自动加载某些东西(例如验证器或表单生成器),那么您应该查看如何使用配置(autoload_paths和eager_load_paths)。
require也可以仅用于加载gem的一部分,例如其扩展。然后,当然需要在哪里配置。
如果您在多线程环境中工作,可能会感到担心,因为这是一些问题。然后,必须确保所有内容都已加载,然后才能运行线程。(有点像类常量已加载,但方法尚未加载,有一篇不错的文章,但我找不到了)。
您可能还想尝试{Module,Kernel} .autoload,Rails广泛使用它来仅加载访问时所需的内容(但看起来很丑)。
您也可以使用const_missing自己修改它(因此,如果您接受结构,则可以进行简单的延迟加载)。这是一个简单的示例(不适用于嵌套类)。
def Object.const_missing c
if (file = Dir["#{c.downcase}.rb"]).size == 1
require_relative(file)
end
if const_defined? c
const_get c
else
super # Object < Module
end
end
Run Code Online (Sandbox Code Playgroud)
关于性能,对require的调用相对昂贵,因此,如果您知道将要使用它,请尽可能只执行一次。但是,要管理项目中的复杂依赖性,可能需要使用相对文件。然后require_relative
是1.9中的方法。
最后,对于一个项目,我建议在lib /的主文件中要求所有内容,并带有一些Dir["**/*.rb"]
表达式。然后require_relative
,您几乎不需要,因为仅当您在类的主体中引用另一个常量时才需要它(方法的所有内容均未解析,因此这没有问题)。
另一个解决方案是在您的主文件中定义这些常量,这也会使您对结构有所了解。