activeinteractor 1.0.0.beta.7 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (102) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +12 -0
  3. data/CHANGELOG.md +50 -158
  4. data/README.md +13 -856
  5. data/lib/active_interactor.rb +61 -4
  6. data/lib/active_interactor/base.rb +26 -20
  7. data/lib/active_interactor/config.rb +36 -18
  8. data/lib/active_interactor/configurable.rb +17 -9
  9. data/lib/active_interactor/context/attributes.rb +73 -26
  10. data/lib/active_interactor/context/base.rb +236 -65
  11. data/lib/active_interactor/context/loader.rb +20 -15
  12. data/lib/active_interactor/context/status.rb +38 -56
  13. data/lib/active_interactor/error.rb +15 -7
  14. data/lib/active_interactor/interactor/callbacks.rb +174 -160
  15. data/lib/active_interactor/interactor/context.rb +279 -87
  16. data/lib/active_interactor/interactor/perform.rb +256 -0
  17. data/lib/active_interactor/interactor/worker.rb +19 -14
  18. data/lib/active_interactor/models.rb +65 -0
  19. data/lib/active_interactor/organizer/base.rb +18 -0
  20. data/lib/active_interactor/organizer/callbacks.rb +153 -0
  21. data/lib/active_interactor/organizer/interactor_interface.rb +38 -26
  22. data/lib/active_interactor/organizer/interactor_interface_collection.rb +35 -32
  23. data/lib/active_interactor/organizer/organize.rb +67 -0
  24. data/lib/active_interactor/organizer/perform.rb +93 -0
  25. data/lib/active_interactor/rails.rb +0 -10
  26. data/lib/active_interactor/rails/orm/active_record.rb +1 -1
  27. data/lib/active_interactor/rails/railtie.rb +8 -11
  28. data/lib/active_interactor/version.rb +2 -1
  29. data/lib/rails/generators/active_interactor.rb +1 -38
  30. data/lib/rails/generators/active_interactor/application_context_generator.rb +21 -0
  31. data/lib/rails/generators/active_interactor/application_interactor_generator.rb +5 -15
  32. data/lib/rails/generators/active_interactor/application_organizer_generator.rb +21 -0
  33. data/lib/rails/generators/active_interactor/base.rb +29 -0
  34. data/lib/rails/generators/active_interactor/generator.rb +21 -0
  35. data/lib/rails/generators/active_interactor/install_generator.rb +2 -9
  36. data/lib/rails/generators/interactor/context/rspec_generator.rb +3 -10
  37. data/lib/rails/generators/interactor/context/test_unit_generator.rb +4 -11
  38. data/lib/rails/generators/interactor/context_generator.rb +7 -10
  39. data/lib/rails/generators/interactor/generates_context.rb +28 -0
  40. data/lib/rails/generators/interactor/interactor_generator.rb +8 -10
  41. data/lib/rails/generators/interactor/organizer_generator.rb +8 -12
  42. data/lib/rails/generators/interactor/rspec_generator.rb +2 -9
  43. data/lib/rails/generators/interactor/test_unit_generator.rb +3 -10
  44. data/lib/rails/generators/{active_interactor/templates/initializer.erb → templates/active_interactor.erb} +3 -11
  45. data/lib/rails/generators/{active_interactor/templates → templates}/application_context.rb +0 -0
  46. data/lib/rails/generators/{active_interactor/templates → templates}/application_interactor.rb +0 -0
  47. data/lib/rails/generators/templates/application_organizer.rb +4 -0
  48. data/lib/rails/generators/{interactor/templates → templates}/context.erb +0 -0
  49. data/lib/rails/generators/{interactor/context/templates/rspec.erb → templates/context_spec.erb} +0 -0
  50. data/lib/rails/generators/{interactor/context/templates/test_unit.erb → templates/context_test_unit.erb} +0 -0
  51. data/lib/rails/generators/{interactor/templates → templates}/interactor.erb +0 -0
  52. data/lib/rails/generators/{interactor/templates/rspec.erb → templates/interactor_spec.erb} +0 -0
  53. data/lib/rails/generators/{interactor/templates/test_unit.erb → templates/interactor_text_unit.erb} +0 -0
  54. data/lib/rails/generators/{interactor/templates → templates}/organizer.erb +0 -0
  55. data/spec/active_interactor/base_spec.rb +3 -3
  56. data/spec/active_interactor/interactor/{perform_options_spec.rb → perform/options_spec.rb} +1 -1
  57. data/spec/active_interactor/interactor/worker_spec.rb +14 -15
  58. data/spec/active_interactor/{organizer_spec.rb → organizer/base_spec.rb} +27 -17
  59. data/spec/integration/a_basic_interactor_spec.rb +106 -0
  60. data/spec/integration/a_basic_organizer_spec.rb +97 -0
  61. data/spec/integration/a_failing_interactor_spec.rb +42 -0
  62. data/spec/integration/active_record_integration_spec.rb +9 -9
  63. data/spec/integration/an_interactor_with_after_context_validation_callbacks_spec.rb +69 -0
  64. data/spec/integration/an_interactor_with_after_perform_callbacks_spec.rb +30 -0
  65. data/spec/integration/an_interactor_with_after_rollback_callbacks_spec.rb +33 -0
  66. data/spec/integration/an_interactor_with_an_existing_context_class_spec.rb +49 -0
  67. data/spec/integration/an_interactor_with_around_perform_callbacks_spec.rb +35 -0
  68. data/spec/integration/an_interactor_with_around_rollback_callbacks_spec.rb +39 -0
  69. data/spec/integration/an_interactor_with_before_perform_callbacks_spec.rb +30 -0
  70. data/spec/integration/an_interactor_with_before_rollback_callbacks_spec.rb +33 -0
  71. data/spec/integration/an_interactor_with_validations_on_called_spec.rb +40 -0
  72. data/spec/integration/an_interactor_with_validations_on_calling_spec.rb +36 -0
  73. data/spec/integration/an_interactor_with_validations_spec.rb +93 -0
  74. data/spec/integration/an_organizer_performing_in_parallel_spec.rb +48 -0
  75. data/spec/integration/an_organizer_with_after_each_callbacks_spec.rb +34 -0
  76. data/spec/integration/an_organizer_with_around_each_callbacks_spec.rb +39 -0
  77. data/spec/integration/an_organizer_with_before_each_callbacks_spec.rb +34 -0
  78. data/spec/integration/an_organizer_with_conditionally_organized_interactors_spec.rb +314 -0
  79. data/spec/spec_helper.rb +8 -12
  80. data/spec/support/coverage.rb +4 -0
  81. data/spec/support/coverage/reporters.rb +11 -0
  82. data/spec/support/coverage/reporters/codacy.rb +39 -0
  83. data/spec/support/coverage/reporters/simple_cov.rb +54 -0
  84. data/spec/support/coverage/runner.rb +66 -0
  85. data/spec/support/helpers/factories.rb +1 -1
  86. data/spec/support/shared_examples/a_class_with_interactor_callback_methods_example.rb +8 -8
  87. data/spec/support/shared_examples/a_class_with_interactor_context_methods_example.rb +5 -5
  88. data/spec/support/shared_examples/a_class_with_interactor_methods_example.rb +2 -2
  89. data/spec/support/shared_examples/a_class_with_organizer_callback_methods_example.rb +3 -3
  90. metadata +83 -40
  91. data/lib/active_interactor/interactor.rb +0 -84
  92. data/lib/active_interactor/interactor/perform_options.rb +0 -29
  93. data/lib/active_interactor/organizer.rb +0 -269
  94. data/lib/active_interactor/rails/config.rb +0 -45
  95. data/lib/active_interactor/rails/models.rb +0 -58
  96. data/lib/rails/generators/active_interactor/templates/application_organizer.rb +0 -4
  97. data/spec/active_interactor/rails/config_spec.rb +0 -29
  98. data/spec/active_interactor/rails_spec.rb +0 -24
  99. data/spec/integration/basic_callback_integration_spec.rb +0 -355
  100. data/spec/integration/basic_context_integration_spec.rb +0 -73
  101. data/spec/integration/basic_integration_spec.rb +0 -570
  102. data/spec/integration/basic_validations_integration_spec.rb +0 -204
