Module: Interaktor::Callable::ClassMethods

Defined in:
lib/interaktor/callable.rb

Instance Method Summary collapse

Instance Method Details

#call(context = {}) ⇒ Interaktor::Context

Invoke an Interaktor. This is the primary public API method to an interaktor. Interaktor failures will not raise an exception.

Parameters:

  • context (Hash, Interaktor::Context) (defaults to: {})

    the context object as a hash with attributes or an already-built context

Returns:



296
297
298
# File 'lib/interaktor/callable.rb', line 296

def call(context = {})
  execute(context, false)
end

#call!(context = {}) ⇒ Interaktor::Context

Invoke an Interaktor. This method behaves identically to #call, but if the interaktor is failed, Interaktor::Failure is raised.

Parameters:

  • context (Hash, Interaktor::Context) (defaults to: {})

    the context object as a hash with attributes or an already-built context

Returns:



309
310
311
# File 'lib/interaktor/callable.rb', line 309

def call!(context = {})
  execute(context, true)
end

#failure(schema = nil) { ... } ⇒ Object

Parameters:

  • schema (Dry::Schema::Params, nil) (defaults to: nil)

    a predefined schema object

Yields:

  • a new Dry::Schema::Params definition block



188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/interaktor/callable.rb', line 188

def failure(schema = nil, &block)
  raise "No schema or schema definition block provided to interaktor failure method." if schema.nil? && !block

  raise "Provided both a schema and a schema definition block for interaktor failure method." if schema && block

  if schema
    raise "Provided argument is not a Dry::Schema::Params object." unless schema.is_a?(Dry::Schema::Params)

    @failure_schema = schema
  elsif block
    @failure_schema = Dry::Schema.Params { instance_eval(&block) }
  end
end

#failure_attributesArray<Symbol>

The complete list of failure attributes.

Returns:

  • (Array<Symbol>)


157
158
159
# File 'lib/interaktor/callable.rb', line 157

def failure_attributes
  required_failure_attributes + optional_failure_attributes
end

#failure_schemaDry::Schema::Params

Get the failure attribute schema. Fall back to an empty schema with a configuration that will deny ALL provided attributes - not defining an failure schema should mean the interaktor has no failure attributes.

Returns:

  • (Dry::Schema::Params)


166
167
168
# File 'lib/interaktor/callable.rb', line 166

def failure_schema
  @failure_schema || Dry::Schema.Params
end

#input(schema = nil) { ... } ⇒ Object

Parameters:

  • schema (Dry::Schema::Params, nil) (defaults to: nil)

    a predefined schema object

Yields:

  • a new Dry::Schema::Params definition block



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/interaktor/callable.rb', line 88

def input(schema = nil, &block)
  raise "No schema or schema definition block provided to interaktor input." if schema.nil? && !block

  raise "Provided both a schema and a schema definition block for interaktor input." if schema && block

  if schema
    raise "Provided argument is not a Dry::Schema::Params object." unless schema.is_a?(Dry::Schema::Params)

    @input_schema = schema
  elsif block
    @input_schema = Dry::Schema.Params { instance_eval(&block) }
  end

  # define the getters and setters for the input attributes
  @input_schema.key_map.keys.each do |key| # rubocop:disable Style/HashEachMethods
    attribute_name = key.id

    # Define getter
    define_method(attribute_name) { @context.send(attribute_name) }

    # Define setter
    define_method("#{attribute_name}=".to_sym) do |value|
      @context.send("#{attribute_name}=".to_sym, value)
    end
  end
end

#input_attributesArray<Symbol>

The complete list of input attributes.

Returns:

  • (Array<Symbol>)


57
58
59
# File 'lib/interaktor/callable.rb', line 57

def input_attributes
  required_input_attributes + optional_input_attributes
end

#input_schemaDry::Schema::Params

Get the input attribute schema. Fall back to an empty schema with a configuration that will deny ALL provided attributes - not defining an input schema should mean the interaktor has no input attributes.

Returns:

  • (Dry::Schema::Params)


66
67
68
# File 'lib/interaktor/callable.rb', line 66

def input_schema
  @input_schema || Dry::Schema.Params
end

#optional_failure_attributesArray<Symbol>

The list of attributes which are not required to be provided when failing the interaktor.

Returns:

  • (Array<Symbol>)


133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/interaktor/callable.rb', line 133

def optional_failure_attributes
  # Adding an optional attribute with NO predicates with Dry::Schema is
  # sort of a "nothing statement" - the schema can sort of ignore it. The
  # problem is that the optional-with-no-predicate key is not included in
  # the #info results, so we need to find an list of keys elsewhere, find
  # the ones that are listed there but not in the #info results, and find
  # the difference. The result are the keys that are omitted from the #info
  # result because they are optional and have no predicates.
  #
  # See https://github.com/dry-rb/dry-schema/issues/347
  @optional_failure_attributes ||= begin
      attributes_in_info = failure_schema.info[:keys].keys
      all_attributes = failure_schema.key_map.keys.map(&:id)
      optional_attributes_by_exclusion = all_attributes - attributes_in_info

      explicitly_optional_attributes = failure_schema.info[:keys].reject { |_, info| info[:required] }.keys

      explicitly_optional_attributes + optional_attributes_by_exclusion
    end
end

#optional_input_attributesArray<Symbol>

The list of attributes which are not required to be passed in when calling the interaktor.

Returns:

  • (Array<Symbol>)


33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/interaktor/callable.rb', line 33

