2

For example:

class Nested
  include Virtus.model

  attribute :name, String
end

class Base
  # Does not raise an exception even though the array failed to coerce!
  include Virtus.model(:strict => true)

  attribute :name, String
  attribute :nested, Nested
  attribute :array , Array[Nested]
  attribute :hash, Hash[String => Nested]
  attribute :hash_array_int, Hash[String => Array[Integer]]
  attribute :hash_array, Hash[String => Array[Nested]]  # attribute in question!
end

If I try creating some objects like this:

a = Nested.new(name: "a")
b = Base.new(
  name: "b",
  nested: { name: "nested b" },
  array: [{ name: "array 1" }, { name: "array 2" }],
  hash: { "key": { name: "hash b" } },
  hash_array_int: { "key": [1, 2, 3] },
  hash_array: {
    # The below fails to coerce the objects in the array
    "key": [{ name: "hash_array 1"}, { name: "hash_array 2" }]
  }
)

Every attribute works except the coercion of the Array[Nested] for the :hash_array, giving me the stack trace:

NoMethodError: undefined method `call' for nil:NilClass
    from /.rvm/gems/ruby-2.2.4/gems/virtus-1.0.5/lib/virtus/attribute.rb:104:in `coerce'
    from /.rvm/gems/ruby-2.2.4/gems/virtus-1.0.5/lib/virtus/attribute/collection.rb:79:in `block in coerce'
    from /.rvm/gems/ruby-2.2.4/gems/virtus-1.0.5/lib/virtus/attribute/collection.rb:78:in `each'
    from /.rvm/gems/ruby-2.2.4/gems/virtus-1.0.5/lib/virtus/attribute/collection.rb:78:in `each_with_object'
    from /.rvm/gems/ruby-2.2.4/gems/virtus-1.0.5/lib/virtus/attribute/collection.rb:78:in `coerce'
    from /.rvm/gems/ruby-2.2.4/gems/virtus-1.0.5/lib/virtus/attribute/hash.rb:110:in `block in coerce'
    from /.rvm/gems/ruby-2.2.4/gems/virtus-1.0.5/lib/virtus/attribute/hash.rb:109:in `each'
    from /.rvm/gems/ruby-2.2.4/gems/virtus-1.0.5/lib/virtus/attribute/hash.rb:109:in `each_with_object'
    from /.rvm/gems/ruby-2.2.4/gems/virtus-1.0.5/lib/virtus/attribute/hash.rb:109:in `coerce'
    from /.rvm/gems/ruby-2.2.4/gems/virtus-1.0.5/lib/virtus/attribute/coercible.rb:14:in `set'
    from /.rvm/gems/ruby-2.2.4/gems/virtus-1.0.5/lib/virtus/attribute_set.rb:146:in `block in define_writer_method'
    from /.rvm/gems/ruby-2.2.4/gems/virtus-1.0.5/lib/virtus/attribute_set.rb:173:in `block in set'
    from /.rvm/gems/ruby-2.2.4/gems/virtus-1.0.5/lib/virtus/attribute_set.rb:170:in `each'
    from /.rvm/gems/ruby-2.2.4/gems/virtus-1.0.5/lib/virtus/attribute_set.rb:170:in `set'
    from /.rvm/gems/ruby-2.2.4/gems/virtus-1.0.5/lib/virtus/instance_methods.rb:17:in `initialize'
    from (irb):2:in `new'

So it looks like the coercer is not being created correctly in https://github.com/solnic/virtus/blob/master/lib/virtus/attribute.rb#L104 via https://github.com/solnic/virtus/blob/master/lib/virtus/attribute/collection.rb#L79 and https://github.com/solnic/virtus/blob/master/lib/virtus/attribute/hash.rb#L110.

Before I dive into rolling my own gem for debugging this, does anyone know of a clean workaround or if I'm even trying to set up the nested relationships properly?

qix
  • 7,228
  • 1
  • 55
  • 65

0 Answers0