@@ -1,10 +1,31 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'active_model'
4
+ require 'active_support/callbacks'
5
+ require 'active_support/core_ext/array/extract_options'
6
+ require 'active_support/core_ext/class/attribute'
7
+ require 'active_support/core_ext/string/inflections'
3
8
  require 'active_support/dependencies/autoload'
9
+ require 'logger'
10
+ require 'ostruct'
4
11
 
5
- require 'active_interactor/version'
12
+ require 'active_interactor/configurable'
6
13
  require 'active_interactor/config'
14
+ require 'active_interactor/version'
7
15
 
16
+ # An {Base interactor} is a simple, single-purpose service object. {Base Interactors} can be used to reduce the
17
+ # responsibility of your controllers, workers, and models and encapsulate your application's
18
+ # {https://en.wikipedia.org/wiki/Business_logic business logic}. Each {Base interactor} represents one thing that your
19
+ # application does.
20
+ #
21
+ # Each {Base interactor} has it's own immutable {Context::Base context} which contains everything the
22
+ # {Base interactor} needs to do its work. When an {Base interactor} does its single purpose, it affects its given
23
+ # {Context::Base context}.
24
+ #
25
+ # @see https://github.com/aaronmallen/activeinteractor/wiki Usage
26
+ #
27
+ # ## License
28
+ #
8
29
  # Copyright (c) 2019 Aaron Allen
