Skip to content

Commit fceab93

Browse files
author
Robert Ross
committed
Add ability to register a formatter on entity classes to be used with :format_with option.
1 parent f6cd72d commit fceab93

File tree

2 files changed

+57
-1
lines changed

2 files changed

+57
-1
lines changed

lib/grape/entity.rb

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,24 @@ def self.exposures
9393
@exposures
9494
end
9595

96+
# This allows you to declare a Proc in which exposures can be formatted with.
97+
# It take a block with an arity of 1 which is passed as the value of the exposed attribute.
98+
def self.format_with(name, &block)
99+
raise ArgumentError, "You must has a block for formatters" unless block_given?
100+
formatters[name.to_sym] = block
101+
end
102+
103+
# Returns a hash of all formatters that are registered for this and it's ancestors.
104+
def self.formatters
105+
@formatters ||= {}
106+
107+
if superclass.respond_to? :formatters
108+
@formatters = superclass.formatters.merge(@formatters)
109+
end
110+
111+
@formatters
112+
end
113+
96114
# This allows you to set a root element name for your representation.
97115
#
98116
# @param plural [String] the root key to use when representing
@@ -173,6 +191,10 @@ def exposures
173191
self.class.exposures
174192
end
175193

194+
def formatters
195+
self.class.formatters
196+
end
197+
176198
# The serializable hash is the Entity's primary output. It is the transformed
177199
# hash for the given data model and is used as the basis for serialization to
178200
# JSON and other formats.
@@ -207,7 +229,9 @@ def value_for(attribute, options = {})
207229
elsif exposure_options[:format_with]
208230
format_with = exposure_options[:format_with]
209231

210-
if format_with.is_a? Symbol
232+
if format_with.is_a?(Symbol) && formatters[format_with]
233+
formatters[format_with].call(object.send(attribute))
234+
elsif format_with.is_a?(Symbol)
211235
self.send(format_with, object.send(attribute))
212236
elsif format_with.respond_to? :call
213237
format_with.call(object.send(attribute))

spec/grape/entity_spec.rb

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,38 @@
7171
child_class.exposures[:name].should have_key :proc
7272
end
7373
end
74+
75+
context 'register formatters' do
76+
let(:date_formatter) { lambda {|date| date.strftime('%m/%d/%Y') }}
77+
78+
it 'should register a formatter' do
79+
subject.format_with :timestamp, &date_formatter
80+
81+
subject.formatters[:timestamp].should_not be_nil
82+
end
83+
84+
it 'should inherit formatters from ancestors' do
85+
subject.format_with :timestamp, &date_formatter
86+
child_class = Class.new(subject)
87+
88+
child_class.formatters.should == subject.formatters
89+
end
90+
91+
it 'should not allow registering a formatter without a block' do
92+
expect{ subject.format_with :foo }.to raise_error(ArgumentError)
93+
end
94+
95+
it 'should format an exposure with a registered formatter' do
96+
subject.format_with :timestamp do |date|
97+
date.strftime('%m/%d/%Y')
98+
end
99+
100+
subject.expose :birthday, :format_with => :timestamp
101+
102+
model = { :birthday => Time.new(2012, 2, 27) }
103+
subject.new(mock(model)).as_json[:birthday].should == '02/27/2012'
104+
end
105+
end
74106
end
75107

76108
describe '.represent' do

0 commit comments

Comments
 (0)