ruby-on-rails - 为什么 Active Record 在内部使用 module_eval 来实现某些功能?

标签 ruby-on-rails ruby activerecord ruby-on-rails-4

我注意到 Rails 源代码中有几个地方使用了 module_eval。一个地方在ActiveRecord::Enum另一个在 ActiveRecord::Store .我熟悉 class_evalinstance_eval 并使用它们来扩展现有类或对象的功能,但对于 module_eval,它似乎有不同的用途。

在这两种情况下,他们都使用相似的模式来定义模块:

def _store_accessors_module
  @_store_accessors_module ||= begin
    mod = Module.new
    include mod
    mod
  end
end

如果模块包含在定义它的类中,那么在这样的嵌套模块中定义相关方法有什么好处?代码隔离更好吗?我问的原因是因为我有一个 gem 可以为 Active Record 添加功能,并且想知道这种方法是否更像是做同样事情的“最佳实践”方式。 Here's the relevant source code of my gem供引用。

最佳答案

在嵌套模块中定义方法的原因是用户可以覆盖这些方法并仍然可以访问 super 以获取原始功能。回想一下,当您在 Ruby 中包含模块时,它们被插入到当前类的祖先列表中,super 的工作方式是简单地遍历祖先数组,寻找响应当前方法的第一个对象。为此,模块的名称并不重要,因为它只是一种类似继承链的传递机制。所以这就是为什么他们只定义一个匿名的新模块并即时包含它。

如果您查看您列出的 2 个示例的责备 View ,您可以看到更改背后的原因。 commit message in the ActiveRecord::Store example使情况非常好。如您所见,他们添加了覆盖访问器定义 color 并通过 super || 附加到原始方法结果的能力。 '红色'。然而,在最初的实现中,必须重写 color 访问器方法,然后执行与原始访问器方法相同的工作,即调用 read_store_attribute(:settings, :color) | | '红色'。因此,这一切都是为了不被迫重现内部结构或使用别名方法链来增强动态定义方法的功能。

我不确定这在您的 gem 中是否是一个有用的功能,但我猜可能不是,因为您的访问器似乎正在返回定义明确的对象枚举相关对象。但是,当然,这取决于您和 gem 的用户 :)。

关于ruby-on-rails - 为什么 Active Record 在内部使用 module_eval 来实现某些功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24909410/

相关文章:

Ruby:尝试运行设置命令

ruby - Jekyll - 如何避免在 YAML frontmatter markdownify 项目上添加段落

css - Rails 4 应用程序中带有图像标签的全宽响应图像

ruby-on-rails - 按不同顺序条件合并两个数组

ruby-on-rails - 已加载模型的预加载关联

jquery - 如何在rails中使用jquery验证插件

ruby-on-rails - 使用RSpec测试Rails辅助方法时,如何在params哈希中设置值?

javascript - 如何在同时使用 Javascript 和 ERB 模板时保持 DRY (Rails)

ruby-on-rails - 为什么Puma Rails Server只接受localhost :3000 rather than 127. 0.0.1:3000

ruby-on-rails - Rails 事件记录唯一约束与 postgres 上的字段值