diff options
103 files changed, 551 insertions, 207 deletions
@@ -40,7 +40,7 @@ gem 'listen', '~> 3.0.5', require: false # Active Job. group :job do - gem 'resque', '< 1.26', require: false + gem 'resque', github: 'resque/resque', require: false gem 'resque-scheduler', require: false gem 'sidekiq', require: false gem 'sucker_punch', require: false diff --git a/Gemfile.lock b/Gemfile.lock index a62a71521e..9fb842ac2c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -22,6 +22,17 @@ GIT delayed_job (>= 3.0, < 5) GIT + remote: git://github.com/resque/resque.git + revision: 06036388ec61e573c761ac5a25a2ef3c76537ec7 + specs: + resque (1.27.0) + mono_logger (~> 1.0) + multi_json (~> 1.0) + redis-namespace (~> 1.3) + sinatra (>= 0.9.2) + vegas (~> 0.1.2) + +GIT remote: git://github.com/sass/sass.git revision: 3fda1cbe70d615e7ef96e28db4fd1f8a3ebb5505 branch: stable @@ -251,12 +262,6 @@ GEM redis (3.3.0) redis-namespace (1.5.2) redis (~> 3.0, >= 3.0.4) - resque (1.25.2) - mono_logger (~> 1.0) - multi_json (~> 1.0) - redis-namespace (~> 1.3) - sinatra (>= 0.9.2) - vegas (~> 0.1.2) resque-scheduler (4.2.0) mono_logger (~> 1.0) redis (~> 3.0) @@ -378,7 +383,7 @@ DEPENDENCIES rake (>= 11.1) redcarpet (~> 3.2.3) redis - resque (< 1.26) + resque! resque-scheduler sass! sass-rails diff --git a/actioncable/CHANGELOG.md b/actioncable/CHANGELOG.md index 9aee32ddb4..cc15e9bf61 100644 --- a/actioncable/CHANGELOG.md +++ b/actioncable/CHANGELOG.md @@ -1,5 +1,17 @@ -* Add ActiveSupport::Notifications hook to Broadcaster#broadcast +* Protect against concurrent writes to a websocket connection from + multiple threads; the underlying OS write is not always threadsafe. + + *Tinco Andringa* + +* Add ActiveSupport::Notifications hook to Broadcaster#broadcast + + *Matthew Wear* + +* Close hijacked socket when connection is shut down. + + Fixes #25613. + + *Tinco Andringa* - *Matthew Wear* Please check [5-0-stable](https://github.com/rails/rails/blob/5-0-stable/actioncable/CHANGELOG.md) for previous changes. diff --git a/actioncable/lib/action_cable/connection/stream.rb b/actioncable/lib/action_cable/connection/stream.rb index c250cf92fc..5695623859 100644 --- a/actioncable/lib/action_cable/connection/stream.rb +++ b/actioncable/lib/action_cable/connection/stream.rb @@ -1,3 +1,5 @@ +require 'thread' + module ActionCable module Connection #-- @@ -11,6 +13,7 @@ module ActionCable @stream_send = socket.env['stream.send'] @rack_hijack_io = nil + @write_lock = Mutex.new end def each(&callback) @@ -27,8 +30,10 @@ module ActionCable end def write(data) - return @rack_hijack_io.write(data) if @rack_hijack_io - return @stream_send.call(data) if @stream_send + @write_lock.synchronize do + return @rack_hijack_io.write(data) if @rack_hijack_io + return @stream_send.call(data) if @stream_send + end rescue EOFError, Errno::ECONNRESET @socket_object.client_gone end diff --git a/actionmailer/lib/action_mailer/base.rb b/actionmailer/lib/action_mailer/base.rb index e766221008..0f7c3b54e9 100644 --- a/actionmailer/lib/action_mailer/base.rb +++ b/actionmailer/lib/action_mailer/base.rb @@ -396,7 +396,7 @@ module ActionMailer # # * <tt>sendmail_settings</tt> - Allows you to override options for the <tt>:sendmail</tt> delivery method. # * <tt>:location</tt> - The location of the sendmail executable. Defaults to <tt>/usr/sbin/sendmail</tt>. - # * <tt>:arguments</tt> - The command line arguments. Defaults to <tt>-i -t</tt> with <tt>-f sender@address</tt> + # * <tt>:arguments</tt> - The command line arguments. Defaults to <tt>-i</tt> with <tt>-f sender@address</tt> # added automatically before the message is sent. # # * <tt>file_settings</tt> - Allows you to override options for the <tt>:file</tt> delivery method. diff --git a/actionmailer/lib/action_mailer/delivery_methods.rb b/actionmailer/lib/action_mailer/delivery_methods.rb index 571c8e7d2a..c78ff555f3 100644 --- a/actionmailer/lib/action_mailer/delivery_methods.rb +++ b/actionmailer/lib/action_mailer/delivery_methods.rb @@ -51,7 +51,7 @@ module ActionMailer # # add_delivery_method :sendmail, Mail::Sendmail, # location: '/usr/sbin/sendmail', - # arguments: '-i -t' + # arguments: '-i' def add_delivery_method(symbol, klass, default_options={}) class_attribute(:"#{symbol}_settings") unless respond_to?(:"#{symbol}_settings") send(:"#{symbol}_settings=", default_options) diff --git a/actionpack/lib/action_controller/metal/strong_parameters.rb b/actionpack/lib/action_controller/metal/strong_parameters.rb index b326695ce2..26794c67b7 100644 --- a/actionpack/lib/action_controller/metal/strong_parameters.rb +++ b/actionpack/lib/action_controller/metal/strong_parameters.rb @@ -572,20 +572,6 @@ module ActionController convert_value_to_parameters(@parameters.values_at(*keys)) end - # Returns an exact copy of the <tt>ActionController::Parameters</tt> - # instance. +permitted+ state is kept on the duped object. - # - # params = ActionController::Parameters.new(a: 1) - # params.permit! - # params.permitted? # => true - # copy_params = params.dup # => <ActionController::Parameters {"a"=>1} permitted: true> - # copy_params.permitted? # => true - def dup - super.tap do |duplicate| - duplicate.permitted = @permitted - end - end - # Returns a new <tt>ActionController::Parameters</tt> with all keys from # +other_hash+ merges into current hash. def merge(other_hash) @@ -783,6 +769,11 @@ module ActionController end end end + + def initialize_copy(source) + super + @parameters = @parameters.dup + end end # == Strong \Parameters diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb index dec9c60ef2..380a24a367 100644 --- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb @@ -64,7 +64,7 @@ module ActionDispatch # <tt>:httponly</tt>. class CookieStore < AbstractStore def initialize(app, options={}) - super(app, options.merge!(:cookie_only => true)) + super(app, options.merge!(cookie_only: true)) end def delete_session(req, session_id, options) diff --git a/actionpack/lib/action_dispatch/middleware/ssl.rb b/actionpack/lib/action_dispatch/middleware/ssl.rb index ab3077b308..0e04d3a524 100644 --- a/actionpack/lib/action_dispatch/middleware/ssl.rb +++ b/actionpack/lib/action_dispatch/middleware/ssl.rb @@ -18,17 +18,18 @@ module ActionDispatch # Enabled by default. Configure `config.ssl_options` with `hsts: false` to disable. # # Set `config.ssl_options` with `hsts: { … }` to configure HSTS: - # * `expires`: How long, in seconds, these settings will stick. Defaults to - # `180.days` (recommended). The minimum required to qualify for browser - # preload lists is `18.weeks`. + # * `expires`: How long, in seconds, these settings will stick. The minimum + # required to qualify for browser preload lists is `18.weeks`. Defaults to + # `180.days` (recommended). # * `subdomains`: Set to `true` to tell the browser to apply these settings # to all subdomains. This protects your cookies from interception by a - # vulnerable site on a subdomain. Defaults to `true`. + # vulnerable site on a subdomain. Defaults to `false`. # * `preload`: Advertise that this site may be included in browsers' # preloaded HSTS lists. HSTS protects your site on every visit *except the # first visit* since it hasn't seen your HSTS header yet. To close this # gap, browser vendors include a baked-in list of HSTS-enabled sites. # Go to https://hstspreload.appspot.com to submit your site for inclusion. + # Defaults to `false`. # # To turn off HSTS, omitting the header is not enough. Browsers will remember the # original HSTS directive until it expires. Instead, use the header to tell browsers to diff --git a/actionpack/lib/action_dispatch/routing/mapper.rb b/actionpack/lib/action_dispatch/routing/mapper.rb index e2cf75da3a..73b4864e45 100644 --- a/actionpack/lib/action_dispatch/routing/mapper.rb +++ b/actionpack/lib/action_dispatch/routing/mapper.rb @@ -1562,6 +1562,12 @@ module ActionDispatch options = path path, to = options.find { |name, _value| name.is_a?(String) } + if path.nil? + ActiveSupport::Deprecation.warn 'Omitting the route path is deprecated. '\ + 'Specify the path with a String or a Symbol instead.' + path = '' + end + case to when Symbol options[:action] = to diff --git a/actionpack/test/controller/parameters/dup_test.rb b/actionpack/test/controller/parameters/dup_test.rb new file mode 100644 index 0000000000..66bc8155c8 --- /dev/null +++ b/actionpack/test/controller/parameters/dup_test.rb @@ -0,0 +1,43 @@ +require 'abstract_unit' +require 'action_controller/metal/strong_parameters' + +class ParametersDupTest < ActiveSupport::TestCase + setup do + ActionController::Parameters.permit_all_parameters = false + + @params = ActionController::Parameters.new( + person: { + age: '32', + name: { + first: 'David', + last: 'Heinemeier Hansson' + }, + addresses: [{city: 'Chicago', state: 'Illinois'}] + } + ) + end + + test "a duplicate maintains the original's permitted status" do + @params.permit! + dupped_params = @params.dup + assert dupped_params.permitted? + end + + test "a duplicate maintains the original's parameters" do + @params.permit! + dupped_params = @params.dup + assert_equal @params.to_h, dupped_params.to_h + end + + test "changes to a duplicate's parameters do not affect the original" do + dupped_params = @params.dup + dupped_params.delete(:person) + assert_not_equal @params, dupped_params + end + + test "changes to a duplicate's permitted status do not affect the original" do + dupped_params = @params.dup + dupped_params.permit! + assert_not_equal @params, dupped_params + end +end diff --git a/actionpack/test/controller/parameters/parameters_permit_test.rb b/actionpack/test/controller/parameters/parameters_permit_test.rb index 2eed2996f6..2dd94c7230 100644 --- a/actionpack/test/controller/parameters/parameters_permit_test.rb +++ b/actionpack/test/controller/parameters/parameters_permit_test.rb @@ -245,11 +245,6 @@ class ParametersPermitTest < ActiveSupport::TestCase assert_equal "Jonas", @params[:person][:family][:brother] end - test "permit state is kept on a dup" do - @params.permit! - assert_equal @params.permitted?, @params.dup.permitted? - end - test "permit is recursive" do @params.permit! assert @params.permitted? diff --git a/actionpack/test/dispatch/response_test.rb b/actionpack/test/dispatch/response_test.rb index aa90433505..9eed796d3c 100644 --- a/actionpack/test/dispatch/response_test.rb +++ b/actionpack/test/dispatch/response_test.rb @@ -145,6 +145,26 @@ class ResponseTest < ActiveSupport::TestCase }, headers) end + test "content length" do + [100, 101, 102, 204].each do |c| + @response = ActionDispatch::Response.new + @response.status = c.to_s + @response.set_header "Content-Length", "0" + _, headers, _ = @response.to_a + assert !headers.has_key?("Content-Length"), "#{c} must not have a Content-Length header field" + end + end + + test "does not contain a message-body" do + [100, 101, 102, 204, 304].each do |c| + @response = ActionDispatch::Response.new + @response.status = c.to_s + @response.body = "Body must not be included" + _, _, body = @response.to_a + assert_empty body, "#{c} must not have a message-body but actually contains #{body}" + end + end + test "content type" do [204, 304].each do |c| @response = ActionDispatch::Response.new diff --git a/actionpack/test/dispatch/routing_test.rb b/actionpack/test/dispatch/routing_test.rb index 75fdc9469f..d54cdf7247 100644 --- a/actionpack/test/dispatch/routing_test.rb +++ b/actionpack/test/dispatch/routing_test.rb @@ -373,6 +373,9 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest post "create", :as => "" put "update" get "remove", :action => :destroy, :as => :remove + tc.assert_deprecated do + get action: :show, as: :show + end end end @@ -391,6 +394,10 @@ class TestRoutingMapper < ActionDispatch::IntegrationTest get '/pagemark/remove' assert_equal 'pagemarks#destroy', @response.body assert_equal '/pagemark/remove', pagemark_remove_path + + get '/pagemark' + assert_equal 'pagemarks#show', @response.body + assert_equal '/pagemark', pagemark_show_path end def test_admin diff --git a/activejob/test/cases/argument_serialization_test.rb b/activejob/test/cases/argument_serialization_test.rb index 59dc3d7f78..75b06ebde4 100644 --- a/activejob/test/cases/argument_serialization_test.rb +++ b/activejob/test/cases/argument_serialization_test.rb @@ -14,7 +14,7 @@ class ArgumentSerializationTest < ActiveSupport::TestCase [ 1, 'a' ], { 'a' => 1 } ].each do |arg| - test "serializes #{arg.class} verbatim" do + test "serializes #{arg.class} - #{arg} verbatim" do assert_arguments_unchanged arg end end diff --git a/activemodel/lib/active_model/type/boolean.rb b/activemodel/lib/active_model/type/boolean.rb index c1bce98c87..4e9d06a3ce 100644 --- a/activemodel/lib/active_model/type/boolean.rb +++ b/activemodel/lib/active_model/type/boolean.rb @@ -1,9 +1,20 @@ module ActiveModel module Type - class Boolean < Value # :nodoc: + # == Active \Model \Type \Boolean + # + # A class that behaves like a boolean type, including rules for coercion of user input. + # + # === Coercion + # Values set from user input will first be coerced into the appropriate ruby type. + # Coercion behavior is roughly mapped to Ruby's boolean semantics. + # + # - "false", "f" , "0", +0+ or any other value in +FALSE_VALUES+ will be coerced to +false+ + # - Empty strings are coerced to +nil+ + # - All other values will be coerced to +true+ + class Boolean < Value FALSE_VALUES = [false, 0, '0', 'f', 'F', 'false', 'FALSE', 'off', 'OFF'].to_set - def type + def type # :nodoc: :boolean end diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 8521d3b07b..c91e6662c9 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,26 @@ +* Using `group` with an attribute that has a custom type will properly cast + the hash keys after calling a calculation method like `count`. Fixes #25595. + + *Sean Griffin* + +* Fix the generated `#to_param` method to use `omission: ''` so that + the resulting output is actually up to 20 characters, not + effectively 17 to leave room for the default "...". + Also call `#parameterize` before `#truncate` and make the + `separator: /-/` to maximize the information included in the + output. + + Fixes #23635. + + *Rob Biedenharn* + +* Ensure concurrent invocations of the connection reaper cannot allocate the + same connection to two threads. + + Fixes #25585. + + *Matthew Draper* + * Inspecting an object with an associated array of over 10 elements no longer truncates the array, preventing `inspect` from looping infinitely in some cases. @@ -5,7 +28,7 @@ *Kevin McPhillips* * Removed the unused methods `ActiveRecord::Base.connection_id` and - `ActiveRecord::Base.connection_id=` + `ActiveRecord::Base.connection_id=`. *Sean Griffin* @@ -24,15 +47,15 @@ *Johannes Opper* -* Introduce ActiveRecord::TransactionSerializationError for catching +* Introduce `ActiveRecord::TransactionSerializationError` for catching transaction serialization failures or deadlocks. *Erol Fornoles* -* PostgreSQL: Fix db:structure:load silent failure on SQL error +* PostgreSQL: Fix db:structure:load silent failure on SQL error. - The command line flag "-v ON_ERROR_STOP=1" should be used - when invoking psql to make sure errors are not suppressed. + The command line flag `-v ON_ERROR_STOP=1` should be used + when invoking `psql` to make sure errors are not suppressed. Example: diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb index c341773be1..9b74c3a10f 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb @@ -74,7 +74,7 @@ module ActiveRecord #-- # Synchronization policy: # * all public methods can be called outside +synchronize+ - # * access to these i-vars needs to be in +synchronize+: + # * access to these instance variables needs to be in +synchronize+: # * @connections # * @now_connecting # * private methods that require being called in a +synchronize+ blocks @@ -329,13 +329,13 @@ module ActiveRecord # default max pool size to 5 @size = (spec.config[:pool] && spec.config[:pool].to_i) || 5 - # The cache of threads mapped to reserved connections, the sole purpose - # of the cache is to speed-up +connection+ method, it is not the authoritative - # registry of which thread owns which connection, that is tracked by - # +connection.owner+ attr on each +connection+ instance. + # This variable tracks the cache of threads mapped to reserved connections, with the + # sole purpose of speeding up the +connection+ method. It is not the authoritative + # registry of which thread owns which connection. Connection ownership is tracked by + # the +connection.owner+ attr on each +connection+ instance. # The invariant works like this: if there is mapping of <tt>thread => conn</tt>, - # then that +thread+ does indeed own that +conn+, however an absence of a such - # mapping does not mean that the +thread+ doesn't own the said connection, in + # then that +thread+ does indeed own that +conn+. However, an absence of a such + # mapping does not mean that the +thread+ doesn't own the said connection. In # that case +conn.owner+ attr should be consulted. # Access and modification of +@thread_cached_conns+ does not require # synchronization. @@ -364,10 +364,10 @@ module ActiveRecord @thread_cached_conns[connection_cache_key(Thread.current)] ||= checkout end - # Is there an open connection that is being used for the current thread? + # Returns true if there is an open connection being used for the current thread. # # This method only works for connections that have been obtained through - # #connection or #with_connection methods, connections obtained through + # #connection or #with_connection methods. Connections obtained through # #checkout will not be detected by #active_connection? def active_connection? @thread_cached_conns[connection_cache_key(Thread.current)] @@ -415,7 +415,10 @@ module ActiveRecord with_exclusively_acquired_all_connections(raise_on_acquisition_timeout) do synchronize do @connections.each do |conn| - checkin conn + if conn.in_use? + conn.steal! + checkin conn + end conn.disconnect! end @connections = [] @@ -426,9 +429,9 @@ module ActiveRecord # Disconnects all connections in the pool, and clears the pool. # - # The pool first tries to gain ownership of all connections, if unable to + # The pool first tries to gain ownership of all connections. If unable to # do so within a timeout interval (default duration is - # <tt>spec.config[:checkout_timeout] * 2</tt> seconds), the pool is forcefully + # <tt>spec.config[:checkout_timeout] * 2</tt> seconds), then the pool is forcefully # disconnected without any regard for other connection owning threads. def disconnect! disconnect(false) @@ -447,7 +450,10 @@ module ActiveRecord with_exclusively_acquired_all_connections(raise_on_acquisition_timeout) do synchronize do @connections.each do |conn| - checkin conn + if conn.in_use? + conn.steal! + checkin conn + end conn.disconnect! if conn.requires_reloading? end @connections.delete_if(&:requires_reloading?) @@ -474,9 +480,9 @@ module ActiveRecord # Clears the cache which maps classes and re-connects connections that # require reloading. # - # The pool first tries to gain ownership of all connections, if unable to + # The pool first tries to gain ownership of all connections. If unable to # do so within a timeout interval (default duration is - # <tt>spec.config[:checkout_timeout] * 2</tt> seconds), the pool forcefully + # <tt>spec.config[:checkout_timeout] * 2</tt> seconds), then the pool forcefully # clears the cache and reloads connections without any regard for other # connection owning threads. def clear_reloadable_connections! @@ -530,20 +536,20 @@ module ActiveRecord @available.delete conn # @available.any_waiting? => true means that prior to removing this - # conn, the pool was at its max size (@connections.size == @size) - # this would mean that any threads stuck waiting in the queue wouldn't + # conn, the pool was at its max size (@connections.size == @size). + # This would mean that any threads stuck waiting in the queue wouldn't # know they could checkout_new_connection, so let's do it for them. # Because condition-wait loop is encapsulated in the Queue class # (that in turn is oblivious to ConnectionPool implementation), threads - # that are "stuck" there are helpless, they have no way of creating + # that are "stuck" there are helpless. They have no way of creating # new connections and are completely reliant on us feeding available # connections into the Queue. needs_new_connection = @available.any_waiting? end # This is intentionally done outside of the synchronized section as we - # would like not to hold the main mutex while checking out new connections, - # thus there is some chance that needs_new_connection information is now + # would like not to hold the main mutex while checking out new connections. + # Thus there is some chance that needs_new_connection information is now # stale, we can live with that (bulk_make_new_connections will make # sure not to exceed the pool's @size limit). bulk_make_new_connections(1) if needs_new_connection @@ -556,17 +562,17 @@ module ActiveRecord stale_connections = synchronize do @connections.select do |conn| conn.in_use? && !conn.owner.alive? + end.each do |conn| + conn.steal! end end stale_connections.each do |conn| - synchronize do - if conn.active? - conn.reset! - checkin conn - else - remove conn - end + if conn.active? + conn.reset! + checkin conn + else + remove conn end end end @@ -698,7 +704,7 @@ module ActiveRecord def acquire_connection(checkout_timeout) # NOTE: we rely on +@available.poll+ and +try_to_checkout_new_connection+ to # +conn.lease+ the returned connection (and to do this in a +synchronized+ - # section), this is not the cleanest implementation, as ideally we would + # section). This is not the cleanest implementation, as ideally we would # <tt>synchronize { conn.lease }</tt> in this method, but by leaving it to +@available.poll+ # and +try_to_checkout_new_connection+ we can piggyback on +synchronize+ sections # of the said methods and avoid an additional +synchronize+ overhead. @@ -822,7 +828,7 @@ module ActiveRecord # should use. # # The ConnectionHandler class is not coupled with the Active models, as it has no knowlodge - # about the model. The model, needs to pass a specification name to the handler, + # about the model. The model needs to pass a specification name to the handler, # in order to lookup the correct connection pool. class ConnectionHandler def initialize @@ -890,7 +896,7 @@ module ActiveRecord # Remove the connection for this class. This will close the active # connection and the defined connection (if they exist). The result - # can be used as an argument for establish_connection, for easily + # can be used as an argument for #establish_connection, for easily # re-establishing the connection. def remove_connection(spec_name) if pool = owner_to_pool.delete(spec_name) diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb index eec0bc8518..396cb0b07a 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -179,7 +179,7 @@ module ActiveRecord # A Symbol can be used to specify the type of the generated primary key column. # [<tt>:primary_key</tt>] # The name of the primary key, if one is to be added automatically. - # Defaults to +id+. If <tt>:id</tt> is false this option is ignored. + # Defaults to +id+. If <tt>:id</tt> is false, then this option is ignored. # # Note that Active Record models will automatically detect their # primary key. This can be avoided by using @@ -305,9 +305,9 @@ module ActiveRecord # # Creates a table called 'assemblies_parts' with no id. # create_join_table(:assemblies, :parts) # - # You can pass a +options+ hash can include the following keys: + # You can pass an +options+ hash which can include the following keys: # [<tt>:table_name</tt>] - # Sets the table name overriding the default + # Sets the table name, overriding the default. # [<tt>:column_options</tt>] # Any extra options you want appended to the columns definition. # [<tt>:options</tt>] @@ -433,7 +433,7 @@ module ActiveRecord # t.remove_index :company_id # end # - # See also Table for details on all of the various column transformation. + # See also Table for details on all of the various column transformations. def change_table(table_name, options = {}) if supports_bulk_alter? && options[:bulk] recorder = ActiveRecord::Migration::CommandRecorder.new(self) @@ -483,10 +483,10 @@ module ActiveRecord # # Available options are (none of these exists by default): # * <tt>:limit</tt> - - # Requests a maximum column length. This is number of characters for a <tt>:string</tt> column + # Requests a maximum column length. This is the number of characters for a <tt>:string</tt> column # and number of bytes for <tt>:text</tt>, <tt>:binary</tt> and <tt>:integer</tt> columns. # * <tt>:default</tt> - - # The column's default value. Use nil for NULL. + # The column's default value. Use +nil+ for +NULL+. # * <tt>:null</tt> - # Allows or disallows +NULL+ values in the column. This option could # have been named <tt>:null_allowed</tt>. @@ -495,7 +495,7 @@ module ActiveRecord # * <tt>:scale</tt> - # Specifies the scale for the <tt>:decimal</tt> and <tt>:numeric</tt> columns. # - # Note: The precision is the total number of significant digits + # Note: The precision is the total number of significant digits, # and the scale is the number of digits that can be stored following # the decimal point. For example, the number 123.45 has a precision of 5 # and a scale of 2. A decimal with a precision of 5 and a scale of 2 can @@ -564,7 +564,7 @@ module ActiveRecord # # The +type+ and +options+ parameters will be ignored if present. It can be helpful # to provide these in a migration's +change+ method so it can be reverted. - # In that case, +type+ and +options+ will be used by add_column. + # In that case, +type+ and +options+ will be used by #add_column. def remove_column(table_name, column_name, type = nil, options = {}) execute "ALTER TABLE #{quote_table_name(table_name)} DROP #{quote_column_name(column_name)}" end @@ -952,13 +952,13 @@ module ActiveRecord # Checks to see if a foreign key exists on a table for a given foreign key definition. # - # # Check a foreign key exists + # # Checks to see if a foreign key exists. # foreign_key_exists?(:accounts, :branches) # - # # Check a foreign key on a specified column exists + # # Checks to see if a foreign key on a specified column exists. # foreign_key_exists?(:accounts, column: :owner_id) # - # # Check a foreign key with a custom name exists + # # Checks to see if a foreign key with a custom name exists. # foreign_key_exists?(:accounts, name: "special_fk_name") # def foreign_key_exists?(from_table, options_or_to_table = {}) @@ -1081,7 +1081,7 @@ module ActiveRecord end # Given a set of columns and an ORDER BY clause, returns the columns for a SELECT DISTINCT. - # PostgreSQL, MySQL, and Oracle overrides this for custom DISTINCT syntax - they + # PostgreSQL, MySQL, and Oracle override this for custom DISTINCT syntax - they # require the order columns appear in the SELECT. # # columns_for_distinct("posts.id", ["posts.created_at desc"]) diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index d4b9e301bc..5747e4d1ee 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -184,7 +184,30 @@ module ActiveRecord # this method must only be called while holding connection pool's mutex def expire - @owner = nil + if in_use? + if @owner != Thread.current + raise ActiveRecordError, "Cannot expire connection, " << + "it is owned by a different thread: #{@owner}. " << + "Current thread: #{Thread.current}." + end + + @owner = nil + else + raise ActiveRecordError, 'Cannot expire connection, it is not currently leased.' + end + end + + # this method must only be called while holding connection pool's mutex (and a desire for segfaults) + def steal! # :nodoc: + if in_use? + if @owner != Thread.current + pool.send :remove_connection_from_thread_cache, self, @owner + + @owner = Thread.current + end + else + raise ActiveRecordError, 'Cannot steal connection, it is not currently leased.' + end end def unprepared_statement diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb index eb2268157b..3384012c49 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb @@ -159,7 +159,7 @@ module ActiveRecord end # Returns 62. SQLite supports index names up to 64 - # characters. The rest is used by rails internally to perform + # characters. The rest is used by Rails internally to perform # temporary rename operations def allowed_index_name_length index_name_length - 2 diff --git a/activerecord/lib/active_record/integration.rb b/activerecord/lib/active_record/integration.rb index 466c8509a4..d729deb07b 100644 --- a/activerecord/lib/active_record/integration.rb +++ b/activerecord/lib/active_record/integration.rb @@ -86,7 +86,7 @@ module ActiveRecord # # user = User.find_by(name: 'David Heinemeier Hansson') # user.id # => 125 - # user_path(user) # => "/users/125-david" + # user_path(user) # => "/users/125-david-heinemeier" # # Because the generated param begins with the record's +id+, it is # suitable for passing to +find+. In a controller, for example: @@ -100,7 +100,7 @@ module ActiveRecord define_method :to_param do if (default = super()) && (result = send(method_name).to_s).present? && - (param = result.squish.truncate(20, separator: /\s/, omission: nil).parameterize).present? + (param = result.squish.parameterize.truncate(20, separator: /-/, omission: '')).present? "#{default}-#{param}" else default diff --git a/activerecord/lib/active_record/model_schema.rb b/activerecord/lib/active_record/model_schema.rb index 7996c32bbc..114686c5d3 100644 --- a/activerecord/lib/active_record/model_schema.rb +++ b/activerecord/lib/active_record/model_schema.rb @@ -282,8 +282,12 @@ module ActiveRecord # # +attr_name+ The name of the attribute to retrieve the type for. Must be # a string - def type_for_attribute(attr_name) - attribute_types[attr_name] + def type_for_attribute(attr_name, &block) + if block + attribute_types.fetch(attr_name, &block) + else + attribute_types[attr_name] + end end # Returns a hash where the keys are column names and the values are diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index ebdb9efba2..510e8a6e43 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -480,10 +480,10 @@ module ActiveRecord # def touch(*names, time: nil) unless persisted? - raise ActiveRecordError, <<-end_error.strip_heredoc + raise ActiveRecordError, <<-MSG.squish cannot touch on a new or destroyed record object. Consider using persisted?, new_record?, or destroyed? before touching - end_error + MSG end time ||= current_time_from_proper_timezone diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index 98ea425d16..2c0ca62924 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -3,7 +3,7 @@ require "rails" require "active_model/railtie" # For now, action_controller must always be present with -# rails, so let's make sure that it gets required before +# Rails, so let's make sure that it gets required before # here. This is needed for correctly setting up the middleware. # In the future, this might become an optional require. require "action_controller/railtie" diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index d6d92b8607..a97b71815a 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -312,8 +312,10 @@ module ActiveRecord Hash[calculated_data.map do |row| key = group_columns.map { |aliaz, col_name| - column = calculated_data.column_types.fetch(aliaz) do - type_for(col_name) + column = type_for(col_name) do + calculated_data.column_types.fetch(aliaz) do + Type::Value.new + end end type_cast_calculated_value(row[aliaz], column) } @@ -346,9 +348,9 @@ module ActiveRecord @klass.connection.table_alias_for(table_name) end - def type_for(field) + def type_for(field, &block) field_name = field.respond_to?(:name) ? field.name.to_s : field.to_s.split('.').last - @klass.type_for_attribute(field_name) + @klass.type_for_attribute(field_name, &block) end def type_cast_calculated_value(value, type, operation = nil) diff --git a/activerecord/lib/active_record/touch_later.rb b/activerecord/lib/active_record/touch_later.rb index 5c41ab6e39..598873ea3a 100644 --- a/activerecord/lib/active_record/touch_later.rb +++ b/activerecord/lib/active_record/touch_later.rb @@ -9,10 +9,10 @@ module ActiveRecord def touch_later(*names) # :nodoc: unless persisted? - raise ActiveRecordError, <<-end_error.strip_heredoc + raise ActiveRecordError, <<-MSG.squish cannot touch on a new or destroyed record object. Consider using persisted?, new_record?, or destroyed? before touching - end_error + MSG end @_defer_touch_attrs ||= timestamp_attributes_for_update_in_model diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index cfae700159..6acfec0621 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -1,4 +1,5 @@ require "cases/helper" +require "models/book" require 'models/club' require 'models/company' require "models/contract" @@ -25,7 +26,7 @@ class NumericData < ActiveRecord::Base end class CalculationsTest < ActiveRecord::TestCase - fixtures :companies, :accounts, :topics, :speedometers, :minivans + fixtures :companies, :accounts, :topics, :speedometers, :minivans, :books def test_should_sum_field assert_equal 318, Account.sum(:credit_limit) @@ -793,4 +794,8 @@ class CalculationsTest < ActiveRecord::TestCase assert_equal 50, result[1].credit_limit assert_equal 50, result[2].credit_limit end + + def test_group_by_attribute_with_custom_type + assert_equal({ "proposed" => 2, "published" => 2 }, Book.group(:status).count) + end end diff --git a/activerecord/test/cases/connection_pool_test.rb b/activerecord/test/cases/connection_pool_test.rb index a45ee281c7..09e7848bda 100644 --- a/activerecord/test/cases/connection_pool_test.rb +++ b/activerecord/test/cases/connection_pool_test.rb @@ -151,7 +151,7 @@ module ActiveRecord assert_equal 1, active_connections(@pool).size ensure - @pool.connections.each(&:close) + @pool.connections.each { |conn| conn.close if conn.in_use? } end def test_remove_connection @@ -432,6 +432,9 @@ module ActiveRecord Thread.new { @pool.send(group_action_method) }.join # assert connection has been forcefully taken away from us assert_not @pool.active_connection? + + # make a new connection for with_connection to clean up + @pool.connection end end end diff --git a/activerecord/test/cases/integration_test.rb b/activerecord/test/cases/integration_test.rb index 08a186ae07..97a0cdb5db 100644 --- a/activerecord/test/cases/integration_test.rb +++ b/activerecord/test/cases/integration_test.rb @@ -29,10 +29,30 @@ class IntegrationTest < ActiveRecord::TestCase assert_equal '4-flamboyant-software', firm.to_param end + def test_to_param_class_method_truncates_words_properly + firm = Firm.find(4) + firm.name << ', Inc.' + assert_equal '4-flamboyant-software', firm.to_param + end + + def test_to_param_class_method_truncates_after_parameterize + firm = Firm.find(4) + firm.name = "Huey, Dewey, & Louie LLC" + # 123456789T123456789v + assert_equal '4-huey-dewey-louie-llc', firm.to_param + end + + def test_to_param_class_method_truncates_after_parameterize_with_hyphens + firm = Firm.find(4) + firm.name = "Door-to-Door Wash-n-Fold Service" + # 123456789T123456789v + assert_equal '4-door-to-door-wash-n', firm.to_param + end + def test_to_param_class_method_truncates firm = Firm.find(4) firm.name = 'a ' * 100 - assert_equal '4-a-a-a-a-a-a-a-a-a', firm.to_param + assert_equal '4-a-a-a-a-a-a-a-a-a-a', firm.to_param end def test_to_param_class_method_truncates_edge_case @@ -41,10 +61,16 @@ class IntegrationTest < ActiveRecord::TestCase assert_equal '4-david', firm.to_param end + def test_to_param_class_method_truncates_case_shown_in_doc + firm = Firm.find(4) + firm.name = 'David Heinemeier Hansson' + assert_equal '4-david-heinemeier', firm.to_param + end + def test_to_param_class_method_squishes firm = Firm.find(4) firm.name = "ab \n" * 100 - assert_equal '4-ab-ab-ab-ab-ab-ab', firm.to_param + assert_equal '4-ab-ab-ab-ab-ab-ab-ab', firm.to_param end def test_to_param_class_method_multibyte_character diff --git a/activerecord/test/cases/mixin_test.rb b/activerecord/test/cases/mixin_test.rb index 7ebdcac711..06af75af0f 100644 --- a/activerecord/test/cases/mixin_test.rb +++ b/activerecord/test/cases/mixin_test.rb @@ -41,13 +41,12 @@ class TouchTest < ActiveRecord::TestCase old_updated_at = stamped.updated_at - travel 5.minutes do - stamped.lft_will_change! - stamped.save + travel 5.minutes + stamped.lft_will_change! + stamped.save - assert_equal Time.now, stamped.updated_at - assert_equal old_updated_at, stamped.created_at - end + assert_equal Time.now, stamped.updated_at + assert_equal old_updated_at, stamped.created_at end def test_create_turned_off diff --git a/activesupport/CHANGELOG.md b/activesupport/CHANGELOG.md index db439b5732..a8d875640e 100644 --- a/activesupport/CHANGELOG.md +++ b/activesupport/CHANGELOG.md @@ -1,3 +1,37 @@ +* Fix `ActiveSupport::TimeZone#strptime`. Now raises `ArgumentError` when the + given time doesn't match the format. The error is the same as the one given + by Ruby's `Date.strptime`. Previously it raised + `NoMethodError: undefined method empty? for nil:NilClass.` due to a bug. + + Fixes #25701. + + *John Gesimondo* + +* `travel/travel_to` travel time helpers, now raise on nested calls, + as this can lead to confusing time stubbing. + + Instead of: + + travel_to 2.days.from_now do + # 2 days from today + travel_to 3.days.from_now do + # 5 days from today + end + end + + preferred way to achieve above is: + + travel 2.days do + # 2 days from today + end + + travel 5.days do + # 5 days from today + end + + *Vipul A M* + + * Support parsing JSON time in ISO8601 local time strings in `ActiveSupport::JSON.decode` when `parse_json_times` is enabled. Strings in the format of `YYYY-MM-DD hh:mm:ss` (without a `Z` at diff --git a/activesupport/lib/active_support/core_ext/class/attribute.rb b/activesupport/lib/active_support/core_ext/class/attribute.rb index 802d988af2..aa0e2a1a88 100644 --- a/activesupport/lib/active_support/core_ext/class/attribute.rb +++ b/activesupport/lib/active_support/core_ext/class/attribute.rb @@ -27,7 +27,7 @@ class Class # This matches normal Ruby method inheritance: think of writing an attribute # on a subclass as overriding the reader method. However, you need to be aware # when using +class_attribute+ with mutable structures as +Array+ or +Hash+. - # In such cases, you don't want to do changes in places but use setters: + # In such cases, you don't want to do changes in place. Instead use setters: # # Base.setting = [] # Base.setting # => [] diff --git a/activesupport/lib/active_support/duration/iso8601_serializer.rb b/activesupport/lib/active_support/duration/iso8601_serializer.rb index 05c6a083a9..eb8136e208 100644 --- a/activesupport/lib/active_support/duration/iso8601_serializer.rb +++ b/activesupport/lib/active_support/duration/iso8601_serializer.rb @@ -12,8 +12,10 @@ module ActiveSupport # Builds and returns output string. def serialize - output = 'P' parts, sign = normalize + return "PT0S".freeze if parts.empty? + + output = 'P' output << "#{parts[:years]}Y" if parts.key?(:years) output << "#{parts[:months]}M" if parts.key?(:months) output << "#{parts[:weeks]}W" if parts.key?(:weeks) diff --git a/activesupport/lib/active_support/testing/time_helpers.rb b/activesupport/lib/active_support/testing/time_helpers.rb index ef27ce8eb5..41dff281ef 100644 --- a/activesupport/lib/active_support/testing/time_helpers.rb +++ b/activesupport/lib/active_support/testing/time_helpers.rb @@ -1,32 +1,39 @@ +require 'active_support/core_ext/string/strip' # for strip_heredoc +require 'concurrent/map' + module ActiveSupport module Testing class SimpleStubs # :nodoc: Stub = Struct.new(:object, :method_name, :original_method) def initialize - @stubs = {} + @stubs = Concurrent::Map.new { |h, k| h[k] = {} } end def stub_object(object, method_name, return_value) - key = [object.object_id, method_name] - - if stub = @stubs[key] + if stub = stubbing(object, method_name) unstub_object(stub) end new_name = "__simple_stub__#{method_name}" - @stubs[key] = Stub.new(object, method_name, new_name) + @stubs[object.object_id][method_name] = Stub.new(object, method_name, new_name) object.singleton_class.send :alias_method, new_name, method_name object.define_singleton_method(method_name) { return_value } end def unstub_all! - @stubs.each_value do |stub| - unstub_object(stub) + @stubs.each_value do |object_stubs| + object_stubs.each_value do |stub| + unstub_object(stub) + end end - @stubs = {} + @stubs.clear + end + + def stubbing(object, method_name) + @stubs[object.object_id][method_name] end private @@ -93,6 +100,34 @@ module ActiveSupport # end # Time.current # => Sat, 09 Nov 2013 15:34:49 EST -05:00 def travel_to(date_or_time) + if block_given? && simple_stubs.stubbing(Time, :now) + travel_to_nested_block_call = <<-MSG.strip_heredoc + + Calling `travel_to` with a block, when we have previously already made a call to `travel_to`, can lead to confusing time stubbing. + + Instead of: + + travel_to 2.days.from_now do + # 2 days from today + travel_to 3.days.from_now do + # 5 days from today + end + end + + preferred way to achieve above is: + + travel 2.days do + # 2 days from today + end + + travel 5.days do + # 5 days from today + end + + MSG + raise travel_to_nested_block_call + end + if date_or_time.is_a?(Date) && !date_or_time.is_a?(DateTime) now = date_or_time.midnight.to_time else diff --git a/activesupport/lib/active_support/values/time_zone.rb b/activesupport/lib/active_support/values/time_zone.rb index 19420cee5e..eb89a6d4c5 100644 --- a/activesupport/lib/active_support/values/time_zone.rb +++ b/activesupport/lib/active_support/values/time_zone.rb @@ -447,6 +447,7 @@ module ActiveSupport private def parts_to_time(parts, now) + raise ArgumentError, "invalid date" if parts.nil? return if parts.empty? time = Time.new( diff --git a/activesupport/test/caching_test.rb b/activesupport/test/caching_test.rb index ec7d028d7e..8002c14539 100644 --- a/activesupport/test/caching_test.rb +++ b/activesupport/test/caching_test.rb @@ -3,6 +3,8 @@ require 'abstract_unit' require 'active_support/cache' require 'dependencies_test_helpers' +require 'pathname' + module ActiveSupport module Cache module Strategy diff --git a/activesupport/test/core_ext/duration_test.rb b/activesupport/test/core_ext/duration_test.rb index 502e2811fa..a24915dfef 100644 --- a/activesupport/test/core_ext/duration_test.rb +++ b/activesupport/test/core_ext/duration_test.rb @@ -279,6 +279,7 @@ class DurationTest < ActiveSupport::TestCase ['PT1S', 1.second ], ['PT1.4S', (1.4).seconds ], ['P1Y1M1DT1H', 1.year + 1.month + 1.day + 1.hour], + ['PT0S', 0.minutes ], ] expectations.each do |expected_output, duration| assert_equal expected_output, duration.iso8601, expected_output.inspect diff --git a/activesupport/test/time_travel_test.rb b/activesupport/test/time_travel_test.rb index 59c3e52c2f..e9f87bdf82 100644 --- a/activesupport/test/time_travel_test.rb +++ b/activesupport/test/time_travel_test.rb @@ -77,6 +77,49 @@ class TimeTravelTest < ActiveSupport::TestCase end end + def test_time_helper_travel_to_with_nested_calls_with_blocks + Time.stub(:now, Time.now) do + outer_expected_time = Time.new(2004, 11, 24, 01, 04, 44) + inner_expected_time = Time.new(2004, 10, 24, 01, 04, 44) + travel_to outer_expected_time do + assert_raises(RuntimeError, /Calling `travel_to` with a block, when we have previously already made a call to `travel_to`, can lead to confusing time stubbing./) do + travel_to(inner_expected_time) do + #noop + end + end + end + end + end + + def test_time_helper_travel_to_with_nested_calls + Time.stub(:now, Time.now) do + outer_expected_time = Time.new(2004, 11, 24, 01, 04, 44) + inner_expected_time = Time.new(2004, 10, 24, 01, 04, 44) + travel_to outer_expected_time do + assert_nothing_raised do + travel_to(inner_expected_time) + + assert_equal inner_expected_time, Time.now + end + end + end + end + + def test_time_helper_travel_to_with_subsequent_calls + Time.stub(:now, Time.now) do + initial_expected_time = Time.new(2004, 11, 24, 01, 04, 44) + subsequent_expected_time = Time.new(2004, 10, 24, 01, 04, 44) + assert_nothing_raised do + travel_to initial_expected_time + travel_to subsequent_expected_time + + assert_equal subsequent_expected_time, Time.now + + travel_back + end + end + end + def test_travel_to_will_reset_the_usec_to_avoid_mysql_rouding Time.stub(:now, Time.now) do travel_to Time.utc(2014, 10, 10, 10, 10, 50, 999999) do diff --git a/activesupport/test/time_zone_test.rb b/activesupport/test/time_zone_test.rb index a15d5c6a0e..76cbb5ce8b 100644 --- a/activesupport/test/time_zone_test.rb +++ b/activesupport/test/time_zone_test.rb @@ -388,6 +388,13 @@ class TimeZoneTest < ActiveSupport::TestCase end end + def test_strptime_with_malformed_string + with_env_tz 'US/Eastern' do + zone = ActiveSupport::TimeZone['Eastern Time (US & Canada)'] + assert_raise(ArgumentError) { zone.strptime('1999-12-31', '%Y/%m/%d') } + end + end + def test_utc_offset_lazy_loaded_from_tzinfo_when_not_passed_in_to_initialize tzinfo = TZInfo::Timezone.get('America/New_York') zone = ActiveSupport::TimeZone.create(tzinfo.name, nil, tzinfo) diff --git a/guides/bug_report_templates/action_controller_gem.rb b/guides/bug_report_templates/action_controller_gem.rb index 604cf4be41..e22c9327a4 100644 --- a/guides/bug_report_templates/action_controller_gem.rb +++ b/guides/bug_report_templates/action_controller_gem.rb @@ -8,7 +8,7 @@ end gemfile(true) do source 'https://rubygems.org' # Activate the gem you are reporting the issue against. - gem 'rails', '5.0.0.rc1' + gem 'rails', '5.0.0' end require 'rack/test' diff --git a/guides/bug_report_templates/active_record_gem.rb b/guides/bug_report_templates/active_record_gem.rb index d4ede4e2c1..46fd2f1aae 100644 --- a/guides/bug_report_templates/active_record_gem.rb +++ b/guides/bug_report_templates/active_record_gem.rb @@ -8,7 +8,7 @@ end gemfile(true) do source 'https://rubygems.org' # Activate the gem you are reporting the issue against. - gem 'activerecord', '5.0.0.rc1' + gem 'activerecord', '5.0.0' gem 'sqlite3' end diff --git a/guides/bug_report_templates/generic_gem.rb b/guides/bug_report_templates/generic_gem.rb index bb8af3be18..2aaaf10615 100644 --- a/guides/bug_report_templates/generic_gem.rb +++ b/guides/bug_report_templates/generic_gem.rb @@ -8,7 +8,7 @@ end gemfile(true) do source 'https://rubygems.org' # Activate the gem you are reporting the issue against. - gem 'activesupport', '5.0.0.rc1' + gem 'activesupport', '5.0.0' end require 'active_support/core_ext/object/blank' diff --git a/guides/source/action_cable_overview.md b/guides/source/action_cable_overview.md index 2308befd12..0d00b7f07b 100644 --- a/guides/source/action_cable_overview.md +++ b/guides/source/action_cable_overview.md @@ -9,7 +9,9 @@ After reading this guide, you will know: * What Action Cable is and its integration on backend and frontend * How to setup Action Cable * How to setup channels -* Deployment and Architecture setup for running Action Cable +* Deployment and Architecture setup for running Action Cable + +-------------------------------------------------------------------------------- Introduction ------------ diff --git a/guides/source/action_mailer_basics.md b/guides/source/action_mailer_basics.md index 7359438025..34847832fd 100644 --- a/guides/source/action_mailer_basics.md +++ b/guides/source/action_mailer_basics.md @@ -735,7 +735,7 @@ files (environment.rb, production.rb, etc...) |---------------|-------------| |`logger`|Generates information on the mailing run if available. Can be set to `nil` for no logging. Compatible with both Ruby's own `Logger` and `Log4r` loggers.| |`smtp_settings`|Allows detailed configuration for `:smtp` delivery method:<ul><li>`:address` - Allows you to use a remote mail server. Just change it from its default `"localhost"` setting.</li><li>`:port` - On the off chance that your mail server doesn't run on port 25, you can change it.</li><li>`:domain` - If you need to specify a HELO domain, you can do it here.</li><li>`:user_name` - If your mail server requires authentication, set the username in this setting.</li><li>`:password` - If your mail server requires authentication, set the password in this setting.</li><li>`:authentication` - If your mail server requires authentication, you need to specify the authentication type here. This is a symbol and one of `:plain` (will send the password in the clear), `:login` (will send password Base64 encoded) or `:cram_md5` (combines a Challenge/Response mechanism to exchange information and a cryptographic Message Digest 5 algorithm to hash important information)</li><li>`:enable_starttls_auto` - Detects if STARTTLS is enabled in your SMTP server and starts to use it. Defaults to `true`.</li><li>`:openssl_verify_mode` - When using TLS, you can set how OpenSSL checks the certificate. This is really useful if you need to validate a self-signed and/or a wildcard certificate. You can use the name of an OpenSSL verify constant ('none' or 'peer') or directly the constant (`OpenSSL::SSL::VERIFY_NONE` or `OpenSSL::SSL::VERIFY_PEER`).</li></ul>| -|`sendmail_settings`|Allows you to override options for the `:sendmail` delivery method.<ul><li>`:location` - The location of the sendmail executable. Defaults to `/usr/sbin/sendmail`.</li><li>`:arguments` - The command line arguments to be passed to sendmail. Defaults to `-i -t`.</li></ul>| +|`sendmail_settings`|Allows you to override options for the `:sendmail` delivery method.<ul><li>`:location` - The location of the sendmail executable. Defaults to `/usr/sbin/sendmail`.</li><li>`:arguments` - The command line arguments to be passed to sendmail. Defaults to `-i`.</li></ul>| |`raise_delivery_errors`|Whether or not errors should be raised if the email fails to be delivered. This only works if the external email server is configured for immediate delivery.| |`delivery_method`|Defines a delivery method. Possible values are:<ul><li>`:smtp` (default), can be configured by using `config.action_mailer.smtp_settings`.</li><li>`:sendmail`, can be configured by using `config.action_mailer.sendmail_settings`.</li><li>`:file`: save emails to files; can be configured by using `config.action_mailer.file_settings`.</li><li>`:test`: save emails to `ActionMailer::Base.deliveries` array.</li></ul>See [API docs](http://api.rubyonrails.org/classes/ActionMailer/Base.html) for more info.| |`perform_deliveries`|Determines whether deliveries are actually carried out when the `deliver` method is invoked on the Mail message. By default they are, but this can be turned off to help functional testing.| @@ -756,7 +756,7 @@ config.action_mailer.delivery_method = :sendmail # Defaults to: # config.action_mailer.sendmail_settings = { # location: '/usr/sbin/sendmail', -# arguments: '-i -t' +# arguments: '-i' # } config.action_mailer.perform_deliveries = true config.action_mailer.raise_delivery_errors = true diff --git a/guides/source/action_view_overview.md b/guides/source/action_view_overview.md index f68abbae3c..e11466e79f 100644 --- a/guides/source/action_view_overview.md +++ b/guides/source/action_view_overview.md @@ -1439,7 +1439,7 @@ Formats a number with the specified level of `precision`, which defaults to 3. ```ruby number_with_precision(111.2345) # => 111.235 -number_with_precision(111.2345, 2) # => 111.23 +number_with_precision(111.2345, precision: 2) # => 111.23 ``` ### SanitizeHelper diff --git a/guides/source/configuring.md b/guides/source/configuring.md index 59cf412c5f..34878e5c38 100644 --- a/guides/source/configuring.md +++ b/guides/source/configuring.md @@ -297,7 +297,9 @@ All these configuration options are delegated to the `I18n` library. * Or you can set different fallbacks for locales individually. For example, if you want to use `:tr` for `:az` and `:de`, `:en` for `:da` as fallbacks, you can do it, like so: ```ruby - config.i18n.fallbacks = { az: :tr, da: [:de, :en] } + config.i18n.fallbacks = { az: :tr, da: [:de, :en] } + #or + config.i18n.fallbacks.map = { az: :tr, da: [:de, :en] } ``` ### Configuring Active Record @@ -531,7 +533,7 @@ There are a number of settings available on `config.action_mailer`: * `config.action_mailer.sendmail_settings` allows detailed configuration for the `sendmail` delivery method. It accepts a hash of options, which can include any of these options: * `:location` - The location of the sendmail executable. Defaults to `/usr/sbin/sendmail`. - * `:arguments` - The command line arguments. Defaults to `-i -t`. + * `:arguments` - The command line arguments. Defaults to `-i`. * `config.action_mailer.raise_delivery_errors` specifies whether to raise an error if email delivery cannot be completed. It defaults to `true`. diff --git a/guides/source/initialization.md b/guides/source/initialization.md index 89e5346d86..a2eec03eba 100644 --- a/guides/source/initialization.md +++ b/guides/source/initialization.md @@ -16,7 +16,7 @@ After reading this guide, you will know: -------------------------------------------------------------------------------- This guide goes through every method call that is -required to boot up the Ruby on Rails stack for a default Rails 4 +required to boot up the Ruby on Rails stack for a default Rails application, explaining each part in detail along the way. For this guide, we will be focusing on what happens when you execute `rails server` to boot your app. @@ -464,7 +464,7 @@ The `options[:config]` value defaults to `config.ru` which contains this: ```ruby # This file is used by Rack-based servers to start the application. -require ::File.expand_path('../config/environment', __FILE__) +require_relative 'config/environment' run <%= app_const %> ``` @@ -485,7 +485,7 @@ end The `initialize` method of `Rack::Builder` will take the block here and execute it within an instance of `Rack::Builder`. This is where the majority of the initialization process of Rails happens. The `require` line for `config/environment.rb` in `config.ru` is the first to run: ```ruby -require ::File.expand_path('../config/environment', __FILE__) +require_relative 'config/environment' ``` ### `config/environment.rb` @@ -495,7 +495,7 @@ This file is the common file required by `config.ru` (`rails server`) and Passen This file begins with requiring `config/application.rb`: ```ruby -require File.expand_path('../application', __FILE__) +require_relative 'application' ``` ### `config/application.rb` @@ -503,7 +503,7 @@ require File.expand_path('../application', __FILE__) This file requires `config/boot.rb`: ```ruby -require File.expand_path('../boot', __FILE__) +require_relative 'boot' ``` But only if it hasn't been required before, which would be the case in `rails server` diff --git a/guides/source/plugins.md b/guides/source/plugins.md index 8f055f8fe3..ff84861b8c 100644 --- a/guides/source/plugins.md +++ b/guides/source/plugins.md @@ -30,7 +30,7 @@ Setup ----- Currently, Rails plugins are built as gems, _gemified plugins_. They can be shared across -different rails applications using RubyGems and Bundler if desired. +different Rails applications using RubyGems and Bundler if desired. ### Generate a gemified plugin. diff --git a/guides/source/rails_on_rack.md b/guides/source/rails_on_rack.md index 8148f70c31..ed935e1008 100644 --- a/guides/source/rails_on_rack.md +++ b/guides/source/rails_on_rack.md @@ -64,7 +64,7 @@ To use `rackup` instead of Rails' `rails server`, you can put the following insi ```ruby # Rails.root/config.ru -require ::File.expand_path('../config/environment', __FILE__) +require_relative 'config/environment' run Rails.application ``` diff --git a/guides/source/security.md b/guides/source/security.md index ca985134e6..2d1bc3b5b3 100644 --- a/guides/source/security.md +++ b/guides/source/security.md @@ -249,7 +249,7 @@ There are many other possibilities, like using a `<script>` tag to make a cross- Note: We can't distinguish a `<script>` tag's origin—whether it's a tag on your own site or on some other malicious site—so we must block all `<script>` across the board, even if it's actually a safe same-origin script served from your own site. In these cases, explicitly skip CSRF protection on actions that serve JavaScript meant for a `<script>` tag. -To protect against all other forged requests, we introduce a _required security token_ that our site knows but other sites don't know. We include the security token in requests and verify it on the server. This is a one-liner in your application controller, and is the default for newly created rails applications: +To protect against all other forged requests, we introduce a _required security token_ that our site knows but other sites don't know. We include the security token in requests and verify it on the server. This is a one-liner in your application controller, and is the default for newly created Rails applications: ```ruby protect_from_forgery with: :exception diff --git a/guides/source/testing.md b/guides/source/testing.md index e8dc6ffe2a..440d87bf73 100644 --- a/guides/source/testing.md +++ b/guides/source/testing.md @@ -851,12 +851,25 @@ cookies["are_good_for_u"] cookies[:are_good_for_u] ### Instance Variables Available -You also have access to three instance variables in your functional tests: +You also have access to three instance variables in your functional tests, after a request is made: * `@controller` - The controller processing the request * `@request` - The request object * `@response` - The response object + +```ruby +class ArticlesControllerTest < ActionDispatch::IntegrationTest + test "should get index" do + get articles_url + + assert_equal "index", @controller.action_name + assert_equal "application/x-www-form-urlencoded", @request.media_type + assert_match "Articles", @response.body + end +end +``` + ### Setting Headers and CGI variables [HTTP headers](http://tools.ietf.org/search/rfc2616#section-5.3) diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md index c41876cd28..2ac5a2188b 100644 --- a/guides/source/upgrading_ruby_on_rails.md +++ b/guides/source/upgrading_ruby_on_rails.md @@ -1185,7 +1185,7 @@ Please read [Pull Request #9978](https://github.com/rails/rails/pull/9978) for d * Rails 4.0 has deprecated `ActionController::Base.page_cache_extension` option. Use `ActionController::Base.default_static_extension` instead. -* Rails 4.0 has removed Action and Page caching from Action Pack. You will need to add the `actionpack-action_caching` gem in order to use `caches_action` and the `actionpack-page_caching` to use `caches_pages` in your controllers. +* Rails 4.0 has removed Action and Page caching from Action Pack. You will need to add the `actionpack-action_caching` gem in order to use `caches_action` and the `actionpack-page_caching` to use `caches_page` in your controllers. * Rails 4.0 has removed the XML parameters parser. You will need to add the `actionpack-xml_parser` gem if you require this feature. diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index 243f40a057..f6552a268b 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,3 +1,13 @@ +* Set the server host using the `HOST` environment variable. + + *mahnunchik* + +* Add public API to register new folders for `rake notes`: + + config.annotations.register_directories('spec', 'features') + + *John Meehan* + * Do not run `bundle install` when generating a new plugin. Since bundler 1.12.0, the gemspec is validated so the `bundle install` @@ -7,7 +17,7 @@ *Rafael Mendonça França* * Default `config.assets.quiet = true` in the development environment. Suppress - logging of `sprockets-rails` requests by default. + logging of assets requests by default. *Kevin McPhillips* diff --git a/railties/lib/rails.rb b/railties/lib/rails.rb index fe789f3c2a..c024fb6641 100644 --- a/railties/lib/rails.rb +++ b/railties/lib/rails.rb @@ -52,7 +52,7 @@ module Rails end end - # Returns a Pathname object of the current rails project, + # Returns a Pathname object of the current Rails project, # otherwise it returns nil if there is no project: # # Rails.root @@ -77,7 +77,7 @@ module Rails @_env = ActiveSupport::StringInquirer.new(environment) end - # Returns all rails groups for loading based on: + # Returns all Rails groups for loading based on: # # * The Rails environment; # * The environment variable RAILS_GROUPS; @@ -100,7 +100,7 @@ module Rails end # Returns a Pathname object of the public folder of the current - # rails project, otherwise it returns nil if there is no project: + # Rails project, otherwise it returns nil if there is no project: # # Rails.public_path # # => #<Pathname:/Users/someuser/some/path/project/public> diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index 5ee08d96e1..8e3f01edd7 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -206,6 +206,10 @@ module Rails } end end + + def respond_to_missing?(symbol, *) + true + end end end end diff --git a/railties/lib/rails/commands/server.rb b/railties/lib/rails/commands/server.rb index 7418dff18b..f641d9bf2c 100644 --- a/railties/lib/rails/commands/server.rb +++ b/railties/lib/rails/commands/server.rb @@ -90,6 +90,7 @@ module Rails def default_options super.merge({ Port: ENV.fetch('PORT', 3000).to_i, + Host: ENV.fetch('HOST', 'localhost').dup, DoNotReverseLookup: true, environment: (ENV['RAILS_ENV'] || ENV['RACK_ENV'] || "development").dup, daemonize: false, diff --git a/railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml b/railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml index bd5c0b10f6..145cfb7f74 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml +++ b/railties/lib/rails/generators/rails/app/templates/config/databases/postgresql.yml @@ -17,7 +17,7 @@ default: &default adapter: postgresql encoding: unicode - # For details on connection pooling, see rails configuration guide + # For details on connection pooling, see Rails configuration guide # http://guides.rubyonrails.org/configuring.html#database-pooling pool: <%%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> diff --git a/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults.rb.tt b/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults.rb.tt index 991963b65e..e539f4c457 100644 --- a/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults.rb.tt +++ b/railties/lib/rails/generators/rails/app/templates/config/initializers/new_framework_defaults.rb.tt @@ -6,7 +6,7 @@ # Once upgraded flip defaults one by one to migrate to the new default. # <%- end -%> -# Read the Rails 5.0 release notes for more info on each option. +# Read the Guide for Upgrading Ruby on Rails for more info on each option. <%- unless options[:api] -%> # Enable per-form CSRF tokens. Previous versions had false. diff --git a/railties/lib/rails/generators/rails/app/templates/public/robots.txt b/railties/lib/rails/generators/rails/app/templates/public/robots.txt index 3c9c7c01f3..37b576a4a0 100644 --- a/railties/lib/rails/generators/rails/app/templates/public/robots.txt +++ b/railties/lib/rails/generators/rails/app/templates/public/robots.txt @@ -1,5 +1 @@ # See http://www.robotstxt.org/robotstxt.html for documentation on how to use the robots.txt file -# -# To ban all spiders from the entire site uncomment the next two lines: -# User-agent: * -# Disallow: / diff --git a/railties/lib/rails/initializable.rb b/railties/lib/rails/initializable.rb index 1a0b6d1e1a..292379e3f3 100644 --- a/railties/lib/rails/initializable.rb +++ b/railties/lib/rails/initializable.rb @@ -34,6 +34,10 @@ module Rails return self if @context Initializer.new(@name, context, @options, &block) end + + def context_class + @context.class + end end class Collection < Array diff --git a/railties/lib/rails/source_annotation_extractor.rb b/railties/lib/rails/source_annotation_extractor.rb index ca195bd752..85818fafc9 100644 --- a/railties/lib/rails/source_annotation_extractor.rb +++ b/railties/lib/rails/source_annotation_extractor.rb @@ -18,6 +18,12 @@ class SourceAnnotationExtractor @@directories ||= %w(app config db lib test) + (ENV['SOURCE_ANNOTATION_DIRECTORIES'] || '').split(',') end + # Registers additional directories to be included + # SourceAnnotationExtractor::Annotation.register_directories("spec","another") + def self.register_directories(*dirs) + directories.push(*dirs) + end + def self.extensions @@extensions ||= {} end diff --git a/railties/lib/rails/tasks/initializers.rake b/railties/lib/rails/tasks/initializers.rake index 2968b5cb53..6522f2ae5a 100644 --- a/railties/lib/rails/tasks/initializers.rake +++ b/railties/lib/rails/tasks/initializers.rake @@ -1,6 +1,6 @@ desc "Print out all defined initializers in the order they are invoked by Rails." task initializers: :environment do Rails.application.initializers.tsort_each do |initializer| - puts initializer.name + puts "#{initializer.context_class}.#{initializer.name}" end end diff --git a/railties/test/application/asset_debugging_test.rb b/railties/test/application/asset_debugging_test.rb index bcb6aff0d7..19327efcc8 100644 --- a/railties/test/application/asset_debugging_test.rb +++ b/railties/test/application/asset_debugging_test.rb @@ -28,8 +28,6 @@ module ApplicationTests RUBY ENV["RAILS_ENV"] = "production" - - boot_rails end def teardown diff --git a/railties/test/application/assets_test.rb b/railties/test/application/assets_test.rb index 12bdbcf23e..20329c6e60 100644 --- a/railties/test/application/assets_test.rb +++ b/railties/test/application/assets_test.rb @@ -9,7 +9,6 @@ module ApplicationTests def setup build_app(initializers: true) - boot_rails end def teardown diff --git a/railties/test/application/configuration/custom_test.rb b/railties/test/application/configuration/custom_test.rb index 28b3b2f2d6..677cb8328c 100644 --- a/railties/test/application/configuration/custom_test.rb +++ b/railties/test/application/configuration/custom_test.rb @@ -5,7 +5,6 @@ module ApplicationTests class CustomTest < ActiveSupport::TestCase def setup build_app - boot_rails FileUtils.rm_rf("#{app_path}/config/environments") end @@ -33,6 +32,13 @@ module ApplicationTests assert_nil x.i_do_not_exist.zomg end + test 'custom configuration responds to all messages' do + x = Rails.configuration.x + assert_equal true, x.respond_to?(:i_do_not_exist) + assert_kind_of Method, x.method(:i_do_not_exist) + assert_kind_of ActiveSupport::OrderedOptions, x.i_do_not_exist + end + private def new_app File.expand_path("#{app_path}/../new_app") diff --git a/railties/test/application/configuration_test.rb b/railties/test/application/configuration_test.rb index 7ec25aeca1..e1c6f214ab 100644 --- a/railties/test/application/configuration_test.rb +++ b/railties/test/application/configuration_test.rb @@ -51,7 +51,6 @@ module ApplicationTests def setup build_app - boot_rails supress_default_config end @@ -570,7 +569,7 @@ module ApplicationTests app_file 'config/secrets.yml', <<-YAML shared: api_key: 3b7cd727 - + development: api_key: abc12345 YAML @@ -779,7 +778,7 @@ module ApplicationTests require "mail" _ = ActionMailer::Base - assert_equal [::MyMailInterceptor], ::Mail.send(:class_variable_get, "@@delivery_interceptors") + assert_equal [::MyMailInterceptor], ::Mail.class_variable_get(:@@delivery_interceptors) end test "registers multiple interceptors with ActionMailer" do @@ -792,7 +791,7 @@ module ApplicationTests require "mail" _ = ActionMailer::Base - assert_equal [::MyMailInterceptor, ::MyOtherMailInterceptor], ::Mail.send(:class_variable_get, "@@delivery_interceptors") + assert_equal [::MyMailInterceptor, ::MyOtherMailInterceptor], ::Mail.class_variable_get(:@@delivery_interceptors) end test "registers preview interceptors with ActionMailer" do @@ -844,7 +843,7 @@ module ApplicationTests require "mail" _ = ActionMailer::Base - assert_equal [::MyMailObserver], ::Mail.send(:class_variable_get, "@@delivery_notification_observers") + assert_equal [::MyMailObserver], ::Mail.class_variable_get(:@@delivery_notification_observers) end test "registers multiple observers with ActionMailer" do @@ -857,7 +856,7 @@ module ApplicationTests require "mail" _ = ActionMailer::Base - assert_equal [::MyMailObserver, ::MyOtherMailObserver], ::Mail.send(:class_variable_get, "@@delivery_notification_observers") + assert_equal [::MyMailObserver, ::MyOtherMailObserver], ::Mail.class_variable_get(:@@delivery_notification_observers) end test "allows setting the queue name for the ActionMailer::DeliveryJob" do @@ -870,7 +869,7 @@ module ApplicationTests require "mail" _ = ActionMailer::Base - assert_equal 'test_default', ActionMailer::Base.send(:class_variable_get, "@@deliver_later_queue_name") + assert_equal 'test_default', ActionMailer::Base.class_variable_get(:@@deliver_later_queue_name) end test "valid timezone is setup correctly" do @@ -1088,7 +1087,7 @@ module ApplicationTests assert_equal %w( controller action format ), ActionController::Parameters.always_permitted_parameters end - test "config.action_controller.always_permitted_parameters = ['controller','action','format'] does not raise exeception" do + test "config.action_controller.always_permitted_parameters = ['controller','action','format'] does not raise exception" do app_file 'app/controllers/posts_controller.rb', <<-RUBY class PostsController < ActionController::Base def create diff --git a/railties/test/application/console_test.rb b/railties/test/application/console_test.rb index ea68e63f8f..ba60b54df3 100644 --- a/railties/test/application/console_test.rb +++ b/railties/test/application/console_test.rb @@ -5,7 +5,6 @@ class ConsoleTest < ActiveSupport::TestCase def setup build_app - boot_rails end def teardown diff --git a/railties/test/application/generators_test.rb b/railties/test/application/generators_test.rb index 644af0e737..4e300bce63 100644 --- a/railties/test/application/generators_test.rb +++ b/railties/test/application/generators_test.rb @@ -6,7 +6,6 @@ module ApplicationTests def setup build_app - boot_rails end def teardown diff --git a/railties/test/application/initializers/frameworks_test.rb b/railties/test/application/initializers/frameworks_test.rb index 44209a52f7..812bb87009 100644 --- a/railties/test/application/initializers/frameworks_test.rb +++ b/railties/test/application/initializers/frameworks_test.rb @@ -6,7 +6,6 @@ module ApplicationTests def setup build_app - boot_rails FileUtils.rm_rf "#{app_path}/config/environments" end diff --git a/railties/test/application/initializers/hooks_test.rb b/railties/test/application/initializers/hooks_test.rb index b2cea0a8e1..3c0c2ac1c0 100644 --- a/railties/test/application/initializers/hooks_test.rb +++ b/railties/test/application/initializers/hooks_test.rb @@ -6,7 +6,6 @@ module ApplicationTests def setup build_app - boot_rails FileUtils.rm_rf "#{app_path}/config/environments" end diff --git a/railties/test/application/initializers/i18n_test.rb b/railties/test/application/initializers/i18n_test.rb index 0f9bb41053..fcafbb6d04 100644 --- a/railties/test/application/initializers/i18n_test.rb +++ b/railties/test/application/initializers/i18n_test.rb @@ -6,7 +6,6 @@ module ApplicationTests def setup build_app - boot_rails FileUtils.rm_rf "#{app_path}/config/environments" require "rails/all" end diff --git a/railties/test/application/initializers/load_path_test.rb b/railties/test/application/initializers/load_path_test.rb index cd05956356..caab7c0c8a 100644 --- a/railties/test/application/initializers/load_path_test.rb +++ b/railties/test/application/initializers/load_path_test.rb @@ -6,7 +6,6 @@ module ApplicationTests def setup build_app - boot_rails FileUtils.rm_rf "#{app_path}/config/environments" end diff --git a/railties/test/application/initializers/notifications_test.rb b/railties/test/application/initializers/notifications_test.rb index 95655b74cf..1a7914b4eb 100644 --- a/railties/test/application/initializers/notifications_test.rb +++ b/railties/test/application/initializers/notifications_test.rb @@ -6,7 +6,6 @@ module ApplicationTests def setup build_app - boot_rails end def teardown diff --git a/railties/test/application/integration_test_case_test.rb b/railties/test/application/integration_test_case_test.rb index d106d5159a..52df5a2e5a 100644 --- a/railties/test/application/integration_test_case_test.rb +++ b/railties/test/application/integration_test_case_test.rb @@ -6,7 +6,6 @@ module ApplicationTests setup do build_app - boot_rails end teardown do diff --git a/railties/test/application/loading_test.rb b/railties/test/application/loading_test.rb index efb21ae473..fe1847d8a5 100644 --- a/railties/test/application/loading_test.rb +++ b/railties/test/application/loading_test.rb @@ -5,7 +5,6 @@ class LoadingTest < ActiveSupport::TestCase def setup build_app - boot_rails end def teardown diff --git a/railties/test/application/mailer_previews_test.rb b/railties/test/application/mailer_previews_test.rb index 643d876a26..3bb77ab0f5 100644 --- a/railties/test/application/mailer_previews_test.rb +++ b/railties/test/application/mailer_previews_test.rb @@ -9,7 +9,6 @@ module ApplicationTests def setup build_app - boot_rails end def teardown diff --git a/railties/test/application/middleware/cache_test.rb b/railties/test/application/middleware/cache_test.rb index c951dabd6c..9802de4a60 100644 --- a/railties/test/application/middleware/cache_test.rb +++ b/railties/test/application/middleware/cache_test.rb @@ -6,7 +6,6 @@ module ApplicationTests def setup build_app - boot_rails require 'rack/test' extend Rack::Test::Methods end diff --git a/railties/test/application/middleware/cookies_test.rb b/railties/test/application/middleware/cookies_test.rb index bbb7627be9..7a1a0083b1 100644 --- a/railties/test/application/middleware/cookies_test.rb +++ b/railties/test/application/middleware/cookies_test.rb @@ -10,7 +10,6 @@ module ApplicationTests def setup build_app - boot_rails FileUtils.rm_rf("#{app_path}/config/environments") end diff --git a/railties/test/application/middleware/exceptions_test.rb b/railties/test/application/middleware/exceptions_test.rb index 639b01b562..44c0215341 100644 --- a/railties/test/application/middleware/exceptions_test.rb +++ b/railties/test/application/middleware/exceptions_test.rb @@ -8,7 +8,6 @@ module ApplicationTests def setup build_app - boot_rails end def teardown diff --git a/railties/test/application/middleware/sendfile_test.rb b/railties/test/application/middleware/sendfile_test.rb index be86f1a3b8..18e23ca17b 100644 --- a/railties/test/application/middleware/sendfile_test.rb +++ b/railties/test/application/middleware/sendfile_test.rb @@ -6,7 +6,6 @@ module ApplicationTests def setup build_app - boot_rails FileUtils.rm_rf "#{app_path}/config/environments" end diff --git a/railties/test/application/middleware/session_test.rb b/railties/test/application/middleware/session_test.rb index 85e7761727..64cae27ea2 100644 --- a/railties/test/application/middleware/session_test.rb +++ b/railties/test/application/middleware/session_test.rb @@ -8,7 +8,6 @@ module ApplicationTests def setup build_app - boot_rails FileUtils.rm_rf "#{app_path}/config/environments" end @@ -373,5 +372,11 @@ module ApplicationTests refute Rails.application.middleware.include?(ActionDispatch::Flash) end + + test "cookie_only is set to true even if user tries to overwrite it" do + add_to_config "config.session_store :cookie_store, key: '_myapp_session', cookie_only: false" + require "#{app_path}/config/environment" + assert app.config.session_options[:cookie_only], "Expected cookie_only to be set to true" + end end end diff --git a/railties/test/application/middleware_test.rb b/railties/test/application/middleware_test.rb index 7a86a96e19..23699cae74 100644 --- a/railties/test/application/middleware_test.rb +++ b/railties/test/application/middleware_test.rb @@ -6,7 +6,6 @@ module ApplicationTests def setup build_app - boot_rails FileUtils.rm_rf "#{app_path}/config/environments" end diff --git a/railties/test/application/multiple_applications_test.rb b/railties/test/application/multiple_applications_test.rb index f2770a9cb4..f9628fe5a8 100644 --- a/railties/test/application/multiple_applications_test.rb +++ b/railties/test/application/multiple_applications_test.rb @@ -6,7 +6,6 @@ module ApplicationTests def setup build_app(initializers: true) - boot_rails require "#{rails_root}/config/environment" Rails.application.config.some_setting = 'something_or_other' end diff --git a/railties/test/application/paths_test.rb b/railties/test/application/paths_test.rb index 4029984ce9..8eb1d42b33 100644 --- a/railties/test/application/paths_test.rb +++ b/railties/test/application/paths_test.rb @@ -6,7 +6,6 @@ module ApplicationTests def setup build_app - boot_rails FileUtils.rm_rf("#{app_path}/config/environments") app_file "config/environments/development.rb", "" add_to_config <<-RUBY diff --git a/railties/test/application/rackup_test.rb b/railties/test/application/rackup_test.rb index 49ac9fc66c..4aef9b299c 100644 --- a/railties/test/application/rackup_test.rb +++ b/railties/test/application/rackup_test.rb @@ -12,14 +12,13 @@ module ApplicationTests def setup build_app - boot_rails end def teardown teardown_app end - test "rails app is present" do + test "Rails app is present" do assert File.exist?(app_path("config")) end diff --git a/railties/test/application/rake/dbs_test.rb b/railties/test/application/rake/dbs_test.rb index cee9db5535..f9bf670c5a 100644 --- a/railties/test/application/rake/dbs_test.rb +++ b/railties/test/application/rake/dbs_test.rb @@ -8,7 +8,6 @@ module ApplicationTests def setup build_app - boot_rails FileUtils.rm_rf("#{app_path}/config/environments") end diff --git a/railties/test/application/rake/framework_test.rb b/railties/test/application/rake/framework_test.rb index ec57af79f6..04e54b2c70 100644 --- a/railties/test/application/rake/framework_test.rb +++ b/railties/test/application/rake/framework_test.rb @@ -8,7 +8,6 @@ module ApplicationTests def setup build_app - boot_rails FileUtils.rm_rf("#{app_path}/config/environments") end diff --git a/railties/test/application/rake/migrations_test.rb b/railties/test/application/rake/migrations_test.rb index 7e2519ae5a..35f14a9b84 100644 --- a/railties/test/application/rake/migrations_test.rb +++ b/railties/test/application/rake/migrations_test.rb @@ -5,7 +5,6 @@ module ApplicationTests class RakeMigrationsTest < ActiveSupport::TestCase def setup build_app - boot_rails FileUtils.rm_rf("#{app_path}/config/environments") end diff --git a/railties/test/application/rake/notes_test.rb b/railties/test/application/rake/notes_test.rb index 50def9beb0..7d1e3efed2 100644 --- a/railties/test/application/rake/notes_test.rb +++ b/railties/test/application/rake/notes_test.rb @@ -126,6 +126,18 @@ module ApplicationTests end end + test 'register additional directories' do + app_file "spec/spec_helper.rb", "# TODO: note in spec" + app_file "spec/models/user_spec.rb", "# TODO: note in model spec" + add_to_config %q{ config.annotations.register_directories("spec") } + + run_rake_notes do |output, lines| + assert_match(/note in spec/, output) + assert_match(/note in model spec/, output) + assert_equal 2, lines.size + end + end + private def run_rake_notes(command = 'bin/rails notes') @@ -149,7 +161,6 @@ module ApplicationTests end def boot_rails - super require "#{app_path}/config/environment" end end diff --git a/railties/test/application/rake/restart_test.rb b/railties/test/application/rake/restart_test.rb index 30f662a9be..78769a6de5 100644 --- a/railties/test/application/rake/restart_test.rb +++ b/railties/test/application/rake/restart_test.rb @@ -7,7 +7,6 @@ module ApplicationTests def setup build_app - boot_rails end def teardown diff --git a/railties/test/application/rake_test.rb b/railties/test/application/rake_test.rb index badb9ecdd6..45ea506226 100644 --- a/railties/test/application/rake_test.rb +++ b/railties/test/application/rake_test.rb @@ -7,7 +7,6 @@ module ApplicationTests def setup build_app - boot_rails end def teardown diff --git a/railties/test/application/rendering_test.rb b/railties/test/application/rendering_test.rb index b01febd768..9514547608 100644 --- a/railties/test/application/rendering_test.rb +++ b/railties/test/application/rendering_test.rb @@ -8,7 +8,6 @@ module ApplicationTests def setup build_app - boot_rails end def teardown diff --git a/railties/test/application/routing_test.rb b/railties/test/application/routing_test.rb index 93847c7aa9..8e7df71880 100644 --- a/railties/test/application/routing_test.rb +++ b/railties/test/application/routing_test.rb @@ -8,7 +8,6 @@ module ApplicationTests def setup build_app - boot_rails end def teardown diff --git a/railties/test/application/runner_test.rb b/railties/test/application/runner_test.rb index 9f15ce5e85..84d90cc6d7 100644 --- a/railties/test/application/runner_test.rb +++ b/railties/test/application/runner_test.rb @@ -8,7 +8,6 @@ module ApplicationTests def setup build_app - boot_rails # Lets create a model so we have something to play with app_file "app/models/user.rb", <<-MODEL @@ -76,12 +75,12 @@ module ApplicationTests def test_runner_detects_syntax_errors Dir.chdir(app_path) { `bin/rails runner "puts 'hello world" 2>&1` } - refute $?.success? + refute $?.success? end def test_runner_detects_bad_script_name Dir.chdir(app_path) { `bin/rails runner "iuiqwiourowe" 2>&1` } - refute $?.success? + refute $?.success? end def test_environment_with_rails_env diff --git a/railties/test/application/test_test.rb b/railties/test/application/test_test.rb index 85b003fce9..1e9d35287e 100644 --- a/railties/test/application/test_test.rb +++ b/railties/test/application/test_test.rb @@ -6,7 +6,6 @@ module ApplicationTests def setup build_app - boot_rails end def teardown diff --git a/railties/test/application/url_generation_test.rb b/railties/test/application/url_generation_test.rb index 894e18cb39..6700323199 100644 --- a/railties/test/application/url_generation_test.rb +++ b/railties/test/application/url_generation_test.rb @@ -9,7 +9,6 @@ module ApplicationTests end test "it works" do - boot_rails require "rails" require "action_controller/railtie" require "action_view/railtie" @@ -44,7 +43,6 @@ module ApplicationTests end def test_routes_know_the_relative_root - boot_rails require "rails" require "action_controller/railtie" require "action_view/railtie" diff --git a/railties/test/commands/server_test.rb b/railties/test/commands/server_test.rb index 38a1605d1f..b9a48bbf98 100644 --- a/railties/test/commands/server_test.rb +++ b/railties/test/commands/server_test.rb @@ -51,6 +51,13 @@ class Rails::ServerTest < ActiveSupport::TestCase end end + def test_environment_with_host + switch_env "HOST", "1.2.3.4" do + server = Rails::Server.new + assert_equal "1.2.3.4", server.options[:Host] + end + end + def test_caching_without_option args = [] options = Rails::Server::Options.new.parse!(args) diff --git a/railties/test/initializable_test.rb b/railties/test/initializable_test.rb index ed9573453b..d4eafebfa4 100644 --- a/railties/test/initializable_test.rb +++ b/railties/test/initializable_test.rb @@ -174,6 +174,11 @@ module InitializableTests end end end + + test "Initializer provides context's class name" do + foo = Foo.new + assert_equal foo.class, foo.initializers.first.context_class + end end class BeforeAfter < ActiveSupport::TestCase diff --git a/railties/test/isolation/abstract_unit.rb b/railties/test/isolation/abstract_unit.rb index e427614dfa..5528459ad2 100644 --- a/railties/test/isolation/abstract_unit.rb +++ b/railties/test/isolation/abstract_unit.rb @@ -1,7 +1,7 @@ # Note: # It is important to keep this file as light as possible # the goal for tests that require this is to test booting up -# rails from an empty state, so anything added here could +# Rails from an empty state, so anything added here could # hide potential failures # # It is also good to know what is the bare minimum to get @@ -310,9 +310,6 @@ module TestHelpers $:.reject! {|path| path =~ %r'/(#{to_remove.join('|')})/' } end - - def boot_rails - end end end diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb index fb8a7656d0..0eaa5bc351 100644 --- a/railties/test/railties/engine_test.rb +++ b/railties/test/railties/engine_test.rb @@ -28,7 +28,6 @@ module RailtiesTest end def boot_rails - super require "#{app_path}/config/environment" end diff --git a/railties/test/railties/mounted_engine_test.rb b/railties/test/railties/mounted_engine_test.rb index fb2071c7c3..70789d86e2 100644 --- a/railties/test/railties/mounted_engine_test.rb +++ b/railties/test/railties/mounted_engine_test.rb @@ -179,8 +179,6 @@ module ApplicationTests end end RUBY - - boot_rails end def teardown diff --git a/railties/test/railties/railtie_test.rb b/railties/test/railties/railtie_test.rb index 5042d628cf..4ae6d8fa04 100644 --- a/railties/test/railties/railtie_test.rb +++ b/railties/test/railties/railtie_test.rb @@ -6,7 +6,6 @@ module RailtiesTest def setup build_app - boot_rails FileUtils.rm_rf("#{app_path}/config/environments") require "rails/all" end |