お気に入り機能の作り方

こんにちは、今回はお気に入り機能の作り方について書いていきます。

ちなみに下記の２つの記事を参考にさせていただきました。
http://labyrinth-of-wisdom.hatenadiary.com/entry/2016/03/03/085059
https://qiita.com/wtb114/items/39367a39bd6a65701db7

さて、ではまずざっと流れを書いていきます。
1.Favoriteモデルの作成
2.モデルのアソシエーション、favoriteのDB作成
3.Routing,Controller,Viewの設定

では、まず1の前にお気に入り機能について簡単に説明していきましょう。
お気に入りは、Userがある投稿につけるものでありますが、お気に入りにおいてはUserとPostは多対多の関係にあると言えます。
Userは多くのお気に入りPostを持っています
Postを多くのお気に入り(By User)を持っています。

ということで、「User1の人だからお気に入りはこのPostでしょ」も「Post1だから、この人のお気に入りでしょ」みたいな断定はできないんですね。要するにもれなく、片方からもう片方にアクセスすることはできないってことです。

ということで、中間テーブルを作るわけです。正直説明下手ですね、すいません。
関係を結んだ後は、お互いのテーブルから他方にアクセスできるようになります。

1.Favoriteモデルの作成
これはおなじみですね。
rails g model Favorite

2.モデルのアソシエーション
3つのモデルについて書いていきます。

```ruby:favorite.rb
class Favorite < ApplicationRecord
  belongs_to :user
  belongs_to :post
end
```
これはuserとpostに１対多で属するので、２つかきます。

```ruby:user.rb
class User < ApplicationRecord
  has_many :favorites
  has_many :posts, through: :favorites
end
```
Userモデル。favoriteモデルはhas_manyですね。
postは、favoriteモデルを経由して取ってくるので、has_many ,thoroughですね。
イメージとしては、Userモデルのidが２番目の人のお気に入りをしているPostを取ってくる場合
   Userモデル　(id=2)
=> Favoriteモデル　(user_id=2のものを探索)
=> Favoriteモデル　(探索したものの、post_idを発見)
=> Postモデル(post_idからPostモデル内のidに変換。たどり着く)

みたいなイメージです。

もしくは、中間テーブルでPostとUserががっちゃんこみたいなイメージでもいいかもしれません。


```ruby:post.rb
class Post < ApplicationRecord
  has_many :favorites
  has_many :users, through: :favorites
end

```

これは一緒です。

さてこのタイミングでfavoriteのDBを作成しましょう。

```ruby:migrationファイル
class CreateFavorites < ActiveRecord::Migration[5.1]
  def change
    create_table :favorites do |t|
      t.references :user, null:false
      t.references :post, null:false

      t.timestamps
    end
  end
end
```

t.references :user　という項目を作りました。ちなみにuser_idでもOKです。自動でkeyだと読み取ってくれます。ちなみに、add_index :favorites, :user_id　とするとエラーが起きました。rails4以降は、refrencesとすると、自動でindexをつけてくれるみたいですね。便利。

これでrails db:migrate!

これで、アソシエーションと、モデルは終了です。
あとは、Favoriteモデルに追加する方法、実際に片側のモデルからもう一方のモデルにデータをとるってことをやりましょう。


### Controller

```ruby:favorites_controller.rb
class FavoritesController < ApplicationController
  
  def create
    user=current_user
    post=Post.find(params[:post_id])
    if Favorite.create(user_id: user.id,post_id:post.id)
    redirect_to post
    else
      redirect_to root_url
    end
    
  end
  
  def destroy
    user=current_user
    post=Post.find(params[:post_id])
    if favorite=Favorite.find_by(user_id: user.id,post_id:post.id)
      favorite.delete
      redirect_to users_path(current_user)
    else
      redirect_to root_url
    end
```

user_idとpost_idがわかればテーブルを作れるのでこちらでお願いします。

###Routing

```ruby:route.rb
 resources :posts do
    post 'add' => 'favorites#create'
    delete '/add' => 'favorites#destroy'
  end
```

postはparams[post_id]から取っているので、postのidがどうしても必要です。ということで、ネストしてurlを作成しました。イメージとしては、doとendに囲まれた中では、普通のroutingの形式でいいみたいです。ルートアドレスが、/posts/:idになったイメージです。resourcesにネストしてるので。

最後にformですね。これは、/posts/:id/addにpostかdeleteを送ればオッケーなので下記になります。

```ruby:
    <% if !Favorite.exists?(user_id:current_user.id,post_id:post.id) %>
    <%= link_to "お気に入り",post_add_path(post),method: :post %>
    <% else %>
    <%= link_to "お気に入り解除",post_add_path(post),method: :delete %>
```

これはそんな難しくないはずです。exists?メソッドを使って切り替えもしました。

以上です。
ありがとうございました。初心者なので、意見あればガシガシお願いします！！a