unfreeze rails

This commit is contained in:
Reinier Balt 2008-11-28 08:16:04 +01:00
parent bd2b410c7b
commit fe5f962dcf
1493 changed files with 1 additions and 191145 deletions

View file

@ -1 +0,0 @@
# Logfile created on Wed Oct 31 16:05:13 +0000 2007 by logger.rb/1.5.2.9

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.7 KiB

View file

@ -1,24 +0,0 @@
# The filename begins with "aaa" to ensure this is the first test.
require "cases/helper"
class AAACreateTablesTest < ActiveRecord::TestCase
self.use_transactional_fixtures = false
def test_load_schema
eval(File.read(SCHEMA_ROOT + "/schema.rb"))
if File.exists?(adapter_specific_schema_file)
eval(File.read(adapter_specific_schema_file))
end
assert true
end
def test_drop_and_create_courses_table
eval(File.read(SCHEMA_ROOT + "/schema2.rb"))
assert true
end
private
def adapter_specific_schema_file
SCHEMA_ROOT + '/' + ActiveRecord::Base.connection.adapter_name.downcase + '_specific_schema.rb'
end
end

View file

@ -1,95 +0,0 @@
require "cases/helper"
class ActiveSchemaTest < ActiveRecord::TestCase
def setup
ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do
alias_method :execute_without_stub, :execute
def execute(sql, name = nil) return sql end
end
end
def teardown
ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do
remove_method :execute
alias_method :execute, :execute_without_stub
end
end
def test_drop_table
assert_equal "DROP TABLE `people`", drop_table(:people)
end
if current_adapter?(:MysqlAdapter)
def test_create_mysql_database_with_encoding
assert_equal "CREATE DATABASE `matt` DEFAULT CHARACTER SET `utf8`", create_database(:matt)
assert_equal "CREATE DATABASE `aimonetti` DEFAULT CHARACTER SET `latin1`", create_database(:aimonetti, {:charset => 'latin1'})
assert_equal "CREATE DATABASE `matt_aimonetti` DEFAULT CHARACTER SET `big5` COLLATE `big5_chinese_ci`", create_database(:matt_aimonetti, {:charset => :big5, :collation => :big5_chinese_ci})
end
end
def test_add_column
assert_equal "ALTER TABLE `people` ADD `last_name` varchar(255)", add_column(:people, :last_name, :string)
end
def test_add_column_with_limit
assert_equal "ALTER TABLE `people` ADD `key` varchar(32)", add_column(:people, :key, :string, :limit => 32)
end
def test_drop_table_with_specific_database
assert_equal "DROP TABLE `otherdb`.`people`", drop_table('otherdb.people')
end
def test_add_timestamps
with_real_execute do
begin
ActiveRecord::Base.connection.create_table :delete_me do |t|
end
ActiveRecord::Base.connection.add_timestamps :delete_me
assert column_present?('delete_me', 'updated_at', 'datetime')
assert column_present?('delete_me', 'created_at', 'datetime')
ensure
ActiveRecord::Base.connection.drop_table :delete_me rescue nil
end
end
end
def test_remove_timestamps
with_real_execute do
begin
ActiveRecord::Base.connection.create_table :delete_me do |t|
t.timestamps
end
ActiveRecord::Base.connection.remove_timestamps :delete_me
assert !column_present?('delete_me', 'updated_at', 'datetime')
assert !column_present?('delete_me', 'created_at', 'datetime')
ensure
ActiveRecord::Base.connection.drop_table :delete_me rescue nil
end
end
end
private
def with_real_execute
#we need to actually modify some data, so we make execute point to the original method
ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do
alias_method :execute_with_stub, :execute
alias_method :execute, :execute_without_stub
end
yield
ensure
#before finishing, we restore the alias to the mock-up method
ActiveRecord::ConnectionAdapters::MysqlAdapter.class_eval do
alias_method :execute, :execute_with_stub
end
end
def method_missing(method_symbol, *arguments)
ActiveRecord::Base.connection.send(method_symbol, *arguments)
end
def column_present?(table_name, column_name, type)
results = ActiveRecord::Base.connection.select_all("SHOW FIELDS FROM #{table_name} LIKE '#{column_name}'")
results.first && results.first['Type'] == type
end
end

View file

@ -1,24 +0,0 @@
require 'cases/helper'
class PostgresqlActiveSchemaTest < Test::Unit::TestCase
def setup
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.class_eval do
alias_method :real_execute, :execute
def execute(sql, name = nil) sql end
end
end
def teardown
ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.send(:alias_method, :execute, :real_execute)
end
def test_create_database_with_encoding
assert_equal "CREATE DATABASE matt ENCODING = 'utf8'", create_database(:matt)
assert_equal "CREATE DATABASE aimonetti ENCODING = 'latin1'", create_database(:aimonetti, :encoding => :latin1)
end
private
def method_missing(method_symbol, *arguments)
ActiveRecord::Base.connection.send(method_symbol, *arguments)
end
end

View file

@ -1,127 +0,0 @@
require "cases/helper"
class AdapterTest < ActiveRecord::TestCase
def setup
@connection = ActiveRecord::Base.connection
end
def test_tables
tables = @connection.tables
assert tables.include?("accounts")
assert tables.include?("authors")
assert tables.include?("tasks")
assert tables.include?("topics")
end
def test_table_exists?
assert @connection.table_exists?("accounts")
assert !@connection.table_exists?("nonexistingtable")
end
def test_indexes
idx_name = "accounts_idx"
if @connection.respond_to?(:indexes)
indexes = @connection.indexes("accounts")
assert indexes.empty?
@connection.add_index :accounts, :firm_id, :name => idx_name
indexes = @connection.indexes("accounts")
assert_equal "accounts", indexes.first.table
# OpenBase does not have the concept of a named index
# Indexes are merely properties of columns.
assert_equal idx_name, indexes.first.name unless current_adapter?(:OpenBaseAdapter)
assert !indexes.first.unique
assert_equal ["firm_id"], indexes.first.columns
else
warn "#{@connection.class} does not respond to #indexes"
end
ensure
@connection.remove_index(:accounts, :name => idx_name) rescue nil
end
def test_current_database
if @connection.respond_to?(:current_database)
assert_equal ENV['ARUNIT_DB_NAME'] || "activerecord_unittest", @connection.current_database
end
end
if current_adapter?(:MysqlAdapter)
def test_charset
assert_not_nil @connection.charset
assert_not_equal 'character_set_database', @connection.charset
assert_equal @connection.show_variable('character_set_database'), @connection.charset
end
def test_collation
assert_not_nil @connection.collation
assert_not_equal 'collation_database', @connection.collation
assert_equal @connection.show_variable('collation_database'), @connection.collation
end
def test_show_nonexistent_variable_returns_nil
assert_nil @connection.show_variable('foo_bar_baz')
end
end
def test_table_alias
def @connection.test_table_alias_length() 10; end
class << @connection
alias_method :old_table_alias_length, :table_alias_length
alias_method :table_alias_length, :test_table_alias_length
end
assert_equal 'posts', @connection.table_alias_for('posts')
assert_equal 'posts_comm', @connection.table_alias_for('posts_comments')
assert_equal 'dbo_posts', @connection.table_alias_for('dbo.posts')
class << @connection
remove_method :table_alias_length
alias_method :table_alias_length, :old_table_alias_length
end
end
# test resetting sequences in odd tables in postgreSQL
if ActiveRecord::Base.connection.respond_to?(:reset_pk_sequence!)
require 'models/movie'
require 'models/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
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
def test_add_limit_offset_should_sanitize_sql_injection_for_limit_without_comas
sql_inject = "1 select * from schema"
assert_equal " LIMIT 1", @connection.add_limit_offset!("", :limit=>sql_inject)
if current_adapter?(:MysqlAdapter)
assert_equal " LIMIT 7, 1", @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7)
else
assert_equal " LIMIT 1 OFFSET 7", @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7)
end
end
def test_add_limit_offset_should_sanitize_sql_injection_for_limit_with_comas
sql_inject = "1, 7 procedure help()"
if current_adapter?(:MysqlAdapter)
assert_equal " LIMIT 1,7", @connection.add_limit_offset!("", :limit=>sql_inject)
assert_equal " LIMIT 7, 1", @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7)
else
assert_equal " LIMIT 1,7", @connection.add_limit_offset!("", :limit=>sql_inject)
assert_equal " LIMIT 1,7 OFFSET 7", @connection.add_limit_offset!("", :limit=>sql_inject, :offset=>7)
end
end
end

View file

@ -1,95 +0,0 @@
require "cases/helper"
require 'models/default'
require 'models/post'
require 'models/task'
class SqlServerAdapterTest < ActiveRecord::TestCase
class TableWithRealColumn < ActiveRecord::Base; end
fixtures :posts, :tasks
def setup
@connection = ActiveRecord::Base.connection
end
def teardown
@connection.execute("SET LANGUAGE us_english") rescue nil
end
def test_real_column_has_float_type
assert_equal :float, TableWithRealColumn.columns_hash["real_number"].type
end
# SQL Server 2000 has a bug where some unambiguous date formats are not
# correctly identified if the session language is set to german
def test_date_insertion_when_language_is_german
@connection.execute("SET LANGUAGE deutsch")
assert_nothing_raised do
Task.create(:starting => Time.utc(2000, 1, 31, 5, 42, 0), :ending => Date.new(2006, 12, 31))
end
end
def test_indexes_with_descending_order
# Make sure we have an index with descending order
@connection.execute "CREATE INDEX idx_credit_limit ON accounts (credit_limit DESC)" rescue nil
assert_equal ["credit_limit"], @connection.indexes('accounts').first.columns
ensure
@connection.execute "DROP INDEX accounts.idx_credit_limit"
end
def test_execute_without_block_closes_statement
assert_all_statements_used_are_closed do
@connection.execute("SELECT 1")
end
end
def test_execute_with_block_closes_statement
assert_all_statements_used_are_closed do
@connection.execute("SELECT 1") do |sth|
assert !sth.finished?, "Statement should still be alive within block"
end
end
end
def test_insert_with_identity_closes_statement
assert_all_statements_used_are_closed do
@connection.insert("INSERT INTO accounts ([id], [firm_id],[credit_limit]) values (999, 1, 50)")
end
end
def test_insert_without_identity_closes_statement
assert_all_statements_used_are_closed do
@connection.insert("INSERT INTO accounts ([firm_id],[credit_limit]) values (1, 50)")
end
end
def test_active_closes_statement
assert_all_statements_used_are_closed do
@connection.active?
end
end
def assert_all_statements_used_are_closed(&block)
existing_handles = []
ObjectSpace.each_object(DBI::StatementHandle) {|handle| existing_handles << handle}
GC.disable
yield
used_handles = []
ObjectSpace.each_object(DBI::StatementHandle) {|handle| used_handles << handle unless existing_handles.include? handle}
assert_block "No statements were used within given block" do
used_handles.size > 0
end
ObjectSpace.each_object(DBI::StatementHandle) do |handle|
assert_block "Statement should have been closed within given block" do
handle.finished?
end
end
ensure
GC.enable
end
end

View file

@ -1,128 +0,0 @@
require "cases/helper"
require 'models/customer'
class AggregationsTest < ActiveRecord::TestCase
fixtures :customers
def test_find_single_value_object
assert_equal 50, customers(:david).balance.amount
assert_kind_of Money, customers(:david).balance
assert_equal 300, customers(:david).balance.exchange_to("DKK").amount
end
def test_find_multiple_value_object
assert_equal customers(:david).address_street, customers(:david).address.street
assert(
customers(:david).address.close_to?(Address.new("Different Street", customers(:david).address_city, customers(:david).address_country))
)
end
def test_change_single_value_object
customers(:david).balance = Money.new(100)
customers(:david).save
assert_equal 100, customers(:david).reload.balance.amount
end
def test_immutable_value_objects
customers(:david).balance = Money.new(100)
assert_raise(ActiveSupport::FrozenObjectError) { customers(:david).balance.instance_eval { @amount = 20 } }
end
def test_inferred_mapping
assert_equal "35.544623640962634", customers(:david).gps_location.latitude
assert_equal "-105.9309951055148", customers(:david).gps_location.longitude
customers(:david).gps_location = GpsLocation.new("39x-110")
assert_equal "39", customers(:david).gps_location.latitude
assert_equal "-110", customers(:david).gps_location.longitude
customers(:david).save
customers(:david).reload
assert_equal "39", customers(:david).gps_location.latitude
assert_equal "-110", customers(:david).gps_location.longitude
end
def test_reloaded_instance_refreshes_aggregations
assert_equal "35.544623640962634", customers(:david).gps_location.latitude
assert_equal "-105.9309951055148", customers(:david).gps_location.longitude
Customer.update_all("gps_location = '24x113'")
customers(:david).reload
assert_equal '24x113', customers(:david)['gps_location']
assert_equal GpsLocation.new('24x113'), customers(:david).gps_location
end
def test_gps_equality
assert GpsLocation.new('39x110') == GpsLocation.new('39x110')
end
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_raise(NoMethodError) { customers(:david).balance = nil }
end
def test_allow_nil_address_loaded_when_only_some_attributes_are_nil
customers(:zaphod).address_street = nil
customers(:zaphod).save
customers(:zaphod).reload
assert_kind_of Address, customers(:zaphod).address
assert customers(:zaphod).address.street.nil?
end
def test_nil_assignment_results_in_nil
customers(:david).gps_location = GpsLocation.new('39x111')
assert_not_equal nil, customers(:david).gps_location
customers(:david).gps_location = nil
assert_equal nil, customers(:david).gps_location
end
end
class OverridingAggregationsTest < ActiveRecord::TestCase
class Name; end
class DifferentName; end
class Person < ActiveRecord::Base
composed_of :composed_of, :mapping => %w(person_first_name first_name)
end
class DifferentPerson < Person
composed_of :composed_of, :class_name => 'DifferentName', :mapping => %w(different_person_first_name first_name)
end
def test_composed_of_aggregation_redefinition_reflections_should_differ_and_not_inherited
assert_not_equal Person.reflect_on_aggregation(:composed_of),
DifferentPerson.reflect_on_aggregation(:composed_of)
end
end

View file

@ -1,33 +0,0 @@
require "cases/helper"
require 'active_record/schema'
if ActiveRecord::Base.connection.supports_migrations?
class ActiveRecordSchemaTest < ActiveRecord::TestCase
self.use_transactional_fixtures = false
def setup
@connection = ActiveRecord::Base.connection
end
def teardown
@connection.drop_table :fruits rescue nil
end
def test_schema_define
ActiveRecord::Schema.define(:version => 7) do
create_table :fruits do |t|
t.column :color, :string
t.column :fruit_size, :string # NOTE: "size" is reserved in Oracle
t.column :texture, :string
t.column :flavor, :string
end
end
assert_nothing_raised { @connection.select_all "SELECT * FROM fruits" }
assert_nothing_raised { @connection.select_all "SELECT * FROM schema_migrations" }
assert_equal 7, ActiveRecord::Migrator::current_version
end
end
end

View file

@ -1,412 +0,0 @@
require "cases/helper"
require 'models/developer'
require 'models/project'
require 'models/company'
require 'models/topic'
require 'models/reply'
require 'models/computer'
require 'models/customer'
require 'models/order'
require 'models/post'
require 'models/author'
require 'models/tag'
require 'models/tagging'
require 'models/comment'
require 'models/sponsor'
require 'models/member'
class BelongsToAssociationsTest < ActiveRecord::TestCase
fixtures :accounts, :companies, :developers, :projects, :topics,
:developers_projects, :computers, :authors, :posts, :tags, :taggings, :comments
def test_belongs_to
Client.find(3).firm.name
assert_equal companies(:first_firm).name, Client.find(3).firm.name
assert !Client.find(3).firm.nil?, "Microsoft should have a firm"
end
def test_proxy_assignment
account = Account.find(1)
assert_nothing_raised { account.firm = account.firm }
end
def test_triple_equality
assert Client.find(3).firm === Firm
assert Firm === Client.find(3).firm
end
def test_type_mismatch
assert_raise(ActiveRecord::AssociationTypeMismatch) { Account.find(1).firm = 1 }
assert_raise(ActiveRecord::AssociationTypeMismatch) { Account.find(1).firm = Project.find(1) }
end
def test_natural_assignment
apple = Firm.create("name" => "Apple")
citibank = Account.create("credit_limit" => 10)
citibank.firm = apple
assert_equal apple.id, citibank.firm_id
end
def test_no_unexpected_aliasing
first_firm = companies(:first_firm)
another_firm = companies(:another_firm)
citibank = Account.create("credit_limit" => 10)
citibank.firm = first_firm
original_proxy = citibank.firm
citibank.firm = another_firm
assert_equal first_firm.object_id, original_proxy.target.object_id
assert_equal another_firm.object_id, citibank.firm.target.object_id
end
def test_creating_the_belonging_object
citibank = Account.create("credit_limit" => 10)
apple = citibank.create_firm("name" => "Apple")
assert_equal apple, citibank.firm
citibank.save
citibank.reload
assert_equal apple, citibank.firm
end
def test_building_the_belonging_object
citibank = Account.create("credit_limit" => 10)
apple = citibank.build_firm("name" => "Apple")
citibank.save
assert_equal apple.id, citibank.firm_id
end
def test_natural_assignment_to_nil
client = Client.find(3)
client.firm = nil
client.save
assert_nil client.firm(true)
assert_nil client.client_of
end
def test_with_different_class_name
assert_equal Company.find(1).name, Company.find(3).firm_with_other_name.name
assert_not_nil Company.find(3).firm_with_other_name, "Microsoft should have a firm"
end
def test_with_condition
assert_equal Company.find(1).name, Company.find(3).firm_with_condition.name
assert_not_nil Company.find(3).firm_with_condition, "Microsoft should have a firm"
end
def test_with_select
assert_equal Company.find(2).firm_with_select.attributes.size, 1
assert_equal Company.find(2, :include => :firm_with_select ).firm_with_select.attributes.size, 1
end
def test_belongs_to_counter
debate = Topic.create("title" => "debate")
assert_equal 0, debate.send(:read_attribute, "replies_count"), "No replies yet"
trash = debate.replies.create("title" => "blah!", "content" => "world around!")
assert_equal 1, Topic.find(debate.id).send(:read_attribute, "replies_count"), "First reply created"
trash.destroy
assert_equal 0, Topic.find(debate.id).send(:read_attribute, "replies_count"), "First reply deleted"
end
def test_belongs_to_counter_with_assigning_nil
p = Post.find(1)
c = Comment.find(1)
assert_equal p.id, c.post_id
assert_equal 2, Post.find(p.id).comments.size
c.post = nil
assert_equal 1, Post.find(p.id).comments.size
end
def test_belongs_to_counter_with_reassigning
t1 = Topic.create("title" => "t1")
t2 = Topic.create("title" => "t2")
r1 = Reply.new("title" => "r1", "content" => "r1")
r1.topic = t1
assert r1.save
assert_equal 1, Topic.find(t1.id).replies.size
assert_equal 0, Topic.find(t2.id).replies.size
r1.topic = Topic.find(t2.id)
assert r1.save
assert_equal 0, Topic.find(t1.id).replies.size
assert_equal 1, Topic.find(t2.id).replies.size
r1.topic = nil
assert_equal 0, Topic.find(t1.id).replies.size
assert_equal 0, Topic.find(t2.id).replies.size
r1.topic = t1
assert_equal 1, Topic.find(t1.id).replies.size
assert_equal 0, Topic.find(t2.id).replies.size
r1.destroy
assert_equal 0, Topic.find(t1.id).replies.size
assert_equal 0, Topic.find(t2.id).replies.size
end
def test_belongs_to_counter_after_save
topic = Topic.create!(:title => "monday night")
topic.replies.create!(:title => "re: monday night", :content => "football")
assert_equal 1, Topic.find(topic.id)[:replies_count]
topic.save!
assert_equal 1, Topic.find(topic.id)[:replies_count]
end
def test_belongs_to_counter_after_update_attributes
topic = Topic.create!(:title => "37s")
topic.replies.create!(:title => "re: 37s", :content => "rails")
assert_equal 1, Topic.find(topic.id)[:replies_count]
topic.update_attributes(:title => "37signals")
assert_equal 1, Topic.find(topic.id)[:replies_count]
end
def test_belongs_to_counter_after_save
topic = Topic.create("title" => "monday night")
topic.replies.create("title" => "re: monday night", "content" => "football")
assert_equal 1, Topic.find(topic.id).send(:read_attribute, "replies_count")
topic.save
assert_equal 1, Topic.find(topic.id).send(:read_attribute, "replies_count")
end
def test_belongs_to_counter_after_update_attributes
topic = Topic.create("title" => "37s")
topic.replies.create("title" => "re: 37s", "content" => "rails")
assert_equal 1, Topic.find(topic.id).send(:read_attribute, "replies_count")
topic.update_attributes("title" => "37signals")
assert_equal 1, Topic.find(topic.id).send(:read_attribute, "replies_count")
end
def test_assignment_before_parent_saved
client = Client.find(:first)
apple = Firm.new("name" => "Apple")
client.firm = apple
assert_equal apple, client.firm
assert apple.new_record?
assert client.save
assert apple.save
assert !apple.new_record?
assert_equal apple, client.firm
assert_equal apple, client.firm(true)
end
def test_assignment_before_child_saved
final_cut = Client.new("name" => "Final Cut")
firm = Firm.find(1)
final_cut.firm = firm
assert final_cut.new_record?
assert final_cut.save
assert !final_cut.new_record?
assert !firm.new_record?
assert_equal firm, final_cut.firm
assert_equal firm, final_cut.firm(true)
end
def test_assignment_before_either_saved
final_cut = Client.new("name" => "Final Cut")
apple = Firm.new("name" => "Apple")
final_cut.firm = apple
assert final_cut.new_record?
assert apple.new_record?
assert final_cut.save
assert !final_cut.new_record?
assert !apple.new_record?
assert_equal apple, final_cut.firm
assert_equal apple, final_cut.firm(true)
end
def test_new_record_with_foreign_key_but_no_object
c = Client.new("firm_id" => 1)
assert_equal Firm.find(:first), c.firm_with_basic_id
end
def test_forgetting_the_load_when_foreign_key_enters_late
c = Client.new
assert_nil c.firm_with_basic_id
c.firm_id = 1
assert_equal Firm.find(:first), c.firm_with_basic_id
end
def test_field_name_same_as_foreign_key
computer = Computer.find(1)
assert_not_nil computer.developer, ":foreign key == attribute didn't lock up" # '
end
def test_counter_cache
topic = Topic.create :title => "Zoom-zoom-zoom"
assert_equal 0, topic[:replies_count]
reply = Reply.create(:title => "re: zoom", :content => "speedy quick!")
reply.topic = topic
assert_equal 1, topic.reload[:replies_count]
assert_equal 1, topic.replies.size
topic[:replies_count] = 15
assert_equal 15, topic.replies.size
end
def test_custom_counter_cache
reply = Reply.create(:title => "re: zoom", :content => "speedy quick!")
assert_equal 0, reply[:replies_count]
silly = SillyReply.create(:title => "gaga", :content => "boo-boo")
silly.reply = reply
assert_equal 1, reply.reload[:replies_count]
assert_equal 1, reply.replies.size
reply[:replies_count] = 17
assert_equal 17, reply.replies.size
end
def test_store_two_association_with_one_save
num_orders = Order.count
num_customers = Customer.count
order = Order.new
customer1 = order.billing = Customer.new
customer2 = order.shipping = Customer.new
assert order.save
assert_equal customer1, order.billing
assert_equal customer2, order.shipping
order.reload
assert_equal customer1, order.billing
assert_equal customer2, order.shipping
assert_equal num_orders +1, Order.count
assert_equal num_customers +2, Customer.count
end
def test_store_association_in_two_relations_with_one_save
num_orders = Order.count
num_customers = Customer.count
order = Order.new
customer = order.billing = order.shipping = Customer.new
assert order.save
assert_equal customer, order.billing
assert_equal customer, order.shipping
order.reload
assert_equal customer, order.billing
assert_equal customer, order.shipping
assert_equal num_orders +1, Order.count
assert_equal num_customers +1, Customer.count
end
def test_store_association_in_two_relations_with_one_save_in_existing_object
num_orders = Order.count
num_customers = Customer.count
order = Order.create
customer = order.billing = order.shipping = Customer.new
assert order.save
assert_equal customer, order.billing
assert_equal customer, order.shipping
order.reload
assert_equal customer, order.billing
assert_equal customer, order.shipping
assert_equal num_orders +1, Order.count
assert_equal num_customers +1, Customer.count
end
def test_store_association_in_two_relations_with_one_save_in_existing_object_with_values
num_orders = Order.count
num_customers = Customer.count
order = Order.create
customer = order.billing = order.shipping = Customer.new
assert order.save
assert_equal customer, order.billing
assert_equal customer, order.shipping
order.reload
customer = order.billing = order.shipping = Customer.new
assert order.save
order.reload
assert_equal customer, order.billing
assert_equal customer, order.shipping
assert_equal num_orders +1, Order.count
assert_equal num_customers +2, Customer.count
end
def test_association_assignment_sticks
post = Post.find(:first)
author1, author2 = Author.find(:all, :limit => 2)
assert_not_nil author1
assert_not_nil author2
# make sure the association is loaded
post.author
# set the association by id, directly
post.author_id = author2.id
# save and reload
post.save!
post.reload
# the author id of the post should be the id we set
assert_equal post.author_id, author2.id
end
def test_cant_save_readonly_association
assert_raise(ActiveRecord::ReadOnlyRecord) { companies(:first_client).readonly_firm.save! }
assert companies(:first_client).readonly_firm.readonly?
end
def test_polymorphic_assignment_foreign_type_field_updating
# should update when assigning a saved record
sponsor = Sponsor.new
member = Member.create
sponsor.sponsorable = member
assert_equal "Member", sponsor.sponsorable_type
# should update when assigning a new record
sponsor = Sponsor.new
member = Member.new
sponsor.sponsorable = member
assert_equal "Member", sponsor.sponsorable_type
end
def test_polymorphic_assignment_updates_foreign_id_field_for_new_and_saved_records
sponsor = Sponsor.new
saved_member = Member.create
new_member = Member.new
sponsor.sponsorable = saved_member
assert_equal saved_member.id, sponsor.sponsorable_id
sponsor.sponsorable = new_member
assert_equal nil, sponsor.sponsorable_id
end
end

View file

@ -1,161 +0,0 @@
require "cases/helper"
require 'models/post'
require 'models/comment'
require 'models/author'
require 'models/category'
require 'models/project'
require 'models/developer'
class AssociationCallbacksTest < ActiveRecord::TestCase
fixtures :posts, :authors, :projects, :developers
def setup
@david = authors(:david)
@thinking = posts(:thinking)
@authorless = posts(:authorless)
assert @david.post_log.empty?
end
def test_adding_macro_callbacks
@david.posts_with_callbacks << @thinking
assert_equal ["before_adding#{@thinking.id}", "after_adding#{@thinking.id}"], @david.post_log
@david.posts_with_callbacks << @thinking
assert_equal ["before_adding#{@thinking.id}", "after_adding#{@thinking.id}", "before_adding#{@thinking.id}",
"after_adding#{@thinking.id}"], @david.post_log
end
def test_adding_with_proc_callbacks
@david.posts_with_proc_callbacks << @thinking
assert_equal ["before_adding#{@thinking.id}", "after_adding#{@thinking.id}"], @david.post_log
@david.posts_with_proc_callbacks << @thinking
assert_equal ["before_adding#{@thinking.id}", "after_adding#{@thinking.id}", "before_adding#{@thinking.id}",
"after_adding#{@thinking.id}"], @david.post_log
end
def test_removing_with_macro_callbacks
first_post, second_post = @david.posts_with_callbacks[0, 2]
@david.posts_with_callbacks.delete(first_post)
assert_equal ["before_removing#{first_post.id}", "after_removing#{first_post.id}"], @david.post_log
@david.posts_with_callbacks.delete(second_post)
assert_equal ["before_removing#{first_post.id}", "after_removing#{first_post.id}", "before_removing#{second_post.id}",
"after_removing#{second_post.id}"], @david.post_log
end
def test_removing_with_proc_callbacks
first_post, second_post = @david.posts_with_callbacks[0, 2]
@david.posts_with_proc_callbacks.delete(first_post)
assert_equal ["before_removing#{first_post.id}", "after_removing#{first_post.id}"], @david.post_log
@david.posts_with_proc_callbacks.delete(second_post)
assert_equal ["before_removing#{first_post.id}", "after_removing#{first_post.id}", "before_removing#{second_post.id}",
"after_removing#{second_post.id}"], @david.post_log
end
def test_multiple_callbacks
@david.posts_with_multiple_callbacks << @thinking
assert_equal ["before_adding#{@thinking.id}", "before_adding_proc#{@thinking.id}", "after_adding#{@thinking.id}",
"after_adding_proc#{@thinking.id}"], @david.post_log
@david.posts_with_multiple_callbacks << @thinking
assert_equal ["before_adding#{@thinking.id}", "before_adding_proc#{@thinking.id}", "after_adding#{@thinking.id}",
"after_adding_proc#{@thinking.id}", "before_adding#{@thinking.id}", "before_adding_proc#{@thinking.id}",
"after_adding#{@thinking.id}", "after_adding_proc#{@thinking.id}"], @david.post_log
end
def test_has_many_callbacks_with_create
morten = Author.create :name => "Morten"
post = morten.posts_with_proc_callbacks.create! :title => "Hello", :body => "How are you doing?"
assert_equal ["before_adding<new>", "after_adding#{post.id}"], morten.post_log
end
def test_has_many_callbacks_with_create!
morten = Author.create! :name => "Morten"
post = morten.posts_with_proc_callbacks.create :title => "Hello", :body => "How are you doing?"
assert_equal ["before_adding<new>", "after_adding#{post.id}"], morten.post_log
end
def test_has_many_callbacks_for_save_on_parent
jack = Author.new :name => "Jack"
post = jack.posts_with_callbacks.build :title => "Call me back!", :body => "Before you wake up and after you sleep"
callback_log = ["before_adding<new>", "after_adding#{jack.posts_with_callbacks.first.id}"]
assert_equal callback_log, jack.post_log
assert jack.save
assert_equal 1, jack.posts_with_callbacks.count
assert_equal callback_log, jack.post_log
end
def test_has_and_belongs_to_many_add_callback
david = developers(:david)
ar = projects(:active_record)
assert ar.developers_log.empty?
ar.developers_with_callbacks << david
assert_equal ["before_adding#{david.id}", "after_adding#{david.id}"], ar.developers_log
ar.developers_with_callbacks << david
assert_equal ["before_adding#{david.id}", "after_adding#{david.id}", "before_adding#{david.id}",
"after_adding#{david.id}"], ar.developers_log
end
def test_has_and_belongs_to_many_after_add_called_after_save
ar = projects(:active_record)
assert ar.developers_log.empty?
alice = Developer.new(:name => 'alice')
ar.developers_with_callbacks << alice
assert_equal"after_adding#{alice.id}", ar.developers_log.last
bob = ar.developers_with_callbacks.create(:name => 'bob')
assert_equal "after_adding#{bob.id}", ar.developers_log.last
ar.developers_with_callbacks.build(:name => 'charlie')
assert_equal "after_adding<new>", ar.developers_log.last
end
def test_has_and_belongs_to_many_remove_callback
david = developers(:david)
jamis = developers(:jamis)
activerecord = projects(:active_record)
assert activerecord.developers_log.empty?
activerecord.developers_with_callbacks.delete(david)
assert_equal ["before_removing#{david.id}", "after_removing#{david.id}"], activerecord.developers_log
activerecord.developers_with_callbacks.delete(jamis)
assert_equal ["before_removing#{david.id}", "after_removing#{david.id}", "before_removing#{jamis.id}",
"after_removing#{jamis.id}"], activerecord.developers_log
end
def test_has_and_belongs_to_many_remove_callback_on_clear
activerecord = projects(:active_record)
assert activerecord.developers_log.empty?
if activerecord.developers_with_callbacks.size == 0
activerecord.developers << developers(:david)
activerecord.developers << developers(:jamis)
activerecord.reload
assert activerecord.developers_with_callbacks.size == 2
end
log_array = activerecord.developers_with_callbacks.collect {|d| ["before_removing#{d.id}","after_removing#{d.id}"]}.flatten.sort
assert activerecord.developers_with_callbacks.clear
assert_equal log_array, activerecord.developers_log.sort
end
def test_has_many_and_belongs_to_many_callbacks_for_save_on_parent
project = Project.new :name => "Callbacks"
project.developers_with_callbacks.build :name => "Jack", :salary => 95000
callback_log = ["before_adding<new>", "after_adding<new>"]
assert_equal callback_log, project.developers_log
assert project.save
assert_equal 1, project.developers_with_callbacks.size
assert_equal callback_log, project.developers_log
end
def test_dont_add_if_before_callback_raises_exception
assert !@david.unchangable_posts.include?(@authorless)
begin
@david.unchangable_posts << @authorless
rescue Exception => e
end
assert @david.post_log.empty?
assert !@david.unchangable_posts.include?(@authorless)
@david.reload
assert !@david.unchangable_posts.include?(@authorless)
end
end

View file

@ -1,111 +0,0 @@
require "cases/helper"
require 'models/post'
require 'models/comment'
require 'models/author'
require 'models/category'
require 'models/categorization'
require 'models/company'
require 'models/topic'
require 'models/reply'
class CascadedEagerLoadingTest < ActiveRecord::TestCase
fixtures :authors, :mixins, :companies, :posts, :topics
def test_eager_association_loading_with_cascaded_two_levels
authors = Author.find(:all, :include=>{:posts=>:comments}, :order=>"authors.id")
assert_equal 2, authors.size
assert_equal 5, authors[0].posts.size
assert_equal 1, authors[1].posts.size
assert_equal 9, authors[0].posts.collect{|post| post.comments.size }.inject(0){|sum,i| sum+i}
end
def test_eager_association_loading_with_cascaded_two_levels_and_one_level
authors = Author.find(:all, :include=>[{:posts=>:comments}, :categorizations], :order=>"authors.id")
assert_equal 2, authors.size
assert_equal 5, authors[0].posts.size
assert_equal 1, authors[1].posts.size
assert_equal 9, authors[0].posts.collect{|post| post.comments.size }.inject(0){|sum,i| sum+i}
assert_equal 1, authors[0].categorizations.size
assert_equal 2, authors[1].categorizations.size
end
def test_eager_association_loading_with_cascaded_two_levels_with_two_has_many_associations
authors = Author.find(:all, :include=>{:posts=>[:comments, :categorizations]}, :order=>"authors.id")
assert_equal 2, authors.size
assert_equal 5, authors[0].posts.size
assert_equal 1, authors[1].posts.size
assert_equal 9, authors[0].posts.collect{|post| post.comments.size }.inject(0){|sum,i| sum+i}
end
def test_eager_association_loading_with_cascaded_two_levels_and_self_table_reference
authors = Author.find(:all, :include=>{:posts=>[:comments, :author]}, :order=>"authors.id")
assert_equal 2, authors.size
assert_equal 5, authors[0].posts.size
assert_equal authors(:david).name, authors[0].name
assert_equal [authors(:david).name], authors[0].posts.collect{|post| post.author.name}.uniq
end
def test_eager_association_loading_with_cascaded_two_levels_with_condition
authors = Author.find(:all, :include=>{:posts=>:comments}, :conditions=>"authors.id=1", :order=>"authors.id")
assert_equal 1, authors.size
assert_equal 5, authors[0].posts.size
end
def test_eager_association_loading_with_cascaded_three_levels_by_ping_pong
firms = Firm.find(:all, :include=>{:account=>{:firm=>:account}}, :order=>"companies.id")
assert_equal 2, firms.size
assert_equal firms.first.account, firms.first.account.firm.account
assert_equal companies(:first_firm).account, assert_no_queries { firms.first.account.firm.account }
assert_equal companies(:first_firm).account.firm.account, assert_no_queries { firms.first.account.firm.account }
end
def test_eager_association_loading_with_has_many_sti
topics = Topic.find(:all, :include => :replies, :order => 'topics.id')
first, second, = topics(:first).replies.size, topics(:second).replies.size
assert_no_queries do
assert_equal first, topics[0].replies.size
assert_equal second, topics[1].replies.size
end
end
def test_eager_association_loading_with_belongs_to_sti
replies = Reply.find(:all, :include => :topic, :order => 'topics.id')
assert replies.include?(topics(:second))
assert !replies.include?(topics(:first))
assert_equal topics(:first), assert_no_queries { replies.first.topic }
end
def test_eager_association_loading_with_multiple_stis_and_order
author = Author.find(:first, :include => { :posts => [ :special_comments , :very_special_comment ] }, :order => 'authors.name, comments.body, very_special_comments_posts.body', :conditions => 'posts.id = 4')
assert_equal authors(:david), author
assert_no_queries do
author.posts.first.special_comments
author.posts.first.very_special_comment
end
end
def test_eager_association_loading_of_stis_with_multiple_references
authors = Author.find(:all, :include => { :posts => { :special_comments => { :post => [ :special_comments, :very_special_comment ] } } }, :order => 'comments.body, very_special_comments_posts.body', :conditions => 'posts.id = 4')
assert_equal [authors(:david)], authors
assert_no_queries do
authors.first.posts.first.special_comments.first.post.special_comments
authors.first.posts.first.special_comments.first.post.very_special_comment
end
end
end
require 'models/vertex'
require 'models/edge'
class CascadedEagerLoadingTest < ActiveRecord::TestCase
fixtures :edges, :vertices
def test_eager_association_loading_with_recursive_cascading_four_levels_has_many_through
source = Vertex.find(:first, :include=>{:sinks=>{:sinks=>{:sinks=>:sinks}}}, :order => 'vertices.id')
assert_equal vertices(:vertex_4), assert_no_queries { source.sinks.first.sinks.first.sinks.first }
end
def test_eager_association_loading_with_recursive_cascading_four_levels_has_and_belongs_to_many
sink = Vertex.find(:first, :include=>{:sources=>{:sources=>{:sources=>:sources}}}, :order => 'vertices.id DESC')
assert_equal vertices(:vertex_1), assert_no_queries { sink.sources.first.sources.first.sources.first.sources.first }
end
end

View file

@ -1,83 +0,0 @@
require 'cases/helper'
class ShapeExpression < ActiveRecord::Base
belongs_to :shape, :polymorphic => true
belongs_to :paint, :polymorphic => true
end
class Circle < ActiveRecord::Base
has_many :shape_expressions, :as => :shape
end
class Square < ActiveRecord::Base
has_many :shape_expressions, :as => :shape
end
class Triangle < ActiveRecord::Base
has_many :shape_expressions, :as => :shape
end
class PaintColor < ActiveRecord::Base
has_many :shape_expressions, :as => :paint
belongs_to :non_poly, :foreign_key => "non_poly_one_id", :class_name => "NonPolyOne"
end
class PaintTexture < ActiveRecord::Base
has_many :shape_expressions, :as => :paint
belongs_to :non_poly, :foreign_key => "non_poly_two_id", :class_name => "NonPolyTwo"
end
class NonPolyOne < ActiveRecord::Base
has_many :paint_colors
end
class NonPolyTwo < ActiveRecord::Base
has_many :paint_textures
end
class EagerLoadPolyAssocsTest < ActiveRecord::TestCase
NUM_SIMPLE_OBJS = 50
NUM_SHAPE_EXPRESSIONS = 100
def setup
generate_test_object_graphs
end
def teardown
[Circle, Square, Triangle, PaintColor, PaintTexture,
ShapeExpression, NonPolyOne, NonPolyTwo].each do |c|
c.delete_all
end
end
# meant to be supplied as an ID, never returns 0
def rand_simple
val = (NUM_SIMPLE_OBJS * rand).round
val == 0 ? 1 : val
end
def generate_test_object_graphs
1.upto(NUM_SIMPLE_OBJS) do
[Circle, Square, Triangle, NonPolyOne, NonPolyTwo].map(&:create!)
end
1.upto(NUM_SIMPLE_OBJS) do |i|
PaintColor.create!(:non_poly_one_id => rand_simple)
PaintTexture.create!(:non_poly_two_id => rand_simple)
end
1.upto(NUM_SHAPE_EXPRESSIONS) do |i|
ShapeExpression.create!(:shape_type => [Circle, Square, Triangle].rand.to_s, :shape_id => rand_simple,
:paint_type => [PaintColor, PaintTexture].rand.to_s, :paint_id => rand_simple)
end
end
def test_include_query
res = 0
res = ShapeExpression.find :all, :include => [ :shape, { :paint => :non_poly } ]
assert_equal NUM_SHAPE_EXPRESSIONS, res.size
assert_queries(0) do
res.each do |se|
assert_not_nil se.paint.non_poly, "this is the association that was loading incorrectly before the change"
assert_not_nil se.shape, "just making sure other associations still work"
end
end
end
end

View file

@ -1,145 +0,0 @@
require "cases/helper"
class Virus < ActiveRecord::Base
belongs_to :octopus
end
class Octopus < ActiveRecord::Base
has_one :virus
end
class Pass < ActiveRecord::Base
belongs_to :bus
end
class Bus < ActiveRecord::Base
has_many :passes
end
class Mess < ActiveRecord::Base
has_and_belongs_to_many :crises
end
class Crisis < ActiveRecord::Base
has_and_belongs_to_many :messes
has_many :analyses, :dependent => :destroy
has_many :successes, :through => :analyses
has_many :dresses, :dependent => :destroy
has_many :compresses, :through => :dresses
end
class Analysis < ActiveRecord::Base
belongs_to :crisis
belongs_to :success
end
class Success < ActiveRecord::Base
has_many :analyses, :dependent => :destroy
has_many :crises, :through => :analyses
end
class Dress < ActiveRecord::Base
belongs_to :crisis
has_many :compresses
end
class Compress < ActiveRecord::Base
belongs_to :dress
end
class EagerSingularizationTest < ActiveRecord::TestCase
def setup
if ActiveRecord::Base.connection.supports_migrations?
ActiveRecord::Base.connection.create_table :viri do |t|
t.column :octopus_id, :integer
t.column :species, :string
end
ActiveRecord::Base.connection.create_table :octopi do |t|
t.column :species, :string
end
ActiveRecord::Base.connection.create_table :passes do |t|
t.column :bus_id, :integer
t.column :rides, :integer
end
ActiveRecord::Base.connection.create_table :buses do |t|
t.column :name, :string
end
ActiveRecord::Base.connection.create_table :crises_messes, :id => false do |t|
t.column :crisis_id, :integer
t.column :mess_id, :integer
end
ActiveRecord::Base.connection.create_table :messes do |t|
t.column :name, :string
end
ActiveRecord::Base.connection.create_table :crises do |t|
t.column :name, :string
end
ActiveRecord::Base.connection.create_table :successes do |t|
t.column :name, :string
end
ActiveRecord::Base.connection.create_table :analyses do |t|
t.column :crisis_id, :integer
t.column :success_id, :integer
end
ActiveRecord::Base.connection.create_table :dresses do |t|
t.column :crisis_id, :integer
end
ActiveRecord::Base.connection.create_table :compresses do |t|
t.column :dress_id, :integer
end
@have_tables = true
else
@have_tables = false
end
end
def teardown
ActiveRecord::Base.connection.drop_table :viri
ActiveRecord::Base.connection.drop_table :octopi
ActiveRecord::Base.connection.drop_table :passes
ActiveRecord::Base.connection.drop_table :buses
ActiveRecord::Base.connection.drop_table :crises_messes
ActiveRecord::Base.connection.drop_table :messes
ActiveRecord::Base.connection.drop_table :crises
ActiveRecord::Base.connection.drop_table :successes
ActiveRecord::Base.connection.drop_table :analyses
ActiveRecord::Base.connection.drop_table :dresses
ActiveRecord::Base.connection.drop_table :compresses
end
def test_eager_no_extra_singularization_belongs_to
return unless @have_tables
assert_nothing_raised do
Virus.find(:all, :include => :octopus)
end
end
def test_eager_no_extra_singularization_has_one
return unless @have_tables
assert_nothing_raised do
Octopus.find(:all, :include => :virus)
end
end
def test_eager_no_extra_singularization_has_many
return unless @have_tables
assert_nothing_raised do
Bus.find(:all, :include => :passes)
end
end
def test_eager_no_extra_singularization_has_and_belongs_to_many
return unless @have_tables
assert_nothing_raised do
Crisis.find(:all, :include => :messes)
Mess.find(:all, :include => :crises)
end
end
def test_eager_no_extra_singularization_has_many_through_belongs_to
return unless @have_tables
assert_nothing_raised do
Crisis.find(:all, :include => :successes)
end
end
def test_eager_no_extra_singularization_has_many_through_has_many
return unless @have_tables
assert_nothing_raised do
Crisis.find(:all, :include => :compresses)
end
end
end

View file

@ -1,612 +0,0 @@
require "cases/helper"
require 'models/post'
require 'models/tagging'
require 'models/comment'
require 'models/author'
require 'models/category'
require 'models/company'
require 'models/person'
require 'models/reader'
require 'models/owner'
require 'models/pet'
require 'models/reference'
require 'models/job'
require 'models/subscriber'
require 'models/subscription'
require 'models/book'
class EagerAssociationTest < ActiveRecord::TestCase
fixtures :posts, :comments, :authors, :categories, :categories_posts,
:companies, :accounts, :tags, :taggings, :people, :readers,
:owners, :pets, :author_favorites, :jobs, :references, :subscribers, :subscriptions, :books
def test_loading_with_one_association
posts = Post.find(:all, :include => :comments)
post = posts.find { |p| p.id == 1 }
assert_equal 2, post.comments.size
assert post.comments.include?(comments(:greetings))
post = Post.find(:first, :include => :comments, :conditions => "posts.title = 'Welcome to the weblog'")
assert_equal 2, post.comments.size
assert post.comments.include?(comments(:greetings))
posts = Post.find(:all, :include => :last_comment)
post = posts.find { |p| p.id == 1 }
assert_equal Post.find(1).last_comment, post.last_comment
end
def test_loading_conditions_with_or
posts = authors(:david).posts.find(:all, :include => :comments, :conditions => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE} = 'SpecialComment'")
assert_nil posts.detect { |p| p.author_id != authors(:david).id },
"expected to find only david's posts"
end
def test_with_ordering
list = Post.find(:all, :include => :comments, :order => "posts.id DESC")
[:eager_other, :sti_habtm, :sti_post_and_comments, :sti_comments,
:authorless, :thinking, :welcome
].each_with_index do |post, index|
assert_equal posts(post), list[index]
end
end
def test_with_two_tables_in_from_without_getting_double_quoted
posts = Post.find(:all,
:select => "posts.*",
:from => "authors, posts",
:include => :comments,
:conditions => "posts.author_id = authors.id",
:order => "posts.id"
)
assert_equal 2, posts.first.comments.size
end
def test_loading_with_multiple_associations
posts = Post.find(:all, :include => [ :comments, :author, :categories ], :order => "posts.id")
assert_equal 2, posts.first.comments.size
assert_equal 2, posts.first.categories.size
assert posts.first.comments.include?(comments(:greetings))
end
def test_duplicate_middle_objects
comments = Comment.find :all, :conditions => 'post_id = 1', :include => [:post => :author]
assert_no_queries do
comments.each {|comment| comment.post.author.name}
end
end
def test_including_duplicate_objects_from_belongs_to
popular_post = Post.create!(:title => 'foo', :body => "I like cars!")
comment = popular_post.comments.create!(:body => "lol")
popular_post.readers.create!(:person => people(:michael))
popular_post.readers.create!(:person => people(:david))
readers = Reader.find(:all, :conditions => ["post_id = ?", popular_post.id],
:include => {:post => :comments})
readers.each do |reader|
assert_equal [comment], reader.post.comments
end
end
def test_including_duplicate_objects_from_has_many
car_post = Post.create!(:title => 'foo', :body => "I like cars!")
car_post.categories << categories(:general)
car_post.categories << categories(:technology)
comment = car_post.comments.create!(:body => "hmm")
categories = Category.find(:all, :conditions => ["posts.id=?", car_post.id],
:include => {:posts => :comments})
categories.each do |category|
assert_equal [comment], category.posts[0].comments
end
end
def test_loading_from_an_association
posts = authors(:david).posts.find(:all, :include => :comments, :order => "posts.id")
assert_equal 2, posts.first.comments.size
end
def test_loading_with_no_associations
assert_nil Post.find(posts(:authorless).id, :include => :author).author
end
def test_nested_loading_with_no_associations
assert_nothing_raised do
Post.find(posts(:authorless).id, :include => {:author => :author_addresss})
end
end
def test_eager_association_loading_with_belongs_to_and_foreign_keys
pets = Pet.find(:all, :include => :owner)
assert_equal 3, pets.length
end
def test_eager_association_loading_with_belongs_to
comments = Comment.find(:all, :include => :post)
assert_equal 10, comments.length
titles = comments.map { |c| c.post.title }
assert titles.include?(posts(:welcome).title)
assert titles.include?(posts(:sti_post_and_comments).title)
end
def test_eager_association_loading_with_belongs_to_and_limit
comments = Comment.find(:all, :include => :post, :limit => 5, :order => 'comments.id')
assert_equal 5, comments.length
assert_equal [1,2,3,5,6], comments.collect { |c| c.id }
end
def test_eager_association_loading_with_belongs_to_and_limit_and_conditions
comments = Comment.find(:all, :include => :post, :conditions => 'post_id = 4', :limit => 3, :order => 'comments.id')
assert_equal 3, comments.length
assert_equal [5,6,7], comments.collect { |c| c.id }
end
def test_eager_association_loading_with_belongs_to_and_limit_and_offset
comments = Comment.find(:all, :include => :post, :limit => 3, :offset => 2, :order => 'comments.id')
assert_equal 3, comments.length
assert_equal [3,5,6], comments.collect { |c| c.id }
end
def test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_conditions
comments = Comment.find(:all, :include => :post, :conditions => 'post_id = 4', :limit => 3, :offset => 1, :order => 'comments.id')
assert_equal 3, comments.length
assert_equal [6,7,8], comments.collect { |c| c.id }
end
def test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_conditions_array
comments = Comment.find(:all, :include => :post, :conditions => ['post_id = ?',4], :limit => 3, :offset => 1, :order => 'comments.id')
assert_equal 3, comments.length
assert_equal [6,7,8], comments.collect { |c| c.id }
end
def test_eager_association_loading_with_belongs_to_and_conditions_string_with_unquoted_table_name
assert_nothing_raised do
Comment.find(:all, :include => :post, :conditions => ['posts.id = ?',4])
end
end
def test_eager_association_loading_with_belongs_to_and_conditions_string_with_quoted_table_name
quoted_posts_id= Comment.connection.quote_table_name('posts') + '.' + Comment.connection.quote_column_name('id')
assert_nothing_raised do
Comment.find(:all, :include => :post, :conditions => ["#{quoted_posts_id} = ?",4])
end
end
def test_eager_association_loading_with_belongs_to_and_order_string_with_unquoted_table_name
assert_nothing_raised do
Comment.find(:all, :include => :post, :order => 'posts.id')
end
end
def test_eager_association_loading_with_belongs_to_and_order_string_with_quoted_table_name
quoted_posts_id= Comment.connection.quote_table_name('posts') + '.' + Comment.connection.quote_column_name('id')
assert_nothing_raised do
Comment.find(:all, :include => :post, :order => quoted_posts_id)
end
end
def test_eager_association_loading_with_belongs_to_and_limit_and_multiple_associations
posts = Post.find(:all, :include => [:author, :very_special_comment], :limit => 1, :order => 'posts.id')
assert_equal 1, posts.length
assert_equal [1], posts.collect { |p| p.id }
end
def test_eager_association_loading_with_belongs_to_and_limit_and_offset_and_multiple_associations
posts = Post.find(:all, :include => [:author, :very_special_comment], :limit => 1, :offset => 1, :order => 'posts.id')
assert_equal 1, posts.length
assert_equal [2], posts.collect { |p| p.id }
end
def test_eager_association_loading_with_belongs_to_inferred_foreign_key_from_association_name
author_favorite = AuthorFavorite.find(:first, :include => :favorite_author)
assert_equal authors(:mary), assert_no_queries { author_favorite.favorite_author }
end
def test_eager_load_belongs_to_quotes_table_and_column_names
job = Job.find jobs(:unicyclist).id, :include => :ideal_reference
references(:michael_unicyclist)
assert_no_queries{ assert_equal references(:michael_unicyclist), job.ideal_reference}
end
def test_eager_load_has_one_quotes_table_and_column_names
michael = Person.find(people(:michael), :include => :favourite_reference)
references(:michael_unicyclist)
assert_no_queries{ assert_equal references(:michael_unicyclist), michael.favourite_reference}
end
def test_eager_load_has_many_quotes_table_and_column_names
michael = Person.find(people(:michael), :include => :references)
references(:michael_magician,:michael_unicyclist)
assert_no_queries{ assert_equal references(:michael_magician,:michael_unicyclist), michael.references.sort_by(&:id) }
end
def test_eager_load_has_many_through_quotes_table_and_column_names
michael = Person.find(people(:michael), :include => :jobs)
jobs(:magician, :unicyclist)
assert_no_queries{ assert_equal jobs(:unicyclist, :magician), michael.jobs.sort_by(&:id) }
end
def test_eager_load_has_many_with_string_keys
subscriptions = subscriptions(:webster_awdr, :webster_rfr)
subscriber =Subscriber.find(subscribers(:second).id, :include => :subscriptions)
assert_equal subscriptions, subscriber.subscriptions.sort_by(&:id)
end
def test_eager_load_has_many_through_with_string_keys
books = books(:awdr, :rfr)
subscriber = Subscriber.find(subscribers(:second).id, :include => :books)
assert_equal books, subscriber.books.sort_by(&:id)
end
def test_eager_load_belongs_to_with_string_keys
subscriber = subscribers(:second)
subscription = Subscription.find(subscriptions(:webster_awdr).id, :include => :subscriber)
assert_equal subscriber, subscription.subscriber
end
def test_eager_association_loading_with_explicit_join
posts = Post.find(:all, :include => :comments, :joins => "INNER JOIN authors ON posts.author_id = authors.id AND authors.name = 'Mary'", :limit => 1, :order => 'author_id')
assert_equal 1, posts.length
end
def test_eager_with_has_many_through
posts_with_comments = people(:michael).posts.find(:all, :include => :comments)
posts_with_author = people(:michael).posts.find(:all, :include => :author )
posts_with_comments_and_author = people(:michael).posts.find(:all, :include => [ :comments, :author ])
assert_equal 2, posts_with_comments.inject(0) { |sum, post| sum += post.comments.size }
assert_equal authors(:david), assert_no_queries { posts_with_author.first.author }
assert_equal authors(:david), assert_no_queries { posts_with_comments_and_author.first.author }
end
def test_eager_with_has_many_through_an_sti_join_model
author = Author.find(:first, :include => :special_post_comments, :order => 'authors.id')
assert_equal [comments(:does_it_hurt)], assert_no_queries { author.special_post_comments }
end
def test_eager_with_has_many_through_an_sti_join_model_with_conditions_on_both
author = Author.find(:first, :include => :special_nonexistant_post_comments, :order => 'authors.id')
assert_equal [], author.special_nonexistant_post_comments
end
def test_eager_with_has_many_through_join_model_with_conditions
assert_equal Author.find(:first, :include => :hello_post_comments,
:order => 'authors.id').hello_post_comments.sort_by(&:id),
Author.find(:first, :order => 'authors.id').hello_post_comments.sort_by(&:id)
end
def test_eager_with_has_many_through_join_model_with_conditions_on_top_level
assert_equal comments(:more_greetings), Author.find(authors(:david).id, :include => :comments_with_order_and_conditions).comments_with_order_and_conditions.first
end
def test_eager_with_has_many_through_join_model_with_include
author_comments = Author.find(authors(:david).id, :include => :comments_with_include).comments_with_include.to_a
assert_no_queries do
author_comments.first.post.title
end
end
def test_eager_with_has_many_and_limit
posts = Post.find(:all, :order => 'posts.id asc', :include => [ :author, :comments ], :limit => 2)
assert_equal 2, posts.size
assert_equal 3, posts.inject(0) { |sum, post| sum += post.comments.size }
end
def test_eager_with_has_many_and_limit_and_conditions
if current_adapter?(:OpenBaseAdapter)
posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => "FETCHBLOB(posts.body) = 'hello'", :order => "posts.id")
else
posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => "posts.body = 'hello'", :order => "posts.id")
end
assert_equal 2, posts.size
assert_equal [4,5], posts.collect { |p| p.id }
end
def test_eager_with_has_many_and_limit_and_conditions_array
if current_adapter?(:OpenBaseAdapter)
posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => [ "FETCHBLOB(posts.body) = ?", 'hello' ], :order => "posts.id")
else
posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => [ "posts.body = ?", 'hello' ], :order => "posts.id")
end
assert_equal 2, posts.size
assert_equal [4,5], posts.collect { |p| p.id }
end
def test_eager_with_has_many_and_limit_and_conditions_array_on_the_eagers
posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => [ "authors.name = ?", 'David' ])
assert_equal 2, posts.size
count = Post.count(:include => [ :author, :comments ], :limit => 2, :conditions => [ "authors.name = ?", 'David' ])
assert_equal count, posts.size
end
def test_eager_with_has_many_and_limit_ond_high_offset
posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :offset => 10, :conditions => [ "authors.name = ?", 'David' ])
assert_equal 0, posts.size
end
def test_count_eager_with_has_many_and_limit_ond_high_offset
posts = Post.count(:all, :include => [ :author, :comments ], :limit => 2, :offset => 10, :conditions => [ "authors.name = ?", 'David' ])
assert_equal 0, posts
end
def test_eager_with_has_many_and_limit_with_no_results
posts = Post.find(:all, :include => [ :author, :comments ], :limit => 2, :conditions => "posts.title = 'magic forest'")
assert_equal 0, posts.size
end
def test_eager_count_performed_on_a_has_many_association_with_multi_table_conditional
author = authors(:david)
author_posts_without_comments = author.posts.select { |post| post.comments.blank? }
assert_equal author_posts_without_comments.size, author.posts.count(:all, :include => :comments, :conditions => 'comments.id is null')
end
def test_eager_count_performed_on_a_has_many_through_association_with_multi_table_conditional
person = people(:michael)
person_posts_without_comments = person.posts.select { |post| post.comments.blank? }
assert_equal person_posts_without_comments.size, person.posts_with_no_comments.count
end
def test_eager_with_has_and_belongs_to_many_and_limit
posts = Post.find(:all, :include => :categories, :order => "posts.id", :limit => 3)
assert_equal 3, posts.size
assert_equal 2, posts[0].categories.size
assert_equal 1, posts[1].categories.size
assert_equal 0, posts[2].categories.size
assert posts[0].categories.include?(categories(:technology))
assert posts[1].categories.include?(categories(:general))
end
def test_eager_with_has_many_and_limit_and_conditions_on_the_eagers
posts = authors(:david).posts.find(:all,
:include => :comments,
:conditions => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment'",
:limit => 2
)
assert_equal 2, posts.size
count = Post.count(
:include => [ :comments, :author ],
:conditions => "authors.name = 'David' AND (comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment')",
:limit => 2
)
assert_equal count, posts.size
end
def test_eager_with_has_many_and_limit_and_scoped_conditions_on_the_eagers
posts = nil
Post.with_scope(:find => {
:include => :comments,
:conditions => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment'"
}) do
posts = authors(:david).posts.find(:all, :limit => 2)
assert_equal 2, posts.size
end
Post.with_scope(:find => {
:include => [ :comments, :author ],
:conditions => "authors.name = 'David' AND (comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment')"
}) do
count = Post.count(:limit => 2)
assert_equal count, posts.size
end
end
def test_eager_with_has_many_and_limit_and_scoped_and_explicit_conditions_on_the_eagers
Post.with_scope(:find => { :conditions => "1=1" }) do
posts = authors(:david).posts.find(:all,
:include => :comments,
:conditions => "comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment'",
:limit => 2
)
assert_equal 2, posts.size
count = Post.count(
:include => [ :comments, :author ],
:conditions => "authors.name = 'David' AND (comments.body like 'Normal%' OR comments.#{QUOTED_TYPE}= 'SpecialComment')",
:limit => 2
)
assert_equal count, posts.size
end
end
def test_eager_with_scoped_order_using_association_limiting_without_explicit_scope
posts_with_explicit_order = Post.find(:all, :conditions => 'comments.id is not null', :include => :comments, :order => 'posts.id DESC', :limit => 2)
posts_with_scoped_order = Post.with_scope(:find => {:order => 'posts.id DESC'}) do
Post.find(:all, :conditions => 'comments.id is not null', :include => :comments, :limit => 2)
end
assert_equal posts_with_explicit_order, posts_with_scoped_order
end
def test_eager_association_loading_with_habtm
posts = Post.find(:all, :include => :categories, :order => "posts.id")
assert_equal 2, posts[0].categories.size
assert_equal 1, posts[1].categories.size
assert_equal 0, posts[2].categories.size
assert posts[0].categories.include?(categories(:technology))
assert posts[1].categories.include?(categories(:general))
end
def test_eager_with_inheritance
posts = SpecialPost.find(:all, :include => [ :comments ])
end
def test_eager_has_one_with_association_inheritance
post = Post.find(4, :include => [ :very_special_comment ])
assert_equal "VerySpecialComment", post.very_special_comment.class.to_s
end
def test_eager_has_many_with_association_inheritance
post = Post.find(4, :include => [ :special_comments ])
post.special_comments.each do |special_comment|
assert_equal "SpecialComment", special_comment.class.to_s
end
end
def test_eager_habtm_with_association_inheritance
post = Post.find(6, :include => [ :special_categories ])
assert_equal 1, post.special_categories.size
post.special_categories.each do |special_category|
assert_equal "SpecialCategory", special_category.class.to_s
end
end
def test_eager_with_has_one_dependent_does_not_destroy_dependent
assert_not_nil companies(:first_firm).account
f = Firm.find(:first, :include => :account,
:conditions => ["companies.name = ?", "37signals"])
assert_not_nil f.account
assert_equal companies(:first_firm, :reload).account, f.account
end
def test_eager_with_multi_table_conditional_properly_counts_the_records_when_using_size
author = authors(:david)
posts_with_no_comments = author.posts.select { |post| post.comments.blank? }
assert_equal posts_with_no_comments.size, author.posts_with_no_comments.size
assert_equal posts_with_no_comments, author.posts_with_no_comments
end
def test_eager_with_invalid_association_reference
assert_raises(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
post = Post.find(6, :include=> :monkeys )
}
assert_raises(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
post = Post.find(6, :include=>[ :monkeys ])
}
assert_raises(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") {
post = Post.find(6, :include=>[ 'monkeys' ])
}
assert_raises(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys, :elephants") {
post = Post.find(6, :include=>[ :monkeys, :elephants ])
}
end
def find_all_ordered(className, include=nil)
className.find(:all, :order=>"#{className.table_name}.#{className.primary_key}", :include=>include)
end
def test_limited_eager_with_order
assert_equal posts(:thinking, :sti_comments), Post.find(:all, :include => [:author, :comments], :conditions => "authors.name = 'David'", :order => 'UPPER(posts.title)', :limit => 2, :offset => 1)
assert_equal posts(:sti_post_and_comments, :sti_comments), Post.find(:all, :include => [:author, :comments], :conditions => "authors.name = 'David'", :order => 'UPPER(posts.title) DESC', :limit => 2, :offset => 1)
end
def test_limited_eager_with_multiple_order_columns
assert_equal posts(:thinking, :sti_comments), Post.find(:all, :include => [:author, :comments], :conditions => "authors.name = 'David'", :order => 'UPPER(posts.title), posts.id', :limit => 2, :offset => 1)
assert_equal posts(:sti_post_and_comments, :sti_comments), Post.find(:all, :include => [:author, :comments], :conditions => "authors.name = 'David'", :order => 'UPPER(posts.title) DESC, posts.id', :limit => 2, :offset => 1)
end
def test_preload_with_interpolation
assert_equal [comments(:greetings)], Post.find(posts(:welcome).id, :include => :comments_with_interpolated_conditions).comments_with_interpolated_conditions
end
def test_polymorphic_type_condition
post = Post.find(posts(:thinking).id, :include => :taggings)
assert post.taggings.include?(taggings(:thinking_general))
post = SpecialPost.find(posts(:thinking).id, :include => :taggings)
assert post.taggings.include?(taggings(:thinking_general))
end
def test_eager_with_multiple_associations_with_same_table_has_many_and_habtm
# Eager includes of has many and habtm associations aren't necessarily sorted in the same way
def assert_equal_after_sort(item1, item2, item3 = nil)
assert_equal(item1.sort{|a,b| a.id <=> b.id}, item2.sort{|a,b| a.id <=> b.id})
assert_equal(item3.sort{|a,b| a.id <=> b.id}, item2.sort{|a,b| a.id <=> b.id}) if item3
end
# Test regular association, association with conditions, association with
# STI, and association with conditions assured not to be true
post_types = [:posts, :other_posts, :special_posts]
# test both has_many and has_and_belongs_to_many
[Author, Category].each do |className|
d1 = find_all_ordered(className)
# test including all post types at once
d2 = find_all_ordered(className, post_types)
d1.each_index do |i|
assert_equal(d1[i], d2[i])
assert_equal_after_sort(d1[i].posts, d2[i].posts)
post_types[1..-1].each do |post_type|
# test including post_types together
d3 = find_all_ordered(className, [:posts, post_type])
assert_equal(d1[i], d3[i])
assert_equal_after_sort(d1[i].posts, d3[i].posts)
assert_equal_after_sort(d1[i].send(post_type), d2[i].send(post_type), d3[i].send(post_type))
end
end
end
end
def test_eager_with_multiple_associations_with_same_table_has_one
d1 = find_all_ordered(Firm)
d2 = find_all_ordered(Firm, :account)
d1.each_index do |i|
assert_equal(d1[i], d2[i])
assert_equal(d1[i].account, d2[i].account)
end
end
def test_eager_with_multiple_associations_with_same_table_belongs_to
firm_types = [:firm, :firm_with_basic_id, :firm_with_other_name, :firm_with_condition]
d1 = find_all_ordered(Client)
d2 = find_all_ordered(Client, firm_types)
d1.each_index do |i|
assert_equal(d1[i], d2[i])
firm_types.each { |type| assert_equal(d1[i].send(type), d2[i].send(type)) }
end
end
def test_eager_with_valid_association_as_string_not_symbol
assert_nothing_raised { Post.find(:all, :include => 'comments') }
end
def test_preconfigured_includes_with_belongs_to
author = posts(:welcome).author_with_posts
assert_no_queries {assert_equal 5, author.posts.size}
end
def test_preconfigured_includes_with_has_one
comment = posts(:sti_comments).very_special_comment_with_post
assert_no_queries {assert_equal posts(:sti_comments), comment.post}
end
def test_preconfigured_includes_with_has_many
posts = authors(:david).posts_with_comments
one = posts.detect { |p| p.id == 1 }
assert_no_queries do
assert_equal 5, posts.size
assert_equal 2, one.comments.size
end
end
def test_preconfigured_includes_with_habtm
posts = authors(:david).posts_with_categories
one = posts.detect { |p| p.id == 1 }
assert_no_queries do
assert_equal 5, posts.size
assert_equal 2, one.categories.size
end
end
def test_preconfigured_includes_with_has_many_and_habtm
posts = authors(:david).posts_with_comments_and_categories
one = posts.detect { |p| p.id == 1 }
assert_no_queries do
assert_equal 5, posts.size
assert_equal 2, one.comments.size
assert_equal 2, one.categories.size
end
end
def test_count_with_include
if current_adapter?(:SQLServerAdapter, :SybaseAdapter)
assert_equal 3, authors(:david).posts_with_comments.count(:conditions => "len(comments.body) > 15")
elsif current_adapter?(:OpenBaseAdapter)
assert_equal 3, authors(:david).posts_with_comments.count(:conditions => "length(FETCHBLOB(comments.body)) > 15")
else
assert_equal 3, authors(:david).posts_with_comments.count(:conditions => "length(comments.body) > 15")
end
end
def test_load_with_sti_sharing_association
assert_queries(2) do #should not do 1 query per subclass
Comment.find :all, :include => :post
end
end
end

View file

@ -1,47 +0,0 @@
require "cases/helper"
require 'models/post'
require 'models/comment'
require 'models/project'
require 'models/developer'
class AssociationsExtensionsTest < ActiveRecord::TestCase
fixtures :projects, :developers, :developers_projects, :comments, :posts
def test_extension_on_has_many
assert_equal comments(:more_greetings), posts(:welcome).comments.find_most_recent
end
def test_extension_on_habtm
assert_equal projects(:action_controller), developers(:david).projects.find_most_recent
end
def test_named_extension_on_habtm
assert_equal projects(:action_controller), developers(:david).projects_extended_by_name.find_most_recent
end
def test_named_two_extensions_on_habtm
assert_equal projects(:action_controller), developers(:david).projects_extended_by_name_twice.find_most_recent
assert_equal projects(:active_record), developers(:david).projects_extended_by_name_twice.find_least_recent
end
def test_named_extension_and_block_on_habtm
assert_equal projects(:action_controller), developers(:david).projects_extended_by_name_and_block.find_most_recent
assert_equal projects(:active_record), developers(:david).projects_extended_by_name_and_block.find_least_recent
end
def test_marshalling_extensions
david = developers(:david)
assert_equal projects(:action_controller), david.projects.find_most_recent
david = Marshal.load(Marshal.dump(david))
assert_equal projects(:action_controller), david.projects.find_most_recent
end
def test_marshalling_named_extensions
david = developers(:david)
assert_equal projects(:action_controller), david.projects_extended_by_name.find_most_recent
david = Marshal.load(Marshal.dump(david))
assert_equal projects(:action_controller), david.projects_extended_by_name.find_most_recent
end
end

View file

@ -1,684 +0,0 @@
require "cases/helper"
require 'models/developer'
require 'models/project'
require 'models/company'
require 'models/topic'
require 'models/reply'
require 'models/computer'
require 'models/customer'
require 'models/order'
require 'models/categorization'
require 'models/category'
require 'models/post'
require 'models/author'
require 'models/comment'
require 'models/tag'
require 'models/tagging'
require 'models/person'
require 'models/reader'
require 'models/parrot'
require 'models/pirate'
require 'models/treasure'
require 'models/price_estimate'
require 'models/club'
require 'models/member'
require 'models/membership'
require 'models/sponsor'
class ProjectWithAfterCreateHook < ActiveRecord::Base
set_table_name 'projects'
has_and_belongs_to_many :developers,
:class_name => "DeveloperForProjectWithAfterCreateHook",
:join_table => "developers_projects",
:foreign_key => "project_id",
:association_foreign_key => "developer_id"
after_create :add_david
def add_david
david = DeveloperForProjectWithAfterCreateHook.find_by_name('David')
david.projects << self
end
end
class DeveloperForProjectWithAfterCreateHook < ActiveRecord::Base
set_table_name 'developers'
has_and_belongs_to_many :projects,
:class_name => "ProjectWithAfterCreateHook",
:join_table => "developers_projects",
:association_foreign_key => "project_id",
:foreign_key => "developer_id"
end
class ProjectWithSymbolsForKeys < ActiveRecord::Base
set_table_name 'projects'
has_and_belongs_to_many :developers,
:class_name => "DeveloperWithSymbolsForKeys",
:join_table => :developers_projects,
:foreign_key => :project_id,
:association_foreign_key => "developer_id"
end
class DeveloperWithSymbolsForKeys < ActiveRecord::Base
set_table_name 'developers'
has_and_belongs_to_many :projects,
:class_name => "ProjectWithSymbolsForKeys",
:join_table => :developers_projects,
:association_foreign_key => :project_id,
:foreign_key => "developer_id"
end
class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
fixtures :accounts, :companies, :categories, :posts, :categories_posts, :developers, :projects, :developers_projects,
:parrots, :pirates, :treasures, :price_estimates
def test_has_and_belongs_to_many
david = Developer.find(1)
assert !david.projects.empty?
assert_equal 2, david.projects.size
active_record = Project.find(1)
assert !active_record.developers.empty?
assert_equal 3, active_record.developers.size
assert active_record.developers.include?(david)
end
def test_triple_equality
assert !(Array === Developer.find(1).projects)
assert Developer.find(1).projects === Array
end
def test_adding_single
jamis = Developer.find(2)
jamis.projects.reload # causing the collection to load
action_controller = Project.find(2)
assert_equal 1, jamis.projects.size
assert_equal 1, action_controller.developers.size
jamis.projects << action_controller
assert_equal 2, jamis.projects.size
assert_equal 2, jamis.projects(true).size
assert_equal 2, action_controller.developers(true).size
end
def test_adding_type_mismatch
jamis = Developer.find(2)
assert_raise(ActiveRecord::AssociationTypeMismatch) { jamis.projects << nil }
assert_raise(ActiveRecord::AssociationTypeMismatch) { jamis.projects << 1 }
end
def test_adding_from_the_project
jamis = Developer.find(2)
action_controller = Project.find(2)
action_controller.developers.reload
assert_equal 1, jamis.projects.size
assert_equal 1, action_controller.developers.size
action_controller.developers << jamis
assert_equal 2, jamis.projects(true).size
assert_equal 2, action_controller.developers.size
assert_equal 2, action_controller.developers(true).size
end
def test_adding_from_the_project_fixed_timestamp
jamis = Developer.find(2)
action_controller = Project.find(2)
action_controller.developers.reload
assert_equal 1, jamis.projects.size
assert_equal 1, action_controller.developers.size
updated_at = jamis.updated_at
action_controller.developers << jamis
assert_equal updated_at, jamis.updated_at
assert_equal 2, jamis.projects(true).size
assert_equal 2, action_controller.developers.size
assert_equal 2, action_controller.developers(true).size
end
def test_adding_multiple
aredridel = Developer.new("name" => "Aredridel")
aredridel.save
aredridel.projects.reload
aredridel.projects.push(Project.find(1), Project.find(2))
assert_equal 2, aredridel.projects.size
assert_equal 2, aredridel.projects(true).size
end
def test_adding_a_collection
aredridel = Developer.new("name" => "Aredridel")
aredridel.save
aredridel.projects.reload
aredridel.projects.concat([Project.find(1), Project.find(2)])
assert_equal 2, aredridel.projects.size
assert_equal 2, aredridel.projects(true).size
end
def test_adding_uses_default_values_on_join_table
ac = projects(:action_controller)
assert !developers(:jamis).projects.include?(ac)
developers(:jamis).projects << ac
assert developers(:jamis, :reload).projects.include?(ac)
project = developers(:jamis).projects.detect { |p| p == ac }
assert_equal 1, project.access_level.to_i
end
def test_habtm_attribute_access_and_respond_to
project = developers(:jamis).projects[0]
assert project.has_attribute?("name")
assert project.has_attribute?("joined_on")
assert project.has_attribute?("access_level")
assert project.respond_to?("name")
assert project.respond_to?("name=")
assert project.respond_to?("name?")
assert project.respond_to?("joined_on")
# given that the 'join attribute' won't be persisted, I don't
# think we should define the mutators
#assert project.respond_to?("joined_on=")
assert project.respond_to?("joined_on?")
assert project.respond_to?("access_level")
#assert project.respond_to?("access_level=")
assert project.respond_to?("access_level?")
end
def test_habtm_adding_before_save
no_of_devels = Developer.count
no_of_projects = Project.count
aredridel = Developer.new("name" => "Aredridel")
aredridel.projects.concat([Project.find(1), p = Project.new("name" => "Projekt")])
assert aredridel.new_record?
assert p.new_record?
assert aredridel.save
assert !aredridel.new_record?
assert_equal no_of_devels+1, Developer.count
assert_equal no_of_projects+1, Project.count
assert_equal 2, aredridel.projects.size
assert_equal 2, aredridel.projects(true).size
end
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}") }.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
assert_equal developers, new_project.developers
end
def test_habtm_unique_order_preserved
assert_equal developers(:poor_jamis, :jamis, :david), projects(:active_record).non_unique_developers
assert_equal developers(:poor_jamis, :jamis, :david), projects(:active_record).developers
end
def test_build
devel = Developer.find(1)
proj = assert_no_queries { devel.projects.build("name" => "Projekt") }
assert !devel.projects.loaded?
assert_equal devel.projects.last, proj
assert devel.projects.loaded?
assert proj.new_record?
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
devel = Developer.find(1)
proj = devel.projects.create("name" => "Projekt")
assert !devel.projects.loaded?
assert_equal devel.projects.last, proj
assert devel.projects.loaded?
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.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_creation_respects_hash_condition
post = categories(:general).post_with_conditions.build(:body => '')
assert post.save
assert_equal 'Yet Another Testing Title', post.title
another_post = categories(:general).post_with_conditions.create(:body => '')
assert !another_post.new_record?
assert_equal 'Yet Another Testing Title', another_post.title
end
def test_uniq_after_the_fact
dev = developers(:jamis)
dev.projects << projects(:active_record)
dev.projects << projects(:active_record)
assert_equal 3, dev.projects.size
assert_equal 1, dev.projects.uniq.size
end
def test_uniq_before_the_fact
projects(:active_record).developers << developers(:jamis)
projects(:active_record).developers << developers(:david)
assert_equal 3, projects(:active_record, :reload).developers.size
end
def test_deleting
david = Developer.find(1)
active_record = Project.find(1)
david.projects.reload
assert_equal 2, david.projects.size
assert_equal 3, active_record.developers.size
david.projects.delete(active_record)
assert_equal 1, david.projects.size
assert_equal 1, david.projects(true).size
assert_equal 2, active_record.developers(true).size
end
def test_deleting_array
david = Developer.find(1)
david.projects.reload
david.projects.delete(Project.find(:all))
assert_equal 0, david.projects.size
assert_equal 0, david.projects(true).size
end
def test_deleting_with_sql
david = Developer.find(1)
active_record = Project.find(1)
active_record.developers.reload
assert_equal 3, active_record.developers_by_sql.size
active_record.developers_by_sql.delete(david)
assert_equal 2, active_record.developers_by_sql(true).size
end
def test_deleting_array_with_sql
active_record = Project.find(1)
active_record.developers.reload
assert_equal 3, active_record.developers_by_sql.size
active_record.developers_by_sql.delete(Developer.find(:all))
assert_equal 0, active_record.developers_by_sql(true).size
end
def test_deleting_all
david = Developer.find(1)
david.projects.reload
david.projects.clear
assert_equal 0, david.projects.size
assert_equal 0, david.projects(true).size
end
def test_removing_associations_on_destroy
david = DeveloperWithBeforeDestroyRaise.find(1)
assert !david.projects.empty?
assert_nothing_raised { david.destroy }
assert david.projects.empty?
assert DeveloperWithBeforeDestroyRaise.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = 1").empty?
end
def test_additional_columns_from_join_table
assert_date_from_db Date.new(2004, 10, 10), Developer.find(1).projects.first.joined_on.to_date
end
def test_destroy_all
david = Developer.find(1)
david.projects.reload
assert !david.projects.empty?
david.projects.destroy_all
assert david.projects.empty?
assert david.projects(true).empty?
end
def test_deprecated_push_with_attributes_was_removed
jamis = developers(:jamis)
assert_raise(NoMethodError) do
jamis.projects.push_with_attributes(projects(:action_controller), :joined_on => Date.today)
end
end
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
assert_equal 2, projects(:active_record, :reload).developers.size
end
def test_find_in_association
# Using sql
assert_equal developers(:david), projects(:active_record).developers.find(developers(:david).id), "SQL find"
# Using ruby
active_record = projects(:active_record)
active_record.developers.reload
assert_equal developers(:david), active_record.developers.find(developers(:david).id), "Ruby find"
end
def test_include_uses_array_include_after_loaded
project = projects(:active_record)
project.developers.class # force load target
developer = project.developers.first
assert_no_queries do
assert project.developers.loaded?
assert project.developers.include?(developer)
end
end
def test_include_checks_if_record_exists_if_target_not_loaded
project = projects(:active_record)
developer = project.developers.first
project.reload
assert ! project.developers.loaded?
assert_queries(1) do
assert project.developers.include?(developer)
end
assert ! project.developers.loaded?
end
def test_include_returns_false_for_non_matching_record_to_verify_scoping
project = projects(:active_record)
developer = Developer.create :name => "Bryan", :salary => 50_000
assert ! project.developers.loaded?
assert ! project.developers.include?(developer)
end
def test_find_in_association_with_custom_finder_sql
assert_equal developers(:david), projects(:active_record).developers_with_finder_sql.find(developers(:david).id), "SQL find"
active_record = projects(:active_record)
active_record.developers_with_finder_sql.reload
assert_equal developers(:david), active_record.developers_with_finder_sql.find(developers(:david).id), "Ruby find"
end
def test_find_in_association_with_custom_finder_sql_and_string_id
assert_equal developers(:david), projects(:active_record).developers_with_finder_sql.find(developers(:david).id.to_s), "SQL find"
end
def test_find_with_merged_options
assert_equal 1, projects(:active_record).limited_developers.size
assert_equal 1, projects(:active_record).limited_developers.find(:all).size
assert_equal 3, projects(:active_record).limited_developers.find(:all, :limit => nil).size
end
def test_dynamic_find_should_respect_association_order
# Developers are ordered 'name DESC, id DESC'
low_id_jamis = developers(:jamis)
middle_id_jamis = developers(:poor_jamis)
high_id_jamis = projects(:active_record).developers.create(:name => 'Jamis')
assert_equal high_id_jamis, projects(:active_record).developers.find(:first, :conditions => "name = 'Jamis'")
assert_equal high_id_jamis, projects(:active_record).developers.find_by_name('Jamis')
end
def test_dynamic_find_order_should_override_association_order
# Developers are ordered 'name DESC, id DESC'
low_id_jamis = developers(:jamis)
middle_id_jamis = developers(:poor_jamis)
high_id_jamis = projects(:active_record).developers.create(:name => 'Jamis')
assert_equal low_id_jamis, projects(:active_record).developers.find(:first, :conditions => "name = 'Jamis'", :order => 'id')
assert_equal low_id_jamis, projects(:active_record).developers.find_by_name('Jamis', :order => 'id')
end
def test_dynamic_find_all_should_respect_association_order
# Developers are ordered 'name DESC, id DESC'
low_id_jamis = developers(:jamis)
middle_id_jamis = developers(:poor_jamis)
high_id_jamis = projects(:active_record).developers.create(:name => 'Jamis')
assert_equal [high_id_jamis, middle_id_jamis, low_id_jamis], projects(:active_record).developers.find(:all, :conditions => "name = 'Jamis'")
assert_equal [high_id_jamis, middle_id_jamis, low_id_jamis], projects(:active_record).developers.find_all_by_name('Jamis')
end
def test_dynamic_find_all_order_should_override_association_order
# Developers are ordered 'name DESC, id DESC'
low_id_jamis = developers(:jamis)
middle_id_jamis = developers(:poor_jamis)
high_id_jamis = projects(:active_record).developers.create(:name => 'Jamis')
assert_equal [low_id_jamis, middle_id_jamis, high_id_jamis], projects(:active_record).developers.find(:all, :conditions => "name = 'Jamis'", :order => 'id')
assert_equal [low_id_jamis, middle_id_jamis, high_id_jamis], projects(:active_record).developers.find_all_by_name('Jamis', :order => 'id')
end
def test_dynamic_find_all_should_respect_association_limit
assert_equal 1, projects(:active_record).limited_developers.find(:all, :conditions => "name = 'Jamis'").length
assert_equal 1, projects(:active_record).limited_developers.find_all_by_name('Jamis').length
end
def test_dynamic_find_all_order_should_override_association_limit
assert_equal 2, projects(:active_record).limited_developers.find(:all, :conditions => "name = 'Jamis'", :limit => 9_000).length
assert_equal 2, projects(:active_record).limited_developers.find_all_by_name('Jamis', :limit => 9_000).length
end
def test_dynamic_find_all_should_respect_readonly_access
projects(:active_record).readonly_developers.each { |d| assert_raise(ActiveRecord::ReadOnlyRecord) { d.save! } if d.valid?}
projects(:active_record).readonly_developers.each { |d| d.readonly? }
end
def test_new_with_values_in_collection
jamis = DeveloperForProjectWithAfterCreateHook.find_by_name('Jamis')
david = DeveloperForProjectWithAfterCreateHook.find_by_name('David')
project = ProjectWithAfterCreateHook.new(:name => "Cooking with Bertie")
project.developers << jamis
project.save!
project.reload
assert project.developers.include?(jamis)
assert project.developers.include?(david)
end
def test_find_in_association_with_options
developers = projects(:active_record).developers.find(:all)
assert_equal 3, developers.size
assert_equal developers(:poor_jamis), projects(:active_record).developers.find(:first, :conditions => "salary < 10000")
assert_equal developers(:jamis), projects(:active_record).developers.find(:first, :order => "salary DESC")
end
def test_replace_with_less
david = developers(:david)
david.projects = [projects(:action_controller)]
assert david.save
assert_equal 1, david.projects.length
end
def test_replace_with_new
david = developers(:david)
david.projects = [projects(:action_controller), Project.new("name" => "ActionWebSearch")]
david.save
assert_equal 2, david.projects.length
assert !david.projects.include?(projects(:active_record))
end
def test_replace_on_new_object
new_developer = Developer.new("name" => "Matz")
new_developer.projects = [projects(:action_controller), Project.new("name" => "ActionWebSearch")]
new_developer.save
assert_equal 2, new_developer.projects.length
end
def test_consider_type
developer = Developer.find(:first)
special_project = SpecialProject.create("name" => "Special Project")
other_project = developer.projects.first
developer.special_projects << special_project
developer.reload
assert developer.projects.include?(special_project)
assert developer.special_projects.include?(special_project)
assert !developer.special_projects.include?(other_project)
end
def test_update_attributes_after_push_without_duplicate_join_table_rows
developer = Developer.new("name" => "Kano")
project = SpecialProject.create("name" => "Special Project")
assert developer.save
developer.projects << project
developer.update_attribute("name", "Bruza")
assert_equal 1, Developer.connection.select_value(<<-end_sql).to_i
SELECT count(*) FROM developers_projects
WHERE project_id = #{project.id}
AND developer_id = #{developer.id}
end_sql
end
def test_updating_attributes_on_non_rich_associations
welcome = categories(:technology).posts.first
welcome.title = "Something else"
assert welcome.save!
end
def test_habtm_respects_select
categories(:technology).select_testing_posts(true).each do |o|
assert_respond_to o, :correctness_marker
end
assert_respond_to categories(:technology).select_testing_posts.find(:first), :correctness_marker
end
def test_updating_attributes_on_rich_associations
david = projects(:action_controller).developers.first
david.name = "DHH"
assert_raises(ActiveRecord::ReadOnlyRecord) { david.save! }
end
def test_updating_attributes_on_rich_associations_with_limited_find_from_reflection
david = projects(:action_controller).selected_developers.first
david.name = "DHH"
assert_nothing_raised { david.save! }
end
def test_updating_attributes_on_rich_associations_with_limited_find
david = projects(:action_controller).developers.find(:all, :select => "developers.*").first
david.name = "DHH"
assert david.save!
end
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, :action_controller).map(&:id).sort, developers(:david).project_ids.sort
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, :action_controller).map(&: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 !projects.include?("'"), projects
assert_equal %w(1 2), projects.scan(/\d/).sort
end
def test_scoped_find_on_through_association_doesnt_return_read_only_records
tag = Post.find(1).tags.find_by_name("General")
assert_nothing_raised do
tag.save!
end
end
def test_has_many_through_polymorphic_has_manys_works
assert_equal [10, 20].to_set, pirates(:redbeard).treasure_estimates.map(&:price).to_set
end
def test_symbols_as_keys
developer = DeveloperWithSymbolsForKeys.new(:name => 'David')
project = ProjectWithSymbolsForKeys.new(:name => 'Rails Testing')
project.developers << developer
project.save!
assert_equal 1, project.developers.size
assert_equal 1, developer.projects.size
assert_equal developer, project.developers.find(:first)
assert_equal project, developer.projects.find(:first)
end
end

View file

@ -1,932 +0,0 @@
require "cases/helper"
require 'models/developer'
require 'models/project'
require 'models/company'
require 'models/topic'
require 'models/reply'
require 'models/category'
require 'models/post'
require 'models/author'
require 'models/comment'
require 'models/person'
require 'models/reader'
class HasManyAssociationsTest < ActiveRecord::TestCase
fixtures :accounts, :categories, :companies, :developers, :projects,
:developers_projects, :topics, :authors, :comments, :author_addresses,
:people, :posts
def setup
Client.destroyed_client_ids.clear
end
def force_signal37_to_load_all_clients_of_firm
companies(:first_firm).clients_of_firm.each {|f| }
end
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_empty_hash_conditions
assert_equal 2, Firm.find(:first).plain_clients.count(:conditions => {})
end
def test_counting_with_single_conditions
assert_equal 2, Firm.find(:first).plain_clients.count(:conditions => '1=1')
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
def test_find_with_blank_conditions
[[], {}, nil, ""].each do |blank|
assert_equal 2, Firm.find(:first).clients.find(:all, :conditions => blank).size
end
end
def test_find_many_with_merged_options
assert_equal 1, companies(:first_firm).limited_clients.size
assert_equal 1, companies(:first_firm).limited_clients.find(:all).size
assert_equal 2, companies(:first_firm).limited_clients.find(:all, :limit => nil).size
end
def test_dynamic_find_should_respect_association_order
assert_equal companies(:second_client), companies(:first_firm).clients_sorted_desc.find(:first, :conditions => "type = 'Client'")
assert_equal companies(:second_client), companies(:first_firm).clients_sorted_desc.find_by_type('Client')
end
def test_dynamic_find_order_should_override_association_order
assert_equal companies(:first_client), companies(:first_firm).clients_sorted_desc.find(:first, :conditions => "type = 'Client'", :order => 'id')
assert_equal companies(:first_client), companies(:first_firm).clients_sorted_desc.find_by_type('Client', :order => 'id')
end
def test_dynamic_find_all_should_respect_association_order
assert_equal [companies(:second_client), companies(:first_client)], companies(:first_firm).clients_sorted_desc.find(:all, :conditions => "type = 'Client'")
assert_equal [companies(:second_client), companies(:first_client)], companies(:first_firm).clients_sorted_desc.find_all_by_type('Client')
end
def test_dynamic_find_all_order_should_override_association_order
assert_equal [companies(:first_client), companies(:second_client)], companies(:first_firm).clients_sorted_desc.find(:all, :conditions => "type = 'Client'", :order => 'id')
assert_equal [companies(:first_client), companies(:second_client)], companies(:first_firm).clients_sorted_desc.find_all_by_type('Client', :order => 'id')
end
def test_dynamic_find_all_should_respect_association_limit
assert_equal 1, companies(:first_firm).limited_clients.find(:all, :conditions => "type = 'Client'").length
assert_equal 1, companies(:first_firm).limited_clients.find_all_by_type('Client').length
end
def test_dynamic_find_all_limit_should_override_association_limit
assert_equal 2, companies(:first_firm).limited_clients.find(:all, :conditions => "type = 'Client'", :limit => 9_000).length
assert_equal 2, companies(:first_firm).limited_clients.find_all_by_type('Client', :limit => 9_000).length
end
def test_dynamic_find_all_should_respect_readonly_access
companies(:first_firm).readonly_clients.find(:all).each { |c| assert_raise(ActiveRecord::ReadOnlyRecord) { c.save! } }
companies(:first_firm).readonly_clients.find(:all).each { |c| assert c.readonly? }
end
def test_cant_save_has_many_readonly_association
authors(:david).readonly_comments.each { |c| assert_raise(ActiveRecord::ReadOnlyRecord) { c.save! } }
authors(:david).readonly_comments.each { |c| assert c.readonly? }
end
def test_triple_equality
assert !(Array === Firm.find(:first).clients)
assert Firm.find(:first).clients === Array
end
def test_finding_default_orders
assert_equal "Summit", Firm.find(:first).clients.first.name
end
def test_finding_with_different_class_name_and_order
assert_equal "Microsoft", Firm.find(:first).clients_sorted_desc.first.name
end
def test_finding_with_foreign_key
assert_equal "Microsoft", Firm.find(:first).clients_of_firm.first.name
end
def test_finding_with_condition
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
assert_not_nil first_client
assert_equal "Microsoft", first_client.name
assert_equal 1, firm.clients_using_sql.size
assert_equal 1, Firm.find(:first).clients_using_sql.size
end
def test_counting_using_sql
assert_equal 1, Firm.find(:first).clients_using_counter_sql.size
assert Firm.find(:first).clients_using_counter_sql.any?
assert_equal 0, Firm.find(:first).clients_using_zero_counter_sql.size
assert !Firm.find(:first).clients_using_zero_counter_sql.any?
end
def test_counting_non_existant_items_using_sql
assert_equal 0, Firm.find(:first).no_clients_using_counter_sql.size
end
def test_belongs_to_sanity
c = Client.new
assert_nil c.firm
if c.firm
assert false, "belongs_to failed if check"
end
unless c.firm
else
assert false, "belongs_to failed unless check"
end
end
def test_find_ids
firm = Firm.find(:first)
assert_raises(ActiveRecord::RecordNotFound) { firm.clients.find }
client = firm.clients.find(2)
assert_kind_of Client, client
client_ary = firm.clients.find([2])
assert_kind_of Array, client_ary
assert_equal client, client_ary.first
client_ary = firm.clients.find(2, 3)
assert_kind_of Array, client_ary
assert_equal 2, client_ary.size
assert_equal client, client_ary.first
assert_raises(ActiveRecord::RecordNotFound) { firm.clients.find(2, 99) }
end
def test_find_string_ids_when_using_finder_sql
firm = Firm.find(:first)
client = firm.clients_using_finder_sql.find("2")
assert_kind_of Client, client
client_ary = firm.clients_using_finder_sql.find(["2"])
assert_kind_of Array, client_ary
assert_equal client, client_ary.first
client_ary = firm.clients_using_finder_sql.find("2", "3")
assert_kind_of Array, client_ary
assert_equal 2, client_ary.size
assert client_ary.include?(client)
end
def test_find_all
firm = Firm.find(:first)
assert_equal 2, firm.clients.find(:all, :conditions => "#{QUOTED_TYPE} = 'Client'").length
assert_equal 1, firm.clients.find(:all, :conditions => "name = 'Summit'").length
end
def test_find_all_sanitized
firm = Firm.find(:first)
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
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, :conditions => "#{QUOTED_TYPE} = 'Client'")
end
def test_find_first_sanitized
firm = Firm.find(:first)
client2 = Client.find(2)
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
def test_find_in_collection
assert_equal Client.find(2).name, companies(:first_firm).clients.find(2).name
assert_raises(ActiveRecord::RecordNotFound) { companies(:first_firm).clients.find(6) }
end
def test_find_grouped
all_clients_of_firm1 = Client.find(:all, :conditions => "firm_id = 1")
grouped_clients_of_firm1 = Client.find(:all, :conditions => "firm_id = 1", :group => "firm_id", :select => 'firm_id, count(id) as clients_count')
assert_equal 2, all_clients_of_firm1.size
assert_equal 1, grouped_clients_of_firm1.size
end
def test_adding
force_signal37_to_load_all_clients_of_firm
natural = Client.new("name" => "Natural Company")
companies(:first_firm).clients_of_firm << natural
assert_equal 2, companies(:first_firm).clients_of_firm.size # checking via the collection
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_create_with_bang_on_has_many_when_parent_is_new_raises
assert_raises(ActiveRecord::RecordNotSaved) do
firm = Firm.new
firm.plain_clients.create! :name=>"Whoever"
end
end
def test_regular_create_on_has_many_when_parent_is_new_raises
assert_raises(ActiveRecord::RecordNotSaved) do
firm = Firm.new
firm.plain_clients.create :name=>"Whoever"
end
end
def test_create_with_bang_on_has_many_raises_when_record_not_saved
assert_raises(ActiveRecord::RecordInvalid) do
firm = Firm.find(:first)
firm.plain_clients.create!
end
end
def test_create_with_bang_on_habtm_when_parent_is_new_raises
assert_raises(ActiveRecord::RecordNotSaved) do
Developer.new("name" => "Aredridel").projects.create!
end
end
def test_adding_a_mismatch_class
assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << nil }
assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << 1 }
assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << Topic.find(1) }
end
def test_adding_a_collection
force_signal37_to_load_all_clients_of_firm
companies(:first_firm).clients_of_firm.concat([Client.new("name" => "Natural Company"), Client.new("name" => "Apple")])
assert_equal 3, companies(:first_firm).clients_of_firm.size
assert_equal 3, companies(:first_firm).clients_of_firm(true).size
end
def test_adding_before_save
no_of_firms = Firm.count
no_of_clients = Client.count
new_firm = Firm.new("name" => "A New Firm, Inc")
c = Client.new("name" => "Apple")
new_firm.clients_of_firm.push Client.new("name" => "Natural Company")
assert_equal 1, new_firm.clients_of_firm.size
new_firm.clients_of_firm << c
assert_equal 2, new_firm.clients_of_firm.size
assert_equal no_of_firms, Firm.count # Firm was not saved to database.
assert_equal no_of_clients, Client.count # Clients were not saved to database.
assert new_firm.save
assert !new_firm.new_record?
assert !c.new_record?
assert_equal new_firm, c.firm
assert_equal no_of_firms+1, Firm.count # Firm was saved to database.
assert_equal no_of_clients+2, Client.count # Clients were saved to database.
assert_equal 2, new_firm.clients_of_firm.size
assert_equal 2, new_firm.clients_of_firm(true).size
end
def test_invalid_adding
firm = Firm.find(1)
assert !(firm.clients_of_firm << c = Client.new)
assert c.new_record?
assert !firm.valid?
assert !firm.save
assert c.new_record?
end
def test_invalid_adding_before_save
no_of_firms = Firm.count
no_of_clients = Client.count
new_firm = Firm.new("name" => "A New Firm, Inc")
new_firm.clients_of_firm.concat([c = Client.new, Client.new("name" => "Apple")])
assert c.new_record?
assert !c.valid?
assert !new_firm.valid?
assert !new_firm.save
assert c.new_record?
assert new_firm.new_record?
end
def test_build
company = companies(:first_firm)
new_client = assert_no_queries { company.clients_of_firm.build("name" => "Another Client") }
assert !company.clients_of_firm.loaded?
assert_equal "Another Client", new_client.name
assert new_client.new_record?
assert_equal new_client, company.clients_of_firm.last
company.name += '-changed'
assert_queries(2) { assert company.save }
assert !new_client.new_record?
assert_equal 2, company.clients_of_firm(true).size
end
def test_build_many
company = companies(:first_firm)
new_clients = assert_no_queries { company.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) }
assert_equal 2, new_clients.size
company.name += '-changed'
assert_queries(3) { assert company.save }
assert_equal 3, company.clients_of_firm(true).size
end
def test_build_followed_by_save_does_not_load_target
new_client = companies(:first_firm).clients_of_firm.build("name" => "Another Client")
assert companies(:first_firm).save
assert !companies(:first_firm).clients_of_firm.loaded?
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?
assert !new_client.valid?
assert_equal new_client, companies(:first_firm).clients_of_firm.last
assert !companies(:first_firm).save
assert new_client.new_record?
assert_equal 1, companies(:first_firm).clients_of_firm(true).size
end
def test_create
force_signal37_to_load_all_clients_of_firm
new_client = companies(:first_firm).clients_of_firm.create("name" => "Another Client")
assert !new_client.new_record?
assert_equal new_client, companies(:first_firm).clients_of_firm.last
assert_equal new_client, companies(:first_firm).clients_of_firm(true).last
end
def test_create_many
companies(:first_firm).clients_of_firm.create([{"name" => "Another Client"}, {"name" => "Another Client II"}])
assert_equal 3, companies(:first_firm).clients_of_firm(true).size
end
def test_create_followed_by_save_does_not_load_target
new_client = companies(:first_firm).clients_of_firm.create("name" => "Another Client")
assert companies(:first_firm).save
assert !companies(:first_firm).clients_of_firm.loaded?
end
def test_find_or_initialize
the_client = companies(:first_firm).clients.find_or_initialize_by_name("Yet another client")
assert_equal companies(:first_firm).id, the_client.firm_id
assert_equal "Yet another client", the_client.name
assert the_client.new_record?
end
def test_find_or_create
number_of_clients = companies(:first_firm).clients.size
the_client = companies(:first_firm).clients.find_or_create_by_name("Yet another client")
assert_equal number_of_clients + 1, companies(:first_firm, :reload).clients.size
assert_equal the_client, companies(:first_firm).clients.find_or_create_by_name("Yet another client")
assert_equal number_of_clients + 1, companies(:first_firm, :reload).clients.size
end
def test_deleting
force_signal37_to_load_all_clients_of_firm
companies(:first_firm).clients_of_firm.delete(companies(:first_firm).clients_of_firm.first)
assert_equal 0, companies(:first_firm).clients_of_firm.size
assert_equal 0, companies(:first_firm).clients_of_firm(true).size
end
def test_deleting_before_save
new_firm = Firm.new("name" => "A New Firm, Inc.")
new_client = new_firm.clients_of_firm.build("name" => "Another Client")
assert_equal 1, new_firm.clients_of_firm.size
new_firm.clients_of_firm.delete(new_client)
assert_equal 0, new_firm.clients_of_firm.size
end
def test_deleting_a_collection
force_signal37_to_load_all_clients_of_firm
companies(:first_firm).clients_of_firm.create("name" => "Another Client")
assert_equal 2, companies(:first_firm).clients_of_firm.size
companies(:first_firm).clients_of_firm.delete([companies(:first_firm).clients_of_firm[0], companies(:first_firm).clients_of_firm[1]])
assert_equal 0, companies(:first_firm).clients_of_firm.size
assert_equal 0, companies(:first_firm).clients_of_firm(true).size
end
def test_delete_all
force_signal37_to_load_all_clients_of_firm
companies(:first_firm).clients_of_firm.create("name" => "Another Client")
assert_equal 2, companies(:first_firm).clients_of_firm.size
companies(:first_firm).clients_of_firm.delete_all
assert_equal 0, companies(:first_firm).clients_of_firm.size
assert_equal 0, companies(:first_firm).clients_of_firm(true).size
end
def test_delete_all_with_not_yet_loaded_association_collection
force_signal37_to_load_all_clients_of_firm
companies(:first_firm).clients_of_firm.create("name" => "Another Client")
assert_equal 2, companies(:first_firm).clients_of_firm.size
companies(:first_firm).clients_of_firm.reset
companies(:first_firm).clients_of_firm.delete_all
assert_equal 0, companies(:first_firm).clients_of_firm.size
assert_equal 0, companies(:first_firm).clients_of_firm(true).size
end
def test_clearing_an_association_collection
firm = companies(:first_firm)
client_id = firm.clients_of_firm.first.id
assert_equal 1, firm.clients_of_firm.size
firm.clients_of_firm.clear
assert_equal 0, firm.clients_of_firm.size
assert_equal 0, firm.clients_of_firm(true).size
assert_equal [], Client.destroyed_client_ids[firm.id]
# Should not be destroyed since the association is not dependent.
assert_nothing_raised do
assert Client.find(client_id).firm.nil?
end
end
def test_clearing_a_dependent_association_collection
firm = companies(:first_firm)
client_id = firm.dependent_clients_of_firm.first.id
assert_equal 1, firm.dependent_clients_of_firm.size
# :dependent means destroy is called on each client
firm.dependent_clients_of_firm.clear
assert_equal 0, firm.dependent_clients_of_firm.size
assert_equal 0, firm.dependent_clients_of_firm(true).size
assert_equal [client_id], Client.destroyed_client_ids[firm.id]
# Should be destroyed since the association is dependent.
assert Client.find_by_id(client_id).nil?
end
def test_clearing_an_exclusively_dependent_association_collection
firm = companies(:first_firm)
client_id = firm.exclusively_dependent_clients_of_firm.first.id
assert_equal 1, firm.exclusively_dependent_clients_of_firm.size
assert_equal [], Client.destroyed_client_ids[firm.id]
# :exclusively_dependent means each client is deleted directly from
# the database without looping through them calling destroy.
firm.exclusively_dependent_clients_of_firm.clear
assert_equal 0, firm.exclusively_dependent_clients_of_firm.size
assert_equal 0, firm.exclusively_dependent_clients_of_firm(true).size
# no destroy-filters should have been called
assert_equal [], Client.destroyed_client_ids[firm.id]
# Should be destroyed since the association is exclusively dependent.
assert Client.find_by_id(client_id).nil?
end
def test_dependent_association_respects_optional_conditions_on_delete
firm = companies(:odegy)
Client.create(:client_of => firm.id, :name => "BigShot Inc.")
Client.create(:client_of => firm.id, :name => "SmallTime Inc.")
# only one of two clients is included in the association due to the :conditions key
assert_equal 2, Client.find_all_by_client_of(firm.id).size
assert_equal 1, firm.dependent_conditional_clients_of_firm.size
firm.destroy
# only the correctly associated client should have been deleted
assert_equal 1, Client.find_all_by_client_of(firm.id).size
end
def test_dependent_association_respects_optional_sanitized_conditions_on_delete
firm = companies(:odegy)
Client.create(:client_of => firm.id, :name => "BigShot Inc.")
Client.create(:client_of => firm.id, :name => "SmallTime Inc.")
# only one of two clients is included in the association due to the :conditions key
assert_equal 2, Client.find_all_by_client_of(firm.id).size
assert_equal 1, firm.dependent_sanitized_conditional_clients_of_firm.size
firm.destroy
# only the correctly associated client should have been deleted
assert_equal 1, Client.find_all_by_client_of(firm.id).size
end
def test_creation_respects_hash_condition
ms_client = companies(:first_firm).clients_like_ms_with_hash_conditions.build
assert ms_client.save
assert_equal 'Microsoft', ms_client.name
another_ms_client = companies(:first_firm).clients_like_ms_with_hash_conditions.create
assert !another_ms_client.new_record?
assert_equal 'Microsoft', another_ms_client.name
end
def test_dependent_delete_and_destroy_with_belongs_to
author_address = author_addresses(:david_address)
assert_equal [], AuthorAddress.destroyed_author_address_ids[authors(:david).id]
assert_difference "AuthorAddress.count", -2 do
authors(:david).destroy
end
assert_equal [author_address.id], AuthorAddress.destroyed_author_address_ids[authors(:david).id]
end
def test_invalid_belongs_to_dependent_option_raises_exception
assert_raises ArgumentError do
Author.belongs_to :special_author_address, :dependent => :nullify
end
end
def test_clearing_without_initial_access
firm = companies(:first_firm)
firm.clients_of_firm.clear
assert_equal 0, firm.clients_of_firm.size
assert_equal 0, firm.clients_of_firm(true).size
end
def test_deleting_a_item_which_is_not_in_the_collection
force_signal37_to_load_all_clients_of_firm
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
assert_equal 2, summit.client_of
end
def test_deleting_type_mismatch
david = Developer.find(1)
david.projects.reload
assert_raises(ActiveRecord::AssociationTypeMismatch) { david.projects.delete(1) }
end
def test_deleting_self_type_mismatch
david = Developer.find(1)
david.projects.reload
assert_raises(ActiveRecord::AssociationTypeMismatch) { david.projects.delete(Project.find(1).developers) }
end
def test_destroy_all
force_signal37_to_load_all_clients_of_firm
assert !companies(:first_firm).clients_of_firm.empty?, "37signals has clients after load"
companies(:first_firm).clients_of_firm.destroy_all
assert companies(:first_firm).clients_of_firm.empty?, "37signals has no clients after destroy all"
assert companies(:first_firm).clients_of_firm(true).empty?, "37signals has no clients after destroy all and refresh"
end
def test_dependence
firm = companies(:first_firm)
assert_equal 2, firm.clients.size
firm.destroy
assert Client.find(:all, :conditions => "firm_id=#{firm.id}").empty?
end
def test_destroy_dependent_when_deleted_from_association
firm = Firm.find(:first)
assert_equal 2, firm.clients.size
client = firm.clients.first
firm.clients.delete(client)
assert_raise(ActiveRecord::RecordNotFound) { Client.find(client.id) }
assert_raise(ActiveRecord::RecordNotFound) { firm.clients.find(client.id) }
assert_equal 1, firm.clients.size
end
def test_three_levels_of_dependence
topic = Topic.create "title" => "neat and simple"
reply = topic.replies.create "title" => "neat and simple", "content" => "still digging it"
silly_reply = reply.replies.create "title" => "neat and simple", "content" => "ain't complaining"
assert_nothing_raised { topic.destroy }
end
uses_transaction :test_dependence_with_transaction_support_on_failure
def test_dependence_with_transaction_support_on_failure
firm = companies(:first_firm)
clients = firm.clients
assert_equal 2, clients.length
clients.last.instance_eval { def before_destroy() raise "Trigger rollback" end }
firm.destroy rescue "do nothing"
assert_equal 2, Client.find(:all, :conditions => "firm_id=#{firm.id}").size
end
def test_dependence_on_account
num_accounts = Account.count
companies(:first_firm).destroy
assert_equal num_accounts - 1, Account.count
end
def test_depends_and_nullify
num_accounts = Account.count
num_companies = Company.count
core = companies(:rails_core)
assert_equal accounts(:rails_core_account), core.account
assert_equal companies(:leetsoft, :jadedpixel), core.companies
core.destroy
assert_nil accounts(:rails_core_account).reload.firm_id
assert_nil companies(:leetsoft).reload.client_of
assert_nil companies(:jadedpixel).reload.client_of
assert_equal num_accounts, Account.count
end
def test_included_in_collection
assert companies(:first_firm).clients.include?(Client.find(2))
end
def test_adding_array_and_collection
assert_nothing_raised { Firm.find(:first).clients + Firm.find(:all).last.clients }
end
def test_find_all_without_conditions
firm = companies(:first_firm)
assert_equal 2, firm.clients.find(:all).length
end
def test_replace_with_less
firm = Firm.find(:first)
firm.clients = [companies(:first_client)]
assert firm.save, "Could not save firm"
firm.reload
assert_equal 1, firm.clients.length
end
def test_replace_with_less_and_dependent_nullify
num_companies = Company.count
companies(:rails_core).companies = []
assert_equal num_companies, Company.count
end
def test_replace_with_new
firm = Firm.find(:first)
firm.clients = [companies(:second_client), Client.new("name" => "New Client")]
firm.save
firm.reload
assert_equal 2, firm.clients.length
assert !firm.clients.include?(:first_client)
end
def test_replace_on_new_object
firm = Firm.new("name" => "New Firm")
firm.clients = [companies(:second_client), Client.new("name" => "New Client")]
assert firm.save
firm.reload
assert_equal 2, firm.clients.length
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]
firm.save
firm.reload
assert_equal 2, firm.clients.length
assert firm.clients.include?(companies(:second_client))
end
def test_assign_ids_ignoring_blanks
firm = Firm.create!(:name => 'Apple')
firm.client_ids = [companies(:first_client).id, nil, companies(:second_client).id, '']
firm.save!
assert_equal 2, firm.clients(true).size
assert firm.clients.include?(companies(:second_client))
end
def test_get_ids_for_through
assert_equal [comments(:eager_other_comment1).id], authors(:mary).comment_ids
end
def test_modifying_a_through_a_has_many_should_raise
[
lambda { authors(:mary).comment_ids = [comments(:greetings).id, comments(:more_greetings).id] },
lambda { authors(:mary).comments = [comments(:greetings), comments(:more_greetings)] },
lambda { authors(:mary).comments << Comment.create!(:body => "Yay", :post_id => 424242) },
lambda { authors(:mary).comments.delete(authors(:mary).comments.first) },
].each {|block| assert_raise(ActiveRecord::HasManyThroughCantAssociateThroughHasManyReflection, &block) }
end
def test_assign_ids_for_through_a_belongs_to
post = Post.new(:title => "Assigning IDs works!", :body => "You heared it here first, folks!")
post.person_ids = [people(:david).id, people(:michael).id]
post.save
post.reload
assert_equal 2, post.people.length
assert post.people.include?(people(:david))
end
def test_dynamic_find_should_respect_association_order_for_through
assert_equal Comment.find(10), authors(:david).comments_desc.find(:first, :conditions => "comments.type = 'SpecialComment'")
assert_equal Comment.find(10), authors(:david).comments_desc.find_by_type('SpecialComment')
end
def test_dynamic_find_order_should_override_association_order_for_through
assert_equal Comment.find(3), authors(:david).comments_desc.find(:first, :conditions => "comments.type = 'SpecialComment'", :order => 'comments.id')
assert_equal Comment.find(3), authors(:david).comments_desc.find_by_type('SpecialComment', :order => 'comments.id')
end
def test_dynamic_find_all_should_respect_association_order_for_through
assert_equal [Comment.find(10), Comment.find(7), Comment.find(6), Comment.find(3)], authors(:david).comments_desc.find(:all, :conditions => "comments.type = 'SpecialComment'")
assert_equal [Comment.find(10), Comment.find(7), Comment.find(6), Comment.find(3)], authors(:david).comments_desc.find_all_by_type('SpecialComment')
end
def test_dynamic_find_all_order_should_override_association_order_for_through
assert_equal [Comment.find(3), Comment.find(6), Comment.find(7), Comment.find(10)], authors(:david).comments_desc.find(:all, :conditions => "comments.type = 'SpecialComment'", :order => 'comments.id')
assert_equal [Comment.find(3), Comment.find(6), Comment.find(7), Comment.find(10)], authors(:david).comments_desc.find_all_by_type('SpecialComment', :order => 'comments.id')
end
def test_dynamic_find_all_should_respect_association_limit_for_through
assert_equal 1, authors(:david).limited_comments.find(:all, :conditions => "comments.type = 'SpecialComment'").length
assert_equal 1, authors(:david).limited_comments.find_all_by_type('SpecialComment').length
end
def test_dynamic_find_all_order_should_override_association_limit_for_through
assert_equal 4, authors(:david).limited_comments.find(:all, :conditions => "comments.type = 'SpecialComment'", :limit => 9_000).length
assert_equal 4, authors(:david).limited_comments.find_all_by_type('SpecialComment', :limit => 9_000).length
end
def test_find_all_include_over_the_same_table_for_through
assert_equal 2, people(:michael).posts.find(:all, :include => :people).length
end
def test_has_many_through_respects_hash_conditions
assert_equal authors(:david).hello_posts, authors(:david).hello_posts_with_hash_conditions
assert_equal authors(:david).hello_post_comments, authors(:david).hello_post_comments_with_hash_conditions
end
def test_include_uses_array_include_after_loaded
firm = companies(:first_firm)
firm.clients.class # force load target
client = firm.clients.first
assert_no_queries do
assert firm.clients.loaded?
assert firm.clients.include?(client)
end
end
def test_include_checks_if_record_exists_if_target_not_loaded
firm = companies(:first_firm)
client = firm.clients.first
firm.reload
assert ! firm.clients.loaded?
assert_queries(1) do
assert firm.clients.include?(client)
end
assert ! firm.clients.loaded?
end
def test_include_loads_collection_if_target_uses_finder_sql
firm = companies(:first_firm)
client = firm.clients_using_sql.first
firm.reload
assert ! firm.clients_using_sql.loaded?
assert firm.clients_using_sql.include?(client)
assert firm.clients_using_sql.loaded?
end
def test_include_returns_false_for_non_matching_record_to_verify_scoping
firm = companies(:first_firm)
client = Client.create!(:name => 'Not Associated')
assert ! firm.clients.loaded?
assert ! firm.clients.include?(client)
end
def test_calling_first_or_last_on_association_should_not_load_association
firm = companies(:first_firm)
firm.clients.first
firm.clients.last
assert !firm.clients.loaded?
end
def test_calling_first_or_last_on_loaded_association_should_not_fetch_with_query
firm = companies(:first_firm)
firm.clients.class # force load target
assert firm.clients.loaded?
assert_no_queries do
firm.clients.first
assert_equal 2, firm.clients.first(2).size
firm.clients.last
assert_equal 2, firm.clients.last(2).size
end
end
def test_calling_first_or_last_on_existing_record_with_build_should_load_association
firm = companies(:first_firm)
firm.clients.build(:name => 'Foo')
assert !firm.clients.loaded?
assert_queries 1 do
firm.clients.first
firm.clients.last
end
assert firm.clients.loaded?
end
def test_calling_first_or_last_on_new_record_should_not_run_queries
firm = Firm.new
assert_no_queries do
firm.clients.first
firm.clients.last
end
end
def test_calling_first_or_last_with_find_options_on_loaded_association_should_fetch_with_query
firm = companies(:first_firm)
firm.clients.class # force load target
assert_queries 2 do
assert firm.clients.loaded?
firm.clients.first(:order => 'name')
firm.clients.last(:order => 'name')
end
end
def test_calling_first_or_last_with_integer_on_association_should_load_association
firm = companies(:first_firm)
assert_queries 1 do
firm.clients.first(2)
firm.clients.last(2)
end
assert firm.clients.loaded?
end
end

View file

@ -1,190 +0,0 @@
require "cases/helper"
require 'models/post'
require 'models/person'
require 'models/reader'
class HasManyThroughAssociationsTest < ActiveRecord::TestCase
fixtures :posts, :readers, :people
def test_associate_existing
assert_queries(2) { posts(:thinking);people(:david) }
assert_queries(1) do
posts(:thinking).people << people(:david)
end
assert_queries(1) do
assert posts(:thinking).people.include?(people(:david))
end
assert posts(:thinking).reload.people(true).include?(people(:david))
end
def test_associating_new
assert_queries(1) { posts(:thinking) }
new_person = nil # so block binding catches it
assert_queries(0) do
new_person = Person.new :first_name => 'bob'
end
# Associating new records always saves them
# Thus, 1 query for the new person record, 1 query for the new join table record
assert_queries(2) do
posts(:thinking).people << new_person
end
assert_queries(1) do
assert posts(:thinking).people.include?(new_person)
end
assert posts(:thinking).reload.people(true).include?(new_person)
end
def test_associate_new_by_building
assert_queries(1) { posts(:thinking) }
assert_queries(0) do
posts(:thinking).people.build(:first_name=>"Bob")
posts(:thinking).people.new(:first_name=>"Ted")
end
# Should only need to load the association once
assert_queries(1) do
assert posts(:thinking).people.collect(&:first_name).include?("Bob")
assert posts(:thinking).people.collect(&:first_name).include?("Ted")
end
# 2 queries for each new record (1 to save the record itself, 1 for the join model)
# * 2 new records = 4
# + 1 query to save the actual post = 5
assert_queries(5) do
posts(:thinking).body += '-changed'
posts(:thinking).save
end
assert posts(:thinking).reload.people(true).collect(&:first_name).include?("Bob")
assert posts(:thinking).reload.people(true).collect(&:first_name).include?("Ted")
end
def test_delete_association
assert_queries(2){posts(:welcome);people(:michael); }
assert_queries(1) do
posts(:welcome).people.delete(people(:michael))
end
assert_queries(1) do
assert posts(:welcome).people.empty?
end
assert posts(:welcome).reload.people(true).empty?
end
def test_replace_association
assert_queries(4){posts(:welcome);people(:david);people(:michael); posts(:welcome).people(true)}
# 1 query to delete the existing reader (michael)
# 1 query to associate the new reader (david)
assert_queries(2) do
posts(:welcome).people = [people(:david)]
end
assert_queries(0){
assert posts(:welcome).people.include?(people(:david))
assert !posts(:welcome).people.include?(people(:michael))
}
assert posts(:welcome).reload.people(true).include?(people(:david))
assert !posts(:welcome).reload.people(true).include?(people(:michael))
end
def test_associate_with_create
assert_queries(1) { posts(:thinking) }
# 1 query for the new record, 1 for the join table record
# No need to update the actual collection yet!
assert_queries(2) do
posts(:thinking).people.create(:first_name=>"Jeb")
end
# *Now* we actually need the collection so it's loaded
assert_queries(1) do
assert posts(:thinking).people.collect(&:first_name).include?("Jeb")
end
assert posts(:thinking).reload.people(true).collect(&:first_name).include?("Jeb")
end
def test_associate_with_create_and_no_options
peeps = posts(:thinking).people.count
posts(:thinking).people.create(:first_name => 'foo')
assert_equal peeps + 1, posts(:thinking).people.count
end
def test_associate_with_create_exclamation_and_no_options
peeps = posts(:thinking).people.count
posts(:thinking).people.create!(:first_name => 'foo')
assert_equal peeps + 1, posts(:thinking).people.count
end
def test_clear_associations
assert_queries(2) { posts(:welcome);posts(:welcome).people(true) }
assert_queries(1) do
posts(:welcome).people.clear
end
assert_queries(0) do
assert posts(:welcome).people.empty?
end
assert posts(:welcome).reload.people(true).empty?
end
def test_association_callback_ordering
Post.reset_log
log = Post.log
post = posts(:thinking)
post.people_with_callbacks << people(:michael)
assert_equal [
[:added, :before, "Michael"],
[:added, :after, "Michael"]
], log.last(2)
post.people_with_callbacks.push(people(:david), Person.create!(:first_name => "Bob"), Person.new(:first_name => "Lary"))
assert_equal [
[:added, :before, "David"],
[:added, :after, "David"],
[:added, :before, "Bob"],
[:added, :after, "Bob"],
[:added, :before, "Lary"],
[:added, :after, "Lary"]
],log.last(6)
post.people_with_callbacks.build(:first_name => "Ted")
assert_equal [
[:added, :before, "Ted"],
[:added, :after, "Ted"]
], log.last(2)
post.people_with_callbacks.create(:first_name => "Sam")
assert_equal [
[:added, :before, "Sam"],
[:added, :after, "Sam"]
], log.last(2)
post.people_with_callbacks = [people(:michael),people(:david), Person.new(:first_name => "Julian"), Person.create!(:first_name => "Roger")]
assert_equal (%w(Ted Bob Sam Lary) * 2).sort, log[-12..-5].collect(&:last).sort
assert_equal [
[:added, :before, "Julian"],
[:added, :after, "Julian"],
[:added, :before, "Roger"],
[:added, :after, "Roger"]
], log.last(4)
post.people_with_callbacks.clear
assert_equal (%w(Michael David Julian Roger) * 2).sort, log.last(8).collect(&:last).sort
end
end

View file

@ -1,323 +0,0 @@
require "cases/helper"
require 'models/developer'
require 'models/project'
require 'models/company'
class HasOneAssociationsTest < ActiveRecord::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_with_select
assert_equal Firm.find(1).account_with_select.attributes.size, 2
assert_equal Firm.find(1, :include => :account_with_select).account_with_select.attributes.size, 2
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 }
end
def test_triple_equality
assert Account === companies(:first_firm).account
assert companies(:first_firm).account === Account
end
def test_type_mismatch
assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).account = 1 }
assert_raises(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).account = Project.find(1) }
end
def test_natural_assignment
apple = Firm.create("name" => "Apple")
citibank = Account.create("credit_limit" => 10)
apple.account = citibank
assert_equal apple.id, citibank.firm_id
end
def test_natural_assignment_to_nil
old_account_id = companies(:first_firm).account.id
companies(:first_firm).account = nil
companies(:first_firm).save
assert_nil companies(:first_firm).account
# account is dependent, therefore is destroyed when reference to owner is lost
assert_raises(ActiveRecord::RecordNotFound) { Account.find(old_account_id) }
end
def test_assignment_without_replacement
apple = Firm.create("name" => "Apple")
citibank = Account.create("credit_limit" => 10)
apple.account = citibank
assert_equal apple.id, citibank.firm_id
hsbc = apple.build_account({ :credit_limit => 20}, false)
assert_equal apple.id, hsbc.firm_id
hsbc.save
assert_equal apple.id, citibank.firm_id
nykredit = apple.create_account({ :credit_limit => 30}, false)
assert_equal apple.id, nykredit.firm_id
assert_equal apple.id, citibank.firm_id
assert_equal apple.id, hsbc.firm_id
end
def test_assignment_without_replacement_on_create
apple = Firm.create("name" => "Apple")
citibank = Account.create("credit_limit" => 10)
apple.account = citibank
assert_equal apple.id, citibank.firm_id
hsbc = apple.create_account({:credit_limit => 10}, false)
assert_equal apple.id, hsbc.firm_id
hsbc.save
assert_equal apple.id, citibank.firm_id
end
def test_dependence
num_accounts = Account.count
firm = Firm.find(1)
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_id], Account.destroyed_account_ids[firm.id]
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
firm = Firm.new("name" => "GlobalMegaCorp")
firm.save
account = firm.build_account("credit_limit" => 1000)
assert account.save
assert_equal account, firm.account
end
def test_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")
end
def test_build_association_twice_without_saving_affects_nothing
count_of_account = Account.count
firm = Firm.find(:first)
account1 = firm.build_account("credit_limit" => 1000)
account2 = firm.build_account("credit_limit" => 2000)
assert_equal count_of_account, Account.count
end
def test_create_association
firm = Firm.create(:name => "GlobalMegaCorp")
account = firm.create_account(:credit_limit => 1000)
assert_equal account, firm.reload.account
end
def test_build
firm = Firm.new("name" => "GlobalMegaCorp")
firm.save
firm.account = account = Account.new("credit_limit" => 1000)
assert_equal account, firm.account
assert account.save
assert_equal account, firm.account
end
def test_build_before_child_saved
firm = Firm.find(1)
account = firm.account.build("credit_limit" => 1000)
assert_equal account, firm.account
assert account.new_record?
assert firm.save
assert_equal account, firm.account
assert !account.new_record?
end
def test_build_before_either_saved
firm = Firm.new("name" => "GlobalMegaCorp")
firm.account = account = Account.new("credit_limit" => 1000)
assert_equal account, firm.account
assert account.new_record?
assert firm.save
assert_equal account, firm.account
assert !account.new_record?
end
def test_failing_build_association
firm = Firm.new("name" => "GlobalMegaCorp")
firm.save
firm.account = account = Account.new
assert_equal account, firm.account
assert !account.save
assert_equal account, firm.account
assert_equal "can't be empty", account.errors.on("credit_limit")
end
def test_create
firm = Firm.new("name" => "GlobalMegaCorp")
firm.save
firm.account = account = Account.create("credit_limit" => 1000)
assert_equal account, firm.account
end
def test_create_before_save
firm = Firm.new("name" => "GlobalMegaCorp")
firm.account = account = Account.create("credit_limit" => 1000)
assert_equal account, firm.account
end
def test_dependence_with_missing_association
Account.destroy_all
firm = Firm.find(1)
assert firm.account.nil?
firm.destroy
end
def test_dependence_with_missing_association_and_nullify
Account.destroy_all
firm = DependentFirm.find(:first)
assert firm.account.nil?
firm.destroy
end
def test_assignment_before_parent_saved
firm = Firm.new("name" => "GlobalMegaCorp")
firm.account = a = Account.find(1)
assert firm.new_record?
assert_equal a, firm.account
assert firm.save
assert_equal a, firm.account
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)
assert !a.new_record?
assert_equal a, firm.account
assert_equal a, firm.account
assert_equal a, firm.account(true)
end
def test_save_fails_for_invalid_has_one
firm = Firm.find(:first)
assert firm.valid?
firm.account = Account.new
assert !firm.account.valid?
assert !firm.valid?
assert !firm.save
assert_equal "is invalid", firm.errors.on("account")
end
def test_assignment_before_either_saved
firm = Firm.new("name" => "GlobalMegaCorp")
firm.account = a = Account.new("credit_limit" => 1000)
assert firm.new_record?
assert a.new_record?
assert_equal a, firm.account
assert firm.save
assert !firm.new_record?
assert !a.new_record?
assert_equal a, firm.account
assert_equal a, firm.account(true)
end
def test_not_resaved_when_unchanged
firm = Firm.find(:first, :include => :account)
firm.name += '-changed'
assert_queries(1) { firm.save! }
firm = Firm.find(:first)
firm.account = Account.find(:first)
assert_queries(Firm.partial_updates? ? 0 : 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_cant_save_readonly_association
assert_raise(ActiveRecord::ReadOnlyRecord) { companies(:first_firm).readonly_account.save! }
assert companies(:first_firm).readonly_account.readonly?
end
end

View file

@ -1,74 +0,0 @@
require "cases/helper"
require 'models/club'
require 'models/member'
require 'models/membership'
require 'models/sponsor'
class HasOneThroughAssociationsTest < ActiveRecord::TestCase
fixtures :members, :clubs, :memberships, :sponsors
def setup
@member = members(:groucho)
end
def test_has_one_through_with_has_one
assert_equal clubs(:boring_club), @member.club
end
def test_has_one_through_with_has_many
assert_equal clubs(:moustache_club), @member.favourite_club
end
def test_creating_association_creates_through_record
new_member = Member.create(:name => "Chris")
new_member.club = Club.create(:name => "LRUG")
assert_not_nil new_member.current_membership
assert_not_nil new_member.club
end
def test_replace_target_record
new_club = Club.create(:name => "Marx Bros")
@member.club = new_club
@member.reload
assert_equal new_club, @member.club
end
def test_replacing_target_record_deletes_old_association
assert_no_difference "Membership.count" do
new_club = Club.create(:name => "Bananarama")
@member.club = new_club
@member.reload
end
end
def test_has_one_through_polymorphic
assert_equal clubs(:moustache_club), @member.sponsor_club
end
def has_one_through_to_has_many
assert_equal 2, @member.fellow_members.size
end
def test_has_one_through_eager_loading
members = Member.find(:all, :include => :club, :conditions => ["name = ?", "Groucho Marx"])
assert_equal 1, members.size
assert_not_nil assert_no_queries {members[0].club}
end
def test_has_one_through_eager_loading_through_polymorphic
members = Member.find(:all, :include => :sponsor_club, :conditions => ["name = ?", "Groucho Marx"])
assert_equal 1, members.size
assert_not_nil assert_no_queries {members[0].sponsor_club}
end
def test_has_one_through_polymorphic_with_source_type
assert_equal members(:groucho), clubs(:moustache_club).sponsored_member
end
def test_eager_has_one_through_polymorphic_with_source_type
clubs = Club.find(:all, :include => :sponsored_member, :conditions => ["name = ?","Moustache and Eyebrow Fancier Club"])
# Only the eyebrow fanciers club has a sponsored_member
assert_not_nil assert_no_queries {clubs[0].sponsored_member}
end
end

View file

@ -1,88 +0,0 @@
require "cases/helper"
require 'models/post'
require 'models/comment'
require 'models/author'
require 'models/category'
require 'models/categorization'
class InnerJoinAssociationTest < ActiveRecord::TestCase
fixtures :authors, :posts, :comments, :categories, :categories_posts, :categorizations
def test_construct_finder_sql_creates_inner_joins
sql = Author.send(:construct_finder_sql, :joins => :posts)
assert_match /INNER JOIN .?posts.? ON .?posts.?.author_id = authors.id/, sql
end
def test_construct_finder_sql_cascades_inner_joins
sql = Author.send(:construct_finder_sql, :joins => {:posts => :comments})
assert_match /INNER JOIN .?posts.? ON .?posts.?.author_id = authors.id/, sql
assert_match /INNER JOIN .?comments.? ON .?comments.?.post_id = posts.id/, sql
end
def test_construct_finder_sql_inner_joins_through_associations
sql = Author.send(:construct_finder_sql, :joins => :categorized_posts)
assert_match /INNER JOIN .?categorizations.?.*INNER JOIN .?posts.?/, sql
end
def test_construct_finder_sql_applies_association_conditions
sql = Author.send(:construct_finder_sql, :joins => :categories_like_general, :conditions => "TERMINATING_MARKER")
assert_match /INNER JOIN .?categories.? ON.*AND.*.?General.?.*TERMINATING_MARKER/, sql
end
def test_construct_finder_sql_unpacks_nested_joins
sql = Author.send(:construct_finder_sql, :joins => {:posts => [[:comments]]})
assert_no_match /inner join.*inner join.*inner join/i, sql, "only two join clauses should be present"
assert_match /INNER JOIN .?posts.? ON .?posts.?.author_id = authors.id/, sql
assert_match /INNER JOIN .?comments.? ON .?comments.?.post_id = .?posts.?.id/, sql
end
def test_construct_finder_sql_ignores_empty_joins_hash
sql = Author.send(:construct_finder_sql, :joins => {})
assert_no_match /JOIN/i, sql
end
def test_construct_finder_sql_ignores_empty_joins_array
sql = Author.send(:construct_finder_sql, :joins => [])
assert_no_match /JOIN/i, sql
end
def test_find_with_implicit_inner_joins_honors_readonly_without_select
authors = Author.find(:all, :joins => :posts)
assert !authors.empty?, "expected authors to be non-empty"
assert authors.all? {|a| a.readonly? }, "expected all authors to be readonly"
end
def test_find_with_implicit_inner_joins_honors_readonly_with_select
authors = Author.find(:all, :select => 'authors.*', :joins => :posts)
assert !authors.empty?, "expected authors to be non-empty"
assert authors.all? {|a| !a.readonly? }, "expected no authors to be readonly"
end
def test_find_with_implicit_inner_joins_honors_readonly_false
authors = Author.find(:all, :joins => :posts, :readonly => false)
assert !authors.empty?, "expected authors to be non-empty"
assert authors.all? {|a| !a.readonly? }, "expected no authors to be readonly"
end
def test_find_with_implicit_inner_joins_does_not_set_associations
authors = Author.find(:all, :select => 'authors.*', :joins => :posts)
assert !authors.empty?, "expected authors to be non-empty"
assert authors.all? {|a| !a.send(:instance_variable_names).include?("@posts")}, "expected no authors to have the @posts association loaded"
end
def test_count_honors_implicit_inner_joins
real_count = Author.find(:all).sum{|a| a.posts.count }
assert_equal real_count, Author.count(:joins => :posts), "plain inner join count should match the number of referenced posts records"
end
def test_calculate_honors_implicit_inner_joins
real_count = Author.find(:all).sum{|a| a.posts.count }
assert_equal real_count, Author.calculate(:count, 'authors.id', :joins => :posts), "plain inner join count should match the number of referenced posts records"
end
def test_calculate_honors_implicit_inner_joins_and_distinct_and_conditions
real_count = Author.find(:all).select {|a| a.posts.any? {|p| p.title =~ /^Welcome/} }.length
authors_with_welcoming_post_titles = Author.calculate(:count, 'authors.id', :joins => :posts, :distinct => true, :conditions => "posts.title like 'Welcome%'")
assert_equal real_count, authors_with_welcoming_post_titles, "inner join and conditions should have only returned authors posting titles starting with 'Welcome'"
end
end

View file

@ -1,707 +0,0 @@
require "cases/helper"
require 'models/tag'
require 'models/tagging'
require 'models/post'
require 'models/item'
require 'models/comment'
require 'models/author'
require 'models/category'
require 'models/categorization'
require 'models/vertex'
require 'models/edge'
require 'models/book'
require 'models/citation'
class AssociationsJoinModelTest < ActiveRecord::TestCase
self.use_transactional_fixtures = false
fixtures :posts, :authors, :categories, :categorizations, :comments, :tags, :taggings, :author_favorites, :vertices, :items, :books
def test_has_many
assert authors(:david).categories.include?(categories(:general))
end
def test_has_many_inherited
assert authors(:mary).categories.include?(categories(:sti_test))
end
def test_inherited_has_many
assert categories(:sti_test).authors.include?(authors(:mary))
end
def test_has_many_uniq_through_join_model
assert_equal 2, authors(:mary).categorized_posts.size
assert_equal 1, authors(:mary).unique_categorized_posts.size
end
def test_has_many_uniq_through_count
author = authors(:mary)
assert !authors(:mary).unique_categorized_posts.loaded?
assert_queries(1) { assert_equal 1, author.unique_categorized_posts.count }
assert_queries(1) { assert_equal 1, author.unique_categorized_posts.count(:title) }
assert_queries(1) { assert_equal 0, author.unique_categorized_posts.count(:title, :conditions => "title is NULL") }
assert !authors(:mary).unique_categorized_posts.loaded?
end
def test_has_many_uniq_through_find
assert_equal 1, authors(:mary).unique_categorized_posts.find(:all).size
end
def test_has_many_uniq_through_dynamic_find
assert_equal 1, authors(:mary).unique_categorized_posts.find_all_by_title("So I was thinking").size
end
def test_polymorphic_has_many
assert posts(:welcome).taggings.include?(taggings(:welcome_general))
end
def test_polymorphic_has_one
assert_equal taggings(:welcome_general), posts(:welcome).tagging
end
def test_polymorphic_belongs_to
assert_equal posts(:welcome), posts(:welcome).taggings.first.taggable
end
def test_polymorphic_has_many_going_through_join_model
assert_equal tags(:general), tag = posts(:welcome).tags.first
assert_no_queries do
tag.tagging
end
end
def test_count_polymorphic_has_many
assert_equal 1, posts(:welcome).taggings.count
assert_equal 1, posts(:welcome).tags.count
end
def test_polymorphic_has_many_going_through_join_model_with_find
assert_equal tags(:general), tag = posts(:welcome).tags.find(:first)
assert_no_queries do
tag.tagging
end
end
def test_polymorphic_has_many_going_through_join_model_with_include_on_source_reflection
assert_equal tags(:general), tag = posts(:welcome).funky_tags.first
assert_no_queries do
tag.tagging
end
end
def test_polymorphic_has_many_going_through_join_model_with_include_on_source_reflection_with_find
assert_equal tags(:general), tag = posts(:welcome).funky_tags.find(:first)
assert_no_queries do
tag.tagging
end
end
def test_polymorphic_has_many_going_through_join_model_with_disabled_include
assert_equal tags(:general), tag = posts(:welcome).tags.add_joins_and_select.first
assert_queries 1 do
tag.tagging
end
end
def test_polymorphic_has_many_going_through_join_model_with_custom_select_and_joins
assert_equal tags(:general), tag = posts(:welcome).tags.add_joins_and_select.first
tag.author_id
end
def test_polymorphic_has_many_going_through_join_model_with_custom_foreign_key
assert_equal tags(:misc), taggings(:welcome_general).super_tag
assert_equal tags(:misc), posts(:welcome).super_tags.first
end
def test_polymorphic_has_many_create_model_with_inheritance_and_custom_base_class
post = SubStiPost.create :title => 'SubStiPost', :body => 'SubStiPost body'
assert_instance_of SubStiPost, post
tagging = tags(:misc).taggings.create(:taggable => post)
assert_equal "SubStiPost", tagging.taggable_type
end
def test_polymorphic_has_many_going_through_join_model_with_inheritance
assert_equal tags(:general), posts(:thinking).tags.first
end
def test_polymorphic_has_many_going_through_join_model_with_inheritance_with_custom_class_name
assert_equal tags(:general), posts(:thinking).funky_tags.first
end
def test_polymorphic_has_many_create_model_with_inheritance
post = posts(:thinking)
assert_instance_of SpecialPost, post
tagging = tags(:misc).taggings.create(:taggable => post)
assert_equal "Post", tagging.taggable_type
end
def test_polymorphic_has_one_create_model_with_inheritance
tagging = tags(:misc).create_tagging(:taggable => posts(:thinking))
assert_equal "Post", tagging.taggable_type
end
def test_set_polymorphic_has_many
tagging = tags(:misc).taggings.create
posts(:thinking).taggings << tagging
assert_equal "Post", tagging.taggable_type
end
def test_set_polymorphic_has_one
tagging = tags(:misc).taggings.create
posts(:thinking).tagging = tagging
assert_equal "Post", tagging.taggable_type
end
def test_create_polymorphic_has_many_with_scope
old_count = posts(:welcome).taggings.count
tagging = posts(:welcome).taggings.create(:tag => tags(:misc))
assert_equal "Post", tagging.taggable_type
assert_equal old_count+1, posts(:welcome).taggings.count
end
def test_create_bang_polymorphic_with_has_many_scope
old_count = posts(:welcome).taggings.count
tagging = posts(:welcome).taggings.create!(:tag => tags(:misc))
assert_equal "Post", tagging.taggable_type
assert_equal old_count+1, posts(:welcome).taggings.count
end
def test_create_polymorphic_has_one_with_scope
old_count = Tagging.count
tagging = posts(:welcome).tagging.create(:tag => tags(:misc))
assert_equal "Post", tagging.taggable_type
assert_equal old_count+1, Tagging.count
end
def test_delete_polymorphic_has_many_with_delete_all
assert_equal 1, posts(:welcome).taggings.count
posts(:welcome).taggings.first.update_attribute :taggable_type, 'PostWithHasManyDeleteAll'
post = find_post_with_dependency(1, :has_many, :taggings, :delete_all)
old_count = Tagging.count
post.destroy
assert_equal old_count-1, Tagging.count
assert_equal 0, posts(:welcome).taggings.count
end
def test_delete_polymorphic_has_many_with_destroy
assert_equal 1, posts(:welcome).taggings.count
posts(:welcome).taggings.first.update_attribute :taggable_type, 'PostWithHasManyDestroy'
post = find_post_with_dependency(1, :has_many, :taggings, :destroy)
old_count = Tagging.count
post.destroy
assert_equal old_count-1, Tagging.count
assert_equal 0, posts(:welcome).taggings.count
end
def test_delete_polymorphic_has_many_with_nullify
assert_equal 1, posts(:welcome).taggings.count
posts(:welcome).taggings.first.update_attribute :taggable_type, 'PostWithHasManyNullify'
post = find_post_with_dependency(1, :has_many, :taggings, :nullify)
old_count = Tagging.count
post.destroy
assert_equal old_count, Tagging.count
assert_equal 0, posts(:welcome).taggings.count
end
def test_delete_polymorphic_has_one_with_destroy
assert posts(:welcome).tagging
posts(:welcome).tagging.update_attribute :taggable_type, 'PostWithHasOneDestroy'
post = find_post_with_dependency(1, :has_one, :tagging, :destroy)
old_count = Tagging.count
post.destroy
assert_equal old_count-1, Tagging.count
assert_nil posts(:welcome).tagging(true)
end
def test_delete_polymorphic_has_one_with_nullify
assert posts(:welcome).tagging
posts(:welcome).tagging.update_attribute :taggable_type, 'PostWithHasOneNullify'
post = find_post_with_dependency(1, :has_one, :tagging, :nullify)
old_count = Tagging.count
post.destroy
assert_equal old_count, Tagging.count
assert_nil posts(:welcome).tagging(true)
end
def test_has_many_with_piggyback
assert_equal "2", categories(:sti_test).authors.first.post_id.to_s
end
def test_include_has_many_through
posts = Post.find(:all, :order => 'posts.id')
posts_with_authors = Post.find(:all, :include => :authors, :order => 'posts.id')
assert_equal posts.length, posts_with_authors.length
posts.length.times do |i|
assert_equal posts[i].authors.length, assert_no_queries { posts_with_authors[i].authors.length }
end
end
def test_include_polymorphic_has_one
post = Post.find_by_id(posts(:welcome).id, :include => :tagging)
tagging = taggings(:welcome_general)
assert_no_queries do
assert_equal tagging, post.tagging
end
end
def test_include_polymorphic_has_one_defined_in_abstract_parent
item = Item.find_by_id(items(:dvd).id, :include => :tagging)
tagging = taggings(:godfather)
assert_no_queries do
assert_equal tagging, item.tagging
end
end
def test_include_polymorphic_has_many_through
posts = Post.find(:all, :order => 'posts.id')
posts_with_tags = Post.find(:all, :include => :tags, :order => 'posts.id')
assert_equal posts.length, posts_with_tags.length
posts.length.times do |i|
assert_equal posts[i].tags.length, assert_no_queries { posts_with_tags[i].tags.length }
end
end
def test_include_polymorphic_has_many
posts = Post.find(:all, :order => 'posts.id')
posts_with_taggings = Post.find(:all, :include => :taggings, :order => 'posts.id')
assert_equal posts.length, posts_with_taggings.length
posts.length.times do |i|
assert_equal posts[i].taggings.length, assert_no_queries { posts_with_taggings[i].taggings.length }
end
end
def test_has_many_find_all
assert_equal [categories(:general)], authors(:david).categories.find(:all)
end
def test_has_many_find_first
assert_equal categories(:general), authors(:david).categories.find(:first)
end
def test_has_many_with_hash_conditions
assert_equal categories(:general), authors(:david).categories_like_general.find(:first)
end
def test_has_many_find_conditions
assert_equal categories(:general), authors(:david).categories.find(:first, :conditions => "categories.name = 'General'")
assert_equal nil, authors(:david).categories.find(:first, :conditions => "categories.name = 'Technology'")
end
def test_has_many_class_methods_called_by_method_missing
assert_equal categories(:general), authors(:david).categories.find_all_by_name('General').first
assert_equal nil, authors(:david).categories.find_by_name('Technology')
end
def test_has_many_array_methods_called_by_method_missing
assert true, authors(:david).categories.any? { |category| category.name == 'General' }
assert_nothing_raised { authors(:david).categories.sort }
end
def test_has_many_going_through_join_model_with_custom_foreign_key
assert_equal [], posts(:thinking).authors
assert_equal [authors(:mary)], posts(:authorless).authors
end
def test_both_scoped_and_explicit_joins_should_be_respected
assert_nothing_raised do
Post.send(:with_scope, :find => {:joins => "left outer join comments on comments.id = posts.id"}) do
Post.find :all, :select => "comments.id, authors.id", :joins => "left outer join authors on authors.id = posts.author_id"
end
end
end
def test_belongs_to_polymorphic_with_counter_cache
assert_equal 0, posts(:welcome)[:taggings_count]
tagging = posts(:welcome).taggings.create(:tag => tags(:general))
assert_equal 1, posts(:welcome, :reload)[:taggings_count]
tagging.destroy
assert posts(:welcome, :reload)[:taggings_count].zero?
end
def test_unavailable_through_reflection
assert_raise(ActiveRecord::HasManyThroughAssociationNotFoundError) { authors(:david).nothings }
end
def test_has_many_through_join_model_with_conditions
assert_equal [], posts(:welcome).invalid_taggings
assert_equal [], posts(:welcome).invalid_tags
end
def test_has_many_polymorphic
assert_raise ActiveRecord::HasManyThroughAssociationPolymorphicError do
assert_equal posts(:welcome, :thinking), tags(:general).taggables
end
assert_raise ActiveRecord::EagerLoadPolymorphicError do
assert_equal posts(:welcome, :thinking), tags(:general).taggings.find(:all, :include => :taggable, :conditions => 'bogus_table.column = 1')
end
end
def test_has_many_polymorphic_with_source_type
assert_equal posts(:welcome, :thinking), tags(:general).tagged_posts
end
def test_eager_has_many_polymorphic_with_source_type
tag_with_include = Tag.find(tags(:general).id, :include => :tagged_posts)
desired = posts(:welcome, :thinking)
assert_no_queries do
assert_equal desired, tag_with_include.tagged_posts
end
assert_equal 5, tag_with_include.taggings.length
end
def test_has_many_through_has_many_find_all
assert_equal comments(:greetings), authors(:david).comments.find(:all, :order => 'comments.id').first
end
def test_has_many_through_has_many_find_all_with_custom_class
assert_equal comments(:greetings), authors(:david).funky_comments.find(:all, :order => 'comments.id').first
end
def test_has_many_through_has_many_find_first
assert_equal comments(:greetings), authors(:david).comments.find(:first, :order => 'comments.id')
end
def test_has_many_through_has_many_find_conditions
options = { :conditions => "comments.#{QUOTED_TYPE}='SpecialComment'", :order => 'comments.id' }
assert_equal comments(:does_it_hurt), authors(:david).comments.find(:first, options)
end
def test_has_many_through_has_many_find_by_id
assert_equal comments(:more_greetings), authors(:david).comments.find(2)
end
def test_has_many_through_polymorphic_has_one
assert_raise(ActiveRecord::HasManyThroughSourceAssociationMacroError) { authors(:david).tagging }
end
def test_has_many_through_polymorphic_has_many
assert_equal taggings(:welcome_general, :thinking_general), authors(:david).taggings.uniq.sort_by { |t| t.id }
end
def test_include_has_many_through_polymorphic_has_many
author = Author.find_by_id(authors(:david).id, :include => :taggings)
expected_taggings = taggings(:welcome_general, :thinking_general)
assert_no_queries do
assert_equal expected_taggings, author.taggings.uniq.sort_by { |t| t.id }
end
end
def test_has_many_through_has_many_through
assert_raise(ActiveRecord::HasManyThroughSourceAssociationMacroError) { authors(:david).tags }
end
def test_has_many_through_habtm
assert_raise(ActiveRecord::HasManyThroughSourceAssociationMacroError) { authors(:david).post_categories }
end
def test_eager_load_has_many_through_has_many
author = Author.find :first, :conditions => ['name = ?', 'David'], :include => :comments, :order => 'comments.id'
SpecialComment.new; VerySpecialComment.new
assert_no_queries do
assert_equal [1,2,3,5,6,7,8,9,10], author.comments.collect(&:id)
end
end
def test_eager_load_has_many_through_has_many_with_conditions
post = Post.find(:first, :include => :invalid_tags)
assert_no_queries do
post.invalid_tags
end
end
def test_eager_belongs_to_and_has_one_not_singularized
assert_nothing_raised do
Author.find(:first, :include => :author_address)
AuthorAddress.find(:first, :include => :author)
end
end
def test_self_referential_has_many_through
assert_equal [authors(:mary)], authors(:david).favorite_authors
assert_equal [], authors(:mary).favorite_authors
end
def test_add_to_self_referential_has_many_through
new_author = Author.create(:name => "Bob")
authors(:david).author_favorites.create :favorite_author => new_author
assert_equal new_author, authors(:david).reload.favorite_authors.first
end
def test_has_many_through_uses_conditions_specified_on_the_has_many_association
author = Author.find(:first)
assert !author.comments.blank?
assert author.nonexistant_comments.blank?
end
def test_has_many_through_uses_correct_attributes
assert_nil posts(:thinking).tags.find_by_name("General").attributes["tag_id"]
end
def test_associating_unsaved_records_with_has_many_through
saved_post = posts(:thinking)
new_tag = Tag.new(:name => "new")
saved_post.tags << new_tag
assert !new_tag.new_record? #consistent with habtm!
assert !saved_post.new_record?
assert saved_post.tags.include?(new_tag)
assert !new_tag.new_record?
assert saved_post.reload.tags(true).include?(new_tag)
new_post = Post.new(:title => "Association replacmenet works!", :body => "You best believe it.")
saved_tag = tags(:general)
new_post.tags << saved_tag
assert new_post.new_record?
assert !saved_tag.new_record?
assert new_post.tags.include?(saved_tag)
new_post.save!
assert !new_post.new_record?
assert new_post.reload.tags(true).include?(saved_tag)
assert posts(:thinking).tags.build.new_record?
assert posts(:thinking).tags.new.new_record?
end
def test_create_associate_when_adding_to_has_many_through
count = posts(:thinking).tags.count
push = Tag.create!(:name => 'pushme')
post_thinking = posts(:thinking)
assert_nothing_raised { post_thinking.tags << push }
assert_nil( wrong = post_thinking.tags.detect { |t| t.class != Tag },
message = "Expected a Tag in tags collection, got #{wrong.class}.")
assert_nil( wrong = post_thinking.taggings.detect { |t| t.class != Tagging },
message = "Expected a Tagging in taggings collection, got #{wrong.class}.")
assert_equal(count + 1, post_thinking.tags.size)
assert_equal(count + 1, post_thinking.tags(true).size)
assert_kind_of Tag, post_thinking.tags.create!(:name => 'foo')
assert_nil( wrong = post_thinking.tags.detect { |t| t.class != Tag },
message = "Expected a Tag in tags collection, got #{wrong.class}.")
assert_nil( wrong = post_thinking.taggings.detect { |t| t.class != Tagging },
message = "Expected a Tagging in taggings collection, got #{wrong.class}.")
assert_equal(count + 2, post_thinking.tags.size)
assert_equal(count + 2, post_thinking.tags(true).size)
assert_nothing_raised { post_thinking.tags.concat(Tag.create!(:name => 'abc'), Tag.create!(:name => 'def')) }
assert_nil( wrong = post_thinking.tags.detect { |t| t.class != Tag },
message = "Expected a Tag in tags collection, got #{wrong.class}.")
assert_nil( wrong = post_thinking.taggings.detect { |t| t.class != Tagging },
message = "Expected a Tagging in taggings collection, got #{wrong.class}.")
assert_equal(count + 4, post_thinking.tags.size)
assert_equal(count + 4, post_thinking.tags(true).size)
# Raises if the wrong reflection name is used to set the Edge belongs_to
assert_nothing_raised { vertices(:vertex_1).sinks << vertices(:vertex_5) }
end
def test_has_many_through_collection_size_doesnt_load_target_if_not_loaded
author = authors(:david)
assert_equal 9, author.comments.size
assert !author.comments.loaded?
end
uses_mocha('has_many_through_collection_size_uses_counter_cache_if_it_exists') do
def test_has_many_through_collection_size_uses_counter_cache_if_it_exists
author = authors(:david)
author.stubs(:read_attribute).with('comments_count').returns(100)
assert_equal 100, author.comments.size
assert !author.comments.loaded?
end
end
def test_adding_junk_to_has_many_through_should_raise_type_mismatch
assert_raise(ActiveRecord::AssociationTypeMismatch) { posts(:thinking).tags << "Uhh what now?" }
end
def test_adding_to_has_many_through_should_return_self
tags = posts(:thinking).tags
assert_equal tags, posts(:thinking).tags.push(tags(:general))
end
def test_delete_associate_when_deleting_from_has_many_through_with_nonstandard_id
count = books(:awdr).references.count
references_before = books(:awdr).references
book = Book.create!(:name => 'Getting Real')
book_awdr = books(:awdr)
book_awdr.references << book
assert_equal(count + 1, book_awdr.references(true).size)
assert_nothing_raised { book_awdr.references.delete(book) }
assert_equal(count, book_awdr.references.size)
assert_equal(count, book_awdr.references(true).size)
assert_equal(references_before.sort, book_awdr.references.sort)
end
def test_delete_associate_when_deleting_from_has_many_through
count = posts(:thinking).tags.count
tags_before = posts(:thinking).tags
tag = Tag.create!(:name => 'doomed')
post_thinking = posts(:thinking)
post_thinking.tags << tag
assert_equal(count + 1, post_thinking.taggings(true).size)
assert_equal(count + 1, post_thinking.tags(true).size)
assert_nothing_raised { post_thinking.tags.delete(tag) }
assert_equal(count, post_thinking.tags.size)
assert_equal(count, post_thinking.tags(true).size)
assert_equal(count, post_thinking.taggings(true).size)
assert_equal(tags_before.sort, post_thinking.tags.sort)
end
def test_delete_associate_when_deleting_from_has_many_through_with_multiple_tags
count = posts(:thinking).tags.count
tags_before = posts(:thinking).tags
doomed = Tag.create!(:name => 'doomed')
doomed2 = Tag.create!(:name => 'doomed2')
quaked = Tag.create!(:name => 'quaked')
post_thinking = posts(:thinking)
post_thinking.tags << doomed << doomed2
assert_equal(count + 2, post_thinking.tags(true).size)
assert_nothing_raised { post_thinking.tags.delete(doomed, doomed2, quaked) }
assert_equal(count, post_thinking.tags.size)
assert_equal(count, post_thinking.tags(true).size)
assert_equal(tags_before.sort, post_thinking.tags.sort)
end
def test_deleting_junk_from_has_many_through_should_raise_type_mismatch
assert_raise(ActiveRecord::AssociationTypeMismatch) { posts(:thinking).tags.delete("Uhh what now?") }
end
def test_has_many_through_sum_uses_calculations
assert_nothing_raised { authors(:david).comments.sum(:post_id) }
end
def test_calculations_on_has_many_through_should_disambiguate_fields
assert_nothing_raised { authors(:david).categories.maximum(:id) }
end
def test_calculations_on_has_many_through_should_not_disambiguate_fields_unless_necessary
assert_nothing_raised { authors(:david).categories.maximum("categories.id") }
end
def test_has_many_through_has_many_with_sti
assert_equal [comments(:does_it_hurt)], authors(:david).special_post_comments
end
def test_uniq_has_many_through_should_retain_order
comment_ids = authors(:david).comments.map(&:id)
assert_equal comment_ids.sort, authors(:david).ordered_uniq_comments.map(&:id)
assert_equal comment_ids.sort.reverse, authors(:david).ordered_uniq_comments_desc.map(&:id)
end
def test_polymorphic_has_many
expected = taggings(:welcome_general)
p = Post.find(posts(:welcome).id, :include => :taggings)
assert_no_queries {assert p.taggings.include?(expected)}
assert posts(:welcome).taggings.include?(taggings(:welcome_general))
end
def test_polymorphic_has_one
expected = posts(:welcome)
tagging = Tagging.find(taggings(:welcome_general).id, :include => :taggable)
assert_no_queries { assert_equal expected, tagging.taggable}
end
def test_polymorphic_belongs_to
p = Post.find(posts(:welcome).id, :include => {:taggings => :taggable})
assert_no_queries {assert_equal posts(:welcome), p.taggings.first.taggable}
end
def test_preload_polymorphic_has_many_through
posts = Post.find(:all, :order => 'posts.id')
posts_with_tags = Post.find(:all, :include => :tags, :order => 'posts.id')
assert_equal posts.length, posts_with_tags.length
posts.length.times do |i|
assert_equal posts[i].tags.length, assert_no_queries { posts_with_tags[i].tags.length }
end
end
def test_preload_polymorph_many_types
taggings = Tagging.find :all, :include => :taggable, :conditions => ['taggable_type != ?', 'FakeModel']
assert_no_queries do
taggings.first.taggable.id
taggings[1].taggable.id
end
taggables = taggings.map(&:taggable)
assert taggables.include?(items(:dvd))
assert taggables.include?(posts(:welcome))
end
def test_preload_nil_polymorphic_belongs_to
assert_nothing_raised do
taggings = Tagging.find(:all, :include => :taggable, :conditions => ['taggable_type IS NULL'])
end
end
def test_preload_polymorphic_has_many
posts = Post.find(:all, :order => 'posts.id')
posts_with_taggings = Post.find(:all, :include => :taggings, :order => 'posts.id')
assert_equal posts.length, posts_with_taggings.length
posts.length.times do |i|
assert_equal posts[i].taggings.length, assert_no_queries { posts_with_taggings[i].taggings.length }
end
end
def test_belongs_to_shared_parent
comments = Comment.find(:all, :include => :post, :conditions => 'post_id = 1')
assert_no_queries do
assert_equal comments.first.post, comments[1].post
end
end
def test_has_many_through_include_uses_array_include_after_loaded
david = authors(:david)
david.categories.class # force load target
category = david.categories.first
assert_no_queries do
assert david.categories.loaded?
assert david.categories.include?(category)
end
end
def test_has_many_through_include_checks_if_record_exists_if_target_not_loaded
david = authors(:david)
category = david.categories.first
david.reload
assert ! david.categories.loaded?
assert_queries(1) do
assert david.categories.include?(category)
end
assert ! david.categories.loaded?
end
def test_has_many_through_include_returns_false_for_non_matching_record_to_verify_scoping
david = authors(:david)
category = Category.create!(:name => 'Not Associated')
assert ! david.categories.loaded?
assert ! david.categories.include?(category)
end
private
# create dynamic Post models to allow different dependency options
def find_post_with_dependency(post_id, association, association_name, dependency)
class_name = "PostWith#{association.to_s.classify}#{dependency.to_s.classify}"
Post.find(post_id).update_attribute :type, class_name
klass = Object.const_set(class_name, Class.new(ActiveRecord::Base))
klass.set_table_name 'posts'
klass.send(association, association_name, :as => :taggable, :dependent => dependency)
klass.find(post_id)
end
end

View file

@ -1,262 +0,0 @@
require "cases/helper"
require 'models/developer'
require 'models/project'
require 'models/company'
require 'models/topic'
require 'models/reply'
require 'models/computer'
require 'models/customer'
require 'models/order'
require 'models/categorization'
require 'models/category'
require 'models/post'
require 'models/author'
require 'models/comment'
require 'models/tag'
require 'models/tagging'
require 'models/person'
require 'models/reader'
require 'models/parrot'
require 'models/pirate'
require 'models/treasure'
require 'models/price_estimate'
require 'models/club'
require 'models/member'
require 'models/membership'
require 'models/sponsor'
class AssociationsTest < ActiveRecord::TestCase
fixtures :accounts, :companies, :developers, :projects, :developers_projects,
:computers
def test_include_with_order_works
assert_nothing_raised {Account.find(:first, :order => 'id', :include => :firm)}
assert_nothing_raised {Account.find(:first, :order => :id, :include => :firm)}
end
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_should_construct_new_finder_sql_after_create
person = Person.new :first_name => 'clark'
assert_equal [], person.readers.find(:all)
person.save!
reader = Reader.create! :person => person, :post => Post.new(:title => "foo", :body => "bar")
assert_equal [reader], person.readers.find(:all)
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_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_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"
assert_equal 1, firm.clients(true).size, "New firm should have reloaded clients count"
end
def test_storing_in_pstore
require "tmpdir"
store_filename = File.join(Dir.tmpdir, "ar-pstore-association-test")
File.delete(store_filename) if File.exist?(store_filename)
require "pstore"
apple = Firm.create("name" => "Apple")
natural = Client.new("name" => "Natural Company")
apple.clients << natural
db = PStore.new(store_filename)
db.transaction do
db["apple"] = apple
end
db = PStore.new(store_filename)
db.transaction do
assert_equal "Natural Company", db["apple"].clients.first.name
end
end
end
class AssociationProxyTest < ActiveRecord::TestCase
fixtures :authors, :posts, :categorizations, :categories, :developers, :projects, :developers_projects
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.class # 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.class # force load target
assert_equal david.posts_with_extension, david.posts_with_extension.testing_proxy_target
end
def test_push_does_not_load_target
david = authors(:david)
david.posts << (post = Post.new(:title => "New on Edge", :body => "More cool stuff!"))
assert !david.posts.loaded?
assert david.posts.include?(post)
end
def test_push_has_many_through_does_not_load_target
david = authors(:david)
david.categories << categories(:technology)
assert !david.categories.loaded?
assert david.categories.include?(categories(:technology))
end
def test_push_followed_by_save_does_not_load_target
david = authors(:david)
david.posts << (post = Post.new(:title => "New on Edge", :body => "More cool stuff!"))
assert !david.posts.loaded?
david.save
assert !david.posts.loaded?
assert david.posts.include?(post)
end
def test_push_does_not_lose_additions_to_new_record
josh = Author.new(:name => "Josh")
josh.posts << Post.new(:title => "New on Edge", :body => "More cool stuff!")
assert josh.posts.loaded?
assert_equal 1, josh.posts.size
end
def test_save_on_parent_does_not_load_target
david = developers(:david)
assert !david.projects.loaded?
david.update_attribute(:created_at, Time.now)
assert !david.projects.loaded?
end
def test_inspect_does_not_reload_a_not_yet_loaded_target
andreas = Developer.new :name => 'Andreas', :log => 'new developer added'
assert !andreas.audit_logs.loaded?
assert_match(/message: "new developer added"/, andreas.audit_logs.inspect)
end
def test_save_on_parent_saves_children
developer = Developer.create :name => "Bryan", :salary => 50_000
assert_equal 1, developer.reload.audit_logs.size
end
def test_create_via_association_with_block
post = authors(:david).posts.create(:title => "New on Edge") {|p| p.body = "More cool stuff!"}
assert_equal post.title, "New on Edge"
assert_equal post.body, "More cool stuff!"
end
def test_create_with_bang_via_association_with_block
post = authors(:david).posts.create!(:title => "New on Edge") {|p| p.body = "More cool stuff!"}
assert_equal post.title, "New on Edge"
assert_equal post.body, "More cool stuff!"
end
def test_failed_reload_returns_nil
p = setup_dangling_association
assert_nil p.author.reload
end
def test_failed_reset_returns_nil
p = setup_dangling_association
assert_nil p.author.reset
end
def test_reload_returns_assocition
david = developers(:david)
assert_nothing_raised do
assert_equal david.projects, david.projects.reload.reload
end
end
def setup_dangling_association
josh = Author.create(:name => "Josh")
p = Post.create(:title => "New on Edge", :body => "More cool stuff!", :author => josh)
josh.destroy
p
end
end
class OverridingAssociationsTest < ActiveRecord::TestCase
class Person < ActiveRecord::Base; end
class DifferentPerson < ActiveRecord::Base; end
class PeopleList < ActiveRecord::Base
has_and_belongs_to_many :has_and_belongs_to_many, :before_add => :enlist
has_many :has_many, :before_add => :enlist
belongs_to :belongs_to
has_one :has_one
end
class DifferentPeopleList < PeopleList
# Different association with the same name, callbacks should be omitted here.
has_and_belongs_to_many :has_and_belongs_to_many, :class_name => 'DifferentPerson'
has_many :has_many, :class_name => 'DifferentPerson'
belongs_to :belongs_to, :class_name => 'DifferentPerson'
has_one :has_one, :class_name => 'DifferentPerson'
end
def test_habtm_association_redefinition_callbacks_should_differ_and_not_inherited
# redeclared association on AR descendant should not inherit callbacks from superclass
callbacks = PeopleList.read_inheritable_attribute(:before_add_for_has_and_belongs_to_many)
assert_equal([:enlist], callbacks)
callbacks = DifferentPeopleList.read_inheritable_attribute(:before_add_for_has_and_belongs_to_many)
assert_equal([], callbacks)
end
def test_has_many_association_redefinition_callbacks_should_differ_and_not_inherited
# redeclared association on AR descendant should not inherit callbacks from superclass
callbacks = PeopleList.read_inheritable_attribute(:before_add_for_has_many)
assert_equal([:enlist], callbacks)
callbacks = DifferentPeopleList.read_inheritable_attribute(:before_add_for_has_many)
assert_equal([], callbacks)
end
def test_habtm_association_redefinition_reflections_should_differ_and_not_inherited
assert_not_equal(
PeopleList.reflect_on_association(:has_and_belongs_to_many),
DifferentPeopleList.reflect_on_association(:has_and_belongs_to_many)
)
end
def test_has_many_association_redefinition_reflections_should_differ_and_not_inherited
assert_not_equal(
PeopleList.reflect_on_association(:has_many),
DifferentPeopleList.reflect_on_association(:has_many)
)
end
def test_belongs_to_association_redefinition_reflections_should_differ_and_not_inherited
assert_not_equal(
PeopleList.reflect_on_association(:belongs_to),
DifferentPeopleList.reflect_on_association(:belongs_to)
)
end
def test_has_one_association_redefinition_reflections_should_differ_and_not_inherited
assert_not_equal(
PeopleList.reflect_on_association(:has_one),
DifferentPeopleList.reflect_on_association(:has_one)
)
end
end

View file

@ -1,238 +0,0 @@
require "cases/helper"
require 'models/topic'
class AttributeMethodsTest < ActiveRecord::TestCase
fixtures :topics
def setup
@old_suffixes = ActiveRecord::Base.send(:attribute_method_suffixes).dup
@target = Class.new(ActiveRecord::Base)
@target.table_name = 'topics'
end
def teardown
ActiveRecord::Base.send(:attribute_method_suffixes).clear
ActiveRecord::Base.attribute_method_suffix *@old_suffixes
end
def test_match_attribute_method_query_returns_match_data
assert_not_nil md = @target.match_attribute_method?('title=')
assert_equal 'title', md.pre_match
assert_equal ['='], md.captures
%w(_hello_world ist! _maybe?).each do |suffix|
@target.class_eval "def attribute#{suffix}(*args) args end"
@target.attribute_method_suffix suffix
assert_not_nil md = @target.match_attribute_method?("title#{suffix}")
assert_equal 'title', md.pre_match
assert_equal [suffix], md.captures
end
end
def test_declared_attribute_method_affects_respond_to_and_method_missing
topic = @target.new(:title => 'Budget')
assert topic.respond_to?('title')
assert_equal 'Budget', topic.title
assert !topic.respond_to?('title_hello_world')
assert_raise(NoMethodError) { topic.title_hello_world }
%w(_hello_world _it! _candidate= able?).each do |suffix|
@target.class_eval "def attribute#{suffix}(*args) args end"
@target.attribute_method_suffix suffix
meth = "title#{suffix}"
assert topic.respond_to?(meth)
assert_equal ['title'], topic.send(meth)
assert_equal ['title', 'a'], topic.send(meth, 'a')
assert_equal ['title', 1, 2, 3], topic.send(meth, 1, 2, 3)
end
end
def test_should_unserialize_attributes_for_frozen_records
myobj = {:value1 => :value2}
topic = Topic.create("content" => myobj)
topic.freeze
assert_equal myobj, topic.content
end
def test_kernel_methods_not_implemented_in_activerecord
%w(test name display y).each do |method|
assert_equal false, ActiveRecord::Base.instance_method_already_implemented?(method), "##{method} is defined"
end
end
def test_primary_key_implemented
assert_equal true, Class.new(ActiveRecord::Base).instance_method_already_implemented?('id')
end
def test_defined_kernel_methods_implemented_in_model
%w(test name display y).each do |method|
klass = Class.new ActiveRecord::Base
klass.class_eval "def #{method}() 'defined #{method}' end"
assert_equal true, klass.instance_method_already_implemented?(method), "##{method} is not defined"
end
end
def test_defined_kernel_methods_implemented_in_model_abstract_subclass
%w(test name display y).each do |method|
abstract = Class.new ActiveRecord::Base
abstract.class_eval "def #{method}() 'defined #{method}' end"
abstract.abstract_class = true
klass = Class.new abstract
assert_equal true, klass.instance_method_already_implemented?(method), "##{method} is not defined"
end
end
def test_raises_dangerous_attribute_error_when_defining_activerecord_method_in_model
%w(save create_or_update).each do |method|
klass = Class.new ActiveRecord::Base
klass.class_eval "def #{method}() 'defined #{method}' end"
assert_raises ActiveRecord::DangerousAttributeError do
klass.instance_method_already_implemented?(method)
end
end
end
def test_only_time_related_columns_are_meant_to_be_cached_by_default
expected = %w(datetime timestamp time date).sort
assert_equal expected, ActiveRecord::Base.attribute_types_cached_by_default.map(&:to_s).sort
end
def test_declaring_attributes_as_cached_adds_them_to_the_attributes_cached_by_default
default_attributes = Topic.cached_attributes
Topic.cache_attributes :replies_count
expected = default_attributes + ["replies_count"]
assert_equal expected.sort, Topic.cached_attributes.sort
Topic.instance_variable_set "@cached_attributes", nil
end
def test_time_related_columns_are_actually_cached
column_types = %w(datetime timestamp time date).map(&:to_sym)
column_names = Topic.columns.select{|c| column_types.include?(c.type) }.map(&:name)
assert_equal column_names.sort, Topic.cached_attributes.sort
assert_equal time_related_columns_on_topic.sort, Topic.cached_attributes.sort
end
def test_accessing_cached_attributes_caches_the_converted_values_and_nothing_else
t = topics(:first)
cache = t.instance_variable_get "@attributes_cache"
assert_not_nil cache
assert cache.empty?
all_columns = Topic.columns.map(&:name)
cached_columns = time_related_columns_on_topic
uncached_columns = all_columns - cached_columns
all_columns.each do |attr_name|
attribute_gets_cached = Topic.cache_attribute?(attr_name)
val = t.send attr_name unless attr_name == "type"
if attribute_gets_cached
assert cached_columns.include?(attr_name)
assert_equal val, cache[attr_name]
else
assert uncached_columns.include?(attr_name)
assert !cache.include?(attr_name)
end
end
end
def test_time_attributes_are_retrieved_in_current_time_zone
in_time_zone "Pacific Time (US & Canada)" do
utc_time = Time.utc(2008, 1, 1)
record = @target.new
record[:written_on] = utc_time
assert_equal utc_time, record.written_on # record.written on is equal to (i.e., simultaneous with) utc_time
assert_kind_of ActiveSupport::TimeWithZone, record.written_on # but is a TimeWithZone
assert_equal TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone # and is in the current Time.zone
assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time # and represents time values adjusted accordingly
end
end
def test_setting_time_zone_aware_attribute_to_utc
in_time_zone "Pacific Time (US & Canada)" do
utc_time = Time.utc(2008, 1, 1)
record = @target.new
record.written_on = utc_time
assert_equal utc_time, record.written_on
assert_equal TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
end
end
def test_setting_time_zone_aware_attribute_in_other_time_zone
utc_time = Time.utc(2008, 1, 1)
cst_time = utc_time.in_time_zone("Central Time (US & Canada)")
in_time_zone "Pacific Time (US & Canada)" do
record = @target.new
record.written_on = cst_time
assert_equal utc_time, record.written_on
assert_equal TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
end
end
def test_setting_time_zone_aware_attribute_with_string
utc_time = Time.utc(2008, 1, 1)
(-11..13).each do |timezone_offset|
time_string = utc_time.in_time_zone(timezone_offset).to_s
in_time_zone "Pacific Time (US & Canada)" do
record = @target.new
record.written_on = time_string
assert_equal Time.zone.parse(time_string), record.written_on
assert_equal TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
end
end
end
def test_setting_time_zone_aware_attribute_to_blank_string_returns_nil
in_time_zone "Pacific Time (US & Canada)" do
record = @target.new
record.written_on = ' '
assert_nil record.written_on
end
end
def test_setting_time_zone_aware_attribute_interprets_time_zone_unaware_string_in_time_zone
time_string = 'Tue Jan 01 00:00:00 2008'
(-11..13).each do |timezone_offset|
in_time_zone timezone_offset do
record = @target.new
record.written_on = time_string
assert_equal Time.zone.parse(time_string), record.written_on
assert_equal TimeZone[timezone_offset], record.written_on.time_zone
assert_equal Time.utc(2008, 1, 1), record.written_on.time
end
end
end
def test_setting_time_zone_aware_attribute_in_current_time_zone
utc_time = Time.utc(2008, 1, 1)
in_time_zone "Pacific Time (US & Canada)" do
record = @target.new
record.written_on = utc_time.in_time_zone
assert_equal utc_time, record.written_on
assert_equal TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
end
end
private
def time_related_columns_on_topic
Topic.columns.select{|c| [:time, :date, :datetime, :timestamp].include?(c.type)}.map(&:name)
end
def in_time_zone(zone)
old_zone = Time.zone
old_tz = ActiveRecord::Base.time_zone_aware_attributes
Time.zone = zone ? TimeZone[zone] : nil
ActiveRecord::Base.time_zone_aware_attributes = !zone.nil?
yield
ensure
Time.zone = old_zone
ActiveRecord::Base.time_zone_aware_attributes = old_tz
end
end

File diff suppressed because it is too large Load diff

View file

@ -1,34 +0,0 @@
require "cases/helper"
# Without using prepared statements, it makes no sense to test
# BLOB data with SQL Server, because the length of a statement is
# limited to 8KB.
#
# Without using prepared statements, it makes no sense to test
# BLOB data with DB2 or Firebird, because the length of a statement
# is limited to 32KB.
unless current_adapter?(:SQLServerAdapter, :SybaseAdapter, :DB2Adapter, :FirebirdAdapter)
require 'models/binary'
class BinaryTest < ActiveRecord::TestCase
FIXTURES = %w(flowers.jpg example.log)
def test_load_save
Binary.delete_all
FIXTURES.each do |filename|
data = File.read(ASSETS_ROOT + "/#{filename}")
data.force_encoding('ASCII-8BIT') if data.respond_to?(:force_encoding)
data.freeze
bin = Binary.new(:data => data)
assert_equal data, bin.data, 'Newly assigned data differs from original'
bin.save!
assert_equal data, bin.data, 'Data differs from original after save'
assert_equal data, bin.reload.data, 'Reloaded data differs from original'
end
end
end
end

View file

@ -1,271 +0,0 @@
require "cases/helper"
require 'models/company'
require 'models/topic'
Company.has_many :accounts
class NumericData < ActiveRecord::Base
self.table_name = 'numeric_data'
end
class CalculationsTest < ActiveRecord::TestCase
fixtures :companies, :accounts, :topics
def test_should_sum_field
assert_equal 318, Account.sum(:credit_limit)
end
def test_should_average_field
value = Account.average(:credit_limit)
assert_kind_of Float, value
assert_in_delta 53.0, value, 0.001
end
def test_should_return_nil_as_average
assert_nil NumericData.average(:bank_balance)
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
def test_should_group_by_field
c = Account.sum(:credit_limit, :group => :firm_id)
[1,6,2].each { |firm_id| assert c.keys.include?(firm_id) }
end
def test_should_group_by_summed_field
c = Account.sum(:credit_limit, :group => :firm_id)
assert_equal 50, c[1]
assert_equal 105, c[6]
assert_equal 60, c[2]
end
def test_should_order_by_grouped_field
c = Account.sum(:credit_limit, :group => :firm_id, :order => "firm_id")
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, 53, 50, 50], c.keys.collect { |k| c[k] }
assert_equal [6, 2, 9, 1], c.keys.compact
end
def test_should_limit_calculation
c = Account.sum(:credit_limit, :conditions => "firm_id IS NOT NULL",
:group => :firm_id, :order => "firm_id", :limit => 2)
assert_equal [1, 2], c.keys.compact
end
def test_should_limit_calculation_with_offset
c = Account.sum(:credit_limit, :conditions => "firm_id IS NOT NULL",
:group => :firm_id, :order => "firm_id", :limit => 2, :offset => 1)
assert_equal [2, 6], c.keys.compact
end
def test_should_group_by_summed_field_having_condition
c = Account.sum(:credit_limit, :group => :firm_id,
:having => 'sum(credit_limit) > 50')
assert_nil c[1]
assert_equal 105, c[6]
assert_equal 60, c[2]
end
def test_should_group_by_summed_association
c = Account.sum(:credit_limit, :group => :firm)
assert_equal 50, c[companies(:first_firm)]
assert_equal 105, c[companies(:rails_core)]
assert_equal 60, c[companies(:first_client)]
end
def test_should_sum_field_with_conditions
assert_equal 105, Account.sum(:credit_limit, :conditions => 'firm_id = 6')
end
def test_should_return_zero_if_sum_conditions_return_nothing
assert_equal 0, Account.sum(:credit_limit, :conditions => '1 = 2')
end
def test_should_group_by_summed_field_with_conditions
c = Account.sum(:credit_limit, :conditions => 'firm_id > 1',
:group => :firm_id)
assert_nil c[1]
assert_equal 105, c[6]
assert_equal 60, c[2]
end
def test_should_group_by_summed_field_with_conditions_and_having
c = Account.sum(:credit_limit, :conditions => 'firm_id > 1',
:group => :firm_id,
:having => 'sum(credit_limit) > 60')
assert_nil c[1]
assert_equal 105, c[6]
assert_nil c[2]
end
def test_should_group_by_fields_with_table_alias
c = Account.sum(:credit_limit, :group => 'accounts.firm_id')
assert_equal 50, c[1]
assert_equal 105, c[6]
assert_equal 60, c[2]
end
def test_should_calculate_with_invalid_field
assert_equal 6, Account.calculate(:count, '*')
assert_equal 6, Account.calculate(:count, :all)
end
def test_should_calculate_grouped_with_invalid_field
c = Account.count(:all, :group => 'accounts.firm_id')
assert_equal 1, c[1]
assert_equal 2, c[6]
assert_equal 1, c[2]
end
def test_should_calculate_grouped_association_with_invalid_field
c = Account.count(:all, :group => :firm)
assert_equal 1, c[companies(:first_firm)]
assert_equal 2, c[companies(:rails_core)]
assert_equal 1, c[companies(:first_client)]
end
uses_mocha 'group_by_non_numeric_foreign_key_association' do
def test_should_group_by_association_with_non_numeric_foreign_key
ActiveRecord::Base.connection.expects(:select_all).returns([{"count_all" => 1, "firm_id" => "ABC"}])
firm = mock()
firm.expects(:id).returns("ABC")
firm.expects(:class).returns(Firm)
Company.expects(:find).with(["ABC"]).returns([firm])
column = mock()
column.expects(:name).at_least_once.returns(:firm_id)
column.expects(:type_cast).with("ABC").returns("ABC")
Account.expects(:columns).at_least_once.returns([column])
c = Account.count(:all, :group => :firm)
assert_equal Firm, c.first.first.class
assert_equal 1, c.first.last
end
end
def test_should_calculate_grouped_association_with_foreign_key_option
Account.belongs_to :another_firm, :class_name => 'Firm', :foreign_key => 'firm_id'
c = Account.count(:all, :group => :another_firm)
assert_equal 1, c[companies(:first_firm)]
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(#{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_calculate_grouped_by_function_with_table_alias
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)
end
def test_should_sum_scoped_field_with_conditions
assert_equal 8, companies(:rails_core).companies.sum(:id, :conditions => 'id > 7')
end
def test_should_group_by_scoped_field
c = companies(:rails_core).companies.sum(:id, :group => :name)
assert_equal 7, c['Leetsoft']
assert_equal 8, c['Jadedpixel']
end
def test_should_group_by_summed_field_with_conditions_and_having
c = companies(:rails_core).companies.sum(:id, :group => :name,
:having => 'sum(id) > 7')
assert_nil c['Leetsoft']
assert_equal 8, c['Jadedpixel']
end
def test_should_reject_invalid_options
assert_nothing_raised do
[:count, :sum].each do |func|
# empty options are valid
Company.send(:validate_calculation_options, func)
# these options are valid for all calculations
[:select, :conditions, :joins, :order, :group, :having, :distinct].each do |opt|
Company.send(:validate_calculation_options, func, opt => true)
end
end
# :include is only valid on :count
Company.send(:validate_calculation_options, :count, :include => true)
end
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_should_count_manual_select_with_include
assert_equal 6, Account.count(:select => "DISTINCT accounts.id", :include => :firm)
end
def test_count_with_column_parameter
assert_equal 5, Account.count(:firm_id)
end
def test_count_with_column_and_options_parameter
assert_equal 2, Account.count(:firm_id, :conditions => "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
def test_should_sum_expression
assert_equal "636", Account.sum("2 * credit_limit")
end
end

View file

@ -1,400 +0,0 @@
require "cases/helper"
class CallbackDeveloper < ActiveRecord::Base
set_table_name 'developers'
class << self
def callback_string(callback_method)
"history << [#{callback_method.to_sym.inspect}, :string]"
end
def callback_proc(callback_method)
Proc.new { |model| model.history << [callback_method, :proc] }
end
def define_callback_method(callback_method)
define_method("#{callback_method}_method") do |model|
model.history << [callback_method, :method]
end
end
def callback_object(callback_method)
klass = Class.new
klass.send(:define_method, callback_method) do |model|
model.history << [callback_method, :object]
end
klass.new
end
end
ActiveRecord::Callbacks::CALLBACKS.each do |callback_method|
callback_method_sym = callback_method.to_sym
define_callback_method(callback_method_sym)
send(callback_method, callback_method_sym)
send(callback_method, callback_string(callback_method_sym))
send(callback_method, callback_proc(callback_method_sym))
send(callback_method, callback_object(callback_method_sym))
send(callback_method) { |model| model.history << [callback_method_sym, :block] }
end
def history
@history ||= []
end
# after_initialize and after_find are invoked only if instance methods have been defined.
def after_initialize
end
def after_find
end
end
class ParentDeveloper < ActiveRecord::Base
set_table_name 'developers'
attr_accessor :after_save_called
before_validation {|record| record.after_save_called = true}
end
class ChildDeveloper < ParentDeveloper
end
class RecursiveCallbackDeveloper < ActiveRecord::Base
set_table_name 'developers'
before_save :on_before_save
after_save :on_after_save
attr_reader :on_before_save_called, :on_after_save_called
def on_before_save
@on_before_save_called ||= 0
@on_before_save_called += 1
save unless @on_before_save_called > 1
end
def on_after_save
@on_after_save_called ||= 0
@on_after_save_called += 1
save unless @on_after_save_called > 1
end
end
class ImmutableDeveloper < ActiveRecord::Base
set_table_name 'developers'
validates_inclusion_of :salary, :in => 50000..200000
before_save :cancel
before_destroy :cancel
def cancelled?
@cancelled == true
end
private
def cancel
@cancelled = true
false
end
end
class ImmutableMethodDeveloper < ActiveRecord::Base
set_table_name 'developers'
validates_inclusion_of :salary, :in => 50000..200000
def cancelled?
@cancelled == true
end
def before_save
@cancelled = true
false
end
def before_destroy
@cancelled = true
false
end
end
class CallbackCancellationDeveloper < ActiveRecord::Base
set_table_name 'developers'
def before_create
false
end
end
class CallbacksTest < ActiveRecord::TestCase
fixtures :developers
def test_initialize
david = CallbackDeveloper.new
assert_equal [
[ :after_initialize, :string ],
[ :after_initialize, :proc ],
[ :after_initialize, :object ],
[ :after_initialize, :block ],
], david.history
end
def test_find
david = CallbackDeveloper.find(1)
assert_equal [
[ :after_find, :string ],
[ :after_find, :proc ],
[ :after_find, :object ],
[ :after_find, :block ],
[ :after_initialize, :string ],
[ :after_initialize, :proc ],
[ :after_initialize, :object ],
[ :after_initialize, :block ],
], david.history
end
def test_new_valid?
david = CallbackDeveloper.new
david.valid?
assert_equal [
[ :after_initialize, :string ],
[ :after_initialize, :proc ],
[ :after_initialize, :object ],
[ :after_initialize, :block ],
[ :before_validation, :string ],
[ :before_validation, :proc ],
[ :before_validation, :object ],
[ :before_validation, :block ],
[ :before_validation_on_create, :string ],
[ :before_validation_on_create, :proc ],
[ :before_validation_on_create, :object ],
[ :before_validation_on_create, :block ],
[ :after_validation, :string ],
[ :after_validation, :proc ],
[ :after_validation, :object ],
[ :after_validation, :block ],
[ :after_validation_on_create, :string ],
[ :after_validation_on_create, :proc ],
[ :after_validation_on_create, :object ],
[ :after_validation_on_create, :block ]
], david.history
end
def test_existing_valid?
david = CallbackDeveloper.find(1)
david.valid?
assert_equal [
[ :after_find, :string ],
[ :after_find, :proc ],
[ :after_find, :object ],
[ :after_find, :block ],
[ :after_initialize, :string ],
[ :after_initialize, :proc ],
[ :after_initialize, :object ],
[ :after_initialize, :block ],
[ :before_validation, :string ],
[ :before_validation, :proc ],
[ :before_validation, :object ],
[ :before_validation, :block ],
[ :before_validation_on_update, :string ],
[ :before_validation_on_update, :proc ],
[ :before_validation_on_update, :object ],
[ :before_validation_on_update, :block ],
[ :after_validation, :string ],
[ :after_validation, :proc ],
[ :after_validation, :object ],
[ :after_validation, :block ],
[ :after_validation_on_update, :string ],
[ :after_validation_on_update, :proc ],
[ :after_validation_on_update, :object ],
[ :after_validation_on_update, :block ]
], david.history
end
def test_create
david = CallbackDeveloper.create('name' => 'David', 'salary' => 1000000)
assert_equal [
[ :after_initialize, :string ],
[ :after_initialize, :proc ],
[ :after_initialize, :object ],
[ :after_initialize, :block ],
[ :before_validation, :string ],
[ :before_validation, :proc ],
[ :before_validation, :object ],
[ :before_validation, :block ],
[ :before_validation_on_create, :string ],
[ :before_validation_on_create, :proc ],
[ :before_validation_on_create, :object ],
[ :before_validation_on_create, :block ],
[ :after_validation, :string ],
[ :after_validation, :proc ],
[ :after_validation, :object ],
[ :after_validation, :block ],
[ :after_validation_on_create, :string ],
[ :after_validation_on_create, :proc ],
[ :after_validation_on_create, :object ],
[ :after_validation_on_create, :block ],
[ :before_save, :string ],
[ :before_save, :proc ],
[ :before_save, :object ],
[ :before_save, :block ],
[ :before_create, :string ],
[ :before_create, :proc ],
[ :before_create, :object ],
[ :before_create, :block ],
[ :after_create, :string ],
[ :after_create, :proc ],
[ :after_create, :object ],
[ :after_create, :block ],
[ :after_save, :string ],
[ :after_save, :proc ],
[ :after_save, :object ],
[ :after_save, :block ]
], david.history
end
def test_save
david = CallbackDeveloper.find(1)
david.save
assert_equal [
[ :after_find, :string ],
[ :after_find, :proc ],
[ :after_find, :object ],
[ :after_find, :block ],
[ :after_initialize, :string ],
[ :after_initialize, :proc ],
[ :after_initialize, :object ],
[ :after_initialize, :block ],
[ :before_validation, :string ],
[ :before_validation, :proc ],
[ :before_validation, :object ],
[ :before_validation, :block ],
[ :before_validation_on_update, :string ],
[ :before_validation_on_update, :proc ],
[ :before_validation_on_update, :object ],
[ :before_validation_on_update, :block ],
[ :after_validation, :string ],
[ :after_validation, :proc ],
[ :after_validation, :object ],
[ :after_validation, :block ],
[ :after_validation_on_update, :string ],
[ :after_validation_on_update, :proc ],
[ :after_validation_on_update, :object ],
[ :after_validation_on_update, :block ],
[ :before_save, :string ],
[ :before_save, :proc ],
[ :before_save, :object ],
[ :before_save, :block ],
[ :before_update, :string ],
[ :before_update, :proc ],
[ :before_update, :object ],
[ :before_update, :block ],
[ :after_update, :string ],
[ :after_update, :proc ],
[ :after_update, :object ],
[ :after_update, :block ],
[ :after_save, :string ],
[ :after_save, :proc ],
[ :after_save, :object ],
[ :after_save, :block ]
], david.history
end
def test_destroy
david = CallbackDeveloper.find(1)
david.destroy
assert_equal [
[ :after_find, :string ],
[ :after_find, :proc ],
[ :after_find, :object ],
[ :after_find, :block ],
[ :after_initialize, :string ],
[ :after_initialize, :proc ],
[ :after_initialize, :object ],
[ :after_initialize, :block ],
[ :before_destroy, :string ],
[ :before_destroy, :proc ],
[ :before_destroy, :object ],
[ :before_destroy, :block ],
[ :after_destroy, :string ],
[ :after_destroy, :proc ],
[ :after_destroy, :object ],
[ :after_destroy, :block ]
], david.history
end
def test_delete
david = CallbackDeveloper.find(1)
CallbackDeveloper.delete(david.id)
assert_equal [
[ :after_find, :string ],
[ :after_find, :proc ],
[ :after_find, :object ],
[ :after_find, :block ],
[ :after_initialize, :string ],
[ :after_initialize, :proc ],
[ :after_initialize, :object ],
[ :after_initialize, :block ],
], david.history
end
def test_before_save_returning_false
david = ImmutableDeveloper.find(1)
assert david.valid?
assert !david.save
assert_raises(ActiveRecord::RecordNotSaved) { david.save! }
david = ImmutableDeveloper.find(1)
david.salary = 10_000_000
assert !david.valid?
assert !david.save
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
assert_not_nil ImmutableDeveloper.find_by_id(1)
end
def test_zzz_callback_returning_false # must be run last since we modify CallbackDeveloper
david = CallbackDeveloper.find(1)
CallbackDeveloper.before_validation proc { |model| model.history << [:before_validation, :returning_false]; return false }
CallbackDeveloper.before_validation proc { |model| model.history << [:before_validation, :should_never_get_here] }
david.save
assert_equal [
[ :after_find, :string ],
[ :after_find, :proc ],
[ :after_find, :object ],
[ :after_find, :block ],
[ :after_initialize, :string ],
[ :after_initialize, :proc ],
[ :after_initialize, :object ],
[ :after_initialize, :block ],
[ :before_validation, :string ],
[ :before_validation, :proc ],
[ :before_validation, :object ],
[ :before_validation, :block ],
[ :before_validation, :returning_false ]
], david.history
end
def test_inheritence_of_callbacks
parent = ParentDeveloper.new
assert !parent.after_save_called
parent.save
assert parent.after_save_called
child = ChildDeveloper.new
assert !child.after_save_called
child.save
assert child.after_save_called
end
end

View file

@ -1,32 +0,0 @@
require 'test/unit'
require "cases/helper"
require 'active_support/core_ext/class/inheritable_attributes'
class A
include ClassInheritableAttributes
end
class B < A
write_inheritable_array "first", [ :one, :two ]
end
class C < A
write_inheritable_array "first", [ :three ]
end
class D < B
write_inheritable_array "first", [ :four ]
end
class ClassInheritableAttributesTest < ActiveRecord::TestCase
def test_first_level
assert_equal [ :one, :two ], B.read_inheritable_attribute("first")
assert_equal [ :three ], C.read_inheritable_attribute("first")
end
def test_second_level
assert_equal [ :one, :two, :four ], D.read_inheritable_attribute("first")
assert_equal [ :one, :two ], B.read_inheritable_attribute("first")
end
end

View file

@ -1,17 +0,0 @@
require "cases/helper"
require 'models/topic'
class TestColumnAlias < ActiveRecord::TestCase
fixtures :topics
QUERY = if 'Oracle' == ActiveRecord::Base.connection.adapter_name
'SELECT id AS pk FROM topics WHERE ROWNUM < 2'
else
'SELECT id AS pk FROM topics'
end
def test_column_alias
records = Topic.connection.select_all(QUERY)
assert_equal 'pk', records[0].keys[0]
end
end

View file

@ -1,8 +0,0 @@
require "cases/helper"
class FirebirdConnectionTest < ActiveRecord::TestCase
def test_charset_properly_set
fb_conn = ActiveRecord::Base.connection.instance_variable_get(:@connection)
assert_equal 'UTF8', fb_conn.database.character_set
end
end

View file

@ -1,30 +0,0 @@
require "cases/helper"
class MysqlConnectionTest < ActiveRecord::TestCase
def setup
@connection = ActiveRecord::Base.connection
end
def test_no_automatic_reconnection_after_timeout
assert @connection.active?
@connection.update('set @@wait_timeout=1')
sleep 2
assert !@connection.active?
end
def test_successful_reconnection_after_timeout_with_manual_reconnect
assert @connection.active?
@connection.update('set @@wait_timeout=1')
sleep 2
@connection.reconnect!
assert @connection.active?
end
def test_successful_reconnection_after_timeout_with_verify
assert @connection.active?
@connection.update('set @@wait_timeout=1')
sleep 2
@connection.verify!(0)
assert @connection.active?
end
end

View file

@ -1,69 +0,0 @@
require "cases/helper"
class CopyTableTest < ActiveRecord::TestCase
fixtures :companies, :comments
def setup
@connection = ActiveRecord::Base.connection
class << @connection
public :copy_table, :table_structure, :indexes
end
end
def test_copy_table(from = 'companies', to = 'companies2', options = {})
assert_nothing_raised {copy_table(from, to, options)}
assert_equal row_count(from), row_count(to)
if block_given?
yield from, to, options
else
assert_equal column_names(from), column_names(to)
end
@connection.drop_table(to) rescue nil
end
def test_copy_table_renaming_column
test_copy_table('companies', 'companies2',
:rename => {'client_of' => 'fan_of'}) do |from, to, options|
expected = column_values(from, 'client_of')
assert expected.any?, 'only nils in resultset; real values are needed'
assert_equal expected, column_values(to, 'fan_of')
end
end
def test_copy_table_with_index
test_copy_table('comments', 'comments_with_index') do
@connection.add_index('comments_with_index', ['post_id', 'type'])
test_copy_table('comments_with_index', 'comments_with_index2') do
assert_equal table_indexes_without_name('comments_with_index'),
table_indexes_without_name('comments_with_index2')
end
end
end
def test_copy_table_without_primary_key
test_copy_table('developers_projects', 'programmers_projects')
end
protected
def copy_table(from, to, options = {})
@connection.copy_table(from, to, {:temporary => true}.merge(options))
end
def column_names(table)
@connection.table_structure(table).map {|column| column['name']}
end
def column_values(table, column)
@connection.select_all("SELECT #{column} FROM #{table} ORDER BY id").map {|row| row[column]}
end
def table_indexes_without_name(table)
@connection.indexes('comments_with_index').delete(:name)
end
def row_count(table)
@connection.select_one("SELECT COUNT(*) AS count FROM #{table}")['count']
end
end

View file

@ -1,203 +0,0 @@
require "cases/helper"
class PostgresqlArray < ActiveRecord::Base
end
class PostgresqlMoney < ActiveRecord::Base
end
class PostgresqlNumber < ActiveRecord::Base
end
class PostgresqlTime < ActiveRecord::Base
end
class PostgresqlNetworkAddress < ActiveRecord::Base
end
class PostgresqlBitString < ActiveRecord::Base
end
class PostgresqlOid < ActiveRecord::Base
end
class PostgresqlDataTypeTest < ActiveRecord::TestCase
self.use_transactional_fixtures = false
def setup
@connection = ActiveRecord::Base.connection
@connection.execute("INSERT INTO postgresql_arrays (commission_by_quarter, nicknames) VALUES ( '{35000,21000,18000,17000}', '{foo,bar,baz}' )")
@first_array = PostgresqlArray.find(1)
@connection.execute("INSERT INTO postgresql_moneys (wealth) VALUES ('567.89'::money)")
@connection.execute("INSERT INTO postgresql_moneys (wealth) VALUES ('-567.89'::money)")
@first_money = PostgresqlMoney.find(1)
@second_money = PostgresqlMoney.find(2)
@connection.execute("INSERT INTO postgresql_numbers (single, double) VALUES (123.456, 123456.789)")
@first_number = PostgresqlNumber.find(1)
@connection.execute("INSERT INTO postgresql_times (time_interval) VALUES ('1 year 2 days ago')")
@first_time = PostgresqlTime.find(1)
@connection.execute("INSERT INTO postgresql_network_addresses (cidr_address, inet_address, mac_address) VALUES('192.168.0/24', '172.16.1.254/32', '01:23:45:67:89:0a')")
@first_network_address = PostgresqlNetworkAddress.find(1)
@connection.execute("INSERT INTO postgresql_bit_strings (bit_string, bit_string_varying) VALUES (B'00010101', X'15')")
@first_bit_string = PostgresqlBitString.find(1)
@connection.execute("INSERT INTO postgresql_oids (obj_id) VALUES (1234)")
@first_oid = PostgresqlOid.find(1)
end
def test_data_type_of_array_types
assert_equal :string, @first_array.column_for_attribute(:commission_by_quarter).type
assert_equal :string, @first_array.column_for_attribute(:nicknames).type
end
def test_data_type_of_money_types
assert_equal :decimal, @first_money.column_for_attribute(:wealth).type
end
def test_data_type_of_number_types
assert_equal :float, @first_number.column_for_attribute(:single).type
assert_equal :float, @first_number.column_for_attribute(:double).type
end
def test_data_type_of_time_types
assert_equal :string, @first_time.column_for_attribute(:time_interval).type
end
def test_data_type_of_network_address_types
assert_equal :string, @first_network_address.column_for_attribute(:cidr_address).type
assert_equal :string, @first_network_address.column_for_attribute(:inet_address).type
assert_equal :string, @first_network_address.column_for_attribute(:mac_address).type
end
def test_data_type_of_bit_string_types
assert_equal :string, @first_bit_string.column_for_attribute(:bit_string).type
assert_equal :string, @first_bit_string.column_for_attribute(:bit_string_varying).type
end
def test_data_type_of_oid_types
assert_equal :integer, @first_oid.column_for_attribute(:obj_id).type
end
def test_array_values
assert_equal '{35000,21000,18000,17000}', @first_array.commission_by_quarter
assert_equal '{foo,bar,baz}', @first_array.nicknames
end
def test_money_values
assert_equal 567.89, @first_money.wealth
assert_equal -567.89, @second_money.wealth
end
def test_number_values
assert_equal 123.456, @first_number.single
assert_equal 123456.789, @first_number.double
end
def test_time_values
assert_equal '-1 years -2 days', @first_time.time_interval
end
def test_network_address_values
assert_equal '192.168.0.0/24', @first_network_address.cidr_address
assert_equal '172.16.1.254', @first_network_address.inet_address
assert_equal '01:23:45:67:89:0a', @first_network_address.mac_address
end
def test_bit_string_values
assert_equal '00010101', @first_bit_string.bit_string
assert_equal '00010101', @first_bit_string.bit_string_varying
end
def test_oid_values
assert_equal 1234, @first_oid.obj_id
end
def test_update_integer_array
new_value = '{32800,95000,29350,17000}'
assert @first_array.commission_by_quarter = new_value
assert @first_array.save
assert @first_array.reload
assert_equal @first_array.commission_by_quarter, new_value
assert @first_array.commission_by_quarter = new_value
assert @first_array.save
assert @first_array.reload
assert_equal @first_array.commission_by_quarter, new_value
end
def test_update_text_array
new_value = '{robby,robert,rob,robbie}'
assert @first_array.nicknames = new_value
assert @first_array.save
assert @first_array.reload
assert_equal @first_array.nicknames, new_value
assert @first_array.nicknames = new_value
assert @first_array.save
assert @first_array.reload
assert_equal @first_array.nicknames, new_value
end
def test_update_money
new_value = BigDecimal.new('123.45')
assert @first_money.wealth = new_value
assert @first_money.save
assert @first_money.reload
assert_equal new_value, @first_money.wealth
end
def test_update_number
new_single = 789.012
new_double = 789012.345
assert @first_number.single = new_single
assert @first_number.double = new_double
assert @first_number.save
assert @first_number.reload
assert_equal @first_number.single, new_single
assert_equal @first_number.double, new_double
end
def test_update_time
assert @first_time.time_interval = '2 years 3 minutes'
assert @first_time.save
assert @first_time.reload
assert_equal @first_time.time_interval, '2 years 00:03:00'
end
def test_update_network_address
new_cidr_address = '10.1.2.3/32'
new_inet_address = '10.0.0.0/8'
new_mac_address = 'bc:de:f0:12:34:56'
assert @first_network_address.cidr_address = new_cidr_address
assert @first_network_address.inet_address = new_inet_address
assert @first_network_address.mac_address = new_mac_address
assert @first_network_address.save
assert @first_network_address.reload
assert_equal @first_network_address.cidr_address, new_cidr_address
assert_equal @first_network_address.inet_address, new_inet_address
assert_equal @first_network_address.mac_address, new_mac_address
end
def test_update_bit_string
new_bit_string = '11111111'
new_bit_string_varying = 'FF'
assert @first_bit_string.bit_string = new_bit_string
assert @first_bit_string.bit_string_varying = new_bit_string_varying
assert @first_bit_string.save
assert @first_bit_string.reload
assert_equal @first_bit_string.bit_string, new_bit_string
assert_equal @first_bit_string.bit_string, @first_bit_string.bit_string_varying
end
def test_update_oid
new_value = 567890
assert @first_oid.obj_id = new_value
assert @first_oid.save
assert @first_oid.reload
assert_equal @first_oid.obj_id, new_value
end
end

View file

@ -1,37 +0,0 @@
require "cases/helper"
require 'models/topic'
require 'models/task'
class DateTimeTest < ActiveRecord::TestCase
def test_saves_both_date_and_time
time_values = [1807, 2, 10, 15, 30, 45]
now = DateTime.civil(*time_values)
task = Task.new
task.starting = now
task.save!
# check against Time.local_time, since some platforms will return a Time instead of a DateTime
assert_equal Time.local_time(*time_values), Task.find(task.id).starting
end
def test_assign_empty_date_time
task = Task.new
task.starting = ''
task.ending = nil
assert_nil task.starting
assert_nil task.ending
end
def test_assign_empty_date
topic = Topic.new
topic.last_read = ''
assert_nil topic.last_read
end
def test_assign_empty_time
topic = Topic.new
topic.bonus_time = ''
assert_nil topic.bonus_time
end
end

View file

@ -1,16 +0,0 @@
require "cases/helper"
require 'models/default'
class DefaultTest < ActiveRecord::TestCase
def test_default_timestamp
default = Default.new
assert_instance_of(Time, default.default_timestamp)
assert_equal(:datetime, default.column_for_attribute(:default_timestamp).type)
# Variance should be small; increase if required -- e.g., if test db is on
# remote host and clocks aren't synchronized.
t1 = Time.new
accepted_variance = 1.0
assert_in_delta(t1.to_f, default.default_timestamp.to_f, accepted_variance)
end
end

View file

@ -1,69 +0,0 @@
require "cases/helper"
require 'models/default'
require 'models/entrant'
class DefaultTest < ActiveRecord::TestCase
def test_nil_defaults_for_not_null_columns
column_defaults =
if current_adapter?(:MysqlAdapter) && Mysql.client_version < 50051
{ '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
# 0 in MySQL 4, nil in 5.
assert [0, nil].include?(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 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
if current_adapter?(:PostgreSQLAdapter)
def test_multiline_default_text
# older postgres versions represent the default with escapes ("\\012" for a newline)
assert ( "--- []\n\n" == Default.columns_hash['multiline_default'].default ||
"--- []\\012\\012" == Default.columns_hash['multiline_default'].default)
end
end
end

View file

@ -1,30 +0,0 @@
require "cases/helper"
require 'models/entrant'
class DeprecatedFinderTest < ActiveRecord::TestCase
fixtures :entrants
def test_deprecated_find_all_was_removed
assert_raise(NoMethodError) { Entrant.find_all }
end
def test_deprecated_find_first_was_removed
assert_raise(NoMethodError) { Entrant.find_first }
end
def test_deprecated_find_on_conditions_was_removed
assert_raise(NoMethodError) { Entrant.find_on_conditions }
end
def test_count
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
assert_equal(0, Entrant.count_by_sql("SELECT COUNT(*) FROM entrants WHERE id > 3"))
assert_equal(1, Entrant.count_by_sql(["SELECT COUNT(*) FROM entrants WHERE id > ?", 2]))
assert_equal(2, Entrant.count_by_sql(["SELECT COUNT(*) FROM entrants WHERE id > ?", 1]))
end
end

View file

@ -1,163 +0,0 @@
require 'cases/helper'
require 'models/topic' # For booleans
require 'models/pirate' # For timestamps
require 'models/parrot'
class Pirate # Just reopening it, not defining it
attr_accessor :detected_changes_in_after_update # Boolean for if changes are detected
attr_accessor :changes_detected_in_after_update # Actual changes
after_update :check_changes
private
# after_save/update in sweepers, observers, and the model itself
# can end up checking dirty status and acting on the results
def check_changes
if self.changed?
self.detected_changes_in_after_update = true
self.changes_detected_in_after_update = self.changes
end
end
end
class DirtyTest < ActiveRecord::TestCase
def test_attribute_changes
# New record - no changes.
pirate = Pirate.new
assert !pirate.catchphrase_changed?
assert_nil pirate.catchphrase_change
# Change catchphrase.
pirate.catchphrase = 'arrr'
assert pirate.catchphrase_changed?
assert_nil pirate.catchphrase_was
assert_equal [nil, 'arrr'], pirate.catchphrase_change
# Saved - no changes.
pirate.save!
assert !pirate.catchphrase_changed?
assert_nil pirate.catchphrase_change
# Same value - no changes.
pirate.catchphrase = 'arrr'
assert !pirate.catchphrase_changed?
assert_nil pirate.catchphrase_change
end
def test_nullable_integer_not_marked_as_changed_if_new_value_is_blank
pirate = Pirate.new
["", nil].each do |value|
pirate.parrot_id = value
assert !pirate.parrot_id_changed?
assert_nil pirate.parrot_id_change
end
end
def test_object_should_be_changed_if_any_attribute_is_changed
pirate = Pirate.new
assert !pirate.changed?
assert_equal [], pirate.changed
assert_equal Hash.new, pirate.changes
pirate.catchphrase = 'arrr'
assert pirate.changed?
assert_nil pirate.catchphrase_was
assert_equal %w(catchphrase), pirate.changed
assert_equal({'catchphrase' => [nil, 'arrr']}, pirate.changes)
pirate.save
assert !pirate.changed?
assert_equal [], pirate.changed
assert_equal Hash.new, pirate.changes
end
def test_attribute_will_change!
pirate = Pirate.create!(:catchphrase => 'arr')
pirate.catchphrase << ' matey'
assert !pirate.catchphrase_changed?
assert pirate.catchphrase_will_change!
assert pirate.catchphrase_changed?
assert_equal ['arr matey', 'arr matey'], pirate.catchphrase_change
pirate.catchphrase << '!'
assert pirate.catchphrase_changed?
assert_equal ['arr matey', 'arr matey!'], pirate.catchphrase_change
end
def test_association_assignment_changes_foreign_key
pirate = Pirate.create!(:catchphrase => 'jarl')
pirate.parrot = Parrot.create!
assert pirate.changed?
assert_equal %w(parrot_id), pirate.changed
end
def test_attribute_should_be_compared_with_type_cast
topic = Topic.new
assert topic.approved?
assert !topic.approved_changed?
# Coming from web form.
params = {:topic => {:approved => 1}}
# In the controller.
topic.attributes = params[:topic]
assert topic.approved?
assert !topic.approved_changed?
end
def test_partial_update
pirate = Pirate.new(:catchphrase => 'foo')
old_updated_on = 1.hour.ago.beginning_of_day
with_partial_updates Pirate, false do
assert_queries(2) { 2.times { pirate.save! } }
Pirate.update_all({ :updated_on => old_updated_on }, :id => pirate.id)
end
with_partial_updates Pirate, true do
assert_queries(0) { 2.times { pirate.save! } }
assert_equal old_updated_on, pirate.reload.updated_on
assert_queries(1) { pirate.catchphrase = 'bar'; pirate.save! }
assert_not_equal old_updated_on, pirate.reload.updated_on
end
end
def test_changed_attributes_should_be_preserved_if_save_failure
pirate = Pirate.new
pirate.parrot_id = 1
assert !pirate.save
check_pirate_after_save_failure(pirate)
pirate = Pirate.new
pirate.parrot_id = 1
assert_raises(ActiveRecord::RecordInvalid) { pirate.save! }
check_pirate_after_save_failure(pirate)
end
def test_reload_should_clear_changed_attributes
pirate = Pirate.create!(:catchphrase => "shiver me timbers")
pirate.catchphrase = "*hic*"
assert pirate.changed?
pirate.reload
assert !pirate.changed?
end
private
def with_partial_updates(klass, on = true)
old = klass.partial_updates?
klass.partial_updates = on
yield
ensure
klass.partial_updates = old
end
def check_pirate_after_save_failure(pirate)
assert pirate.changed?
assert pirate.parrot_id_changed?
assert_equal %w(parrot_id), pirate.changed
assert_nil pirate.parrot_id_was
end
end

View file

@ -1,76 +0,0 @@
require "cases/helper"
require 'models/topic'
class FinderRespondToTest < ActiveRecord::TestCase
fixtures :topics
def test_should_preserve_normal_respond_to_behaviour_and_respond_to_newly_added_method
class << Topic; self; end.send(:define_method, :method_added_for_finder_respond_to_test) { }
assert Topic.respond_to?(:method_added_for_finder_respond_to_test)
ensure
class << Topic; self; end.send(:remove_method, :method_added_for_finder_respond_to_test)
end
def test_should_preserve_normal_respond_to_behaviour_and_respond_to_standard_object_method
assert Topic.respond_to?(:to_s)
end
def test_should_respond_to_find_by_one_attribute_before_caching
ensure_topic_method_is_not_cached(:find_by_title)
assert Topic.respond_to?(:find_by_title)
end
def test_should_respond_to_find_all_by_one_attribute
ensure_topic_method_is_not_cached(:find_all_by_title)
assert Topic.respond_to?(:find_all_by_title)
end
def test_should_respond_to_find_all_by_two_attributes
ensure_topic_method_is_not_cached(:find_all_by_title_and_author_name)
assert Topic.respond_to?(:find_all_by_title_and_author_name)
end
def test_should_respond_to_find_by_two_attributes
ensure_topic_method_is_not_cached(:find_by_title_and_author_name)
assert Topic.respond_to?(:find_by_title_and_author_name)
end
def test_should_respond_to_find_or_initialize_from_one_attribute
ensure_topic_method_is_not_cached(:find_or_initialize_by_title)
assert Topic.respond_to?(:find_or_initialize_by_title)
end
def test_should_respond_to_find_or_initialize_from_two_attributes
ensure_topic_method_is_not_cached(:find_or_initialize_by_title_and_author_name)
assert Topic.respond_to?(:find_or_initialize_by_title_and_author_name)
end
def test_should_respond_to_find_or_create_from_one_attribute
ensure_topic_method_is_not_cached(:find_or_create_by_title)
assert Topic.respond_to?(:find_or_create_by_title)
end
def test_should_respond_to_find_or_create_from_two_attributes
ensure_topic_method_is_not_cached(:find_or_create_by_title_and_author_name)
assert Topic.respond_to?(:find_or_create_by_title_and_author_name)
end
def test_should_not_respond_to_find_by_one_missing_attribute
assert !Topic.respond_to?(:find_by_undertitle)
end
def test_should_not_respond_to_find_by_invalid_method_syntax
assert !Topic.respond_to?(:fail_to_find_by_title)
assert !Topic.respond_to?(:find_by_title?)
assert !Topic.respond_to?(:fail_to_find_or_create_by_title)
assert !Topic.respond_to?(:find_or_create_by_title?)
end
private
def ensure_topic_method_is_not_cached(method_id)
class << Topic; self; end.send(:remove_method, method_id) if Topic.public_methods.any? { |m| m.to_s == method_id.to_s }
end
end

View file

@ -1,883 +0,0 @@
require "cases/helper"
require 'models/author'
require 'models/comment'
require 'models/company'
require 'models/topic'
require 'models/reply'
require 'models/entrant'
require 'models/developer'
require 'models/post'
require 'models/customer'
require 'models/job'
require 'models/categorization'
class FinderTest < ActiveRecord::TestCase
fixtures :companies, :topics, :entrants, :developers, :developers_projects, :posts, :comments, :accounts, :authors, :customers
def test_find
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?("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)
begin
assert !Topic.exists?("foo")
rescue ActiveRecord::StatementInvalid
# PostgreSQL complains about string comparison with integer field
rescue Exception
flunk
end
assert_raise(NoMethodError) { Topic.exists?([1,2]) }
end
def test_exists_with_aggregate_having_three_mappings
existing_address = customers(:david).address
assert Customer.exists?(:address => existing_address)
end
def test_exists_with_aggregate_having_three_mappings_with_one_difference
existing_address = customers(:david).address
assert !Customer.exists?(:address =>
Address.new(existing_address.street, existing_address.city, existing_address.country + "1"))
assert !Customer.exists?(:address =>
Address.new(existing_address.street, existing_address.city + "1", existing_address.country))
assert !Customer.exists?(:address =>
Address.new(existing_address.street + "1", existing_address.city, existing_address.country))
end
def test_find_by_array_of_one_id
assert_kind_of(Array, Topic.find([ 1 ]))
assert_equal(1, Topic.find([ 1 ]).length)
end
def test_find_by_ids
assert_equal 2, Topic.find(1, 2).size
assert_equal topics(:second).title, Topic.find([2]).first.title
end
def test_find_by_ids_with_limit_and_offset
assert_equal 2, Entrant.find([1,3,2], :limit => 2).size
assert_equal 1, Entrant.find([1,3,2], :limit => 3, :offset => 2).size
# Also test an edge case: If you have 11 results, and you set a
# limit of 3 and offset of 9, then you should find that there
# will be only 2 results, regardless of the limit.
devs = Developer.find :all
last_devs = Developer.find devs.map(&:id), :limit => 3, :offset => 9
assert_equal 2, last_devs.size
end
def test_find_an_empty_array
assert_equal [], Topic.find([])
end
def test_find_by_ids_missing_one
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, 2, 45) }
end
def test_find_all_with_limit
entrants = Entrant.find(:all, :order => "id ASC", :limit => 2)
assert_equal(2, entrants.size)
assert_equal(entrants(:first).name, entrants.first.name)
end
def test_find_all_with_prepared_limit_and_offset
entrants = Entrant.find(:all, :order => "id ASC", :limit => 2, :offset => 1)
assert_equal(2, entrants.size)
assert_equal(entrants(:second).name, entrants.first.name)
entrants = Entrant.find(:all, :order => "id ASC", :limit => 2, :offset => 2)
assert_equal(1, entrants.size)
assert_equal(entrants(:third).name, entrants.first.name)
end
def test_find_all_with_limit_and_offset_and_multiple_orderings
developers = Developer.find(:all, :order => "salary ASC, id DESC", :limit => 3, :offset => 1)
assert_equal ["David", "fixture_10", "fixture_9"], developers.collect {|d| d.name}
end
def test_find_with_limit_and_condition
developers = Developer.find(:all, :order => "id DESC", :conditions => "salary = 100000", :limit => 3, :offset =>7)
assert_equal(1, developers.size)
assert_equal("fixture_3", developers.first.name)
end
def test_find_with_entire_select_statement
topics = Topic.find_by_sql "SELECT * FROM topics WHERE author_name = 'Mary'"
assert_equal(1, topics.size)
assert_equal(topics(:second).title, topics.first.title)
end
def test_find_with_prepared_select_statement
topics = Topic.find_by_sql ["SELECT * FROM topics WHERE author_name = ?", "Mary"]
assert_equal(1, topics.size)
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)
end
def test_find_first_failing
first = Topic.find(:first, :conditions => "title = 'The First Topic!'")
assert_nil(first)
end
def test_first
assert_equal topics(:second).title, Topic.first(:conditions => "title = 'The Second Topic of the day'").title
end
def test_first_failing
assert_nil Topic.first(:conditions => "title = 'The Second Topic of the day!'")
end
def test_unexisting_record_exception_handling
assert_raises(ActiveRecord::RecordNotFound) {
Topic.find(1).parent
}
Topic.find(2).topic
end
def test_find_only_some_columns
topic = Topic.find(1, :select => "author_name")
assert_raises(ActiveRecord::MissingAttributeError) {topic.title}
assert_equal "David", topic.author_name
assert !topic.attribute_present?("title")
#assert !topic.respond_to?("title")
assert topic.attribute_present?("author_name")
assert topic.respond_to?("author_name")
end
def test_find_on_blank_conditions
[nil, " ", [], {}].each do |blank|
assert_nothing_raised { Topic.find(:first, :conditions => blank) }
end
end
def test_find_on_blank_bind_conditions
[ [""], ["",{}] ].each do |blank|
assert_nothing_raised { Topic.find(:first, :conditions => blank) }
end
end
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_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_explicit_table_name
assert Topic.find(1, :conditions => { 'topics.approved' => false })
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { 'topics.approved' => true }) }
end
def test_find_on_hash_conditions_with_explicit_table_name_and_aggregate
david = customers(:david)
assert Customer.find(david.id, :conditions => { 'customers.name' => david.name, :address => david.address })
assert_raises(ActiveRecord::RecordNotFound) {
Customer.find(david.id, :conditions => { 'customers.name' => david.name + "1", :address => david.address })
}
end
def test_find_on_association_proxy_conditions
assert_equal [1, 2, 3, 5, 6, 7, 8, 9, 10], Comment.find_all_by_post_id(authors(:david).posts).map(&:id).sort
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_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_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_hash_condition_find_with_aggregate_having_one_mapping
balance = customers(:david).balance
assert_kind_of Money, balance
found_customer = Customer.find(:first, :conditions => {:balance => balance})
assert_equal customers(:david), found_customer
end
def test_hash_condition_find_with_aggregate_attribute_having_same_name_as_field_and_key_value_being_aggregate
gps_location = customers(:david).gps_location
assert_kind_of GpsLocation, gps_location
found_customer = Customer.find(:first, :conditions => {:gps_location => gps_location})
assert_equal customers(:david), found_customer
end
def test_hash_condition_find_with_aggregate_having_one_mapping_and_key_value_being_attribute_value
balance = customers(:david).balance
assert_kind_of Money, balance
found_customer = Customer.find(:first, :conditions => {:balance => balance.amount})
assert_equal customers(:david), found_customer
end
def test_hash_condition_find_with_aggregate_attribute_having_same_name_as_field_and_key_value_being_attribute_value
gps_location = customers(:david).gps_location
assert_kind_of GpsLocation, gps_location
found_customer = Customer.find(:first, :conditions => {:gps_location => gps_location.gps_location})
assert_equal customers(:david), found_customer
end
def test_hash_condition_find_with_aggregate_having_three_mappings
address = customers(:david).address
assert_kind_of Address, address
found_customer = Customer.find(:first, :conditions => {:address => address})
assert_equal customers(:david), found_customer
end
def test_hash_condition_find_with_one_condition_being_aggregate_and_another_not
address = customers(:david).address
assert_kind_of Address, address
found_customer = Customer.find(:first, :conditions => {:address => address, :name => customers(:david).name})
assert_equal customers(:david), found_customer
end
def test_bind_variables
assert_kind_of Firm, Company.find(:first, :conditions => ["name = ?", "37signals"])
assert_nil Company.find(:first, :conditions => ["name = ?", "37signals!"])
assert_nil Company.find(:first, :conditions => ["name = ?", "37signals!' OR 1=1"])
assert_kind_of Time, Topic.find(:first, :conditions => ["id = ?", 1]).written_on
assert_raises(ActiveRecord::PreparedStatementInvalid) {
Company.find(:first, :conditions => ["id=? AND name = ?", 2])
}
assert_raises(ActiveRecord::PreparedStatementInvalid) {
Company.find(:first, :conditions => ["id=?", 2, 3, 4])
}
end
def test_bind_variables_with_quotes
Company.create("name" => "37signals' go'es agains")
assert Company.find(:first, :conditions => ["name = ?", "37signals' go'es agains"])
end
def test_named_bind_variables_with_quotes
Company.create("name" => "37signals' go'es agains")
assert Company.find(:first, :conditions => ["name = :name", {:name => "37signals' go'es agains"}])
end
def test_bind_arity
assert_nothing_raised { bind '' }
assert_raises(ActiveRecord::PreparedStatementInvalid) { bind '', 1 }
assert_raises(ActiveRecord::PreparedStatementInvalid) { bind '?' }
assert_nothing_raised { bind '?', 1 }
assert_raises(ActiveRecord::PreparedStatementInvalid) { bind '?', 1, 1 }
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_nothing_raised { bind("'+00:00'", :foo => "bar") }
assert_kind_of Firm, Company.find(:first, :conditions => ["name = :name", { :name => "37signals" }])
assert_nil Company.find(:first, :conditions => ["name = :name", { :name => "37signals!" }])
assert_nil Company.find(:first, :conditions => ["name = :name", { :name => "37signals!' OR 1=1" }])
assert_kind_of Time, Topic.find(:first, :conditions => ["id = :id", { :id => 1 }]).written_on
end
def test_bind_enumerable
quoted_abc = %(#{ActiveRecord::Base.connection.quote('a')},#{ActiveRecord::Base.connection.quote('b')},#{ActiveRecord::Base.connection.quote('c')})
assert_equal '1,2,3', bind('?', [1, 2, 3])
assert_equal quoted_abc, bind('?', %w(a b c))
assert_equal '1,2,3', bind(':a', :a => [1, 2, 3])
assert_equal quoted_abc, bind(':a', :a => %w(a b c)) # '
require 'set'
assert_equal '1,2,3', bind('?', Set.new([1, 2, 3]))
assert_equal quoted_abc, bind('?', Set.new(%w(a b c)))
assert_equal '1,2,3', bind(':a', :a => Set.new([1, 2, 3]))
assert_equal quoted_abc, 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 ActiveRecord::Base.connection.quote(''), 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 "#{ActiveRecord::Base.connection.quoted_string_prefix}'something ' 1=1'", ActiveRecord::Base.sanitize("something ' 1=1")
assert_equal "#{ActiveRecord::Base.connection.quoted_string_prefix}'something; select table'", ActiveRecord::Base.sanitize("something; select table")
end
def test_count
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
assert_equal(0, Entrant.count_by_sql("SELECT COUNT(*) FROM entrants WHERE id > 3"))
assert_equal(1, Entrant.count_by_sql(["SELECT COUNT(*) FROM entrants WHERE id > ?", 2]))
assert_equal(2, Entrant.count_by_sql(["SELECT COUNT(*) FROM entrants WHERE id > ?", 1]))
end
def test_find_by_one_attribute
assert_equal topics(:first), Topic.find_by_title("The First Topic")
assert_nil Topic.find_by_title("The First Topic!")
end
def test_find_by_one_attribute_caches_dynamic_finder
# ensure this test can run independently of order
class << Topic; self; end.send(:remove_method, :find_by_title) if Topic.public_methods.any? { |m| m.to_s == 'find_by_title' }
assert !Topic.public_methods.any? { |m| m.to_s == 'find_by_title' }
t = Topic.find_by_title("The First Topic")
assert Topic.public_methods.any? { |m| m.to_s == 'find_by_title' }
end
def test_dynamic_finder_returns_same_results_after_caching
# ensure this test can run independently of order
class << Topic; self; end.send(:remove_method, :find_by_title) if Topic.public_method_defined?(:find_by_title)
t = Topic.find_by_title("The First Topic")
assert_equal t, Topic.find_by_title("The First Topic") # find_by_title has been cached
end
def test_find_by_one_attribute_with_order_option
assert_equal accounts(:signals37), Account.find_by_credit_limit(50, :order => 'id')
assert_equal accounts(:rails_core_account), Account.find_by_credit_limit(50, :order => 'id DESC')
end
def test_find_by_one_attribute_with_conditions
assert_equal accounts(:rails_core_account), Account.find_by_credit_limit(50, :conditions => ['firm_id = ?', 6])
end
def test_find_by_one_attribute_that_is_an_aggregate
address = customers(:david).address
assert_kind_of Address, address
found_customer = Customer.find_by_address(address)
assert_equal customers(:david), found_customer
end
def test_find_by_one_attribute_that_is_an_aggregate_with_one_attribute_difference
address = customers(:david).address
assert_kind_of Address, address
missing_address = Address.new(address.street, address.city, address.country + "1")
assert_nil Customer.find_by_address(missing_address)
missing_address = Address.new(address.street, address.city + "1", address.country)
assert_nil Customer.find_by_address(missing_address)
missing_address = Address.new(address.street + "1", address.city, address.country)
assert_nil Customer.find_by_address(missing_address)
end
def test_find_by_two_attributes_that_are_both_aggregates
balance = customers(:david).balance
address = customers(:david).address
assert_kind_of Money, balance
assert_kind_of Address, address
found_customer = Customer.find_by_balance_and_address(balance, address)
assert_equal customers(:david), found_customer
end
def test_find_by_two_attributes_with_one_being_an_aggregate
balance = customers(:david).balance
assert_kind_of Money, balance
found_customer = Customer.find_by_balance_and_name(balance, customers(:david).name)
assert_equal customers(:david), found_customer
end
def test_dynamic_finder_on_one_attribute_with_conditions_caches_method
# ensure this test can run independently of order
class << Account; self; end.send(:remove_method, :find_by_credit_limit) if Account.public_methods.any? { |m| m.to_s == 'find_by_credit_limit' }
assert !Account.public_methods.any? { |m| m.to_s == 'find_by_credit_limit' }
a = Account.find_by_credit_limit(50, :conditions => ['firm_id = ?', 6])
assert Account.public_methods.any? { |m| m.to_s == 'find_by_credit_limit' }
end
def test_dynamic_finder_on_one_attribute_with_conditions_returns_same_results_after_caching
# ensure this test can run independently of order
class << Account; self; end.send(:remove_method, :find_by_credit_limit) if Account.public_methods.any? { |m| m.to_s == 'find_by_credit_limit' }
a = Account.find_by_credit_limit(50, :conditions => ['firm_id = ?', 6])
assert_equal a, Account.find_by_credit_limit(50, :conditions => ['firm_id = ?', 6]) # find_by_credit_limit has been cached
end
def test_find_by_one_attribute_with_several_options
assert_equal accounts(:unknown), Account.find_by_credit_limit(50, :order => 'id DESC', :conditions => ['id != ?', 3])
end
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")
assert_nil Topic.find_by_title_and_author_name("The First Topic", "Mary")
end
def test_find_all_by_one_attribute
topics = Topic.find_all_by_content("Have a nice day")
assert_equal 2, topics.size
assert topics.include?(topics(:first))
assert_equal [], Topic.find_all_by_title("The First Topic!!")
end
def test_find_all_by_one_attribute_that_is_an_aggregate
balance = customers(:david).balance
assert_kind_of Money, balance
found_customers = Customer.find_all_by_balance(balance)
assert_equal 1, found_customers.size
assert_equal customers(:david), found_customers.first
end
def test_find_all_by_two_attributes_that_are_both_aggregates
balance = customers(:david).balance
address = customers(:david).address
assert_kind_of Money, balance
assert_kind_of Address, address
found_customers = Customer.find_all_by_balance_and_address(balance, address)
assert_equal 1, found_customers.size
assert_equal customers(:david), found_customers.first
end
def test_find_all_by_two_attributes_with_one_being_an_aggregate
balance = customers(:david).balance
assert_kind_of Money, balance
found_customers = Customer.find_all_by_balance_and_name(balance, customers(:david).name)
assert_equal 1, found_customers.size
assert_equal customers(:david), found_customers.first
end
def test_find_all_by_one_attribute_with_options
topics = Topic.find_all_by_content("Have a nice day", :order => "id DESC")
assert topics(:first), topics.last
topics = Topic.find_all_by_content("Have a nice day", :order => "id")
assert topics(:first), topics.first
end
def test_find_all_by_array_attribute
assert_equal 2, Topic.find_all_by_title(["The First Topic", "The Second Topic of the day"]).size
end
def test_find_all_by_boolean_attribute
topics = Topic.find_all_by_approved(false)
assert_equal 1, topics.size
assert topics.include?(topics(:first))
topics = Topic.find_all_by_approved(true)
assert_equal 3, topics.size
assert topics.include?(topics(:second))
end
def test_find_by_nil_attribute
topic = Topic.find_by_last_read nil
assert_not_nil topic
assert_nil topic.last_read
end
def test_find_all_by_nil_attribute
topics = Topic.find_all_by_last_read nil
assert_equal 3, topics.size
assert topics.collect(&:last_read).all?(&:nil?)
end
def test_find_by_nil_and_not_nil_attributes
topic = Topic.find_by_last_read_and_author_name nil, "Mary"
assert_equal "Mary", topic.author_name
end
def test_find_all_by_nil_and_not_nil_attributes
topics = Topic.find_all_by_last_read_and_author_name nil, "Mary"
assert_equal 1, topics.size
assert_equal "Mary", topics[0].author_name
end
def test_find_or_create_from_one_attribute
number_of_companies = Company.count
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
number_of_topics = Topic.count
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_create_from_two_attributes_with_one_being_an_aggregate
number_of_customers = Customer.count
created_customer = Customer.find_or_create_by_balance_and_name(Money.new(123), "Elizabeth")
assert_equal number_of_customers + 1, Customer.count
assert_equal created_customer, Customer.find_or_create_by_balance(Money.new(123), "Elizabeth")
assert !created_customer.new_record?
end
def test_find_or_create_from_one_attribute_and_hash
number_of_companies = Company.count
sig38 = Company.find_or_create_by_name({:name => "38signals", :firm_id => 17, :client_of => 23})
assert_equal number_of_companies + 1, Company.count
assert_equal sig38, Company.find_or_create_by_name({:name => "38signals", :firm_id => 17, :client_of => 23})
assert !sig38.new_record?
assert_equal "38signals", sig38.name
assert_equal 17, sig38.firm_id
assert_equal 23, sig38.client_of
end
def test_find_or_create_from_one_aggregate_attribute
number_of_customers = Customer.count
created_customer = Customer.find_or_create_by_balance(Money.new(123))
assert_equal number_of_customers + 1, Customer.count
assert_equal created_customer, Customer.find_or_create_by_balance(Money.new(123))
assert !created_customer.new_record?
end
def test_find_or_create_from_one_aggregate_attribute_and_hash
number_of_customers = Customer.count
balance = Money.new(123)
name = "Elizabeth"
created_customer = Customer.find_or_create_by_balance({:balance => balance, :name => name})
assert_equal number_of_customers + 1, Customer.count
assert_equal created_customer, Customer.find_or_create_by_balance({:balance => balance, :name => name})
assert !created_customer.new_record?
assert_equal balance, created_customer.balance
assert_equal name, created_customer.name
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_one_aggregate_attribute
new_customer = Customer.find_or_initialize_by_balance(Money.new(123))
assert_equal 123, new_customer.balance.amount
assert new_customer.new_record?
end
def test_find_or_initialize_from_one_attribute_should_not_set_attribute_even_when_protected
c = Company.find_or_initialize_by_name({:name => "Fortune 1000", :rating => 1000})
assert_equal "Fortune 1000", c.name
assert_not_equal 1000, c.rating
assert c.valid?
assert c.new_record?
end
def test_find_or_create_from_one_attribute_should_set_not_attribute_even_when_protected
c = Company.find_or_create_by_name({:name => "Fortune 1000", :rating => 1000})
assert_equal "Fortune 1000", c.name
assert_not_equal 1000, c.rating
assert c.valid?
assert !c.new_record?
end
def test_find_or_initialize_from_one_attribute_should_set_attribute_even_when_protected
c = Company.find_or_initialize_by_name_and_rating("Fortune 1000", 1000)
assert_equal "Fortune 1000", c.name
assert_equal 1000, c.rating
assert c.valid?
assert c.new_record?
end
def test_find_or_create_from_one_attribute_should_set_attribute_even_when_protected
c = Company.find_or_create_by_name_and_rating("Fortune 1000", 1000)
assert_equal "Fortune 1000", c.name
assert_equal 1000, c.rating
assert c.valid?
assert !c.new_record?
end
def test_find_or_initialize_should_set_protected_attributes_if_given_as_block
c = Company.find_or_initialize_by_name(:name => "Fortune 1000") { |f| f.rating = 1000 }
assert_equal "Fortune 1000", c.name
assert_equal 1000.to_f, c.rating.to_f
assert c.valid?
assert c.new_record?
end
def test_find_or_create_should_set_protected_attributes_if_given_as_block
c = Company.find_or_create_by_name(:name => "Fortune 1000") { |f| f.rating = 1000 }
assert_equal "Fortune 1000", c.name
assert_equal 1000.to_f, c.rating.to_f
assert c.valid?
assert !c.new_record?
end
def test_dynamic_find_or_initialize_from_one_attribute_caches_method
class << Company; self; end.send(:remove_method, :find_or_initialize_by_name) if Company.public_methods.any? { |m| m.to_s == 'find_or_initialize_by_name' }
assert !Company.public_methods.any? { |m| m.to_s == 'find_or_initialize_by_name' }
sig38 = Company.find_or_initialize_by_name("38signals")
assert Company.public_methods.any? { |m| m.to_s == 'find_or_initialize_by_name' }
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_or_initialize_from_one_aggregate_attribute_and_one_not
new_customer = Customer.find_or_initialize_by_balance_and_name(Money.new(123), "Elizabeth")
assert_equal 123, new_customer.balance.amount
assert_equal "Elizabeth", new_customer.name
assert new_customer.new_record?
end
def test_find_or_initialize_from_one_attribute_and_hash
sig38 = Company.find_or_initialize_by_name({:name => "38signals", :firm_id => 17, :client_of => 23})
assert_equal "38signals", sig38.name
assert_equal 17, sig38.firm_id
assert_equal 23, sig38.client_of
assert sig38.new_record?
end
def test_find_or_initialize_from_one_aggregate_attribute_and_hash
balance = Money.new(123)
name = "Elizabeth"
new_customer = Customer.find_or_initialize_by_balance({:balance => balance, :name => name})
assert_equal balance, new_customer.balance
assert_equal name, new_customer.name
assert new_customer.new_record?
end
def test_find_with_bad_sql
assert_raises(ActiveRecord::StatementInvalid) { Topic.find_by_sql "select 1 from badtable" }
end
def test_find_with_invalid_params
assert_raises(ArgumentError) { Topic.find :first, :join => "It should be `joins'" }
assert_raises(ArgumentError) { Topic.find :first, :conditions => '1 = 1', :join => "It should be `joins'" }
end
def test_dynamic_finder_with_invalid_params
assert_raises(ArgumentError) { Topic.find_by_title 'No Title', :join => "It should be `joins'" }
end
def test_find_all_with_limit
first_five_developers = Developer.find :all, :order => 'id ASC', :limit => 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, :order => 'id ASC', :limit => 0
assert_equal 0, no_developers.length
end
def test_find_all_with_limit_and_offset
first_three_developers = Developer.find :all, :order => 'id ASC', :limit => 3, :offset => 0
second_three_developers = Developer.find :all, :order => 'id ASC', :limit => 3, :offset => 3
last_two_developers = Developer.find :all, :order => 'id ASC', :limit => 2, :offset => 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
def test_find_all_with_limit_and_offset_and_multiple_order_clauses
first_three_posts = Post.find :all, :order => 'author_id, id', :limit => 3, :offset => 0
second_three_posts = Post.find :all, :order => ' author_id,id ', :limit => 3, :offset => 3
last_posts = Post.find :all, :order => ' author_id, id ', :limit => 3, :offset => 6
assert_equal [[0,3],[1,1],[1,2]], first_three_posts.map { |p| [p.author_id, p.id] }
assert_equal [[1,4],[1,5],[1,6]], second_three_posts.map { |p| [p.author_id, p.id] }
assert_equal [[2,7]], last_posts.map { |p| [p.author_id, p.id] }
end
def test_find_all_with_join
developers_on_project_one = Developer.find(
:all,
:joins => 'LEFT JOIN developers_projects ON developers.id = developers_projects.developer_id',
:conditions => 'project_id=1'
)
assert_equal 3, developers_on_project_one.length
developer_names = developers_on_project_one.map { |d| d.name }
assert developer_names.include?('David')
assert developer_names.include?('Jamis')
end
def test_joins_dont_clobber_id
first = Firm.find(
:first,
:joins => 'INNER JOIN companies AS clients ON clients.firm_id = companies.id',
:conditions => 'companies.id = 1'
)
assert_equal 1, first.id
end
def test_find_by_id_with_conditions_with_or
assert_nothing_raised do
Post.find([1,2,3],
:conditions => "posts.id <= 3 OR posts.#{QUOTED_TYPE} = 'Post'")
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")
# make sure we didn't break count...
assert_equal 0, Company.count_by_sql("SELECT COUNT(*) FROM companies WHERE name = 'Halliburton'")
assert_equal 1, Company.count_by_sql("SELECT COUNT(*) FROM companies WHERE name = '37signals'")
end
def test_select_values
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
def test_select_rows
assert_equal(
[["1", nil, nil, "37signals"],
["2", "1", "2", "Summit"],
["3", "1", "1", "Microsoft"]],
Company.connection.select_rows("SELECT id, firm_id, client_of, name FROM companies WHERE id IN (1,2,3) ORDER BY id").map! {|i| i.map! {|j| j.to_s unless j.nil?}})
assert_equal [["1", "37signals"], ["2", "Summit"], ["3", "Microsoft"]],
Company.connection.select_rows("SELECT id, name FROM companies WHERE id IN (1,2,3) ORDER BY id").map! {|i| i.map! {|j| j.to_s unless j.nil?}}
end
def test_find_with_order_on_included_associations_with_construct_finder_sql_for_association_limiting_and_is_distinct
assert_equal 2, Post.find(:all, :include => { :authors => :author_address }, :order => ' author_addresses.id DESC ', :limit => 2).size
assert_equal 3, Post.find(:all, :include => { :author => :author_address, :authors => :author_address},
:order => ' author_addresses_authors.id DESC ', :limit => 3).size
end
def test_with_limiting_with_custom_select
posts = Post.find(:all, :include => :author, :select => ' posts.*, authors.id as "author_id"', :limit => 3, :order => 'posts.id')
assert_equal 3, posts.size
assert_equal [0, 1, 1], posts.map(&:author_id).sort
end
protected
def bind(statement, *vars)
if vars.first.is_a?(Hash)
ActiveRecord::Base.send(:replace_named_bind_variables, statement, vars.first)
else
ActiveRecord::Base.send(:replace_bind_variables, statement, vars)
end
end
end

View file

@ -1,626 +0,0 @@
require "cases/helper"
require 'models/post'
require 'models/binary'
require 'models/topic'
require 'models/computer'
require 'models/developer'
require 'models/company'
require 'models/task'
require 'models/reply'
require 'models/joke'
require 'models/course'
require 'models/category'
require 'models/parrot'
require 'models/pirate'
require 'models/treasure'
require 'models/matey'
require 'models/ship'
class FixturesTest < ActiveRecord::TestCase
self.use_instantiated_fixtures = true
self.use_transactional_fixtures = false
fixtures :topics, :developers, :accounts, :tasks, :categories, :funny_jokes, :binaries
FIXTURES = %w( accounts binaries companies customers
developers developers_projects entrants
movies projects subscribers topics tasks )
MATCH_ATTRIBUTE_NAME = /[a-zA-Z][-_\w]*/
def test_clean_fixtures
FIXTURES.each do |name|
fixtures = nil
assert_nothing_raised { fixtures = create_fixtures(name) }
assert_kind_of(Fixtures, fixtures)
fixtures.each { |name, fixture|
fixture.each { |key, value|
assert_match(MATCH_ATTRIBUTE_NAME, key)
}
}
end
end
def test_multiple_clean_fixtures
fixtures_array = nil
assert_nothing_raised { fixtures_array = create_fixtures(*FIXTURES) }
assert_kind_of(Array, fixtures_array)
fixtures_array.each { |fixtures| assert_kind_of(Fixtures, fixtures) }
end
def test_attributes
topics = create_fixtures("topics")
assert_equal("The First Topic", topics["first"]["title"])
assert_nil(topics["second"]["author_email_address"])
end
def test_inserts
topics = create_fixtures("topics")
first_row = ActiveRecord::Base.connection.select_one("SELECT * FROM topics WHERE author_name = 'David'")
assert_equal("The First Topic", first_row["title"])
second_row = ActiveRecord::Base.connection.select_one("SELECT * FROM topics WHERE author_name = 'Mary'")
assert_nil(second_row["author_email_address"])
end
if ActiveRecord::Base.connection.supports_migrations?
def test_inserts_with_pre_and_suffix
# Reset cache to make finds on the new table work
Fixtures.reset_cache
ActiveRecord::Base.connection.create_table :prefix_topics_suffix do |t|
t.column :title, :string
t.column :author_name, :string
t.column :author_email_address, :string
t.column :written_on, :datetime
t.column :bonus_time, :time
t.column :last_read, :date
t.column :content, :string
t.column :approved, :boolean, :default => true
t.column :replies_count, :integer, :default => 0
t.column :parent_id, :integer
t.column :type, :string, :limit => 50
end
# Store existing prefix/suffix
old_prefix = ActiveRecord::Base.table_name_prefix
old_suffix = ActiveRecord::Base.table_name_suffix
# Set a prefix/suffix we can test against
ActiveRecord::Base.table_name_prefix = 'prefix_'
ActiveRecord::Base.table_name_suffix = '_suffix'
topics = create_fixtures("topics")
first_row = ActiveRecord::Base.connection.select_one("SELECT * FROM prefix_topics_suffix WHERE author_name = 'David'")
assert_equal("The First Topic", first_row["title"])
second_row = ActiveRecord::Base.connection.select_one("SELECT * FROM prefix_topics_suffix WHERE author_name = 'Mary'")
assert_nil(second_row["author_email_address"])
# This checks for a caching problem which causes a bug in the fixtures
# class-level configuration helper.
assert_not_nil topics, "Fixture data inserted, but fixture objects not returned from create"
ensure
# Restore prefix/suffix to its previous values
ActiveRecord::Base.table_name_prefix = old_prefix
ActiveRecord::Base.table_name_suffix = old_suffix
ActiveRecord::Base.connection.drop_table :prefix_topics_suffix rescue nil
end
end
def test_insert_with_datetime
topics = create_fixtures("tasks")
first = Task.find(1)
assert first
end
def test_logger_level_invariant
level = ActiveRecord::Base.logger.level
create_fixtures('topics')
assert_equal level, ActiveRecord::Base.logger.level
end
def test_instantiation
topics = create_fixtures("topics")
assert_kind_of Topic, topics["first"].find
end
def test_complete_instantiation
assert_equal 4, @topics.size
assert_equal "The First Topic", @first.title
end
def test_fixtures_from_root_yml_with_instantiation
# assert_equal 2, @accounts.size
assert_equal 50, @unknown.credit_limit
end
def test_erb_in_fixtures
assert_equal 11, @developers.size
assert_equal "fixture_5", @dev_5.name
end
def test_empty_yaml_fixture
assert_not_nil Fixtures.new( Account.connection, "accounts", 'Account', FIXTURES_ROOT + "/naked/yml/accounts")
end
def test_empty_yaml_fixture_with_a_comment_in_it
assert_not_nil Fixtures.new( Account.connection, "companies", 'Company', FIXTURES_ROOT + "/naked/yml/companies")
end
def test_dirty_dirty_yaml_file
assert_raises(Fixture::FormatError) do
Fixtures.new( Account.connection, "courses", 'Course', FIXTURES_ROOT + "/naked/yml/courses")
end
end
def test_empty_csv_fixtures
assert_not_nil Fixtures.new( Account.connection, "accounts", 'Account', FIXTURES_ROOT + "/naked/csv/accounts")
end
def test_omap_fixtures
assert_nothing_raised do
fixtures = Fixtures.new(Account.connection, 'categories', 'Category', FIXTURES_ROOT + "/categories_ordered")
i = 0
fixtures.each do |name, fixture|
assert_equal "fixture_no_#{i}", name
assert_equal "Category #{i}", fixture['name']
i += 1
end
end
end
def test_yml_file_in_subdirectory
assert_equal(categories(:sub_special_1).name, "A special category in a subdir file")
assert_equal(categories(:sub_special_1).class, SpecialCategory)
end
def test_subsubdir_file_with_arbitrary_name
assert_equal(categories(:sub_special_3).name, "A special category in an arbitrarily named subsubdir file")
assert_equal(categories(:sub_special_3).class, SpecialCategory)
end
def test_binary_in_fixtures
assert_equal 1, @binaries.size
data = File.read(ASSETS_ROOT + "/flowers.jpg")
data.force_encoding('ASCII-8BIT') if data.respond_to?(:force_encoding)
data.freeze
assert_equal data, @flowers.data
end
end
if Account.connection.respond_to?(:reset_pk_sequence!)
class FixturesResetPkSequenceTest < ActiveRecord::TestCase
fixtures :accounts
fixtures :companies
def setup
@instances = [Account.new(:credit_limit => 50), Company.new(:name => 'RoR Consulting')]
Fixtures.reset_cache # make sure tables get reinitialized
end
def test_resets_to_min_pk_with_specified_pk_and_sequence
@instances.each do |instance|
model = instance.class
model.delete_all
model.connection.reset_pk_sequence!(model.table_name, model.primary_key, model.sequence_name)
instance.save!
assert_equal 1, instance.id, "Sequence reset for #{model.table_name} failed."
end
end
def test_resets_to_min_pk_with_default_pk_and_sequence
@instances.each do |instance|
model = instance.class
model.delete_all
model.connection.reset_pk_sequence!(model.table_name)
instance.save!
assert_equal 1, instance.id, "Sequence reset for #{model.table_name} failed."
end
end
def test_create_fixtures_resets_sequences_when_not_cached
@instances.each do |instance|
max_id = create_fixtures(instance.class.table_name).inject(0) do |max_id, (name, fixture)|
fixture_id = fixture['id'].to_i
fixture_id > max_id ? fixture_id : max_id
end
# Clone the last fixture to check that it gets the next greatest id.
instance.save!
assert_equal max_id + 1, instance.id, "Sequence reset for #{instance.class.table_name} failed."
end
end
end
end
class FixturesWithoutInstantiationTest < ActiveRecord::TestCase
self.use_instantiated_fixtures = false
fixtures :topics, :developers, :accounts
def test_without_complete_instantiation
assert_nil @first
assert_nil @topics
assert_nil @developers
assert_nil @accounts
end
def test_fixtures_from_root_yml_without_instantiation
assert_nil @unknown
end
def test_accessor_methods
assert_equal "The First Topic", topics(:first).title
assert_equal "Jamis", developers(:jamis).name
assert_equal 50, accounts(:signals37).credit_limit
end
def test_accessor_methods_with_multiple_args
assert_equal 2, topics(:first, :second).size
assert_raise(StandardError) { topics([:first, :second]) }
end
uses_mocha 'reloading_fixtures_through_accessor_methods' do
def test_reloading_fixtures_through_accessor_methods
assert_equal "The First Topic", topics(:first).title
@loaded_fixtures['topics']['first'].expects(:find).returns(stub(:title => "Fresh Topic!"))
assert_equal "Fresh Topic!", topics(:first, true).title
end
end
end
class FixturesWithoutInstanceInstantiationTest < ActiveRecord::TestCase
self.use_instantiated_fixtures = true
self.use_instantiated_fixtures = :no_instances
fixtures :topics, :developers, :accounts
def test_without_instance_instantiation
assert_nil @first
assert_not_nil @topics
assert_not_nil @developers
assert_not_nil @accounts
end
end
class TransactionalFixturesTest < ActiveRecord::TestCase
self.use_instantiated_fixtures = true
self.use_transactional_fixtures = true
fixtures :topics
def test_destroy
assert_not_nil @first
@first.destroy
end
def test_destroy_just_kidding
assert_not_nil @first
end
end
class MultipleFixturesTest < ActiveRecord::TestCase
fixtures :topics
fixtures :developers, :accounts
def test_fixture_table_names
assert_equal %w(topics developers accounts), fixture_table_names
end
end
class SetupTest < ActiveRecord::TestCase
# fixtures :topics
def setup
@first = true
end
def test_nothing
end
end
class SetupSubclassTest < SetupTest
def setup
super
@second = true
end
def test_subclassing_should_preserve_setups
assert @first
assert @second
end
end
class OverlappingFixturesTest < ActiveRecord::TestCase
fixtures :topics, :developers
fixtures :developers, :accounts
def test_fixture_table_names
assert_equal %w(topics developers accounts), fixture_table_names
end
end
class ForeignKeyFixturesTest < ActiveRecord::TestCase
fixtures :fk_test_has_pk, :fk_test_has_fk
# if foreign keys are implemented and fixtures
# are not deleted in reverse order then this test
# case will raise StatementInvalid
def test_number1
assert true
end
def test_number2
assert true
end
end
class CheckSetTableNameFixturesTest < ActiveRecord::TestCase
set_fixture_class :funny_jokes => 'Joke'
fixtures :funny_jokes
# Set to false to blow away fixtures cache and ensure our fixtures are loaded
# and thus takes into account our set_fixture_class
self.use_transactional_fixtures = false
def test_table_method
assert_kind_of Joke, funny_jokes(:a_joke)
end
end
class CustomConnectionFixturesTest < ActiveRecord::TestCase
set_fixture_class :courses => Course
fixtures :courses
# Set to false to blow away fixtures cache and ensure our fixtures are loaded
# and thus takes into account our set_fixture_class
self.use_transactional_fixtures = false
def test_connection
assert_kind_of Course, courses(:ruby)
assert_equal Course.connection, courses(:ruby).connection
end
end
class InvalidTableNameFixturesTest < ActiveRecord::TestCase
fixtures :funny_jokes
# Set to false to blow away fixtures cache and ensure our fixtures are loaded
# and thus takes into account our lack of set_fixture_class
self.use_transactional_fixtures = false
def test_raises_error
assert_raises FixtureClassNotFound do
funny_jokes(:a_joke)
end
end
end
class CheckEscapedYamlFixturesTest < ActiveRecord::TestCase
set_fixture_class :funny_jokes => 'Joke'
fixtures :funny_jokes
# Set to false to blow away fixtures cache and ensure our fixtures are loaded
# and thus takes into account our set_fixture_class
self.use_transactional_fixtures = false
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 < ActiveRecord::TestCase
fixtures :developers_projects
def test_this_should_run_cleanly
assert true
end
end
class FixturesBrokenRollbackTest < ActiveRecord::TestCase
def blank_setup; end
alias_method :ar_setup_fixtures, :setup_fixtures
alias_method :setup_fixtures, :blank_setup
alias_method :setup, :blank_setup
def blank_teardown; end
alias_method :ar_teardown_fixtures, :teardown_fixtures
alias_method :teardown_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_fixtures }
assert_equal 0, Thread.current['open_transactions']
assert_nothing_raised { ar_teardown_fixtures }
assert_equal 0, Thread.current['open_transactions']
end
private
def load_fixtures
raise 'argh'
end
end
class LoadAllFixturesTest < ActiveRecord::TestCase
self.fixture_path = FIXTURES_ROOT + "/all"
fixtures :all
def test_all_there
assert_equal %w(developers people tasks), fixture_table_names.sort
end
end
class FasterFixturesTest < ActiveRecord::TestCase
fixtures :categories, :authors
def load_extra_fixture(name)
fixture = create_fixtures(name)
assert fixture.is_a?(Fixtures)
@loaded_fixtures[fixture.table_name] = fixture
end
def test_cache
assert Fixtures.fixture_is_cached?(ActiveRecord::Base.connection, 'categories')
assert Fixtures.fixture_is_cached?(ActiveRecord::Base.connection, 'authors')
assert_no_queries do
create_fixtures('categories')
create_fixtures('authors')
end
load_extra_fixture('posts')
assert Fixtures.fixture_is_cached?(ActiveRecord::Base.connection, 'posts')
self.class.setup_fixture_accessors('posts')
assert_equal 'Welcome to the weblog', posts(:welcome).title
end
end
class FoxyFixturesTest < ActiveRecord::TestCase
fixtures :parrots, :parrots_pirates, :pirates, :treasures, :mateys, :ships, :computers, :developers
def test_identifies_strings
assert_equal(Fixtures.identify("foo"), Fixtures.identify("foo"))
assert_not_equal(Fixtures.identify("foo"), Fixtures.identify("FOO"))
end
def test_identifies_symbols
assert_equal(Fixtures.identify(:foo), Fixtures.identify(:foo))
end
TIMESTAMP_COLUMNS = %w(created_at created_on updated_at updated_on)
def test_populates_timestamp_columns
TIMESTAMP_COLUMNS.each do |property|
assert_not_nil(parrots(:george).send(property), "should set #{property}")
end
end
def test_does_not_populate_timestamp_columns_if_model_has_set_record_timestamps_to_false
TIMESTAMP_COLUMNS.each do |property|
assert_nil(ships(:black_pearl).send(property), "should not set #{property}")
end
end
def test_populates_all_columns_with_the_same_time
last = nil
TIMESTAMP_COLUMNS.each do |property|
current = parrots(:george).send(property)
last ||= current
assert_equal(last, current)
last = current
end
end
def test_only_populates_columns_that_exist
assert_not_nil(pirates(:blackbeard).created_on)
assert_not_nil(pirates(:blackbeard).updated_on)
end
def test_preserves_existing_fixture_data
assert_equal(2.weeks.ago.to_date, pirates(:redbeard).created_on.to_date)
assert_equal(2.weeks.ago.to_date, pirates(:redbeard).updated_on.to_date)
end
def test_generates_unique_ids
assert_not_nil(parrots(:george).id)
assert_not_equal(parrots(:george).id, parrots(:louis).id)
end
def test_automatically_sets_primary_key
assert_not_nil(ships(:black_pearl))
end
def test_preserves_existing_primary_key
assert_equal(2, ships(:interceptor).id)
end
def test_resolves_belongs_to_symbols
assert_equal(parrots(:george), pirates(:blackbeard).parrot)
end
def test_ignores_belongs_to_symbols_if_association_and_foreign_key_are_named_the_same
assert_equal(developers(:david), computers(:workstation).developer)
end
def test_supports_join_tables
assert(pirates(:blackbeard).parrots.include?(parrots(:george)))
assert(pirates(:blackbeard).parrots.include?(parrots(:louis)))
assert(parrots(:george).pirates.include?(pirates(:blackbeard)))
end
def test_supports_inline_habtm
assert(parrots(:george).treasures.include?(treasures(:diamond)))
assert(parrots(:george).treasures.include?(treasures(:sapphire)))
assert(!parrots(:george).treasures.include?(treasures(:ruby)))
end
def test_supports_inline_habtm_with_specified_id
assert(parrots(:polly).treasures.include?(treasures(:ruby)))
assert(parrots(:polly).treasures.include?(treasures(:sapphire)))
assert(!parrots(:polly).treasures.include?(treasures(:diamond)))
end
def test_supports_yaml_arrays
assert(parrots(:louis).treasures.include?(treasures(:diamond)))
assert(parrots(:louis).treasures.include?(treasures(:sapphire)))
end
def test_strips_DEFAULTS_key
assert_raise(StandardError) { parrots(:DEFAULTS) }
# this lets us do YAML defaults and not have an extra fixture entry
%w(sapphire ruby).each { |t| assert(parrots(:davey).treasures.include?(treasures(t))) }
end
def test_supports_label_interpolation
assert_equal("frederick", parrots(:frederick).name)
end
def test_supports_polymorphic_belongs_to
assert_equal(pirates(:redbeard), treasures(:sapphire).looter)
assert_equal(parrots(:louis), treasures(:ruby).looter)
end
def test_only_generates_a_pk_if_necessary
m = Matey.find(:first)
m.pirate = pirates(:blackbeard)
m.target = pirates(:redbeard)
end
def test_supports_sti
assert_kind_of DeadParrot, parrots(:polly)
assert_equal pirates(:blackbeard), parrots(:polly).killer
end
end
class ActiveSupportSubclassWithFixturesTest < ActiveRecord::TestCase
fixtures :parrots
# This seemingly useless assertion catches a bug that caused the fixtures
# setup code call nil[]
def test_foo
assert_equal parrots(:louis), Parrot.find_by_name("King Louis")
end
end
class FixtureLoadingTest < ActiveRecord::TestCase
uses_mocha 'reloading_fixtures_through_accessor_methods' do
def test_logs_message_for_failed_dependency_load
Test::Unit::TestCase.expects(:require_dependency).with(:does_not_exist).raises(LoadError)
ActiveRecord::Base.logger.expects(:warn)
Test::Unit::TestCase.try_to_load_dependency(:does_not_exist)
end
def test_does_not_logs_message_for_successful_dependency_load
Test::Unit::TestCase.expects(:require_dependency).with(:works_out_fine)
ActiveRecord::Base.logger.expects(:warn).never
Test::Unit::TestCase.try_to_load_dependency(:works_out_fine)
end
end
end

View file

@ -1,47 +0,0 @@
$:.unshift(File.dirname(__FILE__) + '/../../lib')
require 'config'
require 'test/unit'
require 'active_record'
require 'active_record/fixtures'
require 'active_record/test_case'
require 'connection'
# Show backtraces for deprecated behavior for quicker cleanup.
ActiveSupport::Deprecation.debug = true
# Quote "type" if it's a reserved word for the current connection.
QUOTED_TYPE = ActiveRecord::Base.connection.quote_column_name('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
def uses_mocha(description)
require 'rubygems'
require 'mocha'
yield
rescue LoadError
$stderr.puts "Skipping #{description} tests. `gem install mocha` and try again."
end
ActiveRecord::Base.connection.class.class_eval do
IGNORED_SQL = [/^PRAGMA/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/]
def execute_with_counting(sql, name = nil, &block)
$query_count ||= 0
$query_count += 1 unless IGNORED_SQL.any? { |r| sql =~ r }
execute_without_counting(sql, name, &block)
end
alias_method_chain :execute, :counting
end
# Make with_scope public for tests
class << ActiveRecord::Base
public :with_scope, :with_exclusive_scope
end

View file

@ -1,255 +0,0 @@
require "cases/helper"
require 'models/company'
require 'models/project'
require 'models/subscriber'
class InheritanceTest < ActiveRecord::TestCase
fixtures :companies, :projects, :subscribers, :accounts
def test_class_with_store_full_sti_class_returns_full_name
old = ActiveRecord::Base.store_full_sti_class
ActiveRecord::Base.store_full_sti_class = true
assert_equal 'Namespaced::Company', Namespaced::Company.sti_name
ensure
ActiveRecord::Base.store_full_sti_class = old
end
def test_class_without_store_full_sti_class_returns_demodulized_name
old = ActiveRecord::Base.store_full_sti_class
ActiveRecord::Base.store_full_sti_class = false
assert_equal 'Company', Namespaced::Company.sti_name
ensure
ActiveRecord::Base.store_full_sti_class = old
end
def test_should_store_demodulized_class_name_with_store_full_sti_class_option_disabled
old = ActiveRecord::Base.store_full_sti_class
ActiveRecord::Base.store_full_sti_class = false
item = Namespaced::Company.new
assert_equal 'Company', item[:type]
ensure
ActiveRecord::Base.store_full_sti_class = old
end
def test_should_store_full_class_name_with_store_full_sti_class_option_enabled
old = ActiveRecord::Base.store_full_sti_class
ActiveRecord::Base.store_full_sti_class = true
item = Namespaced::Company.new
assert_equal 'Namespaced::Company', item[:type]
ensure
ActiveRecord::Base.store_full_sti_class = old
end
def test_different_namespace_subclass_should_load_correctly_with_store_full_sti_class_option
old = ActiveRecord::Base.store_full_sti_class
ActiveRecord::Base.store_full_sti_class = true
item = Namespaced::Company.create :name => "Wolverine 2"
assert_not_nil Company.find(item.id)
assert_not_nil Namespaced::Company.find(item.id)
ensure
ActiveRecord::Base.store_full_sti_class = old
end
def test_company_descends_from_active_record
assert_raise(NoMethodError) { ActiveRecord::Base.descends_from_active_record? }
assert AbstractCompany.descends_from_active_record?, 'AbstractCompany should descend from ActiveRecord::Base'
assert Company.descends_from_active_record?, 'Company should descend from ActiveRecord::Base'
assert !Class.new(Company).descends_from_active_record?, 'Company subclass should not descend from ActiveRecord::Base'
end
def test_a_bad_type_column
#SQLServer need to turn Identity Insert On before manually inserting into the Identity column
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, :SybaseAdapter)
Company.connection.execute "SET IDENTITY_INSERT companies OFF"
end
assert_raises(ActiveRecord::SubclassNotFound) { Company.find(100) }
end
def test_inheritance_find
assert Company.find(1).kind_of?(Firm), "37signals should be a firm"
assert Firm.find(1).kind_of?(Firm), "37signals should be a firm"
assert Company.find(2).kind_of?(Client), "Summit should be a client"
assert Client.find(2).kind_of?(Client), "Summit should be a client"
end
def test_alt_inheritance_find
switch_to_alt_inheritance_column
test_inheritance_find
switch_to_default_inheritance_column
end
def test_inheritance_find_all
companies = Company.find(:all, :order => 'id')
assert companies[0].kind_of?(Firm), "37signals should be a firm"
assert companies[1].kind_of?(Client), "Summit should be a client"
end
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
firm = Firm.new
firm.name = "Next Angle"
firm.save
next_angle = Company.find(firm.id)
assert next_angle.kind_of?(Firm), "Next Angle should be a firm"
end
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 9, Company.count
assert_equal 2, Firm.count
assert_equal 3, Client.count
end
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
assert_raises(ActiveRecord::RecordNotFound) { Firm.find(2) }
assert_nothing_raised { Firm.find(1) }
end
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
Client.update_all "name = 'I am a client'"
assert_equal "I am a client", Client.find(:all).first.name
assert_equal "37signals", Firm.find(:all).first.name
end
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
Client.destroy_all
assert_equal 0, Client.count
assert_equal 2, Firm.count
end
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
assert_kind_of Firm, Company.find(:first, :conditions => "name = '37signals'")
assert_kind_of Firm, Firm.find(:first, :conditions => "name = '37signals'")
assert_nil Client.find(:first, :conditions => "name = '37signals'")
end
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
very_special_client = VerySpecialClient.create("name" => "veryspecial")
assert_equal very_special_client, VerySpecialClient.find(:first, :conditions => "name = 'veryspecial'")
assert_equal very_special_client, SpecialClient.find(:first, :conditions => "name = 'veryspecial'")
assert_equal very_special_client, Company.find(:first, :conditions => "name = 'veryspecial'")
assert_equal very_special_client, Client.find(:first, :conditions => "name = 'veryspecial'")
assert_equal 1, Client.find(:all, :conditions => "name = 'Summit'").size
assert_equal very_special_client, Client.find(very_special_client.id)
end
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
end
def test_inheritance_without_mapping
assert_kind_of SpecialSubscriber, SpecialSubscriber.find("webster132")
assert_nothing_raised { s = SpecialSubscriber.new("name" => "And breaaaaathe!"); s.id = 'roger'; s.save }
end
private
def switch_to_alt_inheritance_column
# we don't want misleading test results, so get rid of the values in the type column
Company.find(:all, :order => 'id').each do |c|
c['type'] = nil
c.save
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 < ActiveRecord::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

View file

@ -1,24 +0,0 @@
require 'cases/helper'
require 'models/topic'
class InvalidDateTest < Test::Unit::TestCase
def test_assign_valid_dates
valid_dates = [[2007, 11, 30], [1993, 2, 28], [2008, 2, 29]]
invalid_dates = [[2007, 11, 31], [1993, 2, 29], [2007, 2, 29]]
topic = Topic.new
valid_dates.each do |date_src|
topic = Topic.new("last_read(1i)" => date_src[0].to_s, "last_read(2i)" => date_src[1].to_s, "last_read(3i)" => date_src[2].to_s)
assert_equal(topic.last_read, Date.new(*date_src))
end
invalid_dates.each do |date_src|
assert_nothing_raised do
topic = Topic.new({"last_read(1i)" => date_src[0].to_s, "last_read(2i)" => date_src[1].to_s, "last_read(3i)" => date_src[2].to_s})
assert_equal(topic.last_read, Time.local(*date_src).to_date, "The date should be modified according to the behaviour of the Time object")
end
end
end
end

View file

@ -1,205 +0,0 @@
require "cases/helper"
require 'models/contact'
require 'models/post'
require 'models/author'
require 'models/tagging'
require 'models/tag'
require 'models/comment'
class JsonSerializationTest < ActiveRecord::TestCase
class NamespacedContact < Contact
column :name, :string
end
def setup
@contact = Contact.new(
:name => 'Konata Izumi',
:age => 16,
:avatar => 'binarydata',
:created_at => Time.utc(2006, 8, 1),
:awesome => true,
:preferences => { :shows => 'anime' }
)
end
def test_should_demodulize_root_in_json
NamespacedContact.include_root_in_json = true
@contact = NamespacedContact.new :name => 'whatever'
json = @contact.to_json
assert_match %r{^\{"namespaced_contact": \{}, json
end
def test_should_include_root_in_json
Contact.include_root_in_json = true
json = @contact.to_json
assert_match %r{^\{"contact": \{}, json
assert_match %r{"name": "Konata Izumi"}, json
assert_match %r{"age": 16}, json
assert json.include?(%("created_at": #{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
assert_match %r{"awesome": true}, json
assert_match %r{"preferences": \{"shows": "anime"\}}, json
ensure
Contact.include_root_in_json = false
end
def test_should_encode_all_encodable_attributes
json = @contact.to_json
assert_match %r{"name": "Konata Izumi"}, json
assert_match %r{"age": 16}, json
assert json.include?(%("created_at": #{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
assert_match %r{"awesome": true}, json
assert_match %r{"preferences": \{"shows": "anime"\}}, json
end
def test_should_allow_attribute_filtering_with_only
json = @contact.to_json(:only => [:name, :age])
assert_match %r{"name": "Konata Izumi"}, json
assert_match %r{"age": 16}, json
assert_no_match %r{"awesome": true}, json
assert !json.include?(%("created_at": #{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
assert_no_match %r{"preferences": \{"shows": "anime"\}}, json
end
def test_should_allow_attribute_filtering_with_except
json = @contact.to_json(:except => [:name, :age])
assert_no_match %r{"name": "Konata Izumi"}, json
assert_no_match %r{"age": 16}, json
assert_match %r{"awesome": true}, json
assert json.include?(%("created_at": #{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}))
assert_match %r{"preferences": \{"shows": "anime"\}}, json
end
def test_methods_are_called_on_object
# Define methods on fixture.
def @contact.label; "Has cheezburger"; end
def @contact.favorite_quote; "Constraints are liberating"; end
# Single method.
assert_match %r{"label": "Has cheezburger"}, @contact.to_json(:only => :name, :methods => :label)
# Both methods.
methods_json = @contact.to_json(:only => :name, :methods => [:label, :favorite_quote])
assert_match %r{"label": "Has cheezburger"}, methods_json
assert_match %r{"favorite_quote": "Constraints are liberating"}, methods_json
end
end
class DatabaseConnectedJsonEncodingTest < ActiveRecord::TestCase
fixtures :authors, :posts, :comments, :tags, :taggings
def setup
@david = authors(:david)
@mary = authors(:mary)
end
def test_includes_uses_association_name
json = @david.to_json(:include => :posts)
assert_match %r{"posts": \[}, json
assert_match %r{"id": 1}, json
assert_match %r{"name": "David"}, json
assert_match %r{"author_id": 1}, json
assert_match %r{"title": "Welcome to the weblog"}, json
assert_match %r{"body": "Such a lovely day"}, json
assert_match %r{"title": "So I was thinking"}, json
assert_match %r{"body": "Like I hopefully always am"}, json
end
def test_includes_uses_association_name_and_applies_attribute_filters
json = @david.to_json(:include => { :posts => { :only => :title } })
assert_match %r{"name": "David"}, json
assert_match %r{"posts": \[}, json
assert_match %r{"title": "Welcome to the weblog"}, json
assert_no_match %r{"body": "Such a lovely day"}, json
assert_match %r{"title": "So I was thinking"}, json
assert_no_match %r{"body": "Like I hopefully always am"}, json
end
def test_includes_fetches_second_level_associations
json = @david.to_json(:include => { :posts => { :include => { :comments => { :only => :body } } } })
assert_match %r{"name": "David"}, json
assert_match %r{"posts": \[}, json
assert_match %r{"comments": \[}, json
assert_match %r{\{"body": "Thank you again for the welcome"\}}, json
assert_match %r{\{"body": "Don't think too hard"\}}, json
assert_no_match %r{"post_id": }, json
end
def test_includes_fetches_nth_level_associations
json = @david.to_json(
:include => {
:posts => {
:include => {
:taggings => {
:include => {
:tag => { :only => :name }
}
}
}
}
})
assert_match %r{"name": "David"}, json
assert_match %r{"posts": \[}, json
assert_match %r{"taggings": \[}, json
assert_match %r{"tag": \{"name": "General"\}}, json
end
def test_should_not_call_methods_on_associations_that_dont_respond
def @david.favorite_quote; "Constraints are liberating"; end
json = @david.to_json(:include => :posts, :methods => :favorite_quote)
assert !@david.posts.first.respond_to?(:favorite_quote)
assert_match %r{"favorite_quote": "Constraints are liberating"}, json
assert_equal %r{"favorite_quote": }.match(json).size, 1
end
def test_should_allow_only_option_for_list_of_authors
authors = [@david, @mary]
assert_equal %([{"name": "David"}, {"name": "Mary"}]), authors.to_json(:only => :name)
end
def test_should_allow_except_option_for_list_of_authors
authors = [@david, @mary]
assert_equal %([{"id": 1}, {"id": 2}]), authors.to_json(:except => [:name, :author_address_id, :author_address_extra_id])
end
def test_should_allow_includes_for_list_of_authors
authors = [@david, @mary]
json = authors.to_json(
:only => :name,
:include => {
:posts => { :only => :id }
}
)
['"name": "David"', '"posts": [', '{"id": 1}', '{"id": 2}', '{"id": 4}',
'{"id": 5}', '{"id": 6}', '"name": "Mary"', '"posts": [{"id": 7}]'].each do |fragment|
assert json.include?(fragment), json
end
end
def test_should_allow_options_for_hash_of_authors
authors_hash = {
1 => @david,
2 => @mary
}
assert_equal %({1: {"name": "David"}}), authors_hash.to_json(:only => [1, :name])
end
end

View file

@ -1,140 +0,0 @@
require "cases/helper"
require 'models/topic'
require 'models/developer'
require 'models/reply'
class Topic; def after_find() end end
class Developer; def after_find() end end
class SpecialDeveloper < Developer; end
class TopicManualObserver
include Singleton
attr_reader :action, :object, :callbacks
def initialize
Topic.add_observer(self)
@callbacks = []
end
def update(callback_method, object)
@callbacks << { "callback_method" => callback_method, "object" => object }
end
def has_been_notified?
!@callbacks.empty?
end
end
class TopicaAuditor < ActiveRecord::Observer
observe :topic
attr_reader :topic
def after_find(topic)
@topic = topic
end
end
class TopicObserver < ActiveRecord::Observer
attr_reader :topic
def after_find(topic)
@topic = topic
end
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 < ActiveRecord::TestCase
fixtures :topics, :developers
def test_before_destroy
original_count = Topic.count
(topic_to_be_destroyed = Topic.find(1)).destroy
assert_equal original_count - (1 + topic_to_be_destroyed.replies.size), 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)
assert TopicManualObserver.instance.has_been_notified?
assert_equal :after_find, TopicManualObserver.instance.callbacks.first["callback_method"]
end
def test_auto_observer
topic_observer = TopicaAuditor.instance
assert_nil TopicaAuditor.observed_class
assert_equal [Topic], TopicaAuditor.instance.observed_classes.to_a
topic = Topic.find(1)
assert_equal topic.title, topic_observer.topic.title
end
def test_inferred_auto_observer
topic_observer = TopicObserver.instance
assert_equal Topic, TopicObserver.observed_class
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 topic.title, multi_observer.record.title
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 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

View file

@ -1,289 +0,0 @@
require "cases/helper"
require 'models/person'
require 'models/reader'
require 'models/legacy_thing'
require 'models/reference'
class LockWithoutDefault < ActiveRecord::Base; end
class LockWithCustomColumnWithoutDefault < ActiveRecord::Base
set_table_name :lock_without_defaults_cust
set_locking_column :custom_lock_version
end
class ReadonlyFirstNamePerson < Person
attr_readonly :first_name
end
class OptimisticLockingTest < ActiveRecord::TestCase
fixtures :people, :legacy_things, :references
# need to disable transactional fixtures, because otherwise the sqlite3
# adapter (at least) chokes when we try and change the schema in the middle
# of a test (see test_increment_counter_*).
self.use_transactional_fixtures = false
def test_lock_existing
p1 = Person.find(1)
p2 = Person.find(1)
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_repeating
p1 = Person.find(1)
p2 = Person.find(1)
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! }
assert_raises(ActiveRecord::StaleObjectError) { p2.save! }
end
def test_lock_new
p1 = Person.new(:first_name => 'anika')
assert_equal 0, p1.lock_version
p1.save!
p2 = Person.find(p1.id)
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_with_nil
p1 = Person.new(:first_name => 'anika')
p1.save!
p1.lock_version = nil # simulate bad fixture or column with no default
p1.save!
assert_equal 1, p1.lock_version
end
def test_lock_column_name_existing
t1 = LegacyThing.find(1)
t2 = LegacyThing.find(1)
assert_equal 0, t1.version
assert_equal 0, t2.version
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
def test_readonly_attributes
assert_equal Set.new([ 'first_name' ]), ReadonlyFirstNamePerson.readonly_attributes
p = ReadonlyFirstNamePerson.create(:first_name => "unchangeable name")
p.reload
assert_equal "unchangeable name", p.first_name
p.update_attributes(:first_name => "changed name")
p.reload
assert_equal "unchangeable name", p.first_name
end
{ :lock_version => Person, :custom_lock_version => LegacyThing }.each do |name, model|
define_method("test_increment_counter_updates_#{name}") do
counter_test model, 1 do |id|
model.increment_counter :test_count, id
end
end
define_method("test_decrement_counter_updates_#{name}") do
counter_test model, -1 do |id|
model.decrement_counter :test_count, id
end
end
define_method("test_update_counters_updates_#{name}") do
counter_test model, 1 do |id|
model.update_counters id, :test_count => 1
end
end
end
def test_quote_table_name
ref = references(:michael_magician)
ref.favourite = !ref.favourite
assert ref.save
end
private
def add_counter_column_to(model)
model.connection.add_column model.table_name, :test_count, :integer, :null => false, :default => 0
model.reset_column_information
# OpenBase does not set a value to existing rows when adding a not null default column
model.update_all(:test_count => 0) if current_adapter?(:OpenBaseAdapter)
end
def remove_counter_column_from(model)
model.connection.remove_column model.table_name, :test_count
model.reset_column_information
end
def counter_test(model, expected_count)
add_counter_column_to(model)
object = model.find(:first)
assert_equal 0, object.test_count
assert_equal 0, object.send(model.locking_column)
yield object.id
object.reload
assert_equal expected_count, object.test_count
assert_equal 1, object.send(model.locking_column)
ensure
remove_counter_column_from(model)
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, Sybase, and OpenBase adapters currently have no support for pessimistic locking
unless current_adapter?(:SQLServerAdapter, :SybaseAdapter, :OpenBaseAdapter)
class PessimisticLockingTest < ActiveRecord::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

View file

@ -1,452 +0,0 @@
require "cases/helper"
require 'models/developer'
require 'models/project'
require 'models/comment'
require 'models/post'
require 'models/category'
class MethodScopingTest < ActiveRecord::TestCase
fixtures :developers, :projects, :comments, :posts
def test_set_conditions
Developer.with_scope(:find => { :conditions => 'just a test...' }) do
assert_equal 'just a test...', Developer.send(:current_scoped_methods)[:find][:conditions]
end
end
def test_scoped_find
Developer.with_scope(:find => { :conditions => "name = 'David'" }) do
assert_nothing_raised { Developer.find(1) }
end
end
def test_scoped_find_first
Developer.with_scope(:find => { :conditions => "salary = 100000" }) do
assert_equal Developer.find(10), Developer.find(:first, :order => 'name')
end
end
def test_scoped_find_combines_conditions
Developer.with_scope(:find => { :conditions => "salary = 9000" }) do
assert_equal developers(:poor_jamis), Developer.find(:first, :conditions => "name = 'Jamis'")
end
end
def test_scoped_find_sanitizes_conditions
Developer.with_scope(:find => { :conditions => ['salary = ?', 9000] }) do
assert_equal developers(:poor_jamis), Developer.find(:first)
end
end
def test_scoped_find_combines_and_sanitizes_conditions
Developer.with_scope(:find => { :conditions => ['salary = ?', 9000] }) do
assert_equal developers(:poor_jamis), Developer.find(:first, :conditions => ['name = ?', 'Jamis'])
end
end
def test_scoped_find_all
Developer.with_scope(:find => { :conditions => "name = 'David'" }) do
assert_equal [developers(:david)], Developer.find(:all)
end
end
def test_scoped_find_select
Developer.with_scope(:find => { :select => "id, name" }) do
developer = Developer.find(:first, :conditions => "name = 'David'")
assert_equal "David", developer.name
assert !developer.has_attribute?(:salary)
end
end
def test_options_select_replaces_scope_select
Developer.with_scope(:find => { :select => "id, name" }) do
developer = Developer.find(:first, :select => 'id, salary', :conditions => "name = 'David'")
assert_equal 80000, developer.salary
assert !developer.has_attribute?(:name)
end
end
def test_scoped_count
Developer.with_scope(:find => { :conditions => "name = 'David'" }) do
assert_equal 1, Developer.count
end
Developer.with_scope(:find => { :conditions => 'salary = 100000' }) do
assert_equal 8, Developer.count
assert_equal 1, Developer.count(:conditions => "name LIKE 'fixture_1%'")
end
end
def test_scoped_find_include
# with the include, will retrieve only developers for the given project
scoped_developers = Developer.with_scope(:find => { :include => :projects }) do
Developer.find(:all, :conditions => 'projects.id = 2')
end
assert scoped_developers.include?(developers(:david))
assert !scoped_developers.include?(developers(:jamis))
assert_equal 1, scoped_developers.size
end
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(:conditions => 'projects.id = 2')
end
end
def test_scoped_create
new_comment = nil
VerySpecialComment.with_scope(:create => { :post_id => 1 }) do
assert_equal({ :post_id => 1 }, VerySpecialComment.send(:current_scoped_methods)[:create])
new_comment = VerySpecialComment.create :body => "Wonderful world"
end
assert Post.find(1).comments.include?(new_comment)
end
def test_immutable_scope
options = { :conditions => "name = 'David'" }
Developer.with_scope(:find => options) do
assert_equal %w(David), Developer.find(:all).map { |d| d.name }
options[:conditions] = "name != 'David'"
assert_equal %w(David), Developer.find(:all).map { |d| d.name }
end
scope = { :find => { :conditions => "name = 'David'" }}
Developer.with_scope(scope) do
assert_equal %w(David), Developer.find(:all).map { |d| d.name }
scope[:find][:conditions] = "name != 'David'"
assert_equal %w(David), Developer.find(:all).map { |d| d.name }
end
end
def test_scoped_with_duck_typing
scoping = Struct.new(:method_scoping).new(:find => { :conditions => ["name = ?", 'David'] })
Developer.with_scope(scoping) do
assert_equal %w(David), Developer.find(:all).map { |d| d.name }
end
end
def test_ensure_that_method_scoping_is_correctly_restored
scoped_methods = Developer.instance_eval('current_scoped_methods')
begin
Developer.with_scope(:find => { :conditions => "name = 'Jamis'" }) do
raise "an exception"
end
rescue
end
assert_equal scoped_methods, Developer.instance_eval('current_scoped_methods')
end
end
class NestedScopingTest < ActiveRecord::TestCase
fixtures :developers, :projects, :comments, :posts
def test_merge_options
Developer.with_scope(:find => { :conditions => 'salary = 80000' }) do
Developer.with_scope(:find => { :limit => 10 }) do
merged_option = Developer.instance_eval('current_scoped_methods')[:find]
assert_equal({ :conditions => 'salary = 80000', :limit => 10 }, merged_option)
end
end
end
def test_replace_options
Developer.with_scope(:find => { :conditions => "name = 'David'" }) do
Developer.with_exclusive_scope(:find => { :conditions => "name = 'Jamis'" }) do
assert_equal({:find => { :conditions => "name = 'Jamis'" }}, Developer.instance_eval('current_scoped_methods'))
assert_equal({:find => { :conditions => "name = 'Jamis'" }}, Developer.send(:scoped_methods)[-1])
end
end
end
def test_append_conditions
Developer.with_scope(:find => { :conditions => "name = 'David'" }) do
Developer.with_scope(:find => { :conditions => 'salary = 80000' }) do
appended_condition = Developer.instance_eval('current_scoped_methods')[:find][:conditions]
assert_equal("(name = 'David') AND (salary = 80000)", appended_condition)
assert_equal(1, Developer.count)
end
Developer.with_scope(:find => { :conditions => "name = 'Maiha'" }) do
assert_equal(0, Developer.count)
end
end
end
def test_merge_and_append_options
Developer.with_scope(:find => { :conditions => 'salary = 80000', :limit => 10 }) do
Developer.with_scope(:find => { :conditions => "name = 'David'" }) do
merged_option = Developer.instance_eval('current_scoped_methods')[:find]
assert_equal({ :conditions => "(salary = 80000) AND (name = 'David')", :limit => 10 }, merged_option)
end
end
end
def test_nested_scoped_find
Developer.with_scope(:find => { :conditions => "name = 'Jamis'" }) do
Developer.with_exclusive_scope(:find => { :conditions => "name = 'David'" }) do
assert_nothing_raised { Developer.find(1) }
assert_equal('David', Developer.find(:first).name)
end
assert_equal('Jamis', Developer.find(:first).name)
end
end
def test_nested_scoped_find_include
Developer.with_scope(:find => { :include => :projects }) do
Developer.with_scope(:find => { :conditions => "projects.id = 2" }) do
assert_nothing_raised { Developer.find(1) }
assert_equal('David', Developer.find(:first).name)
end
end
end
def test_nested_scoped_find_merged_include
# :include's remain unique and don't "double up" when merging
Developer.with_scope(:find => { :include => :projects, :conditions => "projects.id = 2" }) do
Developer.with_scope(:find => { :include => :projects }) do
assert_equal 1, Developer.instance_eval('current_scoped_methods')[:find][:include].length
assert_equal('David', Developer.find(:first).name)
end
end
# the nested scope doesn't remove the first :include
Developer.with_scope(:find => { :include => :projects, :conditions => "projects.id = 2" }) do
Developer.with_scope(:find => { :include => [] }) do
assert_equal 1, Developer.instance_eval('current_scoped_methods')[:find][:include].length
assert_equal('David', Developer.find(:first).name)
end
end
# mixing array and symbol include's will merge correctly
Developer.with_scope(:find => { :include => [:projects], :conditions => "projects.id = 2" }) do
Developer.with_scope(:find => { :include => :projects }) do
assert_equal 1, Developer.instance_eval('current_scoped_methods')[:find][:include].length
assert_equal('David', Developer.find(:first).name)
end
end
end
def test_nested_scoped_find_replace_include
Developer.with_scope(:find => { :include => :projects }) do
Developer.with_exclusive_scope(:find => { :include => [] }) do
assert_equal 0, Developer.instance_eval('current_scoped_methods')[:find][:include].length
end
end
end
def test_three_level_nested_exclusive_scoped_find
Developer.with_scope(:find => { :conditions => "name = 'Jamis'" }) do
assert_equal('Jamis', Developer.find(:first).name)
Developer.with_exclusive_scope(:find => { :conditions => "name = 'David'" }) do
assert_equal('David', Developer.find(:first).name)
Developer.with_exclusive_scope(:find => { :conditions => "name = 'Maiha'" }) do
assert_equal(nil, Developer.find(:first))
end
# ensure that scoping is restored
assert_equal('David', Developer.find(:first).name)
end
# ensure that scoping is restored
assert_equal('Jamis', Developer.find(:first).name)
end
end
def test_merged_scoped_find
poor_jamis = developers(:poor_jamis)
Developer.with_scope(:find => { :conditions => "salary < 100000" }) do
Developer.with_scope(:find => { :offset => 1 }) do
assert_equal(poor_jamis, Developer.find(:first, :order => 'id asc'))
end
end
end
def test_merged_scoped_find_sanitizes_conditions
Developer.with_scope(:find => { :conditions => ["name = ?", 'David'] }) do
Developer.with_scope(:find => { :conditions => ['salary = ?', 9000] }) do
assert_raise(ActiveRecord::RecordNotFound) { developers(:poor_jamis) }
end
end
end
def test_nested_scoped_find_combines_and_sanitizes_conditions
Developer.with_scope(:find => { :conditions => ["name = ?", 'David'] }) do
Developer.with_exclusive_scope(:find => { :conditions => ['salary = ?', 9000] }) do
assert_equal developers(:poor_jamis), Developer.find(:first)
assert_equal developers(:poor_jamis), Developer.find(:first, :conditions => ['name = ?', 'Jamis'])
end
end
end
def test_merged_scoped_find_combines_and_sanitizes_conditions
Developer.with_scope(:find => { :conditions => ["name = ?", 'David'] }) do
Developer.with_scope(:find => { :conditions => ['salary > ?', 9000] }) do
assert_equal %w(David), Developer.find(:all).map { |d| d.name }
end
end
end
def test_merged_scoped_find_on_blank_conditions
[nil, " ", [], {}].each do |blank|
Developer.with_scope(:find => {:conditions => blank}) do
Developer.with_scope(:find => {:conditions => blank}) do
assert_nothing_raised { Developer.find(:first) }
end
end
end
end
def test_merged_scoped_find_on_blank_bind_conditions
[ [""], ["",{}] ].each do |blank|
Developer.with_scope(:find => {:conditions => blank}) do
Developer.with_scope(:find => {:conditions => blank}) do
assert_nothing_raised { Developer.find(:first) }
end
end
end
end
def test_immutable_nested_scope
options1 = { :conditions => "name = 'Jamis'" }
options2 = { :conditions => "name = 'David'" }
Developer.with_scope(:find => options1) do
Developer.with_exclusive_scope(:find => options2) do
assert_equal %w(David), Developer.find(:all).map { |d| d.name }
options1[:conditions] = options2[:conditions] = nil
assert_equal %w(David), Developer.find(:all).map { |d| d.name }
end
end
end
def test_immutable_merged_scope
options1 = { :conditions => "name = 'Jamis'" }
options2 = { :conditions => "salary > 10000" }
Developer.with_scope(:find => options1) do
Developer.with_scope(:find => options2) do
assert_equal %w(Jamis), Developer.find(:all).map { |d| d.name }
options1[:conditions] = options2[:conditions] = nil
assert_equal %w(Jamis), Developer.find(:all).map { |d| d.name }
end
end
end
def test_ensure_that_method_scoping_is_correctly_restored
Developer.with_scope(:find => { :conditions => "name = 'David'" }) do
scoped_methods = Developer.instance_eval('current_scoped_methods')
begin
Developer.with_scope(:find => { :conditions => "name = 'Maiha'" }) do
raise "an exception"
end
rescue
end
assert_equal scoped_methods, Developer.instance_eval('current_scoped_methods')
end
end
end
class HasManyScopingTest< ActiveRecord::TestCase
fixtures :comments, :posts
def setup
@welcome = Post.find(1)
end
def test_forwarding_of_static_methods
assert_equal 'a comment...', Comment.what_are_you
assert_equal 'a comment...', @welcome.comments.what_are_you
end
def test_forwarding_to_scoped
assert_equal 4, Comment.search_by_type('Comment').size
assert_equal 2, @welcome.comments.search_by_type('Comment').size
end
def test_forwarding_to_dynamic_finders
assert_equal 4, Comment.find_all_by_type('Comment').size
assert_equal 2, @welcome.comments.find_all_by_type('Comment').size
end
def test_nested_scope
Comment.with_scope(:find => { :conditions => '1=1' }) do
assert_equal 'a comment...', @welcome.comments.what_are_you
end
end
end
class HasAndBelongsToManyScopingTest< ActiveRecord::TestCase
fixtures :posts, :categories, :categories_posts
def setup
@welcome = Post.find(1)
end
def test_forwarding_of_static_methods
assert_equal 'a category...', Category.what_are_you
assert_equal 'a category...', @welcome.categories.what_are_you
end
def test_forwarding_to_dynamic_finders
assert_equal 4, Category.find_all_by_type('SpecialCategory').size
assert_equal 0, @welcome.categories.find_all_by_type('SpecialCategory').size
assert_equal 2, @welcome.categories.find_all_by_type('Category').size
end
def test_nested_scope
Category.with_scope(:find => { :conditions => '1=1' }) do
assert_equal 'a comment...', @welcome.comments.what_are_you
end
end
end
=begin
# We disabled the scoping for has_one and belongs_to as we can't think of a proper use case
class BelongsToScopingTest< ActiveRecord::TestCase
fixtures :comments, :posts
def setup
@greetings = Comment.find(1)
end
def test_forwarding_of_static_method
assert_equal 'a post...', Post.what_are_you
assert_equal 'a post...', @greetings.post.what_are_you
end
def test_forwarding_to_dynamic_finders
assert_equal 4, Post.find_all_by_type('Post').size
assert_equal 1, @greetings.post.find_all_by_type('Post').size
end
end
class HasOneScopingTest< ActiveRecord::TestCase
fixtures :comments, :posts
def setup
@sti_comments = Post.find(4)
end
def test_forwarding_of_static_methods
assert_equal 'a comment...', Comment.what_are_you
assert_equal 'a very special comment...', @sti_comments.very_special_comment.what_are_you
end
def test_forwarding_to_dynamic_finders
assert_equal 1, Comment.find_all_by_type('VerySpecialComment').size
assert_equal 1, @sti_comments.very_special_comment.find_all_by_type('VerySpecialComment').size
assert_equal 0, @sti_comments.very_special_comment.find_all_by_type('Comment').size
end
end
=end

File diff suppressed because it is too large Load diff

View file

@ -1,124 +0,0 @@
require "cases/helper"
require 'models/course'
class FirebirdMigrationTest < ActiveRecord::TestCase
self.use_transactional_fixtures = false
def setup
# using Course connection for tests -- need a db that doesn't already have a BOOLEAN domain
@connection = Course.connection
@fireruby_connection = @connection.instance_variable_get(:@connection)
end
def teardown
@connection.drop_table :foo rescue nil
@connection.execute("DROP DOMAIN D_BOOLEAN") rescue nil
end
def test_create_table_with_custom_sequence_name
assert_nothing_raised do
@connection.create_table(:foo, :sequence => 'foo_custom_seq') do |f|
f.column :bar, :string
end
end
assert !sequence_exists?('foo_seq')
assert sequence_exists?('foo_custom_seq')
assert_nothing_raised { @connection.drop_table(:foo, :sequence => 'foo_custom_seq') }
assert !sequence_exists?('foo_custom_seq')
ensure
FireRuby::Generator.new('foo_custom_seq', @fireruby_connection).drop rescue nil
end
def test_create_table_without_sequence
assert_nothing_raised do
@connection.create_table(:foo, :sequence => false) do |f|
f.column :bar, :string
end
end
assert !sequence_exists?('foo_seq')
assert_nothing_raised { @connection.drop_table :foo }
assert_nothing_raised do
@connection.create_table(:foo, :id => false) do |f|
f.column :bar, :string
end
end
assert !sequence_exists?('foo_seq')
assert_nothing_raised { @connection.drop_table :foo }
end
def test_create_table_with_boolean_column
assert !boolean_domain_exists?
assert_nothing_raised do
@connection.create_table :foo do |f|
f.column :bar, :string
f.column :baz, :boolean
end
end
assert boolean_domain_exists?
end
def test_add_boolean_column
assert !boolean_domain_exists?
@connection.create_table :foo do |f|
f.column :bar, :string
end
assert_nothing_raised { @connection.add_column :foo, :baz, :boolean }
assert boolean_domain_exists?
assert_equal :boolean, @connection.columns(:foo).find { |c| c.name == "baz" }.type
end
def test_change_column_to_boolean
assert !boolean_domain_exists?
# Manually create table with a SMALLINT column, which can be changed to a BOOLEAN
@connection.execute "CREATE TABLE foo (bar SMALLINT)"
assert_equal :integer, @connection.columns(:foo).find { |c| c.name == "bar" }.type
assert_nothing_raised { @connection.change_column :foo, :bar, :boolean }
assert boolean_domain_exists?
assert_equal :boolean, @connection.columns(:foo).find { |c| c.name == "bar" }.type
end
def test_rename_table_with_data_and_index
@connection.create_table :foo do |f|
f.column :baz, :string, :limit => 50
end
100.times { |i| @connection.execute "INSERT INTO foo VALUES (GEN_ID(foo_seq, 1), 'record #{i+1}')" }
@connection.add_index :foo, :baz
assert_nothing_raised { @connection.rename_table :foo, :bar }
assert !@connection.tables.include?("foo")
assert @connection.tables.include?("bar")
assert_equal "index_bar_on_baz", @connection.indexes("bar").first.name
assert_equal 100, FireRuby::Generator.new("bar_seq", @fireruby_connection).last
assert_equal 100, @connection.select_one("SELECT COUNT(*) FROM bar")["count"]
ensure
@connection.drop_table :bar rescue nil
end
def test_renaming_table_with_fk_constraint_raises_error
@connection.create_table :parent do |p|
p.column :name, :string
end
@connection.create_table :child do |c|
c.column :parent_id, :integer
end
@connection.execute "ALTER TABLE child ADD CONSTRAINT fk_child_parent FOREIGN KEY(parent_id) REFERENCES parent(id)"
assert_raise(ActiveRecord::ActiveRecordError) { @connection.rename_table :child, :descendant }
ensure
@connection.drop_table :child rescue nil
@connection.drop_table :descendant rescue nil
@connection.drop_table :parent rescue nil
end
private
def boolean_domain_exists?
!@connection.select_one("SELECT 1 FROM rdb$fields WHERE rdb$field_name = 'D_BOOLEAN'").nil?
end
def sequence_exists?(sequence_name)
FireRuby::Generator.exists?(sequence_name, @fireruby_connection)
end
end

View file

@ -1,96 +0,0 @@
require "cases/helper"
class Mixin < ActiveRecord::Base
end
# 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 TouchTest < ActiveRecord::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
assert_nil stamped.updated_at
assert_nil stamped.created_at
stamped.save
assert_equal Time.now, stamped.updated_at
assert_equal Time.now, stamped.created_at
end
def test_create
obj = Mixin.create
assert_equal Time.now, obj.updated_at
assert_equal Time.now, obj.created_at
end
def test_many_updates
stamped = Mixin.new
assert_nil stamped.updated_at
assert_nil stamped.created_at
stamped.save
assert_equal Time.now, stamped.created_at
assert_equal Time.now, stamped.updated_at
old_updated_at = stamped.updated_at
Time.forced_now_time = 5.minutes.from_now
stamped.lft_will_change!
stamped.save
assert_equal Time.now, stamped.updated_at
assert_equal old_updated_at, stamped.created_at
end
def test_create_turned_off
Mixin.record_timestamps = false
mixin = Mixin.new
assert_nil mixin.updated_at
mixin.save
assert_nil mixin.updated_at
# Make sure Mixin.record_timestamps gets reset, even if this test fails,
# so that other tests do not fail because Mixin.record_timestamps == false
rescue Exception => e
raise e
ensure
Mixin.record_timestamps = true
end
end

View file

@ -1,39 +0,0 @@
require "cases/helper"
require 'models/company_in_module'
class ModulesTest < ActiveRecord::TestCase
fixtures :accounts, :companies, :projects, :developers
def test_module_spanning_associations
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"
end
def test_module_spanning_has_and_belongs_to_many_associations
project = MyApplication::Business::Project.find(:first)
project.developers << MyApplication::Business::Developer.create("name" => "John")
assert "John", project.developers.last.name
end
def test_associations_spanning_cross_modules
account = MyApplication::Billing::Account.find(:first, :order => 'id')
assert_kind_of MyApplication::Business::Firm, account.firm
assert_kind_of MyApplication::Billing::Firm, account.qualified_billing_firm
assert_kind_of MyApplication::Billing::Firm, account.unqualified_billing_firm
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
def test_table_name
assert_equal 'accounts', MyApplication::Billing::Account.table_name, 'table_name for ActiveRecord model in module'
assert_equal 'companies', MyApplication::Business::Client.table_name, 'table_name for ActiveRecord model subclass'
assert_equal 'company_contacts', MyApplication::Business::Client::Contact.table_name, 'table_name for ActiveRecord model enclosed by another ActiveRecord model'
end
end

View file

@ -1,60 +0,0 @@
require "cases/helper"
require 'models/entrant'
# So we can test whether Course.connection survives a reload.
require_dependency 'models/course'
class MultipleDbTest < ActiveRecord::TestCase
self.use_transactional_fixtures = false
def setup
@courses = create_fixtures("courses") { Course.retrieve_connection }
@entrants = create_fixtures("entrants")
end
def test_connected
assert_not_nil Entrant.connection
assert_not_nil Course.connection
end
def test_proper_connection
assert_not_equal(Entrant.connection, Course.connection)
assert_equal(Entrant.connection, Entrant.retrieve_connection)
assert_equal(Course.connection, Course.retrieve_connection)
assert_equal(ActiveRecord::Base.connection, Entrant.connection)
end
def test_find
c1 = Course.find(1)
assert_equal "Ruby Development", c1.name
c2 = Course.find(2)
assert_equal "Java Development", c2.name
e1 = Entrant.find(1)
assert_equal "Ruby Developer", e1.name
e2 = Entrant.find(2)
assert_equal "Ruby Guru", e2.name
e3 = Entrant.find(3)
assert_equal "Java Lover", e3.name
end
def test_associations
c1 = Course.find(1)
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
e3 = Entrant.find(3)
assert_equal e3.course.id, c2.id
end
def test_course_connection_should_survive_dependency_reload
assert Course.connection
Dependencies.clear
Object.send(:remove_const, :Course)
require_dependency 'models/course'
assert Course.connection
end
end

View file

@ -1,157 +0,0 @@
require "cases/helper"
require 'models/post'
require 'models/topic'
require 'models/comment'
require 'models/reply'
require 'models/author'
class NamedScopeTest < ActiveRecord::TestCase
fixtures :posts, :authors, :topics, :comments
def test_implements_enumerable
assert !Topic.find(:all).empty?
assert_equal Topic.find(:all), Topic.base
assert_equal Topic.find(:all), Topic.base.to_a
assert_equal Topic.find(:first), Topic.base.first
assert_equal Topic.find(:all), Topic.base.each { |i| i }
end
def test_found_items_are_cached
Topic.columns
all_posts = Topic.base
assert_queries(1) do
all_posts.collect
all_posts.collect
end
end
def test_reload_expires_cache_of_found_items
all_posts = Topic.base
all_posts.inspect
new_post = Topic.create!
assert !all_posts.include?(new_post)
assert all_posts.reload.include?(new_post)
end
def test_delegates_finds_and_calculations_to_the_base_class
assert !Topic.find(:all).empty?
assert_equal Topic.find(:all), Topic.base.find(:all)
assert_equal Topic.find(:first), Topic.base.find(:first)
assert_equal Topic.count, Topic.base.count
assert_equal Topic.average(:replies_count), Topic.base.average(:replies_count)
end
def test_subclasses_inherit_scopes
assert Topic.scopes.include?(:base)
assert Reply.scopes.include?(:base)
assert_equal Reply.find(:all), Reply.base
end
def test_scopes_with_options_limit_finds_to_those_matching_the_criteria_specified
assert !Topic.find(:all, :conditions => {:approved => true}).empty?
assert_equal Topic.find(:all, :conditions => {:approved => true}), Topic.approved
assert_equal Topic.count(:conditions => {:approved => true}), Topic.approved.count
end
def test_scopes_are_composable
assert_equal (approved = Topic.find(:all, :conditions => {:approved => true})), Topic.approved
assert_equal (replied = Topic.find(:all, :conditions => 'replies_count > 0')), Topic.replied
assert !(approved == replied)
assert !(approved & replied).empty?
assert_equal approved & replied, Topic.approved.replied
end
def test_procedural_scopes
topics_written_before_the_third = Topic.find(:all, :conditions => ['written_on < ?', topics(:third).written_on])
topics_written_before_the_second = Topic.find(:all, :conditions => ['written_on < ?', topics(:second).written_on])
assert_not_equal topics_written_before_the_second, topics_written_before_the_third
assert_equal topics_written_before_the_third, Topic.written_before(topics(:third).written_on)
assert_equal topics_written_before_the_second, Topic.written_before(topics(:second).written_on)
end
def test_extensions
assert_equal 1, Topic.anonymous_extension.one
assert_equal 2, Topic.named_extension.two
end
def test_multiple_extensions
assert_equal 2, Topic.multiple_extensions.extension_two
assert_equal 1, Topic.multiple_extensions.extension_one
end
def test_has_many_associations_have_access_to_named_scopes
assert_not_equal Post.containing_the_letter_a, authors(:david).posts
assert !Post.containing_the_letter_a.empty?
assert_equal authors(:david).posts & Post.containing_the_letter_a, authors(:david).posts.containing_the_letter_a
end
def test_has_many_through_associations_have_access_to_named_scopes
assert_not_equal Comment.containing_the_letter_e, authors(:david).comments
assert !Comment.containing_the_letter_e.empty?
assert_equal authors(:david).comments & Comment.containing_the_letter_e, authors(:david).comments.containing_the_letter_e
end
def test_active_records_have_scope_named__all__
assert !Topic.find(:all).empty?
assert_equal Topic.find(:all), Topic.base
end
def test_active_records_have_scope_named__scoped__
assert !Topic.find(:all, scope = {:conditions => "content LIKE '%Have%'"}).empty?
assert_equal Topic.find(:all, scope), Topic.scoped(scope)
end
def test_proxy_options
expected_proxy_options = { :conditions => { :approved => true } }
assert_equal expected_proxy_options, Topic.approved.proxy_options
end
def test_first_and_last_should_support_find_options
assert_equal Topic.base.first(:order => 'title'), Topic.base.find(:first, :order => 'title')
assert_equal Topic.base.last(:order => 'title'), Topic.base.find(:last, :order => 'title')
end
def test_first_and_last_should_allow_integers_for_limit
assert_equal Topic.base.first(2), Topic.base.to_a.first(2)
assert_equal Topic.base.last(2), Topic.base.to_a.last(2)
end
def test_first_and_last_should_not_use_query_when_results_are_loaded
topics = Topic.base
topics.reload # force load
assert_no_queries do
topics.first
topics.last
end
end
def test_first_and_last_find_options_should_use_query_when_results_are_loaded
topics = Topic.base
topics.reload # force load
assert_queries(2) do
topics.first(:order => 'title')
topics.last(:order => 'title')
end
end
def test_empty_should_not_load_results
topics = Topic.base
assert_queries(2) do
topics.empty? # use count query
topics.collect # force load
topics.empty? # use loaded (no query)
end
end
end

View file

@ -1,101 +0,0 @@
require "cases/helper"
require 'models/topic'
require 'models/reply'
require 'models/subscriber'
require 'models/movie'
require 'models/keyboard'
require 'models/mixed_case_monkey'
class PrimaryKeysTest < ActiveRecord::TestCase
fixtures :topics, :subscribers, :movies, :mixed_case_monkeys
def test_integer_key
topic = Topic.find(1)
assert_equal(topics(:first).author_name, topic.author_name)
topic = Topic.find(2)
assert_equal(topics(:second).author_name, topic.author_name)
topic = Topic.new
topic.title = "New Topic"
assert_equal(nil, topic.id)
assert_nothing_raised { topic.save! }
id = topic.id
topicReloaded = Topic.find(id)
assert_equal("New Topic", topicReloaded.title)
end
def test_customized_primary_key_auto_assigns_on_save
Keyboard.delete_all
keyboard = Keyboard.new(:name => 'HHKB')
assert_nothing_raised { keyboard.save! }
assert_equal keyboard.id, Keyboard.find_by_name('HHKB').id
end
def test_customized_primary_key_can_be_get_before_saving
keyboard = Keyboard.new
assert_nil keyboard.id
assert_nothing_raised { assert_nil keyboard.key_number }
end
def test_customized_string_primary_key_settable_before_save
subscriber = Subscriber.new
assert_nothing_raised { subscriber.id = 'webster123' }
assert_equal 'webster123', subscriber.id
assert_equal 'webster123', subscriber.nick
end
def test_string_key
subscriber = Subscriber.find(subscribers(:first).nick)
assert_equal(subscribers(:first).name, subscriber.name)
subscriber = Subscriber.find(subscribers(:second).nick)
assert_equal(subscribers(:second).name, subscriber.name)
subscriber = Subscriber.new
subscriber.id = "jdoe"
assert_equal("jdoe", subscriber.id)
subscriber.name = "John Doe"
assert_nothing_raised { subscriber.save! }
assert_equal("jdoe", subscriber.id)
subscriberReloaded = Subscriber.find("jdoe")
assert_equal("John Doe", subscriberReloaded.name)
end
def test_find_with_more_than_one_string_key
assert_equal 2, Subscriber.find(subscribers(:first).nick, subscribers(:second).nick).length
end
def test_primary_key_prefix
ActiveRecord::Base.primary_key_prefix_type = :table_name
Topic.reset_primary_key
assert_equal "topicid", Topic.primary_key
ActiveRecord::Base.primary_key_prefix_type = :table_name_with_underscore
Topic.reset_primary_key
assert_equal "topic_id", Topic.primary_key
ActiveRecord::Base.primary_key_prefix_type = nil
Topic.reset_primary_key
assert_equal "id", Topic.primary_key
end
def test_delete_should_quote_pkey
assert_nothing_raised { MixedCaseMonkey.delete(1) }
end
def test_update_counters_should_quote_pkey_and_quote_counter_columns
assert_nothing_raised { MixedCaseMonkey.update_counters(1, :fleaCount => 99) }
end
def test_find_with_one_id_should_quote_pkey
assert_nothing_raised { MixedCaseMonkey.find(1) }
end
def test_find_with_multiple_ids_should_quote_pkey
assert_nothing_raised { MixedCaseMonkey.find([1,2]) }
end
def test_instance_update_should_quote_pkey
assert_nothing_raised { MixedCaseMonkey.find(1).save }
end
def test_instance_destroy_should_quote_pkey
assert_nothing_raised { MixedCaseMonkey.find(1).destroy }
end
end

View file

@ -1,126 +0,0 @@
require "cases/helper"
require 'models/topic'
require 'models/reply'
require 'models/task'
require 'models/course'
require 'models/category'
require 'models/post'
class QueryCacheTest < ActiveRecord::TestCase
fixtures :tasks, :topics, :categories, :posts, :categories_posts
def test_find_queries
assert_queries(2) { Task.find(1); Task.find(1) }
end
def test_find_queries_with_cache
Task.cache do
assert_queries(1) { Task.find(1); Task.find(1) }
end
end
def test_count_queries_with_cache
Task.cache do
assert_queries(1) { Task.count; Task.count }
end
end
def test_query_cache_dups_results_correctly
Task.cache do
now = Time.now.utc
task = Task.find 1
assert_not_equal now, task.starting
task.starting = now
task.reload
assert_not_equal now, task.starting
end
end
def test_cache_is_flat
Task.cache do
Topic.columns # don't count this query
assert_queries(1) { Topic.find(1); Topic.find(1); }
end
ActiveRecord::Base.cache do
assert_queries(1) { Task.find(1); Task.find(1) }
end
end
def test_cache_does_not_wrap_string_results_in_arrays
Task.cache do
assert_instance_of String, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks")
end
end
end
uses_mocha 'QueryCacheExpiryTest' do
class QueryCacheExpiryTest < ActiveRecord::TestCase
fixtures :tasks
def test_find
Task.connection.expects(:clear_query_cache).times(1)
assert !Task.connection.query_cache_enabled
Task.cache do
assert Task.connection.query_cache_enabled
Task.find(1)
Task.uncached do
assert !Task.connection.query_cache_enabled
Task.find(1)
end
assert Task.connection.query_cache_enabled
end
assert !Task.connection.query_cache_enabled
end
def test_update
Task.connection.expects(:clear_query_cache).times(2)
Task.cache do
task = Task.find(1)
task.starting = Time.now.utc
task.save!
end
end
def test_destroy
Task.connection.expects(:clear_query_cache).times(2)
Task.cache do
Task.find(1).destroy
end
end
def test_insert
ActiveRecord::Base.connection.expects(:clear_query_cache).times(2)
Task.cache do
Task.create!
end
end
def test_cache_is_expired_by_habtm_update
ActiveRecord::Base.connection.expects(:clear_query_cache).times(2)
ActiveRecord::Base.cache do
c = Category.find(:first)
p = Post.find(:first)
p.categories << c
end
end
def test_cache_is_expired_by_habtm_delete
ActiveRecord::Base.connection.expects(:clear_query_cache).times(2)
ActiveRecord::Base.cache do
c = Category.find(:first)
p = Post.find(:first)
p.categories.delete_all
end
end
end
end

View file

@ -1,107 +0,0 @@
require "cases/helper"
require 'models/post'
require 'models/comment'
require 'models/developer'
require 'models/project'
require 'models/reader'
require 'models/person'
# Dummy class methods to test implicit association scoping.
def Comment.foo() find :first end
def Project.foo() find :first end
class ReadOnlyTest < ActiveRecord::TestCase
fixtures :posts, :comments, :developers, :projects, :developers_projects
def test_cant_save_readonly_record
dev = Developer.find(1)
assert !dev.readonly?
dev.readonly!
assert dev.readonly?
assert_nothing_raised do
dev.name = 'Luscious forbidden fruit.'
assert !dev.save
dev.name = 'Forbidden.'
end
assert_raise(ActiveRecord::ReadOnlyRecord) { dev.save }
assert_raise(ActiveRecord::ReadOnlyRecord) { dev.save! }
end
def test_find_with_readonly_option
Developer.find(:all).each { |d| assert !d.readonly? }
Developer.find(:all, :readonly => false).each { |d| assert !d.readonly? }
Developer.find(:all, :readonly => true).each { |d| assert d.readonly? }
end
def test_find_with_joins_option_implies_readonly
# Blank joins don't count.
Developer.find(:all, :joins => ' ').each { |d| assert !d.readonly? }
Developer.find(:all, :joins => ' ', :readonly => false).each { |d| assert !d.readonly? }
# Others do.
Developer.find(:all, :joins => ', projects').each { |d| assert d.readonly? }
Developer.find(:all, :joins => ', projects', :readonly => false).each { |d| assert !d.readonly? }
end
def test_habtm_find_readonly
dev = Developer.find(1)
assert !dev.projects.empty?
assert dev.projects.all?(&:readonly?)
assert dev.projects.find(:all).all?(&:readonly?)
assert dev.projects.find(:all, :readonly => true).all?(&:readonly?)
end
def test_has_many_find_readonly
post = Post.find(1)
assert !post.comments.empty?
assert !post.comments.any?(&:readonly?)
assert !post.comments.find(:all).any?(&:readonly?)
assert post.comments.find(:all, :readonly => true).all?(&:readonly?)
end
def test_has_many_with_through_is_not_implicitly_marked_readonly
assert people = Post.find(1).people
assert !people.any?(&:readonly?)
end
def test_readonly_scoping
Post.with_scope(:find => { :conditions => '1=1' }) do
assert !Post.find(1).readonly?
assert Post.find(1, :readonly => true).readonly?
assert !Post.find(1, :readonly => false).readonly?
end
Post.with_scope(:find => { :joins => ' ' }) do
assert !Post.find(1).readonly?
assert Post.find(1, :readonly => true).readonly?
assert !Post.find(1, :readonly => false).readonly?
end
# Oracle barfs on this because the join includes unqualified and
# conflicting column names
unless current_adapter?(:OracleAdapter)
Post.with_scope(:find => { :joins => ', developers' }) do
assert Post.find(1).readonly?
assert Post.find(1, :readonly => true).readonly?
assert !Post.find(1, :readonly => false).readonly?
end
end
Post.with_scope(:find => { :readonly => true }) do
assert Post.find(1).readonly?
assert Post.find(1, :readonly => true).readonly?
assert !Post.find(1, :readonly => false).readonly?
end
end
def test_association_collection_method_missing_scoping_not_readonly
assert !Developer.find(1).projects.foo.readonly?
assert !Post.find(1).comments.foo.readonly?
end
end

View file

@ -1,176 +0,0 @@
require "cases/helper"
require 'models/topic'
require 'models/customer'
require 'models/company'
require 'models/company_in_module'
require 'models/subscriber'
class ReflectionTest < ActiveRecord::TestCase
fixtures :topics, :customers, :companies, :subscribers
def setup
@first = Topic.find(1)
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_read_attribute_names
assert_equal(
%w( id title author_name author_email_address bonus_time written_on last_read content approved replies_count parent_id type ).sort,
@first.attribute_names
)
end
def test_columns
assert_equal 12, Topic.columns.length
end
def test_columns_are_returned_in_the_order_they_were_declared
column_names = Topic.columns.map { |column| column.name }
assert_equal %w(id title author_name author_email_address written_on bonus_time last_read content approved replies_count parent_id type), column_names
end
def test_content_columns
content_columns = Topic.content_columns
content_column_names = content_columns.map {|column| column.name}
assert_equal 8, content_columns.length
assert_equal %w(title author_name author_email_address written_on bonus_time last_read content approved).sort, content_column_names.sort
end
def test_column_string_type_and_limit
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
end
def test_integer_columns
assert_equal :integer, @first.column_for_attribute("id").type
end
def test_reflection_klass_for_nested_class_name
reflection = ActiveRecord::Reflection::MacroReflection.new(nil, nil, { :class_name => 'MyApplication::Business::Company' }, nil)
assert_nothing_raised do
assert_equal MyApplication::Business::Company, reflection.klass
end
end
def test_aggregation_reflection
reflection_for_address = ActiveRecord::Reflection::AggregateReflection.new(
:composed_of, :address, { :mapping => [ %w(address_street street), %w(address_city city), %w(address_country country) ] }, Customer
)
reflection_for_balance = ActiveRecord::Reflection::AggregateReflection.new(
:composed_of, :balance, { :class_name => "Money", :mapping => %w(balance amount) }, Customer
)
reflection_for_gps_location = ActiveRecord::Reflection::AggregateReflection.new(
:composed_of, :gps_location, { }, Customer
)
assert Customer.reflect_on_all_aggregations.include?(reflection_for_gps_location)
assert Customer.reflect_on_all_aggregations.include?(reflection_for_balance)
assert Customer.reflect_on_all_aggregations.include?(reflection_for_address)
assert_equal reflection_for_address, Customer.reflect_on_aggregation(:address)
assert_equal Address, Customer.reflect_on_aggregation(:address).klass
assert_equal Money, Customer.reflect_on_aggregation(:balance).klass
end
def test_has_many_reflection
reflection_for_clients = ActiveRecord::Reflection::AssociationReflection.new(:has_many, :clients, { :order => "id", :dependent => :destroy }, Firm)
assert_equal reflection_for_clients, Firm.reflect_on_association(:clients)
assert_equal Client, Firm.reflect_on_association(:clients).klass
assert_equal 'companies', Firm.reflect_on_association(:clients).table_name
assert_equal Client, Firm.reflect_on_association(:clients_of_firm).klass
assert_equal 'companies', Firm.reflect_on_association(:clients_of_firm).table_name
end
def test_has_one_reflection
reflection_for_account = ActiveRecord::Reflection::AssociationReflection.new(:has_one, :account, { :foreign_key => "firm_id", :dependent => :destroy }, Firm)
assert_equal reflection_for_account, Firm.reflect_on_association(:account)
assert_equal Account, Firm.reflect_on_association(:account).klass
assert_equal 'accounts', Firm.reflect_on_association(:account).table_name
end
def test_belongs_to_inferred_foreign_key_from_assoc_name
Company.belongs_to :foo
assert_equal "foo_id", Company.reflect_on_association(:foo).primary_key_name
Company.belongs_to :bar, :class_name => "Xyzzy"
assert_equal "bar_id", Company.reflect_on_association(:bar).primary_key_name
Company.belongs_to :baz, :class_name => "Xyzzy", :foreign_key => "xyzzy_id"
assert_equal "xyzzy_id", Company.reflect_on_association(:baz).primary_key_name
end
def test_association_reflection_in_modules
assert_reflection MyApplication::Business::Firm,
:clients_of_firm,
:klass => MyApplication::Business::Client,
:class_name => 'Client',
:table_name => 'companies'
assert_reflection MyApplication::Billing::Account,
:firm,
:klass => MyApplication::Business::Firm,
:class_name => 'MyApplication::Business::Firm',
:table_name => 'companies'
assert_reflection MyApplication::Billing::Account,
:qualified_billing_firm,
:klass => MyApplication::Billing::Firm,
:class_name => 'MyApplication::Billing::Firm',
:table_name => 'companies'
assert_reflection MyApplication::Billing::Account,
:unqualified_billing_firm,
:klass => MyApplication::Billing::Firm,
:class_name => 'Firm',
:table_name => 'companies'
assert_reflection MyApplication::Billing::Account,
:nested_qualified_billing_firm,
:klass => MyApplication::Billing::Nested::Firm,
:class_name => 'MyApplication::Billing::Nested::Firm',
:table_name => 'companies'
assert_reflection MyApplication::Billing::Account,
:nested_unqualified_billing_firm,
:klass => MyApplication::Billing::Nested::Firm,
:class_name => 'Nested::Firm',
:table_name => 'companies'
end
def test_reflection_of_all_associations
# FIXME these assertions bust a lot
assert_equal 20, Firm.reflect_on_all_associations.size
assert_equal 16, Firm.reflect_on_all_associations(:has_many).size
assert_equal 4, Firm.reflect_on_all_associations(:has_one).size
assert_equal 0, Firm.reflect_on_all_associations(:belongs_to).size
end
private
def assert_reflection(klass, association, options)
assert reflection = klass.reflect_on_association(association)
options.each do |method, value|
assert_equal(value, reflection.send(method))
end
end
end

View file

@ -1,176 +0,0 @@
require "cases/helper"
class Group < ActiveRecord::Base
Group.table_name = 'group'
belongs_to :select, :class_name => 'Select'
has_one :values
end
class Select < ActiveRecord::Base
Select.table_name = 'select'
has_many :groups
end
class Values < ActiveRecord::Base
Values.table_name = 'values'
end
class Distinct < ActiveRecord::Base
Distinct.table_name = 'distinct'
has_and_belongs_to_many :selects
has_many :values, :through => :groups
end
# a suite of tests to ensure the ConnectionAdapters#MysqlAdapter can handle tables with
# reserved word names (ie: group, order, values, etc...)
class MysqlReservedWordTest < ActiveRecord::TestCase
def setup
@connection = ActiveRecord::Base.connection
# we call execute directly here (and do similar below) because ActiveRecord::Base#create_table()
# will fail with these table names if these test cases fail
create_tables_directly 'group'=>'id int auto_increment primary key, `order` varchar(255), select_id int',
'select'=>'id int auto_increment primary key',
'values'=>'id int auto_increment primary key, group_id int',
'distinct'=>'id int auto_increment primary key',
'distincts_selects'=>'distinct_id int, select_id int'
end
def teardown
drop_tables_directly ['group', 'select', 'values', 'distinct', 'distincts_selects', 'order']
end
# create tables with reserved-word names and columns
def test_create_tables
assert_nothing_raised {
@connection.create_table :order do |t|
t.column :group, :string
end
}
end
# rename tables with reserved-word names
def test_rename_tables
assert_nothing_raised { @connection.rename_table(:group, :order) }
end
# alter column with a reserved-word name in a table with a reserved-word name
def test_change_columns
assert_nothing_raised { @connection.change_column_default(:group, :order, 'whatever') }
#the quoting here will reveal any double quoting issues in change_column's interaction with the column method in the adapter
assert_nothing_raised { @connection.change_column('group', 'order', :Int, :default => 0) }
assert_nothing_raised { @connection.rename_column(:group, :order, :values) }
end
# dump structure of table with reserved word name
def test_structure_dump
assert_nothing_raised { @connection.structure_dump }
end
# introspect table with reserved word name
def test_introspect
assert_nothing_raised { @connection.columns(:group) }
assert_nothing_raised { @connection.indexes(:group) }
end
#fixtures
self.use_instantiated_fixtures = true
self.use_transactional_fixtures = false
#fixtures :group
def test_fixtures
f = create_test_fixtures :select, :distinct, :group, :values, :distincts_selects
assert_nothing_raised {
f.each do |x|
x.delete_existing_fixtures
end
}
assert_nothing_raised {
f.each do |x|
x.insert_fixtures
end
}
end
#activerecord model class with reserved-word table name
def test_activerecord_model
create_test_fixtures :select, :distinct, :group, :values, :distincts_selects
x = nil
assert_nothing_raised { x = Group.new }
x.order = 'x'
assert_nothing_raised { x.save }
x.order = 'y'
assert_nothing_raised { x.save }
assert_nothing_raised { y = Group.find_by_order('y') }
assert_nothing_raised { y = Group.find(1) }
x = Group.find(1)
end
# has_one association with reserved-word table name
def test_has_one_associations
create_test_fixtures :select, :distinct, :group, :values, :distincts_selects
v = nil
assert_nothing_raised { v = Group.find(1).values }
assert_equal v.id, 2
end
# belongs_to association with reserved-word table name
def test_belongs_to_associations
create_test_fixtures :select, :distinct, :group, :values, :distincts_selects
gs = nil
assert_nothing_raised { gs = Select.find(2).groups }
assert_equal gs.length, 2
assert(gs.collect{|x| x.id}.sort == [2, 3])
end
# has_and_belongs_to_many with reserved-word table name
def test_has_and_belongs_to_many
create_test_fixtures :select, :distinct, :group, :values, :distincts_selects
s = nil
assert_nothing_raised { s = Distinct.find(1).selects }
assert_equal s.length, 2
assert(s.collect{|x|x.id}.sort == [1, 2])
end
# activerecord model introspection with reserved-word table and column names
def test_activerecord_introspection
assert_nothing_raised { Group.table_exists? }
assert_nothing_raised { Group.columns }
end
# Calculations
def test_calculations_work_with_reserved_words
assert_nothing_raised { Group.count }
end
def test_associations_work_with_reserved_words
assert_nothing_raised { Select.find(:all, :include => [:groups]) }
end
#the following functions were added to DRY test cases
private
# custom fixture loader, uses Fixtures#create_fixtures and appends base_path to the current file's path
def create_test_fixtures(*fixture_names)
Fixtures.create_fixtures(FIXTURES_ROOT + "/reserved_words", fixture_names)
end
# custom drop table, uses execute on connection to drop a table if it exists. note: escapes table_name
def drop_tables_directly(table_names, connection = @connection)
table_names.each do |name|
connection.execute("DROP TABLE IF EXISTS `#{name}`")
end
end
# custom create table, uses execute on connection to create a table, note: escapes table_name, does NOT escape columns
def create_tables_directly (tables, connection = @connection)
tables.each do |table_name, column_properties|
connection.execute("CREATE TABLE `#{table_name}` ( #{column_properties} )")
end
end
end

View file

@ -1,75 +0,0 @@
require "cases/helper"
class SchemaThing < ActiveRecord::Base
end
class SchemaAuthorizationTest < ActiveRecord::TestCase
self.use_transactional_fixtures = false
TABLE_NAME = 'schema_things'
COLUMNS = [
'id serial primary key',
'name character varying(50)'
]
USERS = ['rails_pg_schema_user1', 'rails_pg_schema_user2']
def setup
@connection = ActiveRecord::Base.connection
@connection.execute "SET search_path TO '$user',public"
set_session_auth
USERS.each do |u|
@connection.execute "CREATE USER #{u}"
@connection.execute "CREATE SCHEMA AUTHORIZATION #{u}"
set_session_auth u
@connection.execute "CREATE TABLE #{TABLE_NAME} (#{COLUMNS.join(',')})"
@connection.execute "INSERT INTO #{TABLE_NAME} (name) VALUES ('#{u}')"
set_session_auth
end
end
def teardown
set_session_auth
@connection.execute "RESET search_path"
USERS.each do |u|
@connection.execute "DROP SCHEMA #{u} CASCADE"
@connection.execute "DROP USER #{u}"
end
end
def test_schema_invisible
assert_raise(ActiveRecord::StatementInvalid) do
set_session_auth
@connection.execute "SELECT * FROM #{TABLE_NAME}"
end
end
def test_schema_uniqueness
assert_nothing_raised do
set_session_auth
USERS.each do |u|
set_session_auth u
assert_equal u, @connection.select_value("SELECT name FROM #{TABLE_NAME} WHERE id = 1")
set_session_auth
end
end
end
def test_sequence_schema_caching
assert_nothing_raised do
USERS.each do |u|
set_session_auth u
st = SchemaThing.new :name => 'TEST1'
st.save!
st = SchemaThing.new :id => 5, :name => 'TEST2'
st.save!
set_session_auth
end
end
end
private
def set_session_auth auth = nil
@connection.execute "SET SESSION AUTHORIZATION #{auth || 'default'}"
end
end

View file

@ -1,138 +0,0 @@
require "cases/helper"
require 'active_record/schema_dumper'
require 'stringio'
class SchemaDumperTest < ActiveRecord::TestCase
def standard_dump
stream = StringIO.new
ActiveRecord::SchemaDumper.ignore_tables = []
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
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_migrations"}, output
end
def test_schema_dump_excludes_sqlite_sequence
output = standard_dump
assert_no_match %r{create_table "sqlite_sequence"}, 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 column_definition_lines(output = standard_dump)
output.scan(/^( *)create_table.*?\n(.*?)^\1end/m).map{ |m| m.last.split(/\n/) }
end
def test_types_line_up
column_definition_lines.each do |column_set|
next if column_set.empty?
lengths = column_set.map do |column|
if match = column.match(/t\.(?:integer|decimal|float|datetime|timestamp|time|date|text|binary|string|boolean)\s+"/)
match[0].length
end
end
assert_equal 1, lengths.uniq.length
end
end
def test_arguments_line_up
column_definition_lines.each do |column_set|
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 = [/^[^r]/]
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
output = stream.string
assert_match %r{:null => false}, output
end
def test_schema_dump_with_string_ignored_table
stream = StringIO.new
ActiveRecord::SchemaDumper.ignore_tables = ['accounts']
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
output = stream.string
assert_no_match %r{create_table "accounts"}, output
assert_match %r{create_table "authors"}, output
assert_no_match %r{create_table "schema_migrations"}, output
end
def test_schema_dump_with_regexp_ignored_table
stream = StringIO.new
ActiveRecord::SchemaDumper.ignore_tables = [/^account/]
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
output = stream.string
assert_no_match %r{create_table "accounts"}, output
assert_match %r{create_table "authors"}, output
assert_no_match %r{create_table "schema_migrations"}, output
end
def test_schema_dump_illegal_ignored_table_value
stream = StringIO.new
ActiveRecord::SchemaDumper.ignore_tables = [5]
assert_raise(StandardError) do
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
end
end
if current_adapter?(:MysqlAdapter)
def test_schema_dump_should_not_add_default_value_for_mysql_text_field
output = standard_dump
assert_match %r{t.text\s+"body",\s+:null => false$}, output
end
def test_mysql_schema_dump_should_honor_nonstandard_primary_keys
output = standard_dump
match = output.match(%r{create_table "movies"(.*)do})
assert_not_nil(match, "nonstandardpk table not found")
assert_match %r(:primary_key => "movieid"), match[1], "non-standard primary key not preserved"
end
def test_schema_dump_includes_length_for_mysql_blob_and_text_fields
output = standard_dump
assert_match %r{t.binary\s+"tiny_blob",\s+:limit => 255$}, output
assert_match %r{t.binary\s+"normal_blob"$}, output
assert_match %r{t.binary\s+"medium_blob",\s+:limit => 16777215$}, output
assert_match %r{t.binary\s+"long_blob",\s+:limit => 2147483647$}, output
assert_match %r{t.text\s+"tiny_text",\s+:limit => 255$}, output
assert_match %r{t.text\s+"normal_text"$}, output
assert_match %r{t.text\s+"medium_text",\s+:limit => 16777215$}, output
assert_match %r{t.text\s+"long_text",\s+:limit => 2147483647$}, output
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

View file

@ -1,102 +0,0 @@
require "cases/helper"
class SchemaTest < ActiveRecord::TestCase
self.use_transactional_fixtures = false
SCHEMA_NAME = 'test_schema'
SCHEMA2_NAME = 'test_schema2'
TABLE_NAME = 'things'
INDEX_A_NAME = 'a_index_things_on_name'
INDEX_B_NAME = 'b_index_things_on_different_columns_in_each_schema'
INDEX_A_COLUMN = 'name'
INDEX_B_COLUMN_S1 = 'email'
INDEX_B_COLUMN_S2 = 'moment'
COLUMNS = [
'id integer',
'name character varying(50)',
'email character varying(50)',
'moment timestamp without time zone default now()'
]
def setup
@connection = ActiveRecord::Base.connection
@connection.execute "CREATE SCHEMA #{SCHEMA_NAME} CREATE TABLE #{TABLE_NAME} (#{COLUMNS.join(',')})"
@connection.execute "CREATE SCHEMA #{SCHEMA2_NAME} CREATE TABLE #{TABLE_NAME} (#{COLUMNS.join(',')})"
@connection.execute "CREATE INDEX #{INDEX_A_NAME} ON #{SCHEMA_NAME}.#{TABLE_NAME} USING btree (#{INDEX_A_COLUMN});"
@connection.execute "CREATE INDEX #{INDEX_A_NAME} ON #{SCHEMA2_NAME}.#{TABLE_NAME} USING btree (#{INDEX_A_COLUMN});"
@connection.execute "CREATE INDEX #{INDEX_B_NAME} ON #{SCHEMA_NAME}.#{TABLE_NAME} USING btree (#{INDEX_B_COLUMN_S1});"
@connection.execute "CREATE INDEX #{INDEX_B_NAME} ON #{SCHEMA2_NAME}.#{TABLE_NAME} USING btree (#{INDEX_B_COLUMN_S2});"
end
def teardown
@connection.execute "DROP SCHEMA #{SCHEMA2_NAME} CASCADE"
@connection.execute "DROP SCHEMA #{SCHEMA_NAME} CASCADE"
end
def test_with_schema_prefixed_table_name
assert_nothing_raised do
assert_equal COLUMNS, columns("#{SCHEMA_NAME}.#{TABLE_NAME}")
end
end
def test_with_schema_search_path
assert_nothing_raised do
with_schema_search_path(SCHEMA_NAME) do
assert_equal COLUMNS, columns(TABLE_NAME)
end
end
end
def test_raise_on_unquoted_schema_name
assert_raise(ActiveRecord::StatementInvalid) do
with_schema_search_path '$user,public'
end
end
def test_without_schema_search_path
assert_raise(ActiveRecord::StatementInvalid) { columns(TABLE_NAME) }
end
def test_ignore_nil_schema_search_path
assert_nothing_raised { with_schema_search_path nil }
end
def test_dump_indexes_for_schema_one
do_dump_index_tests_for_schema(SCHEMA_NAME, INDEX_A_COLUMN, INDEX_B_COLUMN_S1)
end
def test_dump_indexes_for_schema_two
do_dump_index_tests_for_schema(SCHEMA2_NAME, INDEX_A_COLUMN, INDEX_B_COLUMN_S2)
end
private
def columns(table_name)
@connection.send(:column_definitions, table_name).map do |name, type, default|
"#{name} #{type}" + (default ? " default #{default}" : '')
end
end
def with_schema_search_path(schema_search_path)
@connection.schema_search_path = schema_search_path
yield if block_given?
ensure
@connection.schema_search_path = "'$user', public"
end
def do_dump_index_tests_for_schema(this_schema_name, first_index_column_name, second_index_column_name)
with_schema_search_path(this_schema_name) do
indexes = @connection.indexes(TABLE_NAME).sort_by {|i| i.name}
assert_equal 2,indexes.size
do_dump_index_assertions_for_one_index(indexes[0], INDEX_A_NAME, first_index_column_name)
do_dump_index_assertions_for_one_index(indexes[1], INDEX_B_NAME, second_index_column_name)
end
end
def do_dump_index_assertions_for_one_index(this_index, this_index_name, this_index_column)
assert_equal TABLE_NAME, this_index.table
assert_equal 1, this_index.columns.size
assert_equal this_index_column, this_index.columns[0]
assert_equal this_index_name, this_index.name
end
end

View file

@ -1,47 +0,0 @@
require "cases/helper"
require 'models/contact'
class SerializationTest < ActiveRecord::TestCase
FORMATS = [ :xml, :json ]
def setup
@contact_attributes = {
:name => 'aaron stack',
:age => 25,
:avatar => 'binarydata',
:created_at => Time.utc(2006, 8, 1),
:awesome => false,
:preferences => { :gem => '<strong>ruby</strong>' }
}
@contact = Contact.new(@contact_attributes)
end
def test_serialize_should_be_reversible
for format in FORMATS
@serialized = Contact.new.send("to_#{format}")
contact = Contact.new.send("from_#{format}", @serialized)
assert_equal @contact_attributes.keys.collect(&:to_s).sort, contact.attributes.keys.collect(&:to_s).sort, "For #{format}"
end
end
def test_serialize_should_allow_attribute_only_filtering
for format in FORMATS
@serialized = Contact.new(@contact_attributes).send("to_#{format}", :only => [ :age, :name ])
contact = Contact.new.send("from_#{format}", @serialized)
assert_equal @contact_attributes[:name], contact.name, "For #{format}"
assert_nil contact.avatar, "For #{format}"
end
end
def test_serialize_should_allow_attribute_except_filtering
for format in FORMATS
@serialized = Contact.new(@contact_attributes).send("to_#{format}", :except => [ :age, :name ])
contact = Contact.new.send("from_#{format}", @serialized)
assert_nil contact.name, "For #{format}"
assert_nil contact.age, "For #{format}"
assert_equal @contact_attributes[:awesome], contact.awesome, "For #{format}"
end
end
end

View file

@ -1,17 +0,0 @@
require "cases/helper"
require 'models/topic'
require 'models/subject'
# confirm that synonyms work just like tables; in this case
# the "subjects" table in Oracle (defined in oci.sql) is just
# a synonym to the "topics" table
class TestOracleSynonym < ActiveRecord::TestCase
def test_oracle_synonym
topic = Topic.new
subject = Subject.new
assert_equal(topic.attributes, subject.attributes)
end
end

View file

@ -1,23 +0,0 @@
require "cases/helper"
require 'active_record/schema'
if ActiveRecord::Base.connection.supports_migrations?
class Order < ActiveRecord::Base
self.table_name = '[order]'
end
class TableNameTest < ActiveRecord::TestCase
self.use_transactional_fixtures = false
# Ensures Model.columns works when using SQLServer escape characters.
# Enables legacy schemas using SQL reserved words as table names.
# Should work with table names with spaces as well ('table name').
def test_escaped_table_name
assert_nothing_raised do
ActiveRecord::Base.connection.select_all 'SELECT * FROM [order]'
end
assert_equal '[order]', Order.table_name
assert_equal 5, Order.columns.length
end
end
end

View file

@ -1,48 +0,0 @@
require "cases/helper"
require 'models/topic'
require 'models/reply'
unless %w(FrontBase).include? ActiveRecord::Base.connection.adapter_name
class ThreadedConnectionsTest < ActiveRecord::TestCase
self.use_transactional_fixtures = false
fixtures :topics
def setup
@connection = ActiveRecord::Base.remove_connection
@connections = []
@allow_concurrency = ActiveRecord::Base.allow_concurrency
end
def teardown
# clear the connection cache
ActiveRecord::Base.send(:clear_all_cached_connections!)
# set allow_concurrency to saved value
ActiveRecord::Base.allow_concurrency = @allow_concurrency
# reestablish old connection
ActiveRecord::Base.establish_connection(@connection)
end
def gather_connections(use_threaded_connections)
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
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
end

View file

@ -1,307 +0,0 @@
require "cases/helper"
require 'models/topic'
require 'models/reply'
require 'models/developer'
class TransactionTest < ActiveRecord::TestCase
self.use_transactional_fixtures = false
fixtures :topics, :developers
def setup
@first, @second = Topic.find(1, 2).sort_by { |t| t.id }
end
def test_successful
Topic.transaction do
@first.approved = true
@second.approved = false
@first.save
@second.save
end
assert Topic.find(1).approved?, "First should have been approved"
assert !Topic.find(2).approved?, "Second should have been unapproved"
end
def transaction_with_return
Topic.transaction do
@first.approved = true
@second.approved = false
@first.save
@second.save
return
end
end
def test_successful_with_return
class << Topic.connection
alias :real_commit_db_transaction :commit_db_transaction
def commit_db_transaction
$committed = true
real_commit_db_transaction
end
end
$committed = false
transaction_with_return
assert $committed
assert Topic.find(1).approved?, "First should have been approved"
assert !Topic.find(2).approved?, "Second should have been unapproved"
ensure
class << Topic.connection
alias :commit_db_transaction :real_commit_db_transaction rescue nil
end
end
def test_successful_with_instance_method
@first.transaction do
@first.approved = true
@second.approved = false
@first.save
@second.save
end
assert Topic.find(1).approved?, "First should have been approved"
assert !Topic.find(2).approved?, "Second should have been unapproved"
end
def test_failing_on_exception
begin
Topic.transaction do
@first.approved = true
@second.approved = false
@first.save
@second.save
raise "Bad things!"
end
rescue
# caught it
end
assert @first.approved?, "First should still be changed in the objects"
assert !@second.approved?, "Second should still be changed in the objects"
assert !Topic.find(1).approved?, "First shouldn't have been approved"
assert Topic.find(2).approved?, "Second should still be approved"
end
def test_callback_rollback_in_save
add_exception_raising_after_save_callback_to_topic
begin
@first.approved = true
@first.save
flunk
rescue => e
assert_equal "Make the transaction rollback", e.message
assert !Topic.find(1).approved?
ensure
remove_exception_raising_after_save_callback_to_topic
end
end
def test_callback_rollback_in_create
new_topic = Topic.new(
:title => "A new topic",
:author_name => "Ben",
:author_email_address => "ben@example.com",
: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)
new_record_snapshot = new_topic.new_record?
id_present = new_topic.has_attribute?(Topic.primary_key)
id_snapshot = new_topic.id
# Make sure the second save gets the after_create callback called.
2.times do
begin
add_exception_raising_after_create_callback_to_topic
new_topic.approved = true
new_topic.save
flunk
rescue => e
assert_equal "Make the transaction rollback", e.message
assert_equal new_record_snapshot, new_topic.new_record?, "The topic should have its old new_record value"
assert_equal id_snapshot, new_topic.id, "The topic should have its old id"
assert_equal id_present, new_topic.has_attribute?(Topic.primary_key)
ensure
remove_exception_raising_after_create_callback_to_topic
end
end
end
def test_nested_explicit_transactions
Topic.transaction do
Topic.transaction do
@first.approved = true
@second.approved = false
@first.save
@second.save
end
end
assert Topic.find(1).approved?, "First should have been approved"
assert !Topic.find(2).approved?, "Second should have been unapproved"
end
def test_manually_rolling_back_a_transaction
Topic.transaction do
@first.approved = true
@second.approved = false
@first.save
@second.save
raise ActiveRecord::Rollback
end
assert @first.approved?, "First should still be changed in the objects"
assert !@second.approved?, "Second should still be changed in the objects"
assert !Topic.find(1).approved?, "First shouldn't have been approved"
assert Topic.find(2).approved?, "Second should still be approved"
end
uses_mocha 'mocking connection.commit_db_transaction' do
def test_rollback_when_commit_raises
Topic.connection.expects(:begin_db_transaction)
Topic.connection.expects(:commit_db_transaction).raises('OH NOES')
Topic.connection.expects(:rollback_db_transaction)
assert_raise RuntimeError do
Topic.transaction do
# do nothing
end
end
end
end
def test_sqlite_add_column_in_transaction_raises_statement_invalid
return true unless current_adapter?(:SQLite3Adapter, :SQLiteAdapter)
# Test first if column creation/deletion works correctly when no
# transaction is in place.
#
# We go back to the connection for the column queries because
# Topic.columns is cached and won't report changes to the DB
assert_nothing_raised do
Topic.reset_column_information
Topic.connection.add_column('topics', 'stuff', :string)
assert Topic.column_names.include?('stuff')
Topic.reset_column_information
Topic.connection.remove_column('topics', 'stuff')
assert !Topic.column_names.include?('stuff')
end
# Test now inside a transaction: add_column should raise a StatementInvalid
Topic.transaction do
assert_raises(ActiveRecord::StatementInvalid) { Topic.connection.add_column('topics', 'stuff', :string) }
raise ActiveRecord::Rollback
end
end
private
def add_exception_raising_after_save_callback_to_topic
Topic.class_eval { def after_save() raise "Make the transaction rollback" end }
end
def remove_exception_raising_after_save_callback_to_topic
Topic.class_eval { remove_method :after_save }
end
def add_exception_raising_after_create_callback_to_topic
Topic.class_eval { def after_create() raise "Make the transaction rollback" end }
end
def remove_exception_raising_after_create_callback_to_topic
Topic.class_eval { remove_method :after_create }
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

View file

@ -1,32 +0,0 @@
require "cases/helper"
class TestRecord < ActiveRecord::Base
end
class TestUnconnectedAdapter < ActiveRecord::TestCase
self.use_transactional_fixtures = false
def setup
@underlying = ActiveRecord::Base.connection
@specification = ActiveRecord::Base.remove_connection
end
def teardown
@underlying = nil
ActiveRecord::Base.establish_connection(@specification)
end
def test_connection_no_longer_established
assert_raise(ActiveRecord::ConnectionNotEstablished) do
TestRecord.find(1)
end
assert_raise(ActiveRecord::ConnectionNotEstablished) do
TestRecord.new.save
end
end
def test_underlying_adapter_no_longer_active
assert !@underlying.active?, "Removed adapter should no longer be active"
end
end

File diff suppressed because it is too large Load diff

View file

@ -1,202 +0,0 @@
require "cases/helper"
require 'models/contact'
require 'models/post'
require 'models/author'
require 'models/tagging'
require 'models/comment'
class XmlSerializationTest < ActiveRecord::TestCase
def test_should_serialize_default_root
@xml = Contact.new.to_xml
assert_match %r{^<contact>}, @xml
assert_match %r{</contact>$}, @xml
end
def test_should_serialize_default_root_with_namespace
@xml = Contact.new.to_xml :namespace=>"http://xml.rubyonrails.org/contact"
assert_match %r{^<contact xmlns="http://xml.rubyonrails.org/contact">}, @xml
assert_match %r{</contact>$}, @xml
end
def test_should_serialize_custom_root
@xml = Contact.new.to_xml :root => 'xml_contact'
assert_match %r{^<xml-contact>}, @xml
assert_match %r{</xml-contact>$}, @xml
end
def test_should_allow_undasherized_tags
@xml = Contact.new.to_xml :root => 'xml_contact', :dasherize => false
assert_match %r{^<xml_contact>}, @xml
assert_match %r{</xml_contact>$}, @xml
assert_match %r{<created_at}, @xml
end
def test_should_include_yielded_additions
@xml = Contact.new.to_xml do |xml|
xml.creator "David"
end
assert_match %r{<creator>David</creator>}, @xml
end
end
class DefaultXmlSerializationTest < ActiveRecord::TestCase
def setup
@xml = Contact.new(:name => 'aaron stack', :age => 25, :avatar => 'binarydata', :created_at => Time.utc(2006, 8, 1), :awesome => false, :preferences => { :gem => 'ruby' }).to_xml
end
def test_should_serialize_string
assert_match %r{<name>aaron stack</name>}, @xml
end
def test_should_serialize_integer
assert_match %r{<age type="integer">25</age>}, @xml
end
def test_should_serialize_binary
assert_match %r{YmluYXJ5ZGF0YQ==\n</avatar>}, @xml
assert_match %r{<avatar(.*)(type="binary")}, @xml
assert_match %r{<avatar(.*)(encoding="base64")}, @xml
end
def test_should_serialize_datetime
assert_match %r{<created-at type=\"datetime\">2006-08-01T00:00:00Z</created-at>}, @xml
end
def test_should_serialize_boolean
assert_match %r{<awesome type=\"boolean\">false</awesome>}, @xml
end
def test_should_serialize_yaml
assert_match %r{<preferences type=\"yaml\">--- \n:gem: ruby\n</preferences>}, @xml
end
end
class NilXmlSerializationTest < ActiveRecord::TestCase
def setup
@xml = Contact.new.to_xml(:root => 'xml_contact')
end
def test_should_serialize_string
assert_match %r{<name nil="true"></name>}, @xml
end
def test_should_serialize_integer
assert %r{<age (.*)></age>}.match(@xml)
attributes = $1
assert_match %r{nil="true"}, attributes
assert_match %r{type="integer"}, attributes
end
def test_should_serialize_binary
assert %r{<avatar (.*)></avatar>}.match(@xml)
attributes = $1
assert_match %r{type="binary"}, attributes
assert_match %r{encoding="base64"}, attributes
assert_match %r{nil="true"}, attributes
end
def test_should_serialize_datetime
assert %r{<created-at (.*)></created-at>}.match(@xml)
attributes = $1
assert_match %r{nil="true"}, attributes
assert_match %r{type="datetime"}, attributes
end
def test_should_serialize_boolean
assert %r{<awesome (.*)></awesome>}.match(@xml)
attributes = $1
assert_match %r{type="boolean"}, attributes
assert_match %r{nil="true"}, attributes
end
def test_should_serialize_yaml
assert %r{<preferences(.*)></preferences>}.match(@xml)
attributes = $1
assert_match %r{type="yaml"}, attributes
assert_match %r{nil="true"}, attributes
end
end
class DatabaseConnectedXmlSerializationTest < ActiveRecord::TestCase
fixtures :authors, :posts
# to_xml used to mess with the hash the user provided which
# caused the builder to be reused. This meant the document kept
# getting appended to.
def test_passing_hash_shouldnt_reuse_builder
options = {:include=>:posts}
david = authors(:david)
first_xml_size = david.to_xml(options).size
second_xml_size = david.to_xml(options).size
assert_equal first_xml_size, second_xml_size
end
def test_include_uses_association_name
xml = authors(:david).to_xml :include=>:hello_posts, :indent => 0
assert_match %r{<hello-posts type="array">}, xml
assert_match %r{<hello-post type="Post">}, xml
assert_match %r{<hello-post type="StiPost">}, xml
end
def test_methods_are_called_on_object
xml = authors(:david).to_xml :methods => :label, :indent => 0
assert_match %r{<label>.*</label>}, xml
end
def test_should_not_call_methods_on_associations_that_dont_respond
xml = authors(:david).to_xml :include=>:hello_posts, :methods => :label, :indent => 2
assert !authors(:david).hello_posts.first.respond_to?(:label)
assert_match %r{^ <label>.*</label>}, xml
assert_no_match %r{^ <label>}, xml
end
def test_procs_are_called_on_object
proc = Proc.new { |options| options[:builder].tag!('nationality', 'Danish') }
xml = authors(:david).to_xml(:procs => [ proc ])
assert_match %r{<nationality>Danish</nationality>}, xml
end
def test_top_level_procs_arent_applied_to_associations
author_proc = Proc.new { |options| options[:builder].tag!('nationality', 'Danish') }
xml = authors(:david).to_xml(:procs => [ author_proc ], :include => :posts, :indent => 2)
assert_match %r{^ <nationality>Danish</nationality>}, xml
assert_no_match %r{^ {6}<nationality>Danish</nationality>}, xml
end
def test_procs_on_included_associations_are_called
posts_proc = Proc.new { |options| options[:builder].tag!('copyright', 'DHH') }
xml = authors(:david).to_xml(
:indent => 2,
:include => {
:posts => { :procs => [ posts_proc ] }
}
)
assert_no_match %r{^ <copyright>DHH</copyright>}, xml
assert_match %r{^ {6}<copyright>DHH</copyright>}, xml
end
def test_should_include_empty_has_many_as_empty_array
authors(:david).posts.delete_all
xml = authors(:david).to_xml :include=>:posts, :indent => 2
assert_equal [], Hash.from_xml(xml)['author']['posts']
assert_match %r{^ <posts type="array"/>}, xml
end
def test_should_has_many_array_elements_should_include_type_when_different_from_guessed_value
xml = authors(:david).to_xml :include=>:posts_with_comments, :indent => 2
assert Hash.from_xml(xml)
assert_match %r{^ <posts-with-comments type="array">}, xml
assert_match %r{^ <posts-with-comment type="Post">}, xml
assert_match %r{^ <posts-with-comment type="StiPost">}, xml
types = Hash.from_xml(xml)['author']['posts_with_comments'].collect {|t| t['type'] }
assert types.include?('SpecialPost')
assert types.include?('Post')
assert types.include?('StiPost')
end
end

View file

@ -1,5 +0,0 @@
TEST_ROOT = File.expand_path(File.dirname(__FILE__))
ASSETS_ROOT = TEST_ROOT + "/assets"
FIXTURES_ROOT = TEST_ROOT + "/fixtures"
MIGRATIONS_ROOT = TEST_ROOT + "/migrations"
SCHEMA_ROOT = TEST_ROOT + "/schema"

View file

@ -1,25 +0,0 @@
print "Using native DB2\n"
require_dependency 'models/course'
require 'logger'
ActiveRecord::Base.logger = Logger.new("debug.log")
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 'arunit'
Course.establish_connection 'arunit2'

View file

@ -1,26 +0,0 @@
print "Using native Firebird\n"
require_dependency 'models/course'
require 'logger'
ActiveRecord::Base.logger = Logger.new("debug.log")
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 'arunit'
Course.establish_connection 'arunit2'

View file

@ -1,27 +0,0 @@
puts 'Using native Frontbase'
require_dependency 'models/course'
require 'logger'
ActiveRecord::Base.logger = Logger.new("debug.log")
ActiveRecord::Base.configurations = {
'arunit' => {
:adapter => 'frontbase',
:host => 'localhost',
:username => 'rails',
:password => '',
:database => 'activerecord_unittest',
:session_name => "unittest-#{$$}"
},
'arunit2' => {
:adapter => 'frontbase',
:host => 'localhost',
:username => 'rails',
:password => '',
:database => 'activerecord_unittest2',
:session_name => "unittest-#{$$}"
}
}
ActiveRecord::Base.establish_connection 'arunit'
Course.establish_connection 'arunit2'

View file

@ -1,27 +0,0 @@
print "Using native MySQL\n"
require_dependency 'models/course'
require 'logger'
RAILS_DEFAULT_LOGGER = Logger.new('debug.log')
RAILS_DEFAULT_LOGGER.level = Logger::DEBUG
ActiveRecord::Base.logger = RAILS_DEFAULT_LOGGER
# GRANT ALL PRIVILEGES ON activerecord_unittest.* to 'rails'@'localhost';
# GRANT ALL PRIVILEGES ON activerecord_unittest2.* to 'rails'@'localhost';
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 'arunit'
Course.establish_connection 'arunit2'

View file

@ -1,21 +0,0 @@
print "Using native OpenBase\n"
require_dependency 'models/course'
require 'logger'
ActiveRecord::Base.logger = Logger.new("debug.log")
ActiveRecord::Base.configurations = {
'arunit' => {
:adapter => 'openbase',
:username => 'admin',
:database => 'activerecord_unittest',
},
'arunit2' => {
:adapter => 'openbase',
:username => 'admin',
:database => 'activerecord_unittest2'
}
}
ActiveRecord::Base.establish_connection 'arunit'
Course.establish_connection 'arunit2'

View file

@ -1,27 +0,0 @@
print "Using Oracle\n"
require_dependency 'models/course'
require 'logger'
ActiveRecord::Base.logger = Logger.new STDOUT
ActiveRecord::Base.logger.level = Logger::WARN
# Set these to your database connection strings
db = ENV['ARUNIT_DB'] || 'activerecord_unittest'
ActiveRecord::Base.configurations = {
'arunit' => {
:adapter => 'oracle',
:username => 'arunit',
:password => 'arunit',
:database => db,
},
'arunit2' => {
:adapter => 'oracle',
:username => 'arunit2',
:password => 'arunit2',
:database => db
}
}
ActiveRecord::Base.establish_connection 'arunit'
Course.establish_connection 'arunit2'

View file

@ -1,21 +0,0 @@
print "Using native PostgreSQL\n"
require_dependency 'models/course'
require 'logger'
ActiveRecord::Base.logger = Logger.new("debug.log")
ActiveRecord::Base.configurations = {
'arunit' => {
:adapter => 'postgresql',
:database => 'activerecord_unittest',
:min_messages => 'warning'
},
'arunit2' => {
:adapter => 'postgresql',
:database => 'activerecord_unittest2',
:min_messages => 'warning'
}
}
ActiveRecord::Base.establish_connection 'arunit'
Course.establish_connection 'arunit2'

View file

@ -1,25 +0,0 @@
print "Using native SQlite\n"
require_dependency 'models/course'
require 'logger'
ActiveRecord::Base.logger = Logger.new("debug.log")
class SqliteError < StandardError
end
BASE_DIR = FIXTURES_ROOT
sqlite_test_db = "#{BASE_DIR}/fixture_database.sqlite"
sqlite_test_db2 = "#{BASE_DIR}/fixture_database_2.sqlite"
def make_connection(clazz, db_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)
end
clazz.establish_connection(clazz.name)
end
make_connection(ActiveRecord::Base, sqlite_test_db)
make_connection(Course, sqlite_test_db2)

View file

@ -1,25 +0,0 @@
print "Using native SQLite3\n"
require_dependency 'models/course'
require 'logger'
ActiveRecord::Base.logger = Logger.new("debug.log")
class SqliteError < StandardError
end
BASE_DIR = FIXTURES_ROOT
sqlite_test_db = "#{BASE_DIR}/fixture_database.sqlite3"
sqlite_test_db2 = "#{BASE_DIR}/fixture_database_2.sqlite3"
def make_connection(clazz, db_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)
end
clazz.establish_connection(clazz.name)
end
make_connection(ActiveRecord::Base, sqlite_test_db)
make_connection(Course, sqlite_test_db2)

View file

@ -1,18 +0,0 @@
print "Using native SQLite3\n"
require_dependency 'models/course'
require 'logger'
ActiveRecord::Base.logger = Logger.new("debug.log")
class SqliteError < StandardError
end
def make_connection(clazz, db_definitions_file)
clazz.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
File.read(SCHEMA_ROOT + "/#{db_definitions_file}").split(';').each do |command|
clazz.connection.execute(command) unless command.strip.empty?
end
end
make_connection(ActiveRecord::Base, 'sqlite.sql')
make_connection(Course, 'sqlite2.sql')
load(SCHEMA_ROOT + "/schema.rb")

View file

@ -1,23 +0,0 @@
print "Using native Sybase Open Client\n"
require_dependency 'models/course'
require 'logger'
ActiveRecord::Base.logger = Logger.new("debug.log")
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 'arunit'
Course.establish_connection 'arunit2'

View file

@ -1 +0,0 @@
*.sqlite*

View file

@ -1,28 +0,0 @@
signals37:
id: 1
firm_id: 1
credit_limit: 50
unknown:
id: 2
credit_limit: 50
rails_core_account:
id: 3
firm_id: 6
credit_limit: 50
last_account:
id: 4
firm_id: 2
credit_limit: 60
rails_core_account_2:
id: 5
firm_id: 6
credit_limit: 55
odegy_account:
id: 6
firm_id: 9
credit_limit: 53

View file

@ -1,5 +0,0 @@
david_address:
id: 1
david_address_extra:
id: 2

View file

@ -1,4 +0,0 @@
david_mary:
id: 1
author_id: 1
favorite_author_id: 2

View file

@ -1,9 +0,0 @@
david:
id: 1
name: David
author_address_id: 1
author_address_extra_id: 2
mary:
id: 2
name: Mary

View file

@ -1,132 +0,0 @@
flowers:
id: 1
data: !binary | /9j/4AAQSkZJRgABAQEASABIAAD/2wBDAA0JCQoKCg4LCw4UDQsNFBcRDg4R
FxsVFRUVFRsbFRcXFxcVGxoeICEgHhonJyoqJyc1NTU1NTY2NjY2NjY2Njb/
2wBDAQ4NDRERERcRERcXExQTFx0ZGhoZHSYdHR4dHSYsJCAgICAkLCgrJiYm
KygvLywsLy82NjY2NjY2NjY2NjY2Njb/wAARCACvAIMDAREAAhEBAxEB/8QA
GwAAAgMBAQEAAAAAAAAAAAAABAUAAwYCAQf/xABAEAACAQMCBAMFBwMBBQkA
AAABAgMABBESIQUTMUEiUWEUMnGBkQYjQlKxwdEzYqGSFSRD4fAlNUVyc4Ki
svH/xAAZAQADAQEBAAAAAAAAAAAAAAAAAQIDBAX/xAAqEQACAgEEAQQCAgID
AAAAAAAAAQIRAxIhMUFRBBMiYTJxgaFCUpGxwf/aAAwDAQACEQMRAD8A+nUA
SgCUASgDxmCjJ2A6k0ADe3QumqFhID7rA+E/OgBNLecbWcCVoRA2f6Wcj/Vv
USvyNHDtI5y7s3zqCgWR2S7gjiy0koZQM4Axg5+NC+hkHFr8WcjpIYriL3kf
xAMp8S+KnbQqHEHGXG06Z/uT+KpT8icRnBcwzjMTBvMdx8RVkltAEoAlAEoA
lAEoAlAEoArmmSBNbnb9aAEtxdG7bTKP927x9Q3ofOp1DoTwCSy4okMAK2TB
pY4z2/Og+ZyKm9yqD2bVO594NupO2M/h+VJgjmWPmIVyyZ7r1pDJw9Iku44V
Yu8Ebl+Zu+XK75/xVRJZXxzh8WmS7ErRM2kMgAIdiQo+dOaHB7nMCFECMzNj
8T7k/SoGEBuURIjaXXcMD+tCYmh7bXetE52EkbHwJ8hWpAVTAlAEoAlAEoAl
AFc0ywxl26D/ADQAjurlpW5khwOw8hWTZSQMLiAn3x/18aQwTi03s8UV0oyI
ZAzEdkPhfb4GgaDgV2ZTqB3B86BFVwCQGV9Dr7rfh+DVEl/DAGt7qJLiKULm
5cOknpnBwfhp2pwyL+Q8l97O72+ZUEpR1ZFG2fEBg7+tW3YkW/HY0iiMB086
SAsYM7623Pb0+FVZI2sL3mfdSf1B0P5v+dXGVioOqhEoAlAEoA8JxuelAGNu
ftDeX1/7Na2x5eWEJfbVp6t8+1RzwVQXDwtrkcziO7fhgU4VfiV61SQr8Hb8
E4eR4UMZ7FHYH9TRSCxfDYXEuoQzAJpAZJBqDasg7j+KiKstsEtzfWlxdZjV
wjBCAdtlDArnsQaTQfYf7RxEdbGT5Ff5o0sNvIvEgF8sxhdZnDKsW27dBsPS
s6qV9gXXd5ccnBtpIiWXS5G2QwP12q2OIQvEZ239jm33zpPf5U6Yie2Xsp0w
2uG6EOQCMeeaVAR4+KgBpGjjUnBAOo/oP1p6aJs7g4bNIqzG8kVveXQo28uu
acY9hfRqbSbmxDJy42f4+fzrQkvoAlAEoAV8cuWjhECdZfeOcYUdd/Wom9hx
EFhHjiMTYO2r8QONjUwLlwP61Mzk0AAWGxYeg/eoh2VLoC4iUteIrPM3+7Xa
cps7BZI/d+qk0pFR4/QzkuFiVGOcMQNgT1rTolLkSSpJJc61KIBLpjYn3ve2
+O/asq1PYsae1WsdseYA7QeNde+SncD0rSqKhjbkl5Flp9qPapFXkMZG1agp
8K4G2TjvSTO+fpNHYfDe25lRWOJZAdJII6dck4p/Zz5fTtptdFl2fCo9c/QU
pnEi2DaJB6CnHoT5CbaflSBvwnZvhTAcUASgCUAZ/i6e0SK222eozttUTKiL
7WEJexMWX3vygHofKpiUx3Wpmck0AL7Q4kb/AMv71EOypcIB+0EkLRpE5wUc
SasZC4OdwO2KT8eCsf0WT36sXXK+AqkZ8R+9xq+80dh5VZajQseaWVI5IHCR
MwZkIHhckAOPyrkdKlPnoNqdLdkml9mI0za0VtAjCr/VOWLMRjrTGpNU2BSH
lxy3HD5dAClZYG6nR4QQcYI3+NJb7o9DDnWaPyj8r5DC9w0cVsYyyrCGUrjU
8vhJ0b48PlT+hKUVJ773/Q4kLmGMPq5nLOvVjVnGN9O1KfR52SnOTXAWmyge
lX0YnuaAGfCrkzwMGxqiYrt+X8JpAHUwKrltMZ8ztQAg4mhJXwlgwK4H1qJF
RFqQyNd240MMON8Y6bmpiyn2aA1qZlRkUSCPPjIyB6ClfQAMBxK3wP61OPk1
q6Qn4pJcyXeI49UUiaZCPy1r7bt/cTphh0WvKPeCS+02oZtTSkYYquBkbAlt
qK+KtkyT0pbJFV/dSxW8kZBLNEq83w6HcnG4x1rOXZnJbbeQO9RrSKKMnW6t
45Nj4hjYbZ6GufMpbU+DBthXBrG61ZeZo4bZtXs4B0bjOGzse1XhHGTXAebZ
b/dzh4yrow/Cd+nyq49minpYXMfHj+0D6miXKIXYXWhBKAOOBTSxXZidTpbK
E42yNxWa5KfBpa0JBLxt1X50AKOKe5Gdup66vL+2omVHkVxY9rg2QeMdpM1E
eS3wNrq/htQzSnSFGf8A8rY0xencv5FnD76PiN61xETohBU5HXsNPp5+tZ6L
nqsnNg9trfkF4rfrbRvp8cm66B6nbP8AFbQhTbuzpw4qpsVT3XD3n5d1cttE
MFchAxzkeHoR5GtHOG5eTPDeIJFx8w2/Kt5Gj8eU22GWydq5jgk+PsvueJST
BeeBIi7YAwSD3x50tW+5pKq2e5JZ2uFS3c/dBmKsBuc+dZzfSMn8ugi3llsp
fBI0nNULIr+bdCPlWduMkl2QuRvDOLTVzPTVjfSPXFdscdJts6vYcld0WwTx
XcjGM5Axg/ChQU02gWH4Nh5IAyeg6mkcp6hJAJGn41NgBWsgSUuCMq+fecdD
UdmlbGuVtQBHQ7itTMAuDmVvTagBfxCUxquBnrUTKiK2upDLEFAXUwGc+tRH
ktAvFkubZpI5NUyTKyjIz4z00/Stj1MUoNKtmgHhd+bSRrd9UK8soW/EvcN8
DWCk1N2rPOnqlle1/IW8QnnwfEdW5yPI9cfKqlq1N3syvUxyY5PfkVQ8oSa5
TshB0fm9KaOWP2X35iuZOZbJ4QMyaBgAeZA6U0VL8VRdaSxkYmy6Lkjpnby1
VlKO4vDHFhcw+EIcsQS6YBchd8IfM5p49q8mi/tlF8US45aKwyOcS/hZQ2+N
O9LJ8XZD5aBH4s7HlP8A0s+IrsxX1qpSlJVexXvSez4HlrcQq5e3O0gAx0C4
863nmhFLQehKcdCSDBfXEsZCqAc+HUwHw8Jx0/WuaTnJPT/ZwSxveQRBE4TU
+qSRRnfGB323OanHjfMm2zI8trqXHbT8d60NDT8Pn5tnE7bMRv8ALatUzMGk
OXY+ppgA8UH+7Z6EHYk4/WoycDRnVvUjViyDndE1HYefn9a5sOR63GS/Rv6f
8qmWcFuGmnHtPVieSzncjyz3O1dn7Ov1cYxinF7+DvjEltcXSK7qlvb+BmA8
z4lb08qIuLel8h6OaipLnI/J3NwuEqDbeDBXWPe1Rjqu/wCYV0PGmazcskdL
Kr37OcOuHWSNeTkqSE93HcaexIp+xBmD9NB/TOG+zdnCJmtQUeVWRIycp4hp
3zk+tKWBdCl6ZU62A2+y0VtbLqLTyKCZCh07/wBoINYyxUYS9PVFdnAIIo8R
bFG9paUeMdT91q2Bx9ajSTpSsFDR3Gow6pvDp5jDEjd/EMnp0rly25KkZP5P
gEdIYyBpyw643GfM57071JdCrpIbcrRJaCI632MrdUC+WO9dkcKSS/5PRji2
j/Y2iWGS4eGNkDLh1wPCenu5zWkMSi3XBosaiuORlDcxgmJ2CuOgI05/mpyQ
o5M2Ct0B2yQ6D4Vzuerj9q5aMR9w9glpGoG2P39atGbPasQNf7wYzjJ8gf1q
ZcDjyZjjNr9ykyyeOLvjr8umP1qFR2YpxpxmrAU4YdpGkC3Kf6D5fCn7eqPN
DXptcdeoJ4ct887TcyCNR4csQdQ7rpP61p6aNdhg7Td/9jb2hh+TI2+7YEf6
etdp2RRwbiViREpbT72O1cmT1Si6FKUV3R6t+Op2PTftW+PIpqy1G9wKbjCS
utvCGdnb7x12wnfSehNKcujmyvpFL3DBy64a3CFnGC+wbJKE/pWL5OeSr9Ir
jis7hG9mHLlc6o2IwXGdye/eolBTT68EabVoL4TwlJpi08XQEddjj8461msT
tXVIUYb2MWtYLxHMOiO4hfSM+4WXorY3x8K3U6Ov5w47QktmntzpuAIry2zE
yY2zksuCeqsp6+Vaavjd7hHNcN+UH3V3rg1toFzEA2gHOdW3gz19Ky9x72Rj
z03e6KeHz3CSK12GUxnVGrZJPVTo8t6y35ZjPz5NDbXDNCpVCR500c4bViBe
IIWtyR1Xfy9KiXA0Zu+R1hbEYJ8iwz8t6xst/QFPy2iRYoWhf/ian15P6CsM
mR1pWyRPuyrTewTwuZVK2zJHpc+++c+gFb+jzfJQdb/5dm3pslOhoPYJWZYQ
khT3yuCF+JG1esqZ6MZ32VgTQKTHjSxzgiuXJ6GMnY5YoyOBaId5xqDdc9M+
tb48KxqiuFR5d20FtDI+eTgasjAJ076ct50pr7OfL58Gdu5IeIrG0UmZzsFi
BAC4911Pr5Vzs43Ut+w7hHtNvbkOhTUwKnGl8HqwDb9qUXzsPEjQcLmymVyx
zplkI0sxHmKLNdKdlHE/ub1buFFMGwkRAch+xYLQaY8lQcH+XkRcavFuLyK6
3PKTl4PQjuNt+hxuaiUjz55PlsW8znWjzxwgLFiMBcHAG++odKV2my7uOoL4
bMjW2F0q+nGnfVqPUnPb0HrQpXF+Rt6kWiK7xtJPj00gfLBqorYnY1FwwiLk
gkKeijJ+gpvbczEfFOLAjkhBo/FzMgj4qP3rly5b2/8ABGflu87xx/dxnOvG
AfXVuTUJP9DPfazO5d/eY5b4msZ3bsRxc40nPQg/pRDlMa2GHCOI8Lg4ZDFH
IMJpWRejyTP1AXvv3r24TVI78WSOlbjXUs4wv9IEgsdskdhmtdR0KQDHfxQX
Pss7aucmuINtqUErpGe9S59ClkV1wxZxy/itrf2csJTINLQtvjyOe1ZzmjHP
ljTXkF4HPwzh8trcysA4fSTk5GrwuSOmBnY+VYnJcUl5Hl6sE105X75cAmWN
vmACDRaOiLDLS7UHMhA7KuQNvTOKRbXAp+0ExS5SSJuXzFOtVbr2ye24rnzN
pqjlzPfkzzylpWxvj/raj8kmznHfApFS1uhJup/4R6Nt3+taRquTbF+Dst4d
JHaJonZR+UqPwnz071OuK7FexsrBoZ7WOWLdG6eEjvitVJEF12CJWx33FUBk
+MWXFOYzuRNbA6gVwgGe5Xz9azd8ktMUuPDg4YfHIqHJeBaGTaVyxOmYBUEW
n38bD5j/ADUThrX2NffJzejl2zPICOX4WHffp1rmjF60ijOgCNo3R8nZsjqp
8jnuPSvQuhJ1wHzz390BJLNoVGDKo93I74pvP/LNfdm+yrifEpL2USEjIAVf
T4UtTk7kRPI5MHt7d7iQIvXclv3p0wSbouktOSjcwb7fLPSs2pahSjRbacbn
srRrRUR0bOJCMMurr0OD6VoVGdD3iH2i4W9nCLLLXsWATIh93GD6Ghmksol5
rSku8hLMe46fSuWTMXueezg+IOMkjbfejVs1RNfYdHbyhdTKQvn28utRpl/A
1fAwtOGyP4mU47Yx9Sa0hj8l15PodlFybWGP8qAV1USU3y7q3ypgAXKh4XU9
MGpl2Bl723iMMoCqpKnGFK+tYmj4YDaW91I0fO2B3EmMkY33P7mhJmSvkb3t
vBPaj7tvZiMs2Nyo6Y1uSd+m9VJdlGOveGCE5WTVEc6fCc/x/mlHI/8AUWkY
8AurKAv7eNOpcQM4OnQOoHXeqpcmkWhdeexy3MrW33dv6/sKndGUudgeJnjc
GFipHQjbHwqtbBNnsvN0qskjOoJxk567nNGpvrcLb5OhbpJgINR2AGd/lUW1
yBwLaXSZhGdKEAt8a05Q6DH+5VNSNkjbbqeprmS1N7gN+C21tcoJllTnr1jf
dRnoD339K2hjXkSGl/NKIbi2dTq0rJ5hl1AZDdznber+ike8OTmvFGFbxsB7
n75qVyU+Dd4rYgquk1xHzG4+VACxsaTnpijoDN3kC8s+JjnqMmudmoQvD/b7
O1YYVdAWXG2dOV7Vt0QnyNXijePlsoKYxj4dKdEmV43ZJaYDkurKTk7+n6Vn
LYtdiyLhVxeWYuWAECjRGPxNjPTemkSlqYm0EOQDgjbI6fKhiregm3tlOkyS
feO+APLHeplfXRMgmaCK5i0qzFwckbduuKmGz3Bc7hElhZ5ieNgjkZAyR7oD
Z7jI771tJKnwzZxj0VtfzItxa4xLlgrZ93OOnbfvU6tG3NE66tFllwDiE9rG
I7kLG+S8erKgfhbbz8utSop7rkzD7fgt3Zyq8kSXMfuycv39PoD+1Dj53Aa8
RSKGxRYwQGdQNWScbtjxb9qp0o8FxGH2bi5s+v8ADCM/+47ClBFSNRWpBKAF
NzHy2dO2+PhR0Blblm5ZBbY1zmo24If+zYvTUP8A5GtlwjNhpqhCT7RQiSOI
noGIP6/tWeToqIN/4CiqMkb48vGaTfxFwzOPb4dv7jt/ArGMrlSJ7PBGyb9h
512JFHrtoGfd9cUUn0Kgq0iadrf8hfUMjv2NTJdLgfRxdWfst1ytWuVgGd/N
m3OK5skWuyDVwW/IxygNJ6r0+JFbxjVFBQqwAuNDMEX/AKoP0BqZ8DjyaPgN
mbWxXUPvZfG/z6D6URWwMZVQiUADXsOtNQ95f070AYi5wMr+Un9aw7NehpwT
/u+P4v8A/Y1rHhGbDqoQs41g22M76gcd6znwVHkWx3kX+zfZ9LM+46bDxZ61
Mn8K8g+RfPExboCcZz6+Qq4YUqFR5GpVgwzpO5U7q3xBrUVFrmX3kiAC9gMf
SqCjt2bSHxpc/wCKUr4oEcjl3d4zS+5lQfkB0rnmvluVWw9W5hHc1epE0WLc
w/mp6kFBENkvEpoRkGGF+ZL8gcL8zRyBpaYEoAlAEoAx/wBobBrWcyqMwTEk
H8rdSv8AFZTXZafQutOJSxwLBHhQhbfGTuSe9NS2Bota6lb3nJ+dTYUgaZiw
60mMF3UEb77mhAeI+kjX3z8q3TAJiuo4gRpGr1rTUQ4lct5IeunHlijULSBc
ySRyMjbqDsR/NS5F0Fwx/XzrnfIwxM0AXRxSSuI0XLscAetArNhw2xWxtxEN
3O8jebVqiAumBKAJQBKAKbm2iuoWhmGqNxgikBirngsvDZWV/HGxJjkx7w8j
61k40aJlWnekByy0wB3U0ADTLgnoNXVjVxYFPNDjDdvP9iN6sD1iMfi2/vH7
0WBLePXINI2+v+TUyYDaOLA6VmIvSMswUdT7oHegDUcJ4WLRebLvcMP9I8hW
iRDGdUBKAJQBKAJQBKAK54IriMxyrqQ9qQGZ4jwaW1JeMGWDz7r8R+9Q4lJi
rH9tSM5ZCR0/xQBXLbcwYxin+gF83D7nV4Vz/dmrUh2epw+7OxGB6n/nRqDY
YW9qkA3bxd6ixB9rayXL6IFLHv5D4mnQjS8O4TFZ+NvHP+fy9Fq0ibGFMCUA
SgCUASgCUASgCUASgAC74PbXOTvE5/En7jpSoLE8/wBn7uPJjKyj46T9D/NT
pKsXyQzxNpdNP0/akB5484WkMKh4RfXG4UafNmH7b0UxWMrb7Nxg6rl9Z/Im
w+vWq0iscQwxQroiUIvkKsRZQBKAJQBKAJQB/9k=

View file

@ -1,7 +0,0 @@
awdr:
id: 1
name: "Agile Web Development with Rails"
rfr:
id: 2
name: "Ruby for Rails"

View file

@ -1,14 +0,0 @@
general:
id: 1
name: General
type: Category
technology:
id: 2
name: Technology
type: Category
sti_test:
id: 3
name: Special category
type: SpecialCategory

View file

@ -1,9 +0,0 @@
sub_special_1:
id: 100
name: A special category in a subdir file
type: SpecialCategory
sub_special_2:
id: 101
name: Another special category
type: SpecialCategory

View file

@ -1,4 +0,0 @@
sub_special_3:
id: 102
name: A special category in an arbitrarily named subsubdir file
type: SpecialCategory

View file

@ -1,7 +0,0 @@
--- !!omap
<% 100.times do |i| %>
- fixture_no_<%= i %>:
id: <%= i %>
name: <%= "Category #{i}" %>
type: Category
<% end %>

View file

@ -1,23 +0,0 @@
general_welcome:
category_id: 1
post_id: 1
technology_welcome:
category_id: 2
post_id: 1
general_thinking:
category_id: 1
post_id: 2
general_sti_habtm:
category_id: 1
post_id: 6
sti_test_sti_habtm:
category_id: 3
post_id: 6
general_hello:
category_id: 1
post_id: 4

View file

@ -1,17 +0,0 @@
david_welcome_general:
id: 1
author_id: 1
post_id: 1
category_id: 1
mary_thinking_sti:
id: 2
author_id: 2
post_id: 2
category_id: 3
mary_thinking_general:
id: 3
author_id: 2
post_id: 2
category_id: 1

Some files were not shown because too many files have changed in this diff Show more