actionpack 1.10.2 → 1.11.0
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 +57 -3
- data/README +7 -7
- data/lib/action_controller/assertions.rb +28 -11
- data/lib/action_controller/base.rb +22 -15
- data/lib/action_controller/caching.rb +6 -6
- data/lib/action_controller/components.rb +1 -1
- data/lib/action_controller/cookies.rb +3 -3
- data/lib/action_controller/dependencies.rb +1 -1
- data/lib/action_controller/filters.rb +40 -3
- data/lib/action_controller/flash.rb +4 -0
- data/lib/action_controller/helpers.rb +1 -1
- data/lib/action_controller/layout.rb +2 -1
- data/lib/action_controller/pagination.rb +2 -1
- data/lib/action_controller/rescue.rb +1 -1
- data/lib/action_controller/session/active_record_store.rb +18 -29
- data/lib/action_controller/templates/rescues/_trace.rhtml +0 -3
- data/lib/action_controller/templates/scaffolds/layout.rhtml +1 -1
- data/lib/action_controller/vendor/html-scanner/html/document.rb +2 -2
- data/lib/action_pack.rb +24 -0
- data/lib/action_pack/version.rb +2 -2
- data/lib/action_view/base.rb +1 -1
- data/lib/action_view/helpers/asset_tag_helper.rb +21 -3
- data/lib/action_view/helpers/form_options_helper.rb +1 -1
- data/lib/action_view/helpers/javascript_helper.rb +1 -0
- data/lib/action_view/helpers/javascripts/controls.js +18 -5
- data/lib/action_view/helpers/javascripts/dragdrop.js +6 -3
- data/lib/action_view/helpers/javascripts/effects.js +181 -290
- data/lib/action_view/helpers/javascripts/prototype.js +8 -8
- data/lib/action_view/helpers/text_helper.rb +22 -0
- data/lib/action_view/helpers/url_helper.rb +1 -1
- data/lib/action_view/template_error.rb +2 -1
- data/rakefile +1 -1
- data/test/controller/components_test.rb +5 -0
- data/test/controller/filters_test.rb +2 -1
- data/test/controller/flash_test.rb +6 -0
- data/test/controller/new_render_test.rb +11 -0
- data/test/controller/redirect_test.rb +10 -0
- data/test/fixtures/layouts/standard.rhtml +1 -1
- data/test/template/asset_tag_helper_test.rb +19 -2
- data/test/template/javascript_helper_test.rb +1 -0
- data/test/template/text_helper_test.rb +9 -0
- metadata +5 -4
- data/lib/action_view/helpers/javascripts/slider.js +0 -258
@@ -27,7 +27,7 @@ module ActionController #:nodoc:
|
|
27
27
|
# end
|
28
28
|
#
|
29
29
|
# Also note, that if the models follow the pattern of just 1 class per file in the form of MyClass => my_class.rb, then these
|
30
|
-
# classes
|
30
|
+
# classes don't have to be required as Active Support will auto-require them.
|
31
31
|
module ClassMethods
|
32
32
|
# Specifies a variable number of models that this controller depends on. Models are normally Active Record classes or a similar
|
33
33
|
# backend for modelling entity classes.
|
@@ -41,7 +41,7 @@ module ActionController #:nodoc:
|
|
41
41
|
#
|
42
42
|
# Now any actions performed on the BankController will have the audit method called before. On the VaultController,
|
43
43
|
# first the audit method is called, then the verify_credentials method. If the audit method returns false, then
|
44
|
-
# verify_credentials and the intended action
|
44
|
+
# verify_credentials and the intended action are never called.
|
45
45
|
#
|
46
46
|
# == Filter types
|
47
47
|
#
|
@@ -74,7 +74,7 @@ module ActionController #:nodoc:
|
|
74
74
|
#
|
75
75
|
# As you can see, the block expects to be passed the controller after it has assigned the request to the internal variables.
|
76
76
|
# This means that the block has access to both the request and response objects complete with convenience methods for params,
|
77
|
-
# session, template, and assigns. Note: The inline method doesn't strictly
|
77
|
+
# session, template, and assigns. Note: The inline method doesn't strictly have to be a block; any object that responds to call
|
78
78
|
# and returns 1 or -1 on arity will do (such as a Proc or an Method object).
|
79
79
|
#
|
80
80
|
# == Filter chain ordering
|
@@ -127,6 +127,25 @@ module ActionController #:nodoc:
|
|
127
127
|
# end
|
128
128
|
# end
|
129
129
|
#
|
130
|
+
# == Filter chain skipping
|
131
|
+
#
|
132
|
+
# Some times its convenient to specify a filter chain in a superclass that'll hold true for the majority of the
|
133
|
+
# subclasses, but not necessarily all of them. The subclasses that behave in exception can then specify which filters
|
134
|
+
# they would like to be relieved of. Examples
|
135
|
+
#
|
136
|
+
# class ApplicationController < ActionController::Base
|
137
|
+
# before_filter :authenticate
|
138
|
+
# end
|
139
|
+
#
|
140
|
+
# class WeblogController < ApplicationController
|
141
|
+
# # will run the :authenticate filter
|
142
|
+
# end
|
143
|
+
#
|
144
|
+
# class SignupController < ActionController::Base
|
145
|
+
# # will not run the :authenticate filter
|
146
|
+
# skip_before_filter :authenticate
|
147
|
+
# end
|
148
|
+
#
|
130
149
|
# == Filter conditions
|
131
150
|
#
|
132
151
|
# Filters can be limited to run for only specific actions. This can be expressed either by listing the actions to
|
@@ -143,7 +162,7 @@ module ActionController #:nodoc:
|
|
143
162
|
# end
|
144
163
|
# end
|
145
164
|
#
|
146
|
-
# When setting conditions on inline method (proc) filters the condition must come first and be placed in
|
165
|
+
# When setting conditions on inline method (proc) filters the condition must come first and be placed in parentheses.
|
147
166
|
#
|
148
167
|
# class UserPreferences < ActionController::Base
|
149
168
|
# before_filter(:except => :new) { # some proc ... }
|
@@ -229,6 +248,24 @@ module ActionController #:nodoc:
|
|
229
248
|
# Short-hand for append_around_filter since that's the most common of the two.
|
230
249
|
alias :around_filter :append_around_filter
|
231
250
|
|
251
|
+
# Removes the specified filters from the +before+ filter chain. Note that this only works for skipping method-reference
|
252
|
+
# filters, not procs. This is especially useful for managing the chain in inheritance hierarchies where only one out
|
253
|
+
# of many sub-controllers need a different hierarchy.
|
254
|
+
def skip_before_filter(*filters)
|
255
|
+
for filter in filters.flatten
|
256
|
+
write_inheritable_attribute("before_filters", read_inheritable_attribute("before_filters") - [ filter ])
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
# Removes the specified filters from the +after+ filter chain. Note that this only works for skipping method-reference
|
261
|
+
# filters, not procs. This is especially useful for managing the chain in inheritance hierarchies where only one out
|
262
|
+
# of many sub-controllers need a different hierarchy.
|
263
|
+
def skip_after_filter(*filters)
|
264
|
+
for filter in filters.flatten
|
265
|
+
write_inheritable_attribute("after_filters", read_inheritable_attribute("after_filters") - [ filter ])
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
232
269
|
# Returns all the before filters for this class and all its ancestors.
|
233
270
|
def before_filters #:nodoc:
|
234
271
|
read_inheritable_attribute("before_filters")
|
@@ -19,7 +19,7 @@ module ActionController #:nodoc:
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
-
# The template helpers
|
22
|
+
# The template helpers serve to relieve the templates from including the same inline code again and again. It's a
|
23
23
|
# set of standardized methods for working with forms (FormHelper), dates (DateHelper), texts (TextHelper), and
|
24
24
|
# Active Records (ActiveRecordHelper) that's available to all templates by default.
|
25
25
|
#
|
@@ -24,7 +24,7 @@ module ActionController #:nodoc:
|
|
24
24
|
# and if you ever want to change the structure of these two includes, you'll have to change all the templates.
|
25
25
|
#
|
26
26
|
# With layouts, you can flip it around and have the common structure know where to insert changing content. This means
|
27
|
-
# that the header and footer
|
27
|
+
# that the header and footer are only mentioned in one place, like this:
|
28
28
|
#
|
29
29
|
# <!-- The header part of this layout -->
|
30
30
|
# <%= @content_for_layout %>
|
@@ -219,6 +219,7 @@ module ActionController #:nodoc:
|
|
219
219
|
end
|
220
220
|
|
221
221
|
erase_render_results
|
222
|
+
add_variables_to_assigns
|
222
223
|
@template.instance_variable_set("@content_for_layout", content_for_layout)
|
223
224
|
render_text(@template.render_file(layout, true), deprecated_status)
|
224
225
|
else
|
@@ -49,7 +49,8 @@ module ActionController
|
|
49
49
|
# def list
|
50
50
|
# @person_pages = Paginator.new self, Person.count, 10, @params['page']
|
51
51
|
# @people = Person.find :all, :order => 'last_name, first_name',
|
52
|
-
#
|
52
|
+
# :limit => @person_pages.items_per_page,
|
53
|
+
# :offset => @person_pages.current.offset
|
53
54
|
# end
|
54
55
|
#
|
55
56
|
# Explicitly creates the paginator from the previous example and uses
|
@@ -56,7 +56,7 @@ module ActionController #:nodoc:
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
-
# Overwrite to expand the meaning of a local request in order to show local rescues on other
|
59
|
+
# Overwrite to expand the meaning of a local request in order to show local rescues on other occurrences than
|
60
60
|
# the remote IP being 127.0.0.1. For example, this could include the IP of the developer machine when debugging
|
61
61
|
# remotely.
|
62
62
|
def local_request? #:doc:
|
@@ -50,10 +50,10 @@ class CGI
|
|
50
50
|
class ActiveRecordStore
|
51
51
|
# The default Active Record class.
|
52
52
|
class Session < ActiveRecord::Base
|
53
|
+
before_update :loaded? # Don't try to save if we haven't loaded the session
|
53
54
|
before_save :marshal_data!
|
54
55
|
before_save :ensure_data_not_too_big
|
55
|
-
|
56
|
-
|
56
|
+
|
57
57
|
class << self
|
58
58
|
|
59
59
|
# Don't try to reload ARStore::Session in dev mode.
|
@@ -73,7 +73,6 @@ class CGI
|
|
73
73
|
|
74
74
|
def marshal(data) Base64.encode64(Marshal.dump(data)) end
|
75
75
|
def unmarshal(data) Marshal.load(Base64.decode64(data)) end
|
76
|
-
def fingerprint(data) Digest::MD5.hexdigest(data) end
|
77
76
|
|
78
77
|
def create_table!
|
79
78
|
connection.execute <<-end_sql
|
@@ -109,17 +108,14 @@ class CGI
|
|
109
108
|
end
|
110
109
|
end
|
111
110
|
|
112
|
-
# Lazy-unmarshal session state.
|
113
|
-
# whether to save changes later.
|
111
|
+
# Lazy-unmarshal session state.
|
114
112
|
def data
|
115
113
|
unless @data
|
116
|
-
case
|
114
|
+
case data = read_attribute('data')
|
117
115
|
when String
|
118
|
-
@
|
119
|
-
|
120
|
-
|
121
|
-
@data = {}
|
122
|
-
@fingerprint = nil
|
116
|
+
@data = self.class.unmarshal(data)
|
117
|
+
else
|
118
|
+
@data = data || {}
|
123
119
|
end
|
124
120
|
end
|
125
121
|
@data
|
@@ -127,12 +123,12 @@ class CGI
|
|
127
123
|
|
128
124
|
private
|
129
125
|
def marshal_data!
|
130
|
-
write_attribute('data', self.class.marshal(
|
126
|
+
write_attribute('data', self.class.marshal(self.data))
|
131
127
|
end
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
128
|
+
|
129
|
+
# Has the session been loaded yet?
|
130
|
+
def loaded?
|
131
|
+
!! @data
|
136
132
|
end
|
137
133
|
|
138
134
|
# Ensures that the data about to be stored in the database is not
|
@@ -188,7 +184,6 @@ class CGI
|
|
188
184
|
|
189
185
|
def marshal(data) Base64.encode64(Marshal.dump(data)) end
|
190
186
|
def unmarshal(data) Marshal.load(Base64.decode64(data)) end
|
191
|
-
def fingerprint(data) Digest::MD5.hexdigest(data) end
|
192
187
|
|
193
188
|
def create_table!
|
194
189
|
@@connection.execute <<-end_sql
|
@@ -220,16 +215,13 @@ class CGI
|
|
220
215
|
@new_record
|
221
216
|
end
|
222
217
|
|
223
|
-
# Lazy-unmarshal session state.
|
224
|
-
# whether to save changes later.
|
218
|
+
# Lazy-unmarshal session state.
|
225
219
|
def data
|
226
220
|
unless @data
|
227
221
|
if @marshaled_data
|
228
|
-
@fingerprint = self.class.fingerprint(@marshaled_data)
|
229
222
|
@data, @marshaled_data = self.class.unmarshal(@marshaled_data), nil
|
230
223
|
else
|
231
224
|
@data = {}
|
232
|
-
@fingerprint = nil
|
233
225
|
end
|
234
226
|
end
|
235
227
|
@data
|
@@ -249,14 +241,11 @@ class CGI
|
|
249
241
|
#{@@connection.quote(marshaled_data)} )
|
250
242
|
end_sql
|
251
243
|
else
|
252
|
-
|
253
|
-
|
254
|
-
@@connection.
|
255
|
-
|
256
|
-
|
257
|
-
WHERE #{@@connection.quote_column_name(@@session_id_column)}=#{@@connection.quote(session_id)}
|
258
|
-
end_sql
|
259
|
-
end
|
244
|
+
@@connection.update <<-end_sql, 'Update session'
|
245
|
+
UPDATE #{@@table_name}
|
246
|
+
SET #{@@connection.quote_column_name(@@data_column)}=#{@@connection.quote(marshaled_data)}
|
247
|
+
WHERE #{@@connection.quote_column_name(@@session_id_column)}=#{@@connection.quote(session_id)}
|
248
|
+
end_sql
|
260
249
|
end
|
261
250
|
end
|
262
251
|
|
@@ -4,9 +4,6 @@
|
|
4
4
|
["Framework Trace", @exception.framework_backtrace],
|
5
5
|
["Full Trace", @exception.clean_backtrace]
|
6
6
|
]
|
7
|
-
if defined?(RAILS_ROOT)
|
8
|
-
traces.each { |name, trace| trace.map! { |p| p.gsub(/^#{RAILS_ROOT}/, '<b>#{RAILS_ROOT}</b>') } }
|
9
|
-
end
|
10
7
|
names = traces.collect {|name, trace| name}
|
11
8
|
%>
|
12
9
|
|
data/lib/action_pack.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2004 David Heinemeier Hansson
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
require 'action_pack/version'
|
data/lib/action_pack/version.rb
CHANGED
data/lib/action_view/base.rb
CHANGED
@@ -122,7 +122,7 @@ module ActionView #:nodoc:
|
|
122
122
|
attr_accessor :base_path, :assigns, :template_extension
|
123
123
|
attr_accessor :controller
|
124
124
|
|
125
|
-
attr_reader :logger, :params, :response, :session, :headers, :flash
|
125
|
+
attr_reader :logger, :params, :request, :response, :session, :headers, :flash
|
126
126
|
|
127
127
|
# Specify trim mode for the ERB compiler. Defaults to '-'.
|
128
128
|
# See ERB documentation for suitable values.
|
@@ -35,6 +35,9 @@ module ActionView
|
|
35
35
|
compute_public_path(source, 'javascripts', 'js')
|
36
36
|
end
|
37
37
|
|
38
|
+
JAVASCRIPT_DEFAULT_SOURCES = ['prototype', 'effects', 'dragdrop', 'controls']
|
39
|
+
@@javascript_default_sources = JAVASCRIPT_DEFAULT_SOURCES.dup
|
40
|
+
|
38
41
|
# Returns a script include tag per source given as argument. Examples:
|
39
42
|
#
|
40
43
|
# javascript_include_tag "xmlhr" # =>
|
@@ -46,8 +49,9 @@ module ActionView
|
|
46
49
|
#
|
47
50
|
# javascript_include_tag :defaults # =>
|
48
51
|
# <script type="text/javascript" src="/javascripts/prototype.js"></script>
|
49
|
-
# <script type="text/javascript" src="/javascripts/
|
50
|
-
#
|
52
|
+
# <script type="text/javascript" src="/javascripts/effects.js"></script>
|
53
|
+
# ...
|
54
|
+
# <script type="text/javascript" src="/javascripts/application.js"></script> *see below
|
51
55
|
#
|
52
56
|
# If there's an <tt>application.js</tt> file in your <tt>public/javascripts</tt> directory,
|
53
57
|
# <tt>javascript_include_tag :defaults</tt> will automatically include it. This file
|
@@ -56,7 +60,7 @@ module ActionView
|
|
56
60
|
def javascript_include_tag(*sources)
|
57
61
|
options = sources.last.is_a?(Hash) ? sources.pop.stringify_keys : { }
|
58
62
|
if sources.first == :defaults
|
59
|
-
sources =
|
63
|
+
sources = @@javascript_default_sources
|
60
64
|
if defined?(RAILS_ROOT) and File.exists?("#{RAILS_ROOT}/public/javascripts/application.js")
|
61
65
|
sources << 'application'
|
62
66
|
end
|
@@ -66,6 +70,20 @@ module ActionView
|
|
66
70
|
content_tag("script", "", { "type" => "text/javascript", "src" => source }.merge(options))
|
67
71
|
}.join("\n")
|
68
72
|
end
|
73
|
+
|
74
|
+
# Register one or more additional JavaScript files to be included when
|
75
|
+
#
|
76
|
+
# javascript_include_tag :defaults
|
77
|
+
#
|
78
|
+
# is called. This method is intended to be called only from plugin initialization
|
79
|
+
# to register extra .js files the plugin installed in <tt>public/javascripts</tt>.
|
80
|
+
def self.register_javascript_include_default(*sources)
|
81
|
+
@@javascript_default_sources.concat(sources)
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.reset_javascript_include_default #:nodoc:
|
85
|
+
@@javascript_default_sources = JAVASCRIPT_DEFAULT_SOURCES.dup
|
86
|
+
end
|
69
87
|
|
70
88
|
# Returns path to a stylesheet asset. Example:
|
71
89
|
#
|
@@ -146,7 +146,7 @@ module ActionView
|
|
146
146
|
# Returns a string of option tags, like options_from_collection_for_select, but surrounds them with <optgroup> tags.
|
147
147
|
#
|
148
148
|
# An array of group objects are passed. Each group should return an array of options when calling group_method
|
149
|
-
# Each group should
|
149
|
+
# Each group should return its name when calling group_label_method.
|
150
150
|
#
|
151
151
|
# html_option_groups_from_collection(@continents, "countries", "continent_name", "country_id", "country_name", @selected_country.id)
|
152
152
|
#
|
@@ -377,6 +377,7 @@ module ActionView
|
|
377
377
|
# http://script.aculo.us for more documentation.
|
378
378
|
def visual_effect(name, element_id = false, js_options = {})
|
379
379
|
element = element_id ? "'#{element_id}'" : "element"
|
380
|
+
js_options[:queue] = "'#{js_options[:queue]}'" if js_options[:queue]
|
380
381
|
"new Effect.#{name.to_s.camelize}(#{element},#{options_for_javascript(js_options)});"
|
381
382
|
end
|
382
383
|
|
@@ -184,7 +184,10 @@ Autocompleter.Base.prototype = {
|
|
184
184
|
this.show();
|
185
185
|
this.active = true;
|
186
186
|
}
|
187
|
-
} else
|
187
|
+
} else {
|
188
|
+
this.active = false;
|
189
|
+
this.hide();
|
190
|
+
}
|
188
191
|
},
|
189
192
|
|
190
193
|
markPrevious: function() {
|
@@ -425,6 +428,15 @@ Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), {
|
|
425
428
|
//
|
426
429
|
// see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor
|
427
430
|
|
431
|
+
// Use this if you notice weird scrolling problems on some browsers,
|
432
|
+
// the DOM might be a bit confused when this gets called so do this
|
433
|
+
// waits 1 ms (with setTimeout) until it does the activation
|
434
|
+
Field.scrollFreeActivate = function(field) {
|
435
|
+
setTimeout(function() {
|
436
|
+
Field.activate(field);
|
437
|
+
}, 1);
|
438
|
+
}
|
439
|
+
|
428
440
|
Ajax.InPlaceEditor = Class.create();
|
429
441
|
Ajax.InPlaceEditor.defaultHighlightColor = "#FFFF99";
|
430
442
|
Ajax.InPlaceEditor.prototype = {
|
@@ -490,7 +502,7 @@ Ajax.InPlaceEditor.prototype = {
|
|
490
502
|
Event.observe(this.options.externalControl, 'mouseout', this.mouseoutListener);
|
491
503
|
}
|
492
504
|
},
|
493
|
-
enterEditMode: function() {
|
505
|
+
enterEditMode: function(evt) {
|
494
506
|
if (this.saving) return;
|
495
507
|
if (this.editing) return;
|
496
508
|
this.editing = true;
|
@@ -501,11 +513,12 @@ Ajax.InPlaceEditor.prototype = {
|
|
501
513
|
Element.hide(this.element);
|
502
514
|
this.createForm();
|
503
515
|
this.element.parentNode.insertBefore(this.form, this.element);
|
504
|
-
Field.
|
516
|
+
Field.scrollFreeActivate(this.editField);
|
505
517
|
// stop the event to avoid a page refresh in Safari
|
506
|
-
if (
|
507
|
-
Event.stop(
|
518
|
+
if (evt) {
|
519
|
+
Event.stop(evt);
|
508
520
|
}
|
521
|
+
return false;
|
509
522
|
},
|
510
523
|
createForm: function() {
|
511
524
|
this.form = document.createElement("form");
|