composable_decorator 0.0.0 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +73 -9
- data/lib/composable_decorator/version.rb +1 -1
- data/lib/composable_decorator.rb +10 -99
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bd64fc6e7e0eb6eb8ade1ec99a2bad446c873674
|
4
|
+
data.tar.gz: b6def650c067d09960452e9c85d03bf2776905c9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6fef48689f211503b63b9ae06d81d18ee2a42068c3f850f00033792a5bb98c4fc5da3b586a0b633f68e35552a5173000eb720339d9d65c9a4de54985d4dc7fa5
|
7
|
+
data.tar.gz: ca5b1ddd0df506f203068d2b221a9cfad409153c19e021bae32f962b9960d5dd484b4af7fb212753c6a82a78e10c110c699efa9c8514d479e9bc924446d5e776
|
data/README.md
CHANGED
@@ -1,9 +1,14 @@
|
|
1
1
|
# ComposableDecorator
|
2
2
|
|
3
|
-
-- work in progress. I would not rely on this gem yet. --
|
4
|
-
|
5
3
|
A simple, composable decorator for Rails models.
|
6
4
|
|
5
|
+
## Example
|
6
|
+
```ruby
|
7
|
+
class User < ActiveRecord::Base
|
8
|
+
decorate_with NameDecorator, PhoneNumberDecorator
|
9
|
+
end
|
10
|
+
```
|
11
|
+
|
7
12
|
## Installation
|
8
13
|
|
9
14
|
Add this line to your application's Gemfile:
|
@@ -22,13 +27,72 @@ Or install it yourself as:
|
|
22
27
|
|
23
28
|
## Usage
|
24
29
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
30
|
+
```ruby
|
31
|
+
# Decorators are declared in the /decorators folder
|
32
|
+
#
|
33
|
+
# app/decorators/name.rb
|
34
|
+
module Name
|
35
|
+
def full_name
|
36
|
+
"#{first_Name} #{last_name}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
module PhoneNumber
|
41
|
+
def full_phone_number
|
42
|
+
"(#{area_code}) #{phone_number}"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# a #decorate method is declared in the model, that lists the order of decorators
|
47
|
+
# to be called on the instance. The name of this method must be the same across
|
48
|
+
# multiple models in order to decorate the AR relationships
|
49
|
+
#
|
50
|
+
# /app/models/user.rb
|
51
|
+
class User < ActiveRecord::Base
|
52
|
+
decorate_with Name, PhoneNumber
|
53
|
+
end
|
54
|
+
|
55
|
+
# this is roughly the equivalent of wrapping the instance in first the Name decorator,
|
56
|
+
# then the PhoneNumber decorator, i.e.
|
57
|
+
class User < ActiveRecord::Base
|
58
|
+
extend Name
|
59
|
+
extend PhoneNumber
|
60
|
+
# more functionality runs here to work with AR relationships
|
61
|
+
end
|
62
|
+
|
63
|
+
# we can then decorate the model in the controller
|
64
|
+
#
|
65
|
+
# /app/controllers/users_controller.rb
|
66
|
+
class UsersController
|
67
|
+
def show
|
68
|
+
...
|
69
|
+
@user.decorate
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# and we can access the decorated methods in the view
|
74
|
+
#
|
75
|
+
# /app/views/users/show.html.slim
|
76
|
+
@user.full_name
|
77
|
+
@user.full_phone_number
|
78
|
+
|
79
|
+
# DELEGATIONS
|
80
|
+
#
|
81
|
+
# We can delegate the association's decorated methods to the model
|
82
|
+
class Address < ActiveRecord::Base
|
83
|
+
decorate_with AddressDecorator
|
84
|
+
end
|
85
|
+
|
86
|
+
class User
|
87
|
+
decorate_with Name, PhoneNumber
|
88
|
+
delegate_decorated_to :address
|
89
|
+
end
|
90
|
+
|
91
|
+
# which delegates all the decorated methods created in Address#decorate to User
|
92
|
+
#
|
93
|
+
# /app/views/users/show.html.slim
|
94
|
+
@user.address_simple_format
|
95
|
+
```
|
32
96
|
|
33
97
|
## Contributing
|
34
98
|
|
data/lib/composable_decorator.rb
CHANGED
@@ -1,106 +1,17 @@
|
|
1
1
|
require_relative "./composable_decorator/version"
|
2
|
+
require_relative './composable_decorator/class_methods'
|
3
|
+
require_relative './composable_decorator/instance_methods'
|
2
4
|
|
3
5
|
module ComposableDecorator
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
#
|
8
|
-
# class AdminUser
|
9
|
-
# decorate_with UserDecorator, AdminDecorator
|
10
|
-
#
|
11
|
-
# # The above code results in #decorate first decorating the instance
|
12
|
-
# # with the UserDecorator, then the AdminDecorator
|
13
|
-
#
|
14
|
-
# @Param +decorators+ is an <Array> of classes
|
15
|
-
def decorate_with(*decorators)
|
16
|
-
define_method(:decorators) { decorators }
|
17
|
-
end
|
18
|
-
|
19
|
-
# # delegates all of the decorated methods for each association.
|
20
|
-
#
|
21
|
-
# module PostDecorator
|
22
|
-
# def full_name
|
23
|
-
# "#{name} {created_at}"
|
24
|
-
#
|
25
|
-
# class Post
|
26
|
-
# decorate_with PostDecorator
|
27
|
-
#
|
28
|
-
# class Author
|
29
|
-
# has_many :posts
|
30
|
-
# delegate_decorated_to :posts
|
31
|
-
#
|
32
|
-
# # The above code allows you to call:
|
33
|
-
#
|
34
|
-
# author.decorate
|
35
|
-
# author.post_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_delegate_decorated_methods(
|
43
|
-
associations: associations,
|
44
|
-
prefix: prefix,
|
45
|
-
allow_nil: allow_nil,
|
46
|
-
handle_nil_with: handle_nil_with)
|
47
|
-
end
|
48
|
-
|
49
|
-
def define_delegate_decorated_methods(associations: [], prefix: true, allow_nil: true, handle_nil_with: '')
|
50
|
-
define_method(:delegate_decorated_associations) { associations }
|
51
|
-
define_method(:delegate_decorated_prefix) { prefix }
|
52
|
-
define_method(:delegate_decorated_allow_nil) { allow_nil }
|
53
|
-
define_method(:delegate_decorated_handle_nil_with) { handle_nil_with }
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.included(base)
|
58
|
-
base.extend ClassMethods
|
59
|
-
|
60
|
-
base.define_delegate_decorated_methods
|
61
|
-
end
|
62
|
-
|
63
|
-
def decorate
|
64
|
-
add_decorators
|
65
|
-
decorate_associations
|
66
|
-
delegate_decorated_association_methods
|
67
|
-
|
68
|
-
self
|
69
|
-
end
|
70
|
-
|
71
|
-
private def add_decorators
|
72
|
-
decorators.each do |decorator|
|
73
|
-
extend(decorator)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
private def decorate_associations
|
78
|
-
method_delegate_decorated_associations.each do |assoc|
|
79
|
-
public_send(assoc).try(:decorate)
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
private def delegate_decorated_association_methods
|
84
|
-
class_delegate_decorated_associations.each do |klass|
|
85
|
-
methods = class_decorated_methods(klass)
|
86
|
-
|
87
|
-
self.class.delegate(
|
88
|
-
*methods,
|
89
|
-
to: klass.to_s.underscore,
|
90
|
-
prefix: delegate_decorated_prefix,
|
91
|
-
allow_nil: delegate_decorated_allow_nil)
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
private def class_decorated_methods(klass)
|
96
|
-
klass.new.decorators.map(&:instance_methods).flatten
|
97
|
-
end
|
98
|
-
|
99
|
-
private def class_delegate_decorated_associations
|
100
|
-
delegate_decorated_associations.map { |a| a.to_s.camelize.constantize }
|
6
|
+
def self.included(mod)
|
7
|
+
mod.extend ClassMethods
|
8
|
+
mod.include InstanceMethods
|
101
9
|
end
|
10
|
+
end
|
102
11
|
|
103
|
-
|
104
|
-
|
12
|
+
module ActiveRecord
|
13
|
+
class Base
|
14
|
+
include ComposableDecorator
|
105
15
|
end
|
106
16
|
end
|
17
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: composable_decorator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.0
|
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-
|
11
|
+
date: 2015-11-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -92,7 +92,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
92
92
|
version: '0'
|
93
93
|
requirements: []
|
94
94
|
rubyforge_project:
|
95
|
-
rubygems_version: 2.
|
95
|
+
rubygems_version: 2.5.0
|
96
96
|
signing_key:
|
97
97
|
specification_version: 4
|
98
98
|
summary: A simple, composable decorator pattern for Ruby.
|