pump 0.2.0 → 0.3.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/.yardopts +5 -0
- data/{LICENSE.txt → MIT-LICENSE} +1 -1
- data/README.md +5 -5
- data/Rakefile +26 -0
- data/lib/pump/version.rb +1 -1
- data/lib/pump/xml/dsl.rb +51 -0
- data/lib/pump/xml.rb +50 -7
- data/lib/pump.rb +1 -0
- data/spec/pump/xml/dsl_spec.rb +123 -0
- data/spec/pump/xml_spec.rb +28 -5
- metadata +8 -3
data/.yardopts
ADDED
data/{LICENSE.txt → MIT-LICENSE}
RENAMED
data/README.md
CHANGED
@@ -6,8 +6,8 @@ Fast but inflexible XML encoding for ruby objects.
|
|
6
6
|
|
7
7
|
Serializing an array of 100 random entries 1.000 times.
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
user system total real
|
10
|
+
Pump::Xml#encode 1.450000 0.010000 1.460000 ( 1.466962)
|
11
|
+
Pump::Xml#encode (optimized) 1.100000 0.010000 1.110000 ( 1.110234)
|
12
|
+
Ox 1.490000 0.000000 1.490000 ( 1.483275)
|
13
|
+
ActiveModel#serialize 23.280000 0.060000 23.340000 ( 23.333999)
|
data/Rakefile
CHANGED
@@ -3,3 +3,29 @@ require "bundler/gem_tasks"
|
|
3
3
|
require 'rspec/core/rake_task'
|
4
4
|
RSpec::Core::RakeTask.new(:spec)
|
5
5
|
task :default => :spec
|
6
|
+
|
7
|
+
begin
|
8
|
+
require "yard"
|
9
|
+
require "yard/rake/yardoc_task"
|
10
|
+
|
11
|
+
namespace :doc do
|
12
|
+
desc "Generate Yardoc documentation"
|
13
|
+
YARD::Rake::YardocTask.new do |yardoc|
|
14
|
+
yardoc.name = "yard"
|
15
|
+
yardoc.options = ["--verbose", "--markup", "markdown"]
|
16
|
+
yardoc.files = FileList[
|
17
|
+
"lib/**/*.rb",
|
18
|
+
"-", "README.md", "CHANGES.md", "MIT-LICENSE"
|
19
|
+
]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
task "clobber" => ["doc:clobber_yard"]
|
24
|
+
|
25
|
+
desc "Alias to doc:yard"
|
26
|
+
task "doc" => "doc:yard"
|
27
|
+
rescue LoadError
|
28
|
+
# If yard isn't available, it's not the end of the world
|
29
|
+
desc "Alias to doc:rdoc"
|
30
|
+
task "doc" => "doc:rdoc"
|
31
|
+
end
|
data/lib/pump/version.rb
CHANGED
data/lib/pump/xml/dsl.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
module Pump
|
2
|
+
class Xml
|
3
|
+
class Dsl
|
4
|
+
def initialize(&blk)
|
5
|
+
raise ArgumentError unless block_given?
|
6
|
+
instance_eval(&blk)
|
7
|
+
end
|
8
|
+
|
9
|
+
def config
|
10
|
+
@config ||= []
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def tag(name, options={}, &blk)
|
16
|
+
method = if block_given?
|
17
|
+
self.class.new(&blk).config
|
18
|
+
else
|
19
|
+
options.delete(:from) || (name.to_s =~ /-/ ? name.to_s.gsub('-', '_').to_sym : name)
|
20
|
+
end
|
21
|
+
config << ({ name => method }).merge(options)
|
22
|
+
end
|
23
|
+
alias_method :string, :tag
|
24
|
+
|
25
|
+
def integer(name, options={})
|
26
|
+
with_type('integer', name, options)
|
27
|
+
end
|
28
|
+
|
29
|
+
def date(name, options={})
|
30
|
+
with_type('date', name, options)
|
31
|
+
end
|
32
|
+
|
33
|
+
def datetime(name, options={})
|
34
|
+
options[:typecast] = :xmlschema unless options.has_key?(:typecast)
|
35
|
+
with_type('datetime', name, options)
|
36
|
+
end
|
37
|
+
alias_method :time, :datetime
|
38
|
+
|
39
|
+
def with_type(type, name, options)
|
40
|
+
(options[:attributes] ||= {}).merge!({:type => type})
|
41
|
+
options[:xmlsafe] = true unless options.has_key?(:xmlsafe)
|
42
|
+
tag(name, options)
|
43
|
+
end
|
44
|
+
|
45
|
+
def array(name, options={}, &blk)
|
46
|
+
options[:array] = self.class.new(&blk).config
|
47
|
+
tag(name, options)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/pump/xml.rb
CHANGED
@@ -1,19 +1,60 @@
|
|
1
1
|
require "pump/xml/tag"
|
2
2
|
require "pump/xml/value"
|
3
3
|
require "pump/xml/tag_array"
|
4
|
+
require "pump/xml/dsl"
|
5
|
+
require 'active_support/core_ext/string/inflections'
|
4
6
|
|
5
7
|
module Pump
|
6
8
|
class Xml
|
9
|
+
|
7
10
|
attr_reader :root_tag_name, :tag_config, :options
|
8
11
|
|
9
|
-
|
12
|
+
# Creates a new XML-encoder with a root tag named after +root_tag_name+.
|
13
|
+
#
|
14
|
+
# @example Create a simple encoder for a person with a name attribute:
|
15
|
+
# Pump::Xml.new :person do
|
16
|
+
# tag :name
|
17
|
+
# end
|
18
|
+
#
|
19
|
+
# @example Create the same without usage of the DSL:
|
20
|
+
# Pump::Xml.new :person, [{:name => :name}]
|
21
|
+
#
|
22
|
+
# @example Create the same but without the xml instruct
|
23
|
+
# Pump::Xml.new :person, :instruct => false do
|
24
|
+
# tag :name
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# @example The same again without DSL:
|
28
|
+
#
|
29
|
+
# Pump::Xml.new :person, [{:name => :name}], :instruct => false
|
30
|
+
#
|
31
|
+
# @param [String, Symbol] root_tag_name the name of the used root tag
|
32
|
+
# @param [Array<Hash>] tag_config optional config for all tags
|
33
|
+
# @param [Hash] options optional options for the whole encoder
|
34
|
+
# @yield an optional block to create the encoder with the Pump::Xml::Dsl
|
35
|
+
#
|
36
|
+
# @return [self]
|
37
|
+
def initialize(root_tag_name, tag_config=nil, options={}, &blk)
|
38
|
+
unless Array === tag_config
|
39
|
+
raise ArgumentError unless block_given?
|
40
|
+
@options = tag_config || {}
|
41
|
+
@tag_config = Dsl.new(&blk).config
|
42
|
+
else
|
43
|
+
@tag_config = tag_config
|
44
|
+
@options = options
|
45
|
+
end
|
10
46
|
@root_tag_name = root_tag_name
|
11
|
-
@tag_config = tag_config
|
12
|
-
@options = options
|
13
47
|
|
14
48
|
compile
|
15
49
|
end
|
16
50
|
|
51
|
+
# Encode a object or an array of objects to an XML-string.
|
52
|
+
#
|
53
|
+
# @param [Object, Array<Object>] object object or an array of objects to
|
54
|
+
# encode to XML. The only requirement: The given objects must respond
|
55
|
+
# to all methods configured during initalization of the Pump::Xml instance.
|
56
|
+
#
|
57
|
+
# @return [String]
|
17
58
|
def encode(object)
|
18
59
|
Array === object ? encode_array(object) : encode_single(object)
|
19
60
|
end
|
@@ -44,12 +85,14 @@ module Pump
|
|
44
85
|
|
45
86
|
def build_tag(config)
|
46
87
|
tag_name, method_name = config.keys.first, config.values.first
|
88
|
+
attrs = config[:attributes]
|
47
89
|
if method_name.is_a?(Array)
|
48
|
-
Tag.new(tag_name,
|
49
|
-
elsif config[:array]
|
50
|
-
|
90
|
+
Tag.new(tag_name, attrs, method_name.map{|conf| build_tag(conf) }, config)
|
91
|
+
elsif config[:array]
|
92
|
+
config.merge!(:array_method => method_name, :array_root => tag_name)
|
93
|
+
TagArray.new(config[:child_root] || tag_name.to_s.singularize, attrs, config[:array].map{|conf| build_tag(conf) }, config)
|
51
94
|
else
|
52
|
-
Tag.new(tag_name,
|
95
|
+
Tag.new(tag_name, attrs, Value.new(method_name), config)
|
53
96
|
end
|
54
97
|
end
|
55
98
|
|
data/lib/pump.rb
CHANGED
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Pump::Xml::Dsl do
|
4
|
+
subject { Pump::Xml::Dsl.new {} }
|
5
|
+
|
6
|
+
describe ".new" do
|
7
|
+
it "requires one block" do
|
8
|
+
lambda{ Pump::Xml::Dsl.new }.should raise_error(ArgumentError)
|
9
|
+
lambda{ subject }.should_not raise_error
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#config" do
|
14
|
+
its(:config) { should eql([]) }
|
15
|
+
|
16
|
+
context "with tag" do
|
17
|
+
subject { Pump::Xml::Dsl.new { tag :name } }
|
18
|
+
its(:config) { should eql([{:name => :name}]) }
|
19
|
+
|
20
|
+
context "with attributes and options" do
|
21
|
+
subject { Pump::Xml::Dsl.new { tag :name, :attributes => {:a => 'b'}, :options => false } }
|
22
|
+
its(:config) { should eql([{:name => :name, :attributes => {:a => 'b'}, :options => false}]) }
|
23
|
+
end
|
24
|
+
|
25
|
+
context "with :from option" do
|
26
|
+
subject { Pump::Xml::Dsl.new { tag :name, :from => :method_name } }
|
27
|
+
its(:config) { should eql([{:name => :method_name}]) }
|
28
|
+
end
|
29
|
+
|
30
|
+
context "with dashs in tag name" do
|
31
|
+
subject { Pump::Xml::Dsl.new { tag :"first-name" } }
|
32
|
+
its(:config) { should eql([{:"first-name" => :first_name}]) }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "with string" do
|
37
|
+
subject { Pump::Xml::Dsl.new { string :name } }
|
38
|
+
its(:config) { should eql([{:name => :name}]) }
|
39
|
+
|
40
|
+
context "with attributes and options" do
|
41
|
+
subject { Pump::Xml::Dsl.new { string :name, :attributes => {:a => 'b'}, :options => false } }
|
42
|
+
its(:config) { should eql([{:name => :name, :attributes => {:a => 'b'}, :options => false}]) }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "with integer" do
|
47
|
+
subject { Pump::Xml::Dsl.new { integer :name } }
|
48
|
+
its(:config) { should eql([{:name => :name, :attributes => {:type => 'integer'}, :xmlsafe => true}]) }
|
49
|
+
|
50
|
+
context "with attributes and options" do
|
51
|
+
subject { Pump::Xml::Dsl.new { integer :name, :attributes => {:a => 'b'}, :options => false } }
|
52
|
+
its(:config) { should eql([{:name => :name, :attributes => {:type => 'integer', :a => 'b'}, :options => false, :xmlsafe => true}]) }
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "with date" do
|
57
|
+
subject { Pump::Xml::Dsl.new { date :at } }
|
58
|
+
its(:config) { should eql([{:at => :at, :attributes => {:type => 'date'}, :xmlsafe => true}]) }
|
59
|
+
|
60
|
+
context "with attributes and options" do
|
61
|
+
subject { Pump::Xml::Dsl.new { date :at, :attributes => {:a => 'b'}, :options => false } }
|
62
|
+
its(:config) { should eql([{:at => :at, :attributes => {:type => 'date', :a => 'b'}, :options => false, :xmlsafe => true}]) }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "with (date)time" do
|
67
|
+
subject { Pump::Xml::Dsl.new { time :at } }
|
68
|
+
its(:config) { should eql([{:at => :at, :typecast => :xmlschema, :attributes => {:type => 'datetime'}, :xmlsafe => true}]) }
|
69
|
+
|
70
|
+
context "with attributes and options" do
|
71
|
+
subject { Pump::Xml::Dsl.new { time :at, :attributes => {:a => 'b'}, :options => false } }
|
72
|
+
its(:config) { should eql([{:at => :at, :attributes => {:a => 'b', :type => 'datetime'}, :options => false, :typecast => :xmlschema, :xmlsafe => true}]) }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context "with nested tags" do
|
77
|
+
subject do
|
78
|
+
Pump::Xml::Dsl.new do
|
79
|
+
tag :person, :option => 'x' do
|
80
|
+
string :name
|
81
|
+
integer :age
|
82
|
+
end
|
83
|
+
string :parent_name
|
84
|
+
end
|
85
|
+
end
|
86
|
+
its(:config) { should eql([
|
87
|
+
{:person => [
|
88
|
+
{:name => :name},
|
89
|
+
{:age => :age, :attributes => {:type => 'integer'}, :xmlsafe => true}
|
90
|
+
], :option => 'x'},
|
91
|
+
{:parent_name => :parent_name}
|
92
|
+
]) }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context "with array tag" do
|
97
|
+
subject do
|
98
|
+
Pump::Xml::Dsl.new do
|
99
|
+
array(:children) do
|
100
|
+
tag :name
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
its(:config) { should eql(
|
106
|
+
[{:children => :children, :array => [{:name => :name}]}]
|
107
|
+
)}
|
108
|
+
|
109
|
+
context "with options" do
|
110
|
+
subject do
|
111
|
+
Pump::Xml::Dsl.new do
|
112
|
+
array(:children, :from => :kids, :child_root => :ugly_kid_joe) do
|
113
|
+
tag :name
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
its(:config) { should eql(
|
119
|
+
[{:children => :kids, :array => [{:name => :name}], :child_root => :ugly_kid_joe}]
|
120
|
+
)}
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
data/spec/pump/xml_spec.rb
CHANGED
@@ -2,10 +2,21 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Pump::Xml do
|
4
4
|
describe ".new" do
|
5
|
-
it "requires two parameters" do
|
5
|
+
it "requires two parameters or one and a block" do
|
6
6
|
lambda{ Pump::Xml.new }.should raise_error(ArgumentError)
|
7
7
|
lambda{ Pump::Xml.new('record') }.should raise_error(ArgumentError)
|
8
8
|
lambda{ Pump::Xml.new('record', []) }.should_not raise_error
|
9
|
+
lambda{ Pump::Xml.new('record') {} }.should_not raise_error
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "with block given" do
|
13
|
+
subject do
|
14
|
+
Pump::Xml.new('human', :instruct => false) do
|
15
|
+
tag :name
|
16
|
+
end.encode(Struct.new(:name).new('Artur'))
|
17
|
+
end
|
18
|
+
|
19
|
+
its(:encode) { should eql("<human>\n <name>Artur</name>\n</human>\n")}
|
9
20
|
end
|
10
21
|
end
|
11
22
|
|
@@ -201,15 +212,27 @@ describe Pump::Xml do
|
|
201
212
|
end
|
202
213
|
|
203
214
|
context "deep array-like nesting" do
|
204
|
-
let(:person) {
|
205
|
-
|
215
|
+
let(:person) {
|
216
|
+
Struct.new(:name, :children).new('Gustav', [
|
217
|
+
Struct.new(:name).new('Lilly'),
|
218
|
+
Struct.new(:name).new('Lena')
|
219
|
+
]) }
|
220
|
+
|
221
|
+
let(:xml) { Pump::Xml.new('person', [{:name => :name}, {:children => :children,
|
222
|
+
:array => [{:name => :name}]}], :instruct => false) }
|
206
223
|
|
207
224
|
it "returns xml string" do
|
208
225
|
xml.encode(person).should eql("<person>\n <name>Gustav</name>\n <children type=\"array\">\n <child>\n <name>Lilly</name>\n </child>\n <child>\n <name>Lena</name>\n </child>\n </children>\n</person>\n")
|
209
226
|
end
|
210
|
-
end
|
211
|
-
|
212
227
|
|
228
|
+
context "overwriting child name" do
|
229
|
+
let(:xml) { Pump::Xml.new('person', [{:name => :name}, {:children => :children,
|
230
|
+
:array => [{:name => :name}], :child_root => 'kid'}], :instruct => false) }
|
213
231
|
|
232
|
+
it "returns xml string" do
|
233
|
+
xml.encode(person).should eql("<person>\n <name>Gustav</name>\n <children type=\"array\">\n <kid>\n <name>Lilly</name>\n </kid>\n <kid>\n <name>Lena</name>\n </kid>\n </children>\n</person>\n")
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
214
237
|
end
|
215
238
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pump
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-02-
|
12
|
+
date: 2013-02-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -70,21 +70,24 @@ files:
|
|
70
70
|
- .rbenv-gemsets
|
71
71
|
- .rbenv-version
|
72
72
|
- .rspec
|
73
|
+
- .yardopts
|
73
74
|
- CHANGES.md
|
74
75
|
- Gemfile
|
75
76
|
- Guardfile
|
76
|
-
- LICENSE
|
77
|
+
- MIT-LICENSE
|
77
78
|
- README.md
|
78
79
|
- Rakefile
|
79
80
|
- benchmarks/encode.rb
|
80
81
|
- lib/pump.rb
|
81
82
|
- lib/pump/version.rb
|
82
83
|
- lib/pump/xml.rb
|
84
|
+
- lib/pump/xml/dsl.rb
|
83
85
|
- lib/pump/xml/node.rb
|
84
86
|
- lib/pump/xml/tag.rb
|
85
87
|
- lib/pump/xml/tag_array.rb
|
86
88
|
- lib/pump/xml/value.rb
|
87
89
|
- pump.gemspec
|
90
|
+
- spec/pump/xml/dsl_spec.rb
|
88
91
|
- spec/pump/xml/tag_array_spec.rb
|
89
92
|
- spec/pump/xml/tag_spec.rb
|
90
93
|
- spec/pump/xml/value_spec.rb
|
@@ -116,8 +119,10 @@ signing_key:
|
|
116
119
|
specification_version: 3
|
117
120
|
summary: Fast but inflexible XML encoding for ruby objects.
|
118
121
|
test_files:
|
122
|
+
- spec/pump/xml/dsl_spec.rb
|
119
123
|
- spec/pump/xml/tag_array_spec.rb
|
120
124
|
- spec/pump/xml/tag_spec.rb
|
121
125
|
- spec/pump/xml/value_spec.rb
|
122
126
|
- spec/pump/xml_spec.rb
|
123
127
|
- spec/spec_helper.rb
|
128
|
+
has_rdoc:
|