type_wrapper 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +29 -3
- data/lib/type_wrapper/module.rb +51 -0
- data/lib/type_wrapper/version.rb +1 -1
- data/lib/type_wrapper.rb +8 -6
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 69d54edce7635369ec8d00ab82bd42a96c9a7394
|
4
|
+
data.tar.gz: b64a288d3a8ead6d044efe8d4882df5189e4e341
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3cf9f7abf54087cf97bd05633590fe0660ea9f066c8875254fc9fce47f19e3486f9f3a208ed884d891763c87118386ca1010c816f3331f31551dfa7a5c18eb5b
|
7
|
+
data.tar.gz: 198d91a0c3a5ad32434559cd5a16323ea342b03202f64cfeb40655310d22fd3087281e941485a9e71efcbe414e83db8362290a4b15ec4fedfaa0fc6ff2f53070
|
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# TypeWrapper
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/type_wrapper.svg)](https://badge.fury.io/rb/type_wrapper)
|
4
|
+
[![Build Status](https://travis-ci.org/RichOrElse/type-wrapper.svg?branch=master)](https://travis-ci.org/RichOrElse/type-wrapper)
|
4
5
|
|
5
6
|
Delegator pattern in Ruby without object schizophrenia. Because Object#extend at runtime is evil.
|
6
7
|
|
@@ -22,6 +23,10 @@ Or install it yourself as:
|
|
22
23
|
|
23
24
|
## Usage
|
24
25
|
|
26
|
+
### TypeWrapper
|
27
|
+
|
28
|
+
Construct a delegator class using square brackets '[]' method with type as the first argument followed by mixins.
|
29
|
+
|
25
30
|
```ruby
|
26
31
|
module ToArray
|
27
32
|
def to_a
|
@@ -43,18 +48,39 @@ peter = PersonPresenter.new(Person.new('Peter'))
|
|
43
48
|
peter.to_a
|
44
49
|
```
|
45
50
|
|
51
|
+
### TypeWrapper::Module
|
52
|
+
|
53
|
+
Define a block with the 'new' method and pass the 'mod' parameter to 'using' keyword.
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
AwesomeSinging = TypeWrapper::Module.new do |mod| using mod
|
57
|
+
def sing
|
58
|
+
"#{name} sings #{song}"
|
59
|
+
end
|
60
|
+
|
61
|
+
def song
|
62
|
+
"Everything is AWESOME!!!"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
Lego = Struct.new(:name)
|
67
|
+
|
68
|
+
using AwesomeSinging[Lego]
|
69
|
+
Lego.new("Emmet").sing
|
70
|
+
```
|
71
|
+
|
46
72
|
## Pros
|
47
73
|
|
48
74
|
* Five (5) times faster than [Object#extend](https://apidock.com/ruby/Object/extend).
|
49
75
|
* Delegation without [self schizophrenia](https://en.wikipedia.org/wiki/Schizophrenia_(object-oriented_programming)).
|
50
76
|
* [Decorator Pattern](https://en.wikipedia.org/wiki/Decorator_pattern) with multiple traits.
|
51
|
-
* Allows [DCI](
|
77
|
+
* Allows [DCI](https://github.com/RichOrElse/wrapper-based/) in Ruby without [blowing the method cache at run time](https://tonyarcieri.com/dci-in-ruby-is-completely-broken).
|
52
78
|
|
53
79
|
## Cons
|
54
80
|
|
81
|
+
* Must use TypeWrapper::Module to allow procedural code in mixins.
|
55
82
|
* Three (3) times slower than calling class method. [See benchmark.](https://github.com/RichOrElse/wrapper-based/tree/master/examples/benchmark.rb)
|
56
|
-
* [
|
57
|
-
* Methods applied by [Object#extend](https://apidock.com/ruby/Object/extend) takes precedence over Mixin methods.
|
83
|
+
* Methods applied with [Object#extend](https://apidock.com/ruby/Object/extend) takes precedence over Mixin methods.
|
58
84
|
|
59
85
|
## Development
|
60
86
|
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module TypeWrapper
|
2
|
+
# == Basic Usage
|
3
|
+
#
|
4
|
+
# === Define a block with the 'new' method and pass the 'mod' parameter to 'using' keyword.
|
5
|
+
#
|
6
|
+
# AwesomeSinging = TypeWrapper::Module.new do |mod| using mod
|
7
|
+
# def sing
|
8
|
+
# "#{name} sings #{song}"
|
9
|
+
# end
|
10
|
+
#
|
11
|
+
# def song
|
12
|
+
# "Everything is AWESOME!!!"
|
13
|
+
# end
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# === Use as refinement module by passing the 'refines' method with types.
|
17
|
+
#
|
18
|
+
# Lego = Struct.new(:name)
|
19
|
+
# using AwesomeSinging[Lego]
|
20
|
+
# Lego.new("Emmette").sing
|
21
|
+
#
|
22
|
+
|
23
|
+
class Module < ::Module
|
24
|
+
def initialize(default = Object, *types, &blk)
|
25
|
+
mod, @block = self, blk
|
26
|
+
types.unshift(default).each do |type|
|
27
|
+
refine(type) { module_exec mod, &blk }
|
28
|
+
end
|
29
|
+
super(&blk)
|
30
|
+
end
|
31
|
+
|
32
|
+
def refines(*types)
|
33
|
+
self.class.new(*types, &@block)
|
34
|
+
end
|
35
|
+
|
36
|
+
alias_method :[], :refines
|
37
|
+
|
38
|
+
module Refines
|
39
|
+
refine ::Module do
|
40
|
+
def refines(*types)
|
41
|
+
mod = self
|
42
|
+
Module.new do
|
43
|
+
types.each do |type|
|
44
|
+
refine(type) { prepend mod }
|
45
|
+
end
|
46
|
+
end # new Module
|
47
|
+
end # refines method
|
48
|
+
end # ::Module refinements
|
49
|
+
end # Refinements module
|
50
|
+
end # Module class
|
51
|
+
end # TypeWrapper module
|
data/lib/type_wrapper/version.rb
CHANGED
data/lib/type_wrapper.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require "type_wrapper/version"
|
2
|
+
require "type_wrapper/module"
|
2
3
|
require 'delegate'
|
3
4
|
|
4
5
|
module TypeWrapper
|
@@ -10,20 +11,21 @@ module TypeWrapper
|
|
10
11
|
@delegate_tw_obj # return object we are delegating to
|
11
12
|
end
|
12
13
|
|
13
|
-
def self.[](
|
14
|
-
raise TypeError, "wrong argument type (expected
|
15
|
-
raise
|
16
|
-
raise ArgumentError, "wrong number of arguments (given 1, expected 2+)" if modules.empty?
|
14
|
+
def self.[](*types)
|
15
|
+
raise TypeError, "wrong argument type (expected Module(s))" if types.include?(nil)
|
16
|
+
raise ArgumentError, "wrong number of arguments (given #{types.size}, expected 2+)" if types.size < 2
|
17
17
|
|
18
|
-
FOR[
|
18
|
+
FOR[*types]
|
19
19
|
end
|
20
|
+
|
21
|
+
using Module::Refines
|
20
22
|
|
21
23
|
FOR = -> type, *behaviors do
|
22
24
|
Class.new(Delegator) do
|
23
25
|
include TypeWrapper
|
24
26
|
const_set :Type, type
|
25
27
|
const_set :BEHAVIORS, behaviors
|
26
|
-
const_set :Trait, Module.new {
|
28
|
+
const_set :Trait, Module.new { behaviors.each { |mod| include mod.refines(type) } }
|
27
29
|
forwarding = behaviors.flat_map(&:public_instance_methods) - public_instance_methods
|
28
30
|
code = forwarding.uniq.map { |meth| "def %{meth}(*args, &block) __getobj__.%{meth}(*args, &block) end" % { meth: meth } }
|
29
31
|
class_eval code.unshift("using Trait").join("\n")
|
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.
|
4
|
+
version: 1.2.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-
|
11
|
+
date: 2017-07-19 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/module.rb
|
72
73
|
- lib/type_wrapper/version.rb
|
73
74
|
- type_wrapper.gemspec
|
74
75
|
homepage: https://github.com/RichOrElse/type-wrapper/
|
@@ -91,7 +92,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
91
92
|
version: '0'
|
92
93
|
requirements: []
|
93
94
|
rubyforge_project:
|
94
|
-
rubygems_version: 2.
|
95
|
+
rubygems_version: 2.2.2
|
95
96
|
signing_key:
|
96
97
|
specification_version: 4
|
97
98
|
summary: Delegator pattern in Ruby without object schizophrenia. Because Object#extend
|