actionpack 1.9.1 → 1.10.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (123) hide show
  1. data/CHANGELOG +237 -0
  2. data/README +12 -12
  3. data/lib/action_controller.rb +17 -12
  4. data/lib/action_controller/assertions.rb +119 -67
  5. data/lib/action_controller/base.rb +184 -102
  6. data/lib/action_controller/benchmarking.rb +35 -6
  7. data/lib/action_controller/caching.rb +115 -58
  8. data/lib/action_controller/cgi_ext/cgi_methods.rb +54 -21
  9. data/lib/action_controller/cgi_ext/cookie_performance_fix.rb +39 -35
  10. data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +34 -21
  11. data/lib/action_controller/cgi_process.rb +23 -20
  12. data/lib/action_controller/components.rb +11 -2
  13. data/lib/action_controller/dependencies.rb +0 -5
  14. data/lib/action_controller/deprecated_redirects.rb +17 -0
  15. data/lib/action_controller/filters.rb +13 -9
  16. data/lib/action_controller/flash.rb +7 -7
  17. data/lib/action_controller/helpers.rb +1 -14
  18. data/lib/action_controller/layout.rb +40 -29
  19. data/lib/action_controller/macros/auto_complete.rb +52 -0
  20. data/lib/action_controller/macros/in_place_editing.rb +32 -0
  21. data/lib/action_controller/pagination.rb +44 -28
  22. data/lib/action_controller/request.rb +54 -40
  23. data/lib/action_controller/rescue.rb +8 -6
  24. data/lib/action_controller/routing.rb +77 -28
  25. data/lib/action_controller/scaffolding.rb +10 -14
  26. data/lib/action_controller/session/active_record_store.rb +36 -7
  27. data/lib/action_controller/session_management.rb +126 -0
  28. data/lib/action_controller/streaming.rb +14 -5
  29. data/lib/action_controller/templates/rescues/_request_and_response.rhtml +1 -1
  30. data/lib/action_controller/templates/rescues/_trace.rhtml +24 -0
  31. data/lib/action_controller/templates/rescues/diagnostics.rhtml +2 -13
  32. data/lib/action_controller/templates/rescues/template_error.rhtml +4 -2
  33. data/lib/action_controller/templates/scaffolds/list.rhtml +1 -1
  34. data/lib/action_controller/test_process.rb +35 -17
  35. data/lib/action_controller/upload_progress.rb +52 -0
  36. data/lib/action_controller/url_rewriter.rb +21 -16
  37. data/lib/action_controller/vendor/html-scanner/html/document.rb +2 -2
  38. data/lib/action_controller/vendor/html-scanner/html/node.rb +30 -3
  39. data/lib/action_pack/version.rb +9 -0
  40. data/lib/action_view.rb +1 -1
  41. data/lib/action_view/base.rb +204 -60
  42. data/lib/action_view/compiled_templates.rb +70 -0
  43. data/lib/action_view/helpers/active_record_helper.rb +7 -3
  44. data/lib/action_view/helpers/asset_tag_helper.rb +22 -12
  45. data/lib/action_view/helpers/capture_helper.rb +2 -10
  46. data/lib/action_view/helpers/date_helper.rb +21 -13
  47. data/lib/action_view/helpers/form_helper.rb +14 -10
  48. data/lib/action_view/helpers/form_options_helper.rb +4 -4
  49. data/lib/action_view/helpers/form_tag_helper.rb +59 -25
  50. data/lib/action_view/helpers/java_script_macros_helper.rb +188 -0
  51. data/lib/action_view/helpers/javascript_helper.rb +68 -133
  52. data/lib/action_view/helpers/javascripts/controls.js +427 -165
  53. data/lib/action_view/helpers/javascripts/dragdrop.js +256 -277
  54. data/lib/action_view/helpers/javascripts/effects.js +766 -277
  55. data/lib/action_view/helpers/javascripts/prototype.js +906 -218
  56. data/lib/action_view/helpers/javascripts/slider.js +258 -0
  57. data/lib/action_view/helpers/number_helper.rb +4 -3
  58. data/lib/action_view/helpers/pagination_helper.rb +42 -27
  59. data/lib/action_view/helpers/tag_helper.rb +25 -11
  60. data/lib/action_view/helpers/text_helper.rb +119 -13
  61. data/lib/action_view/helpers/upload_progress_helper.rb +2 -2
  62. data/lib/action_view/helpers/url_helper.rb +68 -21
  63. data/lib/action_view/partials.rb +17 -6
  64. data/lib/action_view/template_error.rb +19 -24
  65. data/rakefile +4 -3
  66. data/test/abstract_unit.rb +2 -1
  67. data/test/controller/action_pack_assertions_test.rb +62 -2
  68. data/test/controller/active_record_assertions_test.rb +5 -6
  69. data/test/controller/active_record_store_test.rb +23 -1
  70. data/test/controller/addresses_render_test.rb +4 -0
  71. data/test/controller/{base_tests.rb → base_test.rb} +4 -3
  72. data/test/controller/benchmark_test.rb +36 -0
  73. data/test/controller/caching_filestore.rb +22 -40
  74. data/test/controller/capture_test.rb +10 -1
  75. data/test/controller/cgi_test.rb +145 -23
  76. data/test/controller/components_test.rb +50 -0
  77. data/test/controller/custom_handler_test.rb +3 -3
  78. data/test/controller/fake_controllers.rb +24 -0
  79. data/test/controller/filters_test.rb +6 -6
  80. data/test/controller/flash_test.rb +6 -6
  81. data/test/controller/fragment_store_setting_test.rb +45 -0
  82. data/test/controller/helper_test.rb +1 -3
  83. data/test/controller/new_render_test.rb +119 -7
  84. data/test/controller/redirect_test.rb +11 -1
  85. data/test/controller/render_test.rb +34 -1
  86. data/test/controller/request_test.rb +14 -5
  87. data/test/controller/routing_test.rb +238 -42
  88. data/test/controller/send_file_test.rb +11 -10
  89. data/test/controller/session_management_test.rb +94 -0
  90. data/test/controller/test_test.rb +194 -5
  91. data/test/controller/url_rewriter_test.rb +46 -0
  92. data/test/fixtures/layouts/talk_from_action.rhtml +2 -0
  93. data/test/fixtures/layouts/yield.rhtml +2 -0
  94. data/test/fixtures/multipart/binary_file +0 -0
  95. data/test/fixtures/multipart/large_text_file +10 -0
  96. data/test/fixtures/multipart/mixed_files +0 -0
  97. data/test/fixtures/multipart/single_parameter +5 -0
  98. data/test/fixtures/multipart/text_file +10 -0
  99. data/test/fixtures/test/_customer_greeting.rhtml +1 -0
  100. data/test/fixtures/test/_hash_object.rhtml +1 -0
  101. data/test/fixtures/test/_person.rhtml +2 -0
  102. data/test/fixtures/test/action_talk_to_layout.rhtml +2 -0
  103. data/test/fixtures/test/content_for.rhtml +2 -0
  104. data/test/fixtures/test/potential_conflicts.rhtml +4 -0
  105. data/test/template/active_record_helper_test.rb +15 -8
  106. data/test/template/asset_tag_helper_test.rb +40 -16
  107. data/test/template/compiled_templates_tests.rb +63 -0
  108. data/test/template/date_helper_test.rb +80 -4
  109. data/test/template/form_helper_test.rb +48 -42
  110. data/test/template/form_options_helper_test.rb +40 -40
  111. data/test/template/form_tag_helper_test.rb +21 -15
  112. data/test/template/java_script_macros_helper_test.rb +56 -0
  113. data/test/template/javascript_helper_test.rb +70 -47
  114. data/test/template/number_helper_test.rb +2 -0
  115. data/test/template/tag_helper_test.rb +9 -0
  116. data/test/template/text_helper_test.rb +146 -1
  117. data/test/template/upload_progress_helper_testx.rb +11 -147
  118. data/test/template/url_helper_test.rb +90 -22
  119. data/test/testing_sandbox.rb +26 -0
  120. metadata +37 -7
  121. data/lib/action_controller/auto_complete.rb +0 -47
  122. data/lib/action_controller/deprecated_renders_and_redirects.rb +0 -76
  123. data/lib/action_controller/session.rb +0 -14
