refinement_builder 1.0.1 → 1.0.2

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.
Files changed (4) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +124 -0
  3. data/lib/version.rb +1 -1
  4. metadata +2 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 82b4e5e91e586773c31d1648127eb8256238f927
4
- data.tar.gz: 83a5ff2f102b13a81cf78fa4d0399a01ddc81c31
3
+ metadata.gz: 67c9c31c878d3a7c00915082307ea9907354a7ba
4
+ data.tar.gz: 0095704ec07097ae1d883744c96093a4be815425
5
5
  SHA512:
6
- metadata.gz: 92598daefc4e1b9b7899ec253ef51fd7d3631a3101a33e770db9ffbba81c3e15d013e129206a96d76d3aef85ad75ef09debaab7b36da71d7f15f6cb24c13dea0
7
- data.tar.gz: 408ef3ba867855c283760664836c6b427ae3b40506d67bd78f20a4719dc3751087515a3e56ba09ddf6fb0f3824eb7e1921fd61de5bda6af22a3d3a85e303f095
6
+ metadata.gz: bac819eaff7a59b82cfd4fdc2b28bafd95d9a3124395eadcee8f88d2d57060b4018d16a5ac3fb25d1c9d8d9e90466ccbbab9f6d8d493ff177b577b0150887b1b
7
+ data.tar.gz: e8702b0c9f807d2864b610a9abbbc50dd19eee6b8eb0c0b983d16b055fcd97931e5f83b2a6bd2a3d63f902ce820dff407912dcf456f88d977e2a164aced0b0a3
data/README.md ADDED
@@ -0,0 +1,124 @@
1
+ # refinement_builder
2
+
3
+ This is a gem which offers a helper method to create refinement-compatible
4
+ modules. It's essentially a factory for modules which enables certain functionality
5
+ while avoiding boilerplate.
6
+
7
+ ---
8
+ ## Installation
9
+
10
+ Install the gem:
11
+
12
+ gem install refinement_builder
13
+
14
+ Require the code:
15
+
16
+ require 'refinement_builder'
17
+
18
+ ---
19
+ ## Usage 1 - _calling `build_refinement`_
20
+
21
+ There is one method contained here that is accessible in 3 ways:
22
+
23
+ 1. Class method - [`RefinementBuilder.build_refinement`](http://www.rubydoc.info/gems/refinement_builder/RefinementBuilder.build_refinement):
24
+
25
+ RefinementBuilder.build_refinement "StringPatch" do
26
+ # ...
27
+ end
28
+ 2. Mixin
29
+
30
+ include RefinementBuilder
31
+ build_refinement "StringPatch" do
32
+ # ...
33
+ end
34
+ 3. Refinement
35
+
36
+ using RefinementBuilder
37
+ build_refinement "StringPatch" do
38
+ # ...
39
+ end
40
+
41
+ ---
42
+ ## Usage 2 - _defining functions_
43
+ As for what goes inside the block - normal methods, basically. These will be added as both instance and class methods (using `module_function`) _as well as_ refinements. Furthermore, the methods will be able to call each other with implicit namespacing from any of these contexts. For example:
44
+
45
+ RefinementBuilder.build_refinement "StringPatch" do
46
+ def print_first_5_characters(string=self)
47
+ print first_5_characters(string)
48
+ end
49
+ def first_5_characters(string=self)
50
+ string.slice 0...5
51
+ end
52
+ end
53
+
54
+ By defaulting the `string` argument to `self`, the methods are usable as String instance methods (using `self` as the receiver instead of an argument) and `StringPatch` static methods (passing the receiver as an argument).
55
+
56
+ ---
57
+
58
+ ## Usage 3 - _using functions_
59
+
60
+ The `StringPatch` has its methods accessible in the same 3 ways as `RefinementBuilder`
61
+
62
+ 1. Class method:
63
+
64
+ StringPatch.print_first_5_characters("hello world")
65
+ # => hello
66
+
67
+ 2. Mixin:
68
+
69
+ String.include StringPatch
70
+ "hello world".print_first_5_characters
71
+ # => hello
72
+
73
+ 3. refinement:
74
+
75
+ using StringPatch
76
+ "hello world.print_first_5_characters
77
+ # => hello
78
+
79
+ ## Under the hood
80
+ Under the hood, what happens is this:
81
+
82
+ 1. A module is defined with the given name and instance method definitions
83
+ 2. Each of the instance methods is overwritten in such a way that it will delegate to the class method if called from any other scope, and execute the original function body if it's in class method scope.
84
+ 3. The instance methods are copied to class methods via `module_function`
85
+ 3. A refinement is defined with the instance methods.
86
+
87
+ ## Usage 4 - _options_
88
+
89
+ `refinement_builder` only cares about three arguments (and the block):
90
+
91
+ 1. The name of the module constant to create (e.g. `"StringPatch"` in the above examples).
92
+ 2. The following keyword arguments:
93
+
94
+ 1. `namespace: <class/module>` where the module will be created under (defaults to Object)
95
+ 2. `refines: <class>` what the refinement will patch. Also defaults to Object.
96
+
97
+ ## Benefits of this approach
98
+
99
+ The main benefit is the ability to get these multiple usages without writing wrapper functions. Here's a module definition which is about the same as the one created by this factory:
100
+
101
+ ```
102
+ module StringPatch
103
+ def print_first_5_characters(string=self)
104
+ if eql?(StringPatch)
105
+ print first_5_characters(string)
106
+ else
107
+ StringPatch.print_first_5_characters(string)
108
+ end
109
+ end
110
+ def first_5_characters(string=self)
111
+ if eql?(StringPatch)
112
+ string.slice(0...5)
113
+ else
114
+ StringPatch.first_5_characters(string)
115
+ end
116
+ end
117
+ module_function :print_first_5_characters, :first_5_characters
118
+ refine String do
119
+ include StringPatch
120
+ end
121
+ end
122
+ ```
123
+
124
+ In my opinion, this is no fun - too much boiler.
data/lib/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module RefinementBuilder
2
- VERSION = '1.0.1'
2
+ VERSION = '1.0.2'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: refinement_builder
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - max pleaner
@@ -31,6 +31,7 @@ executables:
31
31
  extensions: []
32
32
  extra_rdoc_files: []
33
33
  files:
34
+ - README.md
34
35
  - bin/refinement_builder
35
36
  - lib/refinement_builder.rb
36
37
  - lib/version.rb