From b9846d60741788e84c889077d9b3b4786ba31042 Mon Sep 17 00:00:00 2001 From: AntonioTerceiro Date: Mon, 17 Dec 2007 19:37:14 +0000 Subject: [PATCH] ActionItem135: upgrading to rails 1.2.6; all tests pass --- vendor/rails/actionmailer/CHANGELOG | 14 ++++++++++++++ vendor/rails/actionmailer/Rakefile | 2 +- vendor/rails/actionmailer/lib/action_mailer/version.rb | 2 +- vendor/rails/actionpack/CHANGELOG | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- vendor/rails/actionpack/Rakefile | 2 +- vendor/rails/actionpack/examples/address_book_controller.cgi | 2 ++ vendor/rails/actionpack/examples/address_book_controller.fcgi | 2 ++ vendor/rails/actionpack/examples/address_book_controller.rbx | 2 ++ vendor/rails/actionpack/examples/benchmark_with_ar.fcgi | 2 ++ vendor/rails/actionpack/examples/blog_controller.cgi | 2 ++ vendor/rails/actionpack/examples/debate_controller.cgi | 2 ++ vendor/rails/actionpack/lib/action_controller/assertions/dom_assertions.rb | 4 ++-- vendor/rails/actionpack/lib/action_controller/assertions/model_assertions.rb | 2 +- vendor/rails/actionpack/lib/action_controller/assertions/response_assertions.rb | 3 +++ vendor/rails/actionpack/lib/action_controller/assertions/routing_assertions.rb | 1 + vendor/rails/actionpack/lib/action_controller/assertions/selector_assertions.rb | 2 ++ vendor/rails/actionpack/lib/action_controller/base.rb | 8 +++++++- vendor/rails/actionpack/lib/action_controller/caching.rb | 77 +++++++++++++++++++++++++++++++++++++++-------------------------------------- vendor/rails/actionpack/lib/action_controller/cgi_ext/pstore_performance_fix.rb | 30 ++++++++++++++++++++++++++++++ vendor/rails/actionpack/lib/action_controller/cgi_ext/raw_post_data_fix.rb | 2 +- vendor/rails/actionpack/lib/action_controller/cgi_process.rb | 19 ++++++++++++++++--- vendor/rails/actionpack/lib/action_controller/cookies.rb | 13 +++++++++---- vendor/rails/actionpack/lib/action_controller/filters.rb | 253 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------------------------------------------------------- vendor/rails/actionpack/lib/action_controller/integration.rb | 52 +++++++++++++++++++++++++++++++--------------------- vendor/rails/actionpack/lib/action_controller/macros/in_place_editing.rb | 2 +- vendor/rails/actionpack/lib/action_controller/pagination.rb | 8 +++++++- vendor/rails/actionpack/lib/action_controller/resources.rb | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------- vendor/rails/actionpack/lib/action_controller/routing.rb | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------- vendor/rails/actionpack/lib/action_controller/session/drb_server.rb | 2 ++ vendor/rails/actionpack/lib/action_controller/test_process.rb | 7 +++++-- vendor/rails/actionpack/lib/action_controller/url_rewriter.rb | 5 ++++- vendor/rails/actionpack/lib/action_controller/verification.rb | 1 + vendor/rails/actionpack/lib/action_pack/version.rb | 2 +- vendor/rails/actionpack/lib/action_view/base.rb | 44 +++++++++++++++++++++++++------------------- vendor/rails/actionpack/lib/action_view/compiled_templates.rb | 4 ++-- vendor/rails/actionpack/lib/action_view/helpers/active_record_helper.rb | 36 ++++++++++++++++++------------------ vendor/rails/actionpack/lib/action_view/helpers/debug_helper.rb | 10 ++++++++++ vendor/rails/actionpack/lib/action_view/helpers/deprecated_helper.rb | 3 +++ vendor/rails/actionpack/lib/action_view/helpers/prototype_helper.rb | 50 +++++++++++++++++++++++++++++++++----------------- vendor/rails/actionpack/test/activerecord/pagination_test.rb | 9 +++++++++ vendor/rails/actionpack/test/controller/action_pack_assertions_test.rb | 13 +++++++++++++ vendor/rails/actionpack/test/controller/addresses_render_test.rb | 5 ++++- vendor/rails/actionpack/test/controller/base_test.rb | 2 +- vendor/rails/actionpack/test/controller/caching_test.rb | 5 +++-- vendor/rails/actionpack/test/controller/cookie_test.rb | 21 ++++++++++++++++++++- vendor/rails/actionpack/test/controller/deprecation/deprecated_base_methods_test.rb | 18 ++++++++++++++++++ vendor/rails/actionpack/test/controller/filter_params_test.rb | 1 + vendor/rails/actionpack/test/controller/filters_test.rb | 175 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------- vendor/rails/actionpack/test/controller/integration_test.rb | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- vendor/rails/actionpack/test/controller/resources_test.rb | 251 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------ vendor/rails/actionpack/test/controller/routing_test.rb | 4 ++-- vendor/rails/actionpack/test/controller/session_fixation_test.rb | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/rails/actionpack/test/controller/test_test.rb | 16 ++++++++++++++++ vendor/rails/actionpack/test/controller/url_rewriter_test.rb | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------- vendor/rails/actionpack/test/controller/verification_test.rb | 15 +++++++++++++++ vendor/rails/actionpack/test/fixtures/test/hello_world.rxml | 3 ++- vendor/rails/actionpack/test/template/asset_tag_helper_test.rb | 5 +++++ vendor/rails/actionpack/test/template/compiled_templates_test.rb | 46 +++++++++++++++++++++++++++++----------------- vendor/rails/actionpack/test/template/javascript_helper_test.rb | 8 ++++---- vendor/rails/actionpack/test/template/number_helper_test.rb | 2 +- vendor/rails/actionpack/test/template/prototype_helper_test.rb | 26 +++++++++++++------------- vendor/rails/actionwebservice/CHANGELOG | 21 +++++++++++++++++++++ vendor/rails/actionwebservice/Rakefile | 4 ++-- vendor/rails/actionwebservice/lib/action_web_service/version.rb | 2 +- vendor/rails/activerecord/CHANGELOG | 43 +++++++++++++++++++++++++++++++++++++++++++ vendor/rails/activerecord/Rakefile | 2 +- vendor/rails/activerecord/lib/active_record/acts/list.rb | 16 ++++++++++++++-- vendor/rails/activerecord/lib/active_record/acts/tree.rb | 7 +++++++ vendor/rails/activerecord/lib/active_record/associations.rb | 59 +++++++++++++++++++++++++++++++++++++++++------------------ vendor/rails/activerecord/lib/active_record/associations/association_collection.rb | 6 +++++- vendor/rails/activerecord/lib/active_record/associations/has_many_association.rb | 4 ++-- vendor/rails/activerecord/lib/active_record/associations/has_many_through_association.rb | 34 +++++++++++++++++++++++++--------- vendor/rails/activerecord/lib/active_record/base.rb | 15 ++++++++++++--- vendor/rails/activerecord/lib/active_record/calculations.rb | 4 ++-- vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb | 2 +- vendor/rails/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb | 2 +- vendor/rails/activerecord/lib/active_record/connection_adapters/oracle_adapter.rb | 1 + vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb | 4 ++-- vendor/rails/activerecord/lib/active_record/deprecated_finders.rb | 6 +++--- vendor/rails/activerecord/lib/active_record/fixtures.rb | 2 +- vendor/rails/activerecord/lib/active_record/timestamp.rb | 9 --------- vendor/rails/activerecord/lib/active_record/vendor/mysql.rb | 2 +- vendor/rails/activerecord/lib/active_record/version.rb | 2 +- vendor/rails/activerecord/test/aggregations_test.rb | 18 ++++++++++++++++++ vendor/rails/activerecord/test/associations/eager_test.rb | 13 +++++++++++++ vendor/rails/activerecord/test/associations/join_model_test.rb | 31 ++++++++++++++++++++++++++++--- vendor/rails/activerecord/test/associations_test.rb | 114 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- vendor/rails/activerecord/test/base_test.rb | 21 +++++++++++++++++---- vendor/rails/activerecord/test/fixtures/author.rb | 1 + vendor/rails/activerecord/test/fixtures/binaries.yml | 437 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/rails/activerecord/test/fixtures/book.rb | 4 ++++ vendor/rails/activerecord/test/fixtures/books.yml | 7 +++++++ vendor/rails/activerecord/test/fixtures/citation.rb | 6 ++++++ vendor/rails/activerecord/test/fixtures/db_definitions/schema.rb | 14 ++++++++++++++ vendor/rails/activerecord/test/fixtures/developer.rb | 10 ++++++++++ vendor/rails/activerecord/test/fixtures_test.rb | 14 +++++++++----- vendor/rails/activerecord/test/migration_test.rb | 19 +++++++++---------- vendor/rails/activerecord/test/mixin_test.rb | 47 +++++++++++++++++++++++++++++++++++++++++++++++ vendor/rails/activerecord/test/validations_test.rb | 4 ++-- vendor/rails/activesupport/CHANGELOG | 16 ++++++++++++++++ vendor/rails/activesupport/lib/active_support/core_ext/blank.rb | 12 +++++++++--- vendor/rails/activesupport/lib/active_support/core_ext/hash/conversions.rb | 51 ++++++++++++++++++++++++++++++++++++++++++++++++--- vendor/rails/activesupport/lib/active_support/core_ext/module/introspection.rb | 14 ++++++++++++++ vendor/rails/activesupport/lib/active_support/dependencies.rb | 6 +++--- vendor/rails/activesupport/lib/active_support/json/encoders/core.rb | 8 +++++--- vendor/rails/activesupport/lib/active_support/multibyte/chars.rb | 12 ++++++------ vendor/rails/activesupport/lib/active_support/version.rb | 2 +- vendor/rails/activesupport/test/core_ext/hash_ext_test.rb | 37 +++++++++++++++++++++++++++++++++++++ vendor/rails/activesupport/test/core_ext/module_test.rb | 8 ++++++++ vendor/rails/activesupport/test/dependencies_test.rb | 11 +++++++++++ vendor/rails/activesupport/test/json_test.rb | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ vendor/rails/railties/CHANGELOG | 32 +++++++++++++++++++++++++++++++- vendor/rails/railties/README | 35 ++++++++++++++++++++++++++++++++--- vendor/rails/railties/Rakefile | 20 +++++++++++--------- vendor/rails/railties/dispatches/dispatch.fcgi | 2 ++ vendor/rails/railties/dispatches/dispatch.rb | 2 ++ vendor/rails/railties/environments/boot.rb | 30 ++++++++++++------------------ vendor/rails/railties/environments/environment.rb | 30 +++++++++++++++--------------- vendor/rails/railties/lib/commands/servers/webrick.rb | 4 ++-- vendor/rails/railties/lib/dispatcher.rb | 3 +-- vendor/rails/railties/lib/initializer.rb | 42 +++++++++++++++++++++++++++++++++--------- vendor/rails/railties/lib/rails/version.rb | 2 +- vendor/rails/railties/lib/rails_generator/generators/components/scaffold/scaffold_generator.rb | 2 +- vendor/rails/railties/lib/rails_generator/generators/components/scaffold_resource/scaffold_resource_generator.rb | 1 + vendor/rails/railties/lib/railties_path.rb | 2 +- vendor/rails/railties/lib/tasks/framework.rake | 8 ++++---- vendor/rails/railties/lib/tasks/routes.rake | 17 +++++++++++++++++ 127 files changed, 2801 insertions(+), 565 deletions(-) create mode 100644 vendor/rails/actionpack/lib/action_controller/cgi_ext/pstore_performance_fix.rb create mode 100644 vendor/rails/actionpack/test/controller/session_fixation_test.rb create mode 100644 vendor/rails/activerecord/test/fixtures/binaries.yml create mode 100644 vendor/rails/activerecord/test/fixtures/book.rb create mode 100644 vendor/rails/activerecord/test/fixtures/books.yml create mode 100644 vendor/rails/activerecord/test/fixtures/citation.rb create mode 100644 vendor/rails/activesupport/test/json_test.rb create mode 100644 vendor/rails/railties/lib/tasks/routes.rake diff --git a/vendor/rails/actionmailer/CHANGELOG b/vendor/rails/actionmailer/CHANGELOG index 968f621..b421aaf 100644 --- a/vendor/rails/actionmailer/CHANGELOG +++ b/vendor/rails/actionmailer/CHANGELOG @@ -1,3 +1,17 @@ +*1.3.6* (October 12th, 2007) + +* Depend on Action Pack 1.13.6 + +*1.3.5* (October 12th, 2007) + +* Depend on Action Pack 1.13.5 + + +*1.3.4* (October 4th, 2007) + +* Depend on Action Pack 1.13.4 + + *1.3.3* (March 12th, 2007) * Depend on Action Pack 1.13.3 diff --git a/vendor/rails/actionmailer/Rakefile b/vendor/rails/actionmailer/Rakefile index aac65b2..db7841c 100755 --- a/vendor/rails/actionmailer/Rakefile +++ b/vendor/rails/actionmailer/Rakefile @@ -54,7 +54,7 @@ spec = Gem::Specification.new do |s| s.rubyforge_project = "actionmailer" s.homepage = "http://www.rubyonrails.org" - s.add_dependency('actionpack', '= 1.13.3' + PKG_BUILD) + s.add_dependency('actionpack', '= 1.13.6' + PKG_BUILD) s.has_rdoc = true s.requirements << 'none' diff --git a/vendor/rails/actionmailer/lib/action_mailer/version.rb b/vendor/rails/actionmailer/lib/action_mailer/version.rb index 03f075f..9858903 100644 --- a/vendor/rails/actionmailer/lib/action_mailer/version.rb +++ b/vendor/rails/actionmailer/lib/action_mailer/version.rb @@ -2,7 +2,7 @@ module ActionMailer module VERSION #:nodoc: MAJOR = 1 MINOR = 3 - TINY = 3 + TINY = 6 STRING = [MAJOR, MINOR, TINY].join('.') end diff --git a/vendor/rails/actionpack/CHANGELOG b/vendor/rails/actionpack/CHANGELOG index c298ff5..463eefc 100644 --- a/vendor/rails/actionpack/CHANGELOG +++ b/vendor/rails/actionpack/CHANGELOG @@ -1,6 +1,61 @@ +*1.13.6* (November 24th, 2007) + +* Correct Broken Fix for session_fixation attacks + +* Ensure that cookies handle array values correctly. Closes #9937 [queso] + +*1.13.5* (October 12th, 2007) + +* 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] + +* Fix in place editor's setter action with non-string fields. #7418 [Andreas] + + +*1.13.4* (October 4th, 2007) + +* Only accept session ids from cookies, prevents session fixation attacks. [bradediger] + +* 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] + +* Integration tests: introduce methods for other HTTP methods. #6353 [caboose] + +* Improve performance of action caching. Closes #8231 [skaes] + +* Fix errors with around_filters which do not yield, restore 1.1 behaviour with after filters. Closes #8891 [skaes] + + After filters will *no longer* be run if an around_filter fails to yield, users relying on + this behaviour are advised to put the code in question after a yield statement in an around filter. + +* Allow you to delete cookies with options. Closes #3685 [josh, Chris Wanstrath] + +* Deprecate pagination. Install the classic_pagination plugin for forward compatibility, or move to the superior will_paginate plugin. #8157 [Mislav Marohnic] + +* Fix filtered parameter logging with nil parameter values. #8422 [choonkeat] + +* 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] + +* Document caches_action. #5419 [Jarkko Laine] + +* observe_form always sends the serialized form. #5271 [manfred, normelton@gmail.com] + +* Update UrlWriter to accept :anchor parameter. Closes #6771. [octopod] + +* Replace the current block/continuation filter chain handling by an implementation based on a simple loop. Closes #8226 [Stefan Kaes] + +* Return the string representation from an Xml Builder when rendering a partial. #5044 [tpope] + +* Cleaned up, corrected, and mildly expanded ActionPack documentation. Closes #7190 [jeremymcanally] + +* Small collection of ActionController documentation cleanups. Closes #7319 [jeremymcanally] + +* Performance: patch cgi/session/pstore to require digest/md5 once rather than per #initialize. #7583 [Stefan Kaes] + +* Deprecation: verification with :redirect_to => :named_route shouldn't be deprecated. #7525 [Justin French] + + *1.13.3* (March 12th, 2007) -* Apply [5709] to stable. +* 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] * session_enabled? works with session :off. #6680 [Catfish] @@ -440,7 +495,7 @@ * Avoid naming collision among compiled view methods. [Jeremy Kemper] -* Fix CGI extensions when they expect string but get nil in Windows. Closes #5276 [mislav@nippur.irb.hr] +* Fix CGI extensions when they expect string but get nil in Windows. Closes #5276 [Mislav Marohnic] * Determine the correct template_root for deeply nested components. #2841 [s.brink@web.de] diff --git a/vendor/rails/actionpack/Rakefile b/vendor/rails/actionpack/Rakefile index 4bca6b6..1b2af37 100755 --- a/vendor/rails/actionpack/Rakefile +++ b/vendor/rails/actionpack/Rakefile @@ -75,7 +75,7 @@ spec = Gem::Specification.new do |s| s.has_rdoc = true s.requirements << 'none' - s.add_dependency('activesupport', '= 1.4.2' + PKG_BUILD) + s.add_dependency('activesupport', '= 1.4.4' + PKG_BUILD) s.require_path = 'lib' s.autorequire = 'action_controller' diff --git a/vendor/rails/actionpack/examples/address_book_controller.cgi b/vendor/rails/actionpack/examples/address_book_controller.cgi index 2e15467..090af9c 100755 --- a/vendor/rails/actionpack/examples/address_book_controller.cgi +++ b/vendor/rails/actionpack/examples/address_book_controller.cgi @@ -1,3 +1,5 @@ +#!/usr/bin/ruby + #!/usr/local/bin/ruby require "address_book_controller" diff --git a/vendor/rails/actionpack/examples/address_book_controller.fcgi b/vendor/rails/actionpack/examples/address_book_controller.fcgi index 39947b4..3a859c8 100755 --- a/vendor/rails/actionpack/examples/address_book_controller.fcgi +++ b/vendor/rails/actionpack/examples/address_book_controller.fcgi @@ -1,3 +1,5 @@ +#!/usr/bin/ruby + #!/usr/local/bin/ruby require "address_book_controller" diff --git a/vendor/rails/actionpack/examples/address_book_controller.rbx b/vendor/rails/actionpack/examples/address_book_controller.rbx index 8c04eec..5598320 100644 --- a/vendor/rails/actionpack/examples/address_book_controller.rbx +++ b/vendor/rails/actionpack/examples/address_book_controller.rbx @@ -1,3 +1,5 @@ +#!/usr/bin/ruby + #!/usr/local/bin/ruby require "address_book_controller" diff --git a/vendor/rails/actionpack/examples/benchmark_with_ar.fcgi b/vendor/rails/actionpack/examples/benchmark_with_ar.fcgi index b9de370..58851bc 100755 --- a/vendor/rails/actionpack/examples/benchmark_with_ar.fcgi +++ b/vendor/rails/actionpack/examples/benchmark_with_ar.fcgi @@ -1,3 +1,5 @@ +#!/usr/bin/ruby + #!/usr/local/bin/ruby begin diff --git a/vendor/rails/actionpack/examples/blog_controller.cgi b/vendor/rails/actionpack/examples/blog_controller.cgi index 3868c30..bc2c6a3 100755 --- a/vendor/rails/actionpack/examples/blog_controller.cgi +++ b/vendor/rails/actionpack/examples/blog_controller.cgi @@ -1,3 +1,5 @@ +#!/usr/bin/ruby + #!/usr/local/bin/ruby $:.unshift(File.dirname(__FILE__) + "/../lib") diff --git a/vendor/rails/actionpack/examples/debate_controller.cgi b/vendor/rails/actionpack/examples/debate_controller.cgi index dbe0225..e615d0c 100755 --- a/vendor/rails/actionpack/examples/debate_controller.cgi +++ b/vendor/rails/actionpack/examples/debate_controller.cgi @@ -1,3 +1,5 @@ +#!/usr/bin/ruby + #!/usr/local/bin/ruby $:.unshift(File.dirname(__FILE__) + "/../lib") diff --git a/vendor/rails/actionpack/lib/action_controller/assertions/dom_assertions.rb b/vendor/rails/actionpack/lib/action_controller/assertions/dom_assertions.rb index d1eea59..355080f 100644 --- a/vendor/rails/actionpack/lib/action_controller/assertions/dom_assertions.rb +++ b/vendor/rails/actionpack/lib/action_controller/assertions/dom_assertions.rb @@ -1,7 +1,7 @@ module ActionController module Assertions module DomAssertions - # test 2 html strings to be equivalent, i.e. identical up to reordering of attributes + # Test two HTML strings for equivalency (e.g., identical up to reordering of attributes) def assert_dom_equal(expected, actual, message="") clean_backtrace do expected_dom = HTML::Document.new(expected).root @@ -11,7 +11,7 @@ module ActionController end end - # negated form of +assert_dom_equivalent+ + # The negated form of +assert_dom_equivalent+. def assert_dom_not_equal(expected, actual, message="") clean_backtrace do expected_dom = HTML::Document.new(expected).root diff --git a/vendor/rails/actionpack/lib/action_controller/assertions/model_assertions.rb b/vendor/rails/actionpack/lib/action_controller/assertions/model_assertions.rb index a9bcd7d..5fc5c81 100644 --- a/vendor/rails/actionpack/lib/action_controller/assertions/model_assertions.rb +++ b/vendor/rails/actionpack/lib/action_controller/assertions/model_assertions.rb @@ -1,7 +1,7 @@ module ActionController module Assertions module ModelAssertions - # ensures that the passed record is valid by active record standards. returns the error messages if not + # Ensures that the passed record is valid by ActiveRecord standards and returns any error messages if it is not. def assert_valid(record) clean_backtrace do assert record.valid?, record.errors.full_messages.join("\n") diff --git a/vendor/rails/actionpack/lib/action_controller/assertions/response_assertions.rb b/vendor/rails/actionpack/lib/action_controller/assertions/response_assertions.rb index bcb07e6..1d68fd8 100644 --- a/vendor/rails/actionpack/lib/action_controller/assertions/response_assertions.rb +++ b/vendor/rails/actionpack/lib/action_controller/assertions/response_assertions.rb @@ -69,6 +69,7 @@ module ActionController end if value.respond_to?(:[]) && value['controller'] + value['controller'] = value['controller'].to_s if key == :actual && value['controller'].first != '/' && !value['controller'].include?('/') new_controller_path = ActionController::Routing.controller_relative_to(value['controller'], @controller.class.controller_path) 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 end private + # Recognizes the route for a given path. def recognized_request_for(path, request_method = nil) path = "/#{path}" unless path.first == '/' @@ -132,6 +134,7 @@ module ActionController request end + # Proxy to to_param if the object will respond to it. def parameterize(value) value.respond_to?(:to_param) ? value.to_param : value end diff --git a/vendor/rails/actionpack/lib/action_controller/assertions/routing_assertions.rb b/vendor/rails/actionpack/lib/action_controller/assertions/routing_assertions.rb index 11a649c..6cd4d48 100644 --- a/vendor/rails/actionpack/lib/action_controller/assertions/routing_assertions.rb +++ b/vendor/rails/actionpack/lib/action_controller/assertions/routing_assertions.rb @@ -82,6 +82,7 @@ module ActionController end private + # Recognizes the route for a given path. def recognized_request_for(path, request_method = nil) path = "/#{path}" unless path.first == '/' diff --git a/vendor/rails/actionpack/lib/action_controller/assertions/selector_assertions.rb b/vendor/rails/actionpack/lib/action_controller/assertions/selector_assertions.rb index a5267e2..54d4f8d 100644 --- a/vendor/rails/actionpack/lib/action_controller/assertions/selector_assertions.rb +++ b/vendor/rails/actionpack/lib/action_controller/assertions/selector_assertions.rb @@ -561,6 +561,8 @@ module ActionController # RJS encodes double quotes and line breaks. unescaped= rjs_string.gsub('\"', '"') unescaped.gsub!('\n', "\n") + unescaped.gsub!('\076', '>') + unescaped.gsub!('\074', '<') # RJS encodes non-ascii characters. unescaped.gsub!(RJS_PATTERN_UNICODE_ESCAPED_CHAR) {|u| [$1.hex].pack('U*')} unescaped diff --git a/vendor/rails/actionpack/lib/action_controller/base.rb b/vendor/rails/actionpack/lib/action_controller/base.rb index a84d876..4450b08 100755 --- a/vendor/rails/actionpack/lib/action_controller/base.rb +++ b/vendor/rails/actionpack/lib/action_controller/base.rb @@ -292,6 +292,10 @@ module ActionController #:nodoc: # Turn on +ignore_missing_templates+ if you want to unit test actions without making the associated templates. cattr_accessor :ignore_missing_templates + # Controls the resource action separator + @@resource_action_separator = "/" + cattr_accessor :resource_action_separator + # Holds the request object that's primarily used to get environment variables through access like # request.env["REQUEST_URI"]. attr_internal :request @@ -393,7 +397,8 @@ module ActionController #:nodoc: elsif value.is_a?(Hash) filtered_parameters[key] = filter_parameters(value) elsif block_given? - key, value = key.dup, value.dup + key = key.dup + value = value.dup if value yield key, value filtered_parameters[key] = value else @@ -538,6 +543,7 @@ module ActionController #:nodoc: self.class.controller_path end + # Test whether the session is enabled for this request. def session_enabled? request.session_options && request.session_options[:disabled] != false end diff --git a/vendor/rails/actionpack/lib/action_controller/caching.rb b/vendor/rails/actionpack/lib/action_controller/caching.rb index 35dee4b..94e44c9 100644 --- a/vendor/rails/actionpack/lib/action_controller/caching.rb +++ b/vendor/rails/actionpack/lib/action_controller/caching.rb @@ -1,5 +1,6 @@ require 'fileutils' require 'uri' +require 'set' module ActionController #:nodoc: # 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: module Actions def self.included(base) #:nodoc: base.extend(ClassMethods) - base.send(:attr_accessor, :rendered_action_cache) + base.class_eval do + attr_accessor :rendered_action_cache, :action_cache_path + alias_method_chain :protected_instance_variables, :action_caching + end end - module ClassMethods #:nodoc: + def protected_instance_variables_with_action_caching + protected_instance_variables_without_action_caching + %w(@action_cache_path) + end + + module ClassMethods + # Declares that +actions+ should be cached. + # See ActionController::Caching::Actions for details. def caches_action(*actions) return unless perform_caching - around_filter(ActionCacheFilter.new(*actions)) + action_cache_filter = ActionCacheFilter.new(*actions) + before_filter action_cache_filter + after_filter action_cache_filter end end @@ -185,70 +197,59 @@ module ActionController #:nodoc: end class ActionCacheFilter #:nodoc: - def initialize(*actions, &block) - @actions = actions + def initialize(*actions) + @actions = Set.new actions end def before(controller) - return unless @actions.include?(controller.action_name.intern) - action_cache_path = ActionCachePath.new(controller) - if cache = controller.read_fragment(action_cache_path.path) + return unless @actions.include?(controller.action_name.to_sym) + cache_path = ActionCachePath.new(controller, {}) + if cache = controller.read_fragment(cache_path.path) controller.rendered_action_cache = true - set_content_type!(action_cache_path) + set_content_type!(controller, cache_path.extension) controller.send(:render_text, cache) false + else + controller.action_cache_path = cache_path end end def after(controller) - return if !@actions.include?(controller.action_name.intern) || controller.rendered_action_cache - controller.write_fragment(ActionCachePath.path_for(controller), controller.response.body) + return if !@actions.include?(controller.action_name.to_sym) || controller.rendered_action_cache + controller.write_fragment(controller.action_cache_path.path, controller.response.body) end private - - def set_content_type!(action_cache_path) - if extention = action_cache_path.extension - content_type = Mime::EXTENSION_LOOKUP[extention] - action_cache_path.controller.response.content_type = content_type.to_s - end + def set_content_type!(controller, extension) + controller.response.content_type = Mime::EXTENSION_LOOKUP[extension].to_s if extension end end class ActionCachePath - attr_reader :controller, :options + attr_reader :path, :extension class << self - def path_for(*args, &block) - new(*args).path + def path_for(controller, options) + new(controller, options).path end end def initialize(controller, options = {}) - @controller = controller - @options = options - end - - def path - return @path if @path - @path = controller.url_for(options).split('://').last - normalize! - add_extension! - URI.unescape(@path) - end - - def extension - @extension ||= extract_extension(controller.request.path) + @extension = extract_extension(controller.request.path) + path = controller.url_for(options).split('://').last + normalize!(path) + add_extension!(path, @extension) + @path = URI.unescape(path) end private - def normalize! - @path << 'index' if @path.last == '/' + def normalize!(path) + path << 'index' if path[-1] == ?/ end - def add_extension! - @path << ".#{extension}" if extension + def add_extension!(path, extension) + path << ".#{extension}" if extension end def extract_extension(file_path) diff --git a/vendor/rails/actionpack/lib/action_controller/cgi_ext/pstore_performance_fix.rb b/vendor/rails/actionpack/lib/action_controller/cgi_ext/pstore_performance_fix.rb new file mode 100644 index 0000000..79e427a --- /dev/null +++ b/vendor/rails/actionpack/lib/action_controller/cgi_ext/pstore_performance_fix.rb @@ -0,0 +1,30 @@ +# CGI::Session::PStore.initialize requires 'digest/md5' on every call. +# This makes sense when spawning processes per request, but is +# unnecessarily expensive when serving requests from a long-lived +# process. +require 'cgi/session' +require 'cgi/session/pstore' +require 'digest/md5' + +class CGI::Session::PStore #:nodoc: + def initialize(session, option={}) + dir = option['tmpdir'] || Dir::tmpdir + prefix = option['prefix'] || '' + id = session.session_id + md5 = Digest::MD5.hexdigest(id)[0,16] + path = dir+"/"+prefix+md5 + path.untaint + if File::exist?(path) + @hash = nil + else + unless session.new_session + raise CGI::Session::NoSession, "uninitialized session" + end + @hash = {} + end + @p = ::PStore.new(path) + @p.transaction do |p| + File.chmod(0600, p.path) + end + end +end diff --git a/vendor/rails/actionpack/lib/action_controller/cgi_ext/raw_post_data_fix.rb b/vendor/rails/actionpack/lib/action_controller/cgi_ext/raw_post_data_fix.rb index 4c124cb..4f6fbce 100644 --- a/vendor/rails/actionpack/lib/action_controller/cgi_ext/raw_post_data_fix.rb +++ b/vendor/rails/actionpack/lib/action_controller/cgi_ext/raw_post_data_fix.rb @@ -65,7 +65,7 @@ class CGI #:nodoc: if env_qs.blank? && !(uri = env_table['REQUEST_URI']).blank? uri.split('?', 2)[1] || '' else - env_qs + env_qs || '' end end end diff --git a/vendor/rails/actionpack/lib/action_controller/cgi_process.rb b/vendor/rails/actionpack/lib/action_controller/cgi_process.rb index efb2c61..dd25e7b 100644 --- a/vendor/rails/actionpack/lib/action_controller/cgi_process.rb +++ b/vendor/rails/actionpack/lib/action_controller/cgi_process.rb @@ -2,6 +2,7 @@ require 'action_controller/cgi_ext/cgi_ext' require 'action_controller/cgi_ext/cookie_performance_fix' require 'action_controller/cgi_ext/raw_post_data_fix' require 'action_controller/cgi_ext/session_performance_fix' +require 'action_controller/cgi_ext/pstore_performance_fix' module ActionController #:nodoc: class Base @@ -12,8 +13,8 @@ module ActionController #:nodoc: # (default). Additionally, there is CGI::Session::DRbStore and CGI::Session::ActiveRecordStore. Read more about these in # lib/action_controller/session. # * :session_key - the parameter name used for the session id. Defaults to '_session_id'. - # * :session_id - the session id to use. If not provided, then it is retrieved from the +session_key+ parameter - # of the request, or automatically generated for a new session. + # * :session_id - the session id to use. If not provided, then it is retrieved from the +session_key+ cookie, or + # automatically generated for a new session. # * :new_session - if true, force creation of a new session. If not set, a new session is only created if none currently # exists. If false, a new session is never created, and if none currently exists and the +session_id+ option is not set, # an ArgumentError is raised. @@ -23,6 +24,8 @@ module ActionController #:nodoc: # server. # * :session_secure - if +true+, this session will only work over HTTPS. # * :session_path - the path for which this session applies. Defaults to the directory of the CGI script. + # * :cookie_only - if +true+ (the default), session IDs will only be accepted from cookies and not from + # the query string or POST parameters. This protects against session fixation attacks. def self.process_cgi(cgi = CGI.new, session_options = {}) new.process_cgi(cgi, session_options) end @@ -34,11 +37,14 @@ module ActionController #:nodoc: class CgiRequest < AbstractRequest #:nodoc: attr_accessor :cgi, :session_options + class SessionFixationAttempt < StandardError; end #:nodoc: DEFAULT_SESSION_OPTIONS = { :database_manager => CGI::Session::PStore, :prefix => "ruby_sess.", - :session_path => "/" + :session_path => "/", + :session_key => "_session_id", + :cookie_only => true } unless const_defined?(:DEFAULT_SESSION_OPTIONS) def initialize(cgi, session_options = {}) @@ -48,6 +54,10 @@ module ActionController #:nodoc: super() end + def cookie_only? + session_options_with_string_keys['cookie_only'] + end + def query_string if (qs = @cgi.query_string) && !qs.empty? qs @@ -108,6 +118,9 @@ module ActionController #:nodoc: @session = Hash.new else stale_session_check! do + if cookie_only? && request_parameters[session_options_with_string_keys['session_key']] + raise SessionFixationAttempt + end case value = session_options_with_string_keys['new_session'] when true @session = new_session diff --git a/vendor/rails/actionpack/lib/action_controller/cookies.rb b/vendor/rails/actionpack/lib/action_controller/cookies.rb index 52423aa..eb5ebfe 100644 --- a/vendor/rails/actionpack/lib/action_controller/cookies.rb +++ b/vendor/rails/actionpack/lib/action_controller/cookies.rb @@ -47,7 +47,10 @@ module ActionController #:nodoc: # Returns the value of the cookie by +name+ -- or nil if no such cookie exists. You set new cookies using either the cookie method # or cookies[]= (for simple name/value cookies without options). def [](name) - @cookies[name.to_s].value.first if @cookies[name.to_s] && @cookies[name.to_s].respond_to?(:value) + cookie = @cookies[name.to_s] + if cookie && cookie.respond_to?(:value) + cookie.size > 1 ? cookie.value : cookie.value.to_s + end end def []=(name, options) @@ -62,9 +65,11 @@ module ActionController #:nodoc: end # Removes the cookie on the client machine by setting the value to an empty string - # and setting its expiration date into the past - def delete(name) - set_cookie("name" => name.to_s, "value" => "", "expires" => Time.at(0)) + # and setting its expiration date into the past. Like []=, you can pass in an options + # hash to delete cookies with extra data such as a +path+. + def delete(name, options = {}) + options.stringify_keys! + set_cookie(options.merge("name" => name.to_s, "value" => "", "expires" => Time.at(0))) end private diff --git a/vendor/rails/actionpack/lib/action_controller/filters.rb b/vendor/rails/actionpack/lib/action_controller/filters.rb index 3290def..11d2374 100644 --- a/vendor/rails/actionpack/lib/action_controller/filters.rb +++ b/vendor/rails/actionpack/lib/action_controller/filters.rb @@ -214,9 +214,10 @@ module ActionController #:nodoc: # == Filter Chain Halting # # before_filter and around_filter may halt the request - # before controller action is run. This is useful, for example, to deny + # before a controller action is run. This is useful, for example, to deny # access to unauthenticated users or to redirect from http to https. # Simply return false from the filter or call render or redirect. + # After filters will not be executed if the filter chain is halted. # # Around filters halt the request unless the action block is called. # Given these filters @@ -238,12 +239,12 @@ module ActionController #:nodoc: # . . / # . #around (code after yield) # . / - # #after (actual filter code is run) + # #after (actual filter code is run, unless the around filter does not yield) # - # If #around returns before yielding, only #after will be run. The #before - # filter and controller action will not be run. If #before returns false, - # the second half of #around and all of #after will still run but the - # action will not. + # If #around returns before yielding, #after will still not be run. The #before + # filter and controller action will not be run. If #before returns false, + # the second half of #around and will still run but #after and the + # action will not. If #around does not yield, #after will not be run. module ClassMethods # The passed filters will be appended to the filter_chain and # will execute before the action on this controller is performed. @@ -263,13 +264,13 @@ module ActionController #:nodoc: # The passed filters will be appended to the array of filters # that run _after_ actions on this controller are performed. def append_after_filter(*filters, &block) - prepend_filter_to_chain(filters, :after, &block) + append_filter_to_chain(filters, :after, &block) end # The passed filters will be prepended to the array of filters # that run _after_ actions on this controller are performed. def prepend_after_filter(*filters, &block) - append_filter_to_chain(filters, :after, &block) + prepend_filter_to_chain(filters, :after, &block) end # Shorthand for append_after_filter since it's the most common. @@ -362,12 +363,12 @@ module ActionController #:nodoc: # Returns a mapping between filters and the actions that may run them. def included_actions #:nodoc: - read_inheritable_attribute("included_actions") || {} + @included_actions ||= read_inheritable_attribute("included_actions") || {} end # Returns a mapping between filters and actions that may not run them. def excluded_actions #:nodoc: - read_inheritable_attribute("excluded_actions") || {} + @excluded_actions ||= read_inheritable_attribute("excluded_actions") || {} end # Find a filter in the filter_chain where the filter method matches the _filter_ param @@ -381,10 +382,11 @@ module ActionController #:nodoc: # Returns true if the filter is excluded from the given action def filter_excluded_from_action?(filter,action) #:nodoc: - if (ia = included_actions[filter]) && !ia.empty? + case + when ia = included_actions[filter] !ia.include?(action) - else - (excluded_actions[filter] || []).include?(action) + when ea = excluded_actions[filter] + ea.include?(action) end end @@ -397,20 +399,28 @@ module ActionController #:nodoc: @filter = filter end + def type + :around + end + def before? - false + type == :before end def after? - false + type == :after end def around? - true + type == :around + end + + def run(controller) + raise ActionControllerError, 'No filter type: Nothing to do here.' end def call(controller, &block) - raise(ActionControllerError, 'No filter type: Nothing to do here.') + run(controller) end end @@ -420,35 +430,38 @@ module ActionController #:nodoc: def filter @filter.filter end - - def around? - false - end end class BeforeFilterProxy < FilterProxy #:nodoc: - def before? - true + def type + :before end - def call(controller, &block) - if false == @filter.call(controller) # must only stop if equal to false. only filters returning false are halted. - controller.halt_filter_chain(@filter, :returned_false) - else - yield + def run(controller) + # only filters returning false are halted. + if false == @filter.call(controller) + controller.send :halt_filter_chain, @filter, :returned_false end end + + def call(controller) + yield unless run(controller) + end end class AfterFilterProxy < FilterProxy #:nodoc: - def after? - true + def type + :after end - def call(controller, &block) - yield + def run(controller) @filter.call(controller) end + + def call(controller) + yield + run(controller) + end end class SymbolFilter < Filter #:nodoc: @@ -485,29 +498,72 @@ module ActionController #:nodoc: end end + class ClassBeforeFilter < Filter #:nodoc: + def call(controller, &block) + @filter.before(controller) + end + end + + class ClassAfterFilter < Filter #:nodoc: + def call(controller, &block) + @filter.after(controller) + end + end + protected - def append_filter_to_chain(filters, position = :around, &block) - write_inheritable_array('filter_chain', create_filters(filters, position, &block) ) + def append_filter_to_chain(filters, filter_type = :around, &block) + pos = find_filter_append_position(filters, filter_type) + update_filter_chain(filters, filter_type, pos, &block) end - def prepend_filter_to_chain(filters, position = :around, &block) - write_inheritable_attribute('filter_chain', create_filters(filters, position, &block) + filter_chain) + def prepend_filter_to_chain(filters, filter_type = :around, &block) + pos = find_filter_prepend_position(filters, filter_type) + update_filter_chain(filters, filter_type, pos, &block) end - def create_filters(filters, position, &block) #:nodoc: + def update_filter_chain(filters, filter_type, pos, &block) + new_filters = create_filters(filters, filter_type, &block) + new_chain = filter_chain.insert(pos, new_filters).flatten + write_inheritable_attribute('filter_chain', new_chain) + end + + def find_filter_append_position(filters, filter_type) + # appending an after filter puts it at the end of the call chain + # before and around filters go before the first after filter in the chain + unless filter_type == :after + filter_chain.each_with_index do |f,i| + return i if f.after? + end + end + return -1 + end + + def find_filter_prepend_position(filters, filter_type) + # prepending a before or around filter puts it at the front of the call chain + # after filters go before the first after filter in the chain + if filter_type == :after + filter_chain.each_with_index do |f,i| + return i if f.after? + end + return -1 + end + return 0 + end + + def create_filters(filters, filter_type, &block) #:nodoc: filters, conditions = extract_conditions(filters, &block) - filters.map! { |filter| find_or_create_filter(filter,position) } + filters.map! { |filter| find_or_create_filter(filter, filter_type) } update_conditions(filters, conditions) filters end - def find_or_create_filter(filter,position) - if found_filter = find_filter(filter) { |f| f.send("#{position}?") } + def find_or_create_filter(filter, filter_type) + if found_filter = find_filter(filter) { |f| f.type == filter_type } found_filter else - f = class_for_filter(filter).new(filter) + f = class_for_filter(filter, filter_type).new(filter) # apply proxy to filter if necessary - case position + case filter_type when :before BeforeFilterProxy.new(f) when :after @@ -520,7 +576,7 @@ module ActionController #:nodoc: # The determination of the filter type was once done at run time. # This method is here to extract as much logic from the filter run time as possible - def class_for_filter(filter) #:nodoc: + def class_for_filter(filter, filter_type) #:nodoc: case when filter.is_a?(Symbol) SymbolFilter @@ -534,8 +590,12 @@ module ActionController #:nodoc: end when filter.respond_to?(:filter) ClassFilter + when filter.respond_to?(:before) && filter_type == :before + ClassBeforeFilter + when filter.respond_to?(:after) && filter_type == :after + ClassAfterFilter else - raise(ActionControllerError, 'A filters must be a Symbol, Proc, Method, or object responding to filter.') + raise(ActionControllerError, 'A filter must be a Symbol, Proc, Method, or object responding to filter, after or before.') end end @@ -550,8 +610,8 @@ module ActionController #:nodoc: return if conditions.empty? if conditions[:only] write_inheritable_hash('included_actions', condition_hash(filters, conditions[:only])) - else - write_inheritable_hash('excluded_actions', condition_hash(filters, conditions[:except])) if conditions[:except] + elsif conditions[:except] + write_inheritable_hash('excluded_actions', condition_hash(filters, conditions[:except])) end end @@ -576,9 +636,9 @@ module ActionController #:nodoc: def remove_actions_from_included_actions!(filters,*actions) actions = actions.flatten.map(&:to_s) - updated_hash = filters.inject(included_actions) do |hash,filter| + updated_hash = filters.inject(read_inheritable_attribute('included_actions')||{}) do |hash,filter| ia = (hash[filter] || []) - actions - ia.blank? ? hash.delete(filter) : hash[filter] = ia + ia.empty? ? hash.delete(filter) : hash[filter] = ia hash end write_inheritable_attribute('included_actions', updated_hash) @@ -595,7 +655,9 @@ module ActionController #:nodoc: def proxy_before_and_after_filter(filter) #:nodoc: return filter unless filter_responds_to_before_and_after(filter) Proc.new do |controller, action| - unless filter.before(controller) == false + if filter.before(controller) == false + controller.send :halt_filter_chain, filter, :returned_false + else begin action.call ensure @@ -615,53 +677,90 @@ module ActionController #:nodoc: end end - def perform_action_with_filters - call_filter(self.class.filter_chain, 0) - end + protected def process_with_filters(request, response, method = :perform_action, *arguments) #:nodoc: @before_filter_chain_aborted = false process_without_filters(request, response, method, *arguments) end - def filter_chain - self.class.filter_chain + def perform_action_with_filters + call_filters(self.class.filter_chain, 0, 0) end - def call_filter(chain, index) - return (performed? || perform_action_without_filters) if index >= chain.size - filter = chain[index] - return call_filter(chain, index.next) if self.class.filter_excluded_from_action?(filter,action_name) + private - halted = false - filter.call(self) do - halted = call_filter(chain, index.next) + def call_filters(chain, index, nesting) + index = run_before_filters(chain, index, nesting) + aborted = @before_filter_chain_aborted + perform_action_without_filters unless performed? || aborted + return index if nesting != 0 || aborted + run_after_filters(chain, index) + end + + def skip_excluded_filters(chain, index) + while (filter = chain[index]) && self.class.filter_excluded_from_action?(filter, action_name) + index = index.next end - halt_filter_chain(filter.filter, :no_yield) if halted == false unless @before_filter_chain_aborted - halted + [filter, index] end - def halt_filter_chain(filter, reason) - if logger - case reason - when :no_yield - logger.info "Filter chain halted as [#{filter.inspect}] did not yield." - when :returned_false - logger.info "Filter chain halted as [#{filter.inspect}] returned false." + def run_before_filters(chain, index, nesting) + while chain[index] + filter, index = skip_excluded_filters(chain, index) + break unless filter # end of call chain reached + case filter.type + when :before + filter.run(self) # invoke before filter + index = index.next + break if @before_filter_chain_aborted + when :around + yielded = false + filter.call(self) do + yielded = true + # all remaining before and around filters will be run in this call + index = call_filters(chain, index.next, nesting.next) + end + halt_filter_chain(filter, :did_not_yield) unless yielded + break + else + break # no before or around filters left end end - @before_filter_chain_aborted = true - return false + index end - private - def process_cleanup_with_filters - if @before_filter_chain_aborted - close_session + def run_after_filters(chain, index) + seen_after_filter = false + while chain[index] + filter, index = skip_excluded_filters(chain, index) + break unless filter # end of call chain reached + case filter.type + when :after + seen_after_filter = true + filter.run(self) # invoke after filter else - process_cleanup_without_filters + # implementation error or someone has mucked with the filter chain + raise ActionControllerError, "filter #{filter.inspect} was in the wrong place!" if seen_after_filter end + index = index.next + end + index.next + end + + def halt_filter_chain(filter, reason) + @before_filter_chain_aborted = true + logger.info "Filter chain halted as [#{filter.inspect}] #{reason}." if logger + false + end + + def process_cleanup_with_filters + if @before_filter_chain_aborted + close_session + else + process_cleanup_without_filters end + end end end end diff --git a/vendor/rails/actionpack/lib/action_controller/integration.rb b/vendor/rails/actionpack/lib/action_controller/integration.rb index d77540a..a0c7409 100644 --- a/vendor/rails/actionpack/lib/action_controller/integration.rb +++ b/vendor/rails/actionpack/lib/action_controller/integration.rb @@ -67,7 +67,7 @@ module ActionController @https = false @cookies = {} @controller = @request = @response = nil - + self.host = "www.example.com" self.remote_addr = "127.0.0.1" 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 # session.https! # session.https!(false) def https!(flag=true) - @https = flag + @https = flag end # Return +true+ if the session is mimicing a secure HTTPS request. @@ -143,10 +143,10 @@ module ActionController # Performs a GET request with the given parameters. The parameters may # be +nil+, a Hash, or a string that is appropriately encoded # (application/x-www-form-urlencoded or multipart/form-data). The headers - # should be a hash. The keys will automatically be upcased, with the + # should be a hash. The keys will automatically be upcased, with the # prefix 'HTTP_' added if needed. # - # You can also perform POST, PUT, DELETE, and HEAD requests with #post, + # You can also perform POST, PUT, DELETE, and HEAD requests with #post, # #put, #delete, and #head. def get(path, parameters=nil, headers=nil) process :get, path, parameters, headers @@ -161,31 +161,41 @@ module ActionController def put(path, parameters=nil, headers=nil) process :put, path, parameters, headers end - + # Performs a DELETE request with the given parameters. See get() for more details. def delete(path, parameters=nil, headers=nil) process :delete, path, parameters, headers end - + # Performs a HEAD request with the given parameters. See get() for more details. def head(path, parameters=nil, headers=nil) process :head, path, parameters, headers end - # Performs an XMLHttpRequest request with the given parameters, mimicing - # the request environment created by the Prototype library. The parameters - # may be +nil+, a Hash, or a string that is appropriately encoded - # (application/x-www-form-urlencoded or multipart/form-data). The headers - # should be a hash. The keys will automatically be upcased, with the - # prefix 'HTTP_' added if needed. - def xml_http_request(path, parameters=nil, headers=nil) - headers = (headers || {}).merge( - "X-Requested-With" => "XMLHttpRequest", - "Accept" => "text/javascript, text/html, application/xml, text/xml, */*" - ) + # Performs an XMLHttpRequest request with the given parameters, mirroring + # a request from the Prototype library. + # + # The request_method is :get, :post, :put, :delete or :head; the + # parameters are +nil+, a hash, or a url-encoded or multipart string; + # the headers are a hash. Keys are automatically upcased and prefixed + # with 'HTTP_' if not already. + # + # This method used to omit the request_method parameter, assuming it + # was :post. This was deprecated in Rails 1.2.4. Always pass the request + # method as the first argument. + def xml_http_request(request_method, path, parameters = nil, headers = nil) + unless request_method.is_a?(Symbol) + 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.' + request_method, path, parameters, headers = :post, request_method, path, parameters + end + + headers ||= {} + headers['X-Requested-With'] = 'XMLHttpRequest' + headers['Accept'] = 'text/javascript, text/html, application/xml, text/xml, */*' - post(path, parameters, headers) + process(request_method, path, parameters, headers) end + alias xhr :xml_http_request # Returns the URL for the given options, according to the rules specified # in the application's routes. @@ -292,7 +302,7 @@ module ActionController @status = @status.to_i end - # Encode the cookies hash in a format suitable for passing to a + # Encode the cookies hash in a format suitable for passing to a # request. def encode_cookies cookies.inject("") do |string, (name, value)| @@ -450,7 +460,7 @@ module ActionController # without any test methods. def run(*args) #:nodoc: return if @method_name == "default_test" - super + super end # Because of how use_instantiated_fixtures and use_transactional_fixtures @@ -490,7 +500,7 @@ module ActionController @integration_session = open_session end - %w(get post cookies assigns xml_http_request).each do |method| + %w(get post put head delete cookies assigns xml_http_request).each do |method| define_method(method) do |*args| reset! unless @integration_session # reset the html_document variable, but only for new get/post calls diff --git a/vendor/rails/actionpack/lib/action_controller/macros/in_place_editing.rb b/vendor/rails/actionpack/lib/action_controller/macros/in_place_editing.rb index d04f1ce..2d973f5 100644 --- a/vendor/rails/actionpack/lib/action_controller/macros/in_place_editing.rb +++ b/vendor/rails/actionpack/lib/action_controller/macros/in_place_editing.rb @@ -24,7 +24,7 @@ module ActionController define_method("set_#{object}_#{attribute}") do @item = object.to_s.camelize.constantize.find(params[:id]) @item.update_attribute(attribute, params[:value]) - render :text => @item.send(attribute) + render :text => @item.send(attribute).to_s end end end diff --git a/vendor/rails/actionpack/lib/action_controller/pagination.rb b/vendor/rails/actionpack/lib/action_controller/pagination.rb index 595a08c..415e720 100644 --- a/vendor/rails/actionpack/lib/action_controller/pagination.rb +++ b/vendor/rails/actionpack/lib/action_controller/pagination.rb @@ -1,7 +1,9 @@ module ActionController # === Action Pack pagination for Active Record collections # - # DEPRECATION WARNING: Pagination will be separated into its own plugin with Rails 2.0. + # DEPRECATION WARNING: Pagination will be moved to a plugin in Rails 2.0. + # Install the classic_pagination plugin for forward compatibility: + # script/plugin install svn://errtheblog.com/svn/plugins/classic_pagination # # The Pagination module aids in the process of paging large collections of # Active Record objects. It offers macro-style automatic fetching of your @@ -130,6 +132,8 @@ module ActionController paginator_and_collection_for(collection_id, options) end + deprecate :paginate => 'Pagination is moving to a plugin in Rails 2.0: script/plugin install svn://errtheblog.com/svn/plugins/classic_pagination' + # These methods become class methods on any controller module ClassMethods # Creates a +before_filter+ which automatically paginates an Active @@ -148,6 +152,8 @@ module ActionController OPTIONS[self][collection_id] = options end end + + deprecate :paginate => 'Pagination is moving to a plugin in Rails 2.0: script/plugin install svn://errtheblog.com/svn/plugins/classic_pagination' end def create_paginators_and_retrieve_collections #:nodoc: diff --git a/vendor/rails/actionpack/lib/action_controller/resources.rb b/vendor/rails/actionpack/lib/action_controller/resources.rb index d55e7f0..204916d 100644 --- a/vendor/rails/actionpack/lib/action_controller/resources.rb +++ b/vendor/rails/actionpack/lib/action_controller/resources.rb @@ -2,48 +2,68 @@ module ActionController module Resources class Resource #:nodoc: attr_reader :collection_methods, :member_methods, :new_methods - attr_reader :path_prefix, :name_prefix + attr_reader :path_prefix, :new_name_prefix attr_reader :plural, :singular attr_reader :options def initialize(entities, options) @plural = entities @singular = options[:singular] || plural.to_s.singularize - + @options = options arrange_actions add_default_actions set_prefixes end - + def controller @controller ||= (options[:controller] || plural).to_s end - + def path @path ||= "#{path_prefix}/#{plural}" end - + def new_path @new_path ||= "#{path}/new" end - + def member_path @member_path ||= "#{path}/:id" end - + def nesting_path_prefix @nesting_path_prefix ||= "#{path}/:#{singular}_id" end - + + def deprecate_name_prefix? + @name_prefix.blank? && !@new_name_prefix.blank? + end + + def name_prefix + deprecate_name_prefix? ? @new_name_prefix : @name_prefix + end + + def old_name_prefix + @name_prefix + end + + def nesting_name_prefix + "#{new_name_prefix}#{singular}_" + end + + def action_separator + @action_separator ||= Base.resource_action_separator + end + protected def arrange_actions @collection_methods = arrange_actions_by_methods(options.delete(:collection)) @member_methods = arrange_actions_by_methods(options.delete(:member)) @new_methods = arrange_actions_by_methods(options.delete(:new)) end - + def add_default_actions add_default_action(member_methods, :get, :edit) add_default_action(new_methods, :get, :new) @@ -52,6 +72,7 @@ module ActionController def set_prefixes @path_prefix = options.delete(:path_prefix) @name_prefix = options.delete(:name_prefix) + @new_name_prefix = options.delete(:new_name_prefix) end def arrange_actions_by_methods(actions) @@ -60,7 +81,7 @@ module ActionController flipped_hash end end - + def add_default_action(collection, method, action) (collection[method] ||= []).unshift(action) end @@ -178,11 +199,11 @@ module ActionController # # The comment resources work the same, but must now include a value for :article_id. # - # comments_url(@article) - # comment_url(@article, @comment) + # article_comments_url(@article) + # article_comment_url(@article, @comment) # - # comments_url(:article_id => @article) - # comment_url(:article_id => @article, :id => @comment) + # article_comments_url(:article_id => @article) + # article_comment_url(:article_id => @article, :id => @comment) # # * :name_prefix -- define a prefix for all generated routes, usually ending in an underscore. # Use this if you have named routes that may clash. @@ -192,7 +213,7 @@ module ActionController # # * :collection -- add named routes for other actions that operate on the collection. # Takes a hash of #{action} => #{method}, where method is :get/:post/:put/:delete - # or :any if the method does not matter. These routes map to a URL like /messages;rss, with a route of rss_messages_url. + # or :any if the method does not matter. These routes map to a URL like /messages/rss, with a route of rss_messages_url. # * :member -- same as :collection, but for actions that operate on a specific member. # * :new -- same as :collection, but for actions that operate on the new resource action. # @@ -204,19 +225,19 @@ module ActionController # # --> GET /thread/7/messages/1 # # map.resources :messages, :collection => { :rss => :get } - # # --> GET /messages;rss (maps to the #rss action) + # # --> GET /messages/rss (maps to the #rss action) # # also adds a named route called "rss_messages" # # map.resources :messages, :member => { :mark => :post } - # # --> POST /messages/1;mark (maps to the #mark action) + # # --> POST /messages/1/mark (maps to the #mark action) # # also adds a named route called "mark_message" # # map.resources :messages, :new => { :preview => :post } - # # --> POST /messages/new;preview (maps to the #preview action) + # # --> POST /messages/new/preview (maps to the #preview action) # # also adds a named route called "preview_new_message" # # map.resources :messages, :new => { :new => :any, :preview => :post } - # # --> POST /messages/new;preview (maps to the #preview action) + # # --> POST /messages/new/preview (maps to the #preview action) # # also adds a named route called "preview_new_message" # # --> /messages/new can be invoked via any request method # @@ -235,9 +256,10 @@ module ActionController # /account profile. # # See map.resources for general conventions. These are the main differences: - # - a singular name is given to map.resource. The default controller name is taken from the singular name. - # - To specify a custom plural name, use the :plural option. There is no :singular option - # - No default index, new, or create routes are created for the singleton resource controller. + # - A singular name is given to map.resource. The default controller name is taken from the singular name. + # - There is no :collection option as there is only the singleton resource. + # - There is no :singular option as the singular name is passed to map.resource. + # - No default index route is created for the singleton resource controller. # - When nesting singleton resources, only the singular name is used as the path prefix (example: 'account/messages/1') # # Example: @@ -300,7 +322,7 @@ module ActionController map_member_actions(map, resource) if block_given? - with_options(:path_prefix => resource.nesting_path_prefix, &block) + with_options(:path_prefix => resource.nesting_path_prefix, :new_name_prefix => resource.nesting_name_prefix, &block) end end end @@ -315,7 +337,7 @@ module ActionController map_member_actions(map, resource) if block_given? - with_options(:path_prefix => resource.nesting_path_prefix, &block) + with_options(:path_prefix => resource.nesting_path_prefix, :new_name_prefix => resource.nesting_name_prefix, &block) end end end @@ -324,8 +346,21 @@ module ActionController resource.collection_methods.each do |method, actions| actions.each do |action| action_options = action_options_for(action, resource, method) - map.named_route("#{resource.name_prefix}#{action}_#{resource.plural}", "#{resource.path};#{action}", action_options) - map.named_route("formatted_#{resource.name_prefix}#{action}_#{resource.plural}", "#{resource.path}.:format;#{action}", action_options) + + unless resource.old_name_prefix.blank? + map.deprecated_named_route("#{action}_#{resource.name_prefix}#{resource.plural}", "#{resource.old_name_prefix}#{action}_#{resource.plural}") + map.deprecated_named_route("formatted_#{action}_#{resource.name_prefix}#{resource.plural}", "formatted_#{resource.old_name_prefix}#{action}_#{resource.plural}") + end + + if resource.deprecate_name_prefix? + map.deprecated_named_route("#{action}_#{resource.name_prefix}#{resource.plural}", "#{action}_#{resource.plural}") + map.deprecated_named_route("formatted_#{action}_#{resource.name_prefix}#{resource.plural}", "formatted_#{action}_#{resource.plural}") + end + + map.named_route("#{action}_#{resource.name_prefix}#{resource.plural}", "#{resource.path}#{resource.action_separator}#{action}", action_options) + map.connect("#{resource.path};#{action}", action_options) + map.connect("#{resource.path}.:format;#{action}", action_options) + map.named_route("formatted_#{action}_#{resource.name_prefix}#{resource.plural}", "#{resource.path}#{resource.action_separator}#{action}.:format", action_options) end end end @@ -335,6 +370,11 @@ module ActionController map.named_route("#{resource.name_prefix}#{resource.plural}", resource.path, index_action_options) map.named_route("formatted_#{resource.name_prefix}#{resource.plural}", "#{resource.path}.:format", index_action_options) + if resource.deprecate_name_prefix? + map.deprecated_named_route("#{resource.name_prefix}#{resource.plural}", "#{resource.plural}") + map.deprecated_named_route("formatted_#{resource.name_prefix}#{resource.plural}", "formatted_#{resource.plural}") + end + create_action_options = action_options_for("create", resource) map.connect(resource.path, create_action_options) map.connect("#{resource.path}.:format", create_action_options) @@ -351,11 +391,37 @@ module ActionController actions.each do |action| action_options = action_options_for(action, resource, method) if action == :new - map.named_route("#{resource.name_prefix}new_#{resource.singular}", resource.new_path, action_options) - map.named_route("formatted_#{resource.name_prefix}new_#{resource.singular}", "#{resource.new_path}.:format", action_options) + + unless resource.old_name_prefix.blank? + map.deprecated_named_route("new_#{resource.name_prefix}#{resource.singular}", "#{resource.old_name_prefix}new_#{resource.singular}") + map.deprecated_named_route("formatted_new_#{resource.name_prefix}#{resource.singular}", "formatted_#{resource.old_name_prefix}new_#{resource.singular}") + end + + if resource.deprecate_name_prefix? + map.deprecated_named_route("new_#{resource.name_prefix}#{resource.singular}", "new_#{resource.singular}") + map.deprecated_named_route("formatted_new_#{resource.name_prefix}#{resource.singular}", "formatted_new_#{resource.singular}") + end + + map.named_route("new_#{resource.name_prefix}#{resource.singular}", resource.new_path, action_options) + map.named_route("formatted_new_#{resource.name_prefix}#{resource.singular}", "#{resource.new_path}.:format", action_options) + else - map.named_route("#{resource.name_prefix}#{action}_new_#{resource.singular}", "#{resource.new_path};#{action}", action_options) - map.named_route("formatted_#{resource.name_prefix}#{action}_new_#{resource.singular}", "#{resource.new_path}.:format;#{action}", action_options) + + unless resource.old_name_prefix.blank? + map.deprecated_named_route("#{action}_new_#{resource.name_prefix}#{resource.singular}", "#{resource.old_name_prefix}#{action}_new_#{resource.singular}") + map.deprecated_named_route("formatted_#{action}_new_#{resource.name_prefix}#{resource.singular}", "formatted_#{resource.old_name_prefix}#{action}_new_#{resource.singular}") + end + + if resource.deprecate_name_prefix? + map.deprecated_named_route("#{action}_new_#{resource.name_prefix}#{resource.singular}", "#{action}_new_#{resource.singular}") + map.deprecated_named_route("formatted_#{action}_new_#{resource.name_prefix}#{resource.singular}", "formatted_#{action}_new_#{resource.singular}") + end + + map.named_route("#{action}_new_#{resource.name_prefix}#{resource.singular}", "#{resource.new_path}#{resource.action_separator}#{action}", action_options) + map.connect("#{resource.new_path};#{action}", action_options) + map.connect("#{resource.new_path}.:format;#{action}", action_options) + map.named_route("formatted_#{action}_new_#{resource.name_prefix}#{resource.singular}", "#{resource.new_path}#{resource.action_separator}#{action}.:format", action_options) + end end end @@ -365,8 +431,22 @@ module ActionController resource.member_methods.each do |method, actions| actions.each do |action| action_options = action_options_for(action, resource, method) - map.named_route("#{resource.name_prefix}#{action}_#{resource.singular}", "#{resource.member_path};#{action}", action_options) - map.named_route("formatted_#{resource.name_prefix}#{action}_#{resource.singular}", "#{resource.member_path}.:format;#{action}",action_options) + + unless resource.old_name_prefix.blank? + map.deprecated_named_route("#{action}_#{resource.name_prefix}#{resource.singular}", "#{resource.old_name_prefix}#{action}_#{resource.singular}") + map.deprecated_named_route("formatted_#{action}_#{resource.name_prefix}#{resource.singular}", "formatted_#{resource.old_name_prefix}#{action}_#{resource.singular}") + end + + if resource.deprecate_name_prefix? + map.deprecated_named_route("#{action}_#{resource.name_prefix}#{resource.singular}", "#{action}_#{resource.singular}") + map.deprecated_named_route("formatted_#{action}_#{resource.name_prefix}#{resource.singular}", "formatted_#{action}_#{resource.singular}") + end + + map.named_route("#{action}_#{resource.name_prefix}#{resource.singular}", "#{resource.member_path}#{resource.action_separator}#{action}", action_options) + map.connect("#{resource.member_path};#{action}", action_options) + map.connect("#{resource.member_path}.:format;#{action}", action_options) + map.named_route("formatted_#{action}_#{resource.name_prefix}#{resource.singular}", "#{resource.member_path}#{resource.action_separator}#{action}.:format", action_options) + end end @@ -374,6 +454,11 @@ module ActionController map.named_route("#{resource.name_prefix}#{resource.singular}", resource.member_path, show_action_options) map.named_route("formatted_#{resource.name_prefix}#{resource.singular}", "#{resource.member_path}.:format", show_action_options) + if resource.deprecate_name_prefix? + map.deprecated_named_route("#{resource.name_prefix}#{resource.singular}", "#{resource.singular}") + map.deprecated_named_route("formatted_#{resource.name_prefix}#{resource.singular}", "formatted_#{resource.singular}") + end + update_action_options = action_options_for("update", resource) map.connect(resource.member_path, update_action_options) map.connect("#{resource.member_path}.:format", update_action_options) diff --git a/vendor/rails/actionpack/lib/action_controller/routing.rb b/vendor/rails/actionpack/lib/action_controller/routing.rb index b132a80..4568a3f 100644 --- a/vendor/rails/actionpack/lib/action_controller/routing.rb +++ b/vendor/rails/actionpack/lib/action_controller/routing.rb @@ -451,26 +451,17 @@ module ActionController # is given (as an array), only the keys indicated will be used to build # the query string. The query string will correctly build array parameter # values. - def build_query_string(hash, only_keys=nil) + def build_query_string(hash, only_keys = nil) elements = [] - - only_keys ||= hash.keys - - only_keys.each do |key| - value = hash[key] or next - key = CGI.escape key.to_s - if value.class == Array - key << '[]' - else - value = [ value ] - end - value.each { |val| elements << "#{key}=#{CGI.escape(val.to_param.to_s)}" } - end - query_string = "?#{elements.join("&")}" unless elements.empty? - query_string || "" + (only_keys || hash.keys).each do |key| + if value = hash[key] + elements << value.to_query(key) + end + end + elements.empty? ? '' : "?#{elements.sort * '&'}" end - + # Write the real recognition implementation and then resend the message. def recognize(path, environment={}) write_recognition @@ -668,7 +659,7 @@ module ActionController end def extract_value - "#{local_name} = hash[:#{key}] #{"|| #{default.inspect}" if default}" + "#{local_name} = hash[:#{key}] && hash[:#{key}].to_param #{"|| #{default.inspect}" if default}" end def value_check if default # Then we know it won't be nil @@ -989,6 +980,10 @@ module ActionController def named_route(name, path, options = {}) @set.add_named_route(name, path, options) end + + def deprecated_named_route(name, deprecated_name, options = {}) + @set.add_deprecated_named_route(name, deprecated_name) + end # Added deprecation notice for anyone who already added a named route called "root". # It'll be used as a shortcut for map.connect '' in Rails 2.0. @@ -1019,7 +1014,7 @@ module ActionController def clear! @routes = {} @helpers = [] - + @module ||= Module.new @module.instance_methods.each do |selector| @module.send :remove_method, selector @@ -1055,6 +1050,38 @@ module ActionController def install(destinations = [ActionController::Base, ActionView::Base]) Array(destinations).each { |dest| dest.send :include, @module } end + + def define_deprecated_named_route_methods(name, deprecated_name) + + [:url, :path].each do |kind| + @module.send :module_eval, <<-end_eval # We use module_eval to avoid leaks + + def #{url_helper_name(deprecated_name, kind)}(*args) + + ActiveSupport::Deprecation.warn( + 'The named route "#{url_helper_name(deprecated_name, kind)}" uses a format that has been deprecated. ' + + 'You should use "#{url_helper_name(name, kind)}" instead.', caller + ) + + send :#{url_helper_name(name, kind)}, *args + + end + + def #{hash_access_name(deprecated_name, kind)}(*args) + + ActiveSupport::Deprecation.warn( + 'The named route "#{hash_access_name(deprecated_name, kind)}" uses a format that has been deprecated. ' + + 'You should use "#{hash_access_name(name, kind)}" instead.', caller + ) + + send :#{hash_access_name(name, kind)}, *args + + end + + end_eval + end + + end private def url_helper_name(name, kind = :url) @@ -1177,6 +1204,10 @@ module ActionController def add_named_route(name, path, options = {}) named_routes[name] = add_route(path, options) end + + def add_deprecated_named_route(name, deprecated_name) + named_routes.define_deprecated_named_route_methods(name, deprecated_name) + end def options_as_params(options) # If an explicit :controller was given, always make :action explicit @@ -1190,10 +1221,9 @@ module ActionController # # great fun, eh? - options_as_params = options[:controller] ? { :action => "index" } : {} - options.each do |k, value| - options_as_params[k] = value.to_param - end + options_as_params = options.clone + options_as_params[:action] ||= 'index' if options[:controller] + options_as_params[:action] = options_as_params[:action].to_s if options_as_params[:action] options_as_params end @@ -1224,6 +1254,9 @@ module ActionController options = options_as_params(options) expire_on = build_expiry(options, recall) + if options[:controller] + options[:controller] = options[:controller].to_s + end # if the controller has changed, make sure it changes relative to the # current controller module, if any. In other words, if we're currently # on admin/get, and the new controller is 'set', the new controller diff --git a/vendor/rails/actionpack/lib/action_controller/session/drb_server.rb b/vendor/rails/actionpack/lib/action_controller/session/drb_server.rb index 6f90db6..2ac1369 100644 --- a/vendor/rails/actionpack/lib/action_controller/session/drb_server.rb +++ b/vendor/rails/actionpack/lib/action_controller/session/drb_server.rb @@ -1,3 +1,5 @@ +#!/usr/bin/ruby -w + #!/usr/local/bin/ruby -w # This is a really simple session storage daemon, basically just a hash, diff --git a/vendor/rails/actionpack/lib/action_controller/test_process.rb b/vendor/rails/actionpack/lib/action_controller/test_process.rb index 4011e6c..79eb0e1 100644 --- a/vendor/rails/actionpack/lib/action_controller/test_process.rb +++ b/vendor/rails/actionpack/lib/action_controller/test_process.rb @@ -24,6 +24,7 @@ module ActionController #:nodoc: attr_accessor :cookies, :session_options attr_accessor :query_parameters, :request_parameters, :path, :session, :env attr_accessor :host + attr_reader :request_uri_overridden def initialize(query_parameters = nil, request_parameters = nil, session = nil) @query_parameters = query_parameters || {} @@ -67,12 +68,14 @@ module ActionController #:nodoc: # Used to check AbstractRequest's request_uri functionality. # Disables the use of @path and @request_uri so superclass can handle those. def set_REQUEST_URI(value) + @request_uri_overridden = true @env["REQUEST_URI"] = value @request_uri = nil @path = nil end def request_uri=(uri) + @env["REQUEST_URI"] = uri @request_uri = uri @path = uri.split("?").first end @@ -426,12 +429,12 @@ module ActionController #:nodoc: end def build_request_uri(action, parameters) - unless @request.env['REQUEST_URI'] + unless @request.request_uri_overridden options = @controller.send(:rewrite_options, parameters) options.update(:only_path => true, :action => action) url = ActionController::UrlRewriter.new(@request, parameters) - @request.set_REQUEST_URI(url.rewrite(options)) + @request.request_uri = url.rewrite(options) end end diff --git a/vendor/rails/actionpack/lib/action_controller/url_rewriter.rb b/vendor/rails/actionpack/lib/action_controller/url_rewriter.rb index 0a5aab1..029f5ea 100644 --- a/vendor/rails/actionpack/lib/action_controller/url_rewriter.rb +++ b/vendor/rails/actionpack/lib/action_controller/url_rewriter.rb @@ -52,8 +52,9 @@ module ActionController # Delete the unused options to prevent their appearance in the query string [:protocol, :host, :port].each { |k| options.delete k } end + anchor = "##{options.delete(:anchor)}" if options.key?(:anchor) url << Routing::Routes.generate(options, {}) - return url + return "#{url}#{anchor}" end end @@ -76,6 +77,7 @@ module ActionController alias_method :to_s, :to_str private + # Given a path and options, returns a rewritten URL string def rewrite_url(path, options) rewritten_url = "" unless options[:only_path] @@ -91,6 +93,7 @@ module ActionController rewritten_url end + # Given a Hash of options, generates a route def rewrite_path(options) options = options.symbolize_keys options.update(options[:params].symbolize_keys) if options[:params] diff --git a/vendor/rails/actionpack/lib/action_controller/verification.rb b/vendor/rails/actionpack/lib/action_controller/verification.rb index 7cdf658..131131a 100644 --- a/vendor/rails/actionpack/lib/action_controller/verification.rb +++ b/vendor/rails/actionpack/lib/action_controller/verification.rb @@ -95,6 +95,7 @@ module ActionController #:nodoc: response.headers.update(options[:add_headers]) if options[:add_headers] unless performed? render(options[:render]) if options[:render] + options[:redirect_to] = self.send(options[:redirect_to]) if options[:redirect_to].is_a? Symbol redirect_to(options[:redirect_to]) if options[:redirect_to] end return false diff --git a/vendor/rails/actionpack/lib/action_pack/version.rb b/vendor/rails/actionpack/lib/action_pack/version.rb index 09eaef6..213ddb7 100644 --- a/vendor/rails/actionpack/lib/action_pack/version.rb +++ b/vendor/rails/actionpack/lib/action_pack/version.rb @@ -2,7 +2,7 @@ module ActionPack #:nodoc: module VERSION #:nodoc: MAJOR = 1 MINOR = 13 - TINY = 3 + TINY = 6 STRING = [MAJOR, MINOR, TINY].join('.') end diff --git a/vendor/rails/actionpack/lib/action_view/base.rb b/vendor/rails/actionpack/lib/action_view/base.rb index e0bd591..1e4fd62 100644 --- a/vendor/rails/actionpack/lib/action_view/base.rb +++ b/vendor/rails/actionpack/lib/action_view/base.rb @@ -148,7 +148,7 @@ module ActionView #:nodoc: # # This refreshes the sidebar, removes a person element and highlights the user list. # - # See the ActionView::Helpers::PrototypeHelper::JavaScriptGenerator documentation for more details. + # See the ActionView::Helpers::PrototypeHelper::GeneratorMethods documentation for more details. class Base include ERB::Util @@ -160,7 +160,7 @@ module ActionView #:nodoc: attr_internal *ActionController::Base::DEPRECATED_INSTANCE_VARIABLES # Specify trim mode for the ERB compiler. Defaults to '-'. - # See ERB documentation for suitable values. + # See ERb documentation for suitable values. @@erb_trim_mode = '-' cattr_accessor :erb_trim_mode @@ -191,17 +191,17 @@ module ActionView #:nodoc: end include CompiledTemplates - # maps inline templates to their method names + # Maps inline templates to their method names @@method_names = {} - # map method names to their compile time + # Map method names to their compile time @@compile_time = {} - # map method names to the names passed in local assigns so far + # Map method names to the names passed in local assigns so far @@template_args = {} - # count the number of inline templates + # Count the number of inline templates @@inline_template_count = 0 - # maps template paths without extension to their file extension returned by pick_template_extension. - # if for a given path, path.ext1 and path.ext2 exist on the file system, the order of extensions - # used by pick_template_extension determines whether ext1 or ext2 will be stored + # Maps template paths without extension to their file extension returned by pick_template_extension. + # If for a given path, path.ext1 and path.ext2 exist on the file system, the order of extensions + # used by pick_template_extension determines whether ext1 or ext2 will be stored. @@cached_template_extension = {} class ObjectWrapper < Struct.new(:value) #:nodoc: @@ -305,7 +305,6 @@ module ActionView #:nodoc: # Render the provided template with the given local assigns. If the template has not been rendered with the provided # local assigns yet, or if the template has been updated on disk, then the template will be compiled to a method. # - # Either, but not both, of template and file_path may be nil. If file_path is given, the template # will only be read if it has to be compiled. # @@ -371,10 +370,12 @@ module ActionView #:nodoc: end private + # Builds a string holding the full path of the template including extension def full_template_path(template_path, extension) "#{@base_path}/#{template_path}.#{extension}" end + # Asserts the existence of a template. def template_exists?(template_path, extension) file_path = full_template_path(template_path, extension) @@method_names.has_key?(file_path) || FileTest.exists?(file_path) @@ -389,6 +390,7 @@ module ActionView #:nodoc: @@cache_template_extensions && @@cached_template_extension[template_path] end + # Determines the template's file extension, such as rhtml, rxml, or rjs. def find_template_extension_for(template_path) if match = delegate_template_exists?(template_path) match.first.to_sym @@ -405,6 +407,7 @@ module ActionView #:nodoc: File.read(template_path) end + # Evaluate the local assigns and pushes them to the view. def evaluate_assigns unless @assigns_added assign_variables_from_controller @@ -416,6 +419,7 @@ module ActionView #:nodoc: handler.new(self).render(template, local_assigns) end + # Assigns instance variables from the controller to the view. def assign_variables_from_controller @assigns.each { |key, value| instance_variable_set("@#{key}", value) } end @@ -427,10 +431,10 @@ module ActionView #:nodoc: ((args = @@template_args[render_symbol]) && local_assigns.all? { |k,_| args.has_key?(k) }) end - # Check whether compilation is necessary. - # Compile if the inline template or file has not been compiled yet. - # Or if local_assigns has a new key, which isn't supported by the compiled code yet. - # Or if the file has changed on disk and checking file mods hasn't been disabled. + # Method to check whether template compilation is necessary. + # The template will be compiled if the inline template or file has not been compiled yet, + # if local_assigns has a new key, which isn't supported by the compiled code yet, + # or if the file has changed on disk and checking file mods hasn't been disabled. def compile_template?(template, file_name, local_assigns) method_key = file_name || template render_symbol = @@method_names[method_key] @@ -445,14 +449,15 @@ module ActionView #:nodoc: end end - # Create source code for given template + # Method to create the source code for a given template. def create_template_source(extension, template, render_symbol, locals) if template_requires_setup?(extension) body = case extension.to_sym when :rxml "controller.response.content_type ||= 'application/xml'\n" + - "xml = Builder::XmlMarkup.new(:indent => 2)\n" + - template + "xml ||= Builder::XmlMarkup.new(:indent => 2)\n" + + template + + "\nxml.target!\n" when :rjs "controller.response.content_type ||= 'text/javascript'\n" + "update_page do |page|\n#{template}\nend" @@ -473,11 +478,11 @@ module ActionView #:nodoc: "def #{render_symbol}(local_assigns)\n#{locals_code}#{body}\nend" end - def template_requires_setup?(extension) + def template_requires_setup?(extension) #:nodoc: templates_requiring_setup.include? extension.to_s end - def templates_requiring_setup + def templates_requiring_setup #:nodoc: %w(rxml rjs) end @@ -501,6 +506,7 @@ module ActionView #:nodoc: end end + # Compile and evaluate the template's code def compile_template(extension, template, file_name, local_assigns) render_symbol = assign_method_name(extension, template, file_name) render_source = create_template_source(extension, template, render_symbol, local_assigns.keys) diff --git a/vendor/rails/actionpack/lib/action_view/compiled_templates.rb b/vendor/rails/actionpack/lib/action_view/compiled_templates.rb index deb730f..73cce12 100644 --- a/vendor/rails/actionpack/lib/action_view/compiled_templates.rb +++ b/vendor/rails/actionpack/lib/action_view/compiled_templates.rb @@ -3,14 +3,14 @@ module ActionView # CompiledTemplates modules hold methods that have been compiled. # Templates are compiled into these methods so that they do not need to be - # re-read and re-parsed each request. + # read and parsed for each request. # # Each template may be compiled into one or more methods. Each method accepts a given # set of parameters which is used to implement local assigns passing. # # To use a compiled template module, create a new instance and include it into the class # in which you want the template to be rendered. - class CompiledTemplates < Module #:nodoc: + class CompiledTemplates < Module attr_reader :method_names def initialize diff --git a/vendor/rails/actionpack/lib/action_view/helpers/active_record_helper.rb b/vendor/rails/actionpack/lib/action_view/helpers/active_record_helper.rb index 33eaa13..a19ee51 100644 --- a/vendor/rails/actionpack/lib/action_view/helpers/active_record_helper.rb +++ b/vendor/rails/actionpack/lib/action_view/helpers/active_record_helper.rb @@ -13,17 +13,18 @@ module ActionView # is a great of making the record quickly available for editing, but likely to prove lackluster for a complicated real-world form. # In that case, it's better to use the input method and the specialized form methods in link:classes/ActionView/Helpers/FormHelper.html module ActiveRecordHelper - # Returns a default input tag for the type of object returned by the method. Example - # (title is a VARCHAR column and holds "Hello World"): + # Returns a default input tag for the type of object returned by the method. For example, let's say you have a model + # that has an attribute +title+ of type VARCHAR column, and this instance holds "Hello World": # input("post", "title") => # def input(record_name, method, options = {}) InstanceTag.new(record_name, method, self).to_tag(options) end - # Returns an entire form with input tags and everything for a specified Active Record object. Example - # (post is a new record that has a title using VARCHAR and a body using TEXT): - # form("post") => + # Returns an entire form with all needed input tags for a specified Active Record object. For example, let's say you + # have a table model Post with attributes named title of type VARCHAR and body of type TEXT: + # form("post") + # That line would yield a form like the following: #
#

