diff options
Diffstat (limited to 'activerecord/test')
38 files changed, 852 insertions, 344 deletions
diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb index fc08c2178a..646aa88d80 100644 --- a/activerecord/test/cases/adapter_test.rb +++ b/activerecord/test/cases/adapter_test.rb @@ -65,15 +65,14 @@ class AdapterTest < ActiveRecord::TestCase end def test_not_specifying_database_name_for_cross_database_selects - assert_nothing_raised do - ActiveRecord::Base.establish_connection({ - :adapter => 'mysql', - :username => 'rails' - }) - ActiveRecord::Base.connection.execute "SELECT activerecord_unittest.pirates.*, activerecord_unittest2.courses.* FROM activerecord_unittest.pirates, activerecord_unittest2.courses" + begin + assert_nothing_raised do + ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['arunit'].except(:database)) + ActiveRecord::Base.connection.execute "SELECT activerecord_unittest.pirates.*, activerecord_unittest2.courses.* FROM activerecord_unittest.pirates, activerecord_unittest2.courses" + end + ensure + ActiveRecord::Base.establish_connection 'arunit' end - - ActiveRecord::Base.establish_connection 'arunit' end end diff --git a/activerecord/test/cases/connection_test_firebird.rb b/activerecord/test/cases/adapters/firebird/connection_test.rb index f57ea686a5..f57ea686a5 100644 --- a/activerecord/test/cases/connection_test_firebird.rb +++ b/activerecord/test/cases/adapters/firebird/connection_test.rb diff --git a/activerecord/test/cases/default_test_firebird.rb b/activerecord/test/cases/adapters/firebird/default_test.rb index 713c7e11bf..713c7e11bf 100644 --- a/activerecord/test/cases/default_test_firebird.rb +++ b/activerecord/test/cases/adapters/firebird/default_test.rb diff --git a/activerecord/test/cases/migration_test_firebird.rb b/activerecord/test/cases/adapters/firebird/migration_test.rb index 710661b9bd..710661b9bd 100644 --- a/activerecord/test/cases/migration_test_firebird.rb +++ b/activerecord/test/cases/adapters/firebird/migration_test.rb diff --git a/activerecord/test/cases/active_schema_test_mysql.rb b/activerecord/test/cases/adapters/mysql/active_schema_test.rb index d7431e5158..6e6645511c 100644 --- a/activerecord/test/cases/active_schema_test_mysql.rb +++ b/activerecord/test/cases/adapters/mysql/active_schema_test.rb @@ -17,8 +17,8 @@ class ActiveSchemaTest < ActiveRecord::TestCase end def test_add_index - # add_index calls index_exists? which can't work since execute is stubbed - ActiveRecord::ConnectionAdapters::MysqlAdapter.send(:define_method, :index_exists?) do |*| + # add_index calls index_name_exists? which can't work since execute is stubbed + ActiveRecord::ConnectionAdapters::MysqlAdapter.send(:define_method, :index_name_exists?) do |*| false end expected = "CREATE INDEX `index_people_on_last_name` ON `people` (`last_name`)" @@ -35,7 +35,7 @@ class ActiveSchemaTest < ActiveRecord::TestCase expected = "CREATE INDEX `index_people_on_last_name_and_first_name` ON `people` (`last_name`(15), `first_name`(10))" assert_equal expected, add_index(:people, [:last_name, :first_name], :length => {:last_name => 15, :first_name => 10}) - ActiveRecord::ConnectionAdapters::MysqlAdapter.send(:remove_method, :index_exists?) + ActiveRecord::ConnectionAdapters::MysqlAdapter.send(:remove_method, :index_name_exists?) end def test_drop_table diff --git a/activerecord/test/cases/connection_test_mysql.rb b/activerecord/test/cases/adapters/mysql/connection_test.rb index 8e4842a1b6..8e4842a1b6 100644 --- a/activerecord/test/cases/connection_test_mysql.rb +++ b/activerecord/test/cases/adapters/mysql/connection_test.rb diff --git a/activerecord/test/cases/reserved_word_test_mysql.rb b/activerecord/test/cases/adapters/mysql/reserved_word_test.rb index 90d8b0d923..90d8b0d923 100644 --- a/activerecord/test/cases/reserved_word_test_mysql.rb +++ b/activerecord/test/cases/adapters/mysql/reserved_word_test.rb diff --git a/activerecord/test/cases/synonym_test_oracle.rb b/activerecord/test/cases/adapters/oracle/synonym_test.rb index b9a422a6ca..b9a422a6ca 100644 --- a/activerecord/test/cases/synonym_test_oracle.rb +++ b/activerecord/test/cases/adapters/oracle/synonym_test.rb diff --git a/activerecord/test/cases/active_schema_test_postgresql.rb b/activerecord/test/cases/adapters/postgresql/active_schema_test.rb index 4f04c6735c..f106e14319 100644 --- a/activerecord/test/cases/active_schema_test_postgresql.rb +++ b/activerecord/test/cases/adapters/postgresql/active_schema_test.rb @@ -10,7 +10,10 @@ class PostgresqlActiveSchemaTest < Test::Unit::TestCase end def teardown - ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.send(:alias_method, :execute, :real_execute) + ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.class_eval do + remove_method :execute + alias_method :execute, :real_execute + end end def test_create_database_with_encoding diff --git a/activerecord/test/cases/datatype_test_postgresql.rb b/activerecord/test/cases/adapters/postgresql/datatype_test.rb index 3c2d9fb7bd..5bb8fa2f93 100644 --- a/activerecord/test/cases/datatype_test_postgresql.rb +++ b/activerecord/test/cases/adapters/postgresql/datatype_test.rb @@ -53,7 +53,7 @@ class PostgresqlDataTypeTest < ActiveRecord::TestCase @connection.execute("INSERT INTO postgresql_oids (obj_id) VALUES (1234)") @first_oid = PostgresqlOid.find(1) - + @connection.execute("INSERT INTO postgresql_timestamp_with_zones (time) VALUES ('2010-01-01 10:00:00-1')") end diff --git a/activerecord/test/cases/schema_authorization_test_postgresql.rb b/activerecord/test/cases/adapters/postgresql/schema_authorization_test.rb index 2860f1ad48..6f372edc38 100644 --- a/activerecord/test/cases/schema_authorization_test_postgresql.rb +++ b/activerecord/test/cases/adapters/postgresql/schema_authorization_test.rb @@ -66,7 +66,7 @@ class SchemaAuthorizationTest < ActiveRecord::TestCase end end end - + def test_tables_in_current_schemas assert !@connection.tables.include?(TABLE_NAME) USERS.each do |u| diff --git a/activerecord/test/cases/schema_test_postgresql.rb b/activerecord/test/cases/adapters/postgresql/schema_test.rb index 3ed9b1974d..a5c3e69af9 100644 --- a/activerecord/test/cases/schema_test_postgresql.rb +++ b/activerecord/test/cases/adapters/postgresql/schema_test.rb @@ -9,9 +9,11 @@ class SchemaTest < ActiveRecord::TestCase CAPITALIZED_TABLE_NAME = 'Things' INDEX_A_NAME = 'a_index_things_on_name' INDEX_B_NAME = 'b_index_things_on_different_columns_in_each_schema' + INDEX_C_NAME = 'c_index_full_text_search' INDEX_A_COLUMN = 'name' INDEX_B_COLUMN_S1 = 'email' INDEX_B_COLUMN_S2 = 'moment' + INDEX_C_COLUMN = %q{(to_tsvector('english', coalesce(things.name, '')))} COLUMNS = [ 'id integer', 'name character varying(50)', @@ -45,6 +47,8 @@ class SchemaTest < ActiveRecord::TestCase @connection.execute "CREATE INDEX #{INDEX_A_NAME} ON #{SCHEMA2_NAME}.#{TABLE_NAME} USING btree (#{INDEX_A_COLUMN});" @connection.execute "CREATE INDEX #{INDEX_B_NAME} ON #{SCHEMA_NAME}.#{TABLE_NAME} USING btree (#{INDEX_B_COLUMN_S1});" @connection.execute "CREATE INDEX #{INDEX_B_NAME} ON #{SCHEMA2_NAME}.#{TABLE_NAME} USING btree (#{INDEX_B_COLUMN_S2});" + @connection.execute "CREATE INDEX #{INDEX_C_NAME} ON #{SCHEMA_NAME}.#{TABLE_NAME} USING gin (#{INDEX_C_COLUMN});" + @connection.execute "CREATE INDEX #{INDEX_C_NAME} ON #{SCHEMA2_NAME}.#{TABLE_NAME} USING gin (#{INDEX_C_COLUMN});" end def teardown diff --git a/activerecord/test/cases/copy_table_test_sqlite.rb b/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb index 575b4806c1..575b4806c1 100644 --- a/activerecord/test/cases/copy_table_test_sqlite.rb +++ b/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb new file mode 100644 index 0000000000..934cf72f72 --- /dev/null +++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb @@ -0,0 +1,56 @@ +require "cases/helper" + +module ActiveRecord + module ConnectionAdapters + class SQLite3AdapterTest < ActiveRecord::TestCase + def test_connection_no_db + assert_raises(ArgumentError) do + Base.sqlite3_connection {} + end + end + + def test_connection_no_adapter + assert_raises(ArgumentError) do + Base.sqlite3_connection :database => ':memory:' + end + end + + def test_connection_wrong_adapter + assert_raises(ArgumentError) do + Base.sqlite3_connection :database => ':memory:',:adapter => 'vuvuzela' + end + end + + def test_bad_timeout + assert_raises(TypeError) do + Base.sqlite3_connection :database => ':memory:', + :adapter => 'sqlite3', + :timeout => 'usa' + end + end + + # connection is OK with a nil timeout + def test_nil_timeout + conn = Base.sqlite3_connection :database => ':memory:', + :adapter => 'sqlite3', + :timeout => nil + assert conn, 'made a connection' + end + + def test_connect + conn = Base.sqlite3_connection :database => ':memory:', + :adapter => 'sqlite3', + :timeout => 100 + assert conn, 'should have connection' + end + + # sqlite3 defaults to UTF-8 encoding + def test_encoding + conn = Base.sqlite3_connection :database => ':memory:', + :adapter => 'sqlite3', + :timeout => 100 + assert_equal 'UTF-8', conn.encoding + end + end + end +end diff --git a/activerecord/test/cases/aggregations_test.rb b/activerecord/test/cases/aggregations_test.rb index e5fc1a2046..74588b4f47 100644 --- a/activerecord/test/cases/aggregations_test.rb +++ b/activerecord/test/cases/aggregations_test.rb @@ -121,34 +121,6 @@ class AggregationsTest < ActiveRecord::TestCase end end -class DeprecatedAggregationsTest < ActiveRecord::TestCase - class Person < ActiveRecord::Base; end - - def test_conversion_block_is_deprecated - assert_deprecated 'conversion block has been deprecated' do - Person.composed_of(:balance, :class_name => "Money", :mapping => %w(balance amount)) { |balance| balance.to_money } - end - end - - def test_conversion_block_used_when_converter_option_is_nil - assert_deprecated 'conversion block has been deprecated' do - Person.composed_of(:balance, :class_name => "Money", :mapping => %w(balance amount)) { |balance| balance.to_money } - end - assert_raise(NoMethodError) { Person.new.balance = 5 } - end - - def test_converter_option_overrides_conversion_block - assert_deprecated 'conversion block has been deprecated' do - Person.composed_of(:balance, :class_name => "Money", :mapping => %w(balance amount), :converter => Proc.new { |balance| Money.new(balance) }) { |balance| balance.to_money } - end - - person = Person.new - assert_nothing_raised { person.balance = 5 } - assert_equal 5, person.balance.amount - assert_kind_of Money, person.balance - end -end - class OverridingAggregationsTest < ActiveRecord::TestCase class Name; end class DifferentName; end diff --git a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb index 050b730dda..9c5dcc2ad9 100644 --- a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb +++ b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb @@ -41,9 +41,9 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase def test_eager_association_loading_grafts_stashed_associations_to_correct_parent assert_nothing_raised do - Person.eager_load(:primary_contact => :primary_contact).where('primary_contacts_people_2.first_name = ?', 'Susan').order('primary_contacts_people_2.id').all + Person.eager_load(:primary_contact => :primary_contact).where('primary_contacts_people_2.first_name = ?', 'Susan').order('people.id').all end - assert_equal people(:michael), Person.eager_load(:primary_contact => :primary_contact).where('primary_contacts_people_2.first_name = ?', 'Susan').order('primary_contacts_people_2.id').first + assert_equal people(:michael), Person.eager_load(:primary_contact => :primary_contact).where('primary_contacts_people_2.first_name = ?', 'Susan').order('people.id').first end def test_eager_association_loading_with_cascaded_two_levels_with_two_has_many_associations diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index 45c7498013..5e3ba778f3 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -21,6 +21,68 @@ class HasManyAssociationsTest < ActiveRecord::TestCase Client.destroyed_client_ids.clear end + def test_create_by + person = Person.create! :first_name => 'tenderlove' + post = Post.find :first + + assert_equal [], person.readers + assert_nil person.readers.find_by_post_id post.id + + reader = person.readers.create_by_post_id post.id + + assert_equal 1, person.readers.count + assert_equal 1, person.readers.length + assert_equal post, person.readers.first.post + assert_equal person, person.readers.first.person + end + + def test_create_by_multi + person = Person.create! :first_name => 'tenderlove' + post = Post.find :first + + assert_equal [], person.readers + + reader = person.readers.create_by_post_id_and_skimmer post.id, false + + assert_equal 1, person.readers.count + assert_equal 1, person.readers.length + assert_equal post, person.readers.first.post + assert_equal person, person.readers.first.person + end + + def test_find_or_create_by + person = Person.create! :first_name => 'tenderlove' + post = Post.find :first + + assert_equal [], person.readers + assert_nil person.readers.find_by_post_id post.id + + reader = person.readers.find_or_create_by_post_id post.id + + assert_equal 1, person.readers.count + assert_equal 1, person.readers.length + assert_equal post, person.readers.first.post + assert_equal person, person.readers.first.person + end + + def test_find_or_create + person = Person.create! :first_name => 'tenderlove' + post = Post.find :first + + assert_equal [], person.readers + assert_nil person.readers.find(:first, :conditions => { + :post_id => post.id + }) + + reader = person.readers.find_or_create :post_id => post.id + + assert_equal 1, person.readers.count + assert_equal 1, person.readers.length + assert_equal post, person.readers.first.post + assert_equal person, person.readers.first.person + end + + def force_signal37_to_load_all_clients_of_firm companies(:first_firm).clients_of_firm.each {|f| } end diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb index 4e4f9c385c..3b89c12a3f 100644 --- a/activerecord/test/cases/autosave_association_test.rb +++ b/activerecord/test/cases/autosave_association_test.rb @@ -712,7 +712,6 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase end assert_raise(RuntimeError) { assert !@pirate.save } - assert before.first.frozen? # the first child was indeed destroyed assert_equal before, @pirate.reload.send(association_name) end diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index 5c175de6d4..ba7db838ca 100755..100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -798,25 +798,6 @@ class BasicsTest < ActiveRecord::TestCase assert_raise(NoMethodError) { t.title2 } end - def test_class_name - assert_equal "Firm", ActiveRecord::Base.class_name("firms") - assert_equal "Category", ActiveRecord::Base.class_name("categories") - assert_equal "AccountHolder", ActiveRecord::Base.class_name("account_holder") - - ActiveRecord::Base.pluralize_table_names = false - assert_equal "Firms", ActiveRecord::Base.class_name( "firms" ) - ActiveRecord::Base.pluralize_table_names = true - - ActiveRecord::Base.table_name_prefix = "test_" - assert_equal "Firm", ActiveRecord::Base.class_name( "test_firms" ) - ActiveRecord::Base.table_name_suffix = "_tests" - assert_equal "Firm", ActiveRecord::Base.class_name( "test_firms_tests" ) - ActiveRecord::Base.table_name_prefix = "" - assert_equal "Firm", ActiveRecord::Base.class_name( "firms_tests" ) - ActiveRecord::Base.table_name_suffix = "" - assert_equal "Firm", ActiveRecord::Base.class_name( "firms" ) - end - def test_null_fields assert_nil Topic.find(1).parent_id assert_nil Topic.create("title" => "Hey you").parent_id @@ -1401,6 +1382,14 @@ class BasicsTest < ActiveRecord::TestCase assert_not_equal clone.id, dev.id end + def test_clone_does_not_clone_associations + author = authors(:david) + assert_not_equal [], author.posts + + author_clone = author.clone + assert_equal [], author_clone.posts + end + def test_clone_preserves_subtype clone = nil assert_nothing_raised { clone = Company.find(3).clone } @@ -2076,10 +2065,6 @@ class BasicsTest < ActiveRecord::TestCase assert !SubStiPost.descends_from_active_record? end - def test_base_subclasses_is_public_method - assert ActiveRecord::Base.public_methods.map(&:to_sym).include?(:subclasses) - end - def test_find_on_abstract_base_class_doesnt_use_type_condition old_class = LooseDescendant Object.send :remove_const, :LooseDescendant @@ -2239,7 +2224,7 @@ class BasicsTest < ActiveRecord::TestCase def test_inspect_instance topic = topics(:first) - assert_equal %(#<Topic id: 1, title: "The First Topic", author_name: "David", author_email_address: "david@loudthinking.com", written_on: "#{topic.written_on.to_s(:db)}", bonus_time: "#{topic.bonus_time.to_s(:db)}", last_read: "#{topic.last_read.to_s(:db)}", content: "Have a nice day", approved: false, replies_count: 1, parent_id: nil, parent_title: nil, type: nil>), topic.inspect + assert_equal %(#<Topic id: 1, title: "The First Topic", author_name: "David", author_email_address: "david@loudthinking.com", written_on: "#{topic.written_on.to_s(:db)}", bonus_time: "#{topic.bonus_time.to_s(:db)}", last_read: "#{topic.last_read.to_s(:db)}", content: "Have a nice day", approved: false, replies_count: 1, parent_id: nil, parent_title: nil, type: nil, group: nil>), topic.inspect end def test_inspect_new_instance diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index 329dd7d761..2c9d23c80f 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -272,7 +272,7 @@ class CalculationsTest < ActiveRecord::TestCase end def test_count_with_column_and_options_parameter - assert_equal 2, Account.count(:firm_id, :conditions => "credit_limit = 50") + assert_equal 2, Account.count(:firm_id, :conditions => "credit_limit = 50 AND firm_id IS NOT NULL") end def test_count_with_no_parameters_isnt_deprecated diff --git a/activerecord/test/cases/counter_cache_test.rb b/activerecord/test/cases/counter_cache_test.rb index 377de168b9..377de168b9 100755..100644 --- a/activerecord/test/cases/counter_cache_test.rb +++ b/activerecord/test/cases/counter_cache_test.rb diff --git a/activerecord/test/cases/inheritance_test.rb b/activerecord/test/cases/inheritance_test.rb index c1c8f01e46..8c09fc4d59 100644 --- a/activerecord/test/cases/inheritance_test.rb +++ b/activerecord/test/cases/inheritance_test.rb @@ -173,7 +173,7 @@ class InheritanceTest < ActiveRecord::TestCase def test_complex_inheritance very_special_client = VerySpecialClient.create("name" => "veryspecial") - assert_equal very_special_client, VerySpecialClient.find(:first, :conditions => "name = 'veryspecial'") + assert_equal very_special_client, VerySpecialClient.where("name = 'veryspecial'").first assert_equal very_special_client, SpecialClient.find(:first, :conditions => "name = 'veryspecial'") assert_equal very_special_client, Company.find(:first, :conditions => "name = 'veryspecial'") assert_equal very_special_client, Client.find(:first, :conditions => "name = 'veryspecial'") diff --git a/activerecord/test/cases/log_subscriber_test.rb b/activerecord/test/cases/log_subscriber_test.rb index 1f544b4211..4aeae1fe45 100644 --- a/activerecord/test/cases/log_subscriber_test.rb +++ b/activerecord/test/cases/log_subscriber_test.rb @@ -1,20 +1,19 @@ require "cases/helper" require "models/developer" -require "rails/log_subscriber/test_helper" -require "active_record/railties/log_subscriber" +require "active_support/log_subscriber/test_helper" class LogSubscriberTest < ActiveSupport::TestCase - include Rails::LogSubscriber::TestHelper + include ActiveSupport::LogSubscriber::TestHelper def setup @old_logger = ActiveRecord::Base.logger super - - Rails::LogSubscriber.add(:active_record, ActiveRecord::Railties::LogSubscriber.new) + ActiveRecord::LogSubscriber.attach_to(:active_record) end def teardown super + ActiveRecord::LogSubscriber.log_subscribers.pop ActiveRecord::Base.logger = @old_logger end diff --git a/activerecord/test/cases/method_scoping_test.rb b/activerecord/test/cases/method_scoping_test.rb index e93f22bede..4e8ce1dac1 100644 --- a/activerecord/test/cases/method_scoping_test.rb +++ b/activerecord/test/cases/method_scoping_test.rb @@ -1,3 +1,7 @@ +# This file can be removed once with_exclusive_scope and with_scope are removed. +# All the tests were already ported to relation_scoping_test.rb when the new +# relation scoping API was added. + require "cases/helper" require 'models/post' require 'models/author' @@ -77,11 +81,13 @@ class MethodScopingTest < ActiveRecord::TestCase end end - def test_options_select_replaces_scope_select - Developer.send(:with_scope, :find => { :select => "id, name" }) do + def test_scope_select_concatenates + Developer.send(:with_scope, :find => { :select => "name" }) do developer = Developer.find(:first, :select => 'id, salary', :conditions => "name = 'David'") assert_equal 80000, developer.salary - assert !developer.has_attribute?(:name) + assert developer.has_attribute?(:id) + assert developer.has_attribute?(:name) + assert developer.has_attribute?(:salary) end end @@ -281,6 +287,12 @@ class NestedScopingTest < ActiveRecord::TestCase end end + def test_with_exclusive_scope_with_relation + assert_raise(ArgumentError) do + Developer.all_johns + end + end + def test_append_conditions Developer.send(:with_scope, :find => { :conditions => "name = 'David'" }) do Developer.send(:with_scope, :find => { :conditions => 'salary = 80000' }) do @@ -531,205 +543,4 @@ class NestedScopingTest < ActiveRecord::TestCase assert_equal 1, scoped_authors.size assert_equal authors(:david).attributes, scoped_authors.first.attributes end -end - -class HasManyScopingTest< ActiveRecord::TestCase - fixtures :comments, :posts - - def setup - @welcome = Post.find(1) - end - - def test_forwarding_of_static_methods - assert_equal 'a comment...', Comment.what_are_you - assert_equal 'a comment...', @welcome.comments.what_are_you - end - - def test_forwarding_to_scoped - assert_equal 4, Comment.search_by_type('Comment').size - assert_equal 2, @welcome.comments.search_by_type('Comment').size - end - - def test_forwarding_to_dynamic_finders - assert_equal 4, Comment.find_all_by_type('Comment').size - assert_equal 2, @welcome.comments.find_all_by_type('Comment').size - end - - def test_nested_scope - Comment.send(:with_scope, :find => { :conditions => '1=1' }) do - assert_equal 'a comment...', @welcome.comments.what_are_you - end - end -end - -class HasAndBelongsToManyScopingTest< ActiveRecord::TestCase - fixtures :posts, :categories, :categories_posts - - def setup - @welcome = Post.find(1) - end - - def test_forwarding_of_static_methods - assert_equal 'a category...', Category.what_are_you - assert_equal 'a category...', @welcome.categories.what_are_you - end - - def test_forwarding_to_dynamic_finders - assert_equal 4, Category.find_all_by_type('SpecialCategory').size - assert_equal 0, @welcome.categories.find_all_by_type('SpecialCategory').size - assert_equal 2, @welcome.categories.find_all_by_type('Category').size - end - - def test_nested_scope - Category.send(:with_scope, :find => { :conditions => '1=1' }) do - assert_equal 'a comment...', @welcome.comments.what_are_you - end - end -end - -class DefaultScopingTest < ActiveRecord::TestCase - fixtures :developers, :posts - - def test_default_scope - expected = Developer.find(:all, :order => 'salary DESC').collect { |dev| dev.salary } - received = DeveloperOrderedBySalary.find(:all).collect { |dev| dev.salary } - assert_equal expected, received - end - - def test_default_scope_with_conditions_string - assert_equal Developer.find_all_by_name('David').map(&:id).sort, DeveloperCalledDavid.find(:all).map(&:id).sort - assert_equal nil, DeveloperCalledDavid.create!.name - end - - def test_default_scope_with_conditions_hash - assert_equal Developer.find_all_by_name('Jamis').map(&:id).sort, DeveloperCalledJamis.find(:all).map(&:id).sort - assert_equal 'Jamis', DeveloperCalledJamis.create!.name - end - - def test_default_scoping_with_threads - 2.times do - Thread.new { assert_equal ['salary DESC'], DeveloperOrderedBySalary.scoped.order_values }.join - end - end - - def test_default_scoping_with_inheritance - # Inherit a class having a default scope and define a new default scope - klass = Class.new(DeveloperOrderedBySalary) - klass.send :default_scope, :limit => 1 - - # Scopes added on children should append to parent scope - assert_equal 1, klass.scoped.limit_value - assert_equal ['salary DESC'], klass.scoped.order_values - - # Parent should still have the original scope - assert_nil DeveloperOrderedBySalary.scoped.limit_value - assert_equal ['salary DESC'], DeveloperOrderedBySalary.scoped.order_values - end - - def test_default_scope_called_twice_merges_conditions - Developer.destroy_all - Developer.create!(:name => "David", :salary => 80000) - Developer.create!(:name => "David", :salary => 100000) - Developer.create!(:name => "Brian", :salary => 100000) - - klass = Class.new(Developer) - klass.__send__ :default_scope, :conditions => { :name => "David" } - klass.__send__ :default_scope, :conditions => { :salary => 100000 } - assert_equal 1, klass.count - assert_equal "David", klass.first.name - assert_equal 100000, klass.first.salary - end - def test_method_scope - expected = Developer.find(:all, :order => 'name DESC').collect { |dev| dev.salary } - received = DeveloperOrderedBySalary.all_ordered_by_name.collect { |dev| dev.salary } - assert_equal expected, received - end - - def test_nested_scope - expected = Developer.find(:all, :order => 'name DESC').collect { |dev| dev.salary } - received = DeveloperOrderedBySalary.send(:with_scope, :find => { :order => 'name DESC'}) do - DeveloperOrderedBySalary.find(:all).collect { |dev| dev.salary } - end - assert_equal expected, received - end - - def test_named_scope_overwrites_default - expected = Developer.find(:all, :order => 'name DESC').collect { |dev| dev.name } - received = DeveloperOrderedBySalary.by_name.find(:all).collect { |dev| dev.name } - assert_equal expected, received - end - - def test_nested_exclusive_scope - expected = Developer.find(:all, :limit => 100).collect { |dev| dev.salary } - received = DeveloperOrderedBySalary.send(:with_exclusive_scope, :find => { :limit => 100 }) do - DeveloperOrderedBySalary.find(:all).collect { |dev| dev.salary } - end - assert_equal expected, received - end - - def test_overwriting_default_scope - expected = Developer.find(:all, :order => 'salary').collect { |dev| dev.salary } - received = DeveloperOrderedBySalary.find(:all, :order => 'salary').collect { |dev| dev.salary } - assert_equal expected, received - end - - def test_default_scope_using_relation - posts = PostWithComment.scoped - assert_equal 2, posts.count - assert_equal posts(:thinking), posts.first - end - - def test_create_attribute_overwrites_default_scoping - assert_equal 'David', PoorDeveloperCalledJamis.create!(:name => 'David').name - assert_equal 200000, PoorDeveloperCalledJamis.create!(:name => 'David', :salary => 200000).salary - end - - def test_create_attribute_overwrites_default_values - assert_equal nil, PoorDeveloperCalledJamis.create!(:salary => nil).salary - assert_equal 50000, PoorDeveloperCalledJamis.create!(:name => 'David').salary - end -end - -=begin -# We disabled the scoping for has_one and belongs_to as we can't think of a proper use case - -class BelongsToScopingTest< ActiveRecord::TestCase - fixtures :comments, :posts - - def setup - @greetings = Comment.find(1) - end - - def test_forwarding_of_static_method - assert_equal 'a post...', Post.what_are_you - assert_equal 'a post...', @greetings.post.what_are_you - end - - def test_forwarding_to_dynamic_finders - assert_equal 4, Post.find_all_by_type('Post').size - assert_equal 1, @greetings.post.find_all_by_type('Post').size - end - -end - -class HasOneScopingTest< ActiveRecord::TestCase - fixtures :comments, :posts - - def setup - @sti_comments = Post.find(4) - end - - def test_forwarding_of_static_methods - assert_equal 'a comment...', Comment.what_are_you - assert_equal 'a very special comment...', @sti_comments.very_special_comment.what_are_you - end - - def test_forwarding_to_dynamic_finders - assert_equal 1, Comment.find_all_by_type('VerySpecialComment').size - assert_equal 1, @sti_comments.very_special_comment.find_all_by_type('VerySpecialComment').size - assert_equal 0, @sti_comments.very_special_comment.find_all_by_type('Comment').size - end - -end - -=end +end
\ No newline at end of file diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index 6fe3b01281..4ce9bdb46d 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -128,9 +128,9 @@ if ActiveRecord::Base.connection.supports_migrations? good_index_name = 'x' * Person.connection.index_name_length too_long_index_name = good_index_name + 'x' assert_nothing_raised { Person.connection.add_index("people", "first_name", :name => too_long_index_name) } - assert !Person.connection.index_exists?("people", too_long_index_name, false) + assert !Person.connection.index_name_exists?("people", too_long_index_name, false) assert_nothing_raised { Person.connection.add_index("people", "first_name", :name => good_index_name) } - assert Person.connection.index_exists?("people", good_index_name, false) + assert Person.connection.index_name_exists?("people", good_index_name, false) end def test_remove_nonexistent_index @@ -146,8 +146,8 @@ if ActiveRecord::Base.connection.supports_migrations? Person.connection.add_index('people', [:first_name], :name => 'old_idx') assert_nothing_raised { Person.connection.rename_index('people', 'old_idx', 'new_idx') } # if the adapter doesn't support the indexes call, pick defaults that let the test pass - assert !Person.connection.index_exists?('people', 'old_idx', false) - assert Person.connection.index_exists?('people', 'new_idx', true) + assert !Person.connection.index_name_exists?('people', 'old_idx', false) + assert Person.connection.index_name_exists?('people', 'new_idx', true) end end @@ -158,6 +158,53 @@ if ActiveRecord::Base.connection.supports_migrations? end end + def test_index_exists + Person.connection.create_table :testings do |t| + t.column :foo, :string, :limit => 100 + t.column :bar, :string, :limit => 100 + end + Person.connection.add_index :testings, :foo + + assert Person.connection.index_exists?(:testings, :foo) + assert !Person.connection.index_exists?(:testings, :bar) + ensure + Person.connection.drop_table :testings rescue nil + end + + def test_index_exists_on_multiple_columns + Person.connection.create_table :testings do |t| + t.column :foo, :string, :limit => 100 + t.column :bar, :string, :limit => 100 + end + Person.connection.add_index :testings, [:foo, :bar] + + assert Person.connection.index_exists?(:testings, [:foo, :bar]) + ensure + Person.connection.drop_table :testings rescue nil + end + + def test_unique_index_exists + Person.connection.create_table :testings do |t| + t.column :foo, :string, :limit => 100 + end + Person.connection.add_index :testings, :foo, :unique => true + + assert Person.connection.index_exists?(:testings, :foo, :unique => true) + ensure + Person.connection.drop_table :testings rescue nil + end + + def test_named_index_exists + Person.connection.create_table :testings do |t| + t.column :foo, :string, :limit => 100 + end + Person.connection.add_index :testings, :foo, :name => "custom_index_name" + + assert Person.connection.index_exists?(:testings, :foo, :name => "custom_index_name") + ensure + Person.connection.drop_table :testings rescue nil + end + def testing_table_with_only_foo_attribute Person.connection.create_table :testings, :id => false do |t| t.column :foo, :string @@ -748,6 +795,10 @@ if ActiveRecord::Base.connection.supports_migrations? ActiveRecord::Base.connection.drop_table(:hats) end + def test_remove_column_no_second_parameter_raises_exception + assert_raise(ArgumentError) { Person.connection.remove_column("funny") } + end + def test_change_type_of_not_null_column assert_nothing_raised do Topic.connection.change_column "topics", "written_on", :datetime, :null => false @@ -970,6 +1021,45 @@ if ActiveRecord::Base.connection.supports_migrations? assert_nil Person.new.first_name end + def test_column_exists + Person.connection.create_table :testings do |t| + t.column :foo, :string + end + + assert Person.connection.column_exists?(:testings, :foo) + assert !Person.connection.column_exists?(:testings, :bar) + ensure + Person.connection.drop_table :testings rescue nil + end + + def test_column_exists_with_type + Person.connection.create_table :testings do |t| + t.column :foo, :string + t.column :bar, :decimal, :precision => 8, :scale => 2 + end + + assert Person.connection.column_exists?(:testings, :foo, :string) + assert !Person.connection.column_exists?(:testings, :foo, :integer) + assert Person.connection.column_exists?(:testings, :bar, :decimal) + assert !Person.connection.column_exists?(:testings, :bar, :integer) + ensure + Person.connection.drop_table :testings rescue nil + end + + def test_column_exists_with_definition + Person.connection.create_table :testings do |t| + t.column :foo, :string, :limit => 100 + t.column :bar, :decimal, :precision => 8, :scale => 2 + end + + assert Person.connection.column_exists?(:testings, :foo, :string, :limit => 100) + assert !Person.connection.column_exists?(:testings, :foo, :string, :limit => 50) + assert Person.connection.column_exists?(:testings, :bar, :decimal, :precision => 8, :scale => 2) + assert !Person.connection.column_exists?(:testings, :bar, :decimal, :precision => 10, :scale => 2) + ensure + Person.connection.drop_table :testings rescue nil + end + def test_add_table assert !Reminder.table_exists? @@ -1531,6 +1621,23 @@ if ActiveRecord::Base.connection.supports_migrations? end end + class ReservedWordsMigrationTest < ActiveRecord::TestCase + def test_drop_index_from_table_named_values + connection = Person.connection + connection.create_table :values, :force => true do |t| + t.integer :value + end + + assert_nothing_raised do + connection.add_index :values, :value + connection.remove_index :values, :column => :value + end + + connection.drop_table :values rescue nil + end + end + + class ChangeTableMigrationsTest < ActiveRecord::TestCase def setup @connection = Person.connection @@ -1680,6 +1787,20 @@ if ActiveRecord::Base.connection.supports_migrations? end end + def test_index_exists + with_change_table do |t| + @connection.expects(:index_exists?).with(:delete_me, :bar, {}) + t.index_exists?(:bar) + end + end + + def test_index_exists_with_options + with_change_table do |t| + @connection.expects(:index_exists?).with(:delete_me, :bar, {:unique => true}) + t.index_exists?(:bar, :unique => true) + end + end + def test_change_changes_column with_change_table do |t| @connection.expects(:change_column).with(:delete_me, :bar, :string, {}) diff --git a/activerecord/test/cases/named_scope_test.rb b/activerecord/test/cases/named_scope_test.rb index 33ffb041c1..dc85b395d3 100644 --- a/activerecord/test/cases/named_scope_test.rb +++ b/activerecord/test/cases/named_scope_test.rb @@ -54,8 +54,8 @@ class NamedScopeTest < ActiveRecord::TestCase end def test_respond_to_respects_include_private_parameter - assert !Topic.approved.respond_to?(:with_create_scope) - assert Topic.approved.respond_to?(:with_create_scope, true) + assert !Topic.approved.respond_to?(:tables_in_string) + assert Topic.approved.respond_to?(:tables_in_string, true) end def test_subclasses_inherit_scopes @@ -450,6 +450,12 @@ class NamedScopeTest < ActiveRecord::TestCase assert before.object_id != post.comments.containing_the_letter_e.object_id, "AssociationCollection##{method} should reset the named scopes cache" end end + + def test_named_scoped_are_lazy_loaded_if_table_still_does_not_exist + assert_nothing_raised do + require "models/without_table" + end + end end class DynamicScopeMatchTest < ActiveRecord::TestCase diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb index 685b11cb03..3c797076e0 100644 --- a/activerecord/test/cases/nested_attributes_test.rb +++ b/activerecord/test/cases/nested_attributes_test.rb @@ -176,12 +176,6 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name end - def test_should_raise_RecordNotFound_if_an_id_is_given_but_doesnt_return_a_record - assert_raise_with_message ActiveRecord::RecordNotFound, "Couldn't find Ship with ID=1234567890 for Pirate with ID=#{@pirate.id}" do - @pirate.ship_attributes = { :id => 1234567890 } - end - end - def test_should_take_a_hash_with_string_keys_and_update_the_associated_model @pirate.reload.ship_attributes = { 'id' => @ship.id, 'name' => 'Davy Jones Gold Dagger' } @@ -331,11 +325,14 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase assert_equal 'Arr', @ship.pirate.catchphrase end - def test_should_raise_RecordNotFound_if_an_id_is_given_but_doesnt_return_a_record - assert_raise_with_message ActiveRecord::RecordNotFound, "Couldn't find Pirate with ID=1234567890 for Ship with ID=#{@ship.id}" do - @ship.pirate_attributes = { :id => 1234567890 } - end - end + def test_should_associate_with_record_if_parent_record_is_not_saved + @ship.destroy + @pirate = Pirate.create(:catchphrase => 'Arr') + @ship = Ship.new(:name => 'Nights Dirty Lightning', :pirate_attributes => { :id => @pirate.id, :catchphrase => @pirate.catchphrase}) + + assert_equal @ship.name, 'Nights Dirty Lightning' + assert_equal @pirate, @ship.pirate + end def test_should_take_a_hash_with_string_keys_and_update_the_associated_model @ship.reload.pirate_attributes = { 'id' => @pirate.id, 'catchphrase' => 'Arr' } @@ -444,6 +441,11 @@ module NestedAttributesOnACollectionAssociationTests assert_equal ['Grace OMalley', 'Privateers Greed'], [@child_1.reload.name, @child_2.reload.name] end + def test_should_assign_existing_children_if_parent_is_new + @pirate = Pirate.new({:catchphrase => "Don' botharr talkin' like one, savvy?"}.merge(@alternate_params)) + assert_equal ['Grace OMalley', 'Privateers Greed'], [@pirate.send(@association_name)[0].name, @pirate.send(@association_name)[1].name] + end + def test_should_also_work_with_a_HashWithIndifferentAccess @pirate.send(association_setter, HashWithIndifferentAccess.new('foo' => HashWithIndifferentAccess.new(:id => @child_1.id, :name => 'Grace OMalley'))) @pirate.save @@ -466,6 +468,27 @@ module NestedAttributesOnACollectionAssociationTests assert_equal 'Grace OMalley', @child_1.reload.name end + def test_should_not_overwrite_unsaved_updates_when_loading_association + @pirate.reload + @pirate.send(association_setter, [{ :id => @child_1.id, :name => 'Grace OMalley' }]) + assert_equal 'Grace OMalley', @pirate.send(@association_name).send(:load_target).find { |r| r.id == @child_1.id }.name + end + + def test_should_preserve_order_when_not_overwriting_unsaved_updates + @pirate.reload + @pirate.send(association_setter, [{ :id => @child_1.id, :name => 'Grace OMalley' }]) + assert_equal @child_1.id, @pirate.send(@association_name).send(:load_target).first.id + end + + def test_should_refresh_saved_records_when_not_overwriting_unsaved_updates + @pirate.reload + record = @pirate.class.reflect_on_association(@association_name).klass.new(:name => 'Grace OMalley') + @pirate.send(@association_name) << record + record.save! + @pirate.send(@association_name).last.update_attributes!(:name => 'Polly') + assert_equal 'Polly', @pirate.send(@association_name).send(:load_target).last.name + end + def test_should_take_a_hash_with_composite_id_keys_and_assign_the_attributes_to_the_associated_models @child_1.stubs(:id).returns('ABC1X') @child_2.stubs(:id).returns('ABC2X') @@ -480,8 +503,8 @@ module NestedAttributesOnACollectionAssociationTests assert_equal ['Grace OMalley', 'Privateers Greed'], [@child_1.name, @child_2.name] end - def test_should_raise_RecordNotFound_if_an_id_is_given_but_doesnt_return_a_record - assert_raise_with_message ActiveRecord::RecordNotFound, "Couldn't find #{@child_1.class.name} with ID=1234567890 for Pirate with ID=#{@pirate.id}" do + def test_should_not_raise_RecordNotFound_if_an_id_is_given_but_doesnt_return_a_record + assert_nothing_raised ActiveRecord::RecordNotFound do @pirate.attributes = { association_getter => [{ :id => 1234567890 }] } end end diff --git a/activerecord/test/cases/reflection_test.rb b/activerecord/test/cases/reflection_test.rb index 67818622d7..03c4fc4e80 100644 --- a/activerecord/test/cases/reflection_test.rb +++ b/activerecord/test/cases/reflection_test.rb @@ -24,25 +24,25 @@ class ReflectionTest < ActiveRecord::TestCase def test_read_attribute_names assert_equal( - %w( id title author_name author_email_address bonus_time written_on last_read content approved replies_count parent_id parent_title type ).sort, + %w( id title author_name author_email_address bonus_time written_on last_read content group approved replies_count parent_id parent_title type ).sort, @first.attribute_names ) end def test_columns - assert_equal 13, Topic.columns.length + assert_equal 14, Topic.columns.length end def test_columns_are_returned_in_the_order_they_were_declared column_names = Topic.columns.map { |column| column.name } - assert_equal %w(id title author_name author_email_address written_on bonus_time last_read content approved replies_count parent_id parent_title type), column_names + assert_equal %w(id title author_name author_email_address written_on bonus_time last_read content approved replies_count parent_id parent_title type group), column_names end def test_content_columns content_columns = Topic.content_columns content_column_names = content_columns.map {|column| column.name} - assert_equal 9, content_columns.length - assert_equal %w(title author_name author_email_address written_on bonus_time last_read content approved parent_title).sort, content_column_names.sort + assert_equal 10, content_columns.length + assert_equal %w(title author_name author_email_address written_on bonus_time last_read content group approved parent_title).sort, content_column_names.sort end def test_column_string_type_and_limit diff --git a/activerecord/test/cases/relation_scoping_test.rb b/activerecord/test/cases/relation_scoping_test.rb new file mode 100644 index 0000000000..41dcdbcd37 --- /dev/null +++ b/activerecord/test/cases/relation_scoping_test.rb @@ -0,0 +1,396 @@ +require "cases/helper" +require 'models/post' +require 'models/author' +require 'models/developer' +require 'models/project' +require 'models/comment' +require 'models/category' + +class RelationScopingTest < ActiveRecord::TestCase + fixtures :authors, :developers, :projects, :comments, :posts, :developers_projects + + def test_scoped_find + Developer.where("name = 'David'").scoping do + assert_nothing_raised { Developer.find(1) } + end + end + + def test_scoped_find_first + developer = Developer.find(10) + Developer.where("salary = 100000").scoping do + assert_equal developer, Developer.order("name").first + end + end + + def test_scoped_find_last + highest_salary = Developer.order("salary DESC").first + + Developer.order("salary").scoping do + assert_equal highest_salary, Developer.last + end + end + + def test_scoped_find_last_preserves_scope + lowest_salary = Developer.first :order => "salary ASC" + highest_salary = Developer.first :order => "salary DESC" + + Developer.order("salary").scoping do + assert_equal highest_salary, Developer.last + assert_equal lowest_salary, Developer.first + end + end + + def test_scoped_find_combines_and_sanitizes_conditions + Developer.where("salary = 9000").scoping do + assert_equal developers(:poor_jamis), Developer.where("name = 'Jamis'").first + end + end + + def test_scoped_find_all + Developer.where("name = 'David'").scoping do + assert_equal [developers(:david)], Developer.all + end + end + + def test_scoped_find_select + Developer.select("id, name").scoping do + developer = Developer.where("name = 'David'").first + assert_equal "David", developer.name + assert !developer.has_attribute?(:salary) + end + end + + def test_scope_select_concatenates + Developer.select("id, name").scoping do + developer = Developer.select('id, salary').where("name = 'David'").first + assert_equal 80000, developer.salary + assert developer.has_attribute?(:id) + assert developer.has_attribute?(:name) + assert developer.has_attribute?(:salary) + end + end + + def test_scoped_count + Developer.where("name = 'David'").scoping do + assert_equal 1, Developer.count + end + + Developer.where('salary = 100000').scoping do + assert_equal 8, Developer.count + assert_equal 1, Developer.where("name LIKE 'fixture_1%'").count + end + end + + def test_scoped_find_include + # with the include, will retrieve only developers for the given project + scoped_developers = Developer.includes(:projects).scoping do + Developer.where('projects.id = 2').all + end + assert scoped_developers.include?(developers(:david)) + assert !scoped_developers.include?(developers(:jamis)) + assert_equal 1, scoped_developers.size + end + + def test_scoped_find_joins + scoped_developers = Developer.joins('JOIN developers_projects ON id = developer_id').scoping do + Developer.where('developers_projects.project_id = 2').all + end + + assert scoped_developers.include?(developers(:david)) + assert !scoped_developers.include?(developers(:jamis)) + assert_equal 1, scoped_developers.size + assert_equal developers(:david).attributes, scoped_developers.first.attributes + end + + def test_scoped_create_with_where + new_comment = VerySpecialComment.where(:post_id => 1).scoping do + VerySpecialComment.create :body => "Wonderful world" + end + + assert_equal 1, new_comment.post_id + assert Post.find(1).comments.include?(new_comment) + end + + def test_scoped_create_with_create_with + new_comment = VerySpecialComment.create_with(:post_id => 1).scoping do + VerySpecialComment.create :body => "Wonderful world" + end + + assert_equal 1, new_comment.post_id + assert Post.find(1).comments.include?(new_comment) + end + + def test_scoped_create_with_create_with_has_higher_priority + new_comment = VerySpecialComment.where(:post_id => 2).create_with(:post_id => 1).scoping do + VerySpecialComment.create :body => "Wonderful world" + end + + assert_equal 1, new_comment.post_id + assert Post.find(1).comments.include?(new_comment) + end + + def test_ensure_that_method_scoping_is_correctly_restored + scoped_methods = Developer.send(:current_scoped_methods) + + begin + Developer.where("name = 'Jamis'").scoping do + raise "an exception" + end + rescue + end + + assert_equal scoped_methods, Developer.send(:current_scoped_methods) + end +end + +class NestedRelationScopingTest < ActiveRecord::TestCase + fixtures :authors, :developers, :projects, :comments, :posts + + def test_merge_options + Developer.where('salary = 80000').scoping do + Developer.limit(10).scoping do + devs = Developer.scoped + assert_equal '(salary = 80000)', devs.arel.send(:where_clauses).join(' AND ') + assert_equal 10, devs.taken + end + end + end + + def test_merge_inner_scope_has_priority + Developer.limit(5).scoping do + Developer.limit(10).scoping do + assert_equal 10, Developer.count + end + end + end + + def test_replace_options + Developer.where(:name => 'David').scoping do + Developer.unscoped do + assert_equal 'Jamis', Developer.where(:name => 'Jamis').first[:name] + end + + assert_equal 'David', Developer.first[:name] + end + end + + def test_three_level_nested_exclusive_scoped_find + Developer.where("name = 'Jamis'").scoping do + assert_equal 'Jamis', Developer.first.name + + Developer.unscoped.where("name = 'David'") do + assert_equal 'David', Developer.first.name + + Developer.unscoped.where("name = 'Maiha'") do + assert_equal nil, Developer.first + end + + # ensure that scoping is restored + assert_equal 'David', Developer.first.name + end + + # ensure that scoping is restored + assert_equal 'Jamis', Developer.first.name + end + end + + def test_nested_scoped_create + comment = Comment.create_with(:post_id => 1).scoping do + Comment.create_with(:post_id => 2).scoping do + Comment.create :body => "Hey guys, nested scopes are broken. Please fix!" + end + end + + assert_equal 2, comment.post_id + end + + def test_nested_exclusive_scope_for_create + comment = Comment.create_with(:body => "Hey guys, nested scopes are broken. Please fix!").scoping do + Comment.unscoped.create_with(:post_id => 1).scoping do + assert Comment.new.body.blank? + Comment.create :body => "Hey guys" + end + end + + assert_equal 1, comment.post_id + assert_equal 'Hey guys', comment.body + end +end + +class HasManyScopingTest< ActiveRecord::TestCase + fixtures :comments, :posts + + def setup + @welcome = Post.find(1) + end + + def test_forwarding_of_static_methods + assert_equal 'a comment...', Comment.what_are_you + assert_equal 'a comment...', @welcome.comments.what_are_you + end + + def test_forwarding_to_scoped + assert_equal 4, Comment.search_by_type('Comment').size + assert_equal 2, @welcome.comments.search_by_type('Comment').size + end + + def test_forwarding_to_dynamic_finders + assert_equal 4, Comment.find_all_by_type('Comment').size + assert_equal 2, @welcome.comments.find_all_by_type('Comment').size + end + + def test_nested_scope_finder + Comment.where('1=0').scoping do + assert_equal 0, @welcome.comments.count + assert_equal 'a comment...', @welcome.comments.what_are_you + end + + Comment.where('1=1').scoping do + assert_equal 2, @welcome.comments.count + assert_equal 'a comment...', @welcome.comments.what_are_you + end + end +end + +class HasAndBelongsToManyScopingTest< ActiveRecord::TestCase + fixtures :posts, :categories, :categories_posts + + def setup + @welcome = Post.find(1) + end + + def test_forwarding_of_static_methods + assert_equal 'a category...', Category.what_are_you + assert_equal 'a category...', @welcome.categories.what_are_you + end + + def test_forwarding_to_dynamic_finders + assert_equal 4, Category.find_all_by_type('SpecialCategory').size + assert_equal 0, @welcome.categories.find_all_by_type('SpecialCategory').size + assert_equal 2, @welcome.categories.find_all_by_type('Category').size + end + + def test_nested_scope_finder + Category.where('1=0').scoping do + assert_equal 0, @welcome.categories.count + assert_equal 'a category...', @welcome.categories.what_are_you + end + + Category.where('1=1').scoping do + assert_equal 2, @welcome.categories.count + assert_equal 'a category...', @welcome.categories.what_are_you + end + end +end + +class DefaultScopingTest < ActiveRecord::TestCase + fixtures :developers, :posts + + def test_default_scope + expected = Developer.find(:all, :order => 'salary DESC').collect { |dev| dev.salary } + received = DeveloperOrderedBySalary.find(:all).collect { |dev| dev.salary } + assert_equal expected, received + end + + def test_default_scope_is_unscoped_on_find + assert_equal 1, DeveloperCalledDavid.count + assert_equal 11, DeveloperCalledDavid.unscoped.count + end + + def test_default_scope_is_unscoped_on_create + assert_nil DeveloperCalledJamis.unscoped.create!.name + end + + def test_default_scope_with_conditions_string + assert_equal Developer.find_all_by_name('David').map(&:id).sort, DeveloperCalledDavid.find(:all).map(&:id).sort + assert_equal nil, DeveloperCalledDavid.create!.name + end + + def test_default_scope_with_conditions_hash + assert_equal Developer.find_all_by_name('Jamis').map(&:id).sort, DeveloperCalledJamis.find(:all).map(&:id).sort + assert_equal 'Jamis', DeveloperCalledJamis.create!.name + end + + def test_default_scoping_with_threads + 2.times do + Thread.new { assert_equal ['salary DESC'], DeveloperOrderedBySalary.scoped.order_values }.join + end + end + + def test_default_scoping_with_inheritance + # Inherit a class having a default scope and define a new default scope + klass = Class.new(DeveloperOrderedBySalary) + klass.send :default_scope, :limit => 1 + + # Scopes added on children should append to parent scope + assert_equal 1, klass.scoped.limit_value + assert_equal ['salary DESC'], klass.scoped.order_values + + # Parent should still have the original scope + assert_nil DeveloperOrderedBySalary.scoped.limit_value + assert_equal ['salary DESC'], DeveloperOrderedBySalary.scoped.order_values + end + + def test_default_scope_called_twice_merges_conditions + Developer.destroy_all + Developer.create!(:name => "David", :salary => 80000) + Developer.create!(:name => "David", :salary => 100000) + Developer.create!(:name => "Brian", :salary => 100000) + + klass = Class.new(Developer) + klass.__send__ :default_scope, :conditions => { :name => "David" } + klass.__send__ :default_scope, :conditions => { :salary => 100000 } + assert_equal 1, klass.count + assert_equal "David", klass.first.name + assert_equal 100000, klass.first.salary + end + def test_method_scope + expected = Developer.find(:all, :order => 'name DESC').collect { |dev| dev.salary } + received = DeveloperOrderedBySalary.all_ordered_by_name.collect { |dev| dev.salary } + assert_equal expected, received + end + + def test_nested_scope + expected = Developer.find(:all, :order => 'name DESC').collect { |dev| dev.salary } + received = DeveloperOrderedBySalary.send(:with_scope, :find => { :order => 'name DESC'}) do + DeveloperOrderedBySalary.find(:all).collect { |dev| dev.salary } + end + assert_equal expected, received + end + + def test_named_scope_overwrites_default + expected = Developer.find(:all, :order => 'name DESC').collect { |dev| dev.name } + received = DeveloperOrderedBySalary.by_name.find(:all).collect { |dev| dev.name } + assert_equal expected, received + end + + def test_nested_exclusive_scope + expected = Developer.find(:all, :limit => 100).collect { |dev| dev.salary } + received = DeveloperOrderedBySalary.send(:with_exclusive_scope, :find => { :limit => 100 }) do + DeveloperOrderedBySalary.find(:all).collect { |dev| dev.salary } + end + assert_equal expected, received + end + + def test_overwriting_default_scope + expected = Developer.find(:all, :order => 'salary').collect { |dev| dev.salary } + received = DeveloperOrderedBySalary.find(:all, :order => 'salary').collect { |dev| dev.salary } + assert_equal expected, received + end + + def test_default_scope_using_relation + posts = PostWithComment.scoped + assert_equal 2, posts.count + assert_equal posts(:thinking), posts.first + end + + def test_create_attribute_overwrites_default_scoping + assert_equal 'David', PoorDeveloperCalledJamis.create!(:name => 'David').name + assert_equal 200000, PoorDeveloperCalledJamis.create!(:name => 'David', :salary => 200000).salary + end + + def test_create_attribute_overwrites_default_values + assert_equal nil, PoorDeveloperCalledJamis.create!(:salary => nil).salary + assert_equal 50000, PoorDeveloperCalledJamis.create!(:name => 'David').salary + end +end
\ No newline at end of file diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index 43519db976..ffde8daa07 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -16,12 +16,34 @@ class RelationTest < ActiveRecord::TestCase fixtures :authors, :topics, :entrants, :developers, :companies, :developers_projects, :accounts, :categories, :categorizations, :posts, :comments, :taggings + def test_apply_relation_as_where_id + posts = Post.arel_table + post_authors = posts.where(posts[:author_id].eq(1)).project(posts[:id]) + assert_equal 5, post_authors.to_a.size + assert_equal 5, Post.where(:id => post_authors).size + end + def test_scoped topics = Topic.scoped assert_kind_of ActiveRecord::Relation, topics assert_equal 4, topics.size end + def test_to_json + assert_nothing_raised { Bird.scoped.to_json } + assert_nothing_raised { Bird.scoped.all.to_json } + end + + def test_to_yaml + assert_nothing_raised { Bird.scoped.to_yaml } + assert_nothing_raised { Bird.scoped.all.to_yaml } + end + + def test_to_xml + assert_nothing_raised { Bird.scoped.to_xml } + assert_nothing_raised { Bird.scoped.all.to_xml } + end + def test_scoped_all topics = Topic.scoped.all assert_kind_of Array, topics @@ -88,6 +110,18 @@ class RelationTest < ActiveRecord::TestCase assert_equal topics(:first).title, topics.first.title end + def test_finding_with_order_concatenated + topics = Topic.order('author_name').order('title') + assert_equal 4, topics.to_a.size + assert_equal topics(:fourth).title, topics.first.title + end + + def test_finding_with_reorder + topics = Topic.order('author_name').order('title').reorder('id') + assert_equal 4, topics.to_a.size + assert_equal topics(:first).title, topics.first.title + end + def test_finding_with_order_and_take entrants = Entrant.order("id ASC").limit(2).to_a @@ -461,7 +495,7 @@ class RelationTest < ActiveRecord::TestCase posts = Post.scoped assert_equal [0], posts.select('comments_count').where('id is not null').group('id').order('id').count.values.uniq - assert_equal 0, posts.where('id is not null').select('comments_count').count + assert_equal 7, posts.where('id is not null').select('comments_count').count assert_equal 7, posts.select('comments_count').count('id') assert_equal 0, posts.select('comments_count').count @@ -469,6 +503,12 @@ class RelationTest < ActiveRecord::TestCase assert_equal 0, posts.count('comments_count') end + def test_multiple_selects + post = Post.scoped.select('comments_count').select('title').order("id ASC").first + assert_equal "Welcome to the weblog", post.title + assert_equal 2, post.comments_count + end + def test_size posts = Post.scoped @@ -503,13 +543,13 @@ class RelationTest < ActiveRecord::TestCase def test_many posts = Post.scoped - + assert_queries(2) do assert posts.many? # Uses COUNT() assert posts.many? {|p| p.id > 0 } assert ! posts.many? {|p| p.id < 2 } end - + assert posts.loaded? end @@ -578,7 +618,7 @@ class RelationTest < ActiveRecord::TestCase end def test_anonymous_extension - relation = Post.where(:author_id => 1).order('id ASC') do + relation = Post.where(:author_id => 1).order('id ASC').extending do def author 'lifo' end @@ -593,4 +633,12 @@ class RelationTest < ActiveRecord::TestCase assert_equal "lifo", relation.author assert_equal "lifo", relation.limit(1).author end + + def test_order_by_relation_attribute + assert_equal Post.order(Post.arel_table[:title]).all, Post.order("title").all + end + + def test_relations_limit_with_conditions_or_limit + assert_equal Post.limit(2).size, Post.limit(2).all.size + end end diff --git a/activerecord/test/cases/transaction_callbacks_test.rb b/activerecord/test/cases/transaction_callbacks_test.rb index ebc16653cb..df123c9de8 100644 --- a/activerecord/test/cases/transaction_callbacks_test.rb +++ b/activerecord/test/cases/transaction_callbacks_test.rb @@ -221,20 +221,28 @@ class TransactionCallbacksTest < ActiveRecord::TestCase assert_equal 2, @first.rollbacks end - def test_after_transaction_callbacks_should_not_raise_errors + def test_after_transaction_callbacks_should_prevent_callbacks_from_being_called def @first.last_after_transaction_error=(e); @last_transaction_error = e; end 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} - @first.save! + Topic.transaction do + @first.save! + @second.save! + end assert_equal :commit, @first.last_after_transaction_error + assert_equal [:after_commit], @second.history + @second.history.clear Topic.transaction do @first.save! + @second.save! raise ActiveRecord::Rollback end - assert_equal :rollback, @first.last_after_transaction_error + assert_equal [:after_rollback], @second.history end end 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 8ee2a5868c..454e42ed37 100644 --- a/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb +++ b/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb @@ -9,22 +9,22 @@ class I18nGenerateMessageValidationTest < ActiveRecord::TestCase I18n.backend = I18n::Backend::Simple.new end - # validates_associated: generate_message(attr_name, :invalid, :default => configuration[:message], :value => value) + # validates_associated: generate_message(attr_name, :invalid, :message => custom_message, :value => value) def test_generate_message_invalid_with_default_message - assert_equal 'is invalid', @topic.errors.generate_message(:title, :invalid, :default => nil, :value => 'title') + assert_equal 'is invalid', @topic.errors.generate_message(:title, :invalid, :value => 'title') end def test_generate_message_invalid_with_custom_message - assert_equal 'custom message title', @topic.errors.generate_message(:title, :invalid, :default => 'custom message %{value}', :value => 'title') + assert_equal 'custom message title', @topic.errors.generate_message(:title, :invalid, :message => 'custom message %{value}', :value => 'title') end - # validates_uniqueness_of: generate_message(attr_name, :taken, :default => configuration[:message]) + # validates_uniqueness_of: generate_message(attr_name, :taken, :message => custom_message) def test_generate_message_taken_with_default_message - assert_equal "has already been taken", @topic.errors.generate_message(:title, :taken, :default => nil, :value => 'title') + assert_equal "has already been taken", @topic.errors.generate_message(:title, :taken, :value => 'title') end def test_generate_message_taken_with_custom_message - assert_equal 'custom message title', @topic.errors.generate_message(:title, :taken, :default => 'custom message %{value}', :value => 'title') + assert_equal 'custom message title', @topic.errors.generate_message(:title, :taken, :message => 'custom message %{value}', :value => 'title') end # ActiveRecord#RecordInvalid exception diff --git a/activerecord/test/cases/validations/i18n_validation_test.rb b/activerecord/test/cases/validations/i18n_validation_test.rb index 38fa2b821d..15b97c02c8 100644 --- a/activerecord/test/cases/validations/i18n_validation_test.rb +++ b/activerecord/test/cases/validations/i18n_validation_test.rb @@ -31,34 +31,40 @@ class I18nValidationTest < ActiveRecord::TestCase end end - # validates_uniqueness_of w/ mocha + # A set of common cases for ActiveModel::Validations message generation that + # are used to generate tests to keep things DRY + # + COMMON_CASES = [ + # [ case, validation_options, generate_message_options] + [ "given no options", {}, {}], + [ "given custom message", {:message => "custom"}, {:message => "custom"}], + [ "given if condition", {:if => lambda { true }}, {}], + [ "given unless condition", {:unless => lambda { false }}, {}], + [ "given option that is not reserved", {:format => "jpg"}, {:format => "jpg" }] + # TODO Add :on case, but below doesn't work, because then the validation isn't run for some reason + # even when using .save instead .valid? + # [ "given on condition", {:on => :save}, {}] + ] - def test_validates_uniqueness_of_generates_message - Topic.validates_uniqueness_of :title - @topic.title = unique_topic.title - @topic.errors.expects(:generate_message).with(:title, :taken, {:default => nil, :value => 'unique!'}) - @topic.valid? - end + # validates_uniqueness_of w/ mocha - def test_validates_uniqueness_of_generates_message_with_custom_default_message - Topic.validates_uniqueness_of :title, :message => 'custom' - @topic.title = unique_topic.title - @topic.errors.expects(:generate_message).with(:title, :taken, {:default => 'custom', :value => 'unique!'}) - @topic.valid? + COMMON_CASES.each do |name, validation_options, generate_message_options| + test "validates_uniqueness_of on generated message #{name}" do + Topic.validates_uniqueness_of :title, validation_options + @topic.title = unique_topic.title + @topic.errors.expects(:generate_message).with(:title, :taken, generate_message_options.merge(:value => 'unique!')) + @topic.valid? + end end # validates_associated w/ mocha - def test_validates_associated_generates_message - Topic.validates_associated :replies - replied_topic.errors.expects(:generate_message).with(:replies, :invalid, {:value => replied_topic.replies, :default => nil}) - replied_topic.valid? - end - - def test_validates_associated_generates_message_with_custom_default_message - Topic.validates_associated :replies - replied_topic.errors.expects(:generate_message).with(:replies, :invalid, {:value => replied_topic.replies, :default => nil}) - replied_topic.valid? + COMMON_CASES.each do |name, validation_options, generate_message_options| + test "validates_associated on generated message #{name}" do + Topic.validates_associated :replies, validation_options + replied_topic.errors.expects(:generate_message).with(:replies, :invalid, generate_message_options.merge(:value => replied_topic.replies)) + replied_topic.save + end end # validates_associated w/o mocha diff --git a/activerecord/test/fixtures/topics.yml b/activerecord/test/fixtures/topics.yml index 1769152445..93f48aedc4 100644 --- a/activerecord/test/fixtures/topics.yml +++ b/activerecord/test/fixtures/topics.yml @@ -24,7 +24,7 @@ second: third: id: 3 title: The Third Topic of the day - author_name: Nick + author_name: Carl written_on: 2005-07-15t15:28:00.0099+01:00 content: I'm a troll approved: true diff --git a/activerecord/test/models/developer.rb b/activerecord/test/models/developer.rb index e35de3b9b0..de68fd7f24 100644 --- a/activerecord/test/models/developer.rb +++ b/activerecord/test/models/developer.rb @@ -55,6 +55,12 @@ class Developer < ActiveRecord::Base def log=(message) audit_logs.build :message => message end + + def self.all_johns + self.with_exclusive_scope :find => where(:name => 'John') do + self.all + end + end end class AuditLog < ActiveRecord::Base @@ -103,4 +109,4 @@ end class PoorDeveloperCalledJamis < ActiveRecord::Base self.table_name = 'developers' default_scope :conditions => { :name => 'Jamis', :salary => 50000 } -end
\ No newline at end of file +end diff --git a/activerecord/test/models/pirate.rb b/activerecord/test/models/pirate.rb index f1dbe32c6e..d89c8cf381 100644 --- a/activerecord/test/models/pirate.rb +++ b/activerecord/test/models/pirate.rb @@ -1,7 +1,7 @@ class Pirate < ActiveRecord::Base belongs_to :parrot, :validate => true belongs_to :non_validated_parrot, :class_name => 'Parrot' - has_and_belongs_to_many :parrots, :validate => true + has_and_belongs_to_many :parrots, :validate => true, :order => 'parrots.id ASC' has_and_belongs_to_many :non_validated_parrots, :class_name => 'Parrot' has_and_belongs_to_many :parrots_with_method_callbacks, :class_name => "Parrot", :before_add => :log_before_add, @@ -21,7 +21,7 @@ class Pirate < ActiveRecord::Base has_one :ship has_one :update_only_ship, :class_name => 'Ship' has_one :non_validated_ship, :class_name => 'Ship' - has_many :birds + has_many :birds, :order => 'birds.id ASC' has_many :birds_with_method_callbacks, :class_name => "Bird", :before_add => :log_before_add, :after_add => :log_after_add, diff --git a/activerecord/test/models/without_table.rb b/activerecord/test/models/without_table.rb new file mode 100644 index 0000000000..87f80911e1 --- /dev/null +++ b/activerecord/test/models/without_table.rb @@ -0,0 +1,3 @@ +class WithoutTable < ActiveRecord::Base + default_scope where(:published => true) +end
\ No newline at end of file diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index f5fba2f87d..b212e7cff2 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -485,6 +485,7 @@ ActiveRecord::Schema.define do t.integer :parent_id t.string :parent_title t.string :type + t.string :group end create_table :taggings, :force => true do |t| |