aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Gemfile3
-rw-r--r--actionmailer/lib/action_mailer/base.rb26
-rw-r--r--actionpack/CHANGELOG50
-rw-r--r--actionpack/actionpack.gemspec2
-rw-r--r--actionpack/lib/action_controller/caching/fragments.rb1
-rw-r--r--actionpack/lib/action_controller/metal/http_authentication.rb6
-rw-r--r--actionpack/lib/action_controller/metal/params_wrapper.rb6
-rw-r--r--actionpack/lib/action_controller/metal/streaming.rb1
-rw-r--r--actionpack/lib/action_controller/record_identifier.rb2
-rw-r--r--actionpack/lib/action_controller/test_case.rb47
-rw-r--r--actionpack/lib/action_dispatch/middleware/cookies.rb15
-rw-r--r--actionpack/lib/action_dispatch/middleware/head.rb2
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb4
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/response.rb8
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb3
-rw-r--r--actionpack/lib/action_dispatch/testing/test_process.rb3
-rw-r--r--actionpack/lib/action_dispatch/testing/test_request.rb27
-rw-r--r--actionpack/lib/action_view.rb5
-rw-r--r--actionpack/lib/action_view/buffers.rb4
-rw-r--r--actionpack/lib/action_view/helpers/asset_paths.rb7
-rw-r--r--actionpack/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb11
-rw-r--r--actionpack/lib/action_view/helpers/cache_helper.rb8
-rw-r--r--actionpack/lib/action_view/helpers/controller_helper.rb2
-rw-r--r--actionpack/lib/action_view/helpers/debug_helper.rb2
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb4
-rw-r--r--actionpack/lib/action_view/helpers/form_options_helper.rb2
-rw-r--r--actionpack/lib/action_view/helpers/javascript_helper.rb2
-rw-r--r--actionpack/lib/action_view/helpers/number_helper.rb2
-rw-r--r--actionpack/lib/action_view/helpers/text_helper.rb3
-rw-r--r--actionpack/lib/action_view/helpers/url_helper.rb4
-rw-r--r--actionpack/lib/action_view/lookup_context.rb2
-rw-r--r--actionpack/lib/action_view/renderer/template_renderer.rb2
-rw-r--r--actionpack/lib/action_view/template/error.rb1
-rw-r--r--actionpack/lib/action_view/testing/resolvers.rb2
-rw-r--r--actionpack/lib/sprockets/helpers/rails_helper.rb66
-rw-r--r--actionpack/lib/sprockets/railtie.rb71
-rw-r--r--actionpack/test/abstract/abstract_controller_test.rb10
-rw-r--r--actionpack/test/abstract/callbacks_test.rb2
-rw-r--r--actionpack/test/abstract/layouts_test.rb12
-rw-r--r--actionpack/test/abstract_unit.rb1
-rw-r--r--actionpack/test/controller/integration_test.rb6
-rw-r--r--actionpack/test/controller/new_base/base_test.rb4
-rw-r--r--actionpack/test/controller/test_test.rb14
-rw-r--r--actionpack/test/dispatch/cookies_test.rb79
-rw-r--r--actionpack/test/dispatch/session/test_session_test.rb1
-rw-r--r--actionpack/test/dispatch/test_request_test.rb24
-rw-r--r--actionpack/test/fixtures/sprockets/app/javascripts/extra.js0
-rw-r--r--actionpack/test/fixtures/sprockets/app/stylesheets/extra.css0
-rw-r--r--actionpack/test/template/form_helper_test.rb10
-rw-r--r--actionpack/test/template/html-scanner/document_test.rb4
-rw-r--r--actionpack/test/template/javascript_helper_test.rb7
-rw-r--r--actionpack/test/template/record_tag_helper_test.rb2
-rw-r--r--actionpack/test/template/render_test.rb4
-rw-r--r--actionpack/test/template/sprockets_helper_test.rb12
-rw-r--r--actionpack/test/template/template_test.rb1
-rw-r--r--actionpack/test/template/text_helper_test.rb4
-rw-r--r--activemodel/CHANGELOG2
-rw-r--r--activemodel/lib/active_model/errors.rb2
-rw-r--r--activemodel/lib/active_model/mass_assignment_security.rb37
-rw-r--r--activemodel/lib/active_model/mass_assignment_security/permission_set.rb8
-rw-r--r--activemodel/lib/active_model/mass_assignment_security/sanitizer.rb43
-rw-r--r--activemodel/lib/active_model/naming.rb7
-rw-r--r--activemodel/lib/active_model/serializers/json.rb20
-rw-r--r--activemodel/lib/active_model/serializers/xml.rb4
-rw-r--r--activemodel/lib/active_model/translation.rb5
-rw-r--r--activemodel/lib/active_model/validations/exclusion.rb2
-rw-r--r--activemodel/lib/active_model/validations/inclusion.rb2
-rw-r--r--activemodel/lib/active_model/validations/length.rb6
-rw-r--r--activemodel/test/cases/mass_assignment_security/black_list_test.rb8
-rw-r--r--activemodel/test/cases/mass_assignment_security/sanitizer_test.rb27
-rw-r--r--activemodel/test/cases/mass_assignment_security/white_list_test.rb9
-rw-r--r--activemodel/test/cases/mass_assignment_security_test.rb20
-rw-r--r--activemodel/test/cases/translation_test.rb10
-rw-r--r--activerecord/CHANGELOG1
-rw-r--r--activerecord/README.rdoc18
-rw-r--r--activerecord/RUNNING_UNIT_TESTS39
-rwxr-xr-xactiverecord/Rakefile43
-rw-r--r--activerecord/lib/active_record/associations.rb16
-rw-r--r--activerecord/lib/active_record/associations/association.rb6
-rw-r--r--activerecord/lib/active_record/associations/association_scope.rb2
-rw-r--r--activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb4
-rw-r--r--activerecord/lib/active_record/associations/collection_association.rb49
-rw-r--r--activerecord/lib/active_record/associations/collection_proxy.rb12
-rw-r--r--activerecord/lib/active_record/associations/has_and_belongs_to_many_association.rb10
-rw-r--r--activerecord/lib/active_record/associations/has_many_association.rb9
-rw-r--r--activerecord/lib/active_record/associations/has_many_through_association.rb13
-rw-r--r--activerecord/lib/active_record/associations/has_one_association.rb2
-rw-r--r--activerecord/lib/active_record/attribute_methods/primary_key.rb2
-rw-r--r--activerecord/lib/active_record/base.rb4
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb4
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb4
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql_adapter.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb15
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb4
-rw-r--r--activerecord/lib/active_record/migration.rb2
-rw-r--r--activerecord/lib/active_record/migration/command_recorder.rb18
-rw-r--r--activerecord/lib/active_record/named_scope.rb2
-rw-r--r--activerecord/lib/active_record/persistence.rb2
-rw-r--r--activerecord/lib/active_record/relation.rb4
-rw-r--r--activerecord/lib/active_record/relation/calculations.rb4
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb15
-rw-r--r--activerecord/lib/active_record/schema_dumper.rb2
-rw-r--r--activerecord/lib/active_record/serialization.rb8
-rw-r--r--activerecord/lib/active_record/transactions.rb2
-rw-r--r--activerecord/lib/rails/generators/active_record/session_migration/templates/migration.rb6
-rw-r--r--activerecord/test/.gitignore1
-rw-r--r--activerecord/test/cases/adapter_test.rb9
-rw-r--r--activerecord/test/cases/adapters/firebird/migration_test.rb2
-rw-r--r--activerecord/test/cases/adapters/mysql/quoting_test.rb1
-rw-r--r--activerecord/test/cases/adapters/mysql2/reserved_word_test.rb4
-rw-r--r--activerecord/test/cases/adapters/postgresql/timestamp_test.rb30
-rw-r--r--activerecord/test/cases/associations/belongs_to_associations_test.rb9
-rw-r--r--activerecord/test/cases/associations/cascaded_eager_loading_test.rb10
-rw-r--r--activerecord/test/cases/associations/eager_test.rb12
-rw-r--r--activerecord/test/cases/associations/habtm_join_table_test.rb9
-rw-r--r--activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb25
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb19
-rw-r--r--activerecord/test/cases/associations/join_model_test.rb20
-rw-r--r--activerecord/test/cases/attribute_methods_test.rb7
-rw-r--r--activerecord/test/cases/base_test.rb7
-rw-r--r--activerecord/test/cases/fixtures/file_test.rb2
-rw-r--r--activerecord/test/cases/helper.rb22
-rw-r--r--activerecord/test/cases/i18n_test.rb1
-rw-r--r--activerecord/test/cases/identity_map_test.rb2
-rw-r--r--activerecord/test/cases/json_serialization_test.rb9
-rw-r--r--activerecord/test/cases/migration/command_recorder_test.rb12
-rw-r--r--activerecord/test/cases/named_scope_test.rb8
-rw-r--r--activerecord/test/cases/relation_scoping_test.rb24
-rw-r--r--activerecord/test/cases/relation_test.rb2
-rw-r--r--activerecord/test/cases/schema_dumper_test.rb1
-rw-r--r--activerecord/test/cases/timestamp_test.rb36
-rw-r--r--activerecord/test/config.example.yml136
-rw-r--r--activerecord/test/connections/jdbc_jdbcderby/connection.rb18
-rw-r--r--activerecord/test/connections/jdbc_jdbch2/connection.rb18
-rw-r--r--activerecord/test/connections/jdbc_jdbchsqldb/connection.rb18
-rw-r--r--activerecord/test/connections/jdbc_jdbcmysql/connection.rb26
-rw-r--r--activerecord/test/connections/jdbc_jdbcpostgresql/connection.rb26
-rw-r--r--activerecord/test/connections/jdbc_jdbcsqlite3/connection.rb25
-rw-r--r--activerecord/test/connections/native_db2/connection.rb25
-rw-r--r--activerecord/test/connections/native_firebird/connection.rb26
-rw-r--r--activerecord/test/connections/native_frontbase/connection.rb27
-rw-r--r--activerecord/test/connections/native_mysql/connection.rb25
-rw-r--r--activerecord/test/connections/native_mysql2/connection.rb25
-rw-r--r--activerecord/test/connections/native_openbase/connection.rb21
-rw-r--r--activerecord/test/connections/native_oracle/connection.rb35
-rw-r--r--activerecord/test/connections/native_postgresql/connection.rb21
-rw-r--r--activerecord/test/connections/native_sqlite3/connection.rb16
-rw-r--r--activerecord/test/connections/native_sqlite3_mem/connection.rb19
-rw-r--r--activerecord/test/connections/native_sybase/connection.rb23
-rw-r--r--activerecord/test/models/comment.rb3
-rw-r--r--activerecord/test/models/contract.rb15
-rw-r--r--activerecord/test/models/developer.rb5
-rw-r--r--activerecord/test/models/post.rb4
-rw-r--r--activerecord/test/support/config.rb39
-rw-r--r--activerecord/test/support/connection.rb20
-rw-r--r--activeresource/lib/active_resource/base.rb2
-rw-r--r--activeresource/lib/active_resource/schema.rb10
-rw-r--r--activeresource/test/cases/base/load_test.rb1
-rw-r--r--activeresource/test/cases/finder_test.rb2
-rw-r--r--activeresource/test/cases/log_subscriber_test.rb2
-rw-r--r--activeresource/test/cases/observing_test.rb2
-rw-r--r--activesupport/CHANGELOG5
-rw-r--r--activesupport/lib/active_support/cache/mem_cache_store.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/array/access.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/date/freeze.rb10
-rw-r--r--activesupport/lib/active_support/core_ext/kernel/reporting.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/module/delegation.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/string/output_safety.rb13
-rw-r--r--activesupport/lib/active_support/dependencies.rb2
-rw-r--r--activesupport/lib/active_support/ordered_hash.rb6
-rw-r--r--activesupport/lib/active_support/testing/performance.rb38
-rw-r--r--activesupport/lib/active_support/testing/performance/jruby.rb18
-rw-r--r--activesupport/lib/active_support/testing/performance/rubinius.rb22
-rw-r--r--activesupport/lib/active_support/testing/performance/ruby.rb6
-rw-r--r--activesupport/lib/active_support/testing/performance/ruby/mri.rb10
-rw-r--r--activesupport/lib/active_support/testing/performance/ruby/yarv.rb8
-rw-r--r--activesupport/lib/active_support/xml_mini/jdom.rb9
-rw-r--r--activesupport/test/core_ext/date_ext_test.rb6
-rw-r--r--activesupport/test/dependencies_test.rb2
-rw-r--r--activesupport/test/ordered_hash_test.rb23
-rw-r--r--activesupport/test/safe_buffer_test.rb12
-rw-r--r--activesupport/test/test_test.rb2
-rw-r--r--activesupport/test/xml_mini/jdom_engine_test.rb28
-rwxr-xr-xci/ci_build.rb17
-rw-r--r--load_paths.rb3
-rw-r--r--railties/CHANGELOG2
-rw-r--r--railties/guides/assets/images/radar.pngbin0 -> 19521 bytes
-rw-r--r--railties/guides/assets/images/vijaydev.jpgbin0 -> 4610 bytes
-rw-r--r--railties/guides/rails_guides/helpers.rb2
-rw-r--r--railties/guides/source/action_view_overview.textile109
-rw-r--r--railties/guides/source/active_record_basics.textile4
-rw-r--r--railties/guides/source/active_record_querying.textile36
-rw-r--r--railties/guides/source/active_record_validations_callbacks.textile8
-rw-r--r--railties/guides/source/active_support_core_extensions.textile8
-rw-r--r--railties/guides/source/ajax_on_rails.textile2
-rw-r--r--railties/guides/source/api_documentation_guidelines.textile8
-rw-r--r--railties/guides/source/asset_pipeline.textile42
-rw-r--r--railties/guides/source/caching_with_rails.textile10
-rw-r--r--railties/guides/source/command_line.textile149
-rw-r--r--railties/guides/source/configuring.textile160
-rw-r--r--railties/guides/source/contribute.textile6
-rw-r--r--railties/guides/source/contributing_to_ruby_on_rails.textile8
-rw-r--r--railties/guides/source/credits.html.erb24
-rw-r--r--railties/guides/source/form_helpers.textile2
-rw-r--r--railties/guides/source/generators.textile6
-rw-r--r--railties/guides/source/getting_started.textile2
-rw-r--r--railties/guides/source/i18n.textile2
-rw-r--r--railties/guides/source/initialization.textile623
-rw-r--r--railties/guides/source/layouts_and_rendering.textile2
-rw-r--r--railties/guides/source/migrations.textile8
-rw-r--r--railties/guides/source/performance_testing.textile2
-rw-r--r--railties/guides/source/rails_on_rack.textile12
-rw-r--r--railties/guides/source/routing.textile2
-rw-r--r--railties/guides/source/ruby_on_rails_guides_guidelines.textile4
-rw-r--r--railties/guides/source/testing.textile4
-rw-r--r--railties/lib/rails/application.rb4
-rw-r--r--railties/lib/rails/commands.rb2
-rw-r--r--railties/lib/rails/commands/benchmarker.rb6
-rw-r--r--railties/lib/rails/commands/profiler.rb6
-rw-r--r--railties/lib/rails/commands/server.rb2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt12
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css12
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/initializers/wrap_parameters.rb.tt4
-rw-r--r--railties/lib/rails/generators/rails/app/templates/test/performance/browsing_test.rb2
-rw-r--r--railties/lib/rails/generators/rails/assets/USAGE2
-rw-r--r--railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb2
-rw-r--r--railties/lib/rails/generators/rails/plugin_new/templates/Gemfile4
-rw-r--r--railties/lib/rails/generators/test_unit/performance/templates/performance_test.rb2
-rw-r--r--railties/lib/rails/railtie/configurable.rb2
-rw-r--r--railties/lib/rails/tasks/assets.rake11
-rw-r--r--railties/test/application/assets_test.rb4
-rw-r--r--railties/test/application/configuration_test.rb1
-rw-r--r--railties/test/application/console_test.rb6
-rw-r--r--railties/test/application/generators_test.rb4
-rw-r--r--railties/test/application/initializers/boot_test.rb6
-rw-r--r--railties/test/application/initializers/check_ruby_version_test.rb4
-rw-r--r--railties/test/application/initializers/frameworks_test.rb4
-rw-r--r--railties/test/application/initializers/hooks_test.rb4
-rw-r--r--railties/test/application/initializers/i18n_test.rb4
-rw-r--r--railties/test/application/initializers/load_path_test.rb4
-rw-r--r--railties/test/application/initializers/notifications_test.rb4
-rw-r--r--railties/test/application/loading_test.rb4
-rw-r--r--railties/test/application/middleware/best_practices_test.rb4
-rw-r--r--railties/test/application/middleware/cache_test.rb4
-rw-r--r--railties/test/application/middleware/remote_ip_test.rb4
-rw-r--r--railties/test/application/middleware/sendfile_test.rb4
-rw-r--r--railties/test/application/middleware/show_exceptions_test.rb4
-rw-r--r--railties/test/application/middleware_test.rb6
-rw-r--r--railties/test/application/paths_test.rb4
-rw-r--r--railties/test/application/rack/logger_test.rb4
-rw-r--r--railties/test/application/rackup_test.rb4
-rw-r--r--railties/test/application/rake_test.rb6
-rw-r--r--railties/test/application/routing_test.rb4
-rw-r--r--railties/test/application/runner_test.rb4
-rw-r--r--railties/test/application/test_test.rb4
-rw-r--r--railties/test/generators/plugin_new_generator_test.rb22
-rw-r--r--railties/test/isolation/abstract_unit.rb7
-rw-r--r--railties/test/railties/engine_test.rb4
-rw-r--r--railties/test/railties/mounted_engine_test.rb7
-rw-r--r--railties/test/railties/plugin_ordering_test.rb6
-rw-r--r--railties/test/railties/plugin_test.rb4
-rw-r--r--railties/test/railties/railtie_test.rb4
262 files changed, 2107 insertions, 1682 deletions
diff --git a/Gemfile b/Gemfile
index b4e85eafd3..f7ea906827 100644
--- a/Gemfile
+++ b/Gemfile
@@ -44,7 +44,8 @@ platforms :ruby do
gem "nokogiri", ">= 1.4.4"
group :test do
- gem "ruby-prof"
+ gem "ruby-prof" if RUBY_VERSION < "1.9.3"
+
end
# AR
gem "sqlite3", "~> 1.3.3"
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index 220cee3da1..ccc25c775b 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -22,16 +22,16 @@ module ActionMailer #:nodoc:
#
# Examples:
#
- # class Notifier < ActionMailer::Base
- # default :from => 'no-reply@example.com',
+ # class Notifier < ActionMailer::Base
+ # default :from => 'no-reply@example.com',
# :return_path => 'system@example.com'
#
- # def welcome(recipient)
- # @account = recipient
- # mail(:to => recipient.email_address_with_name,
- # :bcc => ["bcc@example.com", "Order Watcher <watcher@example.com>"])
- # end
- # end
+ # def welcome(recipient)
+ # @account = recipient
+ # mail(:to => recipient.email_address_with_name,
+ # :bcc => ["bcc@example.com", "Order Watcher <watcher@example.com>"])
+ # end
+ # end
#
# Within the mailer method, you have access to the following methods:
#
@@ -213,14 +213,14 @@ module ActionMailer #:nodoc:
# = Observing and Intercepting Mails
#
# Action Mailer provides hooks into the Mail observer and interceptor methods. These allow you to
- # register objects that are called during the mail delivery life cycle.
+ # register classes that are called during the mail delivery life cycle.
#
- # An observer object must implement the <tt>:delivered_email(message)</tt> method which will be
+ # An observer class must implement the <tt>:delivered_email(message)</tt> method which will be
# called once for every email sent after the email has been sent.
#
- # An interceptor object must implement the <tt>:delivering_email(message)</tt> method which will be
+ # An interceptor class must implement the <tt>:delivering_email(message)</tt> method which will be
# called before the email is sent, allowing you to make modifications to the email before it hits
- # the delivery agents. Your object should make any needed modifications directly to the passed
+ # the delivery agents. Your class should make any needed modifications directly to the passed
# in Mail::Message instance.
#
# = Default Hash
@@ -366,7 +366,7 @@ module ActionMailer #:nodoc:
end
# Register an Inteceptor which will be called before mail is sent.
- # Either a class or a string can be passed in as the Observer. If a string is passed in
+ # Either a class or a string can be passed in as the Interceptor. If a string is passed in
# it will be <tt>constantize</tt>d.
def register_interceptor(interceptor)
delivery_interceptor = (interceptor.is_a?(String) ? interceptor.constantize : interceptor)
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index 48b3e5bfff..42baf6f45f 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -1,3 +1,53 @@
+*Rails 3.2.0 (unreleased)*
+
+* Fix escape_js to work correctly with the new SafeBuffer restriction [Paul Gallagher]
+
+* Brought back alternative convention for namespaced models in i18n [thoefer]
+
+ Now the key can be either "namespace.model" or "namespace/model" until further deprecation.
+
+* It is prohibited to perform a in-place SafeBuffer mutation [tenderlove]
+
+ The old behavior of SafeBuffer allowed you to mutate string in place via
+ method like `sub!`. These methods can add unsafe strings to a safe buffer,
+ and the safe buffer will continue to be marked as safe.
+
+ An example problem would be something like this:
+
+ <%= link_to('hello world', @user).sub!(/hello/, params[:xss]) %>
+
+ In the above example, an untrusted string (`params[:xss]`) is added to the
+ safe buffer returned by `link_to`, and the untrusted content is successfully
+ sent to the client without being escaped. To prevent this from happening
+ `sub!` and other similar methods will now raise an exception when they are called on a safe buffer.
+
+ In addition to the in-place versions, some of the versions of these methods which return a copy of the string will incorrectly mark strings as safe. For example:
+
+ <%= link_to('hello world', @user).sub(/hello/, params[:xss]) %>
+
+ The new versions will now ensure that *all* strings returned by these methods on safe buffers are marked unsafe.
+
+ You can read more about this change in http://groups.google.com/group/rubyonrails-security/browse_thread/thread/2e516e7acc96c4fb
+
+* Refactor ActionController::TestCase cookies [Andrew White]
+
+ Assigning cookies for test cases should now use cookies[], e.g:
+
+ cookies[:email] = 'user@example.com'
+ get :index
+ assert_equal 'user@example.com', cookies[:email]
+
+ To clear the cookies, use clear, e.g:
+
+ cookies.clear
+ get :index
+ assert_nil cookies[:email]
+
+ We now no longer write out HTTP_COOKIE and the cookie jar is
+ persistent between requests so if you need to manipulate the environment
+ for your test you need to do it before the cookie jar is created.
+
+
*Rails 3.1.0 (unreleased)*
* Added 'ActionView::Helpers::FormHelper.fields_for_with_index', similar to fields_for but allows to have access to the current iteration index [Jorge Bejar]
diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec
index d7c8aeadd3..37a3d960f1 100644
--- a/actionpack/actionpack.gemspec
+++ b/actionpack/actionpack.gemspec
@@ -24,7 +24,7 @@ Gem::Specification.new do |s|
s.add_dependency('rack', '~> 1.3.0')
s.add_dependency('rack-test', '~> 0.6.0')
s.add_dependency('rack-mount', '~> 0.8.1')
- s.add_dependency('sprockets', '~> 2.0.0.beta.8')
+ s.add_dependency('sprockets', '~> 2.0.0.beta.10')
s.add_dependency('tzinfo', '~> 0.3.27')
s.add_dependency('erubis', '~> 2.7.0')
end
diff --git a/actionpack/lib/action_controller/caching/fragments.rb b/actionpack/lib/action_controller/caching/fragments.rb
index 0be04b70a1..2bdb23c4d7 100644
--- a/actionpack/lib/action_controller/caching/fragments.rb
+++ b/actionpack/lib/action_controller/caching/fragments.rb
@@ -109,7 +109,6 @@ module ActionController #:nodoc:
def expire_fragment(key, options = nil)
return unless cache_configured?
key = fragment_cache_key(key) unless key.is_a?(Regexp)
- message = nil
instrument_fragment_cache :expire_fragment, key do
if key.is_a?(Regexp)
diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb
index 2ad571b2b5..7420a5e7e9 100644
--- a/actionpack/lib/action_controller/metal/http_authentication.rb
+++ b/actionpack/lib/action_controller/metal/http_authentication.rb
@@ -106,7 +106,7 @@ module ActionController
module ControllerMethods
extend ActiveSupport::Concern
-
+
module ClassMethods
def http_basic_authenticate_with(options = {})
before_filter(options.except(:name, :password, :realm)) do
@@ -116,7 +116,7 @@ module ActionController
end
end
end
-
+
def authenticate_or_request_with_http_basic(realm = "Application", &login_procedure)
authenticate_with_http_basic(&login_procedure) || request_http_basic_authentication(realm)
end
@@ -423,7 +423,7 @@ module ActionController
# Returns an Array of [String, Hash] if a token is present.
# Returns nil if no token is found.
def token_and_options(request)
- if header = request.authorization.to_s[/^Token (.*)/]
+ if request.authorization.to_s[/^Token (.*)/]
values = Hash[$1.split(',').map do |value|
value.strip! # remove any spaces between commas and values
key, value = value.split(/\=\"?/) # split key=value pairs
diff --git a/actionpack/lib/action_controller/metal/params_wrapper.rb b/actionpack/lib/action_controller/metal/params_wrapper.rb
index 5500f88930..2d8afc3a78 100644
--- a/actionpack/lib/action_controller/metal/params_wrapper.rb
+++ b/actionpack/lib/action_controller/metal/params_wrapper.rb
@@ -64,7 +64,7 @@ module ActionController
# end
#
# will try to check if +Admin::User+ or +User+ model exists, and use it to
- # determine the wrapper key respectively. If both of the model doesn't exists,
+ # determine the wrapper key respectively. If both models don't exist,
# it will then fallback to use +user+ as the key.
module ParamsWrapper
extend ActiveSupport::Concern
@@ -88,14 +88,14 @@ module ActionController
# # wraps parameters into +params[:person]+ hash
#
# wrap_parameters Person
- # # wraps parameters by determine the wrapper key from Person class
+ # # wraps parameters by determining the wrapper key from Person class
# (+person+, in this case) and the list of attribute names
#
# wrap_parameters :include => [:username, :title]
# # wraps only +:username+ and +:title+ attributes from parameters.
#
# wrap_parameters false
- # # disable parameters wrapping for this controller altogether.
+ # # disables parameters wrapping for this controller altogether.
#
# ==== Options
# * <tt>:format</tt> - The list of formats in which the parameters wrapper
diff --git a/actionpack/lib/action_controller/metal/streaming.rb b/actionpack/lib/action_controller/metal/streaming.rb
index 3892a12407..0bb436a476 100644
--- a/actionpack/lib/action_controller/metal/streaming.rb
+++ b/actionpack/lib/action_controller/metal/streaming.rb
@@ -260,4 +260,3 @@ module ActionController #:nodoc:
end
end
end
- \ No newline at end of file
diff --git a/actionpack/lib/action_controller/record_identifier.rb b/actionpack/lib/action_controller/record_identifier.rb
index 2def78b51a..c11d676c5e 100644
--- a/actionpack/lib/action_controller/record_identifier.rb
+++ b/actionpack/lib/action_controller/record_identifier.rb
@@ -40,7 +40,7 @@ module ActionController
# dom_class(post, :edit) # => "edit_post"
# dom_class(Person, :edit) # => "edit_person"
def dom_class(record_or_class, prefix = nil)
- singular = ActiveModel::Naming.singular(record_or_class)
+ singular = ActiveModel::Naming.param_key(record_or_class)
prefix ? "#{prefix}#{JOIN}#{singular}" : singular
end
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index 2ca9bae073..d14bb666cc 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -175,10 +175,6 @@ module ActionController
end
def recycle!
- write_cookies!
- @env.delete('HTTP_COOKIE') if @cookies.blank?
- @env.delete('action_dispatch.cookies')
- @cookies = nil
@formats = nil
@env.delete_if { |k, v| k =~ /^(action_dispatch|rack)\.request/ }
@env.delete_if { |k, v| k =~ /^action_dispatch\.rescue/ }
@@ -186,6 +182,14 @@ module ActionController
@method = @request_method = nil
@fullpath = @ip = @remote_ip = nil
@env['action_dispatch.request.query_parameters'] = {}
+ @set_cookies ||= {}
+ @set_cookies.update(Hash[cookie_jar.instance_variable_get("@set_cookies").map{ |k,o| [k,o[:value]] }])
+ deleted_cookies = cookie_jar.instance_variable_get("@delete_cookies")
+ @set_cookies.reject!{ |k,v| deleted_cookies.include?(k) }
+ cookie_jar.update(rack_cookies)
+ cookie_jar.update(cookies)
+ cookie_jar.update(@set_cookies)
+ cookie_jar.recycle!
end
end
@@ -301,18 +305,17 @@ module ActionController
# For redirects within the same controller, you can even call follow_redirect and the redirect will be followed, triggering another
# action call which can then be asserted against.
#
- # == Manipulating the request collections
+ # == Manipulating session and cookie variables
#
- # The collections described above link to the response, so you can test if what the actions were expected to do happened. But
- # sometimes you also want to manipulate these collections in the incoming request. This is really only relevant for sessions
- # and cookies, though. For sessions, you just do:
+ # Sometimes you need to set up the session and cookie variables for a test.
+ # To do this just assign a value to the session or cookie collection:
#
- # @request.session[:key] = "value"
- # @request.cookies[:key] = "value"
+ # session[:key] = "value"
+ # cookies[:key] = "value"
#
- # To clear the cookies for a test just clear the request's cookies hash:
+ # To clear the cookies for a test just clear the cookie collection:
#
- # @request.cookies.clear
+ # cookies.clear
#
# == \Testing named routes
#
@@ -395,7 +398,26 @@ module ActionController
end
alias xhr :xml_http_request
+ def paramify_values(hash_or_array_or_value)
+ case hash_or_array_or_value
+ when Hash
+ hash_or_array_or_value.each do |key, value|
+ hash_or_array_or_value[key] = paramify_values(value)
+ end
+ when Array
+ hash_or_array_or_value.map {|i| paramify_values(i)}
+ when Rack::Test::UploadedFile
+ hash_or_array_or_value
+ else
+ hash_or_array_or_value.to_param
+ end
+ end
+
def process(action, parameters = nil, session = nil, flash = nil, http_method = 'GET')
+ # Ensure that numbers and symbols passed as params are converted to
+ # proper params, as is the case when engaging rack.
+ paramify_values(parameters)
+
# Sanity check for required instance variables so we can give an
# understandable error message.
%w(@routes @controller @request @response).each do |iv_name|
@@ -431,7 +453,6 @@ module ActionController
@controller.process_with_new_base_test(@request, @response)
@assigns = @controller.respond_to?(:view_assigns) ? @controller.view_assigns : {}
@request.session.delete('flash') if @request.session['flash'].blank?
- @request.cookies.merge!(@response.cookies)
@response
end
diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb
index 47c4bad489..8cee9ecdc4 100644
--- a/actionpack/lib/action_dispatch/middleware/cookies.rb
+++ b/actionpack/lib/action_dispatch/middleware/cookies.rb
@@ -1,4 +1,5 @@
-require "active_support/core_ext/object/blank"
+require 'active_support/core_ext/object/blank'
+require 'active_support/core_ext/hash/keys'
module ActionDispatch
class Request
@@ -129,7 +130,7 @@ module ActionDispatch
end
def update(other_hash)
- @cookies.update other_hash
+ @cookies.update other_hash.stringify_keys
self
end
@@ -185,6 +186,11 @@ module ActionDispatch
value
end
+ # Removes all cookies on the client machine by calling <tt>delete</tt> for each cookie
+ def clear(options = {})
+ @cookies.each_key{ |k| delete(k, options) }
+ end
+
# Returns a jar that'll automatically set the assigned cookies to have an expiration date 20 years from now. Example:
#
# cookies.permanent[:prefers_open_id] = true
@@ -222,6 +228,11 @@ module ActionDispatch
@delete_cookies.each { |k, v| ::Rack::Utils.delete_cookie_header!(headers, k, v) }
end
+ def recycle! #:nodoc:
+ @set_cookies.clear
+ @delete_cookies.clear
+ end
+
private
def write_cookie?(cookie)
diff --git a/actionpack/lib/action_dispatch/middleware/head.rb b/actionpack/lib/action_dispatch/middleware/head.rb
index 56e2d2f2a8..f1906a3ab3 100644
--- a/actionpack/lib/action_dispatch/middleware/head.rb
+++ b/actionpack/lib/action_dispatch/middleware/head.rb
@@ -8,7 +8,7 @@ module ActionDispatch
if env["REQUEST_METHOD"] == "HEAD"
env["REQUEST_METHOD"] = "GET"
env["rack.methodoverride.original_method"] = "HEAD"
- status, headers, body = @app.call(env)
+ status, headers, _ = @app.call(env)
[status, headers, []]
else
@app.call(env)
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 3999bd0a5e..ec76d1da1e 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -1423,7 +1423,9 @@ module ActionDispatch
end
def action_path(name, path = nil) #:nodoc:
- path || @scope[:path_names][name.to_sym] || name.to_s
+ # Ruby 1.8 can't transform empty strings to symbols
+ name = name.to_sym if name.is_a?(String) && !name.empty?
+ path || @scope[:path_names][name] || name.to_s
end
def prefix_name_for_action(as, action) #:nodoc:
diff --git a/actionpack/lib/action_dispatch/testing/assertions/response.rb b/actionpack/lib/action_dispatch/testing/assertions/response.rb
index 606b01893e..a2d639cd56 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/response.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/response.rb
@@ -60,11 +60,11 @@ module ActionDispatch
assert_response(:redirect, message)
return true if options == @response.location
- redirected_to_after_normalisation = normalize_argument_to_redirection(@response.location)
- options_after_normalisation = normalize_argument_to_redirection(options)
+ redirected_to_after_normalization = normalize_argument_to_redirection(@response.location)
+ options_after_normalization = normalize_argument_to_redirection(options)
- if redirected_to_after_normalisation != options_after_normalisation
- flunk "Expected response to be a redirect to <#{options_after_normalisation}> but was a redirect to <#{redirected_to_after_normalisation}>"
+ if redirected_to_after_normalization != options_after_normalization
+ flunk "Expected response to be a redirect to <#{options_after_normalization}> but was a redirect to <#{redirected_to_after_normalization}>"
end
end
diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb
index 9791ba58e2..aae5752c93 100644
--- a/actionpack/lib/action_dispatch/testing/integration.rb
+++ b/actionpack/lib/action_dispatch/testing/integration.rb
@@ -207,9 +207,6 @@ module ActionDispatch
"*/*;q=0.5"
unless defined? @named_routes_configured
- # install the named routes in this session instance.
- klass = singleton_class
-
# the helpers are made protected by default--we make them public for
# easier access during testing and troubleshooting.
@named_routes_configured = true
diff --git a/actionpack/lib/action_dispatch/testing/test_process.rb b/actionpack/lib/action_dispatch/testing/test_process.rb
index 397bda41d5..367c295cf5 100644
--- a/actionpack/lib/action_dispatch/testing/test_process.rb
+++ b/actionpack/lib/action_dispatch/testing/test_process.rb
@@ -1,3 +1,4 @@
+require 'action_dispatch/middleware/cookies'
require 'action_dispatch/middleware/flash'
require 'active_support/core_ext/hash/indifferent_access'
@@ -22,7 +23,7 @@ module ActionDispatch
end
def cookies
- @request.cookies.merge(@response.cookies).with_indifferent_access
+ @request.cookie_jar
end
def redirect_to_url
diff --git a/actionpack/lib/action_dispatch/testing/test_request.rb b/actionpack/lib/action_dispatch/testing/test_request.rb
index 822adb6a47..7280e9a93b 100644
--- a/actionpack/lib/action_dispatch/testing/test_request.rb
+++ b/actionpack/lib/action_dispatch/testing/test_request.rb
@@ -1,4 +1,5 @@
require 'active_support/core_ext/object/blank'
+require 'active_support/core_ext/hash/indifferent_access'
require 'active_support/core_ext/hash/reverse_merge'
require 'rack/utils'
@@ -14,18 +15,11 @@ module ActionDispatch
env = Rails.application.env_config.merge(env) if defined?(Rails.application)
super(DEFAULT_ENV.merge(env))
- @cookies = nil
self.host = 'test.host'
self.remote_addr = '0.0.0.0'
self.user_agent = 'Rails Testing'
end
- def env
- write_cookies!
- delete_nil_values!
- super
- end
-
def request_method=(method)
@env['REQUEST_METHOD'] = method.to_s.upcase
end
@@ -71,23 +65,10 @@ module ActionDispatch
@env['HTTP_ACCEPT'] = Array(mime_types).collect { |mime_type| mime_type.to_s }.join(",")
end
+ alias :rack_cookies :cookies
+
def cookies
- @cookies ||= super
+ @cookies ||= {}.with_indifferent_access
end
-
- private
- def write_cookies!
- unless @cookies.blank?
- @env['HTTP_COOKIE'] = @cookies.map { |name, value| escape_cookie(name, value) }.join('; ')
- end
- end
-
- def escape_cookie(name, value)
- "#{Rack::Utils.escape(name)}=#{Rack::Utils.escape(value)}"
- end
-
- def delete_nil_values!
- @env.delete_if { |k, v| v.nil? }
- end
end
end
diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb
index a67b61c1ef..78eddb7530 100644
--- a/actionpack/lib/action_view.rb
+++ b/actionpack/lib/action_view.rb
@@ -71,11 +71,6 @@ module ActionView
autoload :TemplateError
autoload :WrongEncodingError
end
-
- autoload_at "action_view/template" do
- autoload :TemplateHandler
- autoload :TemplateHandlers
- end
end
ENCODING_FLAG = '#.*coding[:=]\s*(\S+)[ \t]*'
diff --git a/actionpack/lib/action_view/buffers.rb b/actionpack/lib/action_view/buffers.rb
index 089fc68706..be7f65c2ce 100644
--- a/actionpack/lib/action_view/buffers.rb
+++ b/actionpack/lib/action_view/buffers.rb
@@ -35,9 +35,9 @@ module ActionView
def html_safe?
true
end
-
+
def html_safe
self
end
end
-end \ No newline at end of file
+end
diff --git a/actionpack/lib/action_view/helpers/asset_paths.rb b/actionpack/lib/action_view/helpers/asset_paths.rb
index 1bc5c9e003..9a99c3cf52 100644
--- a/actionpack/lib/action_view/helpers/asset_paths.rb
+++ b/actionpack/lib/action_view/helpers/asset_paths.rb
@@ -44,7 +44,12 @@ module ActionView
raise NotImplementedError
end
+ def rewrite_relative_url_root(source, relative_url_root)
+ relative_url_root && !source.starts_with?("#{relative_url_root}/") ? "#{relative_url_root}#{source}" : source
+ end
+
def rewrite_host_and_protocol(source, has_request)
+ source = rewrite_relative_url_root(source, controller.config.relative_url_root) if has_request
host = compute_asset_host(source)
if has_request && host && !is_uri?(host)
host = "#{controller.request.protocol}#{host}"
@@ -75,4 +80,4 @@ module ActionView
end
end
-end \ No newline at end of file
+end
diff --git a/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb b/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb
index cd0f8c8878..2d49823412 100644
--- a/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb
+++ b/actionpack/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb
@@ -85,17 +85,8 @@ module ActionView
end
end
end
-
- def rewrite_relative_url_root(source, relative_url_root)
- relative_url_root && !source.starts_with?("#{relative_url_root}/") ? "#{relative_url_root}#{source}" : source
- end
-
- def rewrite_host_and_protocol(source, has_request)
- source = rewrite_relative_url_root(source, controller.config.relative_url_root) if has_request
- super(source, has_request)
- end
end
end
end
-end \ No newline at end of file
+end
diff --git a/actionpack/lib/action_view/helpers/cache_helper.rb b/actionpack/lib/action_view/helpers/cache_helper.rb
index e81d03b537..b57617b3d1 100644
--- a/actionpack/lib/action_view/helpers/cache_helper.rb
+++ b/actionpack/lib/action_view/helpers/cache_helper.rb
@@ -51,7 +51,13 @@ module ActionView
# This dance is needed because Builder can't use capture
pos = output_buffer.length
yield
- fragment = output_buffer.slice!(pos..-1)
+ if output_buffer.is_a?(ActionView::OutputBuffer)
+ safe_output_buffer = output_buffer.to_str
+ fragment = safe_output_buffer.slice!(pos..-1)
+ self.output_buffer = ActionView::OutputBuffer.new(safe_output_buffer)
+ else
+ fragment = output_buffer.slice!(pos..-1)
+ end
controller.write_fragment(name, fragment, options)
end
end
diff --git a/actionpack/lib/action_view/helpers/controller_helper.rb b/actionpack/lib/action_view/helpers/controller_helper.rb
index e22331cb3c..db59bca159 100644
--- a/actionpack/lib/action_view/helpers/controller_helper.rb
+++ b/actionpack/lib/action_view/helpers/controller_helper.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/module/attr_internal'
+
module ActionView
module Helpers
# This module keeps all methods and behavior in ActionView
diff --git a/actionpack/lib/action_view/helpers/debug_helper.rb b/actionpack/lib/action_view/helpers/debug_helper.rb
index cd67851642..c0cc7d347c 100644
--- a/actionpack/lib/action_view/helpers/debug_helper.rb
+++ b/actionpack/lib/action_view/helpers/debug_helper.rb
@@ -30,7 +30,7 @@ module ActionView
begin
Marshal::dump(object)
"<pre class='debug_dump'>#{h(object.to_yaml).gsub(" ", "&nbsp; ")}</pre>".html_safe
- rescue Exception => e # errors from Marshal or YAML
+ rescue Exception # errors from Marshal or YAML
# Object couldn't be dumped, perhaps because of singleton methods -- this is the fallback
"<code class='debug_dump'>#{h(object.inspect)}</code>".html_safe
end
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index cb1c13912a..7ed949504d 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -202,13 +202,13 @@ module ActionView
#
# is equivalent to something like:
#
- # <%= form_for @post, :as => :post, :url => post_path(@post), :html => { :class => "new_post", :id => "new_post" } do |f| %>
+ # <%= form_for @post, :as => :post, :url => posts_path, :html => { :class => "new_post", :id => "new_post" } do |f| %>
# ...
# <% end %>
#
# You can also overwrite the individual conventions, like this:
#
- # <%= form_for(@post, :url => super_post_path(@post)) do |f| %>
+ # <%= form_for(@post, :url => super_posts_path) do |f| %>
# ...
# <% end %>
#
diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb
index 794132637c..6513edcf6e 100644
--- a/actionpack/lib/action_view/helpers/form_options_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_options_helper.rb
@@ -427,7 +427,7 @@ module ActionView
#
# Sample usage (Hash):
# grouped_options = {
- # 'North America' => [['United States','US], 'Canada'],
+ # 'North America' => [['United States','US'], 'Canada'],
# 'Europe' => ['Denmark','Germany','France']
# }
# grouped_options_for_select(grouped_options)
diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb
index d7228bab67..8a6f2e84be 100644
--- a/actionpack/lib/action_view/helpers/javascript_helper.rb
+++ b/actionpack/lib/action_view/helpers/javascript_helper.rb
@@ -18,7 +18,7 @@ module ActionView
# $('some_element').replaceWith('<%=j render 'some/element_template' %>');
def escape_javascript(javascript)
if javascript
- javascript.gsub(/(\\|<\/|\r\n|[\n\r"'])/) { JS_ESCAPE_MAP[$1] }
+ javascript.gsub(/(\\|<\/|\r\n|[\n\r"'])/) {|match| JS_ESCAPE_MAP[match] }
else
''
end
diff --git a/actionpack/lib/action_view/helpers/number_helper.rb b/actionpack/lib/action_view/helpers/number_helper.rb
index 63d13a0f0b..4dafb7739a 100644
--- a/actionpack/lib/action_view/helpers/number_helper.rb
+++ b/actionpack/lib/action_view/helpers/number_helper.rb
@@ -342,7 +342,7 @@ module ActionView
options[:strip_insignificant_zeros] = true if not options.key?(:strip_insignificant_zeros)
storage_units_format = I18n.translate(:'number.human.storage_units.format', :locale => options[:locale], :raise => true)
-
+
base = options[:prefix] == :si ? 1000 : 1024
if number.to_i < base
diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb
index 75422a343d..8f97eb7d75 100644
--- a/actionpack/lib/action_view/helpers/text_helper.rb
+++ b/actionpack/lib/action_view/helpers/text_helper.rb
@@ -258,11 +258,12 @@ module ActionView
text = ''.html_safe if text.nil?
start_tag = tag('p', html_options, true)
text = sanitize(text) unless options[:sanitize] == false
+ text = text.to_str
text.gsub!(/\r\n?/, "\n") # \r\n and \r -> \n
text.gsub!(/\n\n+/, "</p>\n\n#{start_tag}") # 2+ newline -> paragraph
text.gsub!(/([^\n]\n)(?=[^\n])/, '\1<br />') # 1 newline -> br
text.insert 0, start_tag
- text.html_safe.safe_concat("</p>")
+ text = ActiveSupport::SafeBuffer.new(text).safe_concat("</p>")
end
# Creates a Cycle object whose _to_s_ method cycles through elements of an
diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb
index 25411856cb..489b96856d 100644
--- a/actionpack/lib/action_view/helpers/url_helper.rb
+++ b/actionpack/lib/action_view/helpers/url_helper.rb
@@ -497,14 +497,14 @@ module ActionView
}.compact
extras = extras.empty? ? '' : '?' + ERB::Util.html_escape(extras.join('&'))
- email_address_obfuscated = email_address.dup
+ email_address_obfuscated = email_address.to_str
email_address_obfuscated.gsub!(/@/, html_options.delete("replace_at")) if html_options.key?("replace_at")
email_address_obfuscated.gsub!(/\./, html_options.delete("replace_dot")) if html_options.key?("replace_dot")
case encode
when "javascript"
string = ''
html = content_tag("a", name || email_address_obfuscated.html_safe, html_options.merge("href" => "mailto:#{email_address}#{extras}".html_safe))
- html = escape_javascript(html)
+ html = escape_javascript(html.to_str)
"document.write('#{html}');".each_byte do |c|
string << sprintf("%%%x", c)
end
diff --git a/actionpack/lib/action_view/lookup_context.rb b/actionpack/lib/action_view/lookup_context.rb
index f0ed3425de..560df15e82 100644
--- a/actionpack/lib/action_view/lookup_context.rb
+++ b/actionpack/lib/action_view/lookup_context.rb
@@ -10,7 +10,7 @@ module ActionView
# this key is generated just once during the request, it speeds up all cache accesses.
class LookupContext #:nodoc:
attr_accessor :prefixes
-
+
mattr_accessor :fallbacks
@@fallbacks = FallbackFileSystemResolver.instances
diff --git a/actionpack/lib/action_view/renderer/template_renderer.rb b/actionpack/lib/action_view/renderer/template_renderer.rb
index a09cef8fef..d04c00fd40 100644
--- a/actionpack/lib/action_view/renderer/template_renderer.rb
+++ b/actionpack/lib/action_view/renderer/template_renderer.rb
@@ -64,7 +64,7 @@ module ActionView
layout =~ /^\// ?
with_fallbacks { find_template(layout, nil, false, keys) } : find_template(layout, nil, false, keys)
end
- rescue ActionView::MissingTemplate => e
+ rescue ActionView::MissingTemplate
update_details(:formats => nil) do
raise unless template_exists?(layout)
end
diff --git a/actionpack/lib/action_view/template/error.rb b/actionpack/lib/action_view/template/error.rb
index d4448a7b33..587e37a84f 100644
--- a/actionpack/lib/action_view/template/error.rb
+++ b/actionpack/lib/action_view/template/error.rb
@@ -31,7 +31,6 @@ module ActionView
def initialize(paths, path, prefixes, partial, details, *)
@path = path
prefixes = Array.wrap(prefixes)
- display_paths = paths.compact.map{ |p| p.to_s.inspect }.join(", ")
template_type = if partial
"partial"
elsif path =~ /layouts/i
diff --git a/actionpack/lib/action_view/testing/resolvers.rb b/actionpack/lib/action_view/testing/resolvers.rb
index 773dfcbb1d..7afa2fa613 100644
--- a/actionpack/lib/action_view/testing/resolvers.rb
+++ b/actionpack/lib/action_view/testing/resolvers.rb
@@ -34,7 +34,7 @@ module ActionView #:nodoc:
templates << Template.new(source, _path, handler,
:virtual_path => path.virtual, :format => format, :updated_at => updated_at)
end
-
+
templates.sort_by {|t| -t.identifier.match(/^#{query}$/).captures.reject(&:blank?).size }
end
end
diff --git a/actionpack/lib/sprockets/helpers/rails_helper.rb b/actionpack/lib/sprockets/helpers/rails_helper.rb
index a99dcad81d..0b6bd8ca40 100644
--- a/actionpack/lib/sprockets/helpers/rails_helper.rb
+++ b/actionpack/lib/sprockets/helpers/rails_helper.rb
@@ -15,42 +15,48 @@ module Sprockets
end
end
- def javascript_include_tag(source, options = {})
+ def javascript_include_tag(*sources)
+ options = sources.extract_options!
debug = options.key?(:debug) ? options.delete(:debug) : debug_assets?
body = options.key?(:body) ? options.delete(:body) : false
- if debug && asset = asset_paths.asset_for(source, 'js')
- asset.to_a.map { |dep|
- javascript_include_tag(dep, :debug => false, :body => true)
- }.join("\n").html_safe
- else
- options = {
- 'type' => "text/javascript",
- 'src' => asset_path(source, 'js', body)
- }.merge(options.stringify_keys)
-
- content_tag 'script', "", options
- end
+ sources.collect do |source|
+ if debug && asset = asset_paths.asset_for(source, 'js')
+ asset.to_a.map { |dep|
+ javascript_include_tag(dep, :debug => false, :body => true)
+ }.join("\n").html_safe
+ else
+ tag_options = {
+ 'type' => "text/javascript",
+ 'src' => asset_path(source, 'js', body)
+ }.merge(options.stringify_keys)
+
+ content_tag 'script', "", tag_options
+ end
+ end.join("\n").html_safe
end
- def stylesheet_link_tag(source, options = {})
+ def stylesheet_link_tag(*sources)
+ options = sources.extract_options!
debug = options.key?(:debug) ? options.delete(:debug) : debug_assets?
body = options.key?(:body) ? options.delete(:body) : false
- if debug && asset = asset_paths.asset_for(source, 'css')
- asset.to_a.map { |dep|
- stylesheet_link_tag(dep, :debug => false, :body => true)
- }.join("\n").html_safe
- else
- options = {
- 'rel' => "stylesheet",
- 'type' => "text/css",
- 'media' => "screen",
- 'href' => asset_path(source, 'css', body)
- }.merge(options.stringify_keys)
-
- tag 'link', options
- end
+ sources.collect do |source|
+ if debug && asset = asset_paths.asset_for(source, 'css')
+ asset.to_a.map { |dep|
+ stylesheet_link_tag(dep, :debug => false, :body => true)
+ }.join("\n").html_safe
+ else
+ tag_options = {
+ 'rel' => "stylesheet",
+ 'type' => "text/css",
+ 'media' => "screen",
+ 'href' => asset_path(source, 'css', body)
+ }.merge(options.stringify_keys)
+
+ tag 'link', tag_options
+ end
+ end.join("\n").html_safe
end
private
@@ -61,13 +67,13 @@ module Sprockets
def asset_path(source, default_ext = nil, body = false)
source = source.logical_path if source.respond_to?(:logical_path)
- path = asset_paths.compute_public_path(source, 'assets', default_ext, true)
+ path = asset_paths.compute_public_path(source, Rails.application.config.assets.prefix, default_ext, true)
body ? "#{path}?body=1" : path
end
class AssetPaths < ActionView::Helpers::AssetPaths #:nodoc:
def compute_public_path(source, dir, ext=nil, include_host=true)
- super(source, 'assets', ext, include_host)
+ super(source, Rails.application.config.assets.prefix, ext, include_host)
end
def asset_for(source, ext)
diff --git a/actionpack/lib/sprockets/railtie.rb b/actionpack/lib/sprockets/railtie.rb
index 7b8a7ad3bb..4b497d142d 100644
--- a/actionpack/lib/sprockets/railtie.rb
+++ b/actionpack/lib/sprockets/railtie.rb
@@ -46,43 +46,48 @@ module Sprockets
end
protected
+ def asset_environment(app)
+ require "sprockets"
- def asset_environment(app)
- require "sprockets"
- assets = app.config.assets
- env = Sprockets::Environment.new(app.root.to_s)
- env.static_root = File.join(app.root.join("public"), assets.prefix)
- env.paths.concat assets.paths
- env.logger = Rails.logger
- env.js_compressor = expand_js_compressor(assets.js_compressor) if assets.compress
- env.css_compressor = expand_css_compressor(assets.css_compressor) if assets.compress
- env
- end
+ assets = app.config.assets
+
+ env = Sprockets::Environment.new(app.root.to_s)
+
+ env.static_root = File.join(app.root.join("public"), assets.prefix)
+ env.paths.concat assets.paths
+
+ env.logger = Rails.logger
+
+ env.js_compressor = expand_js_compressor(assets.js_compressor)
+ env.css_compressor = expand_css_compressor(assets.css_compressor)
- def expand_js_compressor(sym)
- case sym
- when :closure
- require 'closure-compiler'
- Closure::Compiler.new
- when :uglifier
- require 'uglifier'
- Uglifier.new
- when :yui
- require 'yui/compressor'
- YUI::JavaScriptCompressor.new
- else
- sym
+ env
end
- end
- def expand_css_compressor(sym)
- case sym
- when :yui
- require 'yui/compressor'
- YUI::CssCompressor.new
- else
- sym
+ def expand_js_compressor(sym)
+ case sym
+ when :closure
+ require 'closure-compiler'
+ Closure::Compiler.new
+ when :uglifier
+ require 'uglifier'
+ Uglifier.new
+ when :yui
+ require 'yui/compressor'
+ YUI::JavaScriptCompressor.new
+ else
+ sym
+ end
+ end
+
+ def expand_css_compressor(sym)
+ case sym
+ when :yui
+ require 'yui/compressor'
+ YUI::CssCompressor.new
+ else
+ sym
+ end
end
- end
end
end
diff --git a/actionpack/test/abstract/abstract_controller_test.rb b/actionpack/test/abstract/abstract_controller_test.rb
index 981c023d38..53712a60ec 100644
--- a/actionpack/test/abstract/abstract_controller_test.rb
+++ b/actionpack/test/abstract/abstract_controller_test.rb
@@ -178,12 +178,6 @@ module AbstractController
end
end
- class Me5 < WithLayouts
- def index
- render
- end
- end
-
class TestLayouts < ActiveSupport::TestCase
test "layouts are included" do
controller = Me4.new
@@ -241,11 +235,11 @@ module AbstractController
assert_dispatch ActionMissingRespondToActionController, "success", :ohai
end
- test "a method is available as an action if respond_to_action? returns true" do
+ test "a method is available as an action if method_for_action returns true" do
assert_dispatch RespondToActionController, "success", :index
end
- test "raises ActionNotFound if method is defined but respond_to_action? returns false" do
+ test "raises ActionNotFound if method is defined but method_for_action returns false" do
assert_raise(ActionNotFound) { RespondToActionController.new.process(:fail) }
end
end
diff --git a/actionpack/test/abstract/callbacks_test.rb b/actionpack/test/abstract/callbacks_test.rb
index 3bdde86291..5d1a703c55 100644
--- a/actionpack/test/abstract/callbacks_test.rb
+++ b/actionpack/test/abstract/callbacks_test.rb
@@ -131,7 +131,7 @@ module AbstractController
end
def authenticate
- @list = []
+ @list ||= []
@authenticated = "true"
end
end
diff --git a/actionpack/test/abstract/layouts_test.rb b/actionpack/test/abstract/layouts_test.rb
index 5ed6aa68b5..86208899f8 100644
--- a/actionpack/test/abstract/layouts_test.rb
+++ b/actionpack/test/abstract/layouts_test.rb
@@ -87,18 +87,6 @@ module AbstractControllerTests
end
end
- class WithSymbolReturningString < Base
- layout :no_hello
-
- def index
- render :template => ActionView::Template::Text.new("Hello missing symbol!")
- end
- private
- def no_hello
- nil
- end
- end
-
class WithSymbolReturningNil < Base
layout :nilz
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index 60534a9746..24d071df39 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -151,6 +151,7 @@ class BasicController
config.assets_dir = public_dir
config.javascripts_dir = "#{public_dir}/javascripts"
config.stylesheets_dir = "#{public_dir}/stylesheets"
+ config.assets = ActiveSupport::InheritableOptions.new({ :prefix => "assets" })
config
end
end
diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb
index 01dc2f2091..23709e44e2 100644
--- a/actionpack/test/controller/integration_test.rb
+++ b/actionpack/test/controller/integration_test.rb
@@ -492,6 +492,8 @@ class ApplicationIntegrationTest < ActionDispatch::IntegrationTest
end
routes.draw do
+ match '', :to => 'application_integration_test/test#index', :as => :empty_string
+
match 'foo', :to => 'application_integration_test/test#index', :as => :foo
match 'bar', :to => 'application_integration_test/test#index', :as => :bar
end
@@ -501,11 +503,15 @@ class ApplicationIntegrationTest < ActionDispatch::IntegrationTest
end
test "includes route helpers" do
+ assert_equal '/', empty_string_path
assert_equal '/foo', foo_path
assert_equal '/bar', bar_path
end
test "route helpers after controller access" do
+ get '/'
+ assert_equal '/', empty_string_path
+
get '/foo'
assert_equal '/foo', foo_path
diff --git a/actionpack/test/controller/new_base/base_test.rb b/actionpack/test/controller/new_base/base_test.rb
index 8fa5d20372..ed244513a5 100644
--- a/actionpack/test/controller/new_base/base_test.rb
+++ b/actionpack/test/controller/new_base/base_test.rb
@@ -40,7 +40,7 @@ module Dispatching
class ContainedEmptyController < ActionController::Base ; end
class ContainedSubEmptyController < ContainedEmptyController ; end
class ContainedNonDefaultPathController < ActionController::Base
- def self.controller_path; "i_am_extremly_not_default"; end
+ def self.controller_path; "i_am_extremely_not_default"; end
end
end
@@ -89,7 +89,7 @@ module Dispatching
end
test "namespaced non-default controller path" do
- assert_equal 'i_am_extremly_not_default', Submodule::ContainedNonDefaultPathController.controller_path
+ assert_equal 'i_am_extremely_not_default', Submodule::ContainedNonDefaultPathController.controller_path
assert_equal Submodule::ContainedNonDefaultPathController.controller_path, Submodule::ContainedNonDefaultPathController.new.controller_path
end
diff --git a/actionpack/test/controller/test_test.rb b/actionpack/test/controller/test_test.rb
index 5896222a0a..f48b73b63a 100644
--- a/actionpack/test/controller/test_test.rb
+++ b/actionpack/test/controller/test_test.rb
@@ -493,6 +493,16 @@ XML
)
end
+ def test_params_passing_with_fixnums
+ get :test_params, :page => {:name => "Page name", :month => 4, :year => 2004, :day => 6}
+ parsed_params = eval(@response.body)
+ assert_equal(
+ {'controller' => 'test_test/test', 'action' => 'test_params',
+ 'page' => {'name' => "Page name", 'month' => '4', 'year' => '2004', 'day' => '6'}},
+ parsed_params
+ )
+ end
+
def test_params_passing_with_frozen_values
assert_nothing_raised do
get :test_params, :frozen => 'icy'.freeze, :frozens => ['icy'.freeze].freeze
@@ -583,13 +593,13 @@ XML
end
def test_should_have_knowledge_of_client_side_cookie_state_even_if_they_are_not_set
- @request.cookies['foo'] = 'bar'
+ cookies['foo'] = 'bar'
get :no_op
assert_equal 'bar', cookies['foo']
end
def test_should_detect_if_cookie_is_deleted
- @request.cookies['foo'] = 'bar'
+ cookies['foo'] = 'bar'
get :delete_cookie
assert_nil cookies['foo']
end
diff --git a/actionpack/test/dispatch/cookies_test.rb b/actionpack/test/dispatch/cookies_test.rb
index e42c39f527..8e5fd97cc6 100644
--- a/actionpack/test/dispatch/cookies_test.rb
+++ b/actionpack/test/dispatch/cookies_test.rb
@@ -417,7 +417,7 @@ class CookiesTest < ActionController::TestCase
assert_cookie_header "user_name=; path=/; expires=Thu, 01-Jan-1970 00:00:00 GMT"
end
-
+
def test_cookies_hash_is_indifferent_access
get :symbol_key
assert_equal "david", cookies[:user_name]
@@ -430,54 +430,95 @@ class CookiesTest < ActionController::TestCase
def test_setting_request_cookies_is_indifferent_access
- @request.cookies.clear
- @request.cookies[:user_name] = "andrew"
+ cookies.clear
+ cookies[:user_name] = "andrew"
get :string_key_mock
- assert_equal "david", cookies[:user_name]
+ assert_equal "david", cookies['user_name']
- @request.cookies.clear
- @request.cookies['user_name'] = "andrew"
+ cookies.clear
+ cookies['user_name'] = "andrew"
get :symbol_key_mock
- assert_equal "david", cookies['user_name']
+ assert_equal "david", cookies[:user_name]
end
def test_cookies_retained_across_requests
get :symbol_key
- assert_equal "user_name=david; path=/", @response.headers["Set-Cookie"]
+ assert_cookie_header "user_name=david; path=/"
assert_equal "david", cookies[:user_name]
get :noop
assert_nil @response.headers["Set-Cookie"]
- assert_equal "user_name=david", @request.env['HTTP_COOKIE']
assert_equal "david", cookies[:user_name]
get :noop
assert_nil @response.headers["Set-Cookie"]
- assert_equal "user_name=david", @request.env['HTTP_COOKIE']
assert_equal "david", cookies[:user_name]
end
def test_cookies_can_be_cleared
get :symbol_key
- assert_equal "user_name=david; path=/", @response.headers["Set-Cookie"]
assert_equal "david", cookies[:user_name]
- @request.cookies.clear
+ cookies.clear
get :noop
- assert_nil @response.headers["Set-Cookie"]
- assert_nil @request.env['HTTP_COOKIE']
assert_nil cookies[:user_name]
get :symbol_key
- assert_equal "user_name=david; path=/", @response.headers["Set-Cookie"]
assert_equal "david", cookies[:user_name]
end
- def test_cookies_are_escaped
- @request.cookies[:user_ids] = '1;2'
+ def test_can_set_http_cookie_header
+ @request.env['HTTP_COOKIE'] = 'user_name=david'
+ get :noop
+ assert_equal 'david', cookies['user_name']
+ assert_equal 'david', cookies[:user_name]
+
+ get :noop
+ assert_equal 'david', cookies['user_name']
+ assert_equal 'david', cookies[:user_name]
+
+ @request.env['HTTP_COOKIE'] = 'user_name=andrew'
+ get :noop
+ assert_equal 'andrew', cookies['user_name']
+ assert_equal 'andrew', cookies[:user_name]
+ end
+
+ def test_can_set_request_cookies
+ @request.cookies['user_name'] = 'david'
+ get :noop
+ assert_equal 'david', cookies['user_name']
+ assert_equal 'david', cookies[:user_name]
+
+ get :noop
+ assert_equal 'david', cookies['user_name']
+ assert_equal 'david', cookies[:user_name]
+
+ @request.cookies[:user_name] = 'andrew'
+ get :noop
+ assert_equal 'andrew', cookies['user_name']
+ assert_equal 'andrew', cookies[:user_name]
+ end
+
+ def test_cookies_precedence_over_http_cookie
+ @request.env['HTTP_COOKIE'] = 'user_name=andrew'
+ get :authenticate
+ assert_equal 'david', cookies['user_name']
+ assert_equal 'david', cookies[:user_name]
+
+ get :noop
+ assert_equal 'david', cookies['user_name']
+ assert_equal 'david', cookies[:user_name]
+ end
+
+ def test_cookies_precedence_over_request_cookies
+ @request.cookies['user_name'] = 'andrew'
+ get :authenticate
+ assert_equal 'david', cookies['user_name']
+ assert_equal 'david', cookies[:user_name]
+
get :noop
- assert_equal "user_ids=1%3B2", @request.env['HTTP_COOKIE']
- assert_equal "1;2", cookies[:user_ids]
+ assert_equal 'david', cookies['user_name']
+ assert_equal 'david', cookies[:user_name]
end
private
diff --git a/actionpack/test/dispatch/session/test_session_test.rb b/actionpack/test/dispatch/session/test_session_test.rb
index 31ce97a25b..904398f563 100644
--- a/actionpack/test/dispatch/session/test_session_test.rb
+++ b/actionpack/test/dispatch/session/test_session_test.rb
@@ -29,7 +29,6 @@ class ActionController::TestSessionTest < ActiveSupport::TestCase
end
def test_clear_emptys_session
- params = {:one => 'one', :two => 'two'}
session = ActionController::TestSession.new({:one => 'one', :two => 'two'})
session.clear
assert_nil(session[:one])
diff --git a/actionpack/test/dispatch/test_request_test.rb b/actionpack/test/dispatch/test_request_test.rb
index 81a8c24525..aa115608ef 100644
--- a/actionpack/test/dispatch/test_request_test.rb
+++ b/actionpack/test/dispatch/test_request_test.rb
@@ -34,12 +34,24 @@ class TestRequestTest < ActiveSupport::TestCase
assert_equal({}, req.cookies)
assert_equal nil, req.env["HTTP_COOKIE"]
- req.cookies["user_name"] = "david"
- assert_equal({"user_name" => "david"}, req.cookies)
- assert_equal "user_name=david", req.env["HTTP_COOKIE"]
+ req.cookie_jar["user_name"] = "david"
+ assert_cookies({"user_name" => "david"}, req.cookie_jar)
- req.cookies["login"] = "XJ-122"
- assert_equal({"user_name" => "david", "login" => "XJ-122"}, req.cookies)
- assert_equal %w(login=XJ-122 user_name=david), req.env["HTTP_COOKIE"].split(/; /).sort
+ req.cookie_jar["login"] = "XJ-122"
+ assert_cookies({"user_name" => "david", "login" => "XJ-122"}, req.cookie_jar)
+
+ req.cookie_jar.delete(:login)
+ assert_cookies({"user_name" => "david"}, req.cookie_jar)
+
+ req.cookie_jar.clear
+ assert_cookies({}, req.cookie_jar)
+
+ req.cookie_jar.update(:user_name => "david")
+ assert_cookies({"user_name" => "david"}, req.cookie_jar)
end
+
+ private
+ def assert_cookies(expected, cookie_jar)
+ assert_equal(expected, cookie_jar.instance_variable_get("@cookies"))
+ end
end
diff --git a/actionpack/test/fixtures/sprockets/app/javascripts/extra.js b/actionpack/test/fixtures/sprockets/app/javascripts/extra.js
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/actionpack/test/fixtures/sprockets/app/javascripts/extra.js
diff --git a/actionpack/test/fixtures/sprockets/app/stylesheets/extra.css b/actionpack/test/fixtures/sprockets/app/stylesheets/extra.css
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/actionpack/test/fixtures/sprockets/app/stylesheets/extra.css
diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb
index f2a49f7a68..5296556fe6 100644
--- a/actionpack/test/template/form_helper_test.rb
+++ b/actionpack/test/template/form_helper_test.rb
@@ -696,13 +696,13 @@ class FormHelperTest < ActionView::TestCase
concat f.submit('Edit post')
end
- expected =
- "<form accept-charset='UTF-8' action='/posts/44' method='post'>" +
- snowman +
- "<label for='post_title'>The Title</label>" +
+ expected = whole_form("/posts/44", "edit_post_44" , "edit_post", :method => "put") do
"<input name='post[title]' size='30' type='text' id='post_title' value='And his name will be forty and four.' />" +
- "<input name='commit' id='post_submit' type='submit' value='Edit post' />" +
+ "<input name='commit' type='submit' value='Edit post' />" +
"</form>"
+ end
+
+ assert_dom_equal expected, output_buffer
end
def test_form_for_with_symbol_object_name
diff --git a/actionpack/test/template/html-scanner/document_test.rb b/actionpack/test/template/html-scanner/document_test.rb
index ddfb351595..3db2fba783 100644
--- a/actionpack/test/template/html-scanner/document_test.rb
+++ b/actionpack/test/template/html-scanner/document_test.rb
@@ -123,7 +123,7 @@ HTML
def test_parse_invalid_document
assert_nothing_raised do
- doc = HTML::Document.new("<html>
+ HTML::Document.new("<html>
<table>
<tr>
<td style=\"color: #FFFFFF; height: 17px; onclick=\"window.location.href='http://www.rmeinc.com/about_rme.aspx'\" style=\"cursor:pointer; height: 17px;\"; nowrap onclick=\"window.location.href='http://www.rmeinc.com/about_rme.aspx'\" onmouseout=\"this.bgColor='#0066cc'; this.style.color='#FFFFFF'\" onmouseover=\"this.bgColor='#ffffff'; this.style.color='#0033cc'\">About Us</td>
@@ -135,7 +135,7 @@ HTML
def test_invalid_document_raises_exception_when_strict
assert_raise RuntimeError do
- doc = HTML::Document.new("<html>
+ HTML::Document.new("<html>
<table>
<tr>
<td style=\"color: #FFFFFF; height: 17px; onclick=\"window.location.href='http://www.rmeinc.com/about_rme.aspx'\" style=\"cursor:pointer; height: 17px;\"; nowrap onclick=\"window.location.href='http://www.rmeinc.com/about_rme.aspx'\" onmouseout=\"this.bgColor='#0066cc'; this.style.color='#FFFFFF'\" onmouseover=\"this.bgColor='#ffffff'; this.style.color='#0033cc'\">About Us</td>
diff --git a/actionpack/test/template/javascript_helper_test.rb b/actionpack/test/template/javascript_helper_test.rb
index 538e0e9874..15bd6b4c47 100644
--- a/actionpack/test/template/javascript_helper_test.rb
+++ b/actionpack/test/template/javascript_helper_test.rb
@@ -30,6 +30,13 @@ class JavaScriptHelperTest < ActionView::TestCase
assert_equal %(dont <\\/close> tags), j(%(dont </close> tags))
end
+ def test_escape_javascript_with_safebuffer
+ given = %('quoted' "double-quoted" new-line:\n </closed>)
+ expect = %(\\'quoted\\' \\"double-quoted\\" new-line:\\n <\\/closed>)
+ assert_equal expect, escape_javascript(given)
+ assert_equal expect, escape_javascript(ActiveSupport::SafeBuffer.new(given))
+ end
+
def test_button_to_function
assert_dom_equal %(<input type="button" onclick="alert('Hello world!');" value="Greeting" />),
button_to_function("Greeting", "alert('Hello world!')")
diff --git a/actionpack/test/template/record_tag_helper_test.rb b/actionpack/test/template/record_tag_helper_test.rb
index 74d7bba4fe..1ba14e8bc9 100644
--- a/actionpack/test/template/record_tag_helper_test.rb
+++ b/actionpack/test/template/record_tag_helper_test.rb
@@ -48,14 +48,12 @@ class RecordTagHelperTest < ActionView::TestCase
end
def test_block_works_with_content_tag_for_in_erb
- __in_erb_template = ''
expected = %(<tr class="post" id="post_45">#{@post.body}</tr>)
actual = content_tag_for(:tr, @post) { concat @post.body }
assert_dom_equal expected, actual
end
def test_div_for_in_erb
- __in_erb_template = ''
expected = %(<div class="post bar" id="post_45">#{@post.body}</div>)
actual = div_for(@post, :class => "bar") { concat @post.body }
assert_dom_equal expected, actual
diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb
index 86d08a43a5..4187a0ac78 100644
--- a/actionpack/test/template/render_test.rb
+++ b/actionpack/test/template/render_test.rb
@@ -370,7 +370,7 @@ class LazyViewRenderTest < ActiveSupport::TestCase
def test_render_utf8_template_with_incompatible_external_encoding
with_external_encoding Encoding::SHIFT_JIS do
begin
- result = @view.render(:file => "test/utf8.html.erb", :layouts => "layouts/yield")
+ @view.render(:file => "test/utf8.html.erb", :layouts => "layouts/yield")
flunk 'Should have raised incompatible encoding error'
rescue ActionView::Template::Error => error
assert_match 'Your template was not saved as valid Shift_JIS', error.original_exception.message
@@ -381,7 +381,7 @@ class LazyViewRenderTest < ActiveSupport::TestCase
def test_render_utf8_template_with_partial_with_incompatible_encoding
with_external_encoding Encoding::SHIFT_JIS do
begin
- result = @view.render(:file => "test/utf8_magic_with_bare_partial.html.erb", :layouts => "layouts/yield")
+ @view.render(:file => "test/utf8_magic_with_bare_partial.html.erb", :layouts => "layouts/yield")
flunk 'Should have raised incompatible encoding error'
rescue ActionView::Template::Error => error
assert_match 'Your template was not saved as valid Shift_JIS', error.original_exception.message
diff --git a/actionpack/test/template/sprockets_helper_test.rb b/actionpack/test/template/sprockets_helper_test.rb
index b26315083c..b1317d0a35 100644
--- a/actionpack/test/template/sprockets_helper_test.rb
+++ b/actionpack/test/template/sprockets_helper_test.rb
@@ -57,6 +57,12 @@ class SprocketsHelperTest < ActionView::TestCase
asset_path("http://www.example.com/video/play.mp4")
end
+ test "asset path with relative url root" do
+ @controller.config.relative_url_root = "/collaboration/hieraki"
+ assert_equal "/collaboration/hieraki/images/logo.gif",
+ asset_path("/images/logo.gif")
+ end
+
test "javascript path" do
assert_equal "/assets/application-d41d8cd98f00b204e9800998ecf8427e.js",
asset_path(:application, "js")
@@ -88,6 +94,9 @@ class SprocketsHelperTest < ActionView::TestCase
assert_equal "<script src=\"/assets/xmlhr-d41d8cd98f00b204e9800998ecf8427e.js?body=1\" type=\"text/javascript\"></script>\n<script src=\"/assets/application-d41d8cd98f00b204e9800998ecf8427e.js?body=1\" type=\"text/javascript\"></script>",
javascript_include_tag(:application, :debug => true)
+
+ assert_equal "<script src=\"/assets/xmlhr-d41d8cd98f00b204e9800998ecf8427e.js\" type=\"text/javascript\"></script>\n<script src=\"/assets/extra-d41d8cd98f00b204e9800998ecf8427e.js\" type=\"text/javascript\"></script>",
+ javascript_include_tag("xmlhr", "extra")
end
test "stylesheet path" do
@@ -121,5 +130,8 @@ class SprocketsHelperTest < ActionView::TestCase
assert_equal "<link href=\"/assets/style-d41d8cd98f00b204e9800998ecf8427e.css?body=1\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n<link href=\"/assets/application-68b329da9893e34099c7d8ad5cb9c940.css?body=1\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />",
stylesheet_link_tag(:application, :debug => true)
+
+ assert_equal "<link href=\"/assets/style-d41d8cd98f00b204e9800998ecf8427e.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />\n<link href=\"/assets/extra-d41d8cd98f00b204e9800998ecf8427e.css\" media=\"screen\" rel=\"stylesheet\" type=\"text/css\" />",
+ stylesheet_link_tag("style", "extra")
end
end
diff --git a/actionpack/test/template/template_test.rb b/actionpack/test/template/template_test.rb
index 81fb34b80f..b0ca7de0b6 100644
--- a/actionpack/test/template/template_test.rb
+++ b/actionpack/test/template/template_test.rb
@@ -153,7 +153,6 @@ class TestERBTemplate < ActiveSupport::TestCase
def test_encoding_can_be_specified_with_magic_comment_in_erb
with_external_encoding Encoding::UTF_8 do
@template = new_template("<%# encoding: ISO-8859-1 %>hello \xFCmlat", :virtual_path => nil)
- result = render
assert_equal Encoding::UTF_8, render.encoding
assert_equal "hello \u{fc}mlat", render
end
diff --git a/actionpack/test/template/text_helper_test.rb b/actionpack/test/template/text_helper_test.rb
index 740f577a6e..5a43b5f864 100644
--- a/actionpack/test/template/text_helper_test.rb
+++ b/actionpack/test/template/text_helper_test.rb
@@ -291,7 +291,7 @@ class TextHelperTest < ActionView::TestCase
end
def test_cycle_class_with_no_arguments
- assert_raise(ArgumentError) { value = Cycle.new() }
+ assert_raise(ArgumentError) { Cycle.new }
end
def test_cycle
@@ -304,7 +304,7 @@ class TextHelperTest < ActionView::TestCase
end
def test_cycle_with_no_arguments
- assert_raise(ArgumentError) { value = cycle() }
+ assert_raise(ArgumentError) { cycle }
end
def test_cycle_resets_with_new_values
diff --git a/activemodel/CHANGELOG b/activemodel/CHANGELOG
index be4de2e53c..b1ad315c46 100644
--- a/activemodel/CHANGELOG
+++ b/activemodel/CHANGELOG
@@ -1,3 +1,5 @@
+* Provide mass_assignment_sanitizer as an easy API to replace the sanitizer behavior. Also support both :logger (default) and :strict sanitizer behavior [Bogdan Gusiev]
+
*Rails 3.1.0 (unreleased)*
* attr_accessible and friends now accepts :as as option to specify a role [Josh Kalderimis]
diff --git a/activemodel/lib/active_model/errors.rb b/activemodel/lib/active_model/errors.rb
index 0e2a2fd5e2..71ece15b71 100644
--- a/activemodel/lib/active_model/errors.rb
+++ b/activemodel/lib/active_model/errors.rb
@@ -248,7 +248,7 @@ module ActiveModel
#
# company = Company.create(:address => '123 First St.')
# company.errors.full_messages # =>
- # ["Name is too short (minimum is 5 characters)", "Name can't be blank", "Address can't be blank"]
+ # ["Name is too short (minimum is 5 characters)", "Name can't be blank", "Email can't be blank"]
def full_messages
map { |attribute, message|
if attribute == :base
diff --git a/activemodel/lib/active_model/mass_assignment_security.rb b/activemodel/lib/active_model/mass_assignment_security.rb
index 483b577681..a7b4706906 100644
--- a/activemodel/lib/active_model/mass_assignment_security.rb
+++ b/activemodel/lib/active_model/mass_assignment_security.rb
@@ -1,5 +1,7 @@
-require 'active_support/core_ext/class/attribute.rb'
+require 'active_support/core_ext/class/attribute'
+require 'active_support/core_ext/string/inflections'
require 'active_model/mass_assignment_security/permission_set'
+require 'active_model/mass_assignment_security/sanitizer'
module ActiveModel
# = Active Model Mass-Assignment Security
@@ -10,6 +12,9 @@ module ActiveModel
class_attribute :_accessible_attributes
class_attribute :_protected_attributes
class_attribute :_active_authorizer
+
+ class_attribute :_mass_assignment_sanitizer
+ self.mass_assignment_sanitizer = :logger
end
# Mass assignment security provides an interface for protecting attributes
@@ -41,6 +46,16 @@ module ActiveModel
#
# end
#
+ # = Configuration options
+ #
+ # * <tt>mass_assignment_sanitizer</tt> - Defines sanitize method. Possible values are:
+ # * <tt>:logger</tt> (default) - writes filtered attributes to logger
+ # * <tt>:strict</tt> - raise <tt>ActiveModel::MassAssignmentSecurity::Error</tt> on any protected attribute update
+ #
+ # You can specify your own sanitizer object eg. MySanitizer.new.
+ # See <tt>ActiveModel::MassAssignmentSecurity::LoggerSanitizer</tt> for example implementation.
+ #
+ #
module ClassMethods
# Attributes named in this macro are protected from mass-assignment
# whenever attributes are sanitized before assignment. A role for the
@@ -154,7 +169,7 @@ module ActiveModel
options = args.extract_options!
role = options[:as] || :default
- self._accessible_attributes = accessible_attributes_configs.dup
+ self._accessible_attributes = accessible_attributes_configs.dup
self._accessible_attributes[role] = self.accessible_attributes(role) + args
self._active_authorizer = self._accessible_attributes
@@ -177,21 +192,25 @@ module ActiveModel
[]
end
+ def mass_assignment_sanitizer=(value)
+ self._mass_assignment_sanitizer = if value.is_a?(Symbol)
+ const_get(:"#{value.to_s.camelize}Sanitizer").new(self)
+ else
+ value
+ end
+ end
+
private
def protected_attributes_configs
self._protected_attributes ||= begin
- default_black_list = BlackList.new(attributes_protected_by_default).tap do |w|
- w.logger = self.logger if self.respond_to?(:logger)
- end
- Hash.new(default_black_list)
+ Hash.new { |h,k| h[k] = BlackList.new(attributes_protected_by_default) }
end
end
def accessible_attributes_configs
self._accessible_attributes ||= begin
- default_white_list = WhiteList.new.tap { |w| w.logger = self.logger if self.respond_to?(:logger) }
- Hash.new(default_white_list)
+ Hash.new { |h,k| h[k] = WhiteList.new }
end
end
end
@@ -199,7 +218,7 @@ module ActiveModel
protected
def sanitize_for_mass_assignment(attributes, role = :default)
- mass_assignment_authorizer(role).sanitize(attributes)
+ _mass_assignment_sanitizer.sanitize(attributes, mass_assignment_authorizer(role))
end
def mass_assignment_authorizer(role = :default)
diff --git a/activemodel/lib/active_model/mass_assignment_security/permission_set.rb b/activemodel/lib/active_model/mass_assignment_security/permission_set.rb
index 9fcb94d48a..a1fcdf1a38 100644
--- a/activemodel/lib/active_model/mass_assignment_security/permission_set.rb
+++ b/activemodel/lib/active_model/mass_assignment_security/permission_set.rb
@@ -1,10 +1,8 @@
require 'set'
-require 'active_model/mass_assignment_security/sanitizer'
module ActiveModel
module MassAssignmentSecurity
class PermissionSet < Set
- attr_accessor :logger
def +(values)
super(values.map(&:to_s))
@@ -14,6 +12,10 @@ module ActiveModel
super(remove_multiparameter_id(key))
end
+ def deny?(key)
+ raise NotImplementedError, "#deny?(key) suppose to be overwritten"
+ end
+
protected
def remove_multiparameter_id(key)
@@ -22,7 +24,6 @@ module ActiveModel
end
class WhiteList < PermissionSet
- include Sanitizer
def deny?(key)
!include?(key)
@@ -30,7 +31,6 @@ module ActiveModel
end
class BlackList < PermissionSet
- include Sanitizer
def deny?(key)
include?(key)
diff --git a/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb b/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb
index 150beb1ff2..ee43a6694f 100644
--- a/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb
+++ b/activemodel/lib/active_model/mass_assignment_security/sanitizer.rb
@@ -1,9 +1,14 @@
+require 'active_support/core_ext/module/delegation'
+
module ActiveModel
module MassAssignmentSecurity
- module Sanitizer
+ class Sanitizer
+ def initialize(target=nil)
+ end
+
# Returns all attributes not denied by the authorizer.
- def sanitize(attributes)
- sanitized_attributes = attributes.reject { |key, value| deny?(key) }
+ def sanitize(attributes, authorizer)
+ sanitized_attributes = attributes.reject { |key, value| authorizer.deny?(key) }
debug_protected_attribute_removal(attributes, sanitized_attributes)
sanitized_attributes
end
@@ -12,12 +17,38 @@ module ActiveModel
def debug_protected_attribute_removal(attributes, sanitized_attributes)
removed_keys = attributes.keys - sanitized_attributes.keys
- warn!(removed_keys) if removed_keys.any?
+ process_removed_attributes(removed_keys) if removed_keys.any?
+ end
+
+ def process_removed_attributes(attrs)
+ raise NotImplementedError, "#process_removed_attributes(attrs) suppose to be overwritten"
+ end
+ end
+
+ class LoggerSanitizer < Sanitizer
+ delegate :logger, :to => :@target
+
+ def initialize(target)
+ @target = target
+ super
end
- def warn!(attrs)
- self.logger.debug "WARNING: Can't mass-assign protected attributes: #{attrs.join(', ')}" if self.logger
+ def logger?
+ @target.respond_to?(:logger) && @target.logger
end
+
+ def process_removed_attributes(attrs)
+ logger.debug "WARNING: Can't mass-assign protected attributes: #{attrs.join(', ')}" if logger?
+ end
+ end
+
+ class StrictSanitizer < Sanitizer
+ def process_removed_attributes(attrs)
+ raise ActiveModel::MassAssignmentSecurity::Error, "Can't mass-assign protected attributes: #{attrs.join(', ')}"
+ end
+ end
+
+ class Error < StandardError
end
end
end
diff --git a/activemodel/lib/active_model/naming.rb b/activemodel/lib/active_model/naming.rb
index 4c1a82f413..c7b9c41f46 100644
--- a/activemodel/lib/active_model/naming.rb
+++ b/activemodel/lib/active_model/naming.rb
@@ -21,7 +21,7 @@ module ActiveModel
@partial_path = "#{@collection}/#{@element}".freeze
@param_key = (namespace ? _singularize(@unnamespaced) : @singular).freeze
@route_key = (namespace ? ActiveSupport::Inflector.pluralize(@param_key) : @plural).freeze
- @i18n_key = self.underscore.to_sym
+ @i18n_key = self.underscore.tr('/', '.').to_sym
end
# Transform the model name into a more humane format, using I18n. By default,
@@ -35,8 +35,9 @@ module ActiveModel
@klass.respond_to?(:i18n_scope)
defaults = @klass.lookup_ancestors.map do |klass|
- klass.model_name.i18n_key
- end
+ [klass.model_name.i18n_key,
+ klass.model_name.i18n_key.to_s.tr('.', '/').to_sym]
+ end.flatten
defaults << options[:default] if options[:default]
defaults << @human
diff --git a/activemodel/lib/active_model/serializers/json.rb b/activemodel/lib/active_model/serializers/json.rb
index 0bfbf2aa06..0405705b35 100644
--- a/activemodel/lib/active_model/serializers/json.rb
+++ b/activemodel/lib/active_model/serializers/json.rb
@@ -22,13 +22,13 @@ module ActiveModel
# of +as_json+. If true (the default) +as_json+ will emit a single root
# node named after the object's type. For example:
#
- # konata = User.find(1)
- # konata.as_json
+ # user = User.find(1)
+ # user.as_json
# # => { "user": {"id": 1, "name": "Konata Izumi", "age": 16,
# "created_at": "2006/08/01", "awesome": true} }
#
# ActiveRecord::Base.include_root_in_json = false
- # konata.as_json
+ # user.as_json
# # => {"id": 1, "name": "Konata Izumi", "age": 16,
# "created_at": "2006/08/01", "awesome": true}
#
@@ -38,30 +38,30 @@ module ActiveModel
# Without any +options+, the returned JSON string will include all the model's
# attributes. For example:
#
- # konata = User.find(1)
- # konata.as_json
+ # user = User.find(1)
+ # user.as_json
# # => {"id": 1, "name": "Konata Izumi", "age": 16,
# "created_at": "2006/08/01", "awesome": true}
#
# The <tt>:only</tt> and <tt>:except</tt> options can be used to limit the attributes
# included, and work similar to the +attributes+ method. For example:
#
- # konata.as_json(:only => [ :id, :name ])
+ # user.as_json(:only => [ :id, :name ])
# # => {"id": 1, "name": "Konata Izumi"}
#
- # konata.as_json(:except => [ :id, :created_at, :age ])
+ # user.as_json(:except => [ :id, :created_at, :age ])
# # => {"name": "Konata Izumi", "awesome": true}
#
# To include the result of some method calls on the model use <tt>:methods</tt>:
#
- # konata.as_json(:methods => :permalink)
+ # user.as_json(:methods => :permalink)
# # => {"id": 1, "name": "Konata Izumi", "age": 16,
# "created_at": "2006/08/01", "awesome": true,
# "permalink": "1-konata-izumi"}
#
# To include associations use <tt>:include</tt>:
#
- # konata.as_json(:include => :posts)
+ # user.as_json(:include => :posts)
# # => {"id": 1, "name": "Konata Izumi", "age": 16,
# "created_at": "2006/08/01", "awesome": true,
# "posts": [{"id": 1, "author_id": 1, "title": "Welcome to the weblog"},
@@ -69,7 +69,7 @@ module ActiveModel
#
# Second level and higher order associations work as well:
#
- # konata.as_json(:include => { :posts => {
+ # user.as_json(:include => { :posts => {
# :include => { :comments => {
# :only => :body } },
# :only => :title } })
diff --git a/activemodel/lib/active_model/serializers/xml.rb b/activemodel/lib/active_model/serializers/xml.rb
index f6aae24324..9812af43d6 100644
--- a/activemodel/lib/active_model/serializers/xml.rb
+++ b/activemodel/lib/active_model/serializers/xml.rb
@@ -139,8 +139,8 @@ module ActiveModel
# Without any +options+, the returned XML string will include all the model's
# attributes. For example:
#
- # konata = User.find(1)
- # konata.to_xml
+ # user = User.find(1)
+ # user.to_xml
#
# <?xml version="1.0" encoding="UTF-8"?>
# <user>
diff --git a/activemodel/lib/active_model/translation.rb b/activemodel/lib/active_model/translation.rb
index 6d64c81b5f..c615311692 100644
--- a/activemodel/lib/active_model/translation.rb
+++ b/activemodel/lib/active_model/translation.rb
@@ -44,8 +44,9 @@ module ActiveModel
# Specify +options+ with additional translating options.
def human_attribute_name(attribute, options = {})
defaults = lookup_ancestors.map do |klass|
- :"#{self.i18n_scope}.attributes.#{klass.model_name.i18n_key}.#{attribute}"
- end
+ [:"#{self.i18n_scope}.attributes.#{klass.model_name.i18n_key}.#{attribute}",
+ :"#{self.i18n_scope}.attributes.#{klass.model_name.i18n_key.to_s.tr('.', '/')}.#{attribute}"]
+ end.flatten
defaults << :"attributes.#{attribute}"
defaults << options.delete(:default) if options[:default]
diff --git a/activemodel/lib/active_model/validations/exclusion.rb b/activemodel/lib/active_model/validations/exclusion.rb
index ab4de3c459..d3b8d31502 100644
--- a/activemodel/lib/active_model/validations/exclusion.rb
+++ b/activemodel/lib/active_model/validations/exclusion.rb
@@ -1,4 +1,4 @@
-require 'active_support/core_ext/range.rb'
+require 'active_support/core_ext/range'
module ActiveModel
diff --git a/activemodel/lib/active_model/validations/inclusion.rb b/activemodel/lib/active_model/validations/inclusion.rb
index bfb65d2f3f..9a9270d615 100644
--- a/activemodel/lib/active_model/validations/inclusion.rb
+++ b/activemodel/lib/active_model/validations/inclusion.rb
@@ -1,4 +1,4 @@
-require 'active_support/core_ext/range.rb'
+require 'active_support/core_ext/range'
module ActiveModel
diff --git a/activemodel/lib/active_model/validations/length.rb b/activemodel/lib/active_model/validations/length.rb
index 48d14978fa..144e73904e 100644
--- a/activemodel/lib/active_model/validations/length.rb
+++ b/activemodel/lib/active_model/validations/length.rb
@@ -62,14 +62,14 @@ module ActiveModel
# Validates that the specified attribute matches the length restrictions supplied. Only one option can be used at a time:
#
# class Person < ActiveRecord::Base
- # validates_length_of :first_name, :maximum=>30
- # validates_length_of :last_name, :maximum=>30, :message=>"less than 30 if you don't mind"
+ # validates_length_of :first_name, :maximum => 30
+ # validates_length_of :last_name, :maximum => 30, :message => "less than 30 if you don't mind"
# validates_length_of :fax, :in => 7..32, :allow_nil => true
# validates_length_of :phone, :in => 7..32, :allow_blank => true
# validates_length_of :user_name, :within => 6..20, :too_long => "pick a shorter name", :too_short => "pick a longer name"
# validates_length_of :zip_code, :minimum => 5, :too_short => "please enter at least 5 characters"
# validates_length_of :smurf_leader, :is => 4, :message => "papa is spelled with 4 characters... don't play me."
- # validates_length_of :essay, :minimum => 100, :too_short => "Your essay must be at least 100 words."), :tokenizer => lambda {|str| str.scan(/\w+/) }
+ # validates_length_of :essay, :minimum => 100, :too_short => "Your essay must be at least 100 words.", :tokenizer => lambda { |str| str.scan(/\w+/) }
# end
#
# Configuration options:
diff --git a/activemodel/test/cases/mass_assignment_security/black_list_test.rb b/activemodel/test/cases/mass_assignment_security/black_list_test.rb
index ed168bc016..0ec7f8719c 100644
--- a/activemodel/test/cases/mass_assignment_security/black_list_test.rb
+++ b/activemodel/test/cases/mass_assignment_security/black_list_test.rb
@@ -16,13 +16,5 @@ class BlackListTest < ActiveModel::TestCase
assert_equal false, @black_list.deny?('first_name')
end
- test "sanitize attributes" do
- original_attributes = { 'first_name' => 'allowed', 'admin' => 'denied', 'admin(1)' => 'denied' }
- attributes = @black_list.sanitize(original_attributes)
-
- assert attributes.key?('first_name'), "Allowed key shouldn't be rejected"
- assert !attributes.key?('admin'), "Denied key should be rejected"
- assert !attributes.key?('admin(1)'), "Multi-parameter key should be detected"
- end
end
diff --git a/activemodel/test/cases/mass_assignment_security/sanitizer_test.rb b/activemodel/test/cases/mass_assignment_security/sanitizer_test.rb
index 9a73a5ad91..62a6ec9c9b 100644
--- a/activemodel/test/cases/mass_assignment_security/sanitizer_test.rb
+++ b/activemodel/test/cases/mass_assignment_security/sanitizer_test.rb
@@ -3,36 +3,41 @@ require 'logger'
require 'active_support/core_ext/object/inclusion'
class SanitizerTest < ActiveModel::TestCase
+ attr_accessor :logger
- class SanitizingAuthorizer
- include ActiveModel::MassAssignmentSecurity::Sanitizer
-
- attr_accessor :logger
-
+ class Authorizer < ActiveModel::MassAssignmentSecurity::PermissionSet
def deny?(key)
key.in?(['admin'])
end
-
end
def setup
- @sanitizer = SanitizingAuthorizer.new
+ @logger_sanitizer = ActiveModel::MassAssignmentSecurity::LoggerSanitizer.new(self)
+ @strict_sanitizer = ActiveModel::MassAssignmentSecurity::StrictSanitizer.new(self)
+ @authorizer = Authorizer.new
end
test "sanitize attributes" do
original_attributes = { 'first_name' => 'allowed', 'admin' => 'denied' }
- attributes = @sanitizer.sanitize(original_attributes)
+ attributes = @logger_sanitizer.sanitize(original_attributes, @authorizer)
assert attributes.key?('first_name'), "Allowed key shouldn't be rejected"
assert !attributes.key?('admin'), "Denied key should be rejected"
end
- test "debug mass assignment removal" do
+ test "debug mass assignment removal with LoggerSanitizer" do
original_attributes = { 'first_name' => 'allowed', 'admin' => 'denied' }
log = StringIO.new
- @sanitizer.logger = Logger.new(log)
- @sanitizer.sanitize(original_attributes)
+ self.logger = Logger.new(log)
+ @logger_sanitizer.sanitize(original_attributes, @authorizer)
assert_match(/admin/, log.string, "Should log removed attributes: #{log.string}")
end
+ test "debug mass assignment removal with StrictSanitizer" do
+ original_attributes = { 'first_name' => 'allowed', 'admin' => 'denied' }
+ assert_raise ActiveModel::MassAssignmentSecurity::Error do
+ @strict_sanitizer.sanitize(original_attributes, @authorizer)
+ end
+ end
+
end
diff --git a/activemodel/test/cases/mass_assignment_security/white_list_test.rb b/activemodel/test/cases/mass_assignment_security/white_list_test.rb
index aa3596ad2a..737b55492a 100644
--- a/activemodel/test/cases/mass_assignment_security/white_list_test.rb
+++ b/activemodel/test/cases/mass_assignment_security/white_list_test.rb
@@ -16,13 +16,4 @@ class WhiteListTest < ActiveModel::TestCase
assert_equal true, @white_list.deny?('admin')
end
- test "sanitize attributes" do
- original_attributes = { 'first_name' => 'allowed', 'admin' => 'denied', 'admin(1)' => 'denied' }
- attributes = @white_list.sanitize(original_attributes)
-
- assert attributes.key?('first_name'), "Allowed key shouldn't be rejected"
- assert !attributes.key?('admin'), "Denied key should be rejected"
- assert !attributes.key?('admin(1)'), "Multi-parameter key should be detected"
- end
-
end
diff --git a/activemodel/test/cases/mass_assignment_security_test.rb b/activemodel/test/cases/mass_assignment_security_test.rb
index 43a12eed61..a778240827 100644
--- a/activemodel/test/cases/mass_assignment_security_test.rb
+++ b/activemodel/test/cases/mass_assignment_security_test.rb
@@ -1,6 +1,15 @@
require "cases/helper"
require 'models/mass_assignment_specific'
+
+class CustomSanitizer < ActiveModel::MassAssignmentSecurity::Sanitizer
+
+ def process_removed_attributes(attrs)
+ raise StandardError
+ end
+
+end
+
class MassAssignmentSecurityTest < ActiveModel::TestCase
def test_attribute_protection
@@ -76,4 +85,15 @@ class MassAssignmentSecurityTest < ActiveModel::TestCase
assert_equal sanitized, { }
end
+ def test_custom_sanitizer
+ user = User.new
+ User.mass_assignment_sanitizer = CustomSanitizer.new
+ assert_raise StandardError do
+ user.sanitize_for_mass_assignment("admin" => true)
+ end
+ ensure
+ User.mass_assignment_sanitizer = nil
+
+ end
+
end
diff --git a/activemodel/test/cases/translation_test.rb b/activemodel/test/cases/translation_test.rb
index 1b1d972d5c..838956bc98 100644
--- a/activemodel/test/cases/translation_test.rb
+++ b/activemodel/test/cases/translation_test.rb
@@ -76,5 +76,15 @@ class ActiveModelI18nTests < ActiveModel::TestCase
Person.model_name.human(options)
assert_equal({:default => 'person model'}, options)
end
+
+ def test_alternate_namespaced_model_attribute_translation
+ I18n.backend.store_translations 'en', :activemodel => {:attributes => {:person => {:gender => {:attribute => 'person gender attribute'}}}}
+ assert_equal 'person gender attribute', Person::Gender.human_attribute_name('attribute')
+ end
+
+ def test_alternate_namespaced_model_translation
+ I18n.backend.store_translations 'en', :activemodel => {:models => {:person => {:gender => 'person gender model'}}}
+ assert_equal 'person gender model', Person::Gender.model_name.human
+ end
end
diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG
index b05d3970c7..ead2a244e5 100644
--- a/activerecord/CHANGELOG
+++ b/activerecord/CHANGELOG
@@ -240,7 +240,6 @@
def up
create_table :posts do |t|
t.belongs_to :user
-
t.timestamps
end
diff --git a/activerecord/README.rdoc b/activerecord/README.rdoc
index 0d00749901..822276589b 100644
--- a/activerecord/README.rdoc
+++ b/activerecord/README.rdoc
@@ -3,7 +3,7 @@
Active Record connects classes to relational database tables to establish an
almost zero-configuration persistence layer for applications. The library
provides a base class that, when subclassed, sets up a mapping between the new
-class and an existing table in the database. In context of an application,
+class and an existing table in the database. In the context of an application,
these classes are commonly referred to as *models*. Models can also be
connected to other models; this is done by defining *associations*.
@@ -70,7 +70,7 @@ A short rundown of some of the major features:
{Learn more}[link:classes/ActiveRecord/Validations.html]
-* Callbacks available for the entire life cycle (instantiation, saving, destroying, validating, etc.)
+* Callbacks available for the entire life cycle (instantiation, saving, destroying, validating, etc.).
class Person < ActiveRecord::Base
before_destroy :invalidate_payment_plan
@@ -80,7 +80,7 @@ A short rundown of some of the major features:
{Learn more}[link:classes/ActiveRecord/Callbacks.html]
-* Observers that react to changes in a model
+* Observers that react to changes in a model.
class CommentObserver < ActiveRecord::Observer
def after_create(comment) # is called just after Comment#save
@@ -91,7 +91,7 @@ A short rundown of some of the major features:
{Learn more}[link:classes/ActiveRecord/Observer.html]
-* Inheritance hierarchies
+* Inheritance hierarchies.
class Company < ActiveRecord::Base; end
class Firm < Company; end
@@ -101,7 +101,7 @@ A short rundown of some of the major features:
{Learn more}[link:classes/ActiveRecord/Base.html]
-* Transactions
+* Transactions.
# Database transaction
Account.transaction do
@@ -112,7 +112,7 @@ A short rundown of some of the major features:
{Learn more}[link:classes/ActiveRecord/Transactions/ClassMethods.html]
-* Reflections on columns, associations, and aggregations
+* Reflections on columns, associations, and aggregations.
reflection = Firm.reflect_on_association(:clients)
reflection.klass # => Client (class)
@@ -121,7 +121,7 @@ A short rundown of some of the major features:
{Learn more}[link:classes/ActiveRecord/Reflection/ClassMethods.html]
-* Database abstraction through simple adapters
+* Database abstraction through simple adapters.
# connect to SQLite3
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => "dbfile.sqlite3")
@@ -141,13 +141,13 @@ A short rundown of some of the major features:
SQLite3[link:classes/ActiveRecord/ConnectionAdapters/SQLite3Adapter.html].
-* Logging support for Log4r[http://log4r.sourceforge.net] and Logger[http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc]
+* Logging support for Log4r[http://log4r.sourceforge.net] and Logger[http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc].
ActiveRecord::Base.logger = Logger.new(STDOUT)
ActiveRecord::Base.logger = Log4r::Logger.new("Application Log")
-* Database agnostic schema management with Migrations
+* Database agnostic schema management with Migrations.
class AddSystemSettings < ActiveRecord::Migration
def self.up
diff --git a/activerecord/RUNNING_UNIT_TESTS b/activerecord/RUNNING_UNIT_TESTS
index b3d376772e..16444249cc 100644
--- a/activerecord/RUNNING_UNIT_TESTS
+++ b/activerecord/RUNNING_UNIT_TESTS
@@ -1,37 +1,26 @@
-== Creating the test database
+== Configure databases
-The default names for the test databases are "activerecord_unittest" and
-"activerecord_unittest2". If you want to use another database name, then be sure
-to update the connection adapter setups you want to test within
-test/connections/<your database>/connection.rb.
-When you have the database online, you can import the fixture tables with
-the test/schema/*.sql files.
+Copy test/config.example.yml to test/config.yml and edit as needed. Or just run the tests for
+the first time, which will do the copy automatically and use the default (sqlite3).
-Make sure that you create database objects with the same user that you specified in
-connection.rb otherwise (on Postgres, at least) tests for default values will fail.
+You can build postgres and mysql databases using the build_postgresql and build_mysql rake tasks.
-== Running with Rake
+== Running the tests
-The easiest way to run the unit tests is through Rake. The default task runs
-the entire test suite for all the adapters. You can also run the suite on just
-one adapter by using the tasks test_mysql, test_sqlite3, test_postgresql or any
-of the other test_ tasks. For more information, checkout the full array of rake
-tasks with "rake -T"
+You can run a particular test file from the command line, e.g.
-Rake can be found at http://rake.rubyforge.org
+ $ ruby test/cases/base_test.rb
-== Running by hand
+To run a specific test:
-Unit tests are located in test/cases directory. If you only want to run a single test suite,
-you can do so with:
+ $ ruby test/cases/base_test.rb -n test_something_works
- rake test_mysql TEST=test/cases/base_test.rb
+You can run with a database other than the default you set in test/config.yml, using the ARCONN
+environment variable:
-That'll run the base suite using the MySQL-Ruby adapter. Some tests rely on the schema
-being initialized - you can initialize the schema with:
+ $ ARCONN=postgresql ruby test/cases/base_test.rb
- rake test_mysql TEST=test/cases/aaa_create_tables_test.rb
- rake mysql:build_databases
+You can run all the tests for a given database via rake:
To setup the testing environment for PostgreSQL use this command:
@@ -39,5 +28,5 @@ To setup the testing environment for PostgreSQL use this command:
The incantation for running a particular test looks like this
- rake test TEST=test/cases/datatype_test_postgresql.rb TESTOPTS="-n test_timestamp_with_zone_values_without_rails_time_zone_support"
+ rake test TEST=test/cases/datatype_test_postgresql.rb TESTOPTS="--name=test_timestamp_with_zone_values_without_rails_time_zone_support"
diff --git a/activerecord/Rakefile b/activerecord/Rakefile
index 346c7e8142..d769a73dba 100755
--- a/activerecord/Rakefile
+++ b/activerecord/Rakefile
@@ -4,8 +4,7 @@ require 'rake/packagetask'
require 'rubygems/package_task'
require File.expand_path(File.dirname(__FILE__)) + "/test/config"
-
-MYSQL_DB_USER = 'rails'
+require File.expand_path(File.dirname(__FILE__)) + "/test/support/config"
def run_without_aborting(*tasks)
errors = []
@@ -43,9 +42,8 @@ end
%w( mysql mysql2 postgresql sqlite3 sqlite3_mem firebird db2 oracle sybase openbase frontbase jdbcmysql jdbcpostgresql jdbcsqlite3 jdbcderby jdbch2 jdbchsqldb ).each do |adapter|
Rake::TestTask.new("test_#{adapter}") { |t|
- connection_path = "test/connections/#{adapter =~ /jdbc/ ? 'jdbc' : 'native'}_#{adapter}"
adapter_short = adapter == 'db2' ? adapter : adapter[/^[a-z0-9]+/]
- t.libs << "test" << connection_path
+ t.libs << 'test'
t.test_files = (Dir.glob( "test/cases/**/*_test.rb" ).reject {
|x| x =~ /\/adapters\//
} + Dir.glob("test/cases/adapters/#{adapter_short}/**/*_test.rb")).sort
@@ -55,21 +53,27 @@ end
}
task "isolated_test_#{adapter}" do
- connection_path = "test/connections/#{adapter =~ /jdbc/ ? 'jdbc' : 'native'}_#{adapter}"
adapter_short = adapter == 'db2' ? adapter : adapter[/^[a-z0-9]+/]
- puts [adapter, adapter_short, connection_path].inspect
+ puts [adapter, adapter_short].inspect
ruby = File.join(*RbConfig::CONFIG.values_at('bindir', 'RUBY_INSTALL_NAME'))
(Dir["test/cases/**/*_test.rb"].reject {
|x| x =~ /\/adapters\//
} + Dir["test/cases/adapters/#{adapter_short}/**/*_test.rb"]).all? do |file|
- sh(ruby, "-Ilib:test:#{connection_path}", file)
+ sh(ruby, "-Itest", file)
end or raise "Failures"
end
namespace adapter do
task :test => "test_#{adapter}"
task :isolated_test => "isolated_test_#{adapter}"
+
+ # Set the connection environment for the adapter
+ task(:env) { ENV['ARCONN'] = adapter }
end
+
+ # Make sure the adapter test evaluates the env setting task
+ task "test_#{adapter}" => "#{adapter}:env"
+ task "isolated_test_#{adapter}" => "#{adapter}:env"
end
rule '.sqlite3' do |t|
@@ -84,14 +88,16 @@ task :test_sqlite3 => [
namespace :mysql do
desc 'Build the MySQL test databases'
task :build_databases do
- %x( mysql --user=#{MYSQL_DB_USER} -e "create DATABASE activerecord_unittest DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci ")
- %x( mysql --user=#{MYSQL_DB_USER} -e "create DATABASE activerecord_unittest2 DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci ")
+ config = ARTest.config['connections']['mysql']
+ %x( mysql --user=#{config['arunit']['username']} -e "create DATABASE #{config['arunit']['database']} DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci ")
+ %x( mysql --user=#{config['arunit2']['username']} -e "create DATABASE #{config['arunit2']['database']} DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci ")
end
desc 'Drop the MySQL test databases'
task :drop_databases do
- %x( mysqladmin --user=#{MYSQL_DB_USER} -f drop activerecord_unittest )
- %x( mysqladmin --user=#{MYSQL_DB_USER} -f drop activerecord_unittest2 )
+ config = ARTest.config['connections']['mysql']
+ %x( mysqladmin --user=#{config['arunit']['username']} -f drop #{config['arunit']['database']} )
+ %x( mysqladmin --user=#{config['arunit2']['username']} -f drop #{config['arunit2']['database']} )
end
desc 'Rebuild the MySQL test databases'
@@ -106,14 +112,16 @@ task :rebuild_mysql_databases => 'mysql:rebuild_databases'
namespace :postgresql do
desc 'Build the PostgreSQL test databases'
task :build_databases do
- %x( createdb -E UTF8 activerecord_unittest )
- %x( createdb -E UTF8 activerecord_unittest2 )
+ config = ARTest.config['connections']['postgresql']
+ %x( createdb -E UTF8 #{config['arunit']['database']} )
+ %x( createdb -E UTF8 #{config['arunit2']['database']} )
end
desc 'Drop the PostgreSQL test databases'
task :drop_databases do
- %x( dropdb activerecord_unittest )
- %x( dropdb activerecord_unittest2 )
+ config = ARTest.config['connections']['postgresql']
+ %x( dropdb #{config['arunit']['database']} )
+ %x( dropdb #{config['arunit2']['database']} )
end
desc 'Rebuild the PostgreSQL test databases'
@@ -152,8 +160,9 @@ namespace :frontbase do
DISCONNECT ALL;
)
end
- create_activerecord_unittest = build_frontbase_database['activerecord_unittest', File.join(SCHEMA_ROOT, 'frontbase.sql')]
- create_activerecord_unittest2 = build_frontbase_database['activerecord_unittest2', File.join(SCHEMA_ROOT, 'frontbase2.sql')]
+ config = ARTest.config['connections']['frontbase']
+ create_activerecord_unittest = build_frontbase_database[config['arunit']['database'], File.join(SCHEMA_ROOT, 'frontbase.sql')]
+ create_activerecord_unittest2 = build_frontbase_database[config['arunit2']['database'], File.join(SCHEMA_ROOT, 'frontbase2.sql')]
execute_frontbase_sql = Proc.new do |sql|
system(<<-SHELL)
/Library/FrontBase/bin/sql92 <<-SQL
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index 1c7209e64e..2cbfa42718 100644
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -76,12 +76,6 @@ 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.")
@@ -458,12 +452,12 @@ module ActiveRecord
# end
#
# Some extensions can only be made to work with knowledge of the association's internals.
- # Extensions can access relevant state using the following methods (where 'items' is the
+ # Extensions can access relevant state using the following methods (where +items+ is the
# name of the association):
#
- # * +record.association(:items).owner+ - Returns the object the association is part of.
- # * +record.association(:items).reflection+ - Returns the reflection object that describes the association.
- # * +record.association(:items).target+ - Returns the associated object for +belongs_to+ and +has_one+, or
+ # * <tt>record.association(:items).owner</tt> - Returns the object the association is part of.
+ # * <tt>record.association(:items).reflection</tt> - Returns the reflection object that describes the association.
+ # * <tt>record.association(:items).target</tt> - Returns the associated object for +belongs_to+ and +has_one+, or
# the collection of associated objects for +has_many+ and +has_and_belongs_to_many+.
#
# === Association Join Models
@@ -866,7 +860,7 @@ module ActiveRecord
# the inverse of each other and the inverse of the +dungeon+ association on +EvilWizard+
# is the +evil_wizard+ association on +Dungeon+ (and vice-versa). By default,
# Active Record doesn't know anything about these inverse relationships and so no object
- # loading optimisation is possible. For example:
+ # loading optimization is possible. For example:
#
# d = Dungeon.first
# t = d.traps.first
diff --git a/activerecord/lib/active_record/associations/association.rb b/activerecord/lib/active_record/associations/association.rb
index 687b668634..c3aee90124 100644
--- a/activerecord/lib/active_record/associations/association.rb
+++ b/activerecord/lib/active_record/associations/association.rb
@@ -141,7 +141,7 @@ module ActiveRecord
@target ||= find_target
end
end
- loaded!
+ loaded! unless loaded?
target
rescue ActiveRecord::RecordNotFound
reset
@@ -177,9 +177,7 @@ module ActiveRecord
# Sets the owner attributes on the given record
def set_owner_attributes(record)
- if owner.persisted?
- creation_attributes.each { |key, value| record[key] = value }
- end
+ creation_attributes.each { |key, value| record[key] = value }
end
# Should be true if there is a foreign key present on the owner which
diff --git a/activerecord/lib/active_record/associations/association_scope.rb b/activerecord/lib/active_record/associations/association_scope.rb
index 94847bc2ae..9e6d9e73c5 100644
--- a/activerecord/lib/active_record/associations/association_scope.rb
+++ b/activerecord/lib/active_record/associations/association_scope.rb
@@ -60,7 +60,7 @@ module ActiveRecord
scope = scope.joins(join(
join_table,
- table[reflection.active_record_primary_key].
+ table[reflection.association_primary_key].
eq(join_table[reflection.association_foreign_key])
))
diff --git a/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb b/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb
index 4b48757da7..d7632b2ea9 100644
--- a/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb
+++ b/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb
@@ -39,10 +39,6 @@ module ActiveRecord::Associations::Builder
model.send(:undecorated_table_name, model.to_s),
model.send(:undecorated_table_name, reflection.class_name)
)
-
- if model.connection.supports_primary_key? && (model.connection.primary_key(reflection.options[:join_table]) rescue false)
- raise ActiveRecord::HasAndBelongsToManyAssociationWithPrimaryKeyError.new(reflection)
- end
end
# Generates a join table name from two provided table names.
diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb
index 8a028c8996..7e1a41e84d 100644
--- a/activerecord/lib/active_record/associations/collection_association.rb
+++ b/activerecord/lib/active_record/associations/collection_association.rb
@@ -104,26 +104,11 @@ module ActiveRecord
end
def create(attributes = {}, options = {}, &block)
- unless owner.persisted?
- raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved"
- end
-
- if attributes.is_a?(Array)
- attributes.collect { |attr| create(attr, options, &block) }
- else
- transaction do
- add_to_target(build_record(attributes, options)) do |record|
- yield(record) if block_given?
- insert_record(record)
- end
- end
- end
+ create_record(attributes, options, &block)
end
- def create!(attrs = {}, options = {}, &block)
- record = create(attrs, options, &block)
- Array.wrap(record).each(&:save!)
- record
+ def create!(attributes = {}, options = {}, &block)
+ create_record(attributes, options, true, &block)
end
# Add +records+ to this association. Returns +self+ so method calls may be chained.
@@ -402,9 +387,13 @@ module ActiveRecord
return memory if persisted.empty?
persisted.map! do |record|
- mem_record = memory.delete(record)
+ # Unfortunately we cannot simply do memory.delete(record) since on 1.8 this returns
+ # record rather than memory.at(memory.index(record)). The behaviour is fixed in 1.9.
+ mem_index = memory.index(record)
+
+ if mem_index
+ mem_record = memory.delete_at(mem_index)
- if mem_record
(record.attribute_names - mem_record.changes.keys).each do |name|
mem_record[name] = record[name]
end
@@ -418,8 +407,25 @@ module ActiveRecord
persisted + memory
end
+ def create_record(attributes, options, raise = false, &block)
+ unless owner.persisted?
+ raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved"
+ end
+
+ if attributes.is_a?(Array)
+ attributes.collect { |attr| create_record(attr, options, raise, &block) }
+ else
+ transaction do
+ add_to_target(build_record(attributes, options)) do |record|
+ yield(record) if block_given?
+ insert_record(record, true, raise)
+ end
+ end
+ end
+ end
+
# Do the relevant stuff to insert the given record into the association collection.
- def insert_record(record, validate = true)
+ def insert_record(record, validate = true, raise = false)
raise NotImplementedError
end
@@ -430,7 +436,6 @@ module ActiveRecord
def build_record(attributes, options)
record = reflection.build_association(attributes, options)
record.assign_attributes(create_scope.except(*record.changed), :without_protection => true)
- record.assign_attributes(attributes, options)
record
end
diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb
index adfc71d435..5267116c42 100644
--- a/activerecord/lib/active_record/associations/collection_proxy.rb
+++ b/activerecord/lib/active_record/associations/collection_proxy.rb
@@ -56,6 +56,8 @@ module ActiveRecord
Array.wrap(association.options[:extend]).each { |ext| proxy_extend(ext) }
end
+ alias_method :new, :build
+
def respond_to?(*args)
super ||
(load_target && target.respond_to?(*args)) ||
@@ -65,7 +67,7 @@ module ActiveRecord
def method_missing(method, *args, &block)
match = DynamicFinderMatch.match(method)
if match && match.instantiator?
- record = send(:find_or_instantiator_by_attributes, match, match.attribute_names, *args) do |r|
+ send(:find_or_instantiator_by_attributes, match, match.attribute_names, *args) do |r|
@association.send :set_owner_attributes, r
@association.send :add_to_target, r
yield(r) if block_given?
@@ -115,14 +117,6 @@ module ActiveRecord
@association.reload
self
end
-
- def new(*args, &block)
- if @association.is_a?(HasManyThroughAssociation)
- @association.build(*args, &block)
- else
- method_missing(:new, *args, &block)
- end
- end
end
end
end
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 217213808b..f7ce70db1a 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
@@ -9,8 +9,14 @@ module ActiveRecord
super
end
- def insert_record(record, validate = true)
- return if record.new_record? && !record.save(:validate => validate)
+ def insert_record(record, validate = true, raise = false)
+ if record.new_record?
+ if raise
+ record.save!(:validate => validate)
+ else
+ return unless record.save(:validate => validate)
+ end
+ end
if options[:insert_sql]
owner.connection.insert(interpolate(options[:insert_sql], record))
diff --git a/activerecord/lib/active_record/associations/has_many_association.rb b/activerecord/lib/active_record/associations/has_many_association.rb
index 7172e89a05..50ee60284c 100644
--- a/activerecord/lib/active_record/associations/has_many_association.rb
+++ b/activerecord/lib/active_record/associations/has_many_association.rb
@@ -7,9 +7,14 @@ module ActiveRecord
# is provided by its child HasManyThroughAssociation.
class HasManyAssociation < CollectionAssociation #:nodoc:
- def insert_record(record, validate = true)
+ def insert_record(record, validate = true, raise = false)
set_owner_attributes(record)
- record.save(:validate => validate)
+
+ if raise
+ record.save!(:validate => validate)
+ else
+ record.save(:validate => validate)
+ end
end
private
diff --git a/activerecord/lib/active_record/associations/has_many_through_association.rb b/activerecord/lib/active_record/associations/has_many_through_association.rb
index 7708228d23..2e818dca5d 100644
--- a/activerecord/lib/active_record/associations/has_many_through_association.rb
+++ b/activerecord/lib/active_record/associations/has_many_through_association.rb
@@ -6,8 +6,6 @@ module ActiveRecord
class HasManyThroughAssociation < HasManyAssociation #:nodoc:
include ThroughAssociation
- alias_method :new, :build
-
# Returns the size of the collection by executing a SELECT COUNT(*) query if the collection hasn't been
# loaded and calling collection.size if it has. If it's more likely than not that the collection does
# have a size larger than zero, and you need to fetch that collection afterwards, it'll take one fewer
@@ -33,9 +31,16 @@ module ActiveRecord
super
end
- def insert_record(record, validate = true)
+ def insert_record(record, validate = true, raise = false)
ensure_not_nested
- return if record.new_record? && !record.save(:validate => validate)
+
+ if record.new_record?
+ if raise
+ record.save!(:validate => validate)
+ else
+ return unless record.save(:validate => validate)
+ end
+ end
through_record(record).save!
update_counter(1)
diff --git a/activerecord/lib/active_record/associations/has_one_association.rb b/activerecord/lib/active_record/associations/has_one_association.rb
index 2f3a6e71f1..6b8201973a 100644
--- a/activerecord/lib/active_record/associations/has_one_association.rb
+++ b/activerecord/lib/active_record/associations/has_one_association.rb
@@ -14,8 +14,8 @@ module ActiveRecord
end
if record
- set_inverse_instance(record)
set_owner_attributes(record)
+ set_inverse_instance(record)
if owner.persisted? && save && !record.save
nullify_owner_attributes(record)
diff --git a/activerecord/lib/active_record/attribute_methods/primary_key.rb b/activerecord/lib/active_record/attribute_methods/primary_key.rb
index 5f06452247..e3f221c773 100644
--- a/activerecord/lib/active_record/attribute_methods/primary_key.rb
+++ b/activerecord/lib/active_record/attribute_methods/primary_key.rb
@@ -48,7 +48,7 @@ module ActiveRecord
end
attr_accessor :original_primary_key
-
+
# Attribute writer for the primary key column
def primary_key=(value)
@quoted_primary_key = nil
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index f74810720d..900abd323b 100644
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -660,7 +660,6 @@ module ActiveRecord #:nodoc:
@quoted_table_name = nil
define_attr_method :table_name, value, &block
- @arel_table = Arel::Table.new(table_name, arel_engine)
@relation = Relation.new(self, arel_table)
end
alias :table_name= :set_table_name
@@ -1308,7 +1307,6 @@ MSG
rescue NameError => e
# We don't want to swallow NoMethodError < NameError errors
raise e unless e.instance_of?(NameError)
- rescue ArgumentError
end
end
@@ -2007,7 +2005,7 @@ MSG
set_values = (1..3).collect{|position| values_hash_from_param[position].blank? ? 1 : values_hash_from_param[position]}
begin
Date.new(*set_values)
- rescue ArgumentError => ex # if Date.new raises an exception on an invalid date
+ rescue ArgumentError # if Date.new raises an exception on an invalid date
instantiate_time_object(name, set_values).to_date # we instantiate Time object and convert it back to a date thus using Time's logic in handling invalid dates
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
index a754f46af0..74c07c624d 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -161,7 +161,7 @@ module ActiveRecord
yield td if block_given?
if options[:force] && table_exists?(table_name)
- drop_table(table_name, options)
+ drop_table(table_name)
end
create_sql = "CREATE#{' TEMPORARY' if options[:temporary]} TABLE "
@@ -253,7 +253,7 @@ module ActiveRecord
end
# Drops a table from the database.
- def drop_table(table_name, options = {})
+ def drop_table(table_name)
execute "DROP TABLE #{quote_table_name(table_name)}"
end
diff --git a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
index 6e2c3f4527..24d8c8cad2 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb
@@ -427,10 +427,6 @@ module ActiveRecord
tables(nil, schema).include? table
end
- def drop_table(table_name, options = {})
- super(table_name, options)
- end
-
# Returns an array of indexes for the given table.
def indexes(table_name, name = nil)
indexes = []
diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
index ee83f8120d..9e6cb13cca 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
@@ -568,10 +568,6 @@ module ActiveRecord
tables(nil, schema).include? table
end
- def drop_table(table_name, options = {})
- super(table_name, options)
- end
-
# Returns an array of indexes for the given table.
def indexes(table_name, name = nil)#:nodoc:
indexes = []
@@ -711,7 +707,7 @@ module ActiveRecord
def quoted_columns_for_index(column_names, options = {})
length = options[:length] if options.is_a?(Hash)
- quoted_column_names = case length
+ case length
when Hash
column_names.map {|name| length[name] ? "#{quote_column_name(name)}(#{length[name]})" : quote_column_name(name) }
when Fixnum
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index 8b48c055ac..3e390ba994 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -805,8 +805,8 @@ module ActiveRecord
end
if pk && sequence
- quoted_sequence = quote_column_name(sequence)
-
+ quoted_sequence = quote_table_name(sequence)
+
select_value <<-end_sql, 'Reset sequence'
SELECT setval('#{quoted_sequence}', (SELECT COALESCE(MAX(#{quote_column_name pk})+(SELECT increment_by FROM #{quoted_sequence}), (SELECT min_value FROM #{quoted_sequence})) FROM #{quote_table_name(table)}), false)
end_sql
@@ -818,18 +818,25 @@ module ActiveRecord
# First try looking for a sequence with a dependency on the
# given table's primary key.
result = exec_query(<<-end_sql, 'SCHEMA').rows.first
- SELECT attr.attname, seq.relname
+ SELECT attr.attname, ns.nspname, seq.relname
FROM pg_class seq
INNER JOIN pg_depend dep ON seq.oid = dep.objid
INNER JOIN pg_attribute attr ON attr.attrelid = dep.refobjid AND attr.attnum = dep.refobjsubid
INNER JOIN pg_constraint cons ON attr.attrelid = cons.conrelid AND attr.attnum = cons.conkey[1]
+ INNER JOIN pg_namespace ns ON seq.relnamespace = ns.oid
WHERE seq.relkind = 'S'
AND cons.contype = 'p'
AND dep.refobjid = '#{quote_table_name(table)}'::regclass
end_sql
# [primary_key, sequence]
- [result.first, result.last]
+ if result.second == 'public' then
+ sequence = result.last
+ else
+ sequence = result.second+'.'+result.last
+ end
+
+ [result.first, sequence]
rescue
nil
end
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
index 3c6f52e0fa..724b2e6d9c 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb
@@ -102,6 +102,10 @@ module ActiveRecord
# Clears the prepared statements cache.
def clear_cache!
+ @statements.values.map { |hash| hash[:stmt] }.each { |stmt|
+ stmt.close unless stmt.closed?
+ }
+
@statements.clear
end
diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb
index 640111096d..de26b21f1a 100644
--- a/activerecord/lib/active_record/migration.rb
+++ b/activerecord/lib/active_record/migration.rb
@@ -53,7 +53,7 @@ module ActiveRecord
#
# This migration will add a boolean flag to the accounts table and remove it
# if you're backing out of the migration. It shows how all migrations have
- # two class methods +up+ and +down+ that describes the transformations
+ # two methods +up+ and +down+ that describes the transformations
# required to implement or remove the migration. These methods can consist
# of both the migration specific methods like add_column and remove_column,
# but may also contain regular Ruby code for generating data needed for the
diff --git a/activerecord/lib/active_record/migration/command_recorder.rb b/activerecord/lib/active_record/migration/command_recorder.rb
index f9f7448008..f01e94169f 100644
--- a/activerecord/lib/active_record/migration/command_recorder.rb
+++ b/activerecord/lib/active_record/migration/command_recorder.rb
@@ -1,6 +1,6 @@
module ActiveRecord
class Migration
- # ActiveRecord::Migration::CommandRecorder records commands done during
+ # <tt>ActiveRecord::Migration::CommandRecorder</tt> records commands done during
# a migration and knows how to reverse those commands. The CommandRecorder
# knows how to invert the following commands:
#
@@ -23,7 +23,7 @@ module ActiveRecord
# record +command+. +command+ should be a method name and arguments.
# For example:
#
- # recorder.record(:method_name, [:arg1, arg2])
+ # recorder.record(:method_name, [:arg1, :arg2])
def record(*command)
@commands << command
end
@@ -34,7 +34,7 @@ module ActiveRecord
# recorder.record(:rename_table, [:old, :new])
# recorder.inverse # => [:rename_table, [:new, :old]]
#
- # This method will raise an IrreversibleMigration exception if it cannot
+ # This method will raise an +IrreversibleMigration+ exception if it cannot
# invert the +commands+.
def inverse
@commands.reverse.map { |name, args|
@@ -50,9 +50,9 @@ module ActiveRecord
[:create_table, :rename_table, :add_column, :remove_column, :rename_index, :rename_column, :add_index, :remove_index, :add_timestamps, :remove_timestamps, :change_column, :change_column_default].each do |method|
class_eval <<-EOV, __FILE__, __LINE__ + 1
- def #{method}(*args)
- record(:"#{method}", args)
- end
+ def #{method}(*args) # def create_table(*args)
+ record(:"#{method}", args) # record(:create_table, args)
+ end # end
EOV
end
@@ -79,8 +79,10 @@ module ActiveRecord
end
def invert_add_index(args)
- table, columns, _ = *args
- [:remove_index, [table, {:column => columns}]]
+ table, columns, options = *args
+ index_name = options.try(:[], :name)
+ options_hash = index_name ? {:name => index_name} : {:column => columns}
+ [:remove_index, [table, options_hash]]
end
def invert_remove_timestamps(args)
diff --git a/activerecord/lib/active_record/named_scope.rb b/activerecord/lib/active_record/named_scope.rb
index 588f52be44..14db7a6cd6 100644
--- a/activerecord/lib/active_record/named_scope.rb
+++ b/activerecord/lib/active_record/named_scope.rb
@@ -17,7 +17,7 @@ module ActiveRecord
# posts.each {|p| puts p.name } # Fires "select * from posts" and loads post objects
#
# fruits = Fruit.scoped
- # fruits = fruits.where(:colour => 'red') if options[:red_only]
+ # fruits = fruits.where(:color => 'red') if options[:red_only]
# fruits = fruits.limit(10) if limited?
#
# Anonymous \scopes tend to be useful when procedurally generating complex
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb
index 4ec0431b8c..367a1be4d9 100644
--- a/activerecord/lib/active_record/persistence.rb
+++ b/activerecord/lib/active_record/persistence.rb
@@ -279,7 +279,7 @@ module ActiveRecord
@changed_attributes.except!(*changes.keys)
primary_key = self.class.primary_key
- self.class.update_all(changes, { primary_key => self[primary_key] }) == 1
+ self.class.unscoped.update_all(changes, { primary_key => self[primary_key] }) == 1
end
end
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index d88e2693b6..317af8a15d 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -6,13 +6,13 @@ module ActiveRecord
JoinOperation = Struct.new(:relation, :join_class, :on)
ASSOCIATION_METHODS = [:includes, :eager_load, :preload]
MULTI_VALUE_METHODS = [:select, :group, :order, :joins, :where, :having, :bind]
- SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :create_with, :from, :reorder]
+ SINGLE_VALUE_METHODS = [:limit, :offset, :lock, :readonly, :create_with, :from, :reorder, :reverse_order]
include FinderMethods, Calculations, SpawnMethods, QueryMethods, Batches
# These are explicitly delegated to improve performance (avoids method_missing)
delegate :to_xml, :to_yaml, :length, :collect, :map, :each, :all?, :include?, :to => :to_a
- delegate :table_name, :quoted_table_name, :primary_key, :quoted_primary_key, :to => :klass
+ delegate :table_name, :quoted_table_name, :primary_key, :quoted_primary_key, :connection, :column_hash,:to => :klass
attr_reader :table, :klass, :loaded
attr_accessor :extensions, :default_scoped
diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb
index a785f38e89..aabe5c269b 100644
--- a/activerecord/lib/active_record/relation/calculations.rb
+++ b/activerecord/lib/active_record/relation/calculations.rb
@@ -196,7 +196,7 @@ module ActiveRecord
def execute_simple_calculation(operation, column_name, distinct) #:nodoc:
# Postgresql doesn't like ORDER BY when there are no GROUP BY
- relation = reorder(nil)
+ relation = with_default_scope.reorder(nil)
if operation == "count" && (relation.limit_value || relation.offset_value)
# Shortcut when limit is zero.
@@ -245,7 +245,7 @@ module ActiveRecord
"#{field} AS #{aliaz}"
}
- relation = except(:group).group(group.join(','))
+ relation = with_default_scope.except(:group).group(group.join(','))
relation.select_values = select_values
calculated_data = @klass.connection.select_all(relation.to_sql)
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index 94aa999715..739363415c 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -9,7 +9,7 @@ module ActiveRecord
:select_values, :group_values, :order_values, :joins_values,
:where_values, :having_values, :bind_values,
:limit_value, :offset_value, :lock_value, :readonly_value, :create_with_value,
- :from_value, :reorder_value
+ :from_value, :reorder_value, :reverse_order_value
def includes(*args)
args.reject! {|a| a.blank? }
@@ -158,13 +158,9 @@ module ActiveRecord
end
def reverse_order
- order_clause = arel.order_clauses
-
- order = order_clause.empty? ?
- "#{table_name}.#{primary_key} DESC" :
- reverse_sql_order(order_clause).join(', ')
-
- except(:order).order(Arel.sql(order))
+ relation = clone
+ relation.reverse_order_value = !relation.reverse_order_value
+ relation
end
def arel
@@ -186,6 +182,7 @@ module ActiveRecord
arel.group(*@group_values.uniq.reject{|g| g.blank?}) unless @group_values.empty?
order = @reorder_value ? @reorder_value : @order_values
+ order = reverse_sql_order(order) if @reverse_order_value
arel.order(*order.uniq.reject{|o| o.blank?}) unless order.empty?
build_select(arel, @select_values.uniq)
@@ -306,6 +303,8 @@ module ActiveRecord
end
def reverse_sql_order(order_query)
+ order_query = ["#{quoted_table_name}.#{quoted_primary_key} ASC"] if order_query.empty?
+
order_query.join(', ').split(',').collect do |s|
s.gsub!(/\sasc\Z/i, ' DESC') || s.gsub!(/\sdesc\Z/i, ' ASC') || s.concat(' DESC')
end
diff --git a/activerecord/lib/active_record/schema_dumper.rb b/activerecord/lib/active_record/schema_dumper.rb
index 62e6999736..19585f6214 100644
--- a/activerecord/lib/active_record/schema_dumper.rb
+++ b/activerecord/lib/active_record/schema_dumper.rb
@@ -106,7 +106,7 @@ HEADER
spec = {}
spec[:name] = column.name.inspect
- # AR has an optimisation which handles zero-scale decimals as integers. This
+ # AR has an optimization which handles zero-scale decimals as integers. This
# code ensures that the dumper still dumps the column as a decimal.
spec[:type] = if column.type == :integer && [/^numeric/, /^decimal/].any? { |e| e.match(column.sql_type) }
'decimal'
diff --git a/activerecord/lib/active_record/serialization.rb b/activerecord/lib/active_record/serialization.rb
index be4354ce6a..e3185a9c5a 100644
--- a/activerecord/lib/active_record/serialization.rb
+++ b/activerecord/lib/active_record/serialization.rb
@@ -31,9 +31,6 @@ module ActiveRecord #:nodoc:
def serializable_add_includes(options = {})
return unless include_associations = options.delete(:include)
- base_only_or_except = { :except => options[:except],
- :only => options[:only] }
-
include_has_options = include_associations.is_a?(Hash)
associations = include_has_options ? include_associations.keys : Array.wrap(include_associations)
@@ -46,9 +43,8 @@ module ActiveRecord #:nodoc:
end
if records
- association_options = include_has_options ? include_associations[association] : base_only_or_except
- opts = options.merge(association_options)
- yield(association, records, opts)
+ association_options = include_has_options ? include_associations[association] : {}
+ yield(association, records, association_options)
end
end
diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb
index d363f36108..ae97a3f3ca 100644
--- a/activerecord/lib/active_record/transactions.rb
+++ b/activerecord/lib/active_record/transactions.rb
@@ -165,7 +165,7 @@ module ActiveRecord
# writing, the only database that we're aware of that supports true nested
# transactions, is MS-SQL. Because of this, Active Record emulates nested
# transactions by using savepoints on MySQL and PostgreSQL. See
- # http://dev.mysql.com/doc/refman/5.0/en/savepoints.html
+ # http://dev.mysql.com/doc/refman/5.0/en/savepoint.html
# for more information about savepoints.
#
# === Callbacks
diff --git a/activerecord/lib/rails/generators/active_record/session_migration/templates/migration.rb b/activerecord/lib/rails/generators/active_record/session_migration/templates/migration.rb
index 8f0bf1ef0d..9ea3248513 100644
--- a/activerecord/lib/rails/generators/active_record/session_migration/templates/migration.rb
+++ b/activerecord/lib/rails/generators/active_record/session_migration/templates/migration.rb
@@ -1,5 +1,5 @@
class <%= migration_class_name %> < ActiveRecord::Migration
- def up
+ def change
create_table :<%= session_table_name %> do |t|
t.string :session_id, :null => false
t.text :data
@@ -9,8 +9,4 @@ class <%= migration_class_name %> < ActiveRecord::Migration
add_index :<%= session_table_name %>, :session_id
add_index :<%= session_table_name %>, :updated_at
end
-
- def down
- drop_table :<%= session_table_name %>
- end
end
diff --git a/activerecord/test/.gitignore b/activerecord/test/.gitignore
new file mode 100644
index 0000000000..a0ec5967dd
--- /dev/null
+++ b/activerecord/test/.gitignore
@@ -0,0 +1 @@
+/config.yml
diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb
index 49b2e945c3..07de544868 100644
--- a/activerecord/test/cases/adapter_test.rb
+++ b/activerecord/test/cases/adapter_test.rb
@@ -43,7 +43,7 @@ class AdapterTest < ActiveRecord::TestCase
def test_current_database
if @connection.respond_to?(:current_database)
- assert_equal ENV['ARUNIT_DB_NAME'] || "activerecord_unittest", @connection.current_database
+ assert_equal ARTest.connection_config['arunit']['database'], @connection.current_database
end
end
@@ -68,7 +68,12 @@ class AdapterTest < ActiveRecord::TestCase
begin
assert_nothing_raised do
ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['arunit'].except(:database))
- ActiveRecord::Base.connection.execute "SELECT activerecord_unittest.pirates.*, activerecord_unittest2.courses.* FROM activerecord_unittest.pirates, activerecord_unittest2.courses"
+
+ config = ARTest.connection_config
+ ActiveRecord::Base.connection.execute(
+ "SELECT #{config['arunit']['database']}.pirates.*, #{config['arunit2']['database']}.courses.* " \
+ "FROM #{config['arunit']['database']}.pirates, #{config['arunit2']['database']}.courses"
+ )
end
ensure
ActiveRecord::Base.establish_connection 'arunit'
diff --git a/activerecord/test/cases/adapters/firebird/migration_test.rb b/activerecord/test/cases/adapters/firebird/migration_test.rb
index 710661b9bd..5c94593765 100644
--- a/activerecord/test/cases/adapters/firebird/migration_test.rb
+++ b/activerecord/test/cases/adapters/firebird/migration_test.rb
@@ -24,7 +24,7 @@ class FirebirdMigrationTest < ActiveRecord::TestCase
assert !sequence_exists?('foo_seq')
assert sequence_exists?('foo_custom_seq')
- assert_nothing_raised { @connection.drop_table(:foo, :sequence => 'foo_custom_seq') }
+ assert_nothing_raised { @connection.drop_table(:foo) }
assert !sequence_exists?('foo_custom_seq')
ensure
FireRuby::Generator.new('foo_custom_seq', @fireruby_connection).drop rescue nil
diff --git a/activerecord/test/cases/adapters/mysql/quoting_test.rb b/activerecord/test/cases/adapters/mysql/quoting_test.rb
index 9673e2bb46..3d1330efb8 100644
--- a/activerecord/test/cases/adapters/mysql/quoting_test.rb
+++ b/activerecord/test/cases/adapters/mysql/quoting_test.rb
@@ -23,4 +23,3 @@ module ActiveRecord
end
end
end
-
diff --git a/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb b/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb
index 752b864818..3a9744e78f 100644
--- a/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb
@@ -87,8 +87,8 @@ class MysqlReservedWordTest < ActiveRecord::TestCase
assert_nothing_raised { x.save }
x.order = 'y'
assert_nothing_raised { x.save }
- assert_nothing_raised { y = Group.find_by_order('y') }
- assert_nothing_raised { y = Group.find(1) }
+ assert_nothing_raised { Group.find_by_order('y') }
+ assert_nothing_raised { Group.find(1) }
x = Group.find(1)
end
diff --git a/activerecord/test/cases/adapters/postgresql/timestamp_test.rb b/activerecord/test/cases/adapters/postgresql/timestamp_test.rb
new file mode 100644
index 0000000000..337f43c421
--- /dev/null
+++ b/activerecord/test/cases/adapters/postgresql/timestamp_test.rb
@@ -0,0 +1,30 @@
+require 'cases/helper'
+require 'models/developer'
+
+class TimestampTest < ActiveRecord::TestCase
+ def test_load_infinity_and_beyond
+ unless current_adapter?(:PostgreSQLAdapter)
+ return skip("only tested on postgresql")
+ end
+
+ d = Developer.find_by_sql("select 'infinity'::timestamp as updated_at")
+ assert d.first.updated_at.infinite?, 'timestamp should be infinite'
+
+ d = Developer.find_by_sql("select '-infinity'::timestamp as updated_at")
+ time = d.first.updated_at
+ assert time.infinite?, 'timestamp should be infinite'
+ assert_operator time, :<, 0
+ end
+
+ def test_save_infinity_and_beyond
+ unless current_adapter?(:PostgreSQLAdapter)
+ return skip("only tested on postgresql")
+ end
+
+ d = Developer.create!(:name => 'aaron', :updated_at => 1.0 / 0.0)
+ assert_equal(1.0 / 0.0, d.updated_at)
+
+ d = Developer.create!(:name => 'aaron', :updated_at => -1.0 / 0.0)
+ assert_equal(-1.0 / 0.0, d.updated_at)
+ end
+end
diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb
index 5a900e0605..7338513b41 100644
--- a/activerecord/test/cases/associations/belongs_to_associations_test.rb
+++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb
@@ -296,6 +296,15 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
assert_equal 1, Topic.find(topic.id)[:replies_count]
end
+ def test_belongs_to_counter_when_update_column
+ topic = Topic.create!(:title => "37s")
+ topic.replies.create!(:title => "re: 37s", :content => "rails")
+ assert_equal 1, Topic.find(topic.id)[:replies_count]
+
+ topic.update_column(:content, "rails is wonderfull")
+ assert_equal 1, Topic.find(topic.id)[:replies_count]
+ end
+
def test_assignment_before_child_saved
final_cut = Client.new("name" => "Final Cut")
firm = Firm.find(1)
diff --git a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb
index 49d8722aff..ff376a68d8 100644
--- a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb
+++ b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb
@@ -8,10 +8,12 @@ require 'models/company'
require 'models/topic'
require 'models/reply'
require 'models/person'
+require 'models/vertex'
+require 'models/edge'
class CascadedEagerLoadingTest < ActiveRecord::TestCase
fixtures :authors, :mixins, :companies, :posts, :topics, :accounts, :comments,
- :categorizations, :people, :categories
+ :categorizations, :people, :categories, :edges, :vertices
def test_eager_association_loading_with_cascaded_two_levels
authors = Author.find(:all, :include=>{:posts=>:comments}, :order=>"authors.id")
@@ -164,12 +166,6 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase
authors[2].post_about_thinking.comments.first
end
end
-end
-
-require 'models/vertex'
-require 'models/edge'
-class CascadedEagerLoadingTest < ActiveRecord::TestCase
- fixtures :edges, :vertices
def test_eager_association_loading_with_recursive_cascading_four_levels_has_many_through
source = Vertex.find(:first, :include=>{:sinks=>{:sinks=>{:sinks=>:sinks}}}, :order => 'vertices.id')
diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb
index 5028cee32d..325fc58958 100644
--- a/activerecord/test/cases/associations/eager_test.rb
+++ b/activerecord/test/cases/associations/eager_test.rb
@@ -380,6 +380,18 @@ class EagerAssociationTest < ActiveRecord::TestCase
assert_equal subscriptions, subscriber.subscriptions.sort_by(&:id)
end
+ def test_string_id_column_joins
+ s = Subscriber.create! do |c|
+ c.id = "PL"
+ end
+
+ b = Book.create!
+
+ Subscription.create!(:subscriber_id => "PL", :book_id => b.id)
+ s.reload
+ s.book_ids = s.book_ids
+ end
+
def test_eager_load_has_many_through_with_string_keys
books = books(:awdr, :rfr)
subscriber = Subscriber.find(subscribers(:second).id, :include => :books)
diff --git a/activerecord/test/cases/associations/habtm_join_table_test.rb b/activerecord/test/cases/associations/habtm_join_table_test.rb
index 745f169ad7..fe2b82f2c1 100644
--- a/activerecord/test/cases/associations/habtm_join_table_test.rb
+++ b/activerecord/test/cases/associations/habtm_join_table_test.rb
@@ -32,13 +32,4 @@ class HabtmJoinTableTest < ActiveRecord::TestCase
ActiveRecord::Base.connection.drop_table :my_readers
ActiveRecord::Base.connection.drop_table :my_books_my_readers
end
-
- 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::HasAndBelongsToManyAssociationWithPrimaryKeyError do
- MyReader.has_and_belongs_to_many :my_books
- end
- end
- end
end
diff --git a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb
index f4d14853d3..d8d2a113ff 100644
--- a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb
@@ -101,6 +101,16 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
assert_equal 't1', record[1]
end
+ def test_proper_usage_of_primary_keys_and_join_table
+ setup_data_for_habtm_case
+
+ assert_equal 'country_id', Country.primary_key
+ assert_equal 'treaty_id', Treaty.primary_key
+
+ country = Country.first
+ assert_equal 1, country.treaties.count
+ end
+
def test_has_and_belongs_to_many
david = Developer.find(1)
@@ -235,6 +245,21 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
end
+ def test_new_aliased_to_build
+ devel = Developer.find(1)
+ proj = assert_no_queries { devel.projects.new("name" => "Projekt") }
+ assert !devel.projects.loaded?
+
+ assert_equal devel.projects.last, proj
+ assert devel.projects.loaded?
+
+ assert !proj.persisted?
+ devel.save
+ assert proj.persisted?
+ assert_equal devel.projects.last, proj
+ assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
+ end
+
def test_build_by_new_record
devel = Developer.new(:name => "Marcel", :salary => 75000)
devel.projects.build(:name => "Make bed")
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index 43974fd895..49999630b6 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -2,6 +2,7 @@ require "cases/helper"
require 'models/developer'
require 'models/project'
require 'models/company'
+require 'models/contract'
require 'models/topic'
require 'models/reply'
require 'models/category'
@@ -536,6 +537,16 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_equal 3, companies(:first_firm).clients_of_firm(true).size
end
+ def test_new_aliased_to_build
+ company = companies(:first_firm)
+ new_client = assert_no_queries { company.clients_of_firm.new("name" => "Another Client") }
+ assert !company.clients_of_firm.loaded?
+
+ assert_equal "Another Client", new_client.name
+ assert !new_client.persisted?
+ assert_equal new_client, company.clients_of_firm.last
+ end
+
def test_build
company = companies(:first_firm)
new_client = assert_no_queries { company.clients_of_firm.build("name" => "Another Client") }
@@ -1475,4 +1486,12 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
tagging = Tagging.create! :taggable => post
assert_equal [tagging], post.taggings
end
+
+ def test_dont_call_save_callbacks_twice_on_has_many
+ firm = companies(:first_firm)
+ contract = firm.contracts.create!
+
+ assert_equal 1, contract.hi_count
+ assert_equal 1, contract.bye_count
+ end
end
diff --git a/activerecord/test/cases/associations/join_model_test.rb b/activerecord/test/cases/associations/join_model_test.rb
index b59ce4efeb..4ce8b85098 100644
--- a/activerecord/test/cases/associations/join_model_test.rb
+++ b/activerecord/test/cases/associations/join_model_test.rb
@@ -139,7 +139,21 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
def test_set_polymorphic_has_one
tagging = tags(:misc).taggings.create
posts(:thinking).tagging = tagging
- assert_equal "Post", tagging.taggable_type
+
+ assert_equal "Post", tagging.taggable_type
+ assert_equal posts(:thinking).id, tagging.taggable_id
+ assert_equal posts(:thinking), tagging.taggable
+ end
+
+ def test_set_polymorphic_has_one_on_new_record
+ tagging = tags(:misc).taggings.create
+ post = Post.new :title => "foo", :body => "bar"
+ post.tagging = tagging
+ post.save!
+
+ assert_equal "Post", tagging.taggable_type
+ assert_equal post.id, tagging.taggable_id
+ assert_equal post, tagging.taggable
end
def test_create_polymorphic_has_many_with_scope
@@ -708,8 +722,8 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
end
def test_has_many_with_pluralize_table_names_false
- engine = Engine.create!(:car_id => 1)
- aircraft = Aircraft.create!(:name => "Airbus 380", :id => 1)
+ aircraft = Aircraft.create!(:name => "Airbus 380")
+ engine = Engine.create!(:car_id => aircraft.id)
assert_equal aircraft.engines, [engine]
end
diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb
index 54c4d4ae90..b0896fb236 100644
--- a/activerecord/test/cases/attribute_methods_test.rb
+++ b/activerecord/test/cases/attribute_methods_test.rb
@@ -134,7 +134,12 @@ class AttributeMethodsTest < ActiveRecord::TestCase
if current_adapter?(:MysqlAdapter)
def test_read_attributes_before_type_cast_on_boolean
bool = Boolean.create({ "value" => false })
- assert_equal 0, bool.reload.attributes_before_type_cast["value"]
+ if RUBY_PLATFORM =~ /java/
+ # JRuby will return the value before typecast as string
+ assert_equal "0", bool.reload.attributes_before_type_cast["value"]
+ else
+ assert_equal 0, bool.reload.attributes_before_type_cast["value"]
+ end
end
end
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index 39043447fc..2224097f04 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -1766,6 +1766,13 @@ class BasicsTest < ActiveRecord::TestCase
end
end
+ def test_compute_type_argument_error
+ ActiveSupport::Dependencies.stubs(:constantize).raises(ArgumentError)
+ assert_raises ArgumentError do
+ ActiveRecord::Base.send :compute_type, 'InvalidModel'
+ end
+ end
+
def test_clear_cache!
# preheat cache
c1 = Post.columns
diff --git a/activerecord/test/cases/fixtures/file_test.rb b/activerecord/test/cases/fixtures/file_test.rb
index 8dbf92ae9a..e623fbe4d1 100644
--- a/activerecord/test/cases/fixtures/file_test.rb
+++ b/activerecord/test/cases/fixtures/file_test.rb
@@ -1,4 +1,4 @@
-require "cases/helper"
+require 'cases/helper'
require 'tempfile'
module ActiveRecord
diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb
index fbb4ee6f7b..110f6b97c6 100644
--- a/activerecord/test/cases/helper.rb
+++ b/activerecord/test/cases/helper.rb
@@ -1,8 +1,5 @@
require File.expand_path('../../../../load_paths', __FILE__)
-lib = File.expand_path("#{File.dirname(__FILE__)}/../../lib")
-$:.unshift(lib) unless $:.include?('lib') || $:.include?(lib)
-
require 'config'
require 'test/unit'
@@ -11,14 +8,13 @@ require 'mocha'
require 'active_record'
require 'active_support/dependencies'
-begin
- require 'connection'
-rescue LoadError
- # If we cannot load connection we assume that driver was not loaded for this test case, so we load sqlite3 as default one.
- # This allows for running separate test cases by simply running test file.
- connection_type = defined?(JRUBY_VERSION) ? 'jdbc' : 'native'
- require "test/connections/#{connection_type}_sqlite3/connection"
-end
+
+require 'support/config'
+require 'support/connection'
+
+ARTest.connect
+
+# TODO: Move all these random hacks into the ARTest namespace and into the support/ dir
# Show backtraces for deprecated behavior for quicker cleanup.
ActiveSupport::Deprecation.debug = true
@@ -26,8 +22,8 @@ ActiveSupport::Deprecation.debug = true
# Quote "type" if it's a reserved word for the current connection.
QUOTED_TYPE = ActiveRecord::Base.connection.quote_column_name('type')
-# Enable Identity Map for testing
-ActiveRecord::IdentityMap.enabled = (ENV['IM'] == "false" ? false : true)
+# Enable Identity Map only when ENV['IM'] is set to "true"
+ActiveRecord::IdentityMap.enabled = (ENV['IM'] == "true")
def current_adapter?(*types)
types.any? do |type|
diff --git a/activerecord/test/cases/i18n_test.rb b/activerecord/test/cases/i18n_test.rb
index 469f513e68..a428f1d87b 100644
--- a/activerecord/test/cases/i18n_test.rb
+++ b/activerecord/test/cases/i18n_test.rb
@@ -43,4 +43,3 @@ class ActiveRecordI18nTests < ActiveRecord::TestCase
assert_equal 'topic model', Reply.model_name.human
end
end
-
diff --git a/activerecord/test/cases/identity_map_test.rb b/activerecord/test/cases/identity_map_test.rb
index a0e16400d2..cd9c358799 100644
--- a/activerecord/test/cases/identity_map_test.rb
+++ b/activerecord/test/cases/identity_map_test.rb
@@ -140,7 +140,7 @@ class IdentityMapTest < ActiveRecord::TestCase
assert_not_same(p1, p2)
end
end
-
+
def test_inherited_with_type_attribute_without_identity_map
ActiveRecord::IdentityMap.without do
c = comments(:sub_special_comment)
diff --git a/activerecord/test/cases/json_serialization_test.rb b/activerecord/test/cases/json_serialization_test.rb
index 8664d63e8f..d9e350abc0 100644
--- a/activerecord/test/cases/json_serialization_test.rb
+++ b/activerecord/test/cases/json_serialization_test.rb
@@ -161,6 +161,15 @@ class DatabaseConnectedJsonEncodingTest < ActiveRecord::TestCase
assert_match %r{"tag":\{"name":"General"\}}, json
end
+ def test_includes_doesnt_merge_opts_from_base
+ json = @david.to_json(
+ :only => :id,
+ :include => :posts
+ )
+
+ assert_match %{"title":"Welcome to the weblog"}, json
+ end
+
def test_should_not_call_methods_on_associations_that_dont_respond
def @david.favorite_quote; "Constraints are liberating"; end
json = @david.to_json(:include => :posts, :methods => :favorite_quote)
diff --git a/activerecord/test/cases/migration/command_recorder_test.rb b/activerecord/test/cases/migration/command_recorder_test.rb
index ae531ebb4c..0f79c99e1a 100644
--- a/activerecord/test/cases/migration/command_recorder_test.rb
+++ b/activerecord/test/cases/migration/command_recorder_test.rb
@@ -86,6 +86,18 @@ module ActiveRecord
assert_equal [:remove_index, [:table, {:column => [:one, :two]}]], remove
end
+ def test_invert_add_index_with_name
+ @recorder.record :add_index, [:table, [:one, :two], {:name => "new_index"}]
+ remove = @recorder.inverse.first
+ assert_equal [:remove_index, [:table, {:name => "new_index"}]], remove
+ end
+
+ def test_invert_add_index_with_no_options
+ @recorder.record :add_index, [:table, [:one, :two]]
+ remove = @recorder.inverse.first
+ assert_equal [:remove_index, [:table, {:column => [:one, :two]}]], remove
+ end
+
def test_invert_rename_index
@recorder.record :rename_index, [:old, :new]
rename = @recorder.inverse.first
diff --git a/activerecord/test/cases/named_scope_test.rb b/activerecord/test/cases/named_scope_test.rb
index 34188e4915..2afe3c8f32 100644
--- a/activerecord/test/cases/named_scope_test.rb
+++ b/activerecord/test/cases/named_scope_test.rb
@@ -456,6 +456,14 @@ class NamedScopeTest < ActiveRecord::TestCase
end
end
+ def test_scopes_to_get_newest
+ post = posts(:welcome)
+ old_last_comment = post.comments.newest
+ new_comment = post.comments.create(:body => "My new comment")
+ assert_equal new_comment, post.comments.newest
+ assert_not_equal old_last_comment, post.comments.newest
+ end
+
def test_scopes_are_reset_on_association_reload
post = posts(:welcome)
diff --git a/activerecord/test/cases/relation_scoping_test.rb b/activerecord/test/cases/relation_scoping_test.rb
index 8f8e72f052..a6e08f95d0 100644
--- a/activerecord/test/cases/relation_scoping_test.rb
+++ b/activerecord/test/cases/relation_scoping_test.rb
@@ -11,6 +11,14 @@ require 'models/reference'
class RelationScopingTest < ActiveRecord::TestCase
fixtures :authors, :developers, :projects, :comments, :posts, :developers_projects
+ def test_reverse_order
+ assert_equal Developer.order("id DESC").to_a.reverse, Developer.order("id DESC").reverse_order
+ end
+
+ def test_double_reverse_order_produces_original_order
+ assert_equal Developer.order("name DESC"), Developer.order("name DESC").reverse_order.reverse_order
+ end
+
def test_scoped_find
Developer.where("name = 'David'").scoping do
assert_nothing_raised { Developer.find(1) }
@@ -471,7 +479,23 @@ class DefaultScopingTest < ActiveRecord::TestCase
assert_equal 10, DeveloperCalledJamis.unscoped.poor.length
end
+ def test_default_scope_select_ignored_by_aggregations
+ assert_equal DeveloperWithSelect.all.count, DeveloperWithSelect.count
+ end
+
+ def test_default_scope_select_ignored_by_grouped_aggregations
+ assert_equal Hash[Developer.all.group_by(&:salary).map { |s, d| [s, d.count] }],
+ DeveloperWithSelect.group(:salary).count
+ end
+
def test_default_scope_order_ignored_by_aggregations
assert_equal DeveloperOrderedBySalary.all.count, DeveloperOrderedBySalary.count
end
+
+ def test_default_scope_find_last
+ assert DeveloperOrderedBySalary.count > 1, "need more than one row for test"
+
+ lowest_salary_dev = DeveloperOrderedBySalary.find(developers(:poor_jamis).id)
+ assert_equal lowest_salary_dev, DeveloperOrderedBySalary.last
+ end
end
diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb
index 6874bd18f8..12e58bd340 100644
--- a/activerecord/test/cases/relation_test.rb
+++ b/activerecord/test/cases/relation_test.rb
@@ -20,7 +20,7 @@ module ActiveRecord
end
def test_single_values
- assert_equal [:limit, :offset, :lock, :readonly, :create_with, :from, :reorder].map(&:to_s).sort,
+ assert_equal [:limit, :offset, :lock, :readonly, :create_with, :from, :reorder, :reverse_order].map(&:to_s).sort,
Relation::SINGLE_VALUE_METHODS.map(&:to_s).sort
end
diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb
index e8f2f44189..4adecf8e83 100644
--- a/activerecord/test/cases/schema_dumper_test.rb
+++ b/activerecord/test/cases/schema_dumper_test.rb
@@ -230,4 +230,3 @@ class SchemaDumperTest < ActiveRecord::TestCase
assert_match %r{t.string[[:space:]]+"id",[[:space:]]+:null => false$}, match[2], "non-primary key id column not preserved"
end
end
-
diff --git a/activerecord/test/cases/timestamp_test.rb b/activerecord/test/cases/timestamp_test.rb
index 22d4cac422..4445a12e1d 100644
--- a/activerecord/test/cases/timestamp_test.rb
+++ b/activerecord/test/cases/timestamp_test.rb
@@ -11,35 +11,10 @@ class TimestampTest < ActiveRecord::TestCase
def setup
@developer = Developer.first
+ @developer.update_attribute(:updated_at, Time.now.prev_month)
@previously_updated_at = @developer.updated_at
end
- def test_load_infinity_and_beyond
- unless current_adapter?(:PostgreSQLAdapter)
- return skip("only tested on postgresql")
- end
-
- d = Developer.find_by_sql("select 'infinity'::timestamp as updated_at")
- assert d.first.updated_at.infinite?, 'timestamp should be infinite'
-
- d = Developer.find_by_sql("select '-infinity'::timestamp as updated_at")
- time = d.first.updated_at
- assert time.infinite?, 'timestamp should be infinite'
- assert_operator time, :<, 0
- end
-
- def test_save_infinity_and_beyond
- unless current_adapter?(:PostgreSQLAdapter)
- return skip("only tested on postgresql")
- end
-
- d = Developer.create!(:name => 'aaron', :updated_at => 1.0 / 0.0)
- assert_equal(1.0 / 0.0, d.updated_at)
-
- d = Developer.create!(:name => 'aaron', :updated_at => -1.0 / 0.0)
- assert_equal(-1.0 / 0.0, d.updated_at)
- end
-
def test_saving_a_changed_record_updates_its_timestamp
@developer.name = "Jack Bauer"
@developer.save!
@@ -66,6 +41,15 @@ class TimestampTest < ActiveRecord::TestCase
assert_equal previous_salary, @developer.salary
end
+ def test_touching_a_record_with_default_scope_that_excludes_it_updates_its_timestamp
+ developer = @developer.becomes(DeveloperCalledJamis)
+
+ developer.touch
+ assert_not_equal @previously_updated_at, developer.updated_at
+ developer.reload
+ assert_not_equal @previously_updated_at, developer.updated_at
+ end
+
def test_saving_when_record_timestamps_is_false_doesnt_update_its_timestamp
Developer.record_timestamps = false
@developer.name = "John Smith"
diff --git a/activerecord/test/config.example.yml b/activerecord/test/config.example.yml
new file mode 100644
index 0000000000..8c1a45430e
--- /dev/null
+++ b/activerecord/test/config.example.yml
@@ -0,0 +1,136 @@
+default_connection: <%= defined?(JRUBY_VERSION) ? 'jdbcsqlite3' : 'sqlite3' %>
+
+connections:
+ jdbcderby:
+ arunit: activerecord_unittest
+ arunit2: activerecord_unittest2
+
+ jdbch2:
+ arunit: activerecord_unittest
+ arunit2: activerecord_unittest2
+
+ jdbchsqldb:
+ arunit: activerecord_unittest
+ arunit2: activerecord_unittest2
+
+ jdbcmysql:
+ arunit:
+ username: rails
+ encoding: utf8
+ arunit2:
+ username: rails
+ encoding: utf8
+
+ jdbcpostgresql:
+ arunit:
+ username: <%= ENV['user'] || 'rails' %>
+ arunit2:
+ username: <%= ENV['user'] || 'rails' %>
+
+ jdbcsqlite3:
+ arunit:
+ database: <%= FIXTURES_ROOT %>/fixture_database.sqlite3
+ timeout: 5000
+ arunit2:
+ database: <%= FIXTURES_ROOT %>/fixture_database_2.sqlite3
+ timeout: 5000
+
+ db2:
+ arunit:
+ host: localhost
+ username: arunit
+ password: arunit
+ database: arunit
+ arunit2:
+ host: localhost
+ username: arunit
+ password: arunit
+ database: arunit2
+
+ firebird:
+ arunit:
+ host: localhost
+ username: rails
+ password: rails
+ charset: UTF8
+ arunit2:
+ host: localhost
+ username: rails
+ password: rails
+ charset: UTF8
+
+ frontbase:
+ arunit:
+ host: localhost
+ username: rails
+ session_name: unittest-<%= $$ %>
+ arunit2:
+ host: localhost
+ username: rails
+ session_name: unittest-<%= $$ %>
+
+ mysql:
+ arunit:
+ username: rails
+ encoding: utf8
+ arunit2:
+ username: rails
+ encoding: utf8
+
+ mysql2:
+ arunit:
+ username: rails
+ encoding: utf8
+ arunit2:
+ username: rails
+ encoding: utf8
+
+ openbase:
+ arunit:
+ username: admin
+ arunit2:
+ username: admin
+
+ oracle:
+ arunit:
+ adapter: oracle_enhanced
+ database: <%= ENV['ARUNIT_DB_NAME'] || 'orcl' %>
+ username: <%= ENV['ARUNIT_USER_NAME'] || 'arunit' %>
+ password: <%= ENV['ARUNIT_PASSWORD'] || 'arunit' %>
+ emulate_oracle_adapter: true
+ arunit2:
+ adapter: oracle_enhanced
+ database: <%= ENV['ARUNIT_DB_NAME'] || 'orcl' %>
+ username: <%= ENV['ARUNIT2_USER_NAME'] || 'arunit2' %>
+ password: <%= ENV['ARUNIT2_PASSWORD'] || 'arunit2' %>
+ emulate_oracle_adapter: true
+
+ postgresql:
+ arunit:
+ min_messages: warning
+ arunit2:
+ min_messages: warning
+
+ sqlite3:
+ arunit:
+ database: <%= FIXTURES_ROOT %>/fixture_database.sqlite3
+ timeout: 5000
+ arunit2:
+ database: <%= FIXTURES_ROOT %>/fixture_database_2.sqlite3
+ timeout: 5000
+
+ sqlite3_mem:
+ arunit:
+ adapter: sqlite3
+ database: ':memory:'
+ arunit2:
+ adapter: sqlite3
+ database: ':memory:'
+
+ sybase:
+ arunit:
+ host: database_ASE
+ username: sa
+ arunit2:
+ host: database_ASE
+ username: sa
diff --git a/activerecord/test/connections/jdbc_jdbcderby/connection.rb b/activerecord/test/connections/jdbc_jdbcderby/connection.rb
deleted file mode 100644
index 222ef5db38..0000000000
--- a/activerecord/test/connections/jdbc_jdbcderby/connection.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-print "Using Derby via JRuby, activerecord-jdbc-adapter and activerecord-jdbcderby-adapter\n"
-require_dependency 'models/course'
-require 'logger'
-ActiveRecord::Base.logger = Logger.new("debug.log")
-
-ActiveRecord::Base.configurations = {
- 'arunit' => {
- :adapter => 'jdbcderby',
- :database => 'activerecord_unittest'
- },
- 'arunit2' => {
- :adapter => 'jdbcderby',
- :database => 'activerecord_unittest2'
- }
-}
-
-ActiveRecord::Base.establish_connection 'arunit'
-Course.establish_connection 'arunit2'
diff --git a/activerecord/test/connections/jdbc_jdbch2/connection.rb b/activerecord/test/connections/jdbc_jdbch2/connection.rb
deleted file mode 100644
index 9d2875e8e7..0000000000
--- a/activerecord/test/connections/jdbc_jdbch2/connection.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-print "Using H2 via JRuby, activerecord-jdbc-adapter and activerecord-jdbch2-adapter\n"
-require_dependency 'models/course'
-require 'logger'
-ActiveRecord::Base.logger = Logger.new("debug.log")
-
-ActiveRecord::Base.configurations = {
- 'arunit' => {
- :adapter => 'jdbch2',
- :database => 'activerecord_unittest'
- },
- 'arunit2' => {
- :adapter => 'jdbch2',
- :database => 'activerecord_unittest2'
- }
-}
-
-ActiveRecord::Base.establish_connection 'arunit'
-Course.establish_connection 'arunit2'
diff --git a/activerecord/test/connections/jdbc_jdbchsqldb/connection.rb b/activerecord/test/connections/jdbc_jdbchsqldb/connection.rb
deleted file mode 100644
index fa943c2c76..0000000000
--- a/activerecord/test/connections/jdbc_jdbchsqldb/connection.rb
+++ /dev/null
@@ -1,18 +0,0 @@
-print "Using HSQLDB via JRuby, activerecord-jdbc-adapter and activerecord-jdbchsqldb-adapter\n"
-require_dependency 'models/course'
-require 'logger'
-ActiveRecord::Base.logger = Logger.new("debug.log")
-
-ActiveRecord::Base.configurations = {
- 'arunit' => {
- :adapter => 'jdbchsqldb',
- :database => 'activerecord_unittest'
- },
- 'arunit2' => {
- :adapter => 'jdbchsqldb',
- :database => 'activerecord_unittest2'
- }
-}
-
-ActiveRecord::Base.establish_connection 'arunit'
-Course.establish_connection 'arunit2'
diff --git a/activerecord/test/connections/jdbc_jdbcmysql/connection.rb b/activerecord/test/connections/jdbc_jdbcmysql/connection.rb
deleted file mode 100644
index e2517a50eb..0000000000
--- a/activerecord/test/connections/jdbc_jdbcmysql/connection.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-print "Using MySQL via JRuby, activerecord-jdbc-adapter and activerecord-jdbcmysql-adapter\n"
-require_dependency 'models/course'
-require 'logger'
-
-ActiveRecord::Base.logger = Logger.new("debug.log")
-
-# GRANT ALL PRIVILEGES ON activerecord_unittest.* to 'rails'@'localhost';
-# GRANT ALL PRIVILEGES ON activerecord_unittest2.* to 'rails'@'localhost';
-
-ActiveRecord::Base.configurations = {
- 'arunit' => {
- :adapter => 'jdbcmysql',
- :username => 'rails',
- :encoding => 'utf8',
- :database => 'activerecord_unittest',
- },
- 'arunit2' => {
- :adapter => 'jdbcmysql',
- :username => 'rails',
- :database => 'activerecord_unittest2'
- }
-}
-
-ActiveRecord::Base.establish_connection 'arunit'
-Course.establish_connection 'arunit2'
-
diff --git a/activerecord/test/connections/jdbc_jdbcpostgresql/connection.rb b/activerecord/test/connections/jdbc_jdbcpostgresql/connection.rb
deleted file mode 100644
index 0685da4433..0000000000
--- a/activerecord/test/connections/jdbc_jdbcpostgresql/connection.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-print "Using Postgrsql via JRuby, activerecord-jdbc-adapter and activerecord-postgresql-adapter\n"
-require_dependency 'models/course'
-require 'logger'
-
-ActiveRecord::Base.logger = Logger.new("debug.log")
-
-# createuser rails --createdb --no-superuser --no-createrole
-# createdb -O rails activerecord_unittest
-# createdb -O rails activerecord_unittest2
-
-ActiveRecord::Base.configurations = {
- 'arunit' => {
- :adapter => 'jdbcpostgresql',
- :username => ENV['USER'] || 'rails',
- :database => 'activerecord_unittest'
- },
- 'arunit2' => {
- :adapter => 'jdbcpostgresql',
- :username => ENV['USER'] || 'rails',
- :database => 'activerecord_unittest2'
- }
-}
-
-ActiveRecord::Base.establish_connection 'arunit'
-Course.establish_connection 'arunit2'
-
diff --git a/activerecord/test/connections/jdbc_jdbcsqlite3/connection.rb b/activerecord/test/connections/jdbc_jdbcsqlite3/connection.rb
deleted file mode 100644
index 26d4676ff3..0000000000
--- a/activerecord/test/connections/jdbc_jdbcsqlite3/connection.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-print "Using SQLite3 via JRuby, activerecord-jdbc-adapter and activerecord-jdbcsqlite3-adapter\n"
-require_dependency 'models/course'
-require 'logger'
-ActiveRecord::Base.logger = Logger.new("debug.log")
-
-class SqliteError < StandardError
-end
-
-BASE_DIR = FIXTURES_ROOT
-sqlite_test_db = "#{BASE_DIR}/fixture_database.sqlite3"
-sqlite_test_db2 = "#{BASE_DIR}/fixture_database_2.sqlite3"
-
-def make_connection(clazz, db_file)
- ActiveRecord::Base.configurations = { clazz.name => { :adapter => 'jdbcsqlite3', :database => db_file, :timeout => 5000 } }
- unless File.exist?(db_file)
- puts "SQLite3 database not found at #{db_file}. Rebuilding it."
- sqlite_command = %Q{sqlite3 "#{db_file}" "create table a (a integer); drop table a;"}
- puts "Executing '#{sqlite_command}'"
- raise SqliteError.new("Seems that there is no sqlite3 executable available") unless system(sqlite_command)
- end
- clazz.establish_connection(clazz.name)
-end
-
-make_connection(ActiveRecord::Base, sqlite_test_db)
-make_connection(Course, sqlite_test_db2)
diff --git a/activerecord/test/connections/native_db2/connection.rb b/activerecord/test/connections/native_db2/connection.rb
deleted file mode 100644
index 324315d2c8..0000000000
--- a/activerecord/test/connections/native_db2/connection.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-print "Using native DB2\n"
-require_dependency 'models/course'
-require 'logger'
-
-ActiveRecord::Base.logger = Logger.new("debug.log")
-
-ActiveRecord::Base.configurations = {
- 'arunit' => {
- :adapter => 'db2',
- :host => 'localhost',
- :username => 'arunit',
- :password => 'arunit',
- :database => 'arunit'
- },
- 'arunit2' => {
- :adapter => 'db2',
- :host => 'localhost',
- :username => 'arunit',
- :password => 'arunit',
- :database => 'arunit2'
- }
-}
-
-ActiveRecord::Base.establish_connection 'arunit'
-Course.establish_connection 'arunit2'
diff --git a/activerecord/test/connections/native_firebird/connection.rb b/activerecord/test/connections/native_firebird/connection.rb
deleted file mode 100644
index 67a936ca97..0000000000
--- a/activerecord/test/connections/native_firebird/connection.rb
+++ /dev/null
@@ -1,26 +0,0 @@
-print "Using native Firebird\n"
-require_dependency 'models/course'
-require 'logger'
-
-ActiveRecord::Base.logger = Logger.new("debug.log")
-
-ActiveRecord::Base.configurations = {
- 'arunit' => {
- :adapter => 'firebird',
- :host => 'localhost',
- :username => 'rails',
- :password => 'rails',
- :database => 'activerecord_unittest',
- :charset => 'UTF8'
- },
- 'arunit2' => {
- :adapter => 'firebird',
- :host => 'localhost',
- :username => 'rails',
- :password => 'rails',
- :database => 'activerecord_unittest2'
- }
-}
-
-ActiveRecord::Base.establish_connection 'arunit'
-Course.establish_connection 'arunit2'
diff --git a/activerecord/test/connections/native_frontbase/connection.rb b/activerecord/test/connections/native_frontbase/connection.rb
deleted file mode 100644
index c01d864a8b..0000000000
--- a/activerecord/test/connections/native_frontbase/connection.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-puts 'Using native Frontbase'
-require_dependency 'models/course'
-require 'logger'
-
-ActiveRecord::Base.logger = Logger.new("debug.log")
-
-ActiveRecord::Base.configurations = {
- 'arunit' => {
- :adapter => 'frontbase',
- :host => 'localhost',
- :username => 'rails',
- :password => '',
- :database => 'activerecord_unittest',
- :session_name => "unittest-#{$$}"
- },
- 'arunit2' => {
- :adapter => 'frontbase',
- :host => 'localhost',
- :username => 'rails',
- :password => '',
- :database => 'activerecord_unittest2',
- :session_name => "unittest-#{$$}"
- }
-}
-
-ActiveRecord::Base.establish_connection 'arunit'
-Course.establish_connection 'arunit2'
diff --git a/activerecord/test/connections/native_mysql/connection.rb b/activerecord/test/connections/native_mysql/connection.rb
deleted file mode 100644
index 140e06d631..0000000000
--- a/activerecord/test/connections/native_mysql/connection.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-print "Using native MySQL\n"
-require_dependency 'models/course'
-require 'logger'
-
-ActiveRecord::Base.logger = Logger.new("debug.log")
-
-# GRANT ALL PRIVILEGES ON activerecord_unittest.* to 'rails'@'localhost';
-# GRANT ALL PRIVILEGES ON activerecord_unittest2.* to 'rails'@'localhost';
-
-ActiveRecord::Base.configurations = {
- 'arunit' => {
- :adapter => 'mysql',
- :username => 'rails',
- :encoding => 'utf8',
- :database => 'activerecord_unittest',
- },
- 'arunit2' => {
- :adapter => 'mysql',
- :username => 'rails',
- :database => 'activerecord_unittest2'
- }
-}
-
-ActiveRecord::Base.establish_connection 'arunit'
-Course.establish_connection 'arunit2'
diff --git a/activerecord/test/connections/native_mysql2/connection.rb b/activerecord/test/connections/native_mysql2/connection.rb
deleted file mode 100644
index c6f198b1ac..0000000000
--- a/activerecord/test/connections/native_mysql2/connection.rb
+++ /dev/null
@@ -1,25 +0,0 @@
-print "Using native Mysql2\n"
-require_dependency 'models/course'
-require 'logger'
-
-ActiveRecord::Base.logger = Logger.new("debug.log")
-
-# GRANT ALL PRIVILEGES ON activerecord_unittest.* to 'rails'@'localhost';
-# GRANT ALL PRIVILEGES ON activerecord_unittest2.* to 'rails'@'localhost';
-
-ActiveRecord::Base.configurations = {
- 'arunit' => {
- :adapter => 'mysql2',
- :username => 'rails',
- :encoding => 'utf8',
- :database => 'activerecord_unittest',
- },
- 'arunit2' => {
- :adapter => 'mysql2',
- :username => 'rails',
- :database => 'activerecord_unittest2'
- }
-}
-
-ActiveRecord::Base.establish_connection 'arunit'
-Course.establish_connection 'arunit2'
diff --git a/activerecord/test/connections/native_openbase/connection.rb b/activerecord/test/connections/native_openbase/connection.rb
deleted file mode 100644
index 655cb9ca26..0000000000
--- a/activerecord/test/connections/native_openbase/connection.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-print "Using native OpenBase\n"
-require_dependency 'models/course'
-require 'logger'
-
-ActiveRecord::Base.logger = Logger.new("debug.log")
-
-ActiveRecord::Base.configurations = {
- 'arunit' => {
- :adapter => 'openbase',
- :username => 'admin',
- :database => 'activerecord_unittest',
- },
- 'arunit2' => {
- :adapter => 'openbase',
- :username => 'admin',
- :database => 'activerecord_unittest2'
- }
-}
-
-ActiveRecord::Base.establish_connection 'arunit'
-Course.establish_connection 'arunit2'
diff --git a/activerecord/test/connections/native_oracle/connection.rb b/activerecord/test/connections/native_oracle/connection.rb
deleted file mode 100644
index 99f921879c..0000000000
--- a/activerecord/test/connections/native_oracle/connection.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-# uses oracle_enhanced adapter in ENV['ORACLE_ENHANCED_PATH'] or from github.com/rsim/oracle-enhanced.git
-require 'active_record/connection_adapters/oracle_enhanced_adapter'
-
-# otherwise failed with silence_warnings method missing exception
-require 'active_support/core_ext/kernel/reporting'
-
-print "Using Oracle\n"
-require_dependency 'models/course'
-require 'logger'
-
-ActiveRecord::Base.logger = Logger.new("debug.log")
-
-# Set these to your database connection strings
-ENV['ARUNIT_DB_NAME'] ||= 'orcl'
-
-ActiveRecord::Base.configurations = {
- 'arunit' => {
- :adapter => 'oracle_enhanced',
- :database => ENV['ARUNIT_DB_NAME'],
- :username => 'arunit',
- :password => 'arunit',
- :emulate_oracle_adapter => true
- },
- 'arunit2' => {
- :adapter => 'oracle_enhanced',
- :database => ENV['ARUNIT_DB_NAME'],
- :username => 'arunit2',
- :password => 'arunit2',
- :emulate_oracle_adapter => true
- }
-}
-
-ActiveRecord::Base.establish_connection 'arunit'
-Course.establish_connection 'arunit2'
-
diff --git a/activerecord/test/connections/native_postgresql/connection.rb b/activerecord/test/connections/native_postgresql/connection.rb
deleted file mode 100644
index 3b5ff90003..0000000000
--- a/activerecord/test/connections/native_postgresql/connection.rb
+++ /dev/null
@@ -1,21 +0,0 @@
-print "Using native PostgreSQL\n"
-require_dependency 'models/course'
-require 'logger'
-
-ActiveRecord::Base.logger = Logger.new("debug.log")
-
-ActiveRecord::Base.configurations = {
- 'arunit' => {
- :adapter => 'postgresql',
- :database => 'activerecord_unittest',
- :min_messages => 'warning'
- },
- 'arunit2' => {
- :adapter => 'postgresql',
- :database => 'activerecord_unittest2',
- :min_messages => 'warning'
- }
-}
-
-ActiveRecord::Base.establish_connection 'arunit'
-Course.establish_connection 'arunit2'
diff --git a/activerecord/test/connections/native_sqlite3/connection.rb b/activerecord/test/connections/native_sqlite3/connection.rb
deleted file mode 100644
index c2aff5551f..0000000000
--- a/activerecord/test/connections/native_sqlite3/connection.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-print "Using native SQLite3\n"
-require_dependency 'models/course'
-require 'logger'
-ActiveRecord::Base.logger = Logger.new("debug.log")
-
-BASE_DIR = FIXTURES_ROOT
-sqlite_test_db = "#{BASE_DIR}/fixture_database.sqlite3"
-sqlite_test_db2 = "#{BASE_DIR}/fixture_database_2.sqlite3"
-
-def make_connection(clazz, db_file)
- ActiveRecord::Base.configurations = { clazz.name => { :adapter => 'sqlite3', :database => db_file, :timeout => 5000 } }
- clazz.establish_connection(clazz.name)
-end
-
-make_connection(ActiveRecord::Base, sqlite_test_db)
-make_connection(Course, sqlite_test_db2)
diff --git a/activerecord/test/connections/native_sqlite3_mem/connection.rb b/activerecord/test/connections/native_sqlite3_mem/connection.rb
deleted file mode 100644
index 14e10900d1..0000000000
--- a/activerecord/test/connections/native_sqlite3_mem/connection.rb
+++ /dev/null
@@ -1,19 +0,0 @@
-# This file connects to an in-memory SQLite3 database, which is a very fast way to run the tests.
-# The downside is that disconnect from the database results in the database effectively being
-# wiped. For this reason, pooled_connections_test.rb is disabled when using an in-memory database.
-
-print "Using native SQLite3 (in memory)\n"
-require_dependency 'models/course'
-require 'logger'
-ActiveRecord::Base.logger = Logger.new("debug.log")
-
-class SqliteError < StandardError
-end
-
-def make_connection(clazz)
- ActiveRecord::Base.configurations = { clazz.name => { :adapter => 'sqlite3', :database => ':memory:' } }
- clazz.establish_connection(clazz.name)
-end
-
-make_connection(ActiveRecord::Base)
-make_connection(Course)
diff --git a/activerecord/test/connections/native_sybase/connection.rb b/activerecord/test/connections/native_sybase/connection.rb
deleted file mode 100644
index 3282d26922..0000000000
--- a/activerecord/test/connections/native_sybase/connection.rb
+++ /dev/null
@@ -1,23 +0,0 @@
-print "Using native Sybase Open Client\n"
-require_dependency 'models/course'
-require 'logger'
-
-ActiveRecord::Base.logger = Logger.new("debug.log")
-
-ActiveRecord::Base.configurations = {
- 'arunit' => {
- :adapter => 'sybase',
- :host => 'database_ASE',
- :username => 'sa',
- :database => 'activerecord_unittest'
- },
- 'arunit2' => {
- :adapter => 'sybase',
- :host => 'database_ASE',
- :username => 'sa',
- :database => 'activerecord_unittest2'
- }
-}
-
-ActiveRecord::Base.establish_connection 'arunit'
-Course.establish_connection 'arunit2'
diff --git a/activerecord/test/models/comment.rb b/activerecord/test/models/comment.rb
index 2a4c37089a..43650c0427 100644
--- a/activerecord/test/models/comment.rb
+++ b/activerecord/test/models/comment.rb
@@ -6,7 +6,8 @@ class Comment < ActiveRecord::Base
scope :for_first_author,
:joins => :post,
:conditions => { "posts.author_id" => 1 }
-
+ scope :created
+
belongs_to :post, :counter_cache => true
has_many :ratings
diff --git a/activerecord/test/models/contract.rb b/activerecord/test/models/contract.rb
index 94fd48e12a..2cf5aa7a85 100644
--- a/activerecord/test/models/contract.rb
+++ b/activerecord/test/models/contract.rb
@@ -1,4 +1,19 @@
class Contract < ActiveRecord::Base
belongs_to :company
belongs_to :developer
+
+ before_save :hi
+ after_save :bye
+
+ attr_accessor :hi_count, :bye_count
+
+ def hi
+ @hi_count ||= 0
+ @hi_count += 1
+ end
+
+ def bye
+ @bye_count ||= 0
+ @bye_count += 1
+ end
end
diff --git a/activerecord/test/models/developer.rb b/activerecord/test/models/developer.rb
index 41c52f7df0..98d6aa22f7 100644
--- a/activerecord/test/models/developer.rb
+++ b/activerecord/test/models/developer.rb
@@ -86,6 +86,11 @@ class DeveloperWithBeforeDestroyRaise < ActiveRecord::Base
end
end
+class DeveloperWithSelect < ActiveRecord::Base
+ self.table_name = 'developers'
+ default_scope select('name')
+end
+
class DeveloperOrderedBySalary < ActiveRecord::Base
self.table_name = 'developers'
default_scope :order => 'salary DESC'
diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb
index f2ab7b053e..affa37b02d 100644
--- a/activerecord/test/models/post.rb
+++ b/activerecord/test/models/post.rb
@@ -36,6 +36,10 @@ class Post < ActiveRecord::Base
def find_most_recent
find(:first, :order => "id DESC")
end
+
+ def newest
+ created.last
+ end
end
has_many :author_favorites, :through => :author
diff --git a/activerecord/test/support/config.rb b/activerecord/test/support/config.rb
new file mode 100644
index 0000000000..3b1598e368
--- /dev/null
+++ b/activerecord/test/support/config.rb
@@ -0,0 +1,39 @@
+require 'yaml'
+require 'erubis'
+require 'fileutils'
+
+module ARTest
+ class << self
+ def config
+ @config ||= read_config
+ end
+
+ private
+
+ def read_config
+ unless File.exist?(TEST_ROOT + '/config.yml')
+ FileUtils.cp TEST_ROOT + '/config.example.yml', TEST_ROOT + '/config.yml'
+ end
+
+ raw = File.read(TEST_ROOT + '/config.yml')
+ erb = Erubis::Eruby.new(raw)
+ expand_config(YAML.parse(erb.result(binding)).transform)
+ end
+
+ def expand_config(config)
+ config['connections'].each do |adapter, connection|
+ dbs = [['arunit', 'activerecord_unittest'], ['arunit2', 'activerecord_unittest2']]
+ dbs.each do |name, dbname|
+ unless connection[name].is_a?(Hash)
+ connection[name] = { 'database' => connection[name] }
+ end
+
+ connection[name]['database'] ||= dbname
+ connection[name]['adapter'] ||= adapter
+ end
+ end
+
+ config
+ end
+ end
+end
diff --git a/activerecord/test/support/connection.rb b/activerecord/test/support/connection.rb
new file mode 100644
index 0000000000..fcd2e4dee5
--- /dev/null
+++ b/activerecord/test/support/connection.rb
@@ -0,0 +1,20 @@
+require 'logger'
+require_dependency 'models/course'
+
+module ARTest
+ def self.connection_name
+ ENV['ARCONN'] || config['default_connection']
+ end
+
+ def self.connection_config
+ config['connections'][connection_name]
+ end
+
+ def self.connect
+ puts "Using #{connection_name}"
+ ActiveRecord::Base.logger = Logger.new("debug.log")
+ ActiveRecord::Base.configurations = connection_config
+ ActiveRecord::Base.establish_connection 'arunit'
+ Course.establish_connection 'arunit2'
+ end
+end
diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb
index 0c272fa093..74730ca01f 100644
--- a/activeresource/lib/active_resource/base.rb
+++ b/activeresource/lib/active_resource/base.rb
@@ -283,7 +283,7 @@ module ActiveResource
# attribute 'name', :string
#
# # or use the convenience methods and pass >=1 attribute names
- # string 'eye_colour', 'hair_colour'
+ # string 'eye_color', 'hair_color'
# integer 'age'
# float 'height', 'weight'
#
diff --git a/activeresource/lib/active_resource/schema.rb b/activeresource/lib/active_resource/schema.rb
index 3fd37a9bb6..5957969aa2 100644
--- a/activeresource/lib/active_resource/schema.rb
+++ b/activeresource/lib/active_resource/schema.rb
@@ -20,8 +20,8 @@ module ActiveResource # :nodoc:
# end
#
# The schema stores the name and type of each attribute. That is then
- # read out by the schema method to populate the actual
- # Resource's schema
+ # read out by the schema method to populate the schema of the actual
+ # resource.
def initialize
@attrs = {}
end
@@ -40,6 +40,12 @@ module ActiveResource # :nodoc:
# The following are the attribute types supported by Active Resource
# migrations.
KNOWN_ATTRIBUTE_TYPES.each do |attr_type|
+ # def string(*args)
+ # options = args.extract_options!
+ # attr_names = args
+ #
+ # attr_names.each { |name| attribute(name, 'string', options) }
+ # end
class_eval <<-EOV, __FILE__, __LINE__ + 1
def #{attr_type.to_s}(*args)
options = args.extract_options!
diff --git a/activeresource/test/cases/base/load_test.rb b/activeresource/test/cases/base/load_test.rb
index d6b04cfaa8..0d030148d0 100644
--- a/activeresource/test/cases/base/load_test.rb
+++ b/activeresource/test/cases/base/load_test.rb
@@ -72,7 +72,6 @@ class BaseLoadTest < Test::Unit::TestCase
def test_after_load_attributes_are_accessible_via_indifferent_access
assert_equal Hash.new, @person.attributes
- matz_attributes = @matz.values.first
assert_equal @matz.stringify_keys, @person.load(@matz).attributes
assert_equal @matz[:name], @person.attributes['name']
assert_equal @matz[:name], @person.attributes[:name]
diff --git a/activeresource/test/cases/finder_test.rb b/activeresource/test/cases/finder_test.rb
index 9c51f2a390..5fbbfeef6e 100644
--- a/activeresource/test/cases/finder_test.rb
+++ b/activeresource/test/cases/finder_test.rb
@@ -95,7 +95,7 @@ class FinderTest < Test::Unit::TestCase
def test_find_all_sub_objects_not_found
assert_nothing_raised do
- addys = StreetAddress.find(:all, :params => { :person_id => 2 })
+ StreetAddress.find(:all, :params => { :person_id => 2 })
end
end
diff --git a/activeresource/test/cases/log_subscriber_test.rb b/activeresource/test/cases/log_subscriber_test.rb
index b9143f5b67..ab5c22a783 100644
--- a/activeresource/test/cases/log_subscriber_test.rb
+++ b/activeresource/test/cases/log_subscriber_test.rb
@@ -23,7 +23,7 @@ class LogSubscriberTest < ActiveSupport::TestCase
end
def test_request_notification
- matz = Person.find(1)
+ Person.find(1)
wait
assert_equal 2, @logger.logged(:info).size
assert_equal "GET http://37s.sunrise.i:3000/people/1.json", @logger.logged(:info)[0]
diff --git a/activeresource/test/cases/observing_test.rb b/activeresource/test/cases/observing_test.rb
index ca3ab5d03d..58d3d389ff 100644
--- a/activeresource/test/cases/observing_test.rb
+++ b/activeresource/test/cases/observing_test.rb
@@ -37,7 +37,7 @@ class ObservingTest < Test::Unit::TestCase
end
def test_create_fires_save_and_create_notifications
- rick = Person.create(:name => 'Rick')
+ Person.create(:name => 'Rick')
assert_equal [:before_save, :before_create, :after_create, :after_save], self.history
end
diff --git a/activesupport/CHANGELOG b/activesupport/CHANGELOG
index bfd1e91bb5..6b7044aeae 100644
--- a/activesupport/CHANGELOG
+++ b/activesupport/CHANGELOG
@@ -2,8 +2,13 @@
* Removed ActiveSupport::SecureRandom in favour of SecureRandom from the standard library [Jon Leighton]
+* ActiveSupport::OrderedHash now has different behavior for #each and
+#each_pair when given a block accepting its parameters with a splat. [Andrew Radev]
+
*Rails 3.1.0 (unreleased)*
+* ActiveSupport::Dependencies now raises NameError if it finds an existing constant in load_missing_constant. This better reflects the nature of the error which is usually caused by calling constantize on a nested constant. [Andrew White]
+
* Deprecated ActiveSupport::SecureRandom in favour of SecureRandom from the standard library [Jon Leighton]
* New reporting method Kernel#quietly. [fxn]
diff --git a/activesupport/lib/active_support/cache/mem_cache_store.rb b/activesupport/lib/active_support/cache/mem_cache_store.rb
index 7ef1497ac2..64d2c3bff6 100644
--- a/activesupport/lib/active_support/cache/mem_cache_store.rb
+++ b/activesupport/lib/active_support/cache/mem_cache_store.rb
@@ -31,7 +31,7 @@ module ActiveSupport
DELETED = "DELETED\r\n"
end
- ESCAPE_KEY_CHARS = /[\x00-\x20%\x7F-\xFF]/
+ ESCAPE_KEY_CHARS = /[\x00-\x20%\x7F-\xFF]/n
def self.build_mem_cache(*addresses)
addresses = addresses.flatten
diff --git a/activesupport/lib/active_support/core_ext/array/access.rb b/activesupport/lib/active_support/core_ext/array/access.rb
index 2df4fd1da1..6162f7af27 100644
--- a/activesupport/lib/active_support/core_ext/array/access.rb
+++ b/activesupport/lib/active_support/core_ext/array/access.rb
@@ -16,7 +16,7 @@ class Array
# %w( a b c d ).to(10) # => %w( a b c d )
# %w().to(0) # => %w()
def to(position)
- self[0..position]
+ self.first position + 1
end
# Equal to <tt>self[1]</tt>.
diff --git a/activesupport/lib/active_support/core_ext/date/freeze.rb b/activesupport/lib/active_support/core_ext/date/freeze.rb
index 4edd715ba2..a731f8345e 100644
--- a/activesupport/lib/active_support/core_ext/date/freeze.rb
+++ b/activesupport/lib/active_support/core_ext/date/freeze.rb
@@ -5,7 +5,7 @@
# first call will result in a frozen object error since the memo
# instance variable is uninitialized.
#
-# Work around by eagerly memoizing before freezing.
+# Work around by eagerly memoizing before the first freeze.
#
# Ruby 1.9 uses a preinitialized instance variable so it's unaffected.
# This hack is as close as we can get to feature detection:
@@ -17,9 +17,11 @@ if RUBY_VERSION < '1.9'
if frozen_object_error.message =~ /frozen/
class Date #:nodoc:
def freeze
- self.class.private_instance_methods(false).each do |m|
- if m.to_s =~ /\A__\d+__\Z/
- instance_variable_set(:"@#{m}", [send(m)])
+ unless frozen?
+ self.class.private_instance_methods(false).each do |m|
+ if m.to_s =~ /\A__\d+__\Z/
+ instance_variable_set(:"@#{m}", [send(m)])
+ end
end
end
diff --git a/activesupport/lib/active_support/core_ext/kernel/reporting.rb b/activesupport/lib/active_support/core_ext/kernel/reporting.rb
index c6920098a8..526b8378a5 100644
--- a/activesupport/lib/active_support/core_ext/kernel/reporting.rb
+++ b/activesupport/lib/active_support/core_ext/kernel/reporting.rb
@@ -59,7 +59,7 @@ module Kernel
raise unless exception_classes.any? { |cls| e.kind_of?(cls) }
end
end
-
+
# Captures the given stream and returns it:
#
# stream = capture(:stdout) { puts "Cool" }
diff --git a/activesupport/lib/active_support/core_ext/module/delegation.rb b/activesupport/lib/active_support/core_ext/module/delegation.rb
index 3a7652f5bf..1777a4b32d 100644
--- a/activesupport/lib/active_support/core_ext/module/delegation.rb
+++ b/activesupport/lib/active_support/core_ext/module/delegation.rb
@@ -113,7 +113,7 @@ class Module
raise ArgumentError, "Can only automatically set the delegation prefix when delegating to a method."
end
- prefix = options[:prefix] && "#{options[:prefix] == true ? to : options[:prefix]}_" || ''
+ prefix = options[:prefix] ? "#{options[:prefix] == true ? to : options[:prefix]}_" : ''
file, line = caller.first.split(':', 2)
line = line.to_i
diff --git a/activesupport/lib/active_support/core_ext/string/output_safety.rb b/activesupport/lib/active_support/core_ext/string/output_safety.rb
index c27cbc37c5..aeb21ed8df 100644
--- a/activesupport/lib/active_support/core_ext/string/output_safety.rb
+++ b/activesupport/lib/active_support/core_ext/string/output_safety.rb
@@ -74,6 +74,7 @@ end
module ActiveSupport #:nodoc:
class SafeBuffer < String
+ UNSAFE_STRING_METHODS = ["capitalize", "chomp", "chop", "delete", "downcase", "gsub", "lstrip", "next", "reverse", "rstrip", "slice", "squeeze", "strip", "sub", "succ", "swapcase", "tr", "tr_s", "upcase"].freeze
alias safe_concat concat
def concat(value)
@@ -110,6 +111,18 @@ module ActiveSupport #:nodoc:
to_str.to_yaml(*args)
end
+
+ UNSAFE_STRING_METHODS.each do |unsafe_method|
+ class_eval <<-EOT, __FILE__, __LINE__
+ def #{unsafe_method}(*args)
+ super.to_str
+ end
+
+ def #{unsafe_method}!(*args)
+ raise TypeError, "Cannot modify SafeBuffer in place"
+ end
+ EOT
+ end
end
end
diff --git a/activesupport/lib/active_support/dependencies.rb b/activesupport/lib/active_support/dependencies.rb
index cae68c3c95..26c5c157cb 100644
--- a/activesupport/lib/active_support/dependencies.rb
+++ b/activesupport/lib/active_support/dependencies.rb
@@ -473,7 +473,7 @@ module ActiveSupport #:nodoc:
raise ArgumentError, "A copy of #{from_mod} has been removed from the module tree but is still active!"
end
- raise ArgumentError, "#{from_mod} is not missing constant #{const_name}!" if local_const_defined?(from_mod, const_name)
+ raise NameError, "#{from_mod} is not missing constant #{const_name}!" if local_const_defined?(from_mod, const_name)
qualified_name = qualified_name_for from_mod, const_name
path_suffix = qualified_name.underscore
diff --git a/activesupport/lib/active_support/ordered_hash.rb b/activesupport/lib/active_support/ordered_hash.rb
index 762a64a881..68f4bd66da 100644
--- a/activesupport/lib/active_support/ordered_hash.rb
+++ b/activesupport/lib/active_support/ordered_hash.rb
@@ -158,7 +158,11 @@ module ActiveSupport
self
end
- alias_method :each_pair, :each
+ def each_pair
+ return to_enum(:each_pair) unless block_given?
+ @keys.each {|key| yield key, self[key]}
+ self
+ end
alias_method :select, :find_all
diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb
index 02c19448fd..dd23f8d82d 100644
--- a/activesupport/lib/active_support/testing/performance.rb
+++ b/activesupport/lib/active_support/testing/performance.rb
@@ -9,7 +9,7 @@ module ActiveSupport
module Testing
module Performance
extend ActiveSupport::Concern
-
+
included do
superclass_delegating_accessor :profile_options
self.profile_options = {}
@@ -20,7 +20,7 @@ module ActiveSupport
include ForClassicTestUnit
end
end
-
+
# each implementation should define metrics and freeze the defaults
DEFAULTS =
if ARGV.include?('--benchmark') # HAX for rake test
@@ -32,7 +32,7 @@ module ActiveSupport
:output => 'tmp/performance',
:benchmark => false }
end
-
+
def full_profile_options
DEFAULTS.merge(profile_options)
end
@@ -40,7 +40,7 @@ module ActiveSupport
def full_test_name
"#{self.class.name}##{method_name}"
end
-
+
module ForMiniTest
def run(runner)
@runner = runner
@@ -53,7 +53,7 @@ module ActiveSupport
end
end
end
-
+
return
end
@@ -122,7 +122,7 @@ module ActiveSupport
protected
# overridden by each implementation
def run_gc; end
-
+
def run_warmup
run_gc
@@ -132,7 +132,7 @@ module ActiveSupport
run_gc
end
-
+
def run_profile(metric)
klass = full_profile_options[:benchmark] ? Benchmarker : Profiler
performer = klass.new(self, metric)
@@ -163,7 +163,7 @@ module ActiveSupport
"#{full_profile_options[:output]}/#{full_test_name}_#{@metric.name}"
end
end
-
+
# overridden by each implementation
class Profiler < Performer
def time_with_block
@@ -171,7 +171,7 @@ module ActiveSupport
yield
Time.now - before
end
-
+
def run; end
def record; end
end
@@ -181,10 +181,10 @@ module ActiveSupport
super
@supported = @metric.respond_to?('measure')
end
-
+
def run
return unless @supported
-
+
full_profile_options[:runs].to_i.times { run_test(@metric, :benchmark) }
@total = @metric.total
end
@@ -237,7 +237,7 @@ module ActiveSupport
"#{super}.csv"
end
end
-
+
module Metrics
def self.[](name)
const_get(name.to_s.camelize)
@@ -247,7 +247,7 @@ module ActiveSupport
class Base
include ActionView::Helpers::NumberHelper
-
+
attr_reader :total
def initialize
@@ -265,15 +265,15 @@ module ActiveSupport
@total += (measure - before)
end
end
-
+
# overridden by each implementation
def profile; end
-
+
protected
# overridden by each implementation
def with_gc_stats; end
end
-
+
class Time < Base
def measure
::Time.now.to_f
@@ -287,19 +287,19 @@ module ActiveSupport
end
end
end
-
+
class Amount < Base
def format(measurement)
number_with_delimiter(measurement.floor)
end
end
-
+
class DigitalInformationUnit < Base
def format(measurement)
number_to_human_size(measurement, :precision => 2)
end
end
-
+
# each implementation provides its own metrics like ProcessTime, Memory or GcRuns
end
end
diff --git a/activesupport/lib/active_support/testing/performance/jruby.rb b/activesupport/lib/active_support/testing/performance/jruby.rb
index 326904bbac..b347539f13 100644
--- a/activesupport/lib/active_support/testing/performance/jruby.rb
+++ b/activesupport/lib/active_support/testing/performance/jruby.rb
@@ -1,5 +1,5 @@
require 'jruby/profiler'
-require 'java'
+require 'java'
java_import java.lang.management.ManagementFactory
module ActiveSupport
@@ -12,21 +12,21 @@ module ActiveSupport
{ :metrics => [:wall_time],
:formats => [:flat, :graph] }
end).freeze
-
+
protected
def run_gc
ManagementFactory.memory_mx_bean.gc
- end
+ end
class Profiler < Performer
def initialize(*args)
super
@supported = @metric.is_a?(Metrics::WallTime)
end
-
+
def run
return unless @supported
-
+
@total = time_with_block do
@data = JRuby::Profiler.profile do
full_profile_options[:runs].to_i.times { run_test(@metric, :profile) }
@@ -36,7 +36,7 @@ module ActiveSupport
def record
return unless @supported
-
+
klasses = full_profile_options[:formats].map { |f| JRuby::Profiler.const_get("#{f.to_s.camelize}ProfilePrinter") }.compact
klasses.each do |klass|
@@ -61,7 +61,7 @@ module ActiveSupport
end
end
- module Metrics
+ module Metrics
class Base
def profile
yield
@@ -85,7 +85,7 @@ module ActiveSupport
ManagementFactory.thread_mx_bean.get_current_thread_cpu_time / 1000 / 1000 / 1000.0 # seconds
end
end
-
+
class UserTime < Time
def measure
ManagementFactory.thread_mx_bean.get_current_thread_user_time / 1000 / 1000 / 1000.0 # seconds
@@ -97,7 +97,7 @@ module ActiveSupport
ManagementFactory.memory_mx_bean.non_heap_memory_usage.used + ManagementFactory.memory_mx_bean.heap_memory_usage.used
end
end
-
+
class GcRuns < Amount
def measure
ManagementFactory.garbage_collector_mx_beans.inject(0) { |total_runs, current_gc| total_runs += current_gc.collection_count }
diff --git a/activesupport/lib/active_support/testing/performance/rubinius.rb b/activesupport/lib/active_support/testing/performance/rubinius.rb
index 198d235548..d9ebfbe352 100644
--- a/activesupport/lib/active_support/testing/performance/rubinius.rb
+++ b/activesupport/lib/active_support/testing/performance/rubinius.rb
@@ -10,12 +10,12 @@ module ActiveSupport
{ :metrics => [:wall_time],
:formats => [:flat, :graph] }
end).freeze
-
+
protected
def run_gc
GC.run(true)
end
-
+
class Performer; end
class Profiler < Performer
@@ -23,35 +23,35 @@ module ActiveSupport
super
@supported = @metric.is_a?(Metrics::WallTime)
end
-
+
def run
return unless @supported
-
+
@profiler = Rubinius::Profiler::Instrumenter.new
-
+
@total = time_with_block do
@profiler.profile(false) do
full_profile_options[:runs].to_i.times { run_test(@metric, :profile) }
end
end
end
-
+
def record
return unless @supported
-
+
if(full_profile_options[:formats].include?(:flat))
create_path_and_open_file(:flat) do |file|
@profiler.show(file)
end
end
-
+
if(full_profile_options[:formats].include?(:graph))
create_path_and_open_file(:graph) do |file|
@profiler.show(file)
end
end
end
-
+
protected
def create_path_and_open_file(printer_name)
fname = "#{output_filename}_#{printer_name}.txt"
@@ -62,10 +62,10 @@ module ActiveSupport
end
end
- module Metrics
+ module Metrics
class Base
attr_reader :loopback
-
+
def profile
yield
end
diff --git a/activesupport/lib/active_support/testing/performance/ruby.rb b/activesupport/lib/active_support/testing/performance/ruby.rb
index b29ec6719c..7d6d047ef6 100644
--- a/activesupport/lib/active_support/testing/performance/ruby.rb
+++ b/activesupport/lib/active_support/testing/performance/ruby.rb
@@ -16,7 +16,7 @@ module ActiveSupport
:metrics => [:process_time, :memory, :objects],
:formats => [:flat, :graph_html, :call_tree, :call_stack] }
end).freeze
-
+
protected
def run_gc
GC.start
@@ -77,7 +77,7 @@ module ActiveSupport
def measure_mode
self.class::Mode
end
-
+
def profile
RubyProf.resume
yield
@@ -91,7 +91,7 @@ module ActiveSupport
yield
end
end
-
+
class ProcessTime < Time
Mode = RubyProf::PROCESS_TIME if RubyProf.const_defined?(:PROCESS_TIME)
diff --git a/activesupport/lib/active_support/testing/performance/ruby/mri.rb b/activesupport/lib/active_support/testing/performance/ruby/mri.rb
index 86e650050b..142279dd6e 100644
--- a/activesupport/lib/active_support/testing/performance/ruby/mri.rb
+++ b/activesupport/lib/active_support/testing/performance/ruby/mri.rb
@@ -15,7 +15,7 @@ module ActiveSupport
end
end
end
-
+
class Memory < DigitalInformationUnit
# Ruby 1.8 + ruby-prof wrapper
if RubyProf.respond_to?(:measure_memory)
@@ -24,7 +24,7 @@ module ActiveSupport
end
end
end
-
+
class Objects < Amount
# Ruby 1.8 + ruby-prof wrapper
if RubyProf.respond_to?(:measure_allocations)
@@ -33,7 +33,7 @@ module ActiveSupport
end
end
end
-
+
class GcRuns < Amount
# Ruby 1.8 + ruby-prof wrapper
if RubyProf.respond_to?(:measure_gc_runs)
@@ -42,7 +42,7 @@ module ActiveSupport
end
end
end
-
+
class GcTime < Time
# Ruby 1.8 + ruby-prof wrapper
if RubyProf.respond_to?(:measure_gc_time)
@@ -55,5 +55,3 @@ module ActiveSupport
end
end
end
-
-
diff --git a/activesupport/lib/active_support/testing/performance/ruby/yarv.rb b/activesupport/lib/active_support/testing/performance/ruby/yarv.rb
index 62095a8fe4..7873262331 100644
--- a/activesupport/lib/active_support/testing/performance/ruby/yarv.rb
+++ b/activesupport/lib/active_support/testing/performance/ruby/yarv.rb
@@ -15,7 +15,7 @@ module ActiveSupport
end
end
end
-
+
class Memory < DigitalInformationUnit
# Ruby 1.9 + GCdata patch
if GC.respond_to?(:malloc_allocated_size)
@@ -24,7 +24,7 @@ module ActiveSupport
end
end
end
-
+
class Objects < Amount
# Ruby 1.9 + GCdata patch
if GC.respond_to?(:malloc_allocations)
@@ -33,7 +33,7 @@ module ActiveSupport
end
end
end
-
+
class GcRuns < Amount
# Ruby 1.9
if GC.respond_to?(:count)
@@ -42,7 +42,7 @@ module ActiveSupport
end
end
end
-
+
class GcTime < Time
# Ruby 1.9 with GC::Profiler
if defined?(GC::Profiler) && GC::Profiler.respond_to?(:total_time)
diff --git a/activesupport/lib/active_support/xml_mini/jdom.rb b/activesupport/lib/active_support/xml_mini/jdom.rb
index 7aefabfdd1..6c222b83ba 100644
--- a/activesupport/lib/active_support/xml_mini/jdom.rb
+++ b/activesupport/lib/active_support/xml_mini/jdom.rb
@@ -41,7 +41,7 @@ module ActiveSupport
xml_string_reader = StringReader.new(data)
xml_input_source = InputSource.new(xml_string_reader)
doc = @dbf.new_document_builder.parse(xml_input_source)
- merge_element!({}, doc.document_element)
+ merge_element!({CONTENT_KEY => ''}, doc.document_element)
end
end
@@ -54,9 +54,14 @@ module ActiveSupport
# element::
# XML element to merge into hash
def merge_element!(hash, element)
+ delete_empty(hash)
merge!(hash, element.tag_name, collapse(element))
end
+ def delete_empty(hash)
+ hash.delete(CONTENT_KEY) if hash[CONTENT_KEY] == ''
+ end
+
# Actually converts an XML document element into a data structure.
#
# element::
@@ -84,6 +89,7 @@ module ActiveSupport
# element::
# XML element whose texts are to me merged into the hash
def merge_texts!(hash, element)
+ delete_empty(hash)
text_children = texts(element)
if text_children.join.empty?
hash
@@ -128,6 +134,7 @@ module ActiveSupport
attribute_hash = {}
attributes = element.attributes
for i in 0...attributes.length
+ attribute_hash[CONTENT_KEY] ||= ''
attribute_hash[attributes.item(i).name] = attributes.item(i).value
end
attribute_hash
diff --git a/activesupport/test/core_ext/date_ext_test.rb b/activesupport/test/core_ext/date_ext_test.rb
index d81693209f..b4f848cd44 100644
--- a/activesupport/test/core_ext/date_ext_test.rb
+++ b/activesupport/test/core_ext/date_ext_test.rb
@@ -454,4 +454,10 @@ class DateExtBehaviorTest < Test::Unit::TestCase
Date.today.freeze.inspect
end
end
+
+ def test_can_freeze_twice
+ assert_nothing_raised do
+ Date.today.freeze.freeze
+ end
+ end
end
diff --git a/activesupport/test/dependencies_test.rb b/activesupport/test/dependencies_test.rb
index 2ddbce5150..b4edf0f51d 100644
--- a/activesupport/test/dependencies_test.rb
+++ b/activesupport/test/dependencies_test.rb
@@ -441,7 +441,7 @@ class DependenciesTest < Test::Unit::TestCase
with_autoloading_fixtures do
require_dependency '././counting_loader'
assert_equal 1, $counting_loaded_times
- assert_raise(ArgumentError) { ActiveSupport::Dependencies.load_missing_constant Object, :CountingLoader }
+ assert_raise(NameError) { ActiveSupport::Dependencies.load_missing_constant Object, :CountingLoader }
assert_equal 1, $counting_loaded_times
end
end
diff --git a/activesupport/test/ordered_hash_test.rb b/activesupport/test/ordered_hash_test.rb
index f3dcd7b068..bf851dbcbc 100644
--- a/activesupport/test/ordered_hash_test.rb
+++ b/activesupport/test/ordered_hash_test.rb
@@ -114,6 +114,9 @@ class OrderedHashTest < Test::Unit::TestCase
end
assert_equal @values, values
assert_equal @keys, keys
+
+ expected_class = RUBY_VERSION < '1.9' ? Enumerable::Enumerator : Enumerator
+ assert_kind_of expected_class, @ordered_hash.each_pair
end
def test_find_all
@@ -257,6 +260,26 @@ class OrderedHashTest < Test::Unit::TestCase
assert_equal @values, values
end
+ def test_each_when_yielding_to_block_with_splat
+ hash_values = []
+ ordered_hash_values = []
+
+ @hash.each { |*v| hash_values << v }
+ @ordered_hash.each { |*v| ordered_hash_values << v }
+
+ assert_equal hash_values.sort, ordered_hash_values.sort
+ end
+
+ def test_each_pair_when_yielding_to_block_with_splat
+ hash_values = []
+ ordered_hash_values = []
+
+ @hash.each_pair { |*v| hash_values << v }
+ @ordered_hash.each_pair { |*v| ordered_hash_values << v }
+
+ assert_equal hash_values.sort, ordered_hash_values.sort
+ end
+
def test_order_after_yaml_serialization
@deserialized_ordered_hash = YAML.load(YAML.dump(@ordered_hash))
diff --git a/activesupport/test/safe_buffer_test.rb b/activesupport/test/safe_buffer_test.rb
index a4e2acbb32..3a9854358c 100644
--- a/activesupport/test/safe_buffer_test.rb
+++ b/activesupport/test/safe_buffer_test.rb
@@ -60,4 +60,16 @@ class SafeBufferTest < ActiveSupport::TestCase
yaml = YAML.dump data
assert_equal({'str' => str}, YAML.load(yaml))
end
+
+ test "Should not return safe buffer from gsub" do
+ altered_buffer = @buffer.gsub('', 'asdf')
+ assert_equal 'asdf', altered_buffer
+ assert !altered_buffer.html_safe?
+ end
+
+ test "Should not allow gsub! on safe buffers" do
+ assert_raise TypeError do
+ @buffer.gsub!('', 'asdf')
+ end
+ end
end
diff --git a/activesupport/test/test_test.rb b/activesupport/test/test_test.rb
index ee5a20c789..5bd995aa32 100644
--- a/activesupport/test/test_test.rb
+++ b/activesupport/test/test_test.rb
@@ -50,7 +50,7 @@ class AssertDifferenceTest < ActiveSupport::TestCase
def test_expression_is_evaluated_in_the_appropriate_scope
silence_warnings do
- local_scope = 'foo'
+ local_scope = local_scope = 'foo'
assert_difference('local_scope; @object.num') { @object.increment }
end
end
diff --git a/activesupport/test/xml_mini/jdom_engine_test.rb b/activesupport/test/xml_mini/jdom_engine_test.rb
index 3fe5e4fd78..7f809e7898 100644
--- a/activesupport/test/xml_mini/jdom_engine_test.rb
+++ b/activesupport/test/xml_mini/jdom_engine_test.rb
@@ -15,20 +15,20 @@ if RUBY_PLATFORM =~ /java/
XmlMini.backend = @default_backend
end
- # def test_file_from_xml
- # hash = Hash.from_xml(<<-eoxml)
- # <blog>
- # <logo type="file" name="logo.png" content_type="image/png">
- # </logo>
- # </blog>
- # eoxml
- # assert hash.has_key?('blog')
- # assert hash['blog'].has_key?('logo')
- #
- # file = hash['blog']['logo']
- # assert_equal 'logo.png', file.original_filename
- # assert_equal 'image/png', file.content_type
- # end
+ def test_file_from_xml
+ hash = Hash.from_xml(<<-eoxml)
+ <blog>
+ <logo type="file" name="logo.png" content_type="image/png">
+ </logo>
+ </blog>
+ eoxml
+ assert hash.has_key?('blog')
+ assert hash['blog'].has_key?('logo')
+
+ file = hash['blog']['logo']
+ assert_equal 'logo.png', file.original_filename
+ assert_equal 'image/png', file.content_type
+ end
def test_exception_thrown_on_expansion_attack
assert_raise NativeException do
diff --git a/ci/ci_build.rb b/ci/ci_build.rb
index c3af1f0177..50f7f410fa 100755
--- a/ci/ci_build.rb
+++ b/ci/ci_build.rb
@@ -85,8 +85,8 @@ cd "#{root_dir}/activerecord" do
puts "[CruiseControl] Building Active Record with MySQL IM enabled"
puts
ENV['IM'] = 'true'
- build_results[:activerecord_mysql] = rake 'mysql:rebuild_databases', 'mysql:test'
- build_results[:activerecord_mysql_isolated] = rake 'mysql:rebuild_databases', 'mysql:isolated_test'
+ build_results[:activerecord_mysql_IM] = rake 'mysql:rebuild_databases', 'mysql:test'
+ build_results[:activerecord_mysql_isolated_IM] = rake 'mysql:rebuild_databases', 'mysql:isolated_test'
end
cd "#{root_dir}/activerecord" do
@@ -103,8 +103,8 @@ cd "#{root_dir}/activerecord" do
puts "[CruiseControl] Building Active Record with MySQL2 IM enabled"
puts
ENV['IM'] = 'true'
- build_results[:activerecord_mysql2] = rake 'mysql:rebuild_databases', 'mysql2:test'
- build_results[:activerecord_mysql2_isolated] = rake 'mysql:rebuild_databases', 'mysql2:isolated_test'
+ build_results[:activerecord_mysql2_IM] = rake 'mysql:rebuild_databases', 'mysql2:test'
+ build_results[:activerecord_mysql2_isolated_IM] = rake 'mysql:rebuild_databases', 'mysql2:isolated_test'
end
cd "#{root_dir}/activerecord" do
@@ -121,8 +121,8 @@ cd "#{root_dir}/activerecord" do
puts "[CruiseControl] Building Active Record with PostgreSQL IM enabled"
puts
ENV['IM'] = 'true'
- build_results[:activerecord_postgresql8] = rake 'postgresql:rebuild_databases', 'postgresql:test'
- build_results[:activerecord_postgresql8_isolated] = rake 'postgresql:rebuild_databases', 'postgresql:isolated_test'
+ build_results[:activerecord_postgresql8_IM] = rake 'postgresql:rebuild_databases', 'postgresql:test'
+ build_results[:activerecord_postgresql8_isolated_IM] = rake 'postgresql:rebuild_databases', 'postgresql:isolated_test'
end
cd "#{root_dir}/activerecord" do
@@ -139,8 +139,8 @@ cd "#{root_dir}/activerecord" do
puts "[CruiseControl] Building Active Record with SQLite 3 IM enabled"
puts
ENV['IM'] = 'true'
- build_results[:activerecord_sqlite3] = rake 'sqlite3:test'
- build_results[:activerecord_sqlite3_isolated] = rake 'sqlite3:isolated_test'
+ build_results[:activerecord_sqlite3_IM] = rake 'sqlite3:test'
+ build_results[:activerecord_sqlite3_isolated_IM] = rake 'sqlite3:isolated_test'
end
cd "#{root_dir}/activerecord" do
@@ -179,4 +179,3 @@ else
puts "[CruiseControl] Failed components: #{failures.map { |component| component.first }.join(', ')}"
exit(-1)
end
-
diff --git a/load_paths.rb b/load_paths.rb
index 15345e31e3..590af69330 100644
--- a/load_paths.rb
+++ b/load_paths.rb
@@ -1,9 +1,8 @@
# bust gem prelude
if defined? Gem
- Gem.source_index
gem 'bundler'
else
require 'rubygems'
end
require 'bundler'
-Bundler.setup \ No newline at end of file
+Bundler.setup
diff --git a/railties/CHANGELOG b/railties/CHANGELOG
index c77d03c39f..880849d2ec 100644
--- a/railties/CHANGELOG
+++ b/railties/CHANGELOG
@@ -7,6 +7,8 @@
*Rails 3.1.0 (unreleased)*
+* The new rake task assets:clean removes precompiled assets. [fxn]
+
* Application and plugin generation run bundle install unless --skip-gemfile or --skip-bundle. [fxn]
* Fixed database tasks for jdbc* adapters #jruby
diff --git a/railties/guides/assets/images/radar.png b/railties/guides/assets/images/radar.png
new file mode 100644
index 0000000000..f61e08763f
--- /dev/null
+++ b/railties/guides/assets/images/radar.png
Binary files differ
diff --git a/railties/guides/assets/images/vijaydev.jpg b/railties/guides/assets/images/vijaydev.jpg
new file mode 100644
index 0000000000..e21d3cabfc
--- /dev/null
+++ b/railties/guides/assets/images/vijaydev.jpg
Binary files differ
diff --git a/railties/guides/rails_guides/helpers.rb b/railties/guides/rails_guides/helpers.rb
index d466c76c7c..463df8a7a8 100644
--- a/railties/guides/rails_guides/helpers.rb
+++ b/railties/guides/rails_guides/helpers.rb
@@ -15,7 +15,7 @@ module RailsGuides
def author(name, nick, image = 'credits_pic_blank.gif', &block)
image = "images/#{image}"
- result = content_tag(:img, nil, :src => image, :class => 'left pic', :alt => name)
+ result = content_tag(:img, nil, :src => image, :class => 'left pic', :alt => name, :width => 91, :height => 91)
result << content_tag(:h3, name)
result << content_tag(:p, capture(&block))
content_tag(:div, result, :class => 'clearfix', :id => nick)
diff --git a/railties/guides/source/action_view_overview.textile b/railties/guides/source/action_view_overview.textile
index b064851312..a3454579ad 100644
--- a/railties/guides/source/action_view_overview.textile
+++ b/railties/guides/source/action_view_overview.textile
@@ -929,7 +929,7 @@ Creates a scope around a specific model object like form_for, but doesn‘t crea
h5. file_field
-Returns an file upload input tag tailored for accessing a specified attribute.
+Returns a file upload input tag tailored for accessing a specified attribute.
<ruby>
file_field(:user, :avatar)
@@ -1037,7 +1037,7 @@ Sample usage (selecting the associated Author for an instance of Post, +@post+):
collection_select(:post, :author_id, Author.all, :id, :name_with_initial, {:prompt => true})
</ruby>
-If @post.author_id is already 1, this would return:
+If <tt>@post.author_id</tt> is 1, this would return:
<html>
<select name="post[author_id]">
@@ -1080,8 +1080,6 @@ Sample usage:
option_groups_from_collection_for_select(@continents, :countries, :name, :id, :name, 3)
</ruby>
-TODO check above textile output looks right
-
Possible output:
<html>
@@ -1132,13 +1130,13 @@ h5. select
Create a select tag and a series of contained option tags for the provided object and method.
-Example with @post.person_id => 1:
+Example:
<ruby>
select("post", "person_id", Person.all.collect {|p| [ p.name, p.id ] }, { :include_blank => true })
</ruby>
-could become:
+If <tt>@post.person_id</tt> is 1, this would become:
<html>
<select name="post[person_id]">
@@ -1189,7 +1187,7 @@ h5. file_field_tag
Creates a file upload field.
-If you are using file uploads then you will also need to set the multipart option for the form tag:
+Prior to Rails 3.1, if you are using file uploads, then you will need to set the multipart option for the form tag. Rails 3.1+ does this automatically.
<ruby>
<%= form_tag { :action => "post" }, { :multipart => true } do %>
@@ -1400,102 +1398,6 @@ number_with_precision(111.2345) # => 111.235
number_with_precision(111.2345, 2) # => 111.23
</ruby>
-h5. evaluate_remote_response
-
-Returns +eval(request.responseText)+ which is the JavaScript function that form_remote_tag can call in +:complete+ to evaluate a multiple update return document using +update_element_function+ calls.
-
-h5. form_remote_tag
-
-Returns a form tag that will submit using XMLHttpRequest in the background instead of the regular reloading POST arrangement. Even though it‘s using JavaScript to serialize the form elements, the form submission will work just like a regular submission as viewed by the receiving side.
-
-For example, this:
-
-<ruby>
-form_remote_tag :html => { :action => url_for(:controller => "some", :action => "place") }
-</ruby>
-
-would generate the following:
-
-<html>
-<form action="/some/place" method="post" onsubmit="new Ajax.Request('',
- {asynchronous:true, evalScripts:true, parameters:Form.serialize(this)}); return false;">
-</html>
-
-h5. link_to_remote
-
-Returns a link to a remote action that's called in the background using XMLHttpRequest. You can generate a link that uses AJAX in the general case, while degrading gracefully to plain link behavior in the absence of JavaScript. For example:
-
-<ruby>
-link_to_remote "Delete this post",
- { :update => "posts", :url => { :action => "destroy", :id => post.id } },
- :href => url_for(:action => "destroy", :id => post.id)
-</ruby>
-
-h5. observe_field
-
-Observes the field specified and calls a callback when its contents have changed.
-
-<ruby>
-observe_field("my_field", :function => "alert('Field changed')")
-</ruby>
-
-h5. observe_form
-
-Observes the form specified and calls a callback when its contents have changed. The options for observe_form are the same as the options for observe_field.
-
-<ruby>
-observe_field("my_form", :function => "alert('Form changed')")
-</ruby>
-
-h5. periodically_call_remote
-
-Periodically calls the specified url as often as specified. Usually used to update a specified div with the results of the remote call. The following example will call update every 20 seconds and update the news_block div:
-
-<ruby>
-periodically_call_remote(:url => 'update', :frequency => '20', :update => 'news_block')
-# => PeriodicalExecuter(function() {new Ajax.Updater('news_block', 'update', {asynchronous:true, evalScripts:true})}, 20)
-</ruby>
-
-h5. remote_form_for
-
-Creates a form that will submit using XMLHttpRequest in the background instead of the regular reloading POST arrangement and a scope around a specific resource that is used as a base for questioning about values for the fields.
-
-<ruby>
-<%= remote_form_for(@post) do |f| %>
- ...
-<% end %>
-</ruby>
-
-h5. remote_function
-
-Returns the JavaScript needed for a remote function. Takes the same arguments as +link_to_remote+.
-
-<ruby>
-<select id="options" onchange="<%= remote_function(:update => "options", :url => { :action => :update_options }) %>">
- <option value="0">Hello</option>
- <option value="1">World</option>
-</select>
-# => <select id="options" onchange="new Ajax.Updater('options', '/testing/update_options', {asynchronous:true, evalScripts:true})">
-</ruby>
-
-h5. submit_to_remote
-
-Returns a button input tag that will submit form using XMLHttpRequest in the background instead of a regular POST request that reloads the page.
-
-For example, the following:
-
-<ruby>
-submit_to_remote 'create_btn', 'Create', :url => { :action => 'create' }
-</ruby>
-
-would generate:
-
-<html>
-<input name="create_btn" onclick="new Ajax.Request('/testing/create',
- {asynchronous:true, evalScripts:true, parameters:Form.serialize(this.form)});
- return false;" type="button" value="Create" />
-</html>
-
h3. Localized Views
Action View has the ability render different templates depending on the current locale.
@@ -1520,6 +1422,7 @@ You can read more about the Rails Internationalization (I18n) API "here":i18n.ht
h3. Changelog
+* May 29, 2011: Removed references to remote_* helpers - Vijay Dev
* April 16, 2011: Added 'Using Action View with Rails', 'Templates' and 'Partials' sections. "Sebastian Martinez":http://wyeworks.com
* September 3, 2009: Continuing work by Trevor Turk, leveraging the Action Pack docs and "What's new in Edge Rails":http://ryandaigle.com/articles/2007/8/3/what-s-new-in-edge-rails-partials-get-layouts
* April 5, 2009: Starting work by Trevor Turk, leveraging Mike Gunderloy's docs
diff --git a/railties/guides/source/active_record_basics.textile b/railties/guides/source/active_record_basics.textile
index b7926f3a3b..3e46e7df9f 100644
--- a/railties/guides/source/active_record_basics.textile
+++ b/railties/guides/source/active_record_basics.textile
@@ -64,8 +64,8 @@ There are also some optional column names that will create additional features t
* *created_on* - Automatically gets set to the current date when the record is first created.
* *updated_at* - Automatically gets set to the current date and time whenever the record is updated.
* *updated_on* - Automatically gets set to the current date whenever the record is updated.
-* *lock_version* - Adds "optimistic locking":http://api.rubyonrails.com/classes/ActiveRecord/Locking.html to a model.
-* *type* - Specifies that the model uses "Single Table Inheritance":http://api.rubyonrails.com/classes/ActiveRecord/Base.html
+* *lock_version* - Adds "optimistic locking":http://api.rubyonrails.org/classes/ActiveRecord/Locking.html to a model.
+* *type* - Specifies that the model uses "Single Table Inheritance":http://api.rubyonrails.org/classes/ActiveRecord/Base.html
* *(table_name)_count* - Used to cache the number of belonging objects on associations. For example, a +comments_count+ column in a +Post+ class that has many instances of +Comment+ will cache the number of existent comments for each post.
NOTE: While these column names are optional they are in fact reserved by Active Record. Steer clear of reserved keywords unless you want the extra functionality. For example, "type" is a reserved keyword used to designate a table using Single Table Inheritance. If you are not using STI, try an analogous keyword like "context", that may still accurately describe the data you are modeling.
diff --git a/railties/guides/source/active_record_querying.textile b/railties/guides/source/active_record_querying.textile
index 579a323d57..b4ce60fcaa 100644
--- a/railties/guides/source/active_record_querying.textile
+++ b/railties/guides/source/active_record_querying.textile
@@ -483,16 +483,16 @@ SQL uses the +HAVING+ clause to specify conditions on the +GROUP BY+ fields. You
For example:
<ruby>
-Order.group("date(created_at)").having("created_at > ?", 1.month.ago)
+Order.group("date(created_at)").having("created_at < ?", 1.month.ago)
</ruby>
The SQL that would be executed would be something like this:
<sql>
-SELECT * FROM orders GROUP BY date(created_at) HAVING created_at > '2009-01-15'
+SELECT * FROM orders GROUP BY date(created_at) HAVING created_at < '2011-04-27'
</sql>
-This will return single order objects for each day, but only for the last month.
+This will return single order objects for each day, but only those that are at least one month old.
h3. Overriding Conditions
@@ -675,7 +675,7 @@ class Post < ActiveRecord::Base
has_many :tags
end
-class Comments < ActiveRecord::Base
+class Comment < ActiveRecord::Base
belongs_to :post
has_one :guest
end
@@ -683,6 +683,10 @@ end
class Guest < ActiveRecord::Base
belongs_to :comment
end
+
+class Tag < ActiveRecord::Base
+ belongs_to :post
+end
</ruby>
Now all of the following will produce the expected join queries using +INNER JOIN+:
@@ -700,6 +704,8 @@ SELECT categories.* FROM categories
INNER JOIN posts ON posts.category_id = categories.id
</sql>
+Or, in English: "return a Category object for all categories with posts". Note that you will see duplicate categories if more than one post has the same category. If you want unique categories, you can use Category.joins(:post).select("distinct(categories.id)").
+
h5. Joining Multiple Associations
<ruby>
@@ -714,18 +720,40 @@ SELECT posts.* FROM posts
INNER JOIN comments ON comments.post_id = posts.id
</sql>
+Or, in English: "return all posts that have a category and at least one comment". Note again that posts with multiple comments will show up multiple times.
+
h5. Joining Nested Associations (Single Level)
<ruby>
Post.joins(:comments => :guest)
</ruby>
+This produces:
+
+<sql>
+SELECT posts.* FROM posts
+ INNER JOIN comments ON comments.post_id = posts.id
+ INNER JOIN guests ON guests.comment_id = comments.id
+</sql>
+
+Or, in English: "return all posts that have a comment made by a guest."
+
h5. Joining Nested Associations (Multiple Level)
<ruby>
Category.joins(:posts => [{:comments => :guest}, :tags])
</ruby>
+This produces:
+
+<sql>
+SELECT categories.* FROM categories
+ INNER JOIN posts ON posts.category_id = categories.id
+ INNER JOIN comments ON comments.post_id = posts.id
+ INNER JOIN guests ON guests.comment_id = comments.id
+ INNER JOIN tags ON tags.post_id = posts.id
+</sql>
+
h4. Specifying Conditions on the Joined Tables
You can specify conditions on the joined tables using the regular "Array":#array-conditions and "String":#pure-string-conditions conditions. "Hash conditions":#hash-conditions provides a special syntax for specifying conditions for the joined tables:
diff --git a/railties/guides/source/active_record_validations_callbacks.textile b/railties/guides/source/active_record_validations_callbacks.textile
index 9f59397d7d..36094dcddc 100644
--- a/railties/guides/source/active_record_validations_callbacks.textile
+++ b/railties/guides/source/active_record_validations_callbacks.textile
@@ -82,6 +82,7 @@ The following methods skip validations, and will save the object to the database
* +increment!+
* +increment_counter+
* +toggle!+
+* +touch+
* +update_all+
* +update_attribute+
* +update_column+
@@ -429,7 +430,7 @@ end
The +validates_with+ helper takes a class, or a list of classes to use for validation. There is no default error message for +validates_with+. You must manually add errors to the record's errors collection in the validator class.
-To implement the validate method, you must have an +record+ parameter defined, which is the record to be validated.
+To implement the validate method, you must have a +record+ parameter defined, which is the record to be validated.
Like all other validations, +validates_with+ takes the +:if+, +:unless+ and +:on+ options. If you pass any other options, it will send those options to the validator class as +options+:
@@ -911,20 +912,20 @@ h4. Creating an Object
* +before_validation+
* +after_validation+
* +before_save+
-* +after_save+
* +before_create+
* +around_create+
* +after_create+
+* +after_save+
h4. Updating an Object
* +before_validation+
* +after_validation+
* +before_save+
-* +after_save+
* +before_update+
* +around_update+
* +after_update+
+* +after_save+
h4. Destroying an Object
@@ -1007,6 +1008,7 @@ Just as with validations, it's also possible to skip callbacks. These methods sh
* +increment+
* +increment_counter+
* +toggle+
+* +touch+
* +update_column+
* +update_all+
* +update_counters+
diff --git a/railties/guides/source/active_support_core_extensions.textile b/railties/guides/source/active_support_core_extensions.textile
index 43aa6dfbbb..7512f7bcb9 100644
--- a/railties/guides/source/active_support_core_extensions.textile
+++ b/railties/guides/source/active_support_core_extensions.textile
@@ -868,7 +868,7 @@ The macro accepts several methods:
delegate :name, :age, :address, :twitter, :to => :profile
</ruby>
-When interpolated into a string, the +:to+ option should become an expression that evaluates to the object the method is delegated to. Typically a string or symbol. Such a expression is evaluated in the context of the receiver:
+When interpolated into a string, the +:to+ option should become an expression that evaluates to the object the method is delegated to. Typically a string or symbol. Such an expression is evaluated in the context of the receiver:
<ruby>
# delegates to the Rails constant
@@ -3024,7 +3024,7 @@ Date.new(2010, 1, 31).change(:month => 2)
h5(#date-durations). Durations
-Durations can be added and substracted to dates:
+Durations can be added to and subtracted from dates:
<ruby>
d = Date.current
@@ -3232,7 +3232,7 @@ DateTime.current.change(:month => 2, :day => 30)
h5(#datetime-durations). Durations
-Durations can be added and substracted to datetimes:
+Durations can be added to and subtracted from datetimes:
<ruby>
now = DateTime.current
@@ -3353,7 +3353,7 @@ If the time to be constructed lies beyond the range supported by +Time+ in the r
h5(#time-durations). Durations
-Durations can be added and substracted to time objects:
+Durations can be added to and subtracted from time objects:
<ruby>
now = Time.current
diff --git a/railties/guides/source/ajax_on_rails.textile b/railties/guides/source/ajax_on_rails.textile
index 1566c23414..8b72e20c33 100644
--- a/railties/guides/source/ajax_on_rails.textile
+++ b/railties/guides/source/ajax_on_rails.textile
@@ -72,7 +72,7 @@ link_to_remote "Add to cart",
If the server returns 200, the output of the above example is equivalent to our first, simple one. However, in case of error, the element with the DOM id +error+ is updated rather than the +cart+ element.
-** *position* By default (i.e. when not specifying this option, like in the examples before) the repsonse is injected into the element with the specified DOM id, replacing the original content of the element (if there was any). You might want to alter this behavior by keeping the original content - the only question is where to place the new content? This can specified by the +position+ parameter, with four possibilities:
+** *position* By default (i.e. when not specifying this option, like in the examples before) the response is injected into the element with the specified DOM id, replacing the original content of the element (if there was any). You might want to alter this behavior by keeping the original content - the only question is where to place the new content? This can specified by the +position+ parameter, with four possibilities:
*** +:before+ Inserts the response text just before the target element. More precisely, it creates a text node from the response and inserts it as the left sibling of the target element.
*** +:after+ Similar behavior to +:before+, but in this case the response is inserted after the target element.
*** +:top+ Inserts the text into the target element, before it's original content. If the target element was empty, this is equivalent with not specifying +:position+ at all.
diff --git a/railties/guides/source/api_documentation_guidelines.textile b/railties/guides/source/api_documentation_guidelines.textile
index e22ffa4c04..50e86e05a8 100644
--- a/railties/guides/source/api_documentation_guidelines.textile
+++ b/railties/guides/source/api_documentation_guidelines.textile
@@ -33,12 +33,16 @@ Spell names correctly: Arel, Test::Unit, RSpec, HTML, MySQL, JavaScript, ERB. Wh
Use the article "an" for "SQL", as in "an SQL statement". Also "an SQLite database".
+h3. English
+
+Please use American English (_color_, _center_, _modularize_, etc.). See "a list of American and British English spelling differences here":http://en.wikipedia.org/wiki/American_and_British_English_spelling_differences.
+
h3. Example Code
Choose meaningful examples that depict and cover the basics as well as interesting points or gotchas.
-Use two spaces to indent chunks of code.—that is two spaces with respect to the left margin; the examples
-themselves should use "Rails code conventions":http://rails.lighthouseapp.com/projects/8994/source-style.
+Use two spaces to indent chunks of code--that is two spaces with respect to the left margin; the examples
+themselves should use "Rails coding conventions":contributing_to_ruby_on_rails.html#follow-the-coding-conventions.
Short docs do not need an explicit "Examples" label to introduce snippets, they just follow paragraphs:
diff --git a/railties/guides/source/asset_pipeline.textile b/railties/guides/source/asset_pipeline.textile
index 9ea1aa9e01..5d0dfee41c 100644
--- a/railties/guides/source/asset_pipeline.textile
+++ b/railties/guides/source/asset_pipeline.textile
@@ -4,26 +4,54 @@ This guide will cover the ideology of the asset pipeline introduced in Rails 3.1
By referring to this guide you will be able to:
* Properly organize your application assets
-* Understand the benefits of the asset pipline
-* Adding a preproccessor to the pipeline
-* Package assets with your plugin
+* Understand the benefits of the asset pipeline
+* Adding a preprocessor to the pipeline
+* Package assets with a gem
endprologue.
h3. What Is The Asset Pipeline?
-h4. Why Should I Use it?
+The asset pipeline is a new feature introduced in Rails 3.1 using the "Sprockets":http://getsprockets.org/ engine. It allows developers to place design elements in +app/assets+ instead of +public+, there are many advantages to this. A big one is that they are now processed by Rails instead of your webserver, allowing you to use preprocessors like CoffeeScript, SCSS, or ERB. Another advantage is that your CSS and JavaScript is compiled into one file by default, this allows users to cache all the CSS and JavaScript data so your pages render faster. Not to mention how much cleaner your application will become.
h3. How to Use the Asset Pipeline
+The asset pipeline is easy to migrate to and use. There are a few things that you'll need to learn first, like where to place your files, how to create a manifest, and how to add any preproccesors if you desire.
+
h4. Asset Organization
-h4. Default Files Loaded
+WIP
+
+Sprockets will automatically load manifest files by searching directories in app/assets and including the first file with a basename of index. (Confirm and add: does it load app/assets/index?)
h4. Directives
-h4. Stacking Preproccessors
+WIP
+
+Sprockets, the rails tie that powers the asset pipeline, provides three directives which are like Ruby's methods. They are: +require+, +require_tree+, and +require_self+. These directives must be called at the top of a file in a comment with an equal sign before it. (note: CSS directives need *= if in a continuous comment -- confirm please)
+
+The require directive loads a file with the supplied basename from the following paths: app/assets/*, lib/assets/*, vendor/assets/*, as well as any of your gem's asset files.
+
+Require tree does...
+
+Require self does...
+
+h4. Stacking Preprocessors
-h3. Packaging Assets with Your Plugin
+Sprockets allows you to stack preprocessors. The stack is ran off the file extensions in a last in, first out method (like popping an array). For example if we want to make a JavaScript asset with both CoffeeScript and ERB the file would be named: +name.js.coffee.erb+. If it were named +name.js.erb.coffee+ CoffeeScript would raise an error because it doesn't understand ERB tags.
+
+h4. Adding a Preproccessor
+
+WIP
+
+https://github.com/rtomayko/tilt for gems or config.register_processor('text/css', MyAwesomeProccessor) for local stuff
+
+h3. Packaging Assets with Your Gems
+
+You may find it useful to package certain assets with your gem. A good example would be the "pjax_rails":https://github.com/rails/pjax_rails/ gem. This gem bundles the latest "PJAX":https://github.com/defunkt/jquery-pjax library and some helper methods. If you take a look at the source of pjax_rails, you'll see that it bundles the assets in +lib/assets+ just the same way as you would in +app/assets+. Doing so allows pjax_rails to update JavaScripts without asking users to copy them into their public folder
+
+If you want the user to load your JavaScript files in their template, you will have to ask them to add a directive to do so. Also avoid any common names such as +form_check.js+ instead try using +mygem/form_check.js+ so it's clear where it's coming from. This will also make it unlikely that your users will create a file with the same name causing the asset pipeline to choose the user's file over yours.
h3. More on Sprockets
+
+Sprockets is the engine that handles the asset pipeline in Rails 3.1 and above. Their official website is available at "http://getsprockets.org/":http://getsprockets.org/ and the source code is "available on github":https://github.com/sstephenson/sprockets.
diff --git a/railties/guides/source/caching_with_rails.textile b/railties/guides/source/caching_with_rails.textile
index 91827fd493..f058dce42b 100644
--- a/railties/guides/source/caching_with_rails.textile
+++ b/railties/guides/source/caching_with_rails.textile
@@ -112,7 +112,7 @@ As an example, if you wanted to show all the orders placed on your website in re
<ruby>
<% Order.find_recent.each do |o| %>
- <%= o.buyer.name %> bought <% o.product.name %>
+ <%= o.buyer.name %> bought <%= o.product.name %>
<% end %>
<% cache do %>
@@ -162,17 +162,17 @@ class ProductSweeper < ActionController::Caching::Sweeper
# If our sweeper detects that a Product was created call this
def after_create(product)
- expire_cache_for(product)
+ expire_cache_for(product)
end
# If our sweeper detects that a Product was updated call this
def after_update(product)
- expire_cache_for(product)
+ expire_cache_for(product)
end
# If our sweeper detects that a Product was deleted call this
def after_destroy(product)
- expire_cache_for(product)
+ expire_cache_for(product)
end
private
@@ -345,7 +345,7 @@ ActionController::Base.cache_store = MyCacheStore.new
h4. Cache Keys
-The keys used in a cache can be any object that responds to either +:cache_key+ or to +:to_param+. You can implement the +:cache_key+ method on your classes if you need to generate custom keys. ActiveRecord will generate keys based on the class name and record id.
+The keys used in a cache can be any object that responds to either +:cache_key+ or to +:to_param+. You can implement the +:cache_key+ method on your classes if you need to generate custom keys. Active Record will generate keys based on the class name and record id.
You can use Hashes and Arrays of values as cache keys.
diff --git a/railties/guides/source/command_line.textile b/railties/guides/source/command_line.textile
index ad36c6532e..5fe9ad101b 100644
--- a/railties/guides/source/command_line.textile
+++ b/railties/guides/source/command_line.textile
@@ -55,7 +55,7 @@ INFO: This output will seem very familiar when we get to the +generate+ command.
h4. +rails server+
-Let's try it! The +rails server+ command launches a small web server named WEBrick which comes bundled with Ruby. You'll use this any time you want to view your work through a web browser.
+The +rails server+ command launches a small web server named WEBrick which comes bundled with Ruby. You'll use this any time you want to view your work through a web browser.
INFO: WEBrick isn't your only option for serving Rails. We'll get to that in a later section.
@@ -65,7 +65,7 @@ Without any prodding of any kind, +rails server+ will run our new shiny Rails ap
$ cd commandsapp
$ rails server
=> Booting WEBrick
-=> Rails 3.0.0 application starting in development on http://0.0.0.0:3000
+=> Rails 3.1.0 application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
[2010-04-18 03:20:33] INFO WEBrick 1.3.1
@@ -75,6 +75,8 @@ $ rails server
With just three commands we whipped up a Rails server listening on port 3000. Go to your browser and open "http://localhost:3000":http://localhost:3000, you will see a basic Rails app running.
+You can also use the alias "s" to start the server: <tt>rails s</tt>.
+
h4. +rails generate+
The +rails generate+ command uses templates to create a whole lot of things. You can always find out what's available by running +rails generate+ by itself. Let's do that:
@@ -237,7 +239,7 @@ dependency model
create test/unit/high_score_test.rb
create test/fixtures/high_scores.yml
exists db/migrate
- create db/migrate/20081217071914_create_high_scores.rb
+ create db/migrate/20100209025147_create_high_scores.rb
</shell>
The generator checks that there exist the directories for models, controllers, helpers, layouts, functional and unit tests, stylesheets, creates the views, controller, model and database migration for HighScore (creating the +high_scores+ table and fields), takes care of the route for the *resource*, and new tests for everything.
@@ -267,11 +269,13 @@ h4. +rails console+
The +console+ command lets you interact with your Rails application from the command line. On the underside, +rails console+ uses IRB, so if you've ever used it, you'll be right at home. This is useful for testing out quick ideas with code and changing data server-side without touching the website.
+You can also use the alias "c" to invoke the console: <tt>rails c</tt>.
+
If you wish to test out some code without changing any data, you can do that by invoking +rails console --sandbox+.
<shell>
$ rails console --sandbox
-Loading development environment in sandbox (Rails 3.0.0)
+Loading development environment in sandbox (Rails 3.1.0)
Any modifications you make will be rolled back on exit
irb(main):001:0>
</shell>
@@ -280,6 +284,8 @@ h4. +rails dbconsole+
+rails dbconsole+ figures out which database you're using and drops you into whichever command line interface you would use with it (and figures out the command line parameters to give to it, too!). It supports MySQL, PostgreSQL, SQLite and SQLite3.
+You can also use the alias "db" to invoke the dbconsole: <tt>rails db</tt>.
+
h4. +rails plugin+
The +rails plugin+ command simplifies plugin management; think a miniature version of the Gem utility. Let's walk through installing a plugin. You can call the sub-command +discover+, which sifts through repositories looking for plugins, or call +source+ to add a specific repository of plugins, or you can specify the plugin location directly.
@@ -306,7 +312,7 @@ $ rails runner "Model.long_running_method"
h4. +rails destroy+
-Think of +destroy+ as the opposite of +generate+. It'll figure out what generate did, and undo it. Believe you-me, the creation of this tutorial used this command many times!
+Think of +destroy+ as the opposite of +generate+. It'll figure out what generate did, and undo it.
<shell>
$ rails generate model Oops
@@ -333,9 +339,29 @@ $ rails destroy model Oops
notempty app
</shell>
-h4. +rake about+
+h3. Rake
+
+Rake is Ruby Make, a standalone Ruby utility that replaces the Unix utility 'make', and uses a 'Rakefile' and +.rake+ files to build up a list of tasks. In Rails, Rake is used for common administration tasks, especially sophisticated ones that build off of each other.
+
+You can get a list of Rake tasks available to you, which will often depend on your current directory, by typing +rake --tasks+. Each task has a description, and should help you find the thing you need.
+
+<shell>
+$ rake --tasks
+(in /home/foobar/commandsapp)
+rake db:abort_if_pending_migrations # Raises an error if there are pending migrations
+rake db:charset # Retrieves the charset for the current environment's database
+rake db:collation # Retrieves the collation for the current environment's database
+rake db:create # Create the database defined in config/database.yml for the current Rails.env
+...
+...
+rake tmp:pids:clear # Clears all files in tmp/pids
+rake tmp:sessions:clear # Clears all files in tmp/sessions
+rake tmp:sockets:clear # Clears all files in tmp/sockets
+</shell>
+
+h4. +about+
-Check it: Version numbers for Ruby, RubyGems, Rails, the Rails subcomponents, your application's folder, the current Rails environment name, your app's database adapter, and schema version! +about+ is useful when you need to ask for help, check if a security patch might affect you, or when you need some stats for an existing Rails installation.
+<tt>rake about</tt> gives information about version numbers for Ruby, RubyGems, Rails, the Rails subcomponents, your application's folder, the current Rails environment name, your app's database adapter, and schema version. It is useful when you need to ask for help, check if a security patch might affect you, or when you need some stats for an existing Rails installation.
<shell>
$ rake about
@@ -343,17 +369,55 @@ About your application's environment
Ruby version 1.8.7 (x86_64-linux)
RubyGems version 1.3.6
Rack version 1.1
-Rails version 3.0.0
-Active Record version 3.0.0
-Action Pack version 3.0.0
-Active Resource version 3.0.0
-Action Mailer version 3.0.0
-Active Support version 3.0.0
+Rails version 3.1.0
+Active Record version 3.1.0
+Action Pack version 3.1.0
+Active Resource version 3.1.0
+Action Mailer version 3.1.0
+Active Support version 3.1.0
Middleware ActionDispatch::Static, Rack::Lock, Rack::Runtime, Rails::Rack::Logger, ActionDispatch::ShowExceptions, ActionDispatch::RemoteIp, Rack::Sendfile, ActionDispatch::Callbacks, ActionDispatch::Cookies, ActionDispatch::Session::CookieStore, ActionDispatch::Flash, ActionDispatch::ParamsParser, Rack::MethodOverride, ActionDispatch::Head
Application root /home/foobar/commandsapp
Environment development
</shell>
+h4. +assets+
+
+You can precompile the assets in <tt>app/assets</tt> using <tt>rake assets:precompile</tt> and remove compiled assets using <tt>rake assets:clean</tt>.
+
+h4. +db+
+
+The most common tasks of the +db:+ Rake namespace are +migrate+ and +create+, and it will pay off to try out all of the migration rake tasks (+up+, +down+, +redo+, +reset+). +rake db:version+ is useful when troubleshooting, telling you the current version of the database.
+
+h4. +doc+
+
+If you want to strip out or rebuild any of the Rails documentation (including this guide!), the +doc:+ namespace has the tools. Stripping documentation is mainly useful for slimming your codebase, like if you're writing a Rails application for an embedded platform.
+
+h4. +notes+
+
+These tasks will search through your code for commented lines beginning with "FIXME", "OPTIMIZE", "TODO", or any custom annotation (like XXX) and show you them.
+
+h4. +routes+
+
++rake routes+ will list all of your defined routes, which is useful for tracking down routing problems in your app, or giving you a good overview of the URLs in an app you're trying to get familiar with.
+
+h4. +test+
+
+INFO: A good description of unit testing in Rails is given in "A Guide to Testing Rails Applications":testing.html
+
+Rails comes with a test suite called Test::Unit. It is through the use of tests that Rails itself is so stable, and the slew of people working on Rails can prove that everything works as it should.
+
+The +test:+ namespace helps in running the different tests you will (hopefully!) write.
+
+h4. +tmp+
+
+The <tt>Rails.root/tmp</tt> directory is, like the *nix /tmp directory, the holding place for temporary files like sessions (if you're using a file store for files), process id files, and cached actions. The +tmp:+ namespace tasks will help you clear them if you need to if they've become overgrown, or create them in case of deletions gone awry.
+
+h4. Miscellaneous
+
+* +rake stats+ is great for looking at statistics on your code, displaying things like KLOCs (thousands of lines of code) and your code to test ratio.
+* +rake secret+ will give you a pseudo-random key to use for your session secret.
+* <tt>rake time:zones:all</tt> lists all the timezones Rails knows about.
+
h3. The Rails Advanced Command Line
More advanced use of the command line is focused around finding useful (even surprising at times) options in the utilities, and fitting those to your needs and specific work flow. Listed here are some tricks up Rails' sleeve.
@@ -437,7 +501,7 @@ Successfully installed mongrel-1.1.5
Installing RDoc documentation for mongrel-1.1.5...
$ rails server mongrel
=> Booting Mongrel (use 'rails server webrick' to force WEBrick)
-=> Rails 3.0.0 application starting on http://0.0.0.0:3000
+=> Rails 3.1.0 application starting on http://0.0.0.0:3000
...
</shell>
@@ -534,60 +598,3 @@ I got assigned some args:
</shell>
Tada!
-
-h4. Rake is Ruby Make
-
-Rake is a standalone Ruby utility that replaces the Unix utility 'make', and uses a 'Rakefile' and +.rake+ files to build up a list of tasks. In Rails, Rake is used for common administration tasks, especially sophisticated ones that build off of each other.
-
-You can get a list of Rake tasks available to you, which will often depend on your current directory, by typing +rake --tasks+. Each task has a description, and should help you find the thing you need.
-
-<shell>
-$ rake --tasks
-(in /home/foobar/commandsapp)
-rake db:abort_if_pending_migrations # Raises an error if there are pending migrations
-rake db:charset # Retrieves the charset for the current environment's database
-rake db:collation # Retrieves the collation for the current environment's database
-rake db:create # Create the database defined in config/database.yml for the current Rails.env
-...
-...
-rake tmp:pids:clear # Clears all files in tmp/pids
-rake tmp:sessions:clear # Clears all files in tmp/sessions
-rake tmp:sockets:clear # Clears all files in tmp/sockets
-</shell>
-
-h5. +db:+ Database
-
-The most common tasks of the +db:+ Rake namespace are +migrate+ and +create+, and it will pay off to try out all of the migration rake tasks (+up+, +down+, +redo+, +reset+). +rake db:version+ is useful when troubleshooting, telling you the current version of the database.
-
-h5. +doc:+ Documentation
-
-If you want to strip out or rebuild any of the Rails documentation (including this guide!), the +doc:+ namespace has the tools. Stripping documentation is mainly useful for slimming your codebase, like if you're writing a Rails application for an embedded platform.
-
-h5. +notes:+ Code note enumeration
-
-These tasks will search through your code for commented lines beginning with "FIXME", "OPTIMIZE", "TODO", or any custom annotation (like XXX) and show you them.
-
-h5. +test:+ Rails tests
-
-INFO: A good description of unit testing in Rails is given in "A Guide to Testing Rails Applications":testing.html
-
-Rails comes with a test suite called Test::Unit. It is through the use of tests that Rails itself is so stable, and the slew of people working on Rails can prove that everything works as it should.
-
-The +test:+ namespace helps in running the different tests you will (hopefully!) write.
-
-h5. +time:+ Timezones
-
-You can list all the timezones Rails knows about with +rake time:zones:all+, which is useful just in day-to-day life.
-
-h5. +tmp:+ Temporary files
-
-The tmp directory is, like in the *nix /tmp directory, the holding place for temporary files like sessions (if you're using a file store for files), process id files, and cached actions. The +tmp:+ namespace tasks will help you clear them if you need to if they've become overgrown, or create them in case of deletions gone awry.
-
-h5. Miscellaneous Tasks
-
- +rake stats+ is great for looking at statistics on your code, displaying things like KLOCs (thousands of lines of code) and your code to test ratio.
-
- +rake secret+ will give you a pseudo-random key to use for your session secret.
-
- +rake routes+ will list all of your defined routes, which is useful for tracking down routing problems in your app, or giving you a good overview of the URLs in an app you're trying to get familiar with.
-
diff --git a/railties/guides/source/configuring.textile b/railties/guides/source/configuring.textile
index 135c849ec3..da951a0833 100644
--- a/railties/guides/source/configuring.textile
+++ b/railties/guides/source/configuring.textile
@@ -18,7 +18,7 @@ Rails offers four standard spots to place initialization code:
h3. Running Code Before Rails
-In the rare event that your application needs to run some code before Rails itself is loaded, put it above the call to +require 'rails/all'+ in your +config/application.rb+.
+In the rare event that your application needs to run some code before Rails itself is loaded, put it above the call to +require 'rails/all'+ in +config/application.rb+.
h3. Configuring Rails Components
@@ -52,12 +52,14 @@ end
* +config.asset_host+ sets the host for the assets. Useful when CDNs are used for hosting assets, or when you want to work around the concurrency constraints builtin in browsers using different domain aliases. Shorter version of +config.action_controller.asset_host+.
-* +config.asset_path+ can take a callable, a string, or be +nil+. Default is +nil+. If set, this configuration parameter let's you decorate asset paths. For example, the normal path for +blog.js+ would be +/javascripts/blog.js+, let that absolute path be +path+. If +config.asset_path+ is a callable, Rails calls it when generating asset paths passing +path+ as argument. If +config.asset_path+ is a string, it is expected to be a +sprintf+ format string with a +%s+ where +path+ will get inserted. In either case, Rails outputs the decorated path. *This option is ignored if the asset pipeline is enabled, which is by default*. Shorter version of +config.action_controller.asset_path+.
+* +config.asset_path+ lets you decorate asset paths. This can be a callable, a string, or be +nil+ which is the default. For example, the normal path for +blog.js+ would be +/javascripts/blog.js+, let that absolute path be +path+. If +config.asset_path+ is a callable, Rails calls it when generating asset paths passing +path+ as argument. If +config.asset_path+ is a string, it is expected to be a +sprintf+ format string with a +%s+ where +path+ will get inserted. In either case, Rails outputs the decorated path. Shorter version of +config.action_controller.asset_path+.
<ruby>
config.asset_path = proc { |path| "/blog/public#{path}" }
</ruby>
+NOTE. The +config.asset_path+ configuration is ignored if the asset pipeline is enabled, which is the default.
+
* +config.autoload_once_paths+ accepts an array of paths from which Rails will autoload constants that won't be wiped per request. Relevant if +config.cache_classes+ is false, which is the case in development mode by default. Otherwise, all autoloading happens only once. All elements of this array must also be in +autoload_paths+. Default is an empty array.
* +config.autoload_paths+ accepts an array of paths from which Rails will autoload constants. Default is all directories under +app+.
@@ -84,11 +86,11 @@ config.asset_path = proc { |path| "/blog/public#{path}" }
* +config.log_level+ defines the verbosity of the Rails logger. This option defaults to +:debug+ for all modes except production, where it defaults to +:info+.
-* +config.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ +Logger+ class. Defaults to an instance of +ActiveSupport::BufferedLogger+, with auto flushing off in production mode.
+* +config.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby +Logger+ class. Defaults to an instance of +ActiveSupport::BufferedLogger+, with auto flushing off in production mode.
-* +config.middleware+ allows you to configure the application's middleware. This is covered in depth in the "Configuring Middleware":configuring-middleware section below.
+* +config.middleware+ allows you to configure the application's middleware. This is covered in depth in the "Configuring Middleware":#configuring-middleware section below.
-* +config.plugins+ accepts the list of plugins to load. If this is set to +nil+, default, all plugins will be loaded. If this is set to +[]+, no plugins will be loaded. Otherwise, plugins will be loaded in the order specified. This option let's you enforce some particular loading order, useful when dependencies between plugins require it. For that use case, put first the plugins you want to be loaded in a certain order, and then the special symbol +:all+ to have the rest loaded without the need to specify them.
+* +config.plugins+ accepts the list of plugins to load. The default is +nil+ in which case all plugins will be loaded. If this is set to +[]+, no plugins will be loaded. Otherwise, plugins will be loaded in the order specified. This option lets you enforce some particular loading order, useful when dependencies between plugins require it. For that use case, put first the plugins you want to be loaded in a certain order, and then the special symbol +:all+ to have the rest loaded without the need to specify them.
* +config.preload_frameworks+ enables or disables preloading all frameworks at startup. Enabled by +config.threadsafe!+. Defaults to +nil+, so is disabled.
@@ -98,7 +100,7 @@ config.asset_path = proc { |path| "/blog/public#{path}" }
* +config.serve_static_assets+ configures Rails to serve static assets. Defaults to true, but in the production environment is turned off. The server software used to run the application should be used to serve the assets instead.
-* +config.session_store+ is usually set up in +config/initializers/session_store.rb+ and specifies what class to use to store the session. Possible values are +:cookie_store+, default, +:mem_cache_store+, and +:disabled+. The last one tells Rails not to deal with sessions. Custom session stores can also be specified like so:
+* +config.session_store+ is usually set up in +config/initializers/session_store.rb+ and specifies what class to use to store the session. Possible values are +:cookie_store+ which is the default, +:mem_cache_store+, and +:disabled+. The last one tells Rails not to deal with sessions. Custom session stores can also be specified:
<ruby>
config.session_store :my_custom_store
@@ -121,45 +123,49 @@ h4. Configuring Generators
Rails 3 allows you to alter what generators are used with the +config.generators+ method. This method takes a block:
<ruby>
- config.generators do |g|
- g.orm :active_record
- g.test_framework :test_unit
- end
+config.generators do |g|
+ g.orm :active_record
+ g.test_framework :test_unit
+end
</ruby>
The full set of methods that can be used in this block are as follows:
-* +force_plural+ allows pluralized model names. Defaults to _false_.
-* +helper+ defines whether or not to generate helpers. Defaults to _true_.
-* +orm+ defines which orm to use. Defaults to _nil_, so will use Active Record by default.
-* +integration_tool+ defines which integration tool to use. Defaults to _nil_.
-* +performance_tool+ defines which performance tool to use. Defaults to _nil_.
+* +assets+ allows to create assets on generating a scaffold. Defaults to +true+.
+* +force_plural+ allows pluralized model names. Defaults to +false+.
+* +helper+ defines whether or not to generate helpers. Defaults to +true+.
+* +integration_tool+ defines which integration tool to use. Defaults to +nil+.
+* +javascripts+ turns on the hook for javascripts in generators. Used in Rails for when the +scaffold+ generator is ran. Defaults to +true+.
+* +javascript_engine+ configures the engine to be used (for eg. coffee) when generating assets. Defaults to +nil+.
+* +orm+ defines which orm to use. Defaults to +false+ and will use Active Record by default.
+* +performance_tool+ defines which performance tool to use. Defaults to +nil+.
* +resource_controller+ defines which generator to use for generating a controller when using +rails generate resource+. Defaults to +:controller+.
* +scaffold_controller+ different from +resource_controller+, defines which generator to use for generating a _scaffolded_ controller when using +rails generate scaffold+. Defaults to +:scaffold_controller+.
-* +stylesheets+ turns on the hook for stylesheets in generators. Used in Rails for when the +scaffold+ generator is ran, but this hook can be used in other generates as well.
-* +test_framework+ defines which test framework to use. Defaults to _nil_, so will use Test::Unit by default.
+* +stylesheets+ turns on the hook for stylesheets in generators. Used in Rails for when the +scaffold+ generator is ran, but this hook can be used in other generates as well. Defaults to +true+.
+* +stylesheet_engine+ configures the stylesheet engine (for eg. sass) to be used when generating assets. Defaults to +:css+.
+* +test_framework+ defines which test framework to use. Defaults to +false+ and will use Test::Unit by default.
* +template_engine+ defines which template engine to use, such as ERB or Haml. Defaults to +:erb+.
h4. Configuring Middleware
Every Rails application comes with a standard set of middleware which it uses in this order in the development environment:
-* +Rack::SSL+ Will force every request to be under HTTPS protocol. Will be available if +config.force_ssl+ is set to _true_.
-* +ActionDispatch::Static+ is used to serve static assets. Disabled if +config.serve_static_assets+ is _true_.
-* +Rack::Lock+ Will wrap the app in mutex so it can only be called by a single thread at a time. Only enabled if +config.action_controller.allow_concurrency+ is set to _false_, which it is by default.
+* +Rack::SSL+ Will force every request to be under HTTPS protocol. Will be available if +config.force_ssl+ is set to +true+.
+* +ActionDispatch::Static+ is used to serve static assets. Disabled if +config.serve_static_assets+ is +true+.
+* +Rack::Lock+ Will wrap the app in mutex so it can only be called by a single thread at a time. Only enabled if +config.action_controller.allow_concurrency+ is set to +false+, which it is by default.
* +ActiveSupport::Cache::Strategy::LocalCache+ Serves as a basic memory backed cache. This cache is not thread safe and is intended only for serving as a temporary memory cache for a single thread.
* +Rack::Runtime+ Sets an +X-Runtime+ header, containing the time (in seconds) taken to execute the request.
-* +Rails::Rack::Logger+ Will notify the logs that the request has began. After request is complete, flushes all the logs.
-* +ActionDispatch::ShowExceptions+ rescues any exception returned by the application and renders nice exception pages if the request is local or if +config.consider_all_requests_local+ is set to _true_. If +config.action_dispatch.show_exceptions+ is set to _false_, exceptions will be raised regardless.
-* +ActionDispatch::RemoteIp+ checks for IP spoofing attacks. Configurable with the +config.action_dispatch.ip_spoofing_check+ and +config.action_dispatch.trusted_proxies+ settings.
-* +Rack::Sendfile+ The Sendfile middleware intercepts responses whose body is being served from a file and replaces it with a server specific X-Sendfile header. Configurable with +config.action_dispatch.x_sendfile_header+
+* +Rails::Rack::Logger+ Notifies the logs that the request has began. After request is complete, flushes all the logs.
+* +ActionDispatch::ShowExceptions+ Rescues any exception returned by the application and renders nice exception pages if the request is local or if +config.consider_all_requests_local+ is set to +true+. If +config.action_dispatch.show_exceptions+ is set to +false+, exceptions will be raised regardless.
+* +ActionDispatch::RemoteIp+ Checks for IP spoofing attacks. Configurable with the +config.action_dispatch.ip_spoofing_check+ and +config.action_dispatch.trusted_proxies+ settings.
+* +Rack::Sendfile+ Intercepts responses whose body is being served from a file and replaces it with a server specific X-Sendfile header. Configurable with +config.action_dispatch.x_sendfile_header+.
* +ActionDispatch::Callbacks+ Runs the prepare callbacks before serving the request.
-* +ActiveRecord::ConnectionAdapters::ConnectionManagement+ cleans active connections after each request, unless the +rack.test+ key in the request environment is set to _true_.
-* +ActiveRecord::QueryCache+ caches all +SELECT+ queries generated in a request. If an +INSERT+ or +UPDATE+ takes place then the cache is cleaned.
+* +ActiveRecord::ConnectionAdapters::ConnectionManagement+ cleans active connections after each request, unless the +rack.test+ key in the request environment is set to +true+.
+* +ActiveRecord::QueryCache+ caches all SELECT queries generated in a request. If any INSERT or UPDATE takes place then the cache is cleaned.
* +ActionDispatch::Cookies+ sets cookies for the request.
* +ActionDispatch::Session::CookieStore+ is responsible for storing the session in cookies. An alternate middleware can be used for this by changing the +config.action_controller.session_store+ to an alternate value. Additionally, options passed to this can be configured by using +config.action_controller.session_options+.
* +ActionDispatch::Flash+ sets up the +flash+ keys. Only available if +config.action_controller.session_store+ is set to a value.
-* +ActionDispatch::ParamsParser+ parses out parameters from the request into +params+
+* +ActionDispatch::ParamsParser+ parses out parameters from the request into +params+.
* +Rack::MethodOverride+ allows the method to be overridden if +params[:_method]+ is set. This is the middleware which supports the PUT and DELETE HTTP method types.
* +ActionDispatch::Head+ converts HEAD requests to GET requests and serves them as so.
* +ActionDispatch::BestStandardsSupport+ enables "best standards support" so that IE8 renders some elements correctly.
@@ -167,44 +173,44 @@ Every Rails application comes with a standard set of middleware which it uses in
Besides these usual middleware, you can add your own by using the +config.middleware.use+ method:
<ruby>
- config.middleware.use Magical::Unicorns
+config.middleware.use Magical::Unicorns
</ruby>
-This will put the +Magical::Unicorns+ middleware on the end of the stack. If you wish to put this middleware before another use +insert_before+:
+This will put the +Magical::Unicorns+ middleware on the end of the stack. You can use +insert_before+ if you wish to add a middleware before another.
<ruby>
- config.middleware.insert_before ActionDispatch::Head, Magical::Unicorns
+config.middleware.insert_before ActionDispatch::Head, Magical::Unicorns
</ruby>
-There's also +insert_after+ which will insert a middleware _after_ another:
+There's also +insert_after+ which will insert a middleware after another:
<ruby>
- config.middleware.insert_after ActionDispatch::Head, Magical::Unicorns
+config.middleware.insert_after ActionDispatch::Head, Magical::Unicorns
</ruby>
Middlewares can also be completely swapped out and replaced with others:
<ruby>
- config.middleware.swap ActionDispatch::BestStandardsSupport, Magical::Unicorns
+config.middleware.swap ActionDispatch::BestStandardsSupport, Magical::Unicorns
</ruby>
They can also be removed from the stack completely:
<ruby>
- config.middleware.delete ActionDispatch::BestStandardsSupport
+config.middleware.delete ActionDispatch::BestStandardsSupport
</ruby>
h4. Configuring i18n
* +config.i18n.default_locale+ sets the default locale of an application used for i18n. Defaults to +:en+.
-* +config.i18n.load_path+ sets the path Rails uses to look for locale files. Defaults to +config/locales/*.{yml,rb}+
+* +config.i18n.load_path+ sets the path Rails uses to look for locale files. Defaults to +config/locales/*.{yml,rb}+.
h4. Configuring Active Record
<tt>config.active_record</tt> includes a variety of configuration options:
-* +config.active_record.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby 1.8.x Logger class, which is then passed on to any new database connections made. You can retrieve this logger by calling +logger+ on either an Active Record model class or an Active Record model instance. Set to nil to disable logging.
+* +config.active_record.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby Logger class, which is then passed on to any new database connections made. You can retrieve this logger by calling +logger+ on either an Active Record model class or an Active Record model instance. Set to +nil+ to disable logging.
* +config.active_record.primary_key_prefix_type+ lets you adjust the naming for primary key columns. By default, Rails assumes that primary key columns are named +id+ (and this configuration option doesn't need to be set.) There are two other choices:
** +:table_name+ would make the primary key for the Customer class +customerid+
@@ -214,21 +220,21 @@ h4. Configuring Active Record
* +config.active_record.table_name_suffix+ lets you set a global string to be appended to table names. If you set this to +_northwest+, then the Customer class will look for +customers_northwest+ as its table. The default is an empty string.
-* +config.active_record.pluralize_table_names+ specifies whether Rails will look for singular or plural table names in the database. If set to +true+ (the default), then the Customer class will use the +customers+ table. If set to +false+, then the Customers class will use the +customer+ table.
+* +config.active_record.pluralize_table_names+ specifies whether Rails will look for singular or plural table names in the database. If set to +true+ (the default), then the Customer class will use the +customers+ table. If set to +false+, then the Customer class will use the +customer+ table.
-* +config.active_record.default_timezone+ determines whether to use +Time.local+ (if set to +:local+) or +Time.utc+ (if set to +:utc+) when pulling dates and times from the database. The default is +:utc+ for Rails, although ActiveRecord defaults to +:local+ when used outside of Rails.
+* +config.active_record.default_timezone+ determines whether to use +Time.local+ (if set to +:local+) or +Time.utc+ (if set to +:utc+) when pulling dates and times from the database. The default is +:utc+ for Rails, although Active Record defaults to +:local+ when used outside of Rails.
* +config.active_record.schema_format+ controls the format for dumping the database schema to a file. The options are +:ruby+ (the default) for a database-independent version that depends on migrations, or +:sql+ for a set of (potentially database-dependent) SQL statements.
* +config.active_record.timestamped_migrations+ controls whether migrations are numbered with serial integers or with timestamps. The default is +true+, to use timestamps, which are preferred if there are multiple developers working on the same application.
-* +config.active_record.lock_optimistically+ controls whether ActiveRecord will use optimistic locking. By default this is +true+.
+* +config.active_record.lock_optimistically+ controls whether Active Record will use optimistic locking. By default this is +true+.
* +config.active_record.whitelist_attributes+ will create an empty whitelist of attributes available for mass-assignment security for all models in your app.
The MySQL adapter adds one additional configuration option:
-* +ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans+ controls whether ActiveRecord will consider all +tinyint(1)+ columns in a MySQL database to be booleans. By default this is +true+.
+* +ActiveRecord::ConnectionAdapters::MysqlAdapter.emulate_booleans+ controls whether Active Record will consider all +tinyint(1)+ columns in a MySQL database to be booleans. By default this is +true+.
The schema dumper adds one additional configuration option:
@@ -244,13 +250,13 @@ h4. Configuring Action Controller
* +config.action_controller.page_cache_directory+ should be the document root for the web server and is set using <tt>Base.page_cache_directory = "/document/root"</tt>. For Rails, this directory has already been set to +Rails.public_path+ (which is usually set to <tt>Rails.root + "/public"</tt>). Changing this setting can be useful to avoid naming conflicts with files in <tt>public/</tt>, but doing so will likely require configuring your web server to look in the new location for cached files.
-* +config.action_controller.page_cache_extension+ configures the extension used for cached pages saved to +page_cache_directory+. Defaults to +.html+
+* +config.action_controller.page_cache_extension+ configures the extension used for cached pages saved to +page_cache_directory+. Defaults to +.html+.
-* +config.action_controller.perform_caching+ configures whether the application should perform caching or not. Set to _false_ in development mode, _true_ in production.
+* +config.action_controller.perform_caching+ configures whether the application should perform caching or not. Set to false in development mode, true in production.
* +config.action_controller.default_charset+ specifies the default character set for all renders. The default is "utf-8".
-* +config.action_controller.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then used to log information from Action Controller. Set to nil to disable logging.
+* +config.action_controller.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby Logger class, which is then used to log information from Action Controller. Set to +nil+ to disable logging.
* +config.action_controller.request_forgery_protection_token+ sets the token parameter name for RequestForgery. Calling +protect_from_forgery+ sets it to +:authenticity_token+ by default.
@@ -288,36 +294,40 @@ h4. Configuring Action View
There are only a few configuration options for Action View, starting with four on +ActionView::Base+:
-* +config.action_view.field_error_proc+ provides an HTML generator for displaying errors that come from Active Record. The default is <tt>Proc.new{ |html_tag, instance| %Q(%&lt;div class=&quot;field_with_errors&quot;&gt;#{html_tag}&lt;/div&gt;).html_safe }</tt>
+* +config.action_view.field_error_proc+ provides an HTML generator for displaying errors that come from Active Record. The default is
+
+<ruby>
+Proc.new { |html_tag, instance| %Q(<div class="field_with_errors">#{html_tag}</div>).html_safe }
+</ruby>
* +config.action_view.default_form_builder+ tells Rails which form builder to use by default. The default is +ActionView::Helpers::FormBuilder+.
-* +config.action_view.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then used to log information from Action Mailer. Set to nil to disable logging.
+* +config.action_view.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby Logger class, which is then used to log information from Action Mailer. Set to +nil+ to disable logging.
* +config.action_view.erb_trim_mode+ gives the trim mode to be used by ERB. It defaults to +'-'+. See the "ERB documentation":http://www.ruby-doc.org/stdlib/libdoc/erb/rdoc/ for more information.
* +config.action_view.javascript_expansions+ is a hash containing expansions that can be used for the JavaScript include tag. By default, this is defined as:
<ruby>
- config.action_view.javascript_expansions = { :defaults => ['prototype', 'effects', 'dragdrop', 'controls', 'rails'] }
+config.action_view.javascript_expansions = { :defaults => %w(jquery jquery_ujs) }
</ruby>
However, you may add to this by defining others:
<ruby>
- config.action_view.javascript_expansions[:jquery] = ["jquery", "jquery-ui"]
+config.action_view.javascript_expansions[:prototype] = ['prototype', 'effects', 'dragdrop', 'controls']
</ruby>
And can reference in the view with the following code:
<ruby>
- <%= javascript_include_tag :jquery %>
+<%= javascript_include_tag :prototype %>
</ruby>
* +config.action_view.stylesheet_expansions+ works in much the same way as +javascript_expansions+, but has no default key. Keys defined for this hash can be referenced in the view like such:
<ruby>
- <%= stylesheet_link_tag :special %>
+<%= stylesheet_link_tag :special %>
</ruby>
* +ActionView::Helpers::AssetTagHelper::AssetPaths.cache_asset_ids+ With the cache enabled, the asset tag helper methods will make fewer expensive file system calls (the default implementation checks the file system timestamp). However this prevents you from modifying any asset files while the server is running.
@@ -326,7 +336,7 @@ h4. Configuring Action Mailer
There are a number of settings available on +config.action_mailer+:
-* +config.action_mailer.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then used to log information from Action Mailer. Set to nil to disable logging.
+* +config.action_mailer.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby Logger class, which is then used to log information from Action Mailer. Set to +nil+ to disable logging.
* +config.action_mailer.smtp_settings+ allows detailed configuration for the +:smtp+ delivery method. It accepts a hash of options, which can include any of these options:
** +:address+ - Allows you to use a remote mail server. Just change it from its default "localhost" setting.
@@ -348,17 +358,27 @@ There are a number of settings available on +config.action_mailer+:
* +config.action_mailer.default+ configures Action Mailer defaults. These default to:
<ruby>
- :mime_version => "1.0",
- :charset => "UTF-8",
- :content_type => "text/plain",
- :parts_order => [ "text/plain", "text/enriched", "text/html" ]
+:mime_version => "1.0",
+:charset => "UTF-8",
+:content_type => "text/plain",
+:parts_order => [ "text/plain", "text/enriched", "text/html" ]
+</ruby>
+
+* +config.action_mailer.observers+ registers observers which will be notified when mail is delivered.
+<ruby>
+config.active_record.observers = ["MailObserver"]
+</ruby>
+
+* +config.action_mailer.interceptors+ registers interceptors which will be called before mail is sent.
+<ruby>
+config.active_record.interceptors = ["MailInterceptor"]
</ruby>
h4. Configuring Active Resource
There is a single configuration setting available on +config.active_resource+:
-* +config.active_resource.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby 1.8+ Logger class, which is then used to log information from Active Resource. Set to nil to disable logging.
+* +config.active_resource.logger+ accepts a logger conforming to the interface of Log4r or the default Ruby Logger class, which is then used to log information from Active Resource. Set to +nil+ to disable logging.
h4. Configuring Active Support
@@ -398,7 +418,7 @@ Some parts of Rails can also be configured externally by supplying environment v
h3. Using Initializer Files
-After loading the framework and any gems and plugins in your application, Rails turns to loading initializers. An initializer is any file of Ruby code stored under +config/initializers+ in your application. You can use initializers to hold configuration settings that should be made after all of the frameworks, plugins and gems are loaded, such as options to configure settings for these parts.
+After loading the framework and any gems and plugins in your application, Rails turns to loading initializers. An initializer is any Ruby file stored under +config/initializers+ in your application. You can use initializers to hold configuration settings that should be made after all of the frameworks, plugins and gems are loaded, such as options to configure settings for these parts.
NOTE: You can use subfolders to organize your initializers if you like, because Rails will look into the whole file hierarchy from the initializers folder on down.
@@ -406,7 +426,7 @@ TIP: If you have any ordering dependency in your initializers, you can control t
h3. Initialization events
-Rails has 5 initialization events which can be hooked into (listed in order that they are ran):
+Rails has 5 initialization events which can be hooked into (listed in the order that they are ran):
* +before_configuration+: This is run as soon as the application constant inherits from +Rails::Application+. The +config+ calls are evaluated before this happens.
@@ -437,7 +457,7 @@ Initializers defined using the +initializer+ method will be ran in the order the
WARNING: You may put your initializer before or after any other initializer in the chain, as long as it is logical. Say you have 4 initializers called "one" through "four" (defined in that order) and you define "four" to go _before_ "four" but _after_ "three", that just isn't logical and Rails will not be able to determine your initializer order.
-The block's argument of the +initialize+ is the instance of the application itself, and so we can access the configuration on it by using the +config+ method as this initializer does.
+The block argument of the +initializer+ method is the instance of the application itself, and so we can access the configuration on it by using the +config+ method as done in the example.
Because +Rails::Application+ inherits from +Rails::Railtie+ (indirectly), you can use the +initializer+ method in +config/application.rb+ to define initializers for the application.
@@ -450,11 +470,11 @@ Serves as a placeholder so that +:load_environment_config+ can be defined to run
*+load_active_support+* Requires +active_support/dependencies+ which sets up the basis for Active Support. Optionally requires +active_support/all+ if +config.active_support.bare+ is un-truthful, which is the default.
-*+preload_frameworks+* Will load all autoload dependencies of Rails automatically if +config.preload_frameworks+ is +true+ or "truthful". By default this configuration option is disabled. In Rails, when internal classes are referenced for the first time they are autoloaded. +:preload_frameworks+ loads all of this at once on initialization.
+*+preload_frameworks+* Loads all autoload dependencies of Rails automatically if +config.preload_frameworks+ is +true+ or "truthful". By default this configuration option is disabled. In Rails, when internal classes are referenced for the first time they are autoloaded. +:preload_frameworks+ loads all of this at once on initialization.
-*+initialize_logger+* Initializes the logger (an +ActiveSupport::BufferedLogger+ object) for the application and makes it accessible at +Rails.logger+, providing that there's no initializer inserted before this point that has defined +Rails.logger+.
+*+initialize_logger+* Initializes the logger (an +ActiveSupport::BufferedLogger+ object) for the application and makes it accessible at +Rails.logger+, provided that no initializer inserted before this point has defined +Rails.logger+.
-*+initialize_cache+* If +RAILS_CACHE+ isn't yet set, initializes the cache by referencing the value in +config.cache_store+ and stores the outcome as +RAILS_CACHE+. If this object responds to the +middleware+ method, its middleware is inserted before +Rack::Runtime+ in the middleware stack.
+*+initialize_cache+* If +RAILS_CACHE+ isn't set yet, initializes the cache by referencing the value in +config.cache_store+ and stores the outcome as +RAILS_CACHE+. If this object responds to the +middleware+ method, its middleware is inserted before +Rack::Runtime+ in the middleware stack.
*+set_clear_dependencies_hook+* Provides a hook for +active_record.set_dispatch_hooks+ to use, which will run before this initializer. This initializer -- which runs only if +cache_classes+ is set to +false+ -- uses +ActionDispatch::Callbacks.after+ to remove the constants which have been referenced during the request from the object space so that they will be reloaded during the following request.
@@ -464,7 +484,7 @@ Serves as a placeholder so that +:load_environment_config+ can be defined to run
*+i18n.callbacks+* In the development environment, sets up a +to_prepare+ callback which will call +I18n.reload!+ if any of the locales have changed since the last request. In production mode this callback will only run on the first request.
-*+active_support.initialize_whiny_nils+* Will require +active_support/whiny_nil+ if +config.whiny_nils+ is set to +true+. This file will output errors such as:
+*+active_support.initialize_whiny_nils+* Requires +active_support/whiny_nil+ if +config.whiny_nils+ is set to +true+. This file will output errors such as:
<plain>
Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id
@@ -480,19 +500,19 @@ The error occurred while evaluating nil.each
*+active_support.deprecation_behavior+* Sets up deprecation reporting for environments, defaulting to +:log+ for development, +:notify+ for production and +:stderr+ for test. If a value isn't set for +config.active_support.deprecation+ then this initializer will prompt the user to configure this line in the current environment's +config/environments+ file. Can be set to an array of values.
-*+active_support.initialize_time_zone+* Sets the default time zone for the application based off the +config.time_zone+ setting, which defaults to "UTC".
+*+active_support.initialize_time_zone+* Sets the default time zone for the application based on the +config.time_zone+ setting, which defaults to "UTC".
*+action_dispatch.configure+* Configures the +ActionDispatch::Http::URL.tld_length+ to be set to the value of +config.action_dispatch.tld_length+.
-*+action_view.cache_asset_ids+* Will set +ActionView::Helpers::AssetTagHelper::AssetPaths.cache_asset_ids+ to +false+ when Active Support loads, but only if +config.cache_classes+ is too.
+*+action_view.cache_asset_ids+* Sets +ActionView::Helpers::AssetTagHelper::AssetPaths.cache_asset_ids+ to +false+ when Active Support loads, but only if +config.cache_classes+ is too.
*+action_view.javascript_expansions+* Registers the expansions set up by +config.action_view.javascript_expansions+ and +config.action_view.stylesheet_expansions+ to be recognised by Action View and therefore usable in the views.
*+action_view.set_configs+* Sets up Action View by using the settings in +config.action_view+ by +send+'ing the method names as setters to +ActionView::Base+ and passing the values through.
-*+action_controller.logger+* Sets +ActionController::Base.logger+ -- if it's not already set -- to +Rails.logger+.
+*+action_controller.logger+* Sets +ActionController::Base.logger+ -- if it's not already set -- to +Rails.logger+.
-*+action_controller.initialize_framework_caches+* Sets +ActionController::Base.cache_store+ -- if it's not already set -- to +RAILS_CACHE+.
+*+action_controller.initialize_framework_caches+* Sets +ActionController::Base.cache_store+ -- if it's not already set -- to +RAILS_CACHE+.
*+action_controller.set_configs+* Sets up Action Controller by using the settings in +config.action_controller+ by +send+'ing the method names as setters to +ActionController::Base+ and passing the values through.
@@ -506,9 +526,9 @@ The error occurred while evaluating nil.each
*+active_record.initialize_database+* Loads the database configuration (by default) from +config/database.yml+ and establishes a connection for the current environment.
-*+active_record.log_runtime+* Includes +ActiveRecord::Railties::ControllerRuntime+ which is responsible for reporting the length of time Active Record calls took for the request back to the logger.
+*+active_record.log_runtime+* Includes +ActiveRecord::Railties::ControllerRuntime+ which is responsible for reporting the time taken by Active Record calls for the request back to the logger.
-*+active_record.set_dispatch_hooks+* If +config.cache_classes+ is set to false, all reloadable connections to the database will be reset.
+*+active_record.set_dispatch_hooks+* Resets all reloadable connections to the database if +config.cache_classes+ is set to +false+.
*+action_mailer.logger+* Sets +ActionMailer::Base.logger+ -- if it's not already set -- to +Rails.logger+.
@@ -536,10 +556,6 @@ The error occurred while evaluating nil.each
*+load_config_initializers+* Loads all Ruby files from +config/initializers+ in the application, railties and engines. The files in this directory can be used to hold configuration settings that should be made after all of the frameworks and plugins are loaded.
-NOTE: You can use subfolders to organize your initializers if you like, because Rails will look into the whole file hierarchy from the +initializers+ folder on down.
-
-TIP: If you have any ordering dependency in your initializers, you can control the load order by naming. For example, +01_critical.rb+ will be loaded before +02_normal.rb+.
-
*+engines_blank_point+* Provides a point-in-initialization to hook into if you wish to do anything before engines are loaded. After this point, all railtie and engine initializers are ran.
*+add_generator_templates+* Finds templates for generators at +lib/templates+ for the application, railities and engines and adds these to the +config.generators.templates+ setting, which will make the templates available for all generators to reference.
diff --git a/railties/guides/source/contribute.textile b/railties/guides/source/contribute.textile
index 4bd527d4c7..f9bb80861c 100644
--- a/railties/guides/source/contribute.textile
+++ b/railties/guides/source/contribute.textile
@@ -14,7 +14,7 @@ h3. How to Contribute?
* Sample format : "Active Record Associations":https://github.com/lifo/docrails/blob/3e56a3832415476fdd1cb963980d0ae390ac1ed3/railties/guides/source/association_basics.textile.
* Sample output : "Active Record Associations":association_basics.html.
* You can build the Guides during testing by running +bundle exec rake generate_guides+ in the +railties+ directory.
-* You're encouraged to validate XHTML for the generated guides before commiting your changes by running +bundle exec rake validate_guides+ in the +railties+ directory.
+* You're encouraged to validate XHTML for the generated guides before committing your changes by running +bundle exec rake validate_guides+ in the +railties+ directory.
* Edge guides "can be consulted online":http://edgeguides.rubyonrails.org/. That website is generated periodically from docrails.
h3. What to Contribute?
@@ -33,7 +33,7 @@ h3. What to Contribute?
h3. How is the process?
* The preferred way to contribute is to commit to docrails directly.
-* A new guide is only edited by its author until finished though. In that case feedback can be given in its LH ticket.
+* A new guide is only edited by its author until finished though.
* If you are writing a new guide freely commit to docrails partial work and ping lifo or fxn when done with a first draft.
* Guides reviewers will then provide feedback, some of it possibly in form of direct commits to agilize the process.
* Eventually the guide will be approved and added to the index.
@@ -53,7 +53,7 @@ h3. Rules
* If the same guide writer wants to write multiple guides, that's ideally the situation we'd love to be in! However, that guide writer will only receive the cash prize for all the subsequent guides (and not the GitHub or RPM prizes).
* Our review team will have the final say on whether the guide is complete and of good enough quality.
-All authors should read and follow the "Rails Guides Conventions":https://wiki.github.com/lifo/docrails/rails-guides-conventions and the "Rails API Documentation Conventions":https://wiki.github.com/lifo/docrails/rails-api-documentation-conventions.
+All authors should read and follow the "Rails Guides Conventions":ruby_on_rails_guides_guidelines.html and the "Rails API Documentation Conventions":api_documentation_guidelines.html.
h3. Translations
diff --git a/railties/guides/source/contributing_to_ruby_on_rails.textile b/railties/guides/source/contributing_to_ruby_on_rails.textile
index 5eb925d7d2..2ce8ddc702 100644
--- a/railties/guides/source/contributing_to_ruby_on_rails.textile
+++ b/railties/guides/source/contributing_to_ruby_on_rails.textile
@@ -24,7 +24,7 @@ If you've found a problem in Ruby on Rails which is not a security risk do a sea
At the minimum, your issue report needs a title and descriptive text. But that's only a minimum. You should include as much relevant information as possible. You need to at least post the code sample that has the issue. Even better is to include a unit test that shows how the expected behavior is not occurring. Your goal should be to make it easy for yourself - and others - to replicate the bug and figure out a fix.
-Then don't get your hopes up. Unless you have a "Code Red, Mission Critical, The World is Coming to an End" kind of bug, you're creating this issue report in the hope that others with the same problem will be able to collaborate with you on solving it. Do not expect that the issue report will automatically see any activity or that others will jump to fix it. Creating a issue like this is mostly to help yourself start on the path of fixing the problem and for others to confirm it with a "I'm having this problem too" comment.
+Then don't get your hopes up. Unless you have a "Code Red, Mission Critical, The World is Coming to an End" kind of bug, you're creating this issue report in the hope that others with the same problem will be able to collaborate with you on solving it. Do not expect that the issue report will automatically see any activity or that others will jump to fix it. Creating an issue like this is mostly to help yourself start on the path of fixing the problem and for others to confirm it with a "I'm having this problem too" comment.
h4. Special Treatment for Security Issues
@@ -90,7 +90,7 @@ This command will install all dependencies except the MySQL and PostgreSQL Ruby
$ rake test
</shell>
-You can also run tests for an specific framework, like Action Pack, by going into its directory and executing the same command:
+You can also run tests for a specific framework, like Action Pack, by going into its directory and executing the same command:
<shell>
$ cd actionpack
@@ -264,7 +264,7 @@ When working with documentation, please take into account the "API Documentation
NOTE: As explained above, ordinary code patches should have proper documentation coverage. docrails is only used for isolated documentation improvements.
-WARNING: docrails has a very strict policy: no code can be touched whatsoever, no matter how trivial or small the change. Only RDoc and guides can be edited via docrails.
+WARNING: docrails has a very strict policy: no code can be touched whatsoever, no matter how trivial or small the change. Only RDoc and guides can be edited via docrails. Also, CHANGELOGs should never be edited in docrails.
If you have an idea for a new guide you can refer to the "contribution page":contribute.html for instructions on getting involved.
@@ -309,7 +309,7 @@ Rails follows a simple set of coding style conventions.
* a = b and not a=b.
* Follow the conventions you see used in the source already.
-These are some guidelines and please use your best judgement in using them.
+These are some guidelines and please use your best judgment in using them.
h4. Sanity Check
diff --git a/railties/guides/source/credits.html.erb b/railties/guides/source/credits.html.erb
index 65e396be95..da6bd6acdf 100644
--- a/railties/guides/source/credits.html.erb
+++ b/railties/guides/source/credits.html.erb
@@ -9,18 +9,14 @@ Ruby on Rails Guides: Credits
<% end %>
-<h3 class="section">Rails Documentation Team</h3>
+<h3 class="section">Rails Guides Reviewers</h3>
-<%= author('Mike Gunderloy', 'mgunderloy') do %>
- Mike Gunderloy is a consultant with <a href="http://www.actionrails.com">ActionRails</a>. He brings 25 years of experience in a variety of languages to bear on his current work with Rails. His near-daily links and other blogging can be found at <a href="http://afreshcup.com">A Fresh Cup</a> and he <a href="http://twitter.com/MikeG1">twitters</a> too much.
-<% end %>
-
-<%= author('Pratik Naik', 'lifo') do %>
- Pratik Naik is a Ruby on Rails consultant with <a href="http://www.actionrails.com">ActionRails</a> and also a member of the <a href="http://rubyonrails.org/core">Rails core team</a>. He maintains a blog at <a href="http://m.onkey.org">has_many :bugs, :through =&gt; :rails</a> and has an active <a href="http://twitter.com/lifo">twitter account</a>.
+<%= author('Vijay Dev', 'vijaydev', 'vijaydev.jpg') do %>
+ Vijayakumar, found as Vijay Dev on the web, is a web applications developer and an open source enthusiast who lives in Chennai, India. He started using Rails in 2009 and began actively contributing to Rails documentation in late 2010. He <a href="https://twitter.com/vijay_dev">tweets</a> a lot and also <a href="http://vijaydev.wordpress.com">blogs</a>.
<% end %>
<%= author('Xavier Noria', 'fxn', 'fxn.png') do %>
- Xavier Noria has been into Ruby on Rails since 2005. He is a Rails committer and enjoys combining his passion for Rails and his past life as a proofreader of math textbooks. Xavier is currently a Ruby on Rails consultant. Oh, he also <a href="http://twitter.com/fxn">tweets</a> and can be found everywhere as &quot;fxn&quot;.
+ Xavier Noria has been into Ruby on Rails since 2005. He is a Rails core team member and enjoys combining his passion for Rails and his past life as a proofreader of math textbooks. Xavier is currently an independent Ruby on Rails consultant. Oh, he also <a href="http://twitter.com/fxn">tweets</a> and can be found everywhere as &quot;fxn&quot;.
<% end %>
<h3 class="section">Rails Guides Designers</h3>
@@ -31,6 +27,10 @@ Ruby on Rails Guides: Credits
<h3 class="section">Rails Guides Authors</h3>
+<%= author('Ryan Bigg', 'radar', 'radar.png') do %>
+Ryan Bigg works as a consultant at <a href="http://rubyx.com">RubyX</a> and has been working with Rails since 2006. He's co-authoring a book called <a href="http://manning.com/katz">Rails 3 in Action</a> and he's written many gems which can be seen on <a href="http://github.com/radar">his GitHub page</a> and he also tweets prolifically as <a href="http://twitter.com/ryanbigg">@ryanbigg</a>.
+<% end %>
+
<%= author('Frederick Cheung', 'fcheung') do %>
Frederick Cheung is Chief Wizard at Texperts where he has been using Rails since 2006. He is based in Cambridge (UK) and when not consuming fine ales he blogs at <a href="http://www.spacevatican.org">spacevatican.org</a>.
<% end %>
@@ -43,6 +43,10 @@ Ruby on Rails Guides: Credits
Jeff Dean is a software engineer with <a href="http://pivotallabs.com">Pivotal Labs</a>.
<% end %>
+<%= author('Mike Gunderloy', 'mgunderloy') do %>
+ Mike Gunderloy is a consultant with <a href="http://www.actionrails.com">ActionRails</a>. He brings 25 years of experience in a variety of languages to bear on his current work with Rails. His near-daily links and other blogging can be found at <a href="http://afreshcup.com">A Fresh Cup</a> and he <a href="http://twitter.com/MikeG1">twitters</a> too much.
+<% end %>
+
<%= author('Mikel Lindsaar', 'raasdnil') do %>
Mikel Lindsaar has been working with Rails since 2006 and is the author of the Ruby <a href="https://github.com/mikel/mail">Mail gem</a> and core contributor (he helped re-write Action Mailer's API). Mikel is the founder of <a href="http://rubyx.com/">RubyX</a>, has a <a href="http://lindsaar.net/">blog</a> and <a href="http://twitter.com/raasdnil">tweets</a>.
<% end %>
@@ -55,6 +59,10 @@ Ruby on Rails Guides: Credits
James Miller is a software developer for <a href="http://www.jk-tech.com">JK Tech</a> in San Diego, CA. You can find James on GitHub, Gmail, Twitter, and Freenode as &quot;bensie&quot;.
<% end %>
+<%= author('Pratik Naik', 'lifo') do %>
+ Pratik Naik is a Ruby on Rails consultant with <a href="http://www.actionrails.com">ActionRails</a> and also a member of the <a href="http://rubyonrails.org/core">Rails core team</a>. He maintains a blog at <a href="http://m.onkey.org">has_many :bugs, :through =&gt; :rails</a> and has an active <a href="http://twitter.com/lifo">twitter account</a>.
+<% end %>
+
<%= author('Emilio Tagua', 'miloops') do %>
Emilio Tagua &mdash;a.k.a. miloops&mdash; is an Argentinian entrepreneur, developer, open source contributor and Rails evangelist. Cofounder of <a href="http://eventioz.com">Eventioz</a>. He has been using Rails since 2006 and contributing since early 2008. Can be found at gmail, twitter, freenode, everywhere as &quot;miloops&quot;.
<% end %>
diff --git a/railties/guides/source/form_helpers.textile b/railties/guides/source/form_helpers.textile
index 4134c9f8ed..c7e45c0a23 100644
--- a/railties/guides/source/form_helpers.textile
+++ b/railties/guides/source/form_helpers.textile
@@ -545,7 +545,7 @@ NOTE: In many cases the built-in date pickers are clumsy as they do not aid the
h4. Individual Components
-Occasionally you need to display just a single date component such as a year or a month. Rails provides a series of helpers for this, one for each component +select_year+, +select_month+, +select_day+, +select_hour+, +select_minute+, +select_second+. These helpers are fairly straightforward. By default they will generate an input field named after the time component (for example "year" for +select_year+, "month" for +select_month+ etc.) although this can be overriden with the +:field_name+ option. The +:prefix+ option works in the same way that it does for +select_date+ and +select_time+ and has the same default value.
+Occasionally you need to display just a single date component such as a year or a month. Rails provides a series of helpers for this, one for each component +select_year+, +select_month+, +select_day+, +select_hour+, +select_minute+, +select_second+. These helpers are fairly straightforward. By default they will generate an input field named after the time component (for example "year" for +select_year+, "month" for +select_month+ etc.) although this can be overridden with the +:field_name+ option. The +:prefix+ option works in the same way that it does for +select_date+ and +select_time+ and has the same default value.
The first parameter specifies which value should be selected and can either be an instance of a Date, Time or DateTime, in which case the relevant component will be extracted, or a numerical value. For example
diff --git a/railties/guides/source/generators.textile b/railties/guides/source/generators.textile
index a3181b9ac5..2fa1d6e21d 100644
--- a/railties/guides/source/generators.textile
+++ b/railties/guides/source/generators.textile
@@ -46,7 +46,7 @@ class InitializerGenerator < Rails::Generators::Base
end
</ruby>
-NOTE: +create_file+ is a method provided by +Thor::Actions+ and the documentation for it and its brethren can be found at "rdoc.info":http://rdoc.info/github/wycats/thor/master/Thor/Actions.
+NOTE: +create_file+ is a method provided by +Thor::Actions+. Documentation for +create_file+ and other Thor methods can be found in "Thor's documentation":http://rdoc.info/github/wycats/thor/master/Thor/Actions.html
Our new generator is quite simple: it inherits from +Rails::Generators::Base+ and has one method definition. Each public method in the generator is executed when a generator is invoked. Finally, we invoke the +create_file+ method that will create a file at the given destination with the given content. If you are familiar with the Rails Application Templates API, you'll feel right at home with the new generators API.
@@ -131,7 +131,7 @@ And let's execute our generator:
$ rails generate initializer core_extensions
</shell>
-We can see that now a initializer named core_extensions was created at +config/initializers/core_extensions.rb+ with the contents of our template. That means that +copy_file+ copied a file in our source root to the destination path we gave. The method +file_name+ is automatically created when we inherit from +Rails::Generators::NamedBase+.
+We can see that now an initializer named core_extensions was created at +config/initializers/core_extensions.rb+ with the contents of our template. That means that +copy_file+ copied a file in our source root to the destination path we gave. The method +file_name+ is automatically created when we inherit from +Rails::Generators::NamedBase+.
The methods that are available for generators are covered in the "final section":#generator-methods of this guide.
@@ -365,7 +365,7 @@ $ rails generate scaffold Comment body:text
Fallbacks allow your generators to have a single responsibility, increasing code reuse and reducing the amount of duplication.
-h3. Application templates
+h3. Application Templates
Now that you've seen how generators can be used _inside_ an application, did you know they can also be used to _generate_ applications too? This kind of generator is referred as a "template".
diff --git a/railties/guides/source/getting_started.textile b/railties/guides/source/getting_started.textile
index 8a9086f416..670979c3c2 100644
--- a/railties/guides/source/getting_started.textile
+++ b/railties/guides/source/getting_started.textile
@@ -503,7 +503,7 @@ def index
end
</ruby>
-+Post.all+ calls the +Post+ model to return all of the posts currently in the database. The result of this call is an array of posts that we store in a instance variable called +@posts+.
++Post.all+ calls the +Post+ model to return all of the posts currently in the database. The result of this call is an array of posts that we store in an instance variable called +@posts+.
TIP: For more information on finding records with Active Record, see "Active Record Query Interface":active_record_querying.html.
diff --git a/railties/guides/source/i18n.textile b/railties/guides/source/i18n.textile
index 608643b3d3..0c8e4e974d 100644
--- a/railties/guides/source/i18n.textile
+++ b/railties/guides/source/i18n.textile
@@ -809,7 +809,7 @@ That does not mean you're stuck with these limitations, though. The Ruby I18n ge
I18n.backend = Globalize::Backend::Static.new
</ruby>
-You can also use the Chain backend to chain multiple backends together. This is useful when you want to use standard translations with a Simple backend but store custom application translations in a database or other backends. For example, you could use the ActiveRecord backend and fall back to the (default) Simple backend:
+You can also use the Chain backend to chain multiple backends together. This is useful when you want to use standard translations with a Simple backend but store custom application translations in a database or other backends. For example, you could use the Active Record backend and fall back to the (default) Simple backend:
<ruby>
I18n.backend = I18n::Backend::Chain.new(I18n::Backend::ActiveRecord.new, I18n.backend)
diff --git a/railties/guides/source/initialization.textile b/railties/guides/source/initialization.textile
index 638830cd83..1d5b0c0c11 100644
--- a/railties/guides/source/initialization.textile
+++ b/railties/guides/source/initialization.textile
@@ -20,15 +20,15 @@ h4. +bin/rails+
The actual +rails+ command is kept in _bin/rails_ at the and goes like this:
<ruby>
- #!/usr/bin/env ruby
-
- begin
- require "rails/cli"
- rescue LoadError
- railties_path = File.expand_path('../../railties/lib', __FILE__)
- $:.unshift(railties_path)
- require "rails/cli"
- end
+#!/usr/bin/env ruby
+
+begin
+ require "rails/cli"
+rescue LoadError
+ railties_path = File.expand_path('../../railties/lib', __FILE__)
+ $:.unshift(railties_path)
+ require "rails/cli"
+end
</ruby>
This file will attempt to load +rails/cli+ and if it cannot find it then add the +railties/lib+ path to the load path (+$:+) and will then try to require it again.
@@ -38,22 +38,22 @@ h4. +railites/lib/rails/cli.rb+
This file looks like this:
<ruby>
- require 'rbconfig'
- require 'rails/script_rails_loader'
+require 'rbconfig'
+require 'rails/script_rails_loader'
- # If we are inside a Rails application this method performs an exec and thus
- # the rest of this script is not run.
- Rails::ScriptRailsLoader.exec_script_rails!
+# If we are inside a Rails application this method performs an exec and thus
+# the rest of this script is not run.
+Rails::ScriptRailsLoader.exec_script_rails!
- require 'rails/ruby_version_check'
- Signal.trap("INT") { puts; exit }
+require 'rails/ruby_version_check'
+Signal.trap("INT") { puts; exit }
- if ARGV.first == 'plugin'
- ARGV.shift
- require 'rails/commands/plugin_new'
- else
- require 'rails/commands/application'
- end
+if ARGV.first == 'plugin'
+ ARGV.shift
+ require 'rails/commands/plugin_new'
+else
+ require 'rails/commands/application'
+end
</ruby>
The +rbconfig+ file here is out of Ruby's standard library and provides us with the +RbConfig+ class which contains useful information dependent on how Ruby was compiled. We'll see this in use in +railties/lib/rails/script_rails_loader+.
@@ -76,46 +76,46 @@ The +rails/script_rails_loader+ file uses +RbConfig::Config+ to gather up the +b
Back in +rails/cli+, the next line is this:
<ruby>
- Rails::ScriptRailsLoader.exec_script_rails!
+Rails::ScriptRailsLoader.exec_script_rails!
</ruby>
This method is defined in +rails/script_rails_loader+ like this:
<ruby>
- def self.exec_script_rails!
- cwd = Dir.pwd
- return unless in_rails_application? || in_rails_application_subdirectory?
- exec RUBY, SCRIPT_RAILS, *ARGV if in_rails_application?
- Dir.chdir("..") do
- # Recurse in a chdir block: if the search fails we want to be sure
- # the application is generated in the original working directory.
- exec_script_rails! unless cwd == Dir.pwd
- end
- rescue SystemCallError
- # could not chdir, no problem just return
+def self.exec_script_rails!
+ cwd = Dir.pwd
+ return unless in_rails_application? || in_rails_application_subdirectory?
+ exec RUBY, SCRIPT_RAILS, *ARGV if in_rails_application?
+ Dir.chdir("..") do
+ # Recurse in a chdir block: if the search fails we want to be sure
+ # the application is generated in the original working directory.
+ exec_script_rails! unless cwd == Dir.pwd
end
+rescue SystemCallError
+ # could not chdir, no problem just return
+end
</ruby>
This method will first check if the current working directory (+cwd+) is a Rails application or is a subdirectory of one. The way to determine this is defined in the +in_rails_application?+ method like this:
<ruby>
- def self.in_rails_application?
- File.exists?(SCRIPT_RAILS)
- end
+def self.in_rails_application?
+ File.exists?(SCRIPT_RAILS)
+end
</ruby>
The +SCRIPT_RAILS+ constant defined earlier is used here, with +File.exists?+ checking for its presence in the current directory. If this method returns +false+, then +in_rails_application_subdirectory?+ will be used:
<ruby>
- def self.in_rails_application_subdirectory?(path = Pathname.new(Dir.pwd))
- File.exists?(File.join(path, SCRIPT_RAILS)) || !path.root? && in_rails_application_subdirectory?(path.parent)
- end
+def self.in_rails_application_subdirectory?(path = Pathname.new(Dir.pwd))
+ File.exists?(File.join(path, SCRIPT_RAILS)) || !path.root? && in_rails_application_subdirectory?(path.parent)
+end
</ruby>
This climbs the directory tree until it reaches a path which contains a +script/rails+ file. If a directory is reached which contains this file then this line will run:
<ruby>
- exec RUBY, SCRIPT_RAILS, *ARGV if in_rails_application?
+exec RUBY, SCRIPT_RAILS, *ARGV if in_rails_application?
</ruby>
This is effectively the same as doing +ruby script/rails [arguments]+. Where +[arguments]+ at this point in time is simply "server".
@@ -125,9 +125,9 @@ h4. +script/rails+
This file looks like this:
<ruby>
- APP_PATH = File.expand_path('../../config/application', __FILE__)
- require File.expand_path('../../config/boot', __FILE__)
- require 'rails/commands'
+APP_PATH = File.expand_path('../../config/application', __FILE__)
+require File.expand_path('../../config/boot', __FILE__)
+require 'rails/commands'
</ruby>
The +APP_PATH+ constant here will be used later in +rails/commands+. The +config/boot+ file that +script/rails+ references is the +config/boot.rb+ file in our application which is responsible for loading Bundler and setting it up.
@@ -137,19 +137,19 @@ h4. +config/boot.rb+
+config/boot.rb+ contains this:
<ruby>
- require 'rubygems'
+require 'rubygems'
- # Set up gems listed in the Gemfile.
- gemfile = File.expand_path('../../Gemfile', __FILE__)
- begin
- ENV['BUNDLE_GEMFILE'] = gemfile
- require 'bundler'
- Bundler.setup
- rescue Bundler::GemNotFound => e
- STDERR.puts e.message
- STDERR.puts "Try running `bundle install`."
- exit!
- end if File.exist?(gemfile)
+# Set up gems listed in the Gemfile.
+gemfile = File.expand_path('../../Gemfile', __FILE__)
+begin
+ ENV['BUNDLE_GEMFILE'] = gemfile
+ require 'bundler'
+ Bundler.setup
+rescue Bundler::GemNotFound => e
+ STDERR.puts e.message
+ STDERR.puts "Try running `bundle install`."
+ exit!
+end if File.exist?(gemfile)
</ruby>
In a standard Rails application, there's a +Gemfile+ which declares all dependencies of the application. +config/boot.rb+ sets +ENV["BUNDLE_GEMFILE"]+ to the location of this file, then requires Bundler and calls +Bundler.setup+ which adds the dependencies of the application (including all the Rails parts) to the load path, making them available for the application to load. The gems that a Rails 3.1 application depends on are as follows:
@@ -186,34 +186,34 @@ h4. +rails/commands.rb+
Once +config/boot.rb+ has finished, the next file that is required is +rails/commands+ which will execute a command based on the arguments passed in. In this case, the +ARGV+ array simply contains +server+ which is extracted into the +command+ variable using these lines:
<ruby>
- aliases = {
- "g" => "generate",
- "c" => "console",
- "s" => "server",
- "db" => "dbconsole"
- }
+aliases = {
+ "g" => "generate",
+ "c" => "console",
+ "s" => "server",
+ "db" => "dbconsole"
+}
- command = ARGV.shift
- command = aliases[command] || command
+command = ARGV.shift
+command = aliases[command] || command
</ruby>
If we used <tt>s</tt> rather than +server+, Rails will use the +aliases+ defined in the file and match them to their respective commands. With the +server+ command, Rails will run this code:
<ruby>
- when 'server'
- # Change to the application's path if there is no config.ru file in current dir.
- # This allows us to run script/rails server from other directories, but still get
- # the main config.ru and properly set the tmp directory.
- Dir.chdir(File.expand_path('../../', APP_PATH)) unless File.exists?(File.expand_path("config.ru"))
-
- require 'rails/commands/server'
- Rails::Server.new.tap { |server|
- # We need to require application after the server sets environment,
- # otherwise the --environment option given to the server won't propagate.
- require APP_PATH
- Dir.chdir(Rails.application.root)
- server.start
- }
+when 'server'
+ # Change to the application's path if there is no config.ru file in current dir.
+ # This allows us to run script/rails server from other directories, but still get
+ # the main config.ru and properly set the tmp directory.
+ Dir.chdir(File.expand_path('../../', APP_PATH)) unless File.exists?(File.expand_path("config.ru"))
+
+ require 'rails/commands/server'
+ Rails::Server.new.tap { |server|
+ # We need to require application after the server sets environment,
+ # otherwise the --environment option given to the server won't propagate.
+ require APP_PATH
+ Dir.chdir(Rails.application.root)
+ server.start
+ }
</ruby>
This file will change into the root of the directory (a path two directories back from +APP_PATH+ which points at +config/application.rb+), but only if the +config.ru+ file isn't found. This then requires +rails/commands/server+ which requires +action_dispatch+ and sets up the +Rails::Server+ class.
@@ -239,7 +239,7 @@ The +methods.rb+ file is responsible for defining methods such as +camelize+, +u
In this file there are a lot of lines such as this inside the +ActiveSupport+ module:
<ruby>
- autoload :Inflector
+autoload :Inflector
</ruby>
Due to the overriding of the +autoload+ method, Ruby will know to look for this file at +activesupport/lib/active_support/inflector.rb+ when the +Inflector+ class is first referenced.
@@ -263,10 +263,10 @@ h4. +rails/commands/server.rb+
The +Rails::Server+ class is defined in this file as inheriting from +Rack::Server+. When +Rails::Server.new+ is called, this calls the +initialize+ method in +rails/commands/server.rb+:
<ruby>
- def initialize(*)
- super
- set_environment
- end
+def initialize(*)
+ super
+ set_environment
+end
</ruby>
Firstly, +super+ is called which calls the +initialize+ method on +Rack::Server+.
@@ -278,10 +278,10 @@ h4. Rack: +lib/rack/server.rb+
The +initialize+ method in +Rack::Server+ simply sets a couple of variables:
<ruby>
- def initialize(options = nil)
- @options = options
- @app = options[:app] if options && options[:app]
- end
+def initialize(options = nil)
+ @options = options
+ @app = options[:app] if options && options[:app]
+end
</ruby>
In this case, +options+ will be +nil+ so nothing happens in this method.
@@ -289,64 +289,64 @@ In this case, +options+ will be +nil+ so nothing happens in this method.
After +super+ has finished in +Rack::Server+, we jump back to +rails/commands/server.rb+. At this point, +set_environment+ is called within the context of the +Rails::Server+ object and this method doesn't appear to do much at first glance:
<ruby>
- def set_environment
- ENV["RAILS_ENV"] ||= options[:environment]
- end
+def set_environment
+ ENV["RAILS_ENV"] ||= options[:environment]
+end
</ruby>
In fact, the +options+ method here does quite a lot. This method is defined in +Rack::Server+ like this:
<ruby>
- def options
- @options ||= parse_options(ARGV)
- end
+def options
+ @options ||= parse_options(ARGV)
+end
</ruby>
Then +parse_options+ is defined like this:
<ruby>
- def parse_options(args)
- options = default_options
+def parse_options(args)
+ options = default_options
- # Don't evaluate CGI ISINDEX parameters.
- # http://hoohoo.ncsa.uiuc.edu/cgi/cl.html
- args.clear if ENV.include?("REQUEST_METHOD")
+ # Don't evaluate CGI ISINDEX parameters.
+ # http://hoohoo.ncsa.uiuc.edu/cgi/cl.html
+ args.clear if ENV.include?("REQUEST_METHOD")
- options.merge! opt_parser.parse! args
- options[:config] = ::File.expand_path(options[:config])
- ENV["RACK_ENV"] = options[:environment]
- options
- end
+ options.merge! opt_parser.parse! args
+ options[:config] = ::File.expand_path(options[:config])
+ ENV["RACK_ENV"] = options[:environment]
+ options
+end
</ruby>
With the +default_options+ set to this:
<ruby>
- def default_options
- {
- :environment => ENV['RACK_ENV'] || "development",
- :pid => nil,
- :Port => 9292,
- :Host => "0.0.0.0",
- :AccessLog => [],
- :config => "config.ru"
- }
- end
+def default_options
+ {
+ :environment => ENV['RACK_ENV'] || "development",
+ :pid => nil,
+ :Port => 9292,
+ :Host => "0.0.0.0",
+ :AccessLog => [],
+ :config => "config.ru"
+ }
+end
</ruby>
There is no +REQUEST_METHOD+ key in +ENV+ so we can skip over that line. The next line merges in the options from +opt_parser+ which is defined plainly in +Rack::Server+
<ruby>
- def opt_parser
- Options.new
- end
+def opt_parser
+ Options.new
+end
</ruby>
The class *is* defined in +Rack::Server+, but is overwritten in +Rails::Server+ to take different arguments. Its +parse!+ method begins like this:
<ruby>
- def parse!(args)
- args, options = args.dup, {}
+def parse!(args)
+ args, options = args.dup, {}
opt_parser = OptionParser.new do |opts|
opts.banner = "Usage: rails server [mongrel, thin, etc] [options]"
@@ -362,100 +362,101 @@ h4. +Rails::Server#start+
This method is defined like this:
<ruby>
- def start
- puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}"
- puts "=> Rails #{Rails.version} application starting in #{Rails.env} 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]
-
- #Create required tmp directories if not found
- %w(cache pids sessions sockets).each do |dir_to_make|
- FileUtils.mkdir_p(Rails.root.join('tmp', dir_to_make))
- end
-
- super
- ensure
- # The '-h' option calls exit before @options is set.
- # If we call 'options' with it unset, we get double help banners.
- puts 'Exiting' unless @options && options[:daemonize]
+def start
+ puts "=> Booting #{ActiveSupport::Inflector.demodulize(server)}"
+ puts "=> Rails #{Rails.version} application starting in #{Rails.env} 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]
+
+ #Create required tmp directories if not found
+ %w(cache pids sessions sockets).each do |dir_to_make|
+ FileUtils.mkdir_p(Rails.root.join('tmp', dir_to_make))
end
+
+ super
+ensure
+ # The '-h' option calls exit before @options is set.
+ # If we call 'options' with it unset, we get double help banners.
+ puts 'Exiting' unless @options && options[:daemonize]
+end
</ruby>
This is where the first output of the Rails initialization happens. This method creates a trap for +INT+ signals, so if you +CTRL+C+ the server, it will exit the process. As we can see from the code here, it will create the +tmp/cache+, +tmp/pids+, +tmp/sessions+ and +tmp/sockets+ directories if they don't already exist prior to calling +super+. The +super+ method will call +Rack::Server.start+ which begins its definition like this:
<ruby>
- def start
- if options[:warn]
- $-w = true
- end
+def start
+ if options[:warn]
+ $-w = true
+ end
- if includes = options[:include]
- $LOAD_PATH.unshift(*includes)
- end
+ if includes = options[:include]
+ $LOAD_PATH.unshift(*includes)
+ end
- if library = options[:require]
- require library
- end
+ if library = options[:require]
+ require library
+ end
- if options[:debug]
- $DEBUG = true
- require 'pp'
- p options[:server]
- pp wrapped_app
- pp app
- end
+ if options[:debug]
+ $DEBUG = true
+ require 'pp'
+ p options[:server]
+ pp wrapped_app
+ pp app
+ end
+end
</ruby>
In a Rails application, these options are not set at all and therefore aren't used at all. The first line of code that's executed in this method is a call to this method:
<ruby>
- wrapped_app
+wrapped_app
</ruby>
This method calls another method:
<ruby>
- @wrapped_app ||= build_app app
+@wrapped_app ||= build_app app
</ruby>
Then the +app+ method here is defined like so:
<ruby>
- def app
- @app ||= begin
- if !::File.exist? options[:config]
- abort "configuration #{options[:config]} not found"
- end
-
- app, options = Rack::Builder.parse_file(self.options[:config], opt_parser)
- self.options.merge! options
- app
+def app
+ @app ||= begin
+ if !::File.exist? options[:config]
+ abort "configuration #{options[:config]} not found"
end
+
+ app, options = Rack::Builder.parse_file(self.options[:config], opt_parser)
+ self.options.merge! options
+ app
end
+end
</ruby>
The +options[:config]+ value defaults to +config.ru+ which contains this:
<ruby>
- # This file is used by Rack-based servers to start the application.
+# This file is used by Rack-based servers to start the application.
- require ::File.expand_path('../config/environment', __FILE__)
- run YourApp::Application
+require ::File.expand_path('../config/environment', __FILE__)
+run YourApp::Application
</ruby>
The +Rack::Builder.parse_file+ method here takes the content from this +config.ru+ file and parses it using this code:
<ruby>
- app = eval "Rack::Builder.new {( " + cfgfile + "\n )}.to_app",
+app = eval "Rack::Builder.new {( " + cfgfile + "\n )}.to_app",
TOPLEVEL_BINDING, config
</ruby>
The <ruby>initialize</ruby> method will take the block here and execute it within an instance of +Rack::Builder+. This is where the majority of the initialization process of Rails happens. The chain of events that this simple line sets off will be the focus of a large majority of this guide. The +require+ line for +config/environment.rb+ in +config.ru+ is the first to run:
<ruby>
- require ::File.expand_path('../config/environment', __FILE__)
+require ::File.expand_path('../config/environment', __FILE__)
</ruby>
h4. +config/environment.rb+
@@ -475,7 +476,7 @@ h3. Loading Rails
The next line in +config/application.rb+ is:
<ruby>
- require 'rails/all'
+require 'rails/all'
</ruby>
h4. +railties/lib/rails/all.rb+
@@ -483,20 +484,20 @@ h4. +railties/lib/rails/all.rb+
This file is responsible for requiring all the individual parts of Rails like so:
<ruby>
- require "rails"
+require "rails"
- %w(
+%w(
active_record
action_controller
action_mailer
active_resource
rails/test_unit
- ).each do |framework|
- begin
- require "#{framework}/railtie"
- rescue LoadError
- end
+).each do |framework|
+ begin
+ require "#{framework}/railtie"
+ rescue LoadError
end
+end
</ruby>
First off the line is the +rails+ require itself.
@@ -518,9 +519,9 @@ h4. +active_support/core_ext/kernel/reporting.rb+
This is the first of the many Active Support core extensions that come with Rails. This one in particular defines methods in the +Kernel+ module which is mixed in to the +Object+ class so the methods are available on +main+ and can therefore be called like this:
<ruby>
- silence_warnings do
- # some code
- end
+silence_warnings do
+ # some code
+end
</ruby>
These methods can be used to silence STDERR responses and the +silence_stream+ allows you to also silence other streams. Additionally, this mixin allows you to suppress exceptions and capture streams. For more information see the "Silencing Warnings, Streams, and Exceptions":http://guides.rubyonrails.org/active_support_core_extensions.html#silencing-warnings-streams-and-exceptions section from the Active Support Core Extensions Guide.
@@ -635,14 +636,14 @@ h4. +railties/lib/rails/rack.rb+
The final file to be loaded by +railties/lib/rails/configuration.rb+ is +rails/rack+ which defines some simple autoloads:
<ruby>
- module Rails
- module Rack
- autoload :Debugger, "rails/rack/debugger"
- autoload :Logger, "rails/rack/logger"
- autoload :LogTailer, "rails/rack/log_tailer"
- autoload :Static, "rails/rack/static"
- end
+module Rails
+ module Rack
+ autoload :Debugger, "rails/rack/debugger"
+ autoload :Logger, "rails/rack/logger"
+ autoload :LogTailer, "rails/rack/log_tailer"
+ autoload :Static, "rails/rack/static"
end
+end
</ruby>
Once this file is finished loading, then the +Rails::Configuration+ class is initialized. This completes the loading of +railties/lib/rails/configuration.rb+ and now we jump back to the loading of +railties/lib/rails/railtie.rb+, where the next file loaded is +active_support/inflector+.
@@ -652,12 +653,12 @@ h4. +activesupport/lib/active_support/inflector.rb+
+active_support/inflector.rb+ requires a series of file which are responsible for setting up the basics for knowing how to pluralize and singularize words. These files are:
<ruby>
- require 'active_support/inflector/inflections'
- require 'active_support/inflector/transliterate'
- require 'active_support/inflector/methods'
+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'
+require 'active_support/inflections'
+require 'active_support/core_ext/string/inflections'
</ruby>
The +active_support/inflector/methods+ file has already been required by +active_support/autoload+ and so won't be loaded again here.
@@ -721,22 +722,22 @@ h4. +activesupport/lib/active_support/i18n_railtie.rb+
This file is the first file that sets up configuration with these lines inside the class:
<ruby>
- class Railtie < Rails::Railtie
- config.i18n = ActiveSupport::OrderedOptions.new
- config.i18n.railties_load_path = []
- config.i18n.load_path = []
- config.i18n.fallbacks = ActiveSupport::OrderedOptions.new
+class Railtie < Rails::Railtie
+ config.i18n = ActiveSupport::OrderedOptions.new
+ config.i18n.railties_load_path = []
+ config.i18n.load_path = []
+ config.i18n.fallbacks = ActiveSupport::OrderedOptions.new
</ruby>
By inheriting from +Rails::Railtie+ the +Rails::Railtie#inherited+ method is called:
<ruby>
- def inherited(base)
- unless base.abstract_railtie?
- base.send(:include, Railtie::Configurable)
- subclasses << base
- end
+def inherited(base)
+ unless base.abstract_railtie?
+ base.send(:include, Railtie::Configurable)
+ subclasses << base
end
+end
</ruby>
This first checks if the Railtie that's inheriting it is a component of Rails itself:
@@ -763,15 +764,15 @@ end
The +config+ method used at the top of +I18n::Railtie+ is defined on +Rails::Railtie+ and is defined like this:
<ruby>
- def config
- @config ||= Railtie::Configuration.new
- end
+def config
+ @config ||= Railtie::Configuration.new
+end
</ruby>
At this point, that +Railtie::Configuration+ constant is automatically loaded which causes the +rails/railties/configuration+ file to be loaded. The line for this is this particular line in +railties/lib/rails/railtie.rb+:
<ruby>
- autoload :Configuration, "rails/railtie/configuration"
+autoload :Configuration, "rails/railtie/configuration"
</ruby>
h4. +railties/lib/rails/railtie/configuration.rb+
@@ -781,15 +782,15 @@ This file begins with a require out to +rails/configuration+ which has already b
This file defines the +Rails::Railtie::Configuration+ class which is responsible for providing a way to easily configure railties and it's the +initialize+ method here which is called by the +config+ method back in the +i18n_railtie.rb+ file. The methods on this object don't exist, and so are rescued by the +method_missing+ defined further down in +configuration.rb+:
<ruby>
- def method_missing(name, *args, &blk)
- if name.to_s =~ /=$/
- @@options[$`.to_sym] = args.first
- elsif @@options.key?(name)
- @@options[name]
- else
- super
- end
+def method_missing(name, *args, &blk)
+ if name.to_s =~ /=$/
+ @@options[$`.to_sym] = args.first
+ elsif @@options.key?(name)
+ @@options[name]
+ else
+ super
end
+end
</ruby>
So therefore when an option is referred to it simply stores the value as the key if it's used in a setter context, or retrieves it if used in a getter context. Nothing fancy going on there.
@@ -799,21 +800,21 @@ h4. Back to +activesupport/lib/active_support/i18n_railtie.rb+
After the configuration method the +reloader+ method is defined, and then the first of of Railties' initializers is defined: +i18n.callbacks+.
<ruby>
- initializer "i18n.callbacks" do
- ActionDispatch::Reloader.to_prepare do
- I18n::Railtie.reloader.execute_if_updated
- end
+initializer "i18n.callbacks" do
+ ActionDispatch::Reloader.to_prepare do
+ I18n::Railtie.reloader.execute_if_updated
end
+end
</ruby>
The +initializer+ method (from the +Rails::Initializable+ module) here doesn't run the block, but rather stores it to be run later on:
<ruby>
- def initializer(name, opts = {}, &blk)
- raise ArgumentError, "A block must be passed when defining an initializer" unless blk
- opts[:after] ||= initializers.last.name unless initializers.empty? || initializers.find { |i| i.name == opts[:before] }
- initializers << Initializer.new(name, nil, opts, &blk)
- end
+def initializer(name, opts = {}, &blk)
+ raise ArgumentError, "A block must be passed when defining an initializer" unless blk
+ opts[:after] ||= initializers.last.name unless initializers.empty? || initializers.find { |i| i.name == opts[:before] }
+ initializers << Initializer.new(name, nil, opts, &blk)
+end
</ruby>
An initializer can be configured to run before or after another initializer, which we'll see a couple of times throughout this initialization process. Anything that inherits from +Rails::Railtie+ may also make use of the +initializer+ method, something which is covered in the "Configuration guide":[http://ryanbigg.com/guides/configuring.html#rails-railtie-initializer].
@@ -821,25 +822,25 @@ An initializer can be configured to run before or after another initializer, whi
The +Initializer+ class here is defined within the +Rails::Initializable+ module and its +initialize+ method is defined to just set up a couple of variables:
<ruby>
- def initialize(name, context, options, &block)
- @name, @context, @options, @block = name, context, options, block
- end
+def initialize(name, context, options, &block)
+ @name, @context, @options, @block = name, context, options, block
+end
</ruby>
Once this +initialize+ method is finished, the object is added to the object the +initializers+ method returns:
<ruby>
- def initializers
- @initializers ||= self.class.initializers_for(self)
- end
+def initializers
+ @initializers ||= self.class.initializers_for(self)
+end
</ruby>
If +@initializers+ isn't set (which it won't be at this point), the +intializers_for+ method will be called for this class.
<ruby>
- def initializers_for(binding)
- Collection.new(initializers_chain.map { |i| i.bind(binding) })
- end
+def initializers_for(binding)
+ Collection.new(initializers_chain.map { |i| i.bind(binding) })
+end
</ruby>
The +Collection+ class in +railties/lib/rails/initializable.rb+ inherits from +Array+ and includes the +TSort+ module which is used to sort out the order of the initializers based on the order they are placed in.
@@ -847,57 +848,57 @@ The +Collection+ class in +railties/lib/rails/initializable.rb+ inherits from +A
The +initializers_chain+ method referenced in the +initializers_for+ method is defined like this:
<rub>
- def initializers_chain
- initializers = Collection.new
- ancestors.reverse_each do | klass |
- next unless klass.respond_to?(:initializers)
- initializers = initializers + klass.initializers
- end
- initializers
+def initializers_chain
+ initializers = Collection.new
+ ancestors.reverse_each do | klass |
+ next unless klass.respond_to?(:initializers)
+ initializers = initializers + klass.initializers
end
+ initializers
+end
</ruby>
This method collects the initializers from the ancestors of this class and adds them to a new +Collection+ object using the <tt>+</tt> method which is defined like this for the <tt>Collection</tt> class:
<ruby>
- def +(other)
- Collection.new(to_a + other.to_a)
- end
+def +(other)
+ Collection.new(to_a + other.to_a)
+end
</ruby>
-So this <tt>+</tt> method is overriden to return a new collection comprising of the existing collection as an array and then using the <tt>Array#+</tt> method combines these two collections, returning a "super" +Collection+ object. In this case, the only initializer that's going to be in this new +Collection+ object is the +i18n.callbacks+ initializer.
+So this <tt>+</tt> method is overridden to return a new collection comprising of the existing collection as an array and then using the <tt>Array#+</tt> method combines these two collections, returning a "super" +Collection+ object. In this case, the only initializer that's going to be in this new +Collection+ object is the +i18n.callbacks+ initializer.
The next method to be called after this +initializer+ method is the +after_initialize+ method on the +config+ object, which is defined like this:
<ruby>
- def after_initialize(&block)
- ActiveSupport.on_load(:after_initialize, :yield => true, &block)
- end
+def after_initialize(&block)
+ ActiveSupport.on_load(:after_initialize, :yield => true, &block)
+end
</ruby>
The +on_load+ method here is provided by the +active_support/lazy_load_hooks+ file which was required earlier and is defined like this:
<ruby>
- def self.on_load(name, options = {}, &block)
- if base = @loaded[name]
- execute_hook(base, options, block)
- else
- @load_hooks[name] << [block, options]
- end
+def self.on_load(name, options = {}, &block)
+ if base = @loaded[name]
+ execute_hook(base, options, block)
+ else
+ @load_hooks[name] << [block, options]
end
+end
</ruby>
The +@loaded+ variable here is a hash containing elements representing the different components of Rails that have been loaded at this stage. Currently, this hash is empty. So the +else+ is executed here, using the +@load_hooks+ variable defined in +active_support/lazy_load_hooks+:
<ruby>
- @load_hooks = Hash.new {|h,k| h[k] = [] }
+@load_hooks = Hash.new {|h,k| h[k] = [] }
</ruby>
This defines a new hash which has keys that default to empty arrays. This saves Rails from having to do something like this instead:
<ruby>
- @load_hooks[name] = []
- @load_hooks[name] << [block, options]
+@load_hooks[name] = []
+@load_hooks[name] << [block, options]
</ruby>
The value added to this array here consists of the block and options passed to +after_initialize+.
@@ -929,11 +930,11 @@ h4. +activesupport/lib/action_dispatch.rb+
This file attempts to locate the +active_support+ and +active_model+ libraries by looking a couple of directories back from the current file and then adds the +active_support+ and +active_model+ +lib+ directories to the load path, but only if they aren't already, which they are.
<ruby>
- activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__)
- $:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path)
+activesupport_path = File.expand_path('../../../activesupport/lib', __FILE__)
+$:.unshift(activesupport_path) if File.directory?(activesupport_path) && !$:.include?(activesupport_path)
- activemodel_path = File.expand_path('../../../activemodel/lib', __FILE__)
- $:.unshift(activemodel_path) if File.directory?(activemodel_path) && !$:.include?(activemodel_path)
+activemodel_path = File.expand_path('../../../activemodel/lib', __FILE__)
+$:.unshift(activemodel_path) if File.directory?(activemodel_path) && !$:.include?(activemodel_path)
</ruby>
In effect, these lines only define the +activesupport_path+ and +activemodel_path+ variables and nothing more.
@@ -941,23 +942,23 @@ In effect, these lines only define the +activesupport_path+ and +activemodel_pat
The next two requires in this file are already done, so they are not run:
<ruby>
- require 'active_support'
- require 'active_support/dependencies/autoload'
+require 'active_support'
+require 'active_support/dependencies/autoload'
</ruby>
The following require is to +action_pack+ (+activesupport/lib/action_pack.rb+) which has a 22-line copyright notice at the top of it and ends in a simple require to +action_pack/version+. This file, like other +version.rb+ files before it, defines the +ActionPack::VERSION+ constant:
<ruby>
- module ActionPack
- module VERSION #:nodoc:
- MAJOR = 3
- MINOR = 1
- TINY = 0
- PRE = "beta"
-
- STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
- end
+module ActionPack
+ module VERSION #:nodoc:
+ MAJOR = 3
+ MINOR = 1
+ TINY = 0
+ PRE = "beta"
+
+ STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
end
+end
</ruby>
Once +action_pack+ is finished, then +active_model+ is required.
@@ -967,16 +968,16 @@ h4. +activemodel/lib/active_model.rb+
This file makes a require to +active_model/version+ which defines the version for Active Model:
<ruby>
- module ActiveModel
- module VERSION #:nodoc:
- MAJOR = 3
- MINOR = 1
- TINY = 0
- PRE = "beta"
-
- STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
- end
+module ActiveModel
+ module VERSION #:nodoc:
+ MAJOR = 3
+ MINOR = 1
+ TINY = 0
+ PRE = "beta"
+
+ STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
end
+end
</ruby>
Once the +version.rb+ file is loaded, the +ActiveModel+ module has its autoloaded constants defined as well as a sub-module called +ActiveModel::Serializers+ which has autoloads of its own. When the +ActiveModel+ module is closed the +active_support/i18n+ file is required.
@@ -986,15 +987,15 @@ h4. +activesupport/lib/active_support/i18n.rb+
This is where the +i18n+ gem is required and first configured:
<ruby>
- begin
- require 'i18n'
- require 'active_support/lazy_load_hooks'
- rescue LoadError => e
- $stderr.puts "You don't have i18n installed in your application. Please add it to your Gemfile and run bundle install"
- raise e
- end
+begin
+ require 'i18n'
+ require 'active_support/lazy_load_hooks'
+rescue LoadError => e
+ $stderr.puts "You don't have i18n installed in your application. Please add it to your Gemfile and run bundle install"
+ raise e
+end
- I18n.load_path << "#{File.dirname(__FILE__)}/locale/en.yml"
+I18n.load_path << "#{File.dirname(__FILE__)}/locale/en.yml"
</ruby>
In effect, the +I18n+ module first defined by +i18n_railtie+ is extended by the +i18n+ gem, rather than the other way around. This has no ill effect. They both work on the same way.
@@ -1012,9 +1013,9 @@ h4. Back to +activesupport/lib/action_dispatch.rb+
The remainder of this file requires the +rack+ file from the Rack gem which defines the +Rack+ module. After +rack+, there's autoloads defined for the +Rack+, +ActionDispatch+, +ActionDispatch::Http+, +ActionDispatch::Session+. A new method called +autoload_under+ is used here, and this simply prefixes the files where the modules are autoloaded from with the path specified. For example here:
<ruby>
- autoload_under 'testing' do
- autoload :Assertions
- ...
+autoload_under 'testing' do
+ autoload :Assertions
+...
</ruby>
The +Assertions+ module is in the +action_dispatch/testing+ folder rather than simply +action_dispatch+.
@@ -1046,25 +1047,25 @@ This file begins by detecting if the +lib+ directories of +active_support+ and +
The first three requires have already been done by other files and so aren't loaded here, but the 4th require, the one to +arel+ will require the file provided by the Arel gem, which defines the +Arel+ module.
<ruby>
- require 'active_support'
- require 'active_support/i18n'
- require 'active_model'
- require 'arel'
+require 'active_support'
+require 'active_support/i18n'
+require 'active_model'
+require 'arel'
</ruby>
The 5th require in this file is one to +active_record/version+ which defines the +ActiveRecord::VERSION+ constant:
<ruby>
- module ActiveRecord
- module VERSION #:nodoc:
- MAJOR = 3
- MINOR = 1
- TINY = 0
- PRE = "beta"
-
- STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
- end
+module ActiveRecord
+ module VERSION #:nodoc:
+ MAJOR = 3
+ MINOR = 1
+ TINY = 0
+ PRE = "beta"
+
+ STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
end
+end
</ruby>
Once these requires are finished, the base for the +ActiveRecord+ module is defined along with its autoloads.
@@ -1072,9 +1073,9 @@ Once these requires are finished, the base for the +ActiveRecord+ module is defi
Near the end of the file, we see this line:
<ruby>
- ActiveSupport.on_load(:active_record) do
- Arel::Table.engine = self
- end
+ActiveSupport.on_load(:active_record) do
+ Arel::Table.engine = self
+end
</ruby>
This will set the engine for +Arel::Table+ to be +ActiveRecord::Base+.
@@ -1082,7 +1083,7 @@ This will set the engine for +Arel::Table+ to be +ActiveRecord::Base+.
The file then finishes with this line:
<ruby>
- I18n.load_path << File.dirname(__FILE__) + '/active_record/locale/en.yml'
+I18n.load_path << File.dirname(__FILE__) + '/active_record/locale/en.yml'
</ruby>
This will add the translations from +activerecord/lib/active_record/locale/en.yml+ to the load path for +I18n+, with this file being parsed when all the translations are loaded.
@@ -1092,8 +1093,8 @@ h4. Back to +activerecord/lib/active_record/railtie.rb+
The next two <tt>require</tt>s in this file aren't run because their files are already required, with +rails+ being required by +rails/all+ and +active_model/railtie+ being required from +action_dispatch+.
<ruby>
- require "rails"
- require "active_model/railtie"
+require "rails"
+require "active_model/railtie"
</ruby>
The next +require+ in this file is to +action_controller/railtie+.
@@ -1103,9 +1104,9 @@ h4. +actionpack/lib/action_controller/railtie.rb+
This file begins with a couple more requires to files that have already been loaded:
<ruby>
- require "rails"
- require "action_controller"
- require "action_dispatch/railtie"
+require "rails"
+require "action_controller"
+require "action_dispatch/railtie"
</ruby>
However the require after these is to a file that hasn't yet been loaded, +action_view/railtie+, which begins by requiring +action_view+.
diff --git a/railties/guides/source/layouts_and_rendering.textile b/railties/guides/source/layouts_and_rendering.textile
index d67668df91..ba45b84242 100644
--- a/railties/guides/source/layouts_and_rendering.textile
+++ b/railties/guides/source/layouts_and_rendering.textile
@@ -123,7 +123,7 @@ Cache-Control: no-cache
$
</shell>
-We see there is an empty response (no data after the +Cache-Control+ line), but the request was successful because Rails has set the response to 200 OK. You can set the +:status+ option on render to change this response. Rendering nothing can be useful for AJAX requests where all you want to send back to the browser is an acknowledgement that the request was completed.
+We see there is an empty response (no data after the +Cache-Control+ line), but the request was successful because Rails has set the response to 200 OK. You can set the +:status+ option on render to change this response. Rendering nothing can be useful for AJAX requests where all you want to send back to the browser is an acknowledgment that the request was completed.
TIP: You should probably be using the +head+ method, discussed later in this guide, instead of +render :nothing+. This provides additional flexibility and makes it explicit that you're only generating HTTP headers.
diff --git a/railties/guides/source/migrations.textile b/railties/guides/source/migrations.textile
index d60b68ec7f..f17f686d47 100644
--- a/railties/guides/source/migrations.textile
+++ b/railties/guides/source/migrations.textile
@@ -55,6 +55,8 @@ class AddReceiveNewsletterToUsers < ActiveRecord::Migration
end
</ruby>
+NOTE: Some "caveats":#using-models-in-your-migrations apply to using models in your migrations.
+
This migration adds a +receive_newsletter+ column to the +users+ table. We want it to default to +false+ for new users, but existing users are considered
to have already opted in, so we use the User model to set the flag to +true+ for existing users.
@@ -73,11 +75,9 @@ class CreateProducts < ActiveRecord::Migration
end
</ruby>
-NOTE: Some "caveats":#using-models-in-your-migrations apply to using models in your migrations.
-
h4. Migrations are Classes
-A migration is a subclass of <tt>ActiveRecord::Migration</tt> that implements two class methods: +up+ (perform the required transformations) and +down+ (revert them).
+A migration is a subclass of <tt>ActiveRecord::Migration</tt> that implements two methods: +up+ (perform the required transformations) and +down+ (revert them).
Active Record provides methods that perform common data definition tasks in a database independent way (you'll read about them in detail later):
@@ -115,7 +115,7 @@ h4. Changing Migrations
Occasionally you will make a mistake when writing a migration. If you have already run the migration then you cannot just edit the migration and run the migration again: Rails thinks it has already run the migration and so will do nothing when you run +rake db:migrate+. You must rollback the migration (for example with +rake db:rollback+), edit your migration and then run +rake db:migrate+ to run the corrected version.
-In general editing existing migrations is not a good idea: you will be creating extra work for yourself and your co-workers and cause major headaches if the existing version of the migration has already been run on production machines. Instead you should write a new migration that performs the changes you require. Editing a freshly generated migration that has not yet been committed to source control (or more generally which has not been propagated beyond your development machine) is relatively harmless. Just use some common sense.
+In general editing existing migrations is not a good idea: you will be creating extra work for yourself and your co-workers and cause major headaches if the existing version of the migration has already been run on production machines. Instead you should write a new migration that performs the changes you require. Editing a freshly generated migration that has not yet been committed to source control (or more generally which has not been propagated beyond your development machine) is relatively harmless.
h3. Creating a Migration
diff --git a/railties/guides/source/performance_testing.textile b/railties/guides/source/performance_testing.textile
index 2b79237c59..83db7eee59 100644
--- a/railties/guides/source/performance_testing.textile
+++ b/railties/guides/source/performance_testing.textile
@@ -276,7 +276,7 @@ measurement,created_at,app,rails,ruby,platform
h5(#output-profiling). Profiling
-In profiling mode, performance tests can generate multiple types of outputs. The command line output is always presented but support for the others is dependant on the interpreter in use. A brief description of each type and their availability across interpreters is given below.
+In profiling mode, performance tests can generate multiple types of outputs. The command line output is always presented but support for the others is dependent on the interpreter in use. A brief description of each type and their availability across interpreters is given below.
h6. Command Line
diff --git a/railties/guides/source/rails_on_rack.textile b/railties/guides/source/rails_on_rack.textile
index aa53aa6db6..8d5985dba8 100644
--- a/railties/guides/source/rails_on_rack.textile
+++ b/railties/guides/source/rails_on_rack.textile
@@ -111,11 +111,11 @@ h5. Adding a Middleware
You can add a new middleware to the middleware stack using any of the following methods:
-* +config.middleware.use(new_middleware, args)+ - Adds the new middleware at the bottom of the middleware stack.
+* <tt>config.middleware.use(new_middleware, args)</tt> - Adds the new middleware at the bottom of the middleware stack.
-* +config.middleware.insert_before(existing_middleware, new_middleware, args)+ - Adds the new middleware before the specified existing middleware in the middleware stack.
+* <tt>config.middleware.insert_before(existing_middleware, new_middleware, args)</tt> - Adds the new middleware before the specified existing middleware in the middleware stack.
-* +config.middleware.insert_after(existing_middleware, new_middleware, args)+ - Adds the new middleware after the specified existing middleware in the middleware stack.
+* <tt>config.middleware.insert_after(existing_middleware, new_middleware, args)</tt> - Adds the new middleware after the specified existing middleware in the middleware stack.
<ruby>
# config/environment.rb
@@ -154,20 +154,20 @@ h4. Internal Middleware Stack
Much of Action Controller's functionality is implemented as Middlewares. The following table explains the purpose of each of them:
|_.Middleware|_.Purpose|
-|+Rack::Lock+|Sets +env["rack.multithread"]+ flag to +true+ and wraps the application within a Mutex.|
+|+Rack::Lock+|Sets <tt>env["rack.multithread"]</tt> flag to +true+ and wraps the application within a Mutex.|
|+ActionController::Failsafe+|Returns HTTP Status +500+ to the client if an exception gets raised while dispatching.|
|+ActiveRecord::QueryCache+|Enables the Active Record query cache.|
|+ActionController::Session::CookieStore+|Uses the cookie based session store.|
|+ActionController::Session::MemCacheStore+|Uses the memcached based session store.|
|+ActiveRecord::SessionStore+|Uses the database based session store.|
-|+Rack::MethodOverride+|Sets HTTP method based on +_method+ parameter or +env["HTTP_X_HTTP_METHOD_OVERRIDE"]+.|
+|+Rack::MethodOverride+|Sets HTTP method based on +_method+ parameter or <tt>env["HTTP_X_HTTP_METHOD_OVERRIDE"]</tt>.|
|+Rack::Head+|Discards the response body if the client sends a +HEAD+ request.|
TIP: It's possible to use any of the above middlewares in your custom Rack stack.
h4. Customizing Internal Middleware Stack
-It's possible to replace the entire middleware stack with a custom stack using +ActionController::Dispatcher.middleware=+.
+It's possible to replace the entire middleware stack with a custom stack using <tt>ActionController::Dispatcher.middleware=</tt>.
Put the following in an initializer:
diff --git a/railties/guides/source/routing.textile b/railties/guides/source/routing.textile
index 08615bed4e..1cbc5c8f6e 100644
--- a/railties/guides/source/routing.textile
+++ b/railties/guides/source/routing.textile
@@ -288,7 +288,7 @@ When using +magazine_ad_path+, you can pass in instances of +Magazine+ and +Ad+
You can also use +url_for+ with a set of objects, and Rails will automatically determine which route you want:
<erb>
-<%= link_to "Ad details", url_for(@magazine, @ad) %>
+<%= link_to "Ad details", url_for([@magazine, @ad]) %>
</erb>
In this case, Rails will see that +@magazine+ is a +Magazine+ and +@ad+ is an +Ad+ and will therefore use the +magazine_ad_path+ helper. In helpers like +link_to+, you can specify just the object in place of the full +url_for+ call:
diff --git a/railties/guides/source/ruby_on_rails_guides_guidelines.textile b/railties/guides/source/ruby_on_rails_guides_guidelines.textile
index 9ae360a73b..5989191b5c 100644
--- a/railties/guides/source/ruby_on_rails_guides_guidelines.textile
+++ b/railties/guides/source/ruby_on_rails_guides_guidelines.textile
@@ -65,7 +65,7 @@ It is also recommended that you work with +WARNINGS=1+. This detects duplicate I
If you want to generate guides in languages other than English, you can keep them in a separate directory under +source+ (eg. <tt>source/es</tt>) and use the +GUIDES_LANGUAGE+ environment variable:
<plain>
-rake generate_guides GUIDES_LANGUAGE=es
+bundle exec rake generate_guides GUIDES_LANGUAGE=es
</plain>
h3. HTML Validation
@@ -73,7 +73,7 @@ h3. HTML Validation
Please validate the generated HTML with:
<plain>
-rake validate_guides
+bundle exec rake validate_guides
</plain>
Particularly, titles get an ID generated from their content and this often leads to duplicates. Please set +WARNINGS=1+ when generating guides to detect them. The warning messages suggest a way to fix them.
diff --git a/railties/guides/source/testing.textile b/railties/guides/source/testing.textile
index 7a93c3a1e6..db9c7545c8 100644
--- a/railties/guides/source/testing.textile
+++ b/railties/guides/source/testing.textile
@@ -929,8 +929,8 @@ class UserControllerTest < ActionController::TestCase
end
invite_email = ActionMailer::Base.deliveries.first
- assert_equal invite_email.subject, "You have been invited by me@example.com"
- assert_equal invite_email.to[0], 'friend@example.com'
+ assert_equal "You have been invited by me@example.com", invite_email.subject
+ assert_equal 'friend@example.com', invite_email.to[0]
assert_match /Hi friend@example.com/, invite_email.body
end
end
diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb
index 497d4b5ac3..a2b2af98a6 100644
--- a/railties/lib/rails/application.rb
+++ b/railties/lib/rails/application.rb
@@ -130,6 +130,10 @@ module Rails
@config ||= Application::Configuration.new(find_root_with_flag("config.ru", Dir.pwd))
end
+ def to_app
+ self
+ end
+
protected
alias :build_middleware_stack :app
diff --git a/railties/lib/rails/commands.rb b/railties/lib/rails/commands.rb
index bf6644c782..5e55aeada9 100644
--- a/railties/lib/rails/commands.rb
+++ b/railties/lib/rails/commands.rb
@@ -91,7 +91,7 @@ In addition to those, there are:
benchmarker See how fast a piece of code runs
profiler Get profile information from a piece of code
plugin Install a plugin
- runner Run a piece of code in the application environment
+ runner Run a piece of code in the application environment (short-cut alias: "r")
All commands can be run with -h for more information.
EOT
diff --git a/railties/lib/rails/commands/benchmarker.rb b/railties/lib/rails/commands/benchmarker.rb
index b06c915ac3..6c52d0f70f 100644
--- a/railties/lib/rails/commands/benchmarker.rb
+++ b/railties/lib/rails/commands/benchmarker.rb
@@ -9,7 +9,7 @@ ARGV.pop
def options
options = {}
defaults = ActiveSupport::Testing::Performance::DEFAULTS
-
+
OptionParser.new do |opt|
opt.banner = "Usage: rails benchmarker 'Ruby.code' 'Ruby.more_code' ... [OPTS]"
opt.on('-r', '--runs N', Numeric, 'Number of runs.', "Default: #{defaults[:runs]}") { |r| options[:runs] = r }
@@ -17,13 +17,13 @@ def options
opt.on('-m', '--metrics a,b,c', Array, 'Metrics to use.', "Default: #{defaults[:metrics].join(",")}") { |m| options[:metrics] = m.map(&:to_sym) }
opt.parse!(ARGV)
end
-
+
options
end
class BenchmarkerTest < ActionDispatch::PerformanceTest
self.profile_options = options
-
+
ARGV.each do |expression|
eval <<-RUBY
def test_#{expression.parameterize('_')}
diff --git a/railties/lib/rails/commands/profiler.rb b/railties/lib/rails/commands/profiler.rb
index 94cf32d32d..ea6347c918 100644
--- a/railties/lib/rails/commands/profiler.rb
+++ b/railties/lib/rails/commands/profiler.rb
@@ -6,7 +6,7 @@ require 'active_support/testing/performance'
def options
options = {}
defaults = ActiveSupport::Testing::Performance::DEFAULTS
-
+
OptionParser.new do |opt|
opt.banner = "Usage: rails benchmarker 'Ruby.code' 'Ruby.more_code' ... [OPTS]"
opt.on('-r', '--runs N', Numeric, 'Number of runs.', "Default: #{defaults[:runs]}") { |r| options[:runs] = r }
@@ -15,13 +15,13 @@ def options
opt.on('-f', '--formats x,y,z', Array, 'Formats to output to.', "Default: #{defaults[:formats].join(",")}") { |m| options[:formats] = m.map(&:to_sym) }
opt.parse!(ARGV)
end
-
+
options
end
class ProfilerTest < ActionDispatch::PerformanceTest
self.profile_options = options
-
+
ARGV.each do |expression|
eval <<-RUBY
def test_#{expression.parameterize('_')}
diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb
index 91c87514cf..23392276d5 100644
--- a/railties/lib/rails/commands/server.rb
+++ b/railties/lib/rails/commands/server.rb
@@ -43,7 +43,7 @@ module Rails
end
def app
- @app ||= super.instance
+ @app ||= super.respond_to?(:to_app) ? super.to_app : super
end
def opt_parser
diff --git a/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt b/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt
index 19294b3478..f33a7f4ac2 100644
--- a/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt
+++ b/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt
@@ -1,9 +1,15 @@
-// This is a manifest file that'll be compiled into including all the files listed below.
-// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
-// be included in the compiled file accessible from http://example.com/assets/application.js
+// This is a manifest file that'll be compiled into application.js, which will include all the files
+// listed below.
+//
+// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
+// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
+//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// the compiled file.
//
+// WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
+// GO AFTER THE REQUIRES BELOW.
+//
<% unless options[:skip_javascript] -%>
//= require <%= options[:javascript] %>
//= require <%= options[:javascript] %>_ujs
diff --git a/railties/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css b/railties/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css
index fc25b5723f..9e07c7d9a9 100644
--- a/railties/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css
+++ b/railties/lib/rails/generators/rails/app/templates/app/assets/stylesheets/application.css
@@ -1,7 +1,13 @@
/*
- * This is a manifest file that'll automatically include all the stylesheets available in this directory
- * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
- * the top of the compiled file, but it's generally better to create a new file per style scope.
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
+ * listed below.
+ *
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
+ *
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
+ * compiled file, but it's generally better to create a new file per style scope.
+ *
*= require_self
*= require_tree .
*/ \ No newline at end of file
diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/wrap_parameters.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/initializers/wrap_parameters.rb.tt
index e56195da80..fa1548db8b 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/initializers/wrap_parameters.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/wrap_parameters.rb.tt
@@ -1,7 +1,7 @@
# Be sure to restart your server when you modify this file.
#
-# This file contains the settings for ActionController::ParametersWrapper
-# which will be enabled by default in the upcoming version of Ruby on Rails.
+# This file contains settings for ActionController::ParamsWrapper which
+# is enabled by default.
# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
ActionController::Base.wrap_parameters <%= key_value :format, "[:json]" %>
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 5d1be041a5..3fea27b916 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
@@ -5,7 +5,7 @@ class BrowsingTest < ActionDispatch::PerformanceTest
# Refer to the documentation for all available options
# self.profile_options = { :runs => 5, :metrics => [:wall_time, :memory]
# :output => 'tmp/performance', :formats => [:flat] }
-
+
def test_homepage
get '/'
end
diff --git a/railties/lib/rails/generators/rails/assets/USAGE b/railties/lib/rails/generators/rails/assets/USAGE
index c5375cdc06..d2e5ed4482 100644
--- a/railties/lib/rails/generators/rails/assets/USAGE
+++ b/railties/lib/rails/generators/rails/assets/USAGE
@@ -7,7 +7,7 @@ Description:
This generates a JavaScript stub in app/assets/javascripts and a stylesheet
stub in app/assets/stylesheets.
-
+
If CoffeeScript is available, JavaScripts will be generated with the .coffee extension.
If Sass 3 is available, stylesheets will be generated with the .scss extension.
diff --git a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb
index 184fe19c06..807350316c 100644
--- a/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb
+++ b/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb
@@ -118,7 +118,7 @@ task :default => :test
return if options.skip_javascript?
if mountable?
- copy_file "#{app_templates_dir}/app/assets/javascripts/application.js.tt",
+ template "#{app_templates_dir}/app/assets/javascripts/application.js.tt",
"app/assets/javascripts/application.js"
elsif full?
empty_directory_with_gitkeep "app/assets/javascripts"
diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile b/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile
index 29900c93dc..c28e568711 100644
--- a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile
+++ b/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile
@@ -6,6 +6,10 @@ source "http://rubygems.org"
<%= database_gemfile_entry -%>
<% end -%>
+<% if mountable? -%>
+<%= gem_for_javascript -%>
+<% end -%>
+
if RUBY_VERSION < '1.9'
gem "ruby-debug", ">= 0.10.3"
end
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 14a878328b..d296b26b16 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
@@ -5,7 +5,7 @@ class <%= class_name %>Test < ActionDispatch::PerformanceTest
# Refer to the documentation for all available options
# self.profile_options = { :runs => 5, :metrics => [:wall_time, :memory]
# :output => 'tmp/performance', :formats => [:flat] }
-
+
def test_homepage
get '/'
end
diff --git a/railties/lib/rails/railtie/configurable.rb b/railties/lib/rails/railtie/configurable.rb
index 920ab67ff1..53796c74cf 100644
--- a/railties/lib/rails/railtie/configurable.rb
+++ b/railties/lib/rails/railtie/configurable.rb
@@ -1,3 +1,5 @@
+require 'active_support/concern'
+
module Rails
class Railtie
module Configurable
diff --git a/railties/lib/rails/tasks/assets.rake b/railties/lib/rails/tasks/assets.rake
index 5d2f02af13..4678ea460e 100644
--- a/railties/lib/rails/tasks/assets.rake
+++ b/railties/lib/rails/tasks/assets.rake
@@ -7,4 +7,15 @@ namespace :assets do
assets = Rails.application.config.assets.precompile
Rails.application.assets.precompile(*assets)
end
+
+ desc "Remove compiled assets"
+ task :clean => :environment do
+ assets = Rails.application.config.assets
+ public_asset_path = Rails.public_path + assets.prefix
+ file_list = FileList.new("#{public_asset_path}/*.js", "#{public_asset_path}/*.css")
+ file_list.each do |file|
+ rm file
+ rm "#{file}.gz", :force => true
+ end
+ end
end
diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb
index 98a702f134..2b593005a2 100644
--- a/railties/test/application/assets_test.rb
+++ b/railties/test/application/assets_test.rb
@@ -11,6 +11,10 @@ module ApplicationTests
boot_rails
end
+ def teardown
+ teardown_app
+ end
+
def app
@app ||= Rails.application
end
diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb
index 0e27c9606d..477dada820 100644
--- a/railties/test/application/configuration_test.rb
+++ b/railties/test/application/configuration_test.rb
@@ -35,6 +35,7 @@ module ApplicationTests
end
def teardown
+ teardown_app
FileUtils.rm_rf(new_app) if File.directory?(new_app)
end
diff --git a/railties/test/application/console_test.rb b/railties/test/application/console_test.rb
index db8f1f2ac6..1528d5dd87 100644
--- a/railties/test/application/console_test.rb
+++ b/railties/test/application/console_test.rb
@@ -1,13 +1,17 @@
require 'isolation/abstract_unit'
class ConsoleTest < Test::Unit::TestCase
- include ActiveSupport::Testing::Isolation
+ include ActiveSupport::Testing::Isolation
def setup
build_app
boot_rails
end
+ def teardown
+ teardown_app
+ end
+
def load_environment(sandbox = false)
require "#{rails_root}/config/environment"
Rails.application.sandbox = sandbox
diff --git a/railties/test/application/generators_test.rb b/railties/test/application/generators_test.rb
index 1ca9515335..4365d00b1f 100644
--- a/railties/test/application/generators_test.rb
+++ b/railties/test/application/generators_test.rb
@@ -9,6 +9,10 @@ module ApplicationTests
boot_rails
end
+ def teardown
+ teardown_app
+ end
+
def app_const
@app_const ||= Class.new(Rails::Application)
end
diff --git a/railties/test/application/initializers/boot_test.rb b/railties/test/application/initializers/boot_test.rb
index 5ec562f12f..b1e01dc13f 100644
--- a/railties/test/application/initializers/boot_test.rb
+++ b/railties/test/application/initializers/boot_test.rb
@@ -9,8 +9,12 @@ module ApplicationTests
# boot_rails
end
+ def teardown
+ # teardown_app
+ end
+
test "booting rails sets the load paths correctly" do
# This test is pending reworking the boot process
end
end
-end \ No newline at end of file
+end
diff --git a/railties/test/application/initializers/check_ruby_version_test.rb b/railties/test/application/initializers/check_ruby_version_test.rb
index 5b6196307d..df7e9696a9 100644
--- a/railties/test/application/initializers/check_ruby_version_test.rb
+++ b/railties/test/application/initializers/check_ruby_version_test.rb
@@ -9,6 +9,10 @@ module ApplicationTests
boot_rails
end
+ def teardown
+ teardown_app
+ end
+
test "rails initializes with ruby 1.8.7 or later, except for 1.9.1" do
if RUBY_VERSION < '1.8.7'
assert_rails_does_not_boot
diff --git a/railties/test/application/initializers/frameworks_test.rb b/railties/test/application/initializers/frameworks_test.rb
index 196d121c14..446c85d65a 100644
--- a/railties/test/application/initializers/frameworks_test.rb
+++ b/railties/test/application/initializers/frameworks_test.rb
@@ -10,6 +10,10 @@ module ApplicationTests
FileUtils.rm_rf "#{app_path}/config/environments"
end
+ def teardown
+ teardown_app
+ end
+
# AC & AM
test "set load paths set only if action controller or action mailer are in use" do
assert_nothing_raised NameError do
diff --git a/railties/test/application/initializers/hooks_test.rb b/railties/test/application/initializers/hooks_test.rb
index 198abbe861..8c7726339c 100644
--- a/railties/test/application/initializers/hooks_test.rb
+++ b/railties/test/application/initializers/hooks_test.rb
@@ -10,6 +10,10 @@ module ApplicationTests
FileUtils.rm_rf "#{app_path}/config/environments"
end
+ def teardown
+ teardown_app
+ end
+
test "load initializers" do
app_file "config/initializers/foo.rb", "$foo = true"
require "#{app_path}/config/environment"
diff --git a/railties/test/application/initializers/i18n_test.rb b/railties/test/application/initializers/i18n_test.rb
index 390f65ab5c..aa4db6e12a 100644
--- a/railties/test/application/initializers/i18n_test.rb
+++ b/railties/test/application/initializers/i18n_test.rb
@@ -11,6 +11,10 @@ module ApplicationTests
require "rails/all"
end
+ def teardown
+ teardown_app
+ end
+
def load_app
require "#{app_path}/config/environment"
end
diff --git a/railties/test/application/initializers/load_path_test.rb b/railties/test/application/initializers/load_path_test.rb
index 714d62311d..644b8208a9 100644
--- a/railties/test/application/initializers/load_path_test.rb
+++ b/railties/test/application/initializers/load_path_test.rb
@@ -10,6 +10,10 @@ module ApplicationTests
FileUtils.rm_rf "#{app_path}/config/environments"
end
+ def teardown
+ teardown_app
+ end
+
test "initializing an application adds the application paths to the load path" do
add_to_config <<-RUBY
config.root = "#{app_path}"
diff --git a/railties/test/application/initializers/notifications_test.rb b/railties/test/application/initializers/notifications_test.rb
index c87433db0d..b72c14eaf0 100644
--- a/railties/test/application/initializers/notifications_test.rb
+++ b/railties/test/application/initializers/notifications_test.rb
@@ -9,6 +9,10 @@ module ApplicationTests
boot_rails
end
+ def teardown
+ teardown_app
+ end
+
def instrument(*args, &block)
ActiveSupport::Notifications.instrument(*args, &block)
end
diff --git a/railties/test/application/loading_test.rb b/railties/test/application/loading_test.rb
index c340465e87..47c6fd5c6e 100644
--- a/railties/test/application/loading_test.rb
+++ b/railties/test/application/loading_test.rb
@@ -8,6 +8,10 @@ class LoadingTest < Test::Unit::TestCase
boot_rails
end
+ def teardown
+ teardown_app
+ end
+
def app
@app ||= Rails.application
end
diff --git a/railties/test/application/middleware/best_practices_test.rb b/railties/test/application/middleware/best_practices_test.rb
index 5b722e7510..1c88b9bf06 100644
--- a/railties/test/application/middleware/best_practices_test.rb
+++ b/railties/test/application/middleware/best_practices_test.rb
@@ -12,6 +12,10 @@ module ApplicationTests
simple_controller
end
+ def teardown
+ teardown_app
+ end
+
test "simple controller in production mode returns best standards" do
get '/foo'
assert_equal "IE=Edge,chrome=1", last_response.headers["X-UA-Compatible"]
diff --git a/railties/test/application/middleware/cache_test.rb b/railties/test/application/middleware/cache_test.rb
index a8033d2b23..e656ada3c0 100644
--- a/railties/test/application/middleware/cache_test.rb
+++ b/railties/test/application/middleware/cache_test.rb
@@ -11,6 +11,10 @@ module ApplicationTests
extend Rack::Test::Methods
end
+ def teardown
+ teardown_app
+ end
+
def simple_controller
controller :expires, <<-RUBY
class ExpiresController < ApplicationController
diff --git a/railties/test/application/middleware/remote_ip_test.rb b/railties/test/application/middleware/remote_ip_test.rb
index f28302d70a..da291f061c 100644
--- a/railties/test/application/middleware/remote_ip_test.rb
+++ b/railties/test/application/middleware/remote_ip_test.rb
@@ -10,6 +10,10 @@ module ApplicationTests
FileUtils.rm_rf "#{app_path}/config/environments"
end
+ def teardown
+ teardown_app
+ end
+
def app
@app ||= Rails.application
end
diff --git a/railties/test/application/middleware/sendfile_test.rb b/railties/test/application/middleware/sendfile_test.rb
index 0128261cd4..c7a1c573f9 100644
--- a/railties/test/application/middleware/sendfile_test.rb
+++ b/railties/test/application/middleware/sendfile_test.rb
@@ -10,6 +10,10 @@ module ApplicationTests
FileUtils.rm_rf "#{app_path}/config/environments"
end
+ def teardown
+ teardown_app
+ end
+
def app
@app ||= Rails.application
end
diff --git a/railties/test/application/middleware/show_exceptions_test.rb b/railties/test/application/middleware/show_exceptions_test.rb
index 5487e41e0a..e3f27f63c3 100644
--- a/railties/test/application/middleware/show_exceptions_test.rb
+++ b/railties/test/application/middleware/show_exceptions_test.rb
@@ -10,6 +10,10 @@ module ApplicationTests
FileUtils.rm_rf "#{app_path}/config/environments"
end
+ def teardown
+ teardown_app
+ end
+
def app
@app ||= Rails.application
end
diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb
index 715798ca08..6a0a272073 100644
--- a/railties/test/application/middleware_test.rb
+++ b/railties/test/application/middleware_test.rb
@@ -11,6 +11,10 @@ module ApplicationTests
FileUtils.rm_rf "#{app_path}/config/environments"
end
+ def teardown
+ teardown_app
+ end
+
def app
@app ||= Rails.application
end
@@ -200,4 +204,4 @@ module ApplicationTests
AppTemplate::Application.middleware.map(&:klass).map(&:name)
end
end
-end \ No newline at end of file
+end
diff --git a/railties/test/application/paths_test.rb b/railties/test/application/paths_test.rb
index 03e0247556..0d22d8c19a 100644
--- a/railties/test/application/paths_test.rb
+++ b/railties/test/application/paths_test.rb
@@ -20,6 +20,10 @@ module ApplicationTests
@paths = Rails.application.config.paths
end
+ def teardown
+ teardown_app
+ end
+
def root(*path)
app_path(*path).to_s
end
diff --git a/railties/test/application/rack/logger_test.rb b/railties/test/application/rack/logger_test.rb
index 715af5c642..8b2b2f1802 100644
--- a/railties/test/application/rack/logger_test.rb
+++ b/railties/test/application/rack/logger_test.rb
@@ -14,6 +14,10 @@ module ApplicationTests
super
end
+ def teardown
+ teardown_app
+ end
+
def logs
@logs ||= @logger.logged(:info)
end
diff --git a/railties/test/application/rackup_test.rb b/railties/test/application/rackup_test.rb
index b0a9925890..ff9cdcadc7 100644
--- a/railties/test/application/rackup_test.rb
+++ b/railties/test/application/rackup_test.rb
@@ -15,6 +15,10 @@ module ApplicationTests
boot_rails
end
+ def teardown
+ teardown_app
+ end
+
test "rails app is present" do
assert File.exist?(app_path("config"))
end
diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb
index ab36ace5e5..44ac6615de 100644
--- a/railties/test/application/rake_test.rb
+++ b/railties/test/application/rake_test.rb
@@ -10,6 +10,10 @@ module ApplicationTests
FileUtils.rm_rf("#{app_path}/config/environments")
end
+ def teardown
+ teardown_app
+ end
+
def test_gems_tasks_are_loaded_first_than_application_ones
app_file "lib/tasks/app.rake", <<-RUBY
$task_loaded = Rake::Task.task_defined?("db:create:all")
@@ -113,7 +117,7 @@ module ApplicationTests
end
require "#{rails_root}/config/environment"
-
+
# loading a specific fixture
errormsg = Dir.chdir(app_path) { `rake db:fixtures:load FIXTURES=products` }
assert $?.success?, errormsg
diff --git a/railties/test/application/routing_test.rb b/railties/test/application/routing_test.rb
index e3a7f8a63c..3adf0ccd3e 100644
--- a/railties/test/application/routing_test.rb
+++ b/railties/test/application/routing_test.rb
@@ -11,6 +11,10 @@ module ApplicationTests
boot_rails
end
+ def teardown
+ teardown_app
+ end
+
test "rails/info/properties in development" do
app("development")
get "/rails/info/properties"
diff --git a/railties/test/application/runner_test.rb b/railties/test/application/runner_test.rb
index 292d1e247f..4104bacae5 100644
--- a/railties/test/application/runner_test.rb
+++ b/railties/test/application/runner_test.rb
@@ -18,6 +18,10 @@ module ApplicationTests
MODEL
end
+ def teardown
+ teardown_app
+ end
+
def test_should_include_runner_in_shebang_line_in_help
assert_match "/rails runner", Dir.chdir(app_path) { `bundle exec rails runner --help` }
end
diff --git a/railties/test/application/test_test.rb b/railties/test/application/test_test.rb
index f96319f472..27a7959e84 100644
--- a/railties/test/application/test_test.rb
+++ b/railties/test/application/test_test.rb
@@ -9,6 +9,10 @@ module ApplicationTests
boot_rails
end
+ def teardown
+ teardown_app
+ end
+
test "truth" do
app_file 'test/unit/foo_test.rb', <<-RUBY
require 'test_helper'
diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb
index e87fd265ce..283d99dd9e 100644
--- a/railties/test/generators/plugin_new_generator_test.rb
+++ b/railties/test/generators/plugin_new_generator_test.rb
@@ -111,6 +111,28 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase
assert_file "app/assets/javascripts/application.js"
end
+ def test_jquery_is_the_default_javascript_library
+ run_generator [destination_root, "--mountable"]
+ assert_file "app/assets/javascripts/application.js" do |contents|
+ assert_match %r{^//= require jquery}, contents
+ assert_match %r{^//= require jquery_ujs}, contents
+ end
+ assert_file 'Gemfile' do |contents|
+ assert_match(/^gem 'jquery-rails'/, contents)
+ end
+ end
+
+ def test_other_javascript_libraries
+ run_generator [destination_root, "--mountable", '-j', 'prototype']
+ assert_file "app/assets/javascripts/application.js" do |contents|
+ assert_match %r{^//= require prototype}, contents
+ assert_match %r{^//= require prototype_ujs}, contents
+ end
+ assert_file 'Gemfile' do |contents|
+ assert_match(/^gem 'prototype-rails'/, contents)
+ end
+ end
+
def test_skip_javascripts
run_generator [destination_root, "--skip-javascript", "--mountable"]
assert_no_file "app/assets/javascripts/application.js"
diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb
index 53d3f288d9..0a203fd4d0 100644
--- a/railties/test/isolation/abstract_unit.rb
+++ b/railties/test/isolation/abstract_unit.rb
@@ -91,6 +91,9 @@ module TestHelpers
module Generation
# Build an application by invoking the generator and going through the whole stack.
def build_app(options = {})
+ @prev_rails_env = ENV['RAILS_ENV']
+ ENV['RAILS_ENV'] = 'development'
+
FileUtils.rm_rf(app_path)
FileUtils.cp_r(tmp_path('app_template'), app_path)
@@ -115,6 +118,10 @@ module TestHelpers
add_to_config 'config.secret_token = "3b7cd727ee24e8444053437c36cc66c4"; config.session_store :cookie_store, :key => "_myapp_session"; config.active_support.deprecation = :log'
end
+ def teardown_app
+ ENV['RAILS_ENV'] = @prev_rails_env if @prev_rails_env
+ end
+
# Make a very basic app, without creating the whole directory structure.
# This is faster and simpler than the method above.
def make_basic_app
diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb
index 4c1da76c7d..0ff1e0f180 100644
--- a/railties/test/railties/engine_test.rb
+++ b/railties/test/railties/engine_test.rb
@@ -25,6 +25,10 @@ module RailtiesTest
end
end
+ def teardown
+ teardown_app
+ end
+
test "Rails::Engine itself does not respond to config" do
boot_rails
assert !Rails::Engine.respond_to?(:config)
diff --git a/railties/test/railties/mounted_engine_test.rb b/railties/test/railties/mounted_engine_test.rb
index 47a4753e78..b793a7401f 100644
--- a/railties/test/railties/mounted_engine_test.rb
+++ b/railties/test/railties/mounted_engine_test.rb
@@ -106,6 +106,10 @@ module ApplicationTests
boot_rails
end
+ def teardown
+ teardown_app
+ end
+
def app
@app ||= begin
require "#{app_path}/config/environment"
@@ -116,7 +120,7 @@ module ApplicationTests
def reset_script_name!
Rails.application.routes.default_url_options = {}
end
-
+
def script_name(script_name)
Rails.application.routes.default_url_options = {:script_name => script_name}
end
@@ -171,4 +175,3 @@ module ApplicationTests
end
end
end
-
diff --git a/railties/test/railties/plugin_ordering_test.rb b/railties/test/railties/plugin_ordering_test.rb
index f6ca493fdf..1cfaf557e9 100644
--- a/railties/test/railties/plugin_ordering_test.rb
+++ b/railties/test/railties/plugin_ordering_test.rb
@@ -12,6 +12,10 @@ module RailtiesTest
plugin "c_plugin", "$arr << :c"
end
+ def teardown
+ teardown_app
+ end
+
def boot_rails
super
require "#{app_path}/config/environment"
@@ -69,4 +73,4 @@ module RailtiesTest
assert $bar
end
end
-end \ No newline at end of file
+end
diff --git a/railties/test/railties/plugin_test.rb b/railties/test/railties/plugin_test.rb
index c15ac05103..f307d53cf7 100644
--- a/railties/test/railties/plugin_test.rb
+++ b/railties/test/railties/plugin_test.rb
@@ -15,6 +15,10 @@ module RailtiesTest
end
end
+ def teardown
+ teardown_app
+ end
+
test "Rails::Plugin itself does not respond to config" do
boot_rails
assert !Rails::Plugin.respond_to?(:config)
diff --git a/railties/test/railties/railtie_test.rb b/railties/test/railties/railtie_test.rb
index 18fdf59fe3..55f85c7202 100644
--- a/railties/test/railties/railtie_test.rb
+++ b/railties/test/railties/railtie_test.rb
@@ -11,6 +11,10 @@ module RailtiesTest
require "rails/all"
end
+ def teardown
+ teardown_app
+ end
+
def app
@app ||= Rails.application
end