josevalim-inherited_resources 0.6.2 → 0.6.3

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,5 +1,18 @@
1
1
  # Version 0.6
2
2
 
3
+ * Ensure that the default template is not rendered if the default_template_format
4
+ is not accepted. This is somehow related with the security breach report:
5
+
6
+ http://www.rorsecurity.info/journal/2009/4/24/hidden-actions-render-templates.html
7
+
8
+ IR forbids based on mime types. For example: respond_to :html, :except => :index
9
+ ensures that the index.html.erb view is not rendered, making your IR controllers
10
+ safer.
11
+
12
+ * Fixed a bug that happens only when format.xml is given to blocks and then it
13
+ acts as default, instead of format.html.
14
+ * Fixed a strange bug where when you have create.html.erb or update.html.erb,
15
+ it makes IE6 and IE7 return unprocessable entity (because they send Mime::ALL).
3
16
  * Stop rescueing any error when constantizing the resource class and allow
4
17
  route_prefix to be nil.
5
18
  * Cleaned up tests and responder structure. Whenever you pass a block to aliases
data/README CHANGED
@@ -1,6 +1,6 @@
1
1
  Inherited Resources
2
2
  License: MIT
3
- Version: 0.6.2
3
+ Version: 0.6.3
4
4
 
5
5
  You can also read this README in pretty html at the GitHub project Wiki page:
6
6
 
@@ -37,7 +37,7 @@ rspec-rails <= 1.1.12 known bug
37
37
  -------------------------------
38
38
 
39
39
  InheritedResources has a known bug with rspec-rails when using blocks inside
40
- actions. This will be fixed in the next rspec release, but until it comes out,
40
+ actions. This is fixed in Rspec >= 1.2.0. But if you have to use 1.1.12, you
41
41
  InheritedResources ships with a patch. To apply it, just put the line below on
42
42
  your spec_helper.rb after loading rspec and rspec-rails:
43
43
 
@@ -245,7 +245,7 @@ module InheritedResources #:nodoc:
245
245
  responder.respond_except_any
246
246
  end
247
247
 
248
- respond_to(options.merge(:responder => responder), &block) unless performed?
248
+ respond_to(options.merge!(:responder => responder, :prioritize => :html), &block) unless performed?
249
249
  end
250
250
 
251
251
  end
@@ -118,14 +118,15 @@ module ActionController #:nodoc:
118
118
  def respond_with(object, options = {})
119
119
  attempt_to_respond = false
120
120
 
121
- responder = options.delete(:responder) || Responder.new(self)
122
- skip_not_acceptable = options.delete(:skip_not_acceptable)
121
+ responder = options.delete(:responder) || Responder.new(self)
122
+ skip_not_acceptable = options.delete(:skip_not_acceptable)
123
+ skip_default_template = options.delete(:skip_default_template)
123
124
 
124
125
  mime_types = Array(options.delete(:to))
125
126
  mime_types.map!{ |mime| mime.to_sym }
126
127
 
127
128
  for priority in responder.mime_type_priority
128
- if priority == Mime::ALL && template_exists?
129
+ if !skip_default_template && priority == Mime::ALL && respond_to_default_template?(responder)
129
130
  render options.merge(:action => action_name)
130
131
  return true
131
132
 
@@ -195,11 +196,16 @@ module ActionController #:nodoc:
195
196
  # format.html { render :template => 'new' }
196
197
  # end
197
198
  #
199
+ # It also accepts an option called prioritize. It allows you to put a
200
+ # format as first, and then when Mime::ALL is sent, it will be the one
201
+ # used as response.
202
+ #
198
203
  def respond_to(*types, &block)
199
204
  options = types.extract_options!
200
205
 
201
- object = options.delete(:with)
202
- responder = options.delete(:responder) || Responder.new(self)
206
+ object = options.delete(:with)
207
+ responder = options.delete(:responder) || Responder.new(self)
208
+ prioritize = options.delete(:prioritize)
203
209
 
204
210
  if object.nil?
205
211
  block ||= lambda { |responder| types.each { |type| responder.send(type) } }
@@ -215,11 +221,15 @@ module ActionController #:nodoc:
215
221
  return true if responder.respond_except_any
216
222
  end
217
223
 
