Base
Base class for contracts.
Validates requests and defines response shapes. Drives type generation and request parsing. Types are defined manually per action or auto-generated from a linked representation.
Example: Manual contract
class InvoiceContract < Apiwork::Contract::Base
action :create do
request do
body do
string :title
decimal :amount, min: 0
end
end
end
endExample: With representation
class InvoiceContract < Apiwork::Contract::Base
representation InvoiceRepresentation
endClass Methods
.abstract!
.abstract!
Marks this contract as abstract.
Abstract contracts serve as base classes for other contracts. Use this when creating application-wide base contracts that define shared imports or configuration. Subclasses automatically become non-abstract.
Returns
void
Example: Application base contract
class ApplicationContract < Apiwork::Contract::Base
abstract!
end.abstract?
.abstract?
Whether this contract is abstract.
Returns
Boolean
.action
.action(name, replace: false, &block)
Defines or extends an action on this contract.
Multiple calls with the same name merge definitions (declaration merging).
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
name | Symbol | The action name. Matches your controller action. | |
replace | Boolean | false | Whether to discard any existing definition and start fresh. Use when overriding auto-generated actions from representation. |
Returns
Yields Contract::Action
Example: Query parameters
action :index do
request do
query do
string? :search
integer? :page
end
end
endExample: Request body with custom type
action :create do
request do
body do
reference :invoice, to: :invoice_payload
end
end
response do
body do
reference :invoice
end
end
endExample: Override auto-generated action
action :destroy, replace: true do
response do
body do
reference :invoice
end
end
endExample: No content response
action :destroy do
response { no_content! }
end.enum
.enum(name, deprecated: false, description: nil, example: nil, values: nil)
Defines or extends an enum for this contract.
Subclasses inherit parent enums. In introspection, enums are prefixed with the contract's .identifier (e.g., :status in InvoiceContract becomes :invoice_status).
Multiple calls with the same name merge values (declaration merging).
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
name | Symbol | The enum name. | |
deprecated | Boolean | false | Whether deprecated. Metadata included in exports. |
description | String, nil | nil | The description. Metadata included in exports. |
example | String, nil | nil | The example. Metadata included in exports. |
values | Array<String>, nil | nil | The allowed values. |
Returns
void
Example: Define and reference
enum :status, values: %w[draft sent paid]
action :update do
request do
body do
string :status, enum: :status
end
end
endExample: Inline values (without separate definition)
action :index do
request do
query do
string? :priority, enum: %w[low medium high]
end
end
end.fragment
.fragment(name, &block)
Defines a fragment type for this contract.
Fragments are only available for merging into other types and never appear as standalone types. Use fragments to define reusable field groups.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
name | Symbol | The fragment name. |
Returns
void
Yields API::Object
Example: Reusable timestamps
fragment :timestamps do
datetime :created_at
datetime :updated_at
end
object :invoice do
merge :timestamps
string :number
end.identifier
.identifier(value = nil)
Prefixes types, enums, and unions in introspection output.
Must be unique within the API. Derived from the contract class name when not set (e.g., RecurringInvoiceContract becomes recurring_invoice).
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
value | Symbol, String, nil | nil | The identifier prefix. |
Returns
String, nil
Example
class InvoiceContract < Apiwork::Contract::Base
identifier :billing
object :address do
string :street
end
# In introspection: :address becomes :billing_address
end.import
.import(klass, as:)
Imports types from another contract for reuse.
Imported types are accessed with a prefix matching the alias.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
klass | Class<Contract::Base> | The contract class to import types from. | |
as | Symbol | The alias prefix. |
Returns
void
Example
import UserContract, as: :user
# UserContract's :address becomes :user_address.introspect
.introspect(expand: false, locale: nil)
Returns introspection data for this contract.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
expand | Boolean | false | Whether to expand all types inline. |
locale | Symbol, nil | nil | The locale for translations. |
Returns
Example
InvoiceContract.introspect.object
.object(name, deprecated: false, description: nil, example: nil, &block)
Defines or extends an object type for this contract.
Subclasses inherit parent types. In introspection, types are prefixed with the contract's .identifier (e.g., :item in InvoiceContract becomes :invoice_item).
Multiple calls with the same name merge fields (declaration merging).
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
name | Symbol | The object name. | |
deprecated | Boolean | false | Whether deprecated. Metadata included in exports. |
description | String, nil | nil | The description. Metadata included in exports. |
example | Object, nil | nil | The example. Metadata included in exports. |
Returns
void
Yields API::Object
Example: Define and reference
object :item do
string :description
decimal :amount
end
action :create do
request do
body do
array :items do
reference :item
end
end
end
endExample: Different shapes for request and response
object :invoice do
uuid :id
string :number
string :status
end
object :invoice_payload do
string :number
string :status
end
action :create do
request do
body do
reference :invoice, to: :invoice_payload
end
end
response do
body do
reference :invoice
end
end
end.representation
.representation(klass)
Configures the representation class for this contract.
Adapters use the representation to auto-generate request/response types. Use .representation_class to retrieve.
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
klass | Class<Representation::Base> | The representation class. |
Returns
void
Example
class InvoiceContract < Apiwork::Contract::Base
representation InvoiceRepresentation
end.representation_class
.representation_class
The representation class for this contract.
Returns
Class<Representation::Base>, nil
See also
.union
.union(name, deprecated: false, description: nil, discriminator: nil, example: nil, &block)
Defines or extends a discriminated union for this contract.
Subclasses inherit parent unions. In introspection, unions are prefixed with the contract's .identifier (e.g., :payment_method in InvoiceContract becomes :invoice_payment_method).
Multiple calls with the same name merge variants (declaration merging).
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
name | Symbol | The union name. | |
deprecated | Boolean | false | Whether deprecated. Metadata included in exports. |
description | String, nil | nil | The description. Metadata included in exports. |
discriminator | Symbol, nil | nil | The discriminator field name. |
example | Object, nil | nil | The example. Metadata included in exports. |
Returns
void
Yields API::Union
Example: Define and reference
union :payment_method, discriminator: :type do
variant tag: 'card' do
object do
string :last_four
end
end
variant tag: 'bank_transfer' do
object do
string :bank_name
string :account_number
end
end
end
action :create do
request do
body do
reference :payment_method
end
end
endInstance Methods
#body
#body
The body for this contract.
Use this in controller actions to access validated request data. Contains type-coerced values matching your contract definition. Invalid requests are rejected before the action runs.
Returns
Hash
Example
def create
Invoice.create!(contract.body[:invoice])
end#invalid?
#invalid?
Whether this contract is invalid.
Returns
Boolean
#issues
#issues
The issues for this contract.
Returns
Array<Issue>
#query
#query
The query for this contract.
Use this in controller actions to access validated request data. Contains type-coerced values matching your contract definition. Invalid requests are rejected before the action runs.
Returns
Hash
Example
def index
Invoice.where(status: contract.query[:status])
end#valid?
#valid?
Whether this contract is valid.
Returns
Boolean