Commit b9846d60741788e84c889077d9b3b4786ba31042

Authored by AntonioTerceiro
1 parent 0088a8d8

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
... ... @@ -2,7 +2,7 @@ module ActionMailer
2 2 module VERSION #:nodoc:
3 3 MAJOR = 1
4 4 MINOR = 3
5   - TINY = 3
  5 + TINY = 6
6 6  
7 7 STRING = [MAJOR, MINOR, TINY].join('.')
8 8 end
... ...
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
  1 +#!/usr/bin/ruby
  2 +
1 3 #!/usr/local/bin/ruby
2 4  
3 5 require "address_book_controller"
... ...
vendor/rails/actionpack/examples/address_book_controller.fcgi
  1 +#!/usr/bin/ruby
  2 +
1 3 #!/usr/local/bin/ruby
2 4  
3 5 require "address_book_controller"
... ...
vendor/rails/actionpack/examples/address_book_controller.rbx
  1 +#!/usr/bin/ruby
  2 +
1 3 #!/usr/local/bin/ruby
2 4  
3 5 require "address_book_controller"
... ...
vendor/rails/actionpack/examples/benchmark_with_ar.fcgi
  1 +#!/usr/bin/ruby
  2 +
1 3 #!/usr/local/bin/ruby
2 4  
3 5 begin
... ...
vendor/rails/actionpack/examples/blog_controller.cgi
  1 +#!/usr/bin/ruby
  2 +
1 3 #!/usr/local/bin/ruby
2 4  
3 5 $:.unshift(File.dirname(__FILE__) + "/../lib")
... ...
vendor/rails/actionpack/examples/debate_controller.cgi
  1 +#!/usr/bin/ruby
  2 +
1 3 #!/usr/local/bin/ruby
2 4  
3 5 $:.unshift(File.dirname(__FILE__) + "/../lib")
... ...
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
... ... @@ -82,6 +82,7 @@ module ActionController
82 82 end
83 83  
84 84 private
  85 + # Recognizes the route for a given path.
85 86 def recognized_request_for(path, request_method = nil)
86 87 path = "/#{path}" unless path.first == '/'
87 88  
... ...
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
... ... @@ -65,7 +65,7 @@ class CGI #:nodoc:
65 65 if env_qs.blank? && !(uri = env_table['REQUEST_URI']).blank?
66 66 uri.split('?', 2)[1] || ''
67 67 else
68   - env_qs
  68 + env_qs || ''
69 69 end
70 70 end
71 71 end
... ...
vendor/rails/actionpack/lib/action_controller/cgi_process.rb
... ... @@ -2,6 +2,7 @@ require &#39;action_controller/cgi_ext/cgi_ext&#39;
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
  1 +#!/usr/bin/ruby -w
  2 +
1 3 #!/usr/local/bin/ruby -w
2 4  
3 5 # This is a really simple session storage daemon, basically just a hash,
... ...
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
... ... @@ -2,7 +2,7 @@ module ActionPack #:nodoc:
2 2 module VERSION #:nodoc:
3 3 MAJOR = 1
4 4 MINOR = 13
5   - TINY = 3
  5 + TINY = 6
6 6  
7 7 STRING = [MAJOR, MINOR, TINY].join('.')
8 8 end
... ...
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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &#39;stubba&#39;
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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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
1 1 xml.html do
2 2 xml.p "Hello"
3   -end
4 3 \ No newline at end of file
  4 +end
  5 +"String return value"
... ...
vendor/rails/actionpack/test/template/asset_tag_helper_test.rb
... ... @@ -165,7 +165,12 @@ class AssetTagHelperTest &lt; 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 &lt; 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 &lt; 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 &lt; 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(&quot;header&quot;, &quot;&lt;h1&gt;Greetings&lt;/h1&gt;&quot;);; return false;">Greet me!</a>), html
  39 + assert_dom_equal %q(<a href="#" onclick="Element.update(&quot;header&quot;, &quot;\074h1\076Greetings\074/h1\076&quot;);; 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(&quot;header&quot;, &quot;&lt;h1&gt;Greetings&lt;/h1&gt;&quot;);; return false;">Greet me!</a>), html
  46 + assert_dom_equal %q(<a href="#" class="updater" onclick="Element.update(&quot;header&quot;, &quot;\074h1\076Greetings\074/h1\076&quot;);; return false;">Greet me!</a>), html
