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

Feature request: Expose a Hash merged to the root, not as a sub key #138

Closed
elado opened this issue Jul 9, 2015 · 7 comments · Fixed by #204
Closed

Feature request: Expose a Hash merged to the root, not as a sub key #138

elado opened this issue Jul 9, 2015 · 7 comments · Fixed by #204
Labels

Comments

@elado
Copy link

elado commented Jul 9, 2015

I'd like to be able to append an arbitrary hash to the final result of the entity, without nesting it.

There are a couple of ways I can think of:

class ArticleEntity < Grape::Entity
   expose :title

   # example 1 - most flexible, merge output with this hash
   expose_on_root do |object, options|
      {
         key: "value",
         key_2: object.something
      }
   end

   # example 2: include another entity without nesting it in the result hash
   expose_on_root using: LikeableEntity

   # which is a shortcut for:
   expose_on_root do |object, options|
      LikeableEntity.represent(object, options).as_json
   end
end

class LikeableEntity < Grape::Entity
   expose :like_count
   expose :likers, using: UserEntity
end

ArticleEntity.represent(article).as_json
# => { title: ..., key: ..., key_2: ..., like_count: ..., likers: [...] }

Thoughts?

@dblock
Copy link
Member

dblock commented Jul 9, 2015

For the first part of the example my initial reaction is, why isn't this just expose :key and expose :key_2, what's the purpose of group-nesting? The second one with LikeableEntity makes more sense. But something tells me I would want to include LikeableEntity and get all its exposures (it's a class, so we can't do that though).

Maybe I just don't love the name, and it could be as simple as expose ..., nested: false?

I think expose self using: :LikeableEntity should work without any DSL changes (self can be omitted), it never makes sense to expose your own object as a nested thing IHMO.

@dblock dblock added the feature label Jul 9, 2015
@elado
Copy link
Author

elado commented Jul 9, 2015

why isn't this just expose :key and expose :key_2

because you can return any hash that would be merged to root, not just a specified set of keys.

Let's say that only for admins I want to expose a few unknown properties on the root. If I don't know them in advance, I can't use expose. However, with expose_on_root I can just return any hash.

It helps when the model is normalized and the JSON is denormalized.

I wrote a 🐒 monkey patch

module Grape
  class Entity
    def self.exposures_on_root
      return @exposures_on_root unless @exposures_on_root.nil?

      @exposures_on_root = []

      if superclass.respond_to? :exposures_on_root
        @exposures_on_root = superclass.exposures_on_root + @exposures_on_root
      end

      @exposures_on_root
    end

    def self.expose_on_root(options={}, &block)
      options[:proc] = block if block_given?
      exposures_on_root << options
    end

    alias_method :as_json_old, :as_json
    alias_method :serializable_hash_old, :serializable_hash

    def serializable_hash(runtime_options = {})
      output = serializable_hash_old(runtime_options)

      self.class.exposures_on_root.each do |exposure_on_root|
        partial_output = instance_exec(object, options, &exposure_on_root[:proc])
        output.reverse_merge!(partial_output)
      end

      output
    end

    alias_method :as_json, :serializable_hash
  end
end

class ArticleEntity < Grape::Entity
  # ...
  expose_on_root do |object, options|
     if options[:admin]
       object.admin_metadata.merge(some_other_key: object.something_else.some_other_key)
     end
  end
end

@elado
Copy link
Author

elado commented Jul 9, 2015

In Rabl it's called glue https://github.com/nesquena/rabl#gluing-attributes

@dblock
Copy link
Member

dblock commented Jul 9, 2015

As much as I like glue, what do you think about my suggestion of using a nested: false option? Just brainstorming for now. Or maybe merge?

@elado
Copy link
Author

elado commented Jul 9, 2015

I like merge.

sagebomb added a commit to sagebomb/grape-entity that referenced this issue Jan 28, 2016
sagebomb added a commit to sagebomb/grape-entity that referenced this issue Jan 28, 2016
sagebomb added a commit to sagebomb/grape-entity that referenced this issue Jan 28, 2016
sagebomb added a commit to sagebomb/grape-entity that referenced this issue Jan 28, 2016
@dblock
Copy link
Member

dblock commented Jan 28, 2016

Please check out #204 - add your 👍 or/and comment.

@elado
Copy link
Author

elado commented Jan 28, 2016

@dblock thanks! I've been on the dark side of Node for a while now but it seems great.

sagebomb added a commit to sagebomb/grape-entity that referenced this issue Jan 29, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
2 participants