grape-entity icon indicating copy to clipboard operation
grape-entity copied to clipboard

Duplicated output using extracted entity class

Open sardaukar opened this issue 10 years ago • 1 comments

Hey again :)

I'm using this inside an AR model class:

def links
    {
      self:     topic_path(self),
      publish:  publish_topic_path(self)
    }
end

And the entity associated to this model features:

expose :links, using: 'RelLinks'

The RelLinks class:

class RelLinks < Grape::Entity

  expose :links do |hash, _|
    [].tap do |arr|
      hash.each_pair do |link_k, link_v|
        arr << { rel: link_k, href: link_v }
      end
    end
  end

end

This is so that I can have a generic rel links presenter. However, my output is:

....
 "topics": [
                {
                    "id": 2,
                    "name": "Topic 2",
                    "status": "draft",
                    "created_at": "2014-04-02T13:14:05Z",
                    "updated_at": "2014-04-02T13:14:05Z",
                    "links": {
                        "links": [
                            {
                                "rel": "self",
                                "href": "/courses/1/chapter/1/topics/2"
                            },
                            {
                                "rel": "publish",
                                "href": "/courses/1/chapter/1/topics/2/publish"
                            }
                        ]
                    }
                },
                {
                    "id": 4,
                    "name": "Topic 4",
                    "status": "draft",
           ....

How can I get rid of the links/links duplication?

Thanks!

sardaukar avatar Apr 03 '14 09:04 sardaukar

Hmm, fixed this in another way. Feel free to close the issue, but would still like to know if this is possible. For future reference, I now have a BaseEntity class (since I always show ids and timestamps, useful for the links handling too):

class BaseEntity < Grape::Entity
  format_with(:iso_timestamp) { |dt| dt.iso8601 }
  expose :id
  with_options(format_with: :iso_timestamp) do
    expose :created_at
    expose :updated_at
  end
  expose :links, if: ->(obj, _) { obj.respond_to?(:links) } do |obj, _|
    obj.render_rel_links
  end
end

And model classes that feature the "links" method include this module:

module RelLinkRenderer
  def render_rel_links
    [].tap do |arr|
      self.links.each_pair do |rel,href|
        arr << { rel: rel, href: href }
      end
    end
  end
end

Contrived, but works :D

sardaukar avatar Apr 03 '14 10:04 sardaukar