はじめに
Heroku上のデータベースにデータを格納し,それを参照するだけの簡単なSinatraアプリを作成したかったのですが,少し詰まったので整理も兼ねて記事にします.
ActiveRecordを用いずにcsvファイルからHeroku上のデータベースに格納します.
Heroku上にデータベースを設置し,そのデータベースから読み取りのみを行うWebサービスを作りたい方や初期データを格納したいといった方向けの記事です.
準備: Sinatraアプリの作成
準備として,Sinatraを含めた本記事(作成したいアプリ)で必要なパッケージのインストールを行います.
$ mkdir sinatra-db
$ cd sinatra-db
$ bundle init
$ vim Gemfile
$ bundle install --path vendor/bundle --without production
# gem "rails"
gem "sinatra"
gem "sinatra-contrib"
gem "sinatra-activerecord", :require => 'sinatra/activerecord'
gem "activerecord", "~> 5.2.3"
gem "rake"
group :development do
gem 'sqlite3'
end
group :production do
gem 'pg'
gem "activerecord-postgresql-adapter"
end
2019年9月29日,ActiveRecordの最新バージョンは6.0.0ですが,データベース作成で不具合が発生するので,動作確認の取れている5.2.3をインストールします.
これ以降,~/sinatra-db/
を~
と表記します.
また,以下に本記事対象外のファイルを列挙します.簡単に説明すると,やっていることは単純にデータベース内のデータを表示しているだけです.
後々書くべきこともコード内には書いています.必要に応じてここに戻ってきて,見返してみてください.
require 'bundler'
Bundler.require
class App < Sinatra::Base
configure :development do
ActiveRecord::Base.establish_connection(
adapter: 'sqlite3',
database: 'db/development.db'
)
end
configure :production do
ActiveRecord::Base.establish_connection(ENV['DATABASE_URL'])
end
get '/' do
@comments = Comment.all
erb :index
end
end
class Comment < ActiveRecord::Base
end
<% @comments.each do |comment| %>
<div style="padding: 10px; margin-bottom: 10px; border: 1px dotted #333333;">
<h3><%= comment.title %></h3>
<h5><%= comment.detail %></h5>
by <%= comment.name %>
</div>
<% end %>
require './app'
run App
web: bundle exec rackup config.ru -p $PORT
準備: Herokuにアプリを作成
更に準備として,先にHeroku上にアプリのデプロイ先を作成しておきます.
ここはぱぱーっと行きます.詳しく知りたい方はブログ等を参考にしてください.
# Herolu CLIはインストール済を想定
$ heroku login
...
# リポジトリの作成
$ git init
$ git add .
$ git commit -m "first commit"
# デプロイ先の作成(アプリの名前は一意じゃないとダメみたいです.お好きな名前で.)
$ heroku create (app name)
# デプロイ(後々)
$ git push heroku master
データベースの作成とレコードの追加
本記事では,以下のようなテーブルをローカルとHeroku上に作成します.
ローカルではSQLite3,HerokuではPostgreSQLを使用します.
id | name | title | detail |
---|---|---|---|
1 | hoge | hello | Hello Sinatra |
2 | foo | foodbye | Goodbye Sinatra |
3 | bar | emergency | Reply Required |
以下のようなcsvファイルを用意します.
1,hoge,hello,Hello Sinatra
2,foo,goodbye,Goodbye Sinatra
3,bar,emergency,Reply Required
(1行目にid,name,title,detail
のようなカラムの名前を入れたかったのですが,後々Heroku上のテーブルに追加する際にエラーが起きてしまうので入れていません.)
ローカル
データベースの作成
別の記事を参考にマイグレーションファイルからデータベース(テーブル)を作成します.こちらも詳しくは先の記事を参考にしてください.
$ vim Rakefile
# 使えるコマンドの確認
$ bundle exec rake -T
...
# マイグレーションファイルの作成と編集
$ bundle exec rake db:create_migration NAME=create_comments
# => db/migrate/20190928154422_create_comments.rb
$ vim ./db/migrate/20190928154422_create_comments.rb
# データベースの作成
$ bundle exec rake db:migrate
require 'sinatra'
require 'sinatra/activerecord'
require 'sinatra/activerecord/rake'
require './app'
class CreateComments < ActiveRecord::Migration[5.2]
def change
create_table :comments do |t|
t.string :name
t.string :title
t.string :detail
end
end
end
マイグレーションファイルにて,idをカラムとして追加していませんが,マイグレーションする際に自動でidカラムが作成されるみたいなので,ここでは追加していません.
~/db
にdevelopment.db
とschema.rb
ができたと思います.
このdevelopment.db
がデータベースの本体です.
csvファイルからレコードの追加
データベースにSQLite3で直接接続し,コマンドでcsvファイルからレコードを追加します.
と言っても,コマンドを数ステップ打つだけでできてしまいます.
$ sqlite3 ./db/development.db
...
sqlite> .schema comments
CREATE TABLE IF NOT EXISTS "comments" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar, "title" varchar, "detail" varchar);
sqlite3> .separator ,
sqlite3> .import comments.csv comments
sqlite3> select * from comments;
1|hoge|hello|Hello Sinatra
2|foo|goodbye|Goodbye Sinatra
3|bar|emergency|Reply Required
sqlite3> .quit
無事レコードを追加することができました.
Sinatraアプリの方でも呼び出せるか確認してみましょう.
bundle exec rackup config.ru
と打ち,localhost:9292
にブラウザでアクセスしてみます.
Sinatra(ActiveRecord)の方でもレコードを呼び出すことができています.
これで,ローカルでのデータベースの構築は完了です.
Heroku上
次にHeroku上でデータベースの作成からcsvファイルのレコードの追加を行ってみます.
データベースの作成
Herokuでは,AddonとしてHeroku Postgresが提供されています.
これの無料プラン(hobby-dev)をアプリに追加して使用します.
$ heroku addons:create heroku-postgresql:hobby-dev
これだけで追加できました.
heroku pg:info
で情報を見たり,heroku pg:psql
で作成したデータベースにアクセスできます.
詳しくは,公式リファレンスやこちらのサイトも参考にしてください.
次にテーブルの作成です.と言っても,これ以降はローカルで行ったことと同じようなことを行うだけです.
はじめに,git push
でherokuにデプロイします.comments.csv
やマイグレーションファイルを含めてデプロイしている点がポイント(?)です.
(.vendor
やdb/development.db
等のローカルでしか必要のないファイルやディレクトリは適宜.gitignore
に追加してください.)
$ git add .
$ git commit -m "deploy"
$ git push heroku master
マイグレーションファイルからテーブルを作成します.
$ heroku run bundle exec rake db:migrate
heroku run
の後にコマンドを続けることで,Heroku上でそのコマンドを実行するということですね.
csvファイルからレコードの追加
最後に作成したテーブルにcsvファイルからレコードを追加しましょう.
ローカルではSQLite3でしたが,HerokuではPostgreSQLなので,少し書き方を変える必要がありますが,やっていることは同じです.
$ heroku pg:psql
...
(app name):DATABASE=> \copy comments (id, name, title, detail) from 'comments.csv' with csv
COPY 3
(app name):DATABASE=> select * from comments;
id | name | title | detail
----+------+-----------+-----------------
1 | hoge | hello | Hello Sinatra
2 | foo | goodbye | Goodbye Sinatra
3 | bar | emergency | Reply Required
(app name):DATABASE=> \q
レコードが追加されていますね.
最後に確認として,https://(app name).herokuapp.com/
にアクセスしてみてください.
ローカルで確認した時と同じように表示されていれば成功です!
終わりに
ボリュームの割にタイトルと中身のミスマッチ感がありますが,Sinatraアプリの作成からローカルおよびHerokuにデータベースを構築し,csvファイルからレコードを追加するところまでを書きました.
今回,「はじめに」で述べたように読み取りだけを行うアプリをHeroku上にて動かしたく,試行錯誤の結果,本記事のように進めると解決できたということで,色々ナンセンスな部分はあると思います.(個人的に,ファイルのほとんどをデプロイするのは如何なものかと思っています.)
もっと良いやり方あるよ〜って方はコメントお願いします.
また,書いているうちにデータベースとテーブルがごっちゃになってきたので,気が向いたらまた直します.
参考サイト
Heroku Postgres | Heroku Dev Center
Heroku アプリに PostgreSQL を導入する - Corredor
SQLite3 のテーブルに CSV でデータを読み込む - CUBE SUGAR CONTAINER
CSVファイルをデータベースにインポートする - Qiita