insane_hook 0.3.0 → 0.4.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 +5 -5
- data/Gemfile.lock +2 -2
- data/README.md +40 -26
- data/lib/insane_hook.rb +11 -64
- data/lib/insane_hook/class_methods.rb +53 -0
- data/lib/insane_hook/constants.rb +9 -0
- data/lib/insane_hook/errors.rb +8 -0
- data/lib/insane_hook/version.rb +2 -2
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 02b68a08a81d3f28cfad66779ed793df6ce08fcc200f56395f2c4d6bea82d786
|
4
|
+
data.tar.gz: c141a6ee66ed0766c6e36301f020fbdb2ceb4350e17f021b6fd03f7cf543c9fb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d4280e7a961f0c9d5d442ba93f89dc4bf7da836f96380883306051f12a1227423e69424b9881903c5936bca5b6a4f2dfcbfb758250a4c87a3e749ec2ad4bc172
|
7
|
+
data.tar.gz: 793c51f4be50e4b7af99cba480c64c9fb604230d598428b83b71ff0d6ad9818ec18337b25483f5c0dff930dff3d83b7f8d0c200900f5578dfde36e661b982188
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -2,6 +2,10 @@
|
|
2
2
|
|
3
3
|
Enjoy the enforcing-DSL of this command-patterny gem.
|
4
4
|
|
5
|
+
## Current version
|
6
|
+
|
7
|
+
0.4.0
|
8
|
+
|
5
9
|
## Installation
|
6
10
|
|
7
11
|
Add this line to your application's Gemfile:
|
@@ -21,47 +25,57 @@ Or install it yourself as:
|
|
21
25
|
## Usage
|
22
26
|
|
23
27
|
```ruby
|
24
|
-
class YeOldeTaske
|
25
|
-
|
26
|
-
|
27
|
-
allow :some_optional_arg
|
28
|
+
class YeOldeTaske < InsaneHook
|
29
|
+
requires :some_required_arg
|
30
|
+
fallbacks :some_optional_arg
|
28
31
|
|
29
32
|
call do
|
30
|
-
# attr_readers are available for:
|
31
|
-
# - some_required_arg
|
32
|
-
# - some_optional_arg
|
33
33
|
result "meaningful value"
|
34
34
|
end
|
35
35
|
end
|
36
|
-
|
37
|
-
YeOldeTaske.new # => InsaneHook::MissingArgumentError
|
38
|
-
|
39
|
-
task = YeOldeTaske.new(some_required_arg: "input") # => YeOldeTaske instance
|
40
|
-
task.result # => raises InsaneHook::CommandNotRunError
|
41
|
-
task.call # => YeOldeTaske instance
|
42
|
-
task.result # => "meaningful value"
|
43
36
|
```
|
44
37
|
|
38
|
+
Is equivalent to:
|
39
|
+
|
45
40
|
```ruby
|
46
41
|
class YeOldeTaske
|
47
|
-
include InsaneHook
|
48
|
-
need :some_required_arg
|
49
|
-
allow :some_optional_arg
|
50
42
|
|
51
|
-
call
|
52
|
-
|
53
|
-
# - some_required_arg
|
54
|
-
# - some_optional_arg
|
43
|
+
def self.call(**args)
|
44
|
+
new(**args).call
|
55
45
|
end
|
56
|
-
end
|
57
46
|
|
58
|
-
|
59
|
-
|
47
|
+
attr_reader :some_required_arg, :some_optional_arg
|
48
|
+
def initialize(some_required_arg:, some_optional_arg: nil)
|
49
|
+
@some_required_arg = some_required_arg
|
50
|
+
@some_optional_arg = some_optional_arg
|
51
|
+
end
|
60
52
|
|
61
|
-
|
62
|
-
|
53
|
+
def call
|
54
|
+
result "meaningful value"
|
55
|
+
self
|
56
|
+
end
|
57
|
+
|
58
|
+
def result(arg = InsaneHook::NO_ARG)
|
59
|
+
if arg == InsaneHook::NO_ARG
|
60
|
+
if instance_variable_defined?(:@result)
|
61
|
+
@result
|
62
|
+
else
|
63
|
+
raise InsaneHook::CommandNotRunError
|
64
|
+
end
|
65
|
+
else
|
66
|
+
@result = arg
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
63
71
|
```
|
64
72
|
|
73
|
+
|
74
|
+
## Design decisions
|
75
|
+
1. Usage of `call` is idiomatic Ruby. Procs and method objects respond to `call`, so we are extending an existing Ruby pattern.
|
76
|
+
2. Commands should not return anything, but if you are forced to check a result, then set the result to a single object and work off of that object, for instance if you want to use the command as one of the clauses of a case statement (in which case the result would be a boolean)
|
77
|
+
3. Composition is usually better than Inheritance, especially in a language that doesn't support multiple inheritance. Here we need to use inheritance because we are completely taking over both the `.new` and the `#initialize` methods, meaning the object does not truly belong to the person writing the code.
|
78
|
+
|
65
79
|
## Development
|
66
80
|
|
67
81
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/insane_hook.rb
CHANGED
@@ -1,78 +1,25 @@
|
|
1
|
+
require "insane_hook/class_methods"
|
1
2
|
require "insane_hook/version"
|
3
|
+
require "insane_hook/errors"
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
OPTIONAL_ARGS = :optional
|
7
|
-
RESULT_VAR = :@_result
|
8
|
-
NO_ARG = :_no_value
|
9
|
-
class CommandNotRunError < StandardError ; end
|
10
|
-
class MissingArgumentError < StandardError ; end
|
5
|
+
class InsaneHook
|
6
|
+
include InsaneHook::Errors
|
7
|
+
include InsaneHook::Constants
|
11
8
|
|
12
|
-
def self.
|
13
|
-
|
14
|
-
|
15
|
-
mod.define_singleton_method(:need, mod.instance_method(:_need))
|
16
|
-
mod.define_singleton_method(:allow, mod.instance_method(:_allow))
|
17
|
-
mod.define_singleton_method(:call, mod.instance_method(:_call))
|
9
|
+
def self.inherited(subclass)
|
10
|
+
subclass.class_variable_set(ARGS_VAR, {REQUIRED_ARGS => [], OPTIONAL_ARGS => []})
|
11
|
+
subclass.extend(InsaneHook::ClassMethods)
|
18
12
|
end
|
19
13
|
|
20
14
|
def result(value=NO_ARG)
|
21
15
|
if value == NO_ARG
|
22
|
-
if instance_variable_defined?(
|
23
|
-
instance_variable_get(
|
16
|
+
if instance_variable_defined?(RESULT_VAR)
|
17
|
+
instance_variable_get(RESULT_VAR)
|
24
18
|
else
|
25
19
|
raise CommandNotRunError
|
26
20
|
end
|
27
21
|
else
|
28
|
-
instance_variable_set(
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def _need(key)
|
33
|
-
fail "#{key} is not a symbol" unless key.is_a? Symbol
|
34
|
-
args = self.class_variable_get(::InsaneHook::ARGS_VAR)
|
35
|
-
args[REQUIRED_ARGS] << key
|
36
|
-
self.class_variable_set(::InsaneHook::ARGS_VAR, args)
|
37
|
-
end
|
38
|
-
|
39
|
-
def _allow(key)
|
40
|
-
fail "#{key} is not a symbol" unless key.is_a? Symbol
|
41
|
-
args = self.class_variable_get(::InsaneHook::ARGS_VAR)
|
42
|
-
args[OPTIONAL_ARGS] << key
|
43
|
-
self.class_variable_set(::InsaneHook::ARGS_VAR, args)
|
44
|
-
end
|
45
|
-
|
46
|
-
def _call(**args, &block)
|
47
|
-
if block_given?
|
48
|
-
raise "Block cannot take arguments" if block.arity > 0
|
49
|
-
raise "call method already defined" if self.instance_methods.include?(:call)
|
50
|
-
define_method(:call) do
|
51
|
-
result(nil)
|
52
|
-
instance_eval(&block)
|
53
|
-
self
|
54
|
-
end
|
55
|
-
else
|
56
|
-
new(**args).call
|
57
|
-
end
|
58
|
-
|
59
|
-
end
|
60
|
-
|
61
|
-
module ClassMethods
|
62
|
-
def new(**args)
|
63
|
-
obj = self.allocate
|
64
|
-
self.class_variable_get(::InsaneHook::ARGS_VAR)[REQUIRED_ARGS].each do |var|
|
65
|
-
value = args.fetch(var) { raise(::InsaneHook::MissingArgumentError, "#{var} not provided in #{self.class}") }
|
66
|
-
obj.instance_variable_set("@#{var}", value)
|
67
|
-
obj.class.class_eval{attr_reader var}
|
68
|
-
end
|
69
|
-
self.class_variable_get(::InsaneHook::ARGS_VAR)[OPTIONAL_ARGS].each do |var|
|
70
|
-
value = args.fetch(var, nil)
|
71
|
-
obj.instance_variable_set("@#{var}", value)
|
72
|
-
obj.class.class_eval{attr_reader var}
|
73
|
-
end
|
74
|
-
obj.send :initialize
|
75
|
-
obj
|
22
|
+
instance_variable_set(RESULT_VAR, value)
|
76
23
|
end
|
77
24
|
end
|
78
25
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require "insane_hook/constants"
|
2
|
+
require "insane_hook/errors"
|
3
|
+
|
4
|
+
class InsaneHook
|
5
|
+
module ClassMethods
|
6
|
+
include Constants
|
7
|
+
include Errors
|
8
|
+
|
9
|
+
def new(**args)
|
10
|
+
obj = self.allocate
|
11
|
+
self.class_variable_get(ARGS_VAR)[REQUIRED_ARGS].each do |var|
|
12
|
+
value = args.fetch(var) { raise(MissingArgumentError, "#{var} not provided in #{self.class}") }
|
13
|
+
obj.instance_variable_set("@#{var}", value)
|
14
|
+
obj.class.class_eval{attr_reader var}
|
15
|
+
end
|
16
|
+
self.class_variable_get(ARGS_VAR)[OPTIONAL_ARGS].each do |var|
|
17
|
+
value = args.fetch(var, nil)
|
18
|
+
obj.instance_variable_set("@#{var}", value)
|
19
|
+
obj.class.class_eval{attr_reader var}
|
20
|
+
end
|
21
|
+
obj.send :initialize
|
22
|
+
obj
|
23
|
+
end
|
24
|
+
|
25
|
+
def requires(key)
|
26
|
+
fail "#{key} is not a symbol" unless key.is_a? Symbol
|
27
|
+
args = self.class_variable_get(ARGS_VAR)
|
28
|
+
args[REQUIRED_ARGS] << key
|
29
|
+
self.class_variable_set(ARGS_VAR, args)
|
30
|
+
end
|
31
|
+
|
32
|
+
def fallbacks(key)
|
33
|
+
fail "#{key} is not a symbol" unless key.is_a? Symbol
|
34
|
+
args = self.class_variable_get(ARGS_VAR)
|
35
|
+
args[OPTIONAL_ARGS] << key
|
36
|
+
self.class_variable_set(ARGS_VAR, args)
|
37
|
+
end
|
38
|
+
|
39
|
+
def call(**args, &block)
|
40
|
+
if block_given?
|
41
|
+
raise "Block cannot take arguments" if block.arity > 0
|
42
|
+
raise "call method already defined" if self.instance_methods.include?(:call)
|
43
|
+
define_method(:call) do
|
44
|
+
result(nil)
|
45
|
+
instance_eval(&block)
|
46
|
+
self
|
47
|
+
end
|
48
|
+
else
|
49
|
+
new(**args).call
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/insane_hook/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
VERSION = "0.
|
1
|
+
class InsaneHook
|
2
|
+
VERSION = "0.4.0"
|
3
3
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: insane_hook
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Aldric Giacomoni, Ahmad Ragab
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-07-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -72,6 +72,9 @@ files:
|
|
72
72
|
- bin/setup
|
73
73
|
- insane_hook.gemspec
|
74
74
|
- lib/insane_hook.rb
|
75
|
+
- lib/insane_hook/class_methods.rb
|
76
|
+
- lib/insane_hook/constants.rb
|
77
|
+
- lib/insane_hook/errors.rb
|
75
78
|
- lib/insane_hook/version.rb
|
76
79
|
homepage: https://github.com/Trevoke/insane-hook
|
77
80
|
licenses:
|
@@ -94,7 +97,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
94
97
|
version: '0'
|
95
98
|
requirements: []
|
96
99
|
rubyforge_project:
|
97
|
-
rubygems_version: 2.
|
100
|
+
rubygems_version: 2.7.3
|
98
101
|
signing_key:
|
99
102
|
specification_version: 4
|
100
103
|
summary: Another implementation of the command pattern that provides a DSL.
|