easy_decorator 0.1.0 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2a51c2c2a637daadfba8be3453ec7af886c5f484c2ec62a065bcc423f6f4d21c
4
- data.tar.gz: e747a3b3b141dc49e69da1a7efba88e4752e1c06540037cbda78ebb830199f35
3
+ metadata.gz: 9712b4b6313e508e2cff7302f664f5d96fa0bc9e073b82ba6bfb3ec026831e61
4
+ data.tar.gz: 9afdeb38a1b34ab102a571f9514ec8167718aadfddd68f8ffd0993c388227c30
5
5
  SHA512:
6
- metadata.gz: 0c1b39ac4a156d3ad49d04cbcf494394bcd3f7dbd881c98bc445c30bd3eaccc478c264b2e399ec76eab33bd187d786a437a96c7d9b73cffe8921bcc20795e0f1
7
- data.tar.gz: 90904664433a98ff9a275ad5bc1c9beb8ea58cdab973dd3e6da0f80a5b08bf30bb8624752f17e1154ef7f37540941656cff78be4d15ab7fe43d58daab6e89082
6
+ metadata.gz: 3fd37f90cdda492cd0e17c84d33f6c5c47748ace2e4afbc952129efc37909c82001e34f7e0e47d2a015a19d370626ef361bdd8526c406cd3f46cae5e7e8cb267
7
+ data.tar.gz: b0e246be3a9ea5ed7fc80d547aa30aa9ff28a55fdb3d1e11212c6bb5d85f9bd0cfd7e73277e94e0cf11e919cba79e05a78fe03875331d21a6e30338c8e362d62
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/README.md CHANGED
@@ -1,2 +1,114 @@
1
- # easy_decorator
2
- Python-like decorator pattern implemented in Ruby.
1
+ # EasyDecorator
2
+
3
+ EasyDecorator is a module that bring's in a Python-like method decorator pattern into Ruby.
4
+
5
+ # Table of Contents
6
+
7
+ * [Installation](#installation)
8
+ * [Usage](#usage)
9
+ * [Include Module](#include-module)
10
+ * [Define Decorator](#define-decorator)
11
+ * [Decorating Methods](#decorating-methods)
12
+ * [Example](#example)
13
+ * [Contributing](#contributing)
14
+
15
+ # Installation
16
+ ### command line
17
+ `$ gem install easy_decorator`
18
+
19
+ ### Gemfile
20
+ ```ruby
21
+ # ./Gemfile
22
+
23
+ source 'https://rubygems.org`
24
+ # ...
25
+ gem 'easy_decorator', '~> 0.2.0'
26
+ ```
27
+ # Usage
28
+ ### Include Module
29
+ ```ruby
30
+ # ./my_class.rb
31
+ class MyClass
32
+ include EasyDecorator
33
+ end
34
+ ```
35
+ ### Define Decorator
36
+ A decorator should be defined as a method with an inner wrapper. Within the wrapper you can call the passed method via `func.call(*args)`.
37
+
38
+ ```ruby
39
+ def my_decorator(func, *args)
40
+ wrapper do
41
+ # code here
42
+ func.call(*args)
43
+ # code here
44
+ end
45
+ end
46
+ ```
47
+ \* `wrapper` is essentially syntactic sugar for a proc.
48
+
49
+ ### Decorating Methods
50
+ ```ruby
51
+ decorate(:my_method, :my_decorator)
52
+ def my_method(a, b)
53
+ # code here
54
+ end
55
+ ```
56
+ You can apply multiple decorators to a method, which will applies from last to first declared.
57
+
58
+ ```ruby
59
+ decorate(:my_method, :outer_decorator)
60
+ decorate(:my_method, :inner_decorator)
61
+ def my_method(*args)
62
+ # ...
63
+ end
64
+
65
+ # is essentially the same as:
66
+ outer_decorator(inner_decorator(public_method(:my_method))).call(*args)
67
+ ```
68
+
69
+ ### Example
70
+ ```ruby
71
+ # ./calculator.rb
72
+
73
+ class Calculator
74
+ # include module
75
+ include EasyDecorator
76
+
77
+ # define decorator
78
+ def calculate_time(func, *args)
79
+ wrap do
80
+ logger.info("Timing #{method_name}...")
81
+ start_time = Time.now
82
+ # call inner method
83
+ result = func.call(*args)
84
+ end_time = Time.now
85
+ logger.info("Processing Time: #{end_time - start_time}")
86
+
87
+ result
88
+ end
89
+ end
90
+
91
+ # decorate method
92
+ decorate(:add_numbers, :calculate_time)
93
+ def add_numbers(a, b)
94
+ return a + b
95
+ end
96
+ end
97
+ ```
98
+ Result:
99
+ ```
100
+ $ Calculator.new.add_numbers(1,2)
101
+ Timing add_numbers...
102
+ Processing Time: 0.0001572930
103
+ => 3
104
+ ```
105
+
106
+ # Contributing
107
+ 1. Fork the repo
108
+ 2. Create a your feature branch (`git checkout -b my-feature-branch`)
109
+ 3. Update CHANGELOG.md with a bulleted list of your changes under the `unreleased` heading.
110
+ 4. Include rspec tests for your changes
111
+ 5. Commit your changes to your branch (`git commit -am 'Added my feature'`)
112
+ 6. Push to your remote forked repo (`git push origin my-featuer-branch`)
113
+ 7. Create a new Pull Request
114
+ Once I am able to review the pull request, I will either either approve and merge, or give feedback on it if I do not merge it. I will do my best to address Pull Requests as time allows.
@@ -0,0 +1,3 @@
1
+ # Module for decorator helpers and utilities
2
+ module Decorators
3
+ end
@@ -4,28 +4,35 @@ module EasyDecorator
4
4
  def self.included(base_klass)
5
5
  base_klass.extend(ClassMethods)
6
6
  base_klass.instance_variable_set(:@decorated_methods, {})
7
+ base_klass.define_method :wrapper do |&block|
8
+ block
9
+ end
7
10
  end
8
11
 
9
12
  module ClassMethods
10
- def decorate(decorator, decorated)
11
- @decorated_methods[decorated] = {
12
- decorator: decorator,
13
- is_decorated: false
14
- }
13
+ def decorate(decorated, decorator)
14
+ @decorated_methods[decorated] ||= { method_chain: [], is_decorated: false }
15
+ @decorated_methods[decorated][:method_chain] << decorator
15
16
  end
16
17
 
17
18
  def method_added(method_name)
18
19
  decorator = @decorated_methods[method_name]
20
+
19
21
  if decorator && !decorator[:is_decorated]
20
22
  decorator[:is_decorated] = true
23
+
21
24
  source_method_name = "source_#{method_name}".to_sym
22
25
  alias_method source_method_name, method_name
26
+ decorator[:method_chain] << source_method_name
23
27
 
24
28
  define_method method_name do |*args|
25
- send(decorator[:decorator], source_method_name, *args)
29
+ decorator[:method_chain].then { |*funcs, base_func|
30
+ funcs.reduce(public_method(base_func)) { |acc, func|
31
+ public_method(func).call(acc, *args)
32
+ }
33
+ }.call(*args)
26
34
  end
27
35
  end
28
36
  end
29
37
  end
30
38
  end
31
-
@@ -0,0 +1,3 @@
1
+ module EasyDecorator
2
+ class Error < StandardError; end
3
+ end
@@ -0,0 +1,3 @@
1
+ module EasyDecorator
2
+ VERSION = '0.2.0'
3
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: easy_decorator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Crank
@@ -45,10 +45,14 @@ extensions: []
45
45
  extra_rdoc_files: []
46
46
  files:
47
47
  - ".gitignore"
48
+ - Gemfile
48
49
  - LICENSE
49
50
  - README.md
50
51
  - easy_decorator.gemspec
52
+ - lib/decorators/decorators.rb
51
53
  - lib/easy_decorator.rb
54
+ - lib/easy_decorator/errors.rb
55
+ - lib/easy_decorator/version.rb
52
56
  homepage: https://github.com/jtcrank/easy_decorator
53
57
  licenses:
54
58
  - MIT