Serialize last record of a one-to-many association

422 Views Asked by At

I have a user with many heights (stature measurements) recorded in a Height model but would like to serialize only last height.

I tried to create a (fake) custom has_one association but it does not give me what I was looking for...

app/serializers/user_serializer.rb

class UserSerializer < BaseSerializer
  attributes :email

  # has_many :heights
  has_one :current_height, record_type: :height do |user|
    user.heights.last
  end
end

app/controllers/users_controller.rb

options[:include] = [:heights]
render json: UserSerializer.new(user, options).

As is, I get the error: "heights is not specified as a relationship on UserSerializer."

If I uncomment # has_many :heights, I get though:

{
    "data": {
        "id": "1",
        "type": "user",
        "attributes": {
            "email": "[email protected]"
        },
        "relationships": {
            "heights": {
                "data": [
                    {
                        "id": "1",
                        "type": "height"
                    },
                    {
                        "id": "2",
                        "type": "height"
                    }
                ]
            },
            "currentHeight": {
                "data": {
                    "id": "2",
                    "type": "height"
                }
            }
        }
    },
    "included": [
        {
            "id": "1",
            "type": "height",
            "attributes": {
                "value": "186.0"
            }
        },
        {
            "id": "2",
            "type": "height",
            "attributes": {
                "value": "187.0"
            }
        }
    ]
}

But I don't want to include in the compound document all recorded heights...

Expected result

{
    "data": {
        "id": "1",
        "type": "user",
        "attributes": {
            "email": "[email protected]"
        },
        "relationships": {
            "currentHeight": {
                "data": {
                    "id": "2",
                    "type": "height"
                }
            }
        }
    },
    "included": [
        {
            "id": "2",
            "type": "height",
            "attributes": {
                "value": "187.0"
            }
        }
    ]
}
2

There are 2 best solutions below

1
On

Forgive me if I accuse you of overthinking this, but couldn't you just add a method to your user that gets the last height?

class User < ApplicationRecord
  #
  # your user code here
  # ...

  def last_height
    self.heights.last
  end
end

Then get the record with current_user.last_height

If that's not what you're asking for, I apologize, I may not be fully understanding the question.

1
On

you can add this to User model

has_one :last_height, -> { order 'created_at DESC' }, class_name: "Height"