diff options
Diffstat (limited to 'activerecord')
24 files changed, 205 insertions, 89 deletions
diff --git a/activerecord/MIT-LICENSE b/activerecord/MIT-LICENSE index 7c2197229d..1f496cf280 100644 --- a/activerecord/MIT-LICENSE +++ b/activerecord/MIT-LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2015 David Heinemeier Hansson +Copyright (c) 2004-2016 David Heinemeier Hansson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the @@ -17,4 +17,4 @@ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb index 264f869c68..f35e1d889e 100644 --- a/activerecord/lib/active_record.rb +++ b/activerecord/lib/active_record.rb @@ -1,5 +1,5 @@ #-- -# Copyright (c) 2004-2015 David Heinemeier Hansson +# Copyright (c) 2004-2016 David Heinemeier Hansson # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index fc12c3f45a..bac5a38a5d 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -331,15 +331,30 @@ module ActiveRecord validation_context = self.validation_context unless [:create, :update].include?(self.validation_context) unless valid = record.valid?(validation_context) if reflection.options[:autosave] + indexed_attribute = !index.nil? && (reflection.options[:index_errors] || ActiveRecord::Base.index_nested_attribute_errors) + record.errors.each do |attribute, message| - if index.nil? || (!reflection.options[:index_errors] && !ActiveRecord::Base.index_nested_attribute_errors) - attribute = "#{reflection.name}.#{attribute}" - else + if indexed_attribute attribute = "#{reflection.name}[#{index}].#{attribute}" + else + attribute = "#{reflection.name}.#{attribute}" end errors[attribute] << message errors[attribute].uniq! end + + record.errors.details.each_key do |attribute| + if indexed_attribute + reflection_attribute = "#{reflection.name}[#{index}].#{attribute}" + else + reflection_attribute = "#{reflection.name}.#{attribute}" + end + + record.errors.details[attribute].each do |error| + errors.details[reflection_attribute] << error + errors.details[reflection_attribute].uniq! + end + end else errors.add(reflection.name) end 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 7bf548fcba..a918a8b035 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -1028,11 +1028,12 @@ module ActiveRecord end # Given a set of columns and an ORDER BY clause, returns the columns for a SELECT DISTINCT. - # Both PostgreSQL and Oracle overrides this for custom DISTINCT syntax - they + # PostgreSQL, MySQL, and Oracle overrides this for custom DISTINCT syntax - they # require the order columns appear in the SELECT. # # columns_for_distinct("posts.id", ["posts.created_at desc"]) - def columns_for_distinct(columns, orders) #:nodoc: + # + def columns_for_distinct(columns, orders) # :nodoc: columns end diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index 3b8d1c1a9f..9cbc973f2e 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -391,19 +391,17 @@ module ActiveRecord def release_savepoint(name = nil) end - def case_sensitive_modifier(node, table_attribute) - node - end - def case_sensitive_comparison(table, attribute, column, value) - table_attr = table[attribute] - value = case_sensitive_modifier(value, table_attr) unless value.nil? - table_attr.eq(value) + if value.nil? + table[attribute].eq(value) + else + table[attribute].eq(Arel::Nodes::BindParam.new) + end end def case_insensitive_comparison(table, attribute, column, value) if can_perform_case_insensitive_comparison_for?(column) - table[attribute].lower.eq(table.lower(value)) + table[attribute].lower.eq(table.lower(Arel::Nodes::BindParam.new)) else case_sensitive_comparison(table, attribute, column, value) end diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index 37e4eb24a8..f5b5482efb 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -623,6 +623,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 = {}) + create_table_info_cache.delete(table_name) if create_table_info_cache.key?(table_name) execute "DROP#{' TEMPORARY' if options[:temporary]} TABLE#{' IF EXISTS' if options[:if_exists]} #{quote_table_name(table_name)}#{' CASCADE' if options[:force] == :cascade}" end @@ -751,16 +752,11 @@ module ActiveRecord SQL end - def case_sensitive_modifier(node, table_attribute) - node = Arel::Nodes.build_quoted node, table_attribute - Arel::Nodes::Bin.new(node) - end - def case_sensitive_comparison(table, attribute, column, value) - if column.case_sensitive? - table[attribute].eq(value) - else + if value.nil? || column.case_sensitive? super + else + table[attribute].eq(Arel::Nodes::Bin.new(Arel::Nodes::BindParam.new)) end end @@ -768,10 +764,25 @@ module ActiveRecord if column.case_sensitive? super else - table[attribute].eq(value) + table[attribute].eq(Arel::Nodes::BindParam.new) end end + # In MySQL 5.7.5 and up, ONLY_FULL_GROUP_BY affects handling of queries that use + # DISTINCT and ORDER BY. It requires the ORDER BY columns in the select list for + # distinct queries, and requires that the ORDER BY include the distinct column. + # See https://dev.mysql.com/doc/refman/5.7/en/group-by-handling.html + def columns_for_distinct(columns, orders) # :nodoc: + order_columns = orders.reject(&:blank?).map { |s| + # Convert Arel node to string + s = s.to_sql unless s.is_a?(String) + # Remove any ASC/DESC modifiers + s.gsub(/\s+(?:ASC|DESC)\b/i, '') + }.reject(&:blank?).map.with_index { |column, i| "#{column} AS alias_#{i}" } + + [super, *order_columns].join(', ') + end + def strict_mode? self.class.type_cast_config_to_boolean(@config.fetch(:strict, true)) end @@ -951,11 +962,13 @@ module ActiveRecord subsubselect = select.clone subsubselect.projections = [key] + # Materialize subquery by adding distinct + # to work with MySQL 5.7.6 which sets optimizer_switch='derived_merge=on' + subsubselect.distinct unless select.limit || select.offset || select.orders.any? + subselect = Arel::SelectManager.new(select.engine) subselect.project Arel.sql(key.name) - # Materialized subquery by adding distinct - # to work with MySQL 5.7.6 which sets optimizer_switch='derived_merge=on' - subselect.from subsubselect.distinct.as('__active_record_temp') + subselect.from subsubselect.as('__active_record_temp') end def mariadb? @@ -1018,9 +1031,12 @@ module ActiveRecord end end + def create_table_info_cache # :nodoc: + @create_table_info_cache ||= {} + end + def create_table_info(table_name) # :nodoc: - @create_table_info_cache = {} - @create_table_info_cache[table_name] ||= select_one("SHOW CREATE TABLE #{quote_table_name(table_name)}")["Create Table"] + create_table_info_cache[table_name] ||= select_one("SHOW CREATE TABLE #{quote_table_name(table_name)}")["Create Table"] end def create_table_definition(name, temporary = false, options = nil, as = nil) # :nodoc: diff --git a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb index f4686b680c..96a3a44b30 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb @@ -99,33 +99,15 @@ module ActiveRecord # DATABASE STATEMENTS ====================================== #++ - # FIXME: re-enable the following once a "better" query_cache solution is in core - # - # The overrides below perform much better than the originals in AbstractAdapter - # because we're able to take advantage of mysql2's lazy-loading capabilities - # - # # Returns a record hash with the column names as keys and column values - # # as values. - # def select_one(sql, name = nil) - # result = execute(sql, name) - # result.each(as: :hash) do |r| - # return r - # end - # end - # - # # Returns a single value from a record - # def select_value(sql, name = nil) - # result = execute(sql, name) - # if first = result.first - # first.first - # end - # end - # - # # Returns an array of the values of the first column in a select: - # # select_values("SELECT id FROM companies LIMIT 3") => [1,2,3] - # def select_values(sql, name = nil) - # execute(sql, name).map { |row| row.first } - # end + # Returns a record hash with the column names as keys and column values + # as values. + def select_one(arel, name = nil, binds = []) + arel, binds = binds_from_relation(arel, binds) + execute(to_sql(arel, binds), name).each(as: :hash) do |row| + @connection.next_result while @connection.more_results? + return row + end + end # Returns an array of arrays containing the field values. # Order is the same as that returned by +columns+. diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index a1ec570042..e313a34c3a 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -390,12 +390,12 @@ module ActiveRecord "average" => "avg", } - protected + # Returns the version of the connected PostgreSQL server. + def postgresql_version + @connection.server_version + end - # Returns the version of the connected PostgreSQL server. - def postgresql_version - @connection.server_version - end + protected # See http://www.postgresql.org/docs/current/static/errcodes-appendix.html FOREIGN_KEY_VIOLATION = "23503" diff --git a/activerecord/lib/active_record/enum.rb b/activerecord/lib/active_record/enum.rb index 7ded96f8fb..04519f4dc3 100644 --- a/activerecord/lib/active_record/enum.rb +++ b/activerecord/lib/active_record/enum.rb @@ -124,7 +124,7 @@ module ActiveRecord def deserialize(value) return if value.nil? - mapping.key(value.to_i) + mapping.key(value) end def serialize(value) diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index ba238ea142..8c9eab436d 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -126,9 +126,9 @@ module ActiveRecord class PendingMigrationError < MigrationError#:nodoc: def initialize(message = nil) if !message && defined?(Rails.env) - super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rails db:migrate RAILS_ENV=#{::Rails.env}.") + super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rails db:migrate RAILS_ENV=#{::Rails.env}") elsif !message - super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rails db:migrate.") + super("Migrations are pending. To resolve this issue, run:\n\n\tbin/rails db:migrate") else super end diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 983bf019bc..b86cc094fc 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -649,8 +649,8 @@ module ActiveRecord # they must differ only by #where (if no #group has been defined) or #having (if a #group is # present). Neither relation may have a #limit, #offset, or #distinct set. # - # Post.where("id = 1").or(Post.where("id = 2")) - # # SELECT `posts`.* FROM `posts` WHERE (('id = 1' OR 'id = 2')) + # Post.where("id = 1").or(Post.where("author_id = 3")) + # # SELECT `posts`.* FROM `posts` WHERE (('id = 1' OR 'author_id = 3')) # def or(other) spawn.or!(other) diff --git a/activerecord/lib/active_record/relation/where_clause_factory.rb b/activerecord/lib/active_record/relation/where_clause_factory.rb index a81ff98e49..dbf172a577 100644 --- a/activerecord/lib/active_record/relation/where_clause_factory.rb +++ b/activerecord/lib/active_record/relation/where_clause_factory.rb @@ -22,6 +22,7 @@ module ActiveRecord parts = predicate_builder.build_from_hash(attributes) when Arel::Nodes::Node parts = [opts] + binds = other else raise ArgumentError, "Unsupported argument type: #{opts} (#{opts.class})" end diff --git a/activerecord/lib/active_record/sanitization.rb b/activerecord/lib/active_record/sanitization.rb index 4e89ba4dd1..2bfc5ff7ae 100644 --- a/activerecord/lib/active_record/sanitization.rb +++ b/activerecord/lib/active_record/sanitization.rb @@ -213,7 +213,7 @@ module ActiveRecord end # TODO: Deprecate this - def quoted_id + def quoted_id # :nodoc: self.class.quote_value(@attributes[self.class.primary_key].value_for_database) end end diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb index edc1325b25..a376e2a17f 100644 --- a/activerecord/lib/active_record/validations/uniqueness.rb +++ b/activerecord/lib/active_record/validations/uniqueness.rb @@ -73,15 +73,18 @@ module ActiveRecord value = value.to_s[0, column.limit] end - value = Arel::Nodes::Quoted.new(value) - comparison = if !options[:case_sensitive] && !value.nil? # will use SQL LOWER function before comparison, unless it detects a case insensitive collation klass.connection.case_insensitive_comparison(table, attribute, column, value) else klass.connection.case_sensitive_comparison(table, attribute, column, value) end - klass.unscoped.where(comparison) + if value.nil? + klass.unscoped.where(comparison) + else + bind = Relation::QueryAttribute.new(attribute.to_s, value, Type::Value.new) + klass.unscoped.where(comparison, bind) + end rescue RangeError klass.none end 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 15aecf28ca..7395839fca 100644 --- a/activerecord/lib/rails/generators/active_record/model/model_generator.rb +++ b/activerecord/lib/rails/generators/active_record/model/model_generator.rb @@ -45,7 +45,13 @@ module ActiveRecord def determine_default_parent_class application_record = nil - in_root { application_record = File.exist?('app/models/application_record.rb') } + in_root do + application_record = if mountable_engine? + File.exist?("app/models/#{namespaced_path}/application_record.rb") + else + File.exist?('app/models/application_record.rb') + end + end if application_record "ApplicationRecord" diff --git a/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb b/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb new file mode 100644 index 0000000000..4efd728754 --- /dev/null +++ b/activerecord/test/cases/adapters/mysql2/mysql2_adapter_test.rb @@ -0,0 +1,44 @@ +require "cases/helper" + +class Mysql2AdapterTest < ActiveRecord::Mysql2TestCase + def setup + @conn = ActiveRecord::Base.connection + end + + def test_columns_for_distinct_zero_orders + assert_equal "posts.id", + @conn.columns_for_distinct("posts.id", []) + end + + def test_columns_for_distinct_one_order + assert_equal "posts.id, posts.created_at AS alias_0", + @conn.columns_for_distinct("posts.id", ["posts.created_at desc"]) + end + + def test_columns_for_distinct_few_orders + assert_equal "posts.id, posts.created_at AS alias_0, posts.position AS alias_1", + @conn.columns_for_distinct("posts.id", ["posts.created_at desc", "posts.position asc"]) + end + + def test_columns_for_distinct_with_case + assert_equal( + 'posts.id, CASE WHEN author.is_active THEN UPPER(author.name) ELSE UPPER(author.email) END AS alias_0', + @conn.columns_for_distinct('posts.id', + ["CASE WHEN author.is_active THEN UPPER(author.name) ELSE UPPER(author.email) END"]) + ) + end + + def test_columns_for_distinct_blank_not_nil_orders + assert_equal "posts.id, posts.created_at AS alias_0", + @conn.columns_for_distinct("posts.id", ["posts.created_at desc", "", " "]) + end + + def test_columns_for_distinct_with_arel_order + order = Object.new + def order.to_sql + "posts.created_at desc" + end + assert_equal "posts.id, posts.created_at AS alias_0", + @conn.columns_for_distinct("posts.id", [order]) + end +end diff --git a/activerecord/test/cases/adapters/mysql2/sp_test.rb b/activerecord/test/cases/adapters/mysql2/sp_test.rb index cdaa2cca44..4197ba45f1 100644 --- a/activerecord/test/cases/adapters/mysql2/sp_test.rb +++ b/activerecord/test/cases/adapters/mysql2/sp_test.rb @@ -22,6 +22,12 @@ class Mysql2StoredProcedureTest < ActiveRecord::Mysql2TestCase assert @connection.active?, "Bad connection use by 'Mysql2Adapter.select_rows'" end + def test_multi_results_from_select_one + row = @connection.select_one('CALL topics(1);') + assert_equal 'David', row['author_name'] + assert @connection.active?, "Bad connection use by 'Mysql2Adapter.select_one'" + end + def test_multi_results_from_find_by_sql topics = Topic.find_by_sql 'CALL topics(3);' assert_equal 3, topics.size diff --git a/activerecord/test/cases/adapters/postgresql/uuid_test.rb b/activerecord/test/cases/adapters/postgresql/uuid_test.rb index 049ed1732e..3d90790367 100644 --- a/activerecord/test/cases/adapters/postgresql/uuid_test.rb +++ b/activerecord/test/cases/adapters/postgresql/uuid_test.rb @@ -146,8 +146,6 @@ class PostgresqlUUIDGenerationTest < ActiveRecord::PostgreSQLTestCase end setup do - enable_extension!('uuid-ossp', connection) - connection.create_table('pg_uuids', id: :uuid, default: 'uuid_generate_v1()') do |t| t.string 'name' t.uuid 'other_uuid', default: 'uuid_generate_v4()' @@ -172,7 +170,6 @@ class PostgresqlUUIDGenerationTest < ActiveRecord::PostgreSQLTestCase drop_table "pg_uuids" drop_table 'pg_uuids_2' connection.execute 'DROP FUNCTION IF EXISTS my_uuid_generator();' - disable_extension!('uuid-ossp', connection) end if ActiveRecord::Base.connection.supports_extensions? @@ -217,8 +214,6 @@ class PostgresqlUUIDTestNilDefault < ActiveRecord::PostgreSQLTestCase include SchemaDumpingHelper setup do - enable_extension!('uuid-ossp', connection) - connection.create_table('pg_uuids', id: false) do |t| t.primary_key :id, :uuid, default: nil t.string 'name' @@ -227,7 +222,6 @@ class PostgresqlUUIDTestNilDefault < ActiveRecord::PostgreSQLTestCase teardown do drop_table "pg_uuids" - disable_extension!('uuid-ossp', connection) end if ActiveRecord::Base.connection.supports_extensions? @@ -260,8 +254,6 @@ class PostgresqlUUIDTestInverseOf < ActiveRecord::PostgreSQLTestCase end setup do - enable_extension!('uuid-ossp', connection) - connection.transaction do connection.create_table('pg_uuid_posts', id: :uuid) do |t| t.string 'title' @@ -276,7 +268,6 @@ class PostgresqlUUIDTestInverseOf < ActiveRecord::PostgreSQLTestCase teardown do drop_table "pg_uuid_comments" drop_table "pg_uuid_posts" - disable_extension!('uuid-ossp', connection) end if ActiveRecord::Base.connection.supports_extensions? diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb index 0df8f1f798..3608063b01 100644 --- a/activerecord/test/cases/autosave_association_test.rb +++ b/activerecord/test/cases/autosave_association_test.rb @@ -433,6 +433,53 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociationWithAcceptsNestedAttrib ActiveRecord::Base.index_nested_attribute_errors = old_attribute_config end + def test_errors_details_should_be_set + molecule = Molecule.new + valid_electron = Electron.new(name: 'electron') + invalid_electron = Electron.new + + molecule.electrons = [valid_electron, invalid_electron] + + assert_not invalid_electron.valid? + assert valid_electron.valid? + assert_not molecule.valid? + assert_equal [{error: :blank}], molecule.errors.details["electrons.name"] + end + + def test_errors_details_should_be_indexed_when_passed_as_array + guitar = Guitar.new + tuning_peg_valid = TuningPeg.new + tuning_peg_valid.pitch = 440.0 + tuning_peg_invalid = TuningPeg.new + + guitar.tuning_pegs = [tuning_peg_valid, tuning_peg_invalid] + + assert_not tuning_peg_invalid.valid? + assert tuning_peg_valid.valid? + assert_not guitar.valid? + assert_equal [{error: :not_a_number, value: nil}] , guitar.errors.details["tuning_pegs[1].pitch"] + assert_equal [], guitar.errors.details["tuning_pegs.pitch"] + end + + def test_errors_details_should_be_indexed_when_global_flag_is_set + old_attribute_config = ActiveRecord::Base.index_nested_attribute_errors + ActiveRecord::Base.index_nested_attribute_errors = true + + molecule = Molecule.new + valid_electron = Electron.new(name: 'electron') + invalid_electron = Electron.new + + molecule.electrons = [valid_electron, invalid_electron] + + assert_not invalid_electron.valid? + assert valid_electron.valid? + assert_not molecule.valid? + assert_equal [{error: :blank}], molecule.errors.details["electrons[1].name"] + assert_equal [], molecule.errors.details["electrons.name"] + ensure + ActiveRecord::Base.index_nested_attribute_errors = old_attribute_config + end + def test_valid_adding_with_nested_attributes molecule = Molecule.new valid_electron = Electron.new(name: 'electron') diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb index 9f90ab79a1..75a74c052d 100644 --- a/activerecord/test/cases/finder_test.rb +++ b/activerecord/test/cases/finder_test.rb @@ -19,7 +19,7 @@ require 'models/car' require 'models/tyre' class FinderTest < ActiveRecord::TestCase - fixtures :companies, :topics, :entrants, :developers, :developers_projects, :posts, :comments, :accounts, :authors, :customers, :categories, :categorizations, :cars + fixtures :companies, :topics, :entrants, :developers, :developers_projects, :posts, :comments, :accounts, :authors, :author_addresses, :customers, :categories, :categorizations, :cars def test_find_by_id_with_hash assert_raises(ActiveRecord::StatementInvalid) do @@ -993,10 +993,13 @@ class FinderTest < ActiveRecord::TestCase end def test_find_with_order_on_included_associations_with_construct_finder_sql_for_association_limiting_and_is_distinct - assert_equal 2, Post.includes(authors: :author_address).order('author_addresses.id DESC ').limit(2).to_a.size + assert_equal 2, Post.includes(authors: :author_address). + where.not(author_addresses: { id: nil }). + order('author_addresses.id DESC').limit(2).to_a.size assert_equal 3, Post.includes(author: :author_address, authors: :author_address). - order('author_addresses_authors.id DESC ').limit(3).to_a.size + where.not(author_addresses_authors: { id: nil }). + order('author_addresses_authors.id DESC').limit(3).to_a.size end def test_find_with_nil_inside_set_passed_for_one_attribute diff --git a/activerecord/test/cases/migration/rename_table_test.rb b/activerecord/test/cases/migration/rename_table_test.rb index 8eb027d53f..b926a92849 100644 --- a/activerecord/test/cases/migration/rename_table_test.rb +++ b/activerecord/test/cases/migration/rename_table_test.rb @@ -80,12 +80,10 @@ module ActiveRecord end def test_renaming_table_doesnt_attempt_to_rename_non_existent_sequences - enable_extension!('uuid-ossp', connection) connection.create_table :cats, id: :uuid assert_nothing_raised { rename_table :cats, :felines } ActiveSupport::Deprecation.silence { assert connection.table_exists? :felines } ensure - disable_extension!('uuid-ossp', connection) connection.drop_table :cats, if_exists: true connection.drop_table :felines, if_exists: true end diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb index f46d414b95..2f0382e273 100644 --- a/activerecord/test/cases/relation_test.rb +++ b/activerecord/test/cases/relation_test.rb @@ -77,7 +77,6 @@ module ActiveRecord def test_tree_is_not_traversed relation = Relation.new(Post, Post.arel_table, Post.predicate_builder) - # FIXME: Remove the Arel::Nodes::Quoted in Rails 5.1 left = relation.table[:id].eq(10) right = relation.table[:id].eq(10) combine = left.and right @@ -104,7 +103,6 @@ module ActiveRecord def test_create_with_value_with_wheres relation = Relation.new(Post, Post.arel_table, Post.predicate_builder) - # FIXME: Remove the Arel::Nodes::Quoted in Rails 5.1 relation.where! relation.table[:id].eq(10) relation.create_with_value = {:hello => 'world'} assert_equal({:hello => 'world', :id => 10}, relation.scope_for_create) @@ -115,7 +113,6 @@ module ActiveRecord relation = Relation.new(Post, Post.arel_table, Post.predicate_builder) assert_equal({}, relation.scope_for_create) - # FIXME: Remove the Arel::Nodes::Quoted in Rails 5.1 relation.where! relation.table[:id].eq(10) assert_equal({}, relation.scope_for_create) diff --git a/activerecord/test/fixtures/author_addresses.yml b/activerecord/test/fixtures/author_addresses.yml index 7b90572187..cf75e5998d 100644 --- a/activerecord/test/fixtures/author_addresses.yml +++ b/activerecord/test/fixtures/author_addresses.yml @@ -3,3 +3,9 @@ david_address: david_address_extra: id: 2 + +mary_address: + id: 3 + +bob_address: + id: 4 diff --git a/activerecord/test/fixtures/authors.yml b/activerecord/test/fixtures/authors.yml index 832236a486..41c124179e 100644 --- a/activerecord/test/fixtures/authors.yml +++ b/activerecord/test/fixtures/authors.yml @@ -9,7 +9,9 @@ david: mary: id: 2 name: Mary + author_address_id: 3 bob: id: 3 name: Bob + author_address_id: 4 |