简体   繁体   中英

Rails controller class does not inherit a method from the parent class

I'm following a tutorial on how to create a REST Api using the rails-api gem.

In the tutorial, most of the API logic is encapsulated in the base class file app/controllers/api/v1/api_base_controller.rb

module Api
  module V1
    class ApiBaseController < ApplicationController
      protect_from_forgery with: :null_session
      before_action :set_resource, only: [:destroy, :show, :update]
      respond_to :json

      private
      #Returns the resource from the created instance variable
      #@return [Object]
      def get_resource
        instance_variable_get("@#{resource_name}")
      end

      #Returns the allowed parameters for searching
      # Override this method in each API controller
      # to permit additional parameters to search on
      # @return [Hash]
      def query_params
        {}
      end

      #Returns the allowed parameters for pagination
      # @return [Hash]
      def page_params
        params.permit(:page, :page_size)
      end
      # The resource class based on the controller
      # @return [Class]
      def resource_class
        @resource_class ||= resource_name.classify.constantize
      end

      # The singular name for the resource class based on the controller
      # @return [String]
      def resource_name
        @resource_name ||= self.controller_name.singularize
      end

      #Only allow a trusted parameter "white list" through.
      # If a single resource is loaded for #create or #update,
      # then the controller for the resource must implement
      # the method "#{resource_name}_params" to limit permitted
      # parameters for the individual model.
      def resource_params
        @resource_params ||= self.send("#{resource_name}_params")
      end

      #Use callbacks to share common setup or constraints between actions.
      def set_resource(resource = nil)
        resource ||= resource_class.find(params[:id])
        instance_variable_set("@#{resource_name}", resource)
      end

      #POST /api/v1/{plural_resource_name}
      def create
        set_resource(resource_class.new(resource_params))

        if get_resource.save
          render :show, status: :created
        else
          render json: get_resource.errors, status: :unprocessable_entity
        end
      end

      #DELETE /api/v1/{plural_resource_name}/:id
      def destroy
       get_resource.destroy
        head :no_content
      end

      #GET /api/v1/{plural_resource_name}
      def index
        plural_resource_name = "@#{resource_name.pluralize}"
        resources = resource_class.where(query_params).page(page_params[:page]).per(page_params[:page_size])

        instance_variable_set(plural_resource_name, resources)
        respond_with instance_variable_get(plural_resource_name)
      end

      #GET /api/v1/{plural_resource_name}/1
      def show
        respond_with get_resource
      end

      #PATCH/PUT /api/{plural_resource_name}/1
      def update
        if get_resource.update(resource_params)
          render :show
        else
          render json: get_resource.errors, status: :unprocessable_entity
        end
      end
    end
  end
end

The model controllers inherit from this ApiBaseController one of the model controllers ( albums_controllers.rb ) looks like this:

module Api
  module V1
    class AlbumsController < Api::V1::ApiBaseController
      private
      def album_params
        params.require(:album).permit(:title)
      end

      def query_params
        params.permit(:title, :artist_id)
      end
    end
  end
end

I also have this in routes.rb

Rails.application.routes.draw do
  namespace :api, defaults: {format: 'json'} do
    namespace :v1 do
      resources :albums, :artists
    end
  end
end

when I do http://localhost:3000/api/v1/artists on the browser, i get this error:

`The action 'index' could not be found for Api::V1::ArtistsController`

I have also noted that the ApplicationController generated by the rails-api gem inherits from ActionController::API and not ActionController::Base but i'm not sure whether this is the problem.

private methods are not available to subclasses. If you REALLY want to hide all of those methods but make it available to subclasses, use protected instead.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM