virtus
virtus copied to clipboard
Support annotations/meta information for attribute
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'
I think it's a good candidate for a virtus plugin
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?
:+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 :)
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' }
...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
Yes, it looks good. Thank you.
@mirasrael I wanted to introduce that interface anyway so it's cool to know people need that :)
@solnic I glad to be one of the first consumers of this interface ;)
+1 useful for auto generated documentation