diff options
Diffstat (limited to 'activerecord/test')
32 files changed, 524 insertions, 51 deletions
diff --git a/activerecord/test/cases/adapters/mysql2/bind_parameter_test.rb b/activerecord/test/cases/adapters/mysql2/bind_parameter_test.rb new file mode 100644 index 0000000000..cd9c1041dc --- /dev/null +++ b/activerecord/test/cases/adapters/mysql2/bind_parameter_test.rb @@ -0,0 +1,50 @@ +require "cases/helper" +require 'models/topic' + +module ActiveRecord + module ConnectionAdapters + class Mysql2Adapter + class BindParameterTest < ActiveRecord::TestCase + fixtures :topics + + def test_update_question_marks + str = "foo?bar" + x = Topic.find :first + x.title = str + x.content = str + x.save! + x.reload + assert_equal str, x.title + assert_equal str, x.content + end + + def test_create_question_marks + str = "foo?bar" + x = Topic.create!(:title => str, :content => str) + x.reload + assert_equal str, x.title + assert_equal str, x.content + end + + def test_update_null_bytes + str = "foo\0bar" + x = Topic.find :first + x.title = str + x.content = str + x.save! + x.reload + assert_equal str, x.title + assert_equal str, x.content + end + + def test_create_null_bytes + str = "foo\0bar" + x = Topic.create!(:title => str, :content => str) + x.reload + assert_equal str, x.title + assert_equal str, x.content + end + end + end + end +end diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb index ddcc36c841..b993bf6e90 100644 --- a/activerecord/test/cases/associations/belongs_to_associations_test.rb +++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb @@ -626,4 +626,25 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase assert_equal "Bob", firm.name end + + def test_build_with_block + client = Client.create(:name => 'Client Company') + + firm = client.build_firm{ |f| f.name = 'Agency Company' } + assert_equal 'Agency Company', firm.name + end + + def test_create_with_block + client = Client.create(:name => 'Client Company') + + firm = client.create_firm{ |f| f.name = 'Agency Company' } + assert_equal 'Agency Company', firm.name + end + + def test_create_bang_with_block + client = Client.create(:name => 'Client Company') + + firm = client.create_firm!{ |f| f.name = 'Agency Company' } + assert_equal 'Agency Company', firm.name + end end diff --git a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb index 39e8a7960a..49d8722aff 100644 --- a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb +++ b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb @@ -51,7 +51,9 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase categories = Category.joins(:categorizations).includes([{:posts=>:comments}, :authors]) assert_nothing_raised do - assert_equal 3, categories.count + assert_equal 4, categories.count + assert_equal 4, categories.all.count + assert_equal 3, categories.count(:distinct => true) assert_equal 3, categories.all.uniq.size # Must uniq since instantiating with inner joins will get dupes end end diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index 247decc67b..522ac56d82 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -66,6 +66,63 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal 'exotic', bulb.name end + def test_create_from_association_with_nil_values_should_work + car = Car.create(:name => 'honda') + + bulb = car.bulbs.new(nil) + assert_equal 'defaulty', bulb.name + + bulb = car.bulbs.build(nil) + assert_equal 'defaulty', bulb.name + + bulb = car.bulbs.create(nil) + assert_equal 'defaulty', bulb.name + end + + def test_association_keys_bypass_attribute_protection + car = Car.create(:name => 'honda') + + bulb = car.bulbs.new + assert_equal car.id, bulb.car_id + + bulb = car.bulbs.new :car_id => car.id + 1 + assert_equal car.id, bulb.car_id + + bulb = car.bulbs.build + assert_equal car.id, bulb.car_id + + bulb = car.bulbs.build :car_id => car.id + 1 + assert_equal car.id, bulb.car_id + + bulb = car.bulbs.create + assert_equal car.id, bulb.car_id + + bulb = car.bulbs.create :car_id => car.id + 1 + assert_equal car.id, bulb.car_id + end + + def test_association_conditions_bypass_attribute_protection + car = Car.create(:name => 'honda') + + bulb = car.frickinawesome_bulbs.new + assert_equal true, bulb.frickinawesome? + + bulb = car.frickinawesome_bulbs.new(:frickinawesome => false) + assert_equal true, bulb.frickinawesome? + + bulb = car.frickinawesome_bulbs.build + assert_equal true, bulb.frickinawesome? + + bulb = car.frickinawesome_bulbs.build(:frickinawesome => false) + assert_equal true, bulb.frickinawesome? + + bulb = car.frickinawesome_bulbs.create + assert_equal true, bulb.frickinawesome? + + bulb = car.frickinawesome_bulbs.create(:frickinawesome => false) + assert_equal true, bulb.frickinawesome? + end + # When creating objects on the association, we must not do it within a scope (even though it # would be convenient), because this would cause that scope to be applied to any callbacks etc. def test_build_and_create_should_not_happen_within_scope @@ -1388,4 +1445,27 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_not_equal target.object_id, ary.object_id end + + def test_merging_with_custom_attribute_writer + bulb = Bulb.new(:color => "red") + assert_equal "RED!", bulb.color + + car = Car.create! + car.bulbs << bulb + + assert_equal "RED!", car.bulbs.to_a.first.color + end + + def test_new_is_called_with_attributes_and_options + car = Car.create(:name => 'honda') + + bulb = car.bulbs.build + assert_equal Bulb, bulb.class + + bulb = car.bulbs.build(:bulb_type => :custom) + assert_equal Bulb, bulb.class + + bulb = car.bulbs.build({ :bulb_type => :custom }, :as => :admin) + assert_equal CustomBulb, bulb.class + end end diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb index f3c96ccbe6..f3bf5baa95 100644 --- a/activerecord/test/cases/associations/has_one_associations_test.rb +++ b/activerecord/test/cases/associations/has_one_associations_test.rb @@ -4,6 +4,7 @@ require 'models/project' require 'models/company' require 'models/ship' require 'models/pirate' +require 'models/car' require 'models/bulb' class HasOneAssociationsTest < ActiveRecord::TestCase @@ -95,6 +96,15 @@ class HasOneAssociationsTest < ActiveRecord::TestCase assert_nil Account.find(old_account_id).firm_id end + def test_natural_assignment_to_nil_after_destroy + firm = companies(:rails_core) + old_account_id = firm.account.id + firm.account.destroy + firm.account = nil + assert_nil companies(:rails_core).account + assert_raise(ActiveRecord::RecordNotFound) { Account.find(old_account_id) } + end + def test_association_change_calls_delete companies(:first_firm).deletable_account = Account.new(:credit_limit => 5) assert_equal [], Account.destroyed_account_ids[companies(:first_firm).id] @@ -359,4 +369,82 @@ class HasOneAssociationsTest < ActiveRecord::TestCase assert_equal pirate.id, ships(:black_pearl).reload.pirate_id assert_nil new_ship.pirate_id end + + def test_deprecated_association_loaded + firm = companies(:first_firm) + firm.association(:account).stubs(:loaded?).returns(stub) + + assert_deprecated do + assert_equal firm.association(:account).loaded?, firm.account_loaded? + end + end + + def test_association_keys_bypass_attribute_protection + car = Car.create(:name => 'honda') + + bulb = car.build_bulb + assert_equal car.id, bulb.car_id + + bulb = car.build_bulb :car_id => car.id + 1 + assert_equal car.id, bulb.car_id + + bulb = car.create_bulb + assert_equal car.id, bulb.car_id + + bulb = car.create_bulb :car_id => car.id + 1 + assert_equal car.id, bulb.car_id + end + + def test_association_conditions_bypass_attribute_protection + car = Car.create(:name => 'honda') + + bulb = car.build_frickinawesome_bulb + assert_equal true, bulb.frickinawesome? + + bulb = car.build_frickinawesome_bulb(:frickinawesome => false) + assert_equal true, bulb.frickinawesome? + + bulb = car.create_frickinawesome_bulb + assert_equal true, bulb.frickinawesome? + + bulb = car.create_frickinawesome_bulb(:frickinawesome => false) + assert_equal true, bulb.frickinawesome? + end + + def test_new_is_called_with_attributes_and_options + car = Car.create(:name => 'honda') + + bulb = car.build_bulb + assert_equal Bulb, bulb.class + + bulb = car.build_bulb + assert_equal Bulb, bulb.class + + bulb = car.build_bulb(:bulb_type => :custom) + assert_equal Bulb, bulb.class + + bulb = car.build_bulb({ :bulb_type => :custom }, :as => :admin) + assert_equal CustomBulb, bulb.class + end + + def test_build_with_block + car = Car.create(:name => 'honda') + + bulb = car.build_bulb{ |b| b.color = 'Red' } + assert_equal 'RED!', bulb.color + end + + def test_create_with_block + car = Car.create(:name => 'honda') + + bulb = car.create_bulb{ |b| b.color = 'Red' } + assert_equal 'RED!', bulb.color + end + + def test_create_bang_with_block + car = Car.create(:name => 'honda') + + bulb = car.create_bulb!{ |b| b.color = 'Red' } + assert_equal 'RED!', bulb.color + end 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 968025ade8..2503349c08 100644 --- a/activerecord/test/cases/associations/has_one_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_one_through_associations_test.rb @@ -310,4 +310,8 @@ class HasOneThroughAssociationsTest < ActiveRecord::TestCase assert_equal dashboard, minivan.dashboard assert_equal dashboard, minivan.speedometer.dashboard end + + def test_has_one_through_with_custom_select_on_join_model_default_scope + assert_equal clubs(:boring_club), members(:groucho).selected_club + end end diff --git a/activerecord/test/cases/associations/inner_join_association_test.rb b/activerecord/test/cases/associations/inner_join_association_test.rb index 124693f7c9..e5e9ca6131 100644 --- a/activerecord/test/cases/associations/inner_join_association_test.rb +++ b/activerecord/test/cases/associations/inner_join_association_test.rb @@ -2,6 +2,7 @@ require "cases/helper" require 'models/post' require 'models/comment' require 'models/author' +require 'models/essay' require 'models/category' require 'models/categorization' require 'models/person' @@ -9,7 +10,7 @@ require 'models/tagging' require 'models/tag' class InnerJoinAssociationTest < ActiveRecord::TestCase - fixtures :authors, :posts, :comments, :categories, :categories_posts, :categorizations, + fixtures :authors, :essays, :posts, :comments, :categories, :categories_posts, :categorizations, :taggings, :tags def test_construct_finder_sql_applies_aliases_tables_on_association_conditions diff --git a/activerecord/test/cases/associations/join_model_test.rb b/activerecord/test/cases/associations/join_model_test.rb index 49a1c117bc..8e23ab78be 100644 --- a/activerecord/test/cases/associations/join_model_test.rb +++ b/activerecord/test/cases/associations/join_model_test.rb @@ -13,6 +13,9 @@ require 'models/vertex' require 'models/edge' require 'models/book' require 'models/citation' +require 'models/aircraft' +require 'models/engine' +require 'models/car' class AssociationsJoinModelTest < ActiveRecord::TestCase self.use_transactional_fixtures = false unless supports_savepoints? @@ -704,6 +707,15 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase assert_equal [9, 10, new_comment.id], authors(:david).sti_post_comments.map(&:id).sort end + def test_has_many_with_pluralize_table_names_false + engine = Engine.create(:car_id => 1) + Aircraft.pluralize_table_names = false + aircraft = Aircraft.create!(:name => "Airbus 380", :id => 1) + assert_equal aircraft.engines, [engine] + ensure + ActiveRecord::Base.pluralize_table_names = true + end + private # create dynamic Post models to allow different dependency options def find_post_with_dependency(post_id, association, association_name, dependency) diff --git a/activerecord/test/cases/associations_test.rb b/activerecord/test/cases/associations_test.rb index 04f628a398..49d82ba2df 100644 --- a/activerecord/test/cases/associations_test.rb +++ b/activerecord/test/cases/associations_test.rb @@ -85,7 +85,7 @@ class AssociationsTest < ActiveRecord::TestCase def test_should_construct_new_finder_sql_after_create person = Person.new :first_name => 'clark' - assert_equal [], person.readers.find(:all) + assert_equal [], person.readers.all person.save! reader = Reader.create! :person => person, :post => Post.new(:title => "foo", :body => "bar") assert person.readers.find(reader.id) diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index 1775ba9999..bfb66f07da 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -45,6 +45,10 @@ class ReadonlyTitlePost < Post attr_readonly :title end +class ProtectedTitlePost < Post + attr_protected :title +end + class Weird < ActiveRecord::Base; end class Boolean < ActiveRecord::Base; end @@ -105,7 +109,7 @@ class BasicsTest < ActiveRecord::TestCase def test_select_symbol topic_ids = Topic.select(:id).map(&:id).sort - assert_equal Topic.find(:all).map(&:id).sort, topic_ids + assert_equal Topic.all.map(&:id).sort, topic_ids end def test_table_exists @@ -491,8 +495,9 @@ class BasicsTest < ActiveRecord::TestCase def test_attributes_guard_protected_attributes_is_deprecated attributes = { "title" => "An amazing title" } - topic = Topic.new - assert_deprecated { topic.send(:attributes=, attributes, false) } + post = ProtectedTitlePost.new + assert_deprecated { post.send(:attributes=, attributes, false) } + assert_equal "An amazing title", post.title end def test_multiparameter_attributes_on_date @@ -1785,4 +1790,17 @@ class BasicsTest < ActiveRecord::TestCase assert_equal expected.attributes, actual.attributes end + + def test_attribute_names + assert_equal ["id", "type", "ruby_type", "firm_id", "firm_name", "name", "client_of", "rating", "account_id"], + Company.attribute_names + end + + def test_attribute_names_on_table_not_exists + assert_equal [], NonExistentTable.attribute_names + end + + def test_attribtue_names_on_abstract_class + assert_equal [], AbstractCompany.attribute_names + end end diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index 654c4c9010..56f6d795b6 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -319,6 +319,17 @@ class CalculationsTest < ActiveRecord::TestCase assert_equal 4, Account.count(:distinct => true, :include => :firm, :select => :credit_limit) end + def test_should_not_perform_joined_include_by_default + assert_equal Account.count, Account.includes(:firm).count + queries = assert_sql { Account.includes(:firm).count } + assert_no_match(/join/i, queries.last) + end + + def test_should_perform_joined_include_when_referencing_included_tables + joined_count = Account.includes(:firm).where(:companies => {:name => '37signals'}).count + assert_equal 1, joined_count + end + def test_should_count_scoped_select Account.update_all("credit_limit = NULL") assert_equal 0, Account.scoped(:select => "credit_limit").count diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb index be4ba18555..4e75eafe3d 100644 --- a/activerecord/test/cases/finder_test.rb +++ b/activerecord/test/cases/finder_test.rb @@ -683,6 +683,27 @@ class FinderTest < ActiveRecord::TestCase assert_nil Topic.find_last_by_title_and_author_name(topic.title, "Anonymous") end + def test_find_last_with_limit_gives_same_result_when_loaded_and_unloaded + scope = Topic.limit(2) + unloaded_last = scope.last + loaded_last = scope.all.last + assert_equal loaded_last, unloaded_last + end + + def test_find_last_with_limit_and_offset_gives_same_result_when_loaded_and_unloaded + scope = Topic.offset(2).limit(2) + unloaded_last = scope.last + loaded_last = scope.all.last + assert_equal loaded_last, unloaded_last + end + + def test_find_last_with_offset_gives_same_result_when_loaded_and_unloaded + scope = Topic.offset(3) + unloaded_last = scope.last + loaded_last = scope.all.last + assert_equal loaded_last, unloaded_last + end + def test_find_all_by_one_attribute topics = Topic.find_all_by_content("Have a nice day") assert_equal 2, topics.size diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb index 2bf192e2c6..b0bd9c5763 100644 --- a/activerecord/test/cases/fixtures_test.rb +++ b/activerecord/test/cases/fixtures_test.rb @@ -175,7 +175,9 @@ class FixturesTest < ActiveRecord::TestCase end def test_empty_csv_fixtures - assert_not_nil ActiveRecord::Fixtures.new( Account.connection, "accounts", 'Account', FIXTURES_ROOT + "/naked/csv/accounts") + assert_deprecated do + assert_not_nil ActiveRecord::Fixtures.new( Account.connection, "accounts", 'Account', FIXTURES_ROOT + "/naked/csv/accounts") + end end def test_omap_fixtures diff --git a/activerecord/test/cases/locking_test.rb b/activerecord/test/cases/locking_test.rb index 636a709924..61baa55027 100644 --- a/activerecord/test/cases/locking_test.rb +++ b/activerecord/test/cases/locking_test.rb @@ -5,6 +5,7 @@ require 'models/job' require 'models/reader' require 'models/legacy_thing' require 'models/reference' +require 'models/string_key_object' class LockWithoutDefault < ActiveRecord::Base; end @@ -18,7 +19,40 @@ class ReadonlyFirstNamePerson < Person end class OptimisticLockingTest < ActiveRecord::TestCase - fixtures :people, :legacy_things, :references + fixtures :people, :legacy_things, :references, :string_key_objects + + def test_non_integer_lock_existing + s1 = StringKeyObject.find("record1") + s2 = StringKeyObject.find("record1") + assert_equal 0, s1.lock_version + assert_equal 0, s2.lock_version + + s1.name = 'updated record' + s1.save! + assert_equal 1, s1.lock_version + assert_equal 0, s2.lock_version + + s2.name = 'doubly updated record' + assert_raise(ActiveRecord::StaleObjectError) { s2.save! } + end + + def test_non_integer_lock_destroy + s1 = StringKeyObject.find("record1") + s2 = StringKeyObject.find("record1") + assert_equal 0, s1.lock_version + assert_equal 0, s2.lock_version + + s1.name = 'updated record' + s1.save! + assert_equal 1, s1.lock_version + assert_equal 0, s2.lock_version + assert_raise(ActiveRecord::StaleObjectError) { s2.destroy } + + assert s1.destroy + assert s1.frozen? + assert s1.destroyed? + assert_raises(ActiveRecord::RecordNotFound) { StringKeyObject.find("record1") } + end def test_lock_existing p1 = Person.find(1) diff --git a/activerecord/test/cases/mass_assignment_security_test.rb b/activerecord/test/cases/mass_assignment_security_test.rb index fbbae99e8b..765033852d 100644 --- a/activerecord/test/cases/mass_assignment_security_test.rb +++ b/activerecord/test/cases/mass_assignment_security_test.rb @@ -87,7 +87,11 @@ class MassAssignmentSecurityTest < ActiveRecord::TestCase end end - def test_assign_attributes_uses_default_scope_when_no_scope_is_provided + def test_mass_assigning_does_not_choke_on_nil + Firm.new.assign_attributes(nil) + end + + def test_assign_attributes_uses_default_role_when_no_role_is_provided p = LoosePerson.new p.assign_attributes(attributes_hash) @@ -101,28 +105,28 @@ class MassAssignmentSecurityTest < ActiveRecord::TestCase assert_all_attributes(p) end - def test_assign_attributes_with_default_scope_and_attr_protected_attributes + def test_assign_attributes_with_default_role_and_attr_protected_attributes p = LoosePerson.new p.assign_attributes(attributes_hash, :as => :default) assert_default_attributes(p) end - def test_assign_attributes_with_admin_scope_and_attr_protected_attributes + def test_assign_attributes_with_admin_role_and_attr_protected_attributes p = LoosePerson.new p.assign_attributes(attributes_hash, :as => :admin) assert_admin_attributes(p) end - def test_assign_attributes_with_default_scope_and_attr_accessible_attributes + def test_assign_attributes_with_default_role_and_attr_accessible_attributes p = TightPerson.new p.assign_attributes(attributes_hash, :as => :default) assert_default_attributes(p) end - def test_assign_attributes_with_admin_scope_and_attr_accessible_attributes + def test_assign_attributes_with_admin_role_and_attr_accessible_attributes p = TightPerson.new p.assign_attributes(attributes_hash, :as => :admin) @@ -153,30 +157,42 @@ class MassAssignmentSecurityTest < ActiveRecord::TestCase assert_default_attributes(p, true) end - def test_new_with_admin_scope_with_attr_accessible_attributes + def test_new_with_admin_role_with_attr_accessible_attributes p = TightPerson.new(attributes_hash, :as => :admin) assert_admin_attributes(p) end - def test_new_with_admin_scope_with_attr_protected_attributes + def test_new_with_admin_role_with_attr_protected_attributes p = LoosePerson.new(attributes_hash, :as => :admin) assert_admin_attributes(p) end - def test_create_with_admin_scope_with_attr_accessible_attributes + def test_create_with_admin_role_with_attr_accessible_attributes p = TightPerson.create(attributes_hash, :as => :admin) assert_admin_attributes(p, true) end - def test_create_with_admin_scope_with_attr_protected_attributes + def test_create_with_admin_role_with_attr_protected_attributes p = LoosePerson.create(attributes_hash, :as => :admin) assert_admin_attributes(p, true) end + def test_create_with_bang_with_admin_role_with_attr_accessible_attributes + p = TightPerson.create!(attributes_hash, :as => :admin) + + assert_admin_attributes(p, true) + end + + def test_create_with_bang_with_admin_role_with_attr_protected_attributes + p = LoosePerson.create!(attributes_hash, :as => :admin) + + assert_admin_attributes(p, true) + end + def test_new_with_without_protection_with_attr_accessible_attributes p = TightPerson.new(attributes_hash, :without_protection => true) @@ -201,6 +217,18 @@ class MassAssignmentSecurityTest < ActiveRecord::TestCase assert_all_attributes(p) end + def test_create_with_bang_with_without_protection_with_attr_accessible_attributes + p = TightPerson.create!(attributes_hash, :without_protection => true) + + assert_all_attributes(p) + end + + def test_create_with_bang_with_without_protection_with_attr_protected_attributes + p = LoosePerson.create!(attributes_hash, :without_protection => true) + + assert_all_attributes(p) + end + def test_protection_against_class_attribute_writers [:logger, :configurations, :primary_key_prefix_type, :table_name_prefix, :table_name_suffix, :pluralize_table_names, :default_timezone, :schema_format, :lock_optimistically, :record_timestamps].each do |method| @@ -230,12 +258,12 @@ class MassAssignmentSecurityHasOneRelationsTest < ActiveRecord::TestCase assert_default_attributes(best_friend) end - def test_has_one_build_with_admin_scope_with_attr_protected_attributes + def test_has_one_build_with_admin_role_with_attr_protected_attributes best_friend = @person.build_best_friend(attributes_hash, :as => :admin) assert_admin_attributes(best_friend) end - def test_has_one_build_with_admin_scope_with_attr_accessible_attributes + def test_has_one_build_with_admin_role_with_attr_accessible_attributes best_friend = @person.build_best_friend(attributes_hash, :as => :admin) assert_admin_attributes(best_friend) end @@ -257,12 +285,12 @@ class MassAssignmentSecurityHasOneRelationsTest < ActiveRecord::TestCase assert_default_attributes(best_friend, true) end - def test_has_one_create_with_admin_scope_with_attr_protected_attributes + def test_has_one_create_with_admin_role_with_attr_protected_attributes best_friend = @person.create_best_friend(attributes_hash, :as => :admin) assert_admin_attributes(best_friend, true) end - def test_has_one_create_with_admin_scope_with_attr_accessible_attributes + def test_has_one_create_with_admin_role_with_attr_accessible_attributes best_friend = @person.create_best_friend(attributes_hash, :as => :admin) assert_admin_attributes(best_friend, true) end @@ -284,12 +312,12 @@ class MassAssignmentSecurityHasOneRelationsTest < ActiveRecord::TestCase assert_default_attributes(best_friend, true) end - def test_has_one_create_with_bang_with_admin_scope_with_attr_protected_attributes + def test_has_one_create_with_bang_with_admin_role_with_attr_protected_attributes best_friend = @person.create_best_friend!(attributes_hash, :as => :admin) assert_admin_attributes(best_friend, true) end - def test_has_one_create_with_bang_with_admin_scope_with_attr_accessible_attributes + def test_has_one_create_with_bang_with_admin_role_with_attr_accessible_attributes best_friend = @person.create_best_friend!(attributes_hash, :as => :admin) assert_admin_attributes(best_friend, true) end @@ -318,12 +346,12 @@ class MassAssignmentSecurityBelongsToRelationsTest < ActiveRecord::TestCase assert_default_attributes(best_friend) end - def test_has_one_build_with_admin_scope_with_attr_protected_attributes + def test_has_one_build_with_admin_role_with_attr_protected_attributes best_friend = @person.build_best_friend_of(attributes_hash, :as => :admin) assert_admin_attributes(best_friend) end - def test_has_one_build_with_admin_scope_with_attr_accessible_attributes + def test_has_one_build_with_admin_role_with_attr_accessible_attributes best_friend = @person.build_best_friend_of(attributes_hash, :as => :admin) assert_admin_attributes(best_friend) end @@ -345,12 +373,12 @@ class MassAssignmentSecurityBelongsToRelationsTest < ActiveRecord::TestCase assert_default_attributes(best_friend, true) end - def test_has_one_create_with_admin_scope_with_attr_protected_attributes + def test_has_one_create_with_admin_role_with_attr_protected_attributes best_friend = @person.create_best_friend_of(attributes_hash, :as => :admin) assert_admin_attributes(best_friend, true) end - def test_has_one_create_with_admin_scope_with_attr_accessible_attributes + def test_has_one_create_with_admin_role_with_attr_accessible_attributes best_friend = @person.create_best_friend_of(attributes_hash, :as => :admin) assert_admin_attributes(best_friend, true) end @@ -372,12 +400,12 @@ class MassAssignmentSecurityBelongsToRelationsTest < ActiveRecord::TestCase assert_default_attributes(best_friend, true) end - def test_has_one_create_with_bang_with_admin_scope_with_attr_protected_attributes + def test_has_one_create_with_bang_with_admin_role_with_attr_protected_attributes best_friend = @person.create_best_friend!(attributes_hash, :as => :admin) assert_admin_attributes(best_friend, true) end - def test_has_one_create_with_bang_with_admin_scope_with_attr_accessible_attributes + def test_has_one_create_with_bang_with_admin_role_with_attr_accessible_attributes best_friend = @person.create_best_friend!(attributes_hash, :as => :admin) assert_admin_attributes(best_friend, true) end @@ -406,12 +434,12 @@ class MassAssignmentSecurityHasManyRelationsTest < ActiveRecord::TestCase assert_default_attributes(best_friend) end - def test_has_one_build_with_admin_scope_with_attr_protected_attributes + def test_has_one_build_with_admin_role_with_attr_protected_attributes best_friend = @person.best_friends.build(attributes_hash, :as => :admin) assert_admin_attributes(best_friend) end - def test_has_one_build_with_admin_scope_with_attr_accessible_attributes + def test_has_one_build_with_admin_role_with_attr_accessible_attributes best_friend = @person.best_friends.build(attributes_hash, :as => :admin) assert_admin_attributes(best_friend) end @@ -433,12 +461,12 @@ class MassAssignmentSecurityHasManyRelationsTest < ActiveRecord::TestCase assert_default_attributes(best_friend, true) end - def test_has_one_create_with_admin_scope_with_attr_protected_attributes + def test_has_one_create_with_admin_role_with_attr_protected_attributes best_friend = @person.best_friends.create(attributes_hash, :as => :admin) assert_admin_attributes(best_friend, true) end - def test_has_one_create_with_admin_scope_with_attr_accessible_attributes + def test_has_one_create_with_admin_role_with_attr_accessible_attributes best_friend = @person.best_friends.create(attributes_hash, :as => :admin) assert_admin_attributes(best_friend, true) end @@ -460,12 +488,12 @@ class MassAssignmentSecurityHasManyRelationsTest < ActiveRecord::TestCase assert_default_attributes(best_friend, true) end - def test_has_one_create_with_bang_with_admin_scope_with_attr_protected_attributes + def test_has_one_create_with_bang_with_admin_role_with_attr_protected_attributes best_friend = @person.best_friends.create!(attributes_hash, :as => :admin) assert_admin_attributes(best_friend, true) end - def test_has_one_create_with_bang_with_admin_scope_with_attr_accessible_attributes + def test_has_one_create_with_bang_with_admin_role_with_attr_accessible_attributes best_friend = @person.best_friends.create!(attributes_hash, :as => :admin) assert_admin_attributes(best_friend, true) end diff --git a/activerecord/test/cases/method_scoping_test.rb b/activerecord/test/cases/method_scoping_test.rb index 7f0f007a70..a0cb5dbdc5 100644 --- a/activerecord/test/cases/method_scoping_test.rb +++ b/activerecord/test/cases/method_scoping_test.rb @@ -68,7 +68,7 @@ class MethodScopingTest < ActiveRecord::TestCase def test_scoped_find_all Developer.send(:with_scope, :find => { :conditions => "name = 'David'" }) do - assert_equal [developers(:david)], Developer.find(:all) + assert_equal [developers(:david)], Developer.all end end @@ -235,23 +235,23 @@ class MethodScopingTest < ActiveRecord::TestCase def test_immutable_scope options = { :conditions => "name = 'David'" } Developer.send(:with_scope, :find => options) do - assert_equal %w(David), Developer.find(:all).map { |d| d.name } + assert_equal %w(David), Developer.all.map(&:name) options[:conditions] = "name != 'David'" - assert_equal %w(David), Developer.find(:all).map { |d| d.name } + assert_equal %w(David), Developer.all.map(&:name) end scope = { :find => { :conditions => "name = 'David'" }} Developer.send(:with_scope, scope) do - assert_equal %w(David), Developer.find(:all).map { |d| d.name } + assert_equal %w(David), Developer.all.map(&:name) scope[:find][:conditions] = "name != 'David'" - assert_equal %w(David), Developer.find(:all).map { |d| d.name } + assert_equal %w(David), Developer.all.map(&:name) end end def test_scoped_with_duck_typing scoping = Struct.new(:current_scope).new(:find => { :conditions => ["name = ?", 'David'] }) Developer.send(:with_scope, scoping) do - assert_equal %w(David), Developer.find(:all).map { |d| d.name } + assert_equal %w(David), Developer.all.map(&:name) end end @@ -432,7 +432,7 @@ class NestedScopingTest < ActiveRecord::TestCase def test_merged_scoped_find_combines_and_sanitizes_conditions Developer.send(:with_scope, :find => { :conditions => ["name = ?", 'David'] }) do Developer.send(:with_scope, :find => { :conditions => ['salary > ?', 9000] }) do - assert_equal %w(David), Developer.find(:all).map { |d| d.name } + assert_equal %w(David), Developer.all.map(&:name) end end end @@ -487,9 +487,9 @@ class NestedScopingTest < ActiveRecord::TestCase options2 = { :conditions => "name = 'David'" } Developer.send(:with_scope, :find => options1) do Developer.send(:with_exclusive_scope, :find => options2) do - assert_equal %w(David), Developer.find(:all).map { |d| d.name } + assert_equal %w(David), Developer.all.map(&:name) options1[:conditions] = options2[:conditions] = nil - assert_equal %w(David), Developer.find(:all).map { |d| d.name } + assert_equal %w(David), Developer.all.map(&:name) end end end @@ -499,9 +499,9 @@ class NestedScopingTest < ActiveRecord::TestCase options2 = { :conditions => "salary > 10000" } Developer.send(:with_scope, :find => options1) do Developer.send(:with_scope, :find => options2) do - assert_equal %w(Jamis), Developer.find(:all).map { |d| d.name } + assert_equal %w(Jamis), Developer.all.map(&:name) options1[:conditions] = options2[:conditions] = nil - assert_equal %w(Jamis), Developer.find(:all).map { |d| d.name } + assert_equal %w(Jamis), Developer.all.map(&:name) end end end diff --git a/activerecord/test/cases/named_scope_test.rb b/activerecord/test/cases/named_scope_test.rb index 8fd1fc2577..34188e4915 100644 --- a/activerecord/test/cases/named_scope_test.rb +++ b/activerecord/test/cases/named_scope_test.rb @@ -462,7 +462,7 @@ class NamedScopeTest < ActiveRecord::TestCase [:destroy_all, :reset, :delete_all].each do |method| before = post.comments.containing_the_letter_e post.association(:comments).send(method) - assert before.object_id != post.comments.containing_the_letter_e.object_id, "AssociationCollection##{method} should reset the named scopes cache" + assert before.object_id != post.comments.containing_the_letter_e.object_id, "CollectionAssociation##{method} should reset the named scopes cache" end end diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb index b066575af8..57d1441128 100644 --- a/activerecord/test/cases/persistence_test.rb +++ b/activerecord/test/cases/persistence_test.rb @@ -336,6 +336,10 @@ class PersistencesTest < ActiveRecord::TestCase assert !Topic.find(1).approved? end + def test_update_attribute_does_not_choke_on_nil + assert Topic.find(1).update_attributes(nil) + end + def test_update_attribute_for_readonly_attribute minivan = Minivan.find('m1') assert_raises(ActiveRecord::ActiveRecordError) { minivan.update_attribute(:color, 'black') } diff --git a/activerecord/test/cases/relation_scoping_test.rb b/activerecord/test/cases/relation_scoping_test.rb index 864b3d4846..c215602567 100644 --- a/activerecord/test/cases/relation_scoping_test.rb +++ b/activerecord/test/cases/relation_scoping_test.rb @@ -462,4 +462,8 @@ class DefaultScopingTest < ActiveRecord::TestCase assert DeveloperCalledJamis.unscoped.poor.include?(developers(:david).becomes(DeveloperCalledJamis)) assert_equal 10, DeveloperCalledJamis.unscoped.poor.length end + + def test_default_scope_order_ignored_by_aggregations + assert_equal DeveloperOrderedBySalary.all.count, DeveloperOrderedBySalary.count + end end diff --git a/activerecord/test/cases/session_store/session_test.rb b/activerecord/test/cases/session_store/session_test.rb index cee5ddd003..669c0b7b4d 100644 --- a/activerecord/test/cases/session_store/session_test.rb +++ b/activerecord/test/cases/session_store/session_test.rb @@ -21,6 +21,12 @@ module ActiveRecord assert_equal 'sessions', Session.table_name end + def test_accessible_attributes + assert Session.accessible_attributes.include?(:session_id) + assert Session.accessible_attributes.include?(:data) + assert Session.accessible_attributes.include?(:marshaled_data) + end + def test_create_table! assert !Session.table_exists? Session.create_table! diff --git a/activerecord/test/cases/timestamp_test.rb b/activerecord/test/cases/timestamp_test.rb index ceb1452afd..22d4cac422 100644 --- a/activerecord/test/cases/timestamp_test.rb +++ b/activerecord/test/cases/timestamp_test.rb @@ -14,6 +14,32 @@ class TimestampTest < ActiveRecord::TestCase @previously_updated_at = @developer.updated_at end + def test_load_infinity_and_beyond + unless current_adapter?(:PostgreSQLAdapter) + return skip("only tested on postgresql") + end + + d = Developer.find_by_sql("select 'infinity'::timestamp as updated_at") + assert d.first.updated_at.infinite?, 'timestamp should be infinite' + + d = Developer.find_by_sql("select '-infinity'::timestamp as updated_at") + time = d.first.updated_at + assert time.infinite?, 'timestamp should be infinite' + assert_operator time, :<, 0 + end + + def test_save_infinity_and_beyond + unless current_adapter?(:PostgreSQLAdapter) + return skip("only tested on postgresql") + end + + d = Developer.create!(:name => 'aaron', :updated_at => 1.0 / 0.0) + assert_equal(1.0 / 0.0, d.updated_at) + + d = Developer.create!(:name => 'aaron', :updated_at => -1.0 / 0.0) + assert_equal(-1.0 / 0.0, d.updated_at) + end + def test_saving_a_changed_record_updates_its_timestamp @developer.name = "Jack Bauer" @developer.save! diff --git a/activerecord/test/cases/xml_serialization_test.rb b/activerecord/test/cases/xml_serialization_test.rb index a6074b23e7..756c8a32eb 100644 --- a/activerecord/test/cases/xml_serialization_test.rb +++ b/activerecord/test/cases/xml_serialization_test.rb @@ -143,10 +143,7 @@ class NilXmlSerializationTest < ActiveRecord::TestCase end def test_should_serialize_yaml - assert %r{<preferences(.*)></preferences>}.match(@xml) - attributes = $1 - assert_match %r{type="yaml"}, attributes - assert_match %r{nil="true"}, attributes + assert_match %r{<preferences nil=\"true\"></preferences>}, @xml end end diff --git a/activerecord/test/fixtures/all/people.csv b/activerecord/test/fixtures/all/people.yml index e69de29bb2..e69de29bb2 100644 --- a/activerecord/test/fixtures/all/people.csv +++ b/activerecord/test/fixtures/all/people.yml diff --git a/activerecord/test/fixtures/memberships.yml b/activerecord/test/fixtures/memberships.yml index 60eb641054..a5d52bd438 100644 --- a/activerecord/test/fixtures/memberships.yml +++ b/activerecord/test/fixtures/memberships.yml @@ -25,3 +25,10 @@ blarpy_winkup_crazy_club: member_id: 3 favourite: false type: CurrentMembership + +selected_membership_of_boring_club: + joined_on: <%= 3.weeks.ago.to_s(:db) %> + club: boring_club + member_id: 1 + favourite: false + type: SelectedMembership diff --git a/activerecord/test/fixtures/string_key_objects.yml b/activerecord/test/fixtures/string_key_objects.yml new file mode 100644 index 0000000000..fa1299915b --- /dev/null +++ b/activerecord/test/fixtures/string_key_objects.yml @@ -0,0 +1,7 @@ +first: + id: record1 + name: first record + +second: + id: record2 + name: second record diff --git a/activerecord/test/models/aircraft.rb b/activerecord/test/models/aircraft.rb new file mode 100644 index 0000000000..0c47aab539 --- /dev/null +++ b/activerecord/test/models/aircraft.rb @@ -0,0 +1,3 @@ +class Aircraft < ActiveRecord::Base + has_many :engines, :foreign_key => "car_id" +end diff --git a/activerecord/test/models/bulb.rb b/activerecord/test/models/bulb.rb index c68d008c26..0dcc8d5970 100644 --- a/activerecord/test/models/bulb.rb +++ b/activerecord/test/models/bulb.rb @@ -2,6 +2,8 @@ class Bulb < ActiveRecord::Base default_scope where(:name => 'defaulty') belongs_to :car + attr_protected :car_id, :frickinawesome + attr_reader :scope_after_initialize after_initialize :record_scope_after_initialize @@ -9,4 +11,21 @@ class Bulb < ActiveRecord::Base @scope_after_initialize = self.class.scoped end + def color=(color) + self[:color] = color.upcase + "!" + end + + def self.new(attributes = {}, options = {}, &block) + bulb_type = (attributes || {}).delete(:bulb_type) + + if options && options[:as] == :admin && bulb_type.present? + bulb_class = "#{bulb_type.to_s.camelize}Bulb".constantize + bulb_class.new(attributes, options, &block) + else + super + end + end end + +class CustomBulb < Bulb +end
\ No newline at end of file diff --git a/activerecord/test/models/car.rb b/activerecord/test/models/car.rb index b036f0f5c9..76f20b1061 100644 --- a/activerecord/test/models/car.rb +++ b/activerecord/test/models/car.rb @@ -2,6 +2,11 @@ class Car < ActiveRecord::Base has_many :bulbs has_many :foo_bulbs, :class_name => "Bulb", :conditions => { :name => 'foo' } + has_many :frickinawesome_bulbs, :class_name => "Bulb", :conditions => { :frickinawesome => true } + + has_one :bulb + has_one :frickinawesome_bulb, :class_name => "Bulb", :conditions => { :frickinawesome => true } + has_many :tyres has_many :engines has_many :wheels, :as => :wheelable diff --git a/activerecord/test/models/member.rb b/activerecord/test/models/member.rb index 991e0e051f..11a0f4ff63 100644 --- a/activerecord/test/models/member.rb +++ b/activerecord/test/models/member.rb @@ -1,8 +1,10 @@ class Member < ActiveRecord::Base has_one :current_membership + has_one :selected_membership has_one :membership has_many :fellow_members, :through => :club, :source => :members has_one :club, :through => :current_membership + has_one :selected_club, :through => :selected_membership, :source => :club has_one :favourite_club, :through => :membership, :conditions => ["memberships.favourite = ?", true], :source => :club has_one :hairy_club, :through => :membership, :conditions => {:clubs => {:name => "Moustache and Eyebrow Fancier Club"}}, :source => :club has_one :sponsor, :as => :sponsorable diff --git a/activerecord/test/models/membership.rb b/activerecord/test/models/membership.rb index 905f948c37..bcbb7e42c5 100644 --- a/activerecord/test/models/membership.rb +++ b/activerecord/test/models/membership.rb @@ -7,3 +7,9 @@ class CurrentMembership < Membership belongs_to :member belongs_to :club end + +class SelectedMembership < Membership + def self.default_scope + select("'1' as foo") + end +end diff --git a/activerecord/test/models/string_key_object.rb b/activerecord/test/models/string_key_object.rb new file mode 100644 index 0000000000..f8d4c6e0e4 --- /dev/null +++ b/activerecord/test/models/string_key_object.rb @@ -0,0 +1,3 @@ +class StringKeyObject < ActiveRecord::Base + set_primary_key :id +end diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index 9479242e4f..4fe311b441 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -40,6 +40,10 @@ ActiveRecord::Schema.define do t.references :account end + create_table :aircraft, :force => true do |t| + t.string :name + end + create_table :audit_logs, :force => true do |t| t.column :message, :string, :null=>false t.column :developer_id, :integer, :null=>false @@ -89,6 +93,8 @@ ActiveRecord::Schema.define do create_table :bulbs, :force => true do |t| t.integer :car_id t.string :name + t.boolean :frickinawesome + t.string :color end create_table "CamelCase", :force => true do |t| @@ -543,6 +549,12 @@ ActiveRecord::Schema.define do t.string :sponsorable_type end + create_table :string_key_objects, :id => false, :primary_key => :id, :force => true do |t| + t.string :id + t.string :name + t.integer :lock_version, :null => false, :default => 0 + end + create_table :students, :force => true do |t| t.string :name end |