activeinteractor 1.0.0.beta.7 → 1.0.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.
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