ox-builder 0.1.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,25 @@
1
+ require_relative './runner'
2
+ require 'yaml'
3
+
4
+ Country = Struct.new(:code, :name, :population, :north, :south, :east, :west, :capital, :continent_name)
5
+ data = YAML.load_file('benchmarks/data/countries.yml')['countries']['country'] * 100
6
+ @countries = data.map{ |c| Country.new(*c.values) }
7
+
8
+ builder_tilt = Tilt.new('benchmarks/templates/large.builder')
9
+ ox_tilt = Tilt.new('benchmarks/templates/large.ox')
10
+
11
+ # Output is 11M
12
+
13
+ Benchmark.ips do |x|
14
+ x.config(time: 60, warmup: 10)
15
+
16
+ x.report('builder') do
17
+ builder_tilt.render(Object.new, { countries: @countries })
18
+ end
19
+
20
+ x.report('ox') do
21
+ ox_tilt.render(Object.new, { countries: @countries })
22
+ end
23
+
24
+ x.compare!
25
+ end
@@ -0,0 +1,27 @@
1
+ require_relative './runner'
2
+ require 'yaml'
3
+
4
+ Country = Struct.new(:code, :name, :population, :north, :south, :east, :west, :capital, :continent_name)
5
+ data = YAML.load_file('benchmarks/data/countries.yml')['countries']['country']
6
+ @countries = data.map{ |c| Country.new(*c.values) }
7
+
8
+ builder_tilt = Tilt.new('benchmarks/templates/large.builder')
9
+ ox_tilt = Tilt.new('benchmarks/templates/large.ox')
10
+
11
+ File.write('ox.xml', builder_tilt.render(Object.new, { countries: @countries }))
12
+
13
+ # Output is 107K
14
+
15
+ Benchmark.ips do |x|
16
+ x.config(time: 20, warmup: 10)
17
+
18
+ x.report('builder') do
19
+ builder_tilt.render(Object.new, { countries: @countries })
20
+ end
21
+
22
+ x.report('ox') do
23
+ ox_tilt.render(Object.new, { countries: @countries })
24
+ end
25
+
26
+ x.compare!
27
+ end
@@ -0,0 +1,6 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+
3
+ require 'benchmark/ips'
4
+ require 'builder'
5
+ require 'tilt'
6
+ require 'ox/builder'
@@ -0,0 +1,20 @@
1
+ require_relative './runner'
2
+
3
+ builder_tilt = Tilt.new('benchmarks/templates/small.builder')
4
+ ox_tilt = Tilt.new('benchmarks/templates/small.ox')
5
+
6
+ # Output is 167 bytes
7
+
8
+ Benchmark.ips do |x|
9
+ x.config(time: 10, warmup: 5)
10
+
11
+ x.report('builder') do
12
+ builder_tilt.render
13
+ end
14
+
15
+ x.report('ox') do
16
+ ox_tilt.render
17
+ end
18
+
19
+ x.compare!
20
+ end
@@ -0,0 +1,20 @@
1
+ xml.instruct!
2
+
3
+ xml.countries do
4
+ countries.each do |country|
5
+ xml.country do
6
+ xml.name { xml.cdata!(country.name) }
7
+ xml.code { xml.cdata!(country.code) }
8
+ xml.continent { xml.cdata!(country.continent_name) }
9
+ xml.capital { xml.cdata!(country.capital.to_s) }
10
+ xml.population country.population
11
+
12
+ xml.boundaries do
13
+ xml.north country.north
14
+ xml.sourth country.south
15
+ xml.east country.east
16
+ xml.west country.west
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ instruct!
2
+
3
+ countries do
4
+ countries.each do |country|
5
+ country do
6
+ name { cdata!(country.name) }
7
+ code { cdata!(country.code) }
8
+ continent { cdata!(country.continent_name) }
9
+ capital { cdata!(country.capital) }
10
+ population country.population
11
+
12
+ boundaries do
13
+ north country.north
14
+ sourth country.south
15
+ east country.east
16
+ west country.west
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ xml.instruct!
2
+
3
+ xml.person id: 123 do
4
+ xml.name { xml.cdata!('John Smith') }
5
+ xml.age 37
6
+ xml.nationality 'Canadian'
7
+ end
@@ -0,0 +1,7 @@
1
+ instruct!
2
+
3
+ person id: 123 do
4
+ name { cdata!('John Smith') }
5
+ age 37
6
+ nationality 'Canadian'
7
+ end
data/bin/console CHANGED
@@ -1,6 +1,10 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require "bundler/setup"
4
+ require 'active_support'
5
+ require 'active_support/hash_with_indifferent_access'
6
+ require 'action_view'
7
+ require 'tilt'
4
8
  require "ox/builder"
