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

时间:2019-03-27 23:19:59

标签: ruby-on-rails activerecord polymorphic-associations

我已经构建了一个经典的Rails API后端,该后端具有UserCommentSighting。我已通过多态形态关系将Comment设置为Commentable。顺便说一下,Sighting也是UserAnimal之间的联接表,但是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"):

1 个答案:

答案 0 :(得分:1)

第一个错误

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

该路线只有params [:sighting_id]。

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

但是Api :: V1 :: CommentsController#index没有参数[: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