TeX and CSS tweaks.
Sync with latest Instiki Trunk (Updates Rails to 1.2.2)
This commit is contained in:
parent
0ac586ee25
commit
c358389f25
443 changed files with 24218 additions and 9823 deletions
|
@ -14,7 +14,11 @@ class AAACreateTablesTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_load_schema
|
||||
eval(File.read("#{File.dirname(__FILE__)}/fixtures/db_definitions/schema.rb"))
|
||||
if ActiveRecord::Base.connection.supports_migrations?
|
||||
eval(File.read("#{File.dirname(__FILE__)}/fixtures/db_definitions/schema.rb"))
|
||||
else
|
||||
recreate ActiveRecord::Base, '3'
|
||||
end
|
||||
assert true
|
||||
end
|
||||
|
||||
|
|
26
vendor/rails/activerecord/test/abstract_unit.rb
vendored
26
vendor/rails/activerecord/test/abstract_unit.rb
vendored
|
@ -8,6 +8,10 @@ require 'active_support/binding_of_caller'
|
|||
require 'active_support/breakpoint'
|
||||
require 'connection'
|
||||
|
||||
# Show backtraces for deprecated behavior for quicker cleanup.
|
||||
ActiveSupport::Deprecation.debug = true
|
||||
|
||||
|
||||
QUOTED_TYPE = ActiveRecord::Base.connection.quote_column_name('type') unless Object.const_defined?(:QUOTED_TYPE)
|
||||
|
||||
class Test::Unit::TestCase #:nodoc:
|
||||
|
@ -18,9 +22,9 @@ class Test::Unit::TestCase #:nodoc:
|
|||
def create_fixtures(*table_names, &block)
|
||||
Fixtures.create_fixtures(File.dirname(__FILE__) + "/fixtures/", table_names, {}, &block)
|
||||
end
|
||||
|
||||
|
||||
def assert_date_from_db(expected, actual, message = nil)
|
||||
# SQL Server doesn't have a separate column type just for dates,
|
||||
# SQL Server doesn't have a separate column type just for dates,
|
||||
# so the time is in the string and incorrectly formatted
|
||||
if current_adapter?(:SQLServerAdapter)
|
||||
assert_equal expected.strftime("%Y/%m/%d 00:00:00"), actual.strftime("%Y/%m/%d 00:00:00")
|
||||
|
@ -49,17 +53,23 @@ class Test::Unit::TestCase #:nodoc:
|
|||
end
|
||||
end
|
||||
|
||||
def current_adapter?(type)
|
||||
ActiveRecord::ConnectionAdapters.const_defined?(type) &&
|
||||
ActiveRecord::Base.connection.instance_of?(ActiveRecord::ConnectionAdapters.const_get(type))
|
||||
def current_adapter?(*types)
|
||||
types.any? do |type|
|
||||
ActiveRecord::ConnectionAdapters.const_defined?(type) &&
|
||||
ActiveRecord::Base.connection.is_a?(ActiveRecord::ConnectionAdapters.const_get(type))
|
||||
end
|
||||
end
|
||||
|
||||
ActiveRecord::Base.connection.class.class_eval do
|
||||
cattr_accessor :query_count
|
||||
|
||||
# Array of regexes of queries that are not counted against query_count
|
||||
@@ignore_list = [/^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/]
|
||||
|
||||
alias_method :execute_without_query_counting, :execute
|
||||
def execute_with_query_counting(sql, name = nil)
|
||||
self.query_count += 1
|
||||
execute_without_query_counting(sql, name)
|
||||
def execute_with_query_counting(sql, name = nil, &block)
|
||||
self.query_count += 1 unless @@ignore_list.any? { |r| sql =~ r }
|
||||
execute_without_query_counting(sql, name, &block)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
16
vendor/rails/activerecord/test/adapter_test.rb
vendored
16
vendor/rails/activerecord/test/adapter_test.rb
vendored
|
@ -66,19 +66,21 @@ class AdapterTest < Test::Unit::TestCase
|
|||
if ActiveRecord::Base.connection.respond_to?(:reset_pk_sequence!)
|
||||
require 'fixtures/movie'
|
||||
require 'fixtures/subscriber'
|
||||
|
||||
def test_reset_empty_table_with_custom_pk
|
||||
Movie.delete_all
|
||||
Movie.connection.reset_pk_sequence! 'movies'
|
||||
assert_equal 1, Movie.create(:name => 'fight club').id
|
||||
end
|
||||
|
||||
def test_reset_table_with_non_integer_pk
|
||||
Subscriber.delete_all
|
||||
Subscriber.connection.reset_pk_sequence! 'subscribers'
|
||||
|
||||
sub = Subscriber.new(:name => 'robert drake')
|
||||
sub.id = 'bob drake'
|
||||
assert_nothing_raised { sub.save! }
|
||||
if ActiveRecord::Base.connection.adapter_name != "FrontBase"
|
||||
def test_reset_table_with_non_integer_pk
|
||||
Subscriber.delete_all
|
||||
Subscriber.connection.reset_pk_sequence! 'subscribers'
|
||||
sub = Subscriber.new(:name => 'robert drake')
|
||||
sub.id = 'bob drake'
|
||||
assert_nothing_raised { sub.save! }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -63,4 +63,33 @@ class AggregationsTest < Test::Unit::TestCase
|
|||
def test_gps_inequality
|
||||
assert GpsLocation.new('39x110') != GpsLocation.new('39x111')
|
||||
end
|
||||
|
||||
def test_allow_nil_gps_is_nil
|
||||
assert_equal nil, customers(:zaphod).gps_location
|
||||
end
|
||||
|
||||
def test_allow_nil_gps_set_to_nil
|
||||
customers(:david).gps_location = nil
|
||||
customers(:david).save
|
||||
customers(:david).reload
|
||||
assert_equal nil, customers(:david).gps_location
|
||||
end
|
||||
|
||||
def test_allow_nil_set_address_attributes_to_nil
|
||||
customers(:zaphod).address = nil
|
||||
assert_equal nil, customers(:zaphod).attributes[:address_street]
|
||||
assert_equal nil, customers(:zaphod).attributes[:address_city]
|
||||
assert_equal nil, customers(:zaphod).attributes[:address_country]
|
||||
end
|
||||
|
||||
def test_allow_nil_address_set_to_nil
|
||||
customers(:zaphod).address = nil
|
||||
customers(:zaphod).save
|
||||
customers(:zaphod).reload
|
||||
assert_equal nil, customers(:zaphod).address
|
||||
end
|
||||
|
||||
def test_nil_raises_error_when_allow_nil_is_false
|
||||
assert_raises(NoMethodError) { customers(:david).balance = nil }
|
||||
end
|
||||
end
|
||||
|
|
384
vendor/rails/activerecord/test/associations_test.rb
vendored
384
vendor/rails/activerecord/test/associations_test.rb
vendored
|
@ -11,33 +11,34 @@ require 'fixtures/category'
|
|||
require 'fixtures/post'
|
||||
require 'fixtures/author'
|
||||
|
||||
# Can't declare new classes in test case methods, so tests before that
|
||||
bad_collection_keys = false
|
||||
begin
|
||||
class Car < ActiveRecord::Base; has_many :wheels, :name => "wheels"; end
|
||||
rescue ArgumentError
|
||||
bad_collection_keys = true
|
||||
end
|
||||
raise "ActiveRecord should have barked on bad collection keys" unless bad_collection_keys
|
||||
|
||||
|
||||
class AssociationsTest < Test::Unit::TestCase
|
||||
fixtures :accounts, :companies, :developers, :projects, :developers_projects,
|
||||
:computers
|
||||
|
||||
def test_bad_collection_keys
|
||||
assert_raise(ArgumentError, 'ActiveRecord should have barked on bad collection keys') do
|
||||
Class.new(ActiveRecord::Base).has_many(:wheels, :name => 'wheels')
|
||||
end
|
||||
end
|
||||
|
||||
def test_force_reload
|
||||
firm = Firm.new("name" => "A New Firm, Inc")
|
||||
firm.save
|
||||
firm.clients.each {|c|} # forcing to load all clients
|
||||
assert firm.clients.empty?, "New firm shouldn't have client objects"
|
||||
assert !firm.has_clients?, "New firm shouldn't have clients"
|
||||
assert_deprecated do
|
||||
assert !firm.has_clients?, "New firm shouldn't have clients"
|
||||
end
|
||||
assert_equal 0, firm.clients.size, "New firm should have 0 clients"
|
||||
|
||||
client = Client.new("name" => "TheClient.com", "firm_id" => firm.id)
|
||||
client.save
|
||||
|
||||
assert firm.clients.empty?, "New firm should have cached no client objects"
|
||||
assert !firm.has_clients?, "New firm should have cached a no-clients response"
|
||||
assert_deprecated do
|
||||
assert !firm.has_clients?, "New firm should have cached a no-clients response"
|
||||
end
|
||||
assert_equal 0, firm.clients.size, "New firm should have cached 0 clients count"
|
||||
|
||||
assert !firm.clients(true).empty?, "New firm should have reloaded client objects"
|
||||
|
@ -65,14 +66,62 @@ class AssociationsTest < Test::Unit::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
class AssociationProxyTest < Test::Unit::TestCase
|
||||
fixtures :authors, :posts
|
||||
|
||||
def test_proxy_accessors
|
||||
welcome = posts(:welcome)
|
||||
assert_equal welcome, welcome.author.proxy_owner
|
||||
assert_equal welcome.class.reflect_on_association(:author), welcome.author.proxy_reflection
|
||||
welcome.author.class # force load target
|
||||
assert_equal welcome.author, welcome.author.proxy_target
|
||||
|
||||
david = authors(:david)
|
||||
assert_equal david, david.posts.proxy_owner
|
||||
assert_equal david.class.reflect_on_association(:posts), david.posts.proxy_reflection
|
||||
david.posts.first # force load target
|
||||
assert_equal david.posts, david.posts.proxy_target
|
||||
|
||||
assert_equal david, david.posts_with_extension.testing_proxy_owner
|
||||
assert_equal david.class.reflect_on_association(:posts_with_extension), david.posts_with_extension.testing_proxy_reflection
|
||||
david.posts_with_extension.first # force load target
|
||||
assert_equal david.posts_with_extension, david.posts_with_extension.testing_proxy_target
|
||||
end
|
||||
end
|
||||
|
||||
class HasOneAssociationsTest < Test::Unit::TestCase
|
||||
fixtures :accounts, :companies, :developers, :projects, :developers_projects
|
||||
|
||||
def setup
|
||||
Account.destroyed_account_ids.clear
|
||||
end
|
||||
|
||||
def test_has_one
|
||||
assert_equal companies(:first_firm).account, Account.find(1)
|
||||
assert_equal Account.find(1).credit_limit, companies(:first_firm).account.credit_limit
|
||||
end
|
||||
|
||||
def test_has_one_cache_nils
|
||||
firm = companies(:another_firm)
|
||||
assert_queries(1) { assert_nil firm.account }
|
||||
assert_queries(0) { assert_nil firm.account }
|
||||
|
||||
firms = Firm.find(:all, :include => :account)
|
||||
assert_queries(0) { firms.each(&:account) }
|
||||
end
|
||||
|
||||
def test_can_marshal_has_one_association_with_nil_target
|
||||
firm = Firm.new
|
||||
assert_nothing_raised do
|
||||
assert_equal firm.attributes, Marshal.load(Marshal.dump(firm)).attributes
|
||||
end
|
||||
|
||||
firm.account
|
||||
assert_nothing_raised do
|
||||
assert_equal firm.attributes, Marshal.load(Marshal.dump(firm)).attributes
|
||||
end
|
||||
end
|
||||
|
||||
def test_proxy_assignment
|
||||
company = companies(:first_firm)
|
||||
assert_nothing_raised { company.account = company.account }
|
||||
|
@ -135,10 +184,40 @@ class HasOneAssociationsTest < Test::Unit::TestCase
|
|||
|
||||
def test_dependence
|
||||
num_accounts = Account.count
|
||||
|
||||
firm = Firm.find(1)
|
||||
assert !firm.account.nil?
|
||||
firm.destroy
|
||||
account_id = firm.account.id
|
||||
assert_equal [], Account.destroyed_account_ids[firm.id]
|
||||
|
||||
firm.destroy
|
||||
assert_equal num_accounts - 1, Account.count
|
||||
assert_equal [account_id], Account.destroyed_account_ids[firm.id]
|
||||
end
|
||||
|
||||
def test_deprecated_exclusive_dependence
|
||||
assert_deprecated(/:exclusively_dependent.*:dependent => :delete_all/) do
|
||||
Firm.has_many :deprecated_exclusively_dependent_clients, :class_name => 'Client', :exclusively_dependent => true
|
||||
end
|
||||
end
|
||||
|
||||
def test_exclusive_dependence
|
||||
num_accounts = Account.count
|
||||
|
||||
firm = ExclusivelyDependentFirm.find(9)
|
||||
assert !firm.account.nil?
|
||||
account_id = firm.account.id
|
||||
assert_equal [], Account.destroyed_account_ids[firm.id]
|
||||
|
||||
firm.destroy
|
||||
assert_equal num_accounts - 1, Account.count
|
||||
assert_equal [], Account.destroyed_account_ids[firm.id]
|
||||
end
|
||||
|
||||
def test_dependence_with_nil_associate
|
||||
firm = DependentFirm.new(:name => 'nullify')
|
||||
firm.save!
|
||||
assert_nothing_raised { firm.destroy }
|
||||
end
|
||||
|
||||
def test_succesful_build_association
|
||||
|
@ -247,6 +326,14 @@ class HasOneAssociationsTest < Test::Unit::TestCase
|
|||
assert_equal a, firm.account(true)
|
||||
end
|
||||
|
||||
def test_finding_with_interpolated_condition
|
||||
firm = Firm.find(:first)
|
||||
superior = firm.clients.create(:name => 'SuperiorCo')
|
||||
superior.rating = 10
|
||||
superior.save
|
||||
assert_equal 10, firm.clients_with_interpolated_conditions.first.rating
|
||||
end
|
||||
|
||||
def test_assignment_before_child_saved
|
||||
firm = Firm.find(1)
|
||||
firm.account = a = Account.new("credit_limit" => 1000)
|
||||
|
@ -268,6 +355,40 @@ class HasOneAssociationsTest < Test::Unit::TestCase
|
|||
assert_equal a, firm.account
|
||||
assert_equal a, firm.account(true)
|
||||
end
|
||||
|
||||
def test_not_resaved_when_unchanged
|
||||
firm = Firm.find(:first, :include => :account)
|
||||
assert_queries(1) { firm.save! }
|
||||
|
||||
firm = Firm.find(:first)
|
||||
firm.account = Account.find(:first)
|
||||
assert_queries(1) { firm.save! }
|
||||
|
||||
firm = Firm.find(:first).clone
|
||||
firm.account = Account.find(:first)
|
||||
assert_queries(2) { firm.save! }
|
||||
|
||||
firm = Firm.find(:first).clone
|
||||
firm.account = Account.find(:first).clone
|
||||
assert_queries(2) { firm.save! }
|
||||
end
|
||||
|
||||
def test_save_still_works_after_accessing_nil_has_one
|
||||
jp = Company.new :name => 'Jaded Pixel'
|
||||
jp.dummy_account.nil?
|
||||
|
||||
assert_nothing_raised do
|
||||
jp.save!
|
||||
end
|
||||
end
|
||||
|
||||
def test_deprecated_inferred_foreign_key
|
||||
assert_not_deprecated { Company.belongs_to :firm }
|
||||
assert_not_deprecated { Company.belongs_to :client, :foreign_key => "firm_id" }
|
||||
assert_not_deprecated { Company.belongs_to :firm, :class_name => "Firm", :foreign_key => "client_of" }
|
||||
assert_deprecated("inferred foreign_key name") { Company.belongs_to :client, :class_name => "Firm" }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
@ -283,10 +404,28 @@ class HasManyAssociationsTest < Test::Unit::TestCase
|
|||
companies(:first_firm).clients_of_firm.each {|f| }
|
||||
end
|
||||
|
||||
def test_counting
|
||||
def test_counting_with_counter_sql
|
||||
assert_equal 2, Firm.find(:first).clients.count
|
||||
end
|
||||
|
||||
|
||||
def test_counting
|
||||
assert_equal 2, Firm.find(:first).plain_clients.count
|
||||
end
|
||||
|
||||
def test_counting_with_single_conditions
|
||||
assert_deprecated 'count' do
|
||||
assert_equal 2, Firm.find(:first).plain_clients.count('1=1')
|
||||
end
|
||||
end
|
||||
|
||||
def test_counting_with_single_hash
|
||||
assert_equal 2, Firm.find(:first).plain_clients.count(:conditions => '1=1')
|
||||
end
|
||||
|
||||
def test_counting_with_column_name_and_hash
|
||||
assert_equal 2, Firm.find(:first).plain_clients.count(:all, :conditions => '1=1')
|
||||
end
|
||||
|
||||
def test_finding
|
||||
assert_equal 2, Firm.find(:first).clients.length
|
||||
end
|
||||
|
@ -318,6 +457,10 @@ class HasManyAssociationsTest < Test::Unit::TestCase
|
|||
assert_equal "Microsoft", Firm.find(:first).clients_like_ms.first.name
|
||||
end
|
||||
|
||||
def test_finding_with_condition_hash
|
||||
assert_equal "Microsoft", Firm.find(:first).clients_like_ms_with_hash_conditions.first.name
|
||||
end
|
||||
|
||||
def test_finding_using_sql
|
||||
firm = Firm.find(:first)
|
||||
first_client = firm.clients_using_sql.first
|
||||
|
@ -371,34 +514,44 @@ class HasManyAssociationsTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_find_all
|
||||
firm = Firm.find_first
|
||||
assert_equal firm.clients, firm.clients.find_all
|
||||
assert_equal 2, firm.clients.find(:all, :conditions => "#{QUOTED_TYPE} = 'Client'").length
|
||||
assert_equal 1, firm.clients.find(:all, :conditions => "name = 'Summit'").length
|
||||
assert_deprecated 'find_all' do
|
||||
firm = Firm.find_first
|
||||
assert_equal firm.clients, firm.clients.find_all
|
||||
assert_equal 2, firm.clients.find(:all, :conditions => "#{QUOTED_TYPE} = 'Client'").length
|
||||
assert_equal 1, firm.clients.find(:all, :conditions => "name = 'Summit'").length
|
||||
end
|
||||
end
|
||||
|
||||
def test_find_all_sanitized
|
||||
firm = Firm.find_first
|
||||
assert_equal firm.clients.find_all("name = 'Summit'"), firm.clients.find_all(["name = '%s'", "Summit"])
|
||||
summit = firm.clients.find(:all, :conditions => "name = 'Summit'")
|
||||
assert_equal summit, firm.clients.find(:all, :conditions => ["name = ?", "Summit"])
|
||||
assert_equal summit, firm.clients.find(:all, :conditions => ["name = :name", { :name => "Summit" }])
|
||||
assert_deprecated 'find_all' do
|
||||
firm = Firm.find_first
|
||||
assert_equal firm.clients.find_all("name = 'Summit'"), firm.clients.find_all(["name = '%s'", "Summit"])
|
||||
summit = firm.clients.find(:all, :conditions => "name = 'Summit'")
|
||||
assert_equal summit, firm.clients.find(:all, :conditions => ["name = ?", "Summit"])
|
||||
assert_equal summit, firm.clients.find(:all, :conditions => ["name = :name", { :name => "Summit" }])
|
||||
end
|
||||
end
|
||||
|
||||
def test_find_first
|
||||
firm = Firm.find_first
|
||||
client2 = Client.find(2)
|
||||
assert_equal firm.clients.first, firm.clients.find_first
|
||||
assert_equal client2, firm.clients.find_first("#{QUOTED_TYPE} = 'Client'")
|
||||
assert_equal client2, firm.clients.find(:first, :conditions => "#{QUOTED_TYPE} = 'Client'")
|
||||
assert_deprecated 'find_first' do
|
||||
firm = Firm.find_first
|
||||
client2 = Client.find(2)
|
||||
assert_equal firm.clients.first, firm.clients.find_first
|
||||
assert_equal client2, firm.clients.find_first("#{QUOTED_TYPE} = 'Client'")
|
||||
assert_equal client2, firm.clients.find(:first, :conditions => "#{QUOTED_TYPE} = 'Client'")
|
||||
end
|
||||
end
|
||||
|
||||
def test_find_first_sanitized
|
||||
firm = Firm.find_first
|
||||
client2 = Client.find(2)
|
||||
assert_equal client2, firm.clients.find_first(["#{QUOTED_TYPE} = ?", "Client"])
|
||||
assert_equal client2, firm.clients.find(:first, :conditions => ["#{QUOTED_TYPE} = ?", 'Client'])
|
||||
assert_equal client2, firm.clients.find(:first, :conditions => ["#{QUOTED_TYPE} = :type", { :type => 'Client' }])
|
||||
assert_deprecated 'find_first' do
|
||||
firm = Firm.find_first
|
||||
client2 = Client.find(2)
|
||||
assert_deprecated(/find_first/) do
|
||||
assert_equal client2, firm.clients.find_first(["#{QUOTED_TYPE} = ?", "Client"])
|
||||
end
|
||||
assert_equal client2, firm.clients.find(:first, :conditions => ["#{QUOTED_TYPE} = ?", 'Client'])
|
||||
assert_equal client2, firm.clients.find(:first, :conditions => ["#{QUOTED_TYPE} = :type", { :type => 'Client' }])
|
||||
end
|
||||
end
|
||||
|
||||
def test_find_in_collection
|
||||
|
@ -421,6 +574,14 @@ class HasManyAssociationsTest < Test::Unit::TestCase
|
|||
assert_equal 2, companies(:first_firm).clients_of_firm(true).size # checking using the db
|
||||
assert_equal natural, companies(:first_firm).clients_of_firm.last
|
||||
end
|
||||
|
||||
def test_adding_using_create
|
||||
first_firm = companies(:first_firm)
|
||||
assert_equal 2, first_firm.plain_clients.size
|
||||
natural = first_firm.plain_clients.create(:name => "Natural Company")
|
||||
assert_equal 3, first_firm.plain_clients.length
|
||||
assert_equal 3, first_firm.plain_clients.size
|
||||
end
|
||||
|
||||
def test_adding_a_mismatch_class
|
||||
assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << nil }
|
||||
|
@ -496,6 +657,35 @@ class HasManyAssociationsTest < Test::Unit::TestCase
|
|||
assert_equal 3, companies(:first_firm).clients_of_firm(true).size
|
||||
end
|
||||
|
||||
def test_build_without_loading_association
|
||||
first_topic = topics(:first)
|
||||
Reply.column_names
|
||||
|
||||
assert_equal 1, first_topic.replies.length
|
||||
|
||||
assert_no_queries do
|
||||
first_topic.replies.build(:title => "Not saved", :content => "Superstars")
|
||||
assert_equal 2, first_topic.replies.size
|
||||
end
|
||||
|
||||
assert_equal 2, first_topic.replies.to_ary.size
|
||||
end
|
||||
|
||||
def test_create_without_loading_association
|
||||
first_firm = companies(:first_firm)
|
||||
Firm.column_names
|
||||
Client.column_names
|
||||
|
||||
assert_equal 1, first_firm.clients_of_firm.size
|
||||
first_firm.clients_of_firm.reset
|
||||
|
||||
assert_queries(1) do
|
||||
first_firm.clients_of_firm.create(:name => "Superstars")
|
||||
end
|
||||
|
||||
assert_equal 2, first_firm.clients_of_firm.size
|
||||
end
|
||||
|
||||
def test_invalid_build
|
||||
new_client = companies(:first_firm).clients_of_firm.build
|
||||
assert new_client.new_record?
|
||||
|
@ -633,7 +823,7 @@ class HasManyAssociationsTest < Test::Unit::TestCase
|
|||
|
||||
def test_deleting_a_item_which_is_not_in_the_collection
|
||||
force_signal37_to_load_all_clients_of_firm
|
||||
summit = Client.find_first("name = 'Summit'")
|
||||
summit = Client.find_by_name('Summit')
|
||||
companies(:first_firm).clients_of_firm.delete(summit)
|
||||
assert_equal 1, companies(:first_firm).clients_of_firm.size
|
||||
assert_equal 1, companies(:first_firm).clients_of_firm(true).size
|
||||
|
@ -762,6 +952,10 @@ class HasManyAssociationsTest < Test::Unit::TestCase
|
|||
assert firm.clients.include?(Client.find_by_name("New Client"))
|
||||
end
|
||||
|
||||
def test_get_ids
|
||||
assert_equal [companies(:first_client).id, companies(:second_client).id], companies(:first_firm).client_ids
|
||||
end
|
||||
|
||||
def test_assign_ids
|
||||
firm = Firm.new("name" => "Apple")
|
||||
firm.client_ids = [companies(:first_client).id, companies(:second_client).id]
|
||||
|
@ -770,6 +964,16 @@ class HasManyAssociationsTest < Test::Unit::TestCase
|
|||
assert_equal 2, firm.clients.length
|
||||
assert firm.clients.include?(companies(:second_client))
|
||||
end
|
||||
|
||||
def test_assign_ids_ignoring_blanks
|
||||
firm = Firm.new("name" => "Apple")
|
||||
firm.client_ids = [companies(:first_client).id, nil, companies(:second_client).id, '']
|
||||
firm.save
|
||||
firm.reload
|
||||
assert_equal 2, firm.clients.length
|
||||
assert firm.clients.include?(companies(:second_client))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class BelongsToAssociationsTest < Test::Unit::TestCase
|
||||
|
@ -1200,7 +1404,9 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
|
|||
def test_adding_uses_explicit_values_on_join_table
|
||||
ac = projects(:action_controller)
|
||||
assert !developers(:jamis).projects.include?(ac)
|
||||
developers(:jamis).projects.push_with_attributes(ac, :access_level => 3)
|
||||
assert_deprecated do
|
||||
developers(:jamis).projects.push_with_attributes(ac, :access_level => 3)
|
||||
end
|
||||
|
||||
assert developers(:jamis, :reload).projects.include?(ac)
|
||||
project = developers(:jamis).projects.detect { |p| p == ac }
|
||||
|
@ -1243,9 +1449,13 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
|
|||
no_of_projects = Project.count
|
||||
now = Date.today
|
||||
ken = Developer.new("name" => "Ken")
|
||||
ken.projects.push_with_attributes( Project.find(1), :joined_on => now )
|
||||
assert_deprecated do
|
||||
ken.projects.push_with_attributes( Project.find(1), :joined_on => now )
|
||||
end
|
||||
p = Project.new("name" => "Foomatic")
|
||||
ken.projects.push_with_attributes( p, :joined_on => now )
|
||||
assert_deprecated do
|
||||
ken.projects.push_with_attributes( p, :joined_on => now )
|
||||
end
|
||||
assert ken.new_record?
|
||||
assert p.new_record?
|
||||
assert ken.save
|
||||
|
@ -1262,17 +1472,20 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
|
|||
def test_habtm_saving_multiple_relationships
|
||||
new_project = Project.new("name" => "Grimetime")
|
||||
amount_of_developers = 4
|
||||
developers = (0..amount_of_developers).collect {|i| Developer.create(:name => "JME #{i}") }
|
||||
|
||||
developers = (0...amount_of_developers).collect {|i| Developer.create(:name => "JME #{i}") }.reverse
|
||||
|
||||
new_project.developer_ids = [developers[0].id, developers[1].id]
|
||||
new_project.developers_with_callback_ids = [developers[2].id, developers[3].id]
|
||||
assert new_project.save
|
||||
|
||||
|
||||
new_project.reload
|
||||
assert_equal amount_of_developers, new_project.developers.size
|
||||
amount_of_developers.times do |i|
|
||||
assert_equal developers[i].name, new_project.developers[i].name
|
||||
end
|
||||
assert_equal developers, new_project.developers
|
||||
end
|
||||
|
||||
def test_habtm_unique_order_preserved
|
||||
assert_equal [developers(:poor_jamis), developers(:jamis), developers(:david)], projects(:active_record).non_unique_developers
|
||||
assert_equal [developers(:poor_jamis), developers(:jamis), developers(:david)], projects(:active_record).developers
|
||||
end
|
||||
|
||||
def test_build
|
||||
|
@ -1283,6 +1496,20 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
|
|||
devel.save
|
||||
assert !proj.new_record?
|
||||
assert_equal devel.projects.last, proj
|
||||
assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
|
||||
end
|
||||
|
||||
def test_build_by_new_record
|
||||
devel = Developer.new(:name => "Marcel", :salary => 75000)
|
||||
proj1 = devel.projects.build(:name => "Make bed")
|
||||
proj2 = devel.projects.build(:name => "Lie in it")
|
||||
assert_equal devel.projects.last, proj2
|
||||
assert proj2.new_record?
|
||||
devel.save
|
||||
assert !devel.new_record?
|
||||
assert !proj2.new_record?
|
||||
assert_equal devel.projects.last, proj2
|
||||
assert_equal Developer.find_by_name("Marcel").projects.last, proj2 # prove join table is updated
|
||||
end
|
||||
|
||||
def test_create
|
||||
|
@ -1290,6 +1517,20 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
|
|||
proj = devel.projects.create("name" => "Projekt")
|
||||
assert_equal devel.projects.last, proj
|
||||
assert !proj.new_record?
|
||||
assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
|
||||
end
|
||||
|
||||
def test_create_by_new_record
|
||||
devel = Developer.new(:name => "Marcel", :salary => 75000)
|
||||
proj1 = devel.projects.create(:name => "Make bed")
|
||||
proj2 = devel.projects.create(:name => "Lie in it")
|
||||
assert_equal devel.projects.last, proj2
|
||||
assert proj2.new_record?
|
||||
devel.save
|
||||
assert !devel.new_record?
|
||||
assert !proj2.new_record?
|
||||
assert_equal devel.projects.last, proj2
|
||||
assert_equal Developer.find_by_name("Marcel").projects.last, proj2 # prove join table is updated
|
||||
end
|
||||
|
||||
def test_uniq_after_the_fact
|
||||
|
@ -1377,8 +1618,10 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
|
|||
|
||||
def test_rich_association
|
||||
jamis = developers(:jamis)
|
||||
jamis.projects.push_with_attributes(projects(:action_controller), :joined_on => Date.today)
|
||||
|
||||
assert_deprecated 'push_with_attributes' do
|
||||
jamis.projects.push_with_attributes(projects(:action_controller), :joined_on => Date.today)
|
||||
end
|
||||
|
||||
assert_date_from_db Date.today, jamis.projects.select { |p| p.name == projects(:action_controller).name }.first.joined_on
|
||||
assert_date_from_db Date.today, developers(:jamis).projects.select { |p| p.name == projects(:action_controller).name }.first.joined_on
|
||||
end
|
||||
|
@ -1386,8 +1629,10 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
|
|||
def test_associations_with_conditions
|
||||
assert_equal 3, projects(:active_record).developers.size
|
||||
assert_equal 1, projects(:active_record).developers_named_david.size
|
||||
assert_equal 1, projects(:active_record).developers_named_david_with_hash_conditions.size
|
||||
|
||||
assert_equal developers(:david), projects(:active_record).developers_named_david.find(developers(:david).id)
|
||||
assert_equal developers(:david), projects(:active_record).developers_named_david_with_hash_conditions.find(developers(:david).id)
|
||||
assert_equal developers(:david), projects(:active_record).salaried_developers.find(developers(:david).id)
|
||||
|
||||
projects(:active_record).developers_named_david.clear
|
||||
|
@ -1512,4 +1757,53 @@ class HasAndBelongsToManyAssociationsTest < Test::Unit::TestCase
|
|||
def test_join_table_alias
|
||||
assert_equal 3, Developer.find(:all, :include => {:projects => :developers}, :conditions => 'developers_projects_join.joined_on IS NOT NULL').size
|
||||
end
|
||||
|
||||
def test_join_with_group
|
||||
group = Developer.columns.inject([]) do |g, c|
|
||||
g << "developers.#{c.name}"
|
||||
g << "developers_projects_2.#{c.name}"
|
||||
end
|
||||
Project.columns.each { |c| group << "projects.#{c.name}" }
|
||||
|
||||
assert_equal 3, Developer.find(:all, :include => {:projects => :developers}, :conditions => 'developers_projects_join.joined_on IS NOT NULL', :group => group.join(",")).size
|
||||
end
|
||||
|
||||
def test_get_ids
|
||||
assert_equal [projects(:active_record).id, projects(:action_controller).id], developers(:david).project_ids
|
||||
assert_equal [projects(:active_record).id], developers(:jamis).project_ids
|
||||
end
|
||||
|
||||
def test_assign_ids
|
||||
developer = Developer.new("name" => "Joe")
|
||||
developer.project_ids = [projects(:active_record).id, projects(:action_controller).id]
|
||||
developer.save
|
||||
developer.reload
|
||||
assert_equal 2, developer.projects.length
|
||||
assert_equal projects(:active_record), developer.projects[0]
|
||||
assert_equal projects(:action_controller), developer.projects[1]
|
||||
end
|
||||
|
||||
def test_assign_ids_ignoring_blanks
|
||||
developer = Developer.new("name" => "Joe")
|
||||
developer.project_ids = [projects(:active_record).id, nil, projects(:action_controller).id, '']
|
||||
developer.save
|
||||
developer.reload
|
||||
assert_equal 2, developer.projects.length
|
||||
assert_equal projects(:active_record), developer.projects[0]
|
||||
assert_equal projects(:action_controller), developer.projects[1]
|
||||
end
|
||||
|
||||
def test_select_limited_ids_list
|
||||
# Set timestamps
|
||||
Developer.transaction do
|
||||
Developer.find(:all, :order => 'id').each_with_index do |record, i|
|
||||
record.update_attributes(:created_at => 5.years.ago + (i * 5.minutes))
|
||||
end
|
||||
end
|
||||
|
||||
join_base = ActiveRecord::Associations::ClassMethods::JoinDependency::JoinBase.new(Project)
|
||||
join_dep = ActiveRecord::Associations::ClassMethods::JoinDependency.new(join_base, :developers, nil)
|
||||
projects = Project.send(:select_limited_ids_list, {:order => 'developers.created_at'}, join_dep)
|
||||
assert_equal %w(1 2), projects.scan(/\d/).sort
|
||||
end
|
||||
end
|
||||
|
|
406
vendor/rails/activerecord/test/base_test.rb
vendored
406
vendor/rails/activerecord/test/base_test.rb
vendored
|
@ -10,10 +10,18 @@ require 'fixtures/auto_id'
|
|||
require 'fixtures/column_name'
|
||||
require 'fixtures/subscriber'
|
||||
require 'fixtures/keyboard'
|
||||
require 'fixtures/post'
|
||||
|
||||
class Category < ActiveRecord::Base; end
|
||||
class Smarts < ActiveRecord::Base; end
|
||||
class CreditCard < ActiveRecord::Base; end
|
||||
class CreditCard < ActiveRecord::Base
|
||||
class PinNumber < ActiveRecord::Base
|
||||
class CvvCode < ActiveRecord::Base; end
|
||||
class SubCvvCode < CvvCode; end
|
||||
end
|
||||
class SubPinNumber < PinNumber; end
|
||||
class Brand < Category; end
|
||||
end
|
||||
class MasterCreditCard < ActiveRecord::Base; end
|
||||
class Post < ActiveRecord::Base; end
|
||||
class Computer < ActiveRecord::Base; end
|
||||
|
@ -21,8 +29,9 @@ class NonExistentTable < ActiveRecord::Base; end
|
|||
class TestOracleDefault < ActiveRecord::Base; end
|
||||
|
||||
class LoosePerson < ActiveRecord::Base
|
||||
attr_protected :credit_rating, :administrator
|
||||
self.table_name = 'people'
|
||||
self.abstract_class = true
|
||||
attr_protected :credit_rating, :administrator
|
||||
end
|
||||
|
||||
class LooseDescendant < LoosePerson
|
||||
|
@ -30,6 +39,7 @@ class LooseDescendant < LoosePerson
|
|||
end
|
||||
|
||||
class TightPerson < ActiveRecord::Base
|
||||
self.table_name = 'people'
|
||||
attr_accessible :name, :address
|
||||
end
|
||||
|
||||
|
@ -44,7 +54,7 @@ class Task < ActiveRecord::Base
|
|||
end
|
||||
|
||||
class BasicsTest < Test::Unit::TestCase
|
||||
fixtures :topics, :companies, :developers, :projects, :computers
|
||||
fixtures :topics, :companies, :developers, :projects, :computers, :accounts
|
||||
|
||||
def test_table_exists
|
||||
assert !NonExistentTable.table_exists?
|
||||
|
@ -59,7 +69,7 @@ class BasicsTest < Test::Unit::TestCase
|
|||
assert_equal("Jason", topic.author_name)
|
||||
assert_equal(topics(:first).author_email_address, Topic.find(1).author_email_address)
|
||||
end
|
||||
|
||||
|
||||
def test_integers_as_nil
|
||||
test = AutoId.create('value' => '')
|
||||
assert_nil AutoId.find(test.id).value
|
||||
|
@ -142,8 +152,28 @@ class BasicsTest < Test::Unit::TestCase
|
|||
def test_save!
|
||||
topic = Topic.new(:title => "New Topic")
|
||||
assert topic.save!
|
||||
end
|
||||
|
||||
reply = Reply.new
|
||||
assert_raise(ActiveRecord::RecordInvalid) { reply.save! }
|
||||
end
|
||||
|
||||
def test_save_null_string_attributes
|
||||
topic = Topic.find(1)
|
||||
topic.attributes = { "title" => "null", "author_name" => "null" }
|
||||
topic.save!
|
||||
topic.reload
|
||||
assert_equal("null", topic.title)
|
||||
assert_equal("null", topic.author_name)
|
||||
end
|
||||
|
||||
def test_save_nil_string_attributes
|
||||
topic = Topic.find(1)
|
||||
topic.title = nil
|
||||
topic.save!
|
||||
topic.reload
|
||||
assert_nil topic.title
|
||||
end
|
||||
|
||||
def test_hashes_not_mangled
|
||||
new_topic = { :title => "New Topic" }
|
||||
new_topic_values = { :title => "AnotherTopic" }
|
||||
|
@ -315,23 +345,22 @@ class BasicsTest < Test::Unit::TestCase
|
|||
Time, Topic.find(1).written_on,
|
||||
"The written_on attribute should be of the Time class"
|
||||
)
|
||||
|
||||
# For adapters which support microsecond resolution.
|
||||
if current_adapter?(:PostgreSQLAdapter)
|
||||
assert_equal 11, Topic.find(1).written_on.sec
|
||||
assert_equal 223300, Topic.find(1).written_on.usec
|
||||
assert_equal 9900, Topic.find(2).written_on.usec
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def test_destroy
|
||||
topic = Topic.new
|
||||
topic.title = "Yet Another New Topic"
|
||||
topic.written_on = "2003-12-12 23:23:00"
|
||||
topic.save
|
||||
topic.destroy
|
||||
topic = Topic.find(1)
|
||||
assert_equal topic, topic.destroy, 'topic.destroy did not return self'
|
||||
assert topic.frozen?, 'topic not frozen after destroy'
|
||||
assert_raise(ActiveRecord::RecordNotFound) { Topic.find(topic.id) }
|
||||
end
|
||||
|
||||
def test_destroy_returns_self
|
||||
topic = Topic.new("title" => "Yet Another Title")
|
||||
assert topic.save
|
||||
assert_equal topic, topic.destroy, "destroy did not return destroyed object"
|
||||
end
|
||||
|
||||
|
||||
def test_record_not_found_exception
|
||||
assert_raises(ActiveRecord::RecordNotFound) { topicReloaded = Topic.find(99999) }
|
||||
end
|
||||
|
@ -368,21 +397,33 @@ class BasicsTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_table_name_guesses
|
||||
classes = [Category, Smarts, CreditCard, CreditCard::PinNumber, CreditCard::PinNumber::CvvCode, CreditCard::SubPinNumber, CreditCard::Brand, MasterCreditCard]
|
||||
|
||||
assert_equal "topics", Topic.table_name
|
||||
|
||||
|
||||
assert_equal "categories", Category.table_name
|
||||
assert_equal "smarts", Smarts.table_name
|
||||
assert_equal "credit_cards", CreditCard.table_name
|
||||
assert_equal "credit_card_pin_numbers", CreditCard::PinNumber.table_name
|
||||
assert_equal "credit_card_pin_number_cvv_codes", CreditCard::PinNumber::CvvCode.table_name
|
||||
assert_equal "credit_card_pin_numbers", CreditCard::SubPinNumber.table_name
|
||||
assert_equal "categories", CreditCard::Brand.table_name
|
||||
assert_equal "master_credit_cards", MasterCreditCard.table_name
|
||||
|
||||
ActiveRecord::Base.pluralize_table_names = false
|
||||
[Category, Smarts, CreditCard, MasterCreditCard].each{|c| c.reset_table_name}
|
||||
classes.each(&:reset_table_name)
|
||||
|
||||
assert_equal "category", Category.table_name
|
||||
assert_equal "smarts", Smarts.table_name
|
||||
assert_equal "credit_card", CreditCard.table_name
|
||||
assert_equal "credit_card_pin_number", CreditCard::PinNumber.table_name
|
||||
assert_equal "credit_card_pin_number_cvv_code", CreditCard::PinNumber::CvvCode.table_name
|
||||
assert_equal "credit_card_pin_number", CreditCard::SubPinNumber.table_name
|
||||
assert_equal "category", CreditCard::Brand.table_name
|
||||
assert_equal "master_credit_card", MasterCreditCard.table_name
|
||||
|
||||
ActiveRecord::Base.pluralize_table_names = true
|
||||
[Category, Smarts, CreditCard, MasterCreditCard].each{|c| c.reset_table_name}
|
||||
classes.each(&:reset_table_name)
|
||||
|
||||
ActiveRecord::Base.table_name_prefix = "test_"
|
||||
Category.reset_table_name
|
||||
|
@ -410,8 +451,9 @@ class BasicsTest < Test::Unit::TestCase
|
|||
ActiveRecord::Base.table_name_suffix = ""
|
||||
Category.reset_table_name
|
||||
assert_equal "category", Category.table_name
|
||||
|
||||
ActiveRecord::Base.pluralize_table_names = true
|
||||
[Category, Smarts, CreditCard, MasterCreditCard].each{|c| c.reset_table_name}
|
||||
classes.each(&:reset_table_name)
|
||||
end
|
||||
|
||||
def test_destroy_all
|
||||
|
@ -439,18 +481,18 @@ class BasicsTest < Test::Unit::TestCase
|
|||
|
||||
def test_increment_counter
|
||||
Topic.increment_counter("replies_count", 1)
|
||||
assert_equal 1, Topic.find(1).replies_count
|
||||
assert_equal 2, Topic.find(1).replies_count
|
||||
|
||||
Topic.increment_counter("replies_count", 1)
|
||||
assert_equal 2, Topic.find(1).replies_count
|
||||
assert_equal 3, Topic.find(1).replies_count
|
||||
end
|
||||
|
||||
def test_decrement_counter
|
||||
Topic.decrement_counter("replies_count", 2)
|
||||
assert_equal 1, Topic.find(2).replies_count
|
||||
assert_equal -1, Topic.find(2).replies_count
|
||||
|
||||
Topic.decrement_counter("replies_count", 2)
|
||||
assert_equal 0, Topic.find(1).replies_count
|
||||
assert_equal -2, Topic.find(2).replies_count
|
||||
end
|
||||
|
||||
def test_update_all
|
||||
|
@ -549,16 +591,29 @@ class BasicsTest < Test::Unit::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
def test_utc_as_time_zone
|
||||
# Oracle and SQLServer do not have a TIME datatype.
|
||||
return true if current_adapter?(:SQLServerAdapter) || current_adapter?(:OracleAdapter)
|
||||
# Oracle, SQLServer, and Sybase do not have a TIME datatype.
|
||||
unless current_adapter?(:SQLServerAdapter, :OracleAdapter, :SybaseAdapter)
|
||||
def test_utc_as_time_zone
|
||||
Topic.default_timezone = :utc
|
||||
attributes = { "bonus_time" => "5:42:00AM" }
|
||||
topic = Topic.find(1)
|
||||
topic.attributes = attributes
|
||||
assert_equal Time.utc(2000, 1, 1, 5, 42, 0), topic.bonus_time
|
||||
Topic.default_timezone = :local
|
||||
end
|
||||
|
||||
Topic.default_timezone = :utc
|
||||
attributes = { "bonus_time" => "5:42:00AM" }
|
||||
topic = Topic.find(1)
|
||||
topic.attributes = attributes
|
||||
assert_equal Time.utc(2000, 1, 1, 5, 42, 0), topic.bonus_time
|
||||
Topic.default_timezone = :local
|
||||
def test_utc_as_time_zone_and_new
|
||||
Topic.default_timezone = :utc
|
||||
attributes = { "bonus_time(1i)"=>"2000",
|
||||
"bonus_time(2i)"=>"1",
|
||||
"bonus_time(3i)"=>"1",
|
||||
"bonus_time(4i)"=>"10",
|
||||
"bonus_time(5i)"=>"35",
|
||||
"bonus_time(6i)"=>"50" }
|
||||
topic = Topic.new(attributes)
|
||||
assert_equal Time.utc(2000, 1, 1, 10, 35, 50), topic.bonus_time
|
||||
Topic.default_timezone = :local
|
||||
end
|
||||
end
|
||||
|
||||
def test_default_values_on_empty_strings
|
||||
|
@ -614,11 +669,55 @@ class BasicsTest < Test::Unit::TestCase
|
|||
assert !Topic.find(1).approved?
|
||||
end
|
||||
|
||||
def test_update_attributes
|
||||
topic = Topic.find(1)
|
||||
assert !topic.approved?
|
||||
assert_equal "The First Topic", topic.title
|
||||
|
||||
topic.update_attributes("approved" => true, "title" => "The First Topic Updated")
|
||||
topic.reload
|
||||
assert topic.approved?
|
||||
assert_equal "The First Topic Updated", topic.title
|
||||
|
||||
topic.update_attributes(:approved => false, :title => "The First Topic")
|
||||
topic.reload
|
||||
assert !topic.approved?
|
||||
assert_equal "The First Topic", topic.title
|
||||
end
|
||||
|
||||
def test_update_attributes!
|
||||
reply = Reply.find(2)
|
||||
assert_equal "The Second Topic's of the day", reply.title
|
||||
assert_equal "Have a nice day", reply.content
|
||||
|
||||
reply.update_attributes!("title" => "The Second Topic's of the day updated", "content" => "Have a nice evening")
|
||||
reply.reload
|
||||
assert_equal "The Second Topic's of the day updated", reply.title
|
||||
assert_equal "Have a nice evening", reply.content
|
||||
|
||||
reply.update_attributes!(:title => "The Second Topic's of the day", :content => "Have a nice day")
|
||||
reply.reload
|
||||
assert_equal "The Second Topic's of the day", reply.title
|
||||
assert_equal "Have a nice day", reply.content
|
||||
|
||||
assert_raise(ActiveRecord::RecordInvalid) { reply.update_attributes!(:title => nil, :content => "Have a nice evening") }
|
||||
end
|
||||
|
||||
def test_mass_assignment_protection
|
||||
firm = Firm.new
|
||||
firm.attributes = { "name" => "Next Angle", "rating" => 5 }
|
||||
assert_equal 1, firm.rating
|
||||
end
|
||||
|
||||
def test_mass_assignment_protection_against_class_attribute_writers
|
||||
[:logger, :configurations, :primary_key_prefix_type, :table_name_prefix, :table_name_suffix, :pluralize_table_names, :colorize_logging,
|
||||
:default_timezone, :allow_concurrency, :generate_read_methods, :schema_format, :verification_timeout, :lock_optimistically, :record_timestamps].each do |method|
|
||||
assert Task.respond_to?(method)
|
||||
assert Task.respond_to?("#{method}=")
|
||||
assert Task.new.respond_to?(method)
|
||||
assert !Task.new.respond_to?("#{method}=")
|
||||
end
|
||||
end
|
||||
|
||||
def test_customized_primary_key_remains_protected
|
||||
subscriber = Subscriber.new(:nick => 'webster123', :name => 'nice try')
|
||||
|
@ -732,8 +831,8 @@ class BasicsTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_attributes_on_dummy_time
|
||||
# Oracle and SQL Server do not have a TIME datatype.
|
||||
return true if current_adapter?(:SQLServerAdapter) || current_adapter?(:OracleAdapter)
|
||||
# Oracle, SQL Server, and Sybase do not have a TIME datatype.
|
||||
return true if current_adapter?(:SQLServerAdapter, :OracleAdapter, :SybaseAdapter)
|
||||
|
||||
attributes = {
|
||||
"bonus_time" => "5:42:00AM"
|
||||
|
@ -903,12 +1002,44 @@ class BasicsTest < Test::Unit::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
class NumericData < ActiveRecord::Base
|
||||
self.table_name = 'numeric_data'
|
||||
end
|
||||
|
||||
def test_numeric_fields
|
||||
m = NumericData.new(
|
||||
:bank_balance => 1586.43,
|
||||
:big_bank_balance => BigDecimal("1000234000567.95"),
|
||||
:world_population => 6000000000,
|
||||
:my_house_population => 3
|
||||
)
|
||||
assert m.save
|
||||
|
||||
m1 = NumericData.find(m.id)
|
||||
assert_not_nil m1
|
||||
|
||||
# As with migration_test.rb, we should make world_population >= 2**62
|
||||
# to cover 64-bit platforms and test it is a Bignum, but the main thing
|
||||
# is that it's an Integer.
|
||||
assert_kind_of Integer, m1.world_population
|
||||
assert_equal 6000000000, m1.world_population
|
||||
|
||||
assert_kind_of Fixnum, m1.my_house_population
|
||||
assert_equal 3, m1.my_house_population
|
||||
|
||||
assert_kind_of BigDecimal, m1.bank_balance
|
||||
assert_equal BigDecimal("1586.43"), m1.bank_balance
|
||||
|
||||
assert_kind_of BigDecimal, m1.big_bank_balance
|
||||
assert_equal BigDecimal("1000234000567.95"), m1.big_bank_balance
|
||||
end
|
||||
|
||||
def test_auto_id
|
||||
auto = AutoId.new
|
||||
auto.save
|
||||
assert (auto.id > 0)
|
||||
end
|
||||
|
||||
|
||||
def quote_column_name(name)
|
||||
"<#{name}>"
|
||||
end
|
||||
|
@ -923,13 +1054,9 @@ class BasicsTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_sql_injection_via_find
|
||||
assert_raises(ActiveRecord::RecordNotFound) do
|
||||
assert_raises(ActiveRecord::RecordNotFound, ActiveRecord::StatementInvalid) do
|
||||
Topic.find("123456 OR id > 0")
|
||||
end
|
||||
|
||||
assert_raises(ActiveRecord::RecordNotFound) do
|
||||
Topic.find(";;; this should raise an RecordNotFound error")
|
||||
end
|
||||
end
|
||||
|
||||
def test_column_name_properly_quoted
|
||||
|
@ -942,6 +1069,14 @@ class BasicsTest < Test::Unit::TestCase
|
|||
assert_equal(41, c2.references)
|
||||
end
|
||||
|
||||
def test_quoting_arrays
|
||||
replies = Reply.find(:all, :conditions => [ "id IN (?)", topics(:first).replies.collect(&:id) ])
|
||||
assert_equal topics(:first).replies.size, replies.size
|
||||
|
||||
replies = Reply.find(:all, :conditions => [ "id IN (?)", [] ])
|
||||
assert_equal 0, replies.size
|
||||
end
|
||||
|
||||
MyObject = Struct.new :attribute1, :attribute2
|
||||
|
||||
def test_serialized_attribute
|
||||
|
@ -970,6 +1105,18 @@ class BasicsTest < Test::Unit::TestCase
|
|||
assert_equal author_name, Topic.find(topic.id).author_name
|
||||
end
|
||||
|
||||
def test_quote_chars
|
||||
str = 'The Narrator'
|
||||
topic = Topic.create(:author_name => str)
|
||||
assert_equal str, topic.author_name
|
||||
|
||||
assert_kind_of ActiveSupport::Multibyte::Chars, str.chars
|
||||
topic = Topic.find_by_author_name(str.chars)
|
||||
|
||||
assert_kind_of Topic, topic
|
||||
assert_equal str, topic.author_name, "The right topic should have been found by name even with name passed as Chars"
|
||||
end
|
||||
|
||||
def test_class_level_destroy
|
||||
should_be_destroyed_reply = Reply.create("title" => "hello", "content" => "world")
|
||||
Topic.find(1).replies << should_be_destroyed_reply
|
||||
|
@ -989,12 +1136,12 @@ class BasicsTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_increment_attribute
|
||||
assert_equal 0, topics(:first).replies_count
|
||||
assert_equal 1, topics(:first).replies_count
|
||||
topics(:first).increment! :replies_count
|
||||
assert_equal 1, topics(:first, :reload).replies_count
|
||||
assert_equal 2, topics(:first, :reload).replies_count
|
||||
|
||||
topics(:first).increment(:replies_count).increment!(:replies_count)
|
||||
assert_equal 3, topics(:first, :reload).replies_count
|
||||
assert_equal 4, topics(:first, :reload).replies_count
|
||||
end
|
||||
|
||||
def test_increment_nil_attribute
|
||||
|
@ -1005,13 +1152,13 @@ class BasicsTest < Test::Unit::TestCase
|
|||
|
||||
def test_decrement_attribute
|
||||
topics(:first).increment(:replies_count).increment!(:replies_count)
|
||||
assert_equal 2, topics(:first).replies_count
|
||||
assert_equal 3, topics(:first).replies_count
|
||||
|
||||
topics(:first).decrement!(:replies_count)
|
||||
assert_equal 1, topics(:first, :reload).replies_count
|
||||
assert_equal 2, topics(:first, :reload).replies_count
|
||||
|
||||
topics(:first).decrement(:replies_count).decrement!(:replies_count)
|
||||
assert_equal -1, topics(:first, :reload).replies_count
|
||||
assert_equal 0, topics(:first, :reload).replies_count
|
||||
end
|
||||
|
||||
def test_toggle_attribute
|
||||
|
@ -1091,7 +1238,7 @@ class BasicsTest < Test::Unit::TestCase
|
|||
def test_count_with_join
|
||||
res = Post.count_by_sql "SELECT COUNT(*) FROM posts LEFT JOIN comments ON posts.id=comments.post_id WHERE posts.#{QUOTED_TYPE} = 'Post'"
|
||||
res2 = nil
|
||||
assert_nothing_raised do
|
||||
assert_deprecated 'count' do
|
||||
res2 = Post.count("posts.#{QUOTED_TYPE} = 'Post'",
|
||||
"LEFT JOIN comments ON posts.id=comments.post_id")
|
||||
end
|
||||
|
@ -1104,21 +1251,21 @@ class BasicsTest < Test::Unit::TestCase
|
|||
end
|
||||
assert_equal res, res3
|
||||
|
||||
res4 = Post.count_by_sql "SELECT COUNT(p.id) FROM posts p, comments c WHERE p.#{QUOTED_TYPE} = 'Post' AND p.id=c.post_id"
|
||||
res4 = Post.count_by_sql "SELECT COUNT(p.id) FROM posts p, comments co WHERE p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id"
|
||||
res5 = nil
|
||||
assert_nothing_raised do
|
||||
res5 = Post.count(:conditions => "p.#{QUOTED_TYPE} = 'Post' AND p.id=c.post_id",
|
||||
:joins => "p, comments c",
|
||||
res5 = Post.count(:conditions => "p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id",
|
||||
:joins => "p, comments co",
|
||||
:select => "p.id")
|
||||
end
|
||||
|
||||
assert_equal res4, res5
|
||||
|
||||
res6 = Post.count_by_sql "SELECT COUNT(DISTINCT p.id) FROM posts p, comments c WHERE p.#{QUOTED_TYPE} = 'Post' AND p.id=c.post_id"
|
||||
res6 = Post.count_by_sql "SELECT COUNT(DISTINCT p.id) FROM posts p, comments co WHERE p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id"
|
||||
res7 = nil
|
||||
assert_nothing_raised do
|
||||
res7 = Post.count(:conditions => "p.#{QUOTED_TYPE} = 'Post' AND p.id=c.post_id",
|
||||
:joins => "p, comments c",
|
||||
res7 = Post.count(:conditions => "p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id",
|
||||
:joins => "p, comments co",
|
||||
:select => "p.id",
|
||||
:distinct => true)
|
||||
end
|
||||
|
@ -1174,13 +1321,104 @@ class BasicsTest < Test::Unit::TestCase
|
|||
assert_equal Developer.count, developers.size
|
||||
end
|
||||
|
||||
def test_base_class
|
||||
def test_scoped_find_order
|
||||
# Test order in scope
|
||||
scoped_developers = Developer.with_scope(:find => { :limit => 1, :order => 'salary DESC' }) do
|
||||
Developer.find(:all)
|
||||
end
|
||||
assert_equal 'Jamis', scoped_developers.first.name
|
||||
assert scoped_developers.include?(developers(:jamis))
|
||||
# Test scope without order and order in find
|
||||
scoped_developers = Developer.with_scope(:find => { :limit => 1 }) do
|
||||
Developer.find(:all, :order => 'salary DESC')
|
||||
end
|
||||
# Test scope order + find order, find has priority
|
||||
scoped_developers = Developer.with_scope(:find => { :limit => 3, :order => 'id DESC' }) do
|
||||
Developer.find(:all, :order => 'salary ASC')
|
||||
end
|
||||
assert scoped_developers.include?(developers(:poor_jamis))
|
||||
assert scoped_developers.include?(developers(:david))
|
||||
assert scoped_developers.include?(developers(:dev_10))
|
||||
# Test without scoped find conditions to ensure we get the right thing
|
||||
developers = Developer.find(:all, :order => 'id', :limit => 1)
|
||||
assert scoped_developers.include?(developers(:david))
|
||||
end
|
||||
|
||||
def test_scoped_find_limit_offset_including_has_many_association
|
||||
topics = Topic.with_scope(:find => {:limit => 1, :offset => 1, :include => :replies}) do
|
||||
Topic.find(:all, :order => "topics.id")
|
||||
end
|
||||
assert_equal 1, topics.size
|
||||
assert_equal 2, topics.first.id
|
||||
end
|
||||
|
||||
def test_scoped_find_order_including_has_many_association
|
||||
developers = Developer.with_scope(:find => { :order => 'developers.salary DESC', :include => :projects }) do
|
||||
Developer.find(:all)
|
||||
end
|
||||
assert developers.size >= 2
|
||||
for i in 1...developers.size
|
||||
assert developers[i-1].salary >= developers[i].salary
|
||||
end
|
||||
end
|
||||
|
||||
def test_abstract_class
|
||||
assert !ActiveRecord::Base.abstract_class?
|
||||
assert LoosePerson.abstract_class?
|
||||
assert !LooseDescendant.abstract_class?
|
||||
end
|
||||
|
||||
def test_base_class
|
||||
assert_equal LoosePerson, LoosePerson.base_class
|
||||
assert_equal LooseDescendant, LooseDescendant.base_class
|
||||
assert_equal TightPerson, TightPerson.base_class
|
||||
assert_equal TightPerson, TightDescendant.base_class
|
||||
|
||||
assert_equal Post, Post.base_class
|
||||
assert_equal Post, SpecialPost.base_class
|
||||
assert_equal Post, StiPost.base_class
|
||||
assert_equal SubStiPost, SubStiPost.base_class
|
||||
end
|
||||
|
||||
def test_descends_from_active_record
|
||||
# Tries to call Object.abstract_class?
|
||||
assert_raise(NoMethodError) do
|
||||
ActiveRecord::Base.descends_from_active_record?
|
||||
end
|
||||
|
||||
# Abstract subclass of AR::Base.
|
||||
assert LoosePerson.descends_from_active_record?
|
||||
|
||||
# Concrete subclass of an abstract class.
|
||||
assert LooseDescendant.descends_from_active_record?
|
||||
|
||||
# Concrete subclass of AR::Base.
|
||||
assert TightPerson.descends_from_active_record?
|
||||
|
||||
# Concrete subclass of a concrete class but has no type column.
|
||||
assert TightDescendant.descends_from_active_record?
|
||||
|
||||
# Concrete subclass of AR::Base.
|
||||
assert Post.descends_from_active_record?
|
||||
|
||||
# Abstract subclass of a concrete class which has a type column.
|
||||
# This is pathological, as you'll never have Sub < Abstract < Concrete.
|
||||
assert !StiPost.descends_from_active_record?
|
||||
|
||||
# Concrete subclasses an abstract class which has a type column.
|
||||
assert !SubStiPost.descends_from_active_record?
|
||||
end
|
||||
|
||||
def test_find_on_abstract_base_class_doesnt_use_type_condition
|
||||
old_class = LooseDescendant
|
||||
Object.send :remove_const, :LooseDescendant
|
||||
|
||||
descendant = old_class.create!
|
||||
assert_not_nil LoosePerson.find(descendant.id), "Should have found instance of LooseDescendant when finding abstract LoosePerson: #{descendant.inspect}"
|
||||
ensure
|
||||
unless Object.const_defined?(:LooseDescendant)
|
||||
Object.const_set :LooseDescendant, old_class
|
||||
end
|
||||
end
|
||||
|
||||
def test_assert_queries
|
||||
|
@ -1199,41 +1437,65 @@ class BasicsTest < Test::Unit::TestCase
|
|||
assert xml.include?(%(<title>The First Topic</title>))
|
||||
assert xml.include?(%(<author-name>David</author-name>))
|
||||
assert xml.include?(%(<id type="integer">1</id>))
|
||||
assert xml.include?(%(<replies-count type="integer">0</replies-count>))
|
||||
assert xml.include?(%(<replies-count type="integer">1</replies-count>))
|
||||
assert xml.include?(%(<written-on type="datetime">#{written_on_in_current_timezone}</written-on>))
|
||||
assert xml.include?(%(<content>Have a nice day</content>))
|
||||
assert xml.include?(%(<author-email-address>david@loudthinking.com</author-email-address>))
|
||||
assert xml.include?(%(<parent-id></parent-id>))
|
||||
if current_adapter?(:SybaseAdapter) or current_adapter?(:SQLServerAdapter)
|
||||
assert xml.match(%(<parent-id type="integer"></parent-id>))
|
||||
if current_adapter?(:SybaseAdapter, :SQLServerAdapter, :OracleAdapter)
|
||||
assert xml.include?(%(<last-read type="datetime">#{last_read_in_current_timezone}</last-read>))
|
||||
else
|
||||
assert xml.include?(%(<last-read type="date">2004-04-15</last-read>))
|
||||
end
|
||||
# Oracle and DB2 don't have true boolean or time-only fields
|
||||
unless current_adapter?(:OracleAdapter) || current_adapter?(:DB2Adapter)
|
||||
unless current_adapter?(:OracleAdapter, :DB2Adapter)
|
||||
assert xml.include?(%(<approved type="boolean">false</approved>)), "Approved should be a boolean"
|
||||
assert xml.include?(%(<bonus-time type="datetime">#{bonus_time_in_current_timezone}</bonus-time>))
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def test_to_xml_skipping_attributes
|
||||
xml = topics(:first).to_xml(:indent => 0, :skip_instruct => true, :except => :title)
|
||||
xml = topics(:first).to_xml(:indent => 0, :skip_instruct => true, :except => [:title, :replies_count])
|
||||
assert_equal "<topic>", xml.first(7)
|
||||
assert !xml.include?(%(<title>The First Topic</title>))
|
||||
assert xml.include?(%(<author-name>David</author-name>))
|
||||
|
||||
xml = topics(:first).to_xml(:indent => 0, :skip_instruct => true, :except => [ :title, :author_name ])
|
||||
xml = topics(:first).to_xml(:indent => 0, :skip_instruct => true, :except => [:title, :author_name, :replies_count])
|
||||
assert !xml.include?(%(<title>The First Topic</title>))
|
||||
assert !xml.include?(%(<author-name>David</author-name>))
|
||||
end
|
||||
|
||||
|
||||
def test_to_xml_including_has_many_association
|
||||
xml = topics(:first).to_xml(:indent => 0, :skip_instruct => true, :include => :replies)
|
||||
xml = topics(:first).to_xml(:indent => 0, :skip_instruct => true, :include => :replies, :except => :replies_count)
|
||||
assert_equal "<topic>", xml.first(7)
|
||||
assert xml.include?(%(<replies><reply>))
|
||||
assert xml.include?(%(<title>The Second Topic's of the day</title>))
|
||||
end
|
||||
|
||||
def test_array_to_xml_including_has_many_association
|
||||
xml = [ topics(:first), topics(:second) ].to_xml(:indent => 0, :skip_instruct => true, :include => :replies)
|
||||
assert xml.include?(%(<replies><reply>))
|
||||
end
|
||||
|
||||
def test_array_to_xml_including_methods
|
||||
xml = [ topics(:first), topics(:second) ].to_xml(:indent => 0, :skip_instruct => true, :methods => [ :topic_id ])
|
||||
assert xml.include?(%(<topic-id type="integer">#{topics(:first).topic_id}</topic-id>)), xml
|
||||
assert xml.include?(%(<topic-id type="integer">#{topics(:second).topic_id}</topic-id>)), xml
|
||||
end
|
||||
|
||||
def test_array_to_xml_including_has_one_association
|
||||
xml = [ companies(:first_firm), companies(:rails_core) ].to_xml(:indent => 0, :skip_instruct => true, :include => :account)
|
||||
assert xml.include?(companies(:first_firm).account.to_xml(:indent => 0, :skip_instruct => true))
|
||||
assert xml.include?(companies(:rails_core).account.to_xml(:indent => 0, :skip_instruct => true))
|
||||
end
|
||||
|
||||
def test_array_to_xml_including_belongs_to_association
|
||||
xml = [ companies(:first_client), companies(:second_client), companies(:another_client) ].to_xml(:indent => 0, :skip_instruct => true, :include => :firm)
|
||||
assert xml.include?(companies(:first_client).to_xml(:indent => 0, :skip_instruct => true))
|
||||
assert xml.include?(companies(:second_client).firm.to_xml(:indent => 0, :skip_instruct => true))
|
||||
assert xml.include?(companies(:another_client).firm.to_xml(:indent => 0, :skip_instruct => true))
|
||||
end
|
||||
|
||||
def test_to_xml_including_belongs_to_association
|
||||
xml = companies(:first_client).to_xml(:indent => 0, :skip_instruct => true, :include => :firm)
|
||||
assert !xml.include?("<firm>")
|
||||
|
@ -1260,6 +1522,12 @@ class BasicsTest < Test::Unit::TestCase
|
|||
assert xml.include?(%(<clients><client>))
|
||||
end
|
||||
|
||||
def test_to_xml_including_methods
|
||||
xml = Company.new.to_xml(:methods => :arbitrary_method, :skip_instruct => true)
|
||||
assert_equal "<company>", xml.first(9)
|
||||
assert xml.include?(%(<arbitrary-method>I am Jack's profound disappointment</arbitrary-method>))
|
||||
end
|
||||
|
||||
def test_except_attributes
|
||||
assert_equal(
|
||||
%w( author_name type id approved replies_count bonus_time written_on content author_email_address parent_id last_read),
|
||||
|
@ -1281,6 +1549,10 @@ class BasicsTest < Test::Unit::TestCase
|
|||
assert_equal 'ActiveRecord::Person', ActiveRecord::Base.send(:type_name_with_module, 'Person')
|
||||
assert_equal '::Person', ActiveRecord::Base.send(:type_name_with_module, '::Person')
|
||||
end
|
||||
|
||||
def test_to_param_should_return_string
|
||||
assert_kind_of String, Client.find(:first).to_param
|
||||
end
|
||||
|
||||
# FIXME: this test ought to run, but it needs to run sandboxed so that it
|
||||
# doesn't b0rk the current test environment by undefing everything.
|
||||
|
@ -1306,7 +1578,7 @@ class BasicsTest < Test::Unit::TestCase
|
|||
|
||||
private
|
||||
def assert_readers(model, exceptions)
|
||||
expected_readers = Set.new(model.column_names - (model.serialized_attributes.keys + ['id']))
|
||||
expected_readers = Set.new(model.column_names - ['id'])
|
||||
expected_readers += expected_readers.map { |col| "#{col}?" }
|
||||
expected_readers -= exceptions
|
||||
assert_equal expected_readers, model.read_methods
|
||||
|
|
|
@ -8,19 +8,29 @@ class CalculationsTest < Test::Unit::TestCase
|
|||
fixtures :companies, :accounts, :topics
|
||||
|
||||
def test_should_sum_field
|
||||
assert_equal 265, Account.sum(:credit_limit)
|
||||
assert_equal 318, Account.sum(:credit_limit)
|
||||
end
|
||||
|
||||
def test_should_average_field
|
||||
value = Account.average(:credit_limit)
|
||||
assert_equal 53, value
|
||||
assert_kind_of Float, value
|
||||
assert_in_delta 53.0, value, 0.001
|
||||
end
|
||||
|
||||
def test_should_get_maximum_of_field
|
||||
assert_equal 60, Account.maximum(:credit_limit)
|
||||
end
|
||||
|
||||
def test_should_get_maximum_of_field_with_include
|
||||
assert_equal 50, Account.maximum(:credit_limit, :include => :firm, :conditions => "companies.name != 'Summit'")
|
||||
end
|
||||
|
||||
def test_should_get_maximum_of_field_with_scoped_include
|
||||
Account.with_scope :find => { :include => :firm, :conditions => "companies.name != 'Summit'" } do
|
||||
assert_equal 50, Account.maximum(:credit_limit)
|
||||
end
|
||||
end
|
||||
|
||||
def test_should_get_minimum_of_field
|
||||
assert_equal 50, Account.minimum(:credit_limit)
|
||||
end
|
||||
|
@ -39,13 +49,13 @@ class CalculationsTest < Test::Unit::TestCase
|
|||
|
||||
def test_should_order_by_grouped_field
|
||||
c = Account.sum(:credit_limit, :group => :firm_id, :order => "firm_id")
|
||||
assert_equal [1, 2, 6], c.keys.compact
|
||||
assert_equal [1, 2, 6, 9], c.keys.compact
|
||||
end
|
||||
|
||||
def test_should_order_by_calculation
|
||||
c = Account.sum(:credit_limit, :group => :firm_id, :order => "sum_credit_limit desc, firm_id")
|
||||
assert_equal [105, 60, 50, 50], c.keys.collect { |k| c[k] }
|
||||
assert_equal [6, 2, 1], c.keys.compact
|
||||
assert_equal [105, 60, 53, 50, 50], c.keys.collect { |k| c[k] }
|
||||
assert_equal [6, 2, 9, 1], c.keys.compact
|
||||
end
|
||||
|
||||
def test_should_limit_calculation
|
||||
|
@ -104,8 +114,8 @@ class CalculationsTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_should_calculate_with_invalid_field
|
||||
assert_equal 5, Account.calculate(:count, '*')
|
||||
assert_equal 5, Account.calculate(:count, :all)
|
||||
assert_equal 6, Account.calculate(:count, '*')
|
||||
assert_equal 6, Account.calculate(:count, :all)
|
||||
end
|
||||
|
||||
def test_should_calculate_grouped_with_invalid_field
|
||||
|
@ -121,9 +131,17 @@ class CalculationsTest < Test::Unit::TestCase
|
|||
assert_equal 2, c[companies(:rails_core)]
|
||||
assert_equal 1, c[companies(:first_client)]
|
||||
end
|
||||
|
||||
def test_should_not_modify_options_when_using_includes
|
||||
options = {:conditions => 'companies.id > 1', :include => :firm}
|
||||
options_copy = options.dup
|
||||
|
||||
Account.count(:all, options)
|
||||
assert_equal options_copy, options
|
||||
end
|
||||
|
||||
def test_should_calculate_grouped_by_function
|
||||
c = Company.count(:all, :group => 'UPPER(type)')
|
||||
c = Company.count(:all, :group => "UPPER(#{QUOTED_TYPE})")
|
||||
assert_equal 2, c[nil]
|
||||
assert_equal 1, c['DEPENDENTFIRM']
|
||||
assert_equal 3, c['CLIENT']
|
||||
|
@ -131,12 +149,16 @@ class CalculationsTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_should_calculate_grouped_by_function_with_table_alias
|
||||
c = Company.count(:all, :group => 'UPPER(companies.type)')
|
||||
c = Company.count(:all, :group => "UPPER(companies.#{QUOTED_TYPE})")
|
||||
assert_equal 2, c[nil]
|
||||
assert_equal 1, c['DEPENDENTFIRM']
|
||||
assert_equal 3, c['CLIENT']
|
||||
assert_equal 2, c['FIRM']
|
||||
end
|
||||
|
||||
def test_should_not_overshadow_enumerable_sum
|
||||
assert_equal 6, [1, 2, 3].sum(&:abs)
|
||||
end
|
||||
|
||||
def test_should_sum_scoped_field
|
||||
assert_equal 15, companies(:rails_core).companies.sum(:id)
|
||||
|
@ -174,8 +196,24 @@ class CalculationsTest < Test::Unit::TestCase
|
|||
Company.send(:validate_calculation_options, :count, :include => true)
|
||||
end
|
||||
|
||||
assert_raises(ArgumentError) { Company.send(:validate_calculation_options, :sum, :include => :posts) }
|
||||
assert_raises(ArgumentError) { Company.send(:validate_calculation_options, :sum, :foo => :bar) }
|
||||
assert_raises(ArgumentError) { Company.send(:validate_calculation_options, :count, :foo => :bar) }
|
||||
end
|
||||
|
||||
def test_should_count_selected_field_with_include
|
||||
assert_equal 6, Account.count(:distinct => true, :include => :firm)
|
||||
assert_equal 4, Account.count(:distinct => true, :include => :firm, :select => :credit_limit)
|
||||
end
|
||||
|
||||
def test_deprecated_count_with_string_parameters
|
||||
assert_deprecated('count') { Account.count('credit_limit > 50') }
|
||||
end
|
||||
|
||||
def test_count_with_no_parameters_isnt_deprecated
|
||||
assert_not_deprecated { Account.count }
|
||||
end
|
||||
|
||||
def test_count_with_too_many_parameters_raises
|
||||
assert_raise(ArgumentError) { Account.count(1, 2, 3) }
|
||||
end
|
||||
end
|
||||
|
|
13
vendor/rails/activerecord/test/callbacks_test.rb
vendored
13
vendor/rails/activerecord/test/callbacks_test.rb
vendored
|
@ -109,6 +109,13 @@ class ImmutableMethodDeveloper < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
class CallbackCancellationDeveloper < ActiveRecord::Base
|
||||
set_table_name 'developers'
|
||||
def before_create
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
class CallbacksTest < Test::Unit::TestCase
|
||||
fixtures :developers
|
||||
|
||||
|
@ -334,6 +341,12 @@ class CallbacksTest < Test::Unit::TestCase
|
|||
assert_raises(ActiveRecord::RecordInvalid) { david.save! }
|
||||
end
|
||||
|
||||
def test_before_create_returning_false
|
||||
someone = CallbackCancellationDeveloper.new
|
||||
assert someone.valid?
|
||||
assert !someone.save
|
||||
end
|
||||
|
||||
def test_before_destroy_returning_false
|
||||
david = ImmutableDeveloper.find(1)
|
||||
assert !david.destroy
|
||||
|
|
|
@ -4,21 +4,22 @@ require 'logger'
|
|||
|
||||
ActiveRecord::Base.logger = Logger.new("debug.log")
|
||||
|
||||
db1 = 'arunit'
|
||||
db2 = 'arunit2'
|
||||
ActiveRecord::Base.configurations = {
|
||||
'arunit' => {
|
||||
:adapter => 'db2',
|
||||
:host => 'localhost',
|
||||
:username => 'arunit',
|
||||
:password => 'arunit',
|
||||
:database => 'arunit'
|
||||
},
|
||||
'arunit2' => {
|
||||
:adapter => 'db2',
|
||||
:host => 'localhost',
|
||||
:username => 'arunit',
|
||||
:password => 'arunit',
|
||||
:database => 'arunit2'
|
||||
}
|
||||
}
|
||||
|
||||
ActiveRecord::Base.establish_connection(
|
||||
:adapter => "db2",
|
||||
:host => "localhost",
|
||||
:username => "arunit",
|
||||
:password => "arunit",
|
||||
:database => db1
|
||||
)
|
||||
|
||||
Course.establish_connection(
|
||||
:adapter => "db2",
|
||||
:host => "localhost",
|
||||
:username => "arunit2",
|
||||
:password => "arunit2",
|
||||
:database => db2
|
||||
)
|
||||
ActiveRecord::Base.establish_connection 'arunit'
|
||||
Course.establish_connection 'arunit2'
|
||||
|
|
|
@ -4,21 +4,23 @@ require 'logger'
|
|||
|
||||
ActiveRecord::Base.logger = Logger.new("debug.log")
|
||||
|
||||
db1 = 'activerecord_unittest'
|
||||
db2 = 'activerecord_unittest2'
|
||||
ActiveRecord::Base.configurations = {
|
||||
'arunit' => {
|
||||
:adapter => 'firebird',
|
||||
:host => 'localhost',
|
||||
:username => 'rails',
|
||||
:password => 'rails',
|
||||
:database => 'activerecord_unittest',
|
||||
:charset => 'UTF8'
|
||||
},
|
||||
'arunit2' => {
|
||||
:adapter => 'firebird',
|
||||
:host => 'localhost',
|
||||
:username => 'rails',
|
||||
:password => 'rails',
|
||||
:database => 'activerecord_unittest2'
|
||||
}
|
||||
}
|
||||
|
||||
ActiveRecord::Base.establish_connection(
|
||||
:adapter => "firebird",
|
||||
:host => "localhost",
|
||||
:username => "rails",
|
||||
:password => "rails",
|
||||
:database => db1
|
||||
)
|
||||
|
||||
Course.establish_connection(
|
||||
:adapter => "firebird",
|
||||
:host => "localhost",
|
||||
:username => "rails",
|
||||
:password => "rails",
|
||||
:database => db2
|
||||
)
|
||||
ActiveRecord::Base.establish_connection 'arunit'
|
||||
Course.establish_connection 'arunit2'
|
||||
|
|
|
@ -2,20 +2,23 @@ print "Using native MySQL\n"
|
|||
require_dependency 'fixtures/course'
|
||||
require 'logger'
|
||||
|
||||
ActiveRecord::Base.logger = Logger.new("debug.log")
|
||||
RAILS_DEFAULT_LOGGER = Logger.new('debug.log')
|
||||
RAILS_DEFAULT_LOGGER.level = Logger::DEBUG
|
||||
ActiveRecord::Base.logger = RAILS_DEFAULT_LOGGER
|
||||
|
||||
db1 = 'activerecord_unittest'
|
||||
db2 = 'activerecord_unittest2'
|
||||
ActiveRecord::Base.configurations = {
|
||||
'arunit' => {
|
||||
:adapter => 'mysql',
|
||||
:username => 'rails',
|
||||
:encoding => 'utf8',
|
||||
:database => 'activerecord_unittest',
|
||||
},
|
||||
'arunit2' => {
|
||||
:adapter => 'mysql',
|
||||
:username => 'rails',
|
||||
:database => 'activerecord_unittest2'
|
||||
}
|
||||
}
|
||||
|
||||
ActiveRecord::Base.establish_connection(
|
||||
:adapter => "mysql",
|
||||
:username => "rails",
|
||||
:encoding => "utf8",
|
||||
:database => db1
|
||||
)
|
||||
|
||||
Course.establish_connection(
|
||||
:adapter => "mysql",
|
||||
:username => "rails",
|
||||
:database => db2
|
||||
)
|
||||
ActiveRecord::Base.establish_connection 'arunit'
|
||||
Course.establish_connection 'arunit2'
|
||||
|
|
|
@ -4,19 +4,18 @@ require 'logger'
|
|||
|
||||
ActiveRecord::Base.logger = Logger.new("debug.log")
|
||||
|
||||
db1 = 'activerecord_unittest'
|
||||
db2 = 'activerecord_unittest2'
|
||||
ActiveRecord::Base.configurations = {
|
||||
'arunit' => {
|
||||
:adapter => 'openbase',
|
||||
:username => 'admin',
|
||||
:database => 'activerecord_unittest',
|
||||
},
|
||||
'arunit2' => {
|
||||
:adapter => 'openbase',
|
||||
:username => 'admin',
|
||||
:database => 'activerecord_unittest2'
|
||||
}
|
||||
}
|
||||
|
||||
ActiveRecord::Base.establish_connection(
|
||||
:adapter => "openbase",
|
||||
:username => "admin",
|
||||
:password => "",
|
||||
:database => db1
|
||||
)
|
||||
|
||||
Course.establish_connection(
|
||||
:adapter => "openbase",
|
||||
:username => "admin",
|
||||
:password => "",
|
||||
:database => db2
|
||||
)
|
||||
ActiveRecord::Base.establish_connection 'arunit'
|
||||
Course.establish_connection 'arunit2'
|
||||
|
|
|
@ -8,16 +8,20 @@ ActiveRecord::Base.logger.level = Logger::WARN
|
|||
# Set these to your database connection strings
|
||||
db = ENV['ARUNIT_DB'] || 'activerecord_unittest'
|
||||
|
||||
ActiveRecord::Base.establish_connection(
|
||||
:adapter => 'oracle',
|
||||
:username => 'arunit',
|
||||
:password => 'arunit',
|
||||
:database => db
|
||||
)
|
||||
ActiveRecord::Base.configurations = {
|
||||
'arunit' => {
|
||||
:adapter => 'oracle',
|
||||
:username => 'arunit',
|
||||
:password => 'arunit',
|
||||
:database => db,
|
||||
},
|
||||
'arunit2' => {
|
||||
:adapter => 'oracle',
|
||||
:username => 'arunit2',
|
||||
:password => 'arunit2',
|
||||
:database => db
|
||||
}
|
||||
}
|
||||
|
||||
Course.establish_connection(
|
||||
:adapter => 'oracle',
|
||||
:username => 'arunit2',
|
||||
:password => 'arunit2',
|
||||
:database => db
|
||||
)
|
||||
ActiveRecord::Base.establish_connection 'arunit'
|
||||
Course.establish_connection 'arunit2'
|
||||
|
|
|
@ -4,21 +4,20 @@ require 'logger'
|
|||
|
||||
ActiveRecord::Base.logger = Logger.new("debug.log")
|
||||
|
||||
db1 = 'activerecord_unittest'
|
||||
db2 = 'activerecord_unittest2'
|
||||
ActiveRecord::Base.configurations = {
|
||||
'arunit' => {
|
||||
:adapter => 'postgresql',
|
||||
:username => 'postgres',
|
||||
:database => 'activerecord_unittest',
|
||||
:min_messages => 'warning'
|
||||
},
|
||||
'arunit2' => {
|
||||
:adapter => 'postgresql',
|
||||
:username => 'postgres',
|
||||
:database => 'activerecord_unittest2',
|
||||
:min_messages => 'warning'
|
||||
}
|
||||
}
|
||||
|
||||
ActiveRecord::Base.establish_connection(
|
||||
:adapter => "postgresql",
|
||||
:username => "postgres",
|
||||
:password => "postgres",
|
||||
:database => db1,
|
||||
:min_messages => "warning"
|
||||
)
|
||||
|
||||
Course.establish_connection(
|
||||
:adapter => "postgresql",
|
||||
:username => "postgres",
|
||||
:password => "postgres",
|
||||
:database => db2,
|
||||
:min_messages => "warning"
|
||||
)
|
||||
ActiveRecord::Base.establish_connection 'arunit'
|
||||
Course.establish_connection 'arunit2'
|
||||
|
|
|
@ -11,14 +11,13 @@ sqlite_test_db = "#{BASE_DIR}/fixture_database.sqlite"
|
|||
sqlite_test_db2 = "#{BASE_DIR}/fixture_database_2.sqlite"
|
||||
|
||||
def make_connection(clazz, db_file, db_definitions_file)
|
||||
ActiveRecord::Base.configurations = { clazz.name => { :adapter => 'sqlite', :database => db_file } }
|
||||
unless File.exist?(db_file)
|
||||
puts "SQLite database not found at #{db_file}. Rebuilding it."
|
||||
sqlite_command = %Q{sqlite #{db_file} "create table a (a integer); drop table a;"}
|
||||
puts "Executing '#{sqlite_command}'"
|
||||
raise SqliteError.new("Seems that there is no sqlite executable available") unless system(sqlite_command)
|
||||
clazz.establish_connection(
|
||||
:adapter => "sqlite",
|
||||
:database => db_file)
|
||||
clazz.establish_connection(clazz.name)
|
||||
script = File.read("#{BASE_DIR}/db_definitions/#{db_definitions_file}")
|
||||
# SQLite-Ruby has problems with semi-colon separated commands, so split and execute one at a time
|
||||
script.split(';').each do
|
||||
|
@ -26,9 +25,7 @@ def make_connection(clazz, db_file, db_definitions_file)
|
|||
clazz.connection.execute(command) unless command.strip.empty?
|
||||
end
|
||||
else
|
||||
clazz.establish_connection(
|
||||
:adapter => "sqlite",
|
||||
:database => db_file)
|
||||
clazz.establish_connection(clazz.name)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -11,14 +11,13 @@ sqlite_test_db = "#{BASE_DIR}/fixture_database.sqlite3"
|
|||
sqlite_test_db2 = "#{BASE_DIR}/fixture_database_2.sqlite3"
|
||||
|
||||
def make_connection(clazz, db_file, db_definitions_file)
|
||||
ActiveRecord::Base.configurations = { clazz.name => { :adapter => 'sqlite3', :database => db_file, :timeout => 5000 } }
|
||||
unless File.exist?(db_file)
|
||||
puts "SQLite3 database not found at #{db_file}. Rebuilding it."
|
||||
sqlite_command = %Q{sqlite3 #{db_file} "create table a (a integer); drop table a;"}
|
||||
puts "Executing '#{sqlite_command}'"
|
||||
raise SqliteError.new("Seems that there is no sqlite3 executable available") unless system(sqlite_command)
|
||||
clazz.establish_connection(
|
||||
:adapter => "sqlite3",
|
||||
:database => db_file)
|
||||
clazz.establish_connection(clazz.name)
|
||||
script = File.read("#{BASE_DIR}/db_definitions/#{db_definitions_file}")
|
||||
# SQLite-Ruby has problems with semi-colon separated commands, so split and execute one at a time
|
||||
script.split(';').each do
|
||||
|
@ -26,9 +25,7 @@ def make_connection(clazz, db_file, db_definitions_file)
|
|||
clazz.connection.execute(command) unless command.strip.empty?
|
||||
end
|
||||
else
|
||||
clazz.establish_connection(
|
||||
:adapter => "sqlite3",
|
||||
:database => db_file)
|
||||
clazz.establish_connection(clazz.name)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -4,21 +4,20 @@ require 'logger'
|
|||
|
||||
ActiveRecord::Base.logger = Logger.new("debug.log")
|
||||
|
||||
db1 = 'activerecord_unittest'
|
||||
db2 = 'activerecord_unittest2'
|
||||
ActiveRecord::Base.configurations = {
|
||||
'arunit' => {
|
||||
:adapter => 'sqlserver',
|
||||
:host => 'localhost',
|
||||
:username => 'sa',
|
||||
:database => 'activerecord_unittest'
|
||||
},
|
||||
'arunit2' => {
|
||||
:adapter => 'sqlserver',
|
||||
:host => 'localhost',
|
||||
:username => 'sa',
|
||||
:database => 'activerecord_unittest2'
|
||||
}
|
||||
}
|
||||
|
||||
ActiveRecord::Base.establish_connection(
|
||||
:adapter => "sqlserver",
|
||||
:host => "localhost",
|
||||
:username => "sa",
|
||||
:password => "",
|
||||
:database => db1
|
||||
)
|
||||
|
||||
Course.establish_connection(
|
||||
:adapter => "sqlserver",
|
||||
:host => "localhost",
|
||||
:username => "sa",
|
||||
:password => "",
|
||||
:database => db2
|
||||
)
|
||||
ActiveRecord::Base.establish_connection 'arunit'
|
||||
Course.establish_connection 'arunit2'
|
||||
|
|
|
@ -4,23 +4,22 @@ require 'logger'
|
|||
|
||||
ActiveRecord::Base.logger = Logger.new("debug.log")
|
||||
|
||||
dsn1 = 'activerecord_unittest'
|
||||
dsn2 = 'activerecord_unittest2'
|
||||
ActiveRecord::Base.configurations = {
|
||||
'arunit' => {
|
||||
:adapter => 'sqlserver',
|
||||
:mode => 'ODBC',
|
||||
:host => 'localhost',
|
||||
:username => 'sa',
|
||||
:dsn => 'activerecord_unittest'
|
||||
},
|
||||
'arunit2' => {
|
||||
:adapter => 'sqlserver',
|
||||
:mode => 'ODBC',
|
||||
:host => 'localhost',
|
||||
:username => 'sa',
|
||||
:dsn => 'activerecord_unittest2'
|
||||
}
|
||||
}
|
||||
|
||||
ActiveRecord::Base.establish_connection(
|
||||
:adapter => "sqlserver",
|
||||
:mode => "ODBC",
|
||||
:host => "localhost",
|
||||
:username => "sa",
|
||||
:password => "",
|
||||
:dsn => dsn1
|
||||
)
|
||||
|
||||
Course.establish_connection(
|
||||
:adapter => "sqlserver",
|
||||
:mode => "ODBC",
|
||||
:host => "localhost",
|
||||
:username => "sa",
|
||||
:password => "",
|
||||
:dsn => dsn2
|
||||
)
|
||||
ActiveRecord::Base.establish_connection 'arunit'
|
||||
Course.establish_connection 'arunit2'
|
||||
|
|
|
@ -4,21 +4,20 @@ require 'logger'
|
|||
|
||||
ActiveRecord::Base.logger = Logger.new("debug.log")
|
||||
|
||||
db1 = 'activerecord_unittest'
|
||||
db2 = 'activerecord_unittest2'
|
||||
ActiveRecord::Base.configurations = {
|
||||
'arunit' => {
|
||||
:adapter => 'sybase',
|
||||
:host => 'database_ASE',
|
||||
:username => 'sa',
|
||||
:database => 'activerecord_unittest'
|
||||
},
|
||||
'arunit2' => {
|
||||
:adapter => 'sybase',
|
||||
:host => 'database_ASE',
|
||||
:username => 'sa',
|
||||
:database => 'activerecord_unittest2'
|
||||
}
|
||||
}
|
||||
|
||||
ActiveRecord::Base.establish_connection(
|
||||
:adapter => "sybase",
|
||||
:host => "database_ASE",
|
||||
:username => "sa",
|
||||
:password => "",
|
||||
:database => db1
|
||||
)
|
||||
|
||||
Course.establish_connection(
|
||||
:adapter => "sybase",
|
||||
:host => "database_ASE",
|
||||
:username => "sa",
|
||||
:password => "",
|
||||
:database => db2
|
||||
)
|
||||
ActiveRecord::Base.establish_connection 'arunit'
|
||||
Course.establish_connection 'arunit2'
|
||||
|
|
62
vendor/rails/activerecord/test/defaults_test.rb
vendored
62
vendor/rails/activerecord/test/defaults_test.rb
vendored
|
@ -1,18 +1,60 @@
|
|||
require 'abstract_unit'
|
||||
require 'fixtures/default'
|
||||
require 'fixtures/entrant'
|
||||
|
||||
class DefaultsTest < Test::Unit::TestCase
|
||||
if %w(PostgreSQL).include? ActiveRecord::Base.connection.adapter_name
|
||||
class DefaultTest < Test::Unit::TestCase
|
||||
def test_nil_defaults_for_not_null_columns
|
||||
column_defaults =
|
||||
if current_adapter?(:MysqlAdapter)
|
||||
{ 'id' => nil, 'name' => '', 'course_id' => nil }
|
||||
else
|
||||
{ 'id' => nil, 'name' => nil, 'course_id' => nil }
|
||||
end
|
||||
|
||||
column_defaults.each do |name, default|
|
||||
column = Entrant.columns_hash[name]
|
||||
assert !column.null, "#{name} column should be NOT NULL"
|
||||
assert_equal default, column.default, "#{name} column should be DEFAULT #{default.inspect}"
|
||||
end
|
||||
end
|
||||
|
||||
if current_adapter?(:MysqlAdapter)
|
||||
# MySQL uses an implicit default 0 rather than NULL unless in strict mode.
|
||||
# We use an implicit NULL so schema.rb is compatible with other databases.
|
||||
def test_mysql_integer_not_null_defaults
|
||||
klass = Class.new(ActiveRecord::Base)
|
||||
klass.table_name = 'test_integer_not_null_default_zero'
|
||||
klass.connection.create_table klass.table_name do |t|
|
||||
t.column :zero, :integer, :null => false, :default => 0
|
||||
t.column :omit, :integer, :null => false
|
||||
end
|
||||
|
||||
assert_equal 0, klass.columns_hash['zero'].default
|
||||
assert !klass.columns_hash['zero'].null
|
||||
assert_equal nil, klass.columns_hash['omit'].default
|
||||
assert !klass.columns_hash['omit'].null
|
||||
|
||||
assert_raise(ActiveRecord::StatementInvalid) { klass.create! }
|
||||
|
||||
assert_nothing_raised do
|
||||
instance = klass.create!(:omit => 1)
|
||||
assert_equal 0, instance.zero
|
||||
assert_equal 1, instance.omit
|
||||
end
|
||||
ensure
|
||||
klass.connection.drop_table(klass.table_name) rescue nil
|
||||
end
|
||||
end
|
||||
|
||||
if current_adapter?(:PostgreSQLAdapter, :SQLServerAdapter, :FirebirdAdapter, :OpenBaseAdapter, :OracleAdapter)
|
||||
def test_default_integers
|
||||
default = Default.new
|
||||
assert_instance_of(Fixnum, default.positive_integer)
|
||||
assert_equal(default.positive_integer, 1)
|
||||
assert_instance_of(Fixnum, default.negative_integer)
|
||||
assert_equal(default.negative_integer, -1)
|
||||
end
|
||||
else
|
||||
def test_dummy
|
||||
assert true
|
||||
assert_instance_of Fixnum, default.positive_integer
|
||||
assert_equal 1, default.positive_integer
|
||||
assert_instance_of Fixnum, default.negative_integer
|
||||
assert_equal -1, default.negative_integer
|
||||
assert_instance_of BigDecimal, default.decimal_number
|
||||
assert_equal BigDecimal.new("2.78"), default.decimal_number
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,173 +15,213 @@ end
|
|||
raise "ActiveRecord should have barked on bad collection keys" unless bad_collection_keys
|
||||
|
||||
|
||||
class DeprecatedAssociationWarningsTest < Test::Unit::TestCase
|
||||
def test_deprecation_warnings
|
||||
assert_deprecated('find_first') { Firm.find_first }
|
||||
assert_deprecated('find_all') { Firm.find_all }
|
||||
assert_deprecated('has_account?') { Firm.find(:first).has_account? }
|
||||
assert_deprecated('has_clients?') { Firm.find(:first).has_clients? }
|
||||
end
|
||||
end
|
||||
|
||||
class DeprecatedAssociationsTest < Test::Unit::TestCase
|
||||
fixtures :accounts, :companies, :developers, :projects, :topics,
|
||||
:developers_projects
|
||||
|
||||
def setup
|
||||
@firm = companies(:first_firm)
|
||||
end
|
||||
|
||||
def test_has_many_find
|
||||
assert_equal 2, Firm.find_first.clients.length
|
||||
assert_equal 2, @firm.clients.length
|
||||
end
|
||||
|
||||
def test_has_many_orders
|
||||
assert_equal "Summit", Firm.find_first.clients.first.name
|
||||
assert_equal "Summit", @firm.clients.first.name
|
||||
end
|
||||
|
||||
def test_has_many_class_name
|
||||
assert_equal "Microsoft", Firm.find_first.clients_sorted_desc.first.name
|
||||
assert_equal "Microsoft", @firm.clients_sorted_desc.first.name
|
||||
end
|
||||
|
||||
def test_has_many_foreign_key
|
||||
assert_equal "Microsoft", Firm.find_first.clients_of_firm.first.name
|
||||
assert_equal "Microsoft", @firm.clients_of_firm.first.name
|
||||
end
|
||||
|
||||
def test_has_many_conditions
|
||||
assert_equal "Microsoft", Firm.find_first.clients_like_ms.first.name
|
||||
assert_equal "Microsoft", @firm.clients_like_ms.first.name
|
||||
end
|
||||
|
||||
def test_has_many_sql
|
||||
firm = Firm.find_first
|
||||
assert_equal "Microsoft", firm.clients_using_sql.first.name
|
||||
assert_equal 1, firm.clients_using_sql_count
|
||||
assert_equal 1, Firm.find_first.clients_using_sql_count
|
||||
assert_equal "Microsoft", @firm.clients_using_sql.first.name
|
||||
assert_equal 1, @firm.clients_using_sql.count
|
||||
assert_equal 1, @firm.clients_using_sql.count
|
||||
end
|
||||
|
||||
def test_has_many_counter_sql
|
||||
assert_equal 1, Firm.find_first.clients_using_counter_sql_count
|
||||
assert_equal 1, @firm.clients_using_counter_sql.count
|
||||
end
|
||||
|
||||
def test_has_many_queries
|
||||
assert Firm.find_first.has_clients?
|
||||
firm = Firm.find_first
|
||||
assert_equal 2, firm.clients_count # tests using class count
|
||||
firm.clients
|
||||
assert firm.has_clients?
|
||||
assert_equal 2, firm.clients_count # tests using collection length
|
||||
assert !@firm.clients.loaded?
|
||||
assert_deprecated 'has_clients?' do
|
||||
assert_queries(1) { assert @firm.has_clients? }
|
||||
end
|
||||
assert !@firm.clients.loaded?
|
||||
assert_deprecated 'clients_count' do
|
||||
assert_queries(1) { assert_equal 2, @firm.clients_count }
|
||||
end
|
||||
assert !@firm.clients.loaded?
|
||||
assert_queries(1) { @firm.clients.size }
|
||||
assert !@firm.clients.loaded?
|
||||
assert_queries(0) { @firm.clients }
|
||||
assert !@firm.clients.loaded?
|
||||
assert_queries(1) { @firm.clients.reload }
|
||||
assert @firm.clients.loaded?
|
||||
assert_queries(0) { @firm.clients.size }
|
||||
assert_queries(1) { @firm.clients.count }
|
||||
end
|
||||
|
||||
def test_has_many_dependence
|
||||
assert_equal 3, Client.find_all.length
|
||||
Firm.find_first.destroy
|
||||
assert_equal 1, Client.find_all.length
|
||||
count = Client.count
|
||||
Firm.find(:first).destroy
|
||||
assert_equal count - 2, Client.count
|
||||
end
|
||||
|
||||
uses_transaction :test_has_many_dependence_with_transaction_support_on_failure
|
||||
def test_has_many_dependence_with_transaction_support_on_failure
|
||||
assert_equal 3, Client.find_all.length
|
||||
count = Client.count
|
||||
|
||||
firm = Firm.find_first
|
||||
clients = firm.clients
|
||||
clients = @firm.clients
|
||||
clients.last.instance_eval { def before_destroy() raise "Trigger rollback" end }
|
||||
|
||||
firm.destroy rescue "do nothing"
|
||||
@firm.destroy rescue "do nothing"
|
||||
|
||||
assert_equal 3, Client.find_all.length
|
||||
assert_equal count, Client.count
|
||||
end
|
||||
|
||||
def test_has_one_dependence
|
||||
num_accounts = Account.count
|
||||
firm = Firm.find(1)
|
||||
assert firm.has_account?
|
||||
firm.destroy
|
||||
assert_not_nil @firm.account
|
||||
@firm.destroy
|
||||
assert_equal num_accounts - 1, Account.count
|
||||
end
|
||||
|
||||
def test_has_one_dependence_with_missing_association
|
||||
Account.destroy_all
|
||||
firm = Firm.find(1)
|
||||
assert !firm.has_account?
|
||||
firm.destroy
|
||||
assert_nil @firm.account
|
||||
@firm.destroy
|
||||
end
|
||||
|
||||
def test_belongs_to
|
||||
assert_equal companies(:first_firm).name, Client.find(3).firm.name
|
||||
assert Client.find(3).has_firm?, "Microsoft should have a firm"
|
||||
# assert !Company.find(1).has_firm?, "37signals shouldn't have a firm"
|
||||
client = companies(:second_client)
|
||||
assert_deprecated('has_firm?') do
|
||||
assert companies(:second_client).has_firm?, "Microsoft should have a firm"
|
||||
end
|
||||
assert_equal companies(:first_firm), client.firm, "Microsoft should have a firm"
|
||||
end
|
||||
|
||||
def test_belongs_to_with_different_class_name
|
||||
assert_equal Company.find(1).name, Company.find(3).firm_with_other_name.name
|
||||
assert Company.find(3).has_firm_with_other_name?, "Microsoft should have a firm"
|
||||
assert_equal @firm, companies(:second_client).firm_with_other_name
|
||||
end
|
||||
|
||||
def test_belongs_to_with_condition
|
||||
assert_equal Company.find(1).name, Company.find(3).firm_with_condition.name
|
||||
assert Company.find(3).has_firm_with_condition?, "Microsoft should have a firm"
|
||||
assert_equal @firm, companies(:second_client).firm_with_condition
|
||||
end
|
||||
|
||||
def test_belongs_to_equality
|
||||
assert Company.find(3).firm?(Company.find(1)), "Microsoft should have 37signals as firm"
|
||||
assert_raises(RuntimeError) { !Company.find(3).firm?(Company.find(3)) } # "Summit shouldn't have itself as firm"
|
||||
assert_equal @firm, companies(:second_client).firm, 'Microsoft should have 37signals as firm'
|
||||
end
|
||||
|
||||
def test_has_one
|
||||
assert companies(:first_firm).account?(Account.find(1))
|
||||
assert_equal Account.find(1).credit_limit, companies(:first_firm).account.credit_limit
|
||||
assert companies(:first_firm).has_account?, "37signals should have an account"
|
||||
assert Account.find(1).firm?(companies(:first_firm)), "37signals account should be able to backtrack"
|
||||
assert Account.find(1).has_firm?, "37signals account should be able to backtrack"
|
||||
assert_equal accounts(:signals37), @firm.account
|
||||
assert_deprecated 'has_account?' do
|
||||
assert @firm.has_account?, "37signals should have an account"
|
||||
end
|
||||
assert_deprecated 'firm?' do
|
||||
assert accounts(:signals37).firm?(@firm), "37signals account should be able to backtrack"
|
||||
end
|
||||
assert_deprecated 'has_firm?' do
|
||||
assert accounts(:signals37).has_firm?, "37signals account should be able to backtrack"
|
||||
end
|
||||
|
||||
assert !Account.find(2).has_firm?, "Unknown isn't linked"
|
||||
assert !Account.find(2).firm?(companies(:first_firm)), "Unknown isn't linked"
|
||||
assert_nil accounts(:unknown).firm, "Unknown isn't linked"
|
||||
end
|
||||
|
||||
def test_has_many_dependence_on_account
|
||||
def test_has_many_dependence_on_account
|
||||
num_accounts = Account.count
|
||||
companies(:first_firm).destroy
|
||||
@firm.destroy
|
||||
assert_equal num_accounts - 1, Account.count
|
||||
end
|
||||
|
||||
def test_find_in
|
||||
assert_equal Client.find(2).name, companies(:first_firm).find_in_clients(2).name
|
||||
assert_raises(ActiveRecord::RecordNotFound) { companies(:first_firm).find_in_clients(6) }
|
||||
assert_deprecated 'find_in_clients' do
|
||||
assert_equal companies(:first_client), @firm.find_in_clients(2)
|
||||
assert_raises(ActiveRecord::RecordNotFound) { @firm.find_in_clients(6) }
|
||||
end
|
||||
end
|
||||
|
||||
def test_force_reload
|
||||
firm = Firm.new("name" => "A New Firm, Inc")
|
||||
firm.save
|
||||
firm.clients.each {|c|} # forcing to load all clients
|
||||
assert firm.clients.empty?, "New firm shouldn't have client objects"
|
||||
assert !firm.has_clients?, "New firm shouldn't have clients"
|
||||
assert_equal 0, firm.clients_count, "New firm should have 0 clients"
|
||||
ActiveSupport::Deprecation.silence do
|
||||
firm = Firm.new("name" => "A New Firm, Inc")
|
||||
firm.save
|
||||
firm.clients.each {|c|} # forcing to load all clients
|
||||
assert firm.clients.empty?, "New firm shouldn't have client objects"
|
||||
assert !firm.has_clients?, "New firm shouldn't have clients"
|
||||
assert_equal 0, firm.clients_count, "New firm should have 0 clients"
|
||||
|
||||
client = Client.new("name" => "TheClient.com", "firm_id" => firm.id)
|
||||
client.save
|
||||
client = Client.new("name" => "TheClient.com", "firm_id" => firm.id)
|
||||
client.save
|
||||
|
||||
assert firm.clients.empty?, "New firm should have cached no client objects"
|
||||
assert !firm.has_clients?, "New firm should have cached a no-clients response"
|
||||
assert_equal 0, firm.clients_count, "New firm should have cached 0 clients count"
|
||||
assert firm.clients.empty?, "New firm should have cached no client objects"
|
||||
assert !firm.has_clients?, "New firm should have cached a no-clients response"
|
||||
assert_equal 0, firm.clients_count, "New firm should have cached 0 clients count"
|
||||
|
||||
assert !firm.clients(true).empty?, "New firm should have reloaded client objects"
|
||||
assert firm.has_clients?(true), "New firm should have reloaded with a have-clients response"
|
||||
assert_equal 1, firm.clients_count(true), "New firm should have reloaded clients count"
|
||||
assert !firm.clients(true).empty?, "New firm should have reloaded client objects"
|
||||
assert firm.has_clients?(true), "New firm should have reloaded with a have-clients response"
|
||||
assert_equal 1, firm.clients_count(true), "New firm should have reloaded clients count"
|
||||
end
|
||||
end
|
||||
|
||||
def test_included_in_collection
|
||||
assert companies(:first_firm).clients.include?(Client.find(2))
|
||||
assert @firm.clients.include?(Client.find(2))
|
||||
end
|
||||
|
||||
def test_build_to_collection
|
||||
assert_equal 1, companies(:first_firm).clients_of_firm_count
|
||||
new_client = companies(:first_firm).build_to_clients_of_firm("name" => "Another Client")
|
||||
count = @firm.clients_of_firm.count
|
||||
new_client = nil
|
||||
assert_deprecated 'build_to_clients_of_firm' do
|
||||
new_client = @firm.build_to_clients_of_firm("name" => "Another Client")
|
||||
end
|
||||
assert_equal "Another Client", new_client.name
|
||||
assert new_client.save
|
||||
|
||||
assert new_client.firm?(companies(:first_firm))
|
||||
assert_equal 2, companies(:first_firm).clients_of_firm_count(true)
|
||||
assert_equal @firm, new_client.firm
|
||||
assert_equal count + 1, @firm.clients_of_firm.count
|
||||
end
|
||||
|
||||
def test_create_in_collection
|
||||
assert_equal companies(:first_firm).create_in_clients_of_firm("name" => "Another Client"), companies(:first_firm).clients_of_firm(true).last
|
||||
assert_deprecated 'create_in_clients_of_firm' do
|
||||
assert_equal @firm.create_in_clients_of_firm("name" => "Another Client"), @firm.clients_of_firm(true).last
|
||||
end
|
||||
end
|
||||
|
||||
def test_has_and_belongs_to_many
|
||||
david = Developer.find(1)
|
||||
assert david.has_projects?
|
||||
assert_equal 2, david.projects_count
|
||||
assert_deprecated 'has_projects?' do
|
||||
assert david.has_projects?
|
||||
end
|
||||
assert_deprecated 'projects_count' do
|
||||
assert_equal 2, david.projects_count
|
||||
end
|
||||
|
||||
active_record = Project.find(1)
|
||||
assert active_record.has_developers?
|
||||
assert_equal 3, active_record.developers_count
|
||||
assert_deprecated 'has_developers?' do
|
||||
assert active_record.has_developers?
|
||||
end
|
||||
assert_deprecated 'developers_count' do
|
||||
assert_equal 3, active_record.developers_count
|
||||
end
|
||||
assert active_record.developers.include?(david)
|
||||
end
|
||||
|
||||
|
@ -189,53 +229,59 @@ class DeprecatedAssociationsTest < Test::Unit::TestCase
|
|||
david = Developer.find(1)
|
||||
active_record = Project.find(1)
|
||||
|
||||
david.remove_projects(active_record)
|
||||
|
||||
assert_equal 1, david.projects_count
|
||||
assert_equal 2, active_record.developers_count
|
||||
assert_deprecated do
|
||||
david.remove_projects(active_record)
|
||||
assert_equal 1, david.projects_count
|
||||
assert_equal 2, active_record.developers_count
|
||||
end
|
||||
end
|
||||
|
||||
def test_has_and_belongs_to_many_zero
|
||||
david = Developer.find(1)
|
||||
david.remove_projects(Project.find_all)
|
||||
|
||||
assert_equal 0, david.projects_count
|
||||
assert !david.has_projects?
|
||||
assert_deprecated do
|
||||
david.remove_projects Project.find_all
|
||||
assert_equal 0, david.projects_count
|
||||
assert !david.has_projects?
|
||||
end
|
||||
end
|
||||
|
||||
def test_has_and_belongs_to_many_adding
|
||||
jamis = Developer.find(2)
|
||||
action_controller = Project.find(2)
|
||||
|
||||
jamis.add_projects(action_controller)
|
||||
|
||||
assert_equal 2, jamis.projects_count
|
||||
assert_equal 2, action_controller.developers_count
|
||||
assert_deprecated do
|
||||
jamis.add_projects(action_controller)
|
||||
assert_equal 2, jamis.projects_count
|
||||
assert_equal 2, action_controller.developers_count
|
||||
end
|
||||
end
|
||||
|
||||
def test_has_and_belongs_to_many_adding_from_the_project
|
||||
jamis = Developer.find(2)
|
||||
action_controller = Project.find(2)
|
||||
|
||||
action_controller.add_developers(jamis)
|
||||
|
||||
assert_equal 2, jamis.projects_count
|
||||
assert_equal 2, action_controller.developers_count
|
||||
assert_deprecated do
|
||||
action_controller.add_developers(jamis)
|
||||
assert_equal 2, jamis.projects_count
|
||||
assert_equal 2, action_controller.developers_count
|
||||
end
|
||||
end
|
||||
|
||||
def test_has_and_belongs_to_many_adding_a_collection
|
||||
aredridel = Developer.new("name" => "Aredridel")
|
||||
aredridel.save
|
||||
|
||||
aredridel.add_projects([ Project.find(1), Project.find(2) ])
|
||||
assert_equal 2, aredridel.projects_count
|
||||
assert_deprecated do
|
||||
aredridel.add_projects([ Project.find(1), Project.find(2) ])
|
||||
assert_equal 2, aredridel.projects_count
|
||||
end
|
||||
end
|
||||
|
||||
def test_belongs_to_counter
|
||||
topic = Topic.create("title" => "Apple", "content" => "hello world")
|
||||
assert_equal 0, topic.send(:read_attribute, "replies_count"), "No replies yet"
|
||||
|
||||
reply = topic.create_in_replies("title" => "I'm saying no!", "content" => "over here")
|
||||
reply = assert_deprecated { topic.create_in_replies("title" => "I'm saying no!", "content" => "over here") }
|
||||
assert_equal 1, Topic.find(topic.id).send(:read_attribute, "replies_count"), "First reply created"
|
||||
|
||||
reply.destroy
|
||||
|
@ -312,25 +358,23 @@ class DeprecatedAssociationsTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_has_many_find_all
|
||||
assert_equal 2, Firm.find_first.find_all_in_clients("#{QUOTED_TYPE} = 'Client'").length
|
||||
assert_equal 1, Firm.find_first.find_all_in_clients("name = 'Summit'").length
|
||||
assert_deprecated 'find_all_in_clients' do
|
||||
assert_equal 2, @firm.find_all_in_clients("#{QUOTED_TYPE} = 'Client'").length
|
||||
assert_equal 1, @firm.find_all_in_clients("name = 'Summit'").length
|
||||
end
|
||||
end
|
||||
|
||||
def test_has_one
|
||||
assert companies(:first_firm).account?(Account.find(1))
|
||||
assert companies(:first_firm).has_account?, "37signals should have an account"
|
||||
assert Account.find(1).firm?(companies(:first_firm)), "37signals account should be able to backtrack"
|
||||
assert Account.find(1).has_firm?, "37signals account should be able to backtrack"
|
||||
|
||||
assert !Account.find(2).has_firm?, "Unknown isn't linked"
|
||||
assert !Account.find(2).firm?(companies(:first_firm)), "Unknown isn't linked"
|
||||
assert_equal Account.find(1), @firm.account, "37signals should have an account"
|
||||
assert_equal @firm, Account.find(1).firm, "37signals account should be able to backtrack"
|
||||
assert_nil Account.find(2).firm, "Unknown isn't linked"
|
||||
end
|
||||
|
||||
def test_has_one_build
|
||||
firm = Firm.new("name" => "GlobalMegaCorp")
|
||||
assert firm.save
|
||||
|
||||
account = firm.build_account("credit_limit" => 1000)
|
||||
account = firm.build_account(:credit_limit => 1000)
|
||||
assert account.save
|
||||
assert_equal account, firm.account
|
||||
end
|
||||
|
@ -338,7 +382,7 @@ class DeprecatedAssociationsTest < Test::Unit::TestCase
|
|||
def test_has_one_failing_build_association
|
||||
firm = Firm.new("name" => "GlobalMegaCorp")
|
||||
firm.save
|
||||
|
||||
|
||||
account = firm.build_account
|
||||
assert !account.save
|
||||
assert_equal "can't be empty", account.errors.on("credit_limit")
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
require 'abstract_unit'
|
||||
require 'fixtures/company'
|
||||
require 'fixtures/topic'
|
||||
require 'fixtures/reply'
|
||||
require 'fixtures/entrant'
|
||||
require 'fixtures/developer'
|
||||
|
||||
|
@ -8,78 +9,88 @@ class DeprecatedFinderTest < Test::Unit::TestCase
|
|||
fixtures :companies, :topics, :entrants, :developers
|
||||
|
||||
def test_find_all_with_limit
|
||||
entrants = Entrant.find_all nil, "id ASC", 2
|
||||
|
||||
assert_equal(2, entrants.size)
|
||||
assert_equal(entrants(:first).name, entrants.first.name)
|
||||
entrants = assert_deprecated { Entrant.find_all nil, "id ASC", 2 }
|
||||
assert_equal 2, entrants.size
|
||||
assert_equal entrants(:first), entrants.first
|
||||
end
|
||||
|
||||
def test_find_all_with_prepared_limit_and_offset
|
||||
entrants = Entrant.find_all nil, "id ASC", [2, 1]
|
||||
|
||||
assert_equal(2, entrants.size)
|
||||
assert_equal(entrants(:second).name, entrants.first.name)
|
||||
entrants = assert_deprecated { Entrant.find_all nil, "id ASC", [2, 1] }
|
||||
assert_equal 2, entrants.size
|
||||
assert_equal entrants(:second), entrants.first
|
||||
end
|
||||
|
||||
def test_find_first
|
||||
first = Topic.find_first "title = 'The First Topic'"
|
||||
assert_equal(topics(:first).title, first.title)
|
||||
first = assert_deprecated { Topic.find_first "title = 'The First Topic'" }
|
||||
assert_equal topics(:first), first
|
||||
end
|
||||
|
||||
|
||||
def test_find_first_failing
|
||||
first = Topic.find_first "title = 'The First Topic!'"
|
||||
assert_nil(first)
|
||||
first = assert_deprecated { Topic.find_first "title = 'The First Topic!'" }
|
||||
assert_nil first
|
||||
end
|
||||
|
||||
|
||||
def test_deprecated_find_on_conditions
|
||||
assert Topic.find_on_conditions(1, ["approved = ?", false])
|
||||
assert_raises(ActiveRecord::RecordNotFound) { Topic.find_on_conditions(1, ["approved = ?", true]) }
|
||||
assert_deprecated 'find_on_conditions' do
|
||||
assert Topic.find_on_conditions(1, ["approved = ?", false])
|
||||
assert_raises(ActiveRecord::RecordNotFound) { Topic.find_on_conditions(1, ["approved = ?", true]) }
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def test_condition_interpolation
|
||||
assert_kind_of Firm, Company.find_first(["name = '%s'", "37signals"])
|
||||
assert_nil Company.find_first(["name = '%s'", "37signals!"])
|
||||
assert_nil Company.find_first(["name = '%s'", "37signals!' OR 1=1"])
|
||||
assert_kind_of Time, Topic.find_first(["id = %d", 1]).written_on
|
||||
assert_deprecated do
|
||||
assert_kind_of Firm, Company.find_first(["name = '%s'", "37signals"])
|
||||
assert_nil Company.find_first(["name = '%s'", "37signals!"])
|
||||
assert_nil Company.find_first(["name = '%s'", "37signals!' OR 1=1"])
|
||||
assert_kind_of Time, Topic.find_first(["id = %d", 1]).written_on
|
||||
end
|
||||
end
|
||||
|
||||
def test_bind_variables
|
||||
assert_kind_of Firm, Company.find_first(["name = ?", "37signals"])
|
||||
assert_nil Company.find_first(["name = ?", "37signals!"])
|
||||
assert_nil Company.find_first(["name = ?", "37signals!' OR 1=1"])
|
||||
assert_kind_of Time, Topic.find_first(["id = ?", 1]).written_on
|
||||
assert_raises(ActiveRecord::PreparedStatementInvalid) {
|
||||
Company.find_first(["id=? AND name = ?", 2])
|
||||
}
|
||||
assert_raises(ActiveRecord::PreparedStatementInvalid) {
|
||||
Company.find_first(["id=?", 2, 3, 4])
|
||||
}
|
||||
assert_deprecated do
|
||||
assert_kind_of Firm, Company.find_first(["name = ?", "37signals"])
|
||||
assert_nil Company.find_first(["name = ?", "37signals!"])
|
||||
assert_nil Company.find_first(["name = ?", "37signals!' OR 1=1"])
|
||||
assert_kind_of Time, Topic.find_first(["id = ?", 1]).written_on
|
||||
assert_raises(ActiveRecord::PreparedStatementInvalid) {
|
||||
Company.find_first(["id=? AND name = ?", 2])
|
||||
}
|
||||
assert_raises(ActiveRecord::PreparedStatementInvalid) {
|
||||
Company.find_first(["id=?", 2, 3, 4])
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def test_bind_variables_with_quotes
|
||||
Company.create("name" => "37signals' go'es agains")
|
||||
assert Company.find_first(["name = ?", "37signals' go'es agains"])
|
||||
assert_deprecated do
|
||||
assert_not_nil Company.find_first(["name = ?", "37signals' go'es agains"])
|
||||
end
|
||||
end
|
||||
|
||||
def test_named_bind_variables_with_quotes
|
||||
Company.create("name" => "37signals' go'es agains")
|
||||
assert Company.find_first(["name = :name", {:name => "37signals' go'es agains"}])
|
||||
assert_deprecated do
|
||||
assert_not_nil Company.find_first(["name = :name", {:name => "37signals' go'es agains"}])
|
||||
end
|
||||
end
|
||||
|
||||
def test_named_bind_variables
|
||||
assert_equal '1', bind(':a', :a => 1) # ' ruby-mode
|
||||
assert_equal '1 1', bind(':a :a', :a => 1) # ' ruby-mode
|
||||
|
||||
assert_kind_of Firm, Company.find_first(["name = :name", { :name => "37signals" }])
|
||||
assert_nil Company.find_first(["name = :name", { :name => "37signals!" }])
|
||||
assert_nil Company.find_first(["name = :name", { :name => "37signals!' OR 1=1" }])
|
||||
assert_kind_of Time, Topic.find_first(["id = :id", { :id => 1 }]).written_on
|
||||
|
||||
assert_deprecated do
|
||||
assert_kind_of Firm, Company.find_first(["name = :name", { :name => "37signals" }])
|
||||
assert_nil Company.find_first(["name = :name", { :name => "37signals!" }])
|
||||
assert_nil Company.find_first(["name = :name", { :name => "37signals!' OR 1=1" }])
|
||||
assert_kind_of Time, Topic.find_first(["id = :id", { :id => 1 }]).written_on
|
||||
end
|
||||
end
|
||||
|
||||
def test_count
|
||||
assert_equal(0, Entrant.count("id > 3"))
|
||||
assert_equal(1, Entrant.count(["id > ?", 2]))
|
||||
assert_equal(2, Entrant.count(["id > ?", 1]))
|
||||
assert_equal(0, Entrant.count(:conditions => "id > 3"))
|
||||
assert_equal(1, Entrant.count(:conditions => ["id > ?", 2]))
|
||||
assert_equal(2, Entrant.count(:conditions => ["id > ?", 1]))
|
||||
end
|
||||
|
||||
def test_count_by_sql
|
||||
|
@ -89,38 +100,44 @@ class DeprecatedFinderTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_find_all_with_limit
|
||||
first_five_developers = Developer.find_all nil, 'id ASC', 5
|
||||
assert_equal 5, first_five_developers.length
|
||||
assert_equal 'David', first_five_developers.first.name
|
||||
assert_equal 'fixture_5', first_five_developers.last.name
|
||||
|
||||
no_developers = Developer.find_all nil, 'id ASC', 0
|
||||
assert_equal 0, no_developers.length
|
||||
|
||||
assert_equal first_five_developers, Developer.find_all(nil, 'id ASC', [5])
|
||||
assert_equal no_developers, Developer.find_all(nil, 'id ASC', [0])
|
||||
assert_deprecated do
|
||||
first_five_developers = Developer.find_all nil, 'id ASC', 5
|
||||
assert_equal 5, first_five_developers.length
|
||||
assert_equal 'David', first_five_developers.first.name
|
||||
assert_equal 'fixture_5', first_five_developers.last.name
|
||||
|
||||
no_developers = Developer.find_all nil, 'id ASC', 0
|
||||
assert_equal 0, no_developers.length
|
||||
|
||||
assert_equal first_five_developers, Developer.find_all(nil, 'id ASC', [5])
|
||||
assert_equal no_developers, Developer.find_all(nil, 'id ASC', [0])
|
||||
end
|
||||
end
|
||||
|
||||
def test_find_all_with_limit_and_offset
|
||||
first_three_developers = Developer.find_all nil, 'id ASC', [3, 0]
|
||||
second_three_developers = Developer.find_all nil, 'id ASC', [3, 3]
|
||||
last_two_developers = Developer.find_all nil, 'id ASC', [2, 8]
|
||||
|
||||
assert_equal 3, first_three_developers.length
|
||||
assert_equal 3, second_three_developers.length
|
||||
assert_equal 2, last_two_developers.length
|
||||
|
||||
assert_equal 'David', first_three_developers.first.name
|
||||
assert_equal 'fixture_4', second_three_developers.first.name
|
||||
assert_equal 'fixture_9', last_two_developers.first.name
|
||||
assert_deprecated do
|
||||
first_three_developers = Developer.find_all nil, 'id ASC', [3, 0]
|
||||
second_three_developers = Developer.find_all nil, 'id ASC', [3, 3]
|
||||
last_two_developers = Developer.find_all nil, 'id ASC', [2, 8]
|
||||
|
||||
assert_equal 3, first_three_developers.length
|
||||
assert_equal 3, second_three_developers.length
|
||||
assert_equal 2, last_two_developers.length
|
||||
|
||||
assert_equal 'David', first_three_developers.first.name
|
||||
assert_equal 'fixture_4', second_three_developers.first.name
|
||||
assert_equal 'fixture_9', last_two_developers.first.name
|
||||
end
|
||||
end
|
||||
|
||||
def test_find_all_by_one_attribute_with_options
|
||||
topics = Topic.find_all_by_content("Have a nice day", "id DESC")
|
||||
assert topics(:first), topics.last
|
||||
assert_not_deprecated do
|
||||
topics = Topic.find_all_by_content("Have a nice day", "id DESC")
|
||||
assert topics(:first), topics.last
|
||||
|
||||
topics = Topic.find_all_by_content("Have a nice day", "id DESC")
|
||||
assert topics(:first), topics.first
|
||||
topics = Topic.find_all_by_content("Have a nice day", "id DESC")
|
||||
assert topics(:first), topics.first
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
|
145
vendor/rails/activerecord/test/finder_test.rb
vendored
145
vendor/rails/activerecord/test/finder_test.rb
vendored
|
@ -13,11 +13,21 @@ class FinderTest < Test::Unit::TestCase
|
|||
assert_equal(topics(:first).title, Topic.find(1).title)
|
||||
end
|
||||
|
||||
# find should handle strings that come from URLs
|
||||
# (example: Category.find(params[:id]))
|
||||
def test_find_with_string
|
||||
assert_equal(Topic.find(1).title,Topic.find("1").title)
|
||||
end
|
||||
|
||||
def test_exists
|
||||
assert (Topic.exists?(1))
|
||||
assert !(Topic.exists?(45))
|
||||
assert !(Topic.exists?("foo"))
|
||||
assert !(Topic.exists?([1,2]))
|
||||
assert Topic.exists?(1)
|
||||
assert Topic.exists?("1")
|
||||
assert Topic.exists?(:author_name => "David")
|
||||
assert Topic.exists?(:author_name => "Mary", :approved => true)
|
||||
assert Topic.exists?(["parent_id = ?", 1])
|
||||
assert !Topic.exists?(45)
|
||||
assert !Topic.exists?("foo")
|
||||
assert_raise(NoMethodError) { Topic.exists?([1,2]) }
|
||||
end
|
||||
|
||||
def test_find_by_array_of_one_id
|
||||
|
@ -83,6 +93,11 @@ class FinderTest < Test::Unit::TestCase
|
|||
assert_equal(topics(:second).title, topics.first.title)
|
||||
end
|
||||
|
||||
def test_find_by_sql_with_sti_on_joined_table
|
||||
accounts = Account.find_by_sql("SELECT * FROM accounts INNER JOIN companies ON companies.id = accounts.firm_id")
|
||||
assert_equal [Account], accounts.collect(&:class).uniq
|
||||
end
|
||||
|
||||
def test_find_first
|
||||
first = Topic.find(:first, :conditions => "title = 'The First Topic'")
|
||||
assert_equal(topics(:first).title, first.title)
|
||||
|
@ -111,17 +126,68 @@ class FinderTest < Test::Unit::TestCase
|
|||
assert topic.respond_to?("author_name")
|
||||
end
|
||||
|
||||
def test_find_on_conditions
|
||||
def test_find_on_array_conditions
|
||||
assert Topic.find(1, :conditions => ["approved = ?", false])
|
||||
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => ["approved = ?", true]) }
|
||||
end
|
||||
|
||||
def test_condition_interpolation
|
||||
def test_find_on_hash_conditions
|
||||
assert Topic.find(1, :conditions => { :approved => false })
|
||||
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { :approved => true }) }
|
||||
end
|
||||
|
||||
def test_find_on_hash_conditions_with_range
|
||||
assert_equal [1,2], Topic.find(:all, :conditions => { :id => 1..2 }).map(&:id).sort
|
||||
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { :id => 2..3 }) }
|
||||
end
|
||||
|
||||
def test_find_on_hash_conditions_with_multiple_ranges
|
||||
assert_equal [1,2,3], Comment.find(:all, :conditions => { :id => 1..3, :post_id => 1..2 }).map(&:id).sort
|
||||
assert_equal [1], Comment.find(:all, :conditions => { :id => 1..1, :post_id => 1..10 }).map(&:id).sort
|
||||
end
|
||||
|
||||
def test_find_on_multiple_hash_conditions
|
||||
assert Topic.find(1, :conditions => { :author_name => "David", :title => "The First Topic", :replies_count => 1, :approved => false })
|
||||
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { :author_name => "David", :title => "The First Topic", :replies_count => 1, :approved => true }) }
|
||||
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { :author_name => "David", :title => "HHC", :replies_count => 1, :approved => false }) }
|
||||
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { :author_name => "David", :title => "The First Topic", :replies_count => 1, :approved => true }) }
|
||||
end
|
||||
|
||||
def test_condition_array_interpolation
|
||||
assert_kind_of Firm, Company.find(:first, :conditions => ["name = '%s'", "37signals"])
|
||||
assert_nil Company.find(:first, :conditions => ["name = '%s'", "37signals!"])
|
||||
assert_nil Company.find(:first, :conditions => ["name = '%s'", "37signals!' OR 1=1"])
|
||||
assert_kind_of Time, Topic.find(:first, :conditions => ["id = %d", 1]).written_on
|
||||
end
|
||||
|
||||
def test_condition_hash_interpolation
|
||||
assert_kind_of Firm, Company.find(:first, :conditions => { :name => "37signals"})
|
||||
assert_nil Company.find(:first, :conditions => { :name => "37signals!"})
|
||||
assert_kind_of Time, Topic.find(:first, :conditions => {:id => 1}).written_on
|
||||
end
|
||||
|
||||
def test_hash_condition_find_malformed
|
||||
assert_raises(ActiveRecord::StatementInvalid) {
|
||||
Company.find(:first, :conditions => { :id => 2, :dhh => true })
|
||||
}
|
||||
end
|
||||
|
||||
def test_hash_condition_find_with_escaped_characters
|
||||
Company.create("name" => "Ain't noth'n like' \#stuff")
|
||||
assert Company.find(:first, :conditions => { :name => "Ain't noth'n like' \#stuff" })
|
||||
end
|
||||
|
||||
def test_hash_condition_find_with_array
|
||||
p1, p2 = Post.find(:all, :limit => 2, :order => 'id asc')
|
||||
assert_equal [p1, p2], Post.find(:all, :conditions => { :id => [p1, p2] }, :order => 'id asc')
|
||||
assert_equal [p1, p2], Post.find(:all, :conditions => { :id => [p1, p2.id] }, :order => 'id asc')
|
||||
end
|
||||
|
||||
def test_hash_condition_find_with_nil
|
||||
topic = Topic.find(:first, :conditions => { :last_read => nil } )
|
||||
assert_not_nil topic
|
||||
assert_nil topic.last_read
|
||||
end
|
||||
|
||||
def test_bind_variables
|
||||
assert_kind_of Firm, Company.find(:first, :conditions => ["name = ?", "37signals"])
|
||||
|
@ -180,19 +246,34 @@ class FinderTest < Test::Unit::TestCase
|
|||
assert_equal %('a','b','c'), bind(':a', :a => Set.new(%w(a b c))) # '
|
||||
end
|
||||
|
||||
def test_bind_empty_enumerable
|
||||
quoted_nil = ActiveRecord::Base.connection.quote(nil)
|
||||
assert_equal quoted_nil, bind('?', [])
|
||||
assert_equal " in (#{quoted_nil})", bind(' in (?)', [])
|
||||
assert_equal "foo in (#{quoted_nil})", bind('foo in (?)', [])
|
||||
end
|
||||
|
||||
def test_bind_string
|
||||
assert_equal "''", bind('?', '')
|
||||
end
|
||||
|
||||
def test_bind_record
|
||||
o = Struct.new(:quoted_id).new(1)
|
||||
assert_equal '1', bind('?', o)
|
||||
|
||||
os = [o] * 3
|
||||
assert_equal '1,1,1', bind('?', os)
|
||||
end
|
||||
|
||||
def test_string_sanitation
|
||||
assert_not_equal "'something ' 1=1'", ActiveRecord::Base.sanitize("something ' 1=1")
|
||||
assert_equal "'something; select table'", ActiveRecord::Base.sanitize("something; select table")
|
||||
end
|
||||
|
||||
def test_count
|
||||
assert_equal(0, Entrant.count("id > 3"))
|
||||
assert_equal(1, Entrant.count(["id > ?", 2]))
|
||||
assert_equal(2, Entrant.count(["id > ?", 1]))
|
||||
assert_equal(0, Entrant.count(:conditions => "id > 3"))
|
||||
assert_equal(1, Entrant.count(:conditions => ["id > ?", 2]))
|
||||
assert_equal(2, Entrant.count(:conditions => ["id > ?", 1]))
|
||||
end
|
||||
|
||||
def test_count_by_sql
|
||||
|
@ -222,6 +303,13 @@ class FinderTest < Test::Unit::TestCase
|
|||
def test_find_by_one_missing_attribute
|
||||
assert_raises(NoMethodError) { Topic.find_by_undertitle("The First Topic!") }
|
||||
end
|
||||
|
||||
def test_find_by_invalid_method_syntax
|
||||
assert_raises(NoMethodError) { Topic.fail_to_find_by_title("The First Topic") }
|
||||
assert_raises(NoMethodError) { Topic.find_by_title?("The First Topic") }
|
||||
assert_raises(NoMethodError) { Topic.fail_to_find_or_create_by_title("Nonexistent Title") }
|
||||
assert_raises(NoMethodError) { Topic.find_or_create_by_title?("Nonexistent Title") }
|
||||
end
|
||||
|
||||
def test_find_by_two_attributes
|
||||
assert_equal topics(:first), Topic.find_by_title_and_author_name("The First Topic", "David")
|
||||
|
@ -286,6 +374,7 @@ class FinderTest < Test::Unit::TestCase
|
|||
sig38 = Company.find_or_create_by_name("38signals")
|
||||
assert_equal number_of_companies + 1, Company.count
|
||||
assert_equal sig38, Company.find_or_create_by_name("38signals")
|
||||
assert !sig38.new_record?
|
||||
end
|
||||
|
||||
def test_find_or_create_from_two_attributes
|
||||
|
@ -293,6 +382,20 @@ class FinderTest < Test::Unit::TestCase
|
|||
another = Topic.find_or_create_by_title_and_author_name("Another topic","John")
|
||||
assert_equal number_of_topics + 1, Topic.count
|
||||
assert_equal another, Topic.find_or_create_by_title_and_author_name("Another topic", "John")
|
||||
assert !another.new_record?
|
||||
end
|
||||
|
||||
def test_find_or_initialize_from_one_attribute
|
||||
sig38 = Company.find_or_initialize_by_name("38signals")
|
||||
assert_equal "38signals", sig38.name
|
||||
assert sig38.new_record?
|
||||
end
|
||||
|
||||
def test_find_or_initialize_from_two_attributes
|
||||
another = Topic.find_or_initialize_by_title_and_author_name("Another topic","John")
|
||||
assert_equal "Another topic", another.title
|
||||
assert_equal "John", another.author_name
|
||||
assert another.new_record?
|
||||
end
|
||||
|
||||
def test_find_with_bad_sql
|
||||
|
@ -357,6 +460,26 @@ class FinderTest < Test::Unit::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
# http://dev.rubyonrails.org/ticket/6778
|
||||
def test_find_ignores_previously_inserted_record
|
||||
post = Post.create!(:title => 'test', :body => 'it out')
|
||||
assert_equal [], Post.find_all_by_id(nil)
|
||||
end
|
||||
|
||||
def test_find_by_empty_ids
|
||||
assert_equal [], Post.find([])
|
||||
end
|
||||
|
||||
def test_find_by_empty_in_condition
|
||||
assert_equal [], Post.find(:all, :conditions => ['id in (?)', []])
|
||||
end
|
||||
|
||||
def test_find_by_records
|
||||
p1, p2 = Post.find(:all, :limit => 2, :order => 'id asc')
|
||||
assert_equal [p1, p2], Post.find(:all, :conditions => ['id in (?)', [p1, p2]], :order => 'id asc')
|
||||
assert_equal [p1, p2], Post.find(:all, :conditions => ['id in (?)', [p1, p2.id]], :order => 'id asc')
|
||||
end
|
||||
|
||||
def test_select_value
|
||||
assert_equal "37signals", Company.connection.select_value("SELECT name FROM companies WHERE id = 1")
|
||||
assert_nil Company.connection.select_value("SELECT name FROM companies WHERE id = -1")
|
||||
|
@ -366,8 +489,8 @@ class FinderTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_select_values
|
||||
assert_equal ["1","2","3","4","5","6","7","8"], Company.connection.select_values("SELECT id FROM companies ORDER BY id").map! { |i| i.to_s }
|
||||
assert_equal ["37signals","Summit","Microsoft", "Flamboyant Software", "Ex Nihilo", "RailsCore", "Leetsoft", "Jadedpixel"], Company.connection.select_values("SELECT name FROM companies ORDER BY id")
|
||||
assert_equal ["1","2","3","4","5","6","7","8","9"], Company.connection.select_values("SELECT id FROM companies ORDER BY id").map! { |i| i.to_s }
|
||||
assert_equal ["37signals","Summit","Microsoft", "Flamboyant Software", "Ex Nihilo", "RailsCore", "Leetsoft", "Jadedpixel", "Odegy"], Company.connection.select_values("SELECT name FROM companies ORDER BY id")
|
||||
end
|
||||
|
||||
protected
|
||||
|
|
|
@ -20,4 +20,9 @@ last_account:
|
|||
rails_core_account_2:
|
||||
id: 5
|
||||
firm_id: 6
|
||||
credit_limit: 55
|
||||
credit_limit: 55
|
||||
|
||||
odegy_account:
|
||||
id: 6
|
||||
firm_id: 9
|
||||
credit_limit: 53
|
||||
|
|
|
@ -3,12 +3,30 @@ class Author < ActiveRecord::Base
|
|||
has_many :posts_with_comments, :include => :comments, :class_name => "Post"
|
||||
has_many :posts_with_categories, :include => :categories, :class_name => "Post"
|
||||
has_many :posts_with_comments_and_categories, :include => [ :comments, :categories ], :order => "posts.id", :class_name => "Post"
|
||||
has_many :posts_with_extension, :class_name => "Post" do #, :extend => ProxyTestExtension
|
||||
def testing_proxy_owner
|
||||
proxy_owner
|
||||
end
|
||||
def testing_proxy_reflection
|
||||
proxy_reflection
|
||||
end
|
||||
def testing_proxy_target
|
||||
proxy_target
|
||||
end
|
||||
end
|
||||
has_many :comments, :through => :posts
|
||||
has_many :funky_comments, :through => :posts, :source => :comments
|
||||
|
||||
has_many :special_posts, :class_name => "Post"
|
||||
has_many :hello_posts, :class_name => "Post", :conditions=>"\#{aliased_table_name}.body = 'hello'"
|
||||
has_many :nonexistent_posts, :class_name => "Post", :conditions=>"\#{aliased_table_name}.body = 'nonexistent'"
|
||||
has_many :special_posts
|
||||
has_many :special_post_comments, :through => :special_posts, :source => :comments
|
||||
|
||||
has_many :special_nonexistant_posts, :class_name => "SpecialPost", :conditions => "posts.body = 'nonexistant'"
|
||||
has_many :special_nonexistant_post_comments, :through => :special_nonexistant_posts, :source => :comments, :conditions => "comments.post_id = 0"
|
||||
|
||||
has_many :hello_posts, :class_name => "Post", :conditions => "posts.body = 'hello'"
|
||||
has_many :hello_post_comments, :through => :hello_posts, :source => :comments
|
||||
|
||||
has_many :other_posts, :class_name => "Post"
|
||||
has_many :posts_with_callbacks, :class_name => "Post", :before_add => :log_before_adding,
|
||||
:after_add => :log_after_adding,
|
||||
:before_remove => :log_before_removing,
|
||||
|
@ -26,6 +44,11 @@ class Author < ActiveRecord::Base
|
|||
has_many :categorizations
|
||||
has_many :categories, :through => :categorizations
|
||||
|
||||
has_many :categories_like_general, :through => :categorizations, :source => :category, :class_name => 'Category', :conditions => { :name => 'General' }
|
||||
|
||||
has_many :categorized_posts, :through => :categorizations, :source => :post
|
||||
has_many :unique_categorized_posts, :through => :categorizations, :source => :post, :uniq => true
|
||||
|
||||
has_many :nothings, :through => :kateggorisatons, :class_name => 'Category'
|
||||
|
||||
has_many :author_favorites
|
||||
|
@ -73,4 +96,4 @@ end
|
|||
class AuthorFavorite < ActiveRecord::Base
|
||||
belongs_to :author
|
||||
belongs_to :favorite_author, :class_name => "Author", :foreign_key => 'favorite_author_id'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,9 +3,15 @@ david_welcome_general:
|
|||
author_id: 1
|
||||
post_id: 1
|
||||
category_id: 1
|
||||
|
||||
|
||||
mary_thinking_sti:
|
||||
id: 2
|
||||
author_id: 2
|
||||
post_id: 2
|
||||
category_id: 3
|
||||
category_id: 3
|
||||
|
||||
mary_thinking_general:
|
||||
id: 3
|
||||
author_id: 2
|
||||
post_id: 2
|
||||
category_id: 1
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
class Category < ActiveRecord::Base
|
||||
has_and_belongs_to_many :posts
|
||||
has_and_belongs_to_many :special_posts, :class_name => "Post"
|
||||
has_and_belongs_to_many :hello_posts, :class_name => "Post", :conditions => "\#{aliased_table_name}.body = 'hello'"
|
||||
has_and_belongs_to_many :nonexistent_posts, :class_name => "Post", :conditions=>"\#{aliased_table_name}.body = 'nonexistent'"
|
||||
has_and_belongs_to_many :other_posts, :class_name => "Post"
|
||||
|
||||
def self.what_are_you
|
||||
'a category...'
|
||||
|
|
|
@ -16,12 +16,6 @@ does_it_hurt:
|
|||
body: Don't think too hard
|
||||
type: SpecialComment
|
||||
|
||||
eager_sti_on_associations_comment:
|
||||
id: 4
|
||||
post_id: 4
|
||||
body: Normal type
|
||||
type: Comment
|
||||
|
||||
eager_sti_on_associations_vs_comment:
|
||||
id: 5
|
||||
post_id: 4
|
||||
|
|
|
@ -47,4 +47,9 @@ leetsoft:
|
|||
jadedpixel:
|
||||
id: 8
|
||||
name: Jadedpixel
|
||||
client_of: 6
|
||||
client_of: 6
|
||||
|
||||
odegy:
|
||||
id: 9
|
||||
name: Odegy
|
||||
type: ExclusivelyDependentFirm
|
||||
|
|
|
@ -5,6 +5,10 @@ class Company < ActiveRecord::Base
|
|||
validates_presence_of :name
|
||||
|
||||
has_one :dummy_account, :foreign_key => "firm_id", :class_name => "Account"
|
||||
|
||||
def arbitrary_method
|
||||
"I am Jack's profound disappointment"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
@ -18,6 +22,8 @@ class Firm < Company
|
|||
has_many :exclusively_dependent_clients_of_firm, :foreign_key => "client_of", :class_name => "Client", :order => "id", :dependent => :delete_all
|
||||
has_many :limited_clients, :class_name => "Client", :order => "id", :limit => 1
|
||||
has_many :clients_like_ms, :conditions => "name = 'Microsoft'", :class_name => "Client", :order => "id"
|
||||
has_many :clients_with_interpolated_conditions, :class_name => "Client", :conditions => 'rating > #{rating}'
|
||||
has_many :clients_like_ms_with_hash_conditions, :conditions => { :name => 'Microsoft' }, :class_name => "Client", :order => "id"
|
||||
has_many :clients_using_sql, :class_name => "Client", :finder_sql => 'SELECT * FROM companies WHERE client_of = #{id}'
|
||||
has_many :clients_using_counter_sql, :class_name => "Client",
|
||||
:finder_sql => 'SELECT * FROM companies WHERE client_of = #{id}',
|
||||
|
@ -28,6 +34,7 @@ class Firm < Company
|
|||
has_many :no_clients_using_counter_sql, :class_name => "Client",
|
||||
:finder_sql => 'SELECT * FROM companies WHERE client_of = 1000',
|
||||
:counter_sql => 'SELECT COUNT(*) FROM companies WHERE client_of = 1000'
|
||||
has_many :plain_clients, :class_name => 'Client'
|
||||
|
||||
has_one :account, :foreign_key => "firm_id", :dependent => :destroy
|
||||
end
|
||||
|
@ -37,6 +44,9 @@ class DependentFirm < Company
|
|||
has_many :companies, :foreign_key => 'client_of', :order => "id", :dependent => :nullify
|
||||
end
|
||||
|
||||
class ExclusivelyDependentFirm < Company
|
||||
has_one :account, :foreign_key => "firm_id", :dependent => :delete
|
||||
end
|
||||
|
||||
class Client < Company
|
||||
belongs_to :firm, :foreign_key => "client_of"
|
||||
|
@ -78,8 +88,20 @@ end
|
|||
class Account < ActiveRecord::Base
|
||||
belongs_to :firm
|
||||
|
||||
def self.destroyed_account_ids
|
||||
@destroyed_account_ids ||= Hash.new { |h,k| h[k] = [] }
|
||||
end
|
||||
|
||||
before_destroy do |account|
|
||||
if account.firm
|
||||
Account.destroyed_account_ids[account.firm.id] << account.id
|
||||
end
|
||||
true
|
||||
end
|
||||
|
||||
|
||||
protected
|
||||
def validate
|
||||
errors.add_on_empty "credit_limit"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -21,11 +21,7 @@ module MyApplication
|
|||
|
||||
class Developer < ActiveRecord::Base
|
||||
has_and_belongs_to_many :projects
|
||||
|
||||
protected
|
||||
def validate
|
||||
errors.add_on_boundary_breaking("name", 3..20)
|
||||
end
|
||||
validates_length_of :name, :within => (3..20)
|
||||
end
|
||||
|
||||
class Project < ActiveRecord::Base
|
||||
|
@ -46,11 +42,13 @@ module MyApplication
|
|||
end
|
||||
|
||||
class Account < ActiveRecord::Base
|
||||
belongs_to :firm, :class_name => 'MyApplication::Business::Firm'
|
||||
belongs_to :qualified_billing_firm, :class_name => 'MyApplication::Billing::Firm'
|
||||
belongs_to :unqualified_billing_firm, :class_name => 'Firm'
|
||||
belongs_to :nested_qualified_billing_firm, :class_name => 'MyApplication::Billing::Nested::Firm'
|
||||
belongs_to :nested_unqualified_billing_firm, :class_name => 'Nested::Firm'
|
||||
with_options(:foreign_key => :firm_id) do |i|
|
||||
i.belongs_to :firm, :class_name => 'MyApplication::Business::Firm'
|
||||
i.belongs_to :qualified_billing_firm, :class_name => 'MyApplication::Billing::Firm'
|
||||
i.belongs_to :unqualified_billing_firm, :class_name => 'Firm'
|
||||
i.belongs_to :nested_qualified_billing_firm, :class_name => 'MyApplication::Billing::Nested::Firm'
|
||||
i.belongs_to :nested_unqualified_billing_firm, :class_name => 'Nested::Firm'
|
||||
end
|
||||
|
||||
protected
|
||||
def validate
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
class Customer < ActiveRecord::Base
|
||||
composed_of :address, :mapping => [ %w(address_street street), %w(address_city city), %w(address_country country) ]
|
||||
composed_of :address, :mapping => [ %w(address_street street), %w(address_city city), %w(address_country country) ], :allow_nil => true
|
||||
composed_of :balance, :class_name => "Money", :mapping => %w(balance amount)
|
||||
composed_of :gps_location
|
||||
composed_of :gps_location, :allow_nil => true
|
||||
end
|
||||
|
||||
class Address
|
||||
|
|
|
@ -6,3 +6,12 @@ david:
|
|||
address_city: Scary Town
|
||||
address_country: Loony Land
|
||||
gps_location: 35.544623640962634x-105.9309951055148
|
||||
|
||||
zaphod:
|
||||
id: 2
|
||||
name: Zaphod
|
||||
balance: 62
|
||||
address_street: Avenue Road
|
||||
address_city: Hamlet Town
|
||||
address_country: Nation Land
|
||||
gps_location: NULL
|
|
@ -28,3 +28,4 @@ DROP TABLE fk_test_has_pk;
|
|||
DROP TABLE fk_test_has_fk;
|
||||
DROP TABLE keyboards;
|
||||
DROP TABLE legacy_things;
|
||||
DROP TABLE numeric_data;
|
||||
|
|
|
@ -215,3 +215,12 @@ CREATE TABLE legacy_things (
|
|||
version INT DEFAULT 0,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE numeric_data (
|
||||
id INT NOT NULL PRIMARY KEY,
|
||||
bank_balance DECIMAL(10,2),
|
||||
big_bank_balance DECIMAL(15,2),
|
||||
world_population DECIMAL(10),
|
||||
my_house_population DECIMAL(2),
|
||||
decimal_number_with_default DECIMAL(3,2) DEFAULT 2.78
|
||||
);
|
||||
|
|
|
@ -29,6 +29,7 @@ DROP TABLE fk_test_has_pk;
|
|||
DROP TABLE keyboards;
|
||||
DROP TABLE defaults;
|
||||
DROP TABLE legacy_things;
|
||||
DROP TABLE numeric_data;
|
||||
|
||||
DROP DOMAIN D_BOOLEAN;
|
||||
|
||||
|
@ -56,3 +57,5 @@ DROP GENERATOR tasks_seq;
|
|||
DROP GENERATOR categories_seq;
|
||||
DROP GENERATOR keyboards_seq;
|
||||
DROP GENERATOR defaults_seq;
|
||||
DROP GENERATOR legacy_things_seq;
|
||||
DROP GENERATOR numeric_data_seq;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
CREATE DOMAIN D_BOOLEAN AS SMALLINT CHECK (VALUE IN (0, 1));
|
||||
CREATE DOMAIN D_BOOLEAN AS SMALLINT CHECK (VALUE IN (0, 1) OR VALUE IS NULL);
|
||||
|
||||
CREATE TABLE accounts (
|
||||
id BIGINT NOT NULL,
|
||||
|
@ -283,3 +283,15 @@ CREATE TABLE legacy_things (
|
|||
);
|
||||
CREATE GENERATOR legacy_things_seq;
|
||||
SET GENERATOR legacy_things_seq TO 10000;
|
||||
|
||||
CREATE TABLE numeric_data (
|
||||
id BIGINT NOT NULL,
|
||||
bank_balance DECIMAL(10,2),
|
||||
big_bank_balance DECIMAL(15,2),
|
||||
world_population DECIMAL(10),
|
||||
my_house_population DECIMAL(2),
|
||||
decimal_number_with_default DECIMAL(3,2) DEFAULT 2.78,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
CREATE GENERATOR numeric_data_seq;
|
||||
SET GENERATOR numeric_data_seq TO 10000;
|
||||
|
|
|
@ -28,3 +28,4 @@ DROP TABLE fk_test_has_fk;
|
|||
DROP TABLE fk_test_has_pk;
|
||||
DROP TABLE keyboards;
|
||||
DROP TABLE legacy_things;
|
||||
DROP TABLE numeric_data;
|
||||
|
|
|
@ -37,7 +37,7 @@ CREATE TABLE `topics` (
|
|||
`parent_id` int(11) default NULL,
|
||||
`type` varchar(50) default NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) TYPE=InnoDB;
|
||||
) TYPE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
CREATE TABLE `developers` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
|
@ -51,7 +51,7 @@ CREATE TABLE `developers` (
|
|||
CREATE TABLE `projects` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
`name` varchar(100) default NULL,
|
||||
`type` VARCHAR(255) NOT NULL,
|
||||
`type` VARCHAR(255) default NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) TYPE=InnoDB;
|
||||
|
||||
|
@ -106,7 +106,7 @@ CREATE TABLE `auto_id_tests` (
|
|||
) TYPE=InnoDB;
|
||||
|
||||
CREATE TABLE `entrants` (
|
||||
`id` INTEGER NOT NULL PRIMARY KEY,
|
||||
`id` INTEGER NOT NULL auto_increment PRIMARY KEY,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`course_id` INTEGER NOT NULL
|
||||
);
|
||||
|
@ -131,13 +131,13 @@ CREATE TABLE `mixins` (
|
|||
) TYPE=InnoDB;
|
||||
|
||||
CREATE TABLE `people` (
|
||||
`id` INTEGER NOT NULL PRIMARY KEY,
|
||||
`id` INTEGER NOT NULL auto_increment PRIMARY KEY,
|
||||
`first_name` VARCHAR(40) NOT NULL,
|
||||
`lock_version` INTEGER NOT NULL DEFAULT 0
|
||||
) TYPE=InnoDB;
|
||||
|
||||
CREATE TABLE `readers` (
|
||||
`id` int(11) NOT NULL PRIMARY KEY,
|
||||
`id` int(11) NOT NULL auto_increment PRIMARY KEY,
|
||||
`post_id` INTEGER NOT NULL,
|
||||
`person_id` INTEGER NOT NULL
|
||||
) TYPE=InnoDB;
|
||||
|
@ -149,28 +149,28 @@ CREATE TABLE `binaries` (
|
|||
) TYPE=InnoDB;
|
||||
|
||||
CREATE TABLE `computers` (
|
||||
`id` INTEGER NOT NULL PRIMARY KEY,
|
||||
`id` INTEGER NOT NULL auto_increment PRIMARY KEY,
|
||||
`developer` INTEGER NOT NULL,
|
||||
`extendedWarranty` INTEGER NOT NULL
|
||||
) TYPE=InnoDB;
|
||||
|
||||
CREATE TABLE `posts` (
|
||||
`id` INTEGER NOT NULL PRIMARY KEY,
|
||||
`id` INTEGER NOT NULL auto_increment PRIMARY KEY,
|
||||
`author_id` INTEGER,
|
||||
`title` VARCHAR(255) NOT NULL,
|
||||
`body` TEXT NOT NULL,
|
||||
`type` VARCHAR(255) NOT NULL
|
||||
`type` VARCHAR(255) default NULL
|
||||
) TYPE=InnoDB;
|
||||
|
||||
CREATE TABLE `comments` (
|
||||
`id` INTEGER NOT NULL PRIMARY KEY,
|
||||
`id` INTEGER NOT NULL auto_increment PRIMARY KEY,
|
||||
`post_id` INTEGER NOT NULL,
|
||||
`body` TEXT NOT NULL,
|
||||
`type` VARCHAR(255) NOT NULL
|
||||
`type` VARCHAR(255) default NULL
|
||||
) TYPE=InnoDB;
|
||||
|
||||
CREATE TABLE `authors` (
|
||||
`id` INTEGER NOT NULL PRIMARY KEY,
|
||||
`id` INTEGER NOT NULL auto_increment PRIMARY KEY,
|
||||
`name` VARCHAR(255) NOT NULL
|
||||
) TYPE=InnoDB;
|
||||
|
||||
|
@ -184,7 +184,7 @@ CREATE TABLE `tasks` (
|
|||
CREATE TABLE `categories` (
|
||||
`id` int(11) NOT NULL auto_increment,
|
||||
`name` VARCHAR(255) NOT NULL,
|
||||
`type` VARCHAR(255) NOT NULL,
|
||||
`type` VARCHAR(255) default NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) TYPE=InnoDB;
|
||||
|
||||
|
@ -194,11 +194,11 @@ CREATE TABLE `categories_posts` (
|
|||
) TYPE=InnoDB;
|
||||
|
||||
CREATE TABLE `fk_test_has_pk` (
|
||||
`id` INTEGER NOT NULL PRIMARY KEY
|
||||
`id` INTEGER NOT NULL auto_increment PRIMARY KEY
|
||||
) TYPE=InnoDB;
|
||||
|
||||
CREATE TABLE `fk_test_has_fk` (
|
||||
`id` INTEGER NOT NULL PRIMARY KEY,
|
||||
`id` INTEGER NOT NULL auto_increment PRIMARY KEY,
|
||||
`fk_id` INTEGER NOT NULL,
|
||||
|
||||
FOREIGN KEY (`fk_id`) REFERENCES `fk_test_has_pk`(`id`)
|
||||
|
@ -217,3 +217,12 @@ CREATE TABLE `legacy_things` (
|
|||
`version` int(11) NOT NULL default 0,
|
||||
PRIMARY KEY (`id`)
|
||||
) TYPE=InnoDB;
|
||||
|
||||
CREATE TABLE `numeric_data` (
|
||||
`id` INTEGER NOT NULL auto_increment PRIMARY KEY,
|
||||
`bank_balance` decimal(10,2),
|
||||
`big_bank_balance` decimal(15,2),
|
||||
`world_population` decimal(10),
|
||||
`my_house_population` decimal(2),
|
||||
`decimal_number_with_default` decimal(3,2) DEFAULT 2.78
|
||||
) TYPE=InnoDB;
|
||||
|
|
|
@ -279,4 +279,16 @@ CREATE TABLE legacy_things (
|
|||
)
|
||||
go
|
||||
CREATE PRIMARY KEY legacy_things (id)
|
||||
go
|
||||
go
|
||||
|
||||
CREATE TABLE numeric_data (
|
||||
id INTEGER NOT NULL DEFAULT _rowid,
|
||||
bank_balance DECIMAL(10,2),
|
||||
big_bank_balance DECIMAL(15,2),
|
||||
world_population DECIMAL(10),
|
||||
my_house_population DECIMAL(2),
|
||||
decimal_number_with_default DECIMAL(3,2) DEFAULT 2.78
|
||||
);
|
||||
go
|
||||
CREATE PRIMARY KEY numeric_data (id)
|
||||
go
|
||||
|
|
|
@ -29,6 +29,7 @@ drop table fk_test_has_pk;
|
|||
drop table fk_test_has_fk;
|
||||
drop table keyboards;
|
||||
drop table legacy_things;
|
||||
drop table numeric_data;
|
||||
|
||||
drop sequence accounts_seq;
|
||||
drop sequence funny_jokes_seq;
|
||||
|
@ -59,3 +60,4 @@ drop sequence fk_test_has_pk_seq;
|
|||
drop sequence fk_test_has_fk_seq;
|
||||
drop sequence keyboards_seq;
|
||||
drop sequence legacy_things_seq;
|
||||
drop sequence numeric_data_seq;
|
||||
|
|
|
@ -37,7 +37,7 @@ create table topics (
|
|||
bonus_time timestamp default null,
|
||||
last_read timestamp default null,
|
||||
content varchar(4000),
|
||||
approved integer default 1,
|
||||
approved number(1) default 1,
|
||||
replies_count integer default 0,
|
||||
parent_id integer references topics initially deferred disable,
|
||||
type varchar(50) default null,
|
||||
|
@ -53,7 +53,7 @@ create table topics (
|
|||
bonus_time date default null,
|
||||
last_read date default null,
|
||||
content varchar(4000),
|
||||
approved integer default 1,
|
||||
approved number(1) default 1,
|
||||
replies_count integer default 0,
|
||||
parent_id integer references topics initially deferred disable,
|
||||
type varchar(50) default null,
|
||||
|
@ -137,6 +137,23 @@ create table booleantests (
|
|||
);
|
||||
create sequence booleantests_seq minvalue 10000;
|
||||
|
||||
CREATE TABLE defaults (
|
||||
id integer not null,
|
||||
modified_date date default sysdate,
|
||||
modified_date_function date default sysdate,
|
||||
fixed_date date default to_date('2004-01-01', 'YYYY-MM-DD'),
|
||||
modified_time date default sysdate,
|
||||
modified_time_function date default sysdate,
|
||||
fixed_time date default TO_DATE('2004-01-01 00:00:00', 'YYYY-MM-DD HH24:MI:SS'),
|
||||
char1 varchar2(1) default 'Y',
|
||||
char2 varchar2(50) default 'a varchar field',
|
||||
char3 clob default 'a text field',
|
||||
positive_integer integer default 1,
|
||||
negative_integer integer default -1,
|
||||
decimal_number number(3,2) default 2.78
|
||||
);
|
||||
create sequence defaults_seq minvalue 10000;
|
||||
|
||||
create table auto_id_tests (
|
||||
auto_id integer not null,
|
||||
value integer default null,
|
||||
|
@ -290,3 +307,13 @@ create table legacy_things (
|
|||
version integer default 0
|
||||
);
|
||||
create sequence legacy_things_seq minvalue 10000;
|
||||
|
||||
CREATE TABLE numeric_data (
|
||||
id integer NOT NULL PRIMARY KEY,
|
||||
bank_balance decimal(10,2),
|
||||
big_bank_balance decimal(15,2),
|
||||
world_population decimal(10),
|
||||
my_house_population decimal(2),
|
||||
decimal_number_with_default decimal(3,2) DEFAULT 2.78
|
||||
);
|
||||
create sequence numeric_data_seq minvalue 10000;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
DROP SEQUENCE accounts_id_seq;
|
||||
DROP TABLE accounts;
|
||||
DROP SEQUENCE accounts_id_seq;
|
||||
DROP TABLE funny_jokes;
|
||||
DROP TABLE companies;
|
||||
DROP SEQUENCE companies_nonstd_seq;
|
||||
|
@ -32,3 +32,5 @@ DROP TABLE fk_test_has_pk;
|
|||
DROP TABLE geometrics;
|
||||
DROP TABLE keyboards;
|
||||
DROP TABLE legacy_things;
|
||||
DROP TABLE numeric_data;
|
||||
DROP TABLE column_data;
|
||||
|
|
|
@ -118,7 +118,8 @@ CREATE TABLE defaults (
|
|||
char2 character varying(50) default 'a varchar field',
|
||||
char3 text default 'a text field',
|
||||
positive_integer integer default 1,
|
||||
negative_integer integer default -1
|
||||
negative_integer integer default -1,
|
||||
decimal_number decimal(3,2) default 2.78
|
||||
);
|
||||
|
||||
CREATE TABLE auto_id_tests (
|
||||
|
@ -129,8 +130,8 @@ CREATE TABLE auto_id_tests (
|
|||
|
||||
CREATE TABLE entrants (
|
||||
id serial,
|
||||
name text,
|
||||
course_id integer
|
||||
name text not null,
|
||||
course_id integer not null
|
||||
);
|
||||
|
||||
CREATE TABLE colnametests (
|
||||
|
@ -246,3 +247,12 @@ CREATE TABLE legacy_things (
|
|||
tps_report_number integer,
|
||||
version integer default 0
|
||||
);
|
||||
|
||||
CREATE TABLE numeric_data (
|
||||
id serial primary key,
|
||||
bank_balance decimal(10,2),
|
||||
big_bank_balance decimal(15,2),
|
||||
world_population decimal(10),
|
||||
my_house_population decimal(2),
|
||||
decimal_number_with_default decimal(3,2) default 2.78
|
||||
);
|
||||
|
|
|
@ -1,5 +1,15 @@
|
|||
ActiveRecord::Schema.define do
|
||||
|
||||
# For Firebird, set the sequence values 10000 when create_table is called;
|
||||
# this prevents primary key collisions between "normally" created records
|
||||
# and fixture-based (YAML) records.
|
||||
if adapter_name == "Firebird"
|
||||
def create_table(*args, &block)
|
||||
ActiveRecord::Base.connection.create_table(*args, &block)
|
||||
ActiveRecord::Base.connection.execute "SET GENERATOR #{args.first}_seq TO 10000"
|
||||
end
|
||||
end
|
||||
|
||||
create_table :taggings, :force => true do |t|
|
||||
t.column :tag_id, :integer
|
||||
t.column :super_tag_id, :integer
|
||||
|
@ -29,4 +39,22 @@ ActiveRecord::Schema.define do
|
|||
t.column :author_id, :integer
|
||||
t.column :favorite_author_id, :integer
|
||||
end
|
||||
end
|
||||
|
||||
create_table :vertices, :force => true do |t|
|
||||
t.column :label, :string
|
||||
end
|
||||
|
||||
create_table :edges, :force => true do |t|
|
||||
t.column :source_id, :integer, :null => false
|
||||
t.column :sink_id, :integer, :null => false
|
||||
end
|
||||
add_index :edges, [:source_id, :sink_id], :unique => true, :name => 'unique_edge_index'
|
||||
|
||||
create_table :lock_without_defaults, :force => true do |t|
|
||||
t.column :lock_version, :integer
|
||||
end
|
||||
|
||||
create_table :lock_without_defaults_cust, :force => true do |t|
|
||||
t.column :custom_lock_version, :integer
|
||||
end
|
||||
end
|
||||
|
|
|
@ -28,3 +28,4 @@ DROP TABLE fk_test_has_fk;
|
|||
DROP TABLE fk_test_has_pk;
|
||||
DROP TABLE keyboards;
|
||||
DROP TABLE legacy_things;
|
||||
DROP TABLE numeric_data;
|
||||
|
|
|
@ -144,14 +144,14 @@ CREATE TABLE 'posts' (
|
|||
'id' INTEGER NOT NULL PRIMARY KEY,
|
||||
'author_id' INTEGER,
|
||||
'title' VARCHAR(255) NOT NULL,
|
||||
'type' VARCHAR(255) NOT NULL,
|
||||
'type' VARCHAR(255) DEFAULT NULL,
|
||||
'body' TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE 'comments' (
|
||||
'id' INTEGER NOT NULL PRIMARY KEY,
|
||||
'post_id' INTEGER NOT NULL,
|
||||
'type' VARCHAR(255) NOT NULL,
|
||||
'type' VARCHAR(255) DEFAULT NULL,
|
||||
'body' TEXT NOT NULL
|
||||
);
|
||||
|
||||
|
@ -198,4 +198,13 @@ CREATE TABLE 'legacy_things' (
|
|||
'id' INTEGER NOT NULL PRIMARY KEY,
|
||||
'tps_report_number' INTEGER DEFAULT NULL,
|
||||
'version' INTEGER NOT NULL DEFAULT 0
|
||||
)
|
||||
);
|
||||
|
||||
CREATE TABLE 'numeric_data' (
|
||||
'id' INTEGER NOT NULL PRIMARY KEY,
|
||||
'bank_balance' DECIMAL(10,2),
|
||||
'big_bank_balance' DECIMAL(15,2),
|
||||
'world_population' DECIMAL(10),
|
||||
'my_house_population' DECIMAL(2),
|
||||
'decimal_number_with_default' DECIMAL(3,2) DEFAULT 2.78
|
||||
);
|
||||
|
|
|
@ -10,6 +10,7 @@ DROP TABLE orders;
|
|||
DROP TABLE movies;
|
||||
DROP TABLE subscribers;
|
||||
DROP TABLE booleantests;
|
||||
DROP TABLE defaults;
|
||||
DROP TABLE auto_id_tests;
|
||||
DROP TABLE entrants;
|
||||
DROP TABLE colnametests;
|
||||
|
@ -28,3 +29,5 @@ DROP TABLE fk_test_has_fk;
|
|||
DROP TABLE fk_test_has_pk;
|
||||
DROP TABLE keyboards;
|
||||
DROP TABLE legacy_things;
|
||||
DROP TABLE numeric_data;
|
||||
DROP TABLE [order];
|
||||
|
|
|
@ -88,6 +88,24 @@ CREATE TABLE booleantests (
|
|||
value bit default NULL
|
||||
);
|
||||
|
||||
CREATE TABLE defaults (
|
||||
id int NOT NULL IDENTITY(1, 1) PRIMARY KEY,
|
||||
-- these brought from the PostgreSQL defaults_test.rb but
|
||||
-- tests only exist for integers and decimals, currently
|
||||
-- modified_date date default CURRENT_DATE,
|
||||
-- modified_date_function date default now(),
|
||||
-- fixed_date date default '2004-01-01',
|
||||
-- modified_time timestamp default CURRENT_TIMESTAMP,
|
||||
-- modified_time_function timestamp default now(),
|
||||
-- fixed_time timestamp default '2004-01-01 00:00:00.000000-00',
|
||||
-- char1 char(1) default 'Y',
|
||||
-- char2 character varying(50) default 'a varchar field',
|
||||
-- char3 text default 'a text field',
|
||||
positive_integer integer default 1,
|
||||
negative_integer integer default -1,
|
||||
decimal_number decimal(3,2) default 2.78
|
||||
);
|
||||
|
||||
CREATE TABLE auto_id_tests (
|
||||
auto_id int NOT NULL IDENTITY(1, 1) PRIMARY KEY,
|
||||
value int default NULL
|
||||
|
@ -201,3 +219,20 @@ CREATE TABLE legacy_things (
|
|||
version int default 0,
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE numeric_data (
|
||||
id int NOT NULL IDENTITY(1, 1),
|
||||
bank_balance decimal(10,2),
|
||||
big_bank_balance decimal(15,2),
|
||||
world_population decimal(10),
|
||||
my_house_population decimal(2),
|
||||
decimal_number_with_default decimal(3,2) DEFAULT 2.78
|
||||
);
|
||||
|
||||
CREATE TABLE [order] (
|
||||
id int NOT NULL IDENTITY(1, 1) PRIMARY KEY,
|
||||
color varchar(255),
|
||||
fruit_size varchar(255),
|
||||
texture varchar(255),
|
||||
flavor varchar(255)
|
||||
);
|
||||
|
|
|
@ -28,4 +28,6 @@ DROP TABLE fk_test_has_fk
|
|||
DROP TABLE fk_test_has_pk
|
||||
DROP TABLE keyboards
|
||||
DROP TABLE legacy_things
|
||||
DROP TABLE numeric_data
|
||||
DROP TABLE schema_info
|
||||
go
|
||||
|
|
|
@ -26,7 +26,7 @@ CREATE TABLE topics (
|
|||
author_name varchar(255) NULL,
|
||||
author_email_address varchar(255) NULL,
|
||||
written_on datetime NULL,
|
||||
bonus_time time NULL,
|
||||
bonus_time datetime NULL,
|
||||
last_read datetime NULL,
|
||||
content varchar(255) NULL,
|
||||
approved bit default 1,
|
||||
|
@ -118,7 +118,7 @@ CREATE TABLE mixins (
|
|||
|
||||
CREATE TABLE people (
|
||||
id numeric(9,0) IDENTITY PRIMARY KEY,
|
||||
first_name varchar(40) NOT NULL,
|
||||
first_name varchar(40) NULL,
|
||||
lock_version int DEFAULT 0
|
||||
)
|
||||
|
||||
|
@ -197,8 +197,17 @@ CREATE TABLE keyboards (
|
|||
CREATE TABLE legacy_things (
|
||||
id numeric(9,0) IDENTITY PRIMARY KEY,
|
||||
tps_report_number int default NULL,
|
||||
version int default 0,
|
||||
version int default 0
|
||||
)
|
||||
|
||||
|
||||
CREATE TABLE numeric_data (
|
||||
id numeric(9,0) IDENTITY PRIMARY KEY,
|
||||
bank_balance numeric(10,2),
|
||||
big_bank_balance numeric(15,2),
|
||||
world_population numeric(10),
|
||||
my_house_population numeric(2),
|
||||
decimal_number_with_default numeric(3,2) DEFAULT 2.78
|
||||
)
|
||||
|
||||
go
|
||||
|
||||
|
|
|
@ -4,6 +4,12 @@ module DeveloperProjectsAssociationExtension
|
|||
end
|
||||
end
|
||||
|
||||
module DeveloperProjectsAssociationExtension2
|
||||
def find_least_recent
|
||||
find(:first, :order => "id ASC")
|
||||
end
|
||||
end
|
||||
|
||||
class Developer < ActiveRecord::Base
|
||||
has_and_belongs_to_many :projects do
|
||||
def find_most_recent
|
||||
|
@ -17,6 +23,12 @@ class Developer < ActiveRecord::Base
|
|||
:association_foreign_key => "project_id",
|
||||
:extend => DeveloperProjectsAssociationExtension
|
||||
|
||||
has_and_belongs_to_many :projects_extended_by_name_twice,
|
||||
:class_name => "Project",
|
||||
:join_table => "developers_projects",
|
||||
:association_foreign_key => "project_id",
|
||||
:extend => [DeveloperProjectsAssociationExtension, DeveloperProjectsAssociationExtension2]
|
||||
|
||||
has_and_belongs_to_many :special_projects, :join_table => 'developers_projects', :association_foreign_key => 'project_id'
|
||||
|
||||
validates_inclusion_of :salary, :in => 50000..200000
|
||||
|
|
|
@ -4,11 +4,7 @@ a_joke:
|
|||
|
||||
another_joke:
|
||||
id: 2
|
||||
name: The Aristocrats
|
||||
a_joke:
|
||||
id: 1
|
||||
name: Knock knock
|
||||
name: |
|
||||
The \n Aristocrats
|
||||
Ate the candy
|
||||
|
||||
another_joke:
|
||||
id: 2
|
||||
name: The Aristocrats
|
15
vendor/rails/activerecord/test/fixtures/mixin.rb
vendored
15
vendor/rails/activerecord/test/fixtures/mixin.rb
vendored
|
@ -10,6 +10,11 @@ class TreeMixinWithoutOrder < Mixin
|
|||
acts_as_tree :foreign_key => "parent_id"
|
||||
end
|
||||
|
||||
class RecursivelyCascadedTreeMixin < Mixin
|
||||
acts_as_tree :foreign_key => "parent_id"
|
||||
has_one :first_child, :class_name => 'RecursivelyCascadedTreeMixin', :foreign_key => :parent_id
|
||||
end
|
||||
|
||||
class ListMixin < Mixin
|
||||
acts_as_list :column => "pos", :scope => :parent
|
||||
|
||||
|
@ -46,3 +51,13 @@ class NestedSetWithSymbolScope < Mixin
|
|||
|
||||
def self.table_name() "mixins" end
|
||||
end
|
||||
|
||||
class NestedSetSuperclass < Mixin
|
||||
acts_as_nested_set :scope => :root
|
||||
|
||||
def self.table_name() "mixins" end
|
||||
end
|
||||
|
||||
class NestedSetSubclass < NestedSetSuperclass
|
||||
|
||||
end
|
||||
|
|
|
@ -39,6 +39,26 @@ tree_without_order_2:
|
|||
type: TreeMixinWithoutOrder
|
||||
parent_id:
|
||||
|
||||
recursively_cascaded_tree_1:
|
||||
id: 5005
|
||||
type: RecursivelyCascadedTreeMixin
|
||||
parent_id:
|
||||
|
||||
recursively_cascaded_tree_2:
|
||||
id: 5006
|
||||
type: RecursivelyCascadedTreeMixin
|
||||
parent_id: 5005
|
||||
|
||||
recursively_cascaded_tree_3:
|
||||
id: 5007
|
||||
type: RecursivelyCascadedTreeMixin
|
||||
parent_id: 5006
|
||||
|
||||
recursively_cascaded_tree_4:
|
||||
id: 5008
|
||||
type: RecursivelyCascadedTreeMixin
|
||||
parent_id: 5007
|
||||
|
||||
# List mixins
|
||||
|
||||
<% (1..4).each do |counter| %>
|
||||
|
@ -57,6 +77,24 @@ set_<%= counter %>:
|
|||
type: NestedSet
|
||||
<% end %>
|
||||
|
||||
# Nested set with STI
|
||||
<%
|
||||
[ [3100, 0, 1, 10, "NestedSetSuperclass"],
|
||||
[3101, 3100, 2, 5, "NestedSetSubclass"],
|
||||
[3102, 3101, 3, 4, "NestedSetSuperclass"],
|
||||
[3103, 3100, 6, 9, "NestedSetSuperclass"],
|
||||
[3104, 3103, 7, 8, "NestedSetSubclass"]
|
||||
].each do |sti| %>
|
||||
sti_set_<%= sti[0] %>:
|
||||
id: <%= sti[0] %>
|
||||
parent_id: <%= sti[1] %>
|
||||
lft: <%= sti[2] %>
|
||||
rgt: <%= sti[3] %>
|
||||
type: <%= sti[4] %>
|
||||
root_id: 3100
|
||||
|
||||
<% end %>
|
||||
|
||||
# Big old set
|
||||
<%
|
||||
[[4001, 0, 1, 20],
|
||||
|
|
|
@ -5,7 +5,7 @@ class Post < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
belongs_to :author_with_posts, :class_name => "Author", :include => :posts
|
||||
belongs_to :author_with_posts, :class_name => "Author", :foreign_key => :author_id, :include => :posts
|
||||
|
||||
has_many :comments, :order => "body" do
|
||||
def find_most_recent
|
||||
|
@ -46,7 +46,7 @@ class Post < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
class SpecialPost < Post; end;
|
||||
class SpecialPost < Post; end
|
||||
|
||||
class StiPost < Post
|
||||
self.abstract_class = true
|
||||
|
@ -54,4 +54,5 @@ class StiPost < Post
|
|||
end
|
||||
|
||||
class SubStiPost < StiPost
|
||||
self.table_name = Post.table_name
|
||||
end
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
class Project < ActiveRecord::Base
|
||||
has_and_belongs_to_many :developers, :uniq => true
|
||||
has_and_belongs_to_many :developers, :uniq => true, :order => 'developers.name desc, developers.id desc'
|
||||
has_and_belongs_to_many :non_unique_developers, :order => 'developers.name desc, developers.id desc', :class_name => 'Developer'
|
||||
has_and_belongs_to_many :limited_developers, :class_name => "Developer", :limit => 1
|
||||
has_and_belongs_to_many :developers_named_david, :class_name => "Developer", :conditions => "name = 'David'", :uniq => true
|
||||
has_and_belongs_to_many :developers_named_david_with_hash_conditions, :class_name => "Developer", :conditions => { :name => 'David' }, :uniq => true
|
||||
has_and_belongs_to_many :salaried_developers, :class_name => "Developer", :conditions => "salary > 0"
|
||||
has_and_belongs_to_many :developers_with_finder_sql, :class_name => "Developer", :finder_sql => 'SELECT t.*, j.* FROM developers_projects j, developers t WHERE t.id = j.developer_id AND j.project_id = #{id}'
|
||||
has_and_belongs_to_many :developers_by_sql, :class_name => "Developer", :delete_sql => "DELETE FROM developers_projects WHERE project_id = \#{id} AND developer_id = \#{record.id}"
|
||||
|
|
|
@ -9,6 +9,11 @@ class Topic < ActiveRecord::Base
|
|||
Topic.find(parent_id)
|
||||
end
|
||||
|
||||
# trivial method for testing Array#to_xml with :methods
|
||||
def topic_id
|
||||
id
|
||||
end
|
||||
|
||||
protected
|
||||
def default_written_on
|
||||
self.written_on = Time.now unless attribute_present?("written_on")
|
||||
|
@ -17,4 +22,4 @@ class Topic < ActiveRecord::Base
|
|||
def destroy_children
|
||||
self.class.delete_all "parent_id = #{id}"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,20 +3,20 @@ first:
|
|||
title: The First Topic
|
||||
author_name: David
|
||||
author_email_address: david@loudthinking.com
|
||||
written_on: 2003-07-16t15:28:00.00+01:00
|
||||
written_on: 2003-07-16t15:28:11.2233+01:00
|
||||
last_read: 2004-04-15
|
||||
bonus_time: 2005-01-30t15:28:00.00+01:00
|
||||
content: Have a nice day
|
||||
approved: false
|
||||
replies_count: 0
|
||||
replies_count: 1
|
||||
|
||||
second:
|
||||
id: 2
|
||||
title: The Second Topic's of the day
|
||||
author_name: Mary
|
||||
written_on: 2003-07-15t15:28:00.00+01:00
|
||||
written_on: 2003-07-15t15:28:00.0099+01:00
|
||||
content: Have a nice day
|
||||
approved: true
|
||||
replies_count: 2
|
||||
replies_count: 0
|
||||
parent_id: 1
|
||||
type: Reply
|
||||
|
|
56
vendor/rails/activerecord/test/fixtures_test.rb
vendored
56
vendor/rails/activerecord/test/fixtures_test.rb
vendored
|
@ -5,6 +5,7 @@ require 'fixtures/company'
|
|||
require 'fixtures/task'
|
||||
require 'fixtures/reply'
|
||||
require 'fixtures/joke'
|
||||
require 'fixtures/course'
|
||||
require 'fixtures/category'
|
||||
|
||||
class FixturesTest < Test::Unit::TestCase
|
||||
|
@ -334,6 +335,16 @@ class SetTableNameFixturesTest < Test::Unit::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
class CustomConnectionFixturesTest < Test::Unit::TestCase
|
||||
set_fixture_class :courses => Course
|
||||
fixtures :courses
|
||||
|
||||
def test_connection
|
||||
assert_kind_of Course, courses(:ruby)
|
||||
assert_equal Course.connection, courses(:ruby).connection
|
||||
end
|
||||
end
|
||||
|
||||
class InvalidTableNameFixturesTest < Test::Unit::TestCase
|
||||
fixtures :funny_jokes
|
||||
|
||||
|
@ -343,3 +354,48 @@ class InvalidTableNameFixturesTest < Test::Unit::TestCase
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
class CheckEscapedYamlFixturesTest < Test::Unit::TestCase
|
||||
set_fixture_class :funny_jokes => 'Joke'
|
||||
fixtures :funny_jokes
|
||||
|
||||
def test_proper_escaped_fixture
|
||||
assert_equal "The \\n Aristocrats\nAte the candy\n", funny_jokes(:another_joke).name
|
||||
end
|
||||
end
|
||||
|
||||
class DevelopersProject; end;
|
||||
|
||||
class ManyToManyFixturesWithClassDefined < Test::Unit::TestCase
|
||||
fixtures :developers_projects
|
||||
|
||||
def test_this_should_run_cleanly
|
||||
assert true
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class FixturesBrokenRollbackTest < Test::Unit::TestCase
|
||||
def blank_setup; end
|
||||
alias_method :ar_setup_with_fixtures, :setup_with_fixtures
|
||||
alias_method :setup_with_fixtures, :blank_setup
|
||||
alias_method :setup, :blank_setup
|
||||
|
||||
def blank_teardown; end
|
||||
alias_method :ar_teardown_with_fixtures, :teardown_with_fixtures
|
||||
alias_method :teardown_with_fixtures, :blank_teardown
|
||||
alias_method :teardown, :blank_teardown
|
||||
|
||||
def test_no_rollback_in_teardown_unless_transaction_active
|
||||
assert_equal 0, Thread.current['open_transactions']
|
||||
assert_raise(RuntimeError) { ar_setup_with_fixtures }
|
||||
assert_equal 0, Thread.current['open_transactions']
|
||||
assert_nothing_raised { ar_teardown_with_fixtures }
|
||||
assert_equal 0, Thread.current['open_transactions']
|
||||
end
|
||||
|
||||
private
|
||||
def load_fixtures
|
||||
raise 'argh'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4,17 +4,17 @@ require 'fixtures/project'
|
|||
require 'fixtures/subscriber'
|
||||
|
||||
class InheritanceTest < Test::Unit::TestCase
|
||||
fixtures :companies, :projects, :subscribers
|
||||
fixtures :companies, :projects, :subscribers, :accounts
|
||||
|
||||
def test_a_bad_type_column
|
||||
#SQLServer need to turn Identity Insert On before manually inserting into the Identity column
|
||||
if current_adapter?(:SQLServerAdapter) || current_adapter?(:SybaseAdapter)
|
||||
if current_adapter?(:SQLServerAdapter, :SybaseAdapter)
|
||||
Company.connection.execute "SET IDENTITY_INSERT companies ON"
|
||||
end
|
||||
Company.connection.insert "INSERT INTO companies (id, #{QUOTED_TYPE}, name) VALUES(100, 'bad_class!', 'Not happening')"
|
||||
|
||||
#We then need to turn it back Off before continuing.
|
||||
if current_adapter?(:SQLServerAdapter) || current_adapter?(:SybaseAdapter)
|
||||
if current_adapter?(:SQLServerAdapter, :SybaseAdapter)
|
||||
Company.connection.execute "SET IDENTITY_INSERT companies OFF"
|
||||
end
|
||||
assert_raises(ActiveRecord::SubclassNotFound) { Company.find(100) }
|
||||
|
@ -30,6 +30,7 @@ class InheritanceTest < Test::Unit::TestCase
|
|||
def test_alt_inheritance_find
|
||||
switch_to_alt_inheritance_column
|
||||
test_inheritance_find
|
||||
switch_to_default_inheritance_column
|
||||
end
|
||||
|
||||
def test_inheritance_find_all
|
||||
|
@ -41,6 +42,7 @@ class InheritanceTest < Test::Unit::TestCase
|
|||
def test_alt_inheritance_find_all
|
||||
switch_to_alt_inheritance_column
|
||||
test_inheritance_find_all
|
||||
switch_to_default_inheritance_column
|
||||
end
|
||||
|
||||
def test_inheritance_save
|
||||
|
@ -55,10 +57,11 @@ class InheritanceTest < Test::Unit::TestCase
|
|||
def test_alt_inheritance_save
|
||||
switch_to_alt_inheritance_column
|
||||
test_inheritance_save
|
||||
switch_to_default_inheritance_column
|
||||
end
|
||||
|
||||
def test_inheritance_condition
|
||||
assert_equal 8, Company.count
|
||||
assert_equal 9, Company.count
|
||||
assert_equal 2, Firm.count
|
||||
assert_equal 3, Client.count
|
||||
end
|
||||
|
@ -66,6 +69,7 @@ class InheritanceTest < Test::Unit::TestCase
|
|||
def test_alt_inheritance_condition
|
||||
switch_to_alt_inheritance_column
|
||||
test_inheritance_condition
|
||||
switch_to_default_inheritance_column
|
||||
end
|
||||
|
||||
def test_finding_incorrect_type_data
|
||||
|
@ -76,6 +80,7 @@ class InheritanceTest < Test::Unit::TestCase
|
|||
def test_alt_finding_incorrect_type_data
|
||||
switch_to_alt_inheritance_column
|
||||
test_finding_incorrect_type_data
|
||||
switch_to_default_inheritance_column
|
||||
end
|
||||
|
||||
def test_update_all_within_inheritance
|
||||
|
@ -87,6 +92,7 @@ class InheritanceTest < Test::Unit::TestCase
|
|||
def test_alt_update_all_within_inheritance
|
||||
switch_to_alt_inheritance_column
|
||||
test_update_all_within_inheritance
|
||||
switch_to_default_inheritance_column
|
||||
end
|
||||
|
||||
def test_destroy_all_within_inheritance
|
||||
|
@ -98,6 +104,7 @@ class InheritanceTest < Test::Unit::TestCase
|
|||
def test_alt_destroy_all_within_inheritance
|
||||
switch_to_alt_inheritance_column
|
||||
test_destroy_all_within_inheritance
|
||||
switch_to_default_inheritance_column
|
||||
end
|
||||
|
||||
def test_find_first_within_inheritance
|
||||
|
@ -109,6 +116,7 @@ class InheritanceTest < Test::Unit::TestCase
|
|||
def test_alt_find_first_within_inheritance
|
||||
switch_to_alt_inheritance_column
|
||||
test_find_first_within_inheritance
|
||||
switch_to_default_inheritance_column
|
||||
end
|
||||
|
||||
def test_complex_inheritance
|
||||
|
@ -124,6 +132,19 @@ class InheritanceTest < Test::Unit::TestCase
|
|||
def test_alt_complex_inheritance
|
||||
switch_to_alt_inheritance_column
|
||||
test_complex_inheritance
|
||||
switch_to_default_inheritance_column
|
||||
end
|
||||
|
||||
def test_eager_load_belongs_to_something_inherited
|
||||
account = Account.find(1, :include => :firm)
|
||||
assert_not_nil account.instance_variable_get("@firm"), "nil proves eager load failed"
|
||||
end
|
||||
|
||||
def test_alt_eager_loading
|
||||
switch_to_alt_inheritance_column
|
||||
test_eager_load_belongs_to_something_inherited
|
||||
switch_to_default_inheritance_column
|
||||
ActiveRecord::Base.logger.debug "cocksucker"
|
||||
end
|
||||
|
||||
def test_inheritance_without_mapping
|
||||
|
@ -138,7 +159,47 @@ class InheritanceTest < Test::Unit::TestCase
|
|||
c['type'] = nil
|
||||
c.save
|
||||
end
|
||||
|
||||
def Company.inheritance_column() "ruby_type" end
|
||||
[ Company, Firm, Client].each { |klass| klass.reset_column_information }
|
||||
Company.set_inheritance_column('ruby_type')
|
||||
end
|
||||
def switch_to_default_inheritance_column
|
||||
[ Company, Firm, Client].each { |klass| klass.reset_column_information }
|
||||
Company.set_inheritance_column('type')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class InheritanceComputeTypeTest < Test::Unit::TestCase
|
||||
fixtures :companies
|
||||
|
||||
def setup
|
||||
Dependencies.log_activity = true
|
||||
end
|
||||
|
||||
def teardown
|
||||
Dependencies.log_activity = false
|
||||
self.class.const_remove :FirmOnTheFly rescue nil
|
||||
Firm.const_remove :FirmOnTheFly rescue nil
|
||||
end
|
||||
|
||||
def test_instantiation_doesnt_try_to_require_corresponding_file
|
||||
foo = Firm.find(:first).clone
|
||||
foo.ruby_type = foo.type = 'FirmOnTheFly'
|
||||
foo.save!
|
||||
|
||||
# Should fail without FirmOnTheFly in the type condition.
|
||||
assert_raise(ActiveRecord::RecordNotFound) { Firm.find(foo.id) }
|
||||
|
||||
# Nest FirmOnTheFly in the test case where Dependencies won't see it.
|
||||
self.class.const_set :FirmOnTheFly, Class.new(Firm)
|
||||
assert_raise(ActiveRecord::SubclassNotFound) { Firm.find(foo.id) }
|
||||
|
||||
# Nest FirmOnTheFly in Firm where Dependencies will see it.
|
||||
# This is analogous to nesting models in a migration.
|
||||
Firm.const_set :FirmOnTheFly, Class.new(Firm)
|
||||
|
||||
# And instantiate will find the existing constant rather than trying
|
||||
# to require firm_on_the_fly.
|
||||
assert_nothing_raised { assert_kind_of Firm::FirmOnTheFly, Firm.find(foo.id) }
|
||||
end
|
||||
end
|
||||
|
|
59
vendor/rails/activerecord/test/lifecycle_test.rb
vendored
59
vendor/rails/activerecord/test/lifecycle_test.rb
vendored
|
@ -46,13 +46,22 @@ end
|
|||
|
||||
class MultiObserver < ActiveRecord::Observer
|
||||
attr_reader :record
|
||||
|
||||
|
||||
def self.observed_class() [ Topic, Developer ] end
|
||||
|
||||
cattr_reader :last_inherited
|
||||
@@last_inherited = nil
|
||||
|
||||
def observed_class_inherited_with_testing(subclass)
|
||||
observed_class_inherited_without_testing(subclass)
|
||||
@@last_inherited = subclass
|
||||
end
|
||||
|
||||
alias_method_chain :observed_class_inherited, :testing
|
||||
|
||||
def after_find(record)
|
||||
@record = record
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class LifecycleTest < Test::Unit::TestCase
|
||||
|
@ -63,54 +72,66 @@ class LifecycleTest < Test::Unit::TestCase
|
|||
Topic.find(1).destroy
|
||||
assert_equal 0, Topic.count
|
||||
end
|
||||
|
||||
|
||||
def test_after_save
|
||||
ActiveRecord::Base.observers = :topic_manual_observer
|
||||
ActiveRecord::Base.instantiate_observers
|
||||
|
||||
topic = Topic.find(1)
|
||||
topic.title = "hello"
|
||||
topic.save
|
||||
|
||||
|
||||
assert TopicManualObserver.instance.has_been_notified?
|
||||
assert_equal :after_save, TopicManualObserver.instance.callbacks.last["callback_method"]
|
||||
end
|
||||
|
||||
|
||||
def test_observer_update_on_save
|
||||
ActiveRecord::Base.observers = TopicManualObserver
|
||||
ActiveRecord::Base.instantiate_observers
|
||||
|
||||
topic = Topic.find(1)
|
||||
topic = Topic.find(1)
|
||||
assert TopicManualObserver.instance.has_been_notified?
|
||||
assert_equal :after_find, TopicManualObserver.instance.callbacks.first["callback_method"]
|
||||
end
|
||||
|
||||
|
||||
def test_auto_observer
|
||||
topic_observer = TopicaObserver.instance
|
||||
|
||||
topic = Topic.find(1)
|
||||
assert_equal topic_observer.topic.title, topic.title
|
||||
topic = Topic.find(1)
|
||||
assert_equal topic.title, topic_observer.topic.title
|
||||
end
|
||||
|
||||
def test_infered_auto_observer
|
||||
|
||||
def test_inferred_auto_observer
|
||||
topic_observer = TopicObserver.instance
|
||||
|
||||
topic = Topic.find(1)
|
||||
assert_equal topic_observer.topic.title, topic.title
|
||||
topic = Topic.find(1)
|
||||
assert_equal topic.title, topic_observer.topic.title
|
||||
end
|
||||
|
||||
|
||||
def test_observing_two_classes
|
||||
multi_observer = MultiObserver.instance
|
||||
|
||||
topic = Topic.find(1)
|
||||
assert_equal multi_observer.record.title, topic.title
|
||||
assert_equal topic.title, multi_observer.record.title
|
||||
|
||||
developer = Developer.find(1)
|
||||
assert_equal multi_observer.record.name, developer.name
|
||||
developer = Developer.find(1)
|
||||
assert_equal developer.name, multi_observer.record.name
|
||||
end
|
||||
|
||||
|
||||
def test_observing_subclasses
|
||||
multi_observer = MultiObserver.instance
|
||||
|
||||
developer = SpecialDeveloper.find(1)
|
||||
assert_equal multi_observer.record.name, developer.name
|
||||
assert_equal developer.name, multi_observer.record.name
|
||||
|
||||
klass = Class.new(Developer)
|
||||
assert_equal klass, multi_observer.last_inherited
|
||||
|
||||
developer = klass.find(1)
|
||||
assert_equal developer.name, multi_observer.record.name
|
||||
end
|
||||
|
||||
def test_invalid_observer
|
||||
assert_raise(ArgumentError) { Topic.observers = Object.new; Topic.instantiate_observers }
|
||||
end
|
||||
end
|
||||
|
|
196
vendor/rails/activerecord/test/locking_test.rb
vendored
196
vendor/rails/activerecord/test/locking_test.rb
vendored
|
@ -2,45 +2,189 @@ require 'abstract_unit'
|
|||
require 'fixtures/person'
|
||||
require 'fixtures/legacy_thing'
|
||||
|
||||
class LockingTest < Test::Unit::TestCase
|
||||
class LockWithoutDefault < ActiveRecord::Base; end
|
||||
|
||||
class LockWithCustomColumnWithoutDefault < ActiveRecord::Base
|
||||
set_table_name :lock_without_defaults_cust
|
||||
set_locking_column :custom_lock_version
|
||||
end
|
||||
|
||||
class OptimisticLockingTest < Test::Unit::TestCase
|
||||
fixtures :people, :legacy_things
|
||||
|
||||
def test_lock_existing
|
||||
p1 = Person.find(1)
|
||||
p2 = Person.find(1)
|
||||
|
||||
p1.first_name = "Michael"
|
||||
p1.save
|
||||
|
||||
assert_raises(ActiveRecord::StaleObjectError) {
|
||||
p2.first_name = "should fail"
|
||||
p2.save
|
||||
}
|
||||
assert_equal 0, p1.lock_version
|
||||
assert_equal 0, p2.lock_version
|
||||
|
||||
p1.save!
|
||||
assert_equal 1, p1.lock_version
|
||||
assert_equal 0, p2.lock_version
|
||||
|
||||
assert_raises(ActiveRecord::StaleObjectError) { p2.save! }
|
||||
end
|
||||
|
||||
def test_lock_new
|
||||
p1 = Person.create({ "first_name"=>"anika"})
|
||||
p1 = Person.new(:first_name => 'anika')
|
||||
assert_equal 0, p1.lock_version
|
||||
|
||||
p1.save!
|
||||
p2 = Person.find(p1.id)
|
||||
assert_equal p1.id, p2.id
|
||||
p1.first_name = "Anika"
|
||||
p1.save
|
||||
|
||||
assert_raises(ActiveRecord::StaleObjectError) {
|
||||
p2.first_name = "should fail"
|
||||
p2.save
|
||||
}
|
||||
assert_equal 0, p1.lock_version
|
||||
assert_equal 0, p2.lock_version
|
||||
|
||||
p1.save!
|
||||
assert_equal 1, p1.lock_version
|
||||
assert_equal 0, p2.lock_version
|
||||
|
||||
assert_raises(ActiveRecord::StaleObjectError) { p2.save! }
|
||||
end
|
||||
|
||||
|
||||
def test_lock_column_name_existing
|
||||
t1 = LegacyThing.find(1)
|
||||
t2 = LegacyThing.find(1)
|
||||
t1.tps_report_number = 400
|
||||
t1.save
|
||||
assert_equal 0, t1.version
|
||||
assert_equal 0, t2.version
|
||||
|
||||
assert_raises(ActiveRecord::StaleObjectError) {
|
||||
t2.tps_report_number = 300
|
||||
t2.save
|
||||
}
|
||||
end
|
||||
t1.save!
|
||||
assert_equal 1, t1.version
|
||||
assert_equal 0, t2.version
|
||||
|
||||
assert_raises(ActiveRecord::StaleObjectError) { t2.save! }
|
||||
end
|
||||
|
||||
def test_lock_column_is_mass_assignable
|
||||
p1 = Person.create(:first_name => 'bianca')
|
||||
assert_equal 0, p1.lock_version
|
||||
assert_equal p1.lock_version, Person.new(p1.attributes).lock_version
|
||||
|
||||
p1.save!
|
||||
assert_equal 1, p1.lock_version
|
||||
assert_equal p1.lock_version, Person.new(p1.attributes).lock_version
|
||||
end
|
||||
|
||||
def test_lock_without_default_sets_version_to_zero
|
||||
t1 = LockWithoutDefault.new
|
||||
assert_equal 0, t1.lock_version
|
||||
end
|
||||
|
||||
def test_lock_with_custom_column_without_default_sets_version_to_zero
|
||||
t1 = LockWithCustomColumnWithoutDefault.new
|
||||
assert_equal 0, t1.custom_lock_version
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# TODO: test against the generated SQL since testing locking behavior itself
|
||||
# is so cumbersome. Will deadlock Ruby threads if the underlying db.execute
|
||||
# blocks, so separate script called by Kernel#system is needed.
|
||||
# (See exec vs. async_exec in the PostgreSQL adapter.)
|
||||
|
||||
# TODO: The SQL Server and Sybase adapters currently have no support for pessimistic locking
|
||||
|
||||
unless current_adapter?(:SQLServerAdapter, :SybaseAdapter)
|
||||
class PessimisticLockingTest < Test::Unit::TestCase
|
||||
self.use_transactional_fixtures = false
|
||||
fixtures :people, :readers
|
||||
|
||||
def setup
|
||||
# Avoid introspection queries during tests.
|
||||
Person.columns; Reader.columns
|
||||
|
||||
@allow_concurrency = ActiveRecord::Base.allow_concurrency
|
||||
ActiveRecord::Base.allow_concurrency = true
|
||||
end
|
||||
|
||||
def teardown
|
||||
ActiveRecord::Base.allow_concurrency = @allow_concurrency
|
||||
end
|
||||
|
||||
# Test typical find.
|
||||
def test_sane_find_with_lock
|
||||
assert_nothing_raised do
|
||||
Person.transaction do
|
||||
Person.find 1, :lock => true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Test scoped lock.
|
||||
def test_sane_find_with_scoped_lock
|
||||
assert_nothing_raised do
|
||||
Person.transaction do
|
||||
Person.with_scope(:find => { :lock => true }) do
|
||||
Person.find 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# PostgreSQL protests SELECT ... FOR UPDATE on an outer join.
|
||||
unless current_adapter?(:PostgreSQLAdapter)
|
||||
# Test locked eager find.
|
||||
def test_eager_find_with_lock
|
||||
assert_nothing_raised do
|
||||
Person.transaction do
|
||||
Person.find 1, :include => :readers, :lock => true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Locking a record reloads it.
|
||||
def test_sane_lock_method
|
||||
assert_nothing_raised do
|
||||
Person.transaction do
|
||||
person = Person.find 1
|
||||
old, person.first_name = person.first_name, 'fooman'
|
||||
person.lock!
|
||||
assert_equal old, person.first_name
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if current_adapter?(:PostgreSQLAdapter, :OracleAdapter)
|
||||
def test_no_locks_no_wait
|
||||
first, second = duel { Person.find 1 }
|
||||
assert first.end > second.end
|
||||
end
|
||||
|
||||
def test_second_lock_waits
|
||||
assert [0.2, 1, 5].any? { |zzz|
|
||||
first, second = duel(zzz) { Person.find 1, :lock => true }
|
||||
second.end > first.end
|
||||
}
|
||||
end
|
||||
|
||||
protected
|
||||
def duel(zzz = 5)
|
||||
t0, t1, t2, t3 = nil, nil, nil, nil
|
||||
|
||||
a = Thread.new do
|
||||
t0 = Time.now
|
||||
Person.transaction do
|
||||
yield
|
||||
sleep zzz # block thread 2 for zzz seconds
|
||||
end
|
||||
t1 = Time.now
|
||||
end
|
||||
|
||||
b = Thread.new do
|
||||
sleep zzz / 2.0 # ensure thread 1 tx starts first
|
||||
t2 = Time.now
|
||||
Person.transaction { yield }
|
||||
t3 = Time.now
|
||||
end
|
||||
|
||||
a.join
|
||||
b.join
|
||||
|
||||
assert t1 > t0 + zzz
|
||||
assert t2 > t0
|
||||
assert t3 > t2
|
||||
[t0.to_f..t1.to_f, t2.to_f..t3.to_f]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -57,7 +57,7 @@ class MethodScopingTest < Test::Unit::TestCase
|
|||
|
||||
Developer.with_scope(:find => { :conditions => 'salary = 100000' }) do
|
||||
assert_equal 8, Developer.count
|
||||
assert_equal 1, Developer.count("name LIKE 'fixture_1%'")
|
||||
assert_equal 1, Developer.count(:conditions => "name LIKE 'fixture_1%'")
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -74,7 +74,7 @@ class MethodScopingTest < Test::Unit::TestCase
|
|||
def test_scoped_count_include
|
||||
# with the include, will retrieve only developers for the given project
|
||||
Developer.with_scope(:find => { :include => :projects }) do
|
||||
assert_equal 1, Developer.count('projects.id = 2')
|
||||
assert_equal 1, Developer.count(:conditions => 'projects.id = 2')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
497
vendor/rails/activerecord/test/migration_test.rb
vendored
497
vendor/rails/activerecord/test/migration_test.rb
vendored
|
@ -1,9 +1,15 @@
|
|||
require 'abstract_unit'
|
||||
require 'bigdecimal/util'
|
||||
|
||||
require 'fixtures/person'
|
||||
require 'fixtures/topic'
|
||||
require File.dirname(__FILE__) + '/fixtures/migrations/1_people_have_last_names'
|
||||
require File.dirname(__FILE__) + '/fixtures/migrations/2_we_need_reminders'
|
||||
require File.dirname(__FILE__) + '/fixtures/migrations_with_decimal/1_give_me_big_numbers'
|
||||
|
||||
if ActiveRecord::Base.connection.supports_migrations?
|
||||
class BigNumber < ActiveRecord::Base; end
|
||||
|
||||
if ActiveRecord::Base.connection.supports_migrations?
|
||||
class Reminder < ActiveRecord::Base; end
|
||||
|
||||
class ActiveRecord::Migration
|
||||
|
@ -28,37 +34,46 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
ActiveRecord::Base.connection.initialize_schema_information
|
||||
ActiveRecord::Base.connection.update "UPDATE #{ActiveRecord::Migrator.schema_info_table_name} SET version = 0"
|
||||
|
||||
Reminder.connection.drop_table("reminders") rescue nil
|
||||
Reminder.connection.drop_table("people_reminders") rescue nil
|
||||
Reminder.connection.drop_table("prefix_reminders_suffix") rescue nil
|
||||
%w(reminders people_reminders prefix_reminders_suffix).each do |table|
|
||||
Reminder.connection.drop_table(table) rescue nil
|
||||
end
|
||||
Reminder.reset_column_information
|
||||
|
||||
Person.connection.remove_column("people", "last_name") rescue nil
|
||||
Person.connection.remove_column("people", "key") rescue nil
|
||||
Person.connection.remove_column("people", "bio") rescue nil
|
||||
Person.connection.remove_column("people", "age") rescue nil
|
||||
Person.connection.remove_column("people", "height") rescue nil
|
||||
Person.connection.remove_column("people", "birthday") rescue nil
|
||||
Person.connection.remove_column("people", "favorite_day") rescue nil
|
||||
Person.connection.remove_column("people", "male") rescue nil
|
||||
Person.connection.remove_column("people", "administrator") rescue nil
|
||||
%w(last_name key bio age height wealth birthday favorite_day
|
||||
male administrator).each do |column|
|
||||
Person.connection.remove_column('people', column) rescue nil
|
||||
end
|
||||
Person.connection.remove_column("people", "first_name") rescue nil
|
||||
Person.connection.remove_column("people", "middle_name") rescue nil
|
||||
Person.connection.add_column("people", "first_name", :string, :limit => 40)
|
||||
Person.reset_column_information
|
||||
end
|
||||
|
||||
def test_add_index
|
||||
Person.connection.add_column "people", "last_name", :string
|
||||
# Limit size of last_name and key columns to support Firebird index limitations
|
||||
Person.connection.add_column "people", "last_name", :string, :limit => 100
|
||||
Person.connection.add_column "people", "key", :string, :limit => 100
|
||||
Person.connection.add_column "people", "administrator", :boolean
|
||||
Person.connection.add_column "people", "key", :string
|
||||
|
||||
|
||||
assert_nothing_raised { Person.connection.add_index("people", "last_name") }
|
||||
assert_nothing_raised { Person.connection.remove_index("people", "last_name") }
|
||||
|
||||
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
|
||||
assert_nothing_raised { Person.connection.remove_index("people", "last_name") }
|
||||
|
||||
# Orcl nds shrt indx nms. Sybs 2.
|
||||
unless current_adapter?(:OracleAdapter, :SybaseAdapter)
|
||||
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
|
||||
assert_nothing_raised { Person.connection.remove_index("people", :column => ["last_name", "first_name"]) }
|
||||
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
|
||||
assert_nothing_raised { Person.connection.remove_index("people", :name => "index_people_on_last_name_and_first_name") }
|
||||
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
|
||||
assert_nothing_raised { Person.connection.remove_index("people", "last_name_and_first_name") }
|
||||
assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
|
||||
assert_nothing_raised { Person.connection.remove_index("people", ["last_name", "first_name"]) }
|
||||
end
|
||||
|
||||
# quoting
|
||||
assert_nothing_raised { Person.connection.add_index("people", ["key"], :name => "key", :unique => true) }
|
||||
assert_nothing_raised { Person.connection.remove_index("people", :name => "key") }
|
||||
# Note: changed index name from "key" to "key_idx" since "key" is a Firebird reserved word
|
||||
assert_nothing_raised { Person.connection.add_index("people", ["key"], :name => "key_idx", :unique => true) }
|
||||
assert_nothing_raised { Person.connection.remove_index("people", :name => "key_idx", :unique => true) }
|
||||
|
||||
# Sybase adapter does not support indexes on :boolean columns
|
||||
unless current_adapter?(:SybaseAdapter)
|
||||
|
@ -79,8 +94,10 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
end
|
||||
|
||||
def test_create_table_with_not_null_column
|
||||
Person.connection.create_table :testings do |t|
|
||||
t.column :foo, :string, :null => false
|
||||
assert_nothing_raised do
|
||||
Person.connection.create_table :testings do |t|
|
||||
t.column :foo, :string, :null => false
|
||||
end
|
||||
end
|
||||
|
||||
assert_raises(ActiveRecord::StatementInvalid) do
|
||||
|
@ -105,30 +122,61 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
four = columns.detect { |c| c.name == "four" }
|
||||
|
||||
assert_equal "hello", one.default
|
||||
if current_adapter?(:OracleAdapter)
|
||||
# Oracle doesn't support native booleans
|
||||
assert_equal true, two.default == 1
|
||||
assert_equal false, three.default != 0
|
||||
else
|
||||
assert_equal true, two.default
|
||||
assert_equal false, three.default
|
||||
end
|
||||
assert_equal true, two.default
|
||||
assert_equal false, three.default
|
||||
assert_equal 1, four.default
|
||||
|
||||
ensure
|
||||
Person.connection.drop_table :testings rescue nil
|
||||
end
|
||||
|
||||
|
||||
def test_create_table_with_limits
|
||||
assert_nothing_raised do
|
||||
Person.connection.create_table :testings do |t|
|
||||
t.column :foo, :string, :limit => 255
|
||||
|
||||
t.column :default_int, :integer
|
||||
|
||||
t.column :one_int, :integer, :limit => 1
|
||||
t.column :four_int, :integer, :limit => 4
|
||||
t.column :eight_int, :integer, :limit => 8
|
||||
end
|
||||
end
|
||||
|
||||
columns = Person.connection.columns(:testings)
|
||||
foo = columns.detect { |c| c.name == "foo" }
|
||||
assert_equal 255, foo.limit
|
||||
|
||||
default = columns.detect { |c| c.name == "default_int" }
|
||||
one = columns.detect { |c| c.name == "one_int" }
|
||||
four = columns.detect { |c| c.name == "four_int" }
|
||||
eight = columns.detect { |c| c.name == "eight_int" }
|
||||
|
||||
if current_adapter?(:PostgreSQLAdapter)
|
||||
assert_equal 'integer', default.sql_type
|
||||
assert_equal 'smallint', one.sql_type
|
||||
assert_equal 'integer', four.sql_type
|
||||
assert_equal 'bigint', eight.sql_type
|
||||
elsif current_adapter?(:OracleAdapter)
|
||||
assert_equal 'NUMBER(38)', default.sql_type
|
||||
assert_equal 'NUMBER(1)', one.sql_type
|
||||
assert_equal 'NUMBER(4)', four.sql_type
|
||||
assert_equal 'NUMBER(8)', eight.sql_type
|
||||
end
|
||||
ensure
|
||||
Person.connection.drop_table :testings rescue nil
|
||||
end
|
||||
|
||||
# SQL Server and Sybase will not allow you to add a NOT NULL column
|
||||
# to a table without specifying a default value, so the
|
||||
# following test must be skipped
|
||||
unless current_adapter?(:SQLServerAdapter) || current_adapter?(:SybaseAdapter)
|
||||
# following test must be skipped
|
||||
unless current_adapter?(:SQLServerAdapter, :SybaseAdapter)
|
||||
def test_add_column_not_null_without_default
|
||||
Person.connection.create_table :testings do |t|
|
||||
t.column :foo, :string
|
||||
end
|
||||
Person.connection.add_column :testings, :bar, :string, :null => false
|
||||
|
||||
|
||||
assert_raises(ActiveRecord::StatementInvalid) do
|
||||
Person.connection.execute "insert into testings (foo, bar) values ('hello', NULL)"
|
||||
end
|
||||
|
@ -136,52 +184,113 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
Person.connection.drop_table :testings rescue nil
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def test_add_column_not_null_with_default
|
||||
Person.connection.create_table :testings do |t|
|
||||
t.column :foo, :string
|
||||
end
|
||||
Person.connection.add_column :testings, :bar, :string, :null => false, :default => "default"
|
||||
|
||||
con = Person.connection
|
||||
Person.connection.enable_identity_insert("testings", true) if current_adapter?(:SybaseAdapter)
|
||||
Person.connection.execute "insert into testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}) values (1, 'hello')"
|
||||
Person.connection.enable_identity_insert("testings", false) if current_adapter?(:SybaseAdapter)
|
||||
assert_nothing_raised {Person.connection.add_column :testings, :bar, :string, :null => false, :default => "default" }
|
||||
|
||||
assert_raises(ActiveRecord::StatementInvalid) do
|
||||
Person.connection.execute "insert into testings (foo, bar) values ('hello', NULL)"
|
||||
Person.connection.execute "insert into testings (#{con.quote_column_name('id')}, #{con.quote_column_name('foo')}, #{con.quote_column_name('bar')}) values (2, 'hello', NULL)"
|
||||
end
|
||||
ensure
|
||||
Person.connection.drop_table :testings rescue nil
|
||||
end
|
||||
|
||||
|
||||
# We specifically do a manual INSERT here, and then test only the SELECT
|
||||
# functionality. This allows us to more easily catch INSERT being broken,
|
||||
# but SELECT actually working fine.
|
||||
def test_native_decimal_insert_manual_vs_automatic
|
||||
# SQLite3 always uses float in violation of SQL
|
||||
# 16 decimal places
|
||||
correct_value = (current_adapter?(:SQLiteAdapter) ? '0.123456789012346E20' : '0012345678901234567890.0123456789').to_d
|
||||
|
||||
Person.delete_all
|
||||
Person.connection.add_column "people", "wealth", :decimal, :precision => '30', :scale => '10'
|
||||
Person.reset_column_information
|
||||
|
||||
# Do a manual insertion
|
||||
if current_adapter?(:OracleAdapter)
|
||||
Person.connection.execute "insert into people (id, wealth) values (people_seq.nextval, 12345678901234567890.0123456789)"
|
||||
else
|
||||
Person.connection.execute "insert into people (wealth) values (12345678901234567890.0123456789)"
|
||||
end
|
||||
|
||||
# SELECT
|
||||
row = Person.find(:first)
|
||||
assert_kind_of BigDecimal, row.wealth
|
||||
|
||||
# If this assert fails, that means the SELECT is broken!
|
||||
assert_equal correct_value, row.wealth
|
||||
|
||||
# Reset to old state
|
||||
Person.delete_all
|
||||
|
||||
# Now use the Rails insertion
|
||||
assert_nothing_raised { Person.create :wealth => BigDecimal.new("12345678901234567890.0123456789") }
|
||||
|
||||
# SELECT
|
||||
row = Person.find(:first)
|
||||
assert_kind_of BigDecimal, row.wealth
|
||||
|
||||
# If these asserts fail, that means the INSERT (create function, or cast to SQL) is broken!
|
||||
assert_equal correct_value, row.wealth
|
||||
|
||||
# Reset to old state
|
||||
Person.connection.del_column "people", "wealth" rescue nil
|
||||
Person.reset_column_information
|
||||
end
|
||||
|
||||
def test_native_types
|
||||
Person.delete_all
|
||||
Person.connection.add_column "people", "last_name", :string
|
||||
Person.connection.add_column "people", "bio", :text
|
||||
Person.connection.add_column "people", "age", :integer
|
||||
Person.connection.add_column "people", "height", :float
|
||||
Person.connection.add_column "people", "wealth", :decimal, :precision => '30', :scale => '10'
|
||||
Person.connection.add_column "people", "birthday", :datetime
|
||||
Person.connection.add_column "people", "favorite_day", :date
|
||||
Person.connection.add_column "people", "male", :boolean
|
||||
assert_nothing_raised { Person.create :first_name => 'bob', :last_name => 'bobsen', :bio => "I was born ....", :age => 18, :height => 1.78, :birthday => 18.years.ago, :favorite_day => 10.days.ago, :male => true }
|
||||
assert_nothing_raised { Person.create :first_name => 'bob', :last_name => 'bobsen', :bio => "I was born ....", :age => 18, :height => 1.78, :wealth => BigDecimal.new("12345678901234567890.0123456789"), :birthday => 18.years.ago, :favorite_day => 10.days.ago, :male => true }
|
||||
bob = Person.find(:first)
|
||||
|
||||
assert_equal bob.first_name, 'bob'
|
||||
assert_equal bob.last_name, 'bobsen'
|
||||
assert_equal bob.bio, "I was born ...."
|
||||
assert_equal bob.age, 18
|
||||
assert_equal bob.male?, true
|
||||
|
||||
|
||||
assert_equal 'bob', bob.first_name
|
||||
assert_equal 'bobsen', bob.last_name
|
||||
assert_equal "I was born ....", bob.bio
|
||||
assert_equal 18, bob.age
|
||||
|
||||
# Test for 30 significent digits (beyond the 16 of float), 10 of them
|
||||
# after the decimal place.
|
||||
if current_adapter?(:SQLiteAdapter)
|
||||
# SQLite3 uses float in violation of SQL. Test for 16 decimal places.
|
||||
assert_equal BigDecimal.new('0.123456789012346E20'), bob.wealth
|
||||
else
|
||||
assert_equal BigDecimal.new("0012345678901234567890.0123456789"), bob.wealth
|
||||
end
|
||||
|
||||
assert_equal true, bob.male?
|
||||
|
||||
assert_equal String, bob.first_name.class
|
||||
assert_equal String, bob.last_name.class
|
||||
assert_equal String, bob.bio.class
|
||||
assert_equal Fixnum, bob.age.class
|
||||
assert_equal Time, bob.birthday.class
|
||||
|
||||
if current_adapter?(:SQLServerAdapter) || current_adapter?(:OracleAdapter) || current_adapter?(:SybaseAdapter)
|
||||
# SQL Server, Sybase, and Oracle don't differentiate between date/time
|
||||
if current_adapter?(:SQLServerAdapter, :OracleAdapter, :SybaseAdapter)
|
||||
# Sybase, and Oracle don't differentiate between date/time
|
||||
assert_equal Time, bob.favorite_day.class
|
||||
else
|
||||
assert_equal Date, bob.favorite_day.class
|
||||
end
|
||||
|
||||
assert_equal TrueClass, bob.male?.class
|
||||
assert_kind_of BigDecimal, bob.wealth
|
||||
end
|
||||
|
||||
def test_add_remove_single_field_using_string_arguments
|
||||
|
@ -191,7 +300,7 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
|
||||
Person.reset_column_information
|
||||
assert Person.column_methods_hash.include?(:last_name)
|
||||
|
||||
|
||||
ActiveRecord::Migration.remove_column 'people', 'last_name'
|
||||
|
||||
Person.reset_column_information
|
||||
|
@ -211,27 +320,27 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
Person.reset_column_information
|
||||
assert !Person.column_methods_hash.include?(:last_name)
|
||||
end
|
||||
|
||||
|
||||
def test_add_rename
|
||||
Person.delete_all
|
||||
|
||||
|
||||
begin
|
||||
Person.connection.add_column "people", "girlfriend", :string
|
||||
Person.create :girlfriend => 'bobette'
|
||||
|
||||
Person.connection.add_column "people", "girlfriend", :string
|
||||
Person.create :girlfriend => 'bobette'
|
||||
|
||||
Person.connection.rename_column "people", "girlfriend", "exgirlfriend"
|
||||
|
||||
Person.reset_column_information
|
||||
|
||||
Person.reset_column_information
|
||||
bob = Person.find(:first)
|
||||
|
||||
|
||||
assert_equal "bobette", bob.exgirlfriend
|
||||
ensure
|
||||
Person.connection.remove_column("people", "girlfriend") rescue nil
|
||||
Person.connection.remove_column("people", "exgirlfriend") rescue nil
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
def test_rename_column_using_symbol_arguments
|
||||
begin
|
||||
Person.connection.rename_column :people, :first_name, :nick_name
|
||||
|
@ -242,7 +351,7 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
Person.connection.add_column("people","first_name", :string)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def test_rename_column
|
||||
begin
|
||||
Person.connection.rename_column "people", "first_name", "nick_name"
|
||||
|
@ -253,7 +362,7 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
Person.connection.add_column("people","first_name", :string)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def test_rename_table
|
||||
begin
|
||||
ActiveRecord::Base.connection.create_table :octopuses do |t|
|
||||
|
@ -261,14 +370,11 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
end
|
||||
ActiveRecord::Base.connection.rename_table :octopuses, :octopi
|
||||
|
||||
assert_nothing_raised do
|
||||
if current_adapter?(:OracleAdapter)
|
||||
# Oracle requires the explicit sequence value for the pk
|
||||
ActiveRecord::Base.connection.execute "INSERT INTO octopi (id, url) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')"
|
||||
else
|
||||
ActiveRecord::Base.connection.execute "INSERT INTO octopi (url) VALUES ('http://www.foreverflying.com/octopus-black7.jpg')"
|
||||
end
|
||||
end
|
||||
# Using explicit id in insert for compatibility across all databases
|
||||
con = ActiveRecord::Base.connection
|
||||
con.enable_identity_insert("octopi", true) if current_adapter?(:SybaseAdapter)
|
||||
assert_nothing_raised { con.execute "INSERT INTO octopi (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')" }
|
||||
con.enable_identity_insert("octopi", false) if current_adapter?(:SybaseAdapter)
|
||||
|
||||
assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', ActiveRecord::Base.connection.select_value("SELECT url FROM octopi WHERE id=1")
|
||||
|
||||
|
@ -278,40 +384,159 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
end
|
||||
end
|
||||
|
||||
def test_rename_table_with_an_index
|
||||
begin
|
||||
ActiveRecord::Base.connection.create_table :octopuses do |t|
|
||||
t.column :url, :string
|
||||
end
|
||||
ActiveRecord::Base.connection.add_index :octopuses, :url
|
||||
|
||||
ActiveRecord::Base.connection.rename_table :octopuses, :octopi
|
||||
|
||||
# Using explicit id in insert for compatibility across all databases
|
||||
con = ActiveRecord::Base.connection
|
||||
con.enable_identity_insert("octopi", true) if current_adapter?(:SybaseAdapter)
|
||||
assert_nothing_raised { con.execute "INSERT INTO octopi (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://www.foreverflying.com/octopus-black7.jpg')" }
|
||||
con.enable_identity_insert("octopi", false) if current_adapter?(:SybaseAdapter)
|
||||
|
||||
assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', ActiveRecord::Base.connection.select_value("SELECT url FROM octopi WHERE id=1")
|
||||
assert ActiveRecord::Base.connection.indexes(:octopi).first.columns.include?("url")
|
||||
ensure
|
||||
ActiveRecord::Base.connection.drop_table :octopuses rescue nil
|
||||
ActiveRecord::Base.connection.drop_table :octopi rescue nil
|
||||
end
|
||||
end
|
||||
|
||||
def test_change_column
|
||||
Person.connection.add_column 'people', 'age', :integer
|
||||
old_columns = Person.connection.columns(Person.table_name, "#{name} Columns")
|
||||
assert old_columns.find { |c| c.name == 'age' and c.type == :integer }
|
||||
|
||||
assert_nothing_raised { Person.connection.change_column "people", "age", :string }
|
||||
|
||||
|
||||
new_columns = Person.connection.columns(Person.table_name, "#{name} Columns")
|
||||
assert_nil new_columns.find { |c| c.name == 'age' and c.type == :integer }
|
||||
assert new_columns.find { |c| c.name == 'age' and c.type == :string }
|
||||
end
|
||||
|
||||
old_columns = Topic.connection.columns(Topic.table_name, "#{name} Columns")
|
||||
assert old_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true }
|
||||
assert_nothing_raised { Topic.connection.change_column :topics, :approved, :boolean, :default => false }
|
||||
new_columns = Topic.connection.columns(Topic.table_name, "#{name} Columns")
|
||||
assert_nil new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true }
|
||||
assert new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == false }
|
||||
assert_nothing_raised { Topic.connection.change_column :topics, :approved, :boolean, :default => true }
|
||||
end
|
||||
|
||||
def test_change_column_with_nil_default
|
||||
Person.connection.add_column "people", "contributor", :boolean, :default => true
|
||||
Person.reset_column_information
|
||||
assert Person.new.contributor?
|
||||
|
||||
assert_nothing_raised { Person.connection.change_column "people", "contributor", :boolean, :default => nil }
|
||||
Person.reset_column_information
|
||||
assert !Person.new.contributor?
|
||||
assert_nil Person.new.contributor
|
||||
end
|
||||
|
||||
def test_change_column_with_new_default
|
||||
Person.connection.add_column "people", "administrator", :boolean, :default => 1
|
||||
Person.reset_column_information
|
||||
Person.connection.add_column "people", "administrator", :boolean, :default => true
|
||||
Person.reset_column_information
|
||||
assert Person.new.administrator?
|
||||
|
||||
assert_nothing_raised { Person.connection.change_column "people", "administrator", :boolean, :default => 0 }
|
||||
Person.reset_column_information
|
||||
|
||||
assert_nothing_raised { Person.connection.change_column "people", "administrator", :boolean, :default => false }
|
||||
Person.reset_column_information
|
||||
assert !Person.new.administrator?
|
||||
end
|
||||
end
|
||||
|
||||
def test_change_column_default
|
||||
Person.connection.change_column_default "people", "first_name", "Tester"
|
||||
Person.reset_column_information
|
||||
assert_equal "Tester", Person.new.first_name
|
||||
end
|
||||
|
||||
def test_change_column_default_to_null
|
||||
Person.connection.change_column_default "people", "first_name", nil
|
||||
Person.reset_column_information
|
||||
assert_nil Person.new.first_name
|
||||
end
|
||||
|
||||
def test_add_table
|
||||
assert !Reminder.table_exists?
|
||||
|
||||
|
||||
WeNeedReminders.up
|
||||
|
||||
|
||||
assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
|
||||
assert_equal "hello world", Reminder.find(:first).content
|
||||
|
||||
|
||||
WeNeedReminders.down
|
||||
assert_raises(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
|
||||
end
|
||||
|
||||
def test_add_table_with_decimals
|
||||
Person.connection.drop_table :big_numbers rescue nil
|
||||
|
||||
assert !BigNumber.table_exists?
|
||||
GiveMeBigNumbers.up
|
||||
|
||||
assert BigNumber.create(
|
||||
:bank_balance => 1586.43,
|
||||
:big_bank_balance => BigDecimal("1000234000567.95"),
|
||||
:world_population => 6000000000,
|
||||
:my_house_population => 3,
|
||||
:value_of_e => BigDecimal("2.7182818284590452353602875")
|
||||
)
|
||||
|
||||
b = BigNumber.find(:first)
|
||||
assert_not_nil b
|
||||
|
||||
assert_not_nil b.bank_balance
|
||||
assert_not_nil b.big_bank_balance
|
||||
assert_not_nil b.world_population
|
||||
assert_not_nil b.my_house_population
|
||||
assert_not_nil b.value_of_e
|
||||
|
||||
# TODO: set world_population >= 2**62 to cover 64-bit platforms and test
|
||||
# is_a?(Bignum)
|
||||
assert_kind_of Integer, b.world_population
|
||||
assert_equal 6000000000, b.world_population
|
||||
assert_kind_of Fixnum, b.my_house_population
|
||||
assert_equal 3, b.my_house_population
|
||||
assert_kind_of BigDecimal, b.bank_balance
|
||||
assert_equal BigDecimal("1586.43"), b.bank_balance
|
||||
assert_kind_of BigDecimal, b.big_bank_balance
|
||||
assert_equal BigDecimal("1000234000567.95"), b.big_bank_balance
|
||||
|
||||
# This one is fun. The 'value_of_e' field is defined as 'DECIMAL' with
|
||||
# precision/scale explictly left out. By the SQL standard, numbers
|
||||
# assigned to this field should be truncated but that's seldom respected.
|
||||
if current_adapter?(:PostgreSQLAdapter, :SQLite2Adapter)
|
||||
# - PostgreSQL changes the SQL spec on columns declared simply as
|
||||
# "decimal" to something more useful: instead of being given a scale
|
||||
# of 0, they take on the compile-time limit for precision and scale,
|
||||
# so the following should succeed unless you have used really wacky
|
||||
# compilation options
|
||||
# - SQLite2 has the default behavior of preserving all data sent in,
|
||||
# so this happens there too
|
||||
assert_kind_of BigDecimal, b.value_of_e
|
||||
assert_equal BigDecimal("2.7182818284590452353602875"), b.value_of_e
|
||||
elsif current_adapter?(:SQLiteAdapter)
|
||||
# - SQLite3 stores a float, in violation of SQL
|
||||
assert_kind_of BigDecimal, b.value_of_e
|
||||
assert_equal BigDecimal("2.71828182845905"), b.value_of_e
|
||||
elsif current_adapter?(:SQLServer)
|
||||
# - SQL Server rounds instead of truncating
|
||||
assert_kind_of Fixnum, b.value_of_e
|
||||
assert_equal 3, b.value_of_e
|
||||
else
|
||||
# - SQL standard is an integer
|
||||
assert_kind_of Fixnum, b.value_of_e
|
||||
assert_equal 2, b.value_of_e
|
||||
end
|
||||
|
||||
GiveMeBigNumbers.down
|
||||
assert_raises(ActiveRecord::StatementInvalid) { BigNumber.find(:first) }
|
||||
end
|
||||
|
||||
def test_migrator
|
||||
assert !Person.column_methods_hash.include?(:last_name)
|
||||
assert !Reminder.table_exists?
|
||||
|
@ -335,7 +560,7 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
def test_migrator_one_up
|
||||
assert !Person.column_methods_hash.include?(:last_name)
|
||||
assert !Reminder.table_exists?
|
||||
|
||||
|
||||
ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1)
|
||||
|
||||
Person.reset_column_information
|
||||
|
@ -347,17 +572,17 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
|
||||
assert_equal "hello world", Reminder.find(:first).content
|
||||
end
|
||||
|
||||
|
||||
def test_migrator_one_down
|
||||
ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/')
|
||||
|
||||
|
||||
ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/', 1)
|
||||
|
||||
Person.reset_column_information
|
||||
assert Person.column_methods_hash.include?(:last_name)
|
||||
assert !Reminder.table_exists?
|
||||
end
|
||||
|
||||
|
||||
def test_migrator_one_up_one_down
|
||||
ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1)
|
||||
ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/', 0)
|
||||
|
@ -365,7 +590,7 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
assert !Person.column_methods_hash.include?(:last_name)
|
||||
assert !Reminder.table_exists?
|
||||
end
|
||||
|
||||
|
||||
def test_migrator_verbosity
|
||||
ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1)
|
||||
assert PeopleHaveLastNames.message_count > 0
|
||||
|
@ -375,7 +600,7 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
assert PeopleHaveLastNames.message_count > 0
|
||||
PeopleHaveLastNames.message_count = 0
|
||||
end
|
||||
|
||||
|
||||
def test_migrator_verbosity_off
|
||||
PeopleHaveLastNames.verbose = false
|
||||
ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1)
|
||||
|
@ -383,7 +608,7 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
ActiveRecord::Migrator.down(File.dirname(__FILE__) + '/fixtures/migrations/', 0)
|
||||
assert PeopleHaveLastNames.message_count.zero?
|
||||
end
|
||||
|
||||
|
||||
def test_migrator_going_down_due_to_version_target
|
||||
ActiveRecord::Migrator.up(File.dirname(__FILE__) + '/fixtures/migrations/', 1)
|
||||
ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/fixtures/migrations/', 0)
|
||||
|
@ -412,14 +637,14 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
ActiveRecord::Base.table_name_prefix = ""
|
||||
ActiveRecord::Base.table_name_suffix = ""
|
||||
end
|
||||
|
||||
|
||||
def test_proper_table_name
|
||||
assert_equal "table", ActiveRecord::Migrator.proper_table_name('table')
|
||||
assert_equal "table", ActiveRecord::Migrator.proper_table_name(:table)
|
||||
assert_equal "reminders", ActiveRecord::Migrator.proper_table_name(Reminder)
|
||||
Reminder.reset_table_name
|
||||
assert_equal Reminder.table_name, ActiveRecord::Migrator.proper_table_name(Reminder)
|
||||
|
||||
|
||||
# Use the model's own prefix/suffix if a model is given
|
||||
ActiveRecord::Base.table_name_prefix = "ARprefix_"
|
||||
ActiveRecord::Base.table_name_suffix = "_ARsuffix"
|
||||
|
@ -430,8 +655,8 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
Reminder.table_name_prefix = ''
|
||||
Reminder.table_name_suffix = ''
|
||||
Reminder.reset_table_name
|
||||
|
||||
# Use AR::Base's prefix/suffix if string or symbol is given
|
||||
|
||||
# Use AR::Base's prefix/suffix if string or symbol is given
|
||||
ActiveRecord::Base.table_name_prefix = "prefix_"
|
||||
ActiveRecord::Base.table_name_suffix = "_suffix"
|
||||
Reminder.reset_table_name
|
||||
|
@ -440,7 +665,7 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
ActiveRecord::Base.table_name_prefix = ""
|
||||
ActiveRecord::Base.table_name_suffix = ""
|
||||
Reminder.reset_table_name
|
||||
end
|
||||
end
|
||||
|
||||
def test_add_drop_table_with_prefix_and_suffix
|
||||
assert !Reminder.table_exists?
|
||||
|
@ -461,31 +686,83 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
Reminder.reset_sequence_name
|
||||
end
|
||||
|
||||
def test_create_table_with_binary_column
|
||||
Person.connection.drop_table :binary_testings rescue nil
|
||||
|
||||
assert_nothing_raised {
|
||||
Person.connection.create_table :binary_testings do |t|
|
||||
t.column "data", :binary, :default => "", :null => false
|
||||
# FrontBase does not support default values on BLOB/CLOB columns
|
||||
unless current_adapter?(:FrontBaseAdapter)
|
||||
def test_create_table_with_binary_column
|
||||
Person.connection.drop_table :binary_testings rescue nil
|
||||
|
||||
assert_nothing_raised {
|
||||
Person.connection.create_table :binary_testings do |t|
|
||||
t.column "data", :binary, :default => "", :null => false
|
||||
end
|
||||
}
|
||||
|
||||
columns = Person.connection.columns(:binary_testings)
|
||||
data_column = columns.detect { |c| c.name == "data" }
|
||||
|
||||
if current_adapter?(:OracleAdapter)
|
||||
assert_equal "empty_blob()", data_column.default
|
||||
else
|
||||
assert_equal "", data_column.default
|
||||
end
|
||||
}
|
||||
|
||||
columns = Person.connection.columns(:binary_testings)
|
||||
data_column = columns.detect { |c| c.name == "data" }
|
||||
|
||||
if current_adapter?(:OracleAdapter)
|
||||
assert_equal "empty_blob()", data_column.default
|
||||
else
|
||||
assert_equal "", data_column.default
|
||||
Person.connection.drop_table :binary_testings rescue nil
|
||||
end
|
||||
|
||||
Person.connection.drop_table :binary_testings rescue nil
|
||||
end
|
||||
|
||||
def test_migrator_with_duplicates
|
||||
assert_raises(ActiveRecord::DuplicateMigrationVersionError) do
|
||||
ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/fixtures/migrations_with_duplicate/', nil)
|
||||
end
|
||||
end
|
||||
|
||||
def test_migrator_with_missing_version_numbers
|
||||
ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/fixtures/migrations_with_missing_versions/', 500)
|
||||
assert !Person.column_methods_hash.include?(:middle_name)
|
||||
assert_equal 4, ActiveRecord::Migrator.current_version
|
||||
|
||||
ActiveRecord::Migrator.migrate(File.dirname(__FILE__) + '/fixtures/migrations_with_missing_versions/', 2)
|
||||
assert !Reminder.table_exists?
|
||||
assert Person.column_methods_hash.include?(:last_name)
|
||||
assert_equal 2, ActiveRecord::Migrator.current_version
|
||||
end
|
||||
|
||||
def test_create_table_with_custom_sequence_name
|
||||
return unless current_adapter? :OracleAdapter
|
||||
|
||||
# table name is 29 chars, the standard sequence name will
|
||||
# be 33 chars and fail
|
||||
assert_raises(ActiveRecord::StatementInvalid) do
|
||||
begin
|
||||
Person.connection.create_table :table_with_name_thats_just_ok do |t|
|
||||
t.column :foo, :string, :null => false
|
||||
end
|
||||
ensure
|
||||
Person.connection.drop_table :table_with_name_thats_just_ok rescue nil
|
||||
end
|
||||
end
|
||||
|
||||
# should be all good w/ a custom sequence name
|
||||
assert_nothing_raised do
|
||||
begin
|
||||
Person.connection.create_table :table_with_name_thats_just_ok,
|
||||
:sequence_name => 'suitably_short_seq' do |t|
|
||||
t.column :foo, :string, :null => false
|
||||
end
|
||||
|
||||
Person.connection.execute("select suitably_short_seq.nextval from dual")
|
||||
|
||||
ensure
|
||||
Person.connection.drop_table :table_with_name_thats_just_ok,
|
||||
:sequence_name => 'suitably_short_seq' rescue nil
|
||||
end
|
||||
end
|
||||
|
||||
# confirm the custom sequence got dropped
|
||||
assert_raises(ActiveRecord::StatementInvalid) do
|
||||
Person.connection.execute("select suitably_short_seq.nextval from dual")
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -178,7 +178,19 @@ class MixinNestedSetTest < Test::Unit::TestCase
|
|||
mixins(:set_1).add_child mixins(:set_4)
|
||||
|
||||
assert_equal( 3, mixins(:set_1).all_children.length )
|
||||
|
||||
|
||||
end
|
||||
|
||||
def test_inheritance
|
||||
parent = mixins(:sti_set_3100)
|
||||
child = mixins(:sti_set_3101)
|
||||
grandchild = mixins(:sti_set_3102)
|
||||
assert_equal 5, parent.full_set.size
|
||||
assert_equal 2, child.full_set.size
|
||||
assert_equal 4, parent.all_children.size
|
||||
assert_equal 1, child.all_children.size
|
||||
assert_equal 2, parent.direct_children.size
|
||||
assert_equal 1, child.direct_children.size
|
||||
child.destroy
|
||||
assert_equal 3, parent.full_set.size
|
||||
end
|
||||
end
|
||||
|
|
74
vendor/rails/activerecord/test/mixin_test.rb
vendored
74
vendor/rails/activerecord/test/mixin_test.rb
vendored
|
@ -4,6 +4,23 @@ require 'active_record/acts/list'
|
|||
require 'active_record/acts/nested_set'
|
||||
require 'fixtures/mixin'
|
||||
|
||||
# Let us control what Time.now returns for the TouchTest suite
|
||||
class Time
|
||||
@@forced_now_time = nil
|
||||
cattr_accessor :forced_now_time
|
||||
|
||||
class << self
|
||||
def now_with_forcing
|
||||
if @@forced_now_time
|
||||
@@forced_now_time
|
||||
else
|
||||
now_without_forcing
|
||||
end
|
||||
end
|
||||
alias_method_chain :now, :forcing
|
||||
end
|
||||
end
|
||||
|
||||
class ListTest < Test::Unit::TestCase
|
||||
fixtures :mixins
|
||||
|
||||
|
@ -200,10 +217,12 @@ class TreeTest < Test::Unit::TestCase
|
|||
fixtures :mixins
|
||||
|
||||
def test_has_child
|
||||
assert_equal true, mixins(:tree_1).has_children?
|
||||
assert_equal true, mixins(:tree_2).has_children?
|
||||
assert_equal false, mixins(:tree_3).has_children?
|
||||
assert_equal false, mixins(:tree_4).has_children?
|
||||
assert_deprecated 'has_children?' do
|
||||
assert_equal true, mixins(:tree_1).has_children?
|
||||
assert_equal true, mixins(:tree_2).has_children?
|
||||
assert_equal false, mixins(:tree_3).has_children?
|
||||
assert_equal false, mixins(:tree_4).has_children?
|
||||
end
|
||||
end
|
||||
|
||||
def test_children
|
||||
|
@ -214,10 +233,12 @@ class TreeTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_has_parent
|
||||
assert_equal false, mixins(:tree_1).has_parent?
|
||||
assert_equal true, mixins(:tree_2).has_parent?
|
||||
assert_equal true, mixins(:tree_3).has_parent?
|
||||
assert_equal true, mixins(:tree_4).has_parent?
|
||||
assert_deprecated 'has_parent?' do
|
||||
assert_equal false, mixins(:tree_1).has_parent?
|
||||
assert_equal true, mixins(:tree_2).has_parent?
|
||||
assert_equal true, mixins(:tree_3).has_parent?
|
||||
assert_equal true, mixins(:tree_4).has_parent?
|
||||
end
|
||||
end
|
||||
|
||||
def test_parent
|
||||
|
@ -304,6 +325,23 @@ end
|
|||
|
||||
class TouchTest < Test::Unit::TestCase
|
||||
fixtures :mixins
|
||||
|
||||
def setup
|
||||
Time.forced_now_time = Time.now
|
||||
end
|
||||
|
||||
def teardown
|
||||
Time.forced_now_time = nil
|
||||
end
|
||||
|
||||
def test_time_mocking
|
||||
five_minutes_ago = 5.minutes.ago
|
||||
Time.forced_now_time = five_minutes_ago
|
||||
assert_equal five_minutes_ago, Time.now
|
||||
|
||||
Time.forced_now_time = nil
|
||||
assert_not_equal five_minutes_ago, Time.now
|
||||
end
|
||||
|
||||
def test_update
|
||||
stamped = Mixin.new
|
||||
|
@ -311,14 +349,14 @@ class TouchTest < Test::Unit::TestCase
|
|||
assert_nil stamped.updated_at
|
||||
assert_nil stamped.created_at
|
||||
stamped.save
|
||||
assert_not_nil stamped.updated_at
|
||||
assert_not_nil stamped.created_at
|
||||
assert_equal Time.now, stamped.updated_at
|
||||
assert_equal Time.now, stamped.created_at
|
||||
end
|
||||
|
||||
def test_create
|
||||
@obj = Mixin.create
|
||||
assert_not_nil @obj.updated_at
|
||||
assert_not_nil @obj.created_at
|
||||
obj = Mixin.create
|
||||
assert_equal Time.now, obj.updated_at
|
||||
assert_equal Time.now, obj.created_at
|
||||
end
|
||||
|
||||
def test_many_updates
|
||||
|
@ -327,16 +365,16 @@ class TouchTest < Test::Unit::TestCase
|
|||
assert_nil stamped.updated_at
|
||||
assert_nil stamped.created_at
|
||||
stamped.save
|
||||
assert_not_nil stamped.created_at
|
||||
assert_not_nil stamped.updated_at
|
||||
assert_equal Time.now, stamped.created_at
|
||||
assert_equal Time.now, stamped.updated_at
|
||||
|
||||
old_updated_at = stamped.updated_at
|
||||
|
||||
sleep 1
|
||||
Time.forced_now_time = 5.minutes.from_now
|
||||
stamped.save
|
||||
assert_not_equal stamped.created_at, stamped.updated_at
|
||||
assert_not_equal old_updated_at, stamped.updated_at
|
||||
|
||||
assert_equal Time.now, stamped.updated_at
|
||||
assert_equal old_updated_at, stamped.created_at
|
||||
end
|
||||
|
||||
def test_create_turned_off
|
||||
|
|
10
vendor/rails/activerecord/test/modules_test.rb
vendored
10
vendor/rails/activerecord/test/modules_test.rb
vendored
|
@ -5,10 +5,9 @@ class ModulesTest < Test::Unit::TestCase
|
|||
fixtures :accounts, :companies, :projects, :developers
|
||||
|
||||
def test_module_spanning_associations
|
||||
assert MyApplication::Business::Firm.find(:first).has_clients?, "Firm should have clients"
|
||||
firm = MyApplication::Business::Firm.find(:first)
|
||||
assert !firm.clients.empty?, "Firm should have clients"
|
||||
assert_nil firm.class.table_name.match('::'), "Firm shouldn't have the module appear in its table name"
|
||||
assert_equal 2, firm.clients_count, "Firm should have two clients"
|
||||
end
|
||||
|
||||
def test_module_spanning_has_and_belongs_to_many_associations
|
||||
|
@ -25,4 +24,11 @@ class ModulesTest < Test::Unit::TestCase
|
|||
assert_kind_of MyApplication::Billing::Nested::Firm, account.nested_qualified_billing_firm
|
||||
assert_kind_of MyApplication::Billing::Nested::Firm, account.nested_unqualified_billing_firm
|
||||
end
|
||||
|
||||
def test_find_account_and_include_company
|
||||
account = MyApplication::Billing::Account.find(1, :include => :firm)
|
||||
assert_kind_of MyApplication::Business::Firm, account.instance_variable_get('@firm')
|
||||
assert_kind_of MyApplication::Business::Firm, account.firm
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -39,11 +39,11 @@ class MultipleDbTest < Test::Unit::TestCase
|
|||
|
||||
def test_associations
|
||||
c1 = Course.find(1)
|
||||
assert_equal 2, c1.entrants_count
|
||||
assert_equal 2, c1.entrants.count
|
||||
e1 = Entrant.find(1)
|
||||
assert_equal e1.course.id, c1.id
|
||||
c2 = Course.find(2)
|
||||
assert_equal 1, c2.entrants_count
|
||||
assert_equal 1, c2.entrants.count
|
||||
e3 = Entrant.find(3)
|
||||
assert_equal e3.course.id, c2.id
|
||||
end
|
||||
|
|
1
vendor/rails/activerecord/test/pk_test.rb
vendored
1
vendor/rails/activerecord/test/pk_test.rb
vendored
|
@ -1,5 +1,6 @@
|
|||
require "#{File.dirname(__FILE__)}/abstract_unit"
|
||||
require 'fixtures/topic'
|
||||
require 'fixtures/reply'
|
||||
require 'fixtures/subscriber'
|
||||
require 'fixtures/movie'
|
||||
require 'fixtures/keyboard'
|
||||
|
|
|
@ -45,6 +45,12 @@ class ReflectionTest < Test::Unit::TestCase
|
|||
assert_equal :string, @first.column_for_attribute("title").type
|
||||
assert_equal 255, @first.column_for_attribute("title").limit
|
||||
end
|
||||
|
||||
def test_column_null_not_null
|
||||
subscriber = Subscriber.find(:first)
|
||||
assert subscriber.column_for_attribute("name").null
|
||||
assert !subscriber.column_for_attribute("nick").null
|
||||
end
|
||||
|
||||
def test_human_name_for_column
|
||||
assert_equal "Author name", @first.column_for_attribute("author_name").human_name
|
||||
|
@ -137,8 +143,8 @@ class ReflectionTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_reflection_of_all_associations
|
||||
assert_equal 13, Firm.reflect_on_all_associations.size
|
||||
assert_equal 11, Firm.reflect_on_all_associations(:has_many).size
|
||||
assert_equal 17, Firm.reflect_on_all_associations.size
|
||||
assert_equal 15, Firm.reflect_on_all_associations(:has_many).size
|
||||
assert_equal 2, Firm.reflect_on_all_associations(:has_one).size
|
||||
assert_equal 0, Firm.reflect_on_all_associations(:belongs_to).size
|
||||
end
|
||||
|
|
|
@ -5,20 +5,48 @@ require 'stringio'
|
|||
if ActiveRecord::Base.connection.respond_to?(:tables)
|
||||
|
||||
class SchemaDumperTest < Test::Unit::TestCase
|
||||
def test_schema_dump
|
||||
def standard_dump
|
||||
stream = StringIO.new
|
||||
ActiveRecord::SchemaDumper.ignore_tables = []
|
||||
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
|
||||
output = stream.string
|
||||
|
||||
stream.string
|
||||
end
|
||||
|
||||
def test_schema_dump
|
||||
output = standard_dump
|
||||
assert_match %r{create_table "accounts"}, output
|
||||
assert_match %r{create_table "authors"}, output
|
||||
assert_no_match %r{create_table "schema_info"}, output
|
||||
end
|
||||
|
||||
def assert_line_up(lines, pattern, required = false)
|
||||
return assert(true) if lines.empty?
|
||||
matches = lines.map { |line| line.match(pattern) }
|
||||
assert matches.all? if required
|
||||
matches.compact!
|
||||
return assert(true) if matches.empty?
|
||||
assert_equal 1, matches.map{ |match| match.offset(0).first }.uniq.length
|
||||
end
|
||||
|
||||
def test_arguments_line_up
|
||||
output = standard_dump
|
||||
output.scan(/^( *)create_table.*?\n(.*?)^\1end/m).map{ |m| m.last.split(/\n/) }.each do |column_set|
|
||||
assert_line_up(column_set, /:(?:integer|decimal|float|datetime|timestamp|time|date|text|binary|string|boolean)/, true)
|
||||
assert_line_up(column_set, /:default => /)
|
||||
assert_line_up(column_set, /:limit => /)
|
||||
assert_line_up(column_set, /:null => /)
|
||||
end
|
||||
end
|
||||
|
||||
def test_no_dump_errors
|
||||
output = standard_dump
|
||||
assert_no_match %r{\# Could not dump table}, output
|
||||
end
|
||||
|
||||
def test_schema_dump_includes_not_null_columns
|
||||
stream = StringIO.new
|
||||
|
||||
ActiveRecord::SchemaDumper.ignore_tables = [/^[^s]/]
|
||||
ActiveRecord::SchemaDumper.ignore_tables = [/^[^r]/]
|
||||
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
|
||||
output = stream.string
|
||||
assert_match %r{:null => false}, output
|
||||
|
@ -55,6 +83,14 @@ if ActiveRecord::Base.connection.respond_to?(:tables)
|
|||
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
|
||||
end
|
||||
end
|
||||
|
||||
def test_schema_dump_includes_decimal_options
|
||||
stream = StringIO.new
|
||||
ActiveRecord::SchemaDumper.ignore_tables = [/^[^n]/]
|
||||
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
|
||||
output = stream.string
|
||||
assert_match %r{:precision => 3,[[:space:]]+:scale => 2,[[:space:]]+:default => 2.78}, output
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
require 'abstract_unit'
|
||||
require 'fixtures/topic'
|
||||
require 'fixtures/reply'
|
||||
|
||||
class ThreadedConnectionsTest < Test::Unit::TestCase
|
||||
self.use_transactional_fixtures = false
|
||||
unless %w(FrontBase).include? ActiveRecord::Base.connection.adapter_name
|
||||
class ThreadedConnectionsTest < Test::Unit::TestCase
|
||||
self.use_transactional_fixtures = false
|
||||
|
||||
fixtures :topics
|
||||
fixtures :topics
|
||||
|
||||
def setup
|
||||
@connection = ActiveRecord::Base.remove_connection
|
||||
|
@ -25,21 +27,22 @@ class ThreadedConnectionsTest < Test::Unit::TestCase
|
|||
ActiveRecord::Base.allow_concurrency = use_threaded_connections
|
||||
ActiveRecord::Base.establish_connection(@connection)
|
||||
|
||||
5.times do
|
||||
Thread.new do
|
||||
Topic.find :first
|
||||
@connections << ActiveRecord::Base.active_connections.values.first
|
||||
end.join
|
||||
5.times do
|
||||
Thread.new do
|
||||
Topic.find :first
|
||||
@connections << ActiveRecord::Base.active_connections.values.first
|
||||
end.join
|
||||
end
|
||||
end
|
||||
|
||||
def test_threaded_connections
|
||||
gather_connections(true)
|
||||
assert_equal @connections.uniq.length, 5
|
||||
end
|
||||
|
||||
def test_unthreaded_connections
|
||||
gather_connections(false)
|
||||
assert_equal @connections.uniq.length, 1
|
||||
end
|
||||
end
|
||||
|
||||
def test_threaded_connections
|
||||
gather_connections(true)
|
||||
assert_equal @connections.uniq.length, 5
|
||||
end
|
||||
|
||||
def test_unthreaded_connections
|
||||
gather_connections(false)
|
||||
assert_equal @connections.uniq.length, 1
|
||||
end
|
||||
end
|
||||
|
|
170
vendor/rails/activerecord/test/transactions_test.rb
vendored
170
vendor/rails/activerecord/test/transactions_test.rb
vendored
|
@ -1,15 +1,13 @@
|
|||
require 'abstract_unit'
|
||||
require 'fixtures/topic'
|
||||
require 'fixtures/reply'
|
||||
require 'fixtures/developer'
|
||||
|
||||
class TransactionTest < Test::Unit::TestCase
|
||||
self.use_transactional_fixtures = false
|
||||
|
||||
fixtures :topics, :developers
|
||||
|
||||
def setup
|
||||
# sqlite does not seem to return these in the right order, so we sort them
|
||||
# explicitly for sqlite's sake. sqlite3 does fine.
|
||||
@first, @second = Topic.find(1, 2).sort_by { |t| t.id }
|
||||
end
|
||||
|
||||
|
@ -92,12 +90,14 @@ class TransactionTest < Test::Unit::TestCase
|
|||
assert !@first.approved?, "First should be unapproved initially"
|
||||
|
||||
begin
|
||||
Topic.transaction(@first, @second) do
|
||||
@first.approved = true
|
||||
@second.approved = false
|
||||
@first.save
|
||||
@second.save
|
||||
raise "Bad things!"
|
||||
assert_deprecated /Object transactions/ do
|
||||
Topic.transaction(@first, @second) do
|
||||
@first.approved = true
|
||||
@second.approved = false
|
||||
@first.save
|
||||
@second.save
|
||||
raise "Bad things!"
|
||||
end
|
||||
end
|
||||
rescue
|
||||
# caught it
|
||||
|
@ -136,75 +136,6 @@ class TransactionTest < Test::Unit::TestCase
|
|||
assert !Topic.find(2).approved?, "Second should have been unapproved"
|
||||
end
|
||||
|
||||
# This will cause transactions to overlap and fail unless they are
|
||||
# performed on separate database connections.
|
||||
def test_transaction_per_thread
|
||||
assert_nothing_raised do
|
||||
threads = (1..20).map do
|
||||
Thread.new do
|
||||
Topic.transaction do
|
||||
topic = Topic.find(:first)
|
||||
topic.approved = !topic.approved?
|
||||
topic.save!
|
||||
topic.approved = !topic.approved?
|
||||
topic.save!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
threads.each { |t| t.join }
|
||||
end
|
||||
end
|
||||
|
||||
# Test for dirty reads among simultaneous transactions.
|
||||
def test_transaction_isolation__read_committed
|
||||
# Should be invariant.
|
||||
original_salary = Developer.find(1).salary
|
||||
temporary_salary = 200000
|
||||
|
||||
assert_nothing_raised do
|
||||
threads = (1..20).map do
|
||||
Thread.new do
|
||||
Developer.transaction do
|
||||
# Expect original salary.
|
||||
dev = Developer.find(1)
|
||||
assert_equal original_salary, dev.salary
|
||||
|
||||
dev.salary = temporary_salary
|
||||
dev.save!
|
||||
|
||||
# Expect temporary salary.
|
||||
dev = Developer.find(1)
|
||||
assert_equal temporary_salary, dev.salary
|
||||
|
||||
dev.salary = original_salary
|
||||
dev.save!
|
||||
|
||||
# Expect original salary.
|
||||
dev = Developer.find(1)
|
||||
assert_equal original_salary, dev.salary
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Keep our eyes peeled.
|
||||
threads << Thread.new do
|
||||
10.times do
|
||||
sleep 0.05
|
||||
Developer.transaction do
|
||||
# Always expect original salary.
|
||||
assert_equal original_salary, Developer.find(1).salary
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
threads.each { |t| t.join }
|
||||
end
|
||||
|
||||
assert_equal original_salary, Developer.find(1).salary
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
def add_exception_raising_after_save_callback_to_topic
|
||||
Topic.class_eval { def after_save() raise "Make the transaction rollback" end }
|
||||
|
@ -214,3 +145,86 @@ class TransactionTest < Test::Unit::TestCase
|
|||
Topic.class_eval { remove_method :after_save }
|
||||
end
|
||||
end
|
||||
|
||||
if current_adapter?(:PostgreSQLAdapter)
|
||||
class ConcurrentTransactionTest < TransactionTest
|
||||
def setup
|
||||
@allow_concurrency = ActiveRecord::Base.allow_concurrency
|
||||
ActiveRecord::Base.allow_concurrency = true
|
||||
super
|
||||
end
|
||||
|
||||
def teardown
|
||||
super
|
||||
ActiveRecord::Base.allow_concurrency = @allow_concurrency
|
||||
end
|
||||
|
||||
# This will cause transactions to overlap and fail unless they are performed on
|
||||
# separate database connections.
|
||||
def test_transaction_per_thread
|
||||
assert_nothing_raised do
|
||||
threads = (1..3).map do
|
||||
Thread.new do
|
||||
Topic.transaction do
|
||||
topic = Topic.find(1)
|
||||
topic.approved = !topic.approved?
|
||||
topic.save!
|
||||
topic.approved = !topic.approved?
|
||||
topic.save!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
threads.each { |t| t.join }
|
||||
end
|
||||
end
|
||||
|
||||
# Test for dirty reads among simultaneous transactions.
|
||||
def test_transaction_isolation__read_committed
|
||||
# Should be invariant.
|
||||
original_salary = Developer.find(1).salary
|
||||
temporary_salary = 200000
|
||||
|
||||
assert_nothing_raised do
|
||||
threads = (1..3).map do
|
||||
Thread.new do
|
||||
Developer.transaction do
|
||||
# Expect original salary.
|
||||
dev = Developer.find(1)
|
||||
assert_equal original_salary, dev.salary
|
||||
|
||||
dev.salary = temporary_salary
|
||||
dev.save!
|
||||
|
||||
# Expect temporary salary.
|
||||
dev = Developer.find(1)
|
||||
assert_equal temporary_salary, dev.salary
|
||||
|
||||
dev.salary = original_salary
|
||||
dev.save!
|
||||
|
||||
# Expect original salary.
|
||||
dev = Developer.find(1)
|
||||
assert_equal original_salary, dev.salary
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Keep our eyes peeled.
|
||||
threads << Thread.new do
|
||||
10.times do
|
||||
sleep 0.05
|
||||
Developer.transaction do
|
||||
# Always expect original salary.
|
||||
assert_equal original_salary, Developer.find(1).salary
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
threads.each { |t| t.join }
|
||||
end
|
||||
|
||||
assert_equal original_salary, Developer.find(1).salary
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
186
vendor/rails/activerecord/test/validations_test.rb
vendored
186
vendor/rails/activerecord/test/validations_test.rb
vendored
|
@ -26,16 +26,16 @@ class ValidationsTest < Test::Unit::TestCase
|
|||
def test_single_field_validation
|
||||
r = Reply.new
|
||||
r.title = "There's no content!"
|
||||
assert !r.save, "A reply without content shouldn't be saveable"
|
||||
assert !r.valid?, "A reply without content shouldn't be saveable"
|
||||
|
||||
r.content = "Messa content!"
|
||||
assert r.save, "A reply with content should be saveable"
|
||||
assert r.valid?, "A reply with content should be saveable"
|
||||
end
|
||||
|
||||
def test_single_attr_validation_and_error_msg
|
||||
r = Reply.new
|
||||
r.title = "There's no content!"
|
||||
r.save
|
||||
assert !r.valid?
|
||||
assert r.errors.invalid?("content"), "A reply without content should mark that attribute as invalid"
|
||||
assert_equal "Empty", r.errors.on("content"), "A reply without content should contain an error"
|
||||
assert_equal 1, r.errors.count
|
||||
|
@ -43,7 +43,7 @@ class ValidationsTest < Test::Unit::TestCase
|
|||
|
||||
def test_double_attr_validation_and_error_msg
|
||||
r = Reply.new
|
||||
assert !r.save
|
||||
assert !r.valid?
|
||||
|
||||
assert r.errors.invalid?("title"), "A reply without title should mark that attribute as invalid"
|
||||
assert_equal "Empty", r.errors.on("title"), "A reply without title should contain an error"
|
||||
|
@ -57,7 +57,7 @@ class ValidationsTest < Test::Unit::TestCase
|
|||
def test_error_on_create
|
||||
r = Reply.new
|
||||
r.title = "Wrong Create"
|
||||
assert !r.save
|
||||
assert !r.valid?
|
||||
assert r.errors.invalid?("title"), "A reply with a bad title should mark that attribute as invalid"
|
||||
assert_equal "is Wrong Create", r.errors.on("title"), "A reply with a bad content should contain an error"
|
||||
end
|
||||
|
@ -88,6 +88,12 @@ class ValidationsTest < Test::Unit::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
def test_scoped_create_without_attributes
|
||||
Reply.with_scope(:create => {}) do
|
||||
assert_raises(ActiveRecord::RecordInvalid) { Reply.create! }
|
||||
end
|
||||
end
|
||||
|
||||
def test_single_error_per_attr_iteration
|
||||
r = Reply.new
|
||||
r.save
|
||||
|
@ -135,6 +141,12 @@ class ValidationsTest < Test::Unit::TestCase
|
|||
assert reply.save(false)
|
||||
end
|
||||
|
||||
def test_create_without_validation_bang
|
||||
count = Reply.count
|
||||
assert_nothing_raised { Reply.new.save_without_validation! }
|
||||
assert count+1, Reply.count
|
||||
end
|
||||
|
||||
def test_validates_each
|
||||
perform = true
|
||||
hits = 0
|
||||
|
@ -153,24 +165,21 @@ class ValidationsTest < Test::Unit::TestCase
|
|||
perform = false
|
||||
end
|
||||
|
||||
def test_errors_on_boundary_breaking
|
||||
developer = Developer.new("name" => "xs")
|
||||
assert !developer.save
|
||||
assert_equal "is too short (minimum is 3 characters)", developer.errors.on("name")
|
||||
|
||||
developer.name = "All too very long for this boundary, it really is"
|
||||
assert !developer.save
|
||||
assert_equal "is too long (maximum is 20 characters)", developer.errors.on("name")
|
||||
|
||||
developer.name = "Just right"
|
||||
assert developer.save
|
||||
end
|
||||
|
||||
def test_title_confirmation_no_confirm
|
||||
def test_no_title_confirmation
|
||||
Topic.validates_confirmation_of(:title)
|
||||
|
||||
t = Topic.create("title" => "We should not be confirmed")
|
||||
assert t.save
|
||||
t = Topic.new(:author_name => "Plutarch")
|
||||
assert t.valid?
|
||||
|
||||
t.title_confirmation = "Parallel Lives"
|
||||
assert !t.valid?
|
||||
|
||||
t.title_confirmation = nil
|
||||
t.title = "Parallel Lives"
|
||||
assert t.valid?
|
||||
|
||||
t.title_confirmation = "Parallel Lives"
|
||||
assert t.valid?
|
||||
end
|
||||
|
||||
def test_title_confirmation
|
||||
|
@ -304,6 +313,37 @@ class ValidationsTest < Test::Unit::TestCase
|
|||
assert !r3.save, "Saving r3 the third time."
|
||||
end
|
||||
|
||||
def test_validate_case_insensitive_uniqueness
|
||||
Topic.validates_uniqueness_of(:title, :parent_id, :case_sensitive => false, :allow_nil => true)
|
||||
|
||||
t = Topic.new("title" => "I'm unique!", :parent_id => 2)
|
||||
assert t.save, "Should save t as unique"
|
||||
|
||||
t.content = "Remaining unique"
|
||||
assert t.save, "Should still save t as unique"
|
||||
|
||||
t2 = Topic.new("title" => "I'm UNIQUE!", :parent_id => 1)
|
||||
assert !t2.valid?, "Shouldn't be valid"
|
||||
assert !t2.save, "Shouldn't save t2 as unique"
|
||||
assert t2.errors.on(:title)
|
||||
assert t2.errors.on(:parent_id)
|
||||
assert_equal "has already been taken", t2.errors.on(:title)
|
||||
|
||||
t2.title = "I'm truly UNIQUE!"
|
||||
assert !t2.valid?, "Shouldn't be valid"
|
||||
assert !t2.save, "Shouldn't save t2 as unique"
|
||||
assert_nil t2.errors.on(:title)
|
||||
assert t2.errors.on(:parent_id)
|
||||
|
||||
t2.parent_id = 3
|
||||
assert t2.save, "Should now save t2 as unique"
|
||||
|
||||
t2.parent_id = nil
|
||||
t2.title = nil
|
||||
assert t2.valid?, "should validate with nil"
|
||||
assert t2.save, "should save with nil"
|
||||
end
|
||||
|
||||
def test_validate_format
|
||||
Topic.validates_format_of(:title, :content, :with => /^Validation\smacros \w+!$/, :message => "is bad data")
|
||||
|
||||
|
@ -573,6 +613,18 @@ class ValidationsTest < Test::Unit::TestCase
|
|||
|
||||
assert_equal 'tu est trops petit hombre 10', t.errors['title']
|
||||
end
|
||||
|
||||
def test_add_on_boundary_breaking_is_deprecated
|
||||
t = Topic.new('title' => 'noreplies', 'content' => 'whatever')
|
||||
class << t
|
||||
def validate
|
||||
errors.add_on_boundary_breaking('title', 1..6)
|
||||
end
|
||||
end
|
||||
assert_deprecated 'add_on_boundary_breaking' do
|
||||
assert !t.valid?
|
||||
end
|
||||
end
|
||||
|
||||
def test_validates_size_of_association
|
||||
assert_nothing_raised { Topic.validates_size_of :replies, :minimum => 1 }
|
||||
|
@ -672,7 +724,7 @@ class ValidationsTest < Test::Unit::TestCase
|
|||
|
||||
t = Topic.create("title" => "一二三四五", "content" => "whatever")
|
||||
assert t.valid?
|
||||
|
||||
|
||||
t.title = "一二34五六"
|
||||
assert !t.valid?
|
||||
assert t.errors.on(:title)
|
||||
|
@ -714,16 +766,16 @@ class ValidationsTest < Test::Unit::TestCase
|
|||
assert !t.save
|
||||
assert t.errors.on(:title)
|
||||
assert_equal "長すぎます: 10", t.errors[:title]
|
||||
|
||||
|
||||
t.title = "一二三四五六七八九"
|
||||
assert t.save
|
||||
|
||||
|
||||
t.title = "一二3"
|
||||
assert t.save
|
||||
|
||||
|
||||
t.content = "一二三四五六七八九十"
|
||||
assert t.save
|
||||
|
||||
|
||||
t.content = t.title = "一二三四五六"
|
||||
assert t.save
|
||||
end
|
||||
|
@ -736,17 +788,17 @@ class ValidationsTest < Test::Unit::TestCase
|
|||
t = Topic.create("title" => "一二三4", "content" => "whatever")
|
||||
assert !t.save
|
||||
assert t.errors.on(:title)
|
||||
|
||||
|
||||
t.title = "1二三4"
|
||||
assert !t.save
|
||||
assert t.errors.on(:title)
|
||||
assert_equal "短すぎます: 5", t.errors[:title]
|
||||
|
||||
|
||||
t.title = "valid"
|
||||
t.content = "一二三四五六七八九十A"
|
||||
assert !t.save
|
||||
assert t.errors.on(:content)
|
||||
|
||||
|
||||
t.content = "一二345"
|
||||
assert t.save
|
||||
end
|
||||
|
@ -814,7 +866,7 @@ class ValidationsTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_throw_away_typing
|
||||
d = Developer.create "name" => "David", "salary" => "100,000"
|
||||
d = Developer.new("name" => "David", "salary" => "100,000")
|
||||
assert !d.valid?
|
||||
assert_equal 100, d.salary
|
||||
assert_equal "100,000", d.salary_before_type_cast
|
||||
|
@ -829,20 +881,20 @@ class ValidationsTest < Test::Unit::TestCase
|
|||
end
|
||||
|
||||
def test_validates_confirmation_of_with_custom_error_using_quotes
|
||||
Developer.validates_confirmation_of :name, :message=> "This string contains 'single' and \"double\" quotes"
|
||||
Developer.validates_confirmation_of :name, :message=> "confirm 'single' and \"double\" quotes"
|
||||
d = Developer.new
|
||||
d.name = "John"
|
||||
d.name_confirmation = "Johnny"
|
||||
assert !d.valid?
|
||||
assert_equal d.errors.on(:name), "This string contains 'single' and \"double\" quotes"
|
||||
assert_equal "confirm 'single' and \"double\" quotes", d.errors.on(:name)
|
||||
end
|
||||
|
||||
def test_validates_format_of_with_custom_error_using_quotes
|
||||
Developer.validates_format_of :name, :with => /^(A-Z*)$/, :message=> "This string contains 'single' and \"double\" quotes"
|
||||
Developer.validates_format_of :name, :with => /^(A-Z*)$/, :message=> "format 'single' and \"double\" quotes"
|
||||
d = Developer.new
|
||||
d.name = "John 32"
|
||||
d.name = d.name_confirmation = "John 32"
|
||||
assert !d.valid?
|
||||
assert_equal d.errors.on(:name), "This string contains 'single' and \"double\" quotes"
|
||||
assert_equal "format 'single' and \"double\" quotes", d.errors.on(:name)
|
||||
end
|
||||
|
||||
def test_validates_inclusion_of_with_custom_error_using_quotes
|
||||
|
@ -850,7 +902,7 @@ class ValidationsTest < Test::Unit::TestCase
|
|||
d = Developer.new
|
||||
d.salary = "90,000"
|
||||
assert !d.valid?
|
||||
assert_equal d.errors.on(:salary).first, "This string contains 'single' and \"double\" quotes"
|
||||
assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:salary).first
|
||||
end
|
||||
|
||||
def test_validates_length_of_with_custom_too_long_using_quotes
|
||||
|
@ -858,7 +910,7 @@ class ValidationsTest < Test::Unit::TestCase
|
|||
d = Developer.new
|
||||
d.name = "Jeffrey"
|
||||
assert !d.valid?
|
||||
assert_equal d.errors.on(:name).first, "This string contains 'single' and \"double\" quotes"
|
||||
assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:name).first
|
||||
end
|
||||
|
||||
def test_validates_length_of_with_custom_too_short_using_quotes
|
||||
|
@ -866,7 +918,7 @@ class ValidationsTest < Test::Unit::TestCase
|
|||
d = Developer.new
|
||||
d.name = "Joe"
|
||||
assert !d.valid?
|
||||
assert_equal d.errors.on(:name).first, "This string contains 'single' and \"double\" quotes"
|
||||
assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:name).first
|
||||
end
|
||||
|
||||
def test_validates_length_of_with_custom_message_using_quotes
|
||||
|
@ -874,7 +926,7 @@ class ValidationsTest < Test::Unit::TestCase
|
|||
d = Developer.new
|
||||
d.name = "Joe"
|
||||
assert !d.valid?
|
||||
assert_equal d.errors.on(:name).first, "This string contains 'single' and \"double\" quotes"
|
||||
assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:name).first
|
||||
end
|
||||
|
||||
def test_validates_presence_of_with_custom_message_using_quotes
|
||||
|
@ -882,7 +934,7 @@ class ValidationsTest < Test::Unit::TestCase
|
|||
d = Developer.new
|
||||
d.name = "Joe"
|
||||
assert !d.valid?
|
||||
assert_equal d.errors.on(:non_existent), "This string contains 'single' and \"double\" quotes"
|
||||
assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:non_existent)
|
||||
end
|
||||
|
||||
def test_validates_uniqueness_of_with_custom_message_using_quotes
|
||||
|
@ -890,7 +942,7 @@ class ValidationsTest < Test::Unit::TestCase
|
|||
d = Developer.new
|
||||
d.name = "David"
|
||||
assert !d.valid?
|
||||
assert_equal d.errors.on(:name).first, "This string contains 'single' and \"double\" quotes"
|
||||
assert_equal "This string contains 'single' and \"double\" quotes", d.errors.on(:name).first
|
||||
end
|
||||
|
||||
def test_validates_associated_with_custom_message_using_quotes
|
||||
|
@ -899,7 +951,7 @@ class ValidationsTest < Test::Unit::TestCase
|
|||
r = Reply.create("title" => "A reply", "content" => "with content!")
|
||||
r.topic = Topic.create("title" => "uhohuhoh")
|
||||
assert !r.valid?
|
||||
assert_equal r.errors.on(:topic).first, "This string contains 'single' and \"double\" quotes"
|
||||
assert_equal "This string contains 'single' and \"double\" quotes", r.errors.on(:topic).first
|
||||
end
|
||||
|
||||
def test_conditional_validation_using_method_true
|
||||
|
@ -916,7 +968,7 @@ class ValidationsTest < Test::Unit::TestCase
|
|||
Topic.validates_length_of( :title, :maximum=>5, :too_long=>"hoo %d", :if => :condition_is_true_but_its_not )
|
||||
t = Topic.create("title" => "uhohuhoh", "content" => "whatever")
|
||||
assert t.valid?
|
||||
assert !t.errors.on(:title)
|
||||
assert !t.errors.on(:title)
|
||||
end
|
||||
|
||||
def test_conditional_validation_using_string_true
|
||||
|
@ -964,16 +1016,28 @@ class ValidationsTest < Test::Unit::TestCase
|
|||
r.topic = Topic.find :first
|
||||
assert r.valid?
|
||||
end
|
||||
|
||||
def test_errors_to_xml
|
||||
r = Reply.new :title => "Wrong Create"
|
||||
assert !r.valid?
|
||||
xml = r.errors.to_xml(:skip_instruct => true)
|
||||
assert_equal "<errors>", xml.first(8)
|
||||
assert xml.include?("<error>Title is Wrong Create</error>")
|
||||
assert xml.include?("<error>Content Empty</error>")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
class ValidatesNumericalityTest
|
||||
NIL = [nil, "", " ", " \t \r \n"]
|
||||
FLOAT_STRINGS = %w(0.0 +0.0 -0.0 10.0 10.5 -10.5 -0.0001 -090.1)
|
||||
class ValidatesNumericalityTest < Test::Unit::TestCase
|
||||
NIL = [nil]
|
||||
BLANK = ["", " ", " \t \r \n"]
|
||||
BIGDECIMAL_STRINGS = %w(12345678901234567890.1234567890) # 30 significent digits
|
||||
FLOAT_STRINGS = %w(0.0 +0.0 -0.0 10.0 10.5 -10.5 -0.0001 -090.1 90.1e1 -90.1e5 -90.1e-5 90e-5)
|
||||
INTEGER_STRINGS = %w(0 +0 -0 10 +10 -10 0090 -090)
|
||||
FLOATS = [0.0, 10.0, 10.5, -10.5, -0.0001] + FLOAT_STRINGS
|
||||
INTEGERS = [0, 10, -10] + INTEGER_STRINGS
|
||||
JUNK = ["not a number", "42 not a number", "0xdeadbeef", "00-1", "--3", "+-3", "+3-1", "-+019.0", "12.12.13.12"]
|
||||
BIGDECIMAL = BIGDECIMAL_STRINGS.collect! { |bd| BigDecimal.new(bd) }
|
||||
JUNK = ["not a number", "42 not a number", "0xdeadbeef", "00-1", "--3", "+-3", "+3-1", "-+019.0", "12.12.13.12", "123\nnot a number"]
|
||||
|
||||
def setup
|
||||
Topic.write_inheritable_attribute(:validate, nil)
|
||||
|
@ -984,44 +1048,50 @@ class ValidatesNumericalityTest
|
|||
def test_default_validates_numericality_of
|
||||
Topic.validates_numericality_of :approved
|
||||
|
||||
invalid!(NIL + JUNK)
|
||||
valid!(FLOATS + INTEGERS)
|
||||
invalid!(NIL + BLANK + JUNK)
|
||||
valid!(FLOATS + INTEGERS + BIGDECIMAL)
|
||||
end
|
||||
|
||||
def test_validates_numericality_of_with_nil_allowed
|
||||
Topic.validates_numericality_of :approved, :allow_nil => true
|
||||
|
||||
invalid!(JUNK)
|
||||
valid!(NIL + FLOATS + INTEGERS)
|
||||
invalid!(BLANK + JUNK)
|
||||
valid!(NIL + FLOATS + INTEGERS + BIGDECIMAL)
|
||||
end
|
||||
|
||||
def test_validates_numericality_of_with_integer_only
|
||||
Topic.validates_numericality_of :approved, :only_integer => true
|
||||
|
||||
invalid!(NIL + JUNK + FLOATS)
|
||||
invalid!(NIL + BLANK + JUNK + FLOATS + BIGDECIMAL)
|
||||
valid!(INTEGERS)
|
||||
end
|
||||
|
||||
def test_validates_numericality_of_with_integer_only_and_nil_allowed
|
||||
Topic.validates_numericality_of :approved, :only_integer => true, :allow_nil => true
|
||||
|
||||
invalid!(JUNK + FLOATS)
|
||||
invalid!(BLANK + JUNK + FLOATS + BIGDECIMAL)
|
||||
valid!(NIL + INTEGERS)
|
||||
end
|
||||
|
||||
private
|
||||
def invalid!(values)
|
||||
values.each do |value|
|
||||
topic = Topic.create("title" => "numeric test", "content" => "whatever", "approved" => value)
|
||||
assert !topic.valid?, "#{value} not rejected as a number"
|
||||
with_each_topic_approved_value(values) do |topic, value|
|
||||
assert !topic.valid?, "#{value.inspect} not rejected as a number"
|
||||
assert topic.errors.on(:approved)
|
||||
end
|
||||
end
|
||||
|
||||
def valid!(values)
|
||||
with_each_topic_approved_value(values) do |topic, value|
|
||||
assert topic.valid?, "#{value.inspect} not accepted as a number"
|
||||
end
|
||||
end
|
||||
|
||||
def with_each_topic_approved_value(values)
|
||||
topic = Topic.new("title" => "numeric test", "content" => "whatever")
|
||||
values.each do |value|
|
||||
topic = Topic.create("title" => "numeric test", "content" => "whatever", "approved" => value)
|
||||
assert topic.valid?, "#{value} not accepted as a number"
|
||||
topic.approved = value
|
||||
yield topic, value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue