gyoku 0.3.1 → 0.4.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/.gemtest ADDED
File without changes
data/README.md CHANGED
@@ -37,6 +37,17 @@ Conventions
37
37
  * These conventions are also applied to the return value of objects responding to :call
38
38
  * All other objects are converted to Strings using :to_s
39
39
 
40
+ Symbols are converted to lowerCamelCase?
41
+ ----------------------------------------
42
+
43
+ That's the default. But you can use one of the other conversion formulas:
44
+
45
+ Gyoku.convert_symbols_to :camelcase # or one of [:none, :lower_camelcase]
46
+
47
+ or even define you own one:
48
+
49
+ Gyoku.convert_symbols_to { |key| key.upcase }
50
+
40
51
  Special characters
41
52
  ------------------
42
53
 
data/Rakefile CHANGED
@@ -1,11 +1,9 @@
1
1
  require "bundler"
2
2
  Bundler::GemHelper.install_tasks
3
3
 
4
- task :default => :spec
5
-
6
4
  begin
7
5
  require "yard"
8
-
6
+
9
7
  YARD::Rake::YardocTask.new do |t|
10
8
  t.files = ["README.md", "lib/**/*.rb"]
11
9
  end
@@ -16,7 +14,7 @@ end
16
14
 
17
15
  begin
18
16
  require "metric_fu"
19
-
17
+
20
18
  MetricFu::Configuration.run do |c|
21
19
  c.metrics = [:churn, :flog, :flay, :reek, :roodi, :saikuro] # :rcov seems to be broken
22
20
  c.graphs = [:flog, :flay, :reek, :roodi]
@@ -30,7 +28,7 @@ end
30
28
 
31
29
  begin
32
30
  require "rspec/core/rake_task"
33
-
31
+
34
32
  RSpec::Core::RakeTask.new do |t|
35
33
  t.pattern = "spec/**/*_spec.rb"
36
34
  t.rspec_opts = %w(-fd -c)
@@ -40,3 +38,6 @@ rescue LoadError
40
38
  abort "Run 'gem install rspec' to be able to run specs"
41
39
  end
42
40
  end
41
+
42
+ task :default => :spec
43
+ task :test => :spec
data/lib/gyoku.rb CHANGED
@@ -2,10 +2,22 @@ require "gyoku/version"
2
2
  require "gyoku/hash"
3
3
 
4
4
  module Gyoku
5
+ class << self
5
6
 
6
- # Translates a given +hash+ with +options+ to XML.
7
- def self.xml(hash, options = {})
8
- Hash.to_xml hash, options
9
- end
7
+ # Translates a given +hash+ with +options+ to XML.
8
+ def xml(hash, options = {})
9
+ Hash.to_xml hash, options
10
+ end
11
+
12
+ # Yields this object for configuration.
13
+ def configure
14
+ yield self
15
+ end
10
16
 
17
+ # Sets the formula for converting Symbol keys.
18
+ def convert_symbols_to(formula = nil, &block)
19
+ XMLKey.symbol_converter = formula ? formula : block
20
+ end
21
+
22
+ end
11
23
  end
data/lib/gyoku/array.rb CHANGED
@@ -1,13 +1,10 @@
1
1
  require "builder"
2
2
 
3
3
  require "gyoku/hash"
4
- require "gyoku/xml_key"
5
4
  require "gyoku/xml_value"
6
5
 
7
6
  module Gyoku
8
7
  class Array
9
- extend XMLKey
10
- extend XMLValue
11
8
 
12
9
  # Translates a given +array+ to XML. Accepts the XML +key+ to add the elements to,
13
10
  # whether to +escape_xml+ and an optional Hash of +attributes+.
@@ -16,7 +13,7 @@ module Gyoku
16
13
  case item
17
14
  when ::Hash then xml.tag!(key, attrs) { xml << Hash.to_xml(item) }
18
15
  when NilClass then xml.tag!(key, "xsi:nil" => "true")
19
- else xml.tag!(key, attrs) { xml << to_xml_value(item, escape_xml) }
16
+ else xml.tag!(key, attrs) { xml << XMLValue.create(item, escape_xml) }
20
17
  end
21
18
  end
22
19
  end
@@ -4,11 +4,12 @@ module Gyoku
4
4
 
5
5
  # Returns the String in lowerCamelCase.
6
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
7
+ self[0].chr.downcase + self.camelcase[1..-1]
8
+ end
9
+
10
+ # Returns the String in CamelCase.
11
+ def camelcase
12
+ self.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
12
13
  end
13
14
 
14
15
  end
data/lib/gyoku/hash.rb CHANGED
@@ -6,22 +6,20 @@ require "gyoku/xml_value"
6
6
 
