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 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