9
30
  #
10
31
  # Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -29,18 +50,54 @@ module ActiveInteractor
29
50
 
30
51
  autoload :Base
31
52
 
32
- # ActiveInteractor::Context classes
53
+ # {Context::Base Context} classes and modules
54
+ #
55
+ # @see https://github.com/aaronmallen/activeinteractor/wiki/Context Context
56
+ #
33
57
  # @author Aaron Allen <hello@aaronmallen.me>
34
- # @since 0.0.1
58
+ # @since 0.1.0
35
59
  module Context
36
60
  extend ActiveSupport::Autoload
37
61
 
62
+ autoload :Attributes
38
63
  autoload :Base
39
64
  autoload :Loader
40
65
  autoload :Status
41
66
  end
42
67
 
43
- autoload :Organizer
68
+ # {Base Interactor} classes and modules
69
+ #
70
+ # @see https://github.com/aaronmallen/activeinteractor/wiki/Interactors Interactors
71
+ #
72
+ # @author Aaron Allen <hello@aaronmallen.me>
73
+ # @since 0.1.0
74
+ module Interactor
75
+ extend ActiveSupport::Autoload
76
+
77
+ autoload :Callbacks
78
+ autoload :Context
79
+ autoload :Perform
80
+ autoload :Worker
81
+ end
82
+
83
+ autoload :Models
84
+
85
+ # {Organizer::Base Organizer} classes and modules
86
+ #
87
+ # @see https://github.com/aaronmallen/activeinteractor/wiki/Interactors#organizers Organizers
88
+ #
89
+ # @author Aaron Allen <hello@aaronmallen.me>
90
+ # @since 0.1.0
91
+ module Organizer
92
+ extend ActiveSupport::Autoload
93
+
94
+ autoload :Base
95
+ autoload :Callbacks
96
+ autoload :InteractorInterface
97
+ autoload :InteractorInterfaceCollection
98
+ autoload :Organize
99
+ autoload :Perform
100
+ end
44
101
 
45
102
  eager_autoload do
46
103
  autoload :Error
@@ -1,29 +1,35 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_interactor/interactor'
4
-
5
3
  module ActiveInteractor
6
- # The base interactor class. All interactors should inherit from
7
- # {Base}.
4
+ # The base class all {Base interactors} should inherit from.
5
+ #
6
+ # When {Base} is loaded by your application an
7
+ # {https://api.rubyonrails.org/classes/ActiveSupport/LazyLoadHooks.html ActiveSupport load hook} is called
8
+ # with `:active_interactor` and {Base}.
9
+ #
8
10
  # @author Aaron Allen <hello@aaronmallen.me>
9
- # @since 0.0.1
10
- # @example a basic interactor
11
- # class MyInteractor < ActiveInteractor::Base
12
- # def perform
13
- # context.called = true
14
- # end
15
- # end
11
+ # @since 0.1.0
16
12
  #
17
- # MyInteractor.perform
18
- # #=> <MyInteractor::Context called=true>
13
+ # @example a basic {Base interactor}
14
+ # class MyInteractor < ActiveInteractor::Base
15
+ # def perform
16
+ # # TODO: implement the perform method
17
+ # end
18
+ #
19
+ # def rollback
20
+ # # TODO: implement the rollback method
21
+ # end
22
+ # end
19
23
  class Base
20
- include Interactor
24
+ extend ActiveInteractor::Interactor::Callbacks::ClassMethods
25
+ extend ActiveInteractor::Interactor::Context::ClassMethods
26
+ extend ActiveInteractor::Interactor::Perform::ClassMethods
21
27
 