7
7
  module Gyoku
8
8
  class Hash
9
- extend XMLKey
10
- extend XMLValue
11
9
 
12
10
  # Translates a given +hash+ with +options+ to XML.
13
11
  def self.to_xml(hash, options = {})
14
12
  iterate_with_xml hash do |xml, key, value, attributes|
15
13
  self_closing = key.to_s[-1, 1] == "/"
16
14
  escape_xml = key.to_s[-1, 1] != "!"
17
- xml_key = to_xml_key key, options
15
+ xml_key = XMLKey.create key, options
18
16
 
19
17
  case
20
18
  when ::Array === value then xml << Array.to_xml(value, xml_key, escape_xml, attributes)
21
19
  when ::Hash === value then xml.tag!(xml_key, attributes) { xml << Hash.to_xml(value, options) }
22
20
  when self_closing then xml.tag!(xml_key, attributes)
23
21
  when NilClass === value then xml.tag!(xml_key, "xsi:nil" => "true")
24
- else xml.tag!(xml_key, attributes) { xml << to_xml_value(value, escape_xml) }
22
+ else xml.tag!(xml_key, attributes) { xml << XMLValue.create(value, escape_xml) }
25
23
  end
26
24
  end
27
25
  end
data/lib/gyoku/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  module Gyoku
2
2
 
3
- VERSION = "0.3.1"
3
+ VERSION = "0.4.0"
4
4
 
5
5
  end
data/lib/gyoku/xml_key.rb CHANGED
@@ -2,39 +2,61 @@ require "gyoku/core_ext/string"
2
2
 
3
3
  module Gyoku
4
4
  module XMLKey
5
+ class << self
6
+
7
+ FORMULAS = {
8
+ :lower_camelcase => lambda { |key| key.lower_camelcase },
9
+ :camelcase => lambda { |key| key.camelcase },
10
+ :none => lambda { |key| key }
11
+ }
12
+
13
+ # Converts a given +object+ with +options+ to an XML key.
14
+ def create(key, options = {})
15
+ xml_key = chop_special_characters key.to_s
16
+
17
+ if unqualify?(xml_key)
18
+ xml_key = xml_key.split(":").last
19
+ elsif qualify?(options) && !xml_key.include?(":")
20
+ xml_key = "#{options[:namespace]}:#{xml_key}"
21
+ end
22
+
23
+ case key
24
+ when Symbol then symbol_converter.call(xml_key)
25
+ else xml_key
26
+ end
27
+ end
5
28
 
6
- # Converts a given +object+ with +options+ to an XML key.
7
- def to_xml_key(key, options = {})
8
- xml_key = chop_special_characters key.to_s
9
-
10
- if unqualify?(xml_key)
11
- xml_key = xml_key.split(":").last
12
- elsif qualify?(options) && !xml_key.include?(":")
13
- xml_key = "#{options[:namespace]}:#{xml_key}"
29
+ # Returns the formula for converting Symbol keys.
30
+ def symbol_converter
31
+ @symbol_converter ||= FORMULAS[:lower_camelcase]
14
32
  end
15
33
 
16
- case key
17
- when Symbol then xml_key.lower_camelcase
18
- else xml_key
34
+ # Sets the +formula+ for converting Symbol keys.
35
+ # Accepts one of +FORMULAS+ of an object responding to <tt>:call</tt>.
36
+ def symbol_converter=(formula)
37
+ formula = FORMULAS[formula] unless formula.respond_to? :call
38
+ raise ArgumentError, "Invalid symbol_converter formula" unless formula
39
+
40
+ @symbol_converter = formula
19
41
  end
20
- end
21
42
 
22
- private
43
+ private
23
44
 
24
- # Chops special characters from the end of a given +string+.
25
- def chop_special_characters(string)
26
- ["!", "/"].include?(string[-1, 1]) ? string.chop : string
27
- end
45
+ # Chops special characters from the end of a given +string+.
46
+ def chop_special_characters(string)
47
+ ["!", "/"].include?(string[-1, 1]) ? string.chop : string
48
+ end
28
49
 
29
- # Returns whether to remove the namespace from a given +key+.
30
- def unqualify?(key)
31
- key[0, 1] == ":"
32
- end
50
+ # Returns whether to remove the namespace from a given +key+.
51
+ def unqualify?(key)
52
+ key[0, 1] == ":"
53
+ end
33
54
 
34
- # Returns whether to namespace all keys (elementFormDefault).
35
- def qualify?(options)
36
- options[:element_form_default] == :qualified && options[:namespace]
37
- end
55
+ # Returns whether to namespace all keys (elementFormDefault).
56
+ def qualify?(options)
57
+ options[:element_form_default] == :qualified && options[:namespace]
58
+ end
38
59
 
