Commit b9846d60741788e84c889077d9b3b4786ba31042
1 parent
0088a8d8
Exists in
master
and in
29 other branches
ActionItem135: upgrading to rails 1.2.6; all tests pass
git-svn-id: https://svn.colivre.coop.br/svn/noosfero/trunk@1103 3f533792-8f58-4932-b0fe-aaf55b0a4547
Showing
127 changed files
with
2801 additions
and
565 deletions
Show diff stats
Too many changes.
To preserve performance only 100 of 127 files displayed.
vendor/rails/actionmailer/CHANGELOG
1 | +*1.3.6* (October 12th, 2007) | |
2 | + | |
3 | +* Depend on Action Pack 1.13.6 | |
4 | + | |
5 | +*1.3.5* (October 12th, 2007) | |
6 | + | |
7 | +* Depend on Action Pack 1.13.5 | |
8 | + | |
9 | + | |
10 | +*1.3.4* (October 4th, 2007) | |
11 | + | |
12 | +* Depend on Action Pack 1.13.4 | |
13 | + | |
14 | + | |
1 | 15 | *1.3.3* (March 12th, 2007) |
2 | 16 | |
3 | 17 | * Depend on Action Pack 1.13.3 | ... | ... |
vendor/rails/actionmailer/Rakefile
... | ... | @@ -54,7 +54,7 @@ spec = Gem::Specification.new do |s| |
54 | 54 | s.rubyforge_project = "actionmailer" |
55 | 55 | s.homepage = "http://www.rubyonrails.org" |
56 | 56 | |
57 | - s.add_dependency('actionpack', '= 1.13.3' + PKG_BUILD) | |
57 | + s.add_dependency('actionpack', '= 1.13.6' + PKG_BUILD) | |
58 | 58 | |
59 | 59 | s.has_rdoc = true |
60 | 60 | s.requirements << 'none' | ... | ... |
vendor/rails/actionmailer/lib/action_mailer/version.rb
vendor/rails/actionpack/CHANGELOG
1 | +*1.13.6* (November 24th, 2007) | |
2 | + | |
3 | +* Correct Broken Fix for session_fixation attacks | |
4 | + | |
5 | +* Ensure that cookies handle array values correctly. Closes #9937 [queso] | |
6 | + | |
7 | +*1.13.5* (October 12th, 2007) | |
8 | + | |
9 | +* Backport: allow array and hash query parameters. Array route parameters are converted/to/a/path as before. #6765, #7047, #7462 [bgipsy, Jeremy McAnally, Dan Kubb, brendan, Diego Algorta Casamayou] | |
10 | + | |
11 | +* Fix in place editor's setter action with non-string fields. #7418 [Andreas] | |
12 | + | |
13 | + | |
14 | +*1.13.4* (October 4th, 2007) | |
15 | + | |
16 | +* Only accept session ids from cookies, prevents session fixation attacks. [bradediger] | |
17 | + | |
18 | +* Change the resource seperator from ; to / change the generated routes to use the new-style named routes. e.g. new_group_user_path(@group) instead of group_new_user_path(@group). [pixeltrix] | |
19 | + | |
20 | +* Integration tests: introduce methods for other HTTP methods. #6353 [caboose] | |
21 | + | |
22 | +* Improve performance of action caching. Closes #8231 [skaes] | |
23 | + | |
24 | +* Fix errors with around_filters which do not yield, restore 1.1 behaviour with after filters. Closes #8891 [skaes] | |
25 | + | |
26 | + After filters will *no longer* be run if an around_filter fails to yield, users relying on | |
27 | + this behaviour are advised to put the code in question after a yield statement in an around filter. | |
28 | + | |
29 | +* Allow you to delete cookies with options. Closes #3685 [josh, Chris Wanstrath] | |
30 | + | |
31 | +* Deprecate pagination. Install the classic_pagination plugin for forward compatibility, or move to the superior will_paginate plugin. #8157 [Mislav Marohnic] | |
32 | + | |
33 | +* Fix filtered parameter logging with nil parameter values. #8422 [choonkeat] | |
34 | + | |
35 | +* Integration tests: alias xhr to xml_http_request and add a request_method argument instead of always using POST. #7124 [Nik Wakelin, Francois Beausoleil, Wizard] | |
36 | + | |
37 | +* Document caches_action. #5419 [Jarkko Laine] | |
38 | + | |
39 | +* observe_form always sends the serialized form. #5271 [manfred, normelton@gmail.com] | |
40 | + | |
41 | +* Update UrlWriter to accept :anchor parameter. Closes #6771. [octopod] | |
42 | + | |
43 | +* Replace the current block/continuation filter chain handling by an implementation based on a simple loop. Closes #8226 [Stefan Kaes] | |
44 | + | |
45 | +* Return the string representation from an Xml Builder when rendering a partial. #5044 [tpope] | |
46 | + | |
47 | +* Cleaned up, corrected, and mildly expanded ActionPack documentation. Closes #7190 [jeremymcanally] | |
48 | + | |
49 | +* Small collection of ActionController documentation cleanups. Closes #7319 [jeremymcanally] | |
50 | + | |
51 | +* Performance: patch cgi/session/pstore to require digest/md5 once rather than per #initialize. #7583 [Stefan Kaes] | |
52 | + | |
53 | +* Deprecation: verification with :redirect_to => :named_route shouldn't be deprecated. #7525 [Justin French] | |
54 | + | |
55 | + | |
1 | 56 | *1.13.3* (March 12th, 2007) |
2 | 57 | |
3 | -* Apply [5709] to stable. | |
58 | +* Fix a bug in Routing where a parameter taken from the path of the current request could not be used as a query parameter for the next. #6752 [Nicholas Seckar] | |
4 | 59 | |
5 | 60 | * session_enabled? works with session :off. #6680 [Catfish] |
6 | 61 | |
... | ... | @@ -440,7 +495,7 @@ |
440 | 495 | |
441 | 496 | * Avoid naming collision among compiled view methods. [Jeremy Kemper] |
442 | 497 | |
443 | -* Fix CGI extensions when they expect string but get nil in Windows. Closes #5276 [mislav@nippur.irb.hr] | |
498 | +* Fix CGI extensions when they expect string but get nil in Windows. Closes #5276 [Mislav Marohnic] | |
444 | 499 | |
445 | 500 | * Determine the correct template_root for deeply nested components. #2841 [s.brink@web.de] |
446 | 501 | ... | ... |
vendor/rails/actionpack/Rakefile
... | ... | @@ -75,7 +75,7 @@ spec = Gem::Specification.new do |s| |
75 | 75 | s.has_rdoc = true |
76 | 76 | s.requirements << 'none' |
77 | 77 | |
78 | - s.add_dependency('activesupport', '= 1.4.2' + PKG_BUILD) | |
78 | + s.add_dependency('activesupport', '= 1.4.4' + PKG_BUILD) | |
79 | 79 | |
80 | 80 | s.require_path = 'lib' |
81 | 81 | s.autorequire = 'action_controller' | ... | ... |
vendor/rails/actionpack/examples/address_book_controller.cgi
vendor/rails/actionpack/examples/address_book_controller.fcgi
vendor/rails/actionpack/examples/address_book_controller.rbx
vendor/rails/actionpack/examples/benchmark_with_ar.fcgi
vendor/rails/actionpack/examples/blog_controller.cgi
vendor/rails/actionpack/examples/debate_controller.cgi
vendor/rails/actionpack/lib/action_controller/assertions/dom_assertions.rb
1 | 1 | module ActionController |
2 | 2 | module Assertions |
3 | 3 | module DomAssertions |
4 | - # test 2 html strings to be equivalent, i.e. identical up to reordering of attributes | |
4 | + # Test two HTML strings for equivalency (e.g., identical up to reordering of attributes) | |
5 | 5 | def assert_dom_equal(expected, actual, message="") |
6 | 6 | clean_backtrace do |
7 | 7 | expected_dom = HTML::Document.new(expected).root |
... | ... | @@ -11,7 +11,7 @@ module ActionController |
11 | 11 | end |
12 | 12 | end |
13 | 13 | |
14 | - # negated form of +assert_dom_equivalent+ | |
14 | + # The negated form of +assert_dom_equivalent+. | |
15 | 15 | def assert_dom_not_equal(expected, actual, message="") |
16 | 16 | clean_backtrace do |
17 | 17 | expected_dom = HTML::Document.new(expected).root | ... | ... |
vendor/rails/actionpack/lib/action_controller/assertions/model_assertions.rb
1 | 1 | module ActionController |
2 | 2 | module Assertions |
3 | 3 | module ModelAssertions |
4 | - # ensures that the passed record is valid by active record standards. returns the error messages if not | |
4 | + # Ensures that the passed record is valid by ActiveRecord standards and returns any error messages if it is not. | |
5 | 5 | def assert_valid(record) |
6 | 6 | clean_backtrace do |
7 | 7 | assert record.valid?, record.errors.full_messages.join("\n") | ... | ... |
vendor/rails/actionpack/lib/action_controller/assertions/response_assertions.rb
... | ... | @@ -69,6 +69,7 @@ module ActionController |
69 | 69 | end |
70 | 70 | |
71 | 71 | if value.respond_to?(:[]) && value['controller'] |
72 | + value['controller'] = value['controller'].to_s | |
72 | 73 | if key == :actual && value['controller'].first != '/' && !value['controller'].include?('/') |
73 | 74 | new_controller_path = ActionController::Routing.controller_relative_to(value['controller'], @controller.class.controller_path) |
74 | 75 | value['controller'] = new_controller_path if value['controller'] != new_controller_path && ActionController::Routing.possible_controllers.include?(new_controller_path) |
... | ... | @@ -120,6 +121,7 @@ module ActionController |
120 | 121 | end |
121 | 122 | |
122 | 123 | private |
124 | + # Recognizes the route for a given path. | |
123 | 125 | def recognized_request_for(path, request_method = nil) |
124 | 126 | path = "/#{path}" unless path.first == '/' |
125 | 127 | |
... | ... | @@ -132,6 +134,7 @@ module ActionController |
132 | 134 | request |
133 | 135 | end |
134 | 136 | |
137 | + # Proxy to to_param if the object will respond to it. | |
135 | 138 | def parameterize(value) |
136 | 139 | value.respond_to?(:to_param) ? value.to_param : value |
137 | 140 | end | ... | ... |
vendor/rails/actionpack/lib/action_controller/assertions/routing_assertions.rb
vendor/rails/actionpack/lib/action_controller/assertions/selector_assertions.rb
... | ... | @@ -561,6 +561,8 @@ module ActionController |
561 | 561 | # RJS encodes double quotes and line breaks. |
562 | 562 | unescaped= rjs_string.gsub('\"', '"') |
563 | 563 | unescaped.gsub!('\n', "\n") |
564 | + unescaped.gsub!('\076', '>') | |
565 | + unescaped.gsub!('\074', '<') | |
564 | 566 | # RJS encodes non-ascii characters. |
565 | 567 | unescaped.gsub!(RJS_PATTERN_UNICODE_ESCAPED_CHAR) {|u| [$1.hex].pack('U*')} |
566 | 568 | unescaped | ... | ... |
vendor/rails/actionpack/lib/action_controller/base.rb
... | ... | @@ -292,6 +292,10 @@ module ActionController #:nodoc: |
292 | 292 | # Turn on +ignore_missing_templates+ if you want to unit test actions without making the associated templates. |
293 | 293 | cattr_accessor :ignore_missing_templates |
294 | 294 | |
295 | + # Controls the resource action separator | |
296 | + @@resource_action_separator = "/" | |
297 | + cattr_accessor :resource_action_separator | |
298 | + | |
295 | 299 | # Holds the request object that's primarily used to get environment variables through access like |
296 | 300 | # <tt>request.env["REQUEST_URI"]</tt>. |
297 | 301 | attr_internal :request |
... | ... | @@ -393,7 +397,8 @@ module ActionController #:nodoc: |
393 | 397 | elsif value.is_a?(Hash) |
394 | 398 | filtered_parameters[key] = filter_parameters(value) |
395 | 399 | elsif block_given? |
396 | - key, value = key.dup, value.dup | |
400 | + key = key.dup | |
401 | + value = value.dup if value | |
397 | 402 | yield key, value |
398 | 403 | filtered_parameters[key] = value |
399 | 404 | else |
... | ... | @@ -538,6 +543,7 @@ module ActionController #:nodoc: |
538 | 543 | self.class.controller_path |
539 | 544 | end |
540 | 545 | |
546 | + # Test whether the session is enabled for this request. | |
541 | 547 | def session_enabled? |
542 | 548 | request.session_options && request.session_options[:disabled] != false |
543 | 549 | end | ... | ... |
vendor/rails/actionpack/lib/action_controller/caching.rb
1 | 1 | require 'fileutils' |
2 | 2 | require 'uri' |
3 | +require 'set' | |
3 | 4 | |
4 | 5 | module ActionController #:nodoc: |
5 | 6 | # Caching is a cheap way of speeding up slow applications by keeping the result of calculations, renderings, and database calls |
... | ... | @@ -163,13 +164,24 @@ module ActionController #:nodoc: |
163 | 164 | module Actions |
164 | 165 | def self.included(base) #:nodoc: |
165 | 166 | base.extend(ClassMethods) |
166 | - base.send(:attr_accessor, :rendered_action_cache) | |
167 | + base.class_eval do | |
168 | + attr_accessor :rendered_action_cache, :action_cache_path | |
169 | + alias_method_chain :protected_instance_variables, :action_caching | |
170 | + end | |
167 | 171 | end |
168 | 172 | |
169 | - module ClassMethods #:nodoc: | |
173 | + def protected_instance_variables_with_action_caching | |
174 | + protected_instance_variables_without_action_caching + %w(@action_cache_path) | |
175 | + end | |
176 | + | |
177 | + module ClassMethods | |
178 | + # Declares that +actions+ should be cached. | |
179 | + # See ActionController::Caching::Actions for details. | |
170 | 180 | def caches_action(*actions) |
171 | 181 | return unless perform_caching |
172 | - around_filter(ActionCacheFilter.new(*actions)) | |
182 | + action_cache_filter = ActionCacheFilter.new(*actions) | |
183 | + before_filter action_cache_filter | |
184 | + after_filter action_cache_filter | |
173 | 185 | end |
174 | 186 | end |
175 | 187 | |
... | ... | @@ -185,70 +197,59 @@ module ActionController #:nodoc: |
185 | 197 | end |
186 | 198 | |
187 | 199 | class ActionCacheFilter #:nodoc: |
188 | - def initialize(*actions, &block) | |
189 | - @actions = actions | |
200 | + def initialize(*actions) | |
201 | + @actions = Set.new actions | |
190 | 202 | end |
191 | 203 | |
192 | 204 | def before(controller) |
193 | - return unless @actions.include?(controller.action_name.intern) | |
194 | - action_cache_path = ActionCachePath.new(controller) | |
195 | - if cache = controller.read_fragment(action_cache_path.path) | |
205 | + return unless @actions.include?(controller.action_name.to_sym) | |
206 | + cache_path = ActionCachePath.new(controller, {}) | |
207 | + if cache = controller.read_fragment(cache_path.path) | |
196 | 208 | controller.rendered_action_cache = true |
197 | - set_content_type!(action_cache_path) | |
209 | + set_content_type!(controller, cache_path.extension) | |
198 | 210 | controller.send(:render_text, cache) |
199 | 211 | false |
212 | + else | |
213 | + controller.action_cache_path = cache_path | |
200 | 214 | end |
201 | 215 | end |
202 | 216 | |
203 | 217 | def after(controller) |
204 | - return if !@actions.include?(controller.action_name.intern) || controller.rendered_action_cache | |
205 | - controller.write_fragment(ActionCachePath.path_for(controller), controller.response.body) | |
218 | + return if !@actions.include?(controller.action_name.to_sym) || controller.rendered_action_cache | |
219 | + controller.write_fragment(controller.action_cache_path.path, controller.response.body) | |
206 | 220 | end |
207 | 221 | |
208 | 222 | private |
209 | - | |
210 | - def set_content_type!(action_cache_path) | |
211 | - if extention = action_cache_path.extension | |
212 | - content_type = Mime::EXTENSION_LOOKUP[extention] | |
213 | - action_cache_path.controller.response.content_type = content_type.to_s | |
214 | - end | |
223 | + def set_content_type!(controller, extension) | |
224 | + controller.response.content_type = Mime::EXTENSION_LOOKUP[extension].to_s if extension | |
215 | 225 | end |
216 | 226 | |
217 | 227 | end |
218 | 228 | |
219 | 229 | class ActionCachePath |
220 | - attr_reader :controller, :options | |
230 | + attr_reader :path, :extension | |
221 | 231 | |
222 | 232 | class << self |
223 | - def path_for(*args, &block) | |
224 | - new(*args).path | |
233 | + def path_for(controller, options) | |
234 | + new(controller, options).path | |
225 | 235 | end |
226 | 236 | end |
227 | 237 | |
228 | 238 | def initialize(controller, options = {}) |
229 | - @controller = controller | |
230 | - @options = options | |
231 | - end | |
232 | - | |
233 | - def path | |
234 | - return @path if @path | |
235 | - @path = controller.url_for(options).split('://').last | |
236 | - normalize! | |
237 | - add_extension! | |
238 | - URI.unescape(@path) | |
239 | - end | |
240 | - | |
241 | - def extension | |
242 | - @extension ||= extract_extension(controller.request.path) | |
239 | + @extension = extract_extension(controller.request.path) | |
240 | + path = controller.url_for(options).split('://').last | |
241 | + normalize!(path) | |
242 | + add_extension!(path, @extension) | |
243 | + @path = URI.unescape(path) | |
243 | 244 | end |
244 | 245 | |
245 | 246 | private |
246 | - def normalize! | |
247 | - @path << 'index' if @path.last == '/' | |
247 | + def normalize!(path) | |
248 | + path << 'index' if path[-1] == ?/ | |
248 | 249 | end |
249 | 250 | |
250 | - def add_extension! | |
251 | - @path << ".#{extension}" if extension | |
251 | + def add_extension!(path, extension) | |
252 | + path << ".#{extension}" if extension | |
252 | 253 | end |
253 | 254 | |
254 | 255 | def extract_extension(file_path) | ... | ... |
vendor/rails/actionpack/lib/action_controller/cgi_ext/pstore_performance_fix.rb
0 → 100644
... | ... | @@ -0,0 +1,30 @@ |
1 | +# CGI::Session::PStore.initialize requires 'digest/md5' on every call. | |
2 | +# This makes sense when spawning processes per request, but is | |
3 | +# unnecessarily expensive when serving requests from a long-lived | |
4 | +# process. | |
5 | +require 'cgi/session' | |
6 | +require 'cgi/session/pstore' | |
7 | +require 'digest/md5' | |
8 | + | |
9 | +class CGI::Session::PStore #:nodoc: | |
10 | + def initialize(session, option={}) | |
11 | + dir = option['tmpdir'] || Dir::tmpdir | |
12 | + prefix = option['prefix'] || '' | |
13 | + id = session.session_id | |
14 | + md5 = Digest::MD5.hexdigest(id)[0,16] | |
15 | + path = dir+"/"+prefix+md5 | |
16 | + path.untaint | |
17 | + if File::exist?(path) | |
18 | + @hash = nil | |
19 | + else | |
20 | + unless session.new_session | |
21 | + raise CGI::Session::NoSession, "uninitialized session" | |
22 | + end | |
23 | + @hash = {} | |
24 | + end | |
25 | + @p = ::PStore.new(path) | |
26 | + @p.transaction do |p| | |
27 | + File.chmod(0600, p.path) | |
28 | + end | |
29 | + end | |
30 | +end | ... | ... |
vendor/rails/actionpack/lib/action_controller/cgi_ext/raw_post_data_fix.rb
vendor/rails/actionpack/lib/action_controller/cgi_process.rb
... | ... | @@ -2,6 +2,7 @@ require 'action_controller/cgi_ext/cgi_ext' |
2 | 2 | require 'action_controller/cgi_ext/cookie_performance_fix' |
3 | 3 | require 'action_controller/cgi_ext/raw_post_data_fix' |
4 | 4 | require 'action_controller/cgi_ext/session_performance_fix' |
5 | +require 'action_controller/cgi_ext/pstore_performance_fix' | |
5 | 6 | |
6 | 7 | module ActionController #:nodoc: |
7 | 8 | class Base |
... | ... | @@ -12,8 +13,8 @@ module ActionController #:nodoc: |
12 | 13 | # (default). Additionally, there is CGI::Session::DRbStore and CGI::Session::ActiveRecordStore. Read more about these in |
13 | 14 | # lib/action_controller/session. |
14 | 15 | # * <tt>:session_key</tt> - the parameter name used for the session id. Defaults to '_session_id'. |
15 | - # * <tt>:session_id</tt> - the session id to use. If not provided, then it is retrieved from the +session_key+ parameter | |
16 | - # of the request, or automatically generated for a new session. | |
16 | + # * <tt>:session_id</tt> - the session id to use. If not provided, then it is retrieved from the +session_key+ cookie, or | |
17 | + # automatically generated for a new session. | |
17 | 18 | # * <tt>:new_session</tt> - if true, force creation of a new session. If not set, a new session is only created if none currently |
18 | 19 | # exists. If false, a new session is never created, and if none currently exists and the +session_id+ option is not set, |
19 | 20 | # an ArgumentError is raised. |
... | ... | @@ -23,6 +24,8 @@ module ActionController #:nodoc: |
23 | 24 | # server. |
24 | 25 | # * <tt>:session_secure</tt> - if +true+, this session will only work over HTTPS. |
25 | 26 | # * <tt>:session_path</tt> - the path for which this session applies. Defaults to the directory of the CGI script. |
27 | + # * <tt>:cookie_only</tt> - if +true+ (the default), session IDs will only be accepted from cookies and not from | |
28 | + # the query string or POST parameters. This protects against session fixation attacks. | |
26 | 29 | def self.process_cgi(cgi = CGI.new, session_options = {}) |
27 | 30 | new.process_cgi(cgi, session_options) |
28 | 31 | end |
... | ... | @@ -34,11 +37,14 @@ module ActionController #:nodoc: |
34 | 37 | |
35 | 38 | class CgiRequest < AbstractRequest #:nodoc: |
36 | 39 | attr_accessor :cgi, :session_options |
40 | + class SessionFixationAttempt < StandardError; end #:nodoc: | |
37 | 41 | |
38 | 42 | DEFAULT_SESSION_OPTIONS = { |
39 | 43 | :database_manager => CGI::Session::PStore, |
40 | 44 | :prefix => "ruby_sess.", |
41 | - :session_path => "/" | |
45 | + :session_path => "/", | |
46 | + :session_key => "_session_id", | |
47 | + :cookie_only => true | |
42 | 48 | } unless const_defined?(:DEFAULT_SESSION_OPTIONS) |
43 | 49 | |
44 | 50 | def initialize(cgi, session_options = {}) |
... | ... | @@ -48,6 +54,10 @@ module ActionController #:nodoc: |
48 | 54 | super() |
49 | 55 | end |
50 | 56 | |
57 | + def cookie_only? | |
58 | + session_options_with_string_keys['cookie_only'] | |
59 | + end | |
60 | + | |
51 | 61 | def query_string |
52 | 62 | if (qs = @cgi.query_string) && !qs.empty? |
53 | 63 | qs |
... | ... | @@ -108,6 +118,9 @@ module ActionController #:nodoc: |
108 | 118 | @session = Hash.new |
109 | 119 | else |
110 | 120 | stale_session_check! do |
121 | + if cookie_only? && request_parameters[session_options_with_string_keys['session_key']] | |
122 | + raise SessionFixationAttempt | |
123 | + end | |
111 | 124 | case value = session_options_with_string_keys['new_session'] |
112 | 125 | when true |
113 | 126 | @session = new_session | ... | ... |
vendor/rails/actionpack/lib/action_controller/cookies.rb
... | ... | @@ -47,7 +47,10 @@ module ActionController #:nodoc: |
47 | 47 | # Returns the value of the cookie by +name+ -- or nil if no such cookie exists. You set new cookies using either the cookie method |
48 | 48 | # or cookies[]= (for simple name/value cookies without options). |
49 | 49 | def [](name) |
50 | - @cookies[name.to_s].value.first if @cookies[name.to_s] && @cookies[name.to_s].respond_to?(:value) | |
50 | + cookie = @cookies[name.to_s] | |
51 | + if cookie && cookie.respond_to?(:value) | |
52 | + cookie.size > 1 ? cookie.value : cookie.value.to_s | |
53 | + end | |
51 | 54 | end |
52 | 55 | |
53 | 56 | def []=(name, options) |
... | ... | @@ -62,9 +65,11 @@ module ActionController #:nodoc: |
62 | 65 | end |
63 | 66 | |
64 | 67 | # Removes the cookie on the client machine by setting the value to an empty string |
65 | - # and setting its expiration date into the past | |
66 | - def delete(name) | |
67 | - set_cookie("name" => name.to_s, "value" => "", "expires" => Time.at(0)) | |
68 | + # and setting its expiration date into the past. Like []=, you can pass in an options | |
69 | + # hash to delete cookies with extra data such as a +path+. | |
70 | + def delete(name, options = {}) | |
71 | + options.stringify_keys! | |
72 | + set_cookie(options.merge("name" => name.to_s, "value" => "", "expires" => Time.at(0))) | |
68 | 73 | end |
69 | 74 | |
70 | 75 | private | ... | ... |
vendor/rails/actionpack/lib/action_controller/filters.rb
... | ... | @@ -214,9 +214,10 @@ module ActionController #:nodoc: |
214 | 214 | # == Filter Chain Halting |
215 | 215 | # |
216 | 216 | # <tt>before_filter</tt> and <tt>around_filter</tt> may halt the request |
217 | - # before controller action is run. This is useful, for example, to deny | |
217 | + # before a controller action is run. This is useful, for example, to deny | |
218 | 218 | # access to unauthenticated users or to redirect from http to https. |
219 | 219 | # Simply return false from the filter or call render or redirect. |
220 | + # After filters will not be executed if the filter chain is halted. | |
220 | 221 | # |
221 | 222 | # Around filters halt the request unless the action block is called. |
222 | 223 | # Given these filters |
... | ... | @@ -238,12 +239,12 @@ module ActionController #:nodoc: |
238 | 239 | # . . / |
239 | 240 | # . #around (code after yield) |
240 | 241 | # . / |
241 | - # #after (actual filter code is run) | |
242 | + # #after (actual filter code is run, unless the around filter does not yield) | |
242 | 243 | # |
243 | - # If #around returns before yielding, only #after will be run. The #before | |
244 | - # filter and controller action will not be run. If #before returns false, | |
245 | - # the second half of #around and all of #after will still run but the | |
246 | - # action will not. | |
244 | + # If #around returns before yielding, #after will still not be run. The #before | |
245 | + # filter and controller action will not be run. If #before returns false, | |
246 | + # the second half of #around and will still run but #after and the | |
247 | + # action will not. If #around does not yield, #after will not be run. | |
247 | 248 | module ClassMethods |
248 | 249 | # The passed <tt>filters</tt> will be appended to the filter_chain and |
249 | 250 | # will execute before the action on this controller is performed. |
... | ... | @@ -263,13 +264,13 @@ module ActionController #:nodoc: |
263 | 264 | # The passed <tt>filters</tt> will be appended to the array of filters |
264 | 265 | # that run _after_ actions on this controller are performed. |
265 | 266 | def append_after_filter(*filters, &block) |
266 | - prepend_filter_to_chain(filters, :after, &block) | |
267 | + append_filter_to_chain(filters, :after, &block) | |
267 | 268 | end |
268 | 269 | |
269 | 270 | # The passed <tt>filters</tt> will be prepended to the array of filters |
270 | 271 | # that run _after_ actions on this controller are performed. |
271 | 272 | def prepend_after_filter(*filters, &block) |
272 | - append_filter_to_chain(filters, :after, &block) | |
273 | + prepend_filter_to_chain(filters, :after, &block) | |
273 | 274 | end |
274 | 275 | |
275 | 276 | # Shorthand for append_after_filter since it's the most common. |
... | ... | @@ -362,12 +363,12 @@ module ActionController #:nodoc: |
362 | 363 | |
363 | 364 | # Returns a mapping between filters and the actions that may run them. |
364 | 365 | def included_actions #:nodoc: |
365 | - read_inheritable_attribute("included_actions") || {} | |
366 | + @included_actions ||= read_inheritable_attribute("included_actions") || {} | |
366 | 367 | end |
367 | 368 | |
368 | 369 | # Returns a mapping between filters and actions that may not run them. |
369 | 370 | def excluded_actions #:nodoc: |
370 | - read_inheritable_attribute("excluded_actions") || {} | |
371 | + @excluded_actions ||= read_inheritable_attribute("excluded_actions") || {} | |
371 | 372 | end |
372 | 373 | |
373 | 374 | # Find a filter in the filter_chain where the filter method matches the _filter_ param |
... | ... | @@ -381,10 +382,11 @@ module ActionController #:nodoc: |
381 | 382 | |
382 | 383 | # Returns true if the filter is excluded from the given action |
383 | 384 | def filter_excluded_from_action?(filter,action) #:nodoc: |
384 | - if (ia = included_actions[filter]) && !ia.empty? | |
385 | + case | |
386 | + when ia = included_actions[filter] | |
385 | 387 | !ia.include?(action) |
386 | - else | |
387 | - (excluded_actions[filter] || []).include?(action) | |
388 | + when ea = excluded_actions[filter] | |
389 | + ea.include?(action) | |
388 | 390 | end |
389 | 391 | end |
390 | 392 | |
... | ... | @@ -397,20 +399,28 @@ module ActionController #:nodoc: |
397 | 399 | @filter = filter |
398 | 400 | end |
399 | 401 | |
402 | + def type | |
403 | + :around | |
404 | + end | |
405 | + | |
400 | 406 | def before? |
401 | - false | |
407 | + type == :before | |
402 | 408 | end |
403 | 409 | |
404 | 410 | def after? |
405 | - false | |
411 | + type == :after | |
406 | 412 | end |
407 | 413 | |
408 | 414 | def around? |
409 | - true | |
415 | + type == :around | |
416 | + end | |
417 | + | |
418 | + def run(controller) | |
419 | + raise ActionControllerError, 'No filter type: Nothing to do here.' | |
410 | 420 | end |
411 | 421 | |
412 | 422 | def call(controller, &block) |
413 | - raise(ActionControllerError, 'No filter type: Nothing to do here.') | |
423 | + run(controller) | |
414 | 424 | end |
415 | 425 | end |
416 | 426 | |
... | ... | @@ -420,35 +430,38 @@ module ActionController #:nodoc: |
420 | 430 | def filter |
421 | 431 | @filter.filter |
422 | 432 | end |
423 | - | |
424 | - def around? | |
425 | - false | |
426 | - end | |
427 | 433 | end |
428 | 434 | |
429 | 435 | class BeforeFilterProxy < FilterProxy #:nodoc: |
430 | - def before? | |
431 | - true | |
436 | + def type | |
437 | + :before | |
432 | 438 | end |
433 | 439 | |
434 | - def call(controller, &block) | |
435 | - if false == @filter.call(controller) # must only stop if equal to false. only filters returning false are halted. | |
436 | - controller.halt_filter_chain(@filter, :returned_false) | |
437 | - else | |
438 | - yield | |
440 | + def run(controller) | |
441 | + # only filters returning false are halted. | |
442 | + if false == @filter.call(controller) | |
443 | + controller.send :halt_filter_chain, @filter, :returned_false | |
439 | 444 | end |
440 | 445 | end |
446 | + | |
447 | + def call(controller) | |
448 | + yield unless run(controller) | |
449 | + end | |
441 | 450 | end |
442 | 451 | |
443 | 452 | class AfterFilterProxy < FilterProxy #:nodoc: |
444 | - def after? | |
445 | - true | |
453 | + def type | |
454 | + :after | |
446 | 455 | end |
447 | 456 | |
448 | - def call(controller, &block) | |
449 | - yield | |
457 | + def run(controller) | |
450 | 458 | @filter.call(controller) |
451 | 459 | end |
460 | + | |
461 | + def call(controller) | |
462 | + yield | |
463 | + run(controller) | |
464 | + end | |
452 | 465 | end |
453 | 466 | |
454 | 467 | class SymbolFilter < Filter #:nodoc: |
... | ... | @@ -485,29 +498,72 @@ module ActionController #:nodoc: |
485 | 498 | end |
486 | 499 | end |
487 | 500 | |
501 | + class ClassBeforeFilter < Filter #:nodoc: | |
502 | + def call(controller, &block) | |
503 | + @filter.before(controller) | |
504 | + end | |
505 | + end | |
506 | + | |
507 | + class ClassAfterFilter < Filter #:nodoc: | |
508 | + def call(controller, &block) | |
509 | + @filter.after(controller) | |
510 | + end | |
511 | + end | |
512 | + | |
488 | 513 | protected |
489 | - def append_filter_to_chain(filters, position = :around, &block) | |
490 | - write_inheritable_array('filter_chain', create_filters(filters, position, &block) ) | |
514 | + def append_filter_to_chain(filters, filter_type = :around, &block) | |
515 | + pos = find_filter_append_position(filters, filter_type) | |
516 | + update_filter_chain(filters, filter_type, pos, &block) | |
491 | 517 | end |
492 | 518 | |
493 | - def prepend_filter_to_chain(filters, position = :around, &block) | |
494 | - write_inheritable_attribute('filter_chain', create_filters(filters, position, &block) + filter_chain) | |
519 | + def prepend_filter_to_chain(filters, filter_type = :around, &block) | |
520 | + pos = find_filter_prepend_position(filters, filter_type) | |
521 | + update_filter_chain(filters, filter_type, pos, &block) | |
495 | 522 | end |
496 | 523 | |
497 | - def create_filters(filters, position, &block) #:nodoc: | |
524 | + def update_filter_chain(filters, filter_type, pos, &block) | |
525 | + new_filters = create_filters(filters, filter_type, &block) | |
526 | + new_chain = filter_chain.insert(pos, new_filters).flatten | |
527 | + write_inheritable_attribute('filter_chain', new_chain) | |
528 | + end | |
529 | + | |
530 | + def find_filter_append_position(filters, filter_type) | |
531 | + # appending an after filter puts it at the end of the call chain | |
532 | + # before and around filters go before the first after filter in the chain | |
533 | + unless filter_type == :after | |
534 | + filter_chain.each_with_index do |f,i| | |
535 | + return i if f.after? | |
536 | + end | |
537 | + end | |
538 | + return -1 | |
539 | + end | |
540 | + | |
541 | + def find_filter_prepend_position(filters, filter_type) | |
542 | + # prepending a before or around filter puts it at the front of the call chain | |
543 | + # after filters go before the first after filter in the chain | |
544 | + if filter_type == :after | |
545 | + filter_chain.each_with_index do |f,i| | |
546 | + return i if f.after? | |
547 | + end | |
548 | + return -1 | |
549 | + end | |
550 | + return 0 | |
551 | + end | |
552 | + | |
553 | + def create_filters(filters, filter_type, &block) #:nodoc: | |
498 | 554 | filters, conditions = extract_conditions(filters, &block) |
499 | - filters.map! { |filter| find_or_create_filter(filter,position) } | |
555 | + filters.map! { |filter| find_or_create_filter(filter, filter_type) } | |
500 | 556 | update_conditions(filters, conditions) |
501 | 557 | filters |
502 | 558 | end |
503 | 559 | |
504 | - def find_or_create_filter(filter,position) | |
505 | - if found_filter = find_filter(filter) { |f| f.send("#{position}?") } | |
560 | + def find_or_create_filter(filter, filter_type) | |
561 | + if found_filter = find_filter(filter) { |f| f.type == filter_type } | |
506 | 562 | found_filter |
507 | 563 | else |
508 | - f = class_for_filter(filter).new(filter) | |
564 | + f = class_for_filter(filter, filter_type).new(filter) | |
509 | 565 | # apply proxy to filter if necessary |
510 | - case position | |
566 | + case filter_type | |
511 | 567 | when :before |
512 | 568 | BeforeFilterProxy.new(f) |
513 | 569 | when :after |
... | ... | @@ -520,7 +576,7 @@ module ActionController #:nodoc: |
520 | 576 | |
521 | 577 | # The determination of the filter type was once done at run time. |
522 | 578 | # This method is here to extract as much logic from the filter run time as possible |
523 | - def class_for_filter(filter) #:nodoc: | |
579 | + def class_for_filter(filter, filter_type) #:nodoc: | |
524 | 580 | case |
525 | 581 | when filter.is_a?(Symbol) |
526 | 582 | SymbolFilter |
... | ... | @@ -534,8 +590,12 @@ module ActionController #:nodoc: |
534 | 590 | end |
535 | 591 | when filter.respond_to?(:filter) |
536 | 592 | ClassFilter |
593 | + when filter.respond_to?(:before) && filter_type == :before | |
594 | + ClassBeforeFilter | |
595 | + when filter.respond_to?(:after) && filter_type == :after | |
596 | + ClassAfterFilter | |
537 | 597 | else |
538 | - raise(ActionControllerError, 'A filters must be a Symbol, Proc, Method, or object responding to filter.') | |
598 | + raise(ActionControllerError, 'A filter must be a Symbol, Proc, Method, or object responding to filter, after or before.') | |
539 | 599 | end |
540 | 600 | end |
541 | 601 | |
... | ... | @@ -550,8 +610,8 @@ module ActionController #:nodoc: |
550 | 610 | return if conditions.empty? |
551 | 611 | if conditions[:only] |
552 | 612 | write_inheritable_hash('included_actions', condition_hash(filters, conditions[:only])) |
553 | - else | |
554 | - write_inheritable_hash('excluded_actions', condition_hash(filters, conditions[:except])) if conditions[:except] | |
613 | + elsif conditions[:except] | |
614 | + write_inheritable_hash('excluded_actions', condition_hash(filters, conditions[:except])) | |
555 | 615 | end |
556 | 616 | end |
557 | 617 | |
... | ... | @@ -576,9 +636,9 @@ module ActionController #:nodoc: |
576 | 636 | |
577 | 637 | def remove_actions_from_included_actions!(filters,*actions) |
578 | 638 | actions = actions.flatten.map(&:to_s) |
579 | - updated_hash = filters.inject(included_actions) do |hash,filter| | |
639 | + updated_hash = filters.inject(read_inheritable_attribute('included_actions')||{}) do |hash,filter| | |
580 | 640 | ia = (hash[filter] || []) - actions |
581 | - ia.blank? ? hash.delete(filter) : hash[filter] = ia | |
641 | + ia.empty? ? hash.delete(filter) : hash[filter] = ia | |
582 | 642 | hash |
583 | 643 | end |
584 | 644 | write_inheritable_attribute('included_actions', updated_hash) |
... | ... | @@ -595,7 +655,9 @@ module ActionController #:nodoc: |
595 | 655 | def proxy_before_and_after_filter(filter) #:nodoc: |
596 | 656 | return filter unless filter_responds_to_before_and_after(filter) |
597 | 657 | Proc.new do |controller, action| |
598 | - unless filter.before(controller) == false | |
658 | + if filter.before(controller) == false | |
659 | + controller.send :halt_filter_chain, filter, :returned_false | |
660 | + else | |
599 | 661 | begin |
600 | 662 | action.call |
601 | 663 | ensure |
... | ... | @@ -615,53 +677,90 @@ module ActionController #:nodoc: |
615 | 677 | end |
616 | 678 | end |
617 | 679 | |
618 | - def perform_action_with_filters | |
619 | - call_filter(self.class.filter_chain, 0) | |
620 | - end | |
680 | + protected | |
621 | 681 | |
622 | 682 | def process_with_filters(request, response, method = :perform_action, *arguments) #:nodoc: |
623 | 683 | @before_filter_chain_aborted = false |
624 | 684 | process_without_filters(request, response, method, *arguments) |
625 | 685 | end |
626 | 686 | |
627 | - def filter_chain | |
628 | - self.class.filter_chain | |
687 | + def perform_action_with_filters | |
688 | + call_filters(self.class.filter_chain, 0, 0) | |
629 | 689 | end |
630 | 690 | |
631 | - def call_filter(chain, index) | |
632 | - return (performed? || perform_action_without_filters) if index >= chain.size | |
633 | - filter = chain[index] | |
634 | - return call_filter(chain, index.next) if self.class.filter_excluded_from_action?(filter,action_name) | |
691 | + private | |
635 | 692 | |
636 | - halted = false | |
637 | - filter.call(self) do | |
638 | - halted = call_filter(chain, index.next) | |
693 | + def call_filters(chain, index, nesting) | |
694 | + index = run_before_filters(chain, index, nesting) | |
695 | + aborted = @before_filter_chain_aborted | |
696 | + perform_action_without_filters unless performed? || aborted | |
697 | + return index if nesting != 0 || aborted | |
698 | + run_after_filters(chain, index) | |
699 | + end | |
700 | + | |
701 | + def skip_excluded_filters(chain, index) | |
702 | + while (filter = chain[index]) && self.class.filter_excluded_from_action?(filter, action_name) | |
703 | + index = index.next | |
639 | 704 | end |
640 | - halt_filter_chain(filter.filter, :no_yield) if halted == false unless @before_filter_chain_aborted | |
641 | - halted | |
705 | + [filter, index] | |
642 | 706 | end |
643 | 707 | |
644 | - def halt_filter_chain(filter, reason) | |
645 | - if logger | |
646 | - case reason | |
647 | - when :no_yield | |
648 | - logger.info "Filter chain halted as [#{filter.inspect}] did not yield." | |
649 | - when :returned_false | |
650 | - logger.info "Filter chain halted as [#{filter.inspect}] returned false." | |
708 | + def run_before_filters(chain, index, nesting) | |
709 | + while chain[index] | |
710 | + filter, index = skip_excluded_filters(chain, index) | |
711 | + break unless filter # end of call chain reached | |
712 | + case filter.type | |
713 | + when :before | |
714 | + filter.run(self) # invoke before filter | |
715 | + index = index.next | |
716 | + break if @before_filter_chain_aborted | |
717 | + when :around | |
718 | + yielded = false | |
719 | + filter.call(self) do | |
720 | + yielded = true | |
721 | + # all remaining before and around filters will be run in this call | |
722 | + index = call_filters(chain, index.next, nesting.next) | |
723 | + end | |
724 | + halt_filter_chain(filter, :did_not_yield) unless yielded | |
725 | + break | |
726 | + else | |
727 | + break # no before or around filters left | |
651 | 728 | end |
652 | 729 | end |
653 | - @before_filter_chain_aborted = true | |
654 | - return false | |
730 | + index | |
655 | 731 | end |
656 | 732 | |
657 | - private | |
658 | - def process_cleanup_with_filters | |
659 | - if @before_filter_chain_aborted | |
660 | - close_session | |
733 | + def run_after_filters(chain, index) | |
734 | + seen_after_filter = false | |
735 | + while chain[index] | |
736 | + filter, index = skip_excluded_filters(chain, index) | |
737 | + break unless filter # end of call chain reached | |
738 | + case filter.type | |
739 | + when :after | |
740 | + seen_after_filter = true | |
741 | + filter.run(self) # invoke after filter | |
661 | 742 | else |
662 | - process_cleanup_without_filters | |
743 | + # implementation error or someone has mucked with the filter chain | |
744 | + raise ActionControllerError, "filter #{filter.inspect} was in the wrong place!" if seen_after_filter | |
663 | 745 | end |
746 | + index = index.next | |
747 | + end | |
748 | + index.next | |
749 | + end | |
750 | + | |
751 | + def halt_filter_chain(filter, reason) | |
752 | + @before_filter_chain_aborted = true | |
753 | + logger.info "Filter chain halted as [#{filter.inspect}] #{reason}." if logger | |
754 | + false | |
755 | + end | |
756 | + | |
757 | + def process_cleanup_with_filters | |
758 | + if @before_filter_chain_aborted | |
759 | + close_session | |
760 | + else | |
761 | + process_cleanup_without_filters | |
664 | 762 | end |
763 | + end | |
665 | 764 | end |
666 | 765 | end |
667 | 766 | end | ... | ... |
vendor/rails/actionpack/lib/action_controller/integration.rb
... | ... | @@ -67,7 +67,7 @@ module ActionController |
67 | 67 | @https = false |
68 | 68 | @cookies = {} |
69 | 69 | @controller = @request = @response = nil |
70 | - | |
70 | + | |
71 | 71 | self.host = "www.example.com" |
72 | 72 | self.remote_addr = "127.0.0.1" |
73 | 73 | self.accept = "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5" |
... | ... | @@ -89,7 +89,7 @@ module ActionController |
89 | 89 | # session.https! |
90 | 90 | # session.https!(false) |
91 | 91 | def https!(flag=true) |
92 | - @https = flag | |
92 | + @https = flag | |
93 | 93 | end |
94 | 94 | |
95 | 95 | # Return +true+ if the session is mimicing a secure HTTPS request. |
... | ... | @@ -143,10 +143,10 @@ module ActionController |
143 | 143 | # Performs a GET request with the given parameters. The parameters may |
144 | 144 | # be +nil+, a Hash, or a string that is appropriately encoded |
145 | 145 | # (application/x-www-form-urlencoded or multipart/form-data). The headers |
146 | - # should be a hash. The keys will automatically be upcased, with the | |
146 | + # should be a hash. The keys will automatically be upcased, with the | |
147 | 147 | # prefix 'HTTP_' added if needed. |
148 | 148 | # |
149 | - # You can also perform POST, PUT, DELETE, and HEAD requests with #post, | |
149 | + # You can also perform POST, PUT, DELETE, and HEAD requests with #post, | |
150 | 150 | # #put, #delete, and #head. |
151 | 151 | def get(path, parameters=nil, headers=nil) |
152 | 152 | process :get, path, parameters, headers |
... | ... | @@ -161,31 +161,41 @@ module ActionController |
161 | 161 | def put(path, parameters=nil, headers=nil) |
162 | 162 | process :put, path, parameters, headers |
163 | 163 | end |
164 | - | |
164 | + | |
165 | 165 | # Performs a DELETE request with the given parameters. See get() for more details. |
166 | 166 | def delete(path, parameters=nil, headers=nil) |
167 | 167 | process :delete, path, parameters, headers |
168 | 168 | end |
169 | - | |
169 | + | |
170 | 170 | # Performs a HEAD request with the given parameters. See get() for more details. |
171 | 171 | def head(path, parameters=nil, headers=nil) |
172 | 172 | process :head, path, parameters, headers |
173 | 173 | end |
174 | 174 | |
175 | - # Performs an XMLHttpRequest request with the given parameters, mimicing | |
176 | - # the request environment created by the Prototype library. The parameters | |
177 | - # may be +nil+, a Hash, or a string that is appropriately encoded | |
178 | - # (application/x-www-form-urlencoded or multipart/form-data). The headers | |
179 | - # should be a hash. The keys will automatically be upcased, with the | |
180 | - # prefix 'HTTP_' added if needed. | |
181 | - def xml_http_request(path, parameters=nil, headers=nil) | |
182 | - headers = (headers || {}).merge( | |
183 | - "X-Requested-With" => "XMLHttpRequest", | |
184 | - "Accept" => "text/javascript, text/html, application/xml, text/xml, */*" | |
185 | - ) | |
175 | + # Performs an XMLHttpRequest request with the given parameters, mirroring | |
176 | + # a request from the Prototype library. | |
177 | + # | |
178 | + # The request_method is :get, :post, :put, :delete or :head; the | |
179 | + # parameters are +nil+, a hash, or a url-encoded or multipart string; | |
180 | + # the headers are a hash. Keys are automatically upcased and prefixed | |
181 | + # with 'HTTP_' if not already. | |
182 | + # | |
183 | + # This method used to omit the request_method parameter, assuming it | |
184 | + # was :post. This was deprecated in Rails 1.2.4. Always pass the request | |
185 | + # method as the first argument. | |
186 | + def xml_http_request(request_method, path, parameters = nil, headers = nil) | |
187 | + unless request_method.is_a?(Symbol) | |
188 | + ActiveSupport::Deprecation.warn 'xml_http_request now takes the request_method (:get, :post, etc.) as the first argument. It used to assume :post, so add the :post argument to your existing method calls to silence this warning.' | |
189 | + request_method, path, parameters, headers = :post, request_method, path, parameters | |
190 | + end | |
191 | + | |
192 | + headers ||= {} | |
193 | + headers['X-Requested-With'] = 'XMLHttpRequest' | |
194 | + headers['Accept'] = 'text/javascript, text/html, application/xml, text/xml, */*' | |
186 | 195 | |
187 | - post(path, parameters, headers) | |
196 | + process(request_method, path, parameters, headers) | |
188 | 197 | end |
198 | + alias xhr :xml_http_request | |
189 | 199 | |
190 | 200 | # Returns the URL for the given options, according to the rules specified |
191 | 201 | # in the application's routes. |
... | ... | @@ -292,7 +302,7 @@ module ActionController |
292 | 302 | @status = @status.to_i |
293 | 303 | end |
294 | 304 | |
295 | - # Encode the cookies hash in a format suitable for passing to a | |
305 | + # Encode the cookies hash in a format suitable for passing to a | |
296 | 306 | # request. |
297 | 307 | def encode_cookies |
298 | 308 | cookies.inject("") do |string, (name, value)| |
... | ... | @@ -450,7 +460,7 @@ module ActionController |
450 | 460 | # without any test methods. |
451 | 461 | def run(*args) #:nodoc: |
452 | 462 | return if @method_name == "default_test" |
453 | - super | |
463 | + super | |
454 | 464 | end |
455 | 465 | |
456 | 466 | # Because of how use_instantiated_fixtures and use_transactional_fixtures |
... | ... | @@ -490,7 +500,7 @@ module ActionController |
490 | 500 | @integration_session = open_session |
491 | 501 | end |
492 | 502 | |
493 | - %w(get post cookies assigns xml_http_request).each do |method| | |
503 | + %w(get post put head delete cookies assigns xml_http_request).each do |method| | |
494 | 504 | define_method(method) do |*args| |
495 | 505 | reset! unless @integration_session |
496 | 506 | # reset the html_document variable, but only for new get/post calls | ... | ... |
vendor/rails/actionpack/lib/action_controller/macros/in_place_editing.rb
... | ... | @@ -24,7 +24,7 @@ module ActionController |
24 | 24 | define_method("set_#{object}_#{attribute}") do |
25 | 25 | @item = object.to_s.camelize.constantize.find(params[:id]) |
26 | 26 | @item.update_attribute(attribute, params[:value]) |
27 | - render :text => @item.send(attribute) | |
27 | + render :text => @item.send(attribute).to_s | |
28 | 28 | end |
29 | 29 | end |
30 | 30 | end | ... | ... |
vendor/rails/actionpack/lib/action_controller/pagination.rb
1 | 1 | module ActionController |
2 | 2 | # === Action Pack pagination for Active Record collections |
3 | 3 | # |
4 | - # DEPRECATION WARNING: Pagination will be separated into its own plugin with Rails 2.0. | |
4 | + # DEPRECATION WARNING: Pagination will be moved to a plugin in Rails 2.0. | |
5 | + # Install the classic_pagination plugin for forward compatibility: | |
6 | + # script/plugin install svn://errtheblog.com/svn/plugins/classic_pagination | |
5 | 7 | # |
6 | 8 | # The Pagination module aids in the process of paging large collections of |
7 | 9 | # Active Record objects. It offers macro-style automatic fetching of your |
... | ... | @@ -130,6 +132,8 @@ module ActionController |
130 | 132 | paginator_and_collection_for(collection_id, options) |
131 | 133 | end |
132 | 134 | |
135 | + deprecate :paginate => 'Pagination is moving to a plugin in Rails 2.0: script/plugin install svn://errtheblog.com/svn/plugins/classic_pagination' | |
136 | + | |
133 | 137 | # These methods become class methods on any controller |
134 | 138 | module ClassMethods |
135 | 139 | # Creates a +before_filter+ which automatically paginates an Active |
... | ... | @@ -148,6 +152,8 @@ module ActionController |
148 | 152 | OPTIONS[self][collection_id] = options |
149 | 153 | end |
150 | 154 | end |
155 | + | |
156 | + deprecate :paginate => 'Pagination is moving to a plugin in Rails 2.0: script/plugin install svn://errtheblog.com/svn/plugins/classic_pagination' | |
151 | 157 | end |
152 | 158 | |
153 | 159 | def create_paginators_and_retrieve_collections #:nodoc: | ... | ... |
vendor/rails/actionpack/lib/action_controller/resources.rb
... | ... | @@ -2,48 +2,68 @@ module ActionController |
2 | 2 | module Resources |
3 | 3 | class Resource #:nodoc: |
4 | 4 | attr_reader :collection_methods, :member_methods, :new_methods |
5 | - attr_reader :path_prefix, :name_prefix | |
5 | + attr_reader :path_prefix, :new_name_prefix | |
6 | 6 | attr_reader :plural, :singular |
7 | 7 | attr_reader :options |
8 | 8 | |
9 | 9 | def initialize(entities, options) |
10 | 10 | @plural = entities |
11 | 11 | @singular = options[:singular] || plural.to_s.singularize |
12 | - | |
12 | + | |
13 | 13 | @options = options |
14 | 14 | |
15 | 15 | arrange_actions |
16 | 16 | add_default_actions |
17 | 17 | set_prefixes |
18 | 18 | end |
19 | - | |
19 | + | |
20 | 20 | def controller |
21 | 21 | @controller ||= (options[:controller] || plural).to_s |
22 | 22 | end |
23 | - | |
23 | + | |
24 | 24 | def path |
25 | 25 | @path ||= "#{path_prefix}/#{plural}" |
26 | 26 | end |
27 | - | |
27 | + | |
28 | 28 | def new_path |
29 | 29 | @new_path ||= "#{path}/new" |
30 | 30 | end |
31 | - | |
31 | + | |
32 | 32 | def member_path |
33 | 33 | @member_path ||= "#{path}/:id" |
34 | 34 | end |
35 | - | |
35 | + | |
36 | 36 | def nesting_path_prefix |
37 | 37 | @nesting_path_prefix ||= "#{path}/:#{singular}_id" |
38 | 38 | end |
39 | - | |
39 | + | |
40 | + def deprecate_name_prefix? | |
41 | + @name_prefix.blank? && !@new_name_prefix.blank? | |
42 | + end | |
43 | + | |
44 | + def name_prefix | |
45 | + deprecate_name_prefix? ? @new_name_prefix : @name_prefix | |
46 | + end | |
47 | + | |
48 | + def old_name_prefix | |
49 | + @name_prefix | |
50 | + end | |
51 | + | |
52 | + def nesting_name_prefix | |
53 | + "#{new_name_prefix}#{singular}_" | |
54 | + end | |
55 | + | |
56 | + def action_separator | |
57 | + @action_separator ||= Base.resource_action_separator | |
58 | + end | |
59 | + | |
40 | 60 | protected |
41 | 61 | def arrange_actions |
42 | 62 | @collection_methods = arrange_actions_by_methods(options.delete(:collection)) |
43 | 63 | @member_methods = arrange_actions_by_methods(options.delete(:member)) |
44 | 64 | @new_methods = arrange_actions_by_methods(options.delete(:new)) |
45 | 65 | end |
46 | - | |
66 | + | |
47 | 67 | def add_default_actions |
48 | 68 | add_default_action(member_methods, :get, :edit) |
49 | 69 | add_default_action(new_methods, :get, :new) |
... | ... | @@ -52,6 +72,7 @@ module ActionController |
52 | 72 | def set_prefixes |
53 | 73 | @path_prefix = options.delete(:path_prefix) |
54 | 74 | @name_prefix = options.delete(:name_prefix) |
75 | + @new_name_prefix = options.delete(:new_name_prefix) | |
55 | 76 | end |
56 | 77 | |
57 | 78 | def arrange_actions_by_methods(actions) |
... | ... | @@ -60,7 +81,7 @@ module ActionController |
60 | 81 | flipped_hash |
61 | 82 | end |
62 | 83 | end |
63 | - | |
84 | + | |
64 | 85 | def add_default_action(collection, method, action) |
65 | 86 | (collection[method] ||= []).unshift(action) |
66 | 87 | end |
... | ... | @@ -178,11 +199,11 @@ module ActionController |
178 | 199 | # |
179 | 200 | # The comment resources work the same, but must now include a value for :article_id. |
180 | 201 | # |
181 | - # comments_url(@article) | |
182 | - # comment_url(@article, @comment) | |
202 | + # article_comments_url(@article) | |
203 | + # article_comment_url(@article, @comment) | |
183 | 204 | # |
184 | - # comments_url(:article_id => @article) | |
185 | - # comment_url(:article_id => @article, :id => @comment) | |
205 | + # article_comments_url(:article_id => @article) | |
206 | + # article_comment_url(:article_id => @article, :id => @comment) | |
186 | 207 | # |
187 | 208 | # * <tt>:name_prefix</tt> -- define a prefix for all generated routes, usually ending in an underscore. |
188 | 209 | # Use this if you have named routes that may clash. |
... | ... | @@ -192,7 +213,7 @@ module ActionController |
192 | 213 | # |
193 | 214 | # * <tt>:collection</tt> -- add named routes for other actions that operate on the collection. |
194 | 215 | # Takes a hash of <tt>#{action} => #{method}</tt>, where method is <tt>:get</tt>/<tt>:post</tt>/<tt>:put</tt>/<tt>:delete</tt> |
195 | - # or <tt>:any</tt> if the method does not matter. These routes map to a URL like /messages;rss, with a route of rss_messages_url. | |
216 | + # or <tt>:any</tt> if the method does not matter. These routes map to a URL like /messages/rss, with a route of rss_messages_url. | |
196 | 217 | # * <tt>:member</tt> -- same as :collection, but for actions that operate on a specific member. |
197 | 218 | # * <tt>:new</tt> -- same as :collection, but for actions that operate on the new resource action. |
198 | 219 | # |
... | ... | @@ -204,19 +225,19 @@ module ActionController |
204 | 225 | # # --> GET /thread/7/messages/1 |
205 | 226 | # |
206 | 227 | # map.resources :messages, :collection => { :rss => :get } |
207 | - # # --> GET /messages;rss (maps to the #rss action) | |
228 | + # # --> GET /messages/rss (maps to the #rss action) | |
208 | 229 | # # also adds a named route called "rss_messages" |
209 | 230 | # |
210 | 231 | # map.resources :messages, :member => { :mark => :post } |
211 | - # # --> POST /messages/1;mark (maps to the #mark action) | |
232 | + # # --> POST /messages/1/mark (maps to the #mark action) | |
212 | 233 | # # also adds a named route called "mark_message" |
213 | 234 | # |
214 | 235 | # map.resources :messages, :new => { :preview => :post } |
215 | - # # --> POST /messages/new;preview (maps to the #preview action) | |
236 | + # # --> POST /messages/new/preview (maps to the #preview action) | |
216 | 237 | # # also adds a named route called "preview_new_message" |
217 | 238 | # |
218 | 239 | # map.resources :messages, :new => { :new => :any, :preview => :post } |
219 | - # # --> POST /messages/new;preview (maps to the #preview action) | |
240 | + # # --> POST /messages/new/preview (maps to the #preview action) | |
220 | 241 | # # also adds a named route called "preview_new_message" |
221 | 242 | # # --> /messages/new can be invoked via any request method |
222 | 243 | # |
... | ... | @@ -235,9 +256,10 @@ module ActionController |
235 | 256 | # /account profile. |
236 | 257 | # |
237 | 258 | # See map.resources for general conventions. These are the main differences: |
238 | - # - a singular name is given to map.resource. The default controller name is taken from the singular name. | |
239 | - # - To specify a custom plural name, use the :plural option. There is no :singular option | |
240 | - # - No default index, new, or create routes are created for the singleton resource controller. | |
259 | + # - A singular name is given to map.resource. The default controller name is taken from the singular name. | |
260 | + # - There is no <tt>:collection</tt> option as there is only the singleton resource. | |
261 | + # - There is no <tt>:singular</tt> option as the singular name is passed to map.resource. | |
262 | + # - No default index route is created for the singleton resource controller. | |
241 | 263 | # - When nesting singleton resources, only the singular name is used as the path prefix (example: 'account/messages/1') |
242 | 264 | # |
243 | 265 | # Example: |
... | ... | @@ -300,7 +322,7 @@ module ActionController |
300 | 322 | map_member_actions(map, resource) |
301 | 323 | |
302 | 324 | if block_given? |
303 | - with_options(:path_prefix => resource.nesting_path_prefix, &block) | |
325 | + with_options(:path_prefix => resource.nesting_path_prefix, :new_name_prefix => resource.nesting_name_prefix, &block) | |
304 | 326 | end |
305 | 327 | end |
306 | 328 | end |
... | ... | @@ -315,7 +337,7 @@ module ActionController |
315 | 337 | map_member_actions(map, resource) |
316 | 338 | |
317 | 339 | if block_given? |
318 | - with_options(:path_prefix => resource.nesting_path_prefix, &block) | |
340 | + with_options(:path_prefix => resource.nesting_path_prefix, :new_name_prefix => resource.nesting_name_prefix, &block) | |
319 | 341 | end |
320 | 342 | end |
321 | 343 | end |
... | ... | @@ -324,8 +346,21 @@ module ActionController |
324 | 346 | resource.collection_methods.each do |method, actions| |
325 | 347 | actions.each do |action| |
326 | 348 | action_options = action_options_for(action, resource, method) |
327 | - map.named_route("#{resource.name_prefix}#{action}_#{resource.plural}", "#{resource.path};#{action}", action_options) | |
328 | - map.named_route("formatted_#{resource.name_prefix}#{action}_#{resource.plural}", "#{resource.path}.:format;#{action}", action_options) | |
349 | + | |
350 | + unless resource.old_name_prefix.blank? | |
351 | + map.deprecated_named_route("#{action}_#{resource.name_prefix}#{resource.plural}", "#{resource.old_name_prefix}#{action}_#{resource.plural}") | |
352 | + map.deprecated_named_route("formatted_#{action}_#{resource.name_prefix}#{resource.plural}", "formatted_#{resource.old_name_prefix}#{action}_#{resource.plural}") | |
353 | + end | |
354 | + | |
355 | + if resource.deprecate_name_prefix? | |
356 | + map.deprecated_named_route("#{action}_#{resource.name_prefix}#{resource.plural}", "#{action}_#{resource.plural}") | |
357 | + map.deprecated_named_route("formatted_#{action}_#{resource.name_prefix}#{resource.plural}", "formatted_#{action}_#{resource.plural}") | |
358 | + end | |
359 | + | |
360 | + map.named_route("#{action}_#{resource.name_prefix}#{resource.plural}", "#{resource.path}#{resource.action_separator}#{action}", action_options) | |
361 | + map.connect("#{resource.path};#{action}", action_options) | |
362 | + map.connect("#{resource.path}.:format;#{action}", action_options) | |
363 | + map.named_route("formatted_#{action}_#{resource.name_prefix}#{resource.plural}", "#{resource.path}#{resource.action_separator}#{action}.:format", action_options) | |
329 | 364 | end |
330 | 365 | end |
331 | 366 | end |
... | ... | @@ -335,6 +370,11 @@ module ActionController |
335 | 370 | map.named_route("#{resource.name_prefix}#{resource.plural}", resource.path, index_action_options) |
336 | 371 | map.named_route("formatted_#{resource.name_prefix}#{resource.plural}", "#{resource.path}.:format", index_action_options) |
337 | 372 | |
373 | + if resource.deprecate_name_prefix? | |
374 | + map.deprecated_named_route("#{resource.name_prefix}#{resource.plural}", "#{resource.plural}") | |
375 | + map.deprecated_named_route("formatted_#{resource.name_prefix}#{resource.plural}", "formatted_#{resource.plural}") | |
376 | + end | |
377 | + | |
338 | 378 | create_action_options = action_options_for("create", resource) |
339 | 379 | map.connect(resource.path, create_action_options) |
340 | 380 | map.connect("#{resource.path}.:format", create_action_options) |
... | ... | @@ -351,11 +391,37 @@ module ActionController |
351 | 391 | actions.each do |action| |
352 | 392 | action_options = action_options_for(action, resource, method) |
353 | 393 | if action == :new |
354 | - map.named_route("#{resource.name_prefix}new_#{resource.singular}", resource.new_path, action_options) | |
355 | - map.named_route("formatted_#{resource.name_prefix}new_#{resource.singular}", "#{resource.new_path}.:format", action_options) | |
394 | + | |
395 | + unless resource.old_name_prefix.blank? | |
396 | + map.deprecated_named_route("new_#{resource.name_prefix}#{resource.singular}", "#{resource.old_name_prefix}new_#{resource.singular}") | |
397 | + map.deprecated_named_route("formatted_new_#{resource.name_prefix}#{resource.singular}", "formatted_#{resource.old_name_prefix}new_#{resource.singular}") | |
398 | + end | |
399 | + | |
400 | + if resource.deprecate_name_prefix? | |
401 | + map.deprecated_named_route("new_#{resource.name_prefix}#{resource.singular}", "new_#{resource.singular}") | |
402 | + map.deprecated_named_route("formatted_new_#{resource.name_prefix}#{resource.singular}", "formatted_new_#{resource.singular}") | |
403 | + end | |
404 | + | |
405 | + map.named_route("new_#{resource.name_prefix}#{resource.singular}", resource.new_path, action_options) | |
406 | + map.named_route("formatted_new_#{resource.name_prefix}#{resource.singular}", "#{resource.new_path}.:format", action_options) | |
407 | + | |
356 | 408 | else |
357 | - map.named_route("#{resource.name_prefix}#{action}_new_#{resource.singular}", "#{resource.new_path};#{action}", action_options) | |
358 | - map.named_route("formatted_#{resource.name_prefix}#{action}_new_#{resource.singular}", "#{resource.new_path}.:format;#{action}", action_options) | |
409 | + | |
410 | + unless resource.old_name_prefix.blank? | |
411 | + map.deprecated_named_route("#{action}_new_#{resource.name_prefix}#{resource.singular}", "#{resource.old_name_prefix}#{action}_new_#{resource.singular}") | |
412 | + map.deprecated_named_route("formatted_#{action}_new_#{resource.name_prefix}#{resource.singular}", "formatted_#{resource.old_name_prefix}#{action}_new_#{resource.singular}") | |
413 | + end | |
414 | + | |
415 | + if resource.deprecate_name_prefix? | |
416 | + map.deprecated_named_route("#{action}_new_#{resource.name_prefix}#{resource.singular}", "#{action}_new_#{resource.singular}") | |
417 | + map.deprecated_named_route("formatted_#{action}_new_#{resource.name_prefix}#{resource.singular}", "formatted_#{action}_new_#{resource.singular}") | |
418 | + end | |
419 | + | |
420 | + map.named_route("#{action}_new_#{resource.name_prefix}#{resource.singular}", "#{resource.new_path}#{resource.action_separator}#{action}", action_options) | |
421 | + map.connect("#{resource.new_path};#{action}", action_options) | |
422 | + map.connect("#{resource.new_path}.:format;#{action}", action_options) | |
423 | + map.named_route("formatted_#{action}_new_#{resource.name_prefix}#{resource.singular}", "#{resource.new_path}#{resource.action_separator}#{action}.:format", action_options) | |
424 | + | |
359 | 425 | end |
360 | 426 | end |
361 | 427 | end |
... | ... | @@ -365,8 +431,22 @@ module ActionController |
365 | 431 | resource.member_methods.each do |method, actions| |
366 | 432 | actions.each do |action| |
367 | 433 | action_options = action_options_for(action, resource, method) |
368 | - map.named_route("#{resource.name_prefix}#{action}_#{resource.singular}", "#{resource.member_path};#{action}", action_options) | |
369 | - map.named_route("formatted_#{resource.name_prefix}#{action}_#{resource.singular}", "#{resource.member_path}.:format;#{action}",action_options) | |
434 | + | |
435 | + unless resource.old_name_prefix.blank? | |
436 | + map.deprecated_named_route("#{action}_#{resource.name_prefix}#{resource.singular}", "#{resource.old_name_prefix}#{action}_#{resource.singular}") | |
437 | + map.deprecated_named_route("formatted_#{action}_#{resource.name_prefix}#{resource.singular}", "formatted_#{resource.old_name_prefix}#{action}_#{resource.singular}") | |
438 | + end | |
439 | + | |
440 | + if resource.deprecate_name_prefix? | |
441 | + map.deprecated_named_route("#{action}_#{resource.name_prefix}#{resource.singular}", "#{action}_#{resource.singular}") | |
442 | + map.deprecated_named_route("formatted_#{action}_#{resource.name_prefix}#{resource.singular}", "formatted_#{action}_#{resource.singular}") | |
443 | + end | |
444 | + | |
445 | + map.named_route("#{action}_#{resource.name_prefix}#{resource.singular}", "#{resource.member_path}#{resource.action_separator}#{action}", action_options) | |
446 | + map.connect("#{resource.member_path};#{action}", action_options) | |
447 | + map.connect("#{resource.member_path}.:format;#{action}", action_options) | |
448 | + map.named_route("formatted_#{action}_#{resource.name_prefix}#{resource.singular}", "#{resource.member_path}#{resource.action_separator}#{action}.:format", action_options) | |
449 | + | |
370 | 450 | end |
371 | 451 | end |
372 | 452 | |
... | ... | @@ -374,6 +454,11 @@ module ActionController |
374 | 454 | map.named_route("#{resource.name_prefix}#{resource.singular}", resource.member_path, show_action_options) |
375 | 455 | map.named_route("formatted_#{resource.name_prefix}#{resource.singular}", "#{resource.member_path}.:format", show_action_options) |
376 | 456 | |
457 | + if resource.deprecate_name_prefix? | |
458 | + map.deprecated_named_route("#{resource.name_prefix}#{resource.singular}", "#{resource.singular}") | |
459 | + map.deprecated_named_route("formatted_#{resource.name_prefix}#{resource.singular}", "formatted_#{resource.singular}") | |
460 | + end | |
461 | + | |
377 | 462 | update_action_options = action_options_for("update", resource) |
378 | 463 | map.connect(resource.member_path, update_action_options) |
379 | 464 | map.connect("#{resource.member_path}.:format", update_action_options) | ... | ... |
vendor/rails/actionpack/lib/action_controller/routing.rb
... | ... | @@ -451,26 +451,17 @@ module ActionController |
451 | 451 | # is given (as an array), only the keys indicated will be used to build |
452 | 452 | # the query string. The query string will correctly build array parameter |
453 | 453 | # values. |
454 | - def build_query_string(hash, only_keys=nil) | |
454 | + def build_query_string(hash, only_keys = nil) | |
455 | 455 | elements = [] |
456 | - | |
457 | - only_keys ||= hash.keys | |
458 | - | |
459 | - only_keys.each do |key| | |
460 | - value = hash[key] or next | |
461 | - key = CGI.escape key.to_s | |
462 | - if value.class == Array | |
463 | - key << '[]' | |
464 | - else | |
465 | - value = [ value ] | |
466 | - end | |
467 | - value.each { |val| elements << "#{key}=#{CGI.escape(val.to_param.to_s)}" } | |
468 | - end | |
469 | 456 | |
470 | - query_string = "?#{elements.join("&")}" unless elements.empty? | |
471 | - query_string || "" | |
457 | + (only_keys || hash.keys).each do |key| | |
458 | + if value = hash[key] | |
459 | + elements << value.to_query(key) | |
460 | + end | |
461 | + end | |
462 | + elements.empty? ? '' : "?#{elements.sort * '&'}" | |
472 | 463 | end |
473 | - | |
464 | + | |
474 | 465 | # Write the real recognition implementation and then resend the message. |
475 | 466 | def recognize(path, environment={}) |
476 | 467 | write_recognition |
... | ... | @@ -668,7 +659,7 @@ module ActionController |
668 | 659 | end |
669 | 660 | |
670 | 661 | def extract_value |
671 | - "#{local_name} = hash[:#{key}] #{"|| #{default.inspect}" if default}" | |
662 | + "#{local_name} = hash[:#{key}] && hash[:#{key}].to_param #{"|| #{default.inspect}" if default}" | |
672 | 663 | end |
673 | 664 | def value_check |
674 | 665 | if default # Then we know it won't be nil |
... | ... | @@ -989,6 +980,10 @@ module ActionController |
989 | 980 | def named_route(name, path, options = {}) |
990 | 981 | @set.add_named_route(name, path, options) |
991 | 982 | end |
983 | + | |
984 | + def deprecated_named_route(name, deprecated_name, options = {}) | |
985 | + @set.add_deprecated_named_route(name, deprecated_name) | |
986 | + end | |
992 | 987 | |
993 | 988 | # Added deprecation notice for anyone who already added a named route called "root". |
994 | 989 | # It'll be used as a shortcut for map.connect '' in Rails 2.0. |
... | ... | @@ -1019,7 +1014,7 @@ module ActionController |
1019 | 1014 | def clear! |
1020 | 1015 | @routes = {} |
1021 | 1016 | @helpers = [] |
1022 | - | |
1017 | + | |
1023 | 1018 | @module ||= Module.new |
1024 | 1019 | @module.instance_methods.each do |selector| |
1025 | 1020 | @module.send :remove_method, selector |
... | ... | @@ -1055,6 +1050,38 @@ module ActionController |
1055 | 1050 | def install(destinations = [ActionController::Base, ActionView::Base]) |
1056 | 1051 | Array(destinations).each { |dest| dest.send :include, @module } |
1057 | 1052 | end |
1053 | + | |
1054 | + def define_deprecated_named_route_methods(name, deprecated_name) | |
1055 | + | |
1056 | + [:url, :path].each do |kind| | |
1057 | + @module.send :module_eval, <<-end_eval # We use module_eval to avoid leaks | |
1058 | + | |
1059 | + def #{url_helper_name(deprecated_name, kind)}(*args) | |
1060 | + | |
1061 | + ActiveSupport::Deprecation.warn( | |
1062 | + 'The named route "#{url_helper_name(deprecated_name, kind)}" uses a format that has been deprecated. ' + | |
1063 | + 'You should use "#{url_helper_name(name, kind)}" instead.', caller | |
1064 | + ) | |
1065 | + | |
1066 | + send :#{url_helper_name(name, kind)}, *args | |
1067 | + | |
1068 | + end | |
1069 | + | |
1070 | + def #{hash_access_name(deprecated_name, kind)}(*args) | |
1071 | + | |
1072 | + ActiveSupport::Deprecation.warn( | |
1073 | + 'The named route "#{hash_access_name(deprecated_name, kind)}" uses a format that has been deprecated. ' + | |
1074 | + 'You should use "#{hash_access_name(name, kind)}" instead.', caller | |
1075 | + ) | |
1076 | + | |
1077 | + send :#{hash_access_name(name, kind)}, *args | |
1078 | + | |
1079 | + end | |
1080 | + | |
1081 | + end_eval | |
1082 | + end | |
1083 | + | |
1084 | + end | |
1058 | 1085 | |
1059 | 1086 | private |
1060 | 1087 | def url_helper_name(name, kind = :url) |
... | ... | @@ -1177,6 +1204,10 @@ module ActionController |
1177 | 1204 | def add_named_route(name, path, options = {}) |
1178 | 1205 | named_routes[name] = add_route(path, options) |
1179 | 1206 | end |
1207 | + | |
1208 | + def add_deprecated_named_route(name, deprecated_name) | |
1209 | + named_routes.define_deprecated_named_route_methods(name, deprecated_name) | |
1210 | + end | |
1180 | 1211 | |
1181 | 1212 | def options_as_params(options) |
1182 | 1213 | # If an explicit :controller was given, always make :action explicit |
... | ... | @@ -1190,10 +1221,9 @@ module ActionController |
1190 | 1221 | # |
1191 | 1222 | # great fun, eh? |
1192 | 1223 | |
1193 | - options_as_params = options[:controller] ? { :action => "index" } : {} | |
1194 | - options.each do |k, value| | |
1195 | - options_as_params[k] = value.to_param | |
1196 | - end | |
1224 | + options_as_params = options.clone | |
1225 | + options_as_params[:action] ||= 'index' if options[:controller] | |
1226 | + options_as_params[:action] = options_as_params[:action].to_s if options_as_params[:action] | |
1197 | 1227 | options_as_params |
1198 | 1228 | end |
1199 | 1229 | |
... | ... | @@ -1224,6 +1254,9 @@ module ActionController |
1224 | 1254 | options = options_as_params(options) |
1225 | 1255 | expire_on = build_expiry(options, recall) |
1226 | 1256 | |
1257 | + if options[:controller] | |
1258 | + options[:controller] = options[:controller].to_s | |
1259 | + end | |
1227 | 1260 | # if the controller has changed, make sure it changes relative to the |
1228 | 1261 | # current controller module, if any. In other words, if we're currently |
1229 | 1262 | # on admin/get, and the new controller is 'set', the new controller | ... | ... |
vendor/rails/actionpack/lib/action_controller/session/drb_server.rb
vendor/rails/actionpack/lib/action_controller/test_process.rb
... | ... | @@ -24,6 +24,7 @@ module ActionController #:nodoc: |
24 | 24 | attr_accessor :cookies, :session_options |
25 | 25 | attr_accessor :query_parameters, :request_parameters, :path, :session, :env |
26 | 26 | attr_accessor :host |
27 | + attr_reader :request_uri_overridden | |
27 | 28 | |
28 | 29 | def initialize(query_parameters = nil, request_parameters = nil, session = nil) |
29 | 30 | @query_parameters = query_parameters || {} |
... | ... | @@ -67,12 +68,14 @@ module ActionController #:nodoc: |
67 | 68 | # Used to check AbstractRequest's request_uri functionality. |
68 | 69 | # Disables the use of @path and @request_uri so superclass can handle those. |
69 | 70 | def set_REQUEST_URI(value) |
71 | + @request_uri_overridden = true | |
70 | 72 | @env["REQUEST_URI"] = value |
71 | 73 | @request_uri = nil |
72 | 74 | @path = nil |
73 | 75 | end |
74 | 76 | |
75 | 77 | def request_uri=(uri) |
78 | + @env["REQUEST_URI"] = uri | |
76 | 79 | @request_uri = uri |
77 | 80 | @path = uri.split("?").first |
78 | 81 | end |
... | ... | @@ -426,12 +429,12 @@ module ActionController #:nodoc: |
426 | 429 | end |
427 | 430 | |
428 | 431 | def build_request_uri(action, parameters) |
429 | - unless @request.env['REQUEST_URI'] | |
432 | + unless @request.request_uri_overridden | |
430 | 433 | options = @controller.send(:rewrite_options, parameters) |
431 | 434 | options.update(:only_path => true, :action => action) |
432 | 435 | |
433 | 436 | url = ActionController::UrlRewriter.new(@request, parameters) |
434 | - @request.set_REQUEST_URI(url.rewrite(options)) | |
437 | + @request.request_uri = url.rewrite(options) | |
435 | 438 | end |
436 | 439 | end |
437 | 440 | ... | ... |
vendor/rails/actionpack/lib/action_controller/url_rewriter.rb
... | ... | @@ -52,8 +52,9 @@ module ActionController |
52 | 52 | # Delete the unused options to prevent their appearance in the query string |
53 | 53 | [:protocol, :host, :port].each { |k| options.delete k } |
54 | 54 | end |
55 | + anchor = "##{options.delete(:anchor)}" if options.key?(:anchor) | |
55 | 56 | url << Routing::Routes.generate(options, {}) |
56 | - return url | |
57 | + return "#{url}#{anchor}" | |
57 | 58 | end |
58 | 59 | |
59 | 60 | end |
... | ... | @@ -76,6 +77,7 @@ module ActionController |
76 | 77 | alias_method :to_s, :to_str |
77 | 78 | |
78 | 79 | private |
80 | + # Given a path and options, returns a rewritten URL string | |
79 | 81 | def rewrite_url(path, options) |
80 | 82 | rewritten_url = "" |
81 | 83 | unless options[:only_path] |
... | ... | @@ -91,6 +93,7 @@ module ActionController |
91 | 93 | rewritten_url |
92 | 94 | end |
93 | 95 | |
96 | + # Given a Hash of options, generates a route | |
94 | 97 | def rewrite_path(options) |
95 | 98 | options = options.symbolize_keys |
96 | 99 | options.update(options[:params].symbolize_keys) if options[:params] | ... | ... |
vendor/rails/actionpack/lib/action_controller/verification.rb
... | ... | @@ -95,6 +95,7 @@ module ActionController #:nodoc: |
95 | 95 | response.headers.update(options[:add_headers]) if options[:add_headers] |
96 | 96 | unless performed? |
97 | 97 | render(options[:render]) if options[:render] |
98 | + options[:redirect_to] = self.send(options[:redirect_to]) if options[:redirect_to].is_a? Symbol | |
98 | 99 | redirect_to(options[:redirect_to]) if options[:redirect_to] |
99 | 100 | end |
100 | 101 | return false | ... | ... |
vendor/rails/actionpack/lib/action_pack/version.rb
vendor/rails/actionpack/lib/action_view/base.rb
... | ... | @@ -148,7 +148,7 @@ module ActionView #:nodoc: |
148 | 148 | # |
149 | 149 | # This refreshes the sidebar, removes a person element and highlights the user list. |
150 | 150 | # |
151 | - # See the ActionView::Helpers::PrototypeHelper::JavaScriptGenerator documentation for more details. | |
151 | + # See the ActionView::Helpers::PrototypeHelper::GeneratorMethods documentation for more details. | |
152 | 152 | class Base |
153 | 153 | include ERB::Util |
154 | 154 | |
... | ... | @@ -160,7 +160,7 @@ module ActionView #:nodoc: |
160 | 160 | attr_internal *ActionController::Base::DEPRECATED_INSTANCE_VARIABLES |
161 | 161 | |
162 | 162 | # Specify trim mode for the ERB compiler. Defaults to '-'. |
163 | - # See ERB documentation for suitable values. | |
163 | + # See ERb documentation for suitable values. | |
164 | 164 | @@erb_trim_mode = '-' |
165 | 165 | cattr_accessor :erb_trim_mode |
166 | 166 | |
... | ... | @@ -191,17 +191,17 @@ module ActionView #:nodoc: |
191 | 191 | end |
192 | 192 | include CompiledTemplates |
193 | 193 | |
194 | - # maps inline templates to their method names | |
194 | + # Maps inline templates to their method names | |
195 | 195 | @@method_names = {} |
196 | - # map method names to their compile time | |
196 | + # Map method names to their compile time | |
197 | 197 | @@compile_time = {} |
198 | - # map method names to the names passed in local assigns so far | |
198 | + # Map method names to the names passed in local assigns so far | |
199 | 199 | @@template_args = {} |
200 | - # count the number of inline templates | |
200 | + # Count the number of inline templates | |
201 | 201 | @@inline_template_count = 0 |
202 | - # maps template paths without extension to their file extension returned by pick_template_extension. | |
203 | - # if for a given path, path.ext1 and path.ext2 exist on the file system, the order of extensions | |
204 | - # used by pick_template_extension determines whether ext1 or ext2 will be stored | |
202 | + # Maps template paths without extension to their file extension returned by pick_template_extension. | |
203 | + # If for a given path, path.ext1 and path.ext2 exist on the file system, the order of extensions | |
204 | + # used by pick_template_extension determines whether ext1 or ext2 will be stored. | |
205 | 205 | @@cached_template_extension = {} |
206 | 206 | |
207 | 207 | class ObjectWrapper < Struct.new(:value) #:nodoc: |
... | ... | @@ -305,7 +305,6 @@ module ActionView #:nodoc: |
305 | 305 | # Render the provided template with the given local assigns. If the template has not been rendered with the provided |
306 | 306 | # local assigns yet, or if the template has been updated on disk, then the template will be compiled to a method. |
307 | 307 | # |
308 | - | |
309 | 308 | # Either, but not both, of template and file_path may be nil. If file_path is given, the template |
310 | 309 | # will only be read if it has to be compiled. |
311 | 310 | # |
... | ... | @@ -371,10 +370,12 @@ module ActionView #:nodoc: |
371 | 370 | end |
372 | 371 | |
373 | 372 | private |
373 | + # Builds a string holding the full path of the template including extension | |
374 | 374 | def full_template_path(template_path, extension) |
375 | 375 | "#{@base_path}/#{template_path}.#{extension}" |
376 | 376 | end |
377 | 377 | |
378 | + # Asserts the existence of a template. | |
378 | 379 | def template_exists?(template_path, extension) |
379 | 380 | file_path = full_template_path(template_path, extension) |
380 | 381 | @@method_names.has_key?(file_path) || FileTest.exists?(file_path) |
... | ... | @@ -389,6 +390,7 @@ module ActionView #:nodoc: |
389 | 390 | @@cache_template_extensions && @@cached_template_extension[template_path] |
390 | 391 | end |
391 | 392 | |
393 | + # Determines the template's file extension, such as rhtml, rxml, or rjs. | |
392 | 394 | def find_template_extension_for(template_path) |
393 | 395 | if match = delegate_template_exists?(template_path) |
394 | 396 | match.first.to_sym |
... | ... | @@ -405,6 +407,7 @@ module ActionView #:nodoc: |
405 | 407 | File.read(template_path) |
406 | 408 | end |
407 | 409 | |
410 | + # Evaluate the local assigns and pushes them to the view. | |
408 | 411 | def evaluate_assigns |
409 | 412 | unless @assigns_added |
410 | 413 | assign_variables_from_controller |
... | ... | @@ -416,6 +419,7 @@ module ActionView #:nodoc: |
416 | 419 | handler.new(self).render(template, local_assigns) |
417 | 420 | end |
418 | 421 | |
422 | + # Assigns instance variables from the controller to the view. | |
419 | 423 | def assign_variables_from_controller |
420 | 424 | @assigns.each { |key, value| instance_variable_set("@#{key}", value) } |
421 | 425 | end |
... | ... | @@ -427,10 +431,10 @@ module ActionView #:nodoc: |
427 | 431 | ((args = @@template_args[render_symbol]) && local_assigns.all? { |k,_| args.has_key?(k) }) |
428 | 432 | end |
429 | 433 | |
430 | - # Check whether compilation is necessary. | |
431 | - # Compile if the inline template or file has not been compiled yet. | |
432 | - # Or if local_assigns has a new key, which isn't supported by the compiled code yet. | |
433 | - # Or if the file has changed on disk and checking file mods hasn't been disabled. | |
434 | + # Method to check whether template compilation is necessary. | |
435 | + # The template will be compiled if the inline template or file has not been compiled yet, | |
436 | + # if local_assigns has a new key, which isn't supported by the compiled code yet, | |
437 | + # or if the file has changed on disk and checking file mods hasn't been disabled. | |
434 | 438 | def compile_template?(template, file_name, local_assigns) |
435 | 439 | method_key = file_name || template |
436 | 440 | render_symbol = @@method_names[method_key] |
... | ... | @@ -445,14 +449,15 @@ module ActionView #:nodoc: |
445 | 449 | end |
446 | 450 | end |
447 | 451 | |
448 | - # Create source code for given template | |
452 | + # Method to create the source code for a given template. | |
449 | 453 | def create_template_source(extension, template, render_symbol, locals) |
450 | 454 | if template_requires_setup?(extension) |
451 | 455 | body = case extension.to_sym |
452 | 456 | when :rxml |
453 | 457 | "controller.response.content_type ||= 'application/xml'\n" + |
454 | - "xml = Builder::XmlMarkup.new(:indent => 2)\n" + | |
455 | - template | |
458 | + "xml ||= Builder::XmlMarkup.new(:indent => 2)\n" + | |
459 | + template + | |
460 | + "\nxml.target!\n" | |
456 | 461 | when :rjs |
457 | 462 | "controller.response.content_type ||= 'text/javascript'\n" + |
458 | 463 | "update_page do |page|\n#{template}\nend" |
... | ... | @@ -473,11 +478,11 @@ module ActionView #:nodoc: |
473 | 478 | "def #{render_symbol}(local_assigns)\n#{locals_code}#{body}\nend" |
474 | 479 | end |
475 | 480 | |
476 | - def template_requires_setup?(extension) | |
481 | + def template_requires_setup?(extension) #:nodoc: | |
477 | 482 | templates_requiring_setup.include? extension.to_s |
478 | 483 | end |
479 | 484 | |
480 | - def templates_requiring_setup | |
485 | + def templates_requiring_setup #:nodoc: | |
481 | 486 | %w(rxml rjs) |
482 | 487 | end |
483 | 488 | |
... | ... | @@ -501,6 +506,7 @@ module ActionView #:nodoc: |
501 | 506 | end |
502 | 507 | end |
503 | 508 | |
509 | + # Compile and evaluate the template's code | |
504 | 510 | def compile_template(extension, template, file_name, local_assigns) |
505 | 511 | render_symbol = assign_method_name(extension, template, file_name) |
506 | 512 | render_source = create_template_source(extension, template, render_symbol, local_assigns.keys) | ... | ... |
vendor/rails/actionpack/lib/action_view/compiled_templates.rb
... | ... | @@ -3,14 +3,14 @@ module ActionView |
3 | 3 | |
4 | 4 | # CompiledTemplates modules hold methods that have been compiled. |
5 | 5 | # Templates are compiled into these methods so that they do not need to be |
6 | - # re-read and re-parsed each request. | |
6 | + # read and parsed for each request. | |
7 | 7 | # |
8 | 8 | # Each template may be compiled into one or more methods. Each method accepts a given |
9 | 9 | # set of parameters which is used to implement local assigns passing. |
10 | 10 | # |
11 | 11 | # To use a compiled template module, create a new instance and include it into the class |
12 | 12 | # in which you want the template to be rendered. |
13 | - class CompiledTemplates < Module #:nodoc: | |
13 | + class CompiledTemplates < Module | |
14 | 14 | attr_reader :method_names |
15 | 15 | |
16 | 16 | def initialize | ... | ... |
vendor/rails/actionpack/lib/action_view/helpers/active_record_helper.rb
... | ... | @@ -13,17 +13,18 @@ module ActionView |
13 | 13 | # is a great of making the record quickly available for editing, but likely to prove lackluster for a complicated real-world form. |
14 | 14 | # In that case, it's better to use the input method and the specialized form methods in link:classes/ActionView/Helpers/FormHelper.html |
15 | 15 | module ActiveRecordHelper |
16 | - # Returns a default input tag for the type of object returned by the method. Example | |
17 | - # (title is a VARCHAR column and holds "Hello World"): | |
16 | + # Returns a default input tag for the type of object returned by the method. For example, let's say you have a model | |
17 | + # that has an attribute +title+ of type VARCHAR column, and this instance holds "Hello World": | |
18 | 18 | # input("post", "title") => |
19 | 19 | # <input id="post_title" name="post[title]" size="30" type="text" value="Hello World" /> |
20 | 20 | def input(record_name, method, options = {}) |
21 | 21 | InstanceTag.new(record_name, method, self).to_tag(options) |
22 | 22 | end |
23 | 23 | |
24 | - # Returns an entire form with input tags and everything for a specified Active Record object. Example | |
25 | - # (post is a new record that has a title using VARCHAR and a body using TEXT): | |
26 | - # form("post") => | |
24 | + # Returns an entire form with all needed input tags for a specified Active Record object. For example, let's say you | |
25 | + # have a table model <tt>Post</tt> with attributes named <tt>title</tt> of type <tt>VARCHAR</tt> and <tt>body</tt> of type <tt>TEXT</tt>: | |
26 | + # form("post") | |
27 | + # That line would yield a form like the following: | |
27 | 28 | # <form action='/post/create' method='post'> |
28 | 29 | # <p> |
29 | 30 | # <label for="post_title">Title</label><br /> |
... | ... | @@ -32,14 +33,13 @@ module ActionView |
32 | 33 | # <p> |
33 | 34 | # <label for="post_body">Body</label><br /> |
34 | 35 | # <textarea cols="40" id="post_body" name="post[body]" rows="20"> |
35 | - # Back to the hill and over it again! | |
36 | 36 | # </textarea> |
37 | 37 | # </p> |
38 | 38 | # <input type='submit' value='Create' /> |
39 | 39 | # </form> |
40 | 40 | # |
41 | 41 | # It's possible to specialize the form builder by using a different action name and by supplying another |
42 | - # block renderer. Example (entry is a new record that has a message attribute using VARCHAR): | |
42 | + # block renderer. For example, let's say you have a model <tt>Entry</tt> with an attribute <tt>message</tt> of type <tt>VARCHAR</tt>: | |
43 | 43 | # |
44 | 44 | # form("entry", :action => "sign", :input_block => |
45 | 45 | # Proc.new { |record, column| "#{column.human_name}: #{input(record, column.name)}<br />" }) => |
... | ... | @@ -74,16 +74,16 @@ module ActionView |
74 | 74 | content_tag('form', contents, :action => action, :method => 'post', :enctype => options[:multipart] ? 'multipart/form-data': nil) |
75 | 75 | end |
76 | 76 | |
77 | - # Returns a string containing the error message attached to the +method+ on the +object+, if one exists. | |
78 | - # This error message is wrapped in a DIV tag, which can be specialized to include both a +prepend_text+ and +append_text+ | |
79 | - # to properly introduce the error and a +css_class+ to style it accordingly. Examples (post has an error message | |
80 | - # "can't be empty" on the title attribute): | |
77 | + # Returns a string containing the error message attached to the +method+ on the +object+ if one exists. | |
78 | + # This error message is wrapped in a <tt>DIV</tt> tag, which can be extended to include a +prepend_text+ and/or +append_text+ | |
79 | + # (to properly explain the error), and a +css_class+ to style it accordingly. As an example, let's say you have a model | |
80 | + # +post+ that has an error message on the +title+ attribute: | |
81 | 81 | # |
82 | 82 | # <%= error_message_on "post", "title" %> => |
83 | 83 | # <div class="formError">can't be empty</div> |
84 | 84 | # |
85 | - # <%= error_message_on "post", "title", "Title simply ", " (or it won't work)", "inputError" %> => | |
86 | - # <div class="inputError">Title simply can't be empty (or it won't work)</div> | |
85 | + # <%= error_message_on "post", "title", "Title simply ", " (or it won't work).", "inputError" %> => | |
86 | + # <div class="inputError">Title simply can't be empty (or it won't work).</div> | |
87 | 87 | def error_message_on(object, method, prepend_text = "", append_text = "", css_class = "formError") |
88 | 88 | if (obj = instance_variable_get("@#{object}")) && (errors = obj.errors.on(method)) |
89 | 89 | content_tag("div", "#{prepend_text}#{errors.is_a?(Array) ? errors.first : errors}#{append_text}", :class => css_class) |
... | ... | @@ -92,11 +92,11 @@ module ActionView |
92 | 92 | end |
93 | 93 | end |
94 | 94 | |
95 | - # Returns a string with a div containing all of the error messages for the objects located as instance variables by the names | |
95 | + # Returns a string with a <tt>DIV</tt> containing all of the error messages for the objects located as instance variables by the names | |
96 | 96 | # given. If more than one object is specified, the errors for the objects are displayed in the order that the object names are |
97 | 97 | # provided. |
98 | 98 | # |
99 | - # This div can be tailored by the following options: | |
99 | + # This <tt>DIV</tt> can be tailored by the following options: | |
100 | 100 | # |
101 | 101 | # * <tt>header_tag</tt> - Used for the header of the error div (default: h2) |
102 | 102 | # * <tt>id</tt> - The id of the error div (default: errorExplanation) |
... | ... | @@ -105,12 +105,12 @@ module ActionView |
105 | 105 | # any text that you prefer. If <tt>object_name</tt> is not set, the name of |
106 | 106 | # the first object will be used. |
107 | 107 | # |
108 | - # Specifying one object: | |
108 | + # To specify the display for one object, you simply provide its name as a parameter. For example, for the +User+ model: | |
109 | 109 | # |
110 | 110 | # error_messages_for 'user' |
111 | 111 | # |
112 | - # Specifying more than one object (and using the name 'user' in the | |
113 | - # header as the <tt>object_name</tt> instead of 'user_common'): | |
112 | + # To specify more than one object, you simply list them; optionally, you can add an extra +object_name+ parameter, which | |
113 | + # be the name in the header. | |
114 | 114 | # |
115 | 115 | # error_messages_for 'user_common', 'user', :object_name => 'user' |
116 | 116 | # | ... | ... |
vendor/rails/actionpack/lib/action_view/helpers/debug_helper.rb
... | ... | @@ -3,6 +3,16 @@ module ActionView |
3 | 3 | # Provides a set of methods for making it easier to locate problems. |
4 | 4 | module DebugHelper |
5 | 5 | # Returns a <pre>-tag set with the +object+ dumped by YAML. Very readable way to inspect an object. |
6 | + # my_hash = {'first' => 1, 'second' => 'two', 'third' => [1,2,3]} | |
7 | + # debug(my_hash) | |
8 | + # => <pre class='debug_dump'>--- | |
9 | + # first: 1 | |
10 | + # second: two | |
11 | + # third: | |
12 | + # - 1 | |
13 | + # - 2 | |
14 | + # - 3 | |
15 | + # </pre> | |
6 | 16 | def debug(object) |
7 | 17 | begin |
8 | 18 | Marshal::dump(object) | ... | ... |
vendor/rails/actionpack/lib/action_view/helpers/deprecated_helper.rb
... | ... | @@ -2,6 +2,9 @@ module ActionView |
2 | 2 | module Helpers |
3 | 3 | module PrototypeHelper |
4 | 4 | |
5 | + # Method to execute an element update using Prototype. | |
6 | + # DEPRECATION WARNING: This helper has been depercated; use RJS instead. | |
7 | + # See ActionView::Helpers::PrototypeHelper::JavaScriptGenerator::GeneratorMethods for more information. | |
5 | 8 | def update_element_function(element_id, options = {}, &block) |
6 | 9 | content = escape_javascript(options[:content] || '') |
7 | 10 | content = escape_javascript(capture(&block)) if block | ... | ... |
vendor/rails/actionpack/lib/action_view/helpers/prototype_helper.rb
... | ... | @@ -250,8 +250,10 @@ module ActionView |
250 | 250 | return function |
251 | 251 | end |
252 | 252 | |
253 | - # Observes the field with the DOM ID specified by +field_id+ and makes | |
254 | - # an Ajax call when its contents have changed. | |
253 | + # Observes the field with the DOM ID specified by +field_id+ and calls a | |
254 | + # callback when its contents have changed. The default callback is an | |
255 | + # Ajax call. By default the value of the observed field is sent as a | |
256 | + # parameter with the Ajax call. | |
255 | 257 | # |
256 | 258 | # Required +options+ are either of: |
257 | 259 | # <tt>:url</tt>:: +url_for+-style options for the action to call |
... | ... | @@ -268,14 +270,24 @@ module ActionView |
268 | 270 | # <tt>:update</tt>:: Specifies the DOM ID of the element whose |
269 | 271 | # innerHTML should be updated with the |
270 | 272 | # XMLHttpRequest response text. |
271 | - # <tt>:with</tt>:: A JavaScript expression specifying the | |
272 | - # parameters for the XMLHttpRequest. This defaults | |
273 | - # to 'value', which in the evaluated context | |
274 | - # refers to the new field value. If you specify a | |
275 | - # string without a "=", it'll be extended to mean | |
276 | - # the form key that the value should be assigned to. | |
277 | - # So :with => "term" gives "'term'=value". If a "=" is | |
278 | - # present, no extension will happen. | |
273 | + # <tt>:with</tt>:: A JavaScript expression specifying the parameters | |
274 | + # for the XMLHttpRequest. The default is to send the | |
275 | + # key and value of the observed field. Any custom | |
276 | + # expressions should return a valid URL query string. | |
277 | + # The value of the field is stored in the JavaScript | |
278 | + # variable +value+. | |
279 | + # | |
280 | + # Examples | |
281 | + # | |
282 | + # :with => "'my_custom_key=' + value" | |
283 | + # :with => "'person[name]=' + prompt('New name')" | |
284 | + # :with => "Form.Element.serialize('other-field')" | |
285 | + # | |
286 | + # Finally | |
287 | + # :with => 'name' | |
288 | + # is shorthand for | |
289 | + # :with => "'name=' + value" | |
290 | + # This essentially just changes the key of the parameter. | |
279 | 291 | # <tt>:on</tt>:: Specifies which event handler to observe. By default, |
280 | 292 | # it's set to "changed" for text fields and areas and |
281 | 293 | # "click" for radio buttons and checkboxes. With this, |
... | ... | @@ -291,11 +303,15 @@ module ActionView |
291 | 303 | build_observer('Form.Element.EventObserver', field_id, options) |
292 | 304 | end |
293 | 305 | end |
294 | - | |
295 | - # Like +observe_field+, but operates on an entire form identified by the | |
296 | - # DOM ID +form_id+. +options+ are the same as +observe_field+, except | |
297 | - # the default value of the <tt>:with</tt> option evaluates to the | |
298 | - # serialized (request string) value of the form. | |
306 | + | |
307 | + # Observes the form with the DOM ID specified by +form_id+ and calls a | |
308 | + # callback when its contents have changed. The default callback is an | |
309 | + # Ajax call. By default all fields of the observed field are sent as | |
310 | + # parameters with the Ajax call. | |
311 | + # | |
312 | + # The +options+ for +observe_form+ are the same as the options for | |
313 | + # +observe_field+. The JavaScript variable +value+ available to the | |
314 | + # <tt>:with</tt> option is set to the serialized form by default. | |
299 | 315 | def observe_form(form_id, options = {}) |
300 | 316 | if options[:frequency] |
301 | 317 | build_observer('Form.Observer', form_id, options) |
... | ... | @@ -660,10 +676,10 @@ module ActionView |
660 | 676 | end |
661 | 677 | |
662 | 678 | def build_observer(klass, name, options = {}) |
663 | - if options[:with] && !options[:with].include?("=") | |
679 | + if options[:with] && (options[:with] !~ /[=(.]/) | |
664 | 680 | options[:with] = "'#{options[:with]}=' + value" |
665 | 681 | else |
666 | - options[:with] ||= 'value' if options[:update] | |
682 | + options[:with] ||= 'value' unless options[:function] | |
667 | 683 | end |
668 | 684 | |
669 | 685 | callback = options[:function] || remote_function(options) | ... | ... |
vendor/rails/actionpack/test/activerecord/pagination_test.rb
... | ... | @@ -5,6 +5,8 @@ class PaginationTest < ActiveRecordTestCase |
5 | 5 | |
6 | 6 | class PaginationController < ActionController::Base |
7 | 7 | self.template_root = "#{File.dirname(__FILE__)}/../fixtures/" |
8 | + | |
9 | + around_filter :silence_deprecation_warnings | |
8 | 10 | |
9 | 11 | def simple_paginate |
10 | 12 | @topic_pages, @topics = paginate(:topics) |
... | ... | @@ -67,6 +69,13 @@ class PaginationTest < ActiveRecordTestCase |
67 | 69 | :count => "d.id") |
68 | 70 | render :nothing => true |
69 | 71 | end |
72 | + | |
73 | + | |
74 | + def silence_deprecation_warnings | |
75 | + ActiveSupport::Deprecation.silence do | |
76 | + yield | |
77 | + end | |
78 | + end | |
70 | 79 | |
71 | 80 | def rescue_errors(e) raise e end |
72 | 81 | ... | ... |
vendor/rails/actionpack/test/controller/action_pack_assertions_test.rb
... | ... | @@ -19,6 +19,8 @@ class ActionPackAssertionsController < ActionController::Base |
19 | 19 | |
20 | 20 | def redirect_to_controller() redirect_to :controller => "elsewhere", :action => "flash_me"; end |
21 | 21 | |
22 | + def redirect_to_controller_with_symbol() redirect_to :controller => :elsewhere, :action => :flash_me; end | |
23 | + | |
22 | 24 | def redirect_to_path() redirect_to '/some/path' end |
23 | 25 | |
24 | 26 | def redirect_to_named_route() redirect_to route_one_url end |
... | ... | @@ -555,6 +557,17 @@ class ActionPackAssertionsControllerTest < Test::Unit::TestCase |
555 | 557 | assert_redirected_to 'http://test.host/some/path' |
556 | 558 | end |
557 | 559 | |
560 | + def test_assert_redirection_with_symbol | |
561 | + process :redirect_to_controller_with_symbol | |
562 | + assert_nothing_raised { | |
563 | + assert_redirected_to :controller => "elsewhere", :action => "flash_me" | |
564 | + } | |
565 | + process :redirect_to_controller_with_symbol | |
566 | + assert_nothing_raised { | |
567 | + assert_redirected_to :controller => :elsewhere, :action => :flash_me | |
568 | + } | |
569 | + end | |
570 | + | |
558 | 571 | def test_redirected_to_with_nested_controller |
559 | 572 | @controller = Admin::InnerModuleController.new |
560 | 573 | get :redirect_to_absolute_controller | ... | ... |
vendor/rails/actionpack/test/controller/addresses_render_test.rb
... | ... | @@ -39,7 +39,10 @@ class AddressesTest < Test::Unit::TestCase |
39 | 39 | end |
40 | 40 | |
41 | 41 | def test_list |
42 | - get :list | |
42 | + # because pagination is deprecated | |
43 | + ActiveSupport::Deprecation.silence do | |
44 | + get :list | |
45 | + end | |
43 | 46 | assert_equal "We only need to get this far!", @response.body.chomp |
44 | 47 | end |
45 | 48 | end | ... | ... |
vendor/rails/actionpack/test/controller/base_test.rb
... | ... | @@ -88,7 +88,7 @@ class ControllerInstanceTests < Test::Unit::TestCase |
88 | 88 | # Mocha adds methods to Object which are then included in the public_instance_methods |
89 | 89 | # This method hides those from the controller so the above tests won't know the difference |
90 | 90 | def hide_mocha_methods_from_controller(controller) |
91 | - mocha_methods = [:expects, :metaclass, :mocha, :mocha_inspect, :reset_mocha, :stubba_object, :stubba_method, :stubs, :verify] | |
91 | + mocha_methods = [:expects, :metaclass, :mocha, :mocha_inspect, :reset_mocha, :stubba_object, :stubba_method, :stubs, :verify, :__is_a__, :__metaclass__] | |
92 | 92 | controller.class.send(:hide_action, *mocha_methods) |
93 | 93 | end |
94 | 94 | ... | ... |
vendor/rails/actionpack/test/controller/caching_test.rb
... | ... | @@ -97,6 +97,7 @@ class ActionCachingTestController < ActionController::Base |
97 | 97 | caches_action :index |
98 | 98 | |
99 | 99 | def index |
100 | + sleep 0.01 | |
100 | 101 | @cache_this = Time.now.to_f.to_s |
101 | 102 | render :text => @cache_this |
102 | 103 | end |
... | ... | @@ -195,7 +196,7 @@ class ActionCacheTest < Test::Unit::TestCase |
195 | 196 | def test_xml_version_of_resource_is_treated_as_different_cache |
196 | 197 | @mock_controller.mock_url_for = 'http://example.org/posts/' |
197 | 198 | @mock_controller.mock_path = '/posts/index.xml' |
198 | - path_object = @path_class.new(@mock_controller) | |
199 | + path_object = @path_class.new(@mock_controller, {}) | |
199 | 200 | assert_equal 'xml', path_object.extension |
200 | 201 | assert_equal 'example.org/posts/index.xml', path_object.path |
201 | 202 | end |
... | ... | @@ -204,7 +205,7 @@ class ActionCacheTest < Test::Unit::TestCase |
204 | 205 | @mock_controller.mock_url_for = 'http://example.org/' |
205 | 206 | @mock_controller.mock_path = '/' |
206 | 207 | |
207 | - assert_equal 'example.org/index', @path_class.path_for(@mock_controller) | |
208 | + assert_equal 'example.org/index', @path_class.path_for(@mock_controller, {}) | |
208 | 209 | end |
209 | 210 | |
210 | 211 | def test_file_extensions | ... | ... |
vendor/rails/actionpack/test/controller/cookie_test.rb
... | ... | @@ -22,7 +22,7 @@ class CookieTest < Test::Unit::TestCase |
22 | 22 | cookies["user_name"] = { "value" => "david", "expires" => Time.local(2005, 10, 10) } |
23 | 23 | cookies["login"] = "XJ-122" |
24 | 24 | end |
25 | - | |
25 | + | |
26 | 26 | def access_frozen_cookies |
27 | 27 | cookies["will"] = "work" |
28 | 28 | end |
... | ... | @@ -31,6 +31,11 @@ class CookieTest < Test::Unit::TestCase |
31 | 31 | cookies.delete("user_name") |
32 | 32 | end |
33 | 33 | |
34 | + def delete_cookie_with_path | |
35 | + cookies.delete("user_name", :path => '/beaten') | |
36 | + render_text "hello world" | |
37 | + end | |
38 | + | |
34 | 39 | def rescue_action(e) |
35 | 40 | raise unless ActionController::MissingTemplate # No templates here, and we don't care about the output |
36 | 41 | end |
... | ... | @@ -85,4 +90,18 @@ class CookieTest < Test::Unit::TestCase |
85 | 90 | assert_equal "david", jar["user_name"] |
86 | 91 | assert_equal nil, jar["something_else"] |
87 | 92 | end |
93 | + | |
94 | + def test_cookiejar_accessor_with_array_value | |
95 | + a = %w{1 2 3} | |
96 | + @request.cookies["pages"] = CGI::Cookie.new("name" => "pages", "value" => a, "expires" => Time.local(2025, 10, 10)) | |
97 | + @controller.request = @request | |
98 | + jar = ActionController::CookieJar.new(@controller) | |
99 | + assert_equal a, jar["pages"] | |
100 | + end | |
101 | + | |
102 | + def test_delete_cookie_with_path | |
103 | + get :delete_cookie_with_path | |
104 | + assert_equal "/beaten", @response.headers["cookie"].first.path | |
105 | + assert_not_equal "/", @response.headers["cookie"].first.path | |
106 | + end | |
88 | 107 | end | ... | ... |
vendor/rails/actionpack/test/controller/deprecation/deprecated_base_methods_test.rb
1 | 1 | require File.dirname(__FILE__) + '/../../abstract_unit' |
2 | 2 | |
3 | 3 | class DeprecatedBaseMethodsTest < Test::Unit::TestCase |
4 | + # ActiveRecord model mock to test pagination deprecation | |
5 | + class DummyModel | |
6 | + def self.find(*args) [] end | |
7 | + def self.count(*args) 0 end | |
8 | + end | |
9 | + | |
4 | 10 | class Target < ActionController::Base |
5 | 11 | def deprecated_symbol_parameter_to_url_for |
6 | 12 | redirect_to(url_for(:home_url, "superstars")) |
... | ... | @@ -18,6 +24,11 @@ class DeprecatedBaseMethodsTest < Test::Unit::TestCase |
18 | 24 | this_method_doesnt_exist |
19 | 25 | end |
20 | 26 | |
27 | + def pagination | |
28 | + paginate :dummy_models, :class_name => 'DeprecatedBaseMethodsTest::DummyModel' | |
29 | + render :nothing => true | |
30 | + end | |
31 | + | |
21 | 32 | def rescue_action(e) raise e end |
22 | 33 | end |
23 | 34 | |
... | ... | @@ -27,6 +38,7 @@ class DeprecatedBaseMethodsTest < Test::Unit::TestCase |
27 | 38 | @request = ActionController::TestRequest.new |
28 | 39 | @response = ActionController::TestResponse.new |
29 | 40 | @controller = Target.new |
41 | + @controller.logger = Logger.new(nil) unless @controller.logger | |
30 | 42 | end |
31 | 43 | |
32 | 44 | def test_deprecated_symbol_parameter_to_url_for |
... | ... | @@ -57,4 +69,10 @@ class DeprecatedBaseMethodsTest < Test::Unit::TestCase |
57 | 69 | error = Test::Unit::Error.new('testing ur doodz', e) |
58 | 70 | assert_not_deprecated { error.message } |
59 | 71 | end |
72 | + | |
73 | + def test_pagination_deprecation | |
74 | + assert_deprecated('svn://errtheblog.com/svn/plugins/classic_pagination') do | |
75 | + get :pagination | |
76 | + end | |
77 | + end | |
60 | 78 | end | ... | ... |
vendor/rails/actionpack/test/controller/filter_params_test.rb
... | ... | @@ -16,6 +16,7 @@ class FilterParamTest < Test::Unit::TestCase |
16 | 16 | assert @controller.respond_to?(:filter_parameters) |
17 | 17 | |
18 | 18 | test_hashes = [[{},{},[]], |
19 | + [{'foo'=>nil},{'foo'=>nil},[]], | |
19 | 20 | [{'foo'=>'bar'},{'foo'=>'bar'},[]], |
20 | 21 | [{'foo'=>'bar'},{'foo'=>'bar'},%w'food'], |
21 | 22 | [{'foo'=>'bar'},{'foo'=>'[FILTERED]'},%w'foo'], | ... | ... |
vendor/rails/actionpack/test/controller/filters_test.rb
... | ... | @@ -14,7 +14,7 @@ class FilterTest < Test::Unit::TestCase |
14 | 14 | @ran_filter ||= [] |
15 | 15 | @ran_filter << "ensure_login" |
16 | 16 | end |
17 | - | |
17 | + | |
18 | 18 | def clean_up |
19 | 19 | @ran_after_filter ||= [] |
20 | 20 | @ran_after_filter << "clean_up" |
... | ... | @@ -62,7 +62,7 @@ class FilterTest < Test::Unit::TestCase |
62 | 62 | render :inline => "something else" |
63 | 63 | end |
64 | 64 | end |
65 | - | |
65 | + | |
66 | 66 | class ConditionalFilterController < ActionController::Base |
67 | 67 | def show |
68 | 68 | render :inline => "ran action" |
... | ... | @@ -86,7 +86,7 @@ class FilterTest < Test::Unit::TestCase |
86 | 86 | @ran_filter ||= [] |
87 | 87 | @ran_filter << "clean_up_tmp" |
88 | 88 | end |
89 | - | |
89 | + | |
90 | 90 | def rescue_action(e) raise(e) end |
91 | 91 | end |
92 | 92 | |
... | ... | @@ -94,7 +94,7 @@ class FilterTest < Test::Unit::TestCase |
94 | 94 | before_filter :ensure_login, :except => [ :show_without_filter, :another_action ] |
95 | 95 | end |
96 | 96 | |
97 | - class OnlyConditionSymController < ConditionalFilterController | |
97 | + class OnlyConditionSymController < ConditionalFilterController | |
98 | 98 | before_filter :ensure_login, :only => :show |
99 | 99 | end |
100 | 100 | |
... | ... | @@ -104,10 +104,10 @@ class FilterTest < Test::Unit::TestCase |
104 | 104 | |
105 | 105 | class BeforeAndAfterConditionController < ConditionalFilterController |
106 | 106 | before_filter :ensure_login, :only => :show |
107 | - after_filter :clean_up_tmp, :only => :show | |
107 | + after_filter :clean_up_tmp, :only => :show | |
108 | 108 | end |
109 | - | |
110 | - class OnlyConditionProcController < ConditionalFilterController | |
109 | + | |
110 | + class OnlyConditionProcController < ConditionalFilterController | |
111 | 111 | before_filter(:only => :show) {|c| c.assigns["ran_proc_filter"] = true } |
112 | 112 | end |
113 | 113 | |
... | ... | @@ -131,6 +131,14 @@ class FilterTest < Test::Unit::TestCase |
131 | 131 | before_filter(ConditionalClassFilter, :ensure_login, Proc.new {|c| c.assigns["ran_proc_filter1"] = true }, :except => :show_without_filter) { |c| c.assigns["ran_proc_filter2"] = true} |
132 | 132 | end |
133 | 133 | |
134 | + class EmptyFilterChainController < TestController | |
135 | + self.filter_chain.clear | |
136 | + def show | |
137 | + @action_executed = true | |
138 | + render :text => "yawp!" | |
139 | + end | |
140 | + end | |
141 | + | |
134 | 142 | class PrependingController < TestController |
135 | 143 | prepend_before_filter :wonderful_life |
136 | 144 | # skip_before_filter :fire_flash |
... | ... | @@ -145,7 +153,7 @@ class FilterTest < Test::Unit::TestCase |
145 | 153 | class ConditionalSkippingController < TestController |
146 | 154 | skip_before_filter :ensure_login, :only => [ :login ] |
147 | 155 | skip_after_filter :clean_up, :only => [ :login ] |
148 | - | |
156 | + | |
149 | 157 | before_filter :find_user, :only => [ :change_password ] |
150 | 158 | |
151 | 159 | def login |
... | ... | @@ -155,7 +163,7 @@ class FilterTest < Test::Unit::TestCase |
155 | 163 | def change_password |
156 | 164 | render :inline => "ran action" |
157 | 165 | end |
158 | - | |
166 | + | |
159 | 167 | protected |
160 | 168 | def find_user |
161 | 169 | @ran_filter ||= [] |
... | ... | @@ -166,15 +174,15 @@ class FilterTest < Test::Unit::TestCase |
166 | 174 | class ConditionalParentOfConditionalSkippingController < ConditionalFilterController |
167 | 175 | before_filter :conditional_in_parent, :only => [:show, :another_action] |
168 | 176 | after_filter :conditional_in_parent, :only => [:show, :another_action] |
169 | - | |
177 | + | |
170 | 178 | private |
171 | - | |
179 | + | |
172 | 180 | def conditional_in_parent |
173 | 181 | @ran_filter ||= [] |
174 | 182 | @ran_filter << 'conditional_in_parent' |
175 | 183 | end |
176 | 184 | end |
177 | - | |
185 | + | |
178 | 186 | class ChildOfConditionalParentController < ConditionalParentOfConditionalSkippingController |
179 | 187 | skip_before_filter :conditional_in_parent, :only => :another_action |
180 | 188 | skip_after_filter :conditional_in_parent, :only => :another_action |
... | ... | @@ -197,7 +205,7 @@ class FilterTest < Test::Unit::TestCase |
197 | 205 | controller.assigns["was_audited"] = true |
198 | 206 | end |
199 | 207 | end |
200 | - | |
208 | + | |
201 | 209 | class AroundFilter |
202 | 210 | def before(controller) |
203 | 211 | @execution_log = "before" |
... | ... | @@ -209,7 +217,7 @@ class FilterTest < Test::Unit::TestCase |
209 | 217 | controller.assigns["execution_log"] = @execution_log + " and after" |
210 | 218 | controller.assigns["after_ran"] = true |
211 | 219 | controller.class.execution_log << " after aroundfilter " if controller.respond_to? :execution_log |
212 | - end | |
220 | + end | |
213 | 221 | end |
214 | 222 | |
215 | 223 | class AppendedAroundFilter |
... | ... | @@ -219,12 +227,12 @@ class FilterTest < Test::Unit::TestCase |
219 | 227 | |
220 | 228 | def after(controller) |
221 | 229 | controller.class.execution_log << " after appended aroundfilter " |
222 | - end | |
223 | - end | |
224 | - | |
230 | + end | |
231 | + end | |
232 | + | |
225 | 233 | class AuditController < ActionController::Base |
226 | 234 | before_filter(AuditFilter) |
227 | - | |
235 | + | |
228 | 236 | def show |
229 | 237 | render_text "hello" |
230 | 238 | end |
... | ... | @@ -234,6 +242,14 @@ class FilterTest < Test::Unit::TestCase |
234 | 242 | around_filter AroundFilter.new |
235 | 243 | end |
236 | 244 | |
245 | + class BeforeAfterClassFilterController < PrependingController | |
246 | + begin | |
247 | + filter = AroundFilter.new | |
248 | + before_filter filter | |
249 | + after_filter filter | |
250 | + end | |
251 | + end | |
252 | + | |
237 | 253 | class MixedFilterController < PrependingController |
238 | 254 | cattr_accessor :execution_log |
239 | 255 | |
... | ... | @@ -247,7 +263,7 @@ class FilterTest < Test::Unit::TestCase |
247 | 263 | after_filter { |c| c.class.execution_log << " after procfilter " } |
248 | 264 | append_around_filter AppendedAroundFilter.new |
249 | 265 | end |
250 | - | |
266 | + | |
251 | 267 | class MixedSpecializationController < ActionController::Base |
252 | 268 | class OutOfOrder < StandardError; end |
253 | 269 | |
... | ... | @@ -285,6 +301,101 @@ class FilterTest < Test::Unit::TestCase |
285 | 301 | end |
286 | 302 | end |
287 | 303 | |
304 | + class PrependingBeforeAndAfterController < ActionController::Base | |
305 | + prepend_before_filter :before_all | |
306 | + prepend_after_filter :after_all | |
307 | + before_filter :between_before_all_and_after_all | |
308 | + | |
309 | + def before_all | |
310 | + @ran_filter ||= [] | |
311 | + @ran_filter << 'before_all' | |
312 | + end | |
313 | + | |
314 | + def after_all | |
315 | + @ran_filter ||= [] | |
316 | + @ran_filter << 'after_all' | |
317 | + end | |
318 | + | |
319 | + def between_before_all_and_after_all | |
320 | + @ran_filter ||= [] | |
321 | + @ran_filter << 'between_before_all_and_after_all' | |
322 | + end | |
323 | + def show | |
324 | + render :text => 'hello' | |
325 | + end | |
326 | + end | |
327 | + | |
328 | + class NonYieldingAroundFilterController < ActionController::Base | |
329 | + | |
330 | + before_filter :filter_one | |
331 | + around_filter :non_yielding_filter | |
332 | + before_filter :filter_two | |
333 | + after_filter :filter_three | |
334 | + | |
335 | + def index | |
336 | + render :inline => "index" | |
337 | + end | |
338 | + | |
339 | + #make sure the controller complains | |
340 | + def rescue_action(e); raise e; end | |
341 | + | |
342 | + private | |
343 | + | |
344 | + def filter_one | |
345 | + @filters ||= [] | |
346 | + @filters << "filter_one" | |
347 | + end | |
348 | + | |
349 | + def filter_two | |
350 | + @filters << "filter_two" | |
351 | + end | |
352 | + | |
353 | + def non_yielding_filter | |
354 | + @filters << "zomg it didn't yield" | |
355 | + @filter_return_value | |
356 | + end | |
357 | + | |
358 | + def filter_three | |
359 | + @filters << "filter_three" | |
360 | + end | |
361 | + | |
362 | + end | |
363 | + | |
364 | + def test_non_yielding_around_filters_not_returning_false_do_not_raise | |
365 | + controller = NonYieldingAroundFilterController.new | |
366 | + controller.instance_variable_set "@filter_return_value", true | |
367 | + assert_nothing_raised do | |
368 | + test_process(controller, "index") | |
369 | + end | |
370 | + end | |
371 | + | |
372 | + def test_non_yielding_around_filters_returning_false_do_not_raise | |
373 | + controller = NonYieldingAroundFilterController.new | |
374 | + controller.instance_variable_set "@filter_return_value", false | |
375 | + assert_nothing_raised do | |
376 | + test_process(controller, "index") | |
377 | + end | |
378 | + end | |
379 | + | |
380 | + def test_after_filters_are_not_run_if_around_filter_returns_false | |
381 | + controller = NonYieldingAroundFilterController.new | |
382 | + controller.instance_variable_set "@filter_return_value", false | |
383 | + test_process(controller, "index") | |
384 | + assert_equal ["filter_one", "zomg it didn't yield"], controller.assigns['filters'] | |
385 | + end | |
386 | + | |
387 | + def test_after_filters_are_not_run_if_around_filter_does_not_yield | |
388 | + controller = NonYieldingAroundFilterController.new | |
389 | + controller.instance_variable_set "@filter_return_value", true | |
390 | + test_process(controller, "index") | |
391 | + assert_equal ["filter_one", "zomg it didn't yield"], controller.assigns['filters'] | |
392 | + end | |
393 | + | |
394 | + def test_empty_filter_chain | |
395 | + assert_equal 0, EmptyFilterChainController.filter_chain.size | |
396 | + assert test_process(EmptyFilterChainController).template.assigns['action_executed'] | |
397 | + end | |
398 | + | |
288 | 399 | def test_added_filter_to_inheritance_graph |
289 | 400 | assert_equal [ :ensure_login ], TestController.before_filters |
290 | 401 | end |
... | ... | @@ -292,11 +403,11 @@ class FilterTest < Test::Unit::TestCase |
292 | 403 | def test_base_class_in_isolation |
293 | 404 | assert_equal [ ], ActionController::Base.before_filters |
294 | 405 | end |
295 | - | |
406 | + | |
296 | 407 | def test_prepending_filter |
297 | 408 | assert_equal [ :wonderful_life, :ensure_login ], PrependingController.before_filters |
298 | 409 | end |
299 | - | |
410 | + | |
300 | 411 | def test_running_filters |
301 | 412 | assert_equal %w( wonderful_life ensure_login ), test_process(PrependingController).template.assigns["ran_filter"] |
302 | 413 | end |
... | ... | @@ -304,11 +415,11 @@ class FilterTest < Test::Unit::TestCase |
304 | 415 | def test_running_filters_with_proc |
305 | 416 | assert test_process(ProcController).template.assigns["ran_proc_filter"] |
306 | 417 | end |
307 | - | |
418 | + | |
308 | 419 | def test_running_filters_with_implicit_proc |
309 | 420 | assert test_process(ImplicitProcController).template.assigns["ran_proc_filter"] |
310 | 421 | end |
311 | - | |
422 | + | |
312 | 423 | def test_running_filters_with_class |
313 | 424 | assert test_process(AuditController).template.assigns["was_audited"] |
314 | 425 | end |
... | ... | @@ -319,7 +430,7 @@ class FilterTest < Test::Unit::TestCase |
319 | 430 | assert response.template.assigns["ran_class_filter"] |
320 | 431 | assert response.template.assigns["ran_proc_filter1"] |
321 | 432 | assert response.template.assigns["ran_proc_filter2"] |
322 | - | |
433 | + | |
323 | 434 | response = test_process(AnomolousYetValidConditionController, "show_without_filter") |
324 | 435 | assert_equal nil, response.template.assigns["ran_filter"] |
325 | 436 | assert !response.template.assigns["ran_class_filter"] |
... | ... | @@ -373,6 +484,12 @@ class FilterTest < Test::Unit::TestCase |
373 | 484 | assert controller.template.assigns["after_ran"] |
374 | 485 | end |
375 | 486 | |
487 | + def test_before_after_class_filter | |
488 | + controller = test_process(BeforeAfterClassFilterController) | |
489 | + assert controller.template.assigns["before_ran"] | |
490 | + assert controller.template.assigns["after_ran"] | |
491 | + end | |
492 | + | |
376 | 493 | def test_having_properties_in_around_filter |
377 | 494 | controller = test_process(AroundFilterController) |
378 | 495 | assert_equal "before and after", controller.template.assigns["execution_log"] |
... | ... | @@ -381,10 +498,10 @@ class FilterTest < Test::Unit::TestCase |
381 | 498 | def test_prepending_and_appending_around_filter |
382 | 499 | controller = test_process(MixedFilterController) |
383 | 500 | assert_equal " before aroundfilter before procfilter before appended aroundfilter " + |
384 | - " after appended aroundfilter after aroundfilter after procfilter ", | |
501 | + " after appended aroundfilter after aroundfilter after procfilter ", | |
385 | 502 | MixedFilterController.execution_log |
386 | 503 | end |
387 | - | |
504 | + | |
388 | 505 | def test_rendering_breaks_filtering_chain |
389 | 506 | response = test_process(RenderingController) |
390 | 507 | assert_equal "something else", response.body |
... | ... | @@ -412,6 +529,12 @@ class FilterTest < Test::Unit::TestCase |
412 | 529 | end |
413 | 530 | end |
414 | 531 | |
532 | + def test_running_prepended_before_and_after_filter | |
533 | + assert_equal 3, PrependingBeforeAndAfterController.filter_chain.length | |
534 | + response = test_process(PrependingBeforeAndAfterController) | |
535 | + assert_equal %w( before_all between_before_all_and_after_all after_all ), response.template.assigns["ran_filter"] | |
536 | + end | |
537 | + | |
415 | 538 | def test_conditional_skipping_of_filters |
416 | 539 | assert_nil test_process(ConditionalSkippingController, "login").template.assigns["ran_filter"] |
417 | 540 | assert_equal %w( ensure_login find_user ), test_process(ConditionalSkippingController, "change_password").template.assigns["ran_filter"] | ... | ... |
vendor/rails/actionpack/test/controller/integration_test.rb
... | ... | @@ -11,7 +11,7 @@ require 'stubba' |
11 | 11 | module ActionController |
12 | 12 | module Integration |
13 | 13 | class Session |
14 | - def process | |
14 | + def process(*args) | |
15 | 15 | end |
16 | 16 | |
17 | 17 | def generic_url_rewriter |
... | ... | @@ -56,8 +56,7 @@ class SessionTest < Test::Unit::TestCase |
56 | 56 | |
57 | 57 | @session.expects(:get).with(path,args) |
58 | 58 | |
59 | - redirects = [true, true, false] | |
60 | - @session.stubs(:redirect?).returns(lambda { redirects.shift }) | |
59 | + @session.stubs(:redirect?).returns(true).then.returns(true).then.returns(false) | |
61 | 60 | @session.expects(:follow_redirect!).times(2) |
62 | 61 | |
63 | 62 | @session.stubs(:status).returns(200) |
... | ... | @@ -69,8 +68,7 @@ class SessionTest < Test::Unit::TestCase |
69 | 68 | |
70 | 69 | @session.expects(:post).with(path,args) |
71 | 70 | |
72 | - redirects = [true, true, false] | |
73 | - @session.stubs(:redirect?).returns(lambda { redirects.shift }) | |
71 | + @session.stubs(:redirect?).returns(true).then.returns(true).then.returns(false) | |
74 | 72 | @session.expects(:follow_redirect!).times(2) |
75 | 73 | |
76 | 74 | @session.stubs(:status).returns(200) |
... | ... | @@ -134,15 +132,102 @@ class SessionTest < Test::Unit::TestCase |
134 | 132 | @session.head(path,params,headers) |
135 | 133 | end |
136 | 134 | |
137 | - def test_xml_http_request | |
135 | + def test_xml_http_request_deprecated_call | |
138 | 136 | path = "/index"; params = "blah"; headers = {:location => 'blah'} |
139 | 137 | headers_after_xhr = headers.merge( |
140 | 138 | "X-Requested-With" => "XMLHttpRequest", |
141 | 139 | "Accept" => "text/javascript, text/html, application/xml, text/xml, */*" |
142 | 140 | ) |
143 | - @session.expects(:post).with(path,params,headers_after_xhr) | |
144 | - @session.xml_http_request(path,params,headers) | |
141 | + @session.expects(:process).with(:post,path,params,headers_after_xhr) | |
142 | + assert_deprecated { @session.xml_http_request(path,params,headers) } | |
145 | 143 | end |
144 | + | |
145 | + def test_xml_http_request_get | |
146 | + path = "/index"; params = "blah"; headers = {:location => 'blah'} | |
147 | + headers_after_xhr = headers.merge( | |
148 | + "X-Requested-With" => "XMLHttpRequest", | |
149 | + "Accept" => "text/javascript, text/html, application/xml, text/xml, */*" | |
150 | + ) | |
151 | + @session.expects(:process).with(:get,path,params,headers_after_xhr) | |
152 | + @session.xml_http_request(:get,path,params,headers) | |
153 | + end | |
154 | + | |
155 | + def test_xml_http_request_post | |
156 | + path = "/index"; params = "blah"; headers = {:location => 'blah'} | |
157 | + headers_after_xhr = headers.merge( | |
158 | + "X-Requested-With" => "XMLHttpRequest", | |
159 | + "Accept" => "text/javascript, text/html, application/xml, text/xml, */*" | |
160 | + ) | |
161 | + @session.expects(:process).with(:post,path,params,headers_after_xhr) | |
162 | + @session.xml_http_request(:post,path,params,headers) | |
163 | + end | |
164 | + | |
165 | + def test_xml_http_request_put | |
166 | + path = "/index"; params = "blah"; headers = {:location => 'blah'} | |
167 | + headers_after_xhr = headers.merge( | |
168 | + "X-Requested-With" => "XMLHttpRequest", | |
169 | + "Accept" => "text/javascript, text/html, application/xml, text/xml, */*" | |
170 | + ) | |
171 | + @session.expects(:process).with(:put,path,params,headers_after_xhr) | |
172 | + @session.xml_http_request(:put,path,params,headers) | |
173 | + end | |
174 | + | |
175 | + def test_xml_http_request_delete | |
176 | + path = "/index"; params = "blah"; headers = {:location => 'blah'} | |
177 | + headers_after_xhr = headers.merge( | |
178 | + "X-Requested-With" => "XMLHttpRequest", | |
179 | + "Accept" => "text/javascript, text/html, application/xml, text/xml, */*" | |
180 | + ) | |
181 | + @session.expects(:process).with(:delete,path,params,headers_after_xhr) | |
182 | + @session.xml_http_request(:delete,path,params,headers) | |
183 | + end | |
184 | + | |
185 | + def test_xml_http_request_head | |
186 | + path = "/index"; params = "blah"; headers = {:location => 'blah'} | |
187 | + headers_after_xhr = headers.merge( | |
188 | + "X-Requested-With" => "XMLHttpRequest", | |
189 | + "Accept" => "text/javascript, text/html, application/xml, text/xml, */*" | |
190 | + ) | |
191 | + @session.expects(:process).with(:head,path,params,headers_after_xhr) | |
192 | + @session.xml_http_request(:head,path,params,headers) | |
193 | + end | |
194 | +end | |
195 | + | |
196 | +class IntegrationTestTest < Test::Unit::TestCase | |
197 | + | |
198 | + def setup | |
199 | + @test = ::ActionController::IntegrationTest.new(:default_test) | |
200 | + @test.class.stubs(:fixture_table_names).returns([]) | |
201 | + @session = @test.open_session | |
202 | + end | |
203 | + | |
204 | + def test_opens_new_session | |
205 | + @test.class.expects(:fixture_table_names).times(2).returns(['foo']) | |
206 | + | |
207 | + session1 = @test.open_session { |sess| } | |
208 | + session2 = @test.open_session # implicit session | |
209 | + | |
210 | + assert_equal ::ActionController::Integration::Session, session1.class | |
211 | + assert_equal ::ActionController::Integration::Session, session2.class | |
212 | + assert_not_equal session1, session2 | |
213 | + end | |
214 | + | |
215 | +end | |
216 | + | |
217 | +# Tests that integration tests don't call Controller test methods for processing. | |
218 | +# Integration tests have their own setup and teardown. | |
219 | +class IntegrationTestUsesCorrectClass < ActionController::IntegrationTest | |
220 | + | |
221 | + def self.fixture_table_names | |
222 | + [] | |
223 | + end | |
224 | + | |
225 | + def test_integration_methods_called | |
226 | + %w( get post head put delete ).each do |verb| | |
227 | + assert_nothing_raised("'#{verb}' should use integration test methods") { send(verb, '/') } | |
228 | + end | |
229 | + end | |
230 | + | |
146 | 231 | end |
147 | 232 | |
148 | 233 | # TODO | ... | ... |
vendor/rails/actionpack/test/controller/resources_test.rb
... | ... | @@ -10,8 +10,9 @@ class ThreadsController < ResourcesController; end |
10 | 10 | class MessagesController < ResourcesController; end |
11 | 11 | class CommentsController < ResourcesController; end |
12 | 12 | |
13 | -class AccountController < ResourcesController; end | |
14 | -class AdminController < ResourcesController; end | |
13 | +class AccountController < ResourcesController; end | |
14 | +class AdminController < ResourcesController; end | |
15 | +class ProductsController < ResourcesController; end | |
15 | 16 | |
16 | 17 | class ResourcesTest < Test::Unit::TestCase |
17 | 18 | def test_should_arrange_actions |
... | ... | @@ -63,13 +64,13 @@ class ResourcesTest < Test::Unit::TestCase |
63 | 64 | end |
64 | 65 | end |
65 | 66 | |
66 | - def test_multile_with_path_prefix | |
67 | + def test_multiple_with_path_prefix | |
67 | 68 | with_restful_routing :messages, :comments, :path_prefix => '/thread/:thread_id' do |
68 | 69 | assert_simply_restful_for :messages, :path_prefix => 'thread/5/', :options => { :thread_id => '5' } |
69 | 70 | assert_simply_restful_for :comments, :path_prefix => 'thread/5/', :options => { :thread_id => '5' } |
70 | 71 | end |
71 | 72 | end |
72 | - | |
73 | + | |
73 | 74 | def test_with_name_prefix |
74 | 75 | with_restful_routing :messages, :name_prefix => 'post_' do |
75 | 76 | assert_simply_restful_for :messages, :name_prefix => 'post_' |
... | ... | @@ -78,7 +79,7 @@ class ResourcesTest < Test::Unit::TestCase |
78 | 79 | |
79 | 80 | def test_with_collection_action |
80 | 81 | rss_options = {:action => 'rss'} |
81 | - rss_path = "/messages;rss" | |
82 | + rss_path = "/messages/rss" | |
82 | 83 | actions = { 'a' => :put, 'b' => :post, 'c' => :delete } |
83 | 84 | |
84 | 85 | with_restful_routing :messages, :collection => { :rss => :get }.merge(actions) do |
... | ... | @@ -86,14 +87,14 @@ class ResourcesTest < Test::Unit::TestCase |
86 | 87 | assert_routing rss_path, options.merge(rss_options) |
87 | 88 | |
88 | 89 | actions.each do |action, method| |
89 | - assert_recognizes(options.merge(:action => action), :path => "/messages;#{action}", :method => method) | |
90 | + assert_recognizes(options.merge(:action => action), :path => "/messages/#{action}", :method => method) | |
90 | 91 | end |
91 | 92 | end |
92 | 93 | |
93 | 94 | assert_restful_named_routes_for :messages do |options| |
94 | 95 | assert_named_route rss_path, :rss_messages_path, rss_options |
95 | 96 | actions.keys.each do |action| |
96 | - assert_named_route "/messages;#{action}", "#{action}_messages_path", :action => action | |
97 | + assert_named_route "/messages/#{action}", "#{action}_messages_path", :action => action | |
97 | 98 | end |
98 | 99 | end |
99 | 100 | end |
... | ... | @@ -103,7 +104,7 @@ class ResourcesTest < Test::Unit::TestCase |
103 | 104 | [:put, :post].each do |method| |
104 | 105 | with_restful_routing :messages, :member => { :mark => method } do |
105 | 106 | mark_options = {:action => 'mark', :id => '1'} |
106 | - mark_path = "/messages/1;mark" | |
107 | + mark_path = "/messages/1/mark" | |
107 | 108 | assert_restful_routes_for :messages do |options| |
108 | 109 | assert_recognizes(options.merge(mark_options), :path => mark_path, :method => method) |
109 | 110 | end |
... | ... | @@ -120,7 +121,7 @@ class ResourcesTest < Test::Unit::TestCase |
120 | 121 | with_restful_routing :messages, :member => { :mark => method, :unmark => method } do |
121 | 122 | %w(mark unmark).each do |action| |
122 | 123 | action_options = {:action => action, :id => '1'} |
123 | - action_path = "/messages/1;#{action}" | |
124 | + action_path = "/messages/1/#{action}" | |
124 | 125 | assert_restful_routes_for :messages do |options| |
125 | 126 | assert_recognizes(options.merge(action_options), :path => action_path, :method => method) |
126 | 127 | end |
... | ... | @@ -136,7 +137,7 @@ class ResourcesTest < Test::Unit::TestCase |
136 | 137 | def test_with_new_action |
137 | 138 | with_restful_routing :messages, :new => { :preview => :post } do |
138 | 139 | preview_options = {:action => 'preview'} |
139 | - preview_path = "/messages/new;preview" | |
140 | + preview_path = "/messages/new/preview" | |
140 | 141 | assert_restful_routes_for :messages do |options| |
141 | 142 | assert_recognizes(options.merge(preview_options), :path => preview_path, :method => :post) |
142 | 143 | end |
... | ... | @@ -178,9 +179,11 @@ class ResourcesTest < Test::Unit::TestCase |
178 | 179 | assert_simply_restful_for :threads |
179 | 180 | assert_simply_restful_for :messages, |
180 | 181 | :path_prefix => 'threads/1/', |
182 | + :name_prefix => 'thread_', | |
181 | 183 | :options => { :thread_id => '1' } |
182 | 184 | assert_simply_restful_for :comments, |
183 | 185 | :path_prefix => 'threads/1/messages/2/', |
186 | + :name_prefix => 'thread_message_', | |
184 | 187 | :options => { :thread_id => '1', :message_id => '2' } |
185 | 188 | end |
186 | 189 | end |
... | ... | @@ -217,9 +220,9 @@ class ResourcesTest < Test::Unit::TestCase |
217 | 220 | admin.resource :account |
218 | 221 | end |
219 | 222 | end |
220 | - | |
223 | + | |
221 | 224 | assert_singleton_restful_for :admin |
222 | - assert_singleton_restful_for :account, :path_prefix => 'admin/' | |
225 | + assert_singleton_restful_for :account, :path_prefix => 'admin/', :name_prefix => 'admin_' | |
223 | 226 | end |
224 | 227 | end |
225 | 228 | |
... | ... | @@ -227,7 +230,7 @@ class ResourcesTest < Test::Unit::TestCase |
227 | 230 | [:put, :post].each do |method| |
228 | 231 | with_singleton_resources :account, :member => { :reset => method } do |
229 | 232 | reset_options = {:action => 'reset'} |
230 | - reset_path = "/account;reset" | |
233 | + reset_path = "/account/reset" | |
231 | 234 | assert_singleton_routes_for :account do |options| |
232 | 235 | assert_recognizes(options.merge(reset_options), :path => reset_path, :method => method) |
233 | 236 | end |
... | ... | @@ -244,7 +247,7 @@ class ResourcesTest < Test::Unit::TestCase |
244 | 247 | with_singleton_resources :account, :member => { :reset => method, :disable => method } do |
245 | 248 | %w(reset disable).each do |action| |
246 | 249 | action_options = {:action => action} |
247 | - action_path = "/account;#{action}" | |
250 | + action_path = "/account/#{action}" | |
248 | 251 | assert_singleton_routes_for :account do |options| |
249 | 252 | assert_recognizes(options.merge(action_options), :path => action_path, :method => method) |
250 | 253 | end |
... | ... | @@ -264,9 +267,9 @@ class ResourcesTest < Test::Unit::TestCase |
264 | 267 | account.resources :messages |
265 | 268 | end |
266 | 269 | end |
267 | - | |
270 | + | |
268 | 271 | assert_singleton_restful_for :account |
269 | - assert_simply_restful_for :messages, :path_prefix => 'account/' | |
272 | + assert_simply_restful_for :messages, :path_prefix => 'account/', :name_prefix => 'account_' | |
270 | 273 | end |
271 | 274 | end |
272 | 275 | |
... | ... | @@ -279,10 +282,10 @@ class ResourcesTest < Test::Unit::TestCase |
279 | 282 | end |
280 | 283 | |
281 | 284 | assert_singleton_restful_for :account, :path_prefix => '7/', :options => { :site_id => '7' } |
282 | - assert_simply_restful_for :messages, :path_prefix => '7/account/', :options => { :site_id => '7' } | |
285 | + assert_simply_restful_for :messages, :path_prefix => '7/account/', :name_prefix => 'account_', :options => { :site_id => '7' } | |
283 | 286 | end |
284 | 287 | end |
285 | - | |
288 | + | |
286 | 289 | def test_should_nest_singleton_resource_in_resources |
287 | 290 | with_routing do |set| |
288 | 291 | set.draw do |map| |
... | ... | @@ -290,9 +293,9 @@ class ResourcesTest < Test::Unit::TestCase |
290 | 293 | thread.resource :admin |
291 | 294 | end |
292 | 295 | end |
293 | - | |
296 | + | |
294 | 297 | assert_simply_restful_for :threads |
295 | - assert_singleton_restful_for :admin, :path_prefix => 'threads/5/', :options => { :thread_id => '5' } | |
298 | + assert_singleton_restful_for :admin, :path_prefix => 'threads/5/', :name_prefix => 'thread_', :options => { :thread_id => '5' } | |
296 | 299 | end |
297 | 300 | end |
298 | 301 | |
... | ... | @@ -312,6 +315,181 @@ class ResourcesTest < Test::Unit::TestCase |
312 | 315 | end |
313 | 316 | end |
314 | 317 | |
318 | + def test_resource_action_separator | |
319 | + with_routing do |set| | |
320 | + set.draw do |map| | |
321 | + map.resources :messages, :collection => {:search => :get}, :new => {:preview => :any}, :name_prefix => 'thread_', :path_prefix => '/threads/:thread_id' | |
322 | + map.resource :account, :member => {:login => :get}, :new => {:preview => :any}, :name_prefix => 'admin_', :path_prefix => '/admin' | |
323 | + end | |
324 | + | |
325 | + action_separator = ActionController::Base.resource_action_separator | |
326 | + | |
327 | + assert_simply_restful_for :messages, :name_prefix => 'thread_', :path_prefix => 'threads/1/', :options => { :thread_id => '1' } | |
328 | + assert_named_route "/threads/1/messages#{action_separator}search", "search_thread_messages_path", {} | |
329 | + assert_named_route "/threads/1/messages/new", "new_thread_message_path", {} | |
330 | + assert_named_route "/threads/1/messages/new#{action_separator}preview", "preview_new_thread_message_path", {} | |
331 | + assert_singleton_restful_for :account, :name_prefix => 'admin_', :path_prefix => 'admin/' | |
332 | + assert_named_route "/admin/account#{action_separator}login", "login_admin_account_path", {} | |
333 | + assert_named_route "/admin/account/new", "new_admin_account_path", {} | |
334 | + assert_named_route "/admin/account/new#{action_separator}preview", "preview_new_admin_account_path", {} | |
335 | + end | |
336 | + end | |
337 | + | |
338 | + def test_new_style_named_routes_for_resource | |
339 | + with_routing do |set| | |
340 | + set.draw do |map| | |
341 | + map.resources :messages, :collection => {:search => :get}, :new => {:preview => :any}, :name_prefix => 'thread_', :path_prefix => '/threads/:thread_id' | |
342 | + end | |
343 | + assert_simply_restful_for :messages, :name_prefix => 'thread_', :path_prefix => 'threads/1/', :options => { :thread_id => '1' } | |
344 | + assert_named_route "/threads/1/messages/search", "search_thread_messages_path", {} | |
345 | + assert_named_route "/threads/1/messages/new", "new_thread_message_path", {} | |
346 | + assert_named_route "/threads/1/messages/new/preview", "preview_new_thread_message_path", {} | |
347 | + end | |
348 | + end | |
349 | + | |
350 | + def test_new_style_named_routes_for_singleton_resource | |
351 | + with_routing do |set| | |
352 | + set.draw do |map| | |
353 | + map.resource :account, :member => {:login => :get}, :new => {:preview => :any}, :name_prefix => 'admin_', :path_prefix => '/admin' | |
354 | + end | |
355 | + assert_singleton_restful_for :account, :name_prefix => 'admin_', :path_prefix => 'admin/' | |
356 | + assert_named_route "/admin/account/login", "login_admin_account_path", {} | |
357 | + assert_named_route "/admin/account/new", "new_admin_account_path", {} | |
358 | + assert_named_route "/admin/account/new/preview", "preview_new_admin_account_path", {} | |
359 | + end | |
360 | + end | |
361 | + | |
362 | + def test_should_add_deprecated_named_routes_for_resource | |
363 | + with_routing do |set| | |
364 | + set.draw do |map| | |
365 | + map.resources :messages, :collection => {:search => :get}, :new => {:preview => :any}, :name_prefix => 'thread_', :path_prefix => '/threads/:thread_id' | |
366 | + end | |
367 | + assert_simply_restful_for :messages, :name_prefix => 'thread_', :path_prefix => 'threads/1/', :options => { :thread_id => '1' } | |
368 | + assert_deprecated do | |
369 | + assert_named_route "/threads/1/messages/search", "thread_search_messages_path", {} | |
370 | + assert_named_route "/threads/1/messages/new", "thread_new_message_path", {} | |
371 | + assert_named_route "/threads/1/messages/new/preview", "thread_preview_new_message_path", {} | |
372 | + end | |
373 | + end | |
374 | + end | |
375 | + | |
376 | + def test_should_add_deprecated_named_routes_for_singleton_resource | |
377 | + with_routing do |set| | |
378 | + set.draw do |map| | |
379 | + map.resource :account, :member => {:login => :get}, :new => {:preview => :any}, :name_prefix => 'admin_', :path_prefix => '/admin' | |
380 | + end | |
381 | + assert_singleton_restful_for :account, :name_prefix => 'admin_', :path_prefix => 'admin/' | |
382 | + assert_deprecated do | |
383 | + assert_named_route "/admin/account/login", "admin_login_account_path", {} | |
384 | + assert_named_route "/admin/account/new", "admin_new_account_path", {} | |
385 | + assert_named_route "/admin/account/new/preview", "admin_preview_new_account_path", {} | |
386 | + end | |
387 | + end | |
388 | + end | |
389 | + | |
390 | + def test_should_add_deprecated_named_routes_for_nested_resources | |
391 | + with_routing do |set| | |
392 | + set.draw do |map| | |
393 | + map.resources :threads do |map| | |
394 | + map.resources :messages do |map| | |
395 | + map.resources :comments | |
396 | + end | |
397 | + end | |
398 | + end | |
399 | + | |
400 | + assert_simply_restful_for :threads | |
401 | + assert_simply_restful_for :messages, | |
402 | + :path_prefix => 'threads/1/', | |
403 | + :name_prefix => 'thread_', | |
404 | + :options => { :thread_id => '1' } | |
405 | + assert_simply_restful_for :comments, | |
406 | + :path_prefix => 'threads/1/messages/2/', | |
407 | + :name_prefix => 'thread_message_', | |
408 | + :options => { :thread_id => '1', :message_id => '2' } | |
409 | + | |
410 | + assert_deprecated do | |
411 | + assert_named_route "/threads/1/messages", "messages_path", {} | |
412 | + assert_named_route "/threads/1/messages/1", "message_path", {:thread_id => '1', :id => '1'} | |
413 | + assert_named_route "/threads/1/messages/new", "new_message_path", {:thread_id => '1'} | |
414 | + assert_named_route "/threads/1/messages/1/edit", "edit_message_path", {:thread_id => '1', :id => '1'} | |
415 | + end | |
416 | + end | |
417 | + end | |
418 | + | |
419 | + def test_should_add_deprecated_named_routes_for_nested_singleton_resources | |
420 | + with_routing do |set| | |
421 | + set.draw do |map| | |
422 | + map.resource :admin do |admin| | |
423 | + admin.resource :account | |
424 | + end | |
425 | + end | |
426 | + | |
427 | + assert_singleton_restful_for :admin | |
428 | + assert_singleton_restful_for :account, :path_prefix => 'admin/', :name_prefix => 'admin_' | |
429 | + | |
430 | + assert_deprecated do | |
431 | + assert_named_route "/admin/account", "account_path", {} | |
432 | + assert_named_route "/admin/account/new", "new_account_path", {} | |
433 | + assert_named_route "/admin/account/edit", "edit_account_path", {} | |
434 | + end | |
435 | + end | |
436 | + end | |
437 | + | |
438 | + def test_should_add_deprecated_named_routes_for_nested_resources_in_singleton_resource | |
439 | + with_routing do |set| | |
440 | + set.draw do |map| | |
441 | + map.resource :account do |account| | |
442 | + account.resources :messages | |
443 | + end | |
444 | + end | |
445 | + | |
446 | + assert_singleton_restful_for :account | |
447 | + assert_simply_restful_for :messages, :path_prefix => 'account/', :name_prefix => 'account_' | |
448 | + | |
449 | + assert_deprecated do | |
450 | + assert_named_route "/account/messages", "messages_path", {} | |
451 | + assert_named_route "/account/messages/1", "message_path", {:id => '1'} | |
452 | + assert_named_route "/account/messages/new", "new_message_path", {} | |
453 | + assert_named_route "/account/messages/1/edit", "edit_message_path", {:id => '1'} | |
454 | + end | |
455 | + end | |
456 | + end | |
457 | + | |
458 | + def test_should_add_deprecated_named_routes_for_nested_singleton_resource_in_resources | |
459 | + with_routing do |set| | |
460 | + set.draw do |map| | |
461 | + map.resources :threads do |thread| | |
462 | + thread.resource :admin | |
463 | + end | |
464 | + end | |
465 | + | |
466 | + assert_simply_restful_for :threads | |
467 | + assert_singleton_restful_for :admin, :path_prefix => 'threads/5/', :name_prefix => 'thread_', :options => { :thread_id => '5' } | |
468 | + | |
469 | + assert_deprecated do | |
470 | + assert_named_route "/threads/5/admin", "admin_path", {} | |
471 | + assert_named_route "/threads/5/admin/new", "new_admin_path", {} | |
472 | + assert_named_route "/threads/5/admin/edit", "edit_admin_path", {} | |
473 | + end | |
474 | + end | |
475 | + end | |
476 | + | |
477 | + def test_should_add_deprecated_formatted_routes | |
478 | + with_routing do |set| | |
479 | + set.draw do |map| | |
480 | + map.resources :products, :collection => { :specials => :get }, :member => { :thumbnail => :get } | |
481 | + map.resource :account, :member => { :icon => :get } | |
482 | + end | |
483 | + assert_restful_routes_for :products do |options| | |
484 | + assert_recognizes options.merge({ :action => 'specials', :format => 'xml' }), :path => '/products.xml;specials', :method => :get | |
485 | + assert_recognizes options.merge({ :action => 'thumbnail', :format => 'jpg', :id => '1' }), :path => '/products/1.jpg;thumbnail', :method => :get | |
486 | + end | |
487 | + assert_singleton_restful_for :account do |options| | |
488 | + assert_recognizes options.merge({ :action => 'icon', :format => 'jpg' }), :path => '/account.jpg;icon', :method => :get | |
489 | + end | |
490 | + end | |
491 | + end | |
492 | + | |
315 | 493 | protected |
316 | 494 | def with_restful_routing(*args) |
317 | 495 | with_routing do |set| |
... | ... | @@ -319,7 +497,7 @@ class ResourcesTest < Test::Unit::TestCase |
319 | 497 | yield |
320 | 498 | end |
321 | 499 | end |
322 | - | |
500 | + | |
323 | 501 | def with_singleton_resources(*args) |
324 | 502 | with_routing do |set| |
325 | 503 | set.draw { |map| map.resource(*args) } |
... | ... | @@ -344,8 +522,8 @@ class ResourcesTest < Test::Unit::TestCase |
344 | 522 | collection_path = "/#{options[:path_prefix]}#{controller_name}" |
345 | 523 | member_path = "#{collection_path}/1" |
346 | 524 | new_path = "#{collection_path}/new" |
347 | - edit_member_path = "#{member_path};edit" | |
348 | - formatted_edit_member_path = "#{member_path}.xml;edit" | |
525 | + edit_member_path = "#{member_path}/edit" | |
526 | + formatted_edit_member_path = "#{member_path}/edit.xml" | |
349 | 527 | |
350 | 528 | with_options(options[:options]) do |controller| |
351 | 529 | controller.assert_routing collection_path, :action => 'index' |
... | ... | @@ -395,13 +573,13 @@ class ResourcesTest < Test::Unit::TestCase |
395 | 573 | name_prefix = options[:name_prefix] |
396 | 574 | |
397 | 575 | assert_named_route "#{full_prefix}", "#{name_prefix}#{controller_name}_path", options[:options] |
398 | - assert_named_route "#{full_prefix}/new", "#{name_prefix}new_#{singular_name}_path", options[:options] | |
576 | + assert_named_route "#{full_prefix}/new", "new_#{name_prefix}#{singular_name}_path", options[:options] | |
399 | 577 | assert_named_route "#{full_prefix}/1", "#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1') |
400 | - assert_named_route "#{full_prefix}/1;edit", "#{name_prefix}edit_#{singular_name}_path", options[:options].merge(:id => '1') | |
578 | + assert_named_route "#{full_prefix}/1/edit", "edit_#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1') | |
401 | 579 | assert_named_route "#{full_prefix}.xml", "formatted_#{name_prefix}#{controller_name}_path", options[:options].merge( :format => 'xml') |
402 | - assert_named_route "#{full_prefix}/new.xml", "formatted_#{name_prefix}new_#{singular_name}_path", options[:options].merge( :format => 'xml') | |
580 | + assert_named_route "#{full_prefix}/new.xml", "formatted_new_#{name_prefix}#{singular_name}_path", options[:options].merge( :format => 'xml') | |
403 | 581 | assert_named_route "#{full_prefix}/1.xml", "formatted_#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1', :format => 'xml') |
404 | - assert_named_route "#{full_prefix}/1.xml;edit", "formatted_#{name_prefix}edit_#{singular_name}_path", options[:options].merge(:id => '1', :format => 'xml') | |
582 | + assert_named_route "#{full_prefix}/1/edit.xml", "formatted_edit_#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1', :format => 'xml') | |
405 | 583 | yield options[:options] if block_given? |
406 | 584 | end |
407 | 585 | |
... | ... | @@ -410,8 +588,8 @@ class ResourcesTest < Test::Unit::TestCase |
410 | 588 | |
411 | 589 | full_path = "/#{options[:path_prefix]}#{singleton_name}" |
412 | 590 | new_path = "#{full_path}/new" |
413 | - edit_path = "#{full_path};edit" | |
414 | - formatted_edit_path = "#{full_path}.xml;edit" | |
591 | + edit_path = "#{full_path}/edit" | |
592 | + formatted_edit_path = "#{full_path}/edit.xml" | |
415 | 593 | |
416 | 594 | with_options options[:options] do |controller| |
417 | 595 | controller.assert_routing full_path, :action => 'show' |
... | ... | @@ -448,13 +626,14 @@ class ResourcesTest < Test::Unit::TestCase |
448 | 626 | options[:options].delete :action |
449 | 627 | |
450 | 628 | full_path = "/#{options[:path_prefix]}#{singleton_name}" |
451 | - | |
452 | - assert_named_route "#{full_path}", "#{singleton_name}_path", options[:options] | |
453 | - assert_named_route "#{full_path}/new", "new_#{singleton_name}_path", options[:options] | |
454 | - assert_named_route "#{full_path};edit", "edit_#{singleton_name}_path", options[:options] | |
455 | - assert_named_route "#{full_path}.xml", "formatted_#{singleton_name}_path", options[:options].merge(:format => 'xml') | |
456 | - assert_named_route "#{full_path}/new.xml", "formatted_new_#{singleton_name}_path", options[:options].merge(:format => 'xml') | |
457 | - assert_named_route "#{full_path}.xml;edit", "formatted_edit_#{singleton_name}_path", options[:options].merge(:format => 'xml') | |
629 | + full_name = "#{options[:name_prefix]}#{singleton_name}" | |
630 | + | |
631 | + assert_named_route "#{full_path}", "#{full_name}_path", options[:options] | |
632 | + assert_named_route "#{full_path}/new", "new_#{full_name}_path", options[:options] | |
633 | + assert_named_route "#{full_path}/edit", "edit_#{full_name}_path", options[:options] | |
634 | + assert_named_route "#{full_path}.xml", "formatted_#{full_name}_path", options[:options].merge(:format => 'xml') | |
635 | + assert_named_route "#{full_path}/new.xml", "formatted_new_#{full_name}_path", options[:options].merge(:format => 'xml') | |
636 | + assert_named_route "#{full_path}/edit.xml", "formatted_edit_#{full_name}_path", options[:options].merge(:format => 'xml') | |
458 | 637 | end |
459 | 638 | |
460 | 639 | def assert_named_route(expected, route, options) | ... | ... |
vendor/rails/actionpack/test/controller/routing_test.rb
... | ... | @@ -265,7 +265,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase |
265 | 265 | map.content '/content/:query', :controller => 'content', :action => 'show' |
266 | 266 | end |
267 | 267 | exception = assert_raise(ActionController::RoutingError) { rs.generate(:controller => 'content', :action => 'show', :use_route => "content") } |
268 | - expected_message = %[content_url failed to generate from {:action=>"show", :controller=>"content"} - you may have ambiguous routes, or you may need to supply additional parameters for this route. content_url has the following required parameters: ["content", :query] - are they all satisifed?] | |
268 | + expected_message = "content_url failed to generate from #{{:action=>"show", :controller=>"content"}.inspect} - you may have ambiguous routes, or you may need to supply additional parameters for this route. content_url has the following required parameters: [\"content\", :query] - are they all satisifed?" | |
269 | 269 | assert_equal expected_message, exception.message |
270 | 270 | end |
271 | 271 | |
... | ... | @@ -946,7 +946,7 @@ class RouteTest < Test::Unit::TestCase |
946 | 946 | end |
947 | 947 | |
948 | 948 | def test_expand_array_build_query_string |
949 | - assert_equal '?x[]=1&x[]=2', order_query_string(@route.build_query_string(:x => [1, 2])) | |
949 | + assert_equal '?x%5B%5D=1&x%5B%5D=2', order_query_string(@route.build_query_string(:x => [1, 2])) | |
950 | 950 | end |
951 | 951 | |
952 | 952 | def test_escape_spaces_build_query_string_selected_keys | ... | ... |
vendor/rails/actionpack/test/controller/session_fixation_test.rb
0 → 100644
... | ... | @@ -0,0 +1,92 @@ |
1 | +require File.dirname(__FILE__) + '/../abstract_unit' | |
2 | + | |
3 | +class SessionFixationTest < Test::Unit::TestCase | |
4 | + class MockCGI < CGI #:nodoc: | |
5 | + attr_accessor :stdoutput, :env_table | |
6 | + | |
7 | + def initialize(env, data = '') | |
8 | + self.env_table = env | |
9 | + self.stdoutput = StringIO.new | |
10 | + super(StringIO.new(data)) | |
11 | + end | |
12 | + end | |
13 | + | |
14 | + class TestController < ActionController::Base | |
15 | + session :session_key => '_myapp_session_id', :secret => 'secret', :except => :default_session_key | |
16 | + session :cookie_only => false, :only => :allow_session_fixation | |
17 | + | |
18 | + def default_session_key | |
19 | + render :text => "default_session_key" | |
20 | + end | |
21 | + | |
22 | + def custom_session_key | |
23 | + render :text => "custom_session_key: #{params[:id]}" | |
24 | + end | |
25 | + | |
26 | + def allow_session_fixation | |
27 | + render :text => "allow_session_fixation" | |
28 | + end | |
29 | + | |
30 | + def rescue_action(e) raise end | |
31 | + end | |
32 | + | |
33 | + def setup | |
34 | + @controller = TestController.new | |
35 | + end | |
36 | + | |
37 | + def test_should_be_able_to_make_a_successful_request | |
38 | + cgi = mock_cgi_for_request_to(:custom_session_key, :id => 1) | |
39 | + | |
40 | + assert_nothing_raised do | |
41 | + @controller.send(:process, mock_request(cgi), ActionController::CgiResponse.new(cgi)) | |
42 | + end | |
43 | + assert_equal 'custom_session_key: 1', @controller.response.body | |
44 | + assert_not_nil @controller.session | |
45 | + end | |
46 | + | |
47 | + def test_should_catch_session_fixation_attempt | |
48 | + cgi = mock_cgi_for_request_to(:custom_session_key, :_myapp_session_id => 42) | |
49 | + | |
50 | + assert_raises ActionController::CgiRequest::SessionFixationAttempt do | |
51 | + @controller.send(:process, mock_request(cgi), ActionController::CgiResponse.new(cgi)) | |
52 | + end | |
53 | + assert_nil @controller.session | |
54 | + end | |
55 | + | |
56 | + def test_should_not_catch_session_fixation_attempt_when_cookie_only_setting_is_disabled | |
57 | + cgi = mock_cgi_for_request_to(:allow_session_fixation, :_myapp_session_id => 42) | |
58 | + | |
59 | + assert_nothing_raised do | |
60 | + @controller.send(:process, mock_request(cgi), ActionController::CgiResponse.new(cgi)) | |
61 | + end | |
62 | + assert !@controller.response.body.blank? | |
63 | + assert_not_nil @controller.session | |
64 | + end | |
65 | + | |
66 | + def test_should_catch_session_fixation_attempt_with_default_session_key | |
67 | + ActionController::Base.session_store = :p_store # using the default session_key is not possible with cookie store | |
68 | + cgi = mock_cgi_for_request_to(:default_session_key, :_session_id => 42) | |
69 | + | |
70 | + assert_raises ActionController::CgiRequest::SessionFixationAttempt do | |
71 | + @controller.send(:process, mock_request(cgi) , ActionController::CgiResponse.new(cgi)) | |
72 | + end | |
73 | + assert @controller.response.body.blank? | |
74 | + assert_nil @controller.session | |
75 | + end | |
76 | + | |
77 | +private | |
78 | + | |
79 | + def mock_cgi_for_request_to(action, params = {}) | |
80 | + MockCGI.new({ | |
81 | + "REQUEST_METHOD" => "GET", | |
82 | + "QUERY_STRING" => "action=#{action}&#{params.to_query}", | |
83 | + "REQUEST_URI" => "/", | |
84 | + "SERVER_PORT" => "80", | |
85 | + "HTTP_HOST" => "testdomain.com" }, '') | |
86 | + end | |
87 | + | |
88 | + def mock_request(cgi) | |
89 | + ActionController::CgiRequest.new(cgi, {}) | |
90 | + end | |
91 | + | |
92 | +end | ... | ... |
vendor/rails/actionpack/test/controller/test_test.rb
... | ... | @@ -482,6 +482,22 @@ HTML |
482 | 482 | end |
483 | 483 | end |
484 | 484 | |
485 | + def test_request_uri_updates | |
486 | + get :test_params | |
487 | + uri = @request.request_uri | |
488 | + assert_equal @request.env['REQUEST_URI'], uri | |
489 | + | |
490 | + get :test_uri | |
491 | + assert_not_equal uri, @request.request_uri | |
492 | + uri = @request.request_uri | |
493 | + assert_equal @request.env['REQUEST_URI'], uri | |
494 | + | |
495 | + get :test_uri, :testing => true | |
496 | + assert_not_equal uri, @request.request_uri | |
497 | + uri = @request.request_uri | |
498 | + assert_equal @request.env['REQUEST_URI'], uri | |
499 | + end | |
500 | + | |
485 | 501 | protected |
486 | 502 | def with_foo_routing |
487 | 503 | with_routing do |set| | ... | ... |
vendor/rails/actionpack/test/controller/url_rewriter_test.rb
... | ... | @@ -17,15 +17,12 @@ class UrlRewriterTests < Test::Unit::TestCase |
17 | 17 | assert_match %r(/hi/hi/2$), u |
18 | 18 | end |
19 | 19 | |
20 | - | |
21 | - private | |
22 | - def split_query_string(str) | |
23 | - [str[0].chr] + str[1..-1].split(/&/).sort | |
24 | - end | |
25 | - | |
26 | - def assert_query_equal(q1, q2) | |
27 | - assert_equal(split_query_string(q1), split_query_string(q2)) | |
28 | - end | |
20 | + def test_anchor | |
21 | + assert_equal( | |
22 | + 'http://test.host/c/a/i#anchor', | |
23 | + @rewriter.rewrite(:controller => 'c', :action => 'a', :id => 'i', :anchor => 'anchor') | |
24 | + ) | |
25 | + end | |
29 | 26 | end |
30 | 27 | |
31 | 28 | class UrlWriterTests < Test::Unit::TestCase |
... | ... | @@ -75,6 +72,12 @@ class UrlWriterTests < Test::Unit::TestCase |
75 | 72 | W.new.url_for(:controller => 'c', :action => 'a', :id => 'i', :protocol => 'https') |
76 | 73 | ) |
77 | 74 | end |
75 | + | |
76 | + def test_anchor | |
77 | + assert_equal('/c/a#anchor', | |
78 | + W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :anchor => 'anchor') | |
79 | + ) | |
80 | + end | |
78 | 81 | |
79 | 82 | def test_named_route |
80 | 83 | ActionController::Routing::Routes.draw do |map| |
... | ... | @@ -111,5 +114,58 @@ class UrlWriterTests < Test::Unit::TestCase |
111 | 114 | ensure |
112 | 115 | ActionController::Routing::Routes.load! |
113 | 116 | end |
114 | - | |
117 | + | |
118 | + def test_one_parameter | |
119 | + assert_equal('/c/a?param=val', | |
120 | + W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :param => 'val') | |
121 | + ) | |
122 | + end | |
123 | + | |
124 | + def test_two_parameters | |
125 | + url = W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :p1 => 'X1', :p2 => 'Y2') | |
126 | + params = extract_params(url) | |
127 | + assert_equal params[0], { :p1 => 'X1' }.to_query | |
128 | + assert_equal params[1], { :p2 => 'Y2' }.to_query | |
129 | + end | |
130 | + | |
131 | + def test_hash_parameter | |
132 | + url = W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :query => {:name => 'Bob', :category => 'prof'}) | |
133 | + params = extract_params(url) | |
134 | + assert_equal params[0], { 'query[category]' => 'prof' }.to_query | |
135 | + assert_equal params[1], { 'query[name]' => 'Bob' }.to_query | |
136 | + end | |
137 | + | |
138 | + def test_array_parameter | |
139 | + url = W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :query => ['Bob', 'prof']) | |
140 | + params = extract_params(url) | |
141 | + assert_equal params[0], { 'query[]' => 'Bob' }.to_query | |
142 | + assert_equal params[1], { 'query[]' => 'prof' }.to_query | |
143 | + end | |
144 | + | |
145 | + def test_hash_recursive_parameters | |
146 | + url = W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :query => {:person => {:name => 'Bob', :position => 'prof'}, :hobby => 'piercing'}) | |
147 | + params = extract_params(url) | |
148 | + assert_equal params[0], { 'query[hobby]' => 'piercing' }.to_query | |
149 | + assert_equal params[1], { 'query[person][name]' => 'Bob' }.to_query | |
150 | + assert_equal params[2], { 'query[person][position]' => 'prof' }.to_query | |
151 | + end | |
152 | + | |
153 | + def test_hash_recursive_and_array_parameters | |
154 | + url = W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :id => 101, :query => {:person => {:name => 'Bob', :position => ['prof', 'art director']}, :hobby => 'piercing'}) | |
155 | + assert_match %r(^/c/a/101), url | |
156 | + params = extract_params(url) | |
157 | + assert_equal params[0], { 'query[hobby]' => 'piercing' }.to_query | |
158 | + assert_equal params[1], { 'query[person][name]' => 'Bob' }.to_query | |
159 | + assert_equal params[2], { 'query[person][position][]' => 'art director' }.to_query | |
160 | + assert_equal params[3], { 'query[person][position][]' => 'prof' }.to_query | |
161 | + end | |
162 | + | |
163 | + def test_path_generation_for_symbol_parameter_keys | |
164 | + assert_generates("/image", :controller=> :image) | |
165 | + end | |
166 | + | |
167 | + private | |
168 | + def extract_params(url) | |
169 | + url.split('?', 2).last.split('&') | |
170 | + end | |
115 | 171 | end | ... | ... |
vendor/rails/actionpack/test/controller/verification_test.rb
... | ... | @@ -34,9 +34,16 @@ class VerificationTest < Test::Unit::TestCase |
34 | 34 | |
35 | 35 | verify :only => :must_be_post, :method => :post, :render => { :status => 405, :text => "Must be post" }, :add_headers => { "Allow" => "POST" } |
36 | 36 | |
37 | + verify :only => :guarded_one_for_named_route_test, :params => "one", | |
38 | + :redirect_to => :foo_url | |
39 | + | |
37 | 40 | def guarded_one |
38 | 41 | render :text => "#{params[:one]}" |
39 | 42 | end |
43 | + | |
44 | + def guarded_one_for_named_route_test | |
45 | + render :text => "#{params[:one]}" | |
46 | + end | |
40 | 47 | |
41 | 48 | def guarded_with_flash |
42 | 49 | render :text => "#{params[:one]}" |
... | ... | @@ -94,6 +101,14 @@ class VerificationTest < Test::Unit::TestCase |
94 | 101 | @controller = TestController.new |
95 | 102 | @request = ActionController::TestRequest.new |
96 | 103 | @response = ActionController::TestResponse.new |
104 | + ActionController::Routing::Routes.add_named_route :foo, '/foo', :controller => 'test', :action => 'foo' | |
105 | + end | |
106 | + | |
107 | + def test_no_deprecation_warning_for_named_route | |
108 | + assert_not_deprecated do | |
109 | + get :guarded_one_for_named_route_test, :two => "not one" | |
110 | + assert_redirected_to '/foo' | |
111 | + end | |
97 | 112 | end |
98 | 113 | |
99 | 114 | def test_guarded_one_with_prereqs | ... | ... |
vendor/rails/actionpack/test/fixtures/test/hello_world.rxml
vendor/rails/actionpack/test/template/asset_tag_helper_test.rb
... | ... | @@ -165,7 +165,12 @@ class AssetTagHelperTest < Test::Unit::TestCase |
165 | 165 | |
166 | 166 | def test_preset_empty_asset_id |
167 | 167 | Object.send(:const_set, :RAILS_ROOT, File.dirname(__FILE__) + "/../fixtures/") |
168 | + # on windows, setting ENV["XXX"] to "" makes ENV["XXX"] return nil | |
169 | + if RUBY_PLATFORM =~ /win32/ | |
170 | + ENV["RAILS_ASSET_ID"] = " " | |
171 | + else | |
168 | 172 | ENV["RAILS_ASSET_ID"] = "" |
173 | + end | |
169 | 174 | assert_equal %(<img alt="Rails" src="/images/rails.png" />), image_tag("rails.png") |
170 | 175 | end |
171 | 176 | ... | ... |
vendor/rails/actionpack/test/template/compiled_templates_test.rb
... | ... | @@ -71,7 +71,12 @@ class CompiledTemplateTests < Test::Unit::TestCase |
71 | 71 | end |
72 | 72 | |
73 | 73 | def test_compile_time |
74 | - `echo '#{@a}' > #{@a}; echo '#{@b}' > #{@b}; ln -s #{@a} #{@s}` | |
74 | + File.open(@a, "w"){|f| f.puts @a} | |
75 | + File.open(@b, "w"){|f| f.puts @b} | |
76 | + | |
77 | + # windows doesn't support symlinks (even under cygwin) | |
78 | + windows = (RUBY_PLATFORM =~ /win32/) | |
79 | + `ln -s #{@a} #{@s}` unless windows | |
75 | 80 | |
76 | 81 | v = ActionView::Base.new |
77 | 82 | v.base_path = '.' |
... | ... | @@ -79,47 +84,54 @@ class CompiledTemplateTests < Test::Unit::TestCase |
79 | 84 | |
80 | 85 | sleep 1 |
81 | 86 | t = Time.now |
87 | + sleep 1 | |
88 | + | |
82 | 89 | v.compile_and_render_template(:rhtml, '', @a) |
83 | 90 | v.compile_and_render_template(:rhtml, '', @b) |
84 | - v.compile_and_render_template(:rhtml, '', @s) | |
91 | + v.compile_and_render_template(:rhtml, '', @s) unless windows | |
92 | + | |
85 | 93 | a_n = v.method_names[@a] |
86 | 94 | b_n = v.method_names[@b] |
87 | - s_n = v.method_names[@s] | |
95 | + s_n = v.method_names[@s] unless windows | |
96 | + ct_a = v.compile_time[a_n] | |
97 | + ct_b = v.compile_time[b_n] | |
98 | + ct_s = v.compile_time[s_n] unless windows | |
88 | 99 | # all of the files have changed since last compile |
89 | 100 | assert v.compile_time[a_n] > t |
90 | 101 | assert v.compile_time[b_n] > t |
91 | - assert v.compile_time[s_n] > t | |
102 | + assert v.compile_time[s_n] > t unless windows | |
92 | 103 | |
93 | 104 | sleep 1 |
94 | - t = Time.now | |
95 | 105 | v.compile_and_render_template(:rhtml, '', @a) |
96 | 106 | v.compile_and_render_template(:rhtml, '', @b) |
97 | - v.compile_and_render_template(:rhtml, '', @s) | |
107 | + v.compile_and_render_template(:rhtml, '', @s) unless windows | |
98 | 108 | # none of the files have changed since last compile |
99 | - assert v.compile_time[a_n] < t | |
100 | - assert v.compile_time[b_n] < t | |
101 | - assert v.compile_time[s_n] < t | |
109 | + # so they should not have been recmpiled | |
110 | + assert_equal ct_a, v.compile_time[a_n] | |
111 | + assert_equal ct_b, v.compile_time[b_n] | |
112 | + assert_equal ct_s, v.compile_time[s_n] unless windows | |
102 | 113 | |
103 | - `rm #{@s}; ln -s #{@b} #{@s}` | |
114 | + `rm #{@s}; ln -s #{@b} #{@s}` unless windows | |
104 | 115 | v.compile_and_render_template(:rhtml, '', @a) |
105 | 116 | v.compile_and_render_template(:rhtml, '', @b) |
106 | - v.compile_and_render_template(:rhtml, '', @s) | |
117 | + v.compile_and_render_template(:rhtml, '', @s) unless windows | |
107 | 118 | # the symlink has changed since last compile |
108 | - assert v.compile_time[a_n] < t | |
109 | - assert v.compile_time[b_n] < t | |
110 | - assert v.compile_time[s_n] > t | |
119 | + assert_equal ct_a, v.compile_time[a_n] | |
120 | + assert_equal ct_b, v.compile_time[b_n] | |
121 | + assert v.compile_time[s_n] > t unless windows | |
111 | 122 | |
112 | 123 | sleep 1 |
113 | - `touch #{@b}` | |
124 | + FileUtils.touch @b | |
114 | 125 | t = Time.now |
126 | + sleep 1 | |
115 | 127 | v.compile_and_render_template(:rhtml, '', @a) |
116 | 128 | v.compile_and_render_template(:rhtml, '', @b) |
117 | - v.compile_and_render_template(:rhtml, '', @s) | |
129 | + v.compile_and_render_template(:rhtml, '', @s) unless windows | |
118 | 130 | # the file at the end of the symlink has changed since last compile |
119 | 131 | # both the symlink and the file at the end of it should be recompiled |
120 | 132 | assert v.compile_time[a_n] < t |
121 | 133 | assert v.compile_time[b_n] > t |
122 | - assert v.compile_time[s_n] > t | |
134 | + assert v.compile_time[s_n] > t unless windows | |
123 | 135 | end |
124 | 136 | end |
125 | 137 | ... | ... |
vendor/rails/actionpack/test/template/javascript_helper_test.rb
... | ... | @@ -36,14 +36,14 @@ class JavaScriptHelperTest < Test::Unit::TestCase |
36 | 36 | html = link_to_function( "Greet me!" ) do |page| |
37 | 37 | page.replace_html 'header', "<h1>Greetings</h1>" |
38 | 38 | end |
39 | - assert_dom_equal %(<a href="#" onclick="Element.update("header", "<h1>Greetings</h1>");; return false;">Greet me!</a>), html | |
39 | + assert_dom_equal %q(<a href="#" onclick="Element.update("header", "\074h1\076Greetings\074/h1\076");; return false;">Greet me!</a>), html | |
40 | 40 | end |
41 | 41 | |
42 | 42 | def test_link_to_function_with_rjs_block_and_options |
43 | 43 | html = link_to_function( "Greet me!", :class => "updater" ) do |page| |
44 | 44 | page.replace_html 'header', "<h1>Greetings</h1>" |
45 | 45 | end |
46 | - assert_dom_equal %(<a href="#" class="updater" onclick="Element.update("header", "<h1>Greetings</h1>");; return false;">Greet me!</a>), html | |
46 | + assert_dom_equal %q(<a href="#" class="updater" onclick="Element.update("header", "\074h1\076Greetings\074/h1\076");; return false;">Greet me!</a>), html | |
47 | 47 | end |
48 | 48 | |
49 | 49 | def test_button_to_function |
... | ... | @@ -55,13 +55,13 @@ class JavaScriptHelperTest < Test::Unit::TestCase |
55 | 55 | html = button_to_function( "Greet me!" ) do |page| |
56 | 56 | page.replace_html 'header', "<h1>Greetings</h1>" |
57 | 57 | end |
58 | - assert_dom_equal %(<input type="button" onclick="Element.update("header", "<h1>Greetings</h1>");;" value="Greet me!" />), html | |
58 | + assert_dom_equal %q(<input type="button" onclick="Element.update("header", "\074h1\076Greetings\074/h1\076");;" value="Greet me!" />), html | |
59 | 59 | end |
60 | 60 | |
61 | 61 | def test_button_to_function_with_rjs_block_and_options |
62 | 62 | html = button_to_function( "Greet me!", :class => "greeter" ) do |page| |
63 | 63 | page.replace_html 'header', "<h1>Greetings</h1>" |
64 | 64 | end |
65 | - assert_dom_equal %(<input type="button" class="greeter" onclick="Element.update("header", "<h1>Greetings</h1>");;" value="Greet me!" />), html | |
65 | + assert_dom_equal %q(<input type="button" class="greeter" onclick="Element.update("header", "\074h1\076Greetings\074/h1\076");;" value="Greet me!" />), html | |
66 | 66 | end |
67 | 67 | end | ... | ... |
vendor/rails/actionpack/test/template/number_helper_test.rb
... | ... | @@ -22,7 +22,7 @@ class NumberHelperTest < Test::Unit::TestCase |
22 | 22 | def test_number_to_currency |
23 | 23 | assert_equal("$1,234,567,890.50", number_to_currency(1234567890.50)) |
24 | 24 | assert_equal("$1,234,567,890.51", number_to_currency(1234567890.506)) |
25 | - assert_equal("$1,234,567,890", number_to_currency(1234567890.50, {:precision => 0})) | |
25 | + assert_equal("$1,234,567,891", number_to_currency(1234567890.51, {:precision => 0})) | |
26 | 26 | assert_equal("$1,234,567,890.5", number_to_currency(1234567890.50, {:precision => 1})) |
27 | 27 | assert_equal("£1234567890,50", number_to_currency(1234567890.50, {:unit => "£", :separator => ",", :delimiter => ""})) |
28 | 28 | assert_equal("$1,234,567,890.50", number_to_currency("1234567890.50")) | ... | ... |
vendor/rails/actionpack/test/template/prototype_helper_test.rb
... | ... | @@ -125,7 +125,7 @@ class PrototypeHelperTest < Test::Unit::TestCase |
125 | 125 | end |
126 | 126 | |
127 | 127 | def test_observe_field |
128 | - assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Element.Observer('glass', 300, function(element, value) {new Ajax.Request('http://www.example.com/reorder_if_empty', {asynchronous:true, evalScripts:true})})\n//]]>\n</script>), | |
128 | + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Element.Observer('glass', 300, function(element, value) {new Ajax.Request('http://www.example.com/reorder_if_empty', {asynchronous:true, evalScripts:true, parameters:value})})\n//]]>\n</script>), | |
129 | 129 | observe_field("glass", :frequency => 5.minutes, :url => { :action => "reorder_if_empty" }) |
130 | 130 | end |
131 | 131 | |
... | ... | @@ -135,7 +135,7 @@ class PrototypeHelperTest < Test::Unit::TestCase |
135 | 135 | end |
136 | 136 | |
137 | 137 | def test_observe_form |
138 | - assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Observer('cart', 2, function(element, value) {new Ajax.Request('http://www.example.com/cart_changed', {asynchronous:true, evalScripts:true})})\n//]]>\n</script>), | |
138 | + assert_dom_equal %(<script type=\"text/javascript\">\n//<![CDATA[\nnew Form.Observer('cart', 2, function(element, value) {new Ajax.Request('http://www.example.com/cart_changed', {asynchronous:true, evalScripts:true, parameters:value})})\n//]]>\n</script>), | |
139 | 139 | observe_form("cart", :frequency => 2, :url => { :action => "cart_changed" }) |
140 | 140 | end |
141 | 141 | |
... | ... | @@ -170,23 +170,23 @@ class JavaScriptGeneratorTest < Test::Unit::TestCase |
170 | 170 | end |
171 | 171 | |
172 | 172 | def test_insert_html_with_string |
173 | - assert_equal 'new Insertion.Top("element", "<p>This is a test</p>");', | |
173 | + assert_equal 'new Insertion.Top("element", "\074p\076This is a test\074/p\076");', | |
174 | 174 | @generator.insert_html(:top, 'element', '<p>This is a test</p>') |
175 | - assert_equal 'new Insertion.Bottom("element", "<p>This is a test</p>");', | |
175 | + assert_equal 'new Insertion.Bottom("element", "\074p\076This is a test\074/p\076");', | |
176 | 176 | @generator.insert_html(:bottom, 'element', '<p>This is a test</p>') |
177 | - assert_equal 'new Insertion.Before("element", "<p>This is a test</p>");', | |
177 | + assert_equal 'new Insertion.Before("element", "\074p\076This is a test\074/p\076");', | |
178 | 178 | @generator.insert_html(:before, 'element', '<p>This is a test</p>') |
179 | - assert_equal 'new Insertion.After("element", "<p>This is a test</p>");', | |
179 | + assert_equal 'new Insertion.After("element", "\074p\076This is a test\074/p\076");', | |
180 | 180 | @generator.insert_html(:after, 'element', '<p>This is a test</p>') |
181 | 181 | end |
182 | 182 | |
183 | 183 | def test_replace_html_with_string |
184 | - assert_equal 'Element.update("element", "<p>This is a test</p>");', | |
184 | + assert_equal 'Element.update("element", "\074p\076This is a test\074/p\076");', | |
185 | 185 | @generator.replace_html('element', '<p>This is a test</p>') |
186 | 186 | end |
187 | 187 | |
188 | 188 | def test_replace_element_with_string |
189 | - assert_equal 'Element.replace("element", "<div id=\"element\"><p>This is a test</p></div>");', | |
189 | + assert_equal 'Element.replace("element", "\074div id=\"element\"\076\074p\076This is a test\074/p\076\074/div\076");', | |
190 | 190 | @generator.replace('element', '<div id="element"><p>This is a test</p></div>') |
191 | 191 | end |
192 | 192 | |
... | ... | @@ -241,12 +241,12 @@ class JavaScriptGeneratorTest < Test::Unit::TestCase |
241 | 241 | @generator.remove('foo', 'bar') |
242 | 242 | @generator.replace_html('baz', '<p>This is a test</p>') |
243 | 243 | |
244 | - assert_equal <<-EOS.chomp, @generator.to_s | |
245 | -new Insertion.Top("element", "<p>This is a test</p>"); | |
246 | -new Insertion.Bottom("element", "<p>This is a test</p>"); | |
244 | + expected = %q(new Insertion.Top("element", "\074p\076This is a test\074/p\076"); | |
245 | +new Insertion.Bottom("element", "\074p\076This is a test\074/p\076"); | |
247 | 246 | ["foo", "bar"].each(Element.remove); |
248 | -Element.update("baz", "<p>This is a test</p>"); | |
249 | - EOS | |
247 | +Element.update("baz", "\074p\076This is a test\074/p\076");) | |
248 | + | |
249 | + assert_equal expected, @generator.to_s | |
250 | 250 | end |
251 | 251 | |
252 | 252 | def test_element_access | ... | ... |
vendor/rails/actionwebservice/CHANGELOG
1 | +*1.2.6* (November 24th, 2007) | |
2 | + | |
3 | +* Depend on Action Pack 1.13.6 | |
4 | + | |
5 | +* Depend on Active Record 1.15.6 | |
6 | + | |
7 | + | |
8 | +*1.2.5* (October 12th, 2007) | |
9 | + | |
10 | +* Depend on Action Pack 1.13.5 | |
11 | + | |
12 | +* Depend on Active Record 1.15.5 | |
13 | + | |
14 | + | |
15 | +*1.2.4* (October 4th, 2007) | |
16 | + | |
17 | +* Depend on Action Pack 1.13.4 | |
18 | + | |
19 | +* Depend on Active Record 1.15.4 | |
20 | + | |
21 | + | |
1 | 22 | *1.2.3* (March 12th, 2007) |
2 | 23 | |
3 | 24 | * Depend on Action Pack 1.13.3 | ... | ... |
vendor/rails/actionwebservice/Rakefile
... | ... | @@ -71,8 +71,8 @@ spec = Gem::Specification.new do |s| |
71 | 71 | s.rubyforge_project = "aws" |
72 | 72 | s.homepage = "http://www.rubyonrails.org" |
73 | 73 | |
74 | - s.add_dependency('actionpack', '= 1.13.3' + PKG_BUILD) | |
75 | - s.add_dependency('activerecord', '= 1.15.3' + PKG_BUILD) | |
74 | + s.add_dependency('actionpack', '= 1.13.6' + PKG_BUILD) | |
75 | + s.add_dependency('activerecord', '= 1.15.6' + PKG_BUILD) | |
76 | 76 | |
77 | 77 | s.has_rdoc = true |
78 | 78 | s.requirements << 'none' | ... | ... |
vendor/rails/actionwebservice/lib/action_web_service/version.rb
vendor/rails/activerecord/CHANGELOG
1 | +*1.15.6* (November 24th, 2007) | |
2 | + | |
3 | +* Allow association redefinition in subclasses. #9346 [wildchild] | |
4 | + | |
5 | +* Fix has_many :through delete with custom foreign keys. #6466 [naffis] | |
6 | + | |
7 | +* Fix regression where the association would not construct new finder SQL on save causing bogus queries for "WHERE owner_id = NULL" even after owner was saved. #8713 [Bryan Helmkamp] | |
8 | + | |
9 | + | |
10 | +*1.15.5* (October 12th, 2007) | |
11 | + | |
12 | +* Depend on Action Pack 1.4.4 | |
13 | + | |
14 | + | |
15 | +*1.15.4* (October 4th, 2007) | |
16 | + | |
17 | +* Fix #count on a has_many :through association so that it recognizes the :uniq option. Closes #8801 [lifofifo] | |
18 | + | |
19 | +* Don't clobber includes passed to has_many.count [danger] | |
20 | + | |
21 | +* Make sure has_many uses :include when counting [danger] | |
22 | + | |
23 | +* Save associated records only if the association is already loaded. #8713 [blaine] | |
24 | + | |
25 | +* Changing the :default Date format doesn't break date quoting. #6312 [bshand, Elias] | |
26 | + | |
27 | +* Allow nil serialized attributes with a set class constraint. #7293 [sandofsky] | |
28 | + | |
29 | +* belongs_to assignment creates a new proxy rather than modifying its target in-place. #8412 [mmangino@elevatedrails.com] | |
30 | + | |
31 | +* Fix column type detection while loading fixtures. Closes #7987 [roderickvd] | |
32 | + | |
33 | +* Document deep eager includes. #6267 [Josh Susser, Dan Manges] | |
34 | + | |
35 | +* Oracle: extract column length for CHAR also. #7866 [ymendel] | |
36 | + | |
37 | +* Small additions and fixes for ActiveRecord documentation. Closes #7342 [jeremymcanally] | |
38 | + | |
39 | +* SQLite: binary escaping works with $KCODE='u'. #7862 [tsuka] | |
40 | + | |
41 | +* Improved cloning performance by relying less on exception raising #8159 [Blaine] | |
42 | + | |
43 | + | |
1 | 44 | *1.15.3* (March 12th, 2007) |
2 | 45 | |
3 | 46 | * Allow a polymorphic :source for has_many :through associations. Closes #7143 [protocool] | ... | ... |
vendor/rails/activerecord/Rakefile
... | ... | @@ -151,7 +151,7 @@ spec = Gem::Specification.new do |s| |
151 | 151 | s.files = s.files + Dir.glob( "#{dir}/**/*" ).delete_if { |item| item.include?( "\.svn" ) } |
152 | 152 | end |
153 | 153 | |
154 | - s.add_dependency('activesupport', '= 1.4.2' + PKG_BUILD) | |
154 | + s.add_dependency('activesupport', '= 1.4.4' + PKG_BUILD) | |
155 | 155 | |
156 | 156 | s.files.delete "test/fixtures/fixture_database.sqlite" |
157 | 157 | s.files.delete "test/fixtures/fixture_database_2.sqlite" | ... | ... |
vendor/rails/activerecord/lib/active_record/acts/list.rb
... | ... | @@ -63,7 +63,7 @@ module ActiveRecord |
63 | 63 | |
64 | 64 | #{scope_condition_method} |
65 | 65 | |
66 | - after_destroy :remove_from_list | |
66 | + before_destroy :remove_from_list | |
67 | 67 | before_create :add_to_list_bottom |
68 | 68 | EOV |
69 | 69 | end |
... | ... | @@ -74,6 +74,7 @@ module ActiveRecord |
74 | 74 | # lower in the list of all chapters. Likewise, <tt>chapter.first?</tt> would return true if that chapter is |
75 | 75 | # the first in the list of all chapters. |
76 | 76 | module InstanceMethods |
77 | + # Insert the item at the given position (defaults to the top position of 1). | |
77 | 78 | def insert_at(position = 1) |
78 | 79 | insert_at_position(position) |
79 | 80 | end |
... | ... | @@ -118,8 +119,12 @@ module ActiveRecord |
118 | 119 | end |
119 | 120 | end |
120 | 121 | |
122 | + # Removes the item from the list. | |
121 | 123 | def remove_from_list |
122 | - decrement_positions_on_lower_items if in_list? | |
124 | + if in_list? | |
125 | + decrement_positions_on_lower_items | |
126 | + update_attribute position_column, nil | |
127 | + end | |
123 | 128 | end |
124 | 129 | |
125 | 130 | # Increase the position of this item without adjusting the rest of the list. |
... | ... | @@ -162,6 +167,7 @@ module ActiveRecord |
162 | 167 | ) |
163 | 168 | end |
164 | 169 | |
170 | + # Test if this record is in a list | |
165 | 171 | def in_list? |
166 | 172 | !send(position_column).nil? |
167 | 173 | end |
... | ... | @@ -178,21 +184,26 @@ module ActiveRecord |
178 | 184 | # Overwrite this method to define the scope of the list changes |
179 | 185 | def scope_condition() "1" end |
180 | 186 | |
187 | + # Returns the bottom position number in the list. | |
188 | + # bottom_position_in_list # => 2 | |
181 | 189 | def bottom_position_in_list(except = nil) |
182 | 190 | item = bottom_item(except) |
183 | 191 | item ? item.send(position_column) : 0 |
184 | 192 | end |
185 | 193 | |
194 | + # Returns the bottom item | |
186 | 195 | def bottom_item(except = nil) |
187 | 196 | conditions = scope_condition |
188 | 197 | conditions = "#{conditions} AND #{self.class.primary_key} != #{except.id}" if except |
189 | 198 | acts_as_list_class.find(:first, :conditions => conditions, :order => "#{position_column} DESC") |
190 | 199 | end |
191 | 200 | |
201 | + # Forces item to assume the bottom position in the list. | |
192 | 202 | def assume_bottom_position |
193 | 203 | update_attribute(position_column, bottom_position_in_list(self).to_i + 1) |
194 | 204 | end |
195 | 205 | |
206 | + # Forces item to assume the top position in the list. | |
196 | 207 | def assume_top_position |
197 | 208 | update_attribute(position_column, 1) |
198 | 209 | end |
... | ... | @@ -227,6 +238,7 @@ module ActiveRecord |
227 | 238 | ) |
228 | 239 | end |
229 | 240 | |
241 | + # Increments position (<tt>position_column</tt>) of all items in the list. | |
230 | 242 | def increment_positions_on_all_items |
231 | 243 | acts_as_list_class.update_all( |
232 | 244 | "#{position_column} = (#{position_column} + 1)", "#{scope_condition}" | ... | ... |
vendor/rails/activerecord/lib/active_record/acts/tree.rb
... | ... | @@ -70,16 +70,23 @@ module ActiveRecord |
70 | 70 | nodes |
71 | 71 | end |
72 | 72 | |
73 | + # Returns the root node of the tree. | |
73 | 74 | def root |
74 | 75 | node = self |
75 | 76 | node = node.parent while node.parent |
76 | 77 | node |
77 | 78 | end |
78 | 79 | |
80 | + # Returns all siblings of the current node. | |
81 | + # | |
82 | + # subchild1.siblings # => [subchild2] | |
79 | 83 | def siblings |
80 | 84 | self_and_siblings - [self] |
81 | 85 | end |
82 | 86 | |
87 | + # Returns all siblings and a reference to the current node. | |
88 | + # | |
89 | + # subchild1.self_and_siblings # => [subchild1, subchild2] | |
83 | 90 | def self_and_siblings |
84 | 91 | parent ? parent.children : self.class.roots |
85 | 92 | end | ... | ... |
vendor/rails/activerecord/lib/active_record/associations.rb
... | ... | @@ -50,6 +50,12 @@ module ActiveRecord |
50 | 50 | end |
51 | 51 | end |
52 | 52 | |
53 | + class HasManyThroughCantDissociateNewRecords < ActiveRecordError #:nodoc: | |
54 | + def initialize(owner, reflection) | |
55 | + super("Cannot dissociate new records through '#{owner.class.name}##{reflection.name}' on '#{reflection.source_reflection.class_name rescue nil}##{reflection.source_reflection.name rescue nil}'. Both records must have an id in order to delete the has_many :through record associating them.") | |
56 | + end | |
57 | + end | |
58 | + | |
53 | 59 | class EagerLoadPolymorphicError < ActiveRecordError #:nodoc: |
54 | 60 | def initialize(reflection) |
55 | 61 | super("Can not eagerly load the polymorphic association #{reflection.name.inspect}") |
... | ... | @@ -352,7 +358,15 @@ module ActiveRecord |
352 | 358 | # for post in Post.find(:all, :include => [ :author, :comments ]) |
353 | 359 | # |
354 | 360 | # That'll add another join along the lines of: LEFT OUTER JOIN comments ON comments.post_id = posts.id. And we'll be down to 1 query. |
355 | - # But that shouldn't fool you to think that you can pull out huge amounts of data with no performance penalty just because you've reduced | |
361 | + # | |
362 | + # To include a deep hierarchy of associations, using a hash: | |
363 | + # | |
364 | + # for post in Post.find(:all, :include => [ :author, { :comments => { :author => :gravatar } } ]) | |
365 | + # | |
366 | + # That'll grab not only all the comments but all their authors and gravatar pictures. You can mix and match | |
367 | + # symbols, arrays and hashes in any combination to describe the associations you want to load. | |
368 | + # | |
369 | + # All of this power shouldn't fool you into thinking that you can pull out huge amounts of data with no performance penalty just because you've reduced | |
356 | 370 | # the number of queries. The database still needs to send all the data to Active Record and it still needs to be processed. So it's no |
357 | 371 | # catch-all for performance problems, but it's a great way to cut down on the number of queries in a situation as the one described above. |
358 | 372 | # |
... | ... | @@ -734,6 +748,7 @@ module ActiveRecord |
734 | 748 | deprecated_association_comparison_method(reflection.name, reflection.class_name) |
735 | 749 | end |
736 | 750 | |
751 | + # Create the callbacks to update counter cache | |
737 | 752 | if options[:counter_cache] |
738 | 753 | cache_column = options[:counter_cache] == true ? |
739 | 754 | "#{self.to_s.underscore.pluralize}_count" : |
... | ... | @@ -853,7 +868,7 @@ module ActiveRecord |
853 | 868 | # Don't use a before_destroy callback since users' before_destroy |
854 | 869 | # callbacks will be executed after the association is wiped out. |
855 | 870 | old_method = "destroy_without_habtm_shim_for_#{reflection.name}" |
856 | - class_eval <<-end_eval | |
871 | + class_eval <<-end_eval unless method_defined?(old_method) | |
857 | 872 | alias_method :#{old_method}, :destroy_without_callbacks |
858 | 873 | def destroy_without_callbacks |
859 | 874 | #{reflection.name}.clear |
... | ... | @@ -871,6 +886,12 @@ module ActiveRecord |
871 | 886 | end |
872 | 887 | |
873 | 888 | private |
889 | + # Generate a join table name from two provided tables names. | |
890 | + # The order of names in join name is determined by lexical precedence. | |
891 | + # join_table_name("members", "clubs") | |
892 | + # => "clubs_members" | |
893 | + # join_table_name("members", "special_clubs") | |
894 | + # => "members_special_clubs" | |
874 | 895 | def join_table_name(first_table_name, second_table_name) |
875 | 896 | if first_table_name < second_table_name |
876 | 897 | join_table = "#{first_table_name}_#{second_table_name}" |
... | ... | @@ -880,7 +901,7 @@ module ActiveRecord |
880 | 901 | |
881 | 902 | table_name_prefix + join_table + table_name_suffix |
882 | 903 | end |
883 | - | |
904 | + | |
884 | 905 | def association_accessor_methods(reflection, association_proxy_class) |
885 | 906 | define_method(reflection.name) do |*params| |
886 | 907 | force_reload = params.first unless params.empty? |
... | ... | @@ -901,7 +922,7 @@ module ActiveRecord |
901 | 922 | |
902 | 923 | define_method("#{reflection.name}=") do |new_value| |
903 | 924 | association = instance_variable_get("@#{reflection.name}") |
904 | - if association.nil? | |
925 | + if association.nil? || association.target != new_value | |
905 | 926 | association = association_proxy_class.new(self, reflection) |
906 | 927 | end |
907 | 928 | |
... | ... | @@ -911,10 +932,7 @@ module ActiveRecord |
911 | 932 | instance_variable_set("@#{reflection.name}", association) |
912 | 933 | else |
913 | 934 | instance_variable_set("@#{reflection.name}", nil) |
914 | - return nil | |
915 | 935 | end |
916 | - | |
917 | - association | |
918 | 936 | end |
919 | 937 | |
920 | 938 | define_method("set_#{reflection.name}_target") do |target| |
... | ... | @@ -981,18 +999,21 @@ module ActiveRecord |
981 | 999 | |
982 | 1000 | after_callback = <<-end_eval |
983 | 1001 | association = instance_variable_get("@#{association_name}") |
984 | - | |
985 | - if association.respond_to?(:loaded?) | |
986 | - if @new_record_before_save | |
987 | - records_to_save = association | |
988 | - else | |
989 | - records_to_save = association.select { |record| record.new_record? } | |
990 | - end | |
991 | - records_to_save.each { |record| association.send(:insert_record, record) } | |
992 | - association.send(:construct_sql) # reconstruct the SQL queries now that we know the owner's id | |
1002 | + | |
1003 | + records_to_save = if @new_record_before_save | |
1004 | + association | |
1005 | + elsif association.respond_to?(:loaded?) && association.loaded? | |
1006 | + association.select { |record| record.new_record? } | |
1007 | + else | |
1008 | + [] | |
993 | 1009 | end |
1010 | + | |
1011 | + records_to_save.each { |record| association.send(:insert_record, record) } unless records_to_save.blank? | |
1012 | + | |
1013 | + # reconstruct the SQL queries now that we know the owner's id | |
1014 | + association.send(:construct_sql) if association.respond_to?(:construct_sql) | |
994 | 1015 | end_eval |
995 | - | |
1016 | + | |
996 | 1017 | # Doesn't use after_save as that would save associations added in after_create/after_update twice |
997 | 1018 | after_create(after_callback) |
998 | 1019 | after_update(after_callback) |
... | ... | @@ -1271,7 +1292,9 @@ module ActiveRecord |
1271 | 1292 | defined_callbacks = options[callback_name.to_sym] |
1272 | 1293 | if options.has_key?(callback_name.to_sym) |
1273 | 1294 | class_inheritable_reader full_callback_name.to_sym |
1274 | - write_inheritable_array(full_callback_name.to_sym, [defined_callbacks].flatten) | |
1295 | + write_inheritable_attribute(full_callback_name.to_sym, [defined_callbacks].flatten) | |
1296 | + else | |
1297 | + write_inheritable_attribute(full_callback_name.to_sym, []) | |
1275 | 1298 | end |
1276 | 1299 | end |
1277 | 1300 | end | ... | ... |
vendor/rails/activerecord/lib/active_record/associations/association_collection.rb
... | ... | @@ -91,7 +91,11 @@ module ActiveRecord |
91 | 91 | attributes.collect { |attr| create(attr) } |
92 | 92 | else |
93 | 93 | record = build(attributes) |
94 | - record.save unless @owner.new_record? | |
94 | + if @owner.new_record? | |
95 | + ActiveSupport::Deprecation.warn("Calling .create on a has_many association without saving its owner will not work in rails 2.0, you probably want .build instead") | |
96 | + else | |
97 | + record.save | |
98 | + end | |
95 | 99 | record |
96 | 100 | end |
97 | 101 | end | ... | ... |
vendor/rails/activerecord/lib/active_record/associations/has_many_association.rb
... | ... | @@ -50,7 +50,7 @@ module ActiveRecord |
50 | 50 | options[:conditions] = options[:conditions].nil? ? |
51 | 51 | @finder_sql : |
52 | 52 | @finder_sql + " AND (#{sanitize_sql(options[:conditions])})" |
53 | - options[:include] = @reflection.options[:include] | |
53 | + options[:include] ||= @reflection.options[:include] | |
54 | 54 | |
55 | 55 | @reflection.klass.count(column_name, options) |
56 | 56 | end |
... | ... | @@ -138,7 +138,7 @@ module ActiveRecord |
138 | 138 | elsif @reflection.options[:counter_sql] |
139 | 139 | @reflection.klass.count_by_sql(@counter_sql) |
140 | 140 | else |
141 | - @reflection.klass.count(:conditions => @counter_sql) | |
141 | + @reflection.klass.count(:conditions => @counter_sql, :include => @reflection.options[:include]) | |
142 | 142 | end |
143 | 143 | |
144 | 144 | @target = [] and loaded if count == 0 | ... | ... |
vendor/rails/activerecord/lib/active_record/associations/has_many_through_association.rb
... | ... | @@ -71,20 +71,26 @@ module ActiveRecord |
71 | 71 | |
72 | 72 | # Remove +records+ from this association. Does not destroy +records+. |
73 | 73 | def delete(*records) |
74 | - records = flatten_deeper(records) | |
75 | - records.each { |associate| raise_on_type_mismatch(associate) } | |
76 | - records.reject! { |associate| @target.delete(associate) if associate.new_record? } | |
77 | 74 | return if records.empty? |
78 | - | |
79 | - @delete_join_finder ||= "find_all_by_#{@reflection.source_reflection.association_foreign_key}" | |
75 | + records.each { |associate| raise_on_type_mismatch(associate) } | |
76 | + | |
80 | 77 | through = @reflection.through_reflection |
81 | - through.klass.transaction do | |
82 | - records.each do |associate| | |
83 | - joins = @owner.send(through.name).send(@delete_join_finder, associate.id) | |
84 | - @owner.send(through.name).delete(joins) | |
78 | + raise ActiveRecord::HasManyThroughCantDissociateNewRecords.new(@owner, through) if @owner.new_record? | |
79 | + | |
80 | + load_target | |
81 | + | |
82 | + klass = through.klass | |
83 | + klass.transaction do | |
84 | + flatten_deeper(records).each do |associate| | |
85 | + raise_on_type_mismatch(associate) | |
86 | + raise ActiveRecord::HasManyThroughCantDissociateNewRecords.new(@owner, through) unless associate.respond_to?(:new_record?) && !associate.new_record? | |
87 | + | |
88 | + @owner.send(@reflection.through_reflection.name).proxy_target.delete(klass.delete_all(construct_join_attributes(associate))) | |
85 | 89 | @target.delete(associate) |
86 | 90 | end |
87 | 91 | end |
92 | + | |
93 | + self | |
88 | 94 | end |
89 | 95 | |
90 | 96 | def build(attrs = nil) |
... | ... | @@ -101,6 +107,16 @@ module ActiveRecord |
101 | 107 | def sum(*args, &block) |
102 | 108 | calculate(:sum, *args, &block) |
103 | 109 | end |
110 | + | |
111 | + def count(*args) | |
112 | + column_name, options = @reflection.klass.send(:construct_count_options_from_legacy_args, *args) | |
113 | + if @reflection.options[:uniq] | |
114 | + # This is needed becase 'SELECT count(DISTINCT *)..' is not valid sql statement. | |
115 | + column_name = "#{@reflection.klass.table_name}.#{@reflection.klass.primary_key}" if column_name == :all | |
116 | + options.merge!(:distinct => true) | |
117 | + end | |
118 | + @reflection.klass.send(:with_scope, construct_scope) { @reflection.klass.count(column_name, options) } | |
119 | + end | |
104 | 120 | |
105 | 121 | protected |
106 | 122 | def method_missing(method, *args, &block) | ... | ... |
vendor/rails/activerecord/lib/active_record/base.rb
... | ... | @@ -575,7 +575,7 @@ module ActiveRecord #:nodoc: |
575 | 575 | |
576 | 576 | # Specifies that the attribute by the name of +attr_name+ should be serialized before saving to the database and unserialized |
577 | 577 | # after loading from the database. The serialization is done through YAML. If +class_name+ is specified, the serialized |
578 | - # object must be of that class on retrieval or +SerializationTypeMismatch+ will be raised. | |
578 | + # object must be of that class on retrieval, or nil. Otherwise, +SerializationTypeMismatch+ will be raised. | |
579 | 579 | def serialize(attr_name, class_name = Object) |
580 | 580 | serialized_attributes[attr_name.to_s] = class_name |
581 | 581 | end |
... | ... | @@ -1188,6 +1188,9 @@ module ActiveRecord #:nodoc: |
1188 | 1188 | # |
1189 | 1189 | # It's even possible to use all the additional parameters to find. For example, the full interface for find_all_by_amount |
1190 | 1190 | # is actually find_all_by_amount(amount, options). |
1191 | + # | |
1192 | + # This also enables you to initialize a record if it is not found, such as find_or_initialize_by_amount(amount) | |
1193 | + # or find_or_create_by_user_and_password(user, password). | |
1191 | 1194 | def method_missing(method_id, *arguments) |
1192 | 1195 | if match = /^find_(all_by|by)_([_a-zA-Z]\w*)$/.match(method_id.to_s) |
1193 | 1196 | finder, deprecated_finder = determine_finder(match), determine_deprecated_finder(match) |
... | ... | @@ -1957,7 +1960,7 @@ module ActiveRecord #:nodoc: |
1957 | 1960 | def unserialize_attribute(attr_name) |
1958 | 1961 | unserialized_object = object_from_yaml(@attributes[attr_name]) |
1959 | 1962 | |
1960 | - if unserialized_object.is_a?(self.class.serialized_attributes[attr_name]) | |
1963 | + if unserialized_object.is_a?(self.class.serialized_attributes[attr_name]) || unserialized_object.nil? | |
1961 | 1964 | @attributes[attr_name] = unserialized_object |
1962 | 1965 | else |
1963 | 1966 | raise SerializationTypeMismatch, |
... | ... | @@ -2156,7 +2159,13 @@ module ActiveRecord #:nodoc: |
2156 | 2159 | |
2157 | 2160 | def clone_attribute_value(reader_method, attribute_name) |
2158 | 2161 | value = send(reader_method, attribute_name) |
2159 | - value.clone | |
2162 | + | |
2163 | + case value | |
2164 | + when nil, Fixnum, true, false | |
2165 | + value | |
2166 | + else | |
2167 | + value.clone | |
2168 | + end | |
2160 | 2169 | rescue TypeError, NoMethodError |
2161 | 2170 | value |
2162 | 2171 | end | ... | ... |
vendor/rails/activerecord/lib/active_record/calculations.rb
... | ... | @@ -242,8 +242,8 @@ module ActiveRecord |
242 | 242 | options.assert_valid_keys(CALCULATIONS_OPTIONS) |
243 | 243 | end |
244 | 244 | |
245 | - # converts a given key to the value that the database adapter returns as | |
246 | - # | |
245 | + # Converts a given key to the value that the database adapter returns as | |
246 | + # as a usable column name. | |
247 | 247 | # users.id #=> users_id |
248 | 248 | # sum(id) #=> sum_id |
249 | 249 | # count(distinct users.id) #=> count_distinct_users_id | ... | ... |
vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
... | ... | @@ -24,7 +24,7 @@ module ActiveRecord |
24 | 24 | when Float, Fixnum, Bignum then value.to_s |
25 | 25 | # BigDecimals need to be output in a non-normalized form and quoted. |
26 | 26 | when BigDecimal then value.to_s('F') |
27 | - when Date then "'#{value.to_s}'" | |
27 | + when Date then "'#{value.to_s(:db)}'" | |
28 | 28 | when Time, DateTime then "'#{quoted_date(value)}'" |
29 | 29 | else "'#{quote_string(value.to_yaml)}'" |
30 | 30 | end | ... | ... |
vendor/rails/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
... | ... | @@ -119,7 +119,7 @@ module ActiveRecord |
119 | 119 | # |
120 | 120 | # * <tt>:host</tt> -- Defaults to localhost |
121 | 121 | # * <tt>:port</tt> -- Defaults to 3306 |
122 | - # * <tt>:socket</tt> -- Defaults to /tmp/mysql.sock | |
122 | + # * <tt>:socket</tt> -- Defaults to /var/run/mysqld/mysqld.sock | |
123 | 123 | # * <tt>:username</tt> -- Defaults to root |
124 | 124 | # * <tt>:password</tt> -- Defaults to nothing |
125 | 125 | # * <tt>:database</tt> -- The name of the database. No default, must be provided. | ... | ... |
vendor/rails/activerecord/lib/active_record/connection_adapters/oracle_adapter.rb
... | ... | @@ -320,6 +320,7 @@ begin |
320 | 320 | decode(data_type, 'NUMBER', data_precision, |
321 | 321 | 'FLOAT', data_precision, |
322 | 322 | 'VARCHAR2', data_length, |
323 | + 'CHAR', data_length, | |
323 | 324 | null) as limit, |
324 | 325 | decode(data_type, 'NUMBER', data_scale, null) as scale |
325 | 326 | from all_tab_columns | ... | ... |
vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
... | ... | @@ -68,7 +68,7 @@ module ActiveRecord |
68 | 68 | class SQLiteColumn < Column #:nodoc: |
69 | 69 | class << self |
70 | 70 | def string_to_binary(value) |
71 | - value.gsub(/\0|\%/) do |b| | |
71 | + value.gsub(/\0|\%/n) do |b| | |
72 | 72 | case b |
73 | 73 | when "\0" then "%00" |
74 | 74 | when "%" then "%25" |
... | ... | @@ -77,7 +77,7 @@ module ActiveRecord |
77 | 77 | end |
78 | 78 | |
79 | 79 | def binary_to_string(value) |
80 | - value.gsub(/%00|%25/) do |b| | |
80 | + value.gsub(/%00|%25/n) do |b| | |
81 | 81 | case b |
82 | 82 | when "%00" then "\0" |
83 | 83 | when "%25" then "%" | ... | ... |
vendor/rails/activerecord/lib/active_record/deprecated_finders.rb
1 | 1 | module ActiveRecord |
2 | 2 | class Base |
3 | 3 | class << self |
4 | - # This method is deprecated in favor of find with the :conditions option. | |
4 | + # DEPRECATION NOTICE: This method is deprecated in favor of find with the :conditions option. | |
5 | 5 | # |
6 | 6 | # Works like find, but the record matching +id+ must also meet the +conditions+. |
7 | 7 | # +RecordNotFound+ is raised if no record can be found matching the +id+ or meeting the condition. |
... | ... | @@ -12,7 +12,7 @@ module ActiveRecord |
12 | 12 | end |
13 | 13 | deprecate :find_on_conditions => "use find(ids, :conditions => conditions)" |
14 | 14 | |
15 | - # This method is deprecated in favor of find(:first, options). | |
15 | + # DEPRECATION NOTICE: This method is deprecated in favor of find(:first, options). | |
16 | 16 | # |
17 | 17 | # Returns the object for the first record responding to the conditions in +conditions+, |
18 | 18 | # such as "group = 'master'". If more than one record is returned from the query, it's the first that'll |
... | ... | @@ -24,7 +24,7 @@ module ActiveRecord |
24 | 24 | end |
25 | 25 | deprecate :find_first => "use find(:first, ...)" |
26 | 26 | |
27 | - # This method is deprecated in favor of find(:all, options). | |
27 | + # DEPRECATION NOTICE: This method is deprecated in favor of find(:all, options). | |
28 | 28 | # |
29 | 29 | # Returns an array of all the objects that could be instantiated from the associated |
30 | 30 | # table in the database. The +conditions+ can be used to narrow the selection of objects (WHERE-part), | ... | ... |
vendor/rails/activerecord/lib/active_record/fixtures.rb
... | ... | @@ -412,7 +412,7 @@ class Fixture #:nodoc: |
412 | 412 | klass = @class_name.constantize rescue nil |
413 | 413 | |
414 | 414 | list = @fixture.inject([]) do |fixtures, (key, value)| |
415 | - col = klass.columns_hash[key] if klass.kind_of?(ActiveRecord::Base) | |
415 | + col = klass.columns_hash[key] if klass.respond_to?(:ancestors) && klass.ancestors.include?(ActiveRecord::Base) | |
416 | 416 | fixtures << ActiveRecord::Base.connection.quote(value, col).gsub('[^\]\\n', "\n").gsub('[^\]\\r', "\r") |
417 | 417 | end |
418 | 418 | list * ', ' | ... | ... |
vendor/rails/activerecord/lib/active_record/timestamp.rb
... | ... | @@ -5,15 +5,6 @@ module ActiveRecord |
5 | 5 | # Timestamping can be turned off by setting |
6 | 6 | # <tt>ActiveRecord::Base.record_timestamps = false</tt> |
7 | 7 | # |
8 | - # Keep in mind that, via inheritance, you can turn off timestamps on a per | |
9 | - # model basis by setting <tt>record_timestamps</tt> to false in the desired | |
10 | - # models. | |
11 | - # | |
12 | - # class Feed < ActiveRecord::Base | |
13 | - # self.record_timestamps = false | |
14 | - # # ... | |
15 | - # end | |
16 | - # | |
17 | 8 | # Timestamps are in the local timezone by default but can use UTC by setting |
18 | 9 | # <tt>ActiveRecord::Base.default_timezone = :utc</tt> |
19 | 10 | module Timestamp | ... | ... |
vendor/rails/activerecord/lib/active_record/vendor/mysql.rb
vendor/rails/activerecord/lib/active_record/version.rb
vendor/rails/activerecord/test/aggregations_test.rb
... | ... | @@ -93,3 +93,21 @@ class AggregationsTest < Test::Unit::TestCase |
93 | 93 | assert_raises(NoMethodError) { customers(:david).balance = nil } |
94 | 94 | end |
95 | 95 | end |
96 | + | |
97 | +class OverridingAggregationsTest < Test::Unit::TestCase | |
98 | + class Name; end | |
99 | + class DifferentName; end | |
100 | + | |
101 | + class Person < ActiveRecord::Base | |
102 | + composed_of :composed_of, :mapping => %w(person_first_name first_name) | |
103 | + end | |
104 | + | |
105 | + class DifferentPerson < Person | |
106 | + composed_of :composed_of, :class_name => 'DifferentName', :mapping => %w(different_person_first_name first_name) | |
107 | + end | |
108 | + | |
109 | + def test_composed_of_aggregation_redefinition_reflections_should_differ_and_not_inherited | |
110 | + assert_not_equal Person.reflect_on_aggregation(:composed_of), | |
111 | + DifferentPerson.reflect_on_aggregation(:composed_of) | |
112 | + end | |
113 | +end | ... | ... |
vendor/rails/activerecord/test/associations/eager_test.rb
... | ... | @@ -168,6 +168,12 @@ class EagerAssociationTest < Test::Unit::TestCase |
168 | 168 | posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => "posts.title = 'magic forest'") |
169 | 169 | assert_equal 0, posts.size |
170 | 170 | end |
171 | + | |
172 | + def test_eager_count_performed_on_a_has_many_association_with_multi_table_conditional | |
173 | + author = authors(:david) | |
174 | + author_posts_without_comments = author.posts.select { |post| post.comments.blank? } | |
175 | + assert_equal author_posts_without_comments.size, author.posts.count(:all, :include => :comments, :conditions => 'comments.id is null') | |
176 | + end | |
171 | 177 | |
172 | 178 | def test_eager_with_has_and_belongs_to_many_and_limit |
173 | 179 | posts = Post.find(:all, :include => :categories, :order => "posts.id", :limit => 3) |
... | ... | @@ -271,6 +277,13 @@ class EagerAssociationTest < Test::Unit::TestCase |
271 | 277 | assert_not_nil f.account |
272 | 278 | assert_equal companies(:first_firm, :reload).account, f.account |
273 | 279 | end |
280 | + | |
281 | + def test_eager_with_multi_table_conditional_properly_counts_the_records_when_using_size | |
282 | + author = authors(:david) | |
283 | + posts_with_no_comments = author.posts.select { |post| post.comments.blank? } | |
284 | + assert_equal posts_with_no_comments.size, author.posts_with_no_comments.size | |
285 | + assert_equal posts_with_no_comments, author.posts_with_no_comments | |
286 | + end | |
274 | 287 | |
275 | 288 | def test_eager_with_invalid_association_reference |
276 | 289 | assert_raises(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") { | ... | ... |
vendor/rails/activerecord/test/associations/join_model_test.rb
... | ... | @@ -8,10 +8,12 @@ require 'fixtures/category' |
8 | 8 | require 'fixtures/categorization' |
9 | 9 | require 'fixtures/vertex' |
10 | 10 | require 'fixtures/edge' |
11 | +require 'fixtures/book' | |
12 | +require 'fixtures/citation' | |
11 | 13 | |
12 | 14 | class AssociationsJoinModelTest < Test::Unit::TestCase |
13 | 15 | self.use_transactional_fixtures = false |
14 | - fixtures :posts, :authors, :categories, :categorizations, :comments, :tags, :taggings, :author_favorites, :vertices | |
16 | + fixtures :posts, :authors, :categories, :categorizations, :comments, :tags, :taggings, :author_favorites, :vertices, :books | |
15 | 17 | |
16 | 18 | def test_has_many |
17 | 19 | assert authors(:david).categories.include?(categories(:general)) |
... | ... | @@ -29,7 +31,16 @@ class AssociationsJoinModelTest < Test::Unit::TestCase |
29 | 31 | assert_equal 2, authors(:mary).categorized_posts.size |
30 | 32 | assert_equal 1, authors(:mary).unique_categorized_posts.size |
31 | 33 | end |
32 | - | |
34 | + | |
35 | + def test_has_many_uniq_through_count | |
36 | + author = authors(:mary) | |
37 | + assert !authors(:mary).unique_categorized_posts.loaded? | |
38 | + assert_queries(1) { assert_equal 1, author.unique_categorized_posts.count } | |
39 | + assert_queries(1) { assert_equal 1, author.unique_categorized_posts.count(:title, {}) } | |
40 | + assert_queries(1) { assert_equal 0, author.unique_categorized_posts.count(:title, { :conditions => "title is NULL" }) } | |
41 | + assert !authors(:mary).unique_categorized_posts.loaded? | |
42 | + end | |
43 | + | |
33 | 44 | def test_polymorphic_has_many |
34 | 45 | assert posts(:welcome).taggings.include?(taggings(:welcome_general)) |
35 | 46 | end |
... | ... | @@ -441,7 +452,21 @@ class AssociationsJoinModelTest < Test::Unit::TestCase |
441 | 452 | tags = posts(:thinking).tags |
442 | 453 | assert_equal tags, posts(:thinking).tags.push(tags(:general)) |
443 | 454 | end |
444 | - | |
455 | + | |
456 | + def test_delete_associate_when_deleting_from_has_many_through_with_non_standard_id | |
457 | + count = books(:awdr).references.count | |
458 | + references_before = books(:awdr).references | |
459 | + book = Book.create!(:name => 'Getting Real') | |
460 | + book_awdr = books(:awdr) | |
461 | + book_awdr.references << book | |
462 | + assert_equal(count + 1, book_awdr.references(true).size) | |
463 | + | |
464 | + assert_nothing_raised { book_awdr.references.delete(book) } | |
465 | + assert_equal(count, book_awdr.references.size) | |
466 | + assert_equal(count, book_awdr.references(true).size) | |
467 | + assert_equal(references_before.sort, book_awdr.references.sort) | |
468 | + end | |
469 | + | |
445 | 470 | def test_delete_associate_when_deleting_from_has_many_through |
446 | 471 | count = posts(:thinking).tags.count |
447 | 472 | tags_before = posts(:thinking).tags | ... | ... |
vendor/rails/activerecord/test/associations_test.rb
... | ... | @@ -10,6 +10,8 @@ require 'fixtures/order' |
10 | 10 | require 'fixtures/category' |
11 | 11 | require 'fixtures/post' |
12 | 12 | require 'fixtures/author' |
13 | +require 'fixtures/person' | |
14 | +require 'fixtures/reader' | |
13 | 15 | |
14 | 16 | |
15 | 17 | class AssociationsTest < Test::Unit::TestCase |
... | ... | @@ -21,6 +23,14 @@ class AssociationsTest < Test::Unit::TestCase |
21 | 23 | Class.new(ActiveRecord::Base).has_many(:wheels, :name => 'wheels') |
22 | 24 | end |
23 | 25 | end |
26 | + | |
27 | + def test_should_construct_new_finder_sql_after_create | |
28 | + person = Person.new | |
29 | + assert_equal [], person.readers.find(:all) | |
30 | + person.save! | |
31 | + reader = Reader.create! :person => person, :post => Post.new(:title => "foo", :body => "bar") | |
32 | + assert_equal [reader], person.readers.find(:all) | |
33 | + end | |
24 | 34 | |
25 | 35 | def test_force_reload |
26 | 36 | firm = Firm.new("name" => "A New Firm, Inc") |
... | ... | @@ -67,8 +77,8 @@ class AssociationsTest < Test::Unit::TestCase |
67 | 77 | end |
68 | 78 | |
69 | 79 | class AssociationProxyTest < Test::Unit::TestCase |
70 | - fixtures :authors, :posts | |
71 | - | |
80 | + fixtures :authors, :posts, :developers, :projects, :developers_projects | |
81 | + | |
72 | 82 | def test_proxy_accessors |
73 | 83 | welcome = posts(:welcome) |
74 | 84 | assert_equal welcome, welcome.author.proxy_owner |
... | ... | @@ -87,6 +97,19 @@ class AssociationProxyTest < Test::Unit::TestCase |
87 | 97 | david.posts_with_extension.first # force load target |
88 | 98 | assert_equal david.posts_with_extension, david.posts_with_extension.testing_proxy_target |
89 | 99 | end |
100 | + | |
101 | + def test_save_on_parent_does_not_load_target | |
102 | + david = developers(:david) | |
103 | + | |
104 | + assert !david.projects.loaded? | |
105 | + david.update_attribute(:created_at, Time.now) | |
106 | + assert !david.projects.loaded? | |
107 | + end | |
108 | + | |
109 | + def test_save_on_parent_saves_children | |
110 | + developer = Developer.create :name => "Bryan", :salary => 50_000 | |
111 | + assert_equal 1, developer.reload.audit_logs.size | |
112 | + end | |
90 | 113 | end |
91 | 114 | |
92 | 115 | class HasOneAssociationsTest < Test::Unit::TestCase |
... | ... | @@ -583,6 +606,13 @@ class HasManyAssociationsTest < Test::Unit::TestCase |
583 | 606 | assert_equal 3, first_firm.plain_clients.size |
584 | 607 | end |
585 | 608 | |
609 | + def test_regular_create_on_has_many_when_parent_is_new_raises | |
610 | + assert_deprecated(/.build instead/) do | |
611 | + firm = Firm.new | |
612 | + firm.plain_clients.create :name=>"Whoever" | |
613 | + end | |
614 | + end | |
615 | + | |
586 | 616 | def test_adding_a_mismatch_class |
587 | 617 | assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << nil } |
588 | 618 | assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << 1 } |
... | ... | @@ -1007,7 +1037,20 @@ class BelongsToAssociationsTest < Test::Unit::TestCase |
1007 | 1037 | citibank.firm = apple |
1008 | 1038 | assert_equal apple.id, citibank.firm_id |
1009 | 1039 | end |
1010 | - | |
1040 | + | |
1041 | + def test_no_unexpected_aliasing | |
1042 | + first_firm = companies(:first_firm) | |
1043 | + another_firm = companies(:another_firm) | |
1044 | + | |
1045 | + citibank = Account.create("credit_limit" => 10) | |
1046 | + citibank.firm = first_firm | |
1047 | + original_proxy = citibank.firm | |
1048 | + citibank.firm = another_firm | |
1049 | + | |
1050 | + assert_equal first_firm.object_id, original_proxy.object_id | |
1051 | + assert_equal another_firm.object_id, citibank.firm.object_id | |
1052 | + end | |
1053 | + | |
1011 | 1054 | def test_creating_the_belonging_object |
1012 | 1055 | citibank = Account.create("credit_limit" => 10) |
1013 | 1056 | apple = citibank.create_firm("name" => "Apple") |
... | ... | @@ -1807,3 +1850,68 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase |
1807 | 1850 | assert_equal %w(1 2), projects.scan(/\d/).sort |
1808 | 1851 | end |
1809 | 1852 | end |
1853 | + | |
1854 | + | |
1855 | +class OverridingAssociationsTest < Test::Unit::TestCase | |
1856 | + class Person < ActiveRecord::Base; end | |
1857 | + class DifferentPerson < ActiveRecord::Base; end | |
1858 | + | |
1859 | + class PeopleList < ActiveRecord::Base | |
1860 | + has_and_belongs_to_many :has_and_belongs_to_many, :before_add => :enlist | |
1861 | + has_many :has_many, :before_add => :enlist | |
1862 | + belongs_to :belongs_to | |
1863 | + has_one :has_one | |
1864 | + end | |
1865 | + | |
1866 | + class DifferentPeopleList < PeopleList | |
1867 | + # Different association with the same name, callbacks should be omitted here. | |
1868 | + has_and_belongs_to_many :has_and_belongs_to_many, :class_name => 'DifferentPerson' | |
1869 | + has_many :has_many, :class_name => 'DifferentPerson' | |
1870 | + belongs_to :belongs_to, :class_name => 'DifferentPerson', :foreign_key => 'belongs_to_id' | |
1871 | + has_one :has_one, :class_name => 'DifferentPerson' | |
1872 | + end | |
1873 | + | |
1874 | + def test_habtm_association_redefinition_callbacks_should_differ_and_not_inherited | |
1875 | + # redeclared association on AR descendant should not inherit callbacks from superclass | |
1876 | + callbacks = PeopleList.read_inheritable_attribute(:before_add_for_has_and_belongs_to_many) | |
1877 | + assert_equal([:enlist], callbacks) | |
1878 | + callbacks = DifferentPeopleList.read_inheritable_attribute(:before_add_for_has_and_belongs_to_many) | |
1879 | + assert_equal([], callbacks) | |
1880 | + end | |
1881 | + | |
1882 | + def test_has_many_association_redefinition_callbacks_should_differ_and_not_inherited | |
1883 | + # redeclared association on AR descendant should not inherit callbacks from superclass | |
1884 | + callbacks = PeopleList.read_inheritable_attribute(:before_add_for_has_many) | |
1885 | + assert_equal([:enlist], callbacks) | |
1886 | + callbacks = DifferentPeopleList.read_inheritable_attribute(:before_add_for_has_many) | |
1887 | + assert_equal([], callbacks) | |
1888 | + end | |
1889 | + | |
1890 | + def test_habtm_association_redefinition_reflections_should_differ_and_not_inherited | |
1891 | + assert_not_equal( | |
1892 | + PeopleList.reflect_on_association(:has_and_belongs_to_many), | |
1893 | + DifferentPeopleList.reflect_on_association(:has_and_belongs_to_many) | |
1894 | + ) | |
1895 | + end | |
1896 | + | |
1897 | + def test_has_many_association_redefinition_reflections_should_differ_and_not_inherited | |
1898 | + assert_not_equal( | |
1899 | + PeopleList.reflect_on_association(:has_many), | |
1900 | + DifferentPeopleList.reflect_on_association(:has_many) | |
1901 | + ) | |
1902 | + end | |
1903 | + | |
1904 | + def test_belongs_to_association_redefinition_reflections_should_differ_and_not_inherited | |
1905 | + assert_not_equal( | |
1906 | + PeopleList.reflect_on_association(:belongs_to), | |
1907 | + DifferentPeopleList.reflect_on_association(:belongs_to) | |
1908 | + ) | |
1909 | + end | |
1910 | + | |
1911 | + def test_has_one_association_redefinition_reflections_should_differ_and_not_inherited | |
1912 | + assert_not_equal( | |
1913 | + PeopleList.reflect_on_association(:has_one), | |
1914 | + DifferentPeopleList.reflect_on_association(:has_one) | |
1915 | + ) | |
1916 | + end | |
1917 | +end | ... | ... |
vendor/rails/activerecord/test/base_test.rb
... | ... | @@ -1086,16 +1086,29 @@ class BasicsTest < Test::Unit::TestCase |
1086 | 1086 | assert_equal(myobj, topic.content) |
1087 | 1087 | end |
1088 | 1088 | |
1089 | - def test_serialized_attribute_with_class_constraint | |
1089 | + def test_nil_serialized_attribute_with_class_constraint | |
1090 | 1090 | myobj = MyObject.new('value1', 'value2') |
1091 | - topic = Topic.create("content" => myobj) | |
1092 | - Topic.serialize(:content, Hash) | |
1091 | + topic = Topic.new | |
1092 | + assert_nil topic.content | |
1093 | + end | |
1093 | 1094 | |
1095 | + def test_should_raise_exception_on_serialized_attribute_with_type_mismatch | |
1096 | + myobj = MyObject.new('value1', 'value2') | |
1097 | + topic = Topic.new(:content => myobj) | |
1098 | + assert topic.save | |
1099 | + Topic.serialize(:content, Hash) | |
1094 | 1100 | assert_raise(ActiveRecord::SerializationTypeMismatch) { Topic.find(topic.id).content } |
1101 | + ensure | |
1102 | + Topic.serialize(:content) | |
1103 | + end | |
1095 | 1104 | |
1105 | + def test_serialized_attribute_with_class_constraint | |
1096 | 1106 | settings = { "color" => "blue" } |
1097 | - Topic.find(topic.id).update_attribute("content", settings) | |
1107 | + Topic.serialize(:content, Hash) | |
1108 | + topic = Topic.new(:content => settings) | |
1109 | + assert topic.save | |
1098 | 1110 | assert_equal(settings, Topic.find(topic.id).content) |
1111 | + ensure | |
1099 | 1112 | Topic.serialize(:content) |
1100 | 1113 | end |
1101 | 1114 | ... | ... |
vendor/rails/activerecord/test/fixtures/author.rb
... | ... | @@ -25,6 +25,7 @@ class Author < ActiveRecord::Base |
25 | 25 | |
26 | 26 | has_many :hello_posts, :class_name => "Post", :conditions => "posts.body = 'hello'" |
27 | 27 | has_many :hello_post_comments, :through => :hello_posts, :source => :comments |
28 | + has_many :posts_with_no_comments, :class_name => 'Post', :conditions => 'comments.id is null', :include => :comments | |
28 | 29 | |
29 | 30 | has_many :other_posts, :class_name => "Post" |
30 | 31 | has_many :posts_with_callbacks, :class_name => "Post", :before_add => :log_before_adding, | ... | ... |
... | ... | @@ -0,0 +1,437 @@ |
1 | +flowers: | |
2 | + id: 1 | |
3 | + data: !binary | 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 | |
436 | + KKpVChRRRQAUUUUAFFFFABRRRQAUUUUAf//Z | |
437 | + | ... | ... |
... | ... | @@ -0,0 +1,6 @@ |
1 | +class Citation < ActiveRecord::Base | |
2 | + belongs_to :reference_of, :class_name => "Book", :foreign_key => :book2_id | |
3 | + | |
4 | + belongs_to :book1, :class_name => "Book", :foreign_key => :book1_id | |
5 | + belongs_to :book2, :class_name => "Book", :foreign_key => :book2_id | |
6 | +end | ... | ... |
vendor/rails/activerecord/test/fixtures/db_definitions/schema.rb
... | ... | @@ -57,4 +57,18 @@ ActiveRecord::Schema.define do |
57 | 57 | create_table :lock_without_defaults_cust, :force => true do |t| |
58 | 58 | t.column :custom_lock_version, :integer |
59 | 59 | end |
60 | + | |
61 | + create_table :audit_logs, :force => true do |t| | |
62 | + t.column :message, :string, :null=>false | |
63 | + t.column :developer_id, :integer, :null=>false | |
64 | + end | |
65 | + | |
66 | + create_table :books, :force => true do |t| | |
67 | + t.column :name, :string | |
68 | + end | |
69 | + | |
70 | + create_table :citations, :force => true do |t| | |
71 | + t.column :book1_id, :integer | |
72 | + t.column :book2_id, :integer | |
73 | + end | |
60 | 74 | end | ... | ... |
vendor/rails/activerecord/test/fixtures/developer.rb
... | ... | @@ -31,8 +31,18 @@ class Developer < ActiveRecord::Base |
31 | 31 | |
32 | 32 | has_and_belongs_to_many :special_projects, :join_table => 'developers_projects', :association_foreign_key => 'project_id' |
33 | 33 | |
34 | + has_many :audit_logs | |
35 | + | |
34 | 36 | validates_inclusion_of :salary, :in => 50000..200000 |
35 | 37 | validates_length_of :name, :within => 3..20 |
38 | + | |
39 | + before_create do |developer| | |
40 | + developer.audit_logs.build :message => "Computer created" | |
41 | + end | |
42 | +end | |
43 | + | |
44 | +class AuditLog < ActiveRecord::Base | |
45 | + belongs_to :developer | |
36 | 46 | end |
37 | 47 | |
38 | 48 | DeveloperSalary = Struct.new(:amount) | ... | ... |
vendor/rails/activerecord/test/fixtures_test.rb
... | ... | @@ -12,13 +12,15 @@ class FixturesTest < Test::Unit::TestCase |
12 | 12 | self.use_instantiated_fixtures = true |
13 | 13 | self.use_transactional_fixtures = false |
14 | 14 | |
15 | - fixtures :topics, :developers, :accounts, :tasks, :categories, :funny_jokes | |
15 | + fixtures :topics, :developers, :accounts, :tasks, :categories, :funny_jokes, :binaries | |
16 | 16 | |
17 | - FIXTURES = %w( accounts companies customers | |
17 | + FIXTURES = %w( accounts binaries companies customers | |
18 | 18 | developers developers_projects entrants |
19 | 19 | movies projects subscribers topics tasks ) |
20 | 20 | MATCH_ATTRIBUTE_NAME = /[a-zA-Z][-_\w]*/ |
21 | 21 | |
22 | + BINARY_FIXTURE_PATH = File.dirname(__FILE__) + '/fixtures/flowers.jpg' | |
23 | + | |
22 | 24 | def test_clean_fixtures |
23 | 25 | FIXTURES.each do |name| |
24 | 26 | fixtures = nil |
... | ... | @@ -100,7 +102,6 @@ class FixturesTest < Test::Unit::TestCase |
100 | 102 | assert first |
101 | 103 | end |
102 | 104 | |
103 | - | |
104 | 105 | def test_bad_format |
105 | 106 | path = File.join(File.dirname(__FILE__), 'fixtures', 'bad_fixtures') |
106 | 107 | Dir.entries(path).each do |file| |
... | ... | @@ -174,7 +175,6 @@ class FixturesTest < Test::Unit::TestCase |
174 | 175 | end |
175 | 176 | end |
176 | 177 | |
177 | - | |
178 | 178 | def test_yml_file_in_subdirectory |
179 | 179 | assert_equal(categories(:sub_special_1).name, "A special category in a subdir file") |
180 | 180 | assert_equal(categories(:sub_special_1).class, SpecialCategory) |
... | ... | @@ -185,7 +185,11 @@ class FixturesTest < Test::Unit::TestCase |
185 | 185 | assert_equal(categories(:sub_special_3).class, SpecialCategory) |
186 | 186 | end |
187 | 187 | |
188 | - | |
188 | + def test_binary_in_fixtures | |
189 | + assert_equal 1, @binaries.size | |
190 | + data = File.read(BINARY_FIXTURE_PATH).freeze | |
191 | + assert_equal data, @flowers.data | |
192 | + end | |
189 | 193 | end |
190 | 194 | |
191 | 195 | if Account.connection.respond_to?(:reset_pk_sequence!) | ... | ... |
vendor/rails/activerecord/test/migration_test.rb
... | ... | @@ -170,7 +170,7 @@ if ActiveRecord::Base.connection.supports_migrations? |
170 | 170 | # SQL Server and Sybase will not allow you to add a NOT NULL column |
171 | 171 | # to a table without specifying a default value, so the |
172 | 172 | # following test must be skipped |
173 | - unless current_adapter?(:SQLServerAdapter, :SybaseAdapter) | |
173 | + unless current_adapter?(:SQLServerAdapter, :SybaseAdapter, :SQLiteAdapter) | |
174 | 174 | def test_add_column_not_null_without_default |
175 | 175 | Person.connection.create_table :testings do |t| |
176 | 176 | t.column :foo, :string |
... | ... | @@ -209,7 +209,7 @@ if ActiveRecord::Base.connection.supports_migrations? |
209 | 209 | def test_native_decimal_insert_manual_vs_automatic |
210 | 210 | # SQLite3 always uses float in violation of SQL |
211 | 211 | # 16 decimal places |
212 | - correct_value = (current_adapter?(:SQLiteAdapter) ? '0.123456789012346E20' : '0012345678901234567890.0123456789').to_d | |
212 | + correct_value = '0012345678901234567890.0123456789'.to_d | |
213 | 213 | |
214 | 214 | Person.delete_all |
215 | 215 | Person.connection.add_column "people", "wealth", :decimal, :precision => '30', :scale => '10' |
... | ... | @@ -227,8 +227,9 @@ if ActiveRecord::Base.connection.supports_migrations? |
227 | 227 | assert_kind_of BigDecimal, row.wealth |
228 | 228 | |
229 | 229 | # If this assert fails, that means the SELECT is broken! |
230 | - assert_equal correct_value, row.wealth | |
231 | - | |
230 | + unless current_adapter?(:SQLite3Adapter) | |
231 | + assert_equal correct_value, row.wealth | |
232 | + end | |
232 | 233 | # Reset to old state |
233 | 234 | Person.delete_all |
234 | 235 | |
... | ... | @@ -240,8 +241,9 @@ if ActiveRecord::Base.connection.supports_migrations? |
240 | 241 | assert_kind_of BigDecimal, row.wealth |
241 | 242 | |
242 | 243 | # If these asserts fail, that means the INSERT (create function, or cast to SQL) is broken! |
243 | - assert_equal correct_value, row.wealth | |
244 | - | |
244 | + unless current_adapter?(:SQLite3Adapter) | |
245 | + assert_equal correct_value, row.wealth | |
246 | + end | |
245 | 247 | # Reset to old state |
246 | 248 | Person.connection.del_column "people", "wealth" rescue nil |
247 | 249 | Person.reset_column_information |
... | ... | @@ -267,10 +269,7 @@ if ActiveRecord::Base.connection.supports_migrations? |
267 | 269 | |
268 | 270 | # Test for 30 significent digits (beyond the 16 of float), 10 of them |
269 | 271 | # after the decimal place. |
270 | - if current_adapter?(:SQLiteAdapter) | |
271 | - # SQLite3 uses float in violation of SQL. Test for 16 decimal places. | |
272 | - assert_equal BigDecimal.new('0.123456789012346E20'), bob.wealth | |
273 | - else | |
272 | + unless current_adapter?(:SQLite3Adapter) | |
274 | 273 | assert_equal BigDecimal.new("0012345678901234567890.0123456789"), bob.wealth |
275 | 274 | end |
276 | 275 | ... | ... |
vendor/rails/activerecord/test/mixin_test.rb
... | ... | @@ -211,6 +211,53 @@ class ListTest < Test::Unit::TestCase |
211 | 211 | assert_equal [new2, new1, new3], ListMixin.find(:all, :conditions => 'parent_id IS NULL', :order => 'pos') |
212 | 212 | end |
213 | 213 | |
214 | + def test_remove_from_list_should_then_fail_in_list? | |
215 | + assert_equal true, mixins(:list_1).in_list? | |
216 | + mixins(:list_1).remove_from_list | |
217 | + assert_equal false, mixins(:list_1).in_list? | |
218 | + end | |
219 | + | |
220 | + def test_remove_from_list_should_set_position_to_nil | |
221 | + assert_equal [mixins(:list_1), | |
222 | + mixins(:list_2), | |
223 | + mixins(:list_3), | |
224 | + mixins(:list_4)], | |
225 | + ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos') | |
226 | + | |
227 | + mixins(:list_2).remove_from_list | |
228 | + | |
229 | + assert_equal [mixins(:list_2, :reload), | |
230 | + mixins(:list_1, :reload), | |
231 | + mixins(:list_3, :reload), | |
232 | + mixins(:list_4, :reload)], | |
233 | + ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos') | |
234 | + | |
235 | + assert_equal 1, mixins(:list_1).pos | |
236 | + assert_equal nil, mixins(:list_2).pos | |
237 | + assert_equal 2, mixins(:list_3).pos | |
238 | + assert_equal 3, mixins(:list_4).pos | |
239 | + end | |
240 | + | |
241 | + def test_remove_before_destroy_does_not_shift_lower_items_twice | |
242 | + assert_equal [mixins(:list_1), | |
243 | + mixins(:list_2), | |
244 | + mixins(:list_3), | |
245 | + mixins(:list_4)], | |
246 | + ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos') | |
247 | + | |
248 | + mixins(:list_2).remove_from_list | |
249 | + mixins(:list_2).destroy | |
250 | + | |
251 | + assert_equal [mixins(:list_1, :reload), | |
252 | + mixins(:list_3, :reload), | |
253 | + mixins(:list_4, :reload)], | |
254 | + ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos') | |
255 | + | |
256 | + assert_equal 1, mixins(:list_1).pos | |
257 | + assert_equal 2, mixins(:list_3).pos | |
258 | + assert_equal 3, mixins(:list_4).pos | |
259 | + end | |
260 | + | |
214 | 261 | end |
215 | 262 | |
216 | 263 | class TreeTest < Test::Unit::TestCase | ... | ... |
vendor/rails/activerecord/test/validations_test.rb
... | ... | @@ -631,7 +631,7 @@ class ValidationsTest < Test::Unit::TestCase |
631 | 631 | t = Topic.new('title' => 'noreplies', 'content' => 'whatever') |
632 | 632 | assert !t.save |
633 | 633 | assert t.errors.on(:replies) |
634 | - t.replies.create('title' => 'areply', 'content' => 'whateveragain') | |
634 | + t.replies.build('title' => 'areply', 'content' => 'whateveragain') | |
635 | 635 | assert t.valid? |
636 | 636 | end |
637 | 637 | |
... | ... | @@ -824,7 +824,7 @@ class ValidationsTest < Test::Unit::TestCase |
824 | 824 | t = Topic.new('title' => 'あいうえお', 'content' => 'かきくけこ') |
825 | 825 | assert !t.save |
826 | 826 | assert t.errors.on(:replies) |
827 | - t.replies.create('title' => 'あいうえお', 'content' => 'かきくけこ') | |
827 | + t.replies.build('title' => 'あいうえお', 'content' => 'かきくけこ') | |
828 | 828 | assert t.valid? |
829 | 829 | end |
830 | 830 | end | ... | ... |
vendor/rails/activesupport/CHANGELOG
1 | +*1.4.4* (October 12th, 2007) | |
2 | + | |
3 | +* Backport: allow array and hash query parameters. Array route parameters are converted/to/a/path as before. #6765, #7047, #7462 [bgipsy, Jeremy McAnally, Dan Kubb, brendan, Diego Algorta Casamayou] | |
4 | + | |
5 | + | |
6 | +*1.4.3* (October 4th, 2007) | |
7 | + | |
8 | +* Demote Hash#to_xml to use XmlSimple#xml_in_string so it can't read files or stdin. #8453 [candlerb, Jeremy Kemper] | |
9 | + | |
10 | +* Document Object#blank?. #6491 [Chris Mear] | |
11 | + | |
12 | +* Update Dependencies to ignore constants inherited from ancestors. Closes #6951. [Nicholas Seckar] | |
13 | + | |
14 | +* Improved multibyte performance by relying less on exception raising #8159 [Blaine] | |
15 | + | |
16 | + | |
1 | 17 | *1.4.2* (March 12th, 2007) |
2 | 18 | |
3 | 19 | * Ruby 1.8.6 and 1.9 define private Time#to_date and #to_datetime; make them | ... | ... |