Class: Apiwork::API::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/apiwork/api/base.rb

Overview

Base class for API definitions.

Created via define. Configure resources, types, enums, adapters, and exports. Each API is mounted at a unique path.

Examples:

Define an API

Apiwork::API.define '/api/v1' do
  key_format :camel

  resources :invoices do
    resources :items
  end
end

Constant Summary collapse

VALID_FORMATS =
%i[keep camel pascal kebab underscore].freeze

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.base_pathString (readonly)

The base path for this API.

Returns:

  • (String)


28
29
30
# File 'lib/apiwork/api/base.rb', line 28

def base_path
  @base_path
end

.enum_registryObject (readonly)



28
29
30
# File 'lib/apiwork/api/base.rb', line 28

def enum_registry
  @enum_registry
end

.explorer_configObject (readonly)



28
29
30
# File 'lib/apiwork/api/base.rb', line 28

def explorer_config
  @explorer_config
end

.export_configsObject (readonly)



28
29
30
# File 'lib/apiwork/api/base.rb', line 28

def export_configs
  @export_configs
end

.representation_registryObject (readonly)



28
29
30
# File 'lib/apiwork/api/base.rb', line 28

def representation_registry
  @representation_registry
end

.root_resourceObject (readonly)



28
29
30
# File 'lib/apiwork/api/base.rb', line 28

def root_resource
  @root_resource
end

.type_registryObject (readonly)



28
29
30
# File 'lib/apiwork/api/base.rb', line 28

def type_registry
  @type_registry
end

Class Method Details

.adapter(name = nil) {|config| ... } ⇒ Adapter::Base, void

Sets or configures the adapter for this API.

Without arguments, returns the adapter instance. With a block, configures the current adapter. Without a name, the built-in ‘:standard` adapter is used.

Custom adapters must be registered via Apiwork::Adapter.register and referenced by their ‘adapter_name`.

Examples:

Configure the default :standard adapter

adapter do
  pagination do
    default_size 25
    max_size 100
  end
end

Use a registered custom adapter

adapter :jsonapi

Use and configure a custom adapter

adapter :jsonapi do
  pagination do
    strategy :cursor
  end
end

Parameters:

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

    (nil) A registered adapter name matching ‘adapter_name` in the adapter class.

Yields:

  • Block evaluated in adapter configuration context.

Yield Parameters:

Returns:

  • (Adapter::Base, void)

    the adapter instance when called without block

See Also:



209
210
211
212
213
214
215
216
217
218
# File 'lib/apiwork/api/base.rb', line 209

def adapter(name = nil, &block)
  @adapter_name = name if name.is_a?(Symbol)

  if block
    block.arity.positive? ? yield(adapter_config) : adapter_config.instance_eval(&block)
    return
  end

  @adapter ||= adapter_class.new
end

.adapter_classObject



662
663
664
# File 'lib/apiwork/api/base.rb', line 662

def adapter_class
  Adapter.find!(@adapter_name || :standard)
end

.adapter_configObject



666
667
668
# File 'lib/apiwork/api/base.rb', line 666

def adapter_config
  @adapter_config ||= Configuration.new(adapter_class)
end

.concern(name) {|resource| ... } ⇒ void

This method returns an undefined value.

Defines a reusable concern for resources.

Concerns are reusable blocks of resource configuration that can be included in multiple resources via the ‘concerns` option.

Examples:

instance_eval style

concern :archivable do
  member do
    post :archive
    post :unarchive
  end
end

resources :posts, concerns: [:archivable]

yield style

concern :archivable do |resource|
  resource.member do |member|
    member.post :archive
    member.post :unarchive
  end
end

resources :posts, concerns: [:archivable]

Parameters:

  • name (Symbol)

    The concern name.

Yields:

  • Block defining shared actions and configuration.

Yield Parameters:



568
569
570
# File 'lib/apiwork/api/base.rb', line 568

def concern(name, &block)
  @root_resource.concern(name, &block)
end

.ensure_all_contracts_built!Object



838
839
840
841
842
843
844
# File 'lib/apiwork/api/base.rb', line 838

