aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/test')
-rw-r--r--activerecord/test/active_record/connection_adapters/fake_adapter.rb7
-rw-r--r--activerecord/test/cases/adapter_test.rb241
-rw-r--r--activerecord/test/cases/adapters/mysql/active_schema_test.rb8
-rw-r--r--activerecord/test/cases/adapters/mysql/case_sensitivity_test.rb35
-rw-r--r--activerecord/test/cases/adapters/mysql/schema_test.rb8
-rw-r--r--activerecord/test/cases/adapters/mysql/statement_pool_test.rb23
-rw-r--r--activerecord/test/cases/adapters/mysql2/case_sensitivity_test.rb35
-rw-r--r--activerecord/test/cases/adapters/mysql2/explain_test.rb26
-rw-r--r--activerecord/test/cases/adapters/mysql2/schema_test.rb8
-rw-r--r--activerecord/test/cases/adapters/postgresql/explain_test.rb28
-rw-r--r--activerecord/test/cases/adapters/postgresql/schema_test.rb76
-rw-r--r--activerecord/test/cases/adapters/postgresql/statement_pool_test.rb39
-rw-r--r--activerecord/test/cases/adapters/postgresql/utils_test.rb18
-rw-r--r--activerecord/test/cases/adapters/postgresql/view_test.rb2
-rw-r--r--activerecord/test/cases/adapters/sqlite3/explain_test.rb26
-rw-r--r--activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb23
-rw-r--r--activerecord/test/cases/adapters/sqlite3/statement_pool_test.rb24
-rw-r--r--activerecord/test/cases/associations/belongs_to_associations_test.rb14
-rw-r--r--activerecord/test/cases/associations/eager_load_includes_full_sti_class_test.rb2
-rw-r--r--activerecord/test/cases/associations/extension_test.rb18
-rw-r--r--activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb40
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb73
-rw-r--r--activerecord/test/cases/associations/has_many_through_associations_test.rb42
-rw-r--r--activerecord/test/cases/associations/join_model_test.rb2
-rw-r--r--activerecord/test/cases/associations/nested_through_associations_test.rb13
-rw-r--r--activerecord/test/cases/associations_test.rb16
-rw-r--r--activerecord/test/cases/attribute_methods/read_test.rb1
-rw-r--r--activerecord/test/cases/attribute_methods_test.rb92
-rw-r--r--activerecord/test/cases/autosave_association_test.rb11
-rw-r--r--activerecord/test/cases/base_test.rb292
-rw-r--r--activerecord/test/cases/batches_test.rb20
-rw-r--r--activerecord/test/cases/calculations_test.rb27
-rw-r--r--activerecord/test/cases/callbacks_test.rb14
-rw-r--r--activerecord/test/cases/column_definition_test.rb32
-rw-r--r--activerecord/test/cases/connection_adapters/abstract_adapter_test.rb54
-rw-r--r--activerecord/test/cases/connection_adapters/connection_handler_test.rb19
-rw-r--r--activerecord/test/cases/connection_adapters/schema_cache_test.rb49
-rw-r--r--activerecord/test/cases/connection_management_test.rb34
-rw-r--r--activerecord/test/cases/connection_pool_test.rb72
-rw-r--r--activerecord/test/cases/connection_specification/resolver_test.rb41
-rw-r--r--activerecord/test/cases/finder_test.rb46
-rw-r--r--activerecord/test/cases/fixtures_test.rb50
-rw-r--r--activerecord/test/cases/inheritance_test.rb4
-rw-r--r--activerecord/test/cases/invertible_migration_test.rb39
-rw-r--r--activerecord/test/cases/lifecycle_test.rb12
-rw-r--r--activerecord/test/cases/locking_test.rb65
-rw-r--r--activerecord/test/cases/mass_assignment_security_test.rb4
-rw-r--r--activerecord/test/cases/method_scoping_test.rb8
-rw-r--r--activerecord/test/cases/migration/command_recorder_test.rb4
-rw-r--r--activerecord/test/cases/migration_test.rb156
-rw-r--r--activerecord/test/cases/multiple_db_test.rb1
-rw-r--r--activerecord/test/cases/named_scope_test.rb2
-rw-r--r--activerecord/test/cases/nested_attributes_test.rb8
-rw-r--r--activerecord/test/cases/persistence_test.rb17
-rw-r--r--activerecord/test/cases/pooled_connections_test.rb74
-rw-r--r--activerecord/test/cases/primary_keys_test.rb23
-rw-r--r--activerecord/test/cases/query_cache_test.rb49
-rw-r--r--activerecord/test/cases/reflection_test.rb31
-rw-r--r--activerecord/test/cases/relation_scoping_test.rb20
-rw-r--r--activerecord/test/cases/relation_test.rb2
-rw-r--r--activerecord/test/cases/relations_test.rb204
-rw-r--r--activerecord/test/cases/schema_dumper_test.rb22
-rw-r--r--activerecord/test/cases/serialization_test.rb13
-rw-r--r--activerecord/test/cases/session_store/session_test.rb2
-rw-r--r--activerecord/test/cases/store_test.rb34
-rw-r--r--activerecord/test/cases/timestamp_test.rb10
-rw-r--r--activerecord/test/cases/transaction_callbacks_test.rb4
-rw-r--r--activerecord/test/cases/transactions_test.rb3
-rw-r--r--activerecord/test/cases/unconnected_test.rb2
-rw-r--r--activerecord/test/cases/validations_test.rb2
-rw-r--r--activerecord/test/cases/yaml_serialization_test.rb5
-rw-r--r--activerecord/test/config.example.yml2
-rw-r--r--activerecord/test/fixtures/pirates.yml4
-rw-r--r--activerecord/test/fixtures/tasks.yml2
-rw-r--r--activerecord/test/models/admin/user.rb3
-rw-r--r--activerecord/test/models/author.rb1
-rw-r--r--activerecord/test/models/car.rb2
-rw-r--r--activerecord/test/models/company.rb3
-rw-r--r--activerecord/test/models/contact.rb13
-rw-r--r--activerecord/test/models/country.rb2
-rw-r--r--activerecord/test/models/dashboard.rb4
-rw-r--r--activerecord/test/models/developer.rb9
-rw-r--r--activerecord/test/models/joke.rb4
-rw-r--r--activerecord/test/models/keyboard.rb2
-rw-r--r--activerecord/test/models/legacy_thing.rb2
-rw-r--r--activerecord/test/models/liquid.rb2
-rw-r--r--activerecord/test/models/minivan.rb2
-rw-r--r--activerecord/test/models/mixed_case_monkey.rb2
-rw-r--r--activerecord/test/models/owner.rb2
-rw-r--r--activerecord/test/models/parrot.rb3
-rw-r--r--activerecord/test/models/pet.rb2
-rw-r--r--activerecord/test/models/post.rb14
-rw-r--r--activerecord/test/models/speedometer.rb4
-rw-r--r--activerecord/test/models/string_key_object.rb2
-rw-r--r--activerecord/test/models/subscriber.rb2
-rw-r--r--activerecord/test/models/topic.rb9
-rw-r--r--activerecord/test/models/toy.rb4
-rw-r--r--activerecord/test/models/treaty.rb2
-rw-r--r--activerecord/test/models/warehouse_thing.rb4
-rw-r--r--activerecord/test/schema/mysql2_specific_schema.rb13
-rw-r--r--activerecord/test/schema/mysql_specific_schema.rb11
-rw-r--r--activerecord/test/schema/schema.rb9
102 files changed, 2034 insertions, 627 deletions
diff --git a/activerecord/test/active_record/connection_adapters/fake_adapter.rb b/activerecord/test/active_record/connection_adapters/fake_adapter.rb
index 1c2942170e..267ea8bb6b 100644
--- a/activerecord/test/active_record/connection_adapters/fake_adapter.rb
+++ b/activerecord/test/active_record/connection_adapters/fake_adapter.rb
@@ -9,11 +9,16 @@ module ActiveRecord
class FakeAdapter < AbstractAdapter
attr_accessor :tables, :primary_keys
+ @columns = Hash.new { |h,k| h[k] = [] }
+ class << self
+ attr_reader :columns
+ end
+
def initialize(connection, logger)
super
@tables = []
@primary_keys = {}
- @columns = Hash.new { |h,k| h[k] = [] }
+ @columns = self.class.columns
end
def primary_key(table)
diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb
index 3942e7bb41..5d5ff53004 100644
--- a/activerecord/test/cases/adapter_test.rb
+++ b/activerecord/test/cases/adapter_test.rb
@@ -1,155 +1,160 @@
require "cases/helper"
-class AdapterTest < ActiveRecord::TestCase
- def setup
- @connection = ActiveRecord::Base.connection
- end
-
- def test_tables
- tables = @connection.tables
- assert tables.include?("accounts")
- assert tables.include?("authors")
- assert tables.include?("tasks")
- assert tables.include?("topics")
- end
+module ActiveRecord
+ class AdapterTest < ActiveRecord::TestCase
+ def setup
+ @connection = ActiveRecord::Base.connection
+ end
- def test_table_exists?
- assert @connection.table_exists?("accounts")
- assert !@connection.table_exists?("nonexistingtable")
- end
+ def test_tables
+ tables = @connection.tables
+ assert tables.include?("accounts")
+ assert tables.include?("authors")
+ assert tables.include?("tasks")
+ assert tables.include?("topics")
+ end
- def test_indexes
- idx_name = "accounts_idx"
-
- if @connection.respond_to?(:indexes)
- indexes = @connection.indexes("accounts")
- assert indexes.empty?
-
- @connection.add_index :accounts, :firm_id, :name => idx_name
- indexes = @connection.indexes("accounts")
- assert_equal "accounts", indexes.first.table
- # OpenBase does not have the concept of a named index
- # Indexes are merely properties of columns.
- assert_equal idx_name, indexes.first.name unless current_adapter?(:OpenBaseAdapter)
- assert !indexes.first.unique
- assert_equal ["firm_id"], indexes.first.columns
- else
- warn "#{@connection.class} does not respond to #indexes"
+ def test_table_exists?
+ assert @connection.table_exists?("accounts")
+ assert !@connection.table_exists?("nonexistingtable")
end
- ensure
- @connection.remove_index(:accounts, :name => idx_name) rescue nil
- end
+ def test_indexes
+ idx_name = "accounts_idx"
+
+ if @connection.respond_to?(:indexes)
+ indexes = @connection.indexes("accounts")
+ assert indexes.empty?
+
+ @connection.add_index :accounts, :firm_id, :name => idx_name
+ indexes = @connection.indexes("accounts")
+ assert_equal "accounts", indexes.first.table
+ # OpenBase does not have the concept of a named index
+ # Indexes are merely properties of columns.
+ assert_equal idx_name, indexes.first.name unless current_adapter?(:OpenBaseAdapter)
+ assert !indexes.first.unique
+ assert_equal ["firm_id"], indexes.first.columns
+ else
+ warn "#{@connection.class} does not respond to #indexes"
+ end
- def test_current_database
- if @connection.respond_to?(:current_database)
- assert_equal ARTest.connection_config['arunit']['database'], @connection.current_database
+ ensure
+ @connection.remove_index(:accounts, :name => idx_name) rescue nil
end
- end
- if current_adapter?(:MysqlAdapter)
- def test_charset
- assert_not_nil @connection.charset
- assert_not_equal 'character_set_database', @connection.charset
- assert_equal @connection.show_variable('character_set_database'), @connection.charset
+ def test_current_database
+ if @connection.respond_to?(:current_database)
+ assert_equal ARTest.connection_config['arunit']['database'], @connection.current_database
+ end
end
- def test_collation
- assert_not_nil @connection.collation
- assert_not_equal 'collation_database', @connection.collation
- assert_equal @connection.show_variable('collation_database'), @connection.collation
- end
+ if current_adapter?(:MysqlAdapter)
+ def test_charset
+ assert_not_nil @connection.charset
+ assert_not_equal 'character_set_database', @connection.charset
+ assert_equal @connection.show_variable('character_set_database'), @connection.charset
+ end
- def test_show_nonexistent_variable_returns_nil
- assert_nil @connection.show_variable('foo_bar_baz')
- end
+ def test_collation
+ assert_not_nil @connection.collation
+ assert_not_equal 'collation_database', @connection.collation
+ assert_equal @connection.show_variable('collation_database'), @connection.collation
+ end
- def test_not_specifying_database_name_for_cross_database_selects
- begin
- assert_nothing_raised do
- ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['arunit'].except(:database))
+ def test_show_nonexistent_variable_returns_nil
+ assert_nil @connection.show_variable('foo_bar_baz')
+ end
- config = ARTest.connection_config
- ActiveRecord::Base.connection.execute(
- "SELECT #{config['arunit']['database']}.pirates.*, #{config['arunit2']['database']}.courses.* " \
- "FROM #{config['arunit']['database']}.pirates, #{config['arunit2']['database']}.courses"
- )
+ def test_not_specifying_database_name_for_cross_database_selects
+ begin
+ assert_nothing_raised do
+ ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['arunit'].except(:database))
+
+ config = ARTest.connection_config
+ ActiveRecord::Base.connection.execute(
+ "SELECT #{config['arunit']['database']}.pirates.*, #{config['arunit2']['database']}.courses.* " \
+ "FROM #{config['arunit']['database']}.pirates, #{config['arunit2']['database']}.courses"
+ )
+ end
+ ensure
+ ActiveRecord::Base.establish_connection 'arunit'
end
- ensure
- ActiveRecord::Base.establish_connection 'arunit'
end
end
- end
- def test_table_alias
- def @connection.test_table_alias_length() 10; end
- class << @connection
- alias_method :old_table_alias_length, :table_alias_length
- alias_method :table_alias_length, :test_table_alias_length
- end
+ def test_table_alias
+ def @connection.test_table_alias_length() 10; end
+ class << @connection
+ alias_method :old_table_alias_length, :table_alias_length
+ alias_method :table_alias_length, :test_table_alias_length
+ end
- assert_equal 'posts', @connection.table_alias_for('posts')
- assert_equal 'posts_comm', @connection.table_alias_for('posts_comments')
- assert_equal 'dbo_posts', @connection.table_alias_for('dbo.posts')
+ assert_equal 'posts', @connection.table_alias_for('posts')
+ assert_equal 'posts_comm', @connection.table_alias_for('posts_comments')
+ assert_equal 'dbo_posts', @connection.table_alias_for('dbo.posts')
- class << @connection
- remove_method :table_alias_length
- alias_method :table_alias_length, :old_table_alias_length
+ class << @connection
+ remove_method :table_alias_length
+ alias_method :table_alias_length, :old_table_alias_length
+ end
end
- end
- # test resetting sequences in odd tables in postgreSQL
- if ActiveRecord::Base.connection.respond_to?(:reset_pk_sequence!)
- require 'models/movie'
- require 'models/subscriber'
+ # test resetting sequences in odd tables in postgreSQL
+ if ActiveRecord::Base.connection.respond_to?(:reset_pk_sequence!)
+ require 'models/movie'
+ require 'models/subscriber'
- def test_reset_empty_table_with_custom_pk
- Movie.delete_all
- Movie.connection.reset_pk_sequence! 'movies'
- assert_equal 1, Movie.create(:name => 'fight club').id
- end
+ def test_reset_empty_table_with_custom_pk
+ Movie.delete_all
+ Movie.connection.reset_pk_sequence! 'movies'
+ assert_equal 1, Movie.create(:name => 'fight club').id
+ end
- if ActiveRecord::Base.connection.adapter_name != "FrontBase"
- def test_reset_table_with_non_integer_pk
- Subscriber.delete_all
- Subscriber.connection.reset_pk_sequence! 'subscribers'
- sub = Subscriber.new(:name => 'robert drake')
- sub.id = 'bob drake'
- assert_nothing_raised { sub.save! }
+ if ActiveRecord::Base.connection.adapter_name != "FrontBase"
+ def test_reset_table_with_non_integer_pk
+ Subscriber.delete_all
+ Subscriber.connection.reset_pk_sequence! 'subscribers'
+ sub = Subscriber.new(:name => 'robert drake')
+ sub.id = 'bob drake'
+ assert_nothing_raised { sub.save! }
+ end
end
end
- end
- def test_uniqueness_violations_are_translated_to_specific_exception
- @connection.execute "INSERT INTO subscribers(nick) VALUES('me')"
- assert_raises(ActiveRecord::RecordNotUnique) do
+ def test_uniqueness_violations_are_translated_to_specific_exception
@connection.execute "INSERT INTO subscribers(nick) VALUES('me')"
+ assert_raises(ActiveRecord::RecordNotUnique) do
+ @connection.execute "INSERT INTO subscribers(nick) VALUES('me')"
+ end
end
- end
- def test_foreign_key_violations_are_translated_to_specific_exception
- unless @connection.adapter_name == 'SQLite'
- assert_raises(ActiveRecord::InvalidForeignKey) do
- # Oracle adapter uses prefetched primary key values from sequence and passes them to connection adapter insert method
- if @connection.prefetch_primary_key?
- id_value = @connection.next_sequence_value(@connection.default_sequence_name("fk_test_has_fk", "id"))
- @connection.execute "INSERT INTO fk_test_has_fk (id, fk_id) VALUES (#{id_value},0)"
- else
- @connection.execute "INSERT INTO fk_test_has_fk (fk_id) VALUES (0)"
+ def test_foreign_key_violations_are_translated_to_specific_exception
+ unless @connection.adapter_name == 'SQLite'
+ assert_raises(ActiveRecord::InvalidForeignKey) do
+ # Oracle adapter uses prefetched primary key values from sequence and passes them to connection adapter insert method
+ if @connection.prefetch_primary_key?
+ id_value = @connection.next_sequence_value(@connection.default_sequence_name("fk_test_has_fk", "id"))
+ @connection.execute "INSERT INTO fk_test_has_fk (id, fk_id) VALUES (#{id_value},0)"
+ else
+ @connection.execute "INSERT INTO fk_test_has_fk (fk_id) VALUES (0)"
+ end
end
end
end
- end
- def test_disable_referential_integrity
- assert_nothing_raised do
- @connection.disable_referential_integrity do
- # Oracle adapter uses prefetched primary key values from sequence and passes them to connection adapter insert method
- if @connection.prefetch_primary_key?
- id_value = @connection.next_sequence_value(@connection.default_sequence_name("fk_test_has_fk", "id"))
- @connection.execute "INSERT INTO fk_test_has_fk (id, fk_id) VALUES (#{id_value},0)"
- else
- @connection.execute "INSERT INTO fk_test_has_fk (fk_id) VALUES (0)"
+ def test_disable_referential_integrity
+ assert_nothing_raised do
+ @connection.disable_referential_integrity do
+ # Oracle adapter uses prefetched primary key values from sequence and passes them to connection adapter insert method
+ if @connection.prefetch_primary_key?
+ id_value = @connection.next_sequence_value(@connection.default_sequence_name("fk_test_has_fk", "id"))
+ @connection.execute "INSERT INTO fk_test_has_fk (id, fk_id) VALUES (#{id_value},0)"
+ else
+ @connection.execute "INSERT INTO fk_test_has_fk (fk_id) VALUES (0)"
+ end
+ # should deleted created record as otherwise disable_referential_integrity will try to enable contraints after executed block
+ # and will fail (at least on Oracle)
+ @connection.execute "DELETE FROM fk_test_has_fk"
end
end
end
diff --git a/activerecord/test/cases/adapters/mysql/active_schema_test.rb b/activerecord/test/cases/adapters/mysql/active_schema_test.rb
index 509baacaef..94fc3564df 100644
--- a/activerecord/test/cases/adapters/mysql/active_schema_test.rb
+++ b/activerecord/test/cases/adapters/mysql/active_schema_test.rb
@@ -2,7 +2,7 @@ require "cases/helper"
class ActiveSchemaTest < ActiveRecord::TestCase
def setup
- ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do
+ ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter.class_eval do
alias_method :execute_without_stub, :execute
remove_method :execute
def execute(sql, name = nil) return sql end
@@ -10,7 +10,7 @@ class ActiveSchemaTest < ActiveRecord::TestCase
end
def teardown
- ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do
+ ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter.class_eval do
remove_method :execute
alias_method :execute, :execute_without_stub
end
@@ -99,7 +99,7 @@ class ActiveSchemaTest < ActiveRecord::TestCase
private
def with_real_execute
#we need to actually modify some data, so we make execute point to the original method
- ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do
+ ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter.class_eval do
alias_method :execute_with_stub, :execute
remove_method :execute
alias_method :execute, :execute_without_stub
@@ -107,7 +107,7 @@ class ActiveSchemaTest < ActiveRecord::TestCase
yield
ensure
#before finishing, we restore the alias to the mock-up method
- ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do
+ ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter.class_eval do
remove_method :execute
alias_method :execute, :execute_with_stub
end
diff --git a/activerecord/test/cases/adapters/mysql/case_sensitivity_test.rb b/activerecord/test/cases/adapters/mysql/case_sensitivity_test.rb
new file mode 100644
index 0000000000..97adb6b297
--- /dev/null
+++ b/activerecord/test/cases/adapters/mysql/case_sensitivity_test.rb
@@ -0,0 +1,35 @@
+require "cases/helper"
+require 'models/person'
+
+class MysqlCaseSensitivityTest < ActiveRecord::TestCase
+ class CollationTest < ActiveRecord::Base
+ validates_uniqueness_of :string_cs_column, :case_sensitive => false
+ validates_uniqueness_of :string_ci_column, :case_sensitive => false
+ end
+
+ def test_columns_include_collation_different_from_table
+ assert_equal 'utf8_bin', CollationTest.columns_hash['string_cs_column'].collation
+ assert_equal 'utf8_general_ci', CollationTest.columns_hash['string_ci_column'].collation
+ end
+
+ def test_case_sensitive
+ assert !CollationTest.columns_hash['string_ci_column'].case_sensitive?
+ assert CollationTest.columns_hash['string_cs_column'].case_sensitive?
+ end
+
+ def test_case_insensitive_comparison_for_ci_column
+ CollationTest.create!(:string_ci_column => 'A')
+ invalid = CollationTest.new(:string_ci_column => 'a')
+ queries = assert_sql { invalid.save }
+ ci_uniqueness_query = queries.detect { |q| q.match(/string_ci_column/) }
+ assert_no_match(/lower/i, ci_uniqueness_query)
+ end
+
+ def test_case_insensitive_comparison_for_cs_column
+ CollationTest.create!(:string_cs_column => 'A')
+ invalid = CollationTest.new(:string_cs_column => 'a')
+ queries = assert_sql { invalid.save }
+ cs_uniqueness_query = queries.detect { |q| q.match(/string_cs_column/) }
+ assert_match(/lower/i, cs_uniqueness_query)
+ end
+end
diff --git a/activerecord/test/cases/adapters/mysql/schema_test.rb b/activerecord/test/cases/adapters/mysql/schema_test.rb
index a2155d1dd1..29f885c6e7 100644
--- a/activerecord/test/cases/adapters/mysql/schema_test.rb
+++ b/activerecord/test/cases/adapters/mysql/schema_test.rb
@@ -13,8 +13,8 @@ module ActiveRecord
table = Post.table_name
@db_name = db
- @omgpost = Class.new(Post) do
- set_table_name "#{db}.#{table}"
+ @omgpost = Class.new(ActiveRecord::Base) do
+ self.table_name = "#{db}.#{table}"
def self.name; 'Post'; end
end
end
@@ -23,6 +23,10 @@ module ActiveRecord
assert @omgpost.find(:first)
end
+ def test_primary_key
+ assert_equal 'id', @omgpost.primary_key
+ end
+
def test_table_exists?
name = @omgpost.table_name
assert @connection.table_exists?(name), "#{name} table should exist"
diff --git a/activerecord/test/cases/adapters/mysql/statement_pool_test.rb b/activerecord/test/cases/adapters/mysql/statement_pool_test.rb
new file mode 100644
index 0000000000..83de90f179
--- /dev/null
+++ b/activerecord/test/cases/adapters/mysql/statement_pool_test.rb
@@ -0,0 +1,23 @@
+require 'cases/helper'
+
+module ActiveRecord::ConnectionAdapters
+ class MysqlAdapter
+ class StatementPoolTest < ActiveRecord::TestCase
+ def test_cache_is_per_pid
+ return skip('must support fork') unless Process.respond_to?(:fork)
+
+ cache = StatementPool.new nil, 10
+ cache['foo'] = 'bar'
+ assert_equal 'bar', cache['foo']
+
+ pid = fork {
+ lookup = cache['foo'];
+ exit!(!lookup)
+ }
+
+ Process.waitpid pid
+ assert $?.success?, 'process should exit successfully'
+ end
+ end
+ end
+end
diff --git a/activerecord/test/cases/adapters/mysql2/case_sensitivity_test.rb b/activerecord/test/cases/adapters/mysql2/case_sensitivity_test.rb
new file mode 100644
index 0000000000..6bcc113482
--- /dev/null
+++ b/activerecord/test/cases/adapters/mysql2/case_sensitivity_test.rb
@@ -0,0 +1,35 @@
+require "cases/helper"
+require 'models/person'
+
+class Mysql2CaseSensitivityTest < ActiveRecord::TestCase
+ class CollationTest < ActiveRecord::Base
+ validates_uniqueness_of :string_cs_column, :case_sensitive => false
+ validates_uniqueness_of :string_ci_column, :case_sensitive => false
+ end
+
+ def test_columns_include_collation_different_from_table
+ assert_equal 'utf8_bin', CollationTest.columns_hash['string_cs_column'].collation
+ assert_equal 'utf8_general_ci', CollationTest.columns_hash['string_ci_column'].collation
+ end
+
+ def test_case_sensitive
+ assert !CollationTest.columns_hash['string_ci_column'].case_sensitive?
+ assert CollationTest.columns_hash['string_cs_column'].case_sensitive?
+ end
+
+ def test_case_insensitive_comparison_for_ci_column
+ CollationTest.create!(:string_ci_column => 'A')
+ invalid = CollationTest.new(:string_ci_column => 'a')
+ queries = assert_sql { invalid.save }
+ ci_uniqueness_query = queries.detect { |q| q.match(/string_ci_column/) }
+ assert_no_match(/lower/i, ci_uniqueness_query)
+ end
+
+ def test_case_insensitive_comparison_for_cs_column
+ CollationTest.create!(:string_cs_column => 'A')
+ invalid = CollationTest.new(:string_cs_column => 'a')
+ queries = assert_sql { invalid.save }
+ cs_uniqueness_query = queries.detect { |q| q.match(/string_cs_column/)}
+ assert_match(/lower/i, cs_uniqueness_query)
+ end
+end
diff --git a/activerecord/test/cases/adapters/mysql2/explain_test.rb b/activerecord/test/cases/adapters/mysql2/explain_test.rb
new file mode 100644
index 0000000000..68ed361aeb
--- /dev/null
+++ b/activerecord/test/cases/adapters/mysql2/explain_test.rb
@@ -0,0 +1,26 @@
+require "cases/helper"
+require 'models/developer'
+
+module ActiveRecord
+ module ConnectionAdapters
+ class Mysql2Adapter
+ class ExplainTest < ActiveRecord::TestCase
+ fixtures :developers
+
+ def test_explain_for_one_query
+ explain = Developer.where(:id => 1).explain
+ assert_match %(EXPLAIN for: SELECT `developers`.* FROM `developers` WHERE `developers`.`id` = 1), explain
+ assert_match %(developers | const), explain
+ end
+
+ def test_explain_with_eager_loading
+ explain = Developer.where(:id => 1).includes(:audit_logs).explain
+ assert_match %(EXPLAIN for: SELECT `developers`.* FROM `developers` WHERE `developers`.`id` = 1), explain
+ assert_match %(developers | const), explain
+ assert_match %(EXPLAIN for: SELECT `audit_logs`.* FROM `audit_logs` WHERE `audit_logs`.`developer_id` IN (1)), explain
+ assert_match %(audit_logs | ALL), explain
+ end
+ end
+ end
+ end
+end
diff --git a/activerecord/test/cases/adapters/mysql2/schema_test.rb b/activerecord/test/cases/adapters/mysql2/schema_test.rb
index 858d1da2dd..d5676bc522 100644
--- a/activerecord/test/cases/adapters/mysql2/schema_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/schema_test.rb
@@ -13,8 +13,8 @@ module ActiveRecord
table = Post.table_name
@db_name = db
- @omgpost = Class.new(Post) do
- set_table_name "#{db}.#{table}"
+ @omgpost = Class.new(ActiveRecord::Base) do
+ self.table_name = "#{db}.#{table}"
def self.name; 'Post'; end
end
end
@@ -23,6 +23,10 @@ module ActiveRecord
assert @omgpost.find(:first)
end
+ def test_primary_key
+ assert_equal 'id', @omgpost.primary_key
+ end
+
def test_table_exists?
name = @omgpost.table_name
assert @connection.table_exists?(name), "#{name} table should exist"
diff --git a/activerecord/test/cases/adapters/postgresql/explain_test.rb b/activerecord/test/cases/adapters/postgresql/explain_test.rb
new file mode 100644
index 0000000000..0b61f61572
--- /dev/null
+++ b/activerecord/test/cases/adapters/postgresql/explain_test.rb
@@ -0,0 +1,28 @@
+require "cases/helper"
+require 'models/developer'
+
+module ActiveRecord
+ module ConnectionAdapters
+ class PostgreSQLAdapter
+ class ExplainTest < ActiveRecord::TestCase
+ fixtures :developers
+
+ def test_explain_for_one_query
+ explain = Developer.where(:id => 1).explain
+ assert_match %(EXPLAIN for: SELECT "developers".* FROM "developers" WHERE "developers"."id" = 1), explain
+ assert_match %(QUERY PLAN), explain
+ assert_match %(Index Scan using developers_pkey on developers), explain
+ end
+
+ def test_explain_with_eager_loading
+ explain = Developer.where(:id => 1).includes(:audit_logs).explain
+ assert_match %(QUERY PLAN), explain
+ assert_match %(EXPLAIN for: SELECT "developers".* FROM "developers" WHERE "developers"."id" = 1), explain
+ assert_match %(Index Scan using developers_pkey on developers), explain
+ assert_match %(EXPLAIN for: SELECT "audit_logs".* FROM "audit_logs" WHERE "audit_logs"."developer_id" IN (1)), explain
+ assert_match %(Seq Scan on audit_logs), explain
+ end
+ end
+ end
+ end
+end
diff --git a/activerecord/test/cases/adapters/postgresql/schema_test.rb b/activerecord/test/cases/adapters/postgresql/schema_test.rb
index 3a7f1badf0..d08f0b324d 100644
--- a/activerecord/test/cases/adapters/postgresql/schema_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/schema_test.rb
@@ -10,32 +10,39 @@ class SchemaTest < ActiveRecord::TestCase
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_D_NAME = 'd_index_things_on_description_desc'
INDEX_A_COLUMN = 'name'
INDEX_B_COLUMN_S1 = 'email'
INDEX_B_COLUMN_S2 = 'moment'
INDEX_C_COLUMN = %q{(to_tsvector('english', coalesce(things.name, '')))}
+ INDEX_D_COLUMN = 'description'
COLUMNS = [
'id integer',
'name character varying(50)',
'email character varying(50)',
+ 'description character varying(100)',
'moment timestamp without time zone default now()'
]
PK_TABLE_NAME = 'table_with_pk'
class Thing1 < ActiveRecord::Base
- set_table_name "test_schema.things"
+ self.table_name = "test_schema.things"
end
class Thing2 < ActiveRecord::Base
- set_table_name "test_schema2.things"
+ self.table_name = "test_schema2.things"
end
class Thing3 < ActiveRecord::Base
- set_table_name 'test_schema."things.table"'
+ self.table_name = 'test_schema."things.table"'
end
class Thing4 < ActiveRecord::Base
- set_table_name 'test_schema."Things"'
+ self.table_name = 'test_schema."Things"'
+ end
+
+ class Thing5 < ActiveRecord::Base
+ self.table_name = 'things'
end
def setup
@@ -50,6 +57,8 @@ class SchemaTest < ActiveRecord::TestCase
@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});"
+ @connection.execute "CREATE INDEX #{INDEX_D_NAME} ON #{SCHEMA_NAME}.#{TABLE_NAME} USING btree (#{INDEX_D_COLUMN} DESC);"
+ @connection.execute "CREATE INDEX #{INDEX_D_NAME} ON #{SCHEMA2_NAME}.#{TABLE_NAME} USING btree (#{INDEX_D_COLUMN} DESC);"
@connection.execute "CREATE TABLE #{SCHEMA_NAME}.#{PK_TABLE_NAME} (id serial primary key)"
end
@@ -58,6 +67,14 @@ class SchemaTest < ActiveRecord::TestCase
@connection.execute "DROP SCHEMA #{SCHEMA_NAME} CASCADE"
end
+ def test_schema_change_with_prepared_stmt
+ @connection.exec_query "select * from developers where id = $1", 'sql', [[nil, 1]]
+ @connection.exec_query "alter table developers add column zomg int", 'sql', []
+ @connection.exec_query "select * from developers where id = $1", 'sql', [[nil, 1]]
+ ensure
+ @connection.exec_query "alter table developers drop column if exists zomg", 'sql', []
+ end
+
def test_table_exists?
[Thing1, Thing2, Thing3, Thing4].each do |klass|
name = klass.table_name
@@ -91,6 +108,12 @@ class SchemaTest < ActiveRecord::TestCase
end
end
+ def test_table_exists_quoted_table
+ with_schema_search_path(SCHEMA_NAME) do
+ assert(@connection.table_exists?('"things.table"'), "table should exist")
+ end
+ end
+
def test_with_schema_prefixed_table_name
assert_nothing_raised do
assert_equal COLUMNS, columns("#{SCHEMA_NAME}.#{TABLE_NAME}")
@@ -166,11 +189,15 @@ class SchemaTest < ActiveRecord::TestCase
end
def test_dump_indexes_for_schema_one
- do_dump_index_tests_for_schema(SCHEMA_NAME, INDEX_A_COLUMN, INDEX_B_COLUMN_S1)
+ do_dump_index_tests_for_schema(SCHEMA_NAME, INDEX_A_COLUMN, INDEX_B_COLUMN_S1, INDEX_D_COLUMN)
end
def test_dump_indexes_for_schema_two
- do_dump_index_tests_for_schema(SCHEMA2_NAME, INDEX_A_COLUMN, INDEX_B_COLUMN_S2)
+ do_dump_index_tests_for_schema(SCHEMA2_NAME, INDEX_A_COLUMN, INDEX_B_COLUMN_S2, INDEX_D_COLUMN)
+ end
+
+ def test_dump_indexes_for_schema_multiple_schemas_in_search_path
+ do_dump_index_tests_for_schema("public, #{SCHEMA_NAME}", INDEX_A_COLUMN, INDEX_B_COLUMN_S1, INDEX_D_COLUMN)
end
def test_with_uppercase_index_name
@@ -219,21 +246,6 @@ class SchemaTest < ActiveRecord::TestCase
end
end
- def test_extract_schema_and_table
- {
- %(table_name) => [nil,'table_name'],
- %("table.name") => [nil,'table.name'],
- %(schema.table_name) => %w{schema table_name},
- %("schema".table_name) => %w{schema table_name},
- %(schema."table_name") => %w{schema table_name},
- %("schema"."table_name") => %w{schema table_name},
- %("even spaces".table) => ['even spaces','table'],
- %(schema."table.name") => ['schema', 'table.name']
- }.each do |given, expect|
- assert_equal expect, ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::Utils.extract_schema_and_table(given)
- end
- end
-
def test_current_schema
{
%('$user',public) => 'public',
@@ -245,6 +257,21 @@ class SchemaTest < ActiveRecord::TestCase
end
end
+ def test_prepared_statements_with_multiple_schemas
+
+ @connection.schema_search_path = SCHEMA_NAME
+ Thing5.create(:id => 1, :name => "thing inside #{SCHEMA_NAME}", :email => "thing1@localhost", :moment => Time.now)
+
+ @connection.schema_search_path = SCHEMA2_NAME
+ Thing5.create(:id => 1, :name => "thing inside #{SCHEMA2_NAME}", :email => "thing1@localhost", :moment => Time.now)
+
+ @connection.schema_search_path = SCHEMA_NAME
+ assert_equal 1, Thing5.count
+
+ @connection.schema_search_path = SCHEMA2_NAME
+ assert_equal 1, Thing5.count
+ end
+
def test_schema_exists?
{
'public' => true,
@@ -270,13 +297,16 @@ class SchemaTest < ActiveRecord::TestCase
@connection.schema_search_path = "'$user', public"
end
- def do_dump_index_tests_for_schema(this_schema_name, first_index_column_name, second_index_column_name)
+ def do_dump_index_tests_for_schema(this_schema_name, first_index_column_name, second_index_column_name, third_index_column_name)
with_schema_search_path(this_schema_name) do
indexes = @connection.indexes(TABLE_NAME).sort_by {|i| i.name}
- assert_equal 2,indexes.size
+ assert_equal 3,indexes.size
do_dump_index_assertions_for_one_index(indexes[0], INDEX_A_NAME, first_index_column_name)
do_dump_index_assertions_for_one_index(indexes[1], INDEX_B_NAME, second_index_column_name)
+ do_dump_index_assertions_for_one_index(indexes[2], INDEX_D_NAME, third_index_column_name)
+
+ assert_equal :desc, indexes.select{|i| i.name == INDEX_D_NAME}[0].orders[INDEX_D_COLUMN]
end
end
diff --git a/activerecord/test/cases/adapters/postgresql/statement_pool_test.rb b/activerecord/test/cases/adapters/postgresql/statement_pool_test.rb
new file mode 100644
index 0000000000..f1c4b85126
--- /dev/null
+++ b/activerecord/test/cases/adapters/postgresql/statement_pool_test.rb
@@ -0,0 +1,39 @@
+require 'cases/helper'
+
+module ActiveRecord::ConnectionAdapters
+ class PostgreSQLAdapter < AbstractAdapter
+ class InactivePGconn
+ def query(*args)
+ raise PGError
+ end
+
+ def status
+ PGconn::CONNECTION_BAD
+ end
+ end
+
+ class StatementPoolTest < ActiveRecord::TestCase
+ def test_cache_is_per_pid
+ return skip('must support fork') unless Process.respond_to?(:fork)
+
+ cache = StatementPool.new nil, 10
+ cache['foo'] = 'bar'
+ assert_equal 'bar', cache['foo']
+
+ pid = fork {
+ lookup = cache['foo'];
+ exit!(!lookup)
+ }
+
+ Process.waitpid pid
+ assert $?.success?, 'process should exit successfully'
+ end
+
+ def test_dealloc_does_not_raise_on_inactive_connection
+ cache = StatementPool.new InactivePGconn.new, 10
+ cache['foo'] = 'bar'
+ assert_nothing_raised { cache.clear }
+ end
+ end
+ end
+end
diff --git a/activerecord/test/cases/adapters/postgresql/utils_test.rb b/activerecord/test/cases/adapters/postgresql/utils_test.rb
new file mode 100644
index 0000000000..5f08f79171
--- /dev/null
+++ b/activerecord/test/cases/adapters/postgresql/utils_test.rb
@@ -0,0 +1,18 @@
+class PostgreSQLUtilsTest < ActiveSupport::TestCase
+ include ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::Utils
+
+ def test_extract_schema_and_table
+ {
+ %(table_name) => [nil,'table_name'],
+ %("table.name") => [nil,'table.name'],
+ %(schema.table_name) => %w{schema table_name},
+ %("schema".table_name) => %w{schema table_name},
+ %(schema."table_name") => %w{schema table_name},
+ %("schema"."table_name") => %w{schema table_name},
+ %("even spaces".table) => ['even spaces','table'],
+ %(schema."table.name") => ['schema', 'table.name']
+ }.each do |given, expect|
+ assert_equal expect, extract_schema_and_table(given)
+ end
+ end
+end
diff --git a/activerecord/test/cases/adapters/postgresql/view_test.rb b/activerecord/test/cases/adapters/postgresql/view_test.rb
index 303ba9245a..66e07b71a0 100644
--- a/activerecord/test/cases/adapters/postgresql/view_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/view_test.rb
@@ -14,7 +14,7 @@ class ViewTest < ActiveRecord::TestCase
]
class ThingView < ActiveRecord::Base
- set_table_name 'test_schema.view_things'
+ self.table_name = 'test_schema.view_things'
end
def setup
diff --git a/activerecord/test/cases/adapters/sqlite3/explain_test.rb b/activerecord/test/cases/adapters/sqlite3/explain_test.rb
new file mode 100644
index 0000000000..b227bce680
--- /dev/null
+++ b/activerecord/test/cases/adapters/sqlite3/explain_test.rb
@@ -0,0 +1,26 @@
+require "cases/helper"
+require 'models/developer'
+
+module ActiveRecord
+ module ConnectionAdapters
+ class SQLite3Adapter
+ class ExplainTest < ActiveRecord::TestCase
+ fixtures :developers
+
+ def test_explain_for_one_query
+ explain = Developer.where(:id => 1).explain
+ assert_match %(EXPLAIN for: SELECT "developers".* FROM "developers" WHERE "developers"."id" = 1), explain
+ assert_match(/(SEARCH )?TABLE developers USING (INTEGER )?PRIMARY KEY/, explain)
+ end
+
+ def test_explain_with_eager_loading
+ explain = Developer.where(:id => 1).includes(:audit_logs).explain
+ assert_match %(EXPLAIN for: SELECT "developers".* FROM "developers" WHERE "developers"."id" = 1), explain
+ assert_match(/(SEARCH )?TABLE developers USING (INTEGER )?PRIMARY KEY/, explain)
+ assert_match %(EXPLAIN for: SELECT "audit_logs".* FROM "audit_logs" WHERE "audit_logs"."developer_id" IN (1)), explain
+ assert_match(/(SCAN )?TABLE audit_logs/, explain)
+ end
+ end
+ end
+ end
+end
diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
index 6ff04e3eb3..97b56d38d7 100644
--- a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
+++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb
@@ -1,9 +1,12 @@
# encoding: utf-8
require "cases/helper"
+require 'models/owner'
module ActiveRecord
module ConnectionAdapters
class SQLite3AdapterTest < ActiveRecord::TestCase
+ self.use_transactional_fixtures = false
+
class DualEncoding < ActiveRecord::Base
end
@@ -19,6 +22,21 @@ module ActiveRecord
eosql
end
+ def test_column_types
+ return skip('only test encoding on 1.9') unless "<3".encoding_aware?
+
+ owner = Owner.create!(:name => "hello".encode('ascii-8bit'))
+ owner.reload
+ select = Owner.columns.map { |c| "typeof(#{c.name})" }.join ', '
+ result = Owner.connection.exec_query <<-esql
+ SELECT #{select}
+ FROM #{Owner.table_name}
+ WHERE #{Owner.primary_key} = #{owner.id}
+ esql
+
+ assert(!result.rows.first.include?("blob"), "should not store blobs")
+ end
+
def test_exec_insert
column = @conn.columns('items').find { |col| col.name == 'number' }
vals = [[column, 10]]
@@ -139,6 +157,11 @@ module ActiveRecord
binary = DualEncoding.new :name => 'いただきます!', :data => str
binary.save!
assert_equal str, binary.data
+
+ ensure
+ if "<3".respond_to?(:encode)
+ DualEncoding.connection.drop_table('dual_encodings')
+ end
end
def test_execute
diff --git a/activerecord/test/cases/adapters/sqlite3/statement_pool_test.rb b/activerecord/test/cases/adapters/sqlite3/statement_pool_test.rb
new file mode 100644
index 0000000000..ae272e2c4b
--- /dev/null
+++ b/activerecord/test/cases/adapters/sqlite3/statement_pool_test.rb
@@ -0,0 +1,24 @@
+require 'cases/helper'
+
+module ActiveRecord::ConnectionAdapters
+ class SQLiteAdapter
+ class StatementPoolTest < ActiveRecord::TestCase
+ def test_cache_is_per_pid
+ return skip('must support fork') unless Process.respond_to?(:fork)
+
+ cache = StatementPool.new nil, 10
+ cache['foo'] = 'bar'
+ assert_equal 'bar', cache['foo']
+
+ pid = fork {
+ lookup = cache['foo'];
+ exit!(!lookup)
+ }
+
+ Process.waitpid pid
+ assert $?.success?, 'process should exit successfully'
+ end
+ end
+ end
+end
+
diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb
index 818902beb5..1160d236c9 100644
--- a/activerecord/test/cases/associations/belongs_to_associations_test.rb
+++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb
@@ -13,6 +13,7 @@ require 'models/comment'
require 'models/sponsor'
require 'models/member'
require 'models/essay'
+require 'models/toy'
class BelongsToAssociationsTest < ActiveRecord::TestCase
fixtures :accounts, :companies, :developers, :projects, :topics,
@@ -352,6 +353,12 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
assert_equal members(:groucho), sponsor.sponsorable
end
+ def test_dont_find_target_when_foreign_key_is_null
+ tagging = taggings(:thinking_general)
+ queries = assert_sql { tagging.super_tag }
+ assert_equal 0, queries.length
+ end
+
def test_field_name_same_as_foreign_key
computer = Computer.find(1)
assert_not_nil computer.developer, ":foreign key == attribute didn't lock up" # '
@@ -690,4 +697,11 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
assert_equal nil, comment.reload.parent
assert_equal 0, comments(:greetings).reload.children_count
end
+
+ def test_polymorphic_with_custom_primary_key
+ toy = Toy.create!
+ sponsor = Sponsor.create!(:sponsorable => toy)
+
+ assert_equal toy, sponsor.reload.sponsorable
+ end
end
diff --git a/activerecord/test/cases/associations/eager_load_includes_full_sti_class_test.rb b/activerecord/test/cases/associations/eager_load_includes_full_sti_class_test.rb
index d75791cab9..7965bb404c 100644
--- a/activerecord/test/cases/associations/eager_load_includes_full_sti_class_test.rb
+++ b/activerecord/test/cases/associations/eager_load_includes_full_sti_class_test.rb
@@ -4,7 +4,7 @@ require 'models/tagging'
module Namespaced
class Post < ActiveRecord::Base
- set_table_name 'posts'
+ self.table_name = 'posts'
has_one :tagging, :as => :taggable, :class_name => 'Tagging'
end
end
diff --git a/activerecord/test/cases/associations/extension_test.rb b/activerecord/test/cases/associations/extension_test.rb
index 24830a661a..8dc1423375 100644
--- a/activerecord/test/cases/associations/extension_test.rb
+++ b/activerecord/test/cases/associations/extension_test.rb
@@ -36,18 +36,32 @@ class AssociationsExtensionsTest < ActiveRecord::TestCase
end
def test_marshalling_extensions
+ if ENV['TRAVIS'] && RUBY_VERSION == "1.8.7"
+ return skip("Marshalling tests disabled for Ruby 1.8.7 on Travis CI due to what appears " \
+ "to be a Ruby bug.")
+ end
+
david = developers(:david)
assert_equal projects(:action_controller), david.projects.find_most_recent
- david = Marshal.load(Marshal.dump(david))
+ marshalled = Marshal.dump(david)
+ david = Marshal.load(marshalled)
+
assert_equal projects(:action_controller), david.projects.find_most_recent
end
def test_marshalling_named_extensions
+ if ENV['TRAVIS'] && RUBY_VERSION == "1.8.7"
+ return skip("Marshalling tests disabled for Ruby 1.8.7 on Travis CI due to what appears " \
+ "to be a Ruby bug.")
+ end
+
david = developers(:david)
assert_equal projects(:action_controller), david.projects_extended_by_name.find_most_recent
- david = Marshal.load(Marshal.dump(david))
+ marshalled = Marshal.dump(david)
+ david = Marshal.load(marshalled)
+
assert_equal projects(:action_controller), david.projects_extended_by_name.find_most_recent
end
diff --git a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb
index d8d2a113ff..b49510b202 100644
--- a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb
@@ -23,7 +23,7 @@ require 'models/treaty'
require 'active_support/core_ext/string/conversions'
class ProjectWithAfterCreateHook < ActiveRecord::Base
- set_table_name 'projects'
+ self.table_name = 'projects'
has_and_belongs_to_many :developers,
:class_name => "DeveloperForProjectWithAfterCreateHook",
:join_table => "developers_projects",
@@ -39,7 +39,7 @@ class ProjectWithAfterCreateHook < ActiveRecord::Base
end
class DeveloperForProjectWithAfterCreateHook < ActiveRecord::Base
- set_table_name 'developers'
+ self.table_name = 'developers'
has_and_belongs_to_many :projects,
:class_name => "ProjectWithAfterCreateHook",
:join_table => "developers_projects",
@@ -48,7 +48,7 @@ class DeveloperForProjectWithAfterCreateHook < ActiveRecord::Base
end
class ProjectWithSymbolsForKeys < ActiveRecord::Base
- set_table_name 'projects'
+ self.table_name = 'projects'
has_and_belongs_to_many :developers,
:class_name => "DeveloperWithSymbolsForKeys",
:join_table => :developers_projects,
@@ -57,7 +57,7 @@ class ProjectWithSymbolsForKeys < ActiveRecord::Base
end
class DeveloperWithSymbolsForKeys < ActiveRecord::Base
- set_table_name 'developers'
+ self.table_name = 'developers'
has_and_belongs_to_many :projects,
:class_name => "ProjectWithSymbolsForKeys",
:join_table => :developers_projects,
@@ -66,7 +66,7 @@ class DeveloperWithSymbolsForKeys < ActiveRecord::Base
end
class DeveloperWithCounterSQL < ActiveRecord::Base
- set_table_name 'developers'
+ self.table_name = 'developers'
has_and_belongs_to_many :projects,
:class_name => "DeveloperWithCounterSQL",
:join_table => "developers_projects",
@@ -77,7 +77,7 @@ end
class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
fixtures :accounts, :companies, :categories, :posts, :categories_posts, :developers, :projects, :developers_projects,
- :parrots, :pirates, :treasures, :price_estimates, :tags, :taggings
+ :parrots, :pirates, :parrots_pirates, :treasures, :price_estimates, :tags, :taggings
def setup_data_for_habtm_case
ActiveRecord::Base.connection.execute('delete from countries_treaties')
@@ -445,6 +445,26 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
assert david.projects(true).empty?
end
+ def test_destroy_associations_destroys_multiple_associations
+ george = parrots(:george)
+ assert !george.pirates.empty?
+ assert !george.treasures.empty?
+
+ assert_no_difference "Pirate.count" do
+ assert_no_difference "Treasure.count" do
+ george.destroy_associations
+ end
+ end
+
+ join_records = Parrot.connection.select_all("SELECT * FROM parrots_pirates WHERE parrot_id = #{george.id}")
+ assert join_records.empty?
+ assert george.pirates(true).empty?
+
+ join_records = Parrot.connection.select_all("SELECT * FROM parrots_treasures WHERE parrot_id = #{george.id}")
+ assert join_records.empty?
+ assert george.treasures(true).empty?
+ end
+
def test_deprecated_push_with_attributes_was_removed
jamis = developers(:jamis)
assert_raise(NoMethodError) do
@@ -650,6 +670,14 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
assert_respond_to categories(:technology).select_testing_posts.find(:first), :correctness_marker
end
+ def test_habtm_selects_all_columns_by_default
+ assert_equal Project.column_names.sort, developers(:david).projects.first.attributes.keys.sort
+ end
+
+ def test_habtm_respects_select_query_method
+ assert_equal ['id'], developers(:david).projects.select(:id).first.attributes.keys
+ end
+
def test_join_table_alias
assert_equal 3, Developer.find(:all, :include => {:projects => :developers}, :conditions => 'developers_projects_join.joined_on IS NOT NULL').size
end
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index a2764f3e3b..88d7d47aea 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -8,6 +8,7 @@ require 'models/reply'
require 'models/category'
require 'models/post'
require 'models/author'
+require 'models/essay'
require 'models/comment'
require 'models/person'
require 'models/reader'
@@ -17,6 +18,7 @@ require 'models/invoice'
require 'models/line_item'
require 'models/car'
require 'models/bulb'
+require 'models/engine'
class HasManyAssociationsTestForCountWithFinderSql < ActiveRecord::TestCase
class Invoice < ActiveRecord::Base
@@ -40,12 +42,27 @@ class HasManyAssociationsTestForCountWithCountSql < ActiveRecord::TestCase
end
end
+class HasManyAssociationsTestForCountDistinctWithFinderSql < ActiveRecord::TestCase
+ class Invoice < ActiveRecord::Base
+ has_many :custom_line_items, :class_name => 'LineItem', :finder_sql => "SELECT DISTINCT line_items.amount from line_items"
+ end
+
+ def test_should_count_distinct_results
+ invoice = Invoice.new
+ invoice.custom_line_items << LineItem.new(:amount => 0)
+ invoice.custom_line_items << LineItem.new(:amount => 0)
+ invoice.save!
+
+ assert_equal 1, invoice.custom_line_items.count
+ end
+end
+
class HasManyAssociationsTest < ActiveRecord::TestCase
fixtures :accounts, :categories, :companies, :developers, :projects,
:developers_projects, :topics, :authors, :comments,
- :people, :posts, :readers, :taggings, :cars
+ :people, :posts, :readers, :taggings, :cars, :essays
def setup
Client.destroyed_client_ids.clear
@@ -484,6 +501,14 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_equal 0, authors(:mary).popular_grouped_posts.length
end
+ def test_default_select
+ assert_equal Comment.column_names.sort, posts(:welcome).comments.first.attributes.keys.sort
+ end
+
+ def test_select_query_method
+ assert_equal ['id'], posts(:welcome).comments.select(:id).first.attributes.keys
+ end
+
def test_adding
force_signal37_to_load_all_clients_of_firm
natural = Client.new("name" => "Natural Company")
@@ -850,6 +875,15 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
end
end
+ def test_clearing_updates_counter_cache_when_inverse_counter_cache_is_a_symbol_with_dependent_destroy
+ car = Car.first
+ car.engines.create!
+
+ assert_difference 'car.reload.engines_count', -1 do
+ car.engines.clear
+ end
+ end
+
def test_clearing_a_dependent_association_collection
firm = companies(:first_firm)
client_id = firm.dependent_clients_of_firm.first.id
@@ -1357,6 +1391,32 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
firm.clients.last
end
end
+
+ def test_custom_primary_key_on_new_record_should_fetch_with_query
+ author = Author.new(:name => "David")
+ assert !author.essays.loaded?
+
+ assert_queries 1 do
+ assert_equal 1, author.essays.size
+ end
+
+ assert_equal author.essays, Essay.find_all_by_writer_id("David")
+
+ end
+
+ def test_has_many_custom_primary_key
+ david = authors(:david)
+ assert_equal david.essays, Essay.find_all_by_writer_id("David")
+ end
+
+ def test_blank_custom_primary_key_on_new_record_should_not_run_queries
+ author = Author.new
+ assert !author.essays.loaded?
+
+ assert_queries 0 do
+ assert_equal 0, author.essays.size
+ end
+ end
def test_calling_first_or_last_with_find_options_on_loaded_association_should_fetch_with_query
firm = companies(:first_firm)
@@ -1568,4 +1628,15 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_equal car.id, bulb.attributes_after_initialize['car_id']
end
+
+ def test_replace
+ car = Car.create(:name => 'honda')
+ bulb1 = car.bulbs.create
+ bulb2 = Bulb.create
+
+ assert_equal [bulb1], car.bulbs
+ car.bulbs.replace([bulb2])
+ assert_equal [bulb2], car.bulbs
+ assert_equal [bulb2], car.reload.bulbs
+ end
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 0b1ba31ac2..7a6aba6a6b 100644
--- a/activerecord/test/cases/associations/has_many_through_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb
@@ -67,6 +67,31 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
end
end
+ def test_associate_existing_record_twice_should_add_records_twice
+ post = posts(:thinking)
+ person = people(:david)
+
+ assert_difference 'post.people.count', 2 do
+ post.people << person
+ post.people << person
+ end
+ end
+
+ def test_add_two_instance_and_then_deleting
+ post = posts(:thinking)
+ person = people(:david)
+
+ post.people << person
+ post.people << person
+
+ counts = ['post.people.count', 'post.people.to_a.count', 'post.readers.count', 'post.readers.to_a.count']
+ assert_difference counts, -2 do
+ post.people.delete(person)
+ end
+
+ assert !post.people.reload.include?(person)
+ end
+
def test_associating_new
assert_queries(1) { posts(:thinking) }
new_person = nil # so block binding catches it
@@ -813,4 +838,21 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
assert !c.save
end
end
+
+ def test_preloading_empty_through_association_via_joins
+ person = Person.create!(:first_name => "Gaga")
+ person = Person.where(:id => person.id).where('readers.id = 1 or 1=1').includes(:posts).to_a.first
+
+ assert person.posts.loaded?, 'person.posts should be loaded'
+ assert_equal [], person.posts
+ end
+
+ def test_explicitly_joining_join_table
+ assert_equal owners(:blackbeard).toys, owners(:blackbeard).toys.with_pet
+ end
+
+ def test_has_many_through_with_polymorphic_source
+ post = tags(:general).tagged_posts.create! :title => "foo", :body => "bar"
+ assert_equal [tags(:general)], post.reload.tags
+ end
end
diff --git a/activerecord/test/cases/associations/join_model_test.rb b/activerecord/test/cases/associations/join_model_test.rb
index 4ce8b85098..995afef796 100644
--- a/activerecord/test/cases/associations/join_model_test.rb
+++ b/activerecord/test/cases/associations/join_model_test.rb
@@ -733,7 +733,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase
class_name = "PostWith#{association.to_s.classify}#{dependency.to_s.classify}"
Post.find(post_id).update_column :type, class_name
klass = Object.const_set(class_name, Class.new(ActiveRecord::Base))
- klass.set_table_name 'posts'
+ klass.table_name = 'posts'
klass.send(association, association_name, :as => :taggable, :dependent => dependency)
klass.find(post_id)
end
diff --git a/activerecord/test/cases/associations/nested_through_associations_test.rb b/activerecord/test/cases/associations/nested_through_associations_test.rb
index dd450a2a8e..530f5212a2 100644
--- a/activerecord/test/cases/associations/nested_through_associations_test.rb
+++ b/activerecord/test/cases/associations/nested_through_associations_test.rb
@@ -247,7 +247,7 @@ class NestedThroughAssociationsTest < ActiveRecord::TestCase
def test_has_many_through_has_and_belongs_to_many_with_has_many_source_reflection_preload_via_joins
assert_includes_and_joins_equal(
- Category.where('comments.id' => comments(:more_greetings).id).order('comments.id'),
+ Category.where('comments.id' => comments(:more_greetings).id).order('categories.id'),
[categories(:general), categories(:technology)], :post_comments
)
end
@@ -356,6 +356,17 @@ class NestedThroughAssociationsTest < ActiveRecord::TestCase
assert_equal categories(:general), members(:groucho).club_category
end
+ def test_joins_and_includes_from_through_models_not_included_in_association
+ prev_default_scope = Club.default_scopes
+
+ [:includes, :preload, :joins, :eager_load].each do |q|
+ Club.default_scopes = [Club.send(q, :category)]
+ assert_equal categories(:general), members(:groucho).reload.club_category
+ end
+ ensure
+ Club.default_scopes = prev_default_scope
+ end
+
def test_has_one_through_has_one_through_with_belongs_to_source_reflection_preload
members = assert_queries(4) { Member.includes(:club_category).to_a.sort_by(&:id) }
general = categories(:general)
diff --git a/activerecord/test/cases/associations_test.rb b/activerecord/test/cases/associations_test.rb
index ffe2993e0f..efe71d1771 100644
--- a/activerecord/test/cases/associations_test.rb
+++ b/activerecord/test/cases/associations_test.rb
@@ -1,4 +1,5 @@
require "cases/helper"
+require 'models/computer'
require 'models/developer'
require 'models/project'
require 'models/company'
@@ -273,3 +274,18 @@ class OverridingAssociationsTest < ActiveRecord::TestCase
)
end
end
+
+class GeneratedMethodsTest < ActiveRecord::TestCase
+ fixtures :developers, :computers, :posts, :comments
+ def test_association_methods_override_attribute_methods_of_same_name
+ assert_equal(developers(:david), computers(:workstation).developer)
+ # this next line will fail if the attribute methods module is generated lazily
+ # after the association methods module is generated
+ assert_equal(developers(:david), computers(:workstation).developer)
+ assert_equal(developers(:david).id, computers(:workstation)[:developer])
+ end
+
+ def test_model_method_overrides_association_method
+ assert_equal(comments(:greetings).body, posts(:welcome).first_comment)
+ end
+end
diff --git a/activerecord/test/cases/attribute_methods/read_test.rb b/activerecord/test/cases/attribute_methods/read_test.rb
index 3641031d12..e03ed33591 100644
--- a/activerecord/test/cases/attribute_methods/read_test.rb
+++ b/activerecord/test/cases/attribute_methods/read_test.rb
@@ -35,6 +35,7 @@ module ActiveRecord
end
def self.serialized_attributes; {}; end
+ def self.base_class; self; end
end
end
diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb
index b0896fb236..17cf1ec907 100644
--- a/activerecord/test/cases/attribute_methods_test.rb
+++ b/activerecord/test/cases/attribute_methods_test.rb
@@ -35,6 +35,30 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert !t.attribute_present?("content")
end
+ def test_attribute_present_with_booleans
+ b1 = Boolean.new
+ b1.value = false
+ assert b1.attribute_present?(:value)
+
+ b2 = Boolean.new
+ b2.value = true
+ assert b2.attribute_present?(:value)
+
+ b3 = Boolean.new
+ assert !b3.attribute_present?(:value)
+
+ b4 = Boolean.new
+ b4.value = false
+ b4.save!
+ assert Boolean.find(b4.id).attribute_present?(:value)
+ end
+
+ def test_caching_nil_primary_key
+ klass = Class.new(Minimalistic)
+ klass.expects(:reset_primary_key).returns(nil).once
+ 2.times { klass.primary_key }
+ end
+
def test_attribute_keys_on_new_instance
t = Topic.new
assert_equal nil, t.title, "The topics table has a title column, so it should be nil"
@@ -113,6 +137,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
# by inspecting it.
def test_allocated_object_can_be_inspected
topic = Topic.allocate
+ topic.instance_eval { @attributes = nil }
assert_nothing_raised { topic.inspect }
assert topic.inspect, "#<Topic not initialized>"
end
@@ -430,30 +455,6 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert topic.is_test?
end
- def test_kernel_methods_not_implemented_in_activerecord
- %w(test name display y).each do |method|
- assert !ActiveRecord::Base.instance_method_already_implemented?(method), "##{method} is defined"
- end
- end
-
- def test_defined_kernel_methods_implemented_in_model
- %w(test name display y).each do |method|
- klass = Class.new ActiveRecord::Base
- klass.class_eval "def #{method}() 'defined #{method}' end"
- assert klass.instance_method_already_implemented?(method), "##{method} is not defined"
- end
- end
-
- def test_defined_kernel_methods_implemented_in_model_abstract_subclass
- %w(test name display y).each do |method|
- abstract = Class.new ActiveRecord::Base
- abstract.class_eval "def #{method}() 'defined #{method}' end"
- abstract.abstract_class = true
- klass = Class.new abstract
- assert klass.instance_method_already_implemented?(method), "##{method} is not defined"
- end
- end
-
def test_raises_dangerous_attribute_error_when_defining_activerecord_method_in_model
%w(save create_or_update).each do |method|
klass = Class.new ActiveRecord::Base
@@ -607,7 +608,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
topic = @target.new(:title => "The pros and cons of programming naked.")
assert !topic.respond_to?(:title)
exception = assert_raise(NoMethodError) { topic.title }
- assert_match %r(^Attempt to call private method), exception.message
+ assert exception.message.include?("private method")
assert_equal "I'm private", topic.send(:title)
end
@@ -617,7 +618,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
topic = @target.new
assert !topic.respond_to?(:title=)
exception = assert_raise(NoMethodError) { topic.title = "Pants"}
- assert_match %r(^Attempt to call private method), exception.message
+ assert exception.message.include?("private method")
topic.send(:title=, "Very large pants")
end
@@ -627,7 +628,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase
topic = @target.new(:title => "Isaac Newton's pants")
assert !topic.respond_to?(:title?)
exception = assert_raise(NoMethodError) { topic.title? }
- assert_match %r(^Attempt to call private method), exception.message
+ assert exception.message.include?("private method")
assert topic.send(:title?)
end
@@ -658,19 +659,46 @@ class AttributeMethodsTest < ActiveRecord::TestCase
assert_equal %w(preferences), Contact.serialized_attributes.keys
end
+ def test_instance_method_should_be_defined_on_the_base_class
+ subklass = Class.new(Topic)
+
+ Topic.define_attribute_methods
+
+ instance = subklass.new
+ instance.id = 5
+ assert_equal 5, instance.id
+ assert subklass.method_defined?(:id), "subklass is missing id method"
+
+ Topic.undefine_attribute_methods
+
+ assert_equal 5, instance.id
+ assert subklass.method_defined?(:id), "subklass is missing id method"
+ end
+
+ def test_dispatching_column_attributes_through_method_missing_deprecated
+ Topic.define_attribute_methods
+
+ topic = Topic.new(:id => 5)
+ topic.id = 5
+
+ topic.method(:id).owner.send(:undef_method, :id)
+
+ assert_deprecated do
+ assert_equal 5, topic.id
+ end
+ ensure
+ Topic.undefine_attribute_methods
+ end
+
private
def cached_columns
- @cached_columns ||= (time_related_columns_on_topic + serialized_columns_on_topic).map(&:name)
+ @cached_columns ||= time_related_columns_on_topic.map(&:name)
end
def time_related_columns_on_topic
Topic.columns.select { |c| c.type.in?([:time, :date, :datetime, :timestamp]) }
end
- def serialized_columns_on_topic
- Topic.columns.select { |c| Topic.serialized_attributes.include?(c.name) }
- end
-
def in_time_zone(zone)
old_zone = Time.zone
old_tz = ActiveRecord::Base.time_zone_aware_attributes
diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb
index 4ad2cdfc7e..4c3f2bda57 100644
--- a/activerecord/test/cases/autosave_association_test.rb
+++ b/activerecord/test/cases/autosave_association_test.rb
@@ -347,6 +347,17 @@ class TestDefaultAutosaveAssociationOnABelongsToAssociation < ActiveRecord::Test
client.save!
assert_no_queries { assert_equal apple, client.firm }
end
+
+ def test_validation_does_not_validate_stale_association_target
+ valid_developer = Developer.create!(:name => "Dude", :salary => 50_000)
+ invalid_developer = Developer.new()
+
+ auditlog = AuditLog.new(:message => "foo")
+ auditlog.developer = invalid_developer
+ auditlog.developer_id = valid_developer.id
+
+ assert auditlog.valid?
+ end
end
class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCase
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index 12101c1683..b1a429c869 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -22,8 +22,10 @@ require 'models/person'
require 'models/edge'
require 'models/joke'
require 'models/bulb'
+require 'models/bird'
require 'rexml/document'
require 'active_support/core_ext/exception'
+require 'bcrypt'
class Category < ActiveRecord::Base; end
class Categorization < ActiveRecord::Base; end
@@ -67,6 +69,38 @@ end
class BasicsTest < ActiveRecord::TestCase
fixtures :topics, :companies, :developers, :projects, :computers, :accounts, :minimalistics, 'warehouse-things', :authors, :categorizations, :categories, :posts
+ def test_generated_methods_modules
+ modules = Computer.ancestors
+ assert modules.include?(Computer::GeneratedFeatureMethods)
+ assert_equal(Computer::GeneratedFeatureMethods, Computer.generated_feature_methods)
+ assert(modules.index(Computer.generated_attribute_methods) > modules.index(Computer.generated_feature_methods),
+ "generated_attribute_methods must be higher in inheritance hierarchy than generated_feature_methods")
+ assert_not_equal Computer.generated_feature_methods, Post.generated_feature_methods
+ end
+
+ def test_column_names_are_escaped
+ conn = ActiveRecord::Base.connection
+ classname = conn.class.name[/[^:]*$/]
+ badchar = {
+ 'SQLite3Adapter' => '"',
+ 'MysqlAdapter' => '`',
+ 'Mysql2Adapter' => '`',
+ 'PostgreSQLAdapter' => '"',
+ 'OracleAdapter' => '"',
+ }.fetch(classname) {
+ raise "need a bad char for #{classname}"
+ }
+
+ quoted = conn.quote_column_name "foo#{badchar}bar"
+ if current_adapter?(:OracleAdapter)
+ # Oracle does not allow double quotes in table and column names at all
+ # therefore quoting removes them
+ assert_equal("#{badchar}foobar#{badchar}", quoted)
+ else
+ assert_equal("#{badchar}foo#{badchar * 2}bar#{badchar}", quoted)
+ end
+ end
+
def test_columns_should_obey_set_primary_key
pk = Subscriber.columns.find { |x| x.name == 'nick' }
assert pk.primary, 'nick should be primary key'
@@ -144,25 +178,6 @@ class BasicsTest < ActiveRecord::TestCase
end
end
- def test_use_table_engine_for_quoting_where
- relation = Topic.where(Topic.arel_table[:id].eq(1))
- engine = relation.table.engine
-
- fakepool = Class.new(Struct.new(:spec)) {
- def with_connection; yield self; end
- def connection_pool; self; end
- def table_exists?(name); false; end
- def quote_table_name(*args); raise "lol quote_table_name"; end
- }
-
- relation.table.engine = fakepool.new(engine.connection_pool.spec)
-
- error = assert_raises(RuntimeError) { relation.to_a }
- assert_match('lol', error.message)
- ensure
- relation.table.engine = engine
- end
-
def test_preserving_time_objects
assert_kind_of(
Time, Topic.find(1).bonus_time,
@@ -273,6 +288,29 @@ 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?
+ end
+
def test_load
topics = Topic.find(:all, :order => 'id')
assert_equal(4, topics.size)
@@ -1372,37 +1410,23 @@ class BasicsTest < ActiveRecord::TestCase
assert_equal dev, dev.reload
end
- def test_define_attr_method_with_value
- k = Class.new( ActiveRecord::Base )
- k.send(:define_attr_method, :table_name, "foo")
- assert_equal "foo", k.table_name
- end
-
- def test_define_attr_method_with_block
- k = Class.new( ActiveRecord::Base ) do
- class << self
- attr_accessor :foo_key
- end
- end
- k.foo_key = "id"
- k.send(:define_attr_method, :foo_key) { "sys_" + original_foo_key }
- assert_equal "sys_id", k.foo_key
- end
-
def test_set_table_name_with_value
k = Class.new( ActiveRecord::Base )
k.table_name = "foo"
assert_equal "foo", k.table_name
- k.set_table_name "bar"
+
+ assert_deprecated do
+ k.set_table_name "bar"
+ end
assert_equal "bar", k.table_name
end
def test_switching_between_table_name
assert_difference("GoodJoke.count") do
- Joke.set_table_name "cold_jokes"
+ Joke.table_name = "cold_jokes"
Joke.create
- Joke.set_table_name "funny_jokes"
+ Joke.table_name = "funny_jokes"
Joke.create
end
end
@@ -1410,50 +1434,171 @@ class BasicsTest < ActiveRecord::TestCase
def test_quoted_table_name_after_set_table_name
klass = Class.new(ActiveRecord::Base)
- klass.set_table_name "foo"
+ klass.table_name = "foo"
assert_equal "foo", klass.table_name
assert_equal klass.connection.quote_table_name("foo"), klass.quoted_table_name
- klass.set_table_name "bar"
+ klass.table_name = "bar"
assert_equal "bar", klass.table_name
assert_equal klass.connection.quote_table_name("bar"), klass.quoted_table_name
end
def test_set_table_name_with_block
k = Class.new( ActiveRecord::Base )
- k.set_table_name { "ks" }
- assert_equal "ks", k.table_name
+ assert_deprecated do
+ k.set_table_name "foo"
+ k.set_table_name do
+ ActiveSupport::Deprecation.silence { original_table_name } + "ks"
+ end
+ end
+ assert_equal "fooks", k.table_name
+ end
+
+ def test_set_table_name_with_inheritance
+ k = Class.new( ActiveRecord::Base )
+ def k.name; "Foo"; end
+ def k.table_name; super + "ks"; end
+ assert_equal "foosks", k.table_name
+ end
+
+ def test_original_table_name
+ k = Class.new(ActiveRecord::Base)
+ def k.name; "Foo"; end
+ k.table_name = "bar"
+
+ assert_deprecated do
+ assert_equal "foos", k.original_table_name
+ end
+
+ k = Class.new(ActiveRecord::Base)
+ k.table_name = "omg"
+ k.table_name = "wtf"
+
+ assert_deprecated do
+ assert_equal "omg", k.original_table_name
+ end
end
def test_set_primary_key_with_value
k = Class.new( ActiveRecord::Base )
k.primary_key = "foo"
assert_equal "foo", k.primary_key
- k.set_primary_key "bar"
+
+ assert_deprecated do
+ k.set_primary_key "bar"
+ end
assert_equal "bar", k.primary_key
end
def test_set_primary_key_with_block
k = Class.new( ActiveRecord::Base )
k.primary_key = 'id'
- k.set_primary_key { "sys_" + original_primary_key }
+
+ assert_deprecated do
+ k.set_primary_key do
+ "sys_" + ActiveSupport::Deprecation.silence { original_primary_key }
+ end
+ end
assert_equal "sys_id", k.primary_key
end
+ def test_original_primary_key
+ k = Class.new(ActiveRecord::Base)
+ def k.name; "Foo"; end
+ k.primary_key = "bar"
+
+ assert_deprecated do
+ assert_equal "id", k.original_primary_key
+ end
+
+ k = Class.new(ActiveRecord::Base)
+ k.primary_key = "omg"
+ k.primary_key = "wtf"
+
+ assert_deprecated do
+ assert_equal "omg", k.original_primary_key
+ end
+ end
+
def test_set_inheritance_column_with_value
k = Class.new( ActiveRecord::Base )
k.inheritance_column = "foo"
assert_equal "foo", k.inheritance_column
- k.set_inheritance_column "bar"
+
+ assert_deprecated do
+ k.set_inheritance_column "bar"
+ end
assert_equal "bar", k.inheritance_column
end
def test_set_inheritance_column_with_block
k = Class.new( ActiveRecord::Base )
- k.set_inheritance_column { original_inheritance_column + "_id" }
+ assert_deprecated do
+ k.set_inheritance_column do
+ ActiveSupport::Deprecation.silence { original_inheritance_column } + "_id"
+ end
+ end
assert_equal "type_id", k.inheritance_column
end
+ def test_original_inheritance_column
+ k = Class.new(ActiveRecord::Base)
+ def k.name; "Foo"; end
+ k.inheritance_column = "omg"
+
+ assert_deprecated do
+ assert_equal "type", k.original_inheritance_column
+ end
+ end
+
+ def test_set_sequence_name_with_value
+ k = Class.new( ActiveRecord::Base )
+ k.sequence_name = "foo"
+ assert_equal "foo", k.sequence_name
+
+ assert_deprecated do
+ k.set_sequence_name "bar"
+ end
+ assert_equal "bar", k.sequence_name
+ end
+
+ def test_set_sequence_name_with_block
+ k = Class.new( ActiveRecord::Base )
+ k.table_name = "projects"
+ orig_name = k.sequence_name
+ return skip "sequences not supported by db" unless orig_name
+
+ assert_deprecated do
+ k.set_sequence_name do
+ ActiveSupport::Deprecation.silence { original_sequence_name } + "_lol"
+ end
+ end
+ assert_equal orig_name + "_lol", k.sequence_name
+ end
+
+ def test_original_sequence_name
+ k = Class.new(ActiveRecord::Base)
+ k.table_name = "projects"
+ orig_name = k.sequence_name
+ return skip "sequences not supported by db" unless orig_name
+
+ k = Class.new(ActiveRecord::Base)
+ k.table_name = "projects"
+ k.sequence_name = "omg"
+
+ assert_deprecated do
+ assert_equal orig_name, k.original_sequence_name
+ end
+
+ k = Class.new(ActiveRecord::Base)
+ k.table_name = "projects"
+ k.sequence_name = "omg"
+ k.sequence_name = "wtf"
+ assert_deprecated do
+ assert_equal "omg", k.original_sequence_name
+ end
+ end
+
def test_count_with_join
res = Post.count_by_sql "SELECT COUNT(*) FROM posts LEFT JOIN comments ON posts.id=comments.post_id WHERE posts.#{QUOTED_TYPE} = 'Post'"
@@ -1627,6 +1772,10 @@ class BasicsTest < ActiveRecord::TestCase
assert !LooseDescendant.abstract_class?
end
+ def test_abstract_class_table_name
+ assert_nil AbstractCompany.table_name
+ end
+
def test_base_class
assert_equal LoosePerson, LoosePerson.base_class
assert_equal LooseDescendant, LooseDescendant.base_class
@@ -1728,6 +1877,14 @@ class BasicsTest < ActiveRecord::TestCase
assert_equal "The First Topic", topics(:first).becomes(Reply).title
end
+ def test_becomes_includes_errors
+ company = Company.new(:name => nil)
+ assert !company.valid?
+ original_errors = company.errors
+ client = company.becomes(Client)
+ assert_equal original_errors, client.errors
+ end
+
def test_silence_sets_log_level_to_error_in_block
original_logger = ActiveRecord::Base.logger
log = StringIO.new
@@ -1826,12 +1983,45 @@ class BasicsTest < ActiveRecord::TestCase
end
def test_marshal_round_trip
+ if ENV['TRAVIS'] && RUBY_VERSION == "1.8.7"
+ return skip("Marshalling tests disabled for Ruby 1.8.7 on Travis CI due to what appears " \
+ "to be a Ruby bug.")
+ end
+
expected = posts(:welcome)
- actual = Marshal.load(Marshal.dump(expected))
+ marshalled = Marshal.dump(expected)
+ actual = Marshal.load(marshalled)
assert_equal expected.attributes, actual.attributes
end
+ def test_marshal_new_record_round_trip
+ if ENV['TRAVIS'] && RUBY_VERSION == "1.8.7"
+ return skip("Marshalling tests disabled for Ruby 1.8.7 on Travis CI due to what appears " \
+ "to be a Ruby bug.")
+ end
+
+ marshalled = Marshal.dump(Post.new)
+ post = Marshal.load(marshalled)
+
+ assert post.new_record?, "should be a new record"
+ end
+
+ def test_marshalling_with_associations
+ if ENV['TRAVIS'] && RUBY_VERSION == "1.8.7"
+ return skip("Marshalling tests disabled for Ruby 1.8.7 on Travis CI due to what appears " \
+ "to be a Ruby bug.")
+ end
+
+ post = Post.new
+ post.comments.build
+
+ marshalled = Marshal.dump(post)
+ post = Marshal.load(marshalled)
+
+ assert_equal 1, post.comments.length
+ end
+
def test_attribute_names
assert_equal ["id", "type", "ruby_type", "firm_id", "firm_name", "name", "client_of", "rating", "account_id"],
Company.attribute_names
@@ -1869,4 +2059,10 @@ class BasicsTest < ActiveRecord::TestCase
dev.update_attribute(:updated_at, nil)
assert_match(/\/#{dev.id}$/, dev.cache_key)
end
+
+ def test_uniq_delegates_to_scoped
+ scope = stub
+ Bird.stubs(:scoped).returns(mock(:uniq => scope))
+ assert_equal scope, Bird.uniq
+ end
end
diff --git a/activerecord/test/cases/batches_test.rb b/activerecord/test/cases/batches_test.rb
index a35baee4ed..660098b9ad 100644
--- a/activerecord/test/cases/batches_test.rb
+++ b/activerecord/test/cases/batches_test.rb
@@ -113,7 +113,27 @@ class EachTest < ActiveRecord::TestCase
batch.map! { not_a_post }
end
end
+ end
+ def test_find_in_batches_should_ignore_the_order_default_scope
+ # First post is with title scope
+ first_post = PostWithDefaultScope.first
+ posts = []
+ PostWithDefaultScope.find_in_batches do |batch|
+ posts.concat(batch)
+ end
+ # posts.first will be ordered using id only. Title order scope should not apply here
+ assert_not_equal first_post, posts.first
+ assert_equal posts(:welcome), posts.first
+ end
+
+ def test_find_in_batches_should_not_ignore_the_default_scope_if_it_is_other_then_order
+ special_posts_ids = SpecialPostWithDefaultScope.all.map(&:id).sort
+ posts = []
+ SpecialPostWithDefaultScope.find_in_batches do |batch|
+ posts.concat(batch)
+ end
+ assert_equal special_posts_ids, posts.map(&:id)
end
end
diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb
index 42f98b3d42..5abf3d1af4 100644
--- a/activerecord/test/cases/calculations_test.rb
+++ b/activerecord/test/cases/calculations_test.rb
@@ -1,5 +1,6 @@
require "cases/helper"
require 'models/company'
+require "models/contract"
require 'models/topic'
require 'models/edge'
require 'models/club'
@@ -171,7 +172,7 @@ class CalculationsTest < ActiveRecord::TestCase
end
def test_should_group_by_summed_field_having_condition_from_select
- c = Account.select("MIN(credit_limit) AS min_credit_limit").group(:firm_id).having("min_credit_limit > 50").sum(:credit_limit)
+ c = Account.select("MIN(credit_limit) AS min_credit_limit").group(:firm_id).having("MIN(credit_limit) > 50").sum(:credit_limit)
assert_nil c[1]
assert_equal 60, c[2]
assert_equal 53, c[9]
@@ -446,4 +447,28 @@ class CalculationsTest < ActiveRecord::TestCase
distinct_authors_for_approved_count = Topic.group(:approved).count(:author_name, :distinct => true)[true]
assert_equal distinct_authors_for_approved_count, 2
end
+
+ def test_pluck
+ assert_equal [1,2,3,4], Topic.order(:id).pluck(:id)
+ end
+
+ def test_pluck_type_cast
+ topic = topics(:first)
+ relation = Topic.where(:id => topic.id)
+ assert_equal [ topic.approved ], relation.pluck(:approved)
+ assert_equal [ topic.last_read ], relation.pluck(:last_read)
+ assert_equal [ topic.written_on ], relation.pluck(:written_on)
+
+ end
+
+ def test_pluck_and_uniq
+ assert_equal [50, 53, 55, 60], Account.order(:credit_limit).uniq.pluck(:credit_limit)
+ end
+
+ def test_pluck_in_relation
+ company = Company.first
+ contract = company.contracts.create!
+ assert_equal [contract.id], company.contracts.pluck(:id)
+ end
+
end
diff --git a/activerecord/test/cases/callbacks_test.rb b/activerecord/test/cases/callbacks_test.rb
index 7f4d25790b..7690769226 100644
--- a/activerecord/test/cases/callbacks_test.rb
+++ b/activerecord/test/cases/callbacks_test.rb
@@ -1,7 +1,7 @@
require "cases/helper"
class CallbackDeveloper < ActiveRecord::Base
- set_table_name 'developers'
+ self.table_name = 'developers'
class << self
def callback_string(callback_method)
@@ -48,7 +48,7 @@ class CallbackDeveloperWithFalseValidation < CallbackDeveloper
end
class ParentDeveloper < ActiveRecord::Base
- set_table_name 'developers'
+ self.table_name = 'developers'
attr_accessor :after_save_called
before_validation {|record| record.after_save_called = true}
end
@@ -58,7 +58,7 @@ class ChildDeveloper < ParentDeveloper
end
class RecursiveCallbackDeveloper < ActiveRecord::Base
- set_table_name 'developers'
+ self.table_name = 'developers'
before_save :on_before_save
after_save :on_after_save
@@ -79,7 +79,7 @@ class RecursiveCallbackDeveloper < ActiveRecord::Base
end
class ImmutableDeveloper < ActiveRecord::Base
- set_table_name 'developers'
+ self.table_name = 'developers'
validates_inclusion_of :salary, :in => 50000..200000
@@ -98,7 +98,7 @@ class ImmutableDeveloper < ActiveRecord::Base
end
class ImmutableMethodDeveloper < ActiveRecord::Base
- set_table_name 'developers'
+ self.table_name = 'developers'
validates_inclusion_of :salary, :in => 50000..200000
@@ -118,7 +118,7 @@ class ImmutableMethodDeveloper < ActiveRecord::Base
end
class OnCallbacksDeveloper < ActiveRecord::Base
- set_table_name 'developers'
+ self.table_name = 'developers'
before_validation { history << :before_validation }
before_validation(:on => :create){ history << :before_validation_on_create }
@@ -138,7 +138,7 @@ class OnCallbacksDeveloper < ActiveRecord::Base
end
class CallbackCancellationDeveloper < ActiveRecord::Base
- set_table_name 'developers'
+ self.table_name = 'developers'
attr_reader :after_save_called, :after_create_called, :after_update_called, :after_destroy_called
attr_accessor :cancel_before_save, :cancel_before_create, :cancel_before_update, :cancel_before_destroy
diff --git a/activerecord/test/cases/column_definition_test.rb b/activerecord/test/cases/column_definition_test.rb
index d1dddd4c2c..14884e42af 100644
--- a/activerecord/test/cases/column_definition_test.rb
+++ b/activerecord/test/cases/column_definition_test.rb
@@ -58,68 +58,68 @@ module ActiveRecord
if current_adapter?(:MysqlAdapter)
def test_should_set_default_for_mysql_binary_data_types
- binary_column = MysqlColumn.new("title", "a", "binary(1)")
+ binary_column = MysqlAdapter::Column.new("title", "a", "binary(1)")
assert_equal "a", binary_column.default
- varbinary_column = MysqlColumn.new("title", "a", "varbinary(1)")
+ varbinary_column = MysqlAdapter::Column.new("title", "a", "varbinary(1)")
assert_equal "a", varbinary_column.default
end
def test_should_not_set_default_for_blob_and_text_data_types
assert_raise ArgumentError do
- MysqlColumn.new("title", "a", "blob")
+ MysqlAdapter::Column.new("title", "a", "blob")
end
assert_raise ArgumentError do
- MysqlColumn.new("title", "Hello", "text")
+ MysqlAdapter::Column.new("title", "Hello", "text")
end
- text_column = MysqlColumn.new("title", nil, "text")
+ text_column = MysqlAdapter::Column.new("title", nil, "text")
assert_equal nil, text_column.default
- not_null_text_column = MysqlColumn.new("title", nil, "text", false)
+ not_null_text_column = MysqlAdapter::Column.new("title", nil, "text", false)
assert_equal "", not_null_text_column.default
end
def test_has_default_should_return_false_for_blog_and_test_data_types
- blob_column = MysqlColumn.new("title", nil, "blob")
+ blob_column = MysqlAdapter::Column.new("title", nil, "blob")
assert !blob_column.has_default?
- text_column = MysqlColumn.new("title", nil, "text")
+ text_column = MysqlAdapter::Column.new("title", nil, "text")
assert !text_column.has_default?
end
end
if current_adapter?(:Mysql2Adapter)
def test_should_set_default_for_mysql_binary_data_types
- binary_column = Mysql2Column.new("title", "a", "binary(1)")
+ binary_column = Mysql2Adapter::Column.new("title", "a", "binary(1)")
assert_equal "a", binary_column.default
- varbinary_column = Mysql2Column.new("title", "a", "varbinary(1)")
+ varbinary_column = Mysql2Adapter::Column.new("title", "a", "varbinary(1)")
assert_equal "a", varbinary_column.default
end
def test_should_not_set_default_for_blob_and_text_data_types
assert_raise ArgumentError do
- Mysql2Column.new("title", "a", "blob")
+ Mysql2Adapter::Column.new("title", "a", "blob")
end
assert_raise ArgumentError do
- Mysql2Column.new("title", "Hello", "text")
+ Mysql2Adapter::Column.new("title", "Hello", "text")
end
- text_column = Mysql2Column.new("title", nil, "text")
+ text_column = Mysql2Adapter::Column.new("title", nil, "text")
assert_equal nil, text_column.default
- not_null_text_column = Mysql2Column.new("title", nil, "text", false)
+ not_null_text_column = Mysql2Adapter::Column.new("title", nil, "text", false)
assert_equal "", not_null_text_column.default
end
def test_has_default_should_return_false_for_blog_and_test_data_types
- blob_column = Mysql2Column.new("title", nil, "blob")
+ blob_column = Mysql2Adapter::Column.new("title", nil, "blob")
assert !blob_column.has_default?
- text_column = Mysql2Column.new("title", nil, "text")
+ text_column = Mysql2Adapter::Column.new("title", nil, "text")
assert !text_column.has_default?
end
end
diff --git a/activerecord/test/cases/connection_adapters/abstract_adapter_test.rb b/activerecord/test/cases/connection_adapters/abstract_adapter_test.rb
new file mode 100644
index 0000000000..7af9079b48
--- /dev/null
+++ b/activerecord/test/cases/connection_adapters/abstract_adapter_test.rb
@@ -0,0 +1,54 @@
+require "cases/helper"
+
+module ActiveRecord
+ module ConnectionAdapters
+ class AbstractAdapterTest < ActiveRecord::TestCase
+ attr_reader :adapter
+
+ def setup
+ @adapter = AbstractAdapter.new nil, nil
+ end
+
+ def test_in_use?
+ # FIXME: change to refute in Rails 4.0 / mt
+ assert !adapter.in_use?, 'adapter is not in use'
+ assert adapter.lease, 'lease adapter'
+ assert adapter.in_use?, 'adapter is in use'
+ end
+
+ def test_lease_twice
+ assert adapter.lease, 'should lease adapter'
+ assert !adapter.lease, 'should not lease adapter'
+ end
+
+ def test_last_use
+ assert !adapter.last_use
+ adapter.lease
+ assert adapter.last_use
+ end
+
+ def test_expire_mutates_in_use
+ assert adapter.lease, 'lease adapter'
+ assert adapter.in_use?, 'adapter is in use'
+ adapter.expire
+ assert !adapter.in_use?, 'adapter is in use'
+ end
+
+ def test_close
+ pool = ConnectionPool.new(Base::ConnectionSpecification.new({}, nil))
+ pool.connections << adapter
+ adapter.pool = pool
+
+ # Make sure the pool marks the connection in use
+ assert_equal adapter, pool.connection
+ assert adapter.in_use?
+
+ # Close should put the adapter back in the pool
+ adapter.close
+ assert !adapter.in_use?
+
+ assert_equal adapter, pool.connection
+ end
+ end
+ end
+end
diff --git a/activerecord/test/cases/connection_adapters/connection_handler_test.rb b/activerecord/test/cases/connection_adapters/connection_handler_test.rb
index abf317768f..04d543fea9 100644
--- a/activerecord/test/cases/connection_adapters/connection_handler_test.rb
+++ b/activerecord/test/cases/connection_adapters/connection_handler_test.rb
@@ -6,7 +6,12 @@ module ActiveRecord
def setup
@handler = ConnectionHandler.new
@handler.establish_connection 'america', Base.connection_pool.spec
- @klass = Struct.new(:name).new('america')
+ @klass = Class.new do
+ def self.name; 'america'; end
+ end
+ @subklass = Class.new(@klass) do
+ def self.name; 'north america'; end
+ end
end
def test_retrieve_connection
@@ -28,6 +33,18 @@ module ActiveRecord
def test_retrieve_connection_pool
assert_not_nil @handler.retrieve_connection_pool(@klass)
end
+
+ def test_retrieve_connection_pool_uses_superclass_when_no_subclass_connection
+ assert_not_nil @handler.retrieve_connection_pool(@subklass)
+ end
+
+ def test_retrieve_connection_pool_uses_superclass_pool_after_subclass_establish_and_remove
+ @handler.establish_connection 'north america', Base.connection_pool.spec
+
+ @handler.remove_connection @subklass
+ assert_same @handler.retrieve_connection_pool(@klass),
+ @handler.retrieve_connection_pool(@subklass)
+ end
end
end
end
diff --git a/activerecord/test/cases/connection_adapters/schema_cache_test.rb b/activerecord/test/cases/connection_adapters/schema_cache_test.rb
new file mode 100644
index 0000000000..d60de54aed
--- /dev/null
+++ b/activerecord/test/cases/connection_adapters/schema_cache_test.rb
@@ -0,0 +1,49 @@
+require "cases/helper"
+
+module ActiveRecord
+ module ConnectionAdapters
+ class SchemaCacheTest < ActiveRecord::TestCase
+ def setup
+ connection = ActiveRecord::Base.connection
+ @cache = SchemaCache.new connection
+ end
+
+ def test_primary_key
+ assert_equal 'id', @cache.primary_keys['posts']
+ end
+
+ def test_primary_key_for_non_existent_table
+ assert_equal 'id', @cache.primary_keys['omgponies']
+ end
+
+ def test_primary_key_is_set_on_columns
+ posts_columns = @cache.columns_hash['posts']
+ assert posts_columns['id'].primary
+
+ (posts_columns.keys - ['id']).each do |key|
+ assert !posts_columns[key].primary
+ end
+ end
+
+ def test_caches_columns
+ columns = @cache.columns['posts']
+ assert_equal columns, @cache.columns['posts']
+ end
+
+ def test_caches_columns_hash
+ columns_hash = @cache.columns_hash['posts']
+ assert_equal columns_hash, @cache.columns_hash['posts']
+ end
+
+ def test_clearing_column_cache
+ @cache.columns['posts']
+ @cache.columns_hash['posts']
+
+ @cache.clear!
+
+ assert_equal 0, @cache.columns.size
+ assert_equal 0, @cache.columns_hash.size
+ end
+ end
+ end
+end
diff --git a/activerecord/test/cases/connection_management_test.rb b/activerecord/test/cases/connection_management_test.rb
index f554ceef35..a1d1177289 100644
--- a/activerecord/test/cases/connection_management_test.rb
+++ b/activerecord/test/cases/connection_management_test.rb
@@ -25,40 +25,6 @@ module ActiveRecord
assert ActiveRecord::Base.connection_handler.active_connections?
end
- class FakeBase < ActiveRecord::Base
- def self.establish_connection spec
- String === spec ? super : spec
- end
- end
-
- def test_url_host_no_db
- spec = FakeBase.establish_connection 'postgres://foo?encoding=utf8'
- assert_equal({
- :adapter => "postgresql",
- :database => "",
- :host => "foo",
- :encoding => "utf8" }, spec)
- end
-
- def test_url_host_db
- spec = FakeBase.establish_connection 'postgres://foo/bar?encoding=utf8'
- assert_equal({
- :adapter => "postgresql",
- :database => "bar",
- :host => "foo",
- :encoding => "utf8" }, spec)
- end
-
- def test_url_port
- spec = FakeBase.establish_connection 'postgres://foo:123?encoding=utf8'
- assert_equal({
- :adapter => "postgresql",
- :database => "",
- :port => 123,
- :host => "foo",
- :encoding => "utf8" }, spec)
- end
-
def test_app_delegation
manager = ConnectionManagement.new(@app)
diff --git a/activerecord/test/cases/connection_pool_test.rb b/activerecord/test/cases/connection_pool_test.rb
index f92f4e62c5..d170a13b23 100644
--- a/activerecord/test/cases/connection_pool_test.rb
+++ b/activerecord/test/cases/connection_pool_test.rb
@@ -26,67 +26,6 @@ module ActiveRecord
assert !@pool.active_connection?
end
- def test_pool_caches_columns
- columns = @pool.columns['posts']
- assert_equal columns, @pool.columns['posts']
- end
-
- def test_pool_caches_columns_hash
- columns_hash = @pool.columns_hash['posts']
- assert_equal columns_hash, @pool.columns_hash['posts']
- end
-
- def test_clearing_column_cache
- @pool.columns['posts']
- @pool.columns_hash['posts']
-
- @pool.clear_cache!
-
- assert_equal 0, @pool.columns.size
- assert_equal 0, @pool.columns_hash.size
- end
-
- def test_primary_key
- assert_equal 'id', @pool.primary_keys['posts']
- end
-
- def test_primary_key_for_non_existent_table
- assert_equal 'id', @pool.primary_keys['omgponies']
- end
-
- def test_primary_key_is_set_on_columns
- posts_columns = @pool.columns_hash['posts']
- assert posts_columns['id'].primary
-
- (posts_columns.keys - ['id']).each do |key|
- assert !posts_columns[key].primary
- end
- end
-
- def test_clear_stale_cached_connections!
- pool = ConnectionPool.new ActiveRecord::Base.connection_pool.spec
-
- threads = [
- Thread.new { pool.connection },
- Thread.new { pool.connection }]
-
- threads.map { |t| t.join }
-
- pool.extend Module.new {
- attr_accessor :checkins
- def checkin conn
- @checkins << conn
- conn.object_id
- end
- }
- pool.checkins = []
-
- cleared_threads = pool.clear_stale_cached_connections!
- assert((cleared_threads - threads.map { |x| x.object_id }).empty?,
- "threads should have been removed")
- assert_equal pool.checkins.length, threads.length
- end
-
def test_checkout_behaviour
pool = ConnectionPool.new ActiveRecord::Base.connection_pool.spec
connection = pool.connection
@@ -107,12 +46,15 @@ module ActiveRecord
assert thread_ids.include?(t.object_id)
end
- pool.connection
+ assert_deprecated do
+ pool.connection
+ end
threads.each do |t|
thread_ids = pool.instance_variable_get(:@reserved_connections).keys
assert !thread_ids.include?(t.object_id)
end
- end.join()
+ pool.connection.close
+ end.join
end
@@ -135,6 +77,10 @@ module ActiveRecord
pool.with_connection
end
end
+
+ def test_pool_sets_connection_visitor
+ assert @pool.connection.visitor.is_a?(Arel::Visitors::ToSql)
+ end
end
end
end
diff --git a/activerecord/test/cases/connection_specification/resolver_test.rb b/activerecord/test/cases/connection_specification/resolver_test.rb
new file mode 100644
index 0000000000..d4b0f236ee
--- /dev/null
+++ b/activerecord/test/cases/connection_specification/resolver_test.rb
@@ -0,0 +1,41 @@
+require "cases/helper"
+
+module ActiveRecord
+ class Base
+ class ConnectionSpecification
+ class ResolverTest < ActiveRecord::TestCase
+ def resolve(spec)
+ Resolver.new(spec, {}).spec.config
+ end
+
+ def test_url_host_no_db
+ spec = resolve 'mysql://foo?encoding=utf8'
+ assert_equal({
+ :adapter => "mysql",
+ :database => "",
+ :host => "foo",
+ :encoding => "utf8" }, spec)
+ end
+
+ def test_url_host_db
+ spec = resolve 'mysql://foo/bar?encoding=utf8'
+ assert_equal({
+ :adapter => "mysql",
+ :database => "bar",
+ :host => "foo",
+ :encoding => "utf8" }, spec)
+ end
+
+ def test_url_port
+ spec = resolve 'mysql://foo:123?encoding=utf8'
+ assert_equal({
+ :adapter => "mysql",
+ :database => "",
+ :port => 123,
+ :host => "foo",
+ :encoding => "utf8" }, spec)
+ end
+ end
+ end
+ end
+end
diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb
index 5dc5f99582..4514a26e57 100644
--- a/activerecord/test/cases/finder_test.rb
+++ b/activerecord/test/cases/finder_test.rb
@@ -48,6 +48,20 @@ class FinderTest < ActiveRecord::TestCase
assert Topic.exists?
end
+ # exists? should handle nil for id's that come from URLs and always return false
+ # (example: Topic.exists?(params[:id])) where params[:id] is nil
+ def test_exists_with_nil_arg
+ assert !Topic.exists?(nil)
+ assert Topic.exists?
+ assert !Topic.first.replies.exists?(nil)
+ assert Topic.first.replies.exists?
+ end
+
+ # ensures +exists?+ runs valid SQL by excluding order value
+ def test_exists_with_order
+ assert Topic.order(:id).uniq.exists?
+ end
+
def test_does_not_exist_with_empty_table_and_no_args_given
Topic.delete_all
assert !Topic.exists?
@@ -243,6 +257,32 @@ class FinderTest < ActiveRecord::TestCase
end
end
+ def test_first_and_last_with_integer_should_use_sql_limit
+ assert_sql(/LIMIT 2|ROWNUM <= 2/) { Topic.first(2).entries }
+ assert_sql(/LIMIT 5|ROWNUM <= 5/) { Topic.last(5).entries }
+ end
+
+ def test_last_with_integer_and_order_should_keep_the_order
+ assert_equal Topic.order("title").to_a.last(2), Topic.order("title").last(2)
+ end
+
+ def test_last_with_integer_and_order_should_not_use_sql_limit
+ query = assert_sql { Topic.order("title").last(5).entries }
+ assert_equal 1, query.length
+ assert_no_match(/LIMIT/, query.first)
+ end
+
+ def test_last_with_integer_and_reorder_should_not_use_sql_limit
+ query = assert_sql { Topic.reorder("title").last(5).entries }
+ assert_equal 1, query.length
+ assert_no_match(/LIMIT/, query.first)
+ end
+
+ def test_first_and_last_with_integer_should_return_an_array
+ assert_kind_of Array, Topic.first(5)
+ assert_kind_of Array, Topic.last(5)
+ end
+
def test_unexisting_record_exception_handling
assert_raise(ActiveRecord::RecordNotFound) {
Topic.find(1).parent
@@ -334,6 +374,10 @@ class FinderTest < ActiveRecord::TestCase
assert_equal [1], Comment.find(:all, :conditions => { :id => 1..1, :post_id => 1..10 }).map(&:id).sort
end
+ def test_find_on_hash_conditions_with_array_of_integers_and_ranges
+ assert_equal [1,2,3,5,6,7,8,9], Comment.find(:all, :conditions => {:id => [1..2, 3, 5, 6..8, 9]}).map(&:id).sort
+ end
+
def test_find_on_multiple_hash_conditions
assert Topic.find(1, :conditions => { :author_name => "David", :title => "The First Topic", :replies_count => 1, :approved => false })
assert_raise(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { :author_name => "David", :title => "The First Topic", :replies_count => 1, :approved => true }) }
@@ -1119,7 +1163,7 @@ class FinderTest < ActiveRecord::TestCase
end
def test_find_one_message_with_custom_primary_key
- Toy.set_primary_key :name
+ Toy.primary_key = :name
begin
Toy.find 'Hello World!'
rescue ActiveRecord::RecordNotFound => e
diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb
index 842e8a0049..7e2dafcd01 100644
--- a/activerecord/test/cases/fixtures_test.rb
+++ b/activerecord/test/cases/fixtures_test.rb
@@ -20,6 +20,7 @@ require 'models/book'
require 'models/admin'
require 'models/admin/account'
require 'models/admin/user'
+require 'tempfile'
class FixturesTest < ActiveRecord::TestCase
self.use_instantiated_fixtures = true
@@ -45,6 +46,21 @@ class FixturesTest < ActiveRecord::TestCase
end
end
+ def test_broken_yaml_exception
+ badyaml = Tempfile.new ['foo', '.yml']
+ badyaml.write 'a: : '
+ badyaml.flush
+
+ dir = File.dirname badyaml.path
+ name = File.basename badyaml.path, '.yml'
+ assert_raises(ActiveRecord::Fixture::FormatError) do
+ ActiveRecord::Fixtures.create_fixtures(dir, name)
+ end
+ ensure
+ badyaml.close
+ badyaml.unlink
+ end
+
def test_create_fixtures
ActiveRecord::Fixtures.create_fixtures(FIXTURES_ROOT, "parrots")
assert Parrot.find_by_name('Curious George'), 'George is in the database'
@@ -435,14 +451,36 @@ end
class CustomConnectionFixturesTest < ActiveRecord::TestCase
set_fixture_class :courses => Course
fixtures :courses
- # Set to false to blow away fixtures cache and ensure our fixtures are loaded
- # and thus takes into account our set_fixture_class
self.use_transactional_fixtures = false
def test_connection
assert_kind_of Course, courses(:ruby)
assert_equal Course.connection, courses(:ruby).connection
end
+
+ def test_leaky_destroy
+ assert_nothing_raised { courses(:ruby) }
+ courses(:ruby).destroy
+ end
+
+ def test_it_twice_in_whatever_order_to_check_for_fixture_leakage
+ test_leaky_destroy
+ end
+end
+
+class TransactionalFixturesOnCustomConnectionTest < ActiveRecord::TestCase
+ set_fixture_class :courses => Course
+ fixtures :courses
+ self.use_transactional_fixtures = true
+
+ def test_leaky_destroy
+ assert_nothing_raised { courses(:ruby) }
+ courses(:ruby).destroy
+ end
+
+ def test_it_twice_in_whatever_order_to_check_for_fixture_leakage
+ test_leaky_destroy
+ end
end
class InvalidTableNameFixturesTest < ActiveRecord::TestCase
@@ -480,7 +518,9 @@ class ManyToManyFixturesWithClassDefined < ActiveRecord::TestCase
end
class FixturesBrokenRollbackTest < ActiveRecord::TestCase
- def blank_setup; end
+ def blank_setup
+ @fixture_connections = [ActiveRecord::Base.connection]
+ end
alias_method :ar_setup_fixtures, :setup_fixtures
alias_method :setup_fixtures, :blank_setup
alias_method :setup, :blank_setup
@@ -587,8 +627,8 @@ class FoxyFixturesTest < ActiveRecord::TestCase
end
def test_preserves_existing_fixture_data
- assert_equal(2.weeks.ago.utc.to_date, pirates(:redbeard).created_on.utc.to_date)
- assert_equal(2.weeks.ago.utc.to_date, pirates(:redbeard).updated_on.utc.to_date)
+ assert_equal(2.weeks.ago.to_date, pirates(:redbeard).created_on.to_date)
+ assert_equal(2.weeks.ago.to_date, pirates(:redbeard).updated_on.to_date)
end
def test_generates_unique_ids
diff --git a/activerecord/test/cases/inheritance_test.rb b/activerecord/test/cases/inheritance_test.rb
index b5d8314541..fab858e09c 100644
--- a/activerecord/test/cases/inheritance_test.rb
+++ b/activerecord/test/cases/inheritance_test.rb
@@ -236,11 +236,11 @@ class InheritanceTest < ActiveRecord::TestCase
c.save
end
[ Company, Firm, Client].each { |klass| klass.reset_column_information }
- Company.set_inheritance_column('ruby_type')
+ Company.inheritance_column = 'ruby_type'
end
def switch_to_default_inheritance_column
[ Company, Firm, Client].each { |klass| klass.reset_column_information }
- Company.set_inheritance_column('type')
+ Company.inheritance_column = 'type'
end
end
diff --git a/activerecord/test/cases/invertible_migration_test.rb b/activerecord/test/cases/invertible_migration_test.rb
index afec64750e..3ae7b63dff 100644
--- a/activerecord/test/cases/invertible_migration_test.rb
+++ b/activerecord/test/cases/invertible_migration_test.rb
@@ -27,6 +27,19 @@ module ActiveRecord
end
end
+ class LegacyMigration < ActiveRecord::Migration
+ def self.up
+ create_table("horses") do |t|
+ t.column :content, :text
+ t.column :remind_at, :datetime
+ end
+ end
+
+ def self.down
+ drop_table("horses")
+ end
+ end
+
def teardown
if ActiveRecord::Base.connection.table_exists?("horses")
ActiveRecord::Base.connection.drop_table("horses")
@@ -41,17 +54,39 @@ module ActiveRecord
end
end
- def test_up
+ def test_migrate_up
migration = InvertibleMigration.new
migration.migrate(:up)
assert migration.connection.table_exists?("horses"), "horses should exist"
end
- def test_down
+ def test_migrate_down
migration = InvertibleMigration.new
migration.migrate :up
migration.migrate :down
assert !migration.connection.table_exists?("horses")
end
+
+ def test_legacy_up
+ LegacyMigration.migrate :up
+ assert ActiveRecord::Base.connection.table_exists?("horses"), "horses should exist"
+ end
+
+ def test_legacy_down
+ LegacyMigration.migrate :up
+ LegacyMigration.migrate :down
+ assert !ActiveRecord::Base.connection.table_exists?("horses"), "horses should not exist"
+ end
+
+ def test_up
+ LegacyMigration.up
+ assert ActiveRecord::Base.connection.table_exists?("horses"), "horses should exist"
+ end
+
+ def test_down
+ LegacyMigration.up
+ LegacyMigration.down
+ assert !ActiveRecord::Base.connection.table_exists?("horses"), "horses should not exist"
+ end
end
end
diff --git a/activerecord/test/cases/lifecycle_test.rb b/activerecord/test/cases/lifecycle_test.rb
index 643e949087..75e5dfa49b 100644
--- a/activerecord/test/cases/lifecycle_test.rb
+++ b/activerecord/test/cases/lifecycle_test.rb
@@ -231,6 +231,18 @@ class LifecycleTest < ActiveRecord::TestCase
assert_not_nil observer.topic_ids.last
end
+ test "able to disable observers" do
+ observer = DeveloperObserver.instance # activate
+ observer.calls.clear
+
+ ActiveRecord::Base.observers.disable DeveloperObserver do
+ Developer.create! :name => 'Ancestor', :salary => 100000
+ SpecialDeveloper.create! :name => 'Descendent', :salary => 100000
+ end
+
+ assert_equal [], observer.calls
+ end
+
def test_observer_is_called_once
observer = DeveloperObserver.instance # activate
observer.calls.clear
diff --git a/activerecord/test/cases/locking_test.rb b/activerecord/test/cases/locking_test.rb
index 61baa55027..3d6db91f81 100644
--- a/activerecord/test/cases/locking_test.rb
+++ b/activerecord/test/cases/locking_test.rb
@@ -10,8 +10,8 @@ require 'models/string_key_object'
class LockWithoutDefault < ActiveRecord::Base; end
class LockWithCustomColumnWithoutDefault < ActiveRecord::Base
- set_table_name :lock_without_defaults_cust
- set_locking_column :custom_lock_version
+ self.table_name = :lock_without_defaults_cust
+ self.locking_column = :custom_lock_version
end
class ReadonlyFirstNamePerson < Person
@@ -125,6 +125,24 @@ class OptimisticLockingTest < ActiveRecord::TestCase
assert_raise(ActiveRecord::StaleObjectError) { p2.save! }
end
+ def test_lock_exception_record
+ p1 = Person.new(:first_name => 'mira')
+ assert_equal 0, p1.lock_version
+
+ p1.first_name = 'mira2'
+ p1.save!
+ p2 = Person.find(p1.id)
+ assert_equal 0, p1.lock_version
+ assert_equal 0, p2.lock_version
+
+ p1.first_name = 'mira3'
+ p1.save!
+
+ p2.first_name = 'sue'
+ error = assert_raise(ActiveRecord::StaleObjectError) { p2.save! }
+ assert_equal(error.record.object_id, p2.object_id)
+ end
+
def test_lock_new_with_nil
p1 = Person.new(:first_name => 'anika')
p1.save!
@@ -141,7 +159,6 @@ class OptimisticLockingTest < ActiveRecord::TestCase
assert_equal 1, p1.lock_version
end
-
def test_lock_column_name_existing
t1 = LegacyThing.find(1)
t2 = LegacyThing.find(1)
@@ -209,6 +226,48 @@ class OptimisticLockingTest < ActiveRecord::TestCase
end
end
+class SetLockingColumnTest < ActiveRecord::TestCase
+ def test_set_set_locking_column_with_value
+ k = Class.new( ActiveRecord::Base )
+ k.locking_column = "foo"
+ assert_equal "foo", k.locking_column
+
+ assert_deprecated do
+ k.set_locking_column "bar"
+ end
+ assert_equal "bar", k.locking_column
+ end
+
+ def test_set_locking_column_with_block
+ k = Class.new( ActiveRecord::Base )
+ k.locking_column = 'foo'
+
+ assert_deprecated do
+ k.set_locking_column do
+ "lock_" + ActiveSupport::Deprecation.silence { original_locking_column }
+ end
+ end
+ assert_equal "lock_foo", k.locking_column
+ end
+
+ def test_original_locking_column
+ k = Class.new(ActiveRecord::Base)
+ k.locking_column = "bar"
+
+ assert_deprecated do
+ assert_equal ActiveRecord::Locking::Optimistic::ClassMethods::DEFAULT_LOCKING_COLUMN, k.original_locking_column
+ end
+
+ k = Class.new(ActiveRecord::Base)
+ k.locking_column = "omg"
+ k.locking_column = "wtf"
+
+ assert_deprecated do
+ assert_equal "omg", k.original_locking_column
+ end
+ end
+end
+
class OptimisticLockingWithSchemaChangeTest < ActiveRecord::TestCase
fixtures :people, :legacy_things, :references
diff --git a/activerecord/test/cases/mass_assignment_security_test.rb b/activerecord/test/cases/mass_assignment_security_test.rb
index ef35f3341e..9fff50edcb 100644
--- a/activerecord/test/cases/mass_assignment_security_test.rb
+++ b/activerecord/test/cases/mass_assignment_security_test.rb
@@ -231,7 +231,9 @@ class MassAssignmentSecurityTest < ActiveRecord::TestCase
def test_protection_against_class_attribute_writers
[:logger, :configurations, :primary_key_prefix_type, :table_name_prefix, :table_name_suffix, :pluralize_table_names,
- :default_timezone, :schema_format, :lock_optimistically, :record_timestamps].each do |method|
+ :default_timezone, :schema_format, :lock_optimistically, :timestamped_migrations, :default_scopes,
+ :connection_handler, :nested_attributes_options, :_attr_readonly, :attribute_types_cached_by_default,
+ :attribute_method_matchers, :time_zone_aware_attributes, :skip_time_zone_conversion_for_attributes].each do |method|
assert_respond_to Task, method
assert_respond_to Task, "#{method}="
assert_respond_to Task.new, method
diff --git a/activerecord/test/cases/method_scoping_test.rb b/activerecord/test/cases/method_scoping_test.rb
index a0cb5dbdc5..0ab4f30363 100644
--- a/activerecord/test/cases/method_scoping_test.rb
+++ b/activerecord/test/cases/method_scoping_test.rb
@@ -14,7 +14,7 @@ class MethodScopingTest < ActiveRecord::TestCase
def test_set_conditions
Developer.send(:with_scope, :find => { :conditions => 'just a test...' }) do
- assert_match '(just a test...)', Developer.scoped.arel.to_sql
+ assert_match '(just a test...)', Developer.scoped.to_sql
end
end
@@ -274,7 +274,7 @@ class NestedScopingTest < ActiveRecord::TestCase
Developer.send(:with_scope, :find => { :conditions => 'salary = 80000' }) do
Developer.send(:with_scope, :find => { :limit => 10 }) do
devs = Developer.scoped
- assert_match '(salary = 80000)', devs.arel.to_sql
+ assert_match '(salary = 80000)', devs.to_sql
assert_equal 10, devs.taken
end
end
@@ -308,7 +308,7 @@ class NestedScopingTest < ActiveRecord::TestCase
Developer.send(:with_scope, :find => { :conditions => "name = 'David'" }) do
Developer.send(:with_scope, :find => { :conditions => 'salary = 80000' }) do
devs = Developer.scoped
- assert_match "(name = 'David') AND (salary = 80000)", devs.arel.to_sql
+ assert_match "(name = 'David') AND (salary = 80000)", devs.to_sql
assert_equal(1, Developer.count)
end
Developer.send(:with_scope, :find => { :conditions => "name = 'Maiha'" }) do
@@ -321,7 +321,7 @@ class NestedScopingTest < ActiveRecord::TestCase
Developer.send(:with_scope, :find => { :conditions => 'salary = 80000', :limit => 10 }) do
Developer.send(:with_scope, :find => { :conditions => "name = 'David'" }) do
devs = Developer.scoped
- assert_match "(salary = 80000) AND (name = 'David')", devs.arel.to_sql
+ assert_match "(salary = 80000) AND (name = 'David')", devs.to_sql
assert_equal 10, devs.taken
end
end
diff --git a/activerecord/test/cases/migration/command_recorder_test.rb b/activerecord/test/cases/migration/command_recorder_test.rb
index 36007255fa..d108b456f0 100644
--- a/activerecord/test/cases/migration/command_recorder_test.rb
+++ b/activerecord/test/cases/migration/command_recorder_test.rb
@@ -104,9 +104,9 @@ module ActiveRecord
end
def test_invert_rename_index
- @recorder.record :rename_index, [:old, :new]
+ @recorder.record :rename_index, [:table, :old, :new]
rename = @recorder.inverse.first
- assert_equal [:rename_index, [:new, :old]], rename
+ assert_equal [:rename_index, [:table, :new, :old]], rename
end
def test_invert_add_timestamps
diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb
index 93a1249e43..00c811194c 100644
--- a/activerecord/test/cases/migration_test.rb
+++ b/activerecord/test/cases/migration_test.rb
@@ -121,6 +121,18 @@ if ActiveRecord::Base.connection.supports_migrations?
assert_nothing_raised { Person.connection.add_index("people", %w(last_name first_name administrator), :name => "named_admin") }
assert_nothing_raised { Person.connection.remove_index("people", :name => "named_admin") }
end
+
+ # Selected adapters support index sort order
+ if current_adapter?(:SQLite3Adapter, :MysqlAdapter, :Mysql2Adapter, :PostgreSQLAdapter)
+ assert_nothing_raised { Person.connection.add_index("people", ["last_name"], :order => {:last_name => :desc}) }
+ assert_nothing_raised { Person.connection.remove_index("people", ["last_name"]) }
+ assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :order => {:last_name => :desc}) }
+ assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
+ assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :order => {:last_name => :desc, :first_name => :asc}) }
+ assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
+ assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"], :order => :desc) }
+ assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
+ end
end
def test_index_symbol_names
@@ -389,8 +401,8 @@ if ActiveRecord::Base.connection.supports_migrations?
created_at_column = created_columns.detect {|c| c.name == 'created_at' }
updated_at_column = created_columns.detect {|c| c.name == 'updated_at' }
- assert created_at_column.null
- assert updated_at_column.null
+ assert !created_at_column.null
+ assert !updated_at_column.null
ensure
Person.connection.drop_table table_name rescue nil
end
@@ -471,11 +483,13 @@ if ActiveRecord::Base.connection.supports_migrations?
# Do a manual insertion
if current_adapter?(:OracleAdapter)
- Person.connection.execute "insert into people (id, wealth) values (people_seq.nextval, 12345678901234567890.0123456789)"
+ Person.connection.execute "insert into people (id, wealth, created_at, updated_at) values (people_seq.nextval, 12345678901234567890.0123456789, sysdate, sysdate)"
elsif current_adapter?(:OpenBaseAdapter) || (current_adapter?(:MysqlAdapter) && Mysql.client_version < 50003) #before mysql 5.0.3 decimals stored as strings
- Person.connection.execute "insert into people (wealth) values ('12345678901234567890.0123456789')"
+ Person.connection.execute "insert into people (wealth, created_at, updated_at) values ('12345678901234567890.0123456789', 0, 0)"
+ elsif current_adapter?(:PostgreSQLAdapter)
+ Person.connection.execute "insert into people (wealth, created_at, updated_at) values (12345678901234567890.0123456789, now(), now())"
else
- Person.connection.execute "insert into people (wealth) values (12345678901234567890.0123456789)"
+ Person.connection.execute "insert into people (wealth, created_at, updated_at) values (12345678901234567890.0123456789, 0, 0)"
end
# SELECT
@@ -516,6 +530,42 @@ if ActiveRecord::Base.connection.supports_migrations?
assert_equal 7, wealth_column.scale
end
+ # Test SQLite adapter specifically for decimal types with precision and scale
+ # attributes, since these need to be maintained in schema but aren't actually
+ # used in SQLite itself
+ if current_adapter?(:SQLite3Adapter)
+ def test_change_column_with_new_precision_and_scale
+ Person.delete_all
+ Person.connection.add_column 'people', 'wealth', :decimal, :precision => 9, :scale => 7
+ Person.reset_column_information
+
+ Person.connection.change_column 'people', 'wealth', :decimal, :precision => 12, :scale => 8
+ Person.reset_column_information
+
+ wealth_column = Person.columns_hash['wealth']
+ assert_equal 12, wealth_column.precision
+ assert_equal 8, wealth_column.scale
+ end
+
+ def test_change_column_preserve_other_column_precision_and_scale
+ Person.delete_all
+ Person.connection.add_column 'people', 'last_name', :string
+ Person.connection.add_column 'people', 'wealth', :decimal, :precision => 9, :scale => 7
+ Person.reset_column_information
+
+ wealth_column = Person.columns_hash['wealth']
+ assert_equal 9, wealth_column.precision
+ assert_equal 7, wealth_column.scale
+
+ Person.connection.change_column 'people', 'last_name', :string, :null => false
+ Person.reset_column_information
+
+ wealth_column = Person.columns_hash['wealth']
+ assert_equal 9, wealth_column.precision
+ assert_equal 7, wealth_column.scale
+ end
+ end
+
def test_native_types
Person.delete_all
Person.connection.add_column "people", "last_name", :string
@@ -977,7 +1027,7 @@ if ActiveRecord::Base.connection.supports_migrations?
t.column :title, :string
end
person_klass = Class.new(Person)
- person_klass.set_table_name 'testings'
+ person_klass.table_name = 'testings'
person_klass.connection.add_column "testings", "wealth", :integer, :null => false, :default => 99
person_klass.reset_column_information
@@ -1301,6 +1351,15 @@ if ActiveRecord::Base.connection.supports_migrations?
end
end
+ def test_dump_schema_information_outputs_lexically_ordered_versions
+ migration_path = MIGRATIONS_ROOT + '/valid_with_timestamps'
+ ActiveRecord::Migrator.run(:up, migration_path, 20100301010101)
+ ActiveRecord::Migrator.run(:up, migration_path, 20100201010101)
+
+ schema_info = ActiveRecord::Base.connection.dump_schema_information
+ assert_match(/20100201010101.*20100301010101/m, schema_info)
+ end
+
def test_finds_pending_migrations
ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/interleaved/pass_2", 1)
migrations = ActiveRecord::Migrator.new(:up, MIGRATIONS_ROOT + "/interleaved/pass_2").pending_migrations
@@ -1580,91 +1639,6 @@ if ActiveRecord::Base.connection.supports_migrations?
end
- class SexyMigrationsTest < ActiveRecord::TestCase
- def test_references_column_type_adds_id
- with_new_table do |t|
- t.expects(:column).with('customer_id', :integer, {})
- t.references :customer
- end
- end
-
- def test_references_column_type_with_polymorphic_adds_type
- with_new_table do |t|
- t.expects(:column).with('taggable_type', :string, {})
- t.expects(:column).with('taggable_id', :integer, {})
- t.references :taggable, :polymorphic => true
- end
- end
-
- def test_references_column_type_with_polymorphic_and_options_null_is_false_adds_table_flag
- with_new_table do |t|
- t.expects(:column).with('taggable_type', :string, {:null => false})
- t.expects(:column).with('taggable_id', :integer, {:null => false})
- t.references :taggable, :polymorphic => true, :null => false
- end
- end
-
- def test_belongs_to_works_like_references
- with_new_table do |t|
- t.expects(:column).with('customer_id', :integer, {})
- t.belongs_to :customer
- end
- end
-
- def test_timestamps_creates_updated_at_and_created_at
- with_new_table do |t|
- t.expects(:column).with(:created_at, :datetime, kind_of(Hash))
- t.expects(:column).with(:updated_at, :datetime, kind_of(Hash))
- t.timestamps
- end
- end
-
- def test_integer_creates_integer_column
- with_new_table do |t|
- t.expects(:column).with(:foo, 'integer', {})
- t.expects(:column).with(:bar, 'integer', {})
- t.integer :foo, :bar
- end
- end
-
- def test_string_creates_string_column
- with_new_table do |t|
- t.expects(:column).with(:foo, 'string', {})
- t.expects(:column).with(:bar, 'string', {})
- t.string :foo, :bar
- end
- end
-
- if current_adapter?(:PostgreSQLAdapter) || current_adapter?(:SQLite3Adapter) || current_adapter?(:MysqlAdapter) || current_adapter?(:Mysql2Adapter)
- def test_xml_creates_xml_column
- type = current_adapter?(:PostgreSQLAdapter) ? 'xml' : :text
-
- with_new_table do |t|
- t.expects(:column).with(:data, type, {})
- t.xml :data
- end
- end
- else
- def test_xml_creates_xml_column
- with_new_table do |t|
- assert_raises(NotImplementedError) do
- t.xml :data
- end
- end
- end
- end
-
- protected
- def with_new_table
- Person.connection.create_table :delete_me, :force => true do |t|
- yield t
- end
- ensure
- Person.connection.drop_table :delete_me rescue nil
- end
-
- end # SexyMigrationsTest
-
class MigrationLoggerTest < ActiveRecord::TestCase
def test_migration_should_be_run_without_logger
previous_logger = ActiveRecord::Base.logger
diff --git a/activerecord/test/cases/multiple_db_test.rb b/activerecord/test/cases/multiple_db_test.rb
index bd51388e05..e704322b5d 100644
--- a/activerecord/test/cases/multiple_db_test.rb
+++ b/activerecord/test/cases/multiple_db_test.rb
@@ -85,7 +85,6 @@ class MultipleDbTest < ActiveRecord::TestCase
end
def test_arel_table_engines
- assert_not_equal Entrant.arel_engine, Course.arel_engine
assert_equal Entrant.arel_engine, Bird.arel_engine
end
end
diff --git a/activerecord/test/cases/named_scope_test.rb b/activerecord/test/cases/named_scope_test.rb
index ed0240cada..4a09a87322 100644
--- a/activerecord/test/cases/named_scope_test.rb
+++ b/activerecord/test/cases/named_scope_test.rb
@@ -182,7 +182,7 @@ class NamedScopeTest < ActiveRecord::TestCase
def test_first_and_last_should_allow_integers_for_limit
assert_equal Topic.base.first(2), Topic.base.to_a.first(2)
- assert_equal Topic.base.last(2), Topic.base.to_a.last(2)
+ assert_equal Topic.base.last(2), Topic.base.order("id").to_a.last(2)
end
def test_first_and_last_should_not_use_query_when_results_are_loaded
diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb
index 67a9ed6cd8..2ae9cb4888 100644
--- a/activerecord/test/cases/nested_attributes_test.rb
+++ b/activerecord/test/cases/nested_attributes_test.rb
@@ -45,6 +45,14 @@ class TestNestedAttributesInGeneral < ActiveRecord::TestCase
end
end
+ def test_should_not_build_a_new_record_using_reject_all_even_if_destroy_is_given
+ pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
+ pirate.birds_with_reject_all_blank_attributes = [{:name => '', :color => '', :_destroy => '0'}]
+ pirate.save!
+
+ assert pirate.birds_with_reject_all_blank.empty?
+ end
+
def test_should_not_build_a_new_record_if_reject_all_blank_returns_false
pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
pirate.birds_with_reject_all_blank_attributes = [{:name => '', :color => ''}]
diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb
index 9cd07fa8a5..adfd8e83a1 100644
--- a/activerecord/test/cases/persistence_test.rb
+++ b/activerecord/test/cases/persistence_test.rb
@@ -202,9 +202,12 @@ class PersistencesTest < ActiveRecord::TestCase
end
def test_create_columns_not_equal_attributes
- topic = Topic.new
- topic.title = 'Another New Topic'
- topic.send :write_attribute, 'does_not_exist', 'test'
+ topic = Topic.allocate.init_with(
+ 'attributes' => {
+ 'title' => 'Another New Topic',
+ 'does_not_exist' => 'test'
+ }
+ )
assert_nothing_raised { topic.save }
end
@@ -249,9 +252,11 @@ class PersistencesTest < ActiveRecord::TestCase
topic.title = "Still another topic"
topic.save
- topicReloaded = Topic.find(topic.id)
- topicReloaded.title = "A New Topic"
- topicReloaded.send :write_attribute, 'does_not_exist', 'test'
+ topicReloaded = Topic.allocate
+ topicReloaded.init_with(
+ 'attributes' => topic.attributes.merge('does_not_exist' => 'test')
+ )
+ topicReloaded.title = 'A New Topic'
assert_nothing_raised { topicReloaded.save }
end
diff --git a/activerecord/test/cases/pooled_connections_test.rb b/activerecord/test/cases/pooled_connections_test.rb
index 379cf5b44e..bc3dfb1078 100644
--- a/activerecord/test/cases/pooled_connections_test.rb
+++ b/activerecord/test/cases/pooled_connections_test.rb
@@ -3,6 +3,8 @@ require "models/project"
require "timeout"
class PooledConnectionsTest < ActiveRecord::TestCase
+ self.use_transactional_fixtures = false
+
def setup
@per_test_teardown = []
@connection = ActiveRecord::Base.remove_connection
@@ -64,78 +66,6 @@ class PooledConnectionsTest < ActiveRecord::TestCase
assert_equal 1, ActiveRecord::Base.connection_pool.connections.size
end
- def test_pooled_connection_checkin_two
- checkout_checkin_connections 2, 3
- assert_equal 3, @connection_count
- assert_equal 0, @timed_out
- assert_equal 1, ActiveRecord::Base.connection_pool.connections.size
- end
-
- def test_pooled_connection_checkout_existing_first
- ActiveRecord::Base.establish_connection(@connection.merge({:pool => 1}))
- conn_pool = ActiveRecord::Base.connection_pool
- conn = conn_pool.checkout
- conn_pool.checkin(conn)
- conn = conn_pool.checkout
- assert ActiveRecord::ConnectionAdapters::AbstractAdapter === conn
- conn_pool.checkin(conn)
- end
-
- def test_not_connected_defined_connection_returns_false
- ActiveRecord::Base.establish_connection(@connection)
- assert ! ActiveRecord::Base.connected?
- end
-
- def test_undefined_connection_returns_false
- old_handler = ActiveRecord::Base.connection_handler
- ActiveRecord::Base.connection_handler = ActiveRecord::ConnectionAdapters::ConnectionHandler.new
- assert ! ActiveRecord::Base.connected?
- ensure
- ActiveRecord::Base.connection_handler = old_handler
- end
-
- def test_connection_config
- ActiveRecord::Base.establish_connection(@connection)
- assert_equal @connection, ActiveRecord::Base.connection_config
- end
-
- def test_with_connection_nesting_safety
- ActiveRecord::Base.establish_connection(@connection.merge({:pool => 1, :wait_timeout => 0.1}))
-
- before_count = Project.count
-
- add_record('one')
-
- ActiveRecord::Base.connection.transaction do
- add_record('two')
- # Have another thread try to screw up the transaction
- Thread.new do
- ActiveRecord::Base.connection.rollback_db_transaction
- ActiveRecord::Base.connection_pool.release_connection
- end
- add_record('three')
- end
-
- after_count = Project.count
- assert_equal 3, after_count - before_count
- end
-
- def test_connection_pool_callbacks
- checked_out, checked_in = false, false
- ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval do
- set_callback(:checkout, :after) { checked_out = true }
- set_callback(:checkin, :before) { checked_in = true }
- end
- @per_test_teardown << proc do
- ActiveRecord::ConnectionAdapters::AbstractAdapter.class_eval do
- reset_callbacks :checkout
- reset_callbacks :checkin
- end
- end
- checkout_checkin_connections 1, 1
- assert checked_out
- assert checked_in
- end
private
diff --git a/activerecord/test/cases/primary_keys_test.rb b/activerecord/test/cases/primary_keys_test.rb
index 7e3da145e5..cc8ffb5f27 100644
--- a/activerecord/test/cases/primary_keys_test.rb
+++ b/activerecord/test/cases/primary_keys_test.rb
@@ -26,7 +26,7 @@ class PrimaryKeysTest < ActiveRecord::TestCase
def test_to_key_with_primary_key_after_destroy
topic = Topic.find(1)
topic.destroy
- assert_equal nil, topic.to_key
+ assert_equal [1], topic.to_key
end
def test_integer_key
@@ -142,7 +142,24 @@ class PrimaryKeysTest < ActiveRecord::TestCase
assert_equal k.connection.quote_column_name("id"), k.quoted_primary_key
k.primary_key = "foo"
assert_equal k.connection.quote_column_name("foo"), k.quoted_primary_key
- k.set_primary_key "bar"
- assert_equal k.connection.quote_column_name("bar"), k.quoted_primary_key
+ end
+end
+
+class PrimaryKeyWithNoConnectionTest < ActiveRecord::TestCase
+ self.use_transactional_fixtures = false
+
+ def test_set_primary_key_with_no_connection
+ return skip("disconnect wipes in-memory db") if in_memory_db?
+
+ connection = ActiveRecord::Base.remove_connection
+
+ model = Class.new(ActiveRecord::Base)
+ model.primary_key = 'foo'
+
+ assert_equal 'foo', model.primary_key
+
+ ActiveRecord::Base.establish_connection(connection)
+
+ assert_equal 'foo', model.primary_key
end
end
diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb
index ad17f6f83a..9554386dcf 100644
--- a/activerecord/test/cases/query_cache_test.rb
+++ b/activerecord/test/cases/query_cache_test.rb
@@ -13,6 +13,32 @@ class QueryCacheTest < ActiveRecord::TestCase
ActiveRecord::Base.connection.disable_query_cache!
end
+ def test_exceptional_middleware_clears_and_disables_cache_on_error
+ assert !ActiveRecord::Base.connection.query_cache_enabled, 'cache off'
+
+ mw = ActiveRecord::QueryCache.new lambda { |env|
+ Task.find 1
+ Task.find 1
+ assert_equal 1, ActiveRecord::Base.connection.query_cache.length
+ raise "lol borked"
+ }
+ assert_raises(RuntimeError) { mw.call({}) }
+
+ assert_equal 0, ActiveRecord::Base.connection.query_cache.length
+ assert !ActiveRecord::Base.connection.query_cache_enabled, 'cache off'
+ end
+
+ def test_exceptional_middleware_leaves_enabled_cache_alone
+ ActiveRecord::Base.connection.enable_query_cache!
+
+ mw = ActiveRecord::QueryCache.new lambda { |env|
+ raise "lol borked"
+ }
+ assert_raises(RuntimeError) { mw.call({}) }
+
+ assert ActiveRecord::Base.connection.query_cache_enabled, 'cache on'
+ end
+
def test_middleware_delegates
called = false
mw = ActiveRecord::QueryCache.new lambda { |env|
@@ -121,13 +147,16 @@ class QueryCacheTest < ActiveRecord::TestCase
end
def test_cache_does_not_wrap_string_results_in_arrays
- require 'sqlite3/version' if current_adapter?(:SQLite3Adapter)
+ if current_adapter?(:SQLite3Adapter)
+ require 'sqlite3/version'
+ sqlite3_version = RUBY_PLATFORM =~ /java/ ? Jdbc::SQLite3::VERSION : SQLite3::VERSION
+ end
Task.cache do
# Oracle adapter returns count() as Fixnum or Float
if current_adapter?(:OracleAdapter)
assert_kind_of Numeric, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks")
- elsif current_adapter?(:SQLite3Adapter) && SQLite3::VERSION > '1.2.5' || current_adapter?(:Mysql2Adapter) || current_adapter?(:MysqlAdapter)
+ elsif current_adapter?(:SQLite3Adapter) && sqlite3_version > '1.2.5' || current_adapter?(:Mysql2Adapter) || current_adapter?(:MysqlAdapter)
# Future versions of the sqlite3 adapter will return numeric
assert_instance_of Fixnum,
Task.connection.select_value("SELECT count(*) AS count_all FROM tasks")
@@ -141,6 +170,18 @@ end
class QueryCacheExpiryTest < ActiveRecord::TestCase
fixtures :tasks, :posts, :categories, :categories_posts
+ def test_cache_gets_cleared_after_migration
+ # warm the cache
+ Post.find(1)
+
+ # change the column definition
+ Post.connection.change_column :posts, :title, :string, :limit => 80
+ assert_nothing_raised { Post.find(1) }
+
+ # restore the old definition
+ Post.connection.change_column :posts, :title, :string
+ end
+
def test_find
Task.connection.expects(:clear_query_cache).times(1)
@@ -208,9 +249,9 @@ class QueryCacheBodyProxyTest < ActiveRecord::TestCase
test "is polite to it's body and responds to it" do
body = Class.new(String) { def to_path; "/path"; end }.new
- proxy = ActiveRecord::QueryCache::BodyProxy.new(nil, body)
+ proxy = ActiveRecord::QueryCache::BodyProxy.new(nil, body, ActiveRecord::Base.connection_id)
assert proxy.respond_to?(:to_path)
assert_equal proxy.to_path, "/path"
end
-end \ No newline at end of file
+end
diff --git a/activerecord/test/cases/reflection_test.rb b/activerecord/test/cases/reflection_test.rb
index 41312e8661..b30db542a7 100644
--- a/activerecord/test/cases/reflection_test.rb
+++ b/activerecord/test/cases/reflection_test.rb
@@ -18,6 +18,7 @@ require 'models/subscriber'
require 'models/subscription'
require 'models/tag'
require 'models/sponsor'
+require 'models/edge'
class ReflectionTest < ActiveRecord::TestCase
include ActiveRecord::Reflection
@@ -188,8 +189,8 @@ class ReflectionTest < ActiveRecord::TestCase
def test_reflection_of_all_associations
# FIXME these assertions bust a lot
- assert_equal 36, Firm.reflect_on_all_associations.size
- assert_equal 26, Firm.reflect_on_all_associations(:has_many).size
+ assert_equal 37, Firm.reflect_on_all_associations.size
+ assert_equal 27, Firm.reflect_on_all_associations(:has_many).size
assert_equal 10, Firm.reflect_on_all_associations(:has_one).size
assert_equal 0, Firm.reflect_on_all_associations(:belongs_to).size
end
@@ -244,7 +245,7 @@ class ReflectionTest < ActiveRecord::TestCase
# Normal association
assert_equal "id", Author.reflect_on_association(:posts).association_primary_key.to_s
assert_equal "name", Author.reflect_on_association(:essay).association_primary_key.to_s
- assert_equal "id", Tagging.reflect_on_association(:taggable).association_primary_key.to_s
+ assert_equal "name", Essay.reflect_on_association(:writer).association_primary_key.to_s
# Through association (uses the :primary_key option from the source reflection)
assert_equal "nick", Author.reflect_on_association(:subscribers).association_primary_key.to_s
@@ -252,11 +253,25 @@ class ReflectionTest < ActiveRecord::TestCase
assert_equal "custom_primary_key", Author.reflect_on_association(:tags_with_primary_key).association_primary_key.to_s # nested
end
+ def test_association_primary_key_raises_when_missing_primary_key
+ reflection = ActiveRecord::Reflection::AssociationReflection.new(:fuu, :edge, {}, Author)
+ assert_raises(ActiveRecord::UnknownPrimaryKey) { reflection.association_primary_key }
+
+ through = ActiveRecord::Reflection::ThroughReflection.new(:fuu, :edge, {}, Author)
+ through.stubs(:source_reflection).returns(stub_everything(:options => {}, :class_name => 'Edge'))
+ assert_raises(ActiveRecord::UnknownPrimaryKey) { through.association_primary_key }
+ end
+
def test_active_record_primary_key
assert_equal "nick", Subscriber.reflect_on_association(:subscriptions).active_record_primary_key.to_s
assert_equal "name", Author.reflect_on_association(:essay).active_record_primary_key.to_s
end
+ def test_active_record_primary_key_raises_when_missing_primary_key
+ reflection = ActiveRecord::Reflection::AssociationReflection.new(:fuu, :author, {}, Edge)
+ assert_raises(ActiveRecord::UnknownPrimaryKey) { reflection.active_record_primary_key }
+ end
+
def test_foreign_type
assert_equal "sponsorable_type", Sponsor.reflect_on_association(:sponsorable).foreign_type.to_s
assert_equal "sponsorable_type", Sponsor.reflect_on_association(:thing).foreign_type.to_s
@@ -304,6 +319,16 @@ class ReflectionTest < ActiveRecord::TestCase
assert_equal "category_id", Post.reflect_on_association(:categorizations).foreign_key.to_s
end
+ def test_through_reflection_conditions_do_not_modify_other_reflections
+ orig_conds = Post.reflect_on_association(:first_blue_tags_2).conditions.inspect
+ Author.reflect_on_association(:misc_post_first_blue_tags_2).conditions
+ assert_equal orig_conds, Post.reflect_on_association(:first_blue_tags_2).conditions.inspect
+ end
+
+ def test_symbol_for_class_name
+ assert_equal Client, Firm.reflect_on_association(:unsorted_clients_with_symbol).klass
+ end
+
private
def assert_reflection(klass, association, options)
assert reflection = klass.reflect_on_association(association)
diff --git a/activerecord/test/cases/relation_scoping_test.rb b/activerecord/test/cases/relation_scoping_test.rb
index f2d177d834..1e2093273e 100644
--- a/activerecord/test/cases/relation_scoping_test.rb
+++ b/activerecord/test/cases/relation_scoping_test.rb
@@ -170,7 +170,7 @@ class NestedRelationScopingTest < ActiveRecord::TestCase
Developer.where('salary = 80000').scoping do
Developer.limit(10).scoping do
devs = Developer.scoped
- assert_match '(salary = 80000)', devs.arel.to_sql
+ assert_match '(salary = 80000)', devs.to_sql
assert_equal 10, devs.taken
end
end
@@ -524,4 +524,22 @@ class DefaultScopingTest < ActiveRecord::TestCase
assert_equal 1, DeveloperWithIncludes.where(:audit_logs => { :message => 'foo' }).count
end
+
+ def test_default_scope_is_threadsafe
+ if in_memory_db?
+ skip "in memory db can't share a db between threads"
+ end
+
+ threads = []
+ assert_not_equal 1, ThreadsafeDeveloper.unscoped.count
+
+ threads << Thread.new do
+ Thread.current[:long_default_scope] = true
+ assert_equal 1, ThreadsafeDeveloper.all.count
+ end
+ threads << Thread.new do
+ assert_equal 1, ThreadsafeDeveloper.all.count
+ end
+ threads.each(&:join)
+ end
end
diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb
index b23ead6feb..715a378431 100644
--- a/activerecord/test/cases/relation_test.rb
+++ b/activerecord/test/cases/relation_test.rb
@@ -20,7 +20,7 @@ module ActiveRecord
end
def test_single_values
- assert_equal [:limit, :offset, :lock, :readonly, :from, :reorder, :reverse_order].map(&:to_s).sort,
+ assert_equal [:limit, :offset, :lock, :readonly, :from, :reorder, :reverse_order, :uniq].map(&:to_s).sort,
Relation::SINGLE_VALUE_METHODS.map(&:to_s).sort
end
diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb
index 8a2cf0ef85..bf1eb6386a 100644
--- a/activerecord/test/cases/relations_test.rb
+++ b/activerecord/test/cases/relations_test.rb
@@ -540,6 +540,29 @@ class RelationTest < ActiveRecord::TestCase
}
end
+ def test_find_all_using_where_with_relation_and_alternate_primary_key
+ cool_first = minivans(:cool_first)
+ # switching the lines below would succeed in current rails
+ # assert_queries(2) {
+ assert_queries(1) {
+ relation = Minivan.where(:minivan_id => Minivan.where(:name => cool_first.name))
+ assert_equal [cool_first], relation.all
+ }
+ end
+
+ def test_find_all_using_where_with_relation_does_not_alter_select_values
+ david = authors(:david)
+
+ subquery = Author.where(:id => david.id)
+
+ assert_queries(1) {
+ relation = Author.where(:id => subquery)
+ assert_equal [david], relation.all
+ }
+
+ assert_equal 0, subquery.select_values.size
+ end
+
def test_find_all_using_where_with_relation_with_joins
david = authors(:david)
assert_queries(1) {
@@ -840,6 +863,128 @@ class RelationTest < ActiveRecord::TestCase
assert_equal 'hen', hen.name
end
+ def test_first_or_create
+ parrot = Bird.where(:color => 'green').first_or_create(:name => 'parrot')
+ assert_kind_of Bird, parrot
+ assert parrot.persisted?
+ assert_equal 'parrot', parrot.name
+ assert_equal 'green', parrot.color
+
+ same_parrot = Bird.where(:color => 'green').first_or_create(:name => 'parakeet')
+ assert_kind_of Bird, same_parrot
+ assert same_parrot.persisted?
+ assert_equal parrot, same_parrot
+ end
+
+ def test_first_or_create_with_no_parameters
+ parrot = Bird.where(:color => 'green').first_or_create
+ assert_kind_of Bird, parrot
+ assert !parrot.persisted?
+ assert_equal 'green', parrot.color
+ end
+
+ def test_first_or_create_with_block
+ parrot = Bird.where(:color => 'green').first_or_create { |bird| bird.name = 'parrot' }
+ assert_kind_of Bird, parrot
+ assert parrot.persisted?
+ assert_equal 'green', parrot.color
+ assert_equal 'parrot', parrot.name
+
+ same_parrot = Bird.where(:color => 'green').first_or_create { |bird| bird.name = 'parakeet' }
+ assert_equal parrot, same_parrot
+ end
+
+ def test_first_or_create_with_array
+ several_green_birds = Bird.where(:color => 'green').first_or_create([{:name => 'parrot'}, {:name => 'parakeet'}])
+ assert_kind_of Array, several_green_birds
+ several_green_birds.each { |bird| assert bird.persisted? }
+
+ same_parrot = Bird.where(:color => 'green').first_or_create([{:name => 'hummingbird'}, {:name => 'macaw'}])
+ assert_kind_of Bird, same_parrot
+ assert_equal several_green_birds.first, same_parrot
+ end
+
+ def test_first_or_create_bang_with_valid_options
+ parrot = Bird.where(:color => 'green').first_or_create!(:name => 'parrot')
+ assert_kind_of Bird, parrot
+ assert parrot.persisted?
+ assert_equal 'parrot', parrot.name
+ assert_equal 'green', parrot.color
+
+ same_parrot = Bird.where(:color => 'green').first_or_create!(:name => 'parakeet')
+ assert_kind_of Bird, same_parrot
+ assert same_parrot.persisted?
+ assert_equal parrot, same_parrot
+ end
+
+ def test_first_or_create_bang_with_invalid_options
+ assert_raises(ActiveRecord::RecordInvalid) { Bird.where(:color => 'green').first_or_create!(:pirate_id => 1) }
+ end
+
+ def test_first_or_create_bang_with_no_parameters
+ assert_raises(ActiveRecord::RecordInvalid) { Bird.where(:color => 'green').first_or_create! }
+ end
+
+ def test_first_or_create_bang_with_valid_block
+ parrot = Bird.where(:color => 'green').first_or_create! { |bird| bird.name = 'parrot' }
+ assert_kind_of Bird, parrot
+ assert parrot.persisted?
+ assert_equal 'green', parrot.color
+ assert_equal 'parrot', parrot.name
+
+ same_parrot = Bird.where(:color => 'green').first_or_create! { |bird| bird.name = 'parakeet' }
+ assert_equal parrot, same_parrot
+ end
+
+ def test_first_or_create_bang_with_invalid_block
+ assert_raise(ActiveRecord::RecordInvalid) do
+ Bird.where(:color => 'green').first_or_create! { |bird| bird.pirate_id = 1 }
+ end
+ end
+
+ def test_first_or_create_with_valid_array
+ several_green_birds = Bird.where(:color => 'green').first_or_create!([{:name => 'parrot'}, {:name => 'parakeet'}])
+ assert_kind_of Array, several_green_birds
+ several_green_birds.each { |bird| assert bird.persisted? }
+
+ same_parrot = Bird.where(:color => 'green').first_or_create!([{:name => 'hummingbird'}, {:name => 'macaw'}])
+ assert_kind_of Bird, same_parrot
+ assert_equal several_green_birds.first, same_parrot
+ end
+
+ def test_first_or_create_with_invalid_array
+ assert_raises(ActiveRecord::RecordInvalid) { Bird.where(:color => 'green').first_or_create!([ {:name => 'parrot'}, {:pirate_id => 1} ]) }
+ end
+
+ def test_first_or_initialize
+ parrot = Bird.where(:color => 'green').first_or_initialize(:name => 'parrot')
+ assert_kind_of Bird, parrot
+ assert !parrot.persisted?
+ assert parrot.valid?
+ assert parrot.new_record?
+ assert_equal 'parrot', parrot.name
+ assert_equal 'green', parrot.color
+ end
+
+ def test_first_or_initialize_with_no_parameters
+ parrot = Bird.where(:color => 'green').first_or_initialize
+ assert_kind_of Bird, parrot
+ assert !parrot.persisted?
+ assert !parrot.valid?
+ assert parrot.new_record?
+ assert_equal 'green', parrot.color
+ end
+
+ def test_first_or_initialize_with_block
+ parrot = Bird.where(:color => 'green').first_or_initialize { |bird| bird.name = 'parrot' }
+ assert_kind_of Bird, parrot
+ assert !parrot.persisted?
+ assert parrot.valid?
+ assert parrot.new_record?
+ assert_equal 'green', parrot.color
+ assert_equal 'parrot', parrot.name
+ end
+
def test_explicit_create_scope
hens = Bird.where(:name => 'hen')
assert_equal 'hen', hens.new.name
@@ -911,11 +1056,6 @@ class RelationTest < ActiveRecord::TestCase
assert_equal 'zyke', FastCar.order_using_old_style.limit(1).first.name
end
- def test_order_with_function_and_last
- authors = Author.scoped
- assert_equal authors(:bob), authors.order( "id asc, MAX( organization_id, owned_essay_id)" ).last
- end
-
def test_order_using_scoping
car1 = CoolCar.order('id DESC').scoping do
CoolCar.find(:first, :order => 'id asc')
@@ -970,4 +1110,58 @@ class RelationTest < ActiveRecord::TestCase
def test_ordering_with_extra_spaces
assert_equal authors(:david), Author.order('id DESC , name DESC').last
end
+
+ def test_update_all_with_joins
+ comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id)
+ count = comments.count
+
+ assert_equal count, comments.update_all(:post_id => posts(:thinking).id)
+ assert_equal posts(:thinking), comments(:greetings).post
+ end
+
+ def test_update_all_with_joins_and_limit
+ comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id).limit(1)
+ assert_equal 1, comments.update_all(:post_id => posts(:thinking).id)
+ end
+
+ def test_update_all_with_joins_and_limit_and_order
+ comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id).order('comments.id').limit(1)
+ assert_equal 1, comments.update_all(:post_id => posts(:thinking).id)
+ assert_equal posts(:thinking), comments(:greetings).post
+ assert_equal posts(:welcome), comments(:more_greetings).post
+ end
+
+ def test_update_all_with_joins_and_offset
+ all_comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id)
+ count = all_comments.count
+ comments = all_comments.offset(1)
+
+ assert_equal count - 1, comments.update_all(:post_id => posts(:thinking).id)
+ end
+
+ def test_update_all_with_joins_and_offset_and_order
+ all_comments = Comment.joins(:post).where('posts.id' => posts(:welcome).id).order('posts.id', 'comments.id')
+ count = all_comments.count
+ comments = all_comments.offset(1)
+
+ assert_equal count - 1, comments.update_all(:post_id => posts(:thinking).id)
+ assert_equal posts(:thinking), comments(:more_greetings).post
+ assert_equal posts(:welcome), comments(:greetings).post
+ end
+
+ def test_uniq
+ tag1 = Tag.create(:name => 'Foo')
+ tag2 = Tag.create(:name => 'Foo')
+
+ query = Tag.select(:name).where(:id => [tag1.id, tag2.id])
+
+ assert_equal ['Foo', 'Foo'], query.map(&:name)
+ assert_sql(/DISTINCT/) do
+ assert_equal ['Foo'], query.uniq.map(&:name)
+ end
+ assert_sql(/DISTINCT/) do
+ assert_equal ['Foo'], query.uniq(true).map(&:name)
+ end
+ assert_equal ['Foo', 'Foo'], query.uniq(true).uniq(false).map(&:name)
+ end
end
diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb
index 4adecf8e83..5c3a78688e 100644
--- a/activerecord/test/cases/schema_dumper_test.rb
+++ b/activerecord/test/cases/schema_dumper_test.rb
@@ -1,13 +1,22 @@
require "cases/helper"
-require 'stringio'
class SchemaDumperTest < ActiveRecord::TestCase
+ def setup
+ @stream = StringIO.new
+ end
+
def standard_dump
- stream = StringIO.new
+ @stream = StringIO.new
ActiveRecord::SchemaDumper.ignore_tables = []
- ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
- stream.string
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, @stream)
+ @stream.string
+ end
+
+ if "string".encoding_aware?
+ def test_magic_comment
+ assert_match "# encoding: #{@stream.external_encoding.name}", standard_dump
+ end
end
def test_schema_dump
@@ -229,4 +238,9 @@ class SchemaDumperTest < ActiveRecord::TestCase
assert_match %r(:id => false), match[1], "no table id not preserved"
assert_match %r{t.string[[:space:]]+"id",[[:space:]]+:null => false$}, match[2], "non-primary key id column not preserved"
end
+
+ def test_schema_dump_keeps_id_false_when_id_is_false_and_unique_not_null_column_added
+ output = standard_dump
+ assert_match %r{create_table "subscribers", :id => false}, output
+ end
end
diff --git a/activerecord/test/cases/serialization_test.rb b/activerecord/test/cases/serialization_test.rb
index 382d659289..61b04b3e37 100644
--- a/activerecord/test/cases/serialization_test.rb
+++ b/activerecord/test/cases/serialization_test.rb
@@ -7,12 +7,13 @@ class SerializationTest < ActiveRecord::TestCase
def setup
@contact_attributes = {
- :name => 'aaron stack',
- :age => 25,
- :avatar => 'binarydata',
- :created_at => Time.utc(2006, 8, 1),
- :awesome => false,
- :preferences => { :gem => '<strong>ruby</strong>' }
+ :name => 'aaron stack',
+ :age => 25,
+ :avatar => 'binarydata',
+ :created_at => Time.utc(2006, 8, 1),
+ :awesome => false,
+ :preferences => { :gem => '<strong>ruby</strong>' },
+ :alternative_id => nil
}
end
diff --git a/activerecord/test/cases/session_store/session_test.rb b/activerecord/test/cases/session_store/session_test.rb
index 669c0b7b4d..258cee7aba 100644
--- a/activerecord/test/cases/session_store/session_test.rb
+++ b/activerecord/test/cases/session_store/session_test.rb
@@ -36,6 +36,7 @@ module ActiveRecord
end
def test_find_by_sess_id_compat
+ Session.reset_column_information
klass = Class.new(Session) do
def self.session_id_column
'sessid'
@@ -53,6 +54,7 @@ module ActiveRecord
assert_equal session.sessid, found.session_id
ensure
klass.drop_table!
+ Session.reset_column_information
end
def test_find_by_session_id
diff --git a/activerecord/test/cases/store_test.rb b/activerecord/test/cases/store_test.rb
new file mode 100644
index 0000000000..5a3f9a9711
--- /dev/null
+++ b/activerecord/test/cases/store_test.rb
@@ -0,0 +1,34 @@
+require 'cases/helper'
+require 'models/admin'
+require 'models/admin/user'
+
+class StoreTest < ActiveRecord::TestCase
+ setup do
+ @john = Admin::User.create(:name => 'John Doe', :color => 'black')
+ end
+
+ test "reading store attributes through accessors" do
+ assert_equal 'black', @john.color
+ assert_nil @john.homepage
+ end
+
+ test "writing store attributes through accessors" do
+ @john.color = 'red'
+ @john.homepage = '37signals.com'
+
+ assert_equal 'red', @john.color
+ assert_equal '37signals.com', @john.homepage
+ end
+
+ test "accessing attributes not exposed by accessors" do
+ @john.settings[:icecream] = 'graeters'
+ @john.save
+
+ assert_equal 'graeters', @john.reload.settings[:icecream]
+ end
+
+ test "updating the store will mark it as changed" do
+ @john.color = 'red'
+ assert @john.settings_changed?
+ end
+end
diff --git a/activerecord/test/cases/timestamp_test.rb b/activerecord/test/cases/timestamp_test.rb
index 4445a12e1d..447aa29ffe 100644
--- a/activerecord/test/cases/timestamp_test.rb
+++ b/activerecord/test/cases/timestamp_test.rb
@@ -60,6 +60,16 @@ class TimestampTest < ActiveRecord::TestCase
Developer.record_timestamps = true
end
+ def test_saving_when_instance_record_timestamps_is_false_doesnt_update_its_timestamp
+ @developer.record_timestamps = false
+ assert Developer.record_timestamps
+
+ @developer.name = "John Smith"
+ @developer.save!
+
+ assert_equal @previously_updated_at, @developer.updated_at
+ end
+
def test_touching_an_attribute_updates_timestamp
previously_created_at = @developer.created_at
@developer.touch(:created_at)
diff --git a/activerecord/test/cases/transaction_callbacks_test.rb b/activerecord/test/cases/transaction_callbacks_test.rb
index 85f222bca2..f8b3e01a49 100644
--- a/activerecord/test/cases/transaction_callbacks_test.rb
+++ b/activerecord/test/cases/transaction_callbacks_test.rb
@@ -6,7 +6,7 @@ class TransactionCallbacksTest < ActiveRecord::TestCase
fixtures :topics
class TopicWithCallbacks < ActiveRecord::Base
- set_table_name :topics
+ self.table_name = :topics
after_commit{|record| record.send(:do_after_commit, nil)}
after_commit(:on => :create){|record| record.send(:do_after_commit, :create)}
@@ -252,7 +252,7 @@ class TransactionObserverCallbacksTest < ActiveRecord::TestCase
fixtures :topics
class TopicWithObserverAttached < ActiveRecord::Base
- set_table_name :topics
+ self.table_name = :topics
def history
@history ||= []
end
diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb
index 110a18772f..203dd054f1 100644
--- a/activerecord/test/cases/transactions_test.rb
+++ b/activerecord/test/cases/transactions_test.rb
@@ -563,6 +563,7 @@ if current_adapter?(:PostgreSQLAdapter)
topic.approved = !topic.approved?
topic.save!
end
+ Topic.connection.close
end
end
@@ -598,6 +599,7 @@ if current_adapter?(:PostgreSQLAdapter)
dev = Developer.find(1)
assert_equal original_salary, dev.salary
end
+ Developer.connection.close
end
end
@@ -610,6 +612,7 @@ if current_adapter?(:PostgreSQLAdapter)
assert_equal original_salary, Developer.find(1).salary
end
end
+ Developer.connection.close
end
threads.each { |t| t.join }
diff --git a/activerecord/test/cases/unconnected_test.rb b/activerecord/test/cases/unconnected_test.rb
index f85fb4e5da..e82ca3f93d 100644
--- a/activerecord/test/cases/unconnected_test.rb
+++ b/activerecord/test/cases/unconnected_test.rb
@@ -4,7 +4,7 @@ class TestRecord < ActiveRecord::Base
end
class TestUnconnectedAdapter < ActiveRecord::TestCase
- self.use_transactional_fixtures = false unless supports_savepoints?
+ self.use_transactional_fixtures = false
def setup
@underlying = ActiveRecord::Base.connection
diff --git a/activerecord/test/cases/validations_test.rb b/activerecord/test/cases/validations_test.rb
index c3e494866b..e575a98170 100644
--- a/activerecord/test/cases/validations_test.rb
+++ b/activerecord/test/cases/validations_test.rb
@@ -8,7 +8,7 @@ require 'models/parrot'
require 'models/company'
class ProtectedPerson < ActiveRecord::Base
- set_table_name 'people'
+ self.table_name = 'people'
attr_accessor :addon
attr_protected :first_name
end
diff --git a/activerecord/test/cases/yaml_serialization_test.rb b/activerecord/test/cases/yaml_serialization_test.rb
index 0b54c309d1..5a38f2c6ee 100644
--- a/activerecord/test/cases/yaml_serialization_test.rb
+++ b/activerecord/test/cases/yaml_serialization_test.rb
@@ -18,6 +18,11 @@ class YamlSerializationTest < ActiveRecord::TestCase
assert_equal topic, t
end
+ def test_roundtrip_serialized_column
+ topic = Topic.new(:content => {:omg=>:lol})
+ assert_equal({:omg=>:lol}, YAML.load(YAML.dump(topic)).content)
+ end
+
def test_encode_with_coder
topic = Topic.first
coder = {}
diff --git a/activerecord/test/config.example.yml b/activerecord/test/config.example.yml
index 8c1a45430e..f450efd839 100644
--- a/activerecord/test/config.example.yml
+++ b/activerecord/test/config.example.yml
@@ -37,11 +37,13 @@ connections:
db2:
arunit:
+ adapter: ibm_db
host: localhost
username: arunit
password: arunit
database: arunit
arunit2:
+ adapter: ibm_db
host: localhost
username: arunit
password: arunit
diff --git a/activerecord/test/fixtures/pirates.yml b/activerecord/test/fixtures/pirates.yml
index abb91101da..6004f390a4 100644
--- a/activerecord/test/fixtures/pirates.yml
+++ b/activerecord/test/fixtures/pirates.yml
@@ -5,5 +5,5 @@ blackbeard:
redbeard:
catchphrase: "Avast!"
parrot: louis
- created_on: <%= 2.weeks.ago.to_s(:db) %>
- updated_on: <%= 2.weeks.ago.to_s(:db) %>
+ created_on: "<%= 2.weeks.ago.to_s(:db) %>"
+ updated_on: "<%= 2.weeks.ago.to_s(:db) %>"
diff --git a/activerecord/test/fixtures/tasks.yml b/activerecord/test/fixtures/tasks.yml
index 01c95b3a4c..402ca85faf 100644
--- a/activerecord/test/fixtures/tasks.yml
+++ b/activerecord/test/fixtures/tasks.yml
@@ -1,4 +1,4 @@
-# Read about fixtures at http://api.rubyonrails.org/classes/Fixtures.html
+# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html
first_task:
id: 1
starting: 2005-03-30t06:30:00.00+01:00
diff --git a/activerecord/test/models/admin/user.rb b/activerecord/test/models/admin/user.rb
index 74bb21551e..c12c88e195 100644
--- a/activerecord/test/models/admin/user.rb
+++ b/activerecord/test/models/admin/user.rb
@@ -1,3 +1,4 @@
class Admin::User < ActiveRecord::Base
belongs_to :account
-end \ No newline at end of file
+ store :settings, :accessors => [ :color, :homepage ]
+end
diff --git a/activerecord/test/models/author.rb b/activerecord/test/models/author.rb
index 23db5650d4..bfadfd9d75 100644
--- a/activerecord/test/models/author.rb
+++ b/activerecord/test/models/author.rb
@@ -128,7 +128,6 @@ class Author < ActiveRecord::Base
belongs_to :author_address, :dependent => :destroy
belongs_to :author_address_extra, :dependent => :delete, :class_name => "AuthorAddress"
- has_many :post_categories, :through => :posts, :source => :categories
has_many :category_post_comments, :through => :categories, :source => :post_comments
has_many :misc_posts, :class_name => 'Post',
diff --git a/activerecord/test/models/car.rb b/activerecord/test/models/car.rb
index 76f20b1061..b9c2e8ec9a 100644
--- a/activerecord/test/models/car.rb
+++ b/activerecord/test/models/car.rb
@@ -8,7 +8,7 @@ class Car < ActiveRecord::Base
has_one :frickinawesome_bulb, :class_name => "Bulb", :conditions => { :frickinawesome => true }
has_many :tyres
- has_many :engines
+ has_many :engines, :dependent => :destroy
has_many :wheels, :as => :wheelable
scope :incl_tyres, includes(:tyres)
diff --git a/activerecord/test/models/company.rb b/activerecord/test/models/company.rb
index c1f7a4171a..fe9c465c81 100644
--- a/activerecord/test/models/company.rb
+++ b/activerecord/test/models/company.rb
@@ -4,7 +4,7 @@ end
class Company < AbstractCompany
attr_protected :rating
- set_sequence_name :companies_nonstd_seq
+ self.sequence_name = :companies_nonstd_seq
validates_presence_of :name
@@ -42,6 +42,7 @@ class Firm < Company
:before_remove => :log_before_remove,
:after_remove => :log_after_remove
has_many :unsorted_clients, :class_name => "Client"
+ has_many :unsorted_clients_with_symbol, :class_name => :Client
has_many :clients_sorted_desc, :class_name => "Client", :order => "id DESC"
has_many :clients_of_firm, :foreign_key => "client_of", :class_name => "Client", :order => "id"
has_many :unvalidated_clients_of_firm, :foreign_key => "client_of", :class_name => "Client", :validate => false
diff --git a/activerecord/test/models/contact.rb b/activerecord/test/models/contact.rb
index e081eee661..3d15c7fbed 100644
--- a/activerecord/test/models/contact.rb
+++ b/activerecord/test/models/contact.rb
@@ -11,12 +11,13 @@ class Contact < ActiveRecord::Base
connection.merge_column('contacts', name, sql_type, options)
end
- column :name, :string
- column :age, :integer
- column :avatar, :binary
- column :created_at, :datetime
- column :awesome, :boolean
- column :preferences, :string
+ column :name, :string
+ column :age, :integer
+ column :avatar, :binary
+ column :created_at, :datetime
+ column :awesome, :boolean
+ column :preferences, :string
+ column :alternative_id, :integer
serialize :preferences
diff --git a/activerecord/test/models/country.rb b/activerecord/test/models/country.rb
index 15e3a1de0b..7db9a4e731 100644
--- a/activerecord/test/models/country.rb
+++ b/activerecord/test/models/country.rb
@@ -1,6 +1,6 @@
class Country < ActiveRecord::Base
- set_primary_key :country_id
+ self.primary_key = :country_id
has_and_belongs_to_many :treaties
diff --git a/activerecord/test/models/dashboard.rb b/activerecord/test/models/dashboard.rb
index a8a25834b1..1b3b54545f 100644
--- a/activerecord/test/models/dashboard.rb
+++ b/activerecord/test/models/dashboard.rb
@@ -1,3 +1,3 @@
class Dashboard < ActiveRecord::Base
- set_primary_key :dashboard_id
-end \ No newline at end of file
+ self.primary_key = :dashboard_id
+end
diff --git a/activerecord/test/models/developer.rb b/activerecord/test/models/developer.rb
index f182a7fa97..4dc9fff9fd 100644
--- a/activerecord/test/models/developer.rb
+++ b/activerecord/test/models/developer.rb
@@ -227,3 +227,12 @@ class EagerDeveloperWithCallableDefaultScope < ActiveRecord::Base
default_scope OpenStruct.new(:call => includes(:projects))
end
+
+class ThreadsafeDeveloper < ActiveRecord::Base
+ self.table_name = 'developers'
+
+ def self.default_scope
+ sleep 0.05 if Thread.current[:long_default_scope]
+ limit(1)
+ end
+end
diff --git a/activerecord/test/models/joke.rb b/activerecord/test/models/joke.rb
index d7f01e59e6..edda4655dc 100644
--- a/activerecord/test/models/joke.rb
+++ b/activerecord/test/models/joke.rb
@@ -1,7 +1,7 @@
class Joke < ActiveRecord::Base
- set_table_name 'funny_jokes'
+ self.table_name = 'funny_jokes'
end
class GoodJoke < ActiveRecord::Base
- set_table_name 'funny_jokes'
+ self.table_name = 'funny_jokes'
end
diff --git a/activerecord/test/models/keyboard.rb b/activerecord/test/models/keyboard.rb
index 32a4a7fad0..39347e274e 100644
--- a/activerecord/test/models/keyboard.rb
+++ b/activerecord/test/models/keyboard.rb
@@ -1,3 +1,3 @@
class Keyboard < ActiveRecord::Base
- set_primary_key 'key_number'
+ self.primary_key = 'key_number'
end
diff --git a/activerecord/test/models/legacy_thing.rb b/activerecord/test/models/legacy_thing.rb
index eaeb642d12..eead181a0e 100644
--- a/activerecord/test/models/legacy_thing.rb
+++ b/activerecord/test/models/legacy_thing.rb
@@ -1,3 +1,3 @@
class LegacyThing < ActiveRecord::Base
- set_locking_column :version
+ self.locking_column = :version
end
diff --git a/activerecord/test/models/liquid.rb b/activerecord/test/models/liquid.rb
index b96c054f6c..3fcd5e4b69 100644
--- a/activerecord/test/models/liquid.rb
+++ b/activerecord/test/models/liquid.rb
@@ -1,5 +1,5 @@
class Liquid < ActiveRecord::Base
- set_table_name :liquid
+ self.table_name = :liquid
has_many :molecules, :uniq => true
end
diff --git a/activerecord/test/models/minivan.rb b/activerecord/test/models/minivan.rb
index 830cdb5796..4fe79720ad 100644
--- a/activerecord/test/models/minivan.rb
+++ b/activerecord/test/models/minivan.rb
@@ -1,5 +1,5 @@
class Minivan < ActiveRecord::Base
- set_primary_key :minivan_id
+ self.primary_key = :minivan_id
belongs_to :speedometer
has_one :dashboard, :through => :speedometer
diff --git a/activerecord/test/models/mixed_case_monkey.rb b/activerecord/test/models/mixed_case_monkey.rb
index 853f2682b3..763baefd91 100644
--- a/activerecord/test/models/mixed_case_monkey.rb
+++ b/activerecord/test/models/mixed_case_monkey.rb
@@ -1,3 +1,3 @@
class MixedCaseMonkey < ActiveRecord::Base
- set_primary_key 'monkeyID'
+ self.primary_key = 'monkeyID'
end
diff --git a/activerecord/test/models/owner.rb b/activerecord/test/models/owner.rb
index 5760b991ec..fea55f4535 100644
--- a/activerecord/test/models/owner.rb
+++ b/activerecord/test/models/owner.rb
@@ -1,5 +1,5 @@
class Owner < ActiveRecord::Base
- set_primary_key :owner_id
+ self.primary_key = :owner_id
has_many :pets
has_many :toys, :through => :pets
end
diff --git a/activerecord/test/models/parrot.rb b/activerecord/test/models/parrot.rb
index 737ef9131b..c4ee2bd19d 100644
--- a/activerecord/test/models/parrot.rb
+++ b/activerecord/test/models/parrot.rb
@@ -1,5 +1,6 @@
class Parrot < ActiveRecord::Base
- set_inheritance_column :parrot_sti_class
+ self.inheritance_column = :parrot_sti_class
+
has_and_belongs_to_many :pirates
has_and_belongs_to_many :treasures
has_many :loots, :as => :looter
diff --git a/activerecord/test/models/pet.rb b/activerecord/test/models/pet.rb
index 113826756a..3cd5bceed5 100644
--- a/activerecord/test/models/pet.rb
+++ b/activerecord/test/models/pet.rb
@@ -2,7 +2,7 @@ class Pet < ActiveRecord::Base
attr_accessor :current_user
- set_primary_key :pet_id
+ self.primary_key = :pet_id
belongs_to :owner, :touch => true
has_many :toys
diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb
index affa37b02d..137cee3752 100644
--- a/activerecord/test/models/post.rb
+++ b/activerecord/test/models/post.rb
@@ -24,6 +24,10 @@ class Post < ActiveRecord::Base
belongs_to :author_with_posts, :class_name => "Author", :foreign_key => :author_id, :include => :posts
belongs_to :author_with_address, :class_name => "Author", :foreign_key => :author_id, :include => :author_address
+ def first_comment
+ super.body
+ end
+ has_one :first_comment, :class_name => 'Comment', :order => 'id ASC'
has_one :last_comment, :class_name => 'Comment', :order => 'id desc'
scope :with_special_comments, :joins => :comments, :conditions => {:comments => {:type => 'SpecialComment'} }
@@ -171,4 +175,14 @@ class PostWithDefaultInclude < ActiveRecord::Base
self.table_name = 'posts'
default_scope includes(:comments)
has_many :comments, :foreign_key => :post_id
+end
+
+class PostWithDefaultScope < ActiveRecord::Base
+ self.table_name = 'posts'
+ default_scope :order => :title
+end
+
+class SpecialPostWithDefaultScope < ActiveRecord::Base
+ self.table_name = 'posts'
+ default_scope where(:id => [1, 5,6])
end \ No newline at end of file
diff --git a/activerecord/test/models/speedometer.rb b/activerecord/test/models/speedometer.rb
index 94743eff8e..0a7d38d8ec 100644
--- a/activerecord/test/models/speedometer.rb
+++ b/activerecord/test/models/speedometer.rb
@@ -1,4 +1,4 @@
class Speedometer < ActiveRecord::Base
- set_primary_key :speedometer_id
+ self.primary_key = :speedometer_id
belongs_to :dashboard
-end \ No newline at end of file
+end
diff --git a/activerecord/test/models/string_key_object.rb b/activerecord/test/models/string_key_object.rb
index f8d4c6e0e4..f084ec1bdc 100644
--- a/activerecord/test/models/string_key_object.rb
+++ b/activerecord/test/models/string_key_object.rb
@@ -1,3 +1,3 @@
class StringKeyObject < ActiveRecord::Base
- set_primary_key :id
+ self.primary_key = :id
end
diff --git a/activerecord/test/models/subscriber.rb b/activerecord/test/models/subscriber.rb
index 5b78014e6f..76e85a0cd3 100644
--- a/activerecord/test/models/subscriber.rb
+++ b/activerecord/test/models/subscriber.rb
@@ -1,5 +1,5 @@
class Subscriber < ActiveRecord::Base
- set_primary_key 'nick'
+ self.primary_key = 'nick'
has_many :subscriptions
has_many :books, :through => :subscriptions
end
diff --git a/activerecord/test/models/topic.rb b/activerecord/test/models/topic.rb
index 6440dbe8ab..fe424e61b2 100644
--- a/activerecord/test/models/topic.rb
+++ b/activerecord/test/models/topic.rb
@@ -78,11 +78,12 @@ class Topic < ActiveRecord::Base
after_initialize :set_email_address
+ def approved=(val)
+ @custom_approved = val
+ write_attribute(:approved, val)
+ end
+
protected
- def approved=(val)
- @custom_approved = val
- write_attribute(:approved, val)
- end
def default_written_on
self.written_on = Time.now unless attribute_present?("written_on")
diff --git a/activerecord/test/models/toy.rb b/activerecord/test/models/toy.rb
index 79a88db0da..0377e50011 100644
--- a/activerecord/test/models/toy.rb
+++ b/activerecord/test/models/toy.rb
@@ -1,4 +1,6 @@
class Toy < ActiveRecord::Base
- set_primary_key :toy_id
+ self.primary_key = :toy_id
belongs_to :pet
+
+ scope :with_pet, joins(:pet)
end
diff --git a/activerecord/test/models/treaty.rb b/activerecord/test/models/treaty.rb
index b46537f0d2..41fd1350f3 100644
--- a/activerecord/test/models/treaty.rb
+++ b/activerecord/test/models/treaty.rb
@@ -1,6 +1,6 @@
class Treaty < ActiveRecord::Base
- set_primary_key :treaty_id
+ self.primary_key = :treaty_id
has_and_belongs_to_many :countries
diff --git a/activerecord/test/models/warehouse_thing.rb b/activerecord/test/models/warehouse_thing.rb
index 6ace1183cc..f20bd1a245 100644
--- a/activerecord/test/models/warehouse_thing.rb
+++ b/activerecord/test/models/warehouse_thing.rb
@@ -1,5 +1,5 @@
class WarehouseThing < ActiveRecord::Base
- set_table_name "warehouse-things"
+ self.table_name = "warehouse-things"
validates_uniqueness_of :value
-end \ No newline at end of file
+end
diff --git a/activerecord/test/schema/mysql2_specific_schema.rb b/activerecord/test/schema/mysql2_specific_schema.rb
index c78d99f4af..ab2c7ccc10 100644
--- a/activerecord/test/schema/mysql2_specific_schema.rb
+++ b/activerecord/test/schema/mysql2_specific_schema.rb
@@ -21,4 +21,15 @@ BEGIN
END
SQL
-end
+ ActiveRecord::Base.connection.execute <<-SQL
+DROP TABLE IF EXISTS collation_tests;
+SQL
+
+ ActiveRecord::Base.connection.execute <<-SQL
+CREATE TABLE collation_tests (
+ string_cs_column VARCHAR(1) COLLATE utf8_bin,
+ string_ci_column VARCHAR(1) COLLATE utf8_general_ci
+) CHARACTER SET utf8 COLLATE utf8_general_ci
+SQL
+
+end \ No newline at end of file
diff --git a/activerecord/test/schema/mysql_specific_schema.rb b/activerecord/test/schema/mysql_specific_schema.rb
index 30e1c5a167..a0adfe3752 100644
--- a/activerecord/test/schema/mysql_specific_schema.rb
+++ b/activerecord/test/schema/mysql_specific_schema.rb
@@ -32,4 +32,15 @@ BEGIN
END
SQL
+ ActiveRecord::Base.connection.execute <<-SQL
+DROP TABLE IF EXISTS collation_tests;
+SQL
+
+ ActiveRecord::Base.connection.execute <<-SQL
+CREATE TABLE collation_tests (
+ string_cs_column VARCHAR(1) COLLATE utf8_bin,
+ string_ci_column VARCHAR(1) COLLATE utf8_general_ci
+) CHARACTER SET utf8 COLLATE utf8_general_ci
+SQL
+
end
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index 64e0452100..bb08f5c181 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -37,6 +37,7 @@ ActiveRecord::Schema.define do
create_table :admin_users, :force => true do |t|
t.string :name
+ t.text :settings
t.references :account
end
@@ -47,6 +48,7 @@ ActiveRecord::Schema.define do
create_table :audit_logs, :force => true do |t|
t.column :message, :string, :null=>false
t.column :developer_id, :integer, :null=>false
+ t.integer :unvalidated_developer_id
end
create_table :authors, :force => true do |t|
@@ -156,6 +158,7 @@ ActiveRecord::Schema.define do
t.string :type
t.integer :taggings_count, :default => 0
t.integer :children_count, :default => 0
+ t.integer :parent_id
end
create_table :companies, :force => true do |t|
@@ -461,6 +464,7 @@ ActiveRecord::Schema.define do
create_table :pirates, :force => true do |t|
t.column :catchphrase, :string
t.column :parrot_id, :integer
+ t.integer :non_validated_parrot_id
t.column :created_on, :datetime
t.column :updated_on, :datetime
end
@@ -529,6 +533,7 @@ ActiveRecord::Schema.define do
create_table :ships, :force => true do |t|
t.string :name
t.integer :pirate_id
+ t.integer :update_only_pirate_id
t.datetime :created_at
t.datetime :created_on
t.datetime :updated_at
@@ -663,7 +668,9 @@ ActiveRecord::Schema.define do
t.string :description
t.integer :man_id
t.integer :polymorphic_man_id
- t.string :polymorphic_man_type
+ t.string :polymorphic_man_type
+ t.integer :horrible_polymorphic_man_id
+ t.string :horrible_polymorphic_man_type
end
create_table :interests, :force => true do |t|