method_decorator.rb 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 559bd0649a3e4219ad6ad1782d517a0452cb0fe51a3ccb7f65fdc8578d94ef9d
4
+ data.tar.gz: 441faacb41756a39fffbf9f3d53e18eb86d8139730c7da45859f7e521772476d
5
+ SHA512:
6
+ metadata.gz: 538be9989bfbabde4d8a852de4d63c7621b689b5c34b2e0799d3627eacd3376eed278428e5a77606507dda3f0b8b1c243a87c2e5772105f1f75b3c831b556a8c
7
+ data.tar.gz: baa3b765012839d5d8ee9f6ec11fc983b1066fde8ebeed5a6b0731066e9eccf5c58b5e42cd6374db001902f0b70707bd2b73a97490b09486b78094fbcb92b68e
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ sandbox/
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ gemspec
@@ -0,0 +1,22 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ method-decorator (0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ minitest (5.13.0)
10
+ rake (10.5.0)
11
+
12
+ PLATFORMS
13
+ ruby
14
+
15
+ DEPENDENCIES
16
+ bundler (~> 1.17)
17
+ method-decorator!
18
+ minitest (~> 5.0)
19
+ rake (~> 10.0)
20
+
21
+ BUNDLED WITH
22
+ 1.17.3
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2019 Isty001
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,83 @@
1
+ # MethodDecorator
2
+
3
+ Method decorator implementation for Ruby, similar to Python.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'method-decorator'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install method-decorator
20
+
21
+ ## Usage and Examples
22
+
23
+ Decorators can be used to wrap around method calls. Decoators can have their own arguments, including blocks. When the method is called, each decorator will be called in order, receiving the caller instance, the return value of the previous decorator, and the method's arguments and block.
24
+
25
+ ```ruby
26
+ class Multiply < Decorator::Base
27
+ def call(this, args, ret, &block)
28
+ multiplier, = @decorator_args
29
+
30
+ return multiplier * ret if ret
31
+
32
+ multiplier * original(this, *args, &block)
33
+ end
34
+ end
35
+
36
+ class Controller
37
+ extend Decorator::DecoratorAware
38
+
39
+ Multiply(2)
40
+ Multiply(3)
41
+ def index
42
+ 10
43
+ end
44
+ end
45
+
46
+ puts Controller.new.index # 60
47
+ ```
48
+
49
+ Decorators can have names other than the class:
50
+
51
+ ```ruby
52
+ class DivideDecorator < Decorator::Base
53
+ decorator_name :divide
54
+
55
+ def call(this, args, ret, &block)
56
+ #
57
+ end
58
+ end
59
+ ```
60
+ They can also receive their own block:
61
+
62
+ ```ruby
63
+ class Route < Decorator::Base
64
+ def call(this, args, ret, &block)
65
+ @decorator_block.call
66
+ end
67
+ end
68
+
69
+ class Controller
70
+ extend Decorator::DecoratorAware
71
+
72
+ Route(:get, '/') { p "hello" }
73
+ def index
74
+ 10
75
+ end
76
+ end
77
+
78
+ Controller.new.index # Hello
79
+ ```
80
+
81
+ ## License
82
+
83
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/*_test.rb"]
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,73 @@
1
+ module Decorator
2
+ VERSION = '0.1'
3
+
4
+ module DecoratorAware
5
+ attr_accessor :method_decorator_map
6
+
7
+ class << self
8
+ attr_accessor :decorators, :registry
9
+ end
10
+
11
+ def method_missing(name, *args, &block)
12
+ klass = Decorator::DecoratorAware.registry&.key(name)
13
+
14
+ return super unless klass
15
+
16
+ @decorators ||= []
17
+ @decorators << [klass, args, block]
18
+ end
19
+
20
+ def method_added(name)
21
+ return if @decorators.empty?
22
+
23
+ decorators = @decorators.clone
24
+ @decorators = []
25
+
26
+ @method_decorator_map ||= {}
27
+ @method_decorator_map[name] = []
28
+
29
+ decorators.each do |klass, args, block|
30
+ @method_decorator_map[name] << klass.new(instance_method(name), *args, &block)
31
+ end
32
+
33
+ class_eval "
34
+ def #{name}(*args, &block)
35
+ ret = nil
36
+ self.class.method_decorator_map[:#{name}].each do |decorator|
37
+ ret = decorator.call(self, args, ret, &block)
38
+ end
39
+ ret
40
+ end"
41
+
42
+ @decorators = []
43
+ end
44
+ end
45
+
46
+ class Base
47
+ class << self
48
+ def decorator_name(name)
49
+ Decorator::DecoratorAware.registry ||= {}
50
+ Decorator::DecoratorAware.registry[self] = name.to_sym
51
+ end
52
+
53
+ def inherited(klass)
54
+ Decorator::DecoratorAware.registry ||= {}
55
+ Decorator::DecoratorAware.registry[klass] = klass.name.to_sym
56
+ end
57
+ end
58
+
59
+ def initialize(method, *args, &block)
60
+ @method = method
61
+ @decorator_args = args
62
+ @decorator_block = block
63
+ end
64
+
65
+ def original(this, *args, &block)
66
+ @method.bind(this).call(*args, &block)
67
+ end
68
+
69
+ def call(this, *args, &block)
70
+ raise NotImplementedError.new(self.class.name + '.' + __method__.to_s + ' method must be implemented')
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,28 @@
1
+ lib = File.expand_path("../lib", __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+
4
+ require_relative "lib/method_decorator"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "method_decorator.rb"
8
+ spec.version = Decorator::VERSION
9
+ spec.authors = ["Isty001"]
10
+ spec.email = ["isty001@gmail.com"]
11
+
12
+ spec.summary = %q{Chainable method decorator implementation}
13
+ spec.description = %q{Flexible method decorator implementation for Ruby, to wrap around method calls}
14
+ spec.homepage = "https://github.com/Isty001/method_decorator.rb"
15
+ spec.license = "MIT"
16
+
17
+ # Specify which files should be added to the gem when it is released.
18
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
19
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
20
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
21
+ end
22
+
23
+ spec.require_paths = ["lib"]
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.17"
26
+ spec.add_development_dependency "rake", "~> 10.0"
27
+ spec.add_development_dependency "minitest", "~> 5.0"
28
+ end
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: method_decorator.rb
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ platform: ruby
6
+ authors:
7
+ - Isty001
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-11-07 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.17'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.17'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ description: Flexible method decorator implementation for Ruby, to wrap around method
56
+ calls
57
+ email:
58
+ - isty001@gmail.com
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ".gitignore"
64
+ - Gemfile
65
+ - Gemfile.lock
66
+ - LICENSE
67
+ - README.md
68
+ - Rakefile
69
+ - lib/method_decorator.rb
70
+ - method_decorator.gemspec
71
+ homepage: https://github.com/Isty001/method_decorator.rb
72
+ licenses:
73
+ - MIT
74
+ metadata: {}
75
+ post_install_message:
76
+ rdoc_options: []
77
+ require_paths:
78
+ - lib
79
+ required_ruby_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ requirements: []
90
+ rubygems_version: 3.0.6
91
+ signing_key:
92
+ specification_version: 4
93
+ summary: Chainable method decorator implementation
94
+ test_files: []