无法访问 Rails 5.2 中多态关联中的某些路由

Unable to access some routes in polymorphic associations in Rails 5.2

我构建了一个经典的 Rails API 后端,它有 UserCommentSighting。我通过多态关系将 Comment 设置为 Commentable。顺便说一句,Sighting 也是 UserAnimal 之间的联接 table,但 Animal 与此处无关。 我可以在控制台中通过 Sighting.first.comments.create() 创建评论并通过 `Comment.first.comments.create() 评论评论,但是当我尝试在路由中查看它们时,我没有得到方法错误或路由错误。我需要从 React 获取请求,所以这些路由需要工作。

我的模特:


class Comment < ApplicationRecord

  belongs_to :commentable, :polymorphic => true
  has_many :comments, as: :commentable, dependent: :destroy
end

class Sighting < ApplicationRecord
  has_one_attached :image
  belongs_to :user
  belongs_to :animal
  has_many :comments, :as => :commentable, dependent: :destroy

  def image_filename
    self.image.filename.to_s if self.image.attached?
  end

  def image_attached?
    self.image.attached?
  end


end
class User < ApplicationRecord
    include Rails.application.routes.url_helpers
    has_many :sightings
    has_many :animals, through: :sightings
    has_many :comments, :as => :commentable, dependent: :destroy

  has_secure_password
  has_one_attached :avatar

  def avatar_filename
    self.avatar.filename.to_s if self.avatar.attached?
  end

  def avatar_attached?
    self.avatar.attached?
  end



  validates :username, uniqueness: true

  def attachment_url
    if self.attachment.attached?
      Rails.application.routes.url_helpers.rails_blob_url(self.attachement, only_path: false)
    else
      nil
    end
  end

end

我的控制器:

class Api::V1::CommentsController < ApplicationController
    before_action :find_comment, only: [:index, :update, :destroy]
    before_action :find_commentable


  def index
   @comments = Comment.all
   render json: @comments
  end



  def create
    @comment = @commentable.comments.new(comment_params)
    if @comment.save
      render json: @comment, status: :accepted
    else
      render json: { errors: @comment.errors.full_messages }, status: :unprocessible_entity
    end
  end


  def update
   @comment.update(comment_params)
   if @comment.save
     render json: @comment, status: :accepted
   else
     render json: { errors: @comment.errors.full_messages }, status: :unprocessible_entity
   end
  end




  private

  def comment_params
   params.require(:comment).permit(:body, :likes)
  end

  def find_comment
   @comment = Comment.find(params[:id])
  end

  def find_commentable
    @commentable = Sighting.find_by_id(params[:sighting_id])
    if params[:sighting_id]
    @comentables = Comment.find_by_id(params[:comment_id])
    if params[:comment_id]
    end
  end
  end

end
class Api::V1::SightingsController < ApplicationController
  before_action :find_sighting, only: [:update, :show, :destroy]

  def index
   @sightings = Sighting.all
   render json: @sightings
  end

  def show
    render json: @sighting, status: :ok
  end




  def create
    @sighting = Sighting.new(sighting_params)
    # @sighting.image.attach(params[:sighting][:image])
     if @sighting.save
      render json: @sighting, status: :accepted
    else
      render json: { errors: @sighting.errors.full_messages }, status: :unprocessible_entity
    end
  end


  def update

    # if curr_user.id == @sighting.user_id
   @sighting.update(sighting_params)
   if @sighting.save
     render json: @sighting, status: :accepted
   else
     render json: { errors: @sighting.errors.full_messages }, status: :unprocessible_entity
   end
  end


  def destroy
    if curr_user.id == @sighting.user_id

      @sighting.delete
      render json: "sighting deleted"
    else
      render json: { errors: "You are not authorized to delete"}
    end
  end


  private

  def sighting_params
   params.require(:sighting).permit(:title, :body, :likes, :image, :user_id, :animal_id)
  end

  def find_sighting
   @sighting = Sighting.find(params[:id])
  end
end
class Api::V1::UsersController < ApplicationController

  before_action :find_user, only: [:update, :show, :avatar_upload, :destroy]


  def index
   @users = User.all
   render json: @users
  end


  def create

    @user = User.new(
      username: params[:username],
      password: params[:password]
    )
    if @user.save
    encode_token(@user.id)
      render json: {user: UserSerializer.new(@user), token: ENV['jwt']}, status: :ok
    else
      render json: {errors: @user.errors.full_messages}
    end
  end


  def show
    if @user
      if curr_user.id == @user.id
        render json: @user
      elsif
          curr_user.id == @user.id
          # @user.avatar.attach(params[:user][:avatar])
        render json: @user
      else
        render json: {errors: @user.errors.full_messages }, status: :unprocessible_entity
      end
    else
      render json: {errors: "User not found!"}
    end

  end


  def update

    if curr_user.id == @user.id
      @user.update(user_params)
      # @user.avatar.attach(params[:user][:avatar])
      if @user.save
      render json: @user, status: :accepted
    else
     render json: { errors: @user.errors.full_messages }, status: :unprocessible_entity
      end
    end
  end

  def avatar_upload
    @user.update(user_params)
    if @user.save
    render json: @user, status: :accepted
  else
   render json: { errors: @user.errors.full_messages }, status: :unprocessible_entity
  end
end


  def destroy
    if curr_user.id == @user.id
      @user.avatar.purge_later if @user.avatar
      @user.delete
      render json: "user deleted"
    else
      render json: { errors: "You are not authorized to delete"}
    end
  end

  private

  def user_params
   params.require(:user).permit(:name, :username, :password, :avatar)
  end


  def find_user
   @user = User.find(params[:id])
  end

end

我的序列化程序

class CommentSerializer < ActiveModel::Serializer

  attributes :id, :body, :likes, :user_id

  belongs_to :commentable, :polymorphic => true
  has_many :comments, as: :commentable, dependent: :destroy

  def user_name
     User.all.find { |f| f.id == object.user_id }.username
  end

end
class SightingSerializer < ActiveModel::Serializer
  include Rails.application.routes.url_helpers

  belongs_to :user
  belongs_to :animal
  has_many :comments, :as => :commentable, dependent: :destroy


  attributes :id, :title, :body, :likes, :image, :created_at, :user_id



 def image
   rails_blob_path(object.image, only_path: true) if object.image.attached?
 end

end
class UserSerializer < ActiveModel::Serializer
  include Rails.application.routes.url_helpers

  attributes :id, :name, :username, :avatar

  has_many :sightings
  has_many :animals, through: :sightings
  has_many :comments, :as => :commentable, dependent: :destroy


  def avatar
    rails_blob_path(object.avatar, only_path: true) if object.avatar.attached?
  end


end

和我的路线:

Rails.application.routes.draw do
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
  post "/rails/active_storage/direct_uploads", to: "direct_uploads#create"

  root to: 'sightings#index'

  namespace :api do
    namespace :v1 do

      resources :users, only: [:index, :show, :create, :update, :destroy] do
        resources :comments
      end

      resources :animals, only: [:index, :show, :update]

      resources :sightings, only: [:index, :show, :create, :update, :destroy] do
        resources :comments
      end

      resources :comments, only: [:create, :update, :destroy] do
        resources :comments
      end

      put "/users/avatar_upload/:id",   to: "users#avatar_upload"
      post "/login", to: "auth#login"
      get "/current_user", to: "auth#get_user_from_token"

    end
  end

end

这是 localhost:9000/api/v1/sightings/17/comments

的错误
Started GET "/api/v1/sightings/17/comments" for 127.0.0.1 at 2019-03-27 19:15:03 -0400
Processing by Api::V1::CommentsController#index as HTML
  Parameters: {"sighting_id"=>"17"}
Completed 404 Not Found in 27ms (ActiveRecord: 19.8ms)



ActiveRecord::RecordNotFound (Couldn't find Comment without an ID):

app/controllers/api/v1/comments_controller.rb:42:in `find_comment'

localhost:9000/api/v1/sightings

Completed 200 OK in 157ms (Views: 117.3ms | ActiveRecord: 33.9ms)


Started GET "/api/v1/comments" for 127.0.0.1 at 2019-03-27 19:17:07 -0400

ActionController::RoutingError (No route matches [GET] "/api/v1/comments"):

第一个错误

/api/v1/sightings/17/comments/api/v1/sightings/:sighting_id/comments

该路由只有参数[:sighting_id].

它在 运行 索引操作之前调用 before_action :find_comment 并且 find_comment 需要参数 [:id]

但是Api::V1::CommentsController#index没有params[:id]

所以 Rails 会发出“找不到没有 ID 的评论”

我认为您不需要在请求索引

时调用 before_action

删除:index仅条件

before_action :find_comment, only: [:update, :destroy]

第二个错误

 resources :comments, only: [:create, :update, :destroy] do
    resources :comments
 end

这条路线没有:index

:index添加到唯一条件

 resources :comments, only: [:index, :create, :update, :destroy] do