【问题标题】:Returning resources with different types for rails Restful API为rails Restful API返回不同类型的资源
【发布时间】:2021-02-11 22:14:40
【问题描述】:

我正在根据客户端发送的 json 请求使用 ruby​​ 实现搜索端点,该请求的格式应为 GET /workspace/:id/searches? filter[query]=旧&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: {}
    }

如何使我的代码支持响应具有不同类型的资源?

【问题讨论】:

    标签: ruby-on-rails json ruby-on-rails-5 rails-api


    【解决方案1】:

    您可以基于 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
    

    还可以在这个模型上定义实例方法等

    【讨论】:

      猜你喜欢
      • 2016-01-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多