LoginSignup
you-key
@you-key

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

写真の投稿にネストしているコメントを、どうしても削除できないです……

前提・実現したいこと

rails で簡単な写真の投稿アプリを作っています。
写真の詳細画面に表示させたコメントを削除したいです。
写真とコメントはそれぞれ違うモデルを用意し、ネストしてます。

色々試して、何回もエラーに当たってしまって行き止まってます……

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

undefined method `join' for #Hash:0x00007fbd3f839560

該当のソースコード

class CommentsController < ApplicationController
  def new
    @photo = Photo.find(params[:photo_id])
    comments = Comment.all
    comment = Comment.new
  end

  def create
    @photo = Photo.find(params[:photo_id])
    comment = Comment.new(comment_params)
    if comment.save
      ActionCable.server.broadcast 'comment_channel', content: comment
    end
    render :json => comment
  end

  def destroy
    comment = Comment.find(id: params[:id], photo_id: params[:photo_id])
    if comment.destroy
      redirect_to photo_path
    end
  end

  private

  def comment_params
    params.require(:comment).permit(:text).merge(user_id: current_user.id,photo_id: params[:photo_id])
  end
end
class PhotosController < ApplicationController
  before_action :find_params, except: [:index, :new, :create]
  before_action :authenticate_user!, only: [:new, :edit]


  def index
    @photos = Photo.order(created_at: :desc)
  end

  def new
    @photo = Photo.new
  end

  def create
    @photo = Photo.new(post_params)
    if @photo.save
      redirect_to root_path
    else
      render :new
    end
  end

  def show
    @comment = Comment.new
    @comments = @photo.comments.includes(:user)
  end

  def edit
  end

  def update
    if @photo.update(post_params)
      redirect_to root_path
    else
      render :edit
    end
  end

  def destroy
    if @photo.destroy
      redirect_to root_path
    end
  end

  private

  def find_params
    @photo = Photo.find(params[:id])
  end

  def post_params
    params.require(:photo).permit(:image, :title, :category_id).merge(user_id: current_user.id)
  end
end
<div class="show-comments">
<div class="submit-comment">
 <% if user_signed_in? %>
  <%= form_with(model:[@photo,  @comment]) do |f| %>
    <%= f.text_field :text, class:"submit-field" %>
    <%= f.submit "ボケる" , class:"submit-btn" %>
  <% end %>
 <% else %>
   <strong><p>※※※ コメントの投稿には新規登録/ログインが必要です ※※※</p></strong>
 <% end %>
 </div>
 <h1 class="list-comment">みんなのボケ一覧</h1>
 <div class="comments", id='comments'>
    <% @comments.reverse_each do |comment| %>
      <div class="comment-area", id="comment-area">
        <p class="comment"><%= comment.text %></p>
        <p class="comment-user"><%= comment.user.nickname %></p>
      </div>
      <% if user_signed_in? && current_user.id %>
        <%= link_to "削除", photo_comment_path(comment.photo_id, comment.id), method: :delete, class:"show-delete-btn", id:"show-delete-btn" %>
      <% end %>
    <% end %>
 </div>
</div>
Rails.application.routes.draw do
  get 'comments/new'
  devise_for :users
  root to: "photos#index"
  resources :photos do
    resources :comments, only:[:new, :create, :destroy]
  end
  resources :users
end
class Comment < ApplicationRecord
  belongs_to :photo
  belongs_to :user

  validates :text, presence: true
end
class Photo < ApplicationRecord
  has_one_attached :image
  belongs_to :user
  has_many :comments

  extend ActiveHash::Associations::ActiveRecordExtensions
  belongs_to :category

  with_options presence: true do
    validates :title
    validates :image
    validates :category_id , numericality: { other_than: 0 }
  end

end
class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  with_options presence: true do
    validates :last_name
    validates :first_name
    validates :nickname, length: { maximum: 8 }
    validates :email, uniqueness: {case_sensitive: true}
    validates :password, length: { minimum: 6 }, format: { with: /\A(?=.*?[a-z])(?=.*?\d)[a-z\d]+\z/i }
  end

  has_many :photos
  has_many :comments
end

試したこと

comment = Comment.find(id: params[:id], photo_id: params[:photo_id])
この書き方を色々試しました

******

①comment = Photo.find(id: params[:id], photo_id: params[:photo_id])

→同じ「undefined method `join' for #Hash:0x00007fbd3f839560」エラー

②comment = @photo.comments.find(id: params[:id], photo_id: params[:photo_id])

→undefined method `comments' for nil:NilClass

 この書き方では、「comments」を認識してくれなさそう  PhotoControllerに「comment = Comment.find(params[:id]」とか書いてみたけど、変化なし

③comment = Comment.find(comment_id: params[:comment_id], photo_id: params[:photo_id])

→undefined method `join' for {:comment_id=>nil, :photo_id=>"1"}:Hash
binding.pryでparams[:comment_id]を確認。
これが「Nill:class」になってしまっていました。
comment_idを渡してあげたいけど、どうしてもその方法がわからず……

*******

色々調べて、色々試しましたが、エラーが変われど、どれもうまくいかず……
あと、何を試せるでしょうか……

おしえていただきたいです。
よろしくお願いします。

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

ruby '2.6.5'
rails '~> 6.0.0'

0

2Answer

任意のカラムの値で検索するには Comment.find ではなく Comment.find_by を使ってください。

comment = Comment.find_by(id: params[:id], photo_id: params[:photo_id])

Comment.findComment の id を1つ以上受け取ることしかできません。

comment = Comment.find(params[:id])
comments = Comment.find(1, 42, 109)

@github0013@github Comment.findArray を受け取ったつもりで引数に対して #join を呼ぶが、実際には受け取った Hash#join がないのでエラーが 出ます。ということでエラーメッセージは join で合っています。 出るのではないかと思います。未確認ですが。


Update: このへんで #join してました。 https://github.com/rails/rails/blob/v6.0.4.1/activerecord/lib/active_record/relation/finder_methods.rb#L342

1

まずはエラー内容からちゃんと確認するほうが良いです。

あとはstacktraceが無いと判別がつかないです。

エラーになっているコードが書き換えられているので分かりませんが、activerecordに対してならjoinではなくjoinsです。

0

Your answer might help someone💌