aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/test')
-rw-r--r--activerecord/test/cases/associations/extension_test.rb7
-rw-r--r--activerecord/test/cases/batches_test.rb15
-rw-r--r--activerecord/test/cases/callbacks_test.rb49
-rw-r--r--activerecord/test/cases/dirty_test.rb25
-rw-r--r--activerecord/test/cases/hot_compatibility_test.rb54
-rw-r--r--activerecord/test/cases/tasks/mysql_rake_test.rb46
-rw-r--r--activerecord/test/cases/transaction_isolation_test.rb6
-rw-r--r--activerecord/test/models/post.rb5
8 files changed, 176 insertions, 31 deletions
diff --git a/activerecord/test/cases/associations/extension_test.rb b/activerecord/test/cases/associations/extension_test.rb
index bd5a426ca8..da767a2a7e 100644
--- a/activerecord/test/cases/associations/extension_test.rb
+++ b/activerecord/test/cases/associations/extension_test.rb
@@ -40,9 +40,12 @@ class AssociationsExtensionsTest < ActiveRecord::TestCase
assert_equal projects(:action_controller), david.projects.find_most_recent
marshalled = Marshal.dump(david)
- david = Marshal.load(marshalled)
- assert_equal projects(:action_controller), david.projects.find_most_recent
+ # Marshaling an association shouldn't make it unusable by wiping its reflection.
+ assert_not_nil david.association(:projects).reflection
+
+ david_too = Marshal.load(marshalled)
+ assert_equal projects(:action_controller), david_too.projects.find_most_recent
end
def test_marshalling_named_extensions
diff --git a/activerecord/test/cases/batches_test.rb b/activerecord/test/cases/batches_test.rb
index 3b4ff83725..12d5245fbd 100644
--- a/activerecord/test/cases/batches_test.rb
+++ b/activerecord/test/cases/batches_test.rb
@@ -1,8 +1,9 @@
require 'cases/helper'
require 'models/post'
+require 'models/subscriber'
class EachTest < ActiveRecord::TestCase
- fixtures :posts
+ fixtures :posts, :subscribers
def setup
@posts = Post.order("id asc")
@@ -125,14 +126,14 @@ class EachTest < ActiveRecord::TestCase
end
def test_find_in_batches_should_use_any_column_as_primary_key
- title_order_posts = Post.order('title asc')
- start_title = title_order_posts.first.title
+ nick_order_subscribers = Subscriber.order('nick asc')
+ start_nick = nick_order_subscribers.second.nick
- posts = []
- PostWithTitlePrimaryKey.find_in_batches(:batch_size => 1, :start => start_title) do |batch|
- posts.concat(batch)
+ subscribers = []
+ Subscriber.find_in_batches(:batch_size => 1, :start => start_nick) do |batch|
+ subscribers.concat(batch)
end
- assert_equal title_order_posts.map(&:id), posts.map(&:id)
+ assert_equal nick_order_subscribers[1..-1].map(&:id), subscribers.map(&:id)
end
end
diff --git a/activerecord/test/cases/callbacks_test.rb b/activerecord/test/cases/callbacks_test.rb
index deeef3a3fd..7457bafd4e 100644
--- a/activerecord/test/cases/callbacks_test.rb
+++ b/activerecord/test/cases/callbacks_test.rb
@@ -137,6 +137,32 @@ class OnCallbacksDeveloper < ActiveRecord::Base
end
end
+class ContextualCallbacksDeveloper < ActiveRecord::Base
+ self.table_name = 'developers'
+
+ before_validation { history << :before_validation }
+ before_validation :before_validation_on_create_and_update, :on => [ :create, :update ]
+
+ validate do
+ history << :validate
+ end
+
+ after_validation { history << :after_validation }
+ after_validation :after_validation_on_create_and_update, :on => [ :create, :update ]
+
+ def before_validation_on_create_and_update
+ history << "before_validation_on_#{self.validation_context}".to_sym
+ end
+
+ def after_validation_on_create_and_update
+ history << "after_validation_on_#{self.validation_context}".to_sym
+ end
+
+ def history
+ @history ||= []
+ end
+end
+
class CallbackCancellationDeveloper < ActiveRecord::Base
self.table_name = 'developers'
@@ -285,6 +311,17 @@ class CallbacksTest < ActiveRecord::TestCase
], david.history
end
+ def test_validate_on_contextual_create
+ david = ContextualCallbacksDeveloper.create('name' => 'David', 'salary' => 1000000)
+ assert_equal [
+ :before_validation,
+ :before_validation_on_create,
+ :validate,
+ :after_validation,
+ :after_validation_on_create
+ ], david.history
+ end
+
def test_update
david = CallbackDeveloper.find(1)
david.save
@@ -344,6 +381,18 @@ class CallbacksTest < ActiveRecord::TestCase
], david.history
end
+ def test_validate_on_contextual_update
+ david = ContextualCallbacksDeveloper.find(1)
+ david.save
+ assert_equal [
+ :before_validation,
+ :before_validation_on_update,
+ :validate,
+ :after_validation,
+ :after_validation_on_update
+ ], david.history
+ end
+
def test_destroy
david = CallbackDeveloper.find(1)
david.destroy
diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb
index 9a2a5a4e3c..75a52544d3 100644
--- a/activerecord/test/cases/dirty_test.rb
+++ b/activerecord/test/cases/dirty_test.rb
@@ -3,6 +3,7 @@ require 'models/topic' # For booleans
require 'models/pirate' # For timestamps
require 'models/parrot'
require 'models/person' # For optimistic locking
+require 'models/aircraft'
class Pirate # Just reopening it, not defining it
attr_accessor :detected_changes_in_after_update # Boolean for if changes are detected
@@ -550,6 +551,30 @@ class DirtyTest < ActiveRecord::TestCase
end
end
+ test "partial insert" do
+ with_partial_updates Person do
+ jon = nil
+ assert_sql(/first_name/) do
+ jon = Person.create! first_name: 'Jon'
+ end
+
+ assert ActiveRecord::SQLCounter.log_all.none? { |sql| sql =~ /followers_count/ }
+
+ jon.reload
+ assert_equal 'Jon', jon.first_name
+ assert_equal 0, jon.followers_count
+ assert_not_nil jon.id
+ end
+ end
+
+ test "partial insert with empty values" do
+ with_partial_updates Aircraft do
+ a = Aircraft.create!
+ a.reload
+ assert_not_nil a.id
+ end
+ end
+
private
def with_partial_updates(klass, on = true)
old = klass.partial_updates?
diff --git a/activerecord/test/cases/hot_compatibility_test.rb b/activerecord/test/cases/hot_compatibility_test.rb
new file mode 100644
index 0000000000..96e581ab4c
--- /dev/null
+++ b/activerecord/test/cases/hot_compatibility_test.rb
@@ -0,0 +1,54 @@
+require 'cases/helper'
+
+class HotCompatibilityTest < ActiveRecord::TestCase
+ self.use_transactional_fixtures = false
+
+ setup do
+ @klass = Class.new(ActiveRecord::Base) do
+ connection.create_table :hot_compatibilities do |t|
+ t.string :foo
+ t.string :bar
+ end
+
+ def self.name; 'HotCompatibility'; end
+ end
+ end
+
+ teardown do
+ @klass.connection.drop_table :hot_compatibilities
+ end
+
+ test "insert after remove_column" do
+ # warm cache
+ @klass.create!
+
+ # we have 3 columns
+ assert_equal 3, @klass.columns.length
+
+ # remove one of them
+ @klass.connection.remove_column :hot_compatibilities, :bar
+
+ # we still have 3 columns in the cache
+ assert_equal 3, @klass.columns.length
+
+ # but we can successfully create a record so long as we don't
+ # reference the removed column
+ record = @klass.create! foo: 'foo'
+ record.reload
+ assert_equal 'foo', record.foo
+ end
+
+ test "update after remove_column" do
+ record = @klass.create! foo: 'foo'
+ assert_equal 3, @klass.columns.length
+ @klass.connection.remove_column :hot_compatibilities, :bar
+ assert_equal 3, @klass.columns.length
+
+ record.reload
+ assert_equal 'foo', record.foo
+ record.foo = 'bar'
+ record.save!
+ record.reload
+ assert_equal 'bar', record.foo
+ end
+end
diff --git a/activerecord/test/cases/tasks/mysql_rake_test.rb b/activerecord/test/cases/tasks/mysql_rake_test.rb
index 46b97a1274..69a049fcfa 100644
--- a/activerecord/test/cases/tasks/mysql_rake_test.rb
+++ b/activerecord/test/cases/tasks/mysql_rake_test.rb
@@ -20,20 +20,32 @@ module ActiveRecord
ActiveRecord::Tasks::DatabaseTasks.create @configuration
end
- def test_creates_database_with_default_options
+ def test_creates_database_with_default_encoding_and_collation
@connection.expects(:create_database).
- with('my-app-db', {:charset => 'utf8', :collation => 'utf8_unicode_ci'})
+ with('my-app-db', charset: 'utf8', collation: 'utf8_unicode_ci')
ActiveRecord::Tasks::DatabaseTasks.create @configuration
end
- def test_creates_database_with_given_options
+ def test_creates_database_with_given_encoding_and_default_collation
@connection.expects(:create_database).
- with('my-app-db', {:charset => 'latin', :collation => 'latin_ci'})
+ with('my-app-db', charset: 'utf8', collation: 'utf8_unicode_ci')
- ActiveRecord::Tasks::DatabaseTasks.create @configuration.merge(
- 'encoding' => 'latin', 'collation' => 'latin_ci'
- )
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration.merge('encoding' => 'utf8')
+ end
+
+ def test_creates_database_with_given_encoding_and_no_collation
+ @connection.expects(:create_database).
+ with('my-app-db', charset: 'latin1')
+
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration.merge('encoding' => 'latin1')
+ end
+
+ def test_creates_database_with_given_collation_and_no_encoding
+ @connection.expects(:create_database).
+ with('my-app-db', collation: 'latin1_swedish_ci')
+
+ ActiveRecord::Tasks::DatabaseTasks.create @configuration.merge('collation' => 'latin1_swedish_ci')
end
def test_establishes_connection_to_database
@@ -62,8 +74,9 @@ module ActiveRecord
$stdout.stubs(:print).returns(nil)
@error.stubs(:errno).returns(1045)
ActiveRecord::Base.stubs(:connection).returns(@connection)
- ActiveRecord::Base.stubs(:establish_connection).raises(@error).then.
- returns(true)
+ ActiveRecord::Base.stubs(:establish_connection).
+ raises(@error).
+ then.returns(true)
end
def test_root_password_is_requested
@@ -74,12 +87,12 @@ module ActiveRecord
end
def test_connection_established_as_root
- ActiveRecord::Base.expects(:establish_connection).with({
+ ActiveRecord::Base.expects(:establish_connection).with(
'adapter' => 'mysql',
'database' => nil,
'username' => 'root',
'password' => 'secret'
- })
+ )
ActiveRecord::Tasks::DatabaseTasks.create @configuration
end
@@ -99,12 +112,12 @@ module ActiveRecord
def test_connection_established_as_normal_user
ActiveRecord::Base.expects(:establish_connection).returns do
- ActiveRecord::Base.expects(:establish_connection).with({
+ ActiveRecord::Base.expects(:establish_connection).with(
'adapter' => 'mysql',
'database' => 'my-app-db',
'username' => 'pat',
'password' => 'secret'
- })
+ )
raise @error
end
@@ -166,18 +179,17 @@ module ActiveRecord
def test_recreates_database_with_the_default_options
@connection.expects(:recreate_database).
- with('test-db', {:charset => 'utf8', :collation => 'utf8_unicode_ci'})
+ with('test-db', charset: 'utf8', collation: 'utf8_unicode_ci')
ActiveRecord::Tasks::DatabaseTasks.purge @configuration
end
def test_recreates_database_with_the_given_options
@connection.expects(:recreate_database).
- with('test-db', {:charset => 'latin', :collation => 'latin_ci'})
+ with('test-db', charset: 'latin', collation: 'latin1_swedish_ci')
ActiveRecord::Tasks::DatabaseTasks.purge @configuration.merge(
- 'encoding' => 'latin', 'collation' => 'latin_ci'
- )
+ 'encoding' => 'latin', 'collation' => 'latin1_swedish_ci')
end
end
diff --git a/activerecord/test/cases/transaction_isolation_test.rb b/activerecord/test/cases/transaction_isolation_test.rb
index 1e34f93d8f..a396da6645 100644
--- a/activerecord/test/cases/transaction_isolation_test.rb
+++ b/activerecord/test/cases/transaction_isolation_test.rb
@@ -44,6 +44,9 @@ class TransactionIsolationTest < ActiveRecord::TestCase
# specifies what must not happen at a certain level, not what must happen. At
# the read uncommitted level, there is nothing that must not happen.
test "read uncommitted" do
+ unless ActiveRecord::Base.connection.transaction_isolation_levels.include?(:read_uncommitted)
+ skip "database does not support read uncommitted isolation level"
+ end
Tag.transaction(isolation: :read_uncommitted) do
assert_equal 0, Tag.count
Tag2.create
@@ -67,6 +70,9 @@ class TransactionIsolationTest < ActiveRecord::TestCase
# We are testing that a nonrepeatable read does not happen
test "repeatable read" do
+ unless ActiveRecord::Base.connection.transaction_isolation_levels.include?(:repeatable_read)
+ skip "database does not support repeatable read isolation level"
+ end
tag = Tag.create(name: 'jon')
Tag.transaction(isolation: :repeatable_read) do
diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb
index 9858f68c4a..c995f59a15 100644
--- a/activerecord/test/models/post.rb
+++ b/activerecord/test/models/post.rb
@@ -186,8 +186,3 @@ class SpecialPostWithDefaultScope < ActiveRecord::Base
self.table_name = 'posts'
default_scope { where(:id => [1, 5,6]) }
end
-
-class PostWithTitlePrimaryKey < ActiveRecord::Base
- self.table_name = 'posts'
- self.primary_key = :title
-end