LoginSignup
23
40

More than 5 years have passed since last update.

お気に入り機能の作り方

Posted at

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

ちなみに下記の2つの記事を参考にさせていただきました。
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つのモデルについて書いていきます。

favorite.rb
class Favorite < ApplicationRecord
  belongs_to :user
  belongs_to :post
end

これはuserとpostに1対多で属するので、2つかきます。

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が2番目の人のお気に入りをしているPostを取ってくる場合
Userモデル (id=2)
=> Favoriteモデル (user_id=2のものを探索)
=> Favoriteモデル (探索したものの、post_idを発見)
=> Postモデル(post_idからPostモデル内のidに変換。たどり着く)

みたいなイメージです。

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

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

これは一緒です。

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

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

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

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を送ればオッケーなので下記になります。

    <% 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

23
40
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
40