Conditional attributes with jsonapi-serializers throwing TypeError

1.4k views Asked by At

I am working on a Ruby on Rails project with ruby-2.6.0 and Rails 6. i am working on api part, i have used jsonapi-serializers gem in my app. I want to add conditional attribute in serializer.

Controller:

class OrderDetailsController < Api::V1::ApiApplicationController
    before_action :validate_token
    
  def show
    user = User.find_by_id(@user_id)
    order_details = user.order_details.where(id: params[:id])&.first
    render json: JSONAPI::Serializer.serialize(order_details, context: { order_detail: true })
  end
end

Serializer:

class OrderDetailSerializer
  include JSONAPI::Serializer

  TYPE = 'Order Details'

  attribute :order_number
  attribute :price
  attribute :quantity
  attribute :order_status

  attribute :ordered_date, if: Proc.new { |record|
    context[:order_detail] == true
  }
end

So here i am passing the 'order_detail' from controller inside context.I am getting the below error:-

TypeError (#<Proc:0x00007fe5d8501868@/app_path/app/serializers/order_detail_serializer.rb:46> is not a symbol nor a string):

I have followed the conditional attributes as mentioned on the jsonapi-serializer and have tried to make my 'ordered_date' attribute conditional but it's not working.

Please guide me how to fix it. Thanks in advance.

2

There are 2 answers

2
Christian Bruckmayer On

You access context but it seems not defined. From the documentation

The record and any params passed to the serializer are available inside the Proc as the first and second parameters, respectively.

class OrderDetailSerializer
  include JSONAPI::Serializer

  TYPE = 'Order Details'

  attribute :order_number
  attribute :price
  attribute :quantity
  attribute :order_status

  attribute :ordered_date, if: Proc.new { |record, params|
    params[:context][:order_detail]
  }
end

You also don't need to check for == true as the parameter is already a boolean.

If that doesn't work, you can always add a puts or debugger in your Proc to have a look what is happening in the Proc.

class OrderDetailSerializer
  include JSONAPI::Serializer

  TYPE = 'Order Details'

  attribute :order_number
  attribute :price
  attribute :quantity
  attribute :order_status

  attribute :ordered_date, if: Proc.new { |record, params|
    puts record.inspect
    puts params.inspect
    true
  }
end
0
Mihail Panayotov On

Looking at the example for conditional attributes, you simply need to pass params as a second parameter, so:

in controller:

render json: JSONAPI::Serializer.serialize(order_details, { params: { order_detail: true }})

in serializer:

attribute :ordered_data, if: Proc.new { |record, params|
  params[:order_detail]
}