aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/test
diff options
context:
space:
mode:
authorJoshua Peek <josh@joshpeek.com>2009-05-29 16:06:21 -0500
committerJoshua Peek <josh@joshpeek.com>2009-05-29 16:06:21 -0500
commit69742ca8fa05509f7d7c5512cb6d8e002ecb3ab3 (patch)
tree044c2131cc87d21ee54027511aae2b7f2d2ae26a /activerecord/test
parent5f3f100ce2d689480da85abc88e5e940cf90189e (diff)
parent5ec2c7dc29b36d85b2658465b8a979deb0529d7e (diff)
downloadrails-69742ca8fa05509f7d7c5512cb6d8e002ecb3ab3.tar.gz
rails-69742ca8fa05509f7d7c5512cb6d8e002ecb3ab3.tar.bz2
rails-69742ca8fa05509f7d7c5512cb6d8e002ecb3ab3.zip
Merge branch 'master' into active_model
Conflicts: activemodel/lib/active_model/core.rb activemodel/test/cases/state_machine/event_test.rb activemodel/test/cases/state_machine/state_transition_test.rb activerecord/lib/active_record/validations.rb activerecord/test/cases/validations/i18n_validation_test.rb activeresource/lib/active_resource.rb activeresource/test/abstract_unit.rb
Diffstat (limited to 'activerecord/test')
-rw-r--r--activerecord/test/cases/aaa_create_tables_test.rb24
-rw-r--r--activerecord/test/cases/aggregations_test.rb1
-rw-r--r--activerecord/test/cases/associations/eager_load_nested_include_test.rb24
-rw-r--r--activerecord/test/cases/associations/eager_test.rb16
-rw-r--r--activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb1
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb39
-rw-r--r--activerecord/test/cases/associations/has_many_through_associations_test.rb56
-rw-r--r--activerecord/test/cases/associations/has_one_through_associations_test.rb9
-rw-r--r--activerecord/test/cases/associations/inverse_associations_test.rb313
-rw-r--r--activerecord/test/cases/autosave_association_test.rb29
-rwxr-xr-xactiverecord/test/cases/base_test.rb7
-rw-r--r--activerecord/test/cases/calculations_test.rb2
-rw-r--r--activerecord/test/cases/finder_test.rb23
-rw-r--r--activerecord/test/cases/fixtures_test.rb5
-rw-r--r--activerecord/test/cases/helper.rb23
-rw-r--r--activerecord/test/cases/json_serialization_test.rb112
-rw-r--r--activerecord/test/cases/method_scoping_test.rb18
-rw-r--r--activerecord/test/cases/named_scope_test.rb41
-rw-r--r--activerecord/test/cases/nested_attributes_test.rb19
-rw-r--r--activerecord/test/cases/pooled_connections_test.rb29
-rw-r--r--activerecord/test/cases/repair_helper.rb6
-rw-r--r--activerecord/test/cases/validations/i18n_validation_test.rb15
-rw-r--r--activerecord/test/fixtures/faces.yml7
-rw-r--r--activerecord/test/fixtures/interests.yml29
-rw-r--r--activerecord/test/fixtures/men.yml5
-rw-r--r--activerecord/test/fixtures/people.yml5
-rw-r--r--activerecord/test/fixtures/zines.yml5
-rw-r--r--activerecord/test/models/company_in_module.rb2
-rw-r--r--activerecord/test/models/developer.rb10
-rw-r--r--activerecord/test/models/face.rb5
-rw-r--r--activerecord/test/models/interest.rb4
-rw-r--r--activerecord/test/models/man.rb7
-rw-r--r--activerecord/test/models/person.rb1
-rw-r--r--activerecord/test/models/pirate.rb2
-rw-r--r--activerecord/test/models/zine.rb3
-rw-r--r--activerecord/test/schema/schema.rb27
-rw-r--r--activerecord/test/schema/schema2.rb6
37 files changed, 776 insertions, 154 deletions
diff --git a/activerecord/test/cases/aaa_create_tables_test.rb b/activerecord/test/cases/aaa_create_tables_test.rb
deleted file mode 100644
index 3911afac49..0000000000
--- a/activerecord/test/cases/aaa_create_tables_test.rb
+++ /dev/null
@@ -1,24 +0,0 @@
-# The filename begins with "aaa" to ensure this is the first test.
-require "cases/helper"
-
-class AAACreateTablesTest < ActiveRecord::TestCase
- self.use_transactional_fixtures = false
-
- def test_load_schema
- eval(File.read(SCHEMA_ROOT + "/schema.rb"))
- if File.exists?(adapter_specific_schema_file)
- eval(File.read(adapter_specific_schema_file))
- end
- assert true
- end
-
- def test_drop_and_create_courses_table
- eval(File.read(SCHEMA_ROOT + "/schema2.rb"))
- assert true
- end
-
- private
- def adapter_specific_schema_file
- SCHEMA_ROOT + '/' + ActiveRecord::Base.connection.adapter_name.downcase + '_specific_schema.rb'
- end
-end
diff --git a/activerecord/test/cases/aggregations_test.rb b/activerecord/test/cases/aggregations_test.rb
index 4e0e1c7f15..8b6ec04018 100644
--- a/activerecord/test/cases/aggregations_test.rb
+++ b/activerecord/test/cases/aggregations_test.rb
@@ -1,5 +1,6 @@
require "cases/helper"
require 'models/customer'
+require 'active_support/core_ext/exception'
class AggregationsTest < ActiveRecord::TestCase
fixtures :customers
diff --git a/activerecord/test/cases/associations/eager_load_nested_include_test.rb b/activerecord/test/cases/associations/eager_load_nested_include_test.rb
index 1b2e0fc11e..f313a75233 100644
--- a/activerecord/test/cases/associations/eager_load_nested_include_test.rb
+++ b/activerecord/test/cases/associations/eager_load_nested_include_test.rb
@@ -1,18 +1,18 @@
require 'cases/helper'
-require 'models/author'
require 'models/post'
+require 'models/author'
require 'models/comment'
require 'models/category'
require 'models/categorization'
+require 'active_support/core_ext/array/random_access'
module Remembered
- def self.included(base)
- base.extend ClassMethods
- base.class_eval do
- after_create :remember
- protected
- def remember; self.class.remembered << self; end
- end
+ extend ActiveSupport::Concern
+
+ included do
+ after_create :remember
+ protected
+ def remember; self.class.remembered << self; end
end
module ClassMethods
@@ -66,13 +66,13 @@ class EagerLoadPolyAssocsTest < ActiveRecord::TestCase
def setup
generate_test_object_graphs
end
-
+
def teardown
- [Circle, Square, Triangle, PaintColor, PaintTexture,
+ [Circle, Square, Triangle, PaintColor, PaintTexture,
ShapeExpression, NonPolyOne, NonPolyTwo].each do |c|
c.delete_all
end
-
+
end
@@ -127,4 +127,4 @@ class EagerLoadNestedIncludeWithMissingDataTest < ActiveRecord::TestCase
Author.all :include => includes, :conditions => {:authors => {:name => @davey_mcdave.name}}, :order => 'categories.name'
end
end
-end \ No newline at end of file
+end
diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb
index 40723814c5..4cf49be668 100644
--- a/activerecord/test/cases/associations/eager_test.rb
+++ b/activerecord/test/cases/associations/eager_test.rb
@@ -223,6 +223,18 @@ class EagerAssociationTest < ActiveRecord::TestCase
end
end
+ def test_eager_association_loading_with_belongs_to_and_conditions_hash
+ comments = []
+ assert_nothing_raised do
+ comments = Comment.find(:all, :include => :post, :conditions => {:posts => {:id => 4}}, :limit => 3, :order => 'comments.id')
+ end
+ assert_equal 3, comments.length
+ assert_equal [5,6,7], comments.collect { |c| c.id }
+ assert_no_queries do
+ comments.first.post
+ end
+ end
+
def test_eager_association_loading_with_belongs_to_and_conditions_string_with_quoted_table_name
quoted_posts_id= Comment.connection.quote_table_name('posts') + '.' + Comment.connection.quote_column_name('id')
assert_nothing_raised do
@@ -577,6 +589,10 @@ class EagerAssociationTest < ActiveRecord::TestCase
assert_equal posts(:sti_post_and_comments, :sti_comments), Post.find(:all, :include => [:author, :comments], :conditions => "authors.name = 'David'", :order => 'UPPER(posts.title) DESC, posts.id', :limit => 2, :offset => 1)
end
+ def test_limited_eager_with_numeric_in_association
+ assert_equal people(:david, :susan), Person.find(:all, :include => [:readers, :primary_contact, :number1_fan], :conditions => "number1_fans_people.first_name like 'M%'", :order => 'people.id', :limit => 2, :offset => 0)
+ end
+
def test_preload_with_interpolation
assert_equal [comments(:greetings)], Post.find(posts(:welcome).id, :include => :comments_with_interpolated_conditions).comments_with_interpolated_conditions
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 5e8b2cadfc..8dc95806b9 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
@@ -24,6 +24,7 @@ require 'models/club'
require 'models/member'
require 'models/membership'
require 'models/sponsor'
+require 'active_support/core_ext/string/conversions'
class ProjectWithAfterCreateHook < ActiveRecord::Base
set_table_name 'projects'
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index 5df74fcdcd..d99424f9cd 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -1023,6 +1023,45 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert firm.clients.loaded?
end
+ def test_calling_many_should_count_instead_of_loading_association
+ firm = companies(:first_firm)
+ assert_queries(1) do
+ firm.clients.many? # use count query
+ end
+ assert !firm.clients.loaded?
+ end
+
+ def test_calling_many_on_loaded_association_should_not_use_query
+ firm = companies(:first_firm)
+ firm.clients.collect # force load
+ assert_no_queries { assert firm.clients.many? }
+ end
+
+ def test_calling_many_should_defer_to_collection_if_using_a_block
+ firm = companies(:first_firm)
+ assert_queries(1) do
+ firm.clients.expects(:size).never
+ firm.clients.many? { true }
+ end
+ assert firm.clients.loaded?
+ end
+
+ def test_calling_many_should_return_false_if_none_or_one
+ firm = companies(:another_firm)
+ assert !firm.clients_like_ms.many?
+ assert_equal 0, firm.clients_like_ms.size
+
+ firm = companies(:first_firm)
+ assert !firm.limited_clients.many?
+ assert_equal 1, firm.limited_clients.size
+ end
+
+ def test_calling_many_should_return_true_if_more_than_one
+ firm = companies(:first_firm)
+ assert firm.clients.many?
+ assert_equal 2, firm.clients.size
+ end
+
def test_joins_with_namespaced_model_should_use_correct_type
old = ActiveRecord::Base.store_full_sti_class
ActiveRecord::Base.store_full_sti_class = true
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 97efca7891..4254badef2 100644
--- a/activerecord/test/cases/associations/has_many_through_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb
@@ -13,7 +13,7 @@ require 'models/pet'
require 'models/toy'
class HasManyThroughAssociationsTest < ActiveRecord::TestCase
- fixtures :posts, :readers, :people, :comments, :authors, :owners, :pets, :toys
+ fixtures :posts, :readers, :people, :comments, :authors, :owners, :pets, :toys, :jobs, :references
def test_associate_existing
assert_queries(2) { posts(:thinking);people(:david) }
@@ -23,49 +23,49 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
assert_queries(1) do
posts(:thinking).people << people(:david)
end
-
+
assert_queries(1) do
assert posts(:thinking).people.include?(people(:david))
end
-
+
assert posts(:thinking).reload.people(true).include?(people(:david))
end
def test_associating_new
assert_queries(1) { posts(:thinking) }
new_person = nil # so block binding catches it
-
+
assert_queries(0) do
new_person = Person.new :first_name => 'bob'
end
-
+
# Associating new records always saves them
# Thus, 1 query for the new person record, 1 query for the new join table record
assert_queries(2) do
posts(:thinking).people << new_person
end
-
+
assert_queries(1) do
assert posts(:thinking).people.include?(new_person)
end
-
+
assert posts(:thinking).reload.people(true).include?(new_person)
end
def test_associate_new_by_building
assert_queries(1) { posts(:thinking) }
-
+
assert_queries(0) do
posts(:thinking).people.build(:first_name=>"Bob")
posts(:thinking).people.new(:first_name=>"Ted")
end
-
+
# Should only need to load the association once
assert_queries(1) do
assert posts(:thinking).people.collect(&:first_name).include?("Bob")
assert posts(:thinking).people.collect(&:first_name).include?("Ted")
end
-
+
# 2 queries for each new record (1 to save the record itself, 1 for the join model)
# * 2 new records = 4
# + 1 query to save the actual post = 5
@@ -73,27 +73,27 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
posts(:thinking).body += '-changed'
posts(:thinking).save
end
-
+
assert posts(:thinking).reload.people(true).collect(&:first_name).include?("Bob")
assert posts(:thinking).reload.people(true).collect(&:first_name).include?("Ted")
end
def test_delete_association
assert_queries(2){posts(:welcome);people(:michael); }
-
+
assert_queries(1) do
posts(:welcome).people.delete(people(:michael))
end
-
+
assert_queries(1) do
assert posts(:welcome).people.empty?
end
-
+
assert posts(:welcome).reload.people(true).empty?
end
def test_destroy_association
- assert_difference "Person.count", -1 do
+ assert_difference ["Person.count", "Reader.count"], -1 do
posts(:welcome).people.destroy(people(:michael))
end
@@ -102,7 +102,7 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
end
def test_destroy_all
- assert_difference "Person.count", -1 do
+ assert_difference ["Person.count", "Reader.count"], -1 do
posts(:welcome).people.destroy_all
end
@@ -110,38 +110,44 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
assert posts(:welcome).people(true).empty?
end
+ def test_should_raise_exception_for_destroying_mismatching_records
+ assert_no_difference ["Person.count", "Reader.count"] do
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { posts(:welcome).people.destroy(posts(:thinking)) }
+ end
+ end
+
def test_replace_association
assert_queries(4){posts(:welcome);people(:david);people(:michael); posts(:welcome).people(true)}
-
+
# 1 query to delete the existing reader (michael)
# 1 query to associate the new reader (david)
assert_queries(2) do
posts(:welcome).people = [people(:david)]
end
-
+
assert_queries(0){
assert posts(:welcome).people.include?(people(:david))
assert !posts(:welcome).people.include?(people(:michael))
}
-
+
assert posts(:welcome).reload.people(true).include?(people(:david))
assert !posts(:welcome).reload.people(true).include?(people(:michael))
end
def test_associate_with_create
assert_queries(1) { posts(:thinking) }
-
+
# 1 query for the new record, 1 for the join table record
# No need to update the actual collection yet!
assert_queries(2) do
posts(:thinking).people.create(:first_name=>"Jeb")
end
-
+
# *Now* we actually need the collection so it's loaded
assert_queries(1) do
assert posts(:thinking).people.collect(&:first_name).include?("Jeb")
end
-
+
assert posts(:thinking).reload.people(true).collect(&:first_name).include?("Jeb")
end
@@ -159,15 +165,15 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
def test_clear_associations
assert_queries(2) { posts(:welcome);posts(:welcome).people(true) }
-
+
assert_queries(1) do
posts(:welcome).people.clear
end
-
+
assert_queries(0) do
assert posts(:welcome).people.empty?
end
-
+
assert posts(:welcome).reload.people(true).empty?
end
diff --git a/activerecord/test/cases/associations/has_one_through_associations_test.rb b/activerecord/test/cases/associations/has_one_through_associations_test.rb
index 12c598751b..ab6e6d20fc 100644
--- a/activerecord/test/cases/associations/has_one_through_associations_test.rb
+++ b/activerecord/test/cases/associations/has_one_through_associations_test.rb
@@ -43,7 +43,14 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase
@member.reload
end
end
-
+
+ def test_set_record_to_nil_should_delete_association
+ @member.club = nil
+ @member.reload
+ assert_equal nil, @member.current_membership
+ assert_nil @member.club
+ end
+
def test_has_one_through_polymorphic
assert_equal clubs(:moustache_club), @member.sponsor_club
end
diff --git a/activerecord/test/cases/associations/inverse_associations_test.rb b/activerecord/test/cases/associations/inverse_associations_test.rb
new file mode 100644
index 0000000000..47f83db112
--- /dev/null
+++ b/activerecord/test/cases/associations/inverse_associations_test.rb
@@ -0,0 +1,313 @@
+require "cases/helper"
+require 'models/man'
+require 'models/face'
+require 'models/interest'
+require 'models/zine'
+require 'models/club'
+require 'models/sponsor'
+
+class InverseAssociationTests < ActiveRecord::TestCase
+ def test_should_allow_for_inverse_of_options_in_associations
+ assert_nothing_raised(ArgumentError, 'ActiveRecord should allow the inverse_of options on has_many') do
+ Class.new(ActiveRecord::Base).has_many(:wheels, :inverse_of => :car)
+ end
+
+ assert_nothing_raised(ArgumentError, 'ActiveRecord should allow the inverse_of options on has_one') do
+ Class.new(ActiveRecord::Base).has_one(:engine, :inverse_of => :car)
+ end
+
+ assert_nothing_raised(ArgumentError, 'ActiveRecord should allow the inverse_of options on belongs_to') do
+ Class.new(ActiveRecord::Base).belongs_to(:car, :inverse_of => :driver)
+ end
+ end
+
+ def test_should_be_able_to_ask_a_reflection_if_it_has_an_inverse
+ has_one_with_inverse_ref = Man.reflect_on_association(:face)
+ assert has_one_with_inverse_ref.respond_to?(:has_inverse?)
+ assert has_one_with_inverse_ref.has_inverse?
+
+ has_many_with_inverse_ref = Man.reflect_on_association(:interests)
+ assert has_many_with_inverse_ref.respond_to?(:has_inverse?)
+ assert has_many_with_inverse_ref.has_inverse?
+
+ belongs_to_with_inverse_ref = Face.reflect_on_association(:man)
+ assert belongs_to_with_inverse_ref.respond_to?(:has_inverse?)
+ assert belongs_to_with_inverse_ref.has_inverse?
+
+ has_one_without_inverse_ref = Club.reflect_on_association(:sponsor)
+ assert has_one_without_inverse_ref.respond_to?(:has_inverse?)
+ assert !has_one_without_inverse_ref.has_inverse?
+
+ has_many_without_inverse_ref = Club.reflect_on_association(:memberships)
+ assert has_many_without_inverse_ref.respond_to?(:has_inverse?)
+ assert !has_many_without_inverse_ref.has_inverse?
+
+ belongs_to_without_inverse_ref = Sponsor.reflect_on_association(:sponsor_club)
+ assert belongs_to_without_inverse_ref.respond_to?(:has_inverse?)
+ assert !belongs_to_without_inverse_ref.has_inverse?
+ end
+
+ def test_should_be_able_to_ask_a_reflection_what_it_is_the_inverse_of
+ has_one_ref = Man.reflect_on_association(:face)
+ assert has_one_ref.respond_to?(:inverse_of)
+
+ has_many_ref = Man.reflect_on_association(:interests)
+ assert has_many_ref.respond_to?(:inverse_of)
+
+ belongs_to_ref = Face.reflect_on_association(:man)
+ assert belongs_to_ref.respond_to?(:inverse_of)
+ end
+
+ def test_inverse_of_method_should_supply_the_actual_reflection_instance_it_is_the_inverse_of
+ has_one_ref = Man.reflect_on_association(:face)
+ assert_equal Face.reflect_on_association(:man), has_one_ref.inverse_of
+
+ has_many_ref = Man.reflect_on_association(:interests)
+ assert_equal Interest.reflect_on_association(:man), has_many_ref.inverse_of
+
+ belongs_to_ref = Face.reflect_on_association(:man)
+ assert_equal Man.reflect_on_association(:face), belongs_to_ref.inverse_of
+ end
+
+ def test_associations_with_no_inverse_of_should_return_nil
+ has_one_ref = Club.reflect_on_association(:sponsor)
+ assert_nil has_one_ref.inverse_of
+
+ has_many_ref = Club.reflect_on_association(:memberships)
+ assert_nil has_many_ref.inverse_of
+
+ belongs_to_ref = Sponsor.reflect_on_association(:sponsor_club)
+ assert_nil belongs_to_ref.inverse_of
+ end
+end
+
+class InverseHasOneTests < ActiveRecord::TestCase
+ fixtures :men, :faces
+
+ def test_parent_instance_should_be_shared_with_child_on_find
+ m = Man.find(:first)
+ f = m.face
+ assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance"
+ f.man.name = 'Mungo'
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to child-owned instance"
+ end
+
+
+ def test_parent_instance_should_be_shared_with_eager_loaded_child_on_find
+ m = Man.find(:first, :include => :face)
+ f = m.face
+ assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance"
+ f.man.name = 'Mungo'
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to child-owned instance"
+
+ m = Man.find(:first, :include => :face, :order => 'faces.id')
+ f = m.face
+ assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance"
+ f.man.name = 'Mungo'
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to child-owned instance"
+ end
+
+ def test_parent_instance_should_be_shared_with_newly_built_child
+ m = Man.find(:first)
+ f = m.build_face(:description => 'haunted')
+ assert_not_nil f.man
+ assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance"
+ f.man.name = 'Mungo'
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to just-built-child-owned instance"
+ end
+
+ def test_parent_instance_should_be_shared_with_newly_created_child
+ m = Man.find(:first)
+ f = m.create_face(:description => 'haunted')
+ assert_not_nil f.man
+ assert_equal m.name, f.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to parent instance"
+ f.man.name = 'Mungo'
+ assert_equal m.name, f.man.name, "Name of man should be the same after changes to newly-created-child-owned instance"
+ end
+
+ def test_trying_to_use_inverses_that_dont_exist_should_raise_an_error
+ assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) { Man.find(:first).dirty_face }
+ end
+end
+
+class InverseHasManyTests < ActiveRecord::TestCase
+ fixtures :men, :interests
+
+ def test_parent_instance_should_be_shared_with_every_child_on_find
+ m = Man.find(:first)
+ is = m.interests
+ is.each do |i|
+ assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance"
+ i.man.name = 'Mungo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to child-owned instance"
+ end
+ end
+
+ def test_parent_instance_should_be_shared_with_eager_loaded_children
+ m = Man.find(:first, :include => :interests)
+ is = m.interests
+ is.each do |i|
+ assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance"
+ i.man.name = 'Mungo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to child-owned instance"
+ end
+
+ m = Man.find(:first, :include => :interests, :order => 'interests.id')
+ is = m.interests
+ is.each do |i|
+ assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance"
+ i.man.name = 'Mungo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to child-owned instance"
+ end
+
+ end
+
+ def test_parent_instance_should_be_shared_with_newly_built_child
+ m = Man.find(:first)
+ i = m.interests.build(:topic => 'Industrial Revolution Re-enactment')
+ assert_not_nil i.man
+ assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance"
+ i.man.name = 'Mungo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to just-built-child-owned instance"
+ end
+
+ def test_parent_instance_should_be_shared_with_newly_created_child
+ m = Man.find(:first)
+ i = m.interests.create(:topic => 'Industrial Revolution Re-enactment')
+ assert_not_nil i.man
+ assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance"
+ i.man.name = 'Mungo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to newly-created-child-owned instance"
+ end
+
+ def test_parent_instance_should_be_shared_with_poked_in_child
+ m = Man.find(:first)
+ i = Interest.create(:topic => 'Industrial Revolution Re-enactment')
+ m.interests << i
+ assert_not_nil i.man
+ assert_equal m.name, i.man.name, "Name of man should be the same before changes to parent instance"
+ m.name = 'Bongo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to parent instance"
+ i.man.name = 'Mungo'
+ assert_equal m.name, i.man.name, "Name of man should be the same after changes to newly-created-child-owned instance"
+ end
+
+ def test_trying_to_use_inverses_that_dont_exist_should_raise_an_error
+ assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) { Man.find(:first).secret_interests }
+ end
+end
+
+class InverseBelongsToTests < ActiveRecord::TestCase
+ fixtures :men, :faces, :interests
+
+ def test_child_instance_should_be_shared_with_parent_on_find
+ f = Face.find(:first)
+ m = f.man
+ assert_equal f.description, m.face.description, "Description of face should be the same before changes to child instance"
+ f.description = 'gormless'
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to child instance"
+ m.face.description = 'pleasing'
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to parent-owned instance"
+ end
+
+ def test_eager_loaded_child_instance_should_be_shared_with_parent_on_find
+ f = Face.find(:first, :include => :man)
+ m = f.man
+ assert_equal f.description, m.face.description, "Description of face should be the same before changes to child instance"
+ f.description = 'gormless'
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to child instance"
+ m.face.description = 'pleasing'
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to parent-owned instance"
+
+
+ f = Face.find(:first, :include => :man, :order => 'men.id')
+ m = f.man
+ assert_equal f.description, m.face.description, "Description of face should be the same before changes to child instance"
+ f.description = 'gormless'
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to child instance"
+ m.face.description = 'pleasing'
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to parent-owned instance"
+ end
+
+ def test_child_instance_should_be_shared_with_newly_built_parent
+ f = Face.find(:first)
+ m = f.build_man(:name => 'Charles')
+ assert_not_nil m.face
+ assert_equal f.description, m.face.description, "Description of face should be the same before changes to child instance"
+ f.description = 'gormless'
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to child instance"
+ m.face.description = 'pleasing'
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to just-built-parent-owned instance"
+ end
+
+ def test_child_instance_should_be_shared_with_newly_created_parent
+ f = Face.find(:first)
+ m = f.create_man(:name => 'Charles')
+ assert_not_nil m.face
+ assert_equal f.description, m.face.description, "Description of face should be the same before changes to child instance"
+ f.description = 'gormless'
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to child instance"
+ m.face.description = 'pleasing'
+ assert_equal f.description, m.face.description, "Description of face should be the same after changes to newly-created-parent-owned instance"
+ end
+
+ def test_should_not_try_to_set_inverse_instances_when_the_inverse_is_a_has_many
+ i = Interest.find(:first)
+ m = i.man
+ assert_not_nil m.interests
+ iz = m.interests.detect {|iz| iz.id == i.id}
+ assert_not_nil iz
+ assert_equal i.topic, iz.topic, "Interest topics should be the same before changes to child"
+ i.topic = 'Eating cheese with a spoon'
+ assert_not_equal i.topic, iz.topic, "Interest topics should not be the same after changes to child"
+ iz.topic = 'Cow tipping'
+ assert_not_equal i.topic, iz.topic, "Interest topics should not be the same after changes to parent-owned instance"
+ end
+
+ def test_trying_to_use_inverses_that_dont_exist_should_raise_an_error
+ assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) { Face.find(:first).horrible_man }
+ end
+end
+
+# NOTE - these tests might not be meaningful, ripped as they were from the parental_control plugin
+# which would guess the inverse rather than look for an explicit configuration option.
+class InverseMultipleHasManyInversesForSameModel < ActiveRecord::TestCase
+ fixtures :men, :interests, :zines
+
+ def test_that_we_can_load_associations_that_have_the_same_reciprocal_name_from_different_models
+ assert_nothing_raised(ActiveRecord::AssociationTypeMismatch) do
+ i = Interest.find(:first)
+ z = i.zine
+ m = i.man
+ end
+ end
+
+ def test_that_we_can_create_associations_that_have_the_same_reciprocal_name_from_different_models
+ assert_nothing_raised(ActiveRecord::AssociationTypeMismatch) do
+ i = Interest.find(:first)
+ i.build_zine(:title => 'Get Some in Winter! 2008')
+ i.build_man(:name => 'Gordon')
+ i.save!
+ end
+ end
+end
diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb
index 2712b2a05c..ddca5e962d 100644
--- a/activerecord/test/cases/autosave_association_test.rb
+++ b/activerecord/test/cases/autosave_association_test.rb
@@ -12,6 +12,7 @@ require 'models/reader'
require 'models/ship'
require 'models/ship_part'
require 'models/treasure'
+require 'models/company'
class TestAutosaveAssociationsInGeneral < ActiveRecord::TestCase
def test_autosave_should_be_a_valid_option_for_has_one
@@ -38,6 +39,19 @@ class TestAutosaveAssociationsInGeneral < ActiveRecord::TestCase
end
class TestDefaultAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCase
+ fixtures :companies, :accounts
+
+ def test_should_save_parent_but_not_invalid_child
+ firm = Firm.new(:name => 'GlobalMegaCorp')
+ assert firm.valid?
+
+ firm.build_account_using_primary_key
+ assert !firm.build_account_using_primary_key.valid?
+
+ assert firm.save
+ assert firm.account_using_primary_key.new_record?
+ end
+
def test_save_fails_for_invalid_has_one
firm = Firm.find(:first)
assert firm.valid?
@@ -126,6 +140,19 @@ class TestDefaultAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCas
end
class TestDefaultAutosaveAssociationOnABelongsToAssociation < ActiveRecord::TestCase
+ fixtures :companies
+
+ def test_should_save_parent_but_not_invalid_child
+ client = Client.new(:name => 'Joe (the Plumber)')
+ assert client.valid?
+
+ client.build_firm
+ assert !client.firm.valid?
+
+ assert client.save
+ assert client.firm.new_record?
+ end
+
def test_save_fails_for_invalid_belongs_to
assert log = AuditLog.create(:developer_id => 0, :message => "")
@@ -898,4 +925,4 @@ class TestAutosaveAssociationOnAHasAndBelongsToManyAssociation < ActiveRecord::T
end
include AutosaveAssociationOnACollectionAssociationTests
-end \ No newline at end of file
+end
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index d97cd17d75..59aa6953e3 100755
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -1,4 +1,5 @@
require "cases/helper"
+require 'models/post'
require 'models/author'
require 'models/topic'
require 'models/reply'
@@ -12,12 +13,12 @@ require 'models/auto_id'
require 'models/column_name'
require 'models/subscriber'
require 'models/keyboard'
-require 'models/post'
require 'models/comment'
require 'models/minimalistic'
require 'models/warehouse_thing'
require 'models/parrot'
require 'rexml/document'
+require 'active_support/core_ext/exception'
class Category < ActiveRecord::Base; end
class Categorization < ActiveRecord::Base; end
@@ -1115,7 +1116,7 @@ class BasicsTest < ActiveRecord::TestCase
Time.zone = nil
Topic.skip_time_zone_conversion_for_attributes = []
end
-
+
def test_multiparameter_attributes_on_time_only_column_with_time_zone_aware_attributes_does_not_do_time_zone_conversion
ActiveRecord::Base.time_zone_aware_attributes = true
ActiveRecord::Base.default_timezone = :utc
@@ -1439,7 +1440,7 @@ class BasicsTest < ActiveRecord::TestCase
topic = Topic.create("content" => myobj).reload
assert_equal(myobj, topic.content)
end
-
+
def test_serialized_string_attribute
myobj = "Yes"
topic = Topic.create("content" => myobj).reload
diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb
index 56dcdea110..fd455e0864 100644
--- a/activerecord/test/cases/calculations_test.rb
+++ b/activerecord/test/cases/calculations_test.rb
@@ -233,7 +233,7 @@ class CalculationsTest < ActiveRecord::TestCase
assert_equal 8, c['Jadedpixel']
end
- def test_should_group_by_summed_field_with_conditions_and_having
+ def test_should_group_by_summed_field_through_association_and_having
c = companies(:rails_core).companies.sum(:id, :group => :name,
:having => 'sum(id) > 7')
assert_nil c['Leetsoft']
diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb
index d8778957c0..037b67ec84 100644
--- a/activerecord/test/cases/finder_test.rb
+++ b/activerecord/test/cases/finder_test.rb
@@ -1,4 +1,5 @@
require "cases/helper"
+require 'models/post'
require 'models/author'
require 'models/categorization'
require 'models/comment'
@@ -6,11 +7,10 @@ require 'models/company'
require 'models/topic'
require 'models/reply'
require 'models/entrant'
+require 'models/project'
require 'models/developer'
-require 'models/post'
require 'models/customer'
require 'models/job'
-require 'models/categorization'
class DynamicFinderMatchTest < ActiveRecord::TestCase
def test_find_no_match
@@ -64,7 +64,7 @@ class DynamicFinderMatchTest < ActiveRecord::TestCase
end
class FinderTest < ActiveRecord::TestCase
- fixtures :companies, :topics, :entrants, :developers, :developers_projects, :posts, :comments, :accounts, :authors, :customers
+ fixtures :companies, :topics, :entrants, :developers, :developers_projects, :posts, :comments, :accounts, :authors, :customers, :categories, :categorizations
def test_find
assert_equal(topics(:first).title, Topic.find(1).title)
@@ -94,16 +94,16 @@ class FinderTest < ActiveRecord::TestCase
assert_raise(NoMethodError) { Topic.exists?([1,2]) }
end
-
+
def test_exists_returns_true_with_one_record_and_no_args
assert Topic.exists?
end
-
+
def test_does_not_exist_with_empty_table_and_no_args_given
Topic.delete_all
assert !Topic.exists?
end
-
+
def test_exists_with_aggregate_having_three_mappings
existing_address = customers(:david).address
assert Customer.exists?(:address => existing_address)
@@ -119,6 +119,12 @@ class FinderTest < ActiveRecord::TestCase
Address.new(existing_address.street + "1", existing_address.city, existing_address.country))
end
+ def test_exists_with_scoped_include
+ Developer.with_scope(:find => { :include => :projects, :order => "projects.name" }) do
+ assert Developer.exists?
+ end
+ end
+
def test_find_by_array_of_one_id
assert_kind_of(Array, Topic.find([ 1 ]))
assert_equal(1, Topic.find([ 1 ]).length)
@@ -485,8 +491,9 @@ class FinderTest < ActiveRecord::TestCase
assert_equal "foo in (#{quoted_nil})", bind('foo in (?)', [])
end
- def test_bind_string
- assert_equal ActiveRecord::Base.connection.quote(''), bind('?', '')
+ def test_bind_empty_string
+ quoted_empty = ActiveRecord::Base.connection.quote('')
+ assert_equal quoted_empty, bind('?', '')
end
def test_bind_chars
diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb
index 252bf4ff61..b07d4f3521 100644
--- a/activerecord/test/cases/fixtures_test.rb
+++ b/activerecord/test/cases/fixtures_test.rb
@@ -518,6 +518,11 @@ class FoxyFixturesTest < ActiveRecord::TestCase
assert_equal(Fixtures.identify(:foo), Fixtures.identify(:foo))
end
+ def test_identifies_consistently
+ assert_equal 1281023246, Fixtures.identify(:ruby)
+ assert_equal 2140105598, Fixtures.identify(:sapphire_2)
+ end
+
TIMESTAMP_COLUMNS = %w(created_at created_on updated_at updated_on)
def test_populates_timestamp_columns
diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb
index a4f05f0c72..c30186286d 100644
--- a/activerecord/test/cases/helper.rb
+++ b/activerecord/test/cases/helper.rb
@@ -5,6 +5,7 @@ require 'config'
require 'rubygems'
require 'test/unit'
+require 'stringio'
gem 'mocha', '>= 0.9.5'
require 'mocha'
@@ -15,6 +16,11 @@ require 'connection'
require 'cases/repair_helper'
+begin
+ require 'ruby-debug'
+rescue LoadError
+end
+
# Show backtraces for deprecated behavior for quicker cleanup.
ActiveSupport::Deprecation.debug = true
@@ -67,3 +73,20 @@ class ActiveSupport::TestCase
Fixtures.create_fixtures(ActiveSupport::TestCase.fixture_path, table_names, {}, &block)
end
end
+
+# silence verbose schema loading
+original_stdout = $stdout
+$stdout = StringIO.new
+
+begin
+ adapter_name = ActiveRecord::Base.connection.adapter_name.downcase
+ adapter_specific_schema_file = SCHEMA_ROOT + "/#{adapter_name}_specific_schema.rb"
+
+ load SCHEMA_ROOT + "/schema.rb"
+
+ if File.exists?(adapter_specific_schema_file)
+ load adapter_specific_schema_file
+ end
+ensure
+ $stdout = original_stdout
+end
diff --git a/activerecord/test/cases/json_serialization_test.rb b/activerecord/test/cases/json_serialization_test.rb
index 975acde096..0ffbc9bf3b 100644
--- a/activerecord/test/cases/json_serialization_test.rb
+++ b/activerecord/test/cases/json_serialization_test.rb
@@ -26,19 +26,19 @@ class JsonSerializationTest < ActiveRecord::TestCase
NamespacedContact.include_root_in_json = true
@contact = NamespacedContact.new :name => 'whatever'
json = @contact.to_json
- assert_match %r{^\{"namespaced_contact": \{}, json
+ assert_match %r{^\{"namespaced_contact":\{}, json
end
def test_should_include_root_in_json
Contact.include_root_in_json = true
json = @contact.to_json
- assert_match %r{^\{"contact": \{}, json
- assert_match %r{"name": "Konata Izumi"}, json
- assert_match %r{"age": 16}, json
- assert json.include?(%("created_at": #{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
- assert_match %r{"awesome": true}, json
- assert_match %r{"preferences": \{"shows": "anime"\}}, json
+ assert_match %r{^\{"contact":\{}, json
+ assert_match %r{"name":"Konata Izumi"}, json
+ assert_match %r{"age":16}, json
+ assert json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
+ assert_match %r{"awesome":true}, json
+ assert_match %r{"preferences":\{"shows":"anime"\}}, json
ensure
Contact.include_root_in_json = false
end
@@ -46,31 +46,31 @@ class JsonSerializationTest < ActiveRecord::TestCase
def test_should_encode_all_encodable_attributes
json = @contact.to_json
- assert_match %r{"name": "Konata Izumi"}, json
- assert_match %r{"age": 16}, json
- assert json.include?(%("created_at": #{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
- assert_match %r{"awesome": true}, json
- assert_match %r{"preferences": \{"shows": "anime"\}}, json
+ assert_match %r{"name":"Konata Izumi"}, json
+ assert_match %r{"age":16}, json
+ assert json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
+ assert_match %r{"awesome":true}, json
+ assert_match %r{"preferences":\{"shows":"anime"\}}, json
end
def test_should_allow_attribute_filtering_with_only
json = @contact.to_json(:only => [:name, :age])
- assert_match %r{"name": "Konata Izumi"}, json
- assert_match %r{"age": 16}, json
- assert_no_match %r{"awesome": true}, json
- assert !json.include?(%("created_at": #{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
- assert_no_match %r{"preferences": \{"shows": "anime"\}}, json
+ assert_match %r{"name":"Konata Izumi"}, json
+ assert_match %r{"age":16}, json
+ assert_no_match %r{"awesome":true}, json
+ assert !json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
+ assert_no_match %r{"preferences":\{"shows":"anime"\}}, json
end
def test_should_allow_attribute_filtering_with_except
json = @contact.to_json(:except => [:name, :age])
- assert_no_match %r{"name": "Konata Izumi"}, json
- assert_no_match %r{"age": 16}, json
- assert_match %r{"awesome": true}, json
- assert json.include?(%("created_at": #{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
- assert_match %r{"preferences": \{"shows": "anime"\}}, json
+ assert_no_match %r{"name":"Konata Izumi"}, json
+ assert_no_match %r{"age":16}, json
+ assert_match %r{"awesome":true}, json
+ assert json.include?(%("created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
+ assert_match %r{"preferences":\{"shows":"anime"\}}, json
end
def test_methods_are_called_on_object
@@ -79,12 +79,12 @@ class JsonSerializationTest < ActiveRecord::TestCase
def @contact.favorite_quote; "Constraints are liberating"; end
# Single method.
- assert_match %r{"label": "Has cheezburger"}, @contact.to_json(:only => :name, :methods => :label)
+ assert_match %r{"label":"Has cheezburger"}, @contact.to_json(:only => :name, :methods => :label)
# Both methods.
methods_json = @contact.to_json(:only => :name, :methods => [:label, :favorite_quote])
- assert_match %r{"label": "Has cheezburger"}, methods_json
- assert_match %r{"favorite_quote": "Constraints are liberating"}, methods_json
+ assert_match %r{"label":"Has cheezburger"}, methods_json
+ assert_match %r{"favorite_quote":"Constraints are liberating"}, methods_json
end
end
@@ -99,42 +99,42 @@ class DatabaseConnectedJsonEncodingTest < ActiveRecord::TestCase
def test_includes_uses_association_name
json = @david.to_json(:include => :posts)
- assert_match %r{"posts": \[}, json
+ assert_match %r{"posts":\[}, json
- assert_match %r{"id": 1}, json
- assert_match %r{"name": "David"}, json
+ assert_match %r{"id":1}, json
+ assert_match %r{"name":"David"}, json
- assert_match %r{"author_id": 1}, json
- assert_match %r{"title": "Welcome to the weblog"}, json
- assert_match %r{"body": "Such a lovely day"}, json
+ assert_match %r{"author_id":1}, json
+ assert_match %r{"title":"Welcome to the weblog"}, json
+ assert_match %r{"body":"Such a lovely day"}, json
- assert_match %r{"title": "So I was thinking"}, json
- assert_match %r{"body": "Like I hopefully always am"}, json
+ assert_match %r{"title":"So I was thinking"}, json
+ assert_match %r{"body":"Like I hopefully always am"}, json
end
def test_includes_uses_association_name_and_applies_attribute_filters
json = @david.to_json(:include => { :posts => { :only => :title } })
- assert_match %r{"name": "David"}, json
- assert_match %r{"posts": \[}, json
+ assert_match %r{"name":"David"}, json
+ assert_match %r{"posts":\[}, json
- assert_match %r{"title": "Welcome to the weblog"}, json
- assert_no_match %r{"body": "Such a lovely day"}, json
+ assert_match %r{"title":"Welcome to the weblog"}, json
+ assert_no_match %r{"body":"Such a lovely day"}, json
- assert_match %r{"title": "So I was thinking"}, json
- assert_no_match %r{"body": "Like I hopefully always am"}, json
+ assert_match %r{"title":"So I was thinking"}, json
+ assert_no_match %r{"body":"Like I hopefully always am"}, json
end
def test_includes_fetches_second_level_associations
json = @david.to_json(:include => { :posts => { :include => { :comments => { :only => :body } } } })
- assert_match %r{"name": "David"}, json
- assert_match %r{"posts": \[}, json
+ assert_match %r{"name":"David"}, json
+ assert_match %r{"posts":\[}, json
- assert_match %r{"comments": \[}, json
- assert_match %r{\{"body": "Thank you again for the welcome"\}}, json
- assert_match %r{\{"body": "Don't think too hard"\}}, json
- assert_no_match %r{"post_id": }, json
+ assert_match %r{"comments":\[}, json
+ assert_match %r{\{"body":"Thank you again for the welcome"\}}, json
+ assert_match %r{\{"body":"Don't think too hard"\}}, json
+ assert_no_match %r{"post_id":}, json
end
def test_includes_fetches_nth_level_associations
@@ -151,11 +151,11 @@ class DatabaseConnectedJsonEncodingTest < ActiveRecord::TestCase
}
})
- assert_match %r{"name": "David"}, json
- assert_match %r{"posts": \[}, json
+ assert_match %r{"name":"David"}, json
+ assert_match %r{"posts":\[}, json
- assert_match %r{"taggings": \[}, json
- assert_match %r{"tag": \{"name": "General"\}}, json
+ assert_match %r{"taggings":\[}, json
+ assert_match %r{"tag":\{"name":"General"\}}, json
end
def test_should_not_call_methods_on_associations_that_dont_respond
@@ -163,20 +163,20 @@ class DatabaseConnectedJsonEncodingTest < ActiveRecord::TestCase
json = @david.to_json(:include => :posts, :methods => :favorite_quote)
assert !@david.posts.first.respond_to?(:favorite_quote)
- assert_match %r{"favorite_quote": "Constraints are liberating"}, json
- assert_equal %r{"favorite_quote": }.match(json).size, 1
+ assert_match %r{"favorite_quote":"Constraints are liberating"}, json
+ assert_equal %r{"favorite_quote":}.match(json).size, 1
end
def test_should_allow_only_option_for_list_of_authors
authors = [@david, @mary]
- assert_equal %([{"name": "David"}, {"name": "Mary"}]), authors.to_json(:only => :name)
+ assert_equal %([{"name":"David"},{"name":"Mary"}]), authors.to_json(:only => :name)
end
def test_should_allow_except_option_for_list_of_authors
authors = [@david, @mary]
- assert_equal %([{"id": 1}, {"id": 2}]), authors.to_json(:except => [:name, :author_address_id, :author_address_extra_id])
+ assert_equal %([{"id":1},{"id":2}]), authors.to_json(:except => [:name, :author_address_id, :author_address_extra_id])
end
def test_should_allow_includes_for_list_of_authors
@@ -188,8 +188,8 @@ class DatabaseConnectedJsonEncodingTest < ActiveRecord::TestCase
}
)
- ['"name": "David"', '"posts": [', '{"id": 1}', '{"id": 2}', '{"id": 4}',
- '{"id": 5}', '{"id": 6}', '"name": "Mary"', '"posts": [{"id": 7}]'].each do |fragment|
+ ['"name":"David"', '"posts":[', '{"id":1}', '{"id":2}', '{"id":4}',
+ '{"id":5}', '{"id":6}', '"name":"Mary"', '"posts":[{"id":7}]'].each do |fragment|
assert json.include?(fragment), json
end
end
@@ -200,6 +200,6 @@ class DatabaseConnectedJsonEncodingTest < ActiveRecord::TestCase
2 => @mary
}
- assert_equal %({"1": {"name": "David"}}), authors_hash.to_json(:only => [1, :name])
+ assert_equal %({"1":{"name":"David"}}), authors_hash.to_json(:only => [1, :name])
end
end
diff --git a/activerecord/test/cases/method_scoping_test.rb b/activerecord/test/cases/method_scoping_test.rb
index 3c34cdeade..d8246f49b8 100644
--- a/activerecord/test/cases/method_scoping_test.rb
+++ b/activerecord/test/cases/method_scoping_test.rb
@@ -1,9 +1,9 @@
require "cases/helper"
+require 'models/post'
require 'models/author'
require 'models/developer'
require 'models/project'
require 'models/comment'
-require 'models/post'
require 'models/category'
class MethodScopingTest < ActiveRecord::TestCase
@@ -591,6 +591,16 @@ class DefaultScopingTest < ActiveRecord::TestCase
assert_equal expected, received
end
+ def test_default_scope_with_conditions_string
+ assert_equal Developer.find_all_by_name('David').map(&:id).sort, DeveloperCalledDavid.all.map(&:id).sort
+ assert_equal nil, DeveloperCalledDavid.create!.name
+ end
+
+ def test_default_scope_with_conditions_hash
+ assert_equal Developer.find_all_by_name('Jamis').map(&:id).sort, DeveloperCalledJamis.all.map(&:id).sort
+ assert_equal 'Jamis', DeveloperCalledJamis.create!.name
+ end
+
def test_default_scoping_with_threads
scope = [{ :create => {}, :find => { :order => 'salary DESC' } }]
@@ -628,9 +638,9 @@ class DefaultScopingTest < ActiveRecord::TestCase
assert_equal expected, received
end
- def test_named_scope
- expected = Developer.find(:all, :order => 'salary DESC, name DESC').collect { |dev| dev.salary }
- received = DeveloperOrderedBySalary.by_name.find(:all).collect { |dev| dev.salary }
+ def test_named_scope_overwrites_default
+ expected = Developer.find(:all, :order => 'name 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/named_scope_test.rb b/activerecord/test/cases/named_scope_test.rb
index ae6a54a5bd..92fe48cb5a 100644
--- a/activerecord/test/cases/named_scope_test.rb
+++ b/activerecord/test/cases/named_scope_test.rb
@@ -1,4 +1,5 @@
require "cases/helper"
+require 'active_support/core_ext/array/random_access'
require 'models/post'
require 'models/topic'
require 'models/comment'
@@ -234,6 +235,40 @@ class NamedScopeTest < ActiveRecord::TestCase
assert_no_queries { assert topics.any? }
end
+ def test_many_should_not_load_results
+ topics = Topic.base
+ assert_queries(2) do
+ topics.many? # use count query
+ topics.collect # force load
+ topics.many? # use loaded (no query)
+ end
+ end
+
+ def test_many_should_call_proxy_found_if_using_a_block
+ topics = Topic.base
+ assert_queries(1) do
+ topics.expects(:size).never
+ topics.many? { true }
+ end
+ end
+
+ def test_many_should_not_fire_query_if_named_scope_loaded
+ topics = Topic.base
+ topics.collect # force load
+ assert_no_queries { assert topics.many? }
+ end
+
+ def test_many_should_return_false_if_none_or_one
+ topics = Topic.base.scoped(:conditions => {:id => 0})
+ assert !topics.many?
+ topics = Topic.base.scoped(:conditions => {:id => 1})
+ assert !topics.many?
+ end
+
+ def test_many_should_return_true_if_more_than_one
+ assert Topic.base.many?
+ end
+
def test_should_build_with_proxy_options
topic = Topic.approved.build({})
assert topic.approved
@@ -265,7 +300,7 @@ class NamedScopeTest < ActiveRecord::TestCase
end
def test_rand_should_select_a_random_object_from_proxy
- assert Topic.approved.rand.is_a?(Topic)
+ assert_kind_of Topic, Topic.approved.rand
end
def test_should_use_where_in_query_for_named_scope
@@ -338,7 +373,7 @@ class NamedScopeTest < ActiveRecord::TestCase
end
end
-class DynamicScopeMatchTest < ActiveRecord::TestCase
+class DynamicScopeMatchTest < ActiveRecord::TestCase
def test_scoped_by_no_match
assert_nil ActiveRecord::DynamicScopeMatch.match("not_scoped_at_all")
end
@@ -352,6 +387,8 @@ class DynamicScopeMatchTest < ActiveRecord::TestCase
end
class DynamicScopeTest < ActiveRecord::TestCase
+ fixtures :posts
+
def test_dynamic_scope
assert_equal Post.scoped_by_author_id(1).find(1), Post.find(1)
assert_equal Post.scoped_by_author_id_and_title(1, "Welcome to the weblog").first, Post.find(:first, :conditions => { :author_id => 1, :title => "Welcome to the weblog"})
diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb
index cd6277c24b..f31275163d 100644
--- a/activerecord/test/cases/nested_attributes_test.rb
+++ b/activerecord/test/cases/nested_attributes_test.rb
@@ -4,6 +4,7 @@ require "models/ship"
require "models/bird"
require "models/parrot"
require "models/treasure"
+require 'active_support/hash_with_indifferent_access'
module AssertRaiseWithMessage
def assert_raise_with_message(expected_exception, expected_message)
@@ -31,11 +32,27 @@ class TestNestedAttributesInGeneral < ActiveRecord::TestCase
end
def test_should_add_a_proc_to_reject_new_nested_attributes_procs
- [:parrots, :birds].each do |name|
+ [:parrots, :birds, :birds_with_reject_all_blank].each do |name|
assert_instance_of Proc, Pirate.reject_new_nested_attributes_procs[name]
end
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 => ''}]
+ pirate.save!
+
+ assert pirate.birds_with_reject_all_blank.empty?
+ end
+
+ def test_should_build_a_new_record_if_reject_all_blank_does_not_return_false
+ pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?")
+ pirate.birds_with_reject_all_blank_attributes = [{:name => 'Tweetie', :color => ''}]
+ pirate.save!
+
+ assert_equal 1, pirate.birds_with_reject_all_blank.count
+ end
+
def test_should_raise_an_ArgumentError_for_non_existing_associations
assert_raise_with_message ArgumentError, "No association found for name `honesty'. Has it been defined yet?" do
Pirate.accepts_nested_attributes_for :honesty
diff --git a/activerecord/test/cases/pooled_connections_test.rb b/activerecord/test/cases/pooled_connections_test.rb
index 2649a9358a..bb9013c2a1 100644
--- a/activerecord/test/cases/pooled_connections_test.rb
+++ b/activerecord/test/cases/pooled_connections_test.rb
@@ -1,4 +1,6 @@
require "cases/helper"
+require "models/project"
+require "timeout"
class PooledConnectionsTest < ActiveRecord::TestCase
def setup
@@ -89,6 +91,33 @@ class PooledConnectionsTest < ActiveRecord::TestCase
ensure
ActiveRecord::Base.connection_handler = old_handler
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.join rescue nil
+ add_record('three')
+ end
+
+ after_count = Project.count
+ assert_equal 3, after_count - before_count
+ end
+
+ private
+
+ 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
diff --git a/activerecord/test/cases/repair_helper.rb b/activerecord/test/cases/repair_helper.rb
index 0155668811..80d04010d6 100644
--- a/activerecord/test/cases/repair_helper.rb
+++ b/activerecord/test/cases/repair_helper.rb
@@ -1,11 +1,7 @@
module ActiveRecord
module Testing
module RepairHelper
- def self.included(base)
- base.class_eval do
- extend ClassMethods
- end
- end
+ extend ActiveSupport::Concern
module Toolbox
def self.record_validations(*model_classes)
diff --git a/activerecord/test/cases/validations/i18n_validation_test.rb b/activerecord/test/cases/validations/i18n_validation_test.rb
index 4b34a65bb7..0303147e50 100644
--- a/activerecord/test/cases/validations/i18n_validation_test.rb
+++ b/activerecord/test/cases/validations/i18n_validation_test.rb
@@ -38,12 +38,21 @@ class I18nValidationTest < ActiveRecord::TestCase
end
end
- def test_default_error_messages_is_deprecated
- assert_deprecated('Errors.default_error_messages') do
- ActiveRecord::Errors.default_error_messages
+ def test_percent_s_interpolation_syntax_in_error_messages_was_deprecated
+ assert_not_deprecated do
+ default = "%s interpolation syntax was deprecated"
+ assert_equal default, I18n.t(:does_not_exist, :default => default, :value => 'this')
end
end
+ def test_percent_d_interpolation_syntax_in_error_messages_was_deprecated
+ assert_not_deprecated do
+ default = "%d interpolation syntaxes are deprecated"
+ assert_equal default, I18n.t(:does_not_exist, :default => default, :count => 2)
+ end
+ end
+
+ # ActiveRecord::Errors
def test_errors_generate_message_translates_custom_model_attribute_key
I18n.expects(:translate).with(
:topic,
diff --git a/activerecord/test/fixtures/faces.yml b/activerecord/test/fixtures/faces.yml
new file mode 100644
index 0000000000..1dd2907cf7
--- /dev/null
+++ b/activerecord/test/fixtures/faces.yml
@@ -0,0 +1,7 @@
+trusting:
+ description: trusting
+ man: gordon
+
+weather_beaten:
+ description: weather beaten
+ man: steve
diff --git a/activerecord/test/fixtures/interests.yml b/activerecord/test/fixtures/interests.yml
new file mode 100644
index 0000000000..ec71890ab6
--- /dev/null
+++ b/activerecord/test/fixtures/interests.yml
@@ -0,0 +1,29 @@
+trainspotting:
+ topic: Trainspotting
+ zine: staying_in
+ man: gordon
+
+birdwatching:
+ topic: Birdwatching
+ zine: staying_in
+ man: gordon
+
+stamp_collecting:
+ topic: Stamp Collecting
+ zine: staying_in
+ man: gordon
+
+hunting:
+ topic: Hunting
+ zine: going_out
+ man: steve
+
+woodsmanship:
+ topic: Woodsmanship
+ zine: going_out
+ man: steve
+
+survial:
+ topic: Survival
+ zine: going_out
+ man: steve
diff --git a/activerecord/test/fixtures/men.yml b/activerecord/test/fixtures/men.yml
new file mode 100644
index 0000000000..c67429f925
--- /dev/null
+++ b/activerecord/test/fixtures/men.yml
@@ -0,0 +1,5 @@
+gordon:
+ name: Gordon
+
+steve:
+ name: Steve
diff --git a/activerecord/test/fixtures/people.yml b/activerecord/test/fixtures/people.yml
index 3babb1fe59..123673a2af 100644
--- a/activerecord/test/fixtures/people.yml
+++ b/activerecord/test/fixtures/people.yml
@@ -2,14 +2,17 @@ michael:
id: 1
first_name: Michael
primary_contact_id: 2
+ number1_fan_id: 3
gender: M
david:
id: 2
first_name: David
primary_contact_id: 3
+ number1_fan_id: 1
gender: M
susan:
id: 3
first_name: Susan
primary_contact_id: 2
- gender: F \ No newline at end of file
+ number1_fan_id: 1
+ gender: F
diff --git a/activerecord/test/fixtures/zines.yml b/activerecord/test/fixtures/zines.yml
new file mode 100644
index 0000000000..07dce4db7e
--- /dev/null
+++ b/activerecord/test/fixtures/zines.yml
@@ -0,0 +1,5 @@
+staying_in:
+ title: Staying in '08
+
+going_out:
+ title: Outdoor Pursuits 2k+8
diff --git a/activerecord/test/models/company_in_module.rb b/activerecord/test/models/company_in_module.rb
index 1122c7256f..8b84c2fb5e 100644
--- a/activerecord/test/models/company_in_module.rb
+++ b/activerecord/test/models/company_in_module.rb
@@ -1,3 +1,5 @@
+require 'active_support/core_ext/object/misc'
+
module MyApplication
module Business
class Company < ActiveRecord::Base
diff --git a/activerecord/test/models/developer.rb b/activerecord/test/models/developer.rb
index 92039a4f54..058970336b 100644
--- a/activerecord/test/models/developer.rb
+++ b/activerecord/test/models/developer.rb
@@ -89,3 +89,13 @@ class DeveloperOrderedBySalary < ActiveRecord::Base
end
end
end
+
+class DeveloperCalledDavid < ActiveRecord::Base
+ self.table_name = 'developers'
+ default_scope :conditions => "name = 'David'"
+end
+
+class DeveloperCalledJamis < ActiveRecord::Base
+ self.table_name = 'developers'
+ default_scope :conditions => { :name => 'Jamis' }
+end
diff --git a/activerecord/test/models/face.rb b/activerecord/test/models/face.rb
new file mode 100644
index 0000000000..1540dbf741
--- /dev/null
+++ b/activerecord/test/models/face.rb
@@ -0,0 +1,5 @@
+class Face < ActiveRecord::Base
+ belongs_to :man, :inverse_of => :face
+ # This is a "broken" inverse_of for the purposes of testing
+ belongs_to :horrible_man, :class_name => 'Man', :inverse_of => :horrible_face
+end
diff --git a/activerecord/test/models/interest.rb b/activerecord/test/models/interest.rb
new file mode 100644
index 0000000000..d8291d00cc
--- /dev/null
+++ b/activerecord/test/models/interest.rb
@@ -0,0 +1,4 @@
+class Interest < ActiveRecord::Base
+ belongs_to :man, :inverse_of => :interests
+ belongs_to :zine, :inverse_of => :interests
+end
diff --git a/activerecord/test/models/man.rb b/activerecord/test/models/man.rb
new file mode 100644
index 0000000000..f40bc9d0fc
--- /dev/null
+++ b/activerecord/test/models/man.rb
@@ -0,0 +1,7 @@
+class Man < ActiveRecord::Base
+ has_one :face, :inverse_of => :man
+ has_many :interests, :inverse_of => :man
+ # These are "broken" inverse_of associations for the purposes of testing
+ has_one :dirty_face, :class_name => 'Face', :inverse_of => :dirty_man
+ has_many :secret_interests, :class_name => 'Interest', :inverse_of => :secret_man
+end
diff --git a/activerecord/test/models/person.rb b/activerecord/test/models/person.rb
index ec2f684a6e..57fa6418f1 100644
--- a/activerecord/test/models/person.rb
+++ b/activerecord/test/models/person.rb
@@ -10,6 +10,7 @@ class Person < ActiveRecord::Base
belongs_to :primary_contact, :class_name => 'Person'
has_many :agents, :class_name => 'Person', :foreign_key => 'primary_contact_id'
+ belongs_to :number1_fan, :class_name => 'Person'
named_scope :males, :conditions => { :gender => 'M' }
named_scope :females, :conditions => { :gender => 'F' }
diff --git a/activerecord/test/models/pirate.rb b/activerecord/test/models/pirate.rb
index 238917bf30..acf53fce8b 100644
--- a/activerecord/test/models/pirate.rb
+++ b/activerecord/test/models/pirate.rb
@@ -28,11 +28,13 @@ class Pirate < ActiveRecord::Base
:after_add => proc {|p,b| p.ship_log << "after_adding_proc_bird_#{b.id || '<new>'}"},
:before_remove => proc {|p,b| p.ship_log << "before_removing_proc_bird_#{b.id}"},
:after_remove => proc {|p,b| p.ship_log << "after_removing_proc_bird_#{b.id}"}
+ has_many :birds_with_reject_all_blank, :class_name => "Bird"
accepts_nested_attributes_for :parrots, :birds, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
accepts_nested_attributes_for :ship, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? }
accepts_nested_attributes_for :parrots_with_method_callbacks, :parrots_with_proc_callbacks,
:birds_with_method_callbacks, :birds_with_proc_callbacks, :allow_destroy => true
+ accepts_nested_attributes_for :birds_with_reject_all_blank, :reject_if => :all_blank
validates_presence_of :catchphrase
diff --git a/activerecord/test/models/zine.rb b/activerecord/test/models/zine.rb
new file mode 100644
index 0000000000..c2d0fdaf25
--- /dev/null
+++ b/activerecord/test/models/zine.rb
@@ -0,0 +1,3 @@
+class Zine < ActiveRecord::Base
+ has_many :interests, :inverse_of => :zine
+end
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index 98e6d192a5..6e8813d8ab 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -1,4 +1,3 @@
-
ActiveRecord::Schema.define do
def except(adapter_names_to_exclude)
unless [adapter_names_to_exclude].flatten.include?(adapter_name)
@@ -57,6 +56,7 @@ ActiveRecord::Schema.define do
create_table :birds, :force => true do |t|
t.string :name
+ t.string :color
t.integer :pirate_id
end
@@ -324,6 +324,7 @@ ActiveRecord::Schema.define do
t.string :first_name, :null => false
t.references :primary_contact
t.string :gender, :limit => 1
+ t.references :number1_fan
t.integer :lock_version, :null => false, :default => 0
end
@@ -467,6 +468,26 @@ ActiveRecord::Schema.define do
end
end
+ # NOTE - the following 4 tables are used by models that have :inverse_of options on the associations
+ create_table :men, :force => true do |t|
+ t.string :name
+ end
+
+ create_table :faces, :force => true do |t|
+ t.string :description
+ t.integer :man_id
+ end
+
+ create_table :interests, :force => true do |t|
+ t.string :topic
+ t.integer :man_id
+ t.integer :zine_id
+ end
+
+ create_table :zines, :force => true do |t|
+ t.string :title
+ end
+
except 'SQLite' do
# fk_test_has_fk should be before fk_test_has_pk
create_table :fk_test_has_fk, :force => true do |t|
@@ -479,3 +500,7 @@ ActiveRecord::Schema.define do
execute "ALTER TABLE fk_test_has_fk ADD CONSTRAINT fk_name FOREIGN KEY (#{quote_column_name 'fk_id'}) REFERENCES #{quote_table_name 'fk_test_has_pk'} (#{quote_column_name 'id'})"
end
end
+
+Course.connection.create_table :courses, :force => true do |t|
+ t.column :name, :string, :null => false
+end
diff --git a/activerecord/test/schema/schema2.rb b/activerecord/test/schema/schema2.rb
deleted file mode 100644
index 8527f7ba8f..0000000000
--- a/activerecord/test/schema/schema2.rb
+++ /dev/null
@@ -1,6 +0,0 @@
-ActiveRecord::Schema.define do
-
- Course.connection.create_table :courses, :force => true do |t|
- t.column :name, :string, :null => false
- end
-end