タイトル: アプリケーションの作成
SEOタイトル: Julia Genie アプリケーション作成完全ガイド
| この記事の要点 |
|
Genie アプリ生成の全体像
Genie はジェネレータコマンドで MVC 構成を一発でスキャフォールドできます。Rails の rails new、Laravel の laravel new と同じ位置づけです。
1. 新規アプリ生成
# Julia REPL を起動
julia
# Genie 読み込み
using Genie
# 新規アプリ作成 (MVC フル構成)
Genie.Generator.newapp("MyApp")
# 種類別ジェネレータ
Genie.Generator.newapp_webservice("MyAPI") # API 専用 (View 無し)
Genie.Generator.newapp_mvc("MyWeb") # MVC (DB 付き)
Genie.Generator.newapp_fullstack("MyFull") # MVC + アセットパイプライン
実行すると次のような処理が走ります:
- ディレクトリ作成
- Project.toml / Manifest.toml 生成
- 依存パッケージインストール
- config/secrets.jl にランダムキー生成
- REPL から自動で起動
2. 生成されるディレクトリ構造
MyApp/
├── bin/
│ ├── repl # REPL 起動
│ ├── server # 本番サーバ起動
│ └── runtask # タスク実行
├── bootstrap.jl
├── config/
│ ├── env/
│ │ ├── dev.jl
│ │ ├── prod.jl
│ │ └── test.jl
│ ├── initializers/
│ │ └── searchlight.jl
│ ├── routes.jl # ★ ルーティング定義
│ └── secrets.jl
├── app/
│ ├── resources/
│ │ └── users/
│ │ ├── UsersController.jl
│ │ ├── User.jl # モデル
│ │ └── views/
│ │ └── index.jl.html
│ └── layouts/
│ └── app.jl.html
├── db/
│ ├── migrations/
│ ├── connection.yml
│ └── seeds/
├── public/
│ ├── favicon.ico
│ └── img/
├── test/
└── Project.toml
3. ルーティング (config/routes.jl)
using Genie.Router
using UsersController
# 基本ルート
route("/") do
"Welcome to MyApp"
end
# パラメータ
route("/users/:id::Int") do
UsersController.show()
end
# HTTP メソッド指定
route("/users", UsersController.index)
route("/users", UsersController.create, method = POST)
route("/users/:id::Int", UsersController.update, method = PUT)
route("/users/:id::Int", UsersController.destroy, method = DELETE)
# リソースルート (CRUD 全部)
Router.resources(:users, UsersController)
# → GET /users UsersController.index
# → POST /users UsersController.create
# → GET /users/:id UsersController.show
# → PUT /users/:id UsersController.update
# → DELETE /users/:id UsersController.destroy
# 名前付きルート
route("/login", LoginController.show, named = :login)
linkto(:login) # "/login"
4. コントローラ
# app/resources/users/UsersController.jl
module UsersController
using Genie.Renderer.Html
using Genie.Renderer.Json
using Genie.Requests
using SearchLight
using Users # モデル
function index()
users = SearchLight.all(User)
html(:users, :index, users = users)
end
function show()
user = SearchLight.findone(User, id = params(:id))
isnothing(user) && return Genie.Router.error(404)
html(:users, :show, user = user)
end
function create()
data = jsonpayload()
user = User(name = data["name"], email = data["email"])
if SearchLight.save(user)
json(Dict("id" => user.id, "status" => "ok"), status = 201)
else
json(Dict("errors" => "validation failed"), status = 422)
end
end
end
5. モデル (SearchLight ORM)
# app/resources/users/User.jl
module Users
using SearchLight
import SearchLight.AbstractModel
Base.@kwdef mutable struct User <: AbstractModel
id::SearchLight.DbId = SearchLight.DbId()
name::String = ""
email::String = ""
created_at::String = ""
end
end
# config/initializers/searchlight.jl で接続
using SearchLight
SearchLight.Configuration.load() |> SearchLight.connect
# 利用例
users = SearchLight.find(User, SQLWhereExpression("name LIKE ?", "%alice%"))
user = SearchLight.findone(User, id = 1)
user.name = "New Name"
SearchLight.save!(user)
6. データベース設定 (db/connection.yml)
env: ENV["GENIE_ENV"]
dev:
adapter: PostgreSQL
host: localhost
port: 5432
database: myapp_dev
username: postgres
password: postgres
test:
adapter: SQLite
database: db/test.sqlite
prod:
adapter: PostgreSQL
host: db.example.com
database: myapp_prod
username: ENV["DB_USER"]
password: ENV["DB_PASS"]
7. マイグレーション
# REPL から
using SearchLight, SearchLight.Migrations
# マイグレーション作成
SearchLight.Migrations.new_table_migration(:users)
# db/migrations/xxxxxxxx_create_table_users.jl
module CreateTableUsers
import SearchLight.Migrations: create_table, column, primary_key,
add_index, drop_table
function up()
create_table(:users) do
[
primary_key()
column(:name, :string, limit = 100)
column(:email, :string, limit = 200, not_null = true)
column(:created_at, :datetime)
]
end
add_index(:users, :email, unique = true)
end
function down()
drop_table(:users)
end
end
# 実行
SearchLight.Migrations.last_up() # 最新を up
SearchLight.Migrations.last_down() # ロールバック
SearchLight.Migrations.status() # 状態確認
8. ビュー (.jl.html)
Users
<% for user in users %>
-
<%= user.name %>
(<%= user.email %>)
<% end %>
9. 本番ビルド (PackageCompiler)
Julia の弱点である「起動が遅い」を解消するため、システムイメージを事前生成します:
using PackageCompiler
# システムイメージ生成
create_sysimage(
[:Genie, :SearchLight, :MyApp];
sysimage_path = "MyApp.so",
precompile_execution_file = "precompile.jl",
)
# 起動時に指定
# julia -J MyApp.so --project=. bin/server
# → 初回起動 30 秒 → 2 秒
10. CLI でアプリ操作 (bin/runtask)
# REPL 起動
bin/repl
# サーバ起動 (本番)
bin/server
# カスタムタスク
bin/runtask seed_users
# マイグレーション
bin/repl
julia> using SearchLight.Migrations; last_up()
FAQ
Q: newapp() でエラーになる
A: 既存ディレクトリと衝突している可能性。空のディレクトリで再実行。または Genie.Generator.newapp_mvc 等を指定。
Q: SearchLight でなく別の ORM を使いたい
A: 直接 LibPQ.jl (PG) や MySQL.jl を呼んでも OK。コントローラから自由に SQL 実行可能。
Q: フロントは React / Vue を別で建てたい
A: API 専用なら newapp_webservice。CORS 設定後、フロントと分離開発できます。
Q: ホットリロードが効かない
A: Revise を Genie より先に読み込み、include でなく includet を使う。