Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose default value doesn't work for me #373

Open
j-boers-13 opened this issue Feb 6, 2023 · 2 comments
Open

Expose default value doesn't work for me #373

j-boers-13 opened this issue Feb 6, 2023 · 2 comments

Comments

@j-boers-13
Copy link

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

@j-boers-13 j-boers-13 changed the title Expose :default doesn't work Expose :default doesn't work for me Feb 6, 2023
@j-boers-13 j-boers-13 changed the title Expose :default doesn't work for me Expose default value doesn't work for me Feb 6, 2023
@lenon
Copy link

lenon commented Feb 24, 2023

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.

@lukasz-wojcik
Copy link

lukasz-wojcik commented Apr 28, 2023

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants