roda-sequel-stack を使ってみた
Ruby で ActiveRecord じゃなくて Sequel を使いたい場合のウェブフレームワークは何がいいかなぁ。Hanami かな。まあ Rails で Sequel 使ってもいいんだけども。
とつぶやいたら本人直々に
I recommend Roda+Sequel https://roda.jeremyevans.net
と、roda-sequel-stack を教えてもらったので使ってみる。
初期設定
git clone でローカルにコピー。
% git clone https://github.com/jeremyevans/roda-sequel-stack.git hoge
% cd hoge
roda-sequel-stack 自体の Git 履歴は要らないので削除して新しくリポジトリを作った方がいいかも。
% rm -rf .git
% git init
% git commit --allow-empty -m 'Initial commit'
Hoge アプリとしてセットアップ。
% rake 'setup[Hoge]'
% bundle install
デフォルトだと PostgreSQL だけど MySQL を使いたいので変更。
-gem 'sequel_pg', '>= 1.8', require: 'sequel'
+gem 'ruby-mysql', '>= 4.0', require: 'mysql'
簡単のために MySQL は Docker Compose を使用。
services:
db:
image: mysql:8.0.33
ports:
- "127.0.0.1:13306:3306"
volumes:
- db:/var/lib/mysql
environment:
MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
volumes:
db:
データベースとユーザーを作成。
% docker-compose up -d
% docker-compose exec db mysql
mysql> create database hoge_production;
mysql> create database hoge_development;
mysql> create database hoge_test;
mysql> create user hoge;
mysql> grant all on `hoge\_%`.* to hoge;
データベース接続情報を設定。
...
- ENV['HOGE_DATABASE_URL'] ||= "postgres:///hoge_test?user=hoge"
+ ENV['HOGE_DATABASE_URL'] ||= "mysql://hoge@127.0.0.1:13306/hoge_test"
...
- ENV['HOGE_DATABASE_URL'] ||= "postgres:///hoge_production?user=hoge"
+ ENV['HOGE_DATABASE_URL'] ||= "mysql://hoge@127.0.0.1:13306/hoge_production"
...
- ENV['HOGE_DATABASE_URL'] ||= "postgres:///hoge_development?user=hoge"
+ ENV['HOGE_DATABASE_URL'] ||= "mysql://hoge@127.0.0.1:13306/hoge_development"
...
rackup をインストールしてサービスを起動。
% gem install rackup
% rackup -p 8080
ここでブラウザで http://localhost:8080 にアクセスすると次のようなページが表示される。
よくあるサンプルサービスを作ってみる
マイグレーション
Article モデルを作成する。サンプルのマイグレーションファイルは削除。
% rm migrate/001_tables.rb
新しくマイグレーションファイルを作成。Sequel のマイグレーションファイルの書き方は Sequel の schema_modification.rdoc を参照。
Sequel.migration do
change do
create_table :articles do
primary_key :id
String :title
String :body, size: 1024
end
end
end
マイグレーション実行。
% rake dev_up
モデル
Article モデル作成。
class Article < Sequel::Model
end
ルーティング(コントローラー)
ルートファイル作成。Rails でいうところのコントローラー。
書き方については Roda の README.rdoc を。
class Hoge
hash_branch('articles') do |r|
r.is do
@articles = Article.all
view 'index'
end
end
end
ビュー
ビューファイル作成。erb ファイルなので Rails のビューファイルとだいたい同じ。
<table>
<tr>
<th>タイトル</th>
<th>作成日時</th>
</tr>
<% @articles.each do |article| %>
<tr>
<td><%= article.title %></td>
<td><%= article.created_at %></td>
</tr>
<% end %>
</table>
これで http://localhost:8080/articles にアクセスすると記事の一覧が表示されるはずだけど、まだデータが何も無いので何も表示されない。
IRB(コンソール)
rake dev_irb
で irb を起動して Article オブジェクトを作ってみる。Rails の rails console
みたいなもの。
% rake dev_irb
irb(main):001:0> Article.create(title: 'ほげほげほげほげ', body: "1行目\n2行目", created_at: Time.now)
表示された。
CSS
CSS をいじってテーブルに枠線をつけてみる。
th {
border: solid 1px
}
td {
border: solid 1px
}
リンク
タイトルをクリックすると本文が見れるようにしてみる。
- <td><%= article.title %></td>
+ <td><a href="/articles/<%=article.id%>"><%= article.title %></a></td>
これでタイトルがリンクになった。でもちょっとアレなんで、link_to プラグインを使ってみる。
Article オブジェクトのパスを設定。
plugin :link_to
path Article do |article|
"/articles/#{article.id}"
end
link_to
メソッドを呼ぶようにビューを書き換え。
- <td><a href="/articles/<%=article.id%>"><%= article.title %></a></td>
+ <td><%== link_to(article.title, article) %></a></td>
少し簡単になった。
リンクを押したときに本文を表示するためにルートファイルを変更してビューファイルを作成。
class Hoge
hash_branch('articles') do |r|
r.is do
@articles = Article.all
view 'index'
end
r.is Integer do |id|
@article = Article.with_pk!(id)
view "show"
end
end
end
<dl>
<dt>タイトル</dt>
<dd><%= @article.title %></dd>
<dt>作成日時</dt>
<dd><%= @article.created_at %></dd>
<dt>本文</dt>
<textarea readonly><%= @article.body %></textarea>
</dl>
新規登録
さっきは irb から記事レコードを作ったけどブラウザから登録できるページを作ってみる。
<form method="post" action="/articles">
<dl>
<dt>タイトル</dt>
<dd><input type="text" name="title"></dd>
<dt>本文</dt>
<dd><textarea name="body"></textarea></dd>
</dl>
<input type="submit">
</form>
ルートファイルはこんな感じ。
class Hoge
hash_branch('articles') do |r|
r.is do
@articles = Article.all
view "index"
end
r.is Integer do |id|
@article = Article.with_pk!(id)
view "show"
end
r.is 'new' do
view "new"
end
end
end
これで http://localhost:8080/articles/new にアクセスすると新規登録画面が表示される。
POST を受け付けるようにルートファイルを変更。
class Hoge
hash_branch('articles') do |r|
r.is do
r.post do
Article.create(title: r.params['title'], body: r.params['body'], created_at: Time.now)
r.redirect
end
r.get do
@articles = Article.all
view "index"
end
end
r.is Integer do |id|
@article = Article.with_pk!(id)
view "show"
end
r.is 'new' do
view "new"
end
end
end
でも実際に POST してみると Invalid Security Token というエラーになってしまう。
ビューファイルに csrf_tag
を追加。
<form method="post" action="/articles">
<dl>
<dt>タイトル</dt>
<dd><input type="text" name="title"></dd>
<dt>本文</dt>
<dd><textarea name="body"></textarea></dd>
</dl>
<%== csrf_tag('/articles') %>
<input type="submit">
</form>
これであたらしい記事を作成できるようになった。
おわり
roda-sequel-stack は gem でもないし、Rails みたいなフルスタックフレームワークというよりは、Roda と Sequel やその他ライブラリを使ってフルスタックフレームワークを作るためのサンプルみたいな感じかも。
Sequel は10年以上使ってるし、Roda もなかなか良さそうなので、Rails よりも好きかも。
Discussion