gyoku 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +9 -0
- data/.rspec +1 -0
- data/Gemfile +2 -0
- data/LICENSE +20 -0
- data/README.md +56 -0
- data/Rakefile +42 -0
- data/autotest/discover.rb +1 -0
- data/gyoku.gemspec +25 -0
- data/lib/gyoku.rb +14 -0
- data/lib/gyoku/array.rb +48 -0
- data/lib/gyoku/core_ext/string.rb +18 -0
- data/lib/gyoku/hash.rb +57 -0
- data/lib/gyoku/version.rb +5 -0
- data/lib/gyoku/xml_key.rb +22 -0
- data/lib/gyoku/xml_value.rb +23 -0
- data/spec/gyoku/array_spec.rb +53 -0
- data/spec/gyoku/core_ext/string_spec.rb +11 -0
- data/spec/gyoku/hash_spec.rb +125 -0
- data/spec/gyoku/xml_key_spec.rb +18 -0
- data/spec/gyoku/xml_value_spec.rb +41 -0
- data/spec/gyoku_spec.rb +17 -0
- data/spec/spec_helper.rb +2 -0
- metadata +141 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Daniel Harrington
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
Gyoku
|
2
|
+
=====
|
3
|
+
|
4
|
+
Gyoku translates Ruby Hashes to XML.
|
5
|
+
|
6
|
+
[Bugs](http://github.com/rubiii/gyoku/issues) | [Docs](http://rubydoc.info/gems/gyoku/frames)
|
7
|
+
|
8
|
+
Installation
|
9
|
+
------------
|
10
|
+
|
11
|
+
The gem is available through [Rubygems](http://rubygems.org/gems/gyoku) and can be installed via:
|
12
|
+
|
13
|
+
$ gem install gyoku
|
14
|
+
|
15
|
+
An example
|
16
|
+
----------
|
17
|
+
|
18
|
+
Gyoku.xml :find_user => { :id => 123, "wsdl:Key" => "api" }
|
19
|
+
# => "<findUser><id>123</id><wsdl:Key>api</wsdl:Key></findUser>"
|
20
|
+
|
21
|
+
As you might notice, Gyoku follows a couple of conventions for translating Hashes into XML.
|
22
|
+
|
23
|
+
Conventions
|
24
|
+
-----------
|
25
|
+
|
26
|
+
* Hash key Symbols are converted to lowerCamelCase Strings
|
27
|
+
* Hash key Strings are not converted and may contain namespaces
|
28
|
+
* DateTime values are converted to xs:dateTime Strings
|
29
|
+
* Objects responding to :to_datetime (except Strings) are converted to xs:dateTime Strings
|
30
|
+
* TrueClass and FalseClass objects are converted to "true" and "false" Strings
|
31
|
+
* NilClass objects are converted to xsi:nil tags
|
32
|
+
* All other objects are converted to Strings using :to_s
|
33
|
+
|
34
|
+
Special characters
|
35
|
+
------------------
|
36
|
+
|
37
|
+
Gyoku escapes special characters unless the Hash key ends with an exclamation mark:
|
38
|
+
|
39
|
+
Gyoku.xml :escaped => "<tag />", :not_escaped! => "<tag />"
|
40
|
+
# => "<escaped><tag /></escaped><notEscaped><tag /></notEscaped>"
|
41
|
+
|
42
|
+
Sort XML tags
|
43
|
+
-------------
|
44
|
+
|
45
|
+
In case you need the XML tags to be in a specific order, you can specify the order through an additional Array stored under an :order! key:
|
46
|
+
|
47
|
+
Gyoku.xml :name => "Eve", :id => 1, :order! => [:id, :name]
|
48
|
+
# => "<id>1</id><name>Eve</name>"
|
49
|
+
|
50
|
+
XML attributes
|
51
|
+
--------------
|
52
|
+
|
53
|
+
Adding XML attributes is rather ugly, but it can be done by specifying an additional Hash stored under an :attributes! key:
|
54
|
+
|
55
|
+
Gyoku.xml :person => "Eve", :attributes! => { :person => { :id => 1 } }
|
56
|
+
# => "<person id=\"1\">Eve</person>"
|
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require "bundler"
|
2
|
+
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
task :default => :spec
|
5
|
+
|
6
|
+
begin
|
7
|
+
require "yard"
|
8
|
+
|
9
|
+
YARD::Rake::YardocTask.new do |t|
|
10
|
+
t.files = ["README.md", "lib/**/*.rb"]
|
11
|
+
end
|
12
|
+
rescue LoadError
|
13
|
+
desc message = %{"gem install yard" to generate documentation}
|
14
|
+
task("yard") { abort message }
|
15
|
+
end
|
16
|
+
|
17
|
+
begin
|
18
|
+
require "metric_fu"
|
19
|
+
|
20
|
+
MetricFu::Configuration.run do |c|
|
21
|
+
c.metrics = [:churn, :flog, :flay, :reek, :roodi, :saikuro] # :rcov seems to be broken
|
22
|
+
c.graphs = [:flog, :flay, :reek, :roodi]
|
23
|
+
c.flay = { :dirs_to_flay => ["lib"], :minimum_score => 20 }
|
24
|
+
c.rcov[:rcov_opts] << "-Ilib -Ispec"
|
25
|
+
end
|
26
|
+
rescue LoadError
|
27
|
+
desc message = %{"gem install metric_fu" to generate metrics}
|
28
|
+
task("metrics:all") { abort message }
|
29
|
+
end
|
30
|
+
|
31
|
+
begin
|
32
|
+
require "rspec/core/rake_task"
|
33
|
+
|
34
|
+
RSpec::Core::RakeTask.new do |t|
|
35
|
+
t.pattern = "spec/**/*_spec.rb"
|
36
|
+
t.rspec_opts = %w(-fd -c)
|
37
|
+
end
|
38
|
+
rescue LoadError
|
39
|
+
task :spec do
|
40
|
+
abort "Run 'gem install rspec' to be able to run specs"
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Autotest.add_discovery { "rspec2" }
|
data/gyoku.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
require "gyoku/version"
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "gyoku"
|
6
|
+
s.version = Gyoku::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = "Daniel Harrington"
|
9
|
+
s.email = "me@rubiii.com"
|
10
|
+
s.homepage = "http://github.com/rubiii/#{s.name}"
|
11
|
+
s.summary = %q{Converts Ruby Hashes to XML}
|
12
|
+
s.description = %q{Gyoku converts Ruby Hashes to XML}
|
13
|
+
|
14
|
+
s.rubyforge_project = "gyoku"
|
15
|
+
|
16
|
+
s.add_dependency "builder", "~> 2.1.2"
|
17
|
+
|
18
|
+
s.add_development_dependency "rspec", "2.0.0"
|
19
|
+
s.add_development_dependency "mocha", "~> 0.9.9"
|
20
|
+
|
21
|
+
s.files = `git ls-files`.split("\n")
|
22
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
23
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
24
|
+
s.require_paths = ["lib"]
|
25
|
+
end
|
data/lib/gyoku.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require "gyoku/version"
|
2
|
+
require "gyoku/hash"
|
3
|
+
|
4
|
+
module Gyoku
|
5
|
+
|
6
|
+
def self.xml(object)
|
7
|
+
case object
|
8
|
+
when ::Hash then Hash.to_xml object
|
9
|
+
when ::Array then Array.to_xml object
|
10
|
+
else raise ArgumentError, "Expected kind_of Array || Hash"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
data/lib/gyoku/array.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require "builder"
|
2
|
+
|
3
|
+
require "gyoku/hash"
|
4
|
+
require "gyoku/xml_key"
|
5
|
+
require "gyoku/xml_value"
|
6
|
+
|
7
|
+
module Gyoku
|
8
|
+
class Array
|
9
|
+
extend XMLKey
|
10
|
+
extend XMLValue
|
11
|
+
|
12
|
+
# Translates a given +array+ to XML. Accepts the XML +key+ to add the elements to,
|
13
|
+
# whether to +escape_xml+ and an optional Hash of +attributes+.
|
14
|
+
def self.to_xml(array, key, escape_xml = true, attributes = {})
|
15
|
+
iterate_with_xml array, attributes do |xml, item, attrs, index|
|
16
|
+
case item
|
17
|
+
when ::Hash then xml.tag!(key, attrs) { xml << Hash.to_xml(item) }
|
18
|
+
when NilClass then xml.tag!(key, "xsi:nil" => "true")
|
19
|
+
else xml.tag!(key, attrs) { xml << to_xml_value(item, escape_xml) }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
# Iterates over a given +array+ with a Hash of +attributes+ and yields a builder +xml+
|
27
|
+
# instance, the current +item+, any XML +attributes+ and the current +index+.
|
28
|
+
def self.iterate_with_xml(array, attributes)
|
29
|
+
xml = Builder::XmlMarkup.new
|
30
|
+
array.each_with_index do |item, index|
|
31
|
+
yield xml, item, tag_attributes(attributes, index), index
|
32
|
+
end
|
33
|
+
xml.target!
|
34
|
+
end
|
35
|
+
|
36
|
+
# Takes a Hash of +attributes+ and the +index+ for which to return attributes
|
37
|
+
# for duplicate tags.
|
38
|
+
def self.tag_attributes(attributes, index)
|
39
|
+
return {} if attributes.empty?
|
40
|
+
|
41
|
+
attributes.inject({}) do |hash, (key, value)|
|
42
|
+
value = value[index] if value.kind_of? ::Array
|
43
|
+
hash.merge key => value
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Gyoku
|
2
|
+
module CoreExt
|
3
|
+
module String
|
4
|
+
|
5
|
+
# Returns the String in lowerCamelCase.
|
6
|
+
def lower_camelcase
|
7
|
+
str = dup
|
8
|
+
str.gsub!(/\/(.?)/) { "::#{$1.upcase}" }
|
9
|
+
str.gsub!(/(?:_+|-+)([a-z])/) { $1.upcase }
|
10
|
+
str.gsub!(/(\A|\s)([A-Z])/) { $1 + $2.downcase }
|
11
|
+
str
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
String.send :include, Gyoku::CoreExt::String
|
data/lib/gyoku/hash.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require "builder"
|
2
|
+
|
3
|
+
require "gyoku/array"
|
4
|
+
require "gyoku/xml_key"
|
5
|
+
require "gyoku/xml_value"
|
6
|
+
|
7
|
+
module Gyoku
|
8
|
+
class Hash
|
9
|
+
extend XMLKey
|
10
|
+
extend XMLValue
|
11
|
+
|
12
|
+
# Translates a given +hash+ to XML.
|
13
|
+
def self.to_xml(hash)
|
14
|
+
iterate_with_xml hash do |xml, key, attributes|
|
15
|
+
attrs = attributes[key] || {}
|
16
|
+
value = hash[key]
|
17
|
+
escape_xml = key.to_s[-1, 1] != "!"
|
18
|
+
key = to_xml_key(key)
|
19
|
+
|
20
|
+
case value
|
21
|
+
when ::Array then xml << Array.to_xml(value, key, escape_xml, attrs)
|
22
|
+
when ::Hash then xml.tag!(key, attrs) { xml << Hash.to_xml(value) }
|
23
|
+
when NilClass then xml.tag!(key, "xsi:nil" => "true")
|
24
|
+
else xml.tag!(key, attrs) { xml << to_xml_value(value, escape_xml) }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
# Iterates over a given +hash+ and yields a builder +xml+ instance, the current
|
32
|
+
# Hash +key+ and any XML +attributes+.
|
33
|
+
def self.iterate_with_xml(hash)
|
34
|
+
xml = Builder::XmlMarkup.new
|
35
|
+
attributes = hash.delete(:attributes!) || {}
|
36
|
+
|
37
|
+
order(hash).each { |key| yield xml, key, attributes }
|
38
|
+
|
39
|
+
xml.target!
|
40
|
+
end
|
41
|
+
|
42
|
+
# Deletes and returns an Array of keys stored under the :order! key of a given +hash+.
|
43
|
+
# Defaults to return the actual keys of the Hash if no :order! key could be found.
|
44
|
+
# Raises an ArgumentError in case the :order! Array does not match the Hash keys.
|
45
|
+
def self.order(hash)
|
46
|
+
order = hash.delete :order!
|
47
|
+
order = hash.keys unless order.kind_of? ::Array
|
48
|
+
|
49
|
+
missing, spurious = hash.keys - order, order - hash.keys
|
50
|
+
raise ArgumentError, "Missing elements in :order! #{missing.inspect}" unless missing.empty?
|
51
|
+
raise ArgumentError, "Spurious elements in :order! #{spurious.inspect}" unless spurious.empty?
|
52
|
+
|
53
|
+
order
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "gyoku/core_ext/string"
|
2
|
+
|
3
|
+
module Gyoku
|
4
|
+
module XMLKey
|
5
|
+
|
6
|
+
# Converts a given +object+ to an XML key.
|
7
|
+
def to_xml_key(key)
|
8
|
+
case key
|
9
|
+
when Symbol then chop_exclamation_mark(key.to_s).lower_camelcase
|
10
|
+
else chop_exclamation_mark(key.to_s)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
# Chops existing exclamation marks from the end of a given +string+.
|
17
|
+
def chop_exclamation_mark(string)
|
18
|
+
string[-1, 1] == "!" ? string.chop : string
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require "cgi"
|
2
|
+
|
3
|
+
module Gyoku
|
4
|
+
module XMLValue
|
5
|
+
|
6
|
+
# xs:dateTime format.
|
7
|
+
XS_DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%S%Z"
|
8
|
+
|
9
|
+
# Converts a given +object+ to an XML value.
|
10
|
+
def to_xml_value(object, escape_xml = true)
|
11
|
+
if DateTime === object
|
12
|
+
object.strftime XS_DATETIME_FORMAT
|
13
|
+
elsif String === object
|
14
|
+
escape_xml ? CGI.escapeHTML(object) : object
|
15
|
+
elsif object.respond_to?(:to_datetime)
|
16
|
+
to_xml_value object.to_datetime
|
17
|
+
else
|
18
|
+
object.to_s
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Gyoku::Array do
|
4
|
+
|
5
|
+
describe ".to_xml" do
|
6
|
+
it "should return the XML for an Array of Hashes" do
|
7
|
+
array = [{ :name => "adam" }, { :name => "eve" }]
|
8
|
+
result = "<user><name>adam</name></user><user><name>eve</name></user>"
|
9
|
+
|
10
|
+
to_xml(array, "user").should == result
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should return the XML for an Array of different Objects" do
|
14
|
+
array = [:symbol, "string", 123]
|
15
|
+
result = "<value>symbol</value><value>string</value><value>123</value>"
|
16
|
+
|
17
|
+
to_xml(array, "value").should == result
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should default to escape special characters" do
|
21
|
+
array = ["<tag />", "adam & eve"]
|
22
|
+
result = "<value><tag /></value><value>adam & eve</value>"
|
23
|
+
|
24
|
+
to_xml(array, "value").should == result
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should not escape special characters when told to" do
|
28
|
+
array = ["<tag />", "adam & eve"]
|
29
|
+
result = "<value><tag /></value><value>adam & eve</value>"
|
30
|
+
|
31
|
+
to_xml(array, "value", false).should == result
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should add attributes to a given tag" do
|
35
|
+
array = ["adam", "eve"]
|
36
|
+
result = '<value active="true">adam</value><value active="true">eve</value>'
|
37
|
+
|
38
|
+
to_xml(array, "value", :escape_xml, :active => true).should == result
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should add attributes to duplicate tags" do
|
42
|
+
array = ["adam", "eve"]
|
43
|
+
result = '<value id="1">adam</value><value id="2">eve</value>'
|
44
|
+
|
45
|
+
to_xml(array, "value", :escape_xml, :id => [1, 2]).should == result
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_xml(*args)
|
50
|
+
Gyoku::Array.to_xml *args
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Gyoku::Hash do
|
4
|
+
|
5
|
+
describe ".to_xml" do
|
6
|
+
describe "should return SOAP request compatible XML" do
|
7
|
+
it "for a simple Hash" do
|
8
|
+
to_xml(:some => "user").should == "<some>user</some>"
|
9
|
+
end
|
10
|
+
|
11
|
+
it "for a nested Hash" do
|
12
|
+
to_xml(:some => { :new => "user" }).should == "<some><new>user</new></some>"
|
13
|
+
end
|
14
|
+
|
15
|
+
it "for a Hash with multiple keys" do
|
16
|
+
to_xml(:all => "users", :before => "whatever").should include(
|
17
|
+
"<all>users</all>",
|
18
|
+
"<before>whatever</before>"
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "for a Hash containing an Array" do
|
23
|
+
to_xml(:some => ["user", "gorilla"]).should == "<some>user</some><some>gorilla</some>"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "for a Hash containing an Array of Hashes" do
|
27
|
+
to_xml(:some => [{ :new => "user" }, { :old => "gorilla" }]).
|
28
|
+
should == "<some><new>user</new></some><some><old>gorilla</old></some>"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should convert Hash key Symbols to lowerCamelCase" do
|
33
|
+
to_xml(:find_or_create => "user").should == "<findOrCreate>user</findOrCreate>"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should not convert Hash key Strings" do
|
37
|
+
to_xml("find_or_create" => "user").should == "<find_or_create>user</find_or_create>"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should convert DateTime objects to xs:dateTime compliant Strings" do
|
41
|
+
to_xml(:before => DateTime.new(2012, 03, 22, 16, 22, 33)).
|
42
|
+
should == "<before>2012-03-22T16:22:33+00:00</before>"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should convert Objects responding to to_datetime to xs:dateTime compliant Strings" do
|
46
|
+
singleton = Object.new
|
47
|
+
def singleton.to_datetime
|
48
|
+
DateTime.new(2012, 03, 22, 16, 22, 33)
|
49
|
+
end
|
50
|
+
|
51
|
+
to_xml(:before => singleton).should == "<before>2012-03-22T16:22:33+00:00</before>"
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should call to_s on Strings even if they respond to to_datetime" do
|
55
|
+
object = "gorilla"
|
56
|
+
object.expects(:to_datetime).never
|
57
|
+
|
58
|
+
to_xml(:name => object).should == "<name>gorilla</name>"
|
59
|
+
end
|
60
|
+
|
61
|
+
it "should properly serialize nil values" do
|
62
|
+
to_xml(:some => nil).should == '<some xsi:nil="true"/>'
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should call to_s on any other Object" do
|
66
|
+
[666, true, false].each do |object|
|
67
|
+
to_xml(:some => object).should == "<some>#{object}</some>"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should default to escape special characters" do
|
72
|
+
result = to_xml(:some => { :nested => "<tag />" }, :tag => "<tag />")
|
73
|
+
result.should include("<tag><tag /></tag>")
|
74
|
+
result.should include("<some><nested><tag /></nested></some>")
|
75
|
+
end
|
76
|
+
|
77
|
+
it "should not escape special characters for keys marked with an exclamation mark" do
|
78
|
+
result = to_xml(:some => { :nested! => "<tag />" }, :tag! => "<tag />")
|
79
|
+
result.should include("<tag><tag /></tag>")
|
80
|
+
result.should include("<some><nested><tag /></nested></some>")
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should preserve the order of Hash keys and values specified through :order!" do
|
84
|
+
hash = { :find_user => { :name => "Lucy", :id => 666, :order! => [:id, :name] } }
|
85
|
+
result = "<findUser><id>666</id><name>Lucy</name></findUser>"
|
86
|
+
to_xml(hash).should == result
|
87
|
+
|
88
|
+
hash = { :find_user => { :mname => "in the", :lname => "Sky", :fname => "Lucy", :order! => [:fname, :mname, :lname] } }
|
89
|
+
result = "<findUser><fname>Lucy</fname><mname>in the</mname><lname>Sky</lname></findUser>"
|
90
|
+
to_xml(hash).should == result
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should raise an error if the :order! Array does not match the Hash keys" do
|
94
|
+
hash = { :name => "Lucy", :id => 666, :order! => [:name] }
|
95
|
+
lambda { to_xml(hash) }.should raise_error(ArgumentError)
|
96
|
+
|
97
|
+
hash = { :by_name => { :name => "Lucy", :lname => "Sky", :order! => [:mname, :name] } }
|
98
|
+
lambda { to_xml(hash) }.should raise_error(ArgumentError)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should add attributes to Hash keys specified through :attributes!" do
|
102
|
+
hash = { :find_user => { :person => "Lucy", :attributes! => { :person => { :id => 666 } } } }
|
103
|
+
result = '<findUser><person id="666">Lucy</person></findUser>'
|
104
|
+
to_xml(hash).should == result
|
105
|
+
|
106
|
+
hash = { :find_user => { :person => "Lucy", :attributes! => { :person => { :id => 666, :city => "Hamburg" } } } }
|
107
|
+
to_xml(hash).should include('id="666"', 'city="Hamburg"')
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should add attributes to duplicate Hash keys specified through :attributes!" do
|
111
|
+
hash = { :find_user => { :person => ["Lucy", "Anna"], :attributes! => { :person => { :id => [1, 3] } } } }
|
112
|
+
result = '<findUser><person id="1">Lucy</person><person id="3">Anna</person></findUser>'
|
113
|
+
to_xml(hash).should == result
|
114
|
+
|
115
|
+
hash = { :find_user => { :person => ["Lucy", "Anna"], :attributes! => { :person => { :active => "true" } } } }
|
116
|
+
result = '<findUser><person active="true">Lucy</person><person active="true">Anna</person></findUser>'
|
117
|
+
to_xml(hash).should == result
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def to_xml(hash)
|
122
|
+
Gyoku::Hash.to_xml hash
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Gyoku::XMLKey do
|
4
|
+
include Gyoku::XMLKey
|
5
|
+
|
6
|
+
describe "#to_xml_key" do
|
7
|
+
it "removes exclamation marks from the end of a String" do
|
8
|
+
to_xml_key("value").should == "value"
|
9
|
+
to_xml_key("value!").should == "value"
|
10
|
+
end
|
11
|
+
|
12
|
+
it "converts snake_case Symbols to lowerCamelCase Strings" do
|
13
|
+
to_xml_key(:lower_camel_case).should == "lowerCamelCase"
|
14
|
+
to_xml_key(:lower_camel_case!).should == "lowerCamelCase"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Gyoku::XMLValue do
|
4
|
+
include Gyoku::XMLValue
|
5
|
+
|
6
|
+
let(:datetime) { DateTime.new 2012, 03, 22, 16, 22, 33 }
|
7
|
+
let(:datetime_string) { "2012-03-22T16:22:33+00:00" }
|
8
|
+
|
9
|
+
describe "#to_xml_value" do
|
10
|
+
context "for DateTime objects" do
|
11
|
+
it "should return an xs:dateTime compliant String" do
|
12
|
+
to_xml_value(datetime).should == datetime_string
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should return the String value and escape special characters" do
|
17
|
+
to_xml_value("string").should == "string"
|
18
|
+
to_xml_value("<tag>").should == "<tag>"
|
19
|
+
to_xml_value("at&t").should == "at&t"
|
20
|
+
to_xml_value('"quotes"').should == ""quotes""
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should just return the String value without escaping special characters" do
|
24
|
+
to_xml_value("<tag>", false).should == "<tag>"
|
25
|
+
end
|
26
|
+
|
27
|
+
it "returns an xs:dateTime compliant String for Objects responding to :to_datetime" do
|
28
|
+
singleton = Object.new
|
29
|
+
def singleton.to_datetime
|
30
|
+
DateTime.new(2012, 03, 22, 16, 22, 33)
|
31
|
+
end
|
32
|
+
|
33
|
+
to_xml_value(singleton).should == "2012-03-22T16:22:33+00:00"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "calls to_s unless the Object responds to to_datetime" do
|
37
|
+
to_xml_value("value").should == "value"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
data/spec/gyoku_spec.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Gyoku do
|
4
|
+
|
5
|
+
describe ".xml" do
|
6
|
+
it "should translate a given Hash to XML" do
|
7
|
+
Gyoku::Hash.expects(:to_xml).with(:id => 1)
|
8
|
+
Gyoku.xml :id => 1
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should translate a given Array to XML" do
|
12
|
+
Gyoku::Array.expects(:to_xml).with([1, 2, 3])
|
13
|
+
Gyoku.xml [1, 2, 3]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,141 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gyoku
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Daniel Harrington
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-11-29 00:00:00 +01:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: builder
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 15
|
30
|
+
segments:
|
31
|
+
- 2
|
32
|
+
- 1
|
33
|
+
- 2
|
34
|
+
version: 2.1.2
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: rspec
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - "="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 15
|
46
|
+
segments:
|
47
|
+
- 2
|
48
|
+
- 0
|
49
|
+
- 0
|
50
|
+
version: 2.0.0
|
51
|
+
type: :development
|
52
|
+
version_requirements: *id002
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: mocha
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 41
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
- 9
|
65
|
+
- 9
|
66
|
+
version: 0.9.9
|
67
|
+
type: :development
|
68
|
+
version_requirements: *id003
|
69
|
+
description: Gyoku converts Ruby Hashes to XML
|
70
|
+
email: me@rubiii.com
|
71
|
+
executables: []
|
72
|
+
|
73
|
+
extensions: []
|
74
|
+
|
75
|
+
extra_rdoc_files: []
|
76
|
+
|
77
|
+
files:
|
78
|
+
- .gitignore
|
79
|
+
- .rspec
|
80
|
+
- Gemfile
|
81
|
+
- LICENSE
|
82
|
+
- README.md
|
83
|
+
- Rakefile
|
84
|
+
- autotest/discover.rb
|
85
|
+
- gyoku.gemspec
|
86
|
+
- lib/gyoku.rb
|
87
|
+
- lib/gyoku/array.rb
|
88
|
+
- lib/gyoku/core_ext/string.rb
|
89
|
+
- lib/gyoku/hash.rb
|
90
|
+
- lib/gyoku/version.rb
|
91
|
+
- lib/gyoku/xml_key.rb
|
92
|
+
- lib/gyoku/xml_value.rb
|
93
|
+
- spec/gyoku/array_spec.rb
|
94
|
+
- spec/gyoku/core_ext/string_spec.rb
|
95
|
+
- spec/gyoku/hash_spec.rb
|
96
|
+
- spec/gyoku/xml_key_spec.rb
|
97
|
+
- spec/gyoku/xml_value_spec.rb
|
98
|
+
- spec/gyoku_spec.rb
|
99
|
+
- spec/spec_helper.rb
|
100
|
+
has_rdoc: true
|
101
|
+
homepage: http://github.com/rubiii/gyoku
|
102
|
+
licenses: []
|
103
|
+
|
104
|
+
post_install_message:
|
105
|
+
rdoc_options: []
|
106
|
+
|
107
|
+
require_paths:
|
108
|
+
- lib
|
109
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
110
|
+
none: false
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
hash: 3
|
115
|
+
segments:
|
116
|
+
- 0
|
117
|
+
version: "0"
|
118
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
119
|
+
none: false
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
hash: 3
|
124
|
+
segments:
|
125
|
+
- 0
|
126
|
+
version: "0"
|
127
|
+
requirements: []
|
128
|
+
|
129
|
+
rubyforge_project: gyoku
|
130
|
+
rubygems_version: 1.3.7
|
131
|
+
signing_key:
|
132
|
+
specification_version: 3
|
133
|
+
summary: Converts Ruby Hashes to XML
|
134
|
+
test_files:
|
135
|
+
- spec/gyoku/array_spec.rb
|
136
|
+
- spec/gyoku/core_ext/string_spec.rb
|
137
|
+
- spec/gyoku/hash_spec.rb
|
138
|
+
- spec/gyoku/xml_key_spec.rb
|
139
|
+
- spec/gyoku/xml_value_spec.rb
|
140
|
+
- spec/gyoku_spec.rb
|
141
|
+
- spec/spec_helper.rb
|