forwardable 1.2.0

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: c08b5a019cfdbf0cfcf51bfb66d6500065d8f6492fc50a8e481d1e427a6d2df8
4
+ data.tar.gz: 9a25242aae4c2214ffffc7027eb680a9e09f0fda47f1bcf35cd15cea06c35ac9
5
+ SHA512:
6
+ metadata.gz: a23ba5a69ad8fe490e81bb01815fda286e97259c7010e48c3491c9e2537a1a7cbf78da7805f07c6ac302cab8458152c9343e0f19d3669269afc33c94a11d7b42
7
+ data.tar.gz: 1e809b3fd7e1ff732cbd9abb384e1ad914d1bf53b4ce23973989741414cfe3015ce7cb744222dd4694b58ee1b17ec0e722406770b908ea6cafc1c19387111c3e
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
@@ -0,0 +1,6 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.5.1
5
+ - ruby-head
6
+ before_install: gem install bundler -v 1.16.2
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
+ Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions
5
+ are met:
6
+ 1. Redistributions of source code must retain the above copyright
7
+ notice, this list of conditions and the following disclaimer.
8
+ 2. Redistributions in binary form must reproduce the above copyright
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
+
12
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
16
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22
+ SUCH DAMAGE.
@@ -0,0 +1,79 @@
1
+ # Forwardable
2
+
3
+ The Forwardable module provides delegation of specified methods to a designated object, using the methods #def_delegator and #def_delegators.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'forwardable'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install forwardable
20
+
21
+ ## Usage
22
+
23
+ For example, say you have a class RecordCollection which contains an array <tt>@records</tt>. You could provide the lookup ethod `#record_number()`, which simply calls #[] on the <tt>@records</tt> array, like this:
24
+
25
+ ```
26
+ require 'forwardable'
27
+
28
+ class RecordCollection
29
+ attr_accessor :records
30
+ extend Forwardable
31
+ def_delegator :@records, :[], :record_number
32
+ end
33
+ ```
34
+
35
+ We can use the lookup method like so:
36
+
37
+ ```
38
+ r = RecordCollection.new
39
+ r.records = [4,5,6]
40
+ r.record_number(0) # => 4
41
+ ```
42
+
43
+ Further, if you wish to provide the methods #size, #<<, and #map, all of which delegate to @records, this is how you can do it:
44
+
45
+ ```
46
+ class RecordCollection # re-open RecordCollection class
47
+ def_delegators :@records, :size, :<<, :map
48
+ end
49
+
50
+ r = RecordCollection.new
51
+ r.records = [1,2,3]
52
+ r.record_number(0) # => 1
53
+ r.size # => 3
54
+ r << 4 # => [1, 2, 3, 4]
55
+ r.map { |x| x * 2 } # => [2, 4, 6, 8]
56
+ ```
57
+
58
+ You can even extend regular objects with Forwardable.
59
+
60
+ ```
61
+ my_hash = Hash.new
62
+ my_hash.extend Forwardable # prepare object for delegation
63
+ my_hash.def_delegator "STDOUT", "puts" # add delegation for STDOUT.puts()
64
+ my_hash.puts "Howdy!"
65
+ ```
66
+
67
+ ## Development
68
+
69
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
70
+
71
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
72
+
73
+ ## Contributing
74
+
75
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/forwardable.
76
+
77
+ ## License
78
+
79
+ The gem is available as open source under the terms of the [2-Clause BSD License](https://opensource.org/licenses/BSD-2-Clause).
@@ -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" << "test/lib"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/test_*.rb"]
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require_relative "../lib/forwardable"
5
+
6
+ require "irb"
7
+ IRB.start(__FILE__)
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
@@ -0,0 +1,26 @@
1
+ begin
2
+ require_relative "lib/forwardable"
3
+ rescue LoadError
4
+ # for Ruby core repository
5
+ require_relative "../forwardable"
6
+ end
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = "forwardable"
10
+ spec.version = Forwardable::VERSION
11
+ spec.authors = ["Keiju ISHITSUKA"]
12
+ spec.email = ["keiju@ruby-lang.org"]
13
+
14
+ spec.summary = %q{Provides delegation of specified methods to a designated object.}
15
+ spec.description = %q{Provides delegation of specified methods to a designated object.}
16
+ spec.homepage = "https://github.com/ruby/forwardable"
17
+ spec.license = "BSD-2-Clause"
18
+
19
+ spec.files = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "forwardable.gemspec", "lib/forwardable.rb", "lib/forwardable/impl.rb"]
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_development_dependency "bundler"
25
+ spec.add_development_dependency "rake"
26
+ end
@@ -0,0 +1,309 @@
1
+ # frozen_string_literal: false
2
+ #
3
+ # forwardable.rb -
4
+ # $Release Version: 1.1$
5
+ # $Revision$
6
+ # by Keiju ISHITSUKA(keiju@ishitsuka.com)
7
+ # original definition by delegator.rb
8
+ # Revised by Daniel J. Berger with suggestions from Florian Gross.
9
+ #
10
+ # Documentation by James Edward Gray II and Gavin Sinclair
11
+
12
+
13
+
14
+ # The Forwardable module provides delegation of specified
15
+ # methods to a designated object, using the methods #def_delegator
16
+ # and #def_delegators.
17
+ #
18
+ # For example, say you have a class RecordCollection which
19
+ # contains an array <tt>@records</tt>. You could provide the lookup method
20
+ # #record_number(), which simply calls #[] on the <tt>@records</tt>
21
+ # array, like this:
22
+ #
23
+ # require 'forwardable'
24
+ #
25
+ # class RecordCollection
26
+ # attr_accessor :records
27
+ # extend Forwardable
28
+ # def_delegator :@records, :[], :record_number
29
+ # end
30
+ #
31
+ # We can use the lookup method like so:
32
+ #
33
+ # r = RecordCollection.new
34
+ # r.records = [4,5,6]
35
+ # r.record_number(0) # => 4
36
+ #
37
+ # Further, if you wish to provide the methods #size, #<<, and #map,
38
+ # all of which delegate to @records, this is how you can do it:
39
+ #
40
+ # class RecordCollection # re-open RecordCollection class
41
+ # def_delegators :@records, :size, :<<, :map
42
+ # end
43
+ #
44
+ # r = RecordCollection.new
45
+ # r.records = [1,2,3]
46
+ # r.record_number(0) # => 1
47
+ # r.size # => 3
48
+ # r << 4 # => [1, 2, 3, 4]
49
+ # r.map { |x| x * 2 } # => [2, 4, 6, 8]
50
+ #
51
+ # You can even extend regular objects with Forwardable.
52
+ #
53
+ # my_hash = Hash.new
54
+ # my_hash.extend Forwardable # prepare object for delegation
55
+ # my_hash.def_delegator "STDOUT", "puts" # add delegation for STDOUT.puts()
56
+ # my_hash.puts "Howdy!"
57
+ #
58
+ # == Another example
59
+ #
60
+ # We want to rely on what has come before obviously, but with delegation we can
61
+ # take just the methods we need and even rename them as appropriate. In many
62
+ # cases this is preferable to inheritance, which gives us the entire old
63
+ # interface, even if much of it isn't needed.
64
+ #
65
+ # class Queue
66
+ # extend Forwardable
67
+ #
68
+ # def initialize
69
+ # @q = [ ] # prepare delegate object
70
+ # end
71
+ #
72
+ # # setup preferred interface, enq() and deq()...
73
+ # def_delegator :@q, :push, :enq
74
+ # def_delegator :@q, :shift, :deq
75
+ #
76
+ # # support some general Array methods that fit Queues well
77
+ # def_delegators :@q, :clear, :first, :push, :shift, :size
78
+ # end
79
+ #
80
+ # q = Queue.new
81
+ # q.enq 1, 2, 3, 4, 5
82
+ # q.push 6
83
+ #
84
+ # q.shift # => 1
85
+ # while q.size > 0
86
+ # puts q.deq
87
+ # end
88
+ #
89
+ # q.enq "Ruby", "Perl", "Python"
90
+ # puts q.first
91
+ # q.clear
92
+ # puts q.first
93
+ #
94
+ # This should output:
95
+ #
96
+ # 2
97
+ # 3
98
+ # 4
99
+ # 5
100
+ # 6
101
+ # Ruby
102
+ # nil
103
+ #
104
+ # == Notes
105
+ #
106
+ # Be advised, RDoc will not detect delegated methods.
107
+ #
108
+ # +forwardable.rb+ provides single-method delegation via the def_delegator and
109
+ # def_delegators methods. For full-class delegation via DelegateClass, see
110
+ # +delegate.rb+.
111
+ #
112
+ module Forwardable
113
+ require 'forwardable/impl'
114
+
115
+ # Version of +forwardable.rb+
116
+ VERSION = "1.2.0"
117
+ FORWARDABLE_VERSION = VERSION
118
+
119
+ @debug = nil
120
+ class << self
121
+ # ignored
122
+ attr_accessor :debug
123
+ end
124
+
125
+ # Takes a hash as its argument. The key is a symbol or an array of
126
+ # symbols. These symbols correspond to method names. The value is
127
+ # the accessor to which the methods will be delegated.
128
+ #
129
+ # :call-seq:
130
+ # delegate method => accessor
131
+ # delegate [method, method, ...] => accessor
132
+ #
133
+ def instance_delegate(hash)
134
+ hash.each do |methods, accessor|
135
+ unless defined?(methods.each)
136
+ def_instance_delegator(accessor, methods)
137
+ else
138
+ methods.each {|method| def_instance_delegator(accessor, method)}
139
+ end
140
+ end
141
+ end
142
+
143
+ #
144
+ # Shortcut for defining multiple delegator methods, but with no
145
+ # provision for using a different name. The following two code
146
+ # samples have the same effect:
147
+ #
148
+ # def_delegators :@records, :size, :<<, :map
149
+ #
150
+ # def_delegator :@records, :size
151
+ # def_delegator :@records, :<<
152
+ # def_delegator :@records, :map
153
+ #
154
+ def def_instance_delegators(accessor, *methods)
155
+ methods.delete("__send__")
156
+ methods.delete("__id__")
157
+ for method in methods
158
+ def_instance_delegator(accessor, method)
159
+ end
160
+ end
161
+
162
+ # Define +method+ as delegator instance method with an optional
163
+ # alias name +ali+. Method calls to +ali+ will be delegated to
164
+ # +accessor.method+.
165
+ #
166
+ # class MyQueue
167
+ # extend Forwardable
168
+ # attr_reader :queue
169
+ # def initialize
170
+ # @queue = []
171
+ # end
172
+ #
173
+ # def_delegator :@queue, :push, :mypush
174
+ # end
175
+ #
176
+ # q = MyQueue.new
177
+ # q.mypush 42
178
+ # q.queue #=> [42]
179
+ # q.push 23 #=> NoMethodError
180
+ #
181
+ def def_instance_delegator(accessor, method, ali = method)
182
+ gen = Forwardable._delegator_method(self, accessor, method, ali)
183
+
184
+ # If it's not a class or module, it's an instance
185
+ (Module === self ? self : singleton_class).module_eval(&gen)
186
+ end
187
+
188
+ alias delegate instance_delegate
189
+ alias def_delegators def_instance_delegators
190
+ alias def_delegator def_instance_delegator
191
+
192
+ # :nodoc:
193
+ def self._delegator_method(obj, accessor, method, ali)
194
+ accessor = accessor.to_s unless Symbol === accessor
195
+
196
+ if Module === obj ?
197
+ obj.method_defined?(accessor) || obj.private_method_defined?(accessor) :
198
+ obj.respond_to?(accessor, true)
199
+ accessor = "#{accessor}()"
200
+ end
201
+
202
+ method_call = ".__send__(:#{method}, *args, &block)"
203
+ if _valid_method?(method)
204
+ loc, = caller_locations(2,1)
205
+ pre = "_ ="
206
+ mesg = "#{Module === obj ? obj : obj.class}\##{ali} at #{loc.path}:#{loc.lineno} forwarding to private method "
207
+ method_call = "#{<<-"begin;"}\n#{<<-"end;".chomp}"
208
+ begin;
209
+ unless defined? _.#{method}
210
+ ::Kernel.warn #{mesg.dump}"\#{_.class}"'##{method}', uplevel: 1
211
+ _#{method_call}
212
+ else
213
+ _.#{method}(*args, &block)
214
+ end
215
+ end;
216
+ end
217
+
218
+ _compile_method("#{<<-"begin;"}\n#{<<-"end;"}", __FILE__, __LINE__+1)
219
+ begin;
220
+ proc do
221
+ def #{ali}(*args, &block)
222
+ #{pre}
223
+ begin
224
+ #{accessor}
225
+ end#{method_call}#{FILTER_EXCEPTION}
226
+ end
227
+ end
228
+ end;
229
+ end
230
+ end
231
+
232
+ # SingleForwardable can be used to setup delegation at the object level as well.
233
+ #
234
+ # printer = String.new
235
+ # printer.extend SingleForwardable # prepare object for delegation
236
+ # printer.def_delegator "STDOUT", "puts" # add delegation for STDOUT.puts()
237
+ # printer.puts "Howdy!"
238
+ #
239
+ # Also, SingleForwardable can be used to set up delegation for a Class or Module.
240
+ #
241
+ # class Implementation
242
+ # def self.service
243
+ # puts "serviced!"
244
+ # end
245
+ # end
246
+ #
247
+ # module Facade
248
+ # extend SingleForwardable
249
+ # def_delegator :Implementation, :service
250
+ # end
251
+ #
252
+ # Facade.service #=> serviced!
253
+ #
254
+ # If you want to use both Forwardable and SingleForwardable, you can
255
+ # use methods def_instance_delegator and def_single_delegator, etc.
256
+ module SingleForwardable
257
+ # Takes a hash as its argument. The key is a symbol or an array of
258
+ # symbols. These symbols correspond to method names. The value is
259
+ # the accessor to which the methods will be delegated.
260
+ #
261
+ # :call-seq:
262
+ # delegate method => accessor
263
+ # delegate [method, method, ...] => accessor
264
+ #
265
+ def single_delegate(hash)
266
+ hash.each do |methods, accessor|
267
+ unless defined?(methods.each)
268
+ def_single_delegator(accessor, methods)
269
+ else
270
+ methods.each {|method| def_single_delegator(accessor, method)}
271
+ end
272
+ end
273
+ end
274
+
275
+ #
276
+ # Shortcut for defining multiple delegator methods, but with no
277
+ # provision for using a different name. The following two code
278
+ # samples have the same effect:
279
+ #
280
+ # def_delegators :@records, :size, :<<, :map
281
+ #
282
+ # def_delegator :@records, :size
283
+ # def_delegator :@records, :<<
284
+ # def_delegator :@records, :map
285
+ #
286
+ def def_single_delegators(accessor, *methods)
287
+ methods.delete("__send__")
288
+ methods.delete("__id__")
289
+ for method in methods
290
+ def_single_delegator(accessor, method)
291
+ end
292
+ end
293
+
294
+ # :call-seq:
295
+ # def_single_delegator(accessor, method, new_name=method)
296
+ #
297
+ # Defines a method _method_ which delegates to _accessor_ (i.e. it calls
298
+ # the method of the same name in _accessor_). If _new_name_ is
299
+ # provided, it is used as the name for the delegate method.
300
+ def def_single_delegator(accessor, method, ali = method)
301
+ gen = Forwardable._delegator_method(self, accessor, method, ali)
302
+
303
+ instance_eval(&gen)
304
+ end
305
+
306
+ alias delegate single_delegate
307
+ alias def_delegators def_single_delegators
308
+ alias def_delegator def_single_delegator
309
+ end
@@ -0,0 +1,24 @@
1
+ # :stopdoc:
2
+ module Forwardable
3
+ FILE_REGEXP = %r"#{Regexp.quote(File.dirname(__FILE__))}"
4
+ FILTER_EXCEPTION = <<-'END'
5
+
6
+ rescue ::Exception
7
+ $@.delete_if {|s| ::Forwardable::FILE_REGEXP =~ s} unless ::Forwardable::debug
8
+ ::Kernel::raise
9
+ END
10
+
11
+ def self._valid_method?(method)
12
+ catch {|tag|
13
+ eval("BEGIN{throw tag}; ().#{method}", binding, __FILE__, __LINE__)
14
+ }
15
+ rescue SyntaxError
16
+ false
17
+ else
18
+ true
19
+ end
20
+
21
+ def self._compile_method(src, file, line)
22
+ eval(src, nil, file, line)
23
+ end
24
+ end
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: forwardable
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Keiju ISHITSUKA
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-12-04 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: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Provides delegation of specified methods to a designated object.
42
+ email:
43
+ - keiju@ruby-lang.org
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - ".travis.yml"
50
+ - Gemfile
51
+ - LICENSE.txt
52
+ - README.md
53
+ - Rakefile
54
+ - bin/console
55
+ - bin/setup
56
+ - forwardable.gemspec
57
+ - lib/forwardable.rb
58
+ - lib/forwardable/impl.rb
59
+ homepage: https://github.com/ruby/forwardable
60
+ licenses:
61
+ - BSD-2-Clause
62
+ metadata: {}
63
+ post_install_message:
64
+ rdoc_options: []
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubyforge_project:
79
+ rubygems_version: 2.7.6
80
+ signing_key:
81
+ specification_version: 4
82
+ summary: Provides delegation of specified methods to a designated object.
83
+ test_files: []