13
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Sinatraで最小限にActiveRecordでDBを扱う

Last updated at Posted at 2019-03-31

はじめに

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をインストールします.

Gemfile
# gem "rails"
gem 'sinatra'
gem 'sinatra-contrib'
gem 'activerecord'
gem 'sinatra-activerecord'
gem 'sqlite3'

最小限にはこれぐらいかと.

DBの作成

この章では,SQLファイルからデータベースを作成します.

./db/seeds.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でなくても良いみたいです.)
色々確認してみましょう.

./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の書き方等については扱いません.

app.rb
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も作成していますが,中身は特にないので今回は省略.

./views/show.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 rackuplocalhost: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のインストール

Gemfile
# gem "rails"
gem 'sinatra'
gem 'sinatra-contrib'
gem 'activerecord'
gem 'sinatra-activerecord'
gem 'rake'
gem 'sqlite3'

一つ目とほぼ同じですが,rakeを追加でインストールします.

DBの作成

rakeコマンドの準備

インストールしただけでは,rakeコマンドは使えないので,Rakefileを作成します.

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としました.
また,ファイルの先頭の数字は,作成した日時を表しており,被らないようになっています.
このファイルを編集します.

./db/migrate/20190331052506_create_messages.rb
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でデータベースを扱うプログラムを最小限に作成しました.とりあえず動かしたいということで,効率やセキュリティ等は全然考えていません.
データベースを触るのは初めてで,今回の実装では問題があったり,非効率であるかもしれません.
もし何か気になることや参考になるものがあれば,コメントお願いします!

参考サイト

13
14
6

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?