@@ -16,11 +16,6 @@ module ActionController #:nodoc:
16
16
  alias_method :inherited_without_helper, :inherited
17
17
  alias_method :inherited, :inherited_with_helper
18
18
  end
19
-
20
- # Wrap initialize_template_class to extend new template class
21
- # instances with the master helper module.
22
- alias_method :initialize_template_class_without_helper, :initialize_template_class
23
- alias_method :initialize_template_class, :initialize_template_class_with_helper
24
19
  end
25
20
  end
26
21
 
@@ -50,7 +45,7 @@ module ActionController #:nodoc:
50
45
  # See ActionView::Helpers (link:classes/ActionView/Helpers.html) for more about making your own helper modules
51
46
  # available to the templates.
52
47
  def add_template_helper(helper_module) #:nodoc:
53
- master_helper_module.module_eval "include #{helper_module}"
48
+ master_helper_module.send(:include, helper_module)
54
49
  end
55
50
 
56
51
  # Declare a helper:
@@ -124,13 +119,5 @@ module ActionController #:nodoc:
124
119
  end
125
120
  end
126
121
  end
127
-
128
- private
129
- # Extend the template class instance with our controller's helper module.
130
- def initialize_template_class_with_helper(response)
131
- returning(initialize_template_class_without_helper(response)) do
132
- response.template.extend self.class.master_helper_module
133
- end
134
- end
135
122
  end