22
- # Duplicates an instance of {Base}
23
- # @since 1.0.0-alpha.1
24
- # @return [Base] a new instance of {Base}
25
- def dup
26
- self.class.new(context.dup)
27
- end
28
+ include ActiveSupport::Callbacks
29
+ include ActiveInteractor::Interactor::Callbacks
30
+ include ActiveInteractor::Interactor::Context
31
+ include ActiveInteractor::Interactor::Perform
28
32
  end
33
+
34
+ ActiveSupport.run_load_hooks(:active_interactor, Base)
29
35
  end
@@ -1,41 +1,59 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'logger'
4
-
5
- require 'active_interactor/configurable'
6
-
7
3
  module ActiveInteractor
8
4
  # The ActiveInteractor configuration object
5
+ #
9
6
  # @author Aaron Allen <hello@aaronmallen.me>
10
7
  # @since 1.0.0
8
+ #
11
9
  # @!attribute [rw] logger
12
- # @return [Logger] an instance of Logger
10
+ # The logger instance to use for logging.
11
+ #
12
+ # @since 1.0.0
13
+ #
14
+ # @return [Class] an instance of Logger.
15
+ #
16
+ # @!method initialize(options = {})
17
+ # Initialize a new instance of {Config}
18
+ #
19
+ # @since 1.0.0
20
+ #
21
+ # @param options [Hash{Symbol=>*}] the attributes to assign to {Config}
22
+ # @option options [Class] :logger (Logger.new(STDOUT)) the {Config#logger} attribute
23
+ # @return [Config] a new instance of {Config}
13
24
  class Config
14
- include Configurable
25
+ include ActiveInteractor::Configurable
15
26
  defaults logger: Logger.new(STDOUT)
16
27
  end
17
28
 
18
29
  # The ActiveInteractor configuration
19
- # @since 0.0.1
20
- # @return [ActiveInteractor::Config] the configuration instance
30
+ #
31
+ # @since 0.1.0
32
+ #
33
+ # @return [Config] a {Config} instance
21
34
  def self.config
22
- @config ||= Config.new
35
+ @config ||= ActiveInteractor::Config.new
23
36
  end
24
37
 
25
- # Configures the ActiveInteractor gem
26
- # @since 0.0.1
38
+ # Configure the ActiveInteractor gem
39
+ #
40
+ # @since 0.1.0
41
+ #
27
42
  # @example Configure ActiveInteractor
28
- # ActiveInteractor.configure do |config|
29
- # config.logger = Rails.logger
30
- # end
31
- # @yield [ActiveInteractor#config]
43
+ # require 'active_interactor'
44
+ # ActiveInteractor.configure do |config|
45
+ # config.logger = ::Rails.logger
46
+ # end
47
+ # @yield [#config]
32
48
  def self.configure
33
49
  yield config
34
50
  end
35
51
 
36
- # The ActiveInteractor logger object
37
- # @since 0.0.1
38
- # @return [Logger] an instance of Logger
52
+ # The logger instance to use for logging
53
+ #
54
+ # @since 0.1.0
55
+ #
56
+ # @return [Class] the {Config#logger #config#logger} instance
39
57
  def self.logger
40
58
  config.logger
41
59
  end
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_support/core_ext/class/attribute'
4
-
5
3
  module ActiveInteractor
6
- # Methods for configurable objects
4
+ # Configurable object methods. Because {Configurable} is a module classes should include {Configurable} rather than
5
+ # inherit from it.
6
+ #
7
+ # @api private
7
8
  # @author Aaron Allen <hello@aaronmallen.me>
8
9
  # @since 1.0.0
9
10
  module Configurable
@@ -13,11 +14,18 @@ module ActiveInteractor
13
14
  end
14
15
  end
15
16
 
16
- # Class methods for configuable objects
17
+ # Configurable object class methods. Because {ClassMethods} is a module classes should extend {ClassMethods} rather
18
+ # than inherit from it.
19
+ #
20
+ # @api private
21
+ # @author Aaron Allen <hello@aaronmallen.me>
22
+ # @since 1.0.0
17
23
  module ClassMethods
18
- # Set or get default options for a configurable object
19
- # @param options [Hash] the options to set for defaults
20
- # @return [Hash] the defaults
24
+ # Get or Set the default attributes for a {Configurable} class. This method will create an `attr_accessor` on
25
+ # the configurable class as well as set a default value for the attribute.
26
+ #
27
+ # @param options [Hash{Symbol=>*}, nil] the default options to set on the {Configurable} class
28
+ # @return [Hash{Symbol=>*}] the passed options or the set defaults if no options are passed.
21
29
  def defaults(options = {})
