Невозможно получить доступ к некоторым маршрутам в полиморфных ассоциациях в Rails 5.2 - PullRequest
0 голосов
/ 28 марта 2019

Я создал классический бэкэнд Rails API, который имеет User, Comment, Sighting. Я настроил Comment как Commentable через полиморфные морфические отношения. Кстати, Sighting также является таблицей соединения между User и Animal, но 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 Ответ

1 голос
/ 28 марта 2019

Первая ошибка

/api/v1/sightings/17/comments - это /api/v1/sightings/:sighting_id/comments

Этот маршрут имеет только параметры [: sighting_id].

Вызывает before_action: find_comment перед запуском действия с индексом, а find_comment требует params [: id]

Но Api :: V1 :: CommentsController # index не имеет параметров [: id]

Таким образом, Rails выдаст сообщение «Не удалось найти комментарий без идентификатора»

Я думаю, что вам не нужно вызывать before_action при запросе на индексирование

Удалить :index только для состояния

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

Вторая ошибка

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

этот маршрут не имеет: индекс

Добавить :index только к условию

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