5
9
 
6
10
  # You can add fixtures and/or initialization code here to make experimenting
@@ -0,0 +1,21 @@
1
+ require 'active_support/core_ext/class/attribute'
2
+ require 'action_dispatch/http/mime_type'
3
+
4
+ module Ox
5
+ module Builder
6
+ module ActionView
7
+ class TemplateHandler
8
+ class_attribute :default_format
9
+ self.default_format = Mime::XML
10
+
11
+ def call(template)
12
+ <<-RUBY
13
+ xml = ::Ox::Builder.build {
14
+ #{template.source}
15
+ };xml.to_xml
16
+ RUBY
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,42 @@
1
+ module Ox
2
+ module Builder
3
+ module DSL
4
+ def instruct!(*args)
5
+ attributes = args.last.is_a?(Hash) ? args.pop : { version: '1.0', encoding: 'UTF-8' }
6
+ name = args.first || :xml
7
+
8
+ with_dsl(Ox::Instruct.new(name)) do |instruct|
9
+ instruct.add_attributes(attributes)
10
+ node << instruct.node
11
+ end
12
+ end
13
+
14
+ def cdata!(text)
15
+ node << Ox::CData.new(text)
16
+ end
17
+
18
+ def comment!(text)
19
+ node << Ox::Comment.new(text)
20
+ end
21
+
22
+ def doctype!(type)
23
+ node << Ox::DocType.new(type)
24
+ end
25
+
26
+ def tag!(name, *args, &block)
27
+ builder = Builder.build(Ox::Element.new(name), &block).tap do |tag|
28
+ attributes = args.last.is_a?(Hash) ? args.pop : {}
29
+
30
+ tag.add_attributes(attributes)
31
+
32
+ args.each do |text|
33
+ text = text.is_a?(Ox::Node) ? text : text.to_s
34
+ tag.node << text
35
+ end
36
+ end
37
+
38
+ node << builder.node
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,39 @@
1
+ module Ox
2
+ module Builder
3
+ class Factory
4
+ include DSL
5
+
6
+ attr_reader :node
7
+
8
+ def initialize(node)
9
+ @node = node
10
+ end
11
+
12
+ def to_s
13
+ Ox.dump(node)
14
+ end
15
+ alias_method :to_xml, :to_s
16
+
17
+ def inspect
18
+ "#<#{self.class.name}:0x#{"%x" % object_id} node=#{node}>"
19
+ end
20
+
21
+ def add_attributes(attributes)
22
+ attributes.each do |key, val|
23
+ node[key] = val
24
+ end
25
+ end
26
+
27
+ protected
28
+
29
+ def method_missing(name, *args, &block)
30
+ name = name[0...-1] if name.to_s.end_with?('!')
31
+ tag!(name, *args, &block)
32
+ end
33
+
34
+ def with_dsl(obj, &block)
35
+ Factory.new(obj).tap(&block)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,30 @@
1
+ module Ox
2
+ module Builder
3
+ class FallbackContextProxy < Docile::FallbackContextProxy
4
+ DSL_METHODS = DSL.instance_methods(false)
5
+
6
+ def method_missing(method, *args, &block)
7
+ # This is somewhat more complicated than the normal FallbackContextProxy provided by
8
+ # docile. The reason for this is that the Builder has its own method_missing to
9
+ # allow tags to be defined dynamically, but that can't define a respond_to_missing?
10
+ # because we don't know what the methods will be until they are accessed.
11
+ #
12
+ # Therefore, if the fallback doesn't respond to the method, send it to the receiver
13
+ # regardless of if it responds to it or not (so that its method_missing can pick it up).
14
+ #
15
+ # The next wrinkle is that we need to try the fallback before the receiver or else
16
+ # nested DSLs lose access to methods defined in the original scope. To handle this
17
+ # without allowing the core DSL methods to be clobbered, we first check if the method
18
+ # is a DSL method and if so pass it directly to the receiver.
19
+
20
+ if DSL_METHODS.include?(method.to_sym)
21
+ @__receiver__.__send__(method.to_sym, *args, &block)
22
+ elsif @__fallback__.respond_to?(method.to_sym)
23
+ @__fallback__.__send__(method.to_sym, *args, &block)
24
+ else
25
+ @__receiver__.__send__(method, *args, &block)
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,5 +1,5 @@
1
1
  module Ox