22
30
  return __defaults if options.empty?
23
31
 
@@ -34,8 +42,8 @@ module ActiveInteractor
34
42
  end
35
43
  end
36
44
 
37
- # @param options [Hash] the options for the configuration
38
- # @return [Configurable] a new instance of {Configurable}
45
+ # nodoc #
46
+ # @private
39
47
  def initialize(options = {})
40
48
  self.class.defaults.merge(options).each do |key, value|
41
49
  instance_variable_set("@#{key}", value)
@@ -2,31 +2,34 @@
2
2
 
3
3
  module ActiveInteractor
4
4
  module Context
5
- # Context attribute methods included by all {Context::Base}
5
+ # Context attribute methods. Because {Attributes} is a module classes should include {Attributes} rather than
6
+ # inherit from it.
7
+ #
6
8
  # @author Aaron Allen <hello@aaronmallen.me>
7
9
  # @since 0.1.4
8
10
  module Attributes
9
- def self.included(base)
10
- base.class_eval do
11
- extend ClassMethods
12
- end
13
- end
14
-
15
- # Context attribute class methods extended by all {Context::Base}
11
+ # Context attribute class methods. Because {ClassMethods} is a module classes should extend {ClassMethods} rather
12
+ # than inherit from it.
13
+ #
14
+ # @author Aaron Allen <hello@aaronmallen.me>
15
+ # @since 0.1.4
16
16
  module ClassMethods
17
- # Set or get attributes defined on the context class
18
- # @example Set attributes on a context class
19
- # class MyInteractor::Context < ActiveInteractor::Context::Base
17
+ # Get or set attributes on a {Base context} class
18
+ #
19
+ # @example Set attributes on a {Base context} class
20
+ # class MyContext < ActiveInteractor::Context::Base
20
21
  # attributes :first_name, :last_name
21
22
  # end
22
- # @example Get attributes defined on a context class
23
- # MyInteractor::Context.attributes
24
- # #=> [:first_name, :last_name]
23
+ #
24
+ # @example Get attributes defined on a {Base context} class
25
+ # MyContext.attributes
26
+ # #=> [:first_name, :last_name]
27
+ #
25
28
  # @return [Array<Symbol>] the defined attributes
26
29
  def attributes(*attributes)
27
30
  return __attributes if attributes.empty?
28
31
 
29
- @__attributes = __attributes.concat(attributes).compact.uniq.sort
32
+ @__attributes = __attributes.concat(attributes.map(&:to_sym)).compact.uniq.sort
30
33
  end
31
34
 
32
35
  private
@@ -36,27 +39,71 @@ module ActiveInteractor
36
39
  end
37
40
  end
38
41
 
39
- # Attributes defined on the instance
40
- # @example Get attributes defined on an instance
41
- # class MyInteractor::Context < ActiveInteractor::Context::Base
42
- # attributes :first_name, :last_name
43
- # end
42
+ # Initialize a new instance of {Base}
44
43
  #
45
- # class MyInteractor < ActiveInteractor::Base
46
- # def perform; end
44
+ # @param context [Hash, Base, Class] attributes to assign to the {Base context}
45
+ # @return [Base] a new instance of {Base}
46
+ def initialize(context = {})
47
+ merge_errors!(context.errors) if context.respond_to?(:errors)
48
+ copy_flags!(context)
49
+ copy_called!(context)
50
+ super
51
+ end
52
+
53
+ # Get values defined on the instance of {Base context} whose keys are defined on the {Base context} class'
54
+ # {ClassMethods#attributes .attributes}
55
+ #
56
+ # @example Get attributes defined on an instance of {Base context}
57
+ # class MyContext < ActiveInteractor::Context::Base
58
+ # attributes :first_name, :last_name
47
59
  # end
48
60
  #
49
- # result = MyInteractor.perform(first_name: 'Aaron', last_name: 'Allen', occupation: 'Software Nerd')
50
- # #=> <#MyInteractor::Context first_name='Aaron' last_name='Allen' occupation='Software Nerd'>
61
+ # context = MyContext.new(first_name: 'Aaron', last_name: 'Allen', occupation: 'Ruby Nerd')
62
+ # #=> <#MyContext first_name='Aaron' last_name='Allen' occupation='Ruby Nerd')
51
63
  #