136
123
  end
@@ -194,65 +194,76 @@ module ActionController #:nodoc:
194
194
  # weblog/standard, but <tt>layout "standard"</tt> will return layouts/standard.
195
195
  def active_layout(passed_layout = nil)
196
196
  layout = passed_layout || self.class.read_inheritable_attribute("layout")
197
+
197
198
  active_layout = case layout
198
199
  when Symbol then send(layout)
199
200
  when Proc then layout.call(self)
200
201
  when String then layout
201
202
  end
203
+
202
204
  active_layout.include?("/") ? active_layout : "layouts/#{active_layout}" if active_layout
203
205
  end
204
206
 
205
- def render_with_a_layout(options = {}, deprecated_status = nil, deprecated_layout = nil) #:nodoc:
206
- options = render_with_a_layout_options(options)
207
- if (layout = pick_layout(options, deprecated_layout))
208
- logger.info("Rendering #{options[:template]} within #{layout}") unless logger.nil?
207
+ def render_with_a_layout(options = nil, deprecated_status = nil, deprecated_layout = nil) #:nodoc:
208
+ template_with_options = options.is_a?(Hash)
209
209
 
210
- @content_for_layout = render_with_no_layout(options.merge(:layout => false))
211
- erase_render_results
210
+ if apply_layout?(template_with_options, options) && (layout = pick_layout(template_with_options, options, deprecated_layout))
211
+ options = options.merge :layout => false if template_with_options
212
+ logger.info("Rendering #{options} within #{layout}") if logger
213
+
214
+ if template_with_options
215
+ content_for_layout = render_with_no_layout(options)
216
+ deprecated_status = options[:status] || deprecated_status
217
+ else
218
+ content_for_layout = render_with_no_layout(options, deprecated_status)
219
+ end
212
220
 
213
- add_variables_to_assigns
214
- render_with_no_layout(options.merge({ :text => @template.render_file(layout, true), :status => options[:status] || deprecated_status }))
221
+ erase_render_results
222
+ @template.instance_variable_set("@content_for_layout", content_for_layout)
223
+ render_text(@template.render_file(layout, true), deprecated_status)
215
224
  else
216
225
  render_with_no_layout(options, deprecated_status)
217
226
  end
218
227
  end
219
228
 
220
229
  private
221
- def render_with_a_layout_options(options)
222
- return { :template => options } unless options.is_a?(Hash)
223
- if options.values_at(:text, :file, :inline, :partial, :nothing).compact.empty?
224
- options
230
+ def apply_layout?(template_with_options, options)
231
+ if template_with_options
232
+ (options.has_key?(:layout) && options[:layout]!=false) || options.values_at(:text, :file, :inline, :partial, :nothing).compact.empty?
225
233
  else
226
- { :layout => false }.merge(options)
234
+ true
227
235
  end
228
236
  end
229
237
 
230
- def pick_layout(options = {}, deprecated_layout = nil)
231
- return deprecated_layout if !deprecated_layout.nil?
232
-
233
- if options.is_a?(Hash)
234
- case options[:layout]
238
+ def pick_layout(template_with_options, options, deprecated_layout)
239
+ if deprecated_layout
240
+ deprecated_layout
241
+ elsif template_with_options
242
+ case layout = options[:layout]
235
243
  when FalseClass
