Ruby で ActiveRecord じゃなくて Sequel を使いたい場合のウェブフレームワークは何がいいかなぁ。Hanami かな。まあ Rails で Sequel 使ってもいいんだけども。
— とみたまさひろ🍣🍺 (@tmtms) 2023年5月27日
Ruby で ActiveRecord じゃなくて Sequel を使いたい場合のウェブフレームワークは何がいいかなぁ。Hanami かな。まあ Rails で Sequel 使ってもいいんだけども。
とつぶやいたら本人直々に
I recommend Roda+Sequel https://t.co/7Kz5JqprAU https://t.co/LbeBb3Yvna
— Jeremy Evans (@jeremyevans0) 2023年5月28日
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 を使用。
[docker-compose.yml]
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.rb]
... - 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 を参照。
[migrate/20230611001_articles.rb]
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 モデル作成。
[models/article.rb]
class Article < Sequel::Model end
ルーティング(コントローラー)
ルートファイル作成。Rails でいうところのコントローラー。 書き方については Roda の README.rdoc を。
[routes/articles.rb]
class Hoge hash_branch('articles') do |r| r.is do @articles = Article.all view 'index' end end end
ビュー
ビューファイル作成。erb ファイルなので Rails のビューファイルとだいたい同じ。
[views/articles/index.erb]
<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 をいじってテーブルに枠線をつけてみる。
[assets/css/app.scss]
th { border: solid 1px } td { border: solid 1px }
リンク
タイトルをクリックすると本文が見れるようにしてみる。
[views/articles/index.erb]
- <td><%= article.title %></td> + <td><a href="/articles/<%=article.id%>"><%= article.title %></a></td>
これでタイトルがリンクになった。でもちょっとアレなんで、link_to プラグインを使ってみる。
Article オブジェクトのパスを設定。
[app.rb]
plugin :link_to path Article do |article| "/articles/#{article.id}" end
link_to
メソッドを呼ぶようにビューを書き換え。
[views/articles/index.erb]
- <td><a href="/articles/<%=article.id%>"><%= article.title %></a></td> + <td><%== link_to(article.title, article) %></a></td>
少し簡単になった。
リンクを押したときに本文を表示するためにルートファイルを変更してビューファイルを作成。
[routes/articles.rb]
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
[views/articles/show.erb]
<dl> <dt>タイトル</dt> <dd><%= @article.title %></dd> <dt>作成日時</dt> <dd><%= @article.created_at %></dd> <dt>本文</dt> <textarea readonly><%= @article.body %></textarea> </dl>
新規登録
さっきは irb から記事レコードを作ったけどブラウザから登録できるページを作ってみる。
[views/articles/new.erb]
<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>
ルートファイルはこんな感じ。
[routes/articles.rb]
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 を受け付けるようにルートファイルを変更。
[routes/articles.rb]
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
を追加。
[views/articles/new.erb]
<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 よりも好きかも。