Class: Apiwork::Adapter::Capability::Base

Inherits:
Object
  • Object
show all
Includes:
Configurable
Defined in:
lib/apiwork/adapter/capability/base.rb

Overview

Base class for adapter capabilities.

A capability encapsulates a specific feature (filtering, pagination, sorting) with its own configuration, transformers, builders, and operations. While each capability is self-contained, all capabilities operate on the same response data in sequence, so their effects combine.

Examples:

Filtering capability

class Filtering < Adapter::Capability::Base
  capability_name :filtering

  option :strategy, type: :symbol, default: :simple

  request_transformer RequestTransformer
  api_builder APIBuilder
  contract_builder ContractBuilder
  operation Operation
end

See Also:

  • Adapter::Base#capability
  • Configurable#option

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Configurable

define, option

Constructor Details

#initialize(config = {}, adapter_name: nil) ⇒ Base

Returns a new instance of Base.



190
191
192
193
194
# File 'lib/apiwork/adapter/capability/base.rb', line 190

def initialize(config = {}, adapter_name: nil)
  merged = self.class.default_options.deep_merge(config)
  @config = Configuration.new(self.class, merged)
  @adapter_name = adapter_name
end

Instance Attribute Details

#adapter_nameObject (readonly)



187
188
189
# File 'lib/apiwork/adapter/capability/base.rb', line 187

def adapter_name
  @adapter_name
end

#configObject (readonly)



187
188
189
# File 'lib/apiwork/adapter/capability/base.rb', line 187

def config
  @config
end

Class Method Details

.api_builder(klass = nil) { ... } ⇒ void

This method returns an undefined value.

Registers an API builder for this capability.

API builders run once per API at initialization time to register shared types used across all contracts.

Parameters:

Yields:

See Also:



87
88
89
90
91
92
93
# File 'lib/apiwork/adapter/capability/base.rb', line 87

def api_builder(klass = nil, &block)
  if klass
    self._api_builder = klass
  elsif block
    self._api_builder_block = block
  end
end

.api_builder_classObject



165
166
167
168
169
170
# File 'lib/apiwork/adapter/capability/base.rb', line 165

def api_builder_class
  return _api_builder if _api_builder
  return wrap_api_builder_block(_api_builder_block) if _api_builder_block

  nil
end

.capability_name(value = nil) ⇒ Symbol?

The name for this capability.

Used for configuration options, translation keys, and Base.skip_capability.

Parameters:

  • value (Symbol, nil) (defaults to: nil)

    (nil) The capability name.

Returns:

  • (Symbol, nil)


47
48
49
50
# File 'lib/apiwork/adapter/capability/base.rb', line 47

def capability_name(value = nil)
  @capability_name = value.to_sym if value
  @capability_name
end

.contract_builder(klass = nil) { ... } ⇒ void

This method returns an undefined value.

Registers a contract builder for this capability.

Contract builders run per contract to add capability-specific parameters and response shapes.

Parameters:

Yields:

See Also:



106
107
108
109
110
111
112
# File 'lib/apiwork/adapter/capability/base.rb', line 106

def contract_builder(klass = nil, &block)
  if klass
    self._contract_builder = klass
  elsif block
    self._contract_builder_block = block
  end
end

.contract_builder_classObject



172
173
174
175
176
177
# File 'lib/apiwork/adapter/capability/base.rb', line 172

def contract_builder_class
  return _contract_builder if _contract_builder
  return wrap_contract_builder_block(_contract_builder_block) if _contract_builder_block

  nil
end

.operation(klass = nil) { ... } ⇒ void

This method returns an undefined value.

Registers an operation for this capability.

Operations run at request time to process data based on request parameters.

Parameters:

  • klass (Class<Operation::Base>, nil) (defaults to: nil)

    (nil) The operation class.

Yields:

See Also:



125
126
127
128
129
130
131
# File 'lib/apiwork/adapter/capability/base.rb', line 125

def operation(klass = nil, &block)
  if klass
    self._operation_class = klass
  elsif block
    self._operation_block = block
  end
end

.operation_classObject



