Skip to content

Commit 6935c4a

Browse files
author
Michael Bleigh
committed
Adds .represent method to allow for default entity representations.
1 parent f39d4de commit 6935c4a

File tree

4 files changed

+74
-4
lines changed

4 files changed

+74
-4
lines changed

lib/grape/api.rb

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,7 @@ def settings_stack
4343
@settings
4444
end
4545

46-
# Set a configuration value for this
47-
# namespace.
46+
# Set a configuration value for this namespace.
4847
#
4948
# @param key [Symbol] The key of the configuration variable.
5049
# @param value [Object] The value to which to set the configuration variable.
@@ -146,6 +145,31 @@ def rescue_from(*args, &block)
146145
add(:rescued_errors, args)
147146
end
148147

148+
# Allows you to specify a default representation entity for a
149+
# class. This allows you to map your models to their respective
150+
# entities once and then simply call `present` with the model.
151+
#
152+
# @example
153+
# class ExampleAPI < Grape::API
154+
# represent User, :with => Entity::User
155+
#
156+
# get '/me' do
157+
# present current_user # :with => Entity::User is assumed
158+
# end
159+
# end
160+
#
161+
# Note that Grape will automatically go up the class ancestry to
162+
# try to find a representing entity, so if you, for example, define
163+
# an entity to represent `Object` then all presented objects will
164+
# bubble up and utilize the entity provided on that `represent` call.
165+
#
166+
# @param model_class [Class] The model class that will be represented.
167+
# @option options [Class] :with The entity class that will represent the model.
168+
def represent(model_class, options)
169+
raise ArgumentError, "You must specify an entity class in the :with option." unless options[:with] && options[:with].is_a?(Class)
170+
add(:representations, model_class => options[:with])
171+
end
172+
149173
# Add helper methods that will be accessible from any
150174
# endpoint within this namespace (and child namespaces).
151175
#
@@ -352,8 +376,13 @@ def build_endpoint(&block)
352376

353377
befores = aggregate_setting(:befores)
354378
afters = aggregate_setting(:afters)
379+
representations = settings[:representations] || {}
355380

356-
endpoint = Grape::Endpoint.generate({:befores => befores, :afters => afters}, &block)
381+
endpoint = Grape::Endpoint.generate({
382+
:befores => befores,
383+
:afters => afters,
384+
:representations => representations
385+
}, &block)
357386
endpoint.send :include, helpers
358387
b.run endpoint
359388

lib/grape/endpoint.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ def body(value = nil)
108108
def present(object, options = {})
109109
entity_class = options.delete(:with)
110110

111+
object.class.ancestors.each do |potential|
112+
entity_class ||= self.class.options[:representations][potential]
113+
end
114+
111115
if entity_class
112116
embeds = {:env => env}
113117
embeds[:version] = env['api.version'] if env['api.version']

spec/grape/api_spec.rb

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,18 @@ def app; subject end
100100
end
101101

102102
end
103-
103+
104+
describe '.represent' do
105+
it 'should require a :with option' do
106+
expect{ subject.represent Object, {} }.to raise_error(ArgumentError)
107+
end
108+
109+
it 'should add the association to the :representations setting' do
110+
subject.represent Object, :with => BasicObject
111+
subject.settings[:representations][Object].should == BasicObject
112+
end
113+
end
114+
104115
describe '.namespace' do
105116
it 'should be retrievable and converted to a path' do
106117
subject.namespace :awesome do

spec/grape/endpoint_spec.rb

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,32 @@ def memoized
137137
end
138138
get '/example'
139139
end
140+
141+
it 'should pull a representation from the class options if it exists' do
142+
entity = Class.new(Grape::Entity)
143+
entity.stub!(:represent).and_return("Hiya")
144+
145+
subject.represent Object, :with => entity
146+
subject.get '/example' do
147+
present Object.new
148+
end
149+
get '/example'
150+
last_response.body.should == 'Hiya'
151+
end
152+
153+
it 'should pull a representation from the class ancestor if it exists' do
154+
entity = Class.new(Grape::Entity)
155+
entity.stub!(:represent).and_return("Hiya")
156+
157+
subclass = Class.new(Object)
158+
159+
subject.represent Object, :with => entity
160+
subject.get '/example' do
161+
present subclass.new
162+
end
163+
get '/example'
164+
last_response.body.should == 'Hiya'
165+
end
140166
end
141167

142168
context 'filters' do

0 commit comments

Comments
 (0)