def ensure_all_contracts_built!
  ensure_pre_pass_complete!

  @root_resource.each_resource do |resource|
    build_contracts_for_resource(resource)
  end
end

.ensure_contract_built!(contract_class) ⇒ Object



814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
# File 'lib/apiwork/api/base.rb', line 814

def ensure_contract_built!(contract_class)
  return if @built_contracts.include?(contract_class)

  ensure_pre_pass_complete!

  representation_class = contract_class.representation_class
  return unless representation_class

  @built_contracts.add(contract_class)

  resource = @root_resource.find_resource { |resource| resource.resolve_contract_class == contract_class }
  resource_actions = resource ? resource.actions : {}

  adapter.register_contract(contract_class, representation_class, resource_actions:)
end

.ensure_pre_pass_complete!Object



830
831
832
833
834
835
836
# File 'lib/apiwork/api/base.rb', line 830

def ensure_pre_pass_complete!
  return if @pre_pass_complete

  mark_nested_writable_representations!
  adapter.register_api(self)
  @pre_pass_complete = true
end

.enum(name, deprecated: false, description: nil, example: nil, values: nil) ⇒ void

This method returns an undefined value.

Defines a reusable enumeration type.

Examples:

enum :status, values: %w[draft sent paid]

Parameters:

  • name (Symbol)

    The enum name.

  • values (Array<String>, nil) (defaults to: nil)

    (nil) The allowed values.

  • description (String, nil) (defaults to: nil)

    (nil) The description. Metadata included in exports.

  • example (String, nil) (defaults to: nil)

    (nil) The example. Metadata included in exports.

  • deprecated (Boolean) (defaults to: false)

    (false) Whether deprecated. Metadata included in exports.



286
287
288
# File 'lib/apiwork/api/base.rb', line 286

def enum(name, deprecated: false, description: nil, example: nil, values: nil)
  register_enum(name, deprecated:, description:, example:, values:)
end

.enum?(name, scope: nil) ⇒ Boolean

Returns:

  • (Boolean)


781
782
783
# File 'lib/apiwork/api/base.rb', line 781

def enum?(name, scope: nil)
  enum_registry.exists?(name, scope:)
end

.enum_values(name, scope: nil) ⇒ Object



785
786
787
# File 'lib/apiwork/api/base.rb', line 785

def enum_values(name, scope: nil)
  enum_registry.values(name, scope:)
end

.explorer {|explorer| ... } ⇒ void

This method returns an undefined value.

Configures the explorer for this API.

