質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Slim

SlimはPHPアプリケーションを開発するための軽量なマイクロフレームワークです。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

Q&A

解決済

4回答

780閲覧

rails 非同期いいね機能 初動[DELETE]時のみエラーが発生する

acrobat_coding

総合スコア11

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Slim

SlimはPHPアプリケーションを開発するための軽量なマイクロフレームワークです。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

0グッド

0クリップ

投稿2019/06/10 08:40

編集2019/06/11 00:58

前提・実現したいこと

rails でユーザーごとにリンクを投稿し
投稿の詳細画面に非同期で「いいね機能」を作っています。

------------パターン1------------
投稿詳細画面を開く 
ボタン状態:未いいね

↓ いいね押す(create実行後、レンダリング _goodのif)

ボタン状態:いいね済

↓ いいね押す(destroy実行後、レンダリング _goodのif)

ボタン状態:未いいね


---------繰り返し---------

と正常に動作し、カウンターの数値もきちんと表示されています。
しかし、詳細画面を開いた時にいいね済状態の場合

-----------------------------パターン2------------------------------

投稿詳細画面を開く 
ボタン状態:いいね済

↓ いいね押す(destroy実行後、レンダリング _goodのif)

ボタン状態:未いいね

↓ いいね押す(??POSTではなくDELETEが実行されている??)

------------エラー発生 ボタン状態:未いいね なにも起きない------------

このように挙動がないので
再読み込みをしたら 未いいね状態 その後の動作は パターン1

その後も、詳細画面を いいね済 で開いたら パターン2 となり
ログを確認したら destroyのメソッドエラーとなっていました。

発生している問題・エラーメッセージ

