Controller
Instead of supplying an endpoint body inline, you can also reference a method by name (as a :symbol
).
Itsi will attach the method, resolved by name within the current controller scope, to the endpoint.
E.g.
Itsi.rb
controller UserController.new
get "", :index
The default controller scope is the parent Itsi.rb
config file.
However you can use the controller
middleware to explicitly set a controller scope per location block. All named endpoints will then be satisfied by the current controller.
Itsi will check for the presence and structure of all:
- Controller methods
- Schemas
at boot time ensuring that you can’t be caught out by naming mismatches at runtime, or during a hot-reload. If Itsi boots successfully, the controller methods exist and accept the correct parameters.
Basic Example
Itsi.rb
controller UserController.new
There are no special requirements for a controller in Itsi, it can be any ruby object, so long as it responds to the methods attached to the endpoint and accepts the request object as the first argument. This could be a singleton module, an instance, a struct etc.
Detailed Example
Itsi.rb
require_relative "schemas"
require_relative "user_controller"
location "/users*" do
controller UserController.new
post "/", :create
end
def home(req)
req.respond "I'm home"
end
# Default controller is just the top-level Itsi scope
get "/", :home
user_controller.rb
class UserController
def initialize()
# One time controller set-up here
end
def create(request, params: UserInputSchema, response_format: UserResponseSchema)
user = User.create!(params)
request.created \
json: {
id: user.id,
email: user.email,
full_name: "#{user.first_name} #{user.last_name}",
created_at: user.created_at.iso8601,
address: {
street: user.address.street,
city: user.address.city,
postcode: user.address.postcode
}
},
as: response_format
end
end
# Dummy data model.
Address = Struct.new(:street, :city, :postcode, :country, keyword_init: true)
class User < Struct.new(
:id, :email, :first_name, :last_name, :created_at,
:address, :age, :active, :roles, keyword_init: true)
def self.create!(params)
self.new(
id: Random.rand(1000000...99999999),
address: Address.new(params.delete :address),
**params,
created_at: Time.now
)
end
end
schemas.rb
AddressSchema = {
_required: %i[street city postcode],
street: String,
city: String,
postcode: String,
country: String # Optional
}
UserInputSchema = {
_required: %i[first_name last_name email address],
first_name: String,
last_name: String,
email: String,
age: Integer,
active: :Boolean,
roles: Array[String],
address: AddressSchema
}
UserResponseSchema = {
_required: %i[id email full_name],
id: Integer,
email: String,
full_name: String,
created_at: String,
address: AddressSchema
}
curl http://0.0.0.0:3000/users -H 'Accept: application/json' -H 'Content-Type: application/json' -d '{"id": 3, "age": "nine", "first_name":8,"last_name":"test","email":"test", "address": {"street":"1 Main Street","city":"Wellington","postcode":1234}}'
{"error":"Validation failed: Invalid value for Integer at age: \"nine\" (invalid value for Integer(): \"nine\")"}%
curl http://0.0.0.0:3000/users \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-d '{"id": 3, "age": "ninety-nine", "first_name":"John","last_name":"Smith","email":"test", "address": {"street":"1 Main Street","city":"Wellington","postcode":1234}}'
{
"error":"Validation failed: Invalid value for Integer at age: \"ninety-nine\" (invalid value for Integer(): \"nine\")"}%
curl http://0.0.0.0:3000/users \
-H 'Accept: application/json' \
-H 'Content-Type: application/json' \
-d '{"id": 3, "age": 99, "first_name":"John","last_name":"Smith","email":"test", "address": {"street":"1 Main Street","city":"Wellington","postcode":1234}}'
{
"id":46895213,
"email":"test",
"full_name":"John Smith",
"created_at":"2025-04-20T08:47:28+12:00",
"address":{
"street":"1 Main Street",
"city":"Wellington",
"postcode":"1234",
"country":null
}
}
curl http://0.0.0.0:3000/
I'm home
Module as a Controller
Itsi.rb
module UserController
module_function
def create(req, params)
req.ok json: User.create(params)
end
end
controller User
post "/", :create