[Rails] ActiveModel :: Serializers with or without explicit nesting

what's this

When using Rails ActiveModel :: Serializers When you want to render two json objects, you can nest them in only one or not. This article is written as a memorandum for myself.

What you can get from this article

When writing the following code in a Rails method, the object you want to nest You will know how to play with it as you like.

users_controller.rb


render json: { hoge: hoge, fuga: fuga }, include: :piyo

answer

Use Rails'as_json method to solve it!

environment

Ruby 2.6 Rails 6.0 active_model_serializers 0.10.10

Premise

There are the following four models.

user and facility are 1: N, The product model and user model are not associated. Since the column is not needed this time, it is omitted.

user.rb


class User < ApplicationRecord
  belongs_to :facility
end

facility.rb


class Facility < ApplicationRecord
  has_many :users
end

product.rb


class Product < ApplicationRecord
  #No association
end

Status

When you call the users # show action You need to render both the user and products objects, You also need to retrieve the nested object for user.

Error actually encountered

users_controller.rb


  def show
    user = User.find(params[:id])
    products = Product.all
    render json: { user: user, products: products }, include: ['facility']
  end

When I write in the above code and receive a response, I get the following error!

NoMethodError (undefined method `facility' for #<Product:0x00007fed8d885518>):

Clarified to include in the json object to render. But with the above writing style Facility is nested in both the user and products objects. Since the products model and the facility model do not form an association, Of course there is no such method (model?), So Rails says, "facility? I don't know such a method!"

Then what to do

Conclusion

Use the as_json method to format json at the timing of assigning a variable, Specify that the facility model should be nested with include.

users_controller.rb


  def show
    user = User.find(params[:id]).as_json(include: 'facility')
    products = Product.all
    render json: {user: user, products: products}, status: :ok
  end

This allows you to nest the facility model only in the variable user.

Advanced version

If you want to get data without nesting the facility model because you don't need the facility model, do this.

users_controller.rb


  def show
    user = User.find(params[:id]).as_json
    products = Product.all
    render json: {user: user, products: products}, status: :ok
  end

I know how to write it, but honestly I don't know why json is formatted without being nested. Are there times when it is nested and times when it is not? Verification required here

Bonus: The as_json options are explained in detail in the article ActiveModel as_json option list. Thank you ~

The official documentation for the Rails as_json method is here: https://railsdoc.com/page/as_json

Recommended Posts

[Rails] ActiveModel :: Serializers with or without explicit nesting
Internal class type: With or without static