218
- options.merge!(:to => types, :responder => responder, :skip_not_acceptable => true)
224
+ # If the block includes the default template format, we don't render
225
+ # the default template (which uses the default_template_format).
226
+ options.merge!(:to => types, :responder => responder, :skip_not_acceptable => true,
227
+ :skip_default_template => responder.order.include?(default_template_format))
219
228
 
220
229
  if respond_with(object, options)
221
230
  return true
222
231
  elsif block_given?
232
+ responder.prioritize(prioritize) if prioritize
223
233
  return true if responder.respond_any
224
234
  end
225
235
  end
@@ -229,6 +239,7 @@ module ActionController #:nodoc:
229
239
  end
230
240
 
231
241
  private
242
+
232
243
  # Define template_exists? for Rails 2.3
233
244
  unless ActionController::Base.private_instance_methods.include?('template_exists?') ||
234
245
  ActionController::Base.private_instance_methods.include?(:template_exists?)
@@ -240,20 +251,27 @@ module ActionController #:nodoc:
240
251
  end
241
252
  end
242
253
 
243
- # If ApplicationController is already defined around here, we should call
244
- # inherited_with_inheritable_attributes to insert formats_for_respond_to.
245
- # This usually happens only on Rails 2.3.
246
- #
247
- if defined?(ApplicationController)
248
- self.send(:inherited_with_inheritable_attributes, ApplicationController)
249
- end
254
+ # We respond to the default template if it's a valid format AND the template
255
+ # exists.
256
+ #
257
+ def respond_to_default_template?(responder)
258
+ responder.action_respond_to_format?(default_template_format) && template_exists?
259
+ end
260
+
261
+ # If ApplicationController is already defined around here, we should call
262
+ # inherited_with_inheritable_attributes to insert formats_for_respond_to.
263
+ # This usually happens only on Rails 2.3.
264
+ #
265
+ if defined?(ApplicationController)
266
+ self.send(:inherited_with_inheritable_attributes, ApplicationController)
267
+ end
250
268
 
251
269
  end
252
270
 
253
271
  module MimeResponds #:nodoc:
254
272
  class Responder #:nodoc:
255
273
 
256
- attr_reader :mime_type_priority
274
+ attr_reader :mime_type_priority, :order
257
275
 
258
276
  # Similar as respond but if we can't find a valid mime type, we do not
259
277
  # send :not_acceptable message as head and it does not respond to
@@ -304,6 +322,15 @@ module ActionController #:nodoc:
304
322
  end
305
323
  end
306
324
 
325
+ # Makes a given format the first in the @order array.
326
+ #
327
+ def prioritize(format)
328
+ if index = @order.index(format)
329
+ @order.unshift(@order.delete_at(index))
330
+ end
331
+ @order
332
+ end
333
+
307
334
  end
308
335
  end
309
336
  end
data/test/aliases_test.rb CHANGED
@@ -20,6 +20,7 @@ class StudentsController < InheritedResources::Base
20
20
  def create
21
21
  create! do |success, failure|
22
22
  success.html { render :text => "I won't redirect!" }
23
+ failure.xml { render :text => "I shouldn't be rendered" }
23
24
  end
24
25
  end
25
26
 
@@ -86,11 +87,21 @@ class AliasesTest < ActionController::TestCase
86
87
  end
87
88
 
88
89
  def test_dumb_responder_quietly_receives_everything_on_failure
90
+ @request.accept = 'text/html'
89
91
  Student.stubs(:new).returns(mock_student(:save => false, :errors => []))
90
92
  @controller.stubs(:resource_url).returns('http://test.host/')
91
93
  post :create
92
94
  assert_response :success
93
- assert_template :edit
95
+ assert_equal "New HTML", @response.body.strip
96
+ end
97
+
98
+ def test_html_is_the_default_when_only_xml_is_overwriten
99
+ @request.accept = '*/*'
100
+ Student.stubs(:new).returns(mock_student(:save => false, :errors => []))
101
+ @controller.stubs(:resource_url).returns('http://test.host/')
102
+ post :create
103
+ assert_response :success
104
+ assert_equal "New HTML", @response.body.strip
94
105
  end
95
106
 
96
107
  def test_wont_render_edit_template_on_update_with_failure_if_failure_block_is_given
@@ -17,11 +17,12 @@ end
17
17
  class ProjectsController < ActionController::Base
