用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/kemalcr/kemal --skill kemal-orm命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
正在显示 SKILL.md
| name | kemal-orm |
| description | Object-Relational Mapping (ORM) with Crecto and SQLite in Kemal, following established project patterns. |
| license | MIT |
This skill provides expert guidance on using Crecto ORM with Kemal applications and SQLite, strictly following patterns from kemal-by-example/budget-management-orm.
Dependencies: Include kemal, crecto, and sqlite3 in shard.yml and require them in the main application file.
Repository Setup: Centralize Crecto configuration in a config/repo.cr module:
module MyProject
module Repo
extend Crecto::Repo
config do |conf|
conf.adapter = Crecto::Adapters::SQLite3
conf.db = ENV["DATABASE_URL"]? || "sqlite3:./db/app.db"
end
end
end
Schema Initialization: Set up database schema tables with Repo.db_adapter.exec in a Schema.setup module:
module MyProject
module Schema
extend self
def setup
Repo.db_adapter.exec <<-SQL
CREATE TABLE IF NOT EXISTS budget_entries (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
kind TEXT NOT NULL,
amount_cents INTEGER NOT NULL,
notes TEXT NOT NULL DEFAULT '',
created_at DATETIME,
updated_at DATETIME
);
SQL
end
end
end
Model Definition: Subclass Crecto::Model, declare fields inside schema, and set validation rules:
module MyProject
class BudgetEntry < Crecto::Model
schema "budget_entries" do
field :title, String
field :kind, String
field :amount_cents, Int64
field :notes, String
end
validate_required :title
validate_inclusion :kind, %w[income expense]
end
end
Repository Operations:
query = Crecto::Repo::Query.new.order_by("id DESC"); Repo.all(BudgetEntry, query)Repo.get(BudgetEntry, id)entry = BudgetEntry.new; entry.title = title; Repo.insert(entry)entry.title = new_title; Repo.update(entry)Repo.delete(entry)config/repo.cr)require "crecto"
module BudgetManagementOrm
module Repo
extend Crecto::Repo
config do |conf|
conf.adapter = Crecto::Adapters::SQLite3
conf.db = ENV["DATABASE_URL"]? || "sqlite3:./db/budget.db"
end
end
end
config/schema.cr)require "./repo"
module BudgetManagementOrm
module Schema
extend self
def setup
Repo.db_adapter.exec <<-SQL
CREATE TABLE IF NOT EXISTS budget_entries (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
kind TEXT NOT NULL,
amount_cents INTEGER NOT NULL,
notes TEXT NOT NULL DEFAULT '',
created_at DATETIME,
updated_at DATETIME
);
SQL
end
end
end
models/budget_entry.cr)require "../config/repo"
module BudgetManagementOrm
class BudgetEntry < Crecto::Model
schema "budget_entries" do
field :title, String
field :kind, String
field :amount_cents, Int64
field :notes, String
end
validate_required :title
validate_inclusion :kind, %w[income expense]
def income? : Bool
kind == "income"
end
def expense? : Bool
kind == "expense"
end
def self.all_ordered : Array(BudgetEntry)
query = Crecto::Repo::Query.new.order_by("id DESC")
Repo.all(BudgetEntry, query)
end
def self.find(id : Int64) : BudgetEntry?
Repo.get(BudgetEntry, id)
end
def self.create(title : String, kind : String, notes : String, amount_cents : Int64)
entry = BudgetEntry.new
entry.title = title
entry.kind = kind
entry.notes = notes
entry.amount_cents = amount_cents
Repo.insert(entry)
end
def update_fields(title : String, kind : String, notes : String, amount_cents : Int64)
self.title = title
self.kind = kind
self.notes = notes
self.amount_cents = amount_cents
Repo.update(self)
end
def destroy
Repo.delete(self)
end
end
end
routes/entries.cr)get "/entries" do
entries = BudgetManagementOrm::BudgetEntry.all_ordered
render "src/views/entries/index.ecr", "src/views/layouts/application.ecr"
end
get "/entries/:id/edit" do |env|
id = env.params.url["id"]?.try(&.to_i64?)
entry = id ? BudgetManagementOrm::BudgetEntry.find(id) : nil
if entry
render "src/views/entries/edit.ecr", "src/views/layouts/application.ecr"
else
env.response.status = :not_found
"Entry not found"
end
end
post "/entries" do |env|
title = env.params.body["title"]?.try(&.strip) || ""
raw_kind = env.params.body["kind"]? || "expense"
kind = raw_kind == "income" ? "income" : "expense"
notes = env.params.body["notes"]?.try(&.strip) || ""
cents = BudgetManagementOrm::Money.parse_cents(env.params.body["amount"]? || "")
if !title.empty? && cents && cents > 0
BudgetManagementOrm::BudgetEntry.create(title, kind, notes, cents)
end
env.redirect "/entries"
end
post "/entries/:id/delete" do |env|
id = env.params.url["id"]?.try(&.to_i64?)
entry = id ? BudgetManagementOrm::BudgetEntry.find(id) : nil
entry.try(&.destroy)
env.redirect "/entries"
end
Int64 cents) to avoid floating-point rounding errors.Repo object rather than executing raw SQL strings directly in route handlers.validate_required, validate_format, and validate_inclusion inside model definitions for declarative data integrity.Schema.setup in your main entrypoint file before calling Kemal.run.Use when building, reviewing, debugging, testing, securing, or deploying web applications and HTTP APIs with the Kemal framework for Crystal. Covers Kemal routing, params, context, routers, filters, middleware, ECR, WebSockets, SSE, uploads, configuration, testing, and production concerns.
User authentication and session management in Kemal, following established project patterns.
Core Kemal development (routing verbs, parameters, modular router, version gates, response helpers).