236
244
  nil
237
245
  when NilClass, TrueClass
238
246
  active_layout if action_has_layout?
239
247
  else
240
- active_layout(options[:layout])
248
+ active_layout(layout)
241
249
  end
242
250
  else
243
- (deprecated_layout || active_layout) if action_has_layout?
251
+ active_layout if action_has_layout?
244
252
  end
245
253
  end
246
-
254
+
247
255
  def action_has_layout?
248
- conditions = self.class.layout_conditions || {}
249
- case
250
- when conditions[:only]
251
- conditions[:only].include?(action_name)
252
- when conditions[:except]
253
- !conditions[:except].include?(action_name)
254
- else
255
- true
256
+ if conditions = self.class.layout_conditions
257
+ case
258
+ when only = conditions[:only]
259
+ only.include?(action_name)
260
+ when except = conditions[:except]
261
+ !except.include?(action_name)
262
+ else
263
+ true
264
+ end
265
+ else
266
+ true
256
267
  end
257
268
  end
258
269
  end
@@ -0,0 +1,52 @@
1
+ module ActionController
2
+ # Macros are class-level calls that add pre-defined actions to the controller based on the parameters passed in.
3
+ # Currently, they're used to bridge the JavaScript macros, like autocompletion and in-place editing, with the controller
4
+ # backing.
5
+ module Macros
6
+ module AutoComplete #:nodoc:
7
+ def self.append_features(base) #:nodoc:
8
+ super
9
+ base.extend(ClassMethods)
10
+ end
11
+
12
+ # Example:
13
+ #
14
+ # # Controller
15
+ # class BlogController < ApplicationController
16
+ # auto_complete_for :post, :title
17
+ # end
18
+ #
19
+ # # View
20
+ # <%= text_field_with_auto_complete :post, title %>
21
+ #
22
+ # By default, auto_complete_for limits the results to 10 entries,
23
+ # and sorts by the given field.
24
+ #
25
+ # auto_complete_for takes a third parameter, an options hash to
26
+ # the find method used to search for the records:
27
+ #
28
+ # auto_complete_for :post, :title, :limit => 15, :order => 'created_at DESC'
29
+ #
30
+ # For help on defining text input fields with autocompletion,
31
+ # see ActionView::Helpers::JavaScriptHelper.
32
+ #
33
+ # For more examples, see script.aculo.us:
34
+ # * http://script.aculo.us/demos/ajax/autocompleter
35
+ # * http://script.aculo.us/demos/ajax/autocompleter_customized
36
+ module ClassMethods
37
+ def auto_complete_for(object, method, options = {})
38
+ define_method("auto_complete_for_#{object}_#{method}") do
39
+ find_options = {
40
+ :conditions => [ "LOWER(#{method}) LIKE ?", '%' + params[object][method].downcase + '%' ],
41
+ :order => "#{method} ASC",
42
+ :limit => 10 }.merge!(options)
43
+
44
+ @items = object.to_s.camelize.constantize.find(:all, find_options)
45
+
46
+ render :inline => "<%= auto_complete_result @items, '#{method}' %>"
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,32 @@
1
+ module ActionController
2
+ module Macros
3
+ module InPlaceEditing #:nodoc:
4
+ def self.append_features(base) #:nodoc:
5
+ super
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ # Example:
10
+ #
11
+ # # Controller
12
+ # class BlogController < ApplicationController
13
+ # in_place_edit_for :post, :title
14
+ # end
15
+ #
16
+ # # View
17
+ # <%= in_place_editor_field :post, title %>
18
+ #
19
+ # For help on defining an in place editor in the browser,
20
+ # see ActionView::Helpers::JavaScriptHelper.
21
+ module ClassMethods
22
+ def in_place_edit_for(object, attribute, options = {})
23
+ define_method("set_#{object}_#{attribute}") do
24
+ @item = object.to_s.camelize.constantize.find(params[:id])
25
+ @item.update_attribute(attribute, params[:value])
26
+ render :text => @item.send(attribute)
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -21,7 +21,7 @@ module ActionController
21
21
  # class PersonController < ApplicationController
22
22
  # model :person
23
23
  #
