この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:7
ページ更新者:guest
更新日時:2026-06-11 07:12:00

タイトル: コントローラーの作成と基本
SEOタイトル: Julia Genie Framework コントローラー作成完全ガイド(MVC / ルート / JSON)

この記事の要点
  • Genie = Julia の Rails 風 MVC フルスタック Web フレームワーク
  • 導入: using Pkg; Pkg.add("Genie")Genie.Generator.newcontroller("UserController") で雛形生成
  • ルート → コントローラ関数 → ビューの流れ。route("/users", UserController.index)
  • JSON レスポンスGenie.Renderer.Json.json(payload)
  • ビュー.jl.html(HTML 内 Julia 式)/ .jl.md(Markdown)。Genie 5.x が現行

Genie Framework とは

Genie は Julia 製のフルスタック Web フレームワークで、Ruby on Rails や Django にインスパイアされた MVC アーキテクチャを持ちます。Julia の高速性を活かしてサイエンス系 / シミュレーション系 Web アプリ、ダッシュボード、API サーバに使われます。Genie Apps(フルスタック)、Stipple(リアクティブ UI)、SearchLight(ORM)などのサブパッケージで構成。

環境セットアップ

# Julia REPL(julia コマンドで起動)
using Pkg
Pkg.add("Genie")

# バージョン確認
using Genie
@info "Genie version" pkgversion(Genie)

新規アプリ作成

using Genie
Genie.Generator.newapp("MyApp")

# 生成される構成(抜粋):
# MyApp/
# ├── Project.toml
# ├── Manifest.toml
# ├── bootstrap.jl
# ├── config/
# │   ├── env/        ← 環境別設定 (dev / prod / test)
# │   ├── initializers/
# │   └── routes.jl   ← ルート定義 ★
# ├── src/
# ├── app/
# │   ├── resources/
# │   │   └── home/   ← デフォルト resource
# │   └── layouts/
# └── public/

コントローラ生成

# プロジェクトディレクトリで Julia REPL を開いて
cd("MyApp")
using Genie

# Genie 5.x のジェネレータ
Genie.Generator.newcontroller("Users")

# 以下が作成される:
# app/resources/users/
#   ├── UsersController.jl       ← コントローラ
#   ├── Users.jl                  ← モデル (任意)
#   └── views/                    ← ビュー

シンプルなコントローラを書く

# app/resources/users/UsersController.jl
module UsersController

using Genie.Renderer
using Genie.Renderer.Json
using Genie.Requests

# 一覧 (index)
function index()
    users = [
        Dict("id" => 1, "name" => "Alice"),
        Dict("id" => 2, "name" => "Bob"),
    ]
    return json(users)
end

# 詳細 (show)
function show()
    id = params(:id)
    user = Dict("id" => parse(Int, id), "name" => "Alice")
    return json(user)
end

# 作成 (create)
function create()
    payload = jsonpayload()           # POST body の JSON
    name = get(payload, "name", "")
    return json(Dict("created" => true, "name" => name), status = 201)
end

# 更新 (update)
function update()
    id = params(:id)
    payload = jsonpayload()
    return json(Dict("id" => id, "updated" => true, "data" => payload))
end

# 削除 (destroy)
function destroy()
    id = params(:id)
    return json(Dict("id" => id, "deleted" => true))
end

end # module

ルートの定義

# config/routes.jl
using Genie, Genie.Router
using UsersController

# 個別ルート
route("/users",        UsersController.index,   method = GET)
route("/users/:id",    UsersController.show,    method = GET)
route("/users",        UsersController.create,  method = POST)
route("/users/:id",    UsersController.update,  method = PUT)
route("/users/:id",    UsersController.destroy, method = DELETE)

# 名前付きルート(URL ヘルパーで使う)
route("/users",        UsersController.index,   method = GET, named = :users_index)

# JSON API 専用接頭辞
route("/api/v1/users", UsersController.index, method = GET)

# HTML ビューを返すルート
route("/") do
    html(:home, :index)   # app/resources/home/views/index.jl.html を返す
end

サーバ起動

# Julia REPL で
using Genie
Genie.loadapp()
Genie.up()

# → http://127.0.0.1:8000

# シェルから直接
# julia --project=. -e "using Genie; Genie.loadapp(); up(async=false)"

# 環境を指定
# GENIE_ENV=prod julia --project=. -e "using Genie; ..."

# テスト
# curl http://127.0.0.1:8000/users
# [{"id":1,"name":"Alice"},{"id":2,"name":"Bob"}]

パラメータの受け取り

取得元取得方法
URL パラメータparams(:id)/users/:id → id 取得
クエリ文字列params(:page)?page=2 → "2"
POST フォームpostpayload()Dict として全フィールド
JSON ボディjsonpayload()Dict にパース済
ヘッダgetheaders()Dict
Cookiegetcookies()Dict
using Genie.Requests

