aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test
diff options
context:
space:
mode:
authorPratik Naik <pratiknaik@gmail.com>2010-01-17 03:20:30 +0530
committerPratik Naik <pratiknaik@gmail.com>2010-01-17 03:20:30 +0530
commitb04230e3bbf912d60601e9e7b797c4cd43581d51 (patch)
tree97a2f784a2ec2bfae4f960af56a9280dad6f7774 /activerecord/test
parent867829b187969607aa12f2b0457f25da9c204db0 (diff)
parent6e3bee6cf1f0d2684152292db0a8b757249824fd (diff)
downloadrails-b04230e3bbf912d60601e9e7b797c4cd43581d51.tar.gz
rails-b04230e3bbf912d60601e9e7b797c4cd43581d51.tar.bz2
rails-b04230e3bbf912d60601e9e7b797c4cd43581d51.zip
Merge remote branch 'mainstream/master'
Conflicts: actionpack/lib/action_controller/metal/flash.rb
Diffstat (limited to 'activerecord/test')
-rw-r--r--activerecord/test/cases/associations/inner_join_association_test.rb28
-rw-r--r--activerecord/test/cases/autosave_association_test.rb83
-rwxr-xr-xactiverecord/test/cases/base_test.rb5
-rw-r--r--activerecord/test/cases/callbacks_test.rb45
-rw-r--r--activerecord/test/cases/fixtures_test.rb4
-rw-r--r--activerecord/test/cases/helper.rb2
-rw-r--r--activerecord/test/cases/inheritance_test.rb3
-rw-r--r--activerecord/test/cases/method_scoping_test.rb65
-rw-r--r--activerecord/test/cases/modules_test.rb4
-rw-r--r--activerecord/test/cases/multiple_db_test.rb4
-rw-r--r--activerecord/test/cases/nested_attributes_test.rb39
-rw-r--r--activerecord/test/cases/pooled_connections_test.rb15
-rw-r--r--activerecord/test/cases/reflection_test.rb58
-rw-r--r--activerecord/test/cases/relations_test.rb8
-rw-r--r--activerecord/test/cases/subscriber_test.rb51
-rw-r--r--activerecord/test/cases/validations/association_validation_test.rb98
-rw-r--r--activerecord/test/cases/validations/i18n_generate_message_validation_test.rb10
-rw-r--r--activerecord/test/cases/validations/i18n_validation_test.rb99
-rw-r--r--activerecord/test/cases/validations/uniqueness_validation_test.rb65
-rw-r--r--activerecord/test/models/bird.rb6
-rw-r--r--activerecord/test/models/invoice.rb4
-rw-r--r--activerecord/test/models/line_item.rb3
-rw-r--r--activerecord/test/models/parrot.rb6
-rw-r--r--activerecord/test/models/pirate.rb6
-rw-r--r--activerecord/test/models/ship.rb6
-rw-r--r--activerecord/test/schema/schema.rb10
26 files changed, 443 insertions, 284 deletions
diff --git a/activerecord/test/cases/associations/inner_join_association_test.rb b/activerecord/test/cases/associations/inner_join_association_test.rb
index 18a1cd3cd0..43abcae75e 100644
--- a/activerecord/test/cases/associations/inner_join_association_test.rb
+++ b/activerecord/test/cases/associations/inner_join_association_test.rb
@@ -8,39 +8,11 @@ require 'models/categorization'
class InnerJoinAssociationTest < ActiveRecord::TestCase
fixtures :authors, :posts, :comments, :categories, :categories_posts, :categorizations
- def test_construct_finder_sql_creates_inner_joins
- sql = Author.joins(:posts).to_sql
- assert_match /INNER JOIN .?posts.? ON .?posts.?.author_id = authors.id/, sql
- end
-
- def test_construct_finder_sql_cascades_inner_joins
- sql = Author.joins(:posts => :comments).to_sql
- assert_match /INNER JOIN .?posts.? ON .?posts.?.author_id = authors.id/, sql
- assert_match /INNER JOIN .?comments.? ON .?comments.?.post_id = posts.id/, sql
- end
-
- def test_construct_finder_sql_inner_joins_through_associations
- sql = Author.joins(:categorized_posts).to_sql
- assert_match /INNER JOIN .?categorizations.?.*INNER JOIN .?posts.?/, sql
- end
-
- def test_construct_finder_sql_applies_association_conditions
- sql = Author.joins(:categories_like_general).where("TERMINATING_MARKER").to_sql
- assert_match /INNER JOIN .?categories.? ON.*AND.*.?General.?(.|\n)*TERMINATING_MARKER/, sql
- end
-
def test_construct_finder_sql_applies_aliases_tables_on_association_conditions
result = Author.joins(:thinking_posts, :welcome_posts).to_a
assert_equal authors(:david), result.first
end
- def test_construct_finder_sql_unpacks_nested_joins
- sql = Author.joins(:posts => [[:comments]]).to_sql
- assert_no_match /inner join.*inner join.*inner join/i, sql, "only two join clauses should be present"
- assert_match /INNER JOIN .?posts.? ON .?posts.?.author_id = authors.id/, sql
- assert_match /INNER JOIN .?comments.? ON .?comments.?.post_id = .?posts.?.id/, sql
- end
-
def test_construct_finder_sql_ignores_empty_joins_hash
sql = Author.joins({}).to_sql
assert_no_match /JOIN/i, sql
diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb
index cf763d730a..cc36a6dc5b 100644
--- a/activerecord/test/cases/autosave_association_test.rb
+++ b/activerecord/test/cases/autosave_association_test.rb
@@ -3,6 +3,8 @@ require 'models/bird'
require 'models/company'
require 'models/customer'
require 'models/developer'
+require 'models/invoice'
+require 'models/line_item'
require 'models/order'
require 'models/parrot'
require 'models/person'
@@ -699,23 +701,18 @@ class TestDestroyAsPartOfAutosaveAssociation < ActiveRecord::TestCase
define_method("test_should_rollback_destructions_if_an_exception_occurred_while_saving_#{association_name}") do
2.times { |i| @pirate.send(association_name).create!(:name => "#{association_name}_#{i}") }
- before = @pirate.send(association_name).map { |c| c }
+ before = @pirate.send(association_name).map { |c| c.mark_for_destruction ; c }
- # Stub the save method of the first child to destroy and the second to raise an exception
- class << before.first
- def save(*args)
- super
- destroy
- end
- end
+ # Stub the destroy method of the the second child to raise an exception
class << before.last
- def save(*args)
+ def destroy(*args)
super
raise 'Oh noes!'
end
end
assert_raise(RuntimeError) { assert !@pirate.save }
+ assert before.first.frozen? # the first child was indeed destroyed
assert_equal before, @pirate.reload.send(association_name)
end
@@ -797,6 +794,14 @@ class TestAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCase
assert @pirate.errors[:catchphrase].any?
end
+ def test_should_not_ignore_different_error_messages_on_the_same_attribute
+ Ship.validates_format_of :name, :with => /\w/
+ @pirate.ship.name = ""
+ @pirate.catchphrase = nil
+ assert @pirate.invalid?
+ assert_equal ["can't be blank", "is invalid"], @pirate.errors[:"ship.name"]
+ end
+
def test_should_still_allow_to_bypass_validations_on_the_associated_model
@pirate.catchphrase = ''
@pirate.ship.name = ''
@@ -833,6 +838,18 @@ class TestAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCase
end
end
+ def test_should_not_save_and_return_false_if_a_callback_cancelled_saving
+ pirate = Pirate.new(:catchphrase => 'Arr')
+ ship = pirate.build_ship(:name => 'The Vile Insanity')
+ ship.cancel_save_from_callback = true
+
+ assert_no_difference 'Pirate.count' do
+ assert_no_difference 'Ship.count' do
+ assert !pirate.save
+ end
+ end
+ end
+
def test_should_rollback_any_changes_if_an_exception_occurred_while_saving
before = [@pirate.catchphrase, @pirate.ship.name]
@@ -916,6 +933,18 @@ class TestAutosaveAssociationOnABelongsToAssociation < ActiveRecord::TestCase
end
end
+ def test_should_not_save_and_return_false_if_a_callback_cancelled_saving
+ ship = Ship.new(:name => 'The Vile Insanity')
+ pirate = ship.build_pirate(:catchphrase => 'Arr')
+ pirate.cancel_save_from_callback = true
+
+ assert_no_difference 'Ship.count' do
+ assert_no_difference 'Pirate.count' do
+ assert !ship.save
+ end
+ end
+ end
+
def test_should_rollback_any_changes_if_an_exception_occurred_while_saving
before = [@ship.pirate.catchphrase, @ship.name]
@@ -931,7 +960,6 @@ class TestAutosaveAssociationOnABelongsToAssociation < ActiveRecord::TestCase
end
assert_raise(RuntimeError) { assert !@ship.save }
- # TODO: Why does using reload on @ship looses the associated pirate?
assert_equal before, [@ship.pirate.reload.catchphrase, @ship.reload.name]
end
@@ -974,9 +1002,9 @@ module AutosaveAssociationOnACollectionAssociationTests
end
def test_should_default_invalid_error_from_i18n
- I18n.backend.store_translations(:en, :activerecord => { :errors => { :models =>
+ I18n.backend.store_translations(:en, :errors => { :models =>
{ @association_name.to_s.singularize.to_sym => { :blank => "cannot be blank" } }
- }})
+ })
@pirate.send(@association_name).build(:name => '')
@@ -985,9 +1013,7 @@ module AutosaveAssociationOnACollectionAssociationTests
assert_equal ["#{@association_name.to_s.titleize} name cannot be blank"], @pirate.errors.full_messages
assert @pirate.errors[@association_name].empty?
ensure
- I18n.backend.store_translations(:en, :activerecord => { :errors => { :models =>
- { @association_name.to_s.singularize.to_sym => nil }
- }})
+ I18n.backend = I18n::Backend::Simple.new
end
def test_should_merge_errors_on_the_associated_models_onto_the_parent_even_if_it_is_not_valid
@@ -1034,6 +1060,26 @@ module AutosaveAssociationOnACollectionAssociationTests
end
end
+ def test_should_not_save_and_return_false_if_a_callback_cancelled_saving_in_either_create_or_update
+ @pirate.catchphrase = 'Changed'
+ @child_1.name = 'Changed'
+ @child_1.cancel_save_from_callback = true
+
+ assert !@pirate.save
+ assert_equal "Don' botharrr talkin' like one, savvy?", @pirate.reload.catchphrase
+ assert_equal "Posideons Killer", @child_1.reload.name
+
+ new_pirate = Pirate.new(:catchphrase => 'Arr')
+ new_child = new_pirate.send(@association_name).build(:name => 'Grace OMalley')
+ new_child.cancel_save_from_callback = true
+
+ assert_no_difference 'Pirate.count' do
+ assert_no_difference "#{new_child.class.name}.count" do
+ assert !new_pirate.save
+ end
+ end
+ end
+
def test_should_rollback_any_changes_if_an_exception_occurred_while_saving
before = [@pirate.catchphrase, *@pirate.send(@association_name).map(&:name)]
new_names = ['Grace OMalley', 'Privateers Greed']
@@ -1217,3 +1263,10 @@ class TestAutosaveAssociationValidationMethodsGeneration < ActiveRecord::TestCas
assert !@pirate.respond_to?(:validate_associated_records_for_non_validated_parrots)
end
end
+
+class TestAutosaveAssociationWithTouch < ActiveRecord::TestCase
+ def test_autosave_with_touch_should_not_raise_system_stack_error
+ invoice = Invoice.create
+ assert_nothing_raised { invoice.line_items.create(:amount => 10) }
+ end
+end
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index 730d9d8df7..aea6aed8d9 100755
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -992,7 +992,7 @@ class BasicsTest < ActiveRecord::TestCase
end
def test_mass_assignment_protection_against_class_attribute_writers
- [:logger, :configurations, :primary_key_prefix_type, :table_name_prefix, :table_name_suffix, :pluralize_table_names, :colorize_logging,
+ [: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|
assert Task.respond_to?(method)
assert Task.respond_to?("#{method}=")
@@ -2138,8 +2138,11 @@ class BasicsTest < ActiveRecord::TestCase
end
def test_type_name_with_module_should_handle_beginning
+ ActiveRecord::Base.store_full_sti_class = false
assert_equal 'ActiveRecord::Person', ActiveRecord::Base.send(:type_name_with_module, 'Person')
assert_equal '::Person', ActiveRecord::Base.send(:type_name_with_module, '::Person')
+ ensure
+ ActiveRecord::Base.store_full_sti_class = true
end
def test_to_param_should_return_string
diff --git a/activerecord/test/cases/callbacks_test.rb b/activerecord/test/cases/callbacks_test.rb
index 5a084a611e..ff2322ac15 100644
--- a/activerecord/test/cases/callbacks_test.rb
+++ b/activerecord/test/cases/callbacks_test.rb
@@ -113,6 +113,26 @@ class ImmutableMethodDeveloper < ActiveRecord::Base
end
end
+class OnCallbacksDeveloper < ActiveRecord::Base
+ set_table_name 'developers'
+
+ before_validation { history << :before_validation }
+ before_validation(:on => :create){ history << :before_validation_on_create }
+ before_validation(:on => :update){ history << :before_validation_on_update }
+
+ validate do
+ history << :validate
+ end
+
+ after_validation { history << :after_validation }
+ after_validation(:on => :create){ history << :after_validation_on_create }
+ after_validation(:on => :update){ history << :after_validation_on_update }
+
+ def history
+ @history ||= []
+ end
+end
+
class CallbackCancellationDeveloper < ActiveRecord::Base
set_table_name 'developers'
@@ -250,7 +270,18 @@ class CallbacksTest < ActiveRecord::TestCase
], david.history
end
- def test_save
+ def test_validate_on_create
+ david = OnCallbacksDeveloper.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
assert_equal [
@@ -297,6 +328,18 @@ class CallbacksTest < ActiveRecord::TestCase
], david.history
end
+ def test_validate_on_update
+ david = OnCallbacksDeveloper.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/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb
index eb3f03c91d..f965652a9a 100644
--- a/activerecord/test/cases/fixtures_test.rb
+++ b/activerecord/test/cases/fixtures_test.rb
@@ -519,8 +519,8 @@ class FoxyFixturesTest < ActiveRecord::TestCase
end
def test_identifies_consistently
- assert_equal 1281023246, Fixtures.identify(:ruby)
- assert_equal 2140105598, Fixtures.identify(:sapphire_2)
+ assert_equal 207281424, Fixtures.identify(:ruby)
+ assert_equal 1066363776, Fixtures.identify(:sapphire_2)
end
TIMESTAMP_COLUMNS = %w(created_at created_on updated_at updated_on)
diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb
index 479970b2fa..fa76e2d57a 100644
--- a/activerecord/test/cases/helper.rb
+++ b/activerecord/test/cases/helper.rb
@@ -13,8 +13,6 @@ require 'test/unit'
require 'stringio'
require 'active_record'
-require 'active_record/test_case'
-require 'active_record/fixtures'
require 'connection'
begin
diff --git a/activerecord/test/cases/inheritance_test.rb b/activerecord/test/cases/inheritance_test.rb
index 73e51fbd91..0672fb938b 100644
--- a/activerecord/test/cases/inheritance_test.rb
+++ b/activerecord/test/cases/inheritance_test.rb
@@ -241,6 +241,7 @@ class InheritanceComputeTypeTest < ActiveRecord::TestCase
end
def test_instantiation_doesnt_try_to_require_corresponding_file
+ ActiveRecord::Base.store_full_sti_class = false
foo = Firm.find(:first).clone
foo.ruby_type = foo.type = 'FirmOnTheFly'
foo.save!
@@ -259,5 +260,7 @@ class InheritanceComputeTypeTest < ActiveRecord::TestCase
# And instantiate will find the existing constant rather than trying
# to require firm_on_the_fly.
assert_nothing_raised { assert_kind_of Firm::FirmOnTheFly, Firm.find(foo.id) }
+ ensure
+ ActiveRecord::Base.store_full_sti_class = true
end
end
diff --git a/activerecord/test/cases/method_scoping_test.rb b/activerecord/test/cases/method_scoping_test.rb
index cfc6f8772c..26aa3ed8d5 100644
--- a/activerecord/test/cases/method_scoping_test.rb
+++ b/activerecord/test/cases/method_scoping_test.rb
@@ -11,7 +11,7 @@ class MethodScopingTest < ActiveRecord::TestCase
def test_set_conditions
Developer.send(:with_scope, :find => { :conditions => 'just a test...' }) do
- assert_equal 'just a test...', Developer.send(:current_scoped_methods)[:find][:conditions]
+ assert_equal '(just a test...)', Developer.scoped.send(:where_clause)
end
end
@@ -207,7 +207,7 @@ class MethodScopingTest < ActiveRecord::TestCase
new_comment = nil
VerySpecialComment.send(:with_scope, :create => { :post_id => 1 }) do
- assert_equal({ :post_id => 1 }, VerySpecialComment.send(:current_scoped_methods)[:create])
+ assert_equal({:post_id => 1}, VerySpecialComment.scoped.send(:scope_for_create))
new_comment = VerySpecialComment.create :body => "Wonderful world"
end
@@ -256,8 +256,9 @@ class NestedScopingTest < ActiveRecord::TestCase
def test_merge_options
Developer.send(:with_scope, :find => { :conditions => 'salary = 80000' }) do
Developer.send(:with_scope, :find => { :limit => 10 }) do
- merged_option = Developer.instance_eval('current_scoped_methods')[:find]
- assert_equal({ :conditions => 'salary = 80000', :limit => 10 }, merged_option)
+ devs = Developer.scoped
+ assert_equal '(salary = 80000)', devs.send(:where_clause)
+ assert_equal 10, devs.taken
end
end
end
@@ -265,26 +266,26 @@ class NestedScopingTest < ActiveRecord::TestCase
def test_merge_inner_scope_has_priority
Developer.send(:with_scope, :find => { :limit => 5 }) do
Developer.send(:with_scope, :find => { :limit => 10 }) do
- merged_option = Developer.instance_eval('current_scoped_methods')[:find]
- assert_equal({ :limit => 10 }, merged_option)
+ assert_equal 10, Developer.scoped.taken
end
end
end
def test_replace_options
- Developer.send(:with_scope, :find => { :conditions => "name = 'David'" }) do
- Developer.send(:with_exclusive_scope, :find => { :conditions => "name = 'Jamis'" }) do
- assert_equal({:find => { :conditions => "name = 'Jamis'" }}, Developer.instance_eval('current_scoped_methods'))
- assert_equal({:find => { :conditions => "name = 'Jamis'" }}, Developer.send(:scoped_methods)[-1])
+ Developer.send(:with_scope, :find => { :conditions => {:name => 'David'} }) do
+ Developer.send(:with_exclusive_scope, :find => { :conditions => {:name => 'Jamis'} }) do
+ assert_equal 'Jamis', Developer.scoped.send(:scope_for_create)[:name]
end
+
+ assert_equal 'David', Developer.scoped.send(:scope_for_create)[:name]
end
end
def test_append_conditions
Developer.send(:with_scope, :find => { :conditions => "name = 'David'" }) do
Developer.send(:with_scope, :find => { :conditions => 'salary = 80000' }) do
- appended_condition = Developer.instance_eval('current_scoped_methods')[:find][:conditions]
- assert_equal("(name = 'David') AND (salary = 80000)", appended_condition)
+ devs = Developer.scoped
+ assert_equal "(name = 'David') AND (salary = 80000)", devs.send(:where_clause)
assert_equal(1, Developer.count)
end
Developer.send(:with_scope, :find => { :conditions => "name = 'Maiha'" }) do
@@ -296,8 +297,9 @@ class NestedScopingTest < ActiveRecord::TestCase
def test_merge_and_append_options
Developer.send(:with_scope, :find => { :conditions => 'salary = 80000', :limit => 10 }) do
Developer.send(:with_scope, :find => { :conditions => "name = 'David'" }) do
- merged_option = Developer.instance_eval('current_scoped_methods')[:find]
- assert_equal({ :conditions => "(salary = 80000) AND (name = 'David')", :limit => 10 }, merged_option)
+ devs = Developer.scoped
+ assert_equal "(salary = 80000) AND (name = 'David')", devs.send(:where_clause)
+ assert_equal 10, devs.taken
end
end
end
@@ -325,15 +327,15 @@ class NestedScopingTest < ActiveRecord::TestCase
# :include's remain unique and don't "double up" when merging
Developer.send(:with_scope, :find => { :include => :projects, :conditions => "projects.id = 2" }) do
Developer.send(:with_scope, :find => { :include => :projects }) do
- assert_equal 1, Developer.instance_eval('current_scoped_methods')[:find][:include].length
- assert_equal('David', Developer.find(:first).name)
+ assert_equal 1, Developer.scoped.includes_values.uniq.length
+ assert_equal 'David', Developer.find(:first).name
end
end
# the nested scope doesn't remove the first :include
Developer.send(:with_scope, :find => { :include => :projects, :conditions => "projects.id = 2" }) do
Developer.send(:with_scope, :find => { :include => [] }) do
- assert_equal 1, Developer.instance_eval('current_scoped_methods')[:find][:include].length
+ assert_equal 1, Developer.scoped.includes_values.uniq.length
assert_equal('David', Developer.find(:first).name)
end
end
@@ -341,7 +343,7 @@ class NestedScopingTest < ActiveRecord::TestCase
# mixing array and symbol include's will merge correctly
Developer.send(:with_scope, :find => { :include => [:projects], :conditions => "projects.id = 2" }) do
Developer.send(:with_scope, :find => { :include => :projects }) do
- assert_equal 1, Developer.instance_eval('current_scoped_methods')[:find][:include].length
+ assert_equal 1, Developer.scoped.includes_values.uniq.length
assert_equal('David', Developer.find(:first).name)
end
end
@@ -350,7 +352,7 @@ class NestedScopingTest < ActiveRecord::TestCase
def test_nested_scoped_find_replace_include
Developer.send(:with_scope, :find => { :include => :projects }) do
Developer.send(:with_exclusive_scope, :find => { :include => [] }) do
- assert_equal 0, Developer.instance_eval('current_scoped_methods')[:find][:include].length
+ assert_equal 0, Developer.scoped.includes_values.length
end
end
end
@@ -416,7 +418,7 @@ class NestedScopingTest < ActiveRecord::TestCase
comment = nil
Comment.send(:with_scope, :create => { :post_id => 1}) do
Comment.send(:with_scope, :create => { :post_id => 2}) do
- assert_equal({ :post_id => 2 }, Comment.send(:current_scoped_methods)[:create])
+ assert_equal({:post_id => 2}, Comment.scoped.send(:scope_for_create))
comment = Comment.create :body => "Hey guys, nested scopes are broken. Please fix!"
end
end
@@ -425,9 +427,11 @@ class NestedScopingTest < ActiveRecord::TestCase
def test_nested_exclusive_scope_for_create
comment = nil
+
Comment.send(:with_scope, :create => { :body => "Hey guys, nested scopes are broken. Please fix!" }) do
Comment.send(:with_exclusive_scope, :create => { :post_id => 1 }) do
- assert_equal({ :post_id => 1 }, Comment.send(:current_scoped_methods)[:create])
+ assert_equal({:post_id => 1}, Comment.scoped.send(:scope_for_create))
+ assert Comment.new.body.blank?
comment = Comment.create :body => "Hey guys"
end
end
@@ -603,44 +607,39 @@ class DefaultScopingTest < ActiveRecord::TestCase
end
def test_default_scoping_with_threads
- scope = [{ :create => {}, :find => { :order => 'salary DESC' } }]
-
2.times do
- Thread.new { assert_equal scope, DeveloperOrderedBySalary.send(:scoped_methods) }.join
+ Thread.new { assert_equal 'salary DESC', DeveloperOrderedBySalary.scoped.send(:order_clause) }.join
end
end
def test_default_scoping_with_inheritance
- scope = [{ :create => {}, :find => { :order => 'salary DESC' } }]
-
# Inherit a class having a default scope and define a new default scope
klass = Class.new(DeveloperOrderedBySalary)
klass.send :default_scope, {}
# Scopes added on children should append to parent scope
- expected_klass_scope = [{ :create => {}, :find => { :order => 'salary DESC' }}, { :create => {}, :find => {} }]
- assert_equal expected_klass_scope, klass.send(:scoped_methods)
+ assert klass.scoped.send(:order_clause).blank?
# Parent should still have the original scope
- assert_equal scope, DeveloperOrderedBySalary.send(:scoped_methods)
+ assert_equal 'salary DESC', DeveloperOrderedBySalary.scoped.send(:order_clause)
end
def test_method_scope
- expected = Developer.find(:all, :order => 'name DESC').collect { |dev| dev.salary }
+ expected = Developer.find(:all, :order => 'name DESC, salary DESC').collect { |dev| dev.salary }
received = DeveloperOrderedBySalary.all_ordered_by_name.collect { |dev| dev.salary }
assert_equal expected, received
end
def test_nested_scope
- expected = Developer.find(:all, :order => 'name DESC').collect { |dev| dev.salary }
+ expected = Developer.find(:all, :order => 'name DESC, salary DESC').collect { |dev| dev.salary }
received = DeveloperOrderedBySalary.send(:with_scope, :find => { :order => 'name DESC'}) do
DeveloperOrderedBySalary.find(:all).collect { |dev| dev.salary }
end
assert_equal expected, received
end
- def test_named_scope_overwrites_default
- expected = Developer.find(:all, :order => 'name DESC').collect { |dev| dev.name }
+ def test_named_scope_order_appended_to_default_scope_order
+ expected = Developer.find(:all, :order => 'name DESC, salary DESC').collect { |dev| dev.name }
received = DeveloperOrderedBySalary.by_name.find(:all).collect { |dev| dev.name }
assert_equal expected, received
end
diff --git a/activerecord/test/cases/modules_test.rb b/activerecord/test/cases/modules_test.rb
index 4f559bcaa5..d781a229f4 100644
--- a/activerecord/test/cases/modules_test.rb
+++ b/activerecord/test/cases/modules_test.rb
@@ -12,6 +12,8 @@ class ModulesTest < ActiveRecord::TestCase
[:Firm, :Client].each do |const|
@undefined_consts.merge! const => Object.send(:remove_const, const) if Object.const_defined?(const)
end
+
+ ActiveRecord::Base.store_full_sti_class = false
end
def teardown
@@ -19,6 +21,8 @@ class ModulesTest < ActiveRecord::TestCase
@undefined_consts.each do |constant, value|
Object.send :const_set, constant, value unless value.nil?
end
+
+ ActiveRecord::Base.store_full_sti_class = true
end
def test_module_spanning_associations
diff --git a/activerecord/test/cases/multiple_db_test.rb b/activerecord/test/cases/multiple_db_test.rb
index 6155bfd50a..bd51388e05 100644
--- a/activerecord/test/cases/multiple_db_test.rb
+++ b/activerecord/test/cases/multiple_db_test.rb
@@ -85,7 +85,7 @@ class MultipleDbTest < ActiveRecord::TestCase
end
def test_arel_table_engines
- assert_not_equal Entrant.active_relation_engine, Course.active_relation_engine
- assert_equal Entrant.active_relation_engine, Bird.active_relation_engine
+ 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/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb
index 8891282915..7ca9c416cb 100644
--- a/activerecord/test/cases/nested_attributes_test.rb
+++ b/activerecord/test/cases/nested_attributes_test.rb
@@ -34,7 +34,10 @@ class TestNestedAttributesInGeneral < ActiveRecord::TestCase
end
def test_should_add_a_proc_to_nested_attributes_options
- [:parrots, :birds, :birds_with_reject_all_blank].each do |name|
+ assert_equal ActiveRecord::NestedAttributes::ClassMethods::REJECT_ALL_BLANK_PROC,
+ Pirate.nested_attributes_options[:birds_with_reject_all_blank][:reject_if]
+
+ [:parrots, :birds].each do |name|
assert_instance_of Proc, Pirate.nested_attributes_options[name][:reject_if]
end
end
@@ -79,12 +82,6 @@ class TestNestedAttributesInGeneral < ActiveRecord::TestCase
assert ship._destroy
end
- def test_underscore_delete_is_deprecated
- ActiveSupport::Deprecation.expects(:warn)
- ship = Ship.create!(:name => 'Nights Dirty Lightning')
- ship._delete
- end
-
def test_reject_if_method_without_arguments
Pirate.accepts_nested_attributes_for :ship, :reject_if => :new_record?
@@ -176,6 +173,12 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase
assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name
end
+ def test_should_raise_RecordNotFound_if_an_id_is_given_but_doesnt_return_a_record
+ assert_raise_with_message ActiveRecord::RecordNotFound, "Couldn't find Ship with ID=1234567890 for Pirate with ID=#{@pirate.id}" do
+ @pirate.ship_attributes = { :id => 1234567890 }
+ end
+ end
+
def test_should_take_a_hash_with_string_keys_and_update_the_associated_model
@pirate.reload.ship_attributes = { 'id' => @ship.id, 'name' => 'Davy Jones Gold Dagger' }
@@ -269,6 +272,8 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase
end
class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase
+ include AssertRaiseWithMessage
+
def setup
@ship = Ship.new(:name => 'Nights Dirty Lightning')
@pirate = @ship.build_pirate(:catchphrase => 'Aye')
@@ -323,6 +328,12 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase
assert_equal 'Arr', @ship.pirate.catchphrase
end
+ def test_should_raise_RecordNotFound_if_an_id_is_given_but_doesnt_return_a_record
+ assert_raise_with_message ActiveRecord::RecordNotFound, "Couldn't find Pirate with ID=1234567890 for Ship with ID=#{@ship.id}" do
+ @ship.pirate_attributes = { :id => 1234567890 }
+ end
+ end
+
def test_should_take_a_hash_with_string_keys_and_update_the_associated_model
@ship.reload.pirate_attributes = { 'id' => @pirate.id, 'catchphrase' => 'Arr' }
@@ -384,10 +395,6 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase
assert Ship.reflect_on_association(:pirate).options[:autosave]
end
- def test_should_accept_update_only_option
- @ship.update_attribute(:update_only_pirate_attributes, { :id => @pirate.ship.id, :catchphrase => 'Arr' })
- end
-
def test_should_create_new_model_when_nothing_is_there_and_update_only_is_true
@pirate.delete
assert_difference('Pirate.count', 1) do
@@ -460,6 +467,12 @@ module NestedAttributesOnACollectionAssociationTests
assert_equal ['Grace OMalley', 'Privateers Greed'], [@child_1.name, @child_2.name]
end
+ def test_should_raise_RecordNotFound_if_an_id_is_given_but_doesnt_return_a_record
+ assert_raise_with_message ActiveRecord::RecordNotFound, "Couldn't find #{@child_1.class.name} with ID=1234567890 for Pirate with ID=#{@pirate.id}" do
+ @pirate.attributes = { association_getter => [{ :id => 1234567890 }] }
+ end
+ end
+
def test_should_automatically_build_new_associated_models_for_each_entry_in_a_hash_where_the_id_is_missing
@pirate.send(@association_name).destroy_all
@pirate.reload.attributes = {
@@ -565,7 +578,7 @@ module NestedAttributesOnACollectionAssociationTests
assert Pirate.reflect_on_association(@association_name).options[:autosave]
end
- def test_validate_presence_of_parent__works_with_inverse_of
+ def test_validate_presence_of_parent_works_with_inverse_of
Man.accepts_nested_attributes_for(:interests)
assert_equal :man, Man.reflect_on_association(:interests).options[:inverse_of]
assert_equal :interests, Interest.reflect_on_association(:man).options[:inverse_of]
@@ -582,7 +595,7 @@ module NestedAttributesOnACollectionAssociationTests
end
end
- def test_validate_presence_of_parent__fails_without_inverse_of
+ def test_validate_presence_of_parent_fails_without_inverse_of
Man.accepts_nested_attributes_for(:interests)
Man.reflect_on_association(:interests).options.delete(:inverse_of)
Interest.reflect_on_association(:man).options.delete(:inverse_of)
diff --git a/activerecord/test/cases/pooled_connections_test.rb b/activerecord/test/cases/pooled_connections_test.rb
index 2529a33dab..94d6663778 100644
--- a/activerecord/test/cases/pooled_connections_test.rb
+++ b/activerecord/test/cases/pooled_connections_test.rb
@@ -61,12 +61,14 @@ class PooledConnectionsTest < ActiveRecord::TestCase
checkout_checkin_connections 1, 2
assert_equal 2, @connection_count
assert_equal 0, @timed_out
+ 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
@@ -135,15 +137,4 @@ class PooledConnectionsTest < ActiveRecord::TestCase
def add_record(name)
ActiveRecord::Base.connection_pool.with_connection { Project.create! :name => name }
end
-end unless %w(FrontBase).include? ActiveRecord::Base.connection.adapter_name
-
-class AllowConcurrencyDeprecatedTest < ActiveRecord::TestCase
- def test_allow_concurrency_is_deprecated
- assert_deprecated('ActiveRecord::Base.allow_concurrency') do
- ActiveRecord::Base.allow_concurrency
- end
- assert_deprecated('ActiveRecord::Base.allow_concurrency=') do
- ActiveRecord::Base.allow_concurrency = true
- end
- end
-end
+end unless %w(FrontBase).include? ActiveRecord::Base.connection.adapter_name \ No newline at end of file
diff --git a/activerecord/test/cases/reflection_test.rb b/activerecord/test/cases/reflection_test.rb
index acd214eb5a..2c9158aa7b 100644
--- a/activerecord/test/cases/reflection_test.rb
+++ b/activerecord/test/cases/reflection_test.rb
@@ -4,10 +4,13 @@ require 'models/customer'
require 'models/company'
require 'models/company_in_module'
require 'models/subscriber'
+require 'models/ship'
require 'models/pirate'
require 'models/price_estimate'
class ReflectionTest < ActiveRecord::TestCase
+ include ActiveRecord::Reflection
+
fixtures :topics, :customers, :companies, :subscribers, :price_estimates
def setup
@@ -68,22 +71,22 @@ class ReflectionTest < ActiveRecord::TestCase
end
def test_reflection_klass_for_nested_class_name
- reflection = ActiveRecord::Reflection::MacroReflection.new(nil, nil, { :class_name => 'MyApplication::Business::Company' }, nil)
+ reflection = MacroReflection.new(nil, nil, { :class_name => 'MyApplication::Business::Company' }, nil)
assert_nothing_raised do
assert_equal MyApplication::Business::Company, reflection.klass
end
end
def test_aggregation_reflection
- reflection_for_address = ActiveRecord::Reflection::AggregateReflection.new(
+ reflection_for_address = AggregateReflection.new(
:composed_of, :address, { :mapping => [ %w(address_street street), %w(address_city city), %w(address_country country) ] }, Customer
)
- reflection_for_balance = ActiveRecord::Reflection::AggregateReflection.new(
+ reflection_for_balance = AggregateReflection.new(
:composed_of, :balance, { :class_name => "Money", :mapping => %w(balance amount) }, Customer
)
- reflection_for_gps_location = ActiveRecord::Reflection::AggregateReflection.new(
+ reflection_for_gps_location = AggregateReflection.new(
:composed_of, :gps_location, { }, Customer
)
@@ -108,7 +111,7 @@ class ReflectionTest < ActiveRecord::TestCase
end
def test_has_many_reflection
- reflection_for_clients = ActiveRecord::Reflection::AssociationReflection.new(:has_many, :clients, { :order => "id", :dependent => :destroy }, Firm)
+ reflection_for_clients = AssociationReflection.new(:has_many, :clients, { :order => "id", :dependent => :destroy }, Firm)
assert_equal reflection_for_clients, Firm.reflect_on_association(:clients)
@@ -120,7 +123,7 @@ class ReflectionTest < ActiveRecord::TestCase
end
def test_has_one_reflection
- reflection_for_account = ActiveRecord::Reflection::AssociationReflection.new(:has_one, :account, { :foreign_key => "firm_id", :dependent => :destroy }, Firm)
+ reflection_for_account = AssociationReflection.new(:has_one, :account, { :foreign_key => "firm_id", :dependent => :destroy }, Firm)
assert_equal reflection_for_account, Firm.reflect_on_association(:account)
assert_equal Account, Firm.reflect_on_association(:account).klass
@@ -137,6 +140,8 @@ class ReflectionTest < ActiveRecord::TestCase
end
def test_association_reflection_in_modules
+ ActiveRecord::Base.store_full_sti_class = false
+
assert_reflection MyApplication::Business::Firm,
:clients_of_firm,
:klass => MyApplication::Business::Client,
@@ -172,6 +177,8 @@ class ReflectionTest < ActiveRecord::TestCase
:klass => MyApplication::Billing::Nested::Firm,
:class_name => 'Nested::Firm',
:table_name => 'companies'
+ ensure
+ ActiveRecord::Base.store_full_sti_class = true
end
def test_reflection_of_all_associations
@@ -187,7 +194,44 @@ class ReflectionTest < ActiveRecord::TestCase
end
def test_has_many_through_reflection
- assert_kind_of ActiveRecord::Reflection::ThroughReflection, Subscriber.reflect_on_association(:books)
+ assert_kind_of ThroughReflection, Subscriber.reflect_on_association(:books)
+ end
+
+ def test_collection_association
+ assert Pirate.reflect_on_association(:birds).collection?
+ assert Pirate.reflect_on_association(:parrots).collection?
+
+ assert !Pirate.reflect_on_association(:ship).collection?
+ assert !Ship.reflect_on_association(:pirate).collection?
+ end
+
+ def test_default_association_validation
+ assert AssociationReflection.new(:has_many, :clients, {}, Firm).validate?
+
+ assert !AssociationReflection.new(:has_one, :client, {}, Firm).validate?
+ assert !AssociationReflection.new(:belongs_to, :client, {}, Firm).validate?
+ assert !AssociationReflection.new(:has_and_belongs_to_many, :clients, {}, Firm).validate?
+ end
+
+ def test_always_validate_association_if_explicit
+ assert AssociationReflection.new(:has_one, :client, { :validate => true }, Firm).validate?
+ assert AssociationReflection.new(:belongs_to, :client, { :validate => true }, Firm).validate?
+ assert AssociationReflection.new(:has_many, :clients, { :validate => true }, Firm).validate?
+ assert AssociationReflection.new(:has_and_belongs_to_many, :clients, { :validate => true }, Firm).validate?
+ end
+
+ def test_validate_association_if_autosave
+ assert AssociationReflection.new(:has_one, :client, { :autosave => true }, Firm).validate?
+ assert AssociationReflection.new(:belongs_to, :client, { :autosave => true }, Firm).validate?
+ assert AssociationReflection.new(:has_many, :clients, { :autosave => true }, Firm).validate?
+ assert AssociationReflection.new(:has_and_belongs_to_many, :clients, { :autosave => true }, Firm).validate?
+ end
+
+ def test_never_validate_association_if_explicit
+ assert !AssociationReflection.new(:has_one, :client, { :autosave => true, :validate => false }, Firm).validate?
+ assert !AssociationReflection.new(:belongs_to, :client, { :autosave => true, :validate => false }, Firm).validate?
+ assert !AssociationReflection.new(:has_many, :clients, { :autosave => true, :validate => false }, Firm).validate?
+ assert !AssociationReflection.new(:has_and_belongs_to_many, :clients, { :autosave => true, :validate => false }, Firm).validate?
end
private
diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb
index f895f8b8d2..195889f1df 100644
--- a/activerecord/test/cases/relations_test.rb
+++ b/activerecord/test/cases/relations_test.rb
@@ -545,6 +545,14 @@ class RelationTest < ActiveRecord::TestCase
assert_equal 'hen', hen.name
end
+ def test_explicit_create_scope
+ hens = Bird.where(:name => 'hen')
+ assert_equal 'hen', hens.new.name
+
+ hens = hens.create_with(:name => 'cock')
+ assert_equal 'cock', hens.new.name
+ end
+
def test_except
relation = Post.where(:author_id => 1).order('id ASC').limit(1)
assert_equal [posts(:welcome)], relation.all
diff --git a/activerecord/test/cases/subscriber_test.rb b/activerecord/test/cases/subscriber_test.rb
new file mode 100644
index 0000000000..ce91d9385d
--- /dev/null
+++ b/activerecord/test/cases/subscriber_test.rb
@@ -0,0 +1,51 @@
+require "cases/helper"
+require "models/developer"
+require "rails/subscriber/test_helper"
+require "active_record/railties/subscriber"
+
+module SubscriberTest
+ Rails::Subscriber.add(:active_record, ActiveRecord::Railties::Subscriber.new)
+
+ def setup
+ @old_logger = ActiveRecord::Base.logger
+ super
+ end
+
+ def teardown
+ super
+ ActiveRecord::Base.logger = @old_logger
+ end
+
+ def set_logger(logger)
+ ActiveRecord::Base.logger = logger
+ end
+
+ def test_basic_query_logging
+ Developer.all
+ wait
+ assert_equal 1, @logger.logged(:debug).size
+ assert_match /Developer Load/, @logger.logged(:debug).last
+ assert_match /SELECT .*?FROM .?developers.?/, @logger.logged(:debug).last
+ end
+
+ def test_cached_queries
+ ActiveRecord::Base.cache do
+ Developer.all
+ Developer.all
+ end
+ wait
+ assert_equal 2, @logger.logged(:debug).size
+ assert_match /CACHE/, @logger.logged(:debug).last
+ assert_match /SELECT .*?FROM .?developers.?/, @logger.logged(:debug).last
+ end
+
+ class SyncSubscriberTest < ActiveSupport::TestCase
+ include Rails::Subscriber::SyncTestHelper
+ include SubscriberTest
+ end
+
+ class AsyncSubscriberTest < ActiveSupport::TestCase
+ include Rails::Subscriber::AsyncTestHelper
+ include SubscriberTest
+ end
+end \ No newline at end of file
diff --git a/activerecord/test/cases/validations/association_validation_test.rb b/activerecord/test/cases/validations/association_validation_test.rb
index 5ed997356b..1246dd4276 100644
--- a/activerecord/test/cases/validations/association_validation_test.rb
+++ b/activerecord/test/cases/validations/association_validation_test.rb
@@ -10,33 +10,29 @@ require 'models/interest'
class AssociationValidationTest < ActiveRecord::TestCase
fixtures :topics, :owners
- repair_validations(Topic, Reply)
+ repair_validations(Topic, Reply, Owner)
def test_validates_size_of_association
- repair_validations(Owner) do
- assert_nothing_raised { Owner.validates_size_of :pets, :minimum => 1 }
- o = Owner.new('name' => 'nopets')
- assert !o.save
- assert o.errors[:pets].any?
- pet = o.pets.build('name' => 'apet')
- assert o.valid?
- end
+ assert_nothing_raised { Owner.validates_size_of :pets, :minimum => 1 }
+ o = Owner.new('name' => 'nopets')
+ assert !o.save
+ assert o.errors[:pets].any?
+ pet = o.pets.build('name' => 'apet')
+ assert o.valid?
end
def test_validates_size_of_association_using_within
- repair_validations(Owner) do
- assert_nothing_raised { Owner.validates_size_of :pets, :within => 1..2 }
- o = Owner.new('name' => 'nopets')
- assert !o.save
- assert o.errors[:pets].any?
+ assert_nothing_raised { Owner.validates_size_of :pets, :within => 1..2 }
+ o = Owner.new('name' => 'nopets')
+ assert !o.save
+ assert o.errors[:pets].any?
- pet = o.pets.build('name' => 'apet')
- assert o.valid?
+ pet = o.pets.build('name' => 'apet')
+ assert o.valid?
- 2.times { o.pets.build('name' => 'apet') }
- assert !o.save
- assert o.errors[:pets].any?
- end
+ 2.times { o.pets.build('name' => 'apet') }
+ assert !o.save
+ assert o.errors[:pets].any?
end
def test_validates_associated_many
@@ -55,51 +51,43 @@ class AssociationValidationTest < ActiveRecord::TestCase
end
def test_validates_associated_one
- repair_validations(Reply) do
- Reply.validates_associated( :topic )
- Topic.validates_presence_of( :content )
- r = Reply.new("title" => "A reply", "content" => "with content!")
- r.topic = Topic.create("title" => "uhohuhoh")
- assert !r.valid?
- assert r.errors[:topic].any?
- r.topic.content = "non-empty"
- assert r.valid?
- end
+ Reply.validates :topic, :associated => true
+ Topic.validates_presence_of( :content )
+ r = Reply.new("title" => "A reply", "content" => "with content!")
+ r.topic = Topic.create("title" => "uhohuhoh")
+ assert !r.valid?
+ assert r.errors[:topic].any?
+ r.topic.content = "non-empty"
+ assert r.valid?
end
def test_validates_associated_with_custom_message_using_quotes
- repair_validations(Reply) do
- Reply.validates_associated :topic, :message=> "This string contains 'single' and \"double\" quotes"
- Topic.validates_presence_of :content
- r = Reply.create("title" => "A reply", "content" => "with content!")
- r.topic = Topic.create("title" => "uhohuhoh")
- assert !r.valid?
- assert_equal ["This string contains 'single' and \"double\" quotes"], r.errors[:topic]
- end
+ Reply.validates_associated :topic, :message=> "This string contains 'single' and \"double\" quotes"
+ Topic.validates_presence_of :content
+ r = Reply.create("title" => "A reply", "content" => "with content!")
+ r.topic = Topic.create("title" => "uhohuhoh")
+ assert !r.valid?
+ assert_equal ["This string contains 'single' and \"double\" quotes"], r.errors[:topic]
end
def test_validates_associated_missing
- repair_validations(Reply) do
- Reply.validates_presence_of(:topic)
- r = Reply.create("title" => "A reply", "content" => "with content!")
- assert !r.valid?
- assert r.errors[:topic].any?
+ Reply.validates_presence_of(:topic)
+ r = Reply.create("title" => "A reply", "content" => "with content!")
+ assert !r.valid?
+ assert r.errors[:topic].any?
- r.topic = Topic.find :first
- assert r.valid?
- end
+ r.topic = Topic.find :first
+ assert r.valid?
end
def test_validates_size_of_association_utf8
- repair_validations(Owner) do
- with_kcode('UTF8') do
- assert_nothing_raised { Owner.validates_size_of :pets, :minimum => 1 }
- o = Owner.new('name' => 'あいうえおかきくけこ')
- assert !o.save
- assert o.errors[:pets].any?
- o.pets.build('name' => 'あいうえおかきくけこ')
- assert o.valid?
- end
+ with_kcode('UTF8') do
+ assert_nothing_raised { Owner.validates_size_of :pets, :minimum => 1 }
+ o = Owner.new('name' => 'あいうえおかきくけこ')
+ assert !o.save
+ assert o.errors[:pets].any?
+ o.pets.build('name' => 'あいうえおかきくけこ')
+ assert o.valid?
end
end
diff --git a/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb b/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb
index 3f96d7973b..15730c2a87 100644
--- a/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb
+++ b/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb
@@ -6,15 +6,7 @@ class I18nGenerateMessageValidationTest < ActiveRecord::TestCase
def setup
Topic.reset_callbacks(:validate)
@topic = Topic.new
- I18n.backend.store_translations :'en', {
- :activerecord => {
- :errors => {
- :messages => {
- :taken => "has already been taken",
- }
- }
- }
- }
+ I18n.backend = I18n::Backend::Simple.new
end
# validates_associated: generate_message(attr_name, :invalid, :default => configuration[:message], :value => value)
diff --git a/activerecord/test/cases/validations/i18n_validation_test.rb b/activerecord/test/cases/validations/i18n_validation_test.rb
index f017f24048..5dfbb1516f 100644
--- a/activerecord/test/cases/validations/i18n_validation_test.rb
+++ b/activerecord/test/cases/validations/i18n_validation_test.rb
@@ -4,13 +4,14 @@ require 'models/reply'
class I18nValidationTest < ActiveRecord::TestCase
repair_validations(Topic, Reply)
+
def setup
Reply.validates_presence_of(:title)
@topic = Topic.new
- @old_load_path, @old_backend = I18n.load_path, I18n.backend
+ @old_load_path, @old_backend = I18n.load_path.dup, I18n.backend
I18n.load_path.clear
I18n.backend = I18n::Backend::Simple.new
- I18n.backend.store_translations('en', :activerecord => {:errors => {:messages => {:custom => nil}}})
+ I18n.backend.store_translations('en', :errors => {:messages => {:custom => nil}})
end
def teardown
@@ -30,75 +31,6 @@ class I18nValidationTest < ActiveRecord::TestCase
end
end
- # ActiveRecord::Errors
- def test_errors_generate_message_translates_custom_model_attribute_key
- I18n.expects(:translate).with(
- :topic,
- { :count => 1,
- :default => ['Topic'],
- :scope => [:activerecord, :models]
- }
- ).returns('Topic')
-
- I18n.expects(:translate).with(
- :"topic.title",
- { :count => 1,
- :default => ['Title'],
- :scope => [:activerecord, :attributes]
- }
- ).returns('Title')
-
- I18n.expects(:translate).with(
- :"models.topic.attributes.title.invalid",
- :value => nil,
- :scope => [:activerecord, :errors],
- :default => [
- :"models.topic.invalid",
- 'default from class def error 1',
- :"messages.invalid"],
- :attribute => "Title",
- :model => "Topic"
- ).returns('default from class def error 1')
-
- @topic.errors.generate_message :title, :invalid, :default => 'default from class def error 1'
- end
-
- def test_errors_generate_message_translates_custom_model_attribute_keys_with_sti
-
- I18n.expects(:translate).with(
- :reply,
- { :count => 1,
- :default => [:topic, 'Reply'],
- :scope => [:activerecord, :models]
- }
- ).returns('Reply')
-
- I18n.expects(:translate).with(
- :"reply.title",
- { :count => 1,
- :default => [:'topic.title', 'Title'],
- :scope => [:activerecord, :attributes]
- }
- ).returns('Title')
-
- I18n.expects(:translate).with(
- :"models.reply.attributes.title.invalid",
- :value => nil,
- :scope => [:activerecord, :errors],
- :default => [
- :"models.reply.invalid",
- :"models.topic.attributes.title.invalid",
- :"models.topic.invalid",
- 'default from class def',
- :"messages.invalid"],
- :model => 'Reply',
- :attribute => 'Title'
- ).returns("default from class def")
-
- Reply.new.errors.generate_message :title, :invalid, :default => 'default from class def'
-
- end
-
# validates_uniqueness_of w/ mocha
def test_validates_uniqueness_of_generates_message
@@ -115,6 +47,25 @@ class I18nValidationTest < ActiveRecord::TestCase
@topic.valid?
end
+ # validates_uniqueness_of w/o mocha
+
+ def test_validates_associated_finds_custom_model_key_translation
+ I18n.backend.store_translations 'en', :errors => {:models => {:topic => {:attributes => {:title => {:taken => 'custom message'}}}}}
+ I18n.backend.store_translations 'en', :errors => {:messages => {:taken => 'global message'}}
+
+ Topic.validates_uniqueness_of :title
+ unique_topic.valid?
+ assert_equal ['custom message'], unique_topic.errors[:replies]
+ end
+
+ def test_validates_associated_finds_global_default_translation
+ I18n.backend.store_translations 'en', :errors => {:messages => {:taken => 'global message'}}
+
+ Topic.validates_uniqueness_of :title
+ unique_topic.valid?
+ assert_equal ['global message'], unique_topic.errors[:replies]
+ end
+
# validates_associated w/ mocha
def test_validates_associated_generates_message
@@ -132,8 +83,8 @@ class I18nValidationTest < ActiveRecord::TestCase
# validates_associated w/o mocha
def test_validates_associated_finds_custom_model_key_translation
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:models => {:topic => {:attributes => {:replies => {:invalid => 'custom message'}}}}}}
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:invalid => 'global message'}}}
+ I18n.backend.store_translations 'en', :errors => {:models => {:topic => {:attributes => {:replies => {:invalid => 'custom message'}}}}}
+ I18n.backend.store_translations 'en', :errors => {:messages => {:invalid => 'global message'}}
Topic.validates_associated :replies
replied_topic.valid?
@@ -141,7 +92,7 @@ class I18nValidationTest < ActiveRecord::TestCase
end
def test_validates_associated_finds_global_default_translation
- I18n.backend.store_translations 'en', :activerecord => {:errors => {:messages => {:invalid => 'global message'}}}
+ I18n.backend.store_translations 'en', :errors => {:messages => {:invalid => 'global message'}}
Topic.validates_associated :replies
replied_topic.valid?
diff --git a/activerecord/test/cases/validations/uniqueness_validation_test.rb b/activerecord/test/cases/validations/uniqueness_validation_test.rb
index 8f84841fe6..9a863c25a8 100644
--- a/activerecord/test/cases/validations/uniqueness_validation_test.rb
+++ b/activerecord/test/cases/validations/uniqueness_validation_test.rb
@@ -38,7 +38,7 @@ end
class UniquenessValidationTest < ActiveRecord::TestCase
fixtures :topics, 'warehouse-things', :developers
- repair_validations(Topic)
+ repair_validations(Topic, Reply)
def test_validate_uniqueness
Topic.validates_uniqueness_of(:title)
@@ -58,6 +58,15 @@ class UniquenessValidationTest < ActiveRecord::TestCase
assert t2.save, "Should now save t2 as unique"
end
+ def test_validates_uniqueness_with_validates
+ Topic.validates :title, :uniqueness => true
+ t = Topic.create!('title' => 'abc')
+
+ t2 = Topic.new('title' => 'abc')
+ assert !t2.valid?
+ assert t2.errors[:title]
+ end
+
def test_validates_uniqueness_with_newline_chars
Topic.validates_uniqueness_of(:title, :case_sensitive => false)
@@ -66,24 +75,22 @@ class UniquenessValidationTest < ActiveRecord::TestCase
end
def test_validate_uniqueness_with_scope
- repair_validations(Reply) do
- Reply.validates_uniqueness_of(:content, :scope => "parent_id")
+ Reply.validates_uniqueness_of(:content, :scope => "parent_id")
- t = Topic.create("title" => "I'm unique!")
+ t = Topic.create("title" => "I'm unique!")
- r1 = t.replies.create "title" => "r1", "content" => "hello world"
- assert r1.valid?, "Saving r1"
+ r1 = t.replies.create "title" => "r1", "content" => "hello world"
+ assert r1.valid?, "Saving r1"
- r2 = t.replies.create "title" => "r2", "content" => "hello world"
- assert !r2.valid?, "Saving r2 first time"
+ r2 = t.replies.create "title" => "r2", "content" => "hello world"
+ assert !r2.valid?, "Saving r2 first time"
- r2.content = "something else"
- assert r2.save, "Saving r2 second time"
+ r2.content = "something else"
+ assert r2.save, "Saving r2 second time"
- t2 = Topic.create("title" => "I'm unique too!")
- r3 = t2.replies.create "title" => "r3", "content" => "hello world"
- assert r3.valid?, "Saving r3"
- end
+ t2 = Topic.create("title" => "I'm unique too!")
+ r3 = t2.replies.create "title" => "r3", "content" => "hello world"
+ assert r3.valid?, "Saving r3"
end
def test_validate_uniqueness_scoped_to_defining_class
@@ -102,29 +109,27 @@ class UniquenessValidationTest < ActiveRecord::TestCase
end
def test_validate_uniqueness_with_scope_array
- repair_validations(Reply) do
- Reply.validates_uniqueness_of(:author_name, :scope => [:author_email_address, :parent_id])
+ Reply.validates_uniqueness_of(:author_name, :scope => [:author_email_address, :parent_id])
- t = Topic.create("title" => "The earth is actually flat!")
+ t = Topic.create("title" => "The earth is actually flat!")
- r1 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply"
- assert r1.valid?, "Saving r1"
+ r1 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply"
+ assert r1.valid?, "Saving r1"
- r2 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply again..."
- assert !r2.valid?, "Saving r2. Double reply by same author."
+ r2 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply again..."
+ assert !r2.valid?, "Saving r2. Double reply by same author."
- r2.author_email_address = "jeremy_alt_email@rubyonrails.com"
- assert r2.save, "Saving r2 the second time."
+ r2.author_email_address = "jeremy_alt_email@rubyonrails.com"
+ assert r2.save, "Saving r2 the second time."
- r3 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy_alt_email@rubyonrails.com", "title" => "You're wrong", "content" => "It's cubic"
- assert !r3.valid?, "Saving r3"
+ r3 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy_alt_email@rubyonrails.com", "title" => "You're wrong", "content" => "It's cubic"
+ assert !r3.valid?, "Saving r3"
- r3.author_name = "jj"
- assert r3.save, "Saving r3 the second time."
+ r3.author_name = "jj"
+ assert r3.save, "Saving r3 the second time."
- r3.author_name = "jeremy"
- assert !r3.save, "Saving r3 the third time."
- end
+ r3.author_name = "jeremy"
+ assert !r3.save, "Saving r3 the third time."
end
def test_validate_case_insensitive_uniqueness
diff --git a/activerecord/test/models/bird.rb b/activerecord/test/models/bird.rb
index 341d2eeffc..e61d48e6a5 100644
--- a/activerecord/test/models/bird.rb
+++ b/activerecord/test/models/bird.rb
@@ -1,3 +1,9 @@
class Bird < ActiveRecord::Base
validates_presence_of :name
+
+ attr_accessor :cancel_save_from_callback
+ before_save :cancel_save_callback_method, :if => :cancel_save_from_callback
+ def cancel_save_callback_method
+ false
+ end
end \ No newline at end of file
diff --git a/activerecord/test/models/invoice.rb b/activerecord/test/models/invoice.rb
new file mode 100644
index 0000000000..fc6ef0230e
--- /dev/null
+++ b/activerecord/test/models/invoice.rb
@@ -0,0 +1,4 @@
+class Invoice < ActiveRecord::Base
+ has_many :line_items, :autosave => true
+ before_save {|record| record.balance = record.line_items.map(&:amount).sum }
+end
diff --git a/activerecord/test/models/line_item.rb b/activerecord/test/models/line_item.rb
new file mode 100644
index 0000000000..0dd921a300
--- /dev/null
+++ b/activerecord/test/models/line_item.rb
@@ -0,0 +1,3 @@
+class LineItem < ActiveRecord::Base
+ belongs_to :invoice, :touch => true
+end
diff --git a/activerecord/test/models/parrot.rb b/activerecord/test/models/parrot.rb
index 4a7ed52636..737ef9131b 100644
--- a/activerecord/test/models/parrot.rb
+++ b/activerecord/test/models/parrot.rb
@@ -6,6 +6,12 @@ class Parrot < ActiveRecord::Base
alias_attribute :title, :name
validates_presence_of :name
+
+ attr_accessor :cancel_save_from_callback
+ before_save :cancel_save_callback_method, :if => :cancel_save_from_callback
+ def cancel_save_callback_method
+ false
+ end
end
class LiveParrot < Parrot
diff --git a/activerecord/test/models/pirate.rb b/activerecord/test/models/pirate.rb
index 88c1634717..f1dbe32c6e 100644
--- a/activerecord/test/models/pirate.rb
+++ b/activerecord/test/models/pirate.rb
@@ -51,6 +51,12 @@ class Pirate < ActiveRecord::Base
attributes.delete('_reject_me_if_new').present? && new_record?
end
+ attr_accessor :cancel_save_from_callback
+ before_save :cancel_save_callback_method, :if => :cancel_save_from_callback
+ def cancel_save_callback_method
+ false
+ end
+
private
def log_before_add(record)
log(record, "before_adding_method")
diff --git a/activerecord/test/models/ship.rb b/activerecord/test/models/ship.rb
index a96e38ab41..75c792d176 100644
--- a/activerecord/test/models/ship.rb
+++ b/activerecord/test/models/ship.rb
@@ -9,4 +9,10 @@ class Ship < ActiveRecord::Base
accepts_nested_attributes_for :update_only_pirate, :update_only => true
validates_presence_of :name
+
+ attr_accessor :cancel_save_from_callback
+ before_save :cancel_save_callback_method, :if => :cancel_save_from_callback
+ def cancel_save_callback_method
+ false
+ end
end
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index 1ec36e7832..bec4291457 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -191,6 +191,11 @@ ActiveRecord::Schema.define do
t.string :info
end
+ create_table :invoices, :force => true do |t|
+ t.integer :balance
+ t.datetime :updated_at
+ end
+
create_table :items, :force => true do |t|
t.column :name, :integer
end
@@ -216,6 +221,11 @@ ActiveRecord::Schema.define do
t.integer :version, :null => false, :default => 0
end
+ create_table :line_items, :force => true do |t|
+ t.integer :invoice_id
+ t.integer :amount
+ end
+
create_table :lock_without_defaults, :force => true do |t|
t.column :lock_version, :integer
end