aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.travis.yml3
-rw-r--r--Gemfile3
-rw-r--r--Rakefile6
-rw-r--r--actionmailer/CHANGELOG.md5
-rw-r--r--actionmailer/MIT-LICENSE2
-rw-r--r--actionmailer/lib/action_mailer.rb2
-rw-r--r--actionmailer/lib/action_mailer/base.rb4
-rw-r--r--actionmailer/lib/action_mailer/collector.rb2
-rw-r--r--actionmailer/lib/action_mailer/test_case.rb7
-rw-r--r--actionmailer/lib/action_mailer/test_helper.rb12
-rw-r--r--actionmailer/lib/rails/generators/mailer/USAGE5
-rw-r--r--actionmailer/test/abstract_unit.rb2
-rw-r--r--actionmailer/test/spec_type_test.rb37
-rw-r--r--actionmailer/test/test_test.rb144
-rw-r--r--actionpack/CHANGELOG.md138
-rw-r--r--actionpack/MIT-LICENSE2
-rw-r--r--actionpack/README.rdoc2
-rw-r--r--actionpack/actionpack.gemspec2
-rw-r--r--actionpack/lib/abstract_controller/layouts.rb2
-rw-r--r--actionpack/lib/action_controller.rb1
-rw-r--r--actionpack/lib/action_controller/caching.rb14
-rw-r--r--actionpack/lib/action_controller/deprecated/performance_test.rb3
-rw-r--r--actionpack/lib/action_controller/metal/conditional_get.rb2
-rw-r--r--actionpack/lib/action_controller/metal/head.rb1
-rw-r--r--actionpack/lib/action_controller/metal/http_authentication.rb2
-rw-r--r--actionpack/lib/action_controller/metal/mime_responds.rb10
-rw-r--r--actionpack/lib/action_controller/metal/redirecting.rb2
-rw-r--r--actionpack/lib/action_controller/metal/streaming.rb8
-rw-r--r--actionpack/lib/action_controller/metal/strong_parameters.rb7
-rw-r--r--actionpack/lib/action_controller/record_identifier.rb3
-rw-r--r--actionpack/lib/action_controller/test_case.rb7
-rw-r--r--actionpack/lib/action_dispatch.rb3
-rw-r--r--actionpack/lib/action_dispatch/http/filter_parameters.rb1
-rw-r--r--actionpack/lib/action_dispatch/http/parameters.rb2
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb19
-rw-r--r--actionpack/lib/action_dispatch/http/response.rb8
-rw-r--r--actionpack/lib/action_dispatch/http/upload.rb4
-rw-r--r--actionpack/lib/action_dispatch/http/url.rb6
-rw-r--r--actionpack/lib/action_dispatch/journey/formatter.rb9
-rw-r--r--actionpack/lib/action_dispatch/journey/route.rb12
-rw-r--r--actionpack/lib/action_dispatch/journey/routes.rb27
-rw-r--r--actionpack/lib/action_dispatch/middleware/cookies.rb70
-rw-r--r--actionpack/lib/action_dispatch/middleware/debug_exceptions.rb34
-rw-r--r--actionpack/lib/action_dispatch/middleware/exception_wrapper.rb24
-rw-r--r--actionpack/lib/action_dispatch/middleware/flash.rb22
-rw-r--r--actionpack/lib/action_dispatch/middleware/params_parser.rb8
-rw-r--r--actionpack/lib/action_dispatch/middleware/remote_ip.rb166
-rw-r--r--actionpack/lib/action_dispatch/middleware/session/cookie_store.rb40
-rw-r--r--actionpack/lib/action_dispatch/middleware/show_exceptions.rb17
-rw-r--r--actionpack/lib/action_dispatch/middleware/ssl.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/static.rb2
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb21
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/_source.erb25
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb6
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb24
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb125
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/missing_template.erb9
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb49
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.erb52
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb8
-rw-r--r--actionpack/lib/action_dispatch/middleware/templates/routes/_table.html.erb (renamed from actionpack/lib/action_dispatch/middleware/templates/routes/_route_wrapper.html.erb)8
-rw-r--r--actionpack/lib/action_dispatch/routing/inspector.rb84
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb17
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/dom.rb2
-rw-r--r--actionpack/lib/action_dispatch/testing/assertions/routing.rb9
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb3
-rw-r--r--actionpack/lib/action_dispatch/testing/performance_test.rb10
-rw-r--r--actionpack/lib/action_pack.rb2
-rw-r--r--actionpack/lib/action_view.rb2
-rw-r--r--actionpack/lib/action_view/base.rb2
-rw-r--r--actionpack/lib/action_view/digestor.rb21
-rw-r--r--actionpack/lib/action_view/helpers/cache_helper.rb2
-rw-r--r--actionpack/lib/action_view/helpers/debug_helper.rb14
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb70
-rw-r--r--actionpack/lib/action_view/helpers/form_options_helper.rb2
-rw-r--r--actionpack/lib/action_view/helpers/form_tag_helper.rb18
-rw-r--r--actionpack/lib/action_view/helpers/record_tag_helper.rb10
-rw-r--r--actionpack/lib/action_view/helpers/tags/collection_check_boxes.rb8
-rw-r--r--actionpack/lib/action_view/helpers/tags/collection_helpers.rb3
-rw-r--r--actionpack/lib/action_view/helpers/tags/collection_radio_buttons.rb8
-rw-r--r--actionpack/lib/action_view/helpers/text_helper.rb4
-rw-r--r--actionpack/lib/action_view/helpers/url_helper.rb2
-rw-r--r--actionpack/lib/action_view/record_identifier.rb2
-rw-r--r--actionpack/lib/action_view/renderer/partial_renderer.rb2
-rw-r--r--actionpack/lib/action_view/template.rb1
-rw-r--r--actionpack/lib/action_view/template/error.rb20
-rw-r--r--actionpack/lib/action_view/template/resolver.rb2
-rw-r--r--actionpack/lib/action_view/template/types.rb1
-rw-r--r--actionpack/lib/action_view/test_case.rb3
-rw-r--r--actionpack/test/abstract/abstract_controller_test.rb8
-rw-r--r--actionpack/test/abstract/helper_test.rb10
-rw-r--r--actionpack/test/abstract_unit.rb2
-rw-r--r--actionpack/test/controller/action_pack_assertions_test.rb2
-rw-r--r--actionpack/test/controller/caching_test.rb18
-rw-r--r--actionpack/test/controller/filters_test.rb8
-rw-r--r--actionpack/test/controller/http_token_authentication_test.rb6
-rw-r--r--actionpack/test/controller/live_stream_test.rb2
-rw-r--r--actionpack/test/controller/output_escaping_test.rb2
-rw-r--r--actionpack/test/controller/render_test.rb52
-rw-r--r--actionpack/test/controller/request_forgery_protection_test.rb2
-rw-r--r--actionpack/test/controller/routing_test.rb22
-rw-r--r--actionpack/test/controller/spec_style_test.rb208
-rw-r--r--actionpack/test/controller/spec_type_test.rb37
-rw-r--r--actionpack/test/controller/test_case_test.rb2
-rw-r--r--actionpack/test/controller/url_for_test.rb5
-rw-r--r--actionpack/test/controller/webservice_test.rb50
-rw-r--r--actionpack/test/dispatch/debug_exceptions_test.rb24
-rw-r--r--actionpack/test/dispatch/live_response_test.rb2
-rw-r--r--actionpack/test/dispatch/request/json_params_parsing_test.rb22
-rw-r--r--actionpack/test/dispatch/request/query_string_parsing_test.rb4
-rw-r--r--actionpack/test/dispatch/request/session_test.rb2
-rw-r--r--actionpack/test/dispatch/request/xml_params_parsing_test.rb17
-rw-r--r--actionpack/test/dispatch/request_test.rb102
-rw-r--r--actionpack/test/dispatch/routing/inspector_test.rb28
-rw-r--r--actionpack/test/dispatch/session/abstract_store_test.rb2
-rw-r--r--actionpack/test/dispatch/spec_type_test.rb41
-rw-r--r--actionpack/test/dispatch/ssl_test.rb9
-rw-r--r--actionpack/test/fixtures/test/_partial_name_local_variable.erb1
-rw-r--r--actionpack/test/journey/gtg/builder_test.rb2
-rw-r--r--actionpack/test/journey/gtg/transition_table_test.rb6
-rw-r--r--actionpack/test/journey/nfa/simulator_test.rb12
-rw-r--r--actionpack/test/journey/nfa/transition_table_test.rb2
-rw-r--r--actionpack/test/journey/nodes/symbol_test.rb4
-rw-r--r--actionpack/test/journey/path/pattern_test.rb12
-rw-r--r--actionpack/test/journey/route/definition/parser_test.rb2
-rw-r--r--actionpack/test/journey/route/definition/scanner_test.rb2
-rw-r--r--actionpack/test/journey/route_test.rb4
-rw-r--r--actionpack/test/journey/router/strexp_test.rb2
-rw-r--r--actionpack/test/journey/router/utils_test.rb2
-rw-r--r--actionpack/test/journey/router_test.rb4
-rw-r--r--actionpack/test/journey/routes_test.rb6
-rw-r--r--actionpack/test/template/atom_feed_helper_test.rb2
-rw-r--r--actionpack/test/template/digestor_test.rb18
-rw-r--r--actionpack/test/template/form_collections_helper_test.rb6
-rw-r--r--actionpack/test/template/form_helper_test.rb14
-rw-r--r--actionpack/test/template/form_tag_helper_test.rb4
-rw-r--r--actionpack/test/template/record_tag_helper_test.rb30
-rw-r--r--actionpack/test/template/render_test.rb7
-rw-r--r--actionpack/test/template/spec_type_test.rb39
-rw-r--r--actionpack/test/template/test_test.rb56
-rw-r--r--actionpack/test/ts_isolated.rb2
-rw-r--r--activemodel/MIT-LICENSE2
-rw-r--r--activemodel/README.rdoc18
-rw-r--r--activemodel/lib/active_model.rb2
-rw-r--r--activemodel/lib/active_model/attribute_methods.rb2
-rw-r--r--activemodel/lib/active_model/dirty.rb2
-rw-r--r--activemodel/lib/active_model/validations/clusivity.rb2
-rw-r--r--activemodel/lib/active_model/validations/numericality.rb4
-rw-r--r--activemodel/lib/active_model/validations/presence.rb4
-rw-r--r--activemodel/lib/active_model/validator.rb2
-rw-r--r--activemodel/test/cases/helper.rb2
-rw-r--r--activemodel/test/cases/validations/presence_validation_test.rb36
-rw-r--r--activerecord/CHANGELOG.md26
-rw-r--r--activerecord/MIT-LICENSE2
-rw-r--r--activerecord/examples/performance.rb2
-rw-r--r--activerecord/lib/active_record.rb2
-rw-r--r--activerecord/lib/active_record/aggregations.rb4
-rw-r--r--activerecord/lib/active_record/associations.rb18
-rw-r--r--activerecord/lib/active_record/associations/belongs_to_association.rb7
-rw-r--r--activerecord/lib/active_record/associations/collection_proxy.rb4
-rw-r--r--activerecord/lib/active_record/associations/has_many_through_association.rb6
-rw-r--r--activerecord/lib/active_record/associations/has_one_through_association.rb2
-rw-r--r--activerecord/lib/active_record/associations/preloader.rb4
-rw-r--r--activerecord/lib/active_record/associations/preloader/association.rb2
-rw-r--r--activerecord/lib/active_record/attribute_methods/dirty.rb5
-rw-r--r--activerecord/lib/active_record/attribute_methods/primary_key.rb2
-rw-r--r--activerecord/lib/active_record/base.rb50
-rw-r--r--activerecord/lib/active_record/callbacks.rb4
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb1
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_adapter.rb1
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb8
-rw-r--r--activerecord/lib/active_record/connection_adapters/column.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid.rb3
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb76
-rw-r--r--activerecord/lib/active_record/fixtures.rb2
-rw-r--r--activerecord/lib/active_record/inheritance.rb2
-rw-r--r--activerecord/lib/active_record/locking/optimistic.rb2
-rw-r--r--activerecord/lib/active_record/locking/pessimistic.rb2
-rw-r--r--activerecord/lib/active_record/log_subscriber.rb12
-rw-r--r--activerecord/lib/active_record/nested_attributes.rb2
-rw-r--r--activerecord/lib/active_record/persistence.rb16
-rw-r--r--activerecord/lib/active_record/railtie.rb4
-rw-r--r--activerecord/lib/active_record/railties/databases.rake4
-rw-r--r--activerecord/lib/active_record/relation.rb2
-rw-r--r--activerecord/lib/active_record/relation/calculations.rb22
-rw-r--r--activerecord/lib/active_record/relation/delegation.rb1
-rw-r--r--activerecord/lib/active_record/relation/spawn_methods.rb18
-rw-r--r--activerecord/lib/active_record/scoping/named.rb4
-rw-r--r--activerecord/lib/active_record/store.rb6
-rw-r--r--activerecord/lib/active_record/timestamp.rb4
-rw-r--r--activerecord/test/cases/adapters/mysql/active_schema_test.rb2
-rw-r--r--activerecord/test/cases/adapters/mysql/mysql_adapter_test.rb12
-rw-r--r--activerecord/test/cases/adapters/mysql2/schema_test.rb12
-rw-r--r--activerecord/test/cases/adapters/postgresql/datatype_test.rb30
-rw-r--r--activerecord/test/cases/adapters/postgresql/ltree_test.rb41
-rw-r--r--activerecord/test/cases/adapters/postgresql/timestamp_test.rb9
-rw-r--r--activerecord/test/cases/aggregations_test.rb3
-rw-r--r--activerecord/test/cases/ar_schema_test.rb2
-rw-r--r--activerecord/test/cases/associations/belongs_to_associations_test.rb22
-rw-r--r--activerecord/test/cases/associations/eager_test.rb21
-rw-r--r--activerecord/test/cases/associations/has_many_through_associations_test.rb2
-rw-r--r--activerecord/test/cases/associations/join_model_test.rb4
-rw-r--r--activerecord/test/cases/autosave_association_test.rb8
-rw-r--r--activerecord/test/cases/base_test.rb27
-rw-r--r--activerecord/test/cases/calculations_test.rb27
-rw-r--r--activerecord/test/cases/column_test.rb26
-rw-r--r--activerecord/test/cases/connection_adapters/abstract_adapter_test.rb10
-rw-r--r--activerecord/test/cases/connection_specification/resolver_test.rb8
-rw-r--r--activerecord/test/cases/defaults_test.rb2
-rw-r--r--activerecord/test/cases/deprecated_dynamic_methods_test.rb6
-rw-r--r--activerecord/test/cases/dirty_test.rb2
-rw-r--r--activerecord/test/cases/explain_test.rb2
-rw-r--r--activerecord/test/cases/finder_test.rb12
-rw-r--r--activerecord/test/cases/helper.rb3
-rw-r--r--activerecord/test/cases/locking_test.rb2
-rw-r--r--activerecord/test/cases/log_subscriber_test.rb42
-rw-r--r--activerecord/test/cases/migration/change_schema_test.rb18
-rw-r--r--activerecord/test/cases/migration/change_table_test.rb1
-rw-r--r--activerecord/test/cases/migration/column_attributes_test.rb8
-rw-r--r--activerecord/test/cases/migration/index_test.rb6
-rw-r--r--activerecord/test/cases/migration/references_index_test.rb8
-rw-r--r--activerecord/test/cases/migration/references_statements_test.rb16
-rw-r--r--activerecord/test/cases/migration/rename_column_test.rb32
-rw-r--r--activerecord/test/cases/migration_test.rb6
-rw-r--r--activerecord/test/cases/migrator_test.rb9
-rw-r--r--activerecord/test/cases/nested_attributes_test.rb112
-rw-r--r--activerecord/test/cases/persistence_test.rb54
-rw-r--r--activerecord/test/cases/primary_keys_test.rb6
-rw-r--r--activerecord/test/cases/query_cache_test.rb2
-rw-r--r--activerecord/test/cases/relation/where_test.rb4
-rw-r--r--activerecord/test/cases/relation_scoping_test.rb2
-rw-r--r--activerecord/test/cases/relations_test.rb4
-rw-r--r--activerecord/test/cases/schema_dumper_test.rb11
-rw-r--r--activerecord/test/cases/store_test.rb7
-rw-r--r--activerecord/test/cases/transaction_isolation_test.rb2
-rw-r--r--activerecord/test/cases/transactions_test.rb12
-rw-r--r--activerecord/test/models/reference.rb2
-rw-r--r--activerecord/test/models/reply.rb2
-rw-r--r--activerecord/test/schema/postgresql_specific_schema.rb11
-rw-r--r--activesupport/CHANGELOG.md49
-rw-r--r--activesupport/MIT-LICENSE2
-rw-r--r--activesupport/lib/active_support.rb2
-rw-r--r--activesupport/lib/active_support/backtrace_cleaner.rb3
-rw-r--r--activesupport/lib/active_support/cache.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/array/access.rb8
-rw-r--r--activesupport/lib/active_support/core_ext/array/conversions.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/class/attribute.rb3
-rw-r--r--activesupport/lib/active_support/core_ext/date.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/date/calculations.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/date/infinite_comparable.rb5
-rw-r--r--activesupport/lib/active_support/core_ext/date_time.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/date_time/calculations.rb7
-rw-r--r--activesupport/lib/active_support/core_ext/date_time/infinite_comparable.rb5
-rw-r--r--activesupport/lib/active_support/core_ext/exception.rb3
-rw-r--r--activesupport/lib/active_support/core_ext/hash/conversions.rb27
-rw-r--r--activesupport/lib/active_support/core_ext/hash/except.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/infinite_comparable.rb35
-rw-r--r--activesupport/lib/active_support/core_ext/kernel/reporting.rb7
-rw-r--r--activesupport/lib/active_support/core_ext/marshal.rb24
-rw-r--r--activesupport/lib/active_support/core_ext/numeric.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/numeric/infinite_comparable.rb9
-rw-r--r--activesupport/lib/active_support/core_ext/object/acts_like.rb8
-rw-r--r--activesupport/lib/active_support/core_ext/object/instance_variables.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/string/conversions.rb6
-rw-r--r--activesupport/lib/active_support/core_ext/time.rb1
-rw-r--r--activesupport/lib/active_support/core_ext/time/infinite_comparable.rb5
-rw-r--r--activesupport/lib/active_support/core_ext/time/zones.rb2
-rw-r--r--activesupport/lib/active_support/dependencies/autoload.rb2
-rw-r--r--activesupport/lib/active_support/inflector/methods.rb14
-rw-r--r--activesupport/lib/active_support/json/encoding.rb2
-rw-r--r--activesupport/lib/active_support/log_subscriber.rb4
-rw-r--r--activesupport/lib/active_support/log_subscriber/test_helper.rb2
-rw-r--r--activesupport/lib/active_support/notifications/instrumenter.rb23
-rw-r--r--activesupport/lib/active_support/railtie.rb30
-rw-r--r--activesupport/lib/active_support/test_case.rb42
-rw-r--r--activesupport/lib/active_support/testing/assertions.rb18
-rw-r--r--activesupport/lib/active_support/testing/autorun.rb5
-rw-r--r--activesupport/lib/active_support/testing/declarative.rb40
-rw-r--r--activesupport/lib/active_support/testing/isolation.rb12
-rw-r--r--activesupport/lib/active_support/testing/performance.rb271
-rw-r--r--activesupport/lib/active_support/testing/performance/jruby.rb115
-rw-r--r--activesupport/lib/active_support/testing/performance/rubinius.rb113
-rw-r--r--activesupport/lib/active_support/testing/performance/ruby.rb173
-rw-r--r--activesupport/lib/active_support/testing/tagged_logging.rb21
-rw-r--r--activesupport/lib/active_support/time_with_zone.rb35
-rw-r--r--activesupport/test/abstract_unit.rb2
-rw-r--r--activesupport/test/caching_test.rb6
-rw-r--r--activesupport/test/core_ext/date_ext_test.rb5
-rw-r--r--activesupport/test/core_ext/date_time_ext_test.rb7
-rw-r--r--activesupport/test/core_ext/duration_test.rb14
-rw-r--r--activesupport/test/core_ext/hash_ext_test.rb30
-rw-r--r--activesupport/test/core_ext/numeric_ext_test.rb74
-rw-r--r--activesupport/test/core_ext/range_ext_test.rb25
-rw-r--r--activesupport/test/core_ext/string_ext_test.rb1
-rw-r--r--activesupport/test/core_ext/thread_test.rb4
-rw-r--r--activesupport/test/core_ext/time_ext_test.rb7
-rw-r--r--activesupport/test/core_ext/time_with_zone_test.rb10
-rw-r--r--activesupport/test/dependencies_test.rb10
-rw-r--r--activesupport/test/deprecation_test.rb7
-rw-r--r--activesupport/test/inflector_test.rb2
-rw-r--r--activesupport/test/json/encoding_test.rb3
-rw-r--r--activesupport/test/message_encryptor_test.rb4
-rw-r--r--activesupport/test/notifications/instrumenter_test.rb50
-rw-r--r--activesupport/test/spec_type_test.rb22
-rw-r--r--activesupport/test/string_inquirer_test.rb2
-rw-r--r--activesupport/test/test_test.rb50
-rw-r--r--activesupport/test/testing/performance_test.rb68
-rw-r--r--activesupport/test/ts_isolated.rb2
-rw-r--r--activesupport/test/xml_mini/libxml_engine_test.rb7
-rw-r--r--activesupport/test/xml_mini/libxmlsax_engine_test.rb7
-rw-r--r--activesupport/test/xml_mini/nokogiri_engine_test.rb7
-rw-r--r--activesupport/test/xml_mini/nokogirisax_engine_test.rb7
-rw-r--r--guides/assets/stylesheets/main.css6
-rw-r--r--guides/code/getting_started/README.rdoc263
-rw-r--r--guides/code/getting_started/app/controllers/posts_controller.rb2
-rw-r--r--guides/code/getting_started/doc/README_FOR_APP2
-rw-r--r--guides/code/getting_started/test/performance/browsing_test.rb12
-rw-r--r--guides/rails_guides/markdown.rb4
-rw-r--r--guides/source/4_0_release_notes.md6
-rw-r--r--guides/source/action_controller_overview.md12
-rw-r--r--guides/source/action_mailer_basics.md2
-rw-r--r--guides/source/active_record_basics.md10
-rw-r--r--guides/source/active_record_callbacks.md7
-rw-r--r--guides/source/active_record_querying.md4
-rw-r--r--guides/source/active_record_validations.md10
-rw-r--r--guides/source/active_support_core_extensions.md31
-rw-r--r--guides/source/active_support_instrumentation.md2
-rw-r--r--guides/source/asset_pipeline.md26
-rw-r--r--guides/source/caching_with_rails.md96
-rw-r--r--guides/source/command_line.md46
-rw-r--r--guides/source/configuring.md7
-rw-r--r--guides/source/contributing_to_ruby_on_rails.md6
-rw-r--r--guides/source/credits.html.erb2
-rw-r--r--guides/source/debugging_rails_applications.md8
-rw-r--r--guides/source/documents.yaml4
-rw-r--r--guides/source/engines.md34
-rw-r--r--guides/source/form_helpers.md24
-rw-r--r--guides/source/generators.md18
-rw-r--r--guides/source/getting_started.md29
-rw-r--r--guides/source/i18n.md4
-rw-r--r--guides/source/initialization.md124
-rw-r--r--guides/source/layouts_and_rendering.md10
-rw-r--r--guides/source/migrations.md25
-rw-r--r--guides/source/nested_model_forms.md2
-rw-r--r--guides/source/performance_testing.md686
-rw-r--r--guides/source/rails_application_templates.md7
-rw-r--r--guides/source/rails_on_rack.md6
-rw-r--r--guides/source/security.md2
-rw-r--r--guides/source/testing.md10
-rw-r--r--guides/source/working_with_javascript_in_rails.md66
-rw-r--r--install.rb9
-rw-r--r--rails.gemspec2
-rw-r--r--railties/CHANGELOG.md47
-rw-r--r--railties/MIT-LICENSE2
-rw-r--r--railties/lib/rails/app_rails_loader.rb29
-rw-r--r--railties/lib/rails/application.rb7
-rw-r--r--railties/lib/rails/application/configuration.rb4
-rw-r--r--railties/lib/rails/cli.rb7
-rw-r--r--railties/lib/rails/commands.rb13
-rw-r--r--railties/lib/rails/commands/benchmarker.rb34
-rw-r--r--railties/lib/rails/commands/console.rb24
-rw-r--r--railties/lib/rails/commands/dbconsole.rb10
-rw-r--r--railties/lib/rails/commands/profiler.rb32
-rw-r--r--railties/lib/rails/commands/runner.rb2
-rw-r--r--railties/lib/rails/engine.rb6
-rw-r--r--railties/lib/rails/generators.rb2
-rw-r--r--railties/lib/rails/generators/actions.rb6
-rw-r--r--railties/lib/rails/generators/active_model.rb4
-rw-r--r--railties/lib/rails/generators/app_base.rb11
-rw-r--r--railties/lib/rails/generators/erb/scaffold/templates/index.html.erb12
-rw-r--r--railties/lib/rails/generators/rails/app/app_generator.rb35
-rw-r--r--railties/lib/rails/generators/rails/app/templates/Gemfile6
-rw-r--r--railties/lib/rails/generators/rails/app/templates/README259
-rw-r--r--railties/lib/rails/generators/rails/app/templates/README.rdoc28
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/mailers/.empty_directory0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/app/models/.empty_directory0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/bin/bundle3
-rw-r--r--railties/lib/rails/generators/rails/app/templates/bin/rails3
-rw-r--r--railties/lib/rails/generators/rails/app/templates/bin/rake3
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/application.rb17
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml6
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt3
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb4
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/initializers/inflections.rb2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/initializers/locale.rb2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/config/initializers/wrap_parameters.rb.tt2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/doc/README_FOR_APP2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/gitignore2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/public/stylesheets/.empty_directory0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/script/rails5
-rw-r--r--railties/lib/rails/generators/rails/app/templates/test/fixtures/.empty_directory0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/test/functional/.empty_directory0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/test/integration/.empty_directory0
-rw-r--r--railties/lib/rails/generators/rails/app/templates/test/performance/browsing_test.rb12
-rw-r--r--railties/lib/rails/generators/rails/app/templates/test/unit/.empty_directory0
-rw-r--r--railties/lib/rails/generators/rails/controller/USAGE2
-rw-r--r--railties/lib/rails/generators/rails/migration/USAGE13
-rw-r--r--railties/lib/rails/generators/rails/model/USAGE14
-rw-r--r--railties/lib/rails/generators/rails/performance_test/USAGE10
-rw-r--r--railties/lib/rails/generators/rails/performance_test/performance_test_generator.rb7
-rw-r--r--railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb32
-rw-r--r--railties/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec2
-rw-r--r--railties/lib/rails/generators/rails/plugin_new/templates/Gemfile2
-rw-r--r--railties/lib/rails/generators/rails/plugin_new/templates/Rakefile2
-rw-r--r--railties/lib/rails/generators/rails/plugin_new/templates/bin/rails.tt (renamed from railties/lib/rails/generators/rails/plugin_new/templates/script/rails.tt)0
-rw-r--r--railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb2
-rw-r--r--railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb7
-rw-r--r--railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb9
-rw-r--r--railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb72
-rw-r--r--railties/lib/rails/generators/test_unit/performance/performance_generator.rb13
-rw-r--r--railties/lib/rails/generators/test_unit/performance/templates/performance_test.rb12
-rw-r--r--railties/lib/rails/generators/test_unit/plugin/templates/test_helper.rb2
-rw-r--r--railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb2
-rw-r--r--railties/lib/rails/info_controller.rb6
-rw-r--r--railties/lib/rails/paths.rb12
-rw-r--r--railties/lib/rails/performance_test_help.rb3
-rw-r--r--railties/lib/rails/rack/logger.rb41
-rw-r--r--railties/lib/rails/railtie.rb2
-rw-r--r--railties/lib/rails/script_rails_loader.rb29
-rw-r--r--railties/lib/rails/source_annotation_extractor.rb10
-rw-r--r--railties/lib/rails/tasks/documentation.rake7
-rw-r--r--railties/lib/rails/tasks/framework.rake10
-rw-r--r--railties/lib/rails/tasks/routes.rake4
-rw-r--r--railties/lib/rails/templates/layouts/application.html.erb4
-rw-r--r--railties/lib/rails/templates/rails/info/routes.html.erb5
-rw-r--r--railties/lib/rails/templates/rails/welcome/index.html.erb25
-rw-r--r--railties/lib/rails/test_help.rb12
-rw-r--r--railties/lib/rails/test_unit/railtie.rb1
-rw-r--r--railties/lib/rails/test_unit/testing.rake13
-rw-r--r--railties/test/abstract_unit.rb2
-rw-r--r--railties/test/app_rails_loader_test.rb41
-rw-r--r--railties/test/application/assets_test.rb2
-rw-r--r--railties/test/application/configuration_test.rb22
-rw-r--r--railties/test/application/generators_test.rb2
-rw-r--r--railties/test/application/middleware/remote_ip_test.rb2
-rw-r--r--railties/test/application/rake/notes_test.rb8
-rw-r--r--railties/test/application/test_test.rb25
-rw-r--r--railties/test/commands/console_test.rb6
-rw-r--r--railties/test/commands/dbconsole_test.rb12
-rw-r--r--railties/test/configuration/middleware_stack_proxy_test.rb3
-rw-r--r--railties/test/engine_test.rb2
-rw-r--r--railties/test/fixtures/path/ruby-local-exec0
-rw-r--r--railties/test/generators/actions_test.rb6
-rw-r--r--railties/test/generators/app_generator_test.rb12
-rw-r--r--railties/test/generators/performance_test_generator_test.rb12
-rw-r--r--railties/test/generators/plugin_new_generator_test.rb12
-rw-r--r--railties/test/generators/scaffold_controller_generator_test.rb22
-rw-r--r--railties/test/generators/scaffold_generator_test.rb17
-rw-r--r--railties/test/generators/shared_generator_tests.rb22
-rw-r--r--railties/test/isolation/abstract_unit.rb4
-rw-r--r--railties/test/rack_logger_test.rb71
-rw-r--r--railties/test/railties/engine_test.rb2
-rw-r--r--railties/test/script_rails_loader_test.rb22
455 files changed, 3286 insertions, 4861 deletions
diff --git a/.travis.yml b/.travis.yml
index 18b0100c62..ba5526c009 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -24,6 +24,3 @@ notifications:
rooms:
- secure: "YA1alef1ESHWGFNVwvmVGCkMe4cUy4j+UcNvMUESraceiAfVyRMAovlQBGs6\n9kBRm7DHYBUXYC2ABQoJbQRLDr/1B5JPf/M8+Qd7BKu8tcDC03U01SMHFLpO\naOs/HLXcDxtnnpL07tGVsm0zhMc5N8tq4/L3SHxK7Vi+TacwQzI="
bundler_args: --path vendor/bundle
-matrix:
- allow_failures:
- - rvm: 2.0.0
diff --git a/Gemfile b/Gemfile
index 94a0d15d16..73ac0172ae 100644
--- a/Gemfile
+++ b/Gemfile
@@ -12,7 +12,8 @@ gem 'jquery-rails', '~> 2.1.4', github: 'rails/jquery-rails'
gem 'turbolinks'
gem 'coffee-rails', github: 'rails/coffee-rails'
-gem 'thread_safe', '~> 0.1'
+# TODO: Release thor
+gem 'thor', github: 'wycats/thor', branch: 'master'
gem 'activerecord-deprecated_finders', github: 'rails/activerecord-deprecated_finders', branch: 'master'
diff --git a/Rakefile b/Rakefile
index 1caa69cf92..490627d22c 100644
--- a/Rakefile
+++ b/Rakefile
@@ -40,10 +40,10 @@ task :install => :gem do
version = File.read("RAILS_VERSION").strip
(PROJECTS - ["railties"]).each do |project|
puts "INSTALLING #{project}"
- system("gem install #{project}/pkg/#{project}-#{version}.gem --no-ri --no-rdoc")
+ system("gem install #{project}/pkg/#{project}-#{version}.gem --local --no-ri --no-rdoc")
end
- system("gem install railties/pkg/railties-#{version}.gem --no-ri --no-rdoc")
- system("gem install pkg/rails-#{version}.gem --no-ri --no-rdoc")
+ system("gem install railties/pkg/railties-#{version}.gem --local --no-ri --no-rdoc")
+ system("gem install pkg/rails-#{version}.gem --local --no-ri --no-rdoc")
end
desc "Generate documentation for the Rails framework"
diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md
index 9feca324a3..43bfa536c1 100644
--- a/actionmailer/CHANGELOG.md
+++ b/actionmailer/CHANGELOG.md
@@ -1,5 +1,10 @@
## Rails 4.0.0 (unreleased) ##
+* Eager loading made to use relation's in_clause_length instead of host's one.
+ Fix #8474
+
+ *Boris Staal*
+
* Explicit multipart messages no longer set the order of the MIME parts.
*Nate Berkopec*
diff --git a/actionmailer/MIT-LICENSE b/actionmailer/MIT-LICENSE
index 810daf856c..5c668d9624 100644
--- a/actionmailer/MIT-LICENSE
+++ b/actionmailer/MIT-LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2012 David Heinemeier Hansson
+Copyright (c) 2004-2013 David Heinemeier Hansson
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/actionmailer/lib/action_mailer.rb b/actionmailer/lib/action_mailer.rb
index cfbe2f1cbd..c45124be80 100644
--- a/actionmailer/lib/action_mailer.rb
+++ b/actionmailer/lib/action_mailer.rb
@@ -1,5 +1,5 @@
#--
-# Copyright (c) 2004-2012 David Heinemeier Hansson
+# Copyright (c) 2004-2013 David Heinemeier Hansson
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index a3c0b2c6bd..9ba606c045 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -530,7 +530,7 @@ module ActionMailer
# The resulting Mail::Message will have the following in its header:
#
# X-Special-Domain-Specific-Header: SecretValue
- def headers(args=nil)
+ def headers(args = nil)
if args
@_message.headers(args)
else
@@ -660,7 +660,7 @@ module ActionMailer
# format.html
# end
#
- def mail(headers={}, &block)
+ def mail(headers = {}, &block)
@_mail_was_called = true
m = @_message
diff --git a/actionmailer/lib/action_mailer/collector.rb b/actionmailer/lib/action_mailer/collector.rb
index cbb2778fae..e8883a8235 100644
--- a/actionmailer/lib/action_mailer/collector.rb
+++ b/actionmailer/lib/action_mailer/collector.rb
@@ -20,7 +20,7 @@ module ActionMailer
end
alias :all :any
- def custom(mime, options={})
+ def custom(mime, options = {})
options.reverse_merge!(content_type: mime.to_s)
@context.formats = [mime.to_sym]
options[:body] = block_given? ? yield : @default_render.call
diff --git a/actionmailer/lib/action_mailer/test_case.rb b/actionmailer/lib/action_mailer/test_case.rb
index 80f323873d..207f949fe2 100644
--- a/actionmailer/lib/action_mailer/test_case.rb
+++ b/actionmailer/lib/action_mailer/test_case.rb
@@ -10,13 +10,6 @@ module ActionMailer
end
class TestCase < ActiveSupport::TestCase
-
- # Use AM::TestCase for the base class when describing a mailer
- register_spec_type(self) do |desc|
- Class === desc && desc < ActionMailer::Base
- end
- register_spec_type(/Mailer( ?Test)?\z/i, self)
-
module Behavior
extend ActiveSupport::Concern
diff --git a/actionmailer/lib/action_mailer/test_helper.rb b/actionmailer/lib/action_mailer/test_helper.rb
index 3ab37d8142..6452bf616c 100644
--- a/actionmailer/lib/action_mailer/test_helper.rb
+++ b/actionmailer/lib/action_mailer/test_helper.rb
@@ -4,9 +4,9 @@ module ActionMailer
#
# def test_emails
# assert_emails 0
- # ContactMailer.deliver_contact
+ # ContactMailer.welcome.deliver
# assert_emails 1
- # ContactMailer.deliver_contact
+ # ContactMailer.welcome.deliver
# assert_emails 2
# end
#
@@ -15,12 +15,12 @@ module ActionMailer
#
# def test_emails_again
# assert_emails 1 do
- # ContactMailer.deliver_contact
+ # ContactMailer.welcome.deliver
# end
#
# assert_emails 2 do
- # ContactMailer.deliver_contact
- # ContactMailer.deliver_contact
+ # ContactMailer.welcome.deliver
+ # ContactMailer.welcome.deliver
# end
# end
def assert_emails(number)
@@ -38,7 +38,7 @@ module ActionMailer
#
# def test_emails
# assert_no_emails
- # ContactMailer.deliver_contact
+ # ContactMailer.welcome.deliver
# assert_emails 1
# end
#
diff --git a/actionmailer/lib/rails/generators/mailer/USAGE b/actionmailer/lib/rails/generators/mailer/USAGE
index 7470289fd3..323bb8a87f 100644
--- a/actionmailer/lib/rails/generators/mailer/USAGE
+++ b/actionmailer/lib/rails/generators/mailer/USAGE
@@ -10,9 +10,8 @@ Example:
========
rails generate mailer Notifications signup forgot_password invoice
- creates a Notifications mailer class, views, test, and fixtures:
+ creates a Notifications mailer class, views, and test:
Mailer: app/mailers/notifications.rb
- Views: app/views/notifications/signup.erb [...]
+ Views: app/views/notifications/signup.text.erb [...]
Test: test/mailers/notifications_test.rb
- Fixtures: test/fixtures/notifications/signup [...]
diff --git a/actionmailer/test/abstract_unit.rb b/actionmailer/test/abstract_unit.rb
index 99c44179fd..15729bafba 100644
--- a/actionmailer/test/abstract_unit.rb
+++ b/actionmailer/test/abstract_unit.rb
@@ -8,7 +8,7 @@ silence_warnings do
Encoding.default_external = "UTF-8"
end
-require 'minitest/autorun'
+require 'active_support/testing/autorun'
require 'action_mailer'
require 'action_mailer/test_case'
diff --git a/actionmailer/test/spec_type_test.rb b/actionmailer/test/spec_type_test.rb
deleted file mode 100644
index 90db59c2d2..0000000000
--- a/actionmailer/test/spec_type_test.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-require 'abstract_unit'
-
-class NotificationMailer < ActionMailer::Base; end
-class Notifications < ActionMailer::Base; end
-
-class SpecTypeTest < ActiveSupport::TestCase
- def assert_mailer actual
- assert_equal ActionMailer::TestCase, actual
- end
-
- def refute_mailer actual
- refute_equal ActionMailer::TestCase, actual
- end
-
- def test_spec_type_resolves_for_class_constants
- assert_mailer MiniTest::Spec.spec_type(NotificationMailer)
- assert_mailer MiniTest::Spec.spec_type(Notifications)
- end
-
- def test_spec_type_resolves_for_matching_strings
- assert_mailer MiniTest::Spec.spec_type("WidgetMailer")
- assert_mailer MiniTest::Spec.spec_type("WidgetMailerTest")
- assert_mailer MiniTest::Spec.spec_type("Widget Mailer Test")
- # And is not case sensitive
- assert_mailer MiniTest::Spec.spec_type("widgetmailer")
- assert_mailer MiniTest::Spec.spec_type("widgetmailertest")
- assert_mailer MiniTest::Spec.spec_type("widget mailer test")
- end
-
- def test_spec_type_wont_match_non_space_characters
- refute_mailer MiniTest::Spec.spec_type("Widget Mailer\tTest")
- refute_mailer MiniTest::Spec.spec_type("Widget Mailer\rTest")
- refute_mailer MiniTest::Spec.spec_type("Widget Mailer\nTest")
- refute_mailer MiniTest::Spec.spec_type("Widget Mailer\fTest")
- refute_mailer MiniTest::Spec.spec_type("Widget MailerXTest")
- end
-end
diff --git a/actionmailer/test/test_test.rb b/actionmailer/test/test_test.rb
index 139eb53359..86fd37bea6 100644
--- a/actionmailer/test/test_test.rb
+++ b/actionmailer/test/test_test.rb
@@ -26,147 +26,3 @@ class CrazyStringNameMailerTest < ActionMailer::TestCase
assert_equal TestTestMailer, self.class.mailer_class
end
end
-
-describe TestTestMailer do
- it "gets the mailer from the test name" do
- assert_equal TestTestMailer, self.class.mailer_class
- end
-end
-
-describe TestTestMailer, :action do
- it "gets the mailer from the test name" do
- assert_equal TestTestMailer, self.class.mailer_class
- end
-end
-
-describe TestTestMailer do
- describe "nested" do
- it "gets the mailer from the test name" do
- assert_equal TestTestMailer, self.class.mailer_class
- end
- end
-end
-
-describe TestTestMailer, :action do
- describe "nested" do
- it "gets the mailer from the test name" do
- assert_equal TestTestMailer, self.class.mailer_class
- end
- end
-end
-
-describe "TestTestMailer" do
- it "gets the mailer from the test name" do
- assert_equal TestTestMailer, self.class.mailer_class
- end
-end
-
-describe "TestTestMailerTest" do
- it "gets the mailer from the test name" do
- assert_equal TestTestMailer, self.class.mailer_class
- end
-end
-
-describe "TestTestMailer" do
- describe "nested" do
- it "gets the mailer from the test name" do
- assert_equal TestTestMailer, self.class.mailer_class
- end
- end
-end
-
-describe "TestTestMailerTest" do
- describe "nested" do
- it "gets the mailer from the test name" do
- assert_equal TestTestMailer, self.class.mailer_class
- end
- end
-end
-
-describe "AnotherCrazySymbolNameMailerTest" do
- tests :test_test_mailer
-
- it "gets the mailer after setting it with a symbol" do
- assert_equal TestTestMailer, self.class.mailer_class
- end
-end
-
-describe "AnotherCrazyStringNameMailerTest" do
- tests 'test_test_mailer'
-
- it "gets the mailer after setting it with a string" do
- assert_equal TestTestMailer, self.class.mailer_class
- end
-end
-
-describe "Another Crazy Name Mailer Test" do
- tests TestTestMailer
-
- it "gets the mailer after setting it manually" do
- assert_equal TestTestMailer, self.class.mailer_class
- end
-end
-
-describe "Another Crazy Symbol Name Mailer Test" do
- tests :test_test_mailer
-
- it "gets the mailer after setting it with a symbol" do
- assert_equal TestTestMailer, self.class.mailer_class
- end
-end
-
-describe "Another Crazy String Name Mailer Test" do
- tests 'test_test_mailer'
-
- it "gets the mailer after setting it with a string" do
- assert_equal TestTestMailer, self.class.mailer_class
- end
-end
-
-describe "AnotherCrazySymbolNameMailerTest" do
- tests :test_test_mailer
-
- describe "nested" do
- it "gets the mailer after setting it with a symbol" do
- assert_equal TestTestMailer, self.class.mailer_class
- end
- end
-end
-
-describe "AnotherCrazyStringNameMailerTest" do
- tests 'test_test_mailer'
-
- describe "nested" do
- it "gets the mailer after setting it with a string" do
- assert_equal TestTestMailer, self.class.mailer_class
- end
- end
-end
-
-describe "Another Crazy Name Mailer Test" do
- tests TestTestMailer
-
- describe "nested" do
- it "gets the mailer after setting it manually" do
- assert_equal TestTestMailer, self.class.mailer_class
- end
- end
-end
-
-describe "Another Crazy Symbol Name Mailer Test" do
- tests :test_test_mailer
-
- describe "nested" do
- it "gets the mailer after setting it with a symbol" do
- assert_equal TestTestMailer, self.class.mailer_class
- end
- end
-end
-
-describe "Another Crazy String Name Mailer Test" do
- tests 'test_test_mailer'
-
- it "gets the mailer after setting it with a string" do
- assert_equal TestTestMailer, self.class.mailer_class
- end
-end
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 57b8b5dfc9..2cb7af05e5 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,5 +1,72 @@
## Rails 4.0.0 (unreleased) ##
+* Fixed json params parsing regression for non-object JSON content.
+
+ *Dylan Smith*
+
+* Extract `ActionDispatch::PerformanceTest` into https://github.com/rails/rails-perftest
+ You can add the gem to your Gemfile to keep using performance tests.
+
+ gem 'rails-perftest'
+
+ *Yves Senn*
+
+* Added view_cache_dependency API for declaring dependencies that affect
+ cache digest computation.
+
+ *Jamis Buck*
+
+* `image_submit_tag` will set `alt` attribute from image source if not
+ specified.
+
+ *Nihad Abbasov*
+
+* Do not generate local variables for partials without object or collection.
+ Previously rendering a partial without giving `:object` or `:collection`
+ would generate a local variable with the partial name by default.
+
+ *Carlos Antonio da Silva*
+
+* Return the last valid, non-private IP address from the X-Forwarded-For,
+ Client-IP and Remote-Addr headers, in that order. Document the rationale
+ for that decision, and describe the options that can be passed to the
+ RemoteIp middleware to change it.
+ Fix #7979
+
+ *André Arko*, *Steve Klabnik*, *Alexey Gaziev*
+
+* Do not append second slash to `root_url` when using `trailing_slash: true`
+ Fix #8700
+
+ Example:
+ # before
+ root_url # => http://test.host//
+
+ # after
+ root_url # => http://test.host/
+
+ *Yves Senn*
+
+* Allow to toggle dumps on error pages.
+
+ *Gosha Arinich*
+
+* Fix a bug in `content_tag_for` that prevents it from working without a block.
+
+ *Jasl*
+
+* Change the stylesheet of exception pages for development mode.
+ Additionally display also the line of code and fragment that raised
+ the exception in all exceptions pages.
+
+ *Guillermo Iguaran + Jorge Cuadrado*
+
+* Do not append `charset=` parameter when `head` is called with a
+ `:content_type` option.
+ Fix #8661.
+
+ *Yves Senn*
+
* Added `Mime::NullType` class. This allows to use html?, xml?, json?..etc when
the `format` of `request` is unknown, without raise an exception.
@@ -105,7 +172,7 @@
*Drew Ulmer*
-* No sort Hash options in `grouped_options_for_select`. *Sergey Kojin*
+* Do not sort Hash options in `grouped_options_for_select`. *Sergey Kojin*
* Accept symbols as `send_data :disposition` value *Elia Schito*
@@ -153,14 +220,15 @@
* Render every partial with a new `ActionView::PartialRenderer`. This resolves
issues when rendering nested partials.
- Fix #8197
+ Fix #8197.
*Yves Senn*
* Introduce `ActionView::Template::Handlers::ERB.escape_whitelist`. This is a list
of mime types where template text is not html escaped by default. It prevents `Jack & Joe`
from rendering as `Jack &amp; Joe` for the whitelisted mime types. The default whitelist
- contains text/plain. Fix #7976
+ contains `text/plain`.
+ Fix #7976.
*Joost Baaij*
@@ -176,12 +244,13 @@
check_box("post", "comment_ids", { multiple: true, index: "foo" }, 1)
#=> <input name=\"post[foo][comment_ids][]\" type=\"hidden\" value=\"0\" /><input id=\"post_foo_comment_ids_1\" name=\"post[foo][comment_ids][]\" type=\"checkbox\" value=\"1\" />
- Fix #8108
+ Fix #8108.
*Daniel Fox, Grant Hutchins & Trace Wax*
* `BestStandardsSupport` middleware now appends it's `X-UA-Compatible` value to app's
- returned value if any. Fix #8086
+ returned value if any.
+ Fix #8086.
*Nikita Afanasenko*
@@ -190,21 +259,21 @@
*Pavel Nikitin*
-* Only non-js/css under app/assets path will be included in default config.assets.precompile.
+* Only non-js/css under `app/assets` path will be included in default `config.assets.precompile`.
*Josh Peek*
-* Remove support for the RAILS_ASSET_ID environment configuration
+* Remove support for the `RAILS_ASSET_ID` environment configuration
(no longer needed now that we have the asset pipeline).
*Josh Peek*
-* Remove old asset_path configuration (no longer needed now that we have the asset pipeline).
+* Remove old `asset_path` configuration (no longer needed now that we have the asset pipeline).
*Josh Peek*
* `assert_template` can be used to assert on the same template with different locals
- Fix #3675
+ Fix #3675.
*Yves Senn*
@@ -212,10 +281,10 @@
*Josh Peek*
-* Accept :remote as symbolic option for `link_to` helper. *Riley Lynch*
+* Accept `:remote` as symbolic option for `link_to` helper. *Riley Lynch*
* Warn when the `:locals` option is passed to `assert_template` outside of a view test case
- Fix #3415
+ Fix #3415.
*Yves Senn*
@@ -235,24 +304,24 @@
*Francesco Rodriguez*
-* Failsafe exception returns text/plain. *Steve Klabnik*
+* Failsafe exception returns `text/plain`. *Steve Klabnik*
* Remove `rack-cache` dependency from Action Pack and declare it on Gemfile
*Guillermo Iguaran*
-* Rename internal variables on ActionController::TemplateAssertions to prevent
- naming collisions. @partials, @templates and @layouts are now prefixed with an underscore.
- Fix #7459
+* Rename internal variables on `ActionController::TemplateAssertions` to prevent
+ naming collisions. `@partials`, `@templates` and `@layouts` are now prefixed with an underscore.
+ Fix #7459.
*Yves Senn*
-* `resource` and `resources` don't modify the passed options hash
- Fix #7777
+* `resource` and `resources` don't modify the passed options hash.
+ Fix #7777.
*Yves Senn*
-* Precompiled assets include aliases from foo.js to foo/index.js and vice versa.
+* Precompiled assets include aliases from `foo.js` to `foo/index.js` and vice versa.
# Precompiles phone-<digest>.css and aliases phone/index.css to phone.css.
config.assets.precompile = [ 'phone.css' ]
@@ -290,8 +359,8 @@
*Nihad Abbasov*
-* Deprecate Mime::Type#verify_request? and Mime::Type.browser_generated_types,
- since they are no longer used inside of Rails, they will be removed in Rails 4.1
+* Deprecate `Mime::Type#verify_request?` and `Mime::Type.browser_generated_types`,
+ since they are no longer used inside of Rails, they will be removed in Rails 4.1.
*Michael Grosser*
@@ -307,11 +376,12 @@
* Remove Integration between `attr_accessible`/`attr_protected` and
`ActionController::ParamsWrapper`. ParamWrapper now wraps all the parameters returned
- by the class method attribute_names
+ by the class method `attribute_names`.
*Guillermo Iguaran*
-* Fix #7646, the log now displays the correct status code when an exception is raised.
+* Log now displays the correct status code when an exception is raised.
+ Fix #7646.
*Yves Senn*
@@ -349,7 +419,7 @@
*Sergey Nartimov*
-* Add .ruby template handler, this handler simply allows arbitrary Ruby code as a template. *Guillermo Iguaran*
+* Add `.ruby` template handler, this handler simply allows arbitrary Ruby code as a template. *Guillermo Iguaran*
* Add `separator` option for `ActionView::Helpers::TextHelper#excerpt`:
@@ -370,7 +440,7 @@
end
end
-* Add automatic template digests to all `CacheHelper#cache` calls (originally spiked in the cache_digests plugin) *DHH*
+* Add automatic template digests to all `CacheHelper#cache` calls (originally spiked in the `cache_digests` plugin) *DHH*
* When building a URL fails, add missing keys provided by Journey. Failed URL
generation now returns a 500 status instead of a 404.
@@ -464,7 +534,7 @@
*Egor Homakov*
-* Allow data attributes to be set as a first-level option for form_for, so you can write `form_for @record, data: { behavior: 'autosave' }` instead of `form_for @record, html: { data: { behavior: 'autosave' } }` *DHH*
+* Allow data attributes to be set as a first-level option for `form_for`, so you can write `form_for @record, data: { behavior: 'autosave' }` instead of `form_for @record, html: { data: { behavior: 'autosave' } }` *DHH*
* Deprecate `button_to_function` and `link_to_function` helpers.
@@ -520,7 +590,9 @@
*Carlos Galdino + Rafael Mendonça França*
-* Show routes in exception page while debugging a `RoutingError` in development. *Richard Schneeman and Mattt Thompson*
+* Show routes in exception page while debugging a `RoutingError` in development.
+
+ *Richard Schneeman + Mattt Thompson + Yves Senn*
* Add `ActionController::Flash.add_flash_types` method to allow people to register their own flash types. e.g.:
@@ -570,7 +642,7 @@
*Sergey Nartimov*
-* change a way of ordering helpers from several directories. Previously,
+* Change a way of ordering helpers from several directories. Previously,
when loading helpers from multiple paths, all of the helpers files were
gathered into one array an then they were sorted. Helpers from different
directories should not be mixed before loading them to make loading more
@@ -606,7 +678,7 @@
* Add `time_field` and `time_field_tag` helpers which render an `input[type="time"]` tag. *Alex Soulim*
-* Removed old text_helper apis for highlight, excerpt and word_wrap *Jeremy Walker*
+* Removed old text helper apis from `highlight`, `excerpt` and `word_wrap`. *Jeremy Walker*
* Templates without a handler extension now raises a deprecation warning but still
defaults to ERb. In future releases, it will simply return the template contents. *Steve Klabnik*
@@ -617,7 +689,7 @@
* Remove `:mouseover` option from `image_tag` helper. *Rafael Mendonça França*
-* The `select` method (select tag) forces :include_blank if `required` is true and
+* The `select` method (select tag) forces `:include_blank` if `required` is true and
`display size` is one and `multiple` is not true. *Angelo Capilleri*
* Copy literal route constraints to defaults so that url generation know about them.
@@ -639,7 +711,7 @@
* Make current object and counter (when it applies) variables accessible when
rendering templates with :object / :collection. *Carlos Antonio da Silva*
-* JSONP now uses mimetype text/javascript instead of application/json. *omjokine*
+* JSONP now uses mimetype `text/javascript` instead of `application/json`. *omjokine*
* Allow to lazy load `default_form_builder` by passing a `String` instead of a constant. *Piotr Sarnacki*
@@ -652,14 +724,14 @@
* Add `index` method to FormBuilder class. *Jorge Bejar*
-* Remove the leading \n added by textarea on assert_select. *Santiago Pastorino*
+* Remove the leading \n added by textarea on `assert_select`. *Santiago Pastorino*
* Changed default value for `config.action_view.embed_authenticity_token_in_remote_forms`
to `false`. This change breaks remote forms that need to work also without javascript,
so if you need such behavior, you can either set it to `true` or explicitly pass
- `authenticity_token: true` in form options
+ `authenticity_token: true` in form options.
-* Added ActionDispatch::SSL middleware that when included force all the requests to be under HTTPS protocol. *Rafael Mendonça França*
+* Added `ActionDispatch::SSL` middleware that when included force all the requests to be under HTTPS protocol. *Rafael Mendonça França*
* Add `include_hidden` option to select tag. With `include_hidden: false` select with `multiple` attribute doesn't generate hidden input with blank value. *Vasiliy Ermolovich*
diff --git a/actionpack/MIT-LICENSE b/actionpack/MIT-LICENSE
index 810daf856c..5c668d9624 100644
--- a/actionpack/MIT-LICENSE
+++ b/actionpack/MIT-LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2012 David Heinemeier Hansson
+Copyright (c) 2004-2013 David Heinemeier Hansson
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/actionpack/README.rdoc b/actionpack/README.rdoc
index ccd0193515..29a7fcf0f0 100644
--- a/actionpack/README.rdoc
+++ b/actionpack/README.rdoc
@@ -10,7 +10,7 @@ It consists of several modules:
* Action Dispatch, which parses information about the web request, handles
routing as defined by the user, and does advanced processing related to HTTP
- such as MIME-type negotiation, decoding parameters in POST/PUT bodies,
+ such as MIME-type negotiation, decoding parameters in POST, PATCH, or PUT bodies,
handling HTTP caching logic, cookies and sessions.
* Action Controller, which provides a base controller class that can be
diff --git a/actionpack/actionpack.gemspec b/actionpack/actionpack.gemspec
index c65870cac6..f00fc46b2e 100644
--- a/actionpack/actionpack.gemspec
+++ b/actionpack/actionpack.gemspec
@@ -21,7 +21,7 @@ Gem::Specification.new do |s|
s.add_dependency 'activesupport', version
s.add_dependency 'builder', '~> 3.1.0'
- s.add_dependency 'rack', '~> 1.4.1'
+ s.add_dependency 'rack', '~> 1.4.3'
s.add_dependency 'rack-test', '~> 0.6.1'
s.add_dependency 'erubis', '~> 2.7.0'
diff --git a/actionpack/lib/abstract_controller/layouts.rb b/actionpack/lib/abstract_controller/layouts.rb
index 73799e8085..91864f2a35 100644
--- a/actionpack/lib/abstract_controller/layouts.rb
+++ b/actionpack/lib/abstract_controller/layouts.rb
@@ -209,7 +209,7 @@ module AbstractController
_write_layout_method
end
- delegate :_layout_conditions, :to => "self.class"
+ delegate :_layout_conditions, to: :class
module ClassMethods
def inherited(klass) # :nodoc:
diff --git a/actionpack/lib/action_controller.rb b/actionpack/lib/action_controller.rb
index 1a13d7af29..9cacb3862b 100644
--- a/actionpack/lib/action_controller.rb
+++ b/actionpack/lib/action_controller.rb
@@ -42,7 +42,6 @@ module ActionController
autoload :Integration, 'action_controller/deprecated/integration_test'
autoload :IntegrationTest, 'action_controller/deprecated/integration_test'
- autoload :PerformanceTest, 'action_controller/deprecated/performance_test'
autoload :Routing, 'action_controller/deprecated'
autoload :TestCase, 'action_controller/test_case'
autoload :TemplateAssertions, 'action_controller/test_case'
diff --git a/actionpack/lib/action_controller/caching.rb b/actionpack/lib/action_controller/caching.rb
index 2892e093af..cf2cda039d 100644
--- a/actionpack/lib/action_controller/caching.rb
+++ b/actionpack/lib/action_controller/caching.rb
@@ -70,12 +70,26 @@ module ActionController
config_accessor :perform_caching
self.perform_caching = true if perform_caching.nil?
+
+ class_attribute :_view_cache_dependencies
+ self._view_cache_dependencies = []
+ helper_method :view_cache_dependencies if respond_to?(:helper_method)
+ end
+
+ module ClassMethods
+ def view_cache_dependency(&dependency)
+ self._view_cache_dependencies += [dependency]
+ end
end
def caching_allowed?
request.get? && response.status == 200
end
+ def view_cache_dependencies
+ self.class._view_cache_dependencies.map { |dep| instance_exec(&dep) }.compact
+ end
+
protected
# Convenience accessor.
def cache(key, options = {}, &block)
diff --git a/actionpack/lib/action_controller/deprecated/performance_test.rb b/actionpack/lib/action_controller/deprecated/performance_test.rb
deleted file mode 100644
index c7ba5a2fe7..0000000000
--- a/actionpack/lib/action_controller/deprecated/performance_test.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-ActionController::PerformanceTest = ActionDispatch::PerformanceTest
-
-ActiveSupport::Deprecation.warn 'ActionController::PerformanceTest is deprecated and will be removed, use ActionDispatch::PerformanceTest instead.'
diff --git a/actionpack/lib/action_controller/metal/conditional_get.rb b/actionpack/lib/action_controller/metal/conditional_get.rb
index 3f9b382a11..eddee08545 100644
--- a/actionpack/lib/action_controller/metal/conditional_get.rb
+++ b/actionpack/lib/action_controller/metal/conditional_get.rb
@@ -1,5 +1,3 @@
-require 'active_support/core_ext/class/attribute'
-
module ActionController
module ConditionalGet
extend ActiveSupport::Concern
diff --git a/actionpack/lib/action_controller/metal/head.rb b/actionpack/lib/action_controller/metal/head.rb
index bbace49fd9..8237db15ca 100644
--- a/actionpack/lib/action_controller/metal/head.rb
+++ b/actionpack/lib/action_controller/metal/head.rb
@@ -31,6 +31,7 @@ module ActionController
if include_content?(self.status)
self.content_type = content_type || (Mime[formats.first] if formats)
+ self.response.charset = false if self.response
self.response_body = " "
else
headers.delete('Content-Type')
diff --git a/actionpack/lib/action_controller/metal/http_authentication.rb b/actionpack/lib/action_controller/metal/http_authentication.rb
index 896238b7dc..e295002b16 100644
--- a/actionpack/lib/action_controller/metal/http_authentication.rb
+++ b/actionpack/lib/action_controller/metal/http_authentication.rb
@@ -228,7 +228,7 @@ module ActionController
end
def decode_credentials(header)
- HashWithIndifferentAccess[header.to_s.gsub(/^Digest\s+/,'').split(',').map do |pair|
+ ActiveSupport::HashWithIndifferentAccess[header.to_s.gsub(/^Digest\s+/, '').split(',').map do |pair|
key, value = pair.split('=', 2)
[key.strip, value.to_s.gsub(/^"|"$/,'').delete('\'')]
end]
diff --git a/actionpack/lib/action_controller/metal/mime_responds.rb b/actionpack/lib/action_controller/metal/mime_responds.rb
index 6bf306ac5b..d04fbae150 100644
--- a/actionpack/lib/action_controller/metal/mime_responds.rb
+++ b/actionpack/lib/action_controller/metal/mime_responds.rb
@@ -82,7 +82,7 @@ module ActionController #:nodoc:
# (by name) if it does not already exist, without web-services, it might look like this:
#
# def create
- # @company = Company.find_or_create_by_name(params[:company][:name])
+ # @company = Company.find_or_create_by(name: params[:company][:name])
# @person = @company.people.create(params[:person])
#
# redirect_to(person_list_url)
@@ -92,7 +92,7 @@ module ActionController #:nodoc:
#
# def create
# company = params[:person].delete(:company)
- # @company = Company.find_or_create_by_name(company[:name])
+ # @company = Company.find_or_create_by(name: company[:name])
# @person = @company.people.create(params[:person])
#
# respond_to do |format|
@@ -120,7 +120,7 @@ module ActionController #:nodoc:
# Note, however, the extra bit at the top of that action:
#
# company = params[:person].delete(:company)
- # @company = Company.find_or_create_by_name(company[:name])
+ # @company = Company.find_or_create_by(name: company[:name])
#
# This is because the incoming XML document (if a web-service request is in process) can only contain a
# single root-node. So, we have to rearrange things so that the request looks like this (url-encoded):
@@ -227,7 +227,7 @@ module ActionController #:nodoc:
# i.e. its +show+ action.
# 2. If there are validation errors, the response
# renders a default action, which is <tt>:new</tt> for a
- # +post+ request or <tt>:edit</tt> for +put+.
+ # +post+ request or <tt>:edit</tt> for +patch+ or +put+.
# Thus an example like this -
#
# respond_to :html, :xml
@@ -320,7 +320,7 @@ module ActionController #:nodoc:
# 2. <tt>:action</tt> - overwrites the default render action used after an
# unsuccessful html +post+ request.
def respond_with(*resources, &block)
- raise "In order to use respond_with, first you need to declare the formats your " <<
+ raise "In order to use respond_with, first you need to declare the formats your " \
"controller responds to in the class level" if self.class.mimes_for_respond_to.empty?
if collector = retrieve_collector_from_mimes(&block)
diff --git a/actionpack/lib/action_controller/metal/redirecting.rb b/actionpack/lib/action_controller/metal/redirecting.rb
index 091facfd8d..13ec55fe92 100644
--- a/actionpack/lib/action_controller/metal/redirecting.rb
+++ b/actionpack/lib/action_controller/metal/redirecting.rb
@@ -32,7 +32,7 @@ module ActionController
# redirect_to :back
# redirect_to proc { edit_post_url(@post) }
#
- # The redirection happens as a "302 Moved" header unless otherwise specified.
+ # The redirection happens as a "302 Found" header unless otherwise specified.
#
# redirect_to post_url(@post), status: :found
# redirect_to action: 'atom', status: :moved_permanently
diff --git a/actionpack/lib/action_controller/metal/streaming.rb b/actionpack/lib/action_controller/metal/streaming.rb
index 0b3c438ec2..73e9b5660d 100644
--- a/actionpack/lib/action_controller/metal/streaming.rb
+++ b/actionpack/lib/action_controller/metal/streaming.rb
@@ -26,7 +26,7 @@ module ActionController #:nodoc:
#
# class PostsController
# def index
- # @posts = Post.scoped
+ # @posts = Post.all
# render stream: true
# end
# end
@@ -51,9 +51,9 @@ module ActionController #:nodoc:
#
# def dashboard
# # Allow lazy execution of the queries
- # @posts = Post.scoped
- # @pages = Page.scoped
- # @articles = Article.scoped
+ # @posts = Post.all
+ # @pages = Page.all
+ # @articles = Article.all
# render stream: true
# end
#
diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb
index 8faa5f8a13..941b6e210f 100644
--- a/actionpack/lib/action_controller/metal/strong_parameters.rb
+++ b/actionpack/lib/action_controller/metal/strong_parameters.rb
@@ -1,4 +1,3 @@
-require 'active_support/concern'
require 'active_support/core_ext/hash/indifferent_access'
require 'active_support/core_ext/array/wrap'
require 'active_support/rescuable'
@@ -41,11 +40,11 @@ module ActionController
# permitted.class # => ActionController::Parameters
# permitted.permitted? # => true
#
- # Person.first.update_attributes!(permitted)
+ # Person.first.update!(permitted)
# # => #<Person id: 1, name: "Francesco", age: 22, role: "user">
#
# It provides a +permit_all_parameters+ option that controls the top-level
- # behaviour of new instances. If it's +true+, all the parameters will be
+ # behavior of new instances. If it's +true+, all the parameters will be
# permitted by default. The default value for +permit_all_parameters+
# option is +false+.
#
@@ -329,7 +328,7 @@ module ActionController
# # into a 400 Bad Request reply.
# def update
# redirect_to current_account.people.find(params[:id]).tap { |person|
- # person.update_attributes!(person_params)
+ # person.update!(person_params)
# }
# end
#
diff --git a/actionpack/lib/action_controller/record_identifier.rb b/actionpack/lib/action_controller/record_identifier.rb
index b49128c184..70e0a820c4 100644
--- a/actionpack/lib/action_controller/record_identifier.rb
+++ b/actionpack/lib/action_controller/record_identifier.rb
@@ -1,11 +1,10 @@
-require 'active_support/deprecation'
require 'action_view/record_identifier'
module ActionController
module RecordIdentifier
MESSAGE = 'method will no longer be included by default in controllers since Rails 4.1. ' +
'If you would like to use it in controllers, please include ' +
- 'ActionView::RecodIdentifier module.'
+ 'ActionView::RecordIdentifier module.'
def dom_id(record, prefix = nil)
ActiveSupport::Deprecation.warn('dom_id ' + MESSAGE)
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index 7b48870090..331d15d403 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -360,13 +360,6 @@ module ActionController
#
# assert_redirected_to page_url(title: 'foo')
class TestCase < ActiveSupport::TestCase
-
- # Use AC::TestCase for the base class when describing a controller
- register_spec_type(self) do |desc|
- Class === desc && desc < ActionController::Metal
- end
- register_spec_type(/Controller( ?Test)?\z/i, self)
-
module Behavior
extend ActiveSupport::Concern
include ActionDispatch::TestProcess
diff --git a/actionpack/lib/action_dispatch.rb b/actionpack/lib/action_dispatch.rb
index 938161dc69..9ab048b756 100644
--- a/actionpack/lib/action_dispatch.rb
+++ b/actionpack/lib/action_dispatch.rb
@@ -1,5 +1,5 @@
#--
-# Copyright (c) 2004-2012 David Heinemeier Hansson
+# Copyright (c) 2004-2013 David Heinemeier Hansson
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
@@ -97,7 +97,6 @@ module ActionDispatch
autoload :Assertions
autoload :Integration
autoload :IntegrationTest, 'action_dispatch/testing/integration'
- autoload :PerformanceTest
autoload :TestProcess
autoload :TestRequest
autoload :TestResponse
diff --git a/actionpack/lib/action_dispatch/http/filter_parameters.rb b/actionpack/lib/action_dispatch/http/filter_parameters.rb
index 02ab49b44e..289e204ac8 100644
--- a/actionpack/lib/action_dispatch/http/filter_parameters.rb
+++ b/actionpack/lib/action_dispatch/http/filter_parameters.rb
@@ -1,5 +1,6 @@
require 'active_support/core_ext/hash/keys'
require 'active_support/core_ext/object/duplicable'
+require 'action_dispatch/http/parameter_filter'
module ActionDispatch
module Http
diff --git a/actionpack/lib/action_dispatch/http/parameters.rb b/actionpack/lib/action_dispatch/http/parameters.rb
index 6610315da7..25edd196c3 100644
--- a/actionpack/lib/action_dispatch/http/parameters.rb
+++ b/actionpack/lib/action_dispatch/http/parameters.rb
@@ -72,7 +72,7 @@ module ActionDispatch
end
end
- # Convert nested Hash to HashWithIndifferentAccess
+ # Convert nested Hash to ActiveSupport::HashWithIndifferentAccess
def normalize_parameters(value)
case value
when Hash
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index d60c8775af..7b04d6e851 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -1,12 +1,16 @@
-require 'tempfile'
require 'stringio'
-require 'strscan'
-require 'active_support/core_ext/hash/indifferent_access'
-require 'active_support/core_ext/string/access'
require 'active_support/inflector'
require 'action_dispatch/http/headers'
require 'action_controller/metal/exceptions'
+require 'rack/request'
+require 'action_dispatch/http/cache'
+require 'action_dispatch/http/mime_negotiation'
+require 'action_dispatch/http/parameters'
+require 'action_dispatch/http/filter_parameters'
+require 'action_dispatch/http/upload'
+require 'action_dispatch/http/url'
+require 'active_support/core_ext/array/conversions'
module ActionDispatch
class Request < Rack::Request
@@ -280,15 +284,14 @@ module ActionDispatch
LOCALHOST =~ remote_addr && LOCALHOST =~ remote_ip
end
- protected
-
# Remove nils from the params hash
def deep_munge(hash)
- hash.each_value do |v|
+ hash.each do |k, v|
case v
when Array
v.grep(Hash) { |x| deep_munge(x) }
v.compact!
+ hash[k] = nil if v.empty?
when Hash
deep_munge(v)
end
@@ -297,6 +300,8 @@ module ActionDispatch
hash
end
+ protected
+
def parse_query(qs)
deep_munge(super)
end
diff --git a/actionpack/lib/action_dispatch/http/response.rb b/actionpack/lib/action_dispatch/http/response.rb
index 0f808ac9cf..91cf4784db 100644
--- a/actionpack/lib/action_dispatch/http/response.rb
+++ b/actionpack/lib/action_dispatch/http/response.rb
@@ -260,14 +260,18 @@ module ActionDispatch # :nodoc:
return if headers[CONTENT_TYPE].present?
@content_type ||= Mime::HTML
- @charset ||= self.class.default_charset
+ @charset ||= self.class.default_charset unless @charset == false
type = @content_type.to_s.dup
- type << "; charset=#{@charset}" unless @sending_file
+ type << "; charset=#{@charset}" if append_charset?
headers[CONTENT_TYPE] = type
end
+ def append_charset?
+ !@sending_file && @charset != false
+ end
+
def rack_response(status, header)
assign_default_content_type_and_charset!(header)
handle_conditional_get!
diff --git a/actionpack/lib/action_dispatch/http/upload.rb b/actionpack/lib/action_dispatch/http/upload.rb
index 79437d6e85..8a97248eb3 100644
--- a/actionpack/lib/action_dispatch/http/upload.rb
+++ b/actionpack/lib/action_dispatch/http/upload.rb
@@ -19,7 +19,7 @@ module ActionDispatch
# its interface is available directly.
attr_accessor :tempfile
- # TODO.
+ # A string with the headers of the multipart request.
attr_accessor :headers
def initialize(hash) # :nodoc:
@@ -75,7 +75,7 @@ module ActionDispatch
end
module Upload # :nodoc:
- # Convert nested Hash to HashWithIndifferentAccess and replace
+ # Convert nested Hash to ActiveSupport::HashWithIndifferentAccess and replace
# file upload hash with UploadedFile objects
def normalize_parameters(value)
if Hash === value && value.has_key?(:tempfile)
diff --git a/actionpack/lib/action_dispatch/http/url.rb b/actionpack/lib/action_dispatch/http/url.rb
index bced7d84c0..43f26d696d 100644
--- a/actionpack/lib/action_dispatch/http/url.rb
+++ b/actionpack/lib/action_dispatch/http/url.rb
@@ -32,7 +32,11 @@ module ActionDispatch
params.reject! { |_,v| v.to_param.nil? }
result = build_host_url(options)
- result << (options[:trailing_slash] ? path.sub(/\?|\z/) { "/" + $& } : path)
+ if options[:trailing_slash] && !path.ends_with?('/')
+ result << path.sub(/(\?|\z)/) { "/" + $& }
+ else
+ result << path
+ end
result << "?#{params.to_query}" unless params.empty?
result << "##{Journey::Router::Utils.escape_fragment(options[:anchor].to_param.to_s)}" if options[:anchor]
result
diff --git a/actionpack/lib/action_dispatch/journey/formatter.rb b/actionpack/lib/action_dispatch/journey/formatter.rb
index 4a344f71af..cf755bfbeb 100644
--- a/actionpack/lib/action_dispatch/journey/formatter.rb
+++ b/actionpack/lib/action_dispatch/journey/formatter.rb
@@ -37,19 +37,16 @@ module ActionDispatch
private
def extract_parameterized_parts(route, options, recall, parameterize = nil)
- constraints = recall.merge(options)
- data = constraints.dup
+ parameterized_parts = recall.merge(options)
keys_to_keep = route.parts.reverse.drop_while { |part|
!options.key?(part) || (options[part] || recall[part]).nil?
} | route.required_parts
- (data.keys - keys_to_keep).each do |bad_key|
- data.delete(bad_key)
+ (parameterized_parts.keys - keys_to_keep).each do |bad_key|
+ parameterized_parts.delete(bad_key)
end
- parameterized_parts = data.dup
-
if parameterize
parameterized_parts.each do |k, v|
parameterized_parts[k] = parameterize.call(k, v)
diff --git a/actionpack/lib/action_dispatch/journey/route.rb b/actionpack/lib/action_dispatch/journey/route.rb
index d18efd863a..d3988cf31e 100644
--- a/actionpack/lib/action_dispatch/journey/route.rb
+++ b/actionpack/lib/action_dispatch/journey/route.rb
@@ -30,11 +30,11 @@ module ActionDispatch
end
def ast
- return @decorated_ast if @decorated_ast
-
- @decorated_ast = path.ast
- @decorated_ast.grep(Nodes::Terminal).each { |n| n.memo = self }
- @decorated_ast
+ @decorated_ast ||= begin
+ decorated_ast = path.ast
+ decorated_ast.grep(Nodes::Terminal).each { |n| n.memo = self }
+ decorated_ast
+ end
end
def requirements # :nodoc:
@@ -45,7 +45,7 @@ module ActionDispatch
end
def segments
- @path.names
+ path.names
end
def required_keys
diff --git a/actionpack/lib/action_dispatch/journey/routes.rb b/actionpack/lib/action_dispatch/journey/routes.rb
index 32829a1f20..a99d6d0d6a 100644
--- a/actionpack/lib/action_dispatch/journey/routes.rb
+++ b/actionpack/lib/action_dispatch/journey/routes.rb
@@ -16,12 +16,12 @@ module ActionDispatch
end
def length
- @routes.length
+ routes.length
end
alias :size :length
def last
- @routes.last
+ routes.last
end
def each(&block)
@@ -33,24 +33,23 @@ module ActionDispatch
end
def partitioned_routes
- @partitioned_routes ||= routes.partition { |r|
- r.path.anchored && r.ast.grep(Nodes::Symbol).all? { |n| n.default_regexp? }
- }
+ @partitioned_routes ||= routes.partition do |r|
+ r.path.anchored && r.ast.grep(Nodes::Symbol).all?(&:default_regexp?)
+ end
end
def ast
- return @ast if @ast
- return if partitioned_routes.first.empty?
-
- asts = partitioned_routes.first.map { |r| r.ast }
- @ast = Nodes::Or.new(asts)
+ @ast ||= begin
+ asts = partitioned_routes.first.map(&:ast)
+ Nodes::Or.new(asts) unless asts.empty?
+ end
end
def simulator
- return @simulator if @simulator
-
- gtg = GTG::Builder.new(ast).transition_table
- @simulator = GTG::Simulator.new(gtg)
+ @simulator ||= begin
+ gtg = GTG::Builder.new(ast).transition_table
+ GTG::Simulator.new(gtg)
+ end
end
# Add a route to the routing table.
diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb
index 2f148752cb..6ecbb03784 100644
--- a/actionpack/lib/action_dispatch/middleware/cookies.rb
+++ b/actionpack/lib/action_dispatch/middleware/cookies.rb
@@ -15,7 +15,7 @@ module ActionDispatch
# being written will be sent out with the response. Reading a cookie does not get
# the cookie object itself back, just the value it holds.
#
- # Examples for writing:
+ # Examples of writing:
#
# # Sets a simple session cookie.
# # This cookie will be deleted when the user's browser is closed.
@@ -38,7 +38,7 @@ module ActionDispatch
# # You can also chain these methods:
# cookies.permanent.signed[:login] = "XJ-122"
#
- # Examples for reading:
+ # Examples of reading:
#
# cookies[:user_name] # => "david"
# cookies.size # => 2
@@ -87,6 +87,9 @@ module ActionDispatch
ENCRYPTED_SIGNED_COOKIE_SALT = "action_dispatch.encrypted_signed_cookie_salt".freeze
TOKEN_KEY = "action_dispatch.secret_token".freeze
+ # Cookies can typically store 4096 bytes.
+ MAX_COOKIE_SIZE = 4096
+
# Raised when storing more than 4K of session data.
CookieOverflow = Class.new StandardError
@@ -293,13 +296,17 @@ module ActionDispatch
end
end
- class PermanentCookieJar < CookieJar #:nodoc:
+ class PermanentCookieJar #:nodoc:
def initialize(parent_jar, key_generator, options = {})
@parent_jar = parent_jar
@key_generator = key_generator
@options = options
end
+ def [](key)
+ @parent_jar[name.to_s]
+ end
+
def []=(key, options)
if options.is_a?(Hash)
options.symbolize_keys!
@@ -311,14 +318,25 @@ module ActionDispatch
@parent_jar[key] = options
end
+ def permanent
+ @permanent ||= PermanentCookieJar.new(self, @key_generator, @options)
+ end
+
+ def signed
+ @signed ||= SignedCookieJar.new(self, @key_generator, @options)
+ end
+
+ def encrypted
+ @encrypted ||= EncryptedCookieJar.new(self, @key_generator, @options)
+ end
+
def method_missing(method, *arguments, &block)
- @parent_jar.send(method, *arguments, &block)
+ ActiveSupport::Deprecation.warn "#{method} is deprecated with no replacement. " +
+ "You probably want to try this method over the parent CookieJar."
end
end
- class SignedCookieJar < CookieJar #:nodoc:
- MAX_COOKIE_SIZE = 4096 # Cookies can typically store 4096 bytes.
-
+ class SignedCookieJar #:nodoc:
def initialize(parent_jar, key_generator, options = {})
@parent_jar = parent_jar
@options = options
@@ -346,12 +364,25 @@ module ActionDispatch
@parent_jar[key] = options
end
+ def permanent
+ @permanent ||= PermanentCookieJar.new(self, @key_generator, @options)
+ end
+
+ def signed
+ @signed ||= SignedCookieJar.new(self, @key_generator, @options)
+ end
+
+ def encrypted
+ @encrypted ||= EncryptedCookieJar.new(self, @key_generator, @options)
+ end
+
def method_missing(method, *arguments, &block)
- @parent_jar.send(method, *arguments, &block)
+ ActiveSupport::Deprecation.warn "#{method} is deprecated with no replacement. " +
+ "You probably want to try this method over the parent CookieJar."
end
end
- class EncryptedCookieJar < SignedCookieJar #:nodoc:
+ class EncryptedCookieJar #:nodoc:
def initialize(parent_jar, key_generator, options = {})
if ActiveSupport::DummyKeyGenerator === key_generator
raise "Encrypted Cookies must be used in conjunction with config.secret_key_base." +
@@ -365,8 +396,8 @@ module ActionDispatch
@encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret)
end
- def [](name)
- if encrypted_message = @parent_jar[name]
+ def [](key)
+ if encrypted_message = @parent_jar[key]
@encryptor.decrypt_and_verify(encrypted_message)
end
rescue ActiveSupport::MessageVerifier::InvalidSignature,
@@ -385,6 +416,23 @@ module ActionDispatch
raise CookieOverflow if options[:value].size > MAX_COOKIE_SIZE
@parent_jar[key] = options
end
+
+ def permanent
+ @permanent ||= PermanentCookieJar.new(self, @key_generator, @options)
+ end
+
+ def signed
+ @signed ||= SignedCookieJar.new(self, @key_generator, @options)
+ end
+
+ def encrypted
+ @encrypted ||= EncryptedCookieJar.new(self, @key_generator, @options)
+ end
+
+ def method_missing(method, *arguments, &block)
+ ActiveSupport::Deprecation.warn "#{method} is deprecated with no replacement. " +
+ "You probably want to try this method over the parent CookieJar."
+ end
end
def initialize(app)
diff --git a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
index 6705e531cb..64230ff1ae 100644
--- a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
@@ -2,7 +2,6 @@ require 'action_dispatch/http/request'
require 'action_dispatch/middleware/exception_wrapper'
require 'action_dispatch/routing/inspector'
-
module ActionDispatch
# This middleware is responsible for logging exceptions and
# showing a debugging page in case the request is local.
@@ -15,18 +14,17 @@ module ActionDispatch
end
def call(env)
- begin
- response = (_, headers, body = @app.call(env))
-
- if headers['X-Cascade'] == 'pass'
- body.close if body.respond_to?(:close)
- raise ActionController::RoutingError, "No route matches [#{env['REQUEST_METHOD']}] #{env['PATH_INFO'].inspect}"
- end
- rescue Exception => exception
- raise exception if env['action_dispatch.show_exceptions'] == false
+ _, headers, body = response = @app.call(env)
+
+ if headers['X-Cascade'] == 'pass'
+ body.close if body.respond_to?(:close)
+ raise ActionController::RoutingError, "No route matches [#{env['REQUEST_METHOD']}] #{env['PATH_INFO'].inspect}"
end
- exception ? render_exception(env, exception) : response
+ response
+ rescue Exception => exception
+ raise exception if env['action_dispatch.show_exceptions'] == false
+ render_exception(env, exception)
end
private
@@ -42,9 +40,11 @@ module ActionDispatch
:application_trace => wrapper.application_trace,
:framework_trace => wrapper.framework_trace,
:full_trace => wrapper.full_trace,
- :routes => formatted_routes(exception)
+ :routes_inspector => routes_inspector(exception),
+ :source_extract => wrapper.source_extract,
+ :line_number => wrapper.line_number,
+ :file => wrapper.file
)
-
file = "rescues/#{wrapper.rescue_template}"
body = template.render(:template => file, :layout => 'rescues/layout')
render(wrapper.status_code, body)
@@ -82,11 +82,9 @@ module ActionDispatch
@stderr_logger ||= ActiveSupport::Logger.new($stderr)
end
- def formatted_routes(exception)
- return false unless @routes_app.respond_to?(:routes)
- if exception.is_a?(ActionController::RoutingError) || exception.is_a?(ActionView::Template::Error)
- inspector = ActionDispatch::Routing::RoutesInspector.new
- inspector.collect_routes(@routes_app.routes.routes)
+ def routes_inspector(exception)
+ if @routes_app.respond_to?(:routes) && (exception.is_a?(ActionController::RoutingError) || exception.is_a?(ActionView::Template::Error))
+ ActionDispatch::Routing::RoutesInspector.new(@routes_app.routes.routes)
end
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
index ae38c56a67..869d0aa7af 100644
--- a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
+++ b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb
@@ -1,5 +1,4 @@
require 'action_controller/metal/exceptions'
-require 'active_support/core_ext/exception'
require 'active_support/core_ext/class/attribute_accessors'
module ActionDispatch
@@ -25,7 +24,7 @@ module ActionDispatch
'ActionView::Template::Error' => 'template_error'
)
- attr_reader :env, :exception
+ attr_reader :env, :exception, :line_number, :file
def initialize(env, exception)
@env = env
@@ -56,6 +55,15 @@ module ActionDispatch
Rack::Utils.status_code(@@rescue_responses[class_name])
end
+ def source_extract
+ if application_trace && trace = application_trace.first
+ file, line, _ = trace.split(":")
+ @file = file
+ @line_number = line.to_i
+ source_fragment(@file, @line_number)
+ end
+ end
+
private
def original_exception(exception)
@@ -81,5 +89,17 @@ module ActionDispatch
def backtrace_cleaner
@backtrace_cleaner ||= @env['action_dispatch.backtrace_cleaner']
end
+
+ def source_fragment(path, line)
+ return unless Rails.respond_to?(:root) && Rails.root
+ full_path = Rails.root.join(path)
+ if File.exists?(full_path)
+ File.open(full_path, "r") do |file|
+ start = [line - 3, 0].max
+ lines = file.each_line.drop(start).take(6)
+ Hash[*(start+1..(lines.count+start)).zip(lines).flatten]
+ end
+ end
+ end
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/flash.rb b/actionpack/lib/action_dispatch/middleware/flash.rb
index f24e9b8e18..7e56feb90a 100644
--- a/actionpack/lib/action_dispatch/middleware/flash.rb
+++ b/actionpack/lib/action_dispatch/middleware/flash.rb
@@ -59,12 +59,12 @@ module ActionDispatch
@flash[k]
end
- # Convenience accessor for flash.now[:alert]=
+ # Convenience accessor for <tt>flash.now[:alert]=</tt>.
def alert=(message)
self[:alert] = message
end
- # Convenience accessor for flash.now[:notice]=
+ # Convenience accessor for <tt>flash.now[:notice]=</tt>.
def notice=(message)
self[:notice] = message
end
@@ -82,7 +82,7 @@ module ActionDispatch
else
new
end
-
+
flash.tap(&:sweep)
end
@@ -169,6 +169,14 @@ module ActionDispatch
# vanish when the current action is done.
#
# Entries set via <tt>now</tt> are accessed the same way as standard entries: <tt>flash['my-key']</tt>.
+ #
+ # Also, brings two convenience accessors:
+ #
+ # flash.now.alert = "Beware now!"
+ # # Equivalent to flash.now[:alert] = "Beware now!"
+ #
+ # flash.now.notice = "Good luck now!"
+ # # Equivalent to flash.now[:notice] = "Good luck now!"
def now
@now ||= FlashNow.new(self)
end
@@ -199,22 +207,22 @@ module ActionDispatch
@discard.replace @flashes.keys
end
- # Convenience accessor for flash[:alert]
+ # Convenience accessor for <tt>flash[:alert]</tt>.
def alert
self[:alert]
end
- # Convenience accessor for flash[:alert]=
+ # Convenience accessor for <tt>flash[:alert]=</tt>.
def alert=(message)
self[:alert] = message
end
- # Convenience accessor for flash[:notice]
+ # Convenience accessor for <tt>flash[:notice]</tt>.
def notice
self[:notice]
end
- # Convenience accessor for flash[:notice]=
+ # Convenience accessor for <tt>flash[:notice]=</tt>.
def notice=(message)
self[:notice] = message
end
diff --git a/actionpack/lib/action_dispatch/middleware/params_parser.rb b/actionpack/lib/action_dispatch/middleware/params_parser.rb
index 2c98ca03a8..0898ad82dd 100644
--- a/actionpack/lib/action_dispatch/middleware/params_parser.rb
+++ b/actionpack/lib/action_dispatch/middleware/params_parser.rb
@@ -47,14 +47,12 @@ module ActionDispatch
when Proc
strategy.call(request.raw_post)
when :xml_simple, :xml_node
- data = Hash.from_xml(request.raw_post) || {}
+ data = request.deep_munge(Hash.from_xml(request.body.read) || {})
data.with_indifferent_access
- when :yaml
- YAML.load(request.raw_post)
when :json
- data = ActiveSupport::JSON.decode(request.raw_post)
+ data = ActiveSupport::JSON.decode(request.body)
data = {:_json => data} unless data.is_a?(Hash)
- data.with_indifferent_access
+ request.deep_munge(data).with_indifferent_access
else
false
end
diff --git a/actionpack/lib/action_dispatch/middleware/remote_ip.rb b/actionpack/lib/action_dispatch/middleware/remote_ip.rb
index 5abf8f2802..4e36c9bb49 100644
--- a/actionpack/lib/action_dispatch/middleware/remote_ip.rb
+++ b/actionpack/lib/action_dispatch/middleware/remote_ip.rb
@@ -1,23 +1,59 @@
module ActionDispatch
+ # This middleware calculates the IP address of the remote client that is
+ # making the request. It does this by checking various headers that could
+ # contain the address, and then picking the last-set address that is not
+ # on the list of trusted IPs. This follows the precendent set by e.g.
+ # {the Tomcat server}[https://issues.apache.org/bugzilla/show_bug.cgi?id=50453],
+ # with {reasoning explained at length}[http://blog.gingerlime.com/2012/rails-ip-spoofing-vulnerabilities-and-protection]
+ # by @gingerlime. A more detailed explanation of the algorithm is given
+ # at GetIp#calculate_ip.
+ #
+ # Some Rack servers concatenate repeated headers, like {HTTP RFC 2616}[http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2]
+ # requires. Some Rack servers simply drop preceeding headers, and only report
+ # the value that was {given in the last header}[http://andre.arko.net/2011/12/26/repeated-headers-and-ruby-web-servers].
+ # If you are behind multiple proxy servers (like Nginx to HAProxy to Unicorn)
+ # then you should test your Rack server to make sure your data is good.
+ #
+ # IF YOU DON'T USE A PROXY, THIS MAKES YOU VULNERABLE TO IP SPOOFING.
+ # This middleware assumes that there is at least one proxy sitting around
+ # and setting headers with the client's remote IP address. If you don't use
+ # a proxy, because you are hosted on e.g. Heroku without SSL, any client can
+ # claim to have any IP address by setting the X-Forwarded-For header. If you
+ # care about that, then you need to explicitly drop or ignore those headers
+ # sometime before this middleware runs.
class RemoteIp
- class IpSpoofAttackError < StandardError ; end
+ class IpSpoofAttackError < StandardError; end
- # IP addresses that are "trusted proxies" that can be stripped from
- # the comma-delimited list in the X-Forwarded-For header. See also:
- # http://en.wikipedia.org/wiki/Private_network#Private_IPv4_address_spaces
- # http://en.wikipedia.org/wiki/Private_network#Private_IPv6_addresses.
+ # The default trusted IPs list simply includes IP addresses that are
+ # guaranteed by the IP specification to be private addresses. Those will
+ # not be the ultimate client IP in production, and so are discarded. See
+ # http://en.wikipedia.org/wiki/Private_network for details.
TRUSTED_PROXIES = %r{
- ^127\.0\.0\.1$ | # localhost
- ^::1$ |
- ^(10 | # private IP 10.x.x.x
- 172\.(1[6-9]|2[0-9]|3[0-1]) | # private IP in the range 172.16.0.0 .. 172.31.255.255
- 192\.168 | # private IP 192.168.x.x
- fc00:: # private IP fc00
- )\.
+ ^127\.0\.0\.1$ | # localhost IPv4
+ ^::1$ | # localhost IPv6
+ ^fc00: | # private IPv6 range fc00
+ ^10\. | # private IPv4 range 10.x.x.x
+ ^172\.(1[6-9]|2[0-9]|3[0-1])\.| # private IPv4 range 172.16.0.0 .. 172.31.255.255
+ ^192\.168\. # private IPv4 range 192.168.x.x
}x
attr_reader :check_ip, :proxies
+ # Create a new +RemoteIp+ middleware instance.
+ #
+ # The +check_ip_spoofing+ option is on by default. When on, an exception
+ # is raised if it looks like the client is trying to lie about its own IP
+ # address. It makes sense to turn off this check on sites aimed at non-IP
+ # clients (like WAP devices), or behind proxies that set headers in an
+ # incorrect or confusing way (like AWS ELB).
+ #
+ # The +custom_trusted+ argument can take a regex, which will be used
+ # instead of +TRUSTED_PROXIES+, or a string, which will be used in addition
+ # to +TRUSTED_PROXIES+. Any proxy setup will put the value you want in the
+ # middle (or at the beginning) of the X-Forwarded-For list, with your proxy
+ # servers after it. If your proxies aren't removed, pass them in via the
+ # +custom_trusted+ parameter. That way, the middleware will ignore those
+ # IP addresses, and return the one that you want.
def initialize(app, check_ip_spoofing = true, custom_proxies = nil)
@app = app
@check_ip = check_ip_spoofing
@@ -31,15 +67,23 @@ module ActionDispatch
end
end
+ # Since the IP address may not be needed, we store the object here
+ # without calculating the IP to keep from slowing down the majority of
+ # requests. For those requests that do need to know the IP, the
+ # GetIp#calculate_ip method will calculate the memoized client IP address.
def call(env)
env["action_dispatch.remote_ip"] = GetIp.new(env, self)
@app.call(env)
end
+ # The GetIp class exists as a way to defer processing of the request data
+ # into an actual IP address. If the ActionDispatch::Request#remote_ip method
+ # is called, this class will calculate the value and then memoize it.
class GetIp
- # IP v4 and v6 (with compression) validation regexp
- # https://gist.github.com/1289635
+ # This constant contains a regular expression that validates every known
+ # form of IP v4 and v6 address, with or without abbreviations, adapted
+ # from {this gist}[https://gist.github.com/1289635].
VALID_IP = %r{
(^(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[0-9]{1,2})){3}$) | # ip v4
(^(
@@ -63,62 +107,78 @@ module ActionDispatch
}x
def initialize(env, middleware)
- @env = env
- @middleware = middleware
- @ip = nil
+ @env = env
+ @check_ip = middleware.check_ip
+ @proxies = middleware.proxies
end
- # Determines originating IP address. REMOTE_ADDR is the standard
- # but will be wrong if the user is behind a proxy. Proxies will set
- # HTTP_CLIENT_IP and/or HTTP_X_FORWARDED_FOR, so we prioritize those.
- # HTTP_X_FORWARDED_FOR may be a comma-delimited list in the case of
- # multiple chained proxies. The first address which is in this list
- # if it's not a known proxy will be the originating IP.
- # Format of HTTP_X_FORWARDED_FOR:
- # client_ip, proxy_ip1, proxy_ip2...
- # http://en.wikipedia.org/wiki/X-Forwarded-For
+ # Sort through the various IP address headers, looking for the IP most
+ # likely to be the address of the actual remote client making this
+ # request.
+ #
+ # REMOTE_ADDR will be correct if the request is made directly against the
+ # Ruby process, on e.g. Heroku. When the request is proxied by another
+ # server like HAProxy or Nginx, the IP address that made the original
+ # request will be put in an X-Forwarded-For header. If there are multiple
+ # proxies, that header may contain a list of IPs. Other proxy services
+ # set the Client-Ip header instead, so we check that too.
+ #
+ # As discussed in {this post about Rails IP Spoofing}[http://blog.gingerlime.com/2012/rails-ip-spoofing-vulnerabilities-and-protection/],
+ # while the first IP in the list is likely to be the "originating" IP,
+ # it could also have been set by the client maliciously.
+ #
+ # In order to find the first address that is (probably) accurate, we
+ # take the list of IPs, remove known and trusted proxies, and then take
+ # the last address left, which was presumably set by one of those proxies.
def calculate_ip
- client_ip = @env['HTTP_CLIENT_IP']
- forwarded_ip = ips_from('HTTP_X_FORWARDED_FOR').first
- remote_addrs = ips_from('REMOTE_ADDR')
-
- check_ip = client_ip && @middleware.check_ip
- if check_ip && forwarded_ip != client_ip
+ # Set by the Rack web server, this is a single value.
+ remote_addr = ips_from('REMOTE_ADDR').last
+
+ # Could be a CSV list and/or repeated headers that were concatenated.
+ client_ips = ips_from('HTTP_CLIENT_IP').reverse
+ forwarded_ips = ips_from('HTTP_X_FORWARDED_FOR').reverse
+
+ # +Client-Ip+ and +X-Forwarded-For+ should not, generally, both be set.
+ # If they are both set, it means that this request passed through two
+ # proxies with incompatible IP header conventions, and there is no way
+ # for us to determine which header is the right one after the fact.
+ # Since we have no idea, we give up and explode.
+ should_check_ip = @check_ip && client_ips.last
+ if should_check_ip && !forwarded_ips.include?(client_ips.last)
# We don't know which came from the proxy, and which from the user
- raise IpSpoofAttackError, "IP spoofing attack?!" \
- "HTTP_CLIENT_IP=#{@env['HTTP_CLIENT_IP'].inspect}" \
+ raise IpSpoofAttackError, "IP spoofing attack?! " +
+ "HTTP_CLIENT_IP=#{@env['HTTP_CLIENT_IP'].inspect} " +
"HTTP_X_FORWARDED_FOR=#{@env['HTTP_X_FORWARDED_FOR'].inspect}"
end
- client_ips = remove_proxies [client_ip, forwarded_ip, remote_addrs].flatten
- if client_ips.present?
- client_ips.first
- else
- # If there is no client ip we can return first valid proxy ip from REMOTE_ADDR
- remote_addrs.find { |ip| valid_ip? ip }
- end
+ # We assume these things about the IP headers:
+ #
+ # - X-Forwarded-For will be a list of IPs, one per proxy, or blank
+ # - Client-Ip is propagated from the outermost proxy, or is blank
+ # - REMOTE_ADDR will be the IP that made the request to Rack
+ ips = [forwarded_ips, client_ips, remote_addr].flatten.compact
+
+ # If every single IP option is in the trusted list, just return REMOTE_ADDR
+ filter_proxies(ips).first || remote_addr
end
+ # Memoizes the value returned by #calculate_ip and returns it for
+ # ActionDispatch::Request to use.
def to_s
@ip ||= calculate_ip
end
- private
+ protected
def ips_from(header)
- @env[header] ? @env[header].strip.split(/[,\s]+/) : []
- end
-
- def valid_ip?(ip)
- ip =~ VALID_IP
- end
-
- def not_a_proxy?(ip)
- ip !~ @middleware.proxies
+ # Split the comma-separated list into an array of strings
+ ips = @env[header] ? @env[header].strip.split(/[,\s]+/) : []
+ # Only return IPs that are valid according to the regex
+ ips.select{ |ip| ip =~ VALID_IP }
end
- def remove_proxies(ips)
- ips.select { |ip| valid_ip?(ip) && not_a_proxy?(ip) }
+ def filter_proxies(ips)
+ ips.reject { |ip| ip =~ @proxies }
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
index ce5f89ee5b..1e6ed624b0 100644
--- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
+++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb
@@ -21,15 +21,12 @@ module ActionDispatch
#
# Session options:
#
- # * <tt>:secret</tt>: An application-wide key string or block returning a
- # string called per generated digest. The block is called with the
- # CGI::Session instance as an argument. It's important that the secret
- # is not vulnerable to a dictionary attack. Therefore, you should choose
- # a secret consisting of random numbers and letters and more than 30
- # characters.
+ # * <tt>:secret</tt>: An application-wide key string. It's important that
+ # the secret is not vulnerable to a dictionary attack. Therefore, you
+ # should choose a secret consisting of random numbers and letters and
+ # more than 30 characters.
#
# secret: '449fe2e7daee471bffae2fd8dc02313d'
- # secret: Proc.new { User.current_user.secret_key }
#
# * <tt>:digest</tt>: The message digest algorithm used to verify session
# integrity defaults to 'SHA1' but may be any digest provided by OpenSSL,
@@ -39,21 +36,38 @@ module ActionDispatch
# "rake secret" and set the key in config/initializers/secret_token.rb.
#
# Note that changing digest or secret invalidates all existing sessions!
- class CookieStore < Rack::Session::Cookie
+ class CookieStore < Rack::Session::Abstract::ID
include Compatibility
include StaleSessionCheck
include SessionObject
- # Override rack's method
+ def initialize(app, options={})
+ super(app, options.merge!(:cookie_only => true))
+ end
+
def destroy_session(env, session_id, options)
- new_sid = super
+ new_sid = generate_sid unless options[:drop]
# Reset hash and Assign the new session id
env["action_dispatch.request.unsigned_session_cookie"] = new_sid ? { "session_id" => new_sid } : {}
new_sid
end
+ def load_session(env)
+ stale_session_check! do
+ data = unpacked_cookie_data(env)
+ data = persistent_session_id!(data)
+ [data["session_id"], data]
+ end
+ end
+
private
+ def extract_session_id(env)
+ stale_session_check! do
+ unpacked_cookie_data(env)["session_id"]
+ end
+ end
+
def unpacked_cookie_data(env)
env["action_dispatch.request.unsigned_session_cookie"] ||= begin
stale_session_check! do
@@ -65,6 +79,12 @@ module ActionDispatch
end
end
+ def persistent_session_id!(data, sid=nil)
+ data ||= {}
+ data["session_id"] ||= sid || generate_sid
+ data
+ end
+
def set_session(env, sid, session_data, options)
session_data["session_id"] = sid
session_data
diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
index 2b37a8d026..fcc5bc12c4 100644
--- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb
@@ -16,9 +16,9 @@ module ActionDispatch
# catches the exceptions and returns a FAILSAFE_RESPONSE.
class ShowExceptions
FAILSAFE_RESPONSE = [500, { 'Content-Type' => 'text/plain' },
- ["500 Internal Server Error\n" <<
- "If you are the administrator of this website, then please read this web " <<
- "application's log file and/or the web server's log file to find out what " <<
+ ["500 Internal Server Error\n" \
+ "If you are the administrator of this website, then please read this web " \
+ "application's log file and/or the web server's log file to find out what " \
"went wrong."]]
def initialize(app, exceptions_app)
@@ -27,13 +27,10 @@ module ActionDispatch
end
def call(env)
- begin
- response = @app.call(env)
- rescue Exception => exception
- raise exception if env['action_dispatch.show_exceptions'] == false
- end
-
- response || render_exception(env, exception)
+ @app.call(env)
+ rescue Exception => exception
+ raise exception if env['action_dispatch.show_exceptions'] == false
+ render_exception(env, exception)
end
private
diff --git a/actionpack/lib/action_dispatch/middleware/ssl.rb b/actionpack/lib/action_dispatch/middleware/ssl.rb
index 9098f4e170..9e03cbf2b7 100644
--- a/actionpack/lib/action_dispatch/middleware/ssl.rb
+++ b/actionpack/lib/action_dispatch/middleware/ssl.rb
@@ -45,7 +45,7 @@ module ActionDispatch
# http://tools.ietf.org/html/draft-hodges-strict-transport-sec-02
def hsts_headers
if @hsts
- value = "max-age=#{@hsts[:expires]}"
+ value = "max-age=#{@hsts[:expires].to_i}"
value += "; includeSubDomains" if @hsts[:subdomains]
{ 'Strict-Transport-Security' => value }
else
diff --git a/actionpack/lib/action_dispatch/middleware/static.rb b/actionpack/lib/action_dispatch/middleware/static.rb
index e3b15b43b9..1c9512ad01 100644
--- a/actionpack/lib/action_dispatch/middleware/static.rb
+++ b/actionpack/lib/action_dispatch/middleware/static.rb
@@ -6,7 +6,7 @@ module ActionDispatch
def initialize(root, cache_control)
@root = root.chomp('/')
@compiled_root = /^#{Regexp.escape(root)}/
- @file_server = ::Rack::File.new(@root, cache_control)
+ @file_server = ::Rack::File.new(@root, 'Cache-Control' => cache_control)
end
def match?(path)
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb
index 823f5d25b6..ab24118f3e 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb
@@ -1,8 +1,8 @@
<% unless @exception.blamed_files.blank? %>
<% if (hide = @exception.blamed_files.length > 8) %>
- <a href="#" onclick="document.getElementById('blame_trace').style.display='block'; return false;">Show blamed files</a>
+ <a href="#" onclick="toggleTrace()">Toggle blamed files</a>
<% end %>
- <pre id="blame_trace" <%='style="display:none"' if hide %>><code><%=h @exception.describe_blame %></code></pre>
+ <pre id="blame_trace" <%='style="display:none"' if hide %>><code><%= @exception.describe_blame %></code></pre>
<% end %>
<%
@@ -18,14 +18,17 @@
%>
<h2 style="margin-top: 30px">Request</h2>
-<p><b>Parameters</b>: <pre><%=h request_dump %></pre></p>
+<p><b>Parameters</b>:</p> <pre><%= request_dump %></pre>
-<p><a href="#" onclick="document.getElementById('session_dump').style.display='block'; return false;">Show session dump</a></p>
-<div id="session_dump" style="display:none"><pre><%= debug_hash @request.session %></pre></div>
-
-<p><a href="#" onclick="document.getElementById('env_dump').style.display='block'; return false;">Show env dump</a></p>
-<div id="env_dump" style="display:none"><pre><%= debug_hash @request.env.slice(*@request.class::ENV_METHODS) %></pre></div>
+<div class="details">
+ <div class="summary"><a href="#" onclick="toggleSessionDump()">Toggle session dump</a></div>
+ <div id="session_dump" style="display:none"><pre><%= debug_hash @request.session %></pre></div>
+</div>
+<div class="details">
+ <div class="summary"><a href="#" onclick="toggleEnvDump()">Toggle env dump</a></div>
+ <div id="env_dump" style="display:none"><pre><%= debug_hash @request.env.slice(*@request.class::ENV_METHODS) %></pre></div>
+</div>
<h2 style="margin-top: 30px">Response</h2>
-<p><b>Headers</b>: <pre><%=h defined?(@response) ? @response.headers.inspect.gsub(',', ",\n") : 'None' %></pre></p>
+<p><b>Headers</b>:</p> <pre><%= defined?(@response) ? @response.headers.inspect.gsub(',', ",\n") : 'None' %></pre>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_source.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_source.erb
new file mode 100644
index 0000000000..38429cb78e
--- /dev/null
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_source.erb
@@ -0,0 +1,25 @@
+<% if @source_extract %>
+<div class="source">
+<div class="info">
+ Extracted source (around line <strong>#<%= @line_number %></strong>):
+</div>
+<div class="data">
+ <table cellpadding="0" cellspacing="0" class="lines">
+ <tr>
+ <td>
+ <pre class="line_numbers">
+ <% @source_extract.keys.each do |line_number| %>
+<span><%= line_number -%></span>
+ <% end %>
+ </pre>
+ </td>
+<td width="100%">
+<pre>
+<% @source_extract.each do |line, source| -%><div class="line<%= " active" if line == @line_number -%>"><%= source -%></div><% end -%>
+</pre>
+</td>
+ </tr>
+ </table>
+</div>
+</div>
+<% end %>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb
index 8771b5fd6d..9d947aea40 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/_trace.erb
@@ -12,15 +12,15 @@
<div id="traces">
<% names.each do |name| %>
<%
- show = "document.getElementById('#{name.gsub(/\s/, '-')}').style.display='block';"
- hide = (names - [name]).collect {|hide_name| "document.getElementById('#{hide_name.gsub(/\s/, '-')}').style.display='none';"}
+ show = "show('#{name.gsub(/\s/, '-')}');"
+ hide = (names - [name]).collect {|hide_name| "hide('#{hide_name.gsub(/\s/, '-')}');"}
%>
<a href="#" onclick="<%= hide.join %><%= show %>; return false;"><%= name %></a> <%= '|' unless names.last == name %>
<% end %>
<% traces.each do |name, trace| %>
<div id="<%= name.gsub(/\s/, '-') %>" style="display: <%= (name == "Application Trace") ? 'block' : 'none' %>;">
- <pre><code><%=h trace.join "\n" %></code></pre>
+ <pre><code><%= trace.join "\n" %></code></pre>
</div>
<% end %>
</div>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb
index c5043c5e7b..57a2940802 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb
@@ -1,10 +1,16 @@
-<h1>
- <%=h @exception.class.to_s %>
- <% if @request.parameters['controller'] %>
- in <%=h @request.parameters['controller'].camelize %>Controller<% if @request.parameters['action'] %>#<%=h @request.parameters['action'] %><% end %>
- <% end %>
-</h1>
-<pre><%=h @exception.message %></pre>
+<header>
+ <h1>
+ <%= @exception.class.to_s %>
+ <% if @request.parameters['controller'] %>
+ in <%= @request.parameters['controller'].camelize %>Controller<% if @request.parameters['action'] %>#<%= @request.parameters['action'] %><% end %>
+ <% end %>
+ </h1>
+</header>
-<%= render template: "rescues/_trace" %>
-<%= render template: "rescues/_request_and_response" %>
+<div id="container">
+ <h2><%= @exception.message %></h2>
+
+ <%= render template: "rescues/_source" %>
+ <%= render template: "rescues/_trace" %>
+ <%= render template: "rescues/_request_and_response" %>
+</div>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb
index 1a308707d1..9878c2747e 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/layout.erb
@@ -4,7 +4,11 @@
<meta charset="utf-8" />
<title>Action Controller: Exception caught</title>
<style>
- body { background-color: #fff; color: #333; }
+ body {
+ background-color: #FAFAFA;
+ color: #333;
+ margin: 0px;
+ }
body, p, ol, ul, td {
font-family: helvetica, verdana, arial, sans-serif;
@@ -13,16 +17,127 @@
}
pre {
- background-color: #eee;
- padding: 10px;
font-size: 11px;
white-space: pre-wrap;
}
- a { color: #000; }
+ pre.box {
+ border: 1px solid #EEE;
+ padding: 10px;
+ margin: 0px;
+ width: 958px;
+ }
+
+ header {
+ color: #F0F0F0;
+ background: #C52F24;
+ padding: 0.5em 1.5em;
+ }
+
+ h2 {
+ color: #C52F24;
+ line-height: 25px;
+ }
+
+ .details {
+ border: 1px solid #D0D0D0;
+ border-radius: 4px;
+ margin: 1em 0px;
+ display: block;
+ width: 978px;
+ }
+
+ .summary {
+ padding: 8px 15px;
+ border-bottom: 1px solid #D0D0D0;
+ display: block;
+ }
+
+ .details pre {
+ margin: 5px;
+ border: none;
+ }
+
+ #container {
+ box-sizing: border-box;
+ width: 100%;
+ padding: 0 1.5em;
+ }
+
+ .source * {
+ margin: 0px;
+ padding: 0px;
+ }
+
+ .source {
+ border: 1px solid #D9D9D9;
+ background: #ECECEC;
+ width: 978px;
+ }
+
+ .source pre {
+ padding: 10px 0px;
+ border: none;
+ }
+
+ .source .data {
+ font-size: 80%;
+ overflow: auto;
+ background-color: #FFF;
+ }
+
+ .info {
+ padding: 0.5em;
+ }
+
+ .source .data .line_numbers {
+ background-color: #ECECEC;
+ color: #AAA;
+ padding: 1em .5em;
+ border-right: 1px solid #DDD;
+ text-align: right;
+ }
+
+ .line {
+ padding-left: 10px;
+ }
+
+ .line:hover {
+ background-color: #F6F6F6;
+ }
+
+ .line.active {
+ background-color: #FFCCCC;
+ }
+
+ a { color: #980905; }
a:visited { color: #666; }
- a:hover { color: #fff; background-color:#000; }
+ a:hover { color: #C52F24; }
+
+ <%= yield :style %>
</style>
+
+ <script>
+ var toggle = function(id) {
+ var s = document.getElementById(id).style;
+ s.display = s.display == 'none' ? 'block' : 'none';
+ }
+ var show = function(id) {
+ document.getElementById(id).style.display = 'block';
+ }
+ var hide = function(id) {
+ document.getElementById(id).style.display = 'none';
+ }
+ var toggleTrace = function() {
+ toggle('blame_trace');
+ }
+ var toggleSessionDump = function() {
+ toggle('session_dump');
+ }
+ var toggleEnvDump = function() {
+ toggle('env_dump');
+ }
+ </script>
</head>
<body>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/missing_template.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/missing_template.erb
index dbfdf76947..ca14215946 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/missing_template.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/missing_template.erb
@@ -1,2 +1,7 @@
-<h1>Template is missing</h1>
-<p><%=h @exception.message %></p>
+<header>
+ <h1>Template is missing</h1>
+</header>
+
+<div id="container">
+ <h2><%= @exception.message %></h2>
+</div>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb
index 6c903d6a17..61690d3e50 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/routing_error.erb
@@ -1,25 +1,30 @@
-<h1>Routing Error</h1>
-<p><pre><%=h @exception.message %></pre></p>
-<% unless @exception.failures.empty? %>
- <p>
- <h2>Failure reasons:</h2>
- <ol>
- <% @exception.failures.each do |route, reason| %>
- <li><code><%=h route.inspect.gsub('\\', '') %></code> failed because <%=h reason.downcase %></li>
- <% end %>
- </ol>
- </p>
-<% end %>
-<%= render template: "rescues/_trace" %>
+<header>
+ <h1>Routing Error</h1>
+</header>
+<div id="container">
+ <h2><%= @exception.message %></h2>
+ <% unless @exception.failures.empty? %>
+ <p>
+ <h2>Failure reasons:</h2>
+ <ol>
+ <% @exception.failures.each do |route, reason| %>
+ <li><code><%= route.inspect.gsub('\\', '') %></code> failed because <%= reason.downcase %></li>
+ <% end %>
+ </ol>
+ </p>
+ <% end %>
-<h2>
- Routes
-</h2>
+ <%= render template: "rescues/_trace" %>
-<p>
- Routes match in priority from top to bottom
-</p>
+ <% if @routes_inspector %>
+ <h2>
+ Routes
+ </h2>
-<%= render layout: "routes/route_wrapper" do %>
- <%= render partial: "routes/route", collection: @routes %>
-<% end %>
+ <p>
+ Routes match in priority from top to bottom
+ </p>
+
+ <%= @routes_inspector.format(ActionDispatch::Routing::HtmlTableFormatter.new(self)) %>
+ <% end %>
+</div>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.erb
index a1b377f68c..63216ef7c5 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/template_error.erb
@@ -1,17 +1,43 @@
-<h1>
- <%=h @exception.original_exception.class.to_s %> in
- <%=h @request.parameters["controller"].capitalize if @request.parameters["controller"]%>#<%=h @request.parameters["action"] %>
-</h1>
+<% @source_extract = @exception.source_extract(0, :html) %>
+<header>
+ <h1>
+ <%= @exception.original_exception.class.to_s %> in
+ <%= @request.parameters["controller"].capitalize if @request.parameters["controller"]%>#<%= @request.parameters["action"] %>
+ </h1>
+</header>
-<p>
- Showing <i><%=h @exception.file_name %></i> where line <b>#<%=h @exception.line_number %></b> raised:
- <pre><code><%=h @exception.message %></code></pre>
-</p>
+<div id="container">
+ <p>
+ Showing <i><%= @exception.file_name %></i> where line <b>#<%= @exception.line_number %></b> raised:
+ </p>
+ <pre><code><%= @exception.message %></code></pre>
-<p>Extracted source (around line <b>#<%=h @exception.line_number %></b>):
-<pre><code><%=h @exception.source_extract %></code></pre></p>
+ <div class="source">
+ <div class="info">
+ <p>Extracted source (around line <strong>#<%= @exception.line_number %></strong>):</p>
+ </div>
+ <div class="data">
+ <table cellpadding="0" cellspacing="0" class="lines">
+ <tr>
+ <td>
+ <pre class="line_numbers">
+ <% @source_extract.keys.each do |line_number| %>
+<span><%= line_number -%></span>
+ <% end %>
+ </pre>
+ </td>
+<td width="100%">
+<pre>
+<% @source_extract.each do |line, source| -%><div class="line<%= " active" if line == @exception.line_number -%>"><%= source -%></div><% end -%>
+</pre>
+</td>
+ </tr>
+ </table>
+</div>
+</div>
-<p><%=h @exception.sub_template_message %></p>
+ <p><%= @exception.sub_template_message %></p>
-<%= render template: "rescues/_trace" %>
-<%= render template: "rescues/_request_and_response" %>
+ <%= render template: "rescues/_trace" %>
+ <%= render template: "rescues/_request_and_response" %>
+</div>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb b/actionpack/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb
index 683379da10..c1fbf67eed 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/rescues/unknown_action.erb
@@ -1,2 +1,6 @@
-<h1>Unknown action</h1>
-<p><%=h @exception.message %></p>
+<header>
+ <h1>Unknown action</h1>
+</header>
+<div id="container">
+ <h2><%= @exception.message %></h2>
+</div>
diff --git a/actionpack/lib/action_dispatch/middleware/templates/routes/_route_wrapper.html.erb b/actionpack/lib/action_dispatch/middleware/templates/routes/_table.html.erb
index dc17cb77ef..9026c4eeb2 100644
--- a/actionpack/lib/action_dispatch/middleware/templates/routes/_route_wrapper.html.erb
+++ b/actionpack/lib/action_dispatch/middleware/templates/routes/_table.html.erb
@@ -1,7 +1,7 @@
-<style type='text/css'>
- #route_table td {padding: 0 30px;}
- #route_table {margin: 0 auto 0;}
-</style>
+<% content_for :style do %>
+ #route_table td { padding: 0 30px; }
+ #route_table { margin: 0 auto 0; }
+<% end %>
<table id='route_table' class='route_table'>
<thead>
diff --git a/actionpack/lib/action_dispatch/routing/inspector.rb b/actionpack/lib/action_dispatch/routing/inspector.rb
index 8d7461ecc3..ea3e8357d4 100644
--- a/actionpack/lib/action_dispatch/routing/inspector.rb
+++ b/actionpack/lib/action_dispatch/routing/inspector.rb
@@ -61,32 +61,46 @@ module ActionDispatch
##
# This class is just used for displaying route information when someone
- # executes `rake routes`. People should not use this class.
+ # executes `rake routes` or looks at the RoutingError page.
+ # People should not use this class.
class RoutesInspector # :nodoc:
- def initialize
- @engines = Hash.new
+ def initialize(routes)
+ @engines = {}
+ @routes = routes
end
- def format(all_routes, filter = nil)
- if filter
- all_routes = all_routes.select{ |route| route.defaults[:controller] == filter }
+ def format(formatter, filter = nil)
+ routes_to_display = filter_routes(filter)
+
+ routes = collect_routes(routes_to_display)
+ formatter.section :application, 'Application routes', routes
+
+ @engines.each do |name, engine_routes|
+ formatter.section :engine, "Routes for #{name}", engine_routes
end
- routes = collect_routes(all_routes)
+ formatter.result
+ end
+
+ private
- formatted_routes(routes) +
- formatted_routes_for_engines
+ def filter_routes(filter)
+ if filter
+ @routes.select { |route| route.defaults[:controller] == filter }
+ else
+ @routes
+ end
end
def collect_routes(routes)
- routes = routes.collect do |route|
+ routes.collect do |route|
RouteWrapper.new(route)
end.reject do |route|
route.internal?
end.collect do |route|
collect_engine_routes(route)
- {:name => route.name, :verb => route.verb, :path => route.path, :reqs => route.reqs }
+ { name: route.name, verb: route.verb, path: route.path, reqs: route.reqs }
end
end
@@ -100,21 +114,49 @@ module ActionDispatch
@engines[name] = collect_routes(routes.routes)
end
end
+ end
- def formatted_routes_for_engines
- @engines.map do |name, routes|
- ["\nRoutes for #{name}:"] + formatted_routes(routes)
- end.flatten
+ class ConsoleFormatter
+ def initialize
+ @buffer = []
end
- def formatted_routes(routes)
- name_width = routes.map{ |r| r[:name].length }.max
- verb_width = routes.map{ |r| r[:verb].length }.max
- path_width = routes.map{ |r| r[:path].length }.max
+ def result
+ @buffer.join("\n")
+ end
- routes.map do |r|
- "#{r[:name].rjust(name_width)} #{r[:verb].ljust(verb_width)} #{r[:path].ljust(path_width)} #{r[:reqs]}"
+ def section(type, title, routes)
+ @buffer << "\n#{title}:" unless type == :application
+ @buffer << draw_section(routes)
+ end
+
+ private
+ def draw_section(routes)
+ name_width = routes.map { |r| r[:name].length }.max
+ verb_width = routes.map { |r| r[:verb].length }.max
+ path_width = routes.map { |r| r[:path].length }.max
+
+ routes.map do |r|
+ "#{r[:name].rjust(name_width)} #{r[:verb].ljust(verb_width)} #{r[:path].ljust(path_width)} #{r[:reqs]}"
+ end
end
+ end
+
+ class HtmlTableFormatter
+ def initialize(view)
+ @view = view
+ @buffer = []
+ end
+
+ def section(type, title, routes)
+ @buffer << %(<tr><th colspan="4">#{title}</th></tr>)
+ @buffer << @view.render(partial: "routes/route", collection: routes)
+ end
+
+ def result
+ @view.raw @view.render(layout: "routes/table") {
+ @view.raw @buffer.join("\n")
+ }
end
end
end
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index 3c99932e72..a21383e091 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -26,15 +26,10 @@ module ActionDispatch
def matches?(env)
req = @request.new(env)
- @constraints.each { |constraint|
- if constraint.respond_to?(:matches?) && !constraint.matches?(req)
- return false
- elsif constraint.respond_to?(:call) && !constraint.call(*constraint_args(constraint, req))
- return false
- end
- }
-
- return true
+ @constraints.none? do |constraint|
+ (constraint.respond_to?(:matches?) && !constraint.matches?(req)) ||
+ (constraint.respond_to?(:call) && !constraint.call(*constraint_args(constraint, req)))
+ end
ensure
req.reset_parameters
end
@@ -315,7 +310,7 @@ module ActionDispatch
# A pattern can also point to a +Rack+ endpoint i.e. anything that
# responds to +call+:
#
- # match 'photos/:id', to: lambda {|hash| [200, {}, "Coming soon"] }
+ # match 'photos/:id', to: lambda {|hash| [200, {}, ["Coming soon"]] }
# match 'photos/:id', to: PhotoRackApp
# # Yes, controller actions are just rack endpoints
# match 'photos/:id', to: PhotosController.action(:show)
@@ -360,7 +355,7 @@ module ActionDispatch
# +call+ or a string representing a controller's action.
#
# match 'path', to: 'controller#action'
- # match 'path', to: lambda { |env| [200, {}, "Success!"] }
+ # match 'path', to: lambda { |env| [200, {}, ["Success!"]] }
# match 'path', to: RackApp
#
# [:on]
diff --git a/actionpack/lib/action_dispatch/testing/assertions/dom.rb b/actionpack/lib/action_dispatch/testing/assertions/dom.rb
index 6c61d4e61a..8f90a1223e 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/dom.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/dom.rb
@@ -20,7 +20,7 @@ module ActionDispatch
def assert_dom_not_equal(expected, actual, message = "")
expected_dom = HTML::Document.new(expected).root
actual_dom = HTML::Document.new(actual).root
- refute_equal expected_dom, actual_dom
+ assert_not_equal expected_dom, actual_dom
end
end
end
diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
index 79dff7d121..9210bffd1d 100644
--- a/actionpack/lib/action_dispatch/testing/assertions/routing.rb
+++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb
@@ -1,5 +1,6 @@
require 'uri'
require 'active_support/core_ext/hash/indifferent_access'
+require 'active_support/core_ext/string/access'
require 'action_controller/metal/exceptions'
module ActionDispatch
@@ -208,11 +209,9 @@ module ActionDispatch
end
def fail_on(exception_class)
- begin
- yield
- rescue exception_class => e
- raise MiniTest::Assertion, e.message
- end
+ yield
+ rescue exception_class => e
+ raise MiniTest::Assertion, e.message
end
end
end
diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb
index 95cd89a166..1fc5933e98 100644
--- a/actionpack/lib/action_dispatch/testing/integration.rb
+++ b/actionpack/lib/action_dispatch/testing/integration.rb
@@ -491,9 +491,6 @@ module ActionDispatch
include ActionController::TemplateAssertions
include ActionDispatch::Routing::UrlFor
- # Use AD::IntegrationTest for acceptance tests
- register_spec_type(/(Acceptance|Integration) ?Test\z/i, self)
-
@@app = nil
def self.app
diff --git a/actionpack/lib/action_dispatch/testing/performance_test.rb b/actionpack/lib/action_dispatch/testing/performance_test.rb
deleted file mode 100644
index 13fe693c32..0000000000
--- a/actionpack/lib/action_dispatch/testing/performance_test.rb
+++ /dev/null
@@ -1,10 +0,0 @@
-require 'active_support/testing/performance'
-
-module ActionDispatch
- # An integration test that runs a code profiler on your test methods.
- # Profiling output for combinations of each test method, measurement, and
- # output format are written to your tmp/performance directory.
- class PerformanceTest < ActionDispatch::IntegrationTest
- include ActiveSupport::Testing::Performance
- end
-end
diff --git a/actionpack/lib/action_pack.rb b/actionpack/lib/action_pack.rb
index 39c7faf740..ad5acd8080 100644
--- a/actionpack/lib/action_pack.rb
+++ b/actionpack/lib/action_pack.rb
@@ -1,5 +1,5 @@
#--
-# Copyright (c) 2004-2012 David Heinemeier Hansson
+# Copyright (c) 2004-2013 David Heinemeier Hansson
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
diff --git a/actionpack/lib/action_view.rb b/actionpack/lib/action_view.rb
index 8bbf52382a..4aafbcb655 100644
--- a/actionpack/lib/action_view.rb
+++ b/actionpack/lib/action_view.rb
@@ -1,5 +1,5 @@
#--
-# Copyright (c) 2004-2012 David Heinemeier Hansson
+# Copyright (c) 2004-2013 David Heinemeier Hansson
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
diff --git a/actionpack/lib/action_view/base.rb b/actionpack/lib/action_view/base.rb
index 668515df59..08253de3f4 100644
--- a/actionpack/lib/action_view/base.rb
+++ b/actionpack/lib/action_view/base.rb
@@ -6,7 +6,7 @@ require 'action_view/log_subscriber'
module ActionView #:nodoc:
# = Action View Base
#
- # Action View templates can be written in several ways. If the template file has a <tt>.erb</tt> extension then it uses a mixture of ERb
+ # Action View templates can be written in several ways. If the template file has a <tt>.erb</tt> extension then it uses a mixture of ERB
# (included in Ruby) and HTML. If the template file has a <tt>.builder</tt> extension then Jim Weirich's Builder::XmlMarkup library is used.
#
# == ERB
diff --git a/actionpack/lib/action_view/digestor.rb b/actionpack/lib/action_view/digestor.rb
index f3f6b425a8..4507861dcc 100644
--- a/actionpack/lib/action_view/digestor.rb
+++ b/actionpack/lib/action_view/digestor.rb
@@ -24,16 +24,17 @@ module ActionView
@@cache = ThreadSafe::Cache.new
def self.digest(name, format, finder, options = {})
- @@cache["#{name}.#{format}"] ||= begin
+ cache_key = [name, format] + Array.wrap(options[:dependencies])
+ @@cache[cache_key.join('.')] ||= begin
klass = options[:partial] || name.include?("/_") ? PartialDigestor : Digestor
- klass.new(name, format, finder).digest
+ klass.new(name, format, finder, options).digest
end
end
- attr_reader :name, :format, :finder
+ attr_reader :name, :format, :finder, :options
- def initialize(name, format, finder)
- @name, @format, @finder = name, format, finder
+ def initialize(name, format, finder, options={})
+ @name, @format, @finder, @options = name, format, finder, options
end
def digest
@@ -81,9 +82,11 @@ module ActionView
end
def dependency_digest
- dependencies.collect do |template_name|
+ template_digests = dependencies.collect do |template_name|
Digestor.digest(template_name, format, finder, partial: true)
- end.join("-")
+ end
+
+ (template_digests + injected_dependencies).join("-")
end
def render_dependencies
@@ -105,6 +108,10 @@ module ActionView
def explicit_dependencies
source.scan(EXPLICIT_DEPENDENCY).flatten.uniq
end
+
+ def injected_dependencies
+ Array.wrap(options[:dependencies])
+ end
end
class PartialDigestor < Digestor # :nodoc:
diff --git a/actionpack/lib/action_view/helpers/cache_helper.rb b/actionpack/lib/action_view/helpers/cache_helper.rb
index 995aa10afb..8fc78ea7fb 100644
--- a/actionpack/lib/action_view/helpers/cache_helper.rb
+++ b/actionpack/lib/action_view/helpers/cache_helper.rb
@@ -167,7 +167,7 @@ module ActionView
if @virtual_path
[
*Array(name.is_a?(Hash) ? controller.url_for(name).split("://").last : name),
- Digestor.digest(@virtual_path, formats.last.to_sym, lookup_context)
+ Digestor.digest(@virtual_path, formats.last.to_sym, lookup_context, dependencies: view_cache_dependencies)
]
else
name
diff --git a/actionpack/lib/action_view/helpers/debug_helper.rb b/actionpack/lib/action_view/helpers/debug_helper.rb
index d361a69a92..34fc23ac1a 100644
--- a/actionpack/lib/action_view/helpers/debug_helper.rb
+++ b/actionpack/lib/action_view/helpers/debug_helper.rb
@@ -27,14 +27,12 @@ module ActionView
# new_record: true
# </pre>
def debug(object)
- begin
- Marshal::dump(object)
- object = ERB::Util.html_escape(object.to_yaml).gsub(" ", "&nbsp; ").html_safe
- content_tag(:pre, object, :class => "debug_dump")
- rescue Exception # errors from Marshal or YAML
- # Object couldn't be dumped, perhaps because of singleton methods -- this is the fallback
- content_tag(:code, object.to_yaml, :class => "debug_dump")
- end
+ Marshal::dump(object)
+ object = ERB::Util.html_escape(object.to_yaml).gsub(" ", "&nbsp; ").html_safe
+ content_tag(:pre, object, :class => "debug_dump")
+ rescue Exception # errors from Marshal or YAML
+ # Object couldn't be dumped, perhaps because of singleton methods -- this is the fallback
+ content_tag(:code, object.to_yaml, :class => "debug_dump")
end
end
end
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index 7e4f5fa65c..4a31de715d 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -84,7 +84,7 @@ module ActionView
#
# <form action="/people/256" class="edit_person" id="edit_person_256" method="post">
# <div style="margin:0;padding:0;display:inline">
- # <input name="_method" type="hidden" value="put" />
+ # <input name="_method" type="hidden" value="patch" />
# <input name="authenticity_token" type="hidden" value="NrOp5bsjoLRuK8IW5+dQEYjKGUJDe7TQoZVvq95Wteg=" />
# </div>
# <label for="person_first_name">First name</label>:
@@ -101,9 +101,9 @@ module ActionView
# and generate HTML accordingly.
#
# The controller would receive the form data again in <tt>params[:person]</tt>, ready to be
- # passed to <tt>Person#update_attributes</tt>:
+ # passed to <tt>Person#update</tt>:
#
- # if @person.update_attributes(params[:person])
+ # if @person.update(params[:person])
# # success
# else
# # error handling
@@ -242,7 +242,7 @@ module ActionView
#
# is then equivalent to something like:
#
- # <%= form_for @post, as: :post, url: post_path(@post), method: :put, html: { class: "edit_post", id: "edit_post_45" } do |f| %>
+ # <%= form_for @post, as: :post, url: post_path(@post), method: :patch, html: { class: "edit_post", id: "edit_post_45" } do |f| %>
# ...
# <% end %>
#
@@ -318,7 +318,7 @@ module ActionView
#
# <form action='http://www.example.com' method='post' data-remote='true'>
# <div style='margin:0;padding:0;display:inline'>
- # <input name='_method' type='hidden' value='put' />
+ # <input name='_method' type='hidden' value='patch' />
# </div>
# ...
# </form>
@@ -336,7 +336,7 @@ module ActionView
#
# <form action='http://www.example.com' method='post' data-behavior='autosave' name='go'>
# <div style='margin:0;padding:0;display:inline'>
- # <input name='_method' type='hidden' value='put' />
+ # <input name='_method' type='hidden' value='patch' />
# </div>
# ...
# </form>
@@ -388,9 +388,9 @@ module ActionView
# In many cases you will want to wrap the above in another helper, so you
# could do something like the following:
#
- # def labelled_form_for(record_or_name_or_array, *args, &proc)
+ # def labelled_form_for(record_or_name_or_array, *args, &block)
# options = args.extract_options!
- # form_for(record_or_name_or_array, *(args << options.merge(builder: LabellingFormBuilder)), &proc)
+ # form_for(record_or_name_or_array, *(args << options.merge(builder: LabellingFormBuilder)), &block)
# end
#
# If you don't need to attach a form to a model instance, then check out
@@ -412,10 +412,9 @@ module ActionView
# <%= form_for @invoice, url: external_url, authenticity_token: false do |f|
# ...
# <% end %>
- def form_for(record, options = {}, &proc)
+ def form_for(record, options = {}, &block)
raise ArgumentError, "Missing block" unless block_given?
-
- options[:html] ||= {}
+ html_options = options[:html] ||= {}
case record
when String, Symbol
@@ -428,17 +427,16 @@ module ActionView
apply_form_for_options!(record, object, options)
end
- options[:html][:data] = options.delete(:data) if options.has_key?(:data)
- options[:html][:remote] = options.delete(:remote) if options.has_key?(:remote)
- options[:html][:method] = options.delete(:method) if options.has_key?(:method)
- options[:html][:authenticity_token] = options.delete(:authenticity_token)
+ html_options[:data] = options.delete(:data) if options.has_key?(:data)
+ html_options[:remote] = options.delete(:remote) if options.has_key?(:remote)
+ html_options[:method] = options.delete(:method) if options.has_key?(:method)
+ html_options[:authenticity_token] = options.delete(:authenticity_token)
- builder = options[:parent_builder] = instantiate_builder(object_name, object, options)
- fields_for = fields_for(object_name, object, options, &proc)
- default_options = builder.multipart? ? { multipart: true } : {}
- default_options.merge!(options.delete(:html))
+ builder = instantiate_builder(object_name, object, options)
+ output = capture(builder, &block)
+ html_options[:multipart] = builder.multipart?
- form_tag(options.delete(:url) || {}, default_options) { fields_for }
+ form_tag(options[:url] || {}, html_options) { output }
end
def apply_form_for_options!(record, object, options) #:nodoc:
@@ -707,9 +705,7 @@ module ActionView
# to prevent fields_for from rendering it automatically.
def fields_for(record_name, record_object = nil, options = {}, &block)
builder = instantiate_builder(record_name, record_object, options)
- output = capture(builder, &block)
- output.concat builder.hidden_field(:id) if output && options[:hidden_field_id] && !builder.emitted_hidden_id?
- output
+ capture(builder, &block)
end
# Returns a label tag tailored for labelling an input field for a specified attribute (identified by +method+) on an object
@@ -897,7 +893,7 @@ module ActionView
# invoice the user unchecks its check box, no +paid+ parameter is sent. So,
# any mass-assignment idiom like
#
- # @invoice.update_attributes(params[:invoice])
+ # @invoice.update(params[:invoice])
#
# wouldn't update the flag.
#
@@ -1174,12 +1170,15 @@ module ActionView
attr_accessor :object_name, :object, :options
- attr_reader :multipart, :parent_builder, :index
+ attr_reader :multipart, :index
alias :multipart? :multipart
def multipart=(multipart)
@multipart = multipart
- parent_builder.multipart = multipart if parent_builder
+
+ if parent_builder = @options[:parent_builder]
+ parent_builder.multipart = multipart
+ end
end
def self._to_partial_path
@@ -1201,7 +1200,6 @@ module ActionView
@nested_child_index = {}
@object_name, @object, @template, @options = object_name, object, template, options
- @parent_builder = options[:parent_builder]
@default_options = @options ? @options.slice(:index, :namespace) : {}
if @object_name.to_s.match(/\[\]$/)
if object ||= @template.instance_variable_get("@#{Regexp.last_match.pre_match}") and object.respond_to?(:to_param)
@@ -1478,8 +1476,8 @@ module ActionView
def fields_for(record_name, record_object = nil, fields_options = {}, &block)
fields_options, record_object = record_object, nil if record_object.is_a?(Hash) && record_object.extractable_options?
fields_options[:builder] ||= options[:builder]
- fields_options[:parent_builder] = self
fields_options[:namespace] = options[:namespace]
+ fields_options[:parent_builder] = self
case record_name
when String, Symbol
@@ -1569,7 +1567,7 @@ module ActionView
# invoice the user unchecks its check box, no +paid+ parameter is sent. So,
# any mass-assignment idiom like
#
- # @invoice.update_attributes(params[:invoice])
+ # @invoice.update(params[:invoice])
#
# wouldn't update the flag.
#
@@ -1820,13 +1818,17 @@ module ActionView
end
end
- def fields_for_nested_model(name, object, options, block)
+ def fields_for_nested_model(name, object, fields_options, block)
object = convert_to_model(object)
+ emit_hidden_id = object.persisted? && fields_options.fetch(:include_id) {
+ options.fetch(:include_id, true)
+ }
- parent_include_id = self.options.fetch(:include_id, true)
- include_id = options.fetch(:include_id, parent_include_id)
- options[:hidden_field_id] = object.persisted? && include_id
- @template.fields_for(name, object, options, &block)
+ @template.fields_for(name, object, fields_options) do |f|
+ output = @template.capture(f, &block)
+ output.concat f.hidden_field(:id) if output && emit_hidden_id && !f.emitted_hidden_id?
+ output
+ end
end
def nested_child_index(name)
diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb
index 1b5b788a35..bcad05e033 100644
--- a/actionpack/lib/action_view/helpers/form_options_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_options_helper.rb
@@ -130,7 +130,7 @@ module ActionView
# the user deselects all roles from +role_ids+ multiple select box, no +role_ids+ parameter is sent. So,
# any mass-assignment idiom like
#
- # @user.update_attributes(params[:user])
+ # @user.update(params[:user])
#
# wouldn't update roles.
#
diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb
index ff83ef3ca1..86d9f94067 100644
--- a/actionpack/lib/action_view/helpers/form_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb
@@ -26,7 +26,7 @@ module ActionView
# ==== Options
# * <tt>:multipart</tt> - If set to true, the enctype is set to "multipart/form-data".
# * <tt>:method</tt> - The method to use when submitting the form, usually either "get" or "post".
- # If "put", "delete", or another verb is used, a hidden input with name <tt>_method</tt>
+ # If "patch", "put", "delete", or another verb is used, a hidden input with name <tt>_method</tt>
# is added to simulate the verb over post.
# * <tt>:authenticity_token</tt> - Authenticity token to use in the form. Use only if you need to
# pass custom authenticity token string, or to not add authenticity_token field at all
@@ -184,7 +184,7 @@ module ActionView
# # => <label for="name">Name</label>
#
# label_tag 'name', 'Your name'
- # # => <label for="name">Your Name</label>
+ # # => <label for="name">Your name</label>
#
# label_tag 'name', nil, class: 'small_label'
# # => <label for="name" class="small_label">Name</label>
@@ -526,19 +526,19 @@ module ActionView
#
# ==== Examples
# image_submit_tag("login.png")
- # # => <input src="/images/login.png" type="image" />
+ # # => <input alt="Login" src="/images/login.png" type="image" />
#
# image_submit_tag("purchase.png", disabled: true)
- # # => <input disabled="disabled" src="/images/purchase.png" type="image" />
+ # # => <input alt="Purchase" disabled="disabled" src="/images/purchase.png" type="image" />
#
- # image_submit_tag("search.png", class: 'search_button')
- # # => <input class="search_button" src="/images/search.png" type="image" />
+ # image_submit_tag("search.png", class: 'search_button', alt: 'Find')
+ # # => <input alt="Find" class="search_button" src="/images/search.png" type="image" />
#
# image_submit_tag("agree.png", disabled: true, class: "agree_disagree_button")
- # # => <input class="agree_disagree_button" disabled="disabled" src="/images/agree.png" type="image" />
+ # # => <input alt="Agree" class="agree_disagree_button" disabled="disabled" src="/images/agree.png" type="image" />
#
# image_submit_tag("save.png", data: { confirm: "Are you sure?" })
- # # => <input src="/images/save.png" data-confirm="Are you sure?" type="image" />
+ # # => <input alt="Save" src="/images/save.png" data-confirm="Are you sure?" type="image" />
def image_submit_tag(source, options = {})
options = options.stringify_keys
@@ -550,7 +550,7 @@ module ActionView
options["data-confirm"] = confirm
end
- tag :input, { "type" => "image", "src" => path_to_image(source) }.update(options)
+ tag :input, { "alt" => image_alt(source), "type" => "image", "src" => path_to_image(source) }.update(options)
end
# Creates a field set for grouping HTML form elements.
diff --git a/actionpack/lib/action_view/helpers/record_tag_helper.rb b/actionpack/lib/action_view/helpers/record_tag_helper.rb
index 33194250b7..271a194913 100644
--- a/actionpack/lib/action_view/helpers/record_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/record_tag_helper.rb
@@ -65,8 +65,8 @@ module ActionView
#
# produces:
#
- # <tr id="person_123" class="person">...</tr>
- # <tr id="person_124" class="person">...</tr>
+ # <tr id="person_123" class="person">...</tr>
+ # <tr id="person_124" class="person">...</tr>
#
# content_tag_for also accepts a hash of options, which will be converted to
# additional HTML attributes. If you specify a <tt>:class</tt> value, it will be combined
@@ -95,7 +95,11 @@ module ActionView
options[:class] = "#{dom_class(record, prefix)} #{options[:class]}".rstrip
options[:id] = dom_id(record, prefix)
- content_tag(tag_name, capture(record, &block), options)
+ if block_given?
+ content_tag(tag_name, capture(record, &block), options)
+ else
+ content_tag(tag_name, "", options)
+ end
end
end
end
diff --git a/actionpack/lib/action_view/helpers/tags/collection_check_boxes.rb b/actionpack/lib/action_view/helpers/tags/collection_check_boxes.rb
index 45f0bc3d7b..d27df45b5a 100644
--- a/actionpack/lib/action_view/helpers/tags/collection_check_boxes.rb
+++ b/actionpack/lib/action_view/helpers/tags/collection_check_boxes.rb
@@ -21,7 +21,7 @@ module ActionView
if block_given?
yield builder
else
- builder.check_box + builder.label
+ render_component(builder)
end
end
@@ -31,6 +31,12 @@ module ActionView
rendered_collection + hidden
end
+
+ private
+
+ def render_component(builder)
+ builder.check_box + builder.label
+ end
end
end
end
diff --git a/actionpack/lib/action_view/helpers/tags/collection_helpers.rb b/actionpack/lib/action_view/helpers/tags/collection_helpers.rb
index 4e33e79a36..e92a318c73 100644
--- a/actionpack/lib/action_view/helpers/tags/collection_helpers.rb
+++ b/actionpack/lib/action_view/helpers/tags/collection_helpers.rb
@@ -44,7 +44,8 @@ module ActionView
html_options = @html_options.dup
[:checked, :selected, :disabled].each do |option|
- next unless current_value = @options[option]
+ current_value = @options[option]
+ next if current_value.nil?
accept = if current_value.respond_to?(:call)
current_value.call(item)
diff --git a/actionpack/lib/action_view/helpers/tags/collection_radio_buttons.rb b/actionpack/lib/action_view/helpers/tags/collection_radio_buttons.rb
index ba2035f074..81f2ecb2b3 100644
--- a/actionpack/lib/action_view/helpers/tags/collection_radio_buttons.rb
+++ b/actionpack/lib/action_view/helpers/tags/collection_radio_buttons.rb
@@ -20,10 +20,16 @@ module ActionView
if block_given?
yield builder
else
- builder.radio_button + builder.label
+ render_component(builder)
end
end
end
+
+ private
+
+ def render_component(builder)
+ builder.radio_button + builder.label
+ end
end
end
end
diff --git a/actionpack/lib/action_view/helpers/text_helper.rb b/actionpack/lib/action_view/helpers/text_helper.rb
index 26d2142df9..2e124cf085 100644
--- a/actionpack/lib/action_view/helpers/text_helper.rb
+++ b/actionpack/lib/action_view/helpers/text_helper.rb
@@ -112,12 +112,12 @@ module ActionView
# highlight('You searched for: rails', 'rails', highlighter: '<a href="search?q=\1">\1</a>')
# # => You searched for: <a href="search?q=rails">rails</a>
def highlight(text, phrases, options = {})
- highlighter = options.fetch(:highlighter, '<mark>\1</mark>')
-
text = sanitize(text) if options.fetch(:sanitize, true)
+
if text.blank? || phrases.blank?
text
else
+ highlighter = options.fetch(:highlighter, '<mark>\1</mark>')
match = Array(phrases).map { |p| Regexp.escape(p) }.join('|')
text.gsub(/(#{match})(?![^<]*?>)/i, highlighter)
end.html_safe
diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb
index aeee662071..bade121d44 100644
--- a/actionpack/lib/action_view/helpers/url_helper.rb
+++ b/actionpack/lib/action_view/helpers/url_helper.rb
@@ -170,7 +170,7 @@ module ActionView
# You can also use custom data attributes using the <tt>:data</tt> option:
#
# link_to "Visit Other Site", "http://www.rubyonrails.org/", data: { confirm: "Are you sure?" }
- # # => <a href="http://www.rubyonrails.org/" data-confirm="Are you sure?"">Visit Other Site</a>
+ # # => <a href="http://www.rubyonrails.org/" data-confirm="Are you sure?">Visit Other Site</a>
def link_to(name = nil, options = nil, html_options = nil, &block)
html_options, options = options, name if block_given?
options ||= {}
diff --git a/actionpack/lib/action_view/record_identifier.rb b/actionpack/lib/action_view/record_identifier.rb
index 2953654972..63f645431a 100644
--- a/actionpack/lib/action_view/record_identifier.rb
+++ b/actionpack/lib/action_view/record_identifier.rb
@@ -17,7 +17,7 @@ module ActionView
# # controller
# def update
# post = Post.find(params[:id])
- # post.update_attributes(params[:post])
+ # post.update(params[:post])
#
# redirect_to(post) # Calls polymorphic_url(post) which in turn calls post_url(post)
# end
diff --git a/actionpack/lib/action_view/renderer/partial_renderer.rb b/actionpack/lib/action_view/renderer/partial_renderer.rb
index 37f93a13fc..43a88b0623 100644
--- a/actionpack/lib/action_view/renderer/partial_renderer.rb
+++ b/actionpack/lib/action_view/renderer/partial_renderer.rb
@@ -452,7 +452,7 @@ module ActionView
def retrieve_template_keys
keys = @locals.keys
- keys << @variable
+ keys << @variable if @object || @collection
keys << @variable_counter if @collection
keys
end
diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb
index aefc42be48..b927c69260 100644
--- a/actionpack/lib/action_view/template.rb
+++ b/actionpack/lib/action_view/template.rb
@@ -1,6 +1,5 @@
require 'active_support/core_ext/object/try'
require 'active_support/core_ext/kernel/singleton_class'
-require 'active_support/deprecation'
require 'thread'
module ActionView
diff --git a/actionpack/lib/action_view/template/error.rb b/actionpack/lib/action_view/template/error.rb
index e00056781d..b479f991bc 100644
--- a/actionpack/lib/action_view/template/error.rb
+++ b/actionpack/lib/action_view/template/error.rb
@@ -78,7 +78,7 @@ module ActionView
end
end
- def source_extract(indentation = 0)
+ def source_extract(indentation = 0, output = :console)
return unless num = line_number
num = num.to_i
@@ -88,13 +88,9 @@ module ActionView
end_on_line = [ num + SOURCE_CODE_RADIUS - 1, source_code.length].min
indent = end_on_line.to_s.size + indentation
- line_counter = start_on_line
return unless source_code = source_code[start_on_line..end_on_line]
- source_code.sum do |line|
- line_counter += 1
- "%#{indent}s: %s\n" % [line_counter, line]
- end
+ formatted_code_for(source_code, start_on_line, indent, output)
end
def sub_template_of(template_path)
@@ -123,6 +119,18 @@ module ActionView
'in '
end + file_name
end
+
+ def formatted_code_for(source_code, line_counter, indent, output)
+ start_value = (output == :html) ? {} : ""
+ source_code.inject(start_value) do |result, line|
+ line_counter += 1
+ if output == :html
+ result.update(line_counter.to_s => "%#{indent}s %s\n" % ["", line])
+ else
+ result << "%#{indent}s: %s\n" % [line_counter, line]
+ end
+ end
+ end
end
end
diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb
index 8b23029bbc..1a1083bf00 100644
--- a/actionpack/lib/action_view/template/resolver.rb
+++ b/actionpack/lib/action_view/template/resolver.rb
@@ -118,7 +118,7 @@ module ActionView
private
- delegate :caching?, :to => "self.class"
+ delegate :caching?, to: :class
# This is what child classes implement. No defaults are needed
# because Resolver guarantees that the arguments are present and
diff --git a/actionpack/lib/action_view/template/types.rb b/actionpack/lib/action_view/template/types.rb
index 7611c9e708..db77cb5d19 100644
--- a/actionpack/lib/action_view/template/types.rb
+++ b/actionpack/lib/action_view/template/types.rb
@@ -1,6 +1,5 @@
require 'set'
require 'active_support/core_ext/class/attribute_accessors'
-require 'active_support/core_ext/object/blank'
module ActionView
class Template
diff --git a/actionpack/lib/action_view/test_case.rb b/actionpack/lib/action_view/test_case.rb
index a548b44780..4479da5bc4 100644
--- a/actionpack/lib/action_view/test_case.rb
+++ b/actionpack/lib/action_view/test_case.rb
@@ -30,9 +30,6 @@ module ActionView
end
end
- # Use AV::TestCase for the base class for helpers and views
- register_spec_type(/(Helper|View)( ?Test)?\z/i, self)
-
module Behavior
extend ActiveSupport::Concern
diff --git a/actionpack/test/abstract/abstract_controller_test.rb b/actionpack/test/abstract/abstract_controller_test.rb
index 62f82a4c7a..eb9143c8f6 100644
--- a/actionpack/test/abstract/abstract_controller_test.rb
+++ b/actionpack/test/abstract/abstract_controller_test.rb
@@ -157,13 +157,11 @@ module AbstractController
private
def self.layout(formats)
+ find_template(name.underscore, {:formats => formats}, :_prefixes => ["layouts"])
+ rescue ActionView::MissingTemplate
begin
- find_template(name.underscore, {:formats => formats}, :_prefixes => ["layouts"])
+ find_template("application", {:formats => formats}, :_prefixes => ["layouts"])
rescue ActionView::MissingTemplate
- begin
- find_template("application", {:formats => formats}, :_prefixes => ["layouts"])
- rescue ActionView::MissingTemplate
- end
end
end
diff --git a/actionpack/test/abstract/helper_test.rb b/actionpack/test/abstract/helper_test.rb
index e79008fa9d..7960e5b55b 100644
--- a/actionpack/test/abstract/helper_test.rb
+++ b/actionpack/test/abstract/helper_test.rb
@@ -69,12 +69,10 @@ module AbstractController
end
def test_declare_missing_helper
- begin
- AbstractHelpers.helper :missing
- flunk "should have raised an exception"
- rescue LoadError => e
- assert_equal "helpers/missing_helper.rb", e.path
- end
+ AbstractHelpers.helper :missing
+ flunk "should have raised an exception"
+ rescue LoadError => e
+ assert_equal "helpers/missing_helper.rb", e.path
end
def test_helpers_with_module_through_block
diff --git a/actionpack/test/abstract_unit.rb b/actionpack/test/abstract_unit.rb
index 95bff0a204..bbcd289886 100644
--- a/actionpack/test/abstract_unit.rb
+++ b/actionpack/test/abstract_unit.rb
@@ -15,7 +15,7 @@ silence_warnings do
Encoding.default_external = "UTF-8"
end
-require 'minitest/autorun'
+require 'active_support/testing/autorun'
require 'abstract_controller'
require 'action_controller'
require 'action_view'
diff --git a/actionpack/test/controller/action_pack_assertions_test.rb b/actionpack/test/controller/action_pack_assertions_test.rb
index b94f45bfe7..5d727b3811 100644
--- a/actionpack/test/controller/action_pack_assertions_test.rb
+++ b/actionpack/test/controller/action_pack_assertions_test.rb
@@ -259,7 +259,7 @@ class ActionPackAssertionsControllerTest < ActionController::TestCase
def test_flash_exist
process :flash_me
assert flash.any?
- assert_present flash['hello']
+ assert flash['hello'].present?
end
def test_flash_does_not_exist
diff --git a/actionpack/test/controller/caching_test.rb b/actionpack/test/controller/caching_test.rb
index 2428cd7433..ca86837a2c 100644
--- a/actionpack/test/controller/caching_test.rb
+++ b/actionpack/test/controller/caching_test.rb
@@ -296,6 +296,24 @@ class CacheHelperOutputBufferTest < ActionController::TestCase
end
end
+class ViewCacheDependencyTest < ActionController::TestCase
+ class NoDependenciesController < ActionController::Base
+ end
+
+ class HasDependenciesController < ActionController::Base
+ view_cache_dependency { "trombone" }
+ view_cache_dependency { "flute" }
+ end
+
+ def test_view_cache_dependencies_are_empty_by_default
+ assert NoDependenciesController.new.view_cache_dependencies.empty?
+ end
+
+ def test_view_cache_dependencies_are_listed_in_declaration_order
+ assert_equal %w(trombone flute), HasDependenciesController.new.view_cache_dependencies
+ end
+end
+
class DeprecatedPageCacheExtensionTest < ActiveSupport::TestCase
def test_page_cache_extension_binds_default_static_extension
deprecation_behavior = ActiveSupport::Deprecation.behavior
diff --git a/actionpack/test/controller/filters_test.rb b/actionpack/test/controller/filters_test.rb
index 1c59dd5953..3b79161ad3 100644
--- a/actionpack/test/controller/filters_test.rb
+++ b/actionpack/test/controller/filters_test.rb
@@ -450,11 +450,9 @@ class FilterTest < ActionController::TestCase
class RescuingAroundFilterWithBlock
def around(controller)
- begin
- yield
- rescue ErrorToRescue => ex
- controller.__send__ :render, :text => "I rescued this: #{ex.inspect}"
- end
+ yield
+ rescue ErrorToRescue => ex
+ controller.__send__ :render, :text => "I rescued this: #{ex.inspect}"
end
end
diff --git a/actionpack/test/controller/http_token_authentication_test.rb b/actionpack/test/controller/http_token_authentication_test.rb
index faf923e929..ebf6d224aa 100644
--- a/actionpack/test/controller/http_token_authentication_test.rb
+++ b/actionpack/test/controller/http_token_authentication_test.rb
@@ -111,21 +111,21 @@ class HttpTokenAuthenticationTest < ActionController::TestCase
assert_equal(expected, actual)
end
- test "token_and_options returns correct token" do
+ test "token_and_options returns correct token with value after the equal sign" do
token = 'rcHu+=HzSFw89Ypyhn/896A==f34'
actual = ActionController::HttpAuthentication::Token.token_and_options(sample_request(token)).first
expected = token
assert_equal(expected, actual)
end
- test "token_and_options returns correct token" do
+ test "token_and_options returns correct token with slashes" do
token = 'rcHu+\\\\"/896A'
actual = ActionController::HttpAuthentication::Token.token_and_options(sample_request(token)).first
expected = token
assert_equal(expected, actual)
end
- test "token_and_options returns correct token" do
+ test "token_and_options returns correct token with quotes" do
token = '\"quote\" pretty'
actual = ActionController::HttpAuthentication::Token.token_and_options(sample_request(token)).first
expected = token
diff --git a/actionpack/test/controller/live_stream_test.rb b/actionpack/test/controller/live_stream_test.rb
index 20e433d1ec..3b1a07d7af 100644
--- a/actionpack/test/controller/live_stream_test.rb
+++ b/actionpack/test/controller/live_stream_test.rb
@@ -40,7 +40,7 @@ module ActionController
def thread_locals
tc.assert_equal 'aaron', Thread.current[:setting]
- tc.refute_equal Thread.current.object_id, Thread.current[:originating_thread]
+ tc.assert_not_equal Thread.current.object_id, Thread.current[:originating_thread]
response.headers['Content-Type'] = 'text/event-stream'
%w{ hello world }.each do |word|
diff --git a/actionpack/test/controller/output_escaping_test.rb b/actionpack/test/controller/output_escaping_test.rb
index f6913a2138..43a8c05cda 100644
--- a/actionpack/test/controller/output_escaping_test.rb
+++ b/actionpack/test/controller/output_escaping_test.rb
@@ -3,7 +3,7 @@ require 'abstract_unit'
class OutputEscapingTest < ActiveSupport::TestCase
test "escape_html shouldn't die when passed nil" do
- assert_blank ERB::Util.h(nil)
+ assert ERB::Util.h(nil).blank?
end
test "escapeHTML should escape strings" do
diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb
index 7640bc12a2..0e5bad7482 100644
--- a/actionpack/test/controller/render_test.rb
+++ b/actionpack/test/controller/render_test.rb
@@ -531,6 +531,10 @@ class TestController < ActionController::Base
head :created, :content_type => "application/json"
end
+ def head_ok_with_image_png_content_type
+ head :ok, :content_type => "image/png"
+ end
+
def head_with_location_header
head :location => "/foo"
end
@@ -789,15 +793,13 @@ class RenderTest < ActionController::TestCase
end
def test_line_offset
- begin
- get :render_line_offset
- flunk "the action should have raised an exception"
- rescue StandardError => exc
- line = exc.backtrace.first
- assert(line =~ %r{:(\d+):})
- assert_equal "1", $1,
- "The line offset is wrong, perhaps the wrong exception has been raised, exception was: #{exc.inspect}"
- end
+ get :render_line_offset
+ flunk "the action should have raised an exception"
+ rescue StandardError => exc
+ line = exc.backtrace.first
+ assert(line =~ %r{:(\d+):})
+ assert_equal "1", $1,
+ "The line offset is wrong, perhaps the wrong exception has been raised, exception was: #{exc.inspect}"
end
# :ported: compatibility
@@ -1217,20 +1219,27 @@ class RenderTest < ActionController::TestCase
def test_head_created
post :head_created
- assert_blank @response.body
+ assert @response.body.blank?
assert_response :created
end
def test_head_created_with_application_json_content_type
post :head_created_with_application_json_content_type
- assert_blank @response.body
- assert_equal "application/json", @response.content_type
+ assert @response.body.blank?
+ assert_equal "application/json", @response.header["Content-Type"]
assert_response :created
end
+ def test_head_ok_with_image_png_content_type
+ post :head_ok_with_image_png_content_type
+ assert @response.body.blank?
+ assert_equal "image/png", @response.header["Content-Type"]
+ assert_response :ok
+ end
+
def test_head_with_location_header
get :head_with_location_header
- assert_blank @response.body
+ assert @response.body.blank?
assert_equal "/foo", @response.headers["Location"]
assert_response :ok
end
@@ -1243,7 +1252,7 @@ class RenderTest < ActionController::TestCase
end
get :head_with_location_object
- assert_blank @response.body
+ assert @response.body.blank?
assert_equal "http://www.nextangle.com/customers/1", @response.headers["Location"]
assert_response :ok
end
@@ -1251,14 +1260,14 @@ class RenderTest < ActionController::TestCase
def test_head_with_custom_header
get :head_with_custom_header
- assert_blank @response.body
+ assert @response.body.blank?
assert_equal "something", @response.headers["X-Custom-Header"]
assert_response :ok
end
def test_head_with_www_authenticate_header
get :head_with_www_authenticate_header
- assert_blank @response.body
+ assert @response.body.blank?
assert_equal "something", @response.headers["WWW-Authenticate"]
assert_response :ok
end
@@ -1433,10 +1442,11 @@ class RenderTest < ActionController::TestCase
end
def test_locals_option_to_assert_template_is_not_supported
+ get :partial_collection_with_locals
+
warning_buffer = StringIO.new
$stderr = warning_buffer
- get :partial_collection_with_locals
assert_template partial: 'customer_greeting', locals: { greeting: 'Bonjour' }
assert_equal "the :locals option to #assert_template is only supported in a ActionView::TestCase\n", warning_buffer.string
ensure
@@ -1591,7 +1601,7 @@ class LastModifiedRenderTest < ActionController::TestCase
@request.if_modified_since = @last_modified
get :conditional_hello
assert_equal 304, @response.status.to_i
- assert_blank @response.body
+ assert @response.body.blank?
assert_equal @last_modified, @response.headers['Last-Modified']
end
@@ -1606,7 +1616,7 @@ class LastModifiedRenderTest < ActionController::TestCase
@request.if_modified_since = 'Thu, 16 Jul 2008 00:00:00 GMT'
get :conditional_hello
assert_equal 200, @response.status.to_i
- assert_present @response.body
+ assert @response.body.present?
assert_equal @last_modified, @response.headers['Last-Modified']
end
@@ -1620,7 +1630,7 @@ class LastModifiedRenderTest < ActionController::TestCase
@request.if_modified_since = @last_modified
get :conditional_hello_with_record
assert_equal 304, @response.status.to_i
- assert_blank @response.body
+ assert @response.body.blank?
assert_equal @last_modified, @response.headers['Last-Modified']
end
@@ -1635,7 +1645,7 @@ class LastModifiedRenderTest < ActionController::TestCase
@request.if_modified_since = 'Thu, 16 Jul 2008 00:00:00 GMT'
get :conditional_hello_with_record
assert_equal 200, @response.status.to_i
- assert_present @response.body
+ assert @response.body.present?
assert_equal @last_modified, @response.headers['Last-Modified']
end
diff --git a/actionpack/test/controller/request_forgery_protection_test.rb b/actionpack/test/controller/request_forgery_protection_test.rb
index 1f637eb791..523a8d0572 100644
--- a/actionpack/test/controller/request_forgery_protection_test.rb
+++ b/actionpack/test/controller/request_forgery_protection_test.rb
@@ -320,7 +320,7 @@ class FreeCookieControllerTest < ActionController::TestCase
test 'should not emit a csrf-token meta tag' do
get :meta
- assert_blank @response.body
+ assert @response.body.blank?
end
end
diff --git a/actionpack/test/controller/routing_test.rb b/actionpack/test/controller/routing_test.rb
index f0430e516f..5e821046db 100644
--- a/actionpack/test/controller/routing_test.rb
+++ b/actionpack/test/controller/routing_test.rb
@@ -57,13 +57,13 @@ class UriReservedCharactersRoutingTest < ActiveSupport::TestCase
end
class MockController
- def self.build(helpers)
+ def self.build(helpers, additional_options = {})
Class.new do
- def url_options
- options = super
+ define_method :url_options do
+ options = super()
options[:protocol] ||= "http"
options[:host] ||= "test.host"
- options
+ options.merge(additional_options)
end
include helpers
@@ -428,8 +428,8 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
routes.send(:pages_url)
end
- def setup_for_named_route
- MockController.build(rs.url_helpers).new
+ def setup_for_named_route(options = {})
+ MockController.build(rs.url_helpers, options).new
end
def test_named_route_without_hash
@@ -456,6 +456,16 @@ class LegacyRouteSetTests < ActiveSupport::TestCase
assert_equal("/", routes.send(:root_path))
end
+ def test_named_route_root_with_trailing_slash
+ rs.draw do
+ root "hello#index"
+ end
+
+ routes = setup_for_named_route(trailing_slash: true)
+ assert_equal("http://test.host/", routes.send(:root_url))
+ assert_equal("http://test.host/?foo=bar", routes.send(:root_url, foo: :bar))
+ end
+
def test_named_route_with_regexps
rs.draw do
get 'page/:year/:month/:day/:title' => 'page#show', :as => 'article',
diff --git a/actionpack/test/controller/spec_style_test.rb b/actionpack/test/controller/spec_style_test.rb
deleted file mode 100644
index e118c584ca..0000000000
--- a/actionpack/test/controller/spec_style_test.rb
+++ /dev/null
@@ -1,208 +0,0 @@
-require "abstract_unit"
-
-class ApplicationController < ActionController::Base; end
-class ModelsController < ApplicationController; end
-module Admin
- class WidgetsController < ApplicationController; end
-end
-
-# ApplicationController
-describe ApplicationController do
- describe "nested" do
- describe "even deeper" do
- it "exists" do
- assert_kind_of ApplicationController, @controller
- end
- end
- end
-end
-
-describe ApplicationController, :index do
- describe "nested" do
- describe "even deeper" do
- it "exists" do
- assert_kind_of ApplicationController, @controller
- end
- end
- end
-end
-
-describe ApplicationController, "unauthenticated user" do
- describe "nested" do
- describe "even deeper" do
- it "exists" do
- assert_kind_of ApplicationController, @controller
- end
- end
- end
-end
-
-describe "ApplicationControllerTest" do
- describe "nested" do
- describe "even deeper" do
- it "exists" do
- assert_kind_of ApplicationController, @controller
- end
- end
- end
-end
-
-describe "ApplicationControllerTest", :index do
- describe "nested" do
- describe "even deeper" do
- it "exists" do
- assert_kind_of ApplicationController, @controller
- end
- end
- end
-end
-
-describe "ApplicationControllerTest", "unauthenticated user" do
- describe "nested" do
- describe "even deeper" do
- it "exists" do
- assert_kind_of ApplicationController, @controller
- end
- end
- end
-end
-
-# ModelsController
-describe ModelsController do
- describe "nested" do
- describe "even deeper" do
- it "exists" do
- assert_kind_of ModelsController, @controller
- end
- end
- end
-end
-
-describe ModelsController, :index do
- describe "nested" do
- describe "even deeper" do
- it "exists" do
- assert_kind_of ModelsController, @controller
- end
- end
- end
-end
-
-describe ModelsController, "unauthenticated user" do
- describe "nested" do
- describe "even deeper" do
- it "exists" do
- assert_kind_of ModelsController, @controller
- end
- end
- end
-end
-
-describe "ModelsControllerTest" do
- describe "nested" do
- describe "even deeper" do
- it "exists" do
- assert_kind_of ModelsController, @controller
- end
- end
- end
-end
-
-describe "ModelsControllerTest", :index do
- describe "nested" do
- describe "even deeper" do
- it "exists" do
- assert_kind_of ModelsController, @controller
- end
- end
- end
-end
-
-describe "ModelsControllerTest", "unauthenticated user" do
- describe "nested" do
- describe "even deeper" do
- it "exists" do
- assert_kind_of ModelsController, @controller
- end
- end
- end
-end
-
-# Nested Admin::WidgetsControllerTest
-module Admin
- class WidgetsControllerTest < ActionController::TestCase
- test "exists" do
- assert_kind_of Admin::WidgetsController, @controller
- end
- end
-
- describe WidgetsController do
- describe "index" do
- it "respond successful" do
- assert_kind_of Admin::WidgetsController, @controller
- end
- end
- end
-
- describe WidgetsController, "unauthenticated users" do
- describe "index" do
- it "respond successful" do
- assert_kind_of Admin::WidgetsController, @controller
- end
- end
- end
-end
-
-class Admin::WidgetsControllerTest < ActionController::TestCase
- test "exists here too" do
- assert_kind_of Admin::WidgetsController, @controller
- end
-end
-
-describe Admin::WidgetsController do
- describe "index" do
- it "respond successful" do
- assert_kind_of Admin::WidgetsController, @controller
- end
- end
-end
-
-describe Admin::WidgetsController, "unauthenticated users" do
- describe "index" do
- it "respond successful" do
- assert_kind_of Admin::WidgetsController, @controller
- end
- end
-end
-
-describe "Admin::WidgetsController" do
- describe "index" do
- it "respond successful" do
- assert_kind_of Admin::WidgetsController, @controller
- end
- end
-end
-
-describe "Admin::WidgetsControllerTest" do
- describe "index" do
- it "respond successful" do
- assert_kind_of Admin::WidgetsController, @controller
- end
- end
-end
-
-describe "Admin::WidgetsController", "unauthenticated users" do
- describe "index" do
- it "respond successful" do
- assert_kind_of Admin::WidgetsController, @controller
- end
- end
-end
-
-describe "Admin::WidgetsControllerTest", "unauthenticated users" do
- describe "index" do
- it "respond successful" do
- assert_kind_of Admin::WidgetsController, @controller
- end
- end
-end
diff --git a/actionpack/test/controller/spec_type_test.rb b/actionpack/test/controller/spec_type_test.rb
deleted file mode 100644
index 13be8a3405..0000000000
--- a/actionpack/test/controller/spec_type_test.rb
+++ /dev/null
@@ -1,37 +0,0 @@
-require "abstract_unit"
-
-class ApplicationController < ActionController::Base; end
-class ModelsController < ApplicationController; end
-
-class ActionControllerSpecTypeTest < ActiveSupport::TestCase
- def assert_controller actual
- assert_equal ActionController::TestCase, actual
- end
-
- def refute_controller actual
- refute_equal ActionController::TestCase, actual
- end
-
- def test_spec_type_resolves_for_class_constants
- assert_controller MiniTest::Spec.spec_type(ApplicationController)
- assert_controller MiniTest::Spec.spec_type(ModelsController)
- end
-
- def test_spec_type_resolves_for_matching_strings
- assert_controller MiniTest::Spec.spec_type("WidgetController")
- assert_controller MiniTest::Spec.spec_type("WidgetControllerTest")
- assert_controller MiniTest::Spec.spec_type("Widget Controller Test")
- # And is not case sensitive
- assert_controller MiniTest::Spec.spec_type("widgetcontroller")
- assert_controller MiniTest::Spec.spec_type("widgetcontrollertest")
- assert_controller MiniTest::Spec.spec_type("widget controller test")
- end
-
- def test_spec_type_wont_match_non_space_characters
- refute_controller MiniTest::Spec.spec_type("Widget Controller\tTest")
- refute_controller MiniTest::Spec.spec_type("Widget Controller\rTest")
- refute_controller MiniTest::Spec.spec_type("Widget Controller\nTest")
- refute_controller MiniTest::Spec.spec_type("Widget Controller\fTest")
- refute_controller MiniTest::Spec.spec_type("Widget ControllerXTest")
- end
-end
diff --git a/actionpack/test/controller/test_case_test.rb b/actionpack/test/controller/test_case_test.rb
index bdca1d4d77..e4d78d58b9 100644
--- a/actionpack/test/controller/test_case_test.rb
+++ b/actionpack/test/controller/test_case_test.rb
@@ -692,7 +692,7 @@ XML
assert_equal "bar", @request.params[:foo]
@request.recycle!
post :no_op
- assert_blank @request.params[:foo]
+ assert @request.params[:foo].blank?
end
def test_symbolized_path_params_reset_after_request
diff --git a/actionpack/test/controller/url_for_test.rb b/actionpack/test/controller/url_for_test.rb
index d3fc7128e9..ba24e7fac5 100644
--- a/actionpack/test/controller/url_for_test.rb
+++ b/actionpack/test/controller/url_for_test.rb
@@ -2,7 +2,6 @@ require 'abstract_unit'
module AbstractController
module Testing
-
class UrlForTest < ActionController::TestCase
class W
include ActionDispatch::Routing::RouteSet.new.tap { |r| r.draw { get ':controller(/:action(/:id(.:format)))' } }.url_helpers
@@ -350,10 +349,10 @@ module AbstractController
def test_with_hash_with_indifferent_access
W.default_url_options[:controller] = 'd'
W.default_url_options[:only_path] = false
- assert_equal("/c", W.new.url_for(HashWithIndifferentAccess.new('controller' => 'c', 'only_path' => true)))
+ assert_equal("/c", W.new.url_for(ActiveSupport::HashWithIndifferentAccess.new('controller' => 'c', 'only_path' => true)))
W.default_url_options[:action] = 'b'
- assert_equal("/c/a", W.new.url_for(HashWithIndifferentAccess.new('controller' => 'c', 'action' => 'a', 'only_path' => true)))
+ assert_equal("/c/a", W.new.url_for(ActiveSupport::HashWithIndifferentAccess.new('controller' => 'c', 'action' => 'a', 'only_path' => true)))
end
def test_url_params_with_nil_to_param_are_not_in_url
diff --git a/actionpack/test/controller/webservice_test.rb b/actionpack/test/controller/webservice_test.rb
index c0b9833603..0480295056 100644
--- a/actionpack/test/controller/webservice_test.rb
+++ b/actionpack/test/controller/webservice_test.rb
@@ -116,22 +116,22 @@ class WebServiceTest < ActionDispatch::IntegrationTest
end
end
- def test_register_and_use_yaml
+ def test_post_xml_using_a_disallowed_type_attribute
+ $stderr = StringIO.new
with_test_route_set do
- with_params_parsers Mime::YAML => Proc.new { |d| YAML.load(d) } do
- post "/", {"entry" => "loaded from yaml"}.to_yaml,
- {'CONTENT_TYPE' => 'application/x-yaml'}
+ post '/', '<foo type="symbol">value</foo>', 'CONTENT_TYPE' => 'application/xml'
+ assert_response 500
- assert_equal 'entry', @controller.response.body
- assert @controller.params.has_key?(:entry)
- assert_equal 'loaded from yaml', @controller.params["entry"]
- end
+ post '/', '<foo type="yaml">value</foo>', 'CONTENT_TYPE' => 'application/xml'
+ assert_response 500
end
+ ensure
+ $stderr = STDERR
end
- def test_register_and_use_yaml_as_symbol
+ def test_register_and_use_yaml
with_test_route_set do
- with_params_parsers Mime::YAML => :yaml do
+ with_params_parsers Mime::YAML => Proc.new { |d| YAML.load(d) } do
post "/", {"entry" => "loaded from yaml"}.to_yaml,
{'CONTENT_TYPE' => 'application/x-yaml'}
@@ -211,36 +211,6 @@ class WebServiceTest < ActionDispatch::IntegrationTest
end
end
- def test_typecast_as_yaml
- with_test_route_set do
- with_params_parsers Mime::YAML => :yaml do
- yaml = (<<-YAML).strip
- ---
- data:
- a: 15
- b: false
- c: true
- d: 2005-03-17
- e: 2005-03-17T21:41:07Z
- f: unparsed
- g:
- - 1
- - hello
- - 1974-07-25
- YAML
- post "/", yaml, {'CONTENT_TYPE' => 'application/x-yaml'}
- params = @controller.params
- assert_equal 15, params[:data][:a]
- assert_equal false, params[:data][:b]
- assert_equal true, params[:data][:c]
- assert_equal Date.new(2005,3,17), params[:data][:d]
- assert_equal Time.utc(2005,3,17,21,41,7), params[:data][:e]
- assert_equal "unparsed", params[:data][:f]
- assert_equal [1, "hello", Date.new(1974,7,25)], params[:data][:g]
- end
- end
- end
-
private
def with_params_parsers(parsers = {})
old_session = @integration_session
diff --git a/actionpack/test/dispatch/debug_exceptions_test.rb b/actionpack/test/dispatch/debug_exceptions_test.rb
index d236b14e02..1319eba9ac 100644
--- a/actionpack/test/dispatch/debug_exceptions_test.rb
+++ b/actionpack/test/dispatch/debug_exceptions_test.rb
@@ -45,8 +45,17 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
end
end
- ProductionApp = ActionDispatch::DebugExceptions.new(Boomer.new(false))
- DevelopmentApp = ActionDispatch::DebugExceptions.new(Boomer.new(true))
+ def setup
+ app = ActiveSupport::OrderedOptions.new
+ app.config = ActiveSupport::OrderedOptions.new
+ app.config.assets = ActiveSupport::OrderedOptions.new
+ app.config.assets.prefix = '/sprockets'
+ Rails.stubs(:application).returns(app)
+ end
+
+ RoutesApp = Struct.new(:routes).new(SharedTestRoutes)
+ ProductionApp = ActionDispatch::DebugExceptions.new(Boomer.new(false), RoutesApp)
+ DevelopmentApp = ActionDispatch::DebugExceptions.new(Boomer.new(true), RoutesApp)
test 'skip diagnosis if not showing detailed exceptions' do
@app = ProductionApp
@@ -78,6 +87,15 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
assert boomer.closed, "Expected to close the response body"
end
+ test 'displays routes in a table when a RoutingError occurs' do
+ @app = DevelopmentApp
+ get "/pass", {}, {'action_dispatch.show_exceptions' => true}
+ routing_table = body[/route_table.*<.table>/m]
+ assert_match '/:controller(/:action)(.:format)', routing_table
+ assert_match ':controller#:action', routing_table
+ assert_no_match '&lt;|&gt;', routing_table, "there should not be escaped html in the output"
+ end
+
test "rescue with diagnostics message" do
@app = DevelopmentApp
@@ -135,7 +153,7 @@ class DebugExceptionsTest < ActionDispatch::IntegrationTest
}
})
assert_response 500
- assert_match(/RuntimeError\n in FeaturedTileController/, body)
+ assert_match(/RuntimeError\n\s+in FeaturedTileController/, body)
end
test "sets the HTTP charset parameter" do
diff --git a/actionpack/test/dispatch/live_response_test.rb b/actionpack/test/dispatch/live_response_test.rb
index e16f23914b..e0cfb73acf 100644
--- a/actionpack/test/dispatch/live_response_test.rb
+++ b/actionpack/test/dispatch/live_response_test.rb
@@ -11,7 +11,7 @@ module ActionController
def test_header_merge
header = @response.header.merge('Foo' => 'Bar')
assert_kind_of(ActionController::Live::Response::Header, header)
- refute_equal header, @response.header
+ assert_not_equal header, @response.header
end
def test_initialize_with_default_headers
diff --git a/actionpack/test/dispatch/request/json_params_parsing_test.rb b/actionpack/test/dispatch/request/json_params_parsing_test.rb
index c0c3147e37..7d3fc84089 100644
--- a/actionpack/test/dispatch/request/json_params_parsing_test.rb
+++ b/actionpack/test/dispatch/request/json_params_parsing_test.rb
@@ -30,6 +30,21 @@ class JsonParamsParsingTest < ActionDispatch::IntegrationTest
)
end
+ test "nils are stripped from collections" do
+ assert_parses(
+ {"person" => nil},
+ "{\"person\":[null]}", { 'CONTENT_TYPE' => 'application/json' }
+ )
+ assert_parses(
+ {"person" => ['foo']},
+ "{\"person\":[\"foo\",null]}", { 'CONTENT_TYPE' => 'application/json' }
+ )
+ assert_parses(
+ {"person" => nil},
+ "{\"person\":[null, null]}", { 'CONTENT_TYPE' => 'application/json' }
+ )
+ end
+
test "logs error if parsing unsuccessful" do
with_test_routing do
output = StringIO.new
@@ -107,6 +122,13 @@ class RootLessJSONParamsParsingTest < ActionDispatch::IntegrationTest
)
end
+ test "parses json with non-object JSON content" do
+ assert_parses(
+ {"user" => {"_json" => "string content" }, "_json" => "string content" },
+ "\"string content\"", { 'CONTENT_TYPE' => 'application/json' }
+ )
+ end
+
private
def assert_parses(expected, actual, headers = {})
with_test_routing(UsersController) do
diff --git a/actionpack/test/dispatch/request/query_string_parsing_test.rb b/actionpack/test/dispatch/request/query_string_parsing_test.rb
index 3cb430d83d..f072a9f717 100644
--- a/actionpack/test/dispatch/request/query_string_parsing_test.rb
+++ b/actionpack/test/dispatch/request/query_string_parsing_test.rb
@@ -84,8 +84,8 @@ class QueryStringParsingTest < ActionDispatch::IntegrationTest
assert_parses({"action" => nil}, "action")
assert_parses({"action" => {"foo" => nil}}, "action[foo]")
assert_parses({"action" => {"foo" => { "bar" => nil }}}, "action[foo][bar]")
- assert_parses({"action" => {"foo" => { "bar" => [] }}}, "action[foo][bar][]")
- assert_parses({"action" => {"foo" => []}}, "action[foo][]")
+ assert_parses({"action" => {"foo" => { "bar" => nil }}}, "action[foo][bar][]")
+ assert_parses({"action" => {"foo" => nil }}, "action[foo][]")
assert_parses({"action"=>{"foo"=>[{"bar"=>nil}]}}, "action[foo][][bar]")
end
diff --git a/actionpack/test/dispatch/request/session_test.rb b/actionpack/test/dispatch/request/session_test.rb
index 3f36d4f1a9..1517f96fdc 100644
--- a/actionpack/test/dispatch/request/session_test.rb
+++ b/actionpack/test/dispatch/request/session_test.rb
@@ -24,7 +24,7 @@ module ActionDispatch
s['foo'] = 'bar'
s1 = Session.create(store, env, {})
- refute_equal s, s1
+ assert_not_equal s, s1
assert_equal 'bar', s1['foo']
end
diff --git a/actionpack/test/dispatch/request/xml_params_parsing_test.rb b/actionpack/test/dispatch/request/xml_params_parsing_test.rb
index cb68667002..f13b64a3c7 100644
--- a/actionpack/test/dispatch/request/xml_params_parsing_test.rb
+++ b/actionpack/test/dispatch/request/xml_params_parsing_test.rb
@@ -30,6 +30,23 @@ class XmlParamsParsingTest < ActionDispatch::IntegrationTest
assert_equal "<ok>bar</ok>", resp.body
end
+ def assert_parses(expected, xml)
+ with_test_routing do
+ post "/parse", xml, default_headers
+ assert_response :ok
+ assert_equal(expected, TestController.last_request_parameters)
+ end
+ end
+
+ test "nils are stripped from collections" do
+ assert_parses(
+ {"hash" => { "person" => nil} },
+ "<hash><person type=\"array\"><person nil=\"true\"/></person></hash>")
+ assert_parses(
+ {"hash" => { "person" => ['foo']} },
+ "<hash><person type=\"array\"><person>foo</person><person nil=\"true\"/></person>\n</hash>")
+ end
+
test "parses hash params" do
with_test_routing do
xml = "<person><name>David</name></person>"
diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb
index 4e59e214c6..02675c7f8c 100644
--- a/actionpack/test/dispatch/request_test.rb
+++ b/actionpack/test/dispatch/request_test.rb
@@ -34,7 +34,7 @@ class RequestTest < ActiveSupport::TestCase
assert_equal '1.2.3.4', request.remote_ip
request = stub_request 'REMOTE_ADDR' => '1.2.3.4,3.4.5.6'
- assert_equal '1.2.3.4', request.remote_ip
+ assert_equal '3.4.5.6', request.remote_ip
request = stub_request 'REMOTE_ADDR' => '1.2.3.4',
'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
@@ -47,30 +47,32 @@ class RequestTest < ActiveSupport::TestCase
request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6,unknown'
assert_equal '3.4.5.6', request.remote_ip
- request = stub_request 'HTTP_X_FORWARDED_FOR' => '172.16.0.1,3.4.5.6'
- assert_equal nil, request.remote_ip
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6,172.16.0.1'
+ assert_equal '3.4.5.6', request.remote_ip
- request = stub_request 'HTTP_X_FORWARDED_FOR' => '192.168.0.1,3.4.5.6'
- assert_equal nil, request.remote_ip
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6,192.168.0.1'
+ assert_equal '3.4.5.6', request.remote_ip
- request = stub_request 'HTTP_X_FORWARDED_FOR' => '10.0.0.1,3.4.5.6'
- assert_equal nil, request.remote_ip
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6,10.0.0.1'
+ assert_equal '3.4.5.6', request.remote_ip
- request = stub_request 'HTTP_X_FORWARDED_FOR' => '10.0.0.1, 10.0.0.1, 3.4.5.6'
- assert_equal nil, request.remote_ip
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6, 10.0.0.1, 10.0.0.1'
+ assert_equal '3.4.5.6', request.remote_ip
- request = stub_request 'HTTP_X_FORWARDED_FOR' => '127.0.0.1,3.4.5.6'
- assert_equal nil, request.remote_ip
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6,127.0.0.1'
+ assert_equal '3.4.5.6', request.remote_ip
request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,192.168.0.1'
assert_equal nil, request.remote_ip
- request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6, 9.9.9.9, 10.0.0.1, 172.31.4.4'
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => '9.9.9.9, 3.4.5.6, 172.31.4.4, 10.0.0.1'
assert_equal '3.4.5.6', request.remote_ip
request = stub_request 'HTTP_X_FORWARDED_FOR' => 'not_ip_address'
assert_equal nil, request.remote_ip
+ end
+ test "remote ip spoof detection" do
request = stub_request 'HTTP_X_FORWARDED_FOR' => '1.1.1.1',
'HTTP_CLIENT_IP' => '2.2.2.2'
e = assert_raise(ActionDispatch::RemoteIp::IpSpoofAttackError) {
@@ -79,26 +81,20 @@ class RequestTest < ActiveSupport::TestCase
assert_match(/IP spoofing attack/, e.message)
assert_match(/HTTP_X_FORWARDED_FOR="1.1.1.1"/, e.message)
assert_match(/HTTP_CLIENT_IP="2.2.2.2"/, e.message)
+ end
- # turn IP Spoofing detection off.
- # This is useful for sites that are aimed at non-IP clients. The typical
- # example is WAP. Since the cellular network is not IP based, it's a
- # leap of faith to assume that their proxies are ever going to set the
- # HTTP_CLIENT_IP/HTTP_X_FORWARDED_FOR headers properly.
+ test "remote ip with spoof detection disabled" do
request = stub_request 'HTTP_X_FORWARDED_FOR' => '1.1.1.1',
'HTTP_CLIENT_IP' => '2.2.2.2',
:ip_spoofing_check => false
- assert_equal '2.2.2.2', request.remote_ip
-
- request = stub_request 'HTTP_X_FORWARDED_FOR' => '9.9.9.9, 8.8.8.8'
- assert_equal '9.9.9.9', request.remote_ip
+ assert_equal '1.1.1.1', request.remote_ip
end
test "remote ip v6" do
request = stub_request 'REMOTE_ADDR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334'
assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip
- request = stub_request 'REMOTE_ADDR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334,fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
+ request = stub_request 'REMOTE_ADDR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334'
assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip
request = stub_request 'REMOTE_ADDR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334',
@@ -109,30 +105,26 @@ class RequestTest < ActiveSupport::TestCase
'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip
- request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
- assert_equal nil, request.remote_ip
-
- request = stub_request 'HTTP_X_FORWARDED_FOR' => '::1,fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
- assert_equal nil, request.remote_ip
-
- request = stub_request 'HTTP_X_FORWARDED_FOR' => '::1,fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
- assert_equal nil, request.remote_ip
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329,unknown'
+ assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip
- request = stub_request 'HTTP_X_FORWARDED_FOR' => '::1,fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
- assert_equal nil, request.remote_ip
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329,::1'
+ assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip
- request = stub_request 'HTTP_X_FORWARDED_FOR' => '::1, ::1, fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
- assert_equal nil, request.remote_ip
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329, ::1, ::1'
+ assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip
request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,::1'
assert_equal nil, request.remote_ip
request = stub_request 'HTTP_X_FORWARDED_FOR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334, fe80:0000:0000:0000:0202:b3ff:fe1e:8329, ::1, fc00::'
- assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip
+ assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip
request = stub_request 'HTTP_X_FORWARDED_FOR' => 'not_ip_address'
assert_equal nil, request.remote_ip
+ end
+ test "remote ip v6 spoof detection" do
request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329',
'HTTP_CLIENT_IP' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334'
e = assert_raise(ActionDispatch::RemoteIp::IpSpoofAttackError) {
@@ -141,26 +133,15 @@ class RequestTest < ActiveSupport::TestCase
assert_match(/IP spoofing attack/, e.message)
assert_match(/HTTP_X_FORWARDED_FOR="fe80:0000:0000:0000:0202:b3ff:fe1e:8329"/, e.message)
assert_match(/HTTP_CLIENT_IP="2001:0db8:85a3:0000:0000:8a2e:0370:7334"/, e.message)
+ end
- # Turn IP Spoofing detection off.
- # This is useful for sites that are aimed at non-IP clients. The typical
- # example is WAP. Since the cellular network is not IP based, it's a
- # leap of faith to assume that their proxies are ever going to set the
- # HTTP_CLIENT_IP/HTTP_X_FORWARDED_FOR headers properly.
+ test "remote ip v6 spoof detection disabled" do
request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329',
'HTTP_CLIENT_IP' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334',
:ip_spoofing_check => false
- assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip
-
- request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329, 2001:0db8:85a3:0000:0000:8a2e:0370:7334'
assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip
end
- test "remote ip when the remote ip middleware returns nil" do
- request = stub_request 'REMOTE_ADDR' => '127.0.0.1'
- assert_equal '127.0.0.1', request.remote_ip
- end
-
test "remote ip with user specified trusted proxies String" do
@trusted_proxies = "67.205.106.73"
@@ -170,16 +151,16 @@ class RequestTest < ActiveSupport::TestCase
request = stub_request 'REMOTE_ADDR' => '172.16.0.1,67.205.106.73',
'HTTP_X_FORWARDED_FOR' => '67.205.106.73'
- assert_equal '172.16.0.1', request.remote_ip
+ assert_equal '67.205.106.73', request.remote_ip
request = stub_request 'REMOTE_ADDR' => '67.205.106.73,3.4.5.6',
'HTTP_X_FORWARDED_FOR' => '67.205.106.73'
assert_equal '3.4.5.6', request.remote_ip
- request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,67.205.106.73'
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => '67.205.106.73,unknown'
assert_equal nil, request.remote_ip
- request = stub_request 'HTTP_X_FORWARDED_FOR' => '3.4.5.6, 9.9.9.9, 10.0.0.1, 67.205.106.73'
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => '9.9.9.9, 3.4.5.6, 10.0.0.1, 67.205.106.73'
assert_equal '3.4.5.6', request.remote_ip
end
@@ -196,13 +177,13 @@ class RequestTest < ActiveSupport::TestCase
request = stub_request 'REMOTE_ADDR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329,::1',
'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
- assert_equal 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329', request.remote_ip
+ assert_equal '::1', request.remote_ip
request = stub_request 'HTTP_X_FORWARDED_FOR' => 'unknown,fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
assert_equal nil, request.remote_ip
request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329,2001:0db8:85a3:0000:0000:8a2e:0370:7334'
- assert_equal nil, request.remote_ip
+ assert_equal "2001:0db8:85a3:0000:0000:8a2e:0370:7334", request.remote_ip
end
test "remote ip with user specified trusted proxies Regexp" do
@@ -212,8 +193,8 @@ class RequestTest < ActiveSupport::TestCase
'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
assert_equal '3.4.5.6', request.remote_ip
- request = stub_request 'HTTP_X_FORWARDED_FOR' => '67.205.106.73, 10.0.0.1, 9.9.9.9, 3.4.5.6'
- assert_equal nil, request.remote_ip
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => '10.0.0.1, 9.9.9.9, 3.4.5.6, 67.205.106.73'
+ assert_equal '3.4.5.6', request.remote_ip
end
test "remote ip v6 with user specified trusted proxies Regexp" do
@@ -223,8 +204,13 @@ class RequestTest < ActiveSupport::TestCase
'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip
- request = stub_request 'HTTP_X_FORWARDED_FOR' => 'fe80:0000:0000:0000:0202:b3ff:fe1e:8329, 2001:0db8:85a3:0000:0000:8a2e:0370:7334'
- assert_equal nil, request.remote_ip
+ request = stub_request 'HTTP_X_FORWARDED_FOR' => '2001:0db8:85a3:0000:0000:8a2e:0370:7334, fe80:0000:0000:0000:0202:b3ff:fe1e:8329'
+ assert_equal '2001:0db8:85a3:0000:0000:8a2e:0370:7334', request.remote_ip
+ end
+
+ test "remote ip middleware not present still returns an IP" do
+ request = ActionDispatch::Request.new({'REMOTE_ADDR' => '127.0.0.1'})
+ assert_equal '127.0.0.1', request.remote_ip
end
test "domains" do
@@ -602,7 +588,7 @@ class RequestTest < ActiveSupport::TestCase
assert_equal request.format.xml?, false
assert_equal request.format.json?, false
end
-
+
test "formats with xhr request" do
request = stub_request 'HTTP_X_REQUESTED_WITH' => "XMLHttpRequest"
request.expects(:parameters).at_least_once.returns({})
diff --git a/actionpack/test/dispatch/routing/inspector_test.rb b/actionpack/test/dispatch/routing/inspector_test.rb
index a3034ce001..c7dcb5a683 100644
--- a/actionpack/test/dispatch/routing/inspector_test.rb
+++ b/actionpack/test/dispatch/routing/inspector_test.rb
@@ -1,5 +1,4 @@
-require 'minitest/autorun'
-require 'action_controller'
+require 'abstract_unit'
require 'rails/engine'
require 'action_dispatch/routing/inspector'
@@ -8,7 +7,6 @@ module ActionDispatch
class RoutesInspectorTest < ActiveSupport::TestCase
def setup
@set = ActionDispatch::Routing::RouteSet.new
- @inspector = ActionDispatch::Routing::RoutesInspector.new
app = ActiveSupport::OrderedOptions.new
app.config = ActiveSupport::OrderedOptions.new
app.config.assets = ActiveSupport::OrderedOptions.new
@@ -17,9 +15,10 @@ module ActionDispatch
Rails.stubs(:env).returns("development")
end
- def draw(&block)
+ def draw(options = {}, &block)
@set.draw(&block)
- @inspector.format(@set.routes)
+ inspector = ActionDispatch::Routing::RoutesInspector.new(@set.routes)
+ inspector.format(ActionDispatch::Routing::ConsoleFormatter.new, options[:filter]).split("\n")
end
def test_displaying_routes_for_engines
@@ -40,7 +39,8 @@ module ActionDispatch
expected = [
"custom_assets GET /custom/assets(.:format) custom_assets#show",
" blog /blog Blog::Engine",
- "\nRoutes for Blog::Engine:",
+ "",
+ "Routes for Blog::Engine:",
"cart GET /cart(.:format) cart#show"
]
assert_equal expected, output
@@ -165,6 +165,22 @@ module ActionDispatch
assert_equal " bar GET /bar(.:format) redirect(307, path: /foo/bar)", output[1]
assert_equal "foobar GET /foobar(.:format) redirect(301)", output[2]
end
+
+ def test_routes_can_be_filtered
+ output = draw(filter: 'posts') do
+ resources :articles
+ resources :posts
+ end
+
+ assert_equal [" posts GET /posts(.:format) posts#index",
+ " POST /posts(.:format) posts#create",
+ " new_post GET /posts/new(.:format) posts#new",
+ "edit_post GET /posts/:id/edit(.:format) posts#edit",
+ " post GET /posts/:id(.:format) posts#show",
+ " PATCH /posts/:id(.:format) posts#update",
+ " PUT /posts/:id(.:format) posts#update",
+ " DELETE /posts/:id(.:format) posts#destroy"], output
+ end
end
end
end
diff --git a/actionpack/test/dispatch/session/abstract_store_test.rb b/actionpack/test/dispatch/session/abstract_store_test.rb
index 8daf3d3f5e..fe1a7b4f86 100644
--- a/actionpack/test/dispatch/session/abstract_store_test.rb
+++ b/actionpack/test/dispatch/session/abstract_store_test.rb
@@ -42,7 +42,7 @@ module ActionDispatch
as.call(@env)
session1 = Request::Session.find @env
- refute_equal session, session1
+ assert_not_equal session, session1
assert_equal session.to_hash, session1.to_hash
end
diff --git a/actionpack/test/dispatch/spec_type_test.rb b/actionpack/test/dispatch/spec_type_test.rb
deleted file mode 100644
index 6cd19fd333..0000000000
--- a/actionpack/test/dispatch/spec_type_test.rb
+++ /dev/null
@@ -1,41 +0,0 @@
-require "abstract_unit"
-
-class SpecTypeTest < ActiveSupport::TestCase
- def assert_dispatch actual
- assert_equal ActionDispatch::IntegrationTest, actual
- end
-
- def refute_dispatch actual
- refute_equal ActionDispatch::IntegrationTest, actual
- end
-
- def test_spec_type_resolves_for_matching_acceptance_strings
- assert_dispatch MiniTest::Spec.spec_type("WidgetAcceptanceTest")
- assert_dispatch MiniTest::Spec.spec_type("Widget Acceptance Test")
- assert_dispatch MiniTest::Spec.spec_type("widgetacceptancetest")
- assert_dispatch MiniTest::Spec.spec_type("widget acceptance test")
- end
-
- def test_spec_type_wont_match_non_space_characters_acceptance
- refute_dispatch MiniTest::Spec.spec_type("Widget Acceptance\tTest")
- refute_dispatch MiniTest::Spec.spec_type("Widget Acceptance\rTest")
- refute_dispatch MiniTest::Spec.spec_type("Widget Acceptance\nTest")
- refute_dispatch MiniTest::Spec.spec_type("Widget Acceptance\fTest")
- refute_dispatch MiniTest::Spec.spec_type("Widget AcceptanceXTest")
- end
-
- def test_spec_type_resolves_for_matching_integration_strings
- assert_dispatch MiniTest::Spec.spec_type("WidgetIntegrationTest")
- assert_dispatch MiniTest::Spec.spec_type("Widget Integration Test")
- assert_dispatch MiniTest::Spec.spec_type("widgetintegrationtest")
- assert_dispatch MiniTest::Spec.spec_type("widget integration test")
- end
-
- def test_spec_type_wont_match_non_space_characters_integration
- refute_dispatch MiniTest::Spec.spec_type("Widget Integration\tTest")
- refute_dispatch MiniTest::Spec.spec_type("Widget Integration\rTest")
- refute_dispatch MiniTest::Spec.spec_type("Widget Integration\nTest")
- refute_dispatch MiniTest::Spec.spec_type("Widget Integration\fTest")
- refute_dispatch MiniTest::Spec.spec_type("Widget IntegrationXTest")
- end
-end
diff --git a/actionpack/test/dispatch/ssl_test.rb b/actionpack/test/dispatch/ssl_test.rb
index 6f075a9074..a9bea7ea73 100644
--- a/actionpack/test/dispatch/ssl_test.rb
+++ b/actionpack/test/dispatch/ssl_test.rb
@@ -47,7 +47,7 @@ class SSLTest < ActionDispatch::IntegrationTest
def test_disable_hsts_header
self.app = ActionDispatch::SSL.new(default_app, :hsts => false)
get "https://example.org/"
- refute response.headers['Strict-Transport-Security']
+ assert_not response.headers['Strict-Transport-Security']
end
def test_hsts_expires
@@ -57,6 +57,13 @@ class SSLTest < ActionDispatch::IntegrationTest
response.headers['Strict-Transport-Security']
end
+ def test_hsts_expires_with_duration
+ self.app = ActionDispatch::SSL.new(default_app, :hsts => { :expires => 1.year })
+ get "https://example.org/"
+ assert_equal "max-age=31557600",
+ response.headers['Strict-Transport-Security']
+ end
+
def test_hsts_include_subdomains
self.app = ActionDispatch::SSL.new(default_app, :hsts => { :subdomains => true })
get "https://example.org/"
diff --git a/actionpack/test/fixtures/test/_partial_name_local_variable.erb b/actionpack/test/fixtures/test/_partial_name_local_variable.erb
new file mode 100644
index 0000000000..cc3a91c89f
--- /dev/null
+++ b/actionpack/test/fixtures/test/_partial_name_local_variable.erb
@@ -0,0 +1 @@
+<%= partial_name_local_variable %>
diff --git a/actionpack/test/journey/gtg/builder_test.rb b/actionpack/test/journey/gtg/builder_test.rb
index a633c3eea6..c1da374007 100644
--- a/actionpack/test/journey/gtg/builder_test.rb
+++ b/actionpack/test/journey/gtg/builder_test.rb
@@ -3,7 +3,7 @@ require 'abstract_unit'
module ActionDispatch
module Journey
module GTG
- class TestBuilder < MiniTest::Unit::TestCase
+ class TestBuilder < ActiveSupport::TestCase
def test_following_states_multi
table = tt ['a|a']
assert_equal 1, table.move([0], 'a').length
diff --git a/actionpack/test/journey/gtg/transition_table_test.rb b/actionpack/test/journey/gtg/transition_table_test.rb
index 6d81b72c41..33acba8b65 100644
--- a/actionpack/test/journey/gtg/transition_table_test.rb
+++ b/actionpack/test/journey/gtg/transition_table_test.rb
@@ -4,7 +4,7 @@ require 'json'
module ActionDispatch
module Journey
module GTG
- class TestGeneralizedTable < MiniTest::Unit::TestCase
+ class TestGeneralizedTable < ActiveSupport::TestCase
def test_to_json
table = tt %w{
/articles(.:format)
@@ -29,7 +29,7 @@ module ActionDispatch
}
svg = table.to_svg
assert svg
- refute_match(/DOCTYPE/, svg)
+ assert_no_match(/DOCTYPE/, svg)
end
end
@@ -53,7 +53,7 @@ module ActionDispatch
sim = simulator_for ['/foo(/bar)']
assert_match sim, '/foo'
assert_match sim, '/foo/bar'
- refute_match sim, '/foo/'
+ assert_no_match sim, '/foo/'
end
def test_match_data
diff --git a/actionpack/test/journey/nfa/simulator_test.rb b/actionpack/test/journey/nfa/simulator_test.rb
index 9f89329b57..673a491fe5 100644
--- a/actionpack/test/journey/nfa/simulator_test.rb
+++ b/actionpack/test/journey/nfa/simulator_test.rb
@@ -3,7 +3,7 @@ require 'abstract_unit'
module ActionDispatch
module Journey
module NFA
- class TestSimulator < MiniTest::Unit::TestCase
+ class TestSimulator < ActiveSupport::TestCase
def test_simulate_simple
sim = simulator_for ['/foo']
assert_match sim, '/foo'
@@ -11,17 +11,17 @@ module ActionDispatch
def test_simulate_simple_no_match
sim = simulator_for ['/foo']
- refute_match sim, 'foo'
+ assert_no_match sim, 'foo'
end
def test_simulate_simple_no_match_too_long
sim = simulator_for ['/foo']
- refute_match sim, '/foo/bar'
+ assert_no_match sim, '/foo/bar'
end
def test_simulate_simple_no_match_wrong_string
sim = simulator_for ['/foo']
- refute_match sim, '/bar'
+ assert_no_match sim, '/bar'
end
def test_simulate_regex
@@ -34,14 +34,14 @@ module ActionDispatch
sim = simulator_for ['/foo', '/bar']
assert_match sim, '/bar'
assert_match sim, '/foo'
- refute_match sim, '/baz'
+ assert_no_match sim, '/baz'
end
def test_simulate_optional
sim = simulator_for ['/foo(/bar)']
assert_match sim, '/foo'
assert_match sim, '/foo/bar'
- refute_match sim, '/foo/'
+ assert_no_match sim, '/foo/'
end
def test_matchdata_has_memos
diff --git a/actionpack/test/journey/nfa/transition_table_test.rb b/actionpack/test/journey/nfa/transition_table_test.rb
index 72cefe42bf..1248082c03 100644
--- a/actionpack/test/journey/nfa/transition_table_test.rb
+++ b/actionpack/test/journey/nfa/transition_table_test.rb
@@ -3,7 +3,7 @@ require 'abstract_unit'
module ActionDispatch
module Journey
module NFA
- class TestTransitionTable < MiniTest::Unit::TestCase
+ class TestTransitionTable < ActiveSupport::TestCase
def setup
@parser = Journey::Parser.new
end
diff --git a/actionpack/test/journey/nodes/symbol_test.rb b/actionpack/test/journey/nodes/symbol_test.rb
index f53840274a..d411a5018a 100644
--- a/actionpack/test/journey/nodes/symbol_test.rb
+++ b/actionpack/test/journey/nodes/symbol_test.rb
@@ -3,13 +3,13 @@ require 'abstract_unit'
module ActionDispatch
module Journey
module Nodes
- class TestSymbol < MiniTest::Unit::TestCase
+ class TestSymbol < ActiveSupport::TestCase
def test_default_regexp?
sym = Symbol.new nil
assert sym.default_regexp?
sym.regexp = nil
- refute sym.default_regexp?
+ assert_not sym.default_regexp?
end
end
end
diff --git a/actionpack/test/journey/path/pattern_test.rb b/actionpack/test/journey/path/pattern_test.rb
index 0f2d0d44c0..2b7227cd0d 100644
--- a/actionpack/test/journey/path/pattern_test.rb
+++ b/actionpack/test/journey/path/pattern_test.rb
@@ -3,7 +3,7 @@ require 'abstract_unit'
module ActionDispatch
module Journey
module Path
- class TestPattern < MiniTest::Unit::TestCase
+ class TestPattern < ActiveSupport::TestCase
x = /.+/
{
'/:controller(/:action)' => %r{\A/(#{x})(?:/([^/.?]+))?\Z},
@@ -88,7 +88,7 @@ module ActionDispatch
path = Pattern.new strexp
assert_match(path, '/page/tender')
assert_match(path, '/page/love')
- refute_match(path, '/page/loving')
+ assert_no_match(path, '/page/loving')
end
def test_optional_names
@@ -110,7 +110,7 @@ module ActionDispatch
)
path = Pattern.new strexp
assert_match(path, '/123')
- refute_match(path, '/')
+ assert_no_match(path, '/')
end
def test_to_regexp_with_group
@@ -122,7 +122,7 @@ module ActionDispatch
path = Pattern.new strexp
assert_match(path, '/page/tender')
assert_match(path, '/page/love')
- refute_match(path, '/page/loving')
+ assert_no_match(path, '/page/loving')
end
def test_ast_sets_regular_expressions
@@ -189,7 +189,7 @@ module ActionDispatch
path = Pattern.new strexp
assert_match(path, '/page/TENDER/aaron')
assert_match(path, '/page/loVE/aaron')
- refute_match(path, '/page/loVE/AAron')
+ assert_no_match(path, '/page/loVE/AAron')
end
def test_to_regexp_with_strexp
@@ -210,7 +210,7 @@ module ActionDispatch
path = Pattern.new '/:controller(/:action(/:id(.:format)))'
uri = 'content'
- refute path =~ uri
+ assert_not path =~ uri
end
def test_match_controller
diff --git a/actionpack/test/journey/route/definition/parser_test.rb b/actionpack/test/journey/route/definition/parser_test.rb
index 580235c6a1..d7d7172a40 100644
--- a/actionpack/test/journey/route/definition/parser_test.rb
+++ b/actionpack/test/journey/route/definition/parser_test.rb
@@ -3,7 +3,7 @@ require 'abstract_unit'
module ActionDispatch
module Journey
module Definition
- class TestParser < MiniTest::Unit::TestCase
+ class TestParser < ActiveSupport::TestCase
def setup
@parser = Parser.new
end
diff --git a/actionpack/test/journey/route/definition/scanner_test.rb b/actionpack/test/journey/route/definition/scanner_test.rb
index 110baf9977..624e6df51a 100644
--- a/actionpack/test/journey/route/definition/scanner_test.rb
+++ b/actionpack/test/journey/route/definition/scanner_test.rb
@@ -3,7 +3,7 @@ require 'abstract_unit'
module ActionDispatch
module Journey
module Definition
- class TestScanner < MiniTest::Unit::TestCase
+ class TestScanner < ActiveSupport::TestCase
def setup
@scanner = Scanner.new
end
diff --git a/actionpack/test/journey/route_test.rb b/actionpack/test/journey/route_test.rb
index b205db5fbc..78608a5c6b 100644
--- a/actionpack/test/journey/route_test.rb
+++ b/actionpack/test/journey/route_test.rb
@@ -2,7 +2,7 @@ require 'abstract_unit'
module ActionDispatch
module Journey
- class TestRoute < MiniTest::Unit::TestCase
+ class TestRoute < ActiveSupport::TestCase
def test_initialize
app = Object.new
path = Path::Pattern.new '/:controller(/:action(/:id(.:format)))'
@@ -92,7 +92,7 @@ module ActionDispatch
routes = [specific, generic]
- refute_equal specific.score(knowledge), generic.score(knowledge)
+ assert_not_equal specific.score(knowledge), generic.score(knowledge)
found = routes.sort_by { |r| r.score(knowledge) }.last
diff --git a/actionpack/test/journey/router/strexp_test.rb b/actionpack/test/journey/router/strexp_test.rb
index 9e0337f144..7ccdfb7b4d 100644
--- a/actionpack/test/journey/router/strexp_test.rb
+++ b/actionpack/test/journey/router/strexp_test.rb
@@ -3,7 +3,7 @@ require 'abstract_unit'
module ActionDispatch
module Journey
class Router
- class TestStrexp < MiniTest::Unit::TestCase
+ class TestStrexp < ActiveSupport::TestCase
def test_many_names
exp = Strexp.new(
"/:controller(/:action(/:id(.:format)))",
diff --git a/actionpack/test/journey/router/utils_test.rb b/actionpack/test/journey/router/utils_test.rb
index 97a6449c99..057dc40cca 100644
--- a/actionpack/test/journey/router/utils_test.rb
+++ b/actionpack/test/journey/router/utils_test.rb
@@ -3,7 +3,7 @@ require 'abstract_unit'
module ActionDispatch
module Journey
class Router
- class TestUtils < MiniTest::Unit::TestCase
+ class TestUtils < ActiveSupport::TestCase
def test_path_escape
assert_equal "a/b%20c+d", Utils.escape_path("a/b c+d")
end
diff --git a/actionpack/test/journey/router_test.rb b/actionpack/test/journey/router_test.rb
index 1b64600ba8..27bdb0108a 100644
--- a/actionpack/test/journey/router_test.rb
+++ b/actionpack/test/journey/router_test.rb
@@ -3,7 +3,7 @@ require 'abstract_unit'
module ActionDispatch
module Journey
- class TestRouter < MiniTest::Unit::TestCase
+ class TestRouter < ActiveSupport::TestCase
attr_reader :routes
def setup
@@ -277,7 +277,7 @@ module ActionDispatch
@router.recognize(env) do |*whatever|
yielded = true
end
- refute yielded
+ assert_not yielded
end
def test_required_part_in_recall
diff --git a/actionpack/test/journey/routes_test.rb b/actionpack/test/journey/routes_test.rb
index 3b17bd53b7..25e0321d31 100644
--- a/actionpack/test/journey/routes_test.rb
+++ b/actionpack/test/journey/routes_test.rb
@@ -2,7 +2,7 @@ require 'abstract_unit'
module ActionDispatch
module Journey
- class TestRoutes < MiniTest::Unit::TestCase
+ class TestRoutes < ActiveSupport::TestCase
def test_clear
routes = Routes.new
exp = Router::Strexp.new '/foo(/:id)', {}, ['/.?']
@@ -23,7 +23,7 @@ module ActionDispatch
routes.add_route nil, path, {}, {}, {}
ast = routes.ast
routes.add_route nil, path, {}, {}, {}
- refute_equal ast, routes.ast
+ assert_not_equal ast, routes.ast
end
def test_simulator_changes
@@ -33,7 +33,7 @@ module ActionDispatch
routes.add_route nil, path, {}, {}, {}
sim = routes.simulator
routes.add_route nil, path, {}, {}, {}
- refute_equal sim, routes.simulator
+ assert_not_equal sim, routes.simulator
end
def test_first_name_wins
diff --git a/actionpack/test/template/atom_feed_helper_test.rb b/actionpack/test/template/atom_feed_helper_test.rb
index 89aae4ac56..63b5ac0fab 100644
--- a/actionpack/test/template/atom_feed_helper_test.rb
+++ b/actionpack/test/template/atom_feed_helper_test.rb
@@ -238,7 +238,7 @@ class AtomFeedTest < ActionController::TestCase
get :index, :id=>"provide_builder"
# because we pass in the non-default builder, the content generated by the
# helper should go 'nowhere'. Leaving the response body blank.
- assert_blank @response.body
+ assert @response.body.blank?
end
end
diff --git a/actionpack/test/template/digestor_test.rb b/actionpack/test/template/digestor_test.rb
index 02b1fd87a8..849e2981a6 100644
--- a/actionpack/test/template/digestor_test.rb
+++ b/actionpack/test/template/digestor_test.rb
@@ -138,6 +138,20 @@ class TemplateDigestorTest < ActionView::TestCase
end
end
+ def test_dependencies_via_options_results_in_different_digest
+ digest_plain = digest("comments/_comment")
+ digest_fridge = digest("comments/_comment", dependencies: ["fridge"])
+ digest_phone = digest("comments/_comment", dependencies: ["phone"])
+ digest_fridge_phone = digest("comments/_comment", dependencies: ["fridge", "phone"])
+
+ assert_not_equal digest_plain, digest_fridge
+ assert_not_equal digest_plain, digest_phone
+ assert_not_equal digest_plain, digest_fridge_phone
+ assert_not_equal digest_fridge, digest_phone
+ assert_not_equal digest_fridge, digest_fridge_phone
+ assert_not_equal digest_phone, digest_fridge_phone
+ end
+
private
def assert_logged(message)
old_logger = ActionView::Base.logger
@@ -164,8 +178,8 @@ class TemplateDigestorTest < ActionView::TestCase
ActionView::Digestor.cache.clear
end
- def digest(template_name)
- ActionView::Digestor.digest(template_name, :html, FixtureFinder.new)
+ def digest(template_name, options={})
+ ActionView::Digestor.digest(template_name, :html, FixtureFinder.new, options)
end
def change_template(template_name)
diff --git a/actionpack/test/template/form_collections_helper_test.rb b/actionpack/test/template/form_collections_helper_test.rb
index c73e80ed88..2131f81396 100644
--- a/actionpack/test/template/form_collections_helper_test.rb
+++ b/actionpack/test/template/form_collections_helper_test.rb
@@ -149,6 +149,12 @@ class FormCollectionsHelperTest < ActionView::TestCase
assert_select 'label[for=post_category_id_2]', 'Category 2'
end
+ test 'collection radio accepts checked item which has a value of false' do
+ with_collection_radio_buttons :user, :active, [[1, true], [0, false]], :last, :first, :checked => false
+ assert_no_select 'input[type=radio][value=true][checked=checked]'
+ assert_select 'input[type=radio][value=false][checked=checked]'
+ end
+
# COLLECTION CHECK BOXES
test 'collection check boxes accepts a collection and generate a serie of checkboxes for value method' do
collection = [Category.new(1, 'Category 1'), Category.new(2, 'Category 2')]
diff --git a/actionpack/test/template/form_helper_test.rb b/actionpack/test/template/form_helper_test.rb
index cc098b6be7..247068de4e 100644
--- a/actionpack/test/template/form_helper_test.rb
+++ b/actionpack/test/template/form_helper_test.rb
@@ -1171,7 +1171,6 @@ class FormHelperTest < ActionView::TestCase
assert_dom_equal expected, output_buffer
end
-
def test_form_for_with_format
form_for(@post, :format => :json, :html => { :id => "edit_post_123", :class => "edit_post" }) do |f|
concat f.label(:title)
@@ -2716,6 +2715,19 @@ class FormHelperTest < ActionView::TestCase
end
end
+ def test_form_for_only_instantiates_builder_once
+ initialization_count = 0
+ builder_class = Class.new(ActionView::Helpers::FormBuilder) do
+ define_method :initialize do |*args|
+ super(*args)
+ initialization_count += 1
+ end
+ end
+
+ form_for(@post, builder: builder_class) { }
+ assert_equal 1, initialization_count, 'form builder instantiated more than once'
+ end
+
protected
def hidden_fields(method = nil)
diff --git a/actionpack/test/template/form_tag_helper_test.rb b/actionpack/test/template/form_tag_helper_test.rb
index 0a94fa079b..6c6a142397 100644
--- a/actionpack/test/template/form_tag_helper_test.rb
+++ b/actionpack/test/template/form_tag_helper_test.rb
@@ -488,7 +488,7 @@ class FormTagHelperTest < ActionView::TestCase
def test_image_submit_tag_with_confirmation
assert_dom_equal(
- %(<input type="image" src="/images/save.gif" data-confirm="Are you sure?" />),
+ %(<input alt="Save" type="image" src="/images/save.gif" data-confirm="Are you sure?" />),
image_submit_tag("save.gif", :data => { :confirm => "Are you sure?" })
)
end
@@ -496,7 +496,7 @@ class FormTagHelperTest < ActionView::TestCase
def test_image_submit_tag_with_deprecated_confirmation
assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use 'data: { confirm: \'Text\' }' instead" do
assert_dom_equal(
- %(<input type="image" src="/images/save.gif" data-confirm="Are you sure?" />),
+ %(<input alt="Save" type="image" src="/images/save.gif" data-confirm="Are you sure?" />),
image_submit_tag("save.gif", :confirm => "Are you sure?")
)
end
diff --git a/actionpack/test/template/record_tag_helper_test.rb b/actionpack/test/template/record_tag_helper_test.rb
index a84034c02e..9c49438f6a 100644
--- a/actionpack/test/template/record_tag_helper_test.rb
+++ b/actionpack/test/template/record_tag_helper_test.rb
@@ -25,33 +25,33 @@ class RecordTagHelperTest < ActionView::TestCase
def test_content_tag_for
expected = %(<li class="record_tag_post" id="record_tag_post_45"></li>)
- actual = content_tag_for(:li, @post) { }
+ actual = content_tag_for(:li, @post)
assert_dom_equal expected, actual
end
def test_content_tag_for_prefix
expected = %(<ul class="archived_record_tag_post" id="archived_record_tag_post_45"></ul>)
- actual = content_tag_for(:ul, @post, :archived) { }
+ actual = content_tag_for(:ul, @post, :archived)
assert_dom_equal expected, actual
end
def test_content_tag_for_with_extra_html_options
expected = %(<tr class="record_tag_post special" id="record_tag_post_45" style='background-color: #f0f0f0'></tr>)
- actual = content_tag_for(:tr, @post, :class => "special", :style => "background-color: #f0f0f0") { }
+ actual = content_tag_for(:tr, @post, class: "special", style: "background-color: #f0f0f0")
assert_dom_equal expected, actual
end
def test_content_tag_for_with_prefix_and_extra_html_options
expected = %(<tr class="archived_record_tag_post special" id="archived_record_tag_post_45" style='background-color: #f0f0f0'></tr>)
- actual = content_tag_for(:tr, @post, :archived, :class => "special", :style => "background-color: #f0f0f0") { }
+ actual = content_tag_for(:tr, @post, :archived, class: "special", style: "background-color: #f0f0f0")
assert_dom_equal expected, actual
end
def test_block_not_in_erb_multiple_calls
expected = %(<div class="record_tag_post special" id="record_tag_post_45">What a wonderful world!</div>)
- actual = div_for(@post, :class => "special") { @post.body }
+ actual = div_for(@post, class: "special") { @post.body }
assert_dom_equal expected, actual
- actual = div_for(@post, :class => "special") { @post.body }
+ actual = div_for(@post, class: "special") { @post.body }
assert_dom_equal expected, actual
end
@@ -63,7 +63,7 @@ class RecordTagHelperTest < ActionView::TestCase
def test_div_for_in_erb
expected = %(<div class="record_tag_post special" id="record_tag_post_45">What a wonderful world!</div>)
- actual = render_erb("<%= div_for(@post, :class => 'special') do %><%= @post.body %><% end %>")
+ actual = render_erb("<%= div_for(@post, class: 'special') do %><%= @post.body %><% end %>")
assert_dom_equal expected, actual
end
@@ -75,6 +75,14 @@ class RecordTagHelperTest < ActionView::TestCase
assert_dom_equal expected, actual
end
+ def test_content_tag_for_collection_without_given_block
+ post_1 = RecordTagPost.new.tap { |post| post.id = 101; post.body = "Hello!" }
+ post_2 = RecordTagPost.new.tap { |post| post.id = 102; post.body = "World!" }
+ expected = %(<li class="record_tag_post" id="record_tag_post_101"></li>\n<li class="record_tag_post" id="record_tag_post_102"></li>)
+ actual = content_tag_for(:li, [post_1, post_2])
+ assert_dom_equal expected, actual
+ end
+
def test_div_for_collection
post_1 = RecordTagPost.new { |post| post.id = 101; post.body = "Hello!" }
post_2 = RecordTagPost.new { |post| post.id = 102; post.body = "World!" }
@@ -84,7 +92,7 @@ class RecordTagHelperTest < ActionView::TestCase
end
def test_content_tag_for_single_record_is_html_safe
- result = div_for(@post, :class => "special") { @post.body }
+ result = div_for(@post, class: "special") { @post.body }
assert result.html_safe?
end
@@ -96,8 +104,8 @@ class RecordTagHelperTest < ActionView::TestCase
end
def test_content_tag_for_does_not_change_options_hash
- options = { :class => "important" }
- content_tag_for(:li, @post, options) { }
- assert_equal({ :class => "important" }, options)
+ options = { class: "important" }
+ content_tag_for(:li, @post, options)
+ assert_equal({ class: "important" }, options)
end
end
diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb
index 9fb26e32b1..8111e58527 100644
--- a/actionpack/test/template/render_test.rb
+++ b/actionpack/test/template/render_test.rb
@@ -318,6 +318,13 @@ module RenderTestCases
@controller_view.render(customers, :greeting => "Hello")
end
+ def test_render_partial_without_object_or_collection_does_not_generate_partial_name_local_variable
+ exception = assert_raises ActionView::Template::Error do
+ @controller_view.render("partial_name_local_variable")
+ end
+ assert_match "undefined local variable or method `partial_name_local_variable'", exception.message
+ end
+
# TODO: The reason for this test is unclear, improve documentation
def test_render_partial_and_fallback_to_layout
assert_equal "Before (Josh)\n\nAfter", @view.render(:partial => "test/layout_for_partial", :locals => { :name => "Josh" })
diff --git a/actionpack/test/template/spec_type_test.rb b/actionpack/test/template/spec_type_test.rb
deleted file mode 100644
index 08a7bdf81d..0000000000
--- a/actionpack/test/template/spec_type_test.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-require 'abstract_unit'
-
-class ActionViewSpecTypeTest < ActiveSupport::TestCase
- def assert_view actual
- assert_equal ActionView::TestCase, actual
- end
-
- def refute_view actual
- refute_equal ActionView::TestCase, actual
- end
-
- def test_spec_type_resolves_for_matching_helper_strings
- assert_view MiniTest::Spec.spec_type("WidgetHelper")
- assert_view MiniTest::Spec.spec_type("WidgetHelperTest")
- assert_view MiniTest::Spec.spec_type("Widget Helper Test")
- # And is not case sensitive
- assert_view MiniTest::Spec.spec_type("widgethelper")
- assert_view MiniTest::Spec.spec_type("widgethelpertest")
- assert_view MiniTest::Spec.spec_type("widget helper test")
- end
-
- def test_spec_type_resolves_for_matching_view_strings
- assert_view MiniTest::Spec.spec_type("WidgetView")
- assert_view MiniTest::Spec.spec_type("WidgetViewTest")
- assert_view MiniTest::Spec.spec_type("Widget View Test")
- # And is not case sensitive
- assert_view MiniTest::Spec.spec_type("widgetview")
- assert_view MiniTest::Spec.spec_type("widgetviewtest")
- assert_view MiniTest::Spec.spec_type("widget view test")
- end
-
- def test_spec_type_wont_match_non_space_characters
- refute_view MiniTest::Spec.spec_type("Widget Helper\tTest")
- refute_view MiniTest::Spec.spec_type("Widget Helper\rTest")
- refute_view MiniTest::Spec.spec_type("Widget Helper\nTest")
- refute_view MiniTest::Spec.spec_type("Widget Helper\fTest")
- refute_view MiniTest::Spec.spec_type("Widget HelperXTest")
- end
-end
diff --git a/actionpack/test/template/test_test.rb b/actionpack/test/template/test_test.rb
index e843a1deb4..108a674d95 100644
--- a/actionpack/test/template/test_test.rb
+++ b/actionpack/test/template/test_test.rb
@@ -78,59 +78,3 @@ class CrazyStringHelperTest < ActionView::TestCase
assert_equal PeopleHelper, self.class.helper_class
end
end
-
-describe PeopleHelper do
- it "resolves the right helper_class" do
- assert_equal PeopleHelper, self.class.helper_class
- end
-end
-
-describe PeopleHelper, :helper_class do
- it "resolves the right helper_class" do
- assert_equal PeopleHelper, self.class.helper_class
- end
-end
-
-describe PeopleHelper do
- describe "even while nested" do
- it "resolves the right helper_class" do
- assert_equal PeopleHelper, self.class.helper_class
- end
- end
-end
-
-describe PeopleHelper, :helper_class do
- describe "even while nested" do
- it "resolves the right helper_class" do
- assert_equal PeopleHelper, self.class.helper_class
- end
- end
-end
-
-describe "PeopleHelper" do
- it "resolves the right helper_class" do
- assert_equal PeopleHelper, self.class.helper_class
- end
-end
-
-describe "PeopleHelperTest" do
- it "resolves the right helper_class" do
- assert_equal PeopleHelper, self.class.helper_class
- end
-end
-
-describe "PeopleHelper" do
- describe "even while nested" do
- it "resolves the right helper_class" do
- assert_equal PeopleHelper, self.class.helper_class
- end
- end
-end
-
-describe "PeopleHelperTest" do
- describe "even while nested" do
- it "resolves the right helper_class" do
- assert_equal PeopleHelper, self.class.helper_class
- end
- end
-end
diff --git a/actionpack/test/ts_isolated.rb b/actionpack/test/ts_isolated.rb
index c44c5d8968..55620abe84 100644
--- a/actionpack/test/ts_isolated.rb
+++ b/actionpack/test/ts_isolated.rb
@@ -1,4 +1,4 @@
-require 'minitest/autorun'
+require 'active_support/testing/autorun'
require 'rbconfig'
require 'abstract_unit'
diff --git a/activemodel/MIT-LICENSE b/activemodel/MIT-LICENSE
index 810daf856c..5c668d9624 100644
--- a/activemodel/MIT-LICENSE
+++ b/activemodel/MIT-LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2012 David Heinemeier Hansson
+Copyright (c) 2004-2013 David Heinemeier Hansson
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/activemodel/README.rdoc b/activemodel/README.rdoc
index 3262bf61ac..3cc2d9ad8e 100644
--- a/activemodel/README.rdoc
+++ b/activemodel/README.rdoc
@@ -133,24 +133,6 @@ behavior out of the box:
{Learn more}[link:classes/ActiveModel/Naming.html]
-* Observer support
-
- ActiveModel::Observers allows your object to implement the Observer
- pattern in a Rails App and take advantage of all the standard observer
- functions.
-
- class PersonObserver < ActiveModel::Observer
- def after_create(person)
- person.logger.info("New person added!")
- end
-
- def after_destroy(person)
- person.logger.warn("Person with an id of #{person.id} was destroyed!")
- end
- end
-
- {Learn more}[link:classes/ActiveModel/Observer.html]
-
* Making objects serializable
ActiveModel::Serialization provides a standard interface for your object
diff --git a/activemodel/lib/active_model.rb b/activemodel/lib/active_model.rb
index 0a32c5af05..3bd5531356 100644
--- a/activemodel/lib/active_model.rb
+++ b/activemodel/lib/active_model.rb
@@ -1,5 +1,5 @@
#--
-# Copyright (c) 2004-2012 David Heinemeier Hansson
+# Copyright (c) 2004-2013 David Heinemeier Hansson
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb
index db5759ada9..6d11c0fbdc 100644
--- a/activemodel/lib/active_model/attribute_methods.rb
+++ b/activemodel/lib/active_model/attribute_methods.rb
@@ -436,7 +436,7 @@ module ActiveModel
# attribute_missing is like method_missing, but for attributes. When method_missing is
# called we check to see if there is a matching attribute method. If so, we call
# attribute_missing to dispatch the attribute. This method can be overloaded to
- # customise the behaviour.
+ # customize the behavior.
def attribute_missing(match, *args, &block)
__send__(match.target, match.attr_name, *args, &block)
end
diff --git a/activemodel/lib/active_model/dirty.rb b/activemodel/lib/active_model/dirty.rb
index ecb7a9e9b1..6e67cd2285 100644
--- a/activemodel/lib/active_model/dirty.rb
+++ b/activemodel/lib/active_model/dirty.rb
@@ -119,7 +119,7 @@ module ActiveModel
# person.name = 'bob'
# person.changes # => { "name" => ["bill", "bob"] }
def changes
- HashWithIndifferentAccess[changed.map { |attr| [attr, attribute_change(attr)] }]
+ ActiveSupport::HashWithIndifferentAccess[changed.map { |attr| [attr, attribute_change(attr)] }]
end
# Returns a hash of attributes that were changed before the model was saved.
diff --git a/activemodel/lib/active_model/validations/clusivity.rb b/activemodel/lib/active_model/validations/clusivity.rb
index 3d7067fbcb..49df98d6c1 100644
--- a/activemodel/lib/active_model/validations/clusivity.rb
+++ b/activemodel/lib/active_model/validations/clusivity.rb
@@ -3,7 +3,7 @@ require 'active_support/core_ext/range'
module ActiveModel
module Validations
module Clusivity #:nodoc:
- ERROR_MESSAGE = "An object with the method #include? or a proc, lambda or symbol is required, " <<
+ ERROR_MESSAGE = "An object with the method #include? or a proc, lambda or symbol is required, " \
"and must be supplied as the :in (or :within) option of the configuration hash"
def check_validity!
diff --git a/activemodel/lib/active_model/validations/numericality.rb b/activemodel/lib/active_model/validations/numericality.rb
index 744c196d30..085532c35b 100644
--- a/activemodel/lib/active_model/validations/numericality.rb
+++ b/activemodel/lib/active_model/validations/numericality.rb
@@ -17,9 +17,9 @@ module ActiveModel
end
def validate_each(record, attr_name, value)
- before_type_cast = "#{attr_name}_before_type_cast"
+ before_type_cast = :"#{attr_name}_before_type_cast"
- raw_value = record.send(before_type_cast) if record.respond_to?(before_type_cast.to_sym)
+ raw_value = record.send(before_type_cast) if record.respond_to?(before_type_cast)
raw_value ||= value
return if options[:allow_nil] && raw_value.nil?
diff --git a/activemodel/lib/active_model/validations/presence.rb b/activemodel/lib/active_model/validations/presence.rb
index ae84c376b9..ab8c8359fc 100644
--- a/activemodel/lib/active_model/validations/presence.rb
+++ b/activemodel/lib/active_model/validations/presence.rb
@@ -3,8 +3,8 @@ module ActiveModel
module Validations
class PresenceValidator < EachValidator # :nodoc:
- def validate(record)
- record.errors.add_on_blank(attributes, options)
+ def validate_each(record, attr_name, value)
+ record.errors.add(attr_name, :blank, options) if value.blank?
end
end
diff --git a/activemodel/lib/active_model/validator.rb b/activemodel/lib/active_model/validator.rb
index d51f4d1936..f989b21140 100644
--- a/activemodel/lib/active_model/validator.rb
+++ b/activemodel/lib/active_model/validator.rb
@@ -103,7 +103,7 @@ module ActiveModel
end
# Accepts options that will be made available through the +options+ reader.
- def initialize(options)
+ def initialize(options = {})
@options = options.freeze
end
diff --git a/activemodel/test/cases/helper.rb b/activemodel/test/cases/helper.rb
index 7d6f11b5a5..7a63674757 100644
--- a/activemodel/test/cases/helper.rb
+++ b/activemodel/test/cases/helper.rb
@@ -7,4 +7,4 @@ require 'active_support/core_ext/string/access'
# Show backtraces for deprecated behavior for quicker cleanup.
ActiveSupport::Deprecation.debug = true
-require 'minitest/autorun'
+require 'active_support/testing/autorun'
diff --git a/activemodel/test/cases/validations/presence_validation_test.rb b/activemodel/test/cases/validations/presence_validation_test.rb
index 510c13a7c3..2f228cfa83 100644
--- a/activemodel/test/cases/validations/presence_validation_test.rb
+++ b/activemodel/test/cases/validations/presence_validation_test.rb
@@ -41,7 +41,7 @@ class PresenceValidationTest < ActiveModel::TestCase
end
def test_validates_acceptance_of_with_custom_error_using_quotes
- Person.validates_presence_of :karma, :message => "This string contains 'single' and \"double\" quotes"
+ Person.validates_presence_of :karma, message: "This string contains 'single' and \"double\" quotes"
p = Person.new
assert p.invalid?
assert_equal "This string contains 'single' and \"double\" quotes", p.errors[:karma].last
@@ -70,4 +70,38 @@ class PresenceValidationTest < ActiveModel::TestCase
p[:karma] = "Cold"
assert p.valid?
end
+
+ def test_validates_presence_of_with_allow_nil_option
+ Topic.validates_presence_of(:title, allow_nil: true)
+
+ t = Topic.new(title: "something")
+ assert t.valid?, t.errors.full_messages
+
+ t.title = ""
+ assert t.invalid?
+ assert_equal ["can't be blank"], t.errors[:title]
+
+ t.title = " "
+ assert t.invalid?, t.errors.full_messages
+ assert_equal ["can't be blank"], t.errors[:title]
+
+ t.title = nil
+ assert t.valid?, t.errors.full_messages
+ end
+
+ def test_validates_presence_of_with_allow_blank_option
+ Topic.validates_presence_of(:title, allow_blank: true)
+
+ t = Topic.new(title: "something")
+ assert t.valid?, t.errors.full_messages
+
+ t.title = ""
+ assert t.valid?, t.errors.full_messages
+
+ t.title = " "
+ assert t.valid?, t.errors.full_messages
+
+ t.title = nil
+ assert t.valid?, t.errors.full_messages
+ end
end
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 756bad5507..5a0c391154 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,7 +1,28 @@
## Rails 4.0.0 (unreleased) ##
+* Remove support for parsing YAML parameters from request.
+
+ *Aaron Patterson*
+
+* Support for PostgreSQL's `ltree` data type.
+
+ *Rob Worley*
+
+* Fix undefined method `to_i` when calling `new` on a scope that uses an
+ Array; Fix FloatDomainError when setting integer column to NaN.
+ Fixes #8718, #8734, #8757.
+
+ *Jason Stirk + Tristan Harward*
+
+* Rename `update_attributes` to `update`, keep `update_attributes` as an alias for `update` method.
+ This is a soft-deprecation for `update_attributes`, although it will still work without any
+ deprecation message in 4.0 is recommended to start using `update` since `update_attributes` will be
+ deprecated and removed in future versions of Rails.
+
+ *Amparo Luna + Guillermo Iguaran*
+
* `after_commit` and `after_rollback` now validate the `:on` option and raise an `ArgumentError`
- if it is not one of `:create`, `:destroy` or ``:update`
+ if it is not one of `:create`, `:destroy` or `:update`
*Pascal Friederich*
@@ -18,7 +39,8 @@
If migrating down, the given migration / block is run normally.
See the [Guide on Migration](https://github.com/rails/rails/blob/master/guides/source/migrations.md#reverting-previous-migrations)
- Attempting to revert the methods `execute`, `remove_columns` and `change_column` will now raise an IrreversibleMigration instead of actually executing them without any output.
+ Attempting to revert the methods `execute`, `remove_columns` and `change_column` will now
+ raise an `IrreversibleMigration` instead of actually executing them without any output.
*Marc-André Lafortune*
diff --git a/activerecord/MIT-LICENSE b/activerecord/MIT-LICENSE
index 03bde18130..0d7fb865e2 100644
--- a/activerecord/MIT-LICENSE
+++ b/activerecord/MIT-LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2012 David Heinemeier Hansson
+Copyright (c) 2004-2013 David Heinemeier Hansson
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/activerecord/examples/performance.rb b/activerecord/examples/performance.rb
index cd9825b50c..ad12f8597f 100644
--- a/activerecord/examples/performance.rb
+++ b/activerecord/examples/performance.rb
@@ -143,7 +143,7 @@ Benchmark.ips(TIME) do |x|
end
x.report 'Resource#update' do
- Exhibit.first.update_attributes(:name => 'bob')
+ Exhibit.first.update(name: 'bob')
end
x.report 'Resource#destroy' do
diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb
index 822da84d19..c33f03f13f 100644
--- a/activerecord/lib/active_record.rb
+++ b/activerecord/lib/active_record.rb
@@ -1,5 +1,5 @@
#--
-# Copyright (c) 2004-2012 David Heinemeier Hansson
+# Copyright (c) 2004-2013 David Heinemeier Hansson
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
diff --git a/activerecord/lib/active_record/aggregations.rb b/activerecord/lib/active_record/aggregations.rb
index 8101f7a45e..9d1c12ec62 100644
--- a/activerecord/lib/active_record/aggregations.rb
+++ b/activerecord/lib/active_record/aggregations.rb
@@ -113,7 +113,7 @@ module ActiveRecord
# other than the writer method.
#
# The immutable requirement is enforced by Active Record by freezing any object assigned as a value
- # object. Attempting to change it afterwards will result in a ActiveSupport::FrozenObjectError.
+ # object. Attempting to change it afterwards will result in a RuntimeError.
#
# Read more about value objects on http://c2.com/cgi/wiki?ValueObject and on the dangers of not
# keeping value objects immutable on http://c2.com/cgi/wiki?ValueObjectsShouldBeImmutable
@@ -165,7 +165,7 @@ module ActiveRecord
# by specifying an instance of the value object in the conditions hash. The following example
# finds all customers with +balance_amount+ equal to 20 and +balance_currency+ equal to "USD":
#
- # Customer.where(balance: Money.new(20, "USD")).all
+ # Customer.where(balance: Money.new(20, "USD"))
#
module ClassMethods
# Adds reader and writer methods for manipulating a value object:
diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb
index d8b6d7a86b..16a46a59d1 100644
--- a/activerecord/lib/active_record/associations.rb
+++ b/activerecord/lib/active_record/associations.rb
@@ -1,8 +1,6 @@
require 'active_support/core_ext/enumerable'
require 'active_support/core_ext/string/conversions'
require 'active_support/core_ext/module/remove_method'
-require 'active_support/dependencies/autoload'
-require 'active_support/concern'
require 'active_record/errors'
module ActiveRecord
@@ -194,7 +192,7 @@ module ActiveRecord
# * <tt>Project#project_manager, Project#project_manager=(project_manager), Project#project_manager.nil?,</tt>
# * <tt>Project#milestones.empty?, Project#milestones.size, Project#milestones, Project#milestones<<(milestone),</tt>
# <tt>Project#milestones.delete(milestone), Project#milestones.destroy(mileston), Project#milestones.find(milestone_id),</tt>
- # <tt>Project#milestones.all(options), Project#milestones.build, Project#milestones.create</tt>
+ # <tt>Project#milestones.build, Project#milestones.create</tt>
# * <tt>Project#categories.empty?, Project#categories.size, Project#categories, Project#categories<<(category1),</tt>
# <tt>Project#categories.delete(category1), Project#categories.destroy(category1)</tt>
#
@@ -459,7 +457,7 @@ module ActiveRecord
# has_many :people do
# def find_or_create_by_name(name)
# first_name, last_name = name.split(" ", 2)
- # find_or_create_by_first_name_and_last_name(first_name, last_name)
+ # find_or_create_by(first_name: first_name, last_name: last_name)
# end
# end
# end
@@ -474,7 +472,7 @@ module ActiveRecord
# module FindOrCreateByNameExtension
# def find_or_create_by_name(name)
# first_name, last_name = name.split(" ", 2)
- # find_or_create_by_first_name_and_last_name(first_name, last_name)
+ # find_or_create_by(first_name: first_name, last_name: last_name)
# end
# end
#
@@ -743,7 +741,7 @@ module ActiveRecord
# other than the main one. If this is the case Active Record falls back to the previously
# used LEFT OUTER JOIN based strategy. For example
#
- # Post.includes([:author, :comments]).where(['comments.approved = ?', true]).all
+ # Post.includes([:author, :comments]).where(['comments.approved = ?', true])
#
# This will result in a single SQL query with joins along the lines of:
# <tt>LEFT OUTER JOIN comments ON comments.post_id = posts.id</tt> and
@@ -951,7 +949,7 @@ module ActiveRecord
#
# The <tt>:dependent</tt> option can have different values which specify how the deletion
# is done. For more information, see the documentation for this option on the different
- # specific association types. When no option is given, the behaviour is to do nothing
+ # specific association types. When no option is given, the behavior is to do nothing
# with the associated records when destroying a record.
#
# Note that <tt>:dependent</tt> is implemented using Rails' callback
@@ -1081,7 +1079,7 @@ module ActiveRecord
# === Example
#
# Example: A Firm class declares <tt>has_many :clients</tt>, which will add:
- # * <tt>Firm#clients</tt> (similar to <tt>Clients.all conditions: ["firm_id = ?", id]</tt>)
+ # * <tt>Firm#clients</tt> (similar to <tt>Client.where(firm_id: id)</tt>)
# * <tt>Firm#clients<<</tt>
# * <tt>Firm#clients.delete</tt>
# * <tt>Firm#clients.destroy</tt>
@@ -1091,7 +1089,7 @@ module ActiveRecord
# * <tt>Firm#clients.clear</tt>
# * <tt>Firm#clients.empty?</tt> (similar to <tt>firm.clients.size == 0</tt>)
# * <tt>Firm#clients.size</tt> (similar to <tt>Client.count "firm_id = #{id}"</tt>)
- # * <tt>Firm#clients.find</tt> (similar to <tt>Client.find(id, conditions: "firm_id = #{id}")</tt>)
+ # * <tt>Firm#clients.find</tt> (similar to <tt>Client.where(firm_id: id).find(id)</tt>)
# * <tt>Firm#clients.exists?(name: 'ACME')</tt> (similar to <tt>Client.exists?(name: 'ACME', firm_id: firm.id)</tt>)
# * <tt>Firm#clients.build</tt> (similar to <tt>Client.new("firm_id" => id)</tt>)
# * <tt>Firm#clients.create</tt> (similar to <tt>c = Client.new("firm_id" => id); c.save; c</tt>)
@@ -1213,7 +1211,7 @@ module ActiveRecord
# === Example
#
# An Account class declares <tt>has_one :beneficiary</tt>, which will add:
- # * <tt>Account#beneficiary</tt> (similar to <tt>Beneficiary.first(conditions: "account_id = #{id}")</tt>)
+ # * <tt>Account#beneficiary</tt> (similar to <tt>Beneficiary.where(account_id: id).first</tt>)
# * <tt>Account#beneficiary=(beneficiary)</tt> (similar to <tt>beneficiary.account_id = account.id; beneficiary.save</tt>)
# * <tt>Account#build_beneficiary</tt> (similar to <tt>Beneficiary.new("account_id" => id)</tt>)
# * <tt>Account#create_beneficiary</tt> (similar to <tt>b = Beneficiary.new("account_id" => id); b.save; b</tt>)
diff --git a/activerecord/lib/active_record/associations/belongs_to_association.rb b/activerecord/lib/active_record/associations/belongs_to_association.rb
index 75f72c1a46..532af3e83e 100644
--- a/activerecord/lib/active_record/associations/belongs_to_association.rb
+++ b/activerecord/lib/active_record/associations/belongs_to_association.rb
@@ -50,8 +50,11 @@ module ActiveRecord
# Checks whether record is different to the current target, without loading it
def different_target?(record)
- record.nil? && owner[reflection.foreign_key] ||
- record && record.id != owner[reflection.foreign_key]
+ if record.nil?
+ owner[reflection.foreign_key]
+ else
+ record.id != owner[reflection.foreign_key]
+ end
end
def replace_keys(record)
diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb
index 7c43e37cf2..33dce58982 100644
--- a/activerecord/lib/active_record/associations/collection_proxy.rb
+++ b/activerecord/lib/active_record/associations/collection_proxy.rb
@@ -758,7 +758,7 @@ module ActiveRecord
# person.pets.count # => 0
# person.pets.any? # => true
#
- # You can also pass a block to define criteria. The behaviour
+ # You can also pass a block to define criteria. The behavior
# is the same, it returns true if the collection based on the
# criteria is not empty.
#
@@ -793,7 +793,7 @@ module ActiveRecord
# person.pets.many? #=> true
#
# You can also pass a block to define criteria. The
- # behaviour is the same, it returns true if the collection
+ # behavior is the same, it returns true if the collection
# based on the criteria has more than one record.
#
# person.pets
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 c3266f2bb4..d1458f30ba 100644
--- a/activerecord/lib/active_record/associations/has_many_through_association.rb
+++ b/activerecord/lib/active_record/associations/has_many_through_association.rb
@@ -114,11 +114,7 @@ module ActiveRecord
end
def target_reflection_has_associated_record?
- if through_reflection.macro == :belongs_to && owner[through_reflection.foreign_key].blank?
- false
- else
- true
- end
+ !(through_reflection.macro == :belongs_to && owner[through_reflection.foreign_key].blank?)
end
def update_through_counter?(method)
diff --git a/activerecord/lib/active_record/associations/has_one_through_association.rb b/activerecord/lib/active_record/associations/has_one_through_association.rb
index fdf8ae1453..08e0ec691f 100644
--- a/activerecord/lib/active_record/associations/has_one_through_association.rb
+++ b/activerecord/lib/active_record/associations/has_one_through_association.rb
@@ -23,7 +23,7 @@ module ActiveRecord
attributes = construct_join_attributes(record)
if through_record
- through_record.update_attributes(attributes)
+ through_record.update(attributes)
elsif owner.new_record?
through_proxy.build(attributes)
else
diff --git a/activerecord/lib/active_record/associations/preloader.rb b/activerecord/lib/active_record/associations/preloader.rb
index 0848e7afb3..82bf426b22 100644
--- a/activerecord/lib/active_record/associations/preloader.rb
+++ b/activerecord/lib/active_record/associations/preloader.rb
@@ -100,7 +100,9 @@ module ActiveRecord
case association
when Hash
preload_hash(association)
- when String, Symbol
+ when Symbol
+ preload_one(association)
+ when String
preload_one(association.to_sym)
else
raise ArgumentError, "#{association.inspect} was not recognised for preload"
diff --git a/activerecord/lib/active_record/associations/preloader/association.rb b/activerecord/lib/active_record/associations/preloader/association.rb
index cbf5e734ea..82588905c6 100644
--- a/activerecord/lib/active_record/associations/preloader/association.rb
+++ b/activerecord/lib/active_record/associations/preloader/association.rb
@@ -76,7 +76,7 @@ module ActiveRecord
else
# Some databases impose a limit on the number of ids in a list (in Oracle it's 1000)
# Make several smaller queries if necessary or make one query if the adapter supports it
- sliced = owner_keys.each_slice(model.connection.in_clause_length || owner_keys.size)
+ sliced = owner_keys.each_slice(klass.connection.in_clause_length || owner_keys.size)
records = sliced.map { |slice| records_for(slice).to_a }.flatten
end
diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb
index 0333605eac..616ae1631f 100644
--- a/activerecord/lib/active_record/attribute_methods/dirty.rb
+++ b/activerecord/lib/active_record/attribute_methods/dirty.rb
@@ -1,5 +1,4 @@
require 'active_support/core_ext/module/attribute_accessors'
-require 'active_support/deprecation'
module ActiveRecord
module AttributeMethods
@@ -71,11 +70,11 @@ module ActiveRecord
super(attr, value)
end
- def update(*)
+ def update_record(*)
partial_writes? ? super(keys_for_partial_write) : super
end
- def create(*)
+ def create_record(*)
partial_writes? ? super(keys_for_partial_write) : super
end
diff --git a/activerecord/lib/active_record/attribute_methods/primary_key.rb b/activerecord/lib/active_record/attribute_methods/primary_key.rb
index 0857b02c8e..310f1b6e75 100644
--- a/activerecord/lib/active_record/attribute_methods/primary_key.rb
+++ b/activerecord/lib/active_record/attribute_methods/primary_key.rb
@@ -76,7 +76,7 @@ module ActiveRecord
end
def get_primary_key(base_name) #:nodoc:
- return 'id' unless base_name && !base_name.blank?
+ return 'id' if base_name.blank?
case primary_key_prefix_type
when :table_name
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index aab832c2f7..bf5793d454 100644
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -162,12 +162,9 @@ module ActiveRecord #:nodoc:
#
# Dynamic attribute-based finders are a cleaner way of getting (and/or creating) objects
# by simple queries without turning to SQL. They work by appending the name of an attribute
- # to <tt>find_by_</tt>, <tt>find_last_by_</tt>, or <tt>find_all_by_</tt> and thus produces finders
- # like <tt>Person.find_by_user_name</tt>, <tt>Person.find_all_by_last_name</tt>, and
- # <tt>Payment.find_by_transaction_id</tt>. Instead of writing
- # <tt>Person.where(user_name: user_name).first</tt>, you just do <tt>Person.find_by_user_name(user_name)</tt>.
- # And instead of writing <tt>Person.where(last_name: last_name).all</tt>, you just do
- # <tt>Person.find_all_by_last_name(last_name)</tt>.
+ # to <tt>find_by_</tt> # like <tt>Person.find_by_user_name</tt>.
+ # Instead of writing # <tt>Person.where(user_name: user_name).first</tt>, you just do
+ # <tt>Person.find_by_user_name(user_name)</tt>.
#
# It's possible to add an exclamation point (!) on the end of the dynamic finders to get them to raise an
# <tt>ActiveRecord::RecordNotFound</tt> error if they do not return any records,
@@ -180,46 +177,7 @@ module ActiveRecord #:nodoc:
#
# It's even possible to call these dynamic finder methods on relations and named scopes.
#
- # Payment.order("created_on").find_all_by_amount(50)
- # Payment.pending.find_last_by_amount(100)
- #
- # The same dynamic finder style can be used to create the object if it doesn't already exist.
- # This dynamic finder is called with <tt>find_or_create_by_</tt> and will return the object if
- # it already exists and otherwise creates it, then returns it. Protected attributes won't be set
- # unless they are given in a block.
- #
- # # No 'Summer' tag exists
- # Tag.find_or_create_by_name("Summer") # equal to Tag.create(name: "Summer")
- #
- # # Now the 'Summer' tag does exist
- # Tag.find_or_create_by_name("Summer") # equal to Tag.find_by_name("Summer")
- #
- # # Now 'Bob' exist and is an 'admin'
- # User.find_or_create_by_name('Bob', age: 40) { |u| u.admin = true }
- #
- # Adding an exclamation point (!) on to the end of <tt>find_or_create_by_</tt> will
- # raise an <tt>ActiveRecord::RecordInvalid</tt> error if the new record is invalid.
- #
- # Use the <tt>find_or_initialize_by_</tt> finder if you want to return a new record without
- # saving it first. Protected attributes won't be set unless they are given in a block.
- #
- # # No 'Winter' tag exists
- # winter = Tag.find_or_initialize_by_name("Winter")
- # winter.persisted? # false
- #
- # To find by a subset of the attributes to be used for instantiating a new object, pass a hash instead of
- # a list of parameters.
- #
- # Tag.find_or_create_by_name(name: "rails", creator: current_user)
- #
- # That will either find an existing tag named "rails", or create a new one while setting the
- # user that created it.
- #
- # Just like <tt>find_by_*</tt>, you can also use <tt>scoped_by_*</tt> to retrieve data. The good thing about
- # using this feature is that the very first time result is returned using <tt>method_missing</tt> technique
- # but after that the method is declared on the class. Henceforth <tt>method_missing</tt> will not be hit.
- #
- # User.scoped_by_user_name('David')
+ # Payment.order("created_on").find_by_amount(50)
#
# == Saving arrays, hashes, and other non-mappable objects in text columns
#
diff --git a/activerecord/lib/active_record/callbacks.rb b/activerecord/lib/active_record/callbacks.rb
index 1c9c627090..22226b2f4f 100644
--- a/activerecord/lib/active_record/callbacks.rb
+++ b/activerecord/lib/active_record/callbacks.rb
@@ -299,11 +299,11 @@ module ActiveRecord
run_callbacks(:save) { super }
end
- def create #:nodoc:
+ def create_record #:nodoc:
run_callbacks(:create) { super }
end
- def update(*) #:nodoc:
+ def update_record(*) #:nodoc:
run_callbacks(:update) { super }
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
index 82d0cf7e2e..27e6e8898c 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
@@ -2,7 +2,6 @@ require 'thread'
require 'thread_safe'
require 'monitor'
require 'set'
-require 'active_support/deprecation'
module ActiveRecord
# Raised when a connection could not be obtained within the connection
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
index 8517ce5fc5..cbb6869e66 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
@@ -5,7 +5,6 @@ require 'active_support/core_ext/benchmark'
require 'active_record/connection_adapters/schema_cache'
require 'active_record/connection_adapters/abstract/schema_dumper'
require 'monitor'
-require 'active_support/deprecation'
module ActiveRecord
module ConnectionAdapters # :nodoc:
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
index 124a2419ec..52b0b3fe79 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -14,7 +14,7 @@ module ActiveRecord
end
def extract_default(default)
- if sql_type =~ /blob/i || type == :text
+ if blob_or_text_column?
if default.blank?
null || strict ? nil : ''
else
@@ -28,9 +28,13 @@ module ActiveRecord
end
def has_default?
- return false if sql_type =~ /blob/i || type == :text #mysql forbids defaults on blob and text columns
+ return false if blob_or_text_column? #mysql forbids defaults on blob and text columns
super
end
+
+ def blob_or_text_column?
+ sql_type =~ /blob/i || type == :text
+ end
# Must return the relevant concrete adapter
def adapter
diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb
index fd36a5b075..fb28ecb6cf 100644
--- a/activerecord/lib/active_record/connection_adapters/column.rb
+++ b/activerecord/lib/active_record/connection_adapters/column.rb
@@ -206,7 +206,7 @@ module ActiveRecord
when TrueClass, FalseClass
value ? 1 : 0
else
- value.to_i
+ value.to_i rescue nil
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb
index 34d7a246b2..9b5170f657 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb
@@ -1,5 +1,3 @@
-require 'active_support/deprecation'
-
module ActiveRecord
module ConnectionAdapters
class PostgreSQLAdapter < AbstractAdapter
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
index 18ea83ce42..02c295983f 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
@@ -82,7 +82,7 @@ module ActiveRecord
def type_cast(value)
return if value.nil?
- value.to_i rescue value ? 1 : 0
+ ConnectionAdapters::Column.value_to_integer value
end
end
@@ -276,6 +276,7 @@ module ActiveRecord
register_type 'circle', OID::Identity.new
register_type 'hstore', OID::Hstore.new
register_type 'json', OID::Json.new
+ register_type 'ltree', OID::Identity.new
register_type 'int4range', OID::IntRange.new
alias_type 'int8range', 'int4range'
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index d62a375470..b1b0467379 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -17,22 +17,25 @@ require 'ipaddr'
module ActiveRecord
module ConnectionHandling
+ VALID_CONN_PARAMS = [:host, :hostaddr, :port, :dbname, :user, :password, :connect_timeout,
+ :client_encoding, :options, :application_name, :fallback_application_name,
+ :keepalives, :keepalives_idle, :keepalives_interval, :keepalives_count,
+ :tty, :sslmode, :requiressl, :sslcert, :sslkey, :sslrootcert, :sslcrl,
+ :requirepeer, :krbsrvname, :gsslib, :service]
+
# Establishes a connection to the database that's used by all Active Record objects
def postgresql_connection(config) # :nodoc:
conn_params = config.symbolize_keys
- # Forward any unused config params to PGconn.connect.
- [:statement_limit, :encoding, :min_messages, :schema_search_path,
- :schema_order, :adapter, :pool, :checkout_timeout, :template,
- :reaping_frequency, :insert_returning, :variables].each do |key|
- conn_params.delete key
- end
- conn_params.delete_if { |k,v| v.nil? }
+ conn_params.delete_if { |_, v| v.nil? }
# Map ActiveRecords param names to PGs.
conn_params[:user] = conn_params.delete(:username) if conn_params[:username]
conn_params[:dbname] = conn_params.delete(:database) if conn_params[:database]
+ # Forward only valid config params to PGconn.connect.
+ conn_params.keep_if { |k, _| VALID_CONN_PARAMS.include?(k) }
+
# The postgres drivers don't allow the creation of an unconnected PGconn object,
# so just pass a nil connection object for the time being.
ConnectionAdapters::PostgreSQLAdapter.new(nil, logger, conn_params, config)
@@ -173,6 +176,8 @@ module ActiveRecord
:decimal
when 'hstore'
:hstore
+ when 'ltree'
+ :ltree
# Network address types
when 'inet'
:inet
@@ -275,6 +280,10 @@ module ActiveRecord
column(name, 'hstore', options)
end
+ def ltree(name, options = {})
+ column(name, 'ltree', options)
+ end
+
def inet(name, options = {})
column(name, 'inet', options)
end
@@ -340,7 +349,8 @@ module ActiveRecord
macaddr: { name: "macaddr" },
uuid: { name: "uuid" },
json: { name: "json" },
- intrange: { name: "int4range" }
+ intrange: { name: "int4range" },
+ ltree: { name: "ltree" }
}
include Quoting
@@ -451,8 +461,6 @@ module ActiveRecord
@visitor = BindSubstitution.new self
end
- connection_parameters.delete :prepared_statements
-
@connection_parameters, @config = connection_parameters, config
# @local_tz is initialized as nil to avoid warnings when connect tries to use it
@@ -640,32 +648,30 @@ module ActiveRecord
end
def exec_cache(sql, binds)
+ stmt_key = prepare_statement sql
+
+ # Clear the queue
+ @connection.get_last_result
+ @connection.send_query_prepared(stmt_key, binds.map { |col, val|
+ type_cast(val, col)
+ })
+ @connection.block
+ @connection.get_last_result
+ rescue PGError => e
+ # Get the PG code for the failure. Annoyingly, the code for
+ # prepared statements whose return value may have changed is
+ # FEATURE_NOT_SUPPORTED. Check here for more details:
+ # http://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/cache/plancache.c#l573
begin
- stmt_key = prepare_statement sql
-
- # Clear the queue
- @connection.get_last_result
- @connection.send_query_prepared(stmt_key, binds.map { |col, val|
- type_cast(val, col)
- })
- @connection.block
- @connection.get_last_result
- rescue PGError => e
- # Get the PG code for the failure. Annoyingly, the code for
- # prepared statements whose return value may have changed is
- # FEATURE_NOT_SUPPORTED. Check here for more details:
- # http://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/cache/plancache.c#l573
- begin
- code = e.result.result_error_field(PGresult::PG_DIAG_SQLSTATE)
- rescue
- raise e
- end
- if FEATURE_NOT_SUPPORTED == code
- @statements.delete sql_key(sql)
- retry
- else
- raise e
- end
+ code = e.result.result_error_field(PGresult::PG_DIAG_SQLSTATE)
+ rescue
+ raise e
+ end
+ if FEATURE_NOT_SUPPORTED == code
+ @statements.delete sql_key(sql)
+ retry
+ else
+ raise e
end
end
diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb
index ea3bb8f33f..5a4ef5991d 100644
--- a/activerecord/lib/active_record/fixtures.rb
+++ b/activerecord/lib/active_record/fixtures.rb
@@ -5,8 +5,6 @@ require 'active_support/dependencies'
require 'active_record/fixture_set/file'
require 'active_record/errors'
-require 'active_support/deprecation' # temporary
-
module ActiveRecord
class FixtureClassNotFound < ActiveRecord::ActiveRecordError #:nodoc:
end
diff --git a/activerecord/lib/active_record/inheritance.rb b/activerecord/lib/active_record/inheritance.rb
index 6ab67fdece..e630897a4b 100644
--- a/activerecord/lib/active_record/inheritance.rb
+++ b/activerecord/lib/active_record/inheritance.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/hash/indifferent_access'
+
module ActiveRecord
module Inheritance
extend ActiveSupport::Concern
diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb
index 035c77c424..701949e57b 100644
--- a/activerecord/lib/active_record/locking/optimistic.rb
+++ b/activerecord/lib/active_record/locking/optimistic.rb
@@ -66,7 +66,7 @@ module ActiveRecord
send(lock_col + '=', previous_lock_value + 1)
end
- def update(attribute_names = @attributes.keys) #:nodoc:
+ def update_record(attribute_names = @attributes.keys) #:nodoc:
return super unless locking_enabled?
return 0 if attribute_names.empty?
diff --git a/activerecord/lib/active_record/locking/pessimistic.rb b/activerecord/lib/active_record/locking/pessimistic.rb
index b4bb95a392..8e4ddcac82 100644
--- a/activerecord/lib/active_record/locking/pessimistic.rb
+++ b/activerecord/lib/active_record/locking/pessimistic.rb
@@ -26,7 +26,7 @@ module ActiveRecord
#
# Account.transaction do
# # select * from accounts where ...
- # accounts = Account.where(...).all
+ # accounts = Account.where(...)
# account1 = accounts.detect { |account| ... }
# account2 = accounts.detect { |account| ... }
# # select * from accounts where id=? for update
diff --git a/activerecord/lib/active_record/log_subscriber.rb b/activerecord/lib/active_record/log_subscriber.rb
index 2366a91bb5..c1ba524c84 100644
--- a/activerecord/lib/active_record/log_subscriber.rb
+++ b/activerecord/lib/active_record/log_subscriber.rb
@@ -21,13 +21,15 @@ module ActiveRecord
end
def render_bind(column, value)
- if column.type == :binary
- rendered_value = "<#{value.bytesize} bytes of binary data>"
+ if column
+ if column.binary?
+ value = "<#{value.bytesize} bytes of binary data>"
+ end
+
+ [column.name, value]
else
- rendered_value = value
+ [nil, value]
end
-
- [column.name, rendered_value]
end
def sql(event)
diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb
index 4c9bd76d7c..c5bd11edbf 100644
--- a/activerecord/lib/active_record/nested_attributes.rb
+++ b/activerecord/lib/active_record/nested_attributes.rb
@@ -58,7 +58,7 @@ module ActiveRecord
# It also allows you to update the avatar through the member:
#
# params = { member: { avatar_attributes: { id: '2', icon: 'sad' } } }
- # member.update_attributes params[:member]
+ # member.update params[:member]
# member.avatar.icon # => 'sad'
#
# By default you will only be able to set and update attributes on the
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb
index 4d1a9c94b7..3011f959a5 100644
--- a/activerecord/lib/active_record/persistence.rb
+++ b/activerecord/lib/active_record/persistence.rb
@@ -212,7 +212,7 @@ module ActiveRecord
# Updates the attributes of the model from the passed-in hash and saves the
# record, all wrapped in a transaction. If the object is invalid, the saving
# will fail and false will be returned.
- def update_attributes(attributes)
+ def update(attributes)
# The following transaction covers any possible database side-effects of the
# attributes assignment. For example, setting the IDs of a child collection.
with_transaction_returning_status do
@@ -220,10 +220,12 @@ module ActiveRecord
save
end
end
+
+ alias update_attributes update
- # Updates its receiver just like +update_attributes+ but calls <tt>save!</tt> instead
+ # Updates its receiver just like +update+ but calls <tt>save!</tt> instead
# of +save+, so an exception is raised if the record is invalid.
- def update_attributes!(attributes)
+ def update!(attributes)
# The following transaction covers any possible database side-effects of the
# attributes assignment. For example, setting the IDs of a child collection.
with_transaction_returning_status do
@@ -231,6 +233,8 @@ module ActiveRecord
save!
end
end
+
+ alias update_attributes! update!
# Updates a single attribute of an object, without having to explicitly call save on that object.
#
@@ -406,13 +410,13 @@ module ActiveRecord
def create_or_update
raise ReadOnlyRecord if readonly?
- result = new_record? ? create : update
+ result = new_record? ? create_record : update_record
result != false
end
# Updates the associated record with values matching those of the instance attributes.
# Returns the number of affected rows.
- def update(attribute_names = @attributes.keys)
+ def update_record(attribute_names = @attributes.keys)
attributes_with_values = arel_attributes_with_values_for_update(attribute_names)
if attributes_with_values.empty?
@@ -426,7 +430,7 @@ module ActiveRecord
# Creates a record with values matching those of the instance attributes
# and returns its id.
- def create(attribute_names = @attributes.keys)
+ def create_record(attribute_names = @attributes.keys)
attributes_values = arel_attributes_with_values_for_create(attribute_names)
new_id = self.class.unscoped.insert attributes_values
diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb
index 1081b82bc6..aceb70bc45 100644
--- a/activerecord/lib/active_record/railtie.rb
+++ b/activerecord/lib/active_record/railtie.rb
@@ -112,7 +112,7 @@ module ActiveRecord
`config/application.rb` file and any `mass_assignment_sanitizer` options
from your `config/environments/*.rb` files.
- See http://edgeguides.rubyonrails.org/security.html#mass-assignment for more information
+ See http://guides.rubyonrails.org/security.html#mass-assignment for more information
EOF
end
@@ -124,7 +124,7 @@ module ActiveRecord
To disable this message remove the `observers` option from your
`config/application.rb` or from your initializers.
- See http://edgeguides.rubyonrails.org/4_0_release_notes.html for more information
+ See http://guides.rubyonrails.org/4_0_release_notes.html for more information
EOF
end
ensure
diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake
index b25c0270c2..259d0ff12b 100644
--- a/activerecord/lib/active_record/railties/databases.rake
+++ b/activerecord/lib/active_record/railties/databases.rake
@@ -300,7 +300,9 @@ db_namespace = namespace :db do
end
if ActiveRecord::Base.connection.supports_migrations?
- File.open(filename, "a") { |f| f << ActiveRecord::Base.connection.dump_schema_information }
+ File.open(filename, "a") do |f|
+ f.puts ActiveRecord::Base.connection.dump_schema_information
+ end
end
db_namespace['structure:dump'].reenable
end
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb
index 0df895eb67..6ec5cf3e18 100644
--- a/activerecord/lib/active_record/relation.rb
+++ b/activerecord/lib/active_record/relation.rb
@@ -308,7 +308,7 @@ module ActiveRecord
id.map.with_index { |one_id, idx| update(one_id, attributes[idx]) }
else
object = find(id)
- object.update_attributes(attributes)
+ object.update(attributes)
object
end
end
diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb
index ccc14dddeb..3f154bd1cc 100644
--- a/activerecord/lib/active_record/relation/calculations.rb
+++ b/activerecord/lib/active_record/relation/calculations.rb
@@ -1,5 +1,3 @@
-require 'active_support/deprecation'
-
module ActiveRecord
module Calculations
# Count the records.
@@ -231,6 +229,8 @@ module ActiveRecord
# Postgresql doesn't like ORDER BY when there are no GROUP BY
relation = reorder(nil)
+ column_alias = column_name
+
if operation == "count" && (relation.limit_value || relation.offset_value)
# Shortcut when limit is zero.
return 0 if relation.limit_value == 0
@@ -241,13 +241,20 @@ module ActiveRecord
select_value = operation_over_aggregate_column(column, operation, distinct)
+ column_alias = select_value.alias
relation.select_values = [select_value]
query_builder = relation.arel
end
- result = @klass.connection.select_value(query_builder, nil, relation.bind_values)
- type_cast_calculated_value(result, column_for(column_name), operation)
+ result = @klass.connection.select_all(query_builder, nil, relation.bind_values)
+ row = result.first
+ value = row && row.values.first
+ column = result.column_types.fetch(column_alias) do
+ column_for(column_name)
+ end
+
+ type_cast_calculated_value(value, column, operation)
end
def execute_grouped_calculation(operation, column_name, distinct) #:nodoc:
@@ -265,7 +272,7 @@ module ActiveRecord
column_alias_for(field)
}
group_columns = group_aliases.zip(group_fields).map { |aliaz,field|
- [aliaz, column_for(field)]
+ [aliaz, field]
}
group = group_fields
@@ -305,7 +312,10 @@ module ActiveRecord
end
Hash[calculated_data.map do |row|
- key = group_columns.map { |aliaz, column|
+ key = group_columns.map { |aliaz, col_name|
+ column = calculated_data.column_types.fetch(aliaz) do
+ column_for(col_name)
+ end
type_cast_calculated_value(row[aliaz], column)
}
key = key.first if key.size == 1
diff --git a/activerecord/lib/active_record/relation/delegation.rb b/activerecord/lib/active_record/relation/delegation.rb
index 431d083f21..615309964c 100644
--- a/activerecord/lib/active_record/relation/delegation.rb
+++ b/activerecord/lib/active_record/relation/delegation.rb
@@ -1,4 +1,3 @@
-require 'active_support/concern'
require 'thread'
require 'thread_safe'
diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb
index d417e82548..de784f9f57 100644
--- a/activerecord/lib/active_record/relation/spawn_methods.rb
+++ b/activerecord/lib/active_record/relation/spawn_methods.rb
@@ -50,10 +50,7 @@ module ActiveRecord
# Post.order('id asc').except(:order) # discards the order condition
# Post.where('id > 10').order('id asc').except(:where) # discards the where condition but keeps the order
def except(*skips)
- result = Relation.new(klass, table, values.except(*skips))
- result.default_scoped = default_scoped
- result.extend(*extending_values) if extending_values.any?
- result
+ relation_with values.except(*skips)
end
# Removes any condition from the query other than the one(s) specified in +onlies+.
@@ -61,11 +58,16 @@ module ActiveRecord
# Post.order('id asc').only(:where) # discards the order condition
# Post.order('id asc').only(:where, :order) # uses the specified order
def only(*onlies)
- result = Relation.new(klass, table, values.slice(*onlies))
- result.default_scoped = default_scoped
- result.extend(*extending_values) if extending_values.any?
- result
+ relation_with values.slice(*onlies)
end
+ private
+
+ def relation_with(values) # :nodoc:
+ result = Relation.new(klass, table, values)
+ result.default_scoped = default_scoped
+ result.extend(*extending_values) if extending_values.any?
+ result
+ end
end
end
diff --git a/activerecord/lib/active_record/scoping/named.rb b/activerecord/lib/active_record/scoping/named.rb
index 8b7eda6eee..01fbb96b8e 100644
--- a/activerecord/lib/active_record/scoping/named.rb
+++ b/activerecord/lib/active_record/scoping/named.rb
@@ -134,16 +134,14 @@ module ActiveRecord
# end
#
# def self.titles
- # map(&:title)
+ # pluck(:title)
# end
- #
# end
#
# We are able to call the methods like this:
#
# Article.published.featured.latest_article
# Article.featured.titles
-
def scope(name, body, &block)
extension = Module.new(&block) if block
diff --git a/activerecord/lib/active_record/store.rb b/activerecord/lib/active_record/store.rb
index df7f58c81f..cf4cf9e602 100644
--- a/activerecord/lib/active_record/store.rb
+++ b/activerecord/lib/active_record/store.rb
@@ -107,7 +107,7 @@ module ActiveRecord
private
def initialize_store_attribute(store_attribute)
attribute = send(store_attribute)
- unless attribute.is_a?(HashWithIndifferentAccess)
+ unless attribute.is_a?(ActiveSupport::HashWithIndifferentAccess)
attribute = IndifferentCoder.as_indifferent_hash(attribute)
send :"#{store_attribute}=", attribute
end
@@ -134,12 +134,12 @@ module ActiveRecord
def self.as_indifferent_hash(obj)
case obj
- when HashWithIndifferentAccess
+ when ActiveSupport::HashWithIndifferentAccess
obj
when Hash
obj.with_indifferent_access
else
- HashWithIndifferentAccess.new
+ ActiveSupport::HashWithIndifferentAccess.new
end
end
end
diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb
index cf17b1d8a4..8ded6d4a86 100644
--- a/activerecord/lib/active_record/timestamp.rb
+++ b/activerecord/lib/active_record/timestamp.rb
@@ -43,7 +43,7 @@ module ActiveRecord
private
- def create
+ def create_record
if self.record_timestamps
current_time = current_time_from_proper_timezone
@@ -57,7 +57,7 @@ module ActiveRecord
super
end
- def update(*args)
+ def update_record(*args)
if should_record_timestamps?
current_time = current_time_from_proper_timezone
diff --git a/activerecord/test/cases/adapters/mysql/active_schema_test.rb b/activerecord/test/cases/adapters/mysql/active_schema_test.rb
index 94fc3564df..8812cf1b7d 100644
--- a/activerecord/test/cases/adapters/mysql/active_schema_test.rb
+++ b/activerecord/test/cases/adapters/mysql/active_schema_test.rb
@@ -42,7 +42,7 @@ class ActiveSchemaTest < ActiveRecord::TestCase
assert_equal "DROP TABLE `people`", drop_table(:people)
end
- if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
+ if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
def test_create_mysql_database_with_encoding
assert_equal "CREATE DATABASE `matt` DEFAULT CHARACTER SET `utf8`", create_database(:matt)
assert_equal "CREATE DATABASE `aimonetti` DEFAULT CHARACTER SET `latin1`", create_database(:aimonetti, {:charset => 'latin1'})
diff --git a/activerecord/test/cases/adapters/mysql/mysql_adapter_test.rb b/activerecord/test/cases/adapters/mysql/mysql_adapter_test.rb
index ddfe42b375..0eb1cc511e 100644
--- a/activerecord/test/cases/adapters/mysql/mysql_adapter_test.rb
+++ b/activerecord/test/cases/adapters/mysql/mysql_adapter_test.rb
@@ -49,13 +49,11 @@ module ActiveRecord
end
def test_tables_quoting
- begin
- @conn.tables(nil, "foo-bar", nil)
- flunk
- rescue => e
- # assertion for *quoted* database properly
- assert_match(/database 'foo-bar'/, e.inspect)
- end
+ @conn.tables(nil, "foo-bar", nil)
+ flunk
+ rescue => e
+ # assertion for *quoted* database properly
+ assert_match(/database 'foo-bar'/, e.inspect)
end
def test_pk_and_sequence_for
diff --git a/activerecord/test/cases/adapters/mysql2/schema_test.rb b/activerecord/test/cases/adapters/mysql2/schema_test.rb
index 2c0ed73c92..94429e772f 100644
--- a/activerecord/test/cases/adapters/mysql2/schema_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/schema_test.rb
@@ -37,13 +37,11 @@ module ActiveRecord
end
def test_tables_quoting
- begin
- @connection.tables(nil, "foo-bar", nil)
- flunk
- rescue => e
- # assertion for *quoted* database properly
- assert_match(/database 'foo-bar'/, e.inspect)
- end
+ @connection.tables(nil, "foo-bar", nil)
+ flunk
+ rescue => e
+ # assertion for *quoted* database properly
+ assert_match(/database 'foo-bar'/, e.inspect)
end
end
diff --git a/activerecord/test/cases/adapters/postgresql/datatype_test.rb b/activerecord/test/cases/adapters/postgresql/datatype_test.rb
index c7ce43d71e..2254be8612 100644
--- a/activerecord/test/cases/adapters/postgresql/datatype_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/datatype_test.rb
@@ -30,6 +30,9 @@ end
class PostgresqlUUID < ActiveRecord::Base
end
+class PostgresqlLtree < ActiveRecord::Base
+end
+
class PostgresqlDataTypeTest < ActiveRecord::TestCase
self.use_transactional_fixtures = false
@@ -37,38 +40,43 @@ class PostgresqlDataTypeTest < ActiveRecord::TestCase
@connection = ActiveRecord::Base.connection
@connection.execute("set lc_monetary = 'C'")
- @connection.execute("INSERT INTO postgresql_arrays (commission_by_quarter, nicknames) VALUES ( '{35000,21000,18000,17000}', '{foo,bar,baz}' )")
+ @connection.execute("INSERT INTO postgresql_arrays (id, commission_by_quarter, nicknames) VALUES (1, '{35000,21000,18000,17000}', '{foo,bar,baz}')")
@first_array = PostgresqlArray.find(1)
- @connection.execute("INSERT INTO postgresql_tsvectors (text_vector) VALUES (' ''text'' ''vector'' ')")
+ @connection.execute("INSERT INTO postgresql_tsvectors (id, text_vector) VALUES (1, ' ''text'' ''vector'' ')")
@first_tsvector = PostgresqlTsvector.find(1)
- @connection.execute("INSERT INTO postgresql_moneys (wealth) VALUES ('567.89'::money)")
- @connection.execute("INSERT INTO postgresql_moneys (wealth) VALUES ('-567.89'::money)")
+ @connection.execute("INSERT INTO postgresql_moneys (id, wealth) VALUES (1, '567.89'::money)")
+ @connection.execute("INSERT INTO postgresql_moneys (id, wealth) VALUES (2, '-567.89'::money)")
@first_money = PostgresqlMoney.find(1)
@second_money = PostgresqlMoney.find(2)
- @connection.execute("INSERT INTO postgresql_numbers (single, double) VALUES (123.456, 123456.789)")
+ @connection.execute("INSERT INTO postgresql_numbers (id, single, double) VALUES (1, 123.456, 123456.789)")
@first_number = PostgresqlNumber.find(1)
- @connection.execute("INSERT INTO postgresql_times (time_interval, scaled_time_interval) VALUES ('1 year 2 days ago', '3 weeks ago')")
+ @connection.execute("INSERT INTO postgresql_times (id, time_interval, scaled_time_interval) VALUES (1, '1 year 2 days ago', '3 weeks ago')")
@first_time = PostgresqlTime.find(1)
- @connection.execute("INSERT INTO postgresql_network_addresses (cidr_address, inet_address, mac_address) VALUES('192.168.0/24', '172.16.1.254/32', '01:23:45:67:89:0a')")
+ @connection.execute("INSERT INTO postgresql_network_addresses (id, cidr_address, inet_address, mac_address) VALUES(1, '192.168.0/24', '172.16.1.254/32', '01:23:45:67:89:0a')")
@first_network_address = PostgresqlNetworkAddress.find(1)
- @connection.execute("INSERT INTO postgresql_bit_strings (bit_string, bit_string_varying) VALUES (B'00010101', X'15')")
+ @connection.execute("INSERT INTO postgresql_bit_strings (id, bit_string, bit_string_varying) VALUES (1, B'00010101', X'15')")
@first_bit_string = PostgresqlBitString.find(1)
- @connection.execute("INSERT INTO postgresql_oids (obj_id) VALUES (1234)")
+ @connection.execute("INSERT INTO postgresql_oids (id, obj_id) VALUES (1, 1234)")
@first_oid = PostgresqlOid.find(1)
- @connection.execute("INSERT INTO postgresql_timestamp_with_zones (time) VALUES ('2010-01-01 10:00:00-1')")
+ @connection.execute("INSERT INTO postgresql_timestamp_with_zones (id, time) VALUES (1, '2010-01-01 10:00:00-1')")
- @connection.execute("INSERT INTO postgresql_uuids (guid, compact_guid) VALUES('d96c3da0-96c1-012f-1316-64ce8f32c6d8', 'f06c715096c1012f131764ce8f32c6d8')")
+ @connection.execute("INSERT INTO postgresql_uuids (id, guid, compact_guid) VALUES(1, 'd96c3da0-96c1-012f-1316-64ce8f32c6d8', 'f06c715096c1012f131764ce8f32c6d8')")
@first_uuid = PostgresqlUUID.find(1)
end
+ def teardown
+ [PostgresqlArray, PostgresqlTsvector, PostgresqlMoney, PostgresqlNumber, PostgresqlTime, PostgresqlNetworkAddress,
+ PostgresqlBitString, PostgresqlOid, PostgresqlTimestampWithZone, PostgresqlUUID].each(&:delete_all)
+ end
+
def test_data_type_of_array_types
assert_equal :integer, @first_array.column_for_attribute(:commission_by_quarter).type
assert_equal :text, @first_array.column_for_attribute(:nicknames).type
diff --git a/activerecord/test/cases/adapters/postgresql/ltree_test.rb b/activerecord/test/cases/adapters/postgresql/ltree_test.rb
new file mode 100644
index 0000000000..5d12ca75ca
--- /dev/null
+++ b/activerecord/test/cases/adapters/postgresql/ltree_test.rb
@@ -0,0 +1,41 @@
+# encoding: utf-8
+require "cases/helper"
+require 'active_record/base'
+require 'active_record/connection_adapters/postgresql_adapter'
+
+class PostgresqlLtreeTest < ActiveRecord::TestCase
+ class Ltree < ActiveRecord::Base
+ self.table_name = 'ltrees'
+ end
+
+ def setup
+ @connection = ActiveRecord::Base.connection
+ @connection.transaction do
+ @connection.create_table('ltrees') do |t|
+ t.ltree 'path'
+ end
+ end
+ rescue ActiveRecord::StatementInvalid
+ skip "do not test on PG without ltree"
+ end
+
+ def teardown
+ @connection.execute 'drop table if exists ltrees'
+ end
+
+ def test_column
+ column = Ltree.columns_hash['path']
+ assert_equal :ltree, column.type
+ end
+
+ def test_write
+ ltree = Ltree.new(path: '1.2.3.4')
+ assert ltree.save!
+ end
+
+ def test_select
+ @connection.execute "insert into ltrees (path) VALUES ('1.2.3')"
+ ltree = Ltree.first
+ assert_equal '1.2.3', ltree.path
+ end
+end
diff --git a/activerecord/test/cases/adapters/postgresql/timestamp_test.rb b/activerecord/test/cases/adapters/postgresql/timestamp_test.rb
index 630bdeec67..dbc69a529c 100644
--- a/activerecord/test/cases/adapters/postgresql/timestamp_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/timestamp_test.rb
@@ -1,7 +1,16 @@
require 'cases/helper'
require 'models/developer'
+require 'models/topic'
class TimestampTest < ActiveRecord::TestCase
+ fixtures :topics
+
+ def test_group_by_date
+ keys = Topic.group("date_trunc('month', created_at)").count.keys
+ assert_operator keys.length, :>, 0
+ keys.each { |k| assert_kind_of Time, k }
+ end
+
def test_load_infinity_and_beyond
unless current_adapter?(:PostgreSQLAdapter)
return skip("only tested on postgresql")
diff --git a/activerecord/test/cases/aggregations_test.rb b/activerecord/test/cases/aggregations_test.rb
index 48b06a767f..10195e3ae4 100644
--- a/activerecord/test/cases/aggregations_test.rb
+++ b/activerecord/test/cases/aggregations_test.rb
@@ -1,6 +1,5 @@
require "cases/helper"
require 'models/customer'
-require 'active_support/core_ext/exception'
class AggregationsTest < ActiveRecord::TestCase
fixtures :customers
@@ -26,7 +25,7 @@ class AggregationsTest < ActiveRecord::TestCase
def test_immutable_value_objects
customers(:david).balance = Money.new(100)
- assert_raise(ActiveSupport::FrozenObjectError) { customers(:david).balance.instance_eval { @amount = 20 } }
+ assert_raise(RuntimeError) { customers(:david).balance.instance_eval { @amount = 20 } }
end
def test_inferred_mapping
diff --git a/activerecord/test/cases/ar_schema_test.rb b/activerecord/test/cases/ar_schema_test.rb
index b2eac0349b..aa5b27623e 100644
--- a/activerecord/test/cases/ar_schema_test.rb
+++ b/activerecord/test/cases/ar_schema_test.rb
@@ -7,6 +7,7 @@ if ActiveRecord::Base.connection.supports_migrations?
def setup
@connection = ActiveRecord::Base.connection
+ ActiveRecord::SchemaMigration.drop_table
end
def teardown
@@ -45,5 +46,4 @@ if ActiveRecord::Base.connection.supports_migrations?
assert_nothing_raised { @connection.select_all "SELECT * FROM fruits" }
end
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 04d0f755b6..3a6da0e59f 100644
--- a/activerecord/test/cases/associations/belongs_to_associations_test.rb
+++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb
@@ -33,7 +33,7 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
def test_belongs_to_with_primary_key_joins_on_correct_column
sql = Client.joins(:firm_with_primary_key).to_sql
- if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
+ if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
assert_no_match(/`firm_with_primary_keys_companies`\.`id`/, sql)
assert_match(/`firm_with_primary_keys_companies`\.`name`/, sql)
elsif current_adapter?(:OracleAdapter)
@@ -63,6 +63,13 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
assert_equal apple.id, citibank.firm_id
end
+ def test_id_assignment
+ apple = Firm.create("name" => "Apple")
+ citibank = Account.create("credit_limit" => 10)
+ citibank.firm_id = apple
+ assert_nil citibank.firm_id
+ end
+
def test_natural_assignment_with_primary_key
apple = Firm.create("name" => "Apple")
citibank = Client.create("name" => "Primary key client")
@@ -317,12 +324,12 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
assert_equal 1, Topic.find(topic.id)[:replies_count]
end
- def test_belongs_to_counter_after_update_attributes
- topic = Topic.create!(:title => "37s")
- topic.replies.create!(:title => "re: 37s", :content => "rails")
+ def test_belongs_to_counter_after_update
+ topic = Topic.create!(title: "37s")
+ topic.replies.create!(title: "re: 37s", content: "rails")
assert_equal 1, Topic.find(topic.id)[:replies_count]
- topic.update_attributes(:title => "37signals")
+ topic.update(title: "37signals")
assert_equal 1, Topic.find(topic.id)[:replies_count]
end
@@ -567,6 +574,11 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
assert_equal new_firm.name, "Apple"
end
+ def test_attributes_are_set_without_error_when_initialized_from_belongs_to_association_with_array_in_where_clause
+ new_account = Account.where(:credit_limit => [ 50, 60 ]).new
+ assert_nil new_account.credit_limit
+ end
+
def test_reassigning_the_parent_id_updates_the_object
client = companies(:second_client)
diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb
index 94437380a4..be2d30641e 100644
--- a/activerecord/test/cases/associations/eager_test.rb
+++ b/activerecord/test/cases/associations/eager_test.rb
@@ -93,31 +93,31 @@ class EagerAssociationTest < ActiveRecord::TestCase
end
def test_preloading_has_many_in_multiple_queries_with_more_ids_than_database_can_handle
- Post.connection.expects(:in_clause_length).at_least_once.returns(5)
+ Comment.connection.expects(:in_clause_length).at_least_once.returns(5)
posts = Post.all.merge!(:includes=>:comments).to_a
assert_equal 11, posts.size
end
def test_preloading_has_many_in_one_queries_when_database_has_no_limit_on_ids_it_can_handle
- Post.connection.expects(:in_clause_length).at_least_once.returns(nil)
+ Comment.connection.expects(:in_clause_length).at_least_once.returns(nil)
posts = Post.all.merge!(:includes=>:comments).to_a
assert_equal 11, posts.size
end
def test_preloading_habtm_in_multiple_queries_with_more_ids_than_database_can_handle
- Post.connection.expects(:in_clause_length).at_least_once.returns(5)
+ Comment.connection.expects(:in_clause_length).at_least_once.returns(5)
posts = Post.all.merge!(:includes=>:categories).to_a
assert_equal 11, posts.size
end
def test_preloading_habtm_in_one_queries_when_database_has_no_limit_on_ids_it_can_handle
- Post.connection.expects(:in_clause_length).at_least_once.returns(nil)
+ Comment.connection.expects(:in_clause_length).at_least_once.returns(nil)
posts = Post.all.merge!(:includes=>:categories).to_a
assert_equal 11, posts.size
end
def test_load_associated_records_in_one_query_when_adapter_has_no_limit
- Post.connection.expects(:in_clause_length).at_least_once.returns(nil)
+ Comment.connection.expects(:in_clause_length).at_least_once.returns(nil)
post = posts(:welcome)
assert_queries(2) do
@@ -126,7 +126,7 @@ class EagerAssociationTest < ActiveRecord::TestCase
end
def test_load_associated_records_in_several_queries_when_many_ids_passed
- Post.connection.expects(:in_clause_length).at_least_once.returns(1)
+ Comment.connection.expects(:in_clause_length).at_least_once.returns(1)
post1, post2 = posts(:welcome), posts(:thinking)
assert_queries(3) do
@@ -135,7 +135,7 @@ class EagerAssociationTest < ActiveRecord::TestCase
end
def test_load_associated_records_in_one_query_when_a_few_ids_passed
- Post.connection.expects(:in_clause_length).at_least_once.returns(3)
+ Comment.connection.expects(:in_clause_length).at_least_once.returns(3)
post = posts(:welcome)
assert_queries(2) do
@@ -212,8 +212,9 @@ class EagerAssociationTest < ActiveRecord::TestCase
def test_finding_with_includes_on_null_belongs_to_association_with_same_include_includes_only_once
post = posts(:welcome)
- post.update_attributes!(:author => nil)
- post = assert_queries(1) { Post.all.merge!(:includes => {:author_with_address => :author_address}).find(post.id) } # find the post, then find the author which is null so no query for the author or address
+ post.update!(author: nil)
+ post = assert_queries(1) { Post.all.merge!(includes: {author_with_address: :author_address}).find(post.id) }
+ # find the post, then find the author which is null so no query for the author or address
assert_no_queries do
assert_equal nil, post.author_with_address
end
@@ -221,7 +222,7 @@ class EagerAssociationTest < ActiveRecord::TestCase
def test_finding_with_includes_on_null_belongs_to_polymorphic_association
sponsor = sponsors(:moustache_club_sponsor_for_groucho)
- sponsor.update_attributes!(:sponsorable => nil)
+ sponsor.update!(sponsorable: nil)
sponsor = assert_queries(1) { Sponsor.all.merge!(:includes => :sponsorable).find(sponsor.id) }
assert_no_queries do
assert_equal nil, sponsor.sponsorable
diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb
index 2b96b42032..af91fb2920 100644
--- a/activerecord/test/cases/associations/has_many_through_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb
@@ -706,7 +706,7 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
def test_can_update_through_association
assert_nothing_raised do
- people(:michael).posts.first.update_attributes!(:title => "Can write")
+ people(:michael).posts.first.update!(title: "Can write")
end
end
diff --git a/activerecord/test/cases/associations/join_model_test.rb b/activerecord/test/cases/associations/join_model_test.rb
index 9b00c21b52..10ec33be75 100644
--- a/activerecord/test/cases/associations/join_model_test.rb
+++ b/activerecord/test/cases/associations/join_model_test.rb
@@ -443,8 +443,8 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
def test_has_many_through_uses_conditions_specified_on_the_has_many_association
author = Author.first
- assert_present author.comments
- assert_blank author.nonexistant_comments
+ assert author.comments.present?
+ assert author.nonexistant_comments.blank?
end
def test_has_many_through_uses_correct_attributes
diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb
index 16ce150396..e5cb4f8f7a 100644
--- a/activerecord/test/cases/autosave_association_test.rb
+++ b/activerecord/test/cases/autosave_association_test.rb
@@ -161,16 +161,16 @@ class TestDefaultAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCas
end
def test_callbacks_firing_order_on_update
- eye = Eye.create(:iris_attributes => {:color => 'honey'})
- eye.update_attributes(:iris_attributes => {:color => 'green'})
+ eye = Eye.create(iris_attributes: {color: 'honey'})
+ eye.update(iris_attributes: {color: 'green'})
assert_equal [true, false], eye.after_update_callbacks_stack
end
def test_callbacks_firing_order_on_save
- eye = Eye.create(:iris_attributes => {:color => 'honey'})
+ eye = Eye.create(iris_attributes: {color: 'honey'})
assert_equal [false, false], eye.after_save_callbacks_stack
- eye.update_attributes(:iris_attributes => {:color => 'blue'})
+ eye.update(iris_attributes: {color: 'blue'})
assert_equal [false, false, false, false], eye.after_save_callbacks_stack
end
end
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index d326ed7863..4f46459ab3 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -26,7 +26,6 @@ require 'models/bird'
require 'models/car'
require 'models/bulb'
require 'rexml/document'
-require 'active_support/core_ext/exception'
class FirstAbstractClass < ActiveRecord::Base
self.abstract_class = true
@@ -125,7 +124,7 @@ class BasicsTest < ActiveRecord::TestCase
assert_nil Edge.primary_key
end
- unless current_adapter?(:PostgreSQLAdapter,:OracleAdapter,:SQLServerAdapter)
+ unless current_adapter?(:PostgreSQLAdapter, :OracleAdapter, :SQLServerAdapter)
def test_limit_with_comma
assert Topic.limit("1,2").to_a
end
@@ -154,7 +153,7 @@ class BasicsTest < ActiveRecord::TestCase
end
end
- unless current_adapter?(:MysqlAdapter) || current_adapter?(:Mysql2Adapter)
+ unless current_adapter?(:MysqlAdapter, :Mysql2Adapter)
def test_limit_should_allow_sql_literal
assert_equal 1, Topic.limit(Arel.sql('2-1')).to_a.length
end
@@ -223,7 +222,7 @@ class BasicsTest < ActiveRecord::TestCase
)
# For adapters which support microsecond resolution.
- if current_adapter?(:PostgreSQLAdapter) || current_adapter?(:SQLite3Adapter)
+ if current_adapter?(:PostgreSQLAdapter, :SQLite3Adapter)
assert_equal 11, Topic.find(1).written_on.sec
assert_equal 223300, Topic.find(1).written_on.usec
assert_equal 9900, Topic.find(2).written_on.usec
@@ -301,13 +300,11 @@ class BasicsTest < ActiveRecord::TestCase
end
def test_initialize_with_invalid_attribute
- begin
- Topic.new({ "title" => "test",
- "last_read(1i)" => "2005", "last_read(2i)" => "2", "last_read(3i)" => "31"})
- rescue ActiveRecord::MultiparameterAssignmentErrors => ex
- assert_equal(1, ex.errors.size)
- assert_equal("last_read", ex.errors[0].attribute)
- end
+ Topic.new({ "title" => "test",
+ "last_read(1i)" => "2005", "last_read(2i)" => "2", "last_read(3i)" => "31"})
+ rescue ActiveRecord::MultiparameterAssignmentErrors => ex
+ assert_equal(1, ex.errors.size)
+ assert_equal("last_read", ex.errors[0].attribute)
end
def test_create_after_initialize_without_block
@@ -472,7 +469,7 @@ class BasicsTest < ActiveRecord::TestCase
Post.reset_table_name
end
- if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
+ if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
def test_update_all_with_order_and_limit
assert_equal 1, Topic.limit(1).order('id DESC').update_all(:content => 'bulk updated!')
end
@@ -594,7 +591,7 @@ class BasicsTest < ActiveRecord::TestCase
post.reload
assert_equal "cannot change this", post.title
- post.update_attributes(:title => "try to change", :body => "changed")
+ post.update(title: "try to change", body: "changed")
post.reload
assert_equal "cannot change this", post.title
assert_equal "changed", post.body
@@ -1002,7 +999,7 @@ class BasicsTest < ActiveRecord::TestCase
def test_reload_with_exclusive_scope
dev = DeveloperCalledDavid.first
- dev.update_attributes!( :name => "NotDavid" )
+ dev.update!(name: "NotDavid" )
assert_equal dev, dev.reload
end
@@ -1484,7 +1481,7 @@ class BasicsTest < ActiveRecord::TestCase
def test_column_types_typecast
topic = Topic.first
- refute_equal 't.lo', topic.author_name
+ assert_not_equal 't.lo', topic.author_name
attrs = topic.attributes.dup
attrs.delete 'id'
diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb
index 5cb7eabf0e..b7622705bf 100644
--- a/activerecord/test/cases/calculations_test.rb
+++ b/activerecord/test/cases/calculations_test.rb
@@ -8,6 +8,7 @@ require 'models/possession'
require 'models/topic'
require 'models/minivan'
require 'models/speedometer'
+require 'models/ship_part'
Company.has_many :accounts
@@ -33,8 +34,9 @@ class CalculationsTest < ActiveRecord::TestCase
end
def test_should_return_integer_average_if_db_returns_such
- Account.connection.stubs :select_value => 3
- value = Account.average(:id)
+ ShipPart.delete_all
+ ShipPart.create!(:id => 3, :name => 'foo')
+ value = ShipPart.average(:id)
assert_equal 3, value
end
@@ -416,34 +418,19 @@ class CalculationsTest < ActiveRecord::TestCase
def test_maximum_with_not_auto_table_name_prefix_if_column_included
Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
- # TODO: Investigate why PG isn't being typecast
- if current_adapter?(:PostgreSQLAdapter) || current_adapter?(:MysqlAdapter)
- assert_equal "7", Company.includes(:contracts).maximum(:developer_id)
- else
- assert_equal 7, Company.includes(:contracts).maximum(:developer_id)
- end
+ assert_equal 7, Company.includes(:contracts).maximum(:developer_id)
end
def test_minimum_with_not_auto_table_name_prefix_if_column_included
Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
- # TODO: Investigate why PG isn't being typecast
- if current_adapter?(:PostgreSQLAdapter) || current_adapter?(:MysqlAdapter)
- assert_equal "7", Company.includes(:contracts).minimum(:developer_id)
- else
- assert_equal 7, Company.includes(:contracts).minimum(:developer_id)
- end
+ assert_equal 7, Company.includes(:contracts).minimum(:developer_id)
end
def test_sum_with_not_auto_table_name_prefix_if_column_included
Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
- # TODO: Investigate why PG isn't being typecast
- if current_adapter?(:MysqlAdapter) || current_adapter?(:PostgreSQLAdapter)
- assert_equal "7", Company.includes(:contracts).sum(:developer_id)
- else
- assert_equal 7, Company.includes(:contracts).sum(:developer_id)
- end
+ assert_equal 7, Company.includes(:contracts).sum(:developer_id)
end
diff --git a/activerecord/test/cases/column_test.rb b/activerecord/test/cases/column_test.rb
index 2124c256fa..adbe51f430 100644
--- a/activerecord/test/cases/column_test.rb
+++ b/activerecord/test/cases/column_test.rb
@@ -1,4 +1,5 @@
require "cases/helper"
+require 'models/company'
module ActiveRecord
module ConnectionAdapters
@@ -40,13 +41,26 @@ module ActiveRecord
def test_type_cast_non_integer_to_integer
column = Column.new("field", nil, "integer")
- assert_raises(NoMethodError) do
- column.type_cast([])
- end
+ assert_nil column.type_cast([1,2])
+ assert_nil column.type_cast({1 => 2})
+ assert_nil column.type_cast((1..2))
+ end
- assert_raises(NoMethodError) do
- column.type_cast(Object.new)
- end
+ def test_type_cast_activerecord_to_integer
+ column = Column.new("field", nil, "integer")
+ firm = Firm.create(:name => 'Apple')
+ assert_nil column.type_cast(firm)
+ end
+
+ def test_type_cast_object_without_to_i_to_integer
+ column = Column.new("field", nil, "integer")
+ assert_nil column.type_cast(Object.new)
+ end
+
+ def test_type_cast_nan_and_infinity_to_integer
+ column = Column.new("field", nil, "integer")
+ assert_nil column.type_cast(Float::NAN)
+ assert_nil column.type_cast(1.0/0.0)
end
def test_type_cast_time
diff --git a/activerecord/test/cases/connection_adapters/abstract_adapter_test.rb b/activerecord/test/cases/connection_adapters/abstract_adapter_test.rb
index 1eb9bf60e1..1fd64dd0af 100644
--- a/activerecord/test/cases/connection_adapters/abstract_adapter_test.rb
+++ b/activerecord/test/cases/connection_adapters/abstract_adapter_test.rb
@@ -10,18 +10,18 @@ module ActiveRecord
end
def test_in_use?
- refute adapter.in_use?, 'adapter is not in use'
+ assert_not adapter.in_use?, 'adapter is not in use'
assert adapter.lease, 'lease adapter'
assert adapter.in_use?, 'adapter is in use'
end
def test_lease_twice
assert adapter.lease, 'should lease adapter'
- refute adapter.lease, 'should not lease adapter'
+ assert_not adapter.lease, 'should not lease adapter'
end
def test_last_use
- refute adapter.last_use
+ assert_not adapter.last_use
adapter.lease
assert adapter.last_use
end
@@ -30,7 +30,7 @@ module ActiveRecord
assert adapter.lease, 'lease adapter'
assert adapter.in_use?, 'adapter is in use'
adapter.expire
- refute adapter.in_use?, 'adapter is in use'
+ assert_not adapter.in_use?, 'adapter is in use'
end
def test_close
@@ -44,7 +44,7 @@ module ActiveRecord
# Close should put the adapter back in the pool
adapter.close
- refute adapter.in_use?
+ assert_not adapter.in_use?
assert_equal adapter, pool.connection
end
diff --git a/activerecord/test/cases/connection_specification/resolver_test.rb b/activerecord/test/cases/connection_specification/resolver_test.rb
index ee9818678d..52de0efe7f 100644
--- a/activerecord/test/cases/connection_specification/resolver_test.rb
+++ b/activerecord/test/cases/connection_specification/resolver_test.rb
@@ -9,7 +9,7 @@ module ActiveRecord
end
def test_url_host_no_db
- skip "only if mysql is available" unless current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
+ skip "only if mysql is available" unless current_adapter?(:MysqlAdapter, :Mysql2Adapter)
spec = resolve 'mysql://foo?encoding=utf8'
assert_equal({
:adapter => "mysql",
@@ -18,7 +18,7 @@ module ActiveRecord
end
def test_url_host_db
- skip "only if mysql is available" unless current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
+ skip "only if mysql is available" unless current_adapter?(:MysqlAdapter, :Mysql2Adapter)
spec = resolve 'mysql://foo/bar?encoding=utf8'
assert_equal({
:adapter => "mysql",
@@ -28,7 +28,7 @@ module ActiveRecord
end
def test_url_port
- skip "only if mysql is available" unless current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
+ skip "only if mysql is available" unless current_adapter?(:MysqlAdapter, :Mysql2Adapter)
spec = resolve 'mysql://foo:123?encoding=utf8'
assert_equal({
:adapter => "mysql",
@@ -38,7 +38,7 @@ module ActiveRecord
end
def test_encoded_password
- skip "only if mysql is available" unless current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
+ skip "only if mysql is available" unless current_adapter?(:MysqlAdapter, :Mysql2Adapter)
password = 'am@z1ng_p@ssw0rd#!'
encoded_password = URI.encode_www_form_component(password)
spec = resolve "mysql://foo:#{encoded_password}@localhost/bar"
diff --git a/activerecord/test/cases/defaults_test.rb b/activerecord/test/cases/defaults_test.rb
index ed7eedaa27..e0cf4adf13 100644
--- a/activerecord/test/cases/defaults_test.rb
+++ b/activerecord/test/cases/defaults_test.rb
@@ -39,7 +39,7 @@ class DefaultTest < ActiveRecord::TestCase
end
end
-if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
+if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
class DefaultsTestWithoutTransactionalFixtures < ActiveRecord::TestCase
# ActiveRecord::Base#create! (and #save and other related methods) will
# open a new transaction. When in transactional fixtures mode, this will
diff --git a/activerecord/test/cases/deprecated_dynamic_methods_test.rb b/activerecord/test/cases/deprecated_dynamic_methods_test.rb
index dde36e7f72..8e842d8758 100644
--- a/activerecord/test/cases/deprecated_dynamic_methods_test.rb
+++ b/activerecord/test/cases/deprecated_dynamic_methods_test.rb
@@ -1,7 +1,7 @@
# This file should be deleted when activerecord-deprecated_finders is removed as
# a dependency.
#
-# It is kept for now as there is some fairly nuanced behaviour in the dynamic
+# It is kept for now as there is some fairly nuanced behavior in the dynamic
# finders so it is useful to keep this around to guard against regressions if
# we need to change the code.
@@ -568,9 +568,9 @@ class DynamicScopeTest < ActiveRecord::TestCase
end
def test_dynamic_scope_should_create_methods_after_hitting_method_missing
- assert_blank @test_klass.methods.grep(/scoped_by_type/)
+ assert @test_klass.methods.grep(/scoped_by_type/).blank?
@test_klass.scoped_by_type(nil)
- assert_present @test_klass.methods.grep(/scoped_by_type/)
+ assert @test_klass.methods.grep(/scoped_by_type/).present?
end
def test_dynamic_scope_with_less_number_of_arguments
diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb
index 55ee066cda..b9961a4420 100644
--- a/activerecord/test/cases/dirty_test.rb
+++ b/activerecord/test/cases/dirty_test.rb
@@ -517,7 +517,7 @@ class DirtyTest < ActiveRecord::TestCase
assert !pirate.previous_changes.key?('created_on')
pirate = Pirate.find_by_catchphrase("Thar She Blows!")
- pirate.update_attributes(:catchphrase => "Ahoy!")
+ pirate.update(catchphrase: "Ahoy!")
assert_equal 2, pirate.previous_changes.size
assert_equal ["Thar She Blows!", "Ahoy!"], pirate.previous_changes['catchphrase']
diff --git a/activerecord/test/cases/explain_test.rb b/activerecord/test/cases/explain_test.rb
index a7e5fdf709..aa2a6d7509 100644
--- a/activerecord/test/cases/explain_test.rb
+++ b/activerecord/test/cases/explain_test.rb
@@ -122,7 +122,7 @@ if ActiveRecord::Base.connection.supports_explain?
base.expects(:collecting_sqls_for_explain).never
base.logger.expects(:warn).never
base.silence_auto_explain do
- with_threshold(0) { Car.all }
+ with_threshold(0) { Car.all.to_a }
end
end
diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb
index 7db7953313..a9fa107749 100644
--- a/activerecord/test/cases/finder_test.rb
+++ b/activerecord/test/cases/finder_test.rb
@@ -15,6 +15,18 @@ require 'models/toy'
class FinderTest < ActiveRecord::TestCase
fixtures :companies, :topics, :entrants, :developers, :developers_projects, :posts, :comments, :accounts, :authors, :customers, :categories, :categorizations
+ def test_find_by_id_with_hash
+ assert_raises(ActiveRecord::StatementInvalid) do
+ Post.find_by_id(:limit => 1)
+ end
+ end
+
+ def test_find_by_title_and_id_with_hash
+ assert_raises(ActiveRecord::StatementInvalid) do
+ Post.find_by_title_and_id('foo', :limit => 1)
+ end
+ end
+
def test_find
assert_equal(topics(:first).title, Topic.find(1).title)
end
diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb
index 3a315d843b..5ffb32e809 100644
--- a/activerecord/test/cases/helper.rb
+++ b/activerecord/test/cases/helper.rb
@@ -2,8 +2,7 @@ require File.expand_path('../../../../load_paths', __FILE__)
require 'config'
-gem 'minitest'
-require 'minitest/autorun'
+require 'active_support/testing/autorun'
require 'stringio'
require 'active_record'
diff --git a/activerecord/test/cases/locking_test.rb b/activerecord/test/cases/locking_test.rb
index 2392516395..a0a3e6cb0d 100644
--- a/activerecord/test/cases/locking_test.rb
+++ b/activerecord/test/cases/locking_test.rb
@@ -207,7 +207,7 @@ class OptimisticLockingTest < ActiveRecord::TestCase
s.reload
assert_equal "unchangeable name", s.name
- s.update_attributes(:name => "changed name")
+ s.update(name: "changed name")
s.reload
assert_equal "unchangeable name", s.name
end
diff --git a/activerecord/test/cases/log_subscriber_test.rb b/activerecord/test/cases/log_subscriber_test.rb
index 345e83a102..57eac0c175 100644
--- a/activerecord/test/cases/log_subscriber_test.rb
+++ b/activerecord/test/cases/log_subscriber_test.rb
@@ -8,6 +8,19 @@ class LogSubscriberTest < ActiveRecord::TestCase
include ActiveSupport::LogSubscriber::TestHelper
include ActiveSupport::Logger::Severity
+ class TestDebugLogSubscriber < ActiveRecord::LogSubscriber
+ attr_reader :debugs
+
+ def initialize
+ @debugs = []
+ super
+ end
+
+ def debug message
+ @debugs << message
+ end
+ end
+
fixtures :posts
def setup
@@ -30,30 +43,27 @@ class LogSubscriberTest < ActiveRecord::TestCase
def test_schema_statements_are_ignored
event = Struct.new(:duration, :payload)
- logger = Class.new(ActiveRecord::LogSubscriber) {
- attr_accessor :debugs
-
- def initialize
- @debugs = []
- super
- end
-
- def debug message
- @debugs << message
- end
- }.new
+ logger = TestDebugLogSubscriber.new
assert_equal 0, logger.debugs.length
- logger.sql(event.new(0, { :sql => 'hi mom!' }))
+ logger.sql(event.new(0, sql: 'hi mom!'))
assert_equal 1, logger.debugs.length
- logger.sql(event.new(0, { :sql => 'hi mom!', :name => 'foo' }))
+ logger.sql(event.new(0, sql: 'hi mom!', name: 'foo'))
assert_equal 2, logger.debugs.length
- logger.sql(event.new(0, { :sql => 'hi mom!', :name => 'SCHEMA' }))
+ logger.sql(event.new(0, sql: 'hi mom!', name: 'SCHEMA'))
assert_equal 2, logger.debugs.length
end
+ def test_ignore_binds_payload_with_nil_column
+ event = Struct.new(:duration, :payload)
+
+ logger = TestDebugLogSubscriber.new
+ logger.sql(event.new(0, sql: 'hi mom!', binds: [[nil, 1]]))
+ assert_equal 1, logger.debugs.length
+ end
+
def test_basic_query_logging
Developer.all.load
wait
@@ -105,7 +115,7 @@ class LogSubscriberTest < ActiveRecord::TestCase
def test_binary_data_is_not_logged
skip if current_adapter?(:Mysql2Adapter)
- Binary.create(:data => 'some binary data')
+ Binary.create(data: 'some binary data')
wait
assert_match(/<16 bytes of binary data>/, @logger.logged(:debug).join)
end
diff --git a/activerecord/test/cases/migration/change_schema_test.rb b/activerecord/test/cases/migration/change_schema_test.rb
index 86451289e7..5ac4a16f33 100644
--- a/activerecord/test/cases/migration/change_schema_test.rb
+++ b/activerecord/test/cases/migration/change_schema_test.rb
@@ -50,7 +50,7 @@ module ActiveRecord
def test_create_table_with_defaults
# MySQL doesn't allow defaults on TEXT or BLOB columns.
- mysql = current_adapter?(:MysqlAdapter) || current_adapter?(:Mysql2Adapter)
+ mysql = current_adapter?(:MysqlAdapter, :Mysql2Adapter)
connection.create_table :testings do |t|
t.column :one, :string, :default => "hello"
@@ -99,7 +99,7 @@ module ActiveRecord
assert_equal 'smallint', one.sql_type
assert_equal 'integer', four.sql_type
assert_equal 'bigint', eight.sql_type
- elsif current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
+ elsif current_adapter?(:MysqlAdapter, :Mysql2Adapter)
assert_match 'int(11)', default.sql_type
assert_match 'tinyint', one.sql_type
assert_match 'int', four.sql_type
@@ -293,7 +293,7 @@ module ActiveRecord
end
assert connection.column_exists?(:testings, :foo)
- refute connection.column_exists?(:testings, :bar)
+ assert_not connection.column_exists?(:testings, :bar)
end
def test_column_exists_with_type
@@ -303,10 +303,10 @@ module ActiveRecord
end
assert connection.column_exists?(:testings, :foo, :string)
- refute connection.column_exists?(:testings, :foo, :integer)
+ assert_not connection.column_exists?(:testings, :foo, :integer)
assert connection.column_exists?(:testings, :bar, :decimal)
- refute connection.column_exists?(:testings, :bar, :integer)
+ assert_not connection.column_exists?(:testings, :bar, :integer)
end
def test_column_exists_with_definition
@@ -318,13 +318,13 @@ module ActiveRecord
end
assert connection.column_exists?(:testings, :foo, :string, limit: 100)
- refute connection.column_exists?(:testings, :foo, :string, limit: nil)
+ assert_not connection.column_exists?(:testings, :foo, :string, limit: nil)
assert connection.column_exists?(:testings, :bar, :decimal, precision: 8, scale: 2)
- refute connection.column_exists?(:testings, :bar, :decimal, precision: nil, scale: nil)
+ assert_not connection.column_exists?(:testings, :bar, :decimal, precision: nil, scale: nil)
assert connection.column_exists?(:testings, :taggable_id, :integer, null: false)
- refute connection.column_exists?(:testings, :taggable_id, :integer, null: true)
+ assert_not connection.column_exists?(:testings, :taggable_id, :integer, null: true)
assert connection.column_exists?(:testings, :taggable_type, :string, default: 'Photo')
- refute connection.column_exists?(:testings, :taggable_type, :string, default: nil)
+ assert_not connection.column_exists?(:testings, :taggable_type, :string, default: nil)
end
def test_column_exists_on_table_with_no_options_parameter_supplied
diff --git a/activerecord/test/cases/migration/change_table_test.rb b/activerecord/test/cases/migration/change_table_test.rb
index ac1ad176db..8065541bfe 100644
--- a/activerecord/test/cases/migration/change_table_test.rb
+++ b/activerecord/test/cases/migration/change_table_test.rb
@@ -1,4 +1,5 @@
require "cases/migration/helper"
+require "minitest/mock"
module ActiveRecord
class Migration
diff --git a/activerecord/test/cases/migration/column_attributes_test.rb b/activerecord/test/cases/migration/column_attributes_test.rb
index b88db384a0..ec2926632c 100644
--- a/activerecord/test/cases/migration/column_attributes_test.rb
+++ b/activerecord/test/cases/migration/column_attributes_test.rb
@@ -16,7 +16,7 @@ module ActiveRecord
end
def test_add_remove_single_field_using_string_arguments
- refute TestModel.column_methods_hash.key?(:last_name)
+ assert_not TestModel.column_methods_hash.key?(:last_name)
add_column 'test_models', 'last_name', :string
@@ -27,11 +27,11 @@ module ActiveRecord
remove_column 'test_models', 'last_name'
TestModel.reset_column_information
- refute TestModel.column_methods_hash.key?(:last_name)
+ assert_not TestModel.column_methods_hash.key?(:last_name)
end
def test_add_remove_single_field_using_symbol_arguments
- refute TestModel.column_methods_hash.key?(:last_name)
+ assert_not TestModel.column_methods_hash.key?(:last_name)
add_column :test_models, :last_name, :string
@@ -41,7 +41,7 @@ module ActiveRecord
remove_column :test_models, :last_name
TestModel.reset_column_information
- refute TestModel.column_methods_hash.key?(:last_name)
+ assert_not TestModel.column_methods_hash.key?(:last_name)
end
def test_unabstracted_database_dependent_types
diff --git a/activerecord/test/cases/migration/index_test.rb b/activerecord/test/cases/migration/index_test.rb
index 0787414d8f..a41f2c10f0 100644
--- a/activerecord/test/cases/migration/index_test.rb
+++ b/activerecord/test/cases/migration/index_test.rb
@@ -35,7 +35,7 @@ module ActiveRecord
connection.rename_index(table_name, 'old_idx', 'new_idx')
# if the adapter doesn't support the indexes call, pick defaults that let the test pass
- refute connection.index_name_exists?(table_name, 'old_idx', false)
+ assert_not connection.index_name_exists?(table_name, 'old_idx', false)
assert connection.index_name_exists?(table_name, 'new_idx', true)
end
@@ -63,7 +63,7 @@ module ActiveRecord
connection.add_index(table_name, "foo", :name => too_long_index_name)
}
- refute connection.index_name_exists?(table_name, too_long_index_name, false)
+ assert_not connection.index_name_exists?(table_name, too_long_index_name, false)
connection.add_index(table_name, "foo", :name => good_index_name)
assert connection.index_name_exists?(table_name, good_index_name, false)
@@ -75,7 +75,7 @@ module ActiveRecord
assert connection.index_exists?(table_name, :foo, :name => :symbol_index_name)
connection.remove_index table_name, :name => :symbol_index_name
- refute connection.index_exists?(table_name, :foo, :name => :symbol_index_name)
+ assert_not connection.index_exists?(table_name, :foo, :name => :symbol_index_name)
end
def test_index_exists
diff --git a/activerecord/test/cases/migration/references_index_test.rb b/activerecord/test/cases/migration/references_index_test.rb
index 264a99f9ce..3ff89524fe 100644
--- a/activerecord/test/cases/migration/references_index_test.rb
+++ b/activerecord/test/cases/migration/references_index_test.rb
@@ -29,7 +29,7 @@ module ActiveRecord
t.references :foo
end
- refute connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id)
+ assert_not connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id)
end
def test_does_not_create_index_explicit
@@ -37,7 +37,7 @@ module ActiveRecord
t.references :foo, :index => false
end
- refute connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id)
+ assert_not connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id)
end
def test_creates_index_with_options
@@ -75,7 +75,7 @@ module ActiveRecord
t.references :foo
end
- refute connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id)
+ assert_not connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id)
end
def test_does_not_create_index_for_existing_table_explicit
@@ -84,7 +84,7 @@ module ActiveRecord
t.references :foo, :index => false
end
- refute connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id)
+ assert_not connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id)
end
def test_creates_polymorphic_index_for_existing_table
diff --git a/activerecord/test/cases/migration/references_statements_test.rb b/activerecord/test/cases/migration/references_statements_test.rb
index d8a6565d54..e9545f2cce 100644
--- a/activerecord/test/cases/migration/references_statements_test.rb
+++ b/activerecord/test/cases/migration/references_statements_test.rb
@@ -22,7 +22,7 @@ module ActiveRecord
def test_does_not_create_reference_type_column
add_reference table_name, :taggable
- refute column_exists?(table_name, :taggable_type, :string)
+ assert_not column_exists?(table_name, :taggable_type, :string)
end
def test_creates_reference_type_column
@@ -37,7 +37,7 @@ module ActiveRecord
def test_does_not_create_reference_id_index
add_reference table_name, :user
- refute index_exists?(table_name, :user_id)
+ assert_not index_exists?(table_name, :user_id)
end
def test_creates_polymorphic_index
@@ -57,19 +57,19 @@ module ActiveRecord
def test_deletes_reference_id_column
remove_reference table_name, :supplier
- refute column_exists?(table_name, :supplier_id, :integer)
+ assert_not column_exists?(table_name, :supplier_id, :integer)
end
def test_deletes_reference_id_index
remove_reference table_name, :supplier
- refute index_exists?(table_name, :supplier_id)
+ assert_not index_exists?(table_name, :supplier_id)
end
def test_does_not_delete_reference_type_column
with_polymorphic_column do
remove_reference table_name, :supplier
- refute column_exists?(table_name, :supplier_id, :integer)
+ assert_not column_exists?(table_name, :supplier_id, :integer)
assert column_exists?(table_name, :supplier_type, :string)
end
end
@@ -77,14 +77,14 @@ module ActiveRecord
def test_deletes_reference_type_column
with_polymorphic_column do
remove_reference table_name, :supplier, polymorphic: true
- refute column_exists?(table_name, :supplier_type, :string)
+ assert_not column_exists?(table_name, :supplier_type, :string)
end
end
def test_deletes_polymorphic_index
with_polymorphic_column do
remove_reference table_name, :supplier, polymorphic: true
- refute index_exists?(table_name, [:supplier_id, :supplier_type])
+ assert_not index_exists?(table_name, [:supplier_id, :supplier_type])
end
end
@@ -95,7 +95,7 @@ module ActiveRecord
def test_remove_belongs_to_alias
remove_belongs_to table_name, :supplier
- refute column_exists?(table_name, :supplier_id, :integer)
+ assert_not column_exists?(table_name, :supplier_id, :integer)
end
private
diff --git a/activerecord/test/cases/migration/rename_column_test.rb b/activerecord/test/cases/migration/rename_column_test.rb
index 318d61263a..8f6918d06a 100644
--- a/activerecord/test/cases/migration/rename_column_test.rb
+++ b/activerecord/test/cases/migration/rename_column_test.rb
@@ -84,16 +84,19 @@ module ActiveRecord
add_column "test_models", :hat_name, :string
add_index :test_models, :hat_name
- # FIXME: we should test that the index goes away
+ assert_equal 1, connection.indexes('test_models').size
rename_column "test_models", "hat_name", "name"
+ # FIXME: should we rename the index if it's name was autogenerated by rails?
+ assert_equal ['index_test_models_on_hat_name'], connection.indexes('test_models').map(&:name)
end
def test_remove_column_with_index
add_column "test_models", :hat_name, :string
add_index :test_models, :hat_name
- # FIXME: we should test that the index goes away
+ assert_equal 1, connection.indexes('test_models').size
remove_column("test_models", "hat_name")
+ assert_equal 0, connection.indexes('test_models').size
end
def test_remove_column_with_multi_column_index
@@ -101,14 +104,25 @@ module ActiveRecord
add_column "test_models", :hat_style, :string, :limit => 100
add_index "test_models", ["hat_style", "hat_size"], :unique => true
- # FIXME: we should test that the index goes away
+ assert_equal 1, connection.indexes('test_models').size
remove_column("test_models", "hat_size")
+
+ # Every database and/or database adapter has their own behavior
+ # if it drops the multi-column index when any of the indexed columns dropped by remove_column.
+ if current_adapter?(:PostgreSQLAdapter, :OracleAdapter)
+ assert_equal [], connection.indexes('test_models').map(&:name)
+ else
+ assert_equal ['index_test_models_on_hat_style_and_hat_size'], connection.indexes('test_models').map(&:name)
+ end
end
- # FIXME: we need to test that these calls do something
def test_change_type_of_not_null_column
change_column "test_models", "updated_at", :datetime, :null => false
change_column "test_models", "updated_at", :datetime, :null => false
+
+ TestModel.reset_column_information
+ assert_equal false, TestModel.columns_hash['updated_at'].null
+ ensure
change_column "test_models", "updated_at", :datetime, :null => true
end
@@ -119,7 +133,7 @@ module ActiveRecord
change_column "test_models", "funny", :boolean, :null => false, :default => true
TestModel.reset_column_information
- refute TestModel.columns_hash["funny"].null, "Column 'funny' must *not* allow nulls at this point"
+ assert_not TestModel.columns_hash["funny"].null, "Column 'funny' must *not* allow nulls at this point"
change_column "test_models", "funny", :boolean, :null => true
TestModel.reset_column_information
@@ -138,7 +152,7 @@ module ActiveRecord
new_columns = connection.columns(TestModel.table_name)
- refute new_columns.find { |c| c.name == 'age' and c.type == :integer }
+ assert_not new_columns.find { |c| c.name == 'age' and c.type == :integer }
assert new_columns.find { |c| c.name == 'age' and c.type == :string }
old_columns = connection.columns(TestModel.table_name)
@@ -149,7 +163,7 @@ module ActiveRecord
change_column :test_models, :approved, :boolean, :default => false
new_columns = connection.columns(TestModel.table_name)
- refute new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true }
+ assert_not new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true }
assert new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == false }
change_column :test_models, :approved, :boolean, :default => true
end
@@ -160,7 +174,7 @@ module ActiveRecord
change_column "test_models", "contributor", :boolean, :default => nil
TestModel.reset_column_information
- refute TestModel.new.contributor?
+ assert_not TestModel.new.contributor?
assert_nil TestModel.new.contributor
end
@@ -170,7 +184,7 @@ module ActiveRecord
change_column "test_models", "administrator", :boolean, :default => false
TestModel.reset_column_information
- refute TestModel.new.administrator?
+ assert_not TestModel.new.administrator?
end
def test_change_column_with_custom_index_name
diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb
index c155f29973..187c6e8447 100644
--- a/activerecord/test/cases/migration_test.rb
+++ b/activerecord/test/cases/migration_test.rb
@@ -24,7 +24,7 @@ class MigrationTest < ActiveRecord::TestCase
def setup
super
- %w(reminders people_reminders prefix_reminders_suffix).each do |table|
+ %w(reminders people_reminders prefix_reminders_suffix p_things_s).each do |table|
Reminder.connection.drop_table(table) rescue nil
end
Reminder.reset_column_information
@@ -232,7 +232,7 @@ class MigrationTest < ActiveRecord::TestCase
skip "not supported on #{ActiveRecord::Base.connection.class}"
end
- refute Person.column_methods_hash.include?(:last_name)
+ assert_not Person.column_methods_hash.include?(:last_name)
migration = Struct.new(:name, :version) {
def migrate(x); raise 'Something broke'; end
@@ -245,7 +245,7 @@ class MigrationTest < ActiveRecord::TestCase
assert_equal "An error has occurred, this and all later migrations canceled:\n\nSomething broke", e.message
Person.reset_column_information
- refute Person.column_methods_hash.include?(:last_name)
+ assert_not Person.column_methods_hash.include?(:last_name)
end
def test_schema_migrations_table_name
diff --git a/activerecord/test/cases/migrator_test.rb b/activerecord/test/cases/migrator_test.rb
index 199d0c584b..b5a69c4a92 100644
--- a/activerecord/test/cases/migrator_test.rb
+++ b/activerecord/test/cases/migrator_test.rb
@@ -29,6 +29,7 @@ module ActiveRecord
def teardown
super
ActiveRecord::SchemaMigration.delete_all rescue nil
+ ActiveRecord::Migration.verbose = true
end
def test_migrator_with_duplicate_names
@@ -121,11 +122,11 @@ module ActiveRecord
ActiveRecord::Migrator.new(:up, pass_one).migrate
assert pass_one.first.went_up
- refute pass_one.first.went_down
+ assert_not pass_one.first.went_down
pass_two = [Sensor.new('One', 1), Sensor.new('Three', 3)]
ActiveRecord::Migrator.new(:up, pass_two).migrate
- refute pass_two[0].went_up
+ assert_not pass_two[0].went_up
assert pass_two[1].went_up
assert pass_two.all? { |x| !x.went_down }
@@ -135,7 +136,7 @@ module ActiveRecord
ActiveRecord::Migrator.new(:down, pass_three).migrate
assert pass_three[0].went_down
- refute pass_three[1].went_down
+ assert_not pass_three[1].went_down
assert pass_three[2].went_down
end
@@ -307,7 +308,7 @@ module ActiveRecord
_, migrator = migrator_class(3)
ActiveRecord::Base.connection.execute("DROP TABLE schema_migrations")
- refute ActiveRecord::Base.connection.table_exists?('schema_migrations')
+ assert_not ActiveRecord::Base.connection.table_exists?('schema_migrations')
migrator.migrate("valid", 1)
assert ActiveRecord::Base.connection.table_exists?('schema_migrations')
end
diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb
index 3f08f9ea4d..94837341fc 100644
--- a/activerecord/test/cases/nested_attributes_test.rb
+++ b/activerecord/test/cases/nested_attributes_test.rb
@@ -79,10 +79,10 @@ class TestNestedAttributesInGeneral < ActiveRecord::TestCase
def test_should_disable_allow_destroy_by_default
Pirate.accepts_nested_attributes_for :ship
- pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
- ship = pirate.create_ship(:name => 'Nights Dirty Lightning')
+ pirate = Pirate.create!(catchphrase: "Don' botharrr talkin' like one, savvy?")
+ ship = pirate.create_ship(name: 'Nights Dirty Lightning')
- pirate.update_attributes(:ship_attributes => { '_destroy' => true, :id => ship.id })
+ pirate.update(ship_attributes: { '_destroy' => true, :id => ship.id })
assert_nothing_raised(ActiveRecord::RecordNotFound) { pirate.ship.reload }
end
@@ -125,33 +125,33 @@ class TestNestedAttributesInGeneral < ActiveRecord::TestCase
def test_reject_if_with_a_proc_which_returns_true_always_for_has_one
Pirate.accepts_nested_attributes_for :ship, :reject_if => proc {|attributes| true }
- pirate = Pirate.new(:catchphrase => "Stop wastin' me time")
- ship = pirate.create_ship(:name => 's1')
- pirate.update_attributes({:ship_attributes => { :name => 's2', :id => ship.id } })
+ pirate = Pirate.new(catchphrase: "Stop wastin' me time")
+ ship = pirate.create_ship(name: 's1')
+ pirate.update({ship_attributes: { name: 's2', id: ship.id } })
assert_equal 's1', ship.reload.name
end
def test_reject_if_with_a_proc_which_returns_true_always_for_has_many
Man.accepts_nested_attributes_for :interests, :reject_if => proc {|attributes| true }
- man = Man.create(:name => "John")
- interest = man.interests.create(:topic => 'photography')
- man.update_attributes({:interests_attributes => { :topic => 'gardening', :id => interest.id } })
+ man = Man.create(name: "John")
+ interest = man.interests.create(topic: 'photography')
+ man.update({interests_attributes: { topic: 'gardening', id: interest.id } })
assert_equal 'photography', interest.reload.topic
end
def test_destroy_works_independent_of_reject_if
Man.accepts_nested_attributes_for :interests, :reject_if => proc {|attributes| true }, :allow_destroy => true
- man = Man.create(:name => "Jon")
- interest = man.interests.create(:topic => 'the ladies')
- man.update_attributes({:interests_attributes => { :_destroy => "1", :id => interest.id } })
+ man = Man.create(name: "Jon")
+ interest = man.interests.create(topic: 'the ladies')
+ man.update({interests_attributes: { _destroy: "1", id: interest.id } })
assert man.reload.interests.empty?
end
def test_has_many_association_updating_a_single_record
Man.accepts_nested_attributes_for(:interests)
- man = Man.create(:name => 'John')
- interest = man.interests.create(:topic => 'photography')
- man.update_attributes({:interests_attributes => {:topic => 'gardening', :id => interest.id}})
+ man = Man.create(name: 'John')
+ interest = man.interests.create(topic: 'photography')
+ man.update({interests_attributes: {topic: 'gardening', id: interest.id}})
assert_equal 'gardening', interest.reload.topic
end
@@ -284,8 +284,8 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase
@pirate.ship.destroy
[1, '1', true, 'true'].each do |truth|
- ship = @pirate.reload.create_ship(:name => 'Mister Pablo')
- @pirate.update_attributes(:ship_attributes => { :id => ship.id, :_destroy => truth })
+ ship = @pirate.reload.create_ship(name: 'Mister Pablo')
+ @pirate.update(ship_attributes: { id: ship.id, _destroy: truth })
assert_nil @pirate.reload.ship
assert_raise(ActiveRecord::RecordNotFound) { Ship.find(ship.id) }
@@ -294,7 +294,7 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase
def test_should_not_destroy_an_existing_record_if_destroy_is_not_truthy
[nil, '0', 0, 'false', false].each do |not_truth|
- @pirate.update_attributes(:ship_attributes => { :id => @pirate.ship.id, :_destroy => not_truth })
+ @pirate.update(ship_attributes: { id: @pirate.ship.id, _destroy: not_truth })
assert_equal @ship, @pirate.reload.ship
end
@@ -303,7 +303,7 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase
def test_should_not_destroy_an_existing_record_if_allow_destroy_is_false
Pirate.accepts_nested_attributes_for :ship, :allow_destroy => false, :reject_if => proc { |attributes| attributes.empty? }
- @pirate.update_attributes(:ship_attributes => { :id => @pirate.ship.id, :_destroy => '1' })
+ @pirate.update(ship_attributes: { id: @pirate.ship.id, _destroy: '1' })
assert_equal @ship, @pirate.reload.ship
@@ -311,14 +311,14 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase
end
def test_should_also_work_with_a_HashWithIndifferentAccess
- @pirate.ship_attributes = HashWithIndifferentAccess.new(:id => @ship.id, :name => 'Davy Jones Gold Dagger')
+ @pirate.ship_attributes = ActiveSupport::HashWithIndifferentAccess.new(:id => @ship.id, :name => 'Davy Jones Gold Dagger')
assert @pirate.ship.persisted?
assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name
end
- def test_should_work_with_update_attributes_as_well
- @pirate.update_attributes({ :catchphrase => 'Arr', :ship_attributes => { :id => @ship.id, :name => 'Mister Pablo' } })
+ def test_should_work_with_update_as_well
+ @pirate.update({ catchphrase: 'Arr', ship_attributes: { id: @ship.id, name: 'Mister Pablo' } })
@pirate.reload
assert_equal 'Arr', @pirate.catchphrase
@@ -342,22 +342,22 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase
end
def test_should_accept_update_only_option
- @pirate.update_attributes(:update_only_ship_attributes => { :id => @pirate.ship.id, :name => 'Mayflower' })
+ @pirate.update(update_only_ship_attributes: { id: @pirate.ship.id, name: 'Mayflower' })
end
def test_should_create_new_model_when_nothing_is_there_and_update_only_is_true
@ship.delete
- @pirate.reload.update_attributes(:update_only_ship_attributes => { :name => 'Mayflower' })
+ @pirate.reload.update(update_only_ship_attributes: { name: 'Mayflower' })
assert_not_nil @pirate.ship
end
def test_should_update_existing_when_update_only_is_true_and_no_id_is_given
@ship.delete
- @ship = @pirate.create_update_only_ship(:name => 'Nights Dirty Lightning')
+ @ship = @pirate.create_update_only_ship(name: 'Nights Dirty Lightning')
- @pirate.update_attributes(:update_only_ship_attributes => { :name => 'Mayflower' })
+ @pirate.update(update_only_ship_attributes: { name: 'Mayflower' })
assert_equal 'Mayflower', @ship.reload.name
assert_equal @ship, @pirate.reload.ship
@@ -365,9 +365,9 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase
def test_should_update_existing_when_update_only_is_true_and_id_is_given
@ship.delete
- @ship = @pirate.create_update_only_ship(:name => 'Nights Dirty Lightning')
+ @ship = @pirate.create_update_only_ship(name: 'Nights Dirty Lightning')
- @pirate.update_attributes(:update_only_ship_attributes => { :name => 'Mayflower', :id => @ship.id })
+ @pirate.update(update_only_ship_attributes: { name: 'Mayflower', id: @ship.id })
assert_equal 'Mayflower', @ship.reload.name
assert_equal @ship, @pirate.reload.ship
@@ -376,9 +376,9 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase
def test_should_destroy_existing_when_update_only_is_true_and_id_is_given_and_is_marked_for_destruction
Pirate.accepts_nested_attributes_for :update_only_ship, :update_only => true, :allow_destroy => true
@ship.delete
- @ship = @pirate.create_update_only_ship(:name => 'Nights Dirty Lightning')
+ @ship = @pirate.create_update_only_ship(name: 'Nights Dirty Lightning')
- @pirate.update_attributes(:update_only_ship_attributes => { :name => 'Mayflower', :id => @ship.id, :_destroy => true })
+ @pirate.update(update_only_ship_attributes: { name: 'Mayflower', id: @ship.id, _destroy: true })
assert_nil @pirate.reload.ship
assert_raise(ActiveRecord::RecordNotFound) { Ship.find(@ship.id) }
@@ -468,15 +468,15 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase
def test_should_destroy_an_existing_record_if_there_is_a_matching_id_and_destroy_is_truthy
@ship.pirate.destroy
[1, '1', true, 'true'].each do |truth|
- pirate = @ship.reload.create_pirate(:catchphrase => 'Arr')
- @ship.update_attributes(:pirate_attributes => { :id => pirate.id, :_destroy => truth })
+ pirate = @ship.reload.create_pirate(catchphrase: 'Arr')
+ @ship.update(pirate_attributes: { id: pirate.id, _destroy: truth })
assert_raise(ActiveRecord::RecordNotFound) { pirate.reload }
end
end
def test_should_unset_association_when_an_existing_record_is_destroyed
original_pirate_id = @ship.pirate.id
- @ship.update_attributes! pirate_attributes: { id: @ship.pirate.id, _destroy: true }
+ @ship.update! pirate_attributes: { id: @ship.pirate.id, _destroy: true }
assert_empty Pirate.where(id: original_pirate_id)
assert_nil @ship.pirate_id
@@ -490,7 +490,7 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase
def test_should_not_destroy_an_existing_record_if_destroy_is_not_truthy
[nil, '0', 0, 'false', false].each do |not_truth|
- @ship.update_attributes(:pirate_attributes => { :id => @ship.pirate.id, :_destroy => not_truth })
+ @ship.update(pirate_attributes: { id: @ship.pirate.id, _destroy: not_truth })
assert_nothing_raised(ActiveRecord::RecordNotFound) { @ship.pirate.reload }
end
end
@@ -498,14 +498,14 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase
def test_should_not_destroy_an_existing_record_if_allow_destroy_is_false
Ship.accepts_nested_attributes_for :pirate, :allow_destroy => false, :reject_if => proc { |attributes| attributes.empty? }
- @ship.update_attributes(:pirate_attributes => { :id => @ship.pirate.id, :_destroy => '1' })
+ @ship.update(pirate_attributes: { id: @ship.pirate.id, _destroy: '1' })
assert_nothing_raised(ActiveRecord::RecordNotFound) { @ship.pirate.reload }
ensure
Ship.accepts_nested_attributes_for :pirate, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
end
- def test_should_work_with_update_attributes_as_well
- @ship.update_attributes({ :name => 'Mister Pablo', :pirate_attributes => { :catchphrase => 'Arr' } })
+ def test_should_work_with_update_as_well
+ @ship.update({ name: 'Mister Pablo', pirate_attributes: { catchphrase: 'Arr' } })
@ship.reload
assert_equal 'Mister Pablo', @ship.name
@@ -534,18 +534,18 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase
def test_should_update_existing_when_update_only_is_true_and_no_id_is_given
@pirate.delete
- @pirate = @ship.create_update_only_pirate(:catchphrase => 'Aye')
+ @pirate = @ship.create_update_only_pirate(catchphrase: 'Aye')
- @ship.update_attributes(:update_only_pirate_attributes => { :catchphrase => 'Arr' })
+ @ship.update(update_only_pirate_attributes: { catchphrase: 'Arr' })
assert_equal 'Arr', @pirate.reload.catchphrase
assert_equal @pirate, @ship.reload.update_only_pirate
end
def test_should_update_existing_when_update_only_is_true_and_id_is_given
@pirate.delete
- @pirate = @ship.create_update_only_pirate(:catchphrase => 'Aye')
+ @pirate = @ship.create_update_only_pirate(catchphrase: 'Aye')
- @ship.update_attributes(:update_only_pirate_attributes => { :catchphrase => 'Arr', :id => @pirate.id })
+ @ship.update(update_only_pirate_attributes: { catchphrase: 'Arr', id: @pirate.id })
assert_equal 'Arr', @pirate.reload.catchphrase
assert_equal @pirate, @ship.reload.update_only_pirate
@@ -554,9 +554,9 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase
def test_should_destroy_existing_when_update_only_is_true_and_id_is_given_and_is_marked_for_destruction
Ship.accepts_nested_attributes_for :update_only_pirate, :update_only => true, :allow_destroy => true
@pirate.delete
- @pirate = @ship.create_update_only_pirate(:catchphrase => 'Aye')
+ @pirate = @ship.create_update_only_pirate(catchphrase: 'Aye')
- @ship.update_attributes(:update_only_pirate_attributes => { :catchphrase => 'Arr', :id => @pirate.id, :_destroy => true })
+ @ship.update(update_only_pirate_attributes: { catchphrase: 'Arr', id: @pirate.id, _destroy: true })
assert_raise(ActiveRecord::RecordNotFound) { @pirate.reload }
@@ -582,7 +582,7 @@ module NestedAttributesOnACollectionAssociationTests
def test_should_take_a_hash_with_string_keys_and_assign_the_attributes_to_the_associated_models
@alternate_params[association_getter].stringify_keys!
- @pirate.update_attributes @alternate_params
+ @pirate.update @alternate_params
assert_equal ['Grace OMalley', 'Privateers Greed'], [@child_1.reload.name, @child_2.reload.name]
end
@@ -593,7 +593,7 @@ module NestedAttributesOnACollectionAssociationTests
end
def test_should_also_work_with_a_HashWithIndifferentAccess
- @pirate.send(association_setter, HashWithIndifferentAccess.new('foo' => HashWithIndifferentAccess.new(:id => @child_1.id, :name => 'Grace OMalley')))
+ @pirate.send(association_setter, ActiveSupport::HashWithIndifferentAccess.new('foo' => ActiveSupport::HashWithIndifferentAccess.new(:id => @child_1.id, :name => 'Grace OMalley')))
@pirate.save
assert_equal 'Grace OMalley', @child_1.reload.name
end
@@ -628,10 +628,10 @@ module NestedAttributesOnACollectionAssociationTests
def test_should_refresh_saved_records_when_not_overwriting_unsaved_updates
@pirate.reload
- record = @pirate.class.reflect_on_association(@association_name).klass.new(:name => 'Grace OMalley')
+ record = @pirate.class.reflect_on_association(@association_name).klass.new(name: 'Grace OMalley')
@pirate.send(@association_name) << record
record.save!
- @pirate.send(@association_name).last.update_attributes!(:name => 'Polly')
+ @pirate.send(@association_name).last.update!(name: 'Polly')
assert_equal 'Polly', @pirate.send(@association_name).send(:load_target).last.name
end
@@ -718,17 +718,17 @@ module NestedAttributesOnACollectionAssociationTests
end
end
- def test_should_work_with_update_attributes_as_well
- @pirate.update_attributes(:catchphrase => 'Arr',
+ def test_should_work_with_update_as_well
+ @pirate.update(catchphrase: 'Arr',
association_getter => { 'foo' => { :id => @child_1.id, :name => 'Grace OMalley' }})
assert_equal 'Grace OMalley', @child_1.reload.name
end
def test_should_update_existing_records_and_add_new_ones_that_have_no_id
- @alternate_params[association_getter]['baz'] = { :name => 'Buccaneers Servant' }
+ @alternate_params[association_getter]['baz'] = { name: 'Buccaneers Servant' }
assert_difference('@pirate.send(@association_name).count', +1) do
- @pirate.update_attributes @alternate_params
+ @pirate.update @alternate_params
end
assert_equal ['Grace OMalley', 'Privateers Greed', 'Buccaneers Servant'].to_set, @pirate.reload.send(@association_name).map(&:name).to_set
end
@@ -750,7 +750,7 @@ module NestedAttributesOnACollectionAssociationTests
[nil, '', '0', 0, 'false', false].each do |false_variable|
@alternate_params[association_getter]['foo']['_destroy'] = false_variable
assert_no_difference('@pirate.send(@association_name).count') do
- @pirate.update_attributes(@alternate_params)
+ @pirate.update(@alternate_params)
end
end
end
@@ -814,7 +814,7 @@ module NestedAttributesOnACollectionAssociationTests
man = Man.create(name: 'John')
interest = man.interests.create(topic: 'bar', zine_id: 0)
assert interest.save
- assert !man.update_attributes({interests_attributes: { id: interest.id, zine_id: 'foo' }})
+ assert !man.update({interests_attributes: { id: interest.id, zine_id: 'foo' }})
end
end
@@ -945,18 +945,18 @@ class TestNestedAttributesWithNonStandardPrimaryKeys < ActiveRecord::TestCase
end
def test_should_update_existing_records_with_non_standard_primary_key
- @owner.update_attributes(@params)
+ @owner.update(@params)
assert_equal ['Foo', 'Bar'], @owner.pets.map(&:name)
end
- def test_attr_accessor_of_child_should_be_value_provided_during_update_attributes
+ def test_attr_accessor_of_child_should_be_value_provided_during_update
@owner = owners(:ashley)
@pet1 = pets(:chew)
attributes = {:pets_attributes => { "1"=> { :id => @pet1.id,
:name => "Foo2",
:current_user => "John",
:_destroy=>true }}}
- @owner.update_attributes(attributes)
+ @owner.update(attributes)
assert_equal 'John', Pet.after_destroy_output
end
diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb
index 9e0423ab52..b936cca875 100644
--- a/activerecord/test/cases/persistence_test.rb
+++ b/activerecord/test/cases/persistence_test.rb
@@ -16,7 +16,6 @@ require 'models/person'
require 'models/pet'
require 'models/toy'
require 'rexml/document'
-require 'active_support/core_ext/exception'
class PersistencesTest < ActiveRecord::TestCase
@@ -243,7 +242,7 @@ class PersistencesTest < ActiveRecord::TestCase
assert_equal "David", topic2.author_name
end
- def test_update
+ def test_update_object
topic = Topic.new
topic.title = "Another New Topic"
topic.written_on = "2003-12-12 23:23:00"
@@ -365,7 +364,7 @@ class PersistencesTest < ActiveRecord::TestCase
client.delete
assert client.frozen?
assert_kind_of Firm, client.firm
- assert_raise(ActiveSupport::FrozenObjectError) { client.name = "something else" }
+ assert_raise(RuntimeError) { client.name = "something else" }
end
def test_destroy_new_record
@@ -379,7 +378,7 @@ class PersistencesTest < ActiveRecord::TestCase
client.destroy
assert client.frozen?
assert_kind_of Firm, client.firm
- assert_raise(ActiveSupport::FrozenObjectError) { client.name = "something else" }
+ assert_raise(RuntimeError) { client.name = "something else" }
end
def test_update_attribute
@@ -392,7 +391,7 @@ class PersistencesTest < ActiveRecord::TestCase
end
def test_update_attribute_does_not_choke_on_nil
- assert Topic.find(1).update_attributes(nil)
+ assert Topic.find(1).update(nil)
end
def test_update_attribute_for_readonly_attribute
@@ -548,7 +547,7 @@ class PersistencesTest < ActiveRecord::TestCase
def test_update_columns_should_not_leave_the_object_dirty
topic = Topic.find(1)
- topic.update_attributes({ "content" => "Have a nice day", :author_name => "Jose" })
+ topic.update({ "content" => "Have a nice day", :author_name => "Jose" })
topic.reload
topic.update_columns({ content: "You too", "author_name" => "Sebastian" })
@@ -632,6 +631,22 @@ class PersistencesTest < ActiveRecord::TestCase
assert developer.update_columns(name: 'Will'), 'did not update record due to default scope'
end
+ def test_update
+ topic = Topic.find(1)
+ assert !topic.approved?
+ assert_equal "The First Topic", topic.title
+
+ topic.update("approved" => true, "title" => "The First Topic Updated")
+ topic.reload
+ assert topic.approved?
+ assert_equal "The First Topic Updated", topic.title
+
+ topic.update(approved: false, title: "The First Topic")
+ topic.reload
+ assert !topic.approved?
+ assert_equal "The First Topic", topic.title
+ end
+
def test_update_attributes
topic = Topic.find(1)
assert !topic.approved?
@@ -642,12 +657,33 @@ class PersistencesTest < ActiveRecord::TestCase
assert topic.approved?
assert_equal "The First Topic Updated", topic.title
- topic.update_attributes(:approved => false, :title => "The First Topic")
+ topic.update_attributes(approved: false, title: "The First Topic")
topic.reload
assert !topic.approved?
assert_equal "The First Topic", topic.title
end
+ def test_update!
+ Reply.validates_presence_of(:title)
+ reply = Reply.find(2)
+ assert_equal "The Second Topic of the day", reply.title
+ assert_equal "Have a nice day", reply.content
+
+ reply.update!("title" => "The Second Topic of the day updated", "content" => "Have a nice evening")
+ reply.reload
+ assert_equal "The Second Topic of the day updated", reply.title
+ assert_equal "Have a nice evening", reply.content
+
+ reply.update!(title: "The Second Topic of the day", content: "Have a nice day")
+ reply.reload
+ assert_equal "The Second Topic of the day", reply.title
+ assert_equal "Have a nice day", reply.content
+
+ assert_raise(ActiveRecord::RecordInvalid) { reply.update!(title: nil, content: "Have a nice evening") }
+ ensure
+ Reply.reset_callbacks(:validate)
+ end
+
def test_update_attributes!
Reply.validates_presence_of(:title)
reply = Reply.find(2)
@@ -659,12 +695,12 @@ class PersistencesTest < ActiveRecord::TestCase
assert_equal "The Second Topic of the day updated", reply.title
assert_equal "Have a nice evening", reply.content
- reply.update_attributes!(:title => "The Second Topic of the day", :content => "Have a nice day")
+ reply.update_attributes!(title: "The Second Topic of the day", content: "Have a nice day")
reply.reload
assert_equal "The Second Topic of the day", reply.title
assert_equal "Have a nice day", reply.content
- assert_raise(ActiveRecord::RecordInvalid) { reply.update_attributes!(:title => nil, :content => "Have a nice evening") }
+ assert_raise(ActiveRecord::RecordInvalid) { reply.update_attributes!(title: nil, content: "Have a nice evening") }
ensure
Reply.reset_callbacks(:validate)
end
diff --git a/activerecord/test/cases/primary_keys_test.rb b/activerecord/test/cases/primary_keys_test.rb
index bf8aacc363..8e5379cb1f 100644
--- a/activerecord/test/cases/primary_keys_test.rb
+++ b/activerecord/test/cases/primary_keys_test.rb
@@ -201,10 +201,10 @@ class PrimaryKeyWithNoConnectionTest < ActiveRecord::TestCase
end
end
-if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
+if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
class PrimaryKeyWithAnsiQuotesTest < ActiveRecord::TestCase
self.use_transactional_fixtures = false
-
+
def test_primaery_key_method_with_ansi_quotes
con = ActiveRecord::Base.connection
con.execute("SET SESSION sql_mode='ANSI_QUOTES'")
@@ -212,7 +212,7 @@ if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
ensure
con.reconnect!
end
-
+
end
end
diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb
index 4ff481e6a5..136fda664c 100644
--- a/activerecord/test/cases/query_cache_test.rb
+++ b/activerecord/test/cases/query_cache_test.rb
@@ -167,7 +167,7 @@ class QueryCacheTest < ActiveRecord::TestCase
# Oracle adapter returns count() as Fixnum or Float
if current_adapter?(:OracleAdapter)
assert_kind_of Numeric, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks")
- elsif current_adapter?(:SQLite3Adapter) || current_adapter?(:Mysql2Adapter)
+ elsif current_adapter?(:SQLite3Adapter, :Mysql2Adapter)
# Future versions of the sqlite3 adapter will return numeric
assert_instance_of Fixnum,
Task.connection.select_value("SELECT count(*) AS count_all FROM tasks")
diff --git a/activerecord/test/cases/relation/where_test.rb b/activerecord/test/cases/relation/where_test.rb
index 297e865308..f69a248491 100644
--- a/activerecord/test/cases/relation/where_test.rb
+++ b/activerecord/test/cases/relation/where_test.rb
@@ -82,6 +82,10 @@ module ActiveRecord
assert_equal 0, Post.where(:posts => {}).count
end
+ def test_where_with_table_name_and_empty_array
+ assert_equal 0, Post.where(:id => []).count
+ end
+
def test_where_with_empty_hash_and_no_foreign_key
assert_equal 0, Edge.where(:sink => {}).count
end
diff --git a/activerecord/test/cases/relation_scoping_test.rb b/activerecord/test/cases/relation_scoping_test.rb
index d318dab1e1..78fb91d321 100644
--- a/activerecord/test/cases/relation_scoping_test.rb
+++ b/activerecord/test/cases/relation_scoping_test.rb
@@ -227,7 +227,7 @@ class NestedRelationScopingTest < ActiveRecord::TestCase
def test_nested_exclusive_scope_for_create
comment = Comment.create_with(:body => "Hey guys, nested scopes are broken. Please fix!").scoping do
Comment.unscoped.create_with(:post_id => 1).scoping do
- assert_blank Comment.new.body
+ assert Comment.new.body.blank?
Comment.create :body => "Hey guys"
end
end
diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb
index 0cd838c0b0..3a499a2025 100644
--- a/activerecord/test/cases/relations_test.rb
+++ b/activerecord/test/cases/relations_test.rb
@@ -509,7 +509,7 @@ class RelationTest < ActiveRecord::TestCase
def test_find_in_empty_array
authors = Author.all.where(:id => [])
- assert_blank authors.to_a
+ assert authors.to_a.blank?
end
def test_where_with_ar_object
@@ -723,7 +723,7 @@ class RelationTest < ActiveRecord::TestCase
def test_relation_merging_with_locks
devs = Developer.lock.where("salary >= 80000").order("id DESC").merge(Developer.limit(2))
- assert_present devs.locked
+ assert devs.locked.present?
end
def test_relation_merging_with_preload
diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb
index 7ff0044bd4..cae12e0e3a 100644
--- a/activerecord/test/cases/schema_dumper_test.rb
+++ b/activerecord/test/cases/schema_dumper_test.rb
@@ -112,7 +112,7 @@ class SchemaDumperTest < ActiveRecord::TestCase
assert_match %r{c_int_4.*}, output
assert_no_match %r{c_int_4.*limit:}, output
- elsif current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
+ elsif current_adapter?(:MysqlAdapter, :Mysql2Adapter)
assert_match %r{c_int_1.*limit: 1}, output
assert_match %r{c_int_2.*limit: 2}, output
assert_match %r{c_int_3.*limit: 3}, output
@@ -197,7 +197,7 @@ class SchemaDumperTest < ActiveRecord::TestCase
assert_match %r(primary_key: "movieid"), match[1], "non-standard primary key not preserved"
end
- if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
+ if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
def test_schema_dump_should_not_add_default_value_for_mysql_text_field
output = standard_dump
assert_match %r{t.text\s+"body",\s+null: false$}, output
@@ -280,6 +280,13 @@ class SchemaDumperTest < ActiveRecord::TestCase
end
end
+ def test_schema_dump_includes_ltrees_shorthand_definition
+ output = standard_dump
+ if %r{create_table "postgresql_ltrees"} =~ output
+ assert_match %r[t.ltree "path"], output
+ end
+ end
+
def test_schema_dump_includes_arrays_shorthand_definition
output = standard_dump
if %r{create_table "postgresql_arrays"} =~ output
diff --git a/activerecord/test/cases/store_test.rb b/activerecord/test/cases/store_test.rb
index 562ca8d9ff..43bf285ba9 100644
--- a/activerecord/test/cases/store_test.rb
+++ b/activerecord/test/cases/store_test.rb
@@ -67,9 +67,9 @@ class StoreTest < ActiveRecord::TestCase
end
test "preserve store attributes data in HashWithIndifferentAccess format without any conversion" do
- @john.json_data = HashWithIndifferentAccess.new(:height => 'tall', 'weight' => 'heavy')
+ @john.json_data = ActiveSupport::HashWithIndifferentAccess.new(:height => 'tall', 'weight' => 'heavy')
@john.height = 'low'
- assert_equal true, @john.json_data.instance_of?(HashWithIndifferentAccess)
+ assert_equal true, @john.json_data.instance_of?(ActiveSupport::HashWithIndifferentAccess)
assert_equal 'low', @john.json_data[:height]
assert_equal 'low', @john.json_data['height']
assert_equal 'heavy', @john.json_data[:weight]
@@ -95,7 +95,7 @@ class StoreTest < ActiveRecord::TestCase
test "convert store attributes from any format other than Hash or HashWithIndifferent access losing the data" do
@john.json_data = "somedata"
@john.height = 'low'
- assert_equal true, @john.json_data.instance_of?(HashWithIndifferentAccess)
+ assert_equal true, @john.json_data.instance_of?(ActiveSupport::HashWithIndifferentAccess)
assert_equal 'low', @john.json_data[:height]
assert_equal 'low', @john.json_data['height']
assert_equal false, @john.json_data.delete_if { |k, v| k == 'height' }.any?
@@ -143,5 +143,4 @@ class StoreTest < ActiveRecord::TestCase
assert_raise(NoMethodError) { @john.stored_attributes = Hash.new }
assert_raise(NoMethodError) { @john.stored_attributes }
end
-
end
diff --git a/activerecord/test/cases/transaction_isolation_test.rb b/activerecord/test/cases/transaction_isolation_test.rb
index a396da6645..4f1cb99b68 100644
--- a/activerecord/test/cases/transaction_isolation_test.rb
+++ b/activerecord/test/cases/transaction_isolation_test.rb
@@ -77,7 +77,7 @@ class TransactionIsolationTest < ActiveRecord::TestCase
Tag.transaction(isolation: :repeatable_read) do
tag.reload
- Tag2.find(tag.id).update_attributes(name: 'emily')
+ Tag2.find(tag.id).update(name: 'emily')
tag.reload
assert_equal 'jon', tag.name
diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb
index fdca10f4fb..bcbc48b38a 100644
--- a/activerecord/test/cases/transactions_test.rb
+++ b/activerecord/test/cases/transactions_test.rb
@@ -15,7 +15,7 @@ class TransactionTest < ActiveRecord::TestCase
end
def test_raise_after_destroy
- refute @first.frozen?
+ assert_not @first.frozen?
assert_raises(RuntimeError) {
Topic.transaction do
@@ -26,7 +26,7 @@ class TransactionTest < ActiveRecord::TestCase
}
assert @first.reload
- refute @first.frozen?
+ assert_not @first.frozen?
end
def test_successful
@@ -117,21 +117,21 @@ class TransactionTest < ActiveRecord::TestCase
assert !Topic.find(1).approved?
end
- def test_update_attributes_should_rollback_on_failure
+ def test_update_should_rollback_on_failure
author = Author.find(1)
posts_count = author.posts.size
assert posts_count > 0
- status = author.update_attributes(:name => nil, :post_ids => [])
+ status = author.update(name: nil, post_ids: [])
assert !status
assert_equal posts_count, author.posts(true).size
end
- def test_update_attributes_should_rollback_on_failure!
+ def test_update_should_rollback_on_failure!
author = Author.find(1)
posts_count = author.posts.size
assert posts_count > 0
assert_raise(ActiveRecord::RecordInvalid) do
- author.update_attributes!(:name => nil, :post_ids => [])
+ author.update!(name: nil, post_ids: [])
end
assert_equal posts_count, author.posts(true).size
end
diff --git a/activerecord/test/models/reference.rb b/activerecord/test/models/reference.rb
index 1636c118a2..c2f9068f57 100644
--- a/activerecord/test/models/reference.rb
+++ b/activerecord/test/models/reference.rb
@@ -11,7 +11,7 @@ class Reference < ActiveRecord::Base
def make_comments
if self.class.make_comments
- person.update_attributes :comments => "Reference destroyed"
+ person.update comments: "Reference destroyed"
end
end
end
diff --git a/activerecord/test/models/reply.rb b/activerecord/test/models/reply.rb
index 079e325aad..c88262580e 100644
--- a/activerecord/test/models/reply.rb
+++ b/activerecord/test/models/reply.rb
@@ -1,8 +1,6 @@
require 'models/topic'
class Reply < Topic
- scope :base, -> { scoped }
-
belongs_to :topic, :foreign_key => "parent_id", :counter_cache => true
belongs_to :topic_with_primary_key, :class_name => "Topic", :primary_key => "title", :foreign_key => "parent_title", :counter_cache => "replies_count"
has_many :replies, :class_name => "SillyReply", :dependent => :destroy, :foreign_key => "parent_id"
diff --git a/activerecord/test/schema/postgresql_specific_schema.rb b/activerecord/test/schema/postgresql_specific_schema.rb
index 96fef3a831..ae13f2cd8a 100644
--- a/activerecord/test/schema/postgresql_specific_schema.rb
+++ b/activerecord/test/schema/postgresql_specific_schema.rb
@@ -1,6 +1,6 @@
ActiveRecord::Schema.define do
- %w(postgresql_tsvectors postgresql_hstores postgresql_arrays postgresql_moneys postgresql_numbers postgresql_times postgresql_network_addresses postgresql_bit_strings postgresql_uuids
+ %w(postgresql_tsvectors postgresql_hstores postgresql_arrays postgresql_moneys postgresql_numbers postgresql_times postgresql_network_addresses postgresql_bit_strings postgresql_uuids postgresql_ltrees
postgresql_oids postgresql_xml_data_type defaults geometrics postgresql_timestamp_with_zones postgresql_partitioned_table postgresql_partitioned_table_parent postgresql_json_data_type postgresql_intrange_data_type).each do |table_name|
execute "DROP TABLE IF EXISTS #{quote_table_name table_name}"
end
@@ -89,6 +89,15 @@ _SQL
_SQL
end
+ if 't' == select_value("select 'ltree'=ANY(select typname from pg_type)")
+ execute <<_SQL
+ CREATE TABLE postgresql_ltrees (
+ id SERIAL PRIMARY KEY,
+ path ltree
+ );
+_SQL
+ end
+
if 't' == select_value("select 'json'=ANY(select typname from pg_type)")
execute <<_SQL
CREATE TABLE postgresql_json_data_type (
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index 41fde553fb..2c0d1de70f 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,5 +1,52 @@
## Rails 4.0.0 (unreleased) ##
+* Extract `ActiveSupport::Testing::Performance` into https://github.com/rails/rails-perftest
+ You can add the gem to your Gemfile to keep using performance tests.
+
+ gem 'rails-perftest'
+
+ *Yves Senn*
+
+
+* Hash.from_xml raises when it encounters type="symbol" or type="yaml".
+ Use Hash.from_trusted_xml to parse this XML.
+
+ CVE-2013-0156
+
+ *Jeremy Kemper*
+
+* Deprecate `assert_present` and `assert_blank` in favor of
+ `assert object.blank?` and `assert object.present?`
+
+ *Yves Senn*
+
+* Change `String#to_date` to use `Date.parse`. This gives more consistent error
+ messages and allows the use of partial dates.
+
+ "gibberish".to_date => Argument Error: invalid date
+ "3rd Feb".to_date => Sun, 03 Feb 2013
+
+ *Kelly Stannard*
+
+* It's now possible to compare `Date`, `DateTime`, `Time` and `TimeWithZone`
+ with `Infinity`. This allows to create date/time ranges with one infinite bound.
+ Example:
+
+ range = Range.new(Date.today, Float::INFINITY)
+
+ Also it's possible to check inclusion of date/time in range with conversion.
+
+ range.include?(Time.now + 1.year) # => true
+ range.include?(DateTime.now + 1.year) # => true
+
+ *Alexander Grebennik*
+
+* Remove meaningless `ActiveSupport::FrozenObjectError`, which was just an alias of `RuntimeError`.
+
+ *Akira Matsuda*
+
+* Introduce `assert_not` to replace warty `assert !foo`. *Jeremy Kemper*
+
* Prevent `Callbacks#set_callback` from setting the same callback twice.
before_save :foo, :bar, :foo
@@ -9,7 +56,7 @@
*Dmitriy Kiriyenko*
-* Add ActiveSupport::Logger#silence that works the same as the old Logger#silence extension.
+* Add `ActiveSupport::Logger#silence` that works the same as the old `Logger#silence` extension.
*DHH*
diff --git a/activesupport/MIT-LICENSE b/activesupport/MIT-LICENSE
index c2bcf1d3e7..6aeeb7132d 100644
--- a/activesupport/MIT-LICENSE
+++ b/activesupport/MIT-LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2005-2012 David Heinemeier Hansson
+Copyright (c) 2005-2013 David Heinemeier Hansson
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/activesupport/lib/active_support.rb b/activesupport/lib/active_support.rb
index b602686114..ffa6ffda4f 100644
--- a/activesupport/lib/active_support.rb
+++ b/activesupport/lib/active_support.rb
@@ -1,5 +1,5 @@
#--
-# Copyright (c) 2005-2012 David Heinemeier Hansson
+# Copyright (c) 2005-2013 David Heinemeier Hansson
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
diff --git a/activesupport/lib/active_support/backtrace_cleaner.rb b/activesupport/lib/active_support/backtrace_cleaner.rb
index f1aff8a8e3..4b41e6247d 100644
--- a/activesupport/lib/active_support/backtrace_cleaner.rb
+++ b/activesupport/lib/active_support/backtrace_cleaner.rb
@@ -72,6 +72,9 @@ module ActiveSupport
@silencers = []
end
+ # Removes all filters, but leaves in silencers. Useful if you suddenly
+ # need to see entire filepaths in the backtrace that you had already
+ # filtered out.
def remove_filters!
@filters = []
end
diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb
index fdec2de1d5..5a5548d567 100644
--- a/activesupport/lib/active_support/cache.rb
+++ b/activesupport/lib/active_support/cache.rb
@@ -3,7 +3,6 @@ require 'zlib'
require 'active_support/core_ext/array/extract_options'
require 'active_support/core_ext/array/wrap'
require 'active_support/core_ext/benchmark'
-require 'active_support/core_ext/exception'
require 'active_support/core_ext/class/attribute_accessors'
require 'active_support/core_ext/numeric/bytes'
require 'active_support/core_ext/numeric/time'
diff --git a/activesupport/lib/active_support/core_ext/array/access.rb b/activesupport/lib/active_support/core_ext/array/access.rb
index a8f9dddae5..4f1e432b61 100644
--- a/activesupport/lib/active_support/core_ext/array/access.rb
+++ b/activesupport/lib/active_support/core_ext/array/access.rb
@@ -21,28 +21,28 @@ class Array
# Equal to <tt>self[1]</tt>.
#
- # %w( a b c d e).second # => "b"
+ # %w( a b c d e ).second # => "b"
def second
self[1]
end
# Equal to <tt>self[2]</tt>.
#
- # %w( a b c d e).third # => "c"
+ # %w( a b c d e ).third # => "c"
def third
self[2]
end
# Equal to <tt>self[3]</tt>.
#
- # %w( a b c d e).fourth # => "d"
+ # %w( a b c d e ).fourth # => "d"
def fourth
self[3]
end
# Equal to <tt>self[4]</tt>.
#
- # %w( a b c d e).fifth # => "e"
+ # %w( a b c d e ).fifth # => "e"
def fifth
self[4]
end
diff --git a/activesupport/lib/active_support/core_ext/array/conversions.rb b/activesupport/lib/active_support/core_ext/array/conversions.rb
index 64e9945ef5..430a35fbaf 100644
--- a/activesupport/lib/active_support/core_ext/array/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/array/conversions.rb
@@ -8,7 +8,7 @@ class Array
# Converts the array to a comma-separated sentence where the last element is
# joined by the connector word.
#
- # You can pass the following options to change the default behaviour. If you
+ # You can pass the following options to change the default behavior. If you
# pass an option key that doesn't exist in the list below, it will raise an
# <tt>ArgumentError</tt>.
#
diff --git a/activesupport/lib/active_support/core_ext/class/attribute.rb b/activesupport/lib/active_support/core_ext/class/attribute.rb
index 1504e18839..5d8d09aa69 100644
--- a/activesupport/lib/active_support/core_ext/class/attribute.rb
+++ b/activesupport/lib/active_support/core_ext/class/attribute.rb
@@ -69,7 +69,8 @@ class Class
# To opt out of both instance methods, pass <tt>instance_accessor: false</tt>.
def class_attribute(*attrs)
options = attrs.extract_options!
- instance_reader = options.fetch(:instance_accessor, true) && options.fetch(:instance_reader, true)
+ # double assignment is used to avoid "assigned but unused variable" warning
+ instance_reader = instance_reader = options.fetch(:instance_accessor, true) && options.fetch(:instance_reader, true)
instance_writer = options.fetch(:instance_accessor, true) && options.fetch(:instance_writer, true)
# We use class_eval here rather than define_method because class_attribute
diff --git a/activesupport/lib/active_support/core_ext/date.rb b/activesupport/lib/active_support/core_ext/date.rb
index 465fedda80..5f13f5f70f 100644
--- a/activesupport/lib/active_support/core_ext/date.rb
+++ b/activesupport/lib/active_support/core_ext/date.rb
@@ -2,4 +2,5 @@ require 'active_support/core_ext/date/acts_like'
require 'active_support/core_ext/date/calculations'
require 'active_support/core_ext/date/conversions'
require 'active_support/core_ext/date/zones'
+require 'active_support/core_ext/date/infinite_comparable'
diff --git a/activesupport/lib/active_support/core_ext/date/calculations.rb b/activesupport/lib/active_support/core_ext/date/calculations.rb
index 421aa12100..106a65610c 100644
--- a/activesupport/lib/active_support/core_ext/date/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/date/calculations.rb
@@ -8,8 +8,6 @@ require 'active_support/core_ext/date_and_time/calculations'
class Date
include DateAndTime::Calculations
- @beginning_of_week_default = nil
-
class << self
attr_accessor :beginning_of_week_default
diff --git a/activesupport/lib/active_support/core_ext/date/infinite_comparable.rb b/activesupport/lib/active_support/core_ext/date/infinite_comparable.rb
new file mode 100644
index 0000000000..ca5d793942
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/date/infinite_comparable.rb
@@ -0,0 +1,5 @@
+require 'active_support/core_ext/infinite_comparable'
+
+class Date
+ include InfiniteComparable
+end
diff --git a/activesupport/lib/active_support/core_ext/date_time.rb b/activesupport/lib/active_support/core_ext/date_time.rb
index e8a27b9f38..024af91738 100644
--- a/activesupport/lib/active_support/core_ext/date_time.rb
+++ b/activesupport/lib/active_support/core_ext/date_time.rb
@@ -2,3 +2,4 @@ require 'active_support/core_ext/date_time/acts_like'
require 'active_support/core_ext/date_time/calculations'
require 'active_support/core_ext/date_time/conversions'
require 'active_support/core_ext/date_time/zones'
+require 'active_support/core_ext/date_time/infinite_comparable'
diff --git a/activesupport/lib/active_support/core_ext/date_time/calculations.rb b/activesupport/lib/active_support/core_ext/date_time/calculations.rb
index fca5d4d679..4e4852a5e6 100644
--- a/activesupport/lib/active_support/core_ext/date_time/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/date_time/calculations.rb
@@ -142,11 +142,4 @@ class DateTime
def utc_offset
(offset * 86400).to_i
end
-
- # Layers additional behavior on DateTime#<=> so that Time and
- # ActiveSupport::TimeWithZone instances can be compared with a DateTime.
- def <=>(other)
- super other.to_datetime
- end
-
end
diff --git a/activesupport/lib/active_support/core_ext/date_time/infinite_comparable.rb b/activesupport/lib/active_support/core_ext/date_time/infinite_comparable.rb
new file mode 100644
index 0000000000..8a282b19f2
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/date_time/infinite_comparable.rb
@@ -0,0 +1,5 @@
+require 'active_support/core_ext/infinite_comparable'
+
+class DateTime
+ include InfiniteComparable
+end
diff --git a/activesupport/lib/active_support/core_ext/exception.rb b/activesupport/lib/active_support/core_ext/exception.rb
deleted file mode 100644
index ba7757ea07..0000000000
--- a/activesupport/lib/active_support/core_ext/exception.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-module ActiveSupport
- FrozenObjectError = RuntimeError
-end
diff --git a/activesupport/lib/active_support/core_ext/hash/conversions.rb b/activesupport/lib/active_support/core_ext/hash/conversions.rb
index 6cb7434e5f..8930376ac8 100644
--- a/activesupport/lib/active_support/core_ext/hash/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/hash/conversions.rb
@@ -101,17 +101,33 @@ class Hash
#
# hash = Hash.from_xml(xml)
# # => {"hash"=>{"foo"=>1, "bar"=>2}}
- def from_xml(xml)
- ActiveSupport::XMLConverter.new(xml).to_h
+ #
+ # DisallowedType is raise if the XML contains attributes with <tt>type="yaml"</tt> or
+ # <tt>type="symbol"</tt>. Use <tt>Hash.from_trusted_xml</tt> to parse this XML.
+ def from_xml(xml, disallowed_types = nil)
+ ActiveSupport::XMLConverter.new(xml, disallowed_types).to_h
end
+ # Builds a Hash from XML just like <tt>Hash.from_xml</tt>, but also allows Symbol and YAML.
+ def from_trusted_xml(xml)
+ from_xml xml, []
+ end
end
end
module ActiveSupport
class XMLConverter # :nodoc:
- def initialize(xml)
+ class DisallowedType < StandardError
+ def initialize(type)
+ super "Disallowed type attribute: #{type.inspect}"
+ end
+ end
+
+ DISALLOWED_TYPES = %w(symbol yaml)
+
+ def initialize(xml, disallowed_types = nil)
@xml = normalize_keys(XmlMini.parse(xml))
+ @disallowed_types = disallowed_types || DISALLOWED_TYPES
end
def to_h
@@ -119,7 +135,6 @@ module ActiveSupport
end
private
-
def normalize_keys(params)
case params
when Hash
@@ -145,6 +160,10 @@ module ActiveSupport
end
def process_hash(value)
+ if value.include?('type') && !value['type'].is_a?(Hash) && @disallowed_types.include?(value['type'])
+ raise DisallowedType, value['type']
+ end
+
if become_array?(value)
_, entries = Array.wrap(value.detect { |k,v| not v.is_a?(String) })
if entries.nil? || value['__content__'].try(:empty?)
diff --git a/activesupport/lib/active_support/core_ext/hash/except.rb b/activesupport/lib/active_support/core_ext/hash/except.rb
index 5cb00d0ebd..d90e996ad4 100644
--- a/activesupport/lib/active_support/core_ext/hash/except.rb
+++ b/activesupport/lib/active_support/core_ext/hash/except.rb
@@ -2,7 +2,7 @@ class Hash
# Return a hash that includes everything but the given keys. This is useful for
# limiting a set of parameters to everything but a few known toggles:
#
- # @person.update_attributes(params[:person].except(:admin))
+ # @person.update(params[:person].except(:admin))
def except(*keys)
dup.except!(*keys)
end
diff --git a/activesupport/lib/active_support/core_ext/infinite_comparable.rb b/activesupport/lib/active_support/core_ext/infinite_comparable.rb
new file mode 100644
index 0000000000..b78b2deaad
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/infinite_comparable.rb
@@ -0,0 +1,35 @@
+require 'active_support/concern'
+require 'active_support/core_ext/module/aliasing'
+require 'active_support/core_ext/object/try'
+
+module InfiniteComparable
+ extend ActiveSupport::Concern
+
+ included do
+ alias_method_chain :<=>, :infinity
+ end
+
+ define_method :'<=>_with_infinity' do |other|
+ if other.class == self.class
+ public_send :'<=>_without_infinity', other
+ else
+ infinite = try(:infinite?)
+ other_infinite = other.try(:infinite?)
+
+ # inf <=> inf
+ if infinite && other_infinite
+ infinite <=> other_infinite
+ # not_inf <=> inf
+ elsif other_infinite
+ -other_infinite
+ # inf <=> not_inf
+ elsif infinite
+ infinite
+ else
+ conversion = "to_#{self.class.name.downcase}"
+ other = other.public_send(conversion) if other.respond_to?(conversion)
+ public_send :'<=>_without_infinity', other
+ end
+ 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 7b518821c8..79d3303b41 100644
--- a/activesupport/lib/active_support/core_ext/kernel/reporting.rb
+++ b/activesupport/lib/active_support/core_ext/kernel/reporting.rb
@@ -59,10 +59,9 @@ module Kernel
#
# puts 'This code gets executed and nothing related to ZeroDivisionError was seen'
def suppress(*exception_classes)
- begin yield
- rescue Exception => e
- raise unless exception_classes.any? { |cls| e.kind_of?(cls) }
- end
+ yield
+ rescue Exception => e
+ raise unless exception_classes.any? { |cls| e.kind_of?(cls) }
end
# Captures the given stream and returns it:
diff --git a/activesupport/lib/active_support/core_ext/marshal.rb b/activesupport/lib/active_support/core_ext/marshal.rb
index fec3051c0c..c7a8348b1d 100644
--- a/activesupport/lib/active_support/core_ext/marshal.rb
+++ b/activesupport/lib/active_support/core_ext/marshal.rb
@@ -1,21 +1,19 @@
module Marshal
class << self
def load_with_autoloading(source)
- begin
- load_without_autoloading(source)
- rescue ArgumentError, NameError => exc
- if exc.message.match(%r|undefined class/module (.+)|)
- # try loading the class/module
- $1.constantize
- # if it is a IO we need to go back to read the object
- source.rewind if source.respond_to?(:rewind)
- retry
- else
- raise exc
- end
+ load_without_autoloading(source)
+ rescue ArgumentError, NameError => exc
+ if exc.message.match(%r|undefined class/module (.+)|)
+ # try loading the class/module
+ $1.constantize
+ # if it is a IO we need to go back to read the object
+ source.rewind if source.respond_to?(:rewind)
+ retry
+ else
+ raise exc
end
end
alias_method_chain :load, :autoloading
end
-end \ No newline at end of file
+end
diff --git a/activesupport/lib/active_support/core_ext/numeric.rb b/activesupport/lib/active_support/core_ext/numeric.rb
index a6bc0624be..d5cfc2ece4 100644
--- a/activesupport/lib/active_support/core_ext/numeric.rb
+++ b/activesupport/lib/active_support/core_ext/numeric.rb
@@ -1,3 +1,4 @@
require 'active_support/core_ext/numeric/bytes'
require 'active_support/core_ext/numeric/time'
require 'active_support/core_ext/numeric/conversions'
+require 'active_support/core_ext/numeric/infinite_comparable'
diff --git a/activesupport/lib/active_support/core_ext/numeric/infinite_comparable.rb b/activesupport/lib/active_support/core_ext/numeric/infinite_comparable.rb
new file mode 100644
index 0000000000..b5f1b0487b
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/numeric/infinite_comparable.rb
@@ -0,0 +1,9 @@
+require 'active_support/core_ext/infinite_comparable'
+
+class Float
+ include InfiniteComparable
+end
+
+class BigDecimal
+ include InfiniteComparable
+end
diff --git a/activesupport/lib/active_support/core_ext/object/acts_like.rb b/activesupport/lib/active_support/core_ext/object/acts_like.rb
index fcc8e50f06..3912cc5ace 100644
--- a/activesupport/lib/active_support/core_ext/object/acts_like.rb
+++ b/activesupport/lib/active_support/core_ext/object/acts_like.rb
@@ -1,9 +1,9 @@
class Object
# A duck-type assistant method. For example, Active Support extends Date
- # to define an acts_like_date? method, and extends Time to define
- # acts_like_time?. As a result, we can do "x.acts_like?(:time)" and
- # "x.acts_like?(:date)" to do duck-type-safe comparisons, since classes that
- # we want to act like Time simply need to define an acts_like_time? method.
+ # to define an <tt>acts_like_date?</tt> method, and extends Time to define
+ # <tt>acts_like_time?</tt>. As a result, we can do <tt>x.acts_like?(:time)</tt> and
+ # <tt>x.acts_like?(:date)</tt> to do duck-type-safe comparisons, since classes that
+ # we want to act like Time simply need to define an <tt>acts_like_time?</tt> method.
def acts_like?(duck)
respond_to? :"acts_like_#{duck}?"
end
diff --git a/activesupport/lib/active_support/core_ext/object/instance_variables.rb b/activesupport/lib/active_support/core_ext/object/instance_variables.rb
index 40821fd619..755e1c6b16 100644
--- a/activesupport/lib/active_support/core_ext/object/instance_variables.rb
+++ b/activesupport/lib/active_support/core_ext/object/instance_variables.rb
@@ -13,7 +13,7 @@ class Object
Hash[instance_variables.map { |name| [name[1..-1], instance_variable_get(name)] }]
end
- # Returns an array of instance variable names including "@".
+ # Returns an array of instance variable names as strings including "@".
#
# class C
# def initialize(x, y)
diff --git a/activesupport/lib/active_support/core_ext/string/conversions.rb b/activesupport/lib/active_support/core_ext/string/conversions.rb
index 9d3b81cf38..c795df124b 100644
--- a/activesupport/lib/active_support/core_ext/string/conversions.rb
+++ b/activesupport/lib/active_support/core_ext/string/conversions.rb
@@ -32,11 +32,7 @@ class String
# "2012-12-13".to_date #=> Thu, 13 Dec 2012
# "12/13/2012".to_date #=> ArgumentError: invalid date
def to_date
- unless blank?
- date_values = ::Date._parse(self, false).values_at(:year, :mon, :mday)
-
- ::Date.new(*date_values)
- end
+ ::Date.parse(self, false) unless blank?
end
# Converts a string to a DateTime value.
diff --git a/activesupport/lib/active_support/core_ext/time.rb b/activesupport/lib/active_support/core_ext/time.rb
index 32cffe237d..af6b589b71 100644
--- a/activesupport/lib/active_support/core_ext/time.rb
+++ b/activesupport/lib/active_support/core_ext/time.rb
@@ -3,3 +3,4 @@ require 'active_support/core_ext/time/calculations'
require 'active_support/core_ext/time/conversions'
require 'active_support/core_ext/time/marshal'
require 'active_support/core_ext/time/zones'
+require 'active_support/core_ext/time/infinite_comparable'
diff --git a/activesupport/lib/active_support/core_ext/time/infinite_comparable.rb b/activesupport/lib/active_support/core_ext/time/infinite_comparable.rb
new file mode 100644
index 0000000000..63795885f5
--- /dev/null
+++ b/activesupport/lib/active_support/core_ext/time/infinite_comparable.rb
@@ -0,0 +1,5 @@
+require 'active_support/core_ext/infinite_comparable'
+
+class Time
+ include InfiniteComparable
+end
diff --git a/activesupport/lib/active_support/core_ext/time/zones.rb b/activesupport/lib/active_support/core_ext/time/zones.rb
index 796c5f9805..139d48f59c 100644
--- a/activesupport/lib/active_support/core_ext/time/zones.rb
+++ b/activesupport/lib/active_support/core_ext/time/zones.rb
@@ -1,8 +1,6 @@
require 'active_support/time_with_zone'
class Time
- @zone_default = nil
-
class << self
attr_accessor :zone_default
diff --git a/activesupport/lib/active_support/dependencies/autoload.rb b/activesupport/lib/active_support/dependencies/autoload.rb
index 9fc58a338f..c0dba5f7fd 100644
--- a/activesupport/lib/active_support/dependencies/autoload.rb
+++ b/activesupport/lib/active_support/dependencies/autoload.rb
@@ -34,7 +34,7 @@ module ActiveSupport
def autoload(const_name, path = @_at_path)
unless path
- full = [name, @_under_path, const_name.to_s, path].compact.join("::")
+ full = [name, @_under_path, const_name.to_s].compact.join("::")
path = Inflector.underscore(full)
end
diff --git a/activesupport/lib/active_support/inflector/methods.rb b/activesupport/lib/active_support/inflector/methods.rb
index 1eb2b4212b..39648727fd 100644
--- a/activesupport/lib/active_support/inflector/methods.rb
+++ b/activesupport/lib/active_support/inflector/methods.rb
@@ -266,14 +266,12 @@ module ActiveSupport
# 'UnknownModule'.safe_constantize # => nil
# 'UnknownModule::Foo::Bar'.safe_constantize # => nil
def safe_constantize(camel_cased_word)
- begin
- constantize(camel_cased_word)
- rescue NameError => e
- raise unless e.message =~ /(uninitialized constant|wrong constant name) #{const_regexp(camel_cased_word)}$/ ||
- e.name.to_s == camel_cased_word.to_s
- rescue ArgumentError => e
- raise unless e.message =~ /not missing constant #{const_regexp(camel_cased_word)}\!$/
- end
+ constantize(camel_cased_word)
+ rescue NameError => e
+ raise unless e.message =~ /(uninitialized constant|wrong constant name) #{const_regexp(camel_cased_word)}$/ ||
+ e.name.to_s == camel_cased_word.to_s
+ rescue ArgumentError => e
+ raise unless e.message =~ /not missing constant #{const_regexp(camel_cased_word)}\!$/
end
# Returns the suffix that should be added to a number to denote the position
diff --git a/activesupport/lib/active_support/json/encoding.rb b/activesupport/lib/active_support/json/encoding.rb
index 832d1ce6d5..9bf1ea35b3 100644
--- a/activesupport/lib/active_support/json/encoding.rb
+++ b/activesupport/lib/active_support/json/encoding.rb
@@ -235,7 +235,7 @@ class BigDecimal
# real value.
#
# Use <tt>ActiveSupport.use_standard_json_big_decimal_format = true</tt> to
- # override this behaviour.
+ # override this behavior.
def as_json(options = nil) #:nodoc:
if finite?
ActiveSupport.encode_big_decimal_as_string ? to_s : self
diff --git a/activesupport/lib/active_support/log_subscriber.rb b/activesupport/lib/active_support/log_subscriber.rb
index a58afc6b9d..21a04a9152 100644
--- a/activesupport/lib/active_support/log_subscriber.rb
+++ b/activesupport/lib/active_support/log_subscriber.rb
@@ -53,7 +53,9 @@ module ActiveSupport
class << self
def logger
- @logger ||= Rails.logger if defined?(Rails)
+ if defined?(Rails) && Rails.respond_to?(:logger)
+ @logger ||= Rails.logger
+ end
@logger
end
diff --git a/activesupport/lib/active_support/log_subscriber/test_helper.rb b/activesupport/lib/active_support/log_subscriber/test_helper.rb
index 63dad7e01a..f9a98686d3 100644
--- a/activesupport/lib/active_support/log_subscriber/test_helper.rb
+++ b/activesupport/lib/active_support/log_subscriber/test_helper.rb
@@ -15,7 +15,7 @@ module ActiveSupport
# end
#
# def test_basic_query_logging
- # Developer.all
+ # Developer.all.to_a
# wait
# assert_equal 1, @logger.logged(:debug).size
# assert_match(/Developer Load/, @logger.logged(:debug).last)
diff --git a/activesupport/lib/active_support/notifications/instrumenter.rb b/activesupport/lib/active_support/notifications/instrumenter.rb
index ab0b162ee0..1ee7ca06bb 100644
--- a/activesupport/lib/active_support/notifications/instrumenter.rb
+++ b/activesupport/lib/active_support/notifications/instrumenter.rb
@@ -7,7 +7,7 @@ module ActiveSupport
attr_reader :id
def initialize(notifier)
- @id = unique_id
+ @id = unique_id
@notifier = notifier
end
@@ -15,21 +15,32 @@ module ActiveSupport
# and publish it. Notice that events get sent even if an error occurs
# in the passed-in block.
def instrument(name, payload={})
- @notifier.start(name, @id, payload)
+ start name, payload
begin
yield
rescue Exception => e
payload[:exception] = [e.class.name, e.message]
raise e
ensure
- @notifier.finish(name, @id, payload)
+ finish name, payload
end
end
+ # Send a start notification with +name+ and +payload+.
+ def start(name, payload)
+ @notifier.start name, @id, payload
+ end
+
+ # Send a finish notification with +name+ and +payload+.
+ def finish(name, payload)
+ @notifier.finish name, @id, payload
+ end
+
private
- def unique_id
- SecureRandom.hex(10)
- end
+
+ def unique_id
+ SecureRandom.hex(10)
+ end
end
class Event
diff --git a/activesupport/lib/active_support/railtie.rb b/activesupport/lib/active_support/railtie.rb
index 133aa6a054..72ac597d99 100644
--- a/activesupport/lib/active_support/railtie.rb
+++ b/activesupport/lib/active_support/railtie.rb
@@ -13,20 +13,6 @@ module ActiveSupport
end
end
- # Sets the default value for Time.zone
- # If assigned value cannot be matched to a TimeZone, an exception will be raised.
- initializer "active_support.initialize_time_zone" do |app|
- require 'active_support/core_ext/time/zones'
- zone_default = Time.find_zone!(app.config.time_zone)
-
- unless zone_default
- raise 'Value assigned to config.time_zone not recognized. ' \
- 'Run "rake -D time" for a list of tasks for finding appropriate time zone names.'
- end
-
- Time.zone_default = zone_default
- end
-
# Sets the default week start
# If assigned value is not a valid day symbol (e.g. :sunday, :monday, ...), an exception will be raised.
initializer "active_support.initialize_beginning_of_week" do |app|
@@ -42,5 +28,21 @@ module ActiveSupport
ActiveSupport.send(k, v) if ActiveSupport.respond_to? k
end
end
+
+ # Sets the default value for Time.zone after initialization since the default configuration
+ # lives in application initializers.
+ # If assigned value cannot be matched to a TimeZone, an exception will be raised.
+ config.after_initialize do |app|
+ require 'active_support/core_ext/time/zones'
+ zone_default = Time.find_zone!(app.config.time_zone)
+
+ unless zone_default
+ raise 'Value assigned to config.time_zone not recognized. ' \
+ 'Run "rake -D time" for a list of tasks for finding appropriate time zone names.'
+ end
+
+ Time.zone_default = zone_default
+ end
+
end
end
diff --git a/activesupport/lib/active_support/test_case.rb b/activesupport/lib/active_support/test_case.rb
index e4f182a3aa..8b392c36d0 100644
--- a/activesupport/lib/active_support/test_case.rb
+++ b/activesupport/lib/active_support/test_case.rb
@@ -1,10 +1,11 @@
gem 'minitest' # make sure we get the gem, not stdlib
-require 'minitest/spec'
+require 'minitest/unit'
require 'active_support/testing/tagged_logging'
require 'active_support/testing/setup_and_teardown'
require 'active_support/testing/assertions'
require 'active_support/testing/deprecation'
require 'active_support/testing/pending'
+require 'active_support/testing/declarative'
require 'active_support/testing/isolation'
require 'active_support/testing/constant_lookup'
require 'active_support/core_ext/kernel/reporting'
@@ -16,13 +17,7 @@ rescue LoadError
end
module ActiveSupport
- class TestCase < ::MiniTest::Spec
-
- # Use AS::TestCase for the base class when describing a model
- register_spec_type(self) do |desc|
- Class === desc && desc < ActiveRecord::Base
- end
-
+ class TestCase < ::MiniTest::Unit::TestCase
Assertion = MiniTest::Assertion
alias_method :method_name, :__name__
@@ -42,31 +37,22 @@ module ActiveSupport
include ActiveSupport::Testing::Assertions
include ActiveSupport::Testing::Deprecation
include ActiveSupport::Testing::Pending
-
- def self.describe(text)
- if block_given?
- super
- else
- message = "`describe` without a block is deprecated, please switch to: `def self.name; #{text.inspect}; end`\n"
- ActiveSupport::Deprecation.warn message
-
- class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
- def self.name
- "#{text}"
- end
- RUBY_EVAL
- end
- end
-
- class << self
- alias :test :it
- end
+ extend ActiveSupport::Testing::Declarative
# test/unit backwards compatibility methods
alias :assert_raise :assert_raises
- alias :assert_not_nil :refute_nil
+ alias :assert_not_empty :refute_empty
alias :assert_not_equal :refute_equal
+ alias :assert_not_in_delta :refute_in_delta
+ alias :assert_not_in_epsilon :refute_in_epsilon
+ alias :assert_not_includes :refute_includes
+ alias :assert_not_instance_of :refute_instance_of
+ alias :assert_not_kind_of :refute_kind_of
alias :assert_no_match :refute_match
+ alias :assert_not_nil :refute_nil
+ alias :assert_not_operator :refute_operator
+ alias :assert_not_predicate :refute_predicate
+ alias :assert_not_respond_to :refute_respond_to
alias :assert_not_same :refute_same
# Fails if the block raises an exception.
diff --git a/activesupport/lib/active_support/testing/assertions.rb b/activesupport/lib/active_support/testing/assertions.rb
index 8466049e20..175f7ffe5a 100644
--- a/activesupport/lib/active_support/testing/assertions.rb
+++ b/activesupport/lib/active_support/testing/assertions.rb
@@ -3,6 +3,22 @@ require 'active_support/core_ext/object/blank'
module ActiveSupport
module Testing
module Assertions
+ # Assert that an expression is not truthy. Passes if <tt>object</tt> is
+ # +nil+ or +false+. "Truthy" means "considered true in a conditional"
+ # like <tt>if foo</tt>.
+ #
+ # assert_not nil # => true
+ # assert_not false # => true
+ # assert_not 'foo' # => 'foo' is not nil or false
+ #
+ # An error message can be specified.
+ #
+ # assert_not foo, 'foo should be false'
+ def assert_not(object, message = nil)
+ message ||= "Expected #{mu_pp(object)} to be nil or false"
+ assert !object, message
+ end
+
# Test numeric difference between the return value of an expression as a
# result of what is evaluated in the yielded block.
#
@@ -87,6 +103,7 @@ module ActiveSupport
#
# assert_blank [], 'this should be blank'
def assert_blank(object, message=nil)
+ ActiveSupport::Deprecation.warn('"assert_blank" is deprecated. Please use "assert object.blank?" instead')
message ||= "#{object.inspect} is not blank"
assert object.blank?, message
end
@@ -101,6 +118,7 @@ module ActiveSupport
#
# assert_present({ data: 'x' }, 'this should not be blank')
def assert_present(object, message=nil)
+ ActiveSupport::Deprecation.warn('"assert_present" is deprecated. Please use "assert object.present?" instead')
message ||= "#{object.inspect} is blank"
assert object.present?, message
end
diff --git a/activesupport/lib/active_support/testing/autorun.rb b/activesupport/lib/active_support/testing/autorun.rb
new file mode 100644
index 0000000000..c446adc16d
--- /dev/null
+++ b/activesupport/lib/active_support/testing/autorun.rb
@@ -0,0 +1,5 @@
+gem 'minitest'
+
+require 'minitest/unit'
+
+MiniTest::Unit.autorun
diff --git a/activesupport/lib/active_support/testing/declarative.rb b/activesupport/lib/active_support/testing/declarative.rb
new file mode 100644
index 0000000000..508e37254a
--- /dev/null
+++ b/activesupport/lib/active_support/testing/declarative.rb
@@ -0,0 +1,40 @@
+module ActiveSupport
+ module Testing
+ module Declarative
+
+ def self.extended(klass) #:nodoc:
+ klass.class_eval do
+
+ unless method_defined?(:describe)
+ def self.describe(text)
+ class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
+ def self.name
+ "#{text}"
+ end
+ RUBY_EVAL
+ end
+ end
+
+ end
+ end
+
+ unless defined?(Spec)
+ # test "verify something" do
+ # ...
+ # end
+ def test(name, &block)
+ test_name = "test_#{name.gsub(/\s+/,'_')}".to_sym
+ defined = instance_method(test_name) rescue false
+ raise "#{test_name} is already defined in #{self}" if defined
+ if block_given?
+ define_method(test_name, &block)
+ else
+ define_method(test_name) do
+ flunk "No implementation provided for #{name}"
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/activesupport/lib/active_support/testing/isolation.rb b/activesupport/lib/active_support/testing/isolation.rb
index 27d444fd91..aa87598926 100644
--- a/activesupport/lib/active_support/testing/isolation.rb
+++ b/activesupport/lib/active_support/testing/isolation.rb
@@ -12,8 +12,8 @@ module ActiveSupport
end
class ProxyTestResult
- def initialize
- @calls = []
+ def initialize(calls = [])
+ @calls = calls
end
def add_error(e)
@@ -27,6 +27,14 @@ module ActiveSupport
end
end
+ def marshal_dump
+ @calls
+ end
+
+ def marshal_load(calls)
+ initialize(calls)
+ end
+
def method_missing(name, *args)
@calls << [name, args]
end
diff --git a/activesupport/lib/active_support/testing/performance.rb b/activesupport/lib/active_support/testing/performance.rb
deleted file mode 100644
index 7102ffe2ed..0000000000
--- a/activesupport/lib/active_support/testing/performance.rb
+++ /dev/null
@@ -1,271 +0,0 @@
-require 'fileutils'
-require 'active_support/concern'
-require 'active_support/core_ext/class/delegating_attributes'
-require 'active_support/core_ext/string/inflections'
-require 'active_support/core_ext/module/delegation'
-require 'active_support/number_helper'
-
-module ActiveSupport
- module Testing
- module Performance
- extend ActiveSupport::Concern
-
- included do
- superclass_delegating_accessor :profile_options
- self.profile_options = {}
- end
-
- # each implementation should define metrics and freeze the defaults
- DEFAULTS =
- if ARGV.include?('--benchmark') # HAX for rake test
- { :runs => 4,
- :output => 'tmp/performance',
- :benchmark => true }
- else
- { :runs => 1,
- :output => 'tmp/performance',
- :benchmark => false }
- end
-
- def full_profile_options
- DEFAULTS.merge(profile_options)
- end
-
- def full_test_name
- "#{self.class.name}##{method_name}"
- end
-
- def run(runner)
- @runner = runner
-
- run_warmup
- if full_profile_options && metrics = full_profile_options[:metrics]
- metrics.each do |metric_name|
- if klass = Metrics[metric_name.to_sym]
- run_profile(klass.new)
- end
- end
- end
-
- return
- end
-
- def run_test(metric, mode)
- result = '.'
- begin
- run_callbacks :setup
- setup
- metric.send(mode) { __send__ method_name }
- rescue Exception => e
- result = @runner.puke(self.class, method_name, e)
- ensure
- begin
- teardown
- run_callbacks :teardown
- rescue Exception => e
- result = @runner.puke(self.class, method_name, e)
- end
- end
- result
- end
-
- protected
- # overridden by each implementation.
- def run_gc; end
-
- def run_warmup
- run_gc
-
- time = Metrics::Time.new
- run_test(time, :benchmark)
- puts "%s (%s warmup)" % [full_test_name, time.format(time.total)]
-
- run_gc
- end
-
- def run_profile(metric)
- klass = full_profile_options[:benchmark] ? Benchmarker : Profiler
- performer = klass.new(self, metric)
-
- performer.run
- puts performer.report
- performer.record
- end
-
- class Performer
- delegate :run_test, :full_profile_options, :full_test_name, :to => :@harness
-
- def initialize(harness, metric)
- @harness, @metric, @supported = harness, metric, false
- end
-
- def report
- if @supported
- rate = @total / full_profile_options[:runs]
- '%20s: %s' % [@metric.name, @metric.format(rate)]
- else
- '%20s: unsupported' % @metric.name
- end
- end
-
- protected
- def output_filename
- "#{full_profile_options[:output]}/#{full_test_name}_#{@metric.name}"
- end
- end
-
- # overridden by each implementation.
- class Profiler < Performer
- def time_with_block
- before = Time.now
- yield
- Time.now - before
- end
-
- def run; end
- def record; end
- end
-
- class Benchmarker < Performer
- def initialize(*args)
- 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
-
- def record
- avg = @metric.total / full_profile_options[:runs].to_i
- now = Time.now.utc.xmlschema
- with_output_file do |file|
- file.puts "#{avg},#{now},#{environment}"
- end
- end
-
- def environment
- @env ||= [].tap do |env|
- env << "#{$1}.#{$2}" if File.directory?('.git') && `git branch -v` =~ /^\* (\S+)\s+(\S+)/
- env << rails_version if defined?(Rails::VERSION::STRING)
- env << "#{RUBY_ENGINE}-#{RUBY_VERSION}.#{RUBY_PATCHLEVEL}"
- env << RUBY_PLATFORM
- end.join(',')
- end
-
- protected
- if defined?(Rails::VERSION::STRING)
- HEADER = 'measurement,created_at,app,rails,ruby,platform'
- else
- HEADER = 'measurement,created_at,app,ruby,platform'
- end
-
- def with_output_file
- fname = output_filename
-
- if new = !File.exist?(fname)
- FileUtils.mkdir_p(File.dirname(fname))
- end
-
- File.open(fname, 'ab') do |file|
- file.puts(HEADER) if new
- yield file
- end
- end
-
- def output_filename
- "#{super}.csv"
- end
-
- def rails_version
- "rails-#{Rails::VERSION::STRING}#{rails_branch}"
- end
-
- def rails_branch
- if File.directory?('vendor/rails/.git')
- Dir.chdir('vendor/rails') do
- ".#{$1}.#{$2}" if `git branch -v` =~ /^\* (\S+)\s+(\S+)/
- end
- end
- end
- end
-
- module Metrics
- def self.[](name)
- const_get(name.to_s.camelize)
- rescue NameError
- nil
- end
-
- class Base
- include ActiveSupport::NumberHelper
-
- attr_reader :total
-
- def initialize
- @total = 0
- end
-
- def name
- @name ||= self.class.name.demodulize.underscore
- end
-
- def benchmark
- with_gc_stats do
- before = measure
- yield
- @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
- end
-
- def format(measurement)
- if measurement < 1
- '%d ms' % (measurement * 1000)
- else
- '%.2f sec' % measurement
- end
- end
- end
-
- class Amount < Base
- def format(measurement)
- number_to_delimited(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
- end
-end
-
-case RUBY_ENGINE
- when 'ruby' then require 'active_support/testing/performance/ruby'
- when 'rbx' then require 'active_support/testing/performance/rubinius'
- when 'jruby' then require 'active_support/testing/performance/jruby'
- else
- $stderr.puts 'Your ruby interpreter is not supported for benchmarking.'
- exit
-end
diff --git a/activesupport/lib/active_support/testing/performance/jruby.rb b/activesupport/lib/active_support/testing/performance/jruby.rb
deleted file mode 100644
index 34e3f9f45f..0000000000
--- a/activesupport/lib/active_support/testing/performance/jruby.rb
+++ /dev/null
@@ -1,115 +0,0 @@
-require 'jruby/profiler'
-require 'java'
-java_import java.lang.management.ManagementFactory
-
-module ActiveSupport
- module Testing
- module Performance
- DEFAULTS.merge!(
- if ARGV.include?('--benchmark')
- {:metrics => [:wall_time, :user_time, :memory, :gc_runs, :gc_time]}
- else
- { :metrics => [:wall_time],
- :formats => [:flat, :graph] }
- end).freeze
-
- protected
- def run_gc
- ManagementFactory.memory_mx_bean.gc
- 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) }
- end
- end
- end
-
- 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|
- fname = output_filename(klass)
- FileUtils.mkdir_p(File.dirname(fname))
- File.open(fname, 'wb') do |file|
- klass.new(@data).printProfile(file)
- end
- end
- end
-
- protected
- def output_filename(printer_class)
- suffix =
- case printer_class.name.demodulize
- when 'FlatProfilePrinter'; 'flat.txt'
- when 'GraphProfilePrinter'; 'graph.txt'
- else printer_class.name.sub(/ProfilePrinter$/, '').underscore
- end
-
- "#{super()}_#{suffix}"
- end
- end
-
- module Metrics
- class Base
- def profile
- yield
- end
-
- protected
- def with_gc_stats
- ManagementFactory.memory_mx_bean.gc
- yield
- end
- end
-
- class WallTime < Time
- def measure
- super
- end
- end
-
- class CpuTime < Time
- def measure
- 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
- end
- end
-
- class Memory < DigitalInformationUnit
- def measure
- 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 }
- end
- end
-
- class GcTime < Time
- def measure
- ManagementFactory.garbage_collector_mx_beans.inject(0) { |total_time, current_gc| total_time += current_gc.collection_time } / 1000.0 # seconds
- end
- end
- end
- end
- end
-end
diff --git a/activesupport/lib/active_support/testing/performance/rubinius.rb b/activesupport/lib/active_support/testing/performance/rubinius.rb
deleted file mode 100644
index d9ebfbe352..0000000000
--- a/activesupport/lib/active_support/testing/performance/rubinius.rb
+++ /dev/null
@@ -1,113 +0,0 @@
-require 'rubinius/agent'
-
-module ActiveSupport
- module Testing
- module Performance
- DEFAULTS.merge!(
- if ARGV.include?('--benchmark')
- {:metrics => [:wall_time, :memory, :objects, :gc_runs, :gc_time]}
- else
- { :metrics => [:wall_time],
- :formats => [:flat, :graph] }
- end).freeze
-
- protected
- def run_gc
- GC.run(true)
- end
-
- class Performer; end
-
- class Profiler < Performer
- def initialize(*args)
- 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"
- FileUtils.mkdir_p(File.dirname(fname))
- File.open(fname, 'wb') do |file|
- yield(file)
- end
- end
- end
-
- module Metrics
- class Base
- attr_reader :loopback
-
- def profile
- yield
- end
-
- protected
- def with_gc_stats
- @loopback = Rubinius::Agent.loopback
- GC.run(true)
- yield
- end
- end
-
- class WallTime < Time
- def measure
- super
- end
- end
-
- class Memory < DigitalInformationUnit
- def measure
- loopback.get("system.memory.counter.bytes").last
- end
- end
-
- class Objects < Amount
- def measure
- loopback.get("system.memory.counter.objects").last
- end
- end
-
- class GcRuns < Amount
- def measure
- loopback.get("system.gc.full.count").last + loopback.get("system.gc.young.count").last
- end
- end
-
- class GcTime < Time
- def measure
- (loopback.get("system.gc.full.wallclock").last + loopback.get("system.gc.young.wallclock").last) / 1000.0
- end
- end
- end
- end
- end
-end
diff --git a/activesupport/lib/active_support/testing/performance/ruby.rb b/activesupport/lib/active_support/testing/performance/ruby.rb
deleted file mode 100644
index 7c149df1e4..0000000000
--- a/activesupport/lib/active_support/testing/performance/ruby.rb
+++ /dev/null
@@ -1,173 +0,0 @@
-begin
- require 'ruby-prof'
-rescue LoadError
- $stderr.puts 'Specify ruby-prof as application\'s dependency in Gemfile to run benchmarks.'
- raise
-end
-
-module ActiveSupport
- module Testing
- module Performance
- DEFAULTS.merge!(
- if ARGV.include?('--benchmark')
- { :metrics => [:wall_time, :memory, :objects, :gc_runs, :gc_time] }
- else
- { :min_percent => 0.01,
- :metrics => [:process_time, :memory, :objects],
- :formats => [:flat, :graph_html, :call_tree, :call_stack] }
- end).freeze
-
- protected
- remove_method :run_gc
- def run_gc
- GC.start
- end
-
- class Profiler < Performer
- def initialize(*args)
- super
- @supported = @metric.measure_mode rescue false
- end
-
- remove_method :run
- def run
- return unless @supported
-
- RubyProf.measure_mode = @metric.measure_mode
- RubyProf.start
- RubyProf.pause
- full_profile_options[:runs].to_i.times { run_test(@metric, :profile) }
- @data = RubyProf.stop
- @total = @data.threads.sum(0) { |thread| thread.methods.max.total_time }
- end
-
- remove_method :record
- def record
- return unless @supported
-
- klasses = full_profile_options[:formats].map { |f| RubyProf.const_get("#{f.to_s.camelize}Printer") }.compact
-
- klasses.each do |klass|
- fname = output_filename(klass)
- FileUtils.mkdir_p(File.dirname(fname))
- File.open(fname, 'wb') do |file|
- klass.new(@data).print(file, full_profile_options.slice(:min_percent))
- end
- end
- end
-
- protected
- def output_filename(printer_class)
- suffix =
- case printer_class.name.demodulize
- when 'FlatPrinter'; 'flat.txt'
- when 'FlatPrinterWithLineNumbers'; 'flat_line_numbers.txt'
- when 'GraphPrinter'; 'graph.txt'
- when 'GraphHtmlPrinter'; 'graph.html'
- when 'GraphYamlPrinter'; 'graph.yml'
- when 'CallTreePrinter'; 'tree.txt'
- when 'CallStackPrinter'; 'stack.html'
- when 'DotPrinter'; 'graph.dot'
- else printer_class.name.sub(/Printer$/, '').underscore
- end
-
- "#{super()}_#{suffix}"
- end
- end
-
- module Metrics
- class Base
- def measure_mode
- self.class::Mode
- end
-
- remove_method :profile
- def profile
- RubyProf.resume
- yield
- ensure
- RubyProf.pause
- end
-
- protected
- remove_method :with_gc_stats
- def with_gc_stats
- GC::Profiler.enable
- GC.start
- yield
- ensure
- GC::Profiler.disable
- end
- end
-
- class ProcessTime < Time
- Mode = RubyProf::PROCESS_TIME if RubyProf.const_defined?(:PROCESS_TIME)
-
- def measure
- RubyProf.measure_process_time
- end
- end
-
- class WallTime < Time
- Mode = RubyProf::WALL_TIME if RubyProf.const_defined?(:WALL_TIME)
-
- def measure
- RubyProf.measure_wall_time
- end
- end
-
- class CpuTime < Time
- Mode = RubyProf::CPU_TIME if RubyProf.const_defined?(:CPU_TIME)
-
- def initialize(*args)
- # FIXME: yeah my CPU is 2.33 GHz
- RubyProf.cpu_frequency = 2.33e9 unless RubyProf.cpu_frequency > 0
- super
- end
-
- def measure
- RubyProf.measure_cpu_time
- end
- end
-
- class Memory < DigitalInformationUnit
- Mode = RubyProf::MEMORY if RubyProf.const_defined?(:MEMORY)
-
- # Ruby 1.9 + GCdata patch
- if GC.respond_to?(:malloc_allocated_size)
- def measure
- GC.malloc_allocated_size
- end
- end
- end
-
- class Objects < Amount
- Mode = RubyProf::ALLOCATIONS if RubyProf.const_defined?(:ALLOCATIONS)
-
- # Ruby 1.9 + GCdata patch
- if GC.respond_to?(:malloc_allocations)
- def measure
- GC.malloc_allocations
- end
- end
- end
-
- class GcRuns < Amount
- Mode = RubyProf::GC_RUNS if RubyProf.const_defined?(:GC_RUNS)
-
- def measure
- GC.count
- end
- end
-
- class GcTime < Time
- Mode = RubyProf::GC_TIME if RubyProf.const_defined?(:GC_TIME)
-
- def measure
- GC::Profiler.total_time
- end
- end
- end
- end
- end
-end
diff --git a/activesupport/lib/active_support/testing/tagged_logging.rb b/activesupport/lib/active_support/testing/tagged_logging.rb
index 8ea2605733..9d43eb179f 100644
--- a/activesupport/lib/active_support/testing/tagged_logging.rb
+++ b/activesupport/lib/active_support/testing/tagged_logging.rb
@@ -1,26 +1,25 @@
module ActiveSupport
module Testing
- module TaggedLogging
+ # Logs a "PostsControllerTest: test name" heading before each test to
+ # make test.log easier to search and follow along with.
+ module TaggedLogging #:nodoc:
attr_writer :tagged_logger
def before_setup
- tagged_logger.push_tags(self.class.name, __name__) if tagged_logging?
- super
- end
-
- def after_teardown
+ if tagged_logger
+ heading = "#{self.class}: #{__name__}"
+ divider = '-' * heading.size
+ tagged_logger.info divider
+ tagged_logger.info heading
+ tagged_logger.info divider
+ end
super
- tagged_logger.pop_tags(2) if tagged_logging?
end
private
def tagged_logger
@tagged_logger ||= (defined?(Rails.logger) && Rails.logger)
end
-
- def tagged_logging?
- tagged_logger && tagged_logger.respond_to?(:push_tags)
- end
end
end
end
diff --git a/activesupport/lib/active_support/time_with_zone.rb b/activesupport/lib/active_support/time_with_zone.rb
index 0dbc198ea2..d3741845d2 100644
--- a/activesupport/lib/active_support/time_with_zone.rb
+++ b/activesupport/lib/active_support/time_with_zone.rb
@@ -80,22 +80,43 @@ module ActiveSupport
end
alias_method :getlocal, :localtime
+ # Returns true if the current time is within Daylight Savings Time for the
+ # specified time zone.
+ #
+ # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
+ # Time.zone.parse("2012-5-30").dst? # => true
+ # Time.zone.parse("2012-11-30").dst? # => false
def dst?
period.dst?
end
alias_method :isdst, :dst?
+ # Returns true if the current time zone is set to UTC.
+ #
+ # Time.zone = 'UTC' # => 'UTC'
+ # Time.zone.now.utc? # => true
+ # Time.zone = 'Eastern Time (US & Canada)' # => 'Eastern Time (US & Canada)'
+ # Time.zone.now.utc? # => false
def utc?
time_zone.name == 'UTC'
end
alias_method :gmt?, :utc?
+ # Returns the offset from current time to UTC time in seconds.
def utc_offset
period.utc_total_offset
end
alias_method :gmt_offset, :utc_offset
alias_method :gmtoff, :utc_offset
+ # Returns a formatted string of the offset from UTC, or an alternative
+ # string if the time zone is already UTC.
+ #
+ # Time.zone = 'Eastern Time (US & Canada)' # => "Eastern Time (US & Canada)"
+ # Time.zone.now.formatted_offset(true) # => "-05:00"
+ # Time.zone.now.formatted_offset(false) # => "-0500"
+ # Time.zone = 'UTC' # => "UTC"
+ # Time.zone.now.formatted_offset(true, "0") # => "0"
def formatted_offset(colon = true, alternate_utc_string = nil)
utc? && alternate_utc_string || TimeZone.seconds_to_utc_offset(utc_offset, colon)
end
@@ -147,10 +168,18 @@ module ActiveSupport
end
end
+ # Returns a string of the object's date and time in the format used by
+ # HTTP requests.
+ #
+ # Time.zone.now.httpdate # => "Tue, 01 Jan 2013 04:39:43 GMT"
def httpdate
utc.httpdate
end
+ # Returns a string of the object's date and time in the RFC 2822 standard
+ # format.
+ #
+ # Time.zone.now.rfc2822 # => "Tue, 01 Jan 2013 04:51:39 +0000"
def rfc2822
to_s(:rfc822)
end
@@ -185,18 +214,24 @@ module ActiveSupport
utc <=> other
end
+ # Returns true if the current object's time is within the specified
+ # +min+ and +max+ time.
def between?(min, max)
utc.between?(min, max)
end
+ # Returns true if the current object's time is in the past.
def past?
utc.past?
end
+ # Returns true if the current object's time falls within
+ # the current day.
def today?
time.today?
end
+ # Returns true if the current object's time is in the future.
def future?
utc.future?
end
diff --git a/activesupport/test/abstract_unit.rb b/activesupport/test/abstract_unit.rb
index 8a67b148c3..90e50f235b 100644
--- a/activesupport/test/abstract_unit.rb
+++ b/activesupport/test/abstract_unit.rb
@@ -15,7 +15,7 @@ silence_warnings do
Encoding.default_external = "UTF-8"
end
-require 'minitest/autorun'
+require 'active_support/testing/autorun'
require 'empty_bool'
ENV['NO_RELOAD'] = '1'
diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb
index a2e2c51283..5158bbc196 100644
--- a/activesupport/test/caching_test.rb
+++ b/activesupport/test/caching_test.rb
@@ -675,7 +675,7 @@ class FileStoreTest < ActiveSupport::TestCase
def test_log_exception_when_cache_read_fails
File.expects(:exist?).raises(StandardError, "failed")
@cache.send(:read_entry, "winston", {})
- assert_present @buffer.string
+ assert @buffer.string.present?
end
end
@@ -897,12 +897,12 @@ class CacheStoreLoggerTest < ActiveSupport::TestCase
def test_logging
@cache.fetch('foo') { 'bar' }
- assert_present @buffer.string
+ assert @buffer.string.present?
end
def test_mute_logging
@cache.mute { @cache.fetch('foo') { 'bar' } }
- assert_blank @buffer.string
+ assert @buffer.string.blank?
end
end
diff --git a/activesupport/test/core_ext/date_ext_test.rb b/activesupport/test/core_ext/date_ext_test.rb
index 5e89a6e00b..ec47d0632c 100644
--- a/activesupport/test/core_ext/date_ext_test.rb
+++ b/activesupport/test/core_ext/date_ext_test.rb
@@ -353,6 +353,11 @@ class DateExtBehaviorTest < ActiveSupport::TestCase
Date.today.freeze.freeze
end
end
+
+ def test_compare_with_infinity
+ assert_equal(-1, Date.today <=> Float::INFINITY)
+ assert_equal(1, Date.today <=> -Float::INFINITY)
+ end
end
class DateExtConversionsTest < ActiveSupport::TestCase
diff --git a/activesupport/test/core_ext/date_time_ext_test.rb b/activesupport/test/core_ext/date_time_ext_test.rb
index dfad3a90f8..54bbdbb18f 100644
--- a/activesupport/test/core_ext/date_time_ext_test.rb
+++ b/activesupport/test/core_ext/date_time_ext_test.rb
@@ -317,3 +317,10 @@ class DateTimeExtCalculationsTest < ActiveSupport::TestCase
old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ')
end
end
+
+class DateTimeExtBehaviorTest < ActiveSupport::TestCase
+ def test_compare_with_infinity
+ assert_equal(-1, DateTime.now <=> Float::INFINITY)
+ assert_equal(1, DateTime.now <=> -Float::INFINITY)
+ end
+end
diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb
index 2826f51f2d..5e3987265b 100644
--- a/activesupport/test/core_ext/duration_test.rb
+++ b/activesupport/test/core_ext/duration_test.rb
@@ -50,14 +50,12 @@ class DurationTest < ActiveSupport::TestCase
end
def test_argument_error
- begin
- 1.second.ago('')
- flunk("no exception was raised")
- rescue ArgumentError => e
- assert_equal 'expected a time or date, got ""', e.message, "ensure ArgumentError is not being raised by dependencies.rb"
- rescue Exception => e
- flunk("ArgumentError should be raised, but we got #{e.class} instead")
- end
+ 1.second.ago('')
+ flunk("no exception was raised")
+ rescue ArgumentError => e
+ assert_equal 'expected a time or date, got ""', e.message, "ensure ArgumentError is not being raised by dependencies.rb"
+ rescue Exception => e
+ flunk("ArgumentError should be raised, but we got #{e.class} instead")
end
def test_fractional_weeks
diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb
index 5fc81ba6fc..30d95b75bc 100644
--- a/activesupport/test/core_ext/hash_ext_test.rb
+++ b/activesupport/test/core_ext/hash_ext_test.rb
@@ -8,7 +8,7 @@ require 'active_support/core_ext/object/deep_dup'
require 'active_support/inflections'
class HashExtTest < ActiveSupport::TestCase
- class IndifferentHash < HashWithIndifferentAccess
+ class IndifferentHash < ActiveSupport::HashWithIndifferentAccess
end
class SubclassingArray < Array
@@ -1015,12 +1015,10 @@ class HashToXmlTest < ActiveSupport::TestCase
<replies-close-in type="integer">2592000000</replies-close-in>
<written-on type="date">2003-07-16</written-on>
<viewed-at type="datetime">2003-07-16T09:28:00+0000</viewed-at>
- <content type="yaml">--- \n1: should be an integer\n:message: Have a nice day\narray: \n- should-have-dashes: true\n should_have_underscores: true\n</content>
<author-email-address>david@loudthinking.com</author-email-address>
<parent-id></parent-id>
<ad-revenue type="decimal">1.5</ad-revenue>
<optimum-viewing-angle type="float">135</optimum-viewing-angle>
- <resident type="symbol">yes</resident>
</topic>
EOT
@@ -1033,12 +1031,10 @@ class HashToXmlTest < ActiveSupport::TestCase
:replies_close_in => 2592000000,
:written_on => Date.new(2003, 7, 16),
:viewed_at => Time.utc(2003, 7, 16, 9, 28),
- :content => { :message => "Have a nice day", 1 => "should be an integer", "array" => [{ "should-have-dashes" => true, "should_have_underscores" => true }] },
:author_email_address => "david@loudthinking.com",
:parent_id => nil,
:ad_revenue => BigDecimal("1.50"),
:optimum_viewing_angle => 135.0,
- :resident => :yes
}.stringify_keys
assert_equal expected_topic_hash, Hash.from_xml(topic_xml)["topic"]
@@ -1052,7 +1048,6 @@ class HashToXmlTest < ActiveSupport::TestCase
<approved type="boolean"></approved>
<written-on type="date"></written-on>
<viewed-at type="datetime"></viewed-at>
- <content type="yaml"></content>
<parent-id></parent-id>
</topic>
EOT
@@ -1063,7 +1058,6 @@ class HashToXmlTest < ActiveSupport::TestCase
:approved => nil,
:written_on => nil,
:viewed_at => nil,
- :content => nil,
:parent_id => nil
}.stringify_keys
@@ -1290,6 +1284,28 @@ class HashToXmlTest < ActiveSupport::TestCase
assert_equal expected_product_hash, Hash.from_xml(product_xml)["product"]
end
+ def test_from_xml_raises_on_disallowed_type_attributes
+ assert_raise ActiveSupport::XMLConverter::DisallowedType do
+ Hash.from_xml '<product><name type="foo">value</name></product>', %w(foo)
+ end
+ end
+
+ def test_from_xml_disallows_symbol_and_yaml_types_by_default
+ assert_raise ActiveSupport::XMLConverter::DisallowedType do
+ Hash.from_xml '<product><name type="symbol">value</name></product>'
+ end
+
+ assert_raise ActiveSupport::XMLConverter::DisallowedType do
+ Hash.from_xml '<product><name type="yaml">value</name></product>'
+ end
+ end
+
+ def test_from_trusted_xml_allows_symbol_and_yaml_types
+ expected = { 'product' => { 'name' => :value }}
+ assert_equal expected, Hash.from_trusted_xml('<product><name type="symbol">value</name></product>')
+ assert_equal expected, Hash.from_trusted_xml('<product><name type="yaml">:value</name></product>')
+ end
+
def test_should_use_default_value_for_unknown_key
hash_wia = HashWithIndifferentAccess.new(3)
assert_equal 3, hash_wia[:new_key]
diff --git a/activesupport/test/core_ext/numeric_ext_test.rb b/activesupport/test/core_ext/numeric_ext_test.rb
index 435f4aa5a1..8c7d00cae1 100644
--- a/activesupport/test/core_ext/numeric_ext_test.rb
+++ b/activesupport/test/core_ext/numeric_ext_test.rb
@@ -203,7 +203,7 @@ class NumericExtFormattingTest < ActiveSupport::TestCase
def terabytes(number)
gigabytes(number) * 1024
end
-
+
def test_to_s__phone
assert_equal("555-1234", 5551234.to_s(:phone))
assert_equal("800-555-1212", 8005551212.to_s(:phone))
@@ -217,7 +217,7 @@ class NumericExtFormattingTest < ActiveSupport::TestCase
assert_equal("22-555-1212", 225551212.to_s(:phone))
assert_equal("+45-22-555-1212", 225551212.to_s(:phone, :country_code => 45))
end
-
+
def test_to_s__currency
assert_equal("$1,234,567,890.50", 1234567890.50.to_s(:currency))
assert_equal("$1,234,567,890.51", 1234567890.506.to_s(:currency))
@@ -228,8 +228,8 @@ class NumericExtFormattingTest < ActiveSupport::TestCase
assert_equal("$1,234,567,890.5", 1234567890.50.to_s(:currency, :precision => 1))
assert_equal("&pound;1234567890,50", 1234567890.50.to_s(:currency, :unit => "&pound;", :separator => ",", :delimiter => ""))
end
-
-
+
+
def test_to_s__rounded
assert_equal("-111.235", -111.2346.to_s(:rounded))
assert_equal("111.235", 111.2346.to_s(:rounded))
@@ -246,7 +246,7 @@ class NumericExtFormattingTest < ActiveSupport::TestCase
assert_equal("11.00", 10.995.to_s(:rounded, :precision => 2))
assert_equal("0.00", -0.001.to_s(:rounded, :precision => 2))
end
-
+
def test_to_s__percentage
assert_equal("100.000%", 100.to_s(:percentage))
assert_equal("100%", 100.to_s(:percentage, :precision => 0))
@@ -274,7 +274,7 @@ class NumericExtFormattingTest < ActiveSupport::TestCase
assert_equal '12.345.678,05', 12345678.05.to_s(:delimited, :separator => ',', :delimiter => '.')
assert_equal '12.345.678,05', 12345678.05.to_s(:delimited, :delimiter => '.', :separator => ',')
end
-
+
def test_to_s__rounded_with_custom_delimiter_and_separator
assert_equal '31,83', 31.825.to_s(:rounded, :precision => 2, :separator => ',')
@@ -350,7 +350,7 @@ class NumericExtFormattingTest < ActiveSupport::TestCase
assert_equal '1.23 GB', 1234567890.to_s(:human_size, :prefix => :si)
assert_equal '1.23 TB', 1234567890123.to_s(:human_size, :prefix => :si)
end
-
+
def test_to_s__human_size_with_options_hash
assert_equal '1.2 MB', 1234567.to_s(:human_size, :precision => 2)
assert_equal '3 Bytes', 3.14159265.to_s(:human_size, :precision => 4)
@@ -366,13 +366,13 @@ class NumericExtFormattingTest < ActiveSupport::TestCase
assert_equal '1.012 KB', kilobytes(1.0123).to_s(:human_size, :precision => 3, :significant => false)
assert_equal '1 KB', kilobytes(1.0123).to_s(:human_size, :precision => 0, :significant => true) #ignores significant it precision is 0
end
-
+
def test_to_s__human_size_with_custom_delimiter_and_separator
assert_equal '1,01 KB', kilobytes(1.0123).to_s(:human_size, :precision => 3, :separator => ',')
assert_equal '1,01 KB', kilobytes(1.0100).to_s(:human_size, :precision => 4, :separator => ',')
assert_equal '1.000,1 TB', terabytes(1000.1).to_s(:human_size, :precision => 5, :delimiter => '.', :separator => ',')
end
-
+
def test_number_to_human
assert_equal '-123', -123.to_s(:human)
assert_equal '-0.5', -0.5.to_s(:human)
@@ -436,7 +436,7 @@ class NumericExtFormattingTest < ActiveSupport::TestCase
def test_to_s__injected_on_proper_types
assert_equal Fixnum, 1230.class
assert_equal '1.23 Thousand', 1230.to_s(:human)
-
+
assert_equal Float, Float(1230).class
assert_equal '1.23 Thousand', Float(1230).to_s(:human)
@@ -447,3 +447,57 @@ class NumericExtFormattingTest < ActiveSupport::TestCase
assert_equal '1 Million', BigDecimal("1000010").to_s(:human)
end
end
+
+class NumericExtBehaviorTest < ActiveSupport::TestCase
+ def setup
+ @inf = BigDecimal.new('Infinity')
+ end
+
+ def test_compare_infinity_with_date
+ assert_equal(-1, -Float::INFINITY <=> Date.today)
+ assert_equal(1, Float::INFINITY <=> Date.today)
+ assert_equal(-1, -@inf <=> Date.today)
+ assert_equal(1, @inf <=> Date.today)
+ end
+
+ def test_compare_infinty_with_infinty
+ assert_equal(-1, -Float::INFINITY <=> Float::INFINITY)
+ assert_equal(1, Float::INFINITY <=> -Float::INFINITY)
+ assert_equal(0, Float::INFINITY <=> Float::INFINITY)
+ assert_equal(0, -Float::INFINITY <=> -Float::INFINITY)
+
+ assert_equal(-1, -Float::INFINITY <=> BigDecimal::INFINITY)
+ assert_equal(1, Float::INFINITY <=> -BigDecimal::INFINITY)
+ assert_equal(0, Float::INFINITY <=> BigDecimal::INFINITY)
+ assert_equal(0, -Float::INFINITY <=> -BigDecimal::INFINITY)
+
+ assert_equal(-1, -BigDecimal::INFINITY <=> Float::INFINITY)
+ assert_equal(1, BigDecimal::INFINITY <=> -Float::INFINITY)
+ assert_equal(0, BigDecimal::INFINITY <=> Float::INFINITY)
+ assert_equal(0, -BigDecimal::INFINITY <=> -Float::INFINITY)
+ end
+
+ def test_compare_infinity_with_time
+ assert_equal(-1, -Float::INFINITY <=> Time.now)
+ assert_equal(1, Float::INFINITY <=> Time.now)
+ assert_equal(-1, -@inf <=> Time.now)
+ assert_equal(1, @inf <=> Time.now)
+ end
+
+ def test_compare_infinity_with_datetime
+ assert_equal(-1, -Float::INFINITY <=> DateTime.now)
+ assert_equal(1, Float::INFINITY <=> DateTime.now)
+ assert_equal(-1, -@inf <=> DateTime.now)
+ assert_equal(1, @inf <=> DateTime.now)
+ end
+
+ def test_compare_infinity_with_twz
+ time_zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
+ twz = ActiveSupport::TimeWithZone.new(Time.now, time_zone)
+
+ assert_equal(-1, -Float::INFINITY <=> twz)
+ assert_equal(1, Float::INFINITY <=> twz)
+ assert_equal(-1, -@inf <=> twz)
+ assert_equal(1, @inf <=> twz)
+ end
+end
diff --git a/activesupport/test/core_ext/range_ext_test.rb b/activesupport/test/core_ext/range_ext_test.rb
index f0cdc0bfd4..0051c48984 100644
--- a/activesupport/test/core_ext/range_ext_test.rb
+++ b/activesupport/test/core_ext/range_ext_test.rb
@@ -1,6 +1,7 @@
require 'abstract_unit'
require 'active_support/time'
require 'active_support/core_ext/range'
+require 'active_support/core_ext/numeric'
class RangeTest < ActiveSupport::TestCase
def test_to_s_from_dates
@@ -85,4 +86,28 @@ class RangeTest < ActiveSupport::TestCase
time_range_2 = Time.utc(2005, 12, 10, 17, 31)..Time.utc(2005, 12, 10, 18, 00)
assert !time_range_1.overlaps?(time_range_2)
end
+
+ def test_infinite_bounds
+ time_zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
+
+ time = Time.now
+ date = Date.today
+ datetime = DateTime.now
+ twz = ActiveSupport::TimeWithZone.new(time, time_zone)
+
+ infinity1 = Float::INFINITY
+ infinity2 = BigDecimal.new('Infinity')
+
+ [infinity1, infinity2].each do |infinity|
+ [time, date, datetime, twz].each do |bound|
+ [time, date, datetime, twz].each do |value|
+ assert Range.new(bound, infinity).include?(value + 10.years)
+ assert Range.new(-infinity, bound).include?(value - 10.years)
+
+ assert !Range.new(bound, infinity).include?(value - 10.years)
+ assert !Range.new(-infinity, bound).include?(value + 10.years)
+ end
+ end
+ end
+ end
end
diff --git a/activesupport/test/core_ext/string_ext_test.rb b/activesupport/test/core_ext/string_ext_test.rb
index fa8839bcb3..e0ddeab548 100644
--- a/activesupport/test/core_ext/string_ext_test.rb
+++ b/activesupport/test/core_ext/string_ext_test.rb
@@ -307,6 +307,7 @@ class StringConversionsTest < ActiveSupport::TestCase
def test_string_to_date
assert_equal Date.new(2005, 2, 27), "2005-02-27".to_date
assert_nil "".to_date
+ assert_equal Date.new(Date.today.year, 2, 3), "Feb 3rd".to_date
end
end
diff --git a/activesupport/test/core_ext/thread_test.rb b/activesupport/test/core_ext/thread_test.rb
index b58f59a8d4..230c1203ad 100644
--- a/activesupport/test/core_ext/thread_test.rb
+++ b/activesupport/test/core_ext/thread_test.rb
@@ -39,14 +39,14 @@ class ThreadExt < ActiveSupport::TestCase
end
def test_thread_variable?
- refute Thread.new { Thread.current.thread_variable?("foo") }.join.value
+ assert_not Thread.new { Thread.current.thread_variable?("foo") }.join.value
t = Thread.new {
Thread.current.thread_variable_set("foo", "bar")
}.join
assert t.thread_variable?("foo")
assert t.thread_variable?(:foo)
- refute t.thread_variable?(:bar)
+ assert_not t.thread_variable?(:bar)
end
def test_thread_variable_strings_and_symbols_are_the_same_key
diff --git a/activesupport/test/core_ext/time_ext_test.rb b/activesupport/test/core_ext/time_ext_test.rb
index 70e07cefd1..a2fefee3b8 100644
--- a/activesupport/test/core_ext/time_ext_test.rb
+++ b/activesupport/test/core_ext/time_ext_test.rb
@@ -843,3 +843,10 @@ class TimeExtMarshalingTest < ActiveSupport::TestCase
assert_equal Time.local(2004, 2, 29), Time.local(2004, 5, 31).last_quarter
end
end
+
+class TimeExtBehaviorTest < ActiveSupport::TestCase
+ def test_compare_with_infinity
+ assert_equal(-1, Time.now <=> Float::INFINITY)
+ assert_equal(1, Time.now <=> -Float::INFINITY)
+ end
+end
diff --git a/activesupport/test/core_ext/time_with_zone_test.rb b/activesupport/test/core_ext/time_with_zone_test.rb
index 56020da035..6c773770f0 100644
--- a/activesupport/test/core_ext/time_with_zone_test.rb
+++ b/activesupport/test/core_ext/time_with_zone_test.rb
@@ -1081,3 +1081,13 @@ class TimeWithZoneMethodsForString < ActiveSupport::TestCase
Time.zone = old_tz
end
end
+
+class TimeWithZoneExtBehaviorTest < ActiveSupport::TestCase
+ def test_compare_with_infinity
+ time_zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)']
+ twz = ActiveSupport::TimeWithZone.new(Time.now, time_zone)
+
+ assert_equal(-1, twz <=> Float::INFINITY)
+ assert_equal(1, twz <=> -Float::INFINITY)
+ end
+end
diff --git a/activesupport/test/dependencies_test.rb b/activesupport/test/dependencies_test.rb
index 9d913c27b0..615808090d 100644
--- a/activesupport/test/dependencies_test.rb
+++ b/activesupport/test/dependencies_test.rb
@@ -363,12 +363,10 @@ class DependenciesTest < ActiveSupport::TestCase
end
def test_smart_name_error_strings
- begin
- Object.module_eval "ImaginaryObject"
- flunk "No raise!!"
- rescue NameError => e
- assert e.message.include?("uninitialized constant ImaginaryObject")
- end
+ Object.module_eval "ImaginaryObject"
+ flunk "No raise!!"
+ rescue NameError => e
+ assert e.message.include?("uninitialized constant ImaginaryObject")
end
def test_loadable_constants_for_path_should_handle_empty_autoloads
diff --git a/activesupport/test/deprecation_test.rb b/activesupport/test/deprecation_test.rb
index 332100f5a1..c1a468ec86 100644
--- a/activesupport/test/deprecation_test.rb
+++ b/activesupport/test/deprecation_test.rb
@@ -119,9 +119,10 @@ class DeprecationTest < ActiveSupport::TestCase
ActiveSupport::Deprecation.behavior = :silence
behavior = ActiveSupport::Deprecation.behavior.first
- assert_blank capture(:stderr) {
+ stderr_output = capture(:stderr) {
assert_nil behavior.call('Some error!', ['call stack!'])
}
+ assert stderr_output.blank?
end
def test_deprecated_instance_variable_proxy
@@ -254,10 +255,10 @@ class DeprecationTest < ActiveSupport::TestCase
klass::OLD.to_s
end
end
-
+
def test_deprecated_instance_variable_with_instance_deprecator
deprecator = deprecator_with_messages
-
+
klass = Class.new() do
def initialize(deprecator)
@request = ActiveSupport::Deprecation::DeprecatedInstanceVariableProxy.new(self, :request, :@request, deprecator)
diff --git a/activesupport/test/inflector_test.rb b/activesupport/test/inflector_test.rb
index aa41e57928..a1e5db6a2e 100644
--- a/activesupport/test/inflector_test.rb
+++ b/activesupport/test/inflector_test.rb
@@ -361,7 +361,7 @@ class InflectorTest < ActiveSupport::TestCase
inflect.singular(/s$/, '')
inflect.singular(/es$/, '')
-
+
inflect.irregular('el', 'los')
end
diff --git a/activesupport/test/json/encoding_test.rb b/activesupport/test/json/encoding_test.rb
index b6e2cd4529..12ce250eb3 100644
--- a/activesupport/test/json/encoding_test.rb
+++ b/activesupport/test/json/encoding_test.rb
@@ -276,7 +276,8 @@ class TestJSONEncoding < ActiveSupport::TestCase
f.bar = "world"
hash = {"foo" => f, "other_hash" => {"foo" => "other_foo", "test" => "other_test"}}
- assert_equal(%({"foo":{"foo":"hello","bar":"world"},"other_hash":{"foo":"other_foo","test":"other_test"}}), hash.to_json)
+ assert_equal({"foo"=>{"foo"=>"hello","bar"=>"world"},
+ "other_hash" => {"foo"=>"other_foo","test"=>"other_test"}}, JSON.parse(hash.to_json))
end
def test_struct_encoding
diff --git a/activesupport/test/message_encryptor_test.rb b/activesupport/test/message_encryptor_test.rb
index d6c31396b6..06c7e8a1a7 100644
--- a/activesupport/test/message_encryptor_test.rb
+++ b/activesupport/test/message_encryptor_test.rb
@@ -29,9 +29,9 @@ class MessageEncryptorTest < ActiveSupport::TestCase
end
def test_encrypting_twice_yields_differing_cipher_text
- first_messqage = @encryptor.encrypt_and_sign(@data).split("--").first
+ first_message = @encryptor.encrypt_and_sign(@data).split("--").first
second_message = @encryptor.encrypt_and_sign(@data).split("--").first
- assert_not_equal first_messqage, second_message
+ assert_not_equal first_message, second_message
end
def test_messing_with_either_encrypted_values_causes_failure
diff --git a/activesupport/test/notifications/instrumenter_test.rb b/activesupport/test/notifications/instrumenter_test.rb
new file mode 100644
index 0000000000..62a9b61464
--- /dev/null
+++ b/activesupport/test/notifications/instrumenter_test.rb
@@ -0,0 +1,50 @@
+require 'abstract_unit'
+require 'active_support/notifications/instrumenter'
+
+module ActiveSupport
+ module Notifications
+ class InstrumenterTest < ActiveSupport::TestCase
+ class TestNotifier
+ attr_reader :starts, :finishes
+
+ def initialize
+ @starts = []
+ @finishes = []
+ end
+
+ def start(*args); @starts << args; end
+ def finish(*args); @finishes << args; end
+ end
+
+ attr_reader :instrumenter, :notifier, :payload
+
+ def setup
+ super
+ @notifier = TestNotifier.new
+ @instrumenter = Instrumenter.new @notifier
+ @payload = { :foo => Object.new }
+ end
+
+ def test_instrument
+ called = false
+ instrumenter.instrument("foo", payload) {
+ called = true
+ }
+
+ assert called
+ end
+
+ def test_start
+ instrumenter.start("foo", payload)
+ assert_equal [["foo", instrumenter.id, payload]], notifier.starts
+ assert_predicate notifier.finishes, :empty?
+ end
+
+ def test_finish
+ instrumenter.finish("foo", payload)
+ assert_equal [["foo", instrumenter.id, payload]], notifier.finishes
+ assert_predicate notifier.starts, :empty?
+ end
+ end
+ end
+end
diff --git a/activesupport/test/spec_type_test.rb b/activesupport/test/spec_type_test.rb
deleted file mode 100644
index 9a6cb4ded2..0000000000
--- a/activesupport/test/spec_type_test.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-require "abstract_unit"
-require "active_record"
-
-class SomeRandomModel < ActiveRecord::Base; end
-
-class SpecTypeTest < ActiveSupport::TestCase
- def assert_support actual
- assert_equal ActiveSupport::TestCase, actual
- end
-
- def assert_spec actual
- assert_equal MiniTest::Spec, actual
- end
-
- def test_spec_type_resolves_for_active_record_constants
- assert_support MiniTest::Spec.spec_type(SomeRandomModel)
- end
-
- def test_spec_type_doesnt_resolve_random_strings
- assert_spec MiniTest::Spec.spec_type("Unmatched String")
- end
-end
diff --git a/activesupport/test/string_inquirer_test.rb b/activesupport/test/string_inquirer_test.rb
index 94d5fe197d..a2ed577eb0 100644
--- a/activesupport/test/string_inquirer_test.rb
+++ b/activesupport/test/string_inquirer_test.rb
@@ -10,7 +10,7 @@ class StringInquirerTest < ActiveSupport::TestCase
end
def test_miss
- refute @string_inquirer.development?
+ assert_not @string_inquirer.development?
end
def test_missing_question_mark
diff --git a/activesupport/test/test_test.rb b/activesupport/test/test_test.rb
index d6821135ea..3e6ac811a4 100644
--- a/activesupport/test/test_test.rb
+++ b/activesupport/test/test_test.rb
@@ -15,6 +15,17 @@ class AssertDifferenceTest < ActiveSupport::TestCase
@object.num = 0
end
+ def test_assert_not
+ assert_equal true, assert_not(nil)
+ assert_equal true, assert_not(false)
+
+ e = assert_raises(MiniTest::Assertion) { assert_not true }
+ assert_equal 'Expected true to be nil or false', e.message
+
+ e = assert_raises(MiniTest::Assertion) { assert_not true, 'custom' }
+ assert_equal 'custom', e.message
+ end
+
def test_assert_no_difference
assert_no_difference '@object.num' do
# ...
@@ -81,17 +92,21 @@ class AssertBlankTest < ActiveSupport::TestCase
NOT_BLANK = [ EmptyFalse.new, Object.new, true, 0, 1, 'x', [nil], { nil => 0 } ]
def test_assert_blank_true
- BLANK.each { |v| assert_blank v }
+ BLANK.each { |value|
+ assert_deprecated { assert_blank value }
+ }
end
def test_assert_blank_false
NOT_BLANK.each { |v|
- begin
- assert_blank v
- fail 'should not get to here'
- rescue Exception => e
- assert_match(/is not blank/, e.message)
- end
+ assert_deprecated {
+ begin
+ assert_blank v
+ fail 'should not get to here'
+ rescue Exception => e
+ assert_match(/is not blank/, e.message)
+ end
+ }
}
end
end
@@ -101,17 +116,21 @@ class AssertPresentTest < ActiveSupport::TestCase
NOT_BLANK = [ EmptyFalse.new, Object.new, true, 0, 1, 'x', [nil], { nil => 0 } ]
def test_assert_present_true
- NOT_BLANK.each { |v| assert_present v }
+ NOT_BLANK.each { |v|
+ assert_deprecated { assert_present v }
+ }
end
def test_assert_present_false
BLANK.each { |v|
- begin
- assert_present v
- fail 'should not get to here'
- rescue Exception => e
- assert_match(/is blank/, e.message)
- end
+ assert_deprecated {
+ begin
+ assert_present v
+ fail 'should not get to here'
+ rescue Exception => e
+ assert_match(/is blank/, e.message)
+ end
+ }
}
end
end
@@ -182,7 +201,6 @@ class TestCaseTaggedLoggingTest < ActiveSupport::TestCase
end
def test_logs_tagged_with_current_test_case
- tagged_logger.info 'test'
- assert_equal "[#{self.class.name}] [#{__name__}] test\n", @out.string
+ assert_match "#{self.class}: #{__name__}\n", @out.string
end
end
diff --git a/activesupport/test/testing/performance_test.rb b/activesupport/test/testing/performance_test.rb
deleted file mode 100644
index 6918110cce..0000000000
--- a/activesupport/test/testing/performance_test.rb
+++ /dev/null
@@ -1,68 +0,0 @@
-require 'abstract_unit'
-
-module ActiveSupport
- module Testing
- class PerformanceTest < ActiveSupport::TestCase
- begin
- require 'active_support/testing/performance'
- HAVE_RUBYPROF = true
- rescue LoadError
- HAVE_RUBYPROF = false
- end
-
- def setup
- skip "no rubyprof" unless HAVE_RUBYPROF
- end
-
- def test_amount_format
- amount_metric = ActiveSupport::Testing::Performance::Metrics[:amount].new
- assert_equal "0", amount_metric.format(0)
- assert_equal "1", amount_metric.format(1.23)
- assert_equal "40,000,000", amount_metric.format(40000000)
- end
-
- def test_time_format
- time_metric = ActiveSupport::Testing::Performance::Metrics[:time].new
- assert_equal "0 ms", time_metric.format(0)
- assert_equal "40 ms", time_metric.format(0.04)
- assert_equal "41 ms", time_metric.format(0.0415)
- assert_equal "1.23 sec", time_metric.format(1.23)
- assert_equal "40000.00 sec", time_metric.format(40000)
- assert_equal "-5000 ms", time_metric.format(-5)
- end
-
- def test_space_format
- space_metric = ActiveSupport::Testing::Performance::Metrics[:digital_information_unit].new
- assert_equal "0 Bytes", space_metric.format(0)
- assert_equal "0 Bytes", space_metric.format(0.4)
- assert_equal "1 Byte", space_metric.format(1.23)
- assert_equal "123 Bytes", space_metric.format(123)
- assert_equal "123 Bytes", space_metric.format(123.45)
- assert_equal "12 KB", space_metric.format(12345)
- assert_equal "1.2 MB", space_metric.format(1234567)
- assert_equal "9.3 GB", space_metric.format(10**10)
- assert_equal "91 TB", space_metric.format(10**14)
- assert_equal "910000 TB", space_metric.format(10**18)
- end
-
- def test_environment_format_without_rails
- metric = ActiveSupport::Testing::Performance::Metrics[:time].new
- benchmarker = ActiveSupport::Testing::Performance::Benchmarker.new(self, metric)
- assert_equal "#{RUBY_ENGINE}-#{RUBY_VERSION}.#{RUBY_PATCHLEVEL},#{RUBY_PLATFORM}", benchmarker.environment
- end
-
- def test_environment_format_with_rails
- rails, version = Module.new, Module.new
- version.const_set :STRING, "4.0.0"
- rails.const_set :VERSION, version
- Object.const_set :Rails, rails
-
- metric = ActiveSupport::Testing::Performance::Metrics[:time].new
- benchmarker = ActiveSupport::Testing::Performance::Benchmarker.new(self, metric)
- assert_equal "rails-4.0.0,#{RUBY_ENGINE}-#{RUBY_VERSION}.#{RUBY_PATCHLEVEL},#{RUBY_PLATFORM}", benchmarker.environment
- ensure
- Object.send :remove_const, :Rails
- end
- end
- end
-end
diff --git a/activesupport/test/ts_isolated.rb b/activesupport/test/ts_isolated.rb
index 2c217157d3..294d6595f7 100644
--- a/activesupport/test/ts_isolated.rb
+++ b/activesupport/test/ts_isolated.rb
@@ -1,4 +1,4 @@
-require 'minitest/autorun'
+require 'active_support/testing/autorun'
require 'active_support/test_case'
require 'rbconfig'
require 'active_support/core_ext/kernel/reporting'
diff --git a/activesupport/test/xml_mini/libxml_engine_test.rb b/activesupport/test/xml_mini/libxml_engine_test.rb
index 5debb2fd59..36ac4161ea 100644
--- a/activesupport/test/xml_mini/libxml_engine_test.rb
+++ b/activesupport/test/xml_mini/libxml_engine_test.rb
@@ -1,12 +1,11 @@
-require 'abstract_unit'
-require 'active_support/xml_mini'
-require 'active_support/core_ext/hash/conversions'
-
begin
require 'libxml'
rescue LoadError
# Skip libxml tests
else
+require 'abstract_unit'
+require 'active_support/xml_mini'
+require 'active_support/core_ext/hash/conversions'
class LibxmlEngineTest < ActiveSupport::TestCase
include ActiveSupport
diff --git a/activesupport/test/xml_mini/libxmlsax_engine_test.rb b/activesupport/test/xml_mini/libxmlsax_engine_test.rb
index 94250d48ec..82337961a1 100644
--- a/activesupport/test/xml_mini/libxmlsax_engine_test.rb
+++ b/activesupport/test/xml_mini/libxmlsax_engine_test.rb
@@ -1,12 +1,11 @@
-require 'abstract_unit'
-require 'active_support/xml_mini'
-require 'active_support/core_ext/hash/conversions'
-
begin
require 'libxml'
rescue LoadError
# Skip libxml tests
else
+require 'abstract_unit'
+require 'active_support/xml_mini'
+require 'active_support/core_ext/hash/conversions'
class LibXMLSAXEngineTest < ActiveSupport::TestCase
include ActiveSupport
diff --git a/activesupport/test/xml_mini/nokogiri_engine_test.rb b/activesupport/test/xml_mini/nokogiri_engine_test.rb
index 3f37c7cbb6..71f57e43d2 100644
--- a/activesupport/test/xml_mini/nokogiri_engine_test.rb
+++ b/activesupport/test/xml_mini/nokogiri_engine_test.rb
@@ -1,12 +1,11 @@
-require 'abstract_unit'
-require 'active_support/xml_mini'
-require 'active_support/core_ext/hash/conversions'
-
begin
require 'nokogiri'
rescue LoadError
# Skip nokogiri tests
else
+require 'abstract_unit'
+require 'active_support/xml_mini'
+require 'active_support/core_ext/hash/conversions'
class NokogiriEngineTest < ActiveSupport::TestCase
include ActiveSupport
diff --git a/activesupport/test/xml_mini/nokogirisax_engine_test.rb b/activesupport/test/xml_mini/nokogirisax_engine_test.rb
index d6ae7f12ae..884494e95e 100644
--- a/activesupport/test/xml_mini/nokogirisax_engine_test.rb
+++ b/activesupport/test/xml_mini/nokogirisax_engine_test.rb
@@ -1,12 +1,11 @@
-require 'abstract_unit'
-require 'active_support/xml_mini'
-require 'active_support/core_ext/hash/conversions'
-
begin
require 'nokogiri'
rescue LoadError
# Skip nokogiri tests
else
+require 'abstract_unit'
+require 'active_support/xml_mini'
+require 'active_support/core_ext/hash/conversions'
class NokogiriSAXEngineTest < ActiveSupport::TestCase
include ActiveSupport
diff --git a/guides/assets/stylesheets/main.css b/guides/assets/stylesheets/main.css
index 589c96e0e9..dd029e6314 100644
--- a/guides/assets/stylesheets/main.css
+++ b/guides/assets/stylesheets/main.css
@@ -83,6 +83,10 @@ table th {
padding: 0.5em 1em;
}
+img {
+ max-width: 100%;
+}
+
/* Structure and Layout
--------------------------------------- */
@@ -573,7 +577,7 @@ h6 {
#mainCol div.warning, #subCol dd.warning {
background: #f9d9d8 url(../images/tab_red.gif) no-repeat left top;
border: none;
- padding: 1.25em 1.25em 1.25em 48px;
+ padding: 1.25em 1.25em 0.25em 48px;
margin-left: 0;
margin-top: 0.25em;
}
diff --git a/guides/code/getting_started/README.rdoc b/guides/code/getting_started/README.rdoc
index b5d7b6436b..232856ca5f 100644
--- a/guides/code/getting_started/README.rdoc
+++ b/guides/code/getting_started/README.rdoc
@@ -1,259 +1,28 @@
-== Welcome to Rails
+== README
-Rails is a web-application framework that includes everything needed to create
-database-backed web applications according to the Model-View-Control pattern.
+This README would normally document whatever steps are necessary to get the
+application up and running.
-This pattern splits the view (also called the presentation) into "dumb"
-templates that are primarily responsible for inserting pre-built data in between
-HTML tags. The model contains the "smart" domain objects (such as Account,
-Product, Person, Post) that holds all the business logic and knows how to
-persist themselves to a database. The controller handles the incoming requests
-(such as Save New Account, Update Product, Show Post) by manipulating the model
-and directing data to the view.
+Things you may want to cover:
-In Rails, the model is handled by what's called an object-relational mapping
-layer entitled Active Record. This layer allows you to present the data from
-database rows as objects and embellish these data objects with business logic
-methods. You can read more about Active Record in
-link:files/vendor/rails/activerecord/README.html.
+* Ruby version
-The controller and view are handled by the Action Pack, which handles both
-layers by its two parts: Action View and Action Controller. These two layers
-are bundled in a single package due to their heavy interdependence. This is
-unlike the relationship between the Active Record and Action Pack that is much
-more separate. Each of these packages can be used independently outside of
-Rails. You can read more about Action Pack in
-link:files/vendor/rails/actionpack/README.html.
+* System dependencies
+* Configuration
-== Getting Started
+* Database creation
-1. At the command prompt, create a new Rails application:
- <tt>rails new myapp</tt> (where <tt>myapp</tt> is the application name)
+* Database initialization
-2. Change directory to <tt>myapp</tt> and start the web server:
- <tt>cd myapp; rails server</tt> (run with --help for options)
+* How to run the test suite
-3. Go to http://localhost:3000/ and you'll see:
- "Welcome aboard: You're riding Ruby on Rails!"
+* Services (job queues, cache servers, search engines, etc.)
-4. Follow the guidelines to start developing your application. You can find
-the following resources handy:
+* Deployment instructions
-* The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html
-* Ruby on Rails Tutorial Book: http://www.railstutorial.org/
+* ...
-
-== Debugging Rails
-
-Sometimes your application goes wrong. Fortunately there are a lot of tools that
-will help you debug it and get it back on the rails.
-
-First area to check is the application log files. Have "tail -f" commands
-running on the server.log and development.log. Rails will automatically display
-debugging and runtime information to these files. Debugging info will also be
-shown in the browser on requests from 127.0.0.1.
-
-You can also log your own messages directly into the log file from your code
-using the Ruby logger class from inside your controllers. Example:
-
- class WeblogController < ActionController::Base
- def destroy
- @weblog = Weblog.find(params[:id])
- @weblog.destroy
- logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!")
- end
- end
-
-The result will be a message in your log file along the lines of:
-
- Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1!
-
-More information on how to use the logger is at http://www.ruby-doc.org/core/
-
-Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are
-several books available online as well:
-
-* Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe)
-* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide)
-
-These two books will bring you up to speed on the Ruby language and also on
-programming in general.
-
-
-== Debugger
-
-Debugger support is available through the debugger command when you start your
-Mongrel or WEBrick server with --debugger. This means that you can break out of
-execution at any point in the code, investigate and change the model, and then,
-resume execution! You need to install the 'debugger' gem to run the server in debugging
-mode. Add gem 'debugger' to your Gemfile and run <tt>bundle</tt> to install it. Example:
-
- class WeblogController < ActionController::Base
- def index
- @posts = Post.all
- debugger
- end
- end
-
-So the controller will accept the action, run the first line, then present you
-with a IRB prompt in the server window. Here you can do things like:
-
- >> @posts.inspect
- => "[#<Post:0x14a6be8
- @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>,
- #<Post:0x14a6620
- @attributes={"title"=>"Rails", "body"=>"Only ten..", "id"=>"2"}>]"
- >> @posts.first.title = "hello from a debugger"
- => "hello from a debugger"
-
-...and even better, you can examine how your runtime objects actually work:
-
- >> f = @posts.first
- => #<Post:0x13630c4 @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>
- >> f.
- Display all 152 possibilities? (y or n)
-
-Finally, when you're ready to resume execution, you can enter "cont".
-
-
-== Console
-
-The console is a Ruby shell, which allows you to interact with your
-application's domain model. Here you'll have all parts of the application
-configured, just like it is when the application is running. You can inspect
-domain models, change values, and save to the database. Starting the script
-without arguments will launch it in the development environment.
-
-To start the console, run <tt>rails console</tt> from the application
-directory.
-
-Options:
-
-* Passing the <tt>-s, --sandbox</tt> argument will rollback any modifications
- made to the database.
-* Passing an environment name as an argument will load the corresponding
- environment. Example: <tt>rails console production</tt>.
-
-To reload your controllers and models after launching the console run
-<tt>reload!</tt>
-
-More information about irb can be found at:
-link:http://www.rubycentral.org/pickaxe/irb.html
-
-
-== dbconsole
-
-You can go to the command line of your database directly through <tt>rails
-dbconsole</tt>. You would be connected to the database with the credentials
-defined in database.yml. Starting the script without arguments will connect you
-to the development database. Passing an argument will connect you to a different
-database, like <tt>rails dbconsole production</tt>. Currently works for MySQL,
-PostgreSQL and SQLite 3.
-
-== Description of Contents
-
-The default directory structure of a generated Ruby on Rails application:
-
- |-- app
- | |-- assets
- | |-- images
- | |-- javascripts
- | `-- stylesheets
- | |-- controllers
- | |-- helpers
- | |-- mailers
- | |-- models
- | `-- views
- | `-- layouts
- |-- config
- | |-- environments
- | |-- initializers
- | `-- locales
- |-- db
- |-- doc
- |-- lib
- | `-- tasks
- |-- log
- |-- public
- |-- script
- |-- test
- | |-- fixtures
- | |-- functional
- | |-- integration
- | |-- performance
- | `-- unit
- |-- tmp
- | |-- cache
- | |-- pids
- | |-- sessions
- | `-- sockets
- `-- vendor
- |-- assets
- `-- stylesheets
-
-app
- Holds all the code that's specific to this particular application.
-
-app/assets
- Contains subdirectories for images, stylesheets, and JavaScript files.
-
-app/controllers
- Holds controllers that should be named like weblogs_controller.rb for
- automated URL mapping. All controllers should descend from
- ApplicationController which itself descends from ActionController::Base.
-
-app/models
- Holds models that should be named like post.rb. Models descend from
- ActiveRecord::Base by default.
-
-app/views
- Holds the template files for the view that should be named like
- weblogs/index.html.erb for the WeblogsController#index action. All views use
- eRuby syntax by default.
-
-app/views/layouts
- Holds the template files for layouts to be used with views. This models the
- common header/footer method of wrapping views. In your views, define a layout
- using the <tt>layout :default</tt> and create a file named default.html.erb.
- Inside default.html.erb, call <% yield %> to render the view using this
- layout.
-
-app/helpers
- Holds view helpers that should be named like weblogs_helper.rb. These are
- generated for you automatically when using generators for controllers.
- Helpers can be used to wrap functionality for your views into methods.
-
-config
- Configuration files for the Rails environment, the routing map, the database,
- and other dependencies.
-
-db
- Contains the database schema in schema.rb. db/migrate contains all the
- sequence of Migrations for your schema.
-
-doc
- This directory is where your application documentation will be stored when
- generated using <tt>rake doc:app</tt>
-
-lib
- Application specific libraries. Basically, any kind of custom code that
- doesn't belong under controllers, models, or helpers. This directory is in
- the load path.
-
-public
- The directory available for the web server. Also contains the dispatchers and the
- default HTML files. This should be set as the DOCUMENT_ROOT of your web
- server.
-
-script
- Helper scripts for automation and generation.
-
-test
- Unit and functional tests along with fixtures. When using the rails generate
- command, template test files will be generated for you and placed in this
- directory.
-
-vendor
- External libraries that the application depends on. If the app has frozen rails,
- those gems also go here, under vendor/rails/. This directory is in the load path.
+If you plan to generate application documentation with `rake doc:app` this file
+is expected to be `README.rdoc`, otherwise please feel free to rename it and use
+a different markup language. \ No newline at end of file
diff --git a/guides/code/getting_started/app/controllers/posts_controller.rb b/guides/code/getting_started/app/controllers/posts_controller.rb
index a8ac9aba5a..b74c66ef13 100644
--- a/guides/code/getting_started/app/controllers/posts_controller.rb
+++ b/guides/code/getting_started/app/controllers/posts_controller.rb
@@ -31,7 +31,7 @@ class PostsController < ApplicationController
def update
@post = Post.find(params[:id])
- if @post.update_attributes(params[:post])
+ if @post.update(params[:post])
redirect_to :action => :show, :id => @post.id
else
render 'edit'
diff --git a/guides/code/getting_started/doc/README_FOR_APP b/guides/code/getting_started/doc/README_FOR_APP
deleted file mode 100644
index fe41f5cc24..0000000000
--- a/guides/code/getting_started/doc/README_FOR_APP
+++ /dev/null
@@ -1,2 +0,0 @@
-Use this README file to introduce your application and point to useful places in the API for learning more.
-Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries.
diff --git a/guides/code/getting_started/test/performance/browsing_test.rb b/guides/code/getting_started/test/performance/browsing_test.rb
deleted file mode 100644
index 9342a57b20..0000000000
--- a/guides/code/getting_started/test/performance/browsing_test.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-require 'test_helper'
-require 'rails/performance_test_help'
-
-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
-end
diff --git a/guides/rails_guides/markdown.rb b/guides/rails_guides/markdown.rb
index 650489e6cb..547c6d2c15 100644
--- a/guides/rails_guides/markdown.rb
+++ b/guides/rails_guides/markdown.rb
@@ -1,3 +1,5 @@
+# encoding: utf-8
+
require 'redcarpet'
require 'nokogiri'
require 'rails_guides/markdown/renderer'
@@ -129,7 +131,7 @@ module RailsGuides
def generate_title
if heading = Nokogiri::HTML(@header).at(:h2)
- @title = "Ruby on Rails Guides: #{heading.text}".html_safe
+ @title = "#{heading.text} — Ruby on Rails Guides".html_safe
else
@title = "Ruby on Rails Guides"
end
diff --git a/guides/source/4_0_release_notes.md b/guides/source/4_0_release_notes.md
index 597ac99be0..52571fab60 100644
--- a/guides/source/4_0_release_notes.md
+++ b/guides/source/4_0_release_notes.md
@@ -68,6 +68,7 @@ In Rails 4.0, several features have been extracted into gems. You can simply add
* Action Caching ([Github](https://github.com/rails/actionpack-action_caching), [Pull Request](https://github.com/rails/rails/pull/7833))
* Page Caching ([Github](https://github.com/rails/actionpack-page_caching), [Pull Request](https://github.com/rails/rails/pull/7833))
* Sprockets ([Github](https://github.com/rails/sprockets-rails))
+* Performance tests ([Github](https://github.com/rails/rails-perftest), [Pull Request](https://github.com/rails/rails/pull/8876))
Documentation
-------------
@@ -85,6 +86,8 @@ Please refer to the [Changelog](https://github.com/rails/rails/blob/master/railt
* New test locations `test/models`, `test/helpers`, `test/controllers`, and `test/mailers`. Corresponding rake tasks added as well. ([Pull Request](https://github.com/rails/rails/pull/7878))
+* Your app's executables now live in the `bin/` dir. Run `rake rails:update:bin` to get `bin/bundle`, `bin/rails`, and `bin/rake`.
+
* Threadsafe on by default
### Deprecations
@@ -142,6 +145,7 @@ Please refer to the [Changelog](https://github.com/rails/rails/blob/master/activ
* BufferedLogger is deprecated. Use ActiveSupport::Logger, or the logger from Ruby stdlib.
+* Deprecate `assert_present` and `assert_blank` in favor of `assert object.blank?` and `assert object.present?`
Action Pack
-----------
@@ -150,6 +154,8 @@ Please refer to the [Changelog](https://github.com/rails/rails/blob/master/railt
### Notable changes
+* Change the stylesheet of exception pages for development mode. Additionally display also the line of code and fragment that raised the exception in all exceptions pages.
+
### Deprecations
diff --git a/guides/source/action_controller_overview.md b/guides/source/action_controller_overview.md
index 46ff9027fd..cc80334af3 100644
--- a/guides/source/action_controller_overview.md
+++ b/guides/source/action_controller_overview.md
@@ -114,7 +114,7 @@ To send a hash you include the key name inside the brackets:
When this form is submitted, the value of `params[:client]` will be `{"name" => "Acme", "phone" => "12345", "address" => {"postcode" => "12345", "city" => "Carrot City"}}`. Note the nested hash in `params[:client][:address]`.
-Note that the `params` hash is actually an instance of `HashWithIndifferentAccess` from Active Support, which acts like a hash that lets you use symbols and strings interchangeably as keys.
+Note that the `params` hash is actually an instance of `ActiveSupport::HashWithIndifferentAccess`, which acts like a hash that lets you use symbols and strings interchangeably as keys.
### JSON/XML parameters
@@ -174,10 +174,10 @@ Session
Your application has a session for each user in which you can store small amounts of data that will be persisted between requests. The session is only available in the controller and the view and can use one of a number of different storage mechanisms:
-* ActionDispatch::Session::CookieStore - Stores everything on the client.
-* ActionDispatch::Session::CacheStore - Stores the data in the Rails cache.
-* @ActionDispatch::Session::ActiveRecordStore@ - Stores the data in a database using Active Record. (require `activerecord-session_store` gem).
-* @ActionDispatch::Session::MemCacheStore@ - Stores the data in a memcached cluster (this is a legacy implementation; consider using CacheStore instead).
+* `ActionDispatch::Session::CookieStore` - Stores everything on the client.
+* `ActionDispatch::Session::CacheStore` - Stores the data in the Rails cache.
+* `ActionDispatch::Session::ActiveRecordStore` - Stores the data in a database using Active Record. (require `activerecord-session_store` gem).
+* `ActionDispatch::Session::MemCacheStore` - Stores the data in a memcached cluster (this is a legacy implementation; consider using CacheStore instead).
All session stores use a cookie to store a unique ID for each session (you must use a cookie, Rails will not allow you to pass the session ID in the URL as this is less secure).
@@ -194,7 +194,7 @@ If you need a different session storage mechanism, you can change it in the `con
```ruby
# Use the database for sessions instead of the cookie-based default,
# which shouldn't be used to store highly confidential information
-# (create the session table with "script/rails g active_record:session_migration")
+# (create the session table with "rails g active_record:session_migration")
# YourApp::Application.config.session_store :active_record_store
```
diff --git a/guides/source/action_mailer_basics.md b/guides/source/action_mailer_basics.md
index 795afd0150..7c6ef52f4a 100644
--- a/guides/source/action_mailer_basics.md
+++ b/guides/source/action_mailer_basics.md
@@ -419,7 +419,7 @@ Receiving and parsing emails with Action Mailer can be a rather complex endeavor
* Implement a `receive` method in your mailer.
-* Configure your email server to forward emails from the address(es) you would like your app to receive to `/path/to/app/script/rails runner 'UserMailer.receive(STDIN.read)'`.
+* Configure your email server to forward emails from the address(es) you would like your app to receive to `/path/to/app/bin/rails runner 'UserMailer.receive(STDIN.read)'`.
Once a method called `receive` is defined in any mailer, Action Mailer will parse the raw incoming email into an email object, decode it, instantiate a new mailer, and pass the email object to the mailer `receive` instance method. Here's an example:
diff --git a/guides/source/active_record_basics.md b/guides/source/active_record_basics.md
index 883c2dda4a..062bcd49f4 100644
--- a/guides/source/active_record_basics.md
+++ b/guides/source/active_record_basics.md
@@ -239,12 +239,12 @@ Active Record provides a rich API for accessing data within a database. Below
are a few examples of different data access methods provided by Active Record.
```ruby
-# return array with all records
+# return a collection with all users
users = User.all
```
```ruby
-# return the first record
+# return the first user
user = User.first
```
@@ -277,7 +277,7 @@ value, like so:
```ruby
user = User.find_by_name('David')
-user.update_attributes(name: 'Dave')
+user.update(name: 'Dave')
```
This is most useful when updating several attributes at once. If, on the other
@@ -307,10 +307,10 @@ models and validate that an attribute value is not empty, is unique and not
already in the database, follows a specific format and many more.
Validation is a very important issue to consider when persisting to database, so
-the methods `create`, `save` and `update_attributes` take it into account when
+the methods `create`, `save` and `update` take it into account when
running: they return `false` when validation fails and they didn't actually
perform any operation on database. All of these have a bang counterpart (that
-is, `create!`, `save!` and `update_attributes!`), which are stricter in that
+is, `create!`, `save!` and `update!`), which are stricter in that
they raise the exception `ActiveRecord::RecordInvalid` if validation fails.
A quick example to illustrate:
diff --git a/guides/source/active_record_callbacks.md b/guides/source/active_record_callbacks.md
index 0a93f61f6d..3747b00b82 100644
--- a/guides/source/active_record_callbacks.md
+++ b/guides/source/active_record_callbacks.md
@@ -159,8 +159,8 @@ The following methods trigger callbacks:
* `toggle!`
* `update`
* `update_attribute`
-* `update_attributes`
-* `update_attributes!`
+* `update`
+* `update!`
* `valid?`
Additionally, the `after_find` callback is triggered by the following finder methods:
@@ -168,7 +168,6 @@ Additionally, the `after_find` callback is triggered by the following finder met
* `all`
* `first`
* `find`
-* `find_all_by_*`
* `find_by_*`
* `find_by_*!`
* `find_by_sql`
@@ -176,7 +175,7 @@ Additionally, the `after_find` callback is triggered by the following finder met
The `after_initialize` callback is triggered every time a new object of the class is initialized.
-NOTE: The `find_all_by_*`, `find_by_*` and `find_by_*!` methods are dynamic finders generated automatically for every attribute. Learn more about them at the [Dynamic finders section](active_record_querying.html#dynamic-finders)
+NOTE: The `find_by_*` and `find_by_*!` methods are dynamic finders generated automatically for every attribute. Learn more about them at the [Dynamic finders section](active_record_querying.html#dynamic-finders)
Skipping Callbacks
------------------
diff --git a/guides/source/active_record_querying.md b/guides/source/active_record_querying.md
index 24f98f68ca..62d6294ae5 100644
--- a/guides/source/active_record_querying.md
+++ b/guides/source/active_record_querying.md
@@ -1228,9 +1228,7 @@ Client.unscoped {
Dynamic Finders
---------------
-For every field (also known as an attribute) you define in your table, Active Record provides a finder method. If you have a field called `first_name` on your `Client` model for example, you get `find_by_first_name` and `find_all_by_first_name` for free from Active Record. If you have a `locked` field on the `Client` model, you also get `find_by_locked` and `find_all_by_locked` methods.
-
-You can also use `find_last_by_*` methods which will find the last record matching your argument.
+For every field (also known as an attribute) you define in your table, Active Record provides a finder method. If you have a field called `first_name` on your `Client` model for example, you get `find_by_first_name` for free from Active Record. If you have a `locked` field on the `Client` model, you also get `find_by_locked` and methods.
You can specify an exclamation point (`!`) on the end of the dynamic finders to get them to raise an `ActiveRecord::RecordNotFound` error if they do not return any records, like `Client.find_by_name!("Ryan")`
diff --git a/guides/source/active_record_validations.md b/guides/source/active_record_validations.md
index 822d12aa3a..a911d6b941 100644
--- a/guides/source/active_record_validations.md
+++ b/guides/source/active_record_validations.md
@@ -117,11 +117,11 @@ database only if the object is valid:
* `save`
* `save!`
* `update`
-* `update_attributes`
-* `update_attributes!`
+* `update`
+* `update!`
The bang versions (e.g. `save!`) raise an exception if the record is invalid.
-The non-bang versions don't: `save` and `update_attributes` return `false`,
+The non-bang versions don't: `save` and `update` return `false`,
`create` and `update` just return the objects.
### Skipping Validations
@@ -656,8 +656,6 @@ class Coffee < ActiveRecord::Base
end
```
-TIP: `:allow_nil` is ignored by the presence validator.
-
### `:allow_blank`
The `:allow_blank` option is similar to the `:allow_nil` option. This option
@@ -673,8 +671,6 @@ Topic.create("title" => "").valid? # => true
Topic.create("title" => nil).valid? # => true
```
-TIP: `:allow_blank` is ignored by the presence validator.
-
### `:message`
As you've already seen, the `:message` option lets you specify the message that
diff --git a/guides/source/active_support_core_extensions.md b/guides/source/active_support_core_extensions.md
index 23736020ec..3c1bb0f132 100644
--- a/guides/source/active_support_core_extensions.md
+++ b/guides/source/active_support_core_extensions.md
@@ -422,24 +422,6 @@ NOTE: Defined in `active_support/core_ext/object/with_options.rb`.
Active Support provides several methods to ease access to instance variables.
-#### `instance_variable_names`
-
-Ruby 1.8 and 1.9 have a method called `instance_variables` that returns the names of the defined instance variables. But they behave differently, in 1.8 it returns strings whereas in 1.9 it returns symbols. Active Support defines `instance_variable_names` as a portable way to obtain them as strings:
-
-```ruby
-class C
- def initialize(x, y)
- @x, @y = x, y
- end
-end
-
-C.new(0, 1).instance_variable_names # => ["@y", "@x"]
-```
-
-WARNING: The order in which the names are returned is unspecified, and it indeed depends on the version of the interpreter.
-
-NOTE: Defined in `active_support/core_ext/object/instance_variables.rb`.
-
#### `instance_values`
The method `instance_values` returns a hash that maps instance variable names without "@" to their
@@ -920,7 +902,7 @@ When interpolated into a string, the `:to` option should become an expression th
delegate :logger, to: :Rails
# delegates to the receiver's class
-delegate :table_name, to: 'self.class'
+delegate :table_name, to: :class
```
WARNING: If the `:prefix` option is `true` this is less generic, see below.
@@ -1449,11 +1431,10 @@ As the previous example shows, Active Support knows some irregular plurals and u
Active Record uses this method to compute the default table name that corresponds to a model:
```ruby
-# active_record/base.rb
+# active_record/model_schema.rb
def undecorated_table_name(class_name = base_class.name)
table_name = class_name.to_s.demodulize.underscore
- table_name = table_name.pluralize if pluralize_table_names
- table_name
+ pluralize_table_names ? table_name.pluralize : table_name
end
```
@@ -2413,9 +2394,9 @@ or yields them in turn if a block is passed:
```html+erb
<% sample.in_groups_of(3) do |a, b, c| %>
<tr>
- <td><%=h a %></td>
- <td><%=h b %></td>
- <td><%=h c %></td>
+ <td><%= a %></td>
+ <td><%= b %></td>
+ <td><%= c %></td>
</tr>
<% end %>
```
diff --git a/guides/source/active_support_instrumentation.md b/guides/source/active_support_instrumentation.md
index cf5a51fc5b..6b3be69942 100644
--- a/guides/source/active_support_instrumentation.md
+++ b/guides/source/active_support_instrumentation.md
@@ -432,7 +432,7 @@ from block args like this:
```ruby
ActiveSupport::Notifications.subscribe "process_action.action_controller" do |*args|
- event = ActiveSupport::Notification::Event.new args
+ event = ActiveSupport::Notifications::Event.new *args
event.name # => "process_action.action_controller"
event.duration # => 10 (in milliseconds)
diff --git a/guides/source/asset_pipeline.md b/guides/source/asset_pipeline.md
index b302ef76c6..fffa31927d 100644
--- a/guides/source/asset_pipeline.md
+++ b/guides/source/asset_pipeline.md
@@ -720,7 +720,31 @@ A good example of this is the `jquery-rails` gem which comes with Rails as the s
Making Your Library or Gem a Pre-Processor
------------------------------------------
-TODO: Registering gems on [Tilt](https://github.com/rtomayko/tilt) enabling Sprockets to find them.
+As Sprockets uses [Tilt](https://github.com/rtomayko/tilt) as a generic
+interface to different templating engines, your gem should just
+implement the Tilt template protocol. Normally, you would subclass
+`Tilt::Template` and reimplement `evaluate` method to return final
+output. Template source is stored at `@code`. Have a look at
+[`Tilt::Template`](https://github.com/rtomayko/tilt/blob/master/lib/tilt/template.rb)
+sources to learn more.
+
+```ruby
+module BangBang
+ class Template < ::Tilt::Template
+ # Adds a "!" to original template.
+ def evaluate(scope, locals, &block)
+ "#{@code}!"
+ end
+ end
+end
+```
+
+Now that you have a `Template` class, it's time to associate it with an
+extenstion for template files:
+
+```ruby
+Sprockets.register_engine '.bang', BangBang::Template
+```
Upgrading from Old Versions of Rails
------------------------------------
diff --git a/guides/source/caching_with_rails.md b/guides/source/caching_with_rails.md
index 773102400a..0228d463cf 100644
--- a/guides/source/caching_with_rails.md
+++ b/guides/source/caching_with_rails.md
@@ -30,101 +30,13 @@ config.action_controller.perform_caching = true
Page caching is a Rails mechanism which allows the request for a generated page to be fulfilled by the webserver (i.e. Apache or nginx), without ever having to go through the Rails stack at all. Obviously, this is super-fast. Unfortunately, it can't be applied to every situation (such as pages that need authentication) and since the webserver is literally just serving a file from the filesystem, cache expiration is an issue that needs to be dealt with.
-To enable page caching, you need to use the `caches_page` method.
-
-```ruby
-class ProductsController < ActionController
-
- caches_page :index
-
- def index
- @products = Product.all
- end
-end
-```
-
-Let's say you have a controller called `ProductsController` and an `index` action that lists all the products. The first time anyone requests `/products`, Rails will generate a file called `products.html` and the webserver will then look for that file before it passes the next request for `/products` to your Rails application.
-
-By default, the page cache directory is set to `Rails.public_path` (which is usually set to the `public` folder) and this can be configured by changing the configuration setting `config.action_controller.page_cache_directory`. Changing the default from `public` helps avoid naming conflicts, since you may want to put other static html in `public`, but changing this will require web server reconfiguration to let the web server know where to serve the cached files from.
-
-The Page Caching mechanism will automatically add a `.html` extension to requests for pages that do not have an extension to make it easy for the webserver to find those pages and this can be configured by changing the configuration setting `config.action_controller.default_static_extension`.
-
-In order to expire this page when a new product is added we could extend our example controller like this:
-
-```ruby
-class ProductsController < ActionController
-
- caches_page :index
-
- def index
- @products = Product.all
- end
-
- def create
- expire_page action: :index
- end
-
-end
-```
-
-By default, page caching automatically gzips files (for example, to `products.html.gz` if user requests `/products`) to reduce the size of data transmitted (web servers are typically configured to use a moderate compression ratio as a compromise, but since precompilation happens once, compression ratio is maximum).
-
-Nginx is able to serve compressed content directly from disk by enabling `gzip_static`:
-
-```nginx
-location / {
- gzip_static on; # to serve pre-gzipped version
-}
-```
-
-You can disable gzipping by setting `:gzip` option to false (for example, if action returns image):
-
-```ruby
-caches_page :image, gzip: false
-```
-
-Or, you can set custom gzip compression level (level names are taken from `Zlib` constants):
-
-```ruby
-caches_page :image, gzip: :best_speed
-```
-
-NOTE: Page caching ignores all parameters. For example `/products?page=1` will be written out to the filesystem as `products.html` with no reference to the `page` parameter. Thus, if someone requests `/products?page=2` later, they will get the cached first page. A workaround for this limitation is to include the parameters in the page's path, e.g. `/products/page/1`.
-
-INFO: Page caching runs in an after filter. Thus, invalid requests won't generate spurious cache entries as long as you halt them. Typically, a redirection in some before filter that checks request preconditions does the job.
+INFO: Page Caching has been removed from Rails 4. See the [actionpack-page_caching gem](https://github.com/rails/actionpack-page_caching)
### Action Caching
Page Caching cannot be used for actions that have before filters - for example, pages that require authentication. This is where Action Caching comes in. Action Caching works like Page Caching except the incoming web request hits the Rails stack so that before filters can be run on it before the cache is served. This allows authentication and other restrictions to be run while still serving the result of the output from a cached copy.
-Clearing the cache works in a similar way to Page Caching, except you use `expire_action` instead of `expire_page`.
-
-Let's say you only wanted authenticated users to call actions on `ProductsController`.
-
-```ruby
-class ProductsController < ActionController
-
- before_action :authenticate
- caches_action :index
-
- def index
- @products = Product.all
- end
-
- def create
- expire_action action: :index
- end
-
-end
-```
-
-You can also use `:if` (or `:unless`) to pass a Proc that specifies when the action should be cached. Also, you can use `layout: false` to cache without layout so that dynamic information in the layout such as logged in user info or the number of items in the cart can be left uncached. This feature is available as of Rails 2.2.
-
-You can modify the default action cache path by passing a `:cache_path` option. This will be passed directly to `ActionCachePath.path_for`. This is handy for actions with multiple possible routes that should be cached differently. If a block is given, it is called with the current controller instance.
-
-Finally, if you are using memcached or Ehcache, you can also pass `:expires_in`. In fact, all parameters not used by `caches_action` are sent to the underlying cache store.
-
-INFO: Action caching runs in an after filter. Thus, invalid requests won't generate spurious cache entries as long as you halt them. Typically, a redirection in some before filter that checks request preconditions does the job.
+INFO: Action Caching has been removed from Rails 4. See the [actionpack-action_caching gem](https://github.com/rails/actionpack-action_caching)
### Fragment Caching
@@ -196,10 +108,6 @@ class ProductsController < ActionController
end
```
-The second time the same query is run against the database, it's not actually going to hit the database. The first time the result is returned from the query it is stored in the query cache (in memory) and the second time it's pulled from memory.
-
-However, it's important to note that query caches are created at the start of an action and destroyed at the end of that action and thus persist only for the duration of the action. If you'd like to store query results in a more persistent fashion, you can in Rails by using low level caching.
-
Cache Stores
------------
diff --git a/guides/source/command_line.md b/guides/source/command_line.md
index 746226fa96..12d39ea1cc 100644
--- a/guides/source/command_line.md
+++ b/guides/source/command_line.md
@@ -225,7 +225,8 @@ $ rails generate scaffold HighScore game:string score:integer
invoke test_unit
create test/models/high_score_test.rb
create test/fixtures/high_scores.yml
- route resources :high_scores
+ invoke resource_route
+ route resources :high_scores
invoke scaffold_controller
create app/controllers/high_scores_controller.rb
invoke erb
@@ -377,7 +378,7 @@ Active Record version 4.0.0.beta
Action Pack version 4.0.0.beta
Action Mailer version 4.0.0.beta
Active Support version 4.0.0.beta
-Middleware ActionDispatch::Static, Rack::Lock, Rack::Runtime, Rack::MethodOverride, ActionDispatch::RequestId, Rails::Rack::Logger, ActionDispatch::ShowExceptions, ActionDispatch::DebugExceptions, ActionDispatch::RemoteIp, ActionDispatch::Reloader, ActionDispatch::Callbacks, ActiveRecord::ConnectionAdapters::ConnectionManagement, ActiveRecord::QueryCache, ActionDispatch::Cookies, ActionDispatch::Session::CookieStore, ActionDispatch::Flash, ActionDispatch::ParamsParser, ActionDispatch::Head, Rack::ConditionalGet, Rack::ETag, ActionDispatch::BestStandardsSupport
+Middleware ActionDispatch::Static, Rack::Lock, Rack::Runtime, Rack::MethodOverride, ActionDispatch::RequestId, Rails::Rack::Logger, ActionDispatch::ShowExceptions, ActionDispatch::DebugExceptions, ActionDispatch::RemoteIp, ActionDispatch::Reloader, ActionDispatch::Callbacks, ActiveRecord::Migration::CheckPending, ActiveRecord::ConnectionAdapters::ConnectionManagement, ActiveRecord::QueryCache, ActionDispatch::Cookies, ActionDispatch::Session::EncryptedCookieStore, ActionDispatch::Flash, ActionDispatch::ParamsParser, Rack::Head, Rack::ConditionalGet, Rack::ETag, ActionDispatch::BestStandardsSupport
Application root /home/foobar/commandsapp
Environment development
Database adapter sqlite3
@@ -563,14 +564,20 @@ We had to create the **gitapp** directory and initialize an empty git repository
$ cat config/database.yml
# PostgreSQL. Versions 8.2 and up are supported.
#
-# Install the ruby-postgres driver:
-# gem install ruby-postgres
-# On Mac OS X:
-# gem install ruby-postgres -- --include=/usr/local/pgsql
+# Install the pg driver:
+# gem install pg
+# On OS X with Homebrew:
+# gem install pg -- --with-pg-config=/usr/local/bin/pg_config
+# On OS X with MacPorts:
+# gem install pg -- --with-pg-config=/opt/local/lib/postgresql84/bin/pg_config
# On Windows:
-# gem install ruby-postgres
+# gem install pg
# Choose the win32 build.
# Install PostgreSQL and put its /bin directory on your path.
+#
+# Configure Using Gemfile
+# gem 'pg'
+#
development:
adapter: postgresql
encoding: unicode
@@ -585,28 +592,3 @@ development:
It also generated some lines in our database.yml configuration corresponding to our choice of PostgreSQL for database.
NOTE. The only catch with using the SCM options is that you have to make your application's directory first, then initialize your SCM, then you can run the `rails new` command to generate the basis of your app.
-
-### `server` with Different Backends
-
-Many people have created a large number of different web servers in Ruby, and many of them can be used to run Rails. Since version 2.3, Rails uses Rack to serve its webpages, which means that any webserver that implements a Rack handler can be used. This includes WEBrick, Mongrel, Thin, and Phusion Passenger (to name a few!).
-
-NOTE: For more details on the Rack integration, see [Rails on Rack](rails_on_rack.html).
-
-To use a different server, just install its gem, then use its name for the first parameter to `rails server`:
-
-```bash
-$ sudo gem install mongrel
-Building native extensions. This could take a while...
-Building native extensions. This could take a while...
-Successfully installed gem_plugin-0.2.3
-Successfully installed fastthread-1.0.1
-Successfully installed cgi_multipart_eof_fix-2.5.0
-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.1.0 application starting on http://0.0.0.0:3000
-...
-```
diff --git a/guides/source/configuring.md b/guides/source/configuring.md
index 6e93932d49..cd0b99b177 100644
--- a/guides/source/configuring.md
+++ b/guides/source/configuring.md
@@ -177,7 +177,6 @@ The full set of methods that can be used in this block are as follows:
* `javascripts` turns on the hook for JavaScript files in generators. Used in Rails for when the `scaffold` generator is run. 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 run, but this hook can be used in other generates as well. Defaults to `true`.
@@ -197,7 +196,7 @@ Every Rails application comes with a standard set of middleware which it uses in
* `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::RequestId` makes a unique X-Request-Id header available to the response and enables the `ActionDispatch::Request#uuid` method.
-* `ActionDispatch::RemoteIp` checks for IP spoofing attacks. Configurable with the `config.action_dispatch.ip_spoofing_check` and `config.action_dispatch.trusted_proxies` settings.
+* `ActionDispatch::RemoteIp` checks for IP spoofing attacks and gets valid `client_ip` from request headers. Configurable with the `config.action_dispatch.ip_spoofing_check`, and `config.action_dispatch.trusted_proxies` options.
* `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`.
@@ -304,6 +303,8 @@ The schema dumper adds one additional configuration option:
* `config.action_controller.permit_all_parameters` sets all the parameters for mass assignment to be permitted by default. The default value is `false`.
+* `config.action_controller.raise_on_unpermitted_parameters` enables raising an exception if parameters that are not explicitly permitted are found. The default value is `true` in development and test environments, `false` otherwise.
+
### Configuring Action Dispatch
* `config.action_dispatch.session_store` sets the name of the store for session data. The default is `:cookie_store`; other valid options include `:active_record_store`, `:mem_cache_store` or the name of your own custom class.
@@ -583,7 +584,7 @@ Rails has 5 initialization events which can be hooked into (listed in the order
* `to_prepare`: Run after the initializers are run for all Railties (including the application itself), but before eager loading and the middleware stack is built. More importantly, will run upon every request in `development`, but only once (during boot-up) in `production` and `test`.
-* `before_eager_load`: This is run directly before eager loading occurs, which is the default behaviour for the `production` environment and not for the `development` environment.
+* `before_eager_load`: This is run directly before eager loading occurs, which is the default behavior for the `production` environment and not for the `development` environment.
* `after_initialize`: Run directly after the initialization of the application, but before the application initializers are run.
diff --git a/guides/source/contributing_to_ruby_on_rails.md b/guides/source/contributing_to_ruby_on_rails.md
index ce2a5a4902..baef620c6c 100644
--- a/guides/source/contributing_to_ruby_on_rails.md
+++ b/guides/source/contributing_to_ruby_on_rails.md
@@ -214,7 +214,9 @@ Rails follows a simple set of coding style conventions:
* Prefer `&&`/`||` over `and`/`or`.
* Prefer class << self over self.method for class methods.
* Use `MyClass.my_method(my_arg)` not `my_method( my_arg )` or `my_method my_arg`.
-* Use a = b and not a=b.
+* Use `a = b` and not `a=b`.
+* Use assert_not methods instead of refute.
+* Prefer `method { do_stuff }` instead of `method{do_stuff}` for single-line blocks.
* Follow the conventions in the source you see used already.
The above are guidelines — please use your best judgment in using them.
@@ -403,7 +405,7 @@ following:
```bash
$ git fetch upstream
-$ git checkout my_pull_request
+$ git checkout my_pull_request
$ git rebase upstream/master
$ git rebase -i
diff --git a/guides/source/credits.html.erb b/guides/source/credits.html.erb
index e25168d58d..ff76fa2b85 100644
--- a/guides/source/credits.html.erb
+++ b/guides/source/credits.html.erb
@@ -28,7 +28,7 @@ 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>.
+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="https://github.com/radar">his GitHub page</a> and he also tweets prolifically as <a href="http://twitter.com/ryanbigg">@ryanbigg</a>.
<% end %>
<%= author('Oscar Del Ben', 'oscardelben', 'oscardelben.jpg') do %>
diff --git a/guides/source/debugging_rails_applications.md b/guides/source/debugging_rails_applications.md
index 2e90e8728c..5531dee343 100644
--- a/guides/source/debugging_rails_applications.md
+++ b/guides/source/debugging_rails_applications.md
@@ -29,7 +29,7 @@ The `debug` helper will return a \<pre>-tag that renders the object using the YA
<%= debug @post %>
<p>
<b>Title:</b>
- <%=h @post.title %>
+ <%= @post.title %>
</p>
```
@@ -58,7 +58,7 @@ Displaying an instance variable, or any other object or method, in YAML format c
<%= simple_format @post.to_yaml %>
<p>
<b>Title:</b>
- <%=h @post.title %>
+ <%= @post.title %>
</p>
```
@@ -88,7 +88,7 @@ Another useful method for displaying object values is `inspect`, especially when
<%= [1, 2, 3, 4, 5].inspect %>
<p>
<b>Title:</b>
- <%=h @post.title %>
+ <%= @post.title %>
</p>
```
@@ -664,7 +664,7 @@ References
----------
* [ruby-debug Homepage](http://bashdb.sourceforge.net/ruby-debug/home-page.html)
-* [debugger Homepage](http://github.com/cldwalker/debugger)
+* [debugger Homepage](https://github.com/cldwalker/debugger)
* [Article: Debugging a Rails application with ruby-debug](http://www.sitepoint.com/article/debug-rails-app-ruby-debug/)
* [ruby-debug Basics screencast](http://brian.maybeyoureinsane.net/blog/2007/05/07/ruby-debug-basics-screencast/)
* [Ryan Bates' debugging ruby (revised) screencast](http://railscasts.com/episodes/54-debugging-ruby-revised)
diff --git a/guides/source/documents.yaml b/guides/source/documents.yaml
index e779407fab..13f982d7e2 100644
--- a/guides/source/documents.yaml
+++ b/guides/source/documents.yaml
@@ -84,10 +84,6 @@
url: debugging_rails_applications.html
description: This guide describes how to debug Rails applications. It covers the different ways of achieving this and how to understand what is happening "behind the scenes" of your code.
-
- name: Performance Testing Rails Applications
- url: performance_testing.html
- description: This guide covers the various ways of performance testing a Ruby on Rails application.
- -
name: Configuring Rails Applications
url: configuring.html
description: This guide covers the basic configuration settings for a Rails application.
diff --git a/guides/source/engines.md b/guides/source/engines.md
index 116a7e67cd..f35233993c 100644
--- a/guides/source/engines.md
+++ b/guides/source/engines.md
@@ -16,9 +16,9 @@ After reading this guide, you will know:
What are engines?
-----------------
-Engines can be considered miniature applications that provide functionality to their host applications. A Rails application is actually just a "supercharged" engine, with the `Rails::Application` class inheriting a lot of its behaviour from `Rails::Engine`.
+Engines can be considered miniature applications that provide functionality to their host applications. A Rails application is actually just a "supercharged" engine, with the `Rails::Application` class inheriting a lot of its behavior from `Rails::Engine`.
-Therefore, engines and applications can be thought of almost the same thing, just with very minor differences, as you'll see throughout this guide. Engines and applications also share a common structure.
+Therefore, engines and applications can be thought of almost the same thing, just with subtle differences, as you'll see throughout this guide. Engines and applications also share a common structure.
Engines are also closely related to plugins where the two share a common `lib` directory structure and are both generated using the `rails plugin new` generator. The difference being that an engine is considered a "full plugin" by Rails as indicated by the `--full` option that's passed to the generator command, but this guide will refer to them simply as "engines" throughout. An engine **can** be a plugin, and a plugin **can** be an engine.
@@ -149,9 +149,9 @@ Lastly, the `app/views` directory contains a `layouts` folder which contains a f
If you don't want to force a layout on to users of the engine, then you can delete this file and reference a different layout in the controllers of your engine.
-#### `script` directory
+#### `bin` directory
-This directory contains one file, `script/rails`, which enables you to use the `rails` sub-commands and generators just like you would within an application. This means that you will very easily be able to generate new controllers and models for this engine by running commands like this:
+This directory contains one file, `bin/rails`, which enables you to use the `rails` sub-commands and generators just like you would within an application. This means that you will very easily be able to generate new controllers and models for this engine by running commands like this:
```bash
rails g model
@@ -171,7 +171,7 @@ end
This line mounts the engine at the path `/blorgh`, which will make it accessible through the application only at that path.
-Also in the test directory is the `test/integration` directory, where integration tests for the engine should be placed. Other directories can be created in the `test` directory also. For example, you may wish to create a `test/models` directory for your models tests.
+In the test directory there is the `test/integration` directory, where integration tests for the engine should be placed. Other directories can be created in the `test` directory as well. For example, you may wish to create a `test/models` directory for your models tests.
Providing engine functionality
------------------------------
@@ -232,7 +232,8 @@ Blorgh::Engine.routes.draw do
end
```
-Note here that the routes are drawn upon the `Blorgh::Engine` object rather than the `YourApp::Application` class. This is so that the engine routes are confined to the engine itself and can be mounted at a specific point as shown in the [test directory](#test-directory) section. This is also what causes the engine's routes to be isolated from those routes that are within the application. This is discussed further in the [Routes](#routes) section of this guide.
+Note here that the routes are drawn upon the `Blorgh::Engine` object rather than the `YourApp::Application` class. This is so that the engine routes are confined to the engine itself and can be mounted at a specific point as shown in the [test directory](#test-directory) section. It also causes the engine's routes to be isolated from those routes that are within the application. The [Routes](#routes) section of
+this guide describes it in details.
Next, the `scaffold_controller` generator is invoked, generating a controller called `Blorgh::PostsController` (at `app/controllers/blorgh/posts_controller.rb`) and its related views at `app/views/blorgh/posts`. This generator also generates a test for the controller (`test/controllers/blorgh/posts_controller_test.rb`) and a helper (`app/helpers/blorgh/posts_controller.rb`).
@@ -258,7 +259,7 @@ module Blorgh
end
```
-This helps prevent conflicts with any other engine or application that may have a post resource also.
+This helps prevent conflicts with any other engine or application that may have a post resource as well.
Finally, two files that are the assets for this resource are generated, `app/assets/javascripts/blorgh/posts.js` and `app/assets/javascripts/blorgh/posts.css`. You'll see how to use these a little later.
@@ -287,7 +288,7 @@ Now people will only need to go to the root of the engine to see all the posts,
### Generating a comments resource
-Now that the engine has the ability to create new blog posts, it only makes sense to add commenting functionality as well. To do get this, you'll need to generate a comment model, a comment controller and then modify the posts scaffold to display comments and allow people to create new ones.
+Now that the engine can to create new blog posts, it only makes sense to add commenting functionality as well. To do get this, you'll need to generate a comment model, a comment controller and then modify the posts scaffold to display comments and allow people to create new ones.
Run the model generator and tell it to generate a `Comment` model, with the related table having two columns: a `post_id` integer and `text` text column.
@@ -531,7 +532,7 @@ before_save :set_author
private
def set_author
- self.author = User.find_or_create_by_name(author_name)
+ self.author = User.find_or_create_by(name: author_name)
end
```
@@ -630,7 +631,7 @@ belongs_to :author, class_name: Blorgh.user_class
The `set_author` method also located in this class should also use this class:
```ruby
-self.author = Blorgh.user_class.constantize.find_or_create_by_name(author_name)
+self.author = Blorgh.user_class.constantize.find_or_create_by(name: author_name)
```
To save having to call `constantize` on the `user_class` result all the time, you could instead just override the `user_class` getter method inside the `Blorgh` module in the `lib/blorgh.rb` file to always call `constantize` on the saved value before returning the result:
@@ -644,10 +645,10 @@ end
This would then turn the above code for `set_author` into this:
```ruby
-self.author = Blorgh.user_class.find_or_create_by_name(author_name)
+self.author = Blorgh.user_class.find_or_create_by(name: author_name)
```
-Resulting in something a little shorter, and more implicit in its behaviour. The `user_class` method should always return a `Class` object.
+Resulting in something a little shorter, and more implicit in its behavior. The `user_class` method should always return a `Class` object.
To set this configuration setting within the application, an initializer should be used. By using an initializer, the configuration will be set up before the application starts and calls the engine's models which may depend on this configuration setting existing.
@@ -661,7 +662,7 @@ WARNING: It's very important here to use the `String` version of the class, rath
Go ahead and try to create a new post. You will see that it works exactly in the same way as before, except this time the engine is using the configuration setting in `config/initializers/blorgh.rb` to learn what the class is.
-There are now no strict dependencies on what the class is, only what the API for the class must be. The engine simply requires this class to define a `find_or_create_by_name` method which returns an object of that class to be associated with a post when it's created. This object, of course, should have some sort of identifier by which it can be referenced.
+There are now no strict dependencies on what the class is, only what the API for the class must be. The engine simply requires this class to define a `find_or_create_by` method which returns an object of that class to be associated with a post when it's created. This object, of course, should have some sort of identifier by which it can be referenced.
#### General engine configuration
@@ -800,7 +801,7 @@ module Blorgh::Concerns::Models::Post
private
def set_author
- self.author = User.find_or_create_by_name(author_name)
+ self.author = User.find_or_create_by(name: author_name)
end
end
@@ -914,9 +915,10 @@ For more information, read the [Asset Pipeline guide](http://guides.rubyonrails.
### Other gem dependencies
-Gem dependencies inside an engine should be specified inside the `.gemspec` file at the root of the engine. The reason for this is because the engine may
+Gem dependencies inside an engine should be specified inside the
+`.gemspec` file at the root of the engine. The reason is that the engine may
be installed as a gem. If dependencies were to be specified inside the `Gemfile`,
-these would not be recognised by a traditional gem install and so they would not
+these would not be recognized by a traditional gem install and so they would not
be installed, causing the engine to malfunction.
To specify a dependency that should be installed with the engine during a
diff --git a/guides/source/form_helpers.md b/guides/source/form_helpers.md
index 8ab44ea0bb..b8681d493a 100644
--- a/guides/source/form_helpers.md
+++ b/guides/source/form_helpers.md
@@ -1,7 +1,7 @@
Form Helpers
============
-Forms in web applications are an essential interface for user input. However, form markup can quickly become tedious to write and maintain because of form control naming and their numerous attributes. Rails deals away with these complexities by providing view helpers for generating form markup. However, since they have different use-cases, developers are required to know all the differences between similar helper methods before putting them to use.
+Forms in web applications are an essential interface for user input. However, form markup can quickly become tedious to write and maintain because of form control naming and their numerous attributes. Rails does away with these complexities by providing view helpers for generating form markup. However, since they have different use-cases, developers are required to know all the differences between similar helper methods before putting them to use.
After reading this guide, you will know:
@@ -148,7 +148,9 @@ Output:
As with `check_box_tag`, the second parameter to `radio_button_tag` is the value of the input. Because these two radio buttons share the same name (age) the user will only be able to select one, and `params[:age]` will contain either "child" or "adult".
-NOTE: Always use labels for checkbox and radio buttons. They associate text with a specific option and make it easier for users to click the inputs by expanding the clickable region.
+NOTE: Always use labels for checkbox and radio buttons. They associate text with a specific option and,
+by expanding the clickable region,
+make it easier for users to click the inputs.
### Other Helpers of Interest
@@ -215,7 +217,7 @@ will produce output similar to
<input id="person_name" name="person[name]" type="text" value="Henry"/>
```
-Upon form submission the value entered by the user will be stored in `params[:person][:name]`. The `params[:person]` hash is suitable for passing to `Person.new` or, if `@person` is an instance of Person, `@person.update_attributes`. While the name of an attribute is the most common second parameter to these helpers this is not compulsory. In the example above, as long as person objects have a `name` and a `name=` method Rails will be happy.
+Upon form submission the value entered by the user will be stored in `params[:person][:name]`. The `params[:person]` hash is suitable for passing to `Person.new` or, if `@person` is an instance of Person, `@person.update`. While the name of an attribute is the most common second parameter to these helpers this is not compulsory. In the example above, as long as person objects have a `name` and a `name=` method Rails will be happy.
WARNING: You must pass the name of an instance variable, i.e. `:person` or `"person"`, not an actual instance of your model object.
@@ -236,7 +238,7 @@ end
The corresponding view `app/views/articles/new.html.erb` using `form_for` looks like this:
```erb
-<%= form_for @article, url: {action: "create"}, html => {class: "nifty_form"} do |f| %>
+<%= form_for @article, url: {action: "create"}, html: {class: "nifty_form"} do |f| %>
<%= f.text_field :title %>
<%= f.text_area :body, size: "60x12" %>
<%= f.submit "Create" %>
@@ -426,7 +428,7 @@ WARNING: when `:inlude_blank` or `:prompt:` are not present, `:include_blank` is
You can add arbitrary attributes to the options using hashes:
```html+erb
-<%= options_for_select([['Lisbon', 1, 'data-size': '2.8 million'], ['Madrid', 2, 'data-size': '3.2 million']], 2) %>
+<%= options_for_select([['Lisbon', 1, {'data-size' => '2.8 million'}], ['Madrid', 2, {'data-size' => '3.2 million'}]], 2) %>
output:
@@ -458,7 +460,7 @@ As with other helpers, if you were to use the `select` helper on a form builder
<%= f.select(:city_id, ...) %>
```
-WARNING: If you are using `select` (or similar helpers such as `collection_select`, `select_tag`) to set a `belongs_to` association you must pass the name of the foreign key (in the example above `city_id`), not the name of association itself. If you specify `city` instead of `city_id` Active Record will raise an error along the lines of ` ActiveRecord::AssociationTypeMismatch: City(#17815740) expected, got String(#1138750) ` when you pass the `params` hash to `Person.new` or `update_attributes`. Another way of looking at this is that form helpers only edit attributes. You should also be aware of the potential security ramifications of allowing users to edit foreign keys directly.
+WARNING: If you are using `select` (or similar helpers such as `collection_select`, `select_tag`) to set a `belongs_to` association you must pass the name of the foreign key (in the example above `city_id`), not the name of association itself. If you specify `city` instead of `city_id` Active Record will raise an error along the lines of ` ActiveRecord::AssociationTypeMismatch: City(#17815740) expected, got String(#1138750) ` when you pass the `params` hash to `Person.new` or `update`. Another way of looking at this is that form helpers only edit attributes. You should also be aware of the potential security ramifications of allowing users to edit foreign keys directly.
### Option Tags from a Collection of Arbitrary Objects
@@ -495,7 +497,7 @@ To leverage time zone support in Rails, you have to ask your users what time zon
There is also `time_zone_options_for_select` helper for a more manual (therefore more customizable) way of doing this. Read the API documentation to learn about the possible arguments for these two methods.
-Rails _used_ to have a `country_select` helper for choosing countries, but this has been extracted to the [country_select plugin](https://github.com/chrislerum/country_select). When using this, be aware that the exclusion or inclusion of certain names from the list can be somewhat controversial (and was the reason this functionality was extracted from Rails).
+Rails _used_ to have a `country_select` helper for choosing countries, but this has been extracted to the [country_select plugin](https://github.com/stefanpenner/country_select). When using this, be aware that the exclusion or inclusion of certain names from the list can be somewhat controversial (and was the reason this functionality was extracted from Rails).
Using Date and Time Form Helpers
--------------------------------
@@ -534,7 +536,7 @@ The `:prefix` option is the key used to retrieve the hash of date components fro
### Model Object Helpers
`select_date` does not work well with forms that update or create Active Record objects as Active Record expects each element of the `params` hash to correspond to one attribute.
-The model object helpers for dates and times submit parameters with special names, when Active Record sees parameters with such names it knows they must be combined with the other parameters and given to a constructor appropriate to the column type. For example:
+The model object helpers for dates and times submit parameters with special names; when Active Record sees parameters with such names it knows they must be combined with the other parameters and given to a constructor appropriate to the column type. For example:
```erb
<%= date_select :person, :birth_date %>
@@ -554,7 +556,7 @@ which results in a `params` hash like
{:person => {'birth_date(1i)' => '2008', 'birth_date(2i)' => '11', 'birth_date(3i)' => '22'}}
```
-When this is passed to `Person.new` (or `update_attributes`), Active Record spots that these parameters should all be used to construct the `birth_date` attribute and uses the suffixed information to determine in which order it should pass these parameters to functions such as `Date.civil`.
+When this is passed to `Person.new` (or `update`), Active Record spots that these parameters should all be used to construct the `birth_date` attribute and uses the suffixed information to determine in which order it should pass these parameters to functions such as `Date.civil`.
### Common Options
@@ -620,7 +622,7 @@ Unlike other forms making an asynchronous file upload form is not as simple as p
Customizing Form Builders
-------------------------
-As mentioned previously the object yielded by `form_for` and `fields_for` is an instance of FormBuilder (or a subclass thereof). Form builders encapsulate the notion of displaying form elements for a single object. While you can of course write helpers for your forms in the usual way you can also subclass FormBuilder and add the helpers there. For example
+As mentioned previously the object yielded by `form_for` and `fields_for` is an instance of FormBuilder (or a subclass thereof). Form builders encapsulate the notion of displaying form elements for a single object. While you can of course write helpers for your forms in the usual way, you can also subclass FormBuilder and add the helpers there. For example
```erb
<%= form_for @person do |f| %>
@@ -805,7 +807,7 @@ Sometimes when you submit data to an external resource, like payment gateway, fi
<% end %>
```
-The same technique is available for the `form_for` too:
+The same technique is also available for `form_for`:
```erb
<%= form_for @invoice, url: external_url, authenticity_token: 'external_token' do |f| %>
diff --git a/guides/source/generators.md b/guides/source/generators.md
index 62de5a70bb..8b91dfc5a5 100644
--- a/guides/source/generators.md
+++ b/guides/source/generators.md
@@ -176,7 +176,8 @@ $ rails generate scaffold User name:string
invoke test_unit
create test/models/user_test.rb
create test/fixtures/users.yml
- route resources :users
+ invoke resource_route
+ route resources :users
invoke scaffold_controller
create app/controllers/users_controller.rb
invoke erb
@@ -192,8 +193,13 @@ $ rails generate scaffold User name:string
create app/helpers/users_helper.rb
invoke test_unit
create test/helpers/users_helper_test.rb
- invoke stylesheets
- create app/assets/stylesheets/scaffold.css
+ invoke assets
+ invoke coffee
+ create app/assets/javascripts/users.js.coffee
+ invoke scss
+ create app/assets/stylesheets/users.css.scss
+ invoke scss
+ create app/assets/stylesheets/scaffolds.css.scss
```
Looking at this output, it's easy to understand how generators work in Rails 3.0 and above. The scaffold generator doesn't actually generate anything, it just invokes others to do the work. This allows us to add/replace/remove any of those invocations. For instance, the scaffold generator invokes the scaffold_controller generator, which invokes erb, test_unit and helper generators. Since each generator has a single responsibility, they are easy to reuse, avoiding code duplication.
@@ -350,6 +356,7 @@ $ rails generate scaffold Comment body:text
invoke shoulda
create test/models/comment_test.rb
create test/fixtures/comments.yml
+ invoke resource_route
route resources :comments
invoke scaffold_controller
create app/controllers/comments_controller.rb
@@ -360,13 +367,16 @@ $ rails generate scaffold Comment body:text
create app/views/comments/show.html.erb
create app/views/comments/new.html.erb
create app/views/comments/_form.html.erb
- create app/views/layouts/comments.html.erb
invoke shoulda
create test/controllers/comments_controller_test.rb
invoke my_helper
create app/helpers/comments_helper.rb
invoke shoulda
create test/helpers/comments_helper_test.rb
+ invoke assets
+ invoke coffee
+ create app/assets/javascripts/comments.js.coffee
+ invoke scss
```
Fallbacks allow your generators to have a single responsibility, increasing code reuse and reducing the amount of duplication.
diff --git a/guides/source/getting_started.md b/guides/source/getting_started.md
index 02ec024e5b..7d86b3866a 100644
--- a/guides/source/getting_started.md
+++ b/guides/source/getting_started.md
@@ -45,7 +45,7 @@ code while accomplishing more than many other languages and frameworks.
Experienced Rails developers also report that it makes web application
development more fun.
-Rails is opinionated software. It makes the assumption that there is a "best"
+Rails is opinionated software. It makes the assumption that there is the "best"
way to do things, and it's designed to encourage that way - and in some cases to
discourage alternatives. If you learn "The Rails Way" you'll probably discover a
tremendous increase in productivity. If you persist in bringing old habits from
@@ -71,7 +71,9 @@ By following along with this guide, you'll create a Rails project called
(very) simple weblog. Before you can start building the application, you need to
make sure that you have Rails itself installed.
-TIP: The examples below use # and $ to denote superuser and regular user terminal prompts respectively in a UNIX-like OS. If you are using Windows, your prompt will look something like c:\source_code>
+TIP: The examples below use `#` and `$` to denote superuser and regular
+user terminal prompts respectively in a UNIX-like OS. If you are using
+Windows, your prompt will look something like `c:\source_code>`
### Installing Rails
@@ -132,17 +134,16 @@ application. Most of the work in this tutorial will happen in the `app/` folder,
| File/Folder | Purpose |
| ----------- | ------- |
|app/|Contains the controllers, models, views, helpers, mailers and assets for your application. You'll focus on this folder for the remainder of this guide.|
+|bin/|Contains the rails script that starts your app and can contain other scripts you use to deploy or run your application.|
|config/|Configure your application's runtime rules, routes, database, and more. This is covered in more detail in [Configuring Rails Applications](configuring.html)|
|config.ru|Rack configuration for Rack based servers used to start the application.|
|db/|Contains your current database schema, as well as the database migrations.|
-|doc/|In-depth documentation for your application.|
|Gemfile<br />Gemfile.lock|These files allow you to specify what gem dependencies are needed for your Rails application. These files are used by the Bundler gem. For more information about Bundler, see [the Bundler website](http://gembundler.com) |
|lib/|Extended modules for your application.|
|log/|Application log files.|
|public/|The only folder seen to the world as-is. Contains the static files and compiled assets.|
|Rakefile|This file locates and loads tasks that can be run from the command line. The task definitions are defined throughout the components of Rails. Rather than changing Rakefile, you should add your own tasks by adding files to the lib/tasks directory of your application.|
|README.rdoc|This is a brief instruction manual for your application. You should edit this file to tell others what your application does, how to set it up, and so on.|
-|script/|Contains the rails script that starts your app and can contain other scripts you use to deploy or run your application.|
|test/|Unit tests, fixtures, and other test apparatus. These are covered in [Testing Rails Applications](testing.html)|
|tmp/|Temporary files (like cache, pid and session files)|
|vendor/|A place for all third-party code. In a typical Rails application, this includes Ruby Gems and the Rails source code (if you optionally install it into your project).|
@@ -417,7 +418,7 @@ def create
end
```
-The `render` method here is taking a very simple hash with a key of `text` and value of `params[:post].inspect`. The `params` method is the object which represents the parameters (or fields) coming in from the form. The `params` method returns a `HashWithIndifferentAccess` object, which allows you to access the keys of the hash using either strings or symbols. In this situation, the only parameters that matter are the ones from the form.
+The `render` method here is taking a very simple hash with a key of `text` and value of `params[:post].inspect`. The `params` method is the object which represents the parameters (or fields) coming in from the form. The `params` method returns an `ActiveSupport::HashWithIndifferentAccess` object, which allows you to access the keys of the hash using either strings or symbols. In this situation, the only parameters that matter are the ones from the form.
If you re-submit the form one more time you'll now no longer get the missing template error. Instead, you'll see something that looks like the following:
@@ -830,7 +831,7 @@ it look as follows:
<h1>Editing post</h1>
<%= form_for :post, url: { action: :update, id: @post.id },
-method: :put do |f| %>
+method: :patch do |f| %>
<% if @post.errors.any? %>
<div id="errorExplanation">
<h2><%= pluralize(@post.errors.count, "error") %> prohibited
@@ -863,7 +864,7 @@ method: :put do |f| %>
This time we point the form to the `update` action, which is not defined yet
but will be very soon.
-The `method: :put` option tells Rails that we want this form to be
+The `method: :patch` option tells Rails that we want this form to be
submitted via the `PUT` HTTP method which is the HTTP method you're expected to use to
**update** resources according to the REST protocol.
@@ -873,7 +874,7 @@ Next, we need to add the `update` action. The file
`config/routes.rb` will need just one more line:
```ruby
-put "posts/:id" => "posts#update"
+patch "posts/:id" => "posts#update"
```
And then create the `update` action in `app/controllers/posts_controller.rb`:
@@ -882,7 +883,7 @@ And then create the `update` action in `app/controllers/posts_controller.rb`:
def update
@post = Post.find(params[:id])
- if @post.update_attributes(params[:post])
+ if @post.update(params[:post])
redirect_to action: :show, id: @post.id
else
render 'edit'
@@ -890,13 +891,13 @@ def update
end
```
-The new method, `update_attributes`, is used when you want to update a record
+The new method, `update`, is used when you want to update a record
that already exists, and it accepts a hash containing the attributes
that you want to update. As before, if there was an error updating the
post we want to show the form back to the user.
-TIP: You don't need to pass all attributes to `update_attributes`. For
-example, if you'd call `@post.update_attributes(title: 'A new title')`
+TIP: You don't need to pass all attributes to `update`. For
+example, if you'd call `@post.update(title: 'A new title')`
Rails would only update the `title` attribute, leaving all other
attributes untouched.
@@ -1051,7 +1052,7 @@ called `post_url` and `post_path` available to our application. These are
precisely the methods that the `form_for` needs when editing a post, and so now
you'll be able to update posts again.
-NOTE: The `:as` option is available on the `post`, `put`, `delete` and `match`
+NOTE: The `:as` option is available on the `post`, `patch`, `put`, `delete` and `match`
routing methods also.
### Deleting Posts
@@ -1145,7 +1146,7 @@ get "posts/new"
post "posts" => "posts#create"
get "posts/:id" => "posts#show", as: :post
get "posts/:id/edit" => "posts#edit"
-put "posts/:id" => "posts#update"
+patch "posts/:id" => "posts#update"
delete "posts/:id" => "posts#destroy"
```
diff --git a/guides/source/i18n.md b/guides/source/i18n.md
index 2e61bea5ea..69232d9bd4 100644
--- a/guides/source/i18n.md
+++ b/guides/source/i18n.md
@@ -897,7 +897,7 @@ The I18n API will catch all of these exceptions when they are thrown in the back
The reason for this is that during development you'd usually want your views to still render even though a translation is missing.
-In other contexts you might want to change this behaviour, though. E.g. the default exception handling does not allow to catch missing translations during automated tests easily. For this purpose a different exception handler can be specified. The specified exception handler must be a method on the I18n module or a class with `#call` method:
+In other contexts you might want to change this behavior, though. E.g. the default exception handling does not allow to catch missing translations during automated tests easily. For this purpose a different exception handler can be specified. The specified exception handler must be a method on the I18n module or a class with `#call` method:
```ruby
module I18n
@@ -927,7 +927,7 @@ else
end
```
-Another example where the default behaviour is less desirable is the Rails TranslationHelper which provides the method `#t` (as well as `#translate`). When a `MissingTranslationData` exception occurs in this context, the helper wraps the message into a span with the CSS class `translation_missing`.
+Another example where the default behavior is less desirable is the Rails TranslationHelper which provides the method `#t` (as well as `#translate`). When a `MissingTranslationData` exception occurs in this context, the helper wraps the message into a span with the CSS class `translation_missing`.
To do so, the helper forces `I18n#translate` to raise exceptions no matter what exception handler is defined by setting the `:raise` option:
diff --git a/guides/source/initialization.md b/guides/source/initialization.md
index 32df508f9c..8ba5fa4601 100644
--- a/guides/source/initialization.md
+++ b/guides/source/initialization.md
@@ -26,126 +26,16 @@ quickly.
Launch!
-------
-A Rails application is usually started with the command `rails server`.
+Now we finally boot and initialize the app. It all starts with your app's
+`bin/rails` executable. A Rails application is usually started by running
+`rails console` or `rails server`.
### `bin/rails`
-The actual `rails` command is kept in _bin/rails_:
-
-```ruby
-#!/usr/bin/env ruby
-
-if File.exists?(File.join(File.expand_path('../../..', __FILE__), '.git'))
- railties_path = File.expand_path('../../lib', __FILE__)
- $:.unshift(railties_path)
-end
-require "rails/cli"
-```
-
-This file will first attempt to push the `railties/lib` directory if
-present, and then requires `rails/cli`.
-
-### `railties/lib/rails/cli.rb`
-
-This file looks like this:
-
-```ruby
-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!
-
-require 'rails/ruby_version_check'
-Signal.trap("INT") { puts; exit(1) }
-
-if ARGV.first == 'plugin'
- ARGV.shift
- require 'rails/commands/plugin_new'
-else
- require 'rails/commands/application'
-end
-```
-
-The `rbconfig` file from the Ruby standard library provides us with the `RbConfig` class which contains detailed information about the Ruby environment, including how Ruby was compiled. We can see this in use in `railties/lib/rails/script_rails_loader`.
-
-```ruby
-require 'pathname'
-
-module Rails
- module ScriptRailsLoader
- RUBY = File.join(*RbConfig::CONFIG.values_at("bindir", "ruby_install_name")) + RbConfig::CONFIG["EXEEXT"]
- SCRIPT_RAILS = File.join('script', 'rails')
- ...
-
- end
-end
-```
-
-The `rails/script_rails_loader` file uses `RbConfig::Config` to obtain the `bin_dir` and `ruby_install_name` values for the configuration which together form the path to the Ruby interpreter. The `RbConfig::CONFIG["EXEEXT"]` will suffix this path with ".exe" if the script is running on Windows. This constant is used later on in `exec_script_rails!`. As for the `SCRIPT_RAILS` constant, we'll see that when we get to the `in_rails_application?` method.
-
-Back in `rails/cli`, the next line is this:
-
-```ruby
-Rails::ScriptRailsLoader.exec_script_rails!
-```
-
-This method is defined in `rails/script_rails_loader`:
-
-```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
-end
-```
-
-This method will first check if the current working directory (`cwd`) is a Rails application or a subdirectory of one. This is determined by the `in_rails_application?` method:
-
-```ruby
-def self.in_rails_application?
- File.exists?(SCRIPT_RAILS)
-end
-```
-
-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
-```
-
-This climbs the directory tree until it reaches a path which contains a `script/rails` file. If a directory containing this file is reached then this line will run:
-
-```ruby
-exec RUBY, SCRIPT_RAILS, *ARGV if in_rails_application?
-```
-
-This is effectively the same as running `ruby script/rails [arguments]`, where `[arguments]` at this point in time is simply "server".
-
-Rails Initialization
---------------------
-
-Only now we finally start the real initialization process, beginning
-with `script/rails`.
-
-TIP: If you execute `script/rails` directly from your Rails app you will
-skip executing all the code that we've just described.
-
-### `script/rails`
-
This file is as follows:
```ruby
+#!/usr/bin/env ruby
APP_PATH = File.expand_path('../../config/application', __FILE__)
require File.expand_path('../../config/boot', __FILE__)
require 'rails/commands'
@@ -227,18 +117,18 @@ If we used `s` rather than `server`, Rails will use the `aliases` defined in the
```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
+ # This allows us to run `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|
+ Rails::Server.new.tap do |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
- }
+ end
```
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 sets up the `Rails::Server` class.
diff --git a/guides/source/layouts_and_rendering.md b/guides/source/layouts_and_rendering.md
index dbaa3ec576..7c26512046 100644
--- a/guides/source/layouts_and_rendering.md
+++ b/guides/source/layouts_and_rendering.md
@@ -97,7 +97,7 @@ NOTE: The actual rendering is done by subclasses of `ActionView::TemplateHandler
### Using `render`
-In most cases, the `ActionController::Base#render` method does the heavy lifting of rendering your application's content for use by a browser. There are a variety of ways to customize the behaviour of `render`. You can render the default view for a Rails template, or a specific template, or a file, or inline code, or nothing at all. You can render text, JSON, or XML. You can specify the content type or HTTP status of the rendered response as well.
+In most cases, the `ActionController::Base#render` method does the heavy lifting of rendering your application's content for use by a browser. There are a variety of ways to customize the behavior of `render`. You can render the default view for a Rails template, or a specific template, or a file, or inline code, or nothing at all. You can render text, JSON, or XML. You can specify the content type or HTTP status of the rendered response as well.
TIP: If you want to see the exact results of a call to `render` without needing to inspect it in a browser, you can call `render_to_string`. This method takes exactly the same options as `render`, but it returns a string instead of sending a response back to the browser.
@@ -137,7 +137,7 @@ If you want to render the view that corresponds to a different template within t
```ruby
def update
@book = Book.find(params[:id])
- if @book.update_attributes(params[:book])
+ if @book.update(params[:book])
redirect_to(@book)
else
render "edit"
@@ -145,14 +145,14 @@ def update
end
```
-If the call to `update_attributes` fails, calling the `update` action in this controller will render the `edit.html.erb` template belonging to the same controller.
+If the call to `update` fails, calling the `update` action in this controller will render the `edit.html.erb` template belonging to the same controller.
If you prefer, you can use a symbol instead of a string to specify the action to render:
```ruby
def update
@book = Book.find(params[:id])
- if @book.update_attributes(params[:book])
+ if @book.update(params[:book])
redirect_to(@book)
else
render :edit
@@ -782,7 +782,7 @@ To include `app/assets/stylesheets/main.css` and `app/assets/stylesheets/columns
To include `app/assets/stylesheets/main.css` and `app/assets/stylesheets/photos/columns.css`:
```erb
-<%= stylesheet_link_tag "main", "/photos/columns" %>
+<%= stylesheet_link_tag "main", "photos/columns" %>
```
To include `http://example.com/main.css`:
diff --git a/guides/source/migrations.md b/guides/source/migrations.md
index 62b70b5571..617e01bd15 100644
--- a/guides/source/migrations.md
+++ b/guides/source/migrations.md
@@ -79,7 +79,7 @@ end
Alternatively, you can use `up` and `down` instead of `change`:
-``ruby
+```ruby
class ChangeProductsPrice < ActiveRecord::Migration
def up
change_table :products do |t|
@@ -108,7 +108,9 @@ of the migration. The name of the migration class (CamelCased version)
should match the latter part of the file name. For example
`20080906120000_create_products.rb` should define class `CreateProducts` and
`20080906120001_add_details_to_products.rb` should define
-`AddDetailsToProducts`.
+`AddDetailsToProducts`. Rails uses this timestamp to determine which migration
+should be run and in what order, so if you're copying a migration from another
+application or generate a file yourself, be aware of its position in the order.
Of course, calculating timestamps is no fun, so Active Record provides a
generator to handle making it for you:
@@ -200,6 +202,25 @@ end
This migration will create a `user_id` column and appropriate index.
+There is also a generator which will produce join tables if `JoinTable` is part of the name:
+
+```bash
+rails g migration CreateJoinTableCustomerProduct customer product
+```
+
+will produce the following migration:
+
+```ruby
+class CreateJoinTableCustomerProduct < ActiveRecord::Migration
+ def change
+ create_join_table :customers, :products do |t|
+ # t.index [:customer_id, :product_id]
+ # t.index [:product_id, :customer_id]
+ end
+ end
+end
+```
+
### Model Generators
The model and scaffold generators will create migrations appropriate for adding
diff --git a/guides/source/nested_model_forms.md b/guides/source/nested_model_forms.md
index 2b46a9d51e..93d8e8dfcd 100644
--- a/guides/source/nested_model_forms.md
+++ b/guides/source/nested_model_forms.md
@@ -56,7 +56,7 @@ end
### Custom model
-As you might have inflected from this explanation, you _don’t_ necessarily need an ActiveRecord::Base model to use this functionality. The following examples are sufficient to enable the nested model form behaviour:
+As you might have inflected from this explanation, you _don’t_ necessarily need an ActiveRecord::Base model to use this functionality. The following examples are sufficient to enable the nested model form behavior:
#### Single associated object
diff --git a/guides/source/performance_testing.md b/guides/source/performance_testing.md
deleted file mode 100644
index ee0059623c..0000000000
--- a/guides/source/performance_testing.md
+++ /dev/null
@@ -1,686 +0,0 @@
-Performance Testing Rails Applications
-======================================
-
-This guide covers the various ways of performance testing a Ruby on Rails
-application.
-
-After reading this guide, you will know:
-
-* The various types of benchmarking and profiling metrics.
-* How to generate performance and benchmarking tests.
-* How to install and use a GC-patched Ruby binary to measure memory usage and object
- allocation.
-* The benchmarking information provided by Rails inside the log files.
-* Various tools facilitating benchmarking and profiling.
-
-Performance testing is an integral part of the development cycle. It is very
-important that you don't make your end users wait for too long before the page
-is completely loaded. Ensuring a pleasant browsing experience for end users and
-cutting the cost of unnecessary hardware is important for any non-trivial web
-application.
-
---------------------------------------------------------------------------------
-
-Performance Test Cases
-----------------------
-
-Rails performance tests are a special type of integration tests, designed for
-benchmarking and profiling the test code. With performance tests, you can
-determine where your application's memory or speed problems are coming from,
-and get a more in-depth picture of those problems.
-
-In a freshly generated Rails application, `test/performance/browsing_test.rb`
-contains an example of a performance test:
-
-```ruby
-require 'test_helper'
-require 'rails/performance_test_help'
-
-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] }
-
- test "homepage" do
- get '/'
- end
-end
-```
-
-This example is a simple performance test case for profiling a GET request to
-the application's homepage.
-
-### Generating Performance Tests
-
-Rails provides a generator called `performance_test` for creating new
-performance tests:
-
-```bash
-$ rails generate performance_test homepage
-```
-
-This generates `homepage_test.rb` in the `test/performance` directory:
-
-```ruby
-require 'test_helper'
-require 'rails/performance_test_help'
-
-class HomepageTest < ActionDispatch::PerformanceTest
- # Refer to the documentation for all available options
- # self.profile_options = { runs: 5, metrics: [:wall_time, :memory],
- # output: 'tmp/performance', formats: [:flat] }
-
- test "homepage" do
- get '/'
- end
-end
-```
-
-### Examples
-
-Let's assume your application has the following controller and model:
-
-```ruby
-# routes.rb
-root to: 'home#dashboard'
-resources :posts
-
-# home_controller.rb
-class HomeController < ApplicationController
- def dashboard
- @users = User.last_ten.includes(:avatars)
- @posts = Post.all_today
- end
-end
-
-# posts_controller.rb
-class PostsController < ApplicationController
- def create
- @post = Post.create(params[:post])
- redirect_to(@post)
- end
-end
-
-# post.rb
-class Post < ActiveRecord::Base
- before_save :recalculate_costly_stats
-
- def slow_method
- # I fire gallzilion queries sleeping all around
- end
-
- private
-
- def recalculate_costly_stats
- # CPU heavy calculations
- end
-end
-```
-
-#### Controller Example
-
-Because performance tests are a special kind of integration test, you can use
-the `get` and `post` methods in them.
-
-Here's the performance test for `HomeController#dashboard` and
-`PostsController#create`:
-
-```ruby
-require 'test_helper'
-require 'rails/performance_test_help'
-
-class PostPerformanceTest < ActionDispatch::PerformanceTest
- def setup
- # Application requires logged-in user
- login_as(:lifo)
- end
-
- test "homepage" do
- get '/dashboard'
- end
-
- test "creating new post" do
- post '/posts', post: { body: 'lifo is fooling you' }
- end
-end
-```
-
-You can find more details about the `get` and `post` methods in the
-[Testing Rails Applications](testing.html) guide.
-
-#### Model Example
-
-Even though the performance tests are integration tests and hence closer to
-the request/response cycle by nature, you can still performance test pure model
-code.
-
-Performance test for `Post` model:
-
-```ruby
-require 'test_helper'
-require 'rails/performance_test_help'
-
-class PostModelTest < ActionDispatch::PerformanceTest
- test "creation" do
- Post.create body: 'still fooling you', cost: '100'
- end
-
- test "slow method" do
- # Using posts(:awesome) fixture
- posts(:awesome).slow_method
- end
-end
-```
-
-### Modes
-
-Performance tests can be run in two modes: Benchmarking and Profiling.
-
-#### Benchmarking
-
-Benchmarking makes it easy to quickly gather a few metrics about each test run.
-By default, each test case is run **4 times** in benchmarking mode.
-
-To run performance tests in benchmarking mode:
-
-```bash
-$ rake test:benchmark
-```
-
-#### Profiling
-
-Profiling allows you to make an in-depth analysis of each of your tests by using
-an external profiler. Depending on your Ruby interpreter, this profiler can be
-native (Rubinius, JRuby) or not (MRI, which uses RubyProf). By default, each
-test case is run **once** in profiling mode.
-
-To run performance tests in profiling mode:
-
-```bash
-$ rake test:profile
-```
-
-### Metrics
-
-Benchmarking and profiling run performance tests and give you multiple metrics.
-The availability of each metric is determined by the interpreter being used—none
-of them support all metrics—and by the mode in use. A brief description of each
-metric and their availability across interpreters/modes is given below.
-
-#### Wall Time
-
-Wall time measures the real world time elapsed during the test run. It is
-affected by any other processes concurrently running on the system.
-
-#### Process Time
-
-Process time measures the time taken by the process. It is unaffected by any
-other processes running concurrently on the same system. Hence, process time
-is likely to be constant for any given performance test, irrespective of the
-machine load.
-
-#### CPU Time
-
-Similar to process time, but leverages the more accurate CPU clock counter
-available on the Pentium and PowerPC platforms.
-
-#### User Time
-
-User time measures the amount of time the CPU spent in user-mode, i.e. within
-the process. This is not affected by other processes and by the time it possibly
-spends blocked.
-
-#### Memory
-
-Memory measures the amount of memory used for the performance test case.
-
-#### Objects
-
-Objects measures the number of objects allocated for the performance test case.
-
-#### GC Runs
-
-GC Runs measures the number of times GC was invoked for the performance test case.
-
-#### GC Time
-
-GC Time measures the amount of time spent in GC for the performance test case.
-
-#### Metric Availability
-
-##### Benchmarking
-
-| Interpreter | Wall Time | Process Time | CPU Time | User Time | Memory | Objects | GC Runs | GC Time |
-| ------------ | --------- | ------------ | -------- | --------- | ------ | ------- | ------- | ------- |
-| **MRI** | yes | yes | yes | no | yes | yes | yes | yes |
-| **REE** | yes | yes | yes | no | yes | yes | yes | yes |
-| **Rubinius** | yes | no | no | no | yes | yes | yes | yes |
-| **JRuby** | yes | no | no | yes | yes | yes | yes | yes |
-
-##### Profiling
-
-| Interpreter | Wall Time | Process Time | CPU Time | User Time | Memory | Objects | GC Runs | GC Time |
-| ------------ | --------- | ------------ | -------- | --------- | ------ | ------- | ------- | ------- |
-| **MRI** | yes | yes | no | no | yes | yes | yes | yes |
-| **REE** | yes | yes | no | no | yes | yes | yes | yes |
-| **Rubinius** | yes | no | no | no | no | no | no | no |
-| **JRuby** | yes | no | no | no | no | no | no | no |
-
-NOTE: To profile under JRuby you'll need to run `export JRUBY_OPTS="-Xlaunch.inproc=false --profile.api"`
-**before** the performance tests.
-
-### Understanding the Output
-
-Performance tests generate different outputs inside `tmp/performance` directory
-depending on their mode and metric.
-
-#### Benchmarking
-
-In benchmarking mode, performance tests generate two types of outputs.
-
-##### Command Line
-
-This is the primary form of output in benchmarking mode. Example:
-
-```bash
-BrowsingTest#test_homepage (31 ms warmup)
- wall_time: 6 ms
- memory: 437.27 KB
- objects: 5,514
- gc_runs: 0
- gc_time: 19 ms
-```
-
-##### CSV Files
-
-Performance test results are also appended to `.csv` files inside `tmp/performance`.
-For example, running the default `BrowsingTest#test_homepage` will generate
-following five files:
-
-* BrowsingTest#test_homepage_gc_runs.csv
-* BrowsingTest#test_homepage_gc_time.csv
-* BrowsingTest#test_homepage_memory.csv
-* BrowsingTest#test_homepage_objects.csv
-* BrowsingTest#test_homepage_wall_time.csv
-
-As the results are appended to these files each time the performance tests are
-run in benchmarking mode, you can collect data over a period of time. This can
-be very helpful in analyzing the effects of code changes.
-
-Sample output of `BrowsingTest#test_homepage_wall_time.csv`:
-
-```bash
-measurement,created_at,app,rails,ruby,platform
-0.00738224999999992,2009-01-08T03:40:29Z,,3.0.0,ruby-1.8.7.249,x86_64-linux
-0.00755874999999984,2009-01-08T03:46:18Z,,3.0.0,ruby-1.8.7.249,x86_64-linux
-0.00762099999999993,2009-01-08T03:49:25Z,,3.0.0,ruby-1.8.7.249,x86_64-linux
-0.00603075000000008,2009-01-08T04:03:29Z,,3.0.0,ruby-1.8.7.249,x86_64-linux
-0.00619899999999995,2009-01-08T04:03:53Z,,3.0.0,ruby-1.8.7.249,x86_64-linux
-0.00755449999999991,2009-01-08T04:04:55Z,,3.0.0,ruby-1.8.7.249,x86_64-linux
-0.00595999999999997,2009-01-08T04:05:06Z,,3.0.0,ruby-1.8.7.249,x86_64-linux
-0.00740450000000004,2009-01-09T03:54:47Z,,3.0.0,ruby-1.8.7.249,x86_64-linux
-0.00603150000000008,2009-01-09T03:54:57Z,,3.0.0,ruby-1.8.7.249,x86_64-linux
-0.00771250000000012,2009-01-09T15:46:03Z,,3.0.0,ruby-1.8.7.249,x86_64-linux
-```
-
-#### 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
-dependent on the interpreter in use. A brief description of each type and
-their availability across interpreters is given below.
-
-##### Command Line
-
-This is a very basic form of output in profiling mode:
-
-```bash
-BrowsingTest#test_homepage (58 ms warmup)
- process_time: 63 ms
- memory: 832.13 KB
- objects: 7,882
-```
-
-##### Flat
-
-Flat output shows the metric—time, memory, etc—measure in each method.
-[Check Ruby-Prof documentation for a better explanation](http://ruby-prof.rubyforge.org/files/examples/flat_txt.html).
-
-##### Graph
-
-Graph output shows the metric measure in each method, which methods call it and
-which methods it calls. [Check Ruby-Prof documentation for a better explanation](http://ruby-prof.rubyforge.org/files/examples/graph_txt.html).
-
-##### Tree
-
-Tree output is profiling information in calltree format for use by [kcachegrind](http://kcachegrind.sourceforge.net/html/Home.html)
-and similar tools.
-
-##### Output Availability
-
-| | Flat | Graph | Tree |
-| ------------ | ---- | ----- | ---- |
-| **MRI** | yes | yes | yes |
-| **REE** | yes | yes | yes |
-| **Rubinius** | yes | yes | no |
-| **JRuby** | yes | yes | no |
-
-### Tuning Test Runs
-
-Test runs can be tuned by setting the `profile_options` class variable on your
-test class.
-
-```ruby
-require 'test_helper'
-require 'rails/performance_test_help'
-
-class BrowsingTest < ActionDispatch::PerformanceTest
- self.profile_options = { runs: 5, metrics: [:wall_time, :memory] }
-
- test "homepage"
- get '/'
- end
-end
-```
-
-In this example, the test would run 5 times and measure wall time and memory.
-There are a few configurable options:
-
-| Option | Description | Default | Mode |
-| ---------- | ------------------------------------------ | ----------------------------- | --------- |
-| `:runs` | Number of runs. | Benchmarking: 4, Profiling: 1 | Both |
-| `:output` | Directory to use when writing the results. | `tmp/performance` | Both |
-| `:metrics` | Metrics to use. | See below. | Both |
-| `:formats` | Formats to output to. | See below. | Profiling |
-
-Metrics and formats have different defaults depending on the interpreter in use.
-
-| Interpreter | Mode | Default metrics | Default formats |
-| -------------- | ------------ | ------------------------------------------------------- | ----------------------------------------------- |
-| **MRI/REE** | Benchmarking | `[:wall_time, :memory, :objects, :gc_runs, :gc_time]` | N/A |
-| | Profiling | `[:process_time, :memory, :objects]` | `[:flat, :graph_html, :call_tree, :call_stack]` |
-| **Rubinius** | Benchmarking | `[:wall_time, :memory, :objects, :gc_runs, :gc_time]` | N/A |
-| | Profiling | `[:wall_time]` | `[:flat, :graph]` |
-| **JRuby** | Benchmarking | `[:wall_time, :user_time, :memory, :gc_runs, :gc_time]` | N/A |
-| | Profiling | `[:wall_time]` | `[:flat, :graph]` |
-
-As you've probably noticed by now, metrics and formats are specified using a
-symbol array with each name [underscored.](http://api.rubyonrails.org/classes/String.html#method-i-underscore)
-
-### Performance Test Environment
-
-Performance tests are run in the `test` environment. But running performance
-tests will set the following configuration parameters:
-
-```bash
-ActionController::Base.perform_caching = true
-ActiveSupport::Dependencies.mechanism = :require
-Rails.logger.level = ActiveSupport::Logger::INFO
-```
-
-As `ActionController::Base.perform_caching` is set to `true`, performance tests
-will behave much as they do in the `production` environment.
-
-### Installing GC-Patched MRI
-
-To get the best from Rails' performance tests under MRI, you'll need to build
-a special Ruby binary with some super powers.
-
-The recommended patches for each MRI version are:
-
-| Version | Patch |
-| --------------- | --------- |
-| 1.8.6 | ruby186gc |
-| 1.8.7 | ruby187gc |
-| 1.9.2 and above | gcdata |
-
-All of these can be found on [RVM's _patches_ directory](https://github.com/wayneeseguin/rvm/tree/master/patches/ruby)
-under each specific interpreter version.
-
-Concerning the installation itself, you can either do this easily by using
-[RVM](http://rvm.beginrescueend.com) or you can build everything from source,
-which is a little bit harder.
-
-#### Install Using RVM
-
-The process of installing a patched Ruby interpreter is very easy if you let RVM
-do the hard work. All of the following RVM commands will provide you with a
-patched Ruby interpreter:
-
-```bash
-$ rvm install 1.9.2-p180 --patch gcdata
-$ rvm install 1.8.7 --patch ruby187gc
-$ rvm install 1.9.2-p180 --patch ~/Downloads/downloaded_gcdata_patch.patch
-```
-
-You can even keep your regular interpreter by assigning a name to the patched
-one:
-
-```bash
-$ rvm install 1.9.2-p180 --patch gcdata --name gcdata
-$ rvm use 1.9.2-p180 # your regular ruby
-$ rvm use 1.9.2-p180-gcdata # your patched ruby
-```
-
-And it's done! You have installed a patched Ruby interpreter.
-
-#### Install From Source
-
-This process is a bit more complicated, but straightforward nonetheless. If
-you've never compiled a Ruby binary before, follow these steps to build a
-Ruby binary inside your home directory.
-
-##### Download and Extract
-
-```bash
-$ mkdir rubygc
-$ wget <the version you want from ftp://ftp.ruby-lang.org/pub/ruby>
-$ tar -xzvf <ruby-version.tar.gz>
-$ cd <ruby-version>
-```
-
-##### Apply the Patch
-
-```bash
-$ curl http://github.com/wayneeseguin/rvm/raw/master/patches/ruby/1.9.2/p180/gcdata.patch | patch -p0 # if you're on 1.9.2!
-$ curl http://github.com/wayneeseguin/rvm/raw/master/patches/ruby/1.8.7/ruby187gc.patch | patch -p0 # if you're on 1.8.7!
-```
-
-##### Configure and Install
-
-The following will install Ruby in your home directory's `/rubygc` directory.
-Make sure to replace `<homedir>` with a full patch to your actual home
-directory.
-
-```bash
-$ ./configure --prefix=/<homedir>/rubygc
-$ make && make install
-```
-
-##### Prepare Aliases
-
-For convenience, add the following lines in your `~/.profile`:
-
-```bash
-alias gcruby='~/rubygc/bin/ruby'
-alias gcrake='~/rubygc/bin/rake'
-alias gcgem='~/rubygc/bin/gem'
-alias gcirb='~/rubygc/bin/irb'
-alias gcrails='~/rubygc/bin/rails'
-```
-
-Don't forget to use your aliases from now on.
-
-### Using Ruby-Prof on MRI and REE
-
-Add Ruby-Prof to your applications' Gemfile if you want to benchmark/profile
-under MRI or REE:
-
-```ruby
-gem 'ruby-prof'
-```
-
-Now run `bundle install` and you're ready to go.
-
-Command Line Tools
-------------------
-
-Writing performance test cases could be an overkill when you are looking for one
-time tests. Rails ships with two command line tools that enable quick and dirty
-performance testing:
-
-### `benchmarker`
-
-Usage:
-
-```bash
-Usage: rails benchmarker 'Ruby.code' 'Ruby.more_code' ... [OPTS]
- -r, --runs N Number of runs.
- Default: 4
- -o, --output PATH Directory to use when writing the results.
- Default: tmp/performance
- -m, --metrics a,b,c Metrics to use.
- Default: wall_time,memory,objects,gc_runs,gc_time
-```
-
-Example:
-
-```bash
-$ rails benchmarker 'Item.all' 'CouchItem.all' --runs 3 --metrics wall_time,memory
-```
-
-### `profiler`
-
-Usage:
-
-```bash
-Usage: rails profiler 'Ruby.code' 'Ruby.more_code' ... [OPTS]
- -r, --runs N Number of runs.
- Default: 1
- -o, --output PATH Directory to use when writing the results.
- Default: tmp/performance
- -m, --metrics a,b,c Metrics to use.
- Default: process_time,memory,objects
- -f, --formats x,y,z Formats to output to.
- Default: flat,graph_html,call_tree
-```
-
-Example:
-
-```bash
-$ rails profiler 'Item.all' 'CouchItem.all' --runs 2 --metrics process_time --formats flat
-```
-
-NOTE: Metrics and formats vary from interpreter to interpreter. Pass `--help` to
-each tool to see the defaults for your interpreter.
-
-Helper Methods
---------------
-
-Rails provides various helper methods inside Active Record, Action Controller
-and Action View to measure the time taken by a given piece of code. The method
-is called `benchmark()` in all the three components.
-
-### Model
-
-```ruby
-Project.benchmark("Creating project") do
- project = Project.create("name" => "stuff")
- project.create_manager("name" => "David")
- project.milestones << Milestone.all
-end
-```
-
-This benchmarks the code enclosed in the `Project.benchmark("Creating project") do...end`
-block and prints the result to the log file:
-
-```ruby
-Creating project (185.3ms)
-```
-
-Please refer to the [API docs](http://api.rubyonrails.org/classes/ActiveSupport/Benchmarkable.html#method-i-benchmark)
-for additional options to `benchmark()`.
-
-### Controller
-
-Similarly, you could use this helper method inside [controllers.](http://api.rubyonrails.org/classes/ActiveSupport/Benchmarkable.html)
-
-```ruby
-def process_projects
- benchmark("Processing projects") do
- Project.process(params[:project_ids])
- Project.update_cached_projects
- end
-end
-```
-
-NOTE: `benchmark` is a class method inside controllers.
-
-### View
-
-And in [views](http://api.rubyonrails.org/classes/ActiveSupport/Benchmarkable.html:)
-
-```erb
-<% benchmark("Showing projects partial") do %>
- <%= render @projects %>
-<% end %>
-```
-
-Request Logging
----------------
-
-Rails log files contain very useful information about the time taken to serve
-each request. Here's a typical log file entry:
-
-```bash
-Processing ItemsController#index (for 127.0.0.1 at 2009-01-08 03:06:39) [GET]
-Rendering template within layouts/items
-Rendering items/index
-Completed in 5ms (View: 2, DB: 0) | 200 OK [http://0.0.0.0/items]
-```
-
-For this section, we're only interested in the last line:
-
-```bash
-Completed in 5ms (View: 2, DB: 0) | 200 OK [http://0.0.0.0/items]
-```
-
-This data is fairly straightforward to understand. Rails uses millisecond(ms) as
-the metric to measure the time taken. The complete request spent 5 ms inside
-Rails, out of which 2 ms were spent rendering views and none was spent
-communication with the database. It's safe to assume that the remaining 3 ms
-were spent inside the controller.
-
-Michael Koziarski has an [interesting blog post](http://www.therailsway.com/2009/1/6/requests-per-second)
-explaining the importance of using milliseconds as the metric.
-
-Useful Links
-------------
-
-### Rails Plugins and Gems
-
-* [Rails Analyzer](http://rails-analyzer.rubyforge.org)
-* [Rails Footnotes](https://github.com/josevalim/rails-footnotes/tree/master)
-* [Query Reviewer](https://github.com/nesquena/query_reviewer)
-* [MiniProfiler](http://www.miniprofiler.com)
-
-### Generic Tools
-
-* [httperf](http://www.hpl.hp.com/research/linux/httperf/)
-* [ab](http://httpd.apache.org/docs/2.2/programs/ab.html)
-* [JMeter](http://jakarta.apache.org/jmeter/)
-* [kcachegrind](http://kcachegrind.sourceforge.net/html/Home.html)
-
-### Tutorials and Documentation
-
-* [ruby-prof API Documentation](http://ruby-prof.rubyforge.org)
-* [Request Profiling Railscast](http://railscasts.com/episodes/98-request-profiling) - Outdated, but useful for understanding call graphs.
-
-Commercial Products
--------------------
-
-Rails has been lucky to have a few companies dedicated to Rails-specific
-performance tools. A couple of those are:
-
-* [New Relic](http://www.newrelic.com)
-* [Scout](http://scoutapp.com)
diff --git a/guides/source/rails_application_templates.md b/guides/source/rails_application_templates.md
index 9e694acb98..77138d8871 100644
--- a/guides/source/rails_application_templates.md
+++ b/guides/source/rails_application_templates.md
@@ -34,7 +34,6 @@ Rails templates API is very self explanatory and easy to understand. Here's an e
```ruby
# template.rb
-run "rm public/index.html"
generate(:scaffold, "person name:string")
route "root to: 'people#index'"
rake("db:migrate")
@@ -158,10 +157,10 @@ generate(:scaffold, "person", "name:string", "address:text", "age:number")
### run(command)
-Executes an arbitrary command. Just like the backticks. Let's say you want to remove the `public/index.html` file:
+Executes an arbitrary command. Just like the backticks. Let's say you want to remove the `README.rdoc` file:
```ruby
-run "rm public/index.html"
+run "rm README.rdoc"
```
### rake(command, options = {})
@@ -180,7 +179,7 @@ rake "db:migrate", env: 'production'
### route(routing_code)
-Adds a routing entry to the `config/routes.rb` file. In above steps, we generated a person scaffold and also removed `public/index.html`. Now to make `PeopleController#index` as the default page for the application:
+Adds a routing entry to the `config/routes.rb` file. In above steps, we generated a person scaffold and also removed `README.rdoc`. Now to make `PeopleController#index` as the default page for the application:
```ruby
route "root to: 'person#index'"
diff --git a/guides/source/rails_on_rack.md b/guides/source/rails_on_rack.md
index 1fac6d9883..a6119eb433 100644
--- a/guides/source/rails_on_rack.md
+++ b/guides/source/rails_on_rack.md
@@ -37,11 +37,11 @@ Rails on Rack
Here's how `rails server` creates an instance of `Rack::Server`
```ruby
-Rails::Server.new.tap { |server|
+Rails::Server.new.tap do |server|
require APP_PATH
Dir.chdir(Rails.application.root)
server.start
-}
+end
```
The `Rails::Server` inherits from `Rack::Server` and calls the `Rack::Server#start` method this way:
@@ -229,7 +229,7 @@ Much of Action Controller's functionality is implemented as Middlewares. The fol
**`Rack::Lock`**
-* Sets `env["rack.multithread"]` flag to `true` and wraps the application within a Mutex.
+* Sets `env["rack.multithread"]` flag to `false` and wraps the application within a Mutex.
**`ActiveSupport::Cache::Strategy::LocalCache::Middleware`**
diff --git a/guides/source/security.md b/guides/source/security.md
index 0b0cfe69c4..3706a61431 100644
--- a/guides/source/security.md
+++ b/guides/source/security.md
@@ -210,7 +210,7 @@ The HTTP protocol basically provides two main types of requests - GET and POST (
* The interaction _changes the state_ of the resource in a way that the user would perceive (e.g., a subscription to a service), or
* The user is _held accountable for the results_ of the interaction.
-If your web application is RESTful, you might be used to additional HTTP verbs, such as PUT or DELETE. Most of today's web browsers, however do not support them - only GET and POST. Rails uses a hidden `_method` field to handle this barrier.
+If your web application is RESTful, you might be used to additional HTTP verbs, such as PATCH, PUT or DELETE. Most of today's web browsers, however do not support them - only GET and POST. Rails uses a hidden `_method` field to handle this barrier.
_POST requests can be sent automatically, too_. Here is an example for a link which displays www.harmless.com as destination in the browser's status bar. In fact it dynamically creates a new form that sends a POST request.
diff --git a/guides/source/testing.md b/guides/source/testing.md
index a9bce04522..09d6d2d5ee 100644
--- a/guides/source/testing.md
+++ b/guides/source/testing.md
@@ -39,10 +39,10 @@ Rails creates a `test` folder for you as soon as you create a Rails project usin
```bash
$ ls -F test
-fixtures/ functional/ integration/ performance/ test_helper.rb unit/
+fixtures/ functional/ integration/ test_helper.rb unit/
```
-The `unit` directory is meant to hold tests for your models, the `functional` directory is meant to hold tests for your controllers, the `integration` directory is meant to hold tests that involve any number of controllers interacting, and the `performance` directory is meant for performance tests.
+The `unit` directory is meant to hold tests for your models, the `functional` directory is meant to hold tests for your controllers and the `integration` directory is meant to hold tests that involve any number of controllers interacting.
Fixtures are a way of organizing test data; they reside in the `fixtures` folder.
@@ -77,7 +77,7 @@ steve:
profession: guy with keyboard
```
-Each fixture is given a name followed by an indented list of colon-separated key/value pairs. Records are typically separated by a blank space. You can place comments in a fixture file by using the # character in the first column.
+Each fixture is given a name followed by an indented list of colon-separated key/value pairs. Records are typically separated by a blank space. You can place comments in a fixture file by using the # character in the first column. Keys which resemble YAML keywords such as 'yes' and 'no' are quoted so that the YAML Parser correctly interprets them.
#### ERB'in It Up
@@ -760,14 +760,12 @@ You don't need to set up and run your tests by hand on a test-by-test basis. Rai
| Tasks | Description |
| ------------------------------- | ----------- |
| `rake test` | Runs all unit, functional and integration tests. You can also simply run `rake` as the _test_ target is the default.|
-| `rake test:benchmark` | Benchmark the performance tests|
| `rake test:controllers` | Runs all the controller tests from `test/controllers`|
| `rake test:functionals` | Runs all the functional tests from `test/controllers`, `test/mailers`, and `test/functional`|
| `rake test:helpers` | Runs all the helper tests from `test/helpers`|
| `rake test:integration` | Runs all the integration tests from `test/integration`|
| `rake test:mailers` | Runs all the mailer tests from `test/mailers`|
| `rake test:models` | Runs all the model tests from `test/models`|
-| `rake test:profile` | Profile the performance tests|
| `rake test:recent` | Tests recent changes|
| `rake test:uncommitted` | Runs all the tests which are uncommitted. Supports Subversion and Git|
| `rake test:units` | Runs all the unit tests from `test/models`, `test/helpers`, and `test/unit`|
@@ -830,7 +828,7 @@ Above, the `setup` method is called before each test and so `@post` is available
Let's see the earlier example by specifying `setup` callback by specifying a method name as a symbol:
```ruby
-require '../test_helper'
+require 'test_helper'
class PostsControllerTest < ActionController::TestCase
diff --git a/guides/source/working_with_javascript_in_rails.md b/guides/source/working_with_javascript_in_rails.md
index 0f5acfba3c..a7ca531123 100644
--- a/guides/source/working_with_javascript_in_rails.md
+++ b/guides/source/working_with_javascript_in_rails.md
@@ -66,37 +66,38 @@ Here's the simplest way to write JavaScript. You may see it referred to as
'inline JavaScript':
```html
-<a href="#" onclick="alert('Hello, world.')">Here</a>
+<a href="#" onclick="this.style.backgroundColor='#990000'">Paint it red</a>
```
-
-When clicked, the alert will trigger. Here's the problem: what happens when
-we have lots of JavaScript we want to execute on a click?
+When clicked, the link background will become red. Here's the problem: what
+happens when we have lots of JavaScript we want to execute on a click?
```html
-<a href="#" onclick="function fib(n){return n<2?n:fib(n-1)+fib(n-2);};alert('fib of 15 is: ' + fib(15) + '.');">Calculate</a>
+<a href="#" onclick="this.style.backgroundColor='#009900';this.style.color='#FFFFFF';">Paint it green</a>
```
Awkward, right? We could pull the function definition out of the click handler,
and turn it into CoffeeScript:
```coffeescript
-fib = (n) ->
- (if n < 2 then n else fib(n - 1) + fib(n - 2))
+paintIt = (element, backgroundColor, textColor) ->
+ element.style.backgroundColor = backgroundColor
+ if textColor?
+ element.style.color = textColor
```
And then on our page:
```html
-<a href="#" onclick="alert('fib of 15 is: ' + fib(15) + '.');">Calculate</a>
+<a href="#" onclick="paintIt(this, '#990000')">Paint it red</a>
```
That's a little bit better, but what about multiple links that have the same
effect?
```html
-<a href="#" onclick="alert('fib of 16 is: ' + fib(16) + '.');">Calculate</a>
-<a href="#" onclick="alert('fib of 17 is: ' + fib(17) + '.');">Calculate</a>
-<a href="#" onclick="alert('fib of 18 is: ' + fib(18) + '.');">Calculate</a>
+<a href="#" onclick="paintIt(this, '#990000')">Paint it red</a>
+<a href="#" onclick="paintIt(this, '#009900', '#FFFFFF')">Paint it green</a>
+<a href="#" onclick="paintIt(this, '#000099', '#FFFFFF')">Paint it blue</a>
```
Not very DRY, eh? We can fix this by using events instead. We'll add a `data-*`
@@ -104,19 +105,21 @@ attribute to our link, and then bind a handler to the click event of every link
that has that attribute:
```coffeescript
-fib = (n) ->
- (if n < 2 then n else fib(n - 1) + fib(n - 2))
-
-$(document).ready ->
- $("a[data-fib]").click (e) ->
- count = $(this).data("fib")
- alert "fib of #{count} is: #{fib(count)}."
-
-... later ...
-
-<a href="#" data-fib="15">Calculate</a>
-<a href="#" data-fib="16">Calculate</a>
-<a href="#" data-fib="17">Calculate</a>
+paintIt = (element, backgroundColor, textColor) ->
+ element.style.backgroundColor = backgroundColor
+ if textColor?
+ element.style.color = textColor
+
+$ ->
+ $("a[data-color]").click ->
+ backgroundColor = $(this).data("background-color")
+ textColor = $(this).data("text-color")
+ paintIt(this, backgroundColor, textColor)
+```
+```html
+<a href="#" data-background-color="#990000">Paint it red</a>
+<a href="#" data-background-color="#009900" data-text-color="#FFFFFF">Paint it green</a>
+<a href="#" data-background-color="#000099" data-text-color="#FFFFFF">Paint it blue</a>
```
We call this 'unobtrusive' JavaScript because we're no longer mixing our
@@ -204,7 +207,7 @@ is a helper that assists with generating links. It has a `:remote` option you
can use like this:
```erb
-<%= link_to "first post", @post, remote: true %>
+<%= link_to "a post", @post, remote: true %>
```
which generates
@@ -214,20 +217,19 @@ which generates
```
You can bind to the same Ajax events as `form_for`. Here's an example. Let's
-assume that we have a resource `/fib/:n` that calculates the `n`th Fibonacci
-number. We would generate some HTML like this:
+assume that we have a list of posts that can be deleted with just one
+click. We would generate some HTML like this:
```erb
-<%= link_to "Calculate", "/fib/15", remote: true, data: { fib: 15 } %>
+<%= link_to "Delete post", @post, remote: true, method: :delete %>
```
and write some CoffeeScript like this:
```coffeescript
-$(document).ready ->
- $("a[data-fib]").on "ajax:success", (e, data, status, xhr) ->
- count = $(this).data("fib")
- alert "fib of #{count} is: #{data}."
+$ ->
+ $("a[data-remote]").on "ajax:success", (e, data, status, xhr) ->
+ alert "The post was deleted."
```
### button_to
diff --git a/install.rb b/install.rb
index b87b008c2e..3967624a3f 100644
--- a/install.rb
+++ b/install.rb
@@ -1,11 +1,16 @@
version = ARGV.pop
+if version.nil?
+ puts "Usage: ruby install.rb version"
+ exit(64)
+end
+
%w( activesupport activemodel activerecord actionpack actionmailer railties ).each do |framework|
puts "Installing #{framework}..."
- `cd #{framework} && gem build #{framework}.gemspec && gem install #{framework}-#{version}.gem --no-ri --no-rdoc && rm #{framework}-#{version}.gem`
+ `cd #{framework} && gem build #{framework}.gemspec && gem install #{framework}-#{version}.gem --local --no-ri --no-rdoc && rm #{framework}-#{version}.gem`
end
puts "Installing Rails..."
`gem build rails.gemspec`
-`gem install rails-#{version}.gem --no-ri --no-rdoc `
+`gem install rails-#{version}.gem --local --no-ri --no-rdoc `
`rm rails-#{version}.gem`
diff --git a/rails.gemspec b/rails.gemspec
index ba94354bf1..34957c9455 100644
--- a/rails.gemspec
+++ b/rails.gemspec
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
s.bindir = 'bin'
s.executables = []
- s.files = Dir['guides/**/*']
+ s.files = ['README.rdoc'] + Dir['guides/**/*']
s.add_dependency 'activesupport', version
s.add_dependency 'actionpack', version
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index 953133d8ef..e9a69e5a0c 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -1,8 +1,51 @@
## Rails 4.0.0 (unreleased) ##
+* The generated `README.rdoc` for new applications invites the user to
+ document the necessary steps to get the application up and running.
+
+ *Xavier Noria*
+
+* Generated applications no longer get `doc/README_FOR_APP`. In consequence,
+ the `doc` directory is created on demand by documentation tasks rather than
+ generated by default.
+
+ *Xavier Noria*
+
+* App executables now live in the `bin/` directory: `bin/bundle`,
+ `bin/rails`, `bin/rake`. Run `rake rails:update:bin` to add these
+ executables to your own app. `script/rails` is gone from new apps.
+
+ Running executables within your app ensures they use your app's Ruby
+ version and its bundled gems, and it ensures your production deployment
+ tools only need to execute a single script. No more having to carefully
+ `cd` to the app dir and run `bundle exec ...`.
+
+ Rather than treating `bin/` as a junk drawer for generated "binstubs",
+ bundler 1.3 adds support for generating stubs for just the executables
+ you actually use: `bundle binstubs unicorn` generates `bin/unicorn`.
+ Add that executable to git and version it just like any other app code.
+
+ *Jeremy Kemper*
+
+* `config.assets.enabled` is now true by default. If you're upgrading from a Rails 3.x app
+ that does not use the asset pipeline, you'll be required to add `config.assets.enabled = false`
+ to your application.rb. If you don't want the asset pipeline on a new app use `--skip-sprockets`
+
+ *DHH*
+
+* Environment name can be a start substring of the default environment names
+ (production, development, test). For example: tes, pro, prod, dev, devel.
+ Fix #8628.
+
+ *Mykola Kyryk*
+
+* Add `-B` alias for `--skip-bundle` option in the rails new generators.
+
+ *Jiri Pospisil*
+
* Quote column names in generates fixture files. This prevents
conflicts with reserved YAML keywords such as 'yes' and 'no'
- Fix #8612
+ Fix #8612.
*Yves Senn*
@@ -151,8 +194,6 @@
* Add convenience `hide!` method to Rails generators to hide current generator
namespace from showing when running `rails generate`. *Carlos Antonio da Silva*
-* Scaffold now uses `content_tag_for` in index.html.erb *José Valim*
-
* Rails::Plugin has gone. Instead of adding plugins to vendor/plugins use gems or bundler with path or git dependencies. *Santiago Pastorino*
* Set config.action_mailer.async = true to turn on asynchronous
diff --git a/railties/MIT-LICENSE b/railties/MIT-LICENSE
index 03bde18130..0d7fb865e2 100644
--- a/railties/MIT-LICENSE
+++ b/railties/MIT-LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2004-2012 David Heinemeier Hansson
+Copyright (c) 2004-2013 David Heinemeier Hansson
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
diff --git a/railties/lib/rails/app_rails_loader.rb b/railties/lib/rails/app_rails_loader.rb
new file mode 100644
index 0000000000..8937e10db3
--- /dev/null
+++ b/railties/lib/rails/app_rails_loader.rb
@@ -0,0 +1,29 @@
+require 'pathname'
+
+module Rails
+ module AppRailsLoader
+ RUBY = File.join(*RbConfig::CONFIG.values_at("bindir", "ruby_install_name")) + RbConfig::CONFIG["EXEEXT"]
+ EXECUTABLE = 'bin/rails'
+
+ def self.exec_app_rails
+ cwd = Dir.pwd
+ return unless in_rails_application_or_engine? || in_rails_application_or_engine_subdirectory?
+ exec RUBY, EXECUTABLE, *ARGV if in_rails_application_or_engine?
+ 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_app_rails unless cwd == Dir.pwd
+ end
+ rescue SystemCallError
+ # could not chdir, no problem just return
+ end
+
+ def self.in_rails_application_or_engine?
+ File.exists?(EXECUTABLE) && File.read(EXECUTABLE) =~ /(APP|ENGINE)_PATH/
+ end
+
+ def self.in_rails_application_or_engine_subdirectory?(path = Pathname.new(Dir.pwd))
+ File.exists?(File.join(path, EXECUTABLE)) || !path.root? && in_rails_application_or_engine_subdirectory?(path.parent)
+ end
+ end
+end
diff --git a/railties/lib/rails/application.rb b/railties/lib/rails/application.rb
index 8439d4864d..cff75872b2 100644
--- a/railties/lib/rails/application.rb
+++ b/railties/lib/rails/application.rb
@@ -135,9 +135,10 @@ module Rails
def env_config
@env_config ||= begin
if config.secret_key_base.nil?
- ActiveSupport::Deprecation.warn "You didn't set config.secret_key_base. " +
- "This should be used instead of the old deprecated config.secret_token. " +
- "Set config.secret_key_base instead of config.secret_token in config/initializers/secret_token.rb"
+ ActiveSupport::Deprecation.warn "You didn't set config.secret_key_base in config/initializers/secret_token.rb file. " +
+ "This should be used instead of the old deprecated config.secret_token in order to use the new EncryptedCookieStore. " +
+ "To convert safely to the encrypted store (without losing existing cookies and sessions), see http://guides.rubyonrails.org/upgrading_ruby_on_rails.html#action-pack"
+
if config.secret_token.blank?
raise "You must set config.secret_key_base in your app's config"
end
diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb
index 086fd5ed95..2c7ddd86e7 100644
--- a/railties/lib/rails/application/configuration.rb
+++ b/railties/lib/rails/application/configuration.rb
@@ -48,12 +48,12 @@ module Rails
@secret_key_base = nil
@assets = ActiveSupport::OrderedOptions.new
- @assets.enabled = false
+ @assets.enabled = true
@assets.paths = []
@assets.precompile = [ Proc.new { |path, fn| fn =~ /app\/assets/ && !%w(.js .css).include?(File.extname(path)) },
/(?:\/|\\|\A)application\.(css|js)$/ ]
@assets.prefix = "/assets"
- @assets.version = ''
+ @assets.version = '1.0'
@assets.debug = false
@assets.compile = true
@assets.digest = false
diff --git a/railties/lib/rails/cli.rb b/railties/lib/rails/cli.rb
index 443d6f47ad..b717b026de 100644
--- a/railties/lib/rails/cli.rb
+++ b/railties/lib/rails/cli.rb
@@ -1,9 +1,12 @@
require 'rbconfig'
-require 'rails/script_rails_loader'
+require 'rails/app_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!
+#
+# TODO: when we hit this, advise adding ./bin to $PATH instead. Then the
+# app's `rails` executable is run immediately.
+Rails::AppRailsLoader.exec_app_rails
require 'rails/ruby_version_check'
Signal.trap("INT") { puts; exit(1) }
diff --git a/railties/lib/rails/commands.rb b/railties/lib/rails/commands.rb
index 3ab2a3809e..aacde52cfc 100644
--- a/railties/lib/rails/commands.rb
+++ b/railties/lib/rails/commands.rb
@@ -24,8 +24,6 @@ The most common rails commands are:
In addition to those, there are:
application Generate the Rails application code
destroy Undo code generated with "generate" (short-cut alias: "d")
- benchmarker See how fast a piece of code runs
- profiler Get profile information from a piece of code
plugin new Generates skeleton for developing a Rails plugin
runner Run a piece of code in the application environment (short-cut alias: "r")
@@ -51,11 +49,6 @@ when 'generate', 'destroy', 'plugin'
require "rails/commands/#{command}"
end
-when 'benchmarker', 'profiler'
- require APP_PATH
- Rails.application.require_environment!
- require "rails/commands/#{command}"
-
when 'console'
require 'rails/commands/console'
options = Rails::Console.parse_arguments(ARGV)
@@ -72,18 +65,18 @@ when 'console'
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
+ # This allows us to run `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|
+ Rails::Server.new.tap do |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
- }
+ end
when 'dbconsole'
require 'rails/commands/dbconsole'
diff --git a/railties/lib/rails/commands/benchmarker.rb b/railties/lib/rails/commands/benchmarker.rb
deleted file mode 100644
index b745b45e17..0000000000
--- a/railties/lib/rails/commands/benchmarker.rb
+++ /dev/null
@@ -1,34 +0,0 @@
-require 'optparse'
-require 'rails/test_help'
-require 'rails/performance_test_help'
-
-ARGV.push('--benchmark') # HAX
-require 'active_support/testing/performance'
-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 }
- opt.on('-o', '--output PATH', String, 'Directory to use when writing the results.', "Default: #{defaults[:output]}") { |o| options[:output] = o }
- 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 #:nodoc:
- self.profile_options = options
-
- ARGV.each do |expression|
- eval <<-RUBY
- def test_#{expression.parameterize('_')}
- #{expression}
- end
- RUBY
- end
-end
diff --git a/railties/lib/rails/commands/console.rb b/railties/lib/rails/commands/console.rb
index aef7600fbd..86ab1aabbf 100644
--- a/railties/lib/rails/commands/console.rb
+++ b/railties/lib/rails/commands/console.rb
@@ -24,11 +24,21 @@ module Rails
if arguments.first && arguments.first[0] != '-'
env = arguments.first
- options[:environment] = %w(production development test).detect {|e| e =~ /^#{env}/} || env
+ if available_environments.include? env
+ options[:environment] = env
+ else
+ options[:environment] = %w(production development test).detect {|e| e =~ /^#{env}/} || env
+ end
end
options
end
+
+ private
+
+ def available_environments
+ Dir['config/environments/*.rb'].map { |fname| File.basename(fname, '.*') }
+ end
end
attr_reader :options, :app, :console
@@ -79,13 +89,11 @@ module Rails
end
def require_debugger
- begin
- require 'debugger'
- puts "=> Debugger enabled"
- rescue Exception
- puts "You're missing the 'debugger' gem. Add it to your Gemfile, bundle, and try again."
- exit
- end
+ require 'debugger'
+ puts "=> Debugger enabled"
+ rescue LoadError
+ puts "You're missing the 'debugger' gem. Add it to your Gemfile, bundle, and try again."
+ exit
end
end
end
diff --git a/railties/lib/rails/commands/dbconsole.rb b/railties/lib/rails/commands/dbconsole.rb
index 4a5674236d..5914c9e4ae 100644
--- a/railties/lib/rails/commands/dbconsole.rb
+++ b/railties/lib/rails/commands/dbconsole.rb
@@ -136,12 +136,20 @@ module Rails
if arguments.first && arguments.first[0] != '-'
env = arguments.first
- options[:environment] = %w(production development test).detect {|e| e =~ /^#{env}/} || env
+ if available_environments.include? env
+ options[:environment] = env
+ else
+ options[:environment] = %w(production development test).detect {|e| e =~ /^#{env}/} || env
+ end
end
options
end
+ def available_environments
+ Dir['config/environments/*.rb'].map { |fname| File.basename(fname, '.*') }
+ end
+
def find_cmd_and_exec(commands, *args)
commands = Array(commands)
diff --git a/railties/lib/rails/commands/profiler.rb b/railties/lib/rails/commands/profiler.rb
deleted file mode 100644
index 315bcccf61..0000000000
--- a/railties/lib/rails/commands/profiler.rb
+++ /dev/null
@@ -1,32 +0,0 @@
-require 'optparse'
-require 'rails/test_help'
-require 'rails/performance_test_help'
-require 'active_support/testing/performance'
-
-def options
- options = {}
- defaults = ActiveSupport::Testing::Performance::DEFAULTS
-
- OptionParser.new do |opt|
- opt.banner = "Usage: rails profiler 'Ruby.code' 'Ruby.more_code' ... [OPTS]"
- opt.on('-r', '--runs N', Numeric, 'Number of runs.', "Default: #{defaults[:runs]}") { |r| options[:runs] = r }
- opt.on('-o', '--output PATH', String, 'Directory to use when writing the results.', "Default: #{defaults[:output]}") { |o| options[:output] = o }
- opt.on('-m', '--metrics a,b,c', Array, 'Metrics to use.', "Default: #{defaults[:metrics].join(",")}") { |m| options[:metrics] = m.map(&:to_sym) }
- 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 #:nodoc:
- self.profile_options = options
-
- ARGV.each do |expression|
- eval <<-RUBY
- def test_#{expression.parameterize('_')}
- #{expression}
- end
- RUBY
- end
-end
diff --git a/railties/lib/rails/commands/runner.rb b/railties/lib/rails/commands/runner.rb
index 6adbdc6e0b..c4622d6a2d 100644
--- a/railties/lib/rails/commands/runner.rb
+++ b/railties/lib/rails/commands/runner.rb
@@ -24,7 +24,7 @@ ARGV.clone.options do |opts|
if RbConfig::CONFIG['host_os'] !~ /mswin|mingw/
opts.separator ""
- opts.separator "You can also use runner as a shebang line for your scripts like this:"
+ opts.separator "You can also use runner as a shebang line for your executables:"
opts.separator "-------------------------------------------------------------"
opts.separator "#!/usr/bin/env #{File.expand_path($0)} runner"
opts.separator ""
diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb
index 725295004f..0ae2f16aba 100644
--- a/railties/lib/rails/engine.rb
+++ b/railties/lib/rails/engine.rb
@@ -175,7 +175,7 @@ module Rails
# There are some places where an Engine's name is used:
#
# * routes: when you mount an Engine with <tt>mount(MyEngine::Engine => '/my_engine')</tt>,
- # it's used as default :as option
+ # it's used as default <tt>:as</tt> option
# * rake task for installing migrations <tt>my_engine:install:migrations</tt>
#
# Engine name is set by default based on class name. For <tt>MyEngine::Engine</tt> it will be
@@ -407,10 +407,8 @@ module Rails
end
end
- self.isolated = false
-
delegate :middleware, :root, :paths, to: :config
- delegate :engine_name, :isolated?, to: "self.class"
+ delegate :engine_name, :isolated?, to: :class
def initialize
@_all_autoload_paths = nil
diff --git a/railties/lib/rails/generators.rb b/railties/lib/rails/generators.rb
index d9a91b74d1..4b767ea0c6 100644
--- a/railties/lib/rails/generators.rb
+++ b/railties/lib/rails/generators.rb
@@ -50,7 +50,6 @@ module Rails
javascripts: true,
javascript_engine: :js,
orm: false,
- performance_tool: nil,
resource_controller: :controller,
resource_route: true,
scaffold_controller: :scaffold_controller,
@@ -179,7 +178,6 @@ module Rails
"#{test}:model",
"#{test}:scaffold",
"#{test}:view",
- "#{test}:performance",
"#{template}:controller",
"#{template}:scaffold",
"#{template}:mailer",
diff --git a/railties/lib/rails/generators/actions.rb b/railties/lib/rails/generators/actions.rb
index b96ee9295e..cb3aca5811 100644
--- a/railties/lib/rails/generators/actions.rb
+++ b/railties/lib/rails/generators/actions.rb
@@ -4,6 +4,10 @@ require 'rbconfig'
module Rails
module Generators
module Actions
+ def initialize(*) # :nodoc:
+ super
+ @in_group = nil
+ end
# Adds an entry into Gemfile for the supplied gem.
#
@@ -186,7 +190,7 @@ module Rails
log :generate, what
argument = args.map {|arg| arg.to_s }.flatten.join(" ")
- in_root { run_ruby_script("script/rails generate #{what} #{argument}", verbose: false) }
+ in_root { run_ruby_script("bin/rails generate #{what} #{argument}", verbose: false) }
end
# Runs the supplied rake task
diff --git a/railties/lib/rails/generators/active_model.rb b/railties/lib/rails/generators/active_model.rb
index 0e51b9c568..6183944bb0 100644
--- a/railties/lib/rails/generators/active_model.rb
+++ b/railties/lib/rails/generators/active_model.rb
@@ -59,8 +59,8 @@ module Rails
end
# PATCH/PUT update
- def update_attributes(params=nil)
- "#{name}.update_attributes(#{params})"
+ def update(params=nil)
+ "#{name}.update(#{params})"
end
# POST create
diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb
index 9b9ae72e18..ca3652c703 100644
--- a/railties/lib/rails/generators/app_base.rb
+++ b/railties/lib/rails/generators/app_base.rb
@@ -28,7 +28,7 @@ module Rails
class_option :skip_gemfile, type: :boolean, default: false,
desc: "Don't create a Gemfile"
- class_option :skip_bundle, type: :boolean, default: false,
+ class_option :skip_bundle, type: :boolean, aliases: '-B', default: false,
desc: "Don't run bundle install"
class_option :skip_git, type: :boolean, aliases: '-G', default: false,
@@ -261,14 +261,7 @@ module Rails
end
def run_bundle
- command = "install --binstubs"
- command << " --shebang ruby-local-exec" if detect_ruby_local_exec
-
- bundle_command(command) unless options[:skip_gemfile] || options[:skip_bundle] || options[:pretend]
- end
-
- def detect_ruby_local_exec
- ENV["PATH"].split(":").find { |path| File.file?(File.join(path, "ruby-local-exec")) }
+ bundle_command('install') unless options[:skip_gemfile] || options[:skip_bundle] || options[:pretend]
end
def empty_directory_with_keep_file(destination, config = {})
diff --git a/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb b/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb
index f5182bcc50..90d8db1df5 100644
--- a/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb
+++ b/railties/lib/rails/generators/erb/scaffold/templates/index.html.erb
@@ -3,9 +3,9 @@
<table>
<thead>
<tr>
- <% attributes.each do |attribute| -%>
+<% attributes.each do |attribute| -%>
<th><%= attribute.human_name %></th>
- <% end -%>
+<% end -%>
<th></th>
<th></th>
<th></th>
@@ -13,13 +13,15 @@
</thead>
<tbody>
- <%%= content_tag_for(:tr, @<%= plural_table_name %>) do |<%= singular_table_name %>| %>
- <% attributes.each do |attribute| -%>
+ <%% @<%= plural_table_name %>.each do |<%= singular_table_name %>| %>
+ <tr>
+<% attributes.each do |attribute| -%>
<td><%%= <%= singular_table_name %>.<%= attribute.name %> %></td>
- <% end -%>
+<% end -%>
<td><%%= link_to 'Show', <%= singular_table_name %> %></td>
<td><%%= link_to 'Edit', edit_<%= singular_table_name %>_path(<%= singular_table_name %>) %></td>
<td><%%= link_to 'Destroy', <%= singular_table_name %>, method: :delete, data: { confirm: 'Are you sure?' } %></td>
+ </tr>
<%% end %>
</tbody>
</table>
diff --git a/railties/lib/rails/generators/rails/app/app_generator.rb b/railties/lib/rails/generators/rails/app/app_generator.rb
index 372790df59..e22be40381 100644
--- a/railties/lib/rails/generators/rails/app/app_generator.rb
+++ b/railties/lib/rails/generators/rails/app/app_generator.rb
@@ -38,7 +38,7 @@ module Rails
end
def readme
- copy_file "README", "README.rdoc"
+ copy_file "README.rdoc", "README.rdoc"
end
def gemfile
@@ -63,6 +63,13 @@ module Rails
keep_file 'app/models/concerns'
end
+ def bin
+ directory "bin" do |content|
+ "#{shebang}\n" + content
+ end
+ chmod "bin", 0755, verbose: false
+ end
+
def config
empty_directory "config"
@@ -85,10 +92,6 @@ module Rails
directory "db"
end
- def doc
- directory "doc"
- end
-
def lib
empty_directory 'lib'
empty_directory_with_keep_file 'lib/tasks'
@@ -103,13 +106,6 @@ module Rails
directory "public", "public", recursive: false
end
- def script
- directory "script" do |content|
- "#{shebang}\n" + content
- end
- chmod "script", 0755, verbose: false
- end
-
def test
empty_directory_with_keep_file 'test/fixtures'
empty_directory_with_keep_file 'test/controllers'
@@ -118,7 +114,6 @@ module Rails
empty_directory_with_keep_file 'test/helpers'
empty_directory_with_keep_file 'test/integration'
- template 'test/performance/browsing_test.rb'
template 'test/test_helper.rb'
end
@@ -145,7 +140,7 @@ module Rails
# We need to store the RAILS_DEV_PATH in a constant, otherwise the path
# can change in Ruby 1.8.7 when we FileUtils.cd.
RAILS_DEV_PATH = File.expand_path("../../../../../..", File.dirname(__FILE__))
- RESERVED_NAMES = %w[application destroy benchmarker profiler plugin runner test]
+ RESERVED_NAMES = %w[application destroy plugin runner test]
class AppGenerator < AppBase # :nodoc:
add_shared_options_for "application"
@@ -178,6 +173,10 @@ module Rails
build(:app)
end
+ def create_bin_files
+ build(:bin)
+ end
+
def create_config_files
build(:config)
end
@@ -195,10 +194,6 @@ module Rails
build(:db)
end
- def create_doc_files
- build(:doc)
- end
-
def create_lib_files
build(:lib)
end
@@ -211,10 +206,6 @@ module Rails
build(:public_directory)
end
- def create_script_files
- build(:script)
- end
-
def create_test_files
build(:test) unless options[:skip_test_unit]
end
diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile
index c4846b2c11..b5db3d2187 100644
--- a/railties/lib/rails/generators/rails/app/templates/Gemfile
+++ b/railties/lib/rails/generators/rails/app/templates/Gemfile
@@ -9,12 +9,12 @@ source 'https://rubygems.org'
<%= assets_gemfile_entry %>
<%= javascript_gemfile_entry -%>
+# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
+gem 'jbuilder', '~> 1.0.1'
+
# To use ActiveModel has_secure_password
# gem 'bcrypt-ruby', '~> 3.0.0'
-# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
-# gem 'jbuilder'
-
# Use unicorn as the app server
# gem 'unicorn'
diff --git a/railties/lib/rails/generators/rails/app/templates/README b/railties/lib/rails/generators/rails/app/templates/README
deleted file mode 100644
index b5d7b6436b..0000000000
--- a/railties/lib/rails/generators/rails/app/templates/README
+++ /dev/null
@@ -1,259 +0,0 @@
-== Welcome to Rails
-
-Rails is a web-application framework that includes everything needed to create
-database-backed web applications according to the Model-View-Control pattern.
-
-This pattern splits the view (also called the presentation) into "dumb"
-templates that are primarily responsible for inserting pre-built data in between
-HTML tags. The model contains the "smart" domain objects (such as Account,
-Product, Person, Post) that holds all the business logic and knows how to
-persist themselves to a database. The controller handles the incoming requests
-(such as Save New Account, Update Product, Show Post) by manipulating the model
-and directing data to the view.
-
-In Rails, the model is handled by what's called an object-relational mapping
-layer entitled Active Record. This layer allows you to present the data from
-database rows as objects and embellish these data objects with business logic
-methods. You can read more about Active Record in
-link:files/vendor/rails/activerecord/README.html.
-
-The controller and view are handled by the Action Pack, which handles both
-layers by its two parts: Action View and Action Controller. These two layers
-are bundled in a single package due to their heavy interdependence. This is
-unlike the relationship between the Active Record and Action Pack that is much
-more separate. Each of these packages can be used independently outside of
-Rails. You can read more about Action Pack in
-link:files/vendor/rails/actionpack/README.html.
-
-
-== Getting Started
-
-1. At the command prompt, create a new Rails application:
- <tt>rails new myapp</tt> (where <tt>myapp</tt> is the application name)
-
-2. Change directory to <tt>myapp</tt> and start the web server:
- <tt>cd myapp; rails server</tt> (run with --help for options)
-
-3. Go to http://localhost:3000/ and you'll see:
- "Welcome aboard: You're riding Ruby on Rails!"
-
-4. Follow the guidelines to start developing your application. You can find
-the following resources handy:
-
-* The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html
-* Ruby on Rails Tutorial Book: http://www.railstutorial.org/
-
-
-== Debugging Rails
-
-Sometimes your application goes wrong. Fortunately there are a lot of tools that
-will help you debug it and get it back on the rails.
-
-First area to check is the application log files. Have "tail -f" commands
-running on the server.log and development.log. Rails will automatically display
-debugging and runtime information to these files. Debugging info will also be
-shown in the browser on requests from 127.0.0.1.
-
-You can also log your own messages directly into the log file from your code
-using the Ruby logger class from inside your controllers. Example:
-
- class WeblogController < ActionController::Base
- def destroy
- @weblog = Weblog.find(params[:id])
- @weblog.destroy
- logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!")
- end
- end
-
-The result will be a message in your log file along the lines of:
-
- Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1!
-
-More information on how to use the logger is at http://www.ruby-doc.org/core/
-
-Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are
-several books available online as well:
-
-* Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe)
-* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide)
-
-These two books will bring you up to speed on the Ruby language and also on
-programming in general.
-
-
-== Debugger
-
-Debugger support is available through the debugger command when you start your
-Mongrel or WEBrick server with --debugger. This means that you can break out of
-execution at any point in the code, investigate and change the model, and then,
-resume execution! You need to install the 'debugger' gem to run the server in debugging
-mode. Add gem 'debugger' to your Gemfile and run <tt>bundle</tt> to install it. Example:
-
- class WeblogController < ActionController::Base
- def index
- @posts = Post.all
- debugger
- end
- end
-
-So the controller will accept the action, run the first line, then present you
-with a IRB prompt in the server window. Here you can do things like:
-
- >> @posts.inspect
- => "[#<Post:0x14a6be8
- @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>,
- #<Post:0x14a6620
- @attributes={"title"=>"Rails", "body"=>"Only ten..", "id"=>"2"}>]"
- >> @posts.first.title = "hello from a debugger"
- => "hello from a debugger"
-
-...and even better, you can examine how your runtime objects actually work:
-
- >> f = @posts.first
- => #<Post:0x13630c4 @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>
- >> f.
- Display all 152 possibilities? (y or n)
-
-Finally, when you're ready to resume execution, you can enter "cont".
-
-
-== Console
-
-The console is a Ruby shell, which allows you to interact with your
-application's domain model. Here you'll have all parts of the application
-configured, just like it is when the application is running. You can inspect
-domain models, change values, and save to the database. Starting the script
-without arguments will launch it in the development environment.
-
-To start the console, run <tt>rails console</tt> from the application
-directory.
-
-Options:
-
-* Passing the <tt>-s, --sandbox</tt> argument will rollback any modifications
- made to the database.
-* Passing an environment name as an argument will load the corresponding
- environment. Example: <tt>rails console production</tt>.
-
-To reload your controllers and models after launching the console run
-<tt>reload!</tt>
-
-More information about irb can be found at:
-link:http://www.rubycentral.org/pickaxe/irb.html
-
-
-== dbconsole
-
-You can go to the command line of your database directly through <tt>rails
-dbconsole</tt>. You would be connected to the database with the credentials
-defined in database.yml. Starting the script without arguments will connect you
-to the development database. Passing an argument will connect you to a different
-database, like <tt>rails dbconsole production</tt>. Currently works for MySQL,
-PostgreSQL and SQLite 3.
-
-== Description of Contents
-
-The default directory structure of a generated Ruby on Rails application:
-
- |-- app
- | |-- assets
- | |-- images
- | |-- javascripts
- | `-- stylesheets
- | |-- controllers
- | |-- helpers
- | |-- mailers
- | |-- models
- | `-- views
- | `-- layouts
- |-- config
- | |-- environments
- | |-- initializers
- | `-- locales
- |-- db
- |-- doc
- |-- lib
- | `-- tasks
- |-- log
- |-- public
- |-- script
- |-- test
- | |-- fixtures
- | |-- functional
- | |-- integration
- | |-- performance
- | `-- unit
- |-- tmp
- | |-- cache
- | |-- pids
- | |-- sessions
- | `-- sockets
- `-- vendor
- |-- assets
- `-- stylesheets
-
-app
- Holds all the code that's specific to this particular application.
-
-app/assets
- Contains subdirectories for images, stylesheets, and JavaScript files.
-
-app/controllers
- Holds controllers that should be named like weblogs_controller.rb for
- automated URL mapping. All controllers should descend from
- ApplicationController which itself descends from ActionController::Base.
-
-app/models
- Holds models that should be named like post.rb. Models descend from
- ActiveRecord::Base by default.
-
-app/views
- Holds the template files for the view that should be named like
- weblogs/index.html.erb for the WeblogsController#index action. All views use
- eRuby syntax by default.
-
-app/views/layouts
- Holds the template files for layouts to be used with views. This models the
- common header/footer method of wrapping views. In your views, define a layout
- using the <tt>layout :default</tt> and create a file named default.html.erb.
- Inside default.html.erb, call <% yield %> to render the view using this
- layout.
-
-app/helpers
- Holds view helpers that should be named like weblogs_helper.rb. These are
- generated for you automatically when using generators for controllers.
- Helpers can be used to wrap functionality for your views into methods.
-
-config
- Configuration files for the Rails environment, the routing map, the database,
- and other dependencies.
-
-db
- Contains the database schema in schema.rb. db/migrate contains all the
- sequence of Migrations for your schema.
-
-doc
- This directory is where your application documentation will be stored when
- generated using <tt>rake doc:app</tt>
-
-lib
- Application specific libraries. Basically, any kind of custom code that
- doesn't belong under controllers, models, or helpers. This directory is in
- the load path.
-
-public
- The directory available for the web server. Also contains the dispatchers and the
- default HTML files. This should be set as the DOCUMENT_ROOT of your web
- server.
-
-script
- Helper scripts for automation and generation.
-
-test
- Unit and functional tests along with fixtures. When using the rails generate
- command, template test files will be generated for you and placed in this
- directory.
-
-vendor
- External libraries that the application depends on. If the app has frozen rails,
- those gems also go here, under vendor/rails/. This directory is in the load path.
diff --git a/railties/lib/rails/generators/rails/app/templates/README.rdoc b/railties/lib/rails/generators/rails/app/templates/README.rdoc
new file mode 100644
index 0000000000..dd4e97e22e
--- /dev/null
+++ b/railties/lib/rails/generators/rails/app/templates/README.rdoc
@@ -0,0 +1,28 @@
+== README
+
+This README would normally document whatever steps are necessary to get the
+application up and running.
+
+Things you may want to cover:
+
+* Ruby version
+
+* System dependencies
+
+* Configuration
+
+* Database creation
+
+* Database initialization
+
+* How to run the test suite
+
+* Services (job queues, cache servers, search engines, etc.)
+
+* Deployment instructions
+
+* ...
+
+
+Please feel free to use a different markup language if you do not plan to run
+<tt>rake doc:app</tt>.
diff --git a/railties/lib/rails/generators/rails/app/templates/app/mailers/.empty_directory b/railties/lib/rails/generators/rails/app/templates/app/mailers/.empty_directory
deleted file mode 100644
index e69de29bb2..0000000000
--- a/railties/lib/rails/generators/rails/app/templates/app/mailers/.empty_directory
+++ /dev/null
diff --git a/railties/lib/rails/generators/rails/app/templates/app/models/.empty_directory b/railties/lib/rails/generators/rails/app/templates/app/models/.empty_directory
deleted file mode 100644
index e69de29bb2..0000000000
--- a/railties/lib/rails/generators/rails/app/templates/app/models/.empty_directory
+++ /dev/null
diff --git a/railties/lib/rails/generators/rails/app/templates/bin/bundle b/railties/lib/rails/generators/rails/app/templates/bin/bundle
new file mode 100644
index 0000000000..e0df7f4440
--- /dev/null
+++ b/railties/lib/rails/generators/rails/app/templates/bin/bundle
@@ -0,0 +1,3 @@
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
+require 'rubygems'
+load Gem.bin_path('bundler', 'bundle')
diff --git a/railties/lib/rails/generators/rails/app/templates/bin/rails b/railties/lib/rails/generators/rails/app/templates/bin/rails
new file mode 100644
index 0000000000..6a128b95e5
--- /dev/null
+++ b/railties/lib/rails/generators/rails/app/templates/bin/rails
@@ -0,0 +1,3 @@
+APP_PATH = File.expand_path('../../config/application', __FILE__)
+require_relative '../config/boot'
+require 'rails/commands'
diff --git a/railties/lib/rails/generators/rails/app/templates/bin/rake b/railties/lib/rails/generators/rails/app/templates/bin/rake
new file mode 100644
index 0000000000..d14fc8395b
--- /dev/null
+++ b/railties/lib/rails/generators/rails/app/templates/bin/rake
@@ -0,0 +1,3 @@
+require_relative '../config/boot'
+require 'rake'
+Rake.application.run
diff --git a/railties/lib/rails/generators/rails/app/templates/config/application.rb b/railties/lib/rails/generators/rails/app/templates/config/application.rb
index 5f15c973c6..f5d7d698a3 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/application.rb
+++ b/railties/lib/rails/generators/rails/app/templates/config/application.rb
@@ -22,21 +22,10 @@ module <%= app_const_base %>
# Custom directories with classes and modules you want to be autoloadable.
# config.autoload_paths += %W(#{config.root}/extras)
+<% if options.skip_sprockets? -%>
- # Configure sensitive parameters which will be filtered from the log file.
- config.filter_parameters += [:password]
-
- # Use SQL instead of Active Record's schema dumper when creating the database.
- # This is necessary if your schema can't be completely dumped by the schema dumper,
- # like if you have constraints or database-specific column types.
- # config.active_record.schema_format = :sql
-
-<% unless options.skip_sprockets? -%>
- # Enable the asset pipeline.
- config.assets.enabled = true
-
- # Version of your assets, change this if you want to expire all your assets.
- config.assets.version = '1.0'
+ # Disable the asset pipeline.
+ config.assets.enabled = false
<% end -%>
end
end
diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml
index 22c9194fad..eb569b7dab 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml
+++ b/railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml
@@ -26,7 +26,7 @@ development:
# domain socket that doesn't need configuration. Windows does not have
# domain sockets, so uncomment these lines.
#host: localhost
-
+
# The TCP port the server listens on. Defaults to 5432.
# If your server runs on a different port number, change accordingly.
#port: 5432
diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml
index b52b733c56..53620dc8e2 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml
+++ b/railties/lib/rails/generators/rails/app/templates/config/databases/sqlserver.yml
@@ -1,5 +1,5 @@
# SQL Server (2005 or higher recommended)
-#
+#
# Install the adapters and driver
# gem install tiny_tds
# gem install activerecord-sqlserver-adapter
@@ -8,8 +8,8 @@
# gem 'tiny_tds'
# gem 'activerecord-sqlserver-adapter'
#
-# You should make sure freetds is configured correctly first.
-# freetds.conf contains host/port/protocol_versions settings.
+# You should make sure freetds is configured correctly first.
+# freetds.conf contains host/port/protocol_versions settings.
# http://freetds.schemamania.org/userguide/freetdsconf.htm
#
# A typical Microsoft server
diff --git a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt
index 68df1d1ec8..0ab91d9864 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt
+++ b/railties/lib/rails/generators/rails/app/templates/config/environments/production.rb.tt
@@ -32,6 +32,9 @@
# Generate digests for assets URLs.
config.assets.digest = true
+
+ # Version of your assets, change this if you want to expire all your assets.
+ config.assets.version = '1.0'
<%- end -%>
# Specifies the header that your server uses for sending files.
diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb b/railties/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb
new file mode 100644
index 0000000000..4a994e1e7b
--- /dev/null
+++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/filter_parameter_logging.rb
@@ -0,0 +1,4 @@
+# Be sure to restart your server when you modify this file.
+
+# Configure sensitive parameters which will be filtered from the log file.
+Rails.application.config.filter_parameters += [:password]
diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/inflections.rb b/railties/lib/rails/generators/rails/app/templates/config/initializers/inflections.rb
index 9262c3379f..ac033bf9dc 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/initializers/inflections.rb
+++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/inflections.rb
@@ -9,7 +9,7 @@
# inflect.irregular 'person', 'people'
# inflect.uncountable %w( fish sheep )
# end
-#
+
# These inflection rules are supported but not enabled by default:
# ActiveSupport::Inflector.inflections(:en) do |inflect|
# inflect.acronym 'RESTful'
diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/locale.rb b/railties/lib/rails/generators/rails/app/templates/config/initializers/locale.rb
index a8285f88ca..d89dac7c6a 100644
--- a/railties/lib/rails/generators/rails/app/templates/config/initializers/locale.rb
+++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/locale.rb
@@ -1,3 +1,5 @@
+# Be sure to restart your server when you modify this file.
+
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
# Rails.application.config.time_zone = 'Central Time (US & Canada)'
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 280f777cc0..4f1d56cd2f 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,5 +1,5 @@
# Be sure to restart your server when you modify this file.
-#
+
# This file contains settings for ActionController::ParamsWrapper which
# is enabled by default.
diff --git a/railties/lib/rails/generators/rails/app/templates/doc/README_FOR_APP b/railties/lib/rails/generators/rails/app/templates/doc/README_FOR_APP
deleted file mode 100644
index fe41f5cc24..0000000000
--- a/railties/lib/rails/generators/rails/app/templates/doc/README_FOR_APP
+++ /dev/null
@@ -1,2 +0,0 @@
-Use this README file to introduce your application and point to useful places in the API for learning more.
-Run "rake doc:app" to generate API documentation for your models, controllers, helpers, and libraries.
diff --git a/railties/lib/rails/generators/rails/app/templates/gitignore b/railties/lib/rails/generators/rails/app/templates/gitignore
index 52abb32479..25a742dff0 100644
--- a/railties/lib/rails/generators/rails/app/templates/gitignore
+++ b/railties/lib/rails/generators/rails/app/templates/gitignore
@@ -4,7 +4,7 @@
# or operating system, you probably want to add a global ignore instead:
# git config --global core.excludesfile '~/.gitignore_global'
-# Ignore bundler config
+# Ignore bundler config.
/.bundle
# Ignore the default SQLite database.
diff --git a/railties/lib/rails/generators/rails/app/templates/public/stylesheets/.empty_directory b/railties/lib/rails/generators/rails/app/templates/public/stylesheets/.empty_directory
deleted file mode 100644
index e69de29bb2..0000000000
--- a/railties/lib/rails/generators/rails/app/templates/public/stylesheets/.empty_directory
+++ /dev/null
diff --git a/railties/lib/rails/generators/rails/app/templates/script/rails b/railties/lib/rails/generators/rails/app/templates/script/rails
deleted file mode 100644
index 11bc1edde9..0000000000
--- a/railties/lib/rails/generators/rails/app/templates/script/rails
+++ /dev/null
@@ -1,5 +0,0 @@
-# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.
-
-APP_PATH = File.expand_path('../../config/application', __FILE__)
-require File.expand_path('../../config/boot', __FILE__)
-require 'rails/commands'
diff --git a/railties/lib/rails/generators/rails/app/templates/test/fixtures/.empty_directory b/railties/lib/rails/generators/rails/app/templates/test/fixtures/.empty_directory
deleted file mode 100644
index e69de29bb2..0000000000
--- a/railties/lib/rails/generators/rails/app/templates/test/fixtures/.empty_directory
+++ /dev/null
diff --git a/railties/lib/rails/generators/rails/app/templates/test/functional/.empty_directory b/railties/lib/rails/generators/rails/app/templates/test/functional/.empty_directory
deleted file mode 100644
index e69de29bb2..0000000000
--- a/railties/lib/rails/generators/rails/app/templates/test/functional/.empty_directory
+++ /dev/null
diff --git a/railties/lib/rails/generators/rails/app/templates/test/integration/.empty_directory b/railties/lib/rails/generators/rails/app/templates/test/integration/.empty_directory
deleted file mode 100644
index e69de29bb2..0000000000
--- a/railties/lib/rails/generators/rails/app/templates/test/integration/.empty_directory
+++ /dev/null
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
deleted file mode 100644
index d09ce5ad34..0000000000
--- a/railties/lib/rails/generators/rails/app/templates/test/performance/browsing_test.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-require 'test_helper'
-require 'rails/performance_test_help'
-
-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] }
-
- test "homepage" do
- get '/'
- end
-end
diff --git a/railties/lib/rails/generators/rails/app/templates/test/unit/.empty_directory b/railties/lib/rails/generators/rails/app/templates/test/unit/.empty_directory
deleted file mode 100644
index e69de29bb2..0000000000
--- a/railties/lib/rails/generators/rails/app/templates/test/unit/.empty_directory
+++ /dev/null
diff --git a/railties/lib/rails/generators/rails/controller/USAGE b/railties/lib/rails/generators/rails/controller/USAGE
index 9def4af65c..64239ad599 100644
--- a/railties/lib/rails/generators/rails/controller/USAGE
+++ b/railties/lib/rails/generators/rails/controller/USAGE
@@ -6,7 +6,7 @@ Description:
path like 'parent_module/controller_name'.
This generates a controller class in app/controllers and invokes helper,
- template engine and test framework generators.
+ template engine, assets, and test framework generators.
Example:
`rails generate controller CreditCards open debit credit close`
diff --git a/railties/lib/rails/generators/rails/migration/USAGE b/railties/lib/rails/generators/rails/migration/USAGE
index f340ed97f2..baf3d9894f 100644
--- a/railties/lib/rails/generators/rails/migration/USAGE
+++ b/railties/lib/rails/generators/rails/migration/USAGE
@@ -20,3 +20,16 @@ Example:
add_column :posts, :title, :string
add_column :posts, :body, :text
add_column :posts, :published, :boolean
+
+Migration names containing JoinTable will generate join tables for use with
+has_and_belongs_to_many associations.
+
+Example:
+ `rails g migration CreateMediaJoinTable artists musics:uniq`
+
+ will create the migration
+
+ create_join_table :artists, :musics do |t|
+ # t.index [:artist_id, :music_id]
+ t.index [:music_id, :artist_id], unique: true
+ end
diff --git a/railties/lib/rails/generators/rails/model/USAGE b/railties/lib/rails/generators/rails/model/USAGE
index e29e19490e..6574200fbf 100644
--- a/railties/lib/rails/generators/rails/model/USAGE
+++ b/railties/lib/rails/generators/rails/model/USAGE
@@ -21,12 +21,12 @@ Description:
Available field types:
- Just after the field name you can specify a type like text or boolean.
+ Just after the field name you can specify a type like text or boolean.
It will generate the column with the associated SQL type. For instance:
`rails generate model post title:string body:text`
- will generate a title column with a varchar type and a body column with a text
+ will generate a title column with a varchar type and a body column with a text
type. You can use the following types:
integer
@@ -57,16 +57,16 @@ Available field types:
limit Set the maximum size of the field giving a number between curly braces
default Set a default value for the field
- precision Defines the precision for the decimal fields
+ precision Defines the precision for the decimal fields
scale Defines the scale for the decimal fields
- uniq Defines the field values as unique
+ uniq Defines the field values as unique
index Will add an index on the field
Examples:
`rails generate model user pseudo:string{30}`
`rails generate model user pseudo:string:uniq`
-
+
Examples:
`rails generate model account`
@@ -76,7 +76,7 @@ Examples:
Model: app/models/account.rb
Test: test/models/account_test.rb
Fixtures: test/fixtures/accounts.yml
- Migration: db/migrate/XXX_add_accounts.rb
+ Migration: db/migrate/XXX_create_accounts.rb
`rails generate model post title:string body:text published:boolean`
@@ -90,5 +90,5 @@ Examples:
Model: app/models/admin/account.rb
Test: test/models/admin/account_test.rb
Fixtures: test/fixtures/admin/accounts.yml
- Migration: db/migrate/XXX_add_admin_accounts.rb
+ Migration: db/migrate/XXX_create_admin_accounts.rb
diff --git a/railties/lib/rails/generators/rails/performance_test/USAGE b/railties/lib/rails/generators/rails/performance_test/USAGE
deleted file mode 100644
index 9dc799559c..0000000000
--- a/railties/lib/rails/generators/rails/performance_test/USAGE
+++ /dev/null
@@ -1,10 +0,0 @@
-Description:
- Stubs out a new performance test. Pass the name of the test, either
- CamelCased or under_scored, as an argument.
-
- This generator invokes the current performance tool, which defaults to
- TestUnit.
-
-Example:
- `rails generate performance_test GeneralStories` creates a GeneralStories
- performance test in test/performance/general_stories_test.rb
diff --git a/railties/lib/rails/generators/rails/performance_test/performance_test_generator.rb b/railties/lib/rails/generators/rails/performance_test/performance_test_generator.rb
deleted file mode 100644
index 56cd562f3d..0000000000
--- a/railties/lib/rails/generators/rails/performance_test/performance_test_generator.rb
+++ /dev/null
@@ -1,7 +0,0 @@
-module Rails
- module Generators
- class PerformanceTestGenerator < NamedBase # :nodoc:
- hook_for :performance_tool, as: :performance
- end
- end
-end
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 48ce3e86a1..af00748037 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
@@ -53,13 +53,11 @@ module Rails
template "lib/%name%.rb"
template "lib/tasks/%name%_tasks.rake"
template "lib/%name%/version.rb"
- if full?
- template "lib/%name%/engine.rb"
- end
+ template "lib/%name%/engine.rb" if engine?
end
def config
- template "config/routes.rb" if full?
+ template "config/routes.rb" if engine?
end
def test
@@ -70,7 +68,7 @@ module Rails
task default: :test
EOF
- if full?
+ if engine?
template "test/integration/navigation_test.rb"
end
end
@@ -132,13 +130,13 @@ task default: :test
end
end
- def script(force = false)
- return unless full?
+ def bin(force = false)
+ return unless engine?
- directory "script", force: force do |content|
+ directory "bin", force: force do |content|
"#{shebang}\n" + content
end
- chmod "script", 0755, verbose: false
+ chmod "bin", 0755, verbose: false
end
def gemfile_entry
@@ -175,7 +173,7 @@ task default: :test
"skip adding entry to Gemfile"
def initialize(*args)
- raise Error, "Options should be given after the plugin name. For details run: rails plugin --help" if args[0].blank?
+ raise Error, "Options should be given after the plugin name. For details run: rails plugin new --help" if args[0].blank?
@dummy_path = nil
super
@@ -216,8 +214,8 @@ task default: :test
build(:images)
end
- def create_script_files
- build(:script)
+ def create_bin_files
+ build(:bin)
end
def create_test_files
@@ -266,13 +264,17 @@ task default: :test
store_application_definition!
build(:test_dummy_config)
build(:test_dummy_clean)
- # ensure that script/rails has proper dummy_path
- build(:script, true)
+ # ensure that bin/rails has proper dummy_path
+ build(:bin, true)
end
end
+ def engine?
+ full? || mountable?
+ end
+
def full?
- options[:full] || options[:mountable]
+ options[:full]
end
def mountable?
diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec b/railties/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec
index 568ed653b7..e956d13d8a 100644
--- a/railties/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec
+++ b/railties/lib/rails/generators/rails/plugin_new/templates/%name%.gemspec
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
<% end -%>
<%= '# ' if options.dev? || options.edge? -%>s.add_dependency "rails", "~> <%= Rails::VERSION::STRING %>"
-<% if full? && !options[:skip_javascript] -%>
+<% if engine? && !options[:skip_javascript] -%>
# s.add_dependency "<%= "#{options[:javascript]}-rails" %>"
<% end -%>
<% unless options[:skip_active_record] -%>
diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile b/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile
index d69f943a72..a8b5bfaf3f 100644
--- a/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile
+++ b/railties/lib/rails/generators/rails/plugin_new/templates/Gemfile
@@ -2,7 +2,7 @@ source "https://rubygems.org"
<% if options[:skip_gemspec] -%>
<%= '# ' if options.dev? || options.edge? -%>gem "rails", "~> <%= Rails::VERSION::STRING %>"
-<% if full? && !options[:skip_javascript] -%>
+<% if engine? && !options[:skip_javascript] -%>
# gem "<%= "#{options[:javascript]}-rails" %>"
<% end -%>
<% else -%>
diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile b/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile
index 65a5bae712..0ba899176c 100644
--- a/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile
+++ b/railties/lib/rails/generators/rails/plugin_new/templates/Rakefile
@@ -14,7 +14,7 @@ RDoc::Task.new(:rdoc) do |rdoc|
rdoc.rdoc_files.include('lib/**/*.rb')
end
-<% if full? && !options[:skip_active_record] && with_dummy_app? -%>
+<% if engine? && !options[:skip_active_record] && with_dummy_app? -%>
APP_RAKEFILE = File.expand_path("../<%= dummy_path -%>/Rakefile", __FILE__)
load 'rails/tasks/engine.rake'
<% end %>
diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/script/rails.tt b/railties/lib/rails/generators/rails/plugin_new/templates/bin/rails.tt
index aa87d1b50c..aa87d1b50c 100644
--- a/railties/lib/rails/generators/rails/plugin_new/templates/script/rails.tt
+++ b/railties/lib/rails/generators/rails/plugin_new/templates/bin/rails.tt
diff --git a/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb b/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb
index 2d3bdc510c..40c074cced 100644
--- a/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb
+++ b/railties/lib/rails/generators/rails/plugin_new/templates/lib/%name%.rb
@@ -1,4 +1,4 @@
-<% if full? -%>
+<% if engine? -%>
require "<%= name %>/engine"
<% end -%>
diff --git a/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb b/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb
index dd636ed3cf..36589d65e2 100644
--- a/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb
+++ b/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb
@@ -9,13 +9,8 @@ module Rails
class_option :stylesheets, type: :boolean, desc: "Generate Stylesheets"
class_option :stylesheet_engine, desc: "Engine for Stylesheets"
- class_option :html, type: :boolean, default: true,
- desc: "Generate a scaffold with HTML output"
-
def handle_skip
- if !options[:html] || !options[:stylesheets]
- @options = @options.merge(stylesheet_engine: false)
- end
+ @options = @options.merge(stylesheet_engine: false) unless options[:stylesheets]
end
hook_for :scaffold_controller, required: true
diff --git a/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb b/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb
index 32fa54a362..4f36b612ae 100644
--- a/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb
+++ b/railties/lib/rails/generators/rails/scaffold_controller/scaffold_controller_generator.rb
@@ -10,17 +10,8 @@ module Rails
class_option :orm, banner: "NAME", type: :string, required: true,
desc: "ORM to generate the controller for"
- class_option :html, type: :boolean, default: true,
- desc: "Generate a scaffold with HTML output"
-
argument :attributes, type: :array, default: [], banner: "field:type field:type"
- def handle_skip
- unless options[:html]
- @options = @options.merge(template_engine: false, helper: false)
- end
- end
-
def create_controller_files
template "controller.rb", File.join('app/controllers', class_path, "#{controller_file_name}_controller.rb")
end
diff --git a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb
index 4baad85e9e..e813437d75 100644
--- a/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb
+++ b/railties/lib/rails/generators/rails/scaffold_controller/templates/controller.rb
@@ -7,95 +7,47 @@ class <%= controller_class_name %>Controller < ApplicationController
before_action :set_<%= singular_table_name %>, only: [:show, :edit, :update, :destroy]
# GET <%= route_url %>
- # GET <%= route_url %>.json
def index
@<%= plural_table_name %> = <%= orm_class.all(class_name) %>
-
- respond_to do |format|
- <%- if options[:html] -%>
- format.html # index.html.erb
- <%- end -%>
- format.json { render json: <%= "@#{plural_table_name}" %> }
- end
end
# GET <%= route_url %>/1
- # GET <%= route_url %>/1.json
def show
- respond_to do |format|
- <%- if options[:html] -%>
- format.html # show.html.erb
- <%- end -%>
- format.json { render json: <%= "@#{singular_table_name}" %> }
- end
end
- <%- if options[:html] -%>
# GET <%= route_url %>/new
- # GET <%= route_url %>/new.json
def new
@<%= singular_table_name %> = <%= orm_class.build(class_name) %>
-
- respond_to do |format|
- format.html # new.html.erb
- format.json { render json: <%= "@#{singular_table_name}" %> }
- end
end
# GET <%= route_url %>/1/edit
def edit
end
- <%- end -%>
# POST <%= route_url %>
- # POST <%= route_url %>.json
def create
@<%= singular_table_name %> = <%= orm_class.build(class_name, "#{singular_table_name}_params") %>
- respond_to do |format|
- if @<%= orm_instance.save %>
- <%- if options[:html] -%>
- format.html { redirect_to @<%= singular_table_name %>, notice: <%= "'#{human_name} was successfully created.'" %> }
- <%- end -%>
- format.json { render json: <%= "@#{singular_table_name}" %>, status: :created, location: <%= "@#{singular_table_name}" %> }
- else
- <%- if options[:html] -%>
- format.html { render action: "new" }
- <%- end -%>
- format.json { render json: <%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity }
- end
+ if @<%= orm_instance.save %>
+ redirect_to @<%= singular_table_name %>, notice: <%= "'#{human_name} was successfully created.'" %>
+ else
+ render action: 'new'
end
end
# PATCH/PUT <%= route_url %>/1
- # PATCH/PUT <%= route_url %>/1.json
def update
- respond_to do |format|
- if @<%= orm_instance.update_attributes("#{singular_table_name}_params") %>
- <%- if options[:html] -%>
- format.html { redirect_to @<%= singular_table_name %>, notice: <%= "'#{human_name} was successfully updated.'" %> }
- <%- end -%>
- format.json { head :no_content }
- else
- <%- if options[:html] -%>
- format.html { render action: "edit" }
- <%- end -%>
- format.json { render json: <%= "@#{orm_instance.errors}" %>, status: :unprocessable_entity }
- end
+ if @<%= orm_instance.update("#{singular_table_name}_params") %>
+ redirect_to @<%= singular_table_name %>, notice: <%= "'#{human_name} was successfully updated.'" %>
+ else
+ render action: 'edit'
end
end
# DELETE <%= route_url %>/1
- # DELETE <%= route_url %>/1.json
def destroy
@<%= orm_instance.destroy %>
-
- respond_to do |format|
- <%- if options[:html] -%>
- format.html { redirect_to <%= index_helper %>_url }
- <%- end -%>
- format.json { head :no_content }
- end
+ redirect_to <%= index_helper %>_url
end
private
@@ -104,11 +56,7 @@ class <%= controller_class_name %>Controller < ApplicationController
@<%= singular_table_name %> = <%= orm_class.find(class_name, "params[:id]") %>
end
- # Use this method to whitelist the permissible parameters. Example:
- # params.require(:person).permit(:name, :age)
- #
- # Also, you can specialize this method with per-user checking of permissible
- # attributes.
+ # Never trust parameters from the scary internet, only allow the white list through.
def <%= "#{singular_table_name}_params" %>
<%- if attributes_names.empty? -%>
params[<%= ":#{singular_table_name}" %>]
diff --git a/railties/lib/rails/generators/test_unit/performance/performance_generator.rb b/railties/lib/rails/generators/test_unit/performance/performance_generator.rb
deleted file mode 100644
index 5552edeee4..0000000000
--- a/railties/lib/rails/generators/test_unit/performance/performance_generator.rb
+++ /dev/null
@@ -1,13 +0,0 @@
-require 'rails/generators/test_unit'
-
-module TestUnit # :nodoc:
- module Generators # :nodoc:
- class PerformanceGenerator < Base # :nodoc:
- check_class_collision suffix: "Test"
-
- def create_test_files
- template 'performance_test.rb', File.join('test/performance', class_path, "#{file_name}_test.rb")
- end
- end
- end
-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
deleted file mode 100644
index 2bcb482d68..0000000000
--- a/railties/lib/rails/generators/test_unit/performance/templates/performance_test.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-require 'test_helper'
-require 'rails/performance_test_help'
-
-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] }
-
- test "homepage" do
- get '/'
- end
-end
diff --git a/railties/lib/rails/generators/test_unit/plugin/templates/test_helper.rb b/railties/lib/rails/generators/test_unit/plugin/templates/test_helper.rb
index c9af2ca832..30a861f09d 100644
--- a/railties/lib/rails/generators/test_unit/plugin/templates/test_helper.rb
+++ b/railties/lib/rails/generators/test_unit/plugin/templates/test_helper.rb
@@ -1,2 +1,2 @@
-require 'minitest/autorun'
+require 'active_support/testing/autorun'
require 'active_support'
diff --git a/railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb b/railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb
index 30e1650555..18bd1ece9d 100644
--- a/railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb
+++ b/railties/lib/rails/generators/test_unit/scaffold/templates/functional_test.rb
@@ -36,7 +36,7 @@ class <%= controller_class_name %>ControllerTest < ActionController::TestCase
end
test "should update <%= singular_table_name %>" do
- put :update, id: <%= "@#{singular_table_name}" %>, <%= "#{singular_table_name}: { #{attributes_hash} }" %>
+ patch :update, id: <%= "@#{singular_table_name}" %>, <%= "#{singular_table_name}: { #{attributes_hash} }" %>
assert_redirected_to <%= singular_table_name %>_path(assigns(:<%= singular_table_name %>))
end
diff --git a/railties/lib/rails/info_controller.rb b/railties/lib/rails/info_controller.rb
index e650f58d20..fa5668a5b5 100644
--- a/railties/lib/rails/info_controller.rb
+++ b/railties/lib/rails/info_controller.rb
@@ -3,12 +3,12 @@ require 'action_dispatch/routing/inspector'
class Rails::InfoController < ActionController::Base # :nodoc:
self.view_paths = File.expand_path('../templates', __FILE__)
prepend_view_path ActionDispatch::DebugExceptions::RESCUES_TEMPLATE_PATH
- layout 'application'
+ layout -> { request.xhr? ? nil : 'application' }
before_filter :require_local!
def index
- redirect_to '/rails/info/routes'
+ redirect_to action: :routes
end
def properties
@@ -16,7 +16,7 @@ class Rails::InfoController < ActionController::Base # :nodoc:
end
def routes
- @routes = ActionDispatch::Routing::RoutesInspector.new.collect_routes(_routes.routes)
+ @routes_inspector = ActionDispatch::Routing::RoutesInspector.new(_routes.routes)
end
protected
diff --git a/railties/lib/rails/paths.rb b/railties/lib/rails/paths.rb
index 8af4130e87..de6795eda2 100644
--- a/railties/lib/rails/paths.rb
+++ b/railties/lib/rails/paths.rb
@@ -55,9 +55,9 @@ module Rails
add(path, with: value, glob: glob)
end
- def add(path, options={})
- with = options[:with] || path
- @root[path] = Path.new(self, path, [with].flatten, options)
+ def add(path, options = {})
+ with = Array(options.fetch(:with, path))
+ @root[path] = Path.new(self, path, with, options)
end
def [](path)
@@ -189,9 +189,9 @@ module Rails
path = File.expand_path(p, @root.path)
if @glob && File.directory?(path)
- result.concat Dir.chdir(path) {
- Dir.glob(@glob).map { |file| File.join path, file }.sort
- }
+ Dir.chdir(path) do
+ result.concat(Dir.glob(@glob).map { |file| File.join path, file }.sort)
+ end
else
result << path
end
diff --git a/railties/lib/rails/performance_test_help.rb b/railties/lib/rails/performance_test_help.rb
deleted file mode 100644
index b1285efde2..0000000000
--- a/railties/lib/rails/performance_test_help.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-ActionController::Base.perform_caching = true
-ActiveSupport::Dependencies.mechanism = :require
-Rails.logger.level = ActiveSupport::Logger::INFO
diff --git a/railties/lib/rails/rack/logger.rb b/railties/lib/rails/rack/logger.rb
index 7be2333981..6ed6722c44 100644
--- a/railties/lib/rails/rack/logger.rb
+++ b/railties/lib/rails/rack/logger.rb
@@ -1,19 +1,24 @@
require 'active_support/core_ext/time/conversions'
require 'active_support/core_ext/object/blank'
+require 'active_support/log_subscriber'
+require 'action_dispatch/http/request'
+require 'rack/body_proxy'
module Rails
module Rack
# Sets log tags, logs the request, calls the app, and flushes the logs.
class Logger < ActiveSupport::LogSubscriber
def initialize(app, taggers = nil)
- @app, @taggers = app, taggers || []
+ @app = app
+ @taggers = taggers || []
+ @instrumenter = ActiveSupport::Notifications.instrumenter
end
def call(env)
request = ActionDispatch::Request.new(env)
- if Rails.logger.respond_to?(:tagged)
- Rails.logger.tagged(compute_tags(request)) { call_app(request, env) }
+ if logger.respond_to?(:tagged)
+ logger.tagged(compute_tags(request)) { call_app(request, env) }
else
call_app(request, env)
end
@@ -23,13 +28,19 @@ module Rails
def call_app(request, env)
# Put some space between requests in development logs.
- if Rails.env.development?
- Rails.logger.debug ''
- Rails.logger.debug ''
+ if development?
+ logger.debug ''
+ logger.debug ''
end
- Rails.logger.info started_request_message(request)
- @app.call(env)
+ @instrumenter.start 'action_dispatch.request', request: request
+ logger.info started_request_message(request)
+ resp = @app.call(env)
+ resp[2] = ::Rack::BodyProxy.new(resp[2]) { finish(request) }
+ resp
+ rescue
+ finish(request)
+ raise
ensure
ActiveSupport::LogSubscriber.flush_all!
end
@@ -55,6 +66,20 @@ module Rails
end
end
end
+
+ private
+
+ def finish(request)
+ @instrumenter.finish 'action_dispatch.request', request: request
+ end
+
+ def development?
+ Rails.env.development?
+ end
+
+ def logger
+ Rails.logger
+ end
end
end
end
diff --git a/railties/lib/rails/railtie.rb b/railties/lib/rails/railtie.rb
index 5b454e7f20..9437e9c406 100644
--- a/railties/lib/rails/railtie.rb
+++ b/railties/lib/rails/railtie.rb
@@ -172,7 +172,7 @@ module Rails
end
end
- delegate :railtie_name, to: "self.class"
+ delegate :railtie_name, to: :class
def config
@config ||= Railtie::Configuration.new
diff --git a/railties/lib/rails/script_rails_loader.rb b/railties/lib/rails/script_rails_loader.rb
deleted file mode 100644
index 7054089614..0000000000
--- a/railties/lib/rails/script_rails_loader.rb
+++ /dev/null
@@ -1,29 +0,0 @@
-require 'pathname'
-
-module Rails
- module ScriptRailsLoader
- RUBY = File.join(*RbConfig::CONFIG.values_at("bindir", "ruby_install_name")) + RbConfig::CONFIG["EXEEXT"]
- SCRIPT_RAILS = File.join('script', 'rails')
-
- 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
-
- def self.in_rails_application?
- File.exists?(SCRIPT_RAILS)
- 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
- end
-end \ No newline at end of file
diff --git a/railties/lib/rails/source_annotation_extractor.rb b/railties/lib/rails/source_annotation_extractor.rb
index ac806e8006..971fbf627b 100644
--- a/railties/lib/rails/source_annotation_extractor.rb
+++ b/railties/lib/rails/source_annotation_extractor.rb
@@ -15,7 +15,7 @@
class SourceAnnotationExtractor
class Annotation < Struct.new(:line, :tag, :text)
def self.directories
- @@directories ||= %w(app config db lib script test) + (ENV['SOURCE_ANNOTATION_DIRECTORIES'] || '').split(',')
+ @@directories ||= %w(app config db lib test) + (ENV['SOURCE_ANNOTATION_DIRECTORIES'] || '').split(',')
end
# Returns a representation of the annotation that looks like this:
@@ -31,11 +31,11 @@ class SourceAnnotationExtractor
end
end
- # Prints all annotations with tag +tag+ under the root directories +app+, +config+, +lib+,
- # +script+, and +test+ (recursively). Filenames with extension
+ # Prints all annotations with tag +tag+ under the root directories +app+,
+ # +config+, +lib+, and +test+ (recursively). Filenames with extension
# +.builder+, +.rb+, +.erb+, +.haml+, +.slim+, +.css+, +.scss+, +.js+,
- # +.coffee+, and +.rake+ are taken into account. The +options+ hash is passed to each
- # annotation's +to_s+.
+ # +.coffee+, and +.rake+ are taken into account. The +options+ hash is
+ # passed to each annotation's +to_s+.
#
# This class method is the single entry point for the rake tasks.
def self.enumerate(tag, options={})
diff --git a/railties/lib/rails/tasks/documentation.rake b/railties/lib/rails/tasks/documentation.rake
index 2851ca4189..ea6c074bdc 100644
--- a/railties/lib/rails/tasks/documentation.rake
+++ b/railties/lib/rails/tasks/documentation.rake
@@ -45,7 +45,7 @@ namespace :doc do
rdoc.title = ENV['title'] || "Rails Application Documentation"
rdoc.options << '--line-numbers'
rdoc.options << '--charset' << 'utf-8'
- rdoc.rdoc_files.include('doc/README_FOR_APP')
+ rdoc.rdoc_files.include('README.rdoc')
rdoc.rdoc_files.include('app/**/*.rb')
rdoc.rdoc_files.include('lib/**/*.rb')
}
@@ -57,7 +57,10 @@ namespace :doc do
rdoc.template = "#{ENV['template']}.rb" if ENV['template']
rdoc.title = "Rails Framework Documentation"
rdoc.options << '--line-numbers'
- rdoc.rdoc_files.include('README.rdoc')
+
+ gem_path('rails') do |rails|
+ rdoc.options << '-m' << "#{rails}/README.rdoc"
+ end
gem_path('actionmailer') do |actionmailer|
%w(README.rdoc CHANGELOG.md MIT-LICENSE lib/action_mailer/base.rb).each do |file|
diff --git a/railties/lib/rails/tasks/framework.rake b/railties/lib/rails/tasks/framework.rake
index 50499304cb..2116330b45 100644
--- a/railties/lib/rails/tasks/framework.rake
+++ b/railties/lib/rails/tasks/framework.rake
@@ -1,6 +1,6 @@
namespace :rails do
- desc "Update configs and some other initially generated files (or use just update:configs, update:scripts, or update:application_controller)"
- task update: [ "update:configs", "update:scripts", "update:application_controller" ]
+ desc "Update configs and some other initially generated files (or use just update:configs, update:bin, or update:application_controller)"
+ task update: [ "update:configs", "update:bin", "update:application_controller" ]
desc "Applies the template supplied by LOCATION=(/path/to/template) or URL"
task :template do
@@ -58,9 +58,9 @@ namespace :rails do
invoke_from_app_generator :create_config_files
end
- # desc "Adds new scripts to the application script/ directory"
- task :scripts do
- invoke_from_app_generator :create_script_files
+ # desc "Adds new executables to the application bin/ directory"
+ task :bin do
+ invoke_from_app_generator :create_bin_files
end
# desc "Rename application.rb to application_controller.rb"
diff --git a/railties/lib/rails/tasks/routes.rake b/railties/lib/rails/tasks/routes.rake
index 676b475640..1815c2fdc7 100644
--- a/railties/lib/rails/tasks/routes.rake
+++ b/railties/lib/rails/tasks/routes.rake
@@ -2,6 +2,6 @@ desc 'Print out all defined routes in match order, with names. Target specific c
task routes: :environment do
all_routes = Rails.application.routes.routes
require 'action_dispatch/routing/inspector'
- inspector = ActionDispatch::Routing::RoutesInspector.new
- puts inspector.format(all_routes, ENV['CONTROLLER']).join "\n"
+ inspector = ActionDispatch::Routing::RoutesInspector.new(all_routes)
+ puts inspector.format(ActionDispatch::Routing::ConsoleFormatter.new, ENV['CONTROLLER'])
end
diff --git a/railties/lib/rails/templates/layouts/application.html.erb b/railties/lib/rails/templates/layouts/application.html.erb
index 53276d3e7c..7352d48e7b 100644
--- a/railties/lib/rails/templates/layouts/application.html.erb
+++ b/railties/lib/rails/templates/layouts/application.html.erb
@@ -22,6 +22,10 @@
a { color: #000; }
a:visited { color: #666; }
a:hover { color: #fff; background-color:#000; }
+
+ h2 { padding-left: 10px; }
+
+ <%= yield :style %>
</style>
</head>
<body>
diff --git a/railties/lib/rails/templates/rails/info/routes.html.erb b/railties/lib/rails/templates/rails/info/routes.html.erb
index 1ea387c63f..2d8a190986 100644
--- a/railties/lib/rails/templates/rails/info/routes.html.erb
+++ b/railties/lib/rails/templates/rails/info/routes.html.erb
@@ -6,7 +6,4 @@
Routes match in priority from top to bottom
</p>
-<%# actionpack/lib/action_dispatch/middleware/templates %>
-<%= render layout: "routes/route_wrapper" do %>
- <%= render partial: "routes/route", collection: @routes %>
-<% end %>
+<%= @routes_inspector.format(ActionDispatch::Routing::HtmlTableFormatter.new(self)) %>
diff --git a/railties/lib/rails/templates/rails/welcome/index.html.erb b/railties/lib/rails/templates/rails/welcome/index.html.erb
index 9a62d206dc..e239e1695e 100644
--- a/railties/lib/rails/templates/rails/welcome/index.html.erb
+++ b/railties/lib/rails/templates/rails/welcome/index.html.erb
@@ -59,7 +59,7 @@
#header {
- background-image: url("assets/rails.png");
+ background-image: url("/assets/rails.png");
background-repeat: no-repeat;
background-position: top left;
height: 64px;
@@ -173,15 +173,18 @@
</style>
<script>
function about() {
- info = document.getElementById('about-content');
- if (window.XMLHttpRequest)
- { xhr = new XMLHttpRequest(); }
- else
- { xhr = new ActiveXObject("Microsoft.XMLHTTP"); }
- xhr.open("GET","rails/info/properties",false);
- xhr.send("");
- info.innerHTML = xhr.responseText;
- info.style.display = 'block'
+ var info = document.getElementById('about-content'),
+ xhr;
+
+ if (info.innerHTML === '') {
+ xhr = new XMLHttpRequest();
+ xhr.open("GET", "/rails/info/properties", false);
+ xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
+ xhr.send("");
+ info.innerHTML = xhr.responseText;
+ }
+
+ info.style.display = info.style.display === 'none' ? 'block' : 'none';
}
</script>
</head>
@@ -208,7 +211,7 @@
</div>
<div id="about">
- <h3><a href="rails/info/properties" onclick="about(); return false">About your application&rsquo;s environment</a></h3>
+ <h3><a href="/rails/info/properties" onclick="about(); return false">About your application&rsquo;s environment</a></h3>
<div id="about-content" style="display: none"></div>
</div>
diff --git a/railties/lib/rails/test_help.rb b/railties/lib/rails/test_help.rb
index aed7fd4b14..739e4ad992 100644
--- a/railties/lib/rails/test_help.rb
+++ b/railties/lib/rails/test_help.rb
@@ -2,7 +2,7 @@
# so fixtures aren't loaded into that environment
abort("Abort testing: Your Rails environment is running in production mode!") if Rails.env.production?
-require 'minitest/autorun'
+require 'active_support/testing/autorun'
require 'active_support/test_case'
require 'action_controller/test_case'
require 'action_dispatch/testing/integration'
@@ -11,16 +11,6 @@ require 'action_dispatch/testing/integration'
require 'rails/backtrace_cleaner'
MiniTest.backtrace_filter = Rails.backtrace_cleaner
-# Enable turn if it is available
-begin
- require 'turn'
-
- Turn.config do |c|
- c.natural = true
- end
-rescue LoadError
-end
-
if defined?(ActiveRecord::Base)
class ActiveSupport::TestCase
include ActiveRecord::TestFixtures
diff --git a/railties/lib/rails/test_unit/railtie.rb b/railties/lib/rails/test_unit/railtie.rb
index ed89ce4128..f52c4c44b7 100644
--- a/railties/lib/rails/test_unit/railtie.rb
+++ b/railties/lib/rails/test_unit/railtie.rb
@@ -5,7 +5,6 @@ module Rails
fixture_replacement: nil
c.integration_tool :test_unit
- c.performance_tool :test_unit
end
rake_tasks do
diff --git a/railties/lib/rails/test_unit/testing.rake b/railties/lib/rails/test_unit/testing.rake
index 9ad3a4e6d6..f0d46fd959 100644
--- a/railties/lib/rails/test_unit/testing.rake
+++ b/railties/lib/rails/test_unit/testing.rake
@@ -45,7 +45,7 @@ end
task default: :test
-desc 'Runs test:units, test:functionals, test:integration together (also available: test:benchmark, test:profile)'
+desc 'Runs test:units, test:functionals, test:integration together'
task :test do
Rake::Task[ENV['TEST'] ? 'test:single' : 'test:run'].invoke
end
@@ -146,15 +146,4 @@ namespace :test do
t.libs << "test"
t.pattern = 'test/integration/**/*_test.rb'
end
-
- Rails::SubTestTask.new(benchmark: 'test:prepare') do |t|
- t.libs << 'test'
- t.pattern = 'test/performance/**/*_test.rb'
- t.options = '-- --benchmark'
- end
-
- Rails::SubTestTask.new(profile: 'test:prepare') do |t|
- t.libs << 'test'
- t.pattern = 'test/performance/**/*_test.rb'
- end
end
diff --git a/railties/test/abstract_unit.rb b/railties/test/abstract_unit.rb
index ecd5e03978..491faf4af9 100644
--- a/railties/test/abstract_unit.rb
+++ b/railties/test/abstract_unit.rb
@@ -3,7 +3,7 @@ ENV["RAILS_ENV"] ||= "test"
require File.expand_path("../../../load_paths", __FILE__)
require 'stringio'
-require 'minitest/autorun'
+require 'active_support/testing/autorun'
require 'fileutils'
require 'active_support'
diff --git a/railties/test/app_rails_loader_test.rb b/railties/test/app_rails_loader_test.rb
new file mode 100644
index 0000000000..87e0ad7bd7
--- /dev/null
+++ b/railties/test/app_rails_loader_test.rb
@@ -0,0 +1,41 @@
+require 'abstract_unit'
+require 'rails/app_rails_loader'
+
+class AppRailsLoaderTest < ActiveSupport::TestCase
+ test "is in a rails application if bin/rails exists and contains APP_PATH" do
+ File.stubs(:exists?).returns(true)
+ File.stubs(:read).with('bin/rails').returns('APP_PATH')
+ assert Rails::AppRailsLoader.in_rails_application_or_engine?
+ end
+
+ test "is not in a rails application if bin/rails exists but doesn't contain APP_PATH" do
+ File.stubs(:exists?).returns(true)
+ File.stubs(:read).with('bin/rails').returns('railties bin/rails')
+ assert !Rails::AppRailsLoader.in_rails_application_or_engine?
+ end
+
+ test "is in a rails application if parent directory has bin/rails containing APP_PATH" do
+ File.stubs(:exists?).with("/foo/bar/bin/rails").returns(false)
+ File.stubs(:exists?).with("/foo/bin/rails").returns(true)
+ File.stubs(:read).with('/foo/bin/rails').returns('APP_PATH')
+ assert Rails::AppRailsLoader.in_rails_application_or_engine_subdirectory?(Pathname.new("/foo/bar"))
+ end
+
+ test "is not in a rails application if at the root directory and doesn't have bin/rails" do
+ Pathname.any_instance.stubs(:root?).returns true
+ assert !Rails::AppRailsLoader.in_rails_application_or_engine?
+ end
+
+ test "is in a rails engine if parent directory has bin/rails containing ENGINE_PATH" do
+ File.stubs(:exists?).with("/foo/bar/bin/rails").returns(false)
+ File.stubs(:exists?).with("/foo/bin/rails").returns(true)
+ File.stubs(:read).with('/foo/bin/rails').returns('ENGINE_PATH')
+ assert Rails::AppRailsLoader.in_rails_application_or_engine_subdirectory?(Pathname.new("/foo/bar"))
+ end
+
+ test "is in a rails engine if bin/rails exists containing ENGINE_PATH" do
+ File.stubs(:exists?).returns(true)
+ File.stubs(:read).with('bin/rails').returns('ENGINE_PATH')
+ assert Rails::AppRailsLoader.in_rails_application_or_engine?
+ end
+end
diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb
index f98915d1cc..638df8ca23 100644
--- a/railties/test/application/assets_test.rb
+++ b/railties/test/application/assets_test.rb
@@ -45,7 +45,7 @@ module ApplicationTests
app_file 'config/routes.rb', <<-RUBY
AppTemplate::Application.routes.draw do
- get '*path', to: lambda { |env| [200, { "Content-Type" => "text/html" }, "Not an asset"] }
+ get '*path', to: lambda { |env| [200, { "Content-Type" => "text/html" }, ["Not an asset"]] }
end
RUBY
diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb
index 53109cb041..f9108ed7b9 100644
--- a/railties/test/application/configuration_test.rb
+++ b/railties/test/application/configuration_test.rb
@@ -192,6 +192,16 @@ module ApplicationTests
end
end
+ test "filter_parameters should be able to set via config.filter_parameters in an initializer" do
+ app_file 'config/initializers/filter_parameters_logging.rb', <<-RUBY
+ Rails.application.config.filter_parameters += [ :password, :foo, 'bar' ]
+ RUBY
+
+ require "#{app_path}/config/environment"
+
+ assert_equal [:password, :foo, 'bar'], Rails.application.env_config['action_dispatch.parameter_filter']
+ end
+
test "config.to_prepare is forwarded to ActionDispatch" do
$prepared = false
@@ -407,7 +417,17 @@ module ApplicationTests
require "#{app_path}/config/environment"
- assert_equal "Wellington", Rails.application.config.time_zone
+ assert_equal Time.find_zone!("Wellington"), Time.zone_default
+ end
+
+ test "timezone can be set on initializers" do
+ app_file "config/initializers/locale.rb", <<-RUBY
+ Rails.application.config.time_zone = "Central Time (US & Canada)"
+ RUBY
+
+ require "#{app_path}/config/environment"
+
+ assert_equal Time.find_zone!("Central Time (US & Canada)"), Time.zone_default
end
test "raises when an invalid timezone is defined in the config" do
diff --git a/railties/test/application/generators_test.rb b/railties/test/application/generators_test.rb
index bc0af499c1..78ada58ec8 100644
--- a/railties/test/application/generators_test.rb
+++ b/railties/test/application/generators_test.rb
@@ -30,7 +30,7 @@ module ApplicationTests
end
test "allow running plugin new generator inside Rails app directory" do
- FileUtils.cd(rails_root){ `ruby script/rails plugin new vendor/plugins/bukkits` }
+ FileUtils.cd(rails_root){ `ruby bin/rails plugin new vendor/plugins/bukkits` }
assert File.exist?(File.join(rails_root, "vendor/plugins/bukkits/test/dummy/config/application.rb"))
end
diff --git a/railties/test/application/middleware/remote_ip_test.rb b/railties/test/application/middleware/remote_ip_test.rb
index fde13eeb94..f0d3438aa4 100644
--- a/railties/test/application/middleware/remote_ip_test.rb
+++ b/railties/test/application/middleware/remote_ip_test.rb
@@ -40,7 +40,7 @@ module ApplicationTests
end
assert_nothing_raised(ActionDispatch::RemoteIp::IpSpoofAttackError) do
- assert_equal "1.1.1.2", remote_ip("HTTP_X_FORWARDED_FOR" => "1.1.1.1", "HTTP_CLIENT_IP" => "1.1.1.2")
+ assert_equal "1.1.1.1", remote_ip("HTTP_X_FORWARDED_FOR" => "1.1.1.1", "HTTP_CLIENT_IP" => "1.1.1.2")
end
end
diff --git a/railties/test/application/rake/notes_test.rb b/railties/test/application/rake/notes_test.rb
index 744bb93671..5893d58925 100644
--- a/railties/test/application/rake/notes_test.rb
+++ b/railties/test/application/rake/notes_test.rb
@@ -62,7 +62,6 @@ module ApplicationTests
app_file "config/initializers/some_initializer.rb", "# TODO: note in config directory"
app_file "db/some_seeds.rb", "# TODO: note in db directory"
app_file "lib/some_file.rb", "# TODO: note in lib directory"
- app_file "script/run_something.rb", "# TODO: note in script directory"
app_file "test/some_test.rb", 1000.times.map { "" }.join("\n") << "# TODO: note in test directory"
app_file "some_other_dir/blah.rb", "# TODO: note in some_other directory"
@@ -83,11 +82,10 @@ module ApplicationTests
assert_match(/note in config directory/, output)
assert_match(/note in db directory/, output)
assert_match(/note in lib directory/, output)
- assert_match(/note in script directory/, output)
assert_match(/note in test directory/, output)
assert_no_match(/note in some_other directory/, output)
- assert_equal 6, lines.size
+ assert_equal 5, lines.size
lines.each do |line_number|
assert_equal 4, line_number.size
@@ -100,7 +98,6 @@ module ApplicationTests
app_file "config/initializers/some_initializer.rb", "# TODO: note in config directory"
app_file "db/some_seeds.rb", "# TODO: note in db directory"
app_file "lib/some_file.rb", "# TODO: note in lib directory"
- app_file "script/run_something.rb", "# TODO: note in script directory"
app_file "test/some_test.rb", 1000.times.map { "" }.join("\n") << "# TODO: note in test directory"
app_file "some_other_dir/blah.rb", "# TODO: note in some_other directory"
@@ -121,12 +118,11 @@ module ApplicationTests
assert_match(/note in config directory/, output)
assert_match(/note in db directory/, output)
assert_match(/note in lib directory/, output)
- assert_match(/note in script directory/, output)
assert_match(/note in test directory/, output)
assert_match(/note in some_other directory/, output)
- assert_equal 7, lines.size
+ assert_equal 6, lines.size
lines.each do |line_number|
assert_equal 4, line_number.size
diff --git a/railties/test/application/test_test.rb b/railties/test/application/test_test.rb
index f6bcaa466a..c7ad2fba8f 100644
--- a/railties/test/application/test_test.rb
+++ b/railties/test/application/test_test.rb
@@ -52,31 +52,6 @@ module ApplicationTests
run_test_file 'integration/posts_test.rb'
end
- test "performance test" do
- controller 'posts', <<-RUBY
- class PostsController < ActionController::Base
- end
- RUBY
-
- app_file 'app/views/posts/index.html.erb', <<-HTML
- Posts#index
- HTML
-
- app_file 'test/performance/posts_test.rb', <<-RUBY
- require 'test_helper'
- require 'rails/performance_test_help'
-
- class PostsTest < ActionDispatch::PerformanceTest
- def test_index
- get '/posts'
- assert_response :success
- end
- end
- RUBY
-
- run_test_file 'performance/posts_test.rb'
- end
-
private
def run_test_file(name)
result = ruby '-Itest', "#{app_path}/test/#{name}"
diff --git a/railties/test/commands/console_test.rb b/railties/test/commands/console_test.rb
index 9e449856f4..6be4a5fe89 100644
--- a/railties/test/commands/console_test.rb
+++ b/railties/test/commands/console_test.rb
@@ -111,6 +111,12 @@ class Rails::ConsoleTest < ActiveSupport::TestCase
assert_match(/\sdevelopment\s/, output)
end
+ def test_rails_env_is_dev_when_argument_is_dev_and_dev_env_is_present
+ Rails::Console.stubs(:available_environments).returns(['dev'])
+ options = Rails::Console.parse_arguments(['dev'])
+ assert_match('dev', options[:environment])
+ end
+
private
attr_reader :output
diff --git a/railties/test/commands/dbconsole_test.rb b/railties/test/commands/dbconsole_test.rb
index 6316584825..38fe8ca544 100644
--- a/railties/test/commands/dbconsole_test.rb
+++ b/railties/test/commands/dbconsole_test.rb
@@ -45,6 +45,18 @@ class Rails::DBConsoleTest < ActiveSupport::TestCase
ENV['RAILS_ENV'] = "test"
end
+ def test_rails_env_is_development_when_argument_is_dev
+ Rails::DBConsole.stubs(:available_environments).returns(['development', 'test'])
+ options = Rails::DBConsole.new.send(:parse_arguments, ['dev'])
+ assert_match('development', options[:environment])
+ end
+
+ def test_rails_env_is_dev_when_argument_is_dev_and_dev_env_is_present
+ Rails::DBConsole.stubs(:available_environments).returns(['dev'])
+ options = Rails::DBConsole.new.send(:parse_arguments, ['dev'])
+ assert_match('dev', options[:environment])
+ end
+
def test_mysql
dbconsole.expects(:find_cmd_and_exec).with(%w[mysql mysql5], 'db')
start(adapter: 'mysql', database: 'db')
diff --git a/railties/test/configuration/middleware_stack_proxy_test.rb b/railties/test/configuration/middleware_stack_proxy_test.rb
index 5984c0b425..2442cb995d 100644
--- a/railties/test/configuration/middleware_stack_proxy_test.rb
+++ b/railties/test/configuration/middleware_stack_proxy_test.rb
@@ -1,6 +1,7 @@
-require 'minitest/autorun'
+require 'active_support/testing/autorun'
require 'rails/configuration'
require 'active_support/test_case'
+require 'minitest/mock'
module Rails
module Configuration
diff --git a/railties/test/engine_test.rb b/railties/test/engine_test.rb
index addf49cdb6..7970913d21 100644
--- a/railties/test/engine_test.rb
+++ b/railties/test/engine_test.rb
@@ -1,7 +1,7 @@
require 'abstract_unit'
class EngineTest < ActiveSupport::TestCase
- it "reports routes as available only if they're actually present" do
+ test "reports routes as available only if they're actually present" do
engine = Class.new(Rails::Engine) do
def initialize(*args)
@routes = nil
diff --git a/railties/test/fixtures/path/ruby-local-exec b/railties/test/fixtures/path/ruby-local-exec
deleted file mode 100644
index e69de29bb2..0000000000
--- a/railties/test/fixtures/path/ruby-local-exec
+++ /dev/null
diff --git a/railties/test/generators/actions_test.rb b/railties/test/generators/actions_test.rb
index 54734ed260..f8fa8ee153 100644
--- a/railties/test/generators/actions_test.rb
+++ b/railties/test/generators/actions_test.rb
@@ -151,7 +151,7 @@ class ActionsTest < Rails::Generators::TestCase
end
def test_generate_should_run_script_generate_with_argument_and_options
- generator.expects(:run_ruby_script).once.with('script/rails generate model MyModel', verbose: false)
+ generator.expects(:run_ruby_script).once.with('bin/rails generate model MyModel', verbose: false)
action :generate, 'model', 'MyModel'
end
@@ -203,14 +203,14 @@ class ActionsTest < Rails::Generators::TestCase
def test_readme
run_generator
Rails::Generators::AppGenerator.expects(:source_root).times(2).returns(destination_root)
- assert_match(/Welcome to Rails/, action(:readme, "README.rdoc"))
+ assert_match "application up and running", action(:readme, "README.rdoc")
end
def test_readme_with_quiet
generator(default_arguments, quiet: true)
run_generator
Rails::Generators::AppGenerator.expects(:source_root).times(2).returns(destination_root)
- assert_no_match(/Welcome to Rails/, action(:readme, "README.rdoc"))
+ assert_no_match "application up and running", action(:readme, "README.rdoc")
end
def test_log
diff --git a/railties/test/generators/app_generator_test.rb b/railties/test/generators/app_generator_test.rb
index bd0f9d6a32..ee93dc49cd 100644
--- a/railties/test/generators/app_generator_test.rb
+++ b/railties/test/generators/app_generator_test.rb
@@ -17,23 +17,23 @@ DEFAULT_APP_FILES = %w(
app/models
app/models/concerns
app/views/layouts
+ bin/bundle
+ bin/rails
+ bin/rake
config/environments
config/initializers
config/locales
db
- doc
lib
lib/tasks
lib/assets
log
- script/rails
test/fixtures
test/controllers
test/models
test/helpers
test/mailers
test/integration
- test/performance
vendor
vendor/assets
tmp/cache
@@ -56,7 +56,6 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_file "app/views/layouts/application.html.erb", /stylesheet_link_tag\s+"application"/
assert_file "app/views/layouts/application.html.erb", /javascript_include_tag\s+"application"/
assert_file "app/assets/stylesheets/application.css"
- assert_file "config/application.rb", /config\.assets\.enabled = true/
end
def test_invalid_application_name_raises_an_error
@@ -218,14 +217,13 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_file "test/test_helper.rb" do |helper_content|
assert_no_match(/fixtures :all/, helper_content)
end
- assert_file "test/performance/browsing_test.rb"
end
def test_generator_if_skip_sprockets_is_given
run_generator [destination_root, "--skip-sprockets"]
assert_file "config/application.rb" do |content|
assert_match(/#\s+require\s+["']sprockets\/railtie["']/, content)
- assert_no_match(/config\.assets\.enabled = true/, content)
+ assert_match(/config\.assets\.enabled = false/, content)
end
assert_file "Gemfile" do |content|
assert_no_match(/sass-rails/, content)
@@ -239,8 +237,8 @@ class AppGeneratorTest < Rails::Generators::TestCase
assert_no_match(/config\.assets\.digest = true/, content)
assert_no_match(/config\.assets\.js_compressor = :uglifier/, content)
assert_no_match(/config\.assets\.css_compressor = :sass/, content)
+ assert_no_match(/config\.assets\.version = '1\.0'/, content)
end
- assert_file "test/performance/browsing_test.rb"
end
def test_inclusion_of_javascript_runtime
diff --git a/railties/test/generators/performance_test_generator_test.rb b/railties/test/generators/performance_test_generator_test.rb
deleted file mode 100644
index 37f9857193..0000000000
--- a/railties/test/generators/performance_test_generator_test.rb
+++ /dev/null
@@ -1,12 +0,0 @@
-require 'generators/generators_test_helper'
-require 'rails/generators/rails/performance_test/performance_test_generator'
-
-class PerformanceTestGeneratorTest < Rails::Generators::TestCase
- include GeneratorsTestHelper
- arguments %w(performance)
-
- def test_performance_test_skeleton_is_created
- run_generator
- assert_file "test/performance/performance_test.rb", /class PerformanceTest < ActionDispatch::PerformanceTest/
- end
-end
diff --git a/railties/test/generators/plugin_new_generator_test.rb b/railties/test/generators/plugin_new_generator_test.rb
index ab78800a4e..4bf5a2f08b 100644
--- a/railties/test/generators/plugin_new_generator_test.rb
+++ b/railties/test/generators/plugin_new_generator_test.rb
@@ -209,10 +209,10 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase
assert_file "app/views"
assert_file "app/helpers"
assert_file "app/mailers"
+ assert_file "bin/rails"
assert_file "config/routes.rb", /Rails.application.routes.draw do/
assert_file "lib/bukkits/engine.rb", /module Bukkits\n class Engine < ::Rails::Engine\n end\nend/
assert_file "lib/bukkits.rb", /require "bukkits\/engine"/
- assert_file "script/rails"
end
def test_being_quiet_while_creating_dummy_application
@@ -246,15 +246,15 @@ class PluginNewGeneratorTest < Rails::Generators::TestCase
def test_usage_of_engine_commands
run_generator [destination_root, "--full"]
- assert_file "script/rails", /ENGINE_PATH = File.expand_path\('..\/..\/lib\/bukkits\/engine', __FILE__\)/
- assert_file "script/rails", /ENGINE_ROOT = File.expand_path\('..\/..', __FILE__\)/
- assert_file "script/rails", /require 'rails\/all'/
- assert_file "script/rails", /require 'rails\/engine\/commands'/
+ assert_file "bin/rails", /ENGINE_PATH = File.expand_path\('..\/..\/lib\/bukkits\/engine', __FILE__\)/
+ assert_file "bin/rails", /ENGINE_ROOT = File.expand_path\('..\/..', __FILE__\)/
+ assert_file "bin/rails", /require 'rails\/all'/
+ assert_file "bin/rails", /require 'rails\/engine\/commands'/
end
def test_shebang
run_generator [destination_root, "--full"]
- assert_file "script/rails", /#!\/usr\/bin\/env ruby/
+ assert_file "bin/rails", /#!\/usr\/bin\/env ruby/
end
def test_passing_dummy_path_as_a_parameter
diff --git a/railties/test/generators/scaffold_controller_generator_test.rb b/railties/test/generators/scaffold_controller_generator_test.rb
index f13305adb0..c34ce285e3 100644
--- a/railties/test/generators/scaffold_controller_generator_test.rb
+++ b/railties/test/generators/scaffold_controller_generator_test.rb
@@ -31,12 +31,10 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase
assert_instance_method :create, content do |m|
assert_match(/@user = User\.new\(user_params\)/, m)
assert_match(/@user\.save/, m)
- assert_match(/@user\.errors/, m)
end
assert_instance_method :update, content do |m|
- assert_match(/@user\.update_attributes\(user_params\)/, m)
- assert_match(/@user\.errors/, m)
+ assert_match(/@user\.update\(user_params\)/, m)
end
assert_instance_method :destroy, content do |m|
@@ -101,7 +99,7 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase
assert_match(/class UsersControllerTest < ActionController::TestCase/, content)
assert_match(/test "should get index"/, content)
assert_match(/post :create, user: \{ age: @user\.age, name: @user\.name, organization_id: @user\.organization_id, organization_type: @user\.organization_type \}/, content)
- assert_match(/put :update, id: @user, user: \{ age: @user\.age, name: @user\.name, organization_id: @user\.organization_id, organization_type: @user\.organization_type \}/, content)
+ assert_match(/patch :update, id: @user, user: \{ age: @user\.age, name: @user\.name, organization_id: @user\.organization_id, organization_type: @user\.organization_type \}/, content)
end
end
@@ -112,7 +110,7 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase
assert_match(/class UsersControllerTest < ActionController::TestCase/, content)
assert_match(/test "should get index"/, content)
assert_match(/post :create, user: \{ \}/, content)
- assert_match(/put :update, id: @user, user: \{ \}/, content)
+ assert_match(/patch :update, id: @user, user: \{ \}/, content)
end
end
@@ -127,18 +125,6 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase
assert_no_file "app/views/layouts/users.html.erb"
end
- def test_skip_html_if_required
- run_generator [ "User", "name:string", "age:integer", "--no-html" ]
- assert_no_file "app/helpers/users_helper.rb"
- assert_no_file "app/views/users"
-
- assert_file "app/controllers/users_controller.rb" do |content|
- assert_no_match(/format\.html/, content)
- assert_no_match(/def edit/, content)
- assert_no_match(/def new/, content)
- end
- end
-
def test_default_orm_is_used
run_generator ["User", "--orm=unknown"]
@@ -176,7 +162,7 @@ class ScaffoldControllerGeneratorTest < Rails::Generators::TestCase
def test_new_hash_style
run_generator
assert_file "app/controllers/users_controller.rb" do |content|
- assert_match(/\{ render action: "new" \}/, content)
+ assert_match(/render action: 'new'/, content)
end
end
end
diff --git a/railties/test/generators/scaffold_generator_test.rb b/railties/test/generators/scaffold_generator_test.rb
index f3f2c170ee..357f472a3f 100644
--- a/railties/test/generators/scaffold_generator_test.rb
+++ b/railties/test/generators/scaffold_generator_test.rb
@@ -41,12 +41,10 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
assert_instance_method :create, content do |m|
assert_match(/@product_line = ProductLine\.new\(product_line_params\)/, m)
assert_match(/@product_line\.save/, m)
- assert_match(/@product_line\.errors/, m)
end
assert_instance_method :update, content do |m|
- assert_match(/@product_line\.update_attributes\(product_line_params\)/, m)
- assert_match(/@product_line\.errors/, m)
+ assert_match(/@product_line\.update\(product_line_params\)/, m)
end
assert_instance_method :destroy, content do |m|
@@ -61,7 +59,7 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
assert_file "test/controllers/product_lines_controller_test.rb" do |test|
assert_match(/class ProductLinesControllerTest < ActionController::TestCase/, test)
assert_match(/post :create, product_line: \{ product_id: @product_line\.product_id, title: @product_line\.title, user_id: @product_line\.user_id \}/, test)
- assert_match(/put :update, id: @product_line, product_line: \{ product_id: @product_line\.product_id, title: @product_line\.title, user_id: @product_line\.user_id \}/, test)
+ assert_match(/patch :update, id: @product_line, product_line: \{ product_id: @product_line\.product_id, title: @product_line\.title, user_id: @product_line\.user_id \}/, test)
end
# Views
@@ -87,7 +85,7 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
assert_match(/class ProductLinesControllerTest < ActionController::TestCase/, content)
assert_match(/test "should get index"/, content)
assert_match(/post :create, product_line: \{ \}/, content)
- assert_match(/put :update, id: @product_line, product_line: \{ \}/, content)
+ assert_match(/patch :update, id: @product_line, product_line: \{ \}/, content)
end
end
@@ -158,12 +156,10 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
assert_instance_method :create, content do |m|
assert_match(/@admin_role = Admin::Role\.new\(admin_role_params\)/, m)
assert_match(/@admin_role\.save/, m)
- assert_match(/@admin_role\.errors/, m)
end
assert_instance_method :update, content do |m|
- assert_match(/@admin_role\.update_attributes\(admin_role_params\)/, m)
- assert_match(/@admin_role\.errors/, m)
+ assert_match(/@admin_role\.update\(admin_role_params\)/, m)
end
assert_instance_method :destroy, content do |m|
@@ -257,11 +253,6 @@ class ScaffoldGeneratorTest < Rails::Generators::TestCase
assert_no_file "app/assets/stylesheets/posts.css"
end
- def test_scaffold_generator_no_html
- run_generator [ "posts", "--no-html" ]
- assert_no_file "app/assets/stylesheets/scaffold.css"
- end
-
def test_scaffold_generator_no_javascripts
run_generator [ "posts", "--no-javascripts" ]
assert_file "app/assets/stylesheets/scaffold.css"
diff --git a/railties/test/generators/shared_generator_tests.rb b/railties/test/generators/shared_generator_tests.rb
index 85a90cd968..d203afed5c 100644
--- a/railties/test/generators/shared_generator_tests.rb
+++ b/railties/test/generators/shared_generator_tests.rb
@@ -27,20 +27,10 @@ module SharedGeneratorTests
end
def test_generation_runs_bundle_install
- generator([destination_root]).expects(:bundle_command).with('install --binstubs').once
+ generator([destination_root]).expects(:bundle_command).with('install').once
quietly { generator.invoke_all }
end
- def test_generation_runs_bundle_install_with_shebang_if_needed
- original_path = ENV["PATH"]
- ENV["PATH"] = ENV["PATH"] + ":" + File.expand_path("../../fixtures/path", __FILE__)
-
- generator([destination_root]).expects(:bundle_command).with('install --binstubs --shebang ruby-local-exec').once
- quietly { generator.invoke_all }
- ensure
- ENV["PATH"] = original_path
- end
-
def test_plugin_new_generate_pretend
run_generator ["testapp", "--pretend"]
default_files.each{ |path| assert_no_file File.join("testapp",path) }
@@ -58,7 +48,7 @@ module SharedGeneratorTests
def test_options_before_application_name_raises_an_error
content = capture(:stderr){ run_generator(["--pretend", destination_root]) }
- assert_match(/Options should be given after the \w+ name. For details run: rails( plugin)? --help\n/, content)
+ assert_match(/Options should be given after the \w+ name. For details run: rails( plugin new)? --help\n/, content)
end
def test_name_collision_raises_an_error
@@ -78,12 +68,12 @@ module SharedGeneratorTests
def test_shebang_is_added_to_rails_file
run_generator [destination_root, "--ruby", "foo/bar/baz", "--full"]
- assert_file "script/rails", /#!foo\/bar\/baz/
+ assert_file "bin/rails", /#!foo\/bar\/baz/
end
def test_shebang_when_is_the_same_as_default_use_env
run_generator [destination_root, "--ruby", Thor::Util.ruby_command, "--full"]
- assert_file "script/rails", /#!\/usr\/bin\/env/
+ assert_file "bin/rails", /#!\/usr\/bin\/env/
end
def test_template_raises_an_error_with_invalid_path
@@ -111,14 +101,14 @@ module SharedGeneratorTests
end
def test_dev_option
- generator([destination_root], dev: true).expects(:bundle_command).with('install --binstubs').once
+ generator([destination_root], dev: true).expects(:bundle_command).with('install').once
quietly { generator.invoke_all }
rails_path = File.expand_path('../../..', Rails.root)
assert_file 'Gemfile', /^gem\s+["']rails["'],\s+path:\s+["']#{Regexp.escape(rails_path)}["']$/
end
def test_edge_option
- generator([destination_root], edge: true).expects(:bundle_command).with('install --binstubs').once
+ generator([destination_root], edge: true).expects(:bundle_command).with('install').once
quietly { generator.invoke_all }
assert_file 'Gemfile', %r{^gem\s+["']rails["'],\s+github:\s+["']#{Regexp.escape("rails/rails")}["']$}
end
diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb
index 0cb65f8e0d..7ae1b5ccfd 100644
--- a/railties/test/isolation/abstract_unit.rb
+++ b/railties/test/isolation/abstract_unit.rb
@@ -9,7 +9,7 @@
require 'fileutils'
require 'bundler/setup' unless defined?(Bundler)
-require 'minitest/autorun'
+require 'active_support/testing/autorun'
require 'active_support/test_case'
RAILS_FRAMEWORK_ROOT = File.expand_path("#{File.dirname(__FILE__)}/../../..")
@@ -206,7 +206,7 @@ module TestHelpers
def script(script)
Dir.chdir(app_path) do
- `#{Gem.ruby} #{app_path}/script/rails #{script}`
+ `#{Gem.ruby} #{app_path}/bin/rails #{script}`
end
end
diff --git a/railties/test/rack_logger_test.rb b/railties/test/rack_logger_test.rb
new file mode 100644
index 0000000000..3a9392fd26
--- /dev/null
+++ b/railties/test/rack_logger_test.rb
@@ -0,0 +1,71 @@
+require 'active_support/testing/autorun'
+require 'active_support/test_case'
+require 'rails/rack/logger'
+require 'logger'
+
+module Rails
+ module Rack
+ class LoggerTest < ActiveSupport::TestCase
+ class TestLogger < Rails::Rack::Logger
+ NULL = ::Logger.new File::NULL
+
+ attr_reader :logger
+
+ def initialize(logger = NULL, taggers = nil, &block)
+ super(->(_) { block.call; [200, {}, []] }, taggers)
+ @logger = logger
+ end
+
+ def development?; false; end
+ end
+
+ class Subscriber < Struct.new(:starts, :finishes)
+ def initialize(starts = [], finishes = [])
+ super
+ end
+
+ def start(name, id, payload)
+ starts << [name, id, payload]
+ end
+
+ def finish(name, id, payload)
+ finishes << [name, id, payload]
+ end
+ end
+
+ attr_reader :subscriber, :notifier
+
+ def setup
+ @subscriber = Subscriber.new
+ @notifier = ActiveSupport::Notifications.notifier
+ notifier.subscribe 'action_dispatch.request', subscriber
+ end
+
+ def teardown
+ notifier.unsubscribe subscriber
+ end
+
+ def test_notification
+ logger = TestLogger.new { }
+
+ assert_difference('subscriber.starts.length') do
+ assert_difference('subscriber.finishes.length') do
+ logger.call('REQUEST_METHOD' => 'GET').last.close
+ end
+ end
+ end
+
+ def test_notification_on_raise
+ logger = TestLogger.new { raise }
+
+ assert_difference('subscriber.starts.length') do
+ assert_difference('subscriber.finishes.length') do
+ assert_raises(RuntimeError) do
+ logger.call 'REQUEST_METHOD' => 'GET'
+ end
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb
index fcbe7b6cda..a4a75fe459 100644
--- a/railties/test/railties/engine_test.rb
+++ b/railties/test/railties/engine_test.rb
@@ -568,7 +568,7 @@ YAML
@plugin.write "lib/bukkits.rb", <<-RUBY
module Bukkits
class Engine < ::Rails::Engine
- endpoint lambda { |env| [200, {'Content-Type' => 'text/html'}, 'hello'] }
+ endpoint lambda { |env| [200, {'Content-Type' => 'text/html'}, ['hello']] }
end
end
RUBY
diff --git a/railties/test/script_rails_loader_test.rb b/railties/test/script_rails_loader_test.rb
deleted file mode 100644
index 3ccc147749..0000000000
--- a/railties/test/script_rails_loader_test.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-require 'abstract_unit'
-require 'rails/script_rails_loader'
-
-class ScriptRailsLoaderTest < ActiveSupport::TestCase
-
- test "is in a rails application if script/rails exists" do
- File.stubs(:exists?).returns(true)
- assert Rails::ScriptRailsLoader.in_rails_application?
- end
-
- test "is in a rails application if parent directory has script/rails" do
- File.stubs(:exists?).with("/foo/bar/script/rails").returns(false)
- File.stubs(:exists?).with("/foo/script/rails").returns(true)
- assert Rails::ScriptRailsLoader.in_rails_application_subdirectory?(Pathname.new("/foo/bar"))
- end
-
- test "is not in a rails application if at the root directory and doesn't have script/rails" do
- Pathname.any_instance.stubs(:root?).returns true
- assert !Rails::ScriptRailsLoader.in_rails_application?
- end
-
-end \ No newline at end of file