「本来」と「次に」で消したコードは必要なので戻してください。ファイル名の変更もたぶん不要です。
おそらくですが app/views/posts/index.html.erb の内容にミスがある気がします。コードを貼ってください。
エラーの解消と非同期いいねの実装
Ruby on RailsでTwitterのようなWebアプリをつくっています。
非同期いいね機能の実装中にエラーが発生しました。
解決方法を教えて下さい。
Rails 7.0.3
ruby 3.1.2
deviseなし
https://note.com/become_engineer/n/n45f7285622e3
上記の記事を参考に非同期いいねを導入しています。
ActionController::UnknownFormat in LikesController#create
LikesController#create is missing a template for this request format and variant.
request.formats: ["text/html"]
request.variant: []
$('#likes_buttons_<%= @post.id %>').html("<%= j(render partial: 'likes/like', locals: {post: @post}) %>");
$('#likes_buttons_<%= @post.id %>').html("<%= j(render partial: 'likes/like', locals: {post: @post}) %>");
名前をjs -> html に変更すると反応するようになるという記事を見つけたので名前を変更しました。
$('#likes_buttons_<%= @post.id %>').html("<%= j(render partial: 'likes/like', locals: {post: @post}) %>");
$('#likes_buttons_<%= @post.id %>').html("<%= j(render partial: 'likes/like', locals: {post: @post}) %>");
NoMethodError in Likes#create
undefined method `id' for nil:NilClass
@virtual_path = "likes/create";;@output_buffer.safe_append='$(\'#likes_buttons_'.freeze;@output_buffer.append=( @post.id );@output_buffer.safe_append='\').html("'.freeze;@output_buffer.append=( j(render partial: 'likes/like', locals: {post: @post}) );@output_buffer.safe_append='");'.freeze;
^^^
$('#likes_buttons_<%= @post.id %>').html("<%= j(render partial: 'likes/like', locals: {post: @post}) %>");(赤マーカー)
class LikesController < ApplicationController
before_action :authenticate_user
before_action :post_params
def create
Like.create(user_id: @current_user.id, post_id: params[:id])
end
def destroy
Like.find_by(user_id: @current_user.id, post_id: params[:id]).destroy
end
private
def post_params
end
end
本来は下記のコードだったのですが、
def post_params
@post = Post.find(params[:id])
end
下記のようなエラーが出たため、とりあえず削除しました。
ActiveRecord::RecordNotFound in LikesController#create
Couldn't find Post without an ID
before_action :post_params
上と下
private
def post_params
@post = Post.find(params[:id])
end
上記のコードを不要だと思い、削除すると下記のエラーが発生しました
NoMethodError in Likes#create
undefined method `id' for nil:NilClass
@virtual_path = "likes/create";;@output_buffer.safe_append='$(\'#likes_buttons_'.freeze;@output_buffer.append=( @post.id );@output_buffer.safe_append='\').html("'.freeze;@output_buffer.append=( j(render partial: 'likes/like', locals: {post: @post}) );@output_buffer.safe_append='");'.freeze;
$('#likes_buttons_<%= @post.id %>').html("<%= j(render partial: 'likes/like', locals: {post: @post}) %>");
最後まで読んでいただきありがとうございます。
教えて頂けると幸いです。
よろしくお願いいたします。
「本来」と「次に」で消したコードは必要なので戻してください。ファイル名の変更もたぶん不要です。
おそらくですが app/views/posts/index.html.erb の内容にミスがある気がします。コードを貼ってください。
@NetaNeta0620
Questioner返信いただきありがとうございます。
何かわかると良いのですが
何卒よろしくお願いいたします。
<% @posts.each do |post| %>
<div class="posts-index-item">
<div class="post-left">
<% if post.user.avatar? %>
<%= link_to (image_tag post.user.avatar_url), "/users/#{post.user.id}" %>
<% else %>
<%= link_to (image_tag src="default.jpg"), "/users/#{post.user.id}" %>
<% end %>
</div>
<div class="post-right">
<div class="post-user-name">
<%= link_to(post.user.name, "/users/#{post.user.id}") %>
</div>
<div class="post-title">
<%= link_to(post.title.truncate(30), "/posts/#{post.id}") %>
</div>
------------------------------------------------------------------------------------------------------------------------
<div id="likes_buttons_<%= post.id %>">
<%= render partial: 'likes/like', locals: {post: post} %>
</div>
------------------------------------------------------------------------------------------------------------------------
 
<span class="fa fa-eye"></span>
<%= post.view_counts.count if post.view_counts.count != 0 %>
 
