首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >匿名子类元编程导致不必要的行为(Virtus)

匿名子类元编程导致不必要的行为(Virtus)
EN

Stack Overflow用户
提问于 2011-10-11 02:02:05
回答 1查看 335关注 0票数 0

我使用Virtus (基本上是来自DataMapper的Property )来构建远程API,但是我不认为Virtus是问题所在,我认为这是因为我对Virtus所做的事情缺乏了解。

通过使用语法,我希望允许强制使用给定类型的属性:

代码语言:javascript
复制
Node[AnotherClass]

它只需动态生成Node的子类并返回新的类。那部分起作用了。但出于某种原因,它有一个不良的副作用。来自Virtus::Attribute::Object的所有其他对象实际上也都是Node子类本身。我无法解释,但我认为这一定是与继承模型相关的一种预期的红宝石行为。谁能给我指明正确的方向?

(注意,如果使用gem install virtus,则运行以下代码而不进行修改)。

代码语言:javascript
复制
require "virtus"

class JsonModel
  include Virtus
end

class Node < Virtus::Attribute::Object
  attr_reader :type

  class << self
    def [](type)
      raise ArgumentError, "Child nodes may only be other JsonModel classes" unless type <= JsonModel

      @generated_class_map       ||= {}
      @generated_class_map[type] ||= Class.new(self) do
        default lambda { |m, a| type.new }

        define_method :type do
          type
        end

        define_method :coerce do |value|
          value.kind_of?(Hash) ? type.new(value) : value
        end
      end
    end
  end
end

class ChildModel < JsonModel
end

class ParentModel < JsonModel
  attribute :child,  Node[ChildModel]
  attribute :string, String
end

# This should be String, but it's a descendant of Node??
puts ParentModel.attributes[:string].class.ancestors.inspect
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-10-11 02:33:13

我已经将您的代码简化为以下代码,并且它的行为仍然是一样的。

Class.new(Node)的存在导致了:string属性在其祖先中具有Node

代码语言:javascript
复制
require "virtus"

class JsonModel
  include Virtus
end

class Node < Virtus::Attribute::Object
end

# this does it...
Class.new(Node)

class ParentModel < JsonModel
  attribute :string, String
end

# This should be String, but it's a descendant of Node??
puts ParentModel.attributes[:string].class.ancestors.inspect

我不熟悉Virtus,但我猜这与Virtus实现属性类型的方式有关。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7720665

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档