#
@@ -32,14 +33,13 @@ module ActionView #

#
# #

# #
# # It's possible to specialize the form builder by using a different action name and by supplying another - # block renderer. Example (entry is a new record that has a message attribute using VARCHAR): + # block renderer. For example, let's say you have a model Entry with an attribute message of type VARCHAR: # # form("entry", :action => "sign", :input_block => # Proc.new { |record, column| "#{column.human_name}: #{input(record, column.name)}
" }) => @@ -74,16 +74,16 @@ module ActionView content_tag('form', contents, :action => action, :method => 'post', :enctype => options[:multipart] ? 'multipart/form-data': nil) end - # Returns a string containing the error message attached to the +method+ on the +object+, if one exists. - # This error message is wrapped in a DIV tag, which can be specialized to include both a +prepend_text+ and +append_text+ - # to properly introduce the error and a +css_class+ to style it accordingly. Examples (post has an error message - # "can't be empty" on the title attribute): + # Returns a string containing the error message attached to the +method+ on the +object+ if one exists. + # This error message is wrapped in a DIV tag, which can be extended to include a +prepend_text+ and/or +append_text+ + # (to properly explain the error), and a +css_class+ to style it accordingly. As an example, let's say you have a model + # +post+ that has an error message on the +title+ attribute: # # <%= error_message_on "post", "title" %> => #
can't be empty
# - # <%= error_message_on "post", "title", "Title simply ", " (or it won't work)", "inputError" %> => - #
Title simply can't be empty (or it won't work)
+ # <%= error_message_on "post", "title", "Title simply ", " (or it won't work).", "inputError" %> => + #
Title simply can't be empty (or it won't work).
def error_message_on(object, method, prepend_text = "", append_text = "", css_class = "formError") if (obj = instance_variable_get("@#{object}")) && (errors = obj.errors.on(method)) content_tag("div", "#{prepend_text}#{errors.is_a?(Array) ? errors.first : errors}#{append_text}", :class => css_class) @@ -92,11 +92,11 @@ module ActionView end end - # Returns a string with a div containing all of the error messages for the objects located as instance variables by the names + # Returns a string with a DIV containing all of the error messages for the objects located as instance variables by the names # given. If more than one object is specified, the errors for the objects are displayed in the order that the object names are # provided. # - # This div can be tailored by the following options: + # This DIV can be tailored by the following options: # # * header_tag - Used for the header of the error div (default: h2) # * id - The id of the error div (default: errorExplanation) @@ -105,12 +105,12 @@ module ActionView # any text that you prefer. If object_name is not set, the name of # the first object will be used. # - # Specifying one object: + # To specify the display for one object, you simply provide its name as a parameter. For example, for the +User+ model: # # error_messages_for 'user' # - # Specifying more than one object (and using the name 'user' in the - # header as the object_name instead of 'user_common'): + # To specify more than one object, you simply list them; optionally, you can add an extra +object_name+ parameter, which + # be the name in the header. # # error_messages_for 'user_common', 'user', :object_name => 'user' # diff --git a/vendor/rails/actionpack/lib/action_view/helpers/debug_helper.rb b/vendor/rails/actionpack/lib/action_view/helpers/debug_helper.rb index 9e92813..ef089c1 100644 --- a/vendor/rails/actionpack/lib/action_view/helpers/debug_helper.rb +++ b/vendor/rails/actionpack/lib/action_view/helpers/debug_helper.rb @@ -3,6 +3,16 @@ module ActionView # Provides a set of methods for making it easier to locate problems. module DebugHelper # Returns a
-tag set with the +object+ dumped by YAML. Very readable way to inspect an object.
+      #  my_hash = {'first' => 1, 'second' => 'two', 'third' => [1,2,3]}
+      #  debug(my_hash)
+      #  => 
--- 
+      #  first: 1
+      #  second: two
+      #  third: 
+      #  - 1
+      #  - 2
+      #  - 3
+      #  
def debug(object) begin Marshal::dump(object) diff --git a/vendor/rails/actionpack/lib/action_view/helpers/deprecated_helper.rb b/vendor/rails/actionpack/lib/action_view/helpers/deprecated_helper.rb index 04392f5..81f26df 100644 --- a/vendor/rails/actionpack/lib/action_view/helpers/deprecated_helper.rb +++ b/vendor/rails/actionpack/lib/action_view/helpers/deprecated_helper.rb @@ -2,6 +2,9 @@ module ActionView module Helpers module PrototypeHelper + # Method to execute an element update using Prototype. + # DEPRECATION WARNING: This helper has been depercated; use RJS instead. + # See ActionView::Helpers::PrototypeHelper::JavaScriptGenerator::GeneratorMethods for more information. def update_element_function(element_id, options = {}, &block) content = escape_javascript(options[:content] || '') content = escape_javascript(capture(&block)) if block diff --git a/vendor/rails/actionpack/lib/action_view/helpers/prototype_helper.rb b/vendor/rails/actionpack/lib/action_view/helpers/prototype_helper.rb index 71fe29d..988d246 100644 --- a/vendor/rails/actionpack/lib/action_view/helpers/prototype_helper.rb +++ b/vendor/rails/actionpack/lib/action_view/helpers/prototype_helper.rb @@ -250,8 +250,10 @@ module ActionView return function end - # Observes the field with the DOM ID specified by +field_id+ and makes - # an Ajax call when its contents have changed. + # Observes the field with the DOM ID specified by +field_id+ and calls a + # callback when its contents have changed. The default callback is an + # Ajax call. By default the value of the observed field is sent as a + # parameter with the Ajax call. # # Required +options+ are either of: # :url:: +url_for+-style options for the action to call @@ -268,14 +270,24 @@ module ActionView # :update:: Specifies the DOM ID of the element whose # innerHTML should be updated with the # XMLHttpRequest response text. - # :with:: A JavaScript expression specifying the - # parameters for the XMLHttpRequest. This defaults - # to 'value', which in the evaluated context - # refers to the new field value. If you specify a - # string without a "=", it'll be extended to mean - # the form key that the value should be assigned to. - # So :with => "term" gives "'term'=value". If a "=" is - # present, no extension will happen. + # :with:: A JavaScript expression specifying the parameters + # for the XMLHttpRequest. The default is to send the + # key and value of the observed field. Any custom + # expressions should return a valid URL query string. + # The value of the field is stored in the JavaScript + # variable +value+. + # + # Examples + # + # :with => "'my_custom_key=' + value" + # :with => "'person[name]=' + prompt('New name')" + # :with => "Form.Element.serialize('other-field')" + # + # Finally + # :with => 'name' + # is shorthand for + # :with => "'name=' + value" + # This essentially just changes the key of the parameter. # :on:: Specifies which event handler to observe. By default, # it's set to "changed" for text fields and areas and # "click" for radio buttons and checkboxes. With this, @@ -291,11 +303,15 @@ module ActionView build_observer('Form.Element.EventObserver', field_id, options) end end - - # Like +observe_field+, but operates on an entire form identified by the - # DOM ID +form_id+. +options+ are the same as +observe_field+, except - # the default value of the :with option evaluates to the - # serialized (request string) value of the form. + + # Observes the form with the DOM ID specified by +form_id+ and calls a + # callback when its contents have changed. The default callback is an + # Ajax call. By default all fields of the observed field are sent as + # parameters with the Ajax call. + # + # The +options+ for +observe_form+ are the same as the options for + # +observe_field+. The JavaScript variable +value+ available to the + # :with option is set to the serialized form by default. def observe_form(form_id, options = {}) if options[:frequency] build_observer('Form.Observer', form_id, options) @@ -660,10 +676,10 @@ module ActionView end def build_observer(klass, name, options = {}) - if options[:with] && !options[:with].include?("=") + if options[:with] && (options[:with] !~ /[=(.]/) options[:with] = "'#{options[:with]}=' + value" else - options[:with] ||= 'value' if options[:update] + options[:with] ||= 'value' unless options[:function] end callback = options[:function] || remote_function(options) diff --git a/vendor/rails/actionpack/test/activerecord/pagination_test.rb b/vendor/rails/actionpack/test/activerecord/pagination_test.rb index ddd2cec..5e2fb8e 100644 --- a/vendor/rails/actionpack/test/activerecord/pagination_test.rb +++ b/vendor/rails/actionpack/test/activerecord/pagination_test.rb @@ -5,6 +5,8 @@ class PaginationTest < ActiveRecordTestCase class PaginationController < ActionController::Base self.template_root = "#{File.dirname(__FILE__)}/../fixtures/" + + around_filter :silence_deprecation_warnings def simple_paginate @topic_pages, @topics = paginate(:topics) @@ -67,6 +69,13 @@ class PaginationTest < ActiveRecordTestCase :count => "d.id") render :nothing => true end + + + def silence_deprecation_warnings + ActiveSupport::Deprecation.silence do + yield + end + end def rescue_errors(e) raise e end diff --git a/vendor/rails/actionpack/test/controller/action_pack_assertions_test.rb b/vendor/rails/actionpack/test/controller/action_pack_assertions_test.rb index 5489f52..e7c229d 100644 --- a/vendor/rails/actionpack/test/controller/action_pack_assertions_test.rb +++ b/vendor/rails/actionpack/test/controller/action_pack_assertions_test.rb @@ -19,6 +19,8 @@ class ActionPackAssertionsController < ActionController::Base def redirect_to_controller() redirect_to :controller => "elsewhere", :action => "flash_me"; end + def redirect_to_controller_with_symbol() redirect_to :controller => :elsewhere, :action => :flash_me; end + def redirect_to_path() redirect_to '/some/path' end def redirect_to_named_route() redirect_to route_one_url end @@ -555,6 +557,17 @@ class ActionPackAssertionsControllerTest < Test::Unit::TestCase assert_redirected_to 'http://test.host/some/path' end + def test_assert_redirection_with_symbol + process :redirect_to_controller_with_symbol + assert_nothing_raised { + assert_redirected_to :controller => "elsewhere", :action => "flash_me" + } + process :redirect_to_controller_with_symbol + assert_nothing_raised { + assert_redirected_to :controller => :elsewhere, :action => :flash_me + } + end + def test_redirected_to_with_nested_controller @controller = Admin::InnerModuleController.new get :redirect_to_absolute_controller diff --git a/vendor/rails/actionpack/test/controller/addresses_render_test.rb b/vendor/rails/actionpack/test/controller/addresses_render_test.rb index 4de1c80..f329b2d 100644 --- a/vendor/rails/actionpack/test/controller/addresses_render_test.rb +++ b/vendor/rails/actionpack/test/controller/addresses_render_test.rb @@ -39,7 +39,10 @@ class AddressesTest < Test::Unit::TestCase end def test_list - get :list + # because pagination is deprecated + ActiveSupport::Deprecation.silence do + get :list + end assert_equal "We only need to get this far!", @response.body.chomp end end diff --git a/vendor/rails/actionpack/test/controller/base_test.rb b/vendor/rails/actionpack/test/controller/base_test.rb index bcc4732..1d04b8b 100644 --- a/vendor/rails/actionpack/test/controller/base_test.rb +++ b/vendor/rails/actionpack/test/controller/base_test.rb @@ -88,7 +88,7 @@ class ControllerInstanceTests < Test::Unit::TestCase # Mocha adds methods to Object which are then included in the public_instance_methods # This method hides those from the controller so the above tests won't know the difference def hide_mocha_methods_from_controller(controller) - mocha_methods = [:expects, :metaclass, :mocha, :mocha_inspect, :reset_mocha, :stubba_object, :stubba_method, :stubs, :verify] + mocha_methods = [:expects, :metaclass, :mocha, :mocha_inspect, :reset_mocha, :stubba_object, :stubba_method, :stubs, :verify, :__is_a__, :__metaclass__] controller.class.send(:hide_action, *mocha_methods) end diff --git a/vendor/rails/actionpack/test/controller/caching_test.rb b/vendor/rails/actionpack/test/controller/caching_test.rb index 07e1689..9cc6d0c 100644 --- a/vendor/rails/actionpack/test/controller/caching_test.rb +++ b/vendor/rails/actionpack/test/controller/caching_test.rb @@ -97,6 +97,7 @@ class ActionCachingTestController < ActionController::Base caches_action :index def index + sleep 0.01 @cache_this = Time.now.to_f.to_s render :text => @cache_this end @@ -195,7 +196,7 @@ class ActionCacheTest < Test::Unit::TestCase def test_xml_version_of_resource_is_treated_as_different_cache @mock_controller.mock_url_for = 'http://example.org/posts/' @mock_controller.mock_path = '/posts/index.xml' - path_object = @path_class.new(@mock_controller) + path_object = @path_class.new(@mock_controller, {}) assert_equal 'xml', path_object.extension assert_equal 'example.org/posts/index.xml', path_object.path end @@ -204,7 +205,7 @@ class ActionCacheTest < Test::Unit::TestCase @mock_controller.mock_url_for = 'http://example.org/' @mock_controller.mock_path = '/' - assert_equal 'example.org/index', @path_class.path_for(@mock_controller) + assert_equal 'example.org/index', @path_class.path_for(@mock_controller, {}) end def test_file_extensions diff --git a/vendor/rails/actionpack/test/controller/cookie_test.rb b/vendor/rails/actionpack/test/controller/cookie_test.rb index 5bab99f..34ebbc8 100644 --- a/vendor/rails/actionpack/test/controller/cookie_test.rb +++ b/vendor/rails/actionpack/test/controller/cookie_test.rb @@ -22,7 +22,7 @@ class CookieTest < Test::Unit::TestCase cookies["user_name"] = { "value" => "david", "expires" => Time.local(2005, 10, 10) } cookies["login"] = "XJ-122" end - + def access_frozen_cookies cookies["will"] = "work" end @@ -31,6 +31,11 @@ class CookieTest < Test::Unit::TestCase cookies.delete("user_name") end + def delete_cookie_with_path + cookies.delete("user_name", :path => '/beaten') + render_text "hello world" + end + def rescue_action(e) raise unless ActionController::MissingTemplate # No templates here, and we don't care about the output end @@ -85,4 +90,18 @@ class CookieTest < Test::Unit::TestCase assert_equal "david", jar["user_name"] assert_equal nil, jar["something_else"] end + + def test_cookiejar_accessor_with_array_value + a = %w{1 2 3} + @request.cookies["pages"] = CGI::Cookie.new("name" => "pages", "value" => a, "expires" => Time.local(2025, 10, 10)) + @controller.request = @request + jar = ActionController::CookieJar.new(@controller) + assert_equal a, jar["pages"] + end + + def test_delete_cookie_with_path + get :delete_cookie_with_path + assert_equal "/beaten", @response.headers["cookie"].first.path + assert_not_equal "/", @response.headers["cookie"].first.path + end end diff --git a/vendor/rails/actionpack/test/controller/deprecation/deprecated_base_methods_test.rb b/vendor/rails/actionpack/test/controller/deprecation/deprecated_base_methods_test.rb index d8da676..3b21074 100644 --- a/vendor/rails/actionpack/test/controller/deprecation/deprecated_base_methods_test.rb +++ b/vendor/rails/actionpack/test/controller/deprecation/deprecated_base_methods_test.rb @@ -1,6 +1,12 @@ require File.dirname(__FILE__) + '/../../abstract_unit' class DeprecatedBaseMethodsTest < Test::Unit::TestCase + # ActiveRecord model mock to test pagination deprecation + class DummyModel + def self.find(*args) [] end + def self.count(*args) 0 end + end + class Target < ActionController::Base def deprecated_symbol_parameter_to_url_for redirect_to(url_for(:home_url, "superstars")) @@ -18,6 +24,11 @@ class DeprecatedBaseMethodsTest < Test::Unit::TestCase this_method_doesnt_exist end + def pagination + paginate :dummy_models, :class_name => 'DeprecatedBaseMethodsTest::DummyModel' + render :nothing => true + end + def rescue_action(e) raise e end end @@ -27,6 +38,7 @@ class DeprecatedBaseMethodsTest < Test::Unit::TestCase @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new @controller = Target.new + @controller.logger = Logger.new(nil) unless @controller.logger end def test_deprecated_symbol_parameter_to_url_for @@ -57,4 +69,10 @@ class DeprecatedBaseMethodsTest < Test::Unit::TestCase error = Test::Unit::Error.new('testing ur doodz', e) assert_not_deprecated { error.message } end + + def test_pagination_deprecation + assert_deprecated('svn://errtheblog.com/svn/plugins/classic_pagination') do + get :pagination + end + end end diff --git a/vendor/rails/actionpack/test/controller/filter_params_test.rb b/vendor/rails/actionpack/test/controller/filter_params_test.rb index 5ad0d7f..7b810b1 100644 --- a/vendor/rails/actionpack/test/controller/filter_params_test.rb +++ b/vendor/rails/actionpack/test/controller/filter_params_test.rb @@ -16,6 +16,7 @@ class FilterParamTest < Test::Unit::TestCase assert @controller.respond_to?(:filter_parameters) test_hashes = [[{},{},[]], + [{'foo'=>nil},{'foo'=>nil},[]], [{'foo'=>'bar'},{'foo'=>'bar'},[]], [{'foo'=>'bar'},{'foo'=>'bar'},%w'food'], [{'foo'=>'bar'},{'foo'=>'[FILTERED]'},%w'foo'], diff --git a/vendor/rails/actionpack/test/controller/filters_test.rb b/vendor/rails/actionpack/test/controller/filters_test.rb index 3a74eba..3133096 100644 --- a/vendor/rails/actionpack/test/controller/filters_test.rb +++ b/vendor/rails/actionpack/test/controller/filters_test.rb @@ -14,7 +14,7 @@ class FilterTest < Test::Unit::TestCase @ran_filter ||= [] @ran_filter << "ensure_login" end - + def clean_up @ran_after_filter ||= [] @ran_after_filter << "clean_up" @@ -62,7 +62,7 @@ class FilterTest < Test::Unit::TestCase render :inline => "something else" end end - + class ConditionalFilterController < ActionController::Base def show render :inline => "ran action" @@ -86,7 +86,7 @@ class FilterTest < Test::Unit::TestCase @ran_filter ||= [] @ran_filter << "clean_up_tmp" end - + def rescue_action(e) raise(e) end end @@ -94,7 +94,7 @@ class FilterTest < Test::Unit::TestCase before_filter :ensure_login, :except => [ :show_without_filter, :another_action ] end - class OnlyConditionSymController < ConditionalFilterController + class OnlyConditionSymController < ConditionalFilterController before_filter :ensure_login, :only => :show end @@ -104,10 +104,10 @@ class FilterTest < Test::Unit::TestCase class BeforeAndAfterConditionController < ConditionalFilterController before_filter :ensure_login, :only => :show - after_filter :clean_up_tmp, :only => :show + after_filter :clean_up_tmp, :only => :show end - - class OnlyConditionProcController < ConditionalFilterController + + class OnlyConditionProcController < ConditionalFilterController before_filter(:only => :show) {|c| c.assigns["ran_proc_filter"] = true } end @@ -131,6 +131,14 @@ class FilterTest < Test::Unit::TestCase 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} end + class EmptyFilterChainController < TestController + self.filter_chain.clear + def show + @action_executed = true + render :text => "yawp!" + end + end + class PrependingController < TestController prepend_before_filter :wonderful_life # skip_before_filter :fire_flash @@ -145,7 +153,7 @@ class FilterTest < Test::Unit::TestCase class ConditionalSkippingController < TestController skip_before_filter :ensure_login, :only => [ :login ] skip_after_filter :clean_up, :only => [ :login ] - + before_filter :find_user, :only => [ :change_password ] def login @@ -155,7 +163,7 @@ class FilterTest < Test::Unit::TestCase def change_password render :inline => "ran action" end - + protected def find_user @ran_filter ||= [] @@ -166,15 +174,15 @@ class FilterTest < Test::Unit::TestCase class ConditionalParentOfConditionalSkippingController < ConditionalFilterController before_filter :conditional_in_parent, :only => [:show, :another_action] after_filter :conditional_in_parent, :only => [:show, :another_action] - + private - + def conditional_in_parent @ran_filter ||= [] @ran_filter << 'conditional_in_parent' end end - + class ChildOfConditionalParentController < ConditionalParentOfConditionalSkippingController skip_before_filter :conditional_in_parent, :only => :another_action skip_after_filter :conditional_in_parent, :only => :another_action @@ -197,7 +205,7 @@ class FilterTest < Test::Unit::TestCase controller.assigns["was_audited"] = true end end - + class AroundFilter def before(controller) @execution_log = "before" @@ -209,7 +217,7 @@ class FilterTest < Test::Unit::TestCase controller.assigns["execution_log"] = @execution_log + " and after" controller.assigns["after_ran"] = true controller.class.execution_log << " after aroundfilter " if controller.respond_to? :execution_log - end + end end class AppendedAroundFilter @@ -219,12 +227,12 @@ class FilterTest < Test::Unit::TestCase def after(controller) controller.class.execution_log << " after appended aroundfilter " - end - end - + end + end + class AuditController < ActionController::Base before_filter(AuditFilter) - + def show render_text "hello" end @@ -234,6 +242,14 @@ class FilterTest < Test::Unit::TestCase around_filter AroundFilter.new end + class BeforeAfterClassFilterController < PrependingController + begin + filter = AroundFilter.new + before_filter filter + after_filter filter + end + end + class MixedFilterController < PrependingController cattr_accessor :execution_log @@ -247,7 +263,7 @@ class FilterTest < Test::Unit::TestCase after_filter { |c| c.class.execution_log << " after procfilter " } append_around_filter AppendedAroundFilter.new end - + class MixedSpecializationController < ActionController::Base class OutOfOrder < StandardError; end @@ -285,6 +301,101 @@ class FilterTest < Test::Unit::TestCase end end + class PrependingBeforeAndAfterController < ActionController::Base + prepend_before_filter :before_all + prepend_after_filter :after_all + before_filter :between_before_all_and_after_all + + def before_all + @ran_filter ||= [] + @ran_filter << 'before_all' + end + + def after_all + @ran_filter ||= [] + @ran_filter << 'after_all' + end + + def between_before_all_and_after_all + @ran_filter ||= [] + @ran_filter << 'between_before_all_and_after_all' + end + def show + render :text => 'hello' + end + end + + class NonYieldingAroundFilterController < ActionController::Base + + before_filter :filter_one + around_filter :non_yielding_filter + before_filter :filter_two + after_filter :filter_three + + def index + render :inline => "index" + end + + #make sure the controller complains + def rescue_action(e); raise e; end + + private + + def filter_one + @filters ||= [] + @filters << "filter_one" + end + + def filter_two + @filters << "filter_two" + end + + def non_yielding_filter + @filters << "zomg it didn't yield" + @filter_return_value + end + + def filter_three + @filters << "filter_three" + end + + end + + def test_non_yielding_around_filters_not_returning_false_do_not_raise + controller = NonYieldingAroundFilterController.new + controller.instance_variable_set "@filter_return_value", true + assert_nothing_raised do + test_process(controller, "index") + end + end + + def test_non_yielding_around_filters_returning_false_do_not_raise + controller = NonYieldingAroundFilterController.new + controller.instance_variable_set "@filter_return_value", false + assert_nothing_raised do + test_process(controller, "index") + end + end + + def test_after_filters_are_not_run_if_around_filter_returns_false + controller = NonYieldingAroundFilterController.new + controller.instance_variable_set "@filter_return_value", false + test_process(controller, "index") + assert_equal ["filter_one", "zomg it didn't yield"], controller.assigns['filters'] + end + + def test_after_filters_are_not_run_if_around_filter_does_not_yield + controller = NonYieldingAroundFilterController.new + controller.instance_variable_set "@filter_return_value", true + test_process(controller, "index") + assert_equal ["filter_one", "zomg it didn't yield"], controller.assigns['filters'] + end + + def test_empty_filter_chain + assert_equal 0, EmptyFilterChainController.filter_chain.size + assert test_process(EmptyFilterChainController).template.assigns['action_executed'] + end + def test_added_filter_to_inheritance_graph assert_equal [ :ensure_login ], TestController.before_filters end @@ -292,11 +403,11 @@ class FilterTest < Test::Unit::TestCase def test_base_class_in_isolation assert_equal [ ], ActionController::Base.before_filters end - + def test_prepending_filter assert_equal [ :wonderful_life, :ensure_login ], PrependingController.before_filters end - + def test_running_filters assert_equal %w( wonderful_life ensure_login ), test_process(PrependingController).template.assigns["ran_filter"] end @@ -304,11 +415,11 @@ class FilterTest < Test::Unit::TestCase def test_running_filters_with_proc assert test_process(ProcController).template.assigns["ran_proc_filter"] end - + def test_running_filters_with_implicit_proc assert test_process(ImplicitProcController).template.assigns["ran_proc_filter"] end - + def test_running_filters_with_class assert test_process(AuditController).template.assigns["was_audited"] end @@ -319,7 +430,7 @@ class FilterTest < Test::Unit::TestCase assert response.template.assigns["ran_class_filter"] assert response.template.assigns["ran_proc_filter1"] assert response.template.assigns["ran_proc_filter2"] - + response = test_process(AnomolousYetValidConditionController, "show_without_filter") assert_equal nil, response.template.assigns["ran_filter"] assert !response.template.assigns["ran_class_filter"] @@ -373,6 +484,12 @@ class FilterTest < Test::Unit::TestCase assert controller.template.assigns["after_ran"] end + def test_before_after_class_filter + controller = test_process(BeforeAfterClassFilterController) + assert controller.template.assigns["before_ran"] + assert controller.template.assigns["after_ran"] + end + def test_having_properties_in_around_filter controller = test_process(AroundFilterController) assert_equal "before and after", controller.template.assigns["execution_log"] @@ -381,10 +498,10 @@ class FilterTest < Test::Unit::TestCase def test_prepending_and_appending_around_filter controller = test_process(MixedFilterController) assert_equal " before aroundfilter before procfilter before appended aroundfilter " + - " after appended aroundfilter after aroundfilter after procfilter ", + " after appended aroundfilter after aroundfilter after procfilter ", MixedFilterController.execution_log end - + def test_rendering_breaks_filtering_chain response = test_process(RenderingController) assert_equal "something else", response.body @@ -412,6 +529,12 @@ class FilterTest < Test::Unit::TestCase end end + def test_running_prepended_before_and_after_filter + assert_equal 3, PrependingBeforeAndAfterController.filter_chain.length + response = test_process(PrependingBeforeAndAfterController) + assert_equal %w( before_all between_before_all_and_after_all after_all ), response.template.assigns["ran_filter"] + end + def test_conditional_skipping_of_filters assert_nil test_process(ConditionalSkippingController, "login").template.assigns["ran_filter"] assert_equal %w( ensure_login find_user ), test_process(ConditionalSkippingController, "change_password").template.assigns["ran_filter"] diff --git a/vendor/rails/actionpack/test/controller/integration_test.rb b/vendor/rails/actionpack/test/controller/integration_test.rb index 665c590..6006a8b 100644 --- a/vendor/rails/actionpack/test/controller/integration_test.rb +++ b/vendor/rails/actionpack/test/controller/integration_test.rb @@ -11,7 +11,7 @@ require 'stubba' module ActionController module Integration class Session - def process + def process(*args) end def generic_url_rewriter @@ -56,8 +56,7 @@ class SessionTest < Test::Unit::TestCase @session.expects(:get).with(path,args) - redirects = [true, true, false] - @session.stubs(:redirect?).returns(lambda { redirects.shift }) + @session.stubs(:redirect?).returns(true).then.returns(true).then.returns(false) @session.expects(:follow_redirect!).times(2) @session.stubs(:status).returns(200) @@ -69,8 +68,7 @@ class SessionTest < Test::Unit::TestCase @session.expects(:post).with(path,args) - redirects = [true, true, false] - @session.stubs(:redirect?).returns(lambda { redirects.shift }) + @session.stubs(:redirect?).returns(true).then.returns(true).then.returns(false) @session.expects(:follow_redirect!).times(2) @session.stubs(:status).returns(200) @@ -134,15 +132,102 @@ class SessionTest < Test::Unit::TestCase @session.head(path,params,headers) end - def test_xml_http_request + def test_xml_http_request_deprecated_call path = "/index"; params = "blah"; headers = {:location => 'blah'} headers_after_xhr = headers.merge( "X-Requested-With" => "XMLHttpRequest", "Accept" => "text/javascript, text/html, application/xml, text/xml, */*" ) - @session.expects(:post).with(path,params,headers_after_xhr) - @session.xml_http_request(path,params,headers) + @session.expects(:process).with(:post,path,params,headers_after_xhr) + assert_deprecated { @session.xml_http_request(path,params,headers) } end + + def test_xml_http_request_get + path = "/index"; params = "blah"; headers = {:location => 'blah'} + headers_after_xhr = headers.merge( + "X-Requested-With" => "XMLHttpRequest", + "Accept" => "text/javascript, text/html, application/xml, text/xml, */*" + ) + @session.expects(:process).with(:get,path,params,headers_after_xhr) + @session.xml_http_request(:get,path,params,headers) + end + + def test_xml_http_request_post + path = "/index"; params = "blah"; headers = {:location => 'blah'} + headers_after_xhr = headers.merge( + "X-Requested-With" => "XMLHttpRequest", + "Accept" => "text/javascript, text/html, application/xml, text/xml, */*" + ) + @session.expects(:process).with(:post,path,params,headers_after_xhr) + @session.xml_http_request(:post,path,params,headers) + end + + def test_xml_http_request_put + path = "/index"; params = "blah"; headers = {:location => 'blah'} + headers_after_xhr = headers.merge( + "X-Requested-With" => "XMLHttpRequest", + "Accept" => "text/javascript, text/html, application/xml, text/xml, */*" + ) + @session.expects(:process).with(:put,path,params,headers_after_xhr) + @session.xml_http_request(:put,path,params,headers) + end + + def test_xml_http_request_delete + path = "/index"; params = "blah"; headers = {:location => 'blah'} + headers_after_xhr = headers.merge( + "X-Requested-With" => "XMLHttpRequest", + "Accept" => "text/javascript, text/html, application/xml, text/xml, */*" + ) + @session.expects(:process).with(:delete,path,params,headers_after_xhr) + @session.xml_http_request(:delete,path,params,headers) + end + + def test_xml_http_request_head + path = "/index"; params = "blah"; headers = {:location => 'blah'} + headers_after_xhr = headers.merge( + "X-Requested-With" => "XMLHttpRequest", + "Accept" => "text/javascript, text/html, application/xml, text/xml, */*" + ) + @session.expects(:process).with(:head,path,params,headers_after_xhr) + @session.xml_http_request(:head,path,params,headers) + end +end + +class IntegrationTestTest < Test::Unit::TestCase + + def setup + @test = ::ActionController::IntegrationTest.new(:default_test) + @test.class.stubs(:fixture_table_names).returns([]) + @session = @test.open_session + end + + def test_opens_new_session + @test.class.expects(:fixture_table_names).times(2).returns(['foo']) + + session1 = @test.open_session { |sess| } + session2 = @test.open_session # implicit session + + assert_equal ::ActionController::Integration::Session, session1.class + assert_equal ::ActionController::Integration::Session, session2.class + assert_not_equal session1, session2 + end + +end + +# Tests that integration tests don't call Controller test methods for processing. +# Integration tests have their own setup and teardown. +class IntegrationTestUsesCorrectClass < ActionController::IntegrationTest + + def self.fixture_table_names + [] + end + + def test_integration_methods_called + %w( get post head put delete ).each do |verb| + assert_nothing_raised("'#{verb}' should use integration test methods") { send(verb, '/') } + end + end + end # TODO diff --git a/vendor/rails/actionpack/test/controller/resources_test.rb b/vendor/rails/actionpack/test/controller/resources_test.rb index e5605df..26100d7 100644 --- a/vendor/rails/actionpack/test/controller/resources_test.rb +++ b/vendor/rails/actionpack/test/controller/resources_test.rb @@ -10,8 +10,9 @@ class ThreadsController < ResourcesController; end class MessagesController < ResourcesController; end class CommentsController < ResourcesController; end -class AccountController < ResourcesController; end -class AdminController < ResourcesController; end +class AccountController < ResourcesController; end +class AdminController < ResourcesController; end +class ProductsController < ResourcesController; end class ResourcesTest < Test::Unit::TestCase def test_should_arrange_actions @@ -63,13 +64,13 @@ class ResourcesTest < Test::Unit::TestCase end end - def test_multile_with_path_prefix + def test_multiple_with_path_prefix with_restful_routing :messages, :comments, :path_prefix => '/thread/:thread_id' do assert_simply_restful_for :messages, :path_prefix => 'thread/5/', :options => { :thread_id => '5' } assert_simply_restful_for :comments, :path_prefix => 'thread/5/', :options => { :thread_id => '5' } end end - + def test_with_name_prefix with_restful_routing :messages, :name_prefix => 'post_' do assert_simply_restful_for :messages, :name_prefix => 'post_' @@ -78,7 +79,7 @@ class ResourcesTest < Test::Unit::TestCase def test_with_collection_action rss_options = {:action => 'rss'} - rss_path = "/messages;rss" + rss_path = "/messages/rss" actions = { 'a' => :put, 'b' => :post, 'c' => :delete } with_restful_routing :messages, :collection => { :rss => :get }.merge(actions) do @@ -86,14 +87,14 @@ class ResourcesTest < Test::Unit::TestCase assert_routing rss_path, options.merge(rss_options) actions.each do |action, method| - assert_recognizes(options.merge(:action => action), :path => "/messages;#{action}", :method => method) + assert_recognizes(options.merge(:action => action), :path => "/messages/#{action}", :method => method) end end assert_restful_named_routes_for :messages do |options| assert_named_route rss_path, :rss_messages_path, rss_options actions.keys.each do |action| - assert_named_route "/messages;#{action}", "#{action}_messages_path", :action => action + assert_named_route "/messages/#{action}", "#{action}_messages_path", :action => action end end end @@ -103,7 +104,7 @@ class ResourcesTest < Test::Unit::TestCase [:put, :post].each do |method| with_restful_routing :messages, :member => { :mark => method } do mark_options = {:action => 'mark', :id => '1'} - mark_path = "/messages/1;mark" + mark_path = "/messages/1/mark" assert_restful_routes_for :messages do |options| assert_recognizes(options.merge(mark_options), :path => mark_path, :method => method) end @@ -120,7 +121,7 @@ class ResourcesTest < Test::Unit::TestCase with_restful_routing :messages, :member => { :mark => method, :unmark => method } do %w(mark unmark).each do |action| action_options = {:action => action, :id => '1'} - action_path = "/messages/1;#{action}" + action_path = "/messages/1/#{action}" assert_restful_routes_for :messages do |options| assert_recognizes(options.merge(action_options), :path => action_path, :method => method) end @@ -136,7 +137,7 @@ class ResourcesTest < Test::Unit::TestCase def test_with_new_action with_restful_routing :messages, :new => { :preview => :post } do preview_options = {:action => 'preview'} - preview_path = "/messages/new;preview" + preview_path = "/messages/new/preview" assert_restful_routes_for :messages do |options| assert_recognizes(options.merge(preview_options), :path => preview_path, :method => :post) end @@ -178,9 +179,11 @@ class ResourcesTest < Test::Unit::TestCase assert_simply_restful_for :threads assert_simply_restful_for :messages, :path_prefix => 'threads/1/', + :name_prefix => 'thread_', :options => { :thread_id => '1' } assert_simply_restful_for :comments, :path_prefix => 'threads/1/messages/2/', + :name_prefix => 'thread_message_', :options => { :thread_id => '1', :message_id => '2' } end end @@ -217,9 +220,9 @@ class ResourcesTest < Test::Unit::TestCase admin.resource :account end end - + assert_singleton_restful_for :admin - assert_singleton_restful_for :account, :path_prefix => 'admin/' + assert_singleton_restful_for :account, :path_prefix => 'admin/', :name_prefix => 'admin_' end end @@ -227,7 +230,7 @@ class ResourcesTest < Test::Unit::TestCase [:put, :post].each do |method| with_singleton_resources :account, :member => { :reset => method } do reset_options = {:action => 'reset'} - reset_path = "/account;reset" + reset_path = "/account/reset" assert_singleton_routes_for :account do |options| assert_recognizes(options.merge(reset_options), :path => reset_path, :method => method) end @@ -244,7 +247,7 @@ class ResourcesTest < Test::Unit::TestCase with_singleton_resources :account, :member => { :reset => method, :disable => method } do %w(reset disable).each do |action| action_options = {:action => action} - action_path = "/account;#{action}" + action_path = "/account/#{action}" assert_singleton_routes_for :account do |options| assert_recognizes(options.merge(action_options), :path => action_path, :method => method) end @@ -264,9 +267,9 @@ class ResourcesTest < Test::Unit::TestCase account.resources :messages end end - + assert_singleton_restful_for :account - assert_simply_restful_for :messages, :path_prefix => 'account/' + assert_simply_restful_for :messages, :path_prefix => 'account/', :name_prefix => 'account_' end end @@ -279,10 +282,10 @@ class ResourcesTest < Test::Unit::TestCase end assert_singleton_restful_for :account, :path_prefix => '7/', :options => { :site_id => '7' } - assert_simply_restful_for :messages, :path_prefix => '7/account/', :options => { :site_id => '7' } + assert_simply_restful_for :messages, :path_prefix => '7/account/', :name_prefix => 'account_', :options => { :site_id => '7' } end end - + def test_should_nest_singleton_resource_in_resources with_routing do |set| set.draw do |map| @@ -290,9 +293,9 @@ class ResourcesTest < Test::Unit::TestCase thread.resource :admin end end - + assert_simply_restful_for :threads - assert_singleton_restful_for :admin, :path_prefix => 'threads/5/', :options => { :thread_id => '5' } + assert_singleton_restful_for :admin, :path_prefix => 'threads/5/', :name_prefix => 'thread_', :options => { :thread_id => '5' } end end @@ -312,6 +315,181 @@ class ResourcesTest < Test::Unit::TestCase end end + def test_resource_action_separator + with_routing do |set| + set.draw do |map| + map.resources :messages, :collection => {:search => :get}, :new => {:preview => :any}, :name_prefix => 'thread_', :path_prefix => '/threads/:thread_id' + map.resource :account, :member => {:login => :get}, :new => {:preview => :any}, :name_prefix => 'admin_', :path_prefix => '/admin' + end + + action_separator = ActionController::Base.resource_action_separator + + assert_simply_restful_for :messages, :name_prefix => 'thread_', :path_prefix => 'threads/1/', :options => { :thread_id => '1' } + assert_named_route "/threads/1/messages#{action_separator}search", "search_thread_messages_path", {} + assert_named_route "/threads/1/messages/new", "new_thread_message_path", {} + assert_named_route "/threads/1/messages/new#{action_separator}preview", "preview_new_thread_message_path", {} + assert_singleton_restful_for :account, :name_prefix => 'admin_', :path_prefix => 'admin/' + assert_named_route "/admin/account#{action_separator}login", "login_admin_account_path", {} + assert_named_route "/admin/account/new", "new_admin_account_path", {} + assert_named_route "/admin/account/new#{action_separator}preview", "preview_new_admin_account_path", {} + end + end + + def test_new_style_named_routes_for_resource + with_routing do |set| + set.draw do |map| + map.resources :messages, :collection => {:search => :get}, :new => {:preview => :any}, :name_prefix => 'thread_', :path_prefix => '/threads/:thread_id' + end + assert_simply_restful_for :messages, :name_prefix => 'thread_', :path_prefix => 'threads/1/', :options => { :thread_id => '1' } + assert_named_route "/threads/1/messages/search", "search_thread_messages_path", {} + assert_named_route "/threads/1/messages/new", "new_thread_message_path", {} + assert_named_route "/threads/1/messages/new/preview", "preview_new_thread_message_path", {} + end + end + + def test_new_style_named_routes_for_singleton_resource + with_routing do |set| + set.draw do |map| + map.resource :account, :member => {:login => :get}, :new => {:preview => :any}, :name_prefix => 'admin_', :path_prefix => '/admin' + end + assert_singleton_restful_for :account, :name_prefix => 'admin_', :path_prefix => 'admin/' + assert_named_route "/admin/account/login", "login_admin_account_path", {} + assert_named_route "/admin/account/new", "new_admin_account_path", {} + assert_named_route "/admin/account/new/preview", "preview_new_admin_account_path", {} + end + end + + def test_should_add_deprecated_named_routes_for_resource + with_routing do |set| + set.draw do |map| + map.resources :messages, :collection => {:search => :get}, :new => {:preview => :any}, :name_prefix => 'thread_', :path_prefix => '/threads/:thread_id' + end + assert_simply_restful_for :messages, :name_prefix => 'thread_', :path_prefix => 'threads/1/', :options => { :thread_id => '1' } + assert_deprecated do + assert_named_route "/threads/1/messages/search", "thread_search_messages_path", {} + assert_named_route "/threads/1/messages/new", "thread_new_message_path", {} + assert_named_route "/threads/1/messages/new/preview", "thread_preview_new_message_path", {} + end + end + end + + def test_should_add_deprecated_named_routes_for_singleton_resource + with_routing do |set| + set.draw do |map| + map.resource :account, :member => {:login => :get}, :new => {:preview => :any}, :name_prefix => 'admin_', :path_prefix => '/admin' + end + assert_singleton_restful_for :account, :name_prefix => 'admin_', :path_prefix => 'admin/' + assert_deprecated do + assert_named_route "/admin/account/login", "admin_login_account_path", {} + assert_named_route "/admin/account/new", "admin_new_account_path", {} + assert_named_route "/admin/account/new/preview", "admin_preview_new_account_path", {} + end + end + end + + def test_should_add_deprecated_named_routes_for_nested_resources + with_routing do |set| + set.draw do |map| + map.resources :threads do |map| + map.resources :messages do |map| + map.resources :comments + end + end + end + + assert_simply_restful_for :threads + assert_simply_restful_for :messages, + :path_prefix => 'threads/1/', + :name_prefix => 'thread_', + :options => { :thread_id => '1' } + assert_simply_restful_for :comments, + :path_prefix => 'threads/1/messages/2/', + :name_prefix => 'thread_message_', + :options => { :thread_id => '1', :message_id => '2' } + + assert_deprecated do + assert_named_route "/threads/1/messages", "messages_path", {} + assert_named_route "/threads/1/messages/1", "message_path", {:thread_id => '1', :id => '1'} + assert_named_route "/threads/1/messages/new", "new_message_path", {:thread_id => '1'} + assert_named_route "/threads/1/messages/1/edit", "edit_message_path", {:thread_id => '1', :id => '1'} + end + end + end + + def test_should_add_deprecated_named_routes_for_nested_singleton_resources + with_routing do |set| + set.draw do |map| + map.resource :admin do |admin| + admin.resource :account + end + end + + assert_singleton_restful_for :admin + assert_singleton_restful_for :account, :path_prefix => 'admin/', :name_prefix => 'admin_' + + assert_deprecated do + assert_named_route "/admin/account", "account_path", {} + assert_named_route "/admin/account/new", "new_account_path", {} + assert_named_route "/admin/account/edit", "edit_account_path", {} + end + end + end + + def test_should_add_deprecated_named_routes_for_nested_resources_in_singleton_resource + with_routing do |set| + set.draw do |map| + map.resource :account do |account| + account.resources :messages + end + end + + assert_singleton_restful_for :account + assert_simply_restful_for :messages, :path_prefix => 'account/', :name_prefix => 'account_' + + assert_deprecated do + assert_named_route "/account/messages", "messages_path", {} + assert_named_route "/account/messages/1", "message_path", {:id => '1'} + assert_named_route "/account/messages/new", "new_message_path", {} + assert_named_route "/account/messages/1/edit", "edit_message_path", {:id => '1'} + end + end + end + + def test_should_add_deprecated_named_routes_for_nested_singleton_resource_in_resources + with_routing do |set| + set.draw do |map| + map.resources :threads do |thread| + thread.resource :admin + end + end + + assert_simply_restful_for :threads + assert_singleton_restful_for :admin, :path_prefix => 'threads/5/', :name_prefix => 'thread_', :options => { :thread_id => '5' } + + assert_deprecated do + assert_named_route "/threads/5/admin", "admin_path", {} + assert_named_route "/threads/5/admin/new", "new_admin_path", {} + assert_named_route "/threads/5/admin/edit", "edit_admin_path", {} + end + end + end + + def test_should_add_deprecated_formatted_routes + with_routing do |set| + set.draw do |map| + map.resources :products, :collection => { :specials => :get }, :member => { :thumbnail => :get } + map.resource :account, :member => { :icon => :get } + end + assert_restful_routes_for :products do |options| + assert_recognizes options.merge({ :action => 'specials', :format => 'xml' }), :path => '/products.xml;specials', :method => :get + assert_recognizes options.merge({ :action => 'thumbnail', :format => 'jpg', :id => '1' }), :path => '/products/1.jpg;thumbnail', :method => :get + end + assert_singleton_restful_for :account do |options| + assert_recognizes options.merge({ :action => 'icon', :format => 'jpg' }), :path => '/account.jpg;icon', :method => :get + end + end + end + protected def with_restful_routing(*args) with_routing do |set| @@ -319,7 +497,7 @@ class ResourcesTest < Test::Unit::TestCase yield end end - + def with_singleton_resources(*args) with_routing do |set| set.draw { |map| map.resource(*args) } @@ -344,8 +522,8 @@ class ResourcesTest < Test::Unit::TestCase collection_path = "/#{options[:path_prefix]}#{controller_name}" member_path = "#{collection_path}/1" new_path = "#{collection_path}/new" - edit_member_path = "#{member_path};edit" - formatted_edit_member_path = "#{member_path}.xml;edit" + edit_member_path = "#{member_path}/edit" + formatted_edit_member_path = "#{member_path}/edit.xml" with_options(options[:options]) do |controller| controller.assert_routing collection_path, :action => 'index' @@ -395,13 +573,13 @@ class ResourcesTest < Test::Unit::TestCase name_prefix = options[:name_prefix] assert_named_route "#{full_prefix}", "#{name_prefix}#{controller_name}_path", options[:options] - assert_named_route "#{full_prefix}/new", "#{name_prefix}new_#{singular_name}_path", options[:options] + assert_named_route "#{full_prefix}/new", "new_#{name_prefix}#{singular_name}_path", options[:options] assert_named_route "#{full_prefix}/1", "#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1') - assert_named_route "#{full_prefix}/1;edit", "#{name_prefix}edit_#{singular_name}_path", options[:options].merge(:id => '1') + assert_named_route "#{full_prefix}/1/edit", "edit_#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1') assert_named_route "#{full_prefix}.xml", "formatted_#{name_prefix}#{controller_name}_path", options[:options].merge( :format => 'xml') - assert_named_route "#{full_prefix}/new.xml", "formatted_#{name_prefix}new_#{singular_name}_path", options[:options].merge( :format => 'xml') + assert_named_route "#{full_prefix}/new.xml", "formatted_new_#{name_prefix}#{singular_name}_path", options[:options].merge( :format => 'xml') assert_named_route "#{full_prefix}/1.xml", "formatted_#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1', :format => 'xml') - assert_named_route "#{full_prefix}/1.xml;edit", "formatted_#{name_prefix}edit_#{singular_name}_path", options[:options].merge(:id => '1', :format => 'xml') + assert_named_route "#{full_prefix}/1/edit.xml", "formatted_edit_#{name_prefix}#{singular_name}_path", options[:options].merge(:id => '1', :format => 'xml') yield options[:options] if block_given? end @@ -410,8 +588,8 @@ class ResourcesTest < Test::Unit::TestCase full_path = "/#{options[:path_prefix]}#{singleton_name}" new_path = "#{full_path}/new" - edit_path = "#{full_path};edit" - formatted_edit_path = "#{full_path}.xml;edit" + edit_path = "#{full_path}/edit" + formatted_edit_path = "#{full_path}/edit.xml" with_options options[:options] do |controller| controller.assert_routing full_path, :action => 'show' @@ -448,13 +626,14 @@ class ResourcesTest < Test::Unit::TestCase options[:options].delete :action full_path = "/#{options[:path_prefix]}#{singleton_name}" - - assert_named_route "#{full_path}", "#{singleton_name}_path", options[:options] - assert_named_route "#{full_path}/new", "new_#{singleton_name}_path", options[:options] - assert_named_route "#{full_path};edit", "edit_#{singleton_name}_path", options[:options] - assert_named_route "#{full_path}.xml", "formatted_#{singleton_name}_path", options[:options].merge(:format => 'xml') - assert_named_route "#{full_path}/new.xml", "formatted_new_#{singleton_name}_path", options[:options].merge(:format => 'xml') - assert_named_route "#{full_path}.xml;edit", "formatted_edit_#{singleton_name}_path", options[:options].merge(:format => 'xml') + full_name = "#{options[:name_prefix]}#{singleton_name}" + + assert_named_route "#{full_path}", "#{full_name}_path", options[:options] + assert_named_route "#{full_path}/new", "new_#{full_name}_path", options[:options] + assert_named_route "#{full_path}/edit", "edit_#{full_name}_path", options[:options] + assert_named_route "#{full_path}.xml", "formatted_#{full_name}_path", options[:options].merge(:format => 'xml') + assert_named_route "#{full_path}/new.xml", "formatted_new_#{full_name}_path", options[:options].merge(:format => 'xml') + assert_named_route "#{full_path}/edit.xml", "formatted_edit_#{full_name}_path", options[:options].merge(:format => 'xml') end def assert_named_route(expected, route, options) diff --git a/vendor/rails/actionpack/test/controller/routing_test.rb b/vendor/rails/actionpack/test/controller/routing_test.rb index 5e5f2b0..a201d9c 100644 --- a/vendor/rails/actionpack/test/controller/routing_test.rb +++ b/vendor/rails/actionpack/test/controller/routing_test.rb @@ -265,7 +265,7 @@ class LegacyRouteSetTests < Test::Unit::TestCase map.content '/content/:query', :controller => 'content', :action => 'show' end exception = assert_raise(ActionController::RoutingError) { rs.generate(:controller => 'content', :action => 'show', :use_route => "content") } - 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?] + 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?" assert_equal expected_message, exception.message end @@ -946,7 +946,7 @@ class RouteTest < Test::Unit::TestCase end def test_expand_array_build_query_string - assert_equal '?x[]=1&x[]=2', order_query_string(@route.build_query_string(:x => [1, 2])) + assert_equal '?x%5B%5D=1&x%5B%5D=2', order_query_string(@route.build_query_string(:x => [1, 2])) end def test_escape_spaces_build_query_string_selected_keys diff --git a/vendor/rails/actionpack/test/controller/session_fixation_test.rb b/vendor/rails/actionpack/test/controller/session_fixation_test.rb new file mode 100644 index 0000000..75d1d59 --- /dev/null +++ b/vendor/rails/actionpack/test/controller/session_fixation_test.rb @@ -0,0 +1,92 @@ +require File.dirname(__FILE__) + '/../abstract_unit' + +class SessionFixationTest < Test::Unit::TestCase + class MockCGI < CGI #:nodoc: + attr_accessor :stdoutput, :env_table + + def initialize(env, data = '') + self.env_table = env + self.stdoutput = StringIO.new + super(StringIO.new(data)) + end + end + + class TestController < ActionController::Base + session :session_key => '_myapp_session_id', :secret => 'secret', :except => :default_session_key + session :cookie_only => false, :only => :allow_session_fixation + + def default_session_key + render :text => "default_session_key" + end + + def custom_session_key + render :text => "custom_session_key: #{params[:id]}" + end + + def allow_session_fixation + render :text => "allow_session_fixation" + end + + def rescue_action(e) raise end + end + + def setup + @controller = TestController.new + end + + def test_should_be_able_to_make_a_successful_request + cgi = mock_cgi_for_request_to(:custom_session_key, :id => 1) + + assert_nothing_raised do + @controller.send(:process, mock_request(cgi), ActionController::CgiResponse.new(cgi)) + end + assert_equal 'custom_session_key: 1', @controller.response.body + assert_not_nil @controller.session + end + + def test_should_catch_session_fixation_attempt + cgi = mock_cgi_for_request_to(:custom_session_key, :_myapp_session_id => 42) + + assert_raises ActionController::CgiRequest::SessionFixationAttempt do + @controller.send(:process, mock_request(cgi), ActionController::CgiResponse.new(cgi)) + end + assert_nil @controller.session + end + + def test_should_not_catch_session_fixation_attempt_when_cookie_only_setting_is_disabled + cgi = mock_cgi_for_request_to(:allow_session_fixation, :_myapp_session_id => 42) + + assert_nothing_raised do + @controller.send(:process, mock_request(cgi), ActionController::CgiResponse.new(cgi)) + end + assert !@controller.response.body.blank? + assert_not_nil @controller.session + end + + def test_should_catch_session_fixation_attempt_with_default_session_key + ActionController::Base.session_store = :p_store # using the default session_key is not possible with cookie store + cgi = mock_cgi_for_request_to(:default_session_key, :_session_id => 42) + + assert_raises ActionController::CgiRequest::SessionFixationAttempt do + @controller.send(:process, mock_request(cgi) , ActionController::CgiResponse.new(cgi)) + end + assert @controller.response.body.blank? + assert_nil @controller.session + end + +private + + def mock_cgi_for_request_to(action, params = {}) + MockCGI.new({ + "REQUEST_METHOD" => "GET", + "QUERY_STRING" => "action=#{action}&#{params.to_query}", + "REQUEST_URI" => "/", + "SERVER_PORT" => "80", + "HTTP_HOST" => "testdomain.com" }, '') + end + + def mock_request(cgi) + ActionController::CgiRequest.new(cgi, {}) + end + +end diff --git a/vendor/rails/actionpack/test/controller/test_test.rb b/vendor/rails/actionpack/test/controller/test_test.rb index 2b0086c..a8acd51 100644 --- a/vendor/rails/actionpack/test/controller/test_test.rb +++ b/vendor/rails/actionpack/test/controller/test_test.rb @@ -482,6 +482,22 @@ HTML end end + def test_request_uri_updates + get :test_params + uri = @request.request_uri + assert_equal @request.env['REQUEST_URI'], uri + + get :test_uri + assert_not_equal uri, @request.request_uri + uri = @request.request_uri + assert_equal @request.env['REQUEST_URI'], uri + + get :test_uri, :testing => true + assert_not_equal uri, @request.request_uri + uri = @request.request_uri + assert_equal @request.env['REQUEST_URI'], uri + end + protected def with_foo_routing with_routing do |set| diff --git a/vendor/rails/actionpack/test/controller/url_rewriter_test.rb b/vendor/rails/actionpack/test/controller/url_rewriter_test.rb index 882add4..6378c43 100644 --- a/vendor/rails/actionpack/test/controller/url_rewriter_test.rb +++ b/vendor/rails/actionpack/test/controller/url_rewriter_test.rb @@ -17,15 +17,12 @@ class UrlRewriterTests < Test::Unit::TestCase assert_match %r(/hi/hi/2$), u end - - private - def split_query_string(str) - [str[0].chr] + str[1..-1].split(/&/).sort - end - - def assert_query_equal(q1, q2) - assert_equal(split_query_string(q1), split_query_string(q2)) - end + def test_anchor + assert_equal( + 'http://test.host/c/a/i#anchor', + @rewriter.rewrite(:controller => 'c', :action => 'a', :id => 'i', :anchor => 'anchor') + ) + end end class UrlWriterTests < Test::Unit::TestCase @@ -75,6 +72,12 @@ class UrlWriterTests < Test::Unit::TestCase W.new.url_for(:controller => 'c', :action => 'a', :id => 'i', :protocol => 'https') ) end + + def test_anchor + assert_equal('/c/a#anchor', + W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :anchor => 'anchor') + ) + end def test_named_route ActionController::Routing::Routes.draw do |map| @@ -111,5 +114,58 @@ class UrlWriterTests < Test::Unit::TestCase ensure ActionController::Routing::Routes.load! end - + + def test_one_parameter + assert_equal('/c/a?param=val', + W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :param => 'val') + ) + end + + def test_two_parameters + url = W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :p1 => 'X1', :p2 => 'Y2') + params = extract_params(url) + assert_equal params[0], { :p1 => 'X1' }.to_query + assert_equal params[1], { :p2 => 'Y2' }.to_query + end + + def test_hash_parameter + url = W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :query => {:name => 'Bob', :category => 'prof'}) + params = extract_params(url) + assert_equal params[0], { 'query[category]' => 'prof' }.to_query + assert_equal params[1], { 'query[name]' => 'Bob' }.to_query + end + + def test_array_parameter + url = W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :query => ['Bob', 'prof']) + params = extract_params(url) + assert_equal params[0], { 'query[]' => 'Bob' }.to_query + assert_equal params[1], { 'query[]' => 'prof' }.to_query + end + + def test_hash_recursive_parameters + url = W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :query => {:person => {:name => 'Bob', :position => 'prof'}, :hobby => 'piercing'}) + params = extract_params(url) + assert_equal params[0], { 'query[hobby]' => 'piercing' }.to_query + assert_equal params[1], { 'query[person][name]' => 'Bob' }.to_query + assert_equal params[2], { 'query[person][position]' => 'prof' }.to_query + end + + def test_hash_recursive_and_array_parameters + url = W.new.url_for(:only_path => true, :controller => 'c', :action => 'a', :id => 101, :query => {:person => {:name => 'Bob', :position => ['prof', 'art director']}, :hobby => 'piercing'}) + assert_match %r(^/c/a/101), url + params = extract_params(url) + assert_equal params[0], { 'query[hobby]' => 'piercing' }.to_query + assert_equal params[1], { 'query[person][name]' => 'Bob' }.to_query + assert_equal params[2], { 'query[person][position][]' => 'art director' }.to_query + assert_equal params[3], { 'query[person][position][]' => 'prof' }.to_query + end + + def test_path_generation_for_symbol_parameter_keys + assert_generates("/image", :controller=> :image) + end + + private + def extract_params(url) + url.split('?', 2).last.split('&') + end end diff --git a/vendor/rails/actionpack/test/controller/verification_test.rb b/vendor/rails/actionpack/test/controller/verification_test.rb index 05012cf..bbcd7d5 100644 --- a/vendor/rails/actionpack/test/controller/verification_test.rb +++ b/vendor/rails/actionpack/test/controller/verification_test.rb @@ -34,9 +34,16 @@ class VerificationTest < Test::Unit::TestCase verify :only => :must_be_post, :method => :post, :render => { :status => 405, :text => "Must be post" }, :add_headers => { "Allow" => "POST" } + verify :only => :guarded_one_for_named_route_test, :params => "one", + :redirect_to => :foo_url + def guarded_one render :text => "#{params[:one]}" end + + def guarded_one_for_named_route_test + render :text => "#{params[:one]}" + end def guarded_with_flash render :text => "#{params[:one]}" @@ -94,6 +101,14 @@ class VerificationTest < Test::Unit::TestCase @controller = TestController.new @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new + ActionController::Routing::Routes.add_named_route :foo, '/foo', :controller => 'test', :action => 'foo' + end + + def test_no_deprecation_warning_for_named_route + assert_not_deprecated do + get :guarded_one_for_named_route_test, :two => "not one" + assert_redirected_to '/foo' + end end def test_guarded_one_with_prereqs diff --git a/vendor/rails/actionpack/test/fixtures/test/hello_world.rxml b/vendor/rails/actionpack/test/fixtures/test/hello_world.rxml index bffd219..8455b11 100644 --- a/vendor/rails/actionpack/test/fixtures/test/hello_world.rxml +++ b/vendor/rails/actionpack/test/fixtures/test/hello_world.rxml @@ -1,3 +1,4 @@ xml.html do xml.p "Hello" -end \ No newline at end of file +end +"String return value" diff --git a/vendor/rails/actionpack/test/template/asset_tag_helper_test.rb b/vendor/rails/actionpack/test/template/asset_tag_helper_test.rb index f730f80..739bc46 100644 --- a/vendor/rails/actionpack/test/template/asset_tag_helper_test.rb +++ b/vendor/rails/actionpack/test/template/asset_tag_helper_test.rb @@ -165,7 +165,12 @@ class AssetTagHelperTest < Test::Unit::TestCase def test_preset_empty_asset_id Object.send(:const_set, :RAILS_ROOT, File.dirname(__FILE__) + "/../fixtures/") + # on windows, setting ENV["XXX"] to "" makes ENV["XXX"] return nil + if RUBY_PLATFORM =~ /win32/ + ENV["RAILS_ASSET_ID"] = " " + else ENV["RAILS_ASSET_ID"] = "" + end assert_equal %(Rails), image_tag("rails.png") end diff --git a/vendor/rails/actionpack/test/template/compiled_templates_test.rb b/vendor/rails/actionpack/test/template/compiled_templates_test.rb index e46543d..2e6327a 100644 --- a/vendor/rails/actionpack/test/template/compiled_templates_test.rb +++ b/vendor/rails/actionpack/test/template/compiled_templates_test.rb @@ -71,7 +71,12 @@ class CompiledTemplateTests < Test::Unit::TestCase end def test_compile_time - `echo '#{@a}' > #{@a}; echo '#{@b}' > #{@b}; ln -s #{@a} #{@s}` + File.open(@a, "w"){|f| f.puts @a} + File.open(@b, "w"){|f| f.puts @b} + + # windows doesn't support symlinks (even under cygwin) + windows = (RUBY_PLATFORM =~ /win32/) + `ln -s #{@a} #{@s}` unless windows v = ActionView::Base.new v.base_path = '.' @@ -79,47 +84,54 @@ class CompiledTemplateTests < Test::Unit::TestCase sleep 1 t = Time.now + sleep 1 + v.compile_and_render_template(:rhtml, '', @a) v.compile_and_render_template(:rhtml, '', @b) - v.compile_and_render_template(:rhtml, '', @s) + v.compile_and_render_template(:rhtml, '', @s) unless windows + a_n = v.method_names[@a] b_n = v.method_names[@b] - s_n = v.method_names[@s] + s_n = v.method_names[@s] unless windows + ct_a = v.compile_time[a_n] + ct_b = v.compile_time[b_n] + ct_s = v.compile_time[s_n] unless windows # all of the files have changed since last compile assert v.compile_time[a_n] > t assert v.compile_time[b_n] > t - assert v.compile_time[s_n] > t + assert v.compile_time[s_n] > t unless windows sleep 1 - t = Time.now v.compile_and_render_template(:rhtml, '', @a) v.compile_and_render_template(:rhtml, '', @b) - v.compile_and_render_template(:rhtml, '', @s) + v.compile_and_render_template(:rhtml, '', @s) unless windows # none of the files have changed since last compile - assert v.compile_time[a_n] < t - assert v.compile_time[b_n] < t - assert v.compile_time[s_n] < t + # so they should not have been recmpiled + assert_equal ct_a, v.compile_time[a_n] + assert_equal ct_b, v.compile_time[b_n] + assert_equal ct_s, v.compile_time[s_n] unless windows - `rm #{@s}; ln -s #{@b} #{@s}` + `rm #{@s}; ln -s #{@b} #{@s}` unless windows v.compile_and_render_template(:rhtml, '', @a) v.compile_and_render_template(:rhtml, '', @b) - v.compile_and_render_template(:rhtml, '', @s) + v.compile_and_render_template(:rhtml, '', @s) unless windows # the symlink has changed since last compile - assert v.compile_time[a_n] < t - assert v.compile_time[b_n] < t - assert v.compile_time[s_n] > t + assert_equal ct_a, v.compile_time[a_n] + assert_equal ct_b, v.compile_time[b_n] + assert v.compile_time[s_n] > t unless windows sleep 1 - `touch #{@b}` + FileUtils.touch @b t = Time.now + sleep 1 v.compile_and_render_template(:rhtml, '', @a) v.compile_and_render_template(:rhtml, '', @b) - v.compile_and_render_template(:rhtml, '', @s) + v.compile_and_render_template(:rhtml, '', @s) unless windows # the file at the end of the symlink has changed since last compile # both the symlink and the file at the end of it should be recompiled assert v.compile_time[a_n] < t assert v.compile_time[b_n] > t - assert v.compile_time[s_n] > t + assert v.compile_time[s_n] > t unless windows end end diff --git a/vendor/rails/actionpack/test/template/javascript_helper_test.rb b/vendor/rails/actionpack/test/template/javascript_helper_test.rb index ea13f1a..a2a8863 100644 --- a/vendor/rails/actionpack/test/template/javascript_helper_test.rb +++ b/vendor/rails/actionpack/test/template/javascript_helper_test.rb @@ -36,14 +36,14 @@ class JavaScriptHelperTest < Test::Unit::TestCase html = link_to_function( "Greet me!" ) do |page| page.replace_html 'header', "

