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 CHANGED
@@ -1,4 +1,11 @@
1
- # Version 0.5.2
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.6-0
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.0
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.1-0
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.2-0
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.5.2
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/wikis/home
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 projects_url }
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 projects_url }
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 projects_url }
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
- respond_to(:with => object, :status => :created, :location => location_url) do |format|
242
- block.call(args_for_block(block, format, true)) if block_given?
243
- format.html { redirect_to(resource_url) }
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
- respond_to(:with => object.errors, :status => :unprocessable_entity) do |format|
249
- block.call(args_for_block(block, format, false)) if block_given?
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
- respond_to do |format|
264
- block.call(args_for_block(block, format, true)) if block_given?
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
- respond_to(:with => object.errors, :status => :unprocessable_entity) do |format|
272
- block.call(args_for_block(block, format, false)) if block_given?
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
- respond_to do |format|
286
- yield(format) if block_given?
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 args_for_block(block_to_check_args, format, success = true)
230
- if block_to_check_args.arity == 2
231
- dumb_responder = InheritedResources::DumbResponder.new
232
- if success
233
- return format, dumb_responder
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
- return dumb_responder, format
241
+ dual_block.call(responder)
236
242
  end
237
- else
238
- return format
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
- # Define defaults respond_to
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
- # You can also send a responder object as parameter.
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
- object = options.delete(:with)
210
- responder = Responder.new(self)
211
-
212
- # This is the default respond_to behaviour, when no object is given.
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 # we are done here
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 :respond_to_block instead of :respond.
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.respond_to_block
231
- return true if responder.responded? || performed?
215
+ return true if responder.respond_except_any
232
216
  end
233
217
 
234
- # Let's see if we get lucky rendering with :respond_with.
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
- # Since respond_with couldn't help us, our last chance is to reply to
245
- # any block given if the user send all as mime type.
246
- #
220
+ if respond_with(object, options)
221
+ return true
247
222
  elsif block_given?
248
- return true if responder.respond_to_all
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
- # Stores if this Responder instance called any block.
289
- def responded?; @responded; end
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
- # It does not respond to Mime::ALL in priority as well.
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 (@responded = true) # mime type match found, be happy and return
268
+ return true
303
269
  end
304
270
  end
305
271
 
306
- if @order.include?(Mime::ALL)
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 respond_to_all
319
- if @mime_type_priority.include?(Mime::ALL) && first = @responses[@order.first]
320
- first.call
321
- return (@responded = true)
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 AliasesBaseTest < TEST_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 test_dumb_responder_with_quietly_receive_everything_on_failure
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 test_dumb_responder_with_quietly_receive_everything_on_success
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
@@ -19,12 +19,10 @@ class Admin::AddressesController < InheritedResources::Base
19
19
  end
20
20
  end
21
21
 
22
- class FlashBaseHelpersTest < TEST_CLASS
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 < TEST_CLASS
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