compositor 1.0.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3a5579d42c800d76ab62fe943c825237b216cf84
4
- data.tar.gz: c74728ad5a2cbb902926c7b7a18d2931a91dae3c
3
+ metadata.gz: 39aa83a1dbde3279e06295e7a5ce005444812d92
4
+ data.tar.gz: b36f918486e1adcd5daa2da24676b96a2fac0d26
5
5
  SHA512:
6
- metadata.gz: 39e18ac43d15623e0c3bdca5b6e6eb82960e99d6f1e5b1cac8786f0df97a7c4d1f5f2b7ae821dc2eb2ca6a97dde7203587923a1e457ab9915229fcc3860cd185
7
- data.tar.gz: 550e32aa5840d1e228d2bab660a0e3fc725219f0e4984275319073106af1a6517fd15bc3e9c4e0db40131dc6fef5dc7cbb648876ff5e43deacefd57f331e3490
6
+ metadata.gz: c878fb457203fdd022a49e991d2dee76ac18bb068b7811a196e03e81222a23b73304740efac40a45c6b632561b639a5b04367481841a9419f0e8a4368f050373
7
+ data.tar.gz: e6850ec7f0c0fd5a0b4c4eab1eb5ad2a69873db8afefd93ffde011b43c61e7f705251df25deb1957f230a493e0551d6e1f601ea434ab611ad757855c34601ca1
data/README.md CHANGED
@@ -3,6 +3,7 @@ Compositor
3
3
 
4
4
  [![Gem Version](https://badge.fury.io/rb/compositor.png)](http://badge.fury.io/rb/compositor)
5
5
  [![Build status](https://secure.travis-ci.org/wanelo/compositor.png)](http://travis-ci.org/wanelo/compositor)
6
+ [![Code Climate](https://codeclimate.com/github/wanelo/compositor.png)](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 = Compositor::Map.new(view_context,
87
- :collection => @users.map{|user| UserCompositor.new(view_context, user, { :root => true }),
88
- :root => :users
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 ```Compositor::Map``` and ```Compositor::List``` we can construct multiple objects into a larger
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()``` method, registered by ProductCompositor.
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 Name Collisions in the DSL
180
+ ### Method Names in the DSL
178
181
 
179
- Because DSL uses only the last word of the class name (eg, ```user``` for a class named ```MyModule::UserCompositor```),
180
- there is a possibility of name collisions. In order to prevent that, Compositor will detect if a DSL method is already
181
- defined and throw exception if another class tries to redefine it.
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```.
@@ -1,5 +1,6 @@
1
1
  module Compositor
2
- class MethodAlreadyDefinedError < RuntimeError; end
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 root_class_name
37
- self.class.root_class_name(self.class)
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 = root_class_name(subclass)
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 'literal'
69
- require_relative 'list'
70
- require_relative 'map'
65
+ require_relative 'compositors/literal_compositor'
66
+ require_relative 'compositors/list_compositor'
67
+ require_relative 'compositors/map_compositor'
@@ -0,0 +1,5 @@
1
+ class ListCompositor < Compositor::Composite
2
+ def renderer
3
+ @renderer ||= Compositor::Renderer::Iterator
4
+ end
5
+ end
@@ -0,0 +1,12 @@
1
+ class LiteralCompositor < Compositor::Leaf
2
+ attr_accessor :object
3
+
4
+ def initialize(view_context, object = {}, args = {})
5
+ super(view_context, args)
6
+ self.object = object
7
+ end
8
+
9
+ def to_hash
10
+ object
11
+ end
12
+ end
@@ -0,0 +1,5 @@
1
+ class MapCompositor < ::Compositor::Composite
2
+ def renderer
3
+ @renderer ||= Compositor::Renderer::Merged
4
+ end
5
+ end
@@ -1,3 +1,3 @@
1
1
  module Compositor
2
- VERSION = "1.0.1"
2
+ VERSION = "2.0.0"
3
3
  end
@@ -1,28 +1,22 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Compositor::Base do
4
- describe "#root_class_name" do
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
- Compositor::Base.root_class_name(DslStringCompositor).should == "dsl_string"
6
+ DslStringCompositor.original_dsl_name.should == "dsl_string"
11
7
  end
8
+ end
12
9
 
13
- it "raises exception when two subclasses that clash on the same name are defined" do
14
- block = lambda {
15
- # first class
16
- class UserCompositor < Compositor::Leaf
17
- end
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
- expect { block.call }.to raise_error
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,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Compositor::List do
3
+ describe ListCompositor do
4
4
  let(:context) { Object.new }
5
5
 
6
6
  it 'returns the generated array with the explicit receiver' do
@@ -1,12 +1,12 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Compositor::Literal do
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
- Compositor::Literal.new(context, actual).to_hash.should == actual
10
+ LiteralCompositor.new(context, actual).to_hash.should == actual
11
11
  end
12
12
  end
@@ -1,6 +1,6 @@
1
1
  require 'spec_helper'
2
2
 
3
- describe Compositor::Map do
3
+ describe MapCompositor do
4
4
  let(:context) { Object.new }
5
5
 
6
6
  it 'returns the generated map' do
@@ -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 = Compositor::List.new(context,
37
+ list = ListCompositor.new(context,
38
38
  root: :numbers,
39
39
  collection: [1, 2, 3].map! { |n| DslIntCompositor.new(context, n) })
40
- cmp = Compositor::Map.new(context, collection: [string, int, list])
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: 1.0.1
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: 2013-11-21 00:00:00.000000000 Z
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.1.11
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:
@@ -1,7 +0,0 @@
1
- module Compositor
2
- class List < Compositor::Composite
3
- def renderer
4
- @renderer ||= Compositor::Renderer::Iterator
5
- end
6
- end
7
- end
@@ -1,14 +0,0 @@
1
- module Compositor
2
- class Literal < Compositor::Leaf
3
- attr_accessor :object
4
-
5
- def initialize(view_context, object = {}, args = {})
6
- super(view_context, args)
7
- self.object = object
8
- end
9
-
10
- def to_hash
11
- object
12
- end
13
- end
14
- end
@@ -1,7 +0,0 @@
1
- module Compositor
2
- class Map < ::Compositor::Composite
3
- def renderer
4
- @renderer ||= Compositor::Renderer::Merged
5
- end
6
- end
7
- end