virtus icon indicating copy to clipboard operation
virtus copied to clipboard

Support annotations/meta information for attribute

Open mirasrael opened this issue 11 years ago • 9 comments

Hi. What you think about add support for attributes meta information? In some cases it may be very useful. I.e. we are generating xml by virtus models and have to wrap any array element into custom tag. So it will be handy to specify additional option for attribute and later access it in generator.

I.e. we have a class:

class Container
   include Virtus

   attribute :entries, Array[Entry], annotations: {wrap: 'entry'}
end

and somewhere in code:

Container.attribute_set[:entries].annotations[:wrap] #=> 'entry'

mirasrael avatar Oct 03 '13 09:10 mirasrael

I think it's a good candidate for a virtus plugin

solnic avatar Oct 03 '13 10:10 solnic

What is better point to extend Virtus with this kind of functionality? We can override attribute to catch annotations option, but it may be handy to obtain annotations direct from attribute and how to implement this without monkey patching?

mirasrael avatar Oct 03 '13 11:10 mirasrael

:+1: I think virtus should pay attention to "reflection api" and meta information! It would be very useful in datamappers, serializers, etc (this is already used in java, .net) Attribute annotations is looking like core functionality. When you declare attribute, you already attach type meta information to it, why not just give container for any additional meta data (like attribute.meta || attribute.annotations)?

This feature also gives good extension point for plugins :)

niquola avatar Oct 03 '13 11:10 niquola

I'm fine with a plugin and maybe merging it in later for virtus 2.0.0. Now it's not a good moment as the code base is already very complex due to keeping backward compatibility with 0.5.x.

I already have some initial work done for 'extension' interface so that you can attach additional behaviour to an attribute instance. This could be used to add 'annotation' feature.

All options passed to an attribute are saved and are accessible via Attribute#options so it's a matter of adding one method to Attribute that returns annotations:

module Virtus
  class Attribute
    module Annotated
       def annotations
          options[:annotations]
       end
    end
  end
end

attr = Virtus::Attribute.build(String, annotations: { wrap: 'entry' })
attr.extend(Virtus::Attribute::Annotated)
attr.annotations # => { wrap: 'entry' }

solnic avatar Oct 03 '13 11:10 solnic

...I could introduce a new interface for registering custom extensions, something like that maybe:

Virtus::Attribute.register_extension(Virtus::Attribute::Annotated)

# it would require some method that would tell virtus when to use it, maybe something like this:

module Virtus::Attribute::Annotated
  def extend?(options)
    options.key?(:annotations)
  end
end

it's a simple addition that I could include in 1.0.0 final

solnic avatar Oct 03 '13 11:10 solnic

Yes, it looks good. Thank you.

mirasrael avatar Oct 03 '13 11:10 mirasrael

@mirasrael I wanted to introduce that interface anyway so it's cool to know people need that :)

solnic avatar Oct 03 '13 11:10 solnic

@solnic I glad to be one of the first consumers of this interface ;)

mirasrael avatar Oct 03 '13 11:10 mirasrael

+1 useful for auto generated documentation

dapi avatar Apr 09 '15 17:04 dapi