function search()
    # ?q=julia&page=2
    q     = params(:q, "")           # 第 2 引数はデフォルト値
    page  = parse(Int, params(:page, "1"))
    limit = parse(Int, params(:limit, "20"))

    return json(Dict(
        "query" => q,
        "page" => page,
        "limit" => limit,
    ))
end

function login()
    body = jsonpayload()
    email = get(body, "email", nothing)
    password = get(body, "password", nothing)

    if email === nothing || password === nothing
        return json(Dict("error" => "Missing fields"), status = 400)
    end

    return json(Dict("token" => "fake-jwt-token"))
end

ビューを返す(HTML レスポンス)

HTML テンプレート (.jl.html)

<!-- app/resources/users/views/index.jl.html -->
<h1>Users</h1>
<ul>
  <% for u in users %>
    <li><%= u["name"] %> (id: <%= u["id"] %>)</li>
  <% end %>
</ul>

<p>Total: <%= length(users) %></p>

コントローラからビューを呼ぶ

module UsersController

using Genie.Renderer, Genie.Renderer.Html
using Genie.Requests

function index()
    users = [
        Dict("id" => 1, "name" => "Alice"),
        Dict("id" => 2, "name" => "Bob"),
    ]
    return html(:users, :index, users = users)
    # app/resources/users/views/index.jl.html に users を渡す
end

end

Markdown ビュー (.jl.md)

<!-- app/resources/about/views/index.jl.md -->
# About

This site runs on **Genie Framework** <%= Genie.Configuration.GENIE_VERSION %>.

- Julia version: <%= VERSION %>
- Environment: <%= Genie.Configuration.config.app_env %>

レスポンスの種類

関数用途モジュール
json(payload)JSON レスポンスGenie.Renderer.Json
html(:resource, :view, vars...)HTML テンプレートを描画Genie.Renderer.Html
respond(string, status)素の文字列Genie.Renderer
redirect(&quot;/path&quot;)リダイレクトGenie.Renderer
sendfile(&quot;path&quot;)ファイル送信Genie.Renderer

ステータスコードとヘッダ

function not_found()
    return json(Dict("error" => "User not found"), status = 404)
end

function with_custom_header()
    return json(
        Dict("ok" => true),
        status = 200,
        headers = Dict(
            "X-Request-Id" => "abc123",
            "Cache-Control" => "no-cache",
        ),
    )
end

function created()
    return json(Dict("id" => 42), status = 201, headers = Dict(
        "Location" => "/users/42",
    ))
end

例外処理

using Genie.Exceptions

function show()
    id = params(:id)
    user = find_user(id)
    if user === nothing
        throw(ExceptionalResponse(json(
            Dict("error" => "Not found"),
            status = 404,
        )))
    end
    return json(user)
end

ミドルウェア相当(before / after フック)

# config/initializers/middleware.jl などで
using Genie.Router

# 全リクエストの前にログ出力
Genie.Router.before_request() do
    @info &quot;Request&quot; method = params(:method) path = params(:path)
end

# CORS のためのレスポンス改変はミドルウェアで
# config/initializers/cors.jl
push!(Genie.Router.pre_match_hooks, function (params)
    # ...
end)

MVC 全体像(おさらい)

レイヤ役割配置
Modelデータ定義、DB アクセス(SearchLight ORM)app/resources/<name>/<Name>.jl
View表示テンプレートapp/resources/<name>/views/*.jl.html
Controllerリクエスト処理app/resources/<name>/<Name>Controller.jl
RouterURL → Controller 関数のマッピングconfig/routes.jl

テスト

# test/test_users.jl
using Test
using HTTP
using Genie

@testset &quot;UsersController&quot; begin
    response = HTTP.get(&quot;http://127.0.0.1:8000/users&quot;)
    @test response.status == 200

    payload = HTTP.JSONService.json(String(response.body))
    @test length(payload) == 2
    @test payload[1][&quot;name&quot;] == &quot;Alice&quot;
end

トラブルシューティング

症状原因対処
404 Not Found なのにルートはあるHTTP メソッド指定の不一致method = POST 等を確認
UsersController が見つからないroutes.jl で using 漏れusing UsersController 追加
params(:id) が nothingルートが /users:id プレースホルダ無し/users/:id に修正
JSON が文字列で返るrespond() ではなく json() を使うGenie.Renderer.Json 経由
変更が反映されない開発時はコード変更後再起動 or Revise.jl 導入using Revise; Genie.loadapp()

FAQ

Q: 自動リロードしたい
A: Revise.jl を使うと Julia コードの変更を REPL から検知して反映できます。Genie の REPL 開発フローと相性が良いです。

Q: Genie と Stipple の関係は?
A: Genie は基盤 Web フレームワーク、Stipple は Genie の上に乗るリアクティブ UI ライブラリ(Vue 系)。サイエンス系ダッシュボードは Stipple + GenieFramework がよく使われます。

Q: Django や Rails より速い?
A: Julia ネイティブの速度を活かせるので CPU バウンドな処理(数値計算、画像処理)では速い。I/O バウンドな単純 API では同等。エコシステムは Django/Rails が圧倒的に充実。