我是以前的PHP开发人员,学习Rails和Sinatra。在PHP中,每个页面请求都加载了所有必需的文件。如果我更改了一些代码并刷新了页面,我可以确定代码是新鲜的。
在Rails 3中,每次请求时控制器代码都是新鲜的。但是,如果我修改/ lib文件夹中的任何代码,我需要重新启动服务器以使更改生效。
为什么会这样?这与Ruby的设计方式有关吗? Rails是否进行了一些优化以避免在每个请求上重新加载代码?
谢谢!
编辑:我最感兴趣的是幕后发生的事情。像Rails和Sinatra这样的框架是否为类做了一些特殊的缓存?如果是这样,他们做了什么? Ruby中的默认行为是每次请求都会重新加载所有代码吗?为什么我们需要Shotgun for Sinatra(http://sinatra-book.gittr.com/#automatic_code_reloading)等工具?
答案 0 :(得分:20)
当您处于开发模式时,您应该告诉Rails不要缓存您的类,以便每次都重新加载。这意味着每个请求的类基本上都在rails解释器中重新定义。 Rails.root / config / environments / development.rb中的设置:
config.cache_classes = false
lib / dir中的类通常通过初始化程序加载,不受此设置的约束。
当您转向生产时,您将希望缓存所有类,因此请求更快,rails将对模型上的范围进行优化。
您可以在另一个初始化程序(可能称为Rails.root / config / initializers / development_reload.rb)中放入一些内容,该程序会在开发中的每个请求(或者您正在处理的请求)中重新加载lib目录:
# file development_reload.rb
if Rails.env.development?
ActionDispatch::Callbacks.after do
load 'filename_in_lib'
# or
Dir.entries("#{Rails.root}/lib").each do |entry|
load entry if entry =~ /.rb$/
end
end
end
我正在调用“load”所以它实际上重新加载了文件,而“require”只是检查它是否已经加载并确定它已经有了所以它不会重新加载它。 (我只是将它们放在一起并且不使用它,但Ruby非常灵活,并且允许你做很多事情。)明智地使用这样的东西,只在开发环境中使用。
为什么需要在Rails 3中重新加载代码?
Ruby是一种解释型语言(JRuby对预编译有一些支持,但它仍然被解释)。在初始化时解释类的定义类似于编译php和以可执行格式部署(稍微)。口译员不会一直在重新定义课程。
强制显式重新加载是对此类解释语言的优化。 (如果您在PHP中进行AOT编译,则需要在更改后重新加载已编译的“字节码”;默认的PHP使用即时编译,这是您正在利用的内容)
答案 1 :(得分:2)
如何采用更高级别的方法:
ActionDispatch::Reloader.cleanup!
ActionDispatch::Reloader.prepare!
这取自Rails / ActiveRecord v3.2.13 - active_record / railtie.rb
加载方法对我不起作用。只是执行加载导致一个奇怪的问题,它会为我触发两次验证器。
为了解决这个问题,我在重新加载User之前尝试了Object.send(:remove_const,User),但后来我在那个类上丢失了我的观察者,所以我开始追逐我的尾巴。
上面的方法重新加载所有类,所以也许还有一种更好的方法可以从缓存中正确删除单个类并重新加载它......