gyoku 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|