diff options
133 files changed, 725 insertions, 517 deletions
diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index 3e5125f72e..c7f09ed192 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -21,7 +21,7 @@ module ActionMailer # the mailer views, options on the mail itself such as the <tt>:from</tt> address, and attachments. # # class ApplicationMailer < ActionMailer::Base - # default from: 'from@exmaple.com' + # default from: 'from@example.com' # layout 'mailer' # end # diff --git a/actionpack/CHANGELOG.md b/actionpack/CHANGELOG.md index 108ebfda58..700a446af6 100644 --- a/actionpack/CHANGELOG.md +++ b/actionpack/CHANGELOG.md @@ -1,6 +1,6 @@ * Drop request class from RouteSet constructor. - If you would like to use a custom request class, please subclass and implemet + If you would like to use a custom request class, please subclass and implement the `request_class` method. *tenderlove@ruby-lang.org* diff --git a/actionpack/lib/action_controller/metal/head.rb b/actionpack/lib/action_controller/metal/head.rb index 0d93e2f7aa..70f42bf565 100644 --- a/actionpack/lib/action_controller/metal/head.rb +++ b/actionpack/lib/action_controller/metal/head.rb @@ -38,6 +38,8 @@ module ActionController headers.delete('Content-Type') headers.delete('Content-Length') end + + true end private diff --git a/actionpack/lib/action_controller/test_case.rb b/actionpack/lib/action_controller/test_case.rb index 4782991463..33c24999f9 100644 --- a/actionpack/lib/action_controller/test_case.rb +++ b/actionpack/lib/action_controller/test_case.rb @@ -201,7 +201,7 @@ module ActionController super self.session = TestSession.new - self.session_options = TestSession::DEFAULT_OPTIONS.merge(:id => SecureRandom.hex(16)) + self.session_options = TestSession::DEFAULT_OPTIONS end def assign_parameters(routes, controller_path, action, parameters = {}) diff --git a/actionpack/lib/action_dispatch/middleware/static.rb b/actionpack/lib/action_dispatch/middleware/static.rb index 2e1bd45c3d..fdd1bc4e69 100644 --- a/actionpack/lib/action_dispatch/middleware/static.rb +++ b/actionpack/lib/action_dispatch/middleware/static.rb @@ -47,6 +47,9 @@ module ActionDispatch if gzip_path && gzip_encoding_accepted?(env) env['PATH_INFO'] = gzip_path status, headers, body = @file_server.call(env) + if status == 304 + return [status, headers, body] + end headers['Content-Encoding'] = 'gzip' headers['Content-Type'] = content_type(path) else diff --git a/actionpack/test/controller/render_test.rb b/actionpack/test/controller/render_test.rb index 488585c7a4..79e2104789 100644 --- a/actionpack/test/controller/render_test.rb +++ b/actionpack/test/controller/render_test.rb @@ -173,6 +173,11 @@ class TestController < ActionController::Base head :forbidden, :x_custom_header => "something" end + def head_and_return + head :ok and return + raise 'should not reach this line' + end + def head_with_no_content # Fill in the headers with dummy data to make # sure they get removed during the testing @@ -560,6 +565,12 @@ class HeadRenderTest < ActionController::TestCase assert_equal "something", @response.headers["X-Custom-Header"] assert_response :forbidden end + + def test_head_returns_truthy_value + assert_nothing_raised do + get :head_and_return + end + end end class HttpCacheForeverTest < ActionController::TestCase diff --git a/actionpack/test/controller/request/test_request_test.rb b/actionpack/test/controller/request/test_request_test.rb index e624f11773..77a2f68b1c 100644 --- a/actionpack/test/controller/request/test_request_test.rb +++ b/actionpack/test/controller/request/test_request_test.rb @@ -24,12 +24,4 @@ class ActionController::TestRequestTest < ActiveSupport::TestCase end end - def test_session_id_exists_by_default - assert_not_nil(@request.session_options[:id]) - end - - def test_session_id_different_on_each_call - assert_not_equal(@request.session_options[:id], ActionController::TestRequest.new.session_options[:id]) - end - end diff --git a/actionpack/test/dispatch/session/cache_store_test.rb b/actionpack/test/dispatch/session/cache_store_test.rb index 9f810cad01..22a46b0930 100644 --- a/actionpack/test/dispatch/session/cache_store_test.rb +++ b/actionpack/test/dispatch/session/cache_store_test.rb @@ -22,7 +22,7 @@ class CacheStoreTest < ActionDispatch::IntegrationTest end def get_session_id - render :text => "#{request.session_options[:id]}" + render :text => "#{request.session.id}" end def call_reset_session diff --git a/actionpack/test/dispatch/session/cookie_store_test.rb b/actionpack/test/dispatch/session/cookie_store_test.rb index 2194efa503..e7f4235de8 100644 --- a/actionpack/test/dispatch/session/cookie_store_test.rb +++ b/actionpack/test/dispatch/session/cookie_store_test.rb @@ -29,7 +29,7 @@ class CookieStoreTest < ActionDispatch::IntegrationTest end def get_session_id - render :text => "id: #{request.session_options[:id]}" + render :text => "id: #{request.session.id}" end def get_class_after_reset_session @@ -53,7 +53,7 @@ class CookieStoreTest < ActionDispatch::IntegrationTest end def change_session_id - request.session_options[:id] = nil + request.session.options[:id] = nil get_session_id end diff --git a/actionpack/test/dispatch/session/mem_cache_store_test.rb b/actionpack/test/dispatch/session/mem_cache_store_test.rb index fbd82945cc..9a5d5131c0 100644 --- a/actionpack/test/dispatch/session/mem_cache_store_test.rb +++ b/actionpack/test/dispatch/session/mem_cache_store_test.rb @@ -23,7 +23,7 @@ class MemCacheStoreTest < ActionDispatch::IntegrationTest end def get_session_id - render :text => "#{request.session_options[:id]}" + render :text => "#{request.session.id}" end def call_reset_session diff --git a/actionpack/test/dispatch/static_test.rb b/actionpack/test/dispatch/static_test.rb index ebc9d71403..288a2084f6 100644 --- a/actionpack/test/dispatch/static_test.rb +++ b/actionpack/test/dispatch/static_test.rb @@ -143,6 +143,16 @@ module StaticTests assert_equal default_response.headers['Content-Type'], response.headers['Content-Type'] end + def test_serves_gzip_files_with_not_modified + file_name = "/gzip/application-a71b3024f80aea3181c09774ca17e712.js" + last_modified = File.mtime(File.join(@root, "#{file_name}.gz")) + response = get(file_name, 'HTTP_ACCEPT_ENCODING' => 'gzip', 'HTTP_IF_MODIFIED_SINCE' => last_modified.httpdate) + assert_equal 304, response.status + assert_equal nil, response.headers['Content-Type'] + assert_equal nil, response.headers['Content-Encoding'] + assert_equal nil, response.headers['Vary'] + end + # Windows doesn't allow \ / : * ? " < > | in filenames unless RbConfig::CONFIG['host_os'] =~ /mswin|mingw/ def test_serves_static_file_with_colon diff --git a/actionview/lib/action_view/helpers/form_options_helper.rb b/actionview/lib/action_view/helpers/form_options_helper.rb index bbfbf482a4..8a5928477f 100644 --- a/actionview/lib/action_view/helpers/form_options_helper.rb +++ b/actionview/lib/action_view/helpers/form_options_helper.rb @@ -18,10 +18,10 @@ module ActionView # # could become: # - # <select name="post[category]"> - # <option></option> - # <option>joke</option> - # <option>poem</option> + # <select name="post[category]" id="post_category"> + # <option value=""></option> + # <option value="joke">joke</option> + # <option value="poem">poem</option> # </select> # # Another common case is a select tag for a <tt>belongs_to</tt>-associated object. @@ -32,7 +32,7 @@ module ActionView # # could become: # - # <select name="post[person_id]"> + # <select name="post[person_id]" id="post_person_id"> # <option value="">None</option> # <option value="1">David</option> # <option value="2" selected="selected">Sam</option> @@ -45,7 +45,7 @@ module ActionView # # could become: # - # <select name="post[person_id]"> + # <select name="post[person_id]" id="post_person_id"> # <option value="">Select Person</option> # <option value="1">David</option> # <option value="2">Sam</option> @@ -71,11 +71,11 @@ module ActionView # # could become: # - # <select name="post[category]"> - # <option></option> - # <option>joke</option> - # <option>poem</option> - # <option disabled="disabled">restricted</option> + # <select name="post[category]" id="post_category"> + # <option value=""></option> + # <option value="joke">joke</option> + # <option value="poem">poem</option> + # <option disabled="disabled" value="restricted">restricted</option> # </select> # # When used with the <tt>collection_select</tt> helper, <tt>:disabled</tt> can also be a Proc that identifies those options that should be disabled. @@ -83,7 +83,7 @@ module ActionView # collection_select(:post, :category_id, Category.all, :id, :name, {disabled: lambda{|category| category.archived? }}) # # If the categories "2008 stuff" and "Christmas" return true when the method <tt>archived?</tt> is called, this would return: - # <select name="post[category_id]"> + # <select name="post[category_id]" id="post_category_id"> # <option value="1" disabled="disabled">2008 stuff</option> # <option value="2" disabled="disabled">Christmas</option> # <option value="3">Jokes</option> @@ -109,7 +109,7 @@ module ActionView # # would become: # - # <select name="post[person_id]"> + # <select name="post[person_id]" id="post_person_id"> # <option value=""></option> # <option value="1" selected="selected">David</option> # <option value="2">Sam</option> @@ -192,7 +192,7 @@ module ActionView # collection_select(:post, :author_id, Author.all, :id, :name_with_initial, prompt: true) # # If <tt>@post.author_id</tt> is already <tt>1</tt>, this would return: - # <select name="post[author_id]"> + # <select name="post[author_id]" id="post_author_id"> # <option value="">Please select</option> # <option value="1" selected="selected">D. Heinemeier Hansson</option> # <option value="2">D. Thomas</option> @@ -243,7 +243,7 @@ module ActionView # # Possible output: # - # <select name="city[country_id]"> + # <select name="city[country_id]" id="city_country_id"> # <optgroup label="Africa"> # <option value="1">South Africa</option> # <option value="3">Somalia</option> @@ -302,17 +302,17 @@ module ActionView # # => <option value="DKK">Kroner</option> # # options_for_select([ "VISA", "MasterCard" ], "MasterCard") - # # => <option>VISA</option> - # # => <option selected="selected">MasterCard</option> + # # => <option value="VISA">VISA</option> + # # => <option selected="selected" value="MasterCard">MasterCard</option> # # options_for_select({ "Basic" => "$20", "Plus" => "$40" }, "$40") # # => <option value="$20">Basic</option> # # => <option value="$40" selected="selected">Plus</option> # # options_for_select([ "VISA", "MasterCard", "Discover" ], ["VISA", "Discover"]) - # # => <option selected="selected">VISA</option> - # # => <option>MasterCard</option> - # # => <option selected="selected">Discover</option> + # # => <option selected="selected" value="VISA">VISA</option> + # # => <option value="MasterCard">MasterCard</option> + # # => <option selected="selected" value="Discover">Discover</option> # # You can optionally provide HTML attributes as the last element of the array. # diff --git a/actionview/test/abstract_unit.rb b/actionview/test/abstract_unit.rb index 3eded74f1b..4635c645d0 100644 --- a/actionview/test/abstract_unit.rb +++ b/actionview/test/abstract_unit.rb @@ -49,20 +49,6 @@ I18n.backend.store_translations 'pt-BR', {} ORIGINAL_LOCALES = I18n.available_locales.map(&:to_s).sort FIXTURE_LOAD_PATH = File.join(File.dirname(__FILE__), 'fixtures') -FIXTURES = Pathname.new(FIXTURE_LOAD_PATH) - -module RackTestUtils - def body_to_string(body) - if body.respond_to?(:each) - str = "" - body.each {|s| str << s } - str - else - body - end - end - extend self -end module RenderERBUtils def view @@ -225,49 +211,6 @@ class ActionDispatch::IntegrationTest < ActiveSupport::TestCase end end -# Temporary base class -class Rack::TestCase < ActionDispatch::IntegrationTest - def self.testing(klass = nil) - if klass - @testing = "/#{klass.name.underscore}".sub!(/_controller$/, '') - else - @testing - end - end - - def get(thing, *args) - if thing.is_a?(Symbol) - super("#{self.class.testing}/#{thing}", *args) - else - super - end - end - - def assert_body(body) - assert_equal body, Array(response.body).join - end - - def assert_status(code) - assert_equal code, response.status - end - - def assert_response(body, status = 200, headers = {}) - assert_body body - assert_status status - headers.each do |header, value| - assert_header header, value - end - end - - def assert_content_type(type) - assert_equal type, response.headers["Content-Type"] - end - - def assert_header(name, value) - assert_equal value, response.headers[name] - end -end - ActionView::RoutingUrlFor.include(ActionDispatch::Routing::UrlFor) module ActionController diff --git a/actionview/test/actionpack/abstract/views/abstract_controller/testing/me5/index.erb b/actionview/test/actionpack/abstract/views/abstract_controller/testing/me5/index.erb deleted file mode 100644 index 84d0b7417e..0000000000 --- a/actionview/test/actionpack/abstract/views/abstract_controller/testing/me5/index.erb +++ /dev/null @@ -1 +0,0 @@ -Hello from me5/index.erb
\ No newline at end of file diff --git a/actionview/test/active_record_unit.rb b/actionview/test/active_record_unit.rb index cca55c9af4..f9e94413b5 100644 --- a/actionview/test/active_record_unit.rb +++ b/actionview/test/active_record_unit.rb @@ -76,7 +76,7 @@ class ActiveRecordTestCase < ActionController::TestCase # Set our fixture path if ActiveRecordTestConnector.able_to_connect self.fixture_path = [FIXTURE_LOAD_PATH] - self.use_transactional_fixtures = false + self.use_transactional_tests = false end def self.fixtures(*args) diff --git a/actionview/test/fixtures/multipart/bracketed_utf8_param b/actionview/test/fixtures/multipart/bracketed_utf8_param deleted file mode 100644 index df9cecea08..0000000000 --- a/actionview/test/fixtures/multipart/bracketed_utf8_param +++ /dev/null @@ -1,5 +0,0 @@ ---AaB03x -Content-Disposition: form-data; name="Iñtërnâtiônà lizætiøn_name[Iñtërnâtiônà lizætiøn_nested_name]" - -Iñtërnâtiônà lizætiøn_value ---AaB03x-- diff --git a/actionview/test/fixtures/multipart/single_utf8_param b/actionview/test/fixtures/multipart/single_utf8_param deleted file mode 100644 index 1d9fae7b17..0000000000 --- a/actionview/test/fixtures/multipart/single_utf8_param +++ /dev/null @@ -1,5 +0,0 @@ ---AaB03x -Content-Disposition: form-data; name="Iñtërnâtiônà lizætiøn_name" - -Iñtërnâtiônà lizætiøn_value ---AaB03x-- diff --git a/actionview/test/template/asset_tag_helper_test.rb b/actionview/test/template/asset_tag_helper_test.rb index a15c6fac90..02dce71496 100644 --- a/actionview/test/template/asset_tag_helper_test.rb +++ b/actionview/test/template/asset_tag_helper_test.rb @@ -1,4 +1,3 @@ -require 'zlib' require 'abstract_unit' require 'active_support/ordered_options' diff --git a/actionview/test/template/javascript_helper_test.rb b/actionview/test/template/javascript_helper_test.rb index 9ba7f64ad1..9f1535ef53 100644 --- a/actionview/test/template/javascript_helper_test.rb +++ b/actionview/test/template/javascript_helper_test.rb @@ -3,14 +3,7 @@ require 'abstract_unit' class JavaScriptHelperTest < ActionView::TestCase tests ActionView::Helpers::JavaScriptHelper - def _evaluate_assigns_and_ivars() end - - attr_accessor :formats, :output_buffer - - def update_details(details) - @details = details - yield if block_given? - end + attr_accessor :output_buffer setup do @old_escape_html_entities_in_json = ActiveSupport.escape_html_entities_in_json diff --git a/activejob/lib/active_job/logging.rb b/activejob/lib/active_job/logging.rb index cd29e6908e..54774db601 100644 --- a/activejob/lib/active_job/logging.rb +++ b/activejob/lib/active_job/logging.rb @@ -81,7 +81,7 @@ module ActiveJob private def queue_name(event) - event.payload[:adapter].name.demodulize.remove('Adapter') + "(#{event.payload[:job].queue_name})" + event.payload[:adapter].class.name.demodulize.remove('Adapter') + "(#{event.payload[:job].queue_name})" end def args_info(job) diff --git a/activejob/lib/active_job/queue_adapter.rb b/activejob/lib/active_job/queue_adapter.rb index aa3ebdbc7b..9c4519432d 100644 --- a/activejob/lib/active_job/queue_adapter.rb +++ b/activejob/lib/active_job/queue_adapter.rb @@ -1,4 +1,5 @@ require 'active_job/queue_adapters/inline_adapter' +require 'active_support/core_ext/class/attribute' require 'active_support/core_ext/string/inflections' module ActiveJob @@ -7,27 +8,54 @@ module ActiveJob module QueueAdapter #:nodoc: extend ActiveSupport::Concern + included do + class_attribute :_queue_adapter, instance_accessor: false, instance_predicate: false + self.queue_adapter = :inline + end + # Includes the setter method for changing the active queue adapter. module ClassMethods - mattr_reader(:queue_adapter) { ActiveJob::QueueAdapters::InlineAdapter } + def queue_adapter + _queue_adapter + end # Specify the backend queue provider. The default queue adapter # is the :inline queue. See QueueAdapters for more # information. - def queue_adapter=(name_or_adapter) - @@queue_adapter = \ - case name_or_adapter - when Symbol, String - load_adapter(name_or_adapter) - else - name_or_adapter if name_or_adapter.respond_to?(:enqueue) - end + def queue_adapter=(name_or_adapter_or_class) + self._queue_adapter = interpret_adapter(name_or_adapter_or_class) end private - def load_adapter(name) - "ActiveJob::QueueAdapters::#{name.to_s.camelize}Adapter".constantize + + def interpret_adapter(name_or_adapter_or_class) + case name_or_adapter_or_class + when Symbol, String + ActiveJob::QueueAdapters.lookup(name_or_adapter_or_class).new + else + if queue_adapter?(name_or_adapter_or_class) + name_or_adapter_or_class + elsif queue_adapter_class?(name_or_adapter_or_class) + ActiveSupport::Deprecation.warn "Passing an adapter class is deprecated " \ + "and will be removed in Rails 5.1. Please pass an adapter name " \ + "(.queue_adapter = :#{name_or_adapter_or_class.name.demodulize.remove('Adapter').underscore}) " \ + "or an instance (.queue_adapter = #{name_or_adapter_or_class.name}.new) instead." + name_or_adapter_or_class.new + else + raise ArgumentError + end end + end + + QUEUE_ADAPTER_METHODS = [:enqueue, :enqueue_at].freeze + + def queue_adapter?(object) + QUEUE_ADAPTER_METHODS.all? { |meth| object.respond_to?(meth) } + end + + def queue_adapter_class?(object) + object.is_a?(Class) && QUEUE_ADAPTER_METHODS.all? { |meth| object.public_method_defined?(meth) } + end end end end diff --git a/activejob/lib/active_job/queue_adapters.rb b/activejob/lib/active_job/queue_adapters.rb index 4b91c93dbe..b3d91dc562 100644 --- a/activejob/lib/active_job/queue_adapters.rb +++ b/activejob/lib/active_job/queue_adapters.rb @@ -48,5 +48,14 @@ module ActiveJob autoload :SneakersAdapter autoload :SuckerPunchAdapter autoload :TestAdapter + + ADAPTER = 'Adapter'.freeze + private_constant :ADAPTER + + class << self + def lookup(name) + const_get(name.to_s.camelize << ADAPTER) + end + end end end diff --git a/activejob/lib/active_job/queue_adapters/backburner_adapter.rb b/activejob/lib/active_job/queue_adapters/backburner_adapter.rb index 2453d065de..17703e3e41 100644 --- a/activejob/lib/active_job/queue_adapters/backburner_adapter.rb +++ b/activejob/lib/active_job/queue_adapters/backburner_adapter.rb @@ -13,15 +13,13 @@ module ActiveJob # # Rails.application.config.active_job.queue_adapter = :backburner class BackburnerAdapter - class << self - def enqueue(job) #:nodoc: - Backburner::Worker.enqueue JobWrapper, [ job.serialize ], queue: job.queue_name - end + def enqueue(job) #:nodoc: + Backburner::Worker.enqueue JobWrapper, [ job.serialize ], queue: job.queue_name + end - def enqueue_at(job, timestamp) #:nodoc: - delay = timestamp - Time.current.to_f - Backburner::Worker.enqueue JobWrapper, [ job.serialize ], queue: job.queue_name, delay: delay - end + def enqueue_at(job, timestamp) #:nodoc: + delay = timestamp - Time.current.to_f + Backburner::Worker.enqueue JobWrapper, [ job.serialize ], queue: job.queue_name, delay: delay end class JobWrapper #:nodoc: diff --git a/activejob/lib/active_job/queue_adapters/delayed_job_adapter.rb b/activejob/lib/active_job/queue_adapters/delayed_job_adapter.rb index 69d9e70de3..852a6ee326 100644 --- a/activejob/lib/active_job/queue_adapters/delayed_job_adapter.rb +++ b/activejob/lib/active_job/queue_adapters/delayed_job_adapter.rb @@ -13,14 +13,12 @@ module ActiveJob # # Rails.application.config.active_job.queue_adapter = :delayed_job class DelayedJobAdapter - class << self - def enqueue(job) #:nodoc: - Delayed::Job.enqueue(JobWrapper.new(job.serialize), queue: job.queue_name) - end + def enqueue(job) #:nodoc: + Delayed::Job.enqueue(JobWrapper.new(job.serialize), queue: job.queue_name) + end - def enqueue_at(job, timestamp) #:nodoc: - Delayed::Job.enqueue(JobWrapper.new(job.serialize), queue: job.queue_name, run_at: Time.at(timestamp)) - end + def enqueue_at(job, timestamp) #:nodoc: + Delayed::Job.enqueue(JobWrapper.new(job.serialize), queue: job.queue_name, run_at: Time.at(timestamp)) end class JobWrapper #:nodoc: diff --git a/activejob/lib/active_job/queue_adapters/inline_adapter.rb b/activejob/lib/active_job/queue_adapters/inline_adapter.rb index e25d88e723..1d06324c18 100644 --- a/activejob/lib/active_job/queue_adapters/inline_adapter.rb +++ b/activejob/lib/active_job/queue_adapters/inline_adapter.rb @@ -9,14 +9,12 @@ module ActiveJob # # Rails.application.config.active_job.queue_adapter = :inline class InlineAdapter - class << self - def enqueue(job) #:nodoc: - Base.execute(job.serialize) - end + def enqueue(job) #:nodoc: + Base.execute(job.serialize) + end - def enqueue_at(*) #:nodoc: - raise NotImplementedError.new("Use a queueing backend to enqueue jobs in the future. Read more at http://guides.rubyonrails.org/active_job_basics.html") - end + def enqueue_at(*) #:nodoc: + raise NotImplementedError.new("Use a queueing backend to enqueue jobs in the future. Read more at http://guides.rubyonrails.org/active_job_basics.html") end end end diff --git a/activejob/lib/active_job/queue_adapters/qu_adapter.rb b/activejob/lib/active_job/queue_adapters/qu_adapter.rb index 30aa5a4670..94584ef9d8 100644 --- a/activejob/lib/active_job/queue_adapters/qu_adapter.rb +++ b/activejob/lib/active_job/queue_adapters/qu_adapter.rb @@ -16,16 +16,14 @@ module ActiveJob # # Rails.application.config.active_job.queue_adapter = :qu class QuAdapter - class << self - def enqueue(job, *args) #:nodoc: - Qu::Payload.new(klass: JobWrapper, args: [job.serialize]).tap do |payload| - payload.instance_variable_set(:@queue, job.queue_name) - end.push - end + def enqueue(job, *args) #:nodoc: + Qu::Payload.new(klass: JobWrapper, args: [job.serialize]).tap do |payload| + payload.instance_variable_set(:@queue, job.queue_name) + end.push + end - def enqueue_at(job, timestamp, *args) #:nodoc: - raise NotImplementedError - end + def enqueue_at(job, timestamp, *args) #:nodoc: + raise NotImplementedError end class JobWrapper < Qu::Job #:nodoc: diff --git a/activejob/lib/active_job/queue_adapters/que_adapter.rb b/activejob/lib/active_job/queue_adapters/que_adapter.rb index e501fe0368..84cc2845b0 100644 --- a/activejob/lib/active_job/queue_adapters/que_adapter.rb +++ b/activejob/lib/active_job/queue_adapters/que_adapter.rb @@ -15,14 +15,12 @@ module ActiveJob # # Rails.application.config.active_job.queue_adapter = :que class QueAdapter - class << self - def enqueue(job) #:nodoc: - JobWrapper.enqueue job.serialize, queue: job.queue_name - end + def enqueue(job) #:nodoc: + JobWrapper.enqueue job.serialize, queue: job.queue_name + end - def enqueue_at(job, timestamp) #:nodoc: - JobWrapper.enqueue job.serialize, queue: job.queue_name, run_at: Time.at(timestamp) - end + def enqueue_at(job, timestamp) #:nodoc: + JobWrapper.enqueue job.serialize, queue: job.queue_name, run_at: Time.at(timestamp) end class JobWrapper < Que::Job #:nodoc: diff --git a/activejob/lib/active_job/queue_adapters/queue_classic_adapter.rb b/activejob/lib/active_job/queue_adapters/queue_classic_adapter.rb index 34c11a68b2..059754a87f 100644 --- a/activejob/lib/active_job/queue_adapters/queue_classic_adapter.rb +++ b/activejob/lib/active_job/queue_adapters/queue_classic_adapter.rb @@ -17,29 +17,27 @@ module ActiveJob # # Rails.application.config.active_job.queue_adapter = :queue_classic class QueueClassicAdapter - class << self - def enqueue(job) #:nodoc: - build_queue(job.queue_name).enqueue("#{JobWrapper.name}.perform", job.serialize) - end + def enqueue(job) #:nodoc: + build_queue(job.queue_name).enqueue("#{JobWrapper.name}.perform", job.serialize) + end - def enqueue_at(job, timestamp) #:nodoc: - queue = build_queue(job.queue_name) - unless queue.respond_to?(:enqueue_at) - raise NotImplementedError, 'To be able to schedule jobs with queue_classic ' \ - 'the QC::Queue needs to respond to `enqueue_at(timestamp, method, *args)`. ' \ - 'You can implement this yourself or you can use the queue_classic-later gem.' - end - queue.enqueue_at(timestamp, "#{JobWrapper.name}.perform", job.serialize) + def enqueue_at(job, timestamp) #:nodoc: + queue = build_queue(job.queue_name) + unless queue.respond_to?(:enqueue_at) + raise NotImplementedError, 'To be able to schedule jobs with queue_classic ' \ + 'the QC::Queue needs to respond to `enqueue_at(timestamp, method, *args)`. ' \ + 'You can implement this yourself or you can use the queue_classic-later gem.' end + queue.enqueue_at(timestamp, "#{JobWrapper.name}.perform", job.serialize) + end - # Builds a <tt>QC::Queue</tt> object to schedule jobs on. - # - # If you have a custom <tt>QC::Queue</tt> subclass you'll need to subclass - # <tt>ActiveJob::QueueAdapters::QueueClassicAdapter</tt> and override the - # <tt>build_queue</tt> method. - def build_queue(queue_name) - QC::Queue.new(queue_name) - end + # Builds a <tt>QC::Queue</tt> object to schedule jobs on. + # + # If you have a custom <tt>QC::Queue</tt> subclass you'll need to subclass + # <tt>ActiveJob::QueueAdapters::QueueClassicAdapter</tt> and override the + # <tt>build_queue</tt> method. + def build_queue(queue_name) + QC::Queue.new(queue_name) end class JobWrapper #:nodoc: diff --git a/activejob/lib/active_job/queue_adapters/resque_adapter.rb b/activejob/lib/active_job/queue_adapters/resque_adapter.rb index 88c6b48fef..417854afd8 100644 --- a/activejob/lib/active_job/queue_adapters/resque_adapter.rb +++ b/activejob/lib/active_job/queue_adapters/resque_adapter.rb @@ -26,18 +26,16 @@ module ActiveJob # # Rails.application.config.active_job.queue_adapter = :resque class ResqueAdapter - class << self - def enqueue(job) #:nodoc: - Resque.enqueue_to job.queue_name, JobWrapper, job.serialize - end + def enqueue(job) #:nodoc: + Resque.enqueue_to job.queue_name, JobWrapper, job.serialize + end - def enqueue_at(job, timestamp) #:nodoc: - unless Resque.respond_to?(:enqueue_at_with_queue) - raise NotImplementedError, "To be able to schedule jobs with Resque you need the " \ - "resque-scheduler gem. Please add it to your Gemfile and run bundle install" - end - Resque.enqueue_at_with_queue job.queue_name, timestamp, JobWrapper, job.serialize + def enqueue_at(job, timestamp) #:nodoc: + unless Resque.respond_to?(:enqueue_at_with_queue) + raise NotImplementedError, "To be able to schedule jobs with Resque you need the " \ + "resque-scheduler gem. Please add it to your Gemfile and run bundle install" end + Resque.enqueue_at_with_queue job.queue_name, timestamp, JobWrapper, job.serialize end class JobWrapper #:nodoc: diff --git a/activejob/lib/active_job/queue_adapters/sidekiq_adapter.rb b/activejob/lib/active_job/queue_adapters/sidekiq_adapter.rb index 21005fc728..e02593ec9c 100644 --- a/activejob/lib/active_job/queue_adapters/sidekiq_adapter.rb +++ b/activejob/lib/active_job/queue_adapters/sidekiq_adapter.rb @@ -15,22 +15,20 @@ module ActiveJob # # Rails.application.config.active_job.queue_adapter = :sidekiq class SidekiqAdapter - class << self - def enqueue(job) #:nodoc: - #Sidekiq::Client does not support symbols as keys - Sidekiq::Client.push \ - 'class' => JobWrapper, - 'queue' => job.queue_name, - 'args' => [ job.serialize ] - end + def enqueue(job) #:nodoc: + #Sidekiq::Client does not support symbols as keys + Sidekiq::Client.push \ + 'class' => JobWrapper, + 'queue' => job.queue_name, + 'args' => [ job.serialize ] + end - def enqueue_at(job, timestamp) #:nodoc: - Sidekiq::Client.push \ - 'class' => JobWrapper, - 'queue' => job.queue_name, - 'args' => [ job.serialize ], - 'at' => timestamp - end + def enqueue_at(job, timestamp) #:nodoc: + Sidekiq::Client.push \ + 'class' => JobWrapper, + 'queue' => job.queue_name, + 'args' => [ job.serialize ], + 'at' => timestamp end class JobWrapper #:nodoc: diff --git a/activejob/lib/active_job/queue_adapters/sneakers_adapter.rb b/activejob/lib/active_job/queue_adapters/sneakers_adapter.rb index 6d60a2f303..f5737487ca 100644 --- a/activejob/lib/active_job/queue_adapters/sneakers_adapter.rb +++ b/activejob/lib/active_job/queue_adapters/sneakers_adapter.rb @@ -16,19 +16,19 @@ module ActiveJob # # Rails.application.config.active_job.queue_adapter = :sneakers class SneakersAdapter - @monitor = Monitor.new + def initialize + @monitor = Monitor.new + end - class << self - def enqueue(job) #:nodoc: - @monitor.synchronize do - JobWrapper.from_queue job.queue_name - JobWrapper.enqueue ActiveSupport::JSON.encode(job.serialize) - end + def enqueue(job) #:nodoc: + @monitor.synchronize do + JobWrapper.from_queue job.queue_name + JobWrapper.enqueue ActiveSupport::JSON.encode(job.serialize) end + end - def enqueue_at(job, timestamp) #:nodoc: - raise NotImplementedError - end + def enqueue_at(job, timestamp) #:nodoc: + raise NotImplementedError end class JobWrapper #:nodoc: diff --git a/activejob/lib/active_job/queue_adapters/sucker_punch_adapter.rb b/activejob/lib/active_job/queue_adapters/sucker_punch_adapter.rb index be9e7fd03a..64c93e8198 100644 --- a/activejob/lib/active_job/queue_adapters/sucker_punch_adapter.rb +++ b/activejob/lib/active_job/queue_adapters/sucker_punch_adapter.rb @@ -18,14 +18,12 @@ module ActiveJob # # Rails.application.config.active_job.queue_adapter = :sucker_punch class SuckerPunchAdapter - class << self - def enqueue(job) #:nodoc: - JobWrapper.new.async.perform job.serialize - end + def enqueue(job) #:nodoc: + JobWrapper.new.async.perform job.serialize + end - def enqueue_at(job, timestamp) #:nodoc: - raise NotImplementedError - end + def enqueue_at(job, timestamp) #:nodoc: + raise NotImplementedError end class JobWrapper #:nodoc: diff --git a/activejob/lib/active_job/queue_adapters/test_adapter.rb b/activejob/lib/active_job/queue_adapters/test_adapter.rb index fd7c0b207a..9b7b7139f4 100644 --- a/activejob/lib/active_job/queue_adapters/test_adapter.rb +++ b/activejob/lib/active_job/queue_adapters/test_adapter.rb @@ -10,52 +10,50 @@ module ActiveJob # # Rails.application.config.active_job.queue_adapter = :test class TestAdapter - class << self - attr_accessor(:perform_enqueued_jobs, :perform_enqueued_at_jobs, :filter) - attr_writer(:enqueued_jobs, :performed_jobs) + attr_accessor(:perform_enqueued_jobs, :perform_enqueued_at_jobs, :filter) + attr_writer(:enqueued_jobs, :performed_jobs) - # Provides a store of all the enqueued jobs with the TestAdapter so you can check them. - def enqueued_jobs - @enqueued_jobs ||= [] - end + # Provides a store of all the enqueued jobs with the TestAdapter so you can check them. + def enqueued_jobs + @enqueued_jobs ||= [] + end - # Provides a store of all the performed jobs with the TestAdapter so you can check them. - def performed_jobs - @performed_jobs ||= [] - end + # Provides a store of all the performed jobs with the TestAdapter so you can check them. + def performed_jobs + @performed_jobs ||= [] + end - def enqueue(job) #:nodoc: - return if filtered?(job) + def enqueue(job) #:nodoc: + return if filtered?(job) - job_data = job_to_hash(job) - enqueue_or_perform(perform_enqueued_jobs, job, job_data) - end + job_data = job_to_hash(job) + enqueue_or_perform(perform_enqueued_jobs, job, job_data) + end - def enqueue_at(job, timestamp) #:nodoc: - return if filtered?(job) + def enqueue_at(job, timestamp) #:nodoc: + return if filtered?(job) - job_data = job_to_hash(job, at: timestamp) - enqueue_or_perform(perform_enqueued_at_jobs, job, job_data) - end + job_data = job_to_hash(job, at: timestamp) + enqueue_or_perform(perform_enqueued_at_jobs, job, job_data) + end - private + private - def job_to_hash(job, extras = {}) - { job: job.class, args: job.serialize.fetch('arguments'), queue: job.queue_name }.merge!(extras) - end + def job_to_hash(job, extras = {}) + { job: job.class, args: job.serialize.fetch('arguments'), queue: job.queue_name }.merge!(extras) + end - def enqueue_or_perform(perform, job, job_data) - if perform - performed_jobs << job_data - Base.execute job.serialize - else - enqueued_jobs << job_data - end + def enqueue_or_perform(perform, job, job_data) + if perform + performed_jobs << job_data + Base.execute job.serialize + else + enqueued_jobs << job_data end + end - def filtered?(job) - filter && !Array(filter).include?(job.class) - end + def filtered?(job) + filter && !Array(filter).include?(job.class) end end end diff --git a/activejob/lib/active_job/test_helper.rb b/activejob/lib/active_job/test_helper.rb index bb8b267c31..4efb4b72d2 100644 --- a/activejob/lib/active_job/test_helper.rb +++ b/activejob/lib/active_job/test_helper.rb @@ -1,3 +1,4 @@ +require 'active_support/core_ext/class/subclasses' require 'active_support/core_ext/hash/keys' module ActiveJob @@ -7,19 +8,27 @@ module ActiveJob included do def before_setup - @old_queue_adapter = queue_adapter - ActiveJob::Base.queue_adapter = :test + test_adapter = ActiveJob::QueueAdapters::TestAdapter.new + + @old_queue_adapters = (ActiveJob::Base.subclasses << ActiveJob::Base).select do |klass| + # only override explicitly set adapters, a quirk of `class_attribute` + klass.singleton_class.public_instance_methods(false).include?(:_queue_adapter) + end.map do |klass| + [klass, klass.queue_adapter].tap do + klass.queue_adapter = test_adapter + end + end + clear_enqueued_jobs clear_performed_jobs - queue_adapter.perform_enqueued_jobs = false - queue_adapter.perform_enqueued_at_jobs = false - queue_adapter.filter = nil super end def after_teardown super - ActiveJob::Base.queue_adapter = @old_queue_adapter + @old_queue_adapters.each do |(klass, adapter)| + klass.queue_adapter = adapter + end end # Asserts that the number of enqueued jobs matches the given number. diff --git a/activejob/test/cases/adapter_test.rb b/activejob/test/cases/adapter_test.rb index f0c710f9ed..6d75ae9a7c 100644 --- a/activejob/test/cases/adapter_test.rb +++ b/activejob/test/cases/adapter_test.rb @@ -2,6 +2,6 @@ require 'helper' class AdapterTest < ActiveSupport::TestCase test "should load #{ENV['AJ_ADAPTER']} adapter" do - assert_equal "active_job/queue_adapters/#{ENV['AJ_ADAPTER']}_adapter".classify, ActiveJob::Base.queue_adapter.name + assert_equal "active_job/queue_adapters/#{ENV['AJ_ADAPTER']}_adapter".classify, ActiveJob::Base.queue_adapter.class.name end end diff --git a/activejob/test/cases/logging_test.rb b/activejob/test/cases/logging_test.rb index 64aae00441..b18be553ec 100644 --- a/activejob/test/cases/logging_test.rb +++ b/activejob/test/cases/logging_test.rb @@ -6,7 +6,7 @@ require 'jobs/logging_job' require 'jobs/nested_job' require 'models/person' -class AdapterTest < ActiveSupport::TestCase +class LoggingTest < ActiveSupport::TestCase include ActiveSupport::LogSubscriber::TestHelper include ActiveSupport::Logger::Severity diff --git a/activejob/test/cases/queue_adapter_test.rb b/activejob/test/cases/queue_adapter_test.rb new file mode 100644 index 0000000000..fb3fdc392f --- /dev/null +++ b/activejob/test/cases/queue_adapter_test.rb @@ -0,0 +1,56 @@ +require 'helper' + +module ActiveJob + module QueueAdapters + class StubOneAdapter + def enqueue(*); end + def enqueue_at(*); end + end + + class StubTwoAdapter + def enqueue(*); end + def enqueue_at(*); end + end + end +end + +class QueueAdapterTest < ActiveJob::TestCase + test 'should forbid nonsense arguments' do + assert_raises(ArgumentError) { ActiveJob::Base.queue_adapter = Mutex } + assert_raises(ArgumentError) { ActiveJob::Base.queue_adapter = Mutex.new } + end + + test 'should warn on passing an adapter class' do + klass = Class.new do + def self.name + 'fake' + end + + def enqueue(*); end + def enqueue_at(*); end + end + + assert_deprecated { ActiveJob::Base.queue_adapter = klass } + end + + test 'should allow overriding the queue_adapter at the child class level without affecting the parent or its sibling' do + base_queue_adapter = ActiveJob::Base.queue_adapter + + child_job_one = Class.new(ActiveJob::Base) + child_job_one.queue_adapter = :stub_one + + assert_not_equal ActiveJob::Base.queue_adapter, child_job_one.queue_adapter + assert_kind_of ActiveJob::QueueAdapters::StubOneAdapter, child_job_one.queue_adapter + + child_job_two = Class.new(ActiveJob::Base) + child_job_two.queue_adapter = :stub_two + + assert_kind_of ActiveJob::QueueAdapters::StubTwoAdapter, child_job_two.queue_adapter + assert_kind_of ActiveJob::QueueAdapters::StubOneAdapter, child_job_one.queue_adapter, "child_job_one's queue adapter should remain unchanged" + assert_equal base_queue_adapter, ActiveJob::Base.queue_adapter, "ActiveJob::Base's queue adapter should remain unchanged" + + child_job_three = Class.new(ActiveJob::Base) + + assert_not_nil child_job_three.queue_adapter + end +end diff --git a/activejob/test/cases/test_case_test.rb b/activejob/test/cases/test_case_test.rb index 7d1702990e..0a3a20d5a0 100644 --- a/activejob/test/cases/test_case_test.rb +++ b/activejob/test/cases/test_case_test.rb @@ -4,11 +4,20 @@ require 'jobs/logging_job' require 'jobs/nested_job' class ActiveJobTestCaseTest < ActiveJob::TestCase + # this tests that this job class doesn't get its adapter set. + # that's the correct behaviour since we don't want to break + # the `class_attribute` inheritence + class TestClassAttributeInheritenceJob < ActiveJob::Base + def self.queue_adapter=(*) + raise 'Attemping to break `class_attribute` inheritence, bad!' + end + end + def test_include_helper assert_includes self.class.ancestors, ActiveJob::TestHelper end def test_set_test_adapter - assert_equal ActiveJob::QueueAdapters::TestAdapter, self.queue_adapter + assert_kind_of ActiveJob::QueueAdapters::TestAdapter, self.queue_adapter end end diff --git a/activejob/test/support/integration/test_case_helpers.rb b/activejob/test/support/integration/test_case_helpers.rb index ee2f6aebea..bed28b2900 100644 --- a/activejob/test/support/integration/test_case_helpers.rb +++ b/activejob/test/support/integration/test_case_helpers.rb @@ -5,7 +5,7 @@ module TestCaseHelpers extend ActiveSupport::Concern included do - self.use_transactional_fixtures = false + self.use_transactional_tests = false setup do clear_jobs @@ -27,8 +27,8 @@ module TestCaseHelpers jobs_manager.clear_jobs end - def adapter_is?(adapter) - ActiveJob::Base.queue_adapter.name.split("::").last.gsub(/Adapter$/, '').underscore==adapter.to_s + def adapter_is?(adapter_class_symbol) + ActiveJob::Base.queue_adapter.class.name.split("::").last.gsub(/Adapter$/, '').underscore == adapter_class_symbol.to_s end def wait_for_jobs_to_finish_for(seconds=60) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 0f99f907e8..07714538fb 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,21 @@ +* Add `config.active_record.dump_schemas` to fix `db:structure:dump` + when using schema_search_path and PostgreSQL extensions. + + Fixes #17157. + + *Ryan Wallace* + +* Renaming `use_transactional_fixtures` to `use_transactional_tests` for clarity. + + Fixes #18864. + + *Brandon Weiss* + +* Increase pg gem version requirement to `~> 0.18`. Earlier versions of the + pg gem are known to have problems with Ruby 2.2. + + *Matt Brictson* + * Correctly dump `serial` and `bigserial`. *Ryuta Kamizono* diff --git a/activerecord/lib/active_record/associations/association.rb b/activerecord/lib/active_record/associations/association.rb index 0d8e4ba870..930f678ae8 100644 --- a/activerecord/lib/active_record/associations/association.rb +++ b/activerecord/lib/active_record/associations/association.rb @@ -8,12 +8,12 @@ module ActiveRecord # # Association # SingularAssociation - # HasOneAssociation + # HasOneAssociation + ForeignAssociation # HasOneThroughAssociation + ThroughAssociation # BelongsToAssociation # BelongsToPolymorphicAssociation # CollectionAssociation - # HasManyAssociation + # HasManyAssociation + ForeignAssociation # HasManyThroughAssociation + ThroughAssociation class Association #:nodoc: attr_reader :owner, :target, :reflection diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb index 0ba03338f6..1e245926e0 100644 --- a/activerecord/lib/active_record/associations/collection_association.rb +++ b/activerecord/lib/active_record/associations/collection_association.rb @@ -432,8 +432,7 @@ module ActiveRecord def get_records if reflection.scope_chain.any?(&:any?) || scope.eager_loading? || - klass.current_scope || - klass.default_scopes.any? + klass.scope_attributes? return scope.to_a end diff --git a/activerecord/lib/active_record/associations/singular_association.rb b/activerecord/lib/active_record/associations/singular_association.rb index c44242a0f0..58d0f7d65d 100644 --- a/activerecord/lib/active_record/associations/singular_association.rb +++ b/activerecord/lib/active_record/associations/singular_association.rb @@ -41,8 +41,7 @@ module ActiveRecord def get_records if reflection.scope_chain.any?(&:any?) || scope.eager_loading? || - klass.current_scope || - klass.default_scopes.any? + klass.scope_attributes? return scope.limit(1).to_a end diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index c74f4e8fa5..295a7bed87 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -44,11 +44,12 @@ module ActiveRecord attr_reader :connection, :state, :records, :savepoint_name attr_writer :joinable - def initialize(connection, options) + def initialize(connection, options, run_commit_callbacks: false) @connection = connection @state = TransactionState.new @records = [] @joinable = options.fetch(:joinable, true) + @run_commit_callbacks = run_commit_callbacks end def add_record(record) @@ -75,18 +76,21 @@ module ActiveRecord end def before_commit_records - records.uniq.each(&:before_committed!) + records.uniq.each(&:before_committed!) if @run_commit_callbacks end def commit_records ite = records.uniq while record = ite.shift - record.committed! + if @run_commit_callbacks + record.committed! + else + # if not running callbacks, only adds the record to the parent transaction + record.add_to_transaction + end end ensure - ite.each do |i| - i.committed!(should_run_callbacks: false) - end + ite.each { |i| i.committed!(should_run_callbacks: false) } end def full_rollback?; true; end @@ -97,8 +101,8 @@ module ActiveRecord class SavepointTransaction < Transaction - def initialize(connection, savepoint_name, options) - super(connection, options) + def initialize(connection, savepoint_name, options, *args) + super(connection, options, *args) if options[:isolation] raise ActiveRecord::TransactionIsolationError, "cannot set transaction isolation in a nested transaction" end @@ -120,7 +124,7 @@ module ActiveRecord class RealTransaction < Transaction - def initialize(connection, options) + def initialize(connection, options, *args) super if options[:isolation] connection.begin_isolated_db_transaction(options[:isolation]) @@ -147,11 +151,13 @@ module ActiveRecord end def begin_transaction(options = {}) + run_commit_callbacks = !current_transaction.joinable? transaction = if @stack.empty? - RealTransaction.new(@connection, options) + RealTransaction.new(@connection, options, run_commit_callbacks: run_commit_callbacks) else - SavepointTransaction.new(@connection, "active_record_#{@stack.size}", options) + SavepointTransaction.new(@connection, "active_record_#{@stack.size}", options, + run_commit_callbacks: run_commit_callbacks) end @stack.push(transaction) @@ -159,18 +165,11 @@ module ActiveRecord end def commit_transaction - inner_transaction = @stack.pop - - if current_transaction.joinable? - inner_transaction.commit - inner_transaction.records.each do |r| - r.add_to_transaction - end - else - inner_transaction.before_commit_records - inner_transaction.commit - inner_transaction.commit_records - end + transaction = @stack.last + transaction.before_commit_records + @stack.pop + transaction.commit + transaction.commit_records end def rollback_transaction(transaction = nil) 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 9625fcf9b8..7e41772227 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -785,7 +785,9 @@ module ActiveRecord subselect = Arel::SelectManager.new(select.engine) subselect.project Arel.sql(key.name) - subselect.from subsubselect.as('__active_record_temp') + # Materialized subquery by adding distinct + # to work with MySQL 5.7.6 which sets optimizer_switch='derived_merge=on' + subselect.from subsubselect.distinct.as('__active_record_temp') end def add_index_length(option_strings, column_names, options = {}) diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 92f470ae70..96a3ac7c31 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -12,8 +12,8 @@ require "active_record/connection_adapters/statement_pool" require 'arel/visitors/bind_visitor' -# Make sure we're using pg high enough for PGResult#values -gem 'pg', '~> 0.15' +# Make sure we're using pg high enough for Ruby 2.2+ compatibility +gem 'pg', '~> 0.18' require 'pg' require 'ipaddr' diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index 640642e90b..9a39a0e919 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -85,6 +85,15 @@ module ActiveRecord mattr_accessor :dump_schema_after_migration, instance_writer: false self.dump_schema_after_migration = true + ## + # :singleton-method: + # Specifies which database schemas to dump when calling db:structure:dump. + # If :schema_search_path (the default), it will dumps any schemas listed in schema_search_path. + # Use :all to always dumps all schemas regardless of the schema_search_path. + # A string of comma separated schemas can also be used to pass a custom list of schemas. + mattr_accessor :dump_schemas, instance_writer: false + self.dump_schemas = :schema_search_path + mattr_accessor :maintain_test_schema, instance_accessor: false mattr_accessor :belongs_to_required_by_default, instance_accessor: false @@ -123,8 +132,7 @@ module ActiveRecord return super unless ids.length == 1 return super if block_given? || primary_key.nil? || - default_scopes.any? || - current_scope || + scope_attributes? || columns_hash.include?(inheritance_column) || ids.first.kind_of?(Array) @@ -152,8 +160,7 @@ module ActiveRecord end def find_by(*args) # :nodoc: - return super if current_scope || !(Hash === args.first) || reflect_on_all_aggregations.any? - return super if default_scopes.any? + return super if scope_attributes? || !(Hash === args.first) || reflect_on_all_aggregations.any? hash = args.first diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb index 18775caad2..2c1771dd6c 100644 --- a/activerecord/lib/active_record/fixtures.rb +++ b/activerecord/lib/active_record/fixtures.rb @@ -139,13 +139,13 @@ module ActiveRecord # name: kitten.png # sha: <%= file_sha 'files/kitten.png' %> # - # = Transactional Fixtures + # = Transactional Tests # # Test cases can use begin+rollback to isolate their changes to the database instead of having to # delete+insert for every test case. # # class FooTest < ActiveSupport::TestCase - # self.use_transactional_fixtures = true + # self.use_transactional_tests = true # # test "godzilla" do # assert !Foo.all.empty? @@ -159,14 +159,14 @@ module ActiveRecord # end # # If you preload your test database with all fixture data (probably in the rake task) and use - # transactional fixtures, then you may omit all fixtures declarations in your test cases since + # transactional tests, then you may omit all fixtures declarations in your test cases since # all the data's already there and every case rolls back its changes. # # In order to use instantiated fixtures with preloaded data, set +self.pre_loaded_fixtures+ to # true. This will provide access to fixture data for every table that has been loaded through # fixtures (depending on the value of +use_instantiated_fixtures+). # - # When *not* to use transactional fixtures: + # When *not* to use transactional tests: # # 1. You're testing whether a transaction works correctly. Nested transactions don't commit until # all parent transactions commit, particularly, the fixtures transaction which is begun in setup @@ -835,13 +835,15 @@ module ActiveRecord class_attribute :fixture_path, :instance_writer => false class_attribute :fixture_table_names class_attribute :fixture_class_names + class_attribute :use_transactional_tests class_attribute :use_transactional_fixtures class_attribute :use_instantiated_fixtures # true, false, or :no_instances class_attribute :pre_loaded_fixtures class_attribute :config + singleton_class.deprecate 'use_transactional_fixtures=' => 'use use_transactional_tests= instead' + self.fixture_table_names = [] - self.use_transactional_fixtures = true self.use_instantiated_fixtures = false self.pre_loaded_fixtures = false self.config = ActiveRecord::Base @@ -849,6 +851,16 @@ module ActiveRecord self.fixture_class_names = Hash.new do |h, fixture_set_name| h[fixture_set_name] = ActiveRecord::FixtureSet.default_fixture_model_name(fixture_set_name, self.config) end + + silence_warnings do + define_singleton_method :use_transactional_tests do + if use_transactional_fixtures.nil? + true + else + use_transactional_fixtures + end + end + end end module ClassMethods @@ -919,13 +931,13 @@ module ActiveRecord end def run_in_transaction? - use_transactional_fixtures && + use_transactional_tests && !self.class.uses_transaction?(method_name) end def setup_fixtures(config = ActiveRecord::Base) - if pre_loaded_fixtures && !use_transactional_fixtures - raise RuntimeError, 'pre_loaded_fixtures requires use_transactional_fixtures' + if pre_loaded_fixtures && !use_transactional_tests + raise RuntimeError, 'pre_loaded_fixtures requires use_transactional_tests' end @fixture_cache = {} diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index b6de90e89d..f1bdbc845c 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -58,9 +58,6 @@ module ActiveRecord require "active_record/railties/console_sandbox" if app.sandbox? require "active_record/base" console = ActiveSupport::Logger.new(STDERR) - console.formatter = Rails.logger.formatter - console.level = Rails.logger.level - Rails.logger.extend ActiveSupport::Logger.broadcast console end diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index dab5a502a5..e4704b5b3e 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -166,8 +166,8 @@ module ActiveRecord # AggregateReflection and AssociationReflection are returned by the Reflection::ClassMethods. # # MacroReflection + # AggregateReflection # AssociationReflection - # AggregateReflection # HasManyReflection # HasOneReflection # BelongsToReflection @@ -694,7 +694,7 @@ module ActiveRecord def chain @chain ||= begin a = source_reflection.chain - b = through_reflection.chain + b = through_reflection.chain.map(&:dup) if options[:source_type] b[0] = PolymorphicReflection.new(b[0], self) diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index 7f27e7b463..8f16de3519 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -182,7 +182,7 @@ module ActiveRecord private def has_include?(column_name) - eager_loading? || (includes_values.present? && ((column_name && column_name != :all) || references_eager_loaded_tables?)) + eager_loading? || (includes_values.present? && column_name && column_name != :all) end def perform_calculation(operation, column_name) diff --git a/activerecord/lib/active_record/scoping.rb b/activerecord/lib/active_record/scoping.rb index fca4f1c9d3..f049b658c4 100644 --- a/activerecord/lib/active_record/scoping.rb +++ b/activerecord/lib/active_record/scoping.rb @@ -17,6 +17,17 @@ module ActiveRecord def current_scope=(scope) #:nodoc: ScopeRegistry.set_value_for(:current_scope, self.to_s, scope) end + + # Collects attributes from scopes that should be applied when creating + # an AR instance for the particular class this is called on. + def scope_attributes # :nodoc: + all.scope_for_create + end + + # Are there attributes associated with this scope? + def scope_attributes? # :nodoc: + current_scope + end end def populate_with_current_scope_attributes diff --git a/activerecord/lib/active_record/scoping/default.rb b/activerecord/lib/active_record/scoping/default.rb index 18190cb535..5ec2c88b47 100644 --- a/activerecord/lib/active_record/scoping/default.rb +++ b/activerecord/lib/active_record/scoping/default.rb @@ -33,6 +33,11 @@ module ActiveRecord block_given? ? relation.scoping { yield } : relation end + # Are there attributes associated with this scope? + def scope_attributes? # :nodoc: + super || default_scopes.any? + end + def before_remove_const #:nodoc: self.current_scope = nil end diff --git a/activerecord/lib/active_record/scoping/named.rb b/activerecord/lib/active_record/scoping/named.rb index 43c7b1c574..7b62626896 100644 --- a/activerecord/lib/active_record/scoping/named.rb +++ b/activerecord/lib/active_record/scoping/named.rb @@ -39,17 +39,6 @@ module ActiveRecord end end - # Collects attributes from scopes that should be applied when creating - # an AR instance for the particular class this is called on. - def scope_attributes # :nodoc: - all.scope_for_create - end - - # Are there default attributes associated with this scope? - def scope_attributes? # :nodoc: - current_scope || default_scopes.any? - end - # Adds a class method for retrieving and querying objects. A \scope # represents a narrowing of a database query, such as # <tt>where(color: :red).select('shirts.*').includes(:washing_instructions)</tt>. diff --git a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb index ce1de4b76e..435708a421 100644 --- a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb +++ b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb @@ -46,7 +46,15 @@ module ActiveRecord def structure_dump(filename) set_psql_env - search_path = configuration['schema_search_path'] + + search_path = case ActiveRecord::Base.dump_schemas + when :schema_search_path + configuration['schema_search_path'] + when :all + nil + when String + ActiveRecord::Base.dump_schemas + end unless search_path.blank? search_path = search_path.split(",").map{|search_path_part| "--schema=#{Shellwords.escape(search_path_part.strip)}" }.join(" ") end diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb index ecf1368a91..1712ff0ac6 100644 --- a/activerecord/test/cases/adapter_test.rb +++ b/activerecord/test/cases/adapter_test.rb @@ -226,7 +226,7 @@ module ActiveRecord end class AdapterTestWithoutTransaction < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false class Klass < ActiveRecord::Base end diff --git a/activerecord/test/cases/adapters/mysql/consistency_test.rb b/activerecord/test/cases/adapters/mysql/consistency_test.rb index e972d6b330..ae190b728d 100644 --- a/activerecord/test/cases/adapters/mysql/consistency_test.rb +++ b/activerecord/test/cases/adapters/mysql/consistency_test.rb @@ -1,7 +1,7 @@ require "cases/helper" class MysqlConsistencyTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false class Consistency < ActiveRecord::Base self.table_name = "mysql_consistency" diff --git a/activerecord/test/cases/adapters/mysql/reserved_word_test.rb b/activerecord/test/cases/adapters/mysql/reserved_word_test.rb index 2f9c070255..ec1c394f40 100644 --- a/activerecord/test/cases/adapters/mysql/reserved_word_test.rb +++ b/activerecord/test/cases/adapters/mysql/reserved_word_test.rb @@ -71,7 +71,7 @@ class MysqlReservedWordTest < ActiveRecord::TestCase #fixtures self.use_instantiated_fixtures = true - self.use_transactional_fixtures = false + self.use_transactional_tests = false #activerecord model class with reserved-word table name def test_activerecord_model diff --git a/activerecord/test/cases/adapters/mysql/unsigned_type_test.rb b/activerecord/test/cases/adapters/mysql/unsigned_type_test.rb index 8f521e9181..e9edc53f93 100644 --- a/activerecord/test/cases/adapters/mysql/unsigned_type_test.rb +++ b/activerecord/test/cases/adapters/mysql/unsigned_type_test.rb @@ -1,7 +1,7 @@ require "cases/helper" class UnsignedTypeTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false class UnsignedType < ActiveRecord::Base end diff --git a/activerecord/test/cases/adapters/mysql2/boolean_test.rb b/activerecord/test/cases/adapters/mysql2/boolean_test.rb index 0e641ba3bf..0d81dd6eee 100644 --- a/activerecord/test/cases/adapters/mysql2/boolean_test.rb +++ b/activerecord/test/cases/adapters/mysql2/boolean_test.rb @@ -1,7 +1,7 @@ require "cases/helper" class Mysql2BooleanTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false class BooleanType < ActiveRecord::Base self.table_name = "mysql_booleans" diff --git a/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb b/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb index beb829fc46..799e60a683 100644 --- a/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb +++ b/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb @@ -71,7 +71,7 @@ class MysqlReservedWordTest < ActiveRecord::TestCase #fixtures self.use_instantiated_fixtures = true - self.use_transactional_fixtures = false + self.use_transactional_tests = false #activerecord model class with reserved-word table name def test_activerecord_model diff --git a/activerecord/test/cases/adapters/mysql2/unsigned_type_test.rb b/activerecord/test/cases/adapters/mysql2/unsigned_type_test.rb index 8f521e9181..e9edc53f93 100644 --- a/activerecord/test/cases/adapters/mysql2/unsigned_type_test.rb +++ b/activerecord/test/cases/adapters/mysql2/unsigned_type_test.rb @@ -1,7 +1,7 @@ require "cases/helper" class UnsignedTypeTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false class UnsignedType < ActiveRecord::Base end diff --git a/activerecord/test/cases/adapters/postgresql/datatype_test.rb b/activerecord/test/cases/adapters/postgresql/datatype_test.rb index 4f48a7bce3..2c14252ae4 100644 --- a/activerecord/test/cases/adapters/postgresql/datatype_test.rb +++ b/activerecord/test/cases/adapters/postgresql/datatype_test.rb @@ -12,7 +12,7 @@ class PostgresqlLtree < ActiveRecord::Base end class PostgresqlDataTypeTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false def setup @connection = ActiveRecord::Base.connection diff --git a/activerecord/test/cases/adapters/postgresql/extension_migration_test.rb b/activerecord/test/cases/adapters/postgresql/extension_migration_test.rb index 7b99fcdda0..06d427f464 100644 --- a/activerecord/test/cases/adapters/postgresql/extension_migration_test.rb +++ b/activerecord/test/cases/adapters/postgresql/extension_migration_test.rb @@ -1,7 +1,7 @@ require "cases/helper" class PostgresqlExtensionMigrationTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false class EnableHstore < ActiveRecord::Migration def change diff --git a/activerecord/test/cases/adapters/postgresql/range_test.rb b/activerecord/test/cases/adapters/postgresql/range_test.rb index b6b451ca5c..bbf96278b0 100644 --- a/activerecord/test/cases/adapters/postgresql/range_test.rb +++ b/activerecord/test/cases/adapters/postgresql/range_test.rb @@ -7,7 +7,7 @@ if ActiveRecord::Base.connection.supports_ranges? end class PostgresqlRangeTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false include ConnectionHelper def setup diff --git a/activerecord/test/cases/adapters/postgresql/referential_integrity_test.rb b/activerecord/test/cases/adapters/postgresql/referential_integrity_test.rb index 71ee2d9bab..d76e762815 100644 --- a/activerecord/test/cases/adapters/postgresql/referential_integrity_test.rb +++ b/activerecord/test/cases/adapters/postgresql/referential_integrity_test.rb @@ -2,7 +2,7 @@ require 'cases/helper' require 'support/connection_helper' class PostgreSQLReferentialIntegrityTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false include ConnectionHelper diff --git a/activerecord/test/cases/adapters/postgresql/schema_authorization_test.rb b/activerecord/test/cases/adapters/postgresql/schema_authorization_test.rb index 6937145439..359a45bbd1 100644 --- a/activerecord/test/cases/adapters/postgresql/schema_authorization_test.rb +++ b/activerecord/test/cases/adapters/postgresql/schema_authorization_test.rb @@ -4,7 +4,7 @@ class SchemaThing < ActiveRecord::Base end class SchemaAuthorizationTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false TABLE_NAME = 'schema_things' COLUMNS = [ diff --git a/activerecord/test/cases/adapters/postgresql/schema_test.rb b/activerecord/test/cases/adapters/postgresql/schema_test.rb index 77ff6d01bc..c1be340e7c 100644 --- a/activerecord/test/cases/adapters/postgresql/schema_test.rb +++ b/activerecord/test/cases/adapters/postgresql/schema_test.rb @@ -3,7 +3,7 @@ require 'models/default' require 'support/schema_dumping_helper' class SchemaTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false SCHEMA_NAME = 'test_schema' SCHEMA2_NAME = 'test_schema2' diff --git a/activerecord/test/cases/adapters/postgresql/timestamp_test.rb b/activerecord/test/cases/adapters/postgresql/timestamp_test.rb index da14063e20..a639f98272 100644 --- a/activerecord/test/cases/adapters/postgresql/timestamp_test.rb +++ b/activerecord/test/cases/adapters/postgresql/timestamp_test.rb @@ -5,7 +5,7 @@ require 'models/topic' class PostgresqlTimestampTest < ActiveRecord::TestCase class PostgresqlTimestampWithZone < ActiveRecord::Base; end - self.use_transactional_fixtures = false + self.use_transactional_tests = false setup do @connection = ActiveRecord::Base.connection diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb index 5ca3c92027..27f4ba8eb6 100644 --- a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb @@ -8,7 +8,7 @@ module ActiveRecord class SQLite3AdapterTest < ActiveRecord::TestCase include DdlHelper - self.use_transactional_fixtures = false + self.use_transactional_tests = false class DualEncoding < ActiveRecord::Base end diff --git a/activerecord/test/cases/ar_schema_test.rb b/activerecord/test/cases/ar_schema_test.rb index f4e8003bc3..9d5327bf35 100644 --- a/activerecord/test/cases/ar_schema_test.rb +++ b/activerecord/test/cases/ar_schema_test.rb @@ -3,7 +3,7 @@ require "cases/helper" if ActiveRecord::Base.connection.supports_migrations? class ActiveRecordSchemaTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false setup do @original_verbose = ActiveRecord::Migration.verbose diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb index 7dc9266074..5c2e5e7b43 100644 --- a/activerecord/test/cases/associations/has_one_associations_test.rb +++ b/activerecord/test/cases/associations/has_one_associations_test.rb @@ -12,7 +12,7 @@ require 'models/image' require 'models/post' class HasOneAssociationsTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false unless supports_savepoints? + self.use_transactional_tests = false unless supports_savepoints? fixtures :accounts, :companies, :developers, :projects, :developers_projects, :ships, :pirates def setup diff --git a/activerecord/test/cases/associations/join_model_test.rb b/activerecord/test/cases/associations/join_model_test.rb index 9918601623..213be50e67 100644 --- a/activerecord/test/cases/associations/join_model_test.rb +++ b/activerecord/test/cases/associations/join_model_test.rb @@ -17,7 +17,7 @@ require 'models/engine' require 'models/car' class AssociationsJoinModelTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false unless supports_savepoints? + self.use_transactional_tests = false unless supports_savepoints? fixtures :posts, :authors, :categories, :categorizations, :comments, :tags, :taggings, :author_favorites, :vertices, :items, :books, # Reload edges table from fixtures as otherwise repeated test was failing diff --git a/activerecord/test/cases/associations/required_test.rb b/activerecord/test/cases/associations/required_test.rb index 8b765a2e0c..3e5494e897 100644 --- a/activerecord/test/cases/associations/required_test.rb +++ b/activerecord/test/cases/associations/required_test.rb @@ -1,7 +1,7 @@ require "cases/helper" class RequiredAssociationsTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false class Parent < ActiveRecord::Base end diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb index 859afc4553..8f0d7bd037 100644 --- a/activerecord/test/cases/autosave_association_test.rb +++ b/activerecord/test/cases/autosave_association_test.rb @@ -629,7 +629,7 @@ class TestDefaultAutosaveAssociationOnNewRecord < ActiveRecord::TestCase end class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false setup do @pirate = Pirate.create(:catchphrase => "Don' botharrr talkin' like one, savvy?") @@ -637,7 +637,7 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase end teardown do - # We are running without transactional fixtures and need to cleanup. + # We are running without transactional tests and need to cleanup. Bird.delete_all Parrot.delete_all @ship.delete @@ -1009,7 +1009,7 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase end class TestAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCase - self.use_transactional_fixtures = false unless supports_savepoints? + self.use_transactional_tests = false unless supports_savepoints? def setup super @@ -1145,7 +1145,7 @@ class TestAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCase end class TestAutosaveAssociationOnAHasOneThroughAssociation < ActiveRecord::TestCase - self.use_transactional_fixtures = false unless supports_savepoints? + self.use_transactional_tests = false unless supports_savepoints? def setup super @@ -1166,7 +1166,7 @@ class TestAutosaveAssociationOnAHasOneThroughAssociation < ActiveRecord::TestCas end class TestAutosaveAssociationOnABelongsToAssociation < ActiveRecord::TestCase - self.use_transactional_fixtures = false unless supports_savepoints? + self.use_transactional_tests = false unless supports_savepoints? def setup super @@ -1414,7 +1414,7 @@ module AutosaveAssociationOnACollectionAssociationTests end class TestAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCase - self.use_transactional_fixtures = false unless supports_savepoints? + self.use_transactional_tests = false unless supports_savepoints? def setup super @@ -1430,7 +1430,7 @@ class TestAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCase end class TestAutosaveAssociationOnAHasAndBelongsToManyAssociation < ActiveRecord::TestCase - self.use_transactional_fixtures = false unless supports_savepoints? + self.use_transactional_tests = false unless supports_savepoints? def setup super @@ -1447,7 +1447,7 @@ class TestAutosaveAssociationOnAHasAndBelongsToManyAssociation < ActiveRecord::T end class TestAutosaveAssociationOnAHasAndBelongsToManyAssociationWithAcceptsNestedAttributes < ActiveRecord::TestCase - self.use_transactional_fixtures = false unless supports_savepoints? + self.use_transactional_tests = false unless supports_savepoints? def setup super @@ -1464,7 +1464,7 @@ class TestAutosaveAssociationOnAHasAndBelongsToManyAssociationWithAcceptsNestedA end class TestAutosaveAssociationValidationsOnAHasManyAssociation < ActiveRecord::TestCase - self.use_transactional_fixtures = false unless supports_savepoints? + self.use_transactional_tests = false unless supports_savepoints? def setup super @@ -1481,7 +1481,7 @@ class TestAutosaveAssociationValidationsOnAHasManyAssociation < ActiveRecord::Te end class TestAutosaveAssociationValidationsOnAHasOneAssociation < ActiveRecord::TestCase - self.use_transactional_fixtures = false unless supports_savepoints? + self.use_transactional_tests = false unless supports_savepoints? def setup super @@ -1504,7 +1504,7 @@ class TestAutosaveAssociationValidationsOnAHasOneAssociation < ActiveRecord::Tes end class TestAutosaveAssociationValidationsOnABelongsToAssociation < ActiveRecord::TestCase - self.use_transactional_fixtures = false unless supports_savepoints? + self.use_transactional_tests = false unless supports_savepoints? def setup super @@ -1525,7 +1525,7 @@ class TestAutosaveAssociationValidationsOnABelongsToAssociation < ActiveRecord:: end class TestAutosaveAssociationValidationsOnAHABTMAssociation < ActiveRecord::TestCase - self.use_transactional_fixtures = false unless supports_savepoints? + self.use_transactional_tests = false unless supports_savepoints? def setup super @@ -1548,7 +1548,7 @@ class TestAutosaveAssociationValidationsOnAHABTMAssociation < ActiveRecord::Test end class TestAutosaveAssociationValidationMethodsGeneration < ActiveRecord::TestCase - self.use_transactional_fixtures = false unless supports_savepoints? + self.use_transactional_tests = false unless supports_savepoints? def setup super diff --git a/activerecord/test/cases/date_time_precision_test.rb b/activerecord/test/cases/date_time_precision_test.rb index 6a4e64b22c..698f1b852e 100644 --- a/activerecord/test/cases/date_time_precision_test.rb +++ b/activerecord/test/cases/date_time_precision_test.rb @@ -4,7 +4,7 @@ require 'support/schema_dumping_helper' if ActiveRecord::Base.connection.supports_datetime_with_precision? class DateTimePrecisionTest < ActiveRecord::TestCase include SchemaDumpingHelper - self.use_transactional_fixtures = false + self.use_transactional_tests = false class Foo < ActiveRecord::Base; end diff --git a/activerecord/test/cases/defaults_test.rb b/activerecord/test/cases/defaults_test.rb index b9db0d0123..67fddebf45 100644 --- a/activerecord/test/cases/defaults_test.rb +++ b/activerecord/test/cases/defaults_test.rb @@ -90,14 +90,14 @@ end if current_adapter?(:MysqlAdapter, :Mysql2Adapter) class DefaultsTestWithoutTransactionalFixtures < ActiveRecord::TestCase # ActiveRecord::Base#create! (and #save and other related methods) will - # open a new transaction. When in transactional fixtures mode, this will + # open a new transaction. When in transactional tests mode, this will # cause Active Record to create a new savepoint. However, since MySQL doesn't # support DDL transactions, creating a table will result in any created # savepoints to be automatically released. This in turn causes the savepoint # release code in AbstractAdapter#transaction to fail. # - # We don't want that to happen, so we disable transactional fixtures here. - self.use_transactional_fixtures = false + # We don't want that to happen, so we disable transactional tests here. + self.use_transactional_tests = false def using_strict(strict) connection = ActiveRecord::Base.remove_connection diff --git a/activerecord/test/cases/disconnected_test.rb b/activerecord/test/cases/disconnected_test.rb index 94447addc1..55f0e51717 100644 --- a/activerecord/test/cases/disconnected_test.rb +++ b/activerecord/test/cases/disconnected_test.rb @@ -4,7 +4,7 @@ class TestRecord < ActiveRecord::Base end class TestDisconnectedAdapter < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false def setup @connection = ActiveRecord::Base.connection diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb index d1add21219..f8acdcb51e 100644 --- a/activerecord/test/cases/fixtures_test.rb +++ b/activerecord/test/cases/fixtures_test.rb @@ -28,7 +28,7 @@ require 'tempfile' class FixturesTest < ActiveRecord::TestCase self.use_instantiated_fixtures = true - self.use_transactional_fixtures = false + self.use_transactional_tests = false # other_topics fixture should not be included here fixtures :topics, :developers, :accounts, :tasks, :categories, :funny_jokes, :binaries, :traffic_lights @@ -419,7 +419,7 @@ end class TransactionalFixturesTest < ActiveRecord::TestCase self.use_instantiated_fixtures = true - self.use_transactional_fixtures = true + self.use_transactional_tests = true fixtures :topics @@ -511,7 +511,7 @@ class CheckSetTableNameFixturesTest < ActiveRecord::TestCase fixtures :funny_jokes # Set to false to blow away fixtures cache and ensure our fixtures are loaded # and thus takes into account our set_fixture_class - self.use_transactional_fixtures = false + self.use_transactional_tests = false def test_table_method assert_kind_of Joke, funny_jokes(:a_joke) @@ -523,7 +523,7 @@ class FixtureNameIsNotTableNameFixturesTest < ActiveRecord::TestCase fixtures :items # Set to false to blow away fixtures cache and ensure our fixtures are loaded # and thus takes into account our set_fixture_class - self.use_transactional_fixtures = false + self.use_transactional_tests = false def test_named_accessor assert_kind_of Book, items(:dvd) @@ -535,7 +535,7 @@ class FixtureNameIsNotTableNameMultipleFixturesTest < ActiveRecord::TestCase fixtures :items, :funny_jokes # Set to false to blow away fixtures cache and ensure our fixtures are loaded # and thus takes into account our set_fixture_class - self.use_transactional_fixtures = false + self.use_transactional_tests = false def test_named_accessor_of_differently_named_fixture assert_kind_of Book, items(:dvd) @@ -549,7 +549,7 @@ end class CustomConnectionFixturesTest < ActiveRecord::TestCase set_fixture_class :courses => Course fixtures :courses - self.use_transactional_fixtures = false + self.use_transactional_tests = false def test_leaky_destroy assert_nothing_raised { courses(:ruby) } @@ -564,7 +564,7 @@ end class TransactionalFixturesOnCustomConnectionTest < ActiveRecord::TestCase set_fixture_class :courses => Course fixtures :courses - self.use_transactional_fixtures = true + self.use_transactional_tests = true def test_leaky_destroy assert_nothing_raised { courses(:ruby) } @@ -580,7 +580,7 @@ class InvalidTableNameFixturesTest < ActiveRecord::TestCase fixtures :funny_jokes # Set to false to blow away fixtures cache and ensure our fixtures are loaded # and thus takes into account our lack of set_fixture_class - self.use_transactional_fixtures = false + self.use_transactional_tests = false def test_raises_error assert_raise ActiveRecord::FixtureClassNotFound do @@ -594,7 +594,7 @@ class CheckEscapedYamlFixturesTest < ActiveRecord::TestCase fixtures :funny_jokes # Set to false to blow away fixtures cache and ensure our fixtures are loaded # and thus takes into account our set_fixture_class - self.use_transactional_fixtures = false + self.use_transactional_tests = false def test_proper_escaped_fixture assert_equal "The \\n Aristocrats\nAte the candy\n", funny_jokes(:another_joke).name @@ -664,7 +664,7 @@ class LoadAllFixturesWithPathnameTest < ActiveRecord::TestCase end class FasterFixturesTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false fixtures :categories, :authors def load_extra_fixture(name) diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb index b118ecc125..12c793c408 100644 --- a/activerecord/test/cases/helper.rb +++ b/activerecord/test/cases/helper.rb @@ -143,7 +143,7 @@ class ActiveSupport::TestCase self.fixture_path = FIXTURES_ROOT self.use_instantiated_fixtures = false - self.use_transactional_fixtures = true + self.use_transactional_tests = true def create_fixtures(*fixture_set_names, &block) ActiveRecord::FixtureSet.create_fixtures(ActiveSupport::TestCase.fixture_path, fixture_set_names, fixture_class_names, &block) diff --git a/activerecord/test/cases/hot_compatibility_test.rb b/activerecord/test/cases/hot_compatibility_test.rb index b4617cf6f9..5ba9a1029a 100644 --- a/activerecord/test/cases/hot_compatibility_test.rb +++ b/activerecord/test/cases/hot_compatibility_test.rb @@ -1,7 +1,7 @@ require 'cases/helper' class HotCompatibilityTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false setup do @klass = Class.new(ActiveRecord::Base) do diff --git a/activerecord/test/cases/invalid_connection_test.rb b/activerecord/test/cases/invalid_connection_test.rb index 8416c81f45..6523fc29fd 100644 --- a/activerecord/test/cases/invalid_connection_test.rb +++ b/activerecord/test/cases/invalid_connection_test.rb @@ -1,7 +1,7 @@ require "cases/helper" class TestAdapterWithInvalidConnection < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false class Bird < ActiveRecord::Base end diff --git a/activerecord/test/cases/locking_test.rb b/activerecord/test/cases/locking_test.rb index 848174df06..9e4998a946 100644 --- a/activerecord/test/cases/locking_test.rb +++ b/activerecord/test/cases/locking_test.rb @@ -285,10 +285,10 @@ end class OptimisticLockingWithSchemaChangeTest < ActiveRecord::TestCase fixtures :people, :legacy_things, :references - # need to disable transactional fixtures, because otherwise the sqlite3 + # need to disable transactional tests, because otherwise the sqlite3 # adapter (at least) chokes when we try and change the schema in the middle # of a test (see test_increment_counter_*). - self.use_transactional_fixtures = false + self.use_transactional_tests = false { :lock_version => Person, :custom_lock_version => LegacyThing }.each do |name, model| define_method("test_increment_counter_updates_#{name}") do @@ -365,7 +365,7 @@ end # (See exec vs. async_exec in the PostgreSQL adapter.) unless in_memory_db? class PessimisticLockingTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false fixtures :people, :readers def setup diff --git a/activerecord/test/cases/migration/change_schema_test.rb b/activerecord/test/cases/migration/change_schema_test.rb index 30c91dfdcb..46a62c272f 100644 --- a/activerecord/test/cases/migration/change_schema_test.rb +++ b/activerecord/test/cases/migration/change_schema_test.rb @@ -426,7 +426,7 @@ module ActiveRecord if ActiveRecord::Base.connection.supports_foreign_keys? class ChangeSchemaWithDependentObjectsTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false setup do @connection = ActiveRecord::Base.connection diff --git a/activerecord/test/cases/migration/column_attributes_test.rb b/activerecord/test/cases/migration/column_attributes_test.rb index 763aa88f72..8d8e661aa5 100644 --- a/activerecord/test/cases/migration/column_attributes_test.rb +++ b/activerecord/test/cases/migration/column_attributes_test.rb @@ -5,7 +5,7 @@ module ActiveRecord class ColumnAttributesTest < ActiveRecord::TestCase include ActiveRecord::Migration::TestHelper - self.use_transactional_fixtures = false + self.use_transactional_tests = false def test_add_column_newline_default string = "foo\nbar" diff --git a/activerecord/test/cases/migration/columns_test.rb b/activerecord/test/cases/migration/columns_test.rb index e5ccfe0f91..5fc7702dfa 100644 --- a/activerecord/test/cases/migration/columns_test.rb +++ b/activerecord/test/cases/migration/columns_test.rb @@ -5,7 +5,7 @@ module ActiveRecord class ColumnsTest < ActiveRecord::TestCase include ActiveRecord::Migration::TestHelper - self.use_transactional_fixtures = false + self.use_transactional_tests = false # FIXME: this is more of an integration test with AR::Base and the # schema modifications. Maybe we should move this? diff --git a/activerecord/test/cases/migration/logger_test.rb b/activerecord/test/cases/migration/logger_test.rb index 319d3e1af3..bf6e684887 100644 --- a/activerecord/test/cases/migration/logger_test.rb +++ b/activerecord/test/cases/migration/logger_test.rb @@ -4,7 +4,7 @@ module ActiveRecord class Migration class LoggerTest < ActiveRecord::TestCase # MySQL can't roll back ddl changes - self.use_transactional_fixtures = false + self.use_transactional_tests = false Migration = Struct.new(:name, :version) do def disable_ddl_transaction; false end diff --git a/activerecord/test/cases/migration/references_statements_test.rb b/activerecord/test/cases/migration/references_statements_test.rb index 988bd9c89f..f613fd66c3 100644 --- a/activerecord/test/cases/migration/references_statements_test.rb +++ b/activerecord/test/cases/migration/references_statements_test.rb @@ -5,7 +5,7 @@ module ActiveRecord class ReferencesStatementsTest < ActiveRecord::TestCase include ActiveRecord::Migration::TestHelper - self.use_transactional_fixtures = false + self.use_transactional_tests = false def setup super diff --git a/activerecord/test/cases/migration/rename_table_test.rb b/activerecord/test/cases/migration/rename_table_test.rb index 3eef308428..6d742d3f2f 100644 --- a/activerecord/test/cases/migration/rename_table_test.rb +++ b/activerecord/test/cases/migration/rename_table_test.rb @@ -5,7 +5,7 @@ module ActiveRecord class RenameTableTest < ActiveRecord::TestCase include ActiveRecord::Migration::TestHelper - self.use_transactional_fixtures = false + self.use_transactional_tests = false def setup super diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index 3b73685a2c..b2f209fe97 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -24,7 +24,7 @@ class Reminder < ActiveRecord::Base; end class Thing < ActiveRecord::Base; end class MigrationTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false fixtures :people diff --git a/activerecord/test/cases/migrator_test.rb b/activerecord/test/cases/migrator_test.rb index 1760314099..2ff6938e7b 100644 --- a/activerecord/test/cases/migrator_test.rb +++ b/activerecord/test/cases/migrator_test.rb @@ -2,7 +2,7 @@ require "cases/helper" require "cases/migration/helper" class MigratorTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false # Use this class to sense if migrations have gone # up or down. diff --git a/activerecord/test/cases/multiple_db_test.rb b/activerecord/test/cases/multiple_db_test.rb index f9bc266e84..39cdcf5403 100644 --- a/activerecord/test/cases/multiple_db_test.rb +++ b/activerecord/test/cases/multiple_db_test.rb @@ -4,7 +4,7 @@ require 'models/bird' require 'models/course' class MultipleDbTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false def setup @courses = create_fixtures("courses") { Course.retrieve_connection } diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb index c5f6589c22..6b4addd52f 100644 --- a/activerecord/test/cases/nested_attributes_test.rb +++ b/activerecord/test/cases/nested_attributes_test.rb @@ -943,7 +943,7 @@ class TestNestedAttributesWithNonStandardPrimaryKeys < ActiveRecord::TestCase end class TestHasOneAutosaveAssociationWhichItselfHasAutosaveAssociations < ActiveRecord::TestCase - self.use_transactional_fixtures = false unless supports_savepoints? + self.use_transactional_tests = false unless supports_savepoints? def setup @pirate = Pirate.create!(:catchphrase => "My baby takes tha mornin' train!") @@ -983,7 +983,7 @@ class TestHasOneAutosaveAssociationWhichItselfHasAutosaveAssociations < ActiveRe end class TestHasManyAutosaveAssociationWhichItselfHasAutosaveAssociations < ActiveRecord::TestCase - self.use_transactional_fixtures = false unless supports_savepoints? + self.use_transactional_tests = false unless supports_savepoints? def setup @ship = Ship.create!(:name => "The good ship Dollypop") diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb index 7c281a95b7..2370077eb0 100644 --- a/activerecord/test/cases/persistence_test.rb +++ b/activerecord/test/cases/persistence_test.rb @@ -898,7 +898,7 @@ class PersistenceTest < ActiveRecord::TestCase end class SaveTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false def test_save_touch_false widget = Class.new(ActiveRecord::Base) do diff --git a/activerecord/test/cases/pooled_connections_test.rb b/activerecord/test/cases/pooled_connections_test.rb index 287a3f33ea..daa3271777 100644 --- a/activerecord/test/cases/pooled_connections_test.rb +++ b/activerecord/test/cases/pooled_connections_test.rb @@ -3,7 +3,7 @@ require "models/project" require "timeout" class PooledConnectionsTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false def setup @per_test_teardown = [] diff --git a/activerecord/test/cases/primary_keys_test.rb b/activerecord/test/cases/primary_keys_test.rb index 1ea1ef5e12..3664a2af70 100644 --- a/activerecord/test/cases/primary_keys_test.rb +++ b/activerecord/test/cases/primary_keys_test.rb @@ -178,7 +178,7 @@ class PrimaryKeysTest < ActiveRecord::TestCase end class PrimaryKeyWithNoConnectionTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false unless in_memory_db? def test_set_primary_key_with_no_connection @@ -199,7 +199,7 @@ end class PrimaryKeyAnyTypeTest < ActiveRecord::TestCase include SchemaDumpingHelper - self.use_transactional_fixtures = false + self.use_transactional_tests = false class Barcode < ActiveRecord::Base end @@ -229,7 +229,7 @@ end if current_adapter?(:MysqlAdapter, :Mysql2Adapter) class PrimaryKeyWithAnsiQuotesTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false def test_primary_key_method_with_ansi_quotes con = ActiveRecord::Base.connection @@ -245,7 +245,7 @@ if current_adapter?(:PostgreSQLAdapter, :MysqlAdapter, :Mysql2Adapter) class PrimaryKeyBigSerialTest < ActiveRecord::TestCase include SchemaDumpingHelper - self.use_transactional_fixtures = false + self.use_transactional_tests = false class Widget < ActiveRecord::Base end diff --git a/activerecord/test/cases/reflection_test.rb b/activerecord/test/cases/reflection_test.rb index 67e9bef808..06bc70c172 100644 --- a/activerecord/test/cases/reflection_test.rb +++ b/activerecord/test/cases/reflection_test.rb @@ -23,6 +23,7 @@ require 'models/chef' require 'models/department' require 'models/cake_designer' require 'models/drink_designer' +require 'models/recipe' class ReflectionTest < ActiveRecord::TestCase include ActiveRecord::Reflection @@ -277,6 +278,16 @@ class ReflectionTest < ActiveRecord::TestCase assert_equal 2, @hotel.chefs.size end + def test_scope_chain_of_polymorphic_association_does_not_leak_into_other_hmt_associations + hotel = Hotel.create! + department = hotel.departments.create! + drink = department.chefs.create!(employable: DrinkDesigner.create!) + Recipe.create!(chef_id: drink.id, hotel_id: hotel.id) + + hotel.drink_designers.to_a + assert_sql(/^(?!.*employable_type).*$/) { hotel.recipes.to_a } + end + def test_nested? assert !Author.reflect_on_association(:comments).nested? assert Author.reflect_on_association(:tags).nested? diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb index 513f65f707..6bf4df70eb 100644 --- a/activerecord/test/cases/schema_dumper_test.rb +++ b/activerecord/test/cases/schema_dumper_test.rb @@ -3,7 +3,7 @@ require 'support/schema_dumping_helper' class SchemaDumperTest < ActiveRecord::TestCase include SchemaDumpingHelper - self.use_transactional_fixtures = false + self.use_transactional_tests = false setup do ActiveRecord::SchemaMigration.create_table diff --git a/activerecord/test/cases/tasks/postgresql_rake_test.rb b/activerecord/test/cases/tasks/postgresql_rake_test.rb index 0d574d071c..d45fb07417 100644 --- a/activerecord/test/cases/tasks/postgresql_rake_test.rb +++ b/activerecord/test/cases/tasks/postgresql_rake_test.rb @@ -195,21 +195,54 @@ module ActiveRecord 'adapter' => 'postgresql', 'database' => 'my-app-db' } + @filename = "awesome-file.sql" ActiveRecord::Base.stubs(:connection).returns(@connection) ActiveRecord::Base.stubs(:establish_connection).returns(true) Kernel.stubs(:system) + File.stubs(:open) end def test_structure_dump - filename = "awesome-file.sql" - Kernel.expects(:system).with("pg_dump -i -s -x -O -f #{filename} my-app-db").returns(true) - @connection.expects(:schema_search_path).returns("foo") + Kernel.expects(:system).with("pg_dump -i -s -x -O -f #{@filename} my-app-db").returns(true) + + ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, @filename) + end + + def test_structure_dump_with_schema_search_path + @configuration['schema_search_path'] = 'foo,bar' + + Kernel.expects(:system).with("pg_dump -i -s -x -O -f #{@filename} --schema=foo --schema=bar my-app-db").returns(true) + + ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, @filename) + end + + def test_structure_dump_with_schema_search_path_and_dump_schemas_all + @configuration['schema_search_path'] = 'foo,bar' + + Kernel.expects(:system).with("pg_dump -i -s -x -O -f #{@filename} my-app-db").returns(true) + + with_dump_schemas(:all) do + ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, @filename) + end + end + + def test_structure_dump_with_dump_schemas_string + Kernel.expects(:system).with("pg_dump -i -s -x -O -f #{@filename} --schema=foo --schema=bar my-app-db").returns(true) + + with_dump_schemas('foo,bar') do + ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, @filename) + end + end + + private - ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, filename) - assert File.exist?(filename) + def with_dump_schemas(value, &block) + old_dump_schemas = ActiveRecord::Base.dump_schemas + ActiveRecord::Base.dump_schemas = value + yield ensure - FileUtils.rm(filename) + ActiveRecord::Base.dump_schemas = old_dump_schemas end end diff --git a/activerecord/test/cases/test_fixtures_test.rb b/activerecord/test/cases/test_fixtures_test.rb new file mode 100644 index 0000000000..3f4baf8378 --- /dev/null +++ b/activerecord/test/cases/test_fixtures_test.rb @@ -0,0 +1,36 @@ +require 'cases/helper' + +class TestFixturesTest < ActiveRecord::TestCase + setup do + @klass = Class.new + @klass.send(:include, ActiveRecord::TestFixtures) + end + + def test_deprecated_use_transactional_fixtures= + assert_deprecated 'use use_transactional_tests= instead' do + @klass.use_transactional_fixtures = true + end + end + + def test_use_transactional_tests_prefers_use_transactional_fixtures + ActiveSupport::Deprecation.silence do + @klass.use_transactional_fixtures = false + end + + assert_equal false, @klass.use_transactional_tests + end + + def test_use_transactional_tests_defaults_to_true + ActiveSupport::Deprecation.silence do + @klass.use_transactional_fixtures = nil + end + + assert_equal true, @klass.use_transactional_tests + end + + def test_use_transactional_tests_can_be_overriden + @klass.use_transactional_tests = "foobar" + + assert_equal "foobar", @klass.use_transactional_tests + end +end diff --git a/activerecord/test/cases/time_precision_test.rb b/activerecord/test/cases/time_precision_test.rb index ff4e5ecec5..ff7a81fe60 100644 --- a/activerecord/test/cases/time_precision_test.rb +++ b/activerecord/test/cases/time_precision_test.rb @@ -4,7 +4,7 @@ require 'support/schema_dumping_helper' if ActiveRecord::Base.connection.supports_datetime_with_precision? class TimePrecisionTest < ActiveRecord::TestCase include SchemaDumpingHelper - self.use_transactional_fixtures = false + self.use_transactional_tests = false class Foo < ActiveRecord::Base; end diff --git a/activerecord/test/cases/timestamp_test.rb b/activerecord/test/cases/timestamp_test.rb index c0c62527df..7c89b4b9e8 100644 --- a/activerecord/test/cases/timestamp_test.rb +++ b/activerecord/test/cases/timestamp_test.rb @@ -450,7 +450,7 @@ end class TimestampsWithoutTransactionTest < ActiveRecord::TestCase include DdlHelper - self.use_transactional_fixtures = false + self.use_transactional_tests = false class TimestampAttributePost < ActiveRecord::Base attr_accessor :created_at, :updated_at diff --git a/activerecord/test/cases/transaction_callbacks_test.rb b/activerecord/test/cases/transaction_callbacks_test.rb index e868022fed..f2229939c8 100644 --- a/activerecord/test/cases/transaction_callbacks_test.rb +++ b/activerecord/test/cases/transaction_callbacks_test.rb @@ -367,7 +367,7 @@ class TransactionCallbacksTest < ActiveRecord::TestCase end class CallbacksOnMultipleActionsTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false class TopicWithCallbacksOnMultipleActions < ActiveRecord::Base self.table_name = :topics @@ -376,6 +376,9 @@ class CallbacksOnMultipleActionsTest < ActiveRecord::TestCase after_commit(on: [:create, :update]) { |record| record.history << :create_and_update } after_commit(on: [:update, :destroy]) { |record| record.history << :update_and_destroy } + before_commit(if: :save_before_commit_history) { |record| record.history << :before_commit } + before_commit(if: :update_title) { |record| record.update(title: "before commit title") } + def clear_history @history = [] end @@ -383,6 +386,8 @@ class CallbacksOnMultipleActionsTest < ActiveRecord::TestCase def history @history ||= [] end + + attr_accessor :save_before_commit_history, :update_title end def test_after_commit_on_multiple_actions @@ -399,6 +404,23 @@ class CallbacksOnMultipleActionsTest < ActiveRecord::TestCase topic.destroy assert_equal [:update_and_destroy, :create_and_destroy], topic.history end + + def test_before_commit_actions + topic = TopicWithCallbacksOnMultipleActions.new + topic.save_before_commit_history = true + topic.save + + assert_equal [:before_commit, :create_and_update, :create_and_destroy], topic.history + end + + def test_before_commit_update_in_same_transaction + topic = TopicWithCallbacksOnMultipleActions.new + topic.update_title = true + topic.save + + assert_equal "before commit title", topic.title + assert_equal "before commit title", topic.reload.title + end end diff --git a/activerecord/test/cases/transaction_isolation_test.rb b/activerecord/test/cases/transaction_isolation_test.rb index f89c26532d..2f7d208ed2 100644 --- a/activerecord/test/cases/transaction_isolation_test.rb +++ b/activerecord/test/cases/transaction_isolation_test.rb @@ -2,7 +2,7 @@ require 'cases/helper' unless ActiveRecord::Base.connection.supports_transaction_isolation? class TransactionIsolationUnsupportedTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false class Tag < ActiveRecord::Base end @@ -17,7 +17,7 @@ end if ActiveRecord::Base.connection.supports_transaction_isolation? class TransactionIsolationTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false class Tag < ActiveRecord::Base self.table_name = 'tags' diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb index 4be3ea445c..2468a91969 100644 --- a/activerecord/test/cases/transactions_test.rb +++ b/activerecord/test/cases/transactions_test.rb @@ -9,7 +9,7 @@ require 'models/post' require 'models/movie' class TransactionTest < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false fixtures :topics, :developers, :authors, :posts def setup @@ -703,7 +703,7 @@ class TransactionTest < ActiveRecord::TestCase end class TransactionsWithTransactionalFixturesTest < ActiveRecord::TestCase - self.use_transactional_fixtures = true + self.use_transactional_tests = true fixtures :topics def test_automatic_savepoint_in_outer_transaction diff --git a/activerecord/test/cases/unconnected_test.rb b/activerecord/test/cases/unconnected_test.rb index afb893a52c..b210584644 100644 --- a/activerecord/test/cases/unconnected_test.rb +++ b/activerecord/test/cases/unconnected_test.rb @@ -4,7 +4,7 @@ class TestRecord < ActiveRecord::Base end class TestUnconnectedAdapter < ActiveRecord::TestCase - self.use_transactional_fixtures = false + self.use_transactional_tests = false def setup @underlying = ActiveRecord::Base.connection diff --git a/activerecord/test/models/chef.rb b/activerecord/test/models/chef.rb index 67a4e54f06..698a52e045 100644 --- a/activerecord/test/models/chef.rb +++ b/activerecord/test/models/chef.rb @@ -1,3 +1,4 @@ class Chef < ActiveRecord::Base belongs_to :employable, polymorphic: true + has_many :recipes end diff --git a/activerecord/test/models/hotel.rb b/activerecord/test/models/hotel.rb index b352cd22f3..491f8dfde3 100644 --- a/activerecord/test/models/hotel.rb +++ b/activerecord/test/models/hotel.rb @@ -3,4 +3,5 @@ class Hotel < ActiveRecord::Base has_many :chefs, through: :departments has_many :cake_designers, source_type: 'CakeDesigner', source: :employable, through: :chefs has_many :drink_designers, source_type: 'DrinkDesigner', source: :employable, through: :chefs + has_many :recipes, through: :chefs end diff --git a/activerecord/test/models/recipe.rb b/activerecord/test/models/recipe.rb new file mode 100644 index 0000000000..c387230603 --- /dev/null +++ b/activerecord/test/models/recipe.rb @@ -0,0 +1,3 @@ +class Recipe < ActiveRecord::Base + belongs_to :chef +end diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index 5e5f7a798e..7b42f8a4a5 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -886,6 +886,10 @@ ActiveRecord::Schema.define do t.string :employable_type t.integer :department_id end + create_table :recipes, force: true do |t| + t.integer :chef_id + t.integer :hotel_id + end create_table :records, force: true do |t| end diff --git a/activesupport/lib/active_support/testing/time_helpers.rb b/activesupport/lib/active_support/testing/time_helpers.rb index df5186ddec..c9d20cd837 100644 --- a/activesupport/lib/active_support/testing/time_helpers.rb +++ b/activesupport/lib/active_support/testing/time_helpers.rb @@ -42,12 +42,13 @@ module ActiveSupport # Containing helpers that helps you test passage of time. module TimeHelpers # Changes current time to the time in the future or in the past by a given time difference by - # stubbing +Time.now+ and +Date.today+. + # stubbing +Time.now+, +Date.today+, and +DateTime.now+. # - # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00 + # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00 # travel 1.day - # Time.current # => Sun, 10 Nov 2013 15:34:49 EST -05:00 - # Date.current # => Sun, 10 Nov 2013 + # Time.current # => Sun, 10 Nov 2013 15:34:49 EST -05:00 + # Date.current # => Sun, 10 Nov 2013 + # DateTime.current # => Sun, 10 Nov 2013 15:34:49 -0500 # # This method also accepts a block, which will return the current time back to its original # state at the end of the block: @@ -61,13 +62,14 @@ module ActiveSupport travel_to Time.now + duration, &block end - # Changes current time to the given time by stubbing +Time.now+ and - # +Date.today+ to return the time or date passed into this method. + # Changes current time to the given time by stubbing +Time.now+, + # +Date.today+, and +DateTime.now+ to return the time or date passed into this method. # - # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00 + # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00 # travel_to Time.new(2004, 11, 24, 01, 04, 44) - # Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00 - # Date.current # => Wed, 24 Nov 2004 + # Time.current # => Wed, 24 Nov 2004 01:04:44 EST -05:00 + # Date.current # => Wed, 24 Nov 2004 + # DateTime.current # => Wed, 24 Nov 2004 01:04:44 -0500 # # Dates are taken as their timestamp at the beginning of the day in the # application time zone. <tt>Time.current</tt> returns said timestamp, diff --git a/guides/source/3_1_release_notes.md b/guides/source/3_1_release_notes.md index e187e5f9ab..537aa5a371 100644 --- a/guides/source/3_1_release_notes.md +++ b/guides/source/3_1_release_notes.md @@ -174,7 +174,7 @@ Rails Architectural Changes The major change in Rails 3.1 is the Assets Pipeline. It makes CSS and JavaScript first-class code citizens and enables proper organization, including use in plugins and engines. -The assets pipeline is powered by [Sprockets](https://github.com/sstephenson/sprockets) and is covered in the [Asset Pipeline](asset_pipeline.html) guide. +The assets pipeline is powered by [Sprockets](https://github.com/rails/sprockets) and is covered in the [Asset Pipeline](asset_pipeline.html) guide. ### HTTP Streaming diff --git a/guides/source/4_0_release_notes.md b/guides/source/4_0_release_notes.md index bd35e2d31a..bbc0efa3ea 100644 --- a/guides/source/4_0_release_notes.md +++ b/guides/source/4_0_release_notes.md @@ -87,7 +87,10 @@ Major Features * **Support for specifying transaction isolation level** ([commit](https://github.com/rails/rails/commit/392eeecc11a291e406db927a18b75f41b2658253)) - Choose whether repeatable reads or improved performance (less locking) is more important. * **Dalli** ([commit](https://github.com/rails/rails/commit/82663306f428a5bbc90c511458432afb26d2f238)) - Use Dalli memcache client for the memcache store. * **Notifications start & finish** ([commit](https://github.com/rails/rails/commit/f08f8750a512f741acb004d0cebe210c5f949f28)) - Active Support instrumentation reports start and finish notifications to subscribers. - * **Thread safe by default** ([commit](https://github.com/rails/rails/commit/5d416b907864d99af55ebaa400fff217e17570cd)) - Rails can run in threaded app servers without additional configuration. Note: Check that the gems you are using are threadsafe. + * **Thread safe by default** ([commit](https://github.com/rails/rails/commit/5d416b907864d99af55ebaa400fff217e17570cd)) - Rails can run in threaded app servers without additional configuration. + +NOTE: Check that the gems you are using are threadsafe. + * **PATCH verb** ([commit](https://github.com/rails/rails/commit/eed9f2539e3ab5a68e798802f464b8e4e95e619e)) - In Rails, PATCH replaces PUT. PATCH is used for partial updates of resources. ### Security diff --git a/guides/source/action_controller_overview.md b/guides/source/action_controller_overview.md index f68179841e..8c1551f4a1 100644 --- a/guides/source/action_controller_overview.md +++ b/guides/source/action_controller_overview.md @@ -9,7 +9,7 @@ After reading this guide, you will know: * How to follow the flow of a request through a controller. * How to restrict parameters passed to your controller. -* Why and how to store data in the session or cookies. +* How and why to store data in the session or cookies. * How to work with filters to execute code during request processing. * How to use Action Controller's built-in HTTP authentication. * How to stream data directly to the user's browser. @@ -21,11 +21,11 @@ After reading this guide, you will know: What Does a Controller Do? -------------------------- -Action Controller is the C in MVC. After routing has determined which controller to use for a request, your controller is responsible for making sense of the request and producing the appropriate output. Luckily, Action Controller does most of the groundwork for you and uses smart conventions to make this as straightforward as possible. +Action Controller is the C in MVC. After routing has determined which controller to use for a request, the controller is responsible for making sense of the request and producing the appropriate output. Luckily, Action Controller does most of the groundwork for you and uses smart conventions to make this as straightforward as possible. For most conventional [RESTful](http://en.wikipedia.org/wiki/Representational_state_transfer) applications, the controller will receive the request (this is invisible to you as the developer), fetch or save data from a model and use a view to create HTML output. If your controller needs to do things a little differently, that's not a problem, this is just the most common way for a controller to work. -A controller can thus be thought of as a middle man between models and views. It makes the model data available to the view so it can display that data to the user, and it saves or updates data from the user to the model. +A controller can thus be thought of as a middleman between models and views. It makes the model data available to the view so it can display that data to the user, and it saves or updates user data to the model. NOTE: For more details on the routing process, see [Rails Routing from the Outside In](routing.html). @@ -34,7 +34,7 @@ Controller Naming Convention The naming convention of controllers in Rails favors pluralization of the last word in the controller's name, although it is not strictly required (e.g. `ApplicationController`). For example, `ClientsController` is preferable to `ClientController`, `SiteAdminsController` is preferable to `SiteAdminController` or `SitesAdminsController`, and so on. -Following this convention will allow you to use the default route generators (e.g. `resources`, etc) without needing to qualify each `:path` or `:controller`, and keeps URL and path helpers' usage consistent throughout your application. See [Layouts & Rendering Guide](layouts_and_rendering.html) for more details. +Following this convention will allow you to use the default route generators (e.g. `resources`, etc) without needing to qualify each `:path` or `:controller`, and will keep URL and path helpers' usage consistent throughout your application. See [Layouts & Rendering Guide](layouts_and_rendering.html) for more details. NOTE: The controller naming convention differs from the naming convention of models, which are expected to be named in singular form. @@ -51,7 +51,7 @@ class ClientsController < ApplicationController end ``` -As an example, if a user goes to `/clients/new` in your application to add a new client, Rails will create an instance of `ClientsController` and run the `new` method. Note that the empty method from the example above would work just fine because Rails will by default render the `new.html.erb` view unless the action says otherwise. The `new` method could make available to the view a `@client` instance variable by creating a new `Client`: +As an example, if a user goes to `/clients/new` in your application to add a new client, Rails will create an instance of `ClientsController` and call its `new` method. Note that the empty method from the example above would work just fine because Rails will by default render the `new.html.erb` view unless the action says otherwise. The `new` method could make available to the view a `@client` instance variable by creating a new `Client`: ```ruby def new @@ -63,7 +63,7 @@ The [Layouts & Rendering Guide](layouts_and_rendering.html) explains this in mor `ApplicationController` inherits from `ActionController::Base`, which defines a number of helpful methods. This guide will cover some of these, but if you're curious to see what's in there, you can see all of them in the API documentation or in the source itself. -Only public methods are callable as actions. It is a best practice to lower the visibility of methods which are not intended to be actions, like auxiliary methods or filters. +Only public methods are callable as actions. It is a best practice to lower the visibility of methods (with `private` or `protected`) which are not intended to be actions, like auxiliary methods or filters. Parameters ---------- @@ -104,13 +104,13 @@ end ### Hash and Array Parameters -The `params` hash is not limited to one-dimensional keys and values. It can contain arrays and (nested) hashes. To send an array of values, append an empty pair of square brackets "[]" to the key name: +The `params` hash is not limited to one-dimensional keys and values. It can contain nested arrays and hashes. To send an array of values, append an empty pair of square brackets "[]" to the key name: ``` GET /clients?ids[]=1&ids[]=2&ids[]=3 ``` -NOTE: The actual URL in this example will be encoded as "/clients?ids%5b%5d=1&ids%5b%5d=2&ids%5b%5d=3" as "[" and "]" are not allowed in URLs. Most of the time you don't have to worry about this because the browser will take care of it for you, and Rails will decode it back when it receives it, but if you ever find yourself having to send those requests to the server manually you have to keep this in mind. +NOTE: The actual URL in this example will be encoded as "/clients?ids%5b%5d=1&ids%5b%5d=2&ids%5b%5d=3" as the "[" and "]" characters are not allowed in URLs. Most of the time you don't have to worry about this because the browser will encode it for you, and Rails will decode it automatically, but if you ever find yourself having to send those requests to the server manually you should keep this in mind. The value of `params[:ids]` will now be `["1", "2", "3"]`. Note that parameter values are always strings; Rails makes no attempt to guess or cast the type. @@ -118,7 +118,7 @@ NOTE: Values such as `[nil]` or `[nil, nil, ...]` in `params` are replaced with `[]` for security reasons by default. See [Security Guide](security.html#unsafe-query-generation) for more information. -To send a hash you include the key name inside the brackets: +To send a hash, you include the key name inside the brackets: ```html <form accept-charset="UTF-8" action="/clients" method="post"> @@ -131,11 +131,11 @@ To send a hash you include the key name inside the brackets: When this form is submitted, the value of `params[:client]` will be `{ "name" => "Acme", "phone" => "12345", "address" => { "postcode" => "12345", "city" => "Carrot City" } }`. Note the nested hash in `params[:client][:address]`. -Note that the `params` hash is actually an instance of `ActiveSupport::HashWithIndifferentAccess`, which acts like a hash but lets you use symbols and strings interchangeably as keys. +The `params` object acts like a Hash, but lets you use symbols and strings interchangeably as keys. ### JSON parameters -If you're writing a web service application, you might find yourself more comfortable accepting parameters in JSON format. If the "Content-Type" header of your request is set to "application/json", Rails will automatically convert your parameters into the `params` hash, which you can access as you would normally. +If you're writing a web service application, you might find yourself more comfortable accepting parameters in JSON format. If the "Content-Type" header of your request is set to "application/json", Rails will automatically load your parameters into the `params` hash, which you can access as you would normally. So for example, if you are sending this JSON content: @@ -143,15 +143,15 @@ So for example, if you are sending this JSON content: { "company": { "name": "acme", "address": "123 Carrot Street" } } ``` -You'll get `params[:company]` as `{ "name" => "acme", "address" => "123 Carrot Street" }`. +Your controller will receive `params[:company]` as `{ "name" => "acme", "address" => "123 Carrot Street" }`. -Also, if you've turned on `config.wrap_parameters` in your initializer or calling `wrap_parameters` in your controller, you can safely omit the root element in the JSON parameter. The parameters will be cloned and wrapped in the key according to your controller's name by default. So the above parameter can be written as: +Also, if you've turned on `config.wrap_parameters` in your initializer or called `wrap_parameters` in your controller, you can safely omit the root element in the JSON parameter. In this case, the parameters will be cloned and wrapped with a key chosen based on your controller's name. So the above JSON POST can be written as: ```json { "name": "acme", "address": "123 Carrot Street" } ``` -And assume that you're sending the data to `CompaniesController`, it would then be wrapped in `:company` key like this: +And, assuming that you're sending the data to `CompaniesController`, it would then be wrapped within the `:company` key like this: ```ruby { name: "acme", address: "123 Carrot Street", company: { name: "acme", address: "123 Carrot Street" } } @@ -159,17 +159,17 @@ And assume that you're sending the data to `CompaniesController`, it would then You can customize the name of the key or specific parameters you want to wrap by consulting the [API documentation](http://api.rubyonrails.org/classes/ActionController/ParamsWrapper.html) -NOTE: Support for parsing XML parameters has been extracted into a gem named `actionpack-xml_parser` +NOTE: Support for parsing XML parameters has been extracted into a gem named `actionpack-xml_parser`. ### Routing Parameters -The `params` hash will always contain the `:controller` and `:action` keys, but you should use the methods `controller_name` and `action_name` instead to access these values. Any other parameters defined by the routing, such as `:id` will also be available. As an example, consider a listing of clients where the list can show either active or inactive clients. We can add a route which captures the `:status` parameter in a "pretty" URL: +The `params` hash will always contain the `:controller` and `:action` keys, but you should use the methods `controller_name` and `action_name` instead to access these values. Any other parameters defined by the routing, such as `:id`, will also be available. As an example, consider a listing of clients where the list can show either active or inactive clients. We can add a route which captures the `:status` parameter in a "pretty" URL: ```ruby get '/clients/:status' => 'clients#index', foo: 'bar' ``` -In this case, when a user opens the URL `/clients/active`, `params[:status]` will be set to "active". When this route is used, `params[:foo]` will also be set to "bar" just like it was passed in the query string. In the same way `params[:action]` will contain "index". +In this case, when a user opens the URL `/clients/active`, `params[:status]` will be set to "active". When this route is used, `params[:foo]` will also be set to "bar", as if it were passed in the query string. Your controller will also receive `params[:action]` as "index" and `params[:controller]` as "clients". ### `default_url_options` @@ -183,21 +183,21 @@ class ApplicationController < ActionController::Base end ``` -These options will be used as a starting point when generating URLs, so it's possible they'll be overridden by the options passed in `url_for` calls. +These options will be used as a starting point when generating URLs, so it's possible they'll be overridden by the options passed to `url_for` calls. -If you define `default_url_options` in `ApplicationController`, as in the example above, it would be used for all URL generation. The method can also be defined in one specific controller, in which case it only affects URLs generated there. +If you define `default_url_options` in `ApplicationController`, as in the example above, it will be used for all URL generation. The method can also be defined in a specific controller, in which case it only affects URLs generated there. ### Strong Parameters With strong parameters, Action Controller parameters are forbidden to be used in Active Model mass assignments until they have been -whitelisted. This means you'll have to make a conscious choice about -which attributes to allow for mass updating and thus prevent -accidentally exposing that which shouldn't be exposed. +whitelisted. This means that you'll have to make a conscious decision about +which attributes to allow for mass update. This is a better security +practice to help prevent accidentally allowing users to update sensitive +model attributes. -In addition, parameters can be marked as required and flow through a -predefined raise/rescue flow to end up as a 400 Bad Request with no -effort. +In addition, parameters can be marked as required and will flow through a +predefined raise/rescue flow to end up as a 400 Bad Request. ```ruby class PeopleController < ActionController::Base @@ -239,17 +239,17 @@ params.permit(:id) ``` the key `:id` will pass the whitelisting if it appears in `params` and -it has a permitted scalar value associated. Otherwise the key is going +it has a permitted scalar value associated. Otherwise, the key is going to be filtered out, so arrays, hashes, or any other objects cannot be injected. The permitted scalar types are `String`, `Symbol`, `NilClass`, `Numeric`, `TrueClass`, `FalseClass`, `Date`, `Time`, `DateTime`, -`StringIO`, `IO`, `ActionDispatch::Http::UploadedFile` and +`StringIO`, `IO`, `ActionDispatch::Http::UploadedFile`, and `Rack::Test::UploadedFile`. To declare that the value in `params` must be an array of permitted -scalar values map the key to an empty array: +scalar values, map the key to an empty array: ```ruby params.permit(id: []) @@ -262,14 +262,13 @@ used: params.require(:log_entry).permit! ``` -This will mark the `:log_entry` parameters hash and any sub-hash of it -permitted. Extreme care should be taken when using `permit!` as it -will allow all current and future model attributes to be -mass-assigned. +This will mark the `:log_entry` parameters hash and any sub-hash of it as +permitted. Extreme care should be taken when using `permit!`, as it +will allow all current and future model attributes to be mass-assigned. #### Nested Parameters -You can also use permit on nested parameters, like: +You can also use `permit` on nested parameters, like: ```ruby params.permit(:name, { emails: [] }, @@ -277,19 +276,19 @@ params.permit(:name, { emails: [] }, { family: [ :name ], hobbies: [] }]) ``` -This declaration whitelists the `name`, `emails` and `friends` +This declaration whitelists the `name`, `emails`, and `friends` attributes. It is expected that `emails` will be an array of permitted -scalar values and that `friends` will be an array of resources with -specific attributes : they should have a `name` attribute (any +scalar values, and that `friends` will be an array of resources with +specific attributes: they should have a `name` attribute (any permitted scalar values allowed), a `hobbies` attribute as an array of permitted scalar values, and a `family` attribute which is restricted -to having a `name` (any permitted scalar values allowed, too). +to having a `name` (any permitted scalar values allowed here, too). #### More Examples -You want to also use the permitted attributes in the `new` +You may want to also use the permitted attributes in your `new` action. This raises the problem that you can't use `require` on the -root key because normally it does not exist when calling `new`: +root key because, normally, it does not exist when calling `new`: ```ruby # using `fetch` you can supply a default and use @@ -297,8 +296,8 @@ root key because normally it does not exist when calling `new`: params.fetch(:blog, {}).permit(:title, :author) ``` -`accepts_nested_attributes_for` allows you to update and destroy -associated records. This is based on the `id` and `_destroy` +The model class method `accepts_nested_attributes_for` allows you to +update and destroy associated records. This is based on the `id` and `_destroy` parameters: ```ruby @@ -306,7 +305,7 @@ parameters: params.require(:author).permit(:name, books_attributes: [:title, :id, :_destroy]) ``` -Hashes with integer keys are treated differently and you can declare +Hashes with integer keys are treated differently, and you can declare the attributes as if they were direct children. You get these kinds of parameters when you use `accepts_nested_attributes_for` in combination with a `has_many` association: @@ -323,13 +322,13 @@ params.require(:book).permit(:title, chapters_attributes: [:title]) #### Outside the Scope of Strong Parameters The strong parameter API was designed with the most common use cases -in mind. It is not meant as a silver bullet to handle all your -whitelisting problems. However you can easily mix the API with your +in mind. It is not meant as a silver bullet to handle all of your +whitelisting problems. However, you can easily mix the API with your own code to adapt to your situation. Imagine a scenario where you have parameters representing a product name and a hash of arbitrary data associated with that product, and -you want to whitelist the product name attribute but also the whole +you want to whitelist the product name attribute and also the whole data hash. The strong parameters API doesn't let you directly whitelist the whole of a nested hash with any keys, but you can use the keys of your nested hash to declare what to whitelist: diff --git a/guides/source/active_record_basics.md b/guides/source/active_record_basics.md index bd8cdf62f2..514bec4bf6 100644 --- a/guides/source/active_record_basics.md +++ b/guides/source/active_record_basics.md @@ -20,7 +20,7 @@ After reading this guide, you will know: What is Active Record? ---------------------- -Active Record is the M in [MVC](getting_started.html#the-mvc-architecture) - the +Active Record is the M in [MVC](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) - the model - which is the layer of the system responsible for representing business data and logic. Active Record facilitates the creation and use of business objects whose data requires persistent storage to a database. It is an diff --git a/guides/source/active_record_querying.md b/guides/source/active_record_querying.md index e5a962b739..bef903b751 100644 --- a/guides/source/active_record_querying.md +++ b/guides/source/active_record_querying.md @@ -348,7 +348,7 @@ Another example would be if you wanted multiple workers handling the same proces Similar to the `:begin_at` option, `:end_at` allows you to configure the last ID of the sequence whenever the highest ID is not the one you need. This would be useful, for example, if you wanted to run a batch process, using a subset of records based on `:begin_at` and `:end_at` -For example, to send newsletters only to users with the primary key starting from 2000 upto 10000 and to retrieve them in batches of 1000: +For example, to send newsletters only to users with the primary key starting from 2000 up to 10000 and to retrieve them in batches of 1000: ```ruby User.find_each(begin_at: 2000, end_at: 10000, batch_size: 5000) do |user| diff --git a/guides/source/asset_pipeline.md b/guides/source/asset_pipeline.md index 6f8b4f4d15..c9ae256c83 100644 --- a/guides/source/asset_pipeline.md +++ b/guides/source/asset_pipeline.md @@ -149,7 +149,7 @@ clients to fetch them again, even when the content of those assets has not chang Fingerprinting fixes these problems by avoiding query strings, and by ensuring that filenames are consistent based on their content. -Fingerprinting is enabled by default for both the development and production +Fingerprinting is enabled by default for both the development and production environments. You can enable or disable it in your configuration through the `config.assets.digest` option. @@ -209,7 +209,7 @@ precompiling works. NOTE: You must have an ExecJS supported runtime in order to use CoffeeScript. If you are using Mac OS X or Windows, you have a JavaScript runtime installed in -your operating system. Check [ExecJS](https://github.com/sstephenson/execjs#readme) documentation to know all supported JavaScript runtimes. +your operating system. Check [ExecJS](https://github.com/rails/execjs#readme) documentation to know all supported JavaScript runtimes. You can also disable generation of controller specific asset files by adding the following to your `config/application.rb` configuration: @@ -921,7 +921,7 @@ focus on serving application code as fast as possible. #### Set up a CDN to Serve Static Assets To set up your CDN you have to have your application running in production on -the internet at a publically available URL, for example `example.com`. Next +the internet at a publicly available URL, for example `example.com`. Next you'll need to sign up for a CDN service from a cloud hosting provider. When you do this you need to configure the "origin" of the CDN to point back at your website `example.com`, check your provider for documentation on configuring the @@ -1137,7 +1137,7 @@ The following line invokes `uglifier` for JavaScript compression. config.assets.js_compressor = :uglifier ``` -NOTE: You will need an [ExecJS](https://github.com/sstephenson/execjs#readme) +NOTE: You will need an [ExecJS](https://github.com/rails/execjs#readme) supported runtime in order to use `uglifier`. If you are using Mac OS X or Windows you have a JavaScript runtime installed in your operating system. diff --git a/guides/source/command_line.md b/guides/source/command_line.md index 6f5a6b7957..d153e0bfa6 100644 --- a/guides/source/command_line.md +++ b/guides/source/command_line.md @@ -526,8 +526,8 @@ end To pass arguments to your custom rake task: ```ruby -task :task_name, [:arg_1] => [:pre_1, :pre_2] do |t, args| - # You can use args from here +task :task_name, [:arg_1] => [:prerequisite_1, :prerequisite_2] do |task, args| + argument_1 = args.arg_1 end ``` diff --git a/guides/source/configuring.md b/guides/source/configuring.md index 4ebd634cd6..67285030a9 100644 --- a/guides/source/configuring.md +++ b/guides/source/configuring.md @@ -302,6 +302,11 @@ All these configuration options are delegated to the `I18n` library. `config/environments/production.rb` which is generated by Rails. The default value is true if this configuration is not set. +* `config.active_record.dump_schemas` controls which database schemas will be dumped when calling db:structure:dump. + The options are `:schema_search_path` (the default) which dumps any schemas listed in schema_search_path, + `:all` which always dumps all schemas regardless of the schema_search_path, + or a string of comma separated schemas. + * `config.active_record.belongs_to_required_by_default` is a boolean value and controls whether `belongs_to` association is required by default. The MySQL adapter adds one additional configuration option: diff --git a/guides/source/contributing_to_ruby_on_rails.md b/guides/source/contributing_to_ruby_on_rails.md index 89218f02c7..018100c316 100644 --- a/guides/source/contributing_to_ruby_on_rails.md +++ b/guides/source/contributing_to_ruby_on_rails.md @@ -378,7 +378,7 @@ Your name can be added directly after the last word if you don't provide any cod ### Updating the Gemfile.lock -Some changes requires the dependencies to be upgraded. In these cases make sure you run `bundle update` to get the right version of the dependency and commit the `Gemfile.lock` file within your changes. +Some changes require the dependencies to be upgraded. In these cases make sure you run `bundle update` to get the right version of the dependency and commit the `Gemfile.lock` file within your changes. ### Sanity Check diff --git a/guides/source/getting_started.md b/guides/source/getting_started.md index 66cfb72aaf..7cce9c72cb 100644 --- a/guides/source/getting_started.md +++ b/guides/source/getting_started.md @@ -204,7 +204,7 @@ Rails adds the `therubyracer` gem to the generated `Gemfile` in a commented line for new apps and you can uncomment if you need it. `therubyrhino` is the recommended runtime for JRuby users and is added by default to the `Gemfile` in apps generated under JRuby. You can investigate -all the supported runtimes at [ExecJS](https://github.com/sstephenson/execjs#readme). +all the supported runtimes at [ExecJS](https://github.com/rails/execjs#readme). This will fire up WEBrick, a web server distributed with Ruby by default. To see your application in action, open a browser window and navigate to @@ -1482,9 +1482,9 @@ Here we're using `link_to` in a different way. We pass the named route as the second argument, and then the options as another argument. The `method: :delete` and `data: { confirm: 'Are you sure?' }` options are used as HTML5 attributes so that when the link is clicked, Rails will first show a confirm dialog to the -user, and then submit the link with method `delete`. This is done via the +user, and then submit the link with method `delete`. This is done via the JavaScript file `jquery_ujs` which is automatically included in your -application's layout (`app/views/layouts/application.html.erb`) when you +application's layout (`app/views/layouts/application.html.erb`) when you generated the application. Without this file, the confirmation dialog box won't appear. diff --git a/guides/source/i18n.md b/guides/source/i18n.md index 1e34261272..e8d0a83dd0 100644 --- a/guides/source/i18n.md +++ b/guides/source/i18n.md @@ -707,7 +707,7 @@ you can safely pass the username as set by the user: ```erb <%# This is safe, it is going to be escaped if needed. %> -<%= t('welcome_html', username: @current_user.username %> +<%= t('welcome_html', username: @current_user.username) %> ``` Safe strings on the other hand are interpolated verbatim. diff --git a/guides/source/testing.md b/guides/source/testing.md index b508969f30..84f1f25df9 100644 --- a/guides/source/testing.md +++ b/guides/source/testing.md @@ -632,7 +632,7 @@ WARNING: You must include the "layouts" directory name even if you save your lay If your view renders any partial, when asserting for the layout, you can to assert for the partial at the same time. Otherwise, assertion will fail. -Remember, we added the "_form" partial to our creating Articles view? Let's write an assertion for that in the `:new` action now: +Remember, we added the "_form" partial to our new Article view? Let's write an assertion for that in the `:new` action now: ```ruby test "new should render correct layout" do @@ -1083,7 +1083,7 @@ Testing mailer classes requires some specific tools to do a thorough job. ### Keeping the Postman in Check -Your mailer classes - like every other part of your Rails application - should be tested to ensure that it is working as expected. +Your mailer classes - like every other part of your Rails application - should be tested to ensure that they are working as expected. The goals of testing your mailer classes are to ensure that: diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 8b10144413..b538c81428 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,10 @@ +* Add `rake initializer` + + This task prints out initializers for an application. It is useful to + develop a rubygem which involves the initialization process. + + *Naoto Kaneko* + * Created rake restart task. Restarts your Rails app by touching the `tmp/restart.txt`. @@ -5,13 +12,6 @@ *Hyonjee Joo* -* Set Rails console to use log formatter and log level as specified for the - given environment. - - Fixes #15470. - - *Jacob Evelyn* - * Add `config/initializers/active_record_belongs_to_required_by_default.rb` Newly generated Rails apps have a new initializer called diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 253272c7dd..813f8b21fd 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -291,7 +291,7 @@ module Rails end def javascript_runtime_gemfile_entry - comment = 'See https://github.com/sstephenson/execjs#readme for more supported runtimes' + comment = 'See https://github.com/rails/execjs#readme for more supported runtimes' if defined?(JRUBY_VERSION) GemfileEntry.version 'therubyrhino', nil, comment else diff --git a/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt b/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt index c1a77944e8..cb86978d4c 100644 --- a/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt +++ b/railties/lib/rails/generators/rails/app/templates/app/assets/javascripts/application.js.tt @@ -7,7 +7,7 @@ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the // compiled file. // -// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details +// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details // about supported directives. // <% unless options[:skip_javascript] -%> diff --git a/railties/lib/rails/generators/rails/plugin/templates/rails/javascripts.js b/railties/lib/rails/generators/rails/plugin/templates/rails/javascripts.js index c28e5badc6..8913b40f69 100644 --- a/railties/lib/rails/generators/rails/plugin/templates/rails/javascripts.js +++ b/railties/lib/rails/generators/rails/plugin/templates/rails/javascripts.js @@ -7,7 +7,7 @@ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the // compiled file. // -// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details +// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details // about supported directives. // //= require_tree . diff --git a/railties/lib/rails/generators/test_unit/mailer/templates/preview.rb b/railties/lib/rails/generators/test_unit/mailer/templates/preview.rb index 6b85764a66..b063cbc47b 100644 --- a/railties/lib/rails/generators/test_unit/mailer/templates/preview.rb +++ b/railties/lib/rails/generators/test_unit/mailer/templates/preview.rb @@ -1,9 +1,9 @@ <% module_namespacing do -%> -# Preview all emails at http://localhost:3000/rails/mailers/<%= file_path %> +# Preview all emails at http://localhost:3000/rails/mailers/<%= file_path %>_mailer class <%= class_name %>MailerPreview < ActionMailer::Preview <% actions.each do |action| -%> - # Preview this email at http://localhost:3000/rails/mailers/<%= file_path %>/<%= action %> + # Preview this email at http://localhost:3000/rails/mailers/<%= file_path %>_mailer/<%= action %> def <%= action %> <%= class_name %>Mailer.<%= action %> end diff --git a/railties/lib/rails/tasks.rb b/railties/lib/rails/tasks.rb index a5e4d2935e..5dfc96894c 100644 --- a/railties/lib/rails/tasks.rb +++ b/railties/lib/rails/tasks.rb @@ -4,6 +4,7 @@ require 'rake' %w( annotations framework + initializer log middleware misc diff --git a/railties/lib/rails/tasks/initializer.rake b/railties/lib/rails/tasks/initializer.rake new file mode 100644 index 0000000000..83b9dc6b71 --- /dev/null +++ b/railties/lib/rails/tasks/initializer.rake @@ -0,0 +1,6 @@ +desc "Prints out initializers for your application" +task initializer: :environment do + Rails.application.initializers.tsort_each do |initializer| + puts initializer.name + end +end diff --git a/railties/lib/rails/test_help.rb b/railties/lib/rails/test_help.rb index 40a1915b54..8953e5fd48 100644 --- a/railties/lib/rails/test_help.rb +++ b/railties/lib/rails/test_help.rb @@ -32,13 +32,15 @@ if defined?(ActiveRecord::Base) end class ActionController::TestCase - setup do + def setup @routes = Rails.application.routes + super end end class ActionDispatch::IntegrationTest - setup do + def setup @routes = Rails.application.routes + super end end diff --git a/railties/test/generators/mailer_generator_test.rb b/railties/test/generators/mailer_generator_test.rb index 584e7a82aa..f01e8cd2d9 100644 --- a/railties/test/generators/mailer_generator_test.rb +++ b/railties/test/generators/mailer_generator_test.rb @@ -47,13 +47,13 @@ class MailerGeneratorTest < Rails::Generators::TestCase assert_match(/test "bar"/, test) end assert_file "test/mailers/previews/notifier_mailer_preview.rb" do |preview| - assert_match(/\# Preview all emails at http:\/\/localhost\:3000\/rails\/mailers\/notifier/, preview) + assert_match(/\# Preview all emails at http:\/\/localhost\:3000\/rails\/mailers\/notifier_mailer/, preview) assert_match(/class NotifierMailerPreview < ActionMailer::Preview/, preview) - assert_match(/\# Preview this email at http:\/\/localhost\:3000\/rails\/mailers\/notifier\/foo/, preview) + assert_match(/\# Preview this email at http:\/\/localhost\:3000\/rails\/mailers\/notifier_mailer\/foo/, preview) assert_instance_method :foo, preview do |foo| assert_match(/NotifierMailer.foo/, foo) end - assert_match(/\# Preview this email at http:\/\/localhost\:3000\/rails\/mailers\/notifier\/bar/, preview) + assert_match(/\# Preview this email at http:\/\/localhost\:3000\/rails\/mailers\/notifier_mailer\/bar/, preview) assert_instance_method :bar, preview do |bar| assert_match(/NotifierMailer.bar/, bar) end @@ -129,9 +129,9 @@ class MailerGeneratorTest < Rails::Generators::TestCase assert_match(/en\.farm\.animal_mailer\.moos\.subject/, mailer) end assert_file "test/mailers/previews/farm/animal_mailer_preview.rb" do |preview| - assert_match(/\# Preview all emails at http:\/\/localhost\:3000\/rails\/mailers\/farm\/animal/, preview) + assert_match(/\# Preview all emails at http:\/\/localhost\:3000\/rails\/mailers\/farm\/animal_mailer/, preview) assert_match(/class Farm::AnimalMailerPreview < ActionMailer::Preview/, preview) - assert_match(/\# Preview this email at http:\/\/localhost\:3000\/rails\/mailers\/farm\/animal\/moos/, preview) + assert_match(/\# Preview this email at http:\/\/localhost\:3000\/rails\/mailers\/farm\/animal_mailer\/moos/, preview) end assert_file "app/views/farm/animal_mailer/moos.text.erb" assert_file "app/views/farm/animal_mailer/moos.html.erb" diff --git a/railties/test/rails_info_controller_test.rb b/railties/test/rails_info_controller_test.rb index d87b51d852..c51503c2b7 100644 --- a/railties/test/rails_info_controller_test.rb +++ b/railties/test/rails_info_controller_test.rb @@ -56,26 +56,26 @@ class InfoControllerTest < ActionController::TestCase test "info controller returns exact matches" do exact_count = -> { JSON(response.body)['exact'].size } - get :routes, path: 'rails/info/route' + get :routes, params: { path: 'rails/info/route' } assert exact_count.call == 0, 'should not match incomplete routes' - get :routes, path: 'rails/info/routes' + get :routes, params: { path: 'rails/info/routes' } assert exact_count.call == 1, 'should match complete routes' - - get :routes, path: 'rails/info/routes.html' + + get :routes, params: { path: 'rails/info/routes.html' } assert exact_count.call == 1, 'should match complete routes with optional parts' end test "info controller returns fuzzy matches" do fuzzy_count = -> { JSON(response.body)['fuzzy'].size } - get :routes, path: 'rails/info' + get :routes, params: { path: 'rails/info' } assert fuzzy_count.call == 2, 'should match incomplete routes' - get :routes, path: 'rails/info/routes' + get :routes, params: { path: 'rails/info/routes' } assert fuzzy_count.call == 1, 'should match complete routes' - - get :routes, path: 'rails/info/routes.html' + + get :routes, params: { path: 'rails/info/routes.html' } assert fuzzy_count.call == 0, 'should match optional parts of route literally' end end |