2
2
  module Builder
3
- VERSION = "0.1.0"
3
+ VERSION = "1.0.1"
4
4
  end
5
5
  end
data/lib/ox/builder.rb CHANGED
@@ -1,7 +1,34 @@
1
- require "ox/builder/version"
1
+ require 'ox'
2
+ require 'docile'
3
+ require 'ox/builder/version'
4
+ require 'ox/builder/dsl'
5
+ require 'ox/builder/factory'
6
+ require 'ox/builder/fallback_context_proxy'
2
7
 
3
8
  module Ox
4
9
  module Builder
5
- # Your code goes here...
10
+ class << self
11
+ def build(node = Ox::Document.new, &block)
12
+ Factory.new(node).tap do |builder|
13
+ dsl_eval(builder, builder, &block) if block_given?
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def dsl_eval(dsl, *args, &block)
20
+ Docile::Execution.exec_in_proxy_context(dsl, FallbackContextProxy, *args, &block)
21
+ end
22
+ end
6
23
  end
7
24
  end
25
+
26
+ if defined?(Tilt)
27
+ require 'tilt/ox_builder_template'
28
+ Tilt.register Tilt::OxBuilderTemplate, 'ox'
29
+ end
30
+
31
+ if defined?(ActionView)
32
+ require 'ox/builder/action_view/template_handler'
33
+ ActionView::Template.register_template_handler :ox, Ox::Builder::ActionView::TemplateHandler.new
34
+ end
@@ -0,0 +1,28 @@
1
+ require 'tilt/template'
2
+ require 'ox/builder'
3
+
4
+ module Tilt
5
+ class OxBuilderTemplate < Template
6
+ self.default_mime_type = 'text/xml'
7
+
8
+ def self.engine_initialized?
9
+ defined? ::Ox::Builder
10
+ end
11
+
12
+ def initialize_engine
13
+ require_template_library 'ox-builder'
14
+ end
15
+
16
+ def prepare
17
+ @code =<<-RUBY
18
+ Ox::Builder.build do
19
+ #{data}
20
+ end.to_xml
21
+ RUBY
22
+ end
23
+
24
+ def precompiled_template(locals)
25
+ @code
26
+ end
27
+ end
28
+ end
data/ox-builder.gemspec CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |gem|
9
9
  gem.authors = ["Daniel Vandersluis"]
10
10
  gem.email = ["dvandersluis@selfmgmt.com"]
11
11
 
12
- gem.summary = %q{XML Builder for Rails using ox}
12
+ gem.summary = %q{DSL for easily building XML documents using ox}
13
13
  gem.homepage = "https://www.github.com/dvandersluis/ox-builder"
14
14
  gem.license = "MIT"
15
15
 
@@ -21,4 +21,12 @@ Gem::Specification.new do |gem|
21
21
  gem.add_development_dependency "bundler", "~> 1.11"
22
22
  gem.add_development_dependency "rake", "~> 10.0"