18
18
  # Inherited respond_to definition is:
19
19
  # respond_to :html
20
- respond_to :xml, :except => :edit
21
20
  respond_to :html
21
+ respond_to :xml, :except => :edit
22
22
  respond_to :rjs => :edit
23
23
  respond_to :rss, :only => 'index'
24
24
  respond_to :json, :except => :index
25
+ respond_to :csv, :except => :index
25
26
 
26
27
  def index
27
28
  respond_with(Project.new)
@@ -46,6 +47,16 @@ class ProjectsController < ActionController::Base
46
47
  format.rss { render :text => 'Render RSS' }
47
48
  end
48
49
  end
50
+
51
+ # If the user request Mime::ALL and we have a template called action.html.erb,
52
+ # the html template should be rendered *unless* html is specified inside the
53
+ # block. This tests exactly this case.
54
+ #
55
+ def respond_to_skip_default_template
56
+ respond_to(:with => Project.new) do |format|
57
+ format.html { render :text => 'Render HTML' }
58
+ end
59
+ end
49
60
  end
50
61
 
51
62
  class SuperProjectsController < ProjectsController
@@ -149,6 +160,17 @@ class RespondToUnitTest < ActionController::TestCase
149
160
  @responder.respond_any
150
161
  assert !@performed
151
162
  end
163
+
164
+ def test_responder_prioritize
165
+ prepare_responder_to_respond!
166
+ assert_equal [Mime::HTML, Mime::XML], @responder.order
167
+
168
+ @responder.prioritize(:xml)
169
+ assert_equal [Mime::XML, Mime::HTML], @responder.order
170
+
171
+ @responder.prioritize(:js)
172
+ assert_equal [Mime::XML, Mime::HTML], @responder.order
173
+ end
152
174
 
153
175
  protected
154
176
  def prepare_responder_to_respond!(content_type='*/*')
@@ -195,7 +217,7 @@ class RespondToFunctionalTest < ActionController::TestCase
195
217
  end
196
218
 
197
219
  def test_respond_with_renders_status_not_acceptable_if_mime_type_is_not_registered
198
- @request.accept = 'application/json'
220
+ @request.accept = 'text/csv'
199
221
  get :index
200
222
  assert_equal '406 Not Acceptable', @response.status
201
223
  end
@@ -212,6 +234,13 @@ class RespondToFunctionalTest < ActionController::TestCase
212
234
  assert_equal 'Index HTML', @response.body.strip
213
235
  end
214
236
 
237
+ def test_default_template_is_not_rendered_if_template_format_is_not_accepted
238
+ @controller.stubs(:default_template_format).returns(:json)
239
+ @request.accept = '*/*'
240
+ get :index
241
+ assert_equal '406 Not Acceptable', @response.status
242
+ end
243
+
215
244
  def test_respond_with_sets_content_type_properly
216
245
  @request.accept = 'text/html'
217
246
  get :index
@@ -276,4 +305,10 @@ class RespondToFunctionalTest < ActionController::TestCase
276
305
  get :respond_to_with_resource_and_blocks
277
306
  assert_equal 'Render JSON', @response.body.strip
278
307
  end
308
+
309
+ def test_respond_to_skip_default_template_when_it_is_in_block
310
+ @request.accept = '*/*'
311
+ get :respond_to_skip_default_template
312
+ assert_equal 'Render HTML', @response.body.strip
313
+ end
279
314
  end
@@ -0,0 +1 @@
1
+ Index JSON
@@ -0,0 +1 @@
1
+ DefaultTemplate HTML
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: josevalim-inherited_resources
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.2
4
+ version: 0.6.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - "Jos\xC3\xA9 Valim"
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-04-19 00:00:00 -07:00
12
+ date: 2009-04-24 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -110,6 +110,8 @@ test_files:
110
110
  - test/views/professors/new.html.erb
111
111
  - test/views/professors/show.html.erb
112
112
  - test/views/projects/index.html.erb
113
+ - test/views/projects/index.json.erb
114
+ - test/views/projects/respond_to_skip_default_template.html.erb
113
115
  - test/views/projects/respond_to_with_resource.html.erb
114
116
  - test/views/students/edit.html.erb
115
117
  - test/views/students/new.html.erb