aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--.gitmodules6
-rw-r--r--Gemfile46
-rw-r--r--Rakefile4
-rw-r--r--actionmailer/Rakefile14
-rw-r--r--actionmailer/lib/action_mailer/base.rb6
-rw-r--r--actionmailer/test/abstract_unit.rb4
-rw-r--r--actionmailer/test/mail_service_test.rb2
-rw-r--r--actionpack/actionpack.gemspec6
-rw-r--r--actionpack/lib/abstract_controller/layouts.rb2
-rw-r--r--actionpack/lib/abstract_controller/rendering_controller.rb6
-rw-r--r--actionpack/lib/action_controller/caching.rb1
-rw-r--r--actionpack/lib/action_controller/metal/request_forgery_protection.rb5
-rw-r--r--actionpack/lib/action_controller/metal/responder.rb44
-rw-r--r--actionpack/lib/action_controller/metal/streaming.rb2
-rw-r--r--actionpack/lib/action_controller/translation.rb4
-rwxr-xr-xactionpack/lib/action_dispatch/http/request.rb6
-rw-r--r--actionpack/lib/action_dispatch/middleware/stack.rb6
-rw-r--r--actionpack/lib/action_dispatch/routing.rb117
-rw-r--r--actionpack/lib/action_dispatch/routing/deprecated_mapper.rb3
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb32
-rw-r--r--actionpack/lib/action_dispatch/routing/route_set.rb71
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions.rb19
-rw-r--r--actionpack/lib/action_view/erb/util.rb1
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb13
-rw-r--r--actionpack/lib/action_view/helpers/translation_helper.rb2
-rw-r--r--actionpack/lib/action_view/test_case.rb1
-rw-r--r--actionpack/test/abstract/layouts_test.rb2
-rw-r--r--actionpack/test/abstract_unit.rb22
-rw-r--r--actionpack/test/controller/filters_test.rb1
-rw-r--r--actionpack/test/controller/mime_responds_test.rb22
-rw-r--r--actionpack/test/controller/new_base/render_action_test.rb2
-rw-r--r--actionpack/test/controller/request_forgery_protection_test.rb20
-rw-r--r--actionpack/test/controller/routing_test.rb108
-rw-r--r--actionpack/test/dispatch/request_test.rb4
-rw-r--r--actionpack/test/dispatch/routing_test.rb52
-rw-r--r--actionpack/test/dispatch/test_request_test.rb2
-rw-r--r--actionpack/test/template/form_helper_test.rb66
-rw-r--r--actionpack/test/template/test_case_test.rb13
-rw-r--r--actionpack/test/template/url_helper_test.rb45
-rwxr-xr-xactivemodel/Rakefile27
-rw-r--r--activemodel/lib/active_model/translation.rb2
-rw-r--r--activemodel/test/cases/helper.rb4
-rw-r--r--activerecord/Rakefile12
-rw-r--r--activerecord/activerecord.gemspec2
-rw-r--r--activerecord/lib/active_record/association_preload.rb20
-rwxr-xr-xactiverecord/lib/active_record/associations.rb33
-rw-r--r--activerecord/lib/active_record/associations/association_proxy.rb14
-rw-r--r--activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb14
-rw-r--r--activerecord/lib/active_record/attribute_methods.rb7
-rw-r--r--activerecord/lib/active_record/attribute_methods/dirty.rb2
-rwxr-xr-xactiverecord/lib/active_record/base.rb1
-rw-r--r--activerecord/lib/active_record/locking/optimistic.rb34
-rw-r--r--activerecord/lib/active_record/nested_attributes.rb2
-rw-r--r--activerecord/lib/active_record/notifications.rb4
-rw-r--r--activerecord/lib/active_record/relation.rb10
-rw-r--r--activerecord/lib/active_record/validations.rb2
-rw-r--r--activerecord/test/cases/associations/habtm_join_table_test.rb16
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb12
-rw-r--r--activerecord/test/cases/associations/has_many_through_associations_test.rb22
-rw-r--r--activerecord/test/cases/copy_table_test_sqlite.rb4
-rw-r--r--activerecord/test/cases/helper.rb4
-rw-r--r--activerecord/test/cases/locking_test.rb31
-rw-r--r--activerecord/test/cases/pooled_connections_test.rb2
-rw-r--r--activerecord/test/cases/reflection_test.rb4
-rw-r--r--activerecord/test/cases/relations_test.rb2
-rw-r--r--activerecord/test/fixtures/edges.yml3
-rw-r--r--activerecord/test/models/company.rb2
-rw-r--r--activerecord/test/models/pirate.rb2
-rw-r--r--activerecord/test/models/ship.rb2
-rw-r--r--activerecord/test/schema/schema.rb2
-rw-r--r--activeresource/Rakefile15
-rw-r--r--activeresource/lib/active_resource/base.rb39
-rw-r--r--activeresource/lib/active_resource/connection.rb9
-rw-r--r--activeresource/test/abstract_unit.rb4
-rw-r--r--activeresource/test/cases/base/load_test.rb1
-rw-r--r--activesupport/lib/active_support/cache.rb3
-rw-r--r--activesupport/lib/active_support/cache/mem_cache_store.rb5
-rw-r--r--activesupport/lib/active_support/core_ext/array/wrap.rb7
-rw-r--r--activesupport/lib/active_support/core_ext/date.rb7
-rw-r--r--activesupport/lib/active_support/core_ext/date/conversions.rb3
-rw-r--r--activesupport/lib/active_support/core_ext/date_time.rb5
-rw-r--r--activesupport/lib/active_support/core_ext/enumerable.rb9
-rw-r--r--activesupport/lib/active_support/core_ext/hash/conversions.rb3
-rw-r--r--activesupport/lib/active_support/core_ext/integer.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/integer/even_odd.rb16
-rw-r--r--activesupport/lib/active_support/core_ext/integer/multiple.rb6
-rw-r--r--activesupport/lib/active_support/core_ext/kernel/debugger.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/logger.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/name_error.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/object/extending.rb27
-rw-r--r--activesupport/lib/active_support/core_ext/object/instance_variables.rb7
-rw-r--r--activesupport/lib/active_support/core_ext/object/misc.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/object/tap.rb16
-rw-r--r--activesupport/lib/active_support/core_ext/string.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/string/access.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/string/bytesize.rb5
-rw-r--r--activesupport/lib/active_support/core_ext/string/interpolation.rb3
-rw-r--r--activesupport/lib/active_support/core_ext/string/iterators.rb13
-rw-r--r--activesupport/lib/active_support/core_ext/string/starts_ends_with.rb14
-rw-r--r--activesupport/lib/active_support/core_ext/symbol.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/symbol/to_proc.rb14
-rw-r--r--activesupport/lib/active_support/core_ext/time.rb10
-rw-r--r--activesupport/lib/active_support/dependencies.rb2
-rw-r--r--activesupport/lib/active_support/deprecated_callbacks.rb5
-rw-r--r--activesupport/lib/active_support/inflector.rb411
-rw-r--r--activesupport/lib/active_support/inflector/inflections.rb211
-rw-r--r--activesupport/lib/active_support/inflector/methods.rb139
-rw-r--r--activesupport/lib/active_support/inflector/transliterate.rb61
-rw-r--r--activesupport/lib/active_support/json/backends/jsongem.rb21
-rw-r--r--activesupport/lib/active_support/json/encoding.rb2
-rw-r--r--activesupport/lib/active_support/message_verifier.rb2
-rw-r--r--activesupport/lib/active_support/multibyte/chars.rb5
-rw-r--r--activesupport/lib/active_support/notifications.rb102
-rw-r--r--activesupport/lib/active_support/rescuable.rb2
-rw-r--r--activesupport/lib/active_support/ruby/shim.rb6
-rw-r--r--activesupport/lib/active_support/testing/isolation.rb15
-rw-r--r--activesupport/lib/active_support/testing/setup_and_teardown.rb4
-rw-r--r--activesupport/lib/active_support/time.rb26
-rw-r--r--activesupport/lib/active_support/time_with_zone.rb8
-rw-r--r--activesupport/lib/active_support/values/time_zone.rb4
-rw-r--r--activesupport/lib/active_support/vendor.rb2
-rw-r--r--activesupport/lib/active_support/whiny_nil.rb10
-rw-r--r--activesupport/test/abstract_unit.rb17
-rw-r--r--activesupport/test/caching_test.rb4
-rw-r--r--activesupport/test/core_ext/array_ext_test.rb20
-rw-r--r--activesupport/test/core_ext/date_ext_test.rb2
-rw-r--r--activesupport/test/core_ext/date_time_ext_test.rb2
-rw-r--r--activesupport/test/core_ext/enumerable_test.rb12
-rw-r--r--activesupport/test/core_ext/integer_ext_test.rb16
-rw-r--r--activesupport/test/core_ext/name_error_test.rb26
-rw-r--r--activesupport/test/core_ext/object_and_class_ext_test.rb7
-rw-r--r--activesupport/test/core_ext/object_ext_test.rb9
-rw-r--r--activesupport/test/core_ext/range_ext_test.rb2
-rw-r--r--activesupport/test/core_ext/string_ext_test.rb29
-rw-r--r--activesupport/test/core_ext/symbol_test.rb9
-rw-r--r--activesupport/test/dependencies_test.rb1
-rw-r--r--activesupport/test/i18n_test.rb4
-rw-r--r--activesupport/test/json/decoding_test.rb1
-rw-r--r--activesupport/test/message_encryptor_test.rb1
-rw-r--r--activesupport/test/message_verifier_test.rb2
-rw-r--r--activesupport/test/multibyte_chars_test.rb10
-rw-r--r--activesupport/test/multibyte_utils_test.rb1
-rw-r--r--activesupport/test/notifications_test.rb40
-rw-r--r--activesupport/test/whiny_nil_test.rb14
m---------arel6
-rwxr-xr-xci/ci_build.rb64
-rw-r--r--ci/geminstaller.yml25
m---------rack-mount0
-rw-r--r--railties/CHANGELOG2
-rw-r--r--railties/Rakefile32
-rw-r--r--railties/lib/rails.rb12
-rw-r--r--railties/lib/rails/application.rb55
-rw-r--r--railties/lib/rails/commands/console.rb85
-rw-r--r--railties/lib/rails/commands/destroy.rb3
-rwxr-xr-xrailties/lib/rails/commands/generate.rb3
-rw-r--r--railties/lib/rails/commands/server.rb120
-rw-r--r--railties/lib/rails/configuration.rb35
-rw-r--r--railties/lib/rails/generators.rb36
-rw-r--r--railties/lib/rails/generators/base.rb56
-rw-r--r--railties/lib/rails/generators/rails/app/app_generator.rb6
-rwxr-xr-xrailties/lib/rails/generators/rails/app/templates/script/about (renamed from railties/lib/rails/generators/rails/app/templates/script/about.tt)1
-rwxr-xr-xrailties/lib/rails/generators/rails/app/templates/script/console (renamed from railties/lib/rails/generators/rails/app/templates/script/console.tt)2
-rwxr-xr-xrailties/lib/rails/generators/rails/app/templates/script/dbconsole (renamed from railties/lib/rails/generators/rails/app/templates/script/dbconsole.tt)1
-rwxr-xr-xrailties/lib/rails/generators/rails/app/templates/script/destroy (renamed from railties/lib/rails/generators/rails/app/templates/script/destroy.tt)3
-rwxr-xr-xrailties/lib/rails/generators/rails/app/templates/script/generate (renamed from railties/lib/rails/generators/rails/app/templates/script/generate.tt)3
-rwxr-xr-xrailties/lib/rails/generators/rails/app/templates/script/performance/benchmarker (renamed from railties/lib/rails/generators/rails/app/templates/script/performance/benchmarker.tt)1
-rwxr-xr-xrailties/lib/rails/generators/rails/app/templates/script/performance/profiler (renamed from railties/lib/rails/generators/rails/app/templates/script/performance/profiler.tt)1
-rwxr-xr-xrailties/lib/rails/generators/rails/app/templates/script/plugin (renamed from railties/lib/rails/generators/rails/app/templates/script/plugin.tt)1
-rwxr-xr-xrailties/lib/rails/generators/rails/app/templates/script/runner (renamed from railties/lib/rails/generators/rails/app/templates/script/runner.tt)1
-rwxr-xr-xrailties/lib/rails/generators/rails/app/templates/script/server (renamed from railties/lib/rails/generators/rails/app/templates/script/server.tt)2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/test/performance/browsing_test.rb2
-rw-r--r--railties/lib/rails/generators/test_unit/performance/templates/performance_test.rb2
-rw-r--r--railties/lib/rails/initializable.rb3
-rw-r--r--railties/lib/rails/initializer.rb14
-rw-r--r--railties/lib/rails/paths.rb6
-rw-r--r--railties/lib/rails/plugin.rb209
-rw-r--r--railties/lib/rails/plugin/loader.rb200
-rw-r--r--railties/lib/rails/plugin/locator.rb100
-rw-r--r--railties/lib/rails/rack/debugger.rb2
-rw-r--r--railties/lib/rails/rack/static.rb2
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/CHANGELOG.rdoc (renamed from railties/lib/rails/vendor/thor-0.11.8/CHANGELOG.rdoc)7
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/LICENSE (renamed from railties/lib/rails/vendor/thor-0.11.8/LICENSE)0
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/README.rdoc (renamed from railties/lib/rails/vendor/thor-0.11.8/README.rdoc)0
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/Thorfile (renamed from railties/lib/rails/vendor/thor-0.11.8/Thorfile)0
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor.rb)0
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions.rb)0
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/create_file.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions/create_file.rb)1
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/directory.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions/directory.rb)14
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/empty_directory.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions/empty_directory.rb)1
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/file_manipulation.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions/file_manipulation.rb)0
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/inject_into_file.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions/inject_into_file.rb)0
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor/base.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor/base.rb)0
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor/core_ext/hash_with_indifferent_access.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor/core_ext/hash_with_indifferent_access.rb)0
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor/core_ext/ordered_hash.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor/core_ext/ordered_hash.rb)0
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor/error.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor/error.rb)0
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor/group.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor/group.rb)2
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor/invocation.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor/invocation.rb)0
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor/parser.rb)0
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/argument.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor/parser/argument.rb)0
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/arguments.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor/parser/arguments.rb)0
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/option.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor/parser/option.rb)0
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/options.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor/parser/options.rb)0
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor/rake_compat.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor/rake_compat.rb)0
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor/runner.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor/runner.rb)0
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor/shell.rb)0
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell/basic.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor/shell/basic.rb)0
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell/color.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor/shell/color.rb)0
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor/task.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor/task.rb)0
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor/util.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor/util.rb)0
-rw-r--r--railties/lib/rails/vendor/thor-0.12.0/lib/thor/version.rb (renamed from railties/lib/rails/vendor/thor-0.11.8/lib/thor/version.rb)0
-rw-r--r--railties/test/application/notifications_test.rb4
-rw-r--r--railties/test/application/plugins_test.rb117
-rw-r--r--railties/test/backtrace_cleaner_test.rb4
-rw-r--r--railties/test/fixtures/vendor/plugins/mspec/lib/rails_generators/mspec_generator.rb (renamed from railties/test/fixtures/vendor/plugins/mspec/lib/generators/mspec_generator.rb)0
-rw-r--r--railties/test/generators_test.rb12
-rw-r--r--railties/test/initializable_test.rb8
-rw-r--r--railties/test/initializer/initialize_i18n_test.rb42
-rw-r--r--railties/test/isolation/abstract_unit.rb36
-rw-r--r--railties/test/plugin_loader_test.rb176
-rw-r--r--railties/test/plugin_locator_test.rb73
-rw-r--r--railties/test/plugin_test.rb174
-rw-r--r--railties/test/plugin_test_helper.rb29
-rw-r--r--railties/test/plugins/vendored_test.rb190
-rw-r--r--railties/test/rails_info_controller_test.rb5
-rw-r--r--railties/test/rails_info_test.rb13
226 files changed, 1914 insertions, 2695 deletions
diff --git a/.gitignore b/.gitignore
index 3b922f29f7..70b7c0057a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -27,6 +27,7 @@ railties/guides/output
*.rbc
*.swp
*.swo
+*.tmproj
bin
vendor/gems/
railties/tmp
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000000..20ed3ed9c9
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,6 @@
+[submodule "arel"]
+ path = arel
+ url = git://github.com/rails/arel.git
+[submodule "rack-mount"]
+ path = rack-mount
+ url = git://github.com/rails/rack-mount.git
diff --git a/Gemfile b/Gemfile
index a60c1010d9..87bf43b786 100644
--- a/Gemfile
+++ b/Gemfile
@@ -1,22 +1,32 @@
-clear_sources
-source 'http://gemcutter.org'
+gem "rake", ">= 0.8.7"
+gem "mocha", ">= 0.9.8"
gem "rails", "3.0.pre", :vendored_at => "railties"
-%w(
- activesupport
- activemodel
- actionpack
- actionmailer
- activerecord
- activeresource
-).each do |lib|
+%w(activesupport activemodel actionpack actionmailer activerecord activeresource).each do |lib|
gem lib, '3.0.pre', :vendored_at => lib
end
-gem "rack", "1.0.1"
-gem "rack-mount", :git => "git://github.com/rails/rack-mount.git"
-gem "rack-test", "~> 0.5.0"
-gem "erubis", "~> 2.6.0"
-gem "arel", "0.1.3", :git => "git://github.com/rails/arel.git"
-gem "mocha"
-gem "sqlite3-ruby"
-gem "RedCloth"
+
+# AR
+gem "arel", "0.2.pre", :git => "git://github.com/rails/arel.git"
+gem "sqlite3-ruby", ">= 1.2.5"
+gem "pg", ">= 0.8.0"
+gem "mysql", ">= 2.8.1"
+
+# AP
+gem "rack", "1.0.1", :git => "git://github.com/rails/rack.git"
+gem "RedCloth", ">= 4.2.2"
+
+if ENV['CI']
+ disable_system_gems
+
+ gem "nokogiri", ">= 1.4.0"
+ gem "memcache-client", ">= 1.7.6"
+
+ # fcgi gem doesn't compile on 1.9
+ # avoid minitest strangeness on 1.9
+ if RUBY_VERSION < '1.9.0'
+ gem "fcgi", ">= 0.8.7"
+ else
+ gem "test-unit", ">= 2.0.5"
+ end
+end
diff --git a/Rakefile b/Rakefile
index f9255a4269..6aa8f61028 100644
--- a/Rakefile
+++ b/Rakefile
@@ -10,9 +10,9 @@ Dir["#{File.dirname(__FILE__)}/*/lib/*/version.rb"].each do |version_path|
end
desc 'Run all tests by default'
-task :default => :test
+task :default => %w(test test:isolated)
-%w(test isolated_test rdoc pgem package release gem gemspec).each do |task_name|
+%w(test test:isolated rdoc pgem package release gem gemspec).each do |task_name|
desc "Run #{task_name} task for all projects"
task task_name do
errors = []
diff --git a/actionmailer/Rakefile b/actionmailer/Rakefile
index 96c84b986e..1a7ece5068 100644
--- a/actionmailer/Rakefile
+++ b/actionmailer/Rakefile
@@ -24,14 +24,16 @@ Rake::TestTask.new { |t|
t.libs << "test"
t.pattern = 'test/*_test.rb'
t.verbose = true
- t.warning = false
+ t.warning = true
}
-task :isolated_test do
- ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME'))
- Dir.glob("test/*_test.rb").all? do |file|
- system(ruby, '-Ilib:test', file)
- end or raise "Failures"
+namespace :test do
+ task :isolated do
+ ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME'))
+ Dir.glob("test/*_test.rb").all? do |file|
+ system(ruby, '-Ilib:test', file)
+ end or raise "Failures"
+ end
end
# Generate the RDoc documentation
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index 9876b88ecd..3639992ce9 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -480,6 +480,8 @@ module ActionMailer #:nodoc:
# remain uninitialized (useful when you only need to invoke the "receive"
# method, for instance).
def initialize(method_name=nil, *parameters) #:nodoc:
+ @_response_body = nil
+ super()
create!(method_name, *parameters) if method_name
end
@@ -493,8 +495,8 @@ module ActionMailer #:nodoc:
create_parts
# Set the subject if not set yet
- @subject ||= I18n.t(method_name, :scope => [:actionmailer, :subjects, mailer_name],
- :default => method_name.humanize)
+ @subject ||= I18n.t(:subject, :scope => [:actionmailer, mailer_name, method_name],
+ :default => method_name.humanize)
# build the mail object itself
@mail = create_mail
diff --git a/actionmailer/test/abstract_unit.rb b/actionmailer/test/abstract_unit.rb
index fcbaa9e186..e84b3b0d23 100644
--- a/actionmailer/test/abstract_unit.rb
+++ b/actionmailer/test/abstract_unit.rb
@@ -4,9 +4,11 @@ begin
rescue LoadError
$:.unshift("#{root}/activesupport/lib")
$:.unshift("#{root}/actionpack/lib")
- $:.unshift("#{root}/actionmailer/lib")
end
+lib = File.expand_path("#{File.dirname(__FILE__)}/../lib")
+$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib)
+
require 'rubygems'
require 'test/unit'
diff --git a/actionmailer/test/mail_service_test.rb b/actionmailer/test/mail_service_test.rb
index c49657acd7..7a47a654cd 100644
--- a/actionmailer/test/mail_service_test.rb
+++ b/actionmailer/test/mail_service_test.rb
@@ -415,7 +415,7 @@ class ActionMailerTest < Test::Unit::TestCase
assert_nothing_raised { TestMailer.deliver_subject_with_i18n(@recipient) }
assert_equal "Subject with i18n", ActionMailer::Base.deliveries.first.subject.decoded
- I18n.backend.store_translations('en', :actionmailer => {:subjects => {:test_mailer => {:subject_with_i18n => "New Subject!"}}})
+ I18n.backend.store_translations('en', :actionmailer => {:test_mailer => {:subject_with_i18n => {:subject => "New Subject!"}}})
assert_nothing_raised { TestMailer.deliver_subject_with_i18n(@recipient) }
assert_equal "New Subject!", ActionMailer::Base.deliveries.last.subject.decoded
end
diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec
index 1930416358..ccf6bf1e83 100644
--- a/actionpack/actionpack.gemspec
+++ b/actionpack/actionpack.gemspec
@@ -16,8 +16,10 @@ Gem::Specification.new do |s|
s.add_dependency('activesupport', '= 3.0.pre')
s.add_dependency('activemodel', '= 3.0.pre')
- s.add_dependency('rack', '~> 1.0.0')
- s.add_dependency('rack-test', '~> 0.5.0')
+ s.add_dependency('rack', '~> 1.0.1')
+ s.add_dependency('rack-test', '~> 0.5.0')
+ s.add_dependency('rack-mount', '~> 0.2.2')
+ s.add_dependency('erubis', '~> 2.6.5')
s.require_path = 'lib'
s.autorequire = 'action_controller'
diff --git a/actionpack/lib/abstract_controller/layouts.rb b/actionpack/lib/abstract_controller/layouts.rb
index 1616f8030a..c71cef42b2 100644
--- a/actionpack/lib/abstract_controller/layouts.rb
+++ b/actionpack/lib/abstract_controller/layouts.rb
@@ -100,7 +100,7 @@ module AbstractController
# name, return that string. Otherwise, use the superclass'
# layout (which might also be implied)
def _write_layout_method
- case @_layout
+ case defined?(@_layout) ? @_layout : nil
when String
self.class_eval %{def _layout(details) #{@_layout.inspect} end}
when Symbol
diff --git a/actionpack/lib/abstract_controller/rendering_controller.rb b/actionpack/lib/abstract_controller/rendering_controller.rb
index 0aae2b18e9..7054b9cf26 100644
--- a/actionpack/lib/abstract_controller/rendering_controller.rb
+++ b/actionpack/lib/abstract_controller/rendering_controller.rb
@@ -12,6 +12,12 @@ module AbstractController
self._view_paths ||= ActionView::PathSet.new
end
+ # Initialize controller with nil formats.
+ def initialize(*) #:nodoc:
+ @_formats = nil
+ super
+ end
+
# An instance of a view class. The default view class is ActionView::Base
#
# The view class must have the following methods:
diff --git a/actionpack/lib/action_controller/caching.rb b/actionpack/lib/action_controller/caching.rb
index 083d6328af..3caf759032 100644
--- a/actionpack/lib/action_controller/caching.rb
+++ b/actionpack/lib/action_controller/caching.rb
@@ -26,6 +26,7 @@ module ActionController #:nodoc:
# config.action_controller.cache_store = :file_store, "/path/to/cache/directory"
# config.action_controller.cache_store = :drb_store, "druby://localhost:9192"
# config.action_controller.cache_store = :mem_cache_store, "localhost"
+ # config.action_controller.cache_store = :mem_cache_store, Memcached::Rails.new("localhost:11211")
# config.action_controller.cache_store = MyOwnStore.new("parameter")
module Caching
extend ActiveSupport::Concern
diff --git a/actionpack/lib/action_controller/metal/request_forgery_protection.rb b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
index 113c20a758..173df79ee7 100644
--- a/actionpack/lib/action_controller/metal/request_forgery_protection.rb
+++ b/actionpack/lib/action_controller/metal/request_forgery_protection.rb
@@ -101,6 +101,11 @@ module ActionController #:nodoc:
session[:_csrf_token] ||= ActiveSupport::SecureRandom.base64(32)
end
+ # The form's authenticity parameter. Override to provide your own.
+ def form_authenticity_param
+ params[request_forgery_protection_token]
+ end
+
def protect_against_forgery?
allow_forgery_protection
end
diff --git a/actionpack/lib/action_controller/metal/responder.rb b/actionpack/lib/action_controller/metal/responder.rb
index c6e847ba0f..e8e88e7479 100644
--- a/actionpack/lib/action_controller/metal/responder.rb
+++ b/actionpack/lib/action_controller/metal/responder.rb
@@ -14,12 +14,11 @@ module ActionController #:nodoc:
#
# When a request comes, for example with format :xml, three steps happen:
#
- # 1) respond_with searches for a template at people/index.xml;
+ # 1) responder searches for a template at people/index.xml;
#
- # 2) if the template is not available, it will create a responder, passing
- # the controller and the resource and invoke :to_xml on it;
+ # 2) if the template is not available, it will invoke :to_xml in the given resource;
#
- # 3) if the responder does not respond_to :to_xml, call to_format on it.
+ # 3) if the responder does not respond_to :to_xml, call :to_format on it.
#
# === Builtin HTTP verb semantics
#
@@ -88,14 +87,16 @@ module ActionController #:nodoc:
@resource = resources.is_a?(Array) ? resources.last : resources
@resources = resources
@options = options
+ @action = options.delete(:action)
@default_response = options.delete(:default_response)
end
delegate :head, :render, :redirect_to, :to => :controller
delegate :get?, :post?, :put?, :delete?, :to => :request
- # Undefine :to_json since it's defined on Object
+ # Undefine :to_json and :to_yaml since it's defined on Object
undef_method(:to_json) if method_defined?(:to_json)
+ undef_method(:to_yaml) if method_defined?(:to_yaml)
# Initializes a new responder an invoke the proper format. If the format is
# not defined, call to_format.
@@ -111,14 +112,8 @@ module ActionController #:nodoc:
#
def to_html
default_render
- rescue ActionView::MissingTemplate
- if get?
- raise
- elsif has_errors?
- render :action => default_action
- else
- redirect_to resource_location
- end
+ rescue ActionView::MissingTemplate => e
+ navigation_behavior(e)
end
# All others formats follow the procedure below. First we try to render a
@@ -127,9 +122,26 @@ module ActionController #:nodoc:
#
def to_format
default_render
- rescue ActionView::MissingTemplate
+ rescue ActionView::MissingTemplate => e
raise unless resourceful?
+ api_behavior(e)
+ end
+ protected
+
+ # This is the common behavior for "navigation" requests, like :html, :iphone and so forth.
+ def navigation_behavior(error)
+ if get?
+ raise error
+ elsif has_errors?
+ render :action => default_action
+ else
+ redirect_to resource_location
+ end
+ end
+
+ # This is the common behavior for "API" requests, like :xml and :json.
+ def api_behavior(error)
if get?
display resource
elsif has_errors?
@@ -141,8 +153,6 @@ module ActionController #:nodoc:
end
end
- protected
-
# Checks whether the resource responds to the current format or not.
#
def resourceful?
@@ -194,7 +204,7 @@ module ActionController #:nodoc:
# the verb is post.
#
def default_action
- request.post? ? :new : :edit
+ @action || (request.post? ? :new : :edit)
end
end
end
diff --git a/actionpack/lib/action_controller/metal/streaming.rb b/actionpack/lib/action_controller/metal/streaming.rb
index 4761763a26..43c661bef4 100644
--- a/actionpack/lib/action_controller/metal/streaming.rb
+++ b/actionpack/lib/action_controller/metal/streaming.rb
@@ -1,5 +1,3 @@
-require 'active_support/core_ext/string/bytesize'
-
module ActionController #:nodoc:
# Methods for sending arbitrary data and for streaming files to the browser,
# instead of rendering.
diff --git a/actionpack/lib/action_controller/translation.rb b/actionpack/lib/action_controller/translation.rb
index 9bb63cdb15..65e9eddb0a 100644
--- a/actionpack/lib/action_controller/translation.rb
+++ b/actionpack/lib/action_controller/translation.rb
@@ -1,12 +1,12 @@
module ActionController
module Translation
def translate(*args)
- I18n.translate *args
+ I18n.translate(*args)
end
alias :t :translate
def localize(*args)
- I18n.localize *args
+ I18n.localize(*args)
end
alias :l :localize
end
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index 75be2cc260..6a52854961 100755
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -5,7 +5,7 @@ require 'strscan'
require 'active_support/memoizable'
require 'active_support/core_ext/array/wrap'
require 'active_support/core_ext/hash/indifferent_access'
-require 'active_support/core_ext/object/tap'
+require 'active_support/core_ext/string/access'
module ActionDispatch
class Request < Rack::Request
@@ -166,7 +166,7 @@ module ActionDispatch
@env["action_dispatch.request.formats"] ||=
if parameters[:format]
- [Mime[parameters[:format]]]
+ Array.wrap(Mime[parameters[:format]])
elsif xhr? || (accept && !accept.include?(?,))
accepts
else
@@ -489,7 +489,7 @@ EOM
def self.extended(object)
object.class_eval do
attr_accessor :original_path, :content_type
- alias_method :local_path, :path
+ alias_method :local_path, :path if method_defined?(:path)
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/stack.rb b/actionpack/lib/action_dispatch/middleware/stack.rb
index 4f71ea6165..3b27309f58 100644
--- a/actionpack/lib/action_dispatch/middleware/stack.rb
+++ b/actionpack/lib/action_dispatch/middleware/stack.rb
@@ -1,3 +1,5 @@
+require "active_support/inflector/methods"
+
module ActionDispatch
class MiddlewareStack < Array
class Middleware
@@ -32,7 +34,7 @@ module ActionDispatch
elsif @klass.respond_to?(:call)
@klass.call
else
- @klass.to_s.constantize
+ ActiveSupport::Inflector.constantize(@klass.to_s)
end
end
@@ -53,7 +55,7 @@ module ActionDispatch
when Class
klass == middleware
else
- klass == middleware.to_s.constantize
+ klass == ActiveSupport::Inflector.constantize(middleware.to_s)
end
end
diff --git a/actionpack/lib/action_dispatch/routing.rb b/actionpack/lib/action_dispatch/routing.rb
index 68ed1e3340..9b977800b4 100644
--- a/actionpack/lib/action_dispatch/routing.rb
+++ b/actionpack/lib/action_dispatch/routing.rb
@@ -264,11 +264,8 @@ module ActionDispatch
autoload :RouteSet, 'action_dispatch/routing/route_set'
SEPARATORS = %w( / . ? )
-
HTTP_METHODS = [:get, :head, :post, :put, :delete, :options]
- ALLOWED_REQUIREMENTS_FOR_OPTIMISATION = [:controller, :action].to_set
-
# The root paths which may contain controller files
mattr_accessor :controller_paths
self.controller_paths = []
@@ -279,46 +276,28 @@ module ActionDispatch
end
class << self
- # Expects an array of controller names as the first argument.
- # Executes the passed block with only the named controllers named available.
- # This method is used in internal Rails testing.
- def with_controllers(names)
- prior_controllers = @possible_controllers
- use_controllers! names
- yield
- ensure
- use_controllers! prior_controllers
+ def controller_constraints
+ @controller_constraints ||= Regexp.union(*possible_controllers.collect { |n| Regexp.escape(n) })
end
- # Returns an array of paths, cleaned of double-slashes and relative path references.
- # * "\\\" and "//" become "\\" or "/".
- # * "/foo/bar/../config" becomes "/foo/config".
- # The returned array is sorted by length, descending.
- def normalize_paths(paths)
- # do the hokey-pokey of path normalization...
- paths = paths.collect do |path|
- path = path.
- gsub("//", "/"). # replace double / chars with a single
- gsub("\\\\", "\\"). # replace double \ chars with a single
- gsub(%r{(.)[\\/]$}, '\1') # drop final / or \ if path ends with it
-
- # eliminate .. paths where possible
- re = %r{[^/\\]+[/\\]\.\.[/\\]}
- path.gsub!(re, "") while path.match(re)
- path
- end
-
- # start with longest path, first
- paths = paths.uniq.sort_by { |path| - path.length }
+ def clear_controller_cache!
+ @controller_constraints = nil
end
- # Returns the array of controller names currently available to ActionController::Routing.
- def possible_controllers
- unless @possible_controllers
- @possible_controllers = []
+ private
+ # Returns the array of controller names currently available to ActionController::Routing.
+ def possible_controllers
+ possible_controllers = []
- paths = controller_paths.select { |path| File.directory?(path) && path != "." }
+ # Find any controller classes already in memory
+ ActionController::Base.subclasses.each do |klass|
+ controller_name = klass.underscore
+ controller_name.gsub!(/_controller\Z/, '')
+ possible_controllers << controller_name
+ end
+ # Find controllers in controllers/ directory
+ paths = controller_paths.select { |path| File.directory?(path) && path != "." }
seen_paths = Hash.new {|h, k| h[k] = true; false}
normalize_paths(paths).each do |load_path|
Dir["#{load_path}/**/*_controller.rb"].collect do |path|
@@ -327,55 +306,37 @@ module ActionDispatch
controller_name = path[(load_path.length + 1)..-1]
controller_name.gsub!(/_controller\.rb\Z/, '')
- @possible_controllers << controller_name
+ possible_controllers << controller_name
end
end
# remove duplicates
- @possible_controllers.uniq!
- end
- @possible_controllers
- end
-
- # Replaces the internal list of controllers available to ActionController::Routing with the passed argument.
- # ActionController::Routing.use_controllers!([ "posts", "comments", "admin/comments" ])
- def use_controllers!(controller_names)
- @possible_controllers = controller_names
- end
+ possible_controllers.uniq!
- # Returns a controller path for a new +controller+ based on a +previous+ controller path.
- # Handles 4 scenarios:
- #
- # * stay in the previous controller:
- # controller_relative_to( nil, "groups/discussion" ) # => "groups/discussion"
- #
- # * stay in the previous namespace:
- # controller_relative_to( "posts", "groups/discussion" ) # => "groups/posts"
- #
- # * forced move to the root namespace:
- # controller_relative_to( "/posts", "groups/discussion" ) # => "posts"
- #
- # * previous namespace is root:
- # controller_relative_to( "posts", "anything_with_no_slashes" ) # =>"posts"
- #
- def controller_relative_to(controller, previous)
- if controller.nil? then previous
- elsif controller[0] == ?/ then controller[1..-1]
- elsif %r{^(.*)/} =~ previous then "#{$1}/#{controller}"
- else controller
+ possible_controllers
end
- end
- end
- ActiveSupport::Inflector.module_eval do
- # Ensures that routes are reloaded when Rails inflections are updated.
- def inflections_with_route_reloading(&block)
- returning(inflections_without_route_reloading(&block)) {
- ActionDispatch::Routing::Routes.reload! if block_given?
- }
- end
+ # Returns an array of paths, cleaned of double-slashes and relative path references.
+ # * "\\\" and "//" become "\\" or "/".
+ # * "/foo/bar/../config" becomes "/foo/config".
+ # The returned array is sorted by length, descending.
+ def normalize_paths(paths)
+ # do the hokey-pokey of path normalization...
+ paths = paths.collect do |path|
+ path = path.
+ gsub("//", "/"). # replace double / chars with a single
+ gsub("\\\\", "\\"). # replace double \ chars with a single
+ gsub(%r{(.)[\\/]$}, '\1') # drop final / or \ if path ends with it
+
+ # eliminate .. paths where possible
+ re = %r{[^/\\]+[/\\]\.\.[/\\]}
+ path.gsub!(re, "") while path.match(re)
+ path
+ end
- alias_method_chain :inflections, :route_reloading
+ # start with longest path, first
+ paths = paths.uniq.sort_by { |path| - path.length }
+ end
end
end
end
diff --git a/actionpack/lib/action_dispatch/routing/deprecated_mapper.rb b/actionpack/lib/action_dispatch/routing/deprecated_mapper.rb
index 0564ba9797..dd76391870 100644
--- a/actionpack/lib/action_dispatch/routing/deprecated_mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/deprecated_mapper.rb
@@ -113,8 +113,7 @@ module ActionDispatch
end
end
- possible_names = Routing.possible_controllers.collect { |n| Regexp.escape(n) }
- requirements[:controller] ||= Regexp.union(*possible_names)
+ requirements[:controller] ||= Routing.controller_constraints
if defaults[:controller]
defaults[:action] ||= 'index'
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index ebfb4c9be2..cfe7425a61 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -52,30 +52,38 @@ module ActionDispatch
resource = resources.pop
+ plural = resource.to_s
+ singular = plural.singularize
+
if @scope[:scope_level] == :resources
- member do
- resources(resource, options, &block)
+ parent_resource = @scope[:scope_level_options][:name]
+ with_scope_level(:member) do
+ scope(":#{parent_resource}_id", :name_prefix => parent_resource) do
+ resources(resource, options, &block)
+ end
end
return self
end
- plural = resource.to_s
- singular = plural.singularize
+ if @scope[:options] && (prefix = @scope[:options][:name_prefix])
+ plural = "#{prefix}_#{plural}"
+ singular = "#{prefix}_#{singular}"
+ end
controller(resource) do
namespace(resource) do
- with_scope_level(:resources) do
+ with_scope_level(:resources, :name => singular) do
yield if block_given?
member do
- get "", :to => :show, :as => "#{singular}"
+ get "", :to => :show, :as => singular
put "", :to => :update
delete "", :to => :destroy
get "edit", :to => :edit, :as => "edit_#{singular}"
end
collection do
- get "", :to => :index, :as => "#{plural}"
+ get "", :to => :index, :as => plural
post "", :to => :create
get "new", :to => :new, :as => "new_#{singular}"
end
@@ -127,11 +135,13 @@ module ActionDispatch
end
private
- def with_scope_level(kind)
+ def with_scope_level(kind, options = {})
old, @scope[:scope_level] = @scope[:scope_level], kind
+ old_options, @scope[:scope_level_options] = @scope[:scope_level_options], options
yield
ensure
@scope[:scope_level] = old
+ @scope[:scope_level_options] = old_options
end
end
@@ -195,9 +205,9 @@ module ActionDispatch
@constraints.each { |constraint|
if constraint.respond_to?(:matches?) && !constraint.matches?(req)
- return Rack::Mount::Const::EXPECTATION_FAILED_RESPONSE
+ return [417, {}, []]
elsif constraint.respond_to?(:call) && !constraint.call(req)
- return Rack::Mount::Const::EXPECTATION_FAILED_RESPONSE
+ return [417, {}, []]
end
}
@@ -272,6 +282,8 @@ module ActionDispatch
constraints.reject! { |k, v| segment_keys.include?(k.to_s) }
conditions.merge!(constraints)
+ requirements[:controller] ||= Routing.controller_constraints
+
if via = options[:via]
via = Array(via).map { |m| m.to_s.upcase }
conditions[:request_method] = Regexp.union(*via)
diff --git a/actionpack/lib/action_dispatch/routing/route_set.rb b/actionpack/lib/action_dispatch/routing/route_set.rb
index 28e5b806da..79e15edeaa 100644
--- a/actionpack/lib/action_dispatch/routing/route_set.rb
+++ b/actionpack/lib/action_dispatch/routing/route_set.rb
@@ -5,7 +5,7 @@ module ActionDispatch
module Routing
class RouteSet #:nodoc:
NotFound = lambda { |env|
- raise ActionController::RoutingError, "No route matches #{env[::Rack::Mount::Const::PATH_INFO].inspect} with #{env.inspect}"
+ raise ActionController::RoutingError, "No route matches #{env['PATH_INFO'].inspect} with #{env.inspect}"
}
PARAMETERS_KEY = 'action_dispatch.request.path_parameters'
@@ -246,7 +246,9 @@ module ActionDispatch
end
def load!
- Routing.use_controllers!(nil) # Clear the controller cache so we may discover new ones
+ # Clear the controller cache so we may discover new ones
+ Routing.clear_controller_cache!
+
load_routes!
end
@@ -372,7 +374,17 @@ module ActionDispatch
end
recall[:action] = options.delete(:action) if options[:action] == 'index'
- path = _uri(named_route, options, recall)
+ parameterize = lambda { |name, value|
+ if name == :controller
+ value
+ elsif value.is_a?(Array)
+ value.map { |v| Rack::Mount::Utils.escape_uri(v.to_param) }.join('/')
+ else
+ Rack::Mount::Utils.escape_uri(value.to_param)
+ end
+ }
+
+ path = @set.url(named_route, options, recall, :parameterize => parameterize)
if path && method == :generate_extras
uri = URI(path)
extras = uri.query ?
@@ -439,59 +451,6 @@ module ActionDispatch
def extract_request_environment(request)
{ :method => request.method }
end
-
- private
- def _uri(named_route, params, recall)
- params = URISegment.wrap_values(params)
- recall = URISegment.wrap_values(recall)
-
- unless result = @set.generate(:path_info, named_route, params, recall)
- return
- end
-
- uri, params = result
- params.each do |k, v|
- if v._value
- params[k] = v._value
- else
- params.delete(k)
- end
- end
-
- uri << "?#{Rack::Mount::Utils.build_nested_query(params)}" if uri && params.any?
- uri
- end
-
- class URISegment < Struct.new(:_value, :_escape)
- EXCLUDED = [:controller]
-
- def self.wrap_values(hash)
- hash.inject({}) { |h, (k, v)|
- h[k] = new(v, !EXCLUDED.include?(k.to_sym))
- h
- }
- end
-
- extend Forwardable
- def_delegators :_value, :==, :eql?, :hash
-
- def to_param
- @to_param ||= begin
- if _value.is_a?(Array)
- _value.map { |v| _escaped(v) }.join('/')
- else
- _escaped(_value)
- end
- end
- end
- alias_method :to_s, :to_param
-
- private
- def _escaped(value)
- v = value.respond_to?(:to_param) ? value.to_param : value
- _escape ? Rack::Mount::Utils.escape_uri(v) : v.to_s
- end
- end
end
end
end
diff --git a/actionpack/lib/action_dispatch/testing/assertions.rb b/actionpack/lib/action_dispatch/testing/assertions.rb
index 96f08f2355..0e4a92048f 100644
--- a/actionpack/lib/action_dispatch/testing/assertions.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions.rb
@@ -1,8 +1,21 @@
module ActionDispatch
module Assertions
- %w(response selector tag dom routing model).each do |kind|
- require "action_dispatch/testing/assertions/#{kind}"
- include const_get("#{kind.camelize}Assertions")
+ autoload :DomAssertions, 'action_dispatch/testing/assertions/dom'
+ autoload :ModelAssertions, 'action_dispatch/testing/assertions/model'
+ autoload :ResponseAssertions, 'action_dispatch/testing/assertions/response'
+ autoload :RoutingAssertions, 'action_dispatch/testing/assertions/routing'
+ autoload :SelectorAssertions, 'action_dispatch/testing/assertions/selector'
+ autoload :TagAssertions, 'action_dispatch/testing/assertions/tag'
+
+ extend ActiveSupport::Concern
+
+ included do
+ include DomAssertions
+ include ModelAssertions
+ include ResponseAssertions
+ include RoutingAssertions
+ include SelectorAssertions
+ include TagAssertions
end
end
end
diff --git a/actionpack/lib/action_view/erb/util.rb b/actionpack/lib/action_view/erb/util.rb
index f767a5e27e..aef859b3ac 100644
--- a/actionpack/lib/action_view/erb/util.rb
+++ b/actionpack/lib/action_view/erb/util.rb
@@ -23,6 +23,7 @@ class ERB
end
end
+ undef :h
alias h html_escape
module_function :html_escape
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index c46b39fc23..d0c66eda60 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -963,7 +963,7 @@ module ActionView
end
end
- (field_helpers - %w(label check_box radio_button fields_for)).each do |selector|
+ (field_helpers - %w(label check_box radio_button fields_for hidden_field)).each do |selector|
src = <<-end_src
def #{selector}(method, options = {}) # def text_field(method, options = {})
@template.send( # @template.send(
@@ -1022,6 +1022,11 @@ module ActionView
def radio_button(method, tag_value, options = {})
@template.radio_button(@object_name, method, tag_value, objectify_options(options))
end
+
+ def hidden_field(method, options = {})
+ @emitted_hidden_id = true if method == :id
+ @template.hidden_field(@object_name, method, objectify_options(options))
+ end
def error_message_on(method, *args)
@template.error_message_on(@object, method, *args)
@@ -1035,6 +1040,10 @@ module ActionView
@template.submit_tag(value, options.reverse_merge(:id => "#{object_name}_submit"))
end
+ def emitted_hidden_id?
+ @emitted_hidden_id
+ end
+
private
def objectify_options(options)
@default_options.merge(options.merge(:object => @object))
@@ -1069,8 +1078,8 @@ module ActionView
@template.fields_for(name, object, *args, &block)
else
@template.fields_for(name, object, *args) do |builder|
- @template.concat builder.hidden_field(:id)
block.call(builder)
+ @template.concat builder.hidden_field(:id) unless builder.emitted_hidden_id?
end
end
end
diff --git a/actionpack/lib/action_view/helpers/translation_helper.rb b/actionpack/lib/action_view/helpers/translation_helper.rb
index 4aed10f640..564f12c955 100644
--- a/actionpack/lib/action_view/helpers/translation_helper.rb
+++ b/actionpack/lib/action_view/helpers/translation_helper.rb
@@ -21,7 +21,7 @@ module ActionView
# Delegates to I18n.localize with no additional functionality.
def localize(*args)
- I18n.localize *args
+ I18n.localize(*args)
end
alias :l :localize
diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb
index 8beda24aba..86bbad822d 100644
--- a/actionpack/lib/action_view/test_case.rb
+++ b/actionpack/lib/action_view/test_case.rb
@@ -120,6 +120,7 @@ module ActionView
def _view
view = ActionView::Base.new(ActionController::Base.view_paths, _assigns, @controller)
view.class.send :include, _helpers
+ view.output_buffer = self.output_buffer
view
end
diff --git a/actionpack/test/abstract/layouts_test.rb b/actionpack/test/abstract/layouts_test.rb
index 9c29696ad5..ae2f1bf1f2 100644
--- a/actionpack/test/abstract/layouts_test.rb
+++ b/actionpack/test/abstract/layouts_test.rb
@@ -212,7 +212,7 @@ module AbstractControllerTests
end
test "when the layout is specified as a symbol and the method doesn't exist, raise an exception" do
- assert_raises(NoMethodError, /:nilz/) { WithSymbolAndNoMethod.new.process(:index) }
+ assert_raises(NoMethodError) { WithSymbolAndNoMethod.new.process(:index) }
end
test "when the layout is specified as a symbol and the method returns something besides a string/false/nil, raise an exception" do
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index 214d79cd87..9d055da4b9 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -6,17 +6,13 @@ rescue LoadError
$:.unshift "#{root}/activemodel/lib"
end
-$:.unshift(File.dirname(__FILE__) + '/../lib')
+lib = File.expand_path("#{File.dirname(__FILE__)}/../lib")
+$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib)
+
$:.unshift(File.dirname(__FILE__) + '/lib')
$:.unshift(File.dirname(__FILE__) + '/fixtures/helpers')
$:.unshift(File.dirname(__FILE__) + '/fixtures/alternate_helpers')
-begin
- %w( rack rack/test sqlite3 ).each { |lib| require lib }
-rescue LoadError => e
- abort e.message
-end
-
ENV['TMPDIR'] = File.join(File.dirname(__FILE__), 'tmp')
require 'test/unit'
@@ -195,20 +191,8 @@ class ::ApplicationController < ActionController::Base
end
module ActionController
- module Routing
- def self.possible_controllers
- @@possible_controllers ||= []
- end
- end
-
class Base
include ActionController::Testing
-
- def self.inherited(klass)
- name = klass.name.underscore.sub(/_controller$/, '')
- ActionController::Routing.possible_controllers << name unless name.blank?
- super
- end
end
Base.view_paths = FIXTURE_LOAD_PATH
diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb
index 2da97a9d86..8445428e8f 100644
--- a/actionpack/test/controller/filters_test.rb
+++ b/actionpack/test/controller/filters_test.rb
@@ -1,5 +1,4 @@
require 'abstract_unit'
-require 'active_support/core_ext/symbol'
class ActionController::Base
class << self
diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb
index b070f925d4..fee9cf46f9 100644
--- a/actionpack/test/controller/mime_responds_test.rb
+++ b/actionpack/test/controller/mime_responds_test.rb
@@ -501,6 +501,12 @@ class RespondWithController < ActionController::Base
respond_with(Customer.new("david", 13), :responder => responder)
end
+ def using_resource_with_action
+ respond_with(Customer.new("david", 13), :action => :foo) do |format|
+ format.html { raise ActionView::MissingTemplate.new([], "method") }
+ end
+ end
+
protected
def _render_js(js, options)
@@ -715,6 +721,20 @@ class RespondWithControllerTest < ActionController::TestCase
assert_match /<name>jamis<\/name>/, @response.body
end
+ def test_using_resource_with_action
+ @controller.instance_eval do
+ def render(params={})
+ self.response_body = "#{params[:action]} - #{formats}"
+ end
+ end
+
+ errors = { :name => :invalid }
+ Customer.any_instance.stubs(:errors).returns(errors)
+
+ post :using_resource_with_action
+ assert_equal "foo - #{[:html].to_s}", @controller.response_body
+ end
+
def test_clear_respond_to
@controller = InheritedRespondWithController.new
@request.accept = "text/html"
@@ -760,7 +780,7 @@ class RespondWithControllerTest < ActionController::TestCase
assert_equal "Resource name is david", @response.body
end
- def test_using_resource_with_responder
+ def test_using_resource_with_set_responder
RespondWithController.responder = proc { |c, r, o| c.render :text => "Resource name is #{r.first.name}" }
get :using_resource
assert_equal "Resource name is david", @response.body
diff --git a/actionpack/test/controller/new_base/render_action_test.rb b/actionpack/test/controller/new_base/render_action_test.rb
index ecd29c4530..239f68659c 100644
--- a/actionpack/test/controller/new_base/render_action_test.rb
+++ b/actionpack/test/controller/new_base/render_action_test.rb
@@ -86,7 +86,7 @@ module RenderAction
describe "Both <controller_path>.html.erb and application.html.erb are missing"
test "rendering with layout => true" do
- assert_raise(ArgumentError, /no default layout for RenderAction::BasicController in/) do
+ assert_raise(ArgumentError) do
get "/render_action/basic/hello_world_with_layout", {}, "action_dispatch.show_exceptions" => false
end
end
diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb
index 7111796f8d..09003adf73 100644
--- a/actionpack/test/controller/request_forgery_protection_test.rb
+++ b/actionpack/test/controller/request_forgery_protection_test.rb
@@ -18,7 +18,7 @@ module RequestForgeryProtectionActions
def unsafe
render :text => 'pwn'
end
-
+
def rescue_action(e) raise e end
end
@@ -40,6 +40,13 @@ class FreeCookieController < RequestForgeryProtectionController
end
end
+class CustomAuthenticityParamController < RequestForgeryProtectionController
+ def form_authenticity_param
+ 'foobar'
+ end
+end
+
+
# common test methods
module RequestForgeryProtectionTests
@@ -241,3 +248,14 @@ class FreeCookieControllerTest < ActionController::TestCase
end
end
end
+
+class CustomAuthenticityParamControllerTest < ActionController::TestCase
+ def setup
+ ActionController::Base.request_forgery_protection_token = :authenticity_token
+ end
+
+ def test_should_allow_custom_token
+ post :index, :authenticity_token => 'foobar'
+ assert_response :ok
+ end
+end
diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb
index bb0b9247f3..b5effeda40 100644
--- a/actionpack/test/controller/routing_test.rb
+++ b/actionpack/test/controller/routing_test.rb
@@ -51,30 +51,6 @@ class UriReservedCharactersRoutingTest < Test::Unit::TestCase
end
end
-class RoutingTest < Test::Unit::TestCase
- def test_normalize_unix_paths
- load_paths = %w(. config/../app/controllers config/../app//helpers script/../config/../vendor/rails/actionpack/lib vendor/rails/railties/builtin/rails_info app/models lib script/../config/../foo/bar/../../app/models .foo/../.bar foo.bar/../config)
- paths = ActionController::Routing.normalize_paths(load_paths)
- assert_equal %w(vendor/rails/railties/builtin/rails_info vendor/rails/actionpack/lib app/controllers app/helpers app/models config .bar lib .), paths
- end
-
- def test_normalize_windows_paths
- load_paths = %w(. config\\..\\app\\controllers config\\..\\app\\\\helpers script\\..\\config\\..\\vendor\\rails\\actionpack\\lib vendor\\rails\\railties\\builtin\\rails_info app\\models lib script\\..\\config\\..\\foo\\bar\\..\\..\\app\\models .foo\\..\\.bar foo.bar\\..\\config)
- paths = ActionController::Routing.normalize_paths(load_paths)
- assert_equal %w(vendor\\rails\\railties\\builtin\\rails_info vendor\\rails\\actionpack\\lib app\\controllers app\\helpers app\\models config .bar lib .), paths
- end
-
- def test_routing_helper_module
- assert_kind_of Module, ActionController::Routing::Helpers
-
- h = ActionController::Routing::Helpers
- c = Class.new
- assert ! c.ancestors.include?(h)
- ActionController::Routing::Routes.install_helpers c
- assert c.ancestors.include?(h)
- end
-end
-
class MockController
attr_accessor :routes
@@ -1418,6 +1394,7 @@ class RouteSetTest < ActiveSupport::TestCase
:action => 'show',
:requirements => {:name => /(david|jamis)/i}
end
+
url = set.generate({:controller => 'pages', :action => 'show', :name => 'david'})
assert_equal "/page/david", url
assert_raise ActionController::RoutingError do
@@ -1459,13 +1436,16 @@ class RouteSetTest < ActiveSupport::TestCase
jamis #The Deployer
)/x}
end
- url = set.generate({:controller => 'pages', :action => 'show', :name => 'david'})
- assert_equal "/page/david", url
- assert_raise ActionController::RoutingError do
- url = set.generate({:controller => 'pages', :action => 'show', :name => 'davidjamis'})
- end
- assert_raise ActionController::RoutingError do
- url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'})
+
+ pending do
+ url = set.generate({:controller => 'pages', :action => 'show', :name => 'david'})
+ assert_equal "/page/david", url
+ assert_raise ActionController::RoutingError do
+ url = set.generate({:controller => 'pages', :action => 'show', :name => 'davidjamis'})
+ end
+ assert_raise ActionController::RoutingError do
+ url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'})
+ end
end
end
@@ -1480,8 +1460,11 @@ class RouteSetTest < ActiveSupport::TestCase
jamis #The Deployer
)/xi}
end
- url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'})
- assert_equal "/page/JAMIS", url
+
+ pending do
+ url = set.generate({:controller => 'pages', :action => 'show', :name => 'JAMIS'})
+ assert_equal "/page/JAMIS", url
+ end
end
def test_route_requirement_recognize_with_xi_modifiers
@@ -1645,6 +1628,58 @@ class RouteSetTest < ActiveSupport::TestCase
assert_uri_equal '/foo?x=hello+world', default_route_set.generate({:controller => 'foo', :x => 'hello world'})
end
+ def test_generate_with_default_params
+ set.draw do |map|
+ map.connect 'dummy/page/:page', :controller => 'dummy'
+ map.connect 'dummy/dots/page.:page', :controller => 'dummy', :action => 'dots'
+ map.connect 'ibocorp/:page', :controller => 'ibocorp',
+ :requirements => { :page => /\d+/ },
+ :defaults => { :page => 1 }
+
+ map.connect ':controller/:action/:id'
+ end
+
+ pending do
+ assert_equal '/ibocorp', set.generate({:controller => 'ibocorp', :page => 1})
+ end
+ end
+
+ def test_generate_with_optional_params_recalls_last_request
+ set.draw do |map|
+ map.connect "blog/", :controller => "blog", :action => "index"
+
+ map.connect "blog/:year/:month/:day",
+ :controller => "blog",
+ :action => "show_date",
+ :requirements => { :year => /(19|20)\d\d/, :month => /[01]?\d/, :day => /[0-3]?\d/ },
+ :day => nil, :month => nil
+
+ map.connect "blog/show/:id", :controller => "blog", :action => "show", :id => /\d+/
+ map.connect "blog/:controller/:action/:id"
+ map.connect "*anything", :controller => "blog", :action => "unknown_request"
+ end
+
+ assert_equal({:controller => "blog", :action => "index"}, set.recognize_path("/blog"))
+ assert_equal({:controller => "blog", :action => "show", :id => "123"}, set.recognize_path("/blog/show/123"))
+ assert_equal({:controller => "blog", :action => "show_date", :year => "2004"}, set.recognize_path("/blog/2004"))
+ assert_equal({:controller => "blog", :action => "show_date", :year => "2004", :month => "12"}, set.recognize_path("/blog/2004/12"))
+ assert_equal({:controller => "blog", :action => "show_date", :year => "2004", :month => "12", :day => "25"}, set.recognize_path("/blog/2004/12/25"))
+ assert_equal({:controller => "articles", :action => "edit", :id => "123"}, set.recognize_path("/blog/articles/edit/123"))
+ assert_equal({:controller => "articles", :action => "show_stats"}, set.recognize_path("/blog/articles/show_stats"))
+ assert_equal({:controller => "blog", :action => "unknown_request", :anything => ["blog", "wibble"]}, set.recognize_path("/blog/wibble"))
+ assert_equal({:controller => "blog", :action => "unknown_request", :anything => ["junk"]}, set.recognize_path("/junk"))
+
+ last_request = set.recognize_path("/blog/2006/07/28").freeze
+ assert_equal({:controller => "blog", :action => "show_date", :year => "2006", :month => "07", :day => "28"}, last_request)
+ assert_equal("/blog/2006/07/25", set.generate({:day => 25}, last_request))
+ assert_equal("/blog/2005", set.generate({:year => 2005}, last_request))
+ assert_equal("/blog/show/123", set.generate({:action => "show" , :id => 123}, last_request))
+ pending do
+ assert_equal("/blog/2006/07/28", set.generate({:year => 2006}, last_request))
+ end
+ assert_equal("/blog/2006", set.generate({:year => 2006, :month => nil}, last_request))
+ end
+
private
def assert_uri_equal(expected, actual)
assert_equal(sort_query_string_params(expected), sort_query_string_params(actual))
@@ -1703,13 +1738,6 @@ class RouteLoadingTest < Test::Unit::TestCase
2.times { routes.reload! }
end
- def test_adding_inflections_forces_reload
- ActiveSupport::Inflector::Inflections.instance.expects(:uncountable).with('equipment')
- routes.expects(:reload!)
-
- ActiveSupport::Inflector.inflections { |inflect| inflect.uncountable('equipment') }
- end
-
def test_load_with_configuration
routes.configuration_files.clear
routes.add_configuration_file("foobarbaz")
diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb
index 239fda98e0..b62df9a6b2 100644
--- a/actionpack/test/dispatch/request_test.rb
+++ b/actionpack/test/dispatch/request_test.rb
@@ -432,6 +432,10 @@ class RequestTest < ActiveSupport::TestCase
request = stub_request
request.expects(:parameters).at_least_once.returns({ :format => :txt })
assert_equal with_set(Mime::TEXT), request.formats
+
+ request = stub_request
+ request.expects(:parameters).at_least_once.returns({ :format => :unknown })
+ assert request.formats.empty?
end
test "negotiate_mime" do
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index ca07bc7a28..496445fc34 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -212,9 +212,11 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
with_test_routes do
get '/projects/1/involvements'
assert_equal 'involvements#index', @response.body
+ assert_equal '/projects/1/involvements', project_involvements_path(:project_id => '1')
get '/projects/1/involvements/1'
assert_equal 'involvements#show', @response.body
+ assert_equal '/projects/1/involvements/1', project_involvement_path(:project_id => '1', :id => '1')
end
end
@@ -222,6 +224,7 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
with_test_routes do
get '/projects/1/attachments'
assert_equal 'attachments#index', @response.body
+ assert_equal '/projects/1/attachments', project_attachments_path(:project_id => '1')
end
end
@@ -229,9 +232,14 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
with_test_routes do
get '/projects/1/participants'
assert_equal 'participants#index', @response.body
+ assert_equal '/projects/1/participants', project_participants_path(:project_id => '1')
put '/projects/1/participants/update_all'
assert_equal 'participants#update_all', @response.body
+
+ pending do
+ assert_equal '/projects/1/participants/update_all', update_all_project_participants_path(:project_id => '1')
+ end
end
end
@@ -239,12 +247,19 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
with_test_routes do
get '/projects/1/companies'
assert_equal 'companies#index', @response.body
+ assert_equal '/projects/1/companies', project_companies_path(:project_id => '1')
get '/projects/1/companies/1/people'
assert_equal 'people#index', @response.body
+ pending do
+ assert_equal '/projects/1/companies/1/people', project_company_people_path(:project_id => '1', :company_id => '1')
+ end
get '/projects/1/companies/1/avatar'
assert_equal 'avatars#show', @response.body
+ pending do
+ assert_equal '/projects/1/companies/1/avatar', project_company_avatar_path(:project_id => '1', :company_id => '1')
+ end
end
end
@@ -252,9 +267,13 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
with_test_routes do
get '/projects/1/images'
assert_equal 'images#index', @response.body
+ assert_equal '/projects/1/images', project_images_path(:project_id => '1')
post '/projects/1/images/1/revise'
assert_equal 'images#revise', @response.body
+ pending do
+ assert_equal '/projects/1/images/1/revise', revise_project_image_path(:project_id => '1', :id => '1')
+ end
end
end
@@ -262,21 +281,35 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
with_test_routes do
get '/projects/1/people'
assert_equal 'people#index', @response.body
+ assert_equal '/projects/1/people', project_people_path(:project_id => '1')
get '/projects/1/people/1'
assert_equal 'people#show', @response.body
+ assert_equal '/projects/1/people/1', project_person_path(:project_id => '1', :id => '1')
get '/projects/1/people/1/7a2dec8/avatar'
assert_equal 'avatars#show', @response.body
+ pending do
+ assert_equal '/projects/1/people/1/7a2dec8/avatar', project_person_avatar_path(:project_id => '1', :person_id => '1', :access_token => '7a2dec8')
+ end
put '/projects/1/people/1/accessible_projects'
assert_equal 'people#accessible_projects', @response.body
+ pending do
+ assert_equal '/projects/1/people/1/accessible_projects', accessible_projects_project_person_path(:project_id => '1', :id => '1')
+ end
post '/projects/1/people/1/resend'
assert_equal 'people#resend', @response.body
+ pending do
+ assert_equal '/projects/1/people/1/resend', resend_project_person_path(:project_id => '1', :id => '1')
+ end
post '/projects/1/people/1/generate_new_password'
assert_equal 'people#generate_new_password', @response.body
+ pending do
+ assert_equal '/projects/1/people/1/generate_new_password', generate_new_password_project_person_path(:project_id => '1', :id => '1')
+ end
end
end
@@ -284,24 +317,43 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
with_test_routes do
get '/projects/1/posts'
assert_equal 'posts#index', @response.body
+ assert_equal '/projects/1/posts', project_posts_path(:project_id => '1')
get '/projects/1/posts/archive'
assert_equal 'posts#archive', @response.body
+ pending do
+ assert_equal '/projects/1/posts/archive', archive_project_posts_path(:project_id => '1')
+ end
get '/projects/1/posts/toggle_view'
assert_equal 'posts#toggle_view', @response.body
+ pending do
+ assert_equal '/projects/1/posts/toggle_view', toggle_view_project_posts_path(:project_id => '1')
+ end
post '/projects/1/posts/1/preview'
assert_equal 'posts#preview', @response.body
+ pending do
+ assert_equal '/projects/1/posts/1/preview', preview_project_post_path(:project_id => '1', :id => '1')
+ end
get '/projects/1/posts/1/subscription'
assert_equal 'subscriptions#show', @response.body
+ pending do
+ assert_equal '/projects/1/posts/1/subscription', project_post_subscription_path(:project_id => '1', :post_id => '1')
+ end
get '/projects/1/posts/1/comments'
assert_equal 'comments#index', @response.body
+ pending do
+ assert_equal '/projects/1/posts/1/comments', project_post_comments_path(:project_id => '1', :post_id => '1')
+ end
post '/projects/1/posts/1/comments/preview'
assert_equal 'comments#preview', @response.body
+ pending do
+ assert_equal '/projects/1/posts/1/comments/preview', preview_project_post_comments_path(:project_id => '1', :post_id => '1')
+ end
end
end
diff --git a/actionpack/test/dispatch/test_request_test.rb b/actionpack/test/dispatch/test_request_test.rb
index b2006a0d2f..5da02b2ea6 100644
--- a/actionpack/test/dispatch/test_request_test.rb
+++ b/actionpack/test/dispatch/test_request_test.rb
@@ -5,7 +5,7 @@ class TestRequestTest < ActiveSupport::TestCase
env = ActionDispatch::TestRequest.new.env
assert_equal "GET", env.delete("REQUEST_METHOD")
- assert_equal nil, env.delete("HTTPS")
+ assert_equal "off", env.delete("HTTPS")
assert_equal "http", env.delete("rack.url_scheme")
assert_equal "example.org", env.delete("SERVER_NAME")
assert_equal "80", env.delete("SERVER_PORT")
diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb
index 04c635e770..44734abb18 100644
--- a/actionpack/test/template/form_helper_test.rb
+++ b/actionpack/test/template/form_helper_test.rb
@@ -613,6 +613,26 @@ class FormHelperTest < ActionView::TestCase
expected = '<form action="http://www.example.com" method="post">' +
'<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
+ '<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="author #321" />' +
+ '<input id="post_author_attributes_id" name="post[author_attributes][id]" type="hidden" value="321" />' +
+ '</form>'
+
+ assert_dom_equal expected, output_buffer
+ end
+
+ def test_nested_fields_for_with_existing_records_on_a_nested_attributes_one_to_one_association_with_explicit_hidden_field_placement
+ @post.author = Author.new(321)
+
+ form_for(:post, @post) do |f|
+ concat f.text_field(:title)
+ f.fields_for(:author) do |af|
+ concat af.hidden_field(:id)
+ concat af.text_field(:name)
+ end
+ end
+
+ expected = '<form action="http://www.example.com" method="post">' +
+ '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
'<input id="post_author_attributes_id" name="post[author_attributes][id]" type="hidden" value="321" />' +
'<input id="post_author_attributes_name" name="post[author_attributes][name]" size="30" type="text" value="author #321" />' +
'</form>'
@@ -634,6 +654,30 @@ class FormHelperTest < ActionView::TestCase
expected = '<form action="http://www.example.com" method="post">' +
'<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
+ '<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' +
+ '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' +
+ '<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' +
+ '<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />' +
+ '</form>'
+
+ assert_dom_equal expected, output_buffer
+ end
+
+ def test_nested_fields_for_with_existing_records_on_a_nested_attributes_collection_association_with_explicit_hidden_field_placement
+ @post.comments = Array.new(2) { |id| Comment.new(id + 1) }
+
+ form_for(:post, @post) do |f|
+ concat f.text_field(:title)
+ @post.comments.each do |comment|
+ f.fields_for(:comments, comment) do |cf|
+ concat cf.hidden_field(:id)
+ concat cf.text_field(:name)
+ end
+ end
+ end
+
+ expected = '<form action="http://www.example.com" method="post">' +
+ '<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
'<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' +
'<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' +
'<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />' +
@@ -678,8 +722,8 @@ class FormHelperTest < ActionView::TestCase
expected = '<form action="http://www.example.com" method="post">' +
'<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
- '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="321" />' +
'<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #321" />' +
+ '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="321" />' +
'<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="new comment" />' +
'</form>'
@@ -713,10 +757,10 @@ class FormHelperTest < ActionView::TestCase
expected = '<form action="http://www.example.com" method="post">' +
'<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
- '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' +
'<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #1" />' +
- '<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />' +
+ '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="1" />' +
'<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="comment #2" />' +
+ '<input id="post_comments_attributes_1_id" name="post[comments_attributes][1][id]" type="hidden" value="2" />' +
'</form>'
assert_dom_equal expected, output_buffer
@@ -736,8 +780,8 @@ class FormHelperTest < ActionView::TestCase
expected = '<form action="http://www.example.com" method="post">' +
'<input name="post[title]" size="30" type="text" id="post_title" value="Hello World" />' +
- '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="321" />' +
'<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #321" />' +
+ '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="321" />' +
'<input id="post_comments_attributes_1_name" name="post[comments_attributes][1][name]" size="30" type="text" value="new comment" />' +
'</form>'
@@ -755,8 +799,8 @@ class FormHelperTest < ActionView::TestCase
end
expected = '<form action="http://www.example.com" method="post">' +
- '<input id="post_comments_attributes_abc_id" name="post[comments_attributes][abc][id]" type="hidden" value="321" />' +
'<input id="post_comments_attributes_abc_name" name="post[comments_attributes][abc][name]" size="30" type="text" value="comment #321" />' +
+ '<input id="post_comments_attributes_abc_id" name="post[comments_attributes][abc][id]" type="hidden" value="321" />' +
'</form>'
assert_dom_equal expected, output_buffer
@@ -790,18 +834,18 @@ class FormHelperTest < ActionView::TestCase
end
expected = '<form action="http://www.example.com" method="post">' +
- '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="321" />' +
'<input id="post_comments_attributes_0_name" name="post[comments_attributes][0][name]" size="30" type="text" value="comment #321" />' +
- '<input id="post_comments_attributes_0_relevances_attributes_0_id" name="post[comments_attributes][0][relevances_attributes][0][id]" type="hidden" value="314" />' +
'<input id="post_comments_attributes_0_relevances_attributes_0_value" name="post[comments_attributes][0][relevances_attributes][0][value]" size="30" type="text" value="commentrelevance #314" />' +
- '<input id="post_tags_attributes_0_id" name="post[tags_attributes][0][id]" type="hidden" value="123" />' +
+ '<input id="post_comments_attributes_0_relevances_attributes_0_id" name="post[comments_attributes][0][relevances_attributes][0][id]" type="hidden" value="314" />' +
+ '<input id="post_comments_attributes_0_id" name="post[comments_attributes][0][id]" type="hidden" value="321" />' +
'<input id="post_tags_attributes_0_value" name="post[tags_attributes][0][value]" size="30" type="text" value="tag #123" />' +
- '<input id="post_tags_attributes_0_relevances_attributes_0_id" name="post[tags_attributes][0][relevances_attributes][0][id]" type="hidden" value="3141" />' +
'<input id="post_tags_attributes_0_relevances_attributes_0_value" name="post[tags_attributes][0][relevances_attributes][0][value]" size="30" type="text" value="tagrelevance #3141" />' +
- '<input id="post_tags_attributes_1_id" name="post[tags_attributes][1][id]" type="hidden" value="456" />' +
+ '<input id="post_tags_attributes_0_relevances_attributes_0_id" name="post[tags_attributes][0][relevances_attributes][0][id]" type="hidden" value="3141" />' +
+ '<input id="post_tags_attributes_0_id" name="post[tags_attributes][0][id]" type="hidden" value="123" />' +
'<input id="post_tags_attributes_1_value" name="post[tags_attributes][1][value]" size="30" type="text" value="tag #456" />' +
- '<input id="post_tags_attributes_1_relevances_attributes_0_id" name="post[tags_attributes][1][relevances_attributes][0][id]" type="hidden" value="31415" />' +
'<input id="post_tags_attributes_1_relevances_attributes_0_value" name="post[tags_attributes][1][relevances_attributes][0][value]" size="30" type="text" value="tagrelevance #31415" />' +
+ '<input id="post_tags_attributes_1_relevances_attributes_0_id" name="post[tags_attributes][1][relevances_attributes][0][id]" type="hidden" value="31415" />' +
+ '<input id="post_tags_attributes_1_id" name="post[tags_attributes][1][id]" type="hidden" value="456" />' +
'</form>'
assert_dom_equal expected, output_buffer
diff --git a/actionpack/test/template/test_case_test.rb b/actionpack/test/template/test_case_test.rb
index ca72c13ffa..05a409d05a 100644
--- a/actionpack/test/template/test_case_test.rb
+++ b/actionpack/test/template/test_case_test.rb
@@ -24,7 +24,7 @@ module ActionView
test_case.class_eval do
test "helpers defined on ActionView::TestCase are available" do
assert test_case.ancestors.include?(ASharedTestHelper)
- assert 'Holla!', from_shared_helper
+ assert_equal 'Holla!', from_shared_helper
end
end
end
@@ -38,10 +38,15 @@ module ActionView
assert_equal 'Eloy', render('developers/developer', :developer => stub(:name => 'Eloy'))
end
+ test "can render a layout with block" do
+ assert_equal "Before (ChrisCruft)\n!\nAfter",
+ render(:layout => "test/layout_for_partial", :locals => {:name => "ChrisCruft"}) {"!"}
+ end
+
helper AnotherTestHelper
test "additional helper classes can be specified as in a controller" do
assert test_case.ancestors.include?(AnotherTestHelper)
- assert 'Howdy!', from_another_helper
+ assert_equal 'Howdy!', from_another_helper
end
end
@@ -58,14 +63,14 @@ module ActionView
helper AnotherTestHelper
test "additional helper classes can be specified as in a controller" do
assert test_case.ancestors.include?(AnotherTestHelper)
- assert 'Howdy!', from_another_helper
+ assert_equal 'Howdy!', from_another_helper
test_case.helper_class.module_eval do
def render_from_helper
from_another_helper
end
end
- assert 'Howdy!', render(:partial => 'test/from_helper')
+ assert_equal 'Howdy!', render(:partial => 'test/from_helper')
end
end
diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb
index bf0b4ad3a7..5c463a4f60 100644
--- a/actionpack/test/template/url_helper_test.rb
+++ b/actionpack/test/template/url_helper_test.rb
@@ -391,54 +391,47 @@ class UrlHelperTest < ActionView::TestCase
end
end
-class UrlHelperController < ActionController::Base
- def self.controller_path; 'url_helper_with_controller' end
+class UrlHelperControllerTest < ActionController::TestCase
+ class UrlHelperController < ActionController::Base
+ def show_url_for
+ render :inline => "<%= url_for :controller => 'url_helper_controller_test/url_helper', :action => 'show_url_for' %>"
+ end
- def show_url_for
- render :inline => "<%= url_for :controller => 'url_helper_with_controller', :action => 'show_url_for' %>"
- end
+ def show_named_route
+ render :inline => "<%= show_named_route_#{params[:kind]} %>"
+ end
- def show_named_route
- render :inline => "<%= show_named_route_#{params[:kind]} %>"
- end
+ def nil_url_for
+ render :inline => '<%= url_for(nil) %>'
+ end
- def nil_url_for
- render :inline => '<%= url_for(nil) %>'
+ def rescue_action(e) raise e end
end
- def rescue_action(e) raise e end
-end
-
-class UrlHelperWithControllerTest < ActionController::TestCase
- def setup
- super
- @request = ActionController::TestRequest.new
- @response = ActionController::TestResponse.new
- @controller = UrlHelperController.new
- end
+ tests UrlHelperController
def test_url_for_shows_only_path
get :show_url_for
- assert_equal '/url_helper_with_controller/show_url_for', @response.body
+ assert_equal '/url_helper_controller_test/url_helper/show_url_for', @response.body
end
def test_named_route_url_shows_host_and_path
with_url_helper_routing do
get :show_named_route, :kind => 'url'
- assert_equal 'http://test.host/url_helper_with_controller/show_named_route', @response.body
+ assert_equal 'http://test.host/url_helper_controller_test/url_helper/show_named_route', @response.body
end
end
def test_named_route_path_shows_only_path
with_url_helper_routing do
get :show_named_route, :kind => 'path'
- assert_equal '/url_helper_with_controller/show_named_route', @response.body
+ assert_equal '/url_helper_controller_test/url_helper/show_named_route', @response.body
end
end
def test_url_for_nil_returns_current_path
get :nil_url_for
- assert_equal '/url_helper/nil_url_for', @response.body
+ assert_equal '/url_helper_controller_test/url_helper/nil_url_for', @response.body
end
def test_named_route_should_show_host_and_path_using_controller_default_url_options
@@ -450,7 +443,7 @@ class UrlHelperWithControllerTest < ActionController::TestCase
with_url_helper_routing do
get :show_named_route, :kind => 'url'
- assert_equal 'http://testtwo.host/url_helper_with_controller/show_named_route', @response.body
+ assert_equal 'http://testtwo.host/url_helper_controller_test/url_helper/show_named_route', @response.body
end
end
@@ -458,7 +451,7 @@ class UrlHelperWithControllerTest < ActionController::TestCase
def with_url_helper_routing
with_routing do |set|
set.draw do |map|
- map.show_named_route 'url_helper_with_controller/show_named_route', :controller => 'url_helper', :action => 'show_named_route'
+ map.show_named_route 'url_helper_controller_test/url_helper/show_named_route', :controller => 'url_helper_controller_test/url_helper', :action => 'show_named_route'
end
yield
end
diff --git a/activemodel/Rakefile b/activemodel/Rakefile
index 8897987518..1f4a8466c9 100755
--- a/activemodel/Rakefile
+++ b/activemodel/Rakefile
@@ -1,4 +1,5 @@
-require File.join(File.dirname(__FILE__), 'lib', 'active_model', 'version')
+dir = File.dirname(__FILE__)
+require "#{dir}/lib/active_model/version"
PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
PKG_NAME = 'activemodel'
@@ -12,17 +13,19 @@ require 'rake/testtask'
task :default => :test
Rake::TestTask.new do |t|
- t.libs << "test"
- t.test_files = Dir.glob("test/cases/**/*_test.rb").sort
+ t.libs << "#{dir}/test"
+ t.test_files = Dir.glob("#{dir}/test/cases/**/*_test.rb").sort
t.verbose = true
t.warning = true
end
-task :isolated_test do
- ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME'))
- Dir.glob("test/**/*_test.rb").all? do |file|
- system(ruby, '-w', '-Ilib:test', file)
- end or raise "Failures"
+namespace :test do
+ task :isolated do
+ ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME'))
+ Dir.glob("#{dir}/test/**/*_test.rb").all? do |file|
+ system(ruby, '-w', "-I#{dir}/lib", "-I#{dir}/test", file)
+ end or raise "Failures"
+ end
end
@@ -30,20 +33,20 @@ require 'rake/rdoctask'
# Generate the RDoc documentation
Rake::RDocTask.new do |rdoc|
- rdoc.rdoc_dir = 'doc'
+ rdoc.rdoc_dir = "#{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'] ? "#{ENV['template']}.rb" : '../doc/template/horo'
- rdoc.rdoc_files.include('README', 'CHANGES')
- rdoc.rdoc_files.include('lib/**/*.rb')
+ rdoc.rdoc_files.include("#{dir}/README", "#{dir}/CHANGES")
+ rdoc.rdoc_files.include("#{dir}/lib/**/*.rb")
end
require 'rake/packagetask'
require 'rake/gempackagetask'
-spec = eval(File.read('activemodel.gemspec'))
+spec = eval(File.read("#{dir}/activemodel.gemspec"))
Rake::GemPackageTask.new(spec) do |p|
p.gem_spec = spec
diff --git a/activemodel/lib/active_model/translation.rb b/activemodel/lib/active_model/translation.rb
index 2ad8ca9dea..42ca463f82 100644
--- a/activemodel/lib/active_model/translation.rb
+++ b/activemodel/lib/active_model/translation.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/hash/reverse_merge'
+
module ActiveModel
module Translation
include ActiveModel::Naming
diff --git a/activemodel/test/cases/helper.rb b/activemodel/test/cases/helper.rb
index 49783c2735..c1a3f6a4a7 100644
--- a/activemodel/test/cases/helper.rb
+++ b/activemodel/test/cases/helper.rb
@@ -3,9 +3,11 @@ begin
require "#{root}/vendor/gems/environment"
rescue LoadError
$:.unshift("#{root}/activesupport/lib")
- $:.unshift("#{root}/activemodel/lib")
end
+lib = File.expand_path("#{File.dirname(__FILE__)}/../../lib")
+$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib)
+
require 'config'
require 'active_model'
diff --git a/activerecord/Rakefile b/activerecord/Rakefile
index f7585f789b..2511f13fed 100644
--- a/activerecord/Rakefile
+++ b/activerecord/Rakefile
@@ -49,11 +49,13 @@ task :test do
run_without_aborting(*tasks)
end
-task :isolated_test do
- tasks = defined?(JRUBY_VERSION) ?
- %w(isolated_test_jdbcmysql isolated_test_jdbcsqlite3 isolated_test_jdbcpostgresql) :
- %w(isolated_test_mysql isolated_test_sqlite3 isolated_test_postgresql)
- run_without_aborting(*tasks)
+namespace :test do
+ task :isolated do
+ tasks = defined?(JRUBY_VERSION) ?
+ %w(isolated_test_jdbcmysql isolated_test_jdbcsqlite3 isolated_test_jdbcpostgresql) :
+ %w(isolated_test_mysql isolated_test_sqlite3 isolated_test_postgresql)
+ run_without_aborting(*tasks)
+ end
end
%w( mysql postgresql sqlite3 firebird db2 oracle sybase openbase frontbase jdbcmysql jdbcpostgresql jdbcsqlite3 jdbcderby jdbch2 jdbchsqldb ).each do |adapter|
diff --git a/activerecord/activerecord.gemspec b/activerecord/activerecord.gemspec
index 204cddde47..c84a3ac5a9 100644
--- a/activerecord/activerecord.gemspec
+++ b/activerecord/activerecord.gemspec
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
s.add_dependency('activesupport', '= 3.0.pre')
s.add_dependency('activemodel', '= 3.0.pre')
- s.add_dependency('arel', '~> 0.1.1')
+ s.add_dependency('arel', '= 0.2.pre')
s.require_path = 'lib'
s.autorequire = 'active_record'
diff --git a/activerecord/lib/active_record/association_preload.rb b/activerecord/lib/active_record/association_preload.rb
index e41fda7a4b..9f7b2a60b2 100644
--- a/activerecord/lib/active_record/association_preload.rb
+++ b/activerecord/lib/active_record/association_preload.rb
@@ -1,3 +1,6 @@
+require 'active_support/core_ext/array/wrap'
+require 'active_support/core_ext/enumerable'
+
module ActiveRecord
# See ActiveRecord::AssociationPreload::ClassMethods for documentation.
module AssociationPreload #:nodoc:
@@ -82,7 +85,7 @@ module ActiveRecord
# only one level deep in the +associations+ argument, i.e. it's not passed
# to the child associations when +associations+ is a Hash.
def preload_associations(records, associations, preload_options={})
- records = [records].flatten.compact.uniq
+ records = Array.wrap(records).compact.uniq
return if records.empty?
case associations
when Array then associations.each {|association| preload_associations(records, association, preload_options)}
@@ -92,7 +95,7 @@ module ActiveRecord
raise "parent must be an association name" unless parent.is_a?(String) || parent.is_a?(Symbol)
preload_associations(records, parent, preload_options)
reflection = reflections[parent]
- parents = records.map {|record| record.send(reflection.name)}.flatten.compact
+ parents = records.sum { |record| Array.wrap(record.send(reflection.name)) }
unless parents.empty?
parents.first.class.preload_associations(parents, child)
end
@@ -123,7 +126,8 @@ module ActiveRecord
parent_records.each do |parent_record|
association_proxy = parent_record.send(reflection_name)
association_proxy.loaded
- association_proxy.target.push(*[associated_record].flatten)
+ association_proxy.target.push *Array.wrap(associated_record)
+
association_proxy.__send__(:set_inverse_instance, associated_record, parent_record)
end
end
@@ -254,6 +258,7 @@ module ActiveRecord
through_reflection = reflections[through_association]
through_primary_key = through_reflection.primary_key_name
+ through_records = []
if reflection.options[:source_type]
interface = reflection.source_reflection.options[:foreign_type]
preload_options = {:conditions => ["#{connection.quote_column_name interface} = ?", reflection.options[:source_type]]}
@@ -262,23 +267,22 @@ module ActiveRecord
records.first.class.preload_associations(records, through_association, preload_options)
# Dont cache the association - we would only be caching a subset
- through_records = []
records.each do |record|
proxy = record.send(through_association)
if proxy.respond_to?(:target)
- through_records << proxy.target
+ through_records.concat Array.wrap(proxy.target)
proxy.reset
else # this is a has_one :through reflection
through_records << proxy if proxy
end
end
- through_records.flatten!
else
records.first.class.preload_associations(records, through_association)
- through_records = records.map {|record| record.send(through_association)}.flatten
+ records.each do |record|
+ through_records.concat Array.wrap(record.send(through_association))
+ end
end
- through_records.compact!
through_records
end
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 03c8d4b3ed..0fcd288fc5 100755
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -1,4 +1,5 @@
require 'active_support/core_ext/module/delegation'
+require 'active_support/core_ext/enumerable'
module ActiveRecord
class InverseOfAssociationNotFoundError < ActiveRecordError #:nodoc:
@@ -60,6 +61,12 @@ module ActiveRecord
end
end
+ class HasAndBelongsToManyAssociationWithPrimaryKeyError < ActiveRecordError #:nodoc:
+ def initialize(reflection)
+ super("Primary key is not allowed in a has_and_belongs_to_many join table (#{reflection.options[:join_table]}).")
+ end
+ end
+
class HasAndBelongsToManyAssociationForeignKeyNeeded < ActiveRecordError #:nodoc:
def initialize(reflection)
super("Cannot create self referential has_and_belongs_to_many association on '#{reflection.class_name rescue nil}##{reflection.name rescue nil}'. :association_foreign_key cannot be the same as the :foreign_key.")
@@ -1396,8 +1403,8 @@ module ActiveRecord
end
define_method("#{reflection.name.to_s.singularize}_ids=") do |new_value|
- ids = (new_value || []).reject { |nid| nid.blank? }
- send("#{reflection.name}=", reflection.klass.find(ids))
+ ids = (new_value || []).reject { |nid| nid.blank? }.map(&:to_i)
+ send("#{reflection.name}=", reflection.klass.find(ids).index_by(&:id).values_at(*ids))
end
end
end
@@ -1480,7 +1487,7 @@ module ActiveRecord
if reflection.options.include?(:dependent)
# Add polymorphic type if the :as option is present
dependent_conditions = []
- dependent_conditions << "#{reflection.primary_key_name} = \#{record.quoted_id}"
+ dependent_conditions << "#{reflection.primary_key_name} = \#{record.#{reflection.name}.send(:owner_quoted_id)}"
dependent_conditions << "#{reflection.options[:as]}_type = '#{base_class.name}'" if reflection.options[:as]
dependent_conditions << sanitize_sql(reflection.options[:conditions], reflection.quoted_table_name) if reflection.options[:conditions]
dependent_conditions << extra_conditions if extra_conditions
@@ -1674,7 +1681,6 @@ module ActiveRecord
def create_has_and_belongs_to_many_reflection(association_id, options, &extension)
options.assert_valid_keys(valid_keys_for_has_and_belongs_to_many_association)
-
options[:extend] = create_extension_modules(association_id, extension, options[:extend])
reflection = create_reflection(:has_and_belongs_to_many, association_id, options, self)
@@ -1684,6 +1690,9 @@ module ActiveRecord
end
reflection.options[:join_table] ||= join_table_name(undecorated_table_name(self.to_s), undecorated_table_name(reflection.class_name))
+ if connection.supports_primary_key? && (connection.primary_key(reflection.options[:join_table]) rescue false)
+ raise HasAndBelongsToManyAssociationWithPrimaryKeyError.new(reflection)
+ end
reflection
end
@@ -1922,12 +1931,16 @@ module ActiveRecord
reflection = base.reflections[name]
is_collection = [:has_many, :has_and_belongs_to_many].include?(reflection.macro)
- parent_records = records.map do |record|
- descendant = record.send(reflection.name)
- next unless descendant
- descendant.target.uniq! if is_collection
- descendant
- end.flatten.compact
+ parent_records = []
+ records.each do |record|
+ if descendant = record.send(reflection.name)
+ if is_collection
+ parent_records.concat descendant.target.uniq
+ else
+ parent_records << descendant
+ end
+ end
+ end
remove_duplicate_results!(reflection.klass, parent_records, associations[name]) unless parent_records.empty?
end
diff --git a/activerecord/lib/active_record/associations/association_proxy.rb b/activerecord/lib/active_record/associations/association_proxy.rb
index 75218c01d2..7d8f4670fa 100644
--- a/activerecord/lib/active_record/associations/association_proxy.rb
+++ b/activerecord/lib/active_record/associations/association_proxy.rb
@@ -256,10 +256,16 @@ module ActiveRecord
end
end
- # Array#flatten has problems with recursive arrays. Going one level
- # deeper solves the majority of the problems.
- def flatten_deeper(array)
- array.collect { |element| (element.respond_to?(:flatten) && !element.is_a?(Hash)) ? element.flatten : element }.flatten
+ if RUBY_VERSION < '1.9.2'
+ # Array#flatten has problems with recursive arrays before Ruby 1.9.2.
+ # Going one level deeper solves the majority of the problems.
+ def flatten_deeper(array)
+ array.collect { |element| (element.respond_to?(:flatten) && !element.is_a?(Hash)) ? element.flatten : element }.flatten
+ end
+ else
+ def flatten_deeper(array)
+ array.flatten
+ end
end
# Returns the ID of the owner, quoted if needed.
diff --git a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb
index c646fe488b..b01faa5212 100644
--- a/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb
+++ b/activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb
@@ -1,11 +1,6 @@
module ActiveRecord
module Associations
class HasAndBelongsToManyAssociation < AssociationCollection #:nodoc:
- def initialize(owner, reflection)
- super
- @primary_key_list = {}
- end
-
def create(attributes = {})
create_record(attributes) { |record| insert_record(record) }
end
@@ -23,9 +18,7 @@ module ActiveRecord
end
def has_primary_key?
- return @has_primary_key unless @has_primary_key.nil?
- @has_primary_key = (@owner.connection.supports_primary_key? &&
- @owner.connection.primary_key(@reflection.options[:join_table]))
+ @has_primary_key ||= @owner.connection.supports_primary_key? && @owner.connection.primary_key(@reflection.options[:join_table])
end
protected
@@ -40,11 +33,6 @@ module ActiveRecord
end
def insert_record(record, force = true, validate = true)
- if has_primary_key?
- raise ActiveRecord::ConfigurationError,
- "Primary key is not allowed in a has_and_belongs_to_many join table (#{@reflection.options[:join_table]})."
- end
-
if record.new_record?
if force
record.save!
diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb
index ab7ad34b9e..3a9a67e3a2 100644
--- a/activerecord/lib/active_record/attribute_methods.rb
+++ b/activerecord/lib/active_record/attribute_methods.rb
@@ -31,11 +31,10 @@ module ActiveRecord
self.class.define_attribute_methods
method_name = method_id.to_s
guard_private_attribute_method!(method_name, args)
- if self.class.generated_attribute_methods.instance_methods.include?(method_name)
- return self.send(method_id, *args, &block)
- end
+ send(method_id, *args, &block)
+ else
+ super
end
- super
end
def respond_to?(*args)
diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb
index 4df0f1af69..4a3ab9ea82 100644
--- a/activerecord/lib/active_record/attribute_methods/dirty.rb
+++ b/activerecord/lib/active_record/attribute_methods/dirty.rb
@@ -1,5 +1,3 @@
-require 'active_support/core_ext/object/tap'
-
module ActiveRecord
module AttributeMethods
module Dirty
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index 4e6090458a..056f29f029 100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -12,7 +12,6 @@ require 'active_support/core_ext/hash/deep_merge'
require 'active_support/core_ext/hash/indifferent_access'
require 'active_support/core_ext/hash/slice'
require 'active_support/core_ext/string/behavior'
-require 'active_support/core_ext/symbol'
require 'active_support/core_ext/object/metaclass'
module ActiveRecord #:nodoc:
diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb
index c8cd79a2b0..986bc7009b 100644
--- a/activerecord/lib/active_record/locking/optimistic.rb
+++ b/activerecord/lib/active_record/locking/optimistic.rb
@@ -23,16 +23,6 @@ module ActiveRecord
# p2.first_name = "should fail"
# p2.save # Raises a ActiveRecord::StaleObjectError
#
- # Optimistic locking will also check for stale data when objects are destroyed. Example:
- #
- # p1 = Person.find(1)
- # p2 = Person.find(1)
- #
- # p1.first_name = "Michael"
- # p1.save
- #
- # p2.destroy # Raises a ActiveRecord::StaleObjectError
- #
# You're then responsible for dealing with the conflict by rescuing the exception and either rolling back, merging,
# or otherwise apply the business logic needed to resolve the conflict.
#
@@ -49,7 +39,6 @@ module ActiveRecord
self.lock_optimistically = true
alias_method_chain :update, :lock
- alias_method_chain :destroy, :lock
alias_method_chain :attributes_from_column_definition, :lock
class << self
@@ -111,29 +100,6 @@ module ActiveRecord
end
end
- def destroy_with_lock #:nodoc:
- return destroy_without_lock unless locking_enabled?
-
- unless new_record?
- lock_col = self.class.locking_column
- previous_value = send(lock_col).to_i
-
- arel_table = self.class.arel_table(self.class.table_name)
-
- affected_rows = arel_table.where(
- arel_table[self.class.primary_key].eq(quoted_id).and(
- arel_table[self.class.locking_column].eq(quote_value(previous_value))
- )
- ).delete
-
- unless affected_rows == 1
- raise ActiveRecord::StaleObjectError, "Attempted to delete a stale object"
- end
- end
-
- freeze
- end
-
module ClassMethods
DEFAULT_LOCKING_COLUMN = 'lock_version'
diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb
index edcf547e01..ca3110a374 100644
--- a/activerecord/lib/active_record/nested_attributes.rb
+++ b/activerecord/lib/active_record/nested_attributes.rb
@@ -250,6 +250,8 @@ module ActiveRecord
assign_nested_attributes_for_#{type}_association(:#{association_name}, attributes)
end
}, __FILE__, __LINE__
+
+ add_autosave_association_callbacks(reflection)
else
raise ArgumentError, "No association found for name `#{association_name}'. Has it been defined yet?"
end
diff --git a/activerecord/lib/active_record/notifications.rb b/activerecord/lib/active_record/notifications.rb
index a5ce7ac524..562a5b91f4 100644
--- a/activerecord/lib/active_record/notifications.rb
+++ b/activerecord/lib/active_record/notifications.rb
@@ -1,5 +1,5 @@
require 'active_support/notifications'
-ActiveSupport::Notifications.subscribe("sql") do |event|
- ActiveRecord::Base.connection.log_info(event.payload[:sql], event.payload[:name], event.duration)
+ActiveSupport::Notifications.subscribe("sql") do |name, before, after, result, instrumenter_id, payload|
+ ActiveRecord::Base.connection.log_info(payload[:sql], name, after - before)
end
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index 6bc56ecf15..5f0eec754f 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -110,19 +110,17 @@ module ActiveRecord
end
def respond_to?(method)
- if @relation.respond_to?(method) || Array.instance_methods.include?(method.to_s)
- true
- else
- super
- end
+ @relation.respond_to?(method) || Array.method_defined?(method) || super
end
private
def method_missing(method, *args, &block)
if @relation.respond_to?(method)
@relation.send(method, *args, &block)
- elsif Array.instance_methods.include?(method.to_s)
+ elsif Array.method_defined?(method)
to_a.send(method, *args, &block)
+ else
+ super
end
end
end
diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb
index 0365cb592f..e8a2a72735 100644
--- a/activerecord/lib/active_record/validations.rb
+++ b/activerecord/lib/active_record/validations.rb
@@ -1,5 +1,3 @@
-require 'active_support/core_ext/integer/even_odd'
-
module ActiveRecord
# Raised by <tt>save!</tt> and <tt>create!</tt> when the record is invalid. Use the
# +record+ method to retrieve the record which did not validate.
diff --git a/activerecord/test/cases/associations/habtm_join_table_test.rb b/activerecord/test/cases/associations/habtm_join_table_test.rb
index bf3e04c3eb..745f169ad7 100644
--- a/activerecord/test/cases/associations/habtm_join_table_test.rb
+++ b/activerecord/test/cases/associations/habtm_join_table_test.rb
@@ -36,21 +36,9 @@ class HabtmJoinTableTest < ActiveRecord::TestCase
uses_transaction :test_should_raise_exception_when_join_table_has_a_primary_key
def test_should_raise_exception_when_join_table_has_a_primary_key
if ActiveRecord::Base.connection.supports_primary_key?
- assert_raise ActiveRecord::ConfigurationError do
- jaime = MyReader.create(:name=>"Jaime")
- jaime.my_books << MyBook.create(:name=>'Great Expectations')
+ assert_raise ActiveRecord::HasAndBelongsToManyAssociationWithPrimaryKeyError do
+ MyReader.has_and_belongs_to_many :my_books
end
end
end
-
- uses_transaction :test_should_cache_result_of_primary_key_check
- def test_should_cache_result_of_primary_key_check
- if ActiveRecord::Base.connection.supports_primary_key?
- ActiveRecord::Base.connection.stubs(:primary_key).with('my_books_my_readers').returns(false).once
- weaz = MyReader.create(:name=>'Weaz')
-
- weaz.my_books << MyBook.create(:name=>'Great Expectations')
- weaz.my_books << MyBook.create(:name=>'Greater Expectations')
- end
- end
end
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index b193f8d8ba..86d14c9c81 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -659,6 +659,18 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_equal 1, Client.find_all_by_client_of(firm.id).size
end
+ def test_delete_all_association_with_primary_key_deletes_correct_records
+ firm = Firm.find(:first)
+ # break the vanilla firm_id foreign key
+ assert_equal 2, firm.clients.count
+ firm.clients.first.update_attribute(:firm_id, nil)
+ assert_equal 1, firm.clients(true).count
+ assert_equal 1, firm.clients_using_primary_key_with_delete_all.count
+ old_record = firm.clients_using_primary_key_with_delete_all.first
+ firm = Firm.find(:first)
+ firm.destroy
+ assert Client.find_by_id(old_record.id).nil?
+ end
def test_creation_respects_hash_condition
ms_client = companies(:first_firm).clients_like_ms_with_hash_conditions.build
diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb
index 5f13b66d11..fe68d03de2 100644
--- a/activerecord/test/cases/associations/has_many_through_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb
@@ -137,6 +137,28 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
assert !posts(:welcome).reload.people(true).include?(people(:michael))
end
+ def test_replace_order_is_preserved
+ posts(:welcome).people.clear
+ posts(:welcome).people = [people(:david), people(:michael)]
+ assert_equal [people(:david).id, people(:michael).id], posts(:welcome).readers.all(:order => 'id').map(&:person_id)
+
+ # Test the inverse order in case the first success was a coincidence
+ posts(:welcome).people.clear
+ posts(:welcome).people = [people(:michael), people(:david)]
+ assert_equal [people(:michael).id, people(:david).id], posts(:welcome).readers.all(:order => 'id').map(&:person_id)
+ end
+
+ def test_replace_by_id_order_is_preserved
+ posts(:welcome).people.clear
+ posts(:welcome).person_ids = [people(:david).id, people(:michael).id]
+ assert_equal [people(:david).id, people(:michael).id], posts(:welcome).readers.all(:order => 'id').map(&:person_id)
+
+ # Test the inverse order in case the first success was a coincidence
+ posts(:welcome).people.clear
+ posts(:welcome).person_ids = [people(:michael).id, people(:david).id]
+ assert_equal [people(:michael).id, people(:david).id], posts(:welcome).readers.all(:order => 'id').map(&:person_id)
+ end
+
def test_associate_with_create
assert_queries(1) { posts(:thinking) }
diff --git a/activerecord/test/cases/copy_table_test_sqlite.rb b/activerecord/test/cases/copy_table_test_sqlite.rb
index de8af30997..575b4806c1 100644
--- a/activerecord/test/cases/copy_table_test_sqlite.rb
+++ b/activerecord/test/cases/copy_table_test_sqlite.rb
@@ -1,7 +1,7 @@
require "cases/helper"
class CopyTableTest < ActiveRecord::TestCase
- fixtures :companies, :comments
+ fixtures :customers, :companies, :comments
def setup
@connection = ActiveRecord::Base.connection
@@ -27,8 +27,8 @@ class CopyTableTest < ActiveRecord::TestCase
test_copy_table('customers', 'customers2',
:rename => {'name' => 'person_name'}) do |from, to, options|
expected = column_values(from, 'name')
- assert expected.any?, 'only nils in resultset; real values are needed'
assert_equal expected, column_values(to, 'person_name')
+ assert expected.any?, "No values in table: #{expected.inspect}"
end
end
diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb
index 871cfa6468..25613da912 100644
--- a/activerecord/test/cases/helper.rb
+++ b/activerecord/test/cases/helper.rb
@@ -3,9 +3,11 @@ begin
require "#{root}/vendor/gems/environment"
rescue LoadError
$:.unshift("#{root}/activesupport/lib")
- $:.unshift("#{root}/activerecord/lib")
end
+lib = File.expand_path("#{File.dirname(__FILE__)}/../../lib")
+$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib)
+
require 'config'
require 'rubygems'
diff --git a/activerecord/test/cases/locking_test.rb b/activerecord/test/cases/locking_test.rb
index e177235591..a64c01292f 100644
--- a/activerecord/test/cases/locking_test.rb
+++ b/activerecord/test/cases/locking_test.rb
@@ -38,24 +38,6 @@ class OptimisticLockingTest < ActiveRecord::TestCase
assert_raise(ActiveRecord::StaleObjectError) { p2.save! }
end
- def test_lock_destroy
- p1 = Person.find(1)
- p2 = Person.find(1)
- assert_equal 0, p1.lock_version
- assert_equal 0, p2.lock_version
-
- p1.first_name = 'stu'
- p1.save!
- assert_equal 1, p1.lock_version
- assert_equal 0, p2.lock_version
-
- assert_raises(ActiveRecord::StaleObjectError) { p2.destroy }
-
- assert p1.destroy
- assert_equal true, p1.frozen?
- assert_raises(ActiveRecord::RecordNotFound) { Person.find(1) }
- end
-
def test_lock_repeating
p1 = Person.find(1)
p2 = Person.find(1)
@@ -282,11 +264,14 @@ unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter)
assert first.end > second.end
end
- def test_second_lock_waits
- assert [0.2, 1, 5].any? { |zzz|
- first, second = duel(zzz) { Person.find 1, :lock => true }
- second.end > first.end
- }
+ # Hit by ruby deadlock detection since connection checkout is mutexed.
+ if RUBY_VERSION < '1.9.0'
+ def test_second_lock_waits
+ assert [0.2, 1, 5].any? { |zzz|
+ first, second = duel(zzz) { Person.find 1, :lock => true }
+ second.end > first.end
+ }
+ end
end
protected
diff --git a/activerecord/test/cases/pooled_connections_test.rb b/activerecord/test/cases/pooled_connections_test.rb
index f9eea3d118..2529a33dab 100644
--- a/activerecord/test/cases/pooled_connections_test.rb
+++ b/activerecord/test/cases/pooled_connections_test.rb
@@ -105,7 +105,7 @@ class PooledConnectionsTest < ActiveRecord::TestCase
Thread.new do
ActiveRecord::Base.connection.rollback_db_transaction
ActiveRecord::Base.connection_pool.release_connection
- end.join rescue nil
+ end
add_record('three')
end
diff --git a/activerecord/test/cases/reflection_test.rb b/activerecord/test/cases/reflection_test.rb
index 99e248743a..acd214eb5a 100644
--- a/activerecord/test/cases/reflection_test.rb
+++ b/activerecord/test/cases/reflection_test.rb
@@ -176,8 +176,8 @@ class ReflectionTest < ActiveRecord::TestCase
def test_reflection_of_all_associations
# FIXME these assertions bust a lot
- assert_equal 36, Firm.reflect_on_all_associations.size
- assert_equal 26, Firm.reflect_on_all_associations(:has_many).size
+ assert_equal 37, Firm.reflect_on_all_associations.size
+ assert_equal 27, Firm.reflect_on_all_associations(:has_many).size
assert_equal 10, Firm.reflect_on_all_associations(:has_one).size
assert_equal 0, Firm.reflect_on_all_associations(:belongs_to).size
end
diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb
index 4833d04aff..1a2c8030fb 100644
--- a/activerecord/test/cases/relations_test.rb
+++ b/activerecord/test/cases/relations_test.rb
@@ -78,7 +78,7 @@ class RelationTest < ActiveRecord::TestCase
relation = Topic.all
["map", "uniq", "sort", "insert", "delete", "update"].each do |method|
- assert relation.respond_to?(method)
+ assert relation.respond_to?(method), "Topic.all should respond to #{method.inspect}"
end
end
diff --git a/activerecord/test/fixtures/edges.yml b/activerecord/test/fixtures/edges.yml
index c16c70dd2f..b804f7b6a6 100644
--- a/activerecord/test/fixtures/edges.yml
+++ b/activerecord/test/fixtures/edges.yml
@@ -1,6 +1,5 @@
<% (1..4).each do |id| %>
edge_<%= id %>:
- id: <%= id %>
source_id: <%= id %>
sink_id: <%= id + 1 %>
-<% end %> \ No newline at end of file
+<% end %>
diff --git a/activerecord/test/models/company.rb b/activerecord/test/models/company.rb
index 469f5399ae..7e93fda1eb 100644
--- a/activerecord/test/models/company.rb
+++ b/activerecord/test/models/company.rb
@@ -68,6 +68,8 @@ class Firm < Company
has_many :readonly_clients, :class_name => 'Client', :readonly => true
has_many :clients_using_primary_key, :class_name => 'Client',
:primary_key => 'name', :foreign_key => 'firm_name'
+ has_many :clients_using_primary_key_with_delete_all, :class_name => 'Client',
+ :primary_key => 'name', :foreign_key => 'firm_name', :dependent => :delete_all
has_many :clients_grouped_by_firm_id, :class_name => "Client", :group => "firm_id", :select => "firm_id"
has_many :clients_grouped_by_name, :class_name => "Client", :group => "name", :select => "name"
diff --git a/activerecord/test/models/pirate.rb b/activerecord/test/models/pirate.rb
index 05c5b666ae..f2c05dd48f 100644
--- a/activerecord/test/models/pirate.rb
+++ b/activerecord/test/models/pirate.rb
@@ -18,7 +18,7 @@ class Pirate < ActiveRecord::Base
has_many :treasure_estimates, :through => :treasures, :source => :price_estimates
# These both have :autosave enabled because accepts_nested_attributes_for is used on them.
- has_one :ship, :validate => true
+ has_one :ship
has_one :non_validated_ship, :class_name => 'Ship'
has_many :birds
has_many :birds_with_method_callbacks, :class_name => "Bird",
diff --git a/activerecord/test/models/ship.rb b/activerecord/test/models/ship.rb
index d0df951622..06759d64b8 100644
--- a/activerecord/test/models/ship.rb
+++ b/activerecord/test/models/ship.rb
@@ -1,7 +1,7 @@
class Ship < ActiveRecord::Base
self.record_timestamps = false
- belongs_to :pirate, :validate => true
+ belongs_to :pirate
has_many :parts, :class_name => 'ShipPart', :autosave => true
accepts_nested_attributes_for :pirate, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index 15e5e12d03..0dd9da4c11 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -160,7 +160,7 @@ ActiveRecord::Schema.define do
t.integer :access_level, :default => 1
end
- create_table :edges, :force => true do |t|
+ create_table :edges, :force => true, :id => false do |t|
t.column :source_id, :integer, :null => false
t.column :sink_id, :integer, :null => false
end
diff --git a/activeresource/Rakefile b/activeresource/Rakefile
index 834d4c0c59..6566e84d4c 100644
--- a/activeresource/Rakefile
+++ b/activeresource/Rakefile
@@ -35,15 +35,16 @@ Rake::TestTask.new { |t|
t.warning = true
}
-task :isolated_test do
- ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME'))
- activesupport_path = "#{File.dirname(__FILE__)}/../activesupport/lib"
- Dir.glob("test/**/*_test.rb").all? do |file|
- system(ruby, '-w', "-Ilib:test:#{activesupport_path}", file)
- end or raise "Failures"
+namespace :test do
+ task :isolated do
+ ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME'))
+ activesupport_path = "#{File.dirname(__FILE__)}/../activesupport/lib"
+ Dir.glob("test/**/*_test.rb").all? do |file|
+ system(ruby, '-w', "-Ilib:test:#{activesupport_path}", file)
+ end or raise "Failures"
+ end
end
-
# Generate the RDoc documentation
Rake::RDocTask.new { |rdoc|
diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb
index bd2abdd38e..18105e8887 100644
--- a/activeresource/lib/active_resource/base.rb
+++ b/activeresource/lib/active_resource/base.rb
@@ -274,8 +274,8 @@ module ActiveResource
@site = nil
else
@site = create_site_uri_from(site)
- @user = URI.decode(@site.user) if @site.user
- @password = URI.decode(@site.password) if @site.password
+ @user = uri_parser.unescape(@site.user) if @site.user
+ @password = uri_parser.unescape(@site.password) if @site.password
end
end
@@ -737,12 +737,12 @@ module ActiveResource
# Accepts a URI and creates the site URI from that.
def create_site_uri_from(site)
- site.is_a?(URI) ? site.dup : URI.parse(site)
+ site.is_a?(URI) ? site.dup : uri_parser.parse(site)
end
# Accepts a URI and creates the proxy URI from that.
def create_proxy_uri_from(proxy)
- proxy.is_a?(URI) ? proxy.dup : URI.parse(proxy)
+ proxy.is_a?(URI) ? proxy.dup : uri_parser.parse(proxy)
end
# contains a set of the current prefix parameters.
@@ -767,6 +767,10 @@ module ActiveResource
[ prefix_options, query_options ]
end
+
+ def uri_parser
+ @uri_parser ||= URI.const_defined?(:Parser) ? URI::Parser.new : URI
+ end
end
attr_accessor :attributes #:nodoc:
@@ -1152,15 +1156,16 @@ module ActiveResource
def respond_to?(method, include_priv = false)
method_name = method.to_s
if attributes.nil?
- return super
+ super
elsif attributes.has_key?(method_name)
- return true
- elsif ['?','='].include?(method_name.last) && attributes.has_key?(method_name.first(-1))
- return true
+ true
+ elsif method_name =~ /(?:=|\?)$/ && attributes.include?($`)
+ true
+ else
+ # super must be called at the end of the method, because the inherited respond_to?
+ # would return true for generated readers, even if the attribute wasn't present
+ super
end
- # super must be called at the end of the method, because the inherited respond_to?
- # would return true for generated readers, even if the attribute wasn't present
- super
end
protected
@@ -1249,13 +1254,15 @@ module ActiveResource
def method_missing(method_symbol, *arguments) #:nodoc:
method_name = method_symbol.to_s
- case method_name.last
+ if method_name =~ /(=|\?)$/
+ case $1
when "="
- attributes[method_name.first(-1)] = arguments.first
+ attributes[$`] = arguments.first
when "?"
- attributes[method_name.first(-1)]
- else
- attributes.has_key?(method_name) ? attributes[method_name] : super
+ attributes[$`]
+ end
+ else
+ attributes.include?(method_name) ? attributes[method_name] : super
end
end
end
diff --git a/activeresource/lib/active_resource/connection.rb b/activeresource/lib/active_resource/connection.rb
index 98cb1a932b..193be89a82 100644
--- a/activeresource/lib/active_resource/connection.rb
+++ b/activeresource/lib/active_resource/connection.rb
@@ -31,20 +31,21 @@ module ActiveResource
def initialize(site, format = ActiveResource::Formats::XmlFormat)
raise ArgumentError, 'Missing site URI' unless site
@user = @password = nil
+ @uri_parser = URI.const_defined?(:Parser) ? URI::Parser.new : URI
self.site = site
self.format = format
end
# Set URI for remote service.
def site=(site)
- @site = site.is_a?(URI) ? site : URI.parse(site)
- @user = URI.decode(@site.user) if @site.user
- @password = URI.decode(@site.password) if @site.password
+ @site = site.is_a?(URI) ? site : @uri_parser.parse(site)
+ @user = @uri_parser.unescape(@site.user) if @site.user
+ @password = @uri_parser.unescape(@site.password) if @site.password
end
# Set the proxy for remote service.
def proxy=(proxy)
- @proxy = proxy.is_a?(URI) ? proxy : URI.parse(proxy)
+ @proxy = proxy.is_a?(URI) ? proxy : @uri_parser.parse(proxy)
end
# Sets the user for remote service.
diff --git a/activeresource/test/abstract_unit.rb b/activeresource/test/abstract_unit.rb
index ee12f785b5..10849be20c 100644
--- a/activeresource/test/abstract_unit.rb
+++ b/activeresource/test/abstract_unit.rb
@@ -3,9 +3,11 @@ begin
require "#{root}/vendor/gems/environment"
rescue LoadError
$:.unshift("#{root}/activesupport/lib")
- $:.unshift("#{root}/activeresource/lib")
end
+lib = File.expand_path("#{File.dirname(__FILE__)}/../lib")
+$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib)
+
require 'rubygems'
require 'test/unit'
require 'active_support'
diff --git a/activeresource/test/cases/base/load_test.rb b/activeresource/test/cases/base/load_test.rb
index 189a4d81fe..7745a9439b 100644
--- a/activeresource/test/cases/base/load_test.rb
+++ b/activeresource/test/cases/base/load_test.rb
@@ -1,7 +1,6 @@
require 'abstract_unit'
require "fixtures/person"
require "fixtures/street_address"
-require 'active_support/core_ext/symbol'
require 'active_support/core_ext/hash/conversions'
module Highrise
diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb
index b91ae65e9f..f2d957f154 100644
--- a/activesupport/lib/active_support/cache.rb
+++ b/activesupport/lib/active_support/cache.rb
@@ -1,4 +1,5 @@
require 'benchmark'
+require 'active_support/core_ext/array/wrap'
require 'active_support/core_ext/benchmark'
require 'active_support/core_ext/exception'
require 'active_support/core_ext/class/attribute_accessors'
@@ -43,7 +44,7 @@ module ActiveSupport
# ActiveSupport::Cache.lookup_store(MyOwnCacheStore.new)
# # => returns MyOwnCacheStore.new
def self.lookup_store(*store_option)
- store, *parameters = *([ store_option ].flatten)
+ store, *parameters = *Array.wrap(store_option).flatten
case store
when Symbol
diff --git a/activesupport/lib/active_support/cache/mem_cache_store.rb b/activesupport/lib/active_support/cache/mem_cache_store.rb
index bec9de86ed..1b6b820ca4 100644
--- a/activesupport/lib/active_support/cache/mem_cache_store.rb
+++ b/activesupport/lib/active_support/cache/mem_cache_store.rb
@@ -38,6 +38,11 @@ module ActiveSupport
#
# If no addresses are specified, then MemCacheStore will connect to
# localhost port 11211 (the default memcached port).
+ #
+ # Instead of addresses one can pass in a MemCache-like object. For example:
+ #
+ # require 'memcached' # gem install memcached; uses C bindings to libmemcached
+ # ActiveSupport::Cache::MemCacheStore.new(Memcached::Rails.new("localhost:11211"))
def initialize(*addresses)
if addresses.first.respond_to?(:get)
@data = addresses.first
diff --git a/activesupport/lib/active_support/core_ext/array/wrap.rb b/activesupport/lib/active_support/core_ext/array/wrap.rb
index 38bb68c1ec..f48d5ce500 100644
--- a/activesupport/lib/active_support/core_ext/array/wrap.rb
+++ b/activesupport/lib/active_support/core_ext/array/wrap.rb
@@ -4,11 +4,10 @@ class Array
def self.wrap(object)
if object.nil?
[]
- # to_a doesn't work correctly with Array() but to_ary always does
- elsif object.respond_to?(:to_a) && !object.respond_to?(:to_ary)
- [object]
+ elsif object.respond_to?(:to_ary)
+ object.to_ary
else
- Array(object)
+ [object]
end
end
end
diff --git a/activesupport/lib/active_support/core_ext/date.rb b/activesupport/lib/active_support/core_ext/date.rb
deleted file mode 100644
index 6672129076..0000000000
--- a/activesupport/lib/active_support/core_ext/date.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-require 'date'
-
-require 'active_support/core_ext/date/acts_like'
-require 'active_support/core_ext/date/freeze'
-
-require 'active_support/core_ext/date/calculations'
-require 'active_support/core_ext/date/conversions'
diff --git a/activesupport/lib/active_support/core_ext/date/conversions.rb b/activesupport/lib/active_support/core_ext/date/conversions.rb
index b41ad5b686..f6c870035b 100644
--- a/activesupport/lib/active_support/core_ext/date/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/date/conversions.rb
@@ -1,7 +1,4 @@
require 'active_support/inflector'
-require 'active_support/core_ext/time/conversions'
-require 'active_support/core_ext/date_time/conversions'
-require 'active_support/values/time_zone'
class Date
DATE_FORMATS = {
diff --git a/activesupport/lib/active_support/core_ext/date_time.rb b/activesupport/lib/active_support/core_ext/date_time.rb
deleted file mode 100644
index 004fd0ad29..0000000000
--- a/activesupport/lib/active_support/core_ext/date_time.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-require 'active_support/core_ext/time'
-require 'active_support/core_ext/date_time/acts_like'
-require 'active_support/core_ext/date_time/calculations'
-require 'active_support/core_ext/date_time/conversions'
-require 'active_support/core_ext/date_time/zones'
diff --git a/activesupport/lib/active_support/core_ext/enumerable.rb b/activesupport/lib/active_support/core_ext/enumerable.rb
index 15a303cf04..b11c916f61 100644
--- a/activesupport/lib/active_support/core_ext/enumerable.rb
+++ b/activesupport/lib/active_support/core_ext/enumerable.rb
@@ -101,15 +101,6 @@ module Enumerable
size = block_given? ? select(&block).size : self.size
size > 1
end
-
- # Returns true if none of the elements match the given block.
- #
- # success = responses.none? {|r| r.status / 100 == 5 }
- #
- # This is a builtin method in Ruby 1.8.7 and later.
- def none?(&block)
- !any?(&block)
- end unless [].respond_to?(:none?)
end
class Range #:nodoc:
diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb
index 190173f8a0..35ccec5df4 100644
--- a/activesupport/lib/active_support/core_ext/hash/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb
@@ -1,4 +1,5 @@
require 'active_support/time'
+require 'active_support/core_ext/array/wrap'
require 'active_support/core_ext/hash/reverse_merge'
class Hash
@@ -138,7 +139,7 @@ class Hash
case value.class.to_s
when 'Hash'
if value['type'] == 'array'
- child_key, entries = value.detect { |k,v| k != 'type' } # child_key is throwaway
+ child_key, entries = Array.wrap(value.detect { |k,v| k != 'type' }) # child_key is throwaway
if entries.nil? || (c = value['__content__'] && c.blank?)
[]
else
diff --git a/activesupport/lib/active_support/core_ext/integer.rb b/activesupport/lib/active_support/core_ext/integer.rb
index 7ba018ed7f..a44a1b4c74 100644
--- a/activesupport/lib/active_support/core_ext/integer.rb
+++ b/activesupport/lib/active_support/core_ext/integer.rb
@@ -1,3 +1,3 @@
-require 'active_support/core_ext/integer/even_odd'
+require 'active_support/core_ext/integer/multiple'
require 'active_support/core_ext/integer/inflections'
require 'active_support/core_ext/integer/time'
diff --git a/activesupport/lib/active_support/core_ext/integer/even_odd.rb b/activesupport/lib/active_support/core_ext/integer/even_odd.rb
deleted file mode 100644
index 8f9a97b44c..0000000000
--- a/activesupport/lib/active_support/core_ext/integer/even_odd.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-class Integer
- # Check whether the integer is evenly divisible by the argument.
- def multiple_of?(number)
- self % number == 0
- end
-
- # Is the integer a multiple of 2?
- def even?
- multiple_of? 2
- end unless method_defined?(:even?)
-
- # Is the integer not a multiple of 2?
- def odd?
- !even?
- end unless method_defined?(:odd?)
-end
diff --git a/activesupport/lib/active_support/core_ext/integer/multiple.rb b/activesupport/lib/active_support/core_ext/integer/multiple.rb
new file mode 100644
index 0000000000..40bea54c67
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/integer/multiple.rb
@@ -0,0 +1,6 @@
+class Integer
+ # Check whether the integer is evenly divisible by the argument.
+ def multiple_of?(number)
+ self % number == 0
+ end
+end
diff --git a/activesupport/lib/active_support/core_ext/kernel/debugger.rb b/activesupport/lib/active_support/core_ext/kernel/debugger.rb
index 0813a51383..59e03e3df7 100644
--- a/activesupport/lib/active_support/core_ext/kernel/debugger.rb
+++ b/activesupport/lib/active_support/core_ext/kernel/debugger.rb
@@ -7,6 +7,7 @@ module Kernel
end
end
+ undef :breakpoint if respond_to?(:breakpoint)
def breakpoint
message = "\n***** The 'breakpoint' command has been renamed 'debugger' -- please change *****\n"
defined?(Rails) ? Rails.logger.info(message) : $stderr.puts(message)
diff --git a/activesupport/lib/active_support/core_ext/logger.rb b/activesupport/lib/active_support/core_ext/logger.rb
index 22749229a3..e4df8fe338 100644
--- a/activesupport/lib/active_support/core_ext/logger.rb
+++ b/activesupport/lib/active_support/core_ext/logger.rb
@@ -137,10 +137,10 @@ class Logger
attr_writer :formatter
public :formatter=
- alias old_format_datetime format_datetime
+ alias old_format_datetime format_datetime if method_defined?(:format_datetime)
def format_datetime(datetime) datetime end
- alias old_msg2str msg2str
+ alias old_msg2str msg2str if method_defined?(:msg2str)
def msg2str(msg) msg end
end
end
diff --git a/activesupport/lib/active_support/core_ext/name_error.rb b/activesupport/lib/active_support/core_ext/name_error.rb
index cd165626c8..e1ebd4f91c 100644
--- a/activesupport/lib/active_support/core_ext/name_error.rb
+++ b/activesupport/lib/active_support/core_ext/name_error.rb
@@ -1,7 +1,9 @@
class NameError
# Extract the name of the missing constant from the exception message.
def missing_name
- $1 if /((::)?([A-Z]\w*)(::[A-Z]\w*)*)$/ =~ message
+ if /undefined local variable or method/ !~ message
+ $1 if /((::)?([A-Z]\w*)(::[A-Z]\w*)*)$/ =~ message
+ end
end
# Was this exception raised because the given name was missing?
diff --git a/activesupport/lib/active_support/core_ext/object/extending.rb b/activesupport/lib/active_support/core_ext/object/extending.rb
index bbf6f8563b..0cc74c8298 100644
--- a/activesupport/lib/active_support/core_ext/object/extending.rb
+++ b/activesupport/lib/active_support/core_ext/object/extending.rb
@@ -50,31 +50,4 @@ class Object
def extend_with_included_modules_from(object) #:nodoc:
object.extended_by.each { |mod| extend mod }
end
-
- unless defined? instance_exec # 1.9
- module InstanceExecMethods #:nodoc:
- end
- include InstanceExecMethods
-
- # Evaluate the block with the given arguments within the context of
- # this object, so self is set to the method receiver.
- #
- # From Mauricio's http://eigenclass.org/hiki/bounded+space+instance_exec
- def instance_exec(*args, &block)
- begin
- old_critical, Thread.critical = Thread.critical, true
- n = 0
- n += 1 while respond_to?(method_name = "__instance_exec#{n}")
- InstanceExecMethods.module_eval { define_method(method_name, &block) }
- ensure
- Thread.critical = old_critical
- end
-
- begin
- send(method_name, *args)
- ensure
- InstanceExecMethods.module_eval { remove_method(method_name) } rescue nil
- end
- end
- end
end
diff --git a/activesupport/lib/active_support/core_ext/object/instance_variables.rb b/activesupport/lib/active_support/core_ext/object/instance_variables.rb
index 4ecaab3bbb..866317b17a 100644
--- a/activesupport/lib/active_support/core_ext/object/instance_variables.rb
+++ b/activesupport/lib/active_support/core_ext/object/instance_variables.rb
@@ -1,11 +1,4 @@
class Object
- # Available in 1.8.6 and later.
- unless respond_to?(:instance_variable_defined?)
- def instance_variable_defined?(variable)
- instance_variables.include?(variable.to_s)
- end
- end
-
# Returns a hash that maps instance variable names without "@" to their
# corresponding values. Keys are strings both in Ruby 1.8 and 1.9.
#
diff --git a/activesupport/lib/active_support/core_ext/object/misc.rb b/activesupport/lib/active_support/core_ext/object/misc.rb
index 80011dfbed..3e3af03cc5 100644
--- a/activesupport/lib/active_support/core_ext/object/misc.rb
+++ b/activesupport/lib/active_support/core_ext/object/misc.rb
@@ -1,3 +1,2 @@
require 'active_support/core_ext/object/returning'
-require 'active_support/core_ext/object/tap'
require 'active_support/core_ext/object/with_options'
diff --git a/activesupport/lib/active_support/core_ext/object/tap.rb b/activesupport/lib/active_support/core_ext/object/tap.rb
deleted file mode 100644
index db7e715e2d..0000000000
--- a/activesupport/lib/active_support/core_ext/object/tap.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-class Object
- # Yields <code>x</code> to the block, and then returns <code>x</code>.
- # The primary purpose of this method is to "tap into" a method chain,
- # in order to perform operations on intermediate results within the chain.
- #
- # (1..10).tap { |x| puts "original: #{x.inspect}" }.to_a.
- # tap { |x| puts "array: #{x.inspect}" }.
- # select { |x| x%2 == 0 }.
- # tap { |x| puts "evens: #{x.inspect}" }.
- # map { |x| x*x }.
- # tap { |x| puts "squares: #{x.inspect}" }
- def tap
- yield self
- self
- end unless Object.respond_to?(:tap)
-end
diff --git a/activesupport/lib/active_support/core_ext/string.rb b/activesupport/lib/active_support/core_ext/string.rb
index 6c52f12712..0365b6af1c 100644
--- a/activesupport/lib/active_support/core_ext/string.rb
+++ b/activesupport/lib/active_support/core_ext/string.rb
@@ -4,7 +4,6 @@ require 'active_support/core_ext/string/multibyte'
require 'active_support/core_ext/string/starts_ends_with'
require 'active_support/core_ext/string/inflections'
require 'active_support/core_ext/string/access'
-require 'active_support/core_ext/string/iterators'
require 'active_support/core_ext/string/xchar'
require 'active_support/core_ext/string/behavior'
require 'active_support/core_ext/string/interpolation'
diff --git a/activesupport/lib/active_support/core_ext/string/access.rb b/activesupport/lib/active_support/core_ext/string/access.rb
index 57385d86d2..182b3e745d 100644
--- a/activesupport/lib/active_support/core_ext/string/access.rb
+++ b/activesupport/lib/active_support/core_ext/string/access.rb
@@ -1,3 +1,5 @@
+require "active_support/multibyte"
+
class String
unless '1.9'.respond_to?(:force_encoding)
# Returns the character at the +position+ treating the string as an array (where 0 is the first character).
diff --git a/activesupport/lib/active_support/core_ext/string/bytesize.rb b/activesupport/lib/active_support/core_ext/string/bytesize.rb
deleted file mode 100644
index ed051b921e..0000000000
--- a/activesupport/lib/active_support/core_ext/string/bytesize.rb
+++ /dev/null
@@ -1,5 +0,0 @@
-unless '1.9'.respond_to?(:bytesize)
- class String
- alias :bytesize :size
- end
-end
diff --git a/activesupport/lib/active_support/core_ext/string/interpolation.rb b/activesupport/lib/active_support/core_ext/string/interpolation.rb
index d9159b690a..2048d35091 100644
--- a/activesupport/lib/active_support/core_ext/string/interpolation.rb
+++ b/activesupport/lib/active_support/core_ext/string/interpolation.rb
@@ -5,8 +5,7 @@
You may redistribute it and/or modify it under the same license terms as Ruby.
=end
-if RUBY_VERSION < '1.9'
- require 'active_support/core_ext/string/bytesize'
+if RUBY_VERSION < '1.9' && !"".respond_to?(:interpolate_without_ruby_19_syntax)
# KeyError is raised by String#% when the string contains a named placeholder
# that is not contained in the given arguments hash. Ruby 1.9 includes and
diff --git a/activesupport/lib/active_support/core_ext/string/iterators.rb b/activesupport/lib/active_support/core_ext/string/iterators.rb
deleted file mode 100644
index 2f8aa84024..0000000000
--- a/activesupport/lib/active_support/core_ext/string/iterators.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-unless '1.9'.respond_to?(:each_char)
- class String
- # Yields a single-character string for each character in the string.
- # When $KCODE = 'UTF8', multi-byte characters are yielded appropriately.
- def each_char
- require 'strscan' unless defined? ::StringScanner
- scanner, char = ::StringScanner.new(self), /./mu
- while c = scanner.scan(char)
- yield c
- end
- end
- end
-end
diff --git a/activesupport/lib/active_support/core_ext/string/starts_ends_with.rb b/activesupport/lib/active_support/core_ext/string/starts_ends_with.rb
index f65bb8f75b..641acf62d0 100644
--- a/activesupport/lib/active_support/core_ext/string/starts_ends_with.rb
+++ b/activesupport/lib/active_support/core_ext/string/starts_ends_with.rb
@@ -1,18 +1,4 @@
class String
- unless '1.8.7 and up'.respond_to?(:start_with?)
- # Does the string start with the specified +prefix+?
- def start_with?(prefix)
- prefix = prefix.to_s
- self[0, prefix.length] == prefix
- end
-
- # Does the string end with the specified +suffix+?
- def end_with?(suffix)
- suffix = suffix.to_s
- self[-suffix.length, suffix.length] == suffix
- end
- end
-
alias_method :starts_with?, :start_with?
alias_method :ends_with?, :end_with?
end
diff --git a/activesupport/lib/active_support/core_ext/symbol.rb b/activesupport/lib/active_support/core_ext/symbol.rb
deleted file mode 100644
index c103cd9dcf..0000000000
--- a/activesupport/lib/active_support/core_ext/symbol.rb
+++ /dev/null
@@ -1 +0,0 @@
-require 'active_support/core_ext/symbol/to_proc'
diff --git a/activesupport/lib/active_support/core_ext/symbol/to_proc.rb b/activesupport/lib/active_support/core_ext/symbol/to_proc.rb
deleted file mode 100644
index 520369452b..0000000000
--- a/activesupport/lib/active_support/core_ext/symbol/to_proc.rb
+++ /dev/null
@@ -1,14 +0,0 @@
-class Symbol
- # Turns the symbol into a simple proc, which is especially useful for enumerations. Examples:
- #
- # # The same as people.collect { |p| p.name }
- # people.collect(&:name)
- #
- # # The same as people.select { |p| p.manager? }.collect { |p| p.salary }
- # people.select(&:manager?).collect(&:salary)
- #
- # This is a builtin method in Ruby 1.8.7 and later.
- def to_proc
- Proc.new { |*args| args.shift.__send__(self, *args) }
- end unless :to_proc.respond_to?(:to_proc)
-end
diff --git a/activesupport/lib/active_support/core_ext/time.rb b/activesupport/lib/active_support/core_ext/time.rb
deleted file mode 100644
index b28f7f1a32..0000000000
--- a/activesupport/lib/active_support/core_ext/time.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-require 'date'
-require 'time'
-
-require 'active_support/core_ext/time/publicize_conversion_methods'
-require 'active_support/core_ext/time/marshal_with_utc_flag'
-
-require 'active_support/core_ext/time/acts_like'
-require 'active_support/core_ext/time/calculations'
-require 'active_support/core_ext/time/conversions'
-require 'active_support/core_ext/time/zones'
diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb
index 7f6f012721..e858bcdc80 100644
--- a/activesupport/lib/active_support/dependencies.rb
+++ b/activesupport/lib/active_support/dependencies.rb
@@ -339,7 +339,7 @@ module ActiveSupport #:nodoc:
next
end
[ nesting_camel ]
- end.flatten.compact.uniq
+ end.compact.flatten.compact.uniq
end
# Search for a file in load_paths matching the provided suffix.
diff --git a/activesupport/lib/active_support/deprecated_callbacks.rb b/activesupport/lib/active_support/deprecated_callbacks.rb
index 20fb03cbeb..f56fef0b6d 100644
--- a/activesupport/lib/active_support/deprecated_callbacks.rb
+++ b/activesupport/lib/active_support/deprecated_callbacks.rb
@@ -1,4 +1,5 @@
require 'active_support/core_ext/array/extract_options'
+require 'active_support/core_ext/array/wrap'
module ActiveSupport
# Callbacks are hooks into the lifecycle of an object that allow you to trigger logic
@@ -194,8 +195,8 @@ module ActiveSupport
end
def should_run_callback?(*args)
- [options[:if]].flatten.compact.all? { |a| evaluate_method(a, *args) } &&
- ![options[:unless]].flatten.compact.any? { |a| evaluate_method(a, *args) }
+ Array.wrap(options[:if]).flatten.compact.all? { |a| evaluate_method(a, *args) } &&
+ !Array.wrap(options[:unless]).flatten.compact.any? { |a| evaluate_method(a, *args) }
end
end
diff --git a/activesupport/lib/active_support/inflector.rb b/activesupport/lib/active_support/inflector.rb
index 67aea2782f..215a60eba7 100644
--- a/activesupport/lib/active_support/inflector.rb
+++ b/activesupport/lib/active_support/inflector.rb
@@ -1,410 +1,7 @@
-# encoding: utf-8
-require 'iconv'
-require 'active_support/core_ext/object/blank'
-require 'active_support/core_ext/string/access'
-require 'active_support/core_ext/string/multibyte'
-
-module ActiveSupport
- # The Inflector transforms words from singular to plural, class names to table names, modularized class names to ones without,
- # and class names to foreign keys. The default inflections for pluralization, singularization, and uncountable words are kept
- # in inflections.rb.
- #
- # The Rails core team has stated patches for the inflections library will not be accepted
- # in order to avoid breaking legacy applications which may be relying on errant inflections.
- # If you discover an incorrect inflection and require it for your application, you'll need
- # to correct it yourself (explained below).
- module Inflector
- extend self
-
- # A singleton instance of this class is yielded by Inflector.inflections, which can then be used to specify additional
- # inflection rules. Examples:
- #
- # ActiveSupport::Inflector.inflections do |inflect|
- # inflect.plural /^(ox)$/i, '\1\2en'
- # inflect.singular /^(ox)en/i, '\1'
- #
- # inflect.irregular 'octopus', 'octopi'
- #
- # inflect.uncountable "equipment"
- # end
- #
- # New rules are added at the top. So in the example above, the irregular rule for octopus will now be the first of the
- # pluralization and singularization rules that is runs. This guarantees that your rules run before any of the rules that may
- # already have been loaded.
- class Inflections
- def self.instance
- @__instance__ ||= new
- end
-
- attr_reader :plurals, :singulars, :uncountables, :humans
-
- def initialize
- @plurals, @singulars, @uncountables, @humans = [], [], [], []
- end
-
- # Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression.
- # The replacement should always be a string that may include references to the matched data from the rule.
- def plural(rule, replacement)
- @uncountables.delete(rule) if rule.is_a?(String)
- @uncountables.delete(replacement)
- @plurals.insert(0, [rule, replacement])
- end
-
- # Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression.
- # The replacement should always be a string that may include references to the matched data from the rule.
- def singular(rule, replacement)
- @uncountables.delete(rule) if rule.is_a?(String)
- @uncountables.delete(replacement)
- @singulars.insert(0, [rule, replacement])
- end
-
- # Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used
- # for strings, not regular expressions. You simply pass the irregular in singular and plural form.
- #
- # Examples:
- # irregular 'octopus', 'octopi'
- # irregular 'person', 'people'
- def irregular(singular, plural)
- @uncountables.delete(singular)
- @uncountables.delete(plural)
- if singular[0,1].upcase == plural[0,1].upcase
- plural(Regexp.new("(#{singular[0,1]})#{singular[1..-1]}$", "i"), '\1' + plural[1..-1])
- plural(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + plural[1..-1])
- singular(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + singular[1..-1])
- else
- plural(Regexp.new("#{singular[0,1].upcase}(?i)#{singular[1..-1]}$"), plural[0,1].upcase + plural[1..-1])
- plural(Regexp.new("#{singular[0,1].downcase}(?i)#{singular[1..-1]}$"), plural[0,1].downcase + plural[1..-1])
- plural(Regexp.new("#{plural[0,1].upcase}(?i)#{plural[1..-1]}$"), plural[0,1].upcase + plural[1..-1])
- plural(Regexp.new("#{plural[0,1].downcase}(?i)#{plural[1..-1]}$"), plural[0,1].downcase + plural[1..-1])
- singular(Regexp.new("#{plural[0,1].upcase}(?i)#{plural[1..-1]}$"), singular[0,1].upcase + singular[1..-1])
- singular(Regexp.new("#{plural[0,1].downcase}(?i)#{plural[1..-1]}$"), singular[0,1].downcase + singular[1..-1])
- end
- end
-
- # Add uncountable words that shouldn't be attempted inflected.
- #
- # Examples:
- # uncountable "money"
- # uncountable "money", "information"
- # uncountable %w( money information rice )
- def uncountable(*words)
- (@uncountables << words).flatten!
- end
-
- # Specifies a humanized form of a string by a regular expression rule or by a string mapping.
- # When using a regular expression based replacement, the normal humanize formatting is called after the replacement.
- # When a string is used, the human form should be specified as desired (example: 'The name', not 'the_name')
- #
- # Examples:
- # human /_cnt$/i, '\1_count'
- # human "legacy_col_person_name", "Name"
- def human(rule, replacement)
- @humans.insert(0, [rule, replacement])
- end
-
- # Clears the loaded inflections within a given scope (default is <tt>:all</tt>).
- # Give the scope as a symbol of the inflection type, the options are: <tt>:plurals</tt>,
- # <tt>:singulars</tt>, <tt>:uncountables</tt>, <tt>:humans</tt>.
- #
- # Examples:
- # clear :all
- # clear :plurals
- def clear(scope = :all)
- case scope
- when :all
- @plurals, @singulars, @uncountables = [], [], []
- else
- instance_variable_set "@#{scope}", []
- end
- end
- end
-
- # Yields a singleton instance of Inflector::Inflections so you can specify additional
- # inflector rules.
- #
- # Example:
- # ActiveSupport::Inflector.inflections do |inflect|
- # inflect.uncountable "rails"
- # end
- def inflections
- if block_given?
- yield Inflections.instance
- else
- Inflections.instance
- end
- end
-
- # Returns the plural form of the word in the string.
- #
- # Examples:
- # "post".pluralize # => "posts"
- # "octopus".pluralize # => "octopi"
- # "sheep".pluralize # => "sheep"
- # "words".pluralize # => "words"
- # "CamelOctopus".pluralize # => "CamelOctopi"
- def pluralize(word)
- result = word.to_s.dup
-
- if word.empty? || inflections.uncountables.include?(result.downcase)
- result
- else
- inflections.plurals.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
- result
- end
- end
-
- # The reverse of +pluralize+, returns the singular form of a word in a string.
- #
- # Examples:
- # "posts".singularize # => "post"
- # "octopi".singularize # => "octopus"
- # "sheep".singularize # => "sheep"
- # "word".singularize # => "word"
- # "CamelOctopi".singularize # => "CamelOctopus"
- def singularize(word)
- result = word.to_s.dup
-
- if inflections.uncountables.include?(result.downcase)
- result
- else
- inflections.singulars.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
- result
- end
- end
-
- # By default, +camelize+ converts strings to UpperCamelCase. If the argument to +camelize+
- # is set to <tt>:lower</tt> then +camelize+ produces lowerCamelCase.
- #
- # +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"
- 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 }
- else
- lower_case_and_underscored_word.to_s.first.downcase + camelize(lower_case_and_underscored_word)[1..-1]
- end
- 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
- # used in the Rails internals.
- #
- # +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"
- def titleize(word)
- humanize(underscore(word)).gsub(/\b('?[a-z])/) { $1.capitalize }
- end
-
- # The reverse of +camelize+. Makes an underscored, lowercase form from the expression in the string.
- #
- # Changes '::' to '/' to convert namespaces to paths.
- #
- # 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').
- gsub(/([a-z\d])([A-Z])/,'\1_\2').
- tr("-", "_").
- downcase
- end
-
- # Replaces underscores with dashes in the string.
- #
- # Example:
- # "puni_puni" # => "puni-puni"
- def dasherize(underscored_word)
- underscored_word.gsub(/_/, '-')
- end
-
- # 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"
- def humanize(lower_case_and_underscored_word)
- result = lower_case_and_underscored_word.to_s.dup
-
- inflections.humans.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
- result.gsub(/_id$/, "").gsub(/_/, " ").capitalize
- end
-
- # Removes the module part from the expression in the string.
- #
- # Examples:
- # "ActiveRecord::CoreExtensions::String::Inflections".demodulize # => "Inflections"
- # "Inflections".demodulize # => "Inflections"
- def demodulize(class_name_in_module)
- class_name_in_module.to_s.gsub(/^.*::/, '')
- end
-
- # Replaces special characters in a string so that it may be used as part of a 'pretty' URL.
- #
- # ==== Examples
- #
- # class Person
- # def to_param
- # "#{id}-#{name.parameterize}"
- # end
- # end
- #
- # @person = Person.find(1)
- # # => #<Person id: 1, name: "Donald E. Knuth">
- #
- # <%= link_to(@person.name, person_path(@person)) %>
- # # => <a href="/person/1-donald-e-knuth">Donald E. Knuth</a>
- def parameterize(string, sep = '-')
- # replace accented chars with their ascii equivalents
- parameterized_string = transliterate(string)
- # Turn unwanted chars into the separator
- parameterized_string.gsub!(/[^a-z0-9\-_\+]+/i, sep)
- unless sep.blank?
- re_sep = Regexp.escape(sep)
- # No more than one of the separator in a row.
- parameterized_string.gsub!(/#{re_sep}{2,}/, sep)
- # Remove leading/trailing separator.
- parameterized_string.gsub!(/^#{re_sep}|#{re_sep}$/i, '')
- end
- parameterized_string.downcase
- end
-
-
- # Replaces accented characters with their ascii equivalents.
- def transliterate(string)
- Iconv.iconv('ascii//ignore//translit', 'utf-8', string).to_s
- end
-
- if RUBY_VERSION >= '1.9'
- undef_method :transliterate
- def transliterate(string)
- warn "Ruby 1.9 doesn't support Unicode normalization yet"
- string.dup
- end
-
- # The iconv transliteration code doesn't function correctly
- # on some platforms, but it's very fast where it does function.
- elsif "foo" != (Inflector.transliterate("föö") rescue nil)
- undef_method :transliterate
- def transliterate(string)
- string.mb_chars.normalize(:kd). # Decompose accented characters
- gsub(/[^\x00-\x7F]+/, '') # Remove anything non-ASCII entirely (e.g. diacritics).
- end
- 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.
- #
- # Examples
- # "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+.)
- #
- # Examples:
- # "egg_and_hams".classify # => "EggAndHam"
- # "posts".classify # => "Post"
- #
- # 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(/.*\./, '')))
- end
-
- # Creates a foreign key name from a class name.
- # +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"
- 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
-
- # Ruby 1.9 introduces an inherit argument for Module#const_get and
- # #const_defined? and changes their default behavior.
- if Module.method(:const_get).arity == 1
- # Tries to find a constant with the name specified in the argument string:
- #
- # "Module".constantize # => Module
- # "Test::Unit".constantize # => Test::Unit
- #
- # The name is assumed to be the one of a top-level constant, no matter whether
- # it starts with "::" or not. No lexical context is taken into account:
- #
- # C = 'outside'
- # module M
- # C = 'inside'
- # C # => 'inside'
- # "C".constantize # => 'outside', same as ::C
- # end
- #
- # NameError is raised when the name is not in CamelCase or the constant is
- # unknown.
- def constantize(camel_cased_word)
- names = camel_cased_word.split('::')
- names.shift if names.empty? || names.first.empty?
-
- constant = Object
- names.each do |name|
- constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
- end
- constant
- end
- else
- def constantize(camel_cased_word) #:nodoc:
- names = camel_cased_word.split('::')
- names.shift if names.empty? || names.first.empty?
-
- constant = Object
- names.each do |name|
- constant = constant.const_get(name, false) || constant.const_missing(name)
- end
- constant
- end
- end
-
- # Turns a number into an ordinal string used to denote the position in an
- # ordered sequence such as 1st, 2nd, 3rd, 4th.
- #
- # Examples:
- # ordinalize(1) # => "1st"
- # ordinalize(2) # => "2nd"
- # ordinalize(1002) # => "1002nd"
- # ordinalize(1003) # => "1003rd"
- def ordinalize(number)
- if (11..13).include?(number.to_i % 100)
- "#{number}th"
- else
- case number.to_i % 10
- when 1; "#{number}st"
- when 2; "#{number}nd"
- when 3; "#{number}rd"
- else "#{number}th"
- end
- end
- end
- end
-end
-
# in case active_support/inflector is required without the rest of active_support
+require 'active_support/inflector/inflections'
+require 'active_support/inflector/transliterate'
+require 'active_support/inflector/methods'
+
require 'active_support/inflections'
require 'active_support/core_ext/string/inflections'
diff --git a/activesupport/lib/active_support/inflector/inflections.rb b/activesupport/lib/active_support/inflector/inflections.rb
new file mode 100644
index 0000000000..785e245ea4
--- /dev/null
+++ b/activesupport/lib/active_support/inflector/inflections.rb
@@ -0,0 +1,211 @@
+module ActiveSupport
+ module Inflector
+ # A singleton instance of this class is yielded by Inflector.inflections, which can then be used to specify additional
+ # inflection rules. Examples:
+ #
+ # ActiveSupport::Inflector.inflections do |inflect|
+ # inflect.plural /^(ox)$/i, '\1\2en'
+ # inflect.singular /^(ox)en/i, '\1'
+ #
+ # inflect.irregular 'octopus', 'octopi'
+ #
+ # inflect.uncountable "equipment"
+ # end
+ #
+ # New rules are added at the top. So in the example above, the irregular rule for octopus will now be the first of the
+ # pluralization and singularization rules that is runs. This guarantees that your rules run before any of the rules that may
+ # already have been loaded.
+ class Inflections
+ def self.instance
+ @__instance__ ||= new
+ end
+
+ attr_reader :plurals, :singulars, :uncountables, :humans
+
+ def initialize
+ @plurals, @singulars, @uncountables, @humans = [], [], [], []
+ end
+
+ # Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression.
+ # The replacement should always be a string that may include references to the matched data from the rule.
+ def plural(rule, replacement)
+ @uncountables.delete(rule) if rule.is_a?(String)
+ @uncountables.delete(replacement)
+ @plurals.insert(0, [rule, replacement])
+ end
+
+ # Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression.
+ # The replacement should always be a string that may include references to the matched data from the rule.
+ def singular(rule, replacement)
+ @uncountables.delete(rule) if rule.is_a?(String)
+ @uncountables.delete(replacement)
+ @singulars.insert(0, [rule, replacement])
+ end
+
+ # Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used
+ # for strings, not regular expressions. You simply pass the irregular in singular and plural form.
+ #
+ # Examples:
+ # irregular 'octopus', 'octopi'
+ # irregular 'person', 'people'
+ def irregular(singular, plural)
+ @uncountables.delete(singular)
+ @uncountables.delete(plural)
+ if singular[0,1].upcase == plural[0,1].upcase
+ plural(Regexp.new("(#{singular[0,1]})#{singular[1..-1]}$", "i"), '\1' + plural[1..-1])
+ plural(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + plural[1..-1])
+ singular(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + singular[1..-1])
+ else
+ plural(Regexp.new("#{singular[0,1].upcase}(?i)#{singular[1..-1]}$"), plural[0,1].upcase + plural[1..-1])
+ plural(Regexp.new("#{singular[0,1].downcase}(?i)#{singular[1..-1]}$"), plural[0,1].downcase + plural[1..-1])
+ plural(Regexp.new("#{plural[0,1].upcase}(?i)#{plural[1..-1]}$"), plural[0,1].upcase + plural[1..-1])
+ plural(Regexp.new("#{plural[0,1].downcase}(?i)#{plural[1..-1]}$"), plural[0,1].downcase + plural[1..-1])
+ singular(Regexp.new("#{plural[0,1].upcase}(?i)#{plural[1..-1]}$"), singular[0,1].upcase + singular[1..-1])
+ singular(Regexp.new("#{plural[0,1].downcase}(?i)#{plural[1..-1]}$"), singular[0,1].downcase + singular[1..-1])
+ end
+ end
+
+ # Add uncountable words that shouldn't be attempted inflected.
+ #
+ # Examples:
+ # uncountable "money"
+ # uncountable "money", "information"
+ # uncountable %w( money information rice )
+ def uncountable(*words)
+ (@uncountables << words).flatten!
+ end
+
+ # Specifies a humanized form of a string by a regular expression rule or by a string mapping.
+ # When using a regular expression based replacement, the normal humanize formatting is called after the replacement.
+ # When a string is used, the human form should be specified as desired (example: 'The name', not 'the_name')
+ #
+ # Examples:
+ # human /_cnt$/i, '\1_count'
+ # human "legacy_col_person_name", "Name"
+ def human(rule, replacement)
+ @humans.insert(0, [rule, replacement])
+ end
+
+ # Clears the loaded inflections within a given scope (default is <tt>:all</tt>).
+ # Give the scope as a symbol of the inflection type, the options are: <tt>:plurals</tt>,
+ # <tt>:singulars</tt>, <tt>:uncountables</tt>, <tt>:humans</tt>.
+ #
+ # Examples:
+ # clear :all
+ # clear :plurals
+ def clear(scope = :all)
+ case scope
+ when :all
+ @plurals, @singulars, @uncountables = [], [], []
+ else
+ instance_variable_set "@#{scope}", []
+ end
+ end
+ end
+
+ # Yields a singleton instance of Inflector::Inflections so you can specify additional
+ # inflector rules.
+ #
+ # Example:
+ # ActiveSupport::Inflector.inflections do |inflect|
+ # inflect.uncountable "rails"
+ # end
+ def inflections
+ if block_given?
+ yield Inflections.instance
+ else
+ Inflections.instance
+ end
+ end
+
+ # Returns the plural form of the word in the string.
+ #
+ # Examples:
+ # "post".pluralize # => "posts"
+ # "octopus".pluralize # => "octopi"
+ # "sheep".pluralize # => "sheep"
+ # "words".pluralize # => "words"
+ # "CamelOctopus".pluralize # => "CamelOctopi"
+ def pluralize(word)
+ result = word.to_s.dup
+
+ if word.empty? || inflections.uncountables.include?(result.downcase)
+ result
+ else
+ inflections.plurals.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
+ result
+ end
+ end
+
+ # The reverse of +pluralize+, returns the singular form of a word in a string.
+ #
+ # Examples:
+ # "posts".singularize # => "post"
+ # "octopi".singularize # => "octopus"
+ # "sheep".singularize # => "sheep"
+ # "word".singularize # => "word"
+ # "CamelOctopi".singularize # => "CamelOctopus"
+ def singularize(word)
+ result = word.to_s.dup
+
+ if inflections.uncountables.include?(result.downcase)
+ result
+ else
+ inflections.singulars.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
+ result
+ end
+ end
+
+ # 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"
+ def humanize(lower_case_and_underscored_word)
+ result = lower_case_and_underscored_word.to_s.dup
+
+ inflections.humans.each { |(rule, replacement)| break if result.gsub!(rule, replacement) }
+ result.gsub(/_id$/, "").gsub(/_/, " ").capitalize
+ 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
+ # used in the Rails internals.
+ #
+ # +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"
+ def titleize(word)
+ humanize(underscore(word)).gsub(/\b('?[a-z])/) { $1.capitalize }
+ 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.
+ #
+ # Examples
+ # "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+.)
+ #
+ # Examples:
+ # "egg_and_hams".classify # => "EggAndHam"
+ # "posts".classify # => "Post"
+ #
+ # 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(/.*\./, '')))
+ end
+ end
+end
diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb
new file mode 100644
index 0000000000..41277893e3
--- /dev/null
+++ b/activesupport/lib/active_support/inflector/methods.rb
@@ -0,0 +1,139 @@
+module ActiveSupport
+ # The Inflector transforms words from singular to plural, class names to table names, modularized class names to ones without,
+ # and class names to foreign keys. The default inflections for pluralization, singularization, and uncountable words are kept
+ # in inflections.rb.
+ #
+ # The Rails core team has stated patches for the inflections library will not be accepted
+ # in order to avoid breaking legacy applications which may be relying on errant inflections.
+ # If you discover an incorrect inflection and require it for your application, you'll need
+ # to correct it yourself (explained below).
+ module Inflector
+ extend self
+
+ # By default, +camelize+ converts strings to UpperCamelCase. If the argument to +camelize+
+ # is set to <tt>:lower</tt> then +camelize+ produces lowerCamelCase.
+ #
+ # +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"
+ 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 }
+ else
+ lower_case_and_underscored_word.to_s[0].chr.downcase + camelize(lower_case_and_underscored_word)[1..-1]
+ end
+ end
+
+ # The reverse of +camelize+. Makes an underscored, lowercase form from the expression in the string.
+ #
+ # Changes '::' to '/' to convert namespaces to paths.
+ #
+ # 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').
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
+ tr("-", "_").
+ downcase
+ end
+
+ # Replaces underscores with dashes in the string.
+ #
+ # Example:
+ # "puni_puni" # => "puni-puni"
+ def dasherize(underscored_word)
+ underscored_word.gsub(/_/, '-')
+ end
+
+ # Removes the module part from the expression in the string.
+ #
+ # Examples:
+ # "ActiveRecord::CoreExtensions::String::Inflections".demodulize # => "Inflections"
+ # "Inflections".demodulize # => "Inflections"
+ def demodulize(class_name_in_module)
+ class_name_in_module.to_s.gsub(/^.*::/, '')
+ end
+
+ # Creates a foreign key name from a class name.
+ # +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"
+ 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
+
+ # Ruby 1.9 introduces an inherit argument for Module#const_get and
+ # #const_defined? and changes their default behavior.
+ if Module.method(:const_get).arity == 1
+ # Tries to find a constant with the name specified in the argument string:
+ #
+ # "Module".constantize # => Module
+ # "Test::Unit".constantize # => Test::Unit
+ #
+ # The name is assumed to be the one of a top-level constant, no matter whether
+ # it starts with "::" or not. No lexical context is taken into account:
+ #
+ # C = 'outside'
+ # module M
+ # C = 'inside'
+ # C # => 'inside'
+ # "C".constantize # => 'outside', same as ::C
+ # end
+ #
+ # NameError is raised when the name is not in CamelCase or the constant is
+ # unknown.
+ def constantize(camel_cased_word)
+ names = camel_cased_word.split('::')
+ names.shift if names.empty? || names.first.empty?
+
+ constant = Object
+ names.each do |name|
+ constant = constant.const_defined?(name) ? constant.const_get(name) : constant.const_missing(name)
+ end
+ constant
+ end
+ else
+ def constantize(camel_cased_word) #:nodoc:
+ names = camel_cased_word.split('::')
+ names.shift if names.empty? || names.first.empty?
+
+ constant = Object
+ names.each do |name|
+ constant = constant.const_get(name, false) || constant.const_missing(name)
+ end
+ constant
+ end
+ end
+
+ # Turns a number into an ordinal string used to denote the position in an
+ # ordered sequence such as 1st, 2nd, 3rd, 4th.
+ #
+ # Examples:
+ # ordinalize(1) # => "1st"
+ # ordinalize(2) # => "2nd"
+ # ordinalize(1002) # => "1002nd"
+ # ordinalize(1003) # => "1003rd"
+ def ordinalize(number)
+ if (11..13).include?(number.to_i % 100)
+ "#{number}th"
+ else
+ case number.to_i % 10
+ when 1; "#{number}st"
+ when 2; "#{number}nd"
+ when 3; "#{number}rd"
+ else "#{number}th"
+ end
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/activesupport/lib/active_support/inflector/transliterate.rb b/activesupport/lib/active_support/inflector/transliterate.rb
new file mode 100644
index 0000000000..30a9072ee1
--- /dev/null
+++ b/activesupport/lib/active_support/inflector/transliterate.rb
@@ -0,0 +1,61 @@
+# encoding: utf-8
+require 'iconv'
+require 'active_support/core_ext/string/multibyte'
+
+module ActiveSupport
+ module Inflector
+ extend self
+
+ # Replaces accented characters with their ascii equivalents.
+ def transliterate(string)
+ Iconv.iconv('ascii//ignore//translit', 'utf-8', string).to_s
+ end
+
+ if RUBY_VERSION >= '1.9'
+ undef_method :transliterate
+ def transliterate(string)
+ warn "Ruby 1.9 doesn't support Unicode normalization yet"
+ string.dup
+ end
+
+ # The iconv transliteration code doesn't function correctly
+ # on some platforms, but it's very fast where it does function.
+ elsif "foo" != (Inflector.transliterate("föö") rescue nil)
+ undef_method :transliterate
+ def transliterate(string)
+ string.mb_chars.normalize(:kd). # Decompose accented characters
+ gsub(/[^\x00-\x7F]+/, '') # Remove anything non-ASCII entirely (e.g. diacritics).
+ end
+ end
+
+ # Replaces special characters in a string so that it may be used as part of a 'pretty' URL.
+ #
+ # ==== Examples
+ #
+ # class Person
+ # def to_param
+ # "#{id}-#{name.parameterize}"
+ # end
+ # end
+ #
+ # @person = Person.find(1)
+ # # => #<Person id: 1, name: "Donald E. Knuth">
+ #
+ # <%= link_to(@person.name, person_path(@person)) %>
+ # # => <a href="/person/1-donald-e-knuth">Donald E. Knuth</a>
+ def parameterize(string, sep = '-')
+ # replace accented chars with their ascii equivalents
+ parameterized_string = transliterate(string)
+ # Turn unwanted chars into the separator
+ parameterized_string.gsub!(/[^a-z0-9\-_\+]+/i, sep)
+ unless sep.nil? || sep.empty?
+ re_sep = Regexp.escape(sep)
+ # No more than one of the separator in a row.
+ parameterized_string.gsub!(/#{re_sep}{2,}/, sep)
+ # Remove leading/trailing separator.
+ parameterized_string.gsub!(/^#{re_sep}|#{re_sep}$/i, '')
+ end
+ parameterized_string.downcase
+ end
+ end
+end \ No newline at end of file
diff --git a/activesupport/lib/active_support/json/backends/jsongem.rb b/activesupport/lib/active_support/json/backends/jsongem.rb
index c6c17a3c4e..cfe28d7bb9 100644
--- a/activesupport/lib/active_support/json/backends/jsongem.rb
+++ b/activesupport/lib/active_support/json/backends/jsongem.rb
@@ -23,15 +23,18 @@ module ActiveSupport
private
def convert_dates_from(data)
case data
- when DATE_REGEX
- DateTime.parse(data)
- when Array
- data.map! { |d| convert_dates_from(d) }
- when Hash
- data.each do |key, value|
- data[key] = convert_dates_from(value)
- end
- else data
+ when nil
+ nil
+ when DATE_REGEX
+ DateTime.parse(data)
+ when Array
+ data.map! { |d| convert_dates_from(d) }
+ when Hash
+ data.each do |key, value|
+ data[key] = convert_dates_from(value)
+ end
+ else
+ data
end
end
end
diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb
index 8e8f9022c1..3c15056c41 100644
--- a/activesupport/lib/active_support/json/encoding.rb
+++ b/activesupport/lib/active_support/json/encoding.rb
@@ -6,7 +6,7 @@ require 'active_support/core_ext/module/delegation'
require 'active_support/core_ext/object/instance_variables'
require 'active_support/deprecation'
-require 'active_support/time_with_zone'
+require 'active_support/time'
# Hack to load json gem first so we can overwrite its to_json.
begin
diff --git a/activesupport/lib/active_support/message_verifier.rb b/activesupport/lib/active_support/message_verifier.rb
index 282346b1a6..87e4b1ad33 100644
--- a/activesupport/lib/active_support/message_verifier.rb
+++ b/activesupport/lib/active_support/message_verifier.rb
@@ -1,5 +1,3 @@
-require 'active_support/core_ext/string/bytesize'
-
module ActiveSupport
# MessageVerifier makes it easy to generate and verify messages which are signed
# to prevent tampering.
diff --git a/activesupport/lib/active_support/multibyte/chars.rb b/activesupport/lib/active_support/multibyte/chars.rb
index d372b0ab1f..c7225fec06 100644
--- a/activesupport/lib/active_support/multibyte/chars.rb
+++ b/activesupport/lib/active_support/multibyte/chars.rb
@@ -1,4 +1,5 @@
# encoding: utf-8
+require 'active_support/core_ext/string/access'
require 'active_support/core_ext/string/behavior'
module ActiveSupport #:nodoc:
@@ -197,7 +198,7 @@ module ActiveSupport #:nodoc:
# 'Café périferôl'.mb_chars.index('ô') #=> 12
# 'Café périferôl'.mb_chars.index(/\w/u) #=> 0
def index(needle, offset=0)
- wrapped_offset = self.first(offset).wrapped_string.length
+ wrapped_offset = first(offset).wrapped_string.length
index = @wrapped_string.index(needle, wrapped_offset)
index ? (self.class.u_unpack(@wrapped_string.slice(0...index)).size) : nil
end
@@ -211,7 +212,7 @@ module ActiveSupport #:nodoc:
# 'Café périferôl'.mb_chars.rindex(/\w/u) #=> 13
def rindex(needle, offset=nil)
offset ||= length
- wrapped_offset = self.first(offset).wrapped_string.length
+ wrapped_offset = first(offset).wrapped_string.length
index = @wrapped_string.rindex(needle, wrapped_offset)
index ? (self.class.u_unpack(@wrapped_string.slice(0...index)).size) : nil
end
diff --git a/activesupport/lib/active_support/notifications.rb b/activesupport/lib/active_support/notifications.rb
index 9eae3bebe2..e2540cd598 100644
--- a/activesupport/lib/active_support/notifications.rb
+++ b/activesupport/lib/active_support/notifications.rb
@@ -41,7 +41,7 @@ module ActiveSupport
# to subscribers in a thread. You can use any queue implementation you want.
#
module Notifications
- mattr_accessor :queue
+ mattr_accessor :queue, :listener
class << self
delegate :instrument, :transaction_id, :transaction, :to => :instrumenter
@@ -54,8 +54,13 @@ module ActiveSupport
@publisher ||= Publisher.new(queue)
end
- def subscribe(pattern=nil, &block)
- Subscriber.new(queue).bind(pattern).subscribe(&block)
+ def subscriber
+ @subscriber ||= Subscriber.new(queue)
+ end
+
+ def subscribe(pattern=nil, options={}, &block)
+ with = options[:with] || listener
+ subscriber.bind(with, pattern).subscribe(&block)
end
end
@@ -104,14 +109,15 @@ module ActiveSupport
@queue = queue
end
- def bind(pattern)
- @pattern = pattern
+ def bind(listener, pattern)
+ @listener = listener
+ @pattern = pattern
self
end
def subscribe
- @queue.subscribe(@pattern) do |*args|
- yield *args
+ @queue.subscribe(@listener, @pattern) do |*args|
+ yield(*args)
end
end
end
@@ -138,54 +144,70 @@ module ActiveSupport
end
end
- # This is a default queue implementation that ships with Notifications. It
- # consumes events in a thread and publish them to all registered subscribers.
- #
- class LittleFanout
- def initialize
- @listeners = []
- @stream = Queue.new
+ class AsyncListener
+ def initialize(pattern, &block)
+ @pattern = pattern
+ @subscriber = block
+ @queue = Queue.new
Thread.new { consume }
end
- def publish(*args)
- @stream.push(args)
- end
-
- def subscribe(pattern=nil, &block)
- @listeners << Listener.new(pattern, &block)
+ def publish(name, *args)
+ if !@pattern || @pattern === name.to_s
+ @queue << args.unshift(name)
+ end
end
def consume
- while args = @stream.shift
- @listeners.each { |l| l.publish(*args) }
+ while args = @queue.shift
+ @subscriber.call(*args)
end
end
- class Listener
- # attr_reader :thread
+ def drained?
+ @queue.size.zero?
+ end
+ end
- def initialize(pattern, &block)
- @pattern = pattern
- @subscriber = block
- @queue = Queue.new
- Thread.new { consume }
- end
+ class SyncListener
+ def initialize(pattern, &block)
+ @pattern = pattern
+ @subscriber = block
+ end
- def publish(name, *args)
- if !@pattern || @pattern === name.to_s
- @queue << args.unshift(name)
- end
+ def publish(name, *args)
+ if !@pattern || @pattern === name.to_s
+ @subscriber.call(*args.unshift(name))
end
+ end
- def consume
- while args = @queue.shift
- @subscriber.call(*args)
- end
- end
+ def drained?
+ true
+ end
+ end
+
+ # This is a default queue implementation that ships with Notifications. It
+ # consumes events in a thread and publish them to all registered subscribers.
+ #
+ class LittleFanout
+ def initialize
+ @listeners = []
+ end
+
+ def publish(*args)
+ @listeners.each { |l| l.publish(*args) }
+ end
+
+ def subscribe(listener, pattern=nil, &block)
+ @listeners << listener.new(pattern, &block)
+ end
+
+ def drained?
+ @listeners.all? &:drained?
end
end
end
- Notifications.queue = Notifications::LittleFanout.new
+ Notifications.queue = Notifications::LittleFanout.new
+ Notifications.listener = Notifications::AsyncListener
end
diff --git a/activesupport/lib/active_support/rescuable.rb b/activesupport/lib/active_support/rescuable.rb
index 879662c16c..f0119f5994 100644
--- a/activesupport/lib/active_support/rescuable.rb
+++ b/activesupport/lib/active_support/rescuable.rb
@@ -81,7 +81,7 @@ module ActiveSupport
def handler_for_rescue(exception)
# We go from right to left because pairs are pushed onto rescue_handlers
# as rescue_from declarations are found.
- _, rescuer = Array(rescue_handlers).reverse.detect do |klass_name, handler|
+ _, rescuer = rescue_handlers.reverse.detect do |klass_name, handler|
# The purpose of allowing strings in rescue_from is to support the
# declaration of handler associations for exception classes whose
# definition is yet unknown.
diff --git a/activesupport/lib/active_support/ruby/shim.rb b/activesupport/lib/active_support/ruby/shim.rb
index 37c57c485a..f811239077 100644
--- a/activesupport/lib/active_support/ruby/shim.rb
+++ b/activesupport/lib/active_support/ruby/shim.rb
@@ -4,21 +4,15 @@
# Date next_year, next_month
# DateTime to_date, to_datetime, xmlschema
# Enumerable group_by, each_with_object, none?
-# Integer even?, odd?
-# Object tap
# Process Process.daemon
# REXML security fix
# String ord
-# Symbol to_proc
# Time to_date, to_time, to_datetime
require 'active_support'
require 'active_support/core_ext/date/calculations'
require 'active_support/core_ext/date_time/conversions'
require 'active_support/core_ext/enumerable'
-require 'active_support/core_ext/integer/even_odd'
-require 'active_support/core_ext/object/tap'
require 'active_support/core_ext/process/daemon'
require 'active_support/core_ext/string/conversions'
require 'active_support/core_ext/rexml'
-require 'active_support/core_ext/symbol/to_proc'
require 'active_support/core_ext/time/conversions'
diff --git a/activesupport/lib/active_support/testing/isolation.rb b/activesupport/lib/active_support/testing/isolation.rb
index c75b59c284..81f7e3c9df 100644
--- a/activesupport/lib/active_support/testing/isolation.rb
+++ b/activesupport/lib/active_support/testing/isolation.rb
@@ -1,10 +1,25 @@
module ActiveSupport
module Testing
+ class RemoteError < StandardError
+
+ attr_reader :message, :backtrace
+
+ def initialize(exception)
+ @message = "caught #{exception.class.name}: #{exception.message}"
+ @backtrace = exception.backtrace
+ end
+ end
+
class ProxyTestResult
def initialize
@calls = []
end
+ def add_error(e)
+ e = Test::Unit::Error.new(e.test_name, RemoteError.new(e.exception))
+ @calls << [:add_error, e]
+ end
+
def __replay__(result)
@calls.each do |name, args|
result.send(name, *args)
diff --git a/activesupport/lib/active_support/testing/setup_and_teardown.rb b/activesupport/lib/active_support/testing/setup_and_teardown.rb
index 7952eb50c3..0e998d2dbe 100644
--- a/activesupport/lib/active_support/testing/setup_and_teardown.rb
+++ b/activesupport/lib/active_support/testing/setup_and_teardown.rb
@@ -21,12 +21,12 @@ module ActiveSupport
run_callbacks :setup
result = super
rescue Exception => e
- result = runner.puke(self.class, self.name, e)
+ result = runner.puke(self.class, method_name, e)
ensure
begin
run_callbacks :teardown, :enumerator => :reverse_each
rescue Exception => e
- result = runner.puke(self.class, self.name, e)
+ result = runner.puke(self.class, method_name, e)
end
end
result
diff --git a/activesupport/lib/active_support/time.rb b/activesupport/lib/active_support/time.rb
index d36a683601..0f421421d0 100644
--- a/activesupport/lib/active_support/time.rb
+++ b/activesupport/lib/active_support/time.rb
@@ -1,7 +1,4 @@
require 'active_support'
-require 'active_support/core_ext/time'
-require 'active_support/core_ext/date'
-require 'active_support/core_ext/date_time'
module ActiveSupport
autoload :Duration, 'active_support/duration'
@@ -12,3 +9,26 @@ module ActiveSupport
[Duration, TimeWithZone, TimeZone]
end
end
+
+require 'date'
+require 'time'
+
+require 'active_support/core_ext/time/publicize_conversion_methods'
+require 'active_support/core_ext/time/marshal_with_utc_flag'
+require 'active_support/core_ext/time/acts_like'
+require 'active_support/core_ext/time/calculations'
+require 'active_support/core_ext/time/conversions'
+require 'active_support/core_ext/time/zones'
+
+require 'active_support/core_ext/date/acts_like'
+require 'active_support/core_ext/date/freeze'
+require 'active_support/core_ext/date/calculations'
+require 'active_support/core_ext/date/conversions'
+
+require 'active_support/core_ext/date_time/acts_like'
+require 'active_support/core_ext/date_time/calculations'
+require 'active_support/core_ext/date_time/conversions'
+require 'active_support/core_ext/date_time/zones'
+
+require 'active_support/core_ext/integer/time'
+require 'active_support/core_ext/numeric/time'
diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb
index a64128e49e..8304f6c434 100644
--- a/activesupport/lib/active_support/time_with_zone.rb
+++ b/activesupport/lib/active_support/time_with_zone.rb
@@ -1,10 +1,4 @@
-require 'active_support/duration'
-require 'active_support/values/time_zone'
-require 'active_support/core_ext/numeric/time'
-require 'active_support/core_ext/integer/time'
-require 'active_support/core_ext/time/conversions'
-require 'active_support/core_ext/date/conversions'
-require 'active_support/core_ext/date_time/conversions'
+require "active_support/values/time_zone"
module ActiveSupport
# A Time-like class that can represent a time in any time zone. Necessary because standard Ruby Time instances are
diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb
index 53a4c7acf5..cbb8e890ae 100644
--- a/activesupport/lib/active_support/values/time_zone.rb
+++ b/activesupport/lib/active_support/values/time_zone.rb
@@ -1,6 +1,4 @@
-require 'active_support/core_ext/time'
-require 'active_support/core_ext/date'
-require 'active_support/core_ext/date_time'
+require 'active_support/core_ext/object/blank'
# The TimeZone class serves as a wrapper around TZInfo::Timezone instances. It allows us to do the following:
#
diff --git a/activesupport/lib/active_support/vendor.rb b/activesupport/lib/active_support/vendor.rb
index 4a711b7e25..eb5080888c 100644
--- a/activesupport/lib/active_support/vendor.rb
+++ b/activesupport/lib/active_support/vendor.rb
@@ -9,7 +9,7 @@ end
unless ActiveSupport.requirable? lib
# Try to activate a gem ~> satisfying the requested version first.
begin
- gem lib, "~> #{version}"
+ gem lib, ">= #{version}"
# Use the vendored lib if the gem's missing or we aren't using RubyGems.
rescue LoadError, NoMethodError
# There could be symlinks
diff --git a/activesupport/lib/active_support/whiny_nil.rb b/activesupport/lib/active_support/whiny_nil.rb
index 36fe9510ba..c4aaba7ab3 100644
--- a/activesupport/lib/active_support/whiny_nil.rb
+++ b/activesupport/lib/active_support/whiny_nil.rb
@@ -43,7 +43,14 @@ class NilClass
private
def method_missing(method, *args, &block)
- raise_nil_warning_for METHOD_CLASS_MAP[method], method, caller
+ # Ruby 1.9.2: disallow explicit coercion via method_missing.
+ if method == :to_ary || method == :to_str
+ super
+ elsif klass = METHOD_CLASS_MAP[method]
+ raise_nil_warning_for klass, method, caller
+ else
+ super
+ end
end
# Raises a NoMethodError when you attempt to call a method on +nil+.
@@ -55,4 +62,3 @@ class NilClass
raise NoMethodError, message, with_caller || caller
end
end
-
diff --git a/activesupport/test/abstract_unit.rb b/activesupport/test/abstract_unit.rb
index f390c66838..dda139372e 100644
--- a/activesupport/test/abstract_unit.rb
+++ b/activesupport/test/abstract_unit.rb
@@ -1,22 +1,15 @@
ORIG_ARGV = ARGV.dup
-root = File.expand_path('../../..', __FILE__)
+
begin
- require "#{root}/vendor/gems/environment"
+ require File.expand_path('../../../vendor/gems/environment', __FILE__)
rescue LoadError
- $:.unshift("#{root}/activesupport/lib")
- $:.unshift("#{root}/activerecord/lib")
end
+lib = File.expand_path("#{File.dirname(__FILE__)}/../lib")
+$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib)
require 'test/unit'
-
-begin
- require 'mocha'
-rescue LoadError
- $stderr.puts 'Loading rubygems'
- require 'rubygems'
- require 'mocha'
-end
+require 'mocha'
ENV['NO_RELOAD'] = '1'
require 'active_support'
diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb
index 6a51ce9402..00e05f76fe 100644
--- a/activesupport/test/caching_test.rb
+++ b/activesupport/test/caching_test.rb
@@ -30,7 +30,9 @@ class CacheStoreSettingTest < ActiveSupport::TestCase
def test_mem_cache_fragment_cache_store_with_given_mem_cache_like_object
MemCache.expects(:new).never
- store = ActiveSupport::Cache.lookup_store :mem_cache_store, stub("memcache", :get => true)
+ memcache = Object.new
+ def memcache.get() true end
+ store = ActiveSupport::Cache.lookup_store :mem_cache_store, memcache
assert_kind_of(ActiveSupport::Cache::MemCacheStore, store)
end
diff --git a/activesupport/test/core_ext/array_ext_test.rb b/activesupport/test/core_ext/array_ext_test.rb
index 8198b9bd2c..f5f91ddd80 100644
--- a/activesupport/test/core_ext/array_ext_test.rb
+++ b/activesupport/test/core_ext/array_ext_test.rb
@@ -339,6 +339,11 @@ class ArrayWrapperTests < Test::Unit::TestCase
end
end
+ class Proxy
+ def initialize(target) @target = target end
+ def method_missing(*a) @target.send(*a) end
+ end
+
def test_array
ary = %w(foo bar)
assert_same ary, Array.wrap(ary)
@@ -364,4 +369,19 @@ class ArrayWrapperTests < Test::Unit::TestCase
def test_object_with_to_ary
assert_equal ["foo", "bar"], Array.wrap(FakeCollection.new)
end
+
+ def test_proxy_object
+ p = Proxy.new(Object.new)
+ assert_equal [p], Array.wrap(p)
+ end
+
+ def test_proxy_to_object_with_to_ary
+ p = Proxy.new(FakeCollection.new)
+ assert_equal [p], Array.wrap(p)
+ end
+
+ def test_struct
+ o = Struct.new(:foo).new(123)
+ assert_equal [o], Array.wrap(o)
+ end
end
diff --git a/activesupport/test/core_ext/date_ext_test.rb b/activesupport/test/core_ext/date_ext_test.rb
index 18422d68bc..23c9bc7fb1 100644
--- a/activesupport/test/core_ext/date_ext_test.rb
+++ b/activesupport/test/core_ext/date_ext_test.rb
@@ -1,5 +1,5 @@
require 'abstract_unit'
-require 'active_support/core_ext/date'
+require 'active_support/time'
class DateExtCalculationsTest < Test::Unit::TestCase
def test_to_s
diff --git a/activesupport/test/core_ext/date_time_ext_test.rb b/activesupport/test/core_ext/date_time_ext_test.rb
index a7b179b2be..4341ead488 100644
--- a/activesupport/test/core_ext/date_time_ext_test.rb
+++ b/activesupport/test/core_ext/date_time_ext_test.rb
@@ -1,5 +1,5 @@
require 'abstract_unit'
-require 'active_support/core_ext/date_time'
+require 'active_support/time'
class DateTimeExtCalculationsTest < Test::Unit::TestCase
def test_to_s
diff --git a/activesupport/test/core_ext/enumerable_test.rb b/activesupport/test/core_ext/enumerable_test.rb
index 4170de3dce..66f5f9fbde 100644
--- a/activesupport/test/core_ext/enumerable_test.rb
+++ b/activesupport/test/core_ext/enumerable_test.rb
@@ -1,6 +1,5 @@
require 'abstract_unit'
require 'active_support/core_ext/array'
-require 'active_support/core_ext/symbol'
require 'active_support/core_ext/enumerable'
Payment = Struct.new(:price)
@@ -90,15 +89,4 @@ class EnumerableTests < Test::Unit::TestCase
assert ![ 1, 2 ].many? {|x| x > 1 }
assert [ 1, 2, 2 ].many? {|x| x > 1 }
end
-
- def test_none
- assert [].none?
- assert [nil, false].none?
- assert ![1].none?
-
- assert [].none? {|x| x > 1 }
- assert ![ 2 ].none? {|x| x > 1 }
- assert ![ 1, 2 ].none? {|x| x > 1 }
- assert [ 1, 1 ].none? {|x| x > 1 }
- end
end
diff --git a/activesupport/test/core_ext/integer_ext_test.rb b/activesupport/test/core_ext/integer_ext_test.rb
index 956ae5189d..e1591089f5 100644
--- a/activesupport/test/core_ext/integer_ext_test.rb
+++ b/activesupport/test/core_ext/integer_ext_test.rb
@@ -2,22 +2,6 @@ require 'abstract_unit'
require 'active_support/core_ext/integer'
class IntegerExtTest < Test::Unit::TestCase
- def test_even
- assert [ -2, 0, 2, 4 ].all? { |i| i.even? }
- assert ![ -1, 1, 3 ].all? { |i| i.even? }
-
- assert 22953686867719691230002707821868552601124472329079.odd?
- assert !22953686867719691230002707821868552601124472329079.even?
- assert 22953686867719691230002707821868552601124472329080.even?
- assert !22953686867719691230002707821868552601124472329080.odd?
- end
-
- def test_odd
- assert ![ -2, 0, 2, 4 ].all? { |i| i.odd? }
- assert [ -1, 1, 3 ].all? { |i| i.odd? }
- assert 1000000000000000000000000000000000000000000000000000000001.odd?
- end
-
def test_multiple_of
[ -7, 0, 7, 14 ].each { |i| assert i.multiple_of?(7) }
[ -7, 7, 14 ].each { |i| assert ! i.multiple_of?(6) }
diff --git a/activesupport/test/core_ext/name_error_test.rb b/activesupport/test/core_ext/name_error_test.rb
index 10913e2ade..6352484d04 100644
--- a/activesupport/test/core_ext/name_error_test.rb
+++ b/activesupport/test/core_ext/name_error_test.rb
@@ -3,23 +3,19 @@ require 'active_support/core_ext/name_error'
class NameErrorTest < Test::Unit::TestCase
def test_name_error_should_set_missing_name
- begin
- SomeNameThatNobodyWillUse____Really ? 1 : 0
- flunk "?!?!"
- rescue NameError => exc
- assert_equal "NameErrorTest::SomeNameThatNobodyWillUse____Really", exc.missing_name
- assert exc.missing_name?(:SomeNameThatNobodyWillUse____Really)
- assert exc.missing_name?("NameErrorTest::SomeNameThatNobodyWillUse____Really")
- end
+ SomeNameThatNobodyWillUse____Really ? 1 : 0
+ flunk "?!?!"
+ rescue NameError => exc
+ assert_equal "NameErrorTest::SomeNameThatNobodyWillUse____Really", exc.missing_name
+ assert exc.missing_name?(:SomeNameThatNobodyWillUse____Really)
+ assert exc.missing_name?("NameErrorTest::SomeNameThatNobodyWillUse____Really")
end
def test_missing_method_should_ignore_missing_name
- begin
- some_method_that_does_not_exist
- flunk "?!?!"
- rescue NameError => exc
- assert_equal nil, exc.missing_name
- assert ! exc.missing_name?(:Foo)
- end
+ some_method_that_does_not_exist
+ flunk "?!?!"
+ rescue NameError => exc
+ assert !exc.missing_name?(:Foo)
+ assert_nil exc.missing_name
end
end
diff --git a/activesupport/test/core_ext/object_and_class_ext_test.rb b/activesupport/test/core_ext/object_and_class_ext_test.rb
index f0121b862d..e6fbdb637b 100644
--- a/activesupport/test/core_ext/object_and_class_ext_test.rb
+++ b/activesupport/test/core_ext/object_and_class_ext_test.rb
@@ -182,13 +182,6 @@ class ObjectInstanceVariableTest < Test::Unit::TestCase
assert_equal %w(@bar @baz), @source.instance_variable_names.sort
end
- def test_instance_variable_defined
- assert @source.instance_variable_defined?('@bar')
- assert @source.instance_variable_defined?(:@bar)
- assert !@source.instance_variable_defined?(:@foo)
- assert !@source.instance_variable_defined?('@foo')
- end
-
def test_copy_instance_variables_from_without_explicit_excludes
assert_equal [], @dest.instance_variables
@dest.copy_instance_variables_from(@source)
diff --git a/activesupport/test/core_ext/object_ext_test.rb b/activesupport/test/core_ext/object_ext_test.rb
deleted file mode 100644
index 04c19ed2aa..0000000000
--- a/activesupport/test/core_ext/object_ext_test.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-require 'abstract_unit'
-require 'active_support/core_ext/object/metaclass'
-
-class ObjectExtTest < Test::Unit::TestCase
- def test_tap_yields_and_returns_self
- foo = Object.new
- assert_equal foo, foo.tap { |x| assert_equal foo, x; :bar }
- end
-end
diff --git a/activesupport/test/core_ext/range_ext_test.rb b/activesupport/test/core_ext/range_ext_test.rb
index 2565c56b8a..5701eeef28 100644
--- a/activesupport/test/core_ext/range_ext_test.rb
+++ b/activesupport/test/core_ext/range_ext_test.rb
@@ -1,6 +1,6 @@
require 'abstract_unit'
+require 'active_support/time'
require 'active_support/core_ext/range'
-require 'active_support/core_ext/date/conversions'
class RangeTest < Test::Unit::TestCase
def test_to_s_from_dates
diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb
index 584a41b631..56ed296dac 100644
--- a/activesupport/test/core_ext/string_ext_test.rb
+++ b/activesupport/test/core_ext/string_ext_test.rb
@@ -4,7 +4,8 @@ require 'abstract_unit'
require 'inflector_test_cases'
require 'active_support/core_ext/string'
-require 'active_support/core_ext/time'
+require 'active_support/time'
+require 'active_support/core_ext/kernel/reporting'
class StringInflectionsTest < Test::Unit::TestCase
include InflectorTestCases
@@ -185,17 +186,9 @@ class StringInflectionsTest < Test::Unit::TestCase
assert s.starts_with?('hel')
assert !s.starts_with?('el')
- assert s.start_with?('h')
- assert s.start_with?('hel')
- assert !s.start_with?('el')
-
assert s.ends_with?('o')
assert s.ends_with?('lo')
assert !s.ends_with?('el')
-
- assert s.end_with?('o')
- assert s.end_with?('lo')
- assert !s.end_with?('el')
end
def test_string_squish
@@ -214,17 +207,6 @@ class StringInflectionsTest < Test::Unit::TestCase
# And changes the original string:
assert_equal original, expected
end
-
- if RUBY_VERSION < '1.9'
- def test_each_char_with_utf8_string_when_kcode_is_utf8
- with_kcode('UTF8') do
- '€2.99'.each_char do |char|
- assert_not_equal 1, char.length
- break
- end
- end
- end
- end
end
class StringBehaviourTest < Test::Unit::TestCase
@@ -350,13 +332,6 @@ class TestGetTextString < Test::Unit::TestCase
end
end
-class StringBytesizeTest < Test::Unit::TestCase
- def test_bytesize
- assert_respond_to 'foo', :bytesize
- assert_equal 3, 'foo'.bytesize
- end
-end
-
class OutputSafetyTest < ActiveSupport::TestCase
def setup
@string = "hello"
diff --git a/activesupport/test/core_ext/symbol_test.rb b/activesupport/test/core_ext/symbol_test.rb
deleted file mode 100644
index 1eaccb9965..0000000000
--- a/activesupport/test/core_ext/symbol_test.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-require 'abstract_unit'
-
-class SymbolTests < Test::Unit::TestCase
- def test_to_proc
- assert_equal %w(one two three), [:one, :two, :three].map(&:to_s)
- assert_equal(%w(one two three),
- {1 => "one", 2 => "two", 3 => "three"}.sort_by(&:first).map(&:last))
- end
-end
diff --git a/activesupport/test/dependencies_test.rb b/activesupport/test/dependencies_test.rb
index 97d70cf8c4..0fcf1eaf00 100644
--- a/activesupport/test/dependencies_test.rb
+++ b/activesupport/test/dependencies_test.rb
@@ -3,7 +3,6 @@ require 'pp'
require 'active_support/dependencies'
require 'active_support/core_ext/module/loading'
require 'active_support/core_ext/kernel/reporting'
-require 'active_support/core_ext/symbol/to_proc'
module ModuleWithMissing
mattr_accessor :missing_count
diff --git a/activesupport/test/i18n_test.rb b/activesupport/test/i18n_test.rb
index 9868f1e87d..dfcd4f822d 100644
--- a/activesupport/test/i18n_test.rb
+++ b/activesupport/test/i18n_test.rb
@@ -9,8 +9,8 @@ class I18nTest < Test::Unit::TestCase
end
def test_time_zone_localization_with_default_format
- Time.zone.stubs(:now).returns Time.local(2000)
- assert_equal Time.zone.now.strftime("%a, %d %b %Y %H:%M:%S %z"), I18n.localize(Time.zone.now)
+ now = Time.local(2000)
+ assert_equal now.strftime("%a, %d %b %Y %H:%M:%S %z"), I18n.localize(now)
end
def test_date_localization_should_use_default_format
diff --git a/activesupport/test/json/decoding_test.rb b/activesupport/test/json/decoding_test.rb
index 7b5a4d0416..8fcb16abfb 100644
--- a/activesupport/test/json/decoding_test.rb
+++ b/activesupport/test/json/decoding_test.rb
@@ -1,6 +1,7 @@
# encoding: UTF-8
require 'abstract_unit'
require 'active_support/json'
+require 'active_support/time'
require 'active_support/core_ext/kernel/reporting'
class TestJSONDecoding < ActiveSupport::TestCase
diff --git a/activesupport/test/message_encryptor_test.rb b/activesupport/test/message_encryptor_test.rb
index ed3461571a..5c2b44f188 100644
--- a/activesupport/test/message_encryptor_test.rb
+++ b/activesupport/test/message_encryptor_test.rb
@@ -1,4 +1,5 @@
require 'abstract_unit'
+require 'active_support/time'
class MessageEncryptorTest < Test::Unit::TestCase
def setup
diff --git a/activesupport/test/message_verifier_test.rb b/activesupport/test/message_verifier_test.rb
index ef300e4e26..714a3b3a39 100644
--- a/activesupport/test/message_verifier_test.rb
+++ b/activesupport/test/message_verifier_test.rb
@@ -7,6 +7,8 @@ rescue LoadError, NameError
$stderr.puts "Skipping MessageVerifier test: broken OpenSSL install"
else
+require 'active_support/time'
+
class MessageVerifierTest < Test::Unit::TestCase
def setup
@verifier = ActiveSupport::MessageVerifier.new("Hey, I'm a secret!")
diff --git a/activesupport/test/multibyte_chars_test.rb b/activesupport/test/multibyte_chars_test.rb
index 4ff74abf61..0e489c10e1 100644
--- a/activesupport/test/multibyte_chars_test.rb
+++ b/activesupport/test/multibyte_chars_test.rb
@@ -228,10 +228,10 @@ class MultibyteCharsUTF8BehaviourTest < Test::Unit::TestCase
assert !@chars.include?('a')
end
- def test_include_raises_type_error_when_nil_is_passed
- assert_raise(TypeError) do
- @chars.include?(nil)
- end
+ def test_include_raises_when_nil_is_passed
+ @chars.include?(nil)
+ flunk "Expected chars.include?(nil) to raise TypeError or NoMethodError"
+ rescue Exception => e
end
def test_index_should_return_character_offset
@@ -659,4 +659,4 @@ class MultibyteInternalsTest < ActiveSupport::TestCase
"Expected byte offset #{byte_offset} to translate to #{character_offset}"
end
end
-end \ No newline at end of file
+end
diff --git a/activesupport/test/multibyte_utils_test.rb b/activesupport/test/multibyte_utils_test.rb
index 0a2f20d282..1dff944922 100644
--- a/activesupport/test/multibyte_utils_test.rb
+++ b/activesupport/test/multibyte_utils_test.rb
@@ -2,6 +2,7 @@
require 'abstract_unit'
require 'multibyte_test_helpers'
+require 'active_support/core_ext/kernel/reporting'
class MultibyteUtilsTest < ActiveSupport::TestCase
include MultibyteTestHelpers
diff --git a/activesupport/test/notifications_test.rb b/activesupport/test/notifications_test.rb
index 9175c8f26e..35d44367cf 100644
--- a/activesupport/test/notifications_test.rb
+++ b/activesupport/test/notifications_test.rb
@@ -75,7 +75,7 @@ class NotificationsMainTest < Test::Unit::TestCase
1 + 1
end
- sleep(0.1)
+ drain
assert_equal 1, @events.size
assert_equal :awesome, @events.last.name
@@ -88,19 +88,18 @@ class NotificationsMainTest < Test::Unit::TestCase
1 + 1
end
- sleep(0.1)
+ drain
assert_equal 1, @events.size
assert_equal :wot, @events.first.name
assert_equal Hash[:payload => "child"], @events.first.payload
end
- sleep(0.1)
+ drain
assert_equal 2, @events.size
assert_equal :awesome, @events.last.name
assert_equal Hash[:payload => "notifications"], @events.last.payload
- assert_in_delta 100, @events.last.duration, 70
end
def test_event_is_pushed_even_if_block_fails
@@ -108,7 +107,7 @@ class NotificationsMainTest < Test::Unit::TestCase
raise "OMG"
end rescue RuntimeError
- sleep(0.1)
+ drain
assert_equal 1, @events.size
assert_equal :awesome, @events.last.name
@@ -117,7 +116,7 @@ class NotificationsMainTest < Test::Unit::TestCase
def test_event_is_pushed_even_without_block
ActiveSupport::Notifications.instrument(:awesome, :payload => "notifications")
- sleep(0.1)
+ drain
assert_equal 1, @events.size
assert_equal :awesome, @events.last.name
@@ -137,8 +136,9 @@ class NotificationsMainTest < Test::Unit::TestCase
end
ActiveSupport::Notifications.instrument(:cache){ 1 }
- sleep 0.1
+ drain
+ assert_equal 3, @another.size
before, during, after = @another.map {|e| e.transaction_id }
assert_equal before, after
assert_not_equal before, during
@@ -153,7 +153,7 @@ class NotificationsMainTest < Test::Unit::TestCase
ActiveSupport::Notifications.instrument(:cache){ 1 }
- sleep(0.1)
+ drain
assert_equal 1, @another.size
assert_equal :cache, @another.first.name
@@ -169,7 +169,22 @@ class NotificationsMainTest < Test::Unit::TestCase
ActiveSupport::Notifications.instrument(:something){ 0 }
ActiveSupport::Notifications.instrument(:cache){ 1 }
- sleep(0.1)
+ drain
+
+ assert_equal 1, @another.size
+ assert_equal :cache, @another.first.name
+ assert_equal 1, @another.first.result
+ end
+
+ def test_subscriber_allows_sync_listeners
+ @another = []
+ ActiveSupport::Notifications.subscribe(/cache/, :with => ActiveSupport::Notifications::SyncListener) do |*args|
+ @another << ActiveSupport::Notifications::Event.new(*args)
+ end
+
+ Thread.expects(:new).never
+ ActiveSupport::Notifications.instrument(:something){ 0 }
+ ActiveSupport::Notifications.instrument(:cache){ 1 }
assert_equal 1, @another.size
assert_equal :cache, @another.first.name
@@ -186,7 +201,7 @@ class NotificationsMainTest < Test::Unit::TestCase
ActiveSupport::Notifications.instrument(:value){ i }
end
- sleep 0.1
+ drain
assert_equal 100, @events.size
assert_equal :value, @events.first.name
@@ -198,4 +213,9 @@ class NotificationsMainTest < Test::Unit::TestCase
assert_equal 1, @another.first.result
assert_equal 100, @another.last.result
end
+
+ private
+ def drain
+ sleep(0.05) until ActiveSupport::Notifications.queue.drained?
+ end
end
diff --git a/activesupport/test/whiny_nil_test.rb b/activesupport/test/whiny_nil_test.rb
index 4cb22c41b2..009d97940f 100644
--- a/activesupport/test/whiny_nil_test.rb
+++ b/activesupport/test/whiny_nil_test.rb
@@ -13,7 +13,7 @@ class WhinyNilTest < Test::Unit::TestCase
def test_unchanged
nil.method_thats_not_in_whiners
rescue NoMethodError => nme
- assert_match(/nil.method_thats_not_in_whiners/, nme.message)
+ assert(nme.message =~ /nil:NilClass/)
end
def test_active_record
@@ -35,4 +35,16 @@ class WhinyNilTest < Test::Unit::TestCase
rescue RuntimeError => nme
assert(!(nme.message =~ /nil:NilClass/))
end
+
+ def test_no_to_ary_coercion
+ nil.to_ary
+ rescue NoMethodError => nme
+ assert(nme.message =~ /nil:NilClass/)
+ end
+
+ def test_no_to_str_coercion
+ nil.to_str
+ rescue NoMethodError => nme
+ assert(nme.message =~ /nil:NilClass/)
+ end
end
diff --git a/arel b/arel
new file mode 160000
+Subproject 0faeb5047407348533db952d9cf93ea59d2526d
diff --git a/ci/ci_build.rb b/ci/ci_build.rb
index 0ee952c00b..7ae660fb7d 100755
--- a/ci/ci_build.rb
+++ b/ci/ci_build.rb
@@ -1,12 +1,18 @@
#!/usr/bin/env ruby
require 'fileutils'
-
include FileUtils
-puts "[CruiseControl] Rails build"
+def root_dir
+ @root_dir ||= File.expand_path('../..', __FILE__)
+end
+
+def rake(*tasks)
+ tasks.each { |task| return false unless system("#{root_dir}/bin/rake", task) }
+ true
+end
+puts "[CruiseControl] Rails build"
build_results = {}
-root_dir = File.expand_path('../..', __FILE__)
# Requires gem home and path to be writeable and/or overridden to be ~/.gem,
# Will enable when RubyGems supports this properly (in a coming release)
@@ -20,44 +26,44 @@ cd root_dir do
puts
puts "[CruiseControl] Bundling RubyGems"
puts
- build_results[:bundle] = system 'rm -rf vendor && gem bundle --update'
+ build_results[:bundle] = system 'rm -rf vendor && env CI=1 gem bundle --update && chmod 755 bin vendor vendor/gems'
end
cd "#{root_dir}/activesupport" do
puts
puts "[CruiseControl] Building ActiveSupport"
puts
- build_results[:activesupport] = system 'rake'
- build_results[:activesupport_isolated] = system 'rake test:isolated'
+ build_results[:activesupport] = rake 'test'
+ build_results[:activesupport_isolated] = rake 'test:isolated'
end
-rm_f "#{root_dir}/activerecord/debug.log"
-cd "#{root_dir}/activerecord" do
+cd "#{root_dir}/railties" do
puts
- puts "[CruiseControl] Building ActiveRecord with MySQL"
+ puts "[CruiseControl] Building RailTies"
puts
- build_results[:activerecord_mysql] = system 'rake mysql:rebuild_databases && rake test_mysql'
+ build_results[:railties] = rake 'test'
end
-cd "#{root_dir}/activerecord" do
+cd "#{root_dir}/actionpack" do
puts
- puts "[CruiseControl] Building ActiveRecord with PostgreSQL"
+ puts "[CruiseControl] Building ActionPack"
puts
- build_results[:activerecord_postgresql8] = system 'rake postgresql:rebuild_databases && rake test_postgresql'
+ build_results[:actionpack] = rake 'test'
+ build_results[:actionpack_isolated] = rake 'test:isolated'
end
-cd "#{root_dir}/activerecord" do
+cd "#{root_dir}/actionmailer" do
puts
- puts "[CruiseControl] Building ActiveRecord with SQLite 3"
+ puts "[CruiseControl] Building ActionMailer"
puts
- build_results[:activerecord_sqlite3] = system 'rake test_sqlite3'
+ build_results[:actionmailer] = rake 'test'
end
cd "#{root_dir}/activemodel" do
puts
puts "[CruiseControl] Building ActiveModel"
puts
- build_results[:activemodel] = system 'rake'
+ build_results[:activemodel] = rake 'test'
end
rm_f "#{root_dir}/activeresource/debug.log"
@@ -65,29 +71,29 @@ cd "#{root_dir}/activeresource" do
puts
puts "[CruiseControl] Building ActiveResource"
puts
- build_results[:activeresource] = system 'rake'
+ build_results[:activeresource] = rake 'test'
end
-cd "#{root_dir}/actionpack" do
+rm_f "#{root_dir}/activerecord/debug.log"
+cd "#{root_dir}/activerecord" do
puts
- puts "[CruiseControl] Building ActionPack"
+ puts "[CruiseControl] Building ActiveRecord with MySQL"
puts
- build_results[:actionpack] = system 'rake'
- build_results[:actionpack_isolated] = system 'rake test:isolated'
+ build_results[:activerecord_mysql] = rake 'mysql:rebuild_databases', 'test_mysql'
end
-cd "#{root_dir}/actionmailer" do
+cd "#{root_dir}/activerecord" do
puts
- puts "[CruiseControl] Building ActionMailer"
+ puts "[CruiseControl] Building ActiveRecord with PostgreSQL"
puts
- build_results[:actionmailer] = system 'rake'
+ build_results[:activerecord_postgresql8] = rake 'postgresql:rebuild_databases', 'test_postgresql'
end
-cd "#{root_dir}/railties" do
+cd "#{root_dir}/activerecord" do
puts
- puts "[CruiseControl] Building RailTies"
+ puts "[CruiseControl] Building ActiveRecord with SQLite 3"
puts
- build_results[:railties] = system 'rake'
+ build_results[:activerecord_sqlite3] = rake 'test_sqlite3'
end
@@ -100,6 +106,8 @@ puts "[CruiseControl] #{`mysql --version`}"
puts "[CruiseControl] #{`pg_config --version`}"
puts "[CruiseControl] SQLite3: #{`sqlite3 -version`}"
`gem env`.each_line {|line| print "[CruiseControl] #{line}"}
+puts "[CruiseControl] Bundled gems:"
+`gem bundle --list`.each_line {|line| print "[CruiseControl] #{line}"}
puts "[CruiseControl] Local gems:"
`gem list`.each_line {|line| print "[CruiseControl] #{line}"}
diff --git a/ci/geminstaller.yml b/ci/geminstaller.yml
index a38221884b..776ae8d98d 100644
--- a/ci/geminstaller.yml
+++ b/ci/geminstaller.yml
@@ -1,31 +1,8 @@
---
gems:
-- name: erubis
- version: >= 2.6.5
- name: geminstaller
version: >= 0.4.3
-- name: fcgi
- version: >= 0.8.7
-- name: memcache-client
- version: >= 1.5.0
-- name: mocha
- version: >= 0.9.7
-- name: mysql
- #version: >= 2.7
- version: = 2.7
-- name: nokogiri
- version: >= 1.3.3
-- name: pg
- version: >= 0.8.0
-- name: rack
- version: '~> 1.0.0'
-- name: rack-test
- version: >= 0.5.0
-- name: rake
- version: >= 0.8.1
-- name: sqlite3-ruby
- version: >= 1.2.2
- name: rubygems-update
- version: >= 1.3.3
+ version: >= 1.3.5
- name: bundler
version: >= 0.6.0
diff --git a/rack-mount b/rack-mount
new file mode 160000
+Subproject 3784e633b42f43a4131e02519be60080d179da2
diff --git a/railties/CHANGELOG b/railties/CHANGELOG
index d6311f77a0..66e0d5e9c5 100644
--- a/railties/CHANGELOG
+++ b/railties/CHANGELOG
@@ -1,5 +1,7 @@
*Edge*
+* Fixed that the debugger wouldn't go into IRB mode because of left-over ARGVs [DHH]
+
* I18n support for plugins. #2325 [Antonio Tapiador, Sven Fuchs]
* Ruby 1.9: use UTF-8 for default internal and external encodings. [Jeremy Kemper]
diff --git a/railties/Rakefile b/railties/Rakefile
index 3a87a88ddc..e6f698fc74 100644
--- a/railties/Rakefile
+++ b/railties/Rakefile
@@ -6,12 +6,8 @@ require 'rake/gempackagetask'
require 'date'
require 'rbconfig'
-begin
- require File.expand_path('../../vendor/gems/environment', __FILE__)
-rescue LoadError
-end
$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/lib"
-require 'rails'
+require 'rails/version'
PKG_BUILD = ENV['PKG_BUILD'] ? '.' + ENV['PKG_BUILD'] : ''
PKG_NAME = ENV['PKG_NAME'] || 'rails'
@@ -26,21 +22,23 @@ RUBY_FORGE_USER = "webster132"
task :default => :test
+task :test => 'test:isolated'
## This is required until the regular test task
## below passes. It's not ideal, but at least
## we can see the failures
-task :test do
- dir = ENV["TEST_DIR"] || "**"
- Dir["test/#{dir}/*_test.rb"].all? do |file|
- next true if file.include?("fixtures")
- ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME'))
- system(ruby, '-Itest', "-I#{File.dirname(__FILE__)}/../activesupport/lib", file)
- end or raise "Failures"
-end
-task :isolated_test => :test
-
-Rake::TestTask.new("regular_test") do |t|
+namespace :test do
+ task :isolated do
+ dir = ENV["TEST_DIR"] || "**"
+ Dir["test/#{dir}/*_test.rb"].all? do |file|
+ next true if file.include?("fixtures")
+ ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME'))
+ system(ruby, '-Itest', "-I#{File.dirname(__FILE__)}/../activesupport/lib", file)
+ end or raise "Failures"
+ end
+end
+
+Rake::TestTask.new('test:regular') do |t|
t.libs << 'test' << "#{File.dirname(__FILE__)}/../activesupport/lib"
t.pattern = 'test/**/*_test.rb'
t.warning = true
@@ -152,7 +150,7 @@ end
# Publishing -------------------------------------------------------
desc "Publish the rails gem"
-task :pgem => [:gem] do
+task :pgem => [:gem] do
require 'rake/contrib/sshpublisher'
Rake::SshFilePublisher.new("gems.rubyonrails.org", "/u/sites/gems/gems", "pkg", "#{PKG_FILE_NAME}.gem").upload
`ssh gems.rubyonrails.org '/u/sites/gems/gemupdate.sh'`
diff --git a/railties/lib/rails.rb b/railties/lib/rails.rb
index 43ece14a49..c23b67e321 100644
--- a/railties/lib/rails.rb
+++ b/railties/lib/rails.rb
@@ -1 +1,13 @@
+require "pathname"
+
+require 'rails/initializable'
+require 'rails/application'
+require 'rails/railties_path'
+require 'rails/version'
+require 'rails/rack'
+require 'rails/paths'
+require 'rails/core'
+require 'rails/configuration'
+require 'rails/deprecation'
require 'rails/initializer'
+require 'rails/plugin' \ No newline at end of file
diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb
index b43dcb0041..7c2d8eab67 100644
--- a/railties/lib/rails/application.rb
+++ b/railties/lib/rails/application.rb
@@ -3,6 +3,11 @@ module Rails
include Initializable
class << self
+ def inherited(klass)
+ Rails.application ||= klass unless klass.name =~ /Rails/
+ super
+ end
+
# Stub out App initialize
def initialize!
new
@@ -23,10 +28,6 @@ module Rails
@config = config
end
- def plugin_loader
- @plugin_loader ||= config.plugin_loader.new(self)
- end
-
def root
config.root
end
@@ -37,7 +38,7 @@ module Rails
end
def initialize
- run_initializers
+ run_initializers(self)
end
def config
@@ -46,10 +47,6 @@ module Rails
alias configuration config
- def plugin_loader
- self.class.plugin_loader
- end
-
def middleware
config.middleware
end
@@ -58,6 +55,18 @@ module Rails
ActionController::Routing::Routes
end
+ def initializers
+ initializers = super
+ plugins.each { |p| initializers += p.initializers }
+ initializers
+ end
+
+ def plugins
+ @plugins ||= begin
+ Plugin::Vendored.all(config.plugins || [:all], config.paths.vendor.plugins)
+ end
+ end
+
def call(env)
@app ||= middleware.build(routes)
@app.call(env)
@@ -111,13 +120,6 @@ module Rails
config.load_once_paths.freeze
end
- # Adds all load paths from plugins to the global set of load paths, so that
- # code from plugins can be required (explicitly or automatically via ActiveSupport::Dependencies).
- initializer :add_plugin_load_paths do
- require 'active_support/dependencies'
- plugin_loader.add_plugin_load_paths
- end
-
# Create tmp directories
initializer :ensure_tmp_directories_exist do
%w(cache pids sessions sockets).each do |dir_to_make|
@@ -321,7 +323,6 @@ module Rails
# TODO: Make Rails and metal work without ActionController
if config.frameworks.include?(:action_controller)
Rails::Rack::Metal.requested_metals = config.metals
- Rails::Rack::Metal.metal_paths += plugin_loader.engine_metal_paths
config.middleware.insert_before(
:"ActionDispatch::ParamsParser",
@@ -329,26 +330,6 @@ module Rails
end
end
- # Loads all plugins in <tt>config.plugin_paths</tt>. <tt>plugin_paths</tt>
- # defaults to <tt>vendor/plugins</tt> but may also be set to a list of
- # paths, such as
- # config.plugin_paths = ["#{config.root}/lib/plugins", "#{config.root}/vendor/plugins"]
- #
- # In the default implementation, as each plugin discovered in <tt>plugin_paths</tt> is initialized:
- # * its +lib+ directory, if present, is added to the load path (immediately after the applications lib directory)
- # * <tt>init.rb</tt> is evaluated, if present
- #
- # After all plugins are loaded, duplicates are removed from the load path.
- # If an array of plugin names is specified in config.plugins, only those plugins will be loaded
- # and they plugins will be loaded in that order. Otherwise, plugins are loaded in alphabetical
- # order.
- #
- # if config.plugins ends contains :all then the named plugins will be loaded in the given order and all other
- # plugins will be loaded in alphabetical order
- initializer :load_plugins do
- plugin_loader.load_plugins
- end
-
# # bail out if gems are missing - note that check_gem_dependencies will have
# # already called abort() unless $gems_rake_task is set
# return unless gems_dependencies_loaded
diff --git a/railties/lib/rails/commands/console.rb b/railties/lib/rails/commands/console.rb
index b977b7162f..fc22ad64a9 100644
--- a/railties/lib/rails/commands/console.rb
+++ b/railties/lib/rails/commands/console.rb
@@ -1,45 +1,52 @@
-irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
-
require 'optparse'
+require 'irb'
+require "irb/completion"
-options = { :sandbox => false, :irb => irb }
-OptionParser.new do |opt|
- opt.banner = "Usage: console [environment] [options]"
- opt.on('-s', '--sandbox', 'Rollback database modifications on exit.') { |v| options[:sandbox] = v }
- opt.on("--irb=[#{irb}]", 'Invoke a different irb.') { |v| options[:irb] = v }
- opt.on("--debugger", 'Enable ruby-debugging for the console.') { |v| options[:debugger] = v }
- opt.parse!(ARGV)
-end
+module Rails
+ class Console
+ ENVIRONMENTS = %w(production development test)
-libs = " -r irb/completion"
-libs << %( -r "#{Rails.root}/config/environment")
-libs << " -r rails/console_app"
-libs << " -r rails/console_sandbox" if options[:sandbox]
-libs << " -r rails/console_with_helpers"
-
-if options[:debugger]
- begin
- require 'ruby-debug'
- libs << " -r ruby-debug"
- puts "=> Debugger enabled"
- rescue Exception
- puts "You need to install ruby-debug to run the console in debugging mode. With gems, use 'gem install ruby-debug'"
- exit
- end
-end
+ def self.start
+ new.start
+ end
-ENV['RAILS_ENV'] = case ARGV.first
- when "p"; "production"
- when "d"; "development"
- when "t"; "test"
- else
- ARGV.first || ENV['RAILS_ENV'] || 'development'
-end
+ def start
+ options = {}
-if options[:sandbox]
- 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})"
+ OptionParser.new do |opt|
+ opt.banner = "Usage: console [environment] [options]"
+ opt.on('-s', '--sandbox', 'Rollback database modifications on exit.') { |v| options[:sandbox] = v }
+ opt.on("--debugger", 'Enable ruby-debugging for the console.') { |v| options[:debugger] = v }
+ opt.on('--irb') { |v| abort '--irb option is no longer supported. Invoke `/your/choice/of/ruby script/console` instead' }
+ opt.parse!(ARGV)
+ end
+
+ if env = ARGV.first
+ ENV['RAILS_ENV'] = ENVIRONMENTS.find { |e| e.index(env) } || env
+ end
+
+ require "#{Rails.root}/config/environment"
+ require "rails/console_app"
+ require "rails/console_sandbox" if options[:sandbox]
+ require "rails/console_with_helpers"
+
+ if options[:debugger]
+ begin
+ require 'ruby-debug'
+ puts "=> Debugger enabled"
+ rescue Exception
+ puts "You need to install ruby-debug to run the console in debugging mode. With gems, use 'gem install ruby-debug'"
+ exit
+ end
+ end
+
+ if options[:sandbox]
+ 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})"
+ end
+ IRB.start
+ end
+ end
end
-exec "#{options[:irb]} #{libs} --simple-prompt"
diff --git a/railties/lib/rails/commands/destroy.rb b/railties/lib/rails/commands/destroy.rb
index 15ff90f78a..f85c17bb94 100644
--- a/railties/lib/rails/commands/destroy.rb
+++ b/railties/lib/rails/commands/destroy.rb
@@ -1,3 +1,6 @@
+require 'rails/generators'
+Rails::Generators.configure!
+
if ARGV.size == 0
Rails::Generators.help
exit
diff --git a/railties/lib/rails/commands/generate.rb b/railties/lib/rails/commands/generate.rb
index 82a658e2ed..c5e3ae3529 100755
--- a/railties/lib/rails/commands/generate.rb
+++ b/railties/lib/rails/commands/generate.rb
@@ -1,3 +1,6 @@
+require 'rails/generators'
+Rails::Generators.configure!
+
if ARGV.size == 0
Rails::Generators.help
exit
diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb
index 29359e49a4..ff2282a534 100644
--- a/railties/lib/rails/commands/server.rb
+++ b/railties/lib/rails/commands/server.rb
@@ -1,73 +1,75 @@
-require 'action_controller'
-
require 'fileutils'
require 'optparse'
+require 'action_dispatch'
-options = {
- :Port => 3000,
- :Host => "0.0.0.0",
- :environment => (ENV['RAILS_ENV'] || "development").dup,
- :config => "#{Rails.root}/config.ru",
- :detach => false,
- :debugger => false
-}
+module Rails
+ class Server < ::Rack::Server
+ class Options
+ def parse!(args)
+ options = {}
+ args = args.dup
+ opt_parser = OptionParser.new do |opts|
+ opts.on("-p", "--port=port", Integer,
+ "Runs Rails on the specified port.", "Default: #{options[:Port]}") { |v| options[:Port] = v }
+ opts.on("-b", "--binding=ip", String,
+ "Binds Rails to the specified ip.", "Default: #{options[:Host]}") { |v| options[:Host] = v }
+ opts.on("-c", "--config=file", String,
+ "Use custom rackup configuration file") { |v| options[:config] = v }
+ opts.on("-d", "--daemon", "Make server run as a Daemon.") { options[:daemonize] = true }
+ opts.on("-u", "--debugger", "Enable ruby-debugging for the server.") { options[:debugger] = true }
+ opts.on("-e", "--environment=name", String,
+ "Specifies the environment to run this server under (test/development/production).",
+ "Default: #{options[:environment]}") { |v| options[:environment] = v }
-ARGV.clone.options do |opts|
- opts.on("-p", "--port=port", Integer,
- "Runs Rails on the specified port.", "Default: #{options[:Port]}") { |v| options[:Port] = v }
- opts.on("-b", "--binding=ip", String,
- "Binds Rails to the specified ip.", "Default: #{options[:Host]}") { |v| options[:Host] = v }
- opts.on("-c", "--config=file", String,
- "Use custom rackup configuration file") { |v| options[:config] = v }
- opts.on("-d", "--daemon", "Make server run as a Daemon.") { options[:detach] = true }
- opts.on("-u", "--debugger", "Enable ruby-debugging for the server.") { options[:debugger] = true }
- opts.on("-e", "--environment=name", String,
- "Specifies the environment to run this server under (test/development/production).",
- "Default: #{options[:environment]}") { |v| options[:environment] = v }
+ opts.separator ""
- opts.separator ""
+ opts.on("-h", "--help", "Show this help message.") { puts opts; exit }
+ end
- opts.on("-h", "--help", "Show this help message.") { puts opts; exit }
+ opt_parser.parse! args
- opts.parse!
-end
+ options[:server] = args.shift
+ options
+ end
+ end
-server = Rack::Handler.get(ARGV.first) rescue nil
-unless server
- begin
- server = Rack::Handler::Mongrel
- rescue LoadError => e
- server = Rack::Handler::WEBrick
- end
-end
+ def opt_parser
+ Options.new
+ end
-puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}"
-puts "=> Rails #{Rails.version} application starting on http://#{options[:Host]}:#{options[:Port]}}"
+ def start
+ puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}"
+ puts "=> Rails #{Rails.version} application starting on http://#{options[:Host]}:#{options[:Port]}"
+ puts "=> Call with -d to detach" unless options[:daemonize]
+ trap(:INT) { exit }
+ puts "=> Ctrl-C to shutdown server" unless options[:daemonize]
-if options[:detach]
- Process.daemon
- pid = "#{Rails.root}/tmp/pids/server.pid"
- File.open(pid, 'w'){ |f| f.write(Process.pid) }
- at_exit { File.delete(pid) if File.exist?(pid) }
-end
+ ENV["RAILS_ENV"] = options[:environment]
+ RAILS_ENV.replace(options[:environment]) if defined?(RAILS_ENV)
-ENV["RAILS_ENV"] = options[:environment]
-RAILS_ENV.replace(options[:environment]) if defined?(RAILS_ENV)
+ super
+ ensure
+ puts 'Exiting' unless options[:daemonize]
+ end
-app = Rack::Builder.new {
- use Rails::Rack::LogTailer unless options[:detach]
- use Rails::Rack::Debugger if options[:debugger]
- run ActionDispatch::Utils.parse_config(options[:config])
-}.to_app
+ def middleware
+ middlewares = []
+ middlewares << [Rails::Rack::LogTailer] unless options[:daemonize]
+ middlewares << [Rails::Rack::Debugger] if options[:debugger]
+ Hash.new(middlewares)
+ end
-puts "=> Call with -d to detach"
-
-trap(:INT) { exit }
-
-puts "=> Ctrl-C to shutdown server"
-
-begin
- server.run(app, options.merge(:AccessLog => []))
-ensure
- puts 'Exiting'
+ def default_options
+ {
+ :Port => 3000,
+ :Host => "0.0.0.0",
+ :environment => (ENV['RAILS_ENV'] || "development").dup,
+ :rack_file => "#{Rails.root}/config.ru",
+ :daemonize => false,
+ :debugger => false,
+ :pid => "#{Rails.root}/tmp/pids/server.pid",
+ :AccessLog => []
+ }
+ end
+ end
end
diff --git a/railties/lib/rails/configuration.rb b/railties/lib/rails/configuration.rb
index 2b847ba711..3f43a48e2e 100644
--- a/railties/lib/rails/configuration.rb
+++ b/railties/lib/rails/configuration.rb
@@ -1,17 +1,13 @@
-require 'rails/plugin/loader'
-require 'rails/plugin/locator'
require 'active_support/ordered_options'
module Rails
class Configuration
- attr_accessor :cache_classes, :load_paths,
- :load_once_paths, :after_initialize_blocks,
- :frameworks, :framework_root_path, :root, :plugin_paths, :plugins,
- :plugin_loader, :plugin_locators, :gems, :loaded_plugins, :reload_plugins,
+ attr_accessor :cache_classes, :load_paths, :load_once_paths, :after_initialize_blocks,
+ :frameworks, :framework_root_path, :root, :gems, :plugins,
:i18n, :gems, :whiny_nils, :consider_all_requests_local,
:action_controller, :active_record, :action_view, :active_support,
:action_mailer, :active_resource,
- :log_path, :log_level, :logger, :preload_frameworks,
+ :reload_plugins, :log_path, :log_level, :logger, :preload_frameworks,
:database_configuration_file, :cache_store, :time_zone,
:view_path, :metals, :controller_paths, :routes_configuration_file,
:eager_load_paths, :dependency_loading, :paths, :serve_static_assets
@@ -19,7 +15,6 @@ module Rails
def initialize
@load_once_paths = []
@after_initialize_blocks = []
- @loaded_plugins = []
@dependency_loading = true
@serve_static_assets = true
@@ -36,7 +31,7 @@ module Rails
def root
@root ||= begin
call_stack = caller.map { |p| p.split(':').first }
- root_path = call_stack.detect { |p| p !~ %r[railties/lib/rails] }
+ root_path = call_stack.detect { |p| p !~ %r[railties/lib/rails|rack/lib/rack] }
root_path = File.dirname(root_path)
while root_path && File.directory?(root_path) && !File.exist?("#{root_path}/config.ru")
@@ -199,24 +194,6 @@ module Rails
@frameworks ||= [ :active_record, :action_controller, :action_view, :action_mailer, :active_resource ]
end
- def plugin_paths
- @plugin_paths ||= ["#{root}/vendor/plugins"]
- end
-
- def plugin_loader
- @plugin_loader ||= begin
- Plugin::Loader
- end
- end
-
- def plugin_locators
- @plugin_locators ||= begin
- locators = []
- locators << Plugin::GemLocator if defined? Gem
- locators << Plugin::FileSystemLocator
- end
- end
-
def i18n
@i18n ||= begin
i18n = ActiveSupport::OrderedOptions.new
@@ -235,10 +212,6 @@ module Rails
"#{root}/config/environments/#{RAILS_ENV}.rb"
end
- def reload_plugins?
- @reload_plugins
- end
-
# Holds generators configuration:
#
# config.generators do |g|
diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb
index fa2c11795b..85c2fd52a4 100644
--- a/railties/lib/rails/generators.rb
+++ b/railties/lib/rails/generators.rb
@@ -9,7 +9,7 @@ require 'active_support/core_ext/module/attribute_accessors'
require 'active_support/core_ext/string/inflections'
# TODO: Do not always push on vendored thor
-$LOAD_PATH.unshift("#{File.dirname(__FILE__)}/vendor/thor-0.11.8/lib")
+$LOAD_PATH.unshift("#{File.dirname(__FILE__)}/vendor/thor-0.12.0/lib")
require 'rails/generators/base'
require 'rails/generators/named_base'
@@ -86,28 +86,16 @@ module Rails
@options ||= DEFAULT_OPTIONS.dup
end
- # We have two scenarios here: when rubygems is loaded and when bundler is
- # being used. If rubygems is loaded, we get all generators paths from loaded
- # specs. Otherwise we just have to look into vendor/gems/gems.
- #
- def self.gems_generators_paths
- paths = []
-
- if defined?(Gem) && Gem.respond_to?(:loaded_specs)
- Gem.loaded_specs.each do |name, spec|
- generator_path = File.join(spec.full_gem_path, "lib/generators")
- paths << generator_path if File.exist?(generator_path)
- end
+ def self.gems_generators_paths #:nodoc:
+ return [] unless defined?(Gem) && Gem.respond_to?(:loaded_specs)
+ Gem.loaded_specs.inject([]) do |paths, (name, spec)|
+ paths += Dir[File.join(spec.full_gem_path, "lib/{generators,rails_generators}")]
end
-
- paths
end
- # Load paths from plugin.
- #
- def self.plugins_generators_paths
+ def self.plugins_generators_paths #:nodoc:
return [] unless Rails.root
- Dir[File.join(Rails.root, "vendor", "plugins", "*", "lib", "generators")]
+ Dir[File.join(Rails.root, "vendor", "plugins", "*", "lib", "{generators,rails_generators}")]
end
# Hold configured generators fallbacks. If a plugin developer wants a
@@ -147,8 +135,8 @@ module Rails
def self.load_paths
@load_paths ||= begin
paths = []
- paths << File.join(Rails.root, "lib", "generators") if Rails.root
- paths << File.join(Thor::Util.user_home, ".rails", "generators")
+ paths += Dir[File.join(Rails.root, "lib", "{generators,rails_generators}")] if Rails.root
+ paths += Dir[File.join(Thor::Util.user_home, ".rails", "{generators,rails_generators}")]
paths += self.plugins_generators_paths
paths += self.gems_generators_paths
paths << File.expand_path(File.join(File.dirname(__FILE__), "generators"))
@@ -210,7 +198,7 @@ module Rails
return klass if klass
end
- invoke_fallbacks_for(name, base)
+ invoke_fallbacks_for(name, base) || invoke_fallbacks_for(context, name)
end
# Receives a namespace, arguments and the behavior to invoke the generator.
@@ -278,13 +266,13 @@ module Rails
# By default, Rails strips the generator namespace to make invocations
# easier. This method generaters the both possibilities names.
- def self.generator_names(first, second)
+ def self.generator_names(first, second) #:nodoc:
[ "#{first}:generators:#{second}", "#{first}:#{second}" ]
end
# Try callbacks for the given base.
#
- def self.invoke_fallbacks_for(name, base)
+ def self.invoke_fallbacks_for(name, base) #:nodoc:
return nil unless base && fallbacks[base.to_sym]
invoked_fallbacks = []
diff --git a/railties/lib/rails/generators/base.rb b/railties/lib/rails/generators/base.rb
index af1bf26f4a..226ae63963 100644
--- a/railties/lib/rails/generators/base.rb
+++ b/railties/lib/rails/generators/base.rb
@@ -25,8 +25,11 @@ module Rails
# Automatically sets the source root based on the class name.
#
def self.source_root
- @_rails_source_root ||= File.expand_path(File.join(File.dirname(__FILE__),
- base_name, generator_name, 'templates'))
+ @_rails_source_root ||= begin
+ if base_name && generator_name
+ File.expand_path(File.join(File.dirname(__FILE__), base_name, generator_name, 'templates'))
+ end
+ end
end
# Tries to get the description from a USAGE file one folder above the source
@@ -212,7 +215,11 @@ module Rails
def self.inherited(base) #:nodoc:
super
- if base.name && base.name !~ /Base$/ && defined?(Rails.root) && Rails.root
+ # Cache source root, we need to do this, since __FILE__ is a relative value
+ # and can point to wrong directions when inside an specified directory.
+ base.source_root
+
+ if base.name && base.name !~ /Base$/ && base.base_name && base.generator_name && defined?(Rails.root) && Rails.root
path = File.expand_path(File.join(Rails.root, 'lib', 'templates'))
if base.name.include?('::')
base.source_paths << File.join(path, base.base_name, base.generator_name)
@@ -272,8 +279,10 @@ module Rails
# Sets the base_name taking into account the current class namespace.
#
def self.base_name
- if name
- @base_name ||= name.split('::').first.underscore
+ @base_name ||= begin
+ if base = name.to_s.split('::').first
+ base.underscore
+ end
end
end
@@ -283,9 +292,10 @@ module Rails
def self.generator_name
if name
@generator_name ||= begin
- klass_name = name.to_s.split('::').last
- klass_name.sub!(/Generator$/, '')
- klass_name.underscore
+ if klass_name = name.to_s.split('::').last
+ klass_name.sub!(/Generator$/, '')
+ klass_name.underscore
+ end
end
end
end
@@ -294,35 +304,27 @@ module Rails
# Rails::Generators.options.
#
def self.default_value_for_option(name, options)
- config = Rails::Generators.options
- generator, base = generator_name.to_sym, base_name.to_sym
-
- if config[generator] && config[generator].key?(name)
- config[generator][name]
- elsif config[base] && config[base].key?(name)
- config[base][name]
- elsif config[:rails].key?(name)
- config[:rails][name]
- else
- options[:default]
- end
+ default_for_option(Rails::Generators.options, name, options, options[:default])
end
# Return default aliases for the option name given doing a lookup in
# Rails::Generators.aliases.
#
def self.default_aliases_for_option(name, options)
- config = Rails::Generators.aliases
- generator, base = generator_name.to_sym, base_name.to_sym
+ default_for_option(Rails::Generators.aliases, name, options, options[:aliases])
+ end
- if config[generator] && config[generator].key?(name)
- config[generator][name]
- elsif config[base] && config[base].key?(name)
- config[base][name]
+ # Return default for the option name given doing a lookup in config.
+ #
+ def self.default_for_option(config, name, options, default)
+ if generator_name and c = config[generator_name.to_sym] and c.key?(name)
+ c[name]
+ elsif base_name and c = config[base_name.to_sym] and c.key?(name)
+ c[name]
elsif config[:rails].key?(name)
config[:rails][name]
else
- options[:aliases]
+ default
end
end
diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb
index e552cc4520..2bcea4bc8f 100644
--- a/railties/lib/rails/generators/rails/app/app_generator.rb
+++ b/railties/lib/rails/generators/rails/app/app_generator.rb
@@ -123,8 +123,10 @@ module Rails::Generators
end
def create_script_files
- directory "script"
- chmod "script", 0755, :verbose => false
+ directory "script" do |file|
+ prepend_file file, "#{shebang}\n", :verbose => false
+ chmod file, 0755, :verbose => false
+ end
end
def create_test_files
diff --git a/railties/lib/rails/generators/rails/app/templates/script/about.tt b/railties/lib/rails/generators/rails/app/templates/script/about
index 7639d4040f..93fd007649 100755
--- a/railties/lib/rails/generators/rails/app/templates/script/about.tt
+++ b/railties/lib/rails/generators/rails/app/templates/script/about
@@ -1,4 +1,3 @@
-<%= shebang %>
require File.expand_path('../../config/environment', __FILE__)
$LOAD_PATH.unshift "#{RAILTIES_PATH}/builtin/rails_info"
require 'rails/commands/about'
diff --git a/railties/lib/rails/generators/rails/app/templates/script/console.tt b/railties/lib/rails/generators/rails/app/templates/script/console
index 1cd2eb8b53..6043f3792b 100755
--- a/railties/lib/rails/generators/rails/app/templates/script/console.tt
+++ b/railties/lib/rails/generators/rails/app/templates/script/console
@@ -1,3 +1,3 @@
-<%= shebang %>
require File.expand_path('../../config/application', __FILE__)
require 'rails/commands/console'
+Rails::Console.start
diff --git a/railties/lib/rails/generators/rails/app/templates/script/dbconsole.tt b/railties/lib/rails/generators/rails/app/templates/script/dbconsole
index 94beb13715..e6a1c59394 100755
--- a/railties/lib/rails/generators/rails/app/templates/script/dbconsole.tt
+++ b/railties/lib/rails/generators/rails/app/templates/script/dbconsole
@@ -1,3 +1,2 @@
-<%= shebang %>
require File.expand_path('../../config/application', __FILE__)
require 'rails/commands/dbconsole'
diff --git a/railties/lib/rails/generators/rails/app/templates/script/destroy.tt b/railties/lib/rails/generators/rails/app/templates/script/destroy
index 6adc90b2c3..adfa8e8426 100755
--- a/railties/lib/rails/generators/rails/app/templates/script/destroy.tt
+++ b/railties/lib/rails/generators/rails/app/templates/script/destroy
@@ -1,5 +1,2 @@
-<%= shebang %>
require File.expand_path('../../config/environment', __FILE__)
-require 'rails/generators'
-Rails::Generators.configure!
require 'rails/commands/destroy'
diff --git a/railties/lib/rails/generators/rails/app/templates/script/generate.tt b/railties/lib/rails/generators/rails/app/templates/script/generate
index 71d47dec92..6fb8ad0395 100755
--- a/railties/lib/rails/generators/rails/app/templates/script/generate.tt
+++ b/railties/lib/rails/generators/rails/app/templates/script/generate
@@ -1,5 +1,2 @@
-<%= shebang %>
require File.expand_path('../../config/environment', __FILE__)
-require 'rails/generators'
-Rails::Generators.configure!
require 'rails/commands/generate'
diff --git a/railties/lib/rails/generators/rails/app/templates/script/performance/benchmarker.tt b/railties/lib/rails/generators/rails/app/templates/script/performance/benchmarker
index 9ebc4c92fc..9647d8f10a 100755
--- a/railties/lib/rails/generators/rails/app/templates/script/performance/benchmarker.tt
+++ b/railties/lib/rails/generators/rails/app/templates/script/performance/benchmarker
@@ -1,3 +1,2 @@
-<%= shebang %>
require File.expand_path('../../../config/environment', __FILE__)
require 'rails/commands/performance/benchmarker'
diff --git a/railties/lib/rails/generators/rails/app/templates/script/performance/profiler.tt b/railties/lib/rails/generators/rails/app/templates/script/performance/profiler
index 5f4c763f9d..a5822042d2 100755
--- a/railties/lib/rails/generators/rails/app/templates/script/performance/profiler.tt
+++ b/railties/lib/rails/generators/rails/app/templates/script/performance/profiler
@@ -1,3 +1,2 @@
-<%= shebang %>
require File.expand_path('../../../config/environment', __FILE__)
require 'rails/commands/performance/profiler'
diff --git a/railties/lib/rails/generators/rails/app/templates/script/plugin.tt b/railties/lib/rails/generators/rails/app/templates/script/plugin
index 4a335ee33c..1f1af6c880 100755
--- a/railties/lib/rails/generators/rails/app/templates/script/plugin.tt
+++ b/railties/lib/rails/generators/rails/app/templates/script/plugin
@@ -1,3 +1,2 @@
-<%= shebang %>
require File.expand_path('../../config/application', __FILE__)
require 'rails/commands/plugin'
diff --git a/railties/lib/rails/generators/rails/app/templates/script/runner.tt b/railties/lib/rails/generators/rails/app/templates/script/runner
index 34ad7c18eb..7a70828e90 100755
--- a/railties/lib/rails/generators/rails/app/templates/script/runner.tt
+++ b/railties/lib/rails/generators/rails/app/templates/script/runner
@@ -1,3 +1,2 @@
-<%= shebang %>
require File.expand_path('../../config/environment', __FILE__)
require 'rails/commands/runner'
diff --git a/railties/lib/rails/generators/rails/app/templates/script/server.tt b/railties/lib/rails/generators/rails/app/templates/script/server
index 932e72ea58..709ca002df 100755
--- a/railties/lib/rails/generators/rails/app/templates/script/server.tt
+++ b/railties/lib/rails/generators/rails/app/templates/script/server
@@ -1,3 +1,3 @@
-<%= shebang %>
require File.expand_path('../../config/application', __FILE__)
require 'rails/commands/server'
+Rails::Server.start
diff --git a/railties/lib/rails/generators/rails/app/templates/test/performance/browsing_test.rb b/railties/lib/rails/generators/rails/app/templates/test/performance/browsing_test.rb
index 4b60558b43..a3dc38d9e4 100644
--- a/railties/lib/rails/generators/rails/app/templates/test/performance/browsing_test.rb
+++ b/railties/lib/rails/generators/rails/app/templates/test/performance/browsing_test.rb
@@ -1,5 +1,5 @@
require 'test_helper'
-require 'performance_test_help'
+require 'rails/performance_test_help'
# Profiling results for each test method are written to tmp/performance.
class BrowsingTest < ActionController::PerformanceTest
diff --git a/railties/lib/rails/generators/test_unit/performance/templates/performance_test.rb b/railties/lib/rails/generators/test_unit/performance/templates/performance_test.rb
index 27c91b0fca..362e3dc09f 100644
--- a/railties/lib/rails/generators/test_unit/performance/templates/performance_test.rb
+++ b/railties/lib/rails/generators/test_unit/performance/templates/performance_test.rb
@@ -1,5 +1,5 @@
require 'test_helper'
-require 'performance_test_help'
+require 'rails/performance_test_help'
class <%= class_name %>Test < ActionController::PerformanceTest
# Replace this with your real tests.
diff --git a/railties/lib/rails/initializable.rb b/railties/lib/rails/initializable.rb
index d78eab9a75..3866b856b2 100644
--- a/railties/lib/rails/initializable.rb
+++ b/railties/lib/rails/initializable.rb
@@ -42,7 +42,8 @@ module Rails
if initializer.before
index = index_for(initializer.before)
elsif initializer.after
- index = index_for(initializer.after) + 1
+ index = index_for(initializer.after)
+ index += 1 if index
else
index = length
end
diff --git a/railties/lib/rails/initializer.rb b/railties/lib/rails/initializer.rb
index 2ad1e52746..44101dcc94 100644
--- a/railties/lib/rails/initializer.rb
+++ b/railties/lib/rails/initializer.rb
@@ -1,16 +1,6 @@
-require "pathname"
+require "rails" # In case people require this file directly
-require 'rails/initializable'
-require 'rails/application'
-require 'rails/railties_path'
-require 'rails/version'
-require 'rails/rack'
-require 'rails/paths'
-require 'rails/core'
-require 'rails/configuration'
-require 'rails/deprecation'
-
-RAILS_ENV = (ENV['RAILS_ENV'] || 'development').dup unless defined?(RAILS_ENV)
+RAILS_ENV = (ENV['RAILS_ENV'] || ENV['RACK_ENV'] || 'development').dup unless defined?(RAILS_ENV)
module Rails
class Initializer
diff --git a/railties/lib/rails/paths.rb b/railties/lib/rails/paths.rb
index 0f24106353..b3d105d8c7 100644
--- a/railties/lib/rails/paths.rb
+++ b/railties/lib/rails/paths.rb
@@ -64,7 +64,7 @@ module Rails
end
class Path
- include PathParent
+ include PathParent, Enumerable
attr_reader :path
attr_accessor :glob
@@ -83,6 +83,10 @@ module Rails
@root.all_paths << self
end
+ def each
+ to_a.each { |p| yield p }
+ end
+
def push(path)
@paths.push path
end
diff --git a/railties/lib/rails/plugin.rb b/railties/lib/rails/plugin.rb
index 090ec6e4cb..86bf032641 100644
--- a/railties/lib/rails/plugin.rb
+++ b/railties/lib/rails/plugin.rb
@@ -1,183 +1,64 @@
module Rails
- # The Plugin class should be an object which provides the following methods:
- #
- # * +name+ - Used during initialisation to order the plugin (based on name and
- # the contents of <tt>config.plugins</tt>).
- # * +valid?+ - Returns true if this plugin can be loaded.
- # * +load_paths+ - Each path within the returned array will be added to the <tt>$LOAD_PATH</tt>.
- # * +load+ - Finally 'load' the plugin.
- #
- # These methods are expected by the Rails::Plugin::Locator and Rails::Plugin::Loader classes.
- # The default implementation returns the <tt>lib</tt> directory as its <tt>load_paths</tt>,
- # and evaluates <tt>init.rb</tt> when <tt>load</tt> is called.
- #
- # You can also inspect the about.yml data programmatically:
- #
- # plugin = Rails::Plugin.new(path_to_my_plugin)
- # plugin.about["author"] # => "James Adam"
- # plugin.about["url"] # => "http://interblah.net"
class Plugin
- include Comparable
include Initializable
-
- attr_reader :directory, :name
-
- def initialize(directory)
- @directory = directory
- @name = File.basename(@directory) rescue nil
- @loaded = false
- end
-
- def valid?
- File.directory?(directory) && (has_app_directory? || has_lib_directory? || has_init_file?)
- end
-
- # Returns a list of paths this plugin wishes to make available in <tt>$LOAD_PATH</tt>.
- def load_paths
- report_nonexistant_or_empty_plugin! unless valid?
-
- load_paths = []
- load_paths << lib_path if has_lib_directory?
- load_paths << app_paths if has_app_directory?
- load_paths.flatten
- end
-
- # Evaluates a plugin's init.rb file.
- def load(initializer)
- return if loaded?
- report_nonexistant_or_empty_plugin! unless valid?
- evaluate_init_rb(initializer)
- @loaded = true
- end
-
- def loaded?
- @loaded
- end
-
- def <=>(other_plugin)
- name <=> other_plugin.name
- end
-
- def about
- @about ||= load_about_information
- end
-
- # Engines are plugins with an app/ directory.
- def engine?
- has_app_directory?
- end
-
- # Returns true if the engine ships with a routing file
- def routed?
- File.exist?(routing_file)
- end
-
- # Returns true if there is any localization file in locale_path
- def localized?
- locale_files.any?
- end
-
- def view_path
- File.join(directory, 'app', 'views')
- end
-
- def controller_path
- File.join(directory, 'app', 'controllers')
- end
-
- def metal_path
- File.join(directory, 'app', 'metal')
- end
-
- def routing_file
- File.join(directory, 'config', 'routes.rb')
- end
-
- def locale_path
- File.join(directory, 'config', 'locales')
- end
-
- def locale_files
- Dir[ File.join(locale_path, '*.{rb,yml}') ]
- end
-
- private
- def load_about_information
- about_yml_path = File.join(@directory, "about.yml")
- parsed_yml = File.exist?(about_yml_path) ? YAML.load(File.read(about_yml_path)) : {}
- parsed_yml || {}
- rescue Exception
- {}
- end
- def report_nonexistant_or_empty_plugin!
- raise LoadError, "Can not find the plugin named: #{name}"
- end
-
- def app_paths
- [ File.join(directory, 'app', 'models'), File.join(directory, 'app', 'helpers'), controller_path, metal_path ]
- end
-
- def lib_path
- File.join(directory, 'lib')
- end
-
- def classic_init_path
- File.join(directory, 'init.rb')
- end
+ class Vendored < Plugin
+ def self.all(list, paths)
+ plugins = []
+ paths.each do |path|
+ Dir["#{path}/*"].each do |plugin_path|
+ plugin = new(plugin_path)
+ next unless list.include?(plugin.name) || list.include?(:all)
+ plugins << plugin
+ end
+ end
- def gem_init_path
- File.join(directory, 'rails', 'init.rb')
- end
+ plugins.sort_by do |p|
+ [list.index(p.name) || list.index(:all), p.name.to_s]
+ end
+ end
- def init_path
- File.file?(gem_init_path) ? gem_init_path : classic_init_path
- end
+ attr_reader :name, :path
- def has_app_directory?
- File.directory?(File.join(directory, 'app'))
- end
+ def initialize(path)
+ @name = File.basename(path).to_sym
+ @path = path
+ end
- def has_lib_directory?
- File.directory?(lib_path)
- end
+ def load_paths
+ Dir["#{path}/{lib}", "#{path}/app/{models,controllers,helpers}"]
+ end
- def has_init_file?
- File.file?(init_path)
- end
+ initializer :add_to_load_path, :after => :set_autoload_paths do |app|
+ load_paths.each do |path|
+ $LOAD_PATH << path
+ require "active_support/dependencies"
- def evaluate_init_rb(initializer)
- if has_init_file?
- require 'active_support/core_ext/kernel/reporting'
- silence_warnings do
- # Allow plugins to reference the current configuration object
- config = initializer.configuration
+ ActiveSupport::Dependencies.load_paths << path
- eval(IO.read(init_path), binding, init_path)
+ unless app.config.reload_plugins
+ ActiveSupport::Dependencies.load_once_paths << path
+ end
end
end
- end
- class Vendored < Plugin
- initializer :init_rb do |application|
- evaluate_init_rb(application)
+ initializer :load_init_rb, :before => :load_application_initializers do |app|
+ file = "#{@path}/init.rb"
+ config = app.config
+ eval File.read(file), binding, file if File.file?(file)
end
- end
- end
- # 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, gem)
- directory = spec.full_gem_path
- super(directory)
- @name = spec.name
- end
+ initializer :add_view_paths, :after => :initialize_framework_views do
+ ActionController::Base.view_paths.concat ["#{path}/app/views"] if File.directory?("#{path}/app/views")
+ end
- def init_path
- File.join(directory, 'rails', 'init.rb')
+ initializer :add_routing_file, :after => :initialize_routing do |app|
+ routing_file = "#{path}/config/routes.rb"
+ if File.exist?(routing_file)
+ app.routes.add_configuration_file(routing_file)
+ app.routes.reload!
+ end
+ end
end
end
-end
+end \ No newline at end of file
diff --git a/railties/lib/rails/plugin/loader.rb b/railties/lib/rails/plugin/loader.rb
deleted file mode 100644
index 4808c6ad57..0000000000
--- a/railties/lib/rails/plugin/loader.rb
+++ /dev/null
@@ -1,200 +0,0 @@
-require "rails/plugin"
-
-module Rails
- class Plugin
- class Loader
- attr_reader :initializer
-
- # Creates a new Plugin::Loader instance, associated with the given
- # Rails::Initializer. This default implementation automatically locates
- # all plugins, and adds all plugin load paths, when it is created. The plugins
- # are then fully loaded (init.rb is evaluated) when load_plugins is called.
- #
- # It is the loader's responsibility to ensure that only the plugins specified
- # in the configuration are actually loaded, and that the order defined
- # is respected.
- def initialize(initializer)
- @initializer = initializer
- end
-
- # Returns the plugins to be loaded, in the order they should be loaded.
- def plugins
- @plugins ||= all_plugins.select { |plugin| should_load?(plugin) }.sort { |p1, p2| order_plugins(p1, p2) }
- end
-
- # Returns the plugins that are in engine-form (have an app/ directory)
- def engines
- @engines ||= plugins.select {|plugin| plugin.engine? }
- end
-
- # Returns all the plugins that could be found by the current locators.
- def all_plugins
- @all_plugins ||= locate_plugins
- @all_plugins
- end
-
- def load_plugins
- plugins.each do |plugin|
- plugin.load(initializer)
- register_plugin_as_loaded(plugin)
- end
-
- configure_engines
-
- ensure_all_registered_plugins_are_loaded!
- end
-
- # Adds the load paths for every plugin into the $LOAD_PATH. Plugin load paths are
- # added *after* the application's <tt>lib</tt> directory, to ensure that an application
- # can always override code within a plugin.
- #
- # Plugin load paths are also added to Dependencies.load_paths, and Dependencies.load_once_paths.
- def add_plugin_load_paths
- plugins.each do |plugin|
- plugin.load_paths.each do |path|
- $LOAD_PATH.insert(application_lib_index + 1, path)
-
- ActiveSupport::Dependencies.load_paths << path
-
- unless configuration.reload_plugins?
- ActiveSupport::Dependencies.load_once_paths << path
- end
- end
- end
-
- $LOAD_PATH.uniq!
- end
-
- def engine_metal_paths
- engines.collect {|engine| engine.metal_path }
- end
-
- protected
- def configure_engines
- if engines.any?
- add_engine_routing_configurations
- add_engine_locales
- add_engine_controller_paths
- add_engine_view_paths
- end
- end
-
- def add_engine_routing_configurations
- engines.select {|engine| engine.routed? }.map {|engine| engine.routing_file }.each do |routing_file|
- ActionController::Routing::Routes.add_configuration_file(routing_file)
- end
- end
-
- def add_engine_locales
- localized_engines = engines.select { |engine| engine.localized? }
-
- # reverse it such that the last engine can overwrite translations from the first, like with routes
- locale_files = localized_engines.collect { |engine| engine.locale_files }.reverse.flatten
- I18n.load_path += locale_files - I18n.load_path
- end
-
- def add_engine_controller_paths
- ActionController::Routing.controller_paths += engines.collect {|engine| engine.controller_path }
- end
-
- def add_engine_view_paths
- # reverse it such that the last engine can overwrite view paths from the first, like with routes
- paths = ActionView::PathSet.new(engines.collect {|engine| engine.view_path }.reverse)
- ActionController::Base.view_paths.concat(paths)
- ActionMailer::Base.view_paths.concat(paths) if configuration.frameworks.include?(:action_mailer)
- end
-
- # The locate_plugins method uses each class in config.plugin_locators to
- # find the set of all plugins available to this Rails application.
- def locate_plugins
- configuration.plugin_locators.map do |locator|
- locator.new(initializer).plugins
- end.flatten
- # TODO: sorting based on config.plugins
- end
-
- def register_plugin_as_loaded(plugin)
- initializer.config.loaded_plugins << plugin
- end
-
- def configuration
- initializer.configuration
- end
-
- def should_load?(plugin)
- # uses Plugin#name and Plugin#valid?
- enabled?(plugin) && plugin.valid?
- end
-
- def order_plugins(plugin_a, plugin_b)
- if !explicit_plugin_loading_order?
- plugin_a <=> plugin_b
- else
- if !explicitly_enabled?(plugin_a) && !explicitly_enabled?(plugin_b)
- plugin_a <=> plugin_b
- else
- effective_order_of(plugin_a) <=> effective_order_of(plugin_b)
- end
- end
- end
-
- def effective_order_of(plugin)
- if explicitly_enabled?(plugin)
- registered_plugin_names.index(plugin.name)
- else
- registered_plugin_names.index('all')
- end
- end
-
- def application_lib_index
- $LOAD_PATH.index(File.join(Rails.root, 'lib')) || 0
- end
-
- def enabled?(plugin)
- !explicit_plugin_loading_order? || registered?(plugin)
- end
-
- def explicit_plugin_loading_order?
- !registered_plugin_names.nil?
- end
-
- def registered?(plugin)
- explicit_plugin_loading_order? && registered_plugins_names_plugin?(plugin)
- end
-
- def explicitly_enabled?(plugin)
- !explicit_plugin_loading_order? || explicitly_registered?(plugin)
- end
-
- def explicitly_registered?(plugin)
- explicit_plugin_loading_order? && registered_plugin_names.include?(plugin.name)
- end
-
- def registered_plugins_names_plugin?(plugin)
- registered_plugin_names.include?(plugin.name) || registered_plugin_names.include?('all')
- end
-
- # The plugins that have been explicitly listed with config.plugins. If this list is nil
- # then it means the client does not care which plugins or in what order they are loaded,
- # so we load all in alphabetical order. If it is an empty array, we load no plugins, if it is
- # non empty, we load the named plugins in the order specified.
- def registered_plugin_names
- configuration.plugins ? configuration.plugins.map {|plugin| plugin.to_s } : nil
- end
-
- def loaded?(plugin_name)
- initializer.config.loaded_plugins.detect { |plugin| plugin.name == plugin_name.to_s }
- end
-
- def ensure_all_registered_plugins_are_loaded!
- if explicit_plugin_loading_order?
- if configuration.plugins.detect {|plugin| plugin != :all && !loaded?(plugin) }
- missing_plugins = configuration.plugins - (plugins.map{|p| p.name.to_sym} + [:all])
- raise LoadError, "Could not locate the following plugins: #{missing_plugins.to_sentence(:locale => :en)}"
- end
- end
- end
-
- end
- end
-end
diff --git a/railties/lib/rails/plugin/locator.rb b/railties/lib/rails/plugin/locator.rb
deleted file mode 100644
index 56cbaf37c6..0000000000
--- a/railties/lib/rails/plugin/locator.rb
+++ /dev/null
@@ -1,100 +0,0 @@
-module Rails
- class Plugin
-
- # The Plugin::Locator class should be subclasses to provide custom plugin-finding
- # abilities to Rails (i.e. loading plugins from Gems, etc). Each subclass should implement
- # the <tt>located_plugins</tt> method, which return an array of Plugin objects that have been found.
- class Locator
- include Enumerable
-
- attr_reader :initializer
-
- def initialize(initializer)
- @initializer = initializer
- end
-
- # This method should return all the plugins which this Plugin::Locator can find
- # These will then be used by the current Plugin::Loader, which is responsible for actually
- # loading the plugins themselves
- def plugins
- raise "The `plugins' method must be defined by concrete subclasses of #{self.class}"
- end
-
- def each(&block)
- plugins.each(&block)
- end
-
- def plugin_names
- plugins.map {|plugin| plugin.name }
- end
- end
-
- # The Rails::Plugin::FileSystemLocator will try to locate plugins by examining the directories
- # in the paths given in configuration.plugin_paths. Any plugins that can be found are returned
- # in a list.
- #
- # The criteria for a valid plugin in this case is found in Rails::Plugin#valid?, although
- # other subclasses of Rails::Plugin::Locator can of course use different conditions.
- class FileSystemLocator < Locator
-
- # Returns all the plugins which can be loaded in the filesystem, under the paths given
- # by configuration.plugin_paths.
- def plugins
- initializer.configuration.plugin_paths.flatten.inject([]) do |plugins, path|
- plugins.concat locate_plugins_under(path)
- plugins
- end.flatten
- end
-
- private
-
- # Attempts to create a plugin from the given path. If the created plugin is valid?
- # (see Rails::Plugin#valid?) then the plugin instance is returned; otherwise nil.
- def create_plugin(path)
- plugin = Rails::Plugin.new(path)
- plugin.valid? ? plugin : nil
- end
-
- # This starts at the base path looking for valid plugins (see Rails::Plugin#valid?).
- # Since plugins can be nested arbitrarily deep within an unspecified number of intermediary
- # directories, this method runs recursively until it finds a plugin directory, e.g.
- #
- # locate_plugins_under('vendor/plugins/acts/acts_as_chunky_bacon')
- # => <Rails::Plugin name: 'acts_as_chunky_bacon' ... >
- #
- def locate_plugins_under(base_path)
- Dir.glob(File.join(base_path, '*')).sort.inject([]) do |plugins, path|
- if plugin = create_plugin(path)
- plugins << plugin
- elsif File.directory?(path)
- plugins.concat locate_plugins_under(path)
- end
- plugins
- end
- end
- end
-
- # The GemLocator scans all the loaded RubyGems, looking for gems with
- # a <tt>rails/init.rb</tt> file.
- class GemLocator < Locator
- def plugins
- gem_index = {}
- specs = gem_index.keys
- 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"
-
- deps = Gem::DependencyList.new
- deps.add(*specs) unless specs.empty?
-
- deps.dependency_order.collect do |spec|
- Rails::GemPlugin.new(spec, gem_index[spec])
- end
- end
- end
- end
-end \ No newline at end of file
diff --git a/railties/lib/rails/rack/debugger.rb b/railties/lib/rails/rack/debugger.rb
index aa2711c616..0a7b405553 100644
--- a/railties/lib/rails/rack/debugger.rb
+++ b/railties/lib/rails/rack/debugger.rb
@@ -4,6 +4,8 @@ module Rails
def initialize(app)
@app = app
+ ARGV.clear # clear ARGV so that script/server options aren't passed to IRB
+
require_library_or_gem 'ruby-debug'
::Debugger.start
::Debugger.settings[:autoeval] = true if ::Debugger.respond_to?(:settings)
diff --git a/railties/lib/rails/rack/static.rb b/railties/lib/rails/rack/static.rb
index d6b8face27..ebe8b9e103 100644
--- a/railties/lib/rails/rack/static.rb
+++ b/railties/lib/rails/rack/static.rb
@@ -1,5 +1,5 @@
require 'action_dispatch'
module Rails::Rack
- Static = Deprecation::DeprecatedConstantProxy.new('Rails::Rack::Static', ActionDispatch::Static)
+ Static = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('Rails::Rack::Static', ActionDispatch::Static)
end
diff --git a/railties/lib/rails/vendor/thor-0.11.8/CHANGELOG.rdoc b/railties/lib/rails/vendor/thor-0.12.0/CHANGELOG.rdoc
index dba25b7205..adedfeca9d 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/CHANGELOG.rdoc
+++ b/railties/lib/rails/vendor/thor-0.12.0/CHANGELOG.rdoc
@@ -2,7 +2,12 @@
* Improve spec coverage for Thor::Runner
-== 0.11.x, released 2009-07-01
+== 0.12, released 2009-11-06
+
+* [#7] Do not force white color on status
+* [#8] Yield a block with the filename on directory
+
+== 0.11, released 2009-07-01
* Added a rake compatibility layer. It allows you to use spec and rdoc tasks on
Thor classes.
diff --git a/railties/lib/rails/vendor/thor-0.11.8/LICENSE b/railties/lib/rails/vendor/thor-0.12.0/LICENSE
index 98722da459..98722da459 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/LICENSE
+++ b/railties/lib/rails/vendor/thor-0.12.0/LICENSE
diff --git a/railties/lib/rails/vendor/thor-0.11.8/README.rdoc b/railties/lib/rails/vendor/thor-0.12.0/README.rdoc
index f1106f02b6..f1106f02b6 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/README.rdoc
+++ b/railties/lib/rails/vendor/thor-0.12.0/README.rdoc
diff --git a/railties/lib/rails/vendor/thor-0.11.8/Thorfile b/railties/lib/rails/vendor/thor-0.12.0/Thorfile
index f71a1e57e2..f71a1e57e2 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/Thorfile
+++ b/railties/lib/rails/vendor/thor-0.12.0/Thorfile
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor.rb
index 68944f140d..68944f140d 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor.rb
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions.rb
index d561ccb2aa..d561ccb2aa 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions.rb
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions/create_file.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/create_file.rb
index 8f6badee27..a3d9296823 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions/create_file.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/create_file.rb
@@ -60,6 +60,7 @@ class Thor
FileUtils.mkdir_p(File.dirname(destination))
File.open(destination, 'w'){ |f| f.write render }
end
+ given_destination
end
protected
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions/directory.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/directory.rb
index 063ac57406..467e63732a 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions/directory.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/directory.rb
@@ -40,15 +40,16 @@ class Thor
# directory "doc"
# directory "doc", "docs", :recursive => false
#
- def directory(source, destination=nil, config={})
- action Directory.new(self, source, destination || source, config)
+ def directory(source, destination=nil, config={}, &block)
+ action Directory.new(self, source, destination || source, config, &block)
end
class Directory < EmptyDirectory #:nodoc:
attr_reader :source
- def initialize(base, source, destination=nil, config={})
+ def initialize(base, source, destination=nil, config={}, &block)
@source = File.expand_path(base.find_in_source_paths(source.to_s))
+ @block = block
super(base, destination, { :recursive => true }.merge(config))
end
@@ -70,6 +71,7 @@ class Thor
Dir[lookup].each do |file_source|
next if File.directory?(file_source)
file_destination = File.join(given_destination, file_source.gsub(source, '.'))
+ file_destination.gsub!('/./', '/')
case file_source
when /\.empty_directory$/
@@ -77,9 +79,11 @@ class Thor
next if dirname == given_destination
base.empty_directory(dirname, config)
when /\.tt$/
- base.template(file_source, file_destination[0..-4], config)
+ destination = base.template(file_source, file_destination[0..-4], config)
+ @block.call(destination) if @block
else
- base.copy_file(file_source, file_destination, config)
+ destination = base.copy_file(file_source, file_destination, config)
+ @block.call(destination) if @block
end
end
end
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions/empty_directory.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/empty_directory.rb
index 03c1fe4af1..484cb820f8 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions/empty_directory.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/empty_directory.rb
@@ -55,6 +55,7 @@ class Thor
def revoke!
say_status :remove, :red
::FileUtils.rm_rf(destination) if !pretend? && exists?
+ given_destination
end
protected
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions/file_manipulation.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/file_manipulation.rb
index d77d90d448..d77d90d448 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions/file_manipulation.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/file_manipulation.rb
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions/inject_into_file.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/inject_into_file.rb
index 0636ec6591..0636ec6591 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/actions/inject_into_file.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/actions/inject_into_file.rb
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/base.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/base.rb
index 700d794123..700d794123 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/base.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/base.rb
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/core_ext/hash_with_indifferent_access.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/core_ext/hash_with_indifferent_access.rb
index 78bc5cf4bf..78bc5cf4bf 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/core_ext/hash_with_indifferent_access.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/core_ext/hash_with_indifferent_access.rb
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/core_ext/ordered_hash.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/core_ext/ordered_hash.rb
index 27fea5bb35..27fea5bb35 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/core_ext/ordered_hash.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/core_ext/ordered_hash.rb
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/error.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/error.rb
index f9b31a35d1..f9b31a35d1 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/error.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/error.rb
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/group.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/group.rb
index 1e59df2313..0964a9667a 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/group.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/group.rb
@@ -74,7 +74,7 @@ class Thor::Group
#
def invoke(*names, &block)
options = names.last.is_a?(Hash) ? names.pop : {}
- verbose = options.fetch(:verbose, :white)
+ verbose = options.fetch(:verbose, true)
names.each do |name|
invocations[name] = false
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/invocation.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/invocation.rb
index 32e6a72454..32e6a72454 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/invocation.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/invocation.rb
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/parser.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser.rb
index 57a3f6e1a5..57a3f6e1a5 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/parser.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser.rb
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/parser/argument.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/argument.rb
index aa8ace4719..aa8ace4719 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/parser/argument.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/argument.rb
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/parser/arguments.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/arguments.rb
index fb5d965e06..fb5d965e06 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/parser/arguments.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/arguments.rb
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/parser/option.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/option.rb
index 9e40ec73fa..9e40ec73fa 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/parser/option.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/option.rb
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/parser/options.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/options.rb
index 75092308b5..75092308b5 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/parser/options.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/parser/options.rb
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/rake_compat.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/rake_compat.rb
index 0d0757fdda..0d0757fdda 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/rake_compat.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/rake_compat.rb
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/runner.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/runner.rb
index 9dc70ea069..9dc70ea069 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/runner.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/runner.rb
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/shell.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell.rb
index 1dc8f0e5b4..1dc8f0e5b4 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/shell.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell.rb
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/shell/basic.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell/basic.rb
index ea9665380b..ea9665380b 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/shell/basic.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell/basic.rb
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/shell/color.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell/color.rb
index 24704f7885..24704f7885 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/shell/color.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/shell/color.rb
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/task.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/task.rb
index 91c7564d3f..91c7564d3f 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/task.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/task.rb
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/util.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/util.rb
index ebae0a3193..ebae0a3193 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/util.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/util.rb
diff --git a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/version.rb b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/version.rb
index 885230fac4..885230fac4 100644
--- a/railties/lib/rails/vendor/thor-0.11.8/lib/thor/version.rb
+++ b/railties/lib/rails/vendor/thor-0.12.0/lib/thor/version.rb
diff --git a/railties/test/application/notifications_test.rb b/railties/test/application/notifications_test.rb
index 62ed4f4ad4..28dfdfcd83 100644
--- a/railties/test/application/notifications_test.rb
+++ b/railties/test/application/notifications_test.rb
@@ -10,13 +10,15 @@ module ApplicationTests
def initialize
@events = []
@subscribers = []
+ @listeners = []
end
def publish(name, *args)
@events << name
end
- def subscribe(pattern=nil, &block)
+ def subscribe(listener, pattern=nil, &block)
+ @listeners << listener
@subscribers << pattern
end
end
diff --git a/railties/test/application/plugins_test.rb b/railties/test/application/plugins_test.rb
deleted file mode 100644
index 80a19856d7..0000000000
--- a/railties/test/application/plugins_test.rb
+++ /dev/null
@@ -1,117 +0,0 @@
-require "isolation/abstract_unit"
-
-module ApplicationTests
- class PluginTest < Test::Unit::TestCase
- include ActiveSupport::Testing::Isolation
-
- def assert_plugins(list_of_names, array_of_plugins, message=nil)
- assert_equal list_of_names.map { |n| n.to_s }, array_of_plugins.map { |p| p.name }, message
- end
-
- def setup
- build_app
- boot_rails
- require "rails"
- @failure_tip = "It's likely someone has added a new plugin fixture without updating this list"
- # Tmp hax to get tests working
- FileUtils.cp_r "#{File.dirname(__FILE__)}/../fixtures/plugins", "#{app_path}/vendor"
- end
-
- test "all plugins are loaded when registered plugin list is untouched" do
- Rails::Initializer.run { |c| c.root = app_path }
- Rails.initialize!
- assert_plugins [
- :a, :acts_as_chunky_bacon, :engine, :gemlike, :plugin_with_no_lib_dir, :stubby
- ], Rails.application.config.loaded_plugins, @failure_tip
- end
-
- test "no plugins are loaded if the configuration has an empty plugin list" do
- Rails::Initializer.run { |c| c.root = app_path; c.plugins = [] }
- assert_plugins [], Rails.application.config.loaded_plugins
- end
-
- test "only the specified plugins are located in the order listed" do
- plugin_names = [:plugin_with_no_lib_dir, :acts_as_chunky_bacon]
- Rails::Initializer.run { |c| c.root = app_path; c.plugins = plugin_names }
- Rails.initialize!
- assert_plugins plugin_names, Rails.application.config.loaded_plugins
- end
-
- test "all plugins loaded after all" do
- Rails::Initializer.run do |config|
- config.root = app_path
- config.plugins = [:stubby, :all, :acts_as_chunky_bacon]
- end
- Rails.initialize!
- assert_plugins [:stubby, :a, :engine, :gemlike, :plugin_with_no_lib_dir, :acts_as_chunky_bacon], Rails.application.config.loaded_plugins, @failure_tip
- end
-
- test "plugin names may be strings" do
- plugin_names = ['stubby', 'acts_as_chunky_bacon', :a, :plugin_with_no_lib_dir]
- Rails::Initializer.run do |config|
- config.root = app_path
- config.plugins = ['stubby', 'acts_as_chunky_bacon', :a, :plugin_with_no_lib_dir]
- end
- Rails.initialize!
-
- assert_plugins plugin_names, Rails.application.config.loaded_plugins, @failure_tip
- end
-
- test "all plugins loaded when all is used" do
- Rails::Initializer.run do |config|
- config.root = app_path
- config.plugins = [:stubby, :acts_as_chunky_bacon, :all]
- end
- Rails.initialize!
-
- assert_plugins [:stubby, :acts_as_chunky_bacon, :a, :engine, :gemlike, :plugin_with_no_lib_dir], Rails.application.config.loaded_plugins, @failure_tip
- end
-
- test "all loaded plugins are added to the load paths" do
- Rails::Initializer.run do |config|
- config.root = app_path
- config.plugins = [:stubby, :acts_as_chunky_bacon]
- end
- Rails.initialize!
-
- assert $LOAD_PATH.include?("#{app_path}/vendor/plugins/default/stubby/lib")
- assert $LOAD_PATH.include?("#{app_path}/vendor/plugins/default/acts/acts_as_chunky_bacon/lib")
- end
-
- test "registering a plugin name that does not exist raises a load error" do
- Rails::Initializer.run do |config|
- config.root = app_path
- config.plugins = [:stubby, :acts_as_a_non_existant_plugin]
- end
-
- assert_raise(LoadError) do
- Rails.initialize!
- end
- end
-
- test "load error messages mention missing plugins and no others" do
- valid_plugins = [:stubby, :acts_as_chunky_bacon]
- invalid_plugins = [:non_existant_plugin1, :non_existant_plugin2]
-
- begin
- Rails::Initializer.run do |config|
- config.root = app_path
- config.plugins = [:stubby, :acts_as_chunky_bacon, :non_existant_plugin1, :non_existant_plugin2]
- end
- Rails.initialize!
- flunk "Expected a LoadError but did not get one"
- rescue LoadError => e
- assert_plugins valid_plugins, Rails.application.config.loaded_plugins, @failure_tip
-
- invalid_plugins.each do |plugin|
- assert_match(/#{plugin.to_s}/, e.message, "LoadError message should mention plugin '#{plugin}'")
- end
-
- valid_plugins.each do |plugin|
- assert_no_match(/#{plugin.to_s}/, e.message, "LoadError message should not mention '#{plugin}'")
- end
- end
- end
-
- end
-end \ No newline at end of file
diff --git a/railties/test/backtrace_cleaner_test.rb b/railties/test/backtrace_cleaner_test.rb
index 4e273852e0..6cff591b94 100644
--- a/railties/test/backtrace_cleaner_test.rb
+++ b/railties/test/backtrace_cleaner_test.rb
@@ -16,12 +16,12 @@ if defined? Test::Unit::Util::BacktraceFilter
test "test with backtrace should use the rails backtrace cleaner to clean" do
Rails.stubs(:backtrace_cleaner).returns(stub(:clean))
Rails.backtrace_cleaner.expects(:clean).with(@backtrace, nil)
- @test.filter_backtrace(@backtrace)
+ @test.send(:filter_backtrace, @backtrace)
end
test "filter backtrace should have the same arity as Test::Unit::Util::BacktraceFilter" do
assert_nothing_raised do
- @test.filter_backtrace(@backtrace, '/opt/local/lib')
+ @test.send(:filter_backtrace, @backtrace, '/opt/local/lib')
end
end
end
diff --git a/railties/test/fixtures/vendor/plugins/mspec/lib/generators/mspec_generator.rb b/railties/test/fixtures/vendor/plugins/mspec/lib/rails_generators/mspec_generator.rb
index 191bdbf2fc..191bdbf2fc 100644
--- a/railties/test/fixtures/vendor/plugins/mspec/lib/generators/mspec_generator.rb
+++ b/railties/test/fixtures/vendor/plugins/mspec/lib/rails_generators/mspec_generator.rb
diff --git a/railties/test/generators_test.rb b/railties/test/generators_test.rb
index 9c9a4e6016..4b7b80c7f5 100644
--- a/railties/test/generators_test.rb
+++ b/railties/test/generators_test.rb
@@ -150,6 +150,13 @@ class GeneratorsTest < GeneratorsTestCase
assert_equal "test_unit:generators:plugin", klass.namespace
end
+ def test_fallbacks_for_generators_on_find_by_namespace_with_context
+ Rails::Generators.fallbacks[:remarkable] = :test_unit
+ klass = Rails::Generators.find_by_namespace(:remarkable, :rails, :plugin)
+ assert klass
+ assert_equal "test_unit:generators:plugin", klass.namespace
+ end
+
def test_fallbacks_for_generators_on_invoke
Rails::Generators.fallbacks[:shoulda] = :test_unit
TestUnit::Generators::ModelGenerator.expects(:start).with(["Account"], {})
@@ -166,10 +173,7 @@ class GeneratorsTest < GeneratorsTestCase
Rails::Generators.options[:new_generator] = { :generate => false }
klass = Class.new(Rails::Generators::Base) do
- def self.name
- "NewGenerator"
- end
-
+ def self.name() 'NewGenerator' end
class_option :generate, :default => true
end
diff --git a/railties/test/initializable_test.rb b/railties/test/initializable_test.rb
index 2920883132..a9e60680ac 100644
--- a/railties/test/initializable_test.rb
+++ b/railties/test/initializable_test.rb
@@ -94,6 +94,10 @@ module InitializableTests
include Rails::Initializable
initializer :startup, :before => :last do
+ $arr << 3
+ end
+
+ initializer :terminate, :after => :first do
$arr << two
end
@@ -109,7 +113,7 @@ module InitializableTests
end
initializer :last do
- $arr << 3
+ $arr << 4
end
def self.initializers
@@ -189,7 +193,7 @@ module InitializableTests
test "merges in the initializers from the parent in the right order" do
$arr = []
OverriddenInitializer.new.run_initializers
- assert_equal [1, 2, 3], $arr
+ assert_equal [1, 2, 3, 4], $arr
end
end
end \ No newline at end of file
diff --git a/railties/test/initializer/initialize_i18n_test.rb b/railties/test/initializer/initialize_i18n_test.rb
index d664f96ad1..076816d73b 100644
--- a/railties/test/initializer/initialize_i18n_test.rb
+++ b/railties/test/initializer/initialize_i18n_test.rb
@@ -30,27 +30,27 @@ module InitializerTests
end
test "i18n finds locale files in engines" do
- app_file "vendor/plugins/engine/init.rb", ""
- app_file "vendor/plugins/engine/app/models/hellos.rb", "class Hello ; end"
- app_file "vendor/plugins/engine/lib/omg.rb", "puts 'omg'"
- app_file "vendor/plugins/engine/config/locales/en.yml", "hello:"
-
- Rails::Initializer.run do |c|
- c.root = app_path
- c.i18n.load_path << "my/other/locale.yml"
- end
- Rails.initialize!
-
- #{RAILS_FRAMEWORK_ROOT}/railties/test/fixtures/plugins/engines/engine/config/locales/en.yml
- assert_equal %W(
- #{RAILS_FRAMEWORK_ROOT}/activesupport/lib/active_support/locale/en.yml
- #{RAILS_FRAMEWORK_ROOT}/activemodel/lib/active_model/locale/en.yml
- #{RAILS_FRAMEWORK_ROOT}/activerecord/lib/active_record/locale/en.yml
- #{RAILS_FRAMEWORK_ROOT}/actionpack/lib/action_view/locale/en.yml
- #{app_path}/config/locales/en.yml
- my/other/locale.yml
- #{app_path}/vendor/plugins/engine/config/locales/en.yml
- ).map { |path| File.expand_path(path) }, I18n.load_path.map { |path| File.expand_path(path) }
+ # app_file "vendor/plugins/engine/init.rb", ""
+ # app_file "vendor/plugins/engine/app/models/hellos.rb", "class Hello ; end"
+ # app_file "vendor/plugins/engine/lib/omg.rb", "puts 'omg'"
+ # app_file "vendor/plugins/engine/config/locales/en.yml", "hello:"
+ #
+ # Rails::Initializer.run do |c|
+ # c.root = app_path
+ # c.i18n.load_path << "my/other/locale.yml"
+ # end
+ # Rails.initialize!
+ #
+ # #{RAILS_FRAMEWORK_ROOT}/railties/test/fixtures/plugins/engines/engine/config/locales/en.yml
+ # assert_equal %W(
+ # #{RAILS_FRAMEWORK_ROOT}/activesupport/lib/active_support/locale/en.yml
+ # #{RAILS_FRAMEWORK_ROOT}/activemodel/lib/active_model/locale/en.yml
+ # #{RAILS_FRAMEWORK_ROOT}/activerecord/lib/active_record/locale/en.yml
+ # #{RAILS_FRAMEWORK_ROOT}/actionpack/lib/action_view/locale/en.yml
+ # #{app_path}/config/locales/en.yml
+ # my/other/locale.yml
+ # #{app_path}/vendor/plugins/engine/config/locales/en.yml
+ # ).map { |path| File.expand_path(path) }, I18n.load_path.map { |path| File.expand_path(path) }
end
end
end \ No newline at end of file
diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb
index 462a4d8dea..ba8b35d5cc 100644
--- a/railties/test/isolation/abstract_unit.rb
+++ b/railties/test/isolation/abstract_unit.rb
@@ -92,6 +92,34 @@ module TestHelpers
add_to_config 'config.action_controller.session = { :key => "_myapp_session", :secret => "bac838a849c1d5c4de2e6a50af826079" }'
end
+ class Bukkit
+ def initialize(path)
+ @path = path
+ end
+
+ def write(file, string)
+ path = "#{@path}/#{file}"
+ FileUtils.mkdir_p(File.dirname(path))
+ File.open(path, "w") {|f| f.puts string }
+ end
+
+ def delete(file)
+ File.delete("#{@path}/#{file}")
+ end
+ end
+
+ def plugin(name, string = "")
+ dir = "#{app_path}/vendor/plugins/#{name}"
+ FileUtils.mkdir_p(dir)
+ File.open("#{dir}/init.rb", 'w') do |f|
+ f.puts "::#{name.upcase} = 'loaded'"
+ f.puts string
+ end
+ Bukkit.new(dir).tap do |bukkit|
+ yield bukkit if block_given?
+ end
+ end
+
def script(script)
Dir.chdir(app_path) do
`#{Gem.ruby} #{app_path}/script/#{script}`
@@ -157,9 +185,13 @@ Module.new do
FileUtils.mkdir(tmp_path)
environment = File.expand_path('../../../../vendor/gems/environment', __FILE__)
+ if File.exist?("#{environment}.rb")
+ require_environment = "-r #{environment}"
+ end
- `#{Gem.ruby} -r #{environment} #{RAILS_FRAMEWORK_ROOT}/railties/bin/rails #{tmp_path('app_template')}`
+ `#{Gem.ruby} #{require_environment} #{RAILS_FRAMEWORK_ROOT}/railties/bin/rails #{tmp_path('app_template')}`
File.open("#{tmp_path}/app_template/config/boot.rb", 'w') do |f|
- f.puts "require '#{environment}' ; require 'rails'"
+ f.puts "require '#{environment}'" if require_environment
+ f.puts "require 'rails'"
end
end
diff --git a/railties/test/plugin_loader_test.rb b/railties/test/plugin_loader_test.rb
deleted file mode 100644
index 0b43c49bb2..0000000000
--- a/railties/test/plugin_loader_test.rb
+++ /dev/null
@@ -1,176 +0,0 @@
-require 'plugin_test_helper'
-
-$:.unshift File.dirname(__FILE__) + "/../../actionpack/lib"
-$:.unshift File.dirname(__FILE__) + "/../../actionmailer/lib"
-require 'action_controller'
-require 'action_mailer'
-
-# TODO: Rewrite all these tests
-class FakeInitializerSlashApplication
- attr_reader :config
- alias configuration config
-
- def initialize
- @config = Rails::Configuration.new
- end
-end
-
-class TestPluginLoader < Test::Unit::TestCase
- ORIGINAL_LOAD_PATH = $LOAD_PATH.dup
-
- def setup
- reset_load_path!
-
- @initializer = FakeInitializerSlashApplication.new
- @configuration = @initializer.config
- Rails.application = @initializer
- @configuration.plugin_paths << plugin_fixture_root_path
- @valid_plugin_path = plugin_fixture_path('default/stubby')
- @empty_plugin_path = plugin_fixture_path('default/empty')
-
- @failure_tip = "It's likely someone has added a new plugin fixture without updating this list"
-
- @loader = Rails::Plugin::Loader.new(@initializer)
- end
-
- def test_should_locate_plugins_by_asking_each_locator_specifed_in_configuration_for_its_plugins_result
- locator_1 = stub(:plugins => [:a, :b, :c])
- locator_2 = stub(:plugins => [:d, :e, :f])
- locator_class_1 = stub(:new => locator_1)
- locator_class_2 = stub(:new => locator_2)
- @configuration.plugin_locators = [locator_class_1, locator_class_2]
- assert_equal [:a, :b, :c, :d, :e, :f], @loader.send(:locate_plugins)
- end
-
- def test_should_memoize_the_result_of_locate_plugins_as_all_plugins
- plugin_list = [:a, :b, :c]
- @loader.expects(:locate_plugins).once.returns(plugin_list)
- assert_equal plugin_list, @loader.all_plugins
- assert_equal plugin_list, @loader.all_plugins # ensuring that locate_plugins isn't called again
- end
-
- def test_should_return_empty_array_if_configuration_plugins_is_empty
- @configuration.plugins = []
- assert_equal [], @loader.plugins
- end
-
- def test_should_find_all_availble_plugins_and_return_as_all_plugins
- assert_plugins [ :engine, :stubby, :plugin_with_no_lib_dir, :gemlike, :acts_as_chunky_bacon, :a], @loader.all_plugins.reverse, @failure_tip
- end
-
- def test_should_return_all_plugins_as_plugins_when_registered_plugin_list_is_untouched
- assert_plugins [:a, :acts_as_chunky_bacon, :engine, :gemlike, :plugin_with_no_lib_dir, :stubby], @loader.plugins, @failure_tip
- end
-
- def test_should_return_all_plugins_as_plugins_when_registered_plugin_list_is_nil
- @configuration.plugins = nil
- assert_plugins [:a, :acts_as_chunky_bacon, :engine, :gemlike, :plugin_with_no_lib_dir, :stubby], @loader.plugins, @failure_tip
- end
-
- def test_should_return_specific_plugins_named_in_config_plugins_array_if_set
- plugin_names = [:acts_as_chunky_bacon, :stubby]
- only_load_the_following_plugins! plugin_names
- assert_plugins plugin_names, @loader.plugins
- end
-
- def test_should_respect_the_order_of_plugins_given_in_configuration
- plugin_names = [:stubby, :acts_as_chunky_bacon]
- only_load_the_following_plugins! plugin_names
- assert_plugins plugin_names, @loader.plugins
- end
-
- def test_should_load_all_plugins_in_natural_order_when_all_is_used
- only_load_the_following_plugins! [:all]
- assert_plugins [:a, :acts_as_chunky_bacon, :engine, :gemlike, :plugin_with_no_lib_dir, :stubby], @loader.plugins, @failure_tip
- end
-
- def test_should_load_specified_plugins_in_order_and_then_all_remaining_plugins_when_all_is_used
- only_load_the_following_plugins! [:stubby, :acts_as_chunky_bacon, :all]
- assert_plugins [:stubby, :acts_as_chunky_bacon, :a, :engine, :gemlike, :plugin_with_no_lib_dir], @loader.plugins, @failure_tip
- end
-
- def test_should_be_able_to_specify_loading_of_plugins_loaded_after_all
- only_load_the_following_plugins! [:stubby, :all, :acts_as_chunky_bacon]
- assert_plugins [:stubby, :a, :engine, :gemlike, :plugin_with_no_lib_dir, :acts_as_chunky_bacon], @loader.plugins, @failure_tip
- end
-
- def test_should_accept_plugin_names_given_as_strings
- only_load_the_following_plugins! ['stubby', 'acts_as_chunky_bacon', :a, :plugin_with_no_lib_dir]
- assert_plugins [:stubby, :acts_as_chunky_bacon, :a, :plugin_with_no_lib_dir], @loader.plugins, @failure_tip
- end
-
- def test_should_add_plugin_load_paths_to_global_LOAD_PATH_array
- only_load_the_following_plugins! [:stubby, :acts_as_chunky_bacon]
- stubbed_application_lib_index_in_LOAD_PATHS = 4
- @loader.stubs(:application_lib_index).returns(stubbed_application_lib_index_in_LOAD_PATHS)
-
- @loader.add_plugin_load_paths
-
- assert $LOAD_PATH.index(File.join(plugin_fixture_path('default/stubby'), 'lib')) >= stubbed_application_lib_index_in_LOAD_PATHS
- assert $LOAD_PATH.index(File.join(plugin_fixture_path('default/acts/acts_as_chunky_bacon'), 'lib')) >= stubbed_application_lib_index_in_LOAD_PATHS
- end
-
- def test_should_add_plugin_load_paths_to_Dependencies_load_paths
- only_load_the_following_plugins! [:stubby, :acts_as_chunky_bacon]
-
- @loader.add_plugin_load_paths
-
- assert ActiveSupport::Dependencies.load_paths.include?(File.join(plugin_fixture_path('default/stubby'), 'lib'))
- assert ActiveSupport::Dependencies.load_paths.include?(File.join(plugin_fixture_path('default/acts/acts_as_chunky_bacon'), 'lib'))
- end
-
- def test_should_add_engine_load_paths_to_Dependencies_load_paths
- only_load_the_following_plugins! [:engine]
-
- @loader.add_plugin_load_paths
-
- %w( models controllers metal helpers ).each do |app_part|
- assert ActiveSupport::Dependencies.load_paths.include?(
- File.join(plugin_fixture_path('engines/engine'), 'app', app_part)
- ), "Couldn't find #{app_part} in load path"
- end
- end
-
- def test_engine_controllers_and_action_mailers_should_have_their_view_path_set_when_loaded
- only_load_the_following_plugins!([ :engine ])
-
- @loader.send :add_engine_view_paths
-
- assert_equal [ File.join(plugin_fixture_path('engines/engine'), 'app', 'views') ], ActionController::Base.view_paths.map { |p| p.to_s }
- assert_equal [ File.join(plugin_fixture_path('engines/engine'), 'app', 'views') ], ActionMailer::Base.view_paths.map { |p| p.to_s }
- end
-
- def test_should_add_plugin_load_paths_to_Dependencies_load_once_paths
- only_load_the_following_plugins! [:stubby, :acts_as_chunky_bacon]
-
- @loader.add_plugin_load_paths
-
- assert ActiveSupport::Dependencies.load_once_paths.include?(File.join(plugin_fixture_path('default/stubby'), 'lib'))
- assert ActiveSupport::Dependencies.load_once_paths.include?(File.join(plugin_fixture_path('default/acts/acts_as_chunky_bacon'), 'lib'))
- end
-
- def test_should_add_all_load_paths_from_a_plugin_to_LOAD_PATH_array
- plugin_load_paths = ["a", "b"]
- plugin = stub(:load_paths => plugin_load_paths)
- @loader.stubs(:plugins).returns([plugin])
-
- @loader.add_plugin_load_paths
-
- plugin_load_paths.each { |path| assert $LOAD_PATH.include?(path) }
- end
-
- def test_should_add_locale_files_to_I18n_load_path
- only_load_the_following_plugins! [:engine]
-
- @loader.send :add_engine_locales
-
- assert I18n.load_path.include?(File.join(plugin_fixture_path('engines/engine'), 'config', 'locales', 'en.yml'))
- end
-
-
- private
- def reset_load_path!
- $LOAD_PATH.clear
- ORIGINAL_LOAD_PATH.each { |path| $LOAD_PATH << path }
- end
-end
diff --git a/railties/test/plugin_locator_test.rb b/railties/test/plugin_locator_test.rb
deleted file mode 100644
index ef57e7ed4c..0000000000
--- a/railties/test/plugin_locator_test.rb
+++ /dev/null
@@ -1,73 +0,0 @@
-require 'plugin_test_helper'
-
-# TODO: Rewrite all these tests
-class FakeInitializerSlashApplication
- attr_reader :config
- alias configuration config
-
- def initialize
- @config = Rails::Configuration.new
- end
-end
-
-class PluginLocatorTest < Test::Unit::TestCase
- def test_should_require_subclasses_to_implement_the_plugins_method
- assert_raise(RuntimeError) do
- Rails::Plugin::Locator.new(nil).plugins
- end
- end
-
- def test_should_iterator_over_plugins_returned_by_plugins_when_calling_each
- locator = Rails::Plugin::Locator.new(nil)
- locator.stubs(:plugins).returns([:a, :b, :c])
- plugin_consumer = mock
- plugin_consumer.expects(:consume).with(:a)
- plugin_consumer.expects(:consume).with(:b)
- plugin_consumer.expects(:consume).with(:c)
-
- locator.each do |plugin|
- plugin_consumer.consume(plugin)
- end
- end
-end
-
-class PluginFileSystemLocatorTest < Test::Unit::TestCase
- def setup
- @initializer = FakeInitializerSlashApplication.new
- @configuration = @initializer.config
- Rails.application = @initializer
- # We need to add our testing plugin directory to the plugin paths so
- # the locator knows where to look for our plugins
- @configuration.plugin_paths << plugin_fixture_root_path
- @locator = Rails::Plugin::FileSystemLocator.new(@initializer)
- @valid_plugin_path = plugin_fixture_path('default/stubby')
- @empty_plugin_path = plugin_fixture_path('default/empty')
- end
-
- def test_should_return_rails_plugin_instances_when_calling_create_plugin_with_a_valid_plugin_directory
- assert_kind_of Rails::Plugin, @locator.send(:create_plugin, @valid_plugin_path)
- end
-
- def test_should_return_nil_when_calling_create_plugin_with_an_invalid_plugin_directory
- assert_nil @locator.send(:create_plugin, @empty_plugin_path)
- end
-
- def test_should_return_all_plugins_found_under_the_set_plugin_paths
- assert_equal ["a", "acts_as_chunky_bacon", "engine", "gemlike", "plugin_with_no_lib_dir", "stubby"].sort, @locator.plugins.map { |p| p.name }.sort
- end
-
- def test_should_find_plugins_only_under_the_plugin_paths_set_in_configuration
- @configuration.plugin_paths = [File.join(plugin_fixture_root_path, "default")]
- assert_equal ["acts_as_chunky_bacon", "gemlike", "plugin_with_no_lib_dir", "stubby"].sort, @locator.plugins.map { |p| p.name }.sort
-
- @configuration.plugin_paths = [File.join(plugin_fixture_root_path, "alternate")]
- assert_equal ["a"], @locator.plugins.map { |p| p.name }
- end
-
- def test_should_not_raise_any_error_and_return_no_plugins_if_the_plugin_path_value_does_not_exist
- @configuration.plugin_paths = ["some_missing_directory"]
- assert_nothing_raised do
- assert @locator.plugins.empty?
- end
- end
-end
diff --git a/railties/test/plugin_test.rb b/railties/test/plugin_test.rb
deleted file mode 100644
index 199adcfe39..0000000000
--- a/railties/test/plugin_test.rb
+++ /dev/null
@@ -1,174 +0,0 @@
-require 'plugin_test_helper'
-
-# TODO: Rewrite all these tests
-class FakeInitializerSlashApplication
- attr_reader :config
- alias configuration config
-
- def initialize
- @config = Rails::Configuration.new
- end
-end
-
-class PluginTest < Test::Unit::TestCase
- def setup
- @initializer = FakeInitializerSlashApplication.new
- @configuration = @initializer.config
- Rails.application = @initializer
- @valid_plugin_path = plugin_fixture_path('default/stubby')
- @empty_plugin_path = plugin_fixture_path('default/empty')
- @gemlike_plugin_path = plugin_fixture_path('default/gemlike')
- end
-
- def test_should_determine_plugin_name_from_the_directory_of_the_plugin
- assert_equal 'stubby', plugin_for(@valid_plugin_path).name
- assert_equal 'empty', plugin_for(@empty_plugin_path).name
- end
-
- def test_should_not_be_loaded_when_created
- assert !plugin_for(@valid_plugin_path).loaded?
- end
-
- def test_should_be_marked_as_loaded_when_load_is_called
- plugin = plugin_for(@valid_plugin_path)
- assert !plugin.loaded?
- plugin.stubs(:evaluate_init_rb)
- assert_nothing_raised do
- plugin.send(:load, anything)
- end
- assert plugin.loaded?
- end
-
- def test_should_determine_validity_of_given_path
- # This is a plugin path, with a lib dir
- assert plugin_for(@valid_plugin_path).valid?
- # This just has an init.rb and no lib dir
- assert plugin_for(plugin_fixture_path('default/plugin_with_no_lib_dir')).valid?
- # This would be a plugin path, but the directory is empty
- assert !plugin_for(plugin_fixture_path('default/empty')).valid?
- # This is a non sense path
- assert !plugin_for(plugin_fixture_path('default/this_directory_does_not_exist')).valid?
- end
-
- def test_should_return_empty_array_for_load_paths_when_plugin_has_no_lib_directory
- assert_equal [], plugin_for(plugin_fixture_path('default/plugin_with_no_lib_dir')).load_paths
- end
-
- def test_should_return_array_with_lib_path_for_load_paths_when_plugin_has_a_lib_directory
- expected_lib_dir = File.join(plugin_fixture_path('default/stubby'), 'lib')
- assert_equal [expected_lib_dir], plugin_for(plugin_fixture_path('default/stubby')).load_paths
- end
-
- def test_should_raise_a_load_error_when_trying_to_determine_the_load_paths_from_an_invalid_plugin
- assert_nothing_raised do
- plugin_for(@valid_plugin_path).load_paths
- end
-
- assert_raise(LoadError) do
- plugin_for(@empty_plugin_path).load_paths
- end
-
- assert_raise(LoadError) do
- plugin_for('this_is_not_a_plugin_directory').load_paths
- end
- end
-
- def test_should_raise_a_load_error_when_trying_to_load_an_invalid_plugin
- # This path is fine so nothing is raised
- assert_nothing_raised do
- plugin = plugin_for(@valid_plugin_path)
- plugin.stubs(:evaluate_init_rb)
- plugin.send(:load, @initializer)
- end
-
- # This path is fine so nothing is raised
- assert_nothing_raised do
- plugin = plugin_for(@gemlike_plugin_path)
- plugin.stubs(:evaluate_init_rb)
- plugin.send(:load, @initializer)
- end
-
- # This is an empty path so it raises
- assert_raise(LoadError) do
- plugin = plugin_for(@empty_plugin_path)
- plugin.stubs(:evaluate_init_rb)
- plugin.send(:load, @initializer)
- end
-
- assert_raise(LoadError) do
- plugin = plugin_for('this_is_not_a_plugin_directory')
- plugin.stubs(:evaluate_init_rb)
- plugin.send(:load, @initializer)
- end
- end
-
- def test_should_raise_a_load_error_when_trying_to_access_load_paths_of_an_invalid_plugin
- # This path is fine so nothing is raised
- assert_nothing_raised do
- plugin_for(@valid_plugin_path).load_paths
- end
-
- # This is an empty path so it raises
- assert_raise(LoadError) do
- plugin_for(@empty_plugin_path).load_paths
- end
-
- assert_raise(LoadError) do
- plugin_for('this_is_not_a_plugin_directory').load_paths
- end
- end
-
- def test_loading_a_plugin_gives_the_init_file_access_to_all_it_needs
- failure_tip = "Perhaps someone has written another test that loads this same plugin and therefore makes the StubbyMixin constant defined already."
- assert !defined?(StubbyMixin), failure_tip
- plugin = plugin_for(@valid_plugin_path)
- plugin.load_paths.each { |path| $LOAD_PATH.unshift(path) }
- # The init.rb of this plugin raises if it doesn't have access to all the things it needs
- assert_nothing_raised do
- plugin.load(@initializer)
- end
- assert defined?(StubbyMixin)
- end
-
- def test_should_sort_naturally_by_name
- a = plugin_for("path/a")
- b = plugin_for("path/b")
- z = plugin_for("path/z")
- assert_equal [a, b, z], [b, z, a].sort
- end
-
- def test_should_only_be_loaded_once
- plugin = plugin_for(@valid_plugin_path)
- assert !plugin.loaded?
- plugin.expects(:evaluate_init_rb)
- assert_nothing_raised do
- plugin.send(:load, @initializer)
- plugin.send(:load, @initializer)
- end
- assert plugin.loaded?
- end
-
- def test_should_make_about_yml_available_as_about_method_on_plugin
- plugin = plugin_for(@valid_plugin_path)
- assert_equal "Plugin Author", plugin.about['author']
- assert_equal "1.0.0", plugin.about['version']
- end
-
- def test_should_return_empty_hash_for_about_if_about_yml_is_missing
- assert_equal({}, plugin_for(about_yml_plugin_path('plugin_without_about_yaml')).about)
- end
-
- def test_should_return_empty_hash_for_about_if_about_yml_is_malformed
- assert_equal({}, plugin_for(about_yml_plugin_path('bad_about_yml')).about)
- end
-
- private
-
- def about_yml_plugin_path(name)
- File.join(File.dirname(__FILE__), 'fixtures', 'about_yml_plugins', name)
- end
-
- def plugin_for(path)
- Rails::Plugin.new(path)
- end
-end
diff --git a/railties/test/plugin_test_helper.rb b/railties/test/plugin_test_helper.rb
deleted file mode 100644
index 93004e0ddf..0000000000
--- a/railties/test/plugin_test_helper.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-$:.unshift File.dirname(__FILE__) + "/../lib"
-$:.unshift File.dirname(__FILE__) + "/../../activesupport/lib"
-
-require 'test/unit'
-require 'active_support'
-require 'rails/initializer'
-require 'abstract_unit'
-
-# We need to set RAILS_ROOT if it isn't already set
-RAILS_ROOT = '.' unless defined?(RAILS_ROOT)
-
-class Test::Unit::TestCase
- private
- def plugin_fixture_root_path
- File.expand_path(File.join(File.dirname(__FILE__), 'fixtures', 'plugins'))
- end
-
- def only_load_the_following_plugins!(plugins)
- @initializer.configuration.plugins = plugins
- end
-
- def plugin_fixture_path(path)
- File.join(plugin_fixture_root_path, path)
- end
-
- def assert_plugins(list_of_names, array_of_plugins, message=nil)
- assert_equal list_of_names.map { |n| n.to_s }, array_of_plugins.map { |p| p.name }, message
- end
-end
diff --git a/railties/test/plugins/vendored_test.rb b/railties/test/plugins/vendored_test.rb
index 71de542ff7..9a2d40cad8 100644
--- a/railties/test/plugins/vendored_test.rb
+++ b/railties/test/plugins/vendored_test.rb
@@ -1,19 +1,195 @@
require "isolation/abstract_unit"
-module ApplicationTests
- class PluginTest < Test::Unit::TestCase
+module PluginsTest
+ class VendoredTest < Test::Unit::TestCase
include ActiveSupport::Testing::Isolation
def setup
build_app
- end
- test "generates the plugin" do
- script "generate plugin my_plugin"
- File.open("#{app_path}/vendor/plugins/my_plugin/init.rb", 'w') do |f|
- f.puts "OMG = 'hello'"
+ @plugin = plugin "bukkits", "::LEVEL = config.log_level" do |plugin|
+ plugin.write "lib/bukkits.rb", "class Bukkits; end"
end
+ end
+
+ def boot_rails
+ super
+ require "#{app_path}/config/environment"
+ end
+
+ test "it loads the plugin's init.rb file" do
+ boot_rails
+ assert_equal "loaded", BUKKITS
+ end
+
+ test "the init.rb file has access to the config object" do
+ boot_rails
+ assert_equal :debug, LEVEL
+ end
+
+ test "the plugin puts its lib directory on the load path" do
+ boot_rails
+ require "bukkits"
+ assert_equal "Bukkits", Bukkits.name
+ end
+
+ test "plugin paths get added to the AS::Dependency list" do
+ boot_rails
+ assert_equal "Bukkits", Bukkits.name
+ end
+
+ test "plugin constants do not get reloaded by default" do
+ boot_rails
+ assert_equal "Bukkits", Bukkits.name
+ ActiveSupport::Dependencies.clear
+ @plugin.delete("lib/bukkits.rb")
+ assert_nothing_raised { Bukkits }
+ end
+
+ test "plugin constants get reloaded if config.reload_plugins is set" do
+ add_to_config <<-RUBY
+ config.reload_plugins = true
+ RUBY
+
+ boot_rails
+
+ assert_equal "Bukkits", Bukkits.name
+ ActiveSupport::Dependencies.clear
+ @plugin.delete("lib/bukkits.rb")
+ assert_raises(NameError) { Bukkits }
+ end
+
+ test "plugin should work without init.rb" do
+ @plugin.delete("init.rb")
+
+ boot_rails
+
+ require "bukkits"
+ assert_nothing_raised { Bukkits }
+ end
+
+ test "the plugin puts its models directory on the load path" do
+ @plugin.write "app/models/my_bukkit.rb", "class MyBukkit ; end"
+
+ boot_rails
+
+ assert_nothing_raised { MyBukkit }
+ end
+
+ test "the plugin puts is controllers directory on the load path" do
+ @plugin.write "app/controllers/bukkit_controller.rb", "class BukkitController ; end"
+
+ boot_rails
+
+ assert_nothing_raised { BukkitController }
+ end
+
+ test "the plugin adds its view to the load path" do
+ @plugin.write "app/controllers/bukkit_controller.rb", <<-RUBY
+ class BukkitController < ActionController::Base
+ def index
+ end
+ end
+ RUBY
+
+ @plugin.write "app/views/bukkit/index.html.erb", "Hello bukkits"
+
+ boot_rails
+
+ require "action_controller"
+ require "rack/mock"
+ response = BukkitController.action(:index).call(Rack::MockRequest.env_for("/"))
+ assert_equal "Hello bukkits\n", response[2].body
+ end
+
+ test "the plugin adds helpers to the controller's views" do
+ @plugin.write "app/controllers/bukkit_controller.rb", <<-RUBY
+ class BukkitController < ActionController::Base
+ def index
+ end
+ end
+ RUBY
+
+ @plugin.write "app/helpers/bukkit_helper.rb", <<-RUBY
+ module BukkitHelper
+ def bukkits
+ "bukkits"
+ end
+ end
+ RUBY
+
+ @plugin.write "app/views/bukkit/index.html.erb", "Hello <%= bukkits %>"
+
+ boot_rails
+
+ require "rack/mock"
+ response = BukkitController.action(:index).call(Rack::MockRequest.env_for("/"))
+ assert_equal "Hello bukkits\n", response[2].body
+ end
+
+ test "routes.rb are added to the router" do
+ @plugin.write "config/routes.rb", <<-RUBY
+ class Sprokkit
+ def self.call(env)
+ [200, {'Content-Type' => 'text/html'}, ["I am a Sprokkit"]]
+ end
+ end
+
+ ActionController::Routing::Routes.draw do
+ match "/sprokkit", :to => Sprokkit
+ end
+ RUBY
+
+ boot_rails
+ require "rack/mock"
+ response = Rails.application.call(Rack::MockRequest.env_for("/sprokkit"))
+ assert_equal "I am a Sprokkit", response[2].join
+ end
+ end
+
+ class VendoredOrderingTest < Test::Unit::TestCase
+ include ActiveSupport::Testing::Isolation
+
+ def setup
+ build_app
+ $arr = []
+ plugin "a_plugin", "$arr << :a"
+ plugin "b_plugin", "$arr << :b"
+ plugin "c_plugin", "$arr << :c"
+ end
+
+ def boot_rails
+ super
require "#{app_path}/config/environment"
end
+
+ test "plugins are loaded alphabetically by default" do
+ boot_rails
+ assert_equal [:a, :b, :c], $arr
+ end
+
+ test "if specified, only those plugins are loaded" do
+ add_to_config "config.plugins = [:b_plugin]"
+ boot_rails
+ assert_equal [:b], $arr
+ end
+
+ test "the plugins are initialized in the order they are specified" do
+ add_to_config "config.plugins = [:b_plugin, :a_plugin]"
+ boot_rails
+ assert_equal [:b, :a], $arr
+ end
+
+ test "if :all is specified, the remaining plugins are loaded in alphabetical order" do
+ add_to_config "config.plugins = [:c_plugin, :all]"
+ boot_rails
+ assert_equal [:c, :a, :b], $arr
+ end
+
+ test "if :all is at the beginning, it represents the plugins not otherwise specified" do
+ add_to_config "config.plugins = [:all, :b_plugin]"
+ boot_rails
+ assert_equal [:a, :c, :b], $arr
+ end
end
end \ No newline at end of file
diff --git a/railties/test/rails_info_controller_test.rb b/railties/test/rails_info_controller_test.rb
index a0484c0868..39f23fa0be 100644
--- a/railties/test/rails_info_controller_test.rb
+++ b/railties/test/rails_info_controller_test.rb
@@ -14,17 +14,12 @@ class InfoControllerTest < ActionController::TestCase
tests Rails::InfoController
def setup
- ActionController::Routing.use_controllers!(['rails/info'])
ActionController::Routing::Routes.draw do |map|
map.connect ':controller/:action/:id'
end
@controller.stubs(:consider_all_requests_local => false, :local_request? => true)
end
- def teardown
- ActionController::Routing.use_controllers! nil
- end
-
test "info controller does not allow remote requests" do
@controller.stubs(:consider_all_requests_local => false, :local_request? => false)
get :properties
diff --git a/railties/test/rails_info_test.rb b/railties/test/rails_info_test.rb
index dcf9966c0d..fc28d7e912 100644
--- a/railties/test/rails_info_test.rb
+++ b/railties/test/rails_info_test.rb
@@ -1,15 +1,4 @@
-$:.unshift File.dirname(__FILE__) + "/../lib"
-$:.unshift File.dirname(__FILE__) + "/../builtin/rails_info"
-$:.unshift File.dirname(__FILE__) + "/../../activesupport/lib"
-$:.unshift File.dirname(__FILE__) + "/../../actionpack/lib"
-
-require 'rubygems'
-gem 'rack', '~> 1.0.0'
-
-require 'test/unit'
-require 'active_support'
-require 'active_support/test_case'
-require 'action_controller'
+require 'abstract_unit'
unless defined?(Rails) && defined?(Rails::Info)
module Rails