josevalim-inherited_resources 0.8.5 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +231 -220
- data/Rakefile +2 -0
- data/VERSION +1 -1
- data/lib/inherited_resources.rb +7 -2
- data/lib/inherited_resources/actions.rb +17 -39
- data/lib/inherited_resources/base.rb +3 -0
- data/lib/inherited_resources/base_helpers.rb +25 -35
- data/lib/inherited_resources/class_methods.rb +7 -6
- data/lib/inherited_resources/legacy/respond_to.rb +151 -0
- data/lib/inherited_resources/legacy/responder.rb +181 -0
- data/lib/inherited_resources/polymorphic_helpers.rb +3 -4
- data/test/aliases_test.rb +23 -18
- data/test/base_helpers_test.rb +7 -0
- data/test/base_test.rb +5 -5
- data/test/flash_test.rb +10 -5
- data/test/redirect_to_test.rb +0 -26
- data/test/respond_to_test.rb +29 -188
- data/test/test_helper.rb +4 -1
- metadata +4 -3
- data/lib/inherited_resources/respond_to.rb +0 -339
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.9.0
|
data/lib/inherited_resources.rb
CHANGED
@@ -1,9 +1,14 @@
|
|
1
1
|
# respond_to is the only file that should be loaded before hand. All others
|
2
2
|
# are loaded on demand.
|
3
3
|
#
|
4
|
-
|
4
|
+
unless defined?(ActionController::Responder)
|
5
|
+
require File.join(File.dirname(__FILE__), 'inherited_resources', 'legacy', 'responder')
|
6
|
+
require File.join(File.dirname(__FILE__), 'inherited_resources', 'legacy', 'respond_to')
|
7
|
+
end
|
5
8
|
|
6
|
-
module InheritedResources
|
9
|
+
module InheritedResources
|
10
|
+
ACTIONS = [ :index, :show, :new, :edit, :create, :update, :destroy ] unless self.const_defined?(:ACTIONS)
|
11
|
+
end
|
7
12
|
|
8
13
|
class ActionController::Base
|
9
14
|
# If you cannot inherit from InheritedResources::Base you can call
|
@@ -1,91 +1,69 @@
|
|
1
1
|
module InheritedResources
|
2
|
-
RESOURCES_ACTIONS = [ :index, :show, :new, :edit, :create, :update, :destroy ] unless self.const_defined?(:RESOURCES_ACTIONS)
|
3
|
-
|
4
2
|
# Holds all default actions for InheritedResouces.
|
5
3
|
module Actions
|
6
4
|
|
7
5
|
# GET /resources
|
8
6
|
def index(&block)
|
9
|
-
|
7
|
+
respond_with(collection, &block)
|
10
8
|
end
|
11
9
|
alias :index! :index
|
12
10
|
|
13
11
|
# GET /resources/1
|
14
12
|
def show(&block)
|
15
|
-
|
13
|
+
respond_with(resource, &block)
|
16
14
|
end
|
17
15
|
alias :show! :show
|
18
16
|
|
19
17
|
# GET /resources/new
|
20
18
|
def new(&block)
|
21
|
-
|
19
|
+
respond_with(build_resource, &block)
|
22
20
|
end
|
23
21
|
alias :new! :new
|
24
22
|
|
25
23
|
# GET /resources/1/edit
|
26
24
|
def edit(&block)
|
27
|
-
|
25
|
+
respond_with(resource, &block)
|
28
26
|
end
|
29
27
|
alias :edit! :edit
|
30
28
|
|
31
29
|
# POST /resources
|
32
|
-
def create(&block)
|
30
|
+
def create(options={}, &block)
|
33
31
|
object = build_resource
|
34
|
-
respond_block, redirect_block = select_block_by_arity(block)
|
35
32
|
|
36
33
|
if object.save
|
37
34
|
set_flash_message!(:notice, '{{resource_name}} was successfully created.')
|
38
|
-
options
|
39
|
-
|
40
|
-
respond_to_with_dual_blocks(true, respond_block, options) do |format|
|
41
|
-
format.html { redirect_to(redirect_block ? redirect_block.call : resource_url) }
|
42
|
-
end
|
35
|
+
options[:location] ||= resource_url rescue nil
|
36
|
+
respond_with_dual_blocks(object, options, true, block)
|
43
37
|
else
|
44
38
|
set_flash_message!(:error)
|
45
|
-
|
46
|
-
|
47
|
-
respond_to_with_dual_blocks(false, respond_block, options) do |format|
|
48
|
-
format.html { render :action => 'new' }
|
49
|
-
end
|
39
|
+
respond_with_dual_blocks(object, options, false, block)
|
50
40
|
end
|
51
41
|
end
|
52
42
|
alias :create! :create
|
53
43
|
|
54
44
|
# PUT /resources/1
|
55
|
-
def update(&block)
|
45
|
+
def update(options={}, &block)
|
56
46
|
object = resource
|
57
|
-
respond_block, redirect_block = select_block_by_arity(block)
|
58
47
|
|
59
48
|
if object.update_attributes(params[resource_instance_name])
|
60
49
|
set_flash_message!(:notice, '{{resource_name}} was successfully updated.')
|
61
|
-
|
62
|
-
|
63
|
-
format.html { redirect_to(redirect_block ? redirect_block.call : resource_url) }
|
64
|
-
format.all { head :ok }
|
65
|
-
end
|
50
|
+
options[:location] ||= resource_url rescue nil
|
51
|
+
respond_with_dual_blocks(object, options, true, block)
|
66
52
|
else
|
67
53
|
set_flash_message!(:error)
|
68
|
-
|
69
|
-
options = { :with => object.errors, :status => :unprocessable_entity }
|
70
|
-
|
71
|
-
respond_to_with_dual_blocks(false, block, options) do |format|
|
72
|
-
format.html { render :action => 'edit' }
|
73
|
-
end
|
54
|
+
respond_with_dual_blocks(object, options, false, block)
|
74
55
|
end
|
75
56
|
end
|
76
57
|
alias :update! :update
|
77
58
|
|
78
59
|
# DELETE /resources/1
|
79
|
-
def destroy(&block)
|
80
|
-
resource
|
81
|
-
|
60
|
+
def destroy(options={}, &block)
|
61
|
+
object = resource
|
62
|
+
object.destroy
|
82
63
|
|
83
64
|
set_flash_message!(:notice, '{{resource_name}} was successfully destroyed.')
|
84
|
-
|
85
|
-
|
86
|
-
format.html { redirect_to(redirect_block ? redirect_block.call : collection_url) }
|
87
|
-
format.all { head :ok }
|
88
|
-
end
|
65
|
+
options[:location] ||= collection_url rescue nil
|
66
|
+
respond_with_dual_blocks(object, options, nil, block)
|
89
67
|
end
|
90
68
|
alias :destroy! :destroy
|
91
69
|
|
@@ -20,6 +20,9 @@ module InheritedResources
|
|
20
20
|
extend InheritedResources::ClassMethods
|
21
21
|
extend InheritedResources::UrlHelpers
|
22
22
|
|
23
|
+
# Add at least :html mime type
|
24
|
+
respond_to :html
|
25
|
+
|
23
26
|
helper_method :collection_url, :collection_path, :resource_url, :resource_path,
|
24
27
|
:new_resource_url, :new_resource_path, :edit_resource_url, :edit_resource_path,
|
25
28
|
:resource, :collection, :resource_class
|
@@ -46,7 +46,7 @@ module InheritedResources
|
|
46
46
|
# instance variable.
|
47
47
|
#
|
48
48
|
def build_resource
|
49
|
-
get_resource_ivar || set_resource_ivar(end_of_association_chain.send(method_for_build, params[resource_instance_name]))
|
49
|
+
get_resource_ivar || set_resource_ivar(end_of_association_chain.send(method_for_build, params[resource_instance_name] || {}))
|
50
50
|
end
|
51
51
|
|
52
52
|
# This class allows you to set a instance variable to begin your
|
@@ -271,26 +271,34 @@ module InheritedResources
|
|
271
271
|
# end
|
272
272
|
# end
|
273
273
|
#
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
274
|
+
# It also calculates the response url in case a block without arity is
|
275
|
+
# given and returns it. Otherwise returns nil.
|
276
|
+
#
|
277
|
+
def respond_with_dual_blocks(object, options, success, given_block, &block) #:nodoc:
|
278
|
+
case given_block.try(:arity)
|
279
|
+
when 2
|
280
|
+
respond_with(object, options) do |responder|
|
281
|
+
dumb_responder = InheritedResources::DumbResponder.new
|
282
|
+
if success
|
283
|
+
given_block.call(responder, dumb_responder)
|
284
|
+
else
|
285
|
+
given_block.call(dumb_responder, responder)
|
286
|
+
end
|
287
|
+
block.try(:call, responder)
|
288
|
+
end
|
289
|
+
when 1
|
290
|
+
if block
|
291
|
+
respond_with(object, options) do |responder|
|
292
|
+
given_block.call(responder)
|
293
|
+
block.call(responder)
|
294
|
+
end
|
282
295
|
else
|
283
|
-
|
296
|
+
respond_with(object, options, &given_block)
|
284
297
|
end
|
285
298
|
else
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
# Try to respond with the block given
|
290
|
-
responder.respond_except_any
|
299
|
+
options[:location] = given_block.call if given_block
|
300
|
+
respond_with(object, options, &block)
|
291
301
|
end
|
292
|
-
|
293
|
-
respond_to(options.merge!(:responder => responder, :prioritize => :html), &block) unless performed?
|
294
302
|
end
|
295
303
|
|
296
304
|
# Hook to apply scopes. By default returns only the target_object given.
|
@@ -307,23 +315,5 @@ module InheritedResources
|
|
307
315
|
[]
|
308
316
|
end
|
309
317
|
|
310
|
-
# Holds InheritedResources block structure. It returns two blocks: the first
|
311
|
-
# is used in respond_to blocks and the second is the redirect_to url.
|
312
|
-
#
|
313
|
-
def select_block_by_arity(block) #:nodoc
|
314
|
-
if block
|
315
|
-
case block.arity
|
316
|
-
when 2, 1
|
317
|
-
[block, nil]
|
318
|
-
when 0, -1
|
319
|
-
[nil, block]
|
320
|
-
else
|
321
|
-
raise ScriptError, "InheritedResources does not know how to handle blocks with arity #{block.arity}"
|
322
|
-
end
|
323
|
-
else
|
324
|
-
[nil, nil]
|
325
|
-
end
|
326
|
-
end
|
327
|
-
|
328
318
|
end
|
329
319
|
end
|
@@ -68,7 +68,7 @@ module InheritedResources
|
|
68
68
|
actions_to_remove = Array(options[:except])
|
69
69
|
actions_to_remove.map!{ |a| a.to_s }
|
70
70
|
|
71
|
-
actions_to_remove +=
|
71
|
+
actions_to_remove += ACTIONS.map{ |a| a.to_s } - actions_to_keep unless actions_to_keep.first == 'all'
|
72
72
|
actions_to_remove.uniq!
|
73
73
|
|
74
74
|
(instance_methods & actions_to_remove).each do |action|
|
@@ -108,18 +108,18 @@ module InheritedResources
|
|
108
108
|
#
|
109
109
|
# == Options
|
110
110
|
#
|
111
|
-
# * <tt>:boolean</tt> - When set to true, call the scope only when the
|
111
|
+
# * <tt>:boolean</tt> - When set to true, call the scope only when the param is true or 1,
|
112
112
|
# and does not send the value as argument.
|
113
113
|
#
|
114
|
-
# * <tt>:only</tt> - In
|
114
|
+
# * <tt>:only</tt> - In which actions the scope is applied. By default is :all.
|
115
115
|
#
|
116
|
-
# * <tt>:except</tt> - In
|
116
|
+
# * <tt>:except</tt> - In which actions the scope is not applied. By default is :none.
|
117
117
|
#
|
118
118
|
# * <tt>:key</tt> - The key in the params hash expected to find the scope.
|
119
119
|
# Defaults to the scope name.
|
120
120
|
#
|
121
121
|
# * <tt>:default</tt> - Default value for the scope. Whenever supplied the scope
|
122
|
-
# is always called. This is useful to add easy pagination
|
122
|
+
# is always called. This is useful to add easy pagination.
|
123
123
|
#
|
124
124
|
def has_scope(*scopes)
|
125
125
|
options = scopes.extract_options!
|
@@ -208,6 +208,7 @@ module InheritedResources
|
|
208
208
|
optional = options.delete(:optional)
|
209
209
|
singleton = options.delete(:singleton)
|
210
210
|
polymorphic = options.delete(:polymorphic)
|
211
|
+
finder = options.delete(:finder)
|
211
212
|
|
212
213
|
include BelongsToHelpers if self.parents_symbols.empty?
|
213
214
|
|
@@ -234,8 +235,8 @@ module InheritedResources
|
|
234
235
|
config[:collection_name] = options.delete(:collection_name) || symbol.to_s.pluralize.to_sym
|
235
236
|
config[:instance_name] = options.delete(:instance_name) || symbol
|
236
237
|
config[:param] = options.delete(:param) || :"#{symbol}_id"
|
237
|
-
config[:finder] = options.delete(:finder) || :find
|
238
238
|
config[:route_name] = options.delete(:route_name) || symbol
|
239
|
+
config[:finder] = finder || :find
|
239
240
|
end
|
240
241
|
|
241
242
|
if block_given?
|
@@ -0,0 +1,151 @@
|
|
1
|
+
module ActionController #:nodoc:
|
2
|
+
class Base #:nodoc:
|
3
|
+
attr_accessor :formats
|
4
|
+
|
5
|
+
# Defines mimes that are rendered by default when invoking respond_with.
|
6
|
+
#
|
7
|
+
# Examples:
|
8
|
+
#
|
9
|
+
# respond_to :html, :xml, :json
|
10
|
+
#
|
11
|
+
# All actions on your controller will respond to :html, :xml and :json.
|
12
|
+
#
|
13
|
+
# But if you want to specify it based on your actions, you can use only and
|
14
|
+
# except:
|
15
|
+
#
|
16
|
+
# respond_to :html
|
17
|
+
# respond_to :xml, :json, :except => [ :edit ]
|
18
|
+
#
|
19
|
+
# The definition above explicits that all actions respond to :html. And all
|
20
|
+
# actions except :edit respond to :xml and :json.
|
21
|
+
#
|
22
|
+
# You can specify also only parameters:
|
23
|
+
#
|
24
|
+
# respond_to :rjs, :only => :create
|
25
|
+
#
|
26
|
+
def self.respond_to(*mimes)
|
27
|
+
options = mimes.extract_options!
|
28
|
+
|
29
|
+
only_actions = Array(options.delete(:only))
|
30
|
+
except_actions = Array(options.delete(:except))
|
31
|
+
|
32
|
+
mimes.each do |mime|
|
33
|
+
mime = mime.to_sym
|
34
|
+
mimes_for_respond_to[mime] = {}
|
35
|
+
mimes_for_respond_to[mime][:only] = only_actions unless only_actions.empty?
|
36
|
+
mimes_for_respond_to[mime][:except] = except_actions unless except_actions.empty?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Clear all mimes in respond_to.
|
41
|
+
#
|
42
|
+
def self.clear_respond_to
|
43
|
+
write_inheritable_attribute(:mimes_for_respond_to, ActiveSupport::OrderedHash.new)
|
44
|
+
end
|
45
|
+
|
46
|
+
class_inheritable_reader :mimes_for_respond_to
|
47
|
+
clear_respond_to
|
48
|
+
|
49
|
+
# If ApplicationController is already defined around here, we have to set
|
50
|
+
# mimes_for_respond_to hash as well.
|
51
|
+
#
|
52
|
+
ApplicationController.clear_respond_to if defined?(ApplicationController)
|
53
|
+
|
54
|
+
def respond_to(*mimes, &block)
|
55
|
+
raise ArgumentError, "respond_to takes either types or a block, never both" if mimes.any? && block_given?
|
56
|
+
|
57
|
+
responder = ActionController::MimeResponds::Responder.new(self)
|
58
|
+
mimes = collect_mimes_from_class_level if mimes.empty?
|
59
|
+
mimes.each { |mime| responder.send(mime) }
|
60
|
+
block.call(responder) if block_given?
|
61
|
+
|
62
|
+
if format = responder.negotiate_mime
|
63
|
+
self.response.template.template_format = format.to_sym
|
64
|
+
self.response.content_type = format.to_s
|
65
|
+
self.formats = [ format.to_sym ]
|
66
|
+
|
67
|
+
if response = responder.response_for(format)
|
68
|
+
response.call
|
69
|
+
else
|
70
|
+
default_render
|
71
|
+
end
|
72
|
+
else
|
73
|
+
head :not_acceptable
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def respond_with(*resources, &block)
|
78
|
+
respond_to(&block)
|
79
|
+
rescue ActionView::MissingTemplate
|
80
|
+
options = resources.extract_options!
|
81
|
+
(options.delete(:responder) || responder).call(self, resources, options)
|
82
|
+
end
|
83
|
+
|
84
|
+
def responder
|
85
|
+
ActionController::Responder
|
86
|
+
end
|
87
|
+
|
88
|
+
protected
|
89
|
+
|
90
|
+
# Collect mimes declared in the class method respond_to valid for the
|
91
|
+
# current action.
|
92
|
+
#
|
93
|
+
def collect_mimes_from_class_level #:nodoc:
|
94
|
+
action = action_name.to_sym
|
95
|
+
|
96
|
+
mimes_for_respond_to.keys.select do |mime|
|
97
|
+
config = mimes_for_respond_to[mime]
|
98
|
+
|
99
|
+
if config[:except]
|
100
|
+
!config[:except].include?(action)
|
101
|
+
elsif config[:only]
|
102
|
+
config[:only].include?(action)
|
103
|
+
else
|
104
|
+
true
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
module MimeResponds
|
111
|
+
class Responder #:nodoc:
|
112
|
+
attr_reader :order
|
113
|
+
|
114
|
+
def any(*args, &block)
|
115
|
+
if args.any?
|
116
|
+
args.each { |type| send(type, &block) }
|
117
|
+
else
|
118
|
+
custom(Mime::ALL, &block)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
alias :all :any
|
122
|
+
|
123
|
+
def custom(mime_type, &block)
|
124
|
+
mime_type = mime_type.is_a?(Mime::Type) ? mime_type : Mime::Type.lookup(mime_type.to_s)
|
125
|
+
@order << mime_type
|
126
|
+
@responses[mime_type] ||= block
|
127
|
+
end
|
128
|
+
|
129
|
+
def response_for(mime)
|
130
|
+
@responses[mime] || @responses[Mime::ALL]
|
131
|
+
end
|
132
|
+
|
133
|
+
def negotiate_mime
|
134
|
+
@mime_type_priority.each do |priority|
|
135
|
+
if priority == Mime::ALL
|
136
|
+
return @order.first
|
137
|
+
elsif @order.include?(priority)
|
138
|
+
return priority
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
if @order.include?(Mime::ALL)
|
143
|
+
return Mime::SET.first if @mime_type_priority.first == Mime::ALL
|
144
|
+
return @mime_type_priority.first
|
145
|
+
end
|
146
|
+
|
147
|
+
nil
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
module ActionController #:nodoc:
|
2
|
+
# Responder is responsible to expose a resource for different mime requests,
|
3
|
+
# usually depending on the HTTP verb. The responder is triggered when
|
4
|
+
# respond_with is called. The simplest case to study is a GET request:
|
5
|
+
#
|
6
|
+
# class PeopleController < ApplicationController
|
7
|
+
# respond_to :html, :xml, :json
|
8
|
+
#
|
9
|
+
# def index
|
10
|
+
# @people = Person.find(:all)
|
11
|
+
# respond_with(@people)
|
12
|
+
# end
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# When a request comes, for example with format :xml, three steps happen:
|
16
|
+
#
|
17
|
+
# 1) respond_with searches for a template at people/index.xml;
|
18
|
+
#
|
19
|
+
# 2) if the template is not available, it will create a responder, passing
|
20
|
+
# the controller and the resource and invoke :to_xml on it;
|
21
|
+
#
|
22
|
+
# 3) if the responder does not respond_to :to_xml, call to_format on it.
|
23
|
+
#
|
24
|
+
# === Builtin HTTP verb semantics
|
25
|
+
#
|
26
|
+
# Rails default responder holds semantics for each HTTP verb. Depending on the
|
27
|
+
# content type, verb and the resource status, it will behave differently.
|
28
|
+
#
|
29
|
+
# Using Rails default responder, a POST request for creating an object could
|
30
|
+
# be written as:
|
31
|
+
#
|
32
|
+
# def create
|
33
|
+
# @user = User.new(params[:user])
|
34
|
+
# flash[:notice] = 'User was successfully created.' if @user.save
|
35
|
+
# respond_with(@user)
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# Which is exactly the same as:
|
39
|
+
#
|
40
|
+
# def create
|
41
|
+
# @user = User.new(params[:user])
|
42
|
+
#
|
43
|
+
# respond_to do |format|
|
44
|
+
# if @user.save
|
45
|
+
# flash[:notice] = 'User was successfully created.'
|
46
|
+
# format.html { redirect_to(@user) }
|
47
|
+
# format.xml { render :xml => @user, :status => :created, :location => @user }
|
48
|
+
# else
|
49
|
+
# format.html { render :action => "new" }
|
50
|
+
# format.xml { render :xml => @user.errors, :status => :unprocessable_entity }
|
51
|
+
# end
|
52
|
+
# end
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# The same happens for PUT and DELETE requests.
|
56
|
+
#
|
57
|
+
# === Nested resources
|
58
|
+
#
|
59
|
+
# You can given nested resource as you do in form_for and polymorphic_url.
|
60
|
+
# Consider the project has many tasks example. The create action for
|
61
|
+
# TasksController would be like:
|
62
|
+
#
|
63
|
+
# def create
|
64
|
+
# @project = Project.find(params[:project_id])
|
65
|
+
# @task = @project.comments.build(params[:task])
|
66
|
+
# flash[:notice] = 'Task was successfully created.' if @task.save
|
67
|
+
# respond_with(@project, @task)
|
68
|
+
# end
|
69
|
+
#
|
70
|
+
# Giving an array of resources, you ensure that the responder will redirect to
|
71
|
+
# project_task_url instead of task_url.
|
72
|
+
#
|
73
|
+
# Namespaced and singleton resources requires a symbol to be given, as in
|
74
|
+
# polymorphic urls. If a project has one manager which has many tasks, it
|
75
|
+
# should be invoked as:
|
76
|
+
#
|
77
|
+
# respond_with(@project, :manager, @task)
|
78
|
+
#
|
79
|
+
# Check polymorphic_url documentation for more examples.
|
80
|
+
#
|
81
|
+
class Responder
|
82
|
+
attr_reader :controller, :request, :format, :resource, :resource_location, :options
|
83
|
+
|
84
|
+
def initialize(controller, resources, options={})
|
85
|
+
@controller = controller
|
86
|
+
@request = controller.request
|
87
|
+
@format = controller.formats.first
|
88
|
+
@resource = resources.is_a?(Array) ? resources.last : resources
|
89
|
+
@resource_location = options[:location] || resources
|
90
|
+
@options = options
|
91
|
+
end
|
92
|
+
|
93
|
+
delegate :head, :render, :redirect_to, :to => :controller
|
94
|
+
delegate :get?, :post?, :put?, :delete?, :to => :request
|
95
|
+
|
96
|
+
# Undefine :to_json since it's defined on Object
|
97
|
+
undef_method :to_json
|
98
|
+
|
99
|
+
# Initializes a new responder an invoke the proper format. If the format is
|
100
|
+
# not defined, call to_format.
|
101
|
+
#
|
102
|
+
def self.call(*args)
|
103
|
+
responder = new(*args)
|
104
|
+
method = :"to_#{responder.format}"
|
105
|
+
responder.respond_to?(method) ? responder.send(method) : responder.to_format
|
106
|
+
end
|
107
|
+
|
108
|
+
# HTML format does not render the resource, it always attempt to render a
|
109
|
+
# template.
|
110
|
+
#
|
111
|
+
def to_html
|
112
|
+
if get?
|
113
|
+
render
|
114
|
+
elsif has_errors?
|
115
|
+
render :action => default_action
|
116
|
+
else
|
117
|
+
redirect_to resource_location
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# All others formats try to render the resource given instead. For this
|
122
|
+
# purpose a helper called display as a shortcut to render a resource with
|
123
|
+
# the current format.
|
124
|
+
#
|
125
|
+
def to_format
|
126
|
+
return render unless resourceful?
|
127
|
+
|
128
|
+
if get?
|
129
|
+
display resource
|
130
|
+
elsif has_errors?
|
131
|
+
display resource.errors, :status => :unprocessable_entity
|
132
|
+
elsif post?
|
133
|
+
display resource, :status => :created, :location => resource_location
|
134
|
+
else
|
135
|
+
head :ok
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
protected
|
140
|
+
|
141
|
+
# Checks whether the resource responds to the current format or not.
|
142
|
+
#
|
143
|
+
def resourceful?
|
144
|
+
resource.respond_to?(:"to_#{format}")
|
145
|
+
end
|
146
|
+
|
147
|
+
# display is just a shortcut to render a resource with the current format.
|
148
|
+
#
|
149
|
+
# display @user, :status => :ok
|
150
|
+
#
|
151
|
+
# For xml request is equivalent to:
|
152
|
+
#
|
153
|
+
# render :xml => @user, :status => :ok
|
154
|
+
#
|
155
|
+
# Options sent by the user are also used:
|
156
|
+
#
|
157
|
+
# respond_with(@user, :status => :created)
|
158
|
+
# display(@user, :status => :ok)
|
159
|
+
#
|
160
|
+
# Results in:
|
161
|
+
#
|
162
|
+
# render :xml => @user, :status => :created
|
163
|
+
#
|
164
|
+
def display(resource, given_options={})
|
165
|
+
render given_options.merge!(options).merge!(format => resource)
|
166
|
+
end
|
167
|
+
|
168
|
+
# Check if the resource has errors or not.
|
169
|
+
#
|
170
|
+
def has_errors?
|
171
|
+
resource.respond_to?(:errors) && !resource.errors.empty?
|
172
|
+
end
|
173
|
+
|
174
|
+
# By default, render the :edit action for html requests with failure, unless
|
175
|
+
# the verb is post.
|
176
|
+
#
|
177
|
+
def default_action
|
178
|
+
request.post? ? :new : :edit
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|