ruby/test/psych/test_data.rb
nick evans 136dc52663 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.
2025-05-01 17:52:14 +00:00

69 lines
1.5 KiB
Ruby

# frozen_string_literal: true
require_relative 'helper'
class PsychDataWithIvar < Data.define(:foo)
attr_reader :bar
def initialize(**)
@bar = 'hello'
super
end
end unless RUBY_VERSION < "3.2"
module Psych
class TestData < TestCase
class SelfReferentialData < Data.define(:foo)
attr_accessor :ref
def initialize(foo:)
@ref = self
super
end
end unless RUBY_VERSION < "3.2"
def setup
omit "Data requires ruby >= 3.2" if RUBY_VERSION < "3.2"
end
# TODO: move to another test?
def test_dump_data
assert_equal <<~eoyml, Psych.dump(PsychDataWithIvar["bar"])
--- !ruby/data-with-ivars:PsychDataWithIvar
members:
foo: bar
ivars:
"@bar": hello
eoyml
end
def test_self_referential_data
circular = SelfReferentialData.new("foo")
loaded = Psych.unsafe_load(Psych.dump(circular))
assert_instance_of(SelfReferentialData, loaded.ref)
assert_equal(circular, loaded)
assert_same(loaded, loaded.ref)
end
def test_roundtrip
thing = PsychDataWithIvar.new("bar")
data = Psych.unsafe_load(Psych.dump(thing))
assert_equal "hello", data.bar
assert_equal "bar", data.foo
end
def test_load
obj = Psych.unsafe_load(<<~eoyml)
--- !ruby/data-with-ivars:PsychDataWithIvar
members:
foo: bar
ivars:
"@bar": hello
eoyml
assert_equal "hello", obj.bar
assert_equal "bar", obj.foo
end
end
end