店舗情報とユーザー情報が紐づいたレビュー機能の作成Ruby on Rails（ポートフォリ）

# レビュー機能の作成手順

## レビュー用のDB作成

### モデルの作成

```terminal
$ rails g model Review content:text user:references store:references
      invoke  active_record
      create    db/migrate/20190918094610_create_reviws.rb
      create    app/models/review.rb
      invoke    test_unit
      create      test/models/review_test.rb
      create      test/fixtures/reviews.yml
```

まずはモデルを作成して、書き込み内容を保存するDBを作成する。

### カラムの内容定義

```20190918094610_create_reviews.rb
class CreateReviws < ActiveRecord::Migration[5.2]
  def change
    create_table :reviews do |t|
      t.text :content
      t.references :user, foreign_key: true
      t.references :store, foreign_key: true

      t.timestamps
    end
  end
end
```
作成されたDBの内容はこちらで下記の内容に書き加える

```20190918094610_create_reviews.rb
class CreateReviws < ActiveRecord::Migration[5.2]
  def change
    create_table :reviews do |t|
      t.text :content
      t.references :user, foreign_key: true
      t.references :store, foreign_key: true

      t.timestamps
    end  
    #ここの1行を加える
    add_index :reviews, [:user_id, :store_id]
  end
end
```
**add_index :reviews, [:user_id, :store_id]**の一文を足して店舗とユーザーのIDを加える様にします。

### DBの作成
 
```terminal
$ rails db:migrate
```

いつものDBの作成を行います。

## 各モデルの関連付け

### 作成したモデルの別DBとの紐付け
```review.rb

class Reviw < ApplicationRecord
  belongs_to :user
  belongs_to :store
end
```

店舗IDとユーザーIDの紐付けを行うため、**belongs_to**を使ってDBの紐付けを行います。


```user.rb
class User < ApplicationRecord
    has_many :reviws
(省略)
```
    
```store.rb
class Store < ApplicationRecord
    has_many :reviws
(省略)
```
ユーザーと店舗情報は**has_many:**で紐付け。
has_manでの紐づける場合は複数形で書かなくてはいけないので注意が必要


## 口コミの投稿と表示

```terminal
$ rails g controller reviews
Running via Spring preloader in process 16979
      create  app/controllers/reviews_controller.rb
      invoke  erb
      create    app/views/reviews
      invoke  test_unit
      create    test/controllers/reviews_controller_test.rb
      invoke  helper
      create    app/helpers/reviews_helper.rb
```

口コミ用のコントローラー作成をします。


```reviews_controller.rb
class ReviewsController < ApplicationController
    def create
        @reviews = Review.new(review_params)
        if @reviews.save
            redirect_to root_path
        end
    end

private

    def review_params
        params.require(:review).permit(:content, :user_id, :store_id)
    end
end
```

フォームを作成するにあたり、reviewコントローラーにDB保存するための定義を行います。


```routes.rb
  resources :reviews
```

ありがちですがルートの設定も忘れずに。
### フォームの表示

```store_controller.rb
class StoreController < ApplicationController
  def detail
    @stores          = Store.find(params[:id])
    @reviews         = Review.new
    @users           = current_user.id
  end
end
```

店舗ページのフォームにユーザーIDと店舗DBを送らなければいけないため、idが取得できる様にします。
**current_user.id**：ログイン中のユーザーidを取得してくれるめっちゃ優秀なメソッド。　

```detail.html.rb
<%= form_for(@reviews) do |f| %>
    <%= f.text_field :content,class: "text-field"  %>
    <%= f.hidden_field :user_id ,  value: @users   %>
    <%= f.hidden_field :store_id , value: @stores.id %>
    <%= f.submit '投稿', class: "submit-btn" %>
<% end %>
```

viewで上記のコードを記入して完了。


# その他
## 手間取ったところ。
### カラム名のミス

```reviews_controller.rb
class ReviewsController < ApplicationController
    def create
        @reviews = Review.new(review_params)
        if @reviews.save
            redirect_to root_path
        end
    end

private

    def review_params
        params.require(:review).permit(:content, :user_id, :store_id)
    end
end
```

permit(:content, :user_id, :store_id)の後ろに記載されているをずっとモデル作成時に設定したカラム名の「user」「store」と記載していて動かなかった。

### ユーザーIDの取得

```store_controller.rb
class StoreController < ApplicationController
  def detail
    @stores          = Store.find(params[:id])
    @reviews         = Review.new
    @users           = current_user.id
  end
end
```
**current_user.id**というものを知らなかったので、User.find(params[:id])と書いていたんですが上手く機能できずに混乱状態でした。