pump 0.5.1 → 0.6.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9047d695a9bb5dbbec84d04fc9a77bebb43c35f8
4
- data.tar.gz: eeed27e8e5f98a30fa22271af1e6182cc3178bcd
3
+ metadata.gz: c4b95096c96dfa59274e8b007a7946f0223e507c
4
+ data.tar.gz: 12e6c47f2239231db115c160575870739141ef95
5
5
  SHA512:
6
- metadata.gz: 6c696f69ee33b842a90e2bd2790a802415497a29aed0d274331bdefc7d54bc5c975b9e6cb6cfd53e161f95a37447777ceefb51c58b1a65df83e64829e755e0ab
7
- data.tar.gz: f020baf37e32686173e0334193fbd555c93966a3b8924f3ecaa0dd0127a3dbc8c484dba40217ba11a7d682b6bdb4cd27a238bff04cd460dab16708e18443223c
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
@@ -1,6 +1,6 @@
1
1
  # Pump
2
2
 
3
- Fast but inflexible XML encoding for ruby objects.
3
+ Fast but inflexible XML and JSON encoding for ruby objects.
4
4
 
5
5
  ## Quick benchmark
6
6
 
data/benchmarks/encode.rb CHANGED
@@ -4,17 +4,26 @@ require 'rubygems'
4
4
  require 'benchmark'
5
5
 
6
6
  require 'pump'
7
- require 'ox' rescue nil
8
- require 'active_model' rescue nil
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#serialize") {
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
  }
@@ -1,6 +1,7 @@
1
1
  source "http://rubygems.org"
2
2
 
3
3
  gem "activemodel", "3.2.13"
4
+ gem "oj"
4
5
 
5
6
  gem 'rspec', '>= 2.4.0'
6
7
  gem 'rake'
@@ -1,6 +1,7 @@
1
1
  source "http://rubygems.org"
2
2
 
3
3
  gem "activemodel", "4.0"
4
+ gem "oj"
4
5
 
5
6
  gem 'rspec', '>= 2.4.0'
6
7
  gem 'rake'
data/lib/pump.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "pump/version"
2
2
  require "pump/xml"
3
+ require "pump/json"
3
4
  require "pump/object"
4
5
  require "pump/array"
5
6
 
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
@@ -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
- self.to_xml(options)
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
- pumps.add(set, :xml, Pump::Xml.new(name, options, &block))
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
@@ -1,3 +1,3 @@
1
1
  module Pump
2
- VERSION = "0.5.1"
2
+ VERSION = "0.6.0"
3
3
  end