dekorator 1.0.0.pre.1 → 1.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/.github/workflows/test.yml +51 -0
- data/CHANGELOG.md +20 -4
- data/CODE_OF_CONDUCT.md +1 -1
- data/README.md +104 -38
- data/benchmarks/README.md +7 -0
- data/benchmarks/benchmark.rb +135 -0
- data/dekorator.gemspec +24 -11
- data/lib/dekorator.rb +67 -39
- data/lib/dekorator/rails/controller.rb +17 -0
- data/lib/dekorator/railtie.rb +9 -5
- data/lib/dekorator/version.rb +1 -1
- data/lib/generators/decorator_generator.rb +7 -0
- data/lib/generators/{decorator → dekorator/decorator}/USAGE +1 -1
- data/lib/generators/dekorator/decorator/decorator_generator.rb +17 -0
- data/lib/generators/{decorator → dekorator/decorator}/templates/decorator.rb +0 -0
- data/lib/generators/dekorator/{install_generator.rb → install/install_generator.rb} +8 -6
- data/lib/generators/rspec/decorator_generator.rb +2 -0
- data/lib/generators/test_unit/decorator_generator.rb +2 -0
- metadata +22 -36
- data/.editorconfig +0 -14
- data/.gitignore +0 -11
- data/.rspec +0 -3
- data/.rubocop.yml +0 -114
- data/.simplecov +0 -5
- data/.travis.yml +0 -37
- data/Appraisals +0 -17
- data/Gemfile +0 -22
- data/Gemfile.lock +0 -157
- data/bin/console +0 -16
- data/bin/setup +0 -8
- data/gemfiles/.bundle/config +0 -2
- data/gemfiles/rails_5.0.x.gemfile +0 -21
- data/gemfiles/rails_5.0.x.gemfile.lock +0 -207
- data/gemfiles/rails_5.1.x.gemfile +0 -21
- data/gemfiles/rails_5.1.x.gemfile.lock +0 -207
- data/gemfiles/rails_5.2.x.gemfile +0 -21
- data/gemfiles/rails_5.2.x.gemfile.lock +0 -207
- data/gemfiles/rails_6.0.x.gemfile +0 -21
- data/gemfiles/rails_6.0.x.gemfile.lock +0 -220
- data/lib/dekorator/decorators_helper.rb +0 -5
- data/lib/dekorator/rspec.rb +0 -0
- data/lib/generators/decorator/decorator_generator.rb +0 -11
- data/lib/generators/decorator/templates/decorator_test.rb +0 -1
data/dekorator.gemspec
CHANGED
@@ -1,23 +1,36 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
lib = File.expand_path("
|
3
|
+
lib = File.expand_path("lib", __dir__)
|
4
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
5
5
|
require "dekorator/version"
|
6
6
|
|
7
7
|
Gem::Specification.new do |spec|
|
8
|
-
spec.name
|
9
|
-
spec.version
|
10
|
-
spec.authors
|
11
|
-
spec.email
|
12
|
-
|
13
|
-
spec.summary
|
14
|
-
spec.description
|
15
|
-
spec.
|
8
|
+
spec.name = "dekorator"
|
9
|
+
spec.version = Dekorator::VERSION
|
10
|
+
spec.authors = ["Pantographe"]
|
11
|
+
spec.email = ["oss@pantographe.studio"]
|
12
|
+
|
13
|
+
spec.summary = "An opinionated way of organizing model-view code in Ruby on Rails, based on decorators"
|
14
|
+
spec.description = "An opinionated way of organizing model-view code in Ruby on Rails, based on decorators"
|
15
|
+
spec.homepage = "http://komponent.io"
|
16
|
+
spec.license = "MIT"
|
17
|
+
|
18
|
+
spec.metadata = {
|
19
|
+
"homepage_uri" => "https://github.com/komposable/dekorator",
|
20
|
+
"changelog_uri" => "https://github.com/komposable/dekorator/blob/master/CHANGELOG.md",
|
21
|
+
"source_code_uri" => "https://github.com/komposable/dekorator",
|
22
|
+
"bug_tracker_uri" => "https://github.com/komposable/dekorator/issues",
|
23
|
+
}
|
16
24
|
|
17
25
|
# Specify which files should be added to the gem when it is released.
|
18
26
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
19
|
-
spec.files
|
20
|
-
`git ls-files -z`.split("\x0")
|
27
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
28
|
+
`git ls-files -z`.split("\x0")
|
29
|
+
.reject do |f|
|
30
|
+
f.match(%r{^(test|spec|features|gemfiles|bin)/}) \
|
31
|
+
|| %w[.editorconfig .gitignore .inch.yml .rspec .rubocop.yml .simplecov .travis.yml
|
32
|
+
.yardots Appraisals Gemfile Gemfile.lock].include?(f)
|
33
|
+
end
|
21
34
|
end
|
22
35
|
|
23
36
|
spec.require_paths = ["lib"]
|
data/lib/dekorator.rb
CHANGED
@@ -1,10 +1,13 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "dekorator/version"
|
4
|
-
require "
|
5
|
-
require "active_support/core_ext/module/delegation"
|
4
|
+
require "delegate"
|
6
5
|
|
6
|
+
# :nodoc
|
7
7
|
module Dekorator
|
8
|
+
# @api private
|
9
|
+
module Generators; end
|
10
|
+
|
8
11
|
class DecoratorNotFound < ArgumentError; end
|
9
12
|
|
10
13
|
# Base decorator.
|
@@ -19,11 +22,10 @@ module Dekorator
|
|
19
22
|
#
|
20
23
|
# @raise [DecoratorNotFound] if decorator is not found.
|
21
24
|
def decorate(object_or_collection, with: nil)
|
22
|
-
return object_or_collection if object_or_collection
|
23
|
-
|
24
|
-
with = _guess_decorator(object_or_collection) if with.nil? && object_or_collection.present?
|
25
|
+
return object_or_collection if decorable_object?(object_or_collection)
|
25
26
|
|
26
|
-
|
27
|
+
with ||= self if with != :__guess__ && self != Dekorator::Base
|
28
|
+
with = _guess_decorator(object_or_collection) if with.nil? || with == :__guess__
|
27
29
|
|
28
30
|
object_or_collection = _decorate(object_or_collection, with: with)
|
29
31
|
|
@@ -40,82 +42,108 @@ module Dekorator
|
|
40
42
|
# @option opts [Class] :with the decorator class to use. If empty a decorator will be guessed.
|
41
43
|
#
|
42
44
|
# @example Define an association to decorate
|
43
|
-
# class UserDecorator <
|
45
|
+
# class UserDecorator < Dekorator::Base
|
44
46
|
# decorates_association :posts
|
45
47
|
# end
|
46
48
|
#
|
47
49
|
# # A decorator could be precise
|
48
|
-
# class UserDecorator <
|
50
|
+
# class UserDecorator < Dekorator::Base
|
49
51
|
# decorates_association :posts, PostDecorator
|
50
52
|
# end
|
51
|
-
def decorates_association(relation_name, with:
|
53
|
+
def decorates_association(relation_name, with: :__guess__)
|
52
54
|
relation_name = relation_name.to_sym
|
53
55
|
|
54
56
|
define_method(relation_name) do
|
55
|
-
|
56
|
-
|
57
|
-
@decorated_associations[relation_name] ||= decorate(association, with: with)
|
57
|
+
@decorated_associations[relation_name] ||= decorate(__getobj__.public_send(relation_name), with: with)
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
61
|
+
# Guess and returns the decorated object class.
|
62
|
+
#
|
63
|
+
# @return [Class] the decorated object class.
|
61
64
|
def base_class
|
62
|
-
name.gsub("Decorator", "")
|
65
|
+
_safe_constantize(name.gsub("Decorator", ""))
|
63
66
|
end
|
64
67
|
|
65
68
|
private
|
66
69
|
|
67
|
-
def _decorate(object_or_enumerable, with:
|
68
|
-
if
|
69
|
-
DecoratedEnumerableProxy.new(object_or_enumerable, with)
|
70
|
-
elsif object_or_enumerable.is_a? Enumerable
|
71
|
-
object_or_enumerable.map { |object| with.new(object) }
|
72
|
-
else
|
70
|
+
def _decorate(object_or_enumerable, with:)
|
71
|
+
if !object_or_enumerable.is_a? Enumerable
|
73
72
|
with.new(object_or_enumerable)
|
73
|
+
else
|
74
|
+
if defined?(ActiveRecord::Relation) && object_or_enumerable.is_a?(ActiveRecord::Relation)
|
75
|
+
Dekorator::DecoratedEnumerableProxy.new(with, object_or_enumerable)
|
76
|
+
else object_or_enumerable.is_a? Enumerable
|
77
|
+
object_or_enumerable.map { |object| _decorate(object, with: with) }
|
78
|
+
end
|
74
79
|
end
|
75
80
|
end
|
76
81
|
|
77
82
|
def _guess_decorator(object_or_enumerable)
|
78
83
|
object_or_enumerable = object_or_enumerable.first if object_or_enumerable.is_a? Enumerable
|
79
84
|
|
80
|
-
"#{object_or_enumerable.class}Decorator"
|
85
|
+
_safe_constantize("#{object_or_enumerable.class}Decorator") \
|
86
|
+
|| raise(DecoratorNotFound, "Can't guess decorator for #{object_or_enumerable.class.name} object")
|
81
87
|
end
|
82
|
-
end
|
83
88
|
|
84
|
-
|
89
|
+
def decorable_object?(object_or_collection)
|
90
|
+
(object_or_collection.respond_to?(:empty?) && object_or_collection.empty?) \
|
91
|
+
|| !object_or_collection \
|
92
|
+
|| object_or_collection.is_a?(Dekorator::Base) \
|
93
|
+
|| (defined?(ActiveRecord::Relation) && object_or_collection.is_a?(Dekorator::DecoratedEnumerableProxy))
|
94
|
+
end
|
85
95
|
|
96
|
+
def _safe_constantize(class_name)
|
97
|
+
Object.const_get(class_name)
|
98
|
+
rescue NameError => _e
|
99
|
+
nil
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# :nodoc
|
86
104
|
def initialize(object)
|
87
105
|
@decorated_associations = {}
|
88
106
|
|
89
107
|
super(object)
|
90
108
|
end
|
91
109
|
|
110
|
+
# :nodoc
|
111
|
+
def decorate(object_or_collection, with: :__guess__)
|
112
|
+
self.class.decorate(object_or_collection, with: with)
|
113
|
+
end
|
114
|
+
|
115
|
+
# Returns the decorated object.
|
116
|
+
#
|
117
|
+
# @return [Object] the decorated object.
|
92
118
|
def object
|
93
119
|
__getobj__
|
94
120
|
end
|
121
|
+
end
|
95
122
|
|
96
|
-
|
97
|
-
|
98
|
-
|
123
|
+
if defined?(ActiveRecord::Relation)
|
124
|
+
# DecoratedEnumerableProxy is strongly inspired from
|
125
|
+
# https://github.com/kiote/activeadmin-poro-decorator/blob/master/lib/activeadmin-poro-decorator.rb#L65
|
126
|
+
class DecoratedEnumerableProxy < DelegateClass(ActiveRecord::Relation)
|
127
|
+
include Enumerable
|
99
128
|
|
100
|
-
|
101
|
-
|
102
|
-
|
129
|
+
delegate :as_json, :collect, :map, :each, :[], :all?, :include?,
|
130
|
+
:first, :last, :shift, to: :decorated_collection
|
131
|
+
delegate :each, to: :to_ary
|
103
132
|
|
104
|
-
|
105
|
-
|
133
|
+
def initialize(decorator_class, collection)
|
134
|
+
super(collection)
|
106
135
|
|
107
|
-
|
108
|
-
|
136
|
+
@decorator_class = decorator_class
|
137
|
+
end
|
109
138
|
|
110
|
-
|
111
|
-
|
112
|
-
|
139
|
+
def wrapped_collection
|
140
|
+
__getobj__
|
141
|
+
end
|
113
142
|
|
114
|
-
|
115
|
-
|
116
|
-
end
|
117
|
-
alias to_ary decorated_collection
|
143
|
+
def decorated_collection
|
144
|
+
@decorated_collection ||= wrapped_collection.collect { |member| @decorator_class.new(member) }
|
118
145
|
end
|
146
|
+
alias to_ary decorated_collection
|
119
147
|
end
|
120
148
|
end
|
121
149
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/concern"
|
4
|
+
|
5
|
+
module Dekorator
|
6
|
+
module Controller
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
helper_method :decorate
|
11
|
+
end
|
12
|
+
|
13
|
+
def decorate(object_or_collection, with: nil)
|
14
|
+
Dekorator::Base.decorate(object_or_collection, with: with)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/dekorator/railtie.rb
CHANGED
@@ -1,11 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "dekorator/decorators_helper"
|
4
|
-
|
5
3
|
module Dekorator
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
require "dekorator/rails/controller"
|
5
|
+
|
6
|
+
class Railtie < ::Rails::Railtie
|
7
|
+
config.to_prepare do |_app|
|
8
|
+
ActionController::Base.include Dekorator::Controller
|
9
|
+
end
|
10
|
+
|
11
|
+
config.after_initialize do |app|
|
12
|
+
app.config.paths.add "app/decorators", eager_load: true
|
9
13
|
end
|
10
14
|
end
|
11
15
|
end
|
data/lib/dekorator/version.rb
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails/generators"
|
4
|
+
|
5
|
+
module Dekorator
|
6
|
+
module Generators
|
7
|
+
class DecoratorGenerator < ::Rails::Generators::NamedBase
|
8
|
+
source_root File.expand_path("templates", __dir__)
|
9
|
+
|
10
|
+
def create_decorator
|
11
|
+
template "decorator.rb", File.join("app/decorators", class_path, "#{file_name}_decorator.rb")
|
12
|
+
end
|
13
|
+
|
14
|
+
hook_for :test_framework
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
File without changes
|
@@ -1,18 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "rails/generators"
|
4
|
+
|
3
5
|
module Dekorator
|
4
6
|
module Generators
|
5
|
-
class InstallGenerator < Rails::Generators::Base
|
7
|
+
class InstallGenerator < ::Rails::Generators::Base
|
6
8
|
|
7
9
|
def create_root_directory
|
8
|
-
return if File.directory?(dekorator_root_directory)
|
9
|
-
|
10
10
|
empty_directory(dekorator_root_directory)
|
11
|
+
|
12
|
+
concerns_directory = dekorator_root_directory.join("concerns")
|
13
|
+
empty_directory(concerns_directory)
|
14
|
+
create_file("#{concerns_directory}/.keep")
|
11
15
|
end
|
12
16
|
|
13
17
|
def create_application_decorator
|
14
|
-
return if File.exist?(application_decorator_path)
|
15
|
-
|
16
18
|
create_file application_decorator_path, <<-RUBY
|
17
19
|
# frozen_string_literal: true
|
18
20
|
|
@@ -24,7 +26,7 @@ end
|
|
24
26
|
protected
|
25
27
|
|
26
28
|
def dekorator_root_directory
|
27
|
-
Rails.root.join("app
|
29
|
+
Rails.root.join("app/decorators")
|
28
30
|
end
|
29
31
|
|
30
32
|
def application_decorator_path
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dekorator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- Pantographe
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-12-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: actionview
|
@@ -115,55 +115,41 @@ dependencies:
|
|
115
115
|
description: An opinionated way of organizing model-view code in Ruby on Rails, based
|
116
116
|
on decorators
|
117
117
|
email:
|
118
|
-
-
|
118
|
+
- oss@pantographe.studio
|
119
119
|
executables: []
|
120
120
|
extensions: []
|
121
121
|
extra_rdoc_files: []
|
122
122
|
files:
|
123
|
-
- ".
|
124
|
-
- ".gitignore"
|
125
|
-
- ".rspec"
|
126
|
-
- ".rubocop.yml"
|
127
|
-
- ".simplecov"
|
128
|
-
- ".travis.yml"
|
129
|
-
- Appraisals
|
123
|
+
- ".github/workflows/test.yml"
|
130
124
|
- CHANGELOG.md
|
131
125
|
- CODE_OF_CONDUCT.md
|
132
|
-
- Gemfile
|
133
|
-
- Gemfile.lock
|
134
126
|
- LICENSE.txt
|
135
127
|
- README.md
|
136
128
|
- Rakefile
|
137
|
-
-
|
138
|
-
-
|
129
|
+
- benchmarks/README.md
|
130
|
+
- benchmarks/benchmark.rb
|
139
131
|
- dekorator.gemspec
|
140
|
-
- gemfiles/.bundle/config
|
141
|
-
- gemfiles/rails_5.0.x.gemfile
|
142
|
-
- gemfiles/rails_5.0.x.gemfile.lock
|
143
|
-
- gemfiles/rails_5.1.x.gemfile
|
144
|
-
- gemfiles/rails_5.1.x.gemfile.lock
|
145
|
-
- gemfiles/rails_5.2.x.gemfile
|
146
|
-
- gemfiles/rails_5.2.x.gemfile.lock
|
147
|
-
- gemfiles/rails_6.0.x.gemfile
|
148
|
-
- gemfiles/rails_6.0.x.gemfile.lock
|
149
132
|
- lib/dekorator.rb
|
150
|
-
- lib/dekorator/
|
133
|
+
- lib/dekorator/rails/controller.rb
|
151
134
|
- lib/dekorator/railtie.rb
|
152
|
-
- lib/dekorator/rspec.rb
|
153
135
|
- lib/dekorator/version.rb
|
154
|
-
- lib/generators/
|
155
|
-
- lib/generators/decorator/
|
156
|
-
- lib/generators/decorator/
|
157
|
-
- lib/generators/decorator/templates/
|
158
|
-
- lib/generators/dekorator/install_generator.rb
|
136
|
+
- lib/generators/decorator_generator.rb
|
137
|
+
- lib/generators/dekorator/decorator/USAGE
|
138
|
+
- lib/generators/dekorator/decorator/decorator_generator.rb
|
139
|
+
- lib/generators/dekorator/decorator/templates/decorator.rb
|
140
|
+
- lib/generators/dekorator/install/install_generator.rb
|
159
141
|
- lib/generators/rspec/decorator_generator.rb
|
160
142
|
- lib/generators/rspec/templates/decorator_spec.rb
|
161
143
|
- lib/generators/test_unit/decorator_generator.rb
|
162
144
|
- lib/generators/test_unit/templates/decorator_test.rb
|
163
|
-
homepage:
|
145
|
+
homepage: http://komponent.io
|
164
146
|
licenses:
|
165
147
|
- MIT
|
166
|
-
metadata:
|
148
|
+
metadata:
|
149
|
+
homepage_uri: https://github.com/komposable/dekorator
|
150
|
+
changelog_uri: https://github.com/komposable/dekorator/blob/master/CHANGELOG.md
|
151
|
+
source_code_uri: https://github.com/komposable/dekorator
|
152
|
+
bug_tracker_uri: https://github.com/komposable/dekorator/issues
|
167
153
|
post_install_message:
|
168
154
|
rdoc_options: []
|
169
155
|
require_paths:
|
@@ -175,11 +161,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
175
161
|
version: '2.3'
|
176
162
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
177
163
|
requirements:
|
178
|
-
- - "
|
164
|
+
- - ">="
|
179
165
|
- !ruby/object:Gem::Version
|
180
|
-
version:
|
166
|
+
version: '0'
|
181
167
|
requirements: []
|
182
|
-
rubygems_version: 3.0.
|
168
|
+
rubygems_version: 3.0.6
|
183
169
|
signing_key:
|
184
170
|
specification_version: 4
|
185
171
|
summary: An opinionated way of organizing model-view code in Ruby on Rails, based
|