60
+ end
39
61
  end
40
62
  end
@@ -2,24 +2,26 @@ require "cgi"
2
2
 
3
3
  module Gyoku
4
4
  module XMLValue
5
+ class << self
5
6
 
6
- # xs:dateTime format.
7
- XS_DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%S%Z"
7
+ # xs:dateTime format.
8
+ XS_DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%S%Z"
8
9
 
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
- elsif object.respond_to?(:call)
18
- to_xml_value object.call
19
- else
20
- object.to_s
10
+ # Converts a given +object+ to an XML value.
11
+ def create(object, escape_xml = true)
12
+ if DateTime === object
13
+ object.strftime XS_DATETIME_FORMAT
14
+ elsif String === object
15
+ escape_xml ? CGI.escapeHTML(object) : object
16
+ elsif object.respond_to?(:to_datetime)
17
+ create object.to_datetime
18
+ elsif object.respond_to?(:call)
19
+ create object.call
20
+ else
21
+ object.to_s
22
+ end
21
23
  end
22
- end
23
24
 
25
+ end
24
26
  end
25
27
  end
@@ -8,4 +8,10 @@ describe String do
8
8
  end
9
9
  end
10
10
 
11
+ describe "#camelcase" do
12
+ it "converts a snakecase String to CamelCase" do
13
+ "camel_case".camelcase.should == "CamelCase"
14
+ end
15
+ end
16
+
11
17
  end
@@ -1,37 +1,68 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe Gyoku::XMLKey do
4
- include Gyoku::XMLKey
5
4
 
6
- describe "#to_xml_key" do
5
+ describe ".create" do
7
6
  it "should remove exclamation marks from the end of a String" do
8
- to_xml_key("value!").should == "value"
7
+ create("value!").should == "value"
9
8
  end
10
9
 
11
10
  it "should remove forward slashes from the end of a String" do
12
- to_xml_key("self-closing/").should == "self-closing"
11
+ create("self-closing/").should == "self-closing"
13
12
  end
14
13
 
15
14
  it "should not convert snake_case Strings" do
16
- to_xml_key("lower_camel_case").should == "lower_camel_case"
15
+ create("lower_camel_case").should == "lower_camel_case"
17
16
  end
18
17
 
19
18
  it "should convert snake_case Symbols to lowerCamelCase Strings" do
20
- to_xml_key(:lower_camel_case).should == "lowerCamelCase"
21
- to_xml_key(:lower_camel_case!).should == "lowerCamelCase"
19
+ create(:lower_camel_case).should == "lowerCamelCase"
20
+ create(:lower_camel_case!).should == "lowerCamelCase"
22
21
  end
23
22
 
24
23
  context "with :element_form_default set to :qualified and a :namespace" do
25
24
  it "should add the given namespace" do
26
- key = to_xml_key :qualify, :element_form_default => :qualified, :namespace => :v1
25
+ key = create :qualify, :element_form_default => :qualified, :namespace => :v1
27
26
  key.should == "v1:qualify"
28
27
  end
29
28
 
30
29
  it "should not add the given namespace if the key starts with a colon" do
31
- key = to_xml_key ":qualify", :element_form_default => :qualified, :namespace => :v1
30
+ key = create ":qualify", :element_form_default => :qualified, :namespace => :v1
32
31
  key.should == "qualify"
33
32
  end
34
33
  end
35
34
  end
36
35
 
36
+ describe ".symbol_converter" do
37
+ after { Gyoku::XMLKey.symbol_converter = :lower_camelcase } #reset
38
+
39
+ it "should return the default lower_camelcase converter" do
40
+ Gyoku::XMLKey.symbol_converter.call("snake_case").should == "snakeCase"
41
+ end
42
+
43
+ it "should accept :lower_camelcase" do
44
+ Gyoku::XMLKey.symbol_converter = :lower_camelcase
45
+ Gyoku::XMLKey.create(:snake_case).should == "snakeCase"
46
+ end
47
+
48
+ it "should accept :camelcase" do
49
+ Gyoku::XMLKey.symbol_converter = :camelcase
50
+ Gyoku::XMLKey.create(:snake_case).should == "SnakeCase"
51
+ end
52
+
53
+ it "should accept :none" do
54
+ Gyoku::XMLKey.symbol_converter = :none
55
+ Gyoku::XMLKey.create(:snake_Case).should == "snake_Case"
56
+ end
57
+
58
+ it "should allow to set a custom converter" do
59
+ Gyoku::XMLKey.symbol_converter = Proc.new { |key| key.upcase }
60
+ Gyoku::XMLKey.create(:snake_case).should == "SNAKE_CASE"
61
+ end
62
+ end
63
+
64
+ def create(key, options = {})
65
+ Gyoku::XMLKey.create key, options
66
+ end
67
+
37
68
  end
