compositor 1.0.1 → 2.0.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 +4 -4
- data/README.md +12 -9
- data/lib/compositor/base.rb +8 -11
- data/lib/compositor/compositors/list_compositor.rb +5 -0
- data/lib/compositor/compositors/literal_compositor.rb +12 -0
- data/lib/compositor/compositors/map_compositor.rb +5 -0
- data/lib/compositor/version.rb +1 -1
- data/spec/compositor/base_spec.rb +11 -18
- data/spec/compositor/{list_spec.rb → compositors/list_compositor_spec.rb} +1 -1
- data/spec/compositor/{literal_spec.rb → compositors/literal_compositor_spec.rb} +2 -2
- data/spec/compositor/{hash_spec.rb → compositors/map_compositor_spec.rb} +1 -1
- data/spec/compositor/performance_spec.rb +2 -2
- metadata +27 -26
- data/lib/compositor/list.rb +0 -7
- data/lib/compositor/literal.rb +0 -14
- data/lib/compositor/map.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 39aa83a1dbde3279e06295e7a5ce005444812d92
|
4
|
+
data.tar.gz: b36f918486e1adcd5daa2da24676b96a2fac0d26
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c878fb457203fdd022a49e991d2dee76ac18bb068b7811a196e03e81222a23b73304740efac40a45c6b632561b639a5b04367481841a9419f0e8a4368f050373
|
7
|
+
data.tar.gz: e6850ec7f0c0fd5a0b4c4eab1eb5ad2a69873db8afefd93ffde011b43c61e7f705251df25deb1957f230a493e0551d6e1f601ea434ab611ad757855c34601ca1
|
data/README.md
CHANGED
@@ -3,6 +3,7 @@ Compositor
|
|
3
3
|
|
4
4
|
[](http://badge.fury.io/rb/compositor)
|
5
5
|
[](http://travis-ci.org/wanelo/compositor)
|
6
|
+
[](https://codeclimate.com/github/wanelo/compositor)
|
6
7
|
|
7
8
|
A Composite Design Pattern with a neat DSL for constructing trees of objects in order to render them as a Hash, and subsequently
|
8
9
|
JSON. Used by Wanelo to generate all JSON API responses by compositing multiple objects together in API responses, converting to
|
@@ -83,9 +84,11 @@ element.
|
|
83
84
|
So here is how to create a list of users in this way, but explicitly declaring classes:
|
84
85
|
|
85
86
|
```ruby
|
86
|
-
compositor =
|
87
|
-
|
88
|
-
|
87
|
+
compositor = ListCompositor.new(view_context,
|
88
|
+
:collection => @users.map { |user|
|
89
|
+
UserCompositor.new(view_context, user, { :root => true })
|
90
|
+
},
|
91
|
+
:root => :users)
|
89
92
|
```
|
90
93
|
|
91
94
|
When calling ```to_hash``` on the top level compositor, we get:
|
@@ -121,7 +124,7 @@ of complex responses, as described below.
|
|
121
124
|
```UserCompositor``` class, when defined, automatically adds a ```user``` method to the DSL class, which effictively
|
122
125
|
instantiates the new UserCompositor instance, passing the context into it automatically.
|
123
126
|
|
124
|
-
Using built-in ```
|
127
|
+
Using built-in ```MapCompositor``` and ```ListCompositor``` we can construct multiple objects into a larger
|
125
128
|
hierarchy.
|
126
129
|
|
127
130
|
In the example below, an application is assumed to define ```StoreCompositor```and ```ProductCompositor``` classes
|
@@ -164,7 +167,7 @@ similar to ```UserCompositor```, but wrapping ```Store``` and ```Product``` Acti
|
|
164
167
|
```
|
165
168
|
|
166
169
|
Inside the list definition above, ```@products``` is a collection of Products, ```ActiveRecord``` objects,
|
167
|
-
and the block maps each to a Compositor using ```product
|
170
|
+
and the block maps each to a Compositor using ```product``` method, registered by ProductCompositor.
|
168
171
|
|
169
172
|
### Instance Variables
|
170
173
|
|
@@ -174,11 +177,11 @@ was defined on ```view_context``` (by Rails, which copies them from the Controll
|
|
174
177
|
so became automatically available inside DSL. Note that all instance variables must be
|
175
178
|
defined *before* the DSL instance is created.
|
176
179
|
|
177
|
-
### Method
|
180
|
+
### Method Names in the DSL
|
178
181
|
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
+
Compositor will extract the full name of the class and place that name into the DSL. For example, ```MyModule::UserCompositor```
|
183
|
+
will define a ```my_module_user``` method in the DSL. To create a method called ```user```, the standard convention
|
184
|
+
is to define a class in the global namespace called ```UserCompositor```.
|
182
185
|
|
183
186
|
If you prefer to have your own ```Compositor``` class hierarchy, or just compositors that should not be added to the
|
184
187
|
DSL, you can name the classes starting with ```Abstract```, such as ```MyModule::AbstractCompositor```.
|
data/lib/compositor/base.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module Compositor
|
2
|
-
class MethodAlreadyDefinedError < RuntimeError;
|
2
|
+
class MethodAlreadyDefinedError < RuntimeError;
|
3
|
+
end
|
3
4
|
|
4
5
|
class Base
|
5
6
|
attr_reader :attrs
|
@@ -33,16 +34,12 @@ module Compositor
|
|
33
34
|
self.root ? true : false
|
34
35
|
end
|
35
36
|
|
36
|
-
def
|
37
|
-
self.
|
38
|
-
end
|
39
|
-
|
40
|
-
def self.root_class_name(klazz)
|
41
|
-
klazz.name.gsub(/(.*::)|(Compositor$)/, '').underscore
|
37
|
+
def self.original_dsl_name
|
38
|
+
self.name.gsub(/(Compositor$)/, '').gsub(/::/, '_').underscore
|
42
39
|
end
|
43
40
|
|
44
41
|
def self.inherited(subclass)
|
45
|
-
method_name =
|
42
|
+
method_name = subclass.original_dsl_name
|
46
43
|
unless method_name.eql?("base") || method_name.start_with?("abstract")
|
47
44
|
# check if it's already defined
|
48
45
|
if Compositor::DSL.instance_methods.include?(method_name.to_sym)
|
@@ -65,6 +62,6 @@ end
|
|
65
62
|
require_relative 'dsl'
|
66
63
|
require_relative 'composite'
|
67
64
|
require_relative 'leaf'
|
68
|
-
require_relative '
|
69
|
-
require_relative '
|
70
|
-
require_relative '
|
65
|
+
require_relative 'compositors/literal_compositor'
|
66
|
+
require_relative 'compositors/list_compositor'
|
67
|
+
require_relative 'compositors/map_compositor'
|
data/lib/compositor/version.rb
CHANGED
@@ -1,28 +1,22 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Compositor::Base do
|
4
|
-
describe "#
|
5
|
-
it "returns the underscored class name" do
|
6
|
-
Compositor::Base.root_class_name(Object).should == "object"
|
7
|
-
end
|
8
|
-
|
4
|
+
describe "#original_dsl_name" do
|
9
5
|
it "returns the underscored class name with compositor stripped out" do
|
10
|
-
|
6
|
+
DslStringCompositor.original_dsl_name.should == "dsl_string"
|
11
7
|
end
|
8
|
+
end
|
12
9
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
# 2nd class
|
20
|
-
module ::Foo
|
21
|
-
class UserCompositor < Compositor::Leaf
|
10
|
+
describe '.inherited' do
|
11
|
+
describe "when class is defined inside a module" do
|
12
|
+
it "returns the underscored class name with compositor stripped out but with the module added" do
|
13
|
+
module Exploding
|
14
|
+
class ExplosionCompositor < Compositor::Leaf
|
22
15
|
end
|
23
16
|
end
|
24
|
-
|
25
|
-
|
17
|
+
|
18
|
+
expect(Compositor::DSL.instance_methods).to include(:exploding_explosion)
|
19
|
+
end
|
26
20
|
end
|
27
21
|
|
28
22
|
it "does not add DSL when class name begins with Abstract" do
|
@@ -39,6 +33,5 @@ describe Compositor::Base do
|
|
39
33
|
expect { block.call }.not_to raise_error
|
40
34
|
Compositor::DSL.instance_methods.should_not include(:abstract_user)
|
41
35
|
end
|
42
|
-
|
43
36
|
end
|
44
37
|
end
|
@@ -1,12 +1,12 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe LiteralCompositor do
|
4
4
|
|
5
5
|
let(:context) { Object.new }
|
6
6
|
|
7
7
|
it 'returns the hash its given' do
|
8
8
|
actual = { test: 123 }
|
9
9
|
|
10
|
-
|
10
|
+
LiteralCompositor.new(context, actual).to_hash.should == actual
|
11
11
|
end
|
12
12
|
end
|
@@ -34,10 +34,10 @@ describe 'Performance' do
|
|
34
34
|
10000.times do
|
35
35
|
string = DslStringCompositor.new(context)
|
36
36
|
int = DslIntCompositor.new(context, 3)
|
37
|
-
list =
|
37
|
+
list = ListCompositor.new(context,
|
38
38
|
root: :numbers,
|
39
39
|
collection: [1, 2, 3].map! { |n| DslIntCompositor.new(context, n) })
|
40
|
-
cmp =
|
40
|
+
cmp = MapCompositor.new(context, collection: [string, int, list])
|
41
41
|
cmp.to_hash.should == {:a => "b", :number => 3, :numbers => [{:number => 1}, {:number => 2}, {:number => 3}]}
|
42
42
|
end
|
43
43
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: compositor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Konstantin Gredeskoul
|
@@ -9,62 +9,62 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2014-02-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: oj
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- -
|
18
|
+
- - ">="
|
19
19
|
- !ruby/object:Gem::Version
|
20
20
|
version: '0'
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
|
-
- -
|
25
|
+
- - ">="
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: '0'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: rspec
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
|
-
- -
|
32
|
+
- - ">="
|
33
33
|
- !ruby/object:Gem::Version
|
34
34
|
version: '0'
|
35
35
|
type: :development
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
|
-
- -
|
39
|
+
- - ">="
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: '0'
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: guard-rspec
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
|
-
- -
|
46
|
+
- - ">="
|
47
47
|
- !ruby/object:Gem::Version
|
48
48
|
version: '0'
|
49
49
|
type: :development
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
|
-
- -
|
53
|
+
- - ">="
|
54
54
|
- !ruby/object:Gem::Version
|
55
55
|
version: '0'
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: rb-fsevent
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
59
59
|
requirements:
|
60
|
-
- -
|
60
|
+
- - ">="
|
61
61
|
- !ruby/object:Gem::Version
|
62
62
|
version: '0'
|
63
63
|
type: :development
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
|
-
- -
|
67
|
+
- - ">="
|
68
68
|
- !ruby/object:Gem::Version
|
69
69
|
version: '0'
|
70
70
|
description: Define simple "compositor" classes that represent your domain objects
|
@@ -77,10 +77,10 @@ executables: []
|
|
77
77
|
extensions: []
|
78
78
|
extra_rdoc_files: []
|
79
79
|
files:
|
80
|
-
- .gitignore
|
81
|
-
- .pairs
|
82
|
-
- .rspec
|
83
|
-
- .travis.yml
|
80
|
+
- ".gitignore"
|
81
|
+
- ".pairs"
|
82
|
+
- ".rspec"
|
83
|
+
- ".travis.yml"
|
84
84
|
- Gemfile
|
85
85
|
- Guardfile
|
86
86
|
- LICENSE
|
@@ -90,21 +90,21 @@ files:
|
|
90
90
|
- lib/compositor.rb
|
91
91
|
- lib/compositor/base.rb
|
92
92
|
- lib/compositor/composite.rb
|
93
|
+
- lib/compositor/compositors/list_compositor.rb
|
94
|
+
- lib/compositor/compositors/literal_compositor.rb
|
95
|
+
- lib/compositor/compositors/map_compositor.rb
|
93
96
|
- lib/compositor/dsl.rb
|
94
97
|
- lib/compositor/leaf.rb
|
95
|
-
- lib/compositor/list.rb
|
96
|
-
- lib/compositor/literal.rb
|
97
|
-
- lib/compositor/map.rb
|
98
98
|
- lib/compositor/renderer/base.rb
|
99
99
|
- lib/compositor/renderer/iterator.rb
|
100
100
|
- lib/compositor/renderer/merged.rb
|
101
101
|
- lib/compositor/version.rb
|
102
102
|
- spec/compositor/base_spec.rb
|
103
|
+
- spec/compositor/compositors/list_compositor_spec.rb
|
104
|
+
- spec/compositor/compositors/literal_compositor_spec.rb
|
105
|
+
- spec/compositor/compositors/map_compositor_spec.rb
|
103
106
|
- spec/compositor/dsl_spec.rb
|
104
|
-
- spec/compositor/hash_spec.rb
|
105
107
|
- spec/compositor/leaf_spec.rb
|
106
|
-
- spec/compositor/list_spec.rb
|
107
|
-
- spec/compositor/literal_spec.rb
|
108
108
|
- spec/compositor/performance_spec.rb
|
109
109
|
- spec/spec_helper.rb
|
110
110
|
- spec/support/sample_dsl.rb
|
@@ -118,28 +118,29 @@ require_paths:
|
|
118
118
|
- lib
|
119
119
|
required_ruby_version: !ruby/object:Gem::Requirement
|
120
120
|
requirements:
|
121
|
-
- -
|
121
|
+
- - ">="
|
122
122
|
- !ruby/object:Gem::Version
|
123
123
|
version: '0'
|
124
124
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
125
|
requirements:
|
126
|
-
- -
|
126
|
+
- - ">="
|
127
127
|
- !ruby/object:Gem::Version
|
128
128
|
version: '0'
|
129
129
|
requirements: []
|
130
130
|
rubyforge_project:
|
131
|
-
rubygems_version: 2.
|
131
|
+
rubygems_version: 2.2.0
|
132
132
|
signing_key:
|
133
133
|
specification_version: 4
|
134
134
|
summary: Composite design pattern with a convenient DSL for building JSON/Hashes of
|
135
135
|
complex objects.
|
136
136
|
test_files:
|
137
137
|
- spec/compositor/base_spec.rb
|
138
|
+
- spec/compositor/compositors/list_compositor_spec.rb
|
139
|
+
- spec/compositor/compositors/literal_compositor_spec.rb
|
140
|
+
- spec/compositor/compositors/map_compositor_spec.rb
|
138
141
|
- spec/compositor/dsl_spec.rb
|
139
|
-
- spec/compositor/hash_spec.rb
|
140
142
|
- spec/compositor/leaf_spec.rb
|
141
|
-
- spec/compositor/list_spec.rb
|
142
|
-
- spec/compositor/literal_spec.rb
|
143
143
|
- spec/compositor/performance_spec.rb
|
144
144
|
- spec/spec_helper.rb
|
145
145
|
- spec/support/sample_dsl.rb
|
146
|
+
has_rdoc:
|
data/lib/compositor/list.rb
DELETED
data/lib/compositor/literal.rb
DELETED