diff options
Diffstat (limited to 'activerecord')
176 files changed, 459 insertions, 342 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 6f08b1b8fe..a4def5b270 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,15 +1,24 @@ -* Fix invalid schema when primary key column has a comment +* Add support for multiple databases to `rails db:abort_if_pending_migrations`. - Fixes #29966 + *Mark Lee* + +* Fix sqlite3 collation parsing when using decimal columns. + + *Martin R. Schuster* + +* Fix invalid schema when primary key column has a comment. + + Fixes #29966. *Guilherme Goettems Schneider* -* Fix table comment also being applied to the primary key column +* Fix table comment also being applied to the primary key column. *Guilherme Goettems Schneider* * Allow generated `create_table` migrations to include or skip timestamps. - *Michael Duchemin* + *Michael Duchemin* + Please check [6-0-stable](https://github.com/rails/rails/blob/6-0-stable/activerecord/CHANGELOG.md) for previous changes. diff --git a/activerecord/lib/active_record/aggregations.rb b/activerecord/lib/active_record/aggregations.rb index 3250e29b82..aa08124158 100644 --- a/activerecord/lib/active_record/aggregations.rb +++ b/activerecord/lib/active_record/aggregations.rb @@ -14,7 +14,6 @@ module ActiveRecord end private - def clear_aggregation_cache @aggregation_cache.clear if persisted? end diff --git a/activerecord/lib/active_record/association_relation.rb b/activerecord/lib/active_record/association_relation.rb index 4c538ef2bd..de9892e48d 100644 --- a/activerecord/lib/active_record/association_relation.rb +++ b/activerecord/lib/active_record/association_relation.rb @@ -29,7 +29,6 @@ module ActiveRecord end private - def exec_queries super do |record| @association.set_inverse_instance_from_queries(record) diff --git a/activerecord/lib/active_record/associations/alias_tracker.rb b/activerecord/lib/active_record/associations/alias_tracker.rb index 272eede824..ac90ba0137 100644 --- a/activerecord/lib/active_record/associations/alias_tracker.rb +++ b/activerecord/lib/active_record/associations/alias_tracker.rb @@ -72,7 +72,6 @@ module ActiveRecord attr_reader :aliases private - def truncate(name) name.slice(0, @connection.table_alias_length - 2) end diff --git a/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb b/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb index 0140aa15c8..6ad4c75fb5 100644 --- a/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb +++ b/activerecord/lib/active_record/associations/builder/has_and_belongs_to_many.rb @@ -46,7 +46,6 @@ module ActiveRecord::Associations::Builder # :nodoc: end private - def self.suppress_composite_primary_key(pk) pk unless pk.is_a?(Array) end @@ -73,7 +72,6 @@ module ActiveRecord::Associations::Builder # :nodoc: end private - def middle_options(join_model) middle_options = {} middle_options[:class_name] = "#{lhs_model.name}::#{join_model.name}" diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb index 797d647900..0db0ad8595 100644 --- a/activerecord/lib/active_record/associations/collection_proxy.rb +++ b/activerecord/lib/active_record/associations/collection_proxy.rb @@ -1101,7 +1101,6 @@ module ActiveRecord delegate(*delegate_methods, to: :scope) private - def find_nth_with_limit(index, limit) load_target if find_from_target? super diff --git a/activerecord/lib/active_record/associations/has_many_association.rb b/activerecord/lib/active_record/associations/has_many_association.rb index 5972846940..dd2ed55279 100644 --- a/activerecord/lib/active_record/associations/has_many_association.rb +++ b/activerecord/lib/active_record/associations/has_many_association.rb @@ -37,7 +37,6 @@ module ActiveRecord end private - # Returns the number of records in this collection. # # If the association has a counter cache it gets that value. Otherwise diff --git a/activerecord/lib/active_record/associations/preloader.rb b/activerecord/lib/active_record/associations/preloader.rb index 6b57e5093a..d4e8b364e1 100644 --- a/activerecord/lib/active_record/associations/preloader.rb +++ b/activerecord/lib/active_record/associations/preloader.rb @@ -95,7 +95,6 @@ module ActiveRecord end private - # Loads all the given data into +records+ for the +association+. def preloaders_on(association, records, scope, polymorphic_parent = false) case association diff --git a/activerecord/lib/active_record/associations/preloader/association.rb b/activerecord/lib/active_record/associations/preloader/association.rb index 342d9e7a5a..4c7b0e6f07 100644 --- a/activerecord/lib/active_record/associations/preloader/association.rb +++ b/activerecord/lib/active_record/associations/preloader/association.rb @@ -27,7 +27,9 @@ module ActiveRecord end def records_by_owner - @records_by_owner ||= preloaded_records.each_with_object({}) do |record, result| + # owners can be duplicated when a relation has a collection association join + # #compare_by_identity makes such owners different hash keys + @records_by_owner ||= preloaded_records.each_with_object({}.compare_by_identity) do |record, result| owners_by_key[convert_key(record[association_key_name])].each do |owner| (result[owner] ||= []) << record end diff --git a/activerecord/lib/active_record/attribute_assignment.rb b/activerecord/lib/active_record/attribute_assignment.rb index 929045f29b..acb8ba7e5a 100644 --- a/activerecord/lib/active_record/attribute_assignment.rb +++ b/activerecord/lib/active_record/attribute_assignment.rb @@ -7,7 +7,6 @@ module ActiveRecord include ActiveModel::AttributeAssignment private - def _assign_attributes(attributes) multi_parameter_attributes = {} nested_parameter_attributes = {} diff --git a/activerecord/lib/active_record/attribute_decorators.rb b/activerecord/lib/active_record/attribute_decorators.rb index 98b7805c0a..0b66043d2a 100644 --- a/activerecord/lib/active_record/attribute_decorators.rb +++ b/activerecord/lib/active_record/attribute_decorators.rb @@ -46,7 +46,6 @@ module ActiveRecord end private - def load_schema! super attribute_types.each do |name, type| @@ -75,7 +74,6 @@ module ActiveRecord end private - def decorators_for(name, type) matching(name, type).map(&:last) end diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index fd32eaaf3a..21f72bb6c7 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -159,59 +159,6 @@ module ActiveRecord end end - # Regexp for column names (with or without a table name prefix). Matches - # the following: - # "#{table_name}.#{column_name}" - # "#{column_name}" - COLUMN_NAME = /\A(?:\w+\.)?\w+\z/i - - # Regexp for column names with order (with or without a table name - # prefix, with or without various order modifiers). Matches the following: - # "#{table_name}.#{column_name}" - # "#{table_name}.#{column_name} #{direction}" - # "#{table_name}.#{column_name} #{direction} NULLS FIRST" - # "#{table_name}.#{column_name} NULLS LAST" - # "#{column_name}" - # "#{column_name} #{direction}" - # "#{column_name} #{direction} NULLS FIRST" - # "#{column_name} NULLS LAST" - COLUMN_NAME_WITH_ORDER = / - \A - (?:\w+\.)? - \w+ - (?:\s+asc|\s+desc)? - (?:\s+nulls\s+(?:first|last))? - \z - /ix - - def disallow_raw_sql!(args, permit: COLUMN_NAME) # :nodoc: - unexpected = nil - args.each do |arg| - next if arg.is_a?(Symbol) || Arel.arel_node?(arg) || - arg.to_s.split(/\s*,\s*/).all? { |part| permit.match?(part) } - (unexpected ||= []) << arg - end - - return unless unexpected - - if allow_unsafe_raw_sql == :deprecated - ActiveSupport::Deprecation.warn( - "Dangerous query method (method whose arguments are used as raw " \ - "SQL) called with non-attribute argument(s): " \ - "#{unexpected.map(&:inspect).join(", ")}. Non-attribute " \ - "arguments will be disallowed in Rails 6.1. This method should " \ - "not be called with user-provided values, such as request " \ - "parameters or model attributes. Known-safe values can be passed " \ - "by wrapping them in Arel.sql()." - ) - else - raise(ActiveRecord::UnknownAttributeReference, - "Query method called with non-attribute argument(s): " + - unexpected.map(&:inspect).join(", ") - ) - end - end - # Returns true if the given attribute exists, otherwise false. # # class Person < ActiveRecord::Base diff --git a/activerecord/lib/active_record/attribute_methods/before_type_cast.rb b/activerecord/lib/active_record/attribute_methods/before_type_cast.rb index 3d917ec9b1..4a7b6c60e5 100644 --- a/activerecord/lib/active_record/attribute_methods/before_type_cast.rb +++ b/activerecord/lib/active_record/attribute_methods/before_type_cast.rb @@ -66,7 +66,6 @@ module ActiveRecord end private - # Dispatch target for <tt>*_before_type_cast</tt> attribute methods. def attribute_before_type_cast(attribute_name) read_attribute_before_type_cast(attribute_name) diff --git a/activerecord/lib/active_record/attribute_methods/primary_key.rb b/activerecord/lib/active_record/attribute_methods/primary_key.rb index b4f5e6e75a..768c5f8c05 100644 --- a/activerecord/lib/active_record/attribute_methods/primary_key.rb +++ b/activerecord/lib/active_record/attribute_methods/primary_key.rb @@ -45,7 +45,6 @@ module ActiveRecord end private - def attribute_method?(attr_name) attr_name == "id" || super end @@ -120,7 +119,6 @@ module ActiveRecord end private - def suppress_composite_primary_key(pk) return pk unless pk.is_a?(Array) diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb index 0562327a9a..0f0e721b24 100644 --- a/activerecord/lib/active_record/attribute_methods/read.rb +++ b/activerecord/lib/active_record/attribute_methods/read.rb @@ -7,7 +7,6 @@ module ActiveRecord module ClassMethods # :nodoc: private - def define_method_attribute(name) ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method( generated_attribute_methods, name diff --git a/activerecord/lib/active_record/attribute_methods/serialization.rb b/activerecord/lib/active_record/attribute_methods/serialization.rb index 6e0e90f39c..7bc03b9eed 100644 --- a/activerecord/lib/active_record/attribute_methods/serialization.rb +++ b/activerecord/lib/active_record/attribute_methods/serialization.rb @@ -79,7 +79,6 @@ module ActiveRecord end private - def type_incompatible_with_serialize?(type, class_name) type.is_a?(ActiveRecord::Type::Json) && class_name == ::JSON || type.respond_to?(:type_cast_array, true) && class_name == ::Array diff --git a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb index 294a3dc32c..fb44232dff 100644 --- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb +++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb @@ -25,7 +25,6 @@ module ActiveRecord end private - def convert_time_to_time_zone(value) return if value.nil? @@ -64,7 +63,6 @@ module ActiveRecord module ClassMethods # :nodoc: private - def inherited(subclass) super # We need to apply this decorator here, rather than on module inclusion. The closure diff --git a/activerecord/lib/active_record/attribute_methods/write.rb b/activerecord/lib/active_record/attribute_methods/write.rb index 1c63b553d0..66536a8ddf 100644 --- a/activerecord/lib/active_record/attribute_methods/write.rb +++ b/activerecord/lib/active_record/attribute_methods/write.rb @@ -11,7 +11,6 @@ module ActiveRecord module ClassMethods # :nodoc: private - def define_method_attribute=(name) ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method( generated_attribute_methods, name, writer: true, diff --git a/activerecord/lib/active_record/attributes.rb b/activerecord/lib/active_record/attributes.rb index 7cf421c184..c7846dbe7a 100644 --- a/activerecord/lib/active_record/attributes.rb +++ b/activerecord/lib/active_record/attributes.rb @@ -255,7 +255,6 @@ module ActiveRecord end private - NO_DEFAULT_PROVIDED = Object.new # :nodoc: private_constant :NO_DEFAULT_PROVIDED diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index 8d89e7d84a..a7709b444d 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -147,7 +147,6 @@ module ActiveRecord module ClassMethods # :nodoc: private - def define_non_cyclic_method(name, &block) return if instance_methods(false).include?(name) define_method(name) do |*args| @@ -267,7 +266,6 @@ module ActiveRecord end private - # Returns the record for an association collection that should be validated # or saved. If +autosave+ is +false+ only new records will be returned, # unless the parent is/was a new record itself. diff --git a/activerecord/lib/active_record/callbacks.rb b/activerecord/lib/active_record/callbacks.rb index ef5444dfc3..a9ab9ab7a9 100644 --- a/activerecord/lib/active_record/callbacks.rb +++ b/activerecord/lib/active_record/callbacks.rb @@ -323,7 +323,6 @@ module ActiveRecord end private - def create_or_update(**) _run_save_callbacks { super } end diff --git a/activerecord/lib/active_record/coders/yaml_column.rb b/activerecord/lib/active_record/coders/yaml_column.rb index 11559141c7..881f0bcdb0 100644 --- a/activerecord/lib/active_record/coders/yaml_column.rb +++ b/activerecord/lib/active_record/coders/yaml_column.rb @@ -39,7 +39,6 @@ module ActiveRecord end private - def check_arity_of_constructor load(nil) rescue ArgumentError 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 7628ef5537..be804325b3 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb @@ -20,6 +20,26 @@ module ActiveRecord end module ConnectionAdapters + module AbstractPool # :nodoc: + def get_schema_cache(connection) + @schema_cache ||= SchemaCache.new(connection) + @schema_cache.connection = connection + @schema_cache + end + + def set_schema_cache(cache) + @schema_cache = cache + end + end + + class NullPool # :nodoc: + include ConnectionAdapters::AbstractPool + + def initialize + @schema_cache = nil + end + end + # Connection pool base class for managing Active Record database # connections. # @@ -147,7 +167,6 @@ module ActiveRecord end private - def internal_poll(timeout) no_wait_poll || (timeout && wait_poll(timeout)) end @@ -310,7 +329,6 @@ module ActiveRecord end private - def spawn_thread(frequency) Thread.new(frequency) do |t| loop do @@ -336,6 +354,7 @@ module ActiveRecord include MonitorMixin include QueryCache::ConnectionPoolConfiguration + include ConnectionAdapters::AbstractPool attr_accessor :automatic_reconnect, :checkout_timeout, :schema_cache attr_reader :spec, :connections, :size, :reaper @@ -837,7 +856,6 @@ module ActiveRecord def new_connection Base.send(spec.adapter_method, spec.config).tap do |conn| - conn.schema_cache = schema_cache.dup if schema_cache conn.check_version end end @@ -1092,7 +1110,6 @@ module ActiveRecord end private - def owner_to_pool @owner_to_pool[Process.pid] end diff --git a/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb b/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb index a7753e3e9c..6fec4dbd81 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb @@ -109,7 +109,6 @@ module ActiveRecord end private - def cache_sql(sql, name, binds) @lock.synchronize do result = diff --git a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb index 2877530917..1b6ba8ce97 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb @@ -142,6 +142,59 @@ module ActiveRecord value.to_s.gsub(%r{ (/ (?: | \g<1>) \*) \+? \s* | \s* (\* (?: | \g<2>) /) }x, "") end + def column_name_matcher # :nodoc: + COLUMN_NAME + end + + def column_name_with_order_matcher # :nodoc: + COLUMN_NAME_WITH_ORDER + end + + # Regexp for column names (with or without a table name prefix). + # Matches the following: + # + # "#{table_name}.#{column_name}" + # "#{column_name}" + COLUMN_NAME = / + \A + ( + (?: + # table_name.column_name | function(one or no argument) + ((?:\w+\.)?\w+) | \w+\((?:|\g<2>)\) + ) + (?:(?:\s+AS)?\s+\w+)? + ) + (?:\s*,\s*\g<1>)* + \z + /ix + + # Regexp for column names with order (with or without a table name prefix, + # with or without various order modifiers). Matches the following: + # + # "#{table_name}.#{column_name}" + # "#{table_name}.#{column_name} #{direction}" + # "#{table_name}.#{column_name} #{direction} NULLS FIRST" + # "#{table_name}.#{column_name} NULLS LAST" + # "#{column_name}" + # "#{column_name} #{direction}" + # "#{column_name} #{direction} NULLS FIRST" + # "#{column_name} NULLS LAST" + COLUMN_NAME_WITH_ORDER = / + \A + ( + (?: + # table_name.column_name | function(one or no argument) + ((?:\w+\.)?\w+) | \w+\((?:|\g<2>)\) + ) + (?:\s+ASC|\s+DESC)? + (?:\s+NULLS\s+(?:FIRST|LAST))? + ) + (?:\s*,\s*\g<1>)* + \z + /ix + + private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER + private def type_casted_binds(binds) if binds.first.is_a?(Array) diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_creation.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_creation.rb index 7d20825a75..23c993cfc3 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_creation.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_creation.rb @@ -19,7 +19,6 @@ module ActiveRecord to: :@conn, private: true private - def visit_AlterTable(o) sql = +"ALTER TABLE #{quote_table_name(o.name)} " sql << o.adds.map { |col| accept col }.join(" ") 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 cf57af5473..c85ea8e1da 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -310,6 +310,8 @@ module ActiveRecord if force drop_table(table_name, force: force, if_exists: true) + else + schema_cache.clear_data_source_cache!(table_name.to_s) end result = execute schema_creation.accept td @@ -499,6 +501,7 @@ module ActiveRecord # it can be helpful to provide these in a migration's +change+ method so it can be reverted. # In that case, +options+ and the block will be used by #create_table. def drop_table(table_name, options = {}) + schema_cache.clear_data_source_cache!(table_name.to_s) execute "DROP TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}" end diff --git a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb index 7b6321d83b..cc67baf18a 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/transaction.rb @@ -309,7 +309,6 @@ module ActiveRecord end private - NULL_TRANSACTION = NullTransaction.new # Deallocate invalidated prepared statements outside of the transaction diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index bf0bb84c93..cfd986ebf9 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -78,7 +78,7 @@ module ActiveRecord SIMPLE_INT = /\A\d+\z/ attr_accessor :pool - attr_reader :schema_cache, :visitor, :owner, :logger, :lock, :prepared_statements, :prevent_writes + attr_reader :visitor, :owner, :logger, :lock, :prepared_statements, :prevent_writes alias :in_use? :owner set_callback :checkin, :after, :enable_lazy_transactions! @@ -114,9 +114,8 @@ module ActiveRecord @instrumenter = ActiveSupport::Notifications.instrumenter @logger = logger @config = config - @pool = nil + @pool = ActiveRecord::ConnectionAdapters::NullPool.new @idle_since = Concurrent.monotonic_time - @schema_cache = SchemaCache.new self @quoted_column_names, @quoted_table_names = {}, {} @prevent_writes = false @visitor = arel_visitor @@ -206,9 +205,13 @@ module ActiveRecord @owner = Thread.current end + def schema_cache + @pool.get_schema_cache(self) + end + def schema_cache=(cache) cache.connection = self - @schema_cache = cache + @pool.set_schema_cache(cache) end # this method must only be called while holding connection pool's mutex @@ -487,6 +490,9 @@ module ActiveRecord # # Prevent @connection's finalizer from touching the socket, or # otherwise communicating with its server, when it is collected. + if schema_cache.connection == self + schema_cache.connection = nil + end end # Reset the state of this connection, directing the DBMS to clear @@ -587,7 +593,6 @@ module ActiveRecord end private - def type_map @type_map ||= Type::TypeMap.new.tap do |mapping| initialize_type_map(mapping) diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index ef33d712ad..70292e6d63 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -45,7 +45,6 @@ module ActiveRecord class StatementPool < ConnectionAdapters::StatementPool # :nodoc: private - def dealloc(stmt) stmt.close end @@ -289,6 +288,8 @@ module ActiveRecord # Example: # rename_table('octopuses', 'octopi') def rename_table(table_name, new_name) + schema_cache.clear_data_source_cache!(table_name.to_s) + schema_cache.clear_data_source_cache!(new_name.to_s) execute "RENAME TABLE #{quote_table_name(table_name)} TO #{quote_table_name(new_name)}" rename_table_indexes(table_name, new_name) end @@ -309,6 +310,7 @@ module ActiveRecord # it can be helpful to provide these in a migration's +change+ method so it can be reverted. # In that case, +options+ and the block will be used by create_table. def drop_table(table_name, options = {}) + schema_cache.clear_data_source_cache!(table_name.to_s) execute "DROP#{' TEMPORARY' if options[:temporary]} TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}#{' CASCADE' if options[:force] == :cascade}" end @@ -513,7 +515,6 @@ module ActiveRecord end private - def initialize_type_map(m = type_map) super @@ -795,7 +796,6 @@ module ActiveRecord end private - def cast_value(value) case value when true then "1" diff --git a/activerecord/lib/active_record/connection_adapters/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/connection_specification.rb index 9eaf9d9a89..df26f67c6e 100644 --- a/activerecord/lib/active_record/connection_adapters/connection_specification.rb +++ b/activerecord/lib/active_record/connection_adapters/connection_specification.rb @@ -56,7 +56,6 @@ module ActiveRecord end private - attr_reader :uri def uri_parser diff --git a/activerecord/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb b/activerecord/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb index 20c3c83664..edd5ea0542 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb @@ -37,7 +37,6 @@ module ActiveRecord end private - def compute_column_widths(result) [].tap do |widths| result.columns.each_with_index do |column, i| diff --git a/activerecord/lib/active_record/connection_adapters/mysql/quoting.rb b/activerecord/lib/active_record/connection_adapters/mysql/quoting.rb index 75564a61d6..dfed5471f4 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql/quoting.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql/quoting.rb @@ -32,12 +32,49 @@ module ActiveRecord "x'#{value.hex}'" end - def _type_cast(value) - case value - when Date, Time then value - else super - end + def column_name_matcher + COLUMN_NAME + end + + def column_name_with_order_matcher + COLUMN_NAME_WITH_ORDER end + + COLUMN_NAME = / + \A + ( + (?: + # `table_name`.`column_name` | function(one or no argument) + ((?:\w+\.|`\w+`\.)?(?:\w+|`\w+`)) | \w+\((?:|\g<2>)\) + ) + (?:(?:\s+AS)?\s+(?:\w+|`\w+`))? + ) + (?:\s*,\s*\g<1>)* + \z + /ix + + COLUMN_NAME_WITH_ORDER = / + \A + ( + (?: + # `table_name`.`column_name` | function(one or no argument) + ((?:\w+\.|`\w+`\.)?(?:\w+|`\w+`)) | \w+\((?:|\g<2>)\) + ) + (?:\s+ASC|\s+DESC)? + ) + (?:\s*,\s*\g<1>)* + \z + /ix + + private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER + + private + def _type_cast(value) + case value + when Date, Time then value + else super + end + end end end end diff --git a/activerecord/lib/active_record/connection_adapters/mysql/schema_creation.rb b/activerecord/lib/active_record/connection_adapters/mysql/schema_creation.rb index 82ed320617..0f5ab7562a 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql/schema_creation.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql/schema_creation.rb @@ -7,7 +7,6 @@ module ActiveRecord delegate :add_sql_comment!, :mariadb?, to: :@conn, private: true private - def visit_DropForeignKey(name) "DROP FOREIGN KEY #{name}" end diff --git a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb index 5b0335c22b..53510c62c2 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb @@ -109,12 +109,12 @@ module ActiveRecord end def discard! # :nodoc: + super @connection.automatic_close = false @connection = nil end private - def connect @connection = Mysql2::Client.new(@config) configure_connection diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb index b1dfbde86e..0bbe98145a 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/array.rb @@ -77,7 +77,6 @@ module ActiveRecord end private - def type_cast_array(value, method) if value.is_a?(::Array) value.map { |item| type_cast_array(item, method) } diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/enum.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/enum.rb index f70f09ad95..bae34472e1 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/enum.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/enum.rb @@ -10,7 +10,6 @@ module ActiveRecord end private - def cast_value(value) value.to_s end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb index 7b42677101..8d4dacbd64 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb @@ -46,7 +46,6 @@ module ActiveRecord end private - HstorePair = begin quoted_string = /"[^"\\]*(?:\\.[^"\\]*)*"/ unquoted_string = /(?:\\.|[^\s,])[^\s=,\\]*(?:\\.[^\s=,\\]*|=[^,>])*/ diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb index 7f6adc351c..e52d4385ef 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb @@ -34,7 +34,6 @@ module ActiveRecord end private - def number_for_point(number) number.to_s.gsub(/\.0$/, "") end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/point.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/point.rb index 8c74cecc4d..e81e18ff70 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/point.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/point.rb @@ -50,7 +50,6 @@ module ActiveRecord end private - def number_for_point(number) number.to_s.gsub(/\.0$/, "") end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb index aa7701e038..d19f1f9cf8 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb @@ -58,7 +58,6 @@ module ActiveRecord end private - def type_cast_single(value) infinity?(value) ? value : @subtype.deserialize(value) end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/uuid.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/uuid.rb index 28abdbd073..74a28eef58 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/uuid.rb @@ -14,7 +14,6 @@ module ActiveRecord end private - def cast_value(value) casted = value.to_s casted if casted.match?(ACCEPTABLE_UUID) diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb index d40e0ef1f0..0c800dca83 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb @@ -78,6 +78,43 @@ module ActiveRecord type_map.lookup(column.oid, column.fmod, column.sql_type) end + def column_name_matcher + COLUMN_NAME + end + + def column_name_with_order_matcher + COLUMN_NAME_WITH_ORDER + end + + COLUMN_NAME = / + \A + ( + (?: + # "table_name"."column_name"::type_name | function(one or no argument)::type_name + ((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")(?:::\w+)?) | \w+\((?:|\g<2>)\)(?:::\w+)? + ) + (?:(?:\s+AS)?\s+(?:\w+|"\w+"))? + ) + (?:\s*,\s*\g<1>)* + \z + /ix + + COLUMN_NAME_WITH_ORDER = / + \A + ( + (?: + # "table_name"."column_name"::type_name | function(one or no argument)::type_name + ((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")(?:::\w+)?) | \w+\((?:|\g<2>)\)(?:::\w+)? + ) + (?:\s+ASC|\s+DESC)? + (?:\s+NULLS\s+(?:FIRST|LAST))? + ) + (?:\s*,\s*\g<1>)* + \z + /ix + + private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER + private def lookup_cast_type(sql_type) super(query_value("SELECT #{quote(sql_type)}::regtype::oid", "SCHEMA").to_i) diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_dumper.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_dumper.rb index 84643d20da..d201e40190 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_dumper.rb @@ -5,7 +5,6 @@ module ActiveRecord module PostgreSQL class SchemaDumper < ConnectionAdapters::SchemaDumper # :nodoc: private - def extensions(stream) extensions = @connection.extensions if extensions.any? diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb index 40c5e51d92..0062952667 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb @@ -55,6 +55,7 @@ module ActiveRecord end def drop_table(table_name, options = {}) # :nodoc: + schema_cache.clear_data_source_cache!(table_name.to_s) execute "DROP TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}#{' CASCADE' if options[:force] == :cascade}" end @@ -376,6 +377,8 @@ module ActiveRecord # rename_table('octopuses', 'octopi') def rename_table(table_name, new_name) clear_cache! + schema_cache.clear_data_source_cache!(table_name.to_s) + schema_cache.clear_data_source_cache!(new_name.to_s) execute "ALTER TABLE #{quote_table_name(table_name)} RENAME TO #{quote_table_name(new_name)}" pk, seq = pk_and_sequence_for(new_name) if pk diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/utils.rb b/activerecord/lib/active_record/connection_adapters/postgresql/utils.rb index f2f4701500..e8caeb8132 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/utils.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/utils.rb @@ -37,7 +37,6 @@ module ActiveRecord end protected - def parts @parts ||= [@schema, @identifier].compact end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 91318a0af1..6b18a12bce 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -302,6 +302,7 @@ module ActiveRecord end def discard! # :nodoc: + super @connection.socket_io.reopen(IO::NULL) rescue nil @connection = nil end @@ -452,7 +453,6 @@ module ActiveRecord end private - # See https://www.postgresql.org/docs/current/static/errcodes-appendix.html VALUE_LIMIT_VIOLATION = "22001" NUMERIC_VALUE_OUT_OF_RANGE = "22003" diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb b/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb index cb9d32a577..58787cf9db 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3/quoting.rb @@ -45,8 +45,43 @@ module ActiveRecord 0 end - private + def column_name_matcher + COLUMN_NAME + end + + def column_name_with_order_matcher + COLUMN_NAME_WITH_ORDER + end + COLUMN_NAME = / + \A + ( + (?: + # "table_name"."column_name" | function(one or no argument) + ((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")) | \w+\((?:|\g<2>)\) + ) + (?:(?:\s+AS)?\s+(?:\w+|"\w+"))? + ) + (?:\s*,\s*\g<1>)* + \z + /ix + + COLUMN_NAME_WITH_ORDER = / + \A + ( + (?: + # "table_name"."column_name" | function(one or no argument) + ((?:\w+\.|"\w+"\.)?(?:\w+|"\w+")) | \w+\((?:|\g<2>)\) + ) + (?:\s+ASC|\s+DESC)? + ) + (?:\s*,\s*\g<1>)* + \z + /ix + + private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER + + private def _type_cast(value) case value when BigDecimal diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb index 7f3f32162e..e6302112de 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb @@ -218,6 +218,8 @@ module ActiveRecord # Example: # rename_table('octopuses', 'octopi') def rename_table(table_name, new_name) + schema_cache.clear_data_source_cache!(table_name.to_s) + schema_cache.clear_data_source_cache!(new_name.to_s) exec_query "ALTER TABLE #{quote_table_name(table_name)} RENAME TO #{quote_table_name(new_name)}" rename_table_indexes(table_name, new_name) end @@ -477,9 +479,9 @@ module ActiveRecord result = exec_query(sql, "SCHEMA").first if result - # Splitting with left parentheses and picking up last will return all + # Splitting with left parentheses and discarding the first part will return all # columns separated with comma(,). - columns_string = result["sql"].split("(").last + columns_string = result["sql"].split("(", 2).last columns_string.split(",").each do |column_string| # This regex will match the column name and collation type and will save diff --git a/activerecord/lib/active_record/connection_adapters/statement_pool.rb b/activerecord/lib/active_record/connection_adapters/statement_pool.rb index 46bd831da7..0960feed84 100644 --- a/activerecord/lib/active_record/connection_adapters/statement_pool.rb +++ b/activerecord/lib/active_record/connection_adapters/statement_pool.rb @@ -48,7 +48,6 @@ module ActiveRecord end private - def cache @cache[Process.pid] end diff --git a/activerecord/lib/active_record/connection_handling.rb b/activerecord/lib/active_record/connection_handling.rb index 040ebdb960..c8cefa9906 100644 --- a/activerecord/lib/active_record/connection_handling.rb +++ b/activerecord/lib/active_record/connection_handling.rb @@ -173,7 +173,7 @@ module ActiveRecord raise "Anonymous class is not allowed." unless name config_or_env ||= DEFAULT_ENV.call.to_sym - pool_name = self == Base ? "primary" : name + pool_name = primary_class? ? "primary" : name self.connection_specification_name = pool_name resolver = ConnectionAdapters::ConnectionSpecification::Resolver.new(Base.configurations) @@ -204,11 +204,15 @@ module ActiveRecord # Return the specification name from the current class or its parent. def connection_specification_name if !defined?(@connection_specification_name) || @connection_specification_name.nil? - return self == Base ? "primary" : superclass.connection_specification_name + return primary_class? ? "primary" : superclass.connection_specification_name end @connection_specification_name end + def primary_class? # :nodoc: + self == Base || defined?(ApplicationRecord) && self == ApplicationRecord + end + # Returns the configuration of the associated connection as a hash: # # ActiveRecord::Base.connection_config @@ -252,7 +256,6 @@ module ActiveRecord :clear_all_connections!, :flush_idle_connections!, to: :connection_handler private - def swap_connection_handler(handler, &blk) # :nodoc: old_handler, ActiveRecord::Base.connection_handler = ActiveRecord::Base.connection_handler, handler yield diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index dfd33d3dd7..595ef4ee25 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -286,7 +286,6 @@ module ActiveRecord end private - def cached_find_by_statement(key, &block) cache = @find_by_statement_cache[connection.prepared_statements] cache.compute_if_absent(key) { StatementCache.create(connection, &block) } @@ -554,7 +553,6 @@ module ActiveRecord end private - # +Array#flatten+ will call +#to_ary+ (recursively) on each of the elements of # the array, and then rescues from the possible +NoMethodError+. If those elements are # +ActiveRecord::Base+'s, then this triggers the various +method_missing+'s that we have, diff --git a/activerecord/lib/active_record/database_configurations/url_config.rb b/activerecord/lib/active_record/database_configurations/url_config.rb index e2d30ae416..e6b4acc647 100644 --- a/activerecord/lib/active_record/database_configurations/url_config.rb +++ b/activerecord/lib/active_record/database_configurations/url_config.rb @@ -56,7 +56,6 @@ module ActiveRecord end private - def build_url_hash(url) if url.nil? || /^jdbc:/.match?(url) { "url" => url } diff --git a/activerecord/lib/active_record/dynamic_matchers.rb b/activerecord/lib/active_record/dynamic_matchers.rb index 398a029068..7d9e221faa 100644 --- a/activerecord/lib/active_record/dynamic_matchers.rb +++ b/activerecord/lib/active_record/dynamic_matchers.rb @@ -69,7 +69,6 @@ module ActiveRecord end private - def body "#{finder}(#{attributes_hash})" end diff --git a/activerecord/lib/active_record/explain.rb b/activerecord/lib/active_record/explain.rb index 919e96cd7a..5dca75c539 100644 --- a/activerecord/lib/active_record/explain.rb +++ b/activerecord/lib/active_record/explain.rb @@ -36,7 +36,6 @@ module ActiveRecord end private - def render_bind(attr) value = if attr.type.binary? && attr.value "<#{attr.value_for_database.to_s.bytesize} bytes of binary data>" diff --git a/activerecord/lib/active_record/fixture_set/table_row.rb b/activerecord/lib/active_record/fixture_set/table_row.rb index cb4726f1ee..f65329f91d 100644 --- a/activerecord/lib/active_record/fixture_set/table_row.rb +++ b/activerecord/lib/active_record/fixture_set/table_row.rb @@ -48,7 +48,6 @@ module ActiveRecord end private - def model_metadata @table_rows.model_metadata end diff --git a/activerecord/lib/active_record/fixture_set/table_rows.rb b/activerecord/lib/active_record/fixture_set/table_rows.rb index 23814b6cb5..df1cd63963 100644 --- a/activerecord/lib/active_record/fixture_set/table_rows.rb +++ b/activerecord/lib/active_record/fixture_set/table_rows.rb @@ -29,7 +29,6 @@ module ActiveRecord end private - def build_table_rows_from(table_name, fixtures, config) now = config.default_timezone == :utc ? Time.now.utc : Time.now diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb index 327121a2a2..046ed0e95c 100644 --- a/activerecord/lib/active_record/fixtures.rb +++ b/activerecord/lib/active_record/fixtures.rb @@ -464,7 +464,6 @@ module ActiveRecord end private - def insert_class(class_names, name, klass) # We only want to deal with AR objects. if klass && klass < ActiveRecord::Base @@ -570,7 +569,6 @@ module ActiveRecord end private - def read_and_insert(fixtures_directory, fixture_files, class_names, connection) # :nodoc: fixtures_map = {} fixture_sets = fixture_files.map do |fixture_set_name| @@ -661,7 +659,6 @@ module ActiveRecord end private - def model_class=(class_name) if class_name.is_a?(Class) # TODO: Should be an AR::Base type class, or any? @model_class = class_name diff --git a/activerecord/lib/active_record/inheritance.rb b/activerecord/lib/active_record/inheritance.rb index 9570bc6f86..5ca48fa18c 100644 --- a/activerecord/lib/active_record/inheritance.rb +++ b/activerecord/lib/active_record/inheritance.rb @@ -176,7 +176,6 @@ module ActiveRecord end protected - # Returns the class type of the record using the current module as a prefix. So descendants of # MyApp::Business::Account would appear as MyApp::Business::AccountSubclass. def compute_type(type_name) @@ -208,7 +207,6 @@ module ActiveRecord end private - # Called by +instantiate+ to decide which class to use for a new # record instance. For single-table inheritance, we check the record # for a +type+ column and return the corresponding class. @@ -272,7 +270,6 @@ module ActiveRecord end private - def initialize_internals_callback super ensure_proper_type diff --git a/activerecord/lib/active_record/internal_metadata.rb b/activerecord/lib/active_record/internal_metadata.rb index e6166581f1..8f3c6d0ee3 100644 --- a/activerecord/lib/active_record/internal_metadata.rb +++ b/activerecord/lib/active_record/internal_metadata.rb @@ -28,10 +28,6 @@ module ActiveRecord where(key: key).pluck(:value).first end - def table_exists? - connection.table_exists?(table_name) - end - # Creates an internal metadata table with columns +key+ and +value+ def create_table unless table_exists? diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb index 6711ee9bf4..c2a083bf3b 100644 --- a/activerecord/lib/active_record/locking/optimistic.rb +++ b/activerecord/lib/active_record/locking/optimistic.rb @@ -156,7 +156,6 @@ module ActiveRecord end private - # We need to apply this decorator here, rather than on module inclusion. The closure # created by the matcher would otherwise evaluate for `ActiveRecord::Base`, not the # sub class being decorated. As such, changes to `lock_optimistically`, or diff --git a/activerecord/lib/active_record/middleware/database_selector.rb b/activerecord/lib/active_record/middleware/database_selector.rb index 93a1a39c3e..7374107048 100644 --- a/activerecord/lib/active_record/middleware/database_selector.rb +++ b/activerecord/lib/active_record/middleware/database_selector.rb @@ -55,7 +55,6 @@ module ActiveRecord end private - def select_database(request, &blk) context = context_klass.call(request) resolver = resolver_klass.call(context, options) diff --git a/activerecord/lib/active_record/middleware/database_selector/resolver.rb b/activerecord/lib/active_record/middleware/database_selector/resolver.rb index 80b8cd7cae..5b89c8f668 100644 --- a/activerecord/lib/active_record/middleware/database_selector/resolver.rb +++ b/activerecord/lib/active_record/middleware/database_selector/resolver.rb @@ -44,7 +44,6 @@ module ActiveRecord end private - def read_from_primary(&blk) ActiveRecord::Base.connection.while_preventing_writes do ActiveRecord::Base.connected_to(role: ActiveRecord::Base.writing_role) do diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index f20edbeb93..fa9b650416 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -568,7 +568,6 @@ module ActiveRecord end private - def connection ActiveRecord::Base.connection end @@ -992,7 +991,6 @@ module ActiveRecord delegate :migrate, :announce, :write, :disable_ddl_transaction, to: :migration private - def migration @migration ||= load_migration end @@ -1250,7 +1248,6 @@ module ActiveRecord end private - # Used for running a specific migration. def run_without_lock migration = migrations.detect { |m| m.version == @target_version } diff --git a/activerecord/lib/active_record/migration/command_recorder.rb b/activerecord/lib/active_record/migration/command_recorder.rb index efed4b0e26..67172ef395 100644 --- a/activerecord/lib/active_record/migration/command_recorder.rb +++ b/activerecord/lib/active_record/migration/command_recorder.rb @@ -118,7 +118,6 @@ module ActiveRecord end private - module StraightReversions # :nodoc: private { diff --git a/activerecord/lib/active_record/migration/join_table.rb b/activerecord/lib/active_record/migration/join_table.rb index 9abb289bb0..45169617c1 100644 --- a/activerecord/lib/active_record/migration/join_table.rb +++ b/activerecord/lib/active_record/migration/join_table.rb @@ -4,7 +4,6 @@ module ActiveRecord class Migration module JoinTable #:nodoc: private - def find_join_table_name(table_1, table_2, options = {}) options.delete(:table_name) || join_table_name(table_1, table_2) end diff --git a/activerecord/lib/active_record/model_schema.rb b/activerecord/lib/active_record/model_schema.rb index 55fc58e339..2a45f63d64 100644 --- a/activerecord/lib/active_record/model_schema.rb +++ b/activerecord/lib/active_record/model_schema.rb @@ -456,13 +456,11 @@ module ActiveRecord end protected - def initialize_load_schema_monitor @load_schema_monitor = Monitor.new end private - def inherited(child_class) super child_class.initialize_load_schema_monitor diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index 8b9098df6c..cab2369b71 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -354,7 +354,6 @@ module ActiveRecord end private - # Generates a writer method for this association. Serves as a point for # accessing the objects in the association. For example, this method # could generate the following: @@ -386,7 +385,6 @@ module ActiveRecord end private - # Attribute hash keys that should not be assigned as normal attributes. # These hash keys are nested attributes implementation details. UNASSIGNABLE_KEYS = %w( id _destroy ) diff --git a/activerecord/lib/active_record/null_relation.rb b/activerecord/lib/active_record/null_relation.rb index cf0de0fdeb..bee5b5f24a 100644 --- a/activerecord/lib/active_record/null_relation.rb +++ b/activerecord/lib/active_record/null_relation.rb @@ -60,7 +60,6 @@ module ActiveRecord end private - def exec_queries @records = [].freeze end diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index b7bc4b3b8e..323b01ab2d 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -865,7 +865,6 @@ module ActiveRecord end private - # A hook to be overridden by association modules. def destroy_associations end diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index a1d7c893bf..d5375390c7 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -134,7 +134,6 @@ end_error cache = YAML.load(File.read(filename)) if cache.version == current_version - connection.schema_cache = cache connection_pool.schema_cache = cache.dup else warn "Ignoring db/schema_cache.yml because it has expired. The current schema version is #{current_version}, but the one in the cache is #{cache.version}." diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index e0bc5180c0..d17acc408c 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -250,7 +250,11 @@ db_namespace = namespace :db do # desc "Raises an error if there are pending migrations" task abort_if_pending_migrations: :load_config do - pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations + pending_migrations = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).flat_map do |db_config| + ActiveRecord::Base.establish_connection(db_config.config) + + ActiveRecord::Base.connection.migration_context.open.pending_migrations + end if pending_migrations.any? puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}" @@ -261,17 +265,56 @@ db_namespace = namespace :db do end end + namespace :abort_if_pending_migrations do + ActiveRecord::Tasks::DatabaseTasks.for_each do |spec_name| + # desc "Raises an error if there are pending migrations for #{spec_name} database" + task spec_name => :load_config do + db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name) + ActiveRecord::Base.establish_connection(db_config.config) + + pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations + + if pending_migrations.any? + puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}" + pending_migrations.each do |pending_migration| + puts " %4d %s" % [pending_migration.version, pending_migration.name] + end + abort %{Run `rails db:migrate:#{spec_name}` to update your database then try again.} + end + end + end + end + desc "Creates the database, loads the schema, and initializes with the seed data (use db:reset to also drop the database first)" task setup: ["db:schema:load_if_ruby", "db:structure:load_if_sql", :seed] desc "Runs setup if database does not exist, or runs migrations if it does" task prepare: :load_config do + seed = false + ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config| ActiveRecord::Base.establish_connection(db_config.config) - db_namespace["migrate"].invoke + + ActiveRecord::Tasks::DatabaseTasks.migrate + + # Skipped when no database + ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config.config, ActiveRecord::Base.schema_format, db_config.spec_name) + rescue ActiveRecord::NoDatabaseError - db_namespace["setup"].invoke + ActiveRecord::Tasks::DatabaseTasks.create_current(db_config.env_name, db_config.spec_name) + ActiveRecord::Tasks::DatabaseTasks.load_schema( + db_config.config, + ActiveRecord::Base.schema_format, + nil, + db_config.env_name, + db_config.spec_name + ) + + seed = true end + + ActiveRecord::Base.establish_connection + ActiveRecord::Tasks::DatabaseTasks.load_seed if seed end desc "Loads the seed data from db/seeds.rb" @@ -336,13 +379,9 @@ db_namespace = namespace :db do namespace :schema do desc "Creates a db/schema.rb file that is portable against any DB supported by Active Record" task dump: :load_config do - require "active_record/schema_dumper" ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config| - filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(db_config.spec_name, :ruby) - File.open(filename, "w:utf-8") do |file| - ActiveRecord::Base.establish_connection(db_config.config) - ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file) - end + ActiveRecord::Base.establish_connection(db_config.config) + ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config.config, :ruby, db_config.spec_name) end db_namespace["schema:dump"].reenable @@ -385,14 +424,7 @@ db_namespace = namespace :db do task dump: :load_config do ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config| ActiveRecord::Base.establish_connection(db_config.config) - filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(db_config.spec_name, :sql) - ActiveRecord::Tasks::DatabaseTasks.structure_dump(db_config.config, filename) - if ActiveRecord::SchemaMigration.table_exists? - File.open(filename, "a") do |f| - f.puts ActiveRecord::Base.connection.dump_schema_information - f.print "\n" - end - end + ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config.config, :sql, db_config.spec_name) end db_namespace["structure:dump"].reenable diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index eefda2b8f4..cbfa60d4d9 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -590,7 +590,6 @@ module ActiveRecord end private - def calculate_constructable(macro, options) true end @@ -704,7 +703,6 @@ module ActiveRecord end private - def calculate_constructable(macro, options) !options[:through] end diff --git a/activerecord/lib/active_record/relation/batches.rb b/activerecord/lib/active_record/relation/batches.rb index 9c579843b1..30b8edd0bd 100644 --- a/activerecord/lib/active_record/relation/batches.rb +++ b/activerecord/lib/active_record/relation/batches.rb @@ -258,7 +258,6 @@ module ActiveRecord end private - def apply_limits(relation, start, finish) relation = apply_start_limit(relation, start) if start relation = apply_finish_limit(relation, finish) if finish diff --git a/activerecord/lib/active_record/relation/delegation.rb b/activerecord/lib/active_record/relation/delegation.rb index d59331053e..2f61c05eca 100644 --- a/activerecord/lib/active_record/relation/delegation.rb +++ b/activerecord/lib/active_record/relation/delegation.rb @@ -99,7 +99,6 @@ module ActiveRecord end private - def method_missing(method, *args, &block) if @klass.respond_to?(method) @klass.generate_relation_method(method) @@ -116,7 +115,6 @@ module ActiveRecord end private - def relation_class_for(klass) klass.relation_delegate_class(self) end diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 9c7ac80447..6deb9c7da8 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -346,7 +346,6 @@ module ActiveRecord end private - def offset_index offset_value || 0 end diff --git a/activerecord/lib/active_record/relation/merger.rb b/activerecord/lib/active_record/relation/merger.rb index 84fe424ef0..e1735c0522 100644 --- a/activerecord/lib/active_record/relation/merger.rb +++ b/activerecord/lib/active_record/relation/merger.rb @@ -89,7 +89,6 @@ module ActiveRecord end private - def merge_preloads return if other.preload_values.empty? && other.includes_values.empty? diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 50ff733dc7..d1bcec9704 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -1247,6 +1247,7 @@ module ActiveRecord end def preprocess_order_args(order_args) + order_args.reject!(&:blank?) order_args.map! do |arg| klass.sanitize_sql_for_order(arg) end @@ -1254,7 +1255,7 @@ module ActiveRecord @klass.disallow_raw_sql!( order_args.flat_map { |a| a.is_a?(Hash) ? a.keys : a }, - permit: AttributeMethods::ClassMethods::COLUMN_NAME_WITH_ORDER + permit: connection.column_name_with_order_matcher ) validate_order_args(order_args) diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb index efc4b447aa..3f6dd50139 100644 --- a/activerecord/lib/active_record/relation/spawn_methods.rb +++ b/activerecord/lib/active_record/relation/spawn_methods.rb @@ -67,7 +67,6 @@ module ActiveRecord end private - def relation_with(values) result = Relation.create(klass, values: values) result.extend(*extending_values) if extending_values.any? diff --git a/activerecord/lib/active_record/relation/where_clause.rb b/activerecord/lib/active_record/relation/where_clause.rb index b91b135867..8fae380b0a 100644 --- a/activerecord/lib/active_record/relation/where_clause.rb +++ b/activerecord/lib/active_record/relation/where_clause.rb @@ -87,7 +87,6 @@ module ActiveRecord end protected - attr_reader :predicates def referenced_columns diff --git a/activerecord/lib/active_record/result.rb b/activerecord/lib/active_record/result.rb index da6d10b6ec..3b615f29a3 100644 --- a/activerecord/lib/active_record/result.rb +++ b/activerecord/lib/active_record/result.rb @@ -132,7 +132,6 @@ module ActiveRecord end private - def column_type(name, type_overrides = {}) type_overrides.fetch(name) do column_types.fetch(name, Type.default_value) diff --git a/activerecord/lib/active_record/sanitization.rb b/activerecord/lib/active_record/sanitization.rb index 750766714d..b16cbb0f84 100644 --- a/activerecord/lib/active_record/sanitization.rb +++ b/activerecord/lib/active_record/sanitization.rb @@ -61,8 +61,9 @@ module ActiveRecord # # => "id ASC" def sanitize_sql_for_order(condition) if condition.is_a?(Array) && condition.first.to_s.include?("?") - disallow_raw_sql!([condition.first], - permit: AttributeMethods::ClassMethods::COLUMN_NAME_WITH_ORDER + disallow_raw_sql!( + [condition.first], + permit: connection.column_name_with_order_matcher ) # Ensure we aren't dealing with a subclass of String that might @@ -133,6 +134,33 @@ module ActiveRecord end end + def disallow_raw_sql!(args, permit: connection.column_name_matcher) # :nodoc: + unexpected = nil + args.each do |arg| + next if arg.is_a?(Symbol) || Arel.arel_node?(arg) || permit.match?(arg.to_s) + (unexpected ||= []) << arg + end + + return unless unexpected + + if allow_unsafe_raw_sql == :deprecated + ActiveSupport::Deprecation.warn( + "Dangerous query method (method whose arguments are used as raw " \ + "SQL) called with non-attribute argument(s): " \ + "#{unexpected.map(&:inspect).join(", ")}. Non-attribute " \ + "arguments will be disallowed in Rails 6.1. This method should " \ + "not be called with user-provided values, such as request " \ + "parameters or model attributes. Known-safe values can be passed " \ + "by wrapping them in Arel.sql()." + ) + else + raise(ActiveRecord::UnknownAttributeReference, + "Query method called with non-attribute argument(s): " + + unexpected.map(&:inspect).join(", ") + ) + end + end + private def replace_bind_variables(statement, values) raise_if_bind_arity_mismatch(statement, statement.count("?"), values.size) diff --git a/activerecord/lib/active_record/schema_migration.rb b/activerecord/lib/active_record/schema_migration.rb index 74547de862..dec7fee986 100644 --- a/activerecord/lib/active_record/schema_migration.rb +++ b/activerecord/lib/active_record/schema_migration.rb @@ -22,10 +22,6 @@ module ActiveRecord "#{table_name_prefix}#{schema_migrations_table_name}#{table_name_suffix}" end - def table_exists? - connection.table_exists?(table_name) - end - def create_table unless table_exists? version_options = connection.internal_string_options_for_primary_key diff --git a/activerecord/lib/active_record/scoping.rb b/activerecord/lib/active_record/scoping.rb index 35e9dcbffc..62c7988bd8 100644 --- a/activerecord/lib/active_record/scoping.rb +++ b/activerecord/lib/active_record/scoping.rb @@ -95,7 +95,6 @@ module ActiveRecord end private - def raise_invalid_scope_type!(scope_type) if !VALID_SCOPE_TYPES.include?(scope_type) raise ArgumentError, "Invalid scope type '#{scope_type}' sent to the registry. Scope types must be included in VALID_SCOPE_TYPES" diff --git a/activerecord/lib/active_record/scoping/default.rb b/activerecord/lib/active_record/scoping/default.rb index 87bcfd5181..151eef362b 100644 --- a/activerecord/lib/active_record/scoping/default.rb +++ b/activerecord/lib/active_record/scoping/default.rb @@ -44,7 +44,6 @@ module ActiveRecord end private - # Use this macro in your model to set a default scope for all operations on # the model. # diff --git a/activerecord/lib/active_record/scoping/named.rb b/activerecord/lib/active_record/scoping/named.rb index cd9801b7a0..7baef99e83 100644 --- a/activerecord/lib/active_record/scoping/named.rb +++ b/activerecord/lib/active_record/scoping/named.rb @@ -204,7 +204,6 @@ module ActiveRecord end private - def valid_scope_name?(name) if respond_to?(name, true) && logger logger.warn "Creating scope :#{name}. " \ diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb index c79ed8db60..cf98a203bd 100644 --- a/activerecord/lib/active_record/tasks/database_tasks.rb +++ b/activerecord/lib/active_record/tasks/database_tasks.rb @@ -169,8 +169,8 @@ module ActiveRecord end end - def create_current(environment = env) - each_current_configuration(environment) { |configuration| + def create_current(environment = env, spec_name = nil) + each_current_configuration(environment, spec_name) { |configuration| create configuration } ActiveRecord::Base.establish_connection(environment.to_sym) @@ -325,6 +325,26 @@ module ActiveRecord Migration.verbose = verbose_was end + def dump_schema(configuration, format = ActiveRecord::Base.schema_format, spec_name = "primary") # :nodoc: + require "active_record/schema_dumper" + filename = dump_filename(spec_name, format) + + case format + when :ruby + File.open(filename, "w:utf-8") do |file| + ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file) + end + when :sql + structure_dump(configuration, filename) + if ActiveRecord::SchemaMigration.table_exists? + File.open(filename, "a") do |f| + f.puts ActiveRecord::Base.connection.dump_schema_information + f.print "\n" + end + end + end + end + def schema_file(format = ActiveRecord::Base.schema_format) File.join(db_dir, schema_file_type(format)) end @@ -406,12 +426,14 @@ module ActiveRecord task.is_a?(String) ? task.constantize : task end - def each_current_configuration(environment) + def each_current_configuration(environment, spec_name = nil) environments = [environment] environments << "test" if environment == "development" environments.each do |env| ActiveRecord::Base.configurations.configs_for(env_name: env).each do |db_config| + next if spec_name && spec_name != db_config.spec_name + yield db_config.config, db_config.spec_name, env end end diff --git a/activerecord/lib/active_record/tasks/mysql_database_tasks.rb b/activerecord/lib/active_record/tasks/mysql_database_tasks.rb index 1c1b29b5e1..0d9917a4db 100644 --- a/activerecord/lib/active_record/tasks/mysql_database_tasks.rb +++ b/activerecord/lib/active_record/tasks/mysql_database_tasks.rb @@ -67,7 +67,6 @@ module ActiveRecord end private - attr_reader :configuration def configuration_without_database diff --git a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb index 8acb11f75f..626ffdfdf9 100644 --- a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb +++ b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb @@ -89,7 +89,6 @@ module ActiveRecord end private - attr_reader :configuration def encoding diff --git a/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb b/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb index a82cea80ca..f67a3498b6 100644 --- a/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb +++ b/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb @@ -59,7 +59,6 @@ module ActiveRecord end private - attr_reader :configuration, :root def run_cmd(cmd, args, out) diff --git a/activerecord/lib/active_record/test_fixtures.rb b/activerecord/lib/active_record/test_fixtures.rb index 8c60d71669..1d6fef1eb9 100644 --- a/activerecord/lib/active_record/test_fixtures.rb +++ b/activerecord/lib/active_record/test_fixtures.rb @@ -179,7 +179,6 @@ module ActiveRecord end private - # Shares the writing connection pool with connections on # other handlers. # diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb index a5862ae06b..c883d368b5 100644 --- a/activerecord/lib/active_record/timestamp.rb +++ b/activerecord/lib/active_record/timestamp.rb @@ -96,7 +96,6 @@ module ActiveRecord end private - def _create_record if record_timestamps current_time = current_time_from_proper_timezone diff --git a/activerecord/lib/active_record/touch_later.rb b/activerecord/lib/active_record/touch_later.rb index bc63c8d987..3981bd46ad 100644 --- a/activerecord/lib/active_record/touch_later.rb +++ b/activerecord/lib/active_record/touch_later.rb @@ -36,7 +36,6 @@ module ActiveRecord end private - def surreptitiously_touch(attrs) attrs.each { |attr| write_attribute attr, @_touch_time } clear_attribute_changes attrs diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb index cbb970ac98..5113e08e8e 100644 --- a/activerecord/lib/active_record/transactions.rb +++ b/activerecord/lib/active_record/transactions.rb @@ -282,7 +282,6 @@ module ActiveRecord end private - def set_options_for_callbacks!(args, enforced_options = {}) options = args.extract_options!.merge!(enforced_options) args << options diff --git a/activerecord/lib/active_record/type.rb b/activerecord/lib/active_record/type.rb index 03d00006b7..4c1ef1a7e4 100644 --- a/activerecord/lib/active_record/type.rb +++ b/activerecord/lib/active_record/type.rb @@ -47,7 +47,6 @@ module ActiveRecord end private - def current_adapter_name ActiveRecord::Base.connection.adapter_name.downcase.to_sym end diff --git a/activerecord/lib/active_record/type/adapter_specific_registry.rb b/activerecord/lib/active_record/type/adapter_specific_registry.rb index b300fdfa05..c8c16635b1 100644 --- a/activerecord/lib/active_record/type/adapter_specific_registry.rb +++ b/activerecord/lib/active_record/type/adapter_specific_registry.rb @@ -11,7 +11,6 @@ module ActiveRecord end private - def registration_klass Registration end @@ -53,7 +52,6 @@ module ActiveRecord end protected - attr_reader :name, :block, :adapter, :override def priority @@ -72,7 +70,6 @@ module ActiveRecord end private - def matches_adapter?(adapter: nil, **) (self.adapter.nil? || adapter == self.adapter) end diff --git a/activerecord/lib/active_record/type/hash_lookup_type_map.rb b/activerecord/lib/active_record/type/hash_lookup_type_map.rb index db9853fbcc..b260464df5 100644 --- a/activerecord/lib/active_record/type/hash_lookup_type_map.rb +++ b/activerecord/lib/active_record/type/hash_lookup_type_map.rb @@ -16,7 +16,6 @@ module ActiveRecord end private - def perform_fetch(type, *args, &block) @mapping.fetch(type, block).call(type, *args) end diff --git a/activerecord/lib/active_record/type/serialized.rb b/activerecord/lib/active_record/type/serialized.rb index 0a2f6cb9fb..a34b2fe702 100644 --- a/activerecord/lib/active_record/type/serialized.rb +++ b/activerecord/lib/active_record/type/serialized.rb @@ -56,7 +56,6 @@ module ActiveRecord end private - def default_value?(value) value == coder.load(nil) end diff --git a/activerecord/lib/active_record/type/type_map.rb b/activerecord/lib/active_record/type/type_map.rb index fc40b460f0..58f25ba075 100644 --- a/activerecord/lib/active_record/type/type_map.rb +++ b/activerecord/lib/active_record/type/type_map.rb @@ -45,7 +45,6 @@ module ActiveRecord end private - def perform_fetch(lookup_key, *args) matching_pair = @mapping.reverse_each.detect do |key, _| key === lookup_key diff --git a/activerecord/lib/active_record/type/unsigned_integer.rb b/activerecord/lib/active_record/type/unsigned_integer.rb index 4619528f81..535369e630 100644 --- a/activerecord/lib/active_record/type/unsigned_integer.rb +++ b/activerecord/lib/active_record/type/unsigned_integer.rb @@ -4,7 +4,6 @@ module ActiveRecord module Type class UnsignedInteger < ActiveModel::Type::Integer # :nodoc: private - def max_value super * 2 end diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb index ca27a3f0ab..23e8d53168 100644 --- a/activerecord/lib/active_record/validations.rb +++ b/activerecord/lib/active_record/validations.rb @@ -71,7 +71,6 @@ module ActiveRecord alias_method :validate, :valid? private - def default_validation_context new_record? ? :create : :update end diff --git a/activerecord/lib/active_record/validations/associated.rb b/activerecord/lib/active_record/validations/associated.rb index 3538aeec22..dc89df4be7 100644 --- a/activerecord/lib/active_record/validations/associated.rb +++ b/activerecord/lib/active_record/validations/associated.rb @@ -10,7 +10,6 @@ module ActiveRecord end private - def valid_object?(record) (record.respond_to?(:marked_for_destruction?) && record.marked_for_destruction?) || record.valid? end diff --git a/activerecord/lib/arel/predications.rb b/activerecord/lib/arel/predications.rb index 7dafde4952..dece478615 100644 --- a/activerecord/lib/arel/predications.rb +++ b/activerecord/lib/arel/predications.rb @@ -221,7 +221,6 @@ Passing a range to `#not_in` is deprecated. Call `#not_between`, instead. end private - def grouping_any(method_id, others, *extras) nodes = others.map { |expr| send(method_id, expr, *extras) } Nodes::Grouping.new nodes.inject { |memo, node| diff --git a/activerecord/lib/arel/visitors/depth_first.rb b/activerecord/lib/arel/visitors/depth_first.rb index d696edc507..ca11d9c879 100644 --- a/activerecord/lib/arel/visitors/depth_first.rb +++ b/activerecord/lib/arel/visitors/depth_first.rb @@ -9,7 +9,6 @@ module Arel # :nodoc: all end private - def visit(o) super @block.call o diff --git a/activerecord/lib/arel/visitors/dot.rb b/activerecord/lib/arel/visitors/dot.rb index ecc386de07..c4ea07bcfe 100644 --- a/activerecord/lib/arel/visitors/dot.rb +++ b/activerecord/lib/arel/visitors/dot.rb @@ -31,7 +31,6 @@ module Arel # :nodoc: all end private - def visit_Arel_Nodes_Ordering(o) visit_edge o, "expr" end diff --git a/activerecord/lib/arel/visitors/mssql.rb b/activerecord/lib/arel/visitors/mssql.rb index 8475139870..92eb94f802 100644 --- a/activerecord/lib/arel/visitors/mssql.rb +++ b/activerecord/lib/arel/visitors/mssql.rb @@ -11,7 +11,6 @@ module Arel # :nodoc: all end private - def visit_Arel_Nodes_IsNotDistinctFrom(o, collector) right = o.right diff --git a/activerecord/lib/arel/visitors/oracle.rb b/activerecord/lib/arel/visitors/oracle.rb index f96bf65ee5..aab66301ef 100644 --- a/activerecord/lib/arel/visitors/oracle.rb +++ b/activerecord/lib/arel/visitors/oracle.rb @@ -4,7 +4,6 @@ module Arel # :nodoc: all module Visitors class Oracle < Arel::Visitors::ToSql private - def visit_Arel_Nodes_SelectStatement(o, collector) o = order_hacks(o) diff --git a/activerecord/lib/arel/visitors/oracle12.rb b/activerecord/lib/arel/visitors/oracle12.rb index 6269bc3907..36783243b5 100644 --- a/activerecord/lib/arel/visitors/oracle12.rb +++ b/activerecord/lib/arel/visitors/oracle12.rb @@ -4,7 +4,6 @@ module Arel # :nodoc: all module Visitors class Oracle12 < Arel::Visitors::ToSql private - def visit_Arel_Nodes_SelectStatement(o, collector) # Oracle does not allow LIMIT clause with select for update if o.limit && o.lock diff --git a/activerecord/lib/arel/visitors/postgresql.rb b/activerecord/lib/arel/visitors/postgresql.rb index 8296f1cdc1..d4f21ff93e 100644 --- a/activerecord/lib/arel/visitors/postgresql.rb +++ b/activerecord/lib/arel/visitors/postgresql.rb @@ -4,7 +4,6 @@ module Arel # :nodoc: all module Visitors class PostgreSQL < Arel::Visitors::ToSql private - def visit_Arel_Nodes_Matches(o, collector) op = o.case_sensitive ? " LIKE " : " ILIKE " collector = infix_value o, collector, op diff --git a/activerecord/lib/arel/visitors/sqlite.rb b/activerecord/lib/arel/visitors/sqlite.rb index af6f7e856a..62ec74ad82 100644 --- a/activerecord/lib/arel/visitors/sqlite.rb +++ b/activerecord/lib/arel/visitors/sqlite.rb @@ -4,7 +4,6 @@ module Arel # :nodoc: all module Visitors class SQLite < Arel::Visitors::ToSql private - # Locks are not supported in SQLite def visit_Arel_Nodes_Lock(o, collector) collector diff --git a/activerecord/lib/arel/visitors/to_sql.rb b/activerecord/lib/arel/visitors/to_sql.rb index 4740e6d94f..a67a660fed 100644 --- a/activerecord/lib/arel/visitors/to_sql.rb +++ b/activerecord/lib/arel/visitors/to_sql.rb @@ -19,7 +19,6 @@ module Arel # :nodoc: all end private - def visit_Arel_Nodes_DeleteStatement(o, collector) o = prepare_delete_statement(o) diff --git a/activerecord/lib/arel/visitors/visitor.rb b/activerecord/lib/arel/visitors/visitor.rb index 1c17184e86..2d5a2b6681 100644 --- a/activerecord/lib/arel/visitors/visitor.rb +++ b/activerecord/lib/arel/visitors/visitor.rb @@ -12,7 +12,6 @@ module Arel # :nodoc: all end private - attr_reader :dispatch def self.dispatch_cache diff --git a/activerecord/lib/arel/visitors/where_sql.rb b/activerecord/lib/arel/visitors/where_sql.rb index c6caf5e7c9..8fb299d1c8 100644 --- a/activerecord/lib/arel/visitors/where_sql.rb +++ b/activerecord/lib/arel/visitors/where_sql.rb @@ -9,7 +9,6 @@ module Arel # :nodoc: all end private - def visit_Arel_Nodes_SelectCore(o, collector) collector << "WHERE " wheres = o.wheres.map do |where| diff --git a/activerecord/lib/rails/generators/active_record/application_record/application_record_generator.rb b/activerecord/lib/rails/generators/active_record/application_record/application_record_generator.rb index 35d5664400..56b9628a92 100644 --- a/activerecord/lib/rails/generators/active_record/application_record/application_record_generator.rb +++ b/activerecord/lib/rails/generators/active_record/application_record/application_record_generator.rb @@ -13,7 +13,6 @@ module ActiveRecord end private - def application_record_file_name @application_record_file_name ||= if namespaced? diff --git a/activerecord/lib/rails/generators/active_record/migration.rb b/activerecord/lib/rails/generators/active_record/migration.rb index cbb88d571d..af753071a9 100644 --- a/activerecord/lib/rails/generators/active_record/migration.rb +++ b/activerecord/lib/rails/generators/active_record/migration.rb @@ -17,7 +17,6 @@ module ActiveRecord end private - def primary_key_type key_type = options[:primary_key_type] ", id: :#{key_type}" if key_type diff --git a/activerecord/lib/rails/generators/active_record/model/model_generator.rb b/activerecord/lib/rails/generators/active_record/model/model_generator.rb index c71bbdcab8..d4733f948f 100644 --- a/activerecord/lib/rails/generators/active_record/model/model_generator.rb +++ b/activerecord/lib/rails/generators/active_record/model/model_generator.rb @@ -35,7 +35,6 @@ module ActiveRecord hook_for :test_framework private - def attributes_with_index attributes.select { |a| !a.reference? && a.has_index? } end diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb index ce2ed06c1d..276bdf8a8d 100644 --- a/activerecord/test/cases/adapter_test.rb +++ b/activerecord/test/cases/adapter_test.rb @@ -559,7 +559,6 @@ module ActiveRecord end private - def reset_fixtures(*fixture_names) ActiveRecord::FixtureSet.reset_cache diff --git a/activerecord/test/cases/adapters/mysql2/connection_test.rb b/activerecord/test/cases/adapters/mysql2/connection_test.rb index 9c6566106a..cb7461a8d5 100644 --- a/activerecord/test/cases/adapters/mysql2/connection_test.rb +++ b/activerecord/test/cases/adapters/mysql2/connection_test.rb @@ -197,7 +197,6 @@ class Mysql2ConnectionTest < ActiveRecord::Mysql2TestCase end private - def test_lock_free(lock_name) @connection.select_value("SELECT IS_FREE_LOCK(#{@connection.quote(lock_name)})") == 1 end diff --git a/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb b/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb index 6ade2eec24..9364fabb35 100644 --- a/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb +++ b/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb @@ -213,7 +213,6 @@ class Mysql2AdapterTest < ActiveRecord::Mysql2TestCase end private - def with_example_table(definition = "id int auto_increment primary key, number int, data varchar(255)", &block) super(@conn, "ex", definition, &block) end diff --git a/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb b/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb index d7d9a2d732..182d5a3e58 100644 --- a/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb +++ b/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb @@ -40,7 +40,6 @@ class SchemaMigrationsTest < ActiveRecord::Mysql2TestCase end private - def with_encoding_utf8mb4 database_name = connection.current_database database_info = connection.select_one("SELECT * FROM information_schema.schemata WHERE schema_name = '#{database_name}'") diff --git a/activerecord/test/cases/adapters/postgresql/connection_test.rb b/activerecord/test/cases/adapters/postgresql/connection_test.rb index 9494863a75..dcee4fd22d 100644 --- a/activerecord/test/cases/adapters/postgresql/connection_test.rb +++ b/activerecord/test/cases/adapters/postgresql/connection_test.rb @@ -239,7 +239,6 @@ module ActiveRecord end private - def with_warning_suppression log_level = @connection.client_min_messages @connection.client_min_messages = "error" diff --git a/activerecord/test/cases/adapters/postgresql/geometric_test.rb b/activerecord/test/cases/adapters/postgresql/geometric_test.rb index 14c262f4ce..f312b6e23d 100644 --- a/activerecord/test/cases/adapters/postgresql/geometric_test.rb +++ b/activerecord/test/cases/adapters/postgresql/geometric_test.rb @@ -361,7 +361,6 @@ class PostgreSQLGeometricTypesTest < ActiveRecord::PostgreSQLTestCase end private - def assert_column_exists(column_name) assert connection.column_exists?(table_name, column_name) end diff --git a/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb b/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb index fbd3cbf90f..bc517cef82 100644 --- a/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb +++ b/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb @@ -443,7 +443,6 @@ module ActiveRecord end private - def with_example_table(definition = "id serial primary key, number integer, data character varying(255)", &block) super(@connection, "ex", definition, &block) end diff --git a/activerecord/test/cases/adapters/postgresql/referential_integrity_test.rb b/activerecord/test/cases/adapters/postgresql/referential_integrity_test.rb index 96cfabf58f..a4f722c063 100644 --- a/activerecord/test/cases/adapters/postgresql/referential_integrity_test.rb +++ b/activerecord/test/cases/adapters/postgresql/referential_integrity_test.rb @@ -106,7 +106,6 @@ class PostgreSQLReferentialIntegrityTest < ActiveRecord::PostgreSQLTestCase end private - def assert_transaction_is_not_broken assert_equal 1, @connection.select_value("SELECT 1") end diff --git a/activerecord/test/cases/adapters/postgresql/rename_table_test.rb b/activerecord/test/cases/adapters/postgresql/rename_table_test.rb index 7eccaf4aa2..fae20de086 100644 --- a/activerecord/test/cases/adapters/postgresql/rename_table_test.rb +++ b/activerecord/test/cases/adapters/postgresql/rename_table_test.rb @@ -25,7 +25,6 @@ class PostgresqlRenameTableTest < ActiveRecord::PostgreSQLTestCase end private - def num_indices_named(name) @connection.execute(<<~SQL).values.length SELECT 1 FROM "pg_index" diff --git a/activerecord/test/cases/adapters/postgresql/transaction_test.rb b/activerecord/test/cases/adapters/postgresql/transaction_test.rb index 919ff3d158..311863a418 100644 --- a/activerecord/test/cases/adapters/postgresql/transaction_test.rb +++ b/activerecord/test/cases/adapters/postgresql/transaction_test.rb @@ -177,7 +177,6 @@ module ActiveRecord end private - def with_warning_suppression log_level = ActiveRecord::Base.connection.client_min_messages ActiveRecord::Base.connection.client_min_messages = "error" diff --git a/activerecord/test/cases/adapters/postgresql/uuid_test.rb b/activerecord/test/cases/adapters/postgresql/uuid_test.rb index d2d8ea8042..4b8aeb33f6 100644 --- a/activerecord/test/cases/adapters/postgresql/uuid_test.rb +++ b/activerecord/test/cases/adapters/postgresql/uuid_test.rb @@ -283,6 +283,7 @@ class PostgresqlUUIDGenerationTest < ActiveRecord::PostgreSQLTestCase end end + uses_transaction \ def test_schema_dumper_for_uuid_primary_key_default_in_legacy_migration @verbose_was = ActiveRecord::Migration.verbose ActiveRecord::Migration.verbose = false @@ -300,6 +301,7 @@ class PostgresqlUUIDGenerationTest < ActiveRecord::PostgreSQLTestCase ensure drop_table "pg_uuids_4" ActiveRecord::Migration.verbose = @verbose_was + ActiveRecord::SchemaMigration.delete_all end end @@ -331,6 +333,7 @@ class PostgresqlUUIDTestNilDefault < ActiveRecord::PostgreSQLTestCase assert_match(/\bcreate_table "pg_uuids", id: :uuid, default: nil/, schema) end + uses_transaction \ def test_schema_dumper_for_uuid_primary_key_with_default_nil_in_legacy_migration @verbose_was = ActiveRecord::Migration.verbose ActiveRecord::Migration.verbose = false @@ -348,6 +351,7 @@ class PostgresqlUUIDTestNilDefault < ActiveRecord::PostgreSQLTestCase ensure drop_table "pg_uuids_4" ActiveRecord::Migration.verbose = @verbose_was + ActiveRecord::SchemaMigration.delete_all end end diff --git a/activerecord/test/cases/adapters/sqlite3/collation_test.rb b/activerecord/test/cases/adapters/sqlite3/collation_test.rb index 76c8f7d8dd..d938b5ff2f 100644 --- a/activerecord/test/cases/adapters/sqlite3/collation_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/collation_test.rb @@ -11,6 +11,10 @@ class SQLite3CollationTest < ActiveRecord::SQLite3TestCase @connection.create_table :collation_table_sqlite3, force: true do |t| t.string :string_nocase, collation: "NOCASE" t.text :text_rtrim, collation: "RTRIM" + # The decimal column might interfere with collation parsing. + # Thus, add this column type and some other string column afterwards. + t.decimal :decimal_col, precision: 6, scale: 2 + t.string :string_after_decimal_nocase, collation: "NOCASE" end end @@ -22,6 +26,11 @@ class SQLite3CollationTest < ActiveRecord::SQLite3TestCase column = @connection.columns(:collation_table_sqlite3).find { |c| c.name == "string_nocase" } assert_equal :string, column.type assert_equal "NOCASE", column.collation + + # Verify collation of a column behind the decimal column as well. + column = @connection.columns(:collation_table_sqlite3).find { |c| c.name == "string_after_decimal_nocase" } + assert_equal :string, column.type + assert_equal "NOCASE", column.collation end test "text column with collation" do diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb index 806cfbfc00..22dc0eaad2 100644 --- a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb @@ -636,7 +636,6 @@ module ActiveRecord end private - def assert_logged(logs) subscriber = SQLSubscriber.new subscription = ActiveSupport::Notifications.subscribe("sql.active_record", subscriber) diff --git a/activerecord/test/cases/associations/eager_load_nested_include_test.rb b/activerecord/test/cases/associations/eager_load_nested_include_test.rb index 849939de75..9be21b23db 100644 --- a/activerecord/test/cases/associations/eager_load_nested_include_test.rb +++ b/activerecord/test/cases/associations/eager_load_nested_include_test.rb @@ -14,6 +14,7 @@ module Remembered included do after_create :remember + private def remember; self.class.remembered << self; end end diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb index f7aad9d775..cb46f9e053 100644 --- a/activerecord/test/cases/associations/eager_test.rb +++ b/activerecord/test/cases/associations/eager_test.rb @@ -523,7 +523,7 @@ class EagerAssociationTest < ActiveRecord::TestCase def test_eager_association_loading_with_belongs_to_and_order_string_with_quoted_table_name quoted_posts_id = Comment.connection.quote_table_name("posts") + "." + Comment.connection.quote_column_name("id") assert_nothing_raised do - Comment.includes(:post).references(:posts).order(Arel.sql(quoted_posts_id)) + Comment.includes(:post).references(:posts).order(quoted_posts_id) end end @@ -789,7 +789,6 @@ class EagerAssociationTest < ActiveRecord::TestCase .where("comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment'") .references(:comments) .scoping do - posts = authors(:david).posts.limit(2).to_a assert_equal 2, posts.size end @@ -798,7 +797,6 @@ class EagerAssociationTest < ActiveRecord::TestCase .where("authors.name = 'David' AND (comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment')") .references(:authors, :comments) .scoping do - count = Post.limit(2).count assert_equal count, posts.size end @@ -970,14 +968,14 @@ class EagerAssociationTest < ActiveRecord::TestCase posts(:thinking, :sti_comments), Post.all.merge!( includes: [:author, :comments], where: { "authors.name" => "David" }, - order: Arel.sql("UPPER(posts.title)"), limit: 2, offset: 1 + order: "UPPER(posts.title)", limit: 2, offset: 1 ).to_a ) assert_equal( posts(:sti_post_and_comments, :sti_comments), Post.all.merge!( includes: [:author, :comments], where: { "authors.name" => "David" }, - order: Arel.sql("UPPER(posts.title) DESC"), limit: 2, offset: 1 + order: "UPPER(posts.title) DESC", limit: 2, offset: 1 ).to_a ) end @@ -987,14 +985,14 @@ class EagerAssociationTest < ActiveRecord::TestCase posts(:thinking, :sti_comments), Post.all.merge!( includes: [:author, :comments], where: { "authors.name" => "David" }, - order: [Arel.sql("UPPER(posts.title)"), "posts.id"], limit: 2, offset: 1 + order: ["UPPER(posts.title)", "posts.id"], limit: 2, offset: 1 ).to_a ) assert_equal( posts(:sti_post_and_comments, :sti_comments), Post.all.merge!( includes: [:author, :comments], where: { "authors.name" => "David" }, - order: [Arel.sql("UPPER(posts.title) DESC"), "posts.id"], limit: 2, offset: 1 + order: ["UPPER(posts.title) DESC", "posts.id"], limit: 2, offset: 1 ).to_a ) end diff --git a/activerecord/test/cases/associations/extension_test.rb b/activerecord/test/cases/associations/extension_test.rb index 5e6e3e8ec4..604a52655c 100644 --- a/activerecord/test/cases/associations/extension_test.rb +++ b/activerecord/test/cases/associations/extension_test.rb @@ -87,7 +87,6 @@ class AssociationsExtensionsTest < ActiveRecord::TestCase end private - def extend!(model) ActiveRecord::Associations::Builder::HasMany.send(:define_extensions, model, :association_name) { } end diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index 545bc77fed..6c54c2f1cd 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -2932,8 +2932,12 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal [], reference.ideal_jobs end - private + def test_has_many_preloading_with_duplicate_records + posts = Post.joins(:comments).preload(:comments).to_a + assert_equal [1, 2], posts.first.comments.map(&:id) + end + private def force_signal37_to_load_all_clients_of_firm companies(:first_firm).clients_of_firm.load_target end diff --git a/activerecord/test/cases/associations/nested_through_associations_test.rb b/activerecord/test/cases/associations/nested_through_associations_test.rb index 35da74102d..8d74ae3961 100644 --- a/activerecord/test/cases/associations/nested_through_associations_test.rb +++ b/activerecord/test/cases/associations/nested_through_associations_test.rb @@ -626,7 +626,6 @@ class NestedThroughAssociationsTest < ActiveRecord::TestCase end private - def assert_includes_and_joins_equal(query, expected, association) actual = assert_queries(1) { query.joins(association).to_a.uniq } assert_equal expected, actual diff --git a/activerecord/test/cases/associations/required_test.rb b/activerecord/test/cases/associations/required_test.rb index c7a78e6bc4..db7f945a36 100644 --- a/activerecord/test/cases/associations/required_test.rb +++ b/activerecord/test/cases/associations/required_test.rb @@ -117,7 +117,6 @@ class RequiredAssociationsTest < ActiveRecord::TestCase end private - def subclass_of(klass, &block) subclass = Class.new(klass, &block) def subclass.name diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb index 5cbe5d796d..71b5407dcc 100644 --- a/activerecord/test/cases/attribute_methods_test.rb +++ b/activerecord/test/cases/attribute_methods_test.rb @@ -1087,7 +1087,6 @@ class AttributeMethodsTest < ActiveRecord::TestCase end private - def new_topic_like_ar_class(&block) klass = Class.new(ActiveRecord::Base) do self.table_name = "topics" diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb index 2fb5ca4152..7e61ac9d8b 100644 --- a/activerecord/test/cases/autosave_association_test.rb +++ b/activerecord/test/cases/autosave_association_test.rb @@ -39,7 +39,6 @@ class TestAutosaveAssociationsInGeneral < ActiveRecord::TestCase def self.name; "Person"; end private - def should_be_cool unless first_name == "cool" errors.add :first_name, "not cool" @@ -82,7 +81,6 @@ class TestAutosaveAssociationsInGeneral < ActiveRecord::TestCase end private - def assert_no_difference_when_adding_callbacks_twice_for(model, association_name) reflection = model.reflect_on_association(association_name) assert_no_difference "callbacks_for_model(#{model.name}).length" do diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index e42af3686e..5dabff1431 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -589,11 +589,7 @@ class CalculationsTest < ActiveRecord::TestCase end def test_should_sum_expression - if current_adapter?(:SQLite3Adapter, :Mysql2Adapter, :PostgreSQLAdapter, :OracleAdapter) - assert_equal 636, Account.sum("2 * credit_limit") - else - assert_equal 636, Account.sum("2 * credit_limit").to_i - end + assert_equal 636, Account.sum("2 * credit_limit") end def test_sum_expression_returns_zero_when_no_records_to_sum diff --git a/activerecord/test/cases/connection_adapters/connection_handler_test.rb b/activerecord/test/cases/connection_adapters/connection_handler_test.rb index 6282759a10..27589966af 100644 --- a/activerecord/test/cases/connection_adapters/connection_handler_test.rb +++ b/activerecord/test/cases/connection_adapters/connection_handler_test.rb @@ -367,11 +367,24 @@ module ActiveRecord assert_same klass2.connection, ActiveRecord::Base.connection end + class ApplicationRecord < ActiveRecord::Base + self.abstract_class = true + end + + class MyClass < ApplicationRecord + end + def test_connection_specification_name_should_fallback_to_parent klassA = Class.new(Base) klassB = Class.new(klassA) + klassC = Class.new(MyClass) assert_equal klassB.connection_specification_name, klassA.connection_specification_name + assert_equal klassC.connection_specification_name, klassA.connection_specification_name + + assert_equal "primary", klassA.connection_specification_name + assert_equal "primary", klassC.connection_specification_name + klassA.connection_specification_name = "readonly" assert_equal "readonly", klassB.connection_specification_name end diff --git a/activerecord/test/cases/connection_adapters/mysql_type_lookup_test.rb b/activerecord/test/cases/connection_adapters/mysql_type_lookup_test.rb index 38331aa641..bc823fd072 100644 --- a/activerecord/test/cases/connection_adapters/mysql_type_lookup_test.rb +++ b/activerecord/test/cases/connection_adapters/mysql_type_lookup_test.rb @@ -58,7 +58,6 @@ if current_adapter?(:Mysql2Adapter) end private - def assert_lookup_type(type, lookup) cast_type = @connection.send(:type_map).lookup(lookup) assert_equal type, cast_type.type diff --git a/activerecord/test/cases/connection_adapters/type_lookup_test.rb b/activerecord/test/cases/connection_adapters/type_lookup_test.rb index 1c79d776f0..e92bb40632 100644 --- a/activerecord/test/cases/connection_adapters/type_lookup_test.rb +++ b/activerecord/test/cases/connection_adapters/type_lookup_test.rb @@ -109,7 +109,6 @@ unless current_adapter?(:PostgreSQLAdapter) # PostgreSQL does not use type strin end private - def assert_lookup_type(type, lookup) cast_type = @connection.send(:type_map).lookup(lookup) assert_equal type, cast_type.type diff --git a/activerecord/test/cases/connection_pool_test.rb b/activerecord/test/cases/connection_pool_test.rb index a15ad9a45b..82f5f45a4c 100644 --- a/activerecord/test/cases/connection_pool_test.rb +++ b/activerecord/test/cases/connection_pool_test.rb @@ -507,7 +507,6 @@ module ActiveRecord pool.schema_cache = schema_cache pool.with_connection do |conn| - assert_not_same pool.schema_cache, conn.schema_cache assert_equal pool.schema_cache.size, conn.schema_cache.size assert_same pool.schema_cache.columns(:posts), conn.schema_cache.columns(:posts) end diff --git a/activerecord/test/cases/database_statements_test.rb b/activerecord/test/cases/database_statements_test.rb index 1c934602ec..119d48b85e 100644 --- a/activerecord/test/cases/database_statements_test.rb +++ b/activerecord/test/cases/database_statements_test.rb @@ -23,7 +23,6 @@ class DatabaseStatementsTest < ActiveRecord::TestCase end private - def return_the_inserted_id(method:) # Oracle adapter uses prefetched primary key values from sequence and passes them to connection adapter insert method if current_adapter?(:OracleAdapter) diff --git a/activerecord/test/cases/explain_test.rb b/activerecord/test/cases/explain_test.rb index a0e75f4e89..edd2c768d3 100644 --- a/activerecord/test/cases/explain_test.rb +++ b/activerecord/test/cases/explain_test.rb @@ -72,7 +72,6 @@ if ActiveRecord::Base.connection.supports_explain? end private - def stub_explain_for_query_plans(query_plans = ["query plan foo", "query plan bar"]) explain_called = 0 diff --git a/activerecord/test/cases/finder_respond_to_test.rb b/activerecord/test/cases/finder_respond_to_test.rb index 66413a98e4..d9e88b3feb 100644 --- a/activerecord/test/cases/finder_respond_to_test.rb +++ b/activerecord/test/cases/finder_respond_to_test.rb @@ -54,7 +54,6 @@ class FinderRespondToTest < ActiveRecord::TestCase end private - def ensure_topic_method_is_not_cached(method_id) Topic.singleton_class.remove_method method_id if Topic.public_methods.include? method_id end diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb index 0cb868da6e..a7f01e898e 100644 --- a/activerecord/test/cases/fixtures_test.rb +++ b/activerecord/test/cases/fixtures_test.rb @@ -948,7 +948,6 @@ class TransactionalFixturesOnConnectionNotification < ActiveRecord::TestCase end private - def fire_connection_notification(connection) assert_called_with(ActiveRecord::Base.connection_handler, :retrieve_connection, ["book"], returns: connection) do message_bus = ActiveSupport::Notifications.instrumenter @@ -1367,7 +1366,6 @@ class MultipleDatabaseFixturesTest < ActiveRecord::TestCase end private - def with_temporary_connection_pool old_pool = ActiveRecord::Base.connection_handler.retrieve_connection_pool(ActiveRecord::Base.connection_specification_name) new_pool = ActiveRecord::ConnectionAdapters::ConnectionPool.new ActiveRecord::Base.connection_pool.spec diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb index 543a0aeb39..56c780c4a6 100644 --- a/activerecord/test/cases/helper.rb +++ b/activerecord/test/cases/helper.rb @@ -189,7 +189,6 @@ end module InTimeZone private - def in_time_zone(zone) old_zone = Time.zone old_tz = ActiveRecord::Base.time_zone_aware_attributes diff --git a/activerecord/test/cases/hot_compatibility_test.rb b/activerecord/test/cases/hot_compatibility_test.rb index 7b388ebc5e..f41aea6125 100644 --- a/activerecord/test/cases/hot_compatibility_test.rb +++ b/activerecord/test/cases/hot_compatibility_test.rb @@ -115,7 +115,6 @@ class HotCompatibilityTest < ActiveRecord::TestCase end private - def get_prepared_statement_cache(connection) connection.instance_variable_get(:@statements) .instance_variable_get(:@cache)[Process.pid] diff --git a/activerecord/test/cases/insert_all_test.rb b/activerecord/test/cases/insert_all_test.rb index f24c63031c..d086d77081 100644 --- a/activerecord/test/cases/insert_all_test.rb +++ b/activerecord/test/cases/insert_all_test.rb @@ -262,7 +262,6 @@ class InsertAllTest < ActiveRecord::TestCase end private - def capture_log_output output = StringIO.new old_logger, ActiveRecord::Base.logger = ActiveRecord::Base.logger, ActiveSupport::Logger.new(output) diff --git a/activerecord/test/cases/json_serialization_test.rb b/activerecord/test/cases/json_serialization_test.rb index 82cf281cff..31691d83fc 100644 --- a/activerecord/test/cases/json_serialization_test.rb +++ b/activerecord/test/cases/json_serialization_test.rb @@ -10,7 +10,6 @@ require "models/comment" module JsonSerializationHelpers private - def set_include_root_in_json(value) original_root_in_json = ActiveRecord::Base.include_root_in_json ActiveRecord::Base.include_root_in_json = value diff --git a/activerecord/test/cases/locking_test.rb b/activerecord/test/cases/locking_test.rb index 04f9b26960..b468da7c76 100644 --- a/activerecord/test/cases/locking_test.rb +++ b/activerecord/test/cases/locking_test.rb @@ -593,7 +593,6 @@ class OptimisticLockingWithSchemaChangeTest < ActiveRecord::TestCase end private - def add_counter_column_to(model, col = "test_count") model.connection.add_column model.table_name, col, :integer, null: false, default: 0 model.reset_column_information diff --git a/activerecord/test/cases/migration/create_join_table_test.rb b/activerecord/test/cases/migration/create_join_table_test.rb index e0cbb29dcf..0257545330 100644 --- a/activerecord/test/cases/migration/create_join_table_test.rb +++ b/activerecord/test/cases/migration/create_join_table_test.rb @@ -151,7 +151,6 @@ module ActiveRecord end private - def with_table_cleanup tables_before = connection.data_sources diff --git a/activerecord/test/cases/migration/helper.rb b/activerecord/test/cases/migration/helper.rb index c056199140..da8bdc472a 100644 --- a/activerecord/test/cases/migration/helper.rb +++ b/activerecord/test/cases/migration/helper.rb @@ -34,7 +34,6 @@ module ActiveRecord end private - delegate(*CONNECTION_METHODS, to: :connection) end end diff --git a/activerecord/test/cases/migration/references_statements_test.rb b/activerecord/test/cases/migration/references_statements_test.rb index 769241ba12..451894fc54 100644 --- a/activerecord/test/cases/migration/references_statements_test.rb +++ b/activerecord/test/cases/migration/references_statements_test.rb @@ -126,7 +126,6 @@ module ActiveRecord end private - def with_polymorphic_column add_column table_name, :supplier_type, :string add_index table_name, [:supplier_id, :supplier_type] diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index 255885b599..a557225528 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -190,6 +190,7 @@ class MigrationTest < ActiveRecord::TestCase assert_not_predicate BigNumber, :table_exists? GiveMeBigNumbers.up + assert_predicate BigNumber, :table_exists? BigNumber.reset_column_information assert BigNumber.create( @@ -482,6 +483,7 @@ class MigrationTest < ActiveRecord::TestCase Thing.reset_table_name Thing.reset_sequence_name WeNeedThings.up + assert_predicate Thing, :table_exists? Thing.reset_column_information assert Thing.create("content" => "hello world") @@ -502,8 +504,9 @@ class MigrationTest < ActiveRecord::TestCase ActiveRecord::Base.table_name_suffix = "_suffix" Reminder.reset_table_name Reminder.reset_sequence_name - Reminder.reset_column_information WeNeedReminders.up + assert_predicate Reminder, :table_exists? + Reminder.reset_column_information assert Reminder.create("content" => "hello world", "remind_at" => Time.now) assert_equal "hello world", Reminder.first.content @@ -935,7 +938,6 @@ if ActiveRecord::Base.connection.supports_bulk_alter? end private - def with_bulk_change_table # Reset columns/indexes cache as we're changing the table @columns = @indexes = nil diff --git a/activerecord/test/cases/migrator_test.rb b/activerecord/test/cases/migrator_test.rb index 30e199f1c5..0c2ff95099 100644 --- a/activerecord/test/cases/migrator_test.rb +++ b/activerecord/test/cases/migrator_test.rb @@ -429,10 +429,10 @@ class MigratorTest < ActiveRecord::TestCase _, migrator = migrator_class(3) migrator = migrator.new("valid") - ActiveRecord::Base.connection.drop_table "schema_migrations", if_exists: true - assert_not ActiveRecord::Base.connection.table_exists?("schema_migrations") + ActiveRecord::SchemaMigration.drop_table + assert_not_predicate ActiveRecord::SchemaMigration, :table_exists? migrator.migrate(1) - assert ActiveRecord::Base.connection.table_exists?("schema_migrations") + assert_predicate ActiveRecord::SchemaMigration, :table_exists? end def test_migrator_forward diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb index bb1c1ea17d..b49e62bee6 100644 --- a/activerecord/test/cases/nested_attributes_test.rb +++ b/activerecord/test/cases/nested_attributes_test.rb @@ -851,7 +851,6 @@ module NestedAttributesOnACollectionAssociationTests end private - def association_setter @association_setter ||= "#{@association_name}_attributes=".to_sym end diff --git a/activerecord/test/cases/pooled_connections_test.rb b/activerecord/test/cases/pooled_connections_test.rb index 080aeb0989..d783b2945d 100644 --- a/activerecord/test/cases/pooled_connections_test.rb +++ b/activerecord/test/cases/pooled_connections_test.rb @@ -72,7 +72,6 @@ class PooledConnectionsTest < ActiveRecord::TestCase end private - def add_record(name) ActiveRecord::Base.connection_pool.with_connection { Project.create! name: name } end diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb index eb32b690aa..53a4963909 100644 --- a/activerecord/test/cases/query_cache_test.rb +++ b/activerecord/test/cases/query_cache_test.rb @@ -335,11 +335,7 @@ class QueryCacheTest < ActiveRecord::TestCase def test_cache_does_not_wrap_results_in_arrays Task.cache do - if current_adapter?(:SQLite3Adapter, :Mysql2Adapter, :PostgreSQLAdapter, :OracleAdapter) - assert_equal 2, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks") - else - assert_instance_of String, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks") - end + assert_equal 2, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks") end end @@ -541,7 +537,6 @@ class QueryCacheTest < ActiveRecord::TestCase end private - def with_temporary_connection_pool old_pool = ActiveRecord::Base.connection_handler.retrieve_connection_pool(ActiveRecord::Base.connection_specification_name) new_pool = ActiveRecord::ConnectionAdapters::ConnectionPool.new ActiveRecord::Base.connection_pool.spec diff --git a/activerecord/test/cases/relation/where_clause_test.rb b/activerecord/test/cases/relation/where_clause_test.rb index b26a1a1d80..35db3d1175 100644 --- a/activerecord/test/cases/relation/where_clause_test.rb +++ b/activerecord/test/cases/relation/where_clause_test.rb @@ -233,7 +233,6 @@ class ActiveRecord::Relation end private - def table Arel::Table.new("table") end diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb index 3f370e5ede..e0743de94b 100644 --- a/activerecord/test/cases/relation_test.rb +++ b/activerecord/test/cases/relation_test.rb @@ -405,7 +405,6 @@ module ActiveRecord end private - def skip_if_sqlite3_version_includes_quoting_bug if sqlite3_version_includes_quoting_bug? skip <<-ERROR.squish diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index 4ec695c4c6..a5c162af33 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -298,7 +298,7 @@ class RelationTest < ActiveRecord::TestCase end def test_reverse_order_with_function - topics = Topic.order(Arel.sql("length(title)")).reverse_order + topics = Topic.order("length(title)").reverse_order assert_equal topics(:second).title, topics.first.title end @@ -337,21 +337,21 @@ class RelationTest < ActiveRecord::TestCase def test_reverse_order_with_nulls_first_or_last assert_raises(ActiveRecord::IrreversibleOrderError) do - Topic.order(Arel.sql("title NULLS FIRST")).reverse_order + Topic.order("title NULLS FIRST").reverse_order end assert_raises(ActiveRecord::IrreversibleOrderError) do - Topic.order(Arel.sql("title NULLS FIRST")).reverse_order + Topic.order("title NULLS FIRST").reverse_order end assert_raises(ActiveRecord::IrreversibleOrderError) do - Topic.order(Arel.sql("title nulls last")).reverse_order + Topic.order("title nulls last").reverse_order end assert_raises(ActiveRecord::IrreversibleOrderError) do - Topic.order(Arel.sql("title NULLS FIRST, author_name")).reverse_order + Topic.order("title NULLS FIRST, author_name").reverse_order end assert_raises(ActiveRecord::IrreversibleOrderError) do - Topic.order(Arel.sql("author_name, title nulls last")).reverse_order + Topic.order("author_name, title nulls last").reverse_order end - end + end if current_adapter?(:PostgreSQLAdapter, :OracleAdapter) def test_default_reverse_order_on_table_without_primary_key assert_raises(ActiveRecord::IrreversibleOrderError) do @@ -1679,7 +1679,7 @@ class RelationTest < ActiveRecord::TestCase scope = Post.order("comments.body") assert_equal ["comments"], scope.references_values - scope = Post.order(Arel.sql("#{Comment.quoted_table_name}.#{Comment.quoted_primary_key}")) + scope = Post.order("#{Comment.quoted_table_name}.#{Comment.quoted_primary_key}") if current_adapter?(:OracleAdapter) assert_equal ["COMMENTS"], scope.references_values else @@ -1696,7 +1696,7 @@ class RelationTest < ActiveRecord::TestCase scope = Post.order("comments.body asc") assert_equal ["comments"], scope.references_values - scope = Post.order(Arel.sql("foo(comments.body)")) + scope = Post.order("foo(comments.body)") assert_equal [], scope.references_values end @@ -1704,7 +1704,7 @@ class RelationTest < ActiveRecord::TestCase scope = Post.reorder("comments.body") assert_equal %w(comments), scope.references_values - scope = Post.reorder(Arel.sql("#{Comment.quoted_table_name}.#{Comment.quoted_primary_key}")) + scope = Post.reorder("#{Comment.quoted_table_name}.#{Comment.quoted_primary_key}") if current_adapter?(:OracleAdapter) assert_equal ["COMMENTS"], scope.references_values else @@ -1721,7 +1721,7 @@ class RelationTest < ActiveRecord::TestCase scope = Post.reorder("comments.body asc") assert_equal %w(comments), scope.references_values - scope = Post.reorder(Arel.sql("foo(comments.body)")) + scope = Post.reorder("foo(comments.body)") assert_equal [], scope.references_values end diff --git a/activerecord/test/cases/schema_loading_test.rb b/activerecord/test/cases/schema_loading_test.rb index f539156466..5da2d9e08f 100644 --- a/activerecord/test/cases/schema_loading_test.rb +++ b/activerecord/test/cases/schema_loading_test.rb @@ -43,7 +43,6 @@ class SchemaLoadingTest < ActiveRecord::TestCase end private - def define_model Class.new(ActiveRecord::Base) do include SchemaLoadCounter diff --git a/activerecord/test/cases/tasks/database_tasks_test.rb b/activerecord/test/cases/tasks/database_tasks_test.rb index ffe94eee0f..6b6861465b 100644 --- a/activerecord/test/cases/tasks/database_tasks_test.rb +++ b/activerecord/test/cases/tasks/database_tasks_test.rb @@ -835,7 +835,6 @@ module ActiveRecord end private - def capture_migration_status capture(:stdout) do ActiveRecord::Tasks::DatabaseTasks.migrate_status diff --git a/activerecord/test/cases/tasks/mysql_rake_test.rb b/activerecord/test/cases/tasks/mysql_rake_test.rb index 552e623fd4..258132835f 100644 --- a/activerecord/test/cases/tasks/mysql_rake_test.rb +++ b/activerecord/test/cases/tasks/mysql_rake_test.rb @@ -100,7 +100,6 @@ if current_adapter?(:Mysql2Adapter) end private - def with_stubbed_connection_establish_connection ActiveRecord::Base.stub(:establish_connection, nil) do ActiveRecord::Base.stub(:connection, @connection) do @@ -180,7 +179,6 @@ if current_adapter?(:Mysql2Adapter) end private - def with_stubbed_connection_establish_connection ActiveRecord::Base.stub(:establish_connection, nil) do ActiveRecord::Base.stub(:connection, @connection) do @@ -233,7 +231,6 @@ if current_adapter?(:Mysql2Adapter) end private - def with_stubbed_connection_establish_connection ActiveRecord::Base.stub(:establish_connection, nil) do ActiveRecord::Base.stub(:connection, @connection) do diff --git a/activerecord/test/cases/tasks/postgresql_rake_test.rb b/activerecord/test/cases/tasks/postgresql_rake_test.rb index 065ba7734c..f9df650687 100644 --- a/activerecord/test/cases/tasks/postgresql_rake_test.rb +++ b/activerecord/test/cases/tasks/postgresql_rake_test.rb @@ -139,7 +139,6 @@ if current_adapter?(:PostgreSQLAdapter) end private - def with_stubbed_connection_establish_connection ActiveRecord::Base.stub(:connection, @connection) do ActiveRecord::Base.stub(:establish_connection, nil) do @@ -201,7 +200,6 @@ if current_adapter?(:PostgreSQLAdapter) end private - def with_stubbed_connection_establish_connection ActiveRecord::Base.stub(:connection, @connection) do ActiveRecord::Base.stub(:establish_connection, nil) do @@ -301,7 +299,6 @@ if current_adapter?(:PostgreSQLAdapter) end private - def with_stubbed_connection ActiveRecord::Base.stub(:connection, @connection) do yield diff --git a/activerecord/test/cases/transaction_callbacks_test.rb b/activerecord/test/cases/transaction_callbacks_test.rb index 100bd6a925..19b89ab08c 100644 --- a/activerecord/test/cases/transaction_callbacks_test.rb +++ b/activerecord/test/cases/transaction_callbacks_test.rb @@ -460,7 +460,6 @@ class TransactionCallbacksTest < ActiveRecord::TestCase end private - def add_transaction_execution_blocks(record) record.after_commit_block(:create) { |r| r.history << :commit_on_create } record.after_commit_block(:update) { |r| r.history << :commit_on_update } diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb index 6795996cca..b5c1cac3d9 100644 --- a/activerecord/test/cases/transactions_test.rb +++ b/activerecord/test/cases/transactions_test.rb @@ -1077,7 +1077,6 @@ class TransactionTest < ActiveRecord::TestCase end private - %w(validation save destroy).each do |filter| define_method("add_cancelling_before_#{filter}_with_db_side_effect_to_topic") do |topic| meta = class << topic; self; end diff --git a/activerecord/test/cases/unsafe_raw_sql_test.rb b/activerecord/test/cases/unsafe_raw_sql_test.rb index d5d8f2a09a..87edb163f2 100644 --- a/activerecord/test/cases/unsafe_raw_sql_test.rb +++ b/activerecord/test/cases/unsafe_raw_sql_test.rb @@ -77,7 +77,7 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase assert_equal ids_expected, ids_disabled end - test "order: allows table and column name" do + test "order: allows table and column names" do ids_expected = Post.order(Arel.sql("title")).pluck(:id) ids_depr = with_unsafe_raw_sql_deprecated { Post.order("posts.title").pluck(:id) } @@ -87,6 +87,17 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase assert_equal ids_expected, ids_disabled end + test "order: allows quoted table and column names" do + ids_expected = Post.order(Arel.sql("title")).pluck(:id) + + quoted_title = Post.connection.quote_table_name("posts.title") + ids_depr = with_unsafe_raw_sql_deprecated { Post.order(quoted_title).pluck(:id) } + ids_disabled = with_unsafe_raw_sql_disabled { Post.order(quoted_title).pluck(:id) } + + assert_equal ids_expected, ids_depr + assert_equal ids_expected, ids_disabled + end + test "order: allows column name and direction in string" do ids_expected = Post.order(Arel.sql("title desc")).pluck(:id) @@ -116,10 +127,10 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase ["asc", "desc", ""].each do |direction| %w(first last).each do |position| - ids_expected = Post.order(Arel.sql("type #{direction} nulls #{position}")).pluck(:id) + ids_expected = Post.order(Arel.sql("type::text #{direction} nulls #{position}")).pluck(:id) - ids_depr = with_unsafe_raw_sql_deprecated { Post.order("type #{direction} nulls #{position}").pluck(:id) } - ids_disabled = with_unsafe_raw_sql_disabled { Post.order("type #{direction} nulls #{position}").pluck(:id) } + ids_depr = with_unsafe_raw_sql_deprecated { Post.order("type::text #{direction} nulls #{position}").pluck(:id) } + ids_disabled = with_unsafe_raw_sql_disabled { Post.order("type::text #{direction} nulls #{position}").pluck(:id) } assert_equal ids_expected, ids_depr assert_equal ids_expected, ids_disabled @@ -130,7 +141,7 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase test "order: disallows invalid column name" do with_unsafe_raw_sql_disabled do assert_raises(ActiveRecord::UnknownAttributeReference) do - Post.order("len(title) asc").pluck(:id) + Post.order("REPLACE(title, 'misc', 'zzzz') asc").pluck(:id) end end end @@ -146,7 +157,7 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase test "order: disallows invalid column with direction" do with_unsafe_raw_sql_disabled do assert_raises(ActiveRecord::UnknownAttributeReference) do - Post.order("len(title)" => :asc).pluck(:id) + Post.order("REPLACE(title, 'misc', 'zzzz')" => :asc).pluck(:id) end end end @@ -179,7 +190,7 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase test "order: disallows invalid Array arguments" do with_unsafe_raw_sql_disabled do assert_raises(ActiveRecord::UnknownAttributeReference) do - Post.order(["author_id", "length(title)"]).pluck(:id) + Post.order(["author_id", "REPLACE(title, 'misc', 'zzzz')"]).pluck(:id) end end end @@ -187,8 +198,8 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase test "order: allows valid Array arguments" do ids_expected = Post.order(Arel.sql("author_id, length(title)")).pluck(:id) - ids_depr = with_unsafe_raw_sql_deprecated { Post.order(["author_id", Arel.sql("length(title)")]).pluck(:id) } - ids_disabled = with_unsafe_raw_sql_disabled { Post.order(["author_id", Arel.sql("length(title)")]).pluck(:id) } + ids_depr = with_unsafe_raw_sql_deprecated { Post.order(["author_id", "length(title)"]).pluck(:id) } + ids_disabled = with_unsafe_raw_sql_disabled { Post.order(["author_id", "length(title)"]).pluck(:id) } assert_equal ids_expected, ids_depr assert_equal ids_expected, ids_disabled @@ -197,7 +208,7 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase test "order: logs deprecation warning for unrecognized column" do with_unsafe_raw_sql_deprecated do assert_deprecated(/Dangerous query method/) do - Post.order("length(title)") + Post.order("REPLACE(title, 'misc', 'zzzz')") end end end @@ -212,6 +223,16 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase assert_equal titles_expected, titles_disabled end + test "pluck: allows string column name with function and alias" do + titles_expected = Post.pluck(Arel.sql("UPPER(title)")) + + titles_depr = with_unsafe_raw_sql_deprecated { Post.pluck("UPPER(title) AS title") } + titles_disabled = with_unsafe_raw_sql_disabled { Post.pluck("UPPER(title) AS title") } + + assert_equal titles_expected, titles_depr + assert_equal titles_expected, titles_disabled + end + test "pluck: allows symbol column name" do titles_expected = Post.pluck(Arel.sql("title")) @@ -262,10 +283,21 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase assert_equal titles_expected, titles_disabled end + test "pluck: allows quoted table and column names" do + titles_expected = Post.pluck(Arel.sql("title")) + + quoted_title = Post.connection.quote_table_name("posts.title") + titles_depr = with_unsafe_raw_sql_deprecated { Post.pluck(quoted_title) } + titles_disabled = with_unsafe_raw_sql_disabled { Post.pluck(quoted_title) } + + assert_equal titles_expected, titles_depr + assert_equal titles_expected, titles_disabled + end + test "pluck: disallows invalid column name" do with_unsafe_raw_sql_disabled do assert_raises(ActiveRecord::UnknownAttributeReference) do - Post.pluck("length(title)") + Post.pluck("REPLACE(title, 'misc', 'zzzz')") end end end @@ -273,7 +305,7 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase test "pluck: disallows invalid column name amongst valid names" do with_unsafe_raw_sql_disabled do assert_raises(ActiveRecord::UnknownAttributeReference) do - Post.pluck(:title, "length(title)") + Post.pluck(:title, "REPLACE(title, 'misc', 'zzzz')") end end end @@ -281,7 +313,7 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase test "pluck: disallows invalid column names with includes" do with_unsafe_raw_sql_disabled do assert_raises(ActiveRecord::UnknownAttributeReference) do - Post.includes(:comments).pluck(:title, "length(title)") + Post.includes(:comments).pluck(:title, "REPLACE(title, 'misc', 'zzzz')") end end end @@ -296,24 +328,25 @@ class UnsafeRawSqlTest < ActiveRecord::TestCase test "pluck: logs deprecation warning" do with_unsafe_raw_sql_deprecated do assert_deprecated(/Dangerous query method/) do - Post.includes(:comments).pluck(:title, "length(title)") + Post.includes(:comments).pluck(:title, "REPLACE(title, 'misc', 'zzzz')") end end end - def with_unsafe_raw_sql_disabled(&blk) - with_config(:disabled, &blk) - end + private + def with_unsafe_raw_sql_disabled(&block) + with_config(:disabled, &block) + end - def with_unsafe_raw_sql_deprecated(&blk) - with_config(:deprecated, &blk) - end + def with_unsafe_raw_sql_deprecated(&block) + with_config(:deprecated, &block) + end - def with_config(new_value, &blk) - old_value = ActiveRecord::Base.allow_unsafe_raw_sql - ActiveRecord::Base.allow_unsafe_raw_sql = new_value - blk.call - ensure - ActiveRecord::Base.allow_unsafe_raw_sql = old_value - end + def with_config(new_value, &block) + old_value = ActiveRecord::Base.allow_unsafe_raw_sql + ActiveRecord::Base.allow_unsafe_raw_sql = new_value + yield + ensure + ActiveRecord::Base.allow_unsafe_raw_sql = old_value + end end diff --git a/activerecord/test/cases/yaml_serialization_test.rb b/activerecord/test/cases/yaml_serialization_test.rb index 60ebdce178..7003afa33a 100644 --- a/activerecord/test/cases/yaml_serialization_test.rb +++ b/activerecord/test/cases/yaml_serialization_test.rb @@ -130,7 +130,6 @@ class YamlSerializationTest < ActiveRecord::TestCase end private - def yaml_fixture(file_name) path = File.expand_path( "../support/yaml_compatibility_fixtures/#{file_name}.yml", diff --git a/activerecord/test/models/club.rb b/activerecord/test/models/club.rb index bb49fb300c..890e427616 100644 --- a/activerecord/test/models/club.rb +++ b/activerecord/test/models/club.rb @@ -15,7 +15,6 @@ class Club < ActiveRecord::Base accepts_nested_attributes_for :membership private - def private_method "I'm sorry sir, this is a *private* club, not a *pirate* club" end diff --git a/activerecord/test/models/company.rb b/activerecord/test/models/company.rb index a0f48d23f1..339b5c8ca8 100644 --- a/activerecord/test/models/company.rb +++ b/activerecord/test/models/company.rb @@ -25,7 +25,6 @@ class Company < AbstractCompany end private - def private_method "I am Jack's innermost fears and aspirations" end diff --git a/activerecord/test/models/company_in_module.rb b/activerecord/test/models/company_in_module.rb index 52b7e06a63..320b26b950 100644 --- a/activerecord/test/models/company_in_module.rb +++ b/activerecord/test/models/company_in_module.rb @@ -91,7 +91,6 @@ module MyApplication validate :check_empty_credit_limit private - def check_empty_credit_limit errors.add("credit_card", :blank) if credit_card.blank? end diff --git a/activerecord/test/models/person.rb b/activerecord/test/models/person.rb index c3d15a571a..0dfd29e45e 100644 --- a/activerecord/test/models/person.rb +++ b/activerecord/test/models/person.rb @@ -101,7 +101,6 @@ class RichPerson < ActiveRecord::Base before_validation :run_before_validation private - def run_before_create self.first_name = first_name.to_s + "run_before_create" end diff --git a/activerecord/test/models/topic.rb b/activerecord/test/models/topic.rb index 77101090f2..7a864c728c 100644 --- a/activerecord/test/models/topic.rb +++ b/activerecord/test/models/topic.rb @@ -93,7 +93,6 @@ class Topic < ActiveRecord::Base end private - def default_written_on self.written_on = Time.now unless attribute_present?("written_on") end diff --git a/activerecord/test/support/config.rb b/activerecord/test/support/config.rb index de0d90a18f..66ae57b382 100644 --- a/activerecord/test/support/config.rb +++ b/activerecord/test/support/config.rb @@ -12,7 +12,6 @@ module ARTest end private - def config_file Pathname.new(ENV["ARCONFIG"] || TEST_ROOT + "/config.yml") end |