josevalim-inherited_resources 0.5.2 → 0.6.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/CHANGELOG +12 -5
- data/README +13 -3
- data/lib/inherited_resources/base.rb +29 -19
- data/lib/inherited_resources/base_helpers.rb +17 -8
- data/lib/inherited_resources/respond_to.rb +26 -63
- data/test/aliases_test.rb +5 -11
- data/test/base_helpers_test.rb +5 -8
- data/test/base_test.rb +8 -11
- data/test/belongs_to_test.rb +9 -21
- data/test/class_methods_test.rb +20 -21
- data/test/defaults_test.rb +5 -4
- data/test/nested_belongs_to_test.rb +11 -41
- data/test/optional_belongs_to_test.rb +22 -48
- data/test/polymorphic_test.rb +98 -23
- data/test/redirect_to_test.rb +52 -0
- data/test/respond_to_test.rb +23 -26
- data/test/singleton_test.rb +4 -4
- data/test/test_helper.rb +0 -7
- metadata +3 -2
data/CHANGELOG
CHANGED
@@ -1,4 +1,11 @@
|
|
1
|
-
# Version 0.
|
1
|
+
# Version 0.6
|
2
|
+
|
3
|
+
* Cleaned up tests and responder structure. Whenever you pass a block to aliases
|
4
|
+
and this block responds to the request, the other blocks are not parsed improcing performance.
|
5
|
+
* [BACKWARDS INCOMPATIBLE] By default, Inherited Resources respond only :html requests
|
6
|
+
* Added a quick way to overwrite the redirect to url in :create, :update and :destroy
|
7
|
+
|
8
|
+
# Version 0.5
|
2
9
|
|
3
10
|
* Decoupled routes name from :instance_name and :collection_name. This way we
|
4
11
|
have more flexibility. Use route_instance_name and route_collection_name to
|
@@ -6,7 +13,7 @@
|
|
6
13
|
* Avoid calling human_name on nil when a resource class is not defined.
|
7
14
|
* Only call I18n if it's defined.
|
8
15
|
|
9
|
-
# Version 0.4
|
16
|
+
# Version 0.4
|
10
17
|
|
11
18
|
* Dealing with namespaced controllers out of the box.
|
12
19
|
* Added support to namespaced routes through :route_prefix.
|
@@ -24,7 +31,7 @@
|
|
24
31
|
categories/1/products/2 and /products/2 with just one controller.
|
25
32
|
* Cleaned up tests.
|
26
33
|
|
27
|
-
# Version 0.3
|
34
|
+
# Version 0.3
|
28
35
|
|
29
36
|
* Minor bump after three bug fixes.
|
30
37
|
* Bug fix when showing warning of constant redefinition.
|
@@ -33,13 +40,13 @@
|
|
33
40
|
raise "NoMethodError _url", not it will call root_url.
|
34
41
|
* More comments on UrlHelpers.
|
35
42
|
|
36
|
-
# Version 0.2
|
43
|
+
# Version 0.2
|
37
44
|
|
38
45
|
* Bug fix when ApplicationController is already loaded when we load respond_to.
|
39
46
|
* Added support success/failure blocks.
|
40
47
|
* Eager loading of files to work properly in multithreaded environments.
|
41
48
|
|
42
|
-
# Version 0.1
|
49
|
+
# Version 0.1
|
43
50
|
|
44
51
|
* Added more helper_methods.
|
45
52
|
* Added Rails 2.3.0 and changed tests to work with ActionController::TestCase.
|
data/README
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
Inherited Resources
|
2
2
|
License: MIT
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.6.0
|
4
4
|
|
5
5
|
You can also read this README in pretty html at the GitHub project Wiki page:
|
6
6
|
|
7
|
-
http://github.com/josevalim/inherited_resources
|
7
|
+
http://wiki.github.com/josevalim/inherited_resources
|
8
8
|
|
9
9
|
Description
|
10
10
|
-----------
|
@@ -199,11 +199,21 @@ equivalent:
|
|
199
199
|
class ProjectsController < InheritedResources::Base
|
200
200
|
def destroy
|
201
201
|
destroy! do |format|
|
202
|
-
format.html { redirect_to
|
202
|
+
format.html { redirect_to root_url }
|
203
203
|
end
|
204
204
|
end
|
205
205
|
end
|
206
206
|
|
207
|
+
Even more, since most of the times that you change a :create, :update or :destroy
|
208
|
+
action is because you want to to change to where it redirects, a shortcut is
|
209
|
+
provided. So you can do:
|
210
|
+
|
211
|
+
class ProjectsController < InheritedResources::Base
|
212
|
+
def destroy
|
213
|
+
destroy!(root_url)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
207
217
|
Now let's suppose that before create a project you have to do something special
|
208
218
|
but you don't want to create a before filter for it:
|
209
219
|
|
@@ -54,7 +54,7 @@
|
|
54
54
|
# class ProjectController < InheritedResources::Base
|
55
55
|
# def destroy
|
56
56
|
# super do |format|
|
57
|
-
# format.html { redirect_to
|
57
|
+
# format.html { redirect_to root_url }
|
58
58
|
# end
|
59
59
|
# end
|
60
60
|
# end
|
@@ -65,11 +65,21 @@
|
|
65
65
|
# class ProjectController < InheritedResources::Base
|
66
66
|
# def destroy
|
67
67
|
# destroy! do |format|
|
68
|
-
# format.html { redirect_to
|
68
|
+
# format.html { redirect_to root_url }
|
69
69
|
# end
|
70
70
|
# end
|
71
71
|
# end
|
72
72
|
#
|
73
|
+
# Even more, since most of the times that you change a :create, :update or :destroy
|
74
|
+
# action is because you want to to change to where it redirects, a shortcut is
|
75
|
+
# provided. So you can do:
|
76
|
+
#
|
77
|
+
# class ProjectsController < InheritedResources::Base
|
78
|
+
# def destroy
|
79
|
+
# destroy!(root_url)
|
80
|
+
# end
|
81
|
+
# end
|
82
|
+
#
|
73
83
|
# Since this is actually Ruby (and not a new DSL), if you want to do something
|
74
84
|
# before creating the project that is to small to deserve a before_filter, you
|
75
85
|
# could simply do:
|
@@ -231,22 +241,23 @@ module InheritedResources
|
|
231
241
|
alias :edit! :edit
|
232
242
|
|
233
243
|
# POST /resources
|
234
|
-
def create(&block)
|
244
|
+
def create(redirect_to=nil, &block)
|
235
245
|
object = build_resource(params[resource_instance_name])
|
236
246
|
|
237
247
|
if object.save
|
238
248
|
set_flash_message!(:notice, '{{resource_name}} was successfully created.')
|
239
|
-
location_url = resource_url rescue nil # Sometimes resource_url is undefined
|
240
249
|
|
241
|
-
|
242
|
-
|
243
|
-
|
250
|
+
options = { :with => object, :status => :created, :location => (resource_url rescue nil) }
|
251
|
+
|
252
|
+
respond_to_with_dual_blocks(true, block, options) do |format|
|
253
|
+
format.html { redirect_to(redirect_to || resource_url) }
|
244
254
|
end
|
245
255
|
else
|
246
256
|
set_flash_message!(:error)
|
247
257
|
|
248
|
-
|
249
|
-
|
258
|
+
options = { :with => object.errors, :status => :unprocessable_entity }
|
259
|
+
|
260
|
+
respond_to_with_dual_blocks(false, block, options) do |format|
|
250
261
|
format.html { render :action => 'new' }
|
251
262
|
end
|
252
263
|
end
|
@@ -254,22 +265,22 @@ module InheritedResources
|
|
254
265
|
alias :create! :create
|
255
266
|
|
256
267
|
# PUT /resources/1
|
257
|
-
def update(&block)
|
268
|
+
def update(redirect_to=nil, &block)
|
258
269
|
object = resource
|
259
270
|
|
260
271
|
if object.update_attributes(params[resource_instance_name])
|
261
272
|
set_flash_message!(:notice, '{{resource_name}} was successfully updated.')
|
262
273
|
|
263
|
-
|
264
|
-
|
265
|
-
format.html { redirect_to(resource_url) }
|
274
|
+
respond_to_with_dual_blocks(true, block) do |format|
|
275
|
+
format.html { redirect_to(redirect_to || resource_url) }
|
266
276
|
format.all { head :ok }
|
267
277
|
end
|
268
278
|
else
|
269
279
|
set_flash_message!(:error)
|
270
280
|
|
271
|
-
|
272
|
-
|
281
|
+
options = { :with => object.errors, :status => :unprocessable_entity }
|
282
|
+
|
283
|
+
respond_to_with_dual_blocks(false, block, options) do |format|
|
273
284
|
format.html { render :action => 'edit' }
|
274
285
|
end
|
275
286
|
end
|
@@ -277,14 +288,13 @@ module InheritedResources
|
|
277
288
|
alias :update! :update
|
278
289
|
|
279
290
|
# DELETE /resources/1
|
280
|
-
def destroy
|
291
|
+
def destroy(redirect_to=nil, &block)
|
281
292
|
resource.destroy
|
282
293
|
|
283
294
|
set_flash_message!(:notice, '{{resource_name}} was successfully destroyed.')
|
284
295
|
|
285
|
-
|
286
|
-
|
287
|
-
format.html { redirect_to(collection_url) }
|
296
|
+
respond_to_with_dual_blocks(nil, block) do |format|
|
297
|
+
format.html { redirect_to(redirect_to || collection_url) }
|
288
298
|
format.all { head :ok }
|
289
299
|
end
|
290
300
|
end
|
@@ -226,17 +226,26 @@ module InheritedResources #:nodoc:
|
|
226
226
|
# end
|
227
227
|
# end
|
228
228
|
#
|
229
|
-
def
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
229
|
+
def respond_to_with_dual_blocks(success, dual_block, options={}, &block)
|
230
|
+
responder = ActionController::MimeResponds::Responder.new(self)
|
231
|
+
|
232
|
+
if dual_block
|
233
|
+
if dual_block.arity == 2
|
234
|
+
dumb_responder = InheritedResources::DumbResponder.new
|
235
|
+
if success
|
236
|
+
dual_block.call(responder, dumb_responder)
|
237
|
+
else
|
238
|
+
dual_block.call(dumb_responder, responder)
|
239
|
+
end
|
234
240
|
else
|
235
|
-
|
241
|
+
dual_block.call(responder)
|
236
242
|
end
|
237
|
-
|
238
|
-
|
243
|
+
|
244
|
+
# Try to respond with the block given
|
245
|
+
responder.respond_except_any
|
239
246
|
end
|
247
|
+
|
248
|
+
respond_to(options.merge(:responder => responder), &block) unless performed?
|
240
249
|
end
|
241
250
|
|
242
251
|
end
|
@@ -59,9 +59,8 @@ module ActionController #:nodoc:
|
|
59
59
|
end
|
60
60
|
class_inheritable_reader :formats_for_respond_to
|
61
61
|
|
62
|
-
#
|
62
|
+
# By default, responds only to :html
|
63
63
|
respond_to :html
|
64
|
-
respond_to :xml, :except => [ :edit ]
|
65
64
|
|
66
65
|
# Method to clear all respond_to declared until the current controller.
|
67
66
|
# This is like freeing the controller from the inheritance chain. :)
|
@@ -119,20 +118,12 @@ module ActionController #:nodoc:
|
|
119
118
|
def respond_with(object, options = {})
|
120
119
|
attempt_to_respond = false
|
121
120
|
|
122
|
-
|
123
|
-
|
124
|
-
responder = options.delete(:responder) || Responder.new(self)
|
121
|
+
responder = options.delete(:responder) || Responder.new(self)
|
122
|
+
skip_not_acceptable = options.delete(:skip_not_acceptable)
|
125
123
|
|
126
|
-
# Check for given mime types
|
127
|
-
#
|
128
124
|
mime_types = Array(options.delete(:to))
|
129
125
|
mime_types.map!{ |mime| mime.to_sym }
|
130
126
|
|
131
|
-
# If :skip_not_acceptable is sent, it will not render :not_acceptable
|
132
|
-
# if the mime type sent by the client cannot be found.
|
133
|
-
#
|
134
|
-
skip_not_acceptable = options.delete(:skip_not_acceptable)
|
135
|
-
|
136
127
|
for priority in responder.mime_type_priority
|
137
128
|
if priority == Mime::ALL && template_exists?
|
138
129
|
render options.merge(:action => action_name)
|
@@ -206,58 +197,38 @@ module ActionController #:nodoc:
|
|
206
197
|
#
|
207
198
|
def respond_to(*types, &block)
|
208
199
|
options = types.extract_options!
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
200
|
+
|
201
|
+
object = options.delete(:with)
|
202
|
+
responder = options.delete(:responder) || Responder.new(self)
|
203
|
+
|
213
204
|
if object.nil?
|
214
205
|
block ||= lambda { |responder| types.each { |type| responder.send(type) } }
|
215
206
|
block.call(responder)
|
216
207
|
responder.respond
|
217
|
-
return true
|
218
|
-
|
208
|
+
return true
|
219
209
|
else
|
220
|
-
# If a block is given, it checks if we can perform the requested format.
|
221
|
-
#
|
222
210
|
# Even if Mime::ALL is sent by the client, we do not respond_to it now.
|
223
|
-
# This is done using calling :
|
224
|
-
#
|
225
|
-
# It's worth to remember that responder_to_block does not respond
|
226
|
-
# :not_acceptable also.
|
211
|
+
# This is done using calling :respond_except_any instead of :respond.
|
227
212
|
#
|
228
213
|
if block_given?
|
229
214
|
block.call(responder)
|
230
|
-
responder.
|
231
|
-
return true if responder.responded? || performed?
|
215
|
+
return true if responder.respond_except_any
|
232
216
|
end
|
233
217
|
|
234
|
-
|
235
|
-
# At the end, respond_with checks for Mime::ALL if any template exist.
|
236
|
-
#
|
237
|
-
# Notice that we are sending the responder (for performance gain) and
|
238
|
-
# sending :skip_not_acceptable because we don't want to respond
|
239
|
-
# :not_acceptable yet.
|
240
|
-
#
|
241
|
-
if respond_with(object, options.merge(:to => types, :responder => responder, :skip_not_acceptable => true))
|
242
|
-
return true
|
218
|
+
options.merge!(:to => types, :responder => responder, :skip_not_acceptable => true)
|
243
219
|
|
244
|
-
|
245
|
-
|
246
|
-
#
|
220
|
+
if respond_with(object, options)
|
221
|
+
return true
|
247
222
|
elsif block_given?
|
248
|
-
return true if responder.
|
223
|
+
return true if responder.respond_any
|
249
224
|
end
|
250
225
|
end
|
251
226
|
|
252
|
-
# If we get here it means that we could not satisfy our request.
|
253
|
-
# Now we finally return :not_acceptable.
|
254
|
-
#
|
255
227
|
head :not_acceptable
|
256
228
|
return false
|
257
229
|
end
|
258
230
|
|
259
231
|
private
|
260
|
-
|
261
232
|
# Define template_exists? for Rails 2.3
|
262
233
|
unless ActionController::Base.private_instance_methods.include?('template_exists?') ||
|
263
234
|
ActionController::Base.private_instance_methods.include?(:template_exists?)
|
@@ -282,43 +253,35 @@ module ActionController #:nodoc:
|
|
282
253
|
module MimeResponds #:nodoc:
|
283
254
|
class Responder #:nodoc:
|
284
255
|
|
285
|
-
# Create an attr_reader for @mime_type_priority
|
286
256
|
attr_reader :mime_type_priority
|
287
257
|
|
288
|
-
#
|
289
|
-
|
290
|
-
|
291
|
-
# Similar as respond but if we can't find a valid mime type,
|
292
|
-
# we do not send :not_acceptable message as head.
|
258
|
+
# Similar as respond but if we can't find a valid mime type, we do not
|
259
|
+
# send :not_acceptable message as head and it does not respond to
|
260
|
+
# Mime::ALL in any case.
|
293
261
|
#
|
294
|
-
|
295
|
-
#
|
296
|
-
def respond_to_block
|
262
|
+
def respond_except_any
|
297
263
|
for priority in @mime_type_priority
|
298
264
|
next if priority == Mime::ALL
|
299
265
|
|
300
266
|
if @responses[priority]
|
301
267
|
@responses[priority].call
|
302
|
-
return
|
268
|
+
return true
|
303
269
|
end
|
304
270
|
end
|
305
271
|
|
306
|
-
|
307
|
-
@responses[Mime::ALL].call
|
308
|
-
return (@responded = true)
|
309
|
-
else
|
310
|
-
return (@responded = false)
|
311
|
-
end
|
272
|
+
false
|
312
273
|
end
|
313
274
|
|
314
275
|
# Respond to the first format given if Mime::ALL is included in the
|
315
276
|
# mime type priorites. This is the behaviour expected when the client
|
316
277
|
# sends "*/*" as mime type.
|
317
278
|
#
|
318
|
-
def
|
319
|
-
|
320
|
-
|
321
|
-
|
279
|
+
def respond_any
|
280
|
+
any = @responses[@order.include?(Mime::ALL) ? Mime::ALL : @order.first]
|
281
|
+
|
282
|
+
if any && @mime_type_priority.include?(Mime::ALL)
|
283
|
+
any.call
|
284
|
+
return true
|
322
285
|
end
|
323
286
|
end
|
324
287
|
|
data/test/aliases_test.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# Now we are going to test aliases defined in base.rb and if overwriting
|
2
|
-
# methods works properly.
|
3
1
|
require File.dirname(__FILE__) + '/test_helper'
|
4
2
|
|
5
3
|
class Student;
|
@@ -40,13 +38,8 @@ class StudentsController < InheritedResources::Base
|
|
40
38
|
|
41
39
|
end
|
42
40
|
|
43
|
-
class
|
44
|
-
|
45
|
-
def setup
|
46
|
-
@controller = StudentsController.new
|
47
|
-
@controller.request = @request = ActionController::TestRequest.new
|
48
|
-
@controller.response = @response = ActionController::TestResponse.new
|
49
|
-
end
|
41
|
+
class AliasesTest < ActionController::TestCase
|
42
|
+
tests StudentsController
|
50
43
|
|
51
44
|
def test_assignments_before_calling_alias
|
52
45
|
Student.stubs(:new).returns(mock_student)
|
@@ -92,7 +85,7 @@ class AliasesBaseTest < TEST_CLASS
|
|
92
85
|
assert_equal "I won't redirect!", @response.body
|
93
86
|
end
|
94
87
|
|
95
|
-
def
|
88
|
+
def test_dumb_responder_quietly_receives_everything_on_failure
|
96
89
|
Student.stubs(:new).returns(mock_student(:save => false, :errors => []))
|
97
90
|
@controller.stubs(:resource_url).returns('http://test.host/')
|
98
91
|
post :create
|
@@ -107,8 +100,9 @@ class AliasesBaseTest < TEST_CLASS
|
|
107
100
|
assert_equal "I won't render!", @response.body
|
108
101
|
end
|
109
102
|
|
110
|
-
def
|
103
|
+
def test_dumb_responder_quietly_receives_everything_on_success
|
111
104
|
Student.stubs(:find).returns(mock_student(:update_attributes => true))
|
105
|
+
@controller.stubs(:resource_url).returns('http://test.host/')
|
112
106
|
put :update, :id => '42', :student => {:these => 'params'}
|
113
107
|
assert_equal mock_student, assigns(:student)
|
114
108
|
end
|
data/test/base_helpers_test.rb
CHANGED
@@ -19,12 +19,10 @@ class Admin::AddressesController < InheritedResources::Base
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
class FlashBaseHelpersTest <
|
22
|
+
class FlashBaseHelpersTest < ActionController::TestCase
|
23
|
+
tests AddressesController
|
23
24
|
|
24
25
|
def setup
|
25
|
-
@controller = AddressesController.new
|
26
|
-
@controller.request = @request = ActionController::TestRequest.new
|
27
|
-
@controller.response = @response = ActionController::TestResponse.new
|
28
26
|
@request.accept = 'application/xml'
|
29
27
|
end
|
30
28
|
|
@@ -90,6 +88,7 @@ class Pet
|
|
90
88
|
end
|
91
89
|
|
92
90
|
class PetsController < InheritedResources::Base
|
91
|
+
respond_to :xml
|
93
92
|
attr_accessor :current_user
|
94
93
|
|
95
94
|
def edit
|
@@ -107,12 +106,10 @@ class PetsController < InheritedResources::Base
|
|
107
106
|
end
|
108
107
|
end
|
109
108
|
|
110
|
-
class AssociationChainBaseHelpersTest <
|
109
|
+
class AssociationChainBaseHelpersTest < ActionController::TestCase
|
110
|
+
tests PetsController
|
111
111
|
|
112
112
|
def setup
|
113
|
-
@controller = PetsController.new
|
114
|
-
@controller.request = @request = ActionController::TestRequest.new
|
115
|
-
@controller.response = @response = ActionController::TestResponse.new
|
116
113
|
@controller.current_user = mock()
|
117
114
|
@request.accept = 'application/xml'
|
118
115
|
end
|