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.
- data/CHANGELOG +237 -0
- data/README +12 -12
- data/lib/action_controller.rb +17 -12
- data/lib/action_controller/assertions.rb +119 -67
- data/lib/action_controller/base.rb +184 -102
- data/lib/action_controller/benchmarking.rb +35 -6
- data/lib/action_controller/caching.rb +115 -58
- data/lib/action_controller/cgi_ext/cgi_methods.rb +54 -21
- data/lib/action_controller/cgi_ext/cookie_performance_fix.rb +39 -35
- data/lib/action_controller/cgi_ext/raw_post_data_fix.rb +34 -21
- data/lib/action_controller/cgi_process.rb +23 -20
- data/lib/action_controller/components.rb +11 -2
- data/lib/action_controller/dependencies.rb +0 -5
- data/lib/action_controller/deprecated_redirects.rb +17 -0
- data/lib/action_controller/filters.rb +13 -9
- data/lib/action_controller/flash.rb +7 -7
- data/lib/action_controller/helpers.rb +1 -14
- data/lib/action_controller/layout.rb +40 -29
- data/lib/action_controller/macros/auto_complete.rb +52 -0
- data/lib/action_controller/macros/in_place_editing.rb +32 -0
- data/lib/action_controller/pagination.rb +44 -28
- data/lib/action_controller/request.rb +54 -40
- data/lib/action_controller/rescue.rb +8 -6
- data/lib/action_controller/routing.rb +77 -28
- data/lib/action_controller/scaffolding.rb +10 -14
- data/lib/action_controller/session/active_record_store.rb +36 -7
- data/lib/action_controller/session_management.rb +126 -0
- data/lib/action_controller/streaming.rb +14 -5
- data/lib/action_controller/templates/rescues/_request_and_response.rhtml +1 -1
- data/lib/action_controller/templates/rescues/_trace.rhtml +24 -0
- data/lib/action_controller/templates/rescues/diagnostics.rhtml +2 -13
- data/lib/action_controller/templates/rescues/template_error.rhtml +4 -2
- data/lib/action_controller/templates/scaffolds/list.rhtml +1 -1
- data/lib/action_controller/test_process.rb +35 -17
- data/lib/action_controller/upload_progress.rb +52 -0
- data/lib/action_controller/url_rewriter.rb +21 -16
- data/lib/action_controller/vendor/html-scanner/html/document.rb +2 -2
- data/lib/action_controller/vendor/html-scanner/html/node.rb +30 -3
- data/lib/action_pack/version.rb +9 -0
- data/lib/action_view.rb +1 -1
- data/lib/action_view/base.rb +204 -60
- data/lib/action_view/compiled_templates.rb +70 -0
- data/lib/action_view/helpers/active_record_helper.rb +7 -3
- data/lib/action_view/helpers/asset_tag_helper.rb +22 -12
- data/lib/action_view/helpers/capture_helper.rb +2 -10
- data/lib/action_view/helpers/date_helper.rb +21 -13
- data/lib/action_view/helpers/form_helper.rb +14 -10
- data/lib/action_view/helpers/form_options_helper.rb +4 -4
- data/lib/action_view/helpers/form_tag_helper.rb +59 -25
- data/lib/action_view/helpers/java_script_macros_helper.rb +188 -0
- data/lib/action_view/helpers/javascript_helper.rb +68 -133
- data/lib/action_view/helpers/javascripts/controls.js +427 -165
- data/lib/action_view/helpers/javascripts/dragdrop.js +256 -277
- data/lib/action_view/helpers/javascripts/effects.js +766 -277
- data/lib/action_view/helpers/javascripts/prototype.js +906 -218
- data/lib/action_view/helpers/javascripts/slider.js +258 -0
- data/lib/action_view/helpers/number_helper.rb +4 -3
- data/lib/action_view/helpers/pagination_helper.rb +42 -27
- data/lib/action_view/helpers/tag_helper.rb +25 -11
- data/lib/action_view/helpers/text_helper.rb +119 -13
- data/lib/action_view/helpers/upload_progress_helper.rb +2 -2
- data/lib/action_view/helpers/url_helper.rb +68 -21
- data/lib/action_view/partials.rb +17 -6
- data/lib/action_view/template_error.rb +19 -24
- data/rakefile +4 -3
- data/test/abstract_unit.rb +2 -1
- data/test/controller/action_pack_assertions_test.rb +62 -2
- data/test/controller/active_record_assertions_test.rb +5 -6
- data/test/controller/active_record_store_test.rb +23 -1
- data/test/controller/addresses_render_test.rb +4 -0
- data/test/controller/{base_tests.rb → base_test.rb} +4 -3
- data/test/controller/benchmark_test.rb +36 -0
- data/test/controller/caching_filestore.rb +22 -40
- data/test/controller/capture_test.rb +10 -1
- data/test/controller/cgi_test.rb +145 -23
- data/test/controller/components_test.rb +50 -0
- data/test/controller/custom_handler_test.rb +3 -3
- data/test/controller/fake_controllers.rb +24 -0
- data/test/controller/filters_test.rb +6 -6
- data/test/controller/flash_test.rb +6 -6
- data/test/controller/fragment_store_setting_test.rb +45 -0
- data/test/controller/helper_test.rb +1 -3
- data/test/controller/new_render_test.rb +119 -7
- data/test/controller/redirect_test.rb +11 -1
- data/test/controller/render_test.rb +34 -1
- data/test/controller/request_test.rb +14 -5
- data/test/controller/routing_test.rb +238 -42
- data/test/controller/send_file_test.rb +11 -10
- data/test/controller/session_management_test.rb +94 -0
- data/test/controller/test_test.rb +194 -5
- data/test/controller/url_rewriter_test.rb +46 -0
- data/test/fixtures/layouts/talk_from_action.rhtml +2 -0
- data/test/fixtures/layouts/yield.rhtml +2 -0
- data/test/fixtures/multipart/binary_file +0 -0
- data/test/fixtures/multipart/large_text_file +10 -0
- data/test/fixtures/multipart/mixed_files +0 -0
- data/test/fixtures/multipart/single_parameter +5 -0
- data/test/fixtures/multipart/text_file +10 -0
- data/test/fixtures/test/_customer_greeting.rhtml +1 -0
- data/test/fixtures/test/_hash_object.rhtml +1 -0
- data/test/fixtures/test/_person.rhtml +2 -0
- data/test/fixtures/test/action_talk_to_layout.rhtml +2 -0
- data/test/fixtures/test/content_for.rhtml +2 -0
- data/test/fixtures/test/potential_conflicts.rhtml +4 -0
- data/test/template/active_record_helper_test.rb +15 -8
- data/test/template/asset_tag_helper_test.rb +40 -16
- data/test/template/compiled_templates_tests.rb +63 -0
- data/test/template/date_helper_test.rb +80 -4
- data/test/template/form_helper_test.rb +48 -42
- data/test/template/form_options_helper_test.rb +40 -40
- data/test/template/form_tag_helper_test.rb +21 -15
- data/test/template/java_script_macros_helper_test.rb +56 -0
- data/test/template/javascript_helper_test.rb +70 -47
- data/test/template/number_helper_test.rb +2 -0
- data/test/template/tag_helper_test.rb +9 -0
- data/test/template/text_helper_test.rb +146 -1
- data/test/template/upload_progress_helper_testx.rb +11 -147
- data/test/template/url_helper_test.rb +90 -22
- data/test/testing_sandbox.rb +26 -0
- metadata +37 -7
- data/lib/action_controller/auto_complete.rb +0 -47
- data/lib/action_controller/deprecated_renders_and_redirects.rb +0 -76
- 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.
|
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 =
|
206
|
-
|
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
|
-
|
211
|
-
|
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
|
-
|
214
|
-
|
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
|
222
|
-
|
223
|
-
|
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
|
-
|
234
|
+
true
|
227
235
|
end
|
228
236
|
end
|
229
237
|
|
230
|
-
def pick_layout(options
|
231
|
-
|
232
|
-
|
233
|
-
|
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(
|
248
|
+
active_layout(layout)
|
241
249
|
end
|
242
250
|
else
|
243
|
-
|
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
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
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, :
|
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, :
|
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.
|
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]
|
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>:
|
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.
|
111
|
+
# <tt>:conditions</tt>:: optional conditions passed to Model.find(:all, *params) and
|
105
112
|
# Model.count
|
106
|
-
# <tt>:
|
107
|
-
# <tt>:
|
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 +
|
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,
|
161
|
-
model.
|
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],
|
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
|
-
@
|
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[@
|
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
|
-
|
237
|
-
|
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
|
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
|
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.
|
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
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
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
|
-
|
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
|
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
|
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
|
-
|
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
|
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
|
-
|
131
|
-
(%r{^\w+\://[^/]+(/.*|$)$} =~
|
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[
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
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
|
-
|
151
|
+
ssl? ? 'https://' : 'http://'
|
144
152
|
end
|
145
153
|
|
146
154
|
# Is this an SSL request?
|
147
155
|
def ssl?
|
148
|
-
|
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
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
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(/(^\.$|^\/$)/, '')
|
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
|
-
(
|
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
|
-
|
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
|