52
- # result.attributes
64
+ # context.attributes
53
65
  # #=> { first_name: 'Aaron', last_name: 'Allen' }
54
- # @return [Hash{Symbol=>*}] the defined attributes and values
66
+ #
67
+ # context.occupation
68
+ # #=> 'Ruby Nerd'
69
+ #
70
+ # @return [Hash{Symbol => *}] the defined attributes and values
55
71
  def attributes
56
72
  self.class.attributes.each_with_object({}) do |attribute, hash|
57
73
  hash[attribute] = self[attribute] if self[attribute]
58
74
  end
59
75
  end
76
+
77
+ # Merge an instance of {Base context} into the calling {Base context} instance
78
+ #
79
+ # @since 1.0.0
80
+ #
81
+ # @example
82
+ # context = MyContext.new(first_name: 'Aaron', last_name: 'Allen')
83
+ # other_context = MyContext.new(last_name: 'Awesome')
84
+ # context.merge!(other_context)
85
+ # #=> <#MyContext first_name='Aaron' last_name='Awesome'>
86
+ #
87
+ # @param context [Class] a {Base context} instance to be merged
88
+ # @return [self] the {Base context} instance
89
+ def merge!(context)
90
+ merge_errors!(context.errors) if context.respond_to?(:errors)
91
+ copy_flags!(context)
92
+ context.each_pair do |key, value|
93
+ self[key] = value unless value.nil?
94
+ end
95
+ self
96
+ end
97
+
98
+ private
99
+
100
+ def merge_errors!(errors)
101
+ if errors.is_a? String
102
+ self.errors.add(:context, errors)
103
+ else
104
+ self.errors.merge!(errors)
105
+ end
106
+ end
60
107
  end
61
108
  end
62
109
  end
@@ -1,75 +1,246 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_model'
4
- require 'ostruct'
5
-
6
- require 'active_interactor/context/attributes'
7
-
8
3
  module ActiveInteractor
9
4
  module Context
10
- # The base context class. All interactor contexts should inherit from
11
- # {Context::Base}.
5
+ # The base {Base context} class all {Base context} objects should inherit from.
6
+ #
12
7
  # @author Aaron Allen <hello@aaronmallen.me>