@@ -1,27 +1,26 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe Gyoku::XMLValue do
4
- include Gyoku::XMLValue
5
4
 
6
5
  let(:datetime) { DateTime.new 2012, 03, 22, 16, 22, 33 }
7
6
  let(:datetime_string) { "2012-03-22T16:22:33+00:00" }
8
-
9
- describe "#to_xml_value" do
7
+
8
+ describe ".create" do
10
9
  context "for DateTime objects" do
11
10
  it "should return an xs:dateTime compliant String" do
12
- to_xml_value(datetime).should == datetime_string
11
+ create(datetime).should == datetime_string
13
12
  end
14
13
  end
15
14
 
16
15
  it "should return the String value and escape special characters" do
17
- to_xml_value("string").should == "string"
18
- to_xml_value("<tag>").should == "&lt;tag&gt;"
19
- to_xml_value("at&t").should == "at&amp;t"
20
- to_xml_value('"quotes"').should == "&quot;quotes&quot;"
16
+ create("string").should == "string"
17
+ create("<tag>").should == "&lt;tag&gt;"
18
+ create("at&t").should == "at&amp;t"
19
+ create('"quotes"').should == "&quot;quotes&quot;"
21
20
  end
22
21
 
23
22
  it "should just return the String value without escaping special characters" do
24
- to_xml_value("<tag>", false).should == "<tag>"
23
+ create("<tag>", false).should == "<tag>"
25
24
  end
26
25
 
27
26
  it "should return an xs:dateTime compliant String for Objects responding to #to_datetime" do
@@ -30,17 +29,21 @@ describe Gyoku::XMLValue do
30
29
  DateTime.new 2012, 03, 22, 16, 22, 33
31
30
  end
32
31
 
33
- to_xml_value(singleton).should == "2012-03-22T16:22:33+00:00"
32
+ create(singleton).should == "2012-03-22T16:22:33+00:00"
34
33
  end
35
34
 
36
35
  it "should #call Proc objects and convert their return value" do
37
36
  object = lambda { DateTime.new 2012, 03, 22, 16, 22, 33 }
38
- to_xml_value(object).should == "2012-03-22T16:22:33+00:00"
37
+ create(object).should == "2012-03-22T16:22:33+00:00"
39
38
  end
40
39
 
41
40
  it "should call #to_s unless the Object responds to #to_datetime" do
42
- to_xml_value("value").should == "value"
41
+ create("value").should == "value"
43
42
  end
44
43
  end
45
44
 
45
+ def create(object, escape_xml = true)
46
+ Gyoku::XMLValue.create object, escape_xml
47
+ end
48
+
46
49
  end
data/spec/gyoku_spec.rb CHANGED
@@ -9,4 +9,24 @@ describe Gyoku do
9
9
  end
10
10
  end
11
11
 
12
+ describe ".configure" do
13
+ it "should yield the Gyoku module" do
14
+ Gyoku.configure { |config| config.should respond_to(:convert_symbols_to) }
15
+ end
16
+ end
17
+
18
+ describe ".convert_symbols_to" do
19
+ after { Gyoku.convert_symbols_to(:lower_camelcase) } # reset
20
+
21
+ it "should accept a predefined formula" do
22
+ Gyoku.convert_symbols_to(:camelcase)
23
+ Gyoku::XMLKey.create(:snake_case).should == "SnakeCase"
24
+ end
25
+
26
+ it "should accept a block" do
27
+ Gyoku.convert_symbols_to { |key| key.upcase }
28
+ Gyoku::XMLKey.create(:snake_case).should == "SNAKE_CASE"
29
+ end
30
+ end
31
+
12
32
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gyoku
3
3
  version: !ruby/object:Gem::Version
4
- hash: 17
4
+ hash: 15
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 3
9
- - 1
10
- version: 0.3.1
8
+ - 4
9
+ - 0
10
+ version: 0.4.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Daniel Harrington
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-01-26 00:00:00 +01:00
18
+ date: 2011-04-05 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -89,6 +89,7 @@ extensions: []
89
89
  extra_rdoc_files: []
90
90
 
91
91
  files:
92
+ - .gemtest
92
93
  - .gitignore
93
94
  - .rspec
94
95
  - Gemfile
@@ -140,7 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
140
141
  requirements: []
141
142
 
142
143
  rubyforge_project: gyoku
143
- rubygems_version: 1.4.1
144
+ rubygems_version: 1.4.2
144
145
  signing_key:
145
146
  specification_version: 3
146
147
  summary: Converts Ruby Hashes to XML