首页 > 解决方案 > 在对象初始化时在 ruby​​ 中动态构建访问器

问题描述

我围绕 json API 创建了一个 ruby​​ 包装器,它将 json 格式的响应转换为 ruby​​ 对象。典型的资源如下所示:

module Learning360
  class User
    attr_accessor(
      :_id,
      :mail,
      :firstName,
      :lastName,
      :assignedPrograms,
      :paths,
      :certifications,
      :championAchievements,
      :comments,
      :completedPrograms,
      :groups,
      :imageUrl,
      :labels,
      :lastLoginAt,
      :championStatus,
      :learnerAchievements,
      :managers,
      :messages,
      :publications,
      :reactions,
      :skills,
      :subordinates,
      :toDeactivateAt,
      :totalTimeSpentInMinutes,
      :custom
    )

    def initialize(options = {})
      options.map { |(k, v)| send("#{k}=", v) }
    end
  end
end

当我收到 json 有效负载时,我将其作为选项哈希传递给初始化程序,然后将每个键的值作为实例变量分配。只要我维护一个更新的attr_accessor. 但是,如果 API 决定更改其密钥的命名或添加新密钥,则会抛出一个

undefined method `unexpected_key_from_api=' for #<Learning360::User>

我怎样才能避免这个问题并使我的包装器更健壮。我希望我的包装器对象只从响应中获取任何键,并在它不存在时自动构建相应的访问器。

标签: rubymetaprogrammingattr-accessor

解决方案


attr_accessor您可以在方法内部创建属性initialize。您只需要像下面这样访问它:

module Learning360
  class User
    def initialize(options = {})
      options.each do |(k, v)|
        self.class.attr_accessor(k)
        send("#{k}=", v)
      end
    end
  end
end

user = Learning360::User.new({ name: "Matz" })
puts user.name  # Matz

也可以直接使用类名,就像User.attr_accessor(k).


推荐阅读