13
- # @since 0.0.1
8
+ # @since 0.1.0
9
+ #
10
+ # @!method attribute_method?(attribute)
11
+ # @!scope class
12
+ # @since 0.1.0
13
+ # @see
14
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-attribute_method-3F
15
+ # ActiveModel::Validations::ClassMethods#attribute_method?
16
+ #
17
+ # @!method clear_validators!(attribute)
18
+ # @!scope class
19
+ # @since 0.1.0
20
+ # @see
21
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-clear_validators-21
22
+ # ActiveModel::Validations::ClassMethods#clear_validators!
23
+ #
24
+ # @!method validate(*args, &block)
25
+ # @!scope class
26
+ # @since 0.1.0
27
+ # @see
28
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validate
29
+ # ActiveModel::Validations::ClassMethods#validate
30
+ #
31
+ # @!method validates(*attributes)
32
+ # @!scope class
33
+ # @since 0.1.0
34
+ # @see
35
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates
36
+ # ActiveModel::Validations::ClassMethods#validates
37
+ #
38
+ # @!method validates!(*attributes)
39
+ # @!scope class
40
+ # @since 0.1.0
41
+ # @see
42
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates-21
43
+ # ActiveModel::Validations::ClassMethods#validates!
44
+ #
45
+ # @!method validates_absence_of(*attr_names)
46
+ # @!scope class
47
+ # @since 0.1.0
48
+ # @see
49
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html#method-i-validates_absence_of
50
+ # ActiveModel::Validations::HelperMethods#validates_absence_of
51
+ #
52
+ # @!method validates_acceptance_of(*attr_names)
53
+ # @!scope class
54
+ # @since 0.1.0
55
+ # @see
56
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html#method-i-validates_acceptance_of
57
+ # ActiveModel::Validations::HelperMethods#validates_acceptance_of
58
+ #
59
+ # @!method validates_confirmation_of(*attr_names)
60
+ # @!scope class
61
+ # @since 0.1.0
62
+ # @see
63
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html#method-i-validates_confirmation_of
64
+ # ActiveModel::Validations::HelperMethods#validates_confirmation_of
65
+ #
66
+ # @!method validates_each(*attr_names, &block)
67
+ # @!scope class
68
+ # @since 0.1.0
69
+ # @see
70
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates_each
71
+ # ActiveModel::Validations::ClassMethods#validates_each
72
+ #
73
+ # @!method validates_exclusion_of(*attr_names)
74
+ # @!scope class
75
+ # @since 0.1.0
76
+ # @see
77
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html#method-i-validates_exclusion_of
78
+ # ActiveModel::Validations::HelperMethods#validates_exclusion_of
79
+ #
80
+ # @!method validates_format_of(*attr_names)
81
+ # @!scope class
82
+ # @since 0.1.0
83
+ # @see
84
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html#method-i-validates_format_of
85
+ # ActiveModel::Validations::HelperMethods#validates_format_of
86
+ #
87
+ # @!method validates_inclusion_of(*attr_names)
88
+ # @!scope class
89
+ # @since 0.1.0
90
+ # @see
91
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html#method-i-validates_inclusion_of
92
+ # ActiveModel::Validations::HelperMethods#validates_inclusion_of
93
+ #
94
+ # @!method validates_length_of(*attr_names)
95
+ # @!scope class
96
+ # @since 0.1.0
97
+ # @see
98
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html#method-i-validates_length_of
99
+ # ActiveModel::Validations::HelperMethods#validates_length_of
100
+ #
101
+ # @!method validates_numericality_of(*attr_names)
102
+ # @!scope class
103
+ # @since 0.1.0
104
+ # @see
105
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html#method-i-validates_numericality_of
106
+ # ActiveModel::Validations::HelperMethods#validates_numericality_of
107
+ #
108
+ # @!method validates_presence_of(*attr_names)
109
+ # @!scope class
110
+ # @since 0.1.0
111
+ # @see
112
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html#method-i-validates_presence_of
113
+ # ActiveModel::Validations::HelperMethods#validates_presence_of
114
+ #
115
+ # @!method validates_size_of(*attr_names)
116
+ # @!scope class
117
+ # @since 0.1.0
118
+ # @see
119
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html#method-i-validates_size_of
120
+ # ActiveModel::Validations::HelperMethods#validates_size_of
121
+ #
122
+ # @!method validates_with(*args, &block)
123
+ # @!scope class
124
+ # @since 0.1.0
125
+ # @see
126
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates_with
127
+ # ActiveModel::Validations::ClassMethods#validates_with
128
+ #
129
+ # @!method validators
130
+ # @!scope class
131
+ # @since 0.1.0
132
+ # @see
133
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validators
134
+ # ActiveModel::Validations::ClassMethods#validators
135
+ #
136
+ # @!method validators_on(*attributes)
137
+ # @!scope class
138
+ # @since 0.1.0
139
+ # @see
140
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validators_on
141
+ # ActiveModel::Validations::ClassMethods#validators_on
142
+ #
143
+ # @!method errors
144
+ # @since 0.1.0
145
+ # @see
146
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations.html#method-i-errors
147
+ # ActiveModel::Validations#errors
148
+ #
149
+ # @!method invalid?(context = nil)
150
+ # @since 0.1.0
151
+ # @see
152
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations.html#method-i-invalid-3F
153
+ # ActiveModel::Validations#invalid?
154
+ #
155
+ # @!method valid?(context = nil)
156
+ # @since 0.1.0
157
+ # @see
158
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations.html#method-i-valid-3F
159
+ # ActiveModel::Validations#valid?
160
+ #
161
+ # @!method validate(context = nil)
162
+ # @since 0.1.0
163
+ # @see
164
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations.html#method-i-validate
165
+ # ActiveModel::Validations#validate
166
+ #
167
+ # @!method validate!(context = nil)
168
+ # @since 0.1.0
169
+ # @see
170
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations.html#method-i-validate-21
171
+ # ActiveModel::Validations#validate!
172
+ #
173
+ # @!method validates_absence_of(*attr_names)
174
+ # @since 0.1.0
175
+ # @see
176
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html#method-i-validates_absence_of
177
+ # ActiveModel::Validations::HelperMethods#validates_absence_of
178
+ #
179
+ # @!method validates_acceptance_of(*attr_names)
180
+ # @since 0.1.0
181
+ # @see
182
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html#method-i-validates_acceptance_of
183
+ # ActiveModel::Validations::HelperMethods#validates_acceptance_of
184
+ #
185
+ # @!method validates_confirmation_of(*attr_names)
186
+ # @since 0.1.0
187
+ # @see
188
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html#method-i-validates_confirmation_of
189
+ # ActiveModel::Validations::HelperMethods#validates_confirmation_of
190
+ #
191
+ # @!method validates_exclusion_of(*attr_names)
192
+ # @since 0.1.0
193
+ # @see
194
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html#method-i-validates_exclusion_of
195
+ # ActiveModel::Validations::HelperMethods#validates_exclusion_of
196
+ #
197
+ # @!method validates_format_of(*attr_names)
198
+ # @since 0.1.0
199
+ # @see
200
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html#method-i-validates_format_of
201
+ # ActiveModel::Validations::HelperMethods#validates_format_of
202
+ #
203
+ # @!method validates_inclusion_of(*attr_names)
204
+ # @since 0.1.0
205
+ # @see
206
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html#method-i-validates_inclusion_of
207
+ # ActiveModel::Validations::HelperMethods#validates_inclusion_of
208
+ #
209
+ # @!method validates_length_of(*attr_names)
210
+ # @since 0.1.0
211
+ # @see
212
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html#method-i-validates_length_of
213
+ # ActiveModel::Validations::HelperMethods#validates_length_of
214
+ #
215
+ # @!method validates_numericality_of(*attr_names)
216
+ # @since 0.1.0
217
+ # @see
218
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html#method-i-validates_numericality_of
219
+ # ActiveModel::Validations::HelperMethods#validates_numericality_of
220
+ #
221
+ # @!method validates_presence_of(*attr_names)
222
+ # @since 0.1.0
223
+ # @see
224
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html#method-i-validates_presence_of
225
+ # ActiveModel::Validations::HelperMethods#validates_presence_of
226
+ #
227
+ # @!method validates_size_of(*attr_names)
228
+ # @since 0.1.0
229
+ # @see
230
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations/HelperMethods.html#method-i-validates_size_of
231
+ # ActiveModel::Validations::HelperMethods#validates_size_of
232
+ #
233
+ # @!method validates_with(*args, &block)
234
+ # @since 0.1.0
235
+ # @see
236
+ # https://api.rubyonrails.org/classes/ActiveModel/Validations.html#method-i-validates_with
237
+ # ActiveModel::Validations#validates_with
14
238
  class Base < OpenStruct