24
- # paginate :people, :order_by => 'last_name, first_name',
24
+ # paginate :people, :order => 'last_name, first_name',
25
25
  # :per_page => 20
26
26
  #
27
27
  # # ...
@@ -37,7 +37,7 @@ module ActionController
37
37
  #
38
38
  # def list
39
39
  # @person_pages, @people =
40
- # paginate :people, :order_by => 'last_name, first_name'
40
+ # paginate :people, :order => 'last_name, first_name'
41
41
  # end
42
42
  #
43
43
  # Like the previous example, but explicitly creates <tt>@person_pages</tt>
@@ -48,8 +48,8 @@ module ActionController
48
48
  #
49
49
  # def list
50
50
  # @person_pages = Paginator.new self, Person.count, 10, @params['page']
51
- # @people = Person.find_all nil, 'last_name, first_name',
52
- # @person_pages.current.to_sql
51
+ # @people = Person.find :all, :order => 'last_name, first_name',
52
+ # :conditions => @person_pages.current.to_sql
53
53
  # end
54
54
  #
55
55
  # Explicitly creates the paginator from the previous example and uses
@@ -63,10 +63,15 @@ module ActionController
63
63
  # The default options for pagination
64
64
  DEFAULT_OPTIONS = {
65
65
  :class_name => nil,
66
+ :singular_name => nil,
66
67
  :per_page => 10,
67
68
  :conditions => nil,
68
69
  :order_by => nil,
70
+ :order => nil,
69
71
  :join => nil,
72
+ :joins => nil,
73
+ :include => nil,
74
+ :select => nil,
70
75
  :parameter => 'page'
71
76
  }
72
77
  end
@@ -87,7 +92,7 @@ module ActionController
87
92
  "Unknown options: #{unknown_option_keys.join(', ')}" unless
88
93
  unknown_option_keys.empty?
89
94
 
90
- options[:singular_name] = Inflector.singularize(collection_id.to_s)
95
+ options[:singular_name] ||= Inflector.singularize(collection_id.to_s)
91
96
  options[:class_name] ||= Inflector.camelize(options[:singular_name])
92
97
  end
93
98
 
@@ -97,14 +102,21 @@ module ActionController
97
102
  # ClassMethods#paginate.
98
103
  #
99
104
  # +options+ are:
100
- # <tt>:class_name</tt>:: the class name to use, if it can't be inferred by
105
+ # <tt>:singular_name</tt>:: the singular name to use, if it can't be inferred by
101
106
  # singularizing the collection name
107
+ # <tt>:class_name</tt>:: the class name to use, if it can't be inferred by
108
+ # camelizing the singular name
102
109
  # <tt>:per_page</tt>:: the maximum number of items to include in a
103
110
  # single page. Defaults to 10
104
- # <tt>:conditions</tt>:: optional conditions passed to Model.find_all and
111
+ # <tt>:conditions</tt>:: optional conditions passed to Model.find(:all, *params) and
105
112
  # Model.count
106
- # <tt>:order_by</tt>:: optional order parameter passed to Model.find_all
107
- # <tt>:join</tt>:: optional join parameter passed to Model.find_all
113
+ # <tt>:order</tt>:: optional order parameter passed to Model.find(:all, *params)
114
+ # <tt>:order_by</tt>:: (deprecated, used :order) optional order parameter passed to Model.find(:all, *params)
115
+ # <tt>:joins</tt>:: optional joins parameter passed to Model.find(:all, *params)
116
+ # and Model.count
117
+ # <tt>:join</tt>:: (deprecated, used :joins or :include) optional join parameter passed to Model.find(:all, *params)
118
+ # and Model.count
119
+ # <tt>:include</tt>:: optional eager loading parameter passed to Model.find(:all, *params)
108
120
  # and Model.count
109
121
  def paginate(collection_id, options={})
110
122
  Pagination.validate_options!(collection_id, options, true)
@@ -154,11 +166,15 @@ module ActionController
154
166
  model.count(conditions,joins)
155
167
  end
156
168
 
157
- # Returns a collection of items for the given +model+ and +conditions+,
158
- # ordered by +order_by+, for the current page in the given +paginator+.
169
+ # Returns a collection of items for the given +model+ and +options[conditions]+,
170
+ # ordered by +options[order]+, for the current page in the given +paginator+.
159
171
  # Override this method to implement a custom finder.
