riker 0.1.0.pre3 → 0.1.0.pre5

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: b819ce3e2d6fb0f84fd16e4eb754802ca3c655810179225c9f4ba9cff3d8f068
4
- data.tar.gz: ab2a5b0a1e9f3beb29c1ba8437de4b50be42f395c79cc833985c7da082c572f4
3
+ metadata.gz: fd3f7e1ef08e3dd6db6362747a86a4adbff4acd42a90bd251bbde583c01d5eca
4
+ data.tar.gz: 57c823093ded9ae1ec66fa7dcb6741385fd450072aa59eac0cf962ed0e32b74e
5
5
  SHA512:
6
- metadata.gz: ae433f9f555ceee2b68121953086c7de1e340773ccd1dc802a254126a7bcee94f7f77d2f28427b29e89a6f2e738f9b7aeb5ec709951eb84c150de49bff58ef9c
7
- data.tar.gz: 65a9c8f2be649a18223f3f97caf10b628155f6e0ac54b7891aba504616084eaa6ef85f79f7ac96ff55d7d057d18070bc3a84e527a0ba4b0faac276c80509e74b
6
+ metadata.gz: 92ae6575db90c03567fac3aa2b31d7350c1f616c011dc77c4a17c1cbb4cabc7ab2d630ac7a2311a8f6e341e08ec9fc1c26f162db047034f5122407bf0455185c
7
+ data.tar.gz: 90d6f23aa9224096af1b06a7aaa53a2290e4f125076fedcc58a685829b05e75b68e3d46218842e7ea1d337db01583a149d4f4363a1f7271fec115cbf5ea79f65
data/Gemfile CHANGED
@@ -5,6 +5,7 @@ source 'https://rubygems.org'
5
5
  # Specify your gem's dependencies in riker.gemspec
6
6
  gemspec
7
7
 
8
+ gem 'pry', '~> 0.14'
8
9
  gem 'rake', '~> 13.0'
9
10
  gem 'rspec', '~> 3.0'
10
11
  gem 'rubocop'
data/Gemfile.lock CHANGED
@@ -1,17 +1,22 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- riker (0.1.0.pre2)
4
+ riker (0.1.0.pre5)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
9
  ast (2.4.2)
10
+ coderay (1.1.3)
10
11
  diff-lcs (1.5.0)
11
12
  json (2.6.2)
13
+ method_source (1.0.0)
12
14
  parallel (1.22.1)
13
15
  parser (3.1.2.1)
14
16
  ast (~> 2.4.1)
17
+ pry (0.14.1)
18
+ coderay (~> 1.1)
19
+ method_source (~> 1.0)
15
20
  rainbow (3.1.1)
16
21
  rake (13.0.6)
17
22
  regexp_parser (2.5.0)
@@ -49,6 +54,7 @@ PLATFORMS
49
54
  x86_64-linux
50
55
 
51
56
  DEPENDENCIES
57
+ pry (~> 0.14)
52
58
  rake (~> 13.0)
53
59
  riker!
54
60
  rspec (~> 3.0)
data/README.md CHANGED
@@ -12,7 +12,7 @@ High-Performance, Dependency-Free Command Pattern For Ruby
12
12
  ### In your gemfile:
13
13
 
14
14
  ```ruby
15
- gem 'riker', '0.1.0.pre3'
15
+ gem 'riker', '0.1.0.pre5'
16
16
  ```
17
17
 
18
18
  ### In your code:
@@ -26,6 +26,11 @@ class SimpleGreeting
26
26
  param :punctuation, default: '.'
27
27
 
28
28
  execute do
29
+ if first_name == 'Voldemort'
30
+ errors.add(:first_name, 'He who shall not be named!')
31
+ return
32
+ end
33
+
29
34
  return "Hello #{first_name}#{punctuation}" if last_name.nil?
30
35
 
31
36
  "Hello #{first_name} #{last_name}#{punctuation}"
