aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Gemfile7
-rw-r--r--README.rdoc29
-rw-r--r--Rakefile8
-rw-r--r--actionmailer/CHANGELOG.md8
-rw-r--r--actionmailer/lib/action_mailer/base.rb17
-rw-r--r--actionmailer/test/base_test.rb13
-rw-r--r--actionmailer/test/fixtures/base_mailer/without_mail_call.erb1
-rw-r--r--actionmailer/test/mailers/base_mailer.rb3
-rw-r--r--actionpack/CHANGELOG.md15
-rw-r--r--actionpack/lib/abstract_controller/base.rb10
-rw-r--r--actionpack/lib/abstract_controller/rendering.rb2
-rw-r--r--actionpack/lib/action_controller/metal/exceptions.rb9
-rw-r--r--actionpack/lib/action_controller/metal/strong_parameters.rb2
-rw-r--r--actionpack/lib/action_controller/record_identifier.rb4
-rw-r--r--actionpack/lib/action_controller/test_case.rb6
-rw-r--r--actionpack/lib/action_dispatch/http/request.rb16
-rw-r--r--actionpack/lib/action_dispatch/middleware/best_standards_support.rb8
-rw-r--r--actionpack/lib/action_dispatch/middleware/remote_ip.rb10
-rw-r--r--actionpack/lib/action_dispatch/routing/mapper.rb2
-rw-r--r--actionpack/lib/action_dispatch/testing/integration.rb4
-rw-r--r--actionpack/lib/action_view/helpers/date_helper.rb2
-rw-r--r--actionpack/lib/action_view/helpers/form_helper.rb3
-rw-r--r--actionpack/lib/action_view/helpers/form_options_helper.rb4
-rw-r--r--actionpack/lib/action_view/helpers/form_tag_helper.rb20
-rw-r--r--actionpack/lib/action_view/helpers/javascript_helper.rb6
-rw-r--r--actionpack/lib/action_view/helpers/url_helper.rb8
-rw-r--r--actionpack/lib/action_view/renderer/template_renderer.rb7
-rw-r--r--actionpack/lib/action_view/template.rb3
-rw-r--r--actionpack/lib/action_view/template/resolver.rb8
-rw-r--r--actionpack/test/activerecord/controller_runtime_test.rb8
-rw-r--r--actionpack/test/controller/default_url_options_with_filter_test.rb2
-rw-r--r--actionpack/test/controller/http_basic_authentication_test.rb4
-rw-r--r--actionpack/test/controller/mime_responds_test.rb2
-rw-r--r--actionpack/test/controller/new_base/middleware_test.rb4
-rw-r--r--actionpack/test/controller/new_base/render_partial_test.rb2
-rw-r--r--actionpack/test/controller/parameters/parameters_permit_test.rb4
-rw-r--r--actionpack/test/controller/send_file_test.rb2
-rw-r--r--actionpack/test/dispatch/best_standards_support_test.rb34
-rw-r--r--actionpack/test/dispatch/request_test.rb23
-rw-r--r--actionpack/test/dispatch/routing_test.rb11
-rw-r--r--actionpack/test/template/digestor_test.rb2
-rw-r--r--actionpack/test/template/form_tag_helper_test.rb6
-rw-r--r--actionpack/test/template/javascript_helper_test.rb12
-rw-r--r--actionpack/test/template/render_test.rb4
-rw-r--r--actionpack/test/template/tag_helper_test.rb9
-rw-r--r--actionpack/test/template/url_helper_test.rb18
-rw-r--r--activemodel/lib/active_model/attribute_methods.rb11
-rw-r--r--activemodel/lib/active_model/observing.rb2
-rw-r--r--activemodel/lib/active_model/serializers/json.rb2
-rwxr-xr-xactivemodel/lib/active_model/serializers/xml.rb6
-rw-r--r--activemodel/test/cases/serializers/json_serialization_test.rb10
-rwxr-xr-xactivemodel/test/cases/serializers/xml_serialization_test.rb2
-rw-r--r--activerecord/CHANGELOG.md92
-rw-r--r--activerecord/lib/active_record.rb1
-rw-r--r--activerecord/lib/active_record/associations/alias_tracker.rb2
-rw-r--r--activerecord/lib/active_record/associations/association.rb2
-rw-r--r--activerecord/lib/active_record/associations/collection_association.rb4
-rw-r--r--activerecord/lib/active_record/attribute_methods.rb15
-rw-r--r--activerecord/lib/active_record/attribute_methods/dirty.rb8
-rw-r--r--activerecord/lib/active_record/attribute_methods/read.rb48
-rw-r--r--activerecord/lib/active_record/attribute_methods/serialization.rb13
-rw-r--r--activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb16
-rw-r--r--activerecord/lib/active_record/attribute_methods/write.rb20
-rw-r--r--activerecord/lib/active_record/base.rb46
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb8
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb9
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_adapter.rb5
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb7
-rw-r--r--activerecord/lib/active_record/connection_adapters/column.rb20
-rw-r--r--activerecord/lib/active_record/connection_adapters/connection_specification.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb7
-rw-r--r--activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb10
-rw-r--r--activerecord/lib/active_record/connection_handling.rb1
-rw-r--r--activerecord/lib/active_record/core.rb141
-rw-r--r--activerecord/lib/active_record/explain.rb8
-rw-r--r--activerecord/lib/active_record/fixtures.rb2
-rw-r--r--activerecord/lib/active_record/inheritance.rb41
-rw-r--r--activerecord/lib/active_record/locking/optimistic.rb8
-rw-r--r--activerecord/lib/active_record/migration.rb9
-rw-r--r--activerecord/lib/active_record/model.rb167
-rw-r--r--activerecord/lib/active_record/model_schema.rb47
-rw-r--r--activerecord/lib/active_record/nested_attributes.rb8
-rw-r--r--activerecord/lib/active_record/persistence.rb4
-rw-r--r--activerecord/lib/active_record/query_cache.rb12
-rw-r--r--activerecord/lib/active_record/railtie.rb11
-rw-r--r--activerecord/lib/active_record/readonly_attributes.rb3
-rw-r--r--activerecord/lib/active_record/relation/batches.rb4
-rw-r--r--activerecord/lib/active_record/relation/finder_methods.rb2
-rw-r--r--activerecord/lib/active_record/relation/predicate_builder.rb6
-rw-r--r--activerecord/lib/active_record/relation/query_methods.rb5
-rw-r--r--activerecord/lib/active_record/result.rb2
-rw-r--r--activerecord/lib/active_record/serialization.rb10
-rw-r--r--activerecord/lib/active_record/timestamp.rb5
-rw-r--r--activerecord/lib/active_record/transactions.rb5
-rw-r--r--activerecord/test/cases/adapter_test.rb6
-rw-r--r--activerecord/test/cases/adapters/mysql/connection_test.rb22
-rw-r--r--activerecord/test/cases/adapters/mysql/sql_types_test.rb14
-rw-r--r--activerecord/test/cases/adapters/mysql2/connection_test.rb12
-rw-r--r--activerecord/test/cases/adapters/mysql2/sql_types_test.rb14
-rw-r--r--activerecord/test/cases/adapters/sqlite3/copy_table_test.rb9
-rw-r--r--activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb6
-rw-r--r--activerecord/test/cases/associations/inverse_associations_test.rb13
-rw-r--r--activerecord/test/cases/attribute_methods/read_test.rb2
-rw-r--r--activerecord/test/cases/attribute_methods_test.rb6
-rw-r--r--activerecord/test/cases/base_test.rb14
-rw-r--r--activerecord/test/cases/batches_test.rb8
-rw-r--r--activerecord/test/cases/column_test.rb8
-rw-r--r--activerecord/test/cases/connection_adapters/connection_handler_test.rb4
-rw-r--r--activerecord/test/cases/connection_specification/resolver_test.rb14
-rw-r--r--activerecord/test/cases/defaults_test.rb8
-rw-r--r--activerecord/test/cases/inclusion_test.rb133
-rw-r--r--activerecord/test/cases/inheritance_test.rb11
-rw-r--r--activerecord/test/cases/migration/change_schema_test.rb20
-rw-r--r--activerecord/test/cases/multiple_db_test.rb4
-rw-r--r--activerecord/test/cases/persistence_test.rb13
-rw-r--r--activerecord/test/cases/pooled_connections_test.rb18
-rw-r--r--activerecord/test/cases/primary_keys_test.rb4
-rw-r--r--activerecord/test/cases/query_cache_test.rb11
-rw-r--r--activerecord/test/cases/relation_test.rb6
-rw-r--r--activerecord/test/cases/relations_test.rb9
-rw-r--r--activerecord/test/cases/schema_dumper_test.rb6
-rw-r--r--activerecord/test/cases/serialization_test.rb16
-rw-r--r--activerecord/test/cases/serialized_attribute_test.rb16
-rw-r--r--activerecord/test/cases/transactions_test.rb15
-rw-r--r--activerecord/test/cases/unconnected_test.rb6
-rw-r--r--activerecord/test/cases/validations/i18n_generate_message_validation_test.rb14
-rw-r--r--activerecord/test/models/teapot.rb35
-rw-r--r--activerecord/test/schema/mysql2_specific_schema.rb22
-rw-r--r--activerecord/test/schema/mysql_specific_schema.rb22
-rw-r--r--activerecord/test/schema/schema.rb6
-rw-r--r--activerecord/test/support/connection.rb6
-rw-r--r--activesupport/CHANGELOG.md11
-rw-r--r--activesupport/lib/active_support/benchmarkable.rb3
-rw-r--r--activesupport/lib/active_support/cache.rb10
-rw-r--r--activesupport/lib/active_support/callbacks.rb7
-rw-r--r--activesupport/lib/active_support/core_ext/array/uniq_by.rb4
-rw-r--r--activesupport/lib/active_support/core_ext/date_time/calculations.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/file/atomic.rb13
-rw-r--r--activesupport/lib/active_support/core_ext/module/introspection.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/proc.rb2
-rw-r--r--activesupport/lib/active_support/core_ext/string/encoding.rb2
-rw-r--r--activesupport/lib/active_support/deprecation/method_wrappers.rb2
-rw-r--r--activesupport/lib/active_support/deprecation/reporting.rb7
-rw-r--r--activesupport/lib/active_support/hash_with_indifferent_access.rb8
-rw-r--r--activesupport/lib/active_support/json/variable.rb5
-rw-r--r--activesupport/lib/active_support/queueing.rb8
-rw-r--r--activesupport/lib/active_support/test_case.rb5
-rw-r--r--activesupport/lib/active_support/values/time_zone.rb2
-rw-r--r--activesupport/test/caching_test.rb14
-rw-r--r--activesupport/test/core_ext/hash_ext_test.rb12
-rw-r--r--activesupport/test/core_ext/module/qualified_const_test.rb19
-rw-r--r--activesupport/test/dependencies_test.rb3
-rw-r--r--activesupport/test/deprecation_test.rb2
-rw-r--r--activesupport/test/queueing/threaded_consumer_test.rb24
-rw-r--r--guides/CHANGELOG.md2
-rw-r--r--guides/source/4_0_release_notes.md8
-rw-r--r--guides/source/active_support_core_extensions.md4
-rw-r--r--guides/source/documents.yaml63
-rw-r--r--guides/source/form_helpers.md2
-rw-r--r--guides/source/working_with_javascript_in_rails.md (renamed from guides/source/working_with_javascript.md)106
-rw-r--r--railties/CHANGELOG.md4
-rw-r--r--railties/lib/rails.rb5
-rw-r--r--railties/lib/rails/application/configuration.rb10
-rw-r--r--railties/lib/rails/application/finisher.rb1
-rw-r--r--railties/lib/rails/generators/app_base.rb2
-rw-r--r--railties/lib/rails/generators/rails/app/templates/Gemfile2
-rw-r--r--railties/lib/rails/paths.rb18
-rw-r--r--railties/test/application/assets_test.rb2
-rw-r--r--railties/test/application/paths_test.rb9
-rw-r--r--railties/test/application/queue_test.rb1
-rw-r--r--railties/test/generators/task_generator_test.rb2
-rwxr-xr-xtools/profile22
172 files changed, 1167 insertions, 1067 deletions
diff --git a/Gemfile b/Gemfile
index 6e0f43c526..b9b3a4cb23 100644
--- a/Gemfile
+++ b/Gemfile
@@ -4,7 +4,7 @@ gemspec
gem 'arel', github: 'rails/arel', branch: 'master'
-gem 'mocha', '>= 0.11.2', :require => false
+gem 'mocha', '>= 0.11.2', require: false
gem 'rack-test', github: 'brynary/rack-test'
gem 'rack-cache', '~> 1.2'
gem 'bcrypt-ruby', '~> 3.0.0'
@@ -28,7 +28,7 @@ group :doc do
# for some weeks unapplied. As a temporary solution
# this is our own fork with the fix.
gem 'sdoc', github: 'fxn/sdoc'
- gem 'redcarpet', '~> 2.1.1', :platforms => :ruby
+ gem 'redcarpet', '~> 2.2.2', platforms: :ruby
gem 'w3c_validators'
end
@@ -42,12 +42,11 @@ instance_eval File.read local_gemfile if File.exists? local_gemfile
platforms :mri do
group :test do
gem 'ruby-prof', '~> 0.11.2' if RUBY_VERSION < '2.0'
- gem 'debugger' if !ENV['TRAVIS'] && RUBY_VERSION < '2.0' && RUBY_PATCHLEVEL < 286
+ gem 'debugger' if !ENV['TRAVIS'] && RUBY_VERSION < '2.0'
end
end
platforms :ruby do
- gem 'json'
gem 'yajl-ruby'
gem 'nokogiri', '>= 1.4.5'
diff --git a/README.rdoc b/README.rdoc
index c9fb595efb..87ec64e3b5 100644
--- a/README.rdoc
+++ b/README.rdoc
@@ -6,29 +6,29 @@ database-backed web applications according to the {Model-View-Controller (MVC)}[
Understanding the MVC pattern is key to understanding Rails. MVC divides your application
into three layers, each with a specific responsibility.
-The View layer is composed of "templates" that are responsible for providing
+The View layer is composed of "templates" that are responsible for providing
appropriate representations of your application's resources. Templates
can come in a variety of formats, but most view templates are \HTML with embedded Ruby
-code (.erb files).
+code (.erb files).
-The Model layer represents your domain model (such as Account, Product, Person, Post)
-and encapsulates the business logic that is specific to your application. In Rails,
+The Model layer represents your domain model (such as Account, Product, Person, Post)
+and encapsulates the business logic that is specific to your application. In Rails,
database-backed model classes are derived from ActiveRecord::Base. Active Record allows
-you to present the data from database rows as objects and embellish these data objects
-with business logic methods. Although most Rails models are backed by a database, models
+you to present the data from database rows as objects and embellish these data objects
+with business logic methods. Although most Rails models are backed by a database, models
can also be ordinary Ruby classes, or Ruby classes that implement a set of interfaces as
provided by the ActiveModel module. You can read more about Active Record in its
{README}[link:/rails/rails/blob/master/activerecord/README.rdoc].
-The Controller layer is responsible for handling incoming HTTP requests and providing a
+The Controller layer is responsible for handling incoming HTTP requests and providing a
suitable response. Usually this means returning \HTML, but Rails controllers can also
-generate XML, JSON, PDFs, mobile-specific views, and more. Controllers manipulate models
+generate XML, JSON, PDFs, mobile-specific views, and more. Controllers manipulate models
and render view templates in order to generate the appropriate HTTP response.
In Rails, the Controller and View layers are handled together by Action Pack.
-These two layers are bundled in a single package due to their heavy interdependence.
+These two layers are bundled in a single package due to their heavy interdependence.
This is unlike the relationship between Active Record and Action Pack which are
-independent. Each of these packages can be used independently outside of Rails. You
+independent. Each of these packages can be used independently outside of Rails. You
can read more about Action Pack in its {README}[link:/rails/rails/blob/master/actionpack/README.rdoc].
== Getting Started
@@ -67,12 +67,11 @@ We encourage you to contribute to Ruby on Rails! Please check out the {Contribut
guide}[http://edgeguides.rubyonrails.org/contributing_to_ruby_on_rails.html] for guidelines about how
to proceed. {Join us}[http://contributors.rubyonrails.org]!
-== Build Status {<img src="https://secure.travis-ci.org/rails/rails.png"/>}[http://travis-ci.org/rails/rails]
+== Code Status
-== Dependency Status {<img src="https://gemnasium.com/rails/rails.png?travis"/>}[https://gemnasium.com/rails/rails]
+* {<img src="https://secure.travis-ci.org/rails/rails.png"/>}[http://travis-ci.org/rails/rails]
+* {<img src="https://gemnasium.com/rails/rails.png?travis"/>}[https://gemnasium.com/rails/rails]
== License
-Ruby on Rails is released under the MIT license:
-
-* http://www.opensource.org/licenses/MIT
+Ruby on Rails is released under the {MIT License}[http://www.opensource.org/licenses/MIT].
diff --git a/Rakefile b/Rakefile
index 99a27595e9..1caa69cf92 100644
--- a/Rakefile
+++ b/Rakefile
@@ -75,10 +75,10 @@ RDoc::Task.new do |rdoc|
rdoc_main.gsub!(/^(?=\S).*?\b(?=Rails)\b/) { "#$&\\" }
rdoc_main.gsub!(%r{link:/rails/rails/blob/master/(\w+)/README\.rdoc}, "link:files/\\1/README_rdoc.html")
- # Remove Travis and Gemnasium status images from API pages. Only GitHub
- # README page gets these images. Travis' https build image is used to avoid
- # GitHub caching: http://about.travis-ci.org/docs/user/status-images
- rdoc_main.gsub!(%r{^== (Build|Dependency) Status.*}, '')
+ # Remove Travis and Gemnasium status images from API pages. Only the GitHub
+ # README page gets these images. Travis's HTTPS build image is used to
+ # avoid GitHub caching: http://about.travis-ci.org/docs/user/status-images
+ rdoc_main.gsub!(/^== Code Status(\n(?!==).*)*/, '')
File.open(RDOC_MAIN, 'w') do |f|
f.write(rdoc_main)
diff --git a/actionmailer/CHANGELOG.md b/actionmailer/CHANGELOG.md
index 68b34805ff..28a5c0ab71 100644
--- a/actionmailer/CHANGELOG.md
+++ b/actionmailer/CHANGELOG.md
@@ -1,9 +1,9 @@
## Rails 4.0.0 (unreleased) ##
-* Support `Mailer.deliver_foo(*args)` as a synonym for
- `Mailer.foo(*args).deliver`. This makes it easy to write e.g.
- `Mailer.expects(:deliver_foo)` when testing code that calls
- the mailer. *Jon Leighton*
+* Do not render views when mail() isn't called.
+ Fix #7761
+
+ *Yves Senn*
* Allow delivery method options to be set per mail instance *Aditya Sanghi*
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb
index fee4a64248..a66e81f1c3 100644
--- a/actionmailer/lib/action_mailer/base.rb
+++ b/actionmailer/lib/action_mailer/base.rb
@@ -142,7 +142,6 @@ module ActionMailer
# for delivery later:
#
# Notifier.welcome(david).deliver # sends the email
- # Notifier.deliver_welcome(david) # synonym for the former
# mail = Notifier.welcome(david) # => a Mail::Message object
# mail.deliver # sends the email
#
@@ -488,8 +487,6 @@ module ActionMailer
def method_missing(method_name, *args)
if action_methods.include?(method_name.to_s)
QueuedMessage.new(queue, self, method_name, *args)
- elsif method_name.to_s =~ /^deliver_(.+)$/ && action_methods.include?($1)
- public_send($1, *args).deliver
else
super
end
@@ -510,7 +507,19 @@ module ActionMailer
def process(*args) #:nodoc:
lookup_context.skip_default_locale!
- super
+
+ generated_mail = super
+ unless generated_mail
+ @_message = NullMail.new
+ end
+ end
+
+ class NullMail #:nodoc:
+ def body; '' end
+
+ def method_missing(*args)
+ nil
+ end
end
def mailer_name
diff --git a/actionmailer/test/base_test.rb b/actionmailer/test/base_test.rb
index 1cb3ce63fe..b07b352082 100644
--- a/actionmailer/test/base_test.rb
+++ b/actionmailer/test/base_test.rb
@@ -499,6 +499,12 @@ class BaseTest < ActiveSupport::TestCase
end
end
+ test 'the view is not rendered when mail was never called' do
+ mail = BaseMailer.without_mail_call
+ assert_equal('', mail.body.to_s.strip)
+ mail.deliver
+ end
+
# Before and After hooks
class MyObserver
@@ -662,13 +668,6 @@ class BaseTest < ActiveSupport::TestCase
assert_equal ["robert.pankowecki@gmail.com"], DefaultFromMailer.welcome.from
end
- test "Mailer.deliver_welcome calls Mailer.welcome.deliver" do
- BaseMailer.deliveries.clear
- BaseMailer.deliver_welcome(subject: 'omg')
- assert_equal 1, BaseMailer.deliveries.length
- assert_equal 'omg', BaseMailer.deliveries.first.subject
- end
-
protected
# Execute the block setting the given values and restoring old values after
diff --git a/actionmailer/test/fixtures/base_mailer/without_mail_call.erb b/actionmailer/test/fixtures/base_mailer/without_mail_call.erb
new file mode 100644
index 0000000000..290379d5fb
--- /dev/null
+++ b/actionmailer/test/fixtures/base_mailer/without_mail_call.erb
@@ -0,0 +1 @@
+<% raise 'the template should not be rendered' %> \ No newline at end of file
diff --git a/actionmailer/test/mailers/base_mailer.rb b/actionmailer/test/mailers/base_mailer.rb
index f25d9b9aff..52342bc59e 100644
--- a/actionmailer/test/mailers/base_mailer.rb
+++ b/actionmailer/test/mailers/base_mailer.rb
@@ -115,4 +115,7 @@ class BaseMailer < ActionMailer::Base
def email_with_translations
mail body: render("email_with_translations", formats: [:html])
end
+
+ def without_mail_call
+ end
end
diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md
index 48ba1518e0..0ffae5086e 100644
--- a/actionpack/CHANGELOG.md
+++ b/actionpack/CHANGELOG.md
@@ -1,5 +1,10 @@
## Rails 4.0.0 (unreleased) ##
+* `BestStandardsSupport` middleware now appends it's `X-UA-Compatible` value to app's
+ returned value if any. Fix #8086
+
+ *Nikita Afanasenko*
+
* `date_select` helper accepts `with_css_classes: true` to add css classes similar with type
of generated select tags.
@@ -134,16 +139,6 @@
*Tima Maslyuchenko*
-* Fixed a bug with shorthand routes scoped with the `:module` option not
- adding the module to the controller as described in issue #6497.
- This should now work properly:
-
- scope :module => "engine" do
- get "api/version" # routes to engine/api#version
- end
-
- *Luiz Felipe Garcia Pereira*
-
* Sprockets integration has been extracted from Action Pack to the `sprockets-rails`
gem. `rails` gem is depending on `sprockets-rails` by default.
diff --git a/actionpack/lib/abstract_controller/base.rb b/actionpack/lib/abstract_controller/base.rb
index 388e043f0b..56dc9ab7a1 100644
--- a/actionpack/lib/abstract_controller/base.rb
+++ b/actionpack/lib/abstract_controller/base.rb
@@ -34,6 +34,15 @@ module AbstractController
@abstract = true
end
+ def inherited(klass) # :nodoc:
+ # define the abstract ivar on subclasses so that we don't get
+ # uninitialized ivar warnings
+ unless klass.instance_variable_defined?(:@abstract)
+ klass.instance_variable_set(:@abstract, false)
+ end
+ super
+ end
+
# A list of all internal methods for a controller. This finds the first
# abstract superclass of a controller, and gets a list of all public
# instance methods on that abstract class. Public instance methods of
@@ -42,6 +51,7 @@ module AbstractController
# (ActionController::Metal and ActionController::Base are defined as abstract)
def internal_methods
controller = self
+
controller = controller.superclass until controller.abstract?
controller.public_instance_methods(true)
end
diff --git a/actionpack/lib/abstract_controller/rendering.rb b/actionpack/lib/abstract_controller/rendering.rb
index 3da2834af0..4b984d0558 100644
--- a/actionpack/lib/abstract_controller/rendering.rb
+++ b/actionpack/lib/abstract_controller/rendering.rb
@@ -51,7 +51,7 @@ module AbstractController
@view_context_class ||= begin
routes = respond_to?(:_routes) && _routes
helpers = respond_to?(:_helpers) && _helpers
-
+
Class.new(ActionView::Base) do
if routes
include routes.url_helpers
diff --git a/actionpack/lib/action_controller/metal/exceptions.rb b/actionpack/lib/action_controller/metal/exceptions.rb
index 3c9d0c86a7..3844dbf2a6 100644
--- a/actionpack/lib/action_controller/metal/exceptions.rb
+++ b/actionpack/lib/action_controller/metal/exceptions.rb
@@ -3,6 +3,15 @@ module ActionController
end
class BadRequest < ActionControllerError #:nodoc:
+ attr_reader :original_exception
+
+ def initialize(type = nil, e = nil)
+ return super() unless type && e
+
+ super("Invalid #{type} parameters: #{e.message}")
+ @original_exception = e
+ set_backtrace e.backtrace
+ end
end
class RenderError < ActionControllerError #:nodoc:
diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb
index 73f2e94cd1..04dc1d37f7 100644
--- a/actionpack/lib/action_controller/metal/strong_parameters.rb
+++ b/actionpack/lib/action_controller/metal/strong_parameters.rb
@@ -196,7 +196,7 @@ module ActionController
def permit(*filters)
params = self.class.new
- filters.each do |filter|
+ filters.flatten.each do |filter|
case filter
when Symbol, String then
if has_key?(filter)
diff --git a/actionpack/lib/action_controller/record_identifier.rb b/actionpack/lib/action_controller/record_identifier.rb
index bffd2a02d0..b49128c184 100644
--- a/actionpack/lib/action_controller/record_identifier.rb
+++ b/actionpack/lib/action_controller/record_identifier.rb
@@ -8,12 +8,12 @@ module ActionController
'ActionView::RecodIdentifier module.'
def dom_id(record, prefix = nil)
- ActiveSupport::Deprecation.warn 'dom_id ' + MESSAGE
+ ActiveSupport::Deprecation.warn('dom_id ' + MESSAGE)
ActionView::RecordIdentifier.dom_id(record, prefix)
end
def dom_class(record, prefix = nil)
- ActiveSupport::Deprecation.warn 'dom_class ' + MESSAGE
+ ActiveSupport::Deprecation.warn('dom_class ' + MESSAGE)
ActionView::RecordIdentifier.dom_class(record, prefix)
end
end
diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb
index d007133183..5aecb59df9 100644
--- a/actionpack/lib/action_controller/test_case.rb
+++ b/actionpack/lib/action_controller/test_case.rb
@@ -476,7 +476,7 @@ module ActionController
def process(action, http_method = 'GET', *args)
check_required_ivars
- http_method, args = handle_old_process_api(http_method, args)
+ http_method, args = handle_old_process_api(http_method, args, caller)
if args.first.is_a?(String) && http_method != 'HEAD'
@request.env['RAW_POST_DATA'] = args.shift
@@ -579,10 +579,10 @@ module ActionController
end
end
- def handle_old_process_api(http_method, args)
+ def handle_old_process_api(http_method, args, callstack)
# 4.0: Remove this method.
if http_method.is_a?(Hash)
- ActiveSupport::Deprecation.warn("TestCase#process now expects the HTTP method as second argument: process(action, http_method, params, session, flash)")
+ ActiveSupport::Deprecation.warn("TestCase#process now expects the HTTP method as second argument: process(action, http_method, params, session, flash)", callstack)
args.unshift(http_method)
http_method = args.last.is_a?(String) ? args.last : "GET"
end
diff --git a/actionpack/lib/action_dispatch/http/request.rb b/actionpack/lib/action_dispatch/http/request.rb
index fc8825d6d9..3de927abc8 100644
--- a/actionpack/lib/action_dispatch/http/request.rb
+++ b/actionpack/lib/action_dispatch/http/request.rb
@@ -251,21 +251,17 @@ module ActionDispatch
# Override Rack's GET method to support indifferent access
def GET
- begin
- @env["action_dispatch.request.query_parameters"] ||= (normalize_parameters(super) || {})
- rescue TypeError => e
- raise ActionController::BadRequest, "Invalid query parameters: #{e.message}"
- end
+ @env["action_dispatch.request.query_parameters"] ||= (normalize_parameters(super) || {})
+ rescue TypeError => e
+ raise ActionController::BadRequest.new(:query, e)
end
alias :query_parameters :GET
# Override Rack's POST method to support indifferent access
def POST
- begin
- @env["action_dispatch.request.request_parameters"] ||= (normalize_parameters(super) || {})
- rescue TypeError => e
- raise ActionController::BadRequest, "Invalid request parameters: #{e.message}"
- end
+ @env["action_dispatch.request.request_parameters"] ||= (normalize_parameters(super) || {})
+ rescue TypeError => e
+ raise ActionController::BadRequest.new(:request, e)
end
alias :request_parameters :POST
diff --git a/actionpack/lib/action_dispatch/middleware/best_standards_support.rb b/actionpack/lib/action_dispatch/middleware/best_standards_support.rb
index 69adcc419f..d338996240 100644
--- a/actionpack/lib/action_dispatch/middleware/best_standards_support.rb
+++ b/actionpack/lib/action_dispatch/middleware/best_standards_support.rb
@@ -15,7 +15,13 @@ module ActionDispatch
def call(env)
status, headers, body = @app.call(env)
- headers["X-UA-Compatible"] = @header
+
+ if headers["X-UA-Compatible"] && @header
+ headers["X-UA-Compatible"] << "," << @header.to_s
+ else
+ headers["X-UA-Compatible"] = @header
+ end
+
[status, headers, body]
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/remote_ip.rb b/actionpack/lib/action_dispatch/middleware/remote_ip.rb
index ec15a2a715..5abf8f2802 100644
--- a/actionpack/lib/action_dispatch/middleware/remote_ip.rb
+++ b/actionpack/lib/action_dispatch/middleware/remote_ip.rb
@@ -63,9 +63,9 @@ module ActionDispatch
}x
def initialize(env, middleware)
- @env = env
- @middleware = middleware
- @calculated_ip = false
+ @env = env
+ @middleware = middleware
+ @ip = nil
end
# Determines originating IP address. REMOTE_ADDR is the standard
@@ -100,9 +100,7 @@ module ActionDispatch
end
def to_s
- return @ip if @calculated_ip
- @calculated_ip = true
- @ip = calculate_ip
+ @ip ||= calculate_ip
end
private
diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb
index e337e30766..045299281c 100644
--- a/actionpack/lib/action_dispatch/routing/mapper.rb
+++ b/actionpack/lib/action_dispatch/routing/mapper.rb
@@ -182,7 +182,7 @@ module ActionDispatch
controller ||= default_controller
action ||= default_action
- unless controller.is_a?(Regexp)
+ unless controller.is_a?(Regexp) || to_shorthand
controller = [@scope[:module], controller].compact.join("/").presence
end
diff --git a/actionpack/lib/action_dispatch/testing/integration.rb b/actionpack/lib/action_dispatch/testing/integration.rb
index 2928263163..95cd89a166 100644
--- a/actionpack/lib/action_dispatch/testing/integration.rb
+++ b/actionpack/lib/action_dispatch/testing/integration.rb
@@ -3,6 +3,7 @@ require 'uri'
require 'active_support/core_ext/kernel/singleton_class'
require 'active_support/core_ext/object/try'
require 'rack/test'
+require 'minitest/unit'
module ActionDispatch
module Integration #:nodoc:
@@ -497,8 +498,7 @@ module ActionDispatch
def self.app
if !@@app && !ActionDispatch.test_app
- ActiveSupport::Deprecation.warn "Rails application fallback is deprecated " \
- "and no longer works, please set ActionDispatch.test_app", caller
+ ActiveSupport::Deprecation.warn "Rails application fallback is deprecated and no longer works, please set ActionDispatch.test_app"
end
@@app || ActionDispatch.test_app
diff --git a/actionpack/lib/action_view/helpers/date_helper.rb b/actionpack/lib/action_view/helpers/date_helper.rb
index 77d8794b7d..459f95bb73 100644
--- a/actionpack/lib/action_view/helpers/date_helper.rb
+++ b/actionpack/lib/action_view/helpers/date_helper.rb
@@ -69,7 +69,7 @@ module ActionView
options = include_seconds_or_options
else
ActiveSupport::Deprecation.warn "distance_of_time_in_words and time_ago_in_words now accept :include_seconds " +
- "as a part of options hash, not a boolean argument", caller
+ "as a part of options hash, not a boolean argument"
options[:include_seconds] ||= !!include_seconds_or_options
end
diff --git a/actionpack/lib/action_view/helpers/form_helper.rb b/actionpack/lib/action_view/helpers/form_helper.rb
index b87c2e936f..6abf1e1751 100644
--- a/actionpack/lib/action_view/helpers/form_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_helper.rb
@@ -1181,8 +1181,7 @@ module ActionView
def initialize(object_name, object, template, options, block=nil)
if block
- ActiveSupport::Deprecation.warn(
- "Giving a block to FormBuilder is deprecated and has no effect anymore.")
+ ActiveSupport::Deprecation.warn "Giving a block to FormBuilder is deprecated and has no effect anymore."
end
@nested_child_index = {}
diff --git a/actionpack/lib/action_view/helpers/form_options_helper.rb b/actionpack/lib/action_view/helpers/form_options_helper.rb
index a33b233ed5..b7b3db959e 100644
--- a/actionpack/lib/action_view/helpers/form_options_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_options_helper.rb
@@ -519,7 +519,9 @@ module ActionView
else
prompt = options
options = {}
- ActiveSupport::Deprecation.warn "Passing the prompt to grouped_options_for_select as an argument is deprecated. Please use an options hash like `{ prompt: #{prompt.inspect} }`."
+ message = "Passing the prompt to grouped_options_for_select as an argument is deprecated. " \
+ "Please use an options hash like `{ prompt: #{prompt.inspect} }`."
+ ActiveSupport::Deprecation.warn message
end
body = "".html_safe
diff --git a/actionpack/lib/action_view/helpers/form_tag_helper.rb b/actionpack/lib/action_view/helpers/form_tag_helper.rb
index 0257a13bc4..7f42d6e9c3 100644
--- a/actionpack/lib/action_view/helpers/form_tag_helper.rb
+++ b/actionpack/lib/action_view/helpers/form_tag_helper.rb
@@ -425,13 +425,17 @@ module ActionView
options = options.stringify_keys
if disable_with = options.delete("disable_with")
- ActiveSupport::Deprecation.warn ":disable_with option is deprecated and will be removed from Rails 4.1. Use ':data => { :disable_with => \'Text\' }' instead"
+ message = ":disable_with option is deprecated and will be removed from Rails 4.1. " \
+ "Use 'data: { disable_with: \'Text\' }' instead."
+ ActiveSupport::Deprecation.warn message
options["data-disable-with"] = disable_with
end
if confirm = options.delete("confirm")
- ActiveSupport::Deprecation.warn ":confirm option is deprecated and will be removed from Rails 4.1. Use ':data => { :confirm => \'Text\' }' instead'"
+ message = ":confirm option is deprecated and will be removed from Rails 4.1. " \
+ "Use 'data: { confirm: \'Text\' }' instead'."
+ ActiveSupport::Deprecation.warn message
options["data-confirm"] = confirm
end
@@ -483,13 +487,17 @@ module ActionView
options = options.stringify_keys
if disable_with = options.delete("disable_with")
- ActiveSupport::Deprecation.warn ":disable_with option is deprecated and will be removed from Rails 4.1. Use ':data => { :disable_with => \'Text\' }' instead"
+ message = ":disable_with option is deprecated and will be removed from Rails 4.1. " \
+ "Use 'data: { disable_with: \'Text\' }' instead."
+ ActiveSupport::Deprecation.warn message
options["data-disable-with"] = disable_with
end
if confirm = options.delete("confirm")
- ActiveSupport::Deprecation.warn ":confirm option is deprecated and will be removed from Rails 4.1. Use ':data => { :confirm => \'Text\' }' instead'"
+ message = ":confirm option is deprecated and will be removed from Rails 4.1. " \
+ "Use 'data: { confirm: \'Text\' }' instead'."
+ ActiveSupport::Deprecation.warn message
options["data-confirm"] = confirm
end
@@ -533,7 +541,9 @@ module ActionView
options = options.stringify_keys
if confirm = options.delete("confirm")
- ActiveSupport::Deprecation.warn ":confirm option is deprecated and will be removed from Rails 4.1. Use ':data => { :confirm => \'Text\' }' instead'"
+ message = ":confirm option is deprecated and will be removed from Rails 4.1. " \
+ "Use 'data: { confirm: \'Text\' }' instead'."
+ ActiveSupport::Deprecation.warn message
options["data-confirm"] = confirm
end
diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb
index a30326349a..1a99fc7091 100644
--- a/actionpack/lib/action_view/helpers/javascript_helper.rb
+++ b/actionpack/lib/action_view/helpers/javascript_helper.rb
@@ -78,7 +78,8 @@ module ActionView
# # => <input class="ok" onclick="alert('Hello world!');" type="button" value="Greeting" />
#
def button_to_function(name, function=nil, html_options={})
- message = "button_to_function is deprecated and will be removed from Rails 4.1. Use Unobtrusive JavaScript instead."
+ message = "button_to_function is deprecated and will be removed from Rails 4.1. We recomend to use Unobtrusive JavaScript instead. " +
+ "See http://guides.rubyonrails.org/working_with_javascript_in_rails.html#unobtrusive-javascript"
ActiveSupport::Deprecation.warn message
onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function};"
@@ -99,7 +100,8 @@ module ActionView
# # => <a class="nav_link" href="#" onclick="alert('Hello world!'); return false;">Greeting</a>
#
def link_to_function(name, function, html_options={})
- message = "link_to_function is deprecated and will be removed from Rails 4.1. Use Unobtrusive JavaScript instead."
+ message = "link_to_function is deprecated and will be removed from Rails 4.1. We recomend to use Unobtrusive JavaScript instead. " +
+ "See http://guides.rubyonrails.org/working_with_javascript_in_rails.html#unobtrusive-javascript"
ActiveSupport::Deprecation.warn message
onclick = "#{"#{html_options[:onclick]}; " if html_options[:onclick]}#{function}; return false;"
diff --git a/actionpack/lib/action_view/helpers/url_helper.rb b/actionpack/lib/action_view/helpers/url_helper.rb
index 9bfda0ee9c..fd671c9c07 100644
--- a/actionpack/lib/action_view/helpers/url_helper.rb
+++ b/actionpack/lib/action_view/helpers/url_helper.rb
@@ -577,7 +577,9 @@ module ActionView
method = html_options.delete('method')
if confirm
- ActiveSupport::Deprecation.warn ":confirm option is deprecated and will be removed from Rails 4.1. Use ':data => { :confirm => \'Text\' }' instead"
+ message = ":confirm option is deprecated and will be removed from Rails 4.1. " \
+ "Use 'data: { confirm: \'Text\' }' instead."
+ ActiveSupport::Deprecation.warn message
html_options["data-confirm"] = confirm
end
@@ -585,7 +587,9 @@ module ActionView
add_method_to_attributes!(html_options, method) if method
if disable_with
- ActiveSupport::Deprecation.warn ":disable_with option is deprecated and will be removed from Rails 4.1. Use ':data => { :disable_with => \'Text\' }' instead"
+ message = ":disable_with option is deprecated and will be removed from Rails 4.1. " \
+ "Use 'data: { disable_with: \'Text\' }' instead."
+ ActiveSupport::Deprecation.warn message
html_options["data-disable-with"] = disable_with
end
diff --git a/actionpack/lib/action_view/renderer/template_renderer.rb b/actionpack/lib/action_view/renderer/template_renderer.rb
index 156ad4e547..2a5ea5a711 100644
--- a/actionpack/lib/action_view/renderer/template_renderer.rb
+++ b/actionpack/lib/action_view/renderer/template_renderer.rb
@@ -29,8 +29,11 @@ module ActionView
handler = Template.handler_for_extension(options[:type] || "erb")
Template.new(options[:inline], "inline template", handler, :locals => keys)
elsif options.key?(:template)
- options[:template].respond_to?(:render) ?
- options[:template] : find_template(options[:template], options[:prefixes], false, keys, @details)
+ if options[:template].respond_to?(:render)
+ options[:template]
+ else
+ find_template(options[:template], options[:prefixes], false, keys, @details)
+ end
else
raise ArgumentError, "You invoked render but did not give any of :partial, :template, :inline, :file or :text option."
end
diff --git a/actionpack/lib/action_view/template.rb b/actionpack/lib/action_view/template.rb
index 379cdc8a25..aefc42be48 100644
--- a/actionpack/lib/action_view/template.rb
+++ b/actionpack/lib/action_view/template.rb
@@ -149,7 +149,8 @@ module ActionView
end
def mime_type
- ActiveSupport::Deprecation.warn 'Template#mime_type is deprecated and will be removed in Rails 4.1. Please use type method instead.'
+ message = 'Template#mime_type is deprecated and will be removed in Rails 4.1. Please use type method instead.'
+ ActiveSupport::Deprecation.warn message
@mime_type ||= Mime::Type.lookup_by_extension(@formats.first.to_s) if @formats.first
end
diff --git a/actionpack/lib/action_view/template/resolver.rb b/actionpack/lib/action_view/template/resolver.rb
index 25c6fd4aa8..fc77c1485d 100644
--- a/actionpack/lib/action_view/template/resolver.rb
+++ b/actionpack/lib/action_view/template/resolver.rb
@@ -232,8 +232,14 @@ module ActionView
def extract_handler_and_format(path, default_formats)
pieces = File.basename(path).split(".")
pieces.shift
+
extension = pieces.pop
- ActiveSupport::Deprecation.warn "The file #{path} did not specify a template handler. The default is currently ERB, but will change to RAW in the future." unless extension
+ unless extension
+ message = "The file #{path} did not specify a template handler. The default is currently ERB, " \
+ "but will change to RAW in the future."
+ ActiveSupport::Deprecation.warn message
+ end
+
handler = Template.handler_for_extension(extension)
format = pieces.last && Template::Types[pieces.last]
[handler, format]
diff --git a/actionpack/test/activerecord/controller_runtime_test.rb b/actionpack/test/activerecord/controller_runtime_test.rb
index 2d789395ce..1df826fe2b 100644
--- a/actionpack/test/activerecord/controller_runtime_test.rb
+++ b/actionpack/test/activerecord/controller_runtime_test.rb
@@ -15,7 +15,7 @@ class ControllerRuntimeLogSubscriberTest < ActionController::TestCase
def zero
render :inline => "Zero DB runtime"
end
-
+
def redirect
Project.all
redirect_to :action => 'show'
@@ -63,18 +63,18 @@ class ControllerRuntimeLogSubscriberTest < ActionController::TestCase
assert_equal 2, @logger.logged(:info).size
assert_match(/\(Views: [\d.]+ms \| ActiveRecord: 0.0ms\)/, @logger.logged(:info)[1])
end
-
+
def test_log_with_active_record_when_redirecting
get :redirect
wait
assert_equal 3, @logger.logged(:info).size
assert_match(/\(ActiveRecord: [\d.]+ms\)/, @logger.logged(:info)[2])
end
-
+
def test_include_time_query_time_after_rendering
get :db_after_render
wait
-
+
assert_equal 2, @logger.logged(:info).size
assert_match(/\(Views: [\d.]+ms \| ActiveRecord: ([1-9][\d.]+)ms\)/, @logger.logged(:info)[1])
end
diff --git a/actionpack/test/controller/default_url_options_with_filter_test.rb b/actionpack/test/controller/default_url_options_with_filter_test.rb
index ef028e8cdb..9a9ab17fee 100644
--- a/actionpack/test/controller/default_url_options_with_filter_test.rb
+++ b/actionpack/test/controller/default_url_options_with_filter_test.rb
@@ -16,7 +16,7 @@ class ControllerWithBeforeFilterAndDefaultUrlOptions < ActionController::Base
def default_url_options
{:locale => "de"}
- end
+ end
end
class ControllerWithBeforeFilterAndDefaultUrlOptionsTest < ActionController::TestCase
diff --git a/actionpack/test/controller/http_basic_authentication_test.rb b/actionpack/test/controller/http_basic_authentication_test.rb
index 7286b249c7..2dcfda02a7 100644
--- a/actionpack/test/controller/http_basic_authentication_test.rb
+++ b/actionpack/test/controller/http_basic_authentication_test.rb
@@ -19,7 +19,7 @@ class HttpBasicAuthenticationTest < ActionController::TestCase
def show
render :text => 'Only for loooooong credentials'
end
-
+
def search
render :text => 'All inline'
end
@@ -118,7 +118,7 @@ class HttpBasicAuthenticationTest < ActionController::TestCase
assert assigns(:logged_in)
assert_equal 'Definitely Maybe', @response.body
end
-
+
test "authenticate with class method" do
@request.env['HTTP_AUTHORIZATION'] = encode_credentials('David', 'Goliath')
get :search
diff --git a/actionpack/test/controller/mime_responds_test.rb b/actionpack/test/controller/mime_responds_test.rb
index b21d35c846..d183b0be17 100644
--- a/actionpack/test/controller/mime_responds_test.rb
+++ b/actionpack/test/controller/mime_responds_test.rb
@@ -240,7 +240,7 @@ class RespondToControllerTest < ActionController::TestCase
assert_equal 'HTML', @response.body
@request.accept = "text/javascript, text/html"
-
+
assert_raises(ActionController::UnknownFormat) do
xhr :get, :just_xml
end
diff --git a/actionpack/test/controller/new_base/middleware_test.rb b/actionpack/test/controller/new_base/middleware_test.rb
index ccef060863..6b7b5e10e3 100644
--- a/actionpack/test/controller/new_base/middleware_test.rb
+++ b/actionpack/test/controller/new_base/middleware_test.rb
@@ -25,14 +25,14 @@ module MiddlewareTest
result
end
end
-
+
class BlockMiddleware
attr_accessor :configurable_message
def initialize(app, &block)
@app = app
yield(self) if block_given?
end
-
+
def call(env)
result = @app.call(env)
result[1]["Configurable-Message"] = configurable_message
diff --git a/actionpack/test/controller/new_base/render_partial_test.rb b/actionpack/test/controller/new_base/render_partial_test.rb
index b4a25c49c9..2f1aa22208 100644
--- a/actionpack/test/controller/new_base/render_partial_test.rb
+++ b/actionpack/test/controller/new_base/render_partial_test.rb
@@ -28,7 +28,7 @@ module RenderPartial
@test_unchanged = 'hello'
end
end
-
+
class ChildController < BasicController; end
class TestPartial < Rack::TestCase
diff --git a/actionpack/test/controller/parameters/parameters_permit_test.rb b/actionpack/test/controller/parameters/parameters_permit_test.rb
index ad970f0a9a..fc63470174 100644
--- a/actionpack/test/controller/parameters/parameters_permit_test.rb
+++ b/actionpack/test/controller/parameters/parameters_permit_test.rb
@@ -77,4 +77,8 @@ class ParametersPermitTest < ActiveSupport::TestCase
ActionController::Parameters.permit_all_parameters = false
end
end
+
+ test "permitting parameters as an array" do
+ assert_equal "32", @params[:person].permit([ :age ])[:age]
+ end
end
diff --git a/actionpack/test/controller/send_file_test.rb b/actionpack/test/controller/send_file_test.rb
index 97ede35317..8bf3096888 100644
--- a/actionpack/test/controller/send_file_test.rb
+++ b/actionpack/test/controller/send_file_test.rb
@@ -134,7 +134,7 @@ class SendFileTest < ActionController::TestCase
@controller.headers = {}
assert_raise(ArgumentError){ @controller.send(:send_file_headers!, options) }
end
-
+
def test_send_file_headers_guess_type_from_extension
{
'image.png' => 'image/png',
diff --git a/actionpack/test/dispatch/best_standards_support_test.rb b/actionpack/test/dispatch/best_standards_support_test.rb
new file mode 100644
index 0000000000..0737c40a39
--- /dev/null
+++ b/actionpack/test/dispatch/best_standards_support_test.rb
@@ -0,0 +1,34 @@
+require 'abstract_unit'
+
+class BestStandardsSupportTest < ActiveSupport::TestCase
+ def test_with_best_standards_support
+ _, headers, _ = app(true, {}).call({})
+ assert_equal "IE=Edge,chrome=1", headers["X-UA-Compatible"]
+ end
+
+ def test_with_builtin_best_standards_support
+ _, headers, _ = app(:builtin, {}).call({})
+ assert_equal "IE=Edge", headers["X-UA-Compatible"]
+ end
+
+ def test_without_best_standards_support
+ _, headers, _ = app(false, {}).call({})
+ assert_equal nil, headers["X-UA-Compatible"]
+ end
+
+ def test_appends_to_app_headers
+ app_headers = { "X-UA-Compatible" => "requiresActiveX=true" }
+ _, headers, _ = app(true, app_headers).call({})
+
+ expects = "requiresActiveX=true,IE=Edge,chrome=1"
+ assert_equal expects, headers["X-UA-Compatible"]
+ end
+
+ private
+
+ def app(type, headers)
+ app = proc { [200, headers, "response"] }
+ ActionDispatch::BestStandardsSupport.new(app, type)
+ end
+
+end
diff --git a/actionpack/test/dispatch/request_test.rb b/actionpack/test/dispatch/request_test.rb
index a2b9571660..e2964f9071 100644
--- a/actionpack/test/dispatch/request_test.rb
+++ b/actionpack/test/dispatch/request_test.rb
@@ -550,15 +550,30 @@ class RequestTest < ActiveSupport::TestCase
test "parameters still accessible after rack parse error" do
mock_rack_env = { "QUERY_STRING" => "x[y]=1&x[y][][w]=2", "rack.input" => "foo" }
request = nil
- begin
- request = stub_request(mock_rack_env)
- request.parameters
- rescue ActionController::BadRequest
+ request = stub_request(mock_rack_env)
+
+ assert_raises(ActionController::BadRequest) do
# rack will raise a TypeError when parsing this query string
+ request.parameters
end
+
assert_equal({}, request.parameters)
end
+ test "we have access to the original exception" do
+ mock_rack_env = { "QUERY_STRING" => "x[y]=1&x[y][][w]=2", "rack.input" => "foo" }
+ request = nil
+ request = stub_request(mock_rack_env)
+
+ e = assert_raises(ActionController::BadRequest) do
+ # rack will raise a TypeError when parsing this query string
+ request.parameters
+ end
+
+ assert e.original_exception
+ assert_equal e.original_exception.backtrace, e.backtrace
+ end
+
test "formats with accept header" do
request = stub_request 'HTTP_ACCEPT' => 'text/html'
request.expects(:parameters).at_least_once.returns({})
diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb
index 93d89f7568..34606512dc 100644
--- a/actionpack/test/dispatch/routing_test.rb
+++ b/actionpack/test/dispatch/routing_test.rb
@@ -281,6 +281,8 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
scope(':version', :version => /.+/) do
resources :users, :id => /.+?/, :format => /json|xml/
end
+
+ get "products/list"
end
get 'sprockets.js' => ::TestRoutingMapper::SprocketsApp
@@ -363,7 +365,6 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
resources :errors, :shallow => true do
resources :notices
end
- get 'api/version'
end
scope :path => 'api' do
@@ -1301,10 +1302,10 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest
assert_equal 'account#shorthand', @response.body
end
- def test_match_shorthand_with_module
- assert_equal '/api/version', api_version_path
- get '/api/version'
- assert_equal 'api/api#version', @response.body
+ def test_match_shorthand_inside_namespace_with_controller
+ assert_equal '/api/products/list', api_products_list_path
+ get '/api/products/list'
+ assert_equal 'api/products#list', @response.body
end
def test_dynamically_generated_helpers_on_collection_do_not_clobber_resources_url_helper
diff --git a/actionpack/test/template/digestor_test.rb b/actionpack/test/template/digestor_test.rb
index b9d26da3af..f493c8201d 100644
--- a/actionpack/test/template/digestor_test.rb
+++ b/actionpack/test/template/digestor_test.rb
@@ -63,7 +63,7 @@ class TemplateDigestorTest < ActionView::TestCase
change_template("comments/_comment")
end
end
-
+
def test_directory_depth_dependency
assert_digest_difference("level/below/index") do
change_template("level/below/_header")
diff --git a/actionpack/test/template/form_tag_helper_test.rb b/actionpack/test/template/form_tag_helper_test.rb
index 945dff2a29..0a94fa079b 100644
--- a/actionpack/test/template/form_tag_helper_test.rb
+++ b/actionpack/test/template/form_tag_helper_test.rb
@@ -411,7 +411,7 @@ class FormTagHelperTest < ActionView::TestCase
end
def test_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_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use 'data: { confirm: \'Text\' }' instead" do
assert_dom_equal(
%(<input name='commit' type='submit' value='Save' data-confirm="Are you sure?" />),
submit_tag("Save", :confirm => "Are you sure?")
@@ -478,7 +478,7 @@ class FormTagHelperTest < ActionView::TestCase
end
def test_button_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_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use 'data: { confirm: \'Text\' }' instead" do
assert_dom_equal(
%(<button name="button" type="submit" data-confirm="Are you sure?">Save</button>),
button_tag("Save", :type => "submit", :confirm => "Are you sure?")
@@ -494,7 +494,7 @@ class FormTagHelperTest < ActionView::TestCase
end
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_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?" />),
image_submit_tag("save.gif", :confirm => "Are you sure?")
diff --git a/actionpack/test/template/javascript_helper_test.rb b/actionpack/test/template/javascript_helper_test.rb
index 58784c26fa..56919dc592 100644
--- a/actionpack/test/template/javascript_helper_test.rb
+++ b/actionpack/test/template/javascript_helper_test.rb
@@ -43,42 +43,42 @@ class JavaScriptHelperTest < ActionView::TestCase
end
def test_button_to_function
- assert_deprecated "button_to_function is deprecated and will be removed from Rails 4.1. Use Unobtrusive JavaScript instead." do
+ assert_deprecated do
assert_dom_equal %(<input type="button" onclick="alert(&#39;Hello world!&#39;);" value="Greeting" />),
button_to_function("Greeting", "alert('Hello world!')")
end
end
def test_button_to_function_with_onclick
- assert_deprecated "button_to_function is deprecated and will be removed from Rails 4.1. Use Unobtrusive JavaScript instead." do
+ assert_deprecated do
assert_dom_equal "<input onclick=\"alert(&#39;Goodbye World :(&#39;); alert(&#39;Hello world!&#39;);\" type=\"button\" value=\"Greeting\" />",
button_to_function("Greeting", "alert('Hello world!')", :onclick => "alert('Goodbye World :(')")
end
end
def test_button_to_function_without_function
- assert_deprecated "button_to_function is deprecated and will be removed from Rails 4.1. Use Unobtrusive JavaScript instead." do
+ assert_deprecated do
assert_dom_equal "<input onclick=\";\" type=\"button\" value=\"Greeting\" />",
button_to_function("Greeting")
end
end
def test_link_to_function
- assert_deprecated "link_to_function is deprecated and will be removed from Rails 4.1. Use Unobtrusive JavaScript instead." do
+ assert_deprecated do
assert_dom_equal %(<a href="#" onclick="alert(&#39;Hello world!&#39;); return false;">Greeting</a>),
link_to_function("Greeting", "alert('Hello world!')")
end
end
def test_link_to_function_with_existing_onclick
- assert_deprecated "link_to_function is deprecated and will be removed from Rails 4.1. Use Unobtrusive JavaScript instead." do
+ assert_deprecated do
assert_dom_equal %(<a href="#" onclick="confirm(&#39;Sanity!&#39;); alert(&#39;Hello world!&#39;); return false;">Greeting</a>),
link_to_function("Greeting", "alert('Hello world!')", :onclick => "confirm('Sanity!')")
end
end
def test_function_with_href
- assert_deprecated "link_to_function is deprecated and will be removed from Rails 4.1. Use Unobtrusive JavaScript instead." do
+ assert_deprecated do
assert_dom_equal %(<a href="http://example.com/" onclick="alert(&#39;Hello world!&#39;); return false;">Greeting</a>),
link_to_function("Greeting", "alert('Hello world!')", :href => 'http://example.com/')
end
diff --git a/actionpack/test/template/render_test.rb b/actionpack/test/template/render_test.rb
index ddf5c6a1b3..4e6a676fc6 100644
--- a/actionpack/test/template/render_test.rb
+++ b/actionpack/test/template/render_test.rb
@@ -451,12 +451,12 @@ module RenderTestCases
assert_equal %(<title>David</title>),
@view.render(:file => "test/layout_render_object")
end
-
+
def test_render_with_passing_couple_extensions_to_one_register_template_handler_function_call
ActionView::Template.register_template_handler :foo1, :foo2, CustomHandler
assert_equal @view.render(:inline => "Hello, World!", :type => :foo1), @view.render(:inline => "Hello, World!", :type => :foo2)
end
-
+
def test_render_throws_exception_when_no_extensions_passed_to_register_template_handler_function_call
assert_raises(ArgumentError) { ActionView::Template.register_template_handler CustomHandler }
end
diff --git a/actionpack/test/template/tag_helper_test.rb b/actionpack/test/template/tag_helper_test.rb
index f0a7ce0bc9..9e711c6529 100644
--- a/actionpack/test/template/tag_helper_test.rb
+++ b/actionpack/test/template/tag_helper_test.rb
@@ -87,6 +87,11 @@ class TagHelperTest < ActionView::TestCase
assert_equal "<p class=\"song play>\">limelight</p>", str
end
+ def test_content_tag_with_data_attributes
+ assert_dom_equal '<p data-number="1" data-string="hello" data-string-with-quotes="double&quot;quote&quot;party&quot;">limelight</p>',
+ content_tag('p', "limelight", data: { number: 1, string: 'hello', string_with_quotes: 'double"quote"party"' })
+ end
+
def test_cdata_section
assert_equal "<![CDATA[<hello world>]]>", cdata_section("<hello world>")
end
@@ -118,8 +123,8 @@ class TagHelperTest < ActionView::TestCase
def test_data_attributes
['data', :data].each { |data|
- assert_dom_equal '<a data-a-float="3.14" data-a-big-decimal="-123.456" data-a-number="1" data-array="[1,2,3]" data-hash="{&quot;key&quot;:&quot;value&quot;}" data-string="hello" data-symbol="foo" />',
- tag('a', { data => { :a_float => 3.14, :a_big_decimal => BigDecimal.new("-123.456"), :a_number => 1, :string => 'hello', :symbol => :foo, :array => [1, 2, 3], :hash => { :key => 'value'} } })
+ assert_dom_equal '<a data-a-float="3.14" data-a-big-decimal="-123.456" data-a-number="1" data-array="[1,2,3]" data-hash="{&quot;key&quot;:&quot;value&quot;}" data-string-with-quotes="double&quot;quote&quot;party&quot;" data-string="hello" data-symbol="foo" />',
+ tag('a', { data => { a_float: 3.14, a_big_decimal: BigDecimal.new("-123.456"), a_number: 1, string: 'hello', symbol: :foo, array: [1, 2, 3], hash: { key: 'value'}, string_with_quotes: 'double"quote"party"' } })
}
end
end
diff --git a/actionpack/test/template/url_helper_test.rb b/actionpack/test/template/url_helper_test.rb
index bbfdf7f944..1bb625213d 100644
--- a/actionpack/test/template/url_helper_test.rb
+++ b/actionpack/test/template/url_helper_test.rb
@@ -95,7 +95,7 @@ class UrlHelperTest < ActiveSupport::TestCase
end
def test_button_to_with_deprecated_confirm
- assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use ':data => { :confirm => \'Text\' }' instead" do
+ assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use 'data: { confirm: \'Text\' }' instead" do
assert_dom_equal(
%{<form method="post" action="http://www.example.com" class="button_to"><div><input data-confirm="Are you sure?" type="submit" value="Hello" /></div></form>},
button_to("Hello", "http://www.example.com", confirm: "Are you sure?")
@@ -111,7 +111,7 @@ class UrlHelperTest < ActiveSupport::TestCase
end
def test_button_to_with_javascript_deprecated_disable_with
- assert_deprecated ":disable_with option is deprecated and will be removed from Rails 4.1. Use ':data => { :disable_with => \'Text\' }' instead" do
+ assert_deprecated ":disable_with option is deprecated and will be removed from Rails 4.1. Use 'data: { disable_with: \'Text\' }' instead" do
assert_dom_equal(
%{<form method="post" action="http://www.example.com" class="button_to"><div><input data-disable-with="Greeting..." type="submit" value="Hello" /></div></form>},
button_to("Hello", "http://www.example.com", disable_with: "Greeting...")
@@ -134,7 +134,7 @@ class UrlHelperTest < ActiveSupport::TestCase
end
def test_button_to_with_remote_and_javascript_with_deprecated_confirm
- assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use ':data => { :confirm => \'Text\' }' instead" do
+ assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use 'data: { confirm: \'Text\' }' instead" do
assert_dom_equal(
%{<form method="post" action="http://www.example.com" class="button_to" data-remote="true"><div><input data-confirm="Are you sure?" type="submit" value="Hello" /></div></form>},
button_to("Hello", "http://www.example.com", remote: true, confirm: "Are you sure?")
@@ -150,7 +150,7 @@ class UrlHelperTest < ActiveSupport::TestCase
end
def test_button_to_with_remote_and_javascript_deprecated_disable_with
- assert_deprecated ":disable_with option is deprecated and will be removed from Rails 4.1. Use ':data => { :disable_with => \'Text\' }' instead" do
+ assert_deprecated ":disable_with option is deprecated and will be removed from Rails 4.1. Use 'data: { disable_with: \'Text\' }' instead" do
assert_dom_equal(
%{<form method="post" action="http://www.example.com" class="button_to" data-remote="true"><div><input data-disable-with="Greeting..." type="submit" value="Hello" /></div></form>},
button_to("Hello", "http://www.example.com", remote: true, disable_with: "Greeting...")
@@ -267,19 +267,19 @@ class UrlHelperTest < ActiveSupport::TestCase
end
def test_link_tag_with_deprecated_confirm
- assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use ':data => { :confirm => \'Text\' }' instead" do
+ assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use 'data: { confirm: \'Text\' }' instead" do
assert_dom_equal(
%{<a href="http://www.example.com" data-confirm="Are you sure?">Hello</a>},
link_to("Hello", "http://www.example.com", confirm: "Are you sure?")
)
end
- assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use ':data => { :confirm => \'Text\' }' instead" do
+ assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use 'data: { confirm: \'Text\' }' instead" do
assert_dom_equal(
%{<a href="http://www.example.com" data-confirm="You cant possibly be sure, can you?">Hello</a>},
link_to("Hello", "http://www.example.com", confirm: "You cant possibly be sure, can you?")
)
end
- assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use ':data => { :confirm => \'Text\' }' instead" do
+ assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use 'data: { confirm: \'Text\' }' instead" do
assert_dom_equal(
%{<a href="http://www.example.com" data-confirm="You cant possibly be sure,\n can you?">Hello</a>},
link_to("Hello", "http://www.example.com", confirm: "You cant possibly be sure,\n can you?")
@@ -351,7 +351,7 @@ class UrlHelperTest < ActiveSupport::TestCase
end
def test_link_tag_using_post_javascript_and_with_deprecated_confirm
- assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use ':data => { :confirm => \'Text\' }' instead" do
+ assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use 'data: { confirm: \'Text\' }' instead" do
assert_dom_equal(
%{<a href="http://www.example.com" data-method="post" rel="nofollow" data-confirm="Are you serious?">Hello</a>},
link_to("Hello", "http://www.example.com", method: :post, confirm: "Are you serious?")
@@ -367,7 +367,7 @@ class UrlHelperTest < ActiveSupport::TestCase
end
def test_link_tag_using_delete_javascript_and_href_and_with_deprecated_confirm
- assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use ':data => { :confirm => \'Text\' }' instead" do
+ assert_deprecated ":confirm option is deprecated and will be removed from Rails 4.1. Use 'data: { confirm: \'Text\' }' instead" do
assert_dom_equal(
%{<a href="\#" rel="nofollow" data-confirm="Are you serious?" data-method="delete">Destroy</a>},
link_to("Destroy", "http://www.example.com", method: :delete, href: '#', confirm: "Are you serious?")
diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb
index a1d01b2c89..86eaad830e 100644
--- a/activemodel/lib/active_model/attribute_methods.rb
+++ b/activemodel/lib/active_model/attribute_methods.rb
@@ -383,12 +383,11 @@ module ActiveModel
def initialize(options = {})
if options[:prefix] == '' || options[:suffix] == ''
- ActiveSupport::Deprecation.warn(
- "Specifying an empty prefix/suffix for an attribute method is no longer " \
- "necessary. If the un-prefixed/suffixed version of the method has not been " \
- "defined when `define_attribute_methods` is called, it will be defined " \
- "automatically."
- )
+ message = "Specifying an empty prefix/suffix for an attribute method is no longer " \
+ "necessary. If the un-prefixed/suffixed version of the method has not been " \
+ "defined when `define_attribute_methods` is called, it will be defined " \
+ "automatically."
+ ActiveSupport::Deprecation.warn message
end
@prefix, @suffix = options.fetch(:prefix, ''), options.fetch(:suffix, '')
diff --git a/activemodel/lib/active_model/observing.rb b/activemodel/lib/active_model/observing.rb
index 9419645e7b..5f1c99ce62 100644
--- a/activemodel/lib/active_model/observing.rb
+++ b/activemodel/lib/active_model/observing.rb
@@ -172,7 +172,7 @@ module ActiveModel
# <tt>count_observers</tt> is deprecated. Use #observers_count.
def count_observers
msg = "count_observers is deprecated in favor of observers_count"
- ActiveSupport::Deprecation.warn(msg)
+ ActiveSupport::Deprecation.warn msg
observers_count
end
diff --git a/activemodel/lib/active_model/serializers/json.rb b/activemodel/lib/active_model/serializers/json.rb
index a4252b995d..9d984b7a18 100644
--- a/activemodel/lib/active_model/serializers/json.rb
+++ b/activemodel/lib/active_model/serializers/json.rb
@@ -1,8 +1,8 @@
require 'active_support/json'
module ActiveModel
- # == Active Model JSON Serializer
module Serializers
+ # == Active Model JSON Serializer
module JSON
extend ActiveSupport::Concern
include ActiveModel::Serialization
diff --git a/activemodel/lib/active_model/serializers/xml.rb b/activemodel/lib/active_model/serializers/xml.rb
index cf742d0569..fb6093cce5 100755
--- a/activemodel/lib/active_model/serializers/xml.rb
+++ b/activemodel/lib/active_model/serializers/xml.rb
@@ -4,12 +4,16 @@ require 'active_support/core_ext/hash/conversions'
require 'active_support/core_ext/hash/slice'
module ActiveModel
- # == Active Model XML Serializer
module Serializers
+ # == Active Model XML Serializer
module Xml
extend ActiveSupport::Concern
include ActiveModel::Serialization
+ included do
+ extend ActiveModel::Naming
+ end
+
class Serializer #:nodoc:
class Attribute #:nodoc:
attr_reader :name, :value, :type
diff --git a/activemodel/test/cases/serializers/json_serialization_test.rb b/activemodel/test/cases/serializers/json_serialization_test.rb
index e2690f1827..fd4d068354 100644
--- a/activemodel/test/cases/serializers/json_serialization_test.rb
+++ b/activemodel/test/cases/serializers/json_serialization_test.rb
@@ -4,7 +4,6 @@ require 'models/automobile'
require 'active_support/core_ext/object/instance_variables'
class Contact
- extend ActiveModel::Naming
include ActiveModel::Serializers::JSON
include ActiveModel::Validations
@@ -156,6 +155,15 @@ class JsonSerializationTest < ActiveModel::TestCase
end
end
+ test "as_json should keep the default order in the hash" do
+ json = @contact.as_json
+ keys = json.keys
+
+ %w(name age created_at awesome preferences).each_with_index do |field, index|
+ assert_equal keys.index(field), index
+ end
+ end
+
test "from_json should work without a root (class attribute)" do
json = @contact.to_json
result = Contact.new.from_json(json)
diff --git a/activemodel/test/cases/serializers/xml_serialization_test.rb b/activemodel/test/cases/serializers/xml_serialization_test.rb
index e2bb0dda0b..90ddf8ff0c 100755
--- a/activemodel/test/cases/serializers/xml_serialization_test.rb
+++ b/activemodel/test/cases/serializers/xml_serialization_test.rb
@@ -4,7 +4,6 @@ require 'active_support/core_ext/object/instance_variables'
require 'ostruct'
class Contact
- extend ActiveModel::Naming
include ActiveModel::Serializers::Xml
attr_accessor :address, :friends
@@ -25,7 +24,6 @@ class Customer < Struct.new(:name)
end
class Address
- extend ActiveModel::Naming
include ActiveModel::Serializers::Xml
attr_accessor :street, :city, :state, :zip, :apt_number
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index ffd19a5334..1d43840573 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,5 +1,63 @@
## Rails 4.0.0 (unreleased) ##
+* Fix `find_in_batches` crashing when IDs are strings and start option is not specified.
+
+ *Alexis Bernard*
+
+* `AR::Base#attributes_before_type_cast` now returns unserialized values for serialized attributes.
+
+ *Nikita Afanasenko*
+
+* Use query cache/uncache when using DATABASE_URL.
+ Fix #6951.
+
+ *kennyj*
+
+* Added `#none!` method for mutating `ActiveRecord::Relation` objects to a NullRelation.
+ It acts like `#none` but modifies relation in place.
+
+ *Juanjo Bazán*
+
+* Fix bug where `update_columns` and `update_column` would not let you update the primary key column.
+
+ *Henrik Nyh*
+
+* The `create_table` method raises an `ArgumentError` when the primary key column is redefined.
+ Fix #6378
+
+ *Yves Senn*
+
+* `ActiveRecord::AttributeMethods#[]` raises `ActiveModel::MissingAttributeError`
+ error if the given attribute is missing. Fixes #5433.
+
+ class Person < ActiveRecord::Base
+ belongs_to :company
+ end
+
+ # Before:
+ person = Person.select('id').first
+ person[:name] # => nil
+ person.name # => ActiveModel::MissingAttributeError: missing_attribute: name
+ person[:company_id] # => nil
+ person.company # => nil
+
+ # After:
+ person = Person.select('id').first
+ person[:name] # => ActiveModel::MissingAttributeError: missing_attribute: name
+ person.name # => ActiveModel::MissingAttributeError: missing_attribute: name
+ person[:company_id] # => ActiveModel::MissingAttributeError: missing_attribute: company_id
+ person.company # => ActiveModel::MissingAttributeError: missing_attribute: company_id
+
+ *Francesco Rodriguez*
+
+* Small binary fields use the `VARBINARY` MySQL type, instead of `TINYBLOB`.
+
+ *Victor Costan*
+
+* Decode URI encoded attributes on database connection URLs.
+
+ *Shawn Veader*
+
* Add `find_or_create_by`, `find_or_create_by!` and
`find_or_initialize_by` methods to `Relation`.
@@ -38,12 +96,12 @@
*Jon Leighton*
-* Fix bug with presence validation of associations. Would incorrectly add duplicated errors
+* Fix bug with presence validation of associations. Would incorrectly add duplicated errors
when the association was blank. Bug introduced in 1fab518c6a75dac5773654646eb724a59741bc13.
*Scott Willson*
-* Fix bug where sum(expression) returns string '0' for no matching records
+* Fix bug where sum(expression) returns string '0' for no matching records.
Fixes #7439
*Tim Macfarlane*
@@ -338,7 +396,7 @@
* Fix AR#dup to nullify the validation errors in the dup'ed object. Previously the original
and the dup'ed object shared the same errors.
- * Christian Seiler*
+ *Christian Seiler*
* Raise `ArgumentError` if list of attributes to change is empty in `update_all`.
@@ -926,34 +984,6 @@
*Aaron Patterson*
-* Added the `ActiveRecord::Model` module which can be included in a
- class as an alternative to inheriting from `ActiveRecord::Base`:
-
- class Post
- include ActiveRecord::Model
- end
-
- Please note:
-
- * Up until now it has been safe to assume that all AR models are
- descendants of `ActiveRecord::Base`. This is no longer a safe
- assumption, but it may transpire that there are areas of the
- code which still make this assumption. So there may be
- 'teething difficulties' with this feature. (But please do try it
- and report bugs.)
-
- * Plugins & libraries etc that add methods to `ActiveRecord::Base`
- will not be compatible with `ActiveRecord::Model`. Those libraries
- should add to `ActiveRecord::Model` instead (which is included in
- `Base`), or better still, avoid monkey-patching AR and instead
- provide a module that users can include where they need it.
-
- * To minimise the risk of conflicts with other code, it is
- advisable to include `ActiveRecord::Model` early in your class
- definition.
-
- *Jon Leighton*
-
* PostgreSQL hstore records can be created.
*Aaron Patterson*
diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb
index 1675127ab0..45122539f1 100644
--- a/activerecord/lib/active_record.rb
+++ b/activerecord/lib/active_record.rb
@@ -43,7 +43,6 @@ module ActiveRecord
autoload :Integration
autoload :Migration
autoload :Migrator, 'active_record/migration'
- autoload :Model
autoload :ModelSchema
autoload :NestedAttributes
autoload :Observer
diff --git a/activerecord/lib/active_record/associations/alias_tracker.rb b/activerecord/lib/active_record/associations/alias_tracker.rb
index 84540a7000..0c23029981 100644
--- a/activerecord/lib/active_record/associations/alias_tracker.rb
+++ b/activerecord/lib/active_record/associations/alias_tracker.rb
@@ -8,7 +8,7 @@ module ActiveRecord
attr_reader :aliases, :table_joins, :connection
# table_joins is an array of arel joins which might conflict with the aliases we assign here
- def initialize(connection = ActiveRecord::Model.connection, table_joins = [])
+ def initialize(connection = Base.connection, table_joins = [])
@aliases = Hash.new { |h,k| h[k] = initial_count_for(k) }
@table_joins = table_joins
@connection = connection
diff --git a/activerecord/lib/active_record/associations/association.rb b/activerecord/lib/active_record/associations/association.rb
index 2a5f727728..99e7383d42 100644
--- a/activerecord/lib/active_record/associations/association.rb
+++ b/activerecord/lib/active_record/associations/association.rb
@@ -85,7 +85,7 @@ module ActiveRecord
end
def scoped
- ActiveSupport::Deprecation.warn("#scoped is deprecated. use #scope instead.")
+ ActiveSupport::Deprecation.warn "#scoped is deprecated. use #scope instead."
scope
end
diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb
index 7f39d3083e..54215cf88d 100644
--- a/activerecord/lib/active_record/associations/collection_association.rb
+++ b/activerecord/lib/active_record/associations/collection_association.rb
@@ -576,7 +576,9 @@ module ActiveRecord
args.shift if args.first.is_a?(Hash) && args.first.empty?
collection = fetch_first_or_last_using_find?(args) ? scope : load_target
- collection.send(type, *args).tap {|it| set_inverse_instance it }
+ collection.send(type, *args).tap do |record|
+ set_inverse_instance record if record.is_a? ActiveRecord::Base
+ end
end
end
end
diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb
index 1dd9a3d45d..437fd00948 100644
--- a/activerecord/lib/active_record/attribute_methods.rb
+++ b/activerecord/lib/active_record/attribute_methods.rb
@@ -59,7 +59,7 @@ module ActiveRecord
raise DangerousAttributeError, "#{method_name} is defined by ActiveRecord"
end
- if [Base, Model].include?(active_record_super)
+ if superclass == Base
super
else
# If B < A and A defines its own attribute method, then we don't want to overwrite that.
@@ -269,17 +269,24 @@ module ActiveRecord
end
# Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example,
- # "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)).
- # (Alias for <tt>read_attribute</tt>).
+ # "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)). It raises
+ # <tt>ActiveModel::MissingAttributeError</tt> if the identified attribute is missing.
+ #
+ # Alias for the <tt>read_attribute</tt> method.
#
# class Person < ActiveRecord::Base
+ # belongs_to :organization
# end
#
# person = Person.new(name: 'Francesco', age: '22')
# person[:name] # => "Francesco"
# person[:age] # => 22
+ #
+ # person = Person.select('id').first
+ # person[:name] # => ActiveModel::MissingAttributeError: missing attribute: name
+ # person[:organization_id] # => ActiveModel::MissingAttributeError: missing attribute: organization_id
def [](attr_name)
- read_attribute(attr_name)
+ read_attribute(attr_name) { |n| missing_attribute(n, caller) }
end
# Updates the attribute identified by <tt>attr_name</tt> with the specified +value+.
diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb
index 59f209cec8..0333605eac 100644
--- a/activerecord/lib/active_record/attribute_methods/dirty.rb
+++ b/activerecord/lib/active_record/attribute_methods/dirty.rb
@@ -2,11 +2,6 @@ require 'active_support/core_ext/module/attribute_accessors'
require 'active_support/deprecation'
module ActiveRecord
- ActiveSupport.on_load(:active_record_config) do
- mattr_accessor :partial_writes, instance_accessor: false
- self.partial_writes = true
- end
-
module AttributeMethods
module Dirty # :nodoc:
extend ActiveSupport::Concern
@@ -18,7 +13,8 @@ module ActiveRecord
raise "You cannot include Dirty after Timestamp"
end
- config_attribute :partial_writes
+ class_attribute :partial_writes, instance_writer: false
+ self.partial_writes = true
def self.partial_updates=(v); self.partial_writes = v; end
def self.partial_updates?; partial_writes?; end
diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb
index 46fd6ebfb3..90701938e5 100644
--- a/activerecord/lib/active_record/attribute_methods/read.rb
+++ b/activerecord/lib/active_record/attribute_methods/read.rb
@@ -1,8 +1,4 @@
module ActiveRecord
- ActiveSupport.on_load(:active_record_config) do
- mattr_accessor :attribute_types_cached_by_default, instance_accessor: false
- end
-
module AttributeMethods
module Read
extend ActiveSupport::Concern
@@ -10,7 +6,8 @@ module ActiveRecord
ATTRIBUTE_TYPES_CACHED_BY_DEFAULT = [:datetime, :timestamp, :time, :date]
included do
- config_attribute :attribute_types_cached_by_default
+ class_attribute :attribute_types_cached_by_default, instance_writer: false
+ self.attribute_types_cached_by_default = ATTRIBUTE_TYPES_CACHED_BY_DEFAULT
end
module ClassMethods
@@ -35,36 +32,21 @@ module ActiveRecord
protected
- # We want to generate the methods via module_eval rather than
- # define_method, because define_method is slower on dispatch and
- # uses more memory (because it creates a closure).
+ # We want to generate the methods via module_eval rather than define_method,
+ # because define_method is slower on dispatch and uses more memory (because it
+ # creates a closure).
#
- # But sometimes the database might return columns with
- # characters that are not allowed in normal method names (like
- # 'my_column(omg)'. So to work around this we first define with
- # the __temp__ identifier, and then use alias method to rename
- # it to what we want.
- #
- # We are also defining a constant to hold the frozen string of
- # the attribute name. Using a constant means that we do not have
- # to allocate an object on each call to the attribute method.
- # Making it frozen means that it doesn't get duped when used to
- # key the @attributes_cache in read_attribute.
- def define_method_attribute(name)
- safe_name = name.unpack('h*').first
+ # But sometimes the database might return columns with characters that are not
+ # allowed in normal method names (like 'my_column(omg)'. So to work around this
+ # we first define with the __temp__ identifier, and then use alias method to
+ # rename it to what we want.
+ def define_method_attribute(attr_name)
generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
- module AttrNames
- unless defined? ATTR_#{safe_name}
- ATTR_#{safe_name} = #{name.inspect}.freeze
- end
+ def __temp__
+ read_attribute('#{attr_name}') { |n| missing_attribute(n, caller) }
end
-
- def __temp__#{safe_name}
- read_attribute(AttrNames::ATTR_#{safe_name}) { |n| missing_attribute(n, caller) }
- end
-
- alias_method #{name.inspect}, :__temp__#{safe_name}
- undef_method :__temp__#{safe_name}
+ alias_method '#{attr_name}', :__temp__
+ undef_method :__temp__
STR
end
@@ -79,8 +61,6 @@ module ActiveRecord
end
end
- ActiveRecord::Model.attribute_types_cached_by_default = ATTRIBUTE_TYPES_CACHED_BY_DEFAULT
-
# Returns the value of the attribute identified by <tt>attr_name</tt> after
# it has been typecast (for example, "2004-12-12" in a data column is cast
# to a date object, like Date.new(2004, 12, 12)).
diff --git a/activerecord/lib/active_record/attribute_methods/serialization.rb b/activerecord/lib/active_record/attribute_methods/serialization.rb
index 9994a81ede..5b9ed81424 100644
--- a/activerecord/lib/active_record/attribute_methods/serialization.rb
+++ b/activerecord/lib/active_record/attribute_methods/serialization.rb
@@ -45,7 +45,8 @@ module ActiveRecord
end
def serialized_attributes
- ActiveSupport::Deprecation.warn("Instance level serialized_attributes method is deprecated, please use class level method.")
+ message = "Instance level serialized_attributes method is deprecated, please use class level method."
+ ActiveSupport::Deprecation.warn message
defined?(@serialized_attributes) ? @serialized_attributes : self.class.serialized_attributes
end
@@ -118,6 +119,16 @@ module ActiveRecord
super
end
end
+
+ def attributes_before_type_cast
+ super.dup.tap do |attributes|
+ self.class.serialized_attributes.each_key do |key|
+ if attributes.key?(key)
+ attributes[key] = attributes[key].unserialized_value
+ end
+ end
+ end
+ end
end
end
end
diff --git a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
index f36a5806a9..806dc5b1d2 100644
--- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
+++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb
@@ -1,13 +1,4 @@
-
module ActiveRecord
- ActiveSupport.on_load(:active_record_config) do
- mattr_accessor :time_zone_aware_attributes, instance_accessor: false
- self.time_zone_aware_attributes = false
-
- mattr_accessor :skip_time_zone_conversion_for_attributes, instance_accessor: false
- self.skip_time_zone_conversion_for_attributes = []
- end
-
module AttributeMethods
module TimeZoneConversion
class Type # :nodoc:
@@ -28,8 +19,11 @@ module ActiveRecord
extend ActiveSupport::Concern
included do
- config_attribute :time_zone_aware_attributes, global: true
- config_attribute :skip_time_zone_conversion_for_attributes
+ mattr_accessor :time_zone_aware_attributes, instance_writer: false
+ self.time_zone_aware_attributes = false
+
+ class_attribute :skip_time_zone_conversion_for_attributes, instance_writer: false
+ self.skip_time_zone_conversion_for_attributes = []
end
module ClassMethods
diff --git a/activerecord/lib/active_record/attribute_methods/write.rb b/activerecord/lib/active_record/attribute_methods/write.rb
index cd33494cc3..fa9097db1f 100644
--- a/activerecord/lib/active_record/attribute_methods/write.rb
+++ b/activerecord/lib/active_record/attribute_methods/write.rb
@@ -9,19 +9,15 @@ module ActiveRecord
module ClassMethods
protected
-
- # See define_method_attribute in read.rb for an explanation of
- # this code.
- def define_method_attribute=(name)
- safe_name = name.unpack('h*').first
- generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
- def __temp__#{safe_name}=(value)
- write_attribute(AttrNames::ATTR_#{safe_name}, value)
+ def define_method_attribute=(attr_name)
+ if attr_name =~ ActiveModel::AttributeMethods::NAME_COMPILABLE_REGEXP
+ generated_attribute_methods.module_eval("def #{attr_name}=(new_value); write_attribute('#{attr_name}', new_value); end", __FILE__, __LINE__)
+ else
+ generated_attribute_methods.send(:define_method, "#{attr_name}=") do |new_value|
+ write_attribute(attr_name, new_value)
+ end
end
- alias_method #{(name + '=').inspect}, :__temp__#{safe_name}=
- undef_method :__temp__#{safe_name}=
- STR
- end
+ end
end
# Updates the attribute identified by <tt>attr_name</tt> with the
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index a4705b24ca..eabbd80f66 100644
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -321,8 +321,48 @@ module ActiveRecord #:nodoc:
# So it's possible to assign a logger to the class through <tt>Base.logger=</tt> which will then be used by all
# instances in the current object space.
class Base
- include ActiveRecord::Model
+ extend ActiveModel::Observing::ClassMethods
+ extend ActiveModel::Naming
+
+ extend ActiveSupport::Benchmarkable
+ extend ActiveSupport::DescendantsTracker
+
+ extend ConnectionHandling
+ extend QueryCache::ClassMethods
+ extend Querying
+ extend Translation
+ extend DynamicMatchers
+ extend Explain
+ extend ConnectionHandling
+
+ include Persistence
+ include ReadonlyAttributes
+ include ModelSchema
+ include Inheritance
+ include Scoping
+ include Sanitization
+ include AttributeAssignment
+ include ActiveModel::Conversion
+ include Integration
+ include Validations
+ include CounterCache
+ include Locking::Optimistic
+ include Locking::Pessimistic
+ include AttributeMethods
+ include Callbacks
+ include ActiveModel::Observing
+ include Timestamp
+ include Associations
+ include ActiveModel::SecurePassword
+ include AutosaveAssociation
+ include NestedAttributes
+ include Aggregations
+ include Transactions
+ include Reflection
+ include Serialization
+ include Store
+ include Core
end
-end
-ActiveSupport.run_load_hooks(:active_record, ActiveRecord::Model::DeprecationProxy.new)
+ ActiveSupport.run_load_hooks(:active_record, Base)
+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 42bd16db80..1da95f451f 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb
@@ -441,11 +441,11 @@ module ActiveRecord
end
def new_connection
- ActiveRecord::Model.send(spec.adapter_method, spec.config)
+ Base.send(spec.adapter_method, spec.config)
end
def current_connection_id #:nodoc:
- ActiveRecord::Model.connection_id ||= Thread.current.object_id
+ Base.connection_id ||= Thread.current.object_id
end
def checkout_new_connection
@@ -567,10 +567,10 @@ module ActiveRecord
class_to_pool[klass] ||= begin
until pool = pool_for(klass)
klass = klass.superclass
- break unless klass < ActiveRecord::Tag
+ break unless klass <= Base
end
- class_to_pool[klass] = pool || pool_for(ActiveRecord::Model)
+ class_to_pool[klass] = pool
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
index d61731633a..38960ab873 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
@@ -234,6 +234,10 @@ module ActiveRecord
name = name.to_s
type = type.to_sym
+ if primary_key_column_name == name
+ raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
+ end
+
column = self[name] || new_column_definition(@base, name, type)
limit = options.fetch(:limit) do
@@ -302,6 +306,11 @@ module ActiveRecord
definition
end
+ def primary_key_column_name
+ primary_key_column = columns.detect { |c| c.type == :primary_key }
+ primary_key_column && primary_key_column.name
+ end
+
def native
@base.native_database_types
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
index 0cb219767b..8517ce5fc5 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
@@ -3,7 +3,7 @@ require 'bigdecimal'
require 'bigdecimal/util'
require 'active_support/core_ext/benchmark'
require 'active_record/connection_adapters/schema_cache'
-require 'active_record/connection_adapters/abstract/schema_dumper'
+require 'active_record/connection_adapters/abstract/schema_dumper'
require 'monitor'
require 'active_support/deprecation'
@@ -263,7 +263,8 @@ module ActiveRecord
end
def transaction_joinable=(joinable)
- ActiveSupport::Deprecation.warn "#transaction_joinable= is deprecated. Please pass the :joinable option to #begin_transaction instead."
+ message = "#transaction_joinable= is deprecated. Please pass the :joinable option to #begin_transaction instead."
+ ActiveSupport::Deprecation.warn message
@transaction.joinable = joinable
end
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 7da77af3a9..84e73e6f0f 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -498,6 +498,13 @@ module ActiveRecord
# Maps logical Rails types to MySQL-specific data types.
def type_to_sql(type, limit = nil, precision = nil, scale = nil)
case type.to_s
+ when 'binary'
+ case limit
+ when 0..0xfff; "varbinary(#{limit})"
+ when nil; "blob"
+ when 0x1000..0xffffffff; "blob(#{limit})"
+ else raise(ActiveRecordError, "No binary type has character length #{limit}")
+ end
when 'integer'
case limit
when 1; 'tinyint'
diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb
index 816b5e17c1..80984f39c9 100644
--- a/activerecord/lib/active_record/connection_adapters/column.rb
+++ b/activerecord/lib/active_record/connection_adapters/column.rb
@@ -94,7 +94,7 @@ module ActiveRecord
case type
when :string, :text then value
- when :integer then value.to_i
+ when :integer then klass.value_to_integer(value)
when :float then value.to_f
when :decimal then klass.value_to_decimal(value)
when :datetime, :timestamp then klass.string_to_time(value)
@@ -107,14 +107,15 @@ module ActiveRecord
end
def type_cast_code(var_name)
- ActiveSupport::Deprecation.warn("Column#type_cast_code is deprecated in favor of" \
- "using Column#type_cast only, and it is going to be removed in future Rails versions.")
+ message = "Column#type_cast_code is deprecated in favor of using Column#type_cast only, " \
+ "and it is going to be removed in future Rails versions."
+ ActiveSupport::Deprecation.warn message
klass = self.class.name
case type
when :string, :text then var_name
- when :integer then "(#{var_name}.to_i)"
+ when :integer then "#{klass}.value_to_integer(#{var_name})"
when :float then "#{var_name}.to_f"
when :decimal then "#{klass}.value_to_decimal(#{var_name})"
when :datetime, :timestamp then "#{klass}.string_to_time(#{var_name})"
@@ -197,6 +198,17 @@ module ActiveRecord
end
end
+ # Used to convert values to integer.
+ # handle the case when an integer column is used to store boolean values
+ def value_to_integer(value)
+ case value
+ when TrueClass, FalseClass
+ value ? 1 : 0
+ else
+ value.to_i
+ end
+ end
+
# convert something to a BigDecimal
def value_to_decimal(value)
# Using .class is faster than .is_a? and
diff --git a/activerecord/lib/active_record/connection_adapters/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/connection_specification.rb
index b9a61f7d91..09250d3c01 100644
--- a/activerecord/lib/active_record/connection_adapters/connection_specification.rb
+++ b/activerecord/lib/active_record/connection_adapters/connection_specification.rb
@@ -73,6 +73,8 @@ module ActiveRecord
:database => config.path.sub(%r{^/},""),
:host => config.host }
spec.reject!{ |_,value| value.blank? }
+ uri_parser = URI::Parser.new
+ spec.map { |key,value| spec[key] = uri_parser.unescape(value) if value.is_a?(String) }
if config.query
options = Hash[config.query.split("&").map{ |pair| pair.split("=") }].symbolize_keys
spec.merge!(options)
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 553985bd1e..34d7a246b2 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb
@@ -221,10 +221,9 @@ module ActiveRecord
end
def outside_transaction?
- ActiveSupport::Deprecation.warn(
- "#outside_transaction? is deprecated. This method was only really used " \
- "internally, but you can use #transaction_open? instead."
- )
+ message = "#outside_transaction? is deprecated. This method was only really used " \
+ "internally, but you can use #transaction_open? instead."
+ ActiveSupport::Deprecation.warn message
@connection.transaction_status == PGconn::PQTRANS_IDLE
end
diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
index 4d5cb72c67..b89e9a01a8 100644
--- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb
@@ -251,7 +251,7 @@ module ActiveRecord
value = super
if column.type == :string && value.encoding == Encoding::ASCII_8BIT
logger.error "Binary data inserted for `string` type on column `#{column.name}`" if logger
- value.encode! 'utf-8'
+ value = value.encode Encoding::UTF_8
end
value
end
@@ -519,24 +519,22 @@ module ActiveRecord
def copy_table(from, to, options = {}) #:nodoc:
from_primary_key = primary_key(from)
- options[:primary_key] = from_primary_key if from_primary_key != 'id'
- unless options[:primary_key]
- options[:id] = columns(from).detect{|c| c.name == 'id'}.present? && from_primary_key == 'id'
- end
+ options[:id] = false
create_table(to, options) do |definition|
@definition = definition
+ @definition.primary_key(from_primary_key) if from_primary_key.present?
columns(from).each do |column|
column_name = options[:rename] ?
(options[:rename][column.name] ||
options[:rename][column.name.to_sym] ||
column.name) : column.name
+ next if column_name == from_primary_key
@definition.column(column_name, column.type,
:limit => column.limit, :default => column.default,
:precision => column.precision, :scale => column.scale,
:null => column.null)
end
- @definition.primary_key(from_primary_key) if from_primary_key
yield @definition if block_given?
end
diff --git a/activerecord/lib/active_record/connection_handling.rb b/activerecord/lib/active_record/connection_handling.rb
index 3531be05bf..8ce7a7a463 100644
--- a/activerecord/lib/active_record/connection_handling.rb
+++ b/activerecord/lib/active_record/connection_handling.rb
@@ -1,4 +1,3 @@
-
module ActiveRecord
module ConnectionHandling
# Establishes the connection to the database. Accepts a hash as input where
diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb
index f97c363871..98032db2ef 100644
--- a/activerecord/lib/active_record/core.rb
+++ b/activerecord/lib/active_record/core.rb
@@ -4,73 +4,6 @@ require 'thread'
module ActiveRecord
ActiveSupport.on_load(:active_record_config) do
- ##
- # :singleton-method:
- #
- # Accepts a logger conforming to the interface of Log4r which is then
- # passed on to any new database connections made and which can be
- # retrieved on both a class and instance level by calling +logger+.
- mattr_accessor :logger, instance_accessor: false
-
- ##
- # :singleton-method:
- # Contains the database configuration - as is typically stored in config/database.yml -
- # as a Hash.
- #
- # For example, the following database.yml...
- #
- # development:
- # adapter: sqlite3
- # database: db/development.sqlite3
- #
- # production:
- # adapter: sqlite3
- # database: db/production.sqlite3
- #
- # ...would result in ActiveRecord::Base.configurations to look like this:
- #
- # {
- # 'development' => {
- # 'adapter' => 'sqlite3',
- # 'database' => 'db/development.sqlite3'
- # },
- # 'production' => {
- # 'adapter' => 'sqlite3',
- # 'database' => 'db/production.sqlite3'
- # }
- # }
- mattr_accessor :configurations, instance_accessor: false
- self.configurations = {}
-
- ##
- # :singleton-method:
- # Determines whether to use Time.utc (using :utc) or Time.local (using :local) when pulling
- # dates and times from the database. This is set to :utc by default.
- mattr_accessor :default_timezone, instance_accessor: false
- self.default_timezone = :utc
-
- ##
- # :singleton-method:
- # Specifies the format to use when dumping the database schema with Rails'
- # Rakefile. If :sql, the schema is dumped as (potentially database-
- # specific) SQL statements. If :ruby, the schema is dumped as an
- # ActiveRecord::Schema file which can be loaded into any database that
- # supports migrations. Use :ruby if you want to have different database
- # adapters for, e.g., your development and test environments.
- mattr_accessor :schema_format, instance_accessor: false
- self.schema_format = :ruby
-
- ##
- # :singleton-method:
- # Specify whether or not to use timestamps for migration versions
- mattr_accessor :timestamped_migrations, instance_accessor: false
- self.timestamped_migrations = true
-
- mattr_accessor :connection_handler, instance_accessor: false
- self.connection_handler = ConnectionAdapters::ConnectionHandler.new
-
- mattr_accessor :dependent_restrict_raises, instance_accessor: false
- self.dependent_restrict_raises = true
end
module Core
@@ -79,12 +12,68 @@ module ActiveRecord
included do
##
# :singleton-method:
- # The connection handler
- config_attribute :connection_handler
+ #
+ # Accepts a logger conforming to the interface of Log4r which is then
+ # passed on to any new database connections made and which can be
+ # retrieved on both a class and instance level by calling +logger+.
+ mattr_accessor :logger, instance_writer: false
+
+ ##
+ # :singleton-method:
+ # Contains the database configuration - as is typically stored in config/database.yml -
+ # as a Hash.
+ #
+ # For example, the following database.yml...
+ #
+ # development:
+ # adapter: sqlite3
+ # database: db/development.sqlite3
+ #
+ # production:
+ # adapter: sqlite3
+ # database: db/production.sqlite3
+ #
+ # ...would result in ActiveRecord::Base.configurations to look like this:
+ #
+ # {
+ # 'development' => {
+ # 'adapter' => 'sqlite3',
+ # 'database' => 'db/development.sqlite3'
+ # },
+ # 'production' => {
+ # 'adapter' => 'sqlite3',
+ # 'database' => 'db/production.sqlite3'
+ # }
+ # }
+ mattr_accessor :configurations, instance_writer: false
+ self.configurations = {}
- %w(logger configurations default_timezone schema_format timestamped_migrations).each do |name|
- config_attribute name, global: true
- end
+ ##
+ # :singleton-method:
+ # Determines whether to use Time.utc (using :utc) or Time.local (using :local) when pulling
+ # dates and times from the database. This is set to :utc by default.
+ mattr_accessor :default_timezone, instance_writer: false
+ self.default_timezone = :utc
+
+ ##
+ # :singleton-method:
+ # Specifies the format to use when dumping the database schema with Rails'
+ # Rakefile. If :sql, the schema is dumped as (potentially database-
+ # specific) SQL statements. If :ruby, the schema is dumped as an
+ # ActiveRecord::Schema file which can be loaded into any database that
+ # supports migrations. Use :ruby if you want to have different database
+ # adapters for, e.g., your development and test environments.
+ mattr_accessor :schema_format, instance_writer: false
+ self.schema_format = :ruby
+
+ ##
+ # :singleton-method:
+ # Specify whether or not to use timestamps for migration versions
+ mattr_accessor :timestamped_migrations, instance_writer: false
+ self.timestamped_migrations = true
+
+ class_attribute :connection_handler, instance_writer: false
+ self.connection_handler = ConnectionAdapters::ConnectionHandler.new
end
module ClassMethods
@@ -139,7 +128,13 @@ module ActiveRecord
# Returns the Arel engine.
def arel_engine
- @arel_engine ||= connection_handler.retrieve_connection_pool(self) ? self : active_record_super.arel_engine
+ @arel_engine ||= begin
+ if Base == self || connection_handler.retrieve_connection_pool(self)
+ self
+ else
+ superclass.arel_engine
+ end
+ end
end
private
diff --git a/activerecord/lib/active_record/explain.rb b/activerecord/lib/active_record/explain.rb
index 9e0390bed1..af772996f1 100644
--- a/activerecord/lib/active_record/explain.rb
+++ b/activerecord/lib/active_record/explain.rb
@@ -1,12 +1,10 @@
require 'active_support/lazy_load_hooks'
module ActiveRecord
- ActiveSupport.on_load(:active_record_config) do
- mattr_accessor :auto_explain_threshold_in_seconds, instance_accessor: false
- end
-
module Explain
- delegate :auto_explain_threshold_in_seconds, :auto_explain_threshold_in_seconds=, to: 'ActiveRecord::Model'
+ def self.extended(base)
+ base.mattr_accessor :auto_explain_threshold_in_seconds, instance_accessor: false
+ end
# If auto explain is enabled, this method triggers EXPLAIN logging for the
# queries triggered by the block if it takes more than the threshold as a
diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb
index 7f1d62af39..29a99a5336 100644
--- a/activerecord/lib/active_record/fixtures.rb
+++ b/activerecord/lib/active_record/fixtures.rb
@@ -553,7 +553,7 @@ module ActiveRecord
rows[table_name] = fixtures.map do |label, fixture|
row = fixture.to_hash
- if model_class && model_class < ActiveRecord::Model
+ if model_class && model_class < ActiveRecord::Base
# fill in timestamp columns if they aren't specified and the model is set to record_timestamps
if model_class.record_timestamps
timestamp_column_names.each do |c_name|
diff --git a/activerecord/lib/active_record/inheritance.rb b/activerecord/lib/active_record/inheritance.rb
index 35273b0d81..a448fa1f5c 100644
--- a/activerecord/lib/active_record/inheritance.rb
+++ b/activerecord/lib/active_record/inheritance.rb
@@ -1,29 +1,22 @@
-
module ActiveRecord
- ActiveSupport.on_load(:active_record_config) do
- # Determine whether to store the full constant name including namespace when using STI
- mattr_accessor :store_full_sti_class, instance_accessor: false
- self.store_full_sti_class = true
- end
-
module Inheritance
extend ActiveSupport::Concern
included do
- config_attribute :store_full_sti_class
+ # Determine whether to store the full constant name including namespace when using STI
+ class_attribute :store_full_sti_class, instance_writer: false
+ self.store_full_sti_class = true
end
module ClassMethods
# True if this isn't a concrete subclass needing a STI type condition.
def descends_from_active_record?
- sup = active_record_super
-
- if sup.abstract_class?
- sup.descends_from_active_record?
- elsif self == Base
+ if self == Base
false
+ elsif superclass.abstract_class?
+ superclass.descends_from_active_record?
else
- [Base, Model].include?(sup) || !columns_hash.include?(inheritance_column)
+ superclass == Base || !columns_hash.include?(inheritance_column)
end
end
@@ -40,9 +33,8 @@ module ActiveRecord
@symbolized_sti_name ||= sti_name.present? ? sti_name.to_sym : symbolized_base_class
end
- # Returns the class descending directly from ActiveRecord::Base (or
- # that includes ActiveRecord::Model), or an abstract class, if any, in
- # the inheritance hierarchy.
+ # Returns the class descending directly from ActiveRecord::Base, or
+ # an abstract class, if any, in the inheritance hierarchy.
#
# If A extends AR::Base, A.base_class will return A. If B descends from A
# through some arbitrarily deep hierarchy, B.base_class will return A.
@@ -50,15 +42,14 @@ module ActiveRecord
# If B < A and C < B and if A is an abstract_class then both B.base_class
# and C.base_class would return B as the answer since A is an abstract_class.
def base_class
- unless self < ActiveRecord::Tag
+ unless self < Base
raise ActiveRecordError, "#{name} doesn't belong in a hierarchy descending from ActiveRecord"
end
- sup = active_record_super
- if sup == Base || sup == Model || sup.abstract_class?
+ if superclass == Base || superclass.abstract_class?
self
else
- sup.base_class
+ superclass.base_class
end
end
@@ -97,14 +88,6 @@ module ActiveRecord
sti_class.allocate.init_with('attributes' => record, 'column_types' => column_types)
end
- # For internal use.
- #
- # If this class includes ActiveRecord::Model then it won't have a
- # superclass. So this provides a way to get to the 'root' (ActiveRecord::Model).
- def active_record_super #:nodoc:
- superclass < Model ? superclass : Model
- end
-
protected
# Returns the class type of the record using the current module as a prefix. So descendants of
diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb
index e96ed00f9c..035c77c424 100644
--- a/activerecord/lib/active_record/locking/optimistic.rb
+++ b/activerecord/lib/active_record/locking/optimistic.rb
@@ -1,9 +1,4 @@
module ActiveRecord
- ActiveSupport.on_load(:active_record_config) do
- mattr_accessor :lock_optimistically, instance_accessor: false
- self.lock_optimistically = true
- end
-
module Locking
# == What is Optimistic Locking
#
@@ -56,7 +51,8 @@ module ActiveRecord
extend ActiveSupport::Concern
included do
- config_attribute :lock_optimistically
+ class_attribute :lock_optimistically, instance_writer: false
+ self.lock_optimistically = true
end
def locking_enabled? #:nodoc:
diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb
index d5ee98382d..5499f37802 100644
--- a/activerecord/lib/active_record/migration.rb
+++ b/activerecord/lib/active_record/migration.rb
@@ -342,7 +342,9 @@ module ActiveRecord
end
def call(env)
- ActiveRecord::Migration.check_pending!
+ ActiveRecord::Base.logger.quietly do
+ ActiveRecord::Migration.check_pending!
+ end
@app.call(env)
end
end
@@ -730,9 +732,8 @@ module ActiveRecord
running = runnable
if block_given?
- ActiveSupport::Deprecation.warn(<<-eomsg)
-block argument to migrate is deprecated, please filter migrations before constructing the migrator
- eomsg
+ message = "block argument to migrate is deprecated, please filter migrations before constructing the migrator"
+ ActiveSupport::Deprecation.warn message
running.select! { |m| yield m }
end
diff --git a/activerecord/lib/active_record/model.rb b/activerecord/lib/active_record/model.rb
deleted file mode 100644
index f059840f4d..0000000000
--- a/activerecord/lib/active_record/model.rb
+++ /dev/null
@@ -1,167 +0,0 @@
-require 'active_support/core_ext/module/attribute_accessors'
-
-module ActiveRecord
- module Configuration # :nodoc:
- # This just abstracts out how we define configuration options in AR. Essentially we
- # have mattr_accessors on the ActiveRecord:Model constant that define global defaults.
- # Classes that then use AR get class_attributes defined, which means that when they
- # are assigned the default will be overridden for that class and subclasses. (Except
- # when options[:global] == true, in which case there is one global value always.)
- def config_attribute(name, options = {})
- if options[:global]
- class_eval <<-CODE, __FILE__, __LINE__ + 1
- def self.#{name}; ActiveRecord::Model.#{name}; end
- def #{name}; ActiveRecord::Model.#{name}; end
- def self.#{name}=(val); ActiveRecord::Model.#{name} = val; end
- CODE
- else
- options[:instance_writer] ||= false
- class_attribute name, options
-
- singleton_class.class_eval <<-CODE, __FILE__, __LINE__ + 1
- remove_method :#{name}
- def #{name}; ActiveRecord::Model.#{name}; end
- CODE
- end
- end
- end
-
- # This allows us to detect an ActiveRecord::Model while it's in the process of
- # being included.
- module Tag; end
-
- # <tt>ActiveRecord::Model</tt> can be included into a class to add Active Record
- # persistence. This is an alternative to inheriting from <tt>ActiveRecord::Base</tt>.
- #
- # class Post
- # include ActiveRecord::Model
- # end
- module Model
- extend ActiveSupport::Concern
- extend ConnectionHandling
- extend ActiveModel::Observing::ClassMethods
-
- def self.append_features(base)
- base.class_eval do
- include Tag
- extend Configuration
- end
-
- super
- end
-
- included do
- extend ActiveModel::Naming
- extend ActiveSupport::Benchmarkable
- extend ActiveSupport::DescendantsTracker
-
- extend QueryCache::ClassMethods
- extend Querying
- extend Translation
- extend DynamicMatchers
- extend Explain
- extend ConnectionHandling
-
- initialize_generated_modules unless self == Base
- end
-
- include Persistence
- include ReadonlyAttributes
- include ModelSchema
- include Inheritance
- include Scoping
- include Sanitization
- include AttributeAssignment
- include ActiveModel::Conversion
- include Integration
- include Validations
- include CounterCache
- include Locking::Optimistic
- include Locking::Pessimistic
- include AttributeMethods
- include Callbacks
- include ActiveModel::Observing
- include Timestamp
- include Associations
- include ActiveModel::SecurePassword
- include AutosaveAssociation
- include NestedAttributes
- include Aggregations
- include Transactions
- include Reflection
- include Serialization
- include Store
- include Core
-
- class << self
- def arel_engine
- self
- end
-
- def abstract_class?
- false
- end
-
- # Defines the name of the table column which will store the class name on single-table
- # inheritance situations.
- #
- # The default inheritance column name is +type+, which means it's a
- # reserved word inside Active Record. To be able to use single-table
- # inheritance with another column name, or to use the column +type+ in
- # your own model for something else, you can set +inheritance_column+:
- #
- # self.inheritance_column = 'zoink'
- def inheritance_column
- 'type'
- end
- end
-
- class DeprecationProxy < BasicObject #:nodoc:
- def initialize(model = Model, base = Base)
- @model = model
- @base = base
- end
-
- def method_missing(name, *args, &block)
- if @model.respond_to?(name, true)
- @model.send(name, *args, &block)
- else
- ::ActiveSupport::Deprecation.warn(
- "The object passed to the active_record load hook was previously ActiveRecord::Base " \
- "(a Class). Now it is ActiveRecord::Model (a Module). You have called `#{name}' which " \
- "is only defined on ActiveRecord::Base. Please change your code so that it works with " \
- "a module rather than a class. (Model is included in Base, so anything added to Model " \
- "will be available on Base as well.)"
- )
- @base.send(name, *args, &block)
- end
- end
-
- alias send method_missing
-
- def extend(*mods)
- ::ActiveSupport::Deprecation.warn(
- "The object passed to the active_record load hook was previously ActiveRecord::Base " \
- "(a Class). Now it is ActiveRecord::Model (a Module). You have called `extend' which " \
- "would add singleton methods to Model. This is presumably not what you want, since the " \
- "methods would not be inherited down to Base. Rather than using extend, please use " \
- "ActiveSupport::Concern + include, which will ensure that your class methods are " \
- "inherited."
- )
- @base.extend(*mods)
- end
- end
- end
-
- # This hook is where config accessors on Model get defined.
- #
- # We don't want to just open the Model module and add stuff to it in other files, because
- # that would cause Model to load, which causes all sorts of loading order issues.
- #
- # We need this hook rather than just using the :active_record one, because users of the
- # :active_record hook may need to use config options.
- ActiveSupport.run_load_hooks(:active_record_config, Model)
-
- # Load Base at this point, because the active_record load hook is run in that file.
- Base
-end
diff --git a/activerecord/lib/active_record/model_schema.rb b/activerecord/lib/active_record/model_schema.rb
index 99de16cd33..1b95b72c8a 100644
--- a/activerecord/lib/active_record/model_schema.rb
+++ b/activerecord/lib/active_record/model_schema.rb
@@ -1,18 +1,4 @@
-
module ActiveRecord
- ActiveSupport.on_load(:active_record_config) do
- mattr_accessor :primary_key_prefix_type, instance_accessor: false
-
- mattr_accessor :table_name_prefix, instance_accessor: false
- self.table_name_prefix = ""
-
- mattr_accessor :table_name_suffix, instance_accessor: false
- self.table_name_suffix = ""
-
- mattr_accessor :pluralize_table_names, instance_accessor: false
- self.pluralize_table_names = true
- end
-
module ModelSchema
extend ActiveSupport::Concern
@@ -24,7 +10,7 @@ module ActiveRecord
# the Product class will look for "productid" instead of "id" as the primary column. If the
# latter is specified, the Product class will look for "product_id" instead of "id". Remember
# that this is a global setting for all Active Records.
- config_attribute :primary_key_prefix_type, global: true
+ mattr_accessor :primary_key_prefix_type, instance_writer: false
##
# :singleton-method:
@@ -36,20 +22,25 @@ module ActiveRecord
# If you are organising your models within modules you can add a prefix to the models within
# a namespace by defining a singleton method in the parent module called table_name_prefix which
# returns your chosen prefix.
- config_attribute :table_name_prefix
+ class_attribute :table_name_prefix, instance_writer: false
+ self.table_name_prefix = ""
##
# :singleton-method:
# Works like +table_name_prefix+, but appends instead of prepends (set to "_basecamp" gives "projects_basecamp",
# "people_basecamp"). By default, the suffix is the empty string.
- config_attribute :table_name_suffix
+ class_attribute :table_name_suffix, instance_writer: false
+ self.table_name_suffix = ""
##
# :singleton-method:
# Indicates whether table names should be the pluralized versions of the corresponding class names.
# If true, the default table name for a Product class will be +products+. If false, it would just be +product+.
# See table_name for the full rules on table/class naming. This is true, by default.
- config_attribute :pluralize_table_names
+ class_attribute :pluralize_table_names, instance_writer: false
+ self.pluralize_table_names = true
+
+ self.inheritance_column = 'type'
end
module ClassMethods
@@ -144,9 +135,9 @@ module ActiveRecord
# Computes the table name, (re)sets it internally, and returns it.
def reset_table_name #:nodoc:
self.table_name = if abstract_class?
- active_record_super == Base ? nil : active_record_super.table_name
- elsif active_record_super.abstract_class?
- active_record_super.table_name || compute_table_name
+ superclass == Base ? nil : superclass.table_name
+ elsif superclass.abstract_class?
+ superclass.table_name || compute_table_name
else
compute_table_name
end
@@ -156,9 +147,17 @@ module ActiveRecord
(parents.detect{ |p| p.respond_to?(:table_name_prefix) } || self).table_name_prefix
end
- # The name of the column containing the object's class when Single Table Inheritance is used
+ # Defines the name of the table column which will store the class name on single-table
+ # inheritance situations.
+ #
+ # The default inheritance column name is +type+, which means it's a
+ # reserved word inside Active Record. To be able to use single-table
+ # inheritance with another column name, or to use the column +type+ in
+ # your own model for something else, you can set +inheritance_column+:
+ #
+ # self.inheritance_column = 'zoink'
def inheritance_column
- (@inheritance_column ||= nil) || active_record_super.inheritance_column
+ (@inheritance_column ||= nil) || superclass.inheritance_column
end
# Sets the value of inheritance_column
@@ -331,7 +330,7 @@ module ActiveRecord
base = base_class
if self == base
# Nested classes are prefixed with singular parent table name.
- if parent < ActiveRecord::Model && !parent.abstract_class?
+ if parent < Base && !parent.abstract_class?
contained = parent.table_name
contained = contained.singularize if parent.pluralize_table_names
contained += '_'
diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb
index 43f908ae5f..aba56c2861 100644
--- a/activerecord/lib/active_record/nested_attributes.rb
+++ b/activerecord/lib/active_record/nested_attributes.rb
@@ -3,11 +3,6 @@ require 'active_support/core_ext/object/try'
require 'active_support/core_ext/hash/indifferent_access'
module ActiveRecord
- ActiveSupport.on_load(:active_record_config) do
- mattr_accessor :nested_attributes_options, instance_accessor: false
- self.nested_attributes_options = {}
- end
-
module NestedAttributes #:nodoc:
class TooManyRecords < ActiveRecordError
end
@@ -15,7 +10,8 @@ module ActiveRecord
extend ActiveSupport::Concern
included do
- config_attribute :nested_attributes_options
+ class_attribute :nested_attributes_options, instance_writer: false
+ self.nested_attributes_options = {}
end
# = Active Record Nested Attributes
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb
index 65a31f1566..8e749772a1 100644
--- a/activerecord/lib/active_record/persistence.rb
+++ b/activerecord/lib/active_record/persistence.rb
@@ -224,11 +224,13 @@ module ActiveRecord
verify_readonly_attribute(key.to_s)
end
+ updated_count = self.class.where(self.class.primary_key => id).update_all(attributes)
+
attributes.each do |k,v|
raw_write_attribute(k,v)
end
- self.class.where(self.class.primary_key => id).update_all(attributes) == 1
+ updated_count == 1
end
# Initializes +attribute+ to zero if +nil+ and adds the value passed as +by+ (default is 1).
diff --git a/activerecord/lib/active_record/query_cache.rb b/activerecord/lib/active_record/query_cache.rb
index 2bd8ecda20..38e18b32a4 100644
--- a/activerecord/lib/active_record/query_cache.rb
+++ b/activerecord/lib/active_record/query_cache.rb
@@ -5,19 +5,19 @@ module ActiveRecord
module ClassMethods
# Enable the query cache within the block if Active Record is configured.
def cache(&block)
- if ActiveRecord::Base.configurations.blank?
- yield
- else
+ if ActiveRecord::Base.connected?
connection.cache(&block)
+ else
+ yield
end
end
# Disable the query cache within the block if Active Record is configured.
def uncached(&block)
- if ActiveRecord::Base.configurations.blank?
- yield
- else
+ if ActiveRecord::Base.connected?
connection.uncached(&block)
+ else
+ yield
end
end
end
diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb
index d7e35fb771..77e41ea927 100644
--- a/activerecord/lib/active_record/railtie.rb
+++ b/activerecord/lib/active_record/railtie.rb
@@ -80,7 +80,7 @@ module ActiveRecord
if File.file?(filename)
cache = Marshal.load File.binread filename
if cache.version == ActiveRecord::Migrator.current_version
- ActiveRecord::Model.connection.schema_cache = cache
+ self.connection.schema_cache = cache
else
warn "Ignoring db/schema_cache.dump because it has expired. The current schema version is #{ActiveRecord::Migrator.current_version}, but the one in the cache is #{cache.version}."
end
@@ -122,8 +122,8 @@ module ActiveRecord
ActiveSupport.on_load(:active_record) do
ActionDispatch::Reloader.send(hook) do
- ActiveRecord::Model.clear_reloadable_connections!
- ActiveRecord::Model.clear_cache!
+ ActiveRecord::Base.clear_reloadable_connections!
+ ActiveRecord::Base.clear_cache!
end
end
end
@@ -135,13 +135,12 @@ module ActiveRecord
config.after_initialize do |app|
ActiveSupport.on_load(:active_record) do
- ActiveRecord::Model.instantiate_observers
+ instantiate_observers
ActionDispatch::Reloader.to_prepare do
- ActiveRecord::Model.instantiate_observers
+ ActiveRecord::Base.instantiate_observers
end
end
-
end
end
end
diff --git a/activerecord/lib/active_record/readonly_attributes.rb b/activerecord/lib/active_record/readonly_attributes.rb
index b3c20c4aff..8499bb16e7 100644
--- a/activerecord/lib/active_record/readonly_attributes.rb
+++ b/activerecord/lib/active_record/readonly_attributes.rb
@@ -22,7 +22,8 @@ module ActiveRecord
end
def _attr_readonly
- ActiveSupport::Deprecation.warn("Instance level _attr_readonly method is deprecated, please use class level method.")
+ message = "Instance level _attr_readonly method is deprecated, please use class level method."
+ ActiveSupport::Deprecation.warn message
defined?(@_attr_readonly) ? @_attr_readonly : self.class._attr_readonly
end
end
diff --git a/activerecord/lib/active_record/relation/batches.rb b/activerecord/lib/active_record/relation/batches.rb
index 8af0c6a8ef..b921f2eddb 100644
--- a/activerecord/lib/active_record/relation/batches.rb
+++ b/activerecord/lib/active_record/relation/batches.rb
@@ -62,11 +62,11 @@ module ActiveRecord
ActiveRecord::Base.logger.warn("Scoped order and limit are ignored, it's forced to be batch order and batch size")
end
- start = options.delete(:start) || 0
+ start = options.delete(:start)
batch_size = options.delete(:batch_size) || 1000
relation = relation.reorder(batch_order).limit(batch_size)
- records = relation.where(table[primary_key].gteq(start)).to_a
+ records = start ? relation.where(table[primary_key].gteq(start)).to_a : relation.to_a
while records.any?
records_size = records.size
diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb
index 84aaa39fed..99c2f45bc8 100644
--- a/activerecord/lib/active_record/relation/finder_methods.rb
+++ b/activerecord/lib/active_record/relation/finder_methods.rb
@@ -159,7 +159,7 @@ module ActiveRecord
# Person.exists?(false)
# Person.exists?
def exists?(conditions = :none)
- conditions = conditions.id if ActiveRecord::Model === conditions
+ conditions = conditions.id if Base === conditions
return false if !conditions
join_dependency = construct_join_dependency_for_association_find
diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb
index 71030cb5d7..bd7aeb0c4e 100644
--- a/activerecord/lib/active_record/relation/predicate_builder.rb
+++ b/activerecord/lib/active_record/relation/predicate_builder.rb
@@ -40,7 +40,7 @@ module ActiveRecord
#
# For polymorphic relationships, find the foreign key and type:
# PriceEstimate.where(:estimate_of => treasure)
- if klass && value.class < ActiveRecord::Tag && reflection = klass.reflect_on_association(column.to_sym)
+ if klass && value.class < Base && reflection = klass.reflect_on_association(column.to_sym)
if reflection.polymorphic?
queries << build(table[reflection.foreign_type], value.class.base_class)
end
@@ -67,7 +67,7 @@ module ActiveRecord
def self.build(attribute, value)
case value
when Array, ActiveRecord::Associations::CollectionProxy
- values = value.to_a.map {|x| x.is_a?(ActiveRecord::Model) ? x.id : x}
+ values = value.to_a.map {|x| x.is_a?(Base) ? x.id : x}
ranges, values = values.partition {|v| v.is_a?(Range)}
values_predicate = if values.include?(nil)
@@ -93,7 +93,7 @@ module ActiveRecord
attribute.in(value.arel.ast)
when Range
attribute.in(value)
- when ActiveRecord::Model
+ when ActiveRecord::Base
attribute.eq(value.id)
when Class
# FIXME: I think we need to deprecate this behavior
diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb
index 14bcb337e9..4fdc296c7e 100644
--- a/activerecord/lib/active_record/relation/query_methods.rb
+++ b/activerecord/lib/active_record/relation/query_methods.rb
@@ -496,6 +496,11 @@ module ActiveRecord
extending(NullRelation)
end
+ # Like #none, but modifies relation in place.
+ def none!
+ extending!(NullRelation)
+ end
+
# Sets readonly attributes for the returned relation. If value is
# true (default), attempting to update a record will result in an error.
#
diff --git a/activerecord/lib/active_record/result.rb b/activerecord/lib/active_record/result.rb
index 425b9b41d8..bea195e9b8 100644
--- a/activerecord/lib/active_record/result.rb
+++ b/activerecord/lib/active_record/result.rb
@@ -56,7 +56,7 @@ module ActiveRecord
@hash_rows ||=
begin
# We freeze the strings to prevent them getting duped when
- # used as keys in ActiveRecord::Model's @attributes hash
+ # used as keys in ActiveRecord::Base's @attributes hash
columns = @columns.map { |c| c.dup.freeze }
@rows.map { |row|
Hash[columns.zip(row)]
diff --git a/activerecord/lib/active_record/serialization.rb b/activerecord/lib/active_record/serialization.rb
index e8dd312a47..6b55af4205 100644
--- a/activerecord/lib/active_record/serialization.rb
+++ b/activerecord/lib/active_record/serialization.rb
@@ -1,19 +1,11 @@
module ActiveRecord #:nodoc:
- ActiveSupport.on_load(:active_record_config) do
- mattr_accessor :include_root_in_json, instance_accessor: false
- self.include_root_in_json = true
- end
-
# = Active Record Serialization
module Serialization
extend ActiveSupport::Concern
include ActiveModel::Serializers::JSON
included do
- singleton_class.class_eval do
- remove_method :include_root_in_json
- delegate :include_root_in_json, to: 'ActiveRecord::Model'
- end
+ self.include_root_in_json = true
end
def serializable_hash(options = nil)
diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb
index ec4588f601..920d6848c1 100644
--- a/activerecord/lib/active_record/timestamp.rb
+++ b/activerecord/lib/active_record/timestamp.rb
@@ -1,8 +1,6 @@
module ActiveRecord
ActiveSupport.on_load(:active_record_config) do
- mattr_accessor :record_timestamps, instance_accessor: false
- self.record_timestamps = true
end
# = Active Record Timestamp
@@ -37,7 +35,8 @@ module ActiveRecord
extend ActiveSupport::Concern
included do
- config_attribute :record_timestamps, instance_writer: true
+ class_attribute :record_timestamps
+ self.record_timestamps = true
end
def initialize_dup(other) # :nodoc:
diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb
index 934393b4e7..f91abfbd19 100644
--- a/activerecord/lib/active_record/transactions.rb
+++ b/activerecord/lib/active_record/transactions.rb
@@ -328,6 +328,7 @@ module ActiveRecord
@_start_transaction_state[:new_record] = @new_record
@_start_transaction_state[:destroyed] = @destroyed
@_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) + 1
+ @_start_transaction_state[:frozen?] = @attributes.frozen?
end
# Clear the new record state and id of a record.
@@ -342,8 +343,8 @@ module ActiveRecord
@_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1
if @_start_transaction_state[:level] < 1 || force
restore_state = @_start_transaction_state
- was_frozen = @attributes.frozen?
- @attributes = @attributes.dup if was_frozen
+ was_frozen = restore_state[:frozen?]
+ @attributes = @attributes.dup if @attributes.frozen?
@new_record = restore_state[:new_record]
@destroyed = restore_state[:destroyed]
if restore_state.has_key?(:id)
diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb
index 93b01a3934..404b492288 100644
--- a/activerecord/test/cases/adapter_test.rb
+++ b/activerecord/test/cases/adapter_test.rb
@@ -69,16 +69,16 @@ module ActiveRecord
def test_not_specifying_database_name_for_cross_database_selects
begin
assert_nothing_raised do
- ActiveRecord::Model.establish_connection(ActiveRecord::Base.configurations['arunit'].except(:database))
+ ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['arunit'].except(:database))
config = ARTest.connection_config
- ActiveRecord::Model.connection.execute(
+ ActiveRecord::Base.connection.execute(
"SELECT #{config['arunit']['database']}.pirates.*, #{config['arunit2']['database']}.courses.* " \
"FROM #{config['arunit']['database']}.pirates, #{config['arunit2']['database']}.courses"
)
end
ensure
- ActiveRecord::Model.establish_connection 'arunit'
+ ActiveRecord::Base.establish_connection 'arunit'
end
end
end
diff --git a/activerecord/test/cases/adapters/mysql/connection_test.rb b/activerecord/test/cases/adapters/mysql/connection_test.rb
index 4bccd2cc59..534dc2c2df 100644
--- a/activerecord/test/cases/adapters/mysql/connection_test.rb
+++ b/activerecord/test/cases/adapters/mysql/connection_test.rb
@@ -3,13 +3,13 @@ require "cases/helper"
class MysqlConnectionTest < ActiveRecord::TestCase
def setup
super
- @connection = ActiveRecord::Model.connection
+ @connection = ActiveRecord::Base.connection
end
def test_mysql_reconnect_attribute_after_connection_with_reconnect_true
run_without_connection do |orig_connection|
- ActiveRecord::Model.establish_connection(orig_connection.merge({:reconnect => true}))
- assert ActiveRecord::Model.connection.raw_connection.reconnect
+ ActiveRecord::Base.establish_connection(orig_connection.merge({:reconnect => true}))
+ assert ActiveRecord::Base.connection.raw_connection.reconnect
end
end
@@ -25,8 +25,8 @@ class MysqlConnectionTest < ActiveRecord::TestCase
def test_mysql_reconnect_attribute_after_connection_with_reconnect_false
run_without_connection do |orig_connection|
- ActiveRecord::Model.establish_connection(orig_connection.merge({:reconnect => false}))
- assert !ActiveRecord::Model.connection.raw_connection.reconnect
+ ActiveRecord::Base.establish_connection(orig_connection.merge({:reconnect => false}))
+ assert !ActiveRecord::Base.connection.raw_connection.reconnect
end
end
@@ -117,7 +117,7 @@ class MysqlConnectionTest < ActiveRecord::TestCase
# Test that MySQL allows multiple results for stored procedures
if defined?(Mysql) && Mysql.const_defined?(:CLIENT_MULTI_RESULTS)
def test_multi_results
- rows = ActiveRecord::Model.connection.select_rows('CALL ten();')
+ rows = ActiveRecord::Base.connection.select_rows('CALL ten();')
assert_equal 10, rows[0][0].to_i, "ten() did not return 10 as expected: #{rows.inspect}"
assert @connection.active?, "Bad connection use by 'MysqlAdapter.select_rows'"
end
@@ -130,9 +130,9 @@ class MysqlConnectionTest < ActiveRecord::TestCase
def test_mysql_strict_mode_disabled_dont_override_global_sql_mode
run_without_connection do |orig_connection|
- ActiveRecord::Model.establish_connection(orig_connection.merge({:strict => false}))
- global_sql_mode = ActiveRecord::Model.connection.exec_query "SELECT @@GLOBAL.sql_mode"
- session_sql_mode = ActiveRecord::Model.connection.exec_query "SELECT @@SESSION.sql_mode"
+ ActiveRecord::Base.establish_connection(orig_connection.merge({:strict => false}))
+ global_sql_mode = ActiveRecord::Base.connection.exec_query "SELECT @@GLOBAL.sql_mode"
+ session_sql_mode = ActiveRecord::Base.connection.exec_query "SELECT @@SESSION.sql_mode"
assert_equal global_sql_mode.rows, session_sql_mode.rows
end
end
@@ -140,11 +140,11 @@ class MysqlConnectionTest < ActiveRecord::TestCase
private
def run_without_connection
- original_connection = ActiveRecord::Model.remove_connection
+ original_connection = ActiveRecord::Base.remove_connection
begin
yield original_connection
ensure
- ActiveRecord::Model.establish_connection(original_connection)
+ ActiveRecord::Base.establish_connection(original_connection)
end
end
end
diff --git a/activerecord/test/cases/adapters/mysql/sql_types_test.rb b/activerecord/test/cases/adapters/mysql/sql_types_test.rb
new file mode 100644
index 0000000000..1ddb1b91c9
--- /dev/null
+++ b/activerecord/test/cases/adapters/mysql/sql_types_test.rb
@@ -0,0 +1,14 @@
+require "cases/helper"
+
+class SqlTypesTest < ActiveRecord::TestCase
+ def test_binary_types
+ assert_equal 'varbinary(64)', type_to_sql(:binary, 64)
+ assert_equal 'varbinary(4095)', type_to_sql(:binary, 4095)
+ assert_equal 'blob(4096)', type_to_sql(:binary, 4096)
+ assert_equal 'blob', type_to_sql(:binary)
+ end
+
+ def type_to_sql(*args)
+ ActiveRecord::Base.connection.type_to_sql(*args)
+ end
+end
diff --git a/activerecord/test/cases/adapters/mysql2/connection_test.rb b/activerecord/test/cases/adapters/mysql2/connection_test.rb
index c63e4fe5b6..14c22d2519 100644
--- a/activerecord/test/cases/adapters/mysql2/connection_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/connection_test.rb
@@ -3,7 +3,7 @@ require "cases/helper"
class MysqlConnectionTest < ActiveRecord::TestCase
def setup
super
- @connection = ActiveRecord::Model.connection
+ @connection = ActiveRecord::Base.connection
@connection.extend(LogIntercepter)
@connection.intercepted = true
end
@@ -46,9 +46,9 @@ class MysqlConnectionTest < ActiveRecord::TestCase
def test_mysql_strict_mode_disabled_dont_override_global_sql_mode
run_without_connection do |orig_connection|
- ActiveRecord::Model.establish_connection(orig_connection.merge({:strict => false}))
- global_sql_mode = ActiveRecord::Model.connection.exec_query "SELECT @@GLOBAL.sql_mode"
- session_sql_mode = ActiveRecord::Model.connection.exec_query "SELECT @@SESSION.sql_mode"
+ ActiveRecord::Base.establish_connection(orig_connection.merge({:strict => false}))
+ global_sql_mode = ActiveRecord::Base.connection.exec_query "SELECT @@GLOBAL.sql_mode"
+ session_sql_mode = ActiveRecord::Base.connection.exec_query "SELECT @@SESSION.sql_mode"
assert_equal global_sql_mode.rows, session_sql_mode.rows
end
end
@@ -76,11 +76,11 @@ class MysqlConnectionTest < ActiveRecord::TestCase
private
def run_without_connection
- original_connection = ActiveRecord::Model.remove_connection
+ original_connection = ActiveRecord::Base.remove_connection
begin
yield original_connection
ensure
- ActiveRecord::Model.establish_connection(original_connection)
+ ActiveRecord::Base.establish_connection(original_connection)
end
end
end
diff --git a/activerecord/test/cases/adapters/mysql2/sql_types_test.rb b/activerecord/test/cases/adapters/mysql2/sql_types_test.rb
new file mode 100644
index 0000000000..1ddb1b91c9
--- /dev/null
+++ b/activerecord/test/cases/adapters/mysql2/sql_types_test.rb
@@ -0,0 +1,14 @@
+require "cases/helper"
+
+class SqlTypesTest < ActiveRecord::TestCase
+ def test_binary_types
+ assert_equal 'varbinary(64)', type_to_sql(:binary, 64)
+ assert_equal 'varbinary(4095)', type_to_sql(:binary, 4095)
+ assert_equal 'blob(4096)', type_to_sql(:binary, 4096)
+ assert_equal 'blob', type_to_sql(:binary)
+ end
+
+ def type_to_sql(*args)
+ ActiveRecord::Base.connection.type_to_sql(*args)
+ end
+end
diff --git a/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb b/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb
index 74288a98d1..d03d1dd94c 100644
--- a/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb
+++ b/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb
@@ -32,6 +32,11 @@ class CopyTableTest < ActiveRecord::TestCase
end
end
+ def test_copy_table_allows_to_pass_options_to_create_table
+ @connection.create_table('blocker_table')
+ test_copy_table('customers', 'blocker_table', force: true)
+ end
+
def test_copy_table_with_index
test_copy_table('comments', 'comments_with_index') do
@connection.add_index('comments_with_index', ['post_id', 'type'])
@@ -43,7 +48,9 @@ class CopyTableTest < ActiveRecord::TestCase
end
def test_copy_table_without_primary_key
- test_copy_table('developers_projects', 'programmers_projects')
+ test_copy_table('developers_projects', 'programmers_projects') do
+ assert_nil @connection.primary_key('programmers_projects')
+ end
end
def test_copy_table_with_id_col_that_is_not_primary_key
diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
index 4e26c5dda1..003052bac4 100644
--- a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
+++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
@@ -154,6 +154,12 @@ module ActiveRecord
DualEncoding.connection.drop_table('dual_encodings')
end
+ def test_type_cast_should_not_mutate_encoding
+ name = 'hello'.force_encoding(Encoding::ASCII_8BIT)
+ Owner.create(name: name)
+ assert_equal Encoding::ASCII_8BIT, name.encoding
+ end
+
def test_execute
@conn.execute "INSERT INTO items (number) VALUES (10)"
records = @conn.execute "SELECT * FROM items"
diff --git a/activerecord/test/cases/associations/inverse_associations_test.rb b/activerecord/test/cases/associations/inverse_associations_test.rb
index aad48e7ce9..8c9b4fb921 100644
--- a/activerecord/test/cases/associations/inverse_associations_test.rb
+++ b/activerecord/test/cases/associations/inverse_associations_test.rb
@@ -261,10 +261,23 @@ class InverseHasManyTests < ActiveRecord::TestCase
def test_parent_instance_should_be_shared_with_first_and_last_child
man = Man.first
+
assert man.interests.first.man.equal? man
assert man.interests.last.man.equal? man
end
+ def test_parent_instance_should_be_shared_with_first_n_and_last_n_children
+ man = Man.first
+
+ interests = man.interests.first(2)
+ assert interests[0].man.equal? man
+ assert interests[1].man.equal? man
+
+ interests = man.interests.last(2)
+ assert interests[0].man.equal? man
+ assert interests[1].man.equal? man
+ end
+
def test_trying_to_use_inverses_that_dont_exist_should_raise_an_error
assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) { Man.first.secret_interests }
end
diff --git a/activerecord/test/cases/attribute_methods/read_test.rb b/activerecord/test/cases/attribute_methods/read_test.rb
index da5d9d8c2a..8d8ff2f952 100644
--- a/activerecord/test/cases/attribute_methods/read_test.rb
+++ b/activerecord/test/cases/attribute_methods/read_test.rb
@@ -11,10 +11,8 @@ module ActiveRecord
def setup
@klass = Class.new do
def self.superclass; Base; end
- def self.active_record_super; Base; end
def self.base_class; self; end
- extend ActiveRecord::Configuration
include ActiveRecord::AttributeMethods
def self.define_attribute_methods
diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb
index c2b58fd7d1..8b82b79219 100644
--- a/activerecord/test/cases/attribute_methods_test.rb
+++ b/activerecord/test/cases/attribute_methods_test.rb
@@ -287,6 +287,12 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_equal "Don't change the topic", topic[:title]
end
+ def test_read_attribute_raises_missing_attribute_error_when_not_exists
+ computer = Computer.select('id').first
+ assert_raises(ActiveModel::MissingAttributeError) { computer[:developer] }
+ assert_raises(ActiveModel::MissingAttributeError) { computer[:extendedWarranty] }
+ end
+
def test_read_attribute_when_false
topic = topics(:first)
topic.approved = false
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index 0f859bf452..203e44857a 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -23,7 +23,6 @@ require 'models/edge'
require 'models/joke'
require 'models/bulb'
require 'models/bird'
-require 'models/teapot'
require 'rexml/document'
require 'active_support/core_ext/exception'
@@ -1196,10 +1195,6 @@ class BasicsTest < ActiveRecord::TestCase
# Concrete subclasses an abstract class which has a type column.
assert !SubStiPost.descends_from_active_record?
-
- assert Teapot.descends_from_active_record?
- assert !OtherTeapot.descends_from_active_record?
- assert CoolTeapot.descends_from_active_record?
end
def test_find_on_abstract_base_class_doesnt_use_type_condition
@@ -1453,15 +1448,6 @@ class BasicsTest < ActiveRecord::TestCase
assert_equal scope, Bird.uniq
end
- def test_active_record_super
- assert_equal ActiveRecord::Model, ActiveRecord::Base.active_record_super
- assert_equal ActiveRecord::Base, Topic.active_record_super
- assert_equal Topic, ImportantTopic.active_record_super
- assert_equal ActiveRecord::Model, Teapot.active_record_super
- assert_equal Teapot, OtherTeapot.active_record_super
- assert_equal ActiveRecord::Model, CoolTeapot.active_record_super
- end
-
def test_table_name_with_2_abstract_subclasses
assert_equal "photos", Photo.table_name
end
diff --git a/activerecord/test/cases/batches_test.rb b/activerecord/test/cases/batches_test.rb
index 12d5245fbd..acb8b5f562 100644
--- a/activerecord/test/cases/batches_test.rb
+++ b/activerecord/test/cases/batches_test.rb
@@ -136,4 +136,12 @@ class EachTest < ActiveRecord::TestCase
assert_equal nick_order_subscribers[1..-1].map(&:id), subscribers.map(&:id)
end
+
+ def test_find_in_batches_should_use_any_column_as_primary_key_when_start_is_not_specified
+ assert_queries(Subscriber.count + 1) do
+ Subscriber.find_each(:batch_size => 1) do |subscriber|
+ assert_kind_of Subscriber, subscriber
+ end
+ end
+ end
end
diff --git a/activerecord/test/cases/column_test.rb b/activerecord/test/cases/column_test.rb
index a7b63d15c9..2124c256fa 100644
--- a/activerecord/test/cases/column_test.rb
+++ b/activerecord/test/cases/column_test.rb
@@ -33,6 +33,8 @@ module ActiveRecord
assert_equal 0, column.type_cast('bad1')
assert_equal 0, column.type_cast('bad')
assert_equal 1, column.type_cast(1.7)
+ assert_equal 0, column.type_cast(false)
+ assert_equal 1, column.type_cast(true)
assert_nil column.type_cast(nil)
end
@@ -41,11 +43,9 @@ module ActiveRecord
assert_raises(NoMethodError) do
column.type_cast([])
end
+
assert_raises(NoMethodError) do
- column.type_cast(true)
- end
- assert_raises(NoMethodError) do
- column.type_cast(false)
+ column.type_cast(Object.new)
end
end
diff --git a/activerecord/test/cases/connection_adapters/connection_handler_test.rb b/activerecord/test/cases/connection_adapters/connection_handler_test.rb
index 4467ddfc39..631bf1aaac 100644
--- a/activerecord/test/cases/connection_adapters/connection_handler_test.rb
+++ b/activerecord/test/cases/connection_adapters/connection_handler_test.rb
@@ -4,8 +4,8 @@ module ActiveRecord
module ConnectionAdapters
class ConnectionHandlerTest < ActiveRecord::TestCase
def setup
- @klass = Class.new { include ActiveRecord::Tag }
- @subklass = Class.new(@klass) { include ActiveRecord::Tag }
+ @klass = Class.new(Base)
+ @subklass = Class.new(@klass)
@handler = ConnectionHandler.new
@handler.establish_connection @klass, Base.connection_pool.spec
diff --git a/activerecord/test/cases/connection_specification/resolver_test.rb b/activerecord/test/cases/connection_specification/resolver_test.rb
index 434d2b7ba5..ee9818678d 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 defined?(MysqlAdapter)
+ skip "only if mysql is available" unless current_adapter?(:MysqlAdapter) or current_adapter?(: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 defined?(MysqlAdapter)
+ skip "only if mysql is available" unless current_adapter?(:MysqlAdapter) or current_adapter?(: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 defined?(MysqlAdapter)
+ skip "only if mysql is available" unless current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
spec = resolve 'mysql://foo:123?encoding=utf8'
assert_equal({
:adapter => "mysql",
@@ -36,6 +36,14 @@ module ActiveRecord
:host => "foo",
:encoding => "utf8" }, spec)
end
+
+ def test_encoded_password
+ skip "only if mysql is available" unless current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
+ password = 'am@z1ng_p@ssw0rd#!'
+ encoded_password = URI.encode_www_form_component(password)
+ spec = resolve "mysql://foo:#{encoded_password}@localhost/bar"
+ assert_equal password, spec[:password]
+ end
end
end
end
diff --git a/activerecord/test/cases/defaults_test.rb b/activerecord/test/cases/defaults_test.rb
index 0df872ff10..ed7eedaa27 100644
--- a/activerecord/test/cases/defaults_test.rb
+++ b/activerecord/test/cases/defaults_test.rb
@@ -52,12 +52,12 @@ if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
self.use_transactional_fixtures = false
def using_strict(strict)
- connection = ActiveRecord::Model.remove_connection
- ActiveRecord::Model.establish_connection connection.merge(strict: strict)
+ connection = ActiveRecord::Base.remove_connection
+ ActiveRecord::Base.establish_connection connection.merge(strict: strict)
yield
ensure
- ActiveRecord::Model.remove_connection
- ActiveRecord::Model.establish_connection connection
+ ActiveRecord::Base.remove_connection
+ ActiveRecord::Base.establish_connection connection
end
# MySQL cannot have defaults on text/blob columns. It reports the
diff --git a/activerecord/test/cases/inclusion_test.rb b/activerecord/test/cases/inclusion_test.rb
deleted file mode 100644
index 8f095e4953..0000000000
--- a/activerecord/test/cases/inclusion_test.rb
+++ /dev/null
@@ -1,133 +0,0 @@
-require 'cases/helper'
-require 'models/teapot'
-
-class BasicInclusionModelTest < ActiveRecord::TestCase
- def test_basic_model
- Teapot.create!(:name => "Ronnie Kemper")
- assert_equal "Ronnie Kemper", Teapot.first.name
- end
-
- def test_initialization
- t = Teapot.new(:name => "Bob")
- assert_equal "Bob", t.name
- end
-
- def test_inherited_model
- teapot = CoolTeapot.create!(:name => "Bob")
- teapot.reload
-
- assert_equal "Bob", teapot.name
- assert_equal "mmm", teapot.aaahhh
- end
-
- def test_generated_feature_methods
- assert Teapot < Teapot::GeneratedFeatureMethods
- end
-
- def test_exists
- t = Teapot.create!(:name => "Ronnie Kemper")
- assert Teapot.exists?(t)
- end
-
- def test_predicate_builder
- t = Teapot.create!(:name => "Bob")
- assert_equal "Bob", Teapot.where(:id => [t]).first.name
- assert_equal "Bob", Teapot.where(:id => t).first.name
- end
-
- def test_nested_model
- assert_equal "ceiling_teapots", Ceiling::Teapot.table_name
- end
-end
-
-class InclusionUnitTest < ActiveRecord::TestCase
- def setup
- @klass = Class.new { include ActiveRecord::Model }
- end
-
- def test_non_abstract_class
- assert !@klass.abstract_class?
- end
-
- def test_abstract_class
- @klass.abstract_class = true
- assert @klass.abstract_class?
- end
-
- def test_establish_connection
- assert @klass.respond_to?(:establish_connection)
- assert ActiveRecord::Model.respond_to?(:establish_connection)
- end
-
- def test_adapter_connection
- name = "#{ActiveRecord::Base.connection_config[:adapter]}_connection"
- assert @klass.respond_to?(name)
- assert ActiveRecord::Model.respond_to?(name)
- end
-
- def test_connection_handler
- assert_equal ActiveRecord::Base.connection_handler, @klass.connection_handler
- end
-
- def test_mirrored_configuration
- ActiveRecord::Base.time_zone_aware_attributes = true
- assert @klass.time_zone_aware_attributes
- ActiveRecord::Base.time_zone_aware_attributes = false
- assert !@klass.time_zone_aware_attributes
- ensure
- ActiveRecord::Base.time_zone_aware_attributes = false
- end
-
- # Doesn't really test anything, but this is here to ensure warnings don't occur
- def test_included_twice
- @klass.send :include, ActiveRecord::Model
- end
-
- def test_deprecation_proxy
- proxy = ActiveRecord::Model::DeprecationProxy.new
-
- assert_equal ActiveRecord::Model.name, proxy.name
- assert_equal ActiveRecord::Base.superclass, assert_deprecated { proxy.superclass }
-
- sup, sup2 = nil, nil
- ActiveSupport.on_load(:__test_active_record_model_deprecation) do
- sup = superclass
- sup2 = send(:superclass)
- end
- assert_deprecated do
- ActiveSupport.run_load_hooks(:__test_active_record_model_deprecation, proxy)
- end
- assert_equal ActiveRecord::Base.superclass, sup
- assert_equal ActiveRecord::Base.superclass, sup2
- end
-
- test "including in deprecation proxy" do
- model, base = ActiveRecord::Model.dup, ActiveRecord::Base.dup
- proxy = ActiveRecord::Model::DeprecationProxy.new(model, base)
-
- mod = Module.new
- proxy.include mod
- assert model < mod
- end
-
- test "extending in deprecation proxy" do
- model, base = ActiveRecord::Model.dup, ActiveRecord::Base.dup
- proxy = ActiveRecord::Model::DeprecationProxy.new(model, base)
-
- mod = Module.new
- assert_deprecated { proxy.extend mod }
- assert base.singleton_class < mod
- end
-end
-
-class InclusionFixturesTest < ActiveRecord::TestCase
- fixtures :teapots
-
- def test_fixtured_record
- assert_equal "Bob", teapots(:bob).name
- end
-
- def test_timestamped_fixture
- assert_not_nil teapots(:bob).created_at
- end
-end
diff --git a/activerecord/test/cases/inheritance_test.rb b/activerecord/test/cases/inheritance_test.rb
index 8fded9159f..aab7aa51dd 100644
--- a/activerecord/test/cases/inheritance_test.rb
+++ b/activerecord/test/cases/inheritance_test.rb
@@ -4,7 +4,6 @@ require 'models/person'
require 'models/post'
require 'models/project'
require 'models/subscriber'
-require 'models/teapot'
require 'models/vegetables'
class InheritanceTest < ActiveRecord::TestCase
@@ -81,10 +80,6 @@ class InheritanceTest < ActiveRecord::TestCase
assert_equal SubStiPost, SubStiPost.base_class
end
- def test_active_record_model_included_base_class
- assert_equal Teapot, Teapot.base_class
- end
-
def test_abstract_inheritance_base_class
assert_equal LoosePerson, LoosePerson.base_class
assert_equal LooseDescendant, LooseDescendant.base_class
@@ -93,11 +88,7 @@ class InheritanceTest < ActiveRecord::TestCase
end
def test_base_class_activerecord_error
- klass = Class.new {
- extend ActiveRecord::Configuration
- include ActiveRecord::Inheritance
- }
-
+ klass = Class.new { include ActiveRecord::Inheritance }
assert_raise(ActiveRecord::ActiveRecordError) { klass.base_class }
end
diff --git a/activerecord/test/cases/migration/change_schema_test.rb b/activerecord/test/cases/migration/change_schema_test.rb
index 17c1634444..86451289e7 100644
--- a/activerecord/test/cases/migration/change_schema_test.rb
+++ b/activerecord/test/cases/migration/change_schema_test.rb
@@ -132,6 +132,26 @@ module ActiveRecord
assert_equal %w(foo testingid), connection.columns(:testings).map(&:name).sort
end
+ def test_create_table_raises_when_redefining_primary_key_column
+ error = assert_raise(ArgumentError) do
+ connection.create_table :testings do |t|
+ t.column :id, :string
+ end
+ end
+
+ assert_equal "you can't redefine the primary key column 'id'. To define a custom primary key, pass { id: false } to create_table.", error.message
+ end
+
+ def test_create_table_raises_when_redefining_custom_primary_key_column
+ error = assert_raise(ArgumentError) do
+ connection.create_table :testings, primary_key: :testing_id do |t|
+ t.column :testing_id, :string
+ end
+ end
+
+ assert_equal "you can't redefine the primary key column 'testing_id'. To define a custom primary key, pass { id: false } to create_table.", error.message
+ end
+
def test_create_table_with_timestamps_should_create_datetime_columns
connection.create_table table_name do |t|
t.timestamps
diff --git a/activerecord/test/cases/multiple_db_test.rb b/activerecord/test/cases/multiple_db_test.rb
index 42461e8ecb..2e386a172a 100644
--- a/activerecord/test/cases/multiple_db_test.rb
+++ b/activerecord/test/cases/multiple_db_test.rb
@@ -96,12 +96,12 @@ class MultipleDbTest < ActiveRecord::TestCase
unless in_memory_db?
def test_associations_should_work_when_model_has_no_connection
begin
- ActiveRecord::Model.remove_connection
+ ActiveRecord::Base.remove_connection
assert_nothing_raised ActiveRecord::ConnectionNotEstablished do
College.first.courses.first
end
ensure
- ActiveRecord::Model.establish_connection 'arunit'
+ ActiveRecord::Base.establish_connection 'arunit'
end
end
end
diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb
index b5f32a57b2..4b938da5c4 100644
--- a/activerecord/test/cases/persistence_test.rb
+++ b/activerecord/test/cases/persistence_test.rb
@@ -592,6 +592,19 @@ class PersistencesTest < ActiveRecord::TestCase
assert_equal 'super_title', t.title
end
+ def test_update_columns_changing_id
+ topic = Topic.find(1)
+ topic.update_columns(id: 123)
+ assert_equal 123, topic.id
+ topic.reload
+ assert_equal 123, topic.id
+ end
+
+ def test_update_columns_returns_boolean
+ topic = Topic.find(1)
+ assert_equal true, topic.update_columns(title: "New title")
+ end
+
def test_update_attributes
topic = Topic.find(1)
assert !topic.approved?
diff --git a/activerecord/test/cases/pooled_connections_test.rb b/activerecord/test/cases/pooled_connections_test.rb
index 0a6354f5cc..a8a9b06ec4 100644
--- a/activerecord/test/cases/pooled_connections_test.rb
+++ b/activerecord/test/cases/pooled_connections_test.rb
@@ -7,17 +7,17 @@ class PooledConnectionsTest < ActiveRecord::TestCase
def setup
@per_test_teardown = []
- @connection = ActiveRecord::Model.remove_connection
+ @connection = ActiveRecord::Base.remove_connection
end
def teardown
- ActiveRecord::Model.clear_all_connections!
- ActiveRecord::Model.establish_connection(@connection)
+ ActiveRecord::Base.clear_all_connections!
+ ActiveRecord::Base.establish_connection(@connection)
@per_test_teardown.each {|td| td.call }
end
def checkout_connections
- ActiveRecord::Model.establish_connection(@connection.merge({:pool => 2, :checkout_timeout => 0.3}))
+ ActiveRecord::Base.establish_connection(@connection.merge({:pool => 2, :checkout_timeout => 0.3}))
@connections = []
@timed_out = 0
@@ -34,15 +34,15 @@ class PooledConnectionsTest < ActiveRecord::TestCase
# Will deadlock due to lack of Monitor timeouts in 1.9
def checkout_checkin_connections(pool_size, threads)
- ActiveRecord::Model.establish_connection(@connection.merge({:pool => pool_size, :checkout_timeout => 0.5}))
+ ActiveRecord::Base.establish_connection(@connection.merge({:pool => pool_size, :checkout_timeout => 0.5}))
@connection_count = 0
@timed_out = 0
threads.times do
Thread.new do
begin
- conn = ActiveRecord::Model.connection_pool.checkout
+ conn = ActiveRecord::Base.connection_pool.checkout
sleep 0.1
- ActiveRecord::Model.connection_pool.checkin conn
+ ActiveRecord::Base.connection_pool.checkin conn
@connection_count += 1
rescue ActiveRecord::ConnectionTimeoutError
@timed_out += 1
@@ -55,13 +55,13 @@ class PooledConnectionsTest < ActiveRecord::TestCase
checkout_checkin_connections 1, 2
assert_equal 2, @connection_count
assert_equal 0, @timed_out
- assert_equal 1, ActiveRecord::Model.connection_pool.connections.size
+ assert_equal 1, ActiveRecord::Base.connection_pool.connections.size
end
private
def add_record(name)
- ActiveRecord::Model.connection_pool.with_connection { Project.create! :name => name }
+ ActiveRecord::Base.connection_pool.with_connection { Project.create! :name => name }
end
end unless current_adapter?(:FrontBase) || in_memory_db?
diff --git a/activerecord/test/cases/primary_keys_test.rb b/activerecord/test/cases/primary_keys_test.rb
index e6e50a4cd4..bf8aacc363 100644
--- a/activerecord/test/cases/primary_keys_test.rb
+++ b/activerecord/test/cases/primary_keys_test.rb
@@ -188,14 +188,14 @@ class PrimaryKeyWithNoConnectionTest < ActiveRecord::TestCase
def test_set_primary_key_with_no_connection
return skip("disconnect wipes in-memory db") if in_memory_db?
- connection = ActiveRecord::Model.remove_connection
+ connection = ActiveRecord::Base.remove_connection
model = Class.new(ActiveRecord::Base)
model.primary_key = 'foo'
assert_equal 'foo', model.primary_key
- ActiveRecord::Model.establish_connection(connection)
+ ActiveRecord::Base.establish_connection(connection)
assert_equal 'foo', model.primary_key
end
diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb
index 51a285a2b4..4ff481e6a5 100644
--- a/activerecord/test/cases/query_cache_test.rb
+++ b/activerecord/test/cases/query_cache_test.rb
@@ -184,6 +184,17 @@ class QueryCacheTest < ActiveRecord::TestCase
assert_queries(2) { task.lock!; task.lock! }
end
end
+
+ def test_cache_is_available_when_connection_is_connected
+ conf = ActiveRecord::Base.configurations
+
+ ActiveRecord::Base.configurations = {}
+ Task.cache do
+ assert_queries(1) { Task.find(1); Task.find(1) }
+ end
+ ensure
+ ActiveRecord::Base.configurations = conf
+ end
end
class QueryCacheExpiryTest < ActiveRecord::TestCase
diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb
index 6399111be6..98e278df82 100644
--- a/activerecord/test/cases/relation_test.rb
+++ b/activerecord/test/cases/relation_test.rb
@@ -256,5 +256,11 @@ module ActiveRecord
test 'merge with a proc' do
assert_equal [:foo], relation.merge(-> { where(:foo) }).where_values
end
+
+ test 'none!' do
+ assert relation.none!.equal?(relation)
+ assert_equal [NullRelation], relation.extending_values
+ assert relation.is_a?(NullRelation)
+ end
end
end
diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb
index 5f96145b47..bc6cac0c6c 100644
--- a/activerecord/test/cases/relations_test.rb
+++ b/activerecord/test/cases/relations_test.rb
@@ -1391,6 +1391,15 @@ class RelationTest < ActiveRecord::TestCase
end
end
+ test "loaded relations cannot be mutated by extending!" do
+ relation = Post.all
+ relation.to_a
+
+ assert_raises(ActiveRecord::ImmutableRelation) do
+ relation.extending! Module.new
+ end
+ end
+
test "relations show the records in #inspect" do
relation = Post.limit(2)
assert_equal "#<ActiveRecord::Relation [#{Post.limit(2).map(&:inspect).join(', ')}]>", relation.inspect
diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb
index 5f13124e5b..7ff0044bd4 100644
--- a/activerecord/test/cases/schema_dumper_test.rb
+++ b/activerecord/test/cases/schema_dumper_test.rb
@@ -203,6 +203,12 @@ class SchemaDumperTest < ActiveRecord::TestCase
assert_match %r{t.text\s+"body",\s+null: false$}, output
end
+ def test_schema_dump_includes_length_for_mysql_binary_fields
+ output = standard_dump
+ assert_match %r{t.binary\s+"var_binary",\s+limit: 255$}, output
+ assert_match %r{t.binary\s+"var_binary_large",\s+limit: 4095$}, output
+ end
+
def test_schema_dump_includes_length_for_mysql_blob_and_text_fields
output = standard_dump
assert_match %r{t.binary\s+"tiny_blob",\s+limit: 255$}, output
diff --git a/activerecord/test/cases/serialization_test.rb b/activerecord/test/cases/serialization_test.rb
index 25b860878a..eb9cb91e32 100644
--- a/activerecord/test/cases/serialization_test.rb
+++ b/activerecord/test/cases/serialization_test.rb
@@ -45,4 +45,20 @@ class SerializationTest < ActiveRecord::TestCase
assert_equal @contact_attributes[:awesome], contact.awesome, "For #{format}"
end
end
+
+ def test_include_root_in_json_allows_inheritance
+ original_root_in_json = ActiveRecord::Base.include_root_in_json
+ ActiveRecord::Base.include_root_in_json = true
+
+ klazz = Class.new(ActiveRecord::Base)
+ klazz.table_name = 'topics'
+ assert klazz.include_root_in_json
+
+ klazz.include_root_in_json = false
+ assert ActiveRecord::Base.include_root_in_json
+ assert !klazz.include_root_in_json
+ assert !klazz.new.include_root_in_json
+ ensure
+ ActiveRecord::Base.include_root_in_json = original_root_in_json
+ end
end
diff --git a/activerecord/test/cases/serialized_attribute_test.rb b/activerecord/test/cases/serialized_attribute_test.rb
index f24ee54cd2..068f3cf3cd 100644
--- a/activerecord/test/cases/serialized_attribute_test.rb
+++ b/activerecord/test/cases/serialized_attribute_test.rb
@@ -56,11 +56,21 @@ class SerializedAttributeTest < ActiveRecord::TestCase
def test_serialized_attribute_before_type_cast_returns_unserialized_value
Topic.serialize :content, Hash
- t = Topic.new(:content => { :foo => :bar })
- assert_equal({ :foo => :bar }, t.content_before_type_cast)
+ t = Topic.new(content: { foo: :bar })
+ assert_equal({ foo: :bar }, t.content_before_type_cast)
t.save!
t.reload
- assert_equal({ :foo => :bar }, t.content_before_type_cast)
+ assert_equal({ foo: :bar }, t.content_before_type_cast)
+ end
+
+ def test_serialized_attributes_before_type_cast_returns_unserialized_value
+ Topic.serialize :content, Hash
+
+ t = Topic.new(content: { foo: :bar })
+ assert_equal({ foo: :bar }, t.attributes_before_type_cast["content"])
+ t.save!
+ t.reload
+ assert_equal({ foo: :bar }, t.attributes_before_type_cast["content"])
end
def test_serialized_attribute_calling_dup_method
diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb
index bb4f2c8064..fdca10f4fb 100644
--- a/activerecord/test/cases/transactions_test.rb
+++ b/activerecord/test/cases/transactions_test.rb
@@ -14,6 +14,21 @@ class TransactionTest < ActiveRecord::TestCase
@first, @second = Topic.find(1, 2).sort_by { |t| t.id }
end
+ def test_raise_after_destroy
+ refute @first.frozen?
+
+ assert_raises(RuntimeError) {
+ Topic.transaction do
+ @first.destroy
+ assert @first.frozen?
+ raise
+ end
+ }
+
+ assert @first.reload
+ refute @first.frozen?
+ end
+
def test_successful
Topic.transaction do
@first.approved = true
diff --git a/activerecord/test/cases/unconnected_test.rb b/activerecord/test/cases/unconnected_test.rb
index 5a69054445..e82ca3f93d 100644
--- a/activerecord/test/cases/unconnected_test.rb
+++ b/activerecord/test/cases/unconnected_test.rb
@@ -7,13 +7,13 @@ class TestUnconnectedAdapter < ActiveRecord::TestCase
self.use_transactional_fixtures = false
def setup
- @underlying = ActiveRecord::Model.connection
- @specification = ActiveRecord::Model.remove_connection
+ @underlying = ActiveRecord::Base.connection
+ @specification = ActiveRecord::Base.remove_connection
end
def teardown
@underlying = nil
- ActiveRecord::Model.establish_connection(@specification)
+ ActiveRecord::Base.establish_connection(@specification)
load_schema if in_memory_db?
end
diff --git a/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb b/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb
index 174d96aa4e..32d2bf746f 100644
--- a/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb
+++ b/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb
@@ -59,4 +59,18 @@ class I18nGenerateMessageValidationTest < ActiveRecord::TestCase
assert_equal "Custom taken message", @topic.errors.generate_message(:title, :taken, :value => 'title')
end
+ test "translation for 'taken' can be overridden in activerecord scope" do
+ I18n.backend.store_translations "en", {activerecord: {errors: {messages: {taken: "Custom taken message" }}}}
+ assert_equal "Custom taken message", @topic.errors.generate_message(:title, :taken, :value => 'title')
+ end
+
+ test "translation for 'taken' can be overridden in activerecord model scope" do
+ I18n.backend.store_translations "en", {activerecord: {errors: {models: {topic: {taken: "Custom taken message" }}}}}
+ assert_equal "Custom taken message", @topic.errors.generate_message(:title, :taken, :value => 'title')
+ end
+
+ test "translation for 'taken' can be overridden in activerecord attributes scope" do
+ I18n.backend.store_translations "en", {activerecord: {errors: {models: {topic: {attributes: {title: {taken: "Custom taken message" }}}}}}}
+ assert_equal "Custom taken message", @topic.errors.generate_message(:title, :taken, :value => 'title')
+ end
end
diff --git a/activerecord/test/models/teapot.rb b/activerecord/test/models/teapot.rb
deleted file mode 100644
index b035b18c1b..0000000000
--- a/activerecord/test/models/teapot.rb
+++ /dev/null
@@ -1,35 +0,0 @@
-class Teapot
- # I'm a little teapot,
- # Short and stout,
- # Here is my handle
- # Here is my spout
- # When I get all steamed up,
- # Hear me shout,
- # Tip me over and pour me out!
- #
- # HELL YEAH TEAPOT SONG
-
- include ActiveRecord::Model
-end
-
-class OtherTeapot < Teapot
-end
-
-class OMFGIMATEAPOT
- def aaahhh
- "mmm"
- end
-end
-
-class CoolTeapot < OMFGIMATEAPOT
- include ActiveRecord::Model
- self.table_name = "teapots"
-end
-
-class Ceiling
- include ActiveRecord::Model
-
- class Teapot
- include ActiveRecord::Model
- end
-end
diff --git a/activerecord/test/schema/mysql2_specific_schema.rb b/activerecord/test/schema/mysql2_specific_schema.rb
index 24a43d7ece..f25f72c481 100644
--- a/activerecord/test/schema/mysql2_specific_schema.rb
+++ b/activerecord/test/schema/mysql2_specific_schema.rb
@@ -1,15 +1,19 @@
ActiveRecord::Schema.define do
- create_table :binary_fields, :force => true do |t|
- t.binary :tiny_blob, :limit => 255
- t.binary :normal_blob, :limit => 65535
- t.binary :medium_blob, :limit => 16777215
- t.binary :long_blob, :limit => 2147483647
- t.text :tiny_text, :limit => 255
- t.text :normal_text, :limit => 65535
- t.text :medium_text, :limit => 16777215
- t.text :long_text, :limit => 2147483647
+ create_table :binary_fields, force: true do |t|
+ t.binary :var_binary, limit: 255
+ t.binary :var_binary_large, limit: 4095
+ t.column :tiny_blob, 'tinyblob', limit: 255
+ t.binary :normal_blob, limit: 65535
+ t.binary :medium_blob, limit: 16777215
+ t.binary :long_blob, limit: 2147483647
+ t.text :tiny_text, limit: 255
+ t.text :normal_text, limit: 65535
+ t.text :medium_text, limit: 16777215
+ t.text :long_text, limit: 2147483647
end
+ add_index :binary_fields, :var_binary
+
ActiveRecord::Base.connection.execute <<-SQL
DROP PROCEDURE IF EXISTS ten;
SQL
diff --git a/activerecord/test/schema/mysql_specific_schema.rb b/activerecord/test/schema/mysql_specific_schema.rb
index 802c08b819..5401c12ed5 100644
--- a/activerecord/test/schema/mysql_specific_schema.rb
+++ b/activerecord/test/schema/mysql_specific_schema.rb
@@ -1,15 +1,19 @@
ActiveRecord::Schema.define do
- create_table :binary_fields, :force => true do |t|
- t.binary :tiny_blob, :limit => 255
- t.binary :normal_blob, :limit => 65535
- t.binary :medium_blob, :limit => 16777215
- t.binary :long_blob, :limit => 2147483647
- t.text :tiny_text, :limit => 255
- t.text :normal_text, :limit => 65535
- t.text :medium_text, :limit => 16777215
- t.text :long_text, :limit => 2147483647
+ create_table :binary_fields, force: true do |t|
+ t.binary :var_binary, limit: 255
+ t.binary :var_binary_large, limit: 4095
+ t.column :tiny_blob, 'tinyblob', limit: 255
+ t.binary :normal_blob, limit: 65535
+ t.binary :medium_blob, limit: 16777215
+ t.binary :long_blob, limit: 2147483647
+ t.text :tiny_text, limit: 255
+ t.text :normal_text, limit: 65535
+ t.text :medium_text, limit: 16777215
+ t.text :long_text, limit: 2147483647
end
+ add_index :binary_fields, :var_binary
+
ActiveRecord::Base.connection.execute <<-SQL
DROP PROCEDURE IF EXISTS ten;
SQL
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index 2e4ec96933..eec06754a5 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -648,12 +648,6 @@ ActiveRecord::Schema.define do
t.datetime :ending
end
- create_table :teapots, :force => true do |t|
- t.string :name
- t.string :type
- t.timestamps
- end
-
create_table :topics, :force => true do |t|
t.string :title
t.string :author_name
diff --git a/activerecord/test/support/connection.rb b/activerecord/test/support/connection.rb
index bea894a583..196b3a9493 100644
--- a/activerecord/test/support/connection.rb
+++ b/activerecord/test/support/connection.rb
@@ -13,9 +13,9 @@ module ARTest
def self.connect
puts "Using #{connection_name}"
- ActiveRecord::Model.logger = ActiveSupport::Logger.new("debug.log", 0, 100 * 1024 * 1024)
- ActiveRecord::Model.configurations = connection_config
- ActiveRecord::Model.establish_connection 'arunit'
+ ActiveRecord::Base.logger = ActiveSupport::Logger.new("debug.log", 0, 100 * 1024 * 1024)
+ ActiveRecord::Base.configurations = connection_config
+ ActiveRecord::Base.establish_connection 'arunit'
ARUnit2Model.establish_connection 'arunit2'
end
end
diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md
index 23e2ce0b03..6534c0af85 100644
--- a/activesupport/CHANGELOG.md
+++ b/activesupport/CHANGELOG.md
@@ -1,5 +1,16 @@
## Rails 4.0.0 (unreleased) ##
+* Fixed timezone mapping of the Solomon Islands. *Steve Klabnik*
+
+* Make callstack attribute optional in
+ ActiveSupport::Deprecation::Reporting methods `warn` and `deprecation_warning`
+
+ *Alexey Gaziev*
+
+* Implement HashWithIndifferentAccess#replace so key? works correctly. *David Graham*
+
+* Handle the possible Permission Denied errors atomic.rb might trigger due to its chown and chmod calls. *Daniele Sluijters*
+
* Hash#extract! returns only those keys that present in the receiver.
{:a => 1, :b => 2}.extract!(:a, :x) # => {:a => 1}
diff --git a/activesupport/lib/active_support/benchmarkable.rb b/activesupport/lib/active_support/benchmarkable.rb
index 3d8bb13c49..6413502b53 100644
--- a/activesupport/lib/active_support/benchmarkable.rb
+++ b/activesupport/lib/active_support/benchmarkable.rb
@@ -48,7 +48,8 @@ module ActiveSupport
# Silence the logger during the execution of the block.
def silence
- ActiveSupport::Deprecation.warn "ActiveSupport::Benchmarkable#silence is deprecated. It will be removed from Rails 4.1."
+ message = "ActiveSupport::Benchmarkable#silence is deprecated. It will be removed from Rails 4.1."
+ ActiveSupport::Deprecation.warn message
old_logger_level, logger.level = logger.level, ::Logger::ERROR if logger
yield
ensure
diff --git a/activesupport/lib/active_support/cache.rb b/activesupport/lib/active_support/cache.rb
index 732ab4b7df..9a53870b3d 100644
--- a/activesupport/lib/active_support/cache.rb
+++ b/activesupport/lib/active_support/cache.rb
@@ -182,10 +182,10 @@ module ActiveSupport
# the cache with the given key, then that data is returned.
#
# If there is no such data in the cache (a cache miss), then +nil+ will be
- # returned. However, if a block has been passed, that block will be run
- # in the event of a cache miss. The return value of the block will be
- # written to the cache under the given cache key, and that return value
- # will be returned.
+ # returned. However, if a block has been passed, that block will be passed
+ # the key and executed in the event of a cache miss. The return value of the
+ # block will be written to the cache under the given cache key, and that
+ # return value will be returned.
#
# cache.write('today', 'Monday')
# cache.fetch('today') # => "Monday"
@@ -300,7 +300,7 @@ module ActiveSupport
entry.value
else
result = instrument(:generate, name, options) do |payload|
- yield
+ yield(name)
end
write(name, result, options)
result
diff --git a/activesupport/lib/active_support/callbacks.rb b/activesupport/lib/active_support/callbacks.rb
index a02793bde9..8199f431f1 100644
--- a/activesupport/lib/active_support/callbacks.rb
+++ b/activesupport/lib/active_support/callbacks.rb
@@ -282,12 +282,15 @@ module ActiveSupport
def _normalize_legacy_filter(kind, filter)
if !filter.respond_to?(kind) && filter.respond_to?(:filter)
- ActiveSupport::Deprecation.warn("Filter object with #filter method is deprecated. Define method corresponding to filter type (#before, #after or #around).")
+ message = "Filter object with #filter method is deprecated. Define method corresponding " \
+ "to filter type (#before, #after or #around)."
+ ActiveSupport::Deprecation.warn message
filter.singleton_class.class_eval <<-RUBY_EVAL, __FILE__, __LINE__ + 1
def #{kind}(context, &block) filter(context, &block) end
RUBY_EVAL
elsif filter.respond_to?(:before) && filter.respond_to?(:after) && kind == :around && !filter.respond_to?(:around)
- ActiveSupport::Deprecation.warn("Filter object with #before and #after methods is deprecated. Define #around method instead.")
+ message = "Filter object with #before and #after methods is deprecated. Define #around method instead."
+ ActiveSupport::Deprecation.warn message
def filter.around(context)
should_continue = before(context)
yield if should_continue
diff --git a/activesupport/lib/active_support/core_ext/array/uniq_by.rb b/activesupport/lib/active_support/core_ext/array/uniq_by.rb
index c1d5a355a4..ca3b7748cd 100644
--- a/activesupport/lib/active_support/core_ext/array/uniq_by.rb
+++ b/activesupport/lib/active_support/core_ext/array/uniq_by.rb
@@ -5,7 +5,7 @@ class Array
#
# [1, 2, 3, 4].uniq_by { |i| i.odd? } # => [1, 2]
def uniq_by(&block)
- ActiveSupport::Deprecation.warn 'uniq_by is deprecated. Use Array#uniq instead', caller
+ ActiveSupport::Deprecation.warn 'uniq_by is deprecated. Use Array#uniq instead'
uniq(&block)
end
@@ -13,7 +13,7 @@ class Array
#
# Same as +uniq_by+, but modifies +self+.
def uniq_by!(&block)
- ActiveSupport::Deprecation.warn 'uniq_by! is deprecated. Use Array#uniq! instead', caller
+ ActiveSupport::Deprecation.warn 'uniq_by! is deprecated. Use Array#uniq! instead'
uniq!(&block)
end
end
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 385aa586bb..0c6437b02b 100644
--- a/activesupport/lib/active_support/core_ext/date_time/calculations.rb
+++ b/activesupport/lib/active_support/core_ext/date_time/calculations.rb
@@ -4,7 +4,7 @@ class DateTime
class << self
# *DEPRECATED*: Use +DateTime.civil_from_format+ directly.
def local_offset
- ActiveSupport::Deprecation.warn 'DateTime.local_offset is deprecated. Use DateTime.civil_from_format directly.', caller
+ ActiveSupport::Deprecation.warn 'DateTime.local_offset is deprecated. Use DateTime.civil_from_format directly.'
::Time.local(2012).utc_offset.to_r / 86400
end
diff --git a/activesupport/lib/active_support/core_ext/file/atomic.rb b/activesupport/lib/active_support/core_ext/file/atomic.rb
index 81beb4e85d..c3e6124a57 100644
--- a/activesupport/lib/active_support/core_ext/file/atomic.rb
+++ b/activesupport/lib/active_support/core_ext/file/atomic.rb
@@ -23,10 +23,10 @@ class File
yield temp_file
temp_file.close
- begin
+ if File.exists?(file_name)
# Get original file permissions
old_stat = stat(file_name)
- rescue Errno::ENOENT
+ else
# If not possible, probe which are the default permissions in the
# destination directory.
old_stat = probe_stat_in(dirname(file_name))
@@ -36,8 +36,13 @@ class File
FileUtils.mv(temp_file.path, file_name)
# Set correct permissions on new file
- chown(old_stat.uid, old_stat.gid, file_name)
- chmod(old_stat.mode, file_name)
+ begin
+ chown(old_stat.uid, old_stat.gid, file_name)
+ # This operation will affect filesystem ACL's
+ chmod(old_stat.mode, file_name)
+ rescue Errno::EPERM
+ # Changing file ownership failed, moving on.
+ end
end
# Private utility method.
diff --git a/activesupport/lib/active_support/core_ext/module/introspection.rb b/activesupport/lib/active_support/core_ext/module/introspection.rb
index 649a969149..08e5f8a5c3 100644
--- a/activesupport/lib/active_support/core_ext/module/introspection.rb
+++ b/activesupport/lib/active_support/core_ext/module/introspection.rb
@@ -72,7 +72,7 @@ class Module
# This method is useful for forward compatibility, since Ruby 1.8 returns
# constant names as strings, whereas 1.9 returns them as symbols.
def local_constant_names
- ActiveSupport::Deprecation.warn 'Module#local_constant_names is deprecated, use Module#local_constants instead', caller
+ ActiveSupport::Deprecation.warn 'Module#local_constant_names is deprecated, use Module#local_constants instead'
local_constants.map { |c| c.to_s }
end
end
diff --git a/activesupport/lib/active_support/core_ext/proc.rb b/activesupport/lib/active_support/core_ext/proc.rb
index cd63740940..166c3855a0 100644
--- a/activesupport/lib/active_support/core_ext/proc.rb
+++ b/activesupport/lib/active_support/core_ext/proc.rb
@@ -3,7 +3,7 @@ require "active_support/deprecation"
class Proc #:nodoc:
def bind(object)
- ActiveSupport::Deprecation.warn 'Proc#bind is deprecated and will be removed in future versions', caller
+ ActiveSupport::Deprecation.warn 'Proc#bind is deprecated and will be removed in future versions'
block, time = self, Time.now
object.class_eval do
diff --git a/activesupport/lib/active_support/core_ext/string/encoding.rb b/activesupport/lib/active_support/core_ext/string/encoding.rb
index dc635ed6a5..a583b914db 100644
--- a/activesupport/lib/active_support/core_ext/string/encoding.rb
+++ b/activesupport/lib/active_support/core_ext/string/encoding.rb
@@ -2,7 +2,7 @@ require 'active_support/deprecation'
class String
def encoding_aware?
- ActiveSupport::Deprecation.warn 'String#encoding_aware? is deprecated', caller
+ ActiveSupport::Deprecation.warn 'String#encoding_aware? is deprecated'
true
end
end
diff --git a/activesupport/lib/active_support/deprecation/method_wrappers.rb b/activesupport/lib/active_support/deprecation/method_wrappers.rb
index d3907b03e5..cab8a1b14d 100644
--- a/activesupport/lib/active_support/deprecation/method_wrappers.rb
+++ b/activesupport/lib/active_support/deprecation/method_wrappers.rb
@@ -33,7 +33,7 @@ module ActiveSupport
method_names.each do |method_name|
target_module.alias_method_chain(method_name, :deprecation) do |target, punctuation|
target_module.send(:define_method, "#{target}_with_deprecation#{punctuation}") do |*args, &block|
- deprecator.deprecation_warning(method_name, options[method_name], caller)
+ deprecator.deprecation_warning(method_name, options[method_name])
send(:"#{target}_without_deprecation#{punctuation}", *args, &block)
end
end
diff --git a/activesupport/lib/active_support/deprecation/reporting.rb b/activesupport/lib/active_support/deprecation/reporting.rb
index 1ce54d9381..a7d265d732 100644
--- a/activesupport/lib/active_support/deprecation/reporting.rb
+++ b/activesupport/lib/active_support/deprecation/reporting.rb
@@ -11,8 +11,10 @@ module ActiveSupport
#
# ActiveSupport::Deprecation.warn('something broke!')
# # => "DEPRECATION WARNING: something broke! (called from your_code.rb:1)"
- def warn(message = nil, callstack = caller)
+ def warn(message = nil, callstack = nil)
return if silenced
+
+ callstack ||= caller(2)
deprecation_message(callstack, message).tap do |m|
behavior.each { |b| b.call(m, callstack) }
end
@@ -34,7 +36,8 @@ module ActiveSupport
@silenced = old_silenced
end
- def deprecation_warning(deprecated_method_name, message = nil, caller_backtrace = caller)
+ def deprecation_warning(deprecated_method_name, message = nil, caller_backtrace = nil)
+ caller_backtrace ||= caller(2)
deprecated_method_warning(deprecated_method_name, message).tap do |msg|
warn(msg, caller_backtrace)
end
diff --git a/activesupport/lib/active_support/hash_with_indifferent_access.rb b/activesupport/lib/active_support/hash_with_indifferent_access.rb
index 0c78f1611f..306d80b2df 100644
--- a/activesupport/lib/active_support/hash_with_indifferent_access.rb
+++ b/activesupport/lib/active_support/hash_with_indifferent_access.rb
@@ -204,6 +204,14 @@ module ActiveSupport
replace(reverse_merge( other_hash ))
end
+ # Replaces the contents of this hash with other_hash.
+ #
+ # h = { "a" => 100, "b" => 200 }
+ # h.replace({ "c" => 300, "d" => 400 }) #=> {"c"=>300, "d"=>400}
+ def replace(other_hash)
+ super(self.class.new_from_hash_copying_default(other_hash))
+ end
+
# Removes the specified key from the hash.
def delete(key)
super(convert_key(key))
diff --git a/activesupport/lib/active_support/json/variable.rb b/activesupport/lib/active_support/json/variable.rb
index 8af661a795..d69dab6408 100644
--- a/activesupport/lib/active_support/json/variable.rb
+++ b/activesupport/lib/active_support/json/variable.rb
@@ -5,8 +5,9 @@ module ActiveSupport
# Deprecated: A string that returns itself as its JSON-encoded form.
class Variable < String
def initialize(*args)
- ActiveSupport::Deprecation.warn 'ActiveSupport::JSON::Variable is deprecated and will be removed in Rails 4.1. ' \
- 'For your own custom JSON literals, define #as_json and #encode_json yourself.'
+ message = 'ActiveSupport::JSON::Variable is deprecated and will be removed in Rails 4.1. ' \
+ 'For your own custom JSON literals, define #as_json and #encode_json yourself.'
+ ActiveSupport::Deprecation.warn message
super
end
diff --git a/activesupport/lib/active_support/queueing.rb b/activesupport/lib/active_support/queueing.rb
index c8ba28021d..a89a48d057 100644
--- a/activesupport/lib/active_support/queueing.rb
+++ b/activesupport/lib/active_support/queueing.rb
@@ -64,9 +64,12 @@ module ActiveSupport
# queue and joins the thread, which will ensure that all jobs
# are executed before the process finally dies.
class ThreadedQueueConsumer
+ attr_accessor :logger
+
def initialize(queue, options = {})
@queue = queue
@logger = options[:logger]
+ @fallback_logger = Logger.new($stderr)
end
def start
@@ -80,7 +83,7 @@ module ActiveSupport
end
def drain
- run(@queue.pop) until @queue.empty?
+ @queue.pop.run until @queue.empty?
end
def consume
@@ -96,8 +99,7 @@ module ActiveSupport
end
def handle_exception(job, exception)
- raise exception unless @logger
- @logger.error "Job Error: #{exception.message}\n#{exception.backtrace.join("\n")}"
+ (logger || @fallback_logger).error "Job Error: #{job.inspect}\n#{exception.message}\n#{exception.backtrace.join("\n")}"
end
end
end
diff --git a/activesupport/lib/active_support/test_case.rb b/activesupport/lib/active_support/test_case.rb
index 7b9378a7f6..8b06739b7f 100644
--- a/activesupport/lib/active_support/test_case.rb
+++ b/activesupport/lib/active_support/test_case.rb
@@ -17,7 +17,7 @@ module ActiveSupport
# Use AS::TestCase for the base class when describing a model
register_spec_type(self) do |desc|
- Class === desc && desc < ActiveRecord::Model
+ Class === desc && desc < ActiveRecord::Base
end
Assertion = MiniTest::Assertion
@@ -43,7 +43,8 @@ module ActiveSupport
if block_given?
super
else
- ActiveSupport::Deprecation.warn("`describe` without a block is deprecated, please switch to: `def self.name; #{text.inspect}; end`\n")
+ 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
diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb
index 231d61da96..0207f53238 100644
--- a/activesupport/lib/active_support/values/time_zone.rb
+++ b/activesupport/lib/active_support/values/time_zone.rb
@@ -167,7 +167,7 @@ module ActiveSupport
"Guam" => "Pacific/Guam",
"Port Moresby" => "Pacific/Port_Moresby",
"Magadan" => "Asia/Magadan",
- "Solomon Is." => "Asia/Magadan",
+ "Solomon Is." => "Pacific/Guadalcanal",
"New Caledonia" => "Pacific/Noumea",
"Fiji" => "Pacific/Fiji",
"Kamchatka" => "Asia/Kamchatka",
diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb
index 9f76f4c90b..ed903746c8 100644
--- a/activesupport/test/caching_test.rb
+++ b/activesupport/test/caching_test.rb
@@ -83,7 +83,7 @@ class CacheKeyTest < ActiveSupport::TestCase
def test_expand_cache_key_of_true
assert_equal 'true', ActiveSupport::Cache.expand_cache_key(true)
end
-
+
def test_expand_cache_key_of_array_like_object
assert_equal 'foo/bar/baz', ActiveSupport::Cache.expand_cache_key(%w{foo bar baz}.to_enum)
end
@@ -197,6 +197,16 @@ module CacheStoreBehavior
assert_equal 'baz', @cache.fetch('foo') { 'baz' }
end
+ def test_fetch_with_cache_miss_passes_key_to_block
+ cache_miss = false
+ assert_equal 3, @cache.fetch('foo') { |key| cache_miss = true; key.length }
+ assert cache_miss
+
+ cache_miss = false
+ assert_equal 3, @cache.fetch('foo') { |key| cache_miss = true; key.length }
+ assert !cache_miss
+ end
+
def test_fetch_with_forced_cache_miss
@cache.write('foo', 'bar')
@cache.expects(:read).never
@@ -594,7 +604,7 @@ class FileStoreTest < ActiveSupport::TestCase
assert_equal "views/index?id=1", @cache_with_pathname.send(:file_path_key, key)
end
- # Test that generated cache keys are short enough to have Tempfile stuff added to them and
+ # Test that generated cache keys are short enough to have Tempfile stuff added to them and
# remain valid
def test_filename_max_size
key = "#{'A' * ActiveSupport::Cache::FileStore::FILENAME_MAX_SIZE}"
diff --git a/activesupport/test/core_ext/hash_ext_test.rb b/activesupport/test/core_ext/hash_ext_test.rb
index 7cfe7b0ea7..6746b58cd3 100644
--- a/activesupport/test/core_ext/hash_ext_test.rb
+++ b/activesupport/test/core_ext/hash_ext_test.rb
@@ -428,6 +428,18 @@ class HashExtTest < ActiveSupport::TestCase
assert_equal 2, hash['b']
end
+ def test_indifferent_replace
+ hash = HashWithIndifferentAccess.new
+ hash[:a] = 42
+
+ replaced = hash.replace(b: 12)
+
+ assert hash.key?('b')
+ assert !hash.key?(:a)
+ assert_equal 12, hash[:b]
+ assert_same hash, replaced
+ end
+
def test_indifferent_merging_with_block
hash = HashWithIndifferentAccess.new
hash[:a] = 1
diff --git a/activesupport/test/core_ext/module/qualified_const_test.rb b/activesupport/test/core_ext/module/qualified_const_test.rb
index 343a848a42..37c9228a64 100644
--- a/activesupport/test/core_ext/module/qualified_const_test.rb
+++ b/activesupport/test/core_ext/module/qualified_const_test.rb
@@ -89,13 +89,20 @@ class QualifiedConstTest < ActiveSupport::TestCase
end
test "reject absolute paths" do
- assert_raise(NameError, "wrong constant name ::X") { Object.qualified_const_defined?("::X")}
- assert_raise(NameError, "wrong constant name ::X") { Object.qualified_const_defined?("::X::Y")}
+ assert_raise_with_message(NameError, "wrong constant name ::X") { Object.qualified_const_defined?("::X")}
+ assert_raise_with_message(NameError, "wrong constant name ::X") { Object.qualified_const_defined?("::X::Y")}
- assert_raise(NameError, "wrong constant name ::X") { Object.qualified_const_get("::X")}
- assert_raise(NameError, "wrong constant name ::X") { Object.qualified_const_get("::X::Y")}
+ assert_raise_with_message(NameError, "wrong constant name ::X") { Object.qualified_const_get("::X")}
+ assert_raise_with_message(NameError, "wrong constant name ::X") { Object.qualified_const_get("::X::Y")}
- assert_raise(NameError, "wrong constant name ::X") { Object.qualified_const_set("::X", nil)}
- assert_raise(NameError, "wrong constant name ::X") { Object.qualified_const_set("::X::Y", nil)}
+ assert_raise_with_message(NameError, "wrong constant name ::X") { Object.qualified_const_set("::X", nil)}
+ assert_raise_with_message(NameError, "wrong constant name ::X") { Object.qualified_const_set("::X::Y", nil)}
+ end
+
+ private
+
+ def assert_raise_with_message(expected_exception, expected_message, &block)
+ exception = assert_raise(expected_exception, &block)
+ assert_equal expected_message, exception.message
end
end
diff --git a/activesupport/test/dependencies_test.rb b/activesupport/test/dependencies_test.rb
index e5bc806397..670a04e5df 100644
--- a/activesupport/test/dependencies_test.rb
+++ b/activesupport/test/dependencies_test.rb
@@ -147,7 +147,8 @@ class DependenciesTest < ActiveSupport::TestCase
def test_circular_autoloading_detection
with_autoloading_fixtures do
- assert_raise(RuntimeError, "Circular dependency detected while autoloading constant Circular1") { Circular1 }
+ e = assert_raise(RuntimeError) { Circular1 }
+ assert_equal "Circular dependency detected while autoloading constant Circular1", e.message
end
end
diff --git a/activesupport/test/deprecation_test.rb b/activesupport/test/deprecation_test.rb
index c081103cc7..332100f5a1 100644
--- a/activesupport/test/deprecation_test.rb
+++ b/activesupport/test/deprecation_test.rb
@@ -9,7 +9,7 @@ class Deprecatee
def old_request; @request end
def partially(foo = nil)
- ActiveSupport::Deprecation.warn('calling with foo=nil is out', caller) if foo.nil?
+ ActiveSupport::Deprecation.warn('calling with foo=nil is out') if foo.nil?
end
def not() 2 end
diff --git a/activesupport/test/queueing/threaded_consumer_test.rb b/activesupport/test/queueing/threaded_consumer_test.rb
index fc43cb555a..a3ca46a261 100644
--- a/activesupport/test/queueing/threaded_consumer_test.rb
+++ b/activesupport/test/queueing/threaded_consumer_test.rb
@@ -65,10 +65,22 @@ class TestThreadConsumer < ActiveSupport::TestCase
job = Job.new { raise "RuntimeError: Error!" }
@queue.push job
- @queue.drain
+ consume_queue @queue
assert_equal 1, @logger.logged(:error).size
- assert_match 'Job Error: RuntimeError: Error!', @logger.logged(:error).last
+ assert_match "Job Error: #{job.inspect}\nRuntimeError: Error!", @logger.logged(:error).last
+ end
+
+ test "logger defaults to stderr" do
+ begin
+ $stderr, old_stderr = StringIO.new, $stderr
+ queue = ActiveSupport::Queue.new
+ queue.push Job.new { raise "RuntimeError: Error!" }
+ consume_queue queue
+ assert_match 'Job Error', $stderr.string
+ ensure
+ $stderr = old_stderr
+ end
end
test "test overriding exception handling" do
@@ -85,8 +97,14 @@ class TestThreadConsumer < ActiveSupport::TestCase
job = Job.new { raise "RuntimeError: Error!" }
@queue.push job
- @queue.drain
+ consume_queue @queue
assert_equal "RuntimeError: Error!", @queue.consumer.last_error
end
+
+ private
+ def consume_queue(queue)
+ queue.push nil
+ queue.consumer.consume
+ end
end
diff --git a/guides/CHANGELOG.md b/guides/CHANGELOG.md
index a1a480e911..11fe1c5efa 100644
--- a/guides/CHANGELOG.md
+++ b/guides/CHANGELOG.md
@@ -1,5 +1,7 @@
## Rails 4.0.0 (unreleased) ##
+* New guide _Working with JavaScript in Rails_. *Steve Klabnik*
+
* Guides updated to reflect new test locations. *Mike Moore*
* Guides have a responsive design. *Joe Fiorini*
diff --git a/guides/source/4_0_release_notes.md b/guides/source/4_0_release_notes.md
index 6b3680aa2d..f24a981c6e 100644
--- a/guides/source/4_0_release_notes.md
+++ b/guides/source/4_0_release_notes.md
@@ -642,14 +642,6 @@ Active Record
* Connections *must* be closed at the end of a thread. If not, your connection pool can fill and an exception will be raised.
-* Added the `ActiveRecord::Model` module which can be included in a class as an alternative to inheriting from `ActiveRecord::Base`:
-
- ```ruby
- class Post
- include ActiveRecord::Model
- end
- ```
-
* PostgreSQL hstore records can be created.
* PostgreSQL hstore types are automatically deserialized from the database.
diff --git a/guides/source/active_support_core_extensions.md b/guides/source/active_support_core_extensions.md
index e7ed62ef47..4b2cc947b5 100644
--- a/guides/source/active_support_core_extensions.md
+++ b/guides/source/active_support_core_extensions.md
@@ -3716,7 +3716,9 @@ File.atomic_write(joined_asset_path) do |cache|
end
```
-To accomplish this `atomic_write` creates a temporary file. That's the file the code in the block actually writes to. On completion, the temporary file is renamed, which is an atomic operation on POSIX systems. If the target file exists `atomic_write` overwrites it and keeps owners and permissions.
+To accomplish this `atomic_write` creates a temporary file. That's the file the code in the block actually writes to. On completion, the temporary file is renamed, which is an atomic operation on POSIX systems. If the target file exists `atomic_write` overwrites it and keeps owners and permissions. However there are a few cases where `atomic_write` cannot change the file ownership or permissions, this error is caught and skipped over trusting in the user/filesystem to ensure the file is accessible to the processes that need it.
+
+NOTE. Due to the chmod operation `atomic_write` performs, if the target file has an ACL set on it this ACL will be recalculated/modified.
WARNING. Note you can't append with `atomic_write`.
diff --git a/guides/source/documents.yaml b/guides/source/documents.yaml
index 0b22423798..19425765b8 100644
--- a/guides/source/documents.yaml
+++ b/guides/source/documents.yaml
@@ -1,4 +1,4 @@
--
+-
name: Start Here
documents:
-
@@ -26,82 +26,87 @@
description: This guide covers the database query interface provided by Active Record.
-
name: Views
- documents:
- -
+ documents:
+ -
name: Layouts and Rendering in Rails
url: layouts_and_rendering.html
description: This guide covers the basic layout features of Action Controller and Action View, including rendering and redirecting, using content_for blocks, and working with partials.
- -
+ -
name: Action View Form Helpers
url: form_helpers.html
description: Guide to using built-in Form helpers.
-
name: Controllers
documents:
- -
+ -
name: Action Controller Overview
url: action_controller_overview.html
description: This guide covers how controllers work and how they fit into the request cycle in your application. It includes sessions, filters, and cookies, data streaming, and dealing with exceptions raised by a request, among other topics.
- -
+ -
name: Rails Routing from the Outside In
url: routing.html
description: This guide covers the user-facing features of Rails routing. If you want to understand how to use routing in your own Rails applications, start here.
-
name: Digging Deeper
documents:
- -
+ -
name: Active Support Core Extensions
url: active_support_core_extensions.html
description: This guide documents the Ruby core extensions defined in Active Support.
- -
+ -
name: Rails Internationalization API
url: i18n.html
description: This guide covers how to add internationalization to your applications. Your application will be able to translate content to different languages, change pluralization rules, use correct date formats for each country and so on.
- -
+ -
name: Action Mailer Basics
url: action_mailer_basics.html
work_in_progress: true
description: This guide describes how to use Action Mailer to send and receive emails.
- -
+ -
name: Testing Rails Applications
url: testing.html
work_in_progress: true
description: This is a rather comprehensive guide to doing both unit and functional tests in Rails. It covers everything from 'What is a test?' to the testing APIs. Enjoy.
- -
+ -
name: Securing Rails Applications
url: security.html
description: This guide describes common security problems in web applications and how to avoid them with Rails.
- -
+ -
name: Debugging Rails Applications
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.
- -
+ -
name: Rails Command Line Tools and Rake Tasks
url: command_line.html
description: This guide covers the command line tools and rake tasks provided by Rails.
- -
+ -
name: Caching with Rails
work_in_progress: true
url: caching_with_rails.html
description: Various caching techniques provided by Rails.
- -
+ -
name: Asset Pipeline
url: asset_pipeline.html
description: This guide documents the asset pipeline.
- -
+ -
+ name: Working with JavaScript in Rails
+ work_in_progress: true
+ url: working_with_javascript_in_rails.html
+ description: This guide covers the built-in Ajax/JavaScript functionality of Rails.
+ -
name: Getting Started with Engines
url: engines.html
description: This guide explains how to write a mountable engine.
work_in_progress: true
- -
+ -
name: The Rails Initialization Process
work_in_progress: true
url: initialization.html
@@ -109,38 +114,38 @@
-
name: Extending Rails
documents:
- -
+ -
name: The Basics of Creating Rails Plugins
work_in_progress: true
url: plugins.html
description: This guide covers how to build a plugin to extend the functionality of Rails.
- -
+ -
name: Rails on Rack
url: rails_on_rack.html
description: This guide covers Rails integration with Rack and interfacing with other Rack components.
- -
+ -
name: Creating and Customizing Rails Generators
url: generators.html
description: This guide covers the process of adding a brand new generator to your extension or providing an alternative to an element of a built-in Rails generator (such as providing alternative test stubs for the scaffold generator).
-
name: Contributing to Ruby on Rails
documents:
- -
+ -
name: Contributing to Ruby on Rails
url: contributing_to_ruby_on_rails.html
description: Rails is not 'somebody else's framework.' This guide covers a variety of ways that you can get involved in the ongoing development of Rails.
- -
+ -
name: API Documentation Guidelines
url: api_documentation_guidelines.html
description: This guide documents the Ruby on Rails API documentation guidelines.
- -
+ -
name: Ruby on Rails Guides Guidelines
url: ruby_on_rails_guides_guidelines.html
description: This guide documents the Ruby on Rails guides guidelines.
-
name: Release Notes
documents:
- -
+ -
name: Upgrading Ruby on Rails
url: upgrading_ruby_on_rails.html
work_in_progress: true
@@ -157,15 +162,15 @@
name: Ruby on Rails 3.1 Release Notes
url: 3_1_release_notes.html
description: Release notes for Rails 3.1.
- -
+ -
name: Ruby on Rails 3.0 Release Notes
url: 3_0_release_notes.html
description: Release notes for Rails 3.0.
- -
+ -
name: Ruby on Rails 2.3 Release Notes
url: 2_3_release_notes.html
description: Release notes for Rails 2.3.
- -
+ -
name: Ruby on Rails 2.2 Release Notes
url: 2_2_release_notes.html
description: Release notes for Rails 2.2.
diff --git a/guides/source/form_helpers.md b/guides/source/form_helpers.md
index ec1f1d4df1..f5db76f217 100644
--- a/guides/source/form_helpers.md
+++ b/guides/source/form_helpers.md
@@ -900,7 +900,7 @@ end
}
```
-The keys of the `:addresses_attributes` hash are unimportant, they need merely be different for each address.
+The keys of the `:addresses_attributes` hash are unimportant, they need merely be different for each address.
If the associated object is already saved, `fields_for` autogenerates a hidden input with the `id` of the saved record. You can disable this by passing `:include_id => false` to `fields_for`. You may wish to do this if the autogenerated input is placed in a location where an input tag is not valid HTML or when using an ORM where children do not have an id.
diff --git a/guides/source/working_with_javascript.md b/guides/source/working_with_javascript_in_rails.md
index 106744d605..011303c311 100644
--- a/guides/source/working_with_javascript.md
+++ b/guides/source/working_with_javascript_in_rails.md
@@ -1,22 +1,22 @@
-Working With JavaScript
-=======================
+Working with JavaScript in Rails
+================================
This guide covers the built-in Ajax/JavaScript functionality of Rails (and
-more); it will enable you to create rich and dynamic AJAX applications with
+more); it will enable you to create rich and dynamic Ajax applications with
ease! We will cover the following topics:
-* Quick introduction to AJAX
+* Quick introduction to Ajax
* Unobtrusive JavaScript
* How Rails' built-in helpers assist you
-* Handling AJAX on the server side
+* Handling Ajax on the server side
* The Turbolinks gem
-------------------------------------------------------------------------------
-An introduction to AJAX
+An Introduction to Ajax
------------------------
-In order to understand AJAX, you must first understand what a web browser does
+In order to understand Ajax, you must first understand what a web browser does
normally.
When you type `http://localhost:3000` into your browser's address bar and hit
@@ -30,16 +30,16 @@ JavaScript can also make requests to the server, and parse the response. It
also has the ability to update information on the page. Combining these two
powers, a JavaScript writer can make a web page that can update just parts of
itself, without needing to get the full page data from the server. This is a
-powerful technique that we call AJAX.
+powerful technique that we call Ajax.
Rails ships with CoffeeScript by default, and so the rest of the examples
in this guide will be in CoffeeScript. All of these lessons, of course, apply
to vanilla JavaScript as well.
-As an example, here's some CoffeeScript code that makes an AJAX request using
+As an example, here's some CoffeeScript code that makes an Ajax request using
the jQuery library:
-```
+```coffeescript
$.ajax(url: "/test").done (html) ->
$("#results").append html
```
@@ -63,35 +63,35 @@ demonstrate other ways.
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>
```
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?
-```
+```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>
```
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))
```
And then on our page:
-```
+```html
<a href="#" onclick="alert('fib of 15 is: ' + fib(15) + '.');">Calculate</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>
@@ -101,7 +101,7 @@ Not very DRY, eh? We can fix this by using events instead. We'll add a `data-*`
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))
@@ -133,11 +133,12 @@ Built-in Helpers
----------------------
Rails provides a bunch of view helper methods written in Ruby to assist you
-in generating HTML. Sometimes, you want to add a little AJAX to those elements,
+in generating HTML. Sometimes, you want to add a little Ajax to those elements,
and Rails has got your back in those cases.
-Because of Unobtrusive JavaScript, the Rails AJAX helpers actually consist of two
-parts: the JavaScript part and the Ruby part.
+Because of Unobtrusive JavaScript, the Rails "Ajax helpers" are actually in two
+parts: the JavaScript half and the Ruby half.
+
[rails.js](https://github.com/rails/jquery-ujs/blob/master/src/rails.js)
provides the JavaScript half, and the regular Ruby view helpers add appropriate
tags to your DOM. The CoffeeScript in rails.js then listens for these
@@ -149,7 +150,7 @@ attributes, and attaches appropriate handlers.
is a helper that assists with writing forms. `form_for` takes a `:remote`
option. It works like this:
-```
+```erb
<%= form_for(@post, remote: true) do |f| %>
...
<% end %>
@@ -157,27 +158,25 @@ option. It works like this:
This will generate the following HTML:
-```
+```html
<form accept-charset="UTF-8" action="/posts" class="new_post" data-remote="true" id="new_post" method="post">
...
</form>
```
-Note the `data-remote='true'`. Now, the form will be submitted by AJAX rather
+Note the `data-remote='true'`. Now, the form will be submitted by Ajax rather
than by the browser's normal submit mechanism.
You probably don't want to just sit there with a filled out `<form>`, though.
You probably want to do something upon a successful submission. To do that,
bind to the `ajax:success` event. On failure, use `ajax:error`. Check it out:
-```
-<script>
+```coffeescript
$(document).ready ->
$("#new_post").on("ajax:success", (e, data, status, xhr) ->
$("#new_post").append xhr.responseText
).bind "ajax:error", (e, xhr, status, error) ->
$("#new_post").append "<p>ERROR</p>"
-</script>
```
Obviously, you'll want to be a bit more sophisticated than that, but it's a
@@ -189,7 +188,7 @@ start.
is very similar to `form_for`. It has a `:remote` option that you can use like
this:
-```
+```erb
<%= form_tag('/posts', remote: true) %>
```
@@ -199,60 +198,59 @@ details.
### link_to
[`link_to`](http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to)
-is a helper that assits with generating links. It has a `:remote` option you
+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 %>
```
which generates
-```
+```html
<a href="/posts/1" data-remote="true">a post</a>
```
-You can bind to the same AJAX events as `form_for`. Here's an example. Let's
+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:
-```
+```erb
<%= link_to "Calculate", "/fib/15", remote: true, data: { fib: 15 } %>
```
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}."
```
-Easy!
-
### button_to
[`button_to`](http://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-button_to) is a helper that helps you create buttons. It has a `:remote` option that you can call like this:
-```
+```erb
<%= button_to "A post", @post, remote: true %>
```
this generates
-```
+```html
<form action="/posts/1" class="button_to" data-remote="true" method="post">
+ <div><input type="submit" value="A post"></div>
</form>
```
Since it's just a `<form>`, all of the information on `form_for` also applies.
-Server side concerns
+Server-Side Concerns
--------------------
-AJAX isn't just client-side, you also need to do some work on the server
-side to support it. Often, people like their AJAX requests to return JSON
+Ajax isn't just client-side, you also need to do some work on the server
+side to support it. Often, people like their Ajax requests to return JSON
rather than HTML. Let's discuss what it takes to make that happen.
### A Simple Example
@@ -261,7 +259,7 @@ Imagine you have a series of users that you would like to display and provide a
form on that same page to create a new user. The index action of your
controller looks like this:
-```
+```ruby
class UsersController < ApplicationController
def index
@users = User.all
@@ -272,7 +270,7 @@ class UsersController < ApplicationController
The index view (`app/views/users/index.html.erb`) contains:
-```
+```erb
<b>Users</b>
<ul id="users">
@@ -292,7 +290,7 @@ The index view (`app/views/users/index.html.erb`) contains:
The `app/views/users/_user.html.erb` partial contains the following:
-```
+```erb
<li><%= user.name %></li>
```
@@ -301,11 +299,11 @@ provides a form to create a new user.
The bottom form will call the create action on the Users controller. Because
the form's remote option is set to true, the request will be posted to the
-users controller as an AJAX request, looking for JavaScript. In order to
+users controller as an Ajax request, looking for JavaScript. In order to
service that request, the create action of your controller would look like
this:
-```
+```ruby
# app/controllers/users_controller.rb
# ......
def create
@@ -325,11 +323,11 @@ this:
```
Notice the format.js in the respond_to block; that allows the controller to
-respond to your AJAX request. You then have a corresponding
+respond to your Ajax request. You then have a corresponding
`app/views/users/create.js.erb` view file that generates the actual JavaScript
code that will be sent and executed on the client side.
-```
+```erb
$("<%= escape_javascript(render @user) %>").appendTo("#users");
```
@@ -337,14 +335,14 @@ Turbolinks
----------
Rails 4 ships with the [Turbolinks gem](https://github.com/rails/turbolinks).
-This gem uses AJAX to speed up page rendering in most applications.
+This gem uses Ajax to speed up page rendering in most applications.
-### How Turbolinks works
+### How Turbolinks Works
Turbolinks attaches a click handler to all `<a>` on the page. If your browser
supports
[PushState](https://developer.mozilla.org/en-US/docs/DOM/Manipulating_the_browser_history#The_pushState(\).C2.A0method),
-Turbolinks will make an AJAX request for the page, parse the response, and
+Turbolinks will make an Ajax request for the page, parse the response, and
replace the entire `<body>` of the page with the `<body>` of the response. It
will then use PushState to change the URL to the correct one, preserving
refresh semantics and giving you pretty URLs.
@@ -356,16 +354,16 @@ and put `//= require turbolinks` in your CoffeeScript manifest, which is usually
If you want to disable Turbolinks for certain links, add a `data-no-turbolink`
attribute to the tag:
-```
+```html
<a href="..." data-no-turbolink>No turbolinks here</a>.
```
-### Page Change events
+### Page Change Events
When writing CoffeeScript, you'll often want to do some sort of processing upon
page load. With jQuery, you'd write something like this:
-```
+```coffeescript
$(document).ready ->
alert "page has loaded!"
```
@@ -374,7 +372,7 @@ However, because Turbolinks overrides the normal page loading process, the
event that this relies on will not be fired. If you have code that looks like
this, you must change your code to do this instead:
-```
+```coffeescript
$(document).on "page:change", ->
alert "page has loaded!"
```
@@ -383,7 +381,7 @@ For more details, including other events you can bind to, check out [the
Turbolinks
README](https://github.com/rails/turbolinks/blob/ec9ca4d6cf9626e03a672f3b9e7968c816aff94e/README.md).
-Other resources
+Other Resources
---------------
Here are some helpful links to help you learn even more:
diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md
index ba9b24c6c6..cc77d08684 100644
--- a/railties/CHANGELOG.md
+++ b/railties/CHANGELOG.md
@@ -1,5 +1,9 @@
## Rails 4.0.0 (unreleased) ##
+* Ensure that RAILS_ENV is set when accessing Rails.env *Steve Klabnik*
+
+* Don't eager-load app/assets and app/views *Elia Schito*
+
* Add `.rake` to list of file extensions included by `rake notes` and `rake notes:custom`. *Brent J. Nordquist*
* New test locations `test/models`, `test/helpers`, `test/controllers`, and
diff --git a/railties/lib/rails.rb b/railties/lib/rails.rb
index dd51a6fb01..6bf2d8db20 100644
--- a/railties/lib/rails.rb
+++ b/railties/lib/rails.rb
@@ -85,7 +85,10 @@ module Rails
end
def env
- @_env ||= ActiveSupport::StringInquirer.new(ENV["RAILS_ENV"] || ENV["RACK_ENV"] || "development")
+ @_env ||= begin
+ ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
+ ActiveSupport::StringInquirer.new(ENV["RAILS_ENV"])
+ end
end
def env=(environment)
diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb
index 7df517de71..cc21213f1c 100644
--- a/railties/lib/rails/application/configuration.rb
+++ b/railties/lib/rails/application/configuration.rb
@@ -88,9 +88,10 @@ module Rails
end
def threadsafe!
- ActiveSupport::Deprecation.warn "config.threadsafe! is deprecated. Rails applications " \
- "behave by default as thread safe in production as long as config.cache_classes and " \
- "config.eager_load are set to true"
+ message = "config.threadsafe! is deprecated. Rails applications " \
+ "behave by default as thread safe in production as long as config.cache_classes and " \
+ "config.eager_load are set to true"
+ ActiveSupport::Deprecation.warn message
@cache_classes = true
@eager_load = true
self
@@ -141,8 +142,7 @@ module Rails
end
def whiny_nils=(*)
- ActiveSupport::Deprecation.warn "config.whiny_nils option " \
- "is deprecated and no longer works", caller
+ ActiveSupport::Deprecation.warn "config.whiny_nils option is deprecated and no longer works"
end
end
end
diff --git a/railties/lib/rails/application/finisher.rb b/railties/lib/rails/application/finisher.rb
index c520f7af9d..2d87b8594a 100644
--- a/railties/lib/rails/application/finisher.rb
+++ b/railties/lib/rails/application/finisher.rb
@@ -99,6 +99,7 @@ module Rails
initializer :activate_queue_consumer do |app|
if config.queue.class == ActiveSupport::Queue
app.queue_consumer = config.queue_consumer || config.queue.consumer
+ app.queue_consumer.logger ||= Rails.logger if app.queue_consumer.respond_to?(:logger=)
app.queue_consumer.start
at_exit { app.queue_consumer.shutdown }
end
diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb
index e761e26b04..de3127f43e 100644
--- a/railties/lib/rails/generators/app_base.rb
+++ b/railties/lib/rails/generators/app_base.rb
@@ -209,7 +209,7 @@ module Rails
# Gems used only for assets and not required
# in production environments by default.
group :assets do
- gem 'sprockets-rails', github: 'rails/sprockets-rails'
+ gem 'sprockets-rails', '~> 2.0.0.rc1'
gem 'sass-rails', '~> 4.0.0.beta'
gem 'coffee-rails', '~> 4.0.0.beta'
diff --git a/railties/lib/rails/generators/rails/app/templates/Gemfile b/railties/lib/rails/generators/rails/app/templates/Gemfile
index 30f8a5f75e..5b7a653a09 100644
--- a/railties/lib/rails/generators/rails/app/templates/Gemfile
+++ b/railties/lib/rails/generators/rails/app/templates/Gemfile
@@ -7,7 +7,7 @@ source 'https://rubygems.org'
<%= "gem 'jruby-openssl'\n" if defined?(JRUBY_VERSION) -%>
<%= assets_gemfile_entry %>
-<%= javascript_gemfile_entry %>
+<%= javascript_gemfile_entry -%>
# To use ActiveModel has_secure_password
# gem 'bcrypt-ruby', '~> 3.0.0'
diff --git a/railties/lib/rails/paths.rb b/railties/lib/rails/paths.rb
index 8af4130e87..cfdb15a14e 100644
--- a/railties/lib/rails/paths.rb
+++ b/railties/lib/rails/paths.rb
@@ -99,14 +99,15 @@ module Rails
protected
def filter_by(constraint)
- all = []
+ yes = []
+ no = []
+
all_paths.each do |path|
- if path.send(constraint)
- paths = path.existent
- paths -= path.children.map { |p| p.send(constraint) ? [] : p.existent }.flatten
- all.concat(paths)
- end
+ paths = path.existent + path.existent_base_paths
+ path.send(constraint) ? yes.concat(paths) : no.concat(paths)
end
+
+ all = yes - no
all.uniq!
all
end
@@ -134,6 +135,7 @@ module Rails
keys.delete(@current)
@root.values_at(*keys.sort)
end
+ deprecate :children
def first
expanded.first
@@ -210,6 +212,10 @@ module Rails
expanded.select { |d| File.directory?(d) }
end
+ def existent_base_paths
+ map { |p| File.expand_path(p, @root.path) }.select{ |f| File.exist? f }
+ end
+
alias to_a expanded
end
end
diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb
index 1311194ea6..f86877db34 100644
--- a/railties/test/application/assets_test.rb
+++ b/railties/test/application/assets_test.rb
@@ -246,7 +246,7 @@ module ApplicationTests
manifest = Dir["#{app_path}/public/assets/manifest-*.json"].first
assets = ActiveSupport::JSON.decode(File.read(manifest))
- assert asset_path = assets["assets"].find { |(k, v)| k !~ /rails.png/ && k =~ /.png/ }[1]
+ assert asset_path = assets["assets"].find { |(k, _)| k !~ /rails.png/ && k =~ /.png/ }[1]
require "#{app_path}/config/environment"
diff --git a/railties/test/application/paths_test.rb b/railties/test/application/paths_test.rb
index 4029984ce9..2265d220ab 100644
--- a/railties/test/application/paths_test.rb
+++ b/railties/test/application/paths_test.rb
@@ -59,6 +59,8 @@ module ApplicationTests
assert eager_load.include?(root("app/controllers"))
assert eager_load.include?(root("app/helpers"))
assert eager_load.include?(root("app/models"))
+ assert !eager_load.include?(root("app/views")), "expected to not be in the eager_load_path"
+ assert !eager_load.include?(root("app/assets")), "expected to not be in the eager_load_path"
end
test "environments has a glob equal to the current environment" do
@@ -73,11 +75,18 @@ module ApplicationTests
assert_in_load_path "vendor"
assert_not_in_load_path "app", "views"
+ assert_not_in_load_path "app", "assets"
assert_not_in_load_path "config"
assert_not_in_load_path "config", "locales"
assert_not_in_load_path "config", "environments"
assert_not_in_load_path "tmp"
assert_not_in_load_path "tmp", "cache"
end
+
+ test "deprecated children method" do
+ assert_deprecated "children is deprecated and will be removed from Rails 4.1." do
+ @paths["app/assets"].children
+ end
+ end
end
end
diff --git a/railties/test/application/queue_test.rb b/railties/test/application/queue_test.rb
index b0b3cf18e9..219a35da35 100644
--- a/railties/test/application/queue_test.rb
+++ b/railties/test/application/queue_test.rb
@@ -78,6 +78,7 @@ module ApplicationTests
assert_nil Rails.application.config.queue_consumer
assert_kind_of ActiveSupport::ThreadedQueueConsumer, Rails.application.queue_consumer
+ assert_equal Rails.logger, Rails.application.queue_consumer.logger
end
test "attempting to marshal a queue will raise an exception" do
diff --git a/railties/test/generators/task_generator_test.rb b/railties/test/generators/task_generator_test.rb
index f810a21d1e..9399be9510 100644
--- a/railties/test/generators/task_generator_test.rb
+++ b/railties/test/generators/task_generator_test.rb
@@ -5,7 +5,7 @@ class TaskGeneratorTest < Rails::Generators::TestCase
include GeneratorsTestHelper
arguments %w(feeds foo bar)
- def test_controller_skeleton_is_created
+ def test_task_is_created
run_generator
assert_file "lib/tasks/feeds.rake", /namespace :feeds/
end
diff --git a/tools/profile b/tools/profile
index d4cfa13f0a..665efe049d 100755
--- a/tools/profile
+++ b/tools/profile
@@ -1,12 +1,9 @@
#!/usr/bin/env ruby
# Example:
# tools/profile activesupport/lib/active_support.rb
-abort 'Use REE so you can profile memory and object allocation' unless GC.respond_to?(:enable_stats)
-
ENV['NO_RELOAD'] ||= '1'
ENV['RAILS_ENV'] ||= 'development'
-GC.enable_stats
Gem.source_index
require 'benchmark'
@@ -23,23 +20,18 @@ module RequireProfiler
def profile(file)
stats << [file, depth]
self.depth += 1
- heap_before, objects_before = GC.allocated_size, ObjectSpace.allocated_objects
result = nil
elapsed = Benchmark.realtime { result = yield }
- heap_after, objects_after = GC.allocated_size, ObjectSpace.allocated_objects
self.depth -= 1
stats.pop if stats.last.first == file
- stats << [file, depth, elapsed, heap_after - heap_before, objects_after - objects_before] if result
+ stats << [file, depth, elapsed] if result
result
end
end
end
GC.start
-before = GC.allocated_size
-before_gctime, before_gcruns = GC.time, GC.collections
before_rss = `ps -o rss= -p #{Process.pid}`.to_i
-before_live_objects = ObjectSpace.live_objects
path = ARGV.shift
if mode = ARGV.shift
@@ -53,12 +45,8 @@ end
elapsed = Benchmark.realtime { require path }
results = RubyProf.stop if mode
-after_gctime, after_gcruns = GC.time, GC.collections
GC.start
-after_live_objects = ObjectSpace.live_objects
after_rss = `ps -o rss= -p #{Process.pid}`.to_i
-after = GC.allocated_size
-usage = (after - before) / 1024.0
if mode
if printer = ARGV.shift
@@ -74,11 +62,11 @@ if mode
end
end
-RequireProfiler.stats.each do |file, depth, sec, bytes, objects|
+RequireProfiler.stats.each do |file, depth, sec|
if sec
- puts "%10.2f KB %10d obj %8.1f ms %s%s" % [bytes / 1024.0, objects, sec * 1000, ' ' * depth, file]
+ puts "%8.1f ms %s%s" % [sec * 1000, ' ' * depth, file]
else
- puts "#{' ' * (42 + depth)}#{file}"
+ puts "#{' ' * (13 + depth)}#{file}"
end
end
-puts "%10.2f KB %10d obj %8.1f ms %d KB RSS %8.1f ms GC time %d GC runs" % [usage, after_live_objects - before_live_objects, elapsed * 1000, after_rss - before_rss, (after_gctime - before_gctime) / 1000.0, after_gcruns - before_gcruns]
+puts "%8.1f ms %d KB RSS" % [elapsed * 1000, after_rss - before_rss]