/
responder.rb
98 lines (82 loc) · 2.95 KB
/
responder.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
module Sinatra
module Hat
# The responder assigns data to instance variables, then either
# gets the appropriate response proc and instance_exec's it in the
# context of a new Response object, or serializes the data.
class Responder
delegate :model, :to => :maker
attr_reader :maker
def initialize(maker)
@maker = maker
end
def defaults
@defaults ||= {
:show => {
:success => proc { |data| render(:show) },
:failure => proc { |data| redirect('/') }
},
:index => {
:success => proc { |data| render(:index) },
:failure => proc { |data| redirect('/') }
},
:create => {
:success => proc { |data| redirect(data) },
:failure => proc { |data| render(:new) }
},
:new => {
:success => proc { |data| render(:new) },
:failure => proc { |data| redirect('/') }
},
:edit => {
:success => proc { |data| render(:edit) }
},
:destroy => {
:success => proc { |data| redirect(resource_path('/')) }
},
:update => {
:success => proc { |data| redirect(data) },
:failure => proc { |data| render(:edit) }
}
}
end
# Called when a request is handled successfully. For most GET
# requests, this is always the case. For update/create actions,
# it is when the record is created/updated successfully.
def success(name, request, data)
handle(:success, name, request, data)
end
# Called when a request is not able to handled. This could be
# because a record could not be created or saved.
def failure(name, request, data)
handle(:failure, name, request, data)
end
# Serializes the data passed in, first looking for a custom formatter,
# then falling back on trying to call to_[format] on the data. If neither
# are available, returns an error with the status code 406.
def serialize(request, data)
name = request.params[:format].to_sym
formatter = to_format(name)
formatter[data] || request.error(406)
end
private
def handle(result, name, request, data)
if format = request.params[:format]
serialize(request, data)
else
request.instance_variable_set(ivar_name(data), data)
response = Response.new(maker, request)
response.instance_exec(data, &defaults[name][result])
end
end
def ivar_name(data)
"@" + (data.respond_to?(:each) ? model.plural : model.singular)
end
def to_format(name)
maker.formats[name] || Proc.new do |data|
method_name = "to_#{name}"
data.respond_to?(method_name) ? data.send(method_name) : nil
end
end
end
end
end