diff options
Diffstat (limited to 'activerecord')
24 files changed, 153 insertions, 135 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 5588b24851..3c4f06ccf8 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,5 +1,22 @@ -* Added ActiveRecord::SecureToken in order to encapsulate generation of - unique tokens for attributes in a model using SecureRandom +* Fix accessing of fixtures having non-string labels like Fixnum. + + *Prathamesh Sonpatki* + +* Remove deprecated support to preload instance-dependent associations. + + *Yves Senn* + +* Remove deprecated support for PostgreSQL ranges with exclusive lower bounds. + + *Yves Senn* + +* Remove deprecation when modifying a relation with cached arel. + This raises an `ImmutableRelation` error instead. + + *Yves Senn* + +* Added `ActiveRecord::SecureToken` in order to encapsulate generation of + unique tokens for attributes in a model using `SecureRandom`. *Roberto Miranda* @@ -16,12 +33,12 @@ *Rafael Mendonça França* -* Change transaction callbacks to not swallowing errors. +* Change transaction callbacks to not swallow errors. - Before this change any error raised inside a transaction callback are - rescued and printed in the logs. + Before this change any errors raised inside a transaction callback + were getting rescued and printed in the logs. - Now these errors are not rescue anymore and just bubble up, as the other callbacks. + Now these errors are not rescued anymore and just bubble up, as the other callbacks. *Rafael Mendonça França* @@ -41,7 +58,7 @@ *Rafael Mendonça França* -* Remove deprecated access to connection specification using a string acessor. +* Remove deprecated access to connection specification using a string accessor. Now all strings will be handled as a URL. diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb index 4b72fe7d7e..24e30b6608 100644 --- a/activerecord/lib/active_record/attribute_methods/read.rb +++ b/activerecord/lib/active_record/attribute_methods/read.rb @@ -72,12 +72,9 @@ module ActiveRecord def _read_attribute(attr_name) # :nodoc: @attributes.fetch_value(attr_name.to_s) { |n| yield n if block_given? } end + alias :attribute :_read_attribute + private :attribute - private - - def attribute(attribute_name) - _read_attribute(attribute_name) - end end end end diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index c3a8bf5c74..e52b666296 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -392,7 +392,7 @@ module ActiveRecord end def column_name_for_operation(operation, node) # :nodoc: - node.to_sql + visitor.accept(node, collector).value end protected 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 961e6224c4..3adfb8b9d8 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/range.rb @@ -25,16 +25,7 @@ module ActiveRecord to = type_cast_single extracted[:to] if !infinity?(from) && extracted[:exclude_start] - if from.respond_to?(:succ) - from = from.succ - ActiveSupport::Deprecation.warn(<<-MSG.squish) - Excluding the beginning of a Range is only partialy supported - through `#succ`. This is not reliable and will be removed in - the future. - MSG - else - raise ArgumentError, "The Ruby Range object does not support excluding the beginning of a Range. (unsupported value: '#{value}')" - end + raise ArgumentError, "The Ruby Range object does not support excluding the beginning of a Range. (unsupported value: '#{value}')" end ::Range.new(from, to, extracted[:exclude_end]) end diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index 5c7c0feeb7..5a5139256d 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -276,11 +276,11 @@ module ActiveRecord # User.new(first_name: 'Jamie') def initialize(attributes = nil, options = {}) @attributes = self.class._default_attributes.dup + self.class.define_attribute_methods init_internals initialize_internals_callback - self.class.define_attribute_methods # +options+ argument is only needed to make protected_attributes gem easier to hook. # Remove it when we drop support to this gem. init_attributes(attributes, options) if attributes diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb index 3c71936c3b..10e9be20b5 100644 --- a/activerecord/lib/active_record/fixtures.rb +++ b/activerecord/lib/active_record/fixtures.rb @@ -633,7 +633,7 @@ module ActiveRecord # interpolate the fixture label row.each do |key, value| - row[key] = value.gsub("$LABEL", label) if value.is_a?(String) + row[key] = value.gsub("$LABEL", label.to_s) if value.is_a?(String) end # generate a primary key if necessary @@ -882,7 +882,7 @@ module ActiveRecord @fixture_cache[fs_name] ||= {} instances = fixture_names.map do |f_name| - f_name = f_name.to_s + f_name = f_name.to_s if f_name.is_a?(Symbol) @fixture_cache[fs_name].delete(f_name) if force_reload if @loaded_fixtures[fs_name][f_name] diff --git a/activerecord/lib/active_record/reflection.rb b/activerecord/lib/active_record/reflection.rb index 66f2b6b768..dab5a502a5 100644 --- a/activerecord/lib/active_record/reflection.rb +++ b/activerecord/lib/active_record/reflection.rb @@ -343,13 +343,10 @@ module ActiveRecord return unless scope if scope.arity > 0 - ActiveSupport::Deprecation.warn(<<-MSG.squish) + raise ArgumentError, <<-MSG.squish The association scope '#{name}' is instance dependent (the scope - block takes an argument). Preloading happens before the individual - instances are created. This means that there is no instance being - passed to the association scope. This will most likely result in - broken or incorrect behavior. Joining, Preloading and eager loading - of these associations is deprecated and will be removed in the future. + block takes an argument). Preloading instance dependent scopes is + not supported. MSG end end diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index ef380abfe8..f054e17017 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -62,15 +62,14 @@ module ActiveRecord Relation::MULTI_VALUE_METHODS.each do |name| class_eval <<-CODE, __FILE__, __LINE__ + 1 - def #{name}_values # def select_values - @values[:#{name}] || [] # @values[:select] || [] - end # end - # - def #{name}_values=(values) # def select_values=(values) - raise ImmutableRelation if @loaded # raise ImmutableRelation if @loaded - check_cached_relation - @values[:#{name}] = values # @values[:select] = values - end # end + def #{name}_values # def select_values + @values[:#{name}] || [] # @values[:select] || [] + end # end + # + def #{name}_values=(values) # def select_values=(values) + assert_mutability! # assert_mutability! + @values[:#{name}] = values # @values[:select] = values + end # end CODE end @@ -85,23 +84,12 @@ module ActiveRecord Relation::SINGLE_VALUE_METHODS.each do |name| class_eval <<-CODE, __FILE__, __LINE__ + 1 def #{name}_value=(value) # def readonly_value=(value) - raise ImmutableRelation if @loaded # raise ImmutableRelation if @loaded - check_cached_relation + assert_mutability! # assert_mutability! @values[:#{name}] = value # @values[:readonly] = value end # end CODE end - def check_cached_relation # :nodoc: - if defined?(@arel) && @arel - @arel = nil - ActiveSupport::Deprecation.warn(<<-MSG.squish) - Modifying already cached Relation. The cache will be reset. Use a - cloned Relation to prevent this warning. - MSG - end - end - def create_with_value # :nodoc: @values[:create_with] || {} end @@ -757,6 +745,9 @@ module ActiveRecord def from!(value, subquery_name = nil) # :nodoc: self.from_value = [value, subquery_name] + if value.is_a? Relation + self.bind_values = value.arel.bind_values + value.bind_values + bind_values + end self end @@ -857,6 +848,11 @@ module ActiveRecord private + def assert_mutability! + raise ImmutableRelation if @loaded + raise ImmutableRelation if defined?(@arel) && @arel + end + def build_arel arel = Arel::SelectManager.new(table) @@ -1006,7 +1002,6 @@ module ActiveRecord case opts when Relation name ||= 'subquery' - self.bind_values = opts.bind_values + self.bind_values opts.arel.as(name.to_s) else opts diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb index 1c48196762..9cef50029b 100644 --- a/activerecord/lib/active_record/transactions.rb +++ b/activerecord/lib/active_record/transactions.rb @@ -378,7 +378,7 @@ module ActiveRecord thaw unless restore_state[:frozen?] @new_record = restore_state[:new_record] @destroyed = restore_state[:destroyed] - write_attribute(self.class.primary_key, restore_state[:id]) + write_attribute(self.class.primary_key, restore_state[:id]) if self.class.primary_key end end end diff --git a/activerecord/test/cases/adapters/postgresql/range_test.rb b/activerecord/test/cases/adapters/postgresql/range_test.rb index d812cd01c4..70cf21100a 100644 --- a/activerecord/test/cases/adapters/postgresql/range_test.rb +++ b/activerecord/test/cases/adapters/postgresql/range_test.rb @@ -230,36 +230,14 @@ _SQL assert_nil_round_trip(@first_range, :int8_range, 39999...39999) end - def test_exclude_beginning_for_subtypes_with_succ_method_is_deprecated - tz = ::ActiveRecord::Base.default_timezone - - silence_warnings { - assert_deprecated { - range = PostgresqlRange.create!(date_range: "(''2012-01-02'', ''2012-01-04'']") - assert_equal Date.new(2012, 1, 3)..Date.new(2012, 1, 4), range.date_range - } - assert_deprecated { - range = PostgresqlRange.create!(ts_range: "(''2010-01-01 14:30'', ''2011-01-01 14:30'']") - assert_equal Time.send(tz, 2010, 1, 1, 14, 30, 1)..Time.send(tz, 2011, 1, 1, 14, 30, 0), range.ts_range - } - assert_deprecated { - range = PostgresqlRange.create!(tstz_range: "(''2010-01-01 14:30:00+05'', ''2011-01-01 14:30:00-03'']") - assert_equal Time.parse('2010-01-01 09:30:01 UTC')..Time.parse('2011-01-01 17:30:00 UTC'), range.tstz_range - } - assert_deprecated { - range = PostgresqlRange.create!(int4_range: "(1, 10]") - assert_equal 2..10, range.int4_range - } - assert_deprecated { - range = PostgresqlRange.create!(int8_range: "(10, 100]") - assert_equal 11..100, range.int8_range - } - } - end - def test_exclude_beginning_for_subtypes_without_succ_method_is_not_supported assert_raises(ArgumentError) { PostgresqlRange.create!(num_range: "(0.1, 0.2]") } assert_raises(ArgumentError) { PostgresqlRange.create!(float_range: "(0.5, 0.7]") } + assert_raises(ArgumentError) { PostgresqlRange.create!(int4_range: "(1, 10]") } + assert_raises(ArgumentError) { PostgresqlRange.create!(int8_range: "(10, 100]") } + assert_raises(ArgumentError) { PostgresqlRange.create!(date_range: "(''2012-01-02'', ''2012-01-04'']") } + assert_raises(ArgumentError) { PostgresqlRange.create!(ts_range: "(''2010-01-01 14:30'', ''2011-01-01 14:30'']") } + assert_raises(ArgumentError) { PostgresqlRange.create!(tstz_range: "(''2010-01-01 14:30:00+05'', ''2011-01-01 14:30:00-03'']") } end def test_update_all_with_ranges diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb index fdb437d11d..371635d20a 100644 --- a/activerecord/test/cases/associations/eager_test.rb +++ b/activerecord/test/cases/associations/eager_test.rb @@ -826,18 +826,6 @@ class EagerAssociationTest < ActiveRecord::TestCase ) end - def test_preload_with_interpolation - assert_deprecated do - post = Post.includes(:comments_with_interpolated_conditions).find(posts(:welcome).id) - assert_equal [comments(:greetings)], post.comments_with_interpolated_conditions - end - - assert_deprecated do - post = Post.joins(:comments_with_interpolated_conditions).find(posts(:welcome).id) - assert_equal [comments(:greetings)], post.comments_with_interpolated_conditions - end - end - def test_polymorphic_type_condition post = Post.all.merge!(:includes => :taggings).find(posts(:thinking).id) assert post.taggings.include?(taggings(:thinking_general)) @@ -1294,23 +1282,22 @@ class EagerAssociationTest < ActiveRecord::TestCase assert_equal pets(:parrot), Owner.including_last_pet.first.last_pet end - test "include instance dependent associations is deprecated" do + test "preloading and eager loading of instance dependent associations is not supported" do message = "association scope 'posts_with_signature' is" - assert_deprecated message do - begin - Author.includes(:posts_with_signature).to_a - rescue NoMethodError - # it's expected that preloading of this association fails - end + error = assert_raises(ArgumentError) do + Author.includes(:posts_with_signature).to_a end + assert_match message, error.message - assert_deprecated message do - Author.preload(:posts_with_signature).to_a rescue NoMethodError + error = assert_raises(ArgumentError) do + Author.preload(:posts_with_signature).to_a end + assert_match message, error.message - assert_deprecated message do + error = assert_raises(ArgumentError) do Author.eager_load(:posts_with_signature).to_a end + assert_match message, error.message end test "preloading readonly association" do diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb index feb1fca500..01ee1234a2 100644 --- a/activerecord/test/cases/attribute_methods_test.rb +++ b/activerecord/test/cases/attribute_methods_test.rb @@ -502,7 +502,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase def test_typecast_attribute_from_select_to_false Topic.create(:title => 'Budget') # Oracle does not support boolean expressions in SELECT - if current_adapter?(:OracleAdapter) + if current_adapter?(:OracleAdapter, :FbAdapter) topic = Topic.all.merge!(:select => "topics.*, 0 as is_test").first else topic = Topic.all.merge!(:select => "topics.*, 1=2 as is_test").first @@ -513,7 +513,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase def test_typecast_attribute_from_select_to_true Topic.create(:title => 'Budget') # Oracle does not support boolean expressions in SELECT - if current_adapter?(:OracleAdapter) + if current_adapter?(:OracleAdapter, :FbAdapter) topic = Topic.all.merge!(:select => "topics.*, 1 as is_test").first else topic = Topic.all.merge!(:select => "topics.*, 2=2 as is_test").first diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index 6acd9aa39f..0debd30e5c 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -88,6 +88,7 @@ class BasicsTest < ActiveRecord::TestCase 'Mysql2Adapter' => '`', 'PostgreSQLAdapter' => '"', 'OracleAdapter' => '"', + 'FbAdapter' => '"' }.fetch(classname) { raise "need a bad char for #{classname}" } @@ -111,7 +112,7 @@ class BasicsTest < ActiveRecord::TestCase assert_nil Edge.primary_key end - unless current_adapter?(:PostgreSQLAdapter, :OracleAdapter, :SQLServerAdapter) + unless current_adapter?(:PostgreSQLAdapter, :OracleAdapter, :SQLServerAdapter, :FbAdapter) def test_limit_with_comma assert Topic.limit("1,2").to_a end diff --git a/activerecord/test/cases/bind_parameter_test.rb b/activerecord/test/cases/bind_parameter_test.rb index c4634d11e2..66663b3e0e 100644 --- a/activerecord/test/cases/bind_parameter_test.rb +++ b/activerecord/test/cases/bind_parameter_test.rb @@ -1,9 +1,11 @@ require 'cases/helper' require 'models/topic' +require 'models/author' +require 'models/post' module ActiveRecord class BindParameterTest < ActiveRecord::TestCase - fixtures :topics + fixtures :topics, :authors, :posts class LogListener attr_accessor :calls @@ -30,6 +32,12 @@ module ActiveRecord end if ActiveRecord::Base.connection.supports_statement_cache? + def test_bind_from_join_in_subquery + subquery = Author.joins(:thinking_posts).where(name: 'David') + scope = Author.from(subquery, 'authors').where(id: 1) + assert_equal 1, scope.count + end + def test_binds_are_logged sub = @connection.substitute_at(@pk) binds = [[@pk, 1]] diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb index 9edeb8b47f..07ec08ccf5 100644 --- a/activerecord/test/cases/fixtures_test.rb +++ b/activerecord/test/cases/fixtures_test.rb @@ -792,6 +792,10 @@ class FoxyFixturesTest < ActiveRecord::TestCase assert_equal("X marks the spot!", pirates(:mark).catchphrase) end + def test_supports_label_interpolation_for_fixnum_label + assert_equal("#1 pirate!", pirates(1).catchphrase) + end + def test_supports_polymorphic_belongs_to assert_equal(pirates(:redbeard), treasures(:sapphire).looter) assert_equal(parrots(:louis), treasures(:ruby).looter) diff --git a/activerecord/test/cases/migration/rename_table_test.rb b/activerecord/test/cases/migration/rename_table_test.rb index c8b3f75e10..a018bac43d 100644 --- a/activerecord/test/cases/migration/rename_table_test.rb +++ b/activerecord/test/cases/migration/rename_table_test.rb @@ -39,33 +39,35 @@ module ActiveRecord end end - def test_rename_table - rename_table :test_models, :octopi + unless current_adapter?(:FbAdapter) # Firebird cannot rename tables + def test_rename_table + rename_table :test_models, :octopi - connection.execute "INSERT INTO octopi (#{connection.quote_column_name('id')}, #{connection.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')" + connection.execute "INSERT INTO octopi (#{connection.quote_column_name('id')}, #{connection.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')" - assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', connection.select_value("SELECT url FROM octopi WHERE id=1") - end + assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', connection.select_value("SELECT url FROM octopi WHERE id=1") + end - def test_rename_table_with_an_index - add_index :test_models, :url + def test_rename_table_with_an_index + add_index :test_models, :url - rename_table :test_models, :octopi + rename_table :test_models, :octopi - connection.execute "INSERT INTO octopi (#{connection.quote_column_name('id')}, #{connection.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')" + connection.execute "INSERT INTO octopi (#{connection.quote_column_name('id')}, #{connection.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')" - assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', connection.select_value("SELECT url FROM octopi WHERE id=1") - index = connection.indexes(:octopi).first - assert index.columns.include?("url") - assert_equal 'index_octopi_on_url', index.name - end + assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', connection.select_value("SELECT url FROM octopi WHERE id=1") + index = connection.indexes(:octopi).first + assert index.columns.include?("url") + assert_equal 'index_octopi_on_url', index.name + end - def test_rename_table_does_not_rename_custom_named_index - add_index :test_models, :url, name: 'special_url_idx' + def test_rename_table_does_not_rename_custom_named_index + add_index :test_models, :url, name: 'special_url_idx' - rename_table :test_models, :octopi + rename_table :test_models, :octopi - assert_equal ['special_url_idx'], connection.indexes(:octopi).map(&:name) + assert_equal ['special_url_idx'], connection.indexes(:octopi).map(&:name) + end end if current_adapter?(:PostgreSQLAdapter) diff --git a/activerecord/test/cases/multiple_db_test.rb b/activerecord/test/cases/multiple_db_test.rb index 3831de6ae3..15c60d5562 100644 --- a/activerecord/test/cases/multiple_db_test.rb +++ b/activerecord/test/cases/multiple_db_test.rb @@ -93,6 +93,13 @@ class MultipleDbTest < ActiveRecord::TestCase assert_not_equal Entrant.arel_engine.connection, Course.arel_engine.connection end + def test_count_on_custom_connection + ActiveRecord::Base.remove_connection + assert_equal 1, College.count + ensure + ActiveRecord::Base.establish_connection :arunit + end + unless in_memory_db? def test_associations_should_work_when_model_has_no_connection begin diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index 2e2c5ee10b..9631ea79be 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -1651,6 +1651,14 @@ class RelationTest < ActiveRecord::TestCase end end + test "relations with cached arel can't be mutated [internal API]" do + relation = Post.all + relation.count + + assert_raises(ActiveRecord::ImmutableRelation) { relation.limit!(5) } + assert_raises(ActiveRecord::ImmutableRelation) { relation.where!("1 = 2") } + end + test "relations show the records in #inspect" do relation = Post.limit(2) assert_equal "#<ActiveRecord::Relation [#{Post.limit(2).map(&:inspect).join(', ')}]>", relation.inspect diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb index 57b7346503..b52c66356c 100644 --- a/activerecord/test/cases/schema_dumper_test.rb +++ b/activerecord/test/cases/schema_dumper_test.rb @@ -272,6 +272,8 @@ class SchemaDumperTest < ActiveRecord::TestCase # Oracle supports precision up to 38 and it identifies decimals with scale 0 as integers if current_adapter?(:OracleAdapter) assert_match %r{t.integer\s+"atoms_in_universe",\s+precision: 38}, output + elsif current_adapter?(:FbAdapter) + assert_match %r{t.integer\s+"atoms_in_universe",\s+precision: 18}, output else assert_match %r{t.decimal\s+"atoms_in_universe",\s+precision: 55}, output end diff --git a/activerecord/test/cases/secure_token_test.rb b/activerecord/test/cases/secure_token_test.rb index 400fce8c6e..dc12b528dc 100644 --- a/activerecord/test/cases/secure_token_test.rb +++ b/activerecord/test/cases/secure_token_test.rb @@ -6,13 +6,13 @@ class SecureTokenTest < ActiveRecord::TestCase @user = User.new end - test "assing unique token values" do + def test_token_values_are_generated_for_specified_attributes_and_persisted_on_save @user.save assert_not_nil @user.token assert_not_nil @user.auth_token end - test "regenerate the secure key for the attribute" do + def test_regenerating_the_secure_token @user.save old_token = @user.token old_auth_token = @user.auth_token @@ -23,15 +23,15 @@ class SecureTokenTest < ActiveRecord::TestCase assert_not_equal @user.auth_token, old_auth_token end - test "raise and exception when with 10 attemps is reached" do + def test_raise_after_ten_unsuccessful_attempts_to_generate_a_unique_token User.stubs(:exists?).returns(*Array.new(10, true)) assert_raises(RuntimeError) do @user.save end end - test "assing unique token after 9 attemps reached" do - User.stubs(:exists?).returns(*Array.new(10){ |i| i == 9 ? false : true}) + def test_return_unique_token_after_nine_unsuccessful_attempts + User.stubs(:exists?).returns(*Array.new(10) { |i| i == 9 ? false : true }) @user.save assert_not_nil @user.token assert_not_nil @user.auth_token diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb index c4f2ed474d..d1d8e71c34 100644 --- a/activerecord/test/cases/transactions_test.rb +++ b/activerecord/test/cases/transactions_test.rb @@ -504,6 +504,8 @@ class TransactionTest < ActiveRecord::TestCase end def test_rollback_when_thread_killed + return if in_memory_db? + queue = Queue.new thread = Thread.new do Topic.transaction do @@ -648,6 +650,27 @@ class TransactionTest < ActiveRecord::TestCase assert transaction.state.committed? end + def test_transaction_rollback_with_primarykeyless_tables + connection = ActiveRecord::Base.connection + connection.create_table(:transaction_without_primary_keys, force: true, id: false) do |t| + t.integer :thing_id + end + + klass = Class.new(ActiveRecord::Base) do + self.table_name = 'transaction_without_primary_keys' + after_commit { } # necessary to trigger the has_transactional_callbacks branch + end + + assert_no_difference(-> { klass.count }) do + ActiveRecord::Base.transaction do + klass.create! + raise ActiveRecord::Rollback + end + end + ensure + connection.execute("DROP TABLE IF EXISTS transaction_without_primary_keys") + end + private %w(validation save destroy).each do |filter| diff --git a/activerecord/test/fixtures/pirates.yml b/activerecord/test/fixtures/pirates.yml index 1bb3bf0051..0b1a785853 100644 --- a/activerecord/test/fixtures/pirates.yml +++ b/activerecord/test/fixtures/pirates.yml @@ -10,3 +10,6 @@ redbeard: mark: catchphrase: "X $LABELs the spot!" + +1: + catchphrase: "#$LABEL pirate!" diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb index 56073cc588..7b637c9e3f 100644 --- a/activerecord/test/models/post.rb +++ b/activerecord/test/models/post.rb @@ -72,10 +72,6 @@ class Post < ActiveRecord::Base through: :author_with_address, source: :author_address_extra - has_many :comments_with_interpolated_conditions, - ->(p) { where "#{"#{p.aliased_table_name}." rescue ""}body = ?", 'Thank you for the welcome' }, - :class_name => 'Comment' - has_one :very_special_comment has_one :very_special_comment_with_post, -> { includes(:post) }, :class_name => "VerySpecialComment" has_one :very_special_comment_with_post_with_joins, -> { joins(:post).order('posts.id') }, class_name: "VerySpecialComment" diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index e283f7a9cc..21b23d8e0c 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -479,6 +479,8 @@ ActiveRecord::Schema.define do # Oracle/SQLServer supports precision up to 38 if current_adapter?(:OracleAdapter, :SQLServerAdapter) t.decimal :atoms_in_universe, precision: 38, scale: 0 + elsif current_adapter?(:FbAdapter) + t.decimal :atoms_in_universe, precision: 18, scale: 0 else t.decimal :atoms_in_universe, precision: 55, scale: 0 end |