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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1b0ccfe16ab90f4f07518274c6845ac0055fe7da
4
- data.tar.gz: 727a2f9f2f1bd9780fdc8669cd0db03c16ff5f4b
3
+ metadata.gz: 69d54edce7635369ec8d00ab82bd42a96c9a7394
4
+ data.tar.gz: b64a288d3a8ead6d044efe8d4882df5189e4e341
5
5
  SHA512:
6
- metadata.gz: a0a6bc7d172fe270878473fed419bcc73a39c8a0dece6428f09c727ce7b93afd4c895344f44dde317a0e50fbdeb0a2315d0a5c92ad1920c15357229437bbfcd7
7
- data.tar.gz: d4fe98670eab3f07a487c49d16f079f3b1e522581c7890e551dd138e274d5634a08838cd8beb31ad662019c7bf0b9c98c6eda8ebfacf5ba1a0a99e4a528f7ff7
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](http://dci.github.io/) in Ruby without [blowing the method cache at run time](https://tonyarcieri.com/dci-in-ruby-is-completely-broken).
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
- * [Procedural code](https://en.wikipedia.org/wiki/Procedural_programming) inside Mixin is broken, methods scoped in Mixin cannot directly call another method in the same scope of the Mixin.
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
@@ -1,3 +1,3 @@
1
1
  module TypeWrapper
2
- VERSION = "1.1.0"
2
+ VERSION = "1.2.0".freeze
3
3
  end
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.[](type, *modules)
14
- raise TypeError, "wrong argument type (expected Class)" unless Class === type
15
- raise TypeError, "wrong argument type (expected Module(s))" unless modules.all? { |mod| mod.class == Module }
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[type, *modules]
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 { refine(type) { prepend(*behaviors.reverse) } }
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.1.0
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-06-30 00:00:00.000000000 Z
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.5.1
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