pump 0.5.1 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES.md +8 -1
- data/README.md +1 -1
- data/benchmarks/encode.rb +40 -3
- data/gemfiles/activesupport-3-2 +1 -0
- data/gemfiles/activesupport-4 +1 -0
- data/lib/pump.rb +1 -0
- data/lib/pump/array.rb +7 -1
- data/lib/pump/dsl.rb +57 -0
- data/lib/pump/encoder.rb +92 -0
- data/lib/pump/json.rb +97 -0
- data/lib/pump/object.rb +19 -3
- data/lib/pump/version.rb +1 -1
- data/lib/pump/xml.rb +14 -69
- data/pump.gemspec +3 -2
- data/spec/pump/array_spec.rb +34 -2
- data/spec/pump/{xml/dsl_spec.rb → dsl_spec.rb} +22 -22
- data/spec/pump/encoder_spec.rb +97 -0
- data/spec/pump/json_spec.rb +218 -0
- data/spec/pump/object_spec.rb +82 -3
- data/spec/pump/xml_spec.rb +0 -19
- metadata +27 -7
- data/lib/pump/xml/dsl.rb +0 -59
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c4b95096c96dfa59274e8b007a7946f0223e507c
|
4
|
+
data.tar.gz: 12e6c47f2239231db115c160575870739141ef95
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9725fb7b0bb3152bae3321623744f15e280bfc4edae242836702b3971bd69039007f7c54bc8b1e7a49f49b0d440f7d66db989642b64ad2b8e09858ff1d32e210
|
7
|
+
data.tar.gz: 360c20c887a7c50232df40b77805e86a26d8a8c399695fba4e360121eb721841768918f4738ac6fe957b75bac8d0c161b19eebdee27ebdd95707d45d7ccb758b
|
data/CHANGES.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
1
|
### dev
|
2
2
|
|
3
|
-
[full changelog](http://github.com/yolk/pump/compare/v0.0.1...master)
|
3
|
+
[full changelog](http://github.com/yolk/pump/compare/v0.0.1...master)
|
4
|
+
|
5
|
+
### 0.6.0 / 2013-07-24
|
6
|
+
|
7
|
+
[full changelog](http://github.com/yolk/valvat/compare/v0.5.1...v0.6.0)
|
8
|
+
|
9
|
+
* Added JSON serialization
|
10
|
+
* Added simple inheritance for encoders
|
data/README.md
CHANGED
data/benchmarks/encode.rb
CHANGED
@@ -4,17 +4,26 @@ require 'rubygems'
|
|
4
4
|
require 'benchmark'
|
5
5
|
|
6
6
|
require 'pump'
|
7
|
-
require 'ox'
|
8
|
-
require '
|
7
|
+
require 'ox'
|
8
|
+
require 'oj'
|
9
|
+
require 'yajl'
|
10
|
+
require 'active_model'
|
9
11
|
|
10
12
|
class Person < Struct.new(:name, :age, :created_at)
|
11
13
|
include ActiveModel::Serializers::Xml if defined?(ActiveModel)
|
14
|
+
include ActiveModel::Serializers::JSON if defined?(ActiveModel)
|
12
15
|
|
13
16
|
def attributes
|
14
17
|
{'name' => name, 'age' => age, 'created_at' => created_at}
|
15
18
|
end
|
16
19
|
end
|
17
20
|
|
21
|
+
pump_json = Pump::Json.new('person', [
|
22
|
+
{:age => :age, :attributes => {:type => 'integer'}},
|
23
|
+
{:"created-at" => :created_at, :typecast => :xmlschema, :attributes => {:type => 'datetime'}, :never_nil => true},
|
24
|
+
{:name => :name}
|
25
|
+
])
|
26
|
+
|
18
27
|
# Not optimized pump
|
19
28
|
pump = Pump::Xml.new('person', [
|
20
29
|
{:age => :age, :attributes => {:type => 'integer'}},
|
@@ -77,6 +86,12 @@ puts "Starting benchmark serializing array with #{array.size} entries #{times} t
|
|
77
86
|
|
78
87
|
Benchmark.bmbm { |x|
|
79
88
|
|
89
|
+
x.report("Pump::Json#encode") {
|
90
|
+
times.times {
|
91
|
+
pump_json.encode(array)
|
92
|
+
}
|
93
|
+
}
|
94
|
+
|
80
95
|
x.report("Pump::Xml#encode") {
|
81
96
|
times.times {
|
82
97
|
pump.encode(array)
|
@@ -97,11 +112,33 @@ Benchmark.bmbm { |x|
|
|
97
112
|
}
|
98
113
|
end
|
99
114
|
|
115
|
+
if defined?(Oj)
|
116
|
+
x.report("Oj") {
|
117
|
+
times.times {
|
118
|
+
Oj.dump(array.map(&:attributes), :mode => :compat)
|
119
|
+
}
|
120
|
+
}
|
121
|
+
end
|
122
|
+
|
123
|
+
if defined?(Yajl)
|
124
|
+
x.report("Yajl") {
|
125
|
+
times.times {
|
126
|
+
Yajl::Encoder.encode(array.map(&:attributes))
|
127
|
+
}
|
128
|
+
}
|
129
|
+
end
|
130
|
+
|
100
131
|
if defined?(ActiveModel)
|
101
|
-
x.report("ActiveModel#
|
132
|
+
x.report("ActiveModel#to_xml") {
|
102
133
|
times.times {
|
103
134
|
array.to_xml
|
104
135
|
}
|
105
136
|
}
|
137
|
+
|
138
|
+
x.report("ActiveModel#to_json") {
|
139
|
+
times.times {
|
140
|
+
array.to_json
|
141
|
+
}
|
142
|
+
}
|
106
143
|
end
|
107
144
|
}
|
data/gemfiles/activesupport-3-2
CHANGED
data/gemfiles/activesupport-4
CHANGED
data/lib/pump.rb
CHANGED
data/lib/pump/array.rb
CHANGED
@@ -3,7 +3,13 @@ module Pump
|
|
3
3
|
def pump_to_xml(options={})
|
4
4
|
encoder = get_pump_encoder(options[:set], :xml)
|
5
5
|
return to_xml(options) unless encoder
|
6
|
-
encoder.encode(self)
|
6
|
+
encoder.encode(self, options)
|
7
|
+
end
|
8
|
+
|
9
|
+
def pump_to_json(options={})
|
10
|
+
encoder = get_pump_encoder(options[:set], :json)
|
11
|
+
return to_json(options) unless encoder
|
12
|
+
encoder.encode(self, options)
|
7
13
|
end
|
8
14
|
|
9
15
|
private
|
data/lib/pump/dsl.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
module Pump
|
2
|
+
class Dsl
|
3
|
+
def initialize(&blk)
|
4
|
+
raise ArgumentError unless block_given?
|
5
|
+
instance_eval(&blk)
|
6
|
+
end
|
7
|
+
|
8
|
+
def config
|
9
|
+
@config ||= []
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def tag(name, options={}, &blk)
|
15
|
+
method = if block_given?
|
16
|
+
self.class.new(&blk).config
|
17
|
+
else
|
18
|
+
options.delete(:from) || (name.to_s =~ /-/ ? name.to_s.gsub('-', '_').to_sym : name)
|
19
|
+
end
|
20
|
+
config << ({ name => method }).merge(options)
|
21
|
+
end
|
22
|
+
alias_method :string, :tag
|
23
|
+
|
24
|
+
def integer(name, options={})
|
25
|
+
with_type('integer', name, options)
|
26
|
+
end
|
27
|
+
|
28
|
+
def float(name, options={})
|
29
|
+
with_type('float', name, options)
|
30
|
+
end
|
31
|
+
|
32
|
+
def boolean(name, options={})
|
33
|
+
with_type('boolean', name, options)
|
34
|
+
end
|
35
|
+
|
36
|
+
def date(name, options={})
|
37
|
+
with_type('date', name, options)
|
38
|
+
end
|
39
|
+
|
40
|
+
def datetime(name, options={})
|
41
|
+
options[:typecast] = :xmlschema unless options.has_key?(:typecast)
|
42
|
+
with_type('datetime', name, options)
|
43
|
+
end
|
44
|
+
alias_method :time, :datetime
|
45
|
+
|
46
|
+
def with_type(type, name, options)
|
47
|
+
(options[:attributes] ||= {}).merge!({:type => type})
|
48
|
+
options[:xmlsafe] = true unless options.has_key?(:xmlsafe)
|
49
|
+
tag(name, options)
|
50
|
+
end
|
51
|
+
|
52
|
+
def array(name, options={}, &blk)
|
53
|
+
options[:array] = self.class.new(&blk).config
|
54
|
+
tag(name, options)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/pump/encoder.rb
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
require "pump/dsl"
|
2
|
+
|
3
|
+
module Pump
|
4
|
+
class Encoder
|
5
|
+
attr_reader :root_name, :encoder_config, :encoder_options, :base
|
6
|
+
|
7
|
+
# Creates a new XML-encoder with a root tag named after +root_name+.
|
8
|
+
#
|
9
|
+
# @example Create a simple encoder for a person with a name attribute:
|
10
|
+
# Pump::Xml.new :person do
|
11
|
+
# tag :name
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# @example Create the same without usage of the DSL:
|
15
|
+
# Pump::Xml.new :person, [{:name => :name}]
|
16
|
+
#
|
17
|
+
# @example Create the same but without the xml instruct
|
18
|
+
# Pump::Xml.new :person, :instruct => false do
|
19
|
+
# tag :name
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# @example The same again without DSL:
|
23
|
+
#
|
24
|
+
# Pump::Xml.new :person, [{:name => :name}], :instruct => false
|
25
|
+
#
|
26
|
+
# @param [String, Symbol] root_name the name of the used root tag
|
27
|
+
# @param [Array<Hash>] encoder_config optional config for all tags
|
28
|
+
# @param [Hash] encoder_options optional encoder_options for the whole encoder
|
29
|
+
# @yield an optional block to create the encoder with the Pump::Dsl
|
30
|
+
#
|
31
|
+
# @return [self]
|
32
|
+
def initialize(root_name, encoder_config=nil, encoder_options={}, &blk)
|
33
|
+
if encoder_config.is_a?(Array)
|
34
|
+
@encoder_config = encoder_config
|
35
|
+
@encoder_options = encoder_options || {}
|
36
|
+
else
|
37
|
+
raise ArgumentError unless block_given?
|
38
|
+
@encoder_options = encoder_config || {}
|
39
|
+
@encoder_config = Pump::Dsl.new(&blk).config
|
40
|
+
end
|
41
|
+
@root_name = root_name
|
42
|
+
merge_base
|
43
|
+
|
44
|
+
compile
|
45
|
+
end
|
46
|
+
|
47
|
+
# Encode a object or an array of objects to an XML-string.
|
48
|
+
#
|
49
|
+
# @param [Object, Array<Object>] object object or an array of objects to
|
50
|
+
# encode to XML. The only requirement: The given objects must respond
|
51
|
+
# to all methods configured during initalization of the Pump::Xml instance.
|
52
|
+
#
|
53
|
+
# @return [String]
|
54
|
+
def encode(object, options={})
|
55
|
+
object.is_a?(Array) ? encode_array(object, options) : encode_single(object, options)
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def compile
|
61
|
+
compile_string && instance_eval(compile_string)
|
62
|
+
end
|
63
|
+
|
64
|
+
def compile_string;end
|
65
|
+
|
66
|
+
def merge_base
|
67
|
+
return unless @encoder_options[:base]
|
68
|
+
@base = @encoder_options.delete(:base)
|
69
|
+
|
70
|
+
merge_base_config
|
71
|
+
merge_base_options
|
72
|
+
end
|
73
|
+
|
74
|
+
def merge_base_config
|
75
|
+
original_encoder_config = @encoder_config
|
76
|
+
@encoder_config = base.encoder_config.dup
|
77
|
+
original_encoder_config.each do |it|
|
78
|
+
key = it.keys.first
|
79
|
+
index = @encoder_config.index{|config| config.keys.first == key}
|
80
|
+
if index
|
81
|
+
@encoder_config[index] = it
|
82
|
+
else
|
83
|
+
@encoder_config.push(it)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def merge_base_options
|
89
|
+
encoder_options.merge!(base.encoder_options) { |key, v1, v2| v1 }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
data/lib/pump/json.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
require "pump/encoder"
|
2
|
+
require "oj"
|
3
|
+
|
4
|
+
module Pump
|
5
|
+
class Json < Encoder
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def compile_string
|
10
|
+
<<-EOV
|
11
|
+
def encode_single(object, options)
|
12
|
+
json = {}
|
13
|
+
#{build_string(encoder_config)}
|
14
|
+
unless options[:exclude_root_in_json]
|
15
|
+
json = { :'#{format_name(root_name)}' => json }
|
16
|
+
end
|
17
|
+
Oj.dump(json, :mode => :compat)
|
18
|
+
end
|
19
|
+
|
20
|
+
def encode_array(objects, options)
|
21
|
+
Oj.dump(if options[:exclude_root_in_json]
|
22
|
+
objects.map do |object|
|
23
|
+
json = {}
|
24
|
+
#{build_string(encoder_config)}
|
25
|
+
json
|
26
|
+
end
|
27
|
+
else
|
28
|
+
objects.map do |object|
|
29
|
+
json = {}
|
30
|
+
#{build_string(encoder_config)}
|
31
|
+
{ :'#{format_name(root_name)}' => json }
|
32
|
+
end
|
33
|
+
end, :mode => :compat)
|
34
|
+
end
|
35
|
+
EOV
|
36
|
+
end
|
37
|
+
|
38
|
+
def build_string(config, variable='json')
|
39
|
+
config.inject("") do |str, config|
|
40
|
+
build_key_value_pair(str, config, variable)
|
41
|
+
str
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def build_key_value_pair(str, config, variable='json')
|
46
|
+
name, method_name = config.keys.first, config.values.first
|
47
|
+
if method_name.is_a?(Array) && !config.has_key?(:static_value)
|
48
|
+
build_hash(str, name, method_name, config, variable)
|
49
|
+
elsif config[:array]
|
50
|
+
build_array(str, name, method_name, config, variable)
|
51
|
+
else
|
52
|
+
build_simple(str, name, method_name, config, variable)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def build_hash(str, name, method_name, config, variable)
|
57
|
+
str << "#{build_condition(config)}\n"
|
58
|
+
str << "#{variable}[:'#{format_name(name)}'] = {}\n"
|
59
|
+
str << build_string(method_name, "#{variable}[:'#{format_name(name)}']")
|
60
|
+
str << "end\n" if build_condition(config)
|
61
|
+
end
|
62
|
+
|
63
|
+
def build_array(str, name, method_name, config, variable)
|
64
|
+
str << "#{build_condition(config)}\n"
|
65
|
+
str << "#{variable}[:'#{format_name(name)}'] = []\n"
|
66
|
+
unless config.has_key?(:static_value)
|
67
|
+
str << "object.#{method_name}.each do |object| "
|
68
|
+
str << "#{variable}[:'#{format_name(name)}'] << {}\n"
|
69
|
+
str << build_string(config[:array], "#{variable}[:'#{format_name(name)}'][-1]")
|
70
|
+
str << "end\n"
|
71
|
+
end
|
72
|
+
str << "end\n" if build_condition(config)
|
73
|
+
end
|
74
|
+
|
75
|
+
def build_simple(str, name, method_name, config, variable)
|
76
|
+
str << "#{variable}[:'#{format_name(name)}']=#{build_value(method_name, config)}#{build_condition(config)}\n"
|
77
|
+
end
|
78
|
+
|
79
|
+
def build_value(method_name, config)
|
80
|
+
return config[:static_value].inspect if config.has_key?(:static_value)
|
81
|
+
"object.#{method_name}"
|
82
|
+
end
|
83
|
+
|
84
|
+
def build_condition(config)
|
85
|
+
if config[:if]
|
86
|
+
" if object.#{config[:if]}"
|
87
|
+
elsif config[:unless]
|
88
|
+
" unless object.#{config[:unless]}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def format_name(name)
|
93
|
+
return name if encoder_options[:underscore] == false
|
94
|
+
name.to_s.underscore
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
data/lib/pump/object.rb
CHANGED
@@ -9,9 +9,18 @@ module Pump
|
|
9
9
|
def pump_to_xml(options={})
|
10
10
|
encoder = self.class.pumps.get(options[:set], :xml)
|
11
11
|
if encoder
|
12
|
-
encoder.encode(self)
|
12
|
+
encoder.encode(self, options)
|
13
13
|
else
|
14
|
-
|
14
|
+
to_xml(options)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def pump_to_json(options={})
|
19
|
+
encoder = self.class.pumps.get(options[:set], :json)
|
20
|
+
if encoder
|
21
|
+
encoder.encode(self, options)
|
22
|
+
else
|
23
|
+
to_json(options)
|
15
24
|
end
|
16
25
|
end
|
17
26
|
|
@@ -21,7 +30,14 @@ module Pump
|
|
21
30
|
end
|
22
31
|
|
23
32
|
def add_pump(name, set=nil, options={}, &block)
|
24
|
-
|
33
|
+
if options[:base]
|
34
|
+
xml_options = options.dup.merge({:base => pumps.get(options[:base], :xml)})
|
35
|
+
json_options = options.dup.merge({:base => pumps.get(options[:base], :json)})
|
36
|
+
else
|
37
|
+
xml_options, json_options = options, options
|
38
|
+
end
|
39
|
+
pumps.add(set, :xml, Pump::Xml.new(name, xml_options, &block))
|
40
|
+
pumps.add(set, :json, Pump::Json.new(name, json_options, &block))
|
25
41
|
end
|
26
42
|
end
|
27
43
|
end
|
data/lib/pump/version.rb
CHANGED