forwardable 1.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.
@@ -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: []