【问题标题】:Debugging Rails application without restarting无需重启即可调试 Rails 应用程序
【发布时间】:2017-02-02 16:07:22
【问题描述】:

我正在调试 rails 应用程序 (Redmine),每次我更改插件路由或库中的某些内容以修补基类时,我都必须重新启动 rails 服务器,即使它处于开发模式并关闭缓存等。

这是我的服务器的样子:

rails s
=> Booting WEBrick
=> Rails 3.2.16 application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
[2017-02-02 17:06:18] INFO  WEBrick 1.3.1
[2017-02-02 17:06:18] INFO  ruby 2.1.8 (2015-12-16) [x86_64-darwin15.0]
[2017-02-02 17:06:18] INFO  WEBrick::HTTPServer#start: pid=12042 port=3000

有谁知道强制应用部分重新加载受影响或发生此类更改的类的方法?

【问题讨论】:

  • Rails 应用程序的某些方面仅在服务器启动时执行/解释,例如初始化程序和其他东西。

标签: ruby-on-rails ruby ruby-on-rails-4 redmine webrick


【解决方案1】:

您可能从 Redmine 插件的 init.rb 文件加载补丁。 将它们包围起来是一个好习惯:

ActionDispatch::Reloader.to_prepare

使用此回调,将在开发模式下的每个请求之前重新应用补丁。

这是一个例子:

require 'redmine'
ActionDispatch::Reloader.to_prepare do
  require_dependency 'redmine_multiprojects_issue/issue_patch'
  require_dependency 'redmine_multiprojects_issue/issues_helper_patch'
  require_dependency 'redmine_multiprojects_issue/issues_controller_patch'
end
Redmine::Plugin.register :redmine_multiprojects_issue do
  ...
end

请注意,如果更改路由,您仍然需要重新启动服务器。

【讨论】:

  • 啊,是的!我在找这个回调,但不记得它叫什么了!
  • 但是这种方式会导致生产速度变慢和不必要的重新加载吗?我应该只在开发过程中使用它吗?
  • 这就是使用这个回调的美妙之处——该块在生产模式下只会被调用一次,因为 Rails 的代码重新加载被禁用,但在开发模式下每次重新加载代码时都会调用它。这有几个变体,我最近一直在使用Rails.configuration.to_prepare do,效果相同。
【解决方案2】:

在 Rails 中启动过程需要相当长的时间。大部分时间是由于加载 gem 依赖项。如果您想对每个请求都这样做,那么有一些方法可以像这里描述的那样:

由于初始化程序仅在初始化期间运行,因此 rails 不会重新运行它们是有道理的。如果你依赖猴子补丁,这里有描述的方法

【讨论】:

    【解决方案3】:

    Redmine 插件通常不是 Ruby gem,而是位于 Rails 主应用程序内的文件夹中。

    只要插件作者遵循一些 Rails 最佳实践,Rails 的自动加载应该(并且将)也适用于 Redmine 插件。需要注意的基本事项是:

    • 正确的命名和命名空间 - 具有对应于模块的子目录和对应于它们声明的类/模块的文件名,即Foo::Bar::Baz 位于lib/foo/bar/baz.rb
    • 永远不需要手动加载任何东西,而是让 Rails 自动加载所有内容
    • 在修补的时间和地点要小心,以便在自动重新加载期间重新应用修补程序

    如果插件作者遵循这些规则,插件的代码很可能会自动加载并重新加载就好了。一个例外是插件的init.rb,但这通常不会在插件开发过程中经常更改。

    实际上,许多 Redmine 插件由于违反这些规则而破坏了自动加载。症状可能是没有自动重新加载,甚至尝试重新加载时出现应用程序错误,导致应用程序在生产模式下工作正常,但在开发模式下第一次成功请求后失败。

    通常只需重新组织插件代码以符合 Rails 的期望并删除 require 语句即可解决此类问题。

    更改插件声明的路由将需要重新启动服务器,但我不知道如何使用 Redmine 自动重新加载这些路由。

    【讨论】:

    • 您好,感谢您的启蒙...您能在这里举一些例子吗?原因是,我一直需要 init.rb 以及 rails *to_prepare 事件完成时应用的补丁。
    • to_prepare 块中应用补丁是可行的方法。问题是,你不应该手动 require 任何东西。使用正确的命名和命名空间,即使使用 require_dependency 也没有必要。虽然如果你必须这样做,后者总是更好,因为它不会破坏 Rails 的代码重新加载。
    猜你喜欢
    • 1970-01-01
    • 2011-08-10
    • 2021-03-01
    • 1970-01-01
    • 2012-02-23
    • 2014-12-24
    • 1970-01-01
    • 2016-04-23
    • 1970-01-01
    相关资源
    最近更新 更多