ruby-grape / grape-entity

An API focused facade that sits on top of an object model.
MIT License
721 stars 153 forks source link

Duplicated output using extracted entity class #68

Open sardaukar opened 10 years ago

sardaukar commented 10 years ago

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 commented 10 years ago

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