diff options
author | nick evans <[email protected]> | 2024-10-28 15:41:26 -0400 |
---|---|---|
committer | git <[email protected]> | 2025-05-01 17:52:14 +0000 |
commit | 136dc52663b3e3a1a6c4efd3c4621ea2a7aacd17 () | |
tree | 07c2982b32ffb0ebd1aacb76c392c2e7e1cef7ae /ext | |
parent | a397e4d4b0a0e7e8499a33ec760dba97ce494c63 (diff) |
Add support for Data objects with ivars
This sets the ivars _before_ calling initialize, which feels wrong. But Data doesn't give us any mechanism for setting the members other than 1) initialize, or 2) drop down into the C API. Since initialize freezes the object, we need to set the ivars before that. I think this is a reasonable compromise—if users need better handling, they can implement their own `encode_with` and `init_with`. But it will lead to unhappy surprises for some users. Alternatively, we could use the C API, similarly to Marshal. Psych _is_ already using the C API for path2class and build_exception. This would be the least surprising behavior for users, I think.
-rw-r--r-- | ext/psych/lib/psych/visitors/to_ruby.rb | 23 | ||||
-rw-r--r-- | ext/psych/lib/psych/visitors/yaml_tree.rb | 40 |
2 files changed, 54 insertions, 9 deletions
@@ -197,10 +197,27 @@ module Psych s end - when /^!ruby\/data(?::(.*))?$/ - data = register(o, resolve_class($1).allocate) if $1 members = {} - revive_data_members(members, o) data ||= allocate_anon_data(o, members) data.send(:initialize, **members) data @@ -163,13 +163,41 @@ module Psych alias :visit_Delegator :visit_Object def visit_Data o - tag = ['!ruby/data', o.class.name].compact.join(':') - register o, @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK) - o.members.each do |member| - @emitter.scalar member.to_s, nil, nil, true, false, Nodes::Scalar::ANY - accept o.send member end - @emitter.end_mapping end def visit_Struct o |