diff options
Diffstat (limited to 'activerecord/test')
25 files changed, 379 insertions, 142 deletions
diff --git a/activerecord/test/cases/adapters/mysql/connection_test.rb b/activerecord/test/cases/adapters/mysql/connection_test.rb index b67d70ede7..b965983fec 100644 --- a/activerecord/test/cases/adapters/mysql/connection_test.rb +++ b/activerecord/test/cases/adapters/mysql/connection_test.rb @@ -19,6 +19,9 @@ class MysqlConnectionTest < ActiveRecord::TestCase def test_connect_with_url run_without_connection do |orig| ar_config = ARTest.connection_config['arunit'] + + skip "This test doesn't work with custom socket location" if ar_config['socket'] + url = "mysql://#{ar_config["username"]}@localhost/#{ar_config["database"]}" Klass.establish_connection(url) assert_equal ar_config['database'], Klass.connection.current_database diff --git a/activerecord/test/cases/adapters/postgresql/connection_test.rb b/activerecord/test/cases/adapters/postgresql/connection_test.rb index fa8f339f00..c03660957e 100644 --- a/activerecord/test/cases/adapters/postgresql/connection_test.rb +++ b/activerecord/test/cases/adapters/postgresql/connection_test.rb @@ -108,7 +108,7 @@ module ActiveRecord @connection.verify! new_connection_pid = @connection.query('select pg_backend_pid()') ensure - raw_connection_class.class_eval <<-CODE + raw_connection_class.class_eval <<-CODE, __FILE__, __LINE__ + 1 alias query query_unfake undef query_fake CODE diff --git a/activerecord/test/cases/adapters/postgresql/datatype_test.rb b/activerecord/test/cases/adapters/postgresql/datatype_test.rb index 7351ed9013..33c796191e 100644 --- a/activerecord/test/cases/adapters/postgresql/datatype_test.rb +++ b/activerecord/test/cases/adapters/postgresql/datatype_test.rb @@ -545,13 +545,13 @@ _SQL def test_update_bit_string new_bit_string = '11111111' - new_bit_string_varying = 'FF' + new_bit_string_varying = '11111110' assert @first_bit_string.bit_string = new_bit_string assert @first_bit_string.bit_string_varying = new_bit_string_varying assert @first_bit_string.save assert @first_bit_string.reload - assert_equal @first_bit_string.bit_string, new_bit_string - assert_equal @first_bit_string.bit_string, @first_bit_string.bit_string_varying + assert_equal new_bit_string, @first_bit_string.bit_string + assert_equal new_bit_string_varying, @first_bit_string.bit_string_varying end def test_update_oid diff --git a/activerecord/test/cases/adapters/postgresql/hstore_test.rb b/activerecord/test/cases/adapters/postgresql/hstore_test.rb index 23bafde17b..6640f9b497 100644 --- a/activerecord/test/cases/adapters/postgresql/hstore_test.rb +++ b/activerecord/test/cases/adapters/postgresql/hstore_test.rb @@ -11,15 +11,23 @@ class PostgresqlHstoreTest < ActiveRecord::TestCase def setup @connection = ActiveRecord::Base.connection - begin - @connection.transaction do - @connection.create_table('hstores') do |t| - t.hstore 'tags', :default => '' - end - end - rescue ActiveRecord::StatementInvalid + + unless @connection.supports_extensions? return skip "do not test on PG without hstore" end + + unless @connection.extension_enabled?('hstore') + @connection.enable_extension 'hstore' + @connection.commit_db_transaction + end + + @connection.reconnect! + + @connection.transaction do + @connection.create_table('hstores') do |t| + t.hstore 'tags', :default => '' + end + end @column = Hstore.columns.find { |c| c.name == 'tags' } end @@ -27,6 +35,32 @@ class PostgresqlHstoreTest < ActiveRecord::TestCase @connection.execute 'drop table if exists hstores' end + def test_hstore_included_in_extensions + assert @connection.respond_to?(:extensions), "connection should have a list of extensions" + assert @connection.extensions.include?('hstore'), "extension list should include hstore" + end + + def test_hstore_enabled + assert @connection.extension_enabled?('hstore') + end + + def test_disable_hstore + if @connection.extension_enabled?('hstore') + @connection.disable_extension 'hstore' + assert_not @connection.extension_enabled?('hstore') + end + end + + def test_enable_hstore + if @connection.extension_enabled?('hstore') + @connection.disable_extension 'hstore' + end + + assert_not @connection.extension_enabled?('hstore') + @connection.enable_extension 'hstore' + assert @connection.extension_enabled?('hstore') + end + def test_column assert_equal :hstore, @column.type end diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb index be2d30641e..46f3c38ac5 100644 --- a/activerecord/test/cases/associations/eager_test.rb +++ b/activerecord/test/cases/associations/eager_test.rb @@ -73,6 +73,11 @@ class EagerAssociationTest < ActiveRecord::TestCase end end + def test_has_many_through_with_order + authors = Author.includes(:favorite_authors).to_a + assert_no_queries { authors.map(&:favorite_authors) } + end + def test_with_two_tables_in_from_without_getting_double_quoted posts = Post.select("posts.*").from("authors, posts").eager_load(:comments).where("posts.author_id = authors.id").order("posts.id").to_a assert_equal 2, posts.first.comments.size @@ -1162,4 +1167,10 @@ class EagerAssociationTest < ActiveRecord::TestCase Post.where('1 = 0').scoping { Comment.preload(:post).find(1).post } ) end + + test "preloading does not cache has many association subset when preloaded with a through association" do + author = Author.includes(:comments_with_order_and_conditions, :posts).first + assert_no_queries { assert_equal 2, author.comments_with_order_and_conditions.size } + assert_no_queries { assert_equal 5, author.posts.size, "should not cache a subset of the association" } + 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 fd6d531645..1ddd380f23 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -20,6 +20,8 @@ require 'models/car' require 'models/bulb' require 'models/engine' require 'models/categorization' +require 'models/minivan' +require 'models/speedometer' class HasManyAssociationsTestForCountWithFinderSql < ActiveRecord::TestCase class Invoice < ActiveRecord::Base @@ -1747,4 +1749,12 @@ class HasManyAssociationsTest < ActiveRecord::TestCase david.posts_with_special_categorizations = [] assert_equal [], david.posts_with_special_categorizations end + + test "does not duplicate associations when used with natural primary keys" do + speedometer = Speedometer.create!(id: '4') + speedometer.minivans.create!(minivan_id: 'a-van-red' ,name: 'a van', color: 'red') + + assert_equal 1, speedometer.minivans.to_a.size, "Only one association should be present:\n#{speedometer.minivans.to_a}" + assert_equal 1, speedometer.reload.minivans.to_a.size + end end diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index 4f46459ab3..af1845c937 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -319,27 +319,12 @@ class BasicsTest < ActiveRecord::TestCase assert_equal(true, cb.frickinawesome) end - def test_first_or_create - parrot = Bird.first_or_create(:color => 'green', :name => 'parrot') - assert parrot.persisted? - the_same_parrot = Bird.first_or_create(:color => 'yellow', :name => 'macaw') - assert_equal parrot, the_same_parrot - end - - def test_first_or_create_bang - assert_raises(ActiveRecord::RecordInvalid) { Bird.first_or_create! } - parrot = Bird.first_or_create!(:color => 'green', :name => 'parrot') - assert parrot.persisted? - the_same_parrot = Bird.first_or_create!(:color => 'yellow', :name => 'macaw') - assert_equal parrot, the_same_parrot - end - - def test_first_or_initialize - parrot = Bird.first_or_initialize(:color => 'green', :name => 'parrot') - assert_kind_of Bird, parrot - assert !parrot.persisted? - assert parrot.new_record? - assert parrot.valid? + def test_create_after_initialize_with_array_param + cbs = CustomBulb.create([{ name: 'Dude' }, { name: 'Bob' }]) + assert_equal 'Dude', cbs[0].name + assert_equal 'Bob', cbs[1].name + assert cbs[0].frickinawesome + assert !cbs[1].frickinawesome end def test_load @@ -1462,6 +1447,13 @@ class BasicsTest < ActiveRecord::TestCase assert_match(/\/#{dev.id}$/, dev.cache_key) end + def test_touch_should_raise_error_on_a_new_object + company = Company.new(:rating => 1, :name => "37signals", :firm_name => "37signals") + assert_raises(ActiveRecord::ActiveRecordError) do + company.touch :updated_at + end + end + def test_cache_key_format_is_precise_enough dev = Developer.first key = dev.cache_key diff --git a/activerecord/test/cases/connection_specification/resolver_test.rb b/activerecord/test/cases/connection_specification/resolver_test.rb index 52de0efe7f..c8dfc3244b 100644 --- a/activerecord/test/cases/connection_specification/resolver_test.rb +++ b/activerecord/test/cases/connection_specification/resolver_test.rb @@ -8,42 +8,55 @@ module ActiveRecord Resolver.new(spec, {}).spec.config end + def test_url_invalid_adapter + assert_raises(LoadError) do + resolve 'ridiculous://foo?encoding=utf8' + end + end + + # The abstract adapter is used simply to bypass the bit of code that + # checks that the adapter file can be required in. + def test_url_host_no_db - skip "only if mysql is available" unless current_adapter?(:MysqlAdapter, :Mysql2Adapter) - spec = resolve 'mysql://foo?encoding=utf8' + spec = resolve 'abstract://foo?encoding=utf8' assert_equal({ - :adapter => "mysql", - :host => "foo", - :encoding => "utf8" }, spec) + adapter: "abstract", + host: "foo", + encoding: "utf8" }, spec) end def test_url_host_db - skip "only if mysql is available" unless current_adapter?(:MysqlAdapter, :Mysql2Adapter) - spec = resolve 'mysql://foo/bar?encoding=utf8' + spec = resolve 'abstract://foo/bar?encoding=utf8' assert_equal({ - :adapter => "mysql", - :database => "bar", - :host => "foo", - :encoding => "utf8" }, spec) + adapter: "abstract", + database: "bar", + host: "foo", + encoding: "utf8" }, spec) end def test_url_port - skip "only if mysql is available" unless current_adapter?(:MysqlAdapter, :Mysql2Adapter) - spec = resolve 'mysql://foo:123?encoding=utf8' + spec = resolve 'abstract://foo:123?encoding=utf8' assert_equal({ - :adapter => "mysql", - :port => 123, - :host => "foo", - :encoding => "utf8" }, spec) + adapter: "abstract", + port: 123, + host: "foo", + encoding: "utf8" }, spec) end def test_encoded_password - skip "only if mysql is available" unless current_adapter?(:MysqlAdapter, :Mysql2Adapter) password = 'am@z1ng_p@ssw0rd#!' encoded_password = URI.encode_www_form_component(password) - spec = resolve "mysql://foo:#{encoded_password}@localhost/bar" + spec = resolve "abstract://foo:#{encoded_password}@localhost/bar" assert_equal password, spec[:password] end + + def test_descriptive_error_message_when_adapter_is_missing + error = assert_raise(LoadError) do + resolve(adapter: 'non-existing') + end + + assert_match "Could not load 'active_record/connection_adapters/non-existing_adapter'", error.message + end end end end diff --git a/activerecord/test/cases/explain_test.rb b/activerecord/test/cases/explain_test.rb index aa2a6d7509..b1d276f9eb 100644 --- a/activerecord/test/cases/explain_test.rb +++ b/activerecord/test/cases/explain_test.rb @@ -14,46 +14,9 @@ if ActiveRecord::Base.connection.supports_explain? base.connection end - def test_logging_query_plan_with_logger - base.logger.expects(:warn).with do |message| - message.starts_with?('EXPLAIN for:') - end - - with_threshold(0) do - Car.where(:name => 'honda').to_a - end - end - - def test_logging_query_plan_without_logger - original = base.logger - base.logger = nil - - class << base.logger - def warn; raise "Should not be called" end - end - - with_threshold(0) do - car = Car.where(:name => 'honda').first - assert_equal 'honda', car.name - end - ensure - base.logger = original - end - - def test_collect_queries_for_explain - base.auto_explain_threshold_in_seconds = nil - queries = Thread.current[:available_queries_for_explain] = [] - - with_threshold(0) do - Car.where(:name => 'honda').to_a - end - - sql, binds = queries[0] - assert_match "SELECT", sql - assert_match "honda", sql - assert_equal [], binds - ensure - Thread.current[:available_queries_for_explain] = nil + def test_relation_explain + message = Car.where(:name => 'honda').explain + assert_match(/^EXPLAIN for:/, message) end def test_collecting_queries_for_explain @@ -68,16 +31,6 @@ if ActiveRecord::Base.connection.supports_explain? assert_equal [cars(:honda)], result end - def test_logging_query_plan_when_counting_by_sql - base.logger.expects(:warn).with do |message| - message.starts_with?('EXPLAIN for:') - end - - with_threshold(0) do - Car.count_by_sql "SELECT COUNT(*) FROM cars WHERE name = 'honda'" - end - end - def test_exec_explain_with_no_binds sqls = %w(foo bar) binds = [[], []] @@ -113,25 +66,8 @@ if ActiveRecord::Base.connection.supports_explain? base.logger.expects(:warn).never - with_threshold(0) do - Car.where(:name => 'honda').to_a - end - end - - def test_silence_auto_explain - base.expects(:collecting_sqls_for_explain).never - base.logger.expects(:warn).never - base.silence_auto_explain do - with_threshold(0) { Car.all.to_a } - end + Car.where(:name => 'honda').to_a end - def with_threshold(threshold) - current_threshold = base.auto_explain_threshold_in_seconds - base.auto_explain_threshold_in_seconds = threshold - yield - ensure - base.auto_explain_threshold_in_seconds = current_threshold - end end end diff --git a/activerecord/test/cases/migration/rename_column_test.rb b/activerecord/test/cases/migration/columns_test.rb index 8f6918d06a..e52809f0f8 100644 --- a/activerecord/test/cases/migration/rename_column_test.rb +++ b/activerecord/test/cases/migration/columns_test.rb @@ -2,7 +2,7 @@ require "cases/migration/helper" module ActiveRecord class Migration - class RenameColumnTest < ActiveRecord::TestCase + class ColumnsTest < ActiveRecord::TestCase include ActiveRecord::Migration::TestHelper self.use_transactional_fixtures = false @@ -86,8 +86,37 @@ module ActiveRecord assert_equal 1, connection.indexes('test_models').size rename_column "test_models", "hat_name", "name" - # FIXME: should we rename the index if it's name was autogenerated by rails? - assert_equal ['index_test_models_on_hat_name'], connection.indexes('test_models').map(&:name) + + assert_equal ['index_test_models_on_name'], connection.indexes('test_models').map(&:name) + end + + def test_rename_column_with_multi_column_index + add_column "test_models", :hat_size, :integer + add_column "test_models", :hat_style, :string, limit: 100 + add_index "test_models", ["hat_style", "hat_size"], unique: true + + rename_column "test_models", "hat_size", 'size' + if current_adapter? :OracleAdapter + assert_equal ['i_test_models_hat_style_size'], connection.indexes('test_models').map(&:name) + else + assert_equal ['index_test_models_on_hat_style_and_size'], connection.indexes('test_models').map(&:name) + end + + rename_column "test_models", "hat_style", 'style' + if current_adapter? :OracleAdapter + assert_equal ['i_test_models_style_size'], connection.indexes('test_models').map(&:name) + else + assert_equal ['index_test_models_on_style_and_size'], connection.indexes('test_models').map(&:name) + end + end + + def test_rename_column_does_not_rename_custom_named_index + add_column "test_models", :hat_name, :string + add_index :test_models, :hat_name, :name => 'idx_hat_name' + + assert_equal 1, connection.indexes('test_models').size + rename_column "test_models", "hat_name", "name" + assert_equal ['idx_hat_name'], connection.indexes('test_models').map(&:name) end def test_remove_column_with_index @@ -107,7 +136,7 @@ module ActiveRecord assert_equal 1, connection.indexes('test_models').size remove_column("test_models", "hat_size") - # Every database and/or database adapter has their own behavior + # Every database and/or database adapter has their own behavior # if it drops the multi-column index when any of the indexed columns dropped by remove_column. if current_adapter?(:PostgreSQLAdapter, :OracleAdapter) assert_equal [], connection.indexes('test_models').map(&:name) @@ -197,6 +226,17 @@ module ActiveRecord assert_equal ['test_models_categories_idx'], connection.indexes('test_models').map(&:name) end + def test_change_column_with_long_index_name + table_name_prefix = 'test_models_' + long_index_name = table_name_prefix + ('x' * (connection.allowed_index_name_length - table_name_prefix.length)) + add_column "test_models", "category", :string + add_index :test_models, :category, name: long_index_name + + change_column "test_models", "category", :string, null: false, default: 'article' + + assert_equal [long_index_name], connection.indexes('test_models').map(&:name) + end + def test_change_column_default add_column "test_models", "first_name", :string connection.change_column_default "test_models", "first_name", "Tester" @@ -213,6 +253,20 @@ module ActiveRecord def test_remove_column_no_second_parameter_raises_exception assert_raise(ArgumentError) { connection.remove_column("funny") } end + + def test_removing_and_renaming_column_preserves_custom_primary_key + connection.create_table "my_table", primary_key: "my_table_id", force: true do |t| + t.integer "col_one" + t.string "col_two", limit: 128, null: false + end + + remove_column("my_table", "col_two") + rename_column("my_table", "col_one", "col_three") + + assert_equal 'my_table_id', connection.primary_key('my_table') + ensure + connection.drop_table(:my_table) rescue nil + end end end end diff --git a/activerecord/test/cases/migration/index_test.rb b/activerecord/test/cases/migration/index_test.rb index a41f2c10f0..0e375af6e8 100644 --- a/activerecord/test/cases/migration/index_test.rb +++ b/activerecord/test/cases/migration/index_test.rb @@ -55,19 +55,31 @@ module ActiveRecord assert_raise(ArgumentError) { connection.remove_index(table_name, "no_such_index") } end - def test_add_index_name_length_limit - good_index_name = 'x' * connection.index_name_length + def test_add_index_works_with_long_index_names + connection.add_index(table_name, "foo", name: good_index_name) + + assert connection.index_name_exists?(table_name, good_index_name, false) + connection.remove_index(table_name, name: good_index_name) + end + + def test_add_index_does_not_accept_too_long_index_names too_long_index_name = good_index_name + 'x' - assert_raises(ArgumentError) { - connection.add_index(table_name, "foo", :name => too_long_index_name) + e = assert_raises(ArgumentError) { + connection.add_index(table_name, "foo", name: too_long_index_name) } + assert_match(/too long; the limit is #{connection.allowed_index_name_length} characters/, e.message) assert_not connection.index_name_exists?(table_name, too_long_index_name, false) connection.add_index(table_name, "foo", :name => good_index_name) + end + + def test_internal_index_with_name_matching_database_limit + good_index_name = 'x' * connection.index_name_length + connection.add_index(table_name, "foo", name: good_index_name, internal: true) assert connection.index_name_exists?(table_name, good_index_name, false) - connection.remove_index(table_name, :name => good_index_name) + connection.remove_index(table_name, name: good_index_name) end def test_index_symbol_names @@ -196,6 +208,12 @@ module ActiveRecord connection.remove_index("testings", "last_name") assert !connection.index_exists?("testings", "last_name") end + + private + def good_index_name + 'x' * connection.allowed_index_name_length + end + end end end diff --git a/activerecord/test/cases/migration/rename_table_test.rb b/activerecord/test/cases/migration/rename_table_test.rb index 21901bec3c..22dbd7c38b 100644 --- a/activerecord/test/cases/migration/rename_table_test.rb +++ b/activerecord/test/cases/migration/rename_table_test.rb @@ -63,7 +63,17 @@ module ActiveRecord connection.enable_identity_insert("octopi", false) if current_adapter?(:SybaseAdapter) assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', connection.select_value("SELECT url FROM octopi WHERE id=1") - assert connection.indexes(:octopi).first.columns.include?("url") + index = connection.indexes(:octopi).first + assert index.columns.include?("url") + assert_equal 'index_octopi_on_url', index.name + end + + def test_rename_table_does_not_rename_custom_named_index + add_index :test_models, :url, name: 'special_url_idx' + + rename_table :test_models, :octopi + + assert_equal ['special_url_idx'], connection.indexes(:octopi).map(&:name) end def test_rename_table_for_postgresql_should_also_rename_default_sequence diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb index b936cca875..8156f99037 100644 --- a/activerecord/test/cases/persistence_test.rb +++ b/activerecord/test/cases/persistence_test.rb @@ -399,6 +399,14 @@ class PersistencesTest < ActiveRecord::TestCase assert_raises(ActiveRecord::ActiveRecordError) { minivan.update_attribute(:color, 'black') } end + def test_string_ids + # FIXME: Fix this failing test + skip "Failing test. We need this fixed before 4.0.0" + mv = Minivan.where(:minivan_id => 1234).first_or_initialize + assert mv.new_record? + assert_equal '1234', mv.minivan_id + end + def test_update_attribute_with_one_updated t = Topic.first t.update_attribute(:title, 'super_title') diff --git a/activerecord/test/cases/quoting_test.rb b/activerecord/test/cases/quoting_test.rb index 3dd11ae89d..0ad05223d4 100644 --- a/activerecord/test/cases/quoting_test.rb +++ b/activerecord/test/cases/quoting_test.rb @@ -122,35 +122,35 @@ module ActiveRecord def test_quote_float float = 1.2 assert_equal float.to_s, @quoter.quote(float, nil) - assert_equal float.to_s, @quoter.quote(float, Object.new) + assert_equal float.to_s, @quoter.quote(float, FakeColumn.new(:float)) end def test_quote_fixnum fixnum = 1 assert_equal fixnum.to_s, @quoter.quote(fixnum, nil) - assert_equal fixnum.to_s, @quoter.quote(fixnum, Object.new) + assert_equal fixnum.to_s, @quoter.quote(fixnum, FakeColumn.new(:integer)) end def test_quote_bignum bignum = 1 << 100 assert_equal bignum.to_s, @quoter.quote(bignum, nil) - assert_equal bignum.to_s, @quoter.quote(bignum, Object.new) + assert_equal bignum.to_s, @quoter.quote(bignum, FakeColumn.new(:integer)) end def test_quote_bigdecimal bigdec = BigDecimal.new((1 << 100).to_s) assert_equal bigdec.to_s('F'), @quoter.quote(bigdec, nil) - assert_equal bigdec.to_s('F'), @quoter.quote(bigdec, Object.new) + assert_equal bigdec.to_s('F'), @quoter.quote(bigdec, FakeColumn.new(:decimal)) end def test_dates_and_times @quoter.extend(Module.new { def quoted_date(value) 'lol' end }) assert_equal "'lol'", @quoter.quote(Date.today, nil) - assert_equal "'lol'", @quoter.quote(Date.today, Object.new) + assert_equal "'lol'", @quoter.quote(Date.today, FakeColumn.new(:date)) assert_equal "'lol'", @quoter.quote(Time.now, nil) - assert_equal "'lol'", @quoter.quote(Time.now, Object.new) + assert_equal "'lol'", @quoter.quote(Time.now, FakeColumn.new(:time)) assert_equal "'lol'", @quoter.quote(DateTime.now, nil) - assert_equal "'lol'", @quoter.quote(DateTime.now, Object.new) + assert_equal "'lol'", @quoter.quote(DateTime.now, FakeColumn.new(:datetime)) end def test_crazy_object diff --git a/activerecord/test/cases/relation/where_test.rb b/activerecord/test/cases/relation/where_test.rb index c43c7601a2..53cdf89b1f 100644 --- a/activerecord/test/cases/relation/where_test.rb +++ b/activerecord/test/cases/relation/where_test.rb @@ -108,5 +108,30 @@ module ActiveRecord assert_equal 4, Edge.where(blank).order("sink_id").to_a.size end end + + def test_where_with_integer_for_string_column + count = Post.where(:title => 0).count + assert_equal 0, count + end + + def test_where_with_float_for_string_column + count = Post.where(:title => 0.0).count + assert_equal 0, count + end + + def test_where_with_boolean_for_string_column + count = Post.where(:title => false).count + assert_equal 0, count + end + + def test_where_with_decimal_for_string_column + count = Post.where(:title => BigDecimal.new(0)).count + assert_equal 0, count + end + + def test_where_with_duration_for_string_column + count = Post.where(:title => 0.seconds).count + assert_equal 0, count + end end end diff --git a/activerecord/test/cases/relation_scoping_test.rb b/activerecord/test/cases/relation_scoping_test.rb index 7388324a0d..8e6c38706f 100644 --- a/activerecord/test/cases/relation_scoping_test.rb +++ b/activerecord/test/cases/relation_scoping_test.rb @@ -391,19 +391,19 @@ class DefaultScopingTest < ActiveRecord::TestCase def test_default_scope_with_inheritance wheres = InheritedPoorDeveloperCalledJamis.all.where_values_hash assert_equal "Jamis", wheres[:name] - assert_equal 50000, wheres[:salary] + assert_equal Arel.sql("50000"), wheres[:salary] end def test_default_scope_with_module_includes wheres = ModuleIncludedPoorDeveloperCalledJamis.all.where_values_hash assert_equal "Jamis", wheres[:name] - assert_equal 50000, wheres[:salary] + assert_equal Arel.sql("50000"), wheres[:salary] end def test_default_scope_with_multiple_calls wheres = MultiplePoorDeveloperCalledJamis.all.where_values_hash assert_equal "Jamis", wheres[:name] - assert_equal 50000, wheres[:salary] + assert_equal Arel.sql("50000"), wheres[:salary] end def test_scope_overwrites_default diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index 379c0c0758..8298d7534c 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -321,6 +321,22 @@ class RelationTest < ActiveRecord::TestCase assert_equal 1, person_with_reader_and_post.size end + def test_no_arguments_to_query_methods_raise_errors + assert_raises(ArgumentError) { Topic.references() } + assert_raises(ArgumentError) { Topic.includes() } + assert_raises(ArgumentError) { Topic.preload() } + assert_raises(ArgumentError) { Topic.group() } + assert_raises(ArgumentError) { Topic.reorder() } + end + + def test_blank_like_arguments_to_query_methods_dont_raise_errors + assert_nothing_raised { Topic.references([]) } + assert_nothing_raised { Topic.includes([]) } + assert_nothing_raised { Topic.preload([]) } + assert_nothing_raised { Topic.group([]) } + assert_nothing_raised { Topic.reorder([]) } + end + def test_scoped_responds_to_delegated_methods relation = Topic.all diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb index cae12e0e3a..bfecc0d1e9 100644 --- a/activerecord/test/cases/schema_dumper_test.rb +++ b/activerecord/test/cases/schema_dumper_test.rb @@ -1,6 +1,5 @@ require "cases/helper" - class SchemaDumperTest < ActiveRecord::TestCase def setup super @@ -231,6 +230,21 @@ class SchemaDumperTest < ActiveRecord::TestCase end if current_adapter?(:PostgreSQLAdapter) + def test_schema_dump_includes_extensions + connection = ActiveRecord::Base.connection + skip unless connection.supports_extensions? + + connection.stubs(:extensions).returns(['hstore']) + output = standard_dump + assert_match "# These are extensions that must be enabled", output + assert_match %r{enable_extension "hstore"}, output + + connection.stubs(:extensions).returns([]) + output = standard_dump + assert_no_match "# These are extensions that must be enabled", output + assert_no_match %r{enable_extension}, output + end + def test_schema_dump_includes_xml_shorthand_definition output = standard_dump if %r{create_table "postgresql_xml_data_type"} =~ output diff --git a/activerecord/test/cases/store_test.rb b/activerecord/test/cases/store_test.rb index 43bf285ba9..3e32d866ee 100644 --- a/activerecord/test/cases/store_test.rb +++ b/activerecord/test/cases/store_test.rb @@ -35,6 +35,12 @@ class StoreTest < ActiveRecord::TestCase assert_equal '(123) 456-7890', @john.phone_number end + test "overriding a read accessor using super" do + @john.settings[:color] = nil + + assert_equal 'red', @john.color + end + test "updating the store will mark it as changed" do @john.color = 'red' assert @john.settings_changed? @@ -66,6 +72,12 @@ class StoreTest < ActiveRecord::TestCase assert_equal '1234567890', @john.settings[:phone_number] end + test "overriding a write accessor using super" do + @john.color = 'yellow' + + assert_equal 'blue', @john.color + end + test "preserve store attributes data in HashWithIndifferentAccess format without any conversion" do @john.json_data = ActiveSupport::HashWithIndifferentAccess.new(:height => 'tall', 'weight' => 'heavy') @john.height = 'low' diff --git a/activerecord/test/cases/tasks/database_tasks_test.rb b/activerecord/test/cases/tasks/database_tasks_test.rb index 659d5eae72..3bfbc92afd 100644 --- a/activerecord/test/cases/tasks/database_tasks_test.rb +++ b/activerecord/test/cases/tasks/database_tasks_test.rb @@ -31,6 +31,12 @@ module ActiveRecord ActiveRecord::Tasks::DatabaseTasks.register_task(/foo/, klazz) ActiveRecord::Tasks::DatabaseTasks.structure_dump({'adapter' => :foo}, "awesome-file.sql") end + + def test_unregistered_task + assert_raise(ActiveRecord::Tasks::DatabaseNotSupported) do + ActiveRecord::Tasks::DatabaseTasks.structure_dump({'adapter' => :bar}, "awesome-file.sql") + end + end end class DatabaseTasksCreateTest < ActiveRecord::TestCase diff --git a/activerecord/test/cases/transaction_callbacks_test.rb b/activerecord/test/cases/transaction_callbacks_test.rb index 869892e33f..eb4ffd4498 100644 --- a/activerecord/test/cases/transaction_callbacks_test.rb +++ b/activerecord/test/cases/transaction_callbacks_test.rb @@ -5,9 +5,29 @@ class TransactionCallbacksTest < ActiveRecord::TestCase self.use_transactional_fixtures = false fixtures :topics + class ReplyWithCallbacks < ActiveRecord::Base + self.table_name = :topics + + belongs_to :topic, foreign_key: "parent_id" + + validates_presence_of :content + + after_commit :do_after_commit, on: :create + + def history + @history ||= [] + end + + def do_after_commit + history << :commit_on_create + end + end + class TopicWithCallbacks < ActiveRecord::Base self.table_name = :topics + has_many :replies, class_name: "ReplyWithCallbacks", foreign_key: "parent_id" + after_commit{|record| record.send(:do_after_commit, nil)} after_commit(:on => :create){|record| record.send(:do_after_commit, :create)} after_commit(:on => :update){|record| record.send(:do_after_commit, :update)} @@ -93,6 +113,13 @@ class TransactionCallbacksTest < ActiveRecord::TestCase assert_equal [:commit_on_create], @new_record.history end + def test_only_call_after_commit_on_create_after_transaction_commits_for_new_record_if_create_succeeds_creating_through_association + topic = TopicWithCallbacks.create!(:title => "New topic", :written_on => Date.today) + reply = topic.replies.create + + assert_equal [], reply.history + end + def test_call_after_rollback_after_transaction_rollsback @first.after_commit_block{|r| r.history << :after_commit} @first.after_rollback_block{|r| r.history << :after_rollback} @@ -285,3 +312,38 @@ class SaveFromAfterCommitBlockTest < ActiveRecord::TestCase assert_equal true, topic.record_updated end end + +class CallbacksOnMultipleActionsTest < ActiveRecord::TestCase + self.use_transactional_fixtures = false + + class TopicWithCallbacksOnMultipleActions < ActiveRecord::Base + self.table_name = :topics + + after_commit(on: [:create, :destroy]) { |record| record.history << :create_and_destroy } + after_commit(on: [:create, :update]) { |record| record.history << :create_and_update } + after_commit(on: [:update, :destroy]) { |record| record.history << :update_and_destroy } + + def clear_history + @history = [] + end + + def history + @history ||= [] + end + end + + def test_after_commit_on_multiple_actions + topic = TopicWithCallbacksOnMultipleActions.new + topic.save + assert_equal [:create_and_update, :create_and_destroy], topic.history + + topic.clear_history + topic.approved = true + topic.save + assert_equal [:update_and_destroy, :create_and_update], topic.history + + topic.clear_history + topic.destroy + assert_equal [:update_and_destroy, :create_and_destroy], topic.history + end +end diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb index 546737b398..6d66342fa5 100644 --- a/activerecord/test/cases/transactions_test.rb +++ b/activerecord/test/cases/transactions_test.rb @@ -460,7 +460,7 @@ class TransactionTest < ActiveRecord::TestCase assert !transaction.state.committed? transaction.perform_rollback - + assert transaction.state.rolledback? assert !transaction.state.committed? end @@ -474,7 +474,7 @@ class TransactionTest < ActiveRecord::TestCase assert !transaction.state.committed? transaction.perform_commit - + assert !transaction.state.rolledback? assert transaction.state.committed? end diff --git a/activerecord/test/models/admin/user.rb b/activerecord/test/models/admin/user.rb index 024fede266..4c3b71e8f9 100644 --- a/activerecord/test/models/admin/user.rb +++ b/activerecord/test/models/admin/user.rb @@ -27,4 +27,13 @@ class Admin::User < ActiveRecord::Base def phone_number=(value) write_store_attribute(:settings, :phone_number, value && value.gsub(/[^\d]/,'')) end + + def color + super || 'red' + end + + def color=(value) + value = 'blue' unless %w(black red green blue).include?(value) + super + end end diff --git a/activerecord/test/models/speedometer.rb b/activerecord/test/models/speedometer.rb index 0a7d38d8ec..497c3aba9a 100644 --- a/activerecord/test/models/speedometer.rb +++ b/activerecord/test/models/speedometer.rb @@ -1,4 +1,6 @@ class Speedometer < ActiveRecord::Base self.primary_key = :speedometer_id belongs_to :dashboard + + has_many :minivans end diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index cd9835259a..d789b6cb7a 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -540,6 +540,8 @@ ActiveRecord::Schema.define do create_table :price_estimates, :force => true do |t| t.string :estimate_of_type t.integer :estimate_of_id + t.string :thing_type + t.integer :thing_id t.integer :price end |