neco 0.0.1 → 0.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 +4 -4
- data/.rubocop.yml +2 -0
- data/Gemfile.lock +7 -1
- data/bin/console +4 -4
- data/examples/command.rb +45 -0
- data/examples/composition.rb +45 -0
- data/lib/neco.rb +2 -0
- data/lib/neco/command.rb +94 -0
- data/lib/neco/composition.rb +27 -0
- data/lib/neco/container.rb +29 -0
- data/lib/neco/version.rb +1 -1
- data/neco.gemspec +1 -0
- metadata +21 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5b8600b54de50cbf86de418e8ac297f91ca7944829ad55a970c212f7ebe9f3bc
|
4
|
+
data.tar.gz: 0b96f25e550ce59eff7822f73173da69198c6c6ad2db83fa7b8f0b5c30b9e224
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '05398284cdd89b706c5c37134fabf33ee97475396555c8a49f264e0595efec4ba80d4ee69b2cc980b107e340e69467d13154cec84e1faffe167e96d5f0ccc9ea'
|
7
|
+
data.tar.gz: d0a0fe2de63bcb45e152a94112ef5470610bc9e4e18d3a8616bfc0617388e08598e0452e65caa56e5cee9e574206b643fd8143be5f96939c800f8cbbaf00ae42
|
data/.rubocop.yml
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,17 +1,22 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
neco (0.0
|
4
|
+
neco (0.1.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
9
|
ast (2.4.0)
|
10
|
+
coderay (1.1.2)
|
10
11
|
jaro_winkler (1.5.2)
|
12
|
+
method_source (0.9.2)
|
11
13
|
minitest (5.11.3)
|
12
14
|
parallel (1.17.0)
|
13
15
|
parser (2.6.3.0)
|
14
16
|
ast (~> 2.4.0)
|
17
|
+
pry (0.12.2)
|
18
|
+
coderay (~> 1.1.0)
|
19
|
+
method_source (~> 0.9.0)
|
15
20
|
rainbow (3.0.0)
|
16
21
|
rake (10.5.0)
|
17
22
|
rubocop (0.70.0)
|
@@ -31,6 +36,7 @@ DEPENDENCIES
|
|
31
36
|
bundler (~> 2.0)
|
32
37
|
minitest (~> 5.0)
|
33
38
|
neco!
|
39
|
+
pry (>= 0.12.2)
|
34
40
|
rake (~> 10.0)
|
35
41
|
rubocop (>= 0.70.0)
|
36
42
|
|
data/bin/console
CHANGED
@@ -8,8 +8,8 @@ require 'neco'
|
|
8
8
|
# with your gem easier. You can also use a different console, if you like.
|
9
9
|
|
10
10
|
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
-
|
12
|
-
|
11
|
+
require 'pry'
|
12
|
+
Pry.start
|
13
13
|
|
14
|
-
require 'irb'
|
15
|
-
IRB.start(__FILE__)
|
14
|
+
# require 'irb'
|
15
|
+
# IRB.start(__FILE__)
|
data/examples/command.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'neco'
|
5
|
+
|
6
|
+
# An example class for validation and main logic
|
7
|
+
# with block parameter.
|
8
|
+
class Foo
|
9
|
+
include Neco::Command
|
10
|
+
|
11
|
+
validates do |name:|
|
12
|
+
name == 'Tama'
|
13
|
+
end
|
14
|
+
|
15
|
+
main do |name:|
|
16
|
+
puts "Hello, #{name}!"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
Foo.call(name: 'Tama')
|
21
|
+
Foo.call(name: 'Pochi')
|
22
|
+
Foo.new.call(name: 'Tama')
|
23
|
+
Foo.new(name: 'Pochi').call
|
24
|
+
|
25
|
+
class Bar
|
26
|
+
include Neco::Command
|
27
|
+
|
28
|
+
main do |answer|
|
29
|
+
puts "The ultimate answer is #{answer}"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
Bar.call(42)
|
34
|
+
Bar.new(42).call
|
35
|
+
|
36
|
+
class Buzz
|
37
|
+
include Neco::Command
|
38
|
+
|
39
|
+
main do |user:, params: nil|
|
40
|
+
user.update(params)
|
41
|
+
p "User is now #{user}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
Buzz.new(user: {}).call(params: {name: 'Tama'})
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'neco'
|
5
|
+
|
6
|
+
class Command1
|
7
|
+
include Neco::Command
|
8
|
+
|
9
|
+
main do
|
10
|
+
set :cat_name, 'Tama'
|
11
|
+
end
|
12
|
+
|
13
|
+
rollback do
|
14
|
+
puts 'Rolling back Command1!'
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Command2
|
19
|
+
include Neco::Command
|
20
|
+
|
21
|
+
main do |cat_name:|
|
22
|
+
puts "Hello, #{cat_name}!"
|
23
|
+
end
|
24
|
+
|
25
|
+
rollback do
|
26
|
+
puts 'Rolling back Command2!'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class Command3
|
31
|
+
include Neco::Command
|
32
|
+
|
33
|
+
# Unused block argument
|
34
|
+
main do |cat_name:|
|
35
|
+
raise 'OMG!!!'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Bar
|
40
|
+
include Neco::Composition
|
41
|
+
|
42
|
+
composes Command1, Command2, Command3
|
43
|
+
end
|
44
|
+
|
45
|
+
Bar.call
|
data/lib/neco.rb
CHANGED
data/lib/neco/command.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'neco/container'
|
4
|
+
|
5
|
+
module Neco
|
6
|
+
# Command module is a basic module of Neco.
|
7
|
+
# It provides many DSLs for validating input, executing business logic,
|
8
|
+
# handling errors and much more.
|
9
|
+
module Command
|
10
|
+
def self.included(base)
|
11
|
+
base.class_eval do
|
12
|
+
extend ClassMethods
|
13
|
+
include InstanceMethods
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# DSLs
|
18
|
+
module ClassMethods
|
19
|
+
def main(&blk)
|
20
|
+
@main = blk
|
21
|
+
end
|
22
|
+
|
23
|
+
def validates(&blk)
|
24
|
+
@validation = blk
|
25
|
+
end
|
26
|
+
|
27
|
+
def rollback(&blk)
|
28
|
+
@rollback = blk
|
29
|
+
end
|
30
|
+
|
31
|
+
def call(*args, **params)
|
32
|
+
instance = new(*args, **params)
|
33
|
+
instance.call
|
34
|
+
true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# When command object is instantiated, either by a class-level call,
|
39
|
+
# a container or a user, these methods will be called.
|
40
|
+
module InstanceMethods
|
41
|
+
def initialize(*args, container: FakeContainer.new(command: self), **params)
|
42
|
+
@args = args
|
43
|
+
@container = container
|
44
|
+
@params = params
|
45
|
+
end
|
46
|
+
|
47
|
+
def set(key, value)
|
48
|
+
@container.set(key, value)
|
49
|
+
end
|
50
|
+
|
51
|
+
def call(*args, **params)
|
52
|
+
@args += args
|
53
|
+
@params.merge!(params)
|
54
|
+
|
55
|
+
return false unless validate
|
56
|
+
|
57
|
+
main = self.class.instance_variable_get(:@main)
|
58
|
+
instance_exec(*@args, **@params, &main)
|
59
|
+
end
|
60
|
+
|
61
|
+
def validate
|
62
|
+
validation = self.class.instance_variable_get(:@validation)
|
63
|
+
validation ? validation.call(@args, @params) : true
|
64
|
+
end
|
65
|
+
|
66
|
+
def revert
|
67
|
+
rollback = self.class.instance_variable_get(:@rollback)
|
68
|
+
instance_exec(*@args, **@params, &rollback)
|
69
|
+
end
|
70
|
+
|
71
|
+
def to_s
|
72
|
+
main = self.class.instance_variable_get(:@main)
|
73
|
+
main.inspect
|
74
|
+
end
|
75
|
+
|
76
|
+
def inspect
|
77
|
+
to_s
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# @private
|
82
|
+
class FakeContainer
|
83
|
+
def initialize(command:)
|
84
|
+
@command = command
|
85
|
+
@environment = {}
|
86
|
+
end
|
87
|
+
|
88
|
+
def set(key, value)
|
89
|
+
@environment[key] = value
|
90
|
+
end
|
91
|
+
end
|
92
|
+
private_constant :FakeContainer
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'neco/container'
|
4
|
+
|
5
|
+
module Neco
|
6
|
+
# Composition is a module for users to compose multiple commands.
|
7
|
+
module Composition
|
8
|
+
def self.included(base)
|
9
|
+
base.class_eval do
|
10
|
+
extend ClassMethods
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# DSLs for composition pattern.
|
15
|
+
# `compose` is meant to be used in a class definition
|
16
|
+
# while `call` is meant to be used when users actually execute commands.
|
17
|
+
module ClassMethods
|
18
|
+
def composes(*commands)
|
19
|
+
@container = Container.new(commands: commands)
|
20
|
+
end
|
21
|
+
|
22
|
+
def call(*args, **params)
|
23
|
+
@container.call(args, params)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Neco
|
4
|
+
# Container has two purposes.
|
5
|
+
# One is to store commands and execute rollbacks when one command raises an exception.
|
6
|
+
# Another is to store environment hash for those commands so that commands can pass data between them.
|
7
|
+
class Container
|
8
|
+
def initialize(commands: [], environment: {})
|
9
|
+
@commands = commands.map {|command| command.new(container: self) }
|
10
|
+
@environment = environment
|
11
|
+
@called = []
|
12
|
+
end
|
13
|
+
|
14
|
+
def call(*args, **params)
|
15
|
+
@environment.merge!(params)
|
16
|
+
@commands.each do |command|
|
17
|
+
command.call(*args, **@environment)
|
18
|
+
@called << command
|
19
|
+
rescue StandardError
|
20
|
+
@called.reverse_each(&:revert)
|
21
|
+
break
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def set(key, value)
|
26
|
+
@environment[key] = value
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/neco/version.rb
CHANGED
data/neco.gemspec
CHANGED
@@ -29,6 +29,7 @@ Gem::Specification.new do |spec|
|
|
29
29
|
|
30
30
|
spec.add_development_dependency 'bundler', '~> 2.0'
|
31
31
|
spec.add_development_dependency 'minitest', '~> 5.0'
|
32
|
+
spec.add_development_dependency 'pry', '>= 0.12.2'
|
32
33
|
spec.add_development_dependency 'rake', '~> 10.0'
|
33
34
|
spec.add_development_dependency 'rubocop', '>= 0.70.0'
|
34
35
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: neco
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- OKURA Masafumi
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-05-
|
11
|
+
date: 2019-05-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '5.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 0.12.2
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.12.2
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rake
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -86,7 +100,12 @@ files:
|
|
86
100
|
- Rakefile
|
87
101
|
- bin/console
|
88
102
|
- bin/setup
|
103
|
+
- examples/command.rb
|
104
|
+
- examples/composition.rb
|
89
105
|
- lib/neco.rb
|
106
|
+
- lib/neco/command.rb
|
107
|
+
- lib/neco/composition.rb
|
108
|
+
- lib/neco/container.rb
|
90
109
|
- lib/neco/version.rb
|
91
110
|
- neco.gemspec
|
92
111
|
homepage: https://github.com/okuramasafumi/neco
|