зеркало из https://github.com/github/ruby.git
[ruby/ostruct] Improved YAML serialization.
Patch adapted from Pietro Monteiro [Fixes bug#8382]
This commit is contained in:
Родитель
0e93118c44
Коммит
b36a45c05c
1
NEWS.md
1
NEWS.md
|
@ -275,6 +275,7 @@ Outstanding ones only.
|
|||
* Builtin methods can now be overridden safely. [[Bug #15409]]
|
||||
* Implementation uses only methods ending with `!`.
|
||||
* Ractor compatible.
|
||||
* Improved support for YAML [[Bug #8382]]
|
||||
* Use officially discouraged. Read "Caveats" section.
|
||||
|
||||
* Reline
|
||||
|
|
|
@ -398,6 +398,33 @@ class OpenStruct
|
|||
@table.hash
|
||||
end
|
||||
|
||||
#
|
||||
# Provides marshalling support for use by the YAML library.
|
||||
#
|
||||
def encode_with(coder) # :nodoc:
|
||||
@table.each_pair do |key, value|
|
||||
coder[key.to_s] = value
|
||||
end
|
||||
if @table.size == 1 && @table.key?(:table) # support for legacy format
|
||||
# in the very unlikely case of a single entry called 'table'
|
||||
coder['legacy_support!'] = true # add a bogus second entry
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Provides marshalling support for use by the YAML library.
|
||||
#
|
||||
def init_with(coder) # :nodoc:
|
||||
h = coder.map
|
||||
if h.size == 1 # support for legacy format
|
||||
key, val = h.first
|
||||
if key == 'table'
|
||||
h = val
|
||||
end
|
||||
end
|
||||
update_to_values!(h)
|
||||
end
|
||||
|
||||
# Make all public methods (builtin or our own) accessible with `!`:
|
||||
instance_methods.each do |method|
|
||||
new_name = "#{method}!"
|
||||
|
|
|
@ -37,7 +37,9 @@ describe "YAML.dump" do
|
|||
it "dumps an OpenStruct" do
|
||||
require "ostruct"
|
||||
os = OpenStruct.new("age" => 20, "name" => "John")
|
||||
YAML.dump(os).should match_yaml("--- !ruby/object:OpenStruct\ntable:\n :age: 20\n :name: John\n")
|
||||
os2 = YAML.load(YAML.dump(os))
|
||||
os2.age.should == 20
|
||||
os2.name.should == "John"
|
||||
end
|
||||
|
||||
it "dumps a File without any state" do
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
require 'test/unit'
|
||||
require 'ostruct'
|
||||
require 'yaml'
|
||||
|
||||
class TC_OpenStruct < Test::Unit::TestCase
|
||||
def test_initialize
|
||||
|
@ -309,4 +310,24 @@ class TC_OpenStruct < Test::Unit::TestCase
|
|||
end.take
|
||||
assert obj1.object_id == obj2.object_id
|
||||
end if defined?(Ractor)
|
||||
|
||||
def test_legacy_yaml
|
||||
s = "--- !ruby/object:OpenStruct\ntable:\n :foo: 42\n"
|
||||
o = YAML.load(s)
|
||||
assert_equal(42, o.foo)
|
||||
|
||||
o = OpenStruct.new(table: {foo: 42})
|
||||
assert_equal({foo: 42}, YAML.load(YAML.dump(o)).table)
|
||||
end
|
||||
|
||||
def test_yaml
|
||||
h = {name: "John Smith", age: 70, pension: 300.42}
|
||||
yaml = "--- !ruby/object:OpenStruct\nname: John Smith\nage: 70\npension: 300.42\n"
|
||||
os1 = OpenStruct.new(h)
|
||||
os2 = YAML.load(os1.to_yaml)
|
||||
assert_equal yaml, os1.to_yaml
|
||||
assert_equal os1, os2
|
||||
assert_equal true, os1.eql?(os2)
|
||||
assert_equal 300.42, os2.pension
|
||||
end
|
||||
end
|
||||
|
|
Загрузка…
Ссылка в новой задаче