type_wrapper 1.1.0 → 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.
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