I have an Rails 7 API and i'm using gem 'active_model_serializers', '~> 0.10.0'
to make het fit in the json_api requirements, but i need to in the nested attributes of my items include the name, not only the id and type, i tried many things i found in the internet, but none of them solved this for my, and i'm hoping someone here could.
my products_controller.rb
class ProductsController < ApplicationController
include ActionController::HttpAuthentication::Token::ControllerMethods
before_action :authenticate
include ErrorSerializer
before_action :set_product, only: %i[ show update destroy ]
# GET /products
def index
page_number = params[:page].try(:[], :number)
per_page = params[:page].try(:[], :size)
@products = Product.all.page(page_number).per(per_page)
# paginate json: @products
render json: @products, show_category: (param? params[:category]), show_unit: (param? params[:unit])
end
def all
@products = Product.all
render json: @products
end
# GET /products/1
def show
render json: @product
end
#The rest of crud options
private
# Use callbacks to share common setup or constraints between actions.
def set_product
@product = Product.find(params[:id])
end
# Only allow a list of trusted parameters through.
def product_params
params.require(:product).permit(:name, :description, :quantity_in_stock, :price, :highlight, :category_id, :unit_id)
end
def authenticate
authenticate_or_request_with_http_token do |token, options|
hmac_secret = ENV['TOKEN']
JWT.decode token, hmac_secret, true, { :algorithm => 'HS256' }
end
end
end
my product_serializer
class ProductSerializer < ActiveModel::Serializer
attributes :id, :name, :description, :quantity_in_stock, :price, :highlight
belongs_to :category, optional: true
belongs_to :unit, optional: true
def should_render_category
@instance_options[:show_category]
end
def should_render_unit
@instance_options[:show_unit]
end
end
my unit_serializer:
class UnitSerializer < ActiveModel::Serializer
attributes :id, :name
has_many :products, optional: true
end
my category_serializer:
class CategorySerializer < ActiveModel::Serializer
attributes :id, :name
has_many :products, optional: true
end
and my application_controller:
class ApplicationController < ActionController::API
before_action :ensure_json_request
def param? param
param && param != "false" && param != "nil"
end
def ensure_json_request
unless request.headers["Accept"] =~ /vnd\.api\ json/
render body: nil, :status => 406
else
unless request.get?
return if request.headers["Content-Type"] =~ /vnd\.api\ json/
render body: nil, :status => 415
end
end
end
end
And my actual response:
{
"id": "1",
"type": "products",
"attributes": {
"name": "Lightweight Iron Keyboard",
"description": "Sit quas ipsa. Animi non omnis. Eveniet et quidem.",
"quantity-in-stock": 99,
"price": 27.88,
"highlight": false
},
"relationships": {
"category": {
"data": {
"id": "4",
"type": "categories"
}
},
"unit": {
"data": {
"id": "2",
"type": "units"
}
}
}
}
CodePudding user response:
As mentioned by comments, you should look for alternatives as this gem is no longer maintained
Regarding your question, docs says about specifying serializer So to modify:
class ProductSerializer < ActiveModel::Serializer
# ...
belongs_to :category, optional: true, serializer: MyCategorySerializer
# ...
class MyCategorySerializer < ActiveModel::Serializer
attributes :id, :name, :type
end
and do the same way for UnitSerializer
it should work smoothly.