简体   繁体   English

根据操作仅使用 ActiveModel 和 Grape 序列化特定属性 API

[英]Serialize only specific attributes with ActiveModel and Grape API depending on action

In my Grape API the same model can be accessed by different controllers and endpoints.在我的 Grape API 中,不同的控制器和端点可以访问相同的 model。 I need to serialize the same model for each of them, but not every attribute applies to all endpoints.我需要为它们中的每一个序列化相同的 model,但并非每个属性都适用于所有端点。 I know there is the "filter" method, but this removes an attribute.我知道有“过滤器”方法,但这会删除一个属性。 I would like to list the valid attributes instead.我想改为列出有效属性。 This seems safer.这似乎更安全。 I figured out the following approach.我想出了以下方法。 However, is there a built-in way I'm missing?但是,有没有我缺少的内置方式?

Using the code below, I would like to return "id, comments, status, user_id" if called by the "/event_signups" endpoint.使用下面的代码,如果被“/event_signups”端点调用,我想返回“id, comments, status, user_id”。 I would like to return "id, comments, event_id" if called by the "/user_signups" endpoint.如果由“/user_signups”端点调用,我想返回“id、comments、event_id”。

Serializer串行器

module Mobile
  module V4

    class SignupSerializer < ActiveModel::Serializer

      attributes :id,
                 :comments,
                 :status,
                 :event_id,
                 :user_id

      attribute :id,       if: :id?
      attribute :comments, if: :comments?
      attribute :status,   if: :status?
      attribute :event_id, if: :event_id?
      attribute :user_id,  if: :user_id?

      def id?
        !instance_options[:allowed_attributes].index(:id).nil?
      end

      def comments?
        !instance_options[:allowed_attributes].index(:comments).nil?
      end

      def status?
        !instance_options[:allowed_attributes].index(:status).nil?
      end

      def event_id?
        !instance_options[:allowed_attributes].index(:event_id).nil?
      end

      def user_id?
        !instance_options[:allowed_attributes].index(:user_id).nil?
      end

    end

  end
end

Grape API Endpoints葡萄 API 端点

module Mobile
  module V4
    class Signups < Mobile::V4::Root
      include Mobile::V4::Defaults

      resource :signups, desc: 'Operations about the signups' do

        desc 'Returns list of user's signups'
        oauth2 # This endpoint requires authentication

        get '/user_signups', allowed_attributes: [:id, :comments, :event_id] do
          Signup.where(user_id: current_user.id)
        end

        desc 'Returns list of event's signups'
        params do
          requires :event_id, type: Integer, desc: 'Event ID'
        end
        oauth2 # This endpoint requires authentication

        get '/event_signups', allowed_attributes: [:id, :comments, :status, :user_id] do
          Signup.where(event_id: params[:event_id])
        end

      end

    end

  end
end

I assume that your context does not allow you to use the render function directly.我假设您的上下文不允许您直接使用render function。 You are facing a problem such as excessively fetching extra fields but you want to fetch some fields defined in fields_array你遇到了过度获取额外字段的问题,但你想获取定义在fields_array中的一些字段

ActiveModelSerializers::SerializableResource.new(
        resource,
        serializer: SerializerClass,
        fields: fields_array
      ).serializable_hash

Or, if you have a collection of resources, use each_serializer instead of serializer或者,如果您有资源集合,请使用each_serializer而不是serializer

ActiveModelSerializers::SerializableResource.new(
        collection,
        each_serializer: SerializerClass,
        fields: fields_array
      ).serializable_hash

Can you try selecting only the fields you need?您可以尝试只选择您需要的字段吗? Eg例如

Signup.where(user_id: current_user.id).select(:id, :comments, :status, :user_id)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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