160
- def find_collection_for_pagination(model, conditions, order_by, join, paginator)
161
- model.find_all(conditions, order_by, paginator.current.to_sql, join)
172
+ def find_collection_for_pagination(model, options, paginator)
173
+ model.find(:all, :conditions => options[:conditions],
174
+ :order => options[:order_by] || options[:order],
175
+ :joins => options[:join] || options[:joins], :include => options[:include],
176
+ :select => options[:select], :limit => options[:per_page],
177
+ :offset => paginator.current.offset)
162
178
  end
163
179
 
164
180
  protected :create_paginators_and_retrieve_collections,
@@ -168,12 +184,11 @@ module ActionController
168
184
  def paginator_and_collection_for(collection_id, options) #:nodoc:
169
185
  klass = options[:class_name].constantize
170
186
  page = @params[options[:parameter]]
171
- count = count_collection_for_pagination(klass, options[:conditions], options[:join])
187
+ count = count_collection_for_pagination(klass, options[:conditions],
188
+ options[:join] || options[:joins])
172
189
 
173
190
  paginator = Paginator.new(self, count, options[:per_page], page)
174
-
175
- collection = find_collection_for_pagination(klass,
176
- options[:conditions], options[:order_by], options[:join], paginator)
191
+ collection = find_collection_for_pagination(klass, options, paginator)
177
192
 
178
193
  return paginator, collection
179
194
  end
@@ -196,6 +211,7 @@ module ActionController
196
211
  @controller = controller
197
212
  @item_count = item_count || 0
198
213
  @items_per_page = items_per_page
214
+ @pages = {}
199
215
 
200
216
  self.current_page = current_page
201
217
  end
@@ -210,44 +226,44 @@ module ActionController
210
226
  page.paginator == self
211
227
  end
212
228
  page = page.to_i
213
- @current_page = has_page_number?(page) ? page : 1
229
+ @current_page_number = has_page_number?(page) ? page : 1
214
230
  end
215
231
 
216
232
  # Returns a Page object representing this paginator's current page.
217
233
  def current_page
218
- self[@current_page]
234
+ @current_page ||= self[@current_page_number]
219
235
  end
220
236
  alias current :current_page
221
237
 
222
238
  # Returns a new Page representing the first page in this paginator.
223
239
  def first_page
224
- self[1]
240
+ @first_page ||= self[1]
225
241
  end
226
242
  alias first :first_page
227
243
 
228
244
  # Returns a new Page representing the last page in this paginator.
229
245
  def last_page
230
- self[page_count]
246
+ @last_page ||= self[page_count]
231
247
  end
232
248
  alias last :last_page
233
249
 
234
250
  # Returns the number of pages in this paginator.
235
251
  def page_count
236
- return 1 if @item_count.zero?
237
- (@item_count / @items_per_page.to_f).ceil
252
+ @page_count ||= @item_count.zero? ? 1 :
253
+ (q,r=@item_count.divmod(@items_per_page); r==0? q : q+1)
238
254
  end
255
+
239
256
  alias length :page_count
240
257
 
241
258
  # Returns true if this paginator contains the page of index +number+.
242
259
  def has_page_number?(number)
243
- return false unless number.is_a? Fixnum
244
260
  number >= 1 and number <= page_count
245
261
  end
246
262
 
247
263
  # Returns a new Page representing the page with the given index
248
264
  # +number+.
249
265
  def [](number)
250
- Page.new(self, number)
266
+ @pages[number] ||= Page.new(self, number)
251
267
  end
252
268
 
253
269
  # Successively yields all the paginator's pages to the given block.
@@ -318,13 +334,13 @@ module ActionController
318
334
  # Returns a new Page object representing the page just before this
319
335
  # page, or nil if this is the first page.
320
336
  def previous
321
- if first? then nil else Page.new(@paginator, @number - 1) end
337
+ if first? then nil else @paginator[@number - 1] end
322
338
  end
323
339
 
324
340
  # Returns a new Page object representing the page just after this
325
341
  # page, or nil if this is the last page.
326
342
  def next
327
- if last? then nil else Page.new(@paginator, @number + 1) end
343
+ if last? then nil else @paginator[@number + 1] end
328
344
  end
329
345
 
330
346
  # Returns a new Window object for this page with the specified
@@ -368,7 +384,7 @@ module ActionController
368
384
 