23
23
  gem.add_development_dependency "rspec", "~> 3.0"
24
+ gem.add_development_dependency 'actionpack', ['~> 3.2']
25
+ gem.add_development_dependency 'activesupport', ['~> 3.2']
26
+ gem.add_development_dependency 'tilt', ['~> 1.4']
27
+ gem.add_development_dependency 'benchmark-ips'
28
+ gem.add_development_dependency 'builder'
29
+
30
+ gem.add_dependency 'ox', ['~> 2.3.0']
31
+ gem.add_dependency 'docile', ['~> 1.1.5']
24
32
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ox-builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Vandersluis
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-03-30 00:00:00.000000000 Z
11
+ date: 2016-04-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  type: :development
@@ -52,6 +52,104 @@ dependencies:
52
52
  - - ~>
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ type: :development
57
+ prerelease: false
58
+ name: actionpack
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ~>
62
+ - !ruby/object:Gem::Version
63
+ version: '3.2'
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '3.2'
69
+ - !ruby/object:Gem::Dependency
70
+ type: :development
71
+ prerelease: false
72
+ name: activesupport
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: '3.2'
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '3.2'
83
+ - !ruby/object:Gem::Dependency
84
+ type: :development
85
+ prerelease: false
86
+ name: tilt
87
+ requirement: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ~>
90
+ - !ruby/object:Gem::Version
91
+ version: '1.4'
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: '1.4'
97
+ - !ruby/object:Gem::Dependency
98
+ type: :development
99
+ prerelease: false
100
+ name: benchmark-ips
101
+ requirement: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ! '>='
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ type: :development
113
+ prerelease: false
114
+ name: builder
115
+ requirement: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ! '>='
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ! '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ type: :runtime
127
+ prerelease: false
128
+ name: ox
129
+ requirement: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ~>
132
+ - !ruby/object:Gem::Version
133
+ version: 2.3.0
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ~>
137
+ - !ruby/object:Gem::Version
138
+ version: 2.3.0
139
+ - !ruby/object:Gem::Dependency
140
+ type: :runtime
141
+ prerelease: false
142
+ name: docile
143
+ requirement: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ~>
146
+ - !ruby/object:Gem::Version
147
+ version: 1.1.5
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ~>
151
+ - !ruby/object:Gem::Version
152
+ version: 1.1.5
55
153
  description:
56
154
  email:
57
155
  - dvandersluis@selfmgmt.com
@@ -62,14 +160,29 @@ files:
62
160
  - .gitignore
63
161
  - .rspec
64
162
  - .travis.yml
163
+ - CHANGELOG.md
65
164
  - Gemfile
66
165
  - LICENSE.txt
67
166
  - README.md
68
167
  - Rakefile
168
+ - benchmarks/data/countries.yml
169
+ - benchmarks/huge.rb
170
+ - benchmarks/medium.rb
171
+ - benchmarks/runner.rb
172
+ - benchmarks/small.rb
173
+ - benchmarks/templates/large.builder
174
+ - benchmarks/templates/large.ox
175
+ - benchmarks/templates/small.builder
176
+ - benchmarks/templates/small.ox
69
177
  - bin/console
70
178
  - bin/setup
71
179
  - lib/ox/builder.rb
180
+ - lib/ox/builder/action_view/template_handler.rb
181
+ - lib/ox/builder/dsl.rb
182
+ - lib/ox/builder/factory.rb
183
+ - lib/ox/builder/fallback_context_proxy.rb
72
184
  - lib/ox/builder/version.rb
185
+ - lib/tilt/ox_builder_template.rb
73
186
  - ox-builder.gemspec
74
187
  homepage: https://www.github.com/dvandersluis/ox-builder
75
188
  licenses:
@@ -94,6 +207,6 @@ rubyforge_project:
94
207
  rubygems_version: 2.1.5
95
208
  signing_key:
96
209
  specification_version: 4
97
- summary: XML Builder for Rails using ox
210
+ summary: DSL for easily building XML documents using ox
98
211
  test_files: []
99
212
  has_rdoc: