问题描述
我正在根据客户端发送的 json 请求使用 ruby 实现搜索端点,该请求的格式应为 GET /workspace/:id/searches? filter[query]=Old&filter[type]=ct:Tag,User,WokringArea&items=5 控制器看起来像这样
class SearchesController < ApiV3Controller
load_and_authorize_resource :workspace,class: "Company"
load_and_authorize_resource :user,through: :workspace
load_and_authorize_resource :working_area,through: :workspace
def index
keyword = filtered_params[:query].delete("\000")
keyword = '%' + keyword + '%'
if filtered_params[:type].include?('User')
@users = @workspace.users.where("LOWER(username) LIKE LOWER(?)",keyword)
end
if filtered_params[:type].include?('WorkingArea')
@working_areas = @workspace.working_areas.where("LOWER(name) LIKE LOWER(?)",keyword)
end
@resources = @working_areas
respond_json(@resources)
end
private
def filtered_params
params.require(:filter).permit(:query,:type)
end
def ability_klasses
[WorkspaceAbility,UserWorkspaceAbility,WorkingAreaAbility]
end
end
respond_json 以 json 格式返回资源,它看起来像这样
def respond_json(records,status = :ok)
if records.try(:errors).present?
render json: {
errors: records.errors.map do |pointer,error|
{
status: :unprocessable_entity,source: { pointer: pointer },title: error
}
end
},status: :unprocessable_entity
return
elsif records.respond_to?(:to_ary)
@pagy,records = pagy(records)
end
options = {
include: params[:include],permissions: permissions,current_ability: current_ability,Meta: Meta_infos
}
render json: ApplicationRecord.serialize_fast_apijson(records,options),status: status
结束
现在的问题是响应应该是这样的:
{
data: [
{
id: 32112,type: 'WorkingArea'
attributes: {}
},{
id: 33321,type: 'User',attributes: {}
},{
id: 33221,type: 'Tag'
attributes: {}
}
解决方法
您可以根据 API 的结果定义一个模型,而不是在您的数据库中。然后包含一些 ActiveModel 模块以获得更多功能。
# app/models/workspace_result.rb
class WorkspaceResult
include ActiveModel::Model
include ActiveModel::Validations
include ActiveModel::Serialization
attr_accessor(
:id,:type,:attributes
)
def initialize(attributes={})
filtered_attributes = attributes.select { |k,v| self.class.attribute_method?(k.to_sym) }
super(filtered_attributes)
end
def self.from_json(json)
attrs = JSON.parse(json).deep_transform_keys { |k| k.to_s.underscore }
self.new(attrs)
end
end
然后在您的 API 结果中,您可以执行以下操作:
results = []
response.body["data"].each do |result|
results << WorkspaceArea.from_json(result)
end
你也可以在这个模型上定义实例方法,等等。