Greetings

" end - assert_dom_equal %(Greet me!), html + assert_dom_equal %q(Greet me!), html end def test_link_to_function_with_rjs_block_and_options html = link_to_function( "Greet me!", :class => "updater" ) do |page| page.replace_html 'header', "

Greetings

" end - assert_dom_equal %(Greet me!), html + assert_dom_equal %q(Greet me!), html end def test_button_to_function @@ -55,13 +55,13 @@ class JavaScriptHelperTest < Test::Unit::TestCase html = button_to_function( "Greet me!" ) do |page| page.replace_html 'header', "

Greetings

" end - assert_dom_equal %(), html + assert_dom_equal %q(), html end def test_button_to_function_with_rjs_block_and_options html = button_to_function( "Greet me!", :class => "greeter" ) do |page| page.replace_html 'header', "

Greetings

" end - assert_dom_equal %(), html + assert_dom_equal %q(), html end end diff --git a/vendor/rails/actionpack/test/template/number_helper_test.rb b/vendor/rails/actionpack/test/template/number_helper_test.rb index df2c918..3da1ae6 100644 --- a/vendor/rails/actionpack/test/template/number_helper_test.rb +++ b/vendor/rails/actionpack/test/template/number_helper_test.rb @@ -22,7 +22,7 @@ class NumberHelperTest < Test::Unit::TestCase def test_number_to_currency assert_equal("$1,234,567,890.50", number_to_currency(1234567890.50)) assert_equal("$1,234,567,890.51", number_to_currency(1234567890.506)) - assert_equal("$1,234,567,890", number_to_currency(1234567890.50, {:precision => 0})) + assert_equal("$1,234,567,891", number_to_currency(1234567890.51, {:precision => 0})) assert_equal("$1,234,567,890.5", number_to_currency(1234567890.50, {:precision => 1})) assert_equal("£1234567890,50", number_to_currency(1234567890.50, {:unit => "£", :separator => ",", :delimiter => ""})) assert_equal("$1,234,567,890.50", number_to_currency("1234567890.50")) diff --git a/vendor/rails/actionpack/test/template/prototype_helper_test.rb b/vendor/rails/actionpack/test/template/prototype_helper_test.rb index 7dc366b..80c3d24 100644 --- a/vendor/rails/actionpack/test/template/prototype_helper_test.rb +++ b/vendor/rails/actionpack/test/template/prototype_helper_test.rb @@ -125,7 +125,7 @@ class PrototypeHelperTest < Test::Unit::TestCase end def test_observe_field - assert_dom_equal %(), + assert_dom_equal %(), observe_field("glass", :frequency => 5.minutes, :url => { :action => "reorder_if_empty" }) end @@ -135,7 +135,7 @@ class PrototypeHelperTest < Test::Unit::TestCase end def test_observe_form - assert_dom_equal %(), + assert_dom_equal %(), observe_form("cart", :frequency => 2, :url => { :action => "cart_changed" }) end @@ -170,23 +170,23 @@ class JavaScriptGeneratorTest < Test::Unit::TestCase end def test_insert_html_with_string - assert_equal 'new Insertion.Top("element", "

