composable_decorator 0.1.1 → 0.2.1
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 +18 -1
- data/composable_decorator.gemspec +6 -1
- data/lib/composable_decorator/active_record/base.rb +57 -0
- data/lib/composable_decorator/active_record/dsl.rb +57 -0
- data/lib/composable_decorator/version.rb +1 -1
- data/lib/composable_decorator.rb +4 -13
- metadata +51 -9
- data/lib/composable_decorator/dsl.rb +0 -54
- data/lib/composable_decorator/models.rb +0 -53
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d0fa65ef7eb8fc9f424b8995c47aaeec25cbff91
|
4
|
+
data.tar.gz: a7d9cd5bb1aec8857c5e93b69a990ad309e10a0a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b521e76e756b291fa352c617c72ff51ac3073c8fad20ad9c88fe41137c9377bc793f132ab817ed57282b0d789c6fa87f20827885c4fc041ac7eec750ba1df9b3
|
7
|
+
data.tar.gz: 0d3bedc34f1419b4c338041ef7a962fea86a85c56ce63262224313d8ecb6aa32b9b665a108fa0b40be0c457915be7d98c3dafd86ec140e9a2f4e0602057aae2c
|
data/README.md
CHANGED
@@ -75,6 +75,24 @@ end
|
|
75
75
|
@user.full_name
|
76
76
|
@user.full_phone_number
|
77
77
|
|
78
|
+
# decorators are inherited
|
79
|
+
#
|
80
|
+
#
|
81
|
+
module HatDecorator
|
82
|
+
def hat_decorated_method
|
83
|
+
"hat decorator method"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
class Hat < ActiveRecord::Base
|
88
|
+
decorate_with HatDecorator
|
89
|
+
end
|
90
|
+
|
91
|
+
class Stetson < Hat
|
92
|
+
end
|
93
|
+
|
94
|
+
Stetson.new.decorate.hat_decorator_method #=> "hat decorator method"
|
95
|
+
|
78
96
|
# DELEGATIONS
|
79
97
|
#
|
80
98
|
# We can delegate the association's decorated methods to the model
|
@@ -83,7 +101,6 @@ class Address < ActiveRecord::Base
|
|
83
101
|
end
|
84
102
|
|
85
103
|
class User
|
86
|
-
decorate_with Name, PhoneNumber
|
87
104
|
delegate_decorated_to :address
|
88
105
|
end
|
89
106
|
|
@@ -10,6 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.email = ["adamgsteel@gmail.com"]
|
11
11
|
|
12
12
|
spec.summary = %q{A simple, composable decorator pattern for Ruby.}
|
13
|
+
spec.description = %q{Supports decorator composition and inheritance in ActiveRecord.}
|
13
14
|
spec.homepage = "https://www.github.com/adsteel/composable_decorator"
|
14
15
|
spec.license = "MIT"
|
15
16
|
|
@@ -26,7 +27,11 @@ Gem::Specification.new do |spec|
|
|
26
27
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
27
28
|
spec.require_paths = ["lib"]
|
28
29
|
|
30
|
+
spec.add_dependency "rails", '~> 4.2'
|
31
|
+
|
29
32
|
spec.add_development_dependency "bundler", "~> 1.10"
|
33
|
+
spec.add_development_dependency "pry", "~> 0.10"
|
30
34
|
spec.add_development_dependency "rake", "~> 10.0"
|
31
|
-
spec.add_development_dependency "rspec"
|
35
|
+
spec.add_development_dependency "rspec", "~> 3"
|
36
|
+
spec.add_development_dependency "sqlite3", "~> 1.3"
|
32
37
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require_relative './dsl'
|
2
|
+
|
3
|
+
module ComposableDecorator
|
4
|
+
module ActiveRecord
|
5
|
+
module Base
|
6
|
+
def self.included(mod)
|
7
|
+
mod.extend DSL
|
8
|
+
|
9
|
+
mod.__define_delegation
|
10
|
+
end
|
11
|
+
|
12
|
+
def decorate
|
13
|
+
__add_decorators
|
14
|
+
__decorate_associations
|
15
|
+
__delegate_decorated_association_methods
|
16
|
+
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
private def __add_decorators
|
21
|
+
__decorators.each do |decorator|
|
22
|
+
extend(decorator)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private def __decorate_associations
|
27
|
+
__associations.each do |assoc|
|
28
|
+
public_send(assoc).try(:decorate)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private def __delegate_decorated_association_methods
|
33
|
+
__associations.each do |assoc|
|
34
|
+
methods = __decorator_methods(assoc)
|
35
|
+
|
36
|
+
self.class.delegate(
|
37
|
+
*methods,
|
38
|
+
to: assoc,
|
39
|
+
prefix: __prefix,
|
40
|
+
allow_nil: __allow_nil)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private def __decorators
|
45
|
+
self.class.__decorators
|
46
|
+
end
|
47
|
+
|
48
|
+
private def __decorator_methods(assoc)
|
49
|
+
__association_class(assoc).__decorators.map(&:instance_methods).flatten
|
50
|
+
end
|
51
|
+
|
52
|
+
private def __association_class(assoc)
|
53
|
+
self.class.reflect_on_association(assoc).klass
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module ComposableDecorator
|
2
|
+
module ActiveRecord
|
3
|
+
module DSL
|
4
|
+
# # declares the order of decorators applied to an instance
|
5
|
+
# # that calls the #decorate method
|
6
|
+
#
|
7
|
+
# class AdminUser
|
8
|
+
# decorate_with UserDecorator, AdminDecorator
|
9
|
+
#
|
10
|
+
# # The above code results in #decorate first decorating the instance
|
11
|
+
# # with the UserDecorator, then the AdminDecorator
|
12
|
+
#
|
13
|
+
# @Param +decorators+ is an <Array> of classes
|
14
|
+
def decorate_with(*decorators)
|
15
|
+
existing_decorators = defined?(__decorators) ? __decorators : []
|
16
|
+
|
17
|
+
define_singleton_method(:__decorators) { decorators + existing_decorators }
|
18
|
+
end
|
19
|
+
|
20
|
+
# # delegates all of the decorated methods for each has_one or belongs_to association.
|
21
|
+
#
|
22
|
+
# module PostDecorator
|
23
|
+
# delegate_decorated_to :author
|
24
|
+
#
|
25
|
+
# def full_name
|
26
|
+
# "#{name} {created_at}"
|
27
|
+
#
|
28
|
+
# class Post
|
29
|
+
# belongs_to :author
|
30
|
+
# decorate_with PostDecorator
|
31
|
+
#
|
32
|
+
# # The above code allows you to call:
|
33
|
+
#
|
34
|
+
# post.decorate
|
35
|
+
# post.author_full_name
|
36
|
+
#
|
37
|
+
# # Like Rails's #delegate method, you can choose to allow_nil
|
38
|
+
# # or to prefix the delegated method. Both default to true.
|
39
|
+
#
|
40
|
+
# @Param +associations+ is an <Array> of symbols
|
41
|
+
def delegate_decorated_to(*associations, prefix: true, allow_nil: true, handle_nil_with: '')
|
42
|
+
__define_delegation(
|
43
|
+
associations: associations,
|
44
|
+
prefix: prefix,
|
45
|
+
allow_nil: allow_nil,
|
46
|
+
handle_nil_with: handle_nil_with)
|
47
|
+
end
|
48
|
+
|
49
|
+
def __define_delegation(associations: [], prefix: true, allow_nil: true, handle_nil_with: '')
|
50
|
+
define_method(:__associations) { associations }
|
51
|
+
define_method(:__prefix) { prefix }
|
52
|
+
define_method(:__allow_nil) { allow_nil }
|
53
|
+
define_method(:__handle_nil_with) { handle_nil_with }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/composable_decorator.rb
CHANGED
@@ -1,14 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
module ComposableDecorator
|
6
|
-
end
|
7
|
-
|
8
|
-
module ActiveRecord
|
9
|
-
class Base
|
10
|
-
extend ComposableDecorator::DSL
|
11
|
-
include ComposableDecorator::Models
|
12
|
-
end
|
13
|
-
end
|
1
|
+
require 'composable_decorator/version'
|
2
|
+
require 'composable_decorator/active_record/base'
|
3
|
+
require 'active_record'
|
14
4
|
|
5
|
+
ActiveRecord::Base.include ComposableDecorator::ActiveRecord::Base
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: composable_decorator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Steel
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-12-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.2'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: bundler
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -24,6 +38,20 @@ dependencies:
|
|
24
38
|
- - "~>"
|
25
39
|
- !ruby/object:Gem::Version
|
26
40
|
version: '1.10'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.10'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.10'
|
27
55
|
- !ruby/object:Gem::Dependency
|
28
56
|
name: rake
|
29
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -42,17 +70,31 @@ dependencies:
|
|
42
70
|
name: rspec
|
43
71
|
requirement: !ruby/object:Gem::Requirement
|
44
72
|
requirements:
|
45
|
-
- - "
|
73
|
+
- - "~>"
|
46
74
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
75
|
+
version: '3'
|
48
76
|
type: :development
|
49
77
|
prerelease: false
|
50
78
|
version_requirements: !ruby/object:Gem::Requirement
|
51
79
|
requirements:
|
52
|
-
- - "
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: sqlite3
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.3'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
53
95
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
55
|
-
description:
|
96
|
+
version: '1.3'
|
97
|
+
description: Supports decorator composition and inheritance in ActiveRecord.
|
56
98
|
email:
|
57
99
|
- adamgsteel@gmail.com
|
58
100
|
executables: []
|
@@ -71,8 +113,8 @@ files:
|
|
71
113
|
- bin/setup
|
72
114
|
- composable_decorator.gemspec
|
73
115
|
- lib/composable_decorator.rb
|
74
|
-
- lib/composable_decorator/
|
75
|
-
- lib/composable_decorator/
|
116
|
+
- lib/composable_decorator/active_record/base.rb
|
117
|
+
- lib/composable_decorator/active_record/dsl.rb
|
76
118
|
- lib/composable_decorator/version.rb
|
77
119
|
homepage: https://www.github.com/adsteel/composable_decorator
|
78
120
|
licenses:
|
@@ -1,54 +0,0 @@
|
|
1
|
-
module ComposableDecorator
|
2
|
-
module DSL
|
3
|
-
# # declares the order of decorators applied to an instance
|
4
|
-
# # that calls the #decorate method
|
5
|
-
#
|
6
|
-
# class AdminUser
|
7
|
-
# decorate_with UserDecorator, AdminDecorator
|
8
|
-
#
|
9
|
-
# # The above code results in #decorate first decorating the instance
|
10
|
-
# # with the UserDecorator, then the AdminDecorator
|
11
|
-
#
|
12
|
-
# @Param +decorators+ is an <Array> of classes
|
13
|
-
def decorate_with(*decorators)
|
14
|
-
define_method(:decorators) { decorators }
|
15
|
-
end
|
16
|
-
|
17
|
-
# # delegates all of the decorated methods for each association.
|
18
|
-
#
|
19
|
-
# module PostDecorator
|
20
|
-
# def full_name
|
21
|
-
# "#{name} {created_at}"
|
22
|
-
#
|
23
|
-
# class Post
|
24
|
-
# decorate_with PostDecorator
|
25
|
-
#
|
26
|
-
# class Author
|
27
|
-
# has_many :posts
|
28
|
-
# delegate_decorated_to :posts
|
29
|
-
#
|
30
|
-
# # The above code allows you to call:
|
31
|
-
#
|
32
|
-
# author.decorate
|
33
|
-
# author.post_full_name
|
34
|
-
#
|
35
|
-
# # Like Rails's #delegate method, you can choose to allow_nil
|
36
|
-
# # or to prefix the delegated method. Both default to true.
|
37
|
-
#
|
38
|
-
# @Param +associations+ is an <Array> of symbols
|
39
|
-
def delegate_decorated_to(*associations, prefix: true, allow_nil: true, handle_nil_with: '')
|
40
|
-
define_delegate_decorated_methods(
|
41
|
-
associations: associations,
|
42
|
-
prefix: prefix,
|
43
|
-
allow_nil: allow_nil,
|
44
|
-
handle_nil_with: handle_nil_with)
|
45
|
-
end
|
46
|
-
|
47
|
-
def define_delegate_decorated_methods(associations: [], prefix: true, allow_nil: true, handle_nil_with: '')
|
48
|
-
define_method(:delegate_decorated_associations) { associations }
|
49
|
-
define_method(:delegate_decorated_prefix) { prefix }
|
50
|
-
define_method(:delegate_decorated_allow_nil) { allow_nil }
|
51
|
-
define_method(:delegate_decorated_handle_nil_with) { handle_nil_with }
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
module ComposableDecorator
|
2
|
-
module Models
|
3
|
-
def self.included(base)
|
4
|
-
base.extend DSL
|
5
|
-
|
6
|
-
base.define_delegate_decorated_methods
|
7
|
-
end
|
8
|
-
|
9
|
-
def decorate
|
10
|
-
add_decorators
|
11
|
-
decorate_associations
|
12
|
-
delegate_decorated_association_methods
|
13
|
-
|
14
|
-
self
|
15
|
-
end
|
16
|
-
|
17
|
-
private def add_decorators
|
18
|
-
decorators.each do |decorator|
|
19
|
-
extend(decorator)
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
private def decorate_associations
|
24
|
-
method_delegate_decorated_associations.each do |assoc|
|
25
|
-
public_send(assoc).try(:decorate)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
private def delegate_decorated_association_methods
|
30
|
-
class_delegate_decorated_associations.each do |klass|
|
31
|
-
methods = class_decorated_methods(klass)
|
32
|
-
|
33
|
-
self.class.delegate(
|
34
|
-
*methods,
|
35
|
-
to: klass.to_s.underscore,
|
36
|
-
prefix: delegate_decorated_prefix,
|
37
|
-
allow_nil: delegate_decorated_allow_nil)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
private def class_decorated_methods(klass)
|
42
|
-
klass.new.decorators.map(&:instance_methods).flatten
|
43
|
-
end
|
44
|
-
|
45
|
-
private def class_delegate_decorated_associations
|
46
|
-
delegate_decorated_associations.map { |a| a.to_s.camelize.constantize }
|
47
|
-
end
|
48
|
-
|
49
|
-
private def method_delegate_decorated_associations
|
50
|
-
delegate_decorated_associations
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|