Why does code need to be reloaded in Rails 3?

后端 未结 2 774
不知归路
不知归路 2020-12-06 03:33

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 b

相关标签:
2条回答
  • 2020-12-06 03:45

    How about a more high level approach:

        ActionDispatch::Reloader.cleanup!
        ActionDispatch::Reloader.prepare!
    

    This was taken from Rails/ActiveRecord v3.2.13 - active_record/railtie.rb

    The load approach didn't work for me. Just performing load caused a weird issue where it would trigger certain validators twice for me.

    In order to fix that, I tried Object.send(:remove_const, User) before reloading User, but then I lost my observers on that class, so I started chasing my tail.

    The above approach reloads all the classes, so maybe there is still yet a better approach to properly remove an individual class from cache and reload it...

    0 讨论(0)
  • 2020-12-06 03:47

    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)

    0 讨论(0)
提交回复
热议问题