11require 'hashie'
22
33module Grape
4- # An Entity is a lightweight structure that allows you to easily
4+ # An Entity is a lightweight structure that allows you to easily
55 # represent data from your application in a consistent and abstracted
66 # way in your API.
77 #
@@ -19,7 +19,7 @@ module Grape
1919 # end
2020 # end
2121 #
22- # Entities are not independent structures, rather, they create
22+ # Entities are not independent structures, rather, they create
2323 # **representations** of other Ruby objects using a number of methods
2424 # that are convenient for use in an API. Once you've defined an Entity,
2525 # you can use it in your API like this:
@@ -54,7 +54,7 @@ class Entity
5454 # it will yield the object being represented and the options passed to the
5555 # representation call. Return true to prevent exposure, false to allow it.
5656 # @option options :using This option allows you to map an attribute to another Grape
57- # Entity. Pass it a Grape::Entity class and the attribute in question will
57+ # Entity. Pass it a Grape::Entity class and the attribute in question will
5858 # automatically be transformed into a representation that will receive the same
5959 # options as the parent entity when called. Note that arrays are fine here and
6060 # will automatically be detected and handled appropriately.
@@ -85,6 +85,46 @@ def self.exposures
8585 ( @exposures ||= { } )
8686 end
8787
88+ # This allows you to set a root element name for your representation.
89+ #
90+ # @param singular [String] the root key to use when representing a single object
91+ # @param plural [String] the root key to use when representing a collection of objects
92+ #
93+ # @example Entity Definition
94+ #
95+ # module API
96+ # module Entities
97+ # class User < Grape::Entity
98+ # root 'user', 'users'
99+ # expose :id
100+ # end
101+ # end
102+ # end
103+ #
104+ # @example Usage in the API Layer
105+ #
106+ # module API
107+ # class Users < Grape::API
108+ # version 'v2'
109+ #
110+ # # this will render { "users": [ {"id":"1"}, {"id":"2"} ] }
111+ # get '/users' do
112+ # @users = User.all
113+ # present @users, :with => API::Entities::User
114+ # end
115+ #
116+ # # this will render { "user": {"id":"1"} }
117+ # get '/users/:id' do
118+ # @user = User.find(params[:id])
119+ # present @user, :with => API::Entities::User
120+ # end
121+ # end
122+ # end
123+ def self . root ( singular , plural = nil )
124+ @root = singular
125+ @collection_root = plural
126+ end
127+
88128 # This convenience method allows you to instantiate one or more entities by
89129 # passing either a singular or collection of objects. Each object will be
90130 # initialized with the same options. If an array of objects is passed in,
@@ -95,11 +135,14 @@ def self.exposures
95135 # @param options [Hash] Options that will be passed through to each entity
96136 # representation.
97137 def self . represent ( objects , options = { } )
98- if objects . is_a? ( Array )
138+ inner = if objects . is_a? ( Array )
99139 objects . map { |o | self . new ( o , { :collection => true } . merge ( options ) ) }
100140 else
101141 self . new ( objects , options )
102142 end
143+
144+ root_element = objects . is_a? ( Array ) ? @collection_root : @root
145+ root_element ? { root_element => inner } : inner
103146 end
104147
105148 def initialize ( object , options = { } )
0 commit comments