前提・実現したいこと
rails,jsでいいね機能を非同期で実装しようとしています。
詳細ページでは実装できるようになったのでトップページでも実装しようとした。その時のエラーを解決したいと思っています。何か分かりましたら回答よろしくお願いします。
<現在できている事>
商品詳細ページでは非同期でいいね機能を実装できています。
<前提>
詳細ページでは「お気に入り」という文字を表示されているがトップページでは表示させない。
<解決したい事・できるようにしたい事>
トップページからログインしているユーザーであれば非同期でいいね「登録」「解除」できるようにしたい。
発生している問題・エラーメッセージ
該当のソースコード
・ルーティング
中略
resources :products do
resources :favorites, only: [:create, :destroy]
end
・コントローラー
def index
@products = Product.includes(:photos).order(created_at: :desc).limit(5)
end
def show
@products = Product.all
if @product == @products.first
@next_product = Product.next_search(@product)
elsif @product == @products.last
@prev_product = Product.prev_search(@product)
else
@prev_product = Product.prev_search(@product)
@next_product = Product.next_search(@product)
end
@grandchild = Category.find(@product.category_id)
@child = @grandchild.parent
@parent = @child.parent
@parent_category_products = @products.select { |product| product.category.root.name == @parent.name }
@user = current_user
Payjp.api_key = ENV['PAYJP_PRIVATE_KEY']
@card = CreditCard.find_by(user_id: current_user)
if user_signed_in?
@favorite = Favorite.find_by(user_id: current_user.id, product_id: params[:id])
end
end
class FavoritesController < ApplicationController
def create
@favorite = Favorite.create(user_id: current_user.id, product_id: params[:product_id])
@favorites = Favorite.where(product_id: params[:product_id])
@product = Product.find(params[:product_id])
end
def destroy
@favorite = Favorite.find_by(user_id: current_user.id, product_id: params[:product_id])
@favorite.destroy
@favorites = Favorite.where(product_id: params[:product_id])
@product = Product.find(params[:product_id])
end
end
・モデル
中略
has_many :favorites, dependent: :destroy
has_many :favorite_users, through: :favorites, source: :user
def favorite_user(user_id)
favorites.find_by(user_id: user_id)
end
中略
has_many :products, dependent: :destroy
has_many :favorites, dependent: :destroy
has_many :favorite_products, through: :favorites, source: :product
def already_favorited?(product)
self.favorites.exists?(product_id: product.id)
end
class Favorite < ApplicationRecord
belongs_to :user
belongs_to :product
validates_uniqueness_of :product_id, scope: :user_id
end
・ビュー
products/index.html.haml
#products-favorites
= render "favorites/products_favorite", locals: {product: @product}
products/show.html.haml
#favorites
= render "favorites/favorite", locals: {product: @product}
・部分テンプレート
favorites/_favorite.html.haml
- if user_signed_in?
- if current_user.already_favorited?(product)
= link_to product_favorite_path(product, @favorite), method: :delete, remote: true do
%i.fas.fa-star
お気に入り
= product.favorites.count
- else
= link_to product_favorites_path(product), method: :post, remote: true do
%i.far.fa-star
お気に入り
= product.favorites.count
- else
= icon('fa', 'star')
お気に入り
= product.favorites.count
favorites/_products_favorite.html.haml
- if user_signed_in?
- if current_user.already_favorited?(@product)
= link_to product_favorite_path(@product, @favorite), method: :delete, remote: true do
%i.fas.fa-star
= @product.favorites.count
- else
= link_to product_favorites_path(@product), method: :post, remote: true do
%i.far.fa-star
= @product.favorites.count
- else
= icon('fa', 'star')
= @product.favorites.count
・jsファイル
favorites/create.js.haml、destroy.js.haml
$("#favorites").html("#{j(render partial: "favorites/favorite", locals: { product: @product })}");
$("#products-favorites").html("#{j(render partial: "favorites/products_favorite", locals: { product: @product })}");
試したこと
@product.present?を試すと返り値としてfalseが、@products.present?を試すと返り値としてtrueが帰ってきた。部分テンプレートの@productを@productsに変更したが別のエラーが出た。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
0
詳細ページと同じようにレンダリング使用としていますがこの@productはどこで定義していますか?
- @products.each do |product|
= render partial: "favorites/favorite", locals: {product: product}
上記のような内容になると思います。?(このコードが正しいかは分かりません)
indexアクションでProductモデルのデータを取得しeachでループ処理を行いshow.html.hamlと同じようにレンダリングする形です。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.20%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2020/08/16 22:22
@product = Product.find(params[:id])
を試してみましたが、これもidが取得されていませんでした。
- @products.each do |product|を試した時のターミナルでは、
Completed 500 Internal Server Error in 235ms (ActiveRecord: 14.6ms | Allocations: 306131)
ActionView::Template::Error (undefined method `id' for nil:NilClass):
1: - if user_signed_in?
2: - if current_user.already_favorited?(@product)
3: = link_to product_favorite_path(@product, @favorite), method: :delete, remote: true do
4: %i.fas.fa-star
5: = @product.favorites.count
と表示していました。またもう一度解決方法を考えてみます。本当にご回答ありがとうございました。また何か分かったなら教えていただけるとありがたいです。またのご回答心待ちしています。
2020/08/16 22:28
@productをproductに変更してみてください。
2020/08/16 22:37
https://i.gyazo.com/68f483781ab7670c6a3234565586cd8f.png
2020/08/16 22:54
prtialの記述が必要みたいです。
回答の方修正したのでご確認お願いします。
2020/08/16 23:26
https://i.gyazo.com/f2b1952ffae17202ed4b294f98bccad2.png
2020/08/17 07:11
ProductsControllerのshowアクションだとおそらく@productを定義していると思いますがどのように定義しているのかを確認する必要があるため後基本的にコードは中略して書かないようにお願いします。
2020/08/17 18:31
2020/08/17 18:52