From 516d6dfac0c2207dab979eefbf9c2e3fae77d354 Mon Sep 17 00:00:00 2001 From: Jacques Distler Date: Mon, 2 Jun 2008 01:35:38 -0500 Subject: [PATCH] Rails 2.1 Update to Rails 2.1 final. --- vendor/rails/actionmailer/CHANGELOG | 2 +- vendor/rails/actionmailer/README | 24 +- vendor/rails/actionmailer/Rakefile | 2 +- .../actionmailer/lib/action_mailer/base.rb | 172 +++++------ .../actionmailer/lib/action_mailer/helpers.rb | 2 +- .../actionmailer/lib/action_mailer/part.rb | 4 +- .../actionmailer/lib/action_mailer/quoting.rb | 2 +- .../actionmailer/lib/action_mailer/vendor.rb | 4 +- .../{tmail-1.2.2 => tmail-1.2.3}/tmail.rb | 0 .../tmail/address.rb | 0 .../tmail/attachments.rb | 0 .../tmail/base64.rb | 0 .../tmail/compat.rb | 0 .../tmail/config.rb | 0 .../tmail/core_extensions.rb | 0 .../tmail/encode.rb | 32 ++- .../tmail/header.rb | 0 .../tmail/index.rb | 0 .../tmail/interface.rb | 7 +- .../tmail/loader.rb | 0 .../tmail/mail.rb | 4 +- .../tmail/mailbox.rb | 0 .../tmail/main.rb | 0 .../tmail/mbox.rb | 0 .../{tmail-1.2.2 => tmail-1.2.3}/tmail/net.rb | 0 .../tmail/obsolete.rb | 0 .../tmail/parser.rb | 0 .../tmail/port.rb | 0 .../tmail/quoting.rb | 0 .../tmail/require_arch.rb | 0 .../tmail/scanner.rb | 0 .../tmail/scanner_r.rb | 0 .../tmail/stringio.rb | 0 .../tmail/utils.rb | 2 +- .../tmail/version.rb | 2 +- .../actionmailer/lib/action_mailer/version.rb | 4 +- .../actionmailer/test/mail_service_test.rb | 34 +++ vendor/rails/actionpack/CHANGELOG | 5 +- vendor/rails/actionpack/Rakefile | 2 +- .../assertions/model_assertions.rb | 3 +- .../assertions/routing_assertions.rb | 6 +- .../assertions/selector_assertions.rb | 26 +- .../assertions/tag_assertions.rb | 6 +- .../actionpack/lib/action_controller/base.rb | 65 ++--- .../lib/action_controller/caching/actions.rb | 37 +-- .../action_controller/caching/fragments.rb | 13 +- .../lib/action_controller/caching/sweeping.rb | 6 +- .../lib/action_controller/cgi_ext/cookie.rb | 43 +-- .../lib/action_controller/cgi_ext/stdinput.rb | 1 + .../lib/action_controller/cgi_process.rb | 3 +- .../lib/action_controller/filters.rb | 40 +-- .../lib/action_controller/helpers.rb | 14 +- .../lib/action_controller/integration.rb | 22 +- .../lib/action_controller/mime_responds.rb | 2 +- .../lib/action_controller/mime_type.rb | 21 +- .../lib/action_controller/mime_types.rb | 2 +- .../action_controller/polymorphic_routes.rb | 13 +- .../lib/action_controller/request.rb | 28 +- .../request_forgery_protection.rb | 2 +- .../lib/action_controller/request_profiler.rb | 25 +- .../lib/action_controller/rescue.rb | 6 +- .../lib/action_controller/resources.rb | 6 +- .../lib/action_controller/routing/builder.rb | 6 +- .../lib/action_controller/routing/segments.rb | 2 +- .../action_controller/session/cookie_store.rb | 11 +- .../lib/action_controller/test_case.rb | 2 +- .../lib/action_controller/test_process.rb | 7 +- .../actionpack/lib/action_pack/version.rb | 4 +- .../rails/actionpack/lib/action_view/base.rb | 10 +- .../lib/action_view/compiled_templates.rb | 69 ----- .../action_view/helpers/asset_tag_helper.rb | 24 +- .../lib/action_view/helpers/date_helper.rb | 2 +- .../lib/action_view/helpers/form_helper.rb | 135 ++++++--- .../helpers/form_options_helper.rb | 48 ++-- .../action_view/helpers/form_tag_helper.rb | 8 +- .../action_view/helpers/prototype_helper.rb | 12 +- .../action_view/helpers/record_tag_helper.rb | 4 +- .../action_view/helpers/sanitize_helper.rb | 31 +- .../helpers/scriptaculous_helper.rb | 161 +++++------ .../lib/action_view/helpers/text_helper.rb | 131 ++++----- .../lib/action_view/helpers/url_helper.rb | 65 ++++- .../actionpack/lib/action_view/template.rb | 4 +- .../actionpack/lib/action_view/test_case.rb | 14 +- .../controller/action_pack_assertions_test.rb | 14 + .../test/controller/caching_test.rb | 96 +++++-- .../actionpack/test/controller/cookie_test.rb | 6 + .../test/controller/filter_params_test.rb | 20 +- .../actionpack/test/controller/helper_test.rb | 2 +- .../test/controller/mime_type_test.rb | 25 +- .../request_forgery_protection_test.rb | 71 ++++- .../test/controller/routing_test.rb | 7 + .../controller/session/cookie_store_test.rb | 16 +- .../actionpack/test/controller/test_test.rb | 20 +- .../test/template/compiled_templates_test.rb | 192 ------------- .../test/template/date_helper_test.rb | 6 + .../test/template/form_helper_test.rb | 11 + .../test/template/prototype_helper_test.rb | 11 +- .../test/template/text_helper_test.rb | 44 ++- vendor/rails/activemodel/CHANGES | 12 + vendor/rails/activemodel/README | 21 ++ vendor/rails/activemodel/Rakefile | 16 ++ vendor/rails/activemodel/lib/active_model.rb | 17 ++ .../activemodel/lib/active_model/base.rb | 4 + .../activemodel/lib/active_model/callbacks.rb | 5 + .../active_model/deprecated_error_methods.rb | 38 +++ .../activemodel/lib/active_model/errors.rb | 80 ++++++ .../activemodel/lib/active_model/observing.rb | 100 +++++++ .../lib/active_model/validations.rb | 124 ++++++++ .../active_model/validations/acceptance.rb | 45 +++ .../active_model/validations/associated.rb | 46 +++ .../active_model/validations/confirmation.rb | 44 +++ .../lib/active_model/validations/exclusion.rb | 37 +++ .../lib/active_model/validations/format.rb | 39 +++ .../lib/active_model/validations/inclusion.rb | 37 +++ .../lib/active_model/validations/length.rb | 95 ++++++ .../active_model/validations/numericality.rb | 80 ++++++ .../lib/active_model/validations/presence.rb | 42 +++ .../active_model/validations/uniqueness.rb | 104 +++++++ .../rails/activemodel/spec/observing_spec.rb | 120 ++++++++ vendor/rails/activemodel/spec/spec_helper.rb | 17 ++ vendor/rails/activerecord/CHANGELOG | 12 +- vendor/rails/activerecord/Rakefile | 2 +- .../lib/active_record/aggregations.rb | 18 +- .../lib/active_record/associations.rb | 173 +++++------ .../associations/association_collection.rb | 35 ++- .../associations/association_proxy.rb | 5 +- .../associations/belongs_to_association.rb | 5 +- .../belongs_to_polymorphic_association.rb | 11 +- .../associations/has_many_association.rb | 2 +- .../has_many_through_association.rb | 4 +- .../associations/has_one_association.rb | 5 +- .../lib/active_record/attribute_methods.rb | 46 +-- .../activerecord/lib/active_record/base.rb | 272 ++++++++++-------- .../lib/active_record/calculations.rb | 22 +- .../lib/active_record/callbacks.rb | 2 +- .../abstract/connection_specification.rb | 2 +- .../abstract/database_statements.rb | 13 +- .../abstract/schema_definitions.rb | 120 ++++---- .../abstract/schema_statements.rb | 24 +- .../connection_adapters/abstract_adapter.rb | 14 +- .../connection_adapters/postgresql_adapter.rb | 2 +- .../connection_adapters/sqlite_adapter.rb | 4 + .../activerecord/lib/active_record/dirty.rb | 50 ++-- .../lib/active_record/fixtures.rb | 63 ++-- .../lib/active_record/locking/optimistic.rb | 14 +- .../lib/active_record/migration.rb | 4 +- .../lib/active_record/named_scope.rb | 36 ++- .../lib/active_record/observer.rb | 4 +- .../activerecord/lib/active_record/schema.rb | 4 +- .../lib/active_record/schema_dumper.rb | 2 +- .../serializers/xml_serializer.rb | 6 +- .../lib/active_record/transactions.rb | 4 +- .../lib/active_record/validations.rb | 6 +- .../activerecord/lib/active_record/version.rb | 4 +- .../test/cases/active_schema_test_mysql.rb | 73 ++--- .../activerecord/test/cases/adapter_test.rb | 20 ++ .../belongs_to_associations_test.rb | 38 ++- ...s_and_belongs_to_many_associations_test.rb | 2 + .../has_many_associations_test.rb | 72 +++++ .../has_many_through_associations_test.rb | 1 + .../associations/has_one_associations_test.rb | 5 + .../cases/associations/join_model_test.rb | 2 + .../test/cases/associations_test.rb | 16 +- .../test/cases/datatype_test_postgresql.rb | 8 +- .../activerecord/test/cases/defaults_test.rb | 2 +- .../activerecord/test/cases/dirty_test.rb | 39 ++- .../activerecord/test/cases/finder_test.rb | 12 +- .../activerecord/test/cases/fixtures_test.rb | 20 +- .../test/cases/inheritance_test.rb | 44 +++ .../test/cases/method_scoping_test.rb | 16 ++ .../activerecord/test/cases/migration_test.rb | 4 +- .../test/cases/named_scope_test.rb | 40 ++- .../test/cases/reflection_test.rb | 5 +- .../test/cases/transactions_test.rb | 26 ++ .../test/cases/validations_test.rb | 6 + .../rails/activerecord/test/models/company.rb | 6 + .../rails/activerecord/test/models/pirate.rb | 2 + vendor/rails/activeresource/CHANGELOG | 2 +- vendor/rails/activeresource/Rakefile | 2 +- .../lib/active_resource/base.rb | 32 +-- .../lib/active_resource/custom_methods.rb | 14 +- .../lib/active_resource/formats/xml_format.rb | 2 +- .../lib/active_resource/http_mock.rb | 77 ++++- .../lib/active_resource/validations.rb | 4 +- .../lib/active_resource/version.rb | 4 +- vendor/rails/activesupport/CHANGELOG | 10 +- .../rails/activesupport/lib/active_support.rb | 1 + .../activesupport/lib/active_support/cache.rb | 8 +- .../lib/active_support/cache/file_store.rb | 7 +- .../active_support/cache/mem_cache_store.rb | 8 +- .../lib/active_support/cache/memory_store.rb | 7 +- .../core_ext/class/inheritable_attributes.rb | 2 +- .../core_ext/hash/conversions.rb | 4 +- .../core_ext/integer/even_odd.rb | 12 +- .../core_ext/module/attr_internal.rb | 6 +- .../active_support/core_ext/object/misc.rb | 2 +- .../core_ext/range/conversions.rb | 5 +- .../active_support/core_ext/string/unicode.rb | 10 +- .../core_ext/time/conversions.rb | 2 +- .../lib/active_support/core_ext/time/zones.rb | 37 ++- .../lib/active_support/dependencies.rb | 21 +- .../lib/active_support/deprecation.rb | 17 +- .../lib/active_support/inflector.rb | 125 ++++---- .../activesupport/lib/active_support/json.rb | 2 +- .../lib/active_support/json/decoding.rb | 2 +- .../lib/active_support/json/encoders/time.rb | 2 +- .../lib/active_support/multibyte/chars.rb | 14 +- .../multibyte/handlers/utf8_handler.rb | 18 +- .../lib/active_support/ordered_hash.rb | 43 +++ .../lib/active_support/ordered_options.rb | 44 --- .../testing/setup_and_teardown.rb | 12 +- .../lib/active_support/time_with_zone.rb | 71 +++-- .../lib/active_support/values/time_zone.rb | 34 ++- .../tzinfo-0.3.8/tzinfo/offset_rationals.rb | 114 ++++---- .../lib/active_support/version.rb | 4 +- .../test/core_ext/hash_ext_test.rb | 38 +++ .../test/core_ext/time_with_zone_test.rb | 9 +- .../activesupport/test/dependencies_test.rb | 26 +- .../activesupport/test/deprecation_test.rb | 10 - .../activesupport/test/json/encoding_test.rb | 16 ++ .../activesupport/test/ordered_hash_test.rb | 45 +++ .../test/ordered_options_test.rb | 44 --- .../activesupport/test/time_zone_test.rb | 2 +- vendor/rails/railties/CHANGELOG | 2 +- vendor/rails/railties/README | 16 +- vendor/rails/railties/Rakefile | 10 +- .../railties/configs/databases/frontbase.yml | 4 +- .../railties/configs/databases/mysql.yml | 4 +- .../railties/configs/databases/oracle.yml | 6 +- .../railties/configs/databases/postgresql.yml | 4 +- .../railties/configs/databases/sqlite2.yml | 4 +- .../railties/configs/databases/sqlite3.yml | 4 +- .../initializers/new_rails_defaults.rb | 14 +- .../railties/environments/environment.rb | 10 +- vendor/rails/railties/environments/test.rb | 2 +- vendor/rails/railties/lib/commands/console.rb | 4 +- .../rails/railties/lib/commands/dbconsole.rb | 17 +- vendor/rails/railties/lib/commands/plugin.rb | 2 +- .../railties/lib/commands/servers/lighttpd.rb | 2 +- .../railties/lib/commands/servers/mongrel.rb | 2 +- .../railties/lib/commands/servers/webrick.rb | 2 +- vendor/rails/railties/lib/initializer.rb | 91 +++--- .../railties/lib/rails/gem_dependency.rb | 15 +- .../lib/rails/mongrel_server/commands.rb | 2 +- vendor/rails/railties/lib/rails/plugin.rb | 17 +- .../railties/lib/rails/plugin/locator.rb | 5 +- vendor/rails/railties/lib/rails/version.rb | 4 +- .../railties/lib/rails_generator/base.rb | 2 +- .../railties/lib/rails_generator/commands.rb | 33 ++- .../generators/components/migration/USAGE | 8 +- .../components/scaffold/scaffold_generator.rb | 3 +- .../lib/source_annotation_extractor.rb | 40 +++ .../rails/railties/lib/tasks/databases.rake | 6 +- vendor/rails/railties/lib/tasks/gems.rake | 12 +- .../about_yml_plugins/bad_about_yml/about.yml | 2 +- .../test/generators/generator_test_helper.rb | 94 +++--- .../rails_controller_generator_test.rb | 20 ++ 257 files changed, 4058 insertions(+), 1933 deletions(-) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail.rb (100%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/address.rb (100%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/attachments.rb (100%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/base64.rb (100%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/compat.rb (100%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/config.rb (100%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/core_extensions.rb (100%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/encode.rb (94%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/header.rb (100%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/index.rb (100%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/interface.rb (99%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/loader.rb (100%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/mail.rb (99%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/mailbox.rb (100%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/main.rb (100%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/mbox.rb (100%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/net.rb (100%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/obsolete.rb (100%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/parser.rb (100%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/port.rb (100%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/quoting.rb (100%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/require_arch.rb (100%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/scanner.rb (100%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/scanner_r.rb (100%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/stringio.rb (100%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/utils.rb (99%) rename vendor/rails/actionmailer/lib/action_mailer/vendor/{tmail-1.2.2 => tmail-1.2.3}/tmail/version.rb (98%) delete mode 100644 vendor/rails/actionpack/lib/action_view/compiled_templates.rb delete mode 100644 vendor/rails/actionpack/test/template/compiled_templates_test.rb create mode 100644 vendor/rails/activemodel/CHANGES create mode 100644 vendor/rails/activemodel/README create mode 100644 vendor/rails/activemodel/Rakefile create mode 100644 vendor/rails/activemodel/lib/active_model.rb create mode 100644 vendor/rails/activemodel/lib/active_model/base.rb create mode 100644 vendor/rails/activemodel/lib/active_model/callbacks.rb create mode 100644 vendor/rails/activemodel/lib/active_model/deprecated_error_methods.rb create mode 100644 vendor/rails/activemodel/lib/active_model/errors.rb create mode 100644 vendor/rails/activemodel/lib/active_model/observing.rb create mode 100644 vendor/rails/activemodel/lib/active_model/validations.rb create mode 100644 vendor/rails/activemodel/lib/active_model/validations/acceptance.rb create mode 100644 vendor/rails/activemodel/lib/active_model/validations/associated.rb create mode 100644 vendor/rails/activemodel/lib/active_model/validations/confirmation.rb create mode 100644 vendor/rails/activemodel/lib/active_model/validations/exclusion.rb create mode 100644 vendor/rails/activemodel/lib/active_model/validations/format.rb create mode 100644 vendor/rails/activemodel/lib/active_model/validations/inclusion.rb create mode 100644 vendor/rails/activemodel/lib/active_model/validations/length.rb create mode 100644 vendor/rails/activemodel/lib/active_model/validations/numericality.rb create mode 100644 vendor/rails/activemodel/lib/active_model/validations/presence.rb create mode 100644 vendor/rails/activemodel/lib/active_model/validations/uniqueness.rb create mode 100644 vendor/rails/activemodel/spec/observing_spec.rb create mode 100644 vendor/rails/activemodel/spec/spec_helper.rb mode change 100644 => 100755 vendor/rails/activerecord/lib/active_record/associations.rb mode change 100644 => 100755 vendor/rails/activerecord/lib/active_record/associations/belongs_to_association.rb mode change 100644 => 100755 vendor/rails/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb mode change 100644 => 100755 vendor/rails/activerecord/lib/active_record/associations/has_one_association.rb mode change 100644 => 100755 vendor/rails/activerecord/test/cases/associations/belongs_to_associations_test.rb mode change 100644 => 100755 vendor/rails/activerecord/test/cases/associations/has_one_associations_test.rb create mode 100644 vendor/rails/activesupport/lib/active_support/ordered_hash.rb create mode 100644 vendor/rails/activesupport/test/ordered_hash_test.rb create mode 100644 vendor/rails/railties/test/generators/rails_controller_generator_test.rb diff --git a/vendor/rails/actionmailer/CHANGELOG b/vendor/rails/actionmailer/CHANGELOG index b2ce462f..bdae0d4d 100644 --- a/vendor/rails/actionmailer/CHANGELOG +++ b/vendor/rails/actionmailer/CHANGELOG @@ -1,4 +1,4 @@ -*2.1.0 RC1 (May 11th, 2008)* +*2.1.0 (May 31st, 2008)* * Fixed that a return-path header would be ignored #7572 [joost] diff --git a/vendor/rails/actionmailer/README b/vendor/rails/actionmailer/README index 67e8266e..0e16ea6e 100755 --- a/vendor/rails/actionmailer/README +++ b/vendor/rails/actionmailer/README @@ -19,8 +19,7 @@ are all set up this way. An example of such a method: recipients recipient subject "[Signed up] Welcome #{recipient}" from "system@loudthinking.com" - - body(:recipient => recipient) + body :recipient => recipient end The body of the email is created by using an Action View template (regular @@ -78,21 +77,26 @@ Example: end end -This Mailman can be the target for Postfix. In Rails, you would use the runner like this: +This Mailman can be the target for Postfix or other MTAs. In Rails, you would use the runner in the +trivial case like this: ./script/runner 'Mailman.receive(STDIN.read)' +However, invoking Rails in the runner for each mail to be received is very resource intensive. A single +instance of Rails should be run within a daemon if it is going to be utilized to process more than just +a limited number of email. + == Configuration The Base class has the full list of configuration options. Here's an example: -ActionMailer::Base.smtp_settings = { - :address=>'smtp.yourserver.com', # default: localhost - :port=>'25', # default: 25 - :user_name=>'user', - :password=>'pass', - :authentication=>:plain # :plain, :login or :cram_md5 -} + ActionMailer::Base.smtp_settings = { + :address => 'smtp.yourserver.com', # default: localhost + :port => '25', # default: 25 + :user_name => 'user', + :password => 'pass', + :authentication => :plain # :plain, :login or :cram_md5 + } == Dependencies diff --git a/vendor/rails/actionmailer/Rakefile b/vendor/rails/actionmailer/Rakefile index 22ed3964..c09526cb 100755 --- a/vendor/rails/actionmailer/Rakefile +++ b/vendor/rails/actionmailer/Rakefile @@ -55,7 +55,7 @@ spec = Gem::Specification.new do |s| s.rubyforge_project = "actionmailer" s.homepage = "http://www.rubyonrails.org" - s.add_dependency('actionpack', '= 2.0.991' + PKG_BUILD) + s.add_dependency('actionpack', '= 2.1.0' + PKG_BUILD) s.has_rdoc = true s.requirements << 'none' diff --git a/vendor/rails/actionmailer/lib/action_mailer/base.rb b/vendor/rails/actionmailer/lib/action_mailer/base.rb index a3762bf8..e0651321 100644 --- a/vendor/rails/actionmailer/lib/action_mailer/base.rb +++ b/vendor/rails/actionmailer/lib/action_mailer/base.rb @@ -5,17 +5,17 @@ require 'action_mailer/utils' require 'tmail/net' module ActionMailer #:nodoc: - # ActionMailer allows you to send email from your application using a mailer model and views. + # Action Mailer allows you to send email from your application using a mailer model and views. # # # = Mailer Models # - # To use ActionMailer, you need to create a mailer model. - # + # To use Action Mailer, you need to create a mailer model. + # # $ script/generate mailer Notifier # - # The generated model inherits from ActionMailer::Base. Emails are defined by creating methods within the model which are then - # used to set variables to be used in the mail template, to change options on the mail, or + # The generated model inherits from ActionMailer::Base. Emails are defined by creating methods within the model which are then + # used to set variables to be used in the mail template, to change options on the mail, or # to add attachments. # # Examples: @@ -35,7 +35,8 @@ module ActionMailer #:nodoc: # * subject - The subject of your email. Sets the Subject: header. # * from - Who the email you are sending is from. Sets the From: header. # * cc - Takes one or more email addresses. These addresses will receive a carbon copy of your email. Sets the Cc: header. - # * bcc - Takes one or more email address. These addresses will receive a blind carbon copy of your email. Sets the Bcc header. + # * bcc - Takes one or more email addresses. These addresses will receive a blind carbon copy of your email. Sets the Bcc: header. + # * reply_to - Takes one or more email addresses. These addresses will be listed as the default recipients when replying to your email. Sets the Reply-To: header. # * sent_on - The date on which the message was sent. If not set, the header wil be set by the delivery agent. # * content_type - Specify the content type of the message. Defaults to text/plain. # * headers - Specify additional headers to be set for the message, e.g. headers 'X-Mail-Count' => 107370. @@ -48,16 +49,16 @@ module ActionMailer #:nodoc: # named after each key in the hash containing the value that that key points to. # # So, for example, body :account => recipient would result - # in an instance variable @account with the value of recipient being accessible in the + # in an instance variable @account with the value of recipient being accessible in the # view. # # # = Mailer views # - # Like ActionController, each mailer class has a corresponding view directory + # Like Action Controller, each mailer class has a corresponding view directory # in which each method of the class looks for a template with its name. # To define a template to be used with a mailing, create an .erb file with the same name as the method - # in your mailer model. For example, in the mailer defined above, the template at + # in your mailer model. For example, in the mailer defined above, the template at # app/views/notifier/signup_notification.erb would be used to generate the email. # # Variables defined in the model are accessible as instance variables in the view. @@ -71,48 +72,48 @@ module ActionMailer #:nodoc: # # You got a new note! # <%= truncate(note.body, 25) %> - # + # # # = Generating URLs - # + # # URLs can be generated in mailer views using url_for or named routes. - # Unlike controllers from Action Pack, the mailer instance doesn't have any context about the incoming request, - # so you'll need to provide all of the details needed to generate a URL. + # Unlike controllers from Action Pack, the mailer instance doesn't have any context about the incoming request, + # so you'll need to provide all of the details needed to generate a URL. # # When using url_for you'll need to provide the :host, :controller, and :action: - # + # # <%= url_for(:host => "example.com", :controller => "welcome", :action => "greeting") %> # # When using named routes you only need to supply the :host: - # + # # <%= users_url(:host => "example.com") %> # # You will want to avoid using the name_of_route_path form of named routes because it doesn't make sense to # generate relative URLs in email messages. # - # It is also possible to set a default host that will be used in all mailers by setting the :host option in + # It is also possible to set a default host that will be used in all mailers by setting the :host option in # the ActionMailer::Base.default_url_options hash as follows: # # ActionMailer::Base.default_url_options[:host] = "example.com" - # + # # This can also be set as a configuration option in config/environment.rb: # # config.action_mailer.default_url_options = { :host => "example.com" } # # If you do decide to set a default :host for your mailers you will want to use the # :only_path => false option when using url_for. This will ensure that absolute URLs are generated because - # the url_for view helper will, by default, generate relative URLs when a :host option isn't + # the url_for view helper will, by default, generate relative URLs when a :host option isn't # explicitly provided. # # = Sending mail # - # Once a mailer action and template are defined, you can deliver your message or create it and save it + # Once a mailer action and template are defined, you can deliver your message or create it and save it # for delivery later: # # Notifier.deliver_signup_notification(david) # sends the email # mail = Notifier.create_signup_notification(david) # => a tmail object # Notifier.deliver(mail) - # + # # You never instantiate your mailer class. Rather, your delivery instance # methods are automatically wrapped in class methods that start with the word # deliver_ followed by the name of the mailer method that you would @@ -127,13 +128,13 @@ module ActionMailer #:nodoc: # # class MyMailer < ActionMailer::Base # def signup_notification(recipient) - # recipients recipient.email_address_with_name - # subject "New account information" - # body "account" => recipient - # from "system@example.com" - # content_type "text/html" # Here's where the magic happens + # recipients recipient.email_address_with_name + # subject "New account information" + # from "system@example.com" + # body :account => recipient + # content_type "text/html" # end - # end + # end # # # = Multipart email @@ -145,6 +146,7 @@ module ActionMailer #:nodoc: # recipients recipient.email_address_with_name # subject "New account information" # from "system@example.com" + # content_type "multipart/alternative" # # part :content_type => "text/html", # :body => render_message("signup-as-html", :account => recipient) @@ -155,21 +157,26 @@ module ActionMailer #:nodoc: # end # end # end - # - # Multipart messages can also be used implicitly because ActionMailer will automatically + # + # Multipart messages can also be used implicitly because Action Mailer will automatically # detect and use multipart templates, where each template is named after the name of the action, followed # by the content type. Each such detected template will be added as separate part to the message. - # + # # For example, if the following templates existed: # * signup_notification.text.plain.erb # * signup_notification.text.html.erb # * signup_notification.text.xml.builder # * signup_notification.text.x-yaml.erb - # - # Each would be rendered and added as a separate part to the message, - # with the corresponding content type. The same body hash is passed to - # each template. # + # Each would be rendered and added as a separate part to the message, + # with the corresponding content type. The content type for the entire + # message is automatically set to multipart/alternative, which indicates + # that the email contains multiple different representations of the same email + # body. The same body hash is passed to each template. + # + # Implicit template rendering is not performed if any attachments or parts have been added to the email. + # This means that you'll have to manually add each part to the email and set the content type of the email + # to multipart/alternative. # # = Attachments # @@ -191,7 +198,7 @@ module ActionMailer #:nodoc: # a.body = generate_your_pdf_here() # end # end - # end + # end # # # = Configuration options @@ -210,11 +217,11 @@ module ActionMailer #:nodoc: # * :user_name - If your mail server requires authentication, set the username in this setting. # * :password - If your mail server requires authentication, set the password in this setting. # * :authentication - If your mail server requires authentication, you need to specify the authentication type here. - # This is a symbol and one of :plain, :login, :cram_md5 + # This is a symbol and one of :plain, :login, :cram_md5. # - # * sendmail_settings - Allows you to override options for the :sendmail delivery method - # * :location - The location of the sendmail executable, defaults to "/usr/sbin/sendmail" - # * :arguments - The command line arguments + # * sendmail_settings - Allows you to override options for the :sendmail delivery method. + # * :location - The location of the sendmail executable. Defaults to /usr/sbin/sendmail. + # * :arguments - The command line arguments. Defaults to -i -t. # # * raise_delivery_errors - Whether or not errors should be raised if the email fails to be delivered. # @@ -227,16 +234,16 @@ module ActionMailer #:nodoc: # for unit and functional testing. # # * default_charset - The default charset used for the body and to encode the subject. Defaults to UTF-8. You can also - # pick a different charset from inside a method with @charset. + # pick a different charset from inside a method with +charset+. # * default_content_type - The default content type used for the main part of the message. Defaults to "text/plain". You - # can also pick a different content type from inside a method with @content_type. - # * default_mime_version - The default mime version used for the message. Defaults to "1.0". You - # can also pick a different value from inside a method with @mime_version. + # can also pick a different content type from inside a method with +content_type+. + # * default_mime_version - The default mime version used for the message. Defaults to 1.0. You + # can also pick a different value from inside a method with +mime_version+. # * default_implicit_parts_order - When a message is built implicitly (i.e. multiple parts are assembled from templates # which specify the content type in their filenames) this variable controls how the parts are ordered. Defaults to - # ["text/html", "text/enriched", "text/plain"]. Items that appear first in the array have higher priority in the mail client + # ["text/html", "text/enriched", "text/plain"]. Items that appear first in the array have higher priority in the mail client # and appear last in the mime encoded message. You can also pick a different order from inside a method with - # @implicit_parts_order. + # +implicit_parts_order+. class Base include AdvAttrAccessor, PartContainer include ActionController::UrlWriter if Object.const_defined?(:ActionController) @@ -249,16 +256,16 @@ module ActionMailer #:nodoc: cattr_accessor :template_extensions @@template_extensions = ['erb', 'builder', 'rhtml', 'rxml'] - @@smtp_settings = { - :address => "localhost", - :port => 25, - :domain => 'localhost.localdomain', - :user_name => nil, - :password => nil, + @@smtp_settings = { + :address => "localhost", + :port => 25, + :domain => 'localhost.localdomain', + :user_name => nil, + :password => nil, :authentication => nil } cattr_accessor :smtp_settings - + @@sendmail_settings = { :location => '/usr/sbin/sendmail', :arguments => '-i -t' @@ -270,10 +277,10 @@ module ActionMailer #:nodoc: superclass_delegating_accessor :delivery_method self.delivery_method = :smtp - + @@perform_deliveries = true cattr_accessor :perform_deliveries - + @@deliveries = [] cattr_accessor :deliveries @@ -282,7 +289,7 @@ module ActionMailer #:nodoc: @@default_content_type = "text/plain" cattr_accessor :default_content_type - + @@default_mime_version = "1.0" cattr_accessor :default_mime_version @@ -291,47 +298,51 @@ module ActionMailer #:nodoc: # Specify the BCC addresses for the message adv_attr_accessor :bcc - + # Define the body of the message. This is either a Hash (in which case it # specifies the variables to pass to the template when it is rendered), # or a string, in which case it specifies the actual text of the message. adv_attr_accessor :body - + # Specify the CC addresses for the message. adv_attr_accessor :cc - + # Specify the charset to use for the message. This defaults to the # +default_charset+ specified for ActionMailer::Base. adv_attr_accessor :charset - + # Specify the content type for the message. This defaults to text/plain # in most cases, but can be automatically set in some situations. adv_attr_accessor :content_type - + # Specify the from address for the message. adv_attr_accessor :from - + + # Specify the address (if different than the "from" address) to direct + # replies to this message. + adv_attr_accessor :reply_to + # Specify additional headers to be added to the message. adv_attr_accessor :headers - + # Specify the order in which parts should be sorted, based on content-type. # This defaults to the value for the +default_implicit_parts_order+. adv_attr_accessor :implicit_parts_order - + # Defaults to "1.0", but may be explicitly given if needed. adv_attr_accessor :mime_version - + # The recipient addresses for the message, either as a string (for a single # address) or an array (for multiple addresses). adv_attr_accessor :recipients - + # The date on which the message was sent. If not set (the default), the # header will be set by the delivery agent. adv_attr_accessor :sent_on - + # Specify the subject of the message. adv_attr_accessor :subject - + # Specify the template name to use for current message. This is the "base" # template name, without the extension or directory, and may be used to # have multiple mailer methods share the same template. @@ -347,7 +358,7 @@ module ActionMailer #:nodoc: self.class.mailer_name end end - + def mailer_name=(value) self.class.mailer_name = value end @@ -377,8 +388,8 @@ module ActionMailer #:nodoc: # Receives a raw email, parses it into an email object, decodes it, # instantiates a new mailer, and passes the email object to the mailer - # object's #receive method. If you want your mailer to be able to - # process incoming messages, you'll need to implement a #receive + # object's +receive+ method. If you want your mailer to be able to + # process incoming messages, you'll need to implement a +receive+ # method that accepts the email object as a parameter: # # class MyMailer < ActionMailer::Base @@ -425,7 +436,7 @@ module ActionMailer #:nodoc: # remain uninitialized (useful when you only need to invoke the "receive" # method, for instance). def initialize(method_name=nil, *parameters) #:nodoc: - create!(method_name, *parameters) if method_name + create!(method_name, *parameters) if method_name end # Initialize the mailer via the given +method_name+. The body will be @@ -484,7 +495,7 @@ module ActionMailer #:nodoc: end # Delivers a TMail::Mail object. By default, it delivers the cached mail - # object (from the #create! method). If no cached mail object exists, and + # object (from the create! method). If no cached mail object exists, and # no alternate has been given as the parameter, this will fail. def deliver!(mail = @mail) raise "no mail object available for delivery!" unless mail @@ -511,7 +522,7 @@ module ActionMailer #:nodoc: @content_type ||= @@default_content_type.dup @implicit_parts_order ||= @@default_implicit_parts_order.dup @template ||= method_name - @mailer_name ||= Inflector.underscore(self.class.name) + @mailer_name ||= self.class.name.underscore @parts ||= [] @headers ||= {} @body ||= {} @@ -570,13 +581,14 @@ module ActionMailer #:nodoc: def create_mail m = TMail::Mail.new - m.subject, = quote_any_if_necessary(charset, subject) - m.to, m.from = quote_any_address_if_necessary(charset, recipients, from) - m.bcc = quote_address_if_necessary(bcc, charset) unless bcc.nil? - m.cc = quote_address_if_necessary(cc, charset) unless cc.nil? - + m.subject, = quote_any_if_necessary(charset, subject) + m.to, m.from = quote_any_address_if_necessary(charset, recipients, from) + m.bcc = quote_address_if_necessary(bcc, charset) unless bcc.nil? + m.cc = quote_address_if_necessary(cc, charset) unless cc.nil? + m.reply_to = quote_address_if_necessary(reply_to, charset) unless reply_to.nil? m.mime_version = mime_version unless mime_version.nil? - m.date = sent_on.to_time rescue sent_on if sent_on + m.date = sent_on.to_time rescue sent_on if sent_on + headers.each { |k, v| m[k] = v } real_content_type, ctype_attrs = parse_content_type @@ -597,7 +609,7 @@ module ActionMailer #:nodoc: part = (TMail::Mail === p ? p : p.to_mail(self)) m.parts << part end - + if real_content_type =~ /multipart/ ctype_attrs.delete "charset" m.set_content_type(real_content_type, nil, ctype_attrs) @@ -612,7 +624,7 @@ module ActionMailer #:nodoc: mail.ready_to_send sender = mail['return-path'] || mail.from - Net::SMTP.start(smtp_settings[:address], smtp_settings[:port], smtp_settings[:domain], + Net::SMTP.start(smtp_settings[:address], smtp_settings[:port], smtp_settings[:domain], smtp_settings[:user_name], smtp_settings[:password], smtp_settings[:authentication]) do |smtp| smtp.sendmail(mail.encoded, sender, destinations) end diff --git a/vendor/rails/actionmailer/lib/action_mailer/helpers.rb b/vendor/rails/actionmailer/lib/action_mailer/helpers.rb index 3e5ed9e9..9c5fcc6a 100644 --- a/vendor/rails/actionmailer/lib/action_mailer/helpers.rb +++ b/vendor/rails/actionmailer/lib/action_mailer/helpers.rb @@ -34,7 +34,7 @@ module ActionMailer # helper FooHelper # includes FooHelper in the template class. # helper { def foo() "#{bar} is the very best" end } - # evaluates the block in the template class, adding method #foo. + # evaluates the block in the template class, adding method +foo+. # helper(:three, BlindHelper) { def mice() 'mice' end } # does all three. def helper(*args, &block) diff --git a/vendor/rails/actionmailer/lib/action_mailer/part.rb b/vendor/rails/actionmailer/lib/action_mailer/part.rb index de1b1689..2dabf15f 100644 --- a/vendor/rails/actionmailer/lib/action_mailer/part.rb +++ b/vendor/rails/actionmailer/lib/action_mailer/part.rb @@ -5,7 +5,7 @@ require 'action_mailer/utils' module ActionMailer # Represents a subpart of an email message. It shares many similar # attributes of ActionMailer::Base. Although you can create parts manually - # and add them to the #parts list of the mailer, it is easier + # and add them to the +parts+ list of the mailer, it is easier # to use the helper methods in ActionMailer::PartContainer. class Part include ActionMailer::AdvAttrAccessor @@ -13,7 +13,7 @@ module ActionMailer # Represents the body of the part, as a string. This should not be a # Hash (like ActionMailer::Base), but if you want a template to be rendered - # into the body of a subpart you can do it with the mailer's #render method + # into the body of a subpart you can do it with the mailer's +render+ method # and assign the result here. adv_attr_accessor :body diff --git a/vendor/rails/actionmailer/lib/action_mailer/quoting.rb b/vendor/rails/actionmailer/lib/action_mailer/quoting.rb index b2224327..a2f2c707 100644 --- a/vendor/rails/actionmailer/lib/action_mailer/quoting.rb +++ b/vendor/rails/actionmailer/lib/action_mailer/quoting.rb @@ -40,7 +40,7 @@ module ActionMailer # regular email address, or it can be a phrase followed by an address in # brackets. The phrase is the only part that will be quoted, and only if # it needs to be. This allows extended characters to be used in the - # "to", "from", "cc", and "bcc" headers. + # "to", "from", "cc", "bcc" and "reply-to" headers. def quote_address_if_necessary(address, charset) if Array === address address.map { |a| quote_address_if_necessary(a, charset) } diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor.rb index 56a2858b..7a20e9bd 100644 --- a/vendor/rails/actionmailer/lib/action_mailer/vendor.rb +++ b/vendor/rails/actionmailer/lib/action_mailer/vendor.rb @@ -2,9 +2,9 @@ require 'rubygems' begin - gem 'tmail', '~> 1.2.2' + gem 'tmail', '~> 1.2.3' rescue Gem::LoadError - $:.unshift "#{File.dirname(__FILE__)}/vendor/tmail-1.2.2" + $:.unshift "#{File.dirname(__FILE__)}/vendor/tmail-1.2.3" end begin diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail.rb similarity index 100% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail.rb diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/address.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/address.rb similarity index 100% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/address.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/address.rb diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/attachments.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/attachments.rb similarity index 100% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/attachments.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/attachments.rb diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/base64.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/base64.rb similarity index 100% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/base64.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/base64.rb diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/compat.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/compat.rb similarity index 100% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/compat.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/compat.rb diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/config.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/config.rb similarity index 100% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/config.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/config.rb diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/core_extensions.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/core_extensions.rb similarity index 100% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/core_extensions.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/core_extensions.rb diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/encode.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/encode.rb similarity index 94% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/encode.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/encode.rb index 63bccce4..458dbbfe 100644 --- a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/encode.rb +++ b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/encode.rb @@ -339,22 +339,36 @@ module TMail def scanadd( str, force = false ) types = '' strs = [] - + if str.respond_to?(:encoding) + enc = str.encoding + str.force_encoding(Encoding::ASCII_8BIT) + end until str.empty? if m = /\A[^\e\t\r\n ]+/.match(str) types << (force ? 'j' : 'a') - strs.push m[0] - + if str.respond_to?(:encoding) + strs.push m[0].force_encoding(enc) + else + strs.push m[0] + end elsif m = /\A[\t\r\n ]+/.match(str) types << 's' - strs.push m[0] + if str.respond_to?(:encoding) + strs.push m[0].force_encoding(enc) + else + strs.push m[0] + end elsif m = /\A\e../.match(str) esc = m[0] str = m.post_match if esc != "\e(B" and m = /\A[^\e]+/.match(str) types << 'j' - strs.push m[0] + if str.respond_to?(:encoding) + strs.push m[0].force_encoding(enc) + else + strs.push m[0] + end end else @@ -453,7 +467,13 @@ module TMail size = max_bytes(chunksize, str.size) - 6 size = (size % 2 == 0) ? (size) : (size - 1) return nil if size <= 0 - "\e$B#{str.slice!(0, size)}\e(B" + if str.respond_to?(:encoding) + enc = str.encoding + str.force_encoding(Encoding::ASCII_8BIT) + "\e$B#{str.slice!(0, size)}\e(B".force_encoding(enc) + else + "\e$B#{str.slice!(0, size)}\e(B" + end end def extract_A( chunksize, str ) diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/header.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/header.rb similarity index 100% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/header.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/header.rb diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/index.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/index.rb similarity index 100% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/index.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/index.rb diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/interface.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/interface.rb similarity index 99% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/interface.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/interface.rb index 206653bd..a6d428d7 100644 --- a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/interface.rb +++ b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/interface.rb @@ -591,12 +591,17 @@ module TMail end # Destructively sets the message ID of the mail object instance to the passed in string + # + # Invalid message IDs are ignored (silently, unless configured otherwise) and result in + # a nil message ID. Left and right angle brackets are required. # # Example: # # mail = TMail::Mail.new + # mail.message_id = "<348F04F142D69C21-291E56D292BC@xxxx.net>" + # mail.message_id #=> "<348F04F142D69C21-291E56D292BC@xxxx.net>" # mail.message_id = "this_is_my_badly_formatted_message_id" - # mail.message_id #=> "this_is_my_badly_formatted_message_id" + # mail.message_id #=> nil def message_id=( str ) set_string_attr 'Message-Id', str end diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/loader.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/loader.rb similarity index 100% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/loader.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/loader.rb diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/mail.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/mail.rb similarity index 99% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/mail.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/mail.rb index fef6b01c..5a319907 100644 --- a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/mail.rb +++ b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/mail.rb @@ -408,8 +408,8 @@ module TMail when /\AFrom (\S+)/ unixfrom = $1 - when /^charset=.*/ - + when /^charset=.*/ + else raise SyntaxError, "wrong mail header: '#{line.inspect}'" end diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/mailbox.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/mailbox.rb similarity index 100% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/mailbox.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/mailbox.rb diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/main.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/main.rb similarity index 100% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/main.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/main.rb diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/mbox.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/mbox.rb similarity index 100% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/mbox.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/mbox.rb diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/net.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/net.rb similarity index 100% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/net.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/net.rb diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/obsolete.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/obsolete.rb similarity index 100% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/obsolete.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/obsolete.rb diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/parser.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/parser.rb similarity index 100% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/parser.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/parser.rb diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/port.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/port.rb similarity index 100% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/port.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/port.rb diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/quoting.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/quoting.rb similarity index 100% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/quoting.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/quoting.rb diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/require_arch.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/require_arch.rb similarity index 100% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/require_arch.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/require_arch.rb diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/scanner.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/scanner.rb similarity index 100% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/scanner.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/scanner.rb diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/scanner_r.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/scanner_r.rb similarity index 100% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/scanner_r.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/scanner_r.rb diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/stringio.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/stringio.rb similarity index 100% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/stringio.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/stringio.rb diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/utils.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/utils.rb similarity index 99% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/utils.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/utils.rb index 9a3afe89..dc594a42 100644 --- a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/utils.rb +++ b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/utils.rb @@ -118,7 +118,7 @@ module TMail ATOM_UNSAFE = /[#{Regexp.quote aspecial}#{control}#{lwsp}]/n PHRASE_UNSAFE = /[#{Regexp.quote aspecial}#{control}]/n TOKEN_UNSAFE = /[#{Regexp.quote tspecial}#{control}#{lwsp}]/n - + # Returns true if the string supplied is free from characters not allowed as an ATOM def atom_safe?( str ) not ATOM_UNSAFE === str diff --git a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/version.rb b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/version.rb similarity index 98% rename from vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/version.rb rename to vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/version.rb index 6bf8cc80..95228497 100644 --- a/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.2/tmail/version.rb +++ b/vendor/rails/actionmailer/lib/action_mailer/vendor/tmail-1.2.3/tmail/version.rb @@ -32,7 +32,7 @@ module TMail module VERSION MAJOR = 1 MINOR = 2 - TINY = 2 + TINY = 3 STRING = [MAJOR, MINOR, TINY].join('.') end diff --git a/vendor/rails/actionmailer/lib/action_mailer/version.rb b/vendor/rails/actionmailer/lib/action_mailer/version.rb index 88b9a3c2..c35b648b 100644 --- a/vendor/rails/actionmailer/lib/action_mailer/version.rb +++ b/vendor/rails/actionmailer/lib/action_mailer/version.rb @@ -1,8 +1,8 @@ module ActionMailer module VERSION #:nodoc: MAJOR = 2 - MINOR = 0 - TINY = 991 + MINOR = 1 + TINY = 0 STRING = [MAJOR, MINOR, TINY].join('.') end diff --git a/vendor/rails/actionmailer/test/mail_service_test.rb b/vendor/rails/actionmailer/test/mail_service_test.rb index 57a651cc..e5ecb0e2 100755 --- a/vendor/rails/actionmailer/test/mail_service_test.rb +++ b/vendor/rails/actionmailer/test/mail_service_test.rb @@ -40,6 +40,15 @@ class TestMailer < ActionMailer::Base body "Nothing to see here." end + def different_reply_to(recipient) + recipients recipient + subject "testing reply_to" + from "system@loudthinking.com" + sent_on Time.local(2008, 5, 23) + reply_to "atraver@gmail.com" + body "Nothing to see here." + end + def iso_charset(recipient) @recipients = recipient @subject = "testing isø charsets" @@ -445,6 +454,31 @@ class ActionMailerTest < Test::Unit::TestCase assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded end + def test_reply_to + expected = new_mail + + expected.to = @recipient + expected.subject = "testing reply_to" + expected.body = "Nothing to see here." + expected.from = "system@loudthinking.com" + expected.reply_to = "atraver@gmail.com" + expected.date = Time.local 2008, 5, 23 + + created = nil + assert_nothing_raised do + created = TestMailer.create_different_reply_to @recipient + end + assert_not_nil created + assert_equal expected.encoded, created.encoded + + assert_nothing_raised do + TestMailer.deliver_different_reply_to @recipient + end + + assert_not_nil ActionMailer::Base.deliveries.first + assert_equal expected.encoded, ActionMailer::Base.deliveries.first.encoded + end + def test_iso_charset expected = new_mail( "iso-8859-1" ) expected.to = @recipient diff --git a/vendor/rails/actionpack/CHANGELOG b/vendor/rails/actionpack/CHANGELOG index e8676666..cb684a92 100644 --- a/vendor/rails/actionpack/CHANGELOG +++ b/vendor/rails/actionpack/CHANGELOG @@ -1,9 +1,12 @@ -*2.1.0 RC1 (May 11th, 2008)* +*2.1.0 (May 31st, 2008)* + +* InstanceTag#default_time_from_options overflows to DateTime [Geoff Buesing] * Fixed that forgery protection can be used without session tracking (Peter Jones) [#139] * Added session(:on) to turn session management back on in a controller subclass if the superclass turned it off (Peter Jones) [#136] +* Change the request forgery protection to go by Content-Type instead of request.format so that you can't bypass it by POSTing to "#{request.uri}.xml" [rick] * InstanceTag#default_time_from_options with hash args uses Time.current as default; respects hash settings when time falls in system local spring DST gap [Geoff Buesing] * select_date defaults to Time.zone.today when config.time_zone is set [Geoff Buesing] diff --git a/vendor/rails/actionpack/Rakefile b/vendor/rails/actionpack/Rakefile index 0147a5c1..b37f756c 100644 --- a/vendor/rails/actionpack/Rakefile +++ b/vendor/rails/actionpack/Rakefile @@ -76,7 +76,7 @@ spec = Gem::Specification.new do |s| s.has_rdoc = true s.requirements << 'none' - s.add_dependency('activesupport', '= 2.0.991' + PKG_BUILD) + s.add_dependency('activesupport', '= 2.1.0' + PKG_BUILD) s.require_path = 'lib' s.autorequire = 'action_controller' 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 0b431305..d25214bb 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,8 @@ module ActionController module Assertions module ModelAssertions - # Ensures that the passed record is valid by ActiveRecord standards and returns any error messages if it is not. + # Ensures that the passed record is valid by Active Record standards and + # returns any error messages if it is not. # # ==== Examples # 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 2acd0032..491b72d5 100644 --- a/vendor/rails/actionpack/lib/action_controller/assertions/routing_assertions.rb +++ b/vendor/rails/actionpack/lib/action_controller/assertions/routing_assertions.rb @@ -59,7 +59,7 @@ module ActionController end end - # Asserts that the provided options can be used to generate the provided path. This is the inverse of #assert_recognizes. + # Asserts that the provided options can be used to generate the provided path. This is the inverse of +assert_recognizes+. # The +extras+ parameter is used to tell the request the names and values of additional request parameters that would be in # a query string. The +message+ parameter allows you to specify a custom error message for assertion failures. # @@ -96,8 +96,8 @@ module ActionController end # Asserts that path and options match both ways; in other words, it verifies that path generates - # options and then that options generates path. This essentially combines #assert_recognizes - # and #assert_generates into one step. + # options and then that options generates path. This essentially combines +assert_recognizes+ + # and +assert_generates+ into one step. # # The +extras+ hash allows you to specify options that would normally be provided as a query string to the action. The # +message+ parameter allows you to specify a custom error message to display upon failure. 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 9ef093ac..d3594e71 100644 --- a/vendor/rails/actionpack/lib/action_controller/assertions/selector_assertions.rb +++ b/vendor/rails/actionpack/lib/action_controller/assertions/selector_assertions.rb @@ -12,12 +12,12 @@ module ActionController NO_STRIP = %w{pre script style textarea} end - # Adds the #assert_select method for use in Rails functional + # Adds the +assert_select+ method for use in Rails functional # test cases, which can be used to make assertions on the response HTML of a controller - # action. You can also call #assert_select within another #assert_select to + # action. You can also call +assert_select+ within another +assert_select+ to # make assertions on elements selected by the enclosing assertion. # - # Use #css_select to select elements without making an assertions, either + # Use +css_select+ to select elements without making an assertions, either # from the response HTML or elements selected by the enclosing assertion. # # In addition to HTML responses, you can make the following assertions: @@ -44,8 +44,8 @@ module ActionController # base element and any of its children. Returns an empty array if no # match is found. # - # The selector may be a CSS selector expression (+String+), an expression - # with substitution values (+Array+) or an HTML::Selector object. + # The selector may be a CSS selector expression (String), an expression + # with substitution values (Array) or an HTML::Selector object. # # ==== Examples # # Selects all div tags @@ -114,8 +114,8 @@ module ActionController # starting from (and including) that element and all its children in # depth-first order. # - # If no element if specified, calling #assert_select will select from the - # response HTML. Calling #assert_select inside an #assert_select block will + # If no element if specified, calling +assert_select+ will select from the + # response HTML. Calling #assert_select inside an +assert_select+ block will # run the assertion for each element selected by the enclosing assertion. # # ==== Example @@ -130,7 +130,7 @@ module ActionController # assert_select "li" # end # - # The selector may be a CSS selector expression (+String+), an expression + # The selector may be a CSS selector expression (String), an expression # with substitution values, or an HTML::Selector object. # # === Equality Tests @@ -356,16 +356,16 @@ module ActionController # # === Using blocks # - # Without a block, #assert_select_rjs merely asserts that the response + # Without a block, +assert_select_rjs+ merely asserts that the response # contains one or more RJS statements that replace or update content. # - # With a block, #assert_select_rjs also selects all elements used in + # With a block, +assert_select_rjs+ also selects all elements used in # these statements and passes them to the block. Nested assertions are # supported. # - # Calling #assert_select_rjs with no arguments and using nested asserts + # Calling +assert_select_rjs+ with no arguments and using nested asserts # asserts that the HTML content is returned by one or more RJS statements. - # Using #assert_select directly makes the same assertion on the content, + # Using +assert_select+ directly makes the same assertion on the content, # but without distinguishing whether the content is returned in an HTML # or JavaScript. # @@ -601,7 +601,7 @@ module ActionController RJS_PATTERN_UNICODE_ESCAPED_CHAR = /\\u([0-9a-zA-Z]{4})/ end - # #assert_select and #css_select call this to obtain the content in the HTML + # +assert_select+ and +css_select+ call this to obtain the content in the HTML # page, or from all the RJS statements, depending on the type of response. def response_from_page_or_rjs() content_type = @response.content_type diff --git a/vendor/rails/actionpack/lib/action_controller/assertions/tag_assertions.rb b/vendor/rails/actionpack/lib/action_controller/assertions/tag_assertions.rb index 4ac48952..90ba3668 100644 --- a/vendor/rails/actionpack/lib/action_controller/assertions/tag_assertions.rb +++ b/vendor/rails/actionpack/lib/action_controller/assertions/tag_assertions.rb @@ -91,7 +91,7 @@ module ActionController # :descendant => { :tag => "span", # :child => /hello world/ } # - # Please note: #assert_tag and #assert_no_tag only work + # Please note: +assert_tag+ and +assert_no_tag+ only work # with well-formed XHTML. They recognize a few tags as implicitly self-closing # (like br and hr and such) but will not work correctly with tags # that allow optional closing tags (p, li, td). You must explicitly @@ -104,8 +104,8 @@ module ActionController end end - # Identical to #assert_tag, but asserts that a matching tag does _not_ - # exist. (See #assert_tag for a full discussion of the syntax.) + # Identical to +assert_tag+, but asserts that a matching tag does _not_ + # exist. (See +assert_tag+ for a full discussion of the syntax.) # # === Examples # # Assert that there is not a "div" containing a "p" diff --git a/vendor/rails/actionpack/lib/action_controller/base.rb b/vendor/rails/actionpack/lib/action_controller/base.rb index e1bf005f..a036600c 100755 --- a/vendor/rails/actionpack/lib/action_controller/base.rb +++ b/vendor/rails/actionpack/lib/action_controller/base.rb @@ -104,7 +104,7 @@ module ActionController #:nodoc: # end # # Actions, by default, render a template in the app/views directory corresponding to the name of the controller and action - # after executing code in the action. For example, the +index+ action of the +GuestBookController+ would render the + # after executing code in the action. For example, the +index+ action of the GuestBookController would render the # template app/views/guestbook/index.erb by default after populating the @entries instance variable. # # Unlike index, the sign action will not render a template. After performing its main purpose (creating a @@ -118,10 +118,10 @@ module ActionController #:nodoc: # # Requests are processed by the Action Controller framework by extracting the value of the "action" key in the request parameters. # This value should hold the name of the action to be performed. Once the action has been identified, the remaining - # request parameters, the session (if one is available), and the full request with all the http headers are made available to + # request parameters, the session (if one is available), and the full request with all the HTTP headers are made available to # the action through instance variables. Then the action is performed. # - # The full request object is available with the request accessor and is primarily used to query for http headers. These queries + # The full request object is available with the request accessor and is primarily used to query for HTTP headers. These queries # are made by accessing the environment hash, like this: # # def server_ip @@ -259,12 +259,12 @@ module ActionController #:nodoc: DEFAULT_RENDER_STATUS_CODE = "200 OK" include StatusCodes - + # Controller specific instance variables which will not be accessible inside views. @@protected_view_variables = %w(@assigns @performed_redirect @performed_render @variables_added @request_origin @url @parent_controller @action_name @before_filter_chain_aborted @action_cache_path @_session @_cookies @_headers @_params @_flash @_response) - + # Prepends all the URL-generating helpers from AssetHelper. This makes it possible to easily move javascripts, stylesheets, # and images to a dedicated asset server away from the main web server. Example: # ActionController::Base.asset_host = "http://assets.example.com" @@ -291,10 +291,10 @@ module ActionController #:nodoc: cattr_accessor :allow_concurrency # Modern REST web services often need to submit complex data to the web application. - # The param_parsers hash lets you register handlers which will process the http body and add parameters to the - # params hash. These handlers are invoked for post and put requests. + # The @@param_parsers hash lets you register handlers which will process the HTTP body and add parameters to the + # params hash. These handlers are invoked for POST and PUT requests. # - # By default application/xml is enabled. A XmlSimple class with the same param name as the root will be instantiated + # By default application/xml is enabled. A XmlSimple class with the same param name as the root will be instantiated # in the params. This allows XML requests to mask themselves as regular form submissions, so you can have one # action serve both regular forms and web service requests. # @@ -307,7 +307,7 @@ module ActionController #:nodoc: # # Note: Up until release 1.1 of Rails, Action Controller would default to using XmlSimple configured to discard the # root node for such requests. The new default is to keep the root, such that "David" results - # in params[:r][:name] for "David" instead of params[:name]. To get the old behavior, you can + # in params[:r][:name] for "David" instead of params[:name]. To get the old behavior, you can # re-register XmlSimple as application/xml handler ike this: # # ActionController::Base.param_parsers[Mime::XML] = @@ -325,7 +325,7 @@ module ActionController #:nodoc: # Controls the default charset for all renders. @@default_charset = "utf-8" cattr_accessor :default_charset - + # The logger is used for generating information on the action run-time (including benchmarking) if available. # Can be set to nil for no logging. Compatible with both Ruby's own Logger and Log4r loggers. cattr_accessor :logger @@ -333,7 +333,7 @@ module ActionController #:nodoc: # Controls the resource action separator @@resource_action_separator = "/" cattr_accessor :resource_action_separator - + # Allow to override path names for default resources' actions @@resources_path_names = { :new => 'new', :edit => 'edit' } cattr_accessor :resources_path_names @@ -433,7 +433,7 @@ module ActionController #:nodoc: end # Adds a view_path to the front of the view_paths array. - # If the current class has no view paths, copy them from + # If the current class has no view paths, copy them from # the superclass. This change will be visible for all future requests. # # ArticleController.prepend_view_path("views/default") @@ -444,9 +444,9 @@ module ActionController #:nodoc: view_paths.unshift(*path) ActionView::TemplateFinder.process_view_paths(path) end - + # Adds a view_path to the end of the view_paths array. - # If the current class has no view paths, copy them from + # If the current class has no view paths, copy them from # the superclass. This change will be visible for all future requests. # # ArticleController.append_view_path("views/default") @@ -457,7 +457,7 @@ module ActionController #:nodoc: view_paths.push(*path) ActionView::TemplateFinder.process_view_paths(path) end - + # Replace sensitive parameter data from the request log. # Filters parameters that have any of the arguments as a substring. # Looks in all subhashes of the param hash for keys to filter. @@ -504,6 +504,7 @@ module ActionController #:nodoc: filtered_parameters end + protected :filter_parameters end # Don't render layouts for templates with the given extensions. @@ -643,12 +644,12 @@ module ActionController #:nodoc: end self.view_paths = [] - + # View load paths for controller. def view_paths @template.finder.view_paths end - + def view_paths=(value) @template.finder.view_paths = value # Mutex needed end @@ -662,7 +663,7 @@ module ActionController #:nodoc: def prepend_view_path(path) @template.finder.prepend_view_path(path) # Mutex needed end - + # Adds a view_path to the end of the view_paths array. # This change affects the current request only. # @@ -874,10 +875,10 @@ module ActionController #:nodoc: elsif action_name = options[:action] template = default_template_name(action_name.to_s) if options[:layout] && !template_exempt_from_layout?(template) - render_with_a_layout(:file => template, :status => options[:status], :use_full_path => true, :layout => true) + render_with_a_layout(:file => template, :status => options[:status], :use_full_path => true, :layout => true) else render_with_no_layout(:file => template, :status => options[:status], :use_full_path => true) - end + end elsif xml = options[:xml] response.content_type ||= Mime::XML @@ -895,12 +896,12 @@ module ActionController #:nodoc: if collection = options[:collection] render_for_text( - @template.send!(:render_partial_collection, partial, collection, + @template.send!(:render_partial_collection, partial, collection, options[:spacer_template], options[:locals]), options[:status] ) else render_for_text( - @template.send!(:render_partial, partial, + @template.send!(:render_partial, partial, ActionView::Base::ObjectWrapper.new(options[:object]), options[:locals]), options[:status] ) end @@ -1024,7 +1025,7 @@ module ActionController #:nodoc: # redirect_to articles_url # redirect_to :back # - # The redirection happens as a "302 Moved" header unless otherwise specified. + # The redirection happens as a "302 Moved" header unless otherwise specified. # # Examples: # redirect_to post_url(@post), :status=>:found @@ -1035,17 +1036,17 @@ module ActionController #:nodoc: # When using redirect_to :back, if there is no referrer, # RedirectBackError will be raised. You may specify some fallback # behavior for this case by rescuing RedirectBackError. - def redirect_to(options = {}, response_status = {}) #:doc: + def redirect_to(options = {}, response_status = {}) #:doc: raise ActionControllerError.new("Cannot redirect to nil!") if options.nil? - if options.is_a?(Hash) && options[:status] - status = options.delete(:status) - elsif response_status[:status] - status = response_status[:status] - else - status = 302 + if options.is_a?(Hash) && options[:status] + status = options.delete(:status) + elsif response_status[:status] + status = response_status[:status] + else + status = 302 end - + case options when %r{^\w+://.*} raise DoubleRenderError if performed? @@ -1119,7 +1120,7 @@ module ActionController #:nodoc: response.body = text.is_a?(Proc) ? text : text.to_s end end - + def initialize_template_class(response) response.template = ActionView::Base.new(self.class.view_paths, {}, self) response.template.extend self.class.master_helper_module diff --git a/vendor/rails/actionpack/lib/action_controller/caching/actions.rb b/vendor/rails/actionpack/lib/action_controller/caching/actions.rb index 7b0551c6..1ef9e60a 100644 --- a/vendor/rails/actionpack/lib/action_controller/caching/actions.rb +++ b/vendor/rails/actionpack/lib/action_controller/caching/actions.rb @@ -9,7 +9,7 @@ module ActionController #:nodoc: # class ListsController < ApplicationController # before_filter :authenticate, :except => :public # caches_page :public - # caches_action :show, :feed + # caches_action :index, :show, :feed # end # # In this example, the public action doesn't require authentication, so it's possible to use the faster page caching method. But both the @@ -27,15 +27,19 @@ module ActionController #:nodoc: # You can set modify the default action cache path by passing a :cache_path option. This will be passed directly to ActionCachePath.path_for. This is handy # for actions with multiple possible routes that should be cached differently. If a block is given, it is called with the current controller instance. # + # And you can also use :if to pass a Proc that specifies when the action should be cached. + # # class ListsController < ApplicationController # before_filter :authenticate, :except => :public # caches_page :public + # caches_action :index, :if => Proc.new { |c| !c.request.format.json? } # cache if is not a JSON request # caches_action :show, :cache_path => { :project => 1 } - # caches_action :show, :cache_path => Proc.new { |controller| - # controller.params[:user_id] ? + # caches_action :feed, :cache_path => Proc.new { |controller| + # controller.params[:user_id] ? # controller.send(:user_list_url, c.params[:user_id], c.params[:id]) : # controller.send(:list_url, c.params[:id]) } # end + # module Actions def self.included(base) #:nodoc: base.extend(ClassMethods) @@ -49,7 +53,8 @@ module ActionController #:nodoc: # See ActionController::Caching::Actions for details. def caches_action(*actions) return unless cache_configured? - around_filter(ActionCacheFilter.new(*actions)) + options = actions.extract_options! + around_filter(ActionCacheFilter.new(:cache_path => options.delete(:cache_path)), {:only => actions}.merge(options)) end end @@ -67,16 +72,12 @@ module ActionController #:nodoc: end class ActionCacheFilter #:nodoc: - def initialize(*actions, &block) - @options = actions.extract_options! - @actions = Set.new(actions) + def initialize(options, &block) + @options = options end def before(controller) - return unless @actions.include?(controller.action_name.intern) - cache_path = ActionCachePath.new(controller, path_options_for(controller, @options)) - if cache = controller.read_fragment(cache_path.path) controller.rendered_action_cache = true set_content_type!(controller, cache_path.extension) @@ -88,7 +89,7 @@ module ActionController #:nodoc: end def after(controller) - return if !@actions.include?(controller.action_name.intern) || controller.rendered_action_cache || !caching_allowed(controller) + return if controller.rendered_action_cache || !caching_allowed(controller) controller.write_fragment(controller.action_cache_path.path, controller.response.body) end @@ -105,16 +106,16 @@ module ActionController #:nodoc: controller.request.get? && controller.response.headers['Status'].to_i == 200 end end - + class ActionCachePath attr_reader :path, :extension - + class << self def path_for(controller, options) new(controller, options).path end end - + def initialize(controller, options = {}) @extension = extract_extension(controller.request.path) path = controller.url_for(options).split('://').last @@ -122,16 +123,16 @@ module ActionController #:nodoc: add_extension!(path, @extension) @path = URI.unescape(path) end - + private def normalize!(path) path << 'index' if path[-1] == ?/ end - + def add_extension!(path, extension) path << ".#{extension}" if extension end - + def extract_extension(file_path) # Don't want just what comes after the last '.' to accommodate multi part extensions # such as tar.gz. @@ -140,4 +141,4 @@ module ActionController #:nodoc: end end end -end \ No newline at end of file +end diff --git a/vendor/rails/actionpack/lib/action_controller/caching/fragments.rb b/vendor/rails/actionpack/lib/action_controller/caching/fragments.rb index e4d8678a..e4f5de44 100644 --- a/vendor/rails/actionpack/lib/action_controller/caching/fragments.rb +++ b/vendor/rails/actionpack/lib/action_controller/caching/fragments.rb @@ -98,6 +98,17 @@ module ActionController #:nodoc: end end + # Check if a cached fragment from the location signified by key exists (see expire_fragment for acceptable formats) + def fragment_exist?(key, options = nil) + return unless cache_configured? + + key = fragment_cache_key(key) + + self.class.benchmark "Cached fragment exists?: #{key}" do + cache_store.exist?(key, options) + end + end + # Name can take one of three forms: # * String: This would normally take the form of a path like "pages/45/notes" # * Hash: Is treated as an implicit call to url_for, like { :controller => "pages", :action => "notes", :id => 45 } @@ -124,4 +135,4 @@ module ActionController #:nodoc: end end end -end \ No newline at end of file +end diff --git a/vendor/rails/actionpack/lib/action_controller/caching/sweeping.rb b/vendor/rails/actionpack/lib/action_controller/caching/sweeping.rb index 3164e14f..61559e9e 100644 --- a/vendor/rails/actionpack/lib/action_controller/caching/sweeping.rb +++ b/vendor/rails/actionpack/lib/action_controller/caching/sweeping.rb @@ -28,7 +28,7 @@ module ActionController #:nodoc: # class ListsController < ApplicationController # caches_action :index, :show, :public, :feed # cache_sweeper OpenBar::Sweeper, :only => [ :edit, :destroy, :share ] - # end + # end module Sweeping def self.included(base) #:nodoc: base.extend(ClassMethods) @@ -40,7 +40,7 @@ module ActionController #:nodoc: sweepers.each do |sweeper| ActiveRecord::Base.observers << sweeper if defined?(ActiveRecord) and defined?(ActiveRecord::Base) - sweeper_instance = (sweeper.is_a?(Symbol) ? Object.const_get(Inflector.classify(sweeper)) : sweeper).instance + sweeper_instance = (sweeper.is_a?(Symbol) ? Object.const_get(sweeper.to_s.classify) : sweeper).instance if sweeper_instance.is_a?(Sweeper) around_filter(sweeper_instance, :only => configuration[:only]) @@ -94,4 +94,4 @@ module ActionController #:nodoc: end end end -end \ No newline at end of file +end diff --git a/vendor/rails/actionpack/lib/action_controller/cgi_ext/cookie.rb b/vendor/rails/actionpack/lib/action_controller/cgi_ext/cookie.rb index 3dd374f1..009ddd1c 100644 --- a/vendor/rails/actionpack/lib/action_controller/cgi_ext/cookie.rb +++ b/vendor/rails/actionpack/lib/action_controller/cgi_ext/cookie.rb @@ -6,25 +6,24 @@ class CGI #:nodoc: attr_accessor :name, :value, :path, :domain, :expires attr_reader :secure, :http_only - # Create a new CGI::Cookie object. + # Creates a new CGI::Cookie object. # # The contents of the cookie can be specified as a +name+ and one # or more +value+ arguments. Alternatively, the contents can # be specified as a single hash argument. The possible keywords of # this hash are as follows: # - # name:: the name of the cookie. Required. - # value:: the cookie's value or list of values. - # path:: the path for which this cookie applies. Defaults to the - # base directory of the CGI script. - # domain:: the domain for which this cookie applies. - # expires:: the time at which this cookie expires, as a +Time+ object. - # secure:: whether this cookie is a secure cookie or not (default to - # false). Secure cookies are only transmitted to HTTPS - # servers. - # http_only:: whether this cookie can be accessed by client side scripts (e.g. document.cookie) or only over HTTP - # More details: http://msdn2.microsoft.com/en-us/library/system.web.httpcookie.httponly.aspx - # Defaults to false. + # * :name - The name of the cookie. Required. + # * :value - The cookie's value or list of values. + # * :path - The path for which this cookie applies. Defaults to the + # base directory of the CGI script. + # * :domain - The domain for which this cookie applies. + # * :expires - The time at which this cookie expires, as a Time object. + # * :secure - Whether this cookie is a secure cookie or not (defaults to + # +false+). Secure cookies are only transmitted to HTTPS servers. + # * :http_only - Whether this cookie can be accessed by client side scripts (e.g. document.cookie) or only over HTTP. + # More details in http://msdn2.microsoft.com/en-us/library/system.web.httpcookie.httponly.aspx. Defaults to +false+. + # # These keywords correspond to attributes of the cookie object. def initialize(name = '', *value) if name.kind_of?(String) @@ -37,7 +36,7 @@ class CGI #:nodoc: @path = nil else @name = name['name'] - @value = Array(name['value']) + @value = (name['value'].kind_of?(String) ? [name['value']] : Array(name['value'])).delete_if(&:blank?) @domain = name['domain'] @expires = name['expires'] @secure = name['secure'] || false @@ -56,17 +55,17 @@ class CGI #:nodoc: super(@value) end - # Set whether the Cookie is a secure cookie or not. + # Sets whether the Cookie is a secure cookie or not. def secure=(val) @secure = val == true end - # Set whether the Cookie is an HTTP only cookie or not. + # Sets whether the Cookie is an HTTP only cookie or not. def http_only=(val) @http_only = val == true end - # Convert the Cookie to its string representation. + # Converts the Cookie to its string representation. def to_s buf = '' buf << @name << '=' @@ -79,11 +78,17 @@ class CGI #:nodoc: buf end - # Parse a raw cookie string into a hash of cookie-name=>Cookie + # FIXME: work around broken 1.8.7 DelegateClass#respond_to? + def respond_to?(method, include_private = false) + return true if super(method) + return __getobj__.respond_to?(method, include_private) + end + + # Parses a raw cookie string into a hash of cookie-name => cookie-object # pairs. # # cookies = CGI::Cookie::parse("raw_cookie_string") - # # { "name1" => cookie1, "name2" => cookie2, ... } + # # => { "name1" => cookie1, "name2" => cookie2, ... } # def self.parse(raw_cookie) cookies = Hash.new([]) diff --git a/vendor/rails/actionpack/lib/action_controller/cgi_ext/stdinput.rb b/vendor/rails/actionpack/lib/action_controller/cgi_ext/stdinput.rb index b0ca63ef..5e9b6784 100644 --- a/vendor/rails/actionpack/lib/action_controller/cgi_ext/stdinput.rb +++ b/vendor/rails/actionpack/lib/action_controller/cgi_ext/stdinput.rb @@ -16,6 +16,7 @@ module ActionController def initialize_with_stdinput(type = nil, stdinput = $stdin) @stdinput = stdinput + @stdinput.set_encoding(Encoding::BINARY) if @stdinput.respond_to?(:set_encoding) initialize_without_stdinput(type || 'query') 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 b529db8a..8bc5e4c3 100644 --- a/vendor/rails/actionpack/lib/action_controller/cgi_process.rb +++ b/vendor/rails/actionpack/lib/action_controller/cgi_process.rb @@ -15,7 +15,7 @@ module ActionController #:nodoc: # * :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. - # * :session_expires - the time the current session expires, as a +Time+ object. If not set, the session will continue + # * :session_expires - the time the current session expires, as a Time object. If not set, the session will continue # indefinitely. # * :session_domain - the hostname domain for which this session is valid. If not set, defaults to the hostname of the # server. @@ -65,6 +65,7 @@ module ActionController #:nodoc: # variable is already set, wrap it in a StringIO. def body if raw_post = env['RAW_POST_DATA'] + raw_post.force_encoding(Encoding::BINARY) if raw_post.respond_to?(:force_encoding) StringIO.new(raw_post) else @cgi.stdinput diff --git a/vendor/rails/actionpack/lib/action_controller/filters.rb b/vendor/rails/actionpack/lib/action_controller/filters.rb index 6d0c83eb..60d92d9b 100644 --- a/vendor/rails/actionpack/lib/action_controller/filters.rb +++ b/vendor/rails/actionpack/lib/action_controller/filters.rb @@ -100,10 +100,10 @@ module ActionController #:nodoc: # # Around filters wrap an action, executing code both before and after. # They may be declared as method references, blocks, or objects responding - # to #filter or to both #before and #after. + # to +filter+ or to both +before+ and +after+. # - # To use a method as an around_filter, pass a symbol naming the Ruby method. - # Yield (or block.call) within the method to run the action. + # To use a method as an +around_filter+, pass a symbol naming the Ruby method. + # Yield (or block.call) within the method to run the action. # # around_filter :catch_exceptions # @@ -115,9 +115,9 @@ module ActionController #:nodoc: # raise # end # - # To use a block as an around_filter, pass a block taking as args both + # To use a block as an +around_filter+, pass a block taking as args both # the controller and the action block. You can't call yield directly from - # an around_filter block; explicitly call the action block instead: + # an +around_filter+ block; explicitly call the action block instead: # # around_filter do |controller, action| # logger.debug "before #{controller.action_name}" @@ -125,7 +125,7 @@ module ActionController #:nodoc: # logger.debug "after #{controller.action_name}" # end # - # To use a filter object with around_filter, pass an object responding + # To use a filter object with +around_filter+, pass an object responding # to :filter or both :before and :after. With a # filter method, yield to the block as above: # @@ -137,7 +137,7 @@ module ActionController #:nodoc: # end # end # - # With before and after methods: + # With +before+ and +after+ methods: # # around_filter Authorizer.new # @@ -154,9 +154,9 @@ module ActionController #:nodoc: # end # end # - # If the filter has before and after methods, the before method will be - # called before the action. If before renders or redirects, the filter chain is - # halted and after will not be run. See Filter Chain Halting below for + # If the filter has +before+ and +after+ methods, the +before+ method will be + # called before the action. If +before+ renders or redirects, the filter chain is + # halted and +after+ will not be run. See Filter Chain Halting below for # an example. # # == Filter chain skipping @@ -215,7 +215,7 @@ module ActionController #:nodoc: # # before_filter and around_filter may halt the request # before a controller action is run. This is useful, for example, to deny - # access to unauthenticated users or to redirect from http to https. + # access to unauthenticated users or to redirect from HTTP to HTTPS. # Simply call render or redirect. After filters will not be executed if the filter # chain is halted. # @@ -241,10 +241,10 @@ module ActionController #:nodoc: # . / # #after (actual filter code is run, unless the around filter does not yield) # - # If #around returns before yielding, #after will still not be run. The #before - # filter and controller action will not be run. If #before renders or redirects, - # the second half of #around and will still run but #after and the - # action will not. If #around fails to yield, #after will not be run. + # If +around+ returns before yielding, +after+ will still not be run. The +before+ + # filter and controller action will not be run. If +before+ renders or redirects, + # the second half of +around+ and will still run but +after+ and the + # action will not. If +around+ fails to yield, +after+ will not be run. class FilterChain < ActiveSupport::Callbacks::CallbackChain #:nodoc: def append_filter_to_chain(filters, filter_type, &block) @@ -471,7 +471,7 @@ module ActionController #:nodoc: # Shorthand for append_after_filter since it's the most common. alias :after_filter :append_after_filter - # If you append_around_filter A.new, B.new, the filter chain looks like + # If you append_around_filter A.new, B.new, the filter chain looks like # # B#before # A#before @@ -479,13 +479,13 @@ module ActionController #:nodoc: # A#after # B#after # - # With around filters which yield to the action block, #before and #after + # With around filters which yield to the action block, +before+ and +after+ # are the code before and after the yield. def append_around_filter(*filters, &block) filter_chain.append_filter_to_chain(filters, :around, &block) end - # If you prepend_around_filter A.new, B.new, the filter chain looks like: + # If you prepend_around_filter A.new, B.new, the filter chain looks like: # # A#before # B#before @@ -493,13 +493,13 @@ module ActionController #:nodoc: # B#after # A#after # - # With around filters which yield to the action block, #before and #after + # With around filters which yield to the action block, +before+ and +after+ # are the code before and after the yield. def prepend_around_filter(*filters, &block) filter_chain.prepend_filter_to_chain(filters, :around, &block) end - # Shorthand for append_around_filter since it's the most common. + # Shorthand for +append_around_filter+ since it's the most common. alias :around_filter :append_around_filter # Removes the specified filters from the +before+ filter chain. Note that this only works for skipping method-reference diff --git a/vendor/rails/actionpack/lib/action_controller/helpers.rb b/vendor/rails/actionpack/lib/action_controller/helpers.rb index a8bead4d..ce5e8be5 100644 --- a/vendor/rails/actionpack/lib/action_controller/helpers.rb +++ b/vendor/rails/actionpack/lib/action_controller/helpers.rb @@ -20,7 +20,7 @@ module ActionController #:nodoc: end # The Rails framework provides a large number of helpers for working with +assets+, +dates+, +forms+, - # +numbers+ and +ActiveRecord+ objects, to name a few. These helpers are available to all templates + # +numbers+ and Active Record objects, to name a few. These helpers are available to all templates # by default. # # In addition to using the standard template helpers provided in the Rails framework, creating custom helpers to @@ -32,7 +32,7 @@ module ActionController #:nodoc: # controller which inherits from it. # # ==== Examples - # The +to_s+ method from the +Time+ class can be wrapped in a helper method to display a custom message if + # The +to_s+ method from the Time class can be wrapped in a helper method to display a custom message if # the Time object is blank: # # module FormattedTimeHelper @@ -41,7 +41,7 @@ module ActionController #:nodoc: # end # end # - # +FormattedTimeHelper+ can now be included in a controller, using the +helper+ class method: + # FormattedTimeHelper can now be included in a controller, using the +helper+ class method: # # class EventsController < ActionController::Base # helper FormattedTimeHelper @@ -74,22 +74,22 @@ module ActionController #:nodoc: # The +helper+ class method can take a series of helper module names, a block, or both. # - # * *args: One or more +Modules+, +Strings+ or +Symbols+, or the special symbol :all. + # * *args: One or more modules, strings or symbols, or the special symbol :all. # * &block: A block defining helper methods. # # ==== Examples - # When the argument is a +String+ or +Symbol+, the method will provide the "_helper" suffix, require the file + # When the argument is a string or symbol, the method will provide the "_helper" suffix, require the file # and include the module in the template class. The second form illustrates how to include custom helpers # when working with namespaced controllers, or other cases where the file containing the helper definition is not # in one of Rails' standard load paths: # helper :foo # => requires 'foo_helper' and includes FooHelper # helper 'resources/foo' # => requires 'resources/foo_helper' and includes Resources::FooHelper # - # When the argument is a +Module+, it will be included directly in the template class. + # When the argument is a module it will be included directly in the template class. # helper FooHelper # => includes FooHelper # # When the argument is the symbol :all, the controller will include all helpers from - # app/helpers/**/*.rb under +RAILS_ROOT+. + # app/helpers/**/*.rb under RAILS_ROOT. # helper :all # # Additionally, the +helper+ class method can receive and evaluate a block, making the methods defined available diff --git a/vendor/rails/actionpack/lib/action_controller/integration.rb b/vendor/rails/actionpack/lib/action_controller/integration.rb index a4bbee9c..bd69d02e 100644 --- a/vendor/rails/actionpack/lib/action_controller/integration.rb +++ b/vendor/rails/actionpack/lib/action_controller/integration.rb @@ -58,7 +58,7 @@ module ActionController class MultiPartNeededException < Exception end - # Create and initialize a new +Session+ instance. + # Create and initialize a new Session instance. def initialize reset! end @@ -136,25 +136,25 @@ module ActionController end # Performs a GET request, following any subsequent redirect. - # See #request_via_redirect() for more information. + # See +request_via_redirect+ for more information. def get_via_redirect(path, parameters = nil, headers = nil) request_via_redirect(:get, path, parameters, headers) end # Performs a POST request, following any subsequent redirect. - # See #request_via_redirect() for more information. + # See +request_via_redirect+ for more information. def post_via_redirect(path, parameters = nil, headers = nil) request_via_redirect(:post, path, parameters, headers) end # Performs a PUT request, following any subsequent redirect. - # See #request_via_redirect() for more information. + # See +request_via_redirect+ for more information. def put_via_redirect(path, parameters = nil, headers = nil) request_via_redirect(:put, path, parameters, headers) end # Performs a DELETE request, following any subsequent redirect. - # See #request_via_redirect() for more information. + # See +request_via_redirect+ for more information. def delete_via_redirect(path, parameters = nil, headers = nil) request_via_redirect(:delete, path, parameters, headers) end @@ -166,12 +166,12 @@ 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 + # (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. # - # You can also perform POST, PUT, DELETE, and HEAD requests with #post, - # #put, #delete, and #head. + # 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 end @@ -228,6 +228,8 @@ module ActionController super + stdinput.set_encoding(Encoding::BINARY) if stdinput.respond_to?(:set_encoding) + stdinput.force_encoding(Encoding::BINARY) if stdinput.respond_to?(:force_encoding) @stdinput = stdinput.is_a?(IO) ? stdinput : StringIO.new(stdinput || '') end end @@ -382,6 +384,8 @@ module ActionController multipart_requestify(params).map do |key, value| if value.respond_to?(:original_filename) File.open(value.path) do |f| + f.set_encoding(Encoding::BINARY) if f.respond_to?(:set_encoding) + <<-EOF --#{boundary}\r Content-Disposition: form-data; name="#{key}"; filename="#{CGI.escape(value.original_filename)}"\r diff --git a/vendor/rails/actionpack/lib/action_controller/mime_responds.rb b/vendor/rails/actionpack/lib/action_controller/mime_responds.rb index a17782ca..1dbd8b9e 100644 --- a/vendor/rails/actionpack/lib/action_controller/mime_responds.rb +++ b/vendor/rails/actionpack/lib/action_controller/mime_responds.rb @@ -92,7 +92,7 @@ module ActionController #:nodoc: # with the remaining data. # # Note that you can define your own XML parameter parser which would allow you to describe multiple entities - # in a single request (i.e., by wrapping them all in a single root note), but if you just go with the flow + # in a single request (i.e., by wrapping them all in a single root node), but if you just go with the flow # and accept Rails' defaults, life will be much easier. # # If you need to use a MIME type which isn't supported by default, you can register your own handlers in diff --git a/vendor/rails/actionpack/lib/action_controller/mime_type.rb b/vendor/rails/actionpack/lib/action_controller/mime_type.rb index 8c02f205..fa123f78 100644 --- a/vendor/rails/actionpack/lib/action_controller/mime_type.rb +++ b/vendor/rails/actionpack/lib/action_controller/mime_type.rb @@ -17,6 +17,10 @@ module Mime # end # end class Type + @@html_types = Set.new [:html, :all] + @@unverifiable_types = Set.new [:text, :json, :csv, :xml, :rss, :atom, :yaml] + cattr_reader :html_types, :unverifiable_types + # A simple helper class used in parsing the accept header class AcceptItem #:nodoc: attr_accessor :order, :name, :q @@ -100,7 +104,7 @@ module Mime list[text_xml].name = Mime::XML.to_s end - # Look for more specific xml-based types and sort them ahead of app/xml + # Look for more specific XML-based types and sort them ahead of app/xml if app_xml idx = app_xml @@ -153,12 +157,21 @@ module Mime synonym.to_s == mime_type.to_s || synonym.to_sym == mime_type.to_sym end end - + + # Returns true if Action Pack should check requests using this Mime Type for possible request forgery. See + # ActionController::RequestForgerProtection. + def verify_request? + !@@unverifiable_types.include?(to_sym) + end + + def html? + @@html_types.include?(to_sym) || @string =~ /html/ + end + private def method_missing(method, *args) if method.to_s =~ /(\w+)\?$/ - mime_type = $1.downcase.to_sym - mime_type == @symbol || (mime_type == :html && @symbol == :all) + $1.downcase.to_sym == to_sym else super end diff --git a/vendor/rails/actionpack/lib/action_controller/mime_types.rb b/vendor/rails/actionpack/lib/action_controller/mime_types.rb index 71706b4c..01a266d3 100644 --- a/vendor/rails/actionpack/lib/action_controller/mime_types.rb +++ b/vendor/rails/actionpack/lib/action_controller/mime_types.rb @@ -17,4 +17,4 @@ Mime::Type.register "multipart/form-data", :multipart_form Mime::Type.register "application/x-www-form-urlencoded", :url_encoded_form # http://www.ietf.org/rfc/rfc4627.txt -Mime::Type.register "application/json", :json, %w( text/x-json ) +Mime::Type.register "application/json", :json, %w( text/x-json ) \ No newline at end of file diff --git a/vendor/rails/actionpack/lib/action_controller/polymorphic_routes.rb b/vendor/rails/actionpack/lib/action_controller/polymorphic_routes.rb index e2b7716a..509fa6a0 100644 --- a/vendor/rails/actionpack/lib/action_controller/polymorphic_routes.rb +++ b/vendor/rails/actionpack/lib/action_controller/polymorphic_routes.rb @@ -1,6 +1,6 @@ module ActionController # Polymorphic URL helpers are methods for smart resolution to a named route call when - # given an ActiveRecord model instance. They are to be used in combination with + # given an Active Record model instance. They are to be used in combination with # ActionController::Resources. # # These methods are useful when you want to generate correct URL or path to a RESTful @@ -9,7 +9,9 @@ module ActionController # Nested resources and/or namespaces are also supported, as illustrated in the example: # # polymorphic_url([:admin, @article, @comment]) - # #-> results in: + # + # results in: + # # admin_article_comment_url(@article, @comment) # # == Usage within the framework @@ -38,11 +40,8 @@ module ActionController # # Example usage: # - # edit_polymorphic_path(@post) - # #=> /posts/1/edit - # - # formatted_polymorphic_path([@post, :pdf]) - # #=> /posts/1.pdf + # edit_polymorphic_path(@post) # => "/posts/1/edit" + # formatted_polymorphic_path([@post, :pdf]) # => "/posts/1.pdf" module PolymorphicRoutes # Constructs a call to a named RESTful route for the given record and returns the # resulting URL string. For example: diff --git a/vendor/rails/actionpack/lib/action_controller/request.rb b/vendor/rails/actionpack/lib/action_controller/request.rb index d5ecbd9d..a35b9041 100755 --- a/vendor/rails/actionpack/lib/action_controller/request.rb +++ b/vendor/rails/actionpack/lib/action_controller/request.rb @@ -466,8 +466,8 @@ EOM parser.result end - def parse_multipart_form_parameters(body, boundary, content_length, env) - parse_request_parameters(read_multipart(body, boundary, content_length, env)) + def parse_multipart_form_parameters(body, boundary, body_size, env) + parse_request_parameters(read_multipart(body, boundary, body_size, env)) end def extract_multipart_boundary(content_type_with_parameters) @@ -519,7 +519,7 @@ EOM EOL = "\015\012" - def read_multipart(body, boundary, content_length, env) + def read_multipart(body, boundary, body_size, env) params = Hash.new([]) boundary = "--" + boundary quoted_boundary = Regexp.quote(boundary) @@ -529,8 +529,14 @@ EOM # start multipart/form-data body.binmode if defined? body.binmode + case body + when File + body.set_encoding(Encoding::BINARY) if body.respond_to?(:set_encoding) + when StringIO + body.string.force_encoding(Encoding::BINARY) if body.string.respond_to?(:force_encoding) + end boundary_size = boundary.size + EOL.size - content_length -= boundary_size + body_size -= boundary_size status = body.read(boundary_size) if nil == status raise EOFError, "no content body" @@ -541,7 +547,7 @@ EOM loop do head = nil content = - if 10240 < content_length + if 10240 < body_size UploadedTempfile.new("CGI") else UploadedStringIO.new @@ -563,24 +569,24 @@ EOM buf[0 ... (buf.size - (EOL + boundary + EOL).size)] = "" end - c = if bufsize < content_length + c = if bufsize < body_size body.read(bufsize) else - body.read(content_length) + body.read(body_size) end if c.nil? || c.empty? raise EOFError, "bad content body" end buf.concat(c) - content_length -= c.size + body_size -= c.size end buf = buf.sub(/\A((?:.|\n)*?)(?:[\r\n]{1,2})?#{quoted_boundary}([\r\n]{1,2}|--)/n) do content.print $1 if "--" == $2 - content_length = -1 + body_size = -1 end - boundary_end = $2.dup + boundary_end = $2.dup "" end @@ -607,7 +613,7 @@ EOM else params[name] = [content] end - break if content_length == -1 + break if body_size == -1 end raise EOFError, "bad boundary end of body part" unless boundary_end=~/--/ diff --git a/vendor/rails/actionpack/lib/action_controller/request_forgery_protection.rb b/vendor/rails/actionpack/lib/action_controller/request_forgery_protection.rb index 139e91ec..02c9d59d 100644 --- a/vendor/rails/actionpack/lib/action_controller/request_forgery_protection.rb +++ b/vendor/rails/actionpack/lib/action_controller/request_forgery_protection.rb @@ -99,7 +99,7 @@ module ActionController #:nodoc: end def verifiable_request_format? - request.format.html? || request.format.js? + request.content_type.nil? || request.content_type.verify_request? end # Sets the token value for the current session. Pass a :secret option diff --git a/vendor/rails/actionpack/lib/action_controller/request_profiler.rb b/vendor/rails/actionpack/lib/action_controller/request_profiler.rb index 8a18d194..a6471d0c 100755 --- a/vendor/rails/actionpack/lib/action_controller/request_profiler.rb +++ b/vendor/rails/actionpack/lib/action_controller/request_profiler.rb @@ -17,13 +17,13 @@ module ActionController reset! end - def benchmark(n) + def benchmark(n, profiling = false) @quiet = true print ' ' result = Benchmark.realtime do n.times do |i| - run + run(profiling) print_progress(i) end end @@ -43,8 +43,15 @@ module ActionController script = File.read(script_path) source = <<-end_source - def run - #{script} + def run(profiling = false) + if profiling + RubyProf.resume do + #{script} + end + else + #{script} + end + old_request_count = request_count reset! self.request_count = old_request_count @@ -91,21 +98,22 @@ module ActionController def profile(sandbox) load_ruby_prof - results = RubyProf.profile { benchmark(sandbox) } + benchmark(sandbox, true) + results = RubyProf.stop show_profile_results results results end - def benchmark(sandbox) + def benchmark(sandbox, profiling = false) sandbox.request_count = 0 - elapsed = sandbox.benchmark(options[:n]).to_f + elapsed = sandbox.benchmark(options[:n], profiling).to_f count = sandbox.request_count.to_i puts '%.2f sec, %d requests, %d req/sec' % [elapsed, count, count / elapsed] end def warmup(sandbox) - Benchmark.realtime { sandbox.run } + Benchmark.realtime { sandbox.run(false) } end def default_options @@ -136,6 +144,7 @@ module ActionController protected def load_ruby_prof begin + gem 'ruby-prof', '>= 0.6.1' require 'ruby-prof' if mode = options[:measure] RubyProf.measure_mode = RubyProf.const_get(mode.upcase) diff --git a/vendor/rails/actionpack/lib/action_controller/rescue.rb b/vendor/rails/actionpack/lib/action_controller/rescue.rb index 5022c9a8..40ef4ea0 100644 --- a/vendor/rails/actionpack/lib/action_controller/rescue.rb +++ b/vendor/rails/actionpack/lib/action_controller/rescue.rb @@ -199,10 +199,8 @@ module ActionController #:nodoc: private def perform_action_with_rescue #:nodoc: perform_action_without_rescue - rescue Exception => exception # errors from action performed - return if rescue_action_with_handler(exception) - - rescue_action(exception) + rescue Exception => exception + rescue_action_with_handler(exception) || rescue_action(exception) end def rescues_path(template_name) diff --git a/vendor/rails/actionpack/lib/action_controller/resources.rb b/vendor/rails/actionpack/lib/action_controller/resources.rb index 26f75780..9fb1f9fa 100644 --- a/vendor/rails/actionpack/lib/action_controller/resources.rb +++ b/vendor/rails/actionpack/lib/action_controller/resources.rb @@ -191,7 +191,7 @@ module ActionController # end # end # - # Along with the routes themselves, #resources generates named routes for use in + # Along with the routes themselves, +resources+ generates named routes for use in # controllers and views. map.resources :messages produces the following named routes and helpers: # # Named Route Helpers @@ -208,7 +208,7 @@ module ActionController # edit_message edit_message_url(id), hash_for_edit_message_url(id), # edit_message_path(id), hash_for_edit_message_path(id) # - # You can use these helpers instead of #url_for or methods that take #url_for parameters. For example: + # You can use these helpers instead of +url_for+ or methods that take +url_for+ parameters. For example: # # redirect_to :controller => 'messages', :action => 'index' # # and @@ -406,7 +406,7 @@ module ActionController # end # end # - # Along with the routes themselves, #resource generates named routes for + # Along with the routes themselves, +resource+ generates named routes for # use in controllers and views. map.resource :account produces # these named routes and helpers: # diff --git a/vendor/rails/actionpack/lib/action_controller/routing/builder.rb b/vendor/rails/actionpack/lib/action_controller/routing/builder.rb index b1a98d1a..4740113e 100644 --- a/vendor/rails/actionpack/lib/action_controller/routing/builder.rb +++ b/vendor/rails/actionpack/lib/action_controller/routing/builder.rb @@ -23,9 +23,9 @@ module ActionController # Accepts a "route path" (a string defining a route), and returns the array # of segments that corresponds to it. Note that the segment array is only # partially initialized--the defaults and requirements, for instance, need - # to be set separately, via the #assign_route_options method, and the - # #optional? method for each segment will not be reliable until after - # #assign_route_options is called, as well. + # to be set separately, via the +assign_route_options+ method, and the + # optional? method for each segment will not be reliable until after + # +assign_route_options+ is called, as well. def segments_for_route_path(path) rest, segments = path, [] diff --git a/vendor/rails/actionpack/lib/action_controller/routing/segments.rb b/vendor/rails/actionpack/lib/action_controller/routing/segments.rb index aff8afc4..e6729201 100644 --- a/vendor/rails/actionpack/lib/action_controller/routing/segments.rb +++ b/vendor/rails/actionpack/lib/action_controller/routing/segments.rb @@ -248,7 +248,7 @@ module ActionController end def extract_value - "#{local_name} = hash[:#{key}] && hash[:#{key}].collect { |path_component| CGI.escape(path_component) }.to_param #{"|| #{default.inspect}" if default}" + "#{local_name} = hash[:#{key}] && hash[:#{key}].collect { |path_component| CGI.escape(path_component.to_param, ActionController::Routing::Segment::UNSAFE_PCHAR) }.to_param #{"|| #{default.inspect}" if default}" end def default diff --git a/vendor/rails/actionpack/lib/action_controller/session/cookie_store.rb b/vendor/rails/actionpack/lib/action_controller/session/cookie_store.rb index 560491f9..b477c1f7 100644 --- a/vendor/rails/actionpack/lib/action_controller/session/cookie_store.rb +++ b/vendor/rails/actionpack/lib/action_controller/session/cookie_store.rb @@ -34,7 +34,7 @@ require 'openssl' # to generate the HMAC message digest # such as 'MD5', 'RIPEMD160', 'SHA256', etc. # # To generate a secret key for an existing application, run -# `rake secret` and set the key in config/environment.rb. +# "rake secret" and set the key in config/environment.rb. # # Note that changing digest or secret invalidates all existing sessions! class CGI::Session::CookieStore @@ -130,17 +130,20 @@ class CGI::Session::CookieStore # Marshal a session hash into safe cookie data. Include an integrity hash. def marshal(session) data = ActiveSupport::Base64.encode64(Marshal.dump(session)).chop - CGI.escape "#{data}--#{generate_digest(data)}" + "#{data}--#{generate_digest(data)}" end # Unmarshal cookie data to a hash and verify its integrity. def unmarshal(cookie) if cookie - data, digest = CGI.unescape(cookie).split('--') - unless digest == generate_digest(data) + data, digest = cookie.split('--') + + # Do two checks to transparently support old double-escaped data. + unless digest == generate_digest(data) || digest == generate_digest(data = CGI.unescape(data)) delete raise TamperedWithCookie end + Marshal.load(ActiveSupport::Base64.decode64(data)) end end diff --git a/vendor/rails/actionpack/lib/action_controller/test_case.rb b/vendor/rails/actionpack/lib/action_controller/test_case.rb index 757a80ce..77c6f26e 100644 --- a/vendor/rails/actionpack/lib/action_controller/test_case.rb +++ b/vendor/rails/actionpack/lib/action_controller/test_case.rb @@ -80,4 +80,4 @@ module ActionController @request.remote_addr = '208.77.188.166' # example.com end end -end +end \ No newline at end of file diff --git a/vendor/rails/actionpack/lib/action_controller/test_process.rb b/vendor/rails/actionpack/lib/action_controller/test_process.rb index dcb6cdf4..0cf14321 100644 --- a/vendor/rails/actionpack/lib/action_controller/test_process.rb +++ b/vendor/rails/actionpack/lib/action_controller/test_process.rb @@ -3,7 +3,7 @@ require 'action_controller/test_case' module ActionController #:nodoc: class Base - # Process a test request called with a +TestRequest+ object. + # Process a test request called with a TestRequest object. def self.process_test(request) new.process_test(request) end @@ -49,7 +49,7 @@ module ActionController #:nodoc: # Either the RAW_POST_DATA environment variable or the URL-encoded request # parameters. def raw_post - env['RAW_POST_DATA'] ||= url_encoded_request_parameters + env['RAW_POST_DATA'] ||= returning(url_encoded_request_parameters) { |b| b.force_encoding(Encoding::BINARY) if b.respond_to?(:force_encoding) } end def port=(number) @@ -340,6 +340,7 @@ module ActionController #:nodoc: @content_type = content_type @original_filename = path.sub(/^.*#{File::SEPARATOR}([^#{File::SEPARATOR}]+)$/) { $1 } @tempfile = Tempfile.new(@original_filename) + @tempfile.set_encoding(Encoding::BINARY) if @tempfile.respond_to?(:set_encoding) @tempfile.binmode if binary FileUtils.copy_file(path, @tempfile.path) end @@ -357,7 +358,7 @@ module ActionController #:nodoc: module TestProcess def self.included(base) - # execute the request simulating a specific http method and set/volley the response + # execute the request simulating a specific HTTP method and set/volley the response %w( get post put delete head ).each do |method| base.class_eval <<-EOV, __FILE__, __LINE__ def #{method}(action, parameters = nil, session = nil, flash = nil) diff --git a/vendor/rails/actionpack/lib/action_pack/version.rb b/vendor/rails/actionpack/lib/action_pack/version.rb index 70fc1ced..c67654d9 100644 --- a/vendor/rails/actionpack/lib/action_pack/version.rb +++ b/vendor/rails/actionpack/lib/action_pack/version.rb @@ -1,8 +1,8 @@ module ActionPack #:nodoc: module VERSION #:nodoc: MAJOR = 2 - MINOR = 0 - TINY = 991 + MINOR = 1 + TINY = 0 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 4840b252..f3987565 100644 --- a/vendor/rails/actionpack/lib/action_view/base.rb +++ b/vendor/rails/actionpack/lib/action_view/base.rb @@ -168,12 +168,12 @@ module ActionView #:nodoc: # Specify whether file modification times should be checked to see if a template needs recompilation @@cache_template_loading = false cattr_accessor :cache_template_loading - - # Specify whether file extension lookup should be cached, and whether template base path lookup should be cached. - # Should be +false+ for development environments. Defaults to +true+. - @@cache_template_extensions = true - cattr_accessor :cache_template_extensions + def self.cache_template_extensions=(*args) + ActiveSupport::Deprecation.warn("config.action_view.cache_template_extensions option has been deprecated and has no affect. " << + "Please remove it from your config files.", caller) + end + # Specify whether RJS responses should be wrapped in a try/catch block # that alert()s the caught exception (and then re-raises it). @@debug_rjs = false diff --git a/vendor/rails/actionpack/lib/action_view/compiled_templates.rb b/vendor/rails/actionpack/lib/action_view/compiled_templates.rb deleted file mode 100644 index 5a286432..00000000 --- a/vendor/rails/actionpack/lib/action_view/compiled_templates.rb +++ /dev/null @@ -1,69 +0,0 @@ -module ActionView - - # CompiledTemplates modules hold methods that have been compiled. - # Templates are compiled into these methods so that they do not need to be - # 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 - attr_reader :method_names - - def initialize - @method_names = Hash.new do |hash, key| - hash[key] = "__compiled_method_#{(hash.length + 1)}" - end - @mtimes = {} - end - - # Return the full key for the given identifier and argument names - def full_key(identifier, arg_names) - [identifier, arg_names] - end - - # Return the selector for this method or nil if it has not been compiled - def selector(identifier, arg_names) - key = full_key(identifier, arg_names) - method_names.key?(key) ? method_names[key] : nil - end - alias :compiled? :selector - - # Return the time at which the method for the given identifier and argument names was compiled. - def mtime(identifier, arg_names) - @mtimes[full_key(identifier, arg_names)] - end - - # Compile the provided source code for the given argument names and with the given initial line number. - # The identifier should be unique to this source. - # - # The file_name, if provided will appear in backtraces. If not provided, the file_name defaults - # to the identifier. - # - # This method will return the selector for the compiled version of this method. - def compile_source(identifier, arg_names, source, initial_line_number = 0, file_name = nil) - file_name ||= identifier - name = method_names[full_key(identifier, arg_names)] - arg_desc = arg_names.empty? ? '' : "(#{arg_names * ', '})" - fake_file_name = "#{file_name}#{arg_desc}" # Include the arguments for this version (for now) - - method_def = wrap_source(name, arg_names, source) - - begin - module_eval(method_def, fake_file_name, initial_line_number) - @mtimes[full_key(identifier, arg_names)] = Time.now - rescue Exception => e # errors from compiled source - e.blame_file! identifier - raise - end - name - end - - # Wrap the provided source in a def ... end block. - def wrap_source(name, arg_names, source) - "def #{name}(#{arg_names * ', '})\n#{source}\nend" - end - end -end diff --git a/vendor/rails/actionpack/lib/action_view/helpers/asset_tag_helper.rb b/vendor/rails/actionpack/lib/action_view/helpers/asset_tag_helper.rb index dfc7e2b3..e5a95a96 100644 --- a/vendor/rails/actionpack/lib/action_view/helpers/asset_tag_helper.rb +++ b/vendor/rails/actionpack/lib/action_view/helpers/asset_tag_helper.rb @@ -11,8 +11,8 @@ module ActionView # === Using asset hosts # By default, Rails links to these assets on the current host in the public # folder, but you can direct Rails to link to assets from a dedicated assets server by - # setting ActionController::Base.asset_host in your environment.rb. For example, - # let's say your asset host is assets.example.com. + # setting ActionController::Base.asset_host in your config/environment.rb. For example, + # let's say your asset host is assets.example.com. # # ActionController::Base.asset_host = "assets.example.com" # image_tag("rails.png") @@ -22,8 +22,8 @@ module ActionView # # This is useful since browsers typically open at most two connections to a single host, # which means your assets often wait in single file for their turn to load. You can - # alleviate this by using a %d wildcard in asset_host (for example, "assets%d.example.com") - # to automatically distribute asset requests among four hosts (e.g., assets0.example.com through assets3.example.com) + # alleviate this by using a %d wildcard in asset_host (for example, "assets%d.example.com") + # to automatically distribute asset requests among four hosts (e.g., "assets0.example.com" through "assets3.example.com") # so browsers will open eight connections rather than two. # # image_tag("rails.png") @@ -293,9 +293,9 @@ module ActionView end # Computes the path to a stylesheet asset in the public stylesheets directory. - # If the +source+ filename has no extension, .css will be appended. + # If the +source+ filename has no extension, .css will be appended. # Full paths from the document root will be passed through. - # Used internally by stylesheet_link_tag to build the stylesheet path. + # Used internally by +stylesheet_link_tag+ to build the stylesheet path. # # ==== Examples # stylesheet_path "style" # => /stylesheets/style.css @@ -309,7 +309,7 @@ module ActionView alias_method :path_to_stylesheet, :stylesheet_path # aliased to avoid conflicts with a stylesheet_path named route # Returns a stylesheet link tag for the sources specified as arguments. If - # you don't specify an extension, .css will be appended automatically. + # you don't specify an extension, .css will be appended automatically. # You can modify the link attributes by passing a hash as the last argument. # # ==== Examples @@ -379,7 +379,7 @@ module ActionView # Computes the path to an image asset in the public images directory. # Full paths from the document root will be passed through. - # Used internally by image_tag to build the image path. + # Used internally by +image_tag+ to build the image path. # # ==== Examples # image_path("edit") # => /images/edit @@ -454,8 +454,8 @@ module ActionView end end - # Add the .ext if not present. Return full URLs otherwise untouched. - # Prefix with /dir/ if lacking a leading /. Account for relative URL + # Add the the extension +ext+ if not present. Return full URLs otherwise untouched. + # Prefix with /dir/ if lacking a leading +/+. Account for relative URL # roots. Rewrite the asset path for cache-busting asset ids. Include # asset host, if configured, with the correct request protocol. def compute_public_path(source, dir, ext = nil, include_host = true) @@ -502,9 +502,9 @@ module ActionView end end - # Pick an asset host for this source. Returns nil if no host is set, + # Pick an asset host for this source. Returns +nil+ if no host is set, # the host if no wildcard is set, the host interpolated with the - # numbers 0-3 if it contains %d (the number is the source hash mod 4), + # numbers 0-3 if it contains %d (the number is the source hash mod 4), # or the value returned from invoking the proc if it's a proc. def compute_asset_host(source) if host = ActionController::Base.asset_host diff --git a/vendor/rails/actionpack/lib/action_view/helpers/date_helper.rb b/vendor/rails/actionpack/lib/action_view/helpers/date_helper.rb index 8a9c8044..7ed62728 100755 --- a/vendor/rails/actionpack/lib/action_view/helpers/date_helper.rb +++ b/vendor/rails/actionpack/lib/action_view/helpers/date_helper.rb @@ -689,7 +689,7 @@ module ActionView default[key] ||= time.send(key) end - Time.utc(default[:year], default[:month], default[:day], default[:hour], default[:min], default[:sec]) + Time.utc_time(default[:year], default[:month], default[:day], default[:hour], default[:min], default[:sec]) end end end diff --git a/vendor/rails/actionpack/lib/action_view/helpers/form_helper.rb b/vendor/rails/actionpack/lib/action_view/helpers/form_helper.rb index b8600fe4..0791feb9 100644 --- a/vendor/rails/actionpack/lib/action_view/helpers/form_helper.rb +++ b/vendor/rails/actionpack/lib/action_view/helpers/form_helper.rb @@ -73,30 +73,81 @@ module ActionView # There are also methods for helping to build form tags in link:classes/ActionView/Helpers/FormOptionsHelper.html, # link:classes/ActionView/Helpers/DateHelper.html, and link:classes/ActionView/Helpers/ActiveRecordHelper.html module FormHelper - # Creates a form and a scope around a specific model object that is used as a base for questioning about - # values for the fields. + # Creates a form and a scope around a specific model object that is used as + # a base for questioning about values for the fields. # - # <% form_for :person, @person, :url => { :action => "update" } do |f| %> - # <%= f.error_messages %> - # First name: <%= f.text_field :first_name %> - # Last name : <%= f.text_field :last_name %> - # Biography : <%= f.text_area :biography %> - # Admin? : <%= f.check_box :admin %> + # Rails provides succint resource-oriented form generation with +form_for+ + # like this: + # + # <% form_for @offer do |f| %> + # <%= f.label :version, 'Version' %>: + # <%= f.text_field :version %>
+ # <%= f.label :author, 'Author' %>: + # <%= f.text_field :author %>
# <% end %> # - # Worth noting is that the form_for tag is called in a ERb evaluation block, not an ERb output block. So that's <% %>, - # not <%= %>. Also worth noting is that form_for yields a form_builder object, in this example as f, which emulates - # the API for the stand-alone FormHelper methods, but without the object name. So instead of text_field :person, :name, - # you get away with f.text_field :name. Notice that you can even do <%= f.error_messages %> to display the - # error messsages of the model object in question. + # There, +form_for+ is able to generate the rest of RESTful form parameters + # based on introspection on the record, but to understand what it does we + # need to dig first into the alternative generic usage it is based upon. # - # Even further, the form_for method allows you to more easily escape the instance variable convention. So while the stand-alone - # approach would require text_field :person, :name, :object => person - # to work with local variables instead of instance ones, the form_for calls remain the same. You simply declare once with - # :person, person and all subsequent field calls save :person and :object => person. + # === Generic form_for # - # Also note that form_for doesn't create an exclusive scope. It's still possible to use both the stand-alone FormHelper methods - # and methods from FormTagHelper. For example: + # The generic way to call +form_for+ yields a form builder around a model: + # + # <% form_for :person, :url => { :action => "update" } do |f| %> + # <%= f.error_messages %> + # First name: <%= f.text_field :first_name %>
+ # Last name : <%= f.text_field :last_name %>
+ # Biography : <%= f.text_area :biography %>
+ # Admin? : <%= f.check_box :admin %>
+ # <% end %> + # + # There, the first argument is a symbol or string with the name of the + # object the form is about, and also the name of the instance variable the + # object is stored in. + # + # The form builder acts as a regular form helper that somehow carries the + # model. Thus, the idea is that + # + # <%= f.text_field :first_name %> + # + # gets expanded to + # + # <%= text_field :person, :first_name %> + # + # If the instance variable is not @person you can pass the actual + # record as the second argument: + # + # <% form_for :person, person, :url => { :action => "update" } do |f| %> + # ... + # <% end %> + # + # In that case you can think + # + # <%= f.text_field :first_name %> + # + # gets expanded to + # + # <%= text_field :person, :first_name, :object => person %> + # + # You can even display error messages of the wrapped model this way: + # + # <%= f.error_messages %> + # + # In any of its variants, the rightmost argument to +form_for+ is an + # optional hash of options: + # + # * :url - The URL the form is submitted to. It takes the same fields + # you pass to +url_for+ or +link_to+. In particular you may pass here a + # named route directly as well. Defaults to the current action. + # * :html - Optional HTML attributes for the form tag. + # + # Worth noting is that the +form_for+ tag is called in a ERb evaluation block, + # not an ERb output block. So that's <% %>, not <%= %>. + # + # Also note that +form_for+ doesn't create an exclusive scope. It's still + # possible to use both the stand-alone FormHelper methods and methods from + # FormTagHelper. For example: # # <% form_for :person, @person, :url => { :action => "update" } do |f| %> # First name: <%= f.text_field :first_name %> @@ -105,42 +156,38 @@ module ActionView # Admin? : <%= check_box_tag "person[admin]", @person.company.admin? %> # <% end %> # - # Note: This also works for the methods in FormOptionHelper and DateHelper that are designed to work with an object as base, - # like FormOptionHelper#collection_select and DateHelper#datetime_select. + # This also works for the methods in FormOptionHelper and DateHelper that are + # designed to work with an object as base, like FormOptionHelper#collection_select + # and DateHelper#datetime_select. # - # HTML attributes for the form tag can be given as :html => {...}. For example: + # === Resource-oriented style # - # <% form_for :person, @person, :html => {:id => 'person_form'} do |f| %> + # As we said above, in addition to manually configuring the +form_for+ call, + # you can rely on automated resource identification, which will use the conventions + # and named routes of that approach. This is the preferred way to use +form_for+ + # nowadays. + # + # For example, if @post is an existing record you want to edit + # + # <% form_for @post do |f| %> # ... # <% end %> # - # The above form will then have the id attribute with the value person_form, which you can then - # style with CSS or manipulate with JavaScript. - # - # === Relying on record identification - # - # In addition to manually configuring the form_for call, you can also rely on record identification, which will use - # the conventions and named routes of that approach. Examples: - # - # <% form_for(@post) do |f| %> - # ... - # <% end %> - # - # This will expand to be the same as: + # is equivalent to something like: # # <% form_for :post, @post, :url => post_path(@post), :html => { :method => :put, :class => "edit_post", :id => "edit_post_45" } do |f| %> # ... # <% end %> # - # And for new records: + # And for new records # # <% form_for(Post.new) do |f| %> # ... # <% end %> # - # This will expand to be the same as: + # expands to # - # <% form_for :post, @post, :url => posts_path, :html => { :class => "new_post", :id => "new_post" } do |f| %> + # <% form_for :post, Post.new, :url => posts_path, :html => { :class => "new_post", :id => "new_post" } do |f| %> # ... # <% end %> # @@ -150,7 +197,7 @@ module ActionView # ... # <% end %> # - # And for namespaced routes, like admin_post_url: + # And for namespaced routes, like +admin_post_url+: # # <% form_for([:admin, @post]) do |f| %> # ... @@ -277,13 +324,13 @@ module ActionView # # ==== Examples # label(:post, :title) - # #=> + # # => # # label(:post, :title, "A short title") - # #=> + # # => # # label(:post, :title, "A short title", :class => "title_label") - # #=> + # # => # def label(object_name, method, text = nil, options = {}) InstanceTag.new(object_name, method, self, nil, options.delete(:object)).to_label_tag(text, options) @@ -588,6 +635,8 @@ module ActionView value != 0 when String value == checked_value + when Array + value.include?(checked_value) else value.to_i != 0 end diff --git a/vendor/rails/actionpack/lib/action_view/helpers/form_options_helper.rb b/vendor/rails/actionpack/lib/action_view/helpers/form_options_helper.rb index bf65fe55..e0a097e3 100644 --- a/vendor/rails/actionpack/lib/action_view/helpers/form_options_helper.rb +++ b/vendor/rails/actionpack/lib/action_view/helpers/form_options_helper.rb @@ -119,7 +119,7 @@ module ActionView # end # end # - # Sample usage (selecting the associated +Author+ for an instance of +Post+, @post): + # Sample usage (selecting the associated Author for an instance of Post, @post): # collection_select(:post, :author_id, Author.find(:all), :id, :name_with_initial, {:prompt => true}) # # If @post.author_id is already 1, this would return: @@ -144,10 +144,16 @@ module ActionView # In addition to the :include_blank option documented above, # this method also supports a :model option, which defaults # to TimeZone. This may be used by users to specify a different time - # zone model object. (See #time_zone_options_for_select for more + # zone model object. (See +time_zone_options_for_select+ for more # information.) + # + # You can also supply an array of TimeZone objects + # as +priority_zones+, so that they will be listed above the rest of the + # (long) list. (You can use TimeZone.us_zones as a convenience for + # obtaining a list of the US time zones.) + # # Finally, this method supports a :default option, which selects - # a default TimeZone if the object's time zone is nil. + # a default TimeZone if the object's time zone is +nil+. # # Examples: # time_zone_select( "user", "time_zone", nil, :include_blank => true) @@ -156,6 +162,8 @@ module ActionView # # time_zone_select( "user", 'time_zone', TimeZone.us_zones, :default => "Pacific Time (US & Canada)") # + # time_zone_select( "user", 'time_zone', [ TimeZone['Alaska'], TimeZone['Hawaii'] ]) + # # time_zone_select( "user", "time_zone", TZInfo::Timezone.all.sort, :model => TZInfo::Timezone) def time_zone_select(object, method, priority_zones = nil, options = {}, html_options = {}) InstanceTag.new(object, method, self, nil, options.delete(:object)).to_time_zone_select_tag(priority_zones, options, html_options) @@ -164,7 +172,7 @@ module ActionView # Accepts a container (hash, array, enumerable, your type) and returns a string of option tags. Given a container # where the elements respond to first and last (such as a two-element array), the "lasts" serve as option values and # the "firsts" as option text. Hashes are turned into this form automatically, so the keys become "firsts" and values - # become lasts. If +selected+ is specified, the matching "last" or element will get the selected option-tag. +Selected+ + # become lasts. If +selected+ is specified, the matching "last" or element will get the selected option-tag. +selected+ # may also be an array of values to be selected when using a multiple select. # # Examples (call, result): @@ -209,24 +217,22 @@ module ActionView options_for_select(options, selected) end - # Returns a string of tags, like #options_from_collection_for_select, but + # Returns a string of tags, like options_from_collection_for_select, but # groups them by tags based on the object relationships of the arguments. # # Parameters: - # +collection+:: An array of objects representing the tags - # +group_method+:: The name of a method which, when called on a member of +collection+, returns an - # array of child objects representing the tags - # +group_label_method+:: The name of a method which, when called on a member of +collection+, returns a - # string to be used as the +label+ attribute for its tag - # +option_key_method+:: The name of a method which, when called on a child object of a member of - # +collection+, returns a value to be used as the +value+ attribute for its - # tag - # +option_value_method+:: The name of a method which, when called on a child object of a member of - # +collection+, returns a value to be used as the contents of its - # tag - # +selected_key+:: A value equal to the +value+ attribute for one of the tags, - # which will have the +selected+ attribute set. Corresponds to the return value - # of one of the calls to +option_key_method+. If +nil+, no selection is made. + # * +collection+ - An array of objects representing the tags. + # * +group_method+ - The name of a method which, when called on a member of +collection+, returns an + # array of child objects representing the tags. + # * group_label_method+ - The name of a method which, when called on a member of +collection+, returns a + # string to be used as the +label+ attribute for its tag. + # * +option_key_method+ - The name of a method which, when called on a child object of a member of + # +collection+, returns a value to be used as the +value+ attribute for its tag. + # * +option_value_method+ - The name of a method which, when called on a child object of a member of + # +collection+, returns a value to be used as the contents of its tag. + # * +selected_key+ - A value equal to the +value+ attribute for one of the tags, + # which will have the +selected+ attribute set. Corresponds to the return value of one of the calls + # to +option_key_method+. If +nil+, no selection is made. # # Example object structure for use with this method: # class Continent < ActiveRecord::Base @@ -292,8 +298,8 @@ module ActionView # a TimeZone. # # By default, +model+ is the TimeZone constant (which can be obtained - # in ActiveRecord as a value object). The only requirement is that the - # +model+ parameter be an object that responds to #all, and returns + # in Active Record as a value object). The only requirement is that the + # +model+ parameter be an object that responds to +all+, and returns # an array of objects that represent time zones. # # NOTE: Only the option tags are returned, you have to wrap this call in diff --git a/vendor/rails/actionpack/lib/action_view/helpers/form_tag_helper.rb b/vendor/rails/actionpack/lib/action_view/helpers/form_tag_helper.rb index 922a0662..ca58f4ba 100644 --- a/vendor/rails/actionpack/lib/action_view/helpers/form_tag_helper.rb +++ b/vendor/rails/actionpack/lib/action_view/helpers/form_tag_helper.rb @@ -3,7 +3,7 @@ require 'action_view/helpers/tag_helper' module ActionView module Helpers - # Provides a number of methods for creating form tags that doesn't rely on an ActiveRecord object assigned to the template like + # Provides a number of methods for creating form tags that doesn't rely on an Active Record object assigned to the template like # FormHelper does. Instead, you provide the names and values manually. # # NOTE: The HTML options disabled, readonly, and multiple can all be treated as booleans. So specifying @@ -14,9 +14,9 @@ module ActionView # # ==== Options # * :multipart - If set to true, the enctype is set to "multipart/form-data". - # * :method - The method to use when submitting the form, usually either "get" or "post". - # If "put", "delete", or another verb is used, a hidden input with name _method - # is added to simulate the verb over post. + # * :method - The method to use when submitting the form, usually either "get" or "post". + # If "put", "delete", or another verb is used, a hidden input with name _method + # is added to simulate the verb over post. # * A list of parameters to feed to the URL the form will be posted to. # # ==== Examples 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 1b12aa80..602832e4 100644 --- a/vendor/rails/actionpack/lib/action_view/helpers/prototype_helper.rb +++ b/vendor/rails/actionpack/lib/action_view/helpers/prototype_helper.rb @@ -458,7 +458,7 @@ module ActionView url_options = options[:url] url_options = url_options.merge(:escape => false) if url_options.is_a?(Hash) - function << "'#{url_for(url_options)}'" + function << "'#{escape_javascript(url_for(url_options))}'" function << ", #{javascript_options})" function = "#{options[:before]}; #{function}" if options[:before] @@ -595,8 +595,8 @@ module ActionView # JavaScript sent with a Content-type of "text/javascript". # # Create new instances with PrototypeHelper#update_page or with - # ActionController::Base#render, then call #insert_html, #replace_html, - # #remove, #show, #hide, #visual_effect, or any other of the built-in + # ActionController::Base#render, then call +insert_html+, +replace_html+, + # +remove+, +show+, +hide+, +visual_effect+, or any other of the built-in # methods on the yielded generator in any order you like to modify the # content and appearance of the current page. # @@ -687,7 +687,7 @@ module ActionView end end - # Returns an object whose #to_json evaluates to +code+. Use this to pass a literal JavaScript + # Returns an object whose to_json evaluates to +code+. Use this to pass a literal JavaScript # expression as an argument to another JavaScriptGenerator method. def literal(code) ActiveSupport::JSON::Variable.new(code.to_s) @@ -1068,7 +1068,7 @@ module ActionView def build_observer(klass, name, options = {}) if options[:with] && (options[:with] !~ /[\{=(.]/) - options[:with] = "'#{options[:with]}=' + value" + options[:with] = "'#{options[:with]}=' + encodeURIComponent(value)" else options[:with] ||= 'value' unless options[:function] end @@ -1173,7 +1173,7 @@ module ActionView super(generator) end - # The JSON Encoder calls this to check for the #to_json method + # The JSON Encoder calls this to check for the +to_json+ method # Since it's a blank slate object, I suppose it responds to anything. def respond_to?(method) true diff --git a/vendor/rails/actionpack/lib/action_view/helpers/record_tag_helper.rb b/vendor/rails/actionpack/lib/action_view/helpers/record_tag_helper.rb index 40b66be7..66c596f3 100644 --- a/vendor/rails/actionpack/lib/action_view/helpers/record_tag_helper.rb +++ b/vendor/rails/actionpack/lib/action_view/helpers/record_tag_helper.rb @@ -2,7 +2,7 @@ module ActionView module Helpers module RecordTagHelper # Produces a wrapper DIV element with id and class parameters that - # relate to the specified ActiveRecord object. Usage example: + # relate to the specified Active Record object. Usage example: # # <% div_for(@person, :class => "foo") do %> # <%=h @person.name %> @@ -17,7 +17,7 @@ module ActionView end # content_tag_for creates an HTML element with id and class parameters - # that relate to the specified ActiveRecord object. For example: + # that relate to the specified Active Record object. For example: # # <% content_tag_for(:tr, @person) do %> # <%=h @person.first_name %> diff --git a/vendor/rails/actionpack/lib/action_view/helpers/sanitize_helper.rb b/vendor/rails/actionpack/lib/action_view/helpers/sanitize_helper.rb index 6c0a7ec2..b0dacfe9 100644 --- a/vendor/rails/actionpack/lib/action_view/helpers/sanitize_helper.rb +++ b/vendor/rails/actionpack/lib/action_view/helpers/sanitize_helper.rb @@ -57,7 +57,7 @@ module ActionView self.class.white_list_sanitizer.sanitize(html, options) end - # Sanitizes a block of css code. Used by #sanitize when it comes across a style attribute + # Sanitizes a block of CSS code. Used by +sanitize+ when it comes across a style attribute. def sanitize_css(style) self.class.white_list_sanitizer.sanitize_css(style) end @@ -111,8 +111,8 @@ module ActionView end end - # Gets the HTML::FullSanitizer instance used by strip_tags. Replace with - # any object that responds to #sanitize + # Gets the HTML::FullSanitizer instance used by +strip_tags+. Replace with + # any object that responds to +sanitize+. # # Rails::Initializer.run do |config| # config.action_view.full_sanitizer = MySpecialSanitizer.new @@ -122,8 +122,8 @@ module ActionView @full_sanitizer ||= HTML::FullSanitizer.new end - # Gets the HTML::LinkSanitizer instance used by strip_links. Replace with - # any object that responds to #sanitize + # Gets the HTML::LinkSanitizer instance used by +strip_links+. Replace with + # any object that responds to +sanitize+. # # Rails::Initializer.run do |config| # config.action_view.link_sanitizer = MySpecialSanitizer.new @@ -133,8 +133,8 @@ module ActionView @link_sanitizer ||= HTML::LinkSanitizer.new end - # Gets the HTML::WhiteListSanitizer instance used by sanitize and sanitize_css. - # Replace with any object that responds to #sanitize + # Gets the HTML::WhiteListSanitizer instance used by sanitize and +sanitize_css+. + # Replace with any object that responds to +sanitize+. # # Rails::Initializer.run do |config| # config.action_view.white_list_sanitizer = MySpecialSanitizer.new @@ -144,7 +144,7 @@ module ActionView @white_list_sanitizer ||= HTML::WhiteListSanitizer.new end - # Adds valid HTML attributes that the #sanitize helper checks for URIs. + # Adds valid HTML attributes that the +sanitize+ helper checks for URIs. # # Rails::Initializer.run do |config| # config.action_view.sanitized_uri_attributes = 'lowsrc', 'target' @@ -154,7 +154,7 @@ module ActionView HTML::WhiteListSanitizer.uri_attributes.merge(attributes) end - # Adds to the Set of 'bad' tags for the #sanitize helper. + # Adds to the Set of 'bad' tags for the +sanitize+ helper. # # Rails::Initializer.run do |config| # config.action_view.sanitized_bad_tags = 'embed', 'object' @@ -163,7 +163,8 @@ module ActionView def sanitized_bad_tags=(attributes) HTML::WhiteListSanitizer.bad_tags.merge(attributes) end - # Adds to the Set of allowed tags for the #sanitize helper. + + # Adds to the Set of allowed tags for the +sanitize+ helper. # # Rails::Initializer.run do |config| # config.action_view.sanitized_allowed_tags = 'table', 'tr', 'td' @@ -173,7 +174,7 @@ module ActionView HTML::WhiteListSanitizer.allowed_tags.merge(attributes) end - # Adds to the Set of allowed html attributes for the #sanitize helper. + # Adds to the Set of allowed HTML attributes for the +sanitize+ helper. # # Rails::Initializer.run do |config| # config.action_view.sanitized_allowed_attributes = 'onclick', 'longdesc' @@ -183,7 +184,7 @@ module ActionView HTML::WhiteListSanitizer.allowed_attributes.merge(attributes) end - # Adds to the Set of allowed css properties for the #sanitize and #sanitize_css heleprs. + # Adds to the Set of allowed CSS properties for the #sanitize and +sanitize_css+ heleprs. # # Rails::Initializer.run do |config| # config.action_view.sanitized_allowed_css_properties = 'expression' @@ -193,7 +194,7 @@ module ActionView HTML::WhiteListSanitizer.allowed_css_properties.merge(attributes) end - # Adds to the Set of allowed css keywords for the #sanitize and #sanitize_css helpers. + # Adds to the Set of allowed CSS keywords for the +sanitize+ and +sanitize_css+ helpers. # # Rails::Initializer.run do |config| # config.action_view.sanitized_allowed_css_keywords = 'expression' @@ -203,7 +204,7 @@ module ActionView HTML::WhiteListSanitizer.allowed_css_keywords.merge(attributes) end - # Adds to the Set of allowed shorthand css properties for the #sanitize and #sanitize_css helpers. + # Adds to the Set of allowed shorthand CSS properties for the +sanitize+ and +sanitize_css+ helpers. # # Rails::Initializer.run do |config| # config.action_view.sanitized_shorthand_css_properties = 'expression' @@ -213,7 +214,7 @@ module ActionView HTML::WhiteListSanitizer.shorthand_css_properties.merge(attributes) end - # Adds to the Set of allowed protocols for the #sanitize helper. + # Adds to the Set of allowed protocols for the +sanitize+ helper. # # Rails::Initializer.run do |config| # config.action_view.sanitized_allowed_protocols = 'ssh', 'feed' diff --git a/vendor/rails/actionpack/lib/action_view/helpers/scriptaculous_helper.rb b/vendor/rails/actionpack/lib/action_view/helpers/scriptaculous_helper.rb index 12b4cfd3..c9b2761c 100644 --- a/vendor/rails/actionpack/lib/action_view/helpers/scriptaculous_helper.rb +++ b/vendor/rails/actionpack/lib/action_view/helpers/scriptaculous_helper.rb @@ -26,9 +26,9 @@ module ActionView # :url => { :action => "reload" }, # :complete => visual_effect(:highlight, "posts", :duration => 0.5) # - # If no element_id is given, it assumes "element" which should be a local + # If no +element_id+ is given, it assumes "element" which should be a local # variable in the generated JavaScript execution context. This can be - # used for example with drop_receiving_element: + # used for example with +drop_receiving_element+: # # <%= drop_receiving_element (...), :loading => visual_effect(:fade) %> # @@ -67,6 +67,7 @@ module ActionView # element as parameters. # # Example: + # # <%= sortable_element("my_list", :url => { :action => "order" }) %> # # In the example, the action gets a "my_list" array parameter @@ -79,60 +80,56 @@ module ActionView # # Additional +options+ are: # - # :format:: A regular expression to determine what to send - # as the serialized id to the server (the default - # is /^[^_]*_(.*)$/). - # - # :constraint:: Whether to constrain the dragging to either :horizontal - # or :vertical (or false to make it unconstrained). - # - # :overlap:: Calculate the item overlap in the :horizontal or - # :vertical direction. - # - # :tag:: Which children of the container element to treat as - # sortable (default is li). - # - # :containment:: Takes an element or array of elements to treat as - # potential drop targets (defaults to the original - # target element). - # - # :only:: A CSS class name or arry of class names used to filter - # out child elements as candidates. - # - # :scroll:: Determines whether to scroll the list during drag - # operations if the list runs past the visual border. - # - # :tree:: Determines whether to treat nested lists as part of the - # main sortable list. This means that you can create multi- - # layer lists, and not only sort items at the same level, - # but drag and sort items between levels. - # - # :hoverclass:: If set, the Droppable will have this additional CSS class - # when an accepted Draggable is hovered over it. - # - # :handle:: Sets whether the element should only be draggable by an - # embedded handle. The value may be a string referencing a - # CSS class value (as of script.aculo.us V1.5). The first - # child/grandchild/etc. element found within the element - # that has this CSS class value will be used as the handle. - # - # :ghosting:: Clones the element and drags the clone, leaving the original - # in place until the clone is dropped (default is false). - # - # :dropOnEmpty:: If set to true, the Sortable container will be made into - # a Droppable, that can receive a Draggable (as according to - # the containment rules) as a child element when there are no - # more elements inside (default is false). - # - # :onChange:: Called whenever the sort order changes while dragging. When - # dragging from one Sortable to another, the callback is - # called once on each Sortable. Gets the affected element as - # its parameter. - # - # :onUpdate:: Called when the drag ends and the Sortable's order is - # changed in any way. When dragging from one Sortable to - # another, the callback is called once on each Sortable. Gets - # the container as its parameter. + # * :format - A regular expression to determine what to send as the + # serialized id to the server (the default is /^[^_]*_(.*)$/). + # + # * :constraint - Whether to constrain the dragging to either + # :horizontal or :vertical (or false to make it unconstrained). + # + # * :overlap - Calculate the item overlap in the :horizontal + # or :vertical direction. + # + # * :tag - Which children of the container element to treat as + # sortable (default is li). + # + # * :containment - Takes an element or array of elements to treat as + # potential drop targets (defaults to the original target element). + # + # * :only - A CSS class name or arry of class names used to filter + # out child elements as candidates. + # + # * :scroll - Determines whether to scroll the list during drag + # operations if the list runs past the visual border. + # + # * :tree - Determines whether to treat nested lists as part of the + # main sortable list. This means that you can create multi-layer lists, + # and not only sort items at the same level, but drag and sort items + # between levels. + # + # * :hoverclass - If set, the Droppable will have this additional CSS class + # when an accepted Draggable is hovered over it. + # + # * :handle - Sets whether the element should only be draggable by an + # embedded handle. The value may be a string referencing a CSS class value + # (as of script.aculo.us V1.5). The first child/grandchild/etc. element + # found within the element that has this CSS class value will be used as + # the handle. + # + # * :ghosting - Clones the element and drags the clone, leaving + # the original in place until the clone is dropped (default is false). + # + # * :dropOnEmpty - If true the Sortable container will be made into + # a Droppable, that can receive a Draggable (as according to the containment + # rules) as a child element when there are no more elements inside (default + # is false). + # + # * :onChange - Called whenever the sort order changes while dragging. When + # dragging from one Sortable to another, the callback is called once on each + # Sortable. Gets the affected element as its parameter. + # + # * :onUpdate - Called when the drag ends and the Sortable's order is + # changed in any way. When dragging from one Sortable to another, the callback + # is called once on each Sortable. Gets the container as its parameter. # # See http://script.aculo.us for more documentation. def sortable_element(element_id, options = {}) @@ -170,8 +167,8 @@ module ActionView end # Makes the element with the DOM ID specified by +element_id+ receive - # dropped draggable elements (created by draggable_element). - # and make an AJAX call By default, the action called gets the DOM ID + # dropped draggable elements (created by +draggable_element+). + # and make an AJAX call. By default, the action called gets the DOM ID # of the element as parameter. # # Example: @@ -182,32 +179,30 @@ module ActionView # http://script.aculo.us for more documentation. # # Some of these +options+ include: - # :accept:: Set this to a string or an array of strings describing the - # allowable CSS classes that the draggable_element must have in order - # to be accepted by this drop_receiving_element. - # - # :confirm:: Adds a confirmation dialog. - # - # Example: - # :confirm => "Are you sure you want to do this?" - # - # :hoverclass:: If set, the drop_receiving_element will have this additional CSS class - # when an accepted draggable_element is hovered over it. - # - # :onDrop:: Called when a draggable_element is dropped onto this element. - # Override this callback with a javascript expression to - # change the default drop behavour. - # - # Example: - # :onDrop => "function(draggable_element, droppable_element, event) { alert('I like bananas') }" + # * :accept - Set this to a string or an array of strings describing the + # allowable CSS classes that the +draggable_element+ must have in order + # to be accepted by this +drop_receiving_element+. # - # This callback gets three parameters: - # The +Draggable+ element, the +Droppable+ element and the - # +Event+ object. You can extract additional information about the - # drop - like if the Ctrl or Shift keys were pressed - from the +Event+ object. - # - # :with:: A JavaScript expression specifying the parameters for the XMLHttpRequest. - # Any expressions should return a valid URL query string. + # * :confirm - Adds a confirmation dialog. Example: + # + # :confirm => "Are you sure you want to do this?" + # + # * :hoverclass - If set, the +drop_receiving_element+ will have + # this additional CSS class when an accepted +draggable_element+ is + # hovered over it. + # + # * :onDrop - Called when a +draggable_element+ is dropped onto + # this element. Override this callback with a JavaScript expression to + # change the default drop behavour. Example: + # + # :onDrop => "function(draggable_element, droppable_element, event) { alert('I like bananas') }" + # + # This callback gets three parameters: The Draggable element, the Droppable + # element and the Event object. You can extract additional information about + # the drop - like if the Ctrl or Shift keys were pressed - from the Event object. + # + # * :with - A JavaScript expression specifying the parameters for + # the XMLHttpRequest. Any expressions should return a valid URL query string. def drop_receiving_element(element_id, options = {}) javascript_tag(drop_receiving_element_js(element_id, options).chop!) end diff --git a/vendor/rails/actionpack/lib/action_view/helpers/text_helper.rb b/vendor/rails/actionpack/lib/action_view/helpers/text_helper.rb index f8c3b674..669a2854 100644 --- a/vendor/rails/actionpack/lib/action_view/helpers/text_helper.rb +++ b/vendor/rails/actionpack/lib/action_view/helpers/text_helper.rb @@ -3,19 +3,19 @@ require 'html/document' module ActionView module Helpers #:nodoc: - # The TextHelper module provides a set of methods for filtering, formatting - # and transforming strings, which can reduce the amount of inline Ruby code in - # your views. These helper methods extend ActionView making them callable + # The TextHelper module provides a set of methods for filtering, formatting + # and transforming strings, which can reduce the amount of inline Ruby code in + # your views. These helper methods extend ActionView making them callable # within your template files. - module TextHelper - # The preferred method of outputting text in your views is to use the - # <%= "text" %> eRuby syntax. The regular _puts_ and _print_ methods - # do not operate as expected in an eRuby code block. If you absolutely must + module TextHelper + # The preferred method of outputting text in your views is to use the + # <%= "text" %> eRuby syntax. The regular _puts_ and _print_ methods + # do not operate as expected in an eRuby code block. If you absolutely must # output text within a non-output code block (i.e., <% %>), you can use the concat method. # # ==== Examples - # <% - # concat "hello", binding + # <% + # concat "hello", binding # # is the equivalent of <%= "hello" %> # # if (logged_in == true): @@ -30,15 +30,15 @@ module ActionView end if RUBY_VERSION < '1.9' - # If +text+ is longer than +length+, +text+ will be truncated to the length of + # If +text+ is longer than +length+, +text+ will be truncated to the length of # +length+ (defaults to 30) and the last characters will be replaced with the +truncate_string+ # (defaults to "..."). # # ==== Examples - # truncate("Once upon a time in a world far far away", 14) + # truncate("Once upon a time in a world far far away", 14) # # => Once upon a... # - # truncate("Once upon a time in a world far far away") + # truncate("Once upon a time in a world far far away") # # => Once upon a time in a world f... # # truncate("And they found that many people were sleeping better.", 25, "(clipped)") @@ -63,20 +63,20 @@ module ActionView end # Highlights one or more +phrases+ everywhere in +text+ by inserting it into - # a +highlighter+ string. The highlighter can be specialized by passing +highlighter+ + # a +highlighter+ string. The highlighter can be specialized by passing +highlighter+ # as a single-quoted string with \1 where the phrase is to be inserted (defaults to # '\1') # # ==== Examples - # highlight('You searched for: rails', 'rails') + # highlight('You searched for: rails', 'rails') # # => You searched for: rails # # highlight('You searched for: ruby, rails, dhh', 'actionpack') - # # => You searched for: ruby, rails, dhh + # # => You searched for: ruby, rails, dhh # - # highlight('You searched for: rails', ['for', 'rails'], '\1') + # highlight('You searched for: rails', ['for', 'rails'], '\1') # # => You searched for: rails - # + # # highlight('You searched for: rails', 'rails', "\1") # # => You searched for: \1') @@ -89,23 +89,23 @@ module ActionView end if RUBY_VERSION < '1.9' - # Extracts an excerpt from +text+ that matches the first instance of +phrase+. + # Extracts an excerpt from +text+ that matches the first instance of +phrase+. # The +radius+ expands the excerpt on each side of the first occurrence of +phrase+ by the number of characters # defined in +radius+ (which defaults to 100). If the excerpt radius overflows the beginning or end of the +text+, # then the +excerpt_string+ will be prepended/appended accordingly. The resulting string will be stripped in any case. # If the +phrase+ isn't found, nil is returned. # # ==== Examples - # excerpt('This is an example', 'an', 5) + # excerpt('This is an example', 'an', 5) # # => "...s is an exam..." # - # excerpt('This is an example', 'is', 5) + # excerpt('This is an example', 'is', 5) # # => "This is a..." # - # excerpt('This is an example', 'is') + # excerpt('This is an example', 'is') # # => "This is an example" # - # excerpt('This next thing is an example', 'ex', 2) + # excerpt('This next thing is an example', 'ex', 2) # # => "...next..." # # excerpt('This is also an example', 'an', 8, ' ') @@ -147,33 +147,24 @@ module ActionView end end - # Attempts to pluralize the +singular+ word unless +count+ is 1. If +plural+ - # is supplied, it will use that when count is > 1, if the ActiveSupport Inflector - # is loaded, it will use the Inflector to determine the plural form, otherwise - # it will just add an 's' to the +singular+ word. + # Attempts to pluralize the +singular+ word unless +count+ is 1. If + # +plural+ is supplied, it will use that when count is > 1, otherwise + # it will use the Inflector to determine the plural form # # ==== Examples - # pluralize(1, 'person') + # pluralize(1, 'person') # # => 1 person # - # pluralize(2, 'person') + # pluralize(2, 'person') # # => 2 people # - # pluralize(3, 'person', 'users') + # pluralize(3, 'person', 'users') # # => 3 users # # pluralize(0, 'person') # # => 0 people def pluralize(count, singular, plural = nil) - "#{count || 0} " + if count == 1 || count == '1' - singular - elsif plural - plural - elsif Object.const_defined?("Inflector") - Inflector.pluralize(singular) - else - singular + "s" - end + "#{count || 0} " + ((count == 1 || count == '1') ? singular : (plural || singular.pluralize)) end # Wraps the +text+ into lines no longer than +line_width+ width. This method @@ -229,7 +220,7 @@ module ActionView end end - # Returns the text with all the Textile codes turned into HTML tags, + # Returns the text with all the Textile codes turned into HTML tags, # but without the bounding

tag that RedCloth adds. # # You can learn more about Textile's syntax at its website[http://www.textism.com/tools/textile]. @@ -273,25 +264,25 @@ module ActionView # # => "

We like to write code, not just read it!

" # # markdown("The [Markdown website](http://daringfireball.net/projects/markdown/) has more information.") - # # => "

The Markdown website + # # => "

The Markdown website # # has more information.

" # # markdown('![The ROR logo](http://rubyonrails.com/images/rails.png "Ruby on Rails")') - # # => '

The ROR logo

' + # # => '

The ROR logo

' def markdown(text) text.blank? ? "" : BlueCloth.new(text).to_html end rescue LoadError # We can't really help what's not there end - + # Returns +text+ transformed into HTML using simple formatting rules. - # Two or more consecutive newlines(\n\n) are considered as a + # Two or more consecutive newlines(\n\n) are considered as a # paragraph and wrapped in

tags. One newline (\n) is # considered as a linebreak and a
tag is appended. This - # method does not remove the newlines from the +text+. + # method does not remove the newlines from the +text+. # - # You can pass any HTML attributes into html_options. These + # You can pass any HTML attributes into html_options. These # will be added to all created paragraphs. # ==== Examples # my_text = "Here is some basic text...\n...with a line break." @@ -316,19 +307,19 @@ module ActionView text << "

" end - # Turns all URLs and e-mail addresses into clickable links. The +link+ parameter + # Turns all URLs and e-mail addresses into clickable links. The +link+ parameter # will limit what should be linked. You can add HTML attributes to the links using - # +href_options+. Options for +link+ are :all (default), - # :email_addresses, and :urls. If a block is given, each URL and + # +href_options+. Options for +link+ are :all (default), + # :email_addresses, and :urls. If a block is given, each URL and # e-mail address is yielded and the result is used as the link text. # # ==== Examples - # auto_link("Go to http://www.rubyonrails.org and say hello to david@loudthinking.com") + # auto_link("Go to http://www.rubyonrails.org and say hello to david@loudthinking.com") # # => "Go to http://www.rubyonrails.org and # # say hello to david@loudthinking.com" # # auto_link("Visit http://www.loudthinking.com/ or e-mail david@loudthinking.com", :urls) - # # => "Visit http://www.loudthinking.com/ + # # => "Visit http://www.loudthinking.com/ # # or e-mail david@loudthinking.com" # # auto_link("Visit http://www.loudthinking.com/ or e-mail david@loudthinking.com", :email_addresses) @@ -338,9 +329,9 @@ module ActionView # auto_link(post_body, :all, :target => '_blank') do |text| # truncate(text, 15) # end - # # => "Welcome to my new blog at http://www.m.... + # # => "Welcome to my new blog at http://www.m.... # Please e-mail me at me@email.com." - # + # def auto_link(text, link = :all, href_options = {}, &block) return '' if text.blank? case link @@ -349,15 +340,15 @@ module ActionView when :urls then auto_link_urls(text, href_options, &block) end end - + # Creates a Cycle object whose _to_s_ method cycles through elements of an - # array every time it is called. This can be used for example, to alternate - # classes for table rows. You can use named cycles to allow nesting in loops. - # Passing a Hash as the last parameter with a :name key will create a - # named cycle. You can manually reset a cycle by calling reset_cycle and passing the + # array every time it is called. This can be used for example, to alternate + # classes for table rows. You can use named cycles to allow nesting in loops. + # Passing a Hash as the last parameter with a :name key will create a + # named cycle. You can manually reset a cycle by calling reset_cycle and passing the # name of the cycle. # - # ==== Examples + # ==== Examples # # Alternate CSS classes for even and odd numbers... # @items = [1,2,3,4] # @@ -370,8 +361,8 @@ module ActionView # # # # Cycle CSS classes for rows, and text colors for values within each row - # @items = x = [{:first => 'Robert', :middle => 'Daniel', :last => 'James'}, - # {:first => 'Emily', :middle => 'Shannon', :maiden => 'Pike', :last => 'Hicks'}, + # @items = x = [{:first => 'Robert', :middle => 'Daniel', :last => 'James'}, + # {:first => 'Emily', :middle => 'Shannon', :maiden => 'Pike', :last => 'Hicks'}, # {:first => 'June', :middle => 'Dae', :last => 'Jones'}] # <% @items.each do |item| %> # "row_class") -%>"> @@ -401,8 +392,8 @@ module ActionView end return cycle.to_s end - - # Resets a cycle so that it starts from the first element the next time + + # Resets a cycle so that it starts from the first element the next time # it is called. Pass in +name+ to reset a named cycle. # # ==== Example @@ -428,12 +419,12 @@ module ActionView class Cycle #:nodoc: attr_reader :values - + def initialize(first_value, *values) @values = values.unshift(first_value) reset end - + def reset @index = 0 end @@ -453,7 +444,7 @@ module ActionView @_cycles = Hash.new unless defined?(@_cycles) return @_cycles[name] end - + def set_cycle(name, cycle_object) @_cycles = Hash.new unless defined?(@_cycles) @_cycles[name] = cycle_object @@ -462,22 +453,22 @@ module ActionView AUTO_LINK_RE = %r{ ( # leading text <\w+.*?>| # leading HTML tag, or - [^=!:'"/]| # leading punctuation, or + [^=!:'"/]| # leading punctuation, or ^ # beginning of line ) ( (?:https?://)| # protocol spec, or (?:www\.) # www.* - ) + ) ( [-\w]+ # subdomain or domain (?:\.[-\w]+)* # remaining subdomains or domain (?::\d+)? # port - (?:/(?:(?:[~\w\+@%=-]|(?:[,.;:][^\s$]))+)?)* # path + (?:/(?:(?:[~\w\+@%=\(\)-]|(?:[,.;:][^\s$]))+)?)* # path (?:\?[\w\+@%&=.;-]+)? # query string (?:\#[\w\-]*)? # trailing anchor ) - ([[:punct:]]|\s|<|$) # trailing text + ([[:punct:]]|<|$|) # trailing text }x unless const_defined?(:AUTO_LINK_RE) # Turns all urls into clickable links. If a block is given, each url @@ -502,7 +493,7 @@ module ActionView body = text.dup text.gsub(/([\w\.!#\$%\-+.]+@[A-Za-z0-9\-]+(\.[A-Za-z0-9\-]+)+)/) do text = $1 - + if body.match(/]*>(.*)(#{Regexp.escape(text)})(.*)<\/a>/) text else diff --git a/vendor/rails/actionpack/lib/action_view/helpers/url_helper.rb b/vendor/rails/actionpack/lib/action_view/helpers/url_helper.rb index 375ebfcd..4b12adf2 100644 --- a/vendor/rails/actionpack/lib/action_view/helpers/url_helper.rb +++ b/vendor/rails/actionpack/lib/action_view/helpers/url_helper.rb @@ -10,7 +10,7 @@ module ActionView include JavaScriptHelper # Returns the URL for the set of +options+ provided. This takes the - # same options as url_for in ActionController (see the + # same options as +url_for+ in Action Controller (see the # documentation for ActionController::Base#url_for). Note that by default # :only_path is true so you'll get the relative /controller/action # instead of the fully qualified URL like http://example.com/controller/action. @@ -120,17 +120,72 @@ module ActionView # exception. # # ==== Examples + # Because it relies on +url_for+, +link_to+ supports both older-style controller/action/id arguments + # and newer RESTful routes. Current Rails style favors RESTful routes whenever possible, so base + # your application on resources and use + # + # link_to "Profile", profile_path(@profile) + # # => Profile + # + # or the even pithier + # + # link_to "Profile", @profile + # # => Profile + # + # in place of the older more verbose, non-resource-oriented + # + # link_to "Profile", :controller => "profiles", :action => "show", :id => @profile + # # => Profile + # + # Similarly, + # + # link_to "Profiles", profiles_path + # # => Profiles + # + # is better than + # + # link_to "Profiles", :controller => "profiles" + # # => Profiles + # + # Classes and ids for CSS are easy to produce: + # + # link_to "Articles", articles_path, :id => "news", :class => "article" + # # => Articles + # + # Be careful when using the older argument style, as an extra literal hash is needed: + # + # link_to "Articles", { :controller => "articles" }, :id => "news", :class => "article" + # # => Articles + # + # Leaving the hash off gives the wrong link: + # + # link_to "WRONG!", :controller => "articles", :id => "news", :class => "article" + # # => WRONG! + # + # +link_to+ can also produce links with anchors or query strings: + # + # link_to "Comment wall", profile_path(@profile, :anchor => "wall") + # # => Comment wall + # + # link_to "Ruby on Rails search", :controller => "searches", :query => "ruby on rails" + # # => Ruby on Rails search + # + # link_to "Nonsense search", searches_path(:foo => "bar", :baz => "quux") + # # => Nonsense search + # + # The three options specfic to +link_to+ (:confirm, :popup, and :method) are used as follows: + # # link_to "Visit Other Site", "http://www.rubyonrails.org/", :confirm => "Are you sure?" # # => Visit Other Site # # link_to "Help", { :action => "help" }, :popup => true # # => Help # - # link_to "View Image", { :action => "view" }, :popup => ['new_window_name', 'height=300,width=600'] - # # => View Image + # link_to "View Image", @image, :popup => ['new_window_name', 'height=300,width=600'] + # # => View Image # - # link_to "Delete Image", { :action => "delete", :id => @image.id }, :confirm => "Are you sure?", :method => :delete - # # => "Are you sure?", :method => :delete + # # => Delete Image diff --git a/vendor/rails/actionpack/lib/action_view/template.rb b/vendor/rails/actionpack/lib/action_view/template.rb index 2cda3d94..36952618 100644 --- a/vendor/rails/actionpack/lib/action_view/template.rb +++ b/vendor/rails/actionpack/lib/action_view/template.rb @@ -93,9 +93,9 @@ module ActionView #:nodoc: # Register a class that knows how to handle template files with the given # extension. This can be used to implement new template types. # The constructor for the class must take the ActiveView::Base instance - # as a parameter, and the class must implement a #render method that + # as a parameter, and the class must implement a +render+ method that # takes the contents of the template to render as well as the Hash of - # local assigns available to the template. The #render method ought to + # local assigns available to the template. The +render+ method ought to # return the rendered template as a string. def self.register_template_handler(extension, klass) @@template_handlers[extension.to_sym] = klass diff --git a/vendor/rails/actionpack/lib/action_view/test_case.rb b/vendor/rails/actionpack/lib/action_view/test_case.rb index b2e6589d..16fedd97 100644 --- a/vendor/rails/actionpack/lib/action_view/test_case.rb +++ b/vendor/rails/actionpack/lib/action_view/test_case.rb @@ -1,14 +1,6 @@ require 'active_support/test_case' module ActionView - class NonInferrableHelperError < ActionViewError - def initialize(name) - super "Unable to determine the helper to test from #{name}. " + - "You'll need to specify it using tests YourHelper in your " + - "test case definition" - end - end - class TestCase < ActiveSupport::TestCase class_inheritable_accessor :helper_class @@helper_class = nil @@ -29,7 +21,7 @@ module ActionView def determine_default_helper_class(name) name.sub(/Test$/, '').constantize rescue NameError - raise NonInferrableHelperError.new(name) + nil end end @@ -42,7 +34,9 @@ module ActionView setup :setup_with_helper_class def setup_with_helper_class - self.class.send(:include, helper_class) + if helper_class && !self.class.ancestors.include?(helper_class) + self.class.send(:include, helper_class) + end end class TestController < ActionController::Base 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 1db05758..f152b1d1 100644 --- a/vendor/rails/actionpack/test/controller/action_pack_assertions_test.rb +++ b/vendor/rails/actionpack/test/controller/action_pack_assertions_test.rb @@ -131,6 +131,10 @@ class AssertResponseWithUnexpectedErrorController < ActionController::Base def index raise 'FAIL' end + + def show + render :text => "Boom", :status => 500 + end end module Admin @@ -483,6 +487,16 @@ class ActionPackAssertionsControllerTest < Test::Unit::TestCase rescue Test::Unit::AssertionFailedError => e assert e.message.include?('FAIL') end + + def test_assert_response_failure_response_with_no_exception + @controller = AssertResponseWithUnexpectedErrorController.new + get :show + assert_response :success + flunk 'Expected non-success response' + rescue Test::Unit::AssertionFailedError + rescue + flunk "assert_response failed to handle failure response with missing, but optional, exception." + end end class ActionPackHeaderTest < Test::Unit::TestCase diff --git a/vendor/rails/actionpack/test/controller/caching_test.rb b/vendor/rails/actionpack/test/controller/caching_test.rb index ddc1c683..f9b6b87b 100644 --- a/vendor/rails/actionpack/test/controller/caching_test.rb +++ b/vendor/rails/actionpack/test/controller/caching_test.rb @@ -6,6 +6,7 @@ CACHE_DIR = 'test_cache' FILE_STORE_PATH = File.join(File.dirname(__FILE__), '/../temp/', CACHE_DIR) ActionController::Base.page_cache_directory = FILE_STORE_PATH ActionController::Base.cache_store = :file_store, FILE_STORE_PATH +ActionController::Base.view_paths = [ File.dirname(__FILE__) + '/../fixtures/' ] class PageCachingTestController < ActionController::Base caches_page :ok, :no_content, :if => Proc.new { |c| !c.request.format.json? } @@ -128,7 +129,7 @@ class PageCachingTest < Test::Unit::TestCase end end end - + def test_page_caching_conditional_options @request.env['HTTP_ACCEPT'] = 'application/json' get :ok @@ -151,12 +152,15 @@ end class ActionCachingTestController < ActionController::Base - caches_action :index, :redirected, :forbidden + caches_action :index, :redirected, :forbidden, :if => Proc.new { |c| !c.request.format.json? } caches_action :show, :cache_path => 'http://test.host/custom/show' caches_action :edit, :cache_path => Proc.new { |c| c.params[:id] ? "http://test.host/#{c.params[:id]};edit" : "http://test.host/edit" } + caches_action :with_layout + + layout 'talk_from_action.erb' def index - @cache_this = Time.now.to_f.to_s + @cache_this = MockTime.now.to_f.to_s render :text => @cache_this end @@ -169,14 +173,26 @@ class ActionCachingTestController < ActionController::Base headers["Status"] = "403 Forbidden" end + def with_layout + @cache_this = MockTime.now.to_f.to_s + render :text => @cache_this, :layout => true + end + alias_method :show, :index alias_method :edit, :index + alias_method :destroy, :index def expire expire_action :controller => 'action_caching_test', :action => 'index' render :nothing => true end +end +class MockTime < Time + # Let Time spicy to assure that Time.now != Time.now + def to_f + super+rand + end end class ActionCachingMockController @@ -216,18 +232,48 @@ class ActionCacheTest < Test::Unit::TestCase get :index cached_time = content_to_cache assert_equal cached_time, @response.body - assert_cache_exists 'hostname.com/action_caching_test' + assert fragment_exist?('hostname.com/action_caching_test') reset! get :index assert_equal cached_time, @response.body end + def test_simple_action_not_cached + get :destroy + cached_time = content_to_cache + assert_equal cached_time, @response.body + assert !fragment_exist?('hostname.com/action_caching_test/destroy') + reset! + + get :destroy + assert_not_equal cached_time, @response.body + end + + def test_action_cache_with_layout + get :with_layout + cached_time = content_to_cache + assert_not_equal cached_time, @response.body + assert fragment_exist?('hostname.com/action_caching_test/with_layout') + reset! + + get :with_layout + assert_not_equal cached_time, @response.body + + assert_equal @response.body, read_fragment('hostname.com/action_caching_test/with_layout') + end + + def test_action_cache_conditional_options + @request.env['HTTP_ACCEPT'] = 'application/json' + get :index + assert !fragment_exist?('hostname.com/action_caching_test') + end + def test_action_cache_with_custom_cache_path get :show cached_time = content_to_cache assert_equal cached_time, @response.body - assert_cache_exists 'test.host/custom/show' + assert fragment_exist?('test.host/custom/show') reset! get :show @@ -236,11 +282,11 @@ class ActionCacheTest < Test::Unit::TestCase def test_action_cache_with_custom_cache_path_in_block get :edit - assert_cache_exists 'test.host/edit' + assert fragment_exist?('test.host/edit') reset! get :edit, :id => 1 - assert_cache_exists 'test.host/1;edit' + assert fragment_exist?('test.host/1;edit') end def test_cache_expiration @@ -349,9 +395,12 @@ class ActionCacheTest < Test::Unit::TestCase @request.host = 'hostname.com' end - def assert_cache_exists(path) - full_path = File.join(FILE_STORE_PATH, "views", path + '.cache') - assert File.exist?(full_path), "#{full_path.inspect} does not exist." + def fragment_exist?(path) + @controller.fragment_exist?(path) + end + + def read_fragment(path) + @controller.read_fragment(path) end end @@ -391,6 +440,19 @@ class FragmentCachingTest < Test::Unit::TestCase assert_nil @controller.read_fragment('name') end + def test_fragment_exist__with_caching_enabled + @store.write('views/name', 'value') + assert @controller.fragment_exist?('name') + assert !@controller.fragment_exist?('other_name') + end + + def test_fragment_exist__with_caching_disabled + ActionController::Base.perform_caching = false + @store.write('views/name', 'value') + assert !@controller.fragment_exist?('name') + assert !@controller.fragment_exist?('other_name') + end + def test_write_fragment__with_caching_enabled assert_nil @store.read('views/name') assert_equal 'value', @controller.write_fragment('name', 'value') @@ -435,7 +497,6 @@ class FragmentCachingTest < Test::Unit::TestCase assert_equal 'generated till now -> ', buffer end - def test_fragment_for @store.write('views/expensive', 'fragment content') fragment_computed = false @@ -516,7 +577,7 @@ class FunctionalFragmentCachingTest < Test::Unit::TestCase def setup ActionController::Base.perform_caching = true @store = ActiveSupport::Cache::MemoryStore.new - ActionController::Base.cache_store = @store + ActionController::Base.cache_store = @store @controller = FunctionalCachingController.new @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new @@ -529,17 +590,17 @@ Hello This bit's fragment cached CACHED assert_equal expected_body, @response.body - + assert_equal "This bit's fragment cached", @store.read('views/test.host/functional_caching/fragment_cached') end - + def test_fragment_caching_in_partials get :html_fragment_cached_with_partial assert_response :success assert_match /Fragment caching in a partial/, @response.body assert_match "Fragment caching in a partial", @store.read('views/test.host/functional_caching/html_fragment_cached_with_partial') end - + def test_fragment_caching_in_rjs_partials xhr :get, :js_fragment_cached_with_partial assert_response :success @@ -547,8 +608,3 @@ CACHED assert_match "Fragment caching in a partial", @store.read('views/test.host/functional_caching/js_fragment_cached_with_partial') end end - - - - - diff --git a/vendor/rails/actionpack/test/controller/cookie_test.rb b/vendor/rails/actionpack/test/controller/cookie_test.rb index 42f3bd26..b45fbb17 100644 --- a/vendor/rails/actionpack/test/controller/cookie_test.rb +++ b/vendor/rails/actionpack/test/controller/cookie_test.rb @@ -82,6 +82,7 @@ class CookieTest < Test::Unit::TestCase def test_expiring_cookie get :logout assert_equal [ CGI::Cookie::new("name" => "user_name", "value" => "", "expires" => Time.at(0)) ], @response.headers["cookie"] + assert_equal CGI::Cookie::new("name" => "user_name", "value" => "", "expires" => Time.at(0)).value, [] end def test_cookiejar_accessor @@ -137,4 +138,9 @@ class CookieTest < Test::Unit::TestCase cookies = CGI::Cookie.parse('return_to=http://rubyonrails.org/search?term=api&scope=all&global=true') assert_equal({"return_to" => ["http://rubyonrails.org/search?term=api&scope=all&global=true"]}, cookies) end + + def test_cookies_should_not_be_split_on_values_with_newlines + cookies = CGI::Cookie.new("name" => "val", "value" => "this\nis\na\ntest") + assert cookies.size == 1 + 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 11adacb5..c4de1018 100644 --- a/vendor/rails/actionpack/test/controller/filter_params_test.rb +++ b/vendor/rails/actionpack/test/controller/filter_params_test.rb @@ -7,14 +7,14 @@ class FilterParamTest < Test::Unit::TestCase def setup @controller = FilterParamController.new end - + def test_filter_parameters assert FilterParamController.respond_to?(:filter_parameter_logging) assert !@controller.respond_to?(:filter_parameters) - + FilterParamController.filter_parameter_logging assert @controller.respond_to?(:filter_parameters) - + test_hashes = [[{},{},[]], [{'foo'=>nil},{'foo'=>nil},[]], [{'foo'=>'bar'},{'foo'=>'bar'},[]], @@ -24,11 +24,11 @@ class FilterParamTest < Test::Unit::TestCase [{'foo'=>'bar', 'baz'=>'foo'},{'foo'=>'[FILTERED]', 'baz'=>'[FILTERED]'},%w'foo baz'], [{'bar'=>{'foo'=>'bar','bar'=>'foo'}},{'bar'=>{'foo'=>'[FILTERED]','bar'=>'foo'}},%w'fo'], [{'foo'=>{'foo'=>'bar','bar'=>'foo'}},{'foo'=>'[FILTERED]'},%w'f banana']] - + test_hashes.each do |before_filter, after_filter, filter_words| FilterParamController.filter_parameter_logging(*filter_words) - assert_equal after_filter, @controller.filter_parameters(before_filter) - + assert_equal after_filter, @controller.send!(:filter_parameters, before_filter) + filter_words.push('blah') FilterParamController.filter_parameter_logging(*filter_words) do |key, value| value.reverse! if key =~ /bargain/ @@ -37,7 +37,13 @@ class FilterParamTest < Test::Unit::TestCase before_filter['barg'] = {'bargain'=>'gain', 'blah'=>'bar', 'bar'=>{'bargain'=>{'blah'=>'foo'}}} after_filter['barg'] = {'bargain'=>'niag', 'blah'=>'[FILTERED]', 'bar'=>{'bargain'=>{'blah'=>'[FILTERED]'}}} - assert_equal after_filter, @controller.filter_parameters(before_filter) + assert_equal after_filter, @controller.send!(:filter_parameters, before_filter) end end + + def test_filter_parameters_is_protected + FilterParamController.filter_parameter_logging(:foo) + assert !FilterParamController.action_methods.include?('filter_parameters') + assert_raise(NoMethodError) { @controller.filter_parameters([{'password' => '[FILTERED]'}]) } + end end diff --git a/vendor/rails/actionpack/test/controller/helper_test.rb b/vendor/rails/actionpack/test/controller/helper_test.rb index 6dc77a4a..83e3b085 100644 --- a/vendor/rails/actionpack/test/controller/helper_test.rb +++ b/vendor/rails/actionpack/test/controller/helper_test.rb @@ -85,7 +85,7 @@ class HelperTest < Test::Unit::TestCase def test_helper_block_include assert_equal expected_helper_methods, missing_methods assert_nothing_raised { - @controller_class.helper { include TestHelper } + @controller_class.helper { include HelperTest::TestHelper } } assert [], missing_methods end diff --git a/vendor/rails/actionpack/test/controller/mime_type_test.rb b/vendor/rails/actionpack/test/controller/mime_type_test.rb index 03b0f8ba..f16a3c68 100644 --- a/vendor/rails/actionpack/test/controller/mime_type_test.rb +++ b/vendor/rails/actionpack/test/controller/mime_type_test.rb @@ -52,16 +52,33 @@ class MimeTypeTest < Test::Unit::TestCase end def test_type_convenience_methods - types = [:html, :xml, :png, :pdf, :yaml, :url_encoded_form] + # Don't test Mime::ALL, since it Mime::ALL#html? == true + types = Mime::SET.to_a.map(&:to_sym).uniq - [:all] + + # Remove custom Mime::Type instances set in other tests, like Mime::GIF and Mime::IPHONE + types.delete_if { |type| !Mime.const_defined?(type.to_s.upcase) } + types.each do |type| mime = Mime.const_get(type.to_s.upcase) - assert mime.send("#{type}?"), "Mime::#{type.to_s.upcase} is not #{type}?" - (types - [type]).each { |t| assert !mime.send("#{t}?"), "Mime::#{t.to_s.upcase} is #{t}?" } + assert mime.send("#{type}?"), "#{mime.inspect} is not #{type}?" + (types - [type]).each { |other_type| assert !mime.send("#{other_type}?"), "#{mime.inspect} is #{other_type}?" } end end - + def test_mime_all_is_html assert Mime::ALL.all?, "Mime::ALL is not all?" assert Mime::ALL.html?, "Mime::ALL is not html?" end + + def test_verifiable_mime_types + unverified_types = Mime::Type.unverifiable_types + all_types = Mime::SET.to_a.map(&:to_sym) + all_types.uniq! + # Remove custom Mime::Type instances set in other tests, like Mime::GIF and Mime::IPHONE + all_types.delete_if { |type| !Mime.const_defined?(type.to_s.upcase) } + + unverified, verified = all_types.partition { |type| Mime::Type.unverifiable_types.include? type } + assert verified.all? { |type| Mime.const_get(type.to_s.upcase).verify_request? }, "Not all Mime Types are verified: #{verified.inspect}" + assert unverified.all? { |type| !Mime.const_get(type.to_s.upcase).verify_request? }, "Some Mime Types are verified: #{unverified.inspect}" + end end diff --git a/vendor/rails/actionpack/test/controller/request_forgery_protection_test.rb b/vendor/rails/actionpack/test/controller/request_forgery_protection_test.rb index 7022713e..f7adaa7d 100644 --- a/vendor/rails/actionpack/test/controller/request_forgery_protection_test.rb +++ b/vendor/rails/actionpack/test/controller/request_forgery_protection_test.rb @@ -101,19 +101,79 @@ module RequestForgeryProtectionTests post :unsafe assert_response :success end - + def test_should_not_allow_post_without_token assert_raises(ActionController::InvalidAuthenticityToken) { post :index } end - + def test_should_not_allow_put_without_token assert_raises(ActionController::InvalidAuthenticityToken) { put :index } end - + def test_should_not_allow_delete_without_token assert_raises(ActionController::InvalidAuthenticityToken) { delete :index } end - + + def test_should_not_allow_api_formatted_post_without_token + assert_raises(ActionController::InvalidAuthenticityToken) do + post :index, :format => 'xml' + end + end + + def test_should_not_allow_api_formatted_put_without_token + assert_raises(ActionController::InvalidAuthenticityToken) do + put :index, :format => 'xml' + end + end + + def test_should_not_allow_api_formatted_delete_without_token + assert_raises(ActionController::InvalidAuthenticityToken) do + delete :index, :format => 'xml' + end + end + + def test_should_not_allow_api_formatted_post_sent_as_url_encoded_form_without_token + assert_raises(ActionController::InvalidAuthenticityToken) do + @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s + post :index, :format => 'xml' + end + end + + def test_should_not_allow_api_formatted_put_sent_as_url_encoded_form_without_token + assert_raises(ActionController::InvalidAuthenticityToken) do + @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s + put :index, :format => 'xml' + end + end + + def test_should_not_allow_api_formatted_delete_sent_as_url_encoded_form_without_token + assert_raises(ActionController::InvalidAuthenticityToken) do + @request.env['CONTENT_TYPE'] = Mime::URL_ENCODED_FORM.to_s + delete :index, :format => 'xml' + end + end + + def test_should_not_allow_api_formatted_post_sent_as_multipart_form_without_token + assert_raises(ActionController::InvalidAuthenticityToken) do + @request.env['CONTENT_TYPE'] = Mime::MULTIPART_FORM.to_s + post :index, :format => 'xml' + end + end + + def test_should_not_allow_api_formatted_put_sent_as_multipart_form_without_token + assert_raises(ActionController::InvalidAuthenticityToken) do + @request.env['CONTENT_TYPE'] = Mime::MULTIPART_FORM.to_s + put :index, :format => 'xml' + end + end + + def test_should_not_allow_api_formatted_delete_sent_as_multipart_form_without_token + assert_raises(ActionController::InvalidAuthenticityToken) do + @request.env['CONTENT_TYPE'] = Mime::MULTIPART_FORM.to_s + delete :index, :format => 'xml' + end + end + def test_should_not_allow_xhr_post_without_token assert_raises(ActionController::InvalidAuthenticityToken) { xhr :post, :index } end @@ -142,16 +202,19 @@ module RequestForgeryProtectionTests end def test_should_allow_post_with_xml + @request.env['CONTENT_TYPE'] = Mime::XML.to_s post :index, :format => 'xml' assert_response :success end def test_should_allow_put_with_xml + @request.env['CONTENT_TYPE'] = Mime::XML.to_s put :index, :format => 'xml' assert_response :success end def test_should_allow_delete_with_xml + @request.env['CONTENT_TYPE'] = Mime::XML.to_s delete :index, :format => 'xml' assert_response :success end diff --git a/vendor/rails/actionpack/test/controller/routing_test.rb b/vendor/rails/actionpack/test/controller/routing_test.rb index b28f7bcd..5e5503fd 100644 --- a/vendor/rails/actionpack/test/controller/routing_test.rb +++ b/vendor/rails/actionpack/test/controller/routing_test.rb @@ -50,6 +50,13 @@ class UriReservedCharactersRoutingTest < Test::Unit::TestCase :additional => ["add#{@segment}itional-1", "add#{@segment}itional-2"] } assert_equal options, @set.recognize_path("/controller/act#{@escaped}ion/var#{@escaped}iable/add#{@escaped}itional-1/add#{@escaped}itional-2") end + + def test_route_generation_allows_passing_non_string_values_to_generated_helper + assert_equal "/controller/action/variable/1/2", @set.generate(:controller => "controller", + :action => "action", + :variable => "variable", + :additional => [1, 2]) + end end class LegacyRouteSetTests < Test::Unit::TestCase diff --git a/vendor/rails/actionpack/test/controller/session/cookie_store_test.rb b/vendor/rails/actionpack/test/controller/session/cookie_store_test.rb index d308f2a3..5adaeaf5 100755 --- a/vendor/rails/actionpack/test/controller/session/cookie_store_test.rb +++ b/vendor/rails/actionpack/test/controller/session/cookie_store_test.rb @@ -43,7 +43,9 @@ class CookieStoreTest < Test::Unit::TestCase { :empty => ['BAgw--0686dcaccc01040f4bd4f35fe160afe9bc04c330', {}], :a_one => ['BAh7BiIGYWkG--5689059497d7f122a7119f171aef81dcfd807fec', { 'a' => 1 }], :typical => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7BiILbm90aWNlIgxIZXkgbm93--9d20154623b9eeea05c62ab819be0e2483238759', { 'user_id' => 123, 'flash' => { 'notice' => 'Hey now' }}], - :flashed => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA%3D%3D--bf9785a666d3c4ac09f7fe3353496b437546cfbf', { 'user_id' => 123, 'flash' => {} }] } + :flashed => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA==--bf9785a666d3c4ac09f7fe3353496b437546cfbf', { 'user_id' => 123, 'flash' => {} }], + :double_escaped => [CGI.escape('BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA%3D%3D--bf9785a666d3c4ac09f7fe3353496b437546cfbf'), { 'user_id' => 123, 'flash' => {} }] } + end def setup @@ -101,6 +103,15 @@ class CookieStoreTest < Test::Unit::TestCase end end + def test_restores_double_encoded_cookies + set_cookie! cookie_value(:double_escaped) + new_session do |session| + session.dbman.restore + assert_equal session["user_id"], 123 + assert_equal session["flash"], {} + end + end + def test_close_doesnt_write_cookie_if_data_is_blank new_session do |session| assert_no_cookies session @@ -241,6 +252,7 @@ class CookieStoreWithMD5DigestTest < CookieStoreTest { :empty => ['BAgw--0415cc0be9579b14afc22ee2d341aa21', {}], :a_one => ['BAh7BiIGYWkG--5a0ed962089cc6600ff44168a5d59bc8', { 'a' => 1 }], :typical => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7BiILbm90aWNlIgxIZXkgbm93--f426763f6ef435b3738b493600db8d64', { 'user_id' => 123, 'flash' => { 'notice' => 'Hey now' }}], - :flashed => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA%3D%3D--0af9156650dab044a53a91a4ddec2c51', { 'user_id' => 123, 'flash' => {} }] } + :flashed => ['BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA==--0af9156650dab044a53a91a4ddec2c51', { 'user_id' => 123, 'flash' => {} }], + :double_escaped => [CGI.escape('BAh7ByIMdXNlcl9pZGkBeyIKZmxhc2h7AA%3D%3D--0af9156650dab044a53a91a4ddec2c51'), { 'user_id' => 123, 'flash' => {} }] } end end diff --git a/vendor/rails/actionpack/test/controller/test_test.rb b/vendor/rails/actionpack/test/controller/test_test.rb index ba6c7f42..38898a1f 100644 --- a/vendor/rails/actionpack/test/controller/test_test.rb +++ b/vendor/rails/actionpack/test/controller/test_test.rb @@ -511,16 +511,26 @@ XML FILES_DIR = File.dirname(__FILE__) + '/../fixtures/multipart' + if RUBY_VERSION < '1.9' + READ_BINARY = 'rb' + READ_PLAIN = 'r' + else + READ_BINARY = 'rb:binary' + READ_PLAIN = 'r:binary' + end + def test_test_uploaded_file filename = 'mona_lisa.jpg' path = "#{FILES_DIR}/#{filename}" content_type = 'image/png' + expected = File.read(path) + expected.force_encoding(Encoding::BINARY) if expected.respond_to?(:force_encoding) file = ActionController::TestUploadedFile.new(path, content_type) assert_equal filename, file.original_filename assert_equal content_type, file.content_type assert_equal file.path, file.local_path - assert_equal File.read(path), file.read + assert_equal expected, file.read end def test_test_uploaded_file_with_binary @@ -529,10 +539,10 @@ XML content_type = 'image/png' binary_uploaded_file = ActionController::TestUploadedFile.new(path, content_type, :binary) - assert_equal File.open(path, 'rb').read, binary_uploaded_file.read + assert_equal File.open(path, READ_BINARY).read, binary_uploaded_file.read plain_uploaded_file = ActionController::TestUploadedFile.new(path, content_type) - assert_equal File.open(path, 'r').read, plain_uploaded_file.read + assert_equal File.open(path, READ_PLAIN).read, plain_uploaded_file.read end def test_fixture_file_upload_with_binary @@ -541,10 +551,10 @@ XML content_type = 'image/jpg' binary_file_upload = fixture_file_upload(path, content_type, :binary) - assert_equal File.open(path, 'rb').read, binary_file_upload.read + assert_equal File.open(path, READ_BINARY).read, binary_file_upload.read plain_file_upload = fixture_file_upload(path, content_type) - assert_equal File.open(path, 'r').read, plain_file_upload.read + assert_equal File.open(path, READ_PLAIN).read, plain_file_upload.read end def test_fixture_file_upload diff --git a/vendor/rails/actionpack/test/template/compiled_templates_test.rb b/vendor/rails/actionpack/test/template/compiled_templates_test.rb deleted file mode 100644 index 73e7ec1d..00000000 --- a/vendor/rails/actionpack/test/template/compiled_templates_test.rb +++ /dev/null @@ -1,192 +0,0 @@ -require 'abstract_unit' -require 'action_view/helpers/date_helper' -require 'action_view/compiled_templates' - -class CompiledTemplateTests < Test::Unit::TestCase - def setup - @ct = ActionView::CompiledTemplates.new - @v = Class.new - @v.send :include, @ct - @a = './test_compile_template_a.rhtml' - @b = './test_compile_template_b.rhtml' - @s = './test_compile_template_link.rhtml' - end - def teardown - [@a, @b, @s].each do |f| - FileUtils.rm(f) if File.exist?(f) || File.symlink?(f) - end - end - attr_reader :ct, :v - - def test_name_allocation - hi_world = ct.method_names['hi world'] - hi_sexy = ct.method_names['hi sexy'] - wish_upon_a_star = ct.method_names['I love seeing decent error messages'] - - assert_equal hi_world, ct.method_names['hi world'] - assert_equal hi_sexy, ct.method_names['hi sexy'] - assert_equal wish_upon_a_star, ct.method_names['I love seeing decent error messages'] - assert_equal 3, [hi_world, hi_sexy, wish_upon_a_star].uniq.length - end - - def test_wrap_source - assert_equal( - "def aliased_assignment(value)\nself.value = value\nend", - @ct.wrap_source(:aliased_assignment, [:value], 'self.value = value') - ) - - assert_equal( - "def simple()\nnil\nend", - @ct.wrap_source(:simple, [], 'nil') - ) - end - - def test_compile_source_single_method - selector = ct.compile_source('doubling method', [:a], 'a + a') - assert_equal 2, @v.new.send(selector, 1) - assert_equal 4, @v.new.send(selector, 2) - assert_equal -4, @v.new.send(selector, -2) - assert_equal 0, @v.new.send(selector, 0) - selector - end - - def test_compile_source_two_method - sel1 = test_compile_source_single_method # compile the method in the other test - sel2 = ct.compile_source('doubling method', [:a, :b], 'a + b + a + b') - assert_not_equal sel1, sel2 - - assert_equal 2, @v.new.send(sel1, 1) - assert_equal 4, @v.new.send(sel1, 2) - - assert_equal 6, @v.new.send(sel2, 1, 2) - assert_equal 32, @v.new.send(sel2, 15, 1) - end - - def test_mtime - t1 = Time.now - - test_compile_source_single_method - mtime = ct.mtime('doubling method', [:a]) - - assert mtime < Time.now - assert mtime > t1 - end - - uses_mocha 'test_compile_time' do - - def test_compile_time - t = Time.now - - 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 = '.' - v.cache_template_loading = false - - ta = ActionView::Template.new(v, @a, false, {}) - tb = ActionView::Template.new(v, @b, false, {}) - ts = ActionView::Template.new(v, @s, false, {}) - - @handler_class = ActionView::Template.handler_class_for_extension(:rhtml) - @handler = @handler_class.new(v) - - # All templates were created at t+1 - File::Stat.any_instance.expects(:mtime).times(windows ? 2 : 3).returns(t + 1.second) - - # private methods template_changed_since? and compile_template? - # should report true for all since they have not been compiled - assert @handler.send(:template_changed_since?, @a, t) - assert @handler.send(:template_changed_since?, @b, t) - assert @handler.send(:template_changed_since?, @s, t) unless windows - - assert @handler.send(:compile_template?, ta) - assert @handler.send(:compile_template?, tb) - assert @handler.send(:compile_template?, ts) unless windows - - # All templates are rendered at t+2 - Time.expects(:now).times(windows ? 2 : 3).returns(t + 2.seconds) - v.send(:render_template, ta) - v.send(:render_template, tb) - v.send(:render_template, ts) unless windows - a_n = v.method_names[@a] - b_n = v.method_names[@b] - s_n = v.method_names[@s] unless windows - # all of the files have changed since last compile - assert @handler.compile_time[a_n] > t - assert @handler.compile_time[b_n] > t - assert @handler.compile_time[s_n] > t unless windows - - # private methods template_changed_since? and compile_template? - # should report false for all since none have changed since compile - File::Stat.any_instance.expects(:mtime).times(windows ? 6 : 12).returns(t + 1.second) - assert !@handler.send(:template_changed_since?, @a, @handler.compile_time[a_n]) - assert !@handler.send(:template_changed_since?, @b, @handler.compile_time[b_n]) - assert !@handler.send(:template_changed_since?, @s, @handler.compile_time[s_n]) unless windows - assert !@handler.send(:compile_template?, ta) - assert !@handler.send(:compile_template?, tb) - assert !@handler.send(:compile_template?, ts) unless windows - v.send(:render_template, ta) - v.send(:render_template, tb) - v.send(:render_template, ts) unless windows - # none of the files have changed since last compile - assert @handler.compile_time[a_n] < t + 3.seconds - assert @handler.compile_time[b_n] < t + 3.seconds - assert @handler.compile_time[s_n] < t + 3.seconds unless windows - - `rm #{@s}; ln -s #{@b} #{@s}` unless windows - # private methods template_changed_since? and compile_template? - # should report true for symlink since it has changed since compile - - # t + 3.seconds is for the symlink - File::Stat.any_instance.expects(:mtime).times(windows ? 6 : 9).returns( - *(windows ? [ t + 1.second, t + 1.second ] : - [ t + 1.second, t + 1.second, t + 3.second ]) * 3) - assert !@handler.send(:template_changed_since?, @a, @handler.compile_time[a_n]) - assert !@handler.send(:template_changed_since?, @b, @handler.compile_time[b_n]) - assert @handler.send(:template_changed_since?, @s, @handler.compile_time[s_n]) unless windows - assert !@handler.send(:compile_template?, ta) - assert !@handler.send(:compile_template?, tb) - assert @handler.send(:compile_template?, ts) unless windows - - # Only the symlink template gets rendered at t+3 - Time.stubs(:now).returns(t + 3.seconds) unless windows - v.send(:render_template, ta) - v.send(:render_template, tb) - v.send(:render_template, ts) unless windows - # the symlink has changed since last compile - assert @handler.compile_time[a_n] < t + 3.seconds - assert @handler.compile_time[b_n] < t + 3.seconds - assert_equal @handler.compile_time[s_n], t + 3.seconds unless windows - - FileUtils.touch @b - # private methods template_changed_since? and compile_template? - # should report true for symlink and file at end of symlink - # since it has changed since last compile - # - # t+4 is for @b and also for the file that @s points to, which is @b - File::Stat.any_instance.expects(:mtime).times(windows ? 6 : 12).returns( - *(windows ? [ t + 1.second, t + 4.seconds ] : - [ t + 1.second, t + 4.seconds, t + 3.second, t + 4.seconds ]) * 3) - assert !@handler.send(:template_changed_since?, @a, @handler.compile_time[a_n]) - assert @handler.send(:template_changed_since?, @b, @handler.compile_time[b_n]) - assert @handler.send(:template_changed_since?, @s, @handler.compile_time[s_n]) unless windows - assert !@handler.send(:compile_template?, ta) - assert @handler.send(:compile_template?, tb) - assert @handler.send(:compile_template?, ts) unless windows - - Time.expects(:now).times(windows ? 1 : 2).returns(t + 5.seconds) - v.send(:render_template, ta) - v.send(:render_template, tb) - v.send(:render_template, ts) 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 @handler.compile_time[a_n] < t + 5.seconds - assert_equal @handler.compile_time[b_n], t + 5.seconds - assert_equal @handler.compile_time[s_n], t + 5.seconds unless windows - end - end -end diff --git a/vendor/rails/actionpack/test/template/date_helper_test.rb b/vendor/rails/actionpack/test/template/date_helper_test.rb index ae83c7bf..0a7b19ba 100755 --- a/vendor/rails/actionpack/test/template/date_helper_test.rb +++ b/vendor/rails/actionpack/test/template/date_helper_test.rb @@ -1722,6 +1722,12 @@ class DateHelperTest < ActionView::TestCase assert_equal 2, dummy_instance_tag.send!(:default_time_from_options, :hour => 2).hour end end + + def test_instance_tag_default_time_from_options_handles_far_future_date + dummy_instance_tag = ActionView::Helpers::InstanceTag.new(1,2,3) + time = dummy_instance_tag.send!(:default_time_from_options, :year => 2050, :month => 2, :day => 10, :hour => 15, :min => 30, :sec => 45) + assert_equal 2050, time.year + end end protected diff --git a/vendor/rails/actionpack/test/template/form_helper_test.rb b/vendor/rails/actionpack/test/template/form_helper_test.rb index 4538b6dc..af99e624 100644 --- a/vendor/rails/actionpack/test/template/form_helper_test.rb +++ b/vendor/rails/actionpack/test/template/form_helper_test.rb @@ -181,6 +181,17 @@ class FormHelperTest < ActionView::TestCase '', check_box("post", "secret?") ) + + @post.secret = ['0'] + assert_dom_equal( + '', + check_box("post", "secret") + ) + @post.secret = ['1'] + assert_dom_equal( + '', + check_box("post", "secret") + ) end def test_check_box_with_explicit_checked_and_unchecked_values diff --git a/vendor/rails/actionpack/test/template/prototype_helper_test.rb b/vendor/rails/actionpack/test/template/prototype_helper_test.rb index a84d4e72..53a250f9 100644 --- a/vendor/rails/actionpack/test/template/prototype_helper_test.rb +++ b/vendor/rails/actionpack/test/template/prototype_helper_test.rb @@ -25,8 +25,6 @@ class Author::Nested < Author; end class PrototypeHelperBaseTest < ActionView::TestCase - tests ActionView::Helpers::PrototypeHelper - attr_accessor :template_format def setup @@ -86,6 +84,11 @@ class PrototypeHelperTest < PrototypeHelperBaseTest link_to_remote("Remote outauthor", { :url => { :action => "whatnot" }, :html => { :class => "fine" } }) end + def test_link_to_remote_url_quote_escaping + assert_dom_equal %(Remote), + link_to_remote("Remote", { :url => { :action => "whatnot's" } }) + end + def test_periodically_call_remote assert_dom_equal %(), periodically_call_remote(:update => "schremser_bier", :url => { :action => "mehr_bier" }) @@ -214,9 +217,9 @@ class PrototypeHelperTest < PrototypeHelperBaseTest end def test_observe_field_using_with_option - expected = %() + expected = %() assert_dom_equal expected, observe_field("glass", :frequency => 5.minutes, :url => { :action => "check_value" }, :with => 'id') - assert_dom_equal expected, observe_field("glass", :frequency => 5.minutes, :url => { :action => "check_value" }, :with => "'id=' + value") + assert_dom_equal expected, observe_field("glass", :frequency => 5.minutes, :url => { :action => "check_value" }, :with => "'id=' + encodeURIComponent(value)") end def test_observe_field_using_json_in_with_option diff --git a/vendor/rails/actionpack/test/template/text_helper_test.rb b/vendor/rails/actionpack/test/template/text_helper_test.rb index 25ecda68..62cdca03 100644 --- a/vendor/rails/actionpack/test/template/text_helper_test.rb +++ b/vendor/rails/actionpack/test/template/text_helper_test.rb @@ -23,9 +23,9 @@ class TextHelperTest < ActionView::TestCase text = "A\r\n \nB\n\n\r\n\t\nC\nD".freeze assert_equal "

A\n
\n
B

\n\n

\t\n
C\n
D

", simple_format(text) - + assert_equal %q(

This is a classy test

), simple_format("This is a classy test", :class => 'test') - assert_equal %Q(

para 1

\n\n

para 2

), simple_format("para 1\n\npara 2", :class => 'test') + assert_equal %Q(

para 1

\n\n

para 2

), simple_format("para 1\n\npara 2", :class => 'test') end def test_truncate @@ -41,7 +41,7 @@ class TextHelperTest < ActionView::TestCase if RUBY_VERSION < '1.9.0' def test_truncate_multibyte with_kcode 'none' do - assert_equal "\354\225\210\353\205\225\355...", truncate("\354\225\210\353\205\225\355\225\230\354\204\270\354\232\224", 10) + assert_equal "\354\225\210\353\205\225\355...", truncate("\354\225\210\353\205\225\355\225\230\354\204\270\354\232\224", 10) end with_kcode 'u' do assert_equal "\354\225\204\353\246\254\353\236\221 \354\225\204\353\246\254 ...", @@ -73,7 +73,7 @@ class TextHelperTest < ActionView::TestCase "This is a beautiful morning, but also a beautiful day", highlight("This is a beautiful morning, but also a beautiful day", "beautiful", '\1') ) - + assert_equal( "This text is not changed because we supplied an empty phrase", highlight("This text is not changed because we supplied an empty phrase", nil) @@ -166,18 +166,9 @@ class TextHelperTest < ActionView::TestCase assert_equal("2 counters", pluralize(2, "count", "counters")) assert_equal("0 counters", pluralize(nil, "count", "counters")) assert_equal("2 people", pluralize(2, "person")) - assert_equal("10 buffaloes", pluralize(10, "buffalo")) - end - - uses_mocha("should_just_add_s_for_pluralize_without_inflector_loaded") do - def test_should_just_add_s_for_pluralize_without_inflector_loaded - Object.expects(:const_defined?).with("Inflector").times(4).returns(false) - assert_equal("1 count", pluralize(1, "count")) - assert_equal("2 persons", pluralize(2, "person")) - assert_equal("2 personss", pluralize("2", "persons")) - assert_equal("2 counts", pluralize(2, "count")) - assert_equal("10 buffalos", pluralize(10, "buffalo")) - end + assert_equal("10 buffaloes", pluralize(10, "buffalo")) + assert_equal("1 berry", pluralize(1, "berry")) + assert_equal("12 berries", pluralize(12, "berry")) end def test_auto_link_parsing @@ -195,6 +186,7 @@ class TextHelperTest < ActionView::TestCase http://en.wikipedia.org/wiki/Wikipedia:Today%27s_featured_picture_%28animation%29/January_20%2C_2007 http://www.mail-archive.com/rails@lists.rubyonrails.org/ http://www.amazon.com/Testing-Equal-Sign-In-Path/ref=pd_bbs_sr_1?ie=UTF8&s=books&qid=1198861734&sr=8-1 + http://en.wikipedia.org/wiki/Sprite_(computer_graphics) ) urls.each do |url| @@ -271,6 +263,8 @@ class TextHelperTest < ActionView::TestCase assert_equal email2_result, auto_link(email2_raw) assert_equal '', auto_link(nil) assert_equal '', auto_link('') + assert_equal "#{link_result} #{link_result} #{link_result}", auto_link("#{link_raw} #{link_raw} #{link_raw}") + assert_equal 'Ruby On Rails', auto_link('Ruby On Rails') end def test_auto_link_at_eol @@ -298,7 +292,7 @@ class TextHelperTest < ActionView::TestCase assert_equal("2", value.to_s) assert_equal("3", value.to_s) end - + def test_cycle_class_with_no_arguments assert_raise(ArgumentError) { value = Cycle.new() } end @@ -311,11 +305,11 @@ class TextHelperTest < ActionView::TestCase assert_equal("2", cycle("one", 2, "3")) assert_equal("3", cycle("one", 2, "3")) end - + def test_cycle_with_no_arguments assert_raise(ArgumentError) { value = cycle() } end - + def test_cycle_resets_with_new_values assert_equal("even", cycle("even", "odd")) assert_equal("odd", cycle("even", "odd")) @@ -325,7 +319,7 @@ class TextHelperTest < ActionView::TestCase assert_equal("3", cycle(1, 2, 3)) assert_equal("1", cycle(1, 2, 3)) end - + def test_named_cycles assert_equal("1", cycle(1, 2, 3, :name => "numbers")) assert_equal("red", cycle("red", "blue", :name => "colors")) @@ -334,24 +328,24 @@ class TextHelperTest < ActionView::TestCase assert_equal("3", cycle(1, 2, 3, :name => "numbers")) assert_equal("red", cycle("red", "blue", :name => "colors")) end - + def test_default_named_cycle assert_equal("1", cycle(1, 2, 3)) assert_equal("2", cycle(1, 2, 3, :name => "default")) assert_equal("3", cycle(1, 2, 3)) end - + def test_reset_cycle assert_equal("1", cycle(1, 2, 3)) assert_equal("2", cycle(1, 2, 3)) reset_cycle assert_equal("1", cycle(1, 2, 3)) end - + def test_reset_unknown_cycle reset_cycle("colors") end - + def test_recet_named_cycle assert_equal("1", cycle(1, 2, 3, :name => "numbers")) assert_equal("red", cycle("red", "blue", :name => "colors")) @@ -361,7 +355,7 @@ class TextHelperTest < ActionView::TestCase assert_equal("2", cycle(1, 2, 3, :name => "numbers")) assert_equal("red", cycle("red", "blue", :name => "colors")) end - + def test_cycle_no_instance_variable_clashes @cycles = %w{Specialized Fuji Giant} assert_equal("red", cycle("red", "blue")) diff --git a/vendor/rails/activemodel/CHANGES b/vendor/rails/activemodel/CHANGES new file mode 100644 index 00000000..a9f9c275 --- /dev/null +++ b/vendor/rails/activemodel/CHANGES @@ -0,0 +1,12 @@ +Changes from extracting bits to ActiveModel + +* ActiveModel::Observer#add_observer! + + It has a custom hook to define after_find that should really be in a + ActiveRecord::Observer subclass: + + def add_observer!(klass) + klass.add_observer(self) + klass.class_eval 'def after_find() end' unless + klass.respond_to?(:after_find) + end \ No newline at end of file diff --git a/vendor/rails/activemodel/README b/vendor/rails/activemodel/README new file mode 100644 index 00000000..c20f732a --- /dev/null +++ b/vendor/rails/activemodel/README @@ -0,0 +1,21 @@ +Active Model +============== + +Totally experimental library that aims to extract common model mixins from +ActiveRecord for use in ActiveResource (and other similar libraries). +This is in a very rough state (no autotest or spec rake tasks set up yet), +so please excuse the mess. + +Here's what I plan to extract: + * ActiveModel::Observing + * ActiveModel::Callbacks + * ActiveModel::Validations + + # for ActiveResource params and ActiveRecord options + * ActiveModel::Scoping + + # to_json, to_xml, etc + * ActiveModel::Serialization + +I'm trying to keep ActiveRecord compatibility where possible, but I'm +annotating the spots where I'm diverging a bit. \ No newline at end of file diff --git a/vendor/rails/activemodel/Rakefile b/vendor/rails/activemodel/Rakefile new file mode 100644 index 00000000..87e9b547 --- /dev/null +++ b/vendor/rails/activemodel/Rakefile @@ -0,0 +1,16 @@ +#!/usr/bin/env ruby +$LOAD_PATH << File.join(File.dirname(__FILE__), 'vendor', 'rspec', 'lib') +require 'rake' +require 'spec/rake/spectask' +require 'rake/rdoctask' + +# Generate the RDoc documentation +Rake::RDocTask.new { |rdoc| + rdoc.rdoc_dir = 'doc' + rdoc.title = "Active Model" + rdoc.options << '--line-numbers' << '--inline-source' << '-A cattr_accessor=object' + rdoc.options << '--charset' << 'utf-8' + rdoc.template = "#{ENV['template']}.rb" if ENV['template'] + rdoc.rdoc_files.include('README', 'CHANGES') + rdoc.rdoc_files.include('lib/**/*.rb') +} \ No newline at end of file diff --git a/vendor/rails/activemodel/lib/active_model.rb b/vendor/rails/activemodel/lib/active_model.rb new file mode 100644 index 00000000..369c7fed --- /dev/null +++ b/vendor/rails/activemodel/lib/active_model.rb @@ -0,0 +1,17 @@ +$LOAD_PATH << File.join(File.dirname(__FILE__), '..', '..', 'activesupport', 'lib') + +# premature optimization? +require 'active_support/inflector' +require 'active_support/core_ext/string/inflections' +String.send :include, ActiveSupport::CoreExtensions::String::Inflections + +require 'active_model/base' +require 'active_model/observing' +require 'active_model/callbacks' +require 'active_model/validations' + +ActiveModel::Base.class_eval do + include ActiveModel::Observing + include ActiveModel::Callbacks + include ActiveModel::Validations +end \ No newline at end of file diff --git a/vendor/rails/activemodel/lib/active_model/base.rb b/vendor/rails/activemodel/lib/active_model/base.rb new file mode 100644 index 00000000..1141156d --- /dev/null +++ b/vendor/rails/activemodel/lib/active_model/base.rb @@ -0,0 +1,4 @@ +module ActiveModel + class Base + end +end \ No newline at end of file diff --git a/vendor/rails/activemodel/lib/active_model/callbacks.rb b/vendor/rails/activemodel/lib/active_model/callbacks.rb new file mode 100644 index 00000000..0114fc38 --- /dev/null +++ b/vendor/rails/activemodel/lib/active_model/callbacks.rb @@ -0,0 +1,5 @@ +module ActiveModel + module Callbacks + + end +end \ No newline at end of file diff --git a/vendor/rails/activemodel/lib/active_model/deprecated_error_methods.rb b/vendor/rails/activemodel/lib/active_model/deprecated_error_methods.rb new file mode 100644 index 00000000..e0cbd9ba --- /dev/null +++ b/vendor/rails/activemodel/lib/active_model/deprecated_error_methods.rb @@ -0,0 +1,38 @@ +module ActiveModel + module DeprecatedErrorMethods + def on(attribute) + ActiveSupport::Deprecation.warn "Errors#on have been deprecated, use Errors#[] instead" + self[attribute] + end + + def on_base + ActiveSupport::Deprecation.warn "Errors#on_base have been deprecated, use Errors#[:base] instead" + on(:base) + end + + def add(attribute, msg = Errors.default_error_messages[:invalid]) + ActiveSupport::Deprecation.warn "Errors#add(attribute, msg) has been deprecated, use Errors#[attribute] << msg instead" + self[attribute] << msg + end + + def add_to_base(msg) + ActiveSupport::Deprecation.warn "Errors#add_to_base(msg) has been deprecated, use Errors#[:base] << msg instead" + self[:base] << msg + end + + def invalid?(attribute) + ActiveSupport::Deprecation.warn "Errors#invalid?(attribute) has been deprecated, use Errors#[attribute].any? instead" + self[attribute].any? + end + + def full_messages + ActiveSupport::Deprecation.warn "Errors#full_messages has been deprecated, use Errors#to_a instead" + to_a + end + + def each_full + ActiveSupport::Deprecation.warn "Errors#each_full has been deprecated, use Errors#to_a.each instead" + to_a.each { |error| yield error } + end + end +end \ No newline at end of file diff --git a/vendor/rails/activemodel/lib/active_model/errors.rb b/vendor/rails/activemodel/lib/active_model/errors.rb new file mode 100644 index 00000000..a99bb001 --- /dev/null +++ b/vendor/rails/activemodel/lib/active_model/errors.rb @@ -0,0 +1,80 @@ +module ActiveModel + class Errors < Hash + include DeprecatedErrorMethods + + @@default_error_messages = { + :inclusion => "is not included in the list", + :exclusion => "is reserved", + :invalid => "is invalid", + :confirmation => "doesn't match confirmation", + :accepted => "must be accepted", + :empty => "can't be empty", + :blank => "can't be blank", + :too_long => "is too long (maximum is %d characters)", + :too_short => "is too short (minimum is %d characters)", + :wrong_length => "is the wrong length (should be %d characters)", + :taken => "has already been taken", + :not_a_number => "is not a number", + :greater_than => "must be greater than %d", + :greater_than_or_equal_to => "must be greater than or equal to %d", + :equal_to => "must be equal to %d", + :less_than => "must be less than %d", + :less_than_or_equal_to => "must be less than or equal to %d", + :odd => "must be odd", + :even => "must be even" + } + + # Holds a hash with all the default error messages that can be replaced by your own copy or localizations. + cattr_accessor :default_error_messages + + alias_method :get, :[] + alias_method :set, :[]= + + def [](attribute) + if errors = get(attribute.to_sym) + errors.size == 1 ? errors.first : errors + else + set(attribute.to_sym, []) + end + end + + def []=(attribute, error) + self[attribute.to_sym] << error + end + + def each + each_key do |attribute| + self[attribute].each { |error| yield attribute, error } + end + end + + def size + values.flatten.size + end + + def to_a + inject([]) do |errors_with_attributes, (attribute, errors)| + if error.blank? + errors_with_attributes + else + if attr == :base + errors_with_attributes << error + else + errors_with_attributes << (attribute.to_s.humanize + " " + error) + end + end + end + end + + def to_xml(options={}) + options[:root] ||= "errors" + options[:indent] ||= 2 + options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent]) + + options[:builder].instruct! unless options.delete(:skip_instruct) + options[:builder].errors do |e| + to_a.each { |error| e.error(error) } + end + end + end +end \ No newline at end of file diff --git a/vendor/rails/activemodel/lib/active_model/observing.rb b/vendor/rails/activemodel/lib/active_model/observing.rb new file mode 100644 index 00000000..db758f51 --- /dev/null +++ b/vendor/rails/activemodel/lib/active_model/observing.rb @@ -0,0 +1,100 @@ +require 'observer' + +module ActiveModel + module Observing + module ClassMethods + def observers + @observers ||= [] + end + + def observers=(*values) + @observers = values.flatten + end + + def instantiate_observers + observers.each { |o| instantiate_observer(o) } + end + + protected + def instantiate_observer(observer) + # string/symbol + if observer.respond_to?(:to_sym) + observer = observer.to_s.camelize.constantize.instance + elsif observer.respond_to?(:instance) + observer.instance + else + raise ArgumentError, "#{observer} must be a lowercase, underscored class name (or an instance of the class itself) responding to the instance method. Example: Person.observers = :big_brother # calls BigBrother.instance" + end + end + + # Notify observers when the observed class is subclassed. + def inherited(subclass) + super + changed + notify_observers :observed_class_inherited, subclass + end + end + + def self.included(receiver) + receiver.extend Observable, ClassMethods + end + end + + class Observer + include Singleton + attr_writer :observed_classes + + class << self + attr_accessor :models + # Attaches the observer to the supplied model classes. + def observe(*models) + @models = models.flatten + @models.collect! { |model| model.respond_to?(:to_sym) ? model.to_s.camelize.constantize : model } + end + + def observed_class_name + @observed_class_name ||= + if guessed_name = name.scan(/(.*)Observer/)[0] + @observed_class_name = guessed_name[0] + end + end + + # The class observed by default is inferred from the observer's class name: + # assert_equal [Person], PersonObserver.observed_class + def observed_class + if observed_class_name + observed_class_name.constantize + else + nil + end + end + end + + # Start observing the declared classes and their subclasses. + def initialize + self.observed_classes = self.class.models if self.class.models + observed_classes.each { |klass| add_observer! klass } + end + + # Send observed_method(object) if the method exists. + def update(observed_method, object) #:nodoc: + send(observed_method, object) if respond_to?(observed_method) + end + + # Special method sent by the observed class when it is inherited. + # Passes the new subclass. + def observed_class_inherited(subclass) #:nodoc: + self.class.observe(observed_classes + [subclass]) + add_observer!(subclass) + end + + protected + def observed_classes + @observed_classes ||= [self.class.observed_class] + end + + def add_observer!(klass) + klass.add_observer(self) + end + end +end \ No newline at end of file diff --git a/vendor/rails/activemodel/lib/active_model/validations.rb b/vendor/rails/activemodel/lib/active_model/validations.rb new file mode 100644 index 00000000..34ef3b8f --- /dev/null +++ b/vendor/rails/activemodel/lib/active_model/validations.rb @@ -0,0 +1,124 @@ +module ActiveModel + module Validations + def self.included(base) # :nodoc: + base.extend(ClassMethods) + base.send!(:include, ActiveSupport::Callbacks) + base.define_callbacks :validate, :validate_on_create, :validate_on_update + end + + module ClassMethods + DEFAULT_VALIDATION_OPTIONS = { :on => :save, :allow_nil => false, :allow_blank => false, :message => nil }.freeze + + # Adds a validation method or block to the class. This is useful when + # overriding the +validate+ instance method becomes too unwieldly and + # you're looking for more descriptive declaration of your validations. + # + # This can be done with a symbol pointing to a method: + # + # class Comment < ActiveRecord::Base + # validate :must_be_friends + # + # def must_be_friends + # errors.add_to_base("Must be friends to leave a comment") unless commenter.friend_of?(commentee) + # end + # end + # + # Or with a block which is passed the current record to be validated: + # + # class Comment < ActiveRecord::Base + # validate do |comment| + # comment.must_be_friends + # end + # + # def must_be_friends + # errors.add_to_base("Must be friends to leave a comment") unless commenter.friend_of?(commentee) + # end + # end + # + # This usage applies to +validate_on_create+ and +validate_on_update as well+. + # + # Validates each attribute against a block. + # + # class Person < ActiveRecord::Base + # validates_each :first_name, :last_name do |record, attr, value| + # record.errors.add attr, 'starts with z.' if value[0] == ?z + # end + # end + # + # Options: + # * :on - Specifies when this validation is active (default is :save, other options :create, :update) + # * :allow_nil - Skip validation if attribute is +nil+. + # * :allow_blank - Skip validation if attribute is blank. + # * :if - Specifies a method, proc or string to call to determine if the validation should + # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The + # method, proc or string should return or evaluate to a true or false value. + # * :unless - Specifies a method, proc or string to call to determine if the validation should + # not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The + # method, proc or string should return or evaluate to a true or false value. + def validates_each(*attrs) + options = attrs.extract_options!.symbolize_keys + attrs = attrs.flatten + + # Declare the validation. + send(validation_method(options[:on] || :save), options) do |record| + attrs.each do |attr| + value = record.send(attr) + next if (value.nil? && options[:allow_nil]) || (value.blank? && options[:allow_blank]) + yield record, attr, value + end + end + end + + private + def validation_method(on) + case on + when :save then :validate + when :create then :validate_on_create + when :update then :validate_on_update + end + end + end + + # Returns the Errors object that holds all information about attribute error messages. + def errors + @errors ||= Errors.new + end + + # Runs all the specified validations and returns true if no errors were added otherwise false. + def valid? + errors.clear + + run_callbacks(:validate) + + if responds_to?(:validate) + ActiveSupport::Deprecations.warn "Base#validate has been deprecated, please use Base.validate :method instead" + validate + end + + if new_record? + run_callbacks(:validate_on_create) + + if responds_to?(:validate_on_create) + ActiveSupport::Deprecations.warn( + "Base#validate_on_create has been deprecated, please use Base.validate_on_create :method instead") + validate_on_create + end + else + run_callbacks(:validate_on_update) + + if responds_to?(:validate_on_update) + ActiveSupport::Deprecations.warn( + "Base#validate_on_update has been deprecated, please use Base.validate_on_update :method instead") + validate_on_update + end + end + + errors.empty? + end + end +end + +Dir[File.dirname(__FILE__) + "/validations/*.rb"].sort.each do |path| + filename = File.basename(path) + require "active_model/validations/#{filename}" +end \ No newline at end of file diff --git a/vendor/rails/activemodel/lib/active_model/validations/acceptance.rb b/vendor/rails/activemodel/lib/active_model/validations/acceptance.rb new file mode 100644 index 00000000..9be7d51f --- /dev/null +++ b/vendor/rails/activemodel/lib/active_model/validations/acceptance.rb @@ -0,0 +1,45 @@ +module ActiveModel + module Validations + module ClassMethods + # Encapsulates the pattern of wanting to validate the acceptance of a terms of service check box (or similar agreement). Example: + # + # class Person < ActiveRecord::Base + # validates_acceptance_of :terms_of_service + # validates_acceptance_of :eula, :message => "must be abided" + # end + # + # If the database column does not exist, the :terms_of_service attribute is entirely virtual. This check is + # performed only if :terms_of_service is not +nil+ and by default on save. + # + # Configuration options: + # * :message - A custom error message (default is: "must be accepted") + # * :on - Specifies when this validation is active (default is :save, other options :create, :update) + # * :allow_nil - Skip validation if attribute is +nil+. (default is +true+) + # * :accept - Specifies value that is considered accepted. The default value is a string "1", which + # makes it easy to relate to an HTML checkbox. This should be set to +true+ if you are validating a database + # column, since the attribute is typecasted from "1" to +true+ before validation. + # * :if - Specifies a method, proc or string to call to determine if the validation should + # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The + # method, proc or string should return or evaluate to a true or false value. + # * :unless - Specifies a method, proc or string to call to determine if the validation should + # not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The + # method, proc or string should return or evaluate to a true or false value. + def validates_acceptance_of(*attr_names) + configuration = { :message => ActiveRecord::Errors.default_error_messages[:accepted], :on => :save, :allow_nil => true, :accept => "1" } + configuration.update(attr_names.extract_options!) + + db_cols = begin + column_names + rescue ActiveRecord::StatementInvalid + [] + end + names = attr_names.reject { |name| db_cols.include?(name.to_s) } + attr_accessor(*names) + + validates_each(attr_names,configuration) do |record, attr_name, value| + record.errors.add(attr_name, configuration[:message]) unless value == configuration[:accept] + end + end + end + end +end \ No newline at end of file diff --git a/vendor/rails/activemodel/lib/active_model/validations/associated.rb b/vendor/rails/activemodel/lib/active_model/validations/associated.rb new file mode 100644 index 00000000..b2d78af5 --- /dev/null +++ b/vendor/rails/activemodel/lib/active_model/validations/associated.rb @@ -0,0 +1,46 @@ +module ActiveModel + module Validations + module ClassMethods + # Validates whether the associated object or objects are all valid themselves. Works with any kind of association. + # + # class Book < ActiveRecord::Base + # has_many :pages + # belongs_to :library + # + # validates_associated :pages, :library + # end + # + # Warning: If, after the above definition, you then wrote: + # + # class Page < ActiveRecord::Base + # belongs_to :book + # + # validates_associated :book + # end + # + # ...this would specify a circular dependency and cause infinite recursion. + # + # NOTE: This validation will not fail if the association hasn't been assigned. If you want to ensure that the association + # is both present and guaranteed to be valid, you also need to use +validates_presence_of+. + # + # Configuration options: + # * :message - A custom error message (default is: "is invalid") + # * :on - Specifies when this validation is active (default is :save, other options :create, :update) + # * :if - Specifies a method, proc or string to call to determine if the validation should + # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The + # method, proc or string should return or evaluate to a true or false value. + # * :unless - Specifies a method, proc or string to call to determine if the validation should + # not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The + # method, proc or string should return or evaluate to a true or false value. + def validates_associated(*attr_names) + configuration = { :message => ActiveRecord::Errors.default_error_messages[:invalid], :on => :save } + configuration.update(attr_names.extract_options!) + + validates_each(attr_names, configuration) do |record, attr_name, value| + record.errors.add(attr_name, configuration[:message]) unless + (value.is_a?(Array) ? value : [value]).inject(true) { |v, r| (r.nil? || r.valid?) && v } + end + end + end + end +end \ No newline at end of file diff --git a/vendor/rails/activemodel/lib/active_model/validations/confirmation.rb b/vendor/rails/activemodel/lib/active_model/validations/confirmation.rb new file mode 100644 index 00000000..ba4a18ad --- /dev/null +++ b/vendor/rails/activemodel/lib/active_model/validations/confirmation.rb @@ -0,0 +1,44 @@ +module ActiveModel + module Validations + module ClassMethods + # Encapsulates the pattern of wanting to validate a password or email address field with a confirmation. Example: + # + # Model: + # class Person < ActiveRecord::Base + # validates_confirmation_of :user_name, :password + # validates_confirmation_of :email_address, :message => "should match confirmation" + # end + # + # View: + # <%= password_field "person", "password" %> + # <%= password_field "person", "password_confirmation" %> + # + # The added +password_confirmation+ attribute is virtual; it exists only as an in-memory attribute for validating the password. + # To achieve this, the validation adds accessors to the model for the confirmation attribute. NOTE: This check is performed + # only if +password_confirmation+ is not +nil+, and by default only on save. To require confirmation, make sure to add a presence + # check for the confirmation attribute: + # + # validates_presence_of :password_confirmation, :if => :password_changed? + # + # Configuration options: + # * :message - A custom error message (default is: "doesn't match confirmation") + # * :on - Specifies when this validation is active (default is :save, other options :create, :update) + # * :if - Specifies a method, proc or string to call to determine if the validation should + # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The + # method, proc or string should return or evaluate to a true or false value. + # * :unless - Specifies a method, proc or string to call to determine if the validation should + # not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The + # method, proc or string should return or evaluate to a true or false value. + def validates_confirmation_of(*attr_names) + configuration = { :message => ActiveRecord::Errors.default_error_messages[:confirmation], :on => :save } + configuration.update(attr_names.extract_options!) + + attr_accessor(*(attr_names.map { |n| "#{n}_confirmation" })) + + validates_each(attr_names, configuration) do |record, attr_name, value| + record.errors.add(attr_name, configuration[:message]) unless record.send("#{attr_name}_confirmation").nil? or value == record.send("#{attr_name}_confirmation") + end + end + end + end +end \ No newline at end of file diff --git a/vendor/rails/activemodel/lib/active_model/validations/exclusion.rb b/vendor/rails/activemodel/lib/active_model/validations/exclusion.rb new file mode 100644 index 00000000..f3367abc --- /dev/null +++ b/vendor/rails/activemodel/lib/active_model/validations/exclusion.rb @@ -0,0 +1,37 @@ +module ActiveModel + module Validations + module ClassMethods + # Validates that the value of the specified attribute is not in a particular enumerable object. + # + # class Person < ActiveRecord::Base + # validates_exclusion_of :username, :in => %w( admin superuser ), :message => "You don't belong here" + # validates_exclusion_of :age, :in => 30..60, :message => "This site is only for under 30 and over 60" + # validates_exclusion_of :format, :in => %w( mov avi ), :message => "extension %s is not allowed" + # end + # + # Configuration options: + # * :in - An enumerable object of items that the value shouldn't be part of + # * :message - Specifies a custom error message (default is: "is reserved") + # * :allow_nil - If set to +true+, skips this validation if the attribute is +nil+ (default is: +false+) + # * :allow_blank - If set to +true+, skips this validation if the attribute is blank (default is: +false+) + # * :if - Specifies a method, proc or string to call to determine if the validation should + # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The + # method, proc or string should return or evaluate to a true or false value. + # * :unless - Specifies a method, proc or string to call to determine if the validation should + # not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The + # method, proc or string should return or evaluate to a true or false value. + def validates_exclusion_of(*attr_names) + configuration = { :message => ActiveRecord::Errors.default_error_messages[:exclusion], :on => :save } + configuration.update(attr_names.extract_options!) + + enum = configuration[:in] || configuration[:within] + + raise(ArgumentError, "An object with the method include? is required must be supplied as the :in option of the configuration hash") unless enum.respond_to?("include?") + + validates_each(attr_names, configuration) do |record, attr_name, value| + record.errors.add(attr_name, configuration[:message] % value) if enum.include?(value) + end + end + end + end +end \ No newline at end of file diff --git a/vendor/rails/activemodel/lib/active_model/validations/format.rb b/vendor/rails/activemodel/lib/active_model/validations/format.rb new file mode 100644 index 00000000..1320ef64 --- /dev/null +++ b/vendor/rails/activemodel/lib/active_model/validations/format.rb @@ -0,0 +1,39 @@ +module ActiveModel + module Validations + module ClassMethods + # Validates whether the value of the specified attribute is of the correct form by matching it against the regular expression + # provided. + # + # class Person < ActiveRecord::Base + # validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, :on => :create + # end + # + # Note: use \A and \Z to match the start and end of the string, ^ and $ match the start/end of a line. + # + # A regular expression must be provided or else an exception will be raised. + # + # Configuration options: + # * :message - A custom error message (default is: "is invalid") + # * :allow_nil - If set to +true+, skips this validation if the attribute is +nil+ (default is: +false+) + # * :allow_blank - If set to +true+, skips this validation if the attribute is blank (default is: +false+) + # * :with - The regular expression used to validate the format with (note: must be supplied!) + # * :on - Specifies when this validation is active (default is :save, other options :create, :update) + # * :if - Specifies a method, proc or string to call to determine if the validation should + # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The + # method, proc or string should return or evaluate to a true or false value. + # * :unless - Specifies a method, proc or string to call to determine if the validation should + # not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The + # method, proc or string should return or evaluate to a true or false value. + def validates_format_of(*attr_names) + configuration = { :message => ActiveRecord::Errors.default_error_messages[:invalid], :on => :save, :with => nil } + configuration.update(attr_names.extract_options!) + + raise(ArgumentError, "A regular expression must be supplied as the :with option of the configuration hash") unless configuration[:with].is_a?(Regexp) + + validates_each(attr_names, configuration) do |record, attr_name, value| + record.errors.add(attr_name, configuration[:message]) unless value.to_s =~ configuration[:with] + end + end + end + end +end \ No newline at end of file diff --git a/vendor/rails/activemodel/lib/active_model/validations/inclusion.rb b/vendor/rails/activemodel/lib/active_model/validations/inclusion.rb new file mode 100644 index 00000000..9fc1caaa --- /dev/null +++ b/vendor/rails/activemodel/lib/active_model/validations/inclusion.rb @@ -0,0 +1,37 @@ +module ActiveModel + module Validations + module ClassMethods + # Validates whether the value of the specified attribute is available in a particular enumerable object. + # + # class Person < ActiveRecord::Base + # validates_inclusion_of :gender, :in => %w( m f ), :message => "woah! what are you then!??!!" + # validates_inclusion_of :age, :in => 0..99 + # validates_inclusion_of :format, :in => %w( jpg gif png ), :message => "extension %s is not included in the list" + # end + # + # Configuration options: + # * :in - An enumerable object of available items + # * :message - Specifies a custom error message (default is: "is not included in the list") + # * :allow_nil - If set to +true+, skips this validation if the attribute is null (default is: +false+) + # * :allow_blank - If set to +true+, skips this validation if the attribute is blank (default is: +false+) + # * :if - Specifies a method, proc or string to call to determine if the validation should + # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The + # method, proc or string should return or evaluate to a true or false value. + # * :unless - Specifies a method, proc or string to call to determine if the validation should + # not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The + # method, proc or string should return or evaluate to a true or false value. + def validates_inclusion_of(*attr_names) + configuration = { :message => ActiveRecord::Errors.default_error_messages[:inclusion], :on => :save } + configuration.update(attr_names.extract_options!) + + enum = configuration[:in] || configuration[:within] + + raise(ArgumentError, "An object with the method include? is required must be supplied as the :in option of the configuration hash") unless enum.respond_to?("include?") + + validates_each(attr_names, configuration) do |record, attr_name, value| + record.errors.add(attr_name, configuration[:message] % value) unless enum.include?(value) + end + end + end + end +end \ No newline at end of file diff --git a/vendor/rails/activemodel/lib/active_model/validations/length.rb b/vendor/rails/activemodel/lib/active_model/validations/length.rb new file mode 100644 index 00000000..673ad339 --- /dev/null +++ b/vendor/rails/activemodel/lib/active_model/validations/length.rb @@ -0,0 +1,95 @@ +module ActiveModel + module Validations + module ClassMethods + ALL_RANGE_OPTIONS = [ :is, :within, :in, :minimum, :maximum ].freeze + + # Validates that the specified attribute matches the length restrictions supplied. Only one option can be used at a time: + # + # class Person < ActiveRecord::Base + # validates_length_of :first_name, :maximum => 30 + # validates_length_of :last_name, :maximum => 30, :message => "less than %d if you don't mind" + # validates_length_of :fax, :in => 7..32, :allow_nil => true + # validates_length_of :phone, :in => 7..32, :allow_blank => true + # validates_length_of :user_name, :within => 6..20, :too_long => "pick a shorter name", :too_short => "pick a longer name" + # validates_length_of :fav_bra_size, :minimum => 1, :too_short => "please enter at least %d character" + # validates_length_of :smurf_leader, :is => 4, :message => "papa is spelled with %d characters... don't play me." + # end + # + # Configuration options: + # * :minimum - The minimum size of the attribute + # * :maximum - The maximum size of the attribute + # * :is - The exact size of the attribute + # * :within - A range specifying the minimum and maximum size of the attribute + # * :in - A synonym (or alias) for :within + # * :allow_nil - Attribute may be +nil+; skip validation. + # * :allow_blank - Attribute may be blank; skip validation. + # * :too_long - The error message if the attribute goes over the maximum (default is: "is too long (maximum is %d characters)") + # * :too_short - The error message if the attribute goes under the minimum (default is: "is too short (min is %d characters)") + # * :wrong_length - The error message if using the :is method and the attribute is the wrong size (default is: "is the wrong length (should be %d characters)") + # * :message - The error message to use for a :minimum, :maximum, or :is violation. An alias of the appropriate :too_long/too_short/wrong_length message + # * :on - Specifies when this validation is active (default is :save, other options :create, :update) + # * :if - Specifies a method, proc or string to call to determine if the validation should + # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The + # method, proc or string should return or evaluate to a true or false value. + # * :unless - Specifies a method, proc or string to call to determine if the validation should + # not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The + # method, proc or string should return or evaluate to a true or false value. + def validates_length_of(*attrs) + # Merge given options with defaults. + options = { + :too_long => ActiveRecord::Errors.default_error_messages[:too_long], + :too_short => ActiveRecord::Errors.default_error_messages[:too_short], + :wrong_length => ActiveRecord::Errors.default_error_messages[:wrong_length] + }.merge(DEFAULT_VALIDATION_OPTIONS) + options.update(attrs.extract_options!.symbolize_keys) + + # Ensure that one and only one range option is specified. + range_options = ALL_RANGE_OPTIONS & options.keys + case range_options.size + when 0 + raise ArgumentError, 'Range unspecified. Specify the :within, :maximum, :minimum, or :is option.' + when 1 + # Valid number of options; do nothing. + else + raise ArgumentError, 'Too many range options specified. Choose only one.' + end + + # Get range option and value. + option = range_options.first + option_value = options[range_options.first] + + case option + when :within, :in + raise ArgumentError, ":#{option} must be a Range" unless option_value.is_a?(Range) + + too_short = options[:too_short] % option_value.begin + too_long = options[:too_long] % option_value.end + + validates_each(attrs, options) do |record, attr, value| + value = value.split(//) if value.kind_of?(String) + if value.nil? or value.size < option_value.begin + record.errors.add(attr, too_short) + elsif value.size > option_value.end + record.errors.add(attr, too_long) + end + end + when :is, :minimum, :maximum + raise ArgumentError, ":#{option} must be a nonnegative Integer" unless option_value.is_a?(Integer) and option_value >= 0 + + # Declare different validations per option. + validity_checks = { :is => "==", :minimum => ">=", :maximum => "<=" } + message_options = { :is => :wrong_length, :minimum => :too_short, :maximum => :too_long } + + message = (options[:message] || options[message_options[option]]) % option_value + + validates_each(attrs, options) do |record, attr, value| + value = value.split(//) if value.kind_of?(String) + record.errors.add(attr, message) unless !value.nil? and value.size.method(validity_checks[option])[option_value] + end + end + end + + alias_method :validates_size_of, :validates_length_of + end + end +end \ No newline at end of file diff --git a/vendor/rails/activemodel/lib/active_model/validations/numericality.rb b/vendor/rails/activemodel/lib/active_model/validations/numericality.rb new file mode 100644 index 00000000..92ca5f40 --- /dev/null +++ b/vendor/rails/activemodel/lib/active_model/validations/numericality.rb @@ -0,0 +1,80 @@ +module ActiveModel + module Validations + module ClassMethods + ALL_NUMERICALITY_CHECKS = { :greater_than => '>', :greater_than_or_equal_to => '>=', + :equal_to => '==', :less_than => '<', :less_than_or_equal_to => '<=', + :odd => 'odd?', :even => 'even?' }.freeze + + + # Validates whether the value of the specified attribute is numeric by trying to convert it to + # a float with Kernel.Float (if integer is false) or applying it to the regular expression + # /\A[\+\-]?\d+\Z/ (if integer is true). + # + # class Person < ActiveRecord::Base + # validates_numericality_of :value, :on => :create + # end + # + # Configuration options: + # * :message - A custom error message (default is: "is not a number"). + # * :on - Specifies when this validation is active (default is :save, other options :create, :update). + # * :only_integer - Specifies whether the value has to be an integer, e.g. an integral value (default is +false+). + # * :allow_nil - Skip validation if attribute is +nil+ (default is +false+). Notice that for fixnum and float columns empty strings are converted to +nil+. + # * :greater_than - Specifies the value must be greater than the supplied value. + # * :greater_than_or_equal_to - Specifies the value must be greater than or equal the supplied value. + # * :equal_to - Specifies the value must be equal to the supplied value. + # * :less_than - Specifies the value must be less than the supplied value. + # * :less_than_or_equal_to - Specifies the value must be less than or equal the supplied value. + # * :odd - Specifies the value must be an odd number. + # * :even - Specifies the value must be an even number. + # * :if - Specifies a method, proc or string to call to determine if the validation should + # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The + # method, proc or string should return or evaluate to a true or false value. + # * :unless - Specifies a method, proc or string to call to determine if the validation should + # not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The + # method, proc or string should return or evaluate to a true or false value. + def validates_numericality_of(*attr_names) + configuration = { :on => :save, :only_integer => false, :allow_nil => false } + configuration.update(attr_names.extract_options!) + + + numericality_options = ALL_NUMERICALITY_CHECKS.keys & configuration.keys + + (numericality_options - [ :odd, :even ]).each do |option| + raise ArgumentError, ":#{option} must be a number" unless configuration[option].is_a?(Numeric) + end + + validates_each(attr_names,configuration) do |record, attr_name, value| + raw_value = record.send("#{attr_name}_before_type_cast") || value + + next if configuration[:allow_nil] and raw_value.nil? + + if configuration[:only_integer] + unless raw_value.to_s =~ /\A[+-]?\d+\Z/ + record.errors.add(attr_name, configuration[:message] || ActiveRecord::Errors.default_error_messages[:not_a_number]) + next + end + raw_value = raw_value.to_i + else + begin + raw_value = Kernel.Float(raw_value.to_s) + rescue ArgumentError, TypeError + record.errors.add(attr_name, configuration[:message] || ActiveRecord::Errors.default_error_messages[:not_a_number]) + next + end + end + + numericality_options.each do |option| + case option + when :odd, :even + record.errors.add(attr_name, configuration[:message] || ActiveRecord::Errors.default_error_messages[option]) unless raw_value.to_i.method(ALL_NUMERICALITY_CHECKS[option])[] + else + message = configuration[:message] || ActiveRecord::Errors.default_error_messages[option] + message = message % configuration[option] if configuration[option] + record.errors.add(attr_name, message) unless raw_value.method(ALL_NUMERICALITY_CHECKS[option])[configuration[option]] + end + end + end + end + end + end +end \ No newline at end of file diff --git a/vendor/rails/activemodel/lib/active_model/validations/presence.rb b/vendor/rails/activemodel/lib/active_model/validations/presence.rb new file mode 100644 index 00000000..62e46690 --- /dev/null +++ b/vendor/rails/activemodel/lib/active_model/validations/presence.rb @@ -0,0 +1,42 @@ +module ActiveModel + module Validations + module ClassMethods + # Validates that the specified attributes are not blank (as defined by Object#blank?). Happens by default on save. Example: + # + # class Person < ActiveRecord::Base + # validates_presence_of :first_name + # end + # + # The +first_name+ attribute must be in the object and it cannot be blank. + # + # If you want to validate the presence of a boolean field (where the real values are +true+ and +false+), + # you will want to use + # + # validates_inclusion_of :field_name, :in => [true, false] + # + # This is due to the way Object#blank? handles boolean values: + # + # false.blank? # => true + # + # Configuration options: + # * :message - A custom error message (default is: "can't be blank") + # * :on - Specifies when this validation is active (default is :save, other options :create, :update) + # * :if - Specifies a method, proc or string to call to determine if the validation should + # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The + # method, proc or string should return or evaluate to a true or false value. + # * :unless - Specifies a method, proc or string to call to determine if the validation should + # not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The + # method, proc or string should return or evaluate to a true or false value. + def validates_presence_of(*attr_names) + configuration = { :message => ActiveRecord::Errors.default_error_messages[:blank], :on => :save } + configuration.update(attr_names.extract_options!) + + # can't use validates_each here, because it cannot cope with nonexistent attributes, + # while errors.add_on_empty can + send(validation_method(configuration[:on]), configuration) do |record| + record.errors.add_on_blank(attr_names, configuration[:message]) + end + end + end + end +end \ No newline at end of file diff --git a/vendor/rails/activemodel/lib/active_model/validations/uniqueness.rb b/vendor/rails/activemodel/lib/active_model/validations/uniqueness.rb new file mode 100644 index 00000000..2b47c6bc --- /dev/null +++ b/vendor/rails/activemodel/lib/active_model/validations/uniqueness.rb @@ -0,0 +1,104 @@ +module ActiveModel + module Validations + module ClassMethods + # Validates whether the value of the specified attributes are unique across the system. Useful for making sure that only one user + # can be named "davidhh". + # + # class Person < ActiveRecord::Base + # validates_uniqueness_of :user_name, :scope => :account_id + # end + # + # It can also validate whether the value of the specified attributes are unique based on multiple scope parameters. For example, + # making sure that a teacher can only be on the schedule once per semester for a particular class. + # + # class TeacherSchedule < ActiveRecord::Base + # validates_uniqueness_of :teacher_id, :scope => [:semester_id, :class_id] + # end + # + # When the record is created, a check is performed to make sure that no record exists in the database with the given value for the specified + # attribute (that maps to a column). When the record is updated, the same check is made but disregarding the record itself. + # + # Because this check is performed outside the database there is still a chance that duplicate values + # will be inserted in two parallel transactions. To guarantee against this you should create a + # unique index on the field. See +add_index+ for more information. + # + # Configuration options: + # * :message - Specifies a custom error message (default is: "has already been taken") + # * :scope - One or more columns by which to limit the scope of the uniqueness constraint. + # * :case_sensitive - Looks for an exact match. Ignored by non-text columns (+false+ by default). + # * :allow_nil - If set to +true+, skips this validation if the attribute is +nil+ (default is: +false+) + # * :allow_blank - If set to +true+, skips this validation if the attribute is blank (default is: +false+) + # * :if - Specifies a method, proc or string to call to determine if the validation should + # occur (e.g. :if => :allow_validation, or :if => Proc.new { |user| user.signup_step > 2 }). The + # method, proc or string should return or evaluate to a true or false value. + # * :unless - Specifies a method, proc or string to call to determine if the validation should + # not occur (e.g. :unless => :skip_validation, or :unless => Proc.new { |user| user.signup_step <= 2 }). The + # method, proc or string should return or evaluate to a true or false value. + def validates_uniqueness_of(*attr_names) + configuration = { :message => ActiveRecord::Errors.default_error_messages[:taken] } + configuration.update(attr_names.extract_options!) + + validates_each(attr_names,configuration) do |record, attr_name, value| + # The check for an existing value should be run from a class that + # isn't abstract. This means working down from the current class + # (self), to the first non-abstract class. Since classes don't know + # their subclasses, we have to build the hierarchy between self and + # the record's class. + class_hierarchy = [record.class] + while class_hierarchy.first != self + class_hierarchy.insert(0, class_hierarchy.first.superclass) + end + + # Now we can work our way down the tree to the first non-abstract + # class (which has a database table to query from). + finder_class = class_hierarchy.detect { |klass| !klass.abstract_class? } + + if value.nil? || (configuration[:case_sensitive] || !finder_class.columns_hash[attr_name.to_s].text?) + condition_sql = "#{record.class.quoted_table_name}.#{attr_name} #{attribute_condition(value)}" + condition_params = [value] + else + # sqlite has case sensitive SELECT query, while MySQL/Postgresql don't. + # Hence, this is needed only for sqlite. + condition_sql = "LOWER(#{record.class.quoted_table_name}.#{attr_name}) #{attribute_condition(value)}" + condition_params = [value.downcase] + end + + if scope = configuration[:scope] + Array(scope).map do |scope_item| + scope_value = record.send(scope_item) + condition_sql << " AND #{record.class.quoted_table_name}.#{scope_item} #{attribute_condition(scope_value)}" + condition_params << scope_value + end + end + + unless record.new_record? + condition_sql << " AND #{record.class.quoted_table_name}.#{record.class.primary_key} <> ?" + condition_params << record.send(:id) + end + + results = finder_class.with_exclusive_scope do + connection.select_all( + construct_finder_sql( + :select => "#{attr_name}", + :from => "#{finder_class.quoted_table_name}", + :conditions => [condition_sql, *condition_params] + ) + ) + end + + unless results.length.zero? + found = true + + # As MySQL/Postgres don't have case sensitive SELECT queries, we try to find duplicate + # column in ruby when case sensitive option + if configuration[:case_sensitive] && finder_class.columns_hash[attr_name.to_s].text? + found = results.any? { |a| a[attr_name.to_s] == value } + end + + record.errors.add(attr_name, configuration[:message]) if found + end + end + end + end + end +end \ No newline at end of file diff --git a/vendor/rails/activemodel/spec/observing_spec.rb b/vendor/rails/activemodel/spec/observing_spec.rb new file mode 100644 index 00000000..1919bb59 --- /dev/null +++ b/vendor/rails/activemodel/spec/observing_spec.rb @@ -0,0 +1,120 @@ +require File.join(File.dirname(__FILE__), 'spec_helper') + +class ObservedModel < ActiveModel::Base + class Observer + end +end + +class FooObserver < ActiveModel::Observer + class << self + public :new + end + + attr_accessor :stub + + def on_spec(record) + stub.event_with(record) if stub + end +end + +class Foo < ActiveModel::Base +end + +module ActiveModel + describe Observing do + before do + ObservedModel.observers.clear + end + + it "initializes model with no cached observers" do + ObservedModel.observers.should be_empty + end + + it "stores cached observers in an array" do + ObservedModel.observers << :foo + ObservedModel.observers.should include(:foo) + end + + it "flattens array of assigned cached observers" do + ObservedModel.observers = [[:foo], :bar] + ObservedModel.observers.should include(:foo) + ObservedModel.observers.should include(:bar) + end + + it "instantiates observer names passed as strings" do + ObservedModel.observers << 'foo_observer' + FooObserver.should_receive(:instance) + ObservedModel.instantiate_observers + end + + it "instantiates observer names passed as symbols" do + ObservedModel.observers << :foo_observer + FooObserver.should_receive(:instance) + ObservedModel.instantiate_observers + end + + it "instantiates observer classes" do + ObservedModel.observers << ObservedModel::Observer + ObservedModel::Observer.should_receive(:instance) + ObservedModel.instantiate_observers + end + + it "should pass observers to subclasses" do + FooObserver.instance + bar = Class.new(Foo) + bar.count_observers.should == 1 + end + end + + describe Observer do + before do + ObservedModel.observers = :foo_observer + FooObserver.models = nil + end + + it "guesses implicit observable model name" do + FooObserver.observed_class_name.should == 'Foo' + end + + it "tracks implicit observable models" do + instance = FooObserver.new + instance.send(:observed_classes).should include(Foo) + instance.send(:observed_classes).should_not include(ObservedModel) + end + + it "tracks explicit observed model class" do + FooObserver.new.send(:observed_classes).should_not include(ObservedModel) + FooObserver.observe ObservedModel + instance = FooObserver.new + instance.send(:observed_classes).should include(ObservedModel) + end + + it "tracks explicit observed model as string" do + FooObserver.new.send(:observed_classes).should_not include(ObservedModel) + FooObserver.observe 'observed_model' + instance = FooObserver.new + instance.send(:observed_classes).should include(ObservedModel) + end + + it "tracks explicit observed model as symbol" do + FooObserver.new.send(:observed_classes).should_not include(ObservedModel) + FooObserver.observe :observed_model + instance = FooObserver.new + instance.send(:observed_classes).should include(ObservedModel) + end + + it "calls existing observer event" do + foo = Foo.new + FooObserver.instance.stub = stub!(:stub) + FooObserver.instance.stub.should_receive(:event_with).with(foo) + Foo.send(:changed) + Foo.send(:notify_observers, :on_spec, foo) + end + + it "skips nonexistent observer event" do + foo = Foo.new + Foo.send(:changed) + Foo.send(:notify_observers, :whatever, foo) + end + end +end \ No newline at end of file diff --git a/vendor/rails/activemodel/spec/spec_helper.rb b/vendor/rails/activemodel/spec/spec_helper.rb new file mode 100644 index 00000000..004fdfca --- /dev/null +++ b/vendor/rails/activemodel/spec/spec_helper.rb @@ -0,0 +1,17 @@ +ENV['LOG_NAME'] = 'spec' +$LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'vendor', 'rspec', 'lib') +$LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib') +require 'active_model' +begin + require 'spec' +rescue LoadError + require 'rubygems' + require 'spec' +end + +begin + require 'ruby-debug' + Debugger.start +rescue LoadError + # you do not know the ways of ruby-debug yet, what a shame +end \ No newline at end of file diff --git a/vendor/rails/activerecord/CHANGELOG b/vendor/rails/activerecord/CHANGELOG index 9b936863..1c7c9771 100644 --- a/vendor/rails/activerecord/CHANGELOG +++ b/vendor/rails/activerecord/CHANGELOG @@ -1,4 +1,12 @@ -*2.1.0 RC1 (May 11th, 2008)* +*2.1.0 (May 31st, 2008)* + +* Add ActiveRecord::Base.sti_name that checks ActiveRecord::Base#store_full_sti_class? and returns either the full or demodulized name. [rick] + +* Add first/last methods to associations/named_scope. Resolved #226. [Ryan Bates] + +* Added SQL escaping for :limit and :offset #288 [Aaron Bedra, Steven Bristol, Jonathan Wiess] + +* Added first/last methods to associations/named_scope. Resolved #226. [Ryan Bates] * Ensure hm:t preloading honours reflection options. Resolves #137. [Frederick Cheung] @@ -12,7 +20,7 @@ change_table :videos do |t| t.timestamps # adds created_at, updated_at - t.belongs_to :goat # add goat_id integer + t.belongs_to :goat # adds goat_id integer t.string :name, :email, :limit => 20 # adds name and email both with a 20 char limit t.remove :name, :email # removes the name and email columns end diff --git a/vendor/rails/activerecord/Rakefile b/vendor/rails/activerecord/Rakefile index 043ab6d5..fc068b16 100755 --- a/vendor/rails/activerecord/Rakefile +++ b/vendor/rails/activerecord/Rakefile @@ -171,7 +171,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', '= 2.0.991' + PKG_BUILD) + s.add_dependency('activesupport', '= 2.1.0' + PKG_BUILD) s.files.delete FIXTURES_ROOT + "/fixture_database.sqlite" s.files.delete FIXTURES_ROOT + "/fixture_database_2.sqlite" diff --git a/vendor/rails/activerecord/lib/active_record/aggregations.rb b/vendor/rails/activerecord/lib/active_record/aggregations.rb index 61446cde..a5d3a50e 100644 --- a/vendor/rails/activerecord/lib/active_record/aggregations.rb +++ b/vendor/rails/activerecord/lib/active_record/aggregations.rb @@ -92,19 +92,19 @@ module ActiveRecord # # == Writing value objects # - # Value objects are immutable and interchangeable objects that represent a given value, such as a +Money+ object representing - # $5. Two +Money+ objects both representing $5 should be equal (through methods such as == and <=> from +Comparable+ if ranking - # makes sense). This is unlike entity objects where equality is determined by identity. An entity class such as +Customer+ can + # Value objects are immutable and interchangeable objects that represent a given value, such as a Money object representing + # $5. Two Money objects both representing $5 should be equal (through methods such as == and <=> from Comparable if ranking + # makes sense). This is unlike entity objects where equality is determined by identity. An entity class such as Customer can # easily have two different objects that both have an address on Hyancintvej. Entity identity is determined by object or - # relational unique identifiers (such as primary keys). Normal ActiveRecord::Base classes are entity objects. + # relational unique identifiers (such as primary keys). Normal ActiveRecord::Base classes are entity objects. # - # It's also important to treat the value objects as immutable. Don't allow the +Money+ object to have its amount changed after - # creation. Create a new +Money+ object with the new value instead. This is exemplified by the Money#exchanged_to method that + # It's also important to treat the value objects as immutable. Don't allow the Money object to have its amount changed after + # creation. Create a new Money object with the new value instead. This is exemplified by the Money#exchanged_to method that # returns a new value object instead of changing its own values. Active Record won't persist value objects that have been # changed through means other than the writer method. # # The immutable requirement is enforced by Active Record by freezing any object assigned as a value object. Attempting to - # change it afterwards will result in a ActiveSupport::FrozenObjectError. + # change it afterwards will result in a ActiveSupport::FrozenObjectError. # # Read more about value objects on http://c2.com/cgi/wiki?ValueObject and on the dangers of not keeping value objects # immutable on http://c2.com/cgi/wiki?ValueObjectsShouldBeImmutable @@ -123,8 +123,8 @@ module ActiveRecord # # Options are: # * :class_name - specify the class name of the association. Use it only if that name can't be inferred - # from the part id. So composed_of :address will by default be linked to the +Address+ class, but - # if the real class name is +CompanyAddress+, you'll have to specify it with this option. + # from the part id. So composed_of :address will by default be linked to the Address class, but + # if the real class name is CompanyAddress, you'll have to specify it with this option. # * :mapping - specifies a number of mapping arrays (attribute, parameter) that bind an attribute name # to a constructor parameter on the value class. # * :allow_nil - specifies that the aggregate object will not be instantiated when all mapped diff --git a/vendor/rails/activerecord/lib/active_record/associations.rb b/vendor/rails/activerecord/lib/active_record/associations.rb old mode 100644 new mode 100755 index fb5f1f8a..a3d1bbba --- a/vendor/rails/activerecord/lib/active_record/associations.rb +++ b/vendor/rails/activerecord/lib/active_record/associations.rb @@ -155,7 +155,7 @@ module ActiveRecord # # == Cardinality and associations # - # ActiveRecord associations can be used to describe one-to-one, one-to-many and many-to-many + # Active Record associations can be used to describe one-to-one, one-to-many and many-to-many # relationships between models. Each model uses an association to describe its role in # the relation. The +belongs_to+ association is always used in the model that has # the foreign key. @@ -441,9 +441,9 @@ module ActiveRecord # # == Eager loading of associations # - # Eager loading is a way to find objects of a certain class and a number of named associations along with it in a single SQL call. This is + # Eager loading is a way to find objects of a certain class and a number of named associations. This is # one of the easiest ways of to prevent the dreaded 1+N problem in which fetching 100 posts that each need to display their author - # triggers 101 database queries. Through the use of eager loading, the 101 queries can be reduced to 1. Example: + # triggers 101 database queries. Through the use of eager loading, the 101 queries can be reduced to 2. Example: # # class Post < ActiveRecord::Base # belongs_to :author @@ -452,7 +452,7 @@ module ActiveRecord # # Consider the following loop using the class above: # - # for post in Post.find(:all) + # for post in Post.all # puts "Post: " + post.title # puts "Written by: " + post.author.name # puts "Last comment on: " + post.comments.first.created_on @@ -462,14 +462,15 @@ module ActiveRecord # # for post in Post.find(:all, :include => :author) # - # This references the name of the +belongs_to+ association that also used the :author symbol, so the find will now weave in a join something - # like this: LEFT OUTER JOIN authors ON authors.id = posts.author_id. Doing so will cut down the number of queries from 201 to 101. + # This references the name of the +belongs_to+ association that also used the :author symbol. After loading the posts, find + # will collect the +author_id+ from each one and load all the referenced authors with one query. Doing so will cut down the number of queries from 201 to 102. # # We can improve upon the situation further by referencing both associations in the finder with: # # 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. + # This will load all comments with a single query. This reduces the total number of queries to 3. More generally the number of queries + # will be 1 plus the number of associations named (except if some of the associations are polymorphic +belongs_to+ - see below). # # To include a deep hierarchy of associations, use a hash: # @@ -482,81 +483,91 @@ module ActiveRecord # 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. # - # Since the eager loading pulls from multiple tables, you'll have to disambiguate any column references in both conditions and orders. So - # :order => "posts.id DESC" will work while :order => "id DESC" will not. Because eager loading generates the +SELECT+ statement too, the - # :select option is ignored. + # Since only one table is loaded at a time, conditions or orders cannot reference tables other than the main one. If this is the case + # Active Record falls back to the previously used LEFT OUTER JOIN based strategy. For example + # + # Post.find(:all, :include => [ :author, :comments ], :conditions => ['comments.approved = ?', true]) # - # You can use eager loading on multiple associations from the same table, but you cannot use those associations in orders and conditions - # as there is currently not any way to disambiguate them. Eager loading will not pull additional attributes on join tables, so "rich - # associations" with +has_and_belongs_to_many+ are not a good fit for eager loading. + # will result in a single SQL query with joins along the lines of: LEFT OUTER JOIN comments ON comments.post_id = posts.id and + # LEFT OUTER JOIN authors ON authors.id = posts.author_id. Note that using conditions like this can have unintended consequences. + # In the above example posts with no approved comments are not returned at all, because the conditions apply to the SQL statement as a whole + # and not just to the association. You must disambiguate column references for this fallback to happen, for example + # :order => "author.name DESC" will work but :order => "name DESC" will not. + # + # If you do want eagerload only some members of an association it is usually more natural to :include an association + # which has conditions defined on it: + # + # class Post < ActiveRecord::Base + # has_many :approved_comments, :class_name => 'Comment', :conditions => ['approved = ?', true] + # end + # + # Post.find(:all, :include => :approved_comments) + # + # will load posts and eager load the +approved_comments+ association, which contains only those comments that have been approved. # # When eager loaded, conditions are interpolated in the context of the model class, not the model instance. Conditions are lazily interpolated # before the actual model exists. # - # Eager loading is not supported with polymorphic associations up to (and including) - # version 2.0.2. Given + # Eager loading is supported with polymorphic associations. # # class Address < ActiveRecord::Base # belongs_to :addressable, :polymorphic => true # end # - # a call that tries to eager load the addressable model + # A call that tries to eager load the addressable model # - # Address.find(:all, :include => :addressable) # INVALID + # Address.find(:all, :include => :addressable) # - # will raise ActiveRecord::EagerLoadPolymorphicError. The reason is that the parent model's type - # is a column value so its corresponding table name cannot be put in the +FROM+/+JOIN+ clauses of that early query. - # - # In versions greater than 2.0.2 eager loading in polymorphic associations is supported - # thanks to a change in the overall preloading strategy. - # - # It does work the other way around though: if the User model is addressable you can eager load - # their addresses with :include just fine, every piece needed to construct the query is known beforehand. + # will execute one query to load the addresses and load the addressables with one query per addressable type. + # For example if all the addressables are either of class Person or Company then a total of 3 queries will be executed. The list of + # addressable types to load is determined on the back of the addresses loaded. This is not supported if Active Record has to fallback + # to the previous implementation of eager loading and will raise ActiveRecord::EagerLoadPolymorphicError. The reason is that the parent + # model's type is a column value so its corresponding table name cannot be put in the +FROM+/+JOIN+ clauses of that query. # # == Table Aliasing # - # ActiveRecord uses table aliasing in the case that a table is referenced multiple times in a join. If a table is referenced only once, + # Active Record uses table aliasing in the case that a table is referenced multiple times in a join. If a table is referenced only once, # the standard table name is used. The second time, the table is aliased as #{reflection_name}_#{parent_table_name}. Indexes are appended # for any more successive uses of the table name. # - # Post.find :all, :include => :comments - # # => SELECT ... FROM posts LEFT OUTER JOIN comments ON ... - # Post.find :all, :include => :special_comments # STI - # # => SELECT ... FROM posts LEFT OUTER JOIN comments ON ... AND comments.type = 'SpecialComment' - # Post.find :all, :include => [:comments, :special_comments] # special_comments is the reflection name, posts is the parent table name - # # => SELECT ... FROM posts LEFT OUTER JOIN comments ON ... LEFT OUTER JOIN comments special_comments_posts + # Post.find :all, :joins => :comments + # # => SELECT ... FROM posts INNER JOIN comments ON ... + # Post.find :all, :joins => :special_comments # STI + # # => SELECT ... FROM posts INNER JOIN comments ON ... AND comments.type = 'SpecialComment' + # Post.find :all, :joins => [:comments, :special_comments] # special_comments is the reflection name, posts is the parent table name + # # => SELECT ... FROM posts INNER JOIN comments ON ... INNER JOIN comments special_comments_posts # # Acts as tree example: # - # TreeMixin.find :all, :include => :children - # # => SELECT ... FROM mixins LEFT OUTER JOIN mixins childrens_mixins ... - # TreeMixin.find :all, :include => {:children => :parent} # using cascading eager includes - # # => SELECT ... FROM mixins LEFT OUTER JOIN mixins childrens_mixins ... - # LEFT OUTER JOIN parents_mixins ... - # TreeMixin.find :all, :include => {:children => {:parent => :children}} - # # => SELECT ... FROM mixins LEFT OUTER JOIN mixins childrens_mixins ... - # LEFT OUTER JOIN parents_mixins ... - # LEFT OUTER JOIN mixins childrens_mixins_2 + # TreeMixin.find :all, :joins => :children + # # => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ... + # TreeMixin.find :all, :joins => {:children => :parent} + # # => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ... + # INNER JOIN parents_mixins ... + # TreeMixin.find :all, :joins => {:children => {:parent => :children}} + # # => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ... + # INNER JOIN parents_mixins ... + # INNER JOIN mixins childrens_mixins_2 # # Has and Belongs to Many join tables use the same idea, but add a _join suffix: # - # Post.find :all, :include => :categories - # # => SELECT ... FROM posts LEFT OUTER JOIN categories_posts ... LEFT OUTER JOIN categories ... - # Post.find :all, :include => {:categories => :posts} - # # => SELECT ... FROM posts LEFT OUTER JOIN categories_posts ... LEFT OUTER JOIN categories ... - # LEFT OUTER JOIN categories_posts posts_categories_join LEFT OUTER JOIN posts posts_categories - # Post.find :all, :include => {:categories => {:posts => :categories}} - # # => SELECT ... FROM posts LEFT OUTER JOIN categories_posts ... LEFT OUTER JOIN categories ... - # LEFT OUTER JOIN categories_posts posts_categories_join LEFT OUTER JOIN posts posts_categories - # LEFT OUTER JOIN categories_posts categories_posts_join LEFT OUTER JOIN categories categories_posts + # Post.find :all, :joins => :categories + # # => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ... + # Post.find :all, :joins => {:categories => :posts} + # # => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ... + # INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories + # Post.find :all, :joins => {:categories => {:posts => :categories}} + # # => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ... + # INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories + # INNER JOIN categories_posts categories_posts_join INNER JOIN categories categories_posts_2 # # If you wish to specify your own custom joins using a :joins option, those table names will take precedence over the eager associations: # - # Post.find :all, :include => :comments, :joins => "inner join comments ..." - # # => SELECT ... FROM posts LEFT OUTER JOIN comments_posts ON ... INNER JOIN comments ... - # Post.find :all, :include => [:comments, :special_comments], :joins => "inner join comments ..." - # # => SELECT ... FROM posts LEFT OUTER JOIN comments comments_posts ON ... - # LEFT OUTER JOIN comments special_comments_posts ... + # Post.find :all, :joins => :comments, :joins => "inner join comments ..." + # # => SELECT ... FROM posts INNER JOIN comments_posts ON ... INNER JOIN comments ... + # Post.find :all, :joins => [:comments, :special_comments], :joins => "inner join comments ..." + # # => SELECT ... FROM posts INNER JOIN comments comments_posts ON ... + # INNER JOIN comments special_comments_posts ... # INNER JOIN comments ... # # Table aliases are automatically truncated according to the maximum length of table identifiers according to the specific database. @@ -667,7 +678,7 @@ module ActiveRecord # * :limit - An integer determining the limit on the number of rows that should be returned. # * :offset - An integer determining the offset from where the rows should be fetched. So at 5, it would skip the first 4 rows. # * :select - By default, this is * as in SELECT * FROM, but can be changed if you, for example, want to do a join - # but not include the joined columns. + # but not include the joined columns. Do not forget to include the primary and foreign keys, otherwise it will rise an error. # * :as - Specifies a polymorphic interface (See belongs_to). # * :through - Specifies a Join Model through which to perform the query. Options for :class_name and :foreign_key # are ignored, as the association uses the source reflection. You can only use a :through query through a belongs_to @@ -747,12 +758,16 @@ module ActiveRecord # as the default :foreign_key. # * :include - Specify second-order associations that should be eager loaded when this object is loaded. # * :as - Specifies a polymorphic interface (See belongs_to). + # * :select - By default, this is * as in SELECT * FROM, but can be changed if, for example, you want to do a join + # but not include the joined columns. Do not forget to include the primary and foreign keys, otherwise it will raise an error. # * :through: Specifies a Join Model through which to perform the query. Options for :class_name and :foreign_key # are ignored, as the association uses the source reflection. You can only use a :through query through a # has_one or belongs_to association on the join model. # * :source - Specifies the source association name used by has_one :through queries. Only use it if the name cannot be # inferred from the association. has_one :favorite, :through => :favorites will look for a # :favorite on Favorite, unless a :source is given. + # * :source_type - Specifies type of the source association used by has_one :through queries where the source + # association is a polymorphic +belongs_to+. # * :readonly - If true, the associated object is readonly through the association. # # Option examples: @@ -819,8 +834,8 @@ module ActiveRecord # if the real class name is Person, you'll have to specify it with this option. # * :conditions - Specify the conditions that the associated object must meet in order to be included as a +WHERE+ # SQL fragment, such as authorized = 1. - # * :order - Specify the order in which the associated objects are returned as an ORDER BY SQL fragment, - # such as last_name, first_name DESC. + # * :select - By default, this is * as in SELECT * FROM, but can be changed if, for example, you want to do a join + # but not include the joined columns. Do not forget to include the primary and foreign keys, otherwise it will raise an error. # * :foreign_key - Specify the foreign key used for the association. By default this is guessed to be the name # of the association with an "_id" suffix. So a class that defines a belongs_to :person association will use # "person_id" as the default :foreign_key. Similarly, belongs_to :favorite_person, :class_name => "Person" @@ -838,7 +853,6 @@ module ActiveRecord # this results in a counter with +NULL+ value, which will never increment. # Note: Specifying a counter cache will add it to that model's list of readonly attributes using +attr_readonly+. # * :include - Specify second-order associations that should be eager loaded when this object is loaded. - # Not allowed if the association is polymorphic. # * :polymorphic - Specify this association is a polymorphic association by passing +true+. # Note: If you've enabled the counter cache, then you may want to add the counter cache attribute # to the +attr_readonly+ list in the associated classes (e.g. class Post; attr_readonly :comments_count; end). @@ -938,7 +952,7 @@ module ActiveRecord # # Deprecated: Any additional fields added to the join table will be placed as attributes when pulling records out through # +has_and_belongs_to_many+ associations. Records returned from join tables with additional attributes will be marked as - # +ReadOnly+ (because we can't save changes to the additional attributes). It's strongly recommended that you upgrade any + # readonly (because we can't save changes to the additional attributes). It's strongly recommended that you upgrade any # associations with attributes to a real join model (see introduction). # # Adds the following methods for retrieval and query: @@ -1009,7 +1023,7 @@ module ActiveRecord # * :limit - An integer determining the limit on the number of rows that should be returned. # * :offset - An integer determining the offset from where the rows should be fetched. So at 5, it would skip the first 4 rows. # * :select - By default, this is * as in SELECT * FROM, but can be changed if, for example, you want to do a join - # but not include the joined columns. + # but not include the joined columns. Do not forget to include the primary and foreign keys, otherwise it will raise an error. # * :readonly - If true, all the associated objects are readonly through the association. # # Option examples: @@ -1339,7 +1353,7 @@ module ActiveRecord def create_has_one_reflection(association_id, options) options.assert_valid_keys( - :class_name, :foreign_key, :remote, :conditions, :order, :include, :dependent, :counter_cache, :extend, :as, :readonly + :class_name, :foreign_key, :remote, :select, :conditions, :order, :include, :dependent, :counter_cache, :extend, :as, :readonly ) create_reflection(:has_one, association_id, options, self) @@ -1347,14 +1361,14 @@ module ActiveRecord def create_has_one_through_reflection(association_id, options) options.assert_valid_keys( - :class_name, :foreign_key, :remote, :conditions, :order, :include, :dependent, :counter_cache, :extend, :as, :through, :source, :source_type + :class_name, :foreign_key, :remote, :select, :conditions, :order, :include, :dependent, :counter_cache, :extend, :as, :through, :source, :source_type ) create_reflection(:has_one, association_id, options, self) end def create_belongs_to_reflection(association_id, options) options.assert_valid_keys( - :class_name, :foreign_key, :foreign_type, :remote, :conditions, :order, :include, :dependent, + :class_name, :foreign_key, :foreign_type, :remote, :select, :conditions, :include, :dependent, :counter_cache, :extend, :polymorphic, :readonly ) @@ -1451,9 +1465,6 @@ module ActiveRecord join_dependency.joins_for_table_name(table) }.flatten.compact.uniq - - - is_distinct = !options[:joins].blank? || include_eager_conditions?(options, tables_from_conditions) || include_eager_order?(options, tables_from_order) sql = "SELECT " if is_distinct @@ -1500,26 +1511,28 @@ module ActiveRecord order.scan(/([\.\w]+).?\./).flatten end + def selects_tables(options) + select = options[:select] + return [] unless select && select.is_a?(String) + select.scan(/"?([\.\w]+)"?.?\./).flatten + end + # Checks if the conditions reference a table other than the current model table - def include_eager_conditions?(options,tables = nil) - tables = conditions_tables(options) - return false unless tables.any? - tables.any? do |condition_table_name| - condition_table_name != table_name - end + def include_eager_conditions?(options, tables = nil) + ((tables || conditions_tables(options)) - [table_name]).any? end # Checks if the query order references a table other than the current model's table. - def include_eager_order?(options,tables = nil) - tables = order_tables(options) - return false unless tables.any? - tables.any? do |order_table_name| - order_table_name != table_name - end + def include_eager_order?(options, tables = nil) + ((tables || order_tables(options)) - [table_name]).any? + end + + def include_eager_select?(options) + (selects_tables(options) - [table_name]).any? end def references_eager_loaded_tables?(options) - include_eager_order?(options) || include_eager_conditions?(options) + include_eager_order?(options) || include_eager_conditions?(options) || include_eager_select?(options) end def using_limitable_reflections?(reflections) 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 7e47bf7b..52d2a986 100644 --- a/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb +++ b/vendor/rails/activerecord/lib/active_record/associations/association_collection.rb @@ -48,6 +48,26 @@ module ActiveRecord end end + # Fetches the first one using SQL if possible. + def first(*args) + if fetch_first_or_last_using_find? args + find(:first, *args) + else + load_target unless loaded? + @target.first(*args) + end + end + + # Fetches the last one using SQL if possible. + def last(*args) + if fetch_first_or_last_using_find? args + find(:last, *args) + else + load_target unless loaded? + @target.last(*args) + end + end + def to_ary load_target @target.to_ary @@ -146,12 +166,18 @@ module ActiveRecord if attrs.is_a?(Array) attrs.collect { |attr| create(attr) } else - create_record(attrs) { |record| record.save } + create_record(attrs) do |record| + yield(record) if block_given? + record.save + end end end def create!(attrs = {}) - create_record(attrs) { |record| record.save! } + create_record(attrs) do |record| + yield(record) if block_given? + record.save! + end end # Returns the size of the collection by executing a SELECT COUNT(*) query if the collection hasn't been loaded and @@ -330,7 +356,10 @@ module ActiveRecord raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved" end end - + + def fetch_first_or_last_using_find?(args) + args.first.kind_of?(Hash) || !(loaded? || @owner.new_record? || @reflection.options[:finder_sql] || !@target.blank? || args.first.kind_of?(Integer)) + end end end end diff --git a/vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb b/vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb index 68503a3c..11c64243 100644 --- a/vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb +++ b/vendor/rails/activerecord/lib/active_record/associations/association_proxy.rb @@ -49,7 +49,7 @@ module ActiveRecord alias_method :proxy_respond_to?, :respond_to? alias_method :proxy_extend, :extend delegate :to_param, :to => :proxy_target - instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|proxy_)/ } + instance_methods.each { |m| undef_method m unless m =~ /(^__|^nil\?$|^send$|proxy_|^object_id$)/ } def initialize(owner, reflection) @owner, @reflection = owner, reflection @@ -210,7 +210,8 @@ module ActiveRecord def raise_on_type_mismatch(record) unless record.is_a?(@reflection.klass) - raise ActiveRecord::AssociationTypeMismatch, "#{@reflection.klass} expected, got #{record.class}" + message = "#{@reflection.class_name}(##{@reflection.klass.object_id}) expected, got #{record.class}(##{record.class.object_id})" + raise ActiveRecord::AssociationTypeMismatch, message end end diff --git a/vendor/rails/activerecord/lib/active_record/associations/belongs_to_association.rb b/vendor/rails/activerecord/lib/active_record/associations/belongs_to_association.rb old mode 100644 new mode 100755 index 9ff3f135..7c28cbdd --- a/vendor/rails/activerecord/lib/active_record/associations/belongs_to_association.rb +++ b/vendor/rails/activerecord/lib/active_record/associations/belongs_to_association.rb @@ -42,10 +42,11 @@ module ActiveRecord private def find_target @reflection.klass.find( - @owner[@reflection.primary_key_name], + @owner[@reflection.primary_key_name], + :select => @reflection.options[:select], :conditions => conditions, :include => @reflection.options[:include], - :readonly => @reflection.options[:readonly] + :readonly => @reflection.options[:readonly] ) end diff --git a/vendor/rails/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb b/vendor/rails/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb old mode 100644 new mode 100755 index 9549b959..d8146daa --- a/vendor/rails/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb +++ b/vendor/rails/activerecord/lib/active_record/associations/belongs_to_polymorphic_association.rb @@ -7,10 +7,8 @@ module ActiveRecord else @target = (AssociationProxy === record ? record.target : record) - unless record.new_record? - @owner[@reflection.primary_key_name] = record.id - @owner[@reflection.options[:foreign_type]] = record.class.base_class.name.to_s - end + @owner[@reflection.primary_key_name] = record.id + @owner[@reflection.options[:foreign_type]] = record.class.base_class.name.to_s @updated = true end @@ -29,12 +27,13 @@ module ActiveRecord if @reflection.options[:conditions] association_class.find( - @owner[@reflection.primary_key_name], + @owner[@reflection.primary_key_name], + :select => @reflection.options[:select], :conditions => conditions, :include => @reflection.options[:include] ) else - association_class.find(@owner[@reflection.primary_key_name], :include => @reflection.options[:include]) + association_class.find(@owner[@reflection.primary_key_name], :select => @reflection.options[:select], :include => @reflection.options[:include]) 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 963a9384..f584a97c 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 @@ -9,7 +9,7 @@ module ActiveRecord @reflection.klass.count_by_sql(@finder_sql) else column_name, options = @reflection.klass.send(:construct_count_options_from_args, *args) - options[:conditions] = options[:conditions].nil? ? + options[:conditions] = options[:conditions].blank? ? @finder_sql : @finder_sql + " AND (#{sanitize_sql(options[:conditions])})" options[:include] ||= @reflection.options[:include] 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 f6836696..52ced36d 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 @@ -34,7 +34,7 @@ module ActiveRecord def count(*args) column_name, options = @reflection.klass.send(:construct_count_options_from_args, *args) if @reflection.options[:uniq] - # This is needed because 'SELECT count(DISTINCT *)..' is not valid sql statement. + # This is needed because 'SELECT count(DISTINCT *)..' is not valid SQL statement. column_name = "#{@reflection.quoted_table_name}.#{@reflection.klass.primary_key}" if column_name == :all options.merge!(:distinct => true) end @@ -237,7 +237,7 @@ module ActiveRecord end def build_sti_condition - "#{@reflection.through_reflection.quoted_table_name}.#{@reflection.through_reflection.klass.inheritance_column} = #{@reflection.klass.quote_value(@reflection.through_reflection.klass.name.demodulize)}" + "#{@reflection.through_reflection.quoted_table_name}.#{@reflection.through_reflection.klass.inheritance_column} = #{@reflection.klass.quote_value(@reflection.through_reflection.klass.sti_name)}" end alias_method :sql_conditions, :conditions diff --git a/vendor/rails/activerecord/lib/active_record/associations/has_one_association.rb b/vendor/rails/activerecord/lib/active_record/associations/has_one_association.rb old mode 100644 new mode 100755 index 3ff9fe3b..c2b3503e --- a/vendor/rails/activerecord/lib/active_record/associations/has_one_association.rb +++ b/vendor/rails/activerecord/lib/active_record/associations/has_one_association.rb @@ -51,10 +51,11 @@ module ActiveRecord private def find_target @reflection.klass.find(:first, - :conditions => @finder_sql, + :conditions => @finder_sql, + :select => @reflection.options[:select], :order => @reflection.options[:order], :include => @reflection.options[:include], - :readonly => @reflection.options[:readonly] + :readonly => @reflection.options[:readonly] ) end diff --git a/vendor/rails/activerecord/lib/active_record/attribute_methods.rb b/vendor/rails/activerecord/lib/active_record/attribute_methods.rb index 2db27226..fab16a44 100644 --- a/vendor/rails/activerecord/lib/active_record/attribute_methods.rb +++ b/vendor/rails/activerecord/lib/active_record/attribute_methods.rb @@ -16,16 +16,20 @@ module ActiveRecord # Declare and check for suffixed attribute methods. module ClassMethods - # Declare a method available for all attributes with the given suffix. - # Uses method_missing and respond_to? to rewrite the method + # Declares a method available for all attributes with the given suffix. + # Uses +method_missing+ and respond_to? to rewrite the method + # # #{attr}#{suffix}(*args, &block) + # # to + # # attribute#{suffix}(#{attr}, *args, &block) # - # An attribute#{suffix} instance method must exist and accept at least - # the attr argument. + # An attribute#{suffix} instance method must exist and accept at least + # the +attr+ argument. # # For example: + # # class Person < ActiveRecord::Base # attribute_method_suffix '_changed?' # @@ -60,8 +64,8 @@ module ActiveRecord !generated_methods.empty? end - # generates all the attribute related methods for columns in the database - # accessors, mutators and query methods + # Generates all the attribute related methods for columns in the database + # accessors, mutators and query methods. def define_attribute_methods return if generated_methods? columns_hash.each do |name, column| @@ -89,8 +93,9 @@ module ActiveRecord end end - # Check to see if the method is defined in the model or any of its subclasses that also derive from ActiveRecord. - # Raise DangerousAttributeError if the method is defined by ActiveRecord though. + # Checks whether the method is defined in the model or any of its subclasses + # that also derive from Active Record. Raises DangerousAttributeError if the + # method is defined by Active Record though. def instance_method_already_implemented?(method_name) method_name = method_name.to_s return true if method_name =~ /^id(=$|\?$|$)/ @@ -104,17 +109,19 @@ module ActiveRecord # +cache_attributes+ allows you to declare which converted attribute values should # be cached. Usually caching only pays off for attributes with expensive conversion - # methods, like date columns (e.g. created_at, updated_at). + # methods, like time related columns (e.g. +created_at+, +updated_at+). def cache_attributes(*attribute_names) attribute_names.each {|attr| cached_attributes << attr.to_s} end - # returns the attributes where + # Returns the attributes which are cached. By default time related columns + # with datatype :datetime, :timestamp, :time, :date are cached. def cached_attributes @cached_attributes ||= columns.select{|c| attribute_types_cached_by_default.include?(c.type)}.map(&:name).to_set end + # Returns +true+ if the provided attribute is being cached. def cache_attribute?(attr_name) cached_attributes.include?(attr_name) end @@ -155,6 +162,8 @@ module ActiveRecord evaluate_attribute_method attr_name, "def #{attr_name}; unserialize_attribute('#{attr_name}'); end" end + # Defined for all +datetime+ and +timestamp+ attributes when +time_zone_aware_attributes+ are enabled. + # This enhanced read method automatically converts the UTC time stored in the database to the time zone stored in Time.zone. def define_read_method_for_time_zone_conversion(attr_name) method_body = <<-EOV def #{attr_name}(reload = false) @@ -167,7 +176,7 @@ module ActiveRecord evaluate_attribute_method attr_name, method_body end - # Define an attribute ? method. + # Defines a predicate method attr_name?. def define_question_method(attr_name) evaluate_attribute_method attr_name, "def #{attr_name}?; query_attribute('#{attr_name}'); end", "#{attr_name}?" end @@ -176,6 +185,8 @@ module ActiveRecord evaluate_attribute_method attr_name, "def #{attr_name}=(new_value);write_attribute('#{attr_name}', new_value);end", "#{attr_name}=" end + # Defined for all +datetime+ and +timestamp+ attributes when +time_zone_aware_attributes+ are enabled. + # This enhanced write method will automatically convert the time passed to it to the zone stored in Time.zone. def define_write_method_for_time_zone_conversion(attr_name) method_body = <<-EOV def #{attr_name}=(time) @@ -210,14 +221,14 @@ module ActiveRecord end # ClassMethods - # Allows access to the object attributes, which are held in the @attributes hash, as though they + # Allows access to the object attributes, which are held in the @attributes hash, as though they # were first-class methods. So a Person class with a name attribute can use Person#name and # Person#name= and never directly use the attributes hash -- except for multiple assigns with # ActiveRecord#attributes=. A Milestone class can also ask Milestone#completed? to test that - # the completed attribute is not nil or 0. + # the completed attribute is not +nil+ or 0. # # It's also possible to instantiate related objects, so a Client class belonging to the clients - # table with a master_id foreign key can instantiate master through Client#master. + # table with a +master_id+ foreign key can instantiate master through Client#master. def method_missing(method_id, *args, &block) method_name = method_id.to_s @@ -288,7 +299,7 @@ module ActiveRecord # Updates the attribute identified by attr_name with the specified +value+. Empty strings for fixnum and float - # columns are turned into nil. + # columns are turned into +nil+. def write_attribute(attr_name, value) attr_name = attr_name.to_s @attributes_cache.delete(attr_name) @@ -319,8 +330,9 @@ module ActiveRecord end end - # A Person object with a name attribute can ask person.respond_to?("name"), person.respond_to?("name="), and - # person.respond_to?("name?") which will all return true. + # A Person object with a name attribute can ask person.respond_to?("name"), + # person.respond_to?("name="), and person.respond_to?("name?") + # which will all return +true+. alias :respond_to_without_attributes? :respond_to? def respond_to?(method, include_priv = false) method_name = method.to_s diff --git a/vendor/rails/activerecord/lib/active_record/base.rb b/vendor/rails/activerecord/lib/active_record/base.rb index 392d1870..92a24ecc 100755 --- a/vendor/rails/activerecord/lib/active_record/base.rb +++ b/vendor/rails/activerecord/lib/active_record/base.rb @@ -2,7 +2,7 @@ require 'yaml' require 'set' module ActiveRecord #:nodoc: - # Generic ActiveRecord exception class. + # Generic Active Record exception class. class ActiveRecordError < StandardError end @@ -30,19 +30,19 @@ module ActiveRecord #:nodoc: class SerializationTypeMismatch < ActiveRecordError end - # Raised when adapter not specified on connection (or configuration file config/database.yml misses adapter field). + # Raised when adapter not specified on connection (or configuration file config/database.yml misses adapter field). class AdapterNotSpecified < ActiveRecordError end - # Raised when ActiveRecord cannot find database adapter specified in config/database.yml or programmatically. + # Raised when Active Record cannot find database adapter specified in config/database.yml or programmatically. class AdapterNotFound < ActiveRecordError end - # Raised when connection to the database could not been established (for example when connection= is given a nil object). + # Raised when connection to the database could not been established (for example when connection= is given a nil object). class ConnectionNotEstablished < ActiveRecordError end - # Raised when ActiveRecord cannot find record by given id or set of ids. + # Raised when Active Record cannot find record by given id or set of ids. class RecordNotFound < ActiveRecordError end @@ -70,7 +70,7 @@ module ActiveRecord #:nodoc: # instantiation, for example, when two users edit the same wiki page and one starts editing and saves # the page before the other. # - # Read more about optimistic locking in +ActiveRecord::Locking+ module RDoc. + # Read more about optimistic locking in ActiveRecord::Locking module RDoc. class StaleObjectError < ActiveRecordError end @@ -83,12 +83,12 @@ module ActiveRecord #:nodoc: class ReadOnlyRecord < ActiveRecordError end - # Used by ActiveRecord transaction mechanism to distinguish rollback from other exceptional situations. + # Used by Active Record transaction mechanism to distinguish rollback from other exceptional situations. # You can use it to roll your transaction back explicitly in the block passed to +transaction+ method. class Rollback < ActiveRecordError end - # Raised when attribute has a name reserved by ActiveRecord (when attribute has name of one of ActiveRecord instance methods). + # Raised when attribute has a name reserved by Active Record (when attribute has name of one of Active Record instance methods). class DangerousAttributeError < ActiveRecordError end @@ -200,7 +200,7 @@ module ActiveRecord #:nodoc: # # All column values are automatically available through basic accessors on the Active Record object, but sometimes you # want to specialize this behavior. This can be done by overwriting the default accessors (using the same - # name as the attribute) and calling read_attribute(attr_name) and write_attribute(attr_name, value) to actually change things. + # name as the attribute) and calling read_attribute(attr_name) and write_attribute(attr_name, value) to actually change things. # Example: # # class Song < ActiveRecord::Base @@ -215,8 +215,8 @@ module ActiveRecord #:nodoc: # end # end # - # You can alternatively use self[:attribute]=(value) and self[:attribute] instead of write_attribute(:attribute, value) and - # read_attribute(:attribute) as a shorter form. + # You can alternatively use self[:attribute]=(value) and self[:attribute] instead of write_attribute(:attribute, value) and + # read_attribute(:attribute) as a shorter form. # # == Attribute query methods # @@ -236,7 +236,7 @@ module ActiveRecord #:nodoc: # # Sometimes you want to be able to read the raw attribute data without having the column-determined typecast run its course first. # That can be done by using the _before_type_cast accessors that all attributes have. For example, if your Account model - # has a balance attribute, you can call account.balance_before_type_cast or account.id_before_type_cast. + # has a balance attribute, you can call account.balance_before_type_cast or account.id_before_type_cast. # # This is especially useful in validation situations where the user might supply a string for an integer field and you want to display # the original string back in an error message. Accessing the attribute normally would typecast the string to 0, which isn't what you @@ -245,8 +245,8 @@ module ActiveRecord #:nodoc: # == Dynamic attribute-based finders # # Dynamic attribute-based finders are a cleaner way of getting (and/or creating) objects by simple queries without turning to SQL. They work by - # appending the name of an attribute to find_by_ or find_all_by_, so you get finders like Person.find_by_user_name, - # Person.find_all_by_last_name, Payment.find_by_transaction_id. So instead of writing + # appending the name of an attribute to find_by_ or find_all_by_, so you get finders like Person.find_by_user_name, + # Person.find_all_by_last_name, and Payment.find_by_transaction_id. So instead of writing # Person.find(:first, :conditions => ["user_name = ?", user_name]), you just do Person.find_by_user_name(user_name). # And instead of writing Person.find(:all, :conditions => ["last_name = ?", last_name]), you just do Person.find_all_by_last_name(last_name). # @@ -255,8 +255,8 @@ module ActiveRecord #:nodoc: # Person.find(:first, :conditions => ["user_name = ? AND password = ?", user_name, password]), you just do # Person.find_by_user_name_and_password(user_name, password). # - # It's even possible to use all the additional parameters to find. For example, the full interface for Payment.find_all_by_amount - # is actually Payment.find_all_by_amount(amount, options). And the full interface to Person.find_by_user_name is + # It's even possible to use all the additional parameters to find. For example, the full interface for Payment.find_all_by_amount + # is actually Payment.find_all_by_amount(amount, options). And the full interface to Person.find_by_user_name is # actually Person.find_by_user_name(user_name, options). So you could call Payment.find_all_by_amount(50, :order => "created_on"). # # The same dynamic finder style can be used to create the object if it doesn't already exist. This dynamic finder is called with @@ -316,8 +316,8 @@ module ActiveRecord #:nodoc: # class Client < Company; end # class PriorityClient < Client; end # - # When you do Firm.create(:name => "37signals"), this record will be saved in the companies table with type = "Firm". You can then - # fetch this row again using Company.find(:first, "name = '37signals'") and it will return a Firm object. + # When you do Firm.create(:name => "37signals"), this record will be saved in the companies table with type = "Firm". You can then + # fetch this row again using Company.find(:first, "name = '37signals'") and it will return a Firm object. # # If you don't have a type column defined in your table, single-table inheritance won't be triggered. In that case, it'll work just # like normal subclasses with no special magic for differentiating between them or reloading the right type with find. @@ -329,8 +329,8 @@ module ActiveRecord #:nodoc: # # Connections are usually created through ActiveRecord::Base.establish_connection and retrieved by ActiveRecord::Base.connection. # All classes inheriting from ActiveRecord::Base will use this connection. But you can also set a class-specific connection. - # For example, if Course is an ActiveRecord::Base, but resides in a different database, you can just say Course.establish_connection - # and Course *and all its subclasses* will use this connection instead. + # For example, if Course is an ActiveRecord::Base, but resides in a different database, you can just say Course.establish_connection + # and Course and all of its subclasses will use this connection instead. # # This feature is implemented by keeping a connection pool in ActiveRecord::Base that is a Hash indexed by the class. If a connection is # requested, the retrieve_connection method will go up the class-hierarchy until a connection is found in the connection pool. @@ -407,7 +407,7 @@ module ActiveRecord #:nodoc: @@table_name_suffix = "" # Indicates whether table names should be the pluralized versions of the corresponding class names. - # If true, the default table name for a +Product+ class will be +products+. If false, it would just be +product+. + # If true, the default table name for a Product class will be +products+. If false, it would just be +product+. # See table_name for the full rules on table/class naming. This is true, by default. cattr_accessor :pluralize_table_names, :instance_writer => false @@pluralize_table_names = true @@ -438,40 +438,52 @@ module ActiveRecord #:nodoc: # adapters for, e.g., your development and test environments. cattr_accessor :schema_format , :instance_writer => false @@schema_format = :ruby - + + # Determine whether to store the full constant name including namespace when using STI + superclass_delegating_accessor :store_full_sti_class + self.store_full_sti_class = false + class << self # Class methods # Find operates with four different retrieval approaches: # - # * Find by id: This can either be a specific id (1), a list of ids (1, 5, 6), or an array of ids ([5, 6, 10]). + # * Find by id - This can either be a specific id (1), a list of ids (1, 5, 6), or an array of ids ([5, 6, 10]). # If no record can be found for all of the listed ids, then RecordNotFound will be raised. - # * Find first: This will return the first record matched by the options used. These options can either be specific - # conditions or merely an order. If no record can be matched, nil is returned. - # * Find last: This will return the last record matched by the options used. These options can either be specific - # conditions or merely an order. If no record can be matched, nil is returned. - # * Find all: This will return all the records matched by the options used. If no records are found, an empty array is returned. + # * Find first - This will return the first record matched by the options used. These options can either be specific + # conditions or merely an order. If no record can be matched, +nil+ is returned. Use + # Model.find(:first, *args) or its shortcut Model.first(*args). + # * Find last - This will return the last record matched by the options used. These options can either be specific + # conditions or merely an order. If no record can be matched, +nil+ is returned. Use + # Model.find(:last, *args) or its shortcut Model.last(*args). + # * Find all - This will return all the records matched by the options used. + # If no records are found, an empty array is returned. Use + # Model.find(:all, *args) or its shortcut Model.all(*args). # - # All approaches accept an options hash as their last parameter. The options are: + # All approaches accept an options hash as their last parameter. # - # * :conditions: An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. See conditions in the intro. - # * :order: An SQL fragment like "created_at DESC, name". - # * :group: An attribute name by which the result should be grouped. Uses the GROUP BY SQL-clause. - # * :limit: An integer determining the limit on the number of rows that should be returned. - # * :offset: An integer determining the offset from where the rows should be fetched. So at 5, it would skip rows 0 through 4. - # * :joins: Either an SQL fragment for additional joins like "LEFT JOIN comments ON comments.post_id = id" (rarely needed) - # or named associations in the same form used for the :include option, which will perform an INNER JOIN on the associated table(s). + # ==== Attributes + # + # * :conditions - An SQL fragment like "administrator = 1" or [ "user_name = ?", username ]. See conditions in the intro. + # * :order - An SQL fragment like "created_at DESC, name". + # * :group - An attribute name by which the result should be grouped. Uses the GROUP BY SQL-clause. + # * :limit - An integer determining the limit on the number of rows that should be returned. + # * :offset - An integer determining the offset from where the rows should be fetched. So at 5, it would skip rows 0 through 4. + # * :joins - Either an SQL fragment for additional joins like "LEFT JOIN comments ON comments.post_id = id" (rarely needed) + # or named associations in the same form used for the :include option, which will perform an INNER JOIN on the associated table(s). # If the value is a string, then the records will be returned read-only since they will have attributes that do not correspond to the table's columns. # Pass :readonly => false to override. - # * :include: Names associations that should be loaded alongside using LEFT OUTER JOINs. The symbols named refer + # * :include - Names associations that should be loaded alongside. The symbols named refer # to already defined associations. See eager loading under Associations. - # * :select: By default, this is * as in SELECT * FROM, but can be changed if you, for example, want to do a join but not + # * :select - By default, this is "*" as in "SELECT * FROM", but can be changed if you, for example, want to do a join but not # include the joined columns. - # * :from: By default, this is the table name of the class, but can be changed to an alternate table name (or even the name + # * :from - By default, this is the table name of the class, but can be changed to an alternate table name (or even the name # of a database view). - # * :readonly: Mark the returned records read-only so they cannot be saved or updated. - # * :lock: An SQL fragment like "FOR UPDATE" or "LOCK IN SHARE MODE". + # * :readonly - Mark the returned records read-only so they cannot be saved or updated. + # * :lock - An SQL fragment like "FOR UPDATE" or "LOCK IN SHARE MODE". # :lock => true gives connection's default exclusive lock, usually "FOR UPDATE". # - # Examples for find by id: + # ==== Examples + # + # # find by id # Person.find(1) # returns the object for ID = 1 # Person.find(1, 2, 6) # returns an array for objects with IDs in (1, 2, 6) # Person.find([7, 17]) # returns an array for objects with IDs in (7, 17) @@ -482,17 +494,19 @@ module ActiveRecord #:nodoc: # provide since database rows are unordered. Give an explicit :order # to ensure the results are sorted. # - # Examples for find first: + # ==== Examples + # + # # find first # Person.find(:first) # returns the first object fetched by SELECT * FROM people # Person.find(:first, :conditions => [ "user_name = ?", user_name]) # Person.find(:first, :order => "created_on DESC", :offset => 5) # - # Examples for find last: + # # find last # Person.find(:last) # returns the last object fetched by SELECT * FROM people # Person.find(:last, :conditions => [ "user_name = ?", user_name]) # Person.find(:last, :order => "created_on DESC", :offset => 5) # - # Examples for find all: + # # find all # Person.find(:all) # returns an array of objects for all the rows fetched by SELECT * FROM people # Person.find(:all, :conditions => [ "category IN (?)", categories], :limit => 50) # Person.find(:all, :conditions => { :friends => ["Bob", "Steve", "Fred"] } @@ -500,11 +514,12 @@ module ActiveRecord #:nodoc: # Person.find(:all, :include => [ :account, :friends ]) # Person.find(:all, :group => "category") # - # Example for find with a lock. Imagine two concurrent transactions: - # each will read person.visits == 2, add 1 to it, and save, resulting - # in two saves of person.visits = 3. By locking the row, the second + # Example for find with a lock: Imagine two concurrent transactions: + # each will read person.visits == 2, add 1 to it, and save, resulting + # in two saves of person.visits = 3. By locking the row, the second # transaction has to wait until the first is finished; we get the - # expected person.visits == 4. + # expected person.visits == 4. + # # Person.transaction do # person = Person.find(1, :lock => true) # person.visits += 1 @@ -522,27 +537,26 @@ module ActiveRecord #:nodoc: else find_from_ids(args, options) end end - - # This is an alias for find(:first). You can pass in all the same arguments to this method as you can - # to find(:first) + + # A convenience wrapper for find(:first, *args). You can pass in all the + # same arguments to this method as you can to find(:first). def first(*args) find(:first, *args) end - # This is an alias for find(:last). You can pass in all the same arguments to this method as you can - # to find(:last) + # A convenience wrapper for find(:last, *args). You can pass in all the + # same arguments to this method as you can to find(:last). def last(*args) find(:last, *args) end - + # This is an alias for find(:all). You can pass in all the same arguments to this method as you can # to find(:all) def all(*args) find(:all, *args) end - - # - # Executes a custom sql query against your database and returns all the results. The results will + + # Executes a custom SQL query against your database and returns all the results. The results will # be returned as an array with columns requested encapsulated as attributes of the model you call # this method from. If you call +Product.find_by_sql+ then the results will be returned in a Product # object with the attributes you specified in the SQL query. @@ -551,13 +565,13 @@ module ActiveRecord #:nodoc: # SELECT will be attributes of the model, whether or not they are columns of the corresponding # table. # - # The +sql+ parameter is a full sql query as a string. It will be called as is, there will be + # The +sql+ parameter is a full SQL query as a string. It will be called as is, there will be # no database agnostic conversions performed. This should be a last resort because using, for example, # MySQL specific terms will lock you to using that particular database engine or require you to # change your call if you switch engines # # ==== Examples - # # A simple sql query spanning multiple tables + # # A simple SQL query spanning multiple tables # Post.find_by_sql "SELECT p.title, c.author FROM posts p, comments c WHERE p.id = c.post_id" # > [#"Ruby Meetup", "first_name"=>"Quentin"}>, ...] # @@ -587,10 +601,10 @@ module ActiveRecord #:nodoc: def exists?(id_or_conditions) connection.select_all( construct_finder_sql( - :select => "#{quoted_table_name}.#{primary_key}", - :conditions => expand_id_conditions(id_or_conditions), + :select => "#{quoted_table_name}.#{primary_key}", + :conditions => expand_id_conditions(id_or_conditions), :limit => 1 - ), + ), "#{name} Exists" ).size > 0 end @@ -616,7 +630,7 @@ module ActiveRecord #:nodoc: # # Creating an Array of new objects using a block, where the block is executed for each object: # User.create([{ :first_name => 'Jamie' }, { :first_name => 'Jeremy' }]) do |u| # u.is_admin = false - # end + # end def create(attributes = nil, &block) if attributes.is_a?(Array) attributes.collect { |attr| create(attr, &block) } @@ -856,9 +870,15 @@ module ActiveRecord #:nodoc: end - # Attributes named in this macro are protected from mass-assignment, such as new(attributes) and - # attributes=(attributes). Their assignment will simply be ignored. Instead, you can use the direct writer - # methods to do assignment. This is meant to protect sensitive attributes from being overwritten by URL/form hackers. Example: + # Attributes named in this macro are protected from mass-assignment, + # such as new(attributes), + # update_attributes(attributes), or + # attributes=(attributes). + # + # Mass-assignment to these attributes will simply be ignored, to assign + # to them you can use direct writer methods. This is meant to protect + # sensitive attributes from being overwritten by malicious users + # tampering with URLs or forms. # # class Customer < ActiveRecord::Base # attr_protected :credit_rating @@ -872,7 +892,8 @@ module ActiveRecord #:nodoc: # customer.credit_rating = "Average" # customer.credit_rating # => "Average" # - # To start from an all-closed default and enable attributes as needed, have a look at attr_accessible. + # To start from an all-closed default and enable attributes as needed, + # have a look at +attr_accessible+. def attr_protected(*attributes) write_inheritable_attribute("attr_protected", Set.new(attributes.map(&:to_s)) + (protected_attributes || [])) end @@ -882,19 +903,18 @@ module ActiveRecord #:nodoc: read_inheritable_attribute("attr_protected") end - # Similar to the attr_protected macro, this protects attributes of your model from mass-assignment, - # such as new(attributes) and attributes=(attributes) - # however, it does it in the opposite way. This locks all attributes and only allows access to the - # attributes specified. Assignment to attributes not in this list will be ignored and need to be set - # using the direct writer methods instead. This is meant to protect sensitive attributes from being - # overwritten by URL/form hackers. If you'd rather start from an all-open default and restrict - # attributes as needed, have a look at attr_protected. + # Specifies a white list of model attributes that can be set via + # mass-assignment, such as new(attributes), + # update_attributes(attributes), or + # attributes=(attributes) # - # ==== Attributes - # - # * *attributes A comma separated list of symbols that represent columns _not_ to be protected - # - # ==== Examples + # This is the opposite of the +attr_protected+ macro: Mass-assignment + # will only set attributes in this list, to assign to the rest of + # attributes you can use direct writer methods. This is meant to protect + # sensitive attributes from being overwritten by malicious users + # tampering with URLs or forms. If you'd rather start from an all-open + # default and restrict attributes as needed, have a look at + # +attr_protected+. # # class Customer < ActiveRecord::Base # attr_accessible :name, :nickname @@ -929,7 +949,7 @@ module ActiveRecord #:nodoc: # If you have an attribute that needs to be saved to the database as an object, and retrieved as the same object, # then specify the name of that attribute using this method and it will be handled automatically. # 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. + # class on retrieval or SerializationTypeMismatch will be raised. # # ==== Attributes # @@ -952,12 +972,14 @@ module ActiveRecord #:nodoc: # Guesses the table name (in forced lower-case) based on the name of the class in the inheritance hierarchy descending - # directly from ActiveRecord. So if the hierarchy looks like: Reply < Message < ActiveRecord, then Message is used + # directly from ActiveRecord::Base. So if the hierarchy looks like: Reply < Message < ActiveRecord::Base, then Message is used # to guess the table name even when called on Reply. The rules used to do the guess are handled by the Inflector class # in Active Support, which knows almost all common English inflections. You can add new inflections in config/initializers/inflections.rb. # # Nested classes are given table names prefixed by the singular form of - # the parent's table name. Enclosing modules are not considered. Examples: + # the parent's table name. Enclosing modules are not considered. + # + # ==== Examples # # class Invoice < ActiveRecord::Base; end; # file class table_name @@ -971,8 +993,8 @@ module ActiveRecord #:nodoc: # file class table_name # invoice/lineitem.rb Invoice::Lineitem lineitems # - # Additionally, the class-level table_name_prefix is prepended and the - # table_name_suffix is appended. So if you have "myapp_" as a prefix, + # Additionally, the class-level +table_name_prefix+ is prepended and the + # +table_name_suffix+ is appended. So if you have "myapp_" as a prefix, # the table name guess for an Invoice class becomes "myapp_invoices". # Invoice::Lineitem becomes "myapp_invoice_lineitems". # @@ -1023,9 +1045,9 @@ module ActiveRecord #:nodoc: key = 'id' case primary_key_prefix_type when :table_name - key = Inflector.foreign_key(base_name, false) + key = base_name.to_s.foreign_key(false) when :table_name_with_underscore - key = Inflector.foreign_key(base_name) + key = base_name.to_s.foreign_key end key end @@ -1051,8 +1073,6 @@ module ActiveRecord #:nodoc: # Sets the table name to use to the given value, or (if the value # is nil or false) to the value returned by the given block. # - # Example: - # # class Project < ActiveRecord::Base # set_table_name "project" # end @@ -1065,8 +1085,6 @@ module ActiveRecord #:nodoc: # or (if the value is nil or false) to the value returned by the given # block. # - # Example: - # # class Project < ActiveRecord::Base # set_primary_key "sysid" # end @@ -1079,8 +1097,6 @@ module ActiveRecord #:nodoc: # or (if the value # is nil or false) to the value returned by the # given block. # - # Example: - # # class Project < ActiveRecord::Base # set_inheritance_column do # original_inheritance_column + "_id" @@ -1102,8 +1118,6 @@ module ActiveRecord #:nodoc: # If a sequence name is not explicitly set when using PostgreSQL, it # will discover the sequence corresponding to your primary key for you. # - # Example: - # # class Project < ActiveRecord::Base # set_sequence_name "projectseq" # default would have been "project_seq" # end @@ -1263,7 +1277,7 @@ module ActiveRecord #:nodoc: class_of_active_record_descendant(self) end - # Set this to true if this is an abstract class (see #abstract_class?). + # Set this to true if this is an abstract class (see abstract_class?). attr_accessor :abstract_class # Returns whether this class is a base AR class. If A is a base class and @@ -1279,6 +1293,10 @@ module ActiveRecord #:nodoc: super end + def sti_name + store_full_sti_class ? name : name.demodulize + end + private def find_initial(options) options.update(:limit => 1) @@ -1298,7 +1316,7 @@ module ActiveRecord #:nodoc: scoped_order = reverse_sql_order(scope(:find, :order)) scoped_methods.select { |s| s[:find].update(:order => scoped_order) } end - + find_initial(options.merge({ :order => order })) end @@ -1308,12 +1326,12 @@ module ActiveRecord #:nodoc: s.gsub!(/\s(asc|ASC)$/, ' DESC') elsif s.match(/\s(desc|DESC)$/) s.gsub!(/\s(desc|DESC)$/, ' ASC') - elsif !s.match(/\s(asc|ASC|desc|DESC)$/) + elsif !s.match(/\s(asc|ASC|desc|DESC)$/) s.concat(' DESC') end }.join(',') end - + def find_every(options) include_associations = merge_includes(scope(:find, :include), options[:include]) @@ -1438,12 +1456,16 @@ module ActiveRecord #:nodoc: # Nest the type name in the same module as this class. # Bar is "MyApp::Business::Bar" relative to MyApp::Business::Foo def type_name_with_module(type_name) - (/^::/ =~ type_name) ? type_name : "#{parent.name}::#{type_name}" + if store_full_sti_class + type_name + else + (/^::/ =~ type_name) ? type_name : "#{parent.name}::#{type_name}" + end end def construct_finder_sql(options) scope = scope(:find) - sql = "SELECT #{(scope && scope[:select]) || options[:select] || (options[:joins] && quoted_table_name + '.*') || '*'} " + sql = "SELECT #{options[:select] || (scope && scope[:select]) || (options[:joins] && quoted_table_name + '.*') || '*'} " sql << "FROM #{(scope && scope[:from]) || options[:from] || quoted_table_name} " add_joins!(sql, options, scope) @@ -1557,8 +1579,8 @@ module ActiveRecord #:nodoc: def type_condition quoted_inheritance_column = connection.quote_column_name(inheritance_column) - type_condition = subclasses.inject("#{quoted_table_name}.#{quoted_inheritance_column} = '#{name.demodulize}' ") do |condition, subclass| - condition << "OR #{quoted_table_name}.#{quoted_inheritance_column} = '#{subclass.name.demodulize}' " + type_condition = subclasses.inject("#{quoted_table_name}.#{quoted_inheritance_column} = '#{sti_name}' ") do |condition, subclass| + condition << "OR #{quoted_table_name}.#{quoted_inheritance_column} = '#{subclass.sti_name}' " end " (#{type_condition}) " @@ -1566,8 +1588,8 @@ module ActiveRecord #:nodoc: # Guesses the table name, but does not decorate it with prefix and suffix information. def undecorated_table_name(class_name = base_class.name) - table_name = Inflector.underscore(Inflector.demodulize(class_name)) - table_name = Inflector.pluralize(table_name) if pluralize_table_names + table_name = class_name.to_s.demodulize.underscore + table_name = table_name.pluralize if pluralize_table_names table_name end @@ -1616,7 +1638,7 @@ module ActiveRecord #:nodoc: self.class_eval %{ def self.#{method_id}(*args) guard_protected_attributes = false - + if args[0].is_a?(Hash) guard_protected_attributes = true attributes = args[0].with_indifferent_access @@ -1629,7 +1651,7 @@ module ActiveRecord #:nodoc: set_readonly_option!(options) record = find_initial(options) - + if record.nil? record = self.new { |r| r.send(:attributes=, attributes, guard_protected_attributes) } #{'yield(record) if block_given?'} @@ -1710,8 +1732,8 @@ module ActiveRecord #:nodoc: end - # Defines an "attribute" method (like #inheritance_column or - # #table_name). A new (class) method will be created with the + # Defines an "attribute" method (like +inheritance_column+ or + # +table_name+). A new (class) method will be created with the # given name. If a value is specified, the new method will # return that value (as a string). Otherwise, the given block # will be used to compute the value of the method. @@ -1888,7 +1910,7 @@ module ActiveRecord #:nodoc: end end - # Returns the class descending directly from ActiveRecord in the inheritance hierarchy. + # Returns the class descending directly from Active Record in the inheritance hierarchy. def class_of_active_record_descendant(klass) if klass.superclass == Base || klass.superclass.abstract_class? klass @@ -1899,12 +1921,12 @@ module ActiveRecord #:nodoc: end end - # Returns the name of the class descending directly from ActiveRecord in the inheritance hierarchy. + # Returns the name of the class descending directly from Active Record in the inheritance hierarchy. def class_name_of_active_record_descendant(klass) #:nodoc: klass.base_class.name end - # Accepts an array, hash, or string of sql conditions and sanitizes + # Accepts an array, hash, or string of SQL conditions and sanitizes # them into a valid SQL fragment for a WHERE clause. # ["name='%s' and group_id='%s'", "foo'bar", 4] returns "name='foo''bar' and group_id='4'" # { :name => "foo'bar", :group_id => 4 } returns "name='foo''bar' and group_id='4'" @@ -1920,7 +1942,7 @@ module ActiveRecord #:nodoc: end alias_method :sanitize_sql, :sanitize_sql_for_conditions - # Accepts an array, hash, or string of sql conditions and sanitizes + # Accepts an array, hash, or string of SQL conditions and sanitizes # them into a valid SQL fragment for a SET clause. # { :name => nil, :group_id => 4 } returns "name = NULL , group_id='4'" def sanitize_sql_for_assignment(assignments) @@ -1936,7 +1958,7 @@ module ActiveRecord #:nodoc: mapping.first.is_a?(Array) ? mapping : [mapping] end - # Accepts a hash of sql conditions and replaces those attributes + # Accepts a hash of SQL conditions and replaces those attributes # that correspond to a +composed_of+ relationship with their expanded # aggregate attribute values. # Given: @@ -2009,7 +2031,7 @@ module ActiveRecord #:nodoc: end # Accepts an array of conditions. The array has each value - # sanitized and interpolated into the sql statement. + # sanitized and interpolated into the SQL statement. # ["name='%s' and group_id='%s'", "foo'bar", 4] returns "name='foo''bar' and group_id='4'" def sanitize_sql_array(ary) statement, *values = ary @@ -2129,14 +2151,16 @@ module ActiveRecord #:nodoc: # We can't use alias_method here, because method 'id' optimizes itself on the fly. (id = self.id) ? id.to_s : nil # Be sure to stringify the id for routes end - - # Returns a cache key that can be used to identify this record. Examples: + + # Returns a cache key that can be used to identify this record. + # + # ==== Examples # # Product.new.cache_key # => "products/new" # Product.find(5).cache_key # => "products/5" (updated_at not available) # Person.find(5).cache_key # => "people/5-20071224150000" (updated_at available) def cache_key - case + case when new_record? "#{self.class.name.tableize}/new" when self[:updated_at] @@ -2170,7 +2194,7 @@ module ActiveRecord #:nodoc: # Note: If your model specifies any validations then the method declaration dynamically # changes to: # save(perform_validation=true) - # Calling save(false) saves the model without running validations. + # Calling save(false) saves the model without running validations. # See ActiveRecord::Validations for more information. def save create_or_update @@ -2486,13 +2510,13 @@ module ActiveRecord #:nodoc: id end - # Sets the attribute used for single table inheritance to this class name if this is not the ActiveRecord descendent. - # Considering the hierarchy Reply < Message < ActiveRecord, this makes it possible to do Reply.new without having to - # set Reply[Reply.inheritance_column] = "Reply" yourself. No such attribute would be set for objects of the + # Sets the attribute used for single table inheritance to this class name if this is not the ActiveRecord::Base descendent. + # Considering the hierarchy Reply < Message < ActiveRecord::Base, this makes it possible to do Reply.new without having to + # set Reply[Reply.inheritance_column] = "Reply" yourself. No such attribute would be set for objects of the # Message class in that example. def ensure_proper_type unless self.class.descends_from_active_record? - write_attribute(self.class.inheritance_column, Inflector.demodulize(self.class.name)) + write_attribute(self.class.inheritance_column, self.class.sti_name) end end @@ -2560,7 +2584,7 @@ module ActiveRecord #:nodoc: self.class.connection.quote(value, column) end - # Interpolate custom sql string in instance context. + # Interpolate custom SQL string in instance context. # Optional record argument is meant for custom insert_sql. def interpolate_sql(sql, record = nil) instance_eval("%@#{sql.gsub('@', '\@')}@") diff --git a/vendor/rails/activerecord/lib/active_record/calculations.rb b/vendor/rails/activerecord/lib/active_record/calculations.rb index 3c5caefe..10e8330d 100644 --- a/vendor/rails/activerecord/lib/active_record/calculations.rb +++ b/vendor/rails/activerecord/lib/active_record/calculations.rb @@ -46,28 +46,28 @@ module ActiveRecord calculate(:count, *construct_count_options_from_args(*args)) end - # Calculates the average value on a given column. The value is returned as a float. See #calculate for examples with options. + # Calculates the average value on a given column. The value is returned as a float. See +calculate+ for examples with options. # # Person.average('age') def average(column_name, options = {}) calculate(:avg, column_name, options) end - # Calculates the minimum value on a given column. The value is returned with the same data type of the column. See #calculate for examples with options. + # Calculates the minimum value on a given column. The value is returned with the same data type of the column. See +calculate+ for examples with options. # # Person.minimum('age') def minimum(column_name, options = {}) calculate(:min, column_name, options) end - # Calculates the maximum value on a given column. The value is returned with the same data type of the column. See #calculate for examples with options. + # Calculates the maximum value on a given column. The value is returned with the same data type of the column. See +calculate+ for examples with options. # # Person.maximum('age') def maximum(column_name, options = {}) calculate(:max, column_name, options) end - # Calculates the sum of values on a given column. The value is returned with the same data type of the column. See #calculate for examples with options. + # Calculates the sum of values on a given column. The value is returned with the same data type of the column. See +calculate+ for examples with options. # # Person.sum('age') def sum(column_name, options = {}) @@ -245,12 +245,14 @@ module ActiveRecord options.assert_valid_keys(CALCULATIONS_OPTIONS) end - # Converts a given key to the value that the database adapter returns as - # a usable column name. - # users.id #=> users_id - # sum(id) #=> sum_id - # count(distinct users.id) #=> count_distinct_users_id - # count(*) #=> count_all + # Converts the given keys to the value that the database adapter returns as + # a usable column name: + # + # column_alias_for("users.id") # => "users_id" + # column_alias_for("sum(id)") # => "sum_id" + # column_alias_for("count(distinct users.id)") # => "count_distinct_users_id" + # column_alias_for("count(*)") # => "count_all" + # column_alias_for("count", "id") # => "count_id" def column_alias_for(*keys) connection.table_alias_for(keys.join(' ').downcase.gsub(/\*/, 'all').gsub(/\W+/, ' ').strip.gsub(/ +/, '_')) end diff --git a/vendor/rails/activerecord/lib/active_record/callbacks.rb b/vendor/rails/activerecord/lib/active_record/callbacks.rb index a469af68..41ec5c5e 100755 --- a/vendor/rails/activerecord/lib/active_record/callbacks.rb +++ b/vendor/rails/activerecord/lib/active_record/callbacks.rb @@ -161,7 +161,7 @@ module ActiveRecord # == before_validation* returning statements # # If the returning value of a +before_validation+ callback can be evaluated to +false+, the process will be aborted and Base#save will return +false+. - # If Base#save! is called it will raise a +RecordNotSaved+ exception. + # If Base#save! is called it will raise a RecordNotSaved exception. # Nothing will be appended to the errors object. # # == Canceling callbacks diff --git a/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb b/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb index 34627dfa..2a8807fb 100644 --- a/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb +++ b/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/connection_specification.rb @@ -193,7 +193,7 @@ module ActiveRecord # :database => "path/to/dbfile" # ) # - # Also accepts keys as strings (for parsing from yaml for example): + # Also accepts keys as strings (for parsing from YAML for example): # # ActiveRecord::Base.establish_connection( # "adapter" => "sqlite", diff --git a/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb b/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb index 589acd39..5358491c 100644 --- a/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb +++ b/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb @@ -29,7 +29,7 @@ module ActiveRecord end # Returns an array of arrays containing the field values. - # Order is the same as that returned by #columns. + # Order is the same as that returned by +columns+. def select_rows(sql, name = nil) raise NotImplementedError, "select_rows is an abstract method" end @@ -93,7 +93,7 @@ module ActiveRecord # done if the transaction block raises an exception or returns false. def rollback_db_transaction() end - # Alias for #add_limit_offset!. + # Alias for add_limit_offset!. def add_limit!(sql, options) add_limit_offset!(sql, options) if options end @@ -106,11 +106,16 @@ module ActiveRecord # SELECT * FROM suppliers LIMIT 10 OFFSET 50 def add_limit_offset!(sql, options) if limit = options[:limit] - sql << " LIMIT #{limit}" + sql << " LIMIT #{sanitize_limit(limit)}" if offset = options[:offset] - sql << " OFFSET #{offset}" + sql << " OFFSET #{offset.to_i}" end end + sql + end + + def sanitize_limit(limit) + limit.to_s[/,/] ? limit.split(',').map{ |i| i.to_i }.join(',') : limit.to_i end # Appends a locking clause to an SQL statement. diff --git a/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb index d73ffc3d..f968b9b1 100644 --- a/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb +++ b/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb @@ -16,13 +16,13 @@ module ActiveRecord # Instantiates a new column in the table. # - # +name+ is the column's name, as in supplier_id int(11). - # +default+ is the type-casted default value, such as sales_stage varchar(20) default 'new'. - # +sql_type+ is only used to extract the column's length, if necessary. For example, company_name varchar(60). + # +name+ is the column's name, such as supplier_id in supplier_id int(11). + # +default+ is the type-casted default value, such as +new+ in sales_stage varchar(20) default 'new'. + # +sql_type+ is only used to extract the column's length, if necessary. For example +60+ in company_name varchar(60). # +null+ determines if this column allows +NULL+ values. def initialize(name, default, sql_type = nil, null = true) @name, @sql_type, @null = name, sql_type, null - @limit, @precision, @scale = extract_limit(sql_type), extract_precision(sql_type), extract_scale(sql_type) + @limit, @precision, @scale = extract_limit(sql_type), extract_precision(sql_type), extract_scale(sql_type) @type = simplified_type(sql_type) @default = extract_default(default) @@ -92,7 +92,7 @@ module ActiveRecord # Returns the human name of the column name. # # ===== Examples - # Column.new('sales_stage', ...).human_name #=> 'Sales stage' + # Column.new('sales_stage', ...).human_name # => 'Sales stage' def human_name Base.human_attribute_name(@name) end @@ -172,7 +172,7 @@ module ActiveRecord def new_time(year, mon, mday, hour, min, sec, microsec) # Treat 0000-00-00 00:00:00 as nil. return nil if year.nil? || year == 0 - + Time.time_with_datetime_fallback(Base.default_timezone, year, mon, mday, hour, min, sec, microsec) rescue nil end @@ -250,11 +250,11 @@ module ActiveRecord end class ColumnDefinition < Struct.new(:base, :name, :type, :limit, :precision, :scale, :default, :null) #:nodoc: - + def sql_type base.type_to_sql(type.to_sym, limit, precision, scale) rescue type end - + def to_sql column_sql = "#{base.quote_column_name(name)} #{sql_type}" add_column_options!(column_sql, :null => null, :default => default) unless type.to_sym == :primary_key @@ -270,7 +270,7 @@ module ActiveRecord end # Represents a SQL table in an abstract way. - # Columns are stored as a ColumnDefinition in the #columns attribute. + # Columns are stored as a ColumnDefinition in the +columns+ attribute. class TableDefinition attr_accessor :columns @@ -309,39 +309,39 @@ module ActiveRecord # * :default - # The column's default value. Use nil for NULL. # * :null - - # Allows or disallows +NULL+ values in the column. This option could + # Allows or disallows +NULL+ values in the column. This option could # have been named :null_allowed. # * :precision - - # Specifies the precision for a :decimal column. + # Specifies the precision for a :decimal column. # * :scale - - # Specifies the scale for a :decimal column. + # Specifies the scale for a :decimal column. # # Please be aware of different RDBMS implementations behavior with # :decimal columns: # * The SQL standard says the default scale should be 0, :scale <= # :precision, and makes no comments about the requirements of # :precision. - # * MySQL: :precision [1..63], :scale [0..30]. + # * MySQL: :precision [1..63], :scale [0..30]. # Default is (10,0). - # * PostgreSQL: :precision [1..infinity], + # * PostgreSQL: :precision [1..infinity], # :scale [0..infinity]. No default. - # * SQLite2: Any :precision and :scale may be used. + # * SQLite2: Any :precision and :scale may be used. # Internal storage as strings. No default. # * SQLite3: No restrictions on :precision and :scale, # but the maximum supported :precision is 16. No default. - # * Oracle: :precision [1..38], :scale [-84..127]. + # * Oracle: :precision [1..38], :scale [-84..127]. # Default is (38,0). - # * DB2: :precision [1..63], :scale [0..62]. + # * DB2: :precision [1..63], :scale [0..62]. # Default unknown. - # * Firebird: :precision [1..18], :scale [0..18]. + # * Firebird: :precision [1..18], :scale [0..18]. # Default (9,0). Internal types NUMERIC and DECIMAL have different # storage rules, decimal being better. - # * FrontBase?: :precision [1..38], :scale [0..38]. + # * FrontBase?: :precision [1..38], :scale [0..38]. # Default (38,0). WARNING Max :precision/:scale for # NUMERIC is 19, and DECIMAL is 38. - # * SqlServer?: :precision [1..38], :scale [0..38]. + # * SqlServer?: :precision [1..38], :scale [0..38]. # Default (38,0). - # * Sybase: :precision [1..38], :scale [0..38]. + # * Sybase: :precision [1..38], :scale [0..38]. # Default (38,0). # * OpenBase?: Documentation unclear. Claims storage in double. # @@ -350,28 +350,28 @@ module ActiveRecord # == Examples # # Assuming td is an instance of TableDefinition # td.column(:granted, :boolean) - # #=> granted BOOLEAN + # # granted BOOLEAN # # td.column(:picture, :binary, :limit => 2.megabytes) - # #=> picture BLOB(2097152) + # # => picture BLOB(2097152) # # td.column(:sales_stage, :string, :limit => 20, :default => 'new', :null => false) - # #=> sales_stage VARCHAR(20) DEFAULT 'new' NOT NULL + # # => sales_stage VARCHAR(20) DEFAULT 'new' NOT NULL # - # def.column(:bill_gates_money, :decimal, :precision => 15, :scale => 2) - # #=> bill_gates_money DECIMAL(15,2) + # td.column(:bill_gates_money, :decimal, :precision => 15, :scale => 2) + # # => bill_gates_money DECIMAL(15,2) # - # def.column(:sensor_reading, :decimal, :precision => 30, :scale => 20) - # #=> sensor_reading DECIMAL(30,20) + # td.column(:sensor_reading, :decimal, :precision => 30, :scale => 20) + # # => sensor_reading DECIMAL(30,20) # # # While :scale defaults to zero on most databases, it # # probably wouldn't hurt to include it. - # def.column(:huge_integer, :decimal, :precision => 30) - # #=> huge_integer DECIMAL(30) + # td.column(:huge_integer, :decimal, :precision => 30) + # # => huge_integer DECIMAL(30) # # == Short-hand examples # - # Instead of calling column directly, you can also work with the short-hand definitions for the default types. + # Instead of calling +column+ directly, you can also work with the short-hand definitions for the default types. # They use the type as the method name instead of as a parameter and allow for multiple columns to be defined # in a single statement. # @@ -394,8 +394,8 @@ module ActiveRecord # t.timestamps # end # - # There's a short-hand method for each of the type values declared at the top. And then there's - # TableDefinition#timestamps that'll add created_at and updated_at as datetimes. + # There's a short-hand method for each of the type values declared at the top. And then there's + # TableDefinition#timestamps that'll add created_at and +updated_at+ as datetimes. # # TableDefinition#references will add an appropriately-named _id column, plus a corresponding _type # column if the :polymorphic option is supplied. If :polymorphic is a hash of options, these will be @@ -434,13 +434,13 @@ module ActiveRecord def #{column_type}(*args) options = args.extract_options! column_names = args - + column_names.each { |name| column(name, '#{column_type}', options) } end EOV end - - # Appends :datetime columns :created_at and + + # Appends :datetime columns :created_at and # :updated_at to the table. def timestamps column(:created_at, :datetime) @@ -458,7 +458,7 @@ module ActiveRecord alias :belongs_to :references # Returns a String whose contents are the column definitions - # concatenated together. This string can then be prepended and appended to + # concatenated together. This string can then be prepended and appended to # to generate the final SQL to create the table. def to_sql @columns * ', ' @@ -510,15 +510,15 @@ module ActiveRecord # Adds a new column to the named table. # See TableDefinition#column for details of the options you can use. - # ===== Examples - # ====== Creating a simple columns + # ===== Example + # ====== Creating a simple column # t.column(:name, :string) def column(column_name, type, options = {}) @base.add_column(@table_name, column_name, type, options) end - # Adds a new index to the table. +column_name+ can be a single Symbol, or - # an Array of Symbols. See SchemaStatements#add_index + # Adds a new index to the table. +column_name+ can be a single Symbol, or + # an Array of Symbols. See SchemaStatements#add_index # # ===== Examples # ====== Creating a simple index @@ -531,8 +531,8 @@ module ActiveRecord @base.add_index(@table_name, column_name, options) end - # Adds timestamps (created_at and updated_at) columns to the table. See SchemaStatements#timestamps - # ===== Examples + # Adds timestamps (created_at and updated_at) columns to the table. See SchemaStatements#add_timestamps + # ===== Example # t.timestamps def timestamps @base.add_timestamps(@table_name) @@ -547,7 +547,7 @@ module ActiveRecord @base.change_column(@table_name, column_name, type, options) end - # Sets a new default value for a column. See + # Sets a new default value for a column. See SchemaStatements#change_column_default # ===== Examples # t.change_default(:qualification, 'new') # t.change_default(:authorized, 1) @@ -559,27 +559,27 @@ module ActiveRecord # ===== Examples # t.remove(:qualification) # t.remove(:qualification, :experience) - # t.removes(:qualification, :experience) def remove(*column_names) @base.remove_column(@table_name, column_names) end - # Remove the given index from the table. + # Removes the given index from the table. # - # Remove the suppliers_name_index in the suppliers table. + # ===== Examples + # ====== Remove the suppliers_name_index in the suppliers table # t.remove_index :name - # Remove the index named accounts_branch_id_index in the accounts table. + # ====== Remove the index named accounts_branch_id_index in the accounts table # t.remove_index :column => :branch_id - # Remove the index named accounts_branch_id_party_id_index in the accounts table. + # ====== Remove the index named accounts_branch_id_party_id_index in the accounts table # t.remove_index :column => [:branch_id, :party_id] - # Remove the index named by_branch_party in the accounts table. + # ====== Remove the index named by_branch_party in the accounts table # t.remove_index :name => :by_branch_party def remove_index(options = {}) @base.remove_index(@table_name, options) end # Removes the timestamp columns (created_at and updated_at) from the table. - # ===== Examples + # ===== Example # t.remove_timestamps def remove_timestamps @base.remove_timestamps(@table_name) @@ -592,12 +592,11 @@ module ActiveRecord @base.rename_column(@table_name, column_name, new_column_name) end - # Adds a reference. Optionally adds a +type+ column. reference, - # references and belongs_to are all acceptable - # ===== Example + # Adds a reference. Optionally adds a +type+ column. + # references and belongs_to are acceptable. + # ===== Examples # t.references(:goat) # t.references(:goat, :polymorphic => true) - # t.references(:goat) # t.belongs_to(:goat) def references(*args) options = args.extract_options! @@ -609,12 +608,11 @@ module ActiveRecord end alias :belongs_to :references - # Adds a reference. Optionally removes a +type+ column. remove_reference, - # remove_references and remove_belongs_to are all acceptable - # ===== Example - # t.remove_reference(:goat) - # t.remove_reference(:goat, :polymorphic => true) + # Removes a reference. Optionally removes a +type+ column. + # remove_references and remove_belongs_to are acceptable. + # ===== Examples # t.remove_references(:goat) + # t.remove_references(:goat, :polymorphic => true) # t.remove_belongs_to(:goat) def remove_references(*args) options = args.extract_options! @@ -627,7 +625,7 @@ module ActiveRecord alias :remove_belongs_to :remove_references # Adds a column or columns of a specified type - # ===== Example + # ===== Examples # t.string(:goat) # t.string(:goat, :sheep) %w( string text integer float decimal datetime timestamp time date binary boolean ).each do |column_type| diff --git a/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb index 1594be40..67d70b38 100644 --- a/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -13,7 +13,7 @@ module ActiveRecord 255 end - # Truncates a table alias according to the limits of the current adapter. + # Truncates a table alias according to the limits of the current adapter. def table_alias_for(table_name) table_name[0..table_alias_length-1].gsub(/\./, '_') end @@ -32,7 +32,7 @@ module ActiveRecord def columns(table_name, name = nil) end # Creates a new table - # There are two ways to work with #create_table. You can use the block + # There are two ways to work with +create_table+. You can use the block # form or the regular form, like this: # # === Block form @@ -152,7 +152,7 @@ module ActiveRecord # t.remove :company # end # - # ====== Remove a column + # ====== Remove several columns # change_table(:suppliers) do |t| # t.remove :company_id # t.remove :width, :height @@ -168,7 +168,7 @@ module ActiveRecord def change_table(table_name) yield Table.new(table_name, self) end - + # Renames a table. # ===== Example # rename_table('octopuses', 'octopi') @@ -199,7 +199,7 @@ module ActiveRecord end end alias :remove_columns :remove_column - + # Changes the column's definition according to the new options. # See TableDefinition#column for details of the options you can use. # ===== Examples @@ -302,7 +302,7 @@ module ActiveRecord def dump_schema_information #:nodoc: sm_table = ActiveRecord::Migrator.schema_migrations_table_name migrated = select_values("SELECT version FROM #{sm_table}") - migrated.map { |v| "INSERT INTO #{sm_table} (version) VALUES ('#{v}');" }.join("\n") + migrated.map { |v| "INSERT INTO #{sm_table} (version) VALUES ('#{v}');" }.join("\n\n") end # Should not be called normally, but this operation is non-destructive. @@ -389,7 +389,7 @@ module ActiveRecord def distinct(columns, order_by) "DISTINCT #{columns}" end - + # ORDER BY clause for the passed order option. # PostgreSQL overrides this due to its stricter standards compliance. def add_order_by_for_association_limiting!(sql, options) @@ -401,17 +401,17 @@ module ActiveRecord # add_timestamps(:suppliers) def add_timestamps(table_name) add_column table_name, :created_at, :datetime - add_column table_name, :updated_at, :datetime + add_column table_name, :updated_at, :datetime end - + # Removes the timestamp columns (created_at and updated_at) from the table definition. # ===== Examples # remove_timestamps(:suppliers) def remove_timestamps(table_name) - remove_column table_name, :updated_at - remove_column table_name, :created_at + remove_column table_name, :updated_at + remove_column table_name, :created_at end - + protected def options_include_default?(options) options.include?(:default) && !(options[:null] == false && options[:default].nil?) diff --git a/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index 8c286f64..f48b107a 100755 --- a/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/vendor/rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -128,15 +128,11 @@ module ActiveRecord protected def log(sql, name) if block_given? - if @logger and @logger.debug? - result = nil - seconds = Benchmark.realtime { result = yield } - @runtime += seconds - log_info(sql, name, seconds) - result - else - yield - end + result = nil + seconds = Benchmark.realtime { result = yield } + @runtime += seconds + log_info(sql, name, seconds) + result else log_info(sql, name, 0) nil diff --git a/vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 2ec2d80a..7dbfbb41 100644 --- a/vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/vendor/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -776,7 +776,7 @@ module ActiveRecord # Returns an ORDER BY clause for the passed order option. # # PostgreSQL does not allow arbitrary ordering when using DISTINCT ON, so we work around this - # by wrapping the sql as a sub-select and ordering in that query. + # by wrapping the +sql+ string as a sub-select and ordering in that query. def add_order_by_for_association_limiting!(sql, options) #:nodoc: return sql if options[:order].blank? 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 8abbc6d0..51cfd10e 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 @@ -214,6 +214,10 @@ module ActiveRecord end def add_column(table_name, column_name, type, options = {}) #:nodoc: + if @connection.respond_to?(:transaction_active?) && @connection.transaction_active? + raise StatementInvalid, 'Cannot add columns to a SQLite database while inside a transaction' + end + super(table_name, column_name, type, options) # See last paragraph on http://www.sqlite.org/lang_altertable.html execute "VACUUM" diff --git a/vendor/rails/activerecord/lib/active_record/dirty.rb b/vendor/rails/activerecord/lib/active_record/dirty.rb index c6d89e3a..b32e17e9 100644 --- a/vendor/rails/activerecord/lib/active_record/dirty.rb +++ b/vendor/rails/activerecord/lib/active_record/dirty.rb @@ -40,9 +40,10 @@ module ActiveRecord base.alias_method_chain :save, :dirty base.alias_method_chain :save!, :dirty base.alias_method_chain :update, :dirty + base.alias_method_chain :reload, :dirty base.superclass_delegating_accessor :partial_updates - base.partial_updates = false + base.partial_updates = true end # Do any attributes have unsaved changes? @@ -69,19 +70,26 @@ module ActiveRecord changed.inject({}) { |h, attr| h[attr] = attribute_change(attr); h } end - - # Clear changed attributes after they are saved. + # Attempts to +save+ the record and clears changed attributes if successful. def save_with_dirty(*args) #:nodoc: - save_without_dirty(*args) - ensure - changed_attributes.clear + if status = save_without_dirty(*args) + changed_attributes.clear + end + status end - # Clear changed attributes after they are saved. + # Attempts to save! the record and clears changed attributes if successful. def save_with_dirty!(*args) #:nodoc: - save_without_dirty!(*args) - ensure + status = save_without_dirty!(*args) changed_attributes.clear + status + end + + # reload the record and clears changed attributes. + def reload_with_dirty(*args) #:nodoc: + record = reload_without_dirty(*args) + changed_attributes.clear + record end private @@ -117,14 +125,7 @@ module ActiveRecord # The attribute already has an unsaved change. unless changed_attributes.include?(attr) old = clone_attribute_value(:read_attribute, attr) - - # Remember the original value if it's different. - typecasted = if column = column_for_attribute(attr) - column.type_cast(value) - else - value - end - changed_attributes[attr] = old unless old == typecasted + changed_attributes[attr] = old if field_changed?(attr, old, value) end # Carry on. @@ -138,5 +139,20 @@ module ActiveRecord update_without_dirty end end + + def field_changed?(attr, old, value) + if column = column_for_attribute(attr) + if column.type == :integer && column.null && old.nil? + # For nullable integer columns, NULL gets stored in database for blank (i.e. '') values. + # Hence we don't record it as a change if the value changes from nil to ''. + value = nil if value.blank? + else + value = column.type_cast(value) + end + end + + old != value + end + end end diff --git a/vendor/rails/activerecord/lib/active_record/fixtures.rb b/vendor/rails/activerecord/lib/active_record/fixtures.rb index 9367ea52..c4cbe5d5 100755 --- a/vendor/rails/activerecord/lib/active_record/fixtures.rb +++ b/vendor/rails/activerecord/lib/active_record/fixtures.rb @@ -33,8 +33,8 @@ end # # Unlike single-file fixtures, YAML fixtures are stored in a single file per model, which are placed in the directory appointed # by ActiveSupport::TestCase.fixture_path=(path) (this is automatically configured for Rails, so you can just -# put your files in /test/fixtures/). The fixture file ends with the .yml file extension (Rails example: -# "/test/fixtures/web_sites.yml"). The format of a YAML fixture file looks like this: +# put your files in /test/fixtures/). The fixture file ends with the .yml file extension (Rails example: +# /test/fixtures/web_sites.yml). The format of a YAML fixture file looks like this: # # rubyonrails: # id: 1 @@ -67,7 +67,8 @@ end # = CSV fixtures # # Fixtures can also be kept in the Comma Separated Value format. Akin to YAML fixtures, CSV fixtures are stored -# in a single file, but instead end with the .csv file extension (Rails example: "/test/fixtures/web_sites.csv") +# in a single file, but instead end with the .csv file extension +# (Rails example: /test/fixtures/web_sites.csv). # # The format of this type of fixture file is much more compact than the others, but also a little harder to read by us # humans. The first line of the CSV file is a comma-separated list of field names. The rest of the file is then comprised @@ -93,11 +94,11 @@ end # This type of fixture was the original format for Active Record that has since been deprecated in favor of the YAML and CSV formats. # Fixtures for this format are created by placing text files in a sub-directory (with the name of the model) to the directory # appointed by ActiveSupport::TestCase.fixture_path=(path) (this is automatically configured for Rails, so you can just -# put your files in /test/fixtures// -- like /test/fixtures/web_sites/ for the WebSite -# model). +# put your files in /test/fixtures// -- +# like /test/fixtures/web_sites/ for the WebSite model). # # Each text file placed in this directory represents a "record". Usually these types of fixtures are named without -# extensions, but if you are on a Windows machine, you might consider adding .txt as the extension. Here's what the +# extensions, but if you are on a Windows machine, you might consider adding .txt as the extension. Here's what the # above example might look like: # # web_sites/google @@ -138,20 +139,20 @@ end # # In addition to being available in the database, the fixtures are also loaded into a hash stored in an instance variable # of the test case. It is named after the symbol... so, in our example, there would be a hash available called -# @web_sites. This is where the "fixture name" comes into play. +# @web_sites. This is where the "fixture name" comes into play. # -# On top of that, each record is automatically "found" (using Model.find(id)) and placed in the instance variable of its name. -# So for the YAML fixtures, we'd get @rubyonrails and @google, which could be interrogated using regular Active Record semantics: +# On top of that, each record is automatically "found" (using Model.find(id)) and placed in the instance variable of its name. +# So for the YAML fixtures, we'd get @rubyonrails and @google, which could be interrogated using regular Active Record semantics: # # # test if the object created from the fixture data has the same attributes as the data itself # def test_find # assert_equal @web_sites["rubyonrails"]["name"], @rubyonrails.name # end # -# As seen above, the data hash created from the YAML fixtures would have @web_sites["rubyonrails"]["url"] return -# "http://www.rubyonrails.org" and @web_sites["google"]["name"] would return "Google". The same fixtures, but loaded -# from a CSV fixture file, would be accessible via @web_sites["web_site_1"]["name"] == "Ruby on Rails" and have the individual -# fixtures available as instance variables @web_site_1 and @web_site_2. +# As seen above, the data hash created from the YAML fixtures would have @web_sites["rubyonrails"]["url"] return +# "http://www.rubyonrails.org" and @web_sites["google"]["name"] would return "Google". The same fixtures, but loaded +# from a CSV fixture file, would be accessible via @web_sites["web_site_1"]["name"] == "Ruby on Rails" and have the individual +# fixtures available as instance variables @web_site_1 and @web_site_2. # # If you do not wish to use instantiated fixtures (usually for performance reasons) there are two options. # @@ -184,7 +185,7 @@ end # # This will create 1000 very simple YAML fixtures. # -# Using ERb, you can also inject dynamic values into your fixtures with inserts like <%= Date.today.strftime("%Y-%m-%d") %>. +# Using ERb, you can also inject dynamic values into your fixtures with inserts like <%= Date.today.strftime("%Y-%m-%d") %>. # This is however a feature to be used with some caution. The point of fixtures are that they're stable units of predictable # sample data. If you feel that you need to inject dynamic values, then perhaps you should reexamine whether your application # is properly testable. Hence, dynamic values in fixtures are to be considered a code smell. @@ -197,20 +198,20 @@ end # class FooTest < ActiveSupport::TestCase # self.use_transactional_fixtures = true # self.use_instantiated_fixtures = false -# +# # fixtures :foos -# +# # def test_godzilla # assert !Foo.find(:all).empty? # Foo.destroy_all # assert Foo.find(:all).empty? # end -# +# # def test_godzilla_aftermath # assert !Foo.find(:all).empty? # end # end -# +# # If you preload your test database with all fixture data (probably in the Rakefile task) and use transactional fixtures, # then you may omit all fixtures declarations in your test cases since all the data's already there and every case rolls back its changes. # @@ -257,7 +258,7 @@ end # reginald: # generated id: 324201669 # name: Reginald the Pirate # -# ActiveRecord looks at the fixture's model class, discovers the correct +# Active Record looks at the fixture's model class, discovers the correct # primary key, and generates it right before inserting the fixture # into the database. # @@ -267,7 +268,7 @@ end # == Label references for associations (belongs_to, has_one, has_many) # # Specifying foreign keys in fixtures can be very fragile, not to -# mention difficult to read. Since ActiveRecord can figure out the ID of +# mention difficult to read. Since Active Record can figure out the ID of # any fixture from its label, you can specify FK's by label instead of ID. # # === belongs_to @@ -304,15 +305,15 @@ end # name: George the Monkey # pirate: reginald # -# Pow! All is made clear. ActiveRecord reflects on the fixture's model class, +# Pow! All is made clear. Active Record reflects on the fixture's model class, # finds all the +belongs_to+ associations, and allows you to specify # a target *label* for the *association* (monkey: george) rather than -# a target *id* for the *FK* (monkey_id: 1). +# a target *id* for the *FK* (monkey_id: 1). # # ==== Polymorphic belongs_to # # Supporting polymorphic relationships is a little bit more complicated, since -# ActiveRecord needs to know what type your association is pointing at. Something +# Active Record needs to know what type your association is pointing at. Something # like this should look familiar: # # ### in fruit.rb @@ -332,7 +333,7 @@ end # apple: # eater: george (Monkey) # -# Just provide the polymorphic target type and ActiveRecord will take care of the rest. +# Just provide the polymorphic target type and Active Record will take care of the rest. # # === has_and_belongs_to_many # @@ -395,15 +396,15 @@ end # # Zap! No more fruits_monkeys.yml file. We've specified the list of fruits # on George's fixture, but we could've just as easily specified a list -# of monkeys on each fruit. As with +belongs_to+, ActiveRecord reflects on +# of monkeys on each fruit. As with +belongs_to+, Active Record reflects on # the fixture's model class and discovers the +has_and_belongs_to_many+ # associations. # # == Autofilled timestamp columns # -# If your table/model specifies any of ActiveRecord's -# standard timestamp columns (created_at, created_on, updated_at, updated_on), -# they will automatically be set to Time.now. +# If your table/model specifies any of Active Record's +# standard timestamp columns (+created_at+, +created_on+, +updated_at+, +updated_on+), +# they will automatically be set to Time.now. # # If you've set specific values, they'll be left alone. # @@ -730,7 +731,7 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash) reader.each do |row| data = {} row.each_with_index { |cell, j| data[header[j].to_s.strip] = cell.to_s.strip } - self["#{Inflector::underscore(@class_name)}_#{i+=1}"] = Fixture.new(data, model_class) + self["#{@class_name.to_s.underscore}_#{i+=1}"] = Fixture.new(data, model_class) end end @@ -854,14 +855,14 @@ module Test #:nodoc: require_dependency file_name rescue LoadError => e # Let's hope the developer has included it himself - + # Let's warn in case this is a subdependency, otherwise # subdependency error messages are totally cryptic if ActiveRecord::Base.logger ActiveRecord::Base.logger.warn("Unable to load #{file_name}, underlying cause #{e.message} \n\n #{e.backtrace.join("\n")}") end end - + def require_fixture_classes(table_names = nil) (table_names || fixture_table_names).each do |table_name| file_name = table_name.to_s diff --git a/vendor/rails/activerecord/lib/active_record/locking/optimistic.rb b/vendor/rails/activerecord/lib/active_record/locking/optimistic.rb index 65f88cfd..c66034d1 100644 --- a/vendor/rails/activerecord/lib/active_record/locking/optimistic.rb +++ b/vendor/rails/activerecord/lib/active_record/locking/optimistic.rb @@ -107,20 +107,20 @@ module ActiveRecord end # Is optimistic locking enabled for this table? Returns true if the - # #lock_optimistically flag is set to true (which it is, by default) - # and the table includes the #locking_column column (defaults to - # lock_version). + # +lock_optimistically+ flag is set to true (which it is, by default) + # and the table includes the +locking_column+ column (defaults to + # +lock_version+). def locking_enabled? lock_optimistically && columns_hash[locking_column] end - # Set the column to use for optimistic locking. Defaults to lock_version. + # Set the column to use for optimistic locking. Defaults to +lock_version+. def set_locking_column(value = nil, &block) define_attr_method :locking_column, value, &block value end - # The version column used for optimistic locking. Defaults to lock_version. + # The version column used for optimistic locking. Defaults to +lock_version+. def locking_column reset_locking_column end @@ -130,12 +130,12 @@ module ActiveRecord connection.quote_column_name(locking_column) end - # Reset the column used for optimistic locking back to the lock_version default. + # Reset the column used for optimistic locking back to the +lock_version+ default. def reset_locking_column set_locking_column DEFAULT_LOCKING_COLUMN end - # make sure the lock version column gets updated when counters are + # Make sure the lock version column gets updated when counters are # updated. def update_counters_with_lock(id, counters) counters = counters.merge(locking_column => 1) if locking_enabled? diff --git a/vendor/rails/activerecord/lib/active_record/migration.rb b/vendor/rails/activerecord/lib/active_record/migration.rb index 5cc9f4e1..b47b01e9 100644 --- a/vendor/rails/activerecord/lib/active_record/migration.rb +++ b/vendor/rails/activerecord/lib/active_record/migration.rb @@ -208,7 +208,7 @@ module ActiveRecord # # You can quiet them down by setting ActiveRecord::Migration.verbose = false. # - # You can also insert your own messages and benchmarks by using the #say_with_time + # You can also insert your own messages and benchmarks by using the +say_with_time+ # method: # # def self.up @@ -377,7 +377,7 @@ module ActiveRecord end def proper_table_name(name) - # Use the ActiveRecord objects own table_name, or pre/suffix from ActiveRecord::Base if name is a symbol/string + # Use the Active Record objects own table_name, or pre/suffix from ActiveRecord::Base if name is a symbol/string name.table_name rescue "#{ActiveRecord::Base.table_name_prefix}#{name}#{ActiveRecord::Base.table_name_suffix}" end end diff --git a/vendor/rails/activerecord/lib/active_record/named_scope.rb b/vendor/rails/activerecord/lib/active_record/named_scope.rb index d43ebefc..b0c8a8b8 100644 --- a/vendor/rails/activerecord/lib/active_record/named_scope.rb +++ b/vendor/rails/activerecord/lib/active_record/named_scope.rb @@ -2,9 +2,7 @@ module ActiveRecord module NamedScope # All subclasses of ActiveRecord::Base have two named_scopes: # * all, which is similar to a find(:all) query, and - # * scoped, which allows for the creation of anonymous scopes, on the fly: - # - # Shirt.scoped(:conditions => {:color => 'red'}).scoped(:include => :washing_instructions) + # * scoped, which allows for the creation of anonymous scopes, on the fly: Shirt.scoped(:conditions => {:color => 'red'}).scoped(:include => :washing_instructions) # # These anonymous scopes tend to be useful when procedurally generating complex queries, where passing # intermediate values (scopes) around as first-class objects is convenient. @@ -41,7 +39,7 @@ module ActiveRecord # Nested finds and calculations also work with these compositions: Shirt.red.dry_clean_only.count returns the number of garments # for which these criteria obtain. Similarly with Shirt.red.dry_clean_only.average(:thread_count). # - # All scopes are available as class methods on the ActiveRecord descendent upon which the scopes were defined. But they are also available to + # All scopes are available as class methods on the ActiveRecord::Base descendent upon which the scopes were defined. But they are also available to # has_many associations. If, # # class Person < ActiveRecord::Base @@ -102,7 +100,13 @@ module ActiveRecord class Scope attr_reader :proxy_scope, :proxy_options - [].methods.each { |m| delegate m, :to => :proxy_found unless m =~ /(^__|^nil\?|^send|class|extend|find|count|sum|average|maximum|minimum|paginate)/ } + + [].methods.each do |m| + unless m =~ /(^__|^nil\?|^send|^object_id$|class|extend|find|count|sum|average|maximum|minimum|paginate|first|last|empty?)/ + delegate m, :to => :proxy_found + end + end + delegate :scopes, :with_scope, :to => :proxy_scope def initialize(proxy_scope, options, &block) @@ -115,6 +119,26 @@ module ActiveRecord load_found; self end + def first(*args) + if args.first.kind_of?(Integer) || (@found && !args.first.kind_of?(Hash)) + proxy_found.first(*args) + else + find(:first, *args) + end + end + + def last(*args) + if args.first.kind_of?(Integer) || (@found && !args.first.kind_of?(Hash)) + proxy_found.last(*args) + else + find(:last, *args) + end + end + + def empty? + @found ? @found.empty? : count.zero? + end + protected def proxy_found @found || load_found @@ -136,4 +160,4 @@ module ActiveRecord end end end -end \ No newline at end of file +end diff --git a/vendor/rails/activerecord/lib/active_record/observer.rb b/vendor/rails/activerecord/lib/active_record/observer.rb index 2b0728fc..6e55e36b 100644 --- a/vendor/rails/activerecord/lib/active_record/observer.rb +++ b/vendor/rails/activerecord/lib/active_record/observer.rb @@ -19,7 +19,7 @@ module ActiveRecord # # Same as above, just using explicit class references # ActiveRecord::Base.observers = Cacher, GarbageCollector # - # Note: Setting this does not instantiate the observers yet. #instantiate_observers is + # Note: Setting this does not instantiate the observers yet. +instantiate_observers+ is # called during startup, and before each development request. def observers=(*observers) @observers = observers.flatten @@ -30,7 +30,7 @@ module ActiveRecord @observers ||= [] end - # Instantiate the global ActiveRecord observers + # Instantiate the global Active Record observers. def instantiate_observers return if @observers.blank? @observers.each do |observer| diff --git a/vendor/rails/activerecord/lib/active_record/schema.rb b/vendor/rails/activerecord/lib/active_record/schema.rb index d6b254fc..8a32cf1c 100644 --- a/vendor/rails/activerecord/lib/active_record/schema.rb +++ b/vendor/rails/activerecord/lib/active_record/schema.rb @@ -30,8 +30,8 @@ module ActiveRecord # Eval the given block. All methods available to the current connection # adapter are available within the block, so you can easily use the - # database definition DSL to build up your schema (#create_table, - # #add_index, etc.). + # database definition DSL to build up your schema (+create_table+, + # +add_index+, etc.). # # The +info+ hash is optional, and if given is used to define metadata # about the current schema (currently, only the schema's version): diff --git a/vendor/rails/activerecord/lib/active_record/schema_dumper.rb b/vendor/rails/activerecord/lib/active_record/schema_dumper.rb index 826662d3..b90ed88c 100644 --- a/vendor/rails/activerecord/lib/active_record/schema_dumper.rb +++ b/vendor/rails/activerecord/lib/active_record/schema_dumper.rb @@ -38,7 +38,7 @@ module ActiveRecord stream.puts <
tag! escapes all values # to ensure that valid XML is generated. For known binary # values, it is at least an order of magnitude faster to # Base64 encode binary values and directly put them in the # output XML than to pass the original value or the Base64 - # encoded value to the #tag! method. It definitely makes + # encoded value to the tag! method. It definitely makes # no sense to Base64 encode the value and then give it to - # #tag!, since that just adds additional overhead. + # tag!, since that just adds additional overhead. def needs_encoding? ![ :binary, :date, :datetime, :boolean, :float, :integer ].include?(type) end diff --git a/vendor/rails/activerecord/lib/active_record/transactions.rb b/vendor/rails/activerecord/lib/active_record/transactions.rb index 13cb5f3f..3b683576 100644 --- a/vendor/rails/activerecord/lib/active_record/transactions.rb +++ b/vendor/rails/activerecord/lib/active_record/transactions.rb @@ -30,9 +30,9 @@ module ActiveRecord # Exceptions will force a ROLLBACK that returns the database to the state before the transaction was begun. Be aware, though, # that the objects will _not_ have their instance data returned to their pre-transactional state. # - # == Different ActiveRecord classes in a single transaction + # == Different Active Record classes in a single transaction # - # Though the transaction class method is called on some ActiveRecord class, + # Though the transaction class method is called on some Active Record class, # the objects within the transaction block need not all be instances of # that class. # In this example a Balance record is transactionally saved even diff --git a/vendor/rails/activerecord/lib/active_record/validations.rb b/vendor/rails/activerecord/lib/active_record/validations.rb index b3a75121..c97aafb1 100755 --- a/vendor/rails/activerecord/lib/active_record/validations.rb +++ b/vendor/rails/activerecord/lib/active_record/validations.rb @@ -301,7 +301,7 @@ module ActiveRecord :odd => 'odd?', :even => 'even?' }.freeze # Adds a validation method or block to the class. This is useful when - # overriding the #validate instance method becomes too unwieldly and + # overriding the +validate+ instance method becomes too unwieldly and # you're looking for more descriptive declaration of your validations. # # This can be done with a symbol pointing to a method: @@ -326,7 +326,7 @@ module ActiveRecord # end # end # - # This usage applies to #validate_on_create and #validate_on_update as well. + # This usage applies to +validate_on_create+ and +validate_on_update+ as well. # Validates each attribute against a block. # @@ -692,7 +692,7 @@ module ActiveRecord raise(ArgumentError, "A regular expression must be supplied as the :with option of the configuration hash") unless configuration[:with].is_a?(Regexp) validates_each(attr_names, configuration) do |record, attr_name, value| - record.errors.add(attr_name, configuration[:message]) unless value.to_s =~ configuration[:with] + record.errors.add(attr_name, configuration[:message] % value) unless value.to_s =~ configuration[:with] end end diff --git a/vendor/rails/activerecord/lib/active_record/version.rb b/vendor/rails/activerecord/lib/active_record/version.rb index 1463e847..aaadef99 100644 --- a/vendor/rails/activerecord/lib/active_record/version.rb +++ b/vendor/rails/activerecord/lib/active_record/version.rb @@ -1,8 +1,8 @@ module ActiveRecord module VERSION #:nodoc: MAJOR = 2 - MINOR = 0 - TINY = 991 + MINOR = 1 + TINY = 0 STRING = [MAJOR, MINOR, TINY].join('.') end diff --git a/vendor/rails/activerecord/test/cases/active_schema_test_mysql.rb b/vendor/rails/activerecord/test/cases/active_schema_test_mysql.rb index ddf3e821..2a42dc35 100644 --- a/vendor/rails/activerecord/test/cases/active_schema_test_mysql.rb +++ b/vendor/rails/activerecord/test/cases/active_schema_test_mysql.rb @@ -40,47 +40,56 @@ class ActiveSchemaTest < ActiveRecord::TestCase end def test_add_timestamps - #we need to actually modify some data, so we make execute to point to the original method - ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do - alias_method :execute_with_stub, :execute - alias_method :execute, :execute_without_stub - end - ActiveRecord::Base.connection.create_table :delete_me do |t| - end - ActiveRecord::Base.connection.add_timestamps :delete_me - assert_equal ActiveRecord::Base.connection.execute("SHOW FIELDS FROM delete_me where FIELD='updated_at' AND TYPE='datetime'").num_rows, 1 - assert_equal ActiveRecord::Base.connection.execute("SHOW FIELDS FROM delete_me where FIELD='created_at' AND TYPE='datetime'").num_rows, 1 - ensure - ActiveRecord::Base.connection.drop_table :delete_me rescue nil - #before finishing, we restore the alias to the mock-up method - ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do - alias_method :execute, :execute_with_stub + with_real_execute do + begin + ActiveRecord::Base.connection.create_table :delete_me do |t| + end + ActiveRecord::Base.connection.add_timestamps :delete_me + assert column_present?('delete_me', 'updated_at', 'datetime') + assert column_present?('delete_me', 'created_at', 'datetime') + ensure + ActiveRecord::Base.connection.drop_table :delete_me rescue nil + end end end def test_remove_timestamps - #we need to actually modify some data, so we make execute to point to the original method - ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do - alias_method :execute_with_stub, :execute - alias_method :execute, :execute_without_stub - end - ActiveRecord::Base.connection.create_table :delete_me do |t| - t.timestamps - end - ActiveRecord::Base.connection.remove_timestamps :delete_me - assert_equal ActiveRecord::Base.connection.execute("SHOW FIELDS FROM delete_me where FIELD='updated_at' AND TYPE='datetime'").num_rows, 0 - assert_equal ActiveRecord::Base.connection.execute("SHOW FIELDS FROM delete_me where FIELD='created_at' AND TYPE='datetime'").num_rows, 0 - ensure - ActiveRecord::Base.connection.drop_table :delete_me rescue nil - #before finishing, we restore the alias to the mock-up method - ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do - alias_method :execute, :execute_with_stub + with_real_execute do + begin + ActiveRecord::Base.connection.create_table :delete_me do |t| + t.timestamps + end + ActiveRecord::Base.connection.remove_timestamps :delete_me + assert !column_present?('delete_me', 'updated_at', 'datetime') + assert !column_present?('delete_me', 'created_at', 'datetime') + ensure + ActiveRecord::Base.connection.drop_table :delete_me rescue nil + end end end - private + def with_real_execute + #we need to actually modify some data, so we make execute point to the original method + ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do + alias_method :execute_with_stub, :execute + alias_method :execute, :execute_without_stub + end + yield + ensure + #before finishing, we restore the alias to the mock-up method + ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do + alias_method :execute, :execute_with_stub + end + end + + def method_missing(method_symbol, *arguments) ActiveRecord::Base.connection.send(method_symbol, *arguments) end + + def column_present?(table_name, column_name, type) + results = ActiveRecord::Base.connection.select_all("SHOW FIELDS FROM #{table_name} LIKE '#{column_name}'") + results.first && results.first['Type'] == type + end end diff --git a/vendor/rails/activerecord/test/cases/adapter_test.rb b/vendor/rails/activerecord/test/cases/adapter_test.rb index 91504af9..c77446f8 100644 --- a/vendor/rails/activerecord/test/cases/adapter_test.rb +++ b/vendor/rails/activerecord/test/cases/adapter_test.rb @@ -104,4 +104,24 @@ class AdapterTest < ActiveRecord::TestCase end end + def test_add_limit_offset_should_sanitize_sql_injection_for_limit_without_comas + sql_inject = "1 select * from schema" + assert_equal " LIMIT 1", @connection.add_limit_offset!("", :limit=>sql_inject) + if current_adapter?(:MysqlAdapter) + assert_equal " LIMIT 7, 1", @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7) + else + assert_equal " LIMIT 1 OFFSET 7", @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7) + end + end + + def test_add_limit_offset_should_sanitize_sql_injection_for_limit_with_comas + sql_inject = "1, 7 procedure help()" + if current_adapter?(:MysqlAdapter) + assert_equal " LIMIT 1,7", @connection.add_limit_offset!("", :limit=>sql_inject) + assert_equal " LIMIT 7, 1", @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7) + else + assert_equal " LIMIT 1,7", @connection.add_limit_offset!("", :limit=>sql_inject) + assert_equal " LIMIT 1,7 OFFSET 7", @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7) + end + end end diff --git a/vendor/rails/activerecord/test/cases/associations/belongs_to_associations_test.rb b/vendor/rails/activerecord/test/cases/associations/belongs_to_associations_test.rb old mode 100644 new mode 100755 index b8ec9117..e0da8bfb --- a/vendor/rails/activerecord/test/cases/associations/belongs_to_associations_test.rb +++ b/vendor/rails/activerecord/test/cases/associations/belongs_to_associations_test.rb @@ -12,6 +12,8 @@ require 'models/author' require 'models/tag' require 'models/tagging' require 'models/comment' +require 'models/sponsor' +require 'models/member' class BelongsToAssociationsTest < ActiveRecord::TestCase fixtures :accounts, :companies, :developers, :projects, :topics, @@ -54,8 +56,8 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase 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 + assert_equal first_firm.object_id, original_proxy.target.object_id + assert_equal another_firm.object_id, citibank.firm.target.object_id end def test_creating_the_belonging_object @@ -92,6 +94,11 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase assert_not_nil Company.find(3).firm_with_condition, "Microsoft should have a firm" end + def test_with_select + assert_equal Company.find(2).firm_with_select.attributes.size, 1 + assert_equal Company.find(2, :include => :firm_with_select ).firm_with_select.attributes.size, 1 + end + def test_belongs_to_counter debate = Topic.create("title" => "debate") assert_equal 0, debate.send(:read_attribute, "replies_count"), "No replies yet" @@ -376,5 +383,30 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase assert_raise(ActiveRecord::ReadOnlyRecord) { companies(:first_client).readonly_firm.save! } assert companies(:first_client).readonly_firm.readonly? end - + + def test_polymorphic_assignment_foreign_type_field_updating + # should update when assigning a saved record + sponsor = Sponsor.new + member = Member.create + sponsor.sponsorable = member + assert_equal "Member", sponsor.sponsorable_type + + # should update when assigning a new record + sponsor = Sponsor.new + member = Member.new + sponsor.sponsorable = member + assert_equal "Member", sponsor.sponsorable_type + end + + def test_polymorphic_assignment_updates_foreign_id_field_for_new_and_saved_records + sponsor = Sponsor.new + saved_member = Member.create + new_member = Member.new + + sponsor.sponsorable = saved_member + assert_equal saved_member.id, sponsor.sponsorable_id + + sponsor.sponsorable = new_member + assert_equal nil, sponsor.sponsorable_id + end end diff --git a/vendor/rails/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb b/vendor/rails/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb index 64565141..294b993c 100644 --- a/vendor/rails/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb +++ b/vendor/rails/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb @@ -401,6 +401,8 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase def test_include_uses_array_include_after_loaded project = projects(:active_record) + project.developers.class # force load target + developer = project.developers.first assert_no_queries do diff --git a/vendor/rails/activerecord/test/cases/associations/has_many_associations_test.rb b/vendor/rails/activerecord/test/cases/associations/has_many_associations_test.rb index 9e26e2ad..dbfa025e 100644 --- a/vendor/rails/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/vendor/rails/activerecord/test/cases/associations/has_many_associations_test.rb @@ -32,6 +32,10 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal 2, Firm.find(:first).plain_clients.count end + def test_counting_with_empty_hash_conditions + assert_equal 2, Firm.find(:first).plain_clients.count(:conditions => {}) + end + def test_counting_with_single_conditions assert_equal 2, Firm.find(:first).plain_clients.count(:conditions => '1=1') end @@ -346,6 +350,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal "Another Client", new_client.name assert new_client.new_record? assert_equal new_client, company.clients_of_firm.last + company.name += '-changed' assert_queries(2) { assert company.save } assert !new_client.new_record? assert_equal 2, company.clients_of_firm(true).size @@ -356,6 +361,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase new_clients = assert_no_queries { company.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) } assert_equal 2, new_clients.size + company.name += '-changed' assert_queries(3) { assert company.save } assert_equal 3, company.clients_of_firm(true).size end @@ -818,6 +824,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase def test_include_uses_array_include_after_loaded firm = companies(:first_firm) + firm.clients.class # force load target + client = firm.clients.first assert_no_queries do @@ -857,4 +865,68 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert ! firm.clients.include?(client) end + def test_calling_first_or_last_on_association_should_not_load_association + firm = companies(:first_firm) + firm.clients.first + firm.clients.last + assert !firm.clients.loaded? + end + + def test_calling_first_or_last_on_loaded_association_should_not_fetch_with_query + firm = companies(:first_firm) + firm.clients.class # force load target + assert firm.clients.loaded? + + assert_no_queries do + firm.clients.first + assert_equal 2, firm.clients.first(2).size + firm.clients.last + assert_equal 2, firm.clients.last(2).size + end + end + + def test_calling_first_or_last_on_existing_record_with_build_should_load_association + firm = companies(:first_firm) + firm.clients.build(:name => 'Foo') + assert !firm.clients.loaded? + + assert_queries 1 do + firm.clients.first + firm.clients.last + end + + assert firm.clients.loaded? + end + + def test_calling_first_or_last_on_new_record_should_not_run_queries + firm = Firm.new + + assert_no_queries do + firm.clients.first + firm.clients.last + end + end + + def test_calling_first_or_last_with_find_options_on_loaded_association_should_fetch_with_query + firm = companies(:first_firm) + firm.clients.class # force load target + + assert_queries 2 do + assert firm.clients.loaded? + firm.clients.first(:order => 'name') + firm.clients.last(:order => 'name') + end + end + + def test_calling_first_or_last_with_integer_on_association_should_load_association + firm = companies(:first_firm) + + assert_queries 1 do + firm.clients.first(2) + firm.clients.last(2) + end + + assert firm.clients.loaded? + end + end diff --git a/vendor/rails/activerecord/test/cases/associations/has_many_through_associations_test.rb b/vendor/rails/activerecord/test/cases/associations/has_many_through_associations_test.rb index 5561361b..05155f63 100644 --- a/vendor/rails/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/vendor/rails/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -59,6 +59,7 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase # * 2 new records = 4 # + 1 query to save the actual post = 5 assert_queries(5) do + posts(:thinking).body += '-changed' posts(:thinking).save end diff --git a/vendor/rails/activerecord/test/cases/associations/has_one_associations_test.rb b/vendor/rails/activerecord/test/cases/associations/has_one_associations_test.rb old mode 100644 new mode 100755 index 9e99caa7..abc7ee7e --- a/vendor/rails/activerecord/test/cases/associations/has_one_associations_test.rb +++ b/vendor/rails/activerecord/test/cases/associations/has_one_associations_test.rb @@ -24,6 +24,11 @@ class HasOneAssociationsTest < ActiveRecord::TestCase assert_queries(0) { firms.each(&:account) } end + def test_with_select + assert_equal Firm.find(1).account_with_select.attributes.size, 2 + assert_equal Firm.find(1, :include => :account_with_select).account_with_select.attributes.size, 2 + end + def test_can_marshal_has_one_association_with_nil_target firm = Firm.new assert_nothing_raised do diff --git a/vendor/rails/activerecord/test/cases/associations/join_model_test.rb b/vendor/rails/activerecord/test/cases/associations/join_model_test.rb index 952ea637..9e79d9c8 100644 --- a/vendor/rails/activerecord/test/cases/associations/join_model_test.rb +++ b/vendor/rails/activerecord/test/cases/associations/join_model_test.rb @@ -664,6 +664,8 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase def test_has_many_through_include_uses_array_include_after_loaded david = authors(:david) + david.categories.class # force load target + category = david.categories.first assert_no_queries do diff --git a/vendor/rails/activerecord/test/cases/associations_test.rb b/vendor/rails/activerecord/test/cases/associations_test.rb index d8fe98bf..59349dd7 100755 --- a/vendor/rails/activerecord/test/cases/associations_test.rb +++ b/vendor/rails/activerecord/test/cases/associations_test.rb @@ -99,12 +99,12 @@ class AssociationProxyTest < ActiveRecord::TestCase david = authors(:david) assert_equal david, david.posts.proxy_owner assert_equal david.class.reflect_on_association(:posts), david.posts.proxy_reflection - david.posts.first # force load target + david.posts.class # force load target assert_equal david.posts, david.posts.proxy_target assert_equal david, david.posts_with_extension.testing_proxy_owner assert_equal david.class.reflect_on_association(:posts_with_extension), david.posts_with_extension.testing_proxy_reflection - david.posts_with_extension.first # force load target + david.posts_with_extension.class # force load target assert_equal david.posts_with_extension, david.posts_with_extension.testing_proxy_target end @@ -160,6 +160,18 @@ class AssociationProxyTest < ActiveRecord::TestCase assert_equal 1, developer.reload.audit_logs.size end + def test_create_via_association_with_block + post = authors(:david).posts.create(:title => "New on Edge") {|p| p.body = "More cool stuff!"} + assert_equal post.title, "New on Edge" + assert_equal post.body, "More cool stuff!" + end + + def test_create_with_bang_via_association_with_block + post = authors(:david).posts.create!(:title => "New on Edge") {|p| p.body = "More cool stuff!"} + assert_equal post.title, "New on Edge" + assert_equal post.body, "More cool stuff!" + end + def test_failed_reload_returns_nil p = setup_dangling_association assert_nil p.author.reload diff --git a/vendor/rails/activerecord/test/cases/datatype_test_postgresql.rb b/vendor/rails/activerecord/test/cases/datatype_test_postgresql.rb index 41726ce5..bff092b5 100644 --- a/vendor/rails/activerecord/test/cases/datatype_test_postgresql.rb +++ b/vendor/rails/activerecord/test/cases/datatype_test_postgresql.rb @@ -30,8 +30,8 @@ class PostgresqlDataTypeTest < ActiveRecord::TestCase @connection.execute("INSERT INTO postgresql_arrays (commission_by_quarter, nicknames) VALUES ( '{35000,21000,18000,17000}', '{foo,bar,baz}' )") @first_array = PostgresqlArray.find(1) - @connection.execute("INSERT INTO postgresql_moneys (wealth) VALUES ('$567.89')") - @connection.execute("INSERT INTO postgresql_moneys (wealth) VALUES ('-$567.89')") + @connection.execute("INSERT INTO postgresql_moneys (wealth) VALUES ('567.89'::money)") + @connection.execute("INSERT INTO postgresql_moneys (wealth) VALUES ('-567.89'::money)") @first_money = PostgresqlMoney.find(1) @second_money = PostgresqlMoney.find(2) @@ -143,11 +143,11 @@ class PostgresqlDataTypeTest < ActiveRecord::TestCase end def test_update_money - new_value = 123.45 + new_value = BigDecimal.new('123.45') assert @first_money.wealth = new_value assert @first_money.save assert @first_money.reload - assert_equal @first_money.wealth, new_value + assert_equal new_value, @first_money.wealth end def test_update_number diff --git a/vendor/rails/activerecord/test/cases/defaults_test.rb b/vendor/rails/activerecord/test/cases/defaults_test.rb index bd19ffcc..2ea85417 100644 --- a/vendor/rails/activerecord/test/cases/defaults_test.rb +++ b/vendor/rails/activerecord/test/cases/defaults_test.rb @@ -5,7 +5,7 @@ require 'models/entrant' class DefaultTest < ActiveRecord::TestCase def test_nil_defaults_for_not_null_columns column_defaults = - if current_adapter?(:MysqlAdapter) + if current_adapter?(:MysqlAdapter) && Mysql.client_version < 50051 { 'id' => nil, 'name' => '', 'course_id' => nil } else { 'id' => nil, 'name' => nil, 'course_id' => nil } diff --git a/vendor/rails/activerecord/test/cases/dirty_test.rb b/vendor/rails/activerecord/test/cases/dirty_test.rb index 7412e638..c011ffaf 100644 --- a/vendor/rails/activerecord/test/cases/dirty_test.rb +++ b/vendor/rails/activerecord/test/cases/dirty_test.rb @@ -44,6 +44,16 @@ class DirtyTest < ActiveRecord::TestCase assert_nil pirate.catchphrase_change end + def test_nullable_integer_not_marked_as_changed_if_new_value_is_blank + pirate = Pirate.new + + ["", nil].each do |value| + pirate.parrot_id = value + assert !pirate.parrot_id_changed? + assert_nil pirate.parrot_id_change + end + end + def test_object_should_be_changed_if_any_attribute_is_changed pirate = Pirate.new assert !pirate.changed? @@ -78,7 +88,7 @@ class DirtyTest < ActiveRecord::TestCase end def test_association_assignment_changes_foreign_key - pirate = Pirate.create! + pirate = Pirate.create!(:catchphrase => 'jarl') pirate.parrot = Parrot.create! assert pirate.changed? assert_equal %w(parrot_id), pirate.changed @@ -115,6 +125,26 @@ class DirtyTest < ActiveRecord::TestCase end end + def test_changed_attributes_should_be_preserved_if_save_failure + pirate = Pirate.new + pirate.parrot_id = 1 + assert !pirate.save + check_pirate_after_save_failure(pirate) + + pirate = Pirate.new + pirate.parrot_id = 1 + assert_raises(ActiveRecord::RecordInvalid) { pirate.save! } + check_pirate_after_save_failure(pirate) + end + + def test_reload_should_clear_changed_attributes + pirate = Pirate.create!(:catchphrase => "shiver me timbers") + pirate.catchphrase = "*hic*" + assert pirate.changed? + pirate.reload + assert !pirate.changed? + end + private def with_partial_updates(klass, on = true) old = klass.partial_updates? @@ -123,4 +153,11 @@ class DirtyTest < ActiveRecord::TestCase ensure klass.partial_updates = old end + + def check_pirate_after_save_failure(pirate) + assert pirate.changed? + assert pirate.parrot_id_changed? + assert_equal %w(parrot_id), pirate.changed + assert_nil pirate.parrot_id_was + end end diff --git a/vendor/rails/activerecord/test/cases/finder_test.rb b/vendor/rails/activerecord/test/cases/finder_test.rb index 2acfe9b3..80936d51 100644 --- a/vendor/rails/activerecord/test/cases/finder_test.rb +++ b/vendor/rails/activerecord/test/cases/finder_test.rb @@ -9,6 +9,7 @@ require 'models/developer' require 'models/post' require 'models/customer' require 'models/job' +require 'models/categorization' class FinderTest < ActiveRecord::TestCase fixtures :companies, :topics, :entrants, :developers, :developers_projects, :posts, :comments, :accounts, :authors, :customers @@ -859,12 +860,17 @@ class FinderTest < ActiveRecord::TestCase end def test_find_with_order_on_included_associations_with_construct_finder_sql_for_association_limiting_and_is_distinct - assert_equal 2, Post.find(:all,:include=>{:authors=>:author_address},:order=>' author_addresses.id DESC ', :limit=>2).size + assert_equal 2, Post.find(:all, :include => { :authors => :author_address }, :order => ' author_addresses.id DESC ', :limit => 2).size - assert_equal 3, Post.find(:all,:include=>{:author=>:author_address,:authors=>:author_address}, - :order=>' author_addresses_authors.id DESC ', :limit=>3).size + assert_equal 3, Post.find(:all, :include => { :author => :author_address, :authors => :author_address}, + :order => ' author_addresses_authors.id DESC ', :limit => 3).size end + def test_with_limiting_with_custom_select + posts = Post.find(:all, :include => :author, :select => ' posts.*, authors.id as "author_id"', :limit => 3, :order => 'posts.id') + assert_equal 3, posts.size + assert_equal [0, 1, 1], posts.map(&:author_id).sort + end protected def bind(statement, *vars) diff --git a/vendor/rails/activerecord/test/cases/fixtures_test.rb b/vendor/rails/activerecord/test/cases/fixtures_test.rb index 2787b9a3..aca7cfb3 100755 --- a/vendor/rails/activerecord/test/cases/fixtures_test.rb +++ b/vendor/rails/activerecord/test/cases/fixtures_test.rb @@ -610,15 +610,17 @@ class ActiveSupportSubclassWithFixturesTest < ActiveRecord::TestCase end class FixtureLoadingTest < ActiveRecord::TestCase - def test_logs_message_for_failed_dependency_load - Test::Unit::TestCase.expects(:require_dependency).with(:does_not_exist).raises(LoadError) - ActiveRecord::Base.logger.expects(:warn) - Test::Unit::TestCase.try_to_load_dependency(:does_not_exist) - end + uses_mocha 'reloading_fixtures_through_accessor_methods' do + def test_logs_message_for_failed_dependency_load + Test::Unit::TestCase.expects(:require_dependency).with(:does_not_exist).raises(LoadError) + ActiveRecord::Base.logger.expects(:warn) + Test::Unit::TestCase.try_to_load_dependency(:does_not_exist) + end - def test_does_not_logs_message_for_successful_dependency_load - Test::Unit::TestCase.expects(:require_dependency).with(:works_out_fine) - ActiveRecord::Base.logger.expects(:warn).never - Test::Unit::TestCase.try_to_load_dependency(:works_out_fine) + def test_does_not_logs_message_for_successful_dependency_load + Test::Unit::TestCase.expects(:require_dependency).with(:works_out_fine) + ActiveRecord::Base.logger.expects(:warn).never + Test::Unit::TestCase.try_to_load_dependency(:works_out_fine) + end end end diff --git a/vendor/rails/activerecord/test/cases/inheritance_test.rb b/vendor/rails/activerecord/test/cases/inheritance_test.rb index c9eb83e3..f09b617e 100755 --- a/vendor/rails/activerecord/test/cases/inheritance_test.rb +++ b/vendor/rails/activerecord/test/cases/inheritance_test.rb @@ -6,6 +6,50 @@ require 'models/subscriber' class InheritanceTest < ActiveRecord::TestCase fixtures :companies, :projects, :subscribers, :accounts + def test_class_with_store_full_sti_class_returns_full_name + old = ActiveRecord::Base.store_full_sti_class + ActiveRecord::Base.store_full_sti_class = true + assert_equal 'Namespaced::Company', Namespaced::Company.sti_name + ensure + ActiveRecord::Base.store_full_sti_class = old + end + + def test_class_without_store_full_sti_class_returns_demodulized_name + old = ActiveRecord::Base.store_full_sti_class + ActiveRecord::Base.store_full_sti_class = false + assert_equal 'Company', Namespaced::Company.sti_name + ensure + ActiveRecord::Base.store_full_sti_class = old + end + + def test_should_store_demodulized_class_name_with_store_full_sti_class_option_disabled + old = ActiveRecord::Base.store_full_sti_class + ActiveRecord::Base.store_full_sti_class = false + item = Namespaced::Company.new + assert_equal 'Company', item[:type] + ensure + ActiveRecord::Base.store_full_sti_class = old + end + + def test_should_store_full_class_name_with_store_full_sti_class_option_enabled + old = ActiveRecord::Base.store_full_sti_class + ActiveRecord::Base.store_full_sti_class = true + item = Namespaced::Company.new + assert_equal 'Namespaced::Company', item[:type] + ensure + ActiveRecord::Base.store_full_sti_class = old + end + + def test_different_namespace_subclass_should_load_correctly_with_store_full_sti_class_option + old = ActiveRecord::Base.store_full_sti_class + ActiveRecord::Base.store_full_sti_class = true + item = Namespaced::Company.create :name => "Wolverine 2" + assert_not_nil Company.find(item.id) + assert_not_nil Namespaced::Company.find(item.id) + ensure + ActiveRecord::Base.store_full_sti_class = old + end + def test_company_descends_from_active_record assert_raise(NoMethodError) { ActiveRecord::Base.descends_from_active_record? } assert AbstractCompany.descends_from_active_record?, 'AbstractCompany should descend from ActiveRecord::Base' diff --git a/vendor/rails/activerecord/test/cases/method_scoping_test.rb b/vendor/rails/activerecord/test/cases/method_scoping_test.rb index 4b5bd6c9..1a9a8757 100644 --- a/vendor/rails/activerecord/test/cases/method_scoping_test.rb +++ b/vendor/rails/activerecord/test/cases/method_scoping_test.rb @@ -50,6 +50,22 @@ class MethodScopingTest < ActiveRecord::TestCase end end + def test_scoped_find_select + Developer.with_scope(:find => { :select => "id, name" }) do + developer = Developer.find(:first, :conditions => "name = 'David'") + assert_equal "David", developer.name + assert !developer.has_attribute?(:salary) + end + end + + def test_options_select_replaces_scope_select + Developer.with_scope(:find => { :select => "id, name" }) do + developer = Developer.find(:first, :select => 'id, salary', :conditions => "name = 'David'") + assert_equal 80000, developer.salary + assert !developer.has_attribute?(:name) + end + end + def test_scoped_count Developer.with_scope(:find => { :conditions => "name = 'David'" }) do assert_equal 1, Developer.count diff --git a/vendor/rails/activerecord/test/cases/migration_test.rb b/vendor/rails/activerecord/test/cases/migration_test.rb index 527856b4..f36255e2 100644 --- a/vendor/rails/activerecord/test/cases/migration_test.rb +++ b/vendor/rails/activerecord/test/cases/migration_test.rb @@ -281,7 +281,7 @@ if ActiveRecord::Base.connection.supports_migrations? # Do a manual insertion if current_adapter?(:OracleAdapter) Person.connection.execute "insert into people (id, wealth) values (people_seq.nextval, 12345678901234567890.0123456789)" - elsif current_adapter?(:OpenBaseAdapter) + elsif current_adapter?(:OpenBaseAdapter) || (current_adapter?(:MysqlAdapter) && Mysql.client_version < 50003) #before mysql 5.0.3 decimals stored as strings Person.connection.execute "insert into people (wealth) values ('12345678901234567890.0123456789')" else Person.connection.execute "insert into people (wealth) values (12345678901234567890.0123456789)" @@ -384,7 +384,7 @@ if ActiveRecord::Base.connection.supports_migrations? assert_not_equal "Z", bob.moment_of_truth.zone # US/Eastern is -5 hours from GMT assert_equal Rational(-5, 24), bob.moment_of_truth.offset - assert_equal "-05:00", bob.moment_of_truth.zone + assert_match /\A-05:?00\Z/, bob.moment_of_truth.zone #ruby 1.8.6 uses HH:MM, prior versions use HHMM assert_equal DateTime::ITALY, bob.moment_of_truth.start end end diff --git a/vendor/rails/activerecord/test/cases/named_scope_test.rb b/vendor/rails/activerecord/test/cases/named_scope_test.rb index 30c074c9..d890cf79 100644 --- a/vendor/rails/activerecord/test/cases/named_scope_test.rb +++ b/vendor/rails/activerecord/test/cases/named_scope_test.rb @@ -6,7 +6,7 @@ require 'models/reply' require 'models/author' class NamedScopeTest < ActiveRecord::TestCase - fixtures :posts, :authors, :topics + fixtures :posts, :authors, :topics, :comments def test_implements_enumerable assert !Topic.find(:all).empty? @@ -95,7 +95,7 @@ class NamedScopeTest < ActiveRecord::TestCase end def test_has_many_through_associations_have_access_to_named_scopes - assert_not_equal Comment.containing_the_letter_e, authors(:david).posts + assert_not_equal Comment.containing_the_letter_e, authors(:david).comments assert !Comment.containing_the_letter_e.empty? assert_equal authors(:david).comments & Comment.containing_the_letter_e, authors(:david).comments.containing_the_letter_e @@ -118,4 +118,40 @@ class NamedScopeTest < ActiveRecord::TestCase assert_equal expected_proxy_options, Topic.approved.proxy_options end + def test_first_and_last_should_support_find_options + assert_equal Topic.base.first(:order => 'title'), Topic.base.find(:first, :order => 'title') + assert_equal Topic.base.last(:order => 'title'), Topic.base.find(:last, :order => 'title') + end + + def test_first_and_last_should_allow_integers_for_limit + assert_equal Topic.base.first(2), Topic.base.to_a.first(2) + assert_equal Topic.base.last(2), Topic.base.to_a.last(2) + end + + def test_first_and_last_should_not_use_query_when_results_are_loaded + topics = Topic.base + topics.reload # force load + assert_no_queries do + topics.first + topics.last + end + end + + def test_first_and_last_find_options_should_use_query_when_results_are_loaded + topics = Topic.base + topics.reload # force load + assert_queries(2) do + topics.first(:order => 'title') + topics.last(:order => 'title') + end + end + + def test_empty_should_not_load_results + topics = Topic.base + assert_queries(2) do + topics.empty? # use count query + topics.collect # force load + topics.empty? # use loaded (no query) + end + end end diff --git a/vendor/rails/activerecord/test/cases/reflection_test.rb b/vendor/rails/activerecord/test/cases/reflection_test.rb index c8ee40ea..8b4d2325 100644 --- a/vendor/rails/activerecord/test/cases/reflection_test.rb +++ b/vendor/rails/activerecord/test/cases/reflection_test.rb @@ -159,9 +159,10 @@ class ReflectionTest < ActiveRecord::TestCase end def test_reflection_of_all_associations - assert_equal 19, Firm.reflect_on_all_associations.size + # FIXME these assertions bust a lot + assert_equal 20, Firm.reflect_on_all_associations.size assert_equal 16, Firm.reflect_on_all_associations(:has_many).size - assert_equal 3, Firm.reflect_on_all_associations(:has_one).size + assert_equal 4, Firm.reflect_on_all_associations(:has_one).size assert_equal 0, Firm.reflect_on_all_associations(:belongs_to).size end diff --git a/vendor/rails/activerecord/test/cases/transactions_test.rb b/vendor/rails/activerecord/test/cases/transactions_test.rb index 63f04e30..06a76eac 100644 --- a/vendor/rails/activerecord/test/cases/transactions_test.rb +++ b/vendor/rails/activerecord/test/cases/transactions_test.rb @@ -179,6 +179,32 @@ class TransactionTest < ActiveRecord::TestCase end end + def test_sqlite_add_column_in_transaction_raises_statement_invalid + return true unless current_adapter?(:SQLite3Adapter, :SQLiteAdapter) + + # Test first if column creation/deletion works correctly when no + # transaction is in place. + # + # We go back to the connection for the column queries because + # Topic.columns is cached and won't report changes to the DB + + assert_nothing_raised do + Topic.reset_column_information + Topic.connection.add_column('topics', 'stuff', :string) + assert Topic.column_names.include?('stuff') + + Topic.reset_column_information + Topic.connection.remove_column('topics', 'stuff') + assert !Topic.column_names.include?('stuff') + end + + # Test now inside a transaction: add_column should raise a StatementInvalid + Topic.transaction do + assert_raises(ActiveRecord::StatementInvalid) { Topic.connection.add_column('topics', 'stuff', :string) } + raise ActiveRecord::Rollback + end + end + private def add_exception_raising_after_save_callback_to_topic Topic.class_eval { def after_save() raise "Make the transaction rollback" end } diff --git a/vendor/rails/activerecord/test/cases/validations_test.rb b/vendor/rails/activerecord/test/cases/validations_test.rb index a4d9da48..7b71647d 100755 --- a/vendor/rails/activerecord/test/cases/validations_test.rb +++ b/vendor/rails/activerecord/test/cases/validations_test.rb @@ -583,6 +583,12 @@ class ValidationsTest < ActiveRecord::TestCase assert_nil t.errors.on(:title) end + def test_validate_format_with_formatted_message + Topic.validates_format_of(:title, :with => /^Valid Title$/, :message => "can't be %s") + t = Topic.create(:title => 'Invalid title') + assert_equal "can't be Invalid title", t.errors.on(:title) + end + def test_validates_inclusion_of Topic.validates_inclusion_of( :title, :in => %w( a b c d e f g ) ) diff --git a/vendor/rails/activerecord/test/models/company.rb b/vendor/rails/activerecord/test/models/company.rb index 3d76dfd3..70f83fa8 100755 --- a/vendor/rails/activerecord/test/models/company.rb +++ b/vendor/rails/activerecord/test/models/company.rb @@ -15,6 +15,10 @@ class Company < AbstractCompany end end +module Namespaced + class Company < ::Company + end +end class Firm < Company has_many :clients, :order => "id", :dependent => :destroy, :counter_sql => @@ -43,6 +47,7 @@ class Firm < Company has_many :readonly_clients, :class_name => 'Client', :readonly => true has_one :account, :foreign_key => "firm_id", :dependent => :destroy + has_one :account_with_select, :foreign_key => "firm_id", :select => "id, firm_id", :class_name=>'Account' has_one :readonly_account, :foreign_key => "firm_id", :class_name => "Account", :readonly => true end @@ -60,6 +65,7 @@ end class Client < Company belongs_to :firm, :foreign_key => "client_of" belongs_to :firm_with_basic_id, :class_name => "Firm", :foreign_key => "firm_id" + belongs_to :firm_with_select, :class_name => "Firm", :foreign_key => "firm_id", :select => "id" belongs_to :firm_with_other_name, :class_name => "Firm", :foreign_key => "client_of" belongs_to :firm_with_condition, :class_name => "Firm", :foreign_key => "client_of", :conditions => ["1 = ?", 1] belongs_to :readonly_firm, :class_name => "Firm", :foreign_key => "firm_id", :readonly => true diff --git a/vendor/rails/activerecord/test/models/pirate.rb b/vendor/rails/activerecord/test/models/pirate.rb index bb4d02c1..51c8183d 100644 --- a/vendor/rails/activerecord/test/models/pirate.rb +++ b/vendor/rails/activerecord/test/models/pirate.rb @@ -4,4 +4,6 @@ class Pirate < ActiveRecord::Base has_many :treasures, :as => :looter has_many :treasure_estimates, :through => :treasures, :source => :price_estimates + + validates_presence_of :catchphrase end diff --git a/vendor/rails/activeresource/CHANGELOG b/vendor/rails/activeresource/CHANGELOG index 9aa7d455..e124e40d 100644 --- a/vendor/rails/activeresource/CHANGELOG +++ b/vendor/rails/activeresource/CHANGELOG @@ -1,4 +1,4 @@ -*2.1.0 RC1 (May 11th, 2008)* +*2.1.0 (May 31st, 2008)* * Fixed response logging to use length instead of the entire thing (seangeo) [#27] diff --git a/vendor/rails/activeresource/Rakefile b/vendor/rails/activeresource/Rakefile index 75fe52ae..9fd0ec49 100644 --- a/vendor/rails/activeresource/Rakefile +++ b/vendor/rails/activeresource/Rakefile @@ -64,7 +64,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', '= 2.0.991' + PKG_BUILD) + s.add_dependency('activesupport', '= 2.1.0' + PKG_BUILD) s.require_path = 'lib' s.autorequire = 'active_resource' diff --git a/vendor/rails/activeresource/lib/active_resource/base.rb b/vendor/rails/activeresource/lib/active_resource/base.rb index 08fd0123..463ee9f1 100644 --- a/vendor/rails/activeresource/lib/active_resource/base.rb +++ b/vendor/rails/activeresource/lib/active_resource/base.rb @@ -34,18 +34,18 @@ module ActiveResource # from REST web services. # # ryan = Person.new(:first => 'Ryan', :last => 'Daigle') - # ryan.save #=> true - # ryan.id #=> 2 - # Person.exists?(ryan.id) #=> true - # ryan.exists? #=> true + # ryan.save # => true + # ryan.id # => 2 + # Person.exists?(ryan.id) # => true + # ryan.exists? # => true # # ryan = Person.find(1) - # # => Resource holding our newly created Person object + # # Resource holding our newly created Person object # # ryan.first = 'Rizzle' - # ryan.save #=> true + # ryan.save # => true # - # ryan.destroy #=> true + # ryan.destroy # => true # # As you can see, these are very similar to Active Record's lifecycle methods for database records. # You can read more about each of these methods in their respective documentation. @@ -127,7 +127,7 @@ module ActiveResource # # GET http://api.people.com:3000/people/999.xml # ryan = Person.find(999) # 404, raises ActiveResource::ResourceNotFound # - # 404 is just one of the HTTP error response codes that ActiveResource will handle with its own exception. The + # 404 is just one of the HTTP error response codes that Active Resource will handle with its own exception. The # following HTTP response codes will also result in these exceptions: # # * 200..399 - Valid response, no exception @@ -156,8 +156,8 @@ module ActiveResource # then fail (with a false return value) and the validation errors can be accessed on the resource in question. # # ryan = Person.find(1) - # ryan.first #=> '' - # ryan.save #=> false + # ryan.first # => '' + # ryan.save # => false # # # When # # PUT http://api.people.com:3000/people/1.xml @@ -167,8 +167,8 @@ module ActiveResource # # First cannot be empty # # # - # ryan.errors.invalid?(:first) #=> true - # ryan.errors.full_messages #=> ['First cannot be empty'] + # ryan.errors.invalid?(:first) # => true + # ryan.errors.full_messages # => ['First cannot be empty'] # # Learn more about Active Resource's validation features in the ActiveResource::Validations documentation. # @@ -201,7 +201,7 @@ module ActiveResource class << self # Gets the URI of the REST resources to map for this class. The site variable is required - # ActiveResource's mapping to work. + # Active Resource's mapping to work. def site # Not using superclass_delegating_reader because don't want subclasses to modify superclass instance # @@ -226,7 +226,7 @@ module ActiveResource end # Sets the URI of the REST resources to map for this class to the value in the +site+ argument. - # The site variable is required ActiveResource's mapping to work. + # The site variable is required Active Resource's mapping to work. def site=(site) @connection = nil if site.nil? @@ -701,7 +701,7 @@ module ActiveResource attributes[self.class.primary_key] = id end - # Allows ActiveResource objects to be used as parameters in ActionPack URL generation. + # Allows Active Resource objects to be used as parameters in Action Pack URL generation. def to_param id && id.to_s end @@ -820,7 +820,7 @@ module ActiveResource # ==== Options # The +options+ parameter is handed off to the +to_xml+ method on each # attribute, so it has the same options as the +to_xml+ methods in - # ActiveSupport. + # Active Support. # # * :indent - Set the indent level for the XML output (default is +2+). # * :dasherize - Boolean option to determine whether or not element names should diff --git a/vendor/rails/activeresource/lib/active_resource/custom_methods.rb b/vendor/rails/activeresource/lib/active_resource/custom_methods.rb index 52a4a4f1..4c869928 100644 --- a/vendor/rails/activeresource/lib/active_resource/custom_methods.rb +++ b/vendor/rails/activeresource/lib/active_resource/custom_methods.rb @@ -7,12 +7,12 @@ module ActiveResource # :member => { :promote => :put, :deactivate => :delete } # :collection => { :active => :get } # - # This route set creates routes for the following http requests: + # This route set creates routes for the following HTTP requests: # - # POST /people/new/register.xml #=> PeopleController.register - # PUT /people/1/promote.xml #=> PeopleController.promote with :id => 1 - # DELETE /people/1/deactivate.xml #=> PeopleController.deactivate with :id => 1 - # GET /people/active.xml #=> PeopleController.active + # POST /people/new/register.xml # PeopleController.register + # PUT /people/1/promote.xml # PeopleController.promote with :id => 1 + # DELETE /people/1/deactivate.xml # PeopleController.deactivate with :id => 1 + # GET /people/active.xml # PeopleController.active # # Using this module, Active Resource can use these custom REST methods just like the # standard methods. @@ -48,8 +48,8 @@ module ActiveResource # # => [{:id => 1, :name => 'Ryan'}] # # Note: the objects returned from this method are not automatically converted - # into ActiveResource instances - they are ordinary Hashes. If you are expecting - # ActiveResource instances, use the find class method with the + # into Active Resource instances - they are ordinary Hashes. If you are expecting + # Active Resource instances, use the find class method with the # :from option. For example: # # Person.find(:all, :from => :active) diff --git a/vendor/rails/activeresource/lib/active_resource/formats/xml_format.rb b/vendor/rails/activeresource/lib/active_resource/formats/xml_format.rb index 01c28dce..5e97ffa7 100644 --- a/vendor/rails/activeresource/lib/active_resource/formats/xml_format.rb +++ b/vendor/rails/activeresource/lib/active_resource/formats/xml_format.rb @@ -21,7 +21,7 @@ module ActiveResource private # Manipulate from_xml Hash, because xml_simple is not exactly what we - # want for ActiveResource. + # want for Active Resource. def from_xml_data(data) if data.is_a?(Hash) && data.keys.size == 1 data.values.first diff --git a/vendor/rails/activeresource/lib/active_resource/http_mock.rb b/vendor/rails/activeresource/lib/active_resource/http_mock.rb index d1c14125..22f83ae9 100644 --- a/vendor/rails/activeresource/lib/active_resource/http_mock.rb +++ b/vendor/rails/activeresource/lib/active_resource/http_mock.rb @@ -3,8 +3,52 @@ require 'active_resource/connection' module ActiveResource class InvalidRequestError < StandardError; end #:nodoc: + # One thing that has always been a pain with remote web services is testing. The HttpMock + # class makes it easy to test your Active Resource models by creating a set of mock responses to specific + # requests. + # + # To test your Active Resource model, you simply call the ActiveResource::HttpMock.respond_to + # method with an attached block. The block declares a set of URIs with expected input, and the output + # each request should return. The passed in block has any number of entries in the following generalized + # format: + # + # mock.http_method(path, request_headers = {}, body = nil, status = 200, response_headers = {}) + # + # * http_method - The HTTP method to listen for. This can be +get+, +post+, +put+, +delete+ or + # +head+. + # * path - A string, starting with a "/", defining the URI that is expected to be + # called. + # * request_headers - Headers that are expected along with the request. This argument uses a + # hash format, such as { "Content-Type" => "application/xml" }. This mock will only trigger + # if your tests sends a request with identical headers. + # * body - The data to be returned. This should be a string of Active Resource parseable content, + # such as XML. + # * status - The HTTP response code, as an integer, to return with the response. + # * response_headers - Headers to be returned with the response. Uses the same hash format as + # request_headers listed above. + # + # In order for a mock to deliver its content, the incoming request must match by the http_method, + # +path+ and request_headers. If no match is found an InvalidRequestError exception + # will be raised letting you know you need to create a new mock for that request. + # + # ==== Example + # def setup + # @matz = { :id => 1, :name => "Matz" }.to_xml(:root => "person") + # ActiveResource::HttpMock.respond_to do |mock| + # mock.post "/people.xml", {}, @matz, 201, "Location" => "/people/1.xml" + # mock.get "/people/1.xml", {}, @matz + # mock.put "/people/1.xml", {}, nil, 204 + # mock.delete "/people/1.xml", {}, nil, 200 + # end + # end + # + # def test_get_matz + # person = Person.find(1) + # assert_equal "Matz", person.name + # end + # class HttpMock - class Responder + class Responder #:nodoc: def initialize(responses) @responses = responses end @@ -19,15 +63,41 @@ module ActiveResource end class << self + + # Returns an array of all request objects that have been sent to the mock. You can use this to check + # wether or not your model actually sent an HTTP request. + # + # ==== Example + # def setup + # @matz = { :id => 1, :name => "Matz" }.to_xml(:root => "person") + # ActiveResource::HttpMock.respond_to do |mock| + # mock.get "/people/1.xml", {}, @matz + # end + # end + # + # def test_should_request_remote_service + # person = Person.find(1) # Call the remote service + # + # # This request object has the same HTTP method and path as declared by the mock + # expected_request = ActiveResource::Request.new(:get, "/people/1.xml") + # + # # Assert that the mock received, and responded to, the expected request from the model + # assert ActiveResource::HttpMock.requests.include?(expected_request) + # end def requests @@requests ||= [] end + # Returns a hash of request => response pairs for all all responses this mock has delivered, where +request+ + # is an instance of ActiveResource::Request and the response is, naturally, an instance of + # ActiveResource::Response. def responses @@responses ||= {} end - def respond_to(pairs = {}) + # Accepts a block which declares a set of requests and responses for the HttpMock to respond to. See the main + # ActiveResource::HttpMock description for a more detailed explanation. + def respond_to(pairs = {}) #:yields: mock reset! pairs.each do |(path, response)| responses[path] = response @@ -40,6 +110,7 @@ module ActiveResource end end + # Deletes all logged requests and responses. def reset! requests.clear responses.clear @@ -66,7 +137,7 @@ module ActiveResource EOE end - def initialize(site) + def initialize(site) #:nodoc: @site = site end end diff --git a/vendor/rails/activeresource/lib/active_resource/validations.rb b/vendor/rails/activeresource/lib/active_resource/validations.rb index 57d2ae55..a7c624f3 100644 --- a/vendor/rails/activeresource/lib/active_resource/validations.rb +++ b/vendor/rails/activeresource/lib/active_resource/validations.rb @@ -216,8 +216,8 @@ module ActiveResource end end - # Module to allow validation of ActiveResource objects, which creates an Errors instance for every resource. - # Methods are implemented by overriding +Base#validate+ or its variants Each of these methods can inspect + # Module to allow validation of Active Resource objects, which creates an Errors instance for every resource. + # Methods are implemented by overriding Base#validate or its variants Each of these methods can inspect # the state of the object, which usually means ensuring that a number of attributes have a certain value # (such as not empty, within a given range, matching a certain regular expression and so on). # diff --git a/vendor/rails/activeresource/lib/active_resource/version.rb b/vendor/rails/activeresource/lib/active_resource/version.rb index 34fb05b7..88798ea1 100644 --- a/vendor/rails/activeresource/lib/active_resource/version.rb +++ b/vendor/rails/activeresource/lib/active_resource/version.rb @@ -1,8 +1,8 @@ module ActiveResource module VERSION #:nodoc: MAJOR = 2 - MINOR = 0 - TINY = 991 + MINOR = 1 + TINY = 0 STRING = [MAJOR, MINOR, TINY].join('.') end diff --git a/vendor/rails/activesupport/CHANGELOG b/vendor/rails/activesupport/CHANGELOG index e8821060..690bb987 100644 --- a/vendor/rails/activesupport/CHANGELOG +++ b/vendor/rails/activesupport/CHANGELOG @@ -1,4 +1,12 @@ -*2.1.0 RC1 (May 11th, 2008)* +*2.1.0 (May 31st, 2008)* + +* TimeZone#to_s shows offset as GMT instead of UTC, because GMT will be more familiar to end users (see time zone selects used by Windows OS, google.com and yahoo.com.) Reverts [8370] [Geoff Buesing] + +* Hash.from_xml: datetime xml types overflow to Ruby DateTime class when out of range of Time. Adding tests for utc offsets [Geoff Buesing] + +* TimeWithZone #+ and #- : ensure overflow to DateTime with Numeric arg [Geoff Buesing] + +* Time#to_json: don't convert to utc before encoding. References #175 [Geoff Buesing] * Remove unused JSON::RESERVED_WORDS, JSON.valid_identifier? and JSON.reserved_word? methods. Resolves #164. [Cheah Chu Yeow] diff --git a/vendor/rails/activesupport/lib/active_support.rb b/vendor/rails/activesupport/lib/active_support.rb index 4d2f873a..e4cb145c 100644 --- a/vendor/rails/activesupport/lib/active_support.rb +++ b/vendor/rails/activesupport/lib/active_support.rb @@ -39,6 +39,7 @@ require 'active_support/cache' require 'active_support/dependencies' require 'active_support/deprecation' +require 'active_support/ordered_hash' require 'active_support/ordered_options' require 'active_support/option_merger' diff --git a/vendor/rails/activesupport/lib/active_support/cache.rb b/vendor/rails/activesupport/lib/active_support/cache.rb index b3c9c23d..2f1143e6 100644 --- a/vendor/rails/activesupport/lib/active_support/cache.rb +++ b/vendor/rails/activesupport/lib/active_support/cache.rb @@ -87,8 +87,12 @@ module ActiveSupport def delete_matched(matcher, options = nil) log("delete matched", matcher.inspect, options) - end - + end + + def exist?(key, options = nil) + log("exist?", key, options) + end + def increment(key, amount = 1) log("incrementing", key, amount) if num = read(key) diff --git a/vendor/rails/activesupport/lib/active_support/cache/file_store.rb b/vendor/rails/activesupport/lib/active_support/cache/file_store.rb index 16a2509c..5b771b1d 100644 --- a/vendor/rails/activesupport/lib/active_support/cache/file_store.rb +++ b/vendor/rails/activesupport/lib/active_support/cache/file_store.rb @@ -40,13 +40,18 @@ module ActiveSupport end end + def exist?(name, options = nil) + super + File.exist?(real_file_path(name)) + end + private def real_file_path(name) '%s/%s.cache' % [@cache_path, name.gsub('?', '.').gsub(':', '.')] end def ensure_cache_path(path) - FileUtils.makedirs(path) unless File.exists?(path) + FileUtils.makedirs(path) unless File.exist?(path) end def search_dir(dir, &callback) diff --git a/vendor/rails/activesupport/lib/active_support/cache/mem_cache_store.rb b/vendor/rails/activesupport/lib/active_support/cache/mem_cache_store.rb index bfe7e2cc..b3769b81 100644 --- a/vendor/rails/activesupport/lib/active_support/cache/mem_cache_store.rb +++ b/vendor/rails/activesupport/lib/active_support/cache/mem_cache_store.rb @@ -48,7 +48,13 @@ module ActiveSupport rescue MemCache::MemCacheError => e logger.error("MemCacheError (#{e}): #{e.message}") false - end + end + + def exist?(key, options = nil) + # Doesn't call super, cause exist? in memcache is in fact a read + # But who cares? Reading is very fast anyway + !read(key, options).nil? + end def increment(key, amount = 1) log("incrementing", key, amount) diff --git a/vendor/rails/activesupport/lib/active_support/cache/memory_store.rb b/vendor/rails/activesupport/lib/active_support/cache/memory_store.rb index 4872e025..6f114273 100644 --- a/vendor/rails/activesupport/lib/active_support/cache/memory_store.rb +++ b/vendor/rails/activesupport/lib/active_support/cache/memory_store.rb @@ -24,7 +24,12 @@ module ActiveSupport super @data.delete_if { |k,v| k =~ matcher } end - + + def exist?(name,options = nil) + super + @data.has_key?(name) + end + def clear @data.clear end diff --git a/vendor/rails/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb b/vendor/rails/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb index 371d074d..8724a492 100644 --- a/vendor/rails/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb +++ b/vendor/rails/activesupport/lib/active_support/core_ext/class/inheritable_attributes.rb @@ -128,7 +128,7 @@ class Class # :nodoc: new_inheritable_attributes = EMPTY_INHERITABLE_ATTRIBUTES else new_inheritable_attributes = inheritable_attributes.inject({}) do |memo, (key, value)| - memo.update(key => (value.dup rescue value)) + memo.update(key => value.duplicable? ? value.dup : value) end 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 3d6a8d85..2c606b40 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 @@ -70,7 +70,7 @@ module ActiveSupport #:nodoc: XML_PARSING = { "symbol" => Proc.new { |symbol| symbol.to_sym }, "date" => Proc.new { |date| ::Date.parse(date) }, - "datetime" => Proc.new { |time| ::Time.parse(time).utc }, + "datetime" => Proc.new { |time| ::Time.parse(time).utc rescue ::DateTime.parse(time).utc }, "integer" => Proc.new { |integer| integer.to_i }, "float" => Proc.new { |float| float.to_f }, "decimal" => Proc.new { |number| BigDecimal(number) }, @@ -212,7 +212,7 @@ module ActiveSupport #:nodoc: nil # If the type is the only element which makes it then # this still makes the value nil, except if type is - # a xml node(where type['value'] is a Hash) + # a XML node(where type['value'] is a Hash) elsif value['type'] && value.size == 1 && !value['type'].is_a?(::Hash) nil else diff --git a/vendor/rails/activesupport/lib/active_support/core_ext/integer/even_odd.rb b/vendor/rails/activesupport/lib/active_support/core_ext/integer/even_odd.rb index cfc6b4c6..b1d1e280 100644 --- a/vendor/rails/activesupport/lib/active_support/core_ext/integer/even_odd.rb +++ b/vendor/rails/activesupport/lib/active_support/core_ext/integer/even_odd.rb @@ -3,10 +3,14 @@ module ActiveSupport #:nodoc: module Integer #:nodoc: # For checking if a fixnum is even or odd. # - # 1.even? # => false - # 1.odd? # => true - # 2.even? # => true - # 2.odd? # => false + # 2.even? # => true + # 2.odd? # => false + # 1.even? # => false + # 1.odd? # => true + # 0.even? # => true + # 0.odd? # => false + # -1.even? # => false + # -1.odd? # => true module EvenOdd def multiple_of?(number) self % number == 0 diff --git a/vendor/rails/activesupport/lib/active_support/core_ext/module/attr_internal.rb b/vendor/rails/activesupport/lib/active_support/core_ext/module/attr_internal.rb index e0be3109..b66c0d75 100644 --- a/vendor/rails/activesupport/lib/active_support/core_ext/module/attr_internal.rb +++ b/vendor/rails/activesupport/lib/active_support/core_ext/module/attr_internal.rb @@ -1,19 +1,19 @@ class Module - # Declare an attribute reader backed by an internally-named instance variable. + # Declares an attribute reader backed by an internally-named instance variable. def attr_internal_reader(*attrs) attrs.each do |attr| module_eval "def #{attr}() #{attr_internal_ivar_name(attr)} end" end end - # Declare an attribute writer backed by an internally-named instance variable. + # Declares an attribute writer backed by an internally-named instance variable. def attr_internal_writer(*attrs) attrs.each do |attr| module_eval "def #{attr}=(v) #{attr_internal_ivar_name(attr)} = v end" end end - # Declare an attribute reader and writer backed by an internally-named instance + # Declares an attribute reader and writer backed by an internally-named instance # variable. def attr_internal_accessor(*attrs) attr_internal_reader(*attrs) diff --git a/vendor/rails/activesupport/lib/active_support/core_ext/object/misc.rb b/vendor/rails/activesupport/lib/active_support/core_ext/object/misc.rb index a3637d7a..8384a123 100644 --- a/vendor/rails/activesupport/lib/active_support/core_ext/object/misc.rb +++ b/vendor/rails/activesupport/lib/active_support/core_ext/object/misc.rb @@ -48,7 +48,7 @@ class Object yield ActiveSupport::OptionMerger.new(self, options) end - # A duck-type assistant method. For example, ActiveSupport extends Date + # A duck-type assistant method. For example, Active Support extends Date # to define an acts_like_date? method, and extends Time to define # acts_like_time?. As a result, we can do "x.acts_like?(:time)" and # "x.acts_like?(:date)" to do duck-type-safe comparisons, since classes that diff --git a/vendor/rails/activesupport/lib/active_support/core_ext/range/conversions.rb b/vendor/rails/activesupport/lib/active_support/core_ext/range/conversions.rb index 8d757646..932bdeda 100644 --- a/vendor/rails/activesupport/lib/active_support/core_ext/range/conversions.rb +++ b/vendor/rails/activesupport/lib/active_support/core_ext/range/conversions.rb @@ -15,10 +15,9 @@ module ActiveSupport #:nodoc: end # Gives a human readable format of the range. # - # Example: + # ==== Example: # - # >> [1..100].to_formatted_s - # => "1..100" + # [1..100].to_formatted_s # => "1..100" def to_formatted_s(format = :default) RANGE_FORMATS[format] ? RANGE_FORMATS[format].call(first, last) : to_default_s end diff --git a/vendor/rails/activesupport/lib/active_support/core_ext/string/unicode.rb b/vendor/rails/activesupport/lib/active_support/core_ext/string/unicode.rb index ba16d4d8..5e20534d 100644 --- a/vendor/rails/activesupport/lib/active_support/core_ext/string/unicode.rb +++ b/vendor/rails/activesupport/lib/active_support/core_ext/string/unicode.rb @@ -17,17 +17,17 @@ module ActiveSupport #:nodoc: # string overrides can also be called through the +chars+ proxy. # # name = 'Claus Müller' - # name.reverse #=> "rell??M sualC" - # name.length #=> 13 + # name.reverse # => "rell??M sualC" + # name.length # => 13 # - # name.chars.reverse.to_s #=> "rellüM sualC" - # name.chars.length #=> 12 + # name.chars.reverse.to_s # => "rellüM sualC" + # name.chars.length # => 12 # # # All the methods on the chars proxy which normally return a string will return a Chars object. This allows # method chaining on the result of any of these methods. # - # name.chars.reverse.length #=> 12 + # name.chars.reverse.length # => 12 # # The Char object tries to be as interchangeable with String objects as possible: sorting and comparing between # String and Char work like expected. The bang! methods change the internal string representation in the Chars diff --git a/vendor/rails/activesupport/lib/active_support/core_ext/time/conversions.rb b/vendor/rails/activesupport/lib/active_support/core_ext/time/conversions.rb index edca5b8a..90540083 100644 --- a/vendor/rails/activesupport/lib/active_support/core_ext/time/conversions.rb +++ b/vendor/rails/activesupport/lib/active_support/core_ext/time/conversions.rb @@ -59,7 +59,7 @@ module ActiveSupport #:nodoc: # Converts a Time object to a Date, dropping hour, minute, and second precision. # # my_time = Time.now # => Mon Nov 12 22:59:51 -0500 2007 - # my_time.to_date #=> Mon, 12 Nov 2007 + # my_time.to_date # => Mon, 12 Nov 2007 # # your_time = Time.parse("1/13/2009 1:13:03 P.M.") # => Tue Jan 13 13:13:03 -0500 2009 # your_time.to_date # => Tue, 13 Jan 2009 diff --git a/vendor/rails/activesupport/lib/active_support/core_ext/time/zones.rb b/vendor/rails/activesupport/lib/active_support/core_ext/time/zones.rb index 3ffc7140..079ecdd4 100644 --- a/vendor/rails/activesupport/lib/active_support/core_ext/time/zones.rb +++ b/vendor/rails/activesupport/lib/active_support/core_ext/time/zones.rb @@ -1,9 +1,7 @@ module ActiveSupport #:nodoc: module CoreExtensions #:nodoc: module Time #:nodoc: - # Methods for creating TimeWithZone objects from Time instances module Zones - def self.included(base) #:nodoc: base.extend(ClassMethods) if base == ::Time # i.e., don't include class methods in DateTime end @@ -11,23 +9,36 @@ module ActiveSupport #:nodoc: module ClassMethods attr_accessor :zone_default + # Returns the TimeZone for the current request, if this has been set (via Time.zone=). + # If Time.zone has not been set for the current request, returns the TimeZone specified in config.time_zone. def zone Thread.current[:time_zone] || zone_default end - # Sets a global default time zone, separate from the system time zone in ENV['TZ']. - # Accepts either a Rails TimeZone object, a string that identifies a - # Rails TimeZone object (e.g., "Central Time (US & Canada)"), or a TZInfo::Timezone object. + # Sets Time.zone to a TimeZone object for the current request/thread. # - # Any Time or DateTime object can use this default time zone, via in_time_zone. + # This method accepts any of the following: # - # Time.zone = 'Hawaii' # => 'Hawaii' - # Time.utc(2000).in_time_zone # => Fri, 31 Dec 1999 14:00:00 HST -10:00 + # * A Rails TimeZone object. + # * An identifier for a Rails TimeZone object (e.g., "Eastern Time (US & Canada)", -5.hours). + # * A TZInfo::Timezone object. + # * An identifier for a TZInfo::Timezone object (e.g., "America/New_York"). + # + # Here's an example of how you might set Time.zone on a per request basis -- current_user.time_zone + # just needs to return a string identifying the user's preferred TimeZone: + # + # class ApplicationController < ActionController::Base + # before_filter :set_time_zone + # + # def set_time_zone + # Time.zone = current_user.time_zone + # end + # end def zone=(time_zone) Thread.current[:time_zone] = get_zone(time_zone) end - # Allows override of Time.zone locally inside supplied block; resets Time.zone to existing value when done + # Allows override of Time.zone locally inside supplied block; resets Time.zone to existing value when done. def use_zone(time_zone) old_zone, ::Time.zone = ::Time.zone, get_zone(time_zone) yield @@ -35,7 +46,7 @@ module ActiveSupport #:nodoc: ::Time.zone = old_zone end - # Returns Time.zone.now when config.time_zone is set, otherwise just returns Time.now. + # Returns Time.zone.now when config.time_zone is set, otherwise just returns Time.now. def current ::Time.zone_default ? ::Time.zone.now : ::Time.now end @@ -54,16 +65,16 @@ module ActiveSupport #:nodoc: end end - # Returns the simultaneous time in Time.zone. + # Returns the simultaneous time in Time.zone. # # Time.zone = 'Hawaii' # => 'Hawaii' # Time.utc(2000).in_time_zone # => Fri, 31 Dec 1999 14:00:00 HST -10:00 # - # This method is similar to Time#localtime, except that it uses Time.zone as the local zone + # This method is similar to Time#localtime, except that it uses Time.zone as the local zone # instead of the operating system's time zone. # # You can also pass in a TimeZone instance or string that identifies a TimeZone as an argument, - # and the conversion will be based on that zone instead of Time.zone. + # and the conversion will be based on that zone instead of Time.zone. # # Time.utc(2000).in_time_zone('Alaska') # => Fri, 31 Dec 1999 15:00:00 AKST -09:00 def in_time_zone(zone = ::Time.zone) diff --git a/vendor/rails/activesupport/lib/active_support/dependencies.rb b/vendor/rails/activesupport/lib/active_support/dependencies.rb index eaba46dd..da2ece61 100644 --- a/vendor/rails/activesupport/lib/active_support/dependencies.rb +++ b/vendor/rails/activesupport/lib/active_support/dependencies.rb @@ -82,9 +82,10 @@ module Dependencies #:nodoc: # infinite loop with mutual dependencies. loaded << expanded - if load? - log "loading #{file_name}" - begin + begin + if load? + log "loading #{file_name}" + # Enable warnings iff this file has not been loaded before and # warnings_on_first_load is set. load_args = ["#{file_name}.rb"] @@ -95,13 +96,13 @@ module Dependencies #:nodoc: else enable_warnings { result = load_file(*load_args) } end - rescue Exception - loaded.delete expanded - raise + else + log "requiring #{file_name}" + result = require file_name end - else - log "requiring #{file_name}" - result = require file_name + rescue Exception + loaded.delete expanded + raise end # Record history *after* loading so first load gets warnings. @@ -384,7 +385,7 @@ module Dependencies #:nodoc: return new_constants ensure # Remove the stack frames that we added. - if defined?(watch_frames) && ! watch_frames.empty? + if defined?(watch_frames) && ! watch_frames.blank? frame_ids = watch_frames.collect(&:object_id) constant_watch_stack.delete_if do |watch_frame| frame_ids.include? watch_frame.object_id diff --git a/vendor/rails/activesupport/lib/active_support/deprecation.rb b/vendor/rails/activesupport/lib/active_support/deprecation.rb index 7613652c..758aef54 100644 --- a/vendor/rails/activesupport/lib/active_support/deprecation.rb +++ b/vendor/rails/activesupport/lib/active_support/deprecation.rb @@ -144,8 +144,8 @@ module ActiveSupport end end - # Stand-in for @request, @attributes, @params, etc which emits deprecation - # warnings on any method call (except #inspect). + # Stand-in for @request, @attributes, @params, etc. + # which emits deprecation warnings on any method call (except +inspect+). class DeprecatedInstanceVariableProxy #:nodoc: silence_warnings do instance_methods.each { |m| undef_method m unless m =~ /^__/ } @@ -176,19 +176,6 @@ module ActiveSupport end end - class DeprecatedInstanceVariable < Delegator #:nodoc: - def initialize(value, method) - super(value) - @method = method - @value = value - end - - def __getobj__ - ActiveSupport::Deprecation.warn("Instance variable @#{@method} is deprecated! Call instance method #{@method} instead.") - @value - end - end - end end diff --git a/vendor/rails/activesupport/lib/active_support/inflector.rb b/vendor/rails/activesupport/lib/active_support/inflector.rb index 68fbf3da..a4fd6193 100644 --- a/vendor/rails/activesupport/lib/active_support/inflector.rb +++ b/vendor/rails/activesupport/lib/active_support/inflector.rb @@ -92,6 +92,13 @@ module Inflector extend self + # Yields a singleton instance of Inflector::Inflections so you can specify additional + # inflector rules. + # + # Example: + # Inflector.inflections do |inflect| + # inflect.uncountable "rails" + # end def inflections if block_given? yield Inflections.instance @@ -102,13 +109,13 @@ module Inflector # Returns the plural form of the word in the string. # - # Examples - # "post".pluralize #=> "posts" - # "octopus".pluralize #=> "octopi" - # "sheep".pluralize #=> "sheep" - # "words".pluralize #=> "words" - # "the blue mailman".pluralize #=> "the blue mailmen" - # "CamelOctopus".pluralize #=> "CamelOctopi" + # Examples: + # "post".pluralize # => "posts" + # "octopus".pluralize # => "octopi" + # "sheep".pluralize # => "sheep" + # "words".pluralize # => "words" + # "the blue mailman".pluralize # => "the blue mailmen" + # "CamelOctopus".pluralize # => "CamelOctopi" def pluralize(word) result = word.to_s.dup @@ -120,15 +127,15 @@ module Inflector end end - # The reverse of pluralize, returns the singular form of a word in a string. + # The reverse of +pluralize+, returns the singular form of a word in a string. # - # Examples - # "posts".singularize #=> "post" - # "octopi".singularize #=> "octopus" - # "sheep".singluarize #=> "sheep" - # "word".singluarize #=> "word" - # "the blue mailmen".singularize #=> "the blue mailman" - # "CamelOctopi".singularize #=> "CamelOctopus" + # Examples: + # "posts".singularize # => "post" + # "octopi".singularize # => "octopus" + # "sheep".singluarize # => "sheep" + # "word".singluarize # => "word" + # "the blue mailmen".singularize # => "the blue mailman" + # "CamelOctopi".singularize # => "CamelOctopus" def singularize(word) result = word.to_s.dup @@ -140,16 +147,16 @@ module Inflector end end - # By default, camelize converts strings to UpperCamelCase. If the argument to camelize - # is set to ":lower" then camelize produces lowerCamelCase. + # By default, +camelize+ converts strings to UpperCamelCase. If the argument to +camelize+ + # is set to :lower then +camelize+ produces lowerCamelCase. # - # camelize will also convert '/' to '::' which is useful for converting paths to namespaces + # +camelize+ will also convert '/' to '::' which is useful for converting paths to namespaces. # - # Examples - # "active_record".camelize #=> "ActiveRecord" - # "active_record".camelize(:lower) #=> "activeRecord" - # "active_record/errors".camelize #=> "ActiveRecord::Errors" - # "active_record/errors".camelize(:lower) #=> "activeRecord::Errors" + # Examples: + # "active_record".camelize # => "ActiveRecord" + # "active_record".camelize(:lower) # => "activeRecord" + # "active_record/errors".camelize # => "ActiveRecord::Errors" + # "active_record/errors".camelize(:lower) # => "activeRecord::Errors" def camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true) if first_letter_in_uppercase lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase } @@ -159,14 +166,14 @@ module Inflector end # Capitalizes all the words and replaces some characters in the string to create - # a nicer looking title. Titleize is meant for creating pretty output. It is not + # a nicer looking title. +titleize+ is meant for creating pretty output. It is not # used in the Rails internals. # - # titleize is also aliased as as titlecase + # +titleize+ is also aliased as as +titlecase+. # - # Examples - # "man from the boondocks".titleize #=> "Man From The Boondocks" - # "x-men: the last stand".titleize #=> "X Men: The Last Stand" + # Examples: + # "man from the boondocks".titleize # => "Man From The Boondocks" + # "x-men: the last stand".titleize # => "X Men: The Last Stand" def titleize(word) humanize(underscore(word)).gsub(/\b('?[a-z])/) { $1.capitalize } end @@ -175,9 +182,9 @@ module Inflector # # Changes '::' to '/' to convert namespaces to paths. # - # Examples - # "ActiveRecord".underscore #=> "active_record" - # "ActiveRecord::Errors".underscore #=> active_record/errors + # Examples: + # "ActiveRecord".underscore # => "active_record" + # "ActiveRecord::Errors".underscore # => active_record/errors def underscore(camel_cased_word) camel_cased_word.to_s.gsub(/::/, '/'). gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). @@ -188,52 +195,52 @@ module Inflector # Replaces underscores with dashes in the string. # - # Example - # "puni_puni" #=> "puni-puni" + # Example: + # "puni_puni" # => "puni-puni" def dasherize(underscored_word) underscored_word.gsub(/_/, '-') end - # Capitalizes the first word and turns underscores into spaces and strips _id. - # Like titleize, this is meant for creating pretty output. + # Capitalizes the first word and turns underscores into spaces and strips a + # trailing "_id", if any. Like +titleize+, this is meant for creating pretty output. # - # Examples - # "employee_salary" #=> "Employee salary" - # "author_id" #=> "Author" + # Examples: + # "employee_salary" # => "Employee salary" + # "author_id" # => "Author" def humanize(lower_case_and_underscored_word) lower_case_and_underscored_word.to_s.gsub(/_id$/, "").gsub(/_/, " ").capitalize end - # Removes the module part from the expression in the string + # Removes the module part from the expression in the string. # - # Examples - # "ActiveRecord::CoreExtensions::String::Inflections".demodulize #=> "Inflections" - # "Inflections".demodulize #=> "Inflections" + # Examples: + # "ActiveRecord::CoreExtensions::String::Inflections".demodulize # => "Inflections" + # "Inflections".demodulize # => "Inflections" def demodulize(class_name_in_module) class_name_in_module.to_s.gsub(/^.*::/, '') end # Create the name of a table like Rails does for models to table names. This method - # uses the pluralize method on the last word in the string. + # uses the +pluralize+ method on the last word in the string. # # Examples - # "RawScaledScorer".tableize #=> "raw_scaled_scorers" - # "egg_and_ham".tableize #=> "egg_and_hams" - # "fancyCategory".tableize #=> "fancy_categories" + # "RawScaledScorer".tableize # => "raw_scaled_scorers" + # "egg_and_ham".tableize # => "egg_and_hams" + # "fancyCategory".tableize # => "fancy_categories" def tableize(class_name) pluralize(underscore(class_name)) end # Create a class name from a plural table name like Rails does for table names to models. # Note that this returns a string and not a Class. (To convert to an actual class - # follow classify with constantize.) + # follow +classify+ with +constantize+.) # - # Examples - # "egg_and_hams".classify #=> "EggAndHam" - # "posts".classify #=> "Post" + # Examples: + # "egg_and_hams".classify # => "EggAndHam" + # "posts".classify # => "Post" # - # Singular names are not handled correctly - # "business".classify #=> "Busines" + # Singular names are not handled correctly: + # "business".classify # => "Busines" def classify(table_name) # strip out any leading schema name camelize(singularize(table_name.to_s.sub(/.*\./, ''))) @@ -243,10 +250,10 @@ module Inflector # +separate_class_name_and_id_with_underscore+ sets whether # the method should put '_' between the name and 'id'. # - # Examples - # "Message".foreign_key #=> "message_id" - # "Message".foreign_key(false) #=> "messageid" - # "Admin::Post".foreign_key #=> "post_id" + # Examples: + # "Message".foreign_key # => "message_id" + # "Message".foreign_key(false) # => "messageid" + # "Admin::Post".foreign_key # => "post_id" def foreign_key(class_name, separate_class_name_and_id_with_underscore = true) underscore(demodulize(class_name)) + (separate_class_name_and_id_with_underscore ? "_id" : "id") end @@ -276,10 +283,10 @@ module Inflector Object.module_eval("::#{$1}", __FILE__, __LINE__) end - # Ordinalize turns a number into an ordinal string used to denote the - # position in an ordered sequence such as 1st, 2nd, 3rd, 4th. + # Turns a number into an ordinal string used to denote the position in an + # ordered sequence such as 1st, 2nd, 3rd, 4th. # - # Examples + # Examples: # ordinalize(1) # => "1st" # ordinalize(2) # => "2nd" # ordinalize(1002) # => "1002nd" diff --git a/vendor/rails/activesupport/lib/active_support/json.rb b/vendor/rails/activesupport/lib/active_support/json.rb index bbda2c9f..54a7becd 100644 --- a/vendor/rails/activesupport/lib/active_support/json.rb +++ b/vendor/rails/activesupport/lib/active_support/json.rb @@ -1,5 +1,5 @@ module ActiveSupport - # If true, use ISO 8601 format for dates and times. Otherwise, fall back to the ActiveSupport legacy format. + # If true, use ISO 8601 format for dates and times. Otherwise, fall back to the Active Support legacy format. mattr_accessor :use_standard_json_time_format class << self diff --git a/vendor/rails/activesupport/lib/active_support/json/decoding.rb b/vendor/rails/activesupport/lib/active_support/json/decoding.rb index c58001f4..fdb219db 100644 --- a/vendor/rails/activesupport/lib/active_support/json/decoding.rb +++ b/vendor/rails/activesupport/lib/active_support/json/decoding.rb @@ -31,7 +31,7 @@ module ActiveSupport if json[pos..scanner.pos-2] =~ DATE_REGEX # found a date, track the exact positions of the quotes so we can remove them later. # oh, and increment them for each current mark, each one is an extra padded space that bumps - # the position in the final yaml output + # the position in the final YAML output total_marks = marks.size times << pos+total_marks << scanner.pos+total_marks end diff --git a/vendor/rails/activesupport/lib/active_support/json/encoders/time.rb b/vendor/rails/activesupport/lib/active_support/json/encoders/time.rb index 3660d87c..57ed3c9e 100644 --- a/vendor/rails/activesupport/lib/active_support/json/encoders/time.rb +++ b/vendor/rails/activesupport/lib/active_support/json/encoders/time.rb @@ -6,7 +6,7 @@ class Time # # => 2005/02/01 15:15:10 +0000" def to_json(options = nil) if ActiveSupport.use_standard_json_time_format - utc.xmlschema.inspect + xmlschema.inspect else %("#{strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)}") end diff --git a/vendor/rails/activesupport/lib/active_support/multibyte/chars.rb b/vendor/rails/activesupport/lib/active_support/multibyte/chars.rb index 65114415..185d0302 100644 --- a/vendor/rails/activesupport/lib/active_support/multibyte/chars.rb +++ b/vendor/rails/activesupport/lib/active_support/multibyte/chars.rb @@ -10,7 +10,7 @@ module ActiveSupport::Multibyte #:nodoc: # String methods are proxied through the Chars object, and can be accessed through the +chars+ method. Methods # which would normally return a String object now return a Chars object so methods can be chained. # - # "The Perfect String ".chars.downcase.strip.normalize #=> "the perfect string" + # "The Perfect String ".chars.downcase.strip.normalize # => "the perfect string" # # Chars objects are perfectly interchangeable with String objects as long as no explicit class checks are made. # If certain methods do explicitly check the class, call +to_s+ before you pass chars objects to them. @@ -40,13 +40,15 @@ module ActiveSupport::Multibyte #:nodoc: # core dumps. Don't go there. @string end - + # Make duck-typing with String possible - def respond_to?(method) - super || @string.respond_to?(method) || handler.respond_to?(method) || - (method.to_s =~ /(.*)!/ && handler.respond_to?($1)) || false + def respond_to?(method, include_priv = false) + super || @string.respond_to?(method, include_priv) || + handler.respond_to?(method, include_priv) || + (method.to_s =~ /(.*)!/ && handler.respond_to?($1, include_priv)) || + false end - + # Create a new Chars instance. def initialize(str) @string = str.respond_to?(:string) ? str.string : str diff --git a/vendor/rails/activesupport/lib/active_support/multibyte/handlers/utf8_handler.rb b/vendor/rails/activesupport/lib/active_support/multibyte/handlers/utf8_handler.rb index 0166b69a..aa9c16f5 100644 --- a/vendor/rails/activesupport/lib/active_support/multibyte/handlers/utf8_handler.rb +++ b/vendor/rails/activesupport/lib/active_support/multibyte/handlers/utf8_handler.rb @@ -147,13 +147,11 @@ module ActiveSupport::Multibyte::Handlers #:nodoc: # # s = "Müller" # s.chars[2] = "e" # Replace character with offset 2 - # s - # #=> "Müeler" + # s # => "Müeler" # # s = "Müller" # s.chars[1, 2] = "ö" # Replace 2 characters at character offset 1 - # s - # #=> "Möler" + # s # => "Möler" def []=(str, *args) replace_by = args.pop # Indexed replace with regular expressions already works @@ -183,10 +181,10 @@ module ActiveSupport::Multibyte::Handlers #:nodoc: # Example: # # "¾ cup".chars.rjust(8).to_s - # #=> " ¾ cup" + # # => " ¾ cup" # # "¾ cup".chars.rjust(8, " ").to_s # Use non-breaking whitespace - # #=> "   ¾ cup" + # # => "   ¾ cup" def rjust(str, integer, padstr=' ') justify(str, integer, :right, padstr) end @@ -196,10 +194,10 @@ module ActiveSupport::Multibyte::Handlers #:nodoc: # Example: # # "¾ cup".chars.rjust(8).to_s - # #=> "¾ cup " + # # => "¾ cup " # # "¾ cup".chars.rjust(8, " ").to_s # Use non-breaking whitespace - # #=> "¾ cup   " + # # => "¾ cup   " def ljust(str, integer, padstr=' ') justify(str, integer, :left, padstr) end @@ -209,10 +207,10 @@ module ActiveSupport::Multibyte::Handlers #:nodoc: # Example: # # "¾ cup".chars.center(8).to_s - # #=> " ¾ cup " + # # => " ¾ cup " # # "¾ cup".chars.center(8, " ").to_s # Use non-breaking whitespace - # #=> " ¾ cup  " + # # => " ¾ cup  " def center(str, integer, padstr=' ') justify(str, integer, :center, padstr) end diff --git a/vendor/rails/activesupport/lib/active_support/ordered_hash.rb b/vendor/rails/activesupport/lib/active_support/ordered_hash.rb new file mode 100644 index 00000000..6993621e --- /dev/null +++ b/vendor/rails/activesupport/lib/active_support/ordered_hash.rb @@ -0,0 +1,43 @@ +# OrderedHash is namespaced to prevent conflicts with other implementations +module ActiveSupport + # Hash is ordered in Ruby 1.9! + if RUBY_VERSION >= '1.9' + OrderedHash = ::Hash + else + class OrderedHash < Array #:nodoc: + def []=(key, value) + if pair = assoc(key) + pair.pop + pair << value + else + self << [key, value] + end + end + + def [](key) + pair = assoc(key) + pair ? pair.last : nil + end + + def delete(key) + pair = assoc(key) + pair ? array_index = index(pair) : nil + array_index ? delete_at(array_index).last : nil + end + + def keys + collect { |key, value| key } + end + + def values + collect { |key, value| value } + end + + def to_hash + returning({}) do |hash| + each { |array| hash[array[0]] = array[1] } + end + end + end + end +end diff --git a/vendor/rails/activesupport/lib/active_support/ordered_options.rb b/vendor/rails/activesupport/lib/active_support/ordered_options.rb index 3172f62f..306376e9 100644 --- a/vendor/rails/activesupport/lib/active_support/ordered_options.rb +++ b/vendor/rails/activesupport/lib/active_support/ordered_options.rb @@ -1,47 +1,3 @@ -# OrderedHash is namespaced to prevent conflicts with other implementations -module ActiveSupport - # Hash is ordered in Ruby 1.9! - if RUBY_VERSION >= '1.9' - OrderedHash = ::Hash - else - class OrderedHash < Array #:nodoc: - def []=(key, value) - if pair = assoc(key) - pair.pop - pair << value - else - self << [key, value] - end - end - - def [](key) - pair = assoc(key) - pair ? pair.last : nil - end - - def delete(key) - pair = assoc(key) - pair ? array_index = index(pair) : nil - array_index ? delete_at(array_index).last : nil - end - - def keys - collect { |key, value| key } - end - - def values - collect { |key, value| value } - end - - def to_hash - returning({}) do |hash| - each { |array| hash[array[0]] = array[1] } - end - end - end - end -end - class OrderedOptions < ActiveSupport::OrderedHash #:nodoc: def []=(key, value) super(key.to_sym, value) diff --git a/vendor/rails/activesupport/lib/active_support/testing/setup_and_teardown.rb b/vendor/rails/activesupport/lib/active_support/testing/setup_and_teardown.rb index b2a937ed..ed8e3451 100644 --- a/vendor/rails/activesupport/lib/active_support/testing/setup_and_teardown.rb +++ b/vendor/rails/activesupport/lib/active_support/testing/setup_and_teardown.rb @@ -1,6 +1,14 @@ module ActiveSupport module Testing module SetupAndTeardown + # For compatibility with Ruby < 1.8.6 + PASSTHROUGH_EXCEPTIONS = + if defined?(Test::Unit::TestCase::PASSTHROUGH_EXCEPTIONS) + Test::Unit::TestCase::PASSTHROUGH_EXCEPTIONS + else + [NoMemoryError, SignalException, Interrupt, SystemExit] + end + def self.included(base) base.send :include, ActiveSupport::Callbacks base.define_callbacks :setup, :teardown @@ -25,7 +33,7 @@ module ActiveSupport __send__(@method_name) rescue Test::Unit::AssertionFailedError => e add_failure(e.message, e.backtrace) - rescue *Test::Unit::TestCase::PASSTHROUGH_EXCEPTIONS + rescue *PASSTHROUGH_EXCEPTIONS raise rescue Exception add_error($!) @@ -35,7 +43,7 @@ module ActiveSupport run_callbacks :teardown, :enumerator => :reverse_each rescue Test::Unit::AssertionFailedError => e add_failure(e.message, e.backtrace) - rescue *Test::Unit::TestCase::PASSTHROUGH_EXCEPTIONS + rescue *PASSTHROUGH_EXCEPTIONS raise rescue Exception add_error($!) diff --git a/vendor/rails/activesupport/lib/active_support/time_with_zone.rb b/vendor/rails/activesupport/lib/active_support/time_with_zone.rb index 21ddcaad..bfc5b160 100644 --- a/vendor/rails/activesupport/lib/active_support/time_with_zone.rb +++ b/vendor/rails/activesupport/lib/active_support/time_with_zone.rb @@ -1,7 +1,34 @@ require 'tzinfo' module ActiveSupport # A Time-like class that can represent a time in any time zone. Necessary because standard Ruby Time instances are - # limited to UTC and the system's ENV['TZ'] zone + # limited to UTC and the system's ENV['TZ'] zone. + # + # You shouldn't ever need to create a TimeWithZone instance directly via new -- instead, Rails provides the methods + # +local+, +parse+, +at+ and +now+ on TimeZone instances, and +in_time_zone+ on Time and DateTime instances, for a more + # user-friendly syntax. Examples: + # + # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)' + # Time.zone.local(2007, 2, 10, 15, 30, 45) # => Sat, 10 Feb 2007 15:30:45 EST -05:00 + # Time.zone.parse('2007-02-01 15:30:45') # => Sat, 10 Feb 2007 15:30:45 EST -05:00 + # Time.zone.at(1170361845) # => Sat, 10 Feb 2007 15:30:45 EST -05:00 + # Time.zone.now # => Sun, 18 May 2008 13:07:55 EDT -04:00 + # Time.utc(2007, 2, 10, 20, 30, 45).in_time_zone # => Sat, 10 Feb 2007 15:30:45 EST -05:00 + # + # See TimeZone and ActiveSupport::CoreExtensions::Time::Zones for further documentation for these methods. + # + # TimeWithZone instances implement the same API as Ruby Time instances, so that Time and TimeWithZone instances are interchangable. Examples: + # + # t = Time.zone.now # => Sun, 18 May 2008 13:27:25 EDT -04:00 + # t.hour # => 13 + # t.dst? # => true + # t.utc_offset # => -14400 + # t.zone # => "EDT" + # t.to_s(:rfc822) # => "Sun, 18 May 2008 13:27:25 -0400" + # t + 1.day # => Mon, 19 May 2008 13:27:25 EDT -04:00 + # t.beginning_of_year # => Tue, 01 Jan 2008 00:00:00 EST -05:00 + # t > Time.utc(1999) # => true + # t.is_a?(Time) # => true + # t.is_a?(ActiveSupport::TimeWithZone) # => true class TimeWithZone include Comparable attr_reader :time_zone @@ -11,12 +38,12 @@ module ActiveSupport @period = @utc ? period : get_period_and_ensure_valid_local_time end - # Returns a Time or DateTime instance that represents the time in time_zone + # Returns a Time or DateTime instance that represents the time in +time_zone+. def time @time ||= period.to_local(@utc) end - # Returns a Time or DateTime instance that represents the time in UTC + # Returns a Time or DateTime instance that represents the time in UTC. def utc @utc ||= period.to_utc(@time) end @@ -25,18 +52,18 @@ module ActiveSupport alias_method :getutc, :utc alias_method :gmtime, :utc - # Returns the underlying TZInfo::TimezonePeriod + # Returns the underlying TZInfo::TimezonePeriod. def period @period ||= time_zone.period_for_utc(@utc) end - # Returns the simultaneous time in Time.zone, or the specified zone + # Returns the simultaneous time in Time.zone, or the specified zone. def in_time_zone(new_zone = ::Time.zone) return self if time_zone == new_zone utc.in_time_zone(new_zone) end - # Returns a Time.local() instance of the simultaneous time in your system's ENV['TZ'] zone + # Returns a Time.local() instance of the simultaneous time in your system's ENV['TZ'] zone def localtime utc.getlocal end @@ -62,7 +89,7 @@ module ActiveSupport utc? && alternate_utc_string || utc_offset.to_utc_offset_s(colon) end - # Time uses #zone to display the time zone abbreviation, so we're duck-typing it + # Time uses +zone+ to display the time zone abbreviation, so we're duck-typing it. def zone period.zone_identifier.to_s end @@ -78,7 +105,7 @@ module ActiveSupport def to_json(options = nil) if ActiveSupport.use_standard_json_time_format - utc.xmlschema.inspect + xmlschema.inspect else %("#{time.strftime("%Y/%m/%d %H:%M:%S")} #{formatted_offset(false)}") end @@ -119,7 +146,7 @@ module ActiveSupport time.strftime(format) end - # Use the time in UTC for comparisons + # Use the time in UTC for comparisons. def <=>(other) utc <=> other end @@ -132,10 +159,10 @@ module ActiveSupport utc == other end - # If wrapped #time is a DateTime, use DateTime#since instead of #+ - # Otherwise, just pass on to #method_missing + # If wrapped +time+ is a DateTime, use DateTime#since instead of +. + # Otherwise, just pass on to +method_missing+. def +(other) - result = utc.acts_like?(:date) ? utc.since(other) : utc + other + result = utc.acts_like?(:date) ? utc.since(other) : utc + other rescue utc.since(other) result.in_time_zone(time_zone) end @@ -146,7 +173,7 @@ module ActiveSupport if other.acts_like?(:time) utc - other else - result = utc.acts_like?(:date) ? utc.ago(other) : utc - other + result = utc.acts_like?(:date) ? utc.ago(other) : utc - other rescue utc.ago(other) result.in_time_zone(time_zone) end end @@ -198,18 +225,18 @@ module ActiveSupport utc.to_datetime.new_offset(Rational(utc_offset, 86_400)) end - # so that self acts_like?(:time) + # So that +self+ acts_like?(:time). def acts_like_time? true end - # Say we're a Time to thwart type checking + # Say we're a Time to thwart type checking. def is_a?(klass) klass == ::Time || super end alias_method :kind_of?, :is_a? - # Neuter freeze because freezing can cause problems with lazy loading of attributes + # Neuter freeze because freezing can cause problems with lazy loading of attributes. def freeze self end @@ -221,15 +248,15 @@ module ActiveSupport def marshal_load(variables) initialize(variables[0], ::Time.send!(:get_zone, variables[1]), variables[2]) end - - # Ensure proxy class responds to all methods that underlying time instance responds to - def respond_to?(sym) + + # Ensure proxy class responds to all methods that underlying time instance responds to. + def respond_to?(sym, include_priv = false) # consistently respond false to acts_like?(:date), regardless of whether #time is a Time or DateTime return false if sym.to_s == 'acts_like_date?' - super || time.respond_to?(sym) + super || time.respond_to?(sym, include_priv) end - - # Send the missing method to time instance, and wrap result in a new TimeWithZone with the existing time_zone + + # Send the missing method to +time+ instance, and wrap result in a new TimeWithZone with the existing +time_zone+. def method_missing(sym, *args, &block) result = time.__send__(sym, *args, &block) result.acts_like?(:time) ? self.class.new(nil, time_zone, result) : result diff --git a/vendor/rails/activesupport/lib/active_support/values/time_zone.rb b/vendor/rails/activesupport/lib/active_support/values/time_zone.rb index 0fa99135..a71c819f 100644 --- a/vendor/rails/activesupport/lib/active_support/values/time_zone.rb +++ b/vendor/rails/activesupport/lib/active_support/values/time_zone.rb @@ -1,3 +1,24 @@ +# The TimeZone class serves as a wrapper around TZInfo::Timezone instances. It allows us to do the following: +# +# * Limit the set of zones provided by TZInfo to a meaningful subset of 142 zones. +# * Retrieve and display zones with a friendlier name (e.g., "Eastern Time (US & Canada)" instead of "America/New_York"). +# * Lazily load TZInfo::Timezone instances only when they're needed. +# * Create ActiveSupport::TimeWithZone instances via TimeZone's +local+, +parse+, +at+ and +now+ methods. +# +# If you set config.time_zone in the Rails Initializer, you can access this TimeZone object via Time.zone: +# +# # environment.rb: +# Rails::Initializer.run do |config| +# config.time_zone = "Eastern Time (US & Canada)" +# end +# +# Time.zone # => # +# Time.zone.name # => "Eastern Time (US & Canada)" +# Time.zone.now # => Sun, 18 May 2008 14:30:44 EDT -04:00 +# +# The version of TZInfo bundled with Active Support only includes the definitions necessary to support the zones +# defined by the TimeZone class. If you need to use zones that aren't defined by TimeZone, you'll need to install the TZInfo gem +# (if a recent version of the gem is installed locally, this will be used instead of the bundled version.) class TimeZone unless const_defined?(:MAPPING) # Keys are Rails TimeZone names, values are TZInfo identifiers @@ -181,7 +202,7 @@ class TimeZone # Returns a textual representation of this time zone. def to_s - "(UTC#{formatted_offset}) #{name}" + "(GMT#{formatted_offset}) #{name}" end # Method for creating new ActiveSupport::TimeWithZone instance in time zone of +self+ from given values. Example: @@ -325,6 +346,9 @@ class TimeZone ZONES.sort! ZONES.freeze ZONES_MAP.freeze + + US_ZONES = ZONES.find_all { |z| z.name =~ /US|Arizona|Indiana|Hawaii|Alaska/ } + US_ZONES.freeze end class << self @@ -332,7 +356,7 @@ class TimeZone # Return a TimeZone instance with the given name, or +nil+ if no # such TimeZone instance exists. (This exists to support the use of - # this class with the #composed_of macro.) + # this class with the +composed_of+ macro.) def new(name) self[name] end @@ -361,14 +385,10 @@ class TimeZone end end - # A regular expression that matches the names of all time zones in - # the USA. - US_ZONES = /US|Arizona|Indiana|Hawaii|Alaska/.freeze - # A convenience method for returning a collection of TimeZone objects # for time zones in the USA. def us_zones - all.find_all { |z| z.name =~ US_ZONES } + US_ZONES end end end diff --git a/vendor/rails/activesupport/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/offset_rationals.rb b/vendor/rails/activesupport/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/offset_rationals.rb index 5857de62..32fa4123 100644 --- a/vendor/rails/activesupport/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/offset_rationals.rb +++ b/vendor/rails/activesupport/lib/active_support/vendor/tzinfo-0.3.8/tzinfo/offset_rationals.rb @@ -27,63 +27,63 @@ module TZInfo # -14 and +14 hours to avoid having to call gcd at runtime. module OffsetRationals #:nodoc: @@rational_cache = { - -50400 => Rational.new!(-7,12), - -48600 => Rational.new!(-9,16), - -46800 => Rational.new!(-13,24), - -45000 => Rational.new!(-25,48), - -43200 => Rational.new!(-1,2), - -41400 => Rational.new!(-23,48), - -39600 => Rational.new!(-11,24), - -37800 => Rational.new!(-7,16), - -36000 => Rational.new!(-5,12), - -34200 => Rational.new!(-19,48), - -32400 => Rational.new!(-3,8), - -30600 => Rational.new!(-17,48), - -28800 => Rational.new!(-1,3), - -27000 => Rational.new!(-5,16), - -25200 => Rational.new!(-7,24), - -23400 => Rational.new!(-13,48), - -21600 => Rational.new!(-1,4), - -19800 => Rational.new!(-11,48), - -18000 => Rational.new!(-5,24), - -16200 => Rational.new!(-3,16), - -14400 => Rational.new!(-1,6), - -12600 => Rational.new!(-7,48), - -10800 => Rational.new!(-1,8), - -9000 => Rational.new!(-5,48), - -7200 => Rational.new!(-1,12), - -5400 => Rational.new!(-1,16), - -3600 => Rational.new!(-1,24), - -1800 => Rational.new!(-1,48), - 0 => Rational.new!(0,1), - 1800 => Rational.new!(1,48), - 3600 => Rational.new!(1,24), - 5400 => Rational.new!(1,16), - 7200 => Rational.new!(1,12), - 9000 => Rational.new!(5,48), - 10800 => Rational.new!(1,8), - 12600 => Rational.new!(7,48), - 14400 => Rational.new!(1,6), - 16200 => Rational.new!(3,16), - 18000 => Rational.new!(5,24), - 19800 => Rational.new!(11,48), - 21600 => Rational.new!(1,4), - 23400 => Rational.new!(13,48), - 25200 => Rational.new!(7,24), - 27000 => Rational.new!(5,16), - 28800 => Rational.new!(1,3), - 30600 => Rational.new!(17,48), - 32400 => Rational.new!(3,8), - 34200 => Rational.new!(19,48), - 36000 => Rational.new!(5,12), - 37800 => Rational.new!(7,16), - 39600 => Rational.new!(11,24), - 41400 => Rational.new!(23,48), - 43200 => Rational.new!(1,2), - 45000 => Rational.new!(25,48), - 46800 => Rational.new!(13,24), - 48600 => Rational.new!(9,16), - 50400 => Rational.new!(7,12)} + -50400 => Rational(-7,12), + -48600 => Rational(-9,16), + -46800 => Rational(-13,24), + -45000 => Rational(-25,48), + -43200 => Rational(-1,2), + -41400 => Rational(-23,48), + -39600 => Rational(-11,24), + -37800 => Rational(-7,16), + -36000 => Rational(-5,12), + -34200 => Rational(-19,48), + -32400 => Rational(-3,8), + -30600 => Rational(-17,48), + -28800 => Rational(-1,3), + -27000 => Rational(-5,16), + -25200 => Rational(-7,24), + -23400 => Rational(-13,48), + -21600 => Rational(-1,4), + -19800 => Rational(-11,48), + -18000 => Rational(-5,24), + -16200 => Rational(-3,16), + -14400 => Rational(-1,6), + -12600 => Rational(-7,48), + -10800 => Rational(-1,8), + -9000 => Rational(-5,48), + -7200 => Rational(-1,12), + -5400 => Rational(-1,16), + -3600 => Rational(-1,24), + -1800 => Rational(-1,48), + 0 => Rational(0,1), + 1800 => Rational(1,48), + 3600 => Rational(1,24), + 5400 => Rational(1,16), + 7200 => Rational(1,12), + 9000 => Rational(5,48), + 10800 => Rational(1,8), + 12600 => Rational(7,48), + 14400 => Rational(1,6), + 16200 => Rational(3,16), + 18000 => Rational(5,24), + 19800 => Rational(11,48), + 21600 => Rational(1,4), + 23400 => Rational(13,48), + 25200 => Rational(7,24), + 27000 => Rational(5,16), + 28800 => Rational(1,3), + 30600 => Rational(17,48), + 32400 => Rational(3,8), + 34200 => Rational(19,48), + 36000 => Rational(5,12), + 37800 => Rational(7,16), + 39600 => Rational(11,24), + 41400 => Rational(23,48), + 43200 => Rational(1,2), + 45000 => Rational(25,48), + 46800 => Rational(13,24), + 48600 => Rational(9,16), + 50400 => Rational(7,12)} # Returns a Rational expressing the fraction of a day that offset in # seconds represents (i.e. equivalent to Rational(offset, 86400)). diff --git a/vendor/rails/activesupport/lib/active_support/version.rb b/vendor/rails/activesupport/lib/active_support/version.rb index f3d141cf..b346459a 100644 --- a/vendor/rails/activesupport/lib/active_support/version.rb +++ b/vendor/rails/activesupport/lib/active_support/version.rb @@ -1,8 +1,8 @@ module ActiveSupport module VERSION #:nodoc: MAJOR = 2 - MINOR = 0 - TINY = 991 + MINOR = 1 + TINY = 0 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 706e218a..69028a12 100644 --- a/vendor/rails/activesupport/test/core_ext/hash_ext_test.rb +++ b/vendor/rails/activesupport/test/core_ext/hash_ext_test.rb @@ -733,6 +733,44 @@ class HashToXmlTest < Test::Unit::TestCase assert_equal hash, Hash.from_xml(hash.to_xml(@xml_options))['person'] end + + def test_datetime_xml_type_with_utc_time + alert_xml = <<-XML + + 2008-02-10T15:30:45Z + + XML + alert_at = Hash.from_xml(alert_xml)['alert']['alert_at'] + assert alert_at.utc? + assert_equal Time.utc(2008, 2, 10, 15, 30, 45), alert_at + end + + def test_datetime_xml_type_with_non_utc_time + alert_xml = <<-XML + + 2008-02-10T10:30:45-05:00 + + XML + alert_at = Hash.from_xml(alert_xml)['alert']['alert_at'] + assert alert_at.utc? + assert_equal Time.utc(2008, 2, 10, 15, 30, 45), alert_at + end + + def test_datetime_xml_type_with_far_future_date + alert_xml = <<-XML + + 2050-02-10T15:30:45Z + + XML + alert_at = Hash.from_xml(alert_xml)['alert']['alert_at'] + assert alert_at.utc? + assert_equal 2050, alert_at.year + assert_equal 2, alert_at.month + assert_equal 10, alert_at.day + assert_equal 15, alert_at.hour + assert_equal 30, alert_at.min + assert_equal 45, alert_at.sec + end end class QueryTest < Test::Unit::TestCase diff --git a/vendor/rails/activesupport/test/core_ext/time_with_zone_test.rb b/vendor/rails/activesupport/test/core_ext/time_with_zone_test.rb index 64fcb4af..c373bca8 100644 --- a/vendor/rails/activesupport/test/core_ext/time_with_zone_test.rb +++ b/vendor/rails/activesupport/test/core_ext/time_with_zone_test.rb @@ -70,7 +70,7 @@ class TimeWithZoneTest < Test::Unit::TestCase def test_to_json_with_use_standard_json_time_format_config_set_to_true old, ActiveSupport.use_standard_json_time_format = ActiveSupport.use_standard_json_time_format, true - assert_equal "\"2000-01-01T00:00:00Z\"", @twz.to_json + assert_equal "\"1999-12-31T19:00:00-05:00\"", @twz.to_json ensure ActiveSupport.use_standard_json_time_format = old end @@ -170,6 +170,13 @@ class TimeWithZoneTest < Test::Unit::TestCase assert_equal DateTime.civil(1999, 12, 31, 19, 0 ,5), (twz + 5).time end end + + def test_plus_when_crossing_time_class_limit + silence_warnings do # silence warnings raised by tzinfo gem + twz = ActiveSupport::TimeWithZone.new(Time.utc(2038, 1, 19), @time_zone) + assert_equal [0, 0, 19, 19, 1, 2038], (twz + 86_400).to_a[0,6] + end + end def test_plus_with_duration silence_warnings do # silence warnings raised by tzinfo gem diff --git a/vendor/rails/activesupport/test/dependencies_test.rb b/vendor/rails/activesupport/test/dependencies_test.rb index 9e98e764..0309ab68 100644 --- a/vendor/rails/activesupport/test/dependencies_test.rb +++ b/vendor/rails/activesupport/test/dependencies_test.rb @@ -584,6 +584,12 @@ class DependenciesTest < Test::Unit::TestCase assert_equal [], m end + def test_new_constants_in_with_illegal_module_name_raises_correct_error + assert_raises(NameError) do + Dependencies.new_constants_in("Illegal-Name") {} + end + end + def test_file_with_multiple_constants_and_require_dependency with_loading 'autoloading_fixtures' do assert ! defined?(MultipleConstantFile) @@ -667,7 +673,7 @@ class DependenciesTest < Test::Unit::TestCase assert !defined?(::RaisesNoMethodError), "::RaisesNoMethodError is defined but it should have failed!" end end - + ensure Object.class_eval { remove_const :RaisesNoMethodError if const_defined?(:RaisesNoMethodError) } end @@ -680,11 +686,20 @@ class DependenciesTest < Test::Unit::TestCase assert !defined?(::RaisesNoMethodError), "::RaisesNoMethodError is defined but it should have failed!" end end - + ensure Object.class_eval { remove_const :RaisesNoMethodError if const_defined?(:RaisesNoMethodError) } end + def test_autoload_doesnt_shadow_error_when_mechanism_not_set_to_load + with_loading 'autoloading_fixtures' do + Dependencies.mechanism = :require + 2.times do + assert_raise(NameError) {"RaisesNameError".constantize} + end + end + end + def test_autoload_doesnt_shadow_name_error with_loading 'autoloading_fixtures' do assert !defined?(::RaisesNameError), "::RaisesNameError is defined but it hasn't been referenced yet!" @@ -708,7 +723,7 @@ class DependenciesTest < Test::Unit::TestCase ensure Object.class_eval { remove_const :RaisesNoMethodError if const_defined?(:RaisesNoMethodError) } end - + def test_remove_constant_handles_double_colon_at_start Object.const_set 'DeleteMe', Module.new DeleteMe.const_set 'OrMe', Module.new @@ -718,7 +733,7 @@ class DependenciesTest < Test::Unit::TestCase Dependencies.remove_constant "::DeleteMe" assert ! defined?(DeleteMe) end - + def test_load_once_constants_should_not_be_unloaded with_loading 'autoloading_fixtures' do Dependencies.load_once_paths = Dependencies.load_paths @@ -731,7 +746,7 @@ class DependenciesTest < Test::Unit::TestCase Dependencies.load_once_paths = [] Object.class_eval { remove_const :A if const_defined?(:A) } end - + def test_load_once_paths_should_behave_when_recursively_loading with_loading 'dependencies', 'autoloading_fixtures' do Dependencies.load_once_paths = [Dependencies.load_paths.last] @@ -747,5 +762,4 @@ class DependenciesTest < Test::Unit::TestCase ensure Dependencies.load_once_paths = [] end - end diff --git a/vendor/rails/activesupport/test/deprecation_test.rb b/vendor/rails/activesupport/test/deprecation_test.rb index 11357e25..ebfa4059 100644 --- a/vendor/rails/activesupport/test/deprecation_test.rb +++ b/vendor/rails/activesupport/test/deprecation_test.rb @@ -149,13 +149,3 @@ class DeprecationTest < Test::Unit::TestCase assert_nil @last_message end end - -class DeprecatedIvarTest < Test::Unit::TestCase - - def test_deprecated_ivar - @action = ActiveSupport::Deprecation::DeprecatedInstanceVariable.new("fubar", :foobar) - - assert_deprecated(/Instance variable @foobar is deprecated! Call instance method foobar instead/) { assert_equal "fubar", @action } - end - -end diff --git a/vendor/rails/activesupport/test/json/encoding_test.rb b/vendor/rails/activesupport/test/json/encoding_test.rb index 7bc8eaf0..38bb8f3e 100644 --- a/vendor/rails/activesupport/test/json/encoding_test.rb +++ b/vendor/rails/activesupport/test/json/encoding_test.rb @@ -90,6 +90,15 @@ class TestJSONEncoding < Test::Unit::TestCase def test_hash_should_allow_key_filtering_with_except assert_equal %({"b": 2}), { 'foo' => 'bar', :b => 2, :c => 3 }.to_json(:except => ['foo', :c]) end + + def test_time_to_json_includes_local_offset + ActiveSupport.use_standard_json_time_format = true + with_env_tz 'US/Eastern' do + assert_equal %("2005-02-01T15:15:10-05:00"), Time.local(2005,2,1,15,15,10).to_json + end + ensure + ActiveSupport.use_standard_json_time_format = false + end protected def with_kcode(code) @@ -108,6 +117,13 @@ class TestJSONEncoding < Test::Unit::TestCase def object_keys(json_object) json_object[1..-2].scan(/([^{}:,\s]+):/).flatten.sort end + + def with_env_tz(new_tz = 'US/Eastern') + old_tz, ENV['TZ'] = ENV['TZ'], new_tz + yield + ensure + old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ') + end end uses_mocha 'JsonOptionsTests' do diff --git a/vendor/rails/activesupport/test/ordered_hash_test.rb b/vendor/rails/activesupport/test/ordered_hash_test.rb new file mode 100644 index 00000000..14be4872 --- /dev/null +++ b/vendor/rails/activesupport/test/ordered_hash_test.rb @@ -0,0 +1,45 @@ +require 'abstract_unit' + +class OrderedHashTest < Test::Unit::TestCase + def setup + @keys = %w( blue green red pink orange ) + @values = %w( 000099 009900 aa0000 cc0066 cc6633 ) + @ordered_hash = ActiveSupport::OrderedHash.new + + @keys.each_with_index do |key, index| + @ordered_hash[key] = @values[index] + end + end + + def test_order + assert_equal @keys, @ordered_hash.keys + assert_equal @values, @ordered_hash.values + end + + def test_access + assert @keys.zip(@values).all? { |k, v| @ordered_hash[k] == v } + end + + def test_assignment + key, value = 'purple', '5422a8' + + @ordered_hash[key] = value + assert_equal @keys.length + 1, @ordered_hash.length + assert_equal key, @ordered_hash.keys.last + assert_equal value, @ordered_hash.values.last + assert_equal value, @ordered_hash[key] + end + + def test_delete + key, value = 'white', 'ffffff' + bad_key = 'black' + + @ordered_hash[key] = value + assert_equal @keys.length + 1, @ordered_hash.length + + assert_equal value, @ordered_hash.delete(key) + assert_equal @keys.length, @ordered_hash.length + + assert_nil @ordered_hash.delete(bad_key) + end +end diff --git a/vendor/rails/activesupport/test/ordered_options_test.rb b/vendor/rails/activesupport/test/ordered_options_test.rb index 3d537a0a..fb7a58d0 100644 --- a/vendor/rails/activesupport/test/ordered_options_test.rb +++ b/vendor/rails/activesupport/test/ordered_options_test.rb @@ -1,49 +1,5 @@ require 'abstract_unit' -class OrderedHashTest < Test::Unit::TestCase - def setup - @keys = %w( blue green red pink orange ) - @values = %w( 000099 009900 aa0000 cc0066 cc6633 ) - @ordered_hash = ActiveSupport::OrderedHash.new - - @keys.each_with_index do |key, index| - @ordered_hash[key] = @values[index] - end - end - - def test_order - assert_equal @keys, @ordered_hash.keys - assert_equal @values, @ordered_hash.values - end - - def test_access - assert @keys.zip(@values).all? { |k, v| @ordered_hash[k] == v } - end - - def test_assignment - key, value = 'purple', '5422a8' - - @ordered_hash[key] = value - assert_equal @keys.length + 1, @ordered_hash.length - assert_equal key, @ordered_hash.keys.last - assert_equal value, @ordered_hash.values.last - assert_equal value, @ordered_hash[key] - end - - def test_delete - key, value = 'white', 'ffffff' - bad_key = 'black' - - @ordered_hash[key] = value - assert_equal @keys.length + 1, @ordered_hash.length - - assert_equal value, @ordered_hash.delete(key) - assert_equal @keys.length, @ordered_hash.length - - assert_nil @ordered_hash.delete(bad_key) - end -end - class OrderedOptionsTest < Test::Unit::TestCase def test_usage a = OrderedOptions.new diff --git a/vendor/rails/activesupport/test/time_zone_test.rb b/vendor/rails/activesupport/test/time_zone_test.rb index 3757ddce..f3069b58 100644 --- a/vendor/rails/activesupport/test/time_zone_test.rb +++ b/vendor/rails/activesupport/test/time_zone_test.rb @@ -252,7 +252,7 @@ class TimeZoneTest < Test::Unit::TestCase end def test_to_s - assert_equal "(UTC+03:00) Moscow", TimeZone['Moscow'].to_s + assert_equal "(GMT+03:00) Moscow", TimeZone['Moscow'].to_s end def test_all_sorted diff --git a/vendor/rails/railties/CHANGELOG b/vendor/rails/railties/CHANGELOG index 11d2926f..fe517755 100644 --- a/vendor/rails/railties/CHANGELOG +++ b/vendor/rails/railties/CHANGELOG @@ -1,4 +1,4 @@ -*2.1.0 RC1 (May 11th, 2008)* +*2.1.0 (May 31st, 2008)* * script/dbconsole fires up the command-line database client. #102 [Steve Purcell] diff --git a/vendor/rails/railties/README b/vendor/rails/railties/README index b5f4eee4..2af0fb11 100644 --- a/vendor/rails/railties/README +++ b/vendor/rails/railties/README @@ -145,7 +145,9 @@ and also on programming in general. Debugger support is available through the debugger command when you start your Mongrel or Webrick server with --debugger. This means that you can break out of execution at any point -in the code, investigate and change the model, AND then resume execution! Example: +in the code, investigate and change the model, AND then resume execution! +You need to install ruby-debug to run the server in debugging mode. With gems, use 'gem install ruby-debug' +Example: class WeblogController < ActionController::Base def index @@ -183,6 +185,13 @@ Passing an argument will specify a different environment, like script/consol To reload your controllers and models after launching the console run reload! +== dbconsole + +You can go to the command line of your database directly through script/dbconsole. +You would be connected to the database with the credentials defined in database.yml. +Starting the script without arguments will connect you to the development database. Passing an +argument will connect you to a different database, like script/dbconsole production. +Currently works for mysql, postgresql and sqlite. == Description of Contents @@ -200,13 +209,13 @@ app/models app/views Holds the template files for the view that should be named like - weblogs/index.erb for the WeblogsController#index action. All views use eRuby + weblogs/index.html.erb for the WeblogsController#index action. All views use eRuby syntax. app/views/layouts Holds the template files for layouts to be used with views. This models the common header/footer method of wrapping views. In your views, define a layout using the - layout :default and create a file named default.erb. Inside default.erb, + layout :default and create a file named default.html.erb. Inside default.html.erb, call <% yield %> to render the view using this layout. app/helpers @@ -243,4 +252,5 @@ test vendor External libraries that the application depends on. Also includes the plugins subdirectory. + If the app has frozen rails, those gems also go here, under vendor/rails/. This directory is in the load path. diff --git a/vendor/rails/railties/Rakefile b/vendor/rails/railties/Rakefile index 45ba3942..a1d1095c 100644 --- a/vendor/rails/railties/Rakefile +++ b/vendor/rails/railties/Rakefile @@ -304,11 +304,11 @@ spec = Gem::Specification.new do |s| EOF s.add_dependency('rake', '>= 0.8.1') - s.add_dependency('activesupport', '= 2.0.991' + PKG_BUILD) - s.add_dependency('activerecord', '= 2.0.991' + PKG_BUILD) - s.add_dependency('actionpack', '= 2.0.991' + PKG_BUILD) - s.add_dependency('actionmailer', '= 2.0.991' + PKG_BUILD) - s.add_dependency('activeresource', '= 2.0.991' + PKG_BUILD) + s.add_dependency('activesupport', '= 2.1.0' + PKG_BUILD) + s.add_dependency('activerecord', '= 2.1.0' + PKG_BUILD) + s.add_dependency('actionpack', '= 2.1.0' + PKG_BUILD) + s.add_dependency('actionmailer', '= 2.1.0' + PKG_BUILD) + s.add_dependency('activeresource', '= 2.1.0' + PKG_BUILD) s.rdoc_options << '--exclude' << '.' s.has_rdoc = false diff --git a/vendor/rails/railties/configs/databases/frontbase.yml b/vendor/rails/railties/configs/databases/frontbase.yml index 2eed3133..c0c3588b 100644 --- a/vendor/rails/railties/configs/databases/frontbase.yml +++ b/vendor/rails/railties/configs/databases/frontbase.yml @@ -10,8 +10,8 @@ development: username: <%= app_name %> password: '' -# Warning: The database defined as 'test' will be erased and -# re-generated from your development database when you run 'rake'. +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: adapter: frontbase diff --git a/vendor/rails/railties/configs/databases/mysql.yml b/vendor/rails/railties/configs/databases/mysql.yml index c5c894c5..7fcadcdf 100644 --- a/vendor/rails/railties/configs/databases/mysql.yml +++ b/vendor/rails/railties/configs/databases/mysql.yml @@ -26,8 +26,8 @@ development: host: localhost <% end -%> -# Warning: The database defined as 'test' will be erased and -# re-generated from your development database when you run 'rake'. +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: adapter: mysql diff --git a/vendor/rails/railties/configs/databases/oracle.yml b/vendor/rails/railties/configs/databases/oracle.yml index c86cbdba..a1883f62 100644 --- a/vendor/rails/railties/configs/databases/oracle.yml +++ b/vendor/rails/railties/configs/databases/oracle.yml @@ -4,7 +4,7 @@ # http://rubyforge.org/projects/ruby-oci8/ # # Specify your database using any valid connection syntax, such as a -# tnsnames.ora service name, or a sql connect url string of the form: +# tnsnames.ora service name, or a SQL connect url string of the form: # # //host:[port][/service name] # @@ -23,8 +23,8 @@ development: username: <%= app_name %> password: -# Warning: The database defined as 'test' will be erased and -# re-generated from your development database when you run 'rake'. +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: adapter: oracle diff --git a/vendor/rails/railties/configs/databases/postgresql.yml b/vendor/rails/railties/configs/databases/postgresql.yml index c1b911a9..36f6e5ae 100644 --- a/vendor/rails/railties/configs/databases/postgresql.yml +++ b/vendor/rails/railties/configs/databases/postgresql.yml @@ -30,8 +30,8 @@ development: # The server defaults to notice. #min_messages: warning -# Warning: The database defined as 'test' will be erased and -# re-generated from your development database when you run 'rake'. +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: adapter: postgresql diff --git a/vendor/rails/railties/configs/databases/sqlite2.yml b/vendor/rails/railties/configs/databases/sqlite2.yml index 26d3957d..fc48bd67 100644 --- a/vendor/rails/railties/configs/databases/sqlite2.yml +++ b/vendor/rails/railties/configs/databases/sqlite2.yml @@ -4,8 +4,8 @@ development: adapter: sqlite database: db/development.sqlite2 -# Warning: The database defined as 'test' will be erased and -# re-generated from your development database when you run 'rake'. +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: adapter: sqlite diff --git a/vendor/rails/railties/configs/databases/sqlite3.yml b/vendor/rails/railties/configs/databases/sqlite3.yml index b444b03c..fff44a41 100644 --- a/vendor/rails/railties/configs/databases/sqlite3.yml +++ b/vendor/rails/railties/configs/databases/sqlite3.yml @@ -5,8 +5,8 @@ development: database: db/development.sqlite3 timeout: 5000 -# Warning: The database defined as 'test' will be erased and -# re-generated from your development database when you run 'rake'. +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. test: adapter: sqlite3 diff --git a/vendor/rails/railties/configs/initializers/new_rails_defaults.rb b/vendor/rails/railties/configs/initializers/new_rails_defaults.rb index 3a617e3a..5e60c0ad 100644 --- a/vendor/rails/railties/configs/initializers/new_rails_defaults.rb +++ b/vendor/rails/railties/configs/initializers/new_rails_defaults.rb @@ -1,15 +1,15 @@ -# These settins change the behavior of Rails 2 apps and will be defaults +# These settings change the behavior of Rails 2 apps and will be defaults # for Rails 3. You can remove this initializer when Rails 3 is released. -# Only save the attributes that have changed since the record was loaded. -ActiveRecord::Base.partial_updates = true - -# Include ActiveRecord class name as root for JSON serialized output. +# Include Active Record class name as root for JSON serialized output. ActiveRecord::Base.include_root_in_json = true -# Use ISO 8601 format for JSON serialized times and dates +# Store the full class name (including module namespace) in STI type column. +ActiveRecord::Base.store_full_sti_class = true + +# Use ISO 8601 format for JSON serialized times and dates. ActiveSupport.use_standard_json_time_format = true -# Don't escape HTML entities in JSON, leave that for the #json_escape helper +# Don't escape HTML entities in JSON, leave that for the #json_escape helper. # if you're including raw json in an HTML page. ActiveSupport.escape_html_entities_in_json = false \ No newline at end of file diff --git a/vendor/rails/railties/environments/environment.rb b/vendor/rails/railties/environments/environment.rb index c33b80da..a85ade37 100644 --- a/vendor/rails/railties/environments/environment.rb +++ b/vendor/rails/railties/environments/environment.rb @@ -21,7 +21,7 @@ Rails::Initializer.run do |config| # config.frameworks -= [ :active_record, :active_resource, :action_mailer ] # Specify gems that this application depends on. - # They can then be installed with rake gem:install on new installations. + # They can then be installed with "rake gems:install" on new installations. # config.gem "bj" # config.gem "hpricot", :version => '0.6', :source => "http://code.whytheluckystiff.net" # config.gem "aws-s3", :lib => "aws/s3" @@ -38,9 +38,9 @@ Rails::Initializer.run do |config| # (by default production uses :info, the others :debug) # config.log_level = :debug - # Make Time.zone default to the specified zone, and make ActiveRecord store time values + # Make Time.zone default to the specified zone, and make Active Record store time values # in the database in UTC, and return them converted to the specified local zone. - # Run `rake -D time` for a list of tasks for finding time zone names. Uncomment to use default local time. + # Run "rake -D time" for a list of tasks for finding time zone names. Uncomment to use default local time. config.time_zone = 'UTC' # Your secret key for verifying cookie session data integrity. @@ -54,7 +54,7 @@ Rails::Initializer.run do |config| # Use the database for sessions instead of the cookie-based default, # which shouldn't be used to store highly confidential information - # (create the session table with 'rake db:sessions:create') + # (create the session table with "rake db:sessions:create") # config.action_controller.session_store = :active_record_store # Use SQL instead of Active Record's schema dumper when creating the test database. @@ -64,4 +64,4 @@ Rails::Initializer.run do |config| # Activate observers that should always be running # config.active_record.observers = :cacher, :garbage_collector -end \ No newline at end of file +end diff --git a/vendor/rails/railties/environments/test.rb b/vendor/rails/railties/environments/test.rb index 58850a79..1e709e1d 100644 --- a/vendor/rails/railties/environments/test.rb +++ b/vendor/rails/railties/environments/test.rb @@ -16,7 +16,7 @@ config.action_controller.perform_caching = false # Disable request forgery protection in test environment config.action_controller.allow_forgery_protection = false -# Tell ActionMailer not to deliver emails to the real world. +# Tell Action Mailer not to deliver emails to the real world. # The :test delivery method accumulates sent emails in the # ActionMailer::Base.deliveries array. config.action_mailer.delivery_method = :test diff --git a/vendor/rails/railties/lib/commands/console.rb b/vendor/rails/railties/lib/commands/console.rb index edffe4f1..2b9d92f6 100644 --- a/vendor/rails/railties/lib/commands/console.rb +++ b/vendor/rails/railties/lib/commands/console.rb @@ -24,9 +24,9 @@ ENV['RAILS_ENV'] = case ARGV.first end if options[:sandbox] - puts "Loading #{ENV['RAILS_ENV']} environment in sandbox (Rails #{Rails::VERSION::STRING})" + puts "Loading #{ENV['RAILS_ENV']} environment in sandbox (Rails #{Rails.version})" puts "Any modifications you make will be rolled back on exit" else - puts "Loading #{ENV['RAILS_ENV']} environment (Rails #{Rails::VERSION::STRING})" + puts "Loading #{ENV['RAILS_ENV']} environment (Rails #{Rails.version})" end exec "#{options[:irb]} #{libs} --simple-prompt" diff --git a/vendor/rails/railties/lib/commands/dbconsole.rb b/vendor/rails/railties/lib/commands/dbconsole.rb index 3e5010c6..17acb7b6 100644 --- a/vendor/rails/railties/lib/commands/dbconsole.rb +++ b/vendor/rails/railties/lib/commands/dbconsole.rb @@ -2,8 +2,13 @@ require 'erb' require 'yaml' require 'optparse' +include_password = false + OptionParser.new do |opt| - opt.banner = "Usage: dbconsole [environment]" + opt.banner = "Usage: dbconsole [options] [environment]" + opt.on("-p", "--include-password", "Automatically provide the database from database.yml") do |v| + include_password = true + end opt.parse!(ARGV) abort opt.to_s unless (0..1).include?(ARGV.size) end @@ -31,19 +36,23 @@ when "mysql" 'port' => '--port', 'socket' => '--socket', 'username' => '--user', - 'password' => '--password', 'encoding' => '--default-character-set' }.map { |opt, arg| "#{arg}=#{config[opt]}" if config[opt] }.compact + if config['password'] && include_password + args << "--password=#{config['password']}" + end + args << config['database'] exec(find_cmd('mysql5', 'mysql'), *args) when "postgresql" + ENV['PGUSER'] = config["username"] if config["username"] ENV['PGHOST'] = config["host"] if config["host"] ENV['PGPORT'] = config["port"].to_s if config["port"] - ENV['PGPASSWORD'] = config["password"].to_s if config["password"] - exec(find_cmd('psql'), '-U', config["username"], config["database"]) + ENV['PGPASSWORD'] = config["password"].to_s if config["password"] && include_password + exec(find_cmd('psql'), config["database"]) when "sqlite" exec(find_cmd('sqlite'), config["database"]) diff --git a/vendor/rails/railties/lib/commands/plugin.rb b/vendor/rails/railties/lib/commands/plugin.rb index d12d002c..105819ce 100644 --- a/vendor/rails/railties/lib/commands/plugin.rb +++ b/vendor/rails/railties/lib/commands/plugin.rb @@ -163,7 +163,7 @@ class Plugin end def git_url? - @uri =~ /^git:\/\// || @url =~ /\.git$/ + @uri =~ /^git:\/\// || @uri =~ /\.git$/ end def installed? diff --git a/vendor/rails/railties/lib/commands/servers/lighttpd.rb b/vendor/rails/railties/lib/commands/servers/lighttpd.rb index 07d4f9d0..c9d13e86 100644 --- a/vendor/rails/railties/lib/commands/servers/lighttpd.rb +++ b/vendor/rails/railties/lib/commands/servers/lighttpd.rb @@ -62,7 +62,7 @@ config = IO.read(config_file) default_port, default_ip = 3000, '0.0.0.0' port = config.scan(/^\s*server.port\s*=\s*(\d+)/).first rescue default_port ip = config.scan(/^\s*server.bind\s*=\s*"([^"]+)"/).first rescue default_ip -puts "=> Rails application starting on http://#{ip || default_ip}:#{port || default_port}" +puts "=> Rails #{Rails.version} application starting on http://#{ip || default_ip}:#{port || default_port}" tail_thread = nil diff --git a/vendor/rails/railties/lib/commands/servers/mongrel.rb b/vendor/rails/railties/lib/commands/servers/mongrel.rb index f59265e6..7bb110f6 100644 --- a/vendor/rails/railties/lib/commands/servers/mongrel.rb +++ b/vendor/rails/railties/lib/commands/servers/mongrel.rb @@ -32,7 +32,7 @@ ARGV.clone.options do |opts| opts.parse! end -puts "=> Rails application starting on http://#{OPTIONS[:ip]}:#{OPTIONS[:port]}" +puts "=> Rails #{Rails.version} application starting on http://#{OPTIONS[:ip]}:#{OPTIONS[:port]}" parameters = [ "start", diff --git a/vendor/rails/railties/lib/commands/servers/webrick.rb b/vendor/rails/railties/lib/commands/servers/webrick.rb index b9503761..18c8897c 100644 --- a/vendor/rails/railties/lib/commands/servers/webrick.rb +++ b/vendor/rails/railties/lib/commands/servers/webrick.rb @@ -61,6 +61,6 @@ require 'webrick_server' OPTIONS['working_directory'] = File.expand_path(RAILS_ROOT) -puts "=> Rails application started on http://#{OPTIONS[:ip]}:#{OPTIONS[:port]}" +puts "=> Rails #{Rails.version} application started on http://#{OPTIONS[:ip]}:#{OPTIONS[:port]}" puts "=> Ctrl-C to shutdown server; call with --help for options" if OPTIONS[:server_type] == WEBrick::SimpleServer DispatchServlet.dispatch(OPTIONS) diff --git a/vendor/rails/railties/lib/initializer.rb b/vendor/rails/railties/lib/initializer.rb index dfd43042..ca63fa73 100644 --- a/vendor/rails/railties/lib/initializer.rb +++ b/vendor/rails/railties/lib/initializer.rb @@ -43,6 +43,10 @@ module Rails RAILS_CACHE end + def version + VERSION::STRING + end + def public_path @@public_path ||= self.root ? File.join(self.root, "public") : "public" end @@ -136,7 +140,8 @@ module Rails # pick up any gems that plugins depend on add_gem_load_paths load_gems - + check_gem_dependencies + load_application_initializers # the framework is now fully initialized @@ -149,6 +154,7 @@ module Rails initialize_routing # Observers are loaded after plugins in case Observers or observed models are modified by plugins. + load_observers end @@ -160,12 +166,12 @@ module Rails end # If Rails is vendored and RubyGems is available, install stub GemSpecs - # for Rails, ActiveSupport, ActiveRecord, ActionPack, ActionMailer, and - # ActiveResource. This allows Gem plugins to depend on Rails even when + # for Rails, Active Support, Active Record, Action Pack, Action Mailer, and + # Active Resource. This allows Gem plugins to depend on Rails even when # the Gem version of Rails shouldn't be loaded. def install_gem_spec_stubs unless Rails.respond_to?(:vendor_rails?) - abort "Your config/boot.rb is outdated: Run 'rake rails:update'." + abort %{Your config/boot.rb is outdated: Run "rake rails:update".} end if Rails.vendor_rails? @@ -210,8 +216,8 @@ module Rails end # Requires all frameworks specified by the Configuration#frameworks - # list. By default, all frameworks (ActiveRecord, ActiveSupport, - # ActionPack, ActionMailer, and ActiveResource) are loaded. + # list. By default, all frameworks (Active Record, Active Support, + # Action Pack, Action Mailer, and Active Resource) are loaded. def require_frameworks configuration.frameworks.each { |framework| require(framework.to_s) } rescue LoadError => e @@ -237,7 +243,24 @@ module Rails end def load_gems - @configuration.gems.each &:load + @configuration.gems.each(&:load) + end + + def check_gem_dependencies + unloaded_gems = @configuration.gems.reject { |g| g.loaded? } + if unloaded_gems.size > 0 + @gems_dependencies_loaded = false + # don't print if the gems rake tasks are being run + unless $rails_gem_installer + puts %{These gems that this application depends on are missing:} + unloaded_gems.each do |gem| + puts " - #{gem.name}" + end + puts %{Run "rake gems:install" to install them.} + end + else + @gems_dependencies_loaded = true + end end # Loads all plugins in config.plugin_paths. plugin_paths @@ -283,12 +306,8 @@ module Rails end def load_observers - if configuration.frameworks.include?(:active_record) - if @configuration.gems.any? { |g| !g.loaded? } - puts "Unable to instantiate observers, some gems that this application depends on are missing. Run 'rake gems:install'" - else - ActiveRecord::Base.instantiate_observers - end + if @gems_dependencies_loaded && configuration.frameworks.include?(:active_record) + ActiveRecord::Base.instantiate_observers end end @@ -326,7 +345,7 @@ module Rails end end - # If the +RAILS_DEFAULT_LOGGER+ constant is already set, this initialization + # If the RAILS_DEFAULT_LOGGER constant is already set, this initialization # routine does nothing. If the constant is not set, and Configuration#logger # is not +nil+, this also does nothing. Otherwise, a new logger instance # is created at Configuration#log_path, with a default log level of @@ -359,10 +378,10 @@ module Rails silence_warnings { Object.const_set "RAILS_DEFAULT_LOGGER", logger } end - # Sets the logger for ActiveRecord, ActionController, and ActionMailer + # Sets the logger for Active Record, Action Controller, and Action Mailer # (but only for those frameworks that are to be loaded). If the framework's # logger is already set, it is not changed, otherwise it is set to use - # +RAILS_DEFAULT_LOGGER+. + # RAILS_DEFAULT_LOGGER. def initialize_framework_logging for framework in ([ :active_record, :action_controller, :action_mailer ] & configuration.frameworks) framework.to_s.camelize.constantize.const_get("Base").logger ||= RAILS_DEFAULT_LOGGER @@ -380,7 +399,7 @@ module Rails ActionController::Base.view_paths = [configuration.view_path] if configuration.frameworks.include?(:action_controller) && ActionController::Base.view_paths.empty? end - # If ActionController is not one of the loaded frameworks (Configuration#frameworks) + # If Action Controller is not one of the loaded frameworks (Configuration#frameworks) # this does nothing. Otherwise, it loads the routing definitions and sets up # loading module used to lazily load controllers (Configuration#controller_paths). def initialize_routing @@ -409,13 +428,13 @@ module Rails end end - # Sets the default value for Time.zone, and turns on ActiveRecord time_zone_aware_attributes. + # Sets the default value for Time.zone, and turns on ActiveRecord::Base#time_zone_aware_attributes. # If assigned value cannot be matched to a TimeZone, an exception will be raised. def initialize_time_zone if configuration.time_zone zone_default = Time.send!(:get_zone, configuration.time_zone) unless zone_default - raise "Value assigned to config.time_zone not recognized. Run `rake -D time` for a list of tasks for finding appropriate time zone names." + raise %{Value assigned to config.time_zone not recognized. Run "rake -D time" for a list of tasks for finding appropriate time zone names.} end Time.zone_default = zone_default if configuration.frameworks.include?(:active_record) @@ -443,14 +462,18 @@ module Rails # Fires the user-supplied after_initialize block (Configuration#after_initialize) def after_initialize - configuration.after_initialize_blocks.each do |block| - block.call + if @gems_dependencies_loaded + configuration.after_initialize_blocks.each do |block| + block.call + end end end def load_application_initializers - Dir["#{configuration.root_path}/config/initializers/**/*.rb"].sort.each do |initializer| - load(initializer) + if @gems_dependencies_loaded + Dir["#{configuration.root_path}/config/initializers/**/*.rb"].sort.each do |initializer| + load(initializer) + end end end @@ -475,22 +498,22 @@ module Rails # The application's base directory. attr_reader :root_path - # A stub for setting options on ActionController::Base + # A stub for setting options on ActionController::Base. attr_accessor :action_controller - # A stub for setting options on ActionMailer::Base + # A stub for setting options on ActionMailer::Base. attr_accessor :action_mailer - # A stub for setting options on ActionView::Base + # A stub for setting options on ActionView::Base. attr_accessor :action_view - # A stub for setting options on ActiveRecord::Base + # A stub for setting options on ActiveRecord::Base. attr_accessor :active_record - # A stub for setting options on ActiveRecord::Base + # A stub for setting options on ActiveRecord::Base. attr_accessor :active_resource - # A stub for setting options on ActiveSupport + # A stub for setting options on ActiveSupport. attr_accessor :active_support # Whether or not classes should be cached (set to false if you want @@ -618,9 +641,9 @@ module Rails end alias_method :breakpoint_server=, :breakpoint_server - # Sets the default time_zone. Setting this will enable time_zone - # awareness for ActiveRecord models and set the ActiveRecord default - # timezone to :utc. + # Sets the default +time_zone+. Setting this will enable +time_zone+ + # awareness for Active Record models and set the Active Record default + # timezone to :utc. attr_accessor :time_zone # Create a new Configuration instance, initialized with the default @@ -685,7 +708,7 @@ module Rails end # Return the currently selected environment. By default, it returns the - # value of the +RAILS_ENV+ constant. + # value of the RAILS_ENV constant. def environment ::RAILS_ENV end @@ -843,7 +866,7 @@ end # Needs to be duplicated from Active Support since its needed before Active # Support is available. Here both Options and Hash are namespaced to prevent -# conflicts with other implementations AND with the classes residing in ActiveSupport. +# conflicts with other implementations AND with the classes residing in Active Support. class Rails::OrderedOptions < Array #:nodoc: def []=(key, value) key = key.to_sym diff --git a/vendor/rails/railties/lib/rails/gem_dependency.rb b/vendor/rails/railties/lib/rails/gem_dependency.rb index 2034841c..9f088a18 100644 --- a/vendor/rails/railties/lib/rails/gem_dependency.rb +++ b/vendor/rails/railties/lib/rails/gem_dependency.rb @@ -31,12 +31,13 @@ module Rails args << @requirement.to_s if @requirement gem *args else - $LOAD_PATH << File.join(unpacked_paths.first, 'lib') + $LOAD_PATH.unshift File.join(unpacked_paths.first, 'lib') + ext = File.join(unpacked_paths.first, 'ext') + $LOAD_PATH.unshift(ext) if File.exist?(ext) @frozen = true end @load_paths_added = true rescue Gem::LoadError - puts $!.to_s end def dependencies @@ -73,7 +74,9 @@ module Rails end def install - Gem::GemRunner.new.run(install_command) + cmd = "#{gem_command} #{install_command.join(' ')}" + puts cmd + puts %x(#{cmd}) end def unpack_to(directory) @@ -100,10 +103,14 @@ private ################################################################### def specification @spec ||= Gem.source_index.search(Gem::Dependency.new(@name, @requirement)).sort_by { |s| s.version }.last end + + def gem_command + RUBY_PLATFORM =~ /win32/ ? 'gem.bat' : 'gem' + end def install_command cmd = %w(install) << @name - cmd << "--version" << "#{@requirement.to_s}" if @requirement + cmd << "--version" << %("#{@requirement.to_s}") if @requirement cmd << "--source" << @source if @source cmd end diff --git a/vendor/rails/railties/lib/rails/mongrel_server/commands.rb b/vendor/rails/railties/lib/rails/mongrel_server/commands.rb index 3786a56f..0a92f418 100644 --- a/vendor/rails/railties/lib/rails/mongrel_server/commands.rb +++ b/vendor/rails/railties/lib/rails/mongrel_server/commands.rb @@ -119,7 +119,7 @@ module Rails config = RailsConfigurator.new(settings) do defaults[:log] = $stdout if defaults[:environment] == 'development' - Mongrel.log("=> Rails application starting on http://#{defaults[:host]}:#{defaults[:port]}") + Mongrel.log("=> Rails #{Rails.version} application starting on http://#{defaults[:host]}:#{defaults[:port]}") unless defaults[:daemon] Mongrel.log("=> Call with -d to detach") diff --git a/vendor/rails/railties/lib/rails/plugin.rb b/vendor/rails/railties/lib/rails/plugin.rb index 04f7e37a..256f4b01 100644 --- a/vendor/rails/railties/lib/rails/plugin.rb +++ b/vendor/rails/railties/lib/rails/plugin.rb @@ -98,23 +98,18 @@ module Rails end end - # This Plugin subclass represents a Gem plugin. It behaves exactly like a - # "traditional" Rails plugin, but doesn't expose any additional load paths, - # since RubyGems has already taken care of things. + # This Plugin subclass represents a Gem plugin. Although RubyGems has already + # taken care of $LOAD_PATHs, it exposes its load_paths to add them + # to Dependencies.load_paths. class GemPlugin < Plugin - # Initialize this plugin from a Gem::Specification. def initialize(spec) - super(File.join(spec.full_gem_path, "rails")) + super(File.join(spec.full_gem_path)) @name = spec.name end - def valid? - true - end - - def load_paths - [] + def init_path + File.join(directory, 'rails', 'init.rb') end end end \ No newline at end of file diff --git a/vendor/rails/railties/lib/rails/plugin/locator.rb b/vendor/rails/railties/lib/rails/plugin/locator.rb index fd7de4ee..f06a51a5 100644 --- a/vendor/rails/railties/lib/rails/plugin/locator.rb +++ b/vendor/rails/railties/lib/rails/plugin/locator.rb @@ -78,11 +78,12 @@ module Rails # a rails/init.rb file. class GemLocator < Locator def plugins - specs = initializer.configuration.gems.map(&:specification) - specs + Gem.loaded_specs.values.select do |spec| + specs = initializer.configuration.gems.map(&:specification) + specs += Gem.loaded_specs.values.select do |spec| spec.loaded_from && # prune stubs File.exist?(File.join(spec.full_gem_path, "rails", "init.rb")) end + specs.compact! require "rubygems/dependency_list" diff --git a/vendor/rails/railties/lib/rails/version.rb b/vendor/rails/railties/lib/rails/version.rb index fea63bee..48d24da5 100644 --- a/vendor/rails/railties/lib/rails/version.rb +++ b/vendor/rails/railties/lib/rails/version.rb @@ -1,8 +1,8 @@ module Rails module VERSION #:nodoc: MAJOR = 2 - MINOR = 0 - TINY = 991 + MINOR = 1 + TINY = 0 STRING = [MAJOR, MINOR, TINY].join('.') end diff --git a/vendor/rails/railties/lib/rails_generator/base.rb b/vendor/rails/railties/lib/rails_generator/base.rb index 1ebcff90..b5cfe798 100644 --- a/vendor/rails/railties/lib/rails_generator/base.rb +++ b/vendor/rails/railties/lib/rails_generator/base.rb @@ -36,7 +36,7 @@ module Rails # view.html.erb # # The directory name (+controller+) matches the name of the generator file - # (controller_generator.rb) and class (+ControllerGenerator+). The files + # (controller_generator.rb) and class (ControllerGenerator). The files # that will be copied or used as templates are stored in the +templates+ # directory. # diff --git a/vendor/rails/railties/lib/rails_generator/commands.rb b/vendor/rails/railties/lib/rails_generator/commands.rb index 440bab27..08ecbfb5 100644 --- a/vendor/rails/railties/lib/rails_generator/commands.rb +++ b/vendor/rails/railties/lib/rails_generator/commands.rb @@ -154,28 +154,35 @@ HELP # Ruby or Rails. In the future, expand to check other namespaces # such as the rest of the user's app. def class_collisions(*class_names) + + # Initialize some check varibles + last_class = Object + current_class = nil + name = nil + class_names.flatten.each do |class_name| # Convert to string to allow symbol arguments. class_name = class_name.to_s # Skip empty strings. - next if class_name.strip.empty? + class_name.strip.empty? ? next : current_class = class_name # Split the class from its module nesting. nesting = class_name.split('::') name = nesting.pop # Extract the last Module in the nesting. - last = nesting.inject(Object) { |last, nest| - break unless last.const_defined?(nest) - last.const_get(nest) + last = nesting.inject(last_class) { |last, nest| + break unless last_class.const_defined?(nest) + last_class = last_class.const_get(nest) } - # If the last Module exists, check whether the given - # class exists and raise a collision if so. - if last and last.const_defined?(name.camelize) - raise_class_collision(class_name) - end + end + # If the last Module exists, check whether the given + # class exists and raise a collision if so. + + if last_class and last_class.const_defined?(name.camelize) + raise_class_collision(current_class) end end @@ -373,12 +380,14 @@ HELP # Thanks to Florian Gross (flgr). def raise_class_collision(class_name) message = <rake -T notes and railties/lib/tasks/annotations.rake. +# +# Annotation objects are triplets :line, :tag, :text that +# represent the line where the annotation lives, its tag, and its text. Note +# the filename is not stored. +# +# Annotations are looked for in comments and modulus whitespace they have to +# start with the tag optionally followed by a colon. Everything up to the end +# of the line (or closing ERb comment tag) is considered to be their text. class SourceAnnotationExtractor class Annotation < Struct.new(:line, :tag, :text) + + # Returns a representation of the annotation that looks like this: + # + # [126] [TODO] This algorithm is simple and clearly correct, make it faster. + # + # If +options+ has a flag :tag the tag is shown as in the example above. + # Otherwise the string contains just line and text. def to_s(options={}) s = "[%3d] " % line s << "[#{tag}] " if options[:tag] @@ -7,6 +28,12 @@ class SourceAnnotationExtractor end end + # Prints all annotations with tag +tag+ under the root directories +app+, +lib+, + # and +test+ (recursively). Only filenames with extension +.builder+, +.rb+, + # +.rxml+, +.rjs+, +.rhtml+, or +.erb+ are taken into account. The +options+ + # hash is passed to each annotation's +to_s+. + # + # This class method is the single entry point for the rake tasks. def self.enumerate(tag, options={}) extractor = new(tag) extractor.display(extractor.find, options) @@ -18,10 +45,18 @@ class SourceAnnotationExtractor @tag = tag end + # Returns a hash that maps filenames under +dirs+ (recursively) to arrays + # with their annotations. Only files with annotations are included, and only + # those with extension +.builder+, +.rb+, +.rxml+, +.rjs+, +.rhtml+, and +.erb+ + # are taken into account. def find(dirs=%w(app lib test)) dirs.inject({}) { |h, dir| h.update(find_in(dir)) } end + # Returns a hash that maps filenames under +dir+ (recursively) to arrays + # with their annotations. Only files with annotations are included, and only + # those with extension +.builder+, +.rb+, +.rxml+, +.rjs+, +.rhtml+, and +.erb+ + # are taken into account. def find_in(dir) results = {} @@ -40,6 +75,9 @@ class SourceAnnotationExtractor results end + # If +file+ is the filename of a file that contains annotations this method returns + # a hash with a single entry that maps +file+ to an array of its annotations. + # Otherwise it returns an empty hash. def extract_annotations_from(file, pattern) lineno = 0 result = File.readlines(file).inject([]) do |list, line| @@ -50,6 +88,8 @@ class SourceAnnotationExtractor result.empty? ? {} : { file => result } end + # Prints the mapping from filenames to annotations in +results+ ordered by filename. + # The +options+ hash is passed to each annotation's +to_s+. def display(results, options={}) results.keys.sort.each do |file| puts "#{file}:" diff --git a/vendor/rails/railties/lib/tasks/databases.rake b/vendor/rails/railties/lib/tasks/databases.rake index 63f71448..8077d0a4 100644 --- a/vendor/rails/railties/lib/tasks/databases.rake +++ b/vendor/rails/railties/lib/tasks/databases.rake @@ -45,7 +45,7 @@ namespace :db do when 'postgresql' @encoding = config[:encoding] || ENV['CHARSET'] || 'utf8' begin - ActiveRecord::Base.establish_connection(config.merge('database' => 'template1')) + ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public')) ActiveRecord::Base.connection.create_database(config['database'], config.merge('encoding' => @encoding)) ActiveRecord::Base.establish_connection(config) rescue @@ -173,7 +173,7 @@ namespace :db do pending_migrations.each do |pending_migration| puts ' %4d %s' % [pending_migration.version, pending_migration.name] end - abort "Run `rake db:migrate` to update your database then try again." + abort %{Run "rake db:migrate" to update your database then try again.} end end end @@ -368,7 +368,7 @@ def drop_database(config) when /^sqlite/ FileUtils.rm(File.join(RAILS_ROOT, config['database'])) when 'postgresql' - ActiveRecord::Base.establish_connection(config.merge('database' => 'template1')) + ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public')) ActiveRecord::Base.connection.drop_database config['database'] end end diff --git a/vendor/rails/railties/lib/tasks/gems.rake b/vendor/rails/railties/lib/tasks/gems.rake index c18fea2d..0321e60e 100644 --- a/vendor/rails/railties/lib/tasks/gems.rake +++ b/vendor/rails/railties/lib/tasks/gems.rake @@ -1,5 +1,5 @@ desc "List the gems that this rails application depends on" -task :gems => :environment do +task :gems => 'gems:base' do Rails.configuration.gems.each do |gem| code = gem.loaded? ? (gem.frozen? ? "F" : "I") : " " puts "[#{code}] #{gem.name} #{gem.requirement.to_s}" @@ -10,8 +10,14 @@ task :gems => :environment do end namespace :gems do + task :base do + $rails_gem_installer = true + Rake::Task[:environment].invoke + end + desc "Build any native extensions for unpacked gems" task :build do + $rails_gem_installer = true require 'rails/gem_builder' Dir[File.join(RAILS_ROOT, 'vendor', 'gems', '*')].each do |gem_dir| spec_file = File.join(gem_dir, '.specification') @@ -24,14 +30,14 @@ namespace :gems do end desc "Installs all required gems for this application." - task :install => :environment do + task :install => :base do require 'rubygems' require 'rubygems/gem_runner' Rails.configuration.gems.each { |gem| gem.install unless gem.loaded? } end desc "Unpacks the specified gem into vendor/gems." - task :unpack => :environment do + task :unpack => :base do require 'rubygems' require 'rubygems/gem_runner' Rails.configuration.gems.each do |gem| diff --git a/vendor/rails/railties/test/fixtures/about_yml_plugins/bad_about_yml/about.yml b/vendor/rails/railties/test/fixtures/about_yml_plugins/bad_about_yml/about.yml index 79d5721a..fe80872a 100644 --- a/vendor/rails/railties/test/fixtures/about_yml_plugins/bad_about_yml/about.yml +++ b/vendor/rails/railties/test/fixtures/about_yml_plugins/bad_about_yml/about.yml @@ -1 +1 @@ -# an empty yaml file - any content in here seems to get parsed as a string \ No newline at end of file +# an empty YAML file - any content in here seems to get parsed as a string \ No newline at end of file diff --git a/vendor/rails/railties/test/generators/generator_test_helper.rb b/vendor/rails/railties/test/generators/generator_test_helper.rb index 190bc91d..05dca340 100644 --- a/vendor/rails/railties/test/generators/generator_test_helper.rb +++ b/vendor/rails/railties/test/generators/generator_test_helper.rb @@ -13,7 +13,7 @@ module ActiveRecord module ConnectionAdapters class Column attr_reader :name, :default, :type, :limit, :null, :sql_type, :precision, :scale - + def initialize(name, default, sql_type = nil) @name = name @default = default @@ -59,16 +59,16 @@ require 'rails_generator' class GeneratorTestCase < Test::Unit::TestCase include FileUtils - + def setup ActiveRecord::Base.pluralize_table_names = true - + mkdir_p "#{RAILS_ROOT}/app/views/layouts" mkdir_p "#{RAILS_ROOT}/config" mkdir_p "#{RAILS_ROOT}/db" mkdir_p "#{RAILS_ROOT}/test/fixtures" mkdir_p "#{RAILS_ROOT}/public/stylesheets" - + File.open("#{RAILS_ROOT}/config/routes.rb", 'w') do |f| f << "ActionController::Routing::Routes.draw do |map|\n\nend" end @@ -85,20 +85,20 @@ class GeneratorTestCase < Test::Unit::TestCase def test_truth # don't complain, test/unit end - - # Instantiates the Generator + + # Instantiates the Generator. def build_generator(name, params) Rails::Generator::Base.instance(name, params) end - # Runs the create command (like the command line does) + # Runs the +create+ command (like the command line does). def run_generator(name, params) silence_generator do build_generator(name, params).command(:create).invoke! end end - # Silences the logger temporarily and returns the output as a String + # Silences the logger temporarily and returns the output as a String. def silence_generator logger_original = Rails::Generator::Base.logger myout = StringIO.new @@ -108,7 +108,7 @@ class GeneratorTestCase < Test::Unit::TestCase myout.string end - # asserts that the given controller was generated. + # Asserts that the given controller was generated. # It takes a name or symbol without the _controller part and an optional super class. # The contents of the class source file is passed to a block. def assert_generated_controller_for(name, parent = "ApplicationController") @@ -117,44 +117,44 @@ class GeneratorTestCase < Test::Unit::TestCase end end - # asserts that the given model was generated. + # Asserts that the given model was generated. # It takes a name or symbol and an optional super class. - # the contents of the class source file is passed to a block. + # The contents of the class source file is passed to a block. def assert_generated_model_for(name, parent = "ActiveRecord::Base") assert_generated_class "app/models/#{name.to_s.underscore}", parent do |body| yield body if block_given? end end - # asserts that the given helper was generated. - # It takes a name or symbol without the _helper part - # the contents of the module source file is passed to a block. + # Asserts that the given helper was generated. + # It takes a name or symbol without the _helper part. + # The contents of the module source file is passed to a block. def assert_generated_helper_for(name) assert_generated_module "app/helpers/#{name.to_s.underscore}_helper" do |body| yield body if block_given? end end - # asserts that the given functional test was generated. + # Asserts that the given functional test was generated. # It takes a name or symbol without the _controller_test part and an optional super class. - # the contents of the class source file is passed to a block. + # The contents of the class source file is passed to a block. def assert_generated_functional_test_for(name, parent = "ActionController::TestCase") assert_generated_class "test/functional/#{name.to_s.underscore}_controller_test",parent do |body| yield body if block_given? end end - # asserts that the given unit test was generated. + # Asserts that the given unit test was generated. # It takes a name or symbol without the _test part and an optional super class. - # the contents of the class source file is passed to a block. + # The contents of the class source file is passed to a block. def assert_generated_unit_test_for(name, parent = "ActiveSupport::TestCase") assert_generated_class "test/unit/#{name.to_s.underscore}_test", parent do |body| yield body if block_given? end end - # asserts that the given file was generated. - # the contents of the file is passed to a block. + # Asserts that the given file was generated. + # The contents of the file is passed to a block. def assert_generated_file(path) assert_file_exists(path) File.open("#{RAILS_ROOT}/#{path}") do |f| @@ -168,42 +168,56 @@ class GeneratorTestCase < Test::Unit::TestCase "The file '#{RAILS_ROOT}/#{path}' should exist" end - # asserts that the given class source file was generated. + # Asserts that the given class source file was generated. # It takes a path without the .rb part and an optional super class. - # the contents of the class source file is passed to a block. - def assert_generated_class(path, parent=nil) - path =~ /\/?(\d+_)?(\w+)$/ - class_name = $2.camelize + # The contents of the class source file is passed to a block. + def assert_generated_class(path, parent = nil) + # FIXME: Sucky way to detect namespaced classes + if path.split('/').size > 3 + path =~ /\/?(\d+_)?(\w+)\/(\w+)$/ + class_name = "#{$2.camelize}::#{$3.camelize}" + else + path =~ /\/?(\d+_)?(\w+)$/ + class_name = $2.camelize + end + assert_generated_file("#{path}.rb") do |body| assert_match /class #{class_name}#{parent.nil? ? '':" < #{parent}"}/, body, "the file '#{path}.rb' should be a class" yield body if block_given? end end - # asserts that the given module source file was generated. + # Asserts that the given module source file was generated. # It takes a path without the .rb part. - # the contents of the class source file is passed to a block. + # The contents of the class source file is passed to a block. def assert_generated_module(path) - path =~ /\/?(\w+)$/ - module_name = $1.camelize + # FIXME: Sucky way to detect namespaced modules + if path.split('/').size > 3 + path =~ /\/?(\w+)\/(\w+)$/ + module_name = "#{$1.camelize}::#{$2.camelize}" + else + path =~ /\/?(\w+)$/ + module_name = $1.camelize + end + assert_generated_file("#{path}.rb") do |body| assert_match /module #{module_name}/, body, "the file '#{path}.rb' should be a module" yield body if block_given? end end - # asserts that the given css stylesheet file was generated. + # Asserts that the given CSS stylesheet file was generated. # It takes a path without the .css part. - # the contents of the stylesheet source file is passed to a block. + # The contents of the stylesheet source file is passed to a block. def assert_generated_stylesheet(path) assert_generated_file("public/stylesheets/#{path}.css") do |body| yield body if block_given? end end - # asserts that the given yaml file was generated. + # Asserts that the given YAML file was generated. # It takes a path without the .yml part. - # the parsed yaml tree is passed to a block. + # The parsed YAML tree is passed to a block. def assert_generated_yaml(path) assert_generated_file("#{path}.yml") do |body| yaml = YAML.load(body) @@ -212,18 +226,18 @@ class GeneratorTestCase < Test::Unit::TestCase end end - # asserts that the given fixtures yaml file was generated. + # Asserts that the given fixtures yaml file was generated. # It takes a fixture name without the .yml part. - # the parsed yaml tree is passed to a block. + # The parsed YAML tree is passed to a block. def assert_generated_fixtures_for(name) assert_generated_yaml "test/fixtures/#{name.to_s.underscore}" do |yaml| yield yaml if block_given? end end - # asserts that the given views were generated. + # Asserts that the given views were generated. # It takes a controller name and a list of views (including extensions). - # The body of each view is passed to a block + # The body of each view is passed to a block. def assert_generated_views_for(name, *actions) actions.each do |action| assert_generated_file("app/views/#{name.to_s.underscore}/#{action}") do |body| @@ -248,7 +262,7 @@ class GeneratorTestCase < Test::Unit::TestCase assert !File.exist?(migration_file), "should not create migration #{migration_file}" end - # asserts that the given resource was added to the routes. + # Asserts that the given resource was added to the routes. def assert_added_route_for(name) assert_generated_file("config/routes.rb") do |body| assert_match /map.resources :#{name.to_s.underscore}/, body, @@ -256,7 +270,7 @@ class GeneratorTestCase < Test::Unit::TestCase end end - # asserts that the given methods are defined in the body. + # Asserts that the given methods are defined in the body. # This does assume standard rails code conventions with regards to the source code. # The body of each individual method is passed to a block. def assert_has_method(body, *methods) @@ -266,7 +280,7 @@ class GeneratorTestCase < Test::Unit::TestCase end end - # asserts that the given column is defined in the migration + # Asserts that the given column is defined in the migration. def assert_generated_column(body, name, type) assert_match /t\.#{type.to_s} :#{name.to_s}/, body, "should have column #{name.to_s} defined" end diff --git a/vendor/rails/railties/test/generators/rails_controller_generator_test.rb b/vendor/rails/railties/test/generators/rails_controller_generator_test.rb new file mode 100644 index 00000000..0090d21b --- /dev/null +++ b/vendor/rails/railties/test/generators/rails_controller_generator_test.rb @@ -0,0 +1,20 @@ +require 'generators/generator_test_helper' + +class RailsControllerGeneratorTest < GeneratorTestCase + + def test_controller_generates_controller + run_generator('controller', %w(products)) + + assert_generated_controller_for :products + assert_generated_functional_test_for :products + assert_generated_helper_for :products + end + + def test_controller_generates_namespaced_controller + run_generator('controller', %w(admin::products)) + + assert_generated_controller_for "admin::products" + assert_generated_functional_test_for "admin::products" + assert_generated_helper_for "admin::products" + end +end