aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test/cases
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/test/cases')
-rw-r--r--activerecord/test/cases/adapter_test.rb23
-rw-r--r--activerecord/test/cases/adapters/postgresql/array_test.rb12
-rw-r--r--activerecord/test/cases/adapters/postgresql/json_test.rb2
-rw-r--r--activerecord/test/cases/adapters/postgresql/range_test.rb2
-rw-r--r--activerecord/test/cases/adapters/postgresql/schema_test.rb6
-rw-r--r--activerecord/test/cases/adapters/postgresql/xml_test.rb2
-rw-r--r--activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb38
-rw-r--r--activerecord/test/cases/associations/belongs_to_associations_test.rb17
-rw-r--r--activerecord/test/cases/associations/eager_singularization_test.rb195
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb165
-rw-r--r--activerecord/test/cases/associations/has_one_associations_test.rb17
-rw-r--r--activerecord/test/cases/associations_test.rb9
-rw-r--r--activerecord/test/cases/autosave_association_test.rb17
-rw-r--r--activerecord/test/cases/base_test.rb11
-rw-r--r--activerecord/test/cases/batches_test.rb23
-rw-r--r--activerecord/test/cases/calculations_test.rb22
-rw-r--r--activerecord/test/cases/connection_management_test.rb2
-rw-r--r--activerecord/test/cases/enum_test.rb140
-rw-r--r--activerecord/test/cases/finder_respond_to_test.rb5
-rw-r--r--activerecord/test/cases/finder_test.rb128
-rw-r--r--activerecord/test/cases/hot_compatibility_test.rb2
-rw-r--r--activerecord/test/cases/inheritance_test.rb24
-rw-r--r--activerecord/test/cases/integration_test.rb18
-rw-r--r--activerecord/test/cases/locking_test.rb11
-rw-r--r--activerecord/test/cases/migration_test.rb58
-rw-r--r--activerecord/test/cases/mixin_test.rb6
-rw-r--r--activerecord/test/cases/persistence_test.rb4
-rw-r--r--activerecord/test/cases/query_cache_test.rb7
-rw-r--r--activerecord/test/cases/relation/mutation_test.rb4
-rw-r--r--activerecord/test/cases/relations_test.rb77
-rw-r--r--activerecord/test/cases/schema_dumper_test.rb2
-rw-r--r--activerecord/test/cases/scoping/default_scoping_test.rb10
-rw-r--r--activerecord/test/cases/scoping/named_scoping_test.rb65
-rw-r--r--activerecord/test/cases/store_test.rb24
-rw-r--r--activerecord/test/cases/transaction_callbacks_test.rb157
-rw-r--r--activerecord/test/cases/transactions_test.rb11
-rw-r--r--activerecord/test/cases/validations/i18n_generate_message_validation_test.rb2
37 files changed, 959 insertions, 359 deletions
diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb
index b67e70ec7e..0eb1231c79 100644
--- a/activerecord/test/cases/adapter_test.rb
+++ b/activerecord/test/cases/adapter_test.rb
@@ -1,5 +1,7 @@
require "cases/helper"
require "models/book"
+require "models/post"
+require "models/author"
module ActiveRecord
class AdapterTest < ActiveRecord::TestCase
@@ -179,6 +181,27 @@ module ActiveRecord
assert result.is_a?(ActiveRecord::Result)
end
+ def test_select_methods_passing_a_association_relation
+ author = Author.create!(name: 'john')
+ Post.create!(author: author, title: 'foo', body: 'bar')
+ query = author.posts.select(:title)
+ assert_equal({"title" => "foo"}, @connection.select_one(query.arel, nil, query.bind_values))
+ assert_equal({"title" => "foo"}, @connection.select_one(query))
+ assert @connection.select_all(query).is_a?(ActiveRecord::Result)
+ assert_equal "foo", @connection.select_value(query)
+ assert_equal ["foo"], @connection.select_values(query)
+ end
+
+ def test_select_methods_passing_a_relation
+ Post.create!(title: 'foo', body: 'bar')
+ query = Post.where(title: 'foo').select(:title)
+ assert_equal({"title" => "foo"}, @connection.select_one(query.arel, nil, query.bind_values))
+ assert_equal({"title" => "foo"}, @connection.select_one(query))
+ assert @connection.select_all(query).is_a?(ActiveRecord::Result)
+ assert_equal "foo", @connection.select_value(query)
+ assert_equal ["foo"], @connection.select_values(query)
+ end
+
test "type_to_sql returns a String for unmapped types" do
assert_equal "special_db_type", @connection.type_to_sql(:special_db_type)
end
diff --git a/activerecord/test/cases/adapters/postgresql/array_test.rb b/activerecord/test/cases/adapters/postgresql/array_test.rb
index d71e2aa2bb..3090f4478f 100644
--- a/activerecord/test/cases/adapters/postgresql/array_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/array_test.rb
@@ -93,6 +93,18 @@ class PostgresqlArrayTest < ActiveRecord::TestCase
assert_cycle(:tags, [[['1'], ['2']], [['2'], ['3']]])
end
+ def test_with_empty_strings
+ assert_cycle(:tags, [ '1', '2', '', '4', '', '5' ])
+ end
+
+ def test_with_multi_dimensional_empty_strings
+ assert_cycle(:tags, [[['1', '2'], ['', '4'], ['', '5']]])
+ end
+
+ def test_with_arbitrary_whitespace
+ assert_cycle(:tags, [[['1', '2'], [' ', '4'], [' ', '5']]])
+ end
+
def test_multi_dimensional_with_integers
assert_cycle(:ratings, [[[1], [7]], [[8], [10]]])
end
diff --git a/activerecord/test/cases/adapters/postgresql/json_test.rb b/activerecord/test/cases/adapters/postgresql/json_test.rb
index 01e7334aad..3daef399d8 100644
--- a/activerecord/test/cases/adapters/postgresql/json_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/json_test.rb
@@ -21,7 +21,7 @@ class PostgresqlJSONTest < ActiveRecord::TestCase
end
end
rescue ActiveRecord::StatementInvalid
- return skip "do not test on PG without json"
+ skip "do not test on PG without json"
end
@column = JsonDataType.columns.find { |c| c.name == 'payload' }
end
diff --git a/activerecord/test/cases/adapters/postgresql/range_test.rb b/activerecord/test/cases/adapters/postgresql/range_test.rb
index a56b8ac791..5c2d8e1c1d 100644
--- a/activerecord/test/cases/adapters/postgresql/range_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/range_test.rb
@@ -26,7 +26,7 @@ if ActiveRecord::Base.connection.supports_ranges?
end
end
rescue ActiveRecord::StatementInvalid
- return skip "do not test on PG without range"
+ skip "do not test on PG without range"
end
insert_range(id: 101,
diff --git a/activerecord/test/cases/adapters/postgresql/schema_test.rb b/activerecord/test/cases/adapters/postgresql/schema_test.rb
index c67997c5a1..3f7009c1d1 100644
--- a/activerecord/test/cases/adapters/postgresql/schema_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/schema_test.rb
@@ -115,6 +115,12 @@ class SchemaTest < ActiveRecord::TestCase
end
end
+ def test_raise_wraped_exception_on_bad_prepare
+ assert_raises(ActiveRecord::StatementInvalid) do
+ @connection.exec_query "select * from developers where id = ?", 'sql', [[nil, 1]]
+ end
+ end
+
def test_schema_change_with_prepared_stmt
altered = false
@connection.exec_query "select * from developers where id = $1", 'sql', [[nil, 1]]
diff --git a/activerecord/test/cases/adapters/postgresql/xml_test.rb b/activerecord/test/cases/adapters/postgresql/xml_test.rb
index bf14b378d8..dd2a727afe 100644
--- a/activerecord/test/cases/adapters/postgresql/xml_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/xml_test.rb
@@ -18,7 +18,7 @@ class PostgresqlXMLTest < ActiveRecord::TestCase
end
end
rescue ActiveRecord::StatementInvalid
- return skip "do not test on PG without xml"
+ skip "do not test on PG without xml"
end
@column = XmlDataType.columns.find { |c| c.name == 'payload' }
end
diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
index 0598ff25f8..02834edf7b 100644
--- a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
+++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
@@ -34,24 +34,30 @@ module ActiveRecord
end
def test_connect_with_url
- original_connection = ActiveRecord::Base.remove_connection
- tf = Tempfile.open 'whatever'
- url = "sqlite3://#{tf.path}"
- ActiveRecord::Base.establish_connection(url)
- assert ActiveRecord::Base.connection
- ensure
- tf.close
- tf.unlink
- ActiveRecord::Base.establish_connection(original_connection)
+ skip "can't establish new connection when using memory db" if in_memory_db?
+ begin
+ original_connection = ActiveRecord::Base.remove_connection
+ tf = Tempfile.open 'whatever'
+ url = "sqlite3://#{tf.path}"
+ ActiveRecord::Base.establish_connection(url)
+ assert ActiveRecord::Base.connection
+ ensure
+ tf.close
+ tf.unlink
+ ActiveRecord::Base.establish_connection(original_connection)
+ end
end
def test_connect_memory_with_url
- original_connection = ActiveRecord::Base.remove_connection
- url = "sqlite3:///:memory:"
- ActiveRecord::Base.establish_connection(url)
- assert ActiveRecord::Base.connection
- ensure
- ActiveRecord::Base.establish_connection(original_connection)
+ skip "can't establish new connection when using memory db" if in_memory_db?
+ begin
+ original_connection = ActiveRecord::Base.remove_connection
+ url = "sqlite3:///:memory:"
+ ActiveRecord::Base.establish_connection(url)
+ assert ActiveRecord::Base.connection
+ ensure
+ ActiveRecord::Base.establish_connection(original_connection)
+ end
end
def test_valid_column
@@ -183,7 +189,7 @@ module ActiveRecord
DualEncoding.connection.execute(<<-eosql)
CREATE TABLE dual_encodings (
id integer PRIMARY KEY AUTOINCREMENT,
- name string,
+ name varchar(255),
data binary
)
eosql
diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb
index 3205d0c28b..9340bc0a83 100644
--- a/activerecord/test/cases/associations/belongs_to_associations_test.rb
+++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb
@@ -28,6 +28,13 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
assert_equal companies(:first_firm).name, firm.name
end
+ def test_belongs_to_does_not_use_order_by
+ ActiveRecord::SQLCounter.clear_log
+ Client.find(3).firm
+ ensure
+ assert ActiveRecord::SQLCounter.log_all.all? { |sql| /order by/i !~ sql }, 'ORDER BY was used in the query'
+ end
+
def test_belongs_to_with_primary_key
client = Client.create(:name => "Primary key client", :firm_name => companies(:first_firm).name)
assert_equal companies(:first_firm).name, client.firm_with_primary_key.name
@@ -846,4 +853,14 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
assert post.save
assert_equal post.author_id, author2.id
end
+
+ test 'dangerous association name raises ArgumentError' do
+ [:errors, 'errors', :save, 'save'].each do |name|
+ assert_raises(ArgumentError, "Association #{name} should not be allowed") do
+ Class.new(ActiveRecord::Base) do
+ belongs_to name
+ end
+ end
+ end
+ end
end
diff --git a/activerecord/test/cases/associations/eager_singularization_test.rb b/activerecord/test/cases/associations/eager_singularization_test.rb
index 634f6b63ba..669569a774 100644
--- a/activerecord/test/cases/associations/eager_singularization_test.rb
+++ b/activerecord/test/cases/associations/eager_singularization_test.rb
@@ -1,128 +1,133 @@
require "cases/helper"
-class Virus < ActiveRecord::Base
- belongs_to :octopus
-end
-class Octopus < ActiveRecord::Base
- has_one :virus
-end
-class Pass < ActiveRecord::Base
- belongs_to :bus
-end
-class Bus < ActiveRecord::Base
- has_many :passes
-end
-class Mess < ActiveRecord::Base
- has_and_belongs_to_many :crises
-end
-class Crisis < ActiveRecord::Base
- has_and_belongs_to_many :messes
- has_many :analyses, :dependent => :destroy
- has_many :successes, :through => :analyses
- has_many :dresses, :dependent => :destroy
- has_many :compresses, :through => :dresses
-end
-class Analysis < ActiveRecord::Base
- belongs_to :crisis
- belongs_to :success
-end
-class Success < ActiveRecord::Base
- has_many :analyses, :dependent => :destroy
- has_many :crises, :through => :analyses
-end
-class Dress < ActiveRecord::Base
- belongs_to :crisis
- has_many :compresses
-end
-class Compress < ActiveRecord::Base
- belongs_to :dress
-end
-
class EagerSingularizationTest < ActiveRecord::TestCase
+ class Virus < ActiveRecord::Base
+ belongs_to :octopus
+ end
+
+ class Octopus < ActiveRecord::Base
+ has_one :virus
+ end
+
+ class Pass < ActiveRecord::Base
+ belongs_to :bus
+ end
+
+ class Bus < ActiveRecord::Base
+ has_many :passes
+ end
+
+ class Mess < ActiveRecord::Base
+ has_and_belongs_to_many :crises
+ end
+
+ class Crisis < ActiveRecord::Base
+ has_and_belongs_to_many :messes
+ has_many :analyses, :dependent => :destroy
+ has_many :successes, :through => :analyses
+ has_many :dresses, :dependent => :destroy
+ has_many :compresses, :through => :dresses
+ end
+
+ class Analysis < ActiveRecord::Base
+ belongs_to :crisis
+ belongs_to :success
+ end
+
+ class Success < ActiveRecord::Base
+ has_many :analyses, :dependent => :destroy
+ has_many :crises, :through => :analyses
+ end
+
+ class Dress < ActiveRecord::Base
+ belongs_to :crisis
+ has_many :compresses
+ end
+
+ class Compress < ActiveRecord::Base
+ belongs_to :dress
+ end
def setup
- if ActiveRecord::Base.connection.supports_migrations?
- ActiveRecord::Base.connection.create_table :viri do |t|
- t.column :octopus_id, :integer
- t.column :species, :string
- end
- ActiveRecord::Base.connection.create_table :octopi do |t|
- t.column :species, :string
- end
- ActiveRecord::Base.connection.create_table :passes do |t|
- t.column :bus_id, :integer
- t.column :rides, :integer
- end
- ActiveRecord::Base.connection.create_table :buses do |t|
- t.column :name, :string
- end
- ActiveRecord::Base.connection.create_table :crises_messes, :id => false do |t|
- t.column :crisis_id, :integer
- t.column :mess_id, :integer
- end
- ActiveRecord::Base.connection.create_table :messes do |t|
- t.column :name, :string
- end
- ActiveRecord::Base.connection.create_table :crises do |t|
- t.column :name, :string
- end
- ActiveRecord::Base.connection.create_table :successes do |t|
- t.column :name, :string
- end
- ActiveRecord::Base.connection.create_table :analyses do |t|
- t.column :crisis_id, :integer
- t.column :success_id, :integer
- end
- ActiveRecord::Base.connection.create_table :dresses do |t|
- t.column :crisis_id, :integer
- end
- ActiveRecord::Base.connection.create_table :compresses do |t|
- t.column :dress_id, :integer
- end
- @have_tables = true
- else
- @have_tables = false
+ skip 'Does not support migrations' unless connection.supports_migrations?
+
+ connection.create_table :viri do |t|
+ t.column :octopus_id, :integer
+ t.column :species, :string
+ end
+ connection.create_table :octopi do |t|
+ t.column :species, :string
+ end
+ connection.create_table :passes do |t|
+ t.column :bus_id, :integer
+ t.column :rides, :integer
+ end
+ connection.create_table :buses do |t|
+ t.column :name, :string
+ end
+ connection.create_table :crises_messes, :id => false do |t|
+ t.column :crisis_id, :integer
+ t.column :mess_id, :integer
+ end
+ connection.create_table :messes do |t|
+ t.column :name, :string
+ end
+ connection.create_table :crises do |t|
+ t.column :name, :string
+ end
+ connection.create_table :successes do |t|
+ t.column :name, :string
+ end
+ connection.create_table :analyses do |t|
+ t.column :crisis_id, :integer
+ t.column :success_id, :integer
+ end
+ connection.create_table :dresses do |t|
+ t.column :crisis_id, :integer
+ end
+ connection.create_table :compresses do |t|
+ t.column :dress_id, :integer
end
end
def teardown
- ActiveRecord::Base.connection.drop_table :viri
- ActiveRecord::Base.connection.drop_table :octopi
- ActiveRecord::Base.connection.drop_table :passes
- ActiveRecord::Base.connection.drop_table :buses
- ActiveRecord::Base.connection.drop_table :crises_messes
- ActiveRecord::Base.connection.drop_table :messes
- ActiveRecord::Base.connection.drop_table :crises
- ActiveRecord::Base.connection.drop_table :successes
- ActiveRecord::Base.connection.drop_table :analyses
- ActiveRecord::Base.connection.drop_table :dresses
- ActiveRecord::Base.connection.drop_table :compresses
+ connection.drop_table :viri
+ connection.drop_table :octopi
+ connection.drop_table :passes
+ connection.drop_table :buses
+ connection.drop_table :crises_messes
+ connection.drop_table :messes
+ connection.drop_table :crises
+ connection.drop_table :successes
+ connection.drop_table :analyses
+ connection.drop_table :dresses
+ connection.drop_table :compresses
+ end
+
+ def connection
+ ActiveRecord::Base.connection
end
def test_eager_no_extra_singularization_belongs_to
- return unless @have_tables
assert_nothing_raised do
Virus.all.merge!(:includes => :octopus).to_a
end
end
def test_eager_no_extra_singularization_has_one
- return unless @have_tables
assert_nothing_raised do
Octopus.all.merge!(:includes => :virus).to_a
end
end
def test_eager_no_extra_singularization_has_many
- return unless @have_tables
assert_nothing_raised do
Bus.all.merge!(:includes => :passes).to_a
end
end
def test_eager_no_extra_singularization_has_and_belongs_to_many
- return unless @have_tables
assert_nothing_raised do
Crisis.all.merge!(:includes => :messes).to_a
Mess.all.merge!(:includes => :crises).to_a
@@ -130,14 +135,12 @@ class EagerSingularizationTest < ActiveRecord::TestCase
end
def test_eager_no_extra_singularization_has_many_through_belongs_to
- return unless @have_tables
assert_nothing_raised do
Crisis.all.merge!(:includes => :successes).to_a
end
end
def test_eager_no_extra_singularization_has_many_through_has_many
- return unless @have_tables
assert_nothing_raised do
Crisis.all.merge!(:includes => :compresses).to_a
end
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index e45efb0161..a86fb15719 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -216,6 +216,31 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
end
assert_no_queries do
+ bulbs.second()
+ bulbs.second({})
+ end
+
+ assert_no_queries do
+ bulbs.third()
+ bulbs.third({})
+ end
+
+ assert_no_queries do
+ bulbs.fourth()
+ bulbs.fourth({})
+ end
+
+ assert_no_queries do
+ bulbs.fifth()
+ bulbs.fifth({})
+ end
+
+ assert_no_queries do
+ bulbs.forty_two()
+ bulbs.forty_two({})
+ end
+
+ assert_no_queries do
bulbs.last()
bulbs.last({})
end
@@ -242,11 +267,11 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
# sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first
def test_counting_with_counter_sql
- assert_equal 2, Firm.all.merge!(:order => "id").first.clients.count
+ assert_equal 3, Firm.all.merge!(:order => "id").first.clients.count
end
def test_counting
- assert_equal 2, Firm.all.merge!(:order => "id").first.plain_clients.count
+ assert_equal 3, Firm.all.merge!(:order => "id").first.plain_clients.count
end
def test_counting_with_single_hash
@@ -254,7 +279,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
end
def test_counting_with_column_name_and_hash
- assert_equal 2, Firm.all.merge!(:order => "id").first.plain_clients.count(:name)
+ assert_equal 3, Firm.all.merge!(:order => "id").first.plain_clients.count(:name)
end
def test_counting_with_association_limit
@@ -264,17 +289,17 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
end
def test_finding
- assert_equal 2, Firm.all.merge!(:order => "id").first.clients.length
+ assert_equal 3, Firm.all.merge!(:order => "id").first.clients.length
end
def test_finding_array_compatibility
- assert_equal 2, Firm.order(:id).find{|f| f.id > 0}.clients.length
+ assert_equal 3, Firm.order(:id).find{|f| f.id > 0}.clients.length
end
def test_find_many_with_merged_options
assert_equal 1, companies(:first_firm).limited_clients.size
assert_equal 1, companies(:first_firm).limited_clients.to_a.size
- assert_equal 2, companies(:first_firm).limited_clients.limit(nil).to_a.size
+ assert_equal 3, companies(:first_firm).limited_clients.limit(nil).to_a.size
end
def test_find_should_append_to_association_order
@@ -283,8 +308,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
end
def test_dynamic_find_should_respect_association_order
- assert_equal companies(:second_client), companies(:first_firm).clients_sorted_desc.where("type = 'Client'").first
- assert_equal companies(:second_client), companies(:first_firm).clients_sorted_desc.find_by_type('Client')
+ assert_equal companies(:another_first_firm_client), companies(:first_firm).clients_sorted_desc.where("type = 'Client'").first
+ assert_equal companies(:another_first_firm_client), companies(:first_firm).clients_sorted_desc.find_by_type('Client')
end
def test_cant_save_has_many_readonly_association
@@ -297,7 +322,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
end
def test_finding_with_different_class_name_and_order
- assert_equal "Microsoft", Firm.all.merge!(:order => "id").first.clients_sorted_desc.first.name
+ assert_equal "Apex", Firm.all.merge!(:order => "id").first.clients_sorted_desc.first.name
end
def test_finding_with_foreign_key
@@ -355,7 +380,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
def test_find_all
firm = Firm.all.merge!(:order => "id").first
- assert_equal 2, firm.clients.where("#{QUOTED_TYPE} = 'Client'").to_a.length
+ assert_equal 3, firm.clients.where("#{QUOTED_TYPE} = 'Client'").to_a.length
assert_equal 1, firm.clients.where("name = 'Summit'").to_a.length
end
@@ -364,7 +389,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert ! firm.clients.loaded?
- assert_queries(3) do
+ assert_queries(4) do
firm.clients.find_each(:batch_size => 1) {|c| assert_equal firm.id, c.firm_id }
end
@@ -434,15 +459,15 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
def test_find_grouped
all_clients_of_firm1 = Client.all.merge!(:where => "firm_id = 1").to_a
grouped_clients_of_firm1 = Client.all.merge!(:where => "firm_id = 1", :group => "firm_id", :select => 'firm_id, count(id) as clients_count').to_a
- assert_equal 2, all_clients_of_firm1.size
+ assert_equal 3, all_clients_of_firm1.size
assert_equal 1, grouped_clients_of_firm1.size
end
def test_find_scoped_grouped
assert_equal 1, companies(:first_firm).clients_grouped_by_firm_id.size
assert_equal 1, companies(:first_firm).clients_grouped_by_firm_id.length
- assert_equal 2, companies(:first_firm).clients_grouped_by_name.size
- assert_equal 2, companies(:first_firm).clients_grouped_by_name.length
+ assert_equal 3, companies(:first_firm).clients_grouped_by_name.size
+ assert_equal 3, companies(:first_firm).clients_grouped_by_name.length
end
def test_find_scoped_grouped_having
@@ -462,25 +487,25 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_equal [1], posts(:welcome).comments.select { |c| c.id == 1 }.map(&:id)
end
- def test_select_without_foreign_key
+ def test_select_without_foreign_key
assert_equal companies(:first_firm).accounts.first.credit_limit, companies(:first_firm).accounts.select(:credit_limit).first.credit_limit
- end
+ end
def test_adding
force_signal37_to_load_all_clients_of_firm
natural = Client.new("name" => "Natural Company")
companies(:first_firm).clients_of_firm << natural
- assert_equal 2, companies(:first_firm).clients_of_firm.size # checking via the collection
- assert_equal 2, companies(:first_firm).clients_of_firm(true).size # checking using the db
+ assert_equal 3, companies(:first_firm).clients_of_firm.size # checking via the collection
+ assert_equal 3, companies(:first_firm).clients_of_firm(true).size # checking using the db
assert_equal natural, companies(:first_firm).clients_of_firm.last
end
def test_adding_using_create
first_firm = companies(:first_firm)
- assert_equal 2, first_firm.plain_clients.size
- first_firm.plain_clients.create(:name => "Natural Company")
- assert_equal 3, first_firm.plain_clients.length
assert_equal 3, first_firm.plain_clients.size
+ first_firm.plain_clients.create(:name => "Natural Company")
+ assert_equal 4, first_firm.plain_clients.length
+ assert_equal 4, first_firm.plain_clients.size
end
def test_create_with_bang_on_has_many_when_parent_is_new_raises
@@ -519,8 +544,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
def test_adding_a_collection
force_signal37_to_load_all_clients_of_firm
companies(:first_firm).clients_of_firm.concat([Client.new("name" => "Natural Company"), Client.new("name" => "Apple")])
- assert_equal 3, companies(:first_firm).clients_of_firm.size
- assert_equal 3, companies(:first_firm).clients_of_firm(true).size
+ assert_equal 4, companies(:first_firm).clients_of_firm.size
+ assert_equal 4, companies(:first_firm).clients_of_firm(true).size
end
def test_transactions_when_adding_to_persisted
@@ -573,7 +598,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
company = companies(:first_firm) # company already has one client
company.clients_of_firm.build("name" => "Another Client")
company.clients_of_firm.build("name" => "Yet Another Client")
- assert_equal 3, company.clients_of_firm.size
+ assert_equal 4, company.clients_of_firm.size
end
def test_collection_not_empty_after_building
@@ -649,14 +674,14 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
Firm.column_names
Client.column_names
- assert_equal 1, first_firm.clients_of_firm.size
+ assert_equal 2, first_firm.clients_of_firm.size
first_firm.clients_of_firm.reset
assert_queries(1) do
first_firm.clients_of_firm.create(:name => "Superstars")
end
- assert_equal 2, first_firm.clients_of_firm.size
+ assert_equal 3, first_firm.clients_of_firm.size
end
def test_create
@@ -669,7 +694,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
def test_create_many
companies(:first_firm).clients_of_firm.create([{"name" => "Another Client"}, {"name" => "Another Client II"}])
- assert_equal 3, companies(:first_firm).clients_of_firm(true).size
+ assert_equal 4, companies(:first_firm).clients_of_firm(true).size
end
def test_create_followed_by_save_does_not_load_target
@@ -681,8 +706,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
def test_deleting
force_signal37_to_load_all_clients_of_firm
companies(:first_firm).clients_of_firm.delete(companies(:first_firm).clients_of_firm.first)
- assert_equal 0, companies(:first_firm).clients_of_firm.size
- assert_equal 0, companies(:first_firm).clients_of_firm(true).size
+ assert_equal 1, companies(:first_firm).clients_of_firm.size
+ assert_equal 1, companies(:first_firm).clients_of_firm(true).size
end
def test_deleting_before_save
@@ -779,8 +804,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
def test_deleting_a_collection
force_signal37_to_load_all_clients_of_firm
companies(:first_firm).clients_of_firm.create("name" => "Another Client")
- assert_equal 2, companies(:first_firm).clients_of_firm.size
- companies(:first_firm).clients_of_firm.delete([companies(:first_firm).clients_of_firm[0], companies(:first_firm).clients_of_firm[1]])
+ assert_equal 3, companies(:first_firm).clients_of_firm.size
+ companies(:first_firm).clients_of_firm.delete([companies(:first_firm).clients_of_firm[0], companies(:first_firm).clients_of_firm[1], companies(:first_firm).clients_of_firm[2]])
assert_equal 0, companies(:first_firm).clients_of_firm.size
assert_equal 0, companies(:first_firm).clients_of_firm(true).size
end
@@ -789,7 +814,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
force_signal37_to_load_all_clients_of_firm
companies(:first_firm).dependent_clients_of_firm.create("name" => "Another Client")
clients = companies(:first_firm).dependent_clients_of_firm.to_a
- assert_equal 2, clients.count
+ assert_equal 3, clients.count
assert_difference "Client.count", -(clients.count) do
companies(:first_firm).dependent_clients_of_firm.delete_all
@@ -799,7 +824,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
def test_delete_all_with_not_yet_loaded_association_collection
force_signal37_to_load_all_clients_of_firm
companies(:first_firm).clients_of_firm.create("name" => "Another Client")
- assert_equal 2, companies(:first_firm).clients_of_firm.size
+ assert_equal 3, companies(:first_firm).clients_of_firm.size
companies(:first_firm).clients_of_firm.reset
companies(:first_firm).clients_of_firm.delete_all
assert_equal 0, companies(:first_firm).clients_of_firm.size
@@ -832,7 +857,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
def test_clearing_an_association_collection
firm = companies(:first_firm)
client_id = firm.clients_of_firm.first.id
- assert_equal 1, firm.clients_of_firm.size
+ assert_equal 2, firm.clients_of_firm.size
firm.clients_of_firm.clear
@@ -866,7 +891,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
def test_clearing_a_dependent_association_collection
firm = companies(:first_firm)
client_id = firm.dependent_clients_of_firm.first.id
- assert_equal 1, firm.dependent_clients_of_firm.size
+ assert_equal 2, firm.dependent_clients_of_firm.size
assert_equal 1, Client.find_by_id(client_id).client_of
# :delete_all is called on each client since the dependent options is :destroy
@@ -897,7 +922,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
def test_clearing_an_exclusively_dependent_association_collection
firm = companies(:first_firm)
client_id = firm.exclusively_dependent_clients_of_firm.first.id
- assert_equal 1, firm.exclusively_dependent_clients_of_firm.size
+ assert_equal 2, firm.exclusively_dependent_clients_of_firm.size
assert_equal [], Client.destroyed_client_ids[firm.id]
@@ -953,10 +978,10 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
def test_delete_all_association_with_primary_key_deletes_correct_records
firm = Firm.first
# break the vanilla firm_id foreign key
- assert_equal 2, firm.clients.count
+ assert_equal 3, firm.clients.count
firm.clients.first.update_columns(firm_id: nil)
- assert_equal 1, firm.clients(true).count
- assert_equal 1, firm.clients_using_primary_key_with_delete_all.count
+ assert_equal 2, firm.clients(true).count
+ assert_equal 2, firm.clients_using_primary_key_with_delete_all.count
old_record = firm.clients_using_primary_key_with_delete_all.first
firm = Firm.first
firm.destroy
@@ -988,8 +1013,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
force_signal37_to_load_all_clients_of_firm
summit = Client.find_by_name('Summit')
companies(:first_firm).clients_of_firm.delete(summit)
- assert_equal 1, companies(:first_firm).clients_of_firm.size
- assert_equal 1, companies(:first_firm).clients_of_firm(true).size
+ assert_equal 2, companies(:first_firm).clients_of_firm.size
+ assert_equal 2, companies(:first_firm).clients_of_firm(true).size
assert_equal 2, summit.client_of
end
@@ -1026,8 +1051,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
companies(:first_firm).clients_of_firm.destroy(companies(:first_firm).clients_of_firm.first)
end
- assert_equal 0, companies(:first_firm).reload.clients_of_firm.size
- assert_equal 0, companies(:first_firm).clients_of_firm(true).size
+ assert_equal 1, companies(:first_firm).reload.clients_of_firm.size
+ assert_equal 1, companies(:first_firm).clients_of_firm(true).size
end
def test_destroying_by_fixnum_id
@@ -1037,8 +1062,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
companies(:first_firm).clients_of_firm.destroy(companies(:first_firm).clients_of_firm.first.id)
end
- assert_equal 0, companies(:first_firm).reload.clients_of_firm.size
- assert_equal 0, companies(:first_firm).clients_of_firm(true).size
+ assert_equal 1, companies(:first_firm).reload.clients_of_firm.size
+ assert_equal 1, companies(:first_firm).clients_of_firm(true).size
end
def test_destroying_by_string_id
@@ -1048,21 +1073,21 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
companies(:first_firm).clients_of_firm.destroy(companies(:first_firm).clients_of_firm.first.id.to_s)
end
- assert_equal 0, companies(:first_firm).reload.clients_of_firm.size
- assert_equal 0, companies(:first_firm).clients_of_firm(true).size
+ assert_equal 1, companies(:first_firm).reload.clients_of_firm.size
+ assert_equal 1, companies(:first_firm).clients_of_firm(true).size
end
def test_destroying_a_collection
force_signal37_to_load_all_clients_of_firm
companies(:first_firm).clients_of_firm.create("name" => "Another Client")
- assert_equal 2, companies(:first_firm).clients_of_firm.size
+ assert_equal 3, companies(:first_firm).clients_of_firm.size
assert_difference "Client.count", -2 do
companies(:first_firm).clients_of_firm.destroy([companies(:first_firm).clients_of_firm[0], companies(:first_firm).clients_of_firm[1]])
end
- assert_equal 0, companies(:first_firm).reload.clients_of_firm.size
- assert_equal 0, companies(:first_firm).clients_of_firm(true).size
+ assert_equal 1, companies(:first_firm).reload.clients_of_firm.size
+ assert_equal 1, companies(:first_firm).clients_of_firm(true).size
end
def test_destroy_all
@@ -1078,7 +1103,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
def test_dependence
firm = companies(:first_firm)
- assert_equal 2, firm.clients.size
+ assert_equal 3, firm.clients.size
firm.destroy
assert Client.all.merge!(:where => "firm_id=#{firm.id}").to_a.empty?
end
@@ -1091,14 +1116,14 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
def test_destroy_dependent_when_deleted_from_association
# sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first
firm = Firm.all.merge!(:order => "id").first
- assert_equal 2, firm.clients.size
+ assert_equal 3, firm.clients.size
client = firm.clients.first
firm.clients.delete(client)
assert_raise(ActiveRecord::RecordNotFound) { Client.find(client.id) }
assert_raise(ActiveRecord::RecordNotFound) { firm.clients.find(client.id) }
- assert_equal 1, firm.clients.size
+ assert_equal 2, firm.clients.size
end
def test_three_levels_of_dependence
@@ -1113,12 +1138,12 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
def test_dependence_with_transaction_support_on_failure
firm = companies(:first_firm)
clients = firm.clients
- assert_equal 2, clients.length
+ assert_equal 3, clients.length
clients.last.instance_eval { def overwrite_to_raise() raise "Trigger rollback" end }
firm.destroy rescue "do nothing"
- assert_equal 2, Client.all.merge!(:where => "firm_id=#{firm.id}").to_a.size
+ assert_equal 3, Client.all.merge!(:where => "firm_id=#{firm.id}").to_a.size
end
def test_dependence_on_account
@@ -1239,7 +1264,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
end
def test_get_ids
- assert_equal [companies(:first_client).id, companies(:second_client).id], companies(:first_firm).client_ids
+ assert_equal [companies(:first_client).id, companies(:second_client).id, companies(:another_first_firm_client).id], companies(:first_firm).client_ids
end
def test_get_ids_for_loaded_associations
@@ -1254,7 +1279,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
def test_get_ids_for_unloaded_associations_does_not_load_them
company = companies(:first_firm)
assert !company.clients.loaded?
- assert_equal [companies(:first_client).id, companies(:second_client).id], company.client_ids
+ assert_equal [companies(:first_client).id, companies(:second_client).id, companies(:another_first_firm_client).id], company.client_ids
assert !company.clients.loaded?
end
@@ -1263,7 +1288,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
end
def test_get_ids_for_ordered_association
- assert_equal [companies(:second_client).id, companies(:first_client).id], companies(:first_firm).clients_ordered_by_name_ids
+ assert_equal [companies(:another_first_firm_client).id, companies(:second_client).id, companies(:first_client).id], companies(:first_firm).clients_ordered_by_name_ids
end
def test_get_ids_for_association_on_new_record_does_not_try_to_find_records
@@ -1357,9 +1382,10 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_equal false, firm.clients.include?(client)
end
- def test_calling_first_or_last_on_association_should_not_load_association
+ def test_calling_first_nth_or_last_on_association_should_not_load_association
firm = companies(:first_firm)
firm.clients.first
+ firm.clients.second
firm.clients.last
assert !firm.clients.loaded?
end
@@ -1384,30 +1410,33 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_queries 1 do
firm.clients.first
+ firm.clients.second
firm.clients.last
end
assert firm.clients.loaded?
end
- def test_calling_first_or_last_on_existing_record_with_create_should_not_load_association
+ def test_calling_first_nth_or_last_on_existing_record_with_create_should_not_load_association
firm = companies(:first_firm)
firm.clients.create(:name => 'Foo')
assert !firm.clients.loaded?
- assert_queries 2 do
+ assert_queries 3 do
firm.clients.first
+ firm.clients.second
firm.clients.last
end
assert !firm.clients.loaded?
end
- def test_calling_first_or_last_on_new_record_should_not_run_queries
+ def test_calling_first_nth_or_last_on_new_record_should_not_run_queries
firm = Firm.new
assert_no_queries do
firm.clients.first
+ firm.clients.second
firm.clients.last
end
end
@@ -1494,7 +1523,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
def test_calling_many_should_return_true_if_more_than_one
firm = companies(:first_firm)
assert firm.clients.many?
- assert_equal 2, firm.clients.size
+ assert_equal 3, firm.clients.size
end
def test_joins_with_namespaced_model_should_use_correct_type
@@ -1791,4 +1820,14 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
topic.approved_replies.create!
end
end
+
+ test 'dangerous association name raises ArgumentError' do
+ [:errors, 'errors', :save, 'save'].each do |name|
+ assert_raises(ArgumentError, "Association #{name} should not be allowed") do
+ Class.new(ActiveRecord::Base) do
+ has_many name
+ end
+ end
+ end
+ end
end
diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb
index 5a41461edf..a4650ccdf2 100644
--- a/activerecord/test/cases/associations/has_one_associations_test.rb
+++ b/activerecord/test/cases/associations/has_one_associations_test.rb
@@ -22,6 +22,13 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
assert_equal Account.find(1).credit_limit, companies(:first_firm).account.credit_limit
end
+ def test_has_one_does_not_use_order_by
+ ActiveRecord::SQLCounter.clear_log
+ companies(:first_firm).account
+ ensure
+ assert ActiveRecord::SQLCounter.log_all.all? { |sql| /order by/i !~ sql }, 'ORDER BY was used in the query'
+ end
+
def test_has_one_cache_nils
firm = companies(:another_firm)
assert_queries(1) { assert_nil firm.account }
@@ -557,4 +564,14 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
end
end
end
+
+ test 'dangerous association name raises ArgumentError' do
+ [:errors, 'errors', :save, 'save'].each do |name|
+ assert_raises(ArgumentError, "Association #{name} should not be allowed") do
+ Class.new(ActiveRecord::Base) do
+ has_one name
+ end
+ end
+ end
+ end
end
diff --git a/activerecord/test/cases/associations_test.rb b/activerecord/test/cases/associations_test.rb
index 48e6fc5cd4..f663b5490c 100644
--- a/activerecord/test/cases/associations_test.rb
+++ b/activerecord/test/cases/associations_test.rb
@@ -255,6 +255,15 @@ class AssociationProxyTest < ActiveRecord::TestCase
assert_equal man, man.interests.where("1=1").first.man
end
end
+
+ def test_reset_unloads_target
+ david = authors(:david)
+ david.posts.reload
+
+ assert david.posts.loaded?
+ david.posts.reset
+ assert !david.posts.loaded?
+ end
end
class OverridingAssociationsTest < ActiveRecord::TestCase
diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb
index 517d2674a7..703f805188 100644
--- a/activerecord/test/cases/autosave_association_test.rb
+++ b/activerecord/test/cases/autosave_association_test.rb
@@ -401,7 +401,7 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCa
assert_equal new_client, companies(:first_firm).clients_of_firm.last
assert !companies(:first_firm).save
assert !new_client.persisted?
- assert_equal 1, companies(:first_firm).clients_of_firm(true).size
+ assert_equal 2, companies(:first_firm).clients_of_firm(true).size
end
def test_adding_before_save
@@ -455,7 +455,7 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCa
company.name += '-changed'
assert_queries(2) { assert company.save }
assert new_client.persisted?
- assert_equal 2, company.clients_of_firm(true).size
+ assert_equal 3, company.clients_of_firm(true).size
end
def test_build_many_before_save
@@ -464,7 +464,7 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCa
company.name += '-changed'
assert_queries(3) { assert company.save }
- assert_equal 3, company.clients_of_firm(true).size
+ assert_equal 4, company.clients_of_firm(true).size
end
def test_build_via_block_before_save
@@ -475,7 +475,7 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCa
company.name += '-changed'
assert_queries(2) { assert company.save }
assert new_client.persisted?
- assert_equal 2, company.clients_of_firm(true).size
+ assert_equal 3, company.clients_of_firm(true).size
end
def test_build_many_via_block_before_save
@@ -488,7 +488,7 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCa
company.name += '-changed'
assert_queries(3) { assert company.save }
- assert_equal 3, company.clients_of_firm(true).size
+ assert_equal 4, company.clients_of_firm(true).size
end
def test_replace_on_new_object
@@ -574,6 +574,13 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase
@ship = @pirate.create_ship(:name => 'Nights Dirty Lightning')
end
+ def teardown
+ # We are running without transactional fixtures and need to cleanup.
+ Bird.delete_all
+ @ship.delete
+ @pirate.delete
+ end
+
# reload
def test_a_marked_for_destruction_record_should_not_be_be_marked_after_reload
@pirate.mark_for_destruction
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index cb8e564da1..8a0b0b9589 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -321,7 +321,7 @@ class BasicsTest < ActiveRecord::TestCase
def test_load
topics = Topic.all.merge!(:order => 'id').to_a
- assert_equal(4, topics.size)
+ assert_equal(5, topics.size)
assert_equal(topics(:first).title, topics.first.title)
end
@@ -626,6 +626,7 @@ class BasicsTest < ActiveRecord::TestCase
assert_equal ["EUC-JP"], Weird.columns.map {|c| c.name.encoding.name }.uniq
ensure
silence_warnings { Encoding.default_internal = old_default_internal }
+ Weird.reset_column_information
end
end
@@ -1129,7 +1130,7 @@ class BasicsTest < ActiveRecord::TestCase
k = Class.new(ak)
k.table_name = "projects"
orig_name = k.sequence_name
- return skip "sequences not supported by db" unless orig_name
+ skip "sequences not supported by db" unless orig_name
assert_equal k.reset_sequence_name, orig_name
end
@@ -1301,9 +1302,11 @@ class BasicsTest < ActiveRecord::TestCase
end
def test_compute_type_nonexistent_constant
- assert_raises NameError do
+ e = assert_raises NameError do
ActiveRecord::Base.send :compute_type, 'NonexistentModel'
end
+ assert_equal 'uninitialized constant ActiveRecord::Base::NonexistentModel', e.message
+ assert_equal 'ActiveRecord::Base::NonexistentModel', e.name
end
def test_compute_type_no_method_error
@@ -1377,6 +1380,8 @@ class BasicsTest < ActiveRecord::TestCase
})
rd, wr = IO.pipe
+ rd.binmode
+ wr.binmode
ActiveRecord::Base.connection_handler.clear_all_connections!
diff --git a/activerecord/test/cases/batches_test.rb b/activerecord/test/cases/batches_test.rb
index 38c2560d69..8216d74cb3 100644
--- a/activerecord/test/cases/batches_test.rb
+++ b/activerecord/test/cases/batches_test.rb
@@ -46,7 +46,9 @@ class EachTest < ActiveRecord::TestCase
def test_each_should_raise_if_select_is_set_without_id
assert_raise(RuntimeError) do
- Post.select(:title).find_each(:batch_size => 1) { |post| post }
+ Post.select(:title).find_each(batch_size: 1) { |post|
+ flunk "should not call this block"
+ }
end
end
@@ -151,6 +153,12 @@ class EachTest < ActiveRecord::TestCase
assert_equal special_posts_ids, posts.map(&:id)
end
+ def test_find_in_batches_should_not_modify_passed_options
+ assert_nothing_raised do
+ Post.find_in_batches({ batch_size: 42, start: 1 }.freeze){}
+ end
+ end
+
def test_find_in_batches_should_use_any_column_as_primary_key
nick_order_subscribers = Subscriber.order('nick asc')
start_nick = nick_order_subscribers.second.nick
@@ -170,4 +178,17 @@ class EachTest < ActiveRecord::TestCase
end
end
end
+
+ def test_find_in_batches_should_return_an_enumerator
+ enum = nil
+ assert_queries(0) do
+ enum = Post.find_in_batches(:batch_size => 1)
+ end
+ assert_queries(4) do
+ enum.first(4) do |batch|
+ assert_kind_of Array, batch
+ assert_kind_of Post, batch.first
+ end
+ end
+ end
end
diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb
index 2f6913167d..db999f90ab 100644
--- a/activerecord/test/cases/calculations_test.rb
+++ b/activerecord/test/cases/calculations_test.rb
@@ -278,7 +278,7 @@ class CalculationsTest < ActiveRecord::TestCase
c = Company.group("UPPER(#{QUOTED_TYPE})").count(:all)
assert_equal 2, c[nil]
assert_equal 1, c['DEPENDENTFIRM']
- assert_equal 4, c['CLIENT']
+ assert_equal 5, c['CLIENT']
assert_equal 2, c['FIRM']
end
@@ -286,7 +286,7 @@ class CalculationsTest < ActiveRecord::TestCase
c = Company.group("UPPER(companies.#{QUOTED_TYPE})").count(:all)
assert_equal 2, c[nil]
assert_equal 1, c['DEPENDENTFIRM']
- assert_equal 4, c['CLIENT']
+ assert_equal 5, c['CLIENT']
assert_equal 2, c['FIRM']
end
@@ -466,14 +466,14 @@ class CalculationsTest < ActiveRecord::TestCase
def test_distinct_is_honored_when_used_with_count_operation_after_group
# Count the number of authors for approved topics
approved_topics_count = Topic.group(:approved).count(:author_name)[true]
- assert_equal approved_topics_count, 3
+ assert_equal approved_topics_count, 4
# Count the number of distinct authors for approved Topics
distinct_authors_for_approved_count = Topic.group(:approved).distinct.count(:author_name)[true]
- assert_equal distinct_authors_for_approved_count, 2
+ assert_equal distinct_authors_for_approved_count, 3
end
def test_pluck
- assert_equal [1,2,3,4], Topic.order(:id).pluck(:id)
+ assert_equal [1,2,3,4,5], Topic.order(:id).pluck(:id)
end
def test_pluck_without_column_names
@@ -509,7 +509,7 @@ class CalculationsTest < ActiveRecord::TestCase
end
def test_pluck_with_qualified_column_name
- assert_equal [1,2,3,4], Topic.order(:id).pluck("topics.id")
+ assert_equal [1,2,3,4,5], Topic.order(:id).pluck("topics.id")
end
def test_pluck_auto_table_name_prefix
@@ -557,11 +557,13 @@ class CalculationsTest < ActiveRecord::TestCase
def test_pluck_multiple_columns
assert_equal [
[1, "The First Topic"], [2, "The Second Topic of the day"],
- [3, "The Third Topic of the day"], [4, "The Fourth Topic of the day"]
+ [3, "The Third Topic of the day"], [4, "The Fourth Topic of the day"],
+ [5, "The Fifth Topic of the day"]
], Topic.order(:id).pluck(:id, :title)
assert_equal [
[1, "The First Topic", "David"], [2, "The Second Topic of the day", "Mary"],
- [3, "The Third Topic of the day", "Carl"], [4, "The Fourth Topic of the day", "Carl"]
+ [3, "The Third Topic of the day", "Carl"], [4, "The Fourth Topic of the day", "Carl"],
+ [5, "The Fifth Topic of the day", "Jason"]
], Topic.order(:id).pluck(:id, :title, :author_name)
end
@@ -587,7 +589,7 @@ class CalculationsTest < ActiveRecord::TestCase
def test_pluck_replaces_select_clause
taks_relation = Topic.select(:approved, :id).order(:id)
- assert_equal [1,2,3,4], taks_relation.pluck(:id)
- assert_equal [false, true, true, true], taks_relation.pluck(:approved)
+ assert_equal [1,2,3,4,5], taks_relation.pluck(:id)
+ assert_equal [false, true, true, true, true], taks_relation.pluck(:approved)
end
end
diff --git a/activerecord/test/cases/connection_management_test.rb b/activerecord/test/cases/connection_management_test.rb
index 00667cc52e..77d9ae9b8e 100644
--- a/activerecord/test/cases/connection_management_test.rb
+++ b/activerecord/test/cases/connection_management_test.rb
@@ -31,6 +31,8 @@ module ActiveRecord
object_id = ActiveRecord::Base.connection.object_id
rd, wr = IO.pipe
+ rd.binmode
+ wr.binmode
pid = fork {
rd.close
diff --git a/activerecord/test/cases/enum_test.rb b/activerecord/test/cases/enum_test.rb
index c09e58fbf1..1b95708cb3 100644
--- a/activerecord/test/cases/enum_test.rb
+++ b/activerecord/test/cases/enum_test.rb
@@ -51,6 +51,77 @@ class EnumTest < ActiveRecord::TestCase
assert @book.written?
end
+ test "enum changed attributes" do
+ old_status = @book.status
+ @book.status = :published
+ assert_equal old_status, @book.changed_attributes[:status]
+ end
+
+ test "enum changes" do
+ old_status = @book.status
+ @book.status = :published
+ assert_equal [old_status, 'published'], @book.changes[:status]
+ end
+
+ test "enum attribute was" do
+ old_status = @book.status
+ @book.status = :published
+ assert_equal old_status, @book.attribute_was(:status)
+ end
+
+ test "enum attribute changed" do
+ @book.status = :published
+ assert @book.attribute_changed?(:status)
+ end
+
+ test "enum attribute changed to" do
+ @book.status = :published
+ assert @book.attribute_changed?(:status, to: 'published')
+ end
+
+ test "enum attribute changed from" do
+ old_status = @book.status
+ @book.status = :published
+ assert @book.attribute_changed?(:status, from: old_status)
+ end
+
+ test "enum attribute changed from old status to new status" do
+ old_status = @book.status
+ @book.status = :published
+ assert @book.attribute_changed?(:status, from: old_status, to: 'published')
+ end
+
+ test "enum didn't change" do
+ old_status = @book.status
+ @book.status = old_status
+ assert_not @book.attribute_changed?(:status)
+ end
+
+ test "persist changes that are dirty" do
+ @book.status = :published
+ assert @book.attribute_changed?(:status)
+ @book.status = :written
+ assert @book.attribute_changed?(:status)
+ end
+
+ test "reverted changes that are not dirty" do
+ old_status = @book.status
+ @book.status = :published
+ assert @book.attribute_changed?(:status)
+ @book.status = old_status
+ assert_not @book.attribute_changed?(:status)
+ end
+
+ test "reverted changes are not dirty going from nil to value and back" do
+ book = Book.create!(nullable_status: nil)
+
+ book.nullable_status = :married
+ assert book.attribute_changed?(:nullable_status)
+
+ book.nullable_status = nil
+ assert_not book.attribute_changed?(:nullable_status)
+ end
+
test "assign non existing value raises an error" do
e = assert_raises(ArgumentError) do
@book.status = :unknown
@@ -74,9 +145,9 @@ class EnumTest < ActiveRecord::TestCase
end
test "constant to access the mapping" do
- assert_equal 0, Book::STATUS[:proposed]
- assert_equal 1, Book::STATUS["written"]
- assert_equal 2, Book::STATUS[:published]
+ assert_equal 0, Book.statuses[:proposed]
+ assert_equal 1, Book.statuses["written"]
+ assert_equal 2, Book.statuses[:published]
end
test "building new objects with enum scopes" do
@@ -88,4 +159,67 @@ class EnumTest < ActiveRecord::TestCase
assert Book.written.create.written?
assert Book.read.create.read?
end
+
+ test "_before_type_cast returns the enum label (required for form fields)" do
+ assert_equal "proposed", @book.status_before_type_cast
+ end
+
+ test "reserved enum names" do
+ klass = Class.new(ActiveRecord::Base) do
+ self.table_name = "books"
+ enum status: [:proposed, :written, :published]
+ end
+
+ conflicts = [
+ :column, # generates class method .columns, which conflicts with an AR method
+ :logger, # generates #logger, which conflicts with an AR method
+ :attributes, # generates #attributes=, which conflicts with an AR method
+ ]
+
+ conflicts.each_with_index do |name, i|
+ assert_raises(ArgumentError, "enum name `#{name}` should not be allowed") do
+ klass.class_eval { enum name => ["value_#{i}"] }
+ end
+ end
+ end
+
+ test "reserved enum values" do
+ klass = Class.new(ActiveRecord::Base) do
+ self.table_name = "books"
+ enum status: [:proposed, :written, :published]
+ end
+
+ conflicts = [
+ :new, # generates a scope that conflicts with an AR class method
+ :valid, # generates #valid?, which conflicts with an AR method
+ :save, # generates #save!, which conflicts with an AR method
+ :proposed, # same value as an existing enum
+ ]
+
+ conflicts.each_with_index do |value, i|
+ assert_raises(ArgumentError, "enum value `#{value}` should not be allowed") do
+ klass.class_eval { enum "status_#{i}" => [value] }
+ end
+ end
+ end
+
+ test "overriding enum method should not raise" do
+ assert_nothing_raised do
+ Class.new(ActiveRecord::Base) do
+ self.table_name = "books"
+
+ def published!
+ super
+ "do publish work..."
+ end
+
+ enum status: [:proposed, :written, :published]
+
+ def written!
+ super
+ "do written work..."
+ end
+ end
+ end
+ end
end
diff --git a/activerecord/test/cases/finder_respond_to_test.rb b/activerecord/test/cases/finder_respond_to_test.rb
index 3ff22f222f..6ab2657c44 100644
--- a/activerecord/test/cases/finder_respond_to_test.rb
+++ b/activerecord/test/cases/finder_respond_to_test.rb
@@ -5,6 +5,11 @@ class FinderRespondToTest < ActiveRecord::TestCase
fixtures :topics
+ def test_should_preserve_normal_respond_to_behaviour_on_base
+ assert_respond_to ActiveRecord::Base, :new
+ assert !ActiveRecord::Base.respond_to?(:find_by_something)
+ end
+
def test_should_preserve_normal_respond_to_behaviour_and_respond_to_newly_added_method
class << Topic; self; end.send(:define_method, :method_added_for_finder_respond_to_test) { }
assert_respond_to Topic, :method_added_for_finder_respond_to_test
diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb
index 5125d5df2a..b1eded6494 100644
--- a/activerecord/test/cases/finder_test.rb
+++ b/activerecord/test/cases/finder_test.rb
@@ -254,6 +254,94 @@ class FinderTest < ActiveRecord::TestCase
end
end
+ def test_second
+ assert_equal topics(:second).title, Topic.second.title
+ end
+
+ def test_second_with_offset
+ assert_equal topics(:fifth), Topic.offset(3).second
+ end
+
+ def test_second_have_primary_key_order_by_default
+ expected = topics(:second)
+ expected.touch # PostgreSQL changes the default order if no order clause is used
+ assert_equal expected, Topic.second
+ end
+
+ def test_model_class_responds_to_second_bang
+ assert Topic.second!
+ Topic.delete_all
+ assert_raises ActiveRecord::RecordNotFound do
+ Topic.second!
+ end
+ end
+
+ def test_third
+ assert_equal topics(:third).title, Topic.third.title
+ end
+
+ def test_third_with_offset
+ assert_equal topics(:fifth), Topic.offset(2).third
+ end
+
+ def test_third_have_primary_key_order_by_default
+ expected = topics(:third)
+ expected.touch # PostgreSQL changes the default order if no order clause is used
+ assert_equal expected, Topic.third
+ end
+
+ def test_model_class_responds_to_third_bang
+ assert Topic.third!
+ Topic.delete_all
+ assert_raises ActiveRecord::RecordNotFound do
+ Topic.third!
+ end
+ end
+
+ def test_fourth
+ assert_equal topics(:fourth).title, Topic.fourth.title
+ end
+
+ def test_fourth_with_offset
+ assert_equal topics(:fifth), Topic.offset(1).fourth
+ end
+
+ def test_fourth_have_primary_key_order_by_default
+ expected = topics(:fourth)
+ expected.touch # PostgreSQL changes the default order if no order clause is used
+ assert_equal expected, Topic.fourth
+ end
+
+ def test_model_class_responds_to_fourth_bang
+ assert Topic.fourth!
+ Topic.delete_all
+ assert_raises ActiveRecord::RecordNotFound do
+ Topic.fourth!
+ end
+ end
+
+ def test_fifth
+ assert_equal topics(:fifth).title, Topic.fifth.title
+ end
+
+ def test_fifth_with_offset
+ assert_equal topics(:fifth), Topic.offset(0).fifth
+ end
+
+ def test_fifth_have_primary_key_order_by_default
+ expected = topics(:fifth)
+ expected.touch # PostgreSQL changes the default order if no order clause is used
+ assert_equal expected, Topic.fifth
+ end
+
+ def test_model_class_responds_to_fifth_bang
+ assert Topic.fifth!
+ Topic.delete_all
+ assert_raises ActiveRecord::RecordNotFound do
+ Topic.fifth!
+ end
+ end
+
def test_last_bang_present
assert_nothing_raised do
assert_equal topics(:second), Topic.where("title = 'The Second Topic of the day'").last!
@@ -267,7 +355,7 @@ class FinderTest < ActiveRecord::TestCase
end
def test_model_class_responds_to_last_bang
- assert_equal topics(:fourth), Topic.last!
+ assert_equal topics(:fifth), Topic.last!
assert_raises ActiveRecord::RecordNotFound do
Topic.delete_all
Topic.last!
@@ -812,8 +900,8 @@ class FinderTest < ActiveRecord::TestCase
end
def test_select_values
- assert_equal ["1","2","3","4","5","6","7","8","9", "10"], Company.connection.select_values("SELECT id FROM companies ORDER BY id").map! { |i| i.to_s }
- assert_equal ["37signals","Summit","Microsoft", "Flamboyant Software", "Ex Nihilo", "RailsCore", "Leetsoft", "Jadedpixel", "Odegy", "Ex Nihilo Part Deux"], Company.connection.select_values("SELECT name FROM companies ORDER BY id")
+ assert_equal ["1","2","3","4","5","6","7","8","9", "10", "11"], Company.connection.select_values("SELECT id FROM companies ORDER BY id").map! { |i| i.to_s }
+ assert_equal ["37signals","Summit","Microsoft", "Flamboyant Software", "Ex Nihilo", "RailsCore", "Leetsoft", "Jadedpixel", "Odegy", "Ex Nihilo Part Deux", "Apex"], Company.connection.select_values("SELECT name FROM companies ORDER BY id")
end
def test_select_rows
@@ -863,14 +951,23 @@ class FinderTest < ActiveRecord::TestCase
end
def test_find_one_message_with_custom_primary_key
- Toy.primary_key = :name
- begin
- Toy.find 'Hello World!'
- rescue ActiveRecord::RecordNotFound => e
- assert_equal 'Couldn\'t find Toy with name=Hello World!', e.message
+ table_with_custom_primary_key do |model|
+ model.primary_key = :name
+ e = assert_raises(ActiveRecord::RecordNotFound) do
+ model.find 'Hello World!'
+ end
+ assert_equal %Q{Couldn't find MercedesCar with 'name'=Hello World!}, e.message
+ end
+ end
+
+ def test_find_some_message_with_custom_primary_key
+ table_with_custom_primary_key do |model|
+ model.primary_key = :name
+ e = assert_raises(ActiveRecord::RecordNotFound) do
+ model.find 'Hello', 'World!'
+ end
+ assert_equal %Q{Couldn't find all MercedesCars with 'name': (Hello, World!) (found 0 results, but was looking for 2)}, e.message
end
- ensure
- Toy.reset_primary_key
end
def test_find_without_primary_key
@@ -892,10 +989,11 @@ class FinderTest < ActiveRecord::TestCase
end
end
- def with_env_tz(new_tz = 'US/Eastern')
- old_tz, ENV['TZ'] = ENV['TZ'], new_tz
- yield
- ensure
- old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ')
+ def table_with_custom_primary_key
+ yield(Class.new(Toy) do
+ def self.name
+ 'MercedesCar'
+ end
+ end)
end
end
diff --git a/activerecord/test/cases/hot_compatibility_test.rb b/activerecord/test/cases/hot_compatibility_test.rb
index 96e581ab4c..367d04a154 100644
--- a/activerecord/test/cases/hot_compatibility_test.rb
+++ b/activerecord/test/cases/hot_compatibility_test.rb
@@ -5,7 +5,7 @@ class HotCompatibilityTest < ActiveRecord::TestCase
setup do
@klass = Class.new(ActiveRecord::Base) do
- connection.create_table :hot_compatibilities do |t|
+ connection.create_table :hot_compatibilities, force: true do |t|
t.string :foo
t.string :bar
end
diff --git a/activerecord/test/cases/inheritance_test.rb b/activerecord/test/cases/inheritance_test.rb
index cb0d374ef7..e2ff2aa451 100644
--- a/activerecord/test/cases/inheritance_test.rb
+++ b/activerecord/test/cases/inheritance_test.rb
@@ -1,10 +1,11 @@
-require "cases/helper"
+require 'cases/helper'
require 'models/company'
require 'models/person'
require 'models/post'
require 'models/project'
require 'models/subscriber'
require 'models/vegetables'
+require 'models/shop'
class InheritanceTest < ActiveRecord::TestCase
fixtures :companies, :projects, :subscribers, :accounts, :vegetables
@@ -128,6 +129,17 @@ class InheritanceTest < ActiveRecord::TestCase
assert_kind_of Cabbage, cabbage
end
+ def test_alt_becomes_bang_resets_inheritance_type_column
+ vegetable = Vegetable.create!(name: "Red Pepper")
+ assert_nil vegetable.custom_type
+
+ cabbage = vegetable.becomes!(Cabbage)
+ assert_equal "Cabbage", cabbage.custom_type
+
+ vegetable = cabbage.becomes!(Vegetable)
+ assert_nil cabbage.custom_type
+ end
+
def test_inheritance_find_all
companies = Company.all.merge!(:order => 'id').to_a
assert_kind_of Firm, companies[0], "37signals should be a firm"
@@ -210,9 +222,9 @@ class InheritanceTest < ActiveRecord::TestCase
end
def test_inheritance_condition
- assert_equal 10, Company.count
+ assert_equal 11, Company.count
assert_equal 2, Firm.count
- assert_equal 4, Client.count
+ assert_equal 5, Client.count
end
def test_alt_inheritance_condition
@@ -356,4 +368,10 @@ class InheritanceComputeTypeTest < ActiveRecord::TestCase
ensure
ActiveRecord::Base.store_full_sti_class = true
end
+
+ def test_sti_type_from_attributes_disabled_in_non_sti_class
+ phone = Shop::Product::Type.new(name: 'Phone')
+ product = Shop::Product.new(:type => phone)
+ assert product.save
+ end
end
diff --git a/activerecord/test/cases/integration_test.rb b/activerecord/test/cases/integration_test.rb
index 2e71b1a40d..dfb8a608cb 100644
--- a/activerecord/test/cases/integration_test.rb
+++ b/activerecord/test/cases/integration_test.rb
@@ -3,12 +3,11 @@
require 'cases/helper'
require 'models/company'
require 'models/developer'
-require 'models/car'
-require 'models/bulb'
require 'models/owner'
+require 'models/pet'
class IntegrationTest < ActiveRecord::TestCase
- fixtures :companies, :developers, :owners
+ fixtures :companies, :developers, :owners, :pets
def test_to_param_should_return_string
assert_kind_of String, Client.first.to_param
@@ -91,13 +90,14 @@ class IntegrationTest < ActiveRecord::TestCase
end
def test_cache_key_changes_when_child_touched
- car = Car.create
- Bulb.create(car: car)
+ owner = owners(:blackbeard)
+ pet = pets(:parrot)
+
+ owner.update_column :updated_at, Time.current
+ key = owner.cache_key
- key = car.cache_key
- car.bulb.touch
- car.reload
- assert_not_equal key, car.cache_key
+ assert pet.touch
+ assert_not_equal key, owner.reload.cache_key
end
def test_cache_key_format_for_existing_record_with_nil_updated_timestamps
diff --git a/activerecord/test/cases/locking_test.rb b/activerecord/test/cases/locking_test.rb
index a16ed963fe..c373dc1511 100644
--- a/activerecord/test/cases/locking_test.rb
+++ b/activerecord/test/cases/locking_test.rb
@@ -431,6 +431,17 @@ unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter) || in_memory_db?
assert_equal old, person.reload.first_name
end
+ if current_adapter?(:PostgreSQLAdapter)
+ def test_lock_sending_custom_lock_statement
+ Person.transaction do
+ person = Person.find(1)
+ assert_sql(/LIMIT 1 FOR SHARE NOWAIT/) do
+ person.lock!('FOR SHARE NOWAIT')
+ end
+ end
+ end
+ end
+
if current_adapter?(:PostgreSQLAdapter, :OracleAdapter)
def test_no_locks_no_wait
first, second = duel { Person.find 1 }
diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb
index 0363bf1048..1bda472d23 100644
--- a/activerecord/test/cases/migration_test.rb
+++ b/activerecord/test/cases/migration_test.rb
@@ -328,6 +328,7 @@ class MigrationTest < ActiveRecord::TestCase
end
def test_proper_table_name_on_migrator
+ reminder_class = new_isolated_reminder_class
assert_deprecated do
assert_equal "table", ActiveRecord::Migrator.proper_table_name('table')
end
@@ -335,30 +336,30 @@ class MigrationTest < ActiveRecord::TestCase
assert_equal "table", ActiveRecord::Migrator.proper_table_name(:table)
end
assert_deprecated do
- assert_equal "reminders", ActiveRecord::Migrator.proper_table_name(Reminder)
+ assert_equal "reminders", ActiveRecord::Migrator.proper_table_name(reminder_class)
end
- Reminder.reset_table_name
+ reminder_class.reset_table_name
assert_deprecated do
- assert_equal Reminder.table_name, ActiveRecord::Migrator.proper_table_name(Reminder)
+ assert_equal reminder_class.table_name, ActiveRecord::Migrator.proper_table_name(reminder_class)
end
# Use the model's own prefix/suffix if a model is given
ActiveRecord::Base.table_name_prefix = "ARprefix_"
ActiveRecord::Base.table_name_suffix = "_ARsuffix"
- Reminder.table_name_prefix = 'prefix_'
- Reminder.table_name_suffix = '_suffix'
- Reminder.reset_table_name
+ reminder_class.table_name_prefix = 'prefix_'
+ reminder_class.table_name_suffix = '_suffix'
+ reminder_class.reset_table_name
assert_deprecated do
- assert_equal "prefix_reminders_suffix", ActiveRecord::Migrator.proper_table_name(Reminder)
+ assert_equal "prefix_reminders_suffix", ActiveRecord::Migrator.proper_table_name(reminder_class)
end
- Reminder.table_name_prefix = ''
- Reminder.table_name_suffix = ''
- Reminder.reset_table_name
+ reminder_class.table_name_prefix = ''
+ reminder_class.table_name_suffix = ''
+ reminder_class.reset_table_name
# Use AR::Base's prefix/suffix if string or symbol is given
ActiveRecord::Base.table_name_prefix = "prefix_"
ActiveRecord::Base.table_name_suffix = "_suffix"
- Reminder.reset_table_name
+ reminder_class.reset_table_name
assert_deprecated do
assert_equal "prefix_table_suffix", ActiveRecord::Migrator.proper_table_name('table')
end
@@ -368,28 +369,29 @@ class MigrationTest < ActiveRecord::TestCase
end
def test_proper_table_name_on_migration
+ reminder_class = new_isolated_reminder_class
migration = ActiveRecord::Migration.new
assert_equal "table", migration.proper_table_name('table')
assert_equal "table", migration.proper_table_name(:table)
- assert_equal "reminders", migration.proper_table_name(Reminder)
- Reminder.reset_table_name
- assert_equal Reminder.table_name, migration.proper_table_name(Reminder)
+ assert_equal "reminders", migration.proper_table_name(reminder_class)
+ reminder_class.reset_table_name
+ assert_equal reminder_class.table_name, migration.proper_table_name(reminder_class)
# Use the model's own prefix/suffix if a model is given
ActiveRecord::Base.table_name_prefix = "ARprefix_"
ActiveRecord::Base.table_name_suffix = "_ARsuffix"
- Reminder.table_name_prefix = 'prefix_'
- Reminder.table_name_suffix = '_suffix'
- Reminder.reset_table_name
- assert_equal "prefix_reminders_suffix", migration.proper_table_name(Reminder)
- Reminder.table_name_prefix = ''
- Reminder.table_name_suffix = ''
- Reminder.reset_table_name
+ reminder_class.table_name_prefix = 'prefix_'
+ reminder_class.table_name_suffix = '_suffix'
+ reminder_class.reset_table_name
+ assert_equal "prefix_reminders_suffix", migration.proper_table_name(reminder_class)
+ reminder_class.table_name_prefix = ''
+ reminder_class.table_name_suffix = ''
+ reminder_class.reset_table_name
# Use AR::Base's prefix/suffix if string or symbol is given
ActiveRecord::Base.table_name_prefix = "prefix_"
ActiveRecord::Base.table_name_suffix = "_suffix"
- Reminder.reset_table_name
+ reminder_class.reset_table_name
assert_equal "prefix_table_suffix", migration.proper_table_name('table', migration.table_name_options)
assert_equal "prefix_table_suffix", migration.proper_table_name(:table, migration.table_name_options)
end
@@ -532,11 +534,13 @@ class MigrationTest < ActiveRecord::TestCase
end
protected
- def with_env_tz(new_tz = 'US/Eastern')
- old_tz, ENV['TZ'] = ENV['TZ'], new_tz
- yield
- ensure
- old_tz ? ENV['TZ'] = old_tz : ENV.delete('TZ')
+ # This is needed to isolate class_attribute assignments like `table_name_prefix`
+ # for each test case.
+ def new_isolated_reminder_class
+ Class.new(Reminder) {
+ def self.name; "Reminder"; end
+ def self.base_class; self; end
+ }
end
end
diff --git a/activerecord/test/cases/mixin_test.rb b/activerecord/test/cases/mixin_test.rb
index ad0d5cce27..7ddb2bfee1 100644
--- a/activerecord/test/cases/mixin_test.rb
+++ b/activerecord/test/cases/mixin_test.rb
@@ -6,10 +6,14 @@ end
class TouchTest < ActiveRecord::TestCase
fixtures :mixins
- def setup
+ setup do
travel_to Time.now
end
+ teardown do
+ travel_back
+ end
+
def test_update
stamped = Mixin.new
diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb
index 6f1e518f45..b9f0624f76 100644
--- a/activerecord/test/cases/persistence_test.rb
+++ b/activerecord/test/cases/persistence_test.rb
@@ -740,7 +740,7 @@ class PersistenceTest < ActiveRecord::TestCase
assert_raise(ActiveRecord::RecordInvalid) { reply.update!(title: nil, content: "Have a nice evening") }
ensure
- Reply.reset_callbacks(:validate)
+ Reply.clear_validators!
end
def test_update_attributes!
@@ -761,7 +761,7 @@ class PersistenceTest < ActiveRecord::TestCase
assert_raise(ActiveRecord::RecordInvalid) { reply.update_attributes!(title: nil, content: "Have a nice evening") }
ensure
- Reply.reset_callbacks(:validate)
+ Reply.clear_validators!
end
def test_destroyed_returns_boolean
diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb
index 5566563116..da8ae672fe 100644
--- a/activerecord/test/cases/query_cache_test.rb
+++ b/activerecord/test/cases/query_cache_test.rb
@@ -8,7 +8,7 @@ require 'rack'
class QueryCacheTest < ActiveRecord::TestCase
fixtures :tasks, :topics, :categories, :posts, :categories_posts
- def setup
+ teardown do
Task.connection.clear_query_cache
ActiveRecord::Base.connection.disable_query_cache!
end
@@ -214,7 +214,7 @@ class QueryCacheExpiryTest < ActiveRecord::TestCase
Post.find(1)
# change the column definition
- Post.connection.change_column :posts, :title, :string, :limit => 80
+ Post.connection.change_column :posts, :title, :string, limit: 80
assert_nothing_raised { Post.find(1) }
# restore the old definition
@@ -241,7 +241,6 @@ class QueryCacheExpiryTest < ActiveRecord::TestCase
def test_update
Task.connection.expects(:clear_query_cache).times(2)
-
Task.cache do
task = Task.find(1)
task.starting = Time.now.utc
@@ -251,7 +250,6 @@ class QueryCacheExpiryTest < ActiveRecord::TestCase
def test_destroy
Task.connection.expects(:clear_query_cache).times(2)
-
Task.cache do
Task.find(1).destroy
end
@@ -259,7 +257,6 @@ class QueryCacheExpiryTest < ActiveRecord::TestCase
def test_insert
ActiveRecord::Base.connection.expects(:clear_query_cache).times(2)
-
Task.cache do
Task.create!
end
diff --git a/activerecord/test/cases/relation/mutation_test.rb b/activerecord/test/cases/relation/mutation_test.rb
index 7cb2a19bee..4fafa668fb 100644
--- a/activerecord/test/cases/relation/mutation_test.rb
+++ b/activerecord/test/cases/relation/mutation_test.rb
@@ -14,6 +14,10 @@ module ActiveRecord
def relation_delegate_class(klass)
self.class.relation_delegate_class(klass)
end
+
+ def attribute_alias?(name)
+ false
+ end
end
def relation
diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb
index 031da8e6d6..e390d37871 100644
--- a/activerecord/test/cases/relations_test.rb
+++ b/activerecord/test/cases/relations_test.rb
@@ -65,7 +65,7 @@ class RelationTest < ActiveRecord::TestCase
def test_scoped
topics = Topic.all
assert_kind_of ActiveRecord::Relation, topics
- assert_equal 4, topics.size
+ assert_equal 5, topics.size
end
def test_to_json
@@ -86,14 +86,14 @@ class RelationTest < ActiveRecord::TestCase
def test_scoped_all
topics = Topic.all.to_a
assert_kind_of Array, topics
- assert_no_queries { assert_equal 4, topics.size }
+ assert_no_queries { assert_equal 5, topics.size }
end
def test_loaded_all
topics = Topic.all
assert_queries(1) do
- 2.times { assert_equal 4, topics.to_a.size }
+ 2.times { assert_equal 5, topics.to_a.size }
end
assert topics.loaded?
@@ -164,27 +164,27 @@ class RelationTest < ActiveRecord::TestCase
def test_finding_with_order
topics = Topic.order('id')
- assert_equal 4, topics.to_a.size
+ assert_equal 5, topics.to_a.size
assert_equal topics(:first).title, topics.first.title
end
def test_finding_with_arel_order
topics = Topic.order(Topic.arel_table[:id].asc)
- assert_equal 4, topics.to_a.size
+ assert_equal 5, topics.to_a.size
assert_equal topics(:first).title, topics.first.title
end
def test_finding_with_assoc_order
topics = Topic.order(:id => :desc)
- assert_equal 4, topics.to_a.size
- assert_equal topics(:fourth).title, topics.first.title
+ assert_equal 5, topics.to_a.size
+ assert_equal topics(:fifth).title, topics.first.title
end
def test_finding_with_reverted_assoc_order
topics = Topic.order(:id => :asc).reverse_order
- assert_equal 4, topics.to_a.size
- assert_equal topics(:fourth).title, topics.first.title
+ assert_equal 5, topics.to_a.size
+ assert_equal topics(:fifth).title, topics.first.title
end
def test_order_with_hash_and_symbol_generates_the_same_sql
@@ -197,19 +197,43 @@ class RelationTest < ActiveRecord::TestCase
def test_finding_last_with_arel_order
topics = Topic.order(Topic.arel_table[:id].asc)
- assert_equal topics(:fourth).title, topics.last.title
+ assert_equal topics(:fifth).title, topics.last.title
end
def test_finding_with_order_concatenated
topics = Topic.order('author_name').order('title')
- assert_equal 4, topics.to_a.size
+ assert_equal 5, topics.to_a.size
assert_equal topics(:fourth).title, topics.first.title
end
+ def test_finding_with_order_by_aliased_attributes
+ topics = Topic.order(:heading)
+ assert_equal 5, topics.to_a.size
+ assert_equal topics(:fifth).title, topics.first.title
+ end
+
+ def test_finding_with_assoc_order_by_aliased_attributes
+ topics = Topic.order(heading: :desc)
+ assert_equal 5, topics.to_a.size
+ assert_equal topics(:third).title, topics.first.title
+ end
+
def test_finding_with_reorder
topics = Topic.order('author_name').order('title').reorder('id').to_a
topics_titles = topics.map{ |t| t.title }
- assert_equal ['The First Topic', 'The Second Topic of the day', 'The Third Topic of the day', 'The Fourth Topic of the day'], topics_titles
+ assert_equal ['The First Topic', 'The Second Topic of the day', 'The Third Topic of the day', 'The Fourth Topic of the day', 'The Fifth Topic of the day'], topics_titles
+ end
+
+ def test_finding_with_reorder_by_aliased_attributes
+ topics = Topic.order('author_name').reorder(:heading)
+ assert_equal 5, topics.to_a.size
+ assert_equal topics(:fifth).title, topics.first.title
+ end
+
+ def test_finding_with_assoc_reorder_by_aliased_attributes
+ topics = Topic.order('author_name').reorder(heading: :desc)
+ assert_equal 5, topics.to_a.size
+ assert_equal topics(:third).title, topics.first.title
end
def test_finding_with_order_and_take
@@ -775,6 +799,13 @@ class RelationTest < ActiveRecord::TestCase
assert_equal david.salary, developer.salary
end
+ def test_select_takes_an_aliased_attribute
+ first = topics(:first)
+
+ topic = Topic.where(id: first.id).select(:heading).first
+ assert_equal first.heading, topic.heading
+ end
+
def test_select_argument_error
assert_raises(ArgumentError) { Developer.select }
end
@@ -1505,23 +1536,25 @@ class RelationTest < ActiveRecord::TestCase
end
end
+ test "joins with select" do
+ posts = Post.joins(:author).select("id", "authors.author_address_id").order("posts.id").limit(3)
+ assert_equal [1, 2, 4], posts.map(&:id)
+ assert_equal [1, 1, 1], posts.map(&:author_address_id)
+ end
+
test "delegations do not leak to other classes" do
Topic.all.by_lifo
assert Topic.all.class.method_defined?(:by_lifo)
assert !Post.all.respond_to?(:by_lifo)
end
- test "merge collapses wheres from the LHS only" do
- left = Post.where(title: "omg").where(comments_count: 1)
- right = Post.where(title: "wtf").where(title: "bbq")
-
- expected = [left.where_values[1]] + right.where_values
- merged = left.merge(right)
+ def test_unscope_removes_binds
+ left = Post.where(id: Arel::Nodes::BindParam.new('?'))
+ column = Post.columns_hash['id']
+ left.bind_values += [[column, 20]]
- assert_equal expected, merged.where_values
- assert !merged.to_sql.include?("omg")
- assert merged.to_sql.include?("wtf")
- assert merged.to_sql.include?("bbq")
+ relation = left.unscope(where: :id)
+ assert_equal [], relation.bind_values
end
def test_merging_removes_rhs_bind_parameters
diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb
index 741827446d..c085663efb 100644
--- a/activerecord/test/cases/schema_dumper_test.rb
+++ b/activerecord/test/cases/schema_dumper_test.rb
@@ -190,6 +190,8 @@ class SchemaDumperTest < ActiveRecord::TestCase
assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index", where: "(rating > 10)", using: :btree', index_definition
elsif current_adapter?(:MysqlAdapter) || current_adapter?(:Mysql2Adapter)
assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index", using: :btree', index_definition
+ elsif current_adapter?(:SQLite3Adapter) && ActiveRecord::Base.connection.supports_partial_index?
+ assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index", where: "rating > 10"', index_definition
else
assert_equal 'add_index "companies", ["firm_id", "type"], name: "company_partial_index"', index_definition
end
diff --git a/activerecord/test/cases/scoping/default_scoping_test.rb b/activerecord/test/cases/scoping/default_scoping_test.rb
index 71754cf0a2..170e9a49eb 100644
--- a/activerecord/test/cases/scoping/default_scoping_test.rb
+++ b/activerecord/test/cases/scoping/default_scoping_test.rb
@@ -149,6 +149,16 @@ class DefaultScopingTest < ActiveRecord::TestCase
assert_equal expected, received
end
+ def test_unscope_string_where_clauses_involved
+ dev_relation = Developer.order('salary DESC').where("created_at > ?", 1.year.ago)
+ expected = dev_relation.collect { |dev| dev.name }
+
+ dev_ordered_relation = DeveloperOrderedBySalary.where(name: 'Jamis').where("created_at > ?", 1.year.ago)
+ received = dev_ordered_relation.unscope(where: [:name]).collect { |dev| dev.name }
+
+ assert_equal expected, received
+ end
+
def test_unscope_with_grouping_attributes
expected = Developer.order('salary DESC').collect { |dev| dev.name }
received = DeveloperOrderedBySalary.group(:name).unscope(:group).collect { |dev| dev.name }
diff --git a/activerecord/test/cases/scoping/named_scoping_test.rb b/activerecord/test/cases/scoping/named_scoping_test.rb
index 72c9787b84..9dc26cfd4d 100644
--- a/activerecord/test/cases/scoping/named_scoping_test.rb
+++ b/activerecord/test/cases/scoping/named_scoping_test.rb
@@ -266,6 +266,63 @@ class NamedScopingTest < ActiveRecord::TestCase
assert_equal 'lifo', topic.author_name
end
+ def test_reserved_scope_names
+ klass = Class.new(ActiveRecord::Base) do
+ self.table_name = "topics"
+
+ scope :approved, -> { where(approved: true) }
+
+ class << self
+ public
+ def pub; end
+
+ private
+ def pri; end
+
+ protected
+ def pro; end
+ end
+ end
+
+ subklass = Class.new(klass)
+
+ conflicts = [
+ :create, # public class method on AR::Base
+ :relation, # private class method on AR::Base
+ :new, # redefined class method on AR::Base
+ :all, # a default scope
+ ]
+
+ non_conflicts = [
+ :find_by_title, # dynamic finder method
+ :approved, # existing scope
+ :pub, # existing public class method
+ :pri, # existing private class method
+ :pro, # existing protected class method
+ :open, # a ::Kernel method
+ ]
+
+ conflicts.each do |name|
+ assert_raises(ArgumentError, "scope `#{name}` should not be allowed") do
+ klass.class_eval { scope name, ->{ where(approved: true) } }
+ end
+
+ assert_raises(ArgumentError, "scope `#{name}` should not be allowed") do
+ subklass.class_eval { scope name, ->{ where(approved: true) } }
+ end
+ end
+
+ non_conflicts.each do |name|
+ assert_nothing_raised do
+ klass.class_eval { scope name, ->{ where(approved: true) } }
+ end
+
+ assert_nothing_raised do
+ subklass.class_eval { scope name, ->{ where(approved: true) } }
+ end
+ end
+ end
+
# Method delegation for scope names which look like /\A[a-zA-Z_]\w*[!?]?\z/
# has been done by evaluating a string with a plain def statement. For scope
# names which contain spaces this approach doesn't work.
@@ -344,13 +401,13 @@ class NamedScopingTest < ActiveRecord::TestCase
end
def test_scopes_batch_finders
- assert_equal 3, Topic.approved.count
+ assert_equal 4, Topic.approved.count
- assert_queries(4) do
+ assert_queries(5) do
Topic.approved.find_each(:batch_size => 1) {|t| assert t.approved? }
end
- assert_queries(2) do
+ assert_queries(3) do
Topic.approved.find_in_batches(:batch_size => 2) do |group|
group.each {|t| assert t.approved? }
end
@@ -366,7 +423,7 @@ class NamedScopingTest < ActiveRecord::TestCase
def test_scopes_on_relations
# Topic.replied
approved_topics = Topic.all.approved.order('id DESC')
- assert_equal topics(:fourth), approved_topics.first
+ assert_equal topics(:fifth), approved_topics.first
replied_approved_topics = approved_topics.replied
assert_equal topics(:third), replied_approved_topics.first
diff --git a/activerecord/test/cases/store_test.rb b/activerecord/test/cases/store_test.rb
index 6f632b4d8d..978cee9cfb 100644
--- a/activerecord/test/cases/store_test.rb
+++ b/activerecord/test/cases/store_test.rb
@@ -166,4 +166,28 @@ class StoreTest < ActiveRecord::TestCase
test "YAML coder initializes the store when a Nil value is given" do
assert_equal({}, @john.params)
end
+
+ test "attributes_for_coder should return stored fields already serialized" do
+ attributes = {
+ "id" => @john.id,
+ "name"=> @john.name,
+ "settings" => "--- !ruby/hash:ActiveSupport::HashWithIndifferentAccess\ncolor: black\n",
+ "preferences" => "--- !ruby/hash:ActiveSupport::HashWithIndifferentAccess\nremember_login: true\n",
+ "json_data" => "{\"height\":\"tall\"}", "json_data_empty"=>"{\"is_a_good_guy\":true}",
+ "params" => "--- !ruby/hash:ActiveSupport::HashWithIndifferentAccess {}\n",
+ "account_id"=> @john.account_id
+ }
+
+ assert_equal attributes, @john.attributes_for_coder
+ end
+
+ test "dump, load and dump again a model" do
+ dumped = YAML.dump(@john)
+ loaded = YAML.load(dumped)
+ assert_equal @john, loaded
+
+ second_dump = YAML.dump(loaded)
+ assert_equal dumped, second_dump
+ assert_equal @john, YAML.load(second_dump)
+ end
end
diff --git a/activerecord/test/cases/transaction_callbacks_test.rb b/activerecord/test/cases/transaction_callbacks_test.rb
index 5644a35385..7e7d95841b 100644
--- a/activerecord/test/cases/transaction_callbacks_test.rb
+++ b/activerecord/test/cases/transaction_callbacks_test.rb
@@ -1,9 +1,11 @@
require "cases/helper"
+require 'models/owner'
+require 'models/pet'
require 'models/topic'
class TransactionCallbacksTest < ActiveRecord::TestCase
self.use_transactional_fixtures = false
- fixtures :topics
+ fixtures :topics, :owners, :pets
class ReplyWithCallbacks < ActiveRecord::Base
self.table_name = :topics
@@ -28,14 +30,14 @@ class TransactionCallbacksTest < ActiveRecord::TestCase
has_many :replies, class_name: "ReplyWithCallbacks", foreign_key: "parent_id"
- after_commit{|record| record.send(:do_after_commit, nil)}
- after_commit(:on => :create){|record| record.send(:do_after_commit, :create)}
- after_commit(:on => :update){|record| record.send(:do_after_commit, :update)}
- after_commit(:on => :destroy){|record| record.send(:do_after_commit, :destroy)}
- after_rollback{|record| record.send(:do_after_rollback, nil)}
- after_rollback(:on => :create){|record| record.send(:do_after_rollback, :create)}
- after_rollback(:on => :update){|record| record.send(:do_after_rollback, :update)}
- after_rollback(:on => :destroy){|record| record.send(:do_after_rollback, :destroy)}
+ after_commit { |record| record.do_after_commit(nil) }
+ after_commit(on: :create) { |record| record.do_after_commit(:create) }
+ after_commit(on: :update) { |record| record.do_after_commit(:update) }
+ after_commit(on: :destroy) { |record| record.do_after_commit(:destroy) }
+ after_rollback { |record| record.do_after_rollback(nil) }
+ after_rollback(on: :create) { |record| record.do_after_rollback(:create) }
+ after_rollback(on: :update) { |record| record.do_after_rollback(:update) }
+ after_rollback(on: :destroy) { |record| record.do_after_rollback(:destroy) }
def history
@history ||= []
@@ -65,7 +67,7 @@ class TransactionCallbacksTest < ActiveRecord::TestCase
end
def setup
- @first, @second = TopicWithCallbacks.find(1, 3).sort_by { |t| t.id }
+ @first = TopicWithCallbacks.find(1)
end
def test_call_after_commit_after_transaction_commits
@@ -77,40 +79,25 @@ class TransactionCallbacksTest < ActiveRecord::TestCase
end
def test_only_call_after_commit_on_update_after_transaction_commits_for_existing_record
- @first.after_commit_block(:create){|r| r.history << :commit_on_create}
- @first.after_commit_block(:update){|r| r.history << :commit_on_update}
- @first.after_commit_block(:destroy){|r| r.history << :commit_on_destroy}
- @first.after_rollback_block(:create){|r| r.history << :rollback_on_create}
- @first.after_rollback_block(:update){|r| r.history << :rollback_on_update}
- @first.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy}
+ add_transaction_execution_blocks @first
@first.save!
assert_equal [:commit_on_update], @first.history
end
def test_only_call_after_commit_on_destroy_after_transaction_commits_for_destroyed_record
- @first.after_commit_block(:create){|r| r.history << :commit_on_create}
- @first.after_commit_block(:update){|r| r.history << :commit_on_update}
- @first.after_commit_block(:destroy){|r| r.history << :commit_on_destroy}
- @first.after_rollback_block(:create){|r| r.history << :rollback_on_create}
- @first.after_rollback_block(:update){|r| r.history << :rollback_on_update}
- @first.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy}
+ add_transaction_execution_blocks @first
@first.destroy
assert_equal [:commit_on_destroy], @first.history
end
def test_only_call_after_commit_on_create_after_transaction_commits_for_new_record
- @new_record = TopicWithCallbacks.new(:title => "New topic", :written_on => Date.today)
- @new_record.after_commit_block(:create){|r| r.history << :commit_on_create}
- @new_record.after_commit_block(:update){|r| r.history << :commit_on_update}
- @new_record.after_commit_block(:destroy){|r| r.history << :commit_on_destroy}
- @new_record.after_rollback_block(:create){|r| r.history << :rollback_on_create}
- @new_record.after_rollback_block(:update){|r| r.history << :rollback_on_update}
- @new_record.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy}
-
- @new_record.save!
- assert_equal [:commit_on_create], @new_record.history
+ new_record = TopicWithCallbacks.new(:title => "New topic", :written_on => Date.today)
+ add_transaction_execution_blocks new_record
+
+ new_record.save!
+ assert_equal [:commit_on_create], new_record.history
end
def test_only_call_after_commit_on_create_after_transaction_commits_for_new_record_if_create_succeeds_creating_through_association
@@ -120,6 +107,13 @@ class TransactionCallbacksTest < ActiveRecord::TestCase
assert_equal [], reply.history
end
+ def test_only_call_after_commit_on_update_after_transaction_commits_for_existing_record_on_touch
+ add_transaction_execution_blocks @first
+
+ @first.touch
+ assert_equal [:commit_on_update], @first.history
+ end
+
def test_call_after_rollback_after_transaction_rollsback
@first.after_commit_block{|r| r.history << :after_commit}
@first.after_rollback_block{|r| r.history << :after_rollback}
@@ -133,12 +127,7 @@ class TransactionCallbacksTest < ActiveRecord::TestCase
end
def test_only_call_after_rollback_on_update_after_transaction_rollsback_for_existing_record
- @first.after_commit_block(:create){|r| r.history << :commit_on_create}
- @first.after_commit_block(:update){|r| r.history << :commit_on_update}
- @first.after_commit_block(:destroy){|r| r.history << :commit_on_destroy}
- @first.after_rollback_block(:create){|r| r.history << :rollback_on_create}
- @first.after_rollback_block(:update){|r| r.history << :rollback_on_update}
- @first.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy}
+ add_transaction_execution_blocks @first
Topic.transaction do
@first.save!
@@ -148,13 +137,19 @@ class TransactionCallbacksTest < ActiveRecord::TestCase
assert_equal [:rollback_on_update], @first.history
end
+ def test_only_call_after_rollback_on_update_after_transaction_rollsback_for_existing_record_on_touch
+ add_transaction_execution_blocks @first
+
+ Topic.transaction do
+ @first.touch
+ raise ActiveRecord::Rollback
+ end
+
+ assert_equal [:rollback_on_update], @first.history
+ end
+
def test_only_call_after_rollback_on_destroy_after_transaction_rollsback_for_destroyed_record
- @first.after_commit_block(:create){|r| r.history << :commit_on_create}
- @first.after_commit_block(:update){|r| r.history << :commit_on_update}
- @first.after_commit_block(:destroy){|r| r.history << :commit_on_update}
- @first.after_rollback_block(:create){|r| r.history << :rollback_on_create}
- @first.after_rollback_block(:update){|r| r.history << :rollback_on_update}
- @first.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy}
+ add_transaction_execution_blocks @first
Topic.transaction do
@first.destroy
@@ -165,20 +160,15 @@ class TransactionCallbacksTest < ActiveRecord::TestCase
end
def test_only_call_after_rollback_on_create_after_transaction_rollsback_for_new_record
- @new_record = TopicWithCallbacks.new(:title => "New topic", :written_on => Date.today)
- @new_record.after_commit_block(:create){|r| r.history << :commit_on_create}
- @new_record.after_commit_block(:update){|r| r.history << :commit_on_update}
- @new_record.after_commit_block(:destroy){|r| r.history << :commit_on_destroy}
- @new_record.after_rollback_block(:create){|r| r.history << :rollback_on_create}
- @new_record.after_rollback_block(:update){|r| r.history << :rollback_on_update}
- @new_record.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy}
+ new_record = TopicWithCallbacks.new(:title => "New topic", :written_on => Date.today)
+ add_transaction_execution_blocks new_record
Topic.transaction do
- @new_record.save!
+ new_record.save!
raise ActiveRecord::Rollback
end
- assert_equal [:rollback_on_create], @new_record.history
+ assert_equal [:rollback_on_create], new_record.history
end
def test_call_after_rollback_when_commit_fails
@@ -205,23 +195,24 @@ class TransactionCallbacksTest < ActiveRecord::TestCase
@first.after_rollback_block{|r| r.rollbacks(1)}
@first.after_commit_block{|r| r.commits(1)}
- def @second.rollbacks(i=0); @rollbacks ||= 0; @rollbacks += i if i; end
- def @second.commits(i=0); @commits ||= 0; @commits += i if i; end
- @second.after_rollback_block{|r| r.rollbacks(1)}
- @second.after_commit_block{|r| r.commits(1)}
+ second = TopicWithCallbacks.find(3)
+ def second.rollbacks(i=0); @rollbacks ||= 0; @rollbacks += i if i; end
+ def second.commits(i=0); @commits ||= 0; @commits += i if i; end
+ second.after_rollback_block{|r| r.rollbacks(1)}
+ second.after_commit_block{|r| r.commits(1)}
Topic.transaction do
@first.save!
Topic.transaction(:requires_new => true) do
- @second.save!
+ second.save!
raise ActiveRecord::Rollback
end
end
assert_equal 1, @first.commits
assert_equal 0, @first.rollbacks
- assert_equal 0, @second.commits
- assert_equal 1, @second.rollbacks
+ assert_equal 0, second.commits
+ assert_equal 1, second.rollbacks
end
def test_only_call_after_rollback_on_records_rolled_back_to_a_savepoint_when_release_savepoint_fails
@@ -252,33 +243,61 @@ class TransactionCallbacksTest < ActiveRecord::TestCase
def @first.last_after_transaction_error; @last_transaction_error; end
@first.after_commit_block{|r| r.last_after_transaction_error = :commit; raise "fail!";}
@first.after_rollback_block{|r| r.last_after_transaction_error = :rollback; raise "fail!";}
- @second.after_commit_block{|r| r.history << :after_commit}
- @second.after_rollback_block{|r| r.history << :after_rollback}
+
+ second = TopicWithCallbacks.find(3)
+ second.after_commit_block{|r| r.history << :after_commit}
+ second.after_rollback_block{|r| r.history << :after_rollback}
Topic.transaction do
@first.save!
- @second.save!
+ second.save!
end
assert_equal :commit, @first.last_after_transaction_error
- assert_equal [:after_commit], @second.history
+ assert_equal [:after_commit], second.history
- @second.history.clear
+ second.history.clear
Topic.transaction do
@first.save!
- @second.save!
+ second.save!
raise ActiveRecord::Rollback
end
assert_equal :rollback, @first.last_after_transaction_error
- assert_equal [:after_rollback], @second.history
+ assert_equal [:after_rollback], second.history
end
def test_after_rollback_callbacks_should_validate_on_condition
- assert_raise(ArgumentError) { Topic.send(:after_rollback, :on => :save) }
+ assert_raise(ArgumentError) { Topic.after_rollback(on: :save) }
end
def test_after_commit_callbacks_should_validate_on_condition
- assert_raise(ArgumentError) { Topic.send(:after_commit, :on => :save) }
+ assert_raise(ArgumentError) { Topic.after_commit(on: :save) }
end
+
+ def test_saving_a_record_with_a_belongs_to_that_specifies_touching_the_parent_should_call_callbacks_on_the_parent_object
+ pet = Pet.first
+ owner = pet.owner
+ flag = false
+
+ owner.on_after_commit do
+ flag = true
+ end
+
+ pet.name = "Fluffy the Third"
+ pet.save
+
+ assert flag
+ 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 }
+ record.after_commit_block(:destroy) { |r| r.history << :commit_on_destroy }
+ record.after_rollback_block(:create) { |r| r.history << :rollback_on_create }
+ record.after_rollback_block(:update) { |r| r.history << :rollback_on_update }
+ record.after_rollback_block(:destroy) { |r| r.history << :rollback_on_destroy }
+ end
end
class CallbacksOnMultipleActionsTest < ActiveRecord::TestCase
diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb
index 89dab16975..1664f1a096 100644
--- a/activerecord/test/cases/transactions_test.rb
+++ b/activerecord/test/cases/transactions_test.rb
@@ -430,17 +430,26 @@ class TransactionTest < ActiveRecord::TestCase
end
def test_restore_active_record_state_for_all_records_in_a_transaction
+ topic_without_callbacks = Class.new(ActiveRecord::Base) do
+ self.table_name = 'topics'
+ end
+
topic_1 = Topic.new(:title => 'test_1')
topic_2 = Topic.new(:title => 'test_2')
+ topic_3 = topic_without_callbacks.new(:title => 'test_3')
+
Topic.transaction do
assert topic_1.save
assert topic_2.save
+ assert topic_3.save
@first.save
@second.destroy
assert topic_1.persisted?, 'persisted'
assert_not_nil topic_1.id
assert topic_2.persisted?, 'persisted'
assert_not_nil topic_2.id
+ assert topic_3.persisted?, 'persisted'
+ assert_not_nil topic_3.id
assert @first.persisted?, 'persisted'
assert_not_nil @first.id
assert @second.destroyed?, 'destroyed'
@@ -451,6 +460,8 @@ class TransactionTest < ActiveRecord::TestCase
assert_nil topic_1.id
assert !topic_2.persisted?, 'not persisted'
assert_nil topic_2.id
+ assert !topic_3.persisted?, 'not persisted'
+ assert_nil topic_3.id
assert @first.persisted?, 'persisted'
assert_not_nil @first.id
assert !@second.destroyed?, 'not destroyed'
diff --git a/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb b/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb
index a73c3bf1af..13d4d85afa 100644
--- a/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb
+++ b/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb
@@ -3,7 +3,7 @@ require 'models/topic'
class I18nGenerateMessageValidationTest < ActiveRecord::TestCase
def setup
- Topic.reset_callbacks(:validate)
+ Topic.clear_validators!
@topic = Topic.new
I18n.backend = I18n::Backend::Simple.new
end