Rails 控制器 class 没有从父 class 继承方法
Rails controller class does not inherit a method from the parent class
我正在学习如何使用 rails-api gem.
创建 REST Api 的教程
在教程中,大部分 API 逻辑都封装在基础 class 文件中 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
模型控制器继承自此ApiBaseController
其中一个模型控制器 (albums_controllers.rb
) 看起来像这样:
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
我在routes.rb
中也有这个
Rails.application.routes.draw do
namespace :api, defaults: {format: 'json'} do
namespace :v1 do
resources :albums, :artists
end
end
end
当我在浏览器上执行 http://localhost:3000/api/v1/artists
时,出现此错误:
`The action 'index' could not be found for Api::V1::ArtistsController`
我还注意到 rails-api gem 生成的 ApplicationController
继承自 ActionController::API
而不是 ActionController::Base
但我不确定这是否是问题所在。
private
方法不可用于子类。如果你真的想隐藏所有这些方法但让子类可以使用它,请改用 protected
。
我正在学习如何使用 rails-api gem.
创建 REST Api 的教程在教程中,大部分 API 逻辑都封装在基础 class 文件中 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
模型控制器继承自此ApiBaseController
其中一个模型控制器 (albums_controllers.rb
) 看起来像这样:
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
我在routes.rb
Rails.application.routes.draw do
namespace :api, defaults: {format: 'json'} do
namespace :v1 do
resources :albums, :artists
end
end
end
当我在浏览器上执行 http://localhost:3000/api/v1/artists
时,出现此错误:
`The action 'index' could not be found for Api::V1::ArtistsController`
我还注意到 rails-api gem 生成的 ApplicationController
继承自 ActionController::API
而不是 ActionController::Base
但我不确定这是否是问题所在。
private
方法不可用于子类。如果你真的想隐藏所有这些方法但让子类可以使用它,请改用 protected
。