Let's say we have a Virtus model User
class User
include Virtus.model
attribute :name, String, default: 'John', lazy: true
end
Then we create an instance of this model and extend from Virtus.model to add another attribute on the fly:
user = User.new
user.extend(Virtus.model)
user.attribute(:active, Virtus::Attribute::Boolean, default: true, lazy: true)
Current output:
user.active? # => true
user.name # => 'John'
But when I try to get either attributes or convert the object to JSON via as_json(or to_json) or Hash via to_h I get only post-extended attribute active:
user.to_h # => { active: true }
What is causing the problem and how can I get to convert the object without loosing the data?
P.S.
I have found a github issue, but it seems that it was not fixed after all (the approach recommended there doesn't work stably as well).
Building on Adrian's finding, here is a way to modify Virtus to allow what you want. All specs pass with this modification.
Essentially, Virtus already has the concept of a parent
AttributeSet, but it's only when includingVirtus.modelin a class. We can extend it to consider instances as well, and even allow multipleextend(Virtus.model)in the same object (although that sounds sub-optimal):Maybe this is worth making a PR to Virtus, what do you think?