summaryrefslogtreecommitdiff
path: root/ext
diff options
context:
space:
mode:
authornick evans <[email protected]>2024-10-28 15:41:26 -0400
committergit <[email protected]>2025-05-01 17:52:14 +0000
commit136dc52663b3e3a1a6c4efd3c4621ea2a7aacd17 ()
tree07c2982b32ffb0ebd1aacb76c392c2e7e1cef7ae /ext
parenta397e4d4b0a0e7e8499a33ec760dba97ce494c63 (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.rb23
-rw-r--r--ext/psych/lib/psych/visitors/yaml_tree.rb40
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