Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
311 views
in Technique[技术] by (71.8m points)

ruby - Why does code need to be reloaded in Rails 3?

I am a former PHP developer learning Rails and Sinatra. In PHP, every page request loaded all of the required files. If I changed some code and refreshed the page, I could be sure that the code was fresh.

In Rails 3, Controller code is fresh on every request. However, if I modify any code in the /lib folder, I need to restart the server so the changes take effect.

Why does this happen? Is it something to do with the way Ruby is designed? Is Rails doing some optimizations to avoid reloading code on every request?

Thanks!

Edit: I am mostly interested in what is going on under the hood. Do frameworks like Rails and Sinatra do some special caching for classes? If so, what does they do? Is the default behavior in Ruby that all code gets reloaded on every request? Why do we need tools like Shotgun for Sinatra (http://sinatra-book.gittr.com/#automatic_code_reloading)?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

While you are in development mode you should tell Rails not to cache your classes so they reload each time. This means that each request the classes are basically redefined in the rails interpreter. The setting in your Rails.root/config/environments/development.rb:

config.cache_classes = false

The classes the are in your lib/ dir are usually loaded through an initializer and not subject to this setting.

When you move to production you will want all of your classes to be cached so requests are faster and rails will do optimizations to things like scopes on your models.

You could put something in another initializer (maybe called Rails.root/config/initializers/development_reload.rb) that reloads the lib dir with every request in development (or just the ones you are working on):

# 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

I am calling "load" so it actually reloads the file, whereas "require" would just check if it has been loaded and determine it already has so it will not reload it. (I just threw this together and don't use it, but Ruby is extremely flexible and will allow you to do quite a bit.) Use something like this wisely and only in a dev environment.

Why code needs to be reloaded in Rails 3?

Ruby is an interpreted language (JRuby has some support for precompilation, but it's still interpreted). Interpreting the the definition of classes once on initialization is similar to compiling php and deploying in executable format (somewhat). The interpreter is not bothered with redefining classes all the time.

Forcing the explicit reload is an optimization for this type of interpreted language. (if you AOT compile in php you would need to reload the compiled "bytecode" after changes as well; default php uses on-the-fly compilation which is what you are taking advantage of)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...