1

I have this entity.

class EmpEntity < Grape::Entity
  expose :id
  expose :age
  expose :name do
    expose :firstname
    expose :lastname
    expose :nickname
  end
end

And I take a result like this.

data = {
  id: 1,
  age: 18,
  name: {
    firstname: 'foo',
    lastname: 'bar',
    nickname: 'foobar',
  },
}

When I use entity's method, it return this.

EmpEntity.represent(data)
# => #<EmpEntity:15940 id=1 age=18 name={:firstname=>nil, :lastname=>nil, :nickname=>nil}>

How to take result like this.

# => #<EmpEntity:15940 id=1 age=18 name={:firstname=>'foo', :lastname=>'bar', :nickname=>'foobar'}>

and dot't use entity's using option. Because my app's result is not appropriate new entity.

1 Answers1

1

i think firstname and lastname are nil because your entity don't know how to get them from hash, you could add a lambda to check if the represented instance is a hash or not to determine how you return value

class EmpEntity < Grape::Entity
  expose :id
  expose :age
  expose :name do
    expose :firstname, proc: lambda {|instance, options| 
      if instance.is_a? Hash
       instance[:name][:firstname]
      else
       instance.firstname
      end
    } 
    expose :lastname, proc: lambda {|instance, options| 
      # same as above
    } 
    expose :nickname, proc: lambda {|instance, options| 
      # same as aboce
    } 
  end
end

update a general version

class HashEntity < Grape::Entity
  class << self
    def hash_keys
      @hash_keys ||= []
    end

    def expose_hash(key)
      hash_keys << key
      if block_given?
        expose key do
          yield
        end
      else
        keys = hash_keys.dup
        expose key, proc: lambda { |instance, _|
         instance.dig(*keys)
        }
      end
      hash_keys.pop
    end
  end
end

demo

class InfoEntity < HashEntity
  expose :id
  expose_hash :name do
   expose_hash :first_name
   expose_hash :last_name
  end
end


Lam Phan
  • 3,405
  • 2
  • 9
  • 20
  • It's a lot of trouble. This feature is add common response result with all APIs. Like this { "code": 1, "message": "Success", "data": This is my Enitity Content, "time": "" } I want add base entity class and other entity inheritance this. In child entity add Code expose :data do XXX end – doraemon0711 Jul 29 '21 at 06:34