gpt4 book ai didi

ruby-on-rails - 重新加载模块/类后仍定义 Ruby 方法

转载 作者:数据小太阳 更新时间:2023-10-29 08:08:14 24 4
gpt4 key购买 nike

我在为我的 Rails 应用构建 ruby​​ gem 时遇到了类重新加载问题。

背景

在 gem 中,我定义了以下类

module MyGem
class AppConfigBase

def app_title
"Title Missing"
end

end
end

在 Rails 应用程序中,我创建了一个 config/my_gem.rb 文件来保存一些特定于应用程序的覆盖。 (我的目标是让 gem 的用户定义一些信息,但在父类(super class)中有一些默认值可用。)

module MyGem
class AppConfig < AppConfigBase

def app_title
"Great App"
end

end
end

在 gem 中的某个时刻,我调用 MyGem::AppConfig.new.app_title 并收到正确的字符串。耶!

接下来,我决定稍微挑战一下极限:我想让自动加载工作,这样开发人员就不必在每次更改此文件时都重新启动 Rails 服务器。

我首先尝试查看 Rails 是否已设置为执行此操作。我从 AppConfig 类中删除了 app_title 方法。当我重新加载页面时,我仍然会返回“Great App”字符串。 :( Rails 不会重新加载 config/my_gem.rb(或 config 目录中的任何内容),所以这是预期的结果。

接下来,我尝试添加以下初始化程序:

if Rails.env.development?
ActionDispatch::Callbacks.after do
load "#{Rails.root}/config/my_gem.rb"
end
end

上面的初始化器部分解决了问题,但我想了解为什么它不能完全解决问题。有了这个初始化器,

  1. 如果我从子类中删除 app_title 方法,我仍然会得到错误的字符串(子类方法中的那个……不应该再存在了)。
  2. 如果我重新启动服务器,我会得到预期的字符串的父类(super class)版本。
  3. 现在,如果在子类中重新添加方法并调用 app_title,我将获得该字符串的子类版本!

因此,当我添加一个方法时,初始化程序中的加载调用似乎是在拾取新方法。但是,如果我删除一个方法,它似乎没有帮助。

  1. 为什么会这样?
  2. 如何让这个文件在更改时自动重新加载? (我看到的最简单的解决方法是将 my_gem.rb 移动到 config/my_gem/my_gem.rb,然后将 config/my_gem 添加到 Rails 中的自动加载路径,但我不想创建这个额外的目录,只是自动加载一些东西。)

最佳答案

这并不是自动加载的工作原理。 Rails 的重新加载器(不同于但依赖于自动加载器机制)的工作原理是取消定义常量,然后通过请求定义它们的文件来重新创建它们。你真正想要的是标记常量 unloadable .在您的覆盖中:

module MyGem
class AppConfig < AppConfigBase
unloadable

def app_title
"Great App"
end
end
end

这会将常量添加到每个请求要卸载的常量列表中,但它期望它可以通过加载 my_gem/app_config.rb 来加载常量。并期望它在您的加载路径上。因此,这种覆盖通常发生在 lib/ 中。而不是 config/ ,因为前者在您的加载路径中而后者不在。它意味着除了使用它的那些请求之外,任何请求都可能不需要常量。

通常预期在 config 中更改文件将需要重新启动才能应用。

关于ruby-on-rails - 重新加载模块/类后仍定义 Ruby 方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29308658/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com