Rails CRUD機能実装①(今回は、新規追加、削除)

<h1>この記事の目的</h1>
railsを用いた、CRUD機能をもったwebアプリケーションの作成手順です。鳥の写真と名前を投稿できるサイト(birdtweet)です。
<h1>railsアプリケーションの作成</h1>

railsのバージョン6.0.0を指定。-dの後ろに使用するDB（今回はmysql)を指定。

```ターミナル
rails _6.0.0_ new birdtweet -d mysql
```

設定変更。

```rb:config/database.yml
...
#  encoding: utf8mb4
  encoding: utf8
...
```

DB作成

```
cd birdtweet
rails db:create
```

Gemfileの編集
プロジェクト直下にあるGemfileを開く

```rb:Gemfile
# gem 'mysql2', '>= 0.4.4'
gem 'mysql2', '>= 0.5.3'
........
(ファイル最下行)
gem 'pry-rails'
```

ターミナルで設定内容の更新

```
bundle update
```

<h1>modelの作成</h1>
ターミナルにて

```
rails g model bird
```
カラムを追記

```rb:db/migrate/2020********create_birds.rb
...
create_table :birds do |t|
      t.string :name
      t.text :pic
      t.timestamps
end
...

```

コマンドにて、変更内容の更新！

```
rails db:migrate
```

コンソールでDBにデータをいくつか入れます。

```
rails c
Bird.create(name: "ツノメドリ", pic: "https://cdn.pixabay.com/photo/2020/05/26/13/22/puffins-5223057_1280.jpg")
Bird.create(name: "カワセミ", pic: "https://cdn.pixabay.com/photo/2017/02/07/16/47/kingfisher-2046453_1280.jpg")
exit
```

<h1>コントローラの作成</h1>
以下のコマンドで、コントローラを作成します。

```
rails g controller birds
```

複数形にしたり、しなかったり混乱しますが、
モデルだけが単数形です！

<h1>ここからの流れ</h1>
各機能作成の流れはほぼほぼ同じです！

routes.rbに追記
↓
index.html.erbに各機能へのリンクを追記（index意外）
↓
birds_controller.rbに追記
↓
機能名.html.erb作成


<h1>一覧表示機能</h1>
railsには７つのアクションがある。
<ul>
<li>index：一覧</li>
<li>show：詳細</li>
<li>new：新規作成画面への遷移</li>
<li>create：新規データの保存</li>
<li>edit：編集画面への遷移</li>
<li>update：編集内容の更新</li>
<li>destroy：削除</li>
</ul>

全機能を使わない場合は、onlyオプションで使うものだけを指定する。


```rb:config/routes.rb
# resourcesの後ろは、モデル名の複数形
  resources :birds, only: :index
```



```rb:app/controllers/birds_controller.rb
...
def index
    # インスタンス変数にBirdモデルのデータを格納します。
    @birds = Bird.all
  end
...
```

index.html.erbファイル作成
ビュー内でインスタンス変数を、eachメソッドを使って全て表示します。

```rb:app/views/birds/index.html.erb
<% @birds.each do |bird| %>
<%= bird.name %>
<div style=
"background-image: url(<%= bird.pic %>); 
 background-position: center center;
 background-size: cover;
 width: 300px; 
 height: 300px;
 margin-bottom: 10px;
 ">
</div>
<%end%>
```

以下のように、表示されました！！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618706/e9c03649-2340-a750-8b9c-362618ab1aa4.png)

<h1>新規投稿機能</h1>
流れは同じく、routes → controller →　viewなのですが、投稿画面への移動（new）からのデータ追加（create）なので、一連の流れを二回やります！



```rb:routes.rb
Rails.application.routes.draw do
  # resourcesの後ろは、モデル名の複数形
  # アクションが複数あるときは、配列の形にしてあげます
  resources :birds, only: [:index, :new]
end
```