369
385
  # Returns an array of Page objects in the current window.
370
386
  def pages
371
- (@first.number..@last.number).to_a.map {|n| @paginator[n]}
387
+ (@first.number..@last.number).to_a.collect! {|n| @paginator[n]}
372
388
  end
373
389
  alias to_a :pages
374
390
  end
@@ -51,30 +51,31 @@ module ActionController
51
51
  # For backward compatibility, the post format is extracted from the
52
52
  # X-Post-Data-Format HTTP header if present.
53
53
  def post_format
54
- if env['HTTP_X_POST_DATA_FORMAT']
55
- env['HTTP_X_POST_DATA_FORMAT'].downcase.to_sym
56
- else
57
- case env['CONTENT_TYPE'].to_s.downcase
58
- when 'application/xml', 'text/xml' then :xml
59
- when 'application/x-yaml', 'text/x-yaml' then :yaml
60
- else :url_encoded
61
- end
62
- end
54
+ @post_format ||=
55
+ if env['HTTP_X_POST_DATA_FORMAT']
56
+ env['HTTP_X_POST_DATA_FORMAT'].downcase.to_sym
57
+ else
58
+ case env['CONTENT_TYPE'].to_s.downcase
59
+ when 'application/xml', 'text/xml' then :xml
60
+ when 'application/x-yaml', 'text/x-yaml' then :yaml
61
+ else :url_encoded
62
+ end
63
+ end
63
64
  end
64
65
 
65
66
  # Is this a POST request formatted as XML or YAML?
66
67
  def formatted_post?
67
- [ :xml, :yaml ].include?(post_format) && post?
68
+ post? && (post_format == :xml || post_format == :yaml)
68
69
  end
69
70
 
70
71
  # Is this a POST request formatted as XML?
71
72
  def xml_post?
72
- post_format == :xml && post?
73
+ post? && post_format == :xml
73
74
  end
74
75
 
75
76
  # Is this a POST request formatted as YAML?
76
77
  def yaml_post?
77
- post_format == :yaml && post?
78
+ post? && post_format == :yaml
78
79
  end
79
80
 
80
81
  # Returns true if the request's "X-Requested-With" header contains
@@ -102,12 +103,14 @@ module ActionController
102
103
  return remote_ips.first.strip unless remote_ips.empty?
103
104
  end
104
105
 
105
- return env['REMOTE_ADDR']
106
+ env['REMOTE_ADDR']
106
107
  end
107
108
 
108
109
  # Returns the domain part of a host, such as rubyonrails.org in "www.rubyonrails.org". You can specify
109
110
  # a different <tt>tld_length</tt>, such as 2 to catch rubyonrails.co.uk in "www.rubyonrails.co.uk".
110
111
  def domain(tld_length = 1)
112
+ return nil if !/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/.match(host).nil? or host.nil?
113
+
111
114
  host.split('.').last(1 + tld_length).join('.')
112
115
  end
113
116
 
@@ -115,8 +118,9 @@ module ActionController
115
118
  # You can specify a different <tt>tld_length</tt>, such as 2 to catch ["www"] instead of ["www", "rubyonrails"]
116
119
  # in "www.rubyonrails.co.uk".
117
120
  def subdomains(tld_length = 1)
121
+ return [] unless host
118
122
  parts = host.split('.')
119
- parts - parts.last(1 + tld_length)
123
+ parts[0..-(tld_length+2)]
120
124
  end
121
125
 
122
126
  # Receive the raw post data.
@@ -126,26 +130,30 @@ module ActionController
126
130
  env['RAW_POST_DATA']
127
131
  end
128
132
 
133
+ # Returns the request URI correctly, taking into account the idiosyncracies
134
+ # of the various servers.
129
135
  def request_uri