The explorer is an interactive UI for browsing and testing API endpoints. Requires the ‘apiwork-explorer` gem.

Examples:

Enable with defaults

explorer

Custom configuration

explorer do
  mode :always
  path '/explorer'
end

Yields:

  • Block evaluated in explorer context.

Yield Parameters:



155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/apiwork/api/base.rb', line 155

def explorer(&block)
  unless defined?(Apiwork::Explorer::Engine)
    raise ConfigurationError,
          'explorer requires the apiwork-explorer gem. ' \
          "Add it to your Gemfile: gem 'apiwork-explorer'"
  end

  unless @explorer_config
    options = Configurable.define do
      option :mode, default: :auto, enum: %i[auto always never], type: :symbol
      option :path, default: '/.explorer', type: :string
    end
    @explorer_config = Configuration.new(options)
  end

  return @explorer_config unless block

  block.arity.positive? ? yield(@explorer_config) : @explorer_config.instance_eval(&block)
end

.export(name) {|export| ... } ⇒ void

This method returns an undefined value.

Enables an export for this API.

Examples:

export :openapi
export :typescript do
  endpoint do
    mode :always
  end
end

Parameters:

  • name (Symbol)

    The registered export name. Built-in: :openapi, :typescript, :zod.

Yields:

  • Block evaluated in export context.

Yield Parameters:



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/apiwork/api/base.rb', line 111

def export(name, &block)
  unless Export.exists?(name)
    available = Export.keys.join(', ')
    raise ConfigurationError,
          "Unknown export: :#{name}. " \
          "Available: #{available}"
  end

  unless @export_configs[name]
    export_class = Export.find!(name)

    options = Configurable.define(extends: export_class) do
      option :endpoint, type: :hash do
        option :mode, default: :auto, enum: %i[auto always never], type: :symbol
        option :path, type: :string
      end
    end

    @export_configs[name] = Configuration.new(options)
  end

  return unless block

  block.arity.positive? ? yield(@export_configs[name]) : @export_configs[name].instance_eval(&block)
end

.fingerprintString

The fingerprint for this API.

A 16-character hex digest derived from the application name and base_path.

Returns:

  • (String)


606
607
608
609
610
# File 'lib/apiwork/api/base.rb', line 606

def fingerprint
  @fingerprint ||= Digest::SHA256.hexdigest(
    [Rails.application.class.module_parent_name, base_path].join(':'),
  )[0, 16]
end

.fragment(name) {|object| ... } ⇒ void

This method returns an undefined value.

Defines a fragment type for composition.

Fragments are only available for merging into other types and never appear as standalone types. Use fragments to define reusable field groups.

Examples:

Reusable timestamps

fragment :timestamps do
  datetime :created_at
  datetime :updated_at
end

object :invoice do
  merge :timestamps
  string :number
end

Parameters:

  • name (Symbol)

    The fragment name.

Yield Parameters:



265
266
267
# File 'lib/apiwork/api/base.rb', line 265

def fragment(name, &block)
  register_fragment(name, &block)
end

.info {|info| ... } ⇒ Info?

The info for this API.

Examples:

instance_eval style

info do
  title 'My API'
  version '1.0.0'
end

yield style

info do |info|
  info.title 'My API'
  info.version '1.0.0'
end

Yields:

  • Block for defining API info.

Yield Parameters:

Returns:



392
393
394
395
396
397
398
# File 'lib/apiwork/api/base.rb', line 392

def info(&block)
  return @info unless block

  @info = Info.new
  block.arity.positive? ? yield(@info) : @info.instance_eval(&block)
  @info
end

.introspect(locale: nil) ⇒ Object



797
798
799
800
# File 'lib/apiwork/api/base.rb', line 797

def introspect(locale: nil)
  ensure_all_contracts_built!
  @introspect_cache[locale] ||= Introspection.api(self, locale:)
end

.introspect_contract(contract_class, expand:, locale:) ⇒ Object



802
803
804
805
806
# File 'lib/apiwork/api/base.rb', line 802

def introspect_contract(contract_class, expand:, locale:)
  ensure_all_contracts_built!
  cache_key = [contract_class, locale, expand]
  @introspect_contract_cache[cache_key] ||= Introspection.contract(contract_class, expand:, locale:)
end

.key_format(format = nil) ⇒ Symbol?

Configures key transformation for this API.

Transforms JSON keys in request bodies, response bodies, and query parameters. Incoming requests are normalized to underscore internally, so controllers always receive ‘params` regardless of format.

With ‘:camel`, `user_name` becomes `userName`. With `:pascal`, `user_name` becomes `UserName`. With `:kebab`, `user_name` becomes `user-name`.

Examples:

camelCase keys

key_format :camel

# Client sends: { "userName": "alice" }
# Controller receives: params[:user_name]
# Response: { "userName": "alice", "createdAt": "2024-01-01" }

Parameters:

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

    (nil) [:camel, :kebab, :keep, :pascal, :underscore] The key format. Default is ‘:keep`.

Returns:

  • (Symbol, nil)

Raises:



57
58
59
60
61
62
63
# File 'lib/apiwork/api/base.rb', line 57

def key_format(format = nil)
  return @key_format if format.nil?

  raise ConfigurationError, "key_format must be one of #{VALID_FORMATS}" unless VALID_FORMATS.include?(format)

  @key_format = format
end

.locale_keyObject



670
671
672
# File 'lib/apiwork/api/base.rb', line 670

def locale_key
  @locale_key ||= base_path.delete_prefix('/')
end

.locales(*locale_keys) ⇒ Array<Symbol>

