ruby grape entity - inheritance, the son does not contain the parent's fields

634 views Asked by At

I would expect to get json with both the name and note fields. But I only get the note field. What am I doing wrong?

class OrderPage
  module Entities
    class AsSeller < OrderPage::Entities::Order
      expose :note

      def note
        object.note
      end
    end
  end
end

class OrderPage
  module Entities
    class Order < Grape::Entity
       expose :name
    end
  end
end

 json = OrderPage::Entities::AsSeller.represent(order).as_json
2

There are 2 answers

0
Allison On

I think you should take a step back and remember that an entity is supposed to represent an object, because it doesn't really seem like that's what you're doing here. So you should have one entity representing your codebase's concept of an Order object (AsSeller sounds like a visibility restriction, not an object), and use with_options to restrict what is or is not exposed.

module Entities
  class Order < Grape::Entity
    expose :name

    with_options(if: { visibility: :seller }) do
      expose :note
    end
  end
end

order = { name: 'Relax', note: "Don't do it" }

# Standard order representation
Entities::Order.represent(order).serializable_hash
=> {:name=>"Relax"}

# Order represented with visibility: :seller
Entities::Order.represent(order, visibility: :seller).serializable_hash
=> {:name=>"Relax", :note=>"Don't do it"}

Alternatively, if it's just a matter of conditionally exposing an attribute that only exists on certain descendants of the order model, you should be able to do something like this:

expose :note, if: ->(order, _) { order.respond_to?(:note) }

If you really need to include a subset of attributes defined elsewhere, you could write a Concern and include it in another entity, but from the context available to me in your question and the naming you've used, it doesn't seem like that's a good solution here.

0
mcfoton On

Actually in your case you should receive an error on your third row

uninitialized constant OrderPage::Entities::Order

But changing the order, making class Order defined higher than class AsSeller — all looks good, the JSON is rendered with both fields.

If that doesn't help you can also try updating gem versions.