```ruby:index.html.erb
<%=link_to '新規投稿', new_bird_path, method: :get%>
...
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618706/595d6b23-f9ea-ef40-25e3-841b6e6577f0.png)


```rb:birds_controller.rb
...
def new
  # Birdモデルのインスタンス化したものを、インスタンス変数に格納します。
  @bird = Bird.new
end
...
```

new.html.erb作成

```rb:app/views/birds/new.html.erb
<%# 遷移先urlを記載しなくても、インスタンス変数に入れたモデルから判断して、遷移してくれます %>
<%=form_with(model: @bird, local: true) do |form| %>
  <%= form.text_field :name, placeholder: "鳥の名前" %>
  <%= form.text_field :pic, placeholder: "鳥の写真のURL" %>
  <%= form.submit "投稿" %>
<%end%>
```

http://localhost:3000/birds/new
にアクセスすると投稿画面ができてます！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618706/5140a7ba-d200-2b21-b928-35cb1e8cd57b.png)

次は、入力情報を登録する機能です。


```rb:routes.rb
Rails.application.routes.draw do
  # resourcesの後ろは、モデル名の複数形
  # アクションが複数あるときは、配列の形にしてあげます
  resources :birds, only: [:index, :new, :create]
end
```

birds_controller.rb
formからのハッシュの形でデータが送られてきます。<br><b>全てのデータを受け取るのは危険です！</b><br>
名前と写真のURLだけでいいのに、ログイン情報のキーを悪意で追加されて、他人のログイン情報を勝手に変更し乗っ取るということができてしまいます。
そこで、ストロングパラメータを使います。<br>また、privateを記述した行より下は、他のファイルから呼び出せないメソッドとなります。メソッドが増えたときに、見るべきファイルを減らせるメリットがあります。



```rb:birds_controller.rb
...
  def create
    # private下に定義したbird_paramで指定したパラメータを受け取り、保存する。
    Bird.create(bird_param)
  end

  private
  def bird_param
    # params.require(:モデル名).permit(:カラム名,:カラム名,......)
    params.require(:bird).permit(:name, :pic)
  end
...
```

create.html.erb作成

```rb:app/views/birds/create.html.erb
<h3>投稿完了！</h3>
<a href="/birds">一覧へ</a>
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618706/b7b7e5e5-4238-36ae-b5ac-ace43ab683a6.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618706/46595f69-c2f3-4d50-b623-0ea3c0f98ba1.png)


今のままだと、何も入力しないで登録ができてしまいます。そこでバリデーションチェックするための記述をします。

```rb:app/models/birds.rb
class Bird < ApplicationRecord
  # 入力必須にしたいカラム名を書きます。
  validates :name, presence: true
  validates :pic, presence: true
end
```
これでからのデータを登録できなくなりました！！

<h1>削除機能</h1>
```routes.rb
...
resources :birds, only: [:index, :new, :create, :destroy]
...

```
削除機能へのリンクの調べかたは、まずコマンドで

```
rails routes
```
とします。
すると、以下の出力がされます。
Prefixの値に「_path」をつけると、URIに記載されているURLが出力されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618706/148e2cba-4b89-83d4-0dce-207a32793535.png)

今回は削除なので、VerbにDELETEと描かれている行に注目します。Prefixは「bird」となっているので、「bird_path」とすればいいですね。メソッドは、「Verb」に「DELETE」とあるので「delete」とすれば良いですね。あとは、idも渡します！

```index.html.erb
...
<%= bird.name %><%=link_to "削除", bird_path(bird.id), method: :delete%>
...
```
リンクが表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618706/cef701e9-4f36-ad96-7f16-201f9b473f19.png)

```rb:bird_controller.rb
...
  def destroy
    # 今回は抽出したデータをどこにも送らないので、@をつけません。
    bird = Bird.find(params[:id])
    bird.destroy
  end
...
```

```destroy.html.erb
<a href="/birds">一覧画面</a>
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618706/8bdd31f4-2c50-5787-103e-58b660452d2a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618706/9ec5e330-9a2e-4496-2086-eabcdc67dc4e.png)
つのめどりがちゃんと削除されています！