grape-entity
grape-entity copied to clipboard
Expose default value doesn't work for me
Hi,
First of all thanks for the amazing work! I am using grape entity to serialize ActiveRecord (Rails) objects to a hash, using .respresent(object)
My grape entity looks like this:
class Entities::ProductEntity < Grape::Entity
expose :platform_id, as: :id
expose :name
expose :visible
expose :main_image
expose :url
expose :short_description, default: ''
expose :brand_id
expose :category_ids
expose :relevant_product_ids
def brand_id
object.brand&.platform_id if object.respond_to?(:brand)
end
def category_ids
object.categories&.pluck(:platform_id) if object.respond_to?(:categories)
[]
end
def relevant_product_ids
object.relevant_products&.pluck(:platform_id) if object.respond_to?(:relevant_products)
[]
end
end
The default option on short_description doesn't work, neither did it work if i tried to use it in another entity with default: []
Am i doing something wrong? Or am I on an old version?
I am using https://github.com/ruby-grape/grape-entity#default-value this syntax, and am on grape-entity version 0.10.2
Hope you have some time to help me out, but no worries if not.
Thanks in advance
I'm having a similar issue. When I pass default: []
to a field exposed with using:
, it doesn't work.
require 'grape'
require 'grape-entity'
class Address < Grape::Entity
expose :address_line
expose :city
end
class Account < Grape::Entity
expose :name
expose :state, default: 'pending'
expose :addresses, using: Address, default: []
end
Account.represent({ name: 'alice' }).as_json
# => {:name=>"alice", :state=>"pending", :addresses=>nil}
The default value for state
is used, but for addresses
it is nil
and not an empty array, as I would expect.
I tried to debug the code to find the issue and I noticed that when I pass serializable: true
to as_json
, it seems to work:
Account.represent({ name: 'alice' }).as_json(serializable: true)
# => {:name=>"alice", :state=>"pending", :addresses=>[]}
I wasn't able to find why passing this option works.
I had just the same case. This is messed up and very not intuitive. You cannot set a default to sth which is empty...
Below spec fails: expected #<Grape::Entity::Exposure::NestingExposure::OutputBuilder({:a=>nil, :b=>nil, :c=>nil})> to match {:a=>"", :b=>[], :c=>{}}
it 'sets default to empty structure when key is missing' do
class Dummy < Grape::Entity
expose :a, default: "sth"
expose :b, default: []
expose :c, default: {}
end
expect(Dummy.represent({}).as_json).to match(
{
a: "sth",
b: [],
c: {}
}
)
end
Below spec passes
it 'sets default when key is missing' do
class Dummy < Grape::Entity
expose :a, default: "sth"
expose :b, default: [:element]
expose :c, default: { key: 'value' }
end
expect(Dummy.represent({}).as_json).to match(
{
a: "sth",
b: [:element],
c: { key: 'value' }
}
)
end
end
I have not analysed this gem code as that would take some time which I want to spend elsewhere.
In local project I have created a method:
def expose_with_default(key:, default:, as: nil, **options)
as ||= key.to_sym
expose key, as: as, **options do |object, _|
if object[key].nil?
default
else
object[key]
end
end
end
to handle default properly and do not have to do such modifications in every single case.
Regardless of that we are unfortunately moving away from grape-entity because quirks like this and its performance not sufficient for our needs.