Supported locales for this API.

Declares which locales this API supports. Used by introspection to validate locale parameters and included in introspection output.

Examples:

locales :en, :sv, :it
api_class.locales # => [:en, :sv, :it]

Parameters:

  • locale_keys (Array<Symbol>)

    The locale identifiers.

Returns:

  • (Array<Symbol>)

Raises:



332
333
334
335
336
337
338
339
340
# File 'lib/apiwork/api/base.rb', line 332

def locales(*locale_keys)
  return @locales if locale_keys.empty?

  locale_keys = locale_keys.flatten.uniq
  locale_keys.each do |locale_key|
    raise ConfigurationError, "locales must be symbols, got #{locale_key.class}: #{locale_key}" unless locale_key.is_a?(Symbol)
  end
  @locales = locale_keys
end

.mount(base_path) ⇒ Object



678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
# File 'lib/apiwork/api/base.rb', line 678

def mount(base_path)
  @base_path = base_path
  @fingerprint = nil
  @locale_key = nil
  @namespaces = nil
  @info = nil
  @locales = []
  @raises = []
  @explorer_config = nil
  @export_configs = {}
  @adapter_config = nil
  @root_resource = Resource.new(self)
  @type_registry = TypeRegistry.new
  @enum_registry = EnumRegistry.new
  @representation_registry = RepresentationRegistry.new
  @built_contracts = Set.new
  @key_format = :keep
  @path_format = :keep
  @introspect_cache = {}
  @introspect_contract_cache = {}

  Registry.register(self)
end

.namespacesObject



674
675
676
# File 'lib/apiwork/api/base.rb', line 674

def namespaces
  @namespaces ||= extract_namespaces(base_path)
end

.normalize_key(key) ⇒ Object



739
740
741
742
743
744
745
# File 'lib/apiwork/api/base.rb', line 739

def normalize_key(key)
  key_string = key.to_s

  return key_string if key_string.match?(/\A[A-Z]+\z/)

  key_string.underscore
end

.normalize_request(request) ⇒ Object



747
748
749
750
751
752
753
# File 'lib/apiwork/api/base.rb', line 747

def normalize_request(request)
  return request if key_format == :keep

  request.transform do |hash|
    hash.deep_transform_keys { |key| normalize_key(key).to_sym }
  end
end

.object(name, deprecated: false, description: nil, example: nil) {|object| ... } ⇒ void

This method returns an undefined value.

Defines a reusable object type.

Examples:

object :item do
  string :description
  decimal :amount
end

Parameters:

  • name (Symbol)

    The object name.

  • deprecated (Boolean) (defaults to: false)

    (false) Whether deprecated. Metadata included in exports.

  • description (String, nil) (defaults to: nil)

    (nil) The description. Metadata included in exports.

  • example (Object, nil) (defaults to: nil)

    (nil) The example. Metadata included in exports.

Yield Parameters:



240
241
242
# File 'lib/apiwork/api/base.rb', line 240

def object(name, deprecated: false, description: nil, example: nil, &block)
  register_object(name, deprecated:, description:, example:, &block)
end

.path_format(format = nil) ⇒ Symbol?

Configures URL path transformation for this API.

Transforms URL path segments: base path, resource paths, action paths, and explicit ‘path:` options. Path parameters like `:id` and `:user_id` are not transformed. Controllers and params remain underscore internally.

With ‘:kebab`, `/api/user_profiles/:id` becomes `/api/user-profiles/:id`. With `:pascal`, `/api/user_profiles/:id` becomes `/api/UserProfiles/:id`.

Examples:

kebab-case paths

path_format :kebab

resources :user_profiles
# URL: /user-profiles/:id
# Controller: UserProfilesController
# Params: params[:user_profile]