130
- unless env['REQUEST_URI'].nil?
131
- (%r{^\w+\://[^/]+(/.*|$)$} =~ env['REQUEST_URI']) ? $1 : env['REQUEST_URI'] # Remove domain, which webrick puts into the request_uri.
136
+ if uri = env['REQUEST_URI']
137
+ (%r{^\w+\://[^/]+(/.*|$)$} =~ uri) ? $1 : uri # Remove domain, which webrick puts into the request_uri.
132
138
  else # REQUEST_URI is blank under IIS - get this from PATH_INFO and SCRIPT_NAME
133
- script_filename = env["SCRIPT_NAME"].to_s.match(%r{[^/]+$})
134
- request_uri = env["PATH_INFO"]
135
- request_uri.sub!(/#{script_filename}\//, '') unless script_filename.nil?
136
- request_uri += '?' + env["QUERY_STRING"] unless env["QUERY_STRING"].nil? || env["QUERY_STRING"].empty?
137
- return request_uri
139
+ script_filename = env['SCRIPT_NAME'].to_s.match(%r{[^/]+$})
140
+ uri = env['PATH_INFO']
141
+ uri = uri.sub(/#{script_filename}\//, '') unless script_filename.nil?
142
+ unless (env_qs = env['QUERY_STRING']).nil? || env_qs.empty?
143
+ uri << '?' << env_qs
144
+ end
145
+ uri
138
146
  end
139
147
  end
140
148
 
141
149
  # Return 'https://' if this is an SSL request and 'http://' otherwise.
142
150
  def protocol
143
- env["HTTPS"] == "on" ? 'https://' : 'http://'
151
+ ssl? ? 'https://' : 'http://'
144
152
  end
145
153
 
146
154
  # Is this an SSL request?
147
155
  def ssl?
148
- protocol == 'https://'
156
+ env['HTTPS'] == 'on'
149
157
  end
150
158
 
151
159
  # Returns the interpreted path to requested resource after all the installation directory of this application was taken into account
@@ -153,34 +161,40 @@ module ActionController
153
161
  path = (uri = request_uri) ? uri.split('?').first : ''
154
162
 
155
163
  # Cut off the path to the installation directory if given
156
- if root = relative_url_root
157
- path[root.length..-1]
158
- else
159
- path
160
- end
161
- end
164
+ root = relative_url_root
165
+ path[0, root.length] = '' if root
166
+ path || ''
167
+ end
162
168
 
163
169
  # Returns the path minus the web server relative installation directory.
164
170
  # This method returns nil unless the web server is apache.
165
171
  def relative_url_root
166
- @@relative_url_root ||= File.dirname(env["SCRIPT_NAME"].to_s).gsub(/(^\.$|^\/$)/, '') if server_software == 'apache'
172
+ @@relative_url_root ||= server_software == 'apache' ? File.dirname(env["SCRIPT_NAME"].to_s).gsub(/(^\.$|^\/$)/, '') : ''
167
173
  end
168
174
 
169
175
  # Returns the port number of this request as an integer.
170
176
  def port
171
- env['SERVER_PORT'].to_i
177
+ @port_as_int ||= env['SERVER_PORT'].to_i
178
+ end
179
+
180
+ # Returns the standard port number for this request's protocol
181
+ def standard_port
182
+ case protocol
183
+ when 'https://' then 443
184
+ else 80
185
+ end
172
186
  end
173
187
 
174
188
  # Returns a port suffix like ":8080" if the port number of this request
175
189
  # is not the default HTTP port 80 or HTTPS port 443.
176
190
  def port_string
177
- (protocol == 'http://' && port == 80) || (protocol == 'https://' && port == 443) ? '' : ":#{port}"
191
+ (port == standard_port) ? '' : ":#{port}"
178
192
  end
179
193
 
180
194
  # Returns a host:port string for this request, such as example.com or
181
195
  # example.com:8080.
182
196
  def host_with_port
183
- env['HTTP_HOST'] || host + port_string
197
+ host + port_string
184
198
  end
185
199
 
186
200
  def path_parameters=(parameters)
@@ -204,25 +218,25 @@ module ActionController
204
218
  #--
205
219
  # Must be implemented in the concrete request
206
220
  #++
207
- def query_parameters
221
+ def query_parameters #:nodoc:
208
222
  end
209
223
 
210
- def request_parameters
224
+ def request_parameters #:nodoc:
211
225
  end
212
226
 
213
- def env
227
+ def env #:nodoc:
214
228
  end
215
229
 
216
- def host
230
+ def host #:nodoc:
217
231
  end
218
232
 
219
- def cookies
233
+ def cookies #:nodoc:
220
234
  end
221
235
 
222
- def session
236
+ def session #:nodoc:
223
237
  end
224
238
 
225
- def reset_session
239
+ def reset_session #:nodoc:
226
240
  end
227
241
  end
228
242
  end