47 47 end
48 48  
49 49 def test_button_to_function
... ... @@ -55,13 +55,13 @@ class JavaScriptHelperTest &lt; 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(&quot;header&quot;, &quot;&lt;h1&gt;Greetings&lt;/h1&gt;&quot;);;" value="Greet me!" />), html
  58 + assert_dom_equal %q(<input type="button" onclick="Element.update(&quot;header&quot;, &quot;\074h1\076Greetings\074/h1\076&quot;);;" 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(&quot;header&quot;, &quot;&lt;h1&gt;Greetings&lt;/h1&gt;&quot;);;" value="Greet me!" />), html
  65 + assert_dom_equal %q(<input type="button" class="greeter" onclick="Element.update(&quot;header&quot;, &quot;\074h1\076Greetings\074/h1\076&quot;);;" 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 &lt; 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("&pound;1234567890,50", number_to_currency(1234567890.50, {:unit => "&pound;", :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 &lt; 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 &lt; 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 &lt; 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 &lt; 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
... ... @@ -2,7 +2,7 @@ module ActionWebService
2 2 module VERSION #:nodoc:
3 3 MAJOR = 1
4 4 MINOR = 2
5   - TINY = 3
  5 + TINY = 6
6 6  
7 7 STRING = [MAJOR, MINOR, TINY].join('.')
8 8 end
... ...
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
... ... @@ -14,7 +14,7 @@ class Mysql
14 14 MAX_PACKET_LENGTH = 256*256*256-1
15 15 MAX_ALLOWED_PACKET = 1024*1024*1024
16 16  
17   - MYSQL_UNIX_ADDR = "/tmp/mysql.sock"
  17 + MYSQL_UNIX_ADDR = "/var/run/mysqld/mysqld.sock"
18 18 MYSQL_PORT = 3306
19 19 PROTOCOL_VERSION = 10
20 20  
... ...
vendor/rails/activerecord/lib/active_record/version.rb
... ... @@ -2,7 +2,7 @@ module ActiveRecord
2 2 module VERSION #:nodoc:
3 3 MAJOR = 1
4 4 MINOR = 15
5   - TINY = 3
  5 + TINY = 6
6 6  
7 7 STRING = [MAJOR, MINOR, TINY].join('.')
8 8 end
... ...
vendor/rails/activerecord/test/aggregations_test.rb
... ... @@ -93,3 +93,21 @@ class AggregationsTest &lt; 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 &lt; 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 &lt; 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 &#39;fixtures/category&#39;
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 &lt; 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 &lt; 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 &#39;fixtures/order&#39;
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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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,
... ...
vendor/rails/activerecord/test/fixtures/binaries.yml 0 → 100644
... ... @@ -0,0 +1,437 @@
  1 +flowers:
  2 + id: 1
  3 + data: !binary | /9j/4AAQSkZJRgABAQEASABIAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsL
  4 + DBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/
  5 + 2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy
  6 + MjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAFeAQcDASIAAhEBAxEB/8QA
  7 + HAAAAgMBAQEBAAAAAAAAAAAAAAUDBAYCBwEI/8QARRAAAgEDAwIEAwYEBAQD
  8 + CAMAAQIDAAQRBRIhMUEGE1FhInGBFDKRobHBFSNC0SRSYuEzcvDxBxZDJTRT
  9 + Y3OCkqJEstL/xAAaAQADAQEBAQAAAAAAAAAAAAAAAgMBBAUG/8QAKxEAAgIC
  10 + AgICAgIBBAMAAAAAAAECEQMhEjEEQRNRIjIFYaEUI0KBcZGx/9oADAMBAAIR
  11 + AxEAPwD3+iiigAooooAKKKKACiiigAooqrf6haaZaPdXtxHBCvV3OPoPU+1A
  12 + Fqo5p4reF5ZnVI0BZmY4AApBp/iy01qK5fT9wWCXy3MgwegIOPQ57+lSGXz9
  13 + xL+Z2POaFsOhbe/+JGjW0hSBZ7kD/wBREwn4nk/QVHD4zfUELWzRqMf0jOPn
  14 + np+Ffbzw9otxG7T2MKZyWkT4D88ilGn6XZ6e0v2SNgjH/iSEFmHYewqU7Xsd
  15 + UxjNqd9Nz9plAPUD/aq+ZmU+bI7c9yTx+NSrt5AxnviuRgMQSfnUmxkivMko
  16 + t5PIYGbafL3DI3Y4zUGnXBtbVbZrlzcRAmXbkc5ycc+9XWkQA5PGPqKzng+x
  17 + OqmZpmfDO3mMDghc8YPrWxV6Rr6NLZ6/dOFaG9kZTnaM7s44PWjUfHl5ozQm
  18 + 4s1uInJBYZQ59KzFpaz6Fqs2kytlQ++3du+en4jj51Y8QvDcaUF3Av56ADHI
  19 + OcHP40OUogops9GtPEllcBRIWgdh0ccfiKbI6yKGRgynoQcg151tA4AzirFt
  20 + c3Fo5e2mdD3CnIPzFOsn2K4fRv6Kztl4ojICX6GJu8iqdv8AtT+KWOaNZInV
  21 + 0YZVlOQaqmn0I1R3RRRWmBRRRQAUUUUAFFFFABRRRQAUUUUAFFFFABRRRQAU
  22 + UUi1TWGBaC1J9GlH6D+9Y3QJFrUdYisgUQCSb/LnhfnWYeBfEE8v8Sj86Jei
  23 + MeAe2PTv0qIqWVsTMnvj+9TQyvBbCKCRNx5aRxyT8qTnuxqMdqWnyeCtTeS0
  24 + eRtM1H4MMcmNwcgZ79Tg+nyrR+FtU+1zy27cMi5bJ4znioNc0yTWNPmgciR2
  25 + X4GJ+6w6Y9P96W+DUVvD6nawnSZ1kcH4gwPGT8jSXux2rRo9WklbVltpR/h5
  26 + YMR55BIOScfhR5SEbhkgjpnNRX0811bwBgBcRSh0ZiACOhB7ZIohiRQYymNp
  27 + wTtFLJ7BdEhQ46DjoOlLdUj1CSPFrK0L9Q+0FfkfY+vamRBAciQr74Jrpjv2
  28 + MsilCMjjOfrWaNsWeH7HUrI3V9q7KqrATCcq3xd/u+1MvBaQjw/HJEMu7MJP
  29 + mGP96W6nqZ0u1/lyfAzZwrdKe+HpI5dEhljQIrs7kdsljmqQq9Cyeip4p0aT
  30 + VLeKe1QNdwdADguvpn58/jWI1CDW4PLF7Yy7XkGP5YG9+wyOpzXqu7r/AN6y
  31 + Hi2/JvtLsYQMi6V3bBOCBkDHyOa3LFVbNxSfIpaWdTUN/ESEkP3YdmCo9Wx0
  32 + z2FNt27+lh/y1BHE6AkXBLMcneepqdGcjDKp9xUn/RpIFBGSWJ/1VNZXFzpU
  33 + 7T2h8yJzmS3HRvceh/WuN4AyQT7CoZ5YUTzHLY6AhelCdGNG407U7bU7cTW7
  34 + gjuO4PpVystpyC2tIlUkFRnPQ5praa5aTXYs2mX7R6DofbPr7V0p/ZIaUUUV
  35 + oBRRRQAUUUUAFFFFABRRRQAUUUUAFFFI9b1IBHtYnKnGJHXkj2FY3QIj1bVt
  36 + 7m2t3wv9bjv7fKkgCqBt49s4rvChVAIwR3FUri+t4AwBDt/lU5IqDdlEi0wb
  37 + qGP4igDoeM+uKV/xiIuCLZsgfeBFTJq0Dbd4kjJ7EVlm0XfLywOyPPqc1m7K
  38 + Qaf4tvbBXDxXq/aYmRsDcPvD5itCk0cikqSV9uaw3ieC60nUbXWbVH2QShg/
  39 + YZ7Ee/SjsaPdG6+PaeXHGPi+Kvq4XOSSf+XioYb6G5tVnWaMb0V1G7Gc88Zq
  40 + YljkDI49jWCg5B3Kccjngj86TPdXGkTJ5+JrVzxL/f0b3/q+dOdzc9Bx3FVp
  41 + XcBo7iHfGwwXjG4YPqvX9ankjf8ATArx2tvq9wpuIle2lJhPzIyrexzVrwoy
  42 + 2PhlIp3OYJ5YyzHJOHNZ+DUP4XDJaKA/xCe3kU8DBG5T+Rx2qTSn82/1JpN2
  43 + EuCVbkD4iScDt2rcWZPXsKtM1UWvW0k5jZZI1z8LshAP/X0pTqNlbfx+G5uJ
  44 + WFrnz12ty79MZqxEMHImb/8AL+9KNatXu7zSLYOcS3JQ4OMjGccfKquV9mRV
  45 + PQ7VgzHZh0z8J9R2r4ygjJgOR6GvgiMfwFcY4x6e1SKcZwG49KUY+bR03MPY
  46 + io5UeRo18xVj3DcGA6Z55qYnjJPHuKjCuZnYrwcbfzzWICxe3c038u2bZH3f
  47 + puHtzxUEcSx4KiFccg4qfZnBKr060eWrf+mh96ZuxaNDpGqmcCC4dfN/oYH7
  48 + 3+9OKw2NoBUKMc5BrS6TqX2uLypionUev3h61WE70xWvY0oooqgoUUUUAFFF
  49 + FABRRRQAUUVDd3Mdnay3Epwkaljjv7UALNe12DR4UViTNLwoXBKjuxrINrtp
  50 + 8Z/mk5yOBzz86w2v22q61rN5qV1ckFz8EYHCL/So9gPxOaZeEfCsGsWly1/N
  51 + KskUgVfLAAwR3yDUv3einFJWxzda1PczR2lhbu80owoIGc/sPepLfwO8+ZdU
  52 + 1CRnbny4Oi/U9fwp7o3h+y0NZfs293kxueTG7HoMdqamnUUhXL6MqfAmnf03
  53 + V2Pqp/aqdz4OvrYM9hqmVAJ2Tqf2yK2hrlxlGHqD+lDimHJnnUv22ythcDEx
  54 + ABIjBRjn0x1qP+Pw3VpNZXnmbJVKOlwCSAfzpyozaRkf6TWquLa3ucieCKYf
  55 + /MQN+tShHkikpJHleo3yfaLNIifLREjXYODgY4rZ2+pQGBRL8L4GcqcE/Okf
  56 + iHw7Y2/i/RpREYbG9cwSrExUB8cEemcj8Kin8PxRW0vkyTRshZQwkORzjPvW
  57 + SVM1U1Zp1vrZwwEij/7hXYuoC6YmTnpzSlvBN1jCa25/5oz/AHqH/wAl6n0/
  58 + jEeP+RqPjkZcfs41y0S9VpIDCJoviLAYPPTJ7qfun0OD2r54Xt2tNJkkmcMJ
  59 + ZN2ScEEDBBqm2lXlhLceZfebLGTFjACyBh9315qHSI7vUGuNLtZ1Ty084tJ0
  60 + zkcHg+p/Co8ayX7D0bBJ4eAJFz6Ag0n1m8W3v9Ikt23SpdhsenAGPzquPC+u
  61 + MuUvrNvQ5P8A/mld5puoQ6nBZ3MqNPuDI0S5A4zjGOapJNKxoU2bjz4ppjIH
  62 + XLEnG6uvNjDEGVAfQsKyMPh/X5YopTJahZCQm4bTnnqMcdDVoeG/EQXn7ER6
  63 + 7v8Aam4SYujSNcQooZnUAjgk1Vk1e1jbClpOOqAnFIBoV7BfCK8u1Zdm7bb/
  64 + AAjr3OM9qt2nhG2u1aee9vNpYgRq/Ax7nJpVFt0DaSsmk19UwRGqjHR2AxVV
  65 + vEvnSeTCUaTH3IlLn9KbweEtEhOfsXmn1lkZ/wB64nsLS21BBbW0UIEYyI0A
  66 + zyf7Uzx0rFUk2Imv9SuHKW+nXcjA87VAH1xU0C+J4LlLmDTJEkRtykuOD+Na
  67 + TRRiCZvWT9hTPNNCCasxyp0PtJvpNQ06KeaBrecjEsLHOxu/09KvVnLK7NrO
  68 + CfuNw4/etECCAQcg1YQ+0UUUAFFFFABRRRQAVjfFl7Jc3CWMLqIozmTJ6t2H
  69 + 0rU31wLWymm3BSqEgnpntXmbxRFi93eFpGOWII6nr61LLKlQ8Fuylc282Sm9
  70 + GLZxtPFPfBltJBZ3byDDPMBjOeg6/nSaaGzyT9rcducf25p14Tt1gF5i5EpY
  71 + r8I4wOeaTF2PPo0lfK+18roInyuTzx619Nc5yR86AMmn/uij0X+9arOe9Zcg
  72 + Lan/AJW/U1pVbKA+oH6VHF7KZPRl/wDxAguZPDyXFvn/AAs6zPhckAdG9sHr
  73 + 7Gu9NUa1pSz+YiCdd+SCeT1H41opESWN45FDRuCrKehB4IrzPStU/wDL+o3O
  74 + jzo0qwTlYOvIzwMDrng0ZNbGhuNL0enhgVBB4r4XGcZ57CobdmNuhZNjEZ25
  75 + 6Z5xSme41FNajxbM9sgyxDBQFIIyBnLHPb2qquhIxuxdrM9iLq4tp7nE87/B
  76 + Eg+LPGPl659qVWd0ItanAPlSXVtASPUgDP49aZ3sS6hqmNnCTGSKXaTzxkYH
  77 + Oec4r5B/Cv4zJY+WJSYUy8icRhST97qM59ulQS5y0WStaNFo6sYQsz4y/Xpx
  78 + Vu50/SrbVTfyI5uUUlGZshBjGR/ekg1CQ38sUdxCI4uGVyCu3b14yevH071F
  79 + q2tm40O5ayQz7I2SRZOGMeSu/wBcZHz71alFD4sDlNL7HR1iC7ZYbWZJZFYl
  80 + gxycd+frXUM4eC423SlUDFnEmCp78Y4rxWzvrmyuT5UjJvDAc9Djg/iBWi0G
  81 + z1OWC7nvUxb3iZCyyhDLk5OBnv61kZNns5vAWJfsb5pUcIkzpdIcslwnBx6Z
  82 + qzDbm1i8vOVDEg56gms/a3t19maNIII41ciBUbKP/pO3gZ9+9ffD+uS3IuRf
  83 + xSQyrhREImyOee1brs4s/hucXKPo0OaUXuTqDsD9xRn8P96ak4AIIKsMg+tK
  84 + ZmBnum684/IClydHkxTTplvSRtsz7uf2phmqGncWae5J/OreaaHSFl2SZp1p
  85 + F1vjNu5+JOV9xSLNSQzNbzJKucqc/OmMNbRXEUiyxLIhyrDIrug0KKKKACii
  86 + uJHEcbOegGaAFOtOssE0LKXRY23KOp4rz4G2KqYrXzSB1MhOfpW5nlKpJKSM
  87 + gFufWkDFY4wcqD7cCo5R4GflePlm01Rjvg048JvbNNe+RC6nCbmL7gOvH71z
  88 + NMh/rQY5zmrOgXkbXU0COjBl3jaO4/2NLjVMeTtGgr4aK+E10ET4a5/qHzoJ
  89 + rnuOO9BhmSMwMPdx+Zp9A262iPqin8qRngEf63H503tDmygP+gfpUcXsrk6R
  90 + P8ZcgIdgXcX7DnpXnOvW/keMLO8x/LndkJxxuGQP1FbXVrxba2IbcQ3BCnBG
  91 + eAfx4+tYi91G+sFa4liaWzyFwy8MT0x6H3olttfQ2FPtG5nvrO3s42uyjKdg
  92 + 2k45OPz6UtvJ7OzX+L3N/cSxN9yPHwEYxjH9Rz3+VUNW1C1bVbDTZraV5cBg
  93 + XJ2o3RenJ619n1C+kv7iyfS47q2ihDLC2SgbdgLkDt6VXotGHFHwv5MkGr6f
  94 + bsIGhMkqI5Ujg4O2ki+JGu5YtS+yC2aCRlLA7lZyh27vUdevv0qbSLkskpuo
  95 + pPMM3mJAchdmcFc91yzD5AVNJFDZ6vYXbqYrFpzIYHA2IdgIJ9Tlu/SpKVp+
  96 + jE1xaS2z7JPeaQl5qi6Oi6nJI3ltC2+IjIySOpx+fFfbLULmQLe3Vu9tLOrB
  97 + 9q/CA3XI/PGO9T3Op2sV5HZlJWi6ZRMoueSQ3TH9qQ313cNrU9n9saa3SMPF
  98 + txg7jjHAHvTN0jVKUUnI+ar4euINIjlijE0GTK95GRgbuAo74+feov8AzXdJ
  99 + bSpcxx+RFCqCIjKS9sN36VY0zV5U8QyjyjeWUluYZLYOQriNfh/Aj86+eIbO
  100 + C70e3uY9GuLK6mw00IRjEqrkb1PoSRxSxaltHteL5X+phU4/lfY78MapBa6A
  101 + 2pzLsWMsiW0RZsDspJJyOc57Yqg7R6nplrqtoLiR7TepG7bvVWyOexwevtXS
  102 + aWb3w3Y2lpfPGtunnO0cfwM56Bj1yMdKjtLN9QsorC31FLXVbdyksUHwM68H
  103 + cezH3HrzTd6FjlhHI3e7/wAG40mXULvR47i+hjiZmyio3RT0HrVCUh4p27lj
  104 + +pq1ptpLp1p5U15c3Ug+887Zx7AdBVILnT2bONxFLk6SPFzOMsspR6GlkNtn
  105 + EP8ATVjNQwDEEY9FH6VLVV0crOs0ZrnNFaYONC1KN55dPLfzI1EijPY9f2/G
  106 + n1eeQXMdv4hjvAnxxfy2YHqvf9a9CUhgCDkHoaVOxmqPtFFFMYFUdRkxGsY6
  107 + scn5VepPev5l03ovAoAWaqC2lXIBwdmc/UVmryATxqzyMSnI9K10iCWJ42+6
  108 + 6lT9ayYsL74lLxoBkZLdcGo5NbHhspSbUhZAMFl6188NqV8RR7XLKUfPHtU0
  109 + +n3TDHn2pOO7Hp+FWPDGnyxarPcTPHlEwqo2c56n6Y/Olg7Y8lSZq818Nfa5
  110 + NXInJNcE81xdTpbW0kz/AHUGfn7VW068+22KTH72SrfMH/tWclfEwVOOZP8A
  111 + 6rfrTKzcCwh3EDjH5ml03Dze0zfvVq2KHTB5jBVUsMk9OTSYV+VM6eKlSYv8
  112 + Szo1lJFjEoUlM9++PkQOD6rWSl1GPVNIudPQZUWrPvP+ZQCAPw/On+txfb9M
  113 + YRuXVVOwjnHr/wBfKs5a+H2to5J5b3EiwvlFwEAIPWun4JKTr2j0MfjPEnH7
  114 + Rb0O/TVbaF5IVDxIsQCgu74/PmtNNbyrbrcOVgeNcrGAM8c7iQOG9ecdqwXh
  115 + C5u43kitI1aTf1ILdR6d69Dgg1JmC3dygk67Qq/sKEvwSbJZE1BJtJCm0vG1
  116 + HR/Pmgt/tQm3w7i0bZHTnHIx17VT8TX88Wgwy3VpayyzTlFkWTcsLDuBjvjk
  117 + GpdUtG1LTHhglkV5JiiKATg55OR0yfeszqpKrp2nXVyzRjYJVPCnLEFh+PWo
  118 + T2miM0q19lvw/BqF/EkvkwSQxRsyksUDM2AARyDyDx061SuLhY9RR12hnQxy
  119 + NjlcZA/DJrVXFvarexWAypnjEVwqNtVWjH3/AJlcge/NYeVHinEbv8LMcM/U
  120 + Zri8mMqTT6ORt9n2y1aXQbthp7lrlsoFMQfqfetT4Wn1t9bmk1VtRvLdQd4+
  121 + 0ZjVj2IzgnHbt6VVh0qS1msYI7VZprtVlcn4OMnI389AM1usGCwYFI02ofhj
  122 + GFHHaqeMr2bGTXQuvb43asQqRxIpWNEHAH96R3+iTW+u21/aIWNwoJKttZWC
  123 + jODVzdi3b3WtKijy48j7oBHscVbHtuy6yvHKyNmYaczu4Z/LOT747+9U8YsU
  124 + X3/TirWoEixkx7fqKqghhAB3GcfM1mTtEou7Y2XhQPQV1XzNFWJH2vvp865/
  125 + OvvagDPJMftcwbqHbr869C8O3n2zSY8nLxfy2+nT8sV57e2E/wDF5DAUMb4Y
  126 + 5bGCeorUeEVubW6mhm27JUBGGz8Q/wBjUouplGribCiiirEzmRtkbN6AmkJJ
  127 + JJPU02v322rD/MQKUUAHz6VjdunjcXu5nBJwPQdhWz71kbkP9olC6Ygk3nJ2
  128 + gjOe1SylMfZQlGkYJM0wHrkCrPhj7AmtSfZ5pWeSIhEbtg5JriUTkfFpkBI9
  129 + QKseHZJP4vIg06OBfLPmSgY+QH1qWP8AYpL9TVk1H5ikZBB+X71WvZpIwCF/
  130 + l7SxORx8x1rLa54peztU8pfizxnvjviunrs6PH8KWT/sZ6/M8toIwAESTdNh
  131 + uQuPhOO/Jr54YdZLC5aMlohOVVuxwADj615/b69qeoaq08cbvb7fLuFUZBQk
  132 + 9flk16fZoLfSrWK3gwFjVUQHAUY6n9frUlivLzsn5XirDNJPsXTn+bdA/wDx
  133 + jj86U6jeJb2RkuHxbxSt1PUk54Hc1b1HU4rS5ePyWnk35l8vlV/ufYfM1gvE
  134 + Mlzf6jHCC6yP8axFs+Wp7kdASPyrqxYuDcrs7/GwcGpSHV7eX1xobTWsQt0L
  135 + qI92S7ZOOnQUvk8OXklh5z3Msmw75IT0cdz8/nUHiDxMp0dLC1zHeJMjMwxh
  136 + dvPB789qjt/H9yLUR3dmjybcebE2AfmP7VWWXE7Q2by8TvGXtIvZdJ1PUHjb
  137 + Ys6xMpx3yeR+dX9S8V3ul30BCRSrMDnepLAdBgjpnmvPodUuWnlkZgzMMYbk
  138 + Ae1fBqtw95FPI+4xgKN3IA+tcDuzyJytJ/Z6SPFlvNA0UsJhZhjGf0980jPk
  139 + ag80TyZuG5LNzypzgew9PnVFmaRhNLAPL3KOExgk1Sllc3SNajE6uWPP3vlW
  140 + OaUqZabg40ns1uma1Dp97MsyBlZCvxLkx89P+WkV8Gv7u6nRT5QYFQzYIU8D
  141 + A79K6Zxd3Pm4I2oRIcfqKl0x7h7hzHCsqKdrsFB2Z7j9allleokZf7m6IPJ1
  142 + C5svtZaRre3HlKwbO056e3BNbDTNf+1aJJDcuBOIgiHu/b9vzpVc3FzHYtM8
  143 + 3mxlzDcqMfyjxgkf5T2P71Rj8tdRRQ/lqM4A6ZPr7VBuWOaUfZFKmaHP8nHr
  144 + WpR1bhTyvBBHIrPTLZWUP8y5EwxztRjj8BUN3fXlpGl2pE0BAwzPyAfQ16sM
  145 + HFNyZ6P+kc1bdD7UHxbquOWccH6moxGRcQsP+GQAPxrODxDNdvkBYbdOMdSx
  146 + P5AVqbDElnFksSGzyfQ0QxxyxckZHxv9pyLwr7XxSDnBBIri4nW2haR8kDgK
  147 + OSx7Ae5pG67PPao73DdtyN2M49q6HSq9rC6K0kxBnkIL46D0Uew/uameWOLb
  148 + vdV3HCgnk/Kl5atgI7pYm1OZjfSRfFgoCODjmmmmOltdwT/xF22MMqSMEd6V
  149 + 3Em3U5vMsDKSxG4KDkDpV5WhdCG01hn/AOVmot/kXS0ejCiqumzi5063mAI3
  150 + RjgjBorpIEGpt/w0+ZpfVvUGzdY/yqBVSgD4x2qT6DNI5ZY+GduW5zinbruR
  151 + l9QRWNuYjIqB5HAUYwvFSyDwL8k0KoWDA49aqWuoKuoRCMln5Coq5ySMc+1U
  152 + nVUTqfTJr5oK2y+IIQ80kbPlEZT1J7H2NThTkWj3shv9Qvopjc3AYRnekqbc
  153 + lSCRkEHHpS/WbqC/8LQ3ChfMViOgznJHz9K2uuae08EhtZo4lwfMSRcqw+Ve
  154 + fT2V5cyNZwNb+TGcyeQmFz8zkn3roPfw5ccoprTRBpvlWNgFnIMcoO/y/vxt
  155 + 1Vx649PpW3i1K8ufDdobBV81l2NJnhSOoX3wM5PCjk+lefajpuo6YVuWhdrK
  156 + U8SgcBuhU+nPrTDTNVl03T7hHybeYEBCeG6ZGe3zrljOUMr5KzxJRyZPIbSv
  157 + ZFc6mJppXVi6hyikfdwP8vtyeTyaQajqN1Cs1nGw8mSTzS45cnbjBbrjHGKc
  158 + XiFUEtr/AC4CcALyDnBz6+tZ67tZBG8oRtkbBHJ7Ek4/HBp8kZqbk3pjediy
  159 + 4Zu32KpG7CmOiaeZdQtZLy3ZrJ5Bvy20MM4HPpnFUZAf8hP0q3c6o8oYxIY5
  160 + GTBYHABxzgDpWxqjghXs0WsWFjNExgtYbW4iB4hXaGXuCPUdc1jAp3EGnEuv
  161 + S3LDKhJiMNj7p46/OoJNJuYLCLUiUa3kYrlWyyn3H0plrseauCaLFhcXETrF
  162 + 5itHwWVxkEjp9acwaXHdSiZLYOqMCQJMLk9Mhsj86zkEzSXGegGWxn0FNLa+
  163 + lis5JLa8mt7gDbIqNgSxnr0689q55wuVoxPpmgtLOWS2lZmJUEMzyOAAfcjq
  164 + Dg8DPNPrS6g1K6ktbOwhgKBVy6/CMcsB3yKx2l6sttcLIYhcKse0RkZIOM7g
  165 + PbmnOlX0mpaVObdtupQnzBI7qo29CqjOT79uRW4fxSXstFpvfbDU7Bk1nzLj
  166 + NnEQBNKULRHPQE9s4pVLmO7lERQ/GdpDZBAx0PpTfxDLq1n4Wij1LUIj5s2y
  167 + SEgGRl6g5HYd/pzWbtUjhs2mWXzGX4uOMe36UZqg7JypScWO4/EFrCBHcpcM
  168 + /XK4wD8s1WkvjqtwsNu7NGWwqHjBPcis5d3G+Tdg5bOCO9QwTSQyrKjlHU5B
  169 + HY1s5znHi3oZ+TOS4y6PQL/TvIgh8pcPCNpH+cHrWgiuxaWSiVxGoxuJPTPQ
  170 + f7VlbDXHlRUuI2AIBV+uTjn61dtJI2kE8rEuGzDGxGB/qYk4B9M125fKxwin
  171 + jPanmgsaUTV298DdLAu2OJI2ll3n4lXgLn0J5OOwFVrzVIoWFzIQ0i/+72+e
  172 + Vz/6jDsT2z0HuazyWr3F35twpVmJkLQANxn1z0HSrwg0tzsjuZkctktLHnHu
  173 + Tj8q4ZvLNNw/yeRkwy3OySzvr26BiSRzvbLMik4HpTi3tPs264MZaVQT5kzc
  174 + jjsBk/iahtg8cax2WpxzKD8SqieZj2z1q9LaSNbyhru4clGwMqAePQCp4MDW
  175 + 5ttnOL4r6OM7pGxnk59aaRX8Lx5WQHA7VmIPKePDBSetMkWBcbBtx3U4q10W
  176 + aN34dvEutPbY27y3K/jz+9FJ/Bjqs17EHLbgr8/Uf2oroi7RF9jS7O67lPvi
  177 + oKkmO6Zz6sajpjArJ63E9pNNKCrQFwPvEMpP7Z/WtZWT8QixN1Mtx5vxgBlX
  178 + AB461HOriNG/QnR0nbaZynrlckUxmW10uGK2S5UTzpuErdz25/asyA9sWcOZ
  179 + IlOPNI4+voahlvbe9E0VwFmi3KqSrz5QPX8+a4vFzT+Rwmv/AAdfhtc6yly3
  180 + 1mSa9NnegPLzHuJ3itfpVlGI1iOFbb8QRR+HXivOLCwuZ4pbvzBw+wzSOFAx
  181 + x1NbnwvrOnTnyBeIZohsBYbBJ7jPWvTtJbPR/kY44QTg9/Q61W5stN0qQXWU
  182 + gcGPCruJLA/9+a810/TJ7u5FtJbNLCzbd/Kqvo3rWm8S6xDdynT51P2cuCjI
  183 + fvY45/Glya6ukXUXm7JIYv5bNHyQh7ZHccHFGOcHLg+w/jcsccJQ/wCb+y7N
  184 + 4SjFmYY7whs8jy+ODxjng0raOSTxHb6HJCV0+VQJfg+KQKM8t6ZxWwinWR1Y
  185 + SLJDMA0Uq9Dn+9c3Vosw3D4ZB0YdR8q7XhjI6MrnmhwkzPa34DsrmNZNOb7J
  186 + Mp+IElkZflng1kn8F3q69Bp5eNlmUv8AaFBwFHXI9eRx7ivV45fMiDNjdjDY
  187 + 9ahRR5obA3KCAfrTPxsct0csvCxSd1TPOr//AMOHtru1axne5RpVWVHUAqp6
  188 + tn0FSXuiXekeDdRhvvLbADxmMkgHcPb1r0VcctVW5tY9RzbTxLLbhgZVYZDE
  189 + chf3NLPxYPoWfhQpqOjyLw54fu9YMs6FYrVT5Tzv0BPp64/emH/k7UyjSwiO
  190 + RMOVBcKxAOBkH1616usVtDD5YijWIcbFQBfkAKzWr6DA8UrWsW2/nYgNH1VD
  191 + wR1wBiufJ4/FWck/D4pGQ0DQbq+t7u4M32aOJ1VhKjckc9uncH507tJtL1Gz
  192 + k0/StPgNw33zIQoYY5YZ5YZ47VHptjq9np0kc6faIzKqCGSUnacjH0B5OK7+
  193 + x2+l2989rO0GrRjMfl8qWIyqjdkHIzkVDhSJ8IxTTFZjkksp49eWZZc7LWQq
  194 + SVYHO044wfeoZY/8C8QABxj2HvVOfX9Rv5IINTuA3kSH4WjCEN0ycdT1poLK
  195 + W7RzDtYIuWBYDI9Oa4M6lLIlFEG+b0hJHp8Mlr5ousXhkCRwbOCvTdu/Ouls
  196 + EgeQ3GSyHaiQ/HkDuSOPrVm6eOEMsIQzbQpdzxj29KoB7sfF52VUfHsHTnHp
  197 + z1FHJzivQtK6SNJpltNe6WTGhWDc2AHwSe5JPNfNMuIrTW5LSWEXEQj2eQRu
  198 + ZD169D/Y01gvo7fSf8LA+ETc0sq4APqf8x/Kl2i6bJaXrXbEtdRL57Bj94lv
  199 + iH54r1oeMoxS/wDZ7ePx6jFP/s0M1vp8b201vAYJHI3KmUGD24PyqVB5dwGS
  200 + 3ildeMSSsJPmCTj6Zqtq+qRXEEb2YZVE2xm+6UbHwg/PI/EU20a+t9V05HdQ
  201 + JSSkiMOdynnj1quLx4Y5Pj0XhhjjVpdjK3vFKIs4eN2+5v8A0+dXtjLglSM9
  202 + KR3TXlmN0UMc0HRkY9R9ehqxZ6/Z3DxwfzUJGPiXOwj17ikzY1F2ed5Xipfl
  203 + ETw21lNdyst15aFziPI+HnpTIadalBi7P5VSt2mLuX06OTLHLKQQ3PUVfWS2
  204 + uIZolskeWNSZoQBvUZ7Dv9K8/i2zl3Q68I20dteT4lErsMFvQdQKKPDO2OfK
  205 + 25gUscKRgniirQ6OeXZfY5Y/OvlFFOYFZ3XJJRclBZCX4QVfGePw9c1oaQ38
  206 + 4E8jM5ADkDHtU8nQ8OxG0c15ayJJFLZiNS4KfCWPT0rz4SzWNzLMsJkhclTG
  207 + 54f5Y+Wc9q9RNxEwPTB7N3rH+ItklykpaNM4SOFEGyNAeeffvSRpqmel4+aH
  208 + B48iszyWX8Zg321rIhJ3CN2JU+6kcZ+dSWIl01wJ4JYecfGpxWkit7OwuWe3
  209 + EcaPGGPlggnPOMDgY9R7VPNNBLZFLpRIrLzuIIXHqaHgU4W3Q0fBWXH8rkIr
  210 + 7WbaVlgcFGkGWfoAexHofen2h+KVgSHTLi0jkjxhZIlAIGOpHQ/Okdrpel3u
  211 + oRJJazENlg0LFgQOwxk/Stfaz+GrOHybeWGNV+EgRsDn0ORmujwY8VSkHh0k
  212 + 4t3/APS9b3On3kPl20kYHP8AL27CD/y/2r79peE+XOfZZOx9j6Glk0/h6brd
  213 + pn1wRj8q5+0wbSkGqQzof/TmYE/j1/WvTX9nqQj9jTzSHYoDgj4h6GoGvwry
  214 + BZI92DtwwPOeaWzTs04toSwVVBOeck9vcelT/wAEkWM/cywzszz09a83P/IR
  215 + xyonPJCPboam4OyOMMFduM+nrXaTwrGUjcEIcHB5zWeSU2s+04CNxzxhugx7
  216 + 0fxBYoGkCkDvI/wIPqeTXZgzLLHkVjBSVjvzTLKoJC88e3+9LdUuJZbqTTLY
  217 + yJKIw5McgEijPLcdPQDvmsze+Ir1966apAHLTOMbvYDsKg0K1uX1BtTErWk2
  218 + QkqoMK3f8/SsyTt8UcPkSd8Yj2/khtLa+uo7gGFFVpo1fDM2eDuHIPbpz9Kj
  219 + s9Ys9S0+ENa/yVnCMHCMGYj75475xx3qD7THd29y1hCIY9388MBho8Egc5wC
  220 + fl3qC5N3baR/Fba2jt7tCN5GNu1uMbenoa5XfLRxzjxf9IkfQtOluriW4khu
  221 + C80eWQZ8o4OUIHQEAcmoNXsV05/M2NFA5xGCckH5ZqOw1jUNSuDeTyx4hiDT
  222 + KiYDx89scnI70/tJv41bwM9vI0qS7UTG4lseo46H8qnPHHLFrr6JcOUbRmvs
  223 + 9rdQgeaWuiSSuPhI9u9aTRvCSvYIL7EkQZZFRGwp6Ee/51WTSbY6jOl7cIkz
  224 + uTEYsoEI4K7T3Bx165rcaPYNDZEMWYM3KsOMEDkenTp71GOBpq6pCwxq7ZVf
  225 + SNNuykBjJTPmqquQFIPGfXB9azmq2Y0S8S71EtFayboxKhyFOMgMR0zTOXUY
  226 + rPxRDaqx8iRWJPv8/T+9P5ZrKaCSzmCPDICrxkZDAjpXVHI4nouOTErj7R5h
  227 + pmoWuo2et2sKs4MgkQkHlSMZ/Fac6ZdmzVXkt2aCZ1e6mXBETAbSxHXnCn8a
  228 + W654ck8E63He6erHRbzZDNvbcYyTkg98cZB+dSyXcLM9gtz5YEgNwQMgxA5I
  229 + PzHHtVvkuDd7Mh5LlifLtGutNSs763M0F1G8YIBDccdzSO4YWV7IcKDICY3x
  230 + nIxmqwmstP0Wa8sPLexlYRSM7fzFycFlI4OODgio/EGo2F/YwG3uFMwZVjkZ
  231 + Qu5SSBjvj1zUPmluxMPlOE3e0RWuuTfaAsdwTCx2BMY6HPA9Ke+H5LdtVkKt
  232 + M87p5kkshxkNztGPxwemazMfhO9JucXUEi2qhm2MecckD5Yp5b6ncTWifZYW
  233 + iD4/xEhALpjAxx1965vy/aTObK9cr7NppD7Lp1afe4Ysf9KkcUUj0ENcyPu8
  234 + ryVAOWViCTnvkZNFPC6OJ9msor6ww7D3NfKoKfKy+qRhbyeMu6hn3cN2PNai
  235 + kfiC3gkaFpHaJyCNyjqPSpZP1saPZm3gRTtLNtz+NKNT+zhHEagt1AJ4Bp29
  236 + rbIMteSbSP8AL+vtWf1bTrG7YCC7mMgIAyBtOTXK5WikutDe18J77RLx9ctE
  237 + hIBZ44idnHK53Y/EVl7klnIDFkyQMjGQfarUVjJaPJG1wZmzt3jeMjpjDAGu
  238 + Whw3I69M1yZszrhHSQnzT48L0T6Glgl0v2/4baJSVXnlu3TmtaL3R7+4Cx3U
  239 + csznhdrbj+VYpUyvPyrQeGdUtrJJ4ZjFD/X5zDBI9Ca7P43yWprE6p+/Z1eF
  240 + m4y4j86ZB/8ACX8Kim061Cf8CNvmuaXSeNNOuLxbPTvOvZ2PAhTC+5LN2+QN
  241 + NVSRbcz3m3d/8JCSMnoMnkmvo4uMuj2seXl7ErD7PeMyglWwwKD7p+XcVfbX
  242 + Lc8vARKqkBicVNHASgY43Hk46Z9qq3VtGGVizJ8eMqccEVw5v4vHkfIaeCGR
  243 + 7KDHzrhZnDRpw4c+5ruPQbeZc3QLy9dxYkfgelNIbRYyVOSWHU9/+hivisLJ
  244 + xHMcQMcI5/o9j7fpXTh8eGGNDpJKkLZtDhZdpQEdvSvl/Dqa39stnDGsG0Ft
  245 + oB6HnOecAHjHc1oJItsZbggDPPcVmvE2rWltpN7BJPLBM0RRQpKuSemCOtZl
  246 + ikuzjzvXL6F1zd6dqdtb2SedCty25zCmzeM42tjjkisNeWF1ZXTwXMbxpGu4
  247 + 7j94E/COOP7U10zxci28EF3p0UjwQCGGeI7XU9j/ANquWkd9rl3KSZL0MrJ2
  248 + Ynb2we3b61xS2eXJxyK/Yu0S9gg1K2u2EkkrPh0U4Bzxj3xkGvRZrhw4isol
  249 + RUViV+4S2OAPr1rKWfhjVYkW71S2gtbZCBGmFMmM9OOF496cSwK2pG8tGkll
  250 + QbVRvurkcknPI7/nWQk9pofBFvTHelNcasjT6nZ75xKCMgjJAGCAeeP2rSW9
  251 + 3kLGCWVmOcsOD9KxtjPfy6usFxB/h2QjevxBT3wR19K01tGE+KMxuCOo7H9q
  252 + HIuoxlZD4ut9It9GaY25jvIQWimiTGG75Pcf96znhy+tJHE096jPECArPl3k
  253 + PVj2x2Fa271BCn2aZPMd0J8vGeO5Py9axmo6Zd6Zdj+HwWwhcFyjjJiUYyc5
  254 + 5HIP1pX3ZfDm44niff2Pdfubq58N6hZ2MMN0WhZZftDbQARyU9T6ZIry/RU+
  255 + xyNFcy7ILjCXGF3sF6g/Q+lPr7UJpoRE8n8sc46An1P/AFxWduJAjkKOh7VK
  256 + c9ni5c1zuJtYxpdlpckVs0NyhlCCRnyGQ9SynnuR88Gq95avbW0EH2KFIEcS
  257 + KJXzvVQW2ljjsMZ+VItKKXWrRRSKfjYFeT1HPIHXjNPfE2k+XH9uiZkh24ET
  258 + FiS2eDzkAVnJyi2VUnKHM50VtJEM2pXEm6N3/m2BDblyeDnoRyK0rs0OmNK8
  259 + PkxDLRxhgw2fP2GKxOkXyW4dbuG2ubfkTEkjjGfvYOOR0rXrdreG2eO03BYm
  260 + MiEkIR6gt09xRCblF32M5OcbZSt7jXJjGLKznjglbzIm2gq+AQf2opxo2nTy
  261 + apY5nmZUD7vMfI5U4HHGBg4NFPBVFCckjZzjbcSD0Y1HVi+XbeSe5B/Kk+oN
  262 + qgAGnpbMD1MjYI/amk+KsgW7i4itYTLM4SMHBY9KyesXmlXV35hvp5WYcKG2
  263 + qnyBAqLVby6imjg1F3W7kQ+VFbv94c/E2BgAevWsyZo7dwTbeZIGwPh5yOvD
  264 + DP5V5+fO5fjX+BW6Lv8Ag4P/AOHPdXIOd9xJvT6BeB9RVKK4SDUPMLRxSK25
  265 + I3/obORg8kUuf+K6nM7RRzLGGztAxj8gM1Fd2ps1BmiKSP0AYZ+ZxU4xlW9G
  266 + t+x/qWoi+1CW4ZURpME7O5wATVYMvRxketJ4maFkiZWTcgcBs5Oee/0NX4p9
  267 + vDDI/OubIpKT5GE8yhcnI55AHpS2/j8yzuEyclCePxppIA6JJkEc5PTpzSm5
  268 + mKwSMRyVYn8KzE6kmNHRpP8Aw50ZLfRjqkijzrpiEJ7Ip4/ME/QVqx/ipVcZ
  269 + 8lD/AC/9R/zf2rzDQ/Gz28Flpd4iR6fDH5ZZASWPYt7Z5IFaS68aRXut2mla
  270 + PJlN2+W4xw20Z2r7ccn8K+sx5YqKSPX8fPjUEkzYRIoUpxlWxil0irdTSbcG
  271 + NSVz2J7/AKVAlzdandzwfy4UADA7dzf6iD27VcFxp9tvthcRIbdAXUtyM859
  272 + 6sp32dsclO2KPtt3BNHA20xxyKFdvvZx0PqOafiKG/tWUjKOCpB6j2NZjXQZ
  273 + fDGqXQyjlDKnquCCv14FLvD/AIut9UtPKnna21MLtYIcCf3Hv6j8KV5adCzz
  274 + xUuPTHEKXkNvsimd4cf8Mnr8s0g8S3lhq+mSbwEMcZKyOMMrDoPx/Wm99r9p
  275 + pMDFpY3SNF4RgWz6Y715hqepnUr0O6hELFgqDpk9KhkypKjl8ryIJNfZb0XS
  276 + o7lXmllMSEbYnxwZew+Q616X4A0iHSb3ULYXMUsjxpIGVeUHIweccnPvxXn+
  277 + jatbQbbXUcmyTmNkHxRv746g+lXrHx21p4ltb57RY4owYp0tzjzVPUnjtwcf
  278 + nXKmqPOUoKKrs9B8QWn2hGS4mPl8H4BkAjnOO9In0drnymtLuSOK2X4lXIbj
  279 + H4nAx6c0z1TxNpmswRrpdyk7SDdz8JTp94HoeelVobOSKIhJm3nqO1a5L6O2
  280 + E01Y2F1Iu23t449pIJcFgfoKeWaeYqBYgCi7RkEDnpyKx9uih4ZbiAOpGGlm
  281 + cBU7kgVfh1qxk2KLqVE+7lAwwo6ZBpW77LNJJJFzxRYQzaa7mSOHUIEMkZBy
  282 + SAPiVSOcEV5zHqt4qSJ9pdklTYdxz8Ptnp0rd3N3ZQ2dw6yLLvU7mPxALjkn
  283 + 6dq81Z1DkoCqE5UHqB2FcXlNppxPO8l/lpn28md9kYJCjBZ2P5VWjlRW+CMu
  284 + /LNI4yM+w7VDfTfzVDZwV6+lcxLtt1IKCSQ9Ce1avzinI4utIu2ZYX0CxAea
  285 + ZAqjoQSa9SZP4jpzw6osRQw7D8OAvoTg49+PSvLLRfK1C2aaXYFcEyEZAAre
  286 + XmorLpJheZIw/KoVwXwQeT+lWx8Urs6vHVY22ZnRbi1gvjayws8ckiodv9RB
  287 + 4AHTnA61tbVlEDLLM8QJAOzGY8f0n3rMEWPlbnmYuBhQoywHcbvT589auR+J
  288 + ZoH+C3iZMYCycn8RU/lhFU2ZySR6b4ehiWWAxxhR5ec7cE8dTRS3wHq95q1z
  289 + MZrNY4YouJVJwWyOOfaiumElKNokaTU1xcq3qtLp5lgiaRlZsdFQZZj6AdzT
  290 + fVU/lxv6Ej8aV/rTgYLWfFk8N5NHa2X2GdgFeaVf5xHb5fnWaeZ7mVppZWkl
  291 + c5Z2OST6k16drOg2etIn2jekicLImM49DnqKx2q+EodLKSLJcTo3BwhXn5jN
  292 + QlyW2TlCTYgGCcMK4kiik+GRQc9Dmp3l0/LIJmjK9RJ1B+dV5giopc4RzhW7
  293 + GpPIn6M+KS6LOoyxXmlWdusIS5tmYCVcAuCeAfcVTt2kI2yxsko+8jKR9R7V
  294 + 3ItxaTiOYMkg5VvXH70xlvpddvIIfMggdRmVSNqv1w2T3z8gM0mTGssf7Gjb
  295 + dPsjiXzIJUHOVzjvkc0p1CGWS3nWFGdhG2FUZPA5P608+y3Gn3ixzwtHIpDA
  296 + P0I9fl8qz3i0tY7beNyrM+8Mp529QfzFcOPG/lUWM9GSYEHkEGrOn3UljfQ3
  297 + UYzJC+4D/MO4/DNTR3ySaa1nLYQyShi63C5EvuDzgj6VTRgHG1ufQj9q9i2u
  298 + jE2naNVfeNJP5bWCsshJ3mQdB0wMGs8uqXg16PUHDSzq4YoQeR3GKt21gsjx
  299 + O24RSZxsOCvqcn0OKtzlkyFMk0h5duWZj6k0S8p+tsu82Se2zQa/4jWfRDbW
  300 + 0ZMU6qJDIuNqnnGPXjmsLNdBASu1c+gxXUt15oIJxjtnrVM4d8vwvqaxyeSX
  301 + KYmXLLJK2dwqsxLyMcc8dM4GaIo2YghGIGM4XNfVUShmVSzL/SP6RWg0PTY5
  302 + La5lmaOQFGR4GGHHGcofX1p+L7CMHJoTJaSEEojMBg4wc13c20cKKDIpkC42
  303 + 5HzOT7+lPJ9IhtVVorRvLkRv6ySg28/maWali1dIk+48YYOx+IH9/rUZRmp9
  304 + mTg49kvhTXLXR9azqEX8mRfL3Af8I5+9jvWz1rxPoh0txZXn2m6mUpFHHlSr
  305 + EEBjnGOa81ad3XLS5Xp90cflUBXy3DByCCCOelWTQ0MriqR+idA0vzNIgjuc
  306 + O6LhmbnJAxzWT1i4svC2qzWkkZuE2hoxCQxyc5Df5ewrJwf+JWu2caJGLcuM
  307 + 5eRC27I9Cce9K9W1ufXr37bcxQR3J4drdNm/0JHqOmayT0Wn5DfRb1LWZ9Su
  308 + cBTBDnCxKevPf1qJpMnPA9qjtbq53f8AEZtgOcnt9amS4cNuZInB9Y1/tXBk
  309 + dvZzSdu2U7mHzimWHBy3yr6paSVG2MEUgBiKYRSrvBNuhOc8ZH6HpUheO5lU
  310 + CBUKjBVDu5z+9Cm+LVCcf7OYm+NQmGYcg9hVtBlgDyxHQVcttAu5pCkNtPnY
  311 + HKlArY+pxjPpUt3ptzpsSG5heCN225KcE/PnNS+KTX9Gq+ikV29evtTC102W
  312 + SMSMqqp7McE+9W7HS4ZSJFmBPbctPYtMKqC90uM8gDqKtjw07ZVR9s2Xge2a
  313 + 30QbsZZiRgdBnNFONHjEemx7RgNyB7dqK9FKkITXyeZaSDuBuH0pHWkYBlIP
  314 + QjFZyRDHIyHqpxWgc0p120FxaF5mkeBCC0KMQCPU464ptVLVA38PkKEBgQQD
  315 + 356Uk1aZq7MVJbaTGCsUTxn1Tg0j8RWsUenwvG855yBI5OAfyxWpmkuTnFvG
  316 + aT6uWn06aGWFvNbaEbdkDnpXLqqKyX4sztrq0m4/aIlnyuwlvTtx/bFXLI77
  317 + pFtQYy+Fd5E3BR3wBz74qWw0FJI0d51jjZiqsQTlh1Geg7U30WO4sbK5luJo
  318 + IrHfguluzPC6kYYvx36YJ9xzQoS7ILk9sd2um2UNr5K3GrXoJ3Yki3KD6qGX
  319 + C/Q1mPEOivqUjxvZzbkXEWFBcAeuCcda1djJq+rWD3lzOEgdSIIIcRmQZxvZ
  320 + zkqD1wO1KryCTSLcS6fd3InlI3ToqLEcclVQj7o5PAxz1yapONrkx1vR5Fd2
  321 + 0lrKySqykNgZBGaplS5H3j645r0u8kbUTLPcQLKWx5hePCk89MDH71kboTJk
  322 + RxwwEEg+Uo6jtu/7UmPLOtxM+OiOyaaR7XTLeV1MjYLOvKg8nH0Ga9WsPD2n
  323 + jSFto0Mibif5oG5s9z715La6deOgvreQRNGSBLJKEywHIUnqcHpWrtf/ABBZ
  324 + LTZeWOZcYDRtgH35HFU4rsrCUV2UPFPhqLTbhpLZtqsf+GecfKs0UMgCiEyA
  325 + cEpzg1e1TW7rVrvMkoDHgAdAPmaBdJBbCK3iDt/UQOT+1TdxZzzavQt2NGG8
  326 + oshb7y+tW7HVbywE32Jgkk8ex3I5HuD2NQu87sS0RI9MV3FDuIyg3enpT/LJ
  327 + IFJokttV1SCe5k8wO9wmyR5RuJFUirvITO3J+EZ6+1MWijVFVwIyRlTnr71S
  328 + Y+VKdwUopwxLZ59K3nKTprYXJ6ZL9jJtuFUYbOQRkVE9ihKtv5P3gMcVZiuV
  329 + OCxCqOuB39atwWcN9cpbwyiOaQ4QN0Y/tUuUovYJehRJEpGZHGQMA19iQwuB
  330 + klWHBIxVuLS5biZ4kJd0PxqFO5ee4q7qmiSWE8fkXMdxuQscIfhA755AFXSc
  331 + o6GUW1YW0R+yvJ/mYLn2HP7ipAoHU5qe2sriSyijgMUkmPM27wMbu3z4/Olk
  332 + iak888DwyxNAMyjbtCD1J/6zXBFc5NJmPQ0tbdrqfyY3jRwuTvfbxWg0yyj0
  333 + +VjqFsz2xPxyQurEe5AO4Dvkc1nvDniGPRwyGKaQMfvxygMPoykGvR7fV9Mu
  334 + o4kkuYbuWRQyoyIWAI6HsK6ceKC7ZiJVmcrCftCSnP8AhL3Pwvn/ANOTHQnp
  335 + 79eCMUt8V3C3dnYlEJfe++BhypGAQfcHirOtaMEsJbrSlEE6ruaOPhJlHUFe
  336 + hOOlJtSMmoeHdPu7hFS9uJCQ6ZXKKMA49SMfgKq206Y8eyWyVNoZrKQcZyoN
  337 + NoPKlmRI7SfccBQzNtz+lKNPj1FI1VLkEYx8XP7VpvDtvqNzrVtFcXAMSNvf
  338 + GPiA59PlSJbKt6PSII/KgSP/ACqBRUlFdREKS6nHsut4HDjP1p1VLUovMtSw
  339 + HKHP070AJagvI0ltJVkzt2k8HBGOQanqC8OLKc/6DWPoEY6W2umORcvgjnk/
  340 + 3pPqNtJIPjlJx0Nad24xik2pA4OK42dA20+GG48F20iARvAjDK8fFnBPuT1r
  341 + Py2DapqZU+YLcSrvt8MnxYzgA9SR6+oxWk8FSb9InibB8q5bGfcA06isIIZT
  342 + KFLSFiwZuSMiuqrRNSq0SRRRwwRxRLtjRQqr6ADAFU9S02C/Xe4bzkX+W4OS
  343 + PoeD9avmuTW0Iecz2V7GjPPJNELeR4hHuOwttyp29OCfr9aQXunxPbESK0kp
  344 + X4pAQNxz1P0zXqmq2yyaVeoigNIhc47sBnP5V5VqNxJFC7/dBGNyjJB+VRya
  345 + ZRO0xa99bwaPLYl4VkEoKqsALP65fsB6VTltEuC7wzyGJRks8O0j54J/KtN4
  346 + O0KTV5biSad1tlwsyj70meg9unWtBr+l2/nfZrUR27BEKAfCOmOv0rYxbViQ
  347 + jzls8oOJTiJmKgYyRivqvPGgUYCjuBmrV6GN5KY8CINgADGT3P618CfAA64b
  348 + 1xxj1odPQlJumVQJ7hgkcjEk8AGmKWcsFzCxL7wuVx146n86saaFs70z7Qy7
  349 + CoOO56Grdje+bqrSsOCoCA9sHn8f2pJqT/X0JNNPRNHFeyLtiVmyON3ApJq2
  350 + nTrqUEGNzygAdBl+/wAu1OF1O6ikliWSTy1dvhViMAnoDU7xLeW6tFIEETCQ
  351 + OPvg+5PSkx1CW0EWk9kQ8OQyWUYjaS3vGUb1m5B7cYyOvSqFtpUkG6WSWPfa
  352 + zmJowcknI/DrWq0+/i+zQJMRLcBiXaXOW+R+ePwqjDfQ3Ud0r2JgltFJ2E5J
  353 + AJz27YrpmouLqmdcowq0c2mpONZiVZfKebb9p3oPTlgT6/kc+tT67qf2Tw+s
  354 + ljcQMsrPHJHIgJyeMrg+n45zSDxDbix1dTF5p3wrIPNbcTn27ZHaq6RRypse
  355 + MhW5AxnY3sfT1FJz+HXdE/lcbiUdNa+ieSSxLho0LvsGfhHUkelWbvWL7Uni
  356 + e8kEoT4em3cOuDjr7Vs/CFnpltMLvdKt6FaFrcfEJM+gxnt64rTWvhrS0eaZ
  357 + tOhVrgfzYc7kHORgdj7ilUFN8l2R2eX280EsCJcRrHGhKnyYVBJ9SSe/5ela
  358 + 7w5bWWoI+mrDHBGfjVlkLS7h3zjBHtWquPD+lXSyh7KIGV1kZkG0lh0PH/Rp
  359 + VN4OEF0LnS7kxENuEch4XnPBH70Sxv3sKaHGlaG2mkhdRuJIjn+UwAXJGKVe
  360 + JAkV7ZWsahY4YPhUdhnH7VpbI3RgUXiRiUcExtkN7+1ZXxG+7xKI/SBP1NO0
  361 + ow0isOyxZECNWFbjwdbFnubxgccRrn8T+1YC2mCRkBc4FeuaLZmx0m3hYYfb
  362 + uf8A5jyaXEt2PN6L9FFFdBIK+MAykEZBGDX2igDNzxmCZ4z/AEn8qp33Nhcf
  363 + /TP6U81aDhZ1HT4W/aktyN1rMPVGH5Vj6Ax7TygkEjr1xSzUpJJUIDbcHt3p
  364 + kxR03A9BxSm7c5I61xnQx74EY/ZNQUnkTqf/ANa1ZrI+BnDDU1A6SRn8jWtN
  365 + dUf1RCXYGuDXRrk0xhHJgqQ3Q8dOua8mubIzXJEn/CjJAT1Pqa9aJrz3VYhD
  366 + qdynTErEfr+9RzLSHgr0X/BCbLfUOn/FQf8A6muPFyhbu1kbgFCMnjv/AL11
  367 + 4NkENvfq27HmqchScfD3xUHieBJWgkja3lJY52oc9uvJrJSqBj1Iwd9Gv24k
  368 + bWQnjHAA9a+yRqMrERtQKPqRz8qaXVi0w4RVjzy+No/Oq2VnllRcKjEbWXpn
  369 + j8uK5YZFOdIndMoqkqqCDjAyRVmNwx6A/Lgip/IchgchxwwHao57bylVsHqB
  370 + x2J9K9SMVVlLPvwZLEda5MgR8pwehI7j3qRI5jGCpWRD0PFVZWnhPNpI/uoP
  371 + 9qGk9NGNJ9l62kaKRpVwdq55HpXemRx3PiCO9kjLN5obykBOSOfrXOjxXL+b
  372 + PPFsjYbNjDtTvQbNbfWU2/dwzKT8ulTnF1S6N1xoy8ltNqL3WqsjlGmw0jnA
  373 + 3HsPkKkt9qPsUbhwSScAD962PiuNItEit4UVFMmFVRgdDWRtF8xkgJxskG7v
  374 + wO+K4c8HH2Rao3Vnpa21rBcQxpmWNRcI/Ru4Jx0x69vxp1aTI6eXlxIo5SRs
  375 + sB657j3r7bjEEY+EfCPu5x07Z5r79liLq23G05AHGD6j0+nWuuEOKVDk9drX
  376 + ArtaqaSrWI8QZ/8ANTEDIEcYP4VtxWN1kbvEtwfRE/8A61PJ+o0Oxt4UsF1T
  377 + W0UofKgIkfI9Og+pxXq1Zzwdpn2HSBcOuJrrEhz1C/0j9/rWjrcapBJ2wooo
  378 + pxQooooA4ljWWNkYfCwwazU0TRStE/UHHzrUUs1a0DoLlF+NBhvdaAPMkj2I
  379 + 2TjBwaW3K/zCexFMr1GjvblMkKsjcfWl1yTkY6dK4/Z0ehr4IAEmqY7vH+jV
  380 + rc1kvBP3tTPrJH+hrWGumH6ojLsDXJozXw+1MKcmsR4hj/8AbMuOM4P5CtnL
  381 + NHCpaR1RR3Y1jtcniub7zYW3LgDOMc496ll6Hh2TeD+P4ivfzEP5GrPiZBJb
  382 + 2xc/CshyT6YrO6bqF3ZXNzHbbcyhSSVz0z/epLyW+uXU3bkpnAyRx+FJOV4+
  383 + K9mtO7KVw/nbnGREhAz7ZqiFjVxJGMZkIX6k/wB6cTxobcxp93HHvVL7IGsn
  384 + QfNT6HAIquPx4xSSF4ld7ZmIKSOrx8gp3HpVuwmaWUDU7aGSBPvKhKmQY4wR
  385 + kDnFcRRGWMkDD4wyg8g1KLeYH7owe9dFejHFNFtxZ4IgjCkgt5fHxHvg1Xt7
  386 + mKSQyWwBUfCyg4ZPYr1FfXsrl1GAQwIZSO3/AF+9cX2kK0ivIpSXaNskbbWx
  387 + 7GnTYUi87JcR5CEZ79aqvP8AZCnxgMrAg+lS2kL20BEshuD2LyFSPnjrVd18
  388 + ssNwCuMFQvbOetLk5PSRkaRa8S3Qns7Bh/UWY/MACqtpo6ahcIgkaEkDc6AZ
  389 + OOe9VL2VpZLRCxKjP0JNOtPnEEwZeOvNcWVJzplONxo1MKOiAPJvIGM7QKmF
  390 + J11GTswPzArsalIDg7f/AMarzQnFjeu1NKRqUn+RSK7XVcY3Rcexo5oOLG4p
  391 + HaaS+seO5ISD5CKkkx/0hRx9elXY9Vt2OG3p8xkflW10XSo9PSWcr/iLkq0p
  392 + PbAwF+n6k1rqQLQ0UBQAAAB0Ar7RRTGBRRRQAUUUUAFfCARgjIr7RQB5p4r0
  393 + 99O1SZyv+GuRujbHQ4AIrMzcgH2r2PVtMh1bT5LSbgMMqw6o3YivINRsrjTr
  394 + p7W5XbJGcH0I7EexrmyRp2Wi7VFrwvf2thHfmdyGaRCFAyTwaZv4k3HENtj3
  395 + kb9hWLimEc0o75BxTKGQMoOcZplNqJjjbHUmrXcuP5wQZ5CDFQSXUkn35HY+
  396 + 7GqYJ4ye3UUF8Zx1+dJybNpEhlxnIAqhcu7PuOCAQanL5PIqCXLE8dqxmooJ
  397 + GVujPvxxjaOlSSuzjkmu3iODgmoirUICNbgvI4Q5SNeT23H/AG/WrkW14Qw6
  398 + kheD3B4/Hp+FVlwgZSNoAOe1RW8/lYEn3JEByfcf9f8AQrsjL2Y0N7eCMsrA
  399 + hXJ4Yn73saZyzWtvbq8pQL/qGAf/ALvu/nWdkla3ySWKc4frj/m/v+lfftpw
  400 + WSTCN0KnIJ9Kqpk3D6HDaraENsKY9mzVAanBPExVQxQ9TyM+g+g/OqkrB9hk
  401 + hhfAwWZRx+XNQyS5JAAXHAG3H4Ctc7Rih9nFzqSxqvmBhG3SVQduPfuKrpeW
  402 + 78/akYexz+lRyyPb3LKOVYB2UDpk4yPwqzA1rnzEeEe4wCP3pHNspxomh+PB
  403 + KYU/d3dcVfjGzjH4VHEhY5weatxpx93pXFJ2zTuN8EZNWVbPaoo0JHYVIqsM
  404 + c/P2rAOwd3ORQQf+1GzByG4NMtI0d9VvRbqWCdZHH9I/v6VvZljLwhopvLv7
  405 + fcR/yIW/lg/1P/YfrXoFRW1vFaW8cEKhY412qKlroiqRNuwooorTAooooAKK
  406 + KKACiiigApB4o8OprlkDGQl5ECYn9f8ASfY/lT+isaTVM1Oj89pbvFq09vcx
  407 + NHLGdrIw5BpvHHkAFRx3r03xF4ai1YC5hCpeIuMnpIPQ/wB68+lt3gkaKWMp
  408 + Ipwyngg1zSg4lVKyq+UOAnOK+/F0IqRsgnAJ6d6+kYyTgcVhpEyAd6iYZxgG
  409 + rBOcgkdM1Eyg457+ta0ZZV+IgcYqEbiMZHftVpo88deTUDIoY5Hf0oApXMKu
  410 + w3sxXoQGxmorpgPK2/f5wPYDNXbiMGM5Ax3pf/h7aQlsq/TJyTj2qsHao1Ek
  411 + Vw3l/wApQwGMoDyvyPce3/aomigmcmN/Kl7hCUf6r3/CqeWQr95d2SvZhz7+
  412 + vHBqwsomVvNjWdV4yByvzB5H0qqYNFgQXATH2vI7b4lbH4YqHyrzJBuoV7F/
  413 + KJP5muQLUHAknjB5xuf9DXErwnrfSnv9/wD2reQUBgSJHDO0k0uF3OeW+Q9B
  414 + 1qzZBpAvwIzDjeQM1VhCbt0cbAkYMr5yfx5NN9NtDs3kYycj2FTm/YN6LkEJ
  415 + xzVoIg5JFfUh24461OIhkY+VRFIxhQQqliOldKJSc7V2nsetShQVyM8VZsLW
  416 + TULpba3G+RvwUep9BRQH2ysp7+dLeCIF29+AO5PtXo+l6ZDpdmsEXLdXcjlz
  417 + 61Ho+kQ6TbbE+KV+ZJMdT/amVWjGibdhRRRTmBRRRQAUUUUAFFFFABRRRQAU
  418 + UUUAFKNa0GDVo92fLuVGFkA/I+opvRWNWB5Rf6dcWFw0NzGVcDIOeGHqD3qq
  419 + 0Y5Bz3r1e+sLbUbdoLmMOp6HoVPqD2NYfVvCl1YbpbcNcQDuBl1HuO/zFSlC
  420 + iikZsRKuOV6cn1oKAfeOK+tBKAojVhj/AEgYrowylQDG3TrnFTNISqkt944P
  421 + p61C4QykAMSwHQVbMErMT5Z577sV8ktZDgso445NAFWSJSjfB9Mil1zC4IKA
  422 + AkA53dac+VtPKp/+WKPswZQPg49/WmX9AZOZWlxHLsUBgTzyapF9kjRsQxHC
  423 + knBx7N+xrXXOkw3OQ+3PsKqDw5GxGLiUgdB5ef2qin9jKSESzunWadAOgZM/
  424 + n/vUivJKuRcMSfSP9zT1fDmDnzZQPZMfvViLQ7dCGkSZ/TeRj8M0PIFoU2Vi
  425 + 85yd2OzNyTT6G3ZQMZwOlTKscIGyIEccbufwoW5VwDGkfX+pjU3K+xT6IOCu
  426 + CRnIyehqRVOOenuelEbyO4VUjUngYUtn6VqdI8K3M5WbUSIo+vlKuHb5nt+v
  427 + yrUr6MboUaXpFzqk+2IYQffkP3V/39q3ul6TbaVb+VbryfvuerH/AK7Vbhgj
  428 + t4liiRUReiqOKkqsYpCN2FFFFMYFFFFABRRRQAUUUUAFFFFABRRRQAUUUUAF
  429 + FFFABRRRQAp1Lw/Z6iC2DDMf/UjwD9R0NZPUvDWp23Mam4jH9UR+L6j+2a9C
  430 + opXFM1Ojx+SFhIQ24FeCDkH8K62oDx9a9UutPs70YubaOX3ZeR9etJLnwZp0
  431 + uTBJNAfQHcPz5/Ok+NjcjC5RR8KDHyroSqCMKBk+laSfwPcAHybyJh/rUr+m
  432 + aUv4fuLJSGaEhfiOGY9fmKWmjbKfmlRXJuGBOQMdjVl7KVkwDGPnmrUHh27u
  433 + Nu1rfJxnLsBz9KygFTyP97IJx24qNVDbXb4Succ/jWvh8DyEAzXiL67EJ/U0
  434 + ztfB2lwAeYJZ/Z2wPwFbwkw5IwCxvcSiKFHeXH3EXLVoNN8HXtx8d0RbITkg
  435 + 8v8Ah2+tbm3tLe0TZbwRxL6IoFT06x/YrkLtO0Wx0wAwRDzMYMjcsfr2+lMa
  436 + KKpVChRRRQAUUUUAFFFFABRRRQAUUUUAf//Z
  437 +
... ...
vendor/rails/activerecord/test/fixtures/book.rb 0 → 100644
... ... @@ -0,0 +1,4 @@
  1 +class Book < ActiveRecord::Base
  2 + has_many :citations, :foreign_key => 'book1_id'
  3 + has_many :references, :through => :citations, :source => :reference_of, :uniq => true
  4 +end
... ...
vendor/rails/activerecord/test/fixtures/books.yml 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +awdr:
  2 + id: 1
  3 + name: "Agile Web Development with Rails"
  4 +
  5 +rfr:
  6 + id: 2
  7 + name: "Ruby for Rails"
... ...
vendor/rails/activerecord/test/fixtures/citation.rb 0 → 100644
... ... @@ -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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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 &lt; 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
... ...