15
- include ActiveModel::Validations
16
- include Attributes
17
- include Status
18
-
19
- # @param context [Hash|Context::Base] attributes to assign to the context
20
- # @return [Context::Base] a new instance of {Context::Base}
21
- def initialize(context = {})
22
- merge_errors!(context.errors) if context.respond_to?(:errors)
23
- copy_flags!(context)
24
- copy_called!(context)
25
- super
26
- end
239
+ extend ActiveInteractor::Context::Attributes::ClassMethods
27
240
 
28
- # @!method valid?(context = nil)
29
- # @see
30
- # https://github.com/rails/rails/blob/master/activemodel/lib/active_model/validations.rb#L305
31
- # ActiveModel::Validations#valid?
32
-
33
- # Merge an instance of context or a hash into an existing context
34
- # @since 1.0.0
35
- # @example
36
- # class MyInteractor1 < ActiveInteractor::Base
37
- # def perform
38
- # context.first_name = 'Aaron'
39
- # end
40
- # end
41
- #
42
- # class MyInteractor2 < ActiveInteractor::Base
43
- # def perform
44
- # context.last_name = 'Allen'
45
- # end
46
- # end
47
- #
48
- # result = MyInteractor1.perform
49
- # #=> <#MyInteractor1::Context first_name='Aaron'>
50
- #
51
- # result.merge!(MyInteractor2.perform)
52
- # #=> <#MyInteractor1::Context first_name='Aaron' last_name='Allen'>
53
- # @param context [Base|Hash] attributes to merge into the context
54
- # @return [Base] an instance of {Base}
55
- def merge!(context)
56
- merge_errors!(context.errors) if context.respond_to?(:errors)
57
- copy_flags!(context)
58
- context.each_pair do |key, value|
59
- self[key] = value
60
- end
61
- self
62
- end
63
-
64
- private
65
-
66
- def merge_errors!(errors)
67
- if errors.is_a? String
68
- self.errors.add(:context, errors)
69
- else
70
- self.errors.merge!(errors)
71
- end
72
- end
241
+ include ActiveModel::Validations
242
+ include ActiveInteractor::Context::Attributes
243
+ include ActiveInteractor::Context::Status
73
244
  end
74
245
  end
75
246
  end