virtus icon indicating copy to clipboard operation
virtus copied to clipboard

Recursively call attributes

Open jaimerson opened this issue 11 years ago • 8 comments

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>] }

jaimerson avatar Aug 22 '14 15:08 jaimerson

I look for something like that.

AlfonsoUceda avatar Sep 11 '14 09:09 AlfonsoUceda

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

solnic avatar Sep 11 '14 09:09 solnic

thanks @solnic ;)

AlfonsoUceda avatar Sep 11 '14 10:09 AlfonsoUceda

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 avatar Jul 04 '15 01:07 bradrobertson

@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.

solnic avatar Jul 15 '15 11:07 solnic

It seems like to_json works as expected by converting all nested models. So a workaround might be JSON.parse(model.to_json).

derekclee avatar Jan 21 '16 06:01 derekclee

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>

ilnurnasyrov2 avatar Jan 10 '17 22:01 ilnurnasyrov2

Is there a recommended way to accomplish this?

filipesperandio avatar Jun 23 '17 20:06 filipesperandio