179
180
181
182
183
184
# File 'lib/apiwork/adapter/capability/base.rb', line 179

def operation_class
  return _operation_class if _operation_class
  return wrap_operation_block(_operation_block) if _operation_block

  nil
end

.request_transformer(transformer_class) ⇒ void

This method returns an undefined value.

Registers a request transformer for this capability.

Parameters:

See Also:



59
60
61
62
# File 'lib/apiwork/adapter/capability/base.rb', line 59

def request_transformer(transformer_class)
  @request_transformers ||= []
  @request_transformers << transformer_class
end

.request_transformersObject



133
134
135
# File 'lib/apiwork/adapter/capability/base.rb', line 133

def request_transformers
  @request_transformers || []
end

.response_transformer(transformer_class) ⇒ void

This method returns an undefined value.

Registers a response transformer for this capability.

Parameters:

See Also:



71
72
73
74
# File 'lib/apiwork/adapter/capability/base.rb', line 71

def response_transformer(transformer_class)
  @response_transformers ||= []
  @response_transformers << transformer_class
end

.response_transformersObject



137
138
139
# File 'lib/apiwork/adapter/capability/base.rb', line 137

def response_transformers
  @response_transformers || []
end

.wrap_api_builder_block(callable) ⇒ Object



141
142
143
144
145
146
147
# File 'lib/apiwork/adapter/capability/base.rb', line 141

def wrap_api_builder_block(callable)
  Class.new(Builder::API::Base) do
    define_method(:build) do
      callable.arity.positive? ? callable.call(self) : instance_exec(&callable)
    end
  end
end

.wrap_contract_builder_block(callable) ⇒ Object



149
150
151
152
153
154
155
# File 'lib/apiwork/adapter/capability/base.rb', line 149

def wrap_contract_builder_block(callable)
  Class.new(Builder::Contract::Base) do
    define_method(:build) do
      callable.arity.positive? ? callable.call(self) : instance_exec(&callable)
    end
  end
end

.wrap_operation_block(callable) ⇒ Object



157
158
159
160
161
162
163
# File 'lib/apiwork/adapter/capability/base.rb', line 157

def wrap_operation_block(callable)
  Class.new(Operation::Base) do
    define_method(:apply) do
      callable.arity.positive? ? callable.call(self) : instance_exec(&callable)
    end
  end
end

Instance Method Details

#api_types(api_class) ⇒ Object



196
197
198
199
200
201
202
203
204
205
# File 'lib/apiwork/adapter/capability/base.rb', line 196

def api_types(api_class)
  builder_class = self.class.api_builder_class
  return unless builder_class

  builder_class.new(
    api_class,
    capability_name: self.class.capability_name,
    options: config,
  ).build
end

#apply(data, representation_class, request, wrapper_type:) ⇒ Object



238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
# File 'lib/apiwork/adapter/capability/base.rb', line 238

def apply(data, representation_class, request, wrapper_type:)
  klass = self.class.operation_class
  return Result.new(data:) unless klass

  scope = klass.target
  return Result.new(data:) if scope && scope != wrapper_type

  klass.new(
    data,
    representation_class,
    merged_config(representation_class),
    request,
    translation_context: build_translation_context(representation_class),
  ).apply
end

#contract_types(contract_class, representation_class, actions) ⇒ Object



207
208
209
210
211
212
# File 'lib/apiwork/adapter/capability/base.rb', line 207

def contract_types(contract_class, representation_class, actions)
  builder_class = self.class.contract_builder_class
  return unless builder_class

  builder_class.new(contract_class, representation_class, actions, merged_config(representation_class)).build
end

#shape(representation_class, type) ⇒ Object



214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/apiwork/adapter/capability/base.rb', line 214

def shape(representation_class, type)
  klass = self.class.operation_class
  return nil unless klass

   = klass.
  return nil unless 

  scope = klass.target
  return nil if scope && scope != type

  object = ::Apiwork::API::Object.new
  .apply(object, merged_config(representation_class))
  return nil if object.params.empty?

  type_name = (representation_class)
  (
    representation_class.api_class,
    type_name,
    ,
    merged_config(representation_class),
  )
  type_name
end