Search code examples
ruby-on-railsruby

Rails Render JSON Method Seems To Be Removing Type Attribute from Response


I'm using Single Table Inheritance (STI) in my Rails app for the User object. There is an API response that is including all attributes of my User subclasses (Teacher, Student) except for type. I believe this is due to using the render json method, as I was able to find some other questions from a long time ago with this issue, but haven't found any solutions.

How do I prevent Rails from suppressing the user type attribute in the json response?

My controller is returning:

render json: {
                logged_in: true,
                user: @user,
            }

The user model has the following schema (taken from schema.rb):

  create_table "users", force: :cascade do |t|
    t.string "email"
    t.string "username"
    t.string "password_digest"
    t.string "first_name"
    t.string "last_name"
    t.string "type"
    t.string "phone_number"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

And my JSON response received from the Rails API for the user object was:

"logged_in":true,"user":{"id":2,"email":"[email protected]","username":"Student","password_digest":"redacted","first_name":"Test","last_name":"Test","phone_number":"18008008100","created_at":"2024-06-08T02:35:27.382Z","updated_at":"2024-06-10T05:44:14.299Z"}}

Why does it contain everything except for the type attribute?


Solution

  • Why does it contain everything except for the type attribute?

    Because type attribute, aka User.inheritance_column, is skipped:

    options[:except] |= Array(self.class.inheritance_column)
    

    https://github.com/rails/rails/blob/v7.1.3.4/activerecord/lib/active_record/serialization.rb#L18


    You could use :methods option to add type back:

    render json: {
      logged_in: true,
      user: @user.as_json(methods: :type)
    }
    

    or render json view:

    # app/views/users/show.json.jbuilder
    
    json.logged_in true
    json.user do
      json.extract! @user, :id, :email, :type
    end