はじめに
Sinatraでデータベースを扱うためにネットで色々見ていたのですが,情報が古かったり断片的であったりして,思い通りに動かないことが多々あったので,最小限にデータベースを扱う方法を自分なりにまとめました.データベースではsqlite3を使用します.
とりあえず簡単にSinatraでデータベースを扱いたい人向けです.
環境
$ ruby -v
ruby 2.6.0p0 (2018-12-25 revision 66547)
$ gem -v
3.0.1
$ bundler -v
Bundler version 2.0.1
$ sqlite3 -version
3.27.2 2019-02-25 16:06:06
SQLファイルからDBを作成
今回使用したファイルはGitHubにあげています.
Sinatra Sample 1
ファイル構成はこんな感じです.
$ tree
├── Gemfile
├── Gemfile.lock
├── app.rb
├── config.ru
├── db
│ ├── messages.db
│ └── seeds.sql
├── vendor
│ └── bundle
└── views
├── layout.erb
└── show.erb
gemのインストール
$ bundle init
-> Gemfile
の編集 -> $ bundle install --path=vendor/bundle
で必要なgemをインストールします.
# gem "rails"
gem 'sinatra'
gem 'sinatra-contrib'
gem 'activerecord'
gem 'sinatra-activerecord'
gem 'sqlite3'
最小限にはこれぐらいかと.
DBの作成
この章では,SQLファイルからデータベースを作成します.
drop table if exists messages;
create table messages(
name text,
comment text
);
insert into messages values('aaa', 'Hello'); -- (1)
insert into messages(name, comment) values('bbb', 'Hello World'); -- (2)
messagesテーブルを作成,名前(name)とコメント(comment)を管理します.
(1)と(2)は書き方は違いますが,同じくレコードの挿入をしています.ただし,(1)を用いる場合,カラム数と引数の数が合わないとエラーとなります.
以下のコマンドで実際にデータベースを作成します.
$ cd db
$ sqlite3 messages.db < seed.sql
これで新たにmessages.db
ファイルが作成されます.
(ちなみに,拡張子はdb
でなくても良いみたいです.)
色々確認してみましょう.
$ sqlite3 messages.db
SQLite version 3.27.2 2019-02-25 16:06:06
Enter ".help" for usage hints.
sqlite> .database
main: ~/db/messages.db
sqlite> .schema
CREATE TABLE messages(
name text,
comment text
);
sqlite> select * from messages;
aaa|Hello
bbb|Hello World
sqlite> .quit
作成およびレコードの挿入ができていることが確認できました.
ActiveRecordでレコードの取り出し
今回は,データを取り出すために以下のファイルを作成しました.
Sinatraの書き方等については扱いません.
require 'bundler'
Bundler.require
# 接続部分
ActiveRecord::Base.establish_connection(
adapter: 'sqlite3',
database: './db/messages.db'
)
class Message < ActiveRecord::Base
end
get '/' do
"Number of Messages: #{Message.count}"
end
get '/show' do
@messages = Message.all
erb :show
end
接続部分は,他にも書き方はありますが,とりあえずこれで.sqlite3で./db/messages/db
に接続します.
また,show.erb
は以下のようになっています.共通部分layout.erb
も作成していますが,中身は特にないので今回は省略.
<ul>
<% @messages.each do |message| %>
<li><%= message.name %>: <%= message.comment %></li>
<% end %>
</ul>
これで完成です.
bundle exec ruby app.rb
を実行して,ブラウザでlocalhost:4567
にアクセスしてみましょう.
(config.ru
を用いる場合は,bundle exec rackup
でlocalhost:9292
.)
/
でデータベースに格納されているレコード数を確認でき,/show/
でデータベースに格納されているレコードを確認できるようになっています.
レコードの追加や削除は,パラメータ等紹介しないといけないことが多いので,今回は省略します.なので,このプログラムでは,sqlite3
コマンドでsql文で追加等をするしか方法はありません.
マイグレーションファイルからDBを作成
今回使用したファイルはGitHubにあげています.
Sinatra Sample 2
ファイル構成はこんな感じです.
$ tree
├── Gemfile
├── Gemfile.lock
├── Rakefile
├── app.rb
├── config.ru
├── db
│ ├── messages.db
│ ├── migrate
│ │ └── 20190331060225_create_messages.rb
│ └── schema.rb
├── vendor
└── views
├── layout.erb
└── show.erb
gemのインストール
# gem "rails"
gem 'sinatra'
gem 'sinatra-contrib'
gem 'activerecord'
gem 'sinatra-activerecord'
gem 'rake'
gem 'sqlite3'
一つ目とほぼ同じですが,rake
を追加でインストールします.
DBの作成
rake
コマンドの準備
インストールしただけでは,rake
コマンドは使えないので,Rakefile
を作成します.
require 'sinatra/activerecord'
require 'sinatra/activerecord/rake'
require './app'
以下のコマンドで使えるようになったか確認します.
$ bundle exec rake -T
...
rake db:create_migration # Create a migration (parameters: NAME, VERSION)
rake db:migrate # Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)
...
上記のコマンドで,使えるコマンド一覧を出力します.上記のように色々出てこれば使えるようになっています.
マイグレーションファイルの作成
データベースの設計図となるマイグレーションファイルを作成します.
$ bundle exec rake db:create_migration NAME=create_messages
db/migrate/20190331052506_create_messages.rb
db/migrate/
下にマイグレーションファイルが作成されます.
今回は,一つ目の例と同じようにメッセージという形で名前とコメントを管理したいので,名前をcreate_messagesとしました.
また,ファイルの先頭の数字は,作成した日時を表しており,被らないようになっています.
このファイルを編集します.
class CreateMessages < ActiveRecord::Migration[5.2]
def change
create_table :messages do |t|
t.string :name
t.string :comment
end
end
end
マイグレーションファイルからDBを作成
以下のコマンドでデータベースを作成します.
$ bundle exec rake db:migrate
== 20190331052506 CreateMessages: migrating ===================================
-- create_table(:messages)
-> 0.0010s
== 20190331052506 CreateMessages: migrated (0.0011s) ==========================
新たに./db/messages.db
というファイルが作成されます.確認してみます.
$ sqlite3 db/messages.db
SQLite version 3.27.2 2019-02-25 16:06:06
Enter ".help" for usage hints.
sqlite> .database
main: ~/db/messages.db
sqlite> .schema
CREATE TABLE IF NOT EXISTS "schema_migrations" ("version" varchar NOT NULL PRIMARY KEY);
CREATE TABLE IF NOT EXISTS "ar_internal_metadata" ("key" varchar NOT NULL PRIMARY KEY, "value" varchar, "created_at" datetime NOT NULL,
"updated_at" datetime NOT NULL);
CREATE TABLE IF NOT EXISTS "messages" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar, "comment" varchar);
CREATE TABLE sqlite_sequence(name,seq);
sqlite> insert into messages(name, comment) values('aaa', 'hello');
sqlite> select * from messages;
1|aaa|hello
sqlite> .quit
.schema
と打った時の出力に関しては要勉強.
データベースには,作った時点では,何も入っていないので,sql文でサンプルを一つ入れておきました.
ActiveRecordでレコードの取り出し
最後に1つ目の例と同じapp.rb
を実行するとブラウザで確認できます.
bundle exec ruby app.rb
-> localhost:4567
bundle exec rackup
-> localhost:9292
こちらも今回の実装の場合,レコードの追加等はsql文で行うしか方法はありません.
最後に
今回は,とりあえずSinatraでデータベースを扱うプログラムを最小限に作成しました.とりあえず動かしたいということで,効率やセキュリティ等は全然考えていません.
データベースを触るのは初めてで,今回の実装では問題があったり,非効率であるかもしれません.
もし何か気になることや参考になるものがあれば,コメントお願いします!