type_wrapper 1.2.0 → 1.3.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
  SHA1:
3
- metadata.gz: 69d54edce7635369ec8d00ab82bd42a96c9a7394
4
- data.tar.gz: b64a288d3a8ead6d044efe8d4882df5189e4e341
3
+ metadata.gz: 58f7ba6011b57c1a7e2c036ca846eb83340f16dc
4
+ data.tar.gz: 9a5e7768db72b7f850e7f5161cc676133f221de3
5
5
  SHA512:
6
- metadata.gz: 3cf9f7abf54087cf97bd05633590fe0660ea9f066c8875254fc9fce47f19e3486f9f3a208ed884d891763c87118386ca1010c816f3331f31551dfa7a5c18eb5b
7
- data.tar.gz: 198d91a0c3a5ad32434559cd5a16323ea342b03202f64cfeb40655310d22fd3087281e941485a9e71efcbe414e83db8362290a4b15ec4fedfaa0fc6ff2f53070
6
+ metadata.gz: 8c1f1db9b45f45e1bce94982ec5fc69c3bee9edf6409766610af660627eb5a96a24d49cabf643b09dab9d31da92dabf9a7db75f15836c665ea9333832ffa834d
7
+ data.tar.gz: 6dbd5824a161cf924f0c2d4bc49a371881d41aa32a21dd19f2844acdecfbdcd39d39afbde8dd004050d5ebe6e9ccafc8c2303a4e4f7dce570730ecf4344c6b18
data/README.md CHANGED
@@ -69,6 +69,40 @@ using AwesomeSinging[Lego]
69
69
  Lego.new("Emmet").sing
70
70
  ```
71
71
 
72
+ ### TypeWrapper::Forwarding
73
+
74
+ Creates a Module that delegates Refinements methods (forwarding) to a target object.
75
+
76
+ ```ruby
77
+ Lego = Struct.new(:name)
78
+
79
+ module LoudSpeaking
80
+ def speak(words)
81
+ "#{name}: #{words.upcase}!!!"
82
+ end
83
+
84
+ def say(words)
85
+ "#{name}: #{words.upcase}!!!"
86
+ end
87
+ end
88
+
89
+ # Refinements
90
+ module LoudSpeakingLego
91
+ refine Lego do
92
+ include LoudSpeaking
93
+ end
94
+ end
95
+
96
+ # target: speaker
97
+ class LoudLego < Struct.new(:speaker)
98
+ include TypeWrapper::Forwarding[LoudSpeakingLego, :speak, :say, to: :speaker]
99
+ end
100
+
101
+ batman = Lego.new('Batman')
102
+ loud_lego = LoudLego.new(batman)
103
+ loud_lego.speak("I'm Batman") # => "Batman: I'M BATMAN!!!"
104
+ ```
105
+
72
106
  ## Pros
73
107
 
74
108
  * Five (5) times faster than [Object#extend](https://apidock.com/ruby/Object/extend).
data/lib/type_wrapper.rb CHANGED
@@ -1,34 +1,26 @@
1
1
  require "type_wrapper/version"
2
2
  require "type_wrapper/module"
3
+ require "type_wrapper/forwarding"
3
4
  require 'delegate'
4
5
 
5
6
  module TypeWrapper
6
- alias_method :initialize, def __setobj__(obj)
7
- @delegate_tw_obj = obj # change delegation object
8
- end
9
-
10
- alias_method :~@, def __getobj__
11
- @delegate_tw_obj # return object we are delegating to
12
- end
7
+ using Module::Refines
13
8
 
14
9
  def self.[](*types)
15
10
  raise TypeError, "wrong argument type (expected Module(s))" if types.include?(nil)
16
11
  raise ArgumentError, "wrong number of arguments (given #{types.size}, expected 2+)" if types.size < 2
17
12
 
18
- FOR[*types]
19
- end
20
-
21
- using Module::Refines
13
+ type, *behaviors = *types
22
14
 
23
- FOR = -> type, *behaviors do
24
- Class.new(Delegator) do
25
- include TypeWrapper
26
- const_set :Type, type
27
- const_set :BEHAVIORS, behaviors
28
- const_set :Trait, Module.new { behaviors.each { |mod| include mod.refines(type) } }
29
- forwarding = behaviors.flat_map(&:public_instance_methods) - public_instance_methods
30
- code = forwarding.uniq.map { |meth| "def %{meth}(*args, &block) __getobj__.%{meth}(*args, &block) end" % { meth: meth } }
31
- class_eval code.unshift("using Trait").join("\n")
32
- end
15
+ raise ArgumentError, "Module(s) has no public methods defined" if behaviors.flat_map(&:public_instance_methods).empty?
16
+
17
+ Class.new DelegateClass(type) do
18
+ alias_method :~@, :__getobj__
19
+ define_method(:inspect) { "#< #{self.class.name || behaviors} #{__getobj__} #>" }
20
+
21
+ behaviors.each do |mod|
22
+ include Forwarding.new mod.refines(type), *mod.public_instance_methods, to: :__getobj__
33
23
  end
24
+ end
25
+ end
34
26
  end
@@ -0,0 +1,32 @@
1
+ module TypeWrapper
2
+ class Forwarding < Module
3
+ def initialize(refinements, *forward, to:)
4
+ raise ArgumentError, "No List of Methods specified.", caller if forward.empty?
5
+ raise ArgumentError, "Can't convert #{to}:#{to.class} to Symbol", caller unless to.respond_to? :to_sym
6
+ const_set :Refinements, refinements
7
+ DefineMethods[forward, to.to_sym, self]
8
+ @forward = forward
9
+ @target = to
10
+ end
11
+
12
+ def inspect
13
+ refinements = const_get :Refinements
14
+ name || "Forwarding[#{refinements} #{@forward.join(' ')} to: #{@target}]"
15
+ end
16
+
17
+ def self.[](*args)
18
+ new *args
19
+ end
20
+
21
+ DefineMethods = -> forward, target, base do
22
+ code = forward.uniq.map do |forwarding|
23
+ <<-EOS
24
+ def #{forwarding}(*args, &block)
25
+ #{target}.#{forwarding}(*args, &block)
26
+ end
27
+ EOS
28
+ end
29
+ base.module_eval code.unshift("using Refinements").join("\n")
30
+ end # DefineMethods proc
31
+ end # Forwarding class
32
+ end
@@ -1,3 +1,3 @@
1
1
  module TypeWrapper
2
- VERSION = "1.2.0".freeze
2
+ VERSION = "1.3.0".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: type_wrapper
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ritchie Paul Buitre
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-07-19 00:00:00.000000000 Z
11
+ date: 2017-07-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -69,6 +69,7 @@ files:
69
69
  - bin/setup
70
70
  - examples/benchmark.rb
71
71
  - lib/type_wrapper.rb
72
+ - lib/type_wrapper/forwarding.rb
72
73
  - lib/type_wrapper/module.rb
73
74
  - lib/type_wrapper/version.rb
74
75
  - type_wrapper.gemspec