ruby - 包含一个模块来定义动态类方法

标签 ruby class module

我正在研究 Ruby,并且编写了以下代码:

module IdAndNameRedefine
  def self.included(base)
    base.extend(ClassMethods)
  end

  module ClassMethods
    def use_id_and_name_from_module(use_attribute)
      class_eval <<CODE
        def id_and_name
          "\#{id}-\#{#{use_attribute}.downcase}"
        end
CODE
    end
  end
end


class Model
  include IdAndNameRedefine

  attr_reader :id, :name1, :name2

  def initialize(id, name1, name2)
    @id = id
    @name1 = name1
    @name2 = name2
  end

  def id_and_name
    "#{id}-#{name1}"
  end

  use_id_and_name_from_module :name2
end

model = Model.new(1, "TesT", "Test number TWO")
puts model.id_and_name

当我在这里尝试做的是用 IdAndNameRedefine 模块动态插入的方法覆盖类 Model 中的类方法 id_and_name。当包含该模块时,它会创建一个“静态”方法(实际上,据我所知,是 Model.class 的类方法),当 use_id_and_name_from_module 被调用时,它会在 Model 中创建一个类方法,它重新定义 id_and_name 以使用模型要求的任何属性。

我的问题是.. 有没有更好的方法来做到这一点,或者这是这样做的“正确”方法?我不太确定我是否喜欢 class_eval 带有一个字符串,我需要在其中转义值等才能完成这项工作。

最佳答案

您不必将字符串传递给 class_eval。它可以取而代之。事实上,我想不出有哪一次我必须将字符串传递给 class_eval。所以我们可以像这样重写 ClassMethods 模块:

module ClassMethods
  def use_id_and_name_from_module(use_attribute)
    class_eval do 
      define_method(:id_and_name) {"#{id}-#{send(use_attribute).downcase}"}
    end
  end
end

但在这种特殊情况下,我们只是告诉 selfclass_eval,这意味着我们已经在该类的上下文中。所以它实际上可以缩短为:

module ClassMethods
  def use_id_and_name_from_module(use_attribute)
    define_method(:id_and_name) {"#{id}-#{send(use_attribute).downcase}"}
  end
end

(我只是想展示 class_eval 是如何工作的,因为你似乎对那部分最感兴趣。)

关于ruby - 包含一个模块来定义动态类方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1011142/

相关文章:

Ruby:使用 join 和 ThreadsWait.all_waits 等待所有线程完成 - 有什么区别?

javascript - 单击复选框时检查复选框的选中状态

python - 为什么我必须为每个新项目重新安装所有 python 模块? (皮查姆)

ruby-on-rails - 为什么在安装 Rails 时出现 "write permission"错误?

ruby - 使用 Devise 的 Rails 5,使用 Rspec 测试 Controller (销毁操作)

python - 如何将 models.py 中创建的新类添加到 admin.py (django)

module - 在 Lua 5.2 中让 2 个以上模块递归互相引用的推荐方法

c# - 在 Visual Studio 2017 中运行和调试 Powershell 模块

ruby - 如何比较 ruby 中的时间

c# - 实现 IEnumerable<SqlDataRecord> 时无法访问 'Sum' 函数