Skip to content

Commit 7351ccd

Browse files
committed
support :order! key with value :schema_order
1 parent 2fd02fb commit 7351ccd

File tree

2 files changed

+48
-1
lines changed

2 files changed

+48
-1
lines changed

lib/savon/qualified_message.rb

+19-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@ def to_hash(hash, path)
1414
return hash.map { |value| to_hash(value, path) } if hash.is_a?(Array)
1515
return hash.to_s unless hash.is_a?(Hash)
1616

17-
hash.each_with_object({}) do |(key, value), newhash|
17+
if hash[:order!] == :use_schema || @order_with_schema
18+
@order_with_schema = true
19+
ordered_keys = @used_namespaces.select { |t| t.first == path.first && t.length == 2 }.keys.collect { |k| k.last }
20+
hash[:order!] = ordered_keys
21+
end
22+
23+
result = hash.each_with_object({}) do |(key, value), newhash|
1824
case key
1925
when :order!
2026
newhash[key] = add_namespaces_to_values(value, path)
@@ -32,6 +38,8 @@ def to_hash(hash, path)
3238
end
3339
newhash
3440
end
41+
42+
ordered_keys(result)
3543
end
3644

3745
private
@@ -48,5 +56,15 @@ def add_namespaces_to_values(values, path)
4856
namespace.empty? ? value : "#{namespace}:#{translated_value}"
4957
end
5058
end
59+
60+
def ordered_keys(hash)
61+
return hash unless @order_with_schema
62+
63+
if order_keys = hash.delete(:order!)
64+
present_order_keys = order_keys & hash.keys
65+
hash[:order!] = (present_order_keys + (hash.keys - present_order_keys)).select { |key| !key.to_s.end_with?('!') }
66+
end
67+
hash
68+
end
5169
end
5270
end

spec/savon/qualified_message_spec.rb

+29
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,35 @@ module Savon
6464
expect(xml).to eq good_xml
6565
end
6666

67+
it "uses schema order when :order! is set to :use_schema" do
68+
used_namespaces = {
69+
%w(tns Foo) => 'ns'
70+
}
71+
72+
hash = {
73+
:foo => {
74+
:order! => :use_schema,
75+
:bar => 'zing',
76+
:cash => 'pow'
77+
}
78+
}
79+
80+
good_result = {
81+
"ns:Foo" => {
82+
:order! => [:bar, :cash],
83+
:bar => 'zing',
84+
:cash => 'pow'
85+
}
86+
}
87+
88+
message = described_class.new(types, used_namespaces, key_converter)
89+
resulting_hash = message.to_hash(hash, ['tns'])
90+
91+
expect(Gyoku.xml(resulting_hash, key_converter: key_converter)).to eq %(<ns:Foo><Bar>zing</Bar><Cash>pow</Cash></ns:Foo>)
92+
expect(resulting_hash).to eq good_result
93+
94+
end
95+
6796
it "properly handles boolean false" do
6897
used_namespaces = {
6998
%w(tns Foo) => 'ns'

0 commit comments

Comments
 (0)