Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass options to Builder::XmlMarkup #35

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions lib/gyoku/array.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,19 @@ class Array
# Translates a given +array+ to XML. Accepts the XML +key+ to add the elements to,
# whether to +escape_xml+ and an optional Hash of +attributes+.
def self.to_xml(array, key, escape_xml = true, attributes = {}, options = {})
options[:builder] ||= {}
options[:builder][:indent] ||= 0
options[:builder][:margin] ||= 0
self_closing = options.delete(:self_closing)
iterate_with_xml array, attributes do |xml, item, attrs, index|
iterate_with_xml array, attributes, options do |xml, item, attrs, index|
if self_closing
xml.tag!(key, attrs)

else
case item
when ::Hash then xml.tag!(key, attrs) { xml << Hash.to_xml(item, options) }
when NilClass then xml.tag!(key, "xsi:nil" => "true")
else xml.tag!(key, attrs) { xml << XMLValue.create(item, escape_xml) }
else xml.tag!(key, attrs, false, XMLValue.create(item, escape_xml))
end
end
end
Expand All @@ -28,8 +31,9 @@ def self.to_xml(array, key, escape_xml = true, attributes = {}, options = {})

# Iterates over a given +array+ with a Hash of +attributes+ and yields a builder +xml+
# instance, the current +item+, any XML +attributes+ and the current +index+.
def self.iterate_with_xml(array, attributes)
xml = Builder::XmlMarkup.new
def self.iterate_with_xml(array, attributes, options = {})
xml = Builder::XmlMarkup.new(options[:builder] || {})
options[:builder][:margin] += 1
array.each_with_index do |item, index|
if item.respond_to?(:keys)
attrs = item.reduce({}) do |st, v|
Expand All @@ -42,6 +46,7 @@ def self.iterate_with_xml(array, attributes)
end
yield xml, item, tag_attributes(attributes, index).merge(attrs), index
end
options[:builder][:margin] -= 1
xml.target!
end

Expand Down
13 changes: 9 additions & 4 deletions lib/gyoku/hash.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ class Hash

# Translates a given +hash+ with +options+ to XML.
def self.to_xml(hash, options = {})
iterate_with_xml hash do |xml, key, value, attributes|
options[:builder] ||= {}
options[:builder][:indent] ||= 0
options[:builder][:margin] ||= 0
iterate_with_xml hash, options do |xml, key, value, attributes|
self_closing = key.to_s[-1, 1] == "/"
escape_xml = key.to_s[-1, 1] != "!"
xml_key = XMLKey.create key, options
Expand All @@ -20,7 +23,7 @@ def self.to_xml(hash, options = {})
when ::Hash === value then xml.tag!(xml_key, attributes) { xml << Hash.to_xml(value, options) }
when self_closing then xml.tag!(xml_key, attributes)
when NilClass === value then xml.tag!(xml_key, "xsi:nil" => "true")
else xml.tag!(xml_key, attributes) { xml << XMLValue.create(value, escape_xml) }
else xml.tag!(xml_key, attributes, false, XMLValue.create(value, escape_xml))
end
end
end
Expand All @@ -33,11 +36,12 @@ def self.to_xml(hash, options = {})
# Keys beginning with "@" are treated as explicit attributes for their container.
# You can use both :attributes! and "@" keys to specify attributes.
# In the event of a conflict, the "@" key takes precedence.
def self.iterate_with_xml(hash)
xml = Builder::XmlMarkup.new
def self.iterate_with_xml(hash, options = {})
xml = Builder::XmlMarkup.new(options[:builder] || {})
attributes = hash[:attributes!] || {}
hash_without_attributes = hash.reject { |key, value| key == :attributes! }

options[:builder][:margin] += 1
order(hash_without_attributes).each do |key|
node_attr = attributes[key] || {}
# node_attr must be kind of ActiveSupport::HashWithIndifferentAccess
Expand All @@ -57,6 +61,7 @@ def self.iterate_with_xml(hash)

yield xml, key, node_value, node_attr
end
options[:builder][:margin] -= 1

xml.target!
end
Expand Down
6 changes: 6 additions & 0 deletions spec/gyoku/array_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,12 @@

to_xml(array, "value", :escape_xml, :id => [1, 2]).should == result
end

it "should pass options to XML Builder" do
array = [{ :name => "adam" }, { :name => "eve" }]
result = "<user>\n <name>adam</name>\n</user>\n<user>\n <name>eve</name>\n</user>\n"
to_xml(array, "user", true, {}, { :builder => {:indent => 2} }).should == result
end
end

def to_xml(*args)
Expand Down
6 changes: 6 additions & 0 deletions spec/gyoku/hash_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,12 @@ def singleton.to_datetime
:attributes! => { :countries => { :array => true } }
}
end

it "should pass options to XML Builder" do
hash = {:some => { :new => "user" }}
result = "<some>\n <new>user</new>\n</some>\n"
to_xml(hash, { :builder => {:indent => 2} }).should == result
end
end

it "doesn't modify original hash parameter by deleting its attribute keys" do
Expand Down