diff options
Diffstat (limited to 'activerecord')
23 files changed, 206 insertions, 107 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 082e3d1089..201eddbcae 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,5 +1,26 @@ ## Rails 4.0.0 (unreleased) ## +* Prevent mass assignment to the type column of polymorphic associations when using `build` + Fix #8265 + + *Yves Senn* + +* Deprecate calling `Relation#sum` with a block. To perform a calculation over + the array result of the relation, use `to_a.sum(&block)`. + + *Carlos Antonio da Silva* + +* Fix postgresql adapter to handle BC timestamps correctly + + HistoryEvent.create!(:name => "something", :occured_at => Date.new(0) - 5.years) + + *Bogdan Gusiev* + +* When running migrations on Postgresql, the `:limit` option for `binary` and `text` columns is silently dropped. + Previously, these migrations caused sql exceptions, because Postgresql doesn't support limits on these types. + + *Victor Costan* + * Don't change STI type when calling `ActiveRecord::Base#becomes`. Add `ActiveRecord::Base#becomes!` with the previous behavior. @@ -431,11 +452,11 @@ *kennyj* -* Use inversed parent for first and last child of has_many association. +* Use inversed parent for first and last child of `has_many` association. *Ravil Bayramgalin* -* Fix Column.microseconds and Column.fast_string_to_date to avoid converting +* Fix `Column.microseconds` and `Column.fast_string_to_time` to avoid converting timestamp seconds to a float, since it occasionally results in inaccuracies with microsecond-precision times. Fixes #7352. @@ -725,13 +746,6 @@ *Marc-André Lafortune* -* Allow blocks for `count` with `ActiveRecord::Relation`, to work similar as - `Array#count`: - - Person.where("age > 26").count { |person| person.gender == 'female' } - - *Chris Finne & Carlos Antonio da Silva* - * Added support to `CollectionAssociation#delete` for passing `fixnum` or `string` values as record ids. This finds the records responding to the `id` and executes delete on them. diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 651b17920c..d8b6d7a86b 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -234,7 +234,7 @@ module ActiveRecord # others.size | X | X | X # others.length | X | X | X # others.count | X | X | X - # others.sum(args*,&block) | X | X | X + # others.sum(*args) | X | X | X # others.empty? | X | X | X # others.clear | X | X | X # others.delete(other,other,...) | X | X | X diff --git a/activerecord/lib/active_record/associations/association.rb b/activerecord/lib/active_record/associations/association.rb index 99e7383d42..3f0e4ca999 100644 --- a/activerecord/lib/active_record/associations/association.rb +++ b/activerecord/lib/active_record/associations/association.rb @@ -232,7 +232,8 @@ module ActiveRecord def build_record(attributes) reflection.build_association(attributes) do |record| - attributes = create_scope.except(*(record.changed - [reflection.foreign_key])) + skip_assign = [reflection.foreign_key, reflection.type].compact + attributes = create_scope.except(*(record.changed - skip_assign)) record.assign_attributes(attributes) end end diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb index 862ff201de..1548e68cea 100644 --- a/activerecord/lib/active_record/associations/collection_association.rb +++ b/activerecord/lib/active_record/associations/collection_association.rb @@ -161,15 +161,6 @@ module ActiveRecord end end - # Calculate sum using SQL, not Enumerable. - def sum(*args) - if block_given? - scope.sum(*args) { |*block_args| yield(*block_args) } - else - scope.sum(*args) - end - end - # Count all records using SQL. If the +:counter_sql+ or +:finder_sql+ option is set for the # association, it will be used for the query. Otherwise, construct options and pass them with # scope to the target class's +count+. diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb index 90701938e5..3c03cce838 100644 --- a/activerecord/lib/active_record/attribute_methods/read.rb +++ b/activerecord/lib/active_record/attribute_methods/read.rb @@ -32,21 +32,29 @@ module ActiveRecord protected - # We want to generate the methods via module_eval rather than define_method, - # because define_method is slower on dispatch and uses more memory (because it - # creates a closure). + # We want to generate the methods via module_eval rather than + # define_method, because define_method is slower on dispatch and + # uses more memory (because it creates a closure). # - # But sometimes the database might return columns with characters that are not - # allowed in normal method names (like 'my_column(omg)'. So to work around this - # we first define with the __temp__ identifier, and then use alias method to - # rename it to what we want. - def define_method_attribute(attr_name) + # But sometimes the database might return columns with + # characters that are not allowed in normal method names (like + # 'my_column(omg)'. So to work around this we first define with + # the __temp__ identifier, and then use alias method to rename + # it to what we want. + # + # We are also defining a constant to hold the frozen string of + # the attribute name. Using a constant means that we do not have + # to allocate an object on each call to the attribute method. + # Making it frozen means that it doesn't get duped when used to + # key the @attributes_cache in read_attribute. + def define_method_attribute(name) + safe_name = name.unpack('h*').first generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1 - def __temp__ - read_attribute('#{attr_name}') { |n| missing_attribute(n, caller) } + def __temp__#{safe_name} + read_attribute(AttrNames::ATTR_#{safe_name}) { |n| missing_attribute(n, caller) } end - alias_method '#{attr_name}', :__temp__ - undef_method :__temp__ + alias_method #{name.inspect}, :__temp__#{safe_name} + undef_method :__temp__#{safe_name} STR end diff --git a/activerecord/lib/active_record/attribute_methods/write.rb b/activerecord/lib/active_record/attribute_methods/write.rb index fa9097db1f..cd33494cc3 100644 --- a/activerecord/lib/active_record/attribute_methods/write.rb +++ b/activerecord/lib/active_record/attribute_methods/write.rb @@ -9,15 +9,19 @@ module ActiveRecord module ClassMethods protected - def define_method_attribute=(attr_name) - if attr_name =~ ActiveModel::AttributeMethods::NAME_COMPILABLE_REGEXP - generated_attribute_methods.module_eval("def #{attr_name}=(new_value); write_attribute('#{attr_name}', new_value); end", __FILE__, __LINE__) - else - generated_attribute_methods.send(:define_method, "#{attr_name}=") do |new_value| - write_attribute(attr_name, new_value) - end + + # See define_method_attribute in read.rb for an explanation of + # this code. + def define_method_attribute=(name) + safe_name = name.unpack('h*').first + generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1 + def __temp__#{safe_name}=(value) + write_attribute(AttrNames::ATTR_#{safe_name}, value) end - end + alias_method #{(name + '=').inspect}, :__temp__#{safe_name}= + undef_method :__temp__#{safe_name}= + STR + end end # Updates the attribute identified by <tt>attr_name</tt> with the 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 17dd71e898..f1e42dfbbe 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -540,7 +540,7 @@ module ActiveRecord column_type_sql << "(#{precision})" end elsif scale - raise ArgumentError, "Error adding decimal column: precision cannot be empty if scale if specified" + raise ArgumentError, "Error adding decimal column: precision cannot be empty if scale is specified" end elsif (type != :primary_key) && (limit ||= native.is_a?(Hash) && native[:limit]) diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb index 9627aaae3a..e9677415cc 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb @@ -2,7 +2,7 @@ require 'active_record/connection_adapters/abstract_mysql_adapter' require 'active_record/connection_adapters/statement_pool' require 'active_support/core_ext/hash/keys' -gem 'mysql', '~> 2.9.0' +gem 'mysql', '~> 2.9' require 'mysql' class Mysql diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb b/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb index 62d091357d..c04a799b8d 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb @@ -8,6 +8,8 @@ module ActiveRecord case string when 'infinity'; 1.0 / 0.0 when '-infinity'; -1.0 / 0.0 + when / BC$/ + super("-" + string.sub(/ BC$/, "")) else super end diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb index 9d3fa18e3a..62a4d76928 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb @@ -129,11 +129,15 @@ module ActiveRecord # Quote date/time values for use in SQL input. Includes microseconds # if the value is a Time responding to usec. def quoted_date(value) #:nodoc: + result = super if value.acts_like?(:time) && value.respond_to?(:usec) - "#{super}.#{sprintf("%06d", value.usec)}" - else - super + result = "#{result}.#{sprintf("%06d", value.usec)}" + end + + if value.year < 0 + result = result.sub(/^-/, "") + " BC" end + result end end end 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 82a0b662f4..7c561b6f82 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb @@ -396,6 +396,13 @@ module ActiveRecord when nil, 0..0x3fffffff; super(type) else raise(ActiveRecordError, "No binary type has byte size #{limit}.") end + when 'text' + # PostgreSQL doesn't support limits on text columns. + # The hard limit is 1Gb, according to section 8.3 in the manual. + case limit + when nil, 0..0x3fffffff; super(type) + else raise(ActiveRecordError, "The limit on text can be at most 1GB - 1byte.") + end when 'integer' return 'integer' unless limit @@ -422,20 +429,17 @@ module ActiveRecord # PostgreSQL requires the ORDER BY columns in the select list for distinct queries, and # requires that the ORDER BY include the distinct column. # - # distinct("posts.id", "posts.created_at desc") + # distinct("posts.id", ["posts.created_at desc"]) + # # => "DISTINCT posts.id, posts.created_at AS alias_0" def distinct(columns, orders) #:nodoc: - return "DISTINCT #{columns}" if orders.empty? - - # Construct a clean list of column names from the ORDER BY clause, removing - # any ASC/DESC modifiers - order_columns = orders.collect do |s| - s = s.to_sql unless s.is_a?(String) - s.gsub(/\s+(ASC|DESC)\s*(NULLS\s+(FIRST|LAST)\s*)?/i, '') - end - order_columns.delete_if { |c| c.blank? } - order_columns = order_columns.zip((0...order_columns.size).to_a).map { |s,i| "#{s} AS alias_#{i}" } - - "DISTINCT #{columns}, #{order_columns * ', '}" + order_columns = orders.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)\s*(NULLS\s+(FIRST|LAST)\s*)?/i, '') + }.reject(&:blank?).map.with_index { |column, i| "#{column} AS alias_#{i}" } + + [super].concat(order_columns).join(', ') end end end diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index 957027c1ee..94c6684700 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -83,7 +83,12 @@ module ActiveRecord @attribute_methods_mutex = Mutex.new # force attribute methods to be higher in inheritance hierarchy than other generated methods - generated_attribute_methods + generated_attribute_methods.const_set(:AttrNames, Module.new { + def self.const_missing(name) + const_set(name, [name.to_s.sub(/ATTR_/, '')].pack('h*').freeze) + end + }) + generated_feature_methods end diff --git a/activerecord/lib/active_record/migration/join_table.rb b/activerecord/lib/active_record/migration/join_table.rb index e880ae97bb..ebf64cbcdc 100644 --- a/activerecord/lib/active_record/migration/join_table.rb +++ b/activerecord/lib/active_record/migration/join_table.rb @@ -8,7 +8,7 @@ module ActiveRecord end def join_table_name(table_1, table_2) - [table_1, table_2].sort.join("_").to_sym + [table_1.to_s, table_2.to_s].sort.join("_").to_sym end end end diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index 1c17c578e9..eed49e17b1 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -180,7 +180,7 @@ module ActiveRecord name = name.to_s verify_readonly_attribute(name) send("#{name}=", value) - save(:validate => false) + save(validate: false) end # Updates the attributes of the model from the passed-in hash and saves the @@ -235,8 +235,8 @@ module ActiveRecord updated_count = self.class.where(self.class.primary_key => id).update_all(attributes) - attributes.each do |k,v| - raw_write_attribute(k,v) + attributes.each do |k, v| + raw_write_attribute(k, v) end updated_count == 1 @@ -388,10 +388,14 @@ module ActiveRecord # Returns the number of affected rows. def update(attribute_names = @attributes.keys) attributes_with_values = arel_attributes_with_values_for_update(attribute_names) - return 0 if attributes_with_values.empty? - klass = self.class - stmt = klass.unscoped.where(klass.arel_table[klass.primary_key].eq(id)).arel.compile_update(attributes_with_values) - klass.connection.update stmt + + if attributes_with_values.empty? + 0 + else + klass = self.class + stmt = klass.unscoped.where(klass.arel_table[klass.primary_key].eq(id)).arel.compile_update(attributes_with_values) + klass.connection.update stmt + end end # Creates a record with values matching those of the instance attributes diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 3ee55c580e..f0f170b684 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -31,6 +31,14 @@ module ActiveRecord @default_scoped = false end + def initialize_copy(other) + # This method is a hot spot, so for now, use Hash[] to dup the hash. + # https://bugs.ruby-lang.org/issues/7166 + @values = Hash[@values] + @values[:bind] = @values[:bind].dup if @values.key? :bind + reset + end + def insert(values) primary_key_value = nil @@ -90,14 +98,6 @@ module ActiveRecord scoping { @klass.new(*args, &block) } end - def initialize_copy(other) - # This method is a hot spot, so for now, use Hash[] to dup the hash. - # https://bugs.ruby-lang.org/issues/7166 - @values = Hash[@values] - @values[:bind] = @values[:bind].dup if @values.key? :bind - reset - end - alias build new # Tries to create a new record with the same scoped attributes diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index 741f94f777..72b035a023 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -1,3 +1,5 @@ +require 'active_support/deprecation' + module ActiveRecord module Calculations # Count the records. @@ -13,16 +15,9 @@ module ActiveRecord # # Person.count(:age, distinct: true) # # => counts the number of different age values - # - # Person.where("age > 26").count { |person| person.gender == 'female' } - # # => queries people where "age > 26" then count the loaded results filtering by gender def count(column_name = nil, options = {}) - if block_given? - self.to_a.count { |item| yield item } - else - column_name, options = nil, column_name if column_name.is_a?(Hash) - calculate(:count, column_name, options) - end + column_name, options = nil, column_name if column_name.is_a?(Hash) + calculate(:count, column_name, options) end # Calculates the average value on a given column. Returns +nil+ if there's @@ -56,13 +51,13 @@ module ActiveRecord # +calculate+ for examples with options. # # Person.sum('age') # => 4562 - # # => returns the total sum of all people's age - # - # Person.where('age > 100').sum { |person| person.age - 100 } - # # queries people where "age > 100" then perform a sum calculation with the block returns def sum(*args) if block_given? - self.to_a.sum(*args) { |item| yield item } + ActiveSupport::Deprecation.warn( + "Calling #sum with a block is deprecated and will be removed in Rails 4.1. " \ + "If you want to perform sum calculation over the array of elements, use `to_a.sum(&block)`." + ) + self.to_a.sum(*args) {|*block_args| yield(*block_args)} else calculate(:sum, *args) end diff --git a/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb b/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb index f1362dd15f..872204c644 100644 --- a/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb +++ b/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb @@ -216,6 +216,35 @@ module ActiveRecord assert_equal "(number > 100)", index.where end + def test_distinct_zero_orders + assert_equal "DISTINCT posts.id", + @connection.distinct("posts.id", []) + end + + def test_distinct_one_order + assert_equal "DISTINCT posts.id, posts.created_at AS alias_0", + @connection.distinct("posts.id", ["posts.created_at desc"]) + end + + def test_distinct_few_orders + assert_equal "DISTINCT posts.id, posts.created_at AS alias_0, posts.position AS alias_1", + @connection.distinct("posts.id", ["posts.created_at desc", "posts.position asc"]) + end + + def test_distinct_blank_not_nil_orders + assert_equal "DISTINCT posts.id, posts.created_at AS alias_0", + @connection.distinct("posts.id", ["posts.created_at desc", "", " "]) + end + + def test_distinct_with_arel_order + order = Object.new + def order.to_sql + "posts.created_at desc" + end + assert_equal "DISTINCT posts.id, posts.created_at AS alias_0", + @connection.distinct("posts.id", [order]) + end + def test_distinct_with_nulls assert_equal "DISTINCT posts.title, posts.updater_id AS alias_0", @connection.distinct("posts.title", ["posts.updater_id desc nulls first"]) assert_equal "DISTINCT posts.title, posts.updater_id AS alias_0", @connection.distinct("posts.title", ["posts.updater_id desc nulls last"]) diff --git a/activerecord/test/cases/adapters/postgresql/sql_types_test.rb b/activerecord/test/cases/adapters/postgresql/sql_types_test.rb new file mode 100644 index 0000000000..d7d40f6385 --- /dev/null +++ b/activerecord/test/cases/adapters/postgresql/sql_types_test.rb @@ -0,0 +1,18 @@ +require "cases/helper" + +class SqlTypesTest < ActiveRecord::TestCase + def test_binary_types + assert_equal 'bytea', type_to_sql(:binary, 100_000) + assert_raise ActiveRecord::ActiveRecordError do + type_to_sql :binary, 4294967295 + end + assert_equal 'text', type_to_sql(:text, 100_000) + assert_raise ActiveRecord::ActiveRecordError do + type_to_sql :text, 4294967295 + end + end + + def type_to_sql(*args) + ActiveRecord::Base.connection.type_to_sql(*args) + end +end diff --git a/activerecord/test/cases/adapters/postgresql/timestamp_test.rb b/activerecord/test/cases/adapters/postgresql/timestamp_test.rb index 26507ad654..630bdeec67 100644 --- a/activerecord/test/cases/adapters/postgresql/timestamp_test.rb +++ b/activerecord/test/cases/adapters/postgresql/timestamp_test.rb @@ -75,6 +75,15 @@ class TimestampTest < ActiveRecord::TestCase assert_equal '4', pg_datetime_precision('foos', 'updated_at') end + def test_bc_timestamp + unless current_adapter?(:PostgreSQLAdapter) + return skip("only tested on postgresql") + end + date = Date.new(0) - 1.second + Developer.create!(:name => "aaron", :updated_at => date) + assert_equal date, Developer.find_by_name("aaron").updated_at + end + private def pg_datetime_precision(table_name, column_name) diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index 01afa087be..2ded97582d 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -1579,6 +1579,14 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal [tagging], post.taggings end + def test_build_with_polymotphic_has_many_does_not_allow_to_override_type_and_id + welcome = posts(:welcome) + tagging = welcome.taggings.build(:taggable_id => 99, :taggable_type => 'ShouldNotChange') + + assert_equal welcome.id, tagging.taggable_id + assert_equal 'Post', tagging.taggable_type + end + def test_dont_call_save_callbacks_twice_on_has_many firm = companies(:first_firm) contract = firm.contracts.create! @@ -1658,6 +1666,12 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_deprecated { klass.has_many :foo, :counter_sql => 'lol' } end + test "sum calculation with block for array compatibility is deprecated" do + assert_deprecated do + posts(:welcome).comments.sum { |c| c.id } + end + end + test "has many associations on new records use null relations" do post = Post.new diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index 65d28ea028..5cb7eabf0e 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -383,30 +383,16 @@ class CalculationsTest < ActiveRecord::TestCase Company.where(:type => "Firm").from('companies').count(:type) end - def test_count_with_block_acts_as_array - accounts = Account.where('id > 0') - assert_equal Account.count, accounts.count { true } - assert_equal 0, accounts.count { false } - assert_equal Account.where('credit_limit > 50').size, accounts.count { |account| account.credit_limit > 50 } - assert_equal Account.count, Account.count { true } - assert_equal 0, Account.count { false } - end - - def test_sum_with_block_acts_as_array - accounts = Account.where('id > 0') - assert_equal Account.sum(:credit_limit), accounts.sum { |account| account.credit_limit } - assert_equal Account.sum(:credit_limit) + Account.count, accounts.sum{ |account| account.credit_limit + 1 } - assert_equal 0, accounts.sum { |account| 0 } - end - def test_sum_with_from_option assert_equal Account.sum(:credit_limit), Account.from('accounts').sum(:credit_limit) assert_equal Account.where("credit_limit > 50").sum(:credit_limit), Account.where("credit_limit > 50").from('accounts').sum(:credit_limit) end - def test_sum_array_compatibility - assert_equal Account.sum(:credit_limit), Account.sum(&:credit_limit) + def test_sum_array_compatibility_deprecation + assert_deprecated do + assert_equal Account.sum(:credit_limit), Account.sum(&:credit_limit) + end end def test_average_with_from_option diff --git a/activerecord/test/cases/migration/create_join_table_test.rb b/activerecord/test/cases/migration/create_join_table_test.rb index cd1b0e8b47..f262bbaad7 100644 --- a/activerecord/test/cases/migration/create_join_table_test.rb +++ b/activerecord/test/cases/migration/create_join_table_test.rb @@ -35,6 +35,12 @@ module ActiveRecord assert_equal %w(artist_id music_id), connection.columns(:artists_musics).map(&:name).sort end + def test_create_join_table_with_symbol_and_string + connection.create_join_table :artists, 'musics' + + assert_equal %w(artist_id music_id), connection.columns(:artists_musics).map(&:name).sort + end + def test_create_join_table_with_the_proper_order connection.create_join_table :videos, :musics diff --git a/activerecord/test/schema/postgresql_specific_schema.rb b/activerecord/test/schema/postgresql_specific_schema.rb index d0e7338f15..0cfde83778 100644 --- a/activerecord/test/schema/postgresql_specific_schema.rb +++ b/activerecord/test/schema/postgresql_specific_schema.rb @@ -192,5 +192,10 @@ end _SQL rescue #This version of PostgreSQL either has no XML support or is was not compiled with XML support: skipping table end + + create_table :limitless_fields, force: true do |t| + t.binary :binary, limit: 100_000 + t.text :text, limit: 100_000 + end end |