neco 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4a76769c86da347b95edf51478953e8df04d2eb2ab97f19e7dfd995a05017c9d
4
- data.tar.gz: 5c1d9f6613159a5ceba4c61a3dd38e50de5925b6b760c87cd894500051eaa3b8
3
+ metadata.gz: 5b8600b54de50cbf86de418e8ac297f91ca7944829ad55a970c212f7ebe9f3bc
4
+ data.tar.gz: 0b96f25e550ce59eff7822f73173da69198c6c6ad2db83fa7b8f0b5c30b9e224
5
5
  SHA512:
6
- metadata.gz: d04fd9578ff50db4c6289c13855094ad60865d29ccae1fc10c0e2fc6885e9096e192c2647a13b4610886d5de8e0109271d847489e7697a82aa01a2077ca7bf55
7
- data.tar.gz: e2e49ae215916a6784f422abb0bd2bedc2de97e5ce5be4913ec1d8c7e83fa92c24e917b8faf082e955cd45ffb451f038a1a4be3db2b7fd60a663c648ae623a71
6
+ metadata.gz: '05398284cdd89b706c5c37134fabf33ee97475396555c8a49f264e0595efec4ba80d4ee69b2cc980b107e340e69467d13154cec84e1faffe167e96d5f0ccc9ea'
7
+ data.tar.gz: d0a0fe2de63bcb45e152a94112ef5470610bc9e4e18d3a8616bfc0617388e08598e0452e65caa56e5cee9e574206b643fd8143be5f96939c800f8cbbaf00ae42
@@ -1,5 +1,7 @@
1
1
  AllCops:
2
2
  TargetRubyVersion: 2.6
3
+ Exclude:
4
+ - 'examples/**/*.rb'
3
5
 
4
6
  Style/DoubleNegation:
5
7
  Enabled: false
@@ -1,17 +1,22 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- neco (0.0.1)
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
 
@@ -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
- # require "pry"
12
- # Pry.start
11
+ require 'pry'
12
+ Pry.start
13
13
 
14
- require 'irb'
15
- IRB.start(__FILE__)
14
+ # require 'irb'
15
+ # IRB.start(__FILE__)
@@ -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
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'neco/version'
4
+ require 'neco/command'
5
+ require 'neco/composition'
4
6
 
5
7
  module Neco
6
8
  class Error < StandardError; end
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Neco
4
- VERSION = '0.0.1'
4
+ VERSION = '0.1.0'
5
5
  end
@@ -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.1
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-22 00:00:00.000000000 Z
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