エラーメッセージ NoMethodError (undefined method `destroy' for nil:NilClass): app/controllers/goods_controller.rb:12:in `destroy'
NoMethodError in GoodsController#destroy undefined method `destroy' for nil:NilClass Extracted source (around line #12): #10 def destroy #11 @good = Good.find_by(user_id: current_user.id, post_id: params[:post_id]) *12 @good.destroy #13 #14 @post.reload #15 end Extracted source (around line #6): #4 module BasicImplicitRender # :nodoc: #5 def send_action(method, *args) *6 super.tap { default_render unless performed? } #7 end #8 #9 def default_render(*args) Extracted source (around line #194): #192 # which is *not* necessarily the same as the action name. #193 def process_action(method_name, *args) *194 send_action(method_name, *args) #195 end #196 #197 # Actually call the method associated with the action. Override Request parameters {"_method"=>"delete", "authenticity_token"=>"nyje1yH2NZ4xffO4HVpgb3D/rftrx9yPAxCMaMwx3zZVEStbpapgXuJwph4OfMTySB6RJJAuSvQE2hjjTYHdZQ==", "post_id"=>"9", "format"=>"286"} Session dump _csrf_token: "yjn1jIRcVcDTDVWmEyaknTjhPN/76ZZ7B8qUi4GwAlM=" session_id: "116c5a71c5f53de98fcb17f180645e5d" user_id: 1 Env dump GATEWAY_INTERFACE: "CGI/1.2" HTTP_ACCEPT: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript, */*; q=0.01" HTTP_ACCEPT_ENCODING: "gzip, deflate, br" HTTP_ACCEPT_LANGUAGE: "ja,en-US;q=0.9,en;q=0.8" HTTP_ORIGIN: "http://localhost:3000" HTTP_VERSION: "HTTP/1.1" HTTP_X_CSRF_TOKEN: "nyje1yH2NZ4xffO4HVpgb3D/rftrx9yPAxCMaMwx3zZVEStbpapgXuJwph4OfMTySB6RJJAuSvQE2hjjTYHdZQ==" ORIGINAL_SCRIPT_NAME: "" REMOTE_ADDR: "::1" SERVER_NAME: "localhost" SERVER_PROTOCOL: "HTTP/1.1" Response headers None

routes.rb

ruby

1delete '/posts/:post_id/goods', to: 'goods#destroy', as: :good 2 3 resources :posts do 4 resources :goods 5 end

routes

good DELETE     /posts/:post_id/goods(.:format)                 goods#destroy           post_goods POST /posts/:post_id/goods(.:format)                 goods#create                 

model

good.rb

ruby

1class Good < ApplicationRecord 2 belongs_to :post, counter_cache: :goods_count 3 belongs_to :user 4end 5

post.rb

ruby

1has_many :goods, dependent: :destroy 2 def good_user(user_id) 3 goods.find_by(user_id: user_id) 4 end 5

###show.html.slim

slim

1= render partial: 'goods/good',locals: { post: @post , good: @good}

goods_controller

ruby

1class GoodsController < ApplicationController 2 before_action :good_setup 3 4 def create 5 Good.create(user_id: current_user.id, post_id: params[:post_id]) 6 7 @post.reload 8 end 9 10 def destroy 11 @good = Good.find_by(user_id: current_user.id, post_id: params[:post_id]) 12 @good.destroy 13 14 @post.reload 15 end 16 17 18 private 19 def good_setup 20 @post = Post.find(params[:post_id]) 21 end 22 23end 24

_good.html.slim

slim

1- if post.good_user(current_user.id) 2 = button_to good_path(post,good),method: :delete, id: 'good_buttons', remote: true do 3 = image_tag("no_good.jpg") 4 .nav.justify-content-center 5 ur 6 li = 'good' 7 li = post.goods_count 8- else 9 = button_to post_goods_path(post),method: :post,id: 'good_buttons', remote: true do 10 = image_tag("good.jpg") 11 .nav.justify-content-center 12 ur 13 li = 'good' 14 li = post.goods_count 15

###create.js.erb

$("#good_buttons").html("<%= j(render partial: 'good', locals: { post: @post,good: @good })%>");

###destroy.js.erb

$("#good_buttons").html("<%= j(render partial: 'good', locals: { post: @post,good: @good })%>");

試したこと

ルーティングのidがおかしいのかもしれないと調べてみるも
まだまだ勉強不足でどうしていいのかわからず
jsやAjaxに関しては全く触れたことがなかったのでハマっています。

createの初動がないと
単純に@good.destroycurrent_user.idが取得できていない?
jsの挙動のタイミングなどわからないことだらけで。。。

よろしければ、問題解決に繋がるような
参考サイト、書籍等または解決へのヒントをご教示願います。

補足情報(FW/ツールのバージョンなど)

ruby 2.5.3
Rails 5.2.3
gem 'slim-rails'
gem 'html2slim'
gem 'bootstrap'
gem 'jquery-rails'
gem 'jquery-turbolinks'

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

自己解決

別の問題が出てきたのでこの質問は解決とさせていただきます。

いいね機能自体は
destroyの中に例外処理を入れ
動かすことができました。

投稿2019/06/13 07:02

acrobat_coding

総合スコア11

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

別の問題が出てきたのでこの質問は解決とさせていただきます。

いいね機能自体は
destroyの中に例外処理を入れ
動かすことができました。

投稿2019/06/13 05:07

acrobat_coding

総合スコア11

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

gem を見るに turbolinks を使っているみたいですが、それの悪影響とかではないでしょうか?

erb

1$("#good_buttons").html("<%= j(render partial: 'good', locals: { post: @post,good: @good })%>");

という実装をしている時点で全く turbolinks を活用できていないため turbolinks を削除するか、 turbolinks に従う実装にするか、どちらかを選ぶべきではないでしょうか?

投稿2019/06/11 06:19

Ighrs

総合スコア656

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

acrobat_coding

2019/06/12 01:07

回答ありがとうございます。 turbolinks については行き詰まってから色々試す中で入れたものでした。 削除しても挙動に変化は見られませんでした。
guest

0

多分こうすればいいです。

destroyのfind_byの後に ! をつけてください。
そしたら record not foundのエラーで404にできるはずです。

投稿2019/06/10 16:54

odyu

総合スコア548

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

acrobat_coding

2019/06/11 00:52

回答ありがとうございます。 find_by! で実行したところ ActiveRecord::RecordNotFound (Couldn't find Good): となったのですが Goodが見つかったとしても実行されるのは[DELETE]なので destroy内に例外でcreateを実行し destroyだけでもいいねできるようにしました。 助言のfind_by!では原因までたどり着けず申し訳ありません。 例外処理を思いつかなかったので 今回の回答のおかげで動作自体は無事にできました。 ありがとうございます。 しかし原因が分からず ボタンの表示は[POST]、 [POST]押しているはずなのに [DELETE] が走り出すのは ボタンを押す前に条件が不足しているので[DELETE]になってしまう (じゃあ何故表示は[POST]、動作は[DELETE]??) ルートパス、ID等のルーティングが甘い (例外でcreateした後も[DELETE]ルートなのは??) (URIが同じなので優先度の様なものがある??) など考えてしまいます わかりにくい文章、勉強不足で失礼とは思いますが よろしければご意見を頂けると幸いです。
odyu

2019/06/11 01:18

ボタンの表示はわからないですが、postとdeleteはhttpリクエストのメソッドによって変わります。それがヒントにならないでしょうか?
acrobat_coding

2019/06/12 01:56

ご意見ありがとうございます。 色々と試してみても _goodの条件分岐で -else POSTルートに走っているのに ボタンをクリックしたらDELETEが走ってしまうのかが どうしても辿りつけません。 メソッド指定はDELETEのみで デフォルトのPOSTに走らないと言うことは POSTとDELETEのURIが同じだから? に行き着いてしまいます。 問題のDELETE初動の場合 Processing by GoodsController#destroy as JS ではなく Processing by GoodsController#destroy as となり JS の挙動もよく分からない状態で 視点が狭すぎるのでしょうか 細かいことが気になってしまい この問題だけで数日費やしてしまい 自身の無知さを実感しています。 せっかくのご意見 自分のものにできず申し訳ないです。。
odyu

2019/06/12 04:28

ろぐを貼ってもらえたらみますよ。 ただ、別の質問を立てた方がいいような気もしますが。
acrobat_coding

2019/06/13 05:03

お気遣いありがとうございます。 今回の件はもう一度問題点を洗いなおして 改めて別の質問として解決しようと思います。 お世話になりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問