virtus
virtus copied to clipboard
Recursively call attributes
Suppose I have a class Foo, which has an array of Bar objects, as follows:
class Foo
include Virtus.model
attribute :bars, Array[Bar]
end
class Bar
include Virtus.model
attribute :baz
attributes :bamboo
end
Is there a way to retrieve a attributes hash for each Bar ({ bars: [ {baz:1, bamboo: 2}] }) when I call Foo#attributes? Calling attributes gives me this:
Foo.new(bars: [{baz: 1, bamboo: 2}]).attributes
# => { bars: [#<Bar:0xfd54ad3, @baz=1, @bamboo=2>] }
I look for something like that.
This will be addressed in virtus 2.0 refactoring. #attributes (and effectively #to_h and #to_hash) will be removed from virtus' core and moved to some external gem
thanks @solnic ;)
This would be useful to me as well. IMO to_h and to_hash should not alias attributes but instead return a pure hash. Would a PR in the interim modifying to_h and to_hash to return pure hashes be useful?
Unless 2.0 is right around the corner, but it doesn't look like that's the case.
@bradrobertson we can add that with a limitation that when there are cross-references it will blow up with a stack too deep. You could use a recursion guard too but that will slow it down. I think it's fine to clearly document it and call it a day.
It seems like to_json works as expected by converting all nested models. So a workaround might be JSON.parse(model.to_json).
It seems like to_json works as expected by converting all nested models. So a workaround might be JSON.parse(model.to_json).
looks like this workaround doesn't work anymore
require 'virtus'
class User
include Virtus.model
end
User.new.to_json #=> NoMethodError: undefined method `to_json' for #<User:0x007fed648427c8>
Is there a recommended way to accomplish this?