Rails 关于 Rails reload code

hiveer · 2014年02月20日 · 最后由 yan32768 回复于 2015年06月01日 · 5087 次阅读

想要实现的目的就是,在不 restart rails server 的情况下,如何让更新了的代码起作用。 app/* 的结构如上图 对于像 lib/* 下的文件处理方式又有什么不同呢

生产环境下,不重启服务器新代码无效。 一般的做法是启动新的 rails server 完成后杀掉老的 rails server

#1 楼 @bydmm 在开发环境下呢,实际上这个问题主要针对开发环境提的。

#2 楼 @hiveer 开发环境下,新代码应该就可以实时生效。 除了要 Rake db:migrate 以外的情况

开发模式下: config/environments/development.rb config.cache_classes = true 改为config.cache_classes = false

具体实现:railties-3.2.14/lib/rails/application/finisher.rb +73~+96

#4 楼 @huhongda @bydmm config.cache_classes 没有给值,那么默认就是 false。我想搞明白是这种情况下是不是所有 app/的目录/、文件都会被自动 reload,而不需要我做其他操作。

Rails 有“文件更新监控”的实现,具体参见 ActiveSupport::FileUpdateChecker module,使用案例可以 https://github.com/intridea/grape#reloading-api-changes-in-development

@hiveer 系统目录开发模式下会 reload, 但是你新建的目录 比如 app/workers/xxx 需要加入配置 config.autoload_paths += %W(#{config.root}/lib #{config.root}/app/workers/) 才能 reload!注意一下你的系统时间!跟系统时间也有关系呢!

...有几种东西不会 reload. 最常见的是下面这三个。

  1. initializer
  2. 各种 config
  3. 非 Rails 自建的东西并且对方没有支持 rails 的 reload 机制的 (如 Grape)

热重启 这件事应该交给 unicorn 层面来做吧?

#9 楼 @alsotang development 下应该不需要 unicorn 来帮忙吧

#8 楼 @ruohanc #7 楼 @huhongda #6 楼 @ruby_sky 这是 modules/user_methods.rb

module UserMethod
  def n_upcase
    self.nickname.upcase!
    self.save!
  end
end

这是 models/user.rb

class User < ActiveRecord::Base
  include UserMethod
end

我现在想要实现的就是在 user_methods.rb 变化的时候,比如 upcase! => downcase!,然后不需要重启 server,刷新网页就能看到名字的变化。

你的文件命名这些都没有准训规范呢!

# 加上命名空间
module Modules
    module UserMethods
        extend ActiveSupport::Concern

        def abc
           puts 'abc'
        end
    end
end

class User < ActiveRecord::Base
  include Modules::UserMethods
end

建议把文件放到 concern 中

你可以在 config/application.rb 里添加

config.autoload_paths += %W(#{config.root}/app/models/modules)

同时,不要使用 require 加载文件。

#13 楼 @zhangyuan 我这样做了但是没有实现功能

#14 楼 @hiveer 能给出代码片段吗?

另外,

  1. 打印出 ActiveSupport::Dependencies.autoload_paths 的值
  2. 不要 使用 require 加载文件

#13 楼 @zhangyuan 按照你说的做,重启服务器的时候 modules 下的文件都是没有加载的。

config.autoload_paths += %W(#{config.root}/app/models/modules)

其余的代码见 11 楼

#16 楼 @hiveer 你的文件名是 user_methods.rb 但是你的模块是 UserMethod (注意 s),需要改成一致才符合 Rails 的惯例。

#17 楼 @zhangyuan 嗯,这个确实是个问题。但是我更改了之后,依然没有实现逻辑。 environment.rb

# Load the Rails application.
require File.expand_path('../application', __FILE__)

# Initialize the Rails application.
ShareResources::Application.initialize!


p 'init test log file'
class TestLogger < Logger
  def format_message(severity, timestamp, progname, msg)
    "#{timestamp.to_formatted_s(:db)} #{severity} #{msg}\n"
  end
end

test_logfile = File.open("#{Rails.root}/log/test_logger.log", "a+")
test_logfile.sync = true
TEST_LOG = TestLogger.new(test_logfile)

application.rb

#config.autoload_paths += Dir[Rails.root.join("app", "models", "modules")]
  config.autoload_paths += %W(#{config.root}/app/models/modules)    

users_controller.rb

def index
    @users = User.all
    @users.map(&:n_upcase)    
    TEST_LOG.info "Here i am"
  end

#18 楼 @hiveer 你把 app/models/modules/user_methods.rb 重命名为 app/models/modules/user_method.rb;或者把 UserMethod 这个模块名改成 UserMethods 了吗?

你确定没有在其他地方 require 这个文件吗?如果不符合 Rails 的惯例,是不会自动加载的。

#19 楼 @zhangyuan 名字改过来了,而且确定没有再去 require 这个文件了

#20 楼 @hiveer 现在没问题了吗?

还有,修改 config/application.rb 后要重启 server。

#19 楼 @zhangyuan 还有问题呀,就是不能检测到 user_methods.rb 的变化。我把代码提交到 github,你 fork 一个帮我看看,可以吗?

#23 楼 @hiveer 好的。我在本地跑一下看看

#25 楼 @hiveer 就你目前的代码,是可以自动 reload 的。不过你代码有问题

module UserMethods
  def n_upcase
    self.nickname.upcase!
    self.save!
  end
end

这里,虽然修改了 nickname 这个属性的内容,但是,self.save! 并不会保存到数据库。可以修改为:

module UserMethods
  def n_upcase
    self.nickname = nickname.upcase
    self.save!
  end
end

#26 楼 @zhangyuan #27 楼 @huhongda "这里,虽然修改了 nickname 这个属性的内容,但是,self.save! 并不会保存到数据库。"这里为什么 self.save!不会保存到数据库呢

#27 楼 @huhongda #26 楼 @zhangyuan 周末好好研究了下,确实这个代码是可以自动 reload 的。估计是我的 netbeans 的问题哦,在里面保存了但是没有被 reload,我换成了 rubymine 就 OK 了。 谢谢各位的跟进和指正!

#26 楼 @zhangyuan

module UserMethods
  def n_upcase
    self.nickname = nickname.upcase
    self.save!
  end
end

这里你把 upcase! 改为了 upcase。这里我测试了必须是这样的,但是能给讲讲为什么吗?

标记一下吧,可能用到

需要 登录 后方可回复, 如果你还没有账号请 注册新账号