direct 1.0.0 → 1.1.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/.gitignore +1 -0
- data/.travis.yml +5 -4
- data/CHANGELOG.md +7 -0
- data/Gemfile +2 -1
- data/README.md +12 -10
- data/direct.gemspec +0 -1
- data/lib/direct.rb +34 -15
- data/lib/direct/executable.rb +91 -0
- data/lib/direct/group.rb +26 -0
- data/lib/direct/version.rb +1 -1
- metadata +6 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: fa39232af5f66ca2043ac1b5e258a26e6869b8c012ccaa0661080e89a7644ea8
|
4
|
+
data.tar.gz: 2d9ad86998c6903f6c3146258cf278ec0deac829ac96e8ffb85f47967e1e2c4c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4afc48c61d7b189f49b016af2419f54f03a114d5ad5cfcfcfeaa12373e8787d655b651f223e1b9f45b3adef88124c701f452c6077fc3bdc76380d5a3597ed415
|
7
|
+
data.tar.gz: bef096a5f6212ca376b919ed1238da53571a9fea95631352686acfe49c6ea8b1b7ec071496dfebbdfd33537c81e7cafefad894eaf6d9e668fbc4cfb03ad3883b
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
sudo: false
|
2
2
|
before_install:
|
3
|
-
- gem
|
3
|
+
- gem update --system
|
4
|
+
- gem install bundler
|
4
5
|
language: ruby
|
5
6
|
cache: bundler
|
6
7
|
rvm:
|
7
|
-
- 2.2.9
|
8
8
|
- 2.3.6
|
9
|
-
- 2.4.
|
10
|
-
- 2.5.
|
9
|
+
- 2.4.4
|
10
|
+
- 2.5.3
|
11
|
+
- 2.6.1
|
11
12
|
- ruby-head
|
12
13
|
- jruby-head
|
13
14
|
env:
|
data/CHANGELOG.md
ADDED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -21,13 +21,15 @@ end
|
|
21
21
|
|
22
22
|
# Somewhere else
|
23
23
|
|
24
|
-
SomeClass.new.direct(:success){
|
24
|
+
SomeClass.new.direct(:success){|something, *data|
|
25
25
|
STDOUT.puts data
|
26
|
-
}.direct(:failure){
|
26
|
+
}.direct(:failure){|something, *errors|
|
27
27
|
STDERR.puts errors
|
28
28
|
}.save
|
29
29
|
```
|
30
30
|
|
31
|
+
Your blocks will always receive the object itself as the first argument.
|
32
|
+
|
31
33
|
## Why?
|
32
34
|
|
33
35
|
You could easily write code that says `if` this `else` that.
|
@@ -63,7 +65,7 @@ if something.save!
|
|
63
65
|
puts "yay! #{something}"
|
64
66
|
elsif something.valid? && !something.persisted?
|
65
67
|
puts "it sort of worked"
|
66
|
-
|
68
|
+
elsif !something.valid? || something.need_some_other_thing_set?
|
67
69
|
puts "an alternative to it not working"
|
68
70
|
else
|
69
71
|
puts "boo! #{something}: #{something.errors}"
|
@@ -77,13 +79,13 @@ Instead, we can name these scenarios and allow the object to handle them; we
|
|
77
79
|
merely provide the block of code to execute:
|
78
80
|
|
79
81
|
```ruby
|
80
|
-
Something.new.direct(:success){|
|
81
|
-
|
82
|
-
}.direct(:failure){ |
|
83
|
-
|
84
|
-
}.direct(:other_scenario){|
|
85
|
-
|
86
|
-
}
|
82
|
+
Something.new.direct(:success){ |obj|
|
83
|
+
puts "yay! #{obj}"
|
84
|
+
}.direct(:failure){ |obj, errors|
|
85
|
+
puts "boo! #{obj}: #{errors}"
|
86
|
+
}.direct(:other_scenario){ |obj|
|
87
|
+
puts "here's what happened and what to do..."
|
88
|
+
}
|
87
89
|
```
|
88
90
|
|
89
91
|
_Inside_ of the object is where we can handle these named scenarios. If the
|
data/direct.gemspec
CHANGED
@@ -23,7 +23,6 @@ Gem::Specification.new do |spec|
|
|
23
23
|
|
24
24
|
spec.add_dependency "concurrent-ruby", ">= 1.0"
|
25
25
|
|
26
|
-
spec.add_development_dependency "bundler", "~> 1.16"
|
27
26
|
spec.add_development_dependency "rake", "~> 12.3"
|
28
27
|
spec.add_development_dependency "minitest", "~> 5.11"
|
29
28
|
end
|
data/lib/direct.rb
CHANGED
@@ -1,9 +1,30 @@
|
|
1
1
|
require "direct/version"
|
2
|
-
require "
|
2
|
+
require "direct/executable"
|
3
|
+
require "direct/group"
|
3
4
|
|
4
5
|
# Include this module in your classes to provide a way for
|
5
6
|
# your objects to handle named scenarios with blocks of code.
|
6
7
|
module Direct
|
8
|
+
class MissingProcedure < StandardError; end
|
9
|
+
|
10
|
+
# Wrap a block of code to return an object for handling
|
11
|
+
# success or failure.
|
12
|
+
#
|
13
|
+
# Example:
|
14
|
+
#
|
15
|
+
# def do_it
|
16
|
+
# Direct.defer{
|
17
|
+
# [true, false].sample
|
18
|
+
# }
|
19
|
+
# end
|
20
|
+
# do_it.
|
21
|
+
# success{|result| puts "it worked!" }.
|
22
|
+
# failure{|result| puts "it failed!" }
|
23
|
+
#
|
24
|
+
def self.defer(&block)
|
25
|
+
Executable.new(&block)
|
26
|
+
end
|
27
|
+
|
7
28
|
# Tell the object what to do in a given scenario.
|
8
29
|
#
|
9
30
|
# object.direct(:success){|obj| puts "it worked!" }
|
@@ -11,16 +32,19 @@ module Direct
|
|
11
32
|
#
|
12
33
|
# You may also chain calls to this method
|
13
34
|
#
|
14
|
-
# object.direct(:success){ |obj|
|
35
|
+
# object.direct(:success){ |obj|
|
15
36
|
# puts "it worked!"
|
16
37
|
# }.direct(:failure){ |obj|
|
17
38
|
# puts "it failed!"
|
18
39
|
# }.do_it
|
19
|
-
#
|
20
|
-
|
21
|
-
|
40
|
+
#
|
41
|
+
# Your blocks will always receive the object itself as the first argument.
|
42
|
+
#
|
43
|
+
def direct(key, callable=nil, &block)
|
44
|
+
__directions.store(key, callable || block)
|
22
45
|
self
|
23
46
|
end
|
47
|
+
alias_method :when, :direct
|
24
48
|
|
25
49
|
# Perform the named block of code
|
26
50
|
#
|
@@ -33,21 +57,16 @@ module Direct
|
|
33
57
|
#
|
34
58
|
# This will raise an error if the provided key is not found
|
35
59
|
def as_directed(key, *args)
|
36
|
-
|
60
|
+
__directions.fetch(key).map do |block|
|
37
61
|
block.call(self, *args)
|
38
62
|
end
|
63
|
+
rescue KeyError
|
64
|
+
raise MissingProcedure, "Procedure for :#{key} was reached but not specified."
|
39
65
|
end
|
40
66
|
|
41
67
|
private
|
42
68
|
|
43
|
-
def
|
44
|
-
@
|
45
|
-
@__direct_store.put_if_absent(key, Concurrent::Array.new)
|
46
|
-
@__direct_store.fetch(key) << block
|
47
|
-
@__direct_store
|
48
|
-
end
|
49
|
-
|
50
|
-
def __direct_store_fetch(key)
|
51
|
-
@__direct_store.fetch(key)
|
69
|
+
def __directions
|
70
|
+
@__directions ||= Direct::Group.new
|
52
71
|
end
|
53
72
|
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Direct
|
2
|
+
class Executable
|
3
|
+
include Direct
|
4
|
+
|
5
|
+
# It is intended that you initialize objects via Direct.defer
|
6
|
+
# and not directly initializing this class.
|
7
|
+
#
|
8
|
+
# You may initialize this class and provide an object which
|
9
|
+
# responds to "call" or a block to execute.
|
10
|
+
#
|
11
|
+
# Example:
|
12
|
+
#
|
13
|
+
# Direct.defer do
|
14
|
+
# puts "see ya later!"
|
15
|
+
# end
|
16
|
+
#
|
17
|
+
# Direct.defer(->{ "call me, maybe" })
|
18
|
+
#
|
19
|
+
def initialize(callable=nil, &block)
|
20
|
+
@execution = callable || block
|
21
|
+
@exception_classes = [StandardError]
|
22
|
+
end
|
23
|
+
attr_reader :execution, :exception_classes
|
24
|
+
|
25
|
+
# Tell the object what to do for a success path
|
26
|
+
#
|
27
|
+
# Returns itself
|
28
|
+
#
|
29
|
+
def success(callable=nil, &block)
|
30
|
+
direct(:success, (callable || block))
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
# Tell the object what to do for a failure path
|
35
|
+
#
|
36
|
+
# Returns itself
|
37
|
+
#
|
38
|
+
def failure(callable=nil, &block)
|
39
|
+
direct(:failure, (callable || block))
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
# Tell the object what to do for an exception path.
|
44
|
+
#
|
45
|
+
# You may optionally provide a list of modules rescued by
|
46
|
+
# the value method in the case of an exception.
|
47
|
+
#
|
48
|
+
# Returns itself
|
49
|
+
#
|
50
|
+
# Example:
|
51
|
+
#
|
52
|
+
# Direct.defer {
|
53
|
+
# # something...
|
54
|
+
# }.exception(NoMethodError) { |deferred, exception|
|
55
|
+
# ExceptionNotifier.notify(exception)
|
56
|
+
# }
|
57
|
+
#
|
58
|
+
def exception(*classes, &block)
|
59
|
+
unless classes.empty?
|
60
|
+
@exception_classes = classes
|
61
|
+
end
|
62
|
+
direct(:exception, block)
|
63
|
+
self
|
64
|
+
end
|
65
|
+
|
66
|
+
def run_exception_block(exception)
|
67
|
+
if __directions.key?(:exception)
|
68
|
+
as_directed(:exception, exception)
|
69
|
+
else
|
70
|
+
as_directed(:failure, exception)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
private :run_exception_block
|
74
|
+
|
75
|
+
# Return the value of the success or failure path
|
76
|
+
# and rescue from StandardError or from the modules
|
77
|
+
# provided to the exception path.
|
78
|
+
#
|
79
|
+
def value
|
80
|
+
result = execution.()
|
81
|
+
if result
|
82
|
+
as_directed(:success, result)
|
83
|
+
else
|
84
|
+
as_directed(:failure, result)
|
85
|
+
end
|
86
|
+
rescue *exception_classes => exception
|
87
|
+
run_exception_block(exception)
|
88
|
+
end
|
89
|
+
alias execute value
|
90
|
+
end
|
91
|
+
end
|
data/lib/direct/group.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'concurrent'
|
2
|
+
module Direct
|
3
|
+
class Group
|
4
|
+
def initialize
|
5
|
+
@map = Concurrent::Map.new{|collection, key|
|
6
|
+
collection.put(key, Concurrent::Array.new)
|
7
|
+
}
|
8
|
+
end
|
9
|
+
|
10
|
+
attr_reader :map
|
11
|
+
private :map
|
12
|
+
|
13
|
+
def store(key, callable=nil, &block)
|
14
|
+
map[key] << (callable || block)
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
def fetch(key)
|
19
|
+
map.fetch(key)
|
20
|
+
end
|
21
|
+
|
22
|
+
def key?(key)
|
23
|
+
map.key?(key)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/direct/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: direct
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jim Gay
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-02-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: concurrent-ruby
|
@@ -24,20 +24,6 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: bundler
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - "~>"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '1.16'
|
34
|
-
type: :development
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - "~>"
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '1.16'
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: rake
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -75,6 +61,7 @@ extra_rdoc_files: []
|
|
75
61
|
files:
|
76
62
|
- ".gitignore"
|
77
63
|
- ".travis.yml"
|
64
|
+
- CHANGELOG.md
|
78
65
|
- CODE_OF_CONDUCT.md
|
79
66
|
- Gemfile
|
80
67
|
- LICENSE.txt
|
@@ -84,6 +71,8 @@ files:
|
|
84
71
|
- bin/setup
|
85
72
|
- direct.gemspec
|
86
73
|
- lib/direct.rb
|
74
|
+
- lib/direct/executable.rb
|
75
|
+
- lib/direct/group.rb
|
87
76
|
- lib/direct/version.rb
|
88
77
|
homepage: https://github.com/saturnflyer/direct
|
89
78
|
licenses:
|
@@ -104,8 +93,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
104
93
|
- !ruby/object:Gem::Version
|
105
94
|
version: '0'
|
106
95
|
requirements: []
|
107
|
-
|
108
|
-
rubygems_version: 2.5.2.2
|
96
|
+
rubygems_version: 3.0.2
|
109
97
|
signing_key:
|
110
98
|
specification_version: 4
|
111
99
|
summary: Direct objects to perform arbitrary blocks by name
|