Parameters:

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

    (nil) [:camel, :kebab, :keep, :pascal, :underscore] The path format. Default is ‘:keep`.

Returns:

  • (Symbol, nil)

Raises:



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

def path_format(format = nil)
  return @path_format if format.nil?

  raise ConfigurationError, "path_format must be one of #{VALID_FORMATS}" unless VALID_FORMATS.include?(format)

  @path_format = format
end

.prepare_error_response(response) ⇒ Object



766
767
768
769
770
771
# File 'lib/apiwork/api/base.rb', line 766

def prepare_error_response(response)
  result = prepare_response(response)
  return result if key_format == :keep

  result.transform { |body| transform_issue_paths(body) }
end

.prepare_request(request) ⇒ Object



755
756
757
# File 'lib/apiwork/api/base.rb', line 755

def prepare_request(request)
  request
end

.prepare_response(response) ⇒ Object



759
760
761
762
763
764
# File 'lib/apiwork/api/base.rb', line 759

def prepare_response(response)
  result = adapter.apply_response_transformers(response)
  return result if key_format == :keep

  result.transform { |hash| hash.deep_transform_keys { |key| transform_key(key).to_sym } }
end

.raises(*error_code_keys) ⇒ Array<Symbol>

API-wide error codes.

Included in generated specs (OpenAPI, etc.) as possible error responses.

Examples:

raises :unauthorized, :forbidden, :not_found
api_class.raises # => [:unauthorized, :forbidden, :not_found]

Parameters:

  • error_code_keys (Array<Symbol>)

    The registered error code keys.

Returns:

  • (Array<Symbol>)

Raises:



355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
# File 'lib/apiwork/api/base.rb', line 355

def raises(*error_code_keys)
  return @raises if error_code_keys.empty?

  error_code_keys = error_code_keys.flatten.uniq
  error_code_keys.each do |error_code_key|
    unless error_code_key.is_a?(Symbol)
      hint = error_code_key.is_a?(Integer) ? " Use :#{ErrorCode.key_for_status(error_code_key)} instead." : ''
      raise ConfigurationError, "raises must be symbols, got #{error_code_key.class}: #{error_code_key}.#{hint}"
    end

    next if ErrorCode.exists?(error_code_key)

    raise ConfigurationError,
          "Unknown error code :#{error_code_key}. Register it with: " \
          "Apiwork::ErrorCode.register :#{error_code_key}, status: <status>"
  end
  @raises = error_code_keys
end

.register_enum(name, deprecated: false, description: nil, example: nil, scope: nil, values: nil) ⇒ Object

Raises:



634
635
636
637
638
639
640
641
642
643
644
645
# File 'lib/apiwork/api/base.rb', line 634

def register_enum(name, deprecated: false, description: nil, example: nil, scope: nil, values: nil)
  raise ConfigurationError, 'Values must be an array' if values && !values.is_a?(Array)

  enum_registry.register(
    name,
    values,
    deprecated:,
    description:,
    example:,
    scope:,
  )
end

.register_fragment(name, scope: nil, &block) ⇒ Object



624
625
626
627
628
629
630
631
632
# File 'lib/apiwork/api/base.rb', line 624

def register_fragment(name, scope: nil, &block)
  type_registry.register(
    name,
    scope:,
    fragment: true,
    kind: :object,
    &block
  )
end

.register_object(name, deprecated: false, description: nil, example: nil, scope: nil, &block) ⇒ Object



612
613
614
615
616
617
618
619
620
621
622
# File 'lib/apiwork/api/base.rb', line 612

def register_object(name, deprecated: false, description: nil, example: nil, scope: nil, &block)
  type_registry.register(
    name,
    deprecated:,
    description:,
    example:,
    scope:,
    kind: :object,
    &block
  )
end

.register_union(name, deprecated: false, description: nil, discriminator: nil, example: nil, scope: nil, &block) ⇒ Object

Raises:



647
648
649
650
651
652
653
654
655
656
657
658
659
660
# File 'lib/apiwork/api/base.rb', line 647

def register_union(name, deprecated: false, description: nil, discriminator: nil, example: nil, scope: nil, &block)
  raise ConfigurationError, 'Union requires a block' unless block_given?

  type_registry.register(
    name,
    deprecated:,
    description:,
    discriminator:,
    example:,
    scope:,
    kind: :union,
    &block
  )
end

.reset_contracts!Object



808
809
810
811
812
# File 'lib/apiwork/api/base.rb', line 808

def reset_contracts!
  @built_contracts = Set.new
  @introspect_cache = {}
  @introspect_contract_cache = {}
end

.resource(name, concerns: nil, constraints: nil, contract: nil, controller: nil, defaults: nil, except: nil, only: nil, param: nil, path: nil) {|resource| ... } ⇒ void

This method returns an undefined value.

Defines a singular resource (no index action, no :id in URL).

Useful for resources where only one instance exists, like user profile or application settings.

Examples:

instance_eval style

resource :profile do
  resources :settings
end

yield style

resource :profile do |resource|
  resource.resources :settings
end

Parameters:

  • name (Symbol)

    The resource name (singular).

  • concerns (Array<Symbol>, nil) (defaults to: nil)

    (nil) The concerns to include.

  • constraints (Hash, Proc, nil) (defaults to: nil)

    (nil) The route constraints (regex, lambdas).

  • contract (String, nil) (defaults to: nil)

    (nil) The custom contract path.

  • controller (String, nil) (defaults to: nil)

    (nil) The custom controller path.

  • defaults (Hash, nil) (defaults to: nil)

    (nil) The default parameters for routes.

  • except (Array<Symbol>, nil) (defaults to: nil)

    (nil) The CRUD actions to exclude.

  • only (Array<Symbol>, nil) (defaults to: nil)

    (nil) The CRUD actions to include.

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

    (nil) The custom parameter name for ID.

  • path (String, nil) (defaults to: nil)

    (nil) The custom URL path segment.

Yields:

  • Block for nested resources and custom actions.

Yield Parameters:



509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
# File 'lib/apiwork/api/base.rb', line 509

def resource(
  name,
  concerns: nil,
  constraints: nil,
  contract: nil,
  controller: nil,
  defaults: nil,
  except: nil,
  only: nil,
  param: nil,
  path: nil,
  &block
)
  @root_resource.resource(
    name,
    concerns:,
    constraints:,
    contract:,
    controller:,
    defaults:,
    except:,
    only:,
    param:,
    path:,
    &block
  )
end

.resources(name, concerns: nil, constraints: nil, contract: nil, controller: nil, defaults: nil, except: nil, only: nil, param: nil, path: nil) {|resource| ... } ⇒ void

This method returns an undefined value.

Defines a RESTful resource with standard CRUD actions.

This is the main method for declaring API endpoints. Creates routes for index, show, create, update, destroy actions. Nested resources and custom actions can be defined in the block.

Examples:

instance_eval style

resources :invoices do
  member { post :archive }
  resources :items
end

yield style

resources :invoices do |resource|
  resource.member { |member| member.post :archive }
  resource.resources :items
end

Parameters:

  • name (Symbol)

    The resource name (plural).

  • concerns (Array<Symbol>, nil) (defaults to: nil)

    (nil) The concerns to include.

  • constraints (Hash, Proc, nil) (defaults to: nil)

    (nil) The route constraints (regex, lambdas).

  • contract (String, nil) (defaults to: nil)

    (nil) The custom contract path.

  • controller (String, nil) (defaults to: nil)

    (nil) The custom controller path.

  • defaults (Hash, nil) (defaults to: nil)

    (nil) The default parameters for routes.

  • except (Array<Symbol>, nil) (defaults to: nil)

    (nil) The CRUD actions to exclude.

  • only (Array<Symbol>, nil) (defaults to: nil)

    (nil) The CRUD actions to include.

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

    (nil) The custom parameter name for ID.

  • path (String, nil) (defaults to: nil)

    (nil) The custom URL path segment.

Yields:

  • Block for nested resources and custom actions.

Yield Parameters:



442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
# File 'lib/apiwork/api/base.rb', line 442

def resources(
  name,
  concerns: nil,
  constraints: nil,
  contract: nil,
  controller: nil,
  defaults: nil,
  except: nil,
  only: nil,
  param: nil,
  path: nil,
  &block
)
  @root_resource.resources(
    name,
    concerns:,
    constraints:,
    contract:,
    controller:,
    defaults:,
    except:,
    only:,
    param:,
    path:,
    &block
  )
end

.scoped_enum_name(scope, name) ⇒ Object



793
794
795
# File 'lib/apiwork/api/base.rb', line 793

def scoped_enum_name(scope, name)
  enum_registry.scoped_name(scope, name)
end

.scoped_type_name(scope, name) ⇒ Object



789
790
791
# File 'lib/apiwork/api/base.rb', line 789

def scoped_type_name(scope, name)
  type_registry.scoped_name(scope, name)
end

.transform_key(key) ⇒ Object



725
726
727
728
729
730
731
732
733
734
735
736
737
# File 'lib/apiwork/api/base.rb', line 725

def transform_key(key)
  key_string = key.to_s

  return key_string if key_string.match?(/\A[A-Z]+\z/)

  case key_format
  when :camel then key_string.camelize(:lower)
  when :pascal then key_string.camelize
  when :kebab then key_string.dasherize
  when :underscore then key_string.underscore
  else key_string
  end
end

.transform_path(path) ⇒ Object



707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
# File 'lib/apiwork/api/base.rb', line 707

def transform_path(path)
  path_string = path.to_s
  return path_string if @path_format == :keep
  return path_string if path_string == '/'

  path_string.split('/').map do |segment|
    next segment if segment.empty?

    case @path_format
    when :camel then segment.camelize(:lower)
    when :pascal then segment.camelize
    when :kebab then segment.dasherize
    when :underscore then segment.underscore
    else segment
    end
  end.join('/')
end

.translate(*segments, default: nil) ⇒ Object



702
703
704
705
# File 'lib/apiwork/api/base.rb', line 702

def translate(*segments, default: nil)
  key = :"apiwork.apis.#{locale_key}.#{segments.join('.')}"
  I18n.translate(key, default:)
end

.type?(name, scope: nil) ⇒ Boolean

Returns:

  • (Boolean)


773
774
775
# File 'lib/apiwork/api/base.rb', line 773

def type?(name, scope: nil)
  type_registry.exists?(name, scope:)
end

.type_definition(name, scope: nil) ⇒ Object



777
778
779
# File 'lib/apiwork/api/base.rb', line 777

def type_definition(name, scope: nil)
  type_registry.find(name, scope:)
end

.union(name, deprecated: false, description: nil, discriminator: nil, example: nil) {|union| ... } ⇒ void

This method returns an undefined value.

Defines a discriminated union type.

Examples:

union :payment_method, discriminator: :type do
  variant tag: 'card' do
    object do
      string :last_four
    end
  end
end

Parameters:

  • name (Symbol)

    The union name.

  • deprecated (Boolean) (defaults to: false)

    (false) Whether deprecated. Metadata included in exports.

  • description (String, nil) (defaults to: nil)

    (nil) The description. Metadata included in exports.

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

    (nil) The discriminator field name.

  • example (Object, nil) (defaults to: nil)

    (nil) The example. Metadata included in exports.

Yield Parameters:



314
315
316
# File 'lib/apiwork/api/base.rb', line 314

def union(name, deprecated: false, description: nil, discriminator: nil, example: nil, &block)
  register_union(name, deprecated:, description:, discriminator:, example:, &block)
end

.with_options(options = {}) {|resource| ... } ⇒ void

This method returns an undefined value.

Applies options to all nested resource definitions.

Useful for applying common configuration to a group of resources. Accepts the same options as #resources: only, except, defaults, constraints, controller, param, path.

Examples:

instance_eval style

with_options only: [:index, :show] do
  resources :reports
  resources :analytics
end

yield style

with_options only: [:index, :show] do |resource|
  resource.resources :reports
  resource.resources :analytics
end

Parameters:

  • options (Hash) (defaults to: {})

    ({}) The options to apply to nested resources.

Yields:

  • Block containing resource definitions.

Yield Parameters:



596
597
598
# File 'lib/apiwork/api/base.rb', line 596

def with_options(options = {}, &block)
  @root_resource.with_options(options, &block)
end