def optional_input_attributes
  # Adding an optional attribute with NO predicates with Dry::Schema is
  # sort of a "nothing statement" - the schema can sort of ignore it. The
  # problem is that the optional-with-no-predicate key is not included in
  # the #info results, so we need to find an list of keys elsewhere, find
  # the ones that are listed there but not in the #info results, and find
  # the difference. The result are the keys that are omitted from the #info
  # result because they are optional and have no predicates.
  #
  # See https://github.com/dry-rb/dry-schema/issues/347
  @optional_input_attributes ||= begin
      attributes_in_info = input_schema.info[:keys].keys
      all_attributes = input_schema.key_map.keys.map(&:id)
      optional_attributes_by_exclusion = all_attributes - attributes_in_info

      explicitly_optional_attributes = input_schema.info[:keys].reject { |_, info| info[:required] }.keys

      explicitly_optional_attributes + optional_attributes_by_exclusion
    end
end

#optional_success_attributesArray<Symbol>

The list of attributes which are not required to be provided when failing the interaktor.

Returns:

  • (Array<Symbol>)


220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'lib/interaktor/callable.rb', line 220

def optional_success_attributes
  # Adding an optional attribute with NO predicates with Dry::Schema is
  # sort of a "nothing statement" - the schema can sort of ignore it. The
  # problem is that the optional-with-no-predicate key is not included in
  # the #info results, so we need to find an list of keys elsewhere, find
  # the ones that are listed there but not in the #info results, and find
  # the difference. The result are the keys that are omitted from the #info
  # result because they are optional and have no predicates.
  #
  # See https://github.com/dry-rb/dry-schema/issues/347
  @optional_success_attributes ||= begin
      attributes_in_info = success_schema.info[:keys].keys
      all_attributes = success_schema.key_map.keys.map(&:id)
      optional_attributes_by_exclusion = all_attributes - attributes_in_info

      explicitly_optional_attributes = success_schema.info[:keys].reject { |_, info| info[:required] }.keys

      explicitly_optional_attributes + optional_attributes_by_exclusion
    end
end

#required_failure_attributesArray<Symbol>

The list of attributes which are required to be provided when failing the interaktor.

Returns:

  • (Array<Symbol>)


123
124
125
126
127
# File 'lib/interaktor/callable.rb', line 123

def required_failure_attributes
  @required_failure_attributes ||= failure_schema.info[:keys]
    .select { |_, info| info[:required] }
    .keys
end

#required_input_attributesArray<Symbol>

The list of attributes which are required to be passed in when calling the interaktor.

Returns:

  • (Array<Symbol>)


23
24
25
26
27
# File 'lib/interaktor/callable.rb', line 23

def required_input_attributes
  @required_input_attributes ||= input_schema.info[:keys]
                                             .select { |_, info| info[:required] }
                                             .keys
end

#required_success_attributesArray<Symbol>

The list of attributes which are required to be provided when the interaktor succeeds.

Returns:

  • (Array<Symbol>)


210
211
212
213
214
# File 'lib/interaktor/callable.rb', line 210

def required_success_attributes
  @required_success_attributes ||= success_schema.info[:keys]
                                                 .select { |_, info| info[:required] }
                                                 .keys
end

#success(schema = nil) { ... } ⇒ Object

Parameters:

  • schema (Dry::Schema::Params, nil) (defaults to: nil)

    a predefined schema object

Yields:

  • a new Dry::Schema::Params definition block



275
276
277
278
279
280
281
282
283
284
285
286
287
# File 'lib/interaktor/callable.rb', line 275

def success(schema = nil, &block)
  raise "No schema or schema definition block provided to interaktor success method." if schema.nil? && !block

  raise "Provided both a schema and a schema definition block for interaktor success method." if schema && block

  if schema
    raise "Provided argument is not a Dry::Schema::Params object." unless schema.is_a?(Dry::Schema::Params)

    @success_schema = schema
  elsif block
    @success_schema = Dry::Schema.Params { instance_eval(&block) }
  end
end

#success_attributesArray<Symbol>

The complete list of success attributes.

Returns:

  • (Array<Symbol>)


244
245
246
# File 'lib/interaktor/callable.rb', line 244

def success_attributes
  required_success_attributes + optional_success_attributes
end

#success_schemaDry::Schema::Params

Get the success attribute schema. Fall back to an empty schema with a configuration that will deny ALL provided attributes - not defining an success schema should mean the interaktor has no success attributes.

Returns:

  • (Dry::Schema::Params)


253
254
255
# File 'lib/interaktor/callable.rb', line 253

def success_schema
  @success_schema || Dry::Schema.Params
end

#validate_failure_schema(context) ⇒ void

This method returns an undefined value.

Parameters:

  • context (Hash)


173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/interaktor/callable.rb', line 173

def validate_failure_schema(context)
  return unless failure_schema

  result = failure_schema.call(context)

  if result.errors.any?
    raise Interaktor::Error::AttributeSchemaValidationError.new(
      self,
      result.errors.to_h,
    )
  end
end

#validate_input_schema(context) ⇒ void

This method returns an undefined value.

Parameters:

  • context (Hash)


73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/interaktor/callable.rb', line 73

def validate_input_schema(context)
  return unless input_schema

  result = input_schema.call(context)

  if result.errors.any?
    raise Interaktor::Error::AttributeSchemaValidationError.new(
      self,
      result.errors.to_h,
    )
  end
end

#validate_success_schema(context) ⇒ void

This method returns an undefined value.

Parameters:

  • context (Hash)


260
261
262
263
264
265
266
267
268
269
270
271
# File 'lib/interaktor/callable.rb', line 260

def validate_success_schema(context)
  return unless success_schema

  result = success_schema.call(context)

  if result.errors.any?
    raise Interaktor::Error::AttributeSchemaValidationError.new(
      self,
      result.errors.to_h,
    )
  end
end