This is a test

");', + assert_equal 'new Insertion.Top("element", "\074p\076This is a test\074/p\076");', @generator.insert_html(:top, 'element', '

This is a test

') - assert_equal 'new Insertion.Bottom("element", "

This is a test

");', + assert_equal 'new Insertion.Bottom("element", "\074p\076This is a test\074/p\076");', @generator.insert_html(:bottom, 'element', '

This is a test

') - assert_equal 'new Insertion.Before("element", "

This is a test

");', + assert_equal 'new Insertion.Before("element", "\074p\076This is a test\074/p\076");', @generator.insert_html(:before, 'element', '

This is a test

') - assert_equal 'new Insertion.After("element", "

This is a test

");', + assert_equal 'new Insertion.After("element", "\074p\076This is a test\074/p\076");', @generator.insert_html(:after, 'element', '

This is a test

') end def test_replace_html_with_string - assert_equal 'Element.update("element", "

This is a test

");', + assert_equal 'Element.update("element", "\074p\076This is a test\074/p\076");', @generator.replace_html('element', '

This is a test

') end def test_replace_element_with_string - assert_equal 'Element.replace("element", "

This is a test

");', + assert_equal 'Element.replace("element", "\074div id=\"element\"\076\074p\076This is a test\074/p\076\074/div\076");', @generator.replace('element', '

This is a test

') end @@ -241,12 +241,12 @@ class JavaScriptGeneratorTest < Test::Unit::TestCase @generator.remove('foo', 'bar') @generator.replace_html('baz', '

This is a test

') - assert_equal <<-EOS.chomp, @generator.to_s -new Insertion.Top("element", "

This is a test

"); -new Insertion.Bottom("element", "

This is a test

"); + expected = %q(new Insertion.Top("element", "\074p\076This is a test\074/p\076"); +new Insertion.Bottom("element", "\074p\076This is a test\074/p\076"); ["foo", "bar"].each(Element.remove); -Element.update("baz", "

This is a test

"); - EOS +Element.update("baz", "\074p\076This is a test\074/p\076");) + + assert_equal expected, @generator.to_s end def test_element_access diff --git a/vendor/rails/actionwebservice/CHANGELOG b/vendor/rails/actionwebservice/CHANGELOG index 2c3463e..5c5b3ff 100644 --- a/vendor/rails/actionwebservice/CHANGELOG +++ b/vendor/rails/actionwebservice/CHANGELOG @@ -1,3 +1,24 @@ +*1.2.6* (November 24th, 2007) + +* Depend on Action Pack 1.13.6 + +* Depend on Active Record 1.15.6 + + +*1.2.5* (October 12th, 2007) + +* Depend on Action Pack 1.13.5 + +* Depend on Active Record 1.15.5 + + +*1.2.4* (October 4th, 2007) + +* Depend on Action Pack 1.13.4 + +* Depend on Active Record 1.15.4 + + *1.2.3* (March 12th, 2007) * Depend on Action Pack 1.13.3 diff --git a/vendor/rails/actionwebservice/Rakefile b/vendor/rails/actionwebservice/Rakefile index fec9aae..b6382bb 100644 --- a/vendor/rails/actionwebservice/Rakefile +++ b/vendor/rails/actionwebservice/Rakefile @@ -71,8 +71,8 @@ spec = Gem::Specification.new do |s| s.rubyforge_project = "aws" s.homepage = "http://www.rubyonrails.org" - s.add_dependency('actionpack', '= 1.13.3' + PKG_BUILD) - s.add_dependency('activerecord', '= 1.15.3' + PKG_BUILD) + s.add_dependency('actionpack', '= 1.13.6' + PKG_BUILD) + s.add_dependency('activerecord', '= 1.15.6' + PKG_BUILD) s.has_rdoc = true s.requirements << 'none' diff --git a/vendor/rails/actionwebservice/lib/action_web_service/version.rb b/vendor/rails/actionwebservice/lib/action_web_service/version.rb index ebcb7ea..3a2783e 100644 --- a/vendor/rails/actionwebservice/lib/action_web_service/version.rb +++ b/vendor/rails/actionwebservice/lib/action_web_service/version.rb @@ -2,7 +2,7 @@ module ActionWebService module VERSION #:nodoc: MAJOR = 1 MINOR = 2 - TINY = 3 + TINY = 6 STRING = [MAJOR, MINOR, TINY].join('.') end diff --git a/vendor/rails/activerecord/CHANGELOG b/vendor/rails/activerecord/CHANGELOG index 221f588..258618a 100644 --- a/vendor/rails/activerecord/CHANGELOG +++ b/vendor/rails/activerecord/CHANGELOG @@ -1,3 +1,46 @@ +*1.15.6* (November 24th, 2007) + +* Allow association redefinition in subclasses. #9346 [wildchild] + +* Fix has_many :through delete with custom foreign keys. #6466 [naffis] + +* 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] + + +*1.15.5* (October 12th, 2007) + +* Depend on Action Pack 1.4.4 + + +*1.15.4* (October 4th, 2007) + +* Fix #count on a has_many :through association so that it recognizes the :uniq option. Closes #8801 [lifofifo] + +* Don't clobber includes passed to has_many.count [danger] + +* Make sure has_many uses :include when counting [danger] + +* Save associated records only if the association is already loaded. #8713 [blaine] + +* Changing the :default Date format doesn't break date quoting. #6312 [bshand, Elias] + +* Allow nil serialized attributes with a set class constraint. #7293 [sandofsky] + +* belongs_to assignment creates a new proxy rather than modifying its target in-place. #8412 [mmangino@elevatedrails.com] + +* Fix column type detection while loading fixtures. Closes #7987 [roderickvd] + +* Document deep eager includes. #6267 [Josh Susser, Dan Manges] + +* Oracle: extract column length for CHAR also. #7866 [ymendel] + +* Small additions and fixes for ActiveRecord documentation. Closes #7342 [jeremymcanally] + +* SQLite: binary escaping works with $KCODE='u'. #7862 [tsuka] + +* Improved cloning performance by relying less on exception raising #8159 [Blaine] + + *1.15.3* (March 12th, 2007) * Allow a polymorphic :source for has_many :through associations. Closes #7143 [protocool] diff --git a/vendor/rails/activerecord/Rakefile b/vendor/rails/activerecord/Rakefile index fb3c2c7..e7fd12c 100755 --- a/vendor/rails/activerecord/Rakefile +++ b/vendor/rails/activerecord/Rakefile @@ -151,7 +151,7 @@ spec = Gem::Specification.new do |s| s.files = s.files + Dir.glob( "#{dir}/**/*" ).delete_if { |item| item.include?( "\.svn" ) } end - s.add_dependency('activesupport', '= 1.4.2' + PKG_BUILD) + s.add_dependency('activesupport', '= 1.4.4' + PKG_BUILD) s.files.delete "test/fixtures/fixture_database.sqlite" s.files.delete "test/fixtures/fixture_database_2.sqlite" diff --git a/vendor/rails/activerecord/lib/active_record/acts/list.rb b/vendor/rails/activerecord/lib/active_record/acts/list.rb index 87bb128..fdf1c14 100644 --- a/vendor/rails/activerecord/lib/active_record/acts/list.rb +++ b/vendor/rails/activerecord/lib/active_record/acts/list.rb @@ -63,7 +63,7 @@ module ActiveRecord #{scope_condition_method} - after_destroy :remove_from_list + before_destroy :remove_from_list before_create :add_to_list_bottom EOV end @@ -74,6 +74,7 @@ module ActiveRecord # lower in the list of all chapters. Likewise, chapter.first? would return true if that chapter is # the first in the list of all chapters. module InstanceMethods + # Insert the item at the given position (defaults to the top position of 1). def insert_at(position = 1) insert_at_position(position) end @@ -118,8 +119,12 @@ module ActiveRecord end end + # Removes the item from the list. def remove_from_list - decrement_positions_on_lower_items if in_list? + if in_list? + decrement_positions_on_lower_items + update_attribute position_column, nil + end end # Increase the position of this item without adjusting the rest of the list. @@ -162,6 +167,7 @@ module ActiveRecord ) end + # Test if this record is in a list def in_list? !send(position_column).nil? end @@ -178,21 +184,26 @@ module ActiveRecord # Overwrite this method to define the scope of the list changes def scope_condition() "1" end + # Returns the bottom position number in the list. + # bottom_position_in_list # => 2 def bottom_position_in_list(except = nil) item = bottom_item(except) item ? item.send(position_column) : 0 end + # Returns the bottom item def bottom_item(except = nil) conditions = scope_condition conditions = "#{conditions} AND #{self.class.primary_key} != #{except.id}" if except acts_as_list_class.find(:first, :conditions => conditions, :order => "#{position_column} DESC") end + # Forces item to assume the bottom position in the list. def assume_bottom_position update_attribute(position_column, bottom_position_in_list(self).to_i + 1) end + # Forces item to assume the top position in the list. def assume_top_position update_attribute(position_column, 1) end @@ -227,6 +238,7 @@ module ActiveRecord ) end + # Increments position (position_column) of all items in the list. def increment_positions_on_all_items acts_as_list_class.update_all( "#{position_column} = (#{position_column} + 1)", "#{scope_condition}" diff --git a/vendor/rails/activerecord/lib/active_record/acts/tree.rb b/vendor/rails/activerecord/lib/active_record/acts/tree.rb index 44432d4..b92587e 100644 --- a/vendor/rails/activerecord/lib/active_record/acts/tree.rb +++ b/vendor/rails/activerecord/lib/active_record/acts/tree.rb @@ -70,16 +70,23 @@ module ActiveRecord nodes end + # Returns the root node of the tree. def root node = self node = node.parent while node.parent node end + # Returns all siblings of the current node. + # + # subchild1.siblings # => [subchild2] def siblings self_and_siblings - [self] end + # Returns all siblings and a reference to the current node. + # + # subchild1.self_and_siblings # => [subchild1, subchild2] def self_and_siblings parent ? parent.children : self.class.roots end diff --git a/vendor/rails/activerecord/lib/active_record/associations.rb b/vendor/rails/activerecord/lib/active_record/associations.rb index 354d3c3..1e87f00 100755 --- a/vendor/rails/activerecord/lib/active_record/associations.rb +++ b/vendor/rails/activerecord/lib/active_record/associations.rb @@ -50,6 +50,12 @@ module ActiveRecord end end + class HasManyThroughCantDissociateNewRecords < ActiveRecordError #:nodoc: + def initialize(owner, reflection) + 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.") + end + end + class EagerLoadPolymorphicError < ActiveRecordError #:nodoc: def initialize(reflection) super("Can not eagerly load the polymorphic association #{reflection.name.inspect}") @@ -352,7 +358,15 @@ module ActiveRecord # for post in Post.find(:all, :include => [ :author, :comments ]) # # 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. - # 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 + # + # To include a deep hierarchy of associations, using a hash: + # + # for post in Post.find(:all, :include => [ :author, { :comments => { :author => :gravatar } } ]) + # + # That'll grab not only all the comments but all their authors and gravatar pictures. You can mix and match + # symbols, arrays and hashes in any combination to describe the associations you want to load. + # + # 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 # 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 # 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. # @@ -734,6 +748,7 @@ module ActiveRecord deprecated_association_comparison_method(reflection.name, reflection.class_name) end + # Create the callbacks to update counter cache if options[:counter_cache] cache_column = options[:counter_cache] == true ? "#{self.to_s.underscore.pluralize}_count" : @@ -853,7 +868,7 @@ module ActiveRecord # Don't use a before_destroy callback since users' before_destroy # callbacks will be executed after the association is wiped out. old_method = "destroy_without_habtm_shim_for_#{reflection.name}" - class_eval <<-end_eval + class_eval <<-end_eval unless method_defined?(old_method) alias_method :#{old_method}, :destroy_without_callbacks def destroy_without_callbacks #{reflection.name}.clear @@ -871,6 +886,12 @@ module ActiveRecord end private + # Generate a join table name from two provided tables names. + # The order of names in join name is determined by lexical precedence. + # join_table_name("members", "clubs") + # => "clubs_members" + # join_table_name("members", "special_clubs") + # => "members_special_clubs" def join_table_name(first_table_name, second_table_name) if first_table_name < second_table_name join_table = "#{first_table_name}_#{second_table_name}" @@ -880,7 +901,7 @@ module ActiveRecord table_name_prefix + join_table + table_name_suffix end - + def association_accessor_methods(reflection, association_proxy_class) define_method(reflection.name) do |*params| force_reload = params.first unless params.empty? @@ -901,7 +922,7 @@ module ActiveRecord define_method("#{reflection.name}=") do |new_value| association = instance_variable_get("@#{reflection.name}") - if association.nil? + if association.nil? || association.target != new_value association = association_proxy_class.new(self, reflection) end @@ -911,10 +932,7 @@ module ActiveRecord instance_variable_set("@#{reflection.name}", association) else instance_variable_set("@#{reflection.name}", nil) - return nil end - - association end define_method("set_#{reflection.name}_target") do |target| @@ -981,18 +999,21 @@ module ActiveRecord after_callback = <<-end_eval association = instance_variable_get("@#{association_name}") - - if association.respond_to?(:loaded?) - if @new_record_before_save - records_to_save = association - else - records_to_save = association.select { |record| record.new_record? } - end - records_to_save.each { |record| association.send(:insert_record, record) } - association.send(:construct_sql) # reconstruct the SQL queries now that we know the owner's id + + records_to_save = if @new_record_before_save + association + elsif association.respond_to?(:loaded?) && association.loaded? + association.select { |record| record.new_record? } + else + [] end + + records_to_save.each { |record| association.send(:insert_record, record) } unless records_to_save.blank? + + # reconstruct the SQL queries now that we know the owner's id + association.send(:construct_sql) if association.respond_to?(:construct_sql) end_eval - + # Doesn't use after_save as that would save associations added in after_create/after_update twice after_create(after_callback) after_update(after_callback) @@ -1271,7 +1292,9 @@ module ActiveRecord defined_callbacks = options[callback_name.to_sym] if options.has_key?(callback_name.to_sym) class_inheritable_reader full_callback_name.to_sym - write_inheritable_array(full_callback_name.to_sym, [defined_callbacks].flatten) + write_inheritable_attribute(full_callback_name.to_sym, [defined_callbacks].flatten) + else + write_inheritable_attribute(full_callback_name.to_sym, []) end end end diff --git a/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb b/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb index 552c1ed..e5bf157 100644 --- a/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb +++ b/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb @@ -91,7 +91,11 @@ module ActiveRecord attributes.collect { |attr| create(attr) } else record = build(attributes) - record.save unless @owner.new_record? + if @owner.new_record? + 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") + else + record.save + end record end end diff --git a/vendor/rails/activerecord/lib/active_record/associations/has_many_association.rb b/vendor/rails/activerecord/lib/active_record/associations/has_many_association.rb index 0a275ab..5460c63 100644 --- a/vendor/rails/activerecord/lib/active_record/associations/has_many_association.rb +++ b/vendor/rails/activerecord/lib/active_record/associations/has_many_association.rb @@ -50,7 +50,7 @@ module ActiveRecord options[:conditions] = options[:conditions].nil? ? @finder_sql : @finder_sql + " AND (#{sanitize_sql(options[:conditions])})" - options[:include] = @reflection.options[:include] + options[:include] ||= @reflection.options[:include] @reflection.klass.count(column_name, options) end @@ -138,7 +138,7 @@ module ActiveRecord elsif @reflection.options[:counter_sql] @reflection.klass.count_by_sql(@counter_sql) else - @reflection.klass.count(:conditions => @counter_sql) + @reflection.klass.count(:conditions => @counter_sql, :include => @reflection.options[:include]) end @target = [] and loaded if count == 0 diff --git a/vendor/rails/activerecord/lib/active_record/associations/has_many_through_association.rb b/vendor/rails/activerecord/lib/active_record/associations/has_many_through_association.rb index a8ad52b..0e135c1 100644 --- a/vendor/rails/activerecord/lib/active_record/associations/has_many_through_association.rb +++ b/vendor/rails/activerecord/lib/active_record/associations/has_many_through_association.rb @@ -71,20 +71,26 @@ module ActiveRecord # Remove +records+ from this association. Does not destroy +records+. def delete(*records) - records = flatten_deeper(records) - records.each { |associate| raise_on_type_mismatch(associate) } - records.reject! { |associate| @target.delete(associate) if associate.new_record? } return if records.empty? - - @delete_join_finder ||= "find_all_by_#{@reflection.source_reflection.association_foreign_key}" + records.each { |associate| raise_on_type_mismatch(associate) } + through = @reflection.through_reflection - through.klass.transaction do - records.each do |associate| - joins = @owner.send(through.name).send(@delete_join_finder, associate.id) - @owner.send(through.name).delete(joins) + raise ActiveRecord::HasManyThroughCantDissociateNewRecords.new(@owner, through) if @owner.new_record? + + load_target + + klass = through.klass + klass.transaction do + flatten_deeper(records).each do |associate| + raise_on_type_mismatch(associate) + raise ActiveRecord::HasManyThroughCantDissociateNewRecords.new(@owner, through) unless associate.respond_to?(:new_record?) && !associate.new_record? + + @owner.send(@reflection.through_reflection.name).proxy_target.delete(klass.delete_all(construct_join_attributes(associate))) @target.delete(associate) end end + + self end def build(attrs = nil) @@ -101,6 +107,16 @@ module ActiveRecord def sum(*args, &block) calculate(:sum, *args, &block) end + + def count(*args) + column_name, options = @reflection.klass.send(:construct_count_options_from_legacy_args, *args) + if @reflection.options[:uniq] + # This is needed becase 'SELECT count(DISTINCT *)..' is not valid sql statement. + column_name = "#{@reflection.klass.table_name}.#{@reflection.klass.primary_key}" if column_name == :all + options.merge!(:distinct => true) + end + @reflection.klass.send(:with_scope, construct_scope) { @reflection.klass.count(column_name, options) } + end protected def method_missing(method, *args, &block) diff --git a/vendor/rails/activerecord/lib/active_record/base.rb b/vendor/rails/activerecord/lib/active_record/base.rb index 258aa53..6ddb1c7 100755 --- a/vendor/rails/activerecord/lib/active_record/base.rb +++ b/vendor/rails/activerecord/lib/active_record/base.rb @@ -575,7 +575,7 @@ module ActiveRecord #:nodoc: # Specifies that the attribute by the name of +attr_name+ should be serialized before saving to the database and unserialized # after loading from the database. The serialization is done through YAML. If +class_name+ is specified, the serialized - # object must be of that class on retrieval or +SerializationTypeMismatch+ will be raised. + # object must be of that class on retrieval, or nil. Otherwise, +SerializationTypeMismatch+ will be raised. def serialize(attr_name, class_name = Object) serialized_attributes[attr_name.to_s] = class_name end @@ -1188,6 +1188,9 @@ module ActiveRecord #:nodoc: # # It's even possible to use all the additional parameters to find. For example, the full interface for find_all_by_amount # is actually find_all_by_amount(amount, options). + # + # This also enables you to initialize a record if it is not found, such as find_or_initialize_by_amount(amount) + # or find_or_create_by_user_and_password(user, password). def method_missing(method_id, *arguments) if match = /^find_(all_by|by)_([_a-zA-Z]\w*)$/.match(method_id.to_s) finder, deprecated_finder = determine_finder(match), determine_deprecated_finder(match) @@ -1957,7 +1960,7 @@ module ActiveRecord #:nodoc: def unserialize_attribute(attr_name) unserialized_object = object_from_yaml(@attributes[attr_name]) - if unserialized_object.is_a?(self.class.serialized_attributes[attr_name]) + if unserialized_object.is_a?(self.class.serialized_attributes[attr_name]) || unserialized_object.nil? @attributes[attr_name] = unserialized_object else raise SerializationTypeMismatch, @@ -2156,7 +2159,13 @@ module ActiveRecord #:nodoc: def clone_attribute_value(reader_method, attribute_name) value = send(reader_method, attribute_name) - value.clone + + case value + when nil, Fixnum, true, false + value + else + value.clone + end rescue TypeError, NoMethodError value end diff --git a/vendor/rails/activerecord/lib/active_record/calculations.rb b/vendor/rails/activerecord/lib/active_record/calculations.rb index 6647458..1d9ac4b 100644 --- a/vendor/rails/activerecord/lib/active_record/calculations.rb +++ b/vendor/rails/activerecord/lib/active_record/calculations.rb @@ -242,8 +242,8 @@ module ActiveRecord options.assert_valid_keys(CALCULATIONS_OPTIONS) end - # converts a given key to the value that the database adapter returns as - # + # Converts a given key to the value that the database adapter returns as + # as a usable column name. # users.id #=> users_id # sum(id) #=> sum_id # count(distinct users.id) #=> count_distinct_users_id diff --git a/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb b/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb index 0f2008d..38ba490 100644 --- a/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb +++ b/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb @@ -24,7 +24,7 @@ module ActiveRecord when Float, Fixnum, Bignum then value.to_s # BigDecimals need to be output in a non-normalized form and quoted. when BigDecimal then value.to_s('F') - when Date then "'#{value.to_s}'" + when Date then "'#{value.to_s(:db)}'" when Time, DateTime then "'#{quoted_date(value)}'" else "'#{quote_string(value.to_yaml)}'" end diff --git a/vendor/rails/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/vendor/rails/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb index 842258f..6d0b7c0 100755 --- a/vendor/rails/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb +++ b/vendor/rails/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb @@ -119,7 +119,7 @@ module ActiveRecord # # * :host -- Defaults to localhost # * :port -- Defaults to 3306 - # * :socket -- Defaults to /tmp/mysql.sock + # * :socket -- Defaults to /var/run/mysqld/mysqld.sock # * :username -- Defaults to root # * :password -- Defaults to nothing # * :database -- The name of the database. No default, must be provided. diff --git a/vendor/rails/activerecord/lib/active_record/connection_adapters/oracle_adapter.rb b/vendor/rails/activerecord/lib/active_record/connection_adapters/oracle_adapter.rb index 4e7c3c3..c69b844 100644 --- a/vendor/rails/activerecord/lib/active_record/connection_adapters/oracle_adapter.rb +++ b/vendor/rails/activerecord/lib/active_record/connection_adapters/oracle_adapter.rb @@ -320,6 +320,7 @@ begin decode(data_type, 'NUMBER', data_precision, 'FLOAT', data_precision, 'VARCHAR2', data_length, + 'CHAR', data_length, null) as limit, decode(data_type, 'NUMBER', data_scale, null) as scale from all_tab_columns diff --git a/vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index 2a26897..0a9c57e 100644 --- a/vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/vendor/rails/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -68,7 +68,7 @@ module ActiveRecord class SQLiteColumn < Column #:nodoc: class << self def string_to_binary(value) - value.gsub(/\0|\%/) do |b| + value.gsub(/\0|\%/n) do |b| case b when "\0" then "%00" when "%" then "%25" @@ -77,7 +77,7 @@ module ActiveRecord end def binary_to_string(value) - value.gsub(/%00|%25/) do |b| + value.gsub(/%00|%25/n) do |b| case b when "%00" then "\0" when "%25" then "%" diff --git a/vendor/rails/activerecord/lib/active_record/deprecated_finders.rb b/vendor/rails/activerecord/lib/active_record/deprecated_finders.rb index 4ab2dde..d4dcaa3 100644 --- a/vendor/rails/activerecord/lib/active_record/deprecated_finders.rb +++ b/vendor/rails/activerecord/lib/active_record/deprecated_finders.rb @@ -1,7 +1,7 @@ module ActiveRecord class Base class << self - # This method is deprecated in favor of find with the :conditions option. + # DEPRECATION NOTICE: This method is deprecated in favor of find with the :conditions option. # # Works like find, but the record matching +id+ must also meet the +conditions+. # +RecordNotFound+ is raised if no record can be found matching the +id+ or meeting the condition. @@ -12,7 +12,7 @@ module ActiveRecord end deprecate :find_on_conditions => "use find(ids, :conditions => conditions)" - # This method is deprecated in favor of find(:first, options). + # DEPRECATION NOTICE: This method is deprecated in favor of find(:first, options). # # Returns the object for the first record responding to the conditions in +conditions+, # 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 end deprecate :find_first => "use find(:first, ...)" - # This method is deprecated in favor of find(:all, options). + # DEPRECATION NOTICE: This method is deprecated in favor of find(:all, options). # # Returns an array of all the objects that could be instantiated from the associated # table in the database. The +conditions+ can be used to narrow the selection of objects (WHERE-part), diff --git a/vendor/rails/activerecord/lib/active_record/fixtures.rb b/vendor/rails/activerecord/lib/active_record/fixtures.rb index 4109d36..43d4bda 100755 --- a/vendor/rails/activerecord/lib/active_record/fixtures.rb +++ b/vendor/rails/activerecord/lib/active_record/fixtures.rb @@ -412,7 +412,7 @@ class Fixture #:nodoc: klass = @class_name.constantize rescue nil list = @fixture.inject([]) do |fixtures, (key, value)| - col = klass.columns_hash[key] if klass.kind_of?(ActiveRecord::Base) + col = klass.columns_hash[key] if klass.respond_to?(:ancestors) && klass.ancestors.include?(ActiveRecord::Base) fixtures << ActiveRecord::Base.connection.quote(value, col).gsub('[^\]\\n', "\n").gsub('[^\]\\r', "\r") end list * ', ' diff --git a/vendor/rails/activerecord/lib/active_record/timestamp.rb b/vendor/rails/activerecord/lib/active_record/timestamp.rb index 9c7e798..2fff7b9 100644 --- a/vendor/rails/activerecord/lib/active_record/timestamp.rb +++ b/vendor/rails/activerecord/lib/active_record/timestamp.rb @@ -5,15 +5,6 @@ module ActiveRecord # Timestamping can be turned off by setting # ActiveRecord::Base.record_timestamps = false # - # Keep in mind that, via inheritance, you can turn off timestamps on a per - # model basis by setting record_timestamps to false in the desired - # models. - # - # class Feed < ActiveRecord::Base - # self.record_timestamps = false - # # ... - # end - # # Timestamps are in the local timezone by default but can use UTC by setting # ActiveRecord::Base.default_timezone = :utc module Timestamp diff --git a/vendor/rails/activerecord/lib/active_record/vendor/mysql.rb b/vendor/rails/activerecord/lib/active_record/vendor/mysql.rb index 1c3294c..fcd6656 100644 --- a/vendor/rails/activerecord/lib/active_record/vendor/mysql.rb +++ b/vendor/rails/activerecord/lib/active_record/vendor/mysql.rb @@ -14,7 +14,7 @@ class Mysql MAX_PACKET_LENGTH = 256*256*256-1 MAX_ALLOWED_PACKET = 1024*1024*1024 - MYSQL_UNIX_ADDR = "/tmp/mysql.sock" + MYSQL_UNIX_ADDR = "/var/run/mysqld/mysqld.sock" MYSQL_PORT = 3306 PROTOCOL_VERSION = 10 diff --git a/vendor/rails/activerecord/lib/active_record/version.rb b/vendor/rails/activerecord/lib/active_record/version.rb index 4027561..73bd338 100644 --- a/vendor/rails/activerecord/lib/active_record/version.rb +++ b/vendor/rails/activerecord/lib/active_record/version.rb @@ -2,7 +2,7 @@ module ActiveRecord module VERSION #:nodoc: MAJOR = 1 MINOR = 15 - TINY = 3 + TINY = 6 STRING = [MAJOR, MINOR, TINY].join('.') end diff --git a/vendor/rails/activerecord/test/aggregations_test.rb b/vendor/rails/activerecord/test/aggregations_test.rb index 8cd4bfe..7a69cc5 100644 --- a/vendor/rails/activerecord/test/aggregations_test.rb +++ b/vendor/rails/activerecord/test/aggregations_test.rb @@ -93,3 +93,21 @@ class AggregationsTest < Test::Unit::TestCase assert_raises(NoMethodError) { customers(:david).balance = nil } end end + +class OverridingAggregationsTest < Test::Unit::TestCase + class Name; end + class DifferentName; end + + class Person < ActiveRecord::Base + composed_of :composed_of, :mapping => %w(person_first_name first_name) + end + + class DifferentPerson < Person + composed_of :composed_of, :class_name => 'DifferentName', :mapping => %w(different_person_first_name first_name) + end + + def test_composed_of_aggregation_redefinition_reflections_should_differ_and_not_inherited + assert_not_equal Person.reflect_on_aggregation(:composed_of), + DifferentPerson.reflect_on_aggregation(:composed_of) + end +end diff --git a/vendor/rails/activerecord/test/associations/eager_test.rb b/vendor/rails/activerecord/test/associations/eager_test.rb index 0d69af1..6c054e9 100644 --- a/vendor/rails/activerecord/test/associations/eager_test.rb +++ b/vendor/rails/activerecord/test/associations/eager_test.rb @@ -168,6 +168,12 @@ class EagerAssociationTest < Test::Unit::TestCase posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => "posts.title = 'magic forest'") assert_equal 0, posts.size end + + def test_eager_count_performed_on_a_has_many_association_with_multi_table_conditional + author = authors(:david) + author_posts_without_comments = author.posts.select { |post| post.comments.blank? } + assert_equal author_posts_without_comments.size, author.posts.count(:all, :include => :comments, :conditions => 'comments.id is null') + end def test_eager_with_has_and_belongs_to_many_and_limit posts = Post.find(:all, :include => :categories, :order => "posts.id", :limit => 3) @@ -271,6 +277,13 @@ class EagerAssociationTest < Test::Unit::TestCase assert_not_nil f.account assert_equal companies(:first_firm, :reload).account, f.account end + + def test_eager_with_multi_table_conditional_properly_counts_the_records_when_using_size + author = authors(:david) + posts_with_no_comments = author.posts.select { |post| post.comments.blank? } + assert_equal posts_with_no_comments.size, author.posts_with_no_comments.size + assert_equal posts_with_no_comments, author.posts_with_no_comments + end def test_eager_with_invalid_association_reference assert_raises(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") { diff --git a/vendor/rails/activerecord/test/associations/join_model_test.rb b/vendor/rails/activerecord/test/associations/join_model_test.rb index a5e525c..4be8ded 100644 --- a/vendor/rails/activerecord/test/associations/join_model_test.rb +++ b/vendor/rails/activerecord/test/associations/join_model_test.rb @@ -8,10 +8,12 @@ require 'fixtures/category' require 'fixtures/categorization' require 'fixtures/vertex' require 'fixtures/edge' +require 'fixtures/book' +require 'fixtures/citation' class AssociationsJoinModelTest < Test::Unit::TestCase self.use_transactional_fixtures = false - fixtures :posts, :authors, :categories, :categorizations, :comments, :tags, :taggings, :author_favorites, :vertices + fixtures :posts, :authors, :categories, :categorizations, :comments, :tags, :taggings, :author_favorites, :vertices, :books def test_has_many assert authors(:david).categories.include?(categories(:general)) @@ -29,7 +31,16 @@ class AssociationsJoinModelTest < Test::Unit::TestCase assert_equal 2, authors(:mary).categorized_posts.size assert_equal 1, authors(:mary).unique_categorized_posts.size end - + + def test_has_many_uniq_through_count + author = authors(:mary) + assert !authors(:mary).unique_categorized_posts.loaded? + assert_queries(1) { assert_equal 1, author.unique_categorized_posts.count } + assert_queries(1) { assert_equal 1, author.unique_categorized_posts.count(:title, {}) } + assert_queries(1) { assert_equal 0, author.unique_categorized_posts.count(:title, { :conditions => "title is NULL" }) } + assert !authors(:mary).unique_categorized_posts.loaded? + end + def test_polymorphic_has_many assert posts(:welcome).taggings.include?(taggings(:welcome_general)) end @@ -441,7 +452,21 @@ class AssociationsJoinModelTest < Test::Unit::TestCase tags = posts(:thinking).tags assert_equal tags, posts(:thinking).tags.push(tags(:general)) end - + + def test_delete_associate_when_deleting_from_has_many_through_with_non_standard_id + count = books(:awdr).references.count + references_before = books(:awdr).references + book = Book.create!(:name => 'Getting Real') + book_awdr = books(:awdr) + book_awdr.references << book + assert_equal(count + 1, book_awdr.references(true).size) + + assert_nothing_raised { book_awdr.references.delete(book) } + assert_equal(count, book_awdr.references.size) + assert_equal(count, book_awdr.references(true).size) + assert_equal(references_before.sort, book_awdr.references.sort) + end + def test_delete_associate_when_deleting_from_has_many_through count = posts(:thinking).tags.count tags_before = posts(:thinking).tags diff --git a/vendor/rails/activerecord/test/associations_test.rb b/vendor/rails/activerecord/test/associations_test.rb index f1b02cf..9d57fd0 100755 --- a/vendor/rails/activerecord/test/associations_test.rb +++ b/vendor/rails/activerecord/test/associations_test.rb @@ -10,6 +10,8 @@ require 'fixtures/order' require 'fixtures/category' require 'fixtures/post' require 'fixtures/author' +require 'fixtures/person' +require 'fixtures/reader' class AssociationsTest < Test::Unit::TestCase @@ -21,6 +23,14 @@ class AssociationsTest < Test::Unit::TestCase Class.new(ActiveRecord::Base).has_many(:wheels, :name => 'wheels') end end + + def test_should_construct_new_finder_sql_after_create + person = Person.new + assert_equal [], person.readers.find(:all) + person.save! + reader = Reader.create! :person => person, :post => Post.new(:title => "foo", :body => "bar") + assert_equal [reader], person.readers.find(:all) + end def test_force_reload firm = Firm.new("name" => "A New Firm, Inc") @@ -67,8 +77,8 @@ class AssociationsTest < Test::Unit::TestCase end class AssociationProxyTest < Test::Unit::TestCase - fixtures :authors, :posts - + fixtures :authors, :posts, :developers, :projects, :developers_projects + def test_proxy_accessors welcome = posts(:welcome) assert_equal welcome, welcome.author.proxy_owner @@ -87,6 +97,19 @@ class AssociationProxyTest < Test::Unit::TestCase david.posts_with_extension.first # force load target assert_equal david.posts_with_extension, david.posts_with_extension.testing_proxy_target end + + def test_save_on_parent_does_not_load_target + david = developers(:david) + + assert !david.projects.loaded? + david.update_attribute(:created_at, Time.now) + assert !david.projects.loaded? + end + + def test_save_on_parent_saves_children + developer = Developer.create :name => "Bryan", :salary => 50_000 + assert_equal 1, developer.reload.audit_logs.size + end end class HasOneAssociationsTest < Test::Unit::TestCase @@ -583,6 +606,13 @@ class HasManyAssociationsTest < Test::Unit::TestCase assert_equal 3, first_firm.plain_clients.size end + def test_regular_create_on_has_many_when_parent_is_new_raises + assert_deprecated(/.build instead/) do + firm = Firm.new + firm.plain_clients.create :name=>"Whoever" + end + end + def test_adding_a_mismatch_class assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << nil } assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << 1 } @@ -1007,7 +1037,20 @@ class BelongsToAssociationsTest < Test::Unit::TestCase citibank.firm = apple assert_equal apple.id, citibank.firm_id end - + + def test_no_unexpected_aliasing + first_firm = companies(:first_firm) + another_firm = companies(:another_firm) + + citibank = Account.create("credit_limit" => 10) + citibank.firm = first_firm + original_proxy = citibank.firm + citibank.firm = another_firm + + assert_equal first_firm.object_id, original_proxy.object_id + assert_equal another_firm.object_id, citibank.firm.object_id + end + def test_creating_the_belonging_object citibank = Account.create("credit_limit" => 10) apple = citibank.create_firm("name" => "Apple") @@ -1807,3 +1850,68 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase assert_equal %w(1 2), projects.scan(/\d/).sort end end + + +class OverridingAssociationsTest < Test::Unit::TestCase + class Person < ActiveRecord::Base; end + class DifferentPerson < ActiveRecord::Base; end + + class PeopleList < ActiveRecord::Base + has_and_belongs_to_many :has_and_belongs_to_many, :before_add => :enlist + has_many :has_many, :before_add => :enlist + belongs_to :belongs_to + has_one :has_one + end + + class DifferentPeopleList < PeopleList + # Different association with the same name, callbacks should be omitted here. + has_and_belongs_to_many :has_and_belongs_to_many, :class_name => 'DifferentPerson' + has_many :has_many, :class_name => 'DifferentPerson' + belongs_to :belongs_to, :class_name => 'DifferentPerson', :foreign_key => 'belongs_to_id' + has_one :has_one, :class_name => 'DifferentPerson' + end + + def test_habtm_association_redefinition_callbacks_should_differ_and_not_inherited + # redeclared association on AR descendant should not inherit callbacks from superclass + callbacks = PeopleList.read_inheritable_attribute(:before_add_for_has_and_belongs_to_many) + assert_equal([:enlist], callbacks) + callbacks = DifferentPeopleList.read_inheritable_attribute(:before_add_for_has_and_belongs_to_many) + assert_equal([], callbacks) + end + + def test_has_many_association_redefinition_callbacks_should_differ_and_not_inherited + # redeclared association on AR descendant should not inherit callbacks from superclass + callbacks = PeopleList.read_inheritable_attribute(:before_add_for_has_many) + assert_equal([:enlist], callbacks) + callbacks = DifferentPeopleList.read_inheritable_attribute(:before_add_for_has_many) + assert_equal([], callbacks) + end + + def test_habtm_association_redefinition_reflections_should_differ_and_not_inherited + assert_not_equal( + PeopleList.reflect_on_association(:has_and_belongs_to_many), + DifferentPeopleList.reflect_on_association(:has_and_belongs_to_many) + ) + end + + def test_has_many_association_redefinition_reflections_should_differ_and_not_inherited + assert_not_equal( + PeopleList.reflect_on_association(:has_many), + DifferentPeopleList.reflect_on_association(:has_many) + ) + end + + def test_belongs_to_association_redefinition_reflections_should_differ_and_not_inherited + assert_not_equal( + PeopleList.reflect_on_association(:belongs_to), + DifferentPeopleList.reflect_on_association(:belongs_to) + ) + end + + def test_has_one_association_redefinition_reflections_should_differ_and_not_inherited + assert_not_equal( + PeopleList.reflect_on_association(:has_one), + DifferentPeopleList.reflect_on_association(:has_one) + ) + end +end diff --git a/vendor/rails/activerecord/test/base_test.rb b/vendor/rails/activerecord/test/base_test.rb index 2e98952..fd4ddc0 100755 --- a/vendor/rails/activerecord/test/base_test.rb +++ b/vendor/rails/activerecord/test/base_test.rb @@ -1086,16 +1086,29 @@ class BasicsTest < Test::Unit::TestCase assert_equal(myobj, topic.content) end - def test_serialized_attribute_with_class_constraint + def test_nil_serialized_attribute_with_class_constraint myobj = MyObject.new('value1', 'value2') - topic = Topic.create("content" => myobj) - Topic.serialize(:content, Hash) + topic = Topic.new + assert_nil topic.content + end + def test_should_raise_exception_on_serialized_attribute_with_type_mismatch + myobj = MyObject.new('value1', 'value2') + topic = Topic.new(:content => myobj) + assert topic.save + Topic.serialize(:content, Hash) assert_raise(ActiveRecord::SerializationTypeMismatch) { Topic.find(topic.id).content } + ensure + Topic.serialize(:content) + end + def test_serialized_attribute_with_class_constraint settings = { "color" => "blue" } - Topic.find(topic.id).update_attribute("content", settings) + Topic.serialize(:content, Hash) + topic = Topic.new(:content => settings) + assert topic.save assert_equal(settings, Topic.find(topic.id).content) + ensure Topic.serialize(:content) end diff --git a/vendor/rails/activerecord/test/fixtures/author.rb b/vendor/rails/activerecord/test/fixtures/author.rb index 6b34c75..5571f2c 100644 --- a/vendor/rails/activerecord/test/fixtures/author.rb +++ b/vendor/rails/activerecord/test/fixtures/author.rb @@ -25,6 +25,7 @@ class Author < ActiveRecord::Base has_many :hello_posts, :class_name => "Post", :conditions => "posts.body = 'hello'" has_many :hello_post_comments, :through => :hello_posts, :source => :comments + has_many :posts_with_no_comments, :class_name => 'Post', :conditions => 'comments.id is null', :include => :comments has_many :other_posts, :class_name => "Post" has_many :posts_with_callbacks, :class_name => "Post", :before_add => :log_before_adding, diff --git a/vendor/rails/activerecord/test/fixtures/binaries.yml b/vendor/rails/activerecord/test/fixtures/binaries.yml new file mode 100644 index 0000000..b01e690 --- /dev/null +++ b/vendor/rails/activerecord/test/fixtures/binaries.yml @@ -0,0 +1,437 @@ +flowers: + id: 1 + data: !binary | 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 + KKpVChRRRQAUUUUAFFFFABRRRQAUUUUAf//Z + diff --git a/vendor/rails/activerecord/test/fixtures/book.rb b/vendor/rails/activerecord/test/fixtures/book.rb new file mode 100644 index 0000000..cfd07ab --- /dev/null +++ b/vendor/rails/activerecord/test/fixtures/book.rb @@ -0,0 +1,4 @@ +class Book < ActiveRecord::Base + has_many :citations, :foreign_key => 'book1_id' + has_many :references, :through => :citations, :source => :reference_of, :uniq => true +end diff --git a/vendor/rails/activerecord/test/fixtures/books.yml b/vendor/rails/activerecord/test/fixtures/books.yml new file mode 100644 index 0000000..473663f --- /dev/null +++ b/vendor/rails/activerecord/test/fixtures/books.yml @@ -0,0 +1,7 @@ +awdr: + id: 1 + name: "Agile Web Development with Rails" + +rfr: + id: 2 + name: "Ruby for Rails" diff --git a/vendor/rails/activerecord/test/fixtures/citation.rb b/vendor/rails/activerecord/test/fixtures/citation.rb new file mode 100644 index 0000000..545aa81 --- /dev/null +++ b/vendor/rails/activerecord/test/fixtures/citation.rb @@ -0,0 +1,6 @@ +class Citation < ActiveRecord::Base + belongs_to :reference_of, :class_name => "Book", :foreign_key => :book2_id + + belongs_to :book1, :class_name => "Book", :foreign_key => :book1_id + belongs_to :book2, :class_name => "Book", :foreign_key => :book2_id +end diff --git a/vendor/rails/activerecord/test/fixtures/db_definitions/schema.rb b/vendor/rails/activerecord/test/fixtures/db_definitions/schema.rb index 9c85181..45f9dcc 100644 --- a/vendor/rails/activerecord/test/fixtures/db_definitions/schema.rb +++ b/vendor/rails/activerecord/test/fixtures/db_definitions/schema.rb @@ -57,4 +57,18 @@ ActiveRecord::Schema.define do create_table :lock_without_defaults_cust, :force => true do |t| t.column :custom_lock_version, :integer end + + create_table :audit_logs, :force => true do |t| + t.column :message, :string, :null=>false + t.column :developer_id, :integer, :null=>false + end + + create_table :books, :force => true do |t| + t.column :name, :string + end + + create_table :citations, :force => true do |t| + t.column :book1_id, :integer + t.column :book2_id, :integer + end end diff --git a/vendor/rails/activerecord/test/fixtures/developer.rb b/vendor/rails/activerecord/test/fixtures/developer.rb index 75fb307..ebe91a4 100644 --- a/vendor/rails/activerecord/test/fixtures/developer.rb +++ b/vendor/rails/activerecord/test/fixtures/developer.rb @@ -31,8 +31,18 @@ class Developer < ActiveRecord::Base has_and_belongs_to_many :special_projects, :join_table => 'developers_projects', :association_foreign_key => 'project_id' + has_many :audit_logs + validates_inclusion_of :salary, :in => 50000..200000 validates_length_of :name, :within => 3..20 + + before_create do |developer| + developer.audit_logs.build :message => "Computer created" + end +end + +class AuditLog < ActiveRecord::Base + belongs_to :developer end DeveloperSalary = Struct.new(:amount) diff --git a/vendor/rails/activerecord/test/fixtures_test.rb b/vendor/rails/activerecord/test/fixtures_test.rb index 3588252..2a9c78e 100755 --- a/vendor/rails/activerecord/test/fixtures_test.rb +++ b/vendor/rails/activerecord/test/fixtures_test.rb @@ -12,13 +12,15 @@ class FixturesTest < Test::Unit::TestCase self.use_instantiated_fixtures = true self.use_transactional_fixtures = false - fixtures :topics, :developers, :accounts, :tasks, :categories, :funny_jokes + fixtures :topics, :developers, :accounts, :tasks, :categories, :funny_jokes, :binaries - FIXTURES = %w( accounts companies customers + FIXTURES = %w( accounts binaries companies customers developers developers_projects entrants movies projects subscribers topics tasks ) MATCH_ATTRIBUTE_NAME = /[a-zA-Z][-_\w]*/ + BINARY_FIXTURE_PATH = File.dirname(__FILE__) + '/fixtures/flowers.jpg' + def test_clean_fixtures FIXTURES.each do |name| fixtures = nil @@ -100,7 +102,6 @@ class FixturesTest < Test::Unit::TestCase assert first end - def test_bad_format path = File.join(File.dirname(__FILE__), 'fixtures', 'bad_fixtures') Dir.entries(path).each do |file| @@ -174,7 +175,6 @@ class FixturesTest < Test::Unit::TestCase end end - def test_yml_file_in_subdirectory assert_equal(categories(:sub_special_1).name, "A special category in a subdir file") assert_equal(categories(:sub_special_1).class, SpecialCategory) @@ -185,7 +185,11 @@ class FixturesTest < Test::Unit::TestCase assert_equal(categories(:sub_special_3).class, SpecialCategory) end - + def test_binary_in_fixtures + assert_equal 1, @binaries.size + data = File.read(BINARY_FIXTURE_PATH).freeze + assert_equal data, @flowers.data + end end if Account.connection.respond_to?(:reset_pk_sequence!) diff --git a/vendor/rails/activerecord/test/migration_test.rb b/vendor/rails/activerecord/test/migration_test.rb index 0d78a4e..8ae97c7 100644 --- a/vendor/rails/activerecord/test/migration_test.rb +++ b/vendor/rails/activerecord/test/migration_test.rb @@ -170,7 +170,7 @@ if ActiveRecord::Base.connection.supports_migrations? # SQL Server and Sybase will not allow you to add a NOT NULL column # to a table without specifying a default value, so the # following test must be skipped - unless current_adapter?(:SQLServerAdapter, :SybaseAdapter) + unless current_adapter?(:SQLServerAdapter, :SybaseAdapter, :SQLiteAdapter) def test_add_column_not_null_without_default Person.connection.create_table :testings do |t| t.column :foo, :string @@ -209,7 +209,7 @@ if ActiveRecord::Base.connection.supports_migrations? def test_native_decimal_insert_manual_vs_automatic # SQLite3 always uses float in violation of SQL # 16 decimal places - correct_value = (current_adapter?(:SQLiteAdapter) ? '0.123456789012346E20' : '0012345678901234567890.0123456789').to_d + correct_value = '0012345678901234567890.0123456789'.to_d Person.delete_all Person.connection.add_column "people", "wealth", :decimal, :precision => '30', :scale => '10' @@ -227,8 +227,9 @@ if ActiveRecord::Base.connection.supports_migrations? assert_kind_of BigDecimal, row.wealth # If this assert fails, that means the SELECT is broken! - assert_equal correct_value, row.wealth - + unless current_adapter?(:SQLite3Adapter) + assert_equal correct_value, row.wealth + end # Reset to old state Person.delete_all @@ -240,8 +241,9 @@ if ActiveRecord::Base.connection.supports_migrations? assert_kind_of BigDecimal, row.wealth # If these asserts fail, that means the INSERT (create function, or cast to SQL) is broken! - assert_equal correct_value, row.wealth - + unless current_adapter?(:SQLite3Adapter) + assert_equal correct_value, row.wealth + end # Reset to old state Person.connection.del_column "people", "wealth" rescue nil Person.reset_column_information @@ -267,10 +269,7 @@ if ActiveRecord::Base.connection.supports_migrations? # Test for 30 significent digits (beyond the 16 of float), 10 of them # after the decimal place. - if current_adapter?(:SQLiteAdapter) - # SQLite3 uses float in violation of SQL. Test for 16 decimal places. - assert_equal BigDecimal.new('0.123456789012346E20'), bob.wealth - else + unless current_adapter?(:SQLite3Adapter) assert_equal BigDecimal.new("0012345678901234567890.0123456789"), bob.wealth end diff --git a/vendor/rails/activerecord/test/mixin_test.rb b/vendor/rails/activerecord/test/mixin_test.rb index d4fbab8..e10650e 100644 --- a/vendor/rails/activerecord/test/mixin_test.rb +++ b/vendor/rails/activerecord/test/mixin_test.rb @@ -211,6 +211,53 @@ class ListTest < Test::Unit::TestCase assert_equal [new2, new1, new3], ListMixin.find(:all, :conditions => 'parent_id IS NULL', :order => 'pos') end + def test_remove_from_list_should_then_fail_in_list? + assert_equal true, mixins(:list_1).in_list? + mixins(:list_1).remove_from_list + assert_equal false, mixins(:list_1).in_list? + end + + def test_remove_from_list_should_set_position_to_nil + assert_equal [mixins(:list_1), + mixins(:list_2), + mixins(:list_3), + mixins(:list_4)], + ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos') + + mixins(:list_2).remove_from_list + + assert_equal [mixins(:list_2, :reload), + mixins(:list_1, :reload), + mixins(:list_3, :reload), + mixins(:list_4, :reload)], + ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos') + + assert_equal 1, mixins(:list_1).pos + assert_equal nil, mixins(:list_2).pos + assert_equal 2, mixins(:list_3).pos + assert_equal 3, mixins(:list_4).pos + end + + def test_remove_before_destroy_does_not_shift_lower_items_twice + assert_equal [mixins(:list_1), + mixins(:list_2), + mixins(:list_3), + mixins(:list_4)], + ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos') + + mixins(:list_2).remove_from_list + mixins(:list_2).destroy + + assert_equal [mixins(:list_1, :reload), + mixins(:list_3, :reload), + mixins(:list_4, :reload)], + ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos') + + assert_equal 1, mixins(:list_1).pos + assert_equal 2, mixins(:list_3).pos + assert_equal 3, mixins(:list_4).pos + end + end class TreeTest < Test::Unit::TestCase diff --git a/vendor/rails/activerecord/test/validations_test.rb b/vendor/rails/activerecord/test/validations_test.rb index 9984b48..93c9ad4 100755 --- a/vendor/rails/activerecord/test/validations_test.rb +++ b/vendor/rails/activerecord/test/validations_test.rb @@ -631,7 +631,7 @@ class ValidationsTest < Test::Unit::TestCase t = Topic.new('title' => 'noreplies', 'content' => 'whatever') assert !t.save assert t.errors.on(:replies) - t.replies.create('title' => 'areply', 'content' => 'whateveragain') + t.replies.build('title' => 'areply', 'content' => 'whateveragain') assert t.valid? end @@ -824,7 +824,7 @@ class ValidationsTest < Test::Unit::TestCase t = Topic.new('title' => 'あいうえお', 'content' => 'かきくけこ') assert !t.save assert t.errors.on(:replies) - t.replies.create('title' => 'あいうえお', 'content' => 'かきくけこ') + t.replies.build('title' => 'あいうえお', 'content' => 'かきくけこ') assert t.valid? end end diff --git a/vendor/rails/activesupport/CHANGELOG b/vendor/rails/activesupport/CHANGELOG index a0f7948..f6a025f 100644 --- a/vendor/rails/activesupport/CHANGELOG +++ b/vendor/rails/activesupport/CHANGELOG @@ -1,3 +1,19 @@ +*1.4.4* (October 12th, 2007) + +* 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] + + +*1.4.3* (October 4th, 2007) + +* Demote Hash#to_xml to use XmlSimple#xml_in_string so it can't read files or stdin. #8453 [candlerb, Jeremy Kemper] + +* Document Object#blank?. #6491 [Chris Mear] + +* Update Dependencies to ignore constants inherited from ancestors. Closes #6951. [Nicholas Seckar] + +* Improved multibyte performance by relying less on exception raising #8159 [Blaine] + + *1.4.2* (March 12th, 2007) * Ruby 1.8.6 and 1.9 define private Time#to_date and #to_datetime; make them diff --git a/vendor/rails/activesupport/lib/active_support/core_ext/blank.rb b/vendor/rails/activesupport/lib/active_support/core_ext/blank.rb index f7fbea3..d2a940f 100644 --- a/vendor/rails/activesupport/lib/active_support/core_ext/blank.rb +++ b/vendor/rails/activesupport/lib/active_support/core_ext/blank.rb @@ -1,5 +1,11 @@ -class Object #:nodoc: - # "", " ", nil, [], and {} are blank +class Object + # An object is blank if it's nil, empty, or a whitespace string. + # For example, "", " ", nil, [], and {} are blank. + # + # This simplifies + # if !address.nil? && !address.empty? + # to + # if !address.blank? def blank? if respond_to?(:empty?) && respond_to?(:strip) empty? or strip.empty? @@ -47,4 +53,4 @@ class Numeric #:nodoc: def blank? false end -end \ No newline at end of file +end diff --git a/vendor/rails/activesupport/lib/active_support/core_ext/hash/conversions.rb b/vendor/rails/activesupport/lib/active_support/core_ext/hash/conversions.rb index 83054cd..9331140 100644 --- a/vendor/rails/activesupport/lib/active_support/core_ext/hash/conversions.rb +++ b/vendor/rails/activesupport/lib/active_support/core_ext/hash/conversions.rb @@ -1,5 +1,44 @@ require 'date' require 'xml_simple' +require 'cgi' + +# Extensions needed for Hash#to_query +class Object + def to_param #:nodoc: + to_s + end + + def to_query(key) #:nodoc: + "#{CGI.escape(key.to_s)}=#{CGI.escape(to_param.to_s)}" + end +end + +class Array + def to_query(key) #:nodoc: + collect { |value| value.to_query("#{key}[]") }.sort * '&' + end +end + +# Locked down XmlSimple#xml_in_string +class XmlSimple + # Same as xml_in but doesn't try to smartly shoot itself in the foot. + def xml_in_string(string, options = nil) + handle_options('in', options) + + @doc = parse(string) + result = collapse(@doc.root) + + if @options['keeproot'] + merge({}, @doc.root.name, result) + else + result + end + end + + def self.xml_in_string(string, options = nil) + new.xml_in_string(string, options) + end +end module ActiveSupport #:nodoc: module CoreExtensions #:nodoc: @@ -27,6 +66,12 @@ module ActiveSupport #:nodoc: klass.extend(ClassMethods) end + def to_query(namespace = nil) + collect do |key, value| + value.to_query(namespace ? "#{namespace}[#{key}]" : key) + end.sort * '&' + end + def to_xml(options = {}) options[:indent] ||= 2 options.reverse_merge!({ :builder => Builder::XmlMarkup.new(:indent => options[:indent]), @@ -81,14 +126,14 @@ module ActiveSupport #:nodoc: module ClassMethods def from_xml(xml) # TODO: Refactor this into something much cleaner that doesn't rely on XmlSimple - undasherize_keys(typecast_xml_value(XmlSimple.xml_in(xml, + undasherize_keys(typecast_xml_value(XmlSimple.xml_in_string(xml, 'forcearray' => false, 'forcecontent' => true, 'keeproot' => true, 'contentkey' => '__content__') - )) + )) end - + def create_from_xml(xml) ActiveSupport::Deprecation.warn("Hash.create_from_xml has been renamed to Hash.from_xml", caller) from_xml(xml) diff --git a/vendor/rails/activesupport/lib/active_support/core_ext/module/introspection.rb b/vendor/rails/activesupport/lib/active_support/core_ext/module/introspection.rb index 0cd0d1f..3648192 100644 --- a/vendor/rails/activesupport/lib/active_support/core_ext/module/introspection.rb +++ b/vendor/rails/activesupport/lib/active_support/core_ext/module/introspection.rb @@ -18,4 +18,18 @@ class Module parents << Object unless parents.include? Object parents end + + # Return the constants that have been defined locally by this object and not + # in an ancestor. This method may miss some constants if their definition in + # the ancestor is identical to their definition in the receiver. + def local_constants + inherited = {} + ancestors.each do |anc| + next if anc == self + anc.constants.each { |const| inherited[const] = anc.const_get(const) } + end + constants.select do |const| + ! inherited.key?(const) || inherited[const].object_id != const_get(const).object_id + end + end end diff --git a/vendor/rails/activesupport/lib/active_support/dependencies.rb b/vendor/rails/activesupport/lib/active_support/dependencies.rb index 4880b70..2f6ae28 100644 --- a/vendor/rails/activesupport/lib/active_support/dependencies.rb +++ b/vendor/rails/activesupport/lib/active_support/dependencies.rb @@ -318,13 +318,13 @@ module Dependencies #:nodoc: watch_frames = descs.collect do |desc| if desc.is_a? Module mod_name = desc.name - initial_constants = desc.constants + initial_constants = desc.local_constants elsif desc.is_a?(String) || desc.is_a?(Symbol) mod_name = desc.to_s # Handle the case where the module has yet to be defined. initial_constants = if qualified_const_defined?(mod_name) - mod_name.constantize.constants + mod_name.constantize.local_constants else [] end @@ -349,7 +349,7 @@ module Dependencies #:nodoc: mod = mod_name.constantize next [] unless mod.is_a? Module - new_constants = mod.constants - prior_constants + new_constants = mod.local_constants - prior_constants # Make sure no other frames takes credit for these constants. constant_watch_stack.each do |frame_name, constants| diff --git a/vendor/rails/activesupport/lib/active_support/json/encoders/core.rb b/vendor/rails/activesupport/lib/active_support/json/encoders/core.rb index f6cdfbc..df50c01 100644 --- a/vendor/rails/activesupport/lib/active_support/json/encoders/core.rb +++ b/vendor/rails/activesupport/lib/active_support/json/encoders/core.rb @@ -23,12 +23,14 @@ module ActiveSupport "\n" => '\n', "\r" => '\r', "\t" => '\t', - '"' => '\"', - '\\' => '\\\\' + '"' => '\"', + '\\' => '\\\\', + '<' => '\\074', + '>' => '\\076' } define_encoder String do |string| - '"' + string.gsub(/[\010\f\n\r\t"\\]/) { |s| + '"' + string.gsub(/[\010\f\n\r\t"\\<>]/) { |s| ESCAPED_CHARS[s] }.gsub(/([\xC0-\xDF][\x80-\xBF]| [\xE0-\xEF][\x80-\xBF]{2}| diff --git a/vendor/rails/activesupport/lib/active_support/multibyte/chars.rb b/vendor/rails/activesupport/lib/active_support/multibyte/chars.rb index 374adc7..9018150 100644 --- a/vendor/rails/activesupport/lib/active_support/multibyte/chars.rb +++ b/vendor/rails/activesupport/lib/active_support/multibyte/chars.rb @@ -43,7 +43,7 @@ module ActiveSupport::Multibyte #:nodoc: # Create a new Chars instance. def initialize(str) - @string = (str.string rescue str) + @string = str.respond_to?(:string) ? str.string : str end # Returns -1, 0 or +1 depending on whether the Chars object is to be sorted before, equal or after the @@ -70,18 +70,18 @@ module ActiveSupport::Multibyte #:nodoc: def method_missing(m, *a, &b) begin # Simulate methods with a ! at the end because we can't touch the enclosed string from the handlers. - if m.to_s =~ /^(.*)\!$/ + if m.to_s =~ /^(.*)\!$/ && handler.respond_to?($1) result = handler.send($1, @string, *a, &b) if result == @string result = nil else @string.replace result end - else + elsif handler.respond_to?(m) result = handler.send(m, @string, *a, &b) + else + result = @string.send(m, *a, &b) end - rescue NoMethodError - result = @string.send(m, *a, &b) rescue Handlers::EncodingError @string.replace handler.tidy_bytes(@string) retry @@ -126,4 +126,4 @@ begin ActiveSupport::Multibyte::Chars.handler = ActiveSupport::Multibyte::Handlers::UTF8HandlerProc rescue LoadError ActiveSupport::Multibyte::Chars.handler = ActiveSupport::Multibyte::Handlers::UTF8Handler -end \ No newline at end of file +end diff --git a/vendor/rails/activesupport/lib/active_support/version.rb b/vendor/rails/activesupport/lib/active_support/version.rb index d254873..ff80ec6 100644 --- a/vendor/rails/activesupport/lib/active_support/version.rb +++ b/vendor/rails/activesupport/lib/active_support/version.rb @@ -2,7 +2,7 @@ module ActiveSupport module VERSION #:nodoc: MAJOR = 1 MINOR = 4 - TINY = 2 + TINY = 4 STRING = [MAJOR, MINOR, TINY].join('.') end diff --git a/vendor/rails/activesupport/test/core_ext/hash_ext_test.rb b/vendor/rails/activesupport/test/core_ext/hash_ext_test.rb index 3ede489..f4dbdf4 100644 --- a/vendor/rails/activesupport/test/core_ext/hash_ext_test.rb +++ b/vendor/rails/activesupport/test/core_ext/hash_ext_test.rb @@ -470,3 +470,40 @@ class HashToXmlTest < Test::Unit::TestCase end end end + +class QueryTest < Test::Unit::TestCase + def test_simple_conversion + assert_query_equal 'a=10', :a => 10 + end + + def test_cgi_escaping + assert_query_equal 'a%3Ab=c+d', 'a:b' => 'c d' + end + + def test_nil_parameter_value + empty = Object.new + def empty.to_param; nil end + assert_query_equal 'a=', 'a' => empty + end + + def test_nested_conversion + assert_query_equal 'person%5Bname%5D=Nicholas&person%5Blogin%5D=seckar', + :person => {:name => 'Nicholas', :login => 'seckar'} + end + + def test_multiple_nested + assert_query_equal 'account%5Bperson%5D%5Bid%5D=20&person%5Bid%5D=10', + :person => {:id => 10}, :account => {:person => {:id => 20}} + end + + def test_array_values + assert_query_equal 'person%5Bid%5D%5B%5D=10&person%5Bid%5D%5B%5D=20', + :person => {:id => [10, 20]} + end + + private + def assert_query_equal(expected, actual, message = nil) + assert_equal expected.split('&').sort, actual.to_query.split('&').sort + end +end + diff --git a/vendor/rails/activesupport/test/core_ext/module_test.rb b/vendor/rails/activesupport/test/core_ext/module_test.rb index bbf6dd1..884b440 100644 --- a/vendor/rails/activesupport/test/core_ext/module_test.rb +++ b/vendor/rails/activesupport/test/core_ext/module_test.rb @@ -1,10 +1,14 @@ require File.dirname(__FILE__) + '/../abstract_unit' module One + Constant1 = "Hello World" + Constant2 = "What's up?" end class Ab include One + Constant1 = "Hello World" # Will have different object id than One::Constant1 + Constant3 = "Goodbye World" end module Xy @@ -91,6 +95,10 @@ class ModuleTest < Test::Unit::TestCase assert_equal [Yz::Zy, Yz, Object], Yz::Zy::Cd.parents assert_equal [Yz, Object], Yz::Zy.parents end + + def test_local_constants + assert_equal %w(Constant1 Constant3), Ab.local_constants.sort + end def test_as_load_path assert_equal 'yz/zy', Yz::Zy.as_load_path diff --git a/vendor/rails/activesupport/test/dependencies_test.rb b/vendor/rails/activesupport/test/dependencies_test.rb index 755cff2..ad3472b 100644 --- a/vendor/rails/activesupport/test/dependencies_test.rb +++ b/vendor/rails/activesupport/test/dependencies_test.rb @@ -9,6 +9,10 @@ module ModuleWithMissing end end +module ModuleWithConstant + InheritedConstant = "Hello" +end + class DependenciesTest < Test::Unit::TestCase def teardown Dependencies.clear @@ -574,6 +578,13 @@ class DependenciesTest < Test::Unit::TestCase Object.send :remove_const, :M rescue nil end + def test_new_constants_in_with_inherited_constants + m = Dependencies.new_constants_in(:Object) do + Object.send :include, ModuleWithConstant + end + assert_equal [], m + end + def test_file_with_multiple_constants_and_require_dependency with_loading 'autoloading_fixtures' do assert ! defined?(MultipleConstantFile) diff --git a/vendor/rails/activesupport/test/json_test.rb b/vendor/rails/activesupport/test/json_test.rb new file mode 100644 index 0000000..8d9833e --- /dev/null +++ b/vendor/rails/activesupport/test/json_test.rb @@ -0,0 +1,97 @@ +require File.dirname(__FILE__) + '/abstract_unit' + +class JsonFoo + def initialize(a, b) + @a, @b = a, b + end +end + +class TestJSONEmitters < Test::Unit::TestCase + TrueTests = [[ true, %(true) ]] + FalseTests = [[ false, %(false) ]] + NilTests = [[ nil, %(null) ]] + NumericTests = [[ 1, %(1) ], + [ 2.5, %(2.5) ]] + + StringTests = [[ 'this is the string', %("this is the string") ], + [ 'a "string" with quotes