【4回目(前編)】Railsに挫折中の人が、Ruby/Sinatraから再入門してみた(全7回)
5/11より毎週土曜日、株式会社X-HACK主催の勉強会、
【全7回】Ruby / Vue.js「ゼロから」ウェブサービスを作る【初心者向け | 個別指導あり】
に参加しています。
学んだことをこちらでアウトプットしていきます!
今回は4回目!
1つでは到底まとめきれない充実した内容だったので、
前編:掲示板を作ってみよう!〜関数・モジュール化まで! ←(今回)
後編:スクレイピングデータをDBに保存〜proc、yieldについて!
に分けて説明します!
文中のコードはそのままコピペで動くはず?なので、
最初は処理が分からなくても、まず作ってみましょう!
動かない、間違っている所などあれば教えていただけると嬉しいです!
Sinatraで簡易掲示板を作ってみよう!
⭐︎準備
まずは前回の復習!ここは、さらっとできるようになりましょう!
詳しくは、前回の記事を参照してください!
・プロジェクト作成
【ターミナル】
$ mkdir day4-sinatra
$ cd day4-sinatra
$ bundle init
// ファイルの作成
$ touch app.rb
$ mkdir views
$ touch views/index.erb
・Gemfile編集
【day4-sinatra/Gemfile】
source "https://rubygems.org"
gem 'sinatra'
gem 'sinatra-contrib'
gem 'pg'
・bundle install
$ bundle install
または
$ bundle install --path vendor/bundle //(作者はこっち)
下記のファイル構成になっていたら、準備完成!
⭐︎テーブルを作成しよう!
ここからが今回の本題です!
まず、掲示板に投稿した内容を保存するためのテーブルを作成します。
ターミナル等から作ることももちろん可能ですが、面倒なので今回は rubyファイルからテーブル作成します。
・create_board_contets.rbの作成
【ターミナル】
$ touch day4-sinatra/create_board_contets.rb
・create_board_contets.rbを編集
今回は、簡易掲示板なので、「id」「name」「comment」「commented_at」の4つのカラムを作成します。
接続情報は前回Herokuに作成したPostgresの情報を入力すればOK!
【day4-sinatra/create_board_contets.rb】
require 'pg' #postgresのgem読み込み
# DB情報を確認して埋める
conn = PG::connect(
host: 'ホスト名',
user: 'ユーザー名',
password: 'パスワード',
dbname: 'データベース名',
port: '5432'
)
# テーブルを作成するSQL文を実行
conn.exec("
drop table board_contents;
CREATE TABLE board_contents (
id serial,
name text,
comment text,
commented_at timestamp,
PRIMARY KEY (id)
);"
)
・create_board_contets.rbを実行
【ターミナル】
$ ruby day4-sinatra/create_board_contets.rb
PGCommanderなどでテーブルが作成できているか確認できたら、掲示板用テーブルの作成が完了です!
⭐︎DB情報を悪用されないために
ここで一休み!
先程、Herokuに作成したPostgresの情報を入力しよう!と書きましたが、
実はこのままHeroku、Githubに公開してしまうと悪用されてしまう恐れが!
防ぐための設定をご紹介!
①"dotenv"というgemを使って、環境変数を設定
○"dotenv"とは?
→.envファイルに書いた設定を環境変数として簡単に読み込めるgem。
・Gemfileに"dotenv"を追記→bundle install
【day4-sinatra/Gemfile】
gem 'dotenv'
----------------------
【ターミナル】
$ bundle install
・「.env」ファイルを作成し、環境変数を設定
【ターミナル】
$ touch .env
-----------------
【day4-sinatra/.env】
// DB情報を記述
DATABASE_HOST='ホスト名'
DATABASE_USER='ユーザー名'
DATABASE_PASSWORD='パスワード'
DATABASE_NAME='データベース名'
DATABASE_PORT='5432'
・環境変数をapp.rbで読み込む
【day4-sinatra/app.rb】
require 'dotenv/load' # "dotenv"gemを読み込む
get '/' do
# 設定した環境変数を使う
connect = PG.connect(
host: ENV['DATABASE_HOST'],
user: ENV['DATABASE_USER'],
password: ENV['DATABASE_PASSWORD'],
dbname: ENV['DATABASE_NAME'],
port: ENV['DATABASE_PORT']
)
(省略)...
end
②「.gitignore」ファイルを作成し、gitで管理しない
→「.gitignore」に記述したファイルをgitは無視するので、Githubに公開される事もなくなる!
【ターミナル】
$ touch .gitignore
---------------------
【day4-sinatra/.gitignore】
.env
/vendor/bundle
これでDB接続情報が漏れる心配が無くなりました!\(^o^)/
⭐︎掲示板の画面を作ろう!
・index.erbの編集
【day4-sinatra/views/index.erb】
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>XHACK勉強会</title>
</head>
<body>
<!-- DBから取得したデータを表示 -->
<% @data.each do |data| %>
<ul>
<li>名前:<%= data["name"] %></li>
<li>コメント:<%= data["comment"] %></li>
<li>日時:<%= data["commented_at"] %></li>
</ul>
<% end %>
<!-- 掲示板フォーム -->
<form action="/comments" method="post">
名前:<input type="text" name="name">
<input class="form-control" type="text" placeholder="Default input" name="comment">
<input class="btn btn-light" type="submit" value="送信する">
</form>
</body>
</html>
こんな画面が完成!
⭐︎データを取得・登録しよう
【day4-sinatra/app.rb】
require 'sinatra'
require 'sinatra/reloader'
require 'pg'
require 'dotenv/load'
# DBからデータを取得する処理
get '/' do
# 1.Postgresと接続
conn = PG::connect(
host: ENV['DATABASE_HOST'],
user: ENV['DATABASE_USER'],
password: ENV['DATABASE_PASSWORD'],
dbname: ENV['DATABASE_NAME'],
port: ENV['DATABASE_PORT']
)
# 2.全データを取得するための、sql文を用意
@data = conn.exec("select * from board_contents;")
# 3.接続を終了する
conn.finish
# 4.index.erbに遷移する
erb :index
end
# DBに登録する処理
post '/comments' do
# 1.Postgresと接続
conn = PG.connect(
host: ENV['DATABASE_HOST'],
user: ENV['DATABASE_USER'],
password: ENV['DATABASE_PASSWORD'],
dbname: ENV['DATABASE_NAME'],
port: ENV['DATABASE_PORT']
)
# 2.フォームから入力された情報(パラメータ)を受け取る
name = params['name']
comment = params['comment']
# 3.登録するためのsql文を用意
sql = "INSERT INTO board_contents (name, comment, commented_at) VALUES ('#{name}', '#{comment}', current_timestamp);"
# 4.sql文を実行
@data = conn.exec(sql)
# 5.接続を終了する
conn.finish
# 6.もう一度、データ一を取得〜表示する処理を行う
redirect '/'
end
簡易掲示板、完成!!
フォームから入力すると、フォームの上に投稿内容が表示されるようになります\(^o^)/
⭐︎関数・モジュール化
最後に、関数・モジュール化について!
実は、先程の処理、重複した処理を書かれていたのに、気づきませんでした?!
DBとの接続〜実行〜終了までの部分!
【day4-sinatra/app.rb】
# ①Postgresと接続
conn = PG::connect(
host: ENV['DATABASE_HOST'],
user: ENV['DATABASE_USER'],
password: ENV['DATABASE_PASSWORD'],
dbname: ENV['DATABASE_NAME'],
port: ENV['DATABASE_PORT']
)
# ②SQL文を実行
@data = conn.exec(sql)
# ③接続を終了する
conn.finish
嫌だ!同じこと書きたくない!!絶対に嫌だ!!!
そんなわがままなお悩みを解決するのが、、、
「関数」、「モジュール化」です!!
○関数化
・重複した処理を「関数」で一つにまとめる
# 文字列で受け取ったsqlを実行する関数
def postgres(sql)
# ①Postgresと接続
conn = PG::connect(
host: ENV['DATABASE_HOST'],
user: ENV['DATABASE_USER'],
password: ENV['DATABASE_PASSWORD'],
dbname: ENV['DATABASE_NAME'],
port: ENV['DATABASE_PORT']
)
# ②SQL文を実行
data = conn.exec(sql)
# ③接続を終了する
conn.finish
data
end
post '/' do
# 関数を呼び出す
@data = postgres("select * from board_contents;")
erb :index
end
post '/comments' do
name = params["name"]
comment = params["comment"]
sql = "INSERT INTO board_contents (name, comment) VALUES ('#{name}', '#{comment}');"
# 関数を呼び出す
@data = postgres(sql)
redirect '/'
end
こうすると引数にSQL文を渡せば、DB処理はこの関数がやってくれます!
○モジュール化
更に、モジュール化すると他ファイルからも関数を呼び出すことができます!
・「mydatabase.rb」ファイルを作成
【ターミナル】
$ touch day4-sinatra/mydatabase.rb
・「mydatabase.rb」ファイルを編集
【day4-sinatra/mydatabase.rb】
require 'pg'
require 'dotenv/load'
module Mydatabase
def self.exec(sql)
@conn = PG.connect(
host: ENV['DATABASE_HOST'],
user: ENV['DATABASE_USER'],
password: ENV['DATABASE_PASSWORD'],
dbname: ENV['DATABASE_NAME'],
port: ENV['DATABASE_PORT']
)
data = @conn.exec(sql)
@conn.finish
data
end
end
app.rbで、モジュールを使ってみましょう!
モジュールにすると、require './mydatabase' をすることで違うファイルからも関数を呼び出せる!
require 'sinatra'
require 'sinatra/reloader'
require 'pg'
require 'dotenv/load'
require './mydatabase' # moduleの読み込み
get '/' do
# moduleを使ったDBアクセス
@data = Mydatabase.exec("select * from board_contents;")
erb :index
end
post '/comments' do
name = params["name"]
comment = params["comment"]
sql = "INSERT INTO board_contents (name, comment, commented_at) VALUES ('#{name}', '#{comment}', current_timestamp);"
# moduleを使ったDBアクセス
@data = Mydatabase.exec(sql)
redirect '/'
end
完成!
app.rbのコード量が劇的に減りました!
これで、DB操作はこのモジュールに任せればOK!
SQL文だけ変えれば、delete、update、insert、selectなど全てに対応できるように!
DBは自由自在に扱えます\(^o^)/
めっちゃ便利〜〜〜!!!感動です!!!!(涙)
ぜひ、皆さんも重複した処理は、関数、モジュール化できないか考えると、コードがスッキリ!かつ楽に!なると思います!
前編は以上です!!
今回書ききれなかったprocについては後編に回します!
procとyieldについて学べばコーディングの幅が格段に上がる!はずです!
ぜひ後編も見てください〜!