<span class="fa fa-comment"></span>
<%= @post_comments_count[post.id] %>
<button id="share"><span class="fa fa-share-alt "></span></button>
<script type="text/javascript">
(function () {
function share() {
if (navigator.share) {
navigator.share({
title: '',
text: '',
url: '',
})
.then(() => {
// シェアしたら実行される
console.log('Successful share');
})
.catch((error) => {
// シェアせず終了した場合もここに入ってくる。
console.log('Error sharing', error)
});
} else {
alert('Web Share API is not supported!!');
// Web Share API未対応ブラウザ向けのフォールバックを実装する。
}
}
document.querySelector('#share').addEventListener('click', share);
})();
</script>
</div>
</div>
<% end %>
これだけだとまだ分からないので routes.rb と likes/_like.html.erb もお願いします。
@NetaNeta0620
Questioner了解しました。
Rails.application.routes.draw do
get 'auth/:provider/callback' => 'sessions#create'
resources :posts, only: [] do
resources :comments
end
get 'searches' => 'posts#search'
------------------------------------------------------------------------------------------------------------------------
get "likes/:post_id/create" => "likes#create", as: 'create_like'
get "likes/:post_id/destroy" => "likes#destroy", as: 'destroy_like'
------------------------------------------------------------------------------------------------------------------------
post "users/:id/update" => "users#update"
get "users/:id/edit" => "users#edit"
post "users/create" => "users#create"
get "signup" => "users#new"
get "users/index" => "users#index"
get "users/:id" => "users#show"
post "login" => "users#login"
get "logout" => "users#logout"
get "login" => "users#login_form"
get "users/:id/likes" => "users#likes"
get "users/:id/comments" => "users#comments"
get "posts/index" => "posts#index"
get "posts/new" => "posts#new"
get "posts/:id" => "posts#show"
post "posts/create" => "posts#create"
get "posts/:id/edit" => "posts#edit"
post "posts/:id/update" => "posts#update"
get "posts/:id/destroy" => "posts#destroy"
get "/" => "home#top"
get "about" => "home#about"
end
<% if @current_user %>
<% if @current_user.liked_by?(post.id) %>
<td><%= link_to 'いいねを外す', destroy_like_path(post), method: :POST, remote: true %> <%= post.likes.count %></td>
<% else %>
<td><%= link_to 'いいね', create_like_path(post), method: :POST, remote: true %> <%= post.likes.count %></td>
<% end %>
<% end %>
ルーティングが get "likes/:post_id/create"
になっているので Post の id は params[:post_id]
に入ります。 LikesController
の中で params[:id]
を参照している部分を params[:post_id]
にすれば直ると思います。
@NetaNeta0620
Questionerご指摘いただいたように変更したのですが、(下記)
class LikesController < ApplicationController
before_action :authenticate_user
before_action :post_params
def create
Like.create(user_id: @current_user.id, post_id: params[:post_id])ここ
end
def destroy
Like.find_by(user_id: @current_user.id, post_id: params[:post_id])ここ.destroy
end
private
def post_params
@post = Post.find(params[:post_id])ここ
end
end
下記のエラーが出てしまいます。
ActionController::UnknownFormat in LikesController#create
LikesController#create is missing a template for this request format and variant.
request.formats: ["text/html"]
request.variant: []
create.js.erbとdestroy.js.erbの名称はjsに戻した状態になっています。
解消方法わかりますでしょうか?
よろしくお願いいたします。
get "likes/:post_id/create" => "likes#create", as: 'create_like'
get "likes/:post_id/destroy" => "likes#destroy", as: 'destroy_like'
この先頭の get
を post
にしてください。
@NetaNeta0620
Questionerroutinguエラーが出てしまいました。
viewとcontrollerを確認してみたのですが、原因わかりませんでした。
何かわかりますでしょうか?
Routing Error
No route matches [GET] "/likes/1/create"
込み入った話になりますが、 Rails 7 で新規に作ったプロジェクトでは rails-ujs というライブラリが入らないため、 link_to 'いいねを外す', destroy_like_path(post), method: :POST
の method: :POST
が効かなくなります。そのためリクエストが POST ではなく GET で送られるようになり、ルーティングに一致しないエラーが出ます。参考ページは Rails 6 と思われるため動いているようです。
ターミナルで ./bin/importmap pin rails-ujs
を実行して rails-ujs を入れれば直ると思います。
@NetaNeta0620
Questioner% ./bin/importmap pin rails-ujs
Pinning "rails-ujs" to https://ga.jspm.io/npm:rails-ujs@5.2.8-1/lib/assets/compiled/rails-ujs.js
を行いましたが、まだ
Routing Error
No route matches [GET] "/likes/1/create"
がでてしまいます。
確認ですが、エラーが出るのは likes/_like.html.erb で表示される「いいね」リンクをクリックしたときですよね?
@NetaNeta0620
Questionerposts/indexページのみ
<div id="likes_buttons_<%= post.id %>">
<%= render partial: 'likes/like', locals: {post: post} %>
</div>
上記のコードを使っています。
indexページのいいねリンクをクリックしているため
likes/_like.html.erb
で表示されているいいねリンクのはずです
https://qiita.com/kcl215/items/e226ac58d14360fd1b8e
この記事に書いてあった
yarn add jquery
を試しにターミナルでやってみたのですが、変わらずエラーが出てしまいます。