@@ -10,10 +10,11 @@ module Grape
1010 # module API
1111 # module Entities
1212 # class User < Grape::Endpoint
13- # expose :name , :screen_name, :location
13+ # expose :first_name, :last_name , :screen_name, :location
1414 # expose :latest_status, :using => API::Status, :as => :status, :unless => {:collection => true}
1515 # expose :email, :if => {:type => :full}
1616 # expose :new_attribute, :if => {:version => 'v2'}
17+ # expose(:name){|model,options| [model.first_name, model.last_name].join(' ')}
1718 # end
1819 # end
1920 # end
@@ -57,13 +58,21 @@ class Entity
5758 # automatically be transformed into a representation that will receive the same
5859 # options as the parent entity when called. Note that arrays are fine here and
5960 # will automatically be detected and handled appropriately.
60- def self . expose ( *args )
61+ # @option options :proc If you pass a Proc into this option, it will
62+ # be used directly to determine the value for that attribute. It
63+ # will be called with the represented object as well as the
64+ # runtime options that were passed in. You can also just supply a
65+ # block to the expose call to achieve the same effect.
66+ def self . expose ( *args , &block )
6167 options = args . last . is_a? ( Hash ) ? args . pop : { }
6268
63- if options [ :as ] && args . size > 1
64- raise ArgumentError , "You may not use the :as option on multi-attribute exposures."
69+ if args . size > 1
70+ raise ArgumentError , "You may not use the :as option on multi-attribute exposures." if options [ :as ]
71+ raise ArgumentError , "You may not use block-setting on multi-attribute exposures." if block_given?
6572 end
6673
74+ options [ :proc ] = block if block_given?
75+
6776 args . each do |attribute |
6877 exposures [ attribute . to_sym ] = options
6978 end
@@ -108,9 +117,10 @@ def exposures
108117 # @param options [Hash] Any options you pass in here will be known to the entity
109118 # representation, this is where you can trigger things from conditional options
110119 # etc.
111- def serializable_hash ( options = { } )
120+ def serializable_hash ( runtime_options = { } )
121+ opts = options . merge ( runtime_options )
112122 exposures . inject ( { } ) do |output , ( attribute , exposure_options ) |
113- output [ key_for ( attribute ) ] = value_for ( attribute ) if conditions_met? ( exposure_options , options )
123+ output [ key_for ( attribute ) ] = value_for ( attribute , opts ) if conditions_met? ( exposure_options , opts )
114124 output
115125 end
116126 end
@@ -123,10 +133,12 @@ def key_for(attribute)
123133 exposures [ attribute . to_sym ] [ :as ] || attribute . to_sym
124134 end
125135
126- def value_for ( attribute )
136+ def value_for ( attribute , options = { } )
127137 exposure_options = exposures [ attribute . to_sym ]
128138
129- if exposure_options [ :using ]
139+ if exposure_options [ :proc ]
140+ exposure_options [ :proc ] . call ( object , options )
141+ elsif exposure_options [ :using ]
130142 exposure_options [ :using ] . represent ( object . send ( attribute ) )
131143 else
132144 object . send ( attribute )
0 commit comments