diff options
18 files changed, 102 insertions, 67 deletions
diff --git a/.rubocop.yml b/.rubocop.yml index de355eeb13..62fb263c9e 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -4,37 +4,40 @@ AllCops: # Two spaces, no tabs (for indentation). Style/IndentationWidth: - enabled: true + Enabled: true # No trailing whitespace. Style/TrailingWhitespace: - enabled: true + Enabled: true # Blank lines should not have any spaces. Style/TrailingBlankLines: - enabled: true + Enabled: true # Use Ruby >= 1.9 syntax for hashes. Prefer { a: :b } over { :a => :b }. Style/HashSyntax: - enabled: true + Enabled: true # Prefer &&/|| over and/or. Style/AndOr: - enabled: true + Enabled: true # Use my_method(my_arg) not my_method( my_arg ) or my_method my_arg. Lint/RequireParentheses: - enabled: true + Enabled: true Style/BracesAroundHashParameters: - enabled: true + Enabled: true Style/IndentationConsistency: - enabled: true + Enabled: true EnforcedStyle: rails Style/EmptyLinesAroundClassBody: - enabled: true + Enabled: true Style/EmptyLinesAroundModuleBody: - enabled: true + Enabled: true + +Lint/EndAlignment: + AlignWith: variable diff --git a/actionview/lib/action_view/helpers/form_options_helper.rb b/actionview/lib/action_view/helpers/form_options_helper.rb index 06b696f281..0cd3207b12 100644 --- a/actionview/lib/action_view/helpers/form_options_helper.rb +++ b/actionview/lib/action_view/helpers/form_options_helper.rb @@ -651,12 +651,12 @@ module ActionView # The HTML specification says when nothing is select on a collection of radio buttons # web browsers do not send any value to server. # Unfortunately this introduces a gotcha: - # if a +User+ model has a +category_id+ field, and in the form none category is selected no +category_id+ parameter is sent. So, - # any strong parameters idiom like + # if a +User+ model has a +category_id+ field and in the form no category is selected, no +category_id+ parameter is sent. So, + # any strong parameters idiom like: # # params.require(:user).permit(...) # - # will raise an error since no +{user: ...}+ will be present. + # will raise an error since no <tt>{user: ...}</tt> will be present. # # To prevent this the helper generates an auxiliary hidden field before # every collection of radio buttons. The hidden field has the same name as collection radio button and blank value. diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 3729e22e64..c91b5d3fe3 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -362,7 +362,7 @@ module ActiveRecord # end # end # - # If your model class is <tt>Project</tt>, the module is + # If your model class is <tt>Project</tt>, then the module is # named <tt>Project::GeneratedAssociationMethods</tt>. The +GeneratedAssociationMethods+ module is # included in the model class immediately after the (anonymous) generated attributes methods # module, meaning an association will override the methods for an attribute with the same name. @@ -845,8 +845,8 @@ module ActiveRecord # Post.includes(:author).each do |post| # # This references the name of the #belongs_to association that also used the <tt>:author</tt> - # symbol. After loading the posts, find will collect the +author_id+ from each one and load - # all the referenced authors with one query. Doing so will cut down the number of queries + # symbol. After loading the posts, +find+ will collect the +author_id+ from each one and load + # all of the referenced authors with one query. Doing so will cut down the number of queries # from 201 to 102. # # We can improve upon the situation further by referencing both associations in the finder with: @@ -873,7 +873,7 @@ module ActiveRecord # # Since only one table is loaded at a time, conditions or orders cannot reference tables # other than the main one. If this is the case, Active Record falls back to the previously - # used LEFT OUTER JOIN based strategy. For example: + # used <tt>LEFT OUTER JOIN</tt> based strategy. For example: # # Post.includes([:author, :comments]).where(['comments.approved = ?', true]) # @@ -881,18 +881,18 @@ module ActiveRecord # <tt>LEFT OUTER JOIN comments ON comments.post_id = posts.id</tt> and # <tt>LEFT OUTER JOIN authors ON authors.id = posts.author_id</tt>. Note that using conditions # like this can have unintended consequences. - # In the above example posts with no approved comments are not returned at all, because + # In the above example, posts with no approved comments are not returned at all because # the conditions apply to the SQL statement as a whole and not just to the association. # # You must disambiguate column references for this fallback to happen, for example # <tt>order: "author.name DESC"</tt> will work but <tt>order: "name DESC"</tt> will not. # - # If you want to load all posts (including posts with no approved comments) then write - # your own LEFT OUTER JOIN query using ON + # If you want to load all posts (including posts with no approved comments), then write + # your own <tt>LEFT OUTER JOIN</tt> query using <tt>ON</tt>: # # Post.joins("LEFT OUTER JOIN comments ON comments.post_id = posts.id AND comments.approved = '1'") # - # In this case it is usually more natural to include an association which has conditions defined on it: + # In this case, it is usually more natural to include an association which has conditions defined on it: # # class Post < ActiveRecord::Base # has_many :approved_comments, -> { where(approved: true) }, class_name: 'Comment' @@ -924,7 +924,7 @@ module ActiveRecord # # This will execute one query to load the addresses and load the addressables with one # query per addressable type. - # For example if all the addressables are either of class Person or Company then a total + # For example, if all the addressables are either of class Person or Company, then a total # of 3 queries will be executed. The list of addressable types to load is determined on # the back of the addresses loaded. This is not supported if Active Record has to fallback # to the previous implementation of eager loading and will raise ActiveRecord::EagerLoadPolymorphicError. @@ -1015,7 +1015,7 @@ module ActiveRecord # # == Bi-directional associations # - # When you specify an association there is usually an association on the associated model + # When you specify an association, there is usually an association on the associated model # that specifies the same relationship in reverse. For example, with the following models: # # class Dungeon < ActiveRecord::Base @@ -1032,7 +1032,7 @@ module ActiveRecord # end # # The +traps+ association on +Dungeon+ and the +dungeon+ association on +Trap+ are - # the inverse of each other and the inverse of the +dungeon+ association on +EvilWizard+ + # the inverse of each other, and the inverse of the +dungeon+ association on +EvilWizard+ # is the +evil_wizard+ association on +Dungeon+ (and vice-versa). By default, # Active Record can guess the inverse of the association based on the name # of the class. The result is the following: @@ -1062,7 +1062,7 @@ module ActiveRecord # # * does not work with <tt>:through</tt> associations. # * does not work with <tt>:polymorphic</tt> associations. - # * for #belongs_to associations #has_many inverse associations are ignored. + # * inverse associations for #belongs_to associations #has_many are ignored. # # For more information, see the documentation for the +:inverse_of+ option. # @@ -1070,7 +1070,7 @@ module ActiveRecord # # === Dependent associations # - # #has_many, #has_one and #belongs_to associations support the <tt>:dependent</tt> option. + # #has_many, #has_one, and #belongs_to associations support the <tt>:dependent</tt> option. # This allows you to specify that associated records should be deleted when the owner is # deleted. # 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 57e62cda9f..dc5b305843 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb @@ -855,7 +855,7 @@ module ActiveRecord connection_id: object_id } if spec - payload[:class_name] = spec.name + payload[:spec_name] = spec.name payload[:config] = spec.config end diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index 5747e4d1ee..4f8490fa2b 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -579,14 +579,15 @@ module ActiveRecord exception end - def log(sql, name = "SQL", binds = [], statement_name = nil) + def log(sql, name = "SQL", binds = [], type_casted_binds = [], statement_name = nil) @instrumenter.instrument( "sql.active_record", - :sql => sql, - :name => name, - :connection_id => object_id, - :statement_name => statement_name, - :binds => binds) { yield } + sql: sql, + name: name, + binds: binds, + type_casted_binds: type_casted_binds, + statement_name: statement_name, + connection_id: object_id) { yield } rescue => e raise translate_exception_class(e, sql) end diff --git a/activerecord/lib/active_record/connection_adapters/mysql/database_statements.rb b/activerecord/lib/active_record/connection_adapters/mysql/database_statements.rb index 87f0ff7d85..cc19d95669 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql/database_statements.rb @@ -79,7 +79,7 @@ module ActiveRecord type_casted_binds = binds.map { |attr| type_cast(attr.value_for_database) } - log(sql, name, binds) do + log(sql, name, binds, type_casted_binds) do if cache_stmt cache = @statements[sql] ||= { stmt: @connection.prepare(sql) diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index ddfc560747..487165d511 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -598,14 +598,14 @@ module ActiveRecord def exec_no_cache(sql, name, binds) type_casted_binds = binds.map { |attr| type_cast(attr.value_for_database) } - log(sql, name, binds) { @connection.async_exec(sql, type_casted_binds) } + log(sql, name, binds, type_casted_binds) { @connection.async_exec(sql, type_casted_binds) } end def exec_cache(sql, name, binds) stmt_key = prepare_statement(sql) type_casted_binds = binds.map { |attr| type_cast(attr.value_for_database) } - log(sql, name, binds, stmt_key) do + log(sql, name, binds, type_casted_binds, stmt_key) do @connection.exec_prepared(stmt_key, type_casted_binds) end rescue ActiveRecord::StatementInvalid => e diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb index 3384012c49..7e23f44ddf 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb @@ -190,7 +190,7 @@ module ActiveRecord def exec_query(sql, name = nil, binds = [], prepare: false) type_casted_binds = binds.map { |attr| type_cast(attr.value_for_database) } - log(sql, name, binds) do + log(sql, name, binds, type_casted_binds) do # Don't cache statements if they are not prepared unless prepare stmt = @connection.prepare(sql) diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index 2c94463acd..3e3a7679ac 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -78,7 +78,18 @@ module ActiveRecord mattr_accessor :error_on_ignored_order, instance_writer: false self.error_on_ignored_order = false - mattr_accessor :error_on_ignored_order_or_limit, instance_writer: false + def self.error_on_ignored_order_or_limit + ActiveSupport::Deprecation.warn(<<-MSG.squish) + The flag error_on_ignored_order_or_limit is deprecated. Limits are + now supported. Please use error_on_ignored_order instead. + MSG + self.error_on_ignored_order + end + + def error_on_ignored_order_or_limit + self.class.error_on_ignored_order_or_limit + end + def self.error_on_ignored_order_or_limit=(value) ActiveSupport::Deprecation.warn(<<-MSG.squish) The flag error_on_ignored_order_or_limit is deprecated. Limits are diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb index 6d142285cd..0ec33f7d87 100644 --- a/activerecord/lib/active_record/fixtures.rb +++ b/activerecord/lib/active_record/fixtures.rb @@ -987,16 +987,11 @@ module ActiveRecord # When connections are established in the future, begin a transaction too @connection_subscriber = ActiveSupport::Notifications.subscribe('!connection.active_record') do |_, _, _, _, payload| - model_class = nil - begin - model_class = payload[:class_name].constantize if payload[:class_name] - rescue NameError - model_class = nil - end + spec_name = payload[:spec_name] if payload.key?(:spec_name) - if model_class + if spec_name begin - connection = ActiveRecord::Base.connection_handler.retrieve_connection(model_class) + connection = ActiveRecord::Base.connection_handler.retrieve_connection(spec_name) rescue ConnectionNotEstablished connection = nil end diff --git a/activerecord/lib/active_record/log_subscriber.rb b/activerecord/lib/active_record/log_subscriber.rb index 8e32af1c49..c4998ba686 100644 --- a/activerecord/lib/active_record/log_subscriber.rb +++ b/activerecord/lib/active_record/log_subscriber.rb @@ -20,18 +20,14 @@ module ActiveRecord @odd = false end - def render_bind(attribute) - value = if attribute.type.binary? && attribute.value - if attribute.value.is_a?(Hash) - "<#{attribute.value_for_database.to_s.bytesize} bytes of binary data>" - else - "<#{attribute.value.bytesize} bytes of binary data>" - end + def render_bind(attr, type_casted_value) + value = if attr.type.binary? && attr.value + "<#{attr.value_for_database.to_s.bytesize} bytes of binary data>" else - attribute.value_for_database + type_casted_value end - [attribute.name, value] + [attr.name, value] end def sql(event) @@ -48,7 +44,9 @@ module ActiveRecord binds = nil unless (payload[:binds] || []).empty? - binds = " " + payload[:binds].map { |attr| render_bind(attr) }.inspect + binds = " " + payload[:binds].zip(payload[:type_casted_binds]).map { |attr, value| + render_bind(attr, value) + }.inspect end name = colorize_payload_name(name, payload[:name]) diff --git a/activerecord/test/cases/batches_test.rb b/activerecord/test/cases/batches_test.rb index 2c6011489e..8a4c1bd615 100644 --- a/activerecord/test/cases/batches_test.rb +++ b/activerecord/test/cases/batches_test.rb @@ -587,7 +587,7 @@ class EachTest < ActiveRecord::TestCase end end - test 'error_on_ignored_order_or_limit= is deprecated' do + test '.error_on_ignored_order_or_limit= is deprecated' do begin prev = ActiveRecord::Base.error_on_ignored_order assert_deprecated 'Please use error_on_ignored_order= instead.' do @@ -598,4 +598,20 @@ class EachTest < ActiveRecord::TestCase ActiveRecord::Base.error_on_ignored_order = prev end end + + test '.error_on_ignored_order_or_limit is deprecated' do + expected = ActiveRecord::Base.error_on_ignored_order + actual = assert_deprecated 'Please use error_on_ignored_order instead.' do + ActiveRecord::Base.error_on_ignored_order_or_limit + end + assert_equal expected, actual + end + + test '#error_on_ignored_order_or_limit is deprecated' do + expected = ActiveRecord::Base.error_on_ignored_order + actual = assert_deprecated 'Please use error_on_ignored_order instead.' do + Post.new.error_on_ignored_order_or_limit + end + assert_equal expected, actual + end end diff --git a/activerecord/test/cases/bind_parameter_test.rb b/activerecord/test/cases/bind_parameter_test.rb index fa924fe4cb..3f01885489 100644 --- a/activerecord/test/cases/bind_parameter_test.rb +++ b/activerecord/test/cases/bind_parameter_test.rb @@ -57,10 +57,13 @@ module ActiveRecord end def test_logs_bind_vars_after_type_cast + binds = [Relation::QueryAttribute.new("id", "10", Type::Integer.new)] + type_casted_binds = binds.map { |attr| type_cast(attr.value_for_database) } payload = { :name => 'SQL', :sql => 'select * from topics where id = ?', - :binds => [Relation::QueryAttribute.new("id", "10", Type::Integer.new)] + :binds => binds, + :type_casted_binds => type_casted_binds } event = ActiveSupport::Notifications::Event.new( 'foo', @@ -84,6 +87,12 @@ module ActiveRecord logger.sql event assert_match([[@pk.name, 10]].inspect, logger.debugs.first) end + + private + + def type_cast(value) + ActiveRecord::Base.connection.type_cast(value) + end end end end diff --git a/activerecord/test/cases/connection_pool_test.rb b/activerecord/test/cases/connection_pool_test.rb index 2bdabaee62..bbcb42d58e 100644 --- a/activerecord/test/cases/connection_pool_test.rb +++ b/activerecord/test/cases/connection_pool_test.rb @@ -347,8 +347,8 @@ module ActiveRecord payloads << payload end ActiveRecord::Base.establish_connection :arunit - assert_equal [:class_name, :config, :connection_id], payloads[0].keys.sort - assert_equal 'primary', payloads[0][:class_name] + assert_equal [:config, :connection_id, :spec_name], payloads[0].keys.sort + assert_equal 'primary', payloads[0][:spec_name] ensure ActiveSupport::Notifications.unsubscribe(subscription) if subscription end diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb index a06aa4b247..df53bbf950 100644 --- a/activerecord/test/cases/fixtures_test.rb +++ b/activerecord/test/cases/fixtures_test.rb @@ -650,10 +650,10 @@ class TransactionalFixturesOnConnectionNotification < ActiveRecord::TestCase private def fire_connection_notification(connection) - ActiveRecord::Base.connection_handler.stubs(:retrieve_connection).with(Book).returns(connection) + ActiveRecord::Base.connection_handler.stubs(:retrieve_connection).with('book').returns(connection) message_bus = ActiveSupport::Notifications.instrumenter payload = { - class_name: 'Book', + spec_name: 'book', config: nil, connection_id: connection.object_id } diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb index 03ec063671..085636553e 100644 --- a/activerecord/test/cases/query_cache_test.rb +++ b/activerecord/test/cases/query_cache_test.rb @@ -6,6 +6,8 @@ require 'models/post' require 'rack' class QueryCacheTest < ActiveRecord::TestCase + self.use_transactional_tests = false + fixtures :tasks, :topics, :categories, :posts, :categories_posts teardown do diff --git a/guides/source/action_cable_overview.md b/guides/source/action_cable_overview.md index 0d00b7f07b..02db86888c 100644 --- a/guides/source/action_cable_overview.md +++ b/guides/source/action_cable_overview.md @@ -333,7 +333,7 @@ class ChatChannel < ApplicationCable::Channel end def receive(data) - ChatChannel.broadcast_to("chat_#{params[:room]}", data) + ActionCable.server.broadcast("chat_#{params[:room]}", data) end end ``` diff --git a/guides/source/configuring.md b/guides/source/configuring.md index 34878e5c38..d11edf2bfa 100644 --- a/guides/source/configuring.md +++ b/guides/source/configuring.md @@ -163,7 +163,7 @@ pipeline is enabled. It is set to `true` by default. * `config.assets.js_compressor` defines the JavaScript compressor to use. Possible values are `:closure`, `:uglifier` and `:yui` which require the use of the `closure-compiler`, `uglifier` or `yui-compressor` gems respectively. -* `config.assets.gzip` a flag that enables the creation of gzipped version of compiled assets, along with non-gzipped assets. Set to `true` by default. +* `config.assets.gzip` a flag that enables the creation of gzipped version of compiled assets, along with non-gzipped assets. Set to `true` by default. * `config.assets.paths` contains the paths which are used to look for assets. Appending paths to this configuration option will cause those paths to be used in the search for assets. @@ -297,7 +297,7 @@ 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] } ``` @@ -324,7 +324,7 @@ All these configuration options are delegated to the `I18n` library. * `config.active_record.schema_format` controls the format for dumping the database schema to a file. The options are `:ruby` (the default) for a database-independent version that depends on migrations, or `:sql` for a set of (potentially database-dependent) SQL statements. -* `config.active_record.error_on_ignored_order_or_limit` specifies if an error should be raised if the order or limit of a query is ignored during a batch query. The options are `true` (raise error) or `false` (warn). Default is `false`. +* `config.active_record.error_on_ignored_order` specifies if an error should be raised if the order of a query is ignored during a batch query. The options are `true` (raise error) or `false` (warn). Default is `false`. * `config.active_record.timestamped_migrations` controls whether migrations are numbered with serial integers or with timestamps. The default is `true`, to use timestamps, which are preferred if there are multiple developers working on the same application. @@ -529,7 +529,7 @@ There are a number of settings available on `config.action_mailer`: * `:authentication` - If your mail server requires authentication, you need to specify the authentication type here. This is a symbol and one of `:plain`, `:login`, `:cram_md5`. * `:enable_starttls_auto` - Detects if STARTTLS is enabled in your SMTP server and starts to use it. It defaults to `true`. * `:openssl_verify_mode` - When using TLS, you can set how OpenSSL checks the certificate. This is useful if you need to validate a self-signed and/or a wildcard certificate. This can be one of the OpenSSL verify constants, `:none` or `:peer` -- or the constant directly `OpenSSL::SSL::VERIFY_NONE` or `OpenSSL::SSL::VERIFY_PEER`, respectively. - * `:ssl/:tls` - Enables the SMTP connection to use SMTP/TLS (SMTPS: SMTP over direct TLS connection). + * `:ssl/:tls` - Enables the SMTP connection to use SMTP/TLS (SMTPS: SMTP over direct TLS connection). * `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`. |