Warm tip: This article is reproduced from serverfault.com, please click

Ruby FastJsonAPI dynamic set_type?

发布于 2018-03-17 05:11:06

I've been really digging FastJsonAPI. Works great.

Is it possible to set the set_type serializer definition on a per-object basis?

i.e. I'm using Rails STI (single table inheritance). I have a mixed set of base objects and derivative objects, and I'd like to have different types for each.

This is a fake example of JSON output I would like:

{
  "data": [
    {
      "attributes": {
        "title": "Generic Vehicle"
      },
      "id": "1",
      "type": "vehicle"
    },
    {
      "attributes": {
        "title": "Fast Car"
      },
      "id": "2",
      "type": "car"
    },
    {
      "attributes": {
        "title": "Slow Car"
      },
      "id": "3",
      "type": "car"
    },
    {
      "attributes": {
        "title": "Motorcycle"
      },
      "id": "4",
      "type": "motorcycle"
    }
  ]
}

I do have an object type attribute I can use, of course, since I'm using STI. But I don't want to use it as an attribute: I want to use it as the outside type, as in the JSON above.

serializer(s):

class VehicleSerializer
  include FastJsonapi::ObjectSerializer
  set_type :vehicle  # can I tie this to individual objects, right here?
  attributes :title
end

class CarSerializer < VehicleSerializer
  set_type :car
  attributes :title
end

class MotorcycleSerializer < VehicleSerializer
  set_type :motorcycle
  attributes :title
end

class TruckSerializer < VehicleSerializer
  set_type :truck
  attributes :title
end

You see, I have some controllers which only pull from a single object type, and for them, the single CarSerializer or whatever, works great. The trouble is when I use a controller like this, that aggregates multiple vehicle types in the index method:

require_relative '../serializers/serializers.rb'

class MultiVehiclesController < ApplicationController

  def index
    @vehicles = Vehicle.where(type: ["Car", "Motorcycle"])

    # perhaps there's a way to modify the following line to use a different serializer for each item in the rendered query?
    render json: VehicleSerializer.new(@vehicles).serializable_hash
  end

  def show
    @vehicle = Vehicle.find(params[:id])

    # I suppose here as well:
    render json: VehicleSerializer.new(@vehicle).serializable_hash
  end

end
Questioner
aljabear
Viewed
11
aljabear 2018-11-28 20:29:37

This was not possible in version 1 of FastJsonAPI, which I was using for this. It is now apparently possible as of version 1.2 (although I have not yet tested it).