Ruby初心者が勉強会に参加してみた（全７回）第3回＆4回②

３回目のものもnoteには投稿したけれど、
こちらでは復習も兼ねて３回と４回をまとめて記載していきます！
（長くなりそうなので、何回かに分けます！）

##最終目的：sinatraで簡易的な掲示板アプリを作る

今回は掲示板アプリなので**create_board_contets.rb**ファイルを作成。
`$ touch create_board_contets.rb`


```create_board_contets.rb
require 'pg'

# herokuから持ってきた情報を記入
conn = PG::connect(
  host: '',
  user: '',
  password: '',
  dbname: '',
  port: ''
)
conn.exec("
  CREATE TABLE board_contents (
    id serial,
    name text,
    comment text,
    commented_at timestamp,
    PRIMARY KEY (id)
  );"
)
```

テーブルを作成するために、rubyファイルを実行。
`$ ruby create_board_contets.rb`
これでデータベースに`board_contents`というテーブルが作成される！

PGcommanderでも確認。
![スクリーンショット 2019-06-02 10.43.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378334/e7c9bca7-44ab-2a33-5cdf-56ee4eac9345.png)

board_contentsからデータを持ってくるために、
**app.rb**を修正する。

```app.rb
get '/' do
	
  conn = PG::connect(
    host: '',
    user: '',
    password: '',
    dbname: '',
    port: '5432'
  )

  @data = conn.exec("select * from board_contents;")
  conn.finish
  erb :index
end
```

ビューに反映させるために**index.erb**も修正。

```index.erb
<h1>hello world</h1>
<ul>
<% @data.each do |mes| %>
  <li><%= mes["id"] %>
    /
    <%= mes["name"] %>
    /
    <%= mes["comment"] %>
  </li>
<% end %>
</ul>
```

このままだと、データの情報丸見えなので、
DBの接続情報を隠すために**dotenv**を導入する。

```Gemfile.
source "https://rubygems.org"

git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }

# gem "rails"

gem 'sinatra'
gem 'sinatra-contrib'
gem 'pg'
gem 'dotenv' # ここを追記
```
`$ bundle install`を忘れずに。

環境変数を設定する**.env**ファイルを新規作成する。

```env.
DATABASE_HOST=''
DATABASE_USER=''
DATABASE_PASSWORD=''
DATABASE_NAME=''
DATABASE_PORT=''

```

.envから取得した情報でpostgresqlにアクセスするために、
**app.rb**を修正する。

```app.rb
require 'sinatra'
require 'sinatra/reloader'
require 'pg'
require 'dotenv/load' # 追加

get '/' do
  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("select * from board_contents;")
  conn.finish
  erb :index
end
```

ここまで出来れば、いよいよ投稿フォームを作成していきます。
**・formを使ってPOSTリクエストを実行できるようにする。**

```index.erb
<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <ul>
      <% @data.each do |mes| %>
        <li><%= mes["id"] %>/<%= mes["name"] %>/<%= mes["comment"] %></li>
      <% end %>
    </ul>
    <form action="/comments" method="post">
      名前：<input type="text" name="name">
      コメント：<input type="text" name="comment">
			<!-- 送信ボタン -->
      <input type="submit" value="送信する">
    </form>
  </body>
</html>
```
一度確認してみると、無事表示されました。
↓↓
![スクリーンショット 2019-06-02 11.03.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378334/f48caa0a-79ae-e5e7-1560-09fb027fd84f.png)

ですがformのアクションを実行する処理がまだなので、
POSTメソッドを追加していきます。

```app.rb
# 下記を追記
post '/comments' do
  p params["name"]
  p params["comment"]
end
```

###POSTされたデータをDBへ保存する処理をする。
さっき追記したpostの部分を以下に修正。

```app.rb
post '/comments' do
	# paramsでデータを受け取る
	name = params["name"]
  comment = params["comment"]
	# dbに接続
	conn = PG::connect(
    host: ENV['DATABASE_HOST'],
    user: ENV['DATABASE_USER'],
    password: ENV['DATABASE_PASSWORD'],
    dbname: ENV['DATABASE_NAME'],
    port: ENV['DATABASE_PORT']
  )
	# sqlを組み立てる
	sql = "INSERT INTO board_contents (name, comment) VALUES ('#{name}', '#{comment}');"
  # sqlを実行する
	@data = conn.exec(sql)
end
```
PG commanderなどのツールで反映されているか確認する！

![スクリーンショット 2019-06-02 11.10.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378334/07f59c39-518a-3712-a3d4-1561a8be7c7b.png)

無事、反映されてます！

これで簡単な掲示板アプリの**完成**です。

###データベース接続処理を関数化してみる。

```app.rb
# 文字列で受け取ったsqlを実行する関数
def postgres(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

get '/' 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
```

###さらに、module化もしてみる。
`$ touch mydatabase.rb`

```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も修正する。

```app.rb
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) VALUES ('#{name}', '#{comment}');"
  # moduleを使ったDBアクセス
	@data = Mydatabase.exec(sql)
  redirect '/'
end
```

念の為、ちゃんと表示されているか確認。

![スクリーンショット 2019-06-02 11.28.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378334/b96798a4-f376-68b8-d793-b1f223313c91.png)

無事、module化も完了！

今回の勉強会では最後にスクレイピングもやりました。
こちらはまた長くなりそうなので、
別でもまとめていきたいと思います。