diff options
Diffstat (limited to 'activerecord/test')
-rw-r--r-- | activerecord/test/cases/associations/cascaded_eager_loading_test.rb | 8 | ||||
-rw-r--r-- | activerecord/test/cases/associations/eager_test.rb | 48 | ||||
-rw-r--r-- | activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb | 11 | ||||
-rw-r--r-- | activerecord/test/cases/associations/has_many_associations_test.rb | 9 | ||||
-rwxr-xr-x | activerecord/test/cases/base_test.rb | 5 | ||||
-rw-r--r-- | activerecord/test/cases/callbacks_test.rb | 44 | ||||
-rw-r--r-- | activerecord/test/cases/defaults_test.rb | 63 | ||||
-rw-r--r-- | activerecord/test/cases/dirty_test.rb | 26 | ||||
-rw-r--r-- | activerecord/test/cases/helper.rb | 2 | ||||
-rw-r--r-- | activerecord/test/cases/json_serialization_test.rb | 2 | ||||
-rw-r--r-- | activerecord/test/cases/named_scope_test.rb | 22 | ||||
-rw-r--r-- | activerecord/test/cases/transactions_test.rb | 166 | ||||
-rw-r--r-- | activerecord/test/fixtures/people.yml | 11 | ||||
-rw-r--r-- | activerecord/test/models/person.rb | 6 | ||||
-rw-r--r-- | activerecord/test/schema/schema.rb | 7 |
15 files changed, 392 insertions, 38 deletions
diff --git a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb index 8c9ae8a031..45e74ea024 100644 --- a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb +++ b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb @@ -104,6 +104,14 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase authors.first.posts.first.special_comments.first.post.very_special_comment end end + + def test_eager_association_loading_where_first_level_returns_nil + authors = Author.find(:all, :include => {:post_about_thinking => :comments}, :order => 'authors.id DESC') + assert_equal [authors(:mary), authors(:david)], authors + assert_no_queries do + authors[1].post_about_thinking.comments.first + end + end end require 'models/vertex' diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb index a2d0efab92..14099d4176 100644 --- a/activerecord/test/cases/associations/eager_test.rb +++ b/activerecord/test/cases/associations/eager_test.rb @@ -771,4 +771,52 @@ class EagerAssociationTest < ActiveRecord::TestCase assert_equal author_addresses(:david_address), authors[0].author_address end + def test_preload_belongs_to_uses_exclusive_scope + people = Person.males.find(:all, :include => :primary_contact) + assert_not_equal people.length, 0 + people.each do |person| + assert_no_queries {assert_not_nil person.primary_contact} + assert_equal Person.find(person.id).primary_contact, person.primary_contact + end + end + + def test_preload_has_many_uses_exclusive_scope + people = Person.males.find :all, :include => :agents + people.each do |person| + assert_equal Person.find(person.id).agents, person.agents + end + end + + def test_preload_has_many_using_primary_key + expected = Firm.find(:first).clients_using_primary_key.to_a + firm = Firm.find :first, :include => :clients_using_primary_key + assert_no_queries do + assert_equal expected, firm.clients_using_primary_key + end + end + + def test_include_has_many_using_primary_key + expected = Firm.find(1).clients_using_primary_key.sort_by &:name + firm = Firm.find 1, :include => :clients_using_primary_key, :order => 'clients_using_primary_keys_companies.name' + assert_no_queries do + assert_equal expected, firm.clients_using_primary_key + end + end + + def test_preload_has_one_using_primary_key + expected = Firm.find(:first).account_using_primary_key + firm = Firm.find :first, :include => :account_using_primary_key + assert_no_queries do + assert_equal expected, firm.account_using_primary_key + end + end + + def test_include_has_one_using_primary_key + expected = Firm.find(1).account_using_primary_key + firm = Firm.find(:all, :include => :account_using_primary_key, :order => 'accounts.id').detect {|f| f.id == 1} + assert_no_queries do + assert_equal expected, firm.account_using_primary_key + end + end + end diff --git a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb index 2f08e09d43..1e3b423471 100644 --- a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb @@ -775,4 +775,15 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase end end end + + def test_caching_of_columns + david = Developer.find(1) + # clear cache possibly created by other tests + david.projects.reset_column_information + assert_queries(0) { david.projects.columns; david.projects.columns } + # and again to verify that reset_column_information clears the cache correctly + david.projects.reset_column_information + assert_queries(0) { david.projects.columns; david.projects.columns } + end + end diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index 20b9acda44..428fb50013 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -698,7 +698,8 @@ class HasManyAssociationsTest < ActiveRecord::TestCase authors(:david).destroy end - assert_equal [author_address.id], AuthorAddress.destroyed_author_address_ids[authors(:david).id] + assert_equal nil, AuthorAddress.find_by_id(authors(:david).author_address_id) + assert_equal nil, AuthorAddress.find_by_id(authors(:david).author_address_extra_id) end def test_invalid_belongs_to_dependent_option_raises_exception @@ -1115,5 +1116,11 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert !client_association.respond_to?(:private_method) assert client_association.respond_to?(:private_method, true) end + + def test_creating_using_primary_key + firm = Firm.find(:first) + client = firm.clients_using_primary_key.create!(:name => 'test') + assert_equal firm.name, client.firm_name + end end diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index ce77ba4dbf..0f03dae829 100755 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -1198,6 +1198,11 @@ class BasicsTest < ActiveRecord::TestCase assert b_true.value? end + def test_new_record_returns_boolean + assert_equal Topic.new.new_record?, true + assert_equal Topic.find(1).new_record?, false + end + def test_clone topic = Topic.find(1) cloned_topic = nil diff --git a/activerecord/test/cases/callbacks_test.rb b/activerecord/test/cases/callbacks_test.rb index 11830a2ef6..33b1ea034d 100644 --- a/activerecord/test/cases/callbacks_test.rb +++ b/activerecord/test/cases/callbacks_test.rb @@ -121,9 +121,19 @@ end class CallbackCancellationDeveloper < ActiveRecord::Base set_table_name 'developers' - def before_create - false - end + + attr_reader :after_save_called, :after_create_called, :after_update_called, :after_destroy_called + attr_accessor :cancel_before_save, :cancel_before_create, :cancel_before_update, :cancel_before_destroy + + def before_save; !@cancel_before_save; end + def before_create; !@cancel_before_create; end + def before_update; !@cancel_before_update; end + def before_destroy; !@cancel_before_destroy; end + + def after_save; @after_save_called = true; end + def after_update; @after_update_called = true; end + def after_create; @after_create_called = true; end + def after_destroy; @after_destroy_called = true; end end class CallbacksTest < ActiveRecord::TestCase @@ -349,19 +359,47 @@ class CallbacksTest < ActiveRecord::TestCase assert !david.valid? assert !david.save assert_raises(ActiveRecord::RecordInvalid) { david.save! } + + someone = CallbackCancellationDeveloper.find(1) + someone.cancel_before_save = true + assert someone.valid? + assert !someone.save + assert_save_callbacks_not_called(someone) end def test_before_create_returning_false someone = CallbackCancellationDeveloper.new + someone.cancel_before_create = true assert someone.valid? assert !someone.save + assert_save_callbacks_not_called(someone) + end + + def test_before_update_returning_false + someone = CallbackCancellationDeveloper.find(1) + someone.cancel_before_update = true + assert someone.valid? + assert !someone.save + assert_save_callbacks_not_called(someone) end def test_before_destroy_returning_false david = ImmutableDeveloper.find(1) assert !david.destroy assert_not_nil ImmutableDeveloper.find_by_id(1) + + someone = CallbackCancellationDeveloper.find(1) + someone.cancel_before_destroy = true + assert !someone.destroy + assert !someone.after_destroy_called + end + + def assert_save_callbacks_not_called(someone) + assert !someone.after_save_called + assert !someone.after_create_called + assert !someone.after_update_called end + private :assert_save_callbacks_not_called def test_zzz_callback_returning_false # must be run last since we modify CallbackDeveloper david = CallbackDeveloper.find(1) diff --git a/activerecord/test/cases/defaults_test.rb b/activerecord/test/cases/defaults_test.rb index 38e4853dc0..b4032c23e6 100644 --- a/activerecord/test/cases/defaults_test.rb +++ b/activerecord/test/cases/defaults_test.rb @@ -18,11 +18,43 @@ class DefaultTest < ActiveRecord::TestCase end end - if current_adapter?(:MysqlAdapter) + if current_adapter?(:PostgreSQLAdapter, :FirebirdAdapter, :OpenBaseAdapter, :OracleAdapter) + def test_default_integers + default = Default.new + assert_instance_of Fixnum, default.positive_integer + assert_equal 1, default.positive_integer + assert_instance_of Fixnum, default.negative_integer + assert_equal -1, default.negative_integer + assert_instance_of BigDecimal, default.decimal_number + assert_equal BigDecimal.new("2.78"), default.decimal_number + end + end + + if current_adapter?(:PostgreSQLAdapter) + def test_multiline_default_text + # older postgres versions represent the default with escapes ("\\012" for a newline) + assert ( "--- []\n\n" == Default.columns_hash['multiline_default'].default || + "--- []\\012\\012" == Default.columns_hash['multiline_default'].default) + end + end +end - #MySQL 5 and higher is quirky with not null text/blob columns. - #With MySQL Text/blob columns cannot have defaults. If the column is not null MySQL will report that the column has a null default - #but it behaves as though the column had a default of '' +if current_adapter?(:MysqlAdapter) + class DefaultsTestWithoutTransactionalFixtures < ActiveRecord::TestCase + # ActiveRecord::Base#create! (and #save and other related methods) will + # open a new transaction. When in transactional fixtures mode, this will + # cause ActiveRecord to create a new savepoint. However, since MySQL doesn't + # support DDL transactions, creating a table will result in any created + # savepoints to be automatically released. This in turn causes the savepoint + # release code in AbstractAdapter#transaction to fail. + # + # We don't want that to happen, so we disable transactional fixtures here. + self.use_transactional_fixtures = false + + # MySQL 5 and higher is quirky with not null text/blob columns. + # With MySQL Text/blob columns cannot have defaults. If the column is not + # null MySQL will report that the column has a null default + # but it behaves as though the column had a default of '' def test_mysql_text_not_null_defaults klass = Class.new(ActiveRecord::Base) klass.table_name = 'test_mysql_text_not_null_defaults' @@ -48,8 +80,7 @@ class DefaultTest < ActiveRecord::TestCase ensure klass.connection.drop_table(klass.table_name) rescue nil end - - + # MySQL uses an implicit default 0 rather than NULL unless in strict mode. # We use an implicit NULL so schema.rb is compatible with other databases. def test_mysql_integer_not_null_defaults @@ -77,24 +108,4 @@ class DefaultTest < ActiveRecord::TestCase klass.connection.drop_table(klass.table_name) rescue nil end end - - if current_adapter?(:PostgreSQLAdapter, :FirebirdAdapter, :OpenBaseAdapter, :OracleAdapter) - def test_default_integers - default = Default.new - assert_instance_of Fixnum, default.positive_integer - assert_equal 1, default.positive_integer - assert_instance_of Fixnum, default.negative_integer - assert_equal -1, default.negative_integer - assert_instance_of BigDecimal, default.decimal_number - assert_equal BigDecimal.new("2.78"), default.decimal_number - end - end - - if current_adapter?(:PostgreSQLAdapter) - def test_multiline_default_text - # older postgres versions represent the default with escapes ("\\012" for a newline) - assert ( "--- []\n\n" == Default.columns_hash['multiline_default'].default || - "--- []\\012\\012" == Default.columns_hash['multiline_default'].default) - end - end end diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb index 10cdbdc622..1c9e281cc0 100644 --- a/activerecord/test/cases/dirty_test.rb +++ b/activerecord/test/cases/dirty_test.rb @@ -21,6 +21,10 @@ private end end +class NumericData < ActiveRecord::Base + self.table_name = 'numeric_data' +end + class DirtyTest < ActiveRecord::TestCase def test_attribute_changes # New record - no changes. @@ -58,7 +62,7 @@ class DirtyTest < ActiveRecord::TestCase assert_equal parrot.name_change, parrot.title_change end - def test_nullable_integer_not_marked_as_changed_if_new_value_is_blank + def test_nullable_number_not_marked_as_changed_if_new_value_is_blank pirate = Pirate.new ["", nil].each do |value| @@ -68,6 +72,26 @@ class DirtyTest < ActiveRecord::TestCase end end + def test_nullable_decimal_not_marked_as_changed_if_new_value_is_blank + numeric_data = NumericData.new + + ["", nil].each do |value| + numeric_data.bank_balance = value + assert !numeric_data.bank_balance_changed? + assert_nil numeric_data.bank_balance_change + end + end + + def test_nullable_float_not_marked_as_changed_if_new_value_is_blank + numeric_data = NumericData.new + + ["", nil].each do |value| + numeric_data.temperature = value + assert !numeric_data.temperature_changed? + assert_nil numeric_data.temperature_change + end + end + def test_nullable_integer_zero_to_string_zero_not_marked_as_changed pirate = Pirate.new pirate.parrot_id = 0 diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb index 2043138ca3..24ce35e2e2 100644 --- a/activerecord/test/cases/helper.rb +++ b/activerecord/test/cases/helper.rb @@ -34,7 +34,7 @@ rescue LoadError end ActiveRecord::Base.connection.class.class_eval do - IGNORED_SQL = [/^PRAGMA/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/] + IGNORED_SQL = [/^PRAGMA/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/, /SHOW FIELDS/] def execute_with_query_record(sql, name = nil, &block) $queries_executed ||= [] diff --git a/activerecord/test/cases/json_serialization_test.rb b/activerecord/test/cases/json_serialization_test.rb index 3446e5e7f0..975acde096 100644 --- a/activerecord/test/cases/json_serialization_test.rb +++ b/activerecord/test/cases/json_serialization_test.rb @@ -200,6 +200,6 @@ class DatabaseConnectedJsonEncodingTest < ActiveRecord::TestCase 2 => @mary } - assert_equal %({1: {"name": "David"}}), authors_hash.to_json(:only => [1, :name]) + assert_equal %({"1": {"name": "David"}}), authors_hash.to_json(:only => [1, :name]) end end diff --git a/activerecord/test/cases/named_scope_test.rb b/activerecord/test/cases/named_scope_test.rb index 64e899780c..bab842cf66 100644 --- a/activerecord/test/cases/named_scope_test.rb +++ b/activerecord/test/cases/named_scope_test.rb @@ -254,7 +254,7 @@ class NamedScopeTest < ActiveRecord::TestCase end def test_should_use_where_in_query_for_named_scope - assert_equal Developer.find_all_by_name('Jamis'), Developer.find_all_by_id(Developer.jamises) + assert_equal Developer.find_all_by_name('Jamis').to_set, Developer.find_all_by_id(Developer.jamises).to_set end def test_size_should_use_count_when_results_are_not_loaded @@ -278,3 +278,23 @@ class NamedScopeTest < ActiveRecord::TestCase assert_equal post.comments.size, Post.scoped(:joins => join).scoped(:joins => join, :conditions => "posts.id = #{post.id}").size end end + +class DynamicScopeMatchTest < ActiveRecord::TestCase + def test_scoped_by_no_match + assert_nil ActiveRecord::DynamicScopeMatch.match("not_scoped_at_all") + end + + def test_scoped_by + match = ActiveRecord::DynamicScopeMatch.match("scoped_by_age_and_sex_and_location") + assert_not_nil match + assert match.scope? + assert_equal %w(age sex location), match.attribute_names + end +end + +class DynamicScopeTest < ActiveRecord::TestCase + def test_dynamic_scope + assert_equal Post.scoped_by_author_id(1).find(1), Post.find(1) + assert_equal Post.scoped_by_author_id_and_title(1, "Welcome to the weblog").first, Post.find(:first, :conditions => { :author_id => 1, :title => "Welcome to the weblog"}) + end +end diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb index b12ec36455..4a07a8bb1d 100644 --- a/activerecord/test/cases/transactions_test.rb +++ b/activerecord/test/cases/transactions_test.rb @@ -213,11 +213,104 @@ class TransactionTest < ActiveRecord::TestCase assert Topic.find(2).approved?, "Second should still be approved" end + def test_invalid_keys_for_transaction + assert_raises ArgumentError do + Topic.transaction :nested => true do + end + end + end + + def test_force_savepoint_in_nested_transaction + Topic.transaction do + @first.approved = true + @second.approved = false + @first.save! + @second.save! + + begin + Topic.transaction :requires_new => true do + @first.happy = false + @first.save! + raise + end + rescue + end + end + + assert @first.reload.approved? + assert !@second.reload.approved? + end if Topic.connection.supports_savepoints? + + def test_no_savepoint_in_nested_transaction_without_force + Topic.transaction do + @first.approved = true + @second.approved = false + @first.save! + @second.save! + + begin + Topic.transaction do + @first.approved = false + @first.save! + raise + end + rescue + end + end + + assert !@first.reload.approved? + assert !@second.reload.approved? + end if Topic.connection.supports_savepoints? + + def test_many_savepoints + Topic.transaction do + @first.content = "One" + @first.save! + + begin + Topic.transaction :requires_new => true do + @first.content = "Two" + @first.save! + + begin + Topic.transaction :requires_new => true do + @first.content = "Three" + @first.save! + + begin + Topic.transaction :requires_new => true do + @first.content = "Four" + @first.save! + raise + end + rescue + end + + @three = @first.reload.content + raise + end + rescue + end + + @two = @first.reload.content + raise + end + rescue + end + + @one = @first.reload.content + end + + assert_equal "One", @one + assert_equal "Two", @two + assert_equal "Three", @three + end if Topic.connection.supports_savepoints? + uses_mocha 'mocking connection.commit_db_transaction' do def test_rollback_when_commit_raises Topic.connection.expects(:begin_db_transaction) - Topic.connection.expects(:transaction_active?).returns(true) if current_adapter?(:PostgreSQLAdapter) Topic.connection.expects(:commit_db_transaction).raises('OH NOES') + Topic.connection.expects(:outside_transaction?).returns(false) Topic.connection.expects(:rollback_db_transaction) assert_raise RuntimeError do @@ -227,6 +320,38 @@ class TransactionTest < ActiveRecord::TestCase end end end + + if current_adapter?(:PostgreSQLAdapter) && defined?(PGconn::PQTRANS_IDLE) + def test_outside_transaction_works + assert Topic.connection.outside_transaction? + Topic.connection.begin_db_transaction + assert !Topic.connection.outside_transaction? + Topic.connection.rollback_db_transaction + assert Topic.connection.outside_transaction? + end + + uses_mocha 'mocking connection.rollback_db_transaction' do + def test_rollback_wont_be_executed_if_no_transaction_active + assert_raise RuntimeError do + Topic.transaction do + Topic.connection.rollback_db_transaction + Topic.connection.expects(:rollback_db_transaction).never + raise "Rails doesn't scale!" + end + end + end + end + + def test_open_transactions_count_is_reset_to_zero_if_no_transaction_active + Topic.transaction do + Topic.transaction do + Topic.connection.rollback_db_transaction + end + assert_equal 0, Topic.connection.open_transactions + end + assert_equal 0, Topic.connection.open_transactions + end + end def test_sqlite_add_column_in_transaction_raises_statement_invalid return true unless current_adapter?(:SQLite3Adapter, :SQLiteAdapter) @@ -282,6 +407,45 @@ class TransactionTest < ActiveRecord::TestCase end end +class TransactionsWithTransactionalFixturesTest < ActiveRecord::TestCase + self.use_transactional_fixtures = true + fixtures :topics + + def test_automatic_savepoint_in_outer_transaction + @first = Topic.find(1) + + begin + Topic.transaction do + @first.approved = true + @first.save! + raise + end + rescue + assert !@first.reload.approved? + end + end + + def test_no_automatic_savepoint_for_inner_transaction + @first = Topic.find(1) + + Topic.transaction do + @first.approved = true + @first.save! + + begin + Topic.transaction do + @first.approved = false + @first.save! + raise + end + rescue + end + end + + assert !@first.reload.approved? + end +end if Topic.connection.supports_savepoints? + if current_adapter?(:PostgreSQLAdapter) class ConcurrentTransactionTest < TransactionTest use_concurrent_connections diff --git a/activerecord/test/fixtures/people.yml b/activerecord/test/fixtures/people.yml index d5a69e561d..3babb1fe59 100644 --- a/activerecord/test/fixtures/people.yml +++ b/activerecord/test/fixtures/people.yml @@ -1,6 +1,15 @@ michael: id: 1 first_name: Michael + primary_contact_id: 2 + gender: M david: id: 2 - first_name: David
\ No newline at end of file + first_name: David + primary_contact_id: 3 + gender: M +susan: + id: 3 + first_name: Susan + primary_contact_id: 2 + gender: F
\ No newline at end of file diff --git a/activerecord/test/models/person.rb b/activerecord/test/models/person.rb index 430d0b38f7..ec2f684a6e 100644 --- a/activerecord/test/models/person.rb +++ b/activerecord/test/models/person.rb @@ -7,4 +7,10 @@ class Person < ActiveRecord::Base has_many :jobs, :through => :references has_one :favourite_reference, :class_name => 'Reference', :conditions => ['favourite=?', true] has_many :posts_with_comments_sorted_by_comment_id, :through => :readers, :source => :post, :include => :comments, :order => 'comments.id' + + belongs_to :primary_contact, :class_name => 'Person' + has_many :agents, :class_name => 'Person', :foreign_key => 'primary_contact_id' + + named_scope :males, :conditions => { :gender => 'M' } + named_scope :females, :conditions => { :gender => 'F' } end diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index fbacc692b4..094932d375 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -252,6 +252,7 @@ ActiveRecord::Schema.define do t.decimal :world_population, :precision => 10, :scale => 0 t.decimal :my_house_population, :precision => 2, :scale => 0 t.decimal :decimal_number_with_default, :precision => 3, :scale => 2, :default => 2.78 + t.float :temperature end create_table :orders, :force => true do |t| @@ -298,8 +299,10 @@ ActiveRecord::Schema.define do end create_table :people, :force => true do |t| - t.string :first_name, :null => false - t.integer :lock_version, :null => false, :default => 0 + t.string :first_name, :null => false + t.references :primary_contact + t.string :gender, :limit => 1 + t.integer :lock_version, :null => false, :default => 0 end create_table :pets, :primary_key => :pet_id ,:force => true do |t| |