@@ -44,6 +49,24 @@ SimpleGreeting.run!(first_name: 'Will', last_name: 'Riker')
44
49
 
45
50
  SimpleGreeting.run!(first_name: 'Will', last_name: 'Riker', punctuation: '!')
46
51
  # => "Hello Will Riker!"
52
+
53
+ SimpleGreeting.run!(first_name: 'Voldemort')
54
+ # => Riker::Outcome::ExecutionError => e
55
+ # => e.errors.messages == ['He who shall not be named!']
56
+
57
+ outcome = SimpleGreeting.run(first_name: 'Will')
58
+ outcome.valid?
59
+ # => true
60
+ outcome.result
61
+ # => "Hello Will."
62
+
63
+ outcome = SimpleGreeting.run(first_name: 'Voldemort')
64
+ outcome.invalid?
65
+ # => true
66
+ outcome.result
67
+ # => nil
68
+ outcome.errors.messages
69
+ # => ['He who shall not be named!']
47
70
  ```
48
71
 
49
72
  ## Default Procs
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Riker
4
+ class Command
5
+ # Fallible Methods
6
+ #
7
+ # Every command has fallible functionality. This is
8
+ # how you can convey something has gone wrong to the
9
+ # caller of your command.
10
+ #
11
+ module FallibleMethods
12
+ # @return [Riker::Outcome::Errors]
13
+ def errors
14
+ @errors ||= Riker::Outcome::Errors.new
15
+ end
16
+
17
+ # @return [Boolean]
18
+ def errored?
19
+ defined?(@errors) && @errors.any?
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Riker
4
+ class Command
5
+ # Individual Function
6
+ #
7
+ # Repsonible for debugging and writing out functions
8
+ # for a command to provide the needed functionality
9
+ # that is setup for it.
10
+ #
11
+ class Function
12
+ # @param command [Riker::Command]
13
+ def initialize(command)
14
+ @command = command
15
+ end
16
+
17
+ # @return [Symbol]
18
+ def name
19
+ raise NotImplementedError
20
+ end
21
+
22
+ # @return [Riker::Command::FunctionDetails]
23
+ def details
24
+ raise NotImplementedError
25
+ end
26
+
27
+ private
28
+
29
+ # @return [Riker::Command]
30
+ attr_reader :command
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Riker
4
+ class Command
5
+ # Function Detail Data
6
+ #
7
+ # Holds information needed to write a function to a class
8
+ # with `class_eval` on a class object.
9
+ #
10
+ class FunctionDetails
11
+ # @return [String]
12
+ attr_reader :code
13
+
14
+ # @return [String]
15
+ attr_reader :file
16
+
17
+ # @return [Integer]
18
+ attr_reader :line
19
+
20
+ def initialize(code, file, line)
21
+ @code = code
22
+ @file = file
23
+ @line = line
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'run_bang_function'
4
+ require_relative 'initialize_function'
5
+ require_relative 'run_function'
6
+
7
+ module Riker
8
+ class Command
9
+ # Function Writer
10
+ #
11
+ # This is responsible for creating the functions that
12
+ # are needed to create a command pattern class.
13
+ #
14
+ class FunctionWriter
15
+ DEFAULT_FUNCTIONS = [
16
+ RunBangFunction,
17
+ RunFunction,
18
+ InitializeFunction
19
+ ].freeze
20
+
21
+ INSTANCE_METHOD_MODULES = [
22
+ FallibleMethods
23
+ ].freeze
24
+
25
+ # @return [Riker::Command]
26
+ attr_reader :command
27
+
28
+ # @return [Array<Riker::Command::Function>]
29
+ attr_reader :functions
30
+
31
+ # @param command [Riker::Command]
32
+ def initialize(command)
33
+ @command = command
34
+ @functions = DEFAULT_FUNCTIONS.map { |func| func.new(command) }
35
+ end
36
+
37
+ # @param klass [Class]
38
+ def write!(klass)
39
+ klass.define_method(:execute, &command.execute_block)
40
+ define_default_setters!(klass)
41
+ define_attr_readers!(klass)
42
+ write_functions!(klass)
43
+ include_instance_methods!(klass)
44
+ end
45
+
46
+ private
47
+
48
+ # @param klass [Class]
49
+ def write_functions!(klass)
50
+ functions.each do |function|
51
+ details = function.details
52
+ klass.class_eval(details.code, details.file, details.line)
53
+ end
54
+ end
55
+
56
+ # @param klass [Class]
57
+ def define_attr_readers!(klass)
58
+ klass.attr_reader(*command.parameters.map(&:name))
59
+ end
60
+
61
+ # @param klass [Class]
62
+ def define_default_setters!(klass)
63
+ command.parameters.each do |param|
64
+ param.default.build_default_function!(klass)
65
+ end
66
+ end
67
+
68
+ # @param klass [Class]
69
+ def include_instance_methods!(klass)
70
+ INSTANCE_METHOD_MODULES.each do |mod|
71
+ klass.include(mod)
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Riker
4
+ class Command
5
+ # Run!
6
+ #
7
+ # Represents the `initialize` method for your command
8
+ #
9
+ class InitializeFunction < Function
10
+ # @return [Symbol]
11
+ def name
12
+ :initialize
13
+ end
14
+
15
+ # @return [Riker::Command::FunctionDetails]
16
+ def details
17
+ FunctionDetails.new(<<~RUBY, __FILE__, __LINE__ + 1)
18
+ def initialize(#{command.parameters.ctor_args}) # def initialize(foo:)
19
+ #{command.parameters.variable_sets} # @foo = foo
20
+ end # end
21
+ RUBY
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Riker
4
+ class Command
5
+ # Command Parameters
6
+ #
7
+ # This is responsible for keeping track of the command's
8
+ # parameters. This includes how they are used and applied
9
+ # to the construction of a command.
10
+ #
11
+ class Parameters
12
+ include Enumerable
13
+ class ParamNameTaken < ::Riker::Error; end
14
+ class InvalidParamName < ::Riker::Error; end
15
+ class ReservedAttributeName < ::Riker::Error; end
16
+
17
+ RESERVED_ATTR_NAMES = %i[
18
+ errors
19
+ ].to_set.freeze
20
+
21
+ def initialize
22
+ # @var [Hash<Symbol, Parameter>]
23
+ @params = {}
24
+ end
25
+
26
+ # @param name [Symbol]
27
+ # @return [Parameters]
28
+ #
29
+ def add(name, **options)
30
+ validate_name!(name)
31
+ @params[name] = Parameter.new(name, **options)
32
+
33
+ self
34
+ end
35
+
36
+ # @return [String]
37
+ def ctor_args
38
+ map(&:ctor_arg).join(', ')
39
+ end
40
+
41
+ # @return [String]
42
+ def variable_sets
43
+ map(&:variable_set).join("\n")
44
+ end
45
+
46
+ # @yield [Parameter]
47
+ def each(&block)
48
+ @params.values.each(&block)
49
+ end
50
+
51
+ private
52
+
53
+ def validate_name!(name)
54
+ raise InvalidParamName unless name.is_a?(Symbol)
55
+ raise ReservedAttributeName if RESERVED_ATTR_NAMES.include?(name)
56
+ raise ParamNameTaken if @params.key?(name)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Riker
4
+ class Command
5
+ # Run!
6
+ #
7
+ # Represents the `run!` static method for your command
8
+ #
9
+ class RunBangFunction < Function
10
+ # @return [Symbol]
11
+ def name
12
+ :run!
13
+ end
14
+
15
+ # @return [Riker::Command::FunctionDetails]
16
+ def details
17
+ FunctionDetails.new(<<~RUBY, __FILE__, __LINE__ + 1)
18
+ def self.run!(**arguments) # def self.run!(**arguments)
19
+ command = new(**arguments) # command = new(**arguments)
20
+ result = command.execute # result = command.execute
21
+ if command.errored? # if command.errored?
22
+ command.errors.raise! # command.errors.raise!
23
+ end # end
24
+ result # result
25
+ end # end
26
+ RUBY
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Riker
4
+ class Command
5
+ # Run!
6
+ #
7
+ # Represents the `run!` static method for your command
8
+ #
9
+ class RunFunction < Function
10
+ # @return [Symbol]
11
+ def name
12
+ :run
13
+ end
14
+
15
+ # @return [Riker::Command::FunctionDetails]
16
+ def details
17
+ FunctionDetails.new(<<~RUBY, __FILE__, __LINE__ + 1)
18
+ def self.run(**arguments) # def self.run!(**arguments)
19
+ command = new(**arguments) # command = new(**arguments)
20
+ result = command.execute # result = command.execute
21
+ if command.errored? # if command.errored?
22
+ Riker::Outcome.invalid(command.errors) # Riker::Outcome.invalid(command.errors)
23
+ else # else
24
+ Riker::Outcome.valid(result) # Riker::Outcome.valid(result)
25
+ end # end
26
+ end # end
27
+ RUBY
28
+ end
29
+ end
30
+ end
31
+ end
data/lib/riker/command.rb CHANGED
@@ -1,5 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative 'command/parameters'
4
+ require_relative 'command/fallible_methods'
5
+ require_relative 'command/function'
6
+ require_relative 'command/function_details'
7
+ require_relative 'command/function_writer'
8
+
3
9
  module Riker
4
10
  # Command Builder
5
11
  #
@@ -7,56 +13,18 @@ module Riker
7
13
  # track of the build of a command in your application
8
14
  #
9
15
  class Command
10
- # @return [Riker::CommandParameters]
16
+ # @return [Riker::Command::Parameters]
11
17
  attr_reader :parameters
12
18
 
19
+ # @return [Riker::Command::FunctionWriter]
20
+ attr_reader :function_writer
21
+
13
22
  # @return [Proc, nil]
14
23
  attr_accessor :execute_block
15
24
 
16
25
  def initialize
17
- @parameters = CommandParameters.new
18
- end
19
-
20
- # @param klass [Class]
21
- def build!(klass)
22
- klass.define_method(:execute, &execute_block)
23
- define_default_setters!(klass)
24
- define_init!(klass)
25
- define_run_bang!(klass)
26
- define_attr_readers!(klass)
27
- end
28
-
29
- private
30
-
31
- # @param klass [Class]
32
- def define_init!(klass)
33
- klass.class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
34
- def initialize(#{parameters.ctor_args}) # def initialize(foo:)
35
- #{parameters.variable_sets} # @foo = foo
36
- end # end
37
- RUBY
38
- end
39
-
40
- # @param klass [Class]
41
- def define_run_bang!(klass)
42
- klass.class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
43
- def self.run!(**arguments) # def initialize(**arguments)
44
- command = new(**arguments) # command = new(**arguments)
45
- command.execute # command.execute
46
- end # end
47
- RUBY
48
- end
49
-
50
- # @param klass [Class]
51
- def define_attr_readers!(klass)
52
- klass.attr_reader(*parameters.map(&:name))
53
- end
54
-
55
- # @param klass [Class]
56
- def define_default_setters!(klass)
57
- parameters.each do |param|
58
- param.default.build_default_function!(klass)
59
- end
26
+ @parameters = Parameters.new
27
+ @function_writer = FunctionWriter.new(self)
60
28
  end
61
29
  end
62
30
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Riker
4
+ class Outcome
5
+ # Outcome Errors
6
+ #
7
+ # A wrapper to keep track of and report on errors
8
+ # that happened during the execution of a command.
9
+ #
10
+ class Errors
11
+ # @!method any?
12
+ # @return [Boolean]
13
+ # @!method none?
14
+ # @return [Boolean]
15
+ extend Forwardable
16
+ def_delegators :@errors, :any?, :none?
17
+
18
+ def initialize
19
+ @errors = Hash.new { |hash, key| hash[key] = [] }
20
+ end
21
+
22
+ # @param key [Symbol]
23
+ # @param error [String]
24
+ # @return [void]
25
+ def add(key, error)
26
+ @errors[key] << error
27
+
28
+ nil
29
+ end
30
+
31
+ # @return [Array<String>]
32
+ def messages
33
+ @errors.values.flatten!
34
+ end
35
+
36
+ # @raise [Riker::ExecutionError]
37
+ def raise!
38
+ raise as_execution_error
39
+ end
40
+
41
+ private
42
+
43
+ def as_execution_error
44
+ Riker::Outcome::ExecutionError.new(self)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Riker
4
+ class Outcome
5
+ # Execution Error
6
+ #
7
+ # This exception is raised when a problem has happened
8
+ # with your command. It is the result normall of having
9
+ # errors.
10
+ #
11
+ # @see Riker::Command::FallibleMethods
12
+ #
13
+ class ExecutionError < Error
14
+ # @return [Riker::Outcome::Errors]
15
+ attr_reader :errors
16
+
17
+ # @param errors [Riker::Outcome::Errors]
18
+ def initialize(errors)
19
+ super()
20
+ @errors = errors
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'outcome/errors'
4
+ require_relative 'outcome/execution_error'
5
+
6
+ module Riker
7
+ # Wrapped Outcome of a Command
8
+ #
9
+ # Commands may be fallible; and in that case
10
+ # they return an outcome that will either detail
11
+ # the errors that came up during execution or the
12
+ # expected data if it was success.
13
+ #
14
+ class Outcome
15
+ # @return [Object]
16
+ attr_reader :result
17
+
18
+ class << self
19
+ # @param result [Object]
20
+ # @return [Riker::Outcome]
21
+ def valid(result)
22
+ new(:valid, result)
23
+ end
24
+
25
+ def invalid(errors)
26
+ new(:invalid, errors)
27
+ end
28
+
29
+ private :new
30
+ end
31
+
32
+ # @param state [:valid, :invalid]
33
+ # @data [Object, Riker::Outcome::Errors]
34
+ def initialize(state, data)
35
+ if state == :valid
36
+ @result = data
37
+ else
38
+ @errors = data
39
+ end
40
+ end
41
+
42
+ # @return [Boolean]
43
+ def valid?
44
+ return true unless defined?(@errors)
45
+
46
+ @errors.none?
47
+ end
48
+
49
+ # @return [Boolean]
50
+ def invalid?
51
+ return false unless defined?(@errors)
52
+
53
+ @errors.any?
54
+ end
55
+
56
+ # @return [Riker::Outcome::Errors]
57
+ def errors
58
+ @errors ||= Errors.new
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Riker
4
+ class Parameter
5
+ # Default Parameter Value
6
+ #
7
+ # Sometimes we want to have parameters default to sensible
8
+ # defaults. This class's responsibility is to keep track
9
+ # this and set's up work to ensure defaults setup properly.
10
+ #
11
+ class DefaultValue
12
+ # @return [Symbol]
13
+ attr_reader :name
14
+
15
+ # @return [BasicObject]
16
+ def self.no_value
17
+ :__no_default__
18
+ end
19
+
20
+ # @param name [Symbol]
21
+ # @param value [Object, Proc]
22
+ def initialize(name, value)
23
+ @name = name
24
+ @present = value != :__no_default__
25
+ @value_proc = value.is_a?(Proc) ? value : -> { value }
26
+ end
27
+
28
+ # @return [Boolean]
29
+ def present?
30
+ @present
31
+ end
32
+
33
+ # @return [Symbol, nil]
34
+ def function_name
35
+ return unless present?
36
+
37
+ @function_name ||= :"default_value_for_#{name}"
38
+ end
39
+
40
+ def build_default_function!(klass)
41
+ return unless present?
42
+
43
+ klass.define_method(function_name, &@value_proc)
44
+ klass.send(:private, function_name)
45
+ end
46
+ end
47
+ end
48
+ end
data/lib/riker/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Riker
4
- VERSION = '0.1.0.pre3'
4
+ VERSION = '0.1.0.pre5'
5
5
  end
data/lib/riker.rb CHANGED
@@ -1,10 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'forwardable'
4
+ require 'set'
5
+
3
6
  require_relative 'riker/version'
4
7
  require_relative 'riker/error'
5
8
  require_relative 'riker/command'
6
- require_relative 'riker/command_parameters'
7
9
  require_relative 'riker/parameter'
10
+ require_relative 'riker/outcome'
8
11
 
9
12
  # The Commander of the USS Enterprise
10
13
  module Riker
@@ -26,6 +29,6 @@ module Riker
26
29
  raise Error, "execute block already called for #{self}!" if command.execute_block
27
30
 
28
31
  command.execute_block = block
29
- command.build!(self)
32
+ command.function_writer.write!(self)
30
33
  end
31
34
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: riker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.pre3
4
+ version: 0.1.0.pre5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Benjamin Falk
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-09-28 00:00:00.000000000 Z
11
+ date: 2022-10-21 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: High-Performance, Dependency-Free Command Pattern For Ruby
14
14
  email:
@@ -29,9 +29,20 @@ files:
29
29
  - bin/setup
30
30
  - lib/riker.rb
31
31
  - lib/riker/command.rb
32
- - lib/riker/command_parameters.rb
32
+ - lib/riker/command/fallible_methods.rb
33
+ - lib/riker/command/function.rb
34
+ - lib/riker/command/function_details.rb
35
+ - lib/riker/command/function_writer.rb
36
+ - lib/riker/command/initialize_function.rb
37
+ - lib/riker/command/parameters.rb
38
+ - lib/riker/command/run_bang_function.rb
39
+ - lib/riker/command/run_function.rb
33
40
  - lib/riker/error.rb
41
+ - lib/riker/outcome.rb
42
+ - lib/riker/outcome/errors.rb
43
+ - lib/riker/outcome/execution_error.rb
34
44
  - lib/riker/parameter.rb
45
+ - lib/riker/parameter/default_value.rb
35
46
  - lib/riker/version.rb
36
47
  - sig/riker.rbs
37
48
  homepage:
@@ -55,7 +66,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
55
66
  - !ruby/object:Gem::Version
56
67
  version: 1.3.1
57
68
  requirements: []
58
- rubygems_version: 3.1.6
69
+ rubygems_version: 3.3.7
59
70
  signing_key:
60
71
  specification_version: 4
61
72
  summary: High-Performance, Dependency-Free Command Pattern For Ruby
@@ -1,52 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Riker
4
- # Command Parameters
5
- #
6
- # This is responsible for keeping track of the command's
7
- # parameters. This includes how they are used and applied
8
- # to the construction of a command.
9
- #
10
- class CommandParameters
11
- include Enumerable
12
- class ParamNameTaken < ::Riker::Error; end
13
- class InvalidParamName < ::Riker::Error; end
14
-
15
- def initialize
16
- # @var [Hash<Symbol, Parameter>]
17
- @params = {}
18
- end
19
-
20
- # @param name [Symbol]
21
- # @return [Parameters]
22
- #
23
- def add(name, **options)
24
- validate_name!(name)
25
- @params[name] = Parameter.new(name, **options)
26
-
27
- self
28
- end
29
-
30
- # @return [String]
31
- def ctor_args
32
- map(&:ctor_arg).join(', ')
33
- end
34
-
35
- # @return [String]
36
- def variable_sets
37
- map(&:variable_set).join("\n")
38
- end
39
-
40
- # @yield [Parameter]
41
- def each(&block)
42
- @params.values.each(&block)
43
- end
44
-
45
- private
46
-
47
- def validate_name!(name)
48
- raise InvalidParamName unless name.is_a?(Symbol)
49
- raise ParamNameTaken if @params.key?(name)
50
- end
51
- end
52
- end