josevalim-inherited_resources 0.5.2 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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