diff options
Diffstat (limited to 'activerecord/test/cases')
18 files changed, 233 insertions, 68 deletions
diff --git a/activerecord/test/cases/adapters/postgresql/quoting_test.rb b/activerecord/test/cases/adapters/postgresql/quoting_test.rb index f8a605b67c..685f0ea74f 100644 --- a/activerecord/test/cases/adapters/postgresql/quoting_test.rb +++ b/activerecord/test/cases/adapters/postgresql/quoting_test.rb @@ -1,4 +1,5 @@ require "cases/helper" +require 'ipaddr' module ActiveRecord module ConnectionAdapters @@ -20,6 +21,18 @@ module ActiveRecord assert_equal 'f', @conn.type_cast(false, c) end + def test_type_cast_cidr + ip = IPAddr.new('255.0.0.0/8') + c = Column.new(nil, ip, 'cidr') + assert_equal ip, @conn.type_cast(ip, c) + end + + def test_type_cast_inet + ip = IPAddr.new('255.1.0.0/8') + c = Column.new(nil, ip, 'inet') + assert_equal ip, @conn.type_cast(ip, c) + end + def test_quote_float_nan nan = 0.0/0 c = Column.new(nil, 1, 'float') diff --git a/activerecord/test/cases/adapters/postgresql/schema_test.rb b/activerecord/test/cases/adapters/postgresql/schema_test.rb index 9208f53997..cd31900d4e 100644 --- a/activerecord/test/cases/adapters/postgresql/schema_test.rb +++ b/activerecord/test/cases/adapters/postgresql/schema_test.rb @@ -72,7 +72,7 @@ class SchemaTest < ActiveRecord::TestCase end def test_schema_names - assert_equal ["public", "test_schema", "test_schema2"], @connection.schema_names + assert_equal ["public", "schema_1", "test_schema", "test_schema2"], @connection.schema_names end def test_create_schema @@ -97,7 +97,7 @@ class SchemaTest < ActiveRecord::TestCase def test_drop_schema begin - @connection.create_schema "test_schema3" + @connection.create_schema "test_schema3" ensure @connection.drop_schema "test_schema3" end diff --git a/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb b/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb index 7eef4ace81..74288a98d1 100644 --- a/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb @@ -59,7 +59,7 @@ class CopyTableTest < ActiveRecord::TestCase def test_copy_table_with_unconventional_primary_key test_copy_table('owners', 'owners_unconventional') do |from, to, options| - original_pk = @connection.primary_key('owners') + original_pk = @connection.primary_key('owners') copied_pk = @connection.primary_key('owners_unconventional') assert_equal original_pk, copied_pk end diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb index f0582a3090..b2a5d9d6f7 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -19,7 +19,6 @@ require 'models/book' require 'models/subscription' require 'models/essay' require 'models/category' -require 'models/owner' require 'models/categorization' require 'models/member' require 'models/membership' diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb index d08b157011..c2b58fd7d1 100644 --- a/activerecord/test/cases/attribute_methods_test.rb +++ b/activerecord/test/cases/attribute_methods_test.rb @@ -542,10 +542,10 @@ class AttributeMethodsTest < ActiveRecord::TestCase val = t.send attr_name unless attr_name == "type" if attribute_gets_cached assert cached_columns.include?(attr_name) - assert_equal val, cache[attr_name.to_sym] + assert_equal val, cache[attr_name] else assert uncached_columns.include?(attr_name) - assert !cache.include?(attr_name.to_sym) + assert !cache.include?(attr_name) end end end diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb index fd4f09ab36..16ce150396 100644 --- a/activerecord/test/cases/autosave_association_test.rb +++ b/activerecord/test/cases/autosave_association_test.rb @@ -16,7 +16,6 @@ require 'models/ship_part' require 'models/tag' require 'models/tagging' require 'models/treasure' -require 'models/company' require 'models/eye' class TestAutosaveAssociationsInGeneral < ActiveRecord::TestCase @@ -145,7 +144,7 @@ class TestDefaultAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCas firm = Firm.first firm.account = Account.first - assert_queries(Firm.partial_updates? ? 0 : 1) { firm.save! } + assert_queries(Firm.partial_writes? ? 0 : 1) { firm.save! } firm = Firm.first.dup firm.account = Account.first diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index 6cb6c469d2..abbf2a765e 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -6,6 +6,8 @@ require 'models/edge' require 'models/organization' require 'models/possession' require 'models/topic' +require 'models/minivan' +require 'models/speedometer' Company.has_many :accounts @@ -239,21 +241,12 @@ class CalculationsTest < ActiveRecord::TestCase end def test_should_group_by_association_with_non_numeric_foreign_key - ActiveRecord::Base.connection.expects(:select_all).returns([{"count_all" => 1, "firm_id" => "ABC"}]) + Speedometer.create! id: 'ABC' + Minivan.create! id: 'OMG', speedometer_id: 'ABC' - firm = mock() - firm.expects(:id).returns("ABC") - firm.expects(:class).returns(Firm) - Company.expects(:find).with(["ABC"]).returns([firm]) - - column = mock() - column.expects(:name).at_least_once.returns(:firm_id) - column.expects(:type_cast).with("ABC").returns("ABC") - Account.expects(:columns).at_least_once.returns([column]) - - c = Account.group(:firm).count(:all) + c = Minivan.group(:speedometer).count(:all) first_key = c.keys.first - assert_equal Firm, first_key.class + assert_equal Speedometer, first_key.class assert_equal 1, c[first_key] end @@ -378,6 +371,10 @@ class CalculationsTest < ActiveRecord::TestCase end end + def test_sum_expression_returns_zero_when_no_records_to_sum + assert_equal 0, Account.where('1 = 2').sum("2 * credit_limit") + end + def test_count_with_from_option assert_equal Company.count(:all), Company.from('companies').count(:all) assert_equal Account.where("credit_limit = 50").count(:all), diff --git a/activerecord/test/cases/defaults_test.rb b/activerecord/test/cases/defaults_test.rb index deaf5252db..0df872ff10 100644 --- a/activerecord/test/cases/defaults_test.rb +++ b/activerecord/test/cases/defaults_test.rb @@ -51,11 +51,60 @@ if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) # 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 + def using_strict(strict) + connection = ActiveRecord::Model.remove_connection + ActiveRecord::Model.establish_connection connection.merge(strict: strict) + yield + ensure + ActiveRecord::Model.remove_connection + ActiveRecord::Model.establish_connection connection + end + + # MySQL cannot have defaults on text/blob columns. It reports the + # default value as null. + # + # Despite this, in non-strict mode, MySQL will use an empty string + # as the default value of the field, if no other value is + # specified. + # + # Therefore, in non-strict mode, we want column.default to report + # an empty string as its default, to be consistent with that. + # + # In strict mode, column.default should be nil. + def test_mysql_text_not_null_defaults_non_strict + using_strict(false) do + with_text_blob_not_null_table do |klass| + assert_equal '', klass.columns_hash['non_null_blob'].default + assert_equal '', klass.columns_hash['non_null_text'].default + + assert_nil klass.columns_hash['null_blob'].default + assert_nil klass.columns_hash['null_text'].default + + instance = klass.create! + + assert_equal '', instance.non_null_text + assert_equal '', instance.non_null_blob + + assert_nil instance.null_text + assert_nil instance.null_blob + end + end + end + + def test_mysql_text_not_null_defaults_strict + using_strict(true) do + with_text_blob_not_null_table do |klass| + assert_nil klass.columns_hash['non_null_blob'].default + assert_nil klass.columns_hash['non_null_text'].default + assert_nil klass.columns_hash['null_blob'].default + assert_nil klass.columns_hash['null_text'].default + + assert_raises(ActiveRecord::StatementInvalid) { klass.create } + end + end + end + + def with_text_blob_not_null_table klass = Class.new(ActiveRecord::Base) klass.table_name = 'test_mysql_text_not_null_defaults' klass.connection.create_table klass.table_name do |t| @@ -64,19 +113,8 @@ if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) t.column :null_text, :text, :null => true t.column :null_blob, :blob, :null => true end - assert_equal '', klass.columns_hash['non_null_blob'].default - assert_equal '', klass.columns_hash['non_null_text'].default - - assert_nil klass.columns_hash['null_blob'].default - assert_nil klass.columns_hash['null_text'].default - assert_nothing_raised do - instance = klass.create! - assert_equal '', instance.non_null_text - assert_equal '', instance.non_null_blob - assert_nil instance.null_text - assert_nil instance.null_blob - end + yield klass ensure klass.connection.drop_table(klass.table_name) rescue nil end @@ -109,3 +147,43 @@ if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) end end end + +if current_adapter?(:PostgreSQLAdapter) + class DefaultsUsingMultipleSchemasAndDomainTest < ActiveSupport::TestCase + def setup + @connection = ActiveRecord::Base.connection + + @old_search_path = @connection.schema_search_path + @connection.schema_search_path = "schema_1, pg_catalog" + @connection.create_table "defaults" do |t| + t.text "text_col", :default => "some value" + t.string "string_col", :default => "some value" + end + Default.reset_column_information + end + + def test_text_defaults_in_new_schema_when_overriding_domain + assert_equal "some value", Default.new.text_col, "Default of text column was not correctly parse" + end + + def test_string_defaults_in_new_schema_when_overriding_domain + assert_equal "some value", Default.new.string_col, "Default of string column was not correctly parse" + end + + def test_bpchar_defaults_in_new_schema_when_overriding_domain + @connection.execute "ALTER TABLE defaults ADD bpchar_col bpchar DEFAULT 'some value'" + Default.reset_column_information + assert_equal "some value", Default.new.bpchar_col, "Default of bpchar column was not correctly parse" + end + + def test_text_defaults_after_updating_column_default + @connection.execute "ALTER TABLE defaults ALTER COLUMN text_col SET DEFAULT 'some text'::schema_1.text" + assert_equal "some text", Default.new.text_col, "Default of text column was not correctly parse after updating default using '::text' since postgreSQL will add parens to the default in db" + end + + def teardown + @connection.schema_search_path = @old_search_path + Default.reset_column_information + end + end +end diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb index 7334514f9a..40f1dbccde 100644 --- a/activerecord/test/cases/dirty_test.rb +++ b/activerecord/test/cases/dirty_test.rb @@ -311,12 +311,12 @@ class DirtyTest < ActiveRecord::TestCase pirate = Pirate.new(:catchphrase => 'foo') old_updated_on = 1.hour.ago.beginning_of_day - with_partial_updates Pirate, false do + with_partial_writes Pirate, false do assert_queries(2) { 2.times { pirate.save! } } Pirate.where(id: pirate.id).update_all(:updated_on => old_updated_on) end - with_partial_updates Pirate, true do + with_partial_writes Pirate, true do assert_queries(0) { 2.times { pirate.save! } } assert_equal old_updated_on, pirate.reload.updated_on @@ -329,12 +329,12 @@ class DirtyTest < ActiveRecord::TestCase person = Person.new(:first_name => 'foo') old_lock_version = 1 - with_partial_updates Person, false do + with_partial_writes Person, false do assert_queries(2) { 2.times { person.save! } } Person.where(id: person.id).update_all(:first_name => 'baz') end - with_partial_updates Person, true do + with_partial_writes Person, true do assert_queries(0) { 2.times { person.save! } } assert_equal old_lock_version, person.reload.lock_version @@ -408,8 +408,8 @@ class DirtyTest < ActiveRecord::TestCase assert !pirate.catchphrase_changed? end - def test_save_should_store_serialized_attributes_even_with_partial_updates - with_partial_updates(Topic) do + def test_save_should_store_serialized_attributes_even_with_partial_writes + with_partial_writes(Topic) do topic = Topic.create!(:content => {:a => "a"}) topic.content[:b] = "b" #assert topic.changed? # Known bug, will fail @@ -421,7 +421,7 @@ class DirtyTest < ActiveRecord::TestCase end def test_save_always_should_update_timestamps_when_serialized_attributes_are_present - with_partial_updates(Topic) do + with_partial_writes(Topic) do topic = Topic.create!(:content => {:a => "a"}) topic.save! @@ -434,8 +434,8 @@ class DirtyTest < ActiveRecord::TestCase end end - def test_save_should_not_save_serialized_attribute_with_partial_updates_if_not_present - with_partial_updates(Topic) do + def test_save_should_not_save_serialized_attribute_with_partial_writes_if_not_present + with_partial_writes(Topic) do Topic.create!(:author_name => 'Bill', :content => {:a => "a"}) topic = Topic.select('id, author_name').first topic.update_columns author_name: 'John' @@ -552,7 +552,7 @@ class DirtyTest < ActiveRecord::TestCase end test "partial insert" do - with_partial_updates Person do + with_partial_writes Person do jon = nil assert_sql(/first_name/i) do jon = Person.create! first_name: 'Jon' @@ -568,20 +568,34 @@ class DirtyTest < ActiveRecord::TestCase end test "partial insert with empty values" do - with_partial_updates Aircraft do + with_partial_writes Aircraft do a = Aircraft.create! a.reload assert_not_nil a.id end end + test "partial_updates config attribute is deprecated" do + klass = Class.new(ActiveRecord::Base) + + assert klass.partial_writes? + assert_deprecated { assert klass.partial_updates? } + assert_deprecated { assert klass.partial_updates } + + assert_deprecated { klass.partial_updates = false } + + assert !klass.partial_writes? + assert_deprecated { assert !klass.partial_updates? } + assert_deprecated { assert !klass.partial_updates } + end + private - def with_partial_updates(klass, on = true) - old = klass.partial_updates? - klass.partial_updates = on + def with_partial_writes(klass, on = true) + old = klass.partial_writes? + klass.partial_writes = on yield ensure - klass.partial_updates = old + klass.partial_writes = old end def check_pirate_after_save_failure(pirate) diff --git a/activerecord/test/cases/dup_test.rb b/activerecord/test/cases/dup_test.rb index 71b2b16608..4e2adff344 100644 --- a/activerecord/test/cases/dup_test.rb +++ b/activerecord/test/cases/dup_test.rb @@ -107,5 +107,19 @@ module ActiveRecord assert Topic.after_initialize_called end + def test_dup_validity_is_independent + Topic.validates_presence_of :title + topic = Topic.new("title" => "Litterature") + topic.valid? + + duped = topic.dup + duped.title = nil + assert duped.invalid? + + topic.title = nil + duped.title = 'Mathematics' + assert topic.invalid? + assert duped.valid? + end end end diff --git a/activerecord/test/cases/migration/change_schema_test.rb b/activerecord/test/cases/migration/change_schema_test.rb index ec4c554abb..17c1634444 100644 --- a/activerecord/test/cases/migration/change_schema_test.rb +++ b/activerecord/test/cases/migration/change_schema_test.rb @@ -293,7 +293,7 @@ module ActiveRecord connection.create_table :testings do |t| t.column :foo, :string, limit: 100 t.column :bar, :decimal, precision: 8, scale: 2 - t.column :taggable_id, :integer, null: false + t.column :taggable_id, :integer, null: false t.column :taggable_type, :string, default: 'Photo' end diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index 3c0d2b18d9..c155f29973 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -344,11 +344,7 @@ class MigrationTest < ActiveRecord::TestCase columns = Person.connection.columns(:binary_testings) data_column = columns.detect { |c| c.name == "data" } - if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) - assert_equal '', data_column.default - else - assert_nil data_column.default - end + assert_nil data_column.default Person.connection.drop_table :binary_testings rescue nil end diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb index 2d778e9e90..51a285a2b4 100644 --- a/activerecord/test/cases/query_cache_test.rb +++ b/activerecord/test/cases/query_cache_test.rb @@ -48,7 +48,7 @@ class QueryCacheTest < ActiveRecord::TestCase } assert_raises(RuntimeError) { mw.call({}) } - assert_equal connection_id, ActiveRecord::Base.connection_id + assert_equal connection_id, ActiveRecord::Base.connection_id end def test_middleware_delegates diff --git a/activerecord/test/cases/reflection_test.rb b/activerecord/test/cases/reflection_test.rb index 588da68ec1..a9d46f4fba 100644 --- a/activerecord/test/cases/reflection_test.rb +++ b/activerecord/test/cases/reflection_test.rb @@ -3,7 +3,6 @@ require 'models/topic' require 'models/customer' require 'models/company' require 'models/company_in_module' -require 'models/subscriber' require 'models/ship' require 'models/pirate' require 'models/price_estimate' diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index b91423351e..5f96145b47 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -5,7 +5,6 @@ require 'models/post' require 'models/topic' require 'models/comment' require 'models/author' -require 'models/comment' require 'models/entrant' require 'models/developer' require 'models/reply' @@ -158,6 +157,22 @@ class RelationTest < ActiveRecord::TestCase assert_equal 4, topics.to_a.size assert_equal topics(:first).title, topics.first.title end + + def test_finding_with_assoc_order + topics = Topic.order(:id => :desc) + assert_equal 4, topics.to_a.size + assert_equal topics(:fourth).title, topics.first.title + end + + def test_finding_with_reverted_assoc_order + topics = Topic.order(:id => :asc).reverse_order + assert_equal 4, topics.to_a.size + assert_equal topics(:fourth).title, topics.first.title + end + + def test_raising_exception_on_invalid_hash_params + assert_raise(ArgumentError) { Topic.order(:name, "id DESC", :id => :DeSc) } + end def test_finding_last_with_arel_order topics = Topic.order(Topic.arel_table[:id].asc) @@ -1043,6 +1058,39 @@ class RelationTest < ActiveRecord::TestCase assert_equal 'parrot', parrot.name end + def test_find_or_create_by + assert_nil Bird.find_by(name: 'bob') + + bird = Bird.find_or_create_by(name: 'bob') + assert bird.persisted? + + assert_equal bird, Bird.find_or_create_by(name: 'bob') + end + + def test_find_or_create_by_with_create_with + assert_nil Bird.find_by(name: 'bob') + + bird = Bird.create_with(color: 'green').find_or_create_by(name: 'bob') + assert bird.persisted? + assert_equal 'green', bird.color + + assert_equal bird, Bird.create_with(color: 'blue').find_or_create_by(name: 'bob') + end + + def test_find_or_create_by! + assert_raises(ActiveRecord::RecordInvalid) { Bird.find_or_create_by!(color: 'green') } + end + + def test_find_or_initialize_by + assert_nil Bird.find_by(name: 'bob') + + bird = Bird.find_or_initialize_by(name: 'bob') + assert bird.new_record? + bird.save! + + assert_equal bird, Bird.find_or_initialize_by(name: 'bob') + end + def test_explicit_create_scope hens = Bird.where(:name => 'hen') assert_equal 'hen', hens.new.name diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb index 80f46c6b08..5f13124e5b 100644 --- a/activerecord/test/cases/schema_dumper_test.rb +++ b/activerecord/test/cases/schema_dumper_test.rb @@ -2,13 +2,9 @@ require "cases/helper" class SchemaDumperTest < ActiveRecord::TestCase - def initialize(*) - super - ActiveRecord::SchemaMigration.create_table - end - def setup super + ActiveRecord::SchemaMigration.create_table @stream = StringIO.new 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 a8e513d81f..174d96aa4e 100644 --- a/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb +++ b/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb @@ -13,7 +13,7 @@ class I18nGenerateMessageValidationTest < ActiveRecord::TestCase I18n.load_path.clear I18n.backend = I18n::Backend::Simple.new yield - ensure + ensure I18n.load_path.replace @old_load_path I18n.backend = @old_backend end @@ -54,4 +54,9 @@ class I18nGenerateMessageValidationTest < ActiveRecord::TestCase end end + test "translation for 'taken' can be overridden" do + I18n.backend.store_translations "en", {errors: {attributes: {title: {taken: "Custom taken message" }}}} + assert_equal "Custom taken message", @topic.errors.generate_message(:title, :taken, :value => 'title') + end + end diff --git a/activerecord/test/cases/validations/presence_validation_test.rb b/activerecord/test/cases/validations/presence_validation_test.rb index cd9175f454..1de8934406 100644 --- a/activerecord/test/cases/validations/presence_validation_test.rb +++ b/activerecord/test/cases/validations/presence_validation_test.rb @@ -18,6 +18,13 @@ class PresenceValidationTest < ActiveRecord::TestCase assert b.valid? end + def test_validates_presence_of_has_one + Boy.validates_presence_of(:face) + b = Boy.new + assert b.invalid?, "should not be valid if has_one association missing" + assert_equal 1, b.errors[:face].size, "validates_presence_of should only add one error" + end + def test_validates_presence_of_has_one_marked_for_destruction Boy.validates_presence_of(:face) b = Boy.new |