diff options
Diffstat (limited to 'activerecord/test')
59 files changed, 1617 insertions, 400 deletions
diff --git a/activerecord/test/cases/adapters/mysql/connection_test.rb b/activerecord/test/cases/adapters/mysql/connection_test.rb index f76a23a8ad..62ffde558f 100644 --- a/activerecord/test/cases/adapters/mysql/connection_test.rb +++ b/activerecord/test/cases/adapters/mysql/connection_test.rb @@ -43,6 +43,64 @@ class MysqlConnectionTest < ActiveRecord::TestCase assert @connection.active? end + def test_bind_value_substitute + bind_param = @connection.substitute_for('foo', []) + assert_equal Arel.sql('?'), bind_param + end + + def test_exec_no_binds + @connection.exec_query('drop table if exists ex') + @connection.exec_query(<<-eosql) + CREATE TABLE `ex` (`id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, + `data` varchar(255)) + eosql + result = @connection.exec_query('SELECT id, data FROM ex') + assert_equal 0, result.rows.length + assert_equal 2, result.columns.length + assert_equal %w{ id data }, result.columns + + @connection.exec_query('INSERT INTO ex (id, data) VALUES (1, "foo")') + result = @connection.exec_query('SELECT id, data FROM ex') + assert_equal 1, result.rows.length + assert_equal 2, result.columns.length + + assert_equal [[1, 'foo']], result.rows + end + + def test_exec_with_binds + @connection.exec_query('drop table if exists ex') + @connection.exec_query(<<-eosql) + CREATE TABLE `ex` (`id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, + `data` varchar(255)) + eosql + @connection.exec_query('INSERT INTO ex (id, data) VALUES (1, "foo")') + result = @connection.exec_query( + 'SELECT id, data FROM ex WHERE id = ?', nil, [[nil, 1]]) + + assert_equal 1, result.rows.length + assert_equal 2, result.columns.length + + assert_equal [[1, 'foo']], result.rows + end + + def test_exec_typecasts_bind_vals + @connection.exec_query('drop table if exists ex') + @connection.exec_query(<<-eosql) + CREATE TABLE `ex` (`id` int(11) DEFAULT NULL auto_increment PRIMARY KEY, + `data` varchar(255)) + eosql + @connection.exec_query('INSERT INTO ex (id, data) VALUES (1, "foo")') + column = @connection.columns('ex').find { |col| col.name == 'id' } + + result = @connection.exec_query( + 'SELECT id, data FROM ex WHERE id = ?', nil, [[column, '1-fuu']]) + + assert_equal 1, result.rows.length + assert_equal 2, result.columns.length + + assert_equal [[1, 'foo']], result.rows + end + # Test that MySQL allows multiple results for stored procedures if Mysql.const_defined?(:CLIENT_MULTI_RESULTS) def test_multi_results diff --git a/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb b/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb index 7b72151b57..b0a4a4e39d 100644 --- a/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb +++ b/activerecord/test/cases/adapters/postgresql/postgresql_adapter_test.rb @@ -5,6 +5,8 @@ module ActiveRecord class PostgreSQLAdapterTest < ActiveRecord::TestCase def setup @connection = ActiveRecord::Base.connection + @connection.exec_query('drop table if exists ex') + @connection.exec_query('create table ex(id serial primary key, data character varying(255))') end def test_table_alias_length @@ -12,6 +14,55 @@ module ActiveRecord @connection.table_alias_length end end + + def test_exec_no_binds + result = @connection.exec_query('SELECT id, data FROM ex') + assert_equal 0, result.rows.length + assert_equal 2, result.columns.length + assert_equal %w{ id data }, result.columns + + string = @connection.quote('foo') + @connection.exec_query("INSERT INTO ex (id, data) VALUES (1, #{string})") + result = @connection.exec_query('SELECT id, data FROM ex') + assert_equal 1, result.rows.length + assert_equal 2, result.columns.length + + assert_equal [['1', 'foo']], result.rows + end + + def test_exec_with_binds + string = @connection.quote('foo') + @connection.exec_query("INSERT INTO ex (id, data) VALUES (1, #{string})") + result = @connection.exec_query( + 'SELECT id, data FROM ex WHERE id = $1', nil, [[nil, 1]]) + + assert_equal 1, result.rows.length + assert_equal 2, result.columns.length + + assert_equal [['1', 'foo']], result.rows + end + + def test_exec_typecasts_bind_vals + string = @connection.quote('foo') + @connection.exec_query("INSERT INTO ex (id, data) VALUES (1, #{string})") + + column = @connection.columns('ex').find { |col| col.name == 'id' } + result = @connection.exec_query( + 'SELECT id, data FROM ex WHERE id = $1', nil, [[column, '1-fuu']]) + + assert_equal 1, result.rows.length + assert_equal 2, result.columns.length + + assert_equal [['1', 'foo']], result.rows + end + + def test_substitute_for + bind = @connection.substitute_for(nil, []) + assert_equal Arel.sql('$1'), bind + + bind = @connection.substitute_for(nil, [nil]) + assert_equal Arel.sql('$2'), bind + end end end end diff --git a/activerecord/test/cases/adapters/postgresql/schema_authorization_test.rb b/activerecord/test/cases/adapters/postgresql/schema_authorization_test.rb index 6f372edc38..d5e1838543 100644 --- a/activerecord/test/cases/adapters/postgresql/schema_authorization_test.rb +++ b/activerecord/test/cases/adapters/postgresql/schema_authorization_test.rb @@ -43,6 +43,36 @@ class SchemaAuthorizationTest < ActiveRecord::TestCase end end + def test_session_auth= + assert_raise(ActiveRecord::StatementInvalid) do + @connection.session_auth = 'DEFAULT' + @connection.execute "SELECT * FROM #{TABLE_NAME}" + end + end + + def test_setting_auth_clears_stmt_cache + assert_nothing_raised do + set_session_auth + USERS.each do |u| + set_session_auth u + assert_equal u, @connection.exec_query("SELECT name FROM #{TABLE_NAME} WHERE id = $1", 'SQL', [[nil, 1]]).first['name'] + set_session_auth + end + end + end + + def test_auth_with_bind + assert_nothing_raised do + set_session_auth + USERS.each do |u| + @connection.clear_cache! + set_session_auth u + assert_equal u, @connection.exec_query("SELECT name FROM #{TABLE_NAME} WHERE id = $1", 'SQL', [[nil, 1]]).first['name'] + set_session_auth + end + end + end + def test_schema_uniqueness assert_nothing_raised do set_session_auth @@ -78,7 +108,7 @@ class SchemaAuthorizationTest < ActiveRecord::TestCase private def set_session_auth auth = nil - @connection.execute "SET SESSION AUTHORIZATION #{auth || 'default'}" + @connection.session_auth = auth || 'default' end end diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb index 934cf72f72..234696adeb 100644 --- a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb @@ -3,6 +3,12 @@ require "cases/helper" module ActiveRecord module ConnectionAdapters class SQLite3AdapterTest < ActiveRecord::TestCase + def setup + @conn = Base.sqlite3_connection :database => ':memory:', + :adapter => 'sqlite3', + :timeout => 100 + end + def test_connection_no_db assert_raises(ArgumentError) do Base.sqlite3_connection {} @@ -38,18 +44,58 @@ module ActiveRecord end def test_connect - conn = Base.sqlite3_connection :database => ':memory:', - :adapter => 'sqlite3', - :timeout => 100 - assert conn, 'should have connection' + assert @conn, 'should have connection' end # sqlite3 defaults to UTF-8 encoding def test_encoding - conn = Base.sqlite3_connection :database => ':memory:', - :adapter => 'sqlite3', - :timeout => 100 - assert_equal 'UTF-8', conn.encoding + assert_equal 'UTF-8', @conn.encoding + end + + def test_bind_value_substitute + bind_param = @conn.substitute_for('foo', []) + assert_equal Arel.sql('?'), bind_param + end + + def test_exec_no_binds + @conn.exec_query('create table ex(id int, data string)') + result = @conn.exec_query('SELECT id, data FROM ex') + assert_equal 0, result.rows.length + assert_equal 2, result.columns.length + assert_equal %w{ id data }, result.columns + + @conn.exec_query('INSERT INTO ex (id, data) VALUES (1, "foo")') + result = @conn.exec_query('SELECT id, data FROM ex') + assert_equal 1, result.rows.length + assert_equal 2, result.columns.length + + assert_equal [[1, 'foo']], result.rows + end + + def test_exec_query_with_binds + @conn.exec_query('create table ex(id int, data string)') + @conn.exec_query('INSERT INTO ex (id, data) VALUES (1, "foo")') + result = @conn.exec_query( + 'SELECT id, data FROM ex WHERE id = ?', nil, [[nil, 1]]) + + assert_equal 1, result.rows.length + assert_equal 2, result.columns.length + + assert_equal [[1, 'foo']], result.rows + end + + def test_exec_query_typecasts_bind_vals + @conn.exec_query('create table ex(id int, data string)') + @conn.exec_query('INSERT INTO ex (id, data) VALUES (1, "foo")') + column = @conn.columns('ex').find { |col| col.name == 'id' } + + result = @conn.exec_query( + 'SELECT id, data FROM ex WHERE id = ?', nil, [[column, '1-fuu']]) + + assert_equal 1, result.rows.length + assert_equal 2, result.columns.length + + assert_equal [[1, 'foo']], result.rows end end end diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb index cbaa4990f7..1b0c00bd5a 100644 --- a/activerecord/test/cases/associations/belongs_to_associations_test.rb +++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb @@ -81,6 +81,13 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase assert_not_nil citibank_result.instance_variable_get("@firm_with_primary_key") end + def test_eager_loading_with_primary_key_as_symbol + Firm.create("name" => "Apple") + Client.create("name" => "Citibank", :firm_name => "Apple") + citibank_result = Client.find(:first, :conditions => {:name => "Citibank"}, :include => :firm_with_primary_key_symbols) + assert_not_nil citibank_result.instance_variable_get("@firm_with_primary_key_symbols") + end + def test_no_unexpected_aliasing first_firm = companies(:first_firm) another_firm = companies(:another_firm) @@ -278,10 +285,10 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase final_cut = Client.new("name" => "Final Cut") firm = Firm.find(1) final_cut.firm = firm - assert final_cut.new_record? + assert !final_cut.persisted? assert final_cut.save - assert !final_cut.new_record? - assert !firm.new_record? + assert final_cut.persisted? + assert firm.persisted? assert_equal firm, final_cut.firm assert_equal firm, final_cut.firm(true) end @@ -290,10 +297,10 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase final_cut = Client.new("name" => "Final Cut") firm = Firm.find(1) final_cut.firm_with_primary_key = firm - assert final_cut.new_record? + assert !final_cut.persisted? assert final_cut.save - assert !final_cut.new_record? - assert !firm.new_record? + assert final_cut.persisted? + assert firm.persisted? assert_equal firm, final_cut.firm_with_primary_key assert_equal firm, final_cut.firm_with_primary_key(true) end diff --git a/activerecord/test/cases/associations/callbacks_test.rb b/activerecord/test/cases/associations/callbacks_test.rb index 15537d6940..6a30e2905b 100644 --- a/activerecord/test/cases/associations/callbacks_test.rb +++ b/activerecord/test/cases/associations/callbacks_test.rb @@ -72,7 +72,7 @@ class AssociationCallbacksTest < ActiveRecord::TestCase 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" + 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 @@ -149,7 +149,7 @@ class AssociationCallbacksTest < ActiveRecord::TestCase assert !@david.unchangable_posts.include?(@authorless) begin @david.unchangable_posts << @authorless - rescue Exception => e + rescue Exception end assert @david.post_log.empty? assert !@david.unchangable_posts.include?(@authorless) diff --git a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb index b93e49613d..0742e311d9 100644 --- a/activerecord/test/cases/associations/cascaded_eager_loading_test.rb +++ b/activerecord/test/cases/associations/cascaded_eager_loading_test.rb @@ -3,20 +3,22 @@ require 'models/post' require 'models/comment' require 'models/author' require 'models/categorization' +require 'models/category' require 'models/company' require 'models/topic' require 'models/reply' require 'models/person' class CascadedEagerLoadingTest < ActiveRecord::TestCase - fixtures :authors, :mixins, :companies, :posts, :topics, :accounts, :comments, :categorizations, :people + fixtures :authors, :mixins, :companies, :posts, :topics, :accounts, :comments, + :categorizations, :people, :categories 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} + assert_equal 10, 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 @@ -24,7 +26,7 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase 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 10, 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 @@ -35,7 +37,7 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase end authors = Author.joins(:posts).eager_load(:comments).where(:posts => {:taggings_count => 1}).all assert_equal 1, assert_no_queries { authors.size } - assert_equal 9, assert_no_queries { authors[0].comments.size } + assert_equal 10, assert_no_queries { authors[0].comments.size } end def test_eager_association_loading_grafts_stashed_associations_to_correct_parent @@ -45,6 +47,31 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase assert_equal people(:michael), Person.eager_load(:primary_contact => :primary_contact).where('primary_contacts_people_2.first_name = ?', 'Susan').order('people.id').first end + def test_cascaded_eager_association_loading_with_join_for_count + categories = Category.joins(:categorizations).includes([{:posts=>:comments}, :authors]) + + assert_nothing_raised do + assert_equal 2, categories.count + assert_equal 2, categories.all.uniq.size # Must uniq since instantiating with inner joins will get dupes + end + end + + def test_cascaded_eager_association_loading_with_duplicated_includes + categories = Category.includes(:categorizations).includes(:categorizations => :author).where("categorizations.id is not null") + assert_nothing_raised do + assert_equal 2, categories.count + assert_equal 2, categories.all.size + end + end + + def test_cascaded_eager_association_loading_with_twice_includes_edge_cases + categories = Category.includes(:categorizations => :author).includes(:categorizations => :post).where("posts.id is not null") + assert_nothing_raised do + assert_equal 2, categories.count + assert_equal 2, categories.all.size + end + end + def test_eager_association_loading_with_join_for_count authors = Author.joins(:special_posts).includes([:posts, :categorizations]) @@ -57,7 +84,7 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase 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 10, 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 @@ -111,7 +138,7 @@ class CascadedEagerLoadingTest < ActiveRecord::TestCase 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') + 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 diff --git a/activerecord/test/cases/associations/eager_load_includes_full_sti_class_test.rb b/activerecord/test/cases/associations/eager_load_includes_full_sti_class_test.rb index b124a2bfc3..fb59f63f91 100644 --- a/activerecord/test/cases/associations/eager_load_includes_full_sti_class_test.rb +++ b/activerecord/test/cases/associations/eager_load_includes_full_sti_class_test.rb @@ -17,7 +17,7 @@ class EagerLoadIncludeFullStiClassNamesTest < ActiveRecord::TestCase def generate_test_objects post = Namespaced::Post.create( :title => 'Great stuff', :body => 'This is not', :author_id => 1 ) - tagging = Tagging.create( :taggable => post ) + Tagging.create( :taggable => post ) end def test_class_names diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb index 40859d425f..ea86ac29d0 100644 --- a/activerecord/test/cases/associations/eager_test.rb +++ b/activerecord/test/cases/associations/eager_test.rb @@ -79,6 +79,58 @@ class EagerAssociationTest < ActiveRecord::TestCase end end + def test_preloading_has_many_in_multiple_queries_with_more_ids_than_database_can_handle + Post.connection.expects(:in_clause_length).at_least_once.returns(5) + posts = Post.find(:all, :include=>:comments) + assert_equal 7, posts.size + end + + def test_preloading_has_many_in_one_queries_when_database_has_no_limit_on_ids_it_can_handle + Post.connection.expects(:in_clause_length).at_least_once.returns(nil) + posts = Post.find(:all, :include=>:comments) + assert_equal 7, posts.size + end + + def test_preloading_habtm_in_multiple_queries_with_more_ids_than_database_can_handle + Post.connection.expects(:in_clause_length).at_least_once.returns(5) + posts = Post.find(:all, :include=>:categories) + assert_equal 7, posts.size + end + + def test_preloading_habtm_in_one_queries_when_database_has_no_limit_on_ids_it_can_handle + Post.connection.expects(:in_clause_length).at_least_once.returns(nil) + posts = Post.find(:all, :include=>:categories) + assert_equal 7, posts.size + end + + def test_load_associated_records_in_one_query_when_adapter_has_no_limit + Post.connection.expects(:in_clause_length).at_least_once.returns(nil) + Post.expects(:i_was_called).with([1,2,3,4,5,6,7]).returns([1]) + associated_records = Post.send(:associated_records, [1,2,3,4,5,6,7]) do |some_ids| + Post.i_was_called(some_ids) + end + assert_equal [1], associated_records + end + + def test_load_associated_records_in_several_queries_when_many_ids_passed + Post.connection.expects(:in_clause_length).at_least_once.returns(5) + Post.expects(:i_was_called).with([1,2,3,4,5]).returns([1]) + Post.expects(:i_was_called).with([6,7]).returns([6]) + associated_records = Post.send(:associated_records, [1,2,3,4,5,6,7]) do |some_ids| + Post.i_was_called(some_ids) + end + assert_equal [1,6], associated_records + end + + def test_load_associated_records_in_one_query_when_a_few_ids_passed + Post.connection.expects(:in_clause_length).at_least_once.returns(5) + Post.expects(:i_was_called).with([1,2,3]).returns([1]) + associated_records = Post.send(:associated_records, [1,2,3]) do |some_ids| + Post.i_was_called(some_ids) + end + assert_equal [1], associated_records + 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") @@ -174,7 +226,7 @@ class EagerAssociationTest < ActiveRecord::TestCase def test_eager_association_loading_with_belongs_to comments = Comment.find(:all, :include => :post) - assert_equal 10, comments.length + assert_equal 11, comments.length titles = comments.map { |c| c.post.title } assert titles.include?(posts(:welcome).title) assert titles.include?(posts(:sti_post_and_comments).title) @@ -323,7 +375,7 @@ class EagerAssociationTest < ActiveRecord::TestCase def test_eager_with_has_many_through_a_belongs_to_association author = authors(:mary) - post = Post.create!(:author => author, :title => "TITLE", :body => "BODY") + Post.create!(:author => author, :title => "TITLE", :body => "BODY") author.author_favorites.create(:favorite_author_id => 1) author.author_favorites.create(:favorite_author_id => 2) posts_with_author_favorites = author.posts.find(:all, :include => :author_favorites) @@ -521,7 +573,7 @@ class EagerAssociationTest < ActiveRecord::TestCase end def test_eager_with_inheritance - posts = SpecialPost.find(:all, :include => [ :comments ]) + SpecialPost.find(:all, :include => [ :comments ]) end def test_eager_has_one_with_association_inheritance @@ -532,7 +584,7 @@ class EagerAssociationTest < ActiveRecord::TestCase 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 + assert special_comment.is_a?(SpecialComment) end end @@ -561,16 +613,16 @@ class EagerAssociationTest < ActiveRecord::TestCase def test_eager_with_invalid_association_reference assert_raise(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") { - post = Post.find(6, :include=> :monkeys ) + Post.find(6, :include=> :monkeys ) } assert_raise(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") { - post = Post.find(6, :include=>[ :monkeys ]) + Post.find(6, :include=>[ :monkeys ]) } assert_raise(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys") { - post = Post.find(6, :include=>[ 'monkeys' ]) + Post.find(6, :include=>[ 'monkeys' ]) } assert_raise(ActiveRecord::ConfigurationError, "Association was not found; perhaps you misspelled it? You specified :include => :monkeys, :elephants") { - post = Post.find(6, :include=>[ :monkeys, :elephants ]) + Post.find(6, :include=>[ :monkeys, :elephants ]) } end @@ -584,8 +636,8 @@ class EagerAssociationTest < ActiveRecord::TestCase 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) + 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_limited_eager_with_numeric_in_association @@ -726,8 +778,8 @@ class EagerAssociationTest < ActiveRecord::TestCase posts = assert_queries(2) do Post.find(:all, :joins => :comments, :include => :author, :order => 'comments.id DESC') end - assert_equal posts(:eager_other), posts[0] - assert_equal authors(:mary), assert_no_queries { posts[0].author} + assert_equal posts(:eager_other), posts[1] + assert_equal authors(:mary), assert_no_queries { posts[1].author} end def test_eager_loading_with_conditions_on_joined_table_preloads diff --git a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb index 7e070e1746..705550216c 100644 --- a/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_and_belongs_to_many_associations_test.rb @@ -251,10 +251,10 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase 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.persisted? + assert !p.persisted? assert aredridel.save - assert !aredridel.new_record? + assert aredridel.persisted? assert_equal no_of_devels+1, Developer.count assert_equal no_of_projects+1, Project.count assert_equal 2, aredridel.projects.size @@ -288,22 +288,22 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase assert_equal devel.projects.last, proj assert devel.projects.loaded? - assert proj.new_record? + assert !proj.persisted? devel.save - assert !proj.new_record? + assert proj.persisted? 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") + devel.projects.build(:name => "Make bed") proj2 = devel.projects.build(:name => "Lie in it") assert_equal devel.projects.last, proj2 - assert proj2.new_record? + assert !proj2.persisted? devel.save - assert !devel.new_record? - assert !proj2.new_record? + assert devel.persisted? + assert proj2.persisted? assert_equal devel.projects.last, proj2 assert_equal Developer.find_by_name("Marcel").projects.last, proj2 # prove join table is updated end @@ -316,19 +316,19 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase assert_equal devel.projects.last, proj assert !devel.projects.loaded? - assert !proj.new_record? + assert proj.persisted? 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") + devel.projects.build(:name => "Make bed") proj2 = devel.projects.build(:name => "Lie in it") assert_equal devel.projects.last, proj2 - assert proj2.new_record? + assert !proj2.persisted? devel.save - assert !devel.new_record? - assert !proj2.new_record? + assert devel.persisted? + assert proj2.persisted? assert_equal devel.projects.last, proj2 assert_equal Developer.find_by_name("Marcel").projects.last, proj2 # prove join table is updated end @@ -343,7 +343,7 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase # in Oracle '' is saved as null therefore need to save ' ' in not null column another_post = categories(:general).post_with_conditions.create(:body => ' ') - assert !another_post.new_record? + assert another_post.persisted? assert_equal 'Yet Another Testing Title', another_post.title end @@ -559,8 +559,6 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase 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'") diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index c9f00fd737..fb772bb8e6 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -66,6 +66,16 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal 'exotic', bulb.name end + def test_no_sql_should_be_fired_if_association_already_loaded + Car.create(:name => 'honda') + bulbs = Car.first.bulbs + bulbs.inspect # to load all instances of bulbs + assert_no_queries do + bulbs.first() + bulbs.first({}) + end + end + def test_create_resets_cached_counters person = Person.create!(:first_name => 'tenderlove') post = Post.first @@ -73,7 +83,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal [], person.readers assert_nil person.readers.find_by_post_id(post.id) - reader = person.readers.create(:post_id => post.id) + person.readers.create(:post_id => post.id) assert_equal 1, person.readers.count assert_equal 1, person.readers.length @@ -88,7 +98,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal [], person.readers assert_nil person.readers.find_by_post_id(post.id) - reader = person.readers.find_or_create_by_post_id(post.id) + person.readers.find_or_create_by_post_id(post.id) assert_equal 1, person.readers.count assert_equal 1, person.readers.length @@ -187,7 +197,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase another = author.posts.find_or_create_by_title_and_body("Another Post", "This is the Body") assert_equal number_of_posts + 1, Post.count assert_equal another, author.posts.find_or_create_by_title_and_body("Another Post", "This is the Body") - assert !another.new_record? + assert another.persisted? end def test_cant_save_has_many_readonly_association @@ -402,7 +412,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase 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") + 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 @@ -453,7 +463,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert !company.clients_of_firm.loaded? assert_equal "Another Client", new_client.name - assert new_client.new_record? + assert !new_client.persisted? assert_equal new_client, company.clients_of_firm.last end @@ -483,7 +493,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase end def test_build_followed_by_save_does_not_load_target - new_client = companies(:first_firm).clients_of_firm.build("name" => "Another 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 @@ -508,7 +518,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert !company.clients_of_firm.loaded? assert_equal "Another Client", new_client.name - assert new_client.new_record? + assert !new_client.persisted? assert_equal new_client, company.clients_of_firm.last end @@ -543,7 +553,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase 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 new_client.persisted? assert_equal new_client, companies(:first_firm).clients_of_firm.last assert_equal new_client, companies(:first_firm).clients_of_firm(true).last end @@ -554,7 +564,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase end def test_create_followed_by_save_does_not_load_target - new_client = companies(:first_firm).clients_of_firm.create("name" => "Another 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 @@ -563,7 +573,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase 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? + assert !the_client.persisted? end def test_find_or_create_updates_size @@ -752,7 +762,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase another_ms_client = companies(:first_firm).clients_like_ms_with_hash_conditions.create - assert !another_ms_client.new_record? + assert another_ms_client.persisted? assert_equal 'Microsoft', another_ms_client.name end @@ -852,7 +862,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase def test_dependence_for_associations_with_hash_condition david = authors(:david) - post = posts(:thinking).id assert_difference('Post.count', -1) { assert david.destroy } end @@ -872,7 +881,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase 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" + reply.replies.create "title" => "neat and simple", "content" => "ain't complaining" assert_nothing_raised { topic.destroy } end @@ -897,7 +906,6 @@ class HasManyAssociationsTest < ActiveRecord::TestCase 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 @@ -914,7 +922,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase def test_restrict firm = RestrictedFirm.new(:name => 'restrict') firm.save! - child_firm = firm.companies.create(:name => 'child') + firm.companies.create(:name => 'child') assert !firm.companies.empty? assert_raise(ActiveRecord::DeleteRestrictionError) { firm.destroy } end @@ -1273,4 +1281,25 @@ class HasManyAssociationsTest < ActiveRecord::TestCase comment = post.comments.build assert post.comments.include?(comment) end + + def test_load_target_respects_protected_attributes + topic = Topic.create! + reply = topic.replies.create(:title => "reply 1") + reply.approved = false + reply.save! + + # Save with a different object instance, so the instance that's still held + # in topic.relies doesn't know about the changed attribute. + reply2 = Reply.find(reply.id) + reply2.approved = true + reply2.save! + + # Force loading the collection from the db. This will merge the existing + # object (reply) with what gets loaded from the db (which includes the + # changed approved attribute). approved is a protected attribute, so if mass + # assignment is used, it won't get updated and will still be false. + first = topic.replies.to_a.first + assert_equal reply.id, first.id + assert_equal true, first.approved? + end end diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb index 4b9f49f1ec..52432b0428 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -354,7 +354,6 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase end def test_has_many_association_through_a_belongs_to_association_where_the_association_doesnt_exist - author = authors(:mary) post = Post.create!(:title => "TITLE", :body => "BODY") assert_equal [], post.author_favorites end @@ -449,4 +448,11 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase comment = post.comments.build assert author.comments.include?(comment) end + + def test_size_of_through_association_should_increase_correctly_when_has_many_association_is_added + post = posts(:thinking) + readers = post.readers.size + post.people << people(:michael) + assert_equal readers + 1, post.readers.size + end end diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb index b522be3fe0..64449df8f5 100644 --- a/activerecord/test/cases/associations/has_one_associations_test.rb +++ b/activerecord/test/cases/associations/has_one_associations_test.rb @@ -163,7 +163,6 @@ class HasOneAssociationsTest < ActiveRecord::TestCase firm = ExclusivelyDependentFirm.find(9) assert_not_nil firm.account - account_id = firm.account.id assert_equal [], Account.destroyed_account_ids[firm.id] firm.destroy @@ -180,7 +179,7 @@ class HasOneAssociationsTest < ActiveRecord::TestCase def test_dependence_with_restrict firm = RestrictedFirm.new(:name => 'restrict') firm.save! - account = firm.create_account(:credit_limit => 10) + firm.create_account(:credit_limit => 10) assert_not_nil firm.account assert_raise(ActiveRecord::DeleteRestrictionError) { firm.destroy } end @@ -197,8 +196,8 @@ class HasOneAssociationsTest < ActiveRecord::TestCase 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) + firm.build_account("credit_limit" => 1000) + firm.build_account("credit_limit" => 2000) assert_equal count_of_account, Account.count end @@ -268,7 +267,7 @@ class HasOneAssociationsTest < ActiveRecord::TestCase def test_assignment_before_child_saved firm = Firm.find(1) firm.account = a = Account.new("credit_limit" => 1000) - assert !a.new_record? + assert a.persisted? assert_equal a, firm.account assert_equal a, firm.account assert_equal a, firm.account(true) @@ -323,7 +322,7 @@ class HasOneAssociationsTest < ActiveRecord::TestCase def test_create_respects_hash_condition account = companies(:first_firm).create_account_limit_500_with_hash_conditions - assert !account.new_record? + assert account.persisted? assert_equal 500, account.credit_limit end diff --git a/activerecord/test/cases/associations/inner_join_association_test.rb b/activerecord/test/cases/associations/inner_join_association_test.rb index 4ba867dc7c..780eabc443 100644 --- a/activerecord/test/cases/associations/inner_join_association_test.rb +++ b/activerecord/test/cases/associations/inner_join_association_test.rb @@ -4,9 +4,12 @@ require 'models/comment' require 'models/author' require 'models/category' require 'models/categorization' +require 'models/tagging' +require 'models/tag' class InnerJoinAssociationTest < ActiveRecord::TestCase - fixtures :authors, :posts, :comments, :categories, :categories_posts, :categorizations + fixtures :authors, :posts, :comments, :categories, :categories_posts, :categorizations, + :taggings, :tags def test_construct_finder_sql_applies_aliases_tables_on_association_conditions result = Author.joins(:thinking_posts, :welcome_posts).to_a @@ -62,4 +65,23 @@ class InnerJoinAssociationTest < ActiveRecord::TestCase 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 + + def test_find_with_sti_join + scope = Post.joins(:special_comments).where(:id => posts(:sti_comments).id) + + # The join should match SpecialComment and its subclasses only + assert scope.where("comments.type" => "Comment").empty? + assert !scope.where("comments.type" => "SpecialComment").empty? + assert !scope.where("comments.type" => "SubSpecialComment").empty? + end + + def test_find_with_conditions_on_reflection + assert !posts(:welcome).comments.empty? + assert Post.joins(:nonexistant_comments).where(:id => posts(:welcome).id).empty? # [sic!] + end + + def test_find_with_conditions_on_through_reflection + assert !posts(:welcome).tags.empty? + assert Post.joins(:misc_tags).where(:id => posts(:welcome).id).empty? + end end diff --git a/activerecord/test/cases/associations/inverse_associations_test.rb b/activerecord/test/cases/associations/inverse_associations_test.rb index fa5c2e49df..0491b2d1fa 100644 --- a/activerecord/test/cases/associations/inverse_associations_test.rb +++ b/activerecord/test/cases/associations/inverse_associations_test.rb @@ -484,7 +484,6 @@ class InversePolymorphicBelongsToTests < ActiveRecord::TestCase def test_child_instance_should_be_shared_with_replaced_via_accessor_parent face = faces(:confused) - old_man = face.polymorphic_man new_man = Man.new assert_not_nil face.polymorphic_man @@ -499,7 +498,6 @@ class InversePolymorphicBelongsToTests < ActiveRecord::TestCase def test_child_instance_should_be_shared_with_replaced_via_method_parent face = faces(:confused) - old_man = face.polymorphic_man new_man = Man.new assert_not_nil face.polymorphic_man @@ -551,8 +549,8 @@ class InverseMultipleHasManyInversesForSameModel < ActiveRecord::TestCase def test_that_we_can_load_associations_that_have_the_same_reciprocal_name_from_different_models assert_nothing_raised(ActiveRecord::AssociationTypeMismatch) do i = Interest.find(:first) - z = i.zine - m = i.man + i.zine + i.man end end diff --git a/activerecord/test/cases/associations/join_model_test.rb b/activerecord/test/cases/associations/join_model_test.rb index f131dc01f6..1ece961d2e 100644 --- a/activerecord/test/cases/associations/join_model_test.rb +++ b/activerecord/test/cases/associations/join_model_test.rb @@ -406,7 +406,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase 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) + assert_equal [1,2,3,5,6,7,8,9,10,12], author.comments.collect(&:id) end end @@ -450,11 +450,11 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase 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 new_tag.persisted? #consistent with habtm! + assert saved_post.persisted? assert saved_post.tags.include?(new_tag) - assert !new_tag.new_record? + assert new_tag.persisted? assert saved_post.reload.tags(true).include?(new_tag) @@ -462,16 +462,16 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase saved_tag = tags(:general) new_post.tags << saved_tag - assert new_post.new_record? - assert !saved_tag.new_record? + assert !new_post.persisted? + assert saved_tag.persisted? assert new_post.tags.include?(saved_tag) new_post.save! - assert !new_post.new_record? + assert new_post.persisted? assert new_post.reload.tags(true).include?(saved_tag) - assert posts(:thinking).tags.build.new_record? - assert posts(:thinking).tags.new.new_record? + assert !posts(:thinking).tags.build.persisted? + assert !posts(:thinking).tags.new.persisted? end def test_create_associate_when_adding_to_has_many_through @@ -508,7 +508,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase def test_has_many_through_collection_size_doesnt_load_target_if_not_loaded author = authors(:david) - assert_equal 9, author.comments.size + assert_equal 10, author.comments.size assert !author.comments.loaded? end @@ -642,7 +642,7 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase def test_preload_nil_polymorphic_belongs_to assert_nothing_raised do - taggings = Tagging.find(:all, :include => :taggable, :conditions => ['taggable_type IS NULL']) + Tagging.find(:all, :include => :taggable, :conditions => ['taggable_type IS NULL']) end end diff --git a/activerecord/test/cases/associations_test.rb b/activerecord/test/cases/associations_test.rb index dd8152b219..83c605d2bb 100644 --- a/activerecord/test/cases/associations_test.rb +++ b/activerecord/test/cases/associations_test.rb @@ -120,7 +120,7 @@ class AssociationsTest < ActiveRecord::TestCase def test_force_reload_is_uncached firm = Firm.create!("name" => "A New Firm, Inc") - client = Client.create!("name" => "TheClient.com", :firm => firm) + Client.create!("name" => "TheClient.com", :firm => firm) ActiveRecord::Base.cache do firm.clients.each {} assert_queries(0) { assert_not_nil firm.clients.each {} } @@ -270,17 +270,17 @@ class OverridingAssociationsTest < ActiveRecord::TestCase 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) + callbacks = PeopleList.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) + callbacks = DifferentPeopleList.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) + callbacks = PeopleList.before_add_for_has_many assert_equal([:enlist], callbacks) - callbacks = DifferentPeopleList.read_inheritable_attribute(:before_add_for_has_many) + callbacks = DifferentPeopleList.before_add_for_has_many assert_equal([], callbacks) end diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb index 1750bf004a..bb0166a60c 100644 --- a/activerecord/test/cases/attribute_methods_test.rb +++ b/activerecord/test/cases/attribute_methods_test.rb @@ -103,7 +103,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase if current_adapter?(:MysqlAdapter) def test_read_attributes_before_type_cast_on_boolean bool = Boolean.create({ "value" => false }) - assert_equal "0", bool.reload.attributes_before_type_cast["value"] + assert_equal 0, bool.reload.attributes_before_type_cast["value"] end end @@ -112,7 +112,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase developer = Developer.find(:first) # Oracle adapter returns Time before type cast unless current_adapter?(:OracleAdapter) - assert_equal developer.created_at.to_s(:db) , developer.attributes_before_type_cast["created_at"] + assert_equal developer.created_at.to_s(:db) , developer.attributes_before_type_cast["created_at"].to_s else assert_equal developer.created_at.to_s(:db) , developer.attributes_before_type_cast["created_at"].to_s(:db) @@ -121,7 +121,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase assert_equal developer.created_at, nil developer.created_at = "2010-03-21 21:23:32" - assert_equal developer.created_at_before_type_cast, "2010-03-21 21:23:32" + assert_equal developer.created_at_before_type_cast.to_s, "2010-03-21 21:23:32" assert_equal developer.created_at, Time.parse("2010-03-21 21:23:32") end end @@ -568,7 +568,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase def test_bulk_update_respects_access_control privatize("title=(value)") - assert_raise(ActiveRecord::UnknownAttributeError) { topic = @target.new(:title => "Rants about pants") } + assert_raise(ActiveRecord::UnknownAttributeError) { @target.new(:title => "Rants about pants") } assert_raise(ActiveRecord::UnknownAttributeError) { @target.new.attributes = { :title => "Ants in pants" } } end diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb index 52382f5afc..fbf7121468 100644 --- a/activerecord/test/cases/autosave_association_test.rb +++ b/activerecord/test/cases/autosave_association_test.rb @@ -17,6 +17,7 @@ require 'models/tag' require 'models/tagging' require 'models/treasure' require 'models/company' +require 'models/eye' class TestAutosaveAssociationsInGeneral < ActiveRecord::TestCase def test_autosave_should_be_a_valid_option_for_has_one @@ -82,7 +83,7 @@ class TestDefaultAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCas assert !firm.build_account_using_primary_key.valid? assert firm.save - assert firm.account_using_primary_key.new_record? + assert !firm.account_using_primary_key.persisted? end def test_save_fails_for_invalid_has_one @@ -113,10 +114,10 @@ class TestDefaultAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCas account = firm.account.build("credit_limit" => 1000) assert_equal account, firm.account - assert account.new_record? + assert !account.persisted? assert firm.save assert_equal account, firm.account - assert !account.new_record? + assert account.persisted? end def test_build_before_either_saved @@ -124,16 +125,16 @@ class TestDefaultAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCas firm.account = account = Account.new("credit_limit" => 1000) assert_equal account, firm.account - assert account.new_record? + assert !account.persisted? assert firm.save assert_equal account, firm.account - assert !account.new_record? + assert account.persisted? end def test_assignment_before_parent_saved firm = Firm.new("name" => "GlobalMegaCorp") firm.account = a = Account.find(1) - assert firm.new_record? + assert !firm.persisted? assert_equal a, firm.account assert firm.save assert_equal a, firm.account @@ -143,12 +144,12 @@ class TestDefaultAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCas 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 !firm.persisted? + assert !a.persisted? assert_equal a, firm.account assert firm.save - assert !firm.new_record? - assert !a.new_record? + assert firm.persisted? + assert a.persisted? assert_equal a, firm.account assert_equal a, firm.account(true) end @@ -162,14 +163,33 @@ class TestDefaultAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCas firm.account = Account.find(:first) assert_queries(Firm.partial_updates? ? 0 : 1) { firm.save! } - firm = Firm.find(:first).clone + firm = Firm.find(:first).dup firm.account = Account.find(:first) assert_queries(2) { firm.save! } - firm = Firm.find(:first).clone - firm.account = Account.find(:first).clone + firm = Firm.find(:first).dup + firm.account = Account.find(:first).dup assert_queries(2) { firm.save! } end + + def test_callbacks_firing_order_on_create + eye = Eye.create(:iris_attributes => {:color => 'honey'}) + assert_equal [true, false], eye.after_create_callbacks_stack + end + + def test_callbacks_firing_order_on_update + eye = Eye.create(:iris_attributes => {:color => 'honey'}) + eye.update_attributes(:iris_attributes => {:color => 'green'}) + assert_equal [true, false], eye.after_update_callbacks_stack + end + + def test_callbacks_firing_order_on_save + eye = Eye.create(:iris_attributes => {:color => 'honey'}) + assert_equal [false, false], eye.after_save_callbacks_stack + + eye.update_attributes(:iris_attributes => {:color => 'blue'}) + assert_equal [false, false, false, false], eye.after_save_callbacks_stack + end end class TestDefaultAutosaveAssociationOnABelongsToAssociation < ActiveRecord::TestCase @@ -183,7 +203,7 @@ class TestDefaultAutosaveAssociationOnABelongsToAssociation < ActiveRecord::Test assert !client.firm.valid? assert client.save - assert client.firm.new_record? + assert !client.firm.persisted? end def test_save_fails_for_invalid_belongs_to @@ -212,10 +232,10 @@ class TestDefaultAutosaveAssociationOnABelongsToAssociation < ActiveRecord::Test apple = Firm.new("name" => "Apple") client.firm = apple assert_equal apple, client.firm - assert apple.new_record? + assert !apple.persisted? assert client.save assert apple.save - assert !apple.new_record? + assert apple.persisted? assert_equal apple, client.firm assert_equal apple, client.firm(true) end @@ -224,11 +244,11 @@ class TestDefaultAutosaveAssociationOnABelongsToAssociation < ActiveRecord::Test 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.persisted? + assert !apple.persisted? assert final_cut.save - assert !final_cut.new_record? - assert !apple.new_record? + assert final_cut.persisted? + assert apple.persisted? assert_equal apple, final_cut.firm assert_equal apple, final_cut.firm(true) end @@ -328,23 +348,21 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCa def test_invalid_adding firm = Firm.find(1) assert !(firm.clients_of_firm << c = Client.new) - assert c.new_record? + assert !c.persisted? assert !firm.valid? assert !firm.save - assert c.new_record? + assert !c.persisted? 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.persisted? assert !c.valid? assert !new_firm.valid? assert !new_firm.save - assert c.new_record? - assert new_firm.new_record? + assert !c.persisted? + assert !new_firm.persisted? end def test_invalid_adding_with_validate_false @@ -355,7 +373,7 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCa assert firm.valid? assert !client.valid? assert firm.save - assert client.new_record? + assert !client.persisted? end def test_valid_adding_with_validate_false @@ -366,22 +384,22 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCa assert firm.valid? assert client.valid? - assert client.new_record? + assert !client.persisted? firm.unvalidated_clients_of_firm << client assert firm.save - assert !client.new_record? + assert client.persisted? assert_equal no_of_clients + 1, Client.count end def test_invalid_build new_client = companies(:first_firm).clients_of_firm.build - assert new_client.new_record? + assert !new_client.persisted? 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 !new_client.persisted? assert_equal 1, companies(:first_firm).clients_of_firm(true).size end @@ -400,8 +418,8 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCa 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 new_firm.persisted? + assert c.persisted? 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. @@ -435,13 +453,13 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCa company.name += '-changed' assert_queries(2) { assert company.save } - assert !new_client.new_record? + assert new_client.persisted? assert_equal 2, company.clients_of_firm(true).size end def test_build_many_before_save company = companies(:first_firm) - new_clients = assert_no_queries { company.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) } + assert_no_queries { company.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) } company.name += '-changed' assert_queries(3) { assert company.save } @@ -455,13 +473,13 @@ class TestDefaultAutosaveAssociationOnAHasManyAssociation < ActiveRecord::TestCa company.name += '-changed' assert_queries(2) { assert company.save } - assert !new_client.new_record? + assert new_client.persisted? assert_equal 2, company.clients_of_firm(true).size end def test_build_many_via_block_before_save company = companies(:first_firm) - new_clients = assert_no_queries do + assert_no_queries do company.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) do |client| client.name = "changed" end @@ -487,62 +505,62 @@ class TestDefaultAutosaveAssociationOnNewRecord < ActiveRecord::TestCase new_account = Account.new("credit_limit" => 1000) new_firm = Firm.new("name" => "some firm") - assert new_firm.new_record? + assert !new_firm.persisted? new_account.firm = new_firm new_account.save! - assert !new_firm.new_record? + assert new_firm.persisted? new_account = Account.new("credit_limit" => 1000) new_autosaved_firm = Firm.new("name" => "some firm") - assert new_autosaved_firm.new_record? + assert !new_autosaved_firm.persisted? new_account.unautosaved_firm = new_autosaved_firm new_account.save! - assert new_autosaved_firm.new_record? + assert !new_autosaved_firm.persisted? end def test_autosave_new_record_on_has_one_can_be_disabled_per_relationship firm = Firm.new("name" => "some firm") account = Account.new("credit_limit" => 1000) - assert account.new_record? + assert !account.persisted? firm.account = account firm.save! - assert !account.new_record? + assert account.persisted? firm = Firm.new("name" => "some firm") account = Account.new("credit_limit" => 1000) firm.unautosaved_account = account - assert account.new_record? + assert !account.persisted? firm.unautosaved_account = account firm.save! - assert account.new_record? + assert !account.persisted? end def test_autosave_new_record_on_has_many_can_be_disabled_per_relationship firm = Firm.new("name" => "some firm") account = Account.new("credit_limit" => 1000) - assert account.new_record? + assert !account.persisted? firm.accounts << account firm.save! - assert !account.new_record? + assert account.persisted? firm = Firm.new("name" => "some firm") account = Account.new("credit_limit" => 1000) - assert account.new_record? + assert !account.persisted? firm.unautosaved_accounts << account firm.save! - assert account.new_record? + assert !account.persisted? end end diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index 16fd9a7465..c3ba1f0c35 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -48,6 +48,11 @@ class Boolean < ActiveRecord::Base; end class BasicsTest < ActiveRecord::TestCase fixtures :topics, :companies, :developers, :projects, :computers, :accounts, :minimalistics, 'warehouse-things', :authors, :categorizations, :categories, :posts + def test_select_symbol + topic_ids = Topic.select(:id).map(&:id).sort + assert_equal Topic.find(:all).map(&:id).sort, topic_ids + end + def test_table_exists assert !NonExistentTable.table_exists? assert Topic.table_exists? @@ -177,7 +182,7 @@ class BasicsTest < ActiveRecord::TestCase def test_initialize_with_invalid_attribute begin - topic = Topic.new({ "title" => "test", + Topic.new({ "title" => "test", "last_read(1i)" => "2005", "last_read(2i)" => "2", "last_read(3i)" => "31"}) rescue ActiveRecord::MultiparameterAssignmentErrors => ex assert_equal(1, ex.errors.size) @@ -392,6 +397,15 @@ class BasicsTest < ActiveRecord::TestCase assert_not_equal Topic.new, Topic.new end + def test_equality_of_destroyed_records + topic_1 = Topic.new(:title => 'test_1') + topic_1.save + topic_2 = Topic.find(topic_1.id) + topic_1.destroy + assert_equal topic_1, topic_2 + assert_equal topic_2, topic_1 + end + def test_hashing assert_equal [ Topic.find(1) ], [ Topic.find(2).topic ] & [ Topic.find(1) ] end @@ -651,68 +665,69 @@ class BasicsTest < ActiveRecord::TestCase end def test_new_record_returns_boolean - assert_equal true, Topic.new.new_record? - assert_equal false, Topic.find(1).new_record? + assert_equal false, Topic.new.persisted? + assert_equal true, Topic.find(1).persisted? end - def test_clone + def test_dup topic = Topic.find(1) - cloned_topic = nil - assert_nothing_raised { cloned_topic = topic.clone } - assert_equal topic.title, cloned_topic.title - assert cloned_topic.new_record? + duped_topic = nil + assert_nothing_raised { duped_topic = topic.dup } + assert_equal topic.title, duped_topic.title + assert !duped_topic.persisted? - # test if the attributes have been cloned + # test if the attributes have been duped topic.title = "a" - cloned_topic.title = "b" + duped_topic.title = "b" assert_equal "a", topic.title - assert_equal "b", cloned_topic.title + assert_equal "b", duped_topic.title - # test if the attribute values have been cloned + # test if the attribute values have been duped topic.title = {"a" => "b"} - cloned_topic = topic.clone - cloned_topic.title["a"] = "c" + duped_topic = topic.dup + duped_topic.title["a"] = "c" assert_equal "b", topic.title["a"] - # test if attributes set as part of after_initialize are cloned correctly - assert_equal topic.author_email_address, cloned_topic.author_email_address + # test if attributes set as part of after_initialize are duped correctly + assert_equal topic.author_email_address, duped_topic.author_email_address # test if saved clone object differs from original - cloned_topic.save - assert !cloned_topic.new_record? - assert_not_equal cloned_topic.id, topic.id + duped_topic.save + assert duped_topic.persisted? + assert_not_equal duped_topic.id, topic.id - cloned_topic.reload + duped_topic.reload # FIXME: I think this is poor behavior, and will fix it with #5686 - assert_equal({'a' => 'c'}.to_s, cloned_topic.title) + assert_equal({'a' => 'c'}.to_s, duped_topic.title) end - def test_clone_with_aggregate_of_same_name_as_attribute + def test_dup_with_aggregate_of_same_name_as_attribute dev = DeveloperWithAggregate.find(1) assert_kind_of DeveloperSalary, dev.salary - clone = nil - assert_nothing_raised { clone = dev.clone } - assert_kind_of DeveloperSalary, clone.salary - assert_equal dev.salary.amount, clone.salary.amount - assert clone.new_record? + dup = nil + assert_nothing_raised { dup = dev.dup } + assert_kind_of DeveloperSalary, dup.salary + assert_equal dev.salary.amount, dup.salary.amount + assert !dup.persisted? - # test if the attributes have been cloned - original_amount = clone.salary.amount + # test if the attributes have been dupd + original_amount = dup.salary.amount dev.salary.amount = 1 - assert_equal original_amount, clone.salary.amount + assert_equal original_amount, dup.salary.amount - assert clone.save - assert !clone.new_record? - assert_not_equal clone.id, dev.id + assert dup.save + assert dup.persisted? + assert_not_equal dup.id, dev.id end - def test_clone_does_not_clone_associations + def test_dup_does_not_copy_associations author = authors(:david) assert_not_equal [], author.posts + author.send(:clear_association_cache) - author_clone = author.clone - assert_equal [], author_clone.posts + author_dup = author.dup + assert_equal [], author_dup.posts end def test_clone_preserves_subtype @@ -751,22 +766,22 @@ class BasicsTest < ActiveRecord::TestCase assert !cloned_developer.salary_changed? # ... and cloned instance should behave same end - def test_clone_of_saved_object_marks_attributes_as_dirty + def test_dup_of_saved_object_marks_attributes_as_dirty developer = Developer.create! :name => 'Bjorn', :salary => 100000 assert !developer.name_changed? assert !developer.salary_changed? - cloned_developer = developer.clone + cloned_developer = developer.dup assert cloned_developer.name_changed? # both attributes differ from defaults assert cloned_developer.salary_changed? end - def test_clone_of_saved_object_marks_as_dirty_only_changed_attributes + def test_dup_of_saved_object_marks_as_dirty_only_changed_attributes developer = Developer.create! :name => 'Bjorn' assert !developer.name_changed? # both attributes of saved object should be threated as not changed assert !developer.salary_changed? - cloned_developer = developer.clone + cloned_developer = developer.dup assert cloned_developer.name_changed? # ... but on cloned object should be assert !cloned_developer.salary_changed? # ... BUT salary has non-nil default which should be threated as not changed on cloned instance end @@ -958,7 +973,6 @@ class BasicsTest < ActiveRecord::TestCase end def test_nil_serialized_attribute_with_class_constraint - myobj = MyObject.new('value1', 'value2') topic = Topic.new assert_nil topic.content end @@ -1145,6 +1159,12 @@ class BasicsTest < ActiveRecord::TestCase assert_equal 3, scoped_developers.size end + def test_no_limit_offset + assert_nothing_raised do + Developer.find(:all, :offset => 2) + end + end + def test_scoped_find_limit_offset scoped_developers = Developer.send(:with_scope, :find => { :limit => 3, :offset => 2 }) do Developer.find(:all, :order => 'id') @@ -1342,7 +1362,7 @@ class BasicsTest < ActiveRecord::TestCase def test_inspect_instance topic = topics(:first) - assert_equal %(#<Topic id: 1, title: "The First Topic", author_name: "David", author_email_address: "david@loudthinking.com", written_on: "#{topic.written_on.to_s(:db)}", bonus_time: "#{topic.bonus_time.to_s(:db)}", last_read: "#{topic.last_read.to_s(:db)}", content: "Have a nice day", approved: false, replies_count: 1, parent_id: nil, parent_title: nil, type: nil, group: nil>), topic.inspect + assert_equal %(#<Topic id: 1, title: "The First Topic", author_name: "David", author_email_address: "david@loudthinking.com", written_on: "#{topic.written_on.to_s(:db)}", bonus_time: "#{topic.bonus_time.to_s(:db)}", last_read: "#{topic.last_read.to_s(:db)}", content: "Have a nice day", approved: false, replies_count: 1, parent_id: nil, parent_title: nil, type: nil, group: nil, created_at: "#{topic.created_at.to_s(:db)}", updated_at: "#{topic.updated_at.to_s(:db)}">), topic.inspect end def test_inspect_new_instance @@ -1424,10 +1444,6 @@ class BasicsTest < ActiveRecord::TestCase ActiveRecord::Base.logger = original_logger end - def test_dup - assert !Minimalistic.new.freeze.dup.frozen? - end - def test_compute_type_success assert_equal Author, ActiveRecord::Base.send(:compute_type, 'Author') end @@ -1451,6 +1467,7 @@ class BasicsTest < ActiveRecord::TestCase UnloadablePost.class_eval do default_scope order('posts.comments_count ASC') end + UnloadablePost.scoped_methods # make Thread.current[:UnloadablePost_scoped_methods] not nil UnloadablePost.unloadable assert_not_nil Thread.current[:UnloadablePost_scoped_methods] diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index 7ec40906d4..5cb8485b4b 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -54,6 +54,19 @@ class CalculationsTest < ActiveRecord::TestCase 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_multiple_fields + c = Account.count(:all, :group => ['firm_id', :credit_limit]) + [ [nil, 50], [1, 50], [6, 50], [6, 55], [9, 53], [2, 60] ].each { |firm_and_limit| assert c.keys.include?(firm_and_limit) } + end + + def test_should_group_by_multiple_fields_having_functions + c = Topic.group(:author_name, 'COALESCE(type, title)').count(:all) + assert_equal 1, c[["Carl", "The Third Topic of the day"]] + assert_equal 1, c[["Mary", "Reply"]] + assert_equal 1, c[["David", "The First Topic"]] + assert_equal 1, c[["Carl", "Reply"]] + end def test_should_group_by_summed_field c = Account.sum(:credit_limit, :group => :firm_id) @@ -346,4 +359,13 @@ class CalculationsTest < ActiveRecord::TestCase def test_from_option_with_table_different_than_class assert_equal Account.count(:all), Company.count(:all, :from => 'accounts') end + + def test_distinct_is_honored_when_used_with_count_operation_after_group + # Count the number of authors for approved topics + approved_topics_count = Topic.group(:approved).count(:author_name)[true] + assert_equal approved_topics_count, 3 + # Count the number of distinct authors for approved Topics + distinct_authors_for_approved_count = Topic.group(:approved).count(:author_name, :distinct => true)[true] + assert_equal distinct_authors_for_approved_count, 2 + end end diff --git a/activerecord/test/cases/clone_test.rb b/activerecord/test/cases/clone_test.rb new file mode 100644 index 0000000000..d91646efca --- /dev/null +++ b/activerecord/test/cases/clone_test.rb @@ -0,0 +1,33 @@ +require "cases/helper" +require 'models/topic' + +module ActiveRecord + class CloneTest < ActiveRecord::TestCase + fixtures :topics + + def test_persisted + topic = Topic.first + cloned = topic.clone + assert topic.persisted?, 'topic persisted' + assert cloned.persisted?, 'topic persisted' + assert !cloned.new_record?, 'topic is not new' + end + + def test_stays_frozen + topic = Topic.first + topic.freeze + + cloned = topic.clone + assert cloned.persisted?, 'topic persisted' + assert !cloned.new_record?, 'topic is not new' + assert cloned.frozen?, 'topic should be frozen' + end + + def test_shallow + topic = Topic.first + cloned = topic.clone + topic.author_name = 'Aaron' + assert_equal 'Aaron', cloned.author_name + end + end +end diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb index bde93d1c85..a6738fb654 100644 --- a/activerecord/test/cases/dirty_test.rb +++ b/activerecord/test/cases/dirty_test.rb @@ -338,13 +338,13 @@ class DirtyTest < ActiveRecord::TestCase assert !pirate.changed? end - def test_cloned_objects_should_not_copy_dirty_flag_from_creator + def test_dup_objects_should_not_copy_dirty_flag_from_creator pirate = Pirate.create!(:catchphrase => "shiver me timbers") - pirate_clone = pirate.clone - pirate_clone.reset_catchphrase! + pirate_dup = pirate.dup + pirate_dup.reset_catchphrase! pirate.catchphrase = "I love Rum" assert pirate.catchphrase_changed? - assert !pirate_clone.catchphrase_changed? + assert !pirate_dup.catchphrase_changed? end def test_reverted_changes_are_not_dirty @@ -395,6 +395,20 @@ class DirtyTest < ActiveRecord::TestCase end end + def test_save_always_should_update_timestamps_when_serialized_attributes_are_present + with_partial_updates(Topic) do + topic = Topic.create!(:content => {:a => "a"}) + topic.save! + + updated_at = topic.updated_at + topic.content[:hello] = 'world' + topic.save! + + assert_not_equal updated_at, topic.updated_at + assert_equal 'world', topic.content[:hello] + end + end + def test_save_should_not_save_serialized_attribute_with_partial_updates_if_not_present with_partial_updates(Topic) do Topic.create!(:author_name => 'Bill', :content => {:a => "a"}) diff --git a/activerecord/test/cases/dup_test.rb b/activerecord/test/cases/dup_test.rb new file mode 100644 index 0000000000..0236f9b0a1 --- /dev/null +++ b/activerecord/test/cases/dup_test.rb @@ -0,0 +1,103 @@ +require "cases/helper" +require 'models/topic' + +module ActiveRecord + class DupTest < ActiveRecord::TestCase + fixtures :topics + + def test_dup + assert !Topic.new.freeze.dup.frozen? + end + + def test_not_readonly + topic = Topic.first + + duped = topic.dup + assert !duped.readonly?, 'should not be readonly' + end + + def test_is_readonly + topic = Topic.first + topic.readonly! + + duped = topic.dup + assert duped.readonly?, 'should be readonly' + end + + def test_dup_not_persisted + topic = Topic.first + duped = topic.dup + + assert !duped.persisted?, 'topic not persisted' + assert duped.new_record?, 'topic is new' + end + + def test_dup_has_no_id + topic = Topic.first + duped = topic.dup + assert_nil duped.id + end + + def test_dup_with_modified_attributes + topic = Topic.first + topic.author_name = 'Aaron' + duped = topic.dup + assert_equal 'Aaron', duped.author_name + end + + def test_dup_with_changes + dbtopic = Topic.first + topic = Topic.new + + topic.attributes = dbtopic.attributes + + #duped has no timestamp values + duped = dbtopic.dup + + #clear topic timestamp values + topic.send(:clear_timestamp_attributes) + + assert_equal topic.changes, duped.changes + end + + def test_dup_topics_are_independent + topic = Topic.first + topic.author_name = 'Aaron' + duped = topic.dup + + duped.author_name = 'meow' + + assert_not_equal topic.changes, duped.changes + end + + def test_dup_attributes_are_independent + topic = Topic.first + duped = topic.dup + + duped.author_name = 'meow' + topic.author_name = 'Aaron' + + assert_equal 'Aaron', topic.author_name + assert_equal 'meow', duped.author_name + end + + def test_dup_timestamps_are_cleared + topic = Topic.first + assert_not_nil topic.updated_at + assert_not_nil topic.created_at + + # temporary change to the topic object + topic.updated_at -= 3.days + + #dup should not preserve the timestamps if present + new_topic = topic.dup + assert_nil new_topic.updated_at + assert_nil new_topic.created_at + + new_topic.save + assert_not_nil new_topic.updated_at + assert_not_nil new_topic.created_at + end + + end +end diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb index 26b5096255..31e4981a1d 100644 --- a/activerecord/test/cases/finder_test.rb +++ b/activerecord/test/cases/finder_test.rb @@ -10,6 +10,7 @@ require 'models/entrant' require 'models/project' require 'models/developer' require 'models/customer' +require 'models/toy' class FinderTest < ActiveRecord::TestCase fixtures :companies, :topics, :entrants, :developers, :developers_projects, :posts, :comments, :accounts, :authors, :customers, :categories, :categorizations @@ -259,7 +260,7 @@ class FinderTest < ActiveRecord::TestCase 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 + assert_equal [1, 2, 3, 5, 6, 7, 8, 9, 10, 12], Comment.find_all_by_post_id(authors(:david).posts).map(&:id).sort end def test_find_on_hash_conditions_with_range @@ -726,7 +727,7 @@ class FinderTest < ActiveRecord::TestCase sig38 = Company.find_or_create_by_name("38signals") assert_equal number_of_companies + 1, Company.count assert_equal sig38, Company.find_or_create_by_name("38signals") - assert !sig38.new_record? + assert sig38.persisted? end def test_find_or_create_from_two_attributes @@ -734,7 +735,7 @@ class FinderTest < ActiveRecord::TestCase another = Topic.find_or_create_by_title_and_author_name("Another topic","John") assert_equal number_of_topics + 1, Topic.count assert_equal another, Topic.find_or_create_by_title_and_author_name("Another topic", "John") - assert !another.new_record? + assert another.persisted? end def test_find_or_create_from_two_attributes_with_one_being_an_aggregate @@ -742,7 +743,7 @@ class FinderTest < ActiveRecord::TestCase 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? + assert created_customer.persisted? end def test_find_or_create_from_one_attribute_and_hash @@ -750,7 +751,7 @@ class FinderTest < ActiveRecord::TestCase 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 sig38.persisted? assert_equal "38signals", sig38.name assert_equal 17, sig38.firm_id assert_equal 23, sig38.client_of @@ -761,7 +762,7 @@ class FinderTest < ActiveRecord::TestCase 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? + assert created_customer.persisted? end def test_find_or_create_from_one_aggregate_attribute_and_hash @@ -771,7 +772,7 @@ class FinderTest < ActiveRecord::TestCase 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 created_customer.persisted? assert_equal balance, created_customer.balance assert_equal name, created_customer.name end @@ -779,13 +780,13 @@ class FinderTest < ActiveRecord::TestCase 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? + assert !sig38.persisted? 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? + assert !new_customer.persisted? end def test_find_or_initialize_from_one_attribute_should_not_set_attribute_even_when_protected @@ -793,7 +794,7 @@ class FinderTest < ActiveRecord::TestCase assert_equal "Fortune 1000", c.name assert_not_equal 1000, c.rating assert c.valid? - assert c.new_record? + assert !c.persisted? end def test_find_or_create_from_one_attribute_should_not_set_attribute_even_when_protected @@ -801,7 +802,7 @@ class FinderTest < ActiveRecord::TestCase assert_equal "Fortune 1000", c.name assert_not_equal 1000, c.rating assert c.valid? - assert !c.new_record? + assert c.persisted? end def test_find_or_initialize_from_one_attribute_should_set_attribute_even_when_protected @@ -809,7 +810,7 @@ class FinderTest < ActiveRecord::TestCase assert_equal "Fortune 1000", c.name assert_equal 1000, c.rating assert c.valid? - assert c.new_record? + assert !c.persisted? end def test_find_or_create_from_one_attribute_should_set_attribute_even_when_protected @@ -817,7 +818,7 @@ class FinderTest < ActiveRecord::TestCase assert_equal "Fortune 1000", c.name assert_equal 1000, c.rating assert c.valid? - assert !c.new_record? + assert c.persisted? end def test_find_or_initialize_from_one_attribute_should_set_attribute_even_when_protected_and_also_set_the_hash @@ -825,7 +826,7 @@ class FinderTest < ActiveRecord::TestCase assert_equal "Fortune 1000", c.name assert_equal 1000, c.rating assert c.valid? - assert c.new_record? + assert !c.persisted? end def test_find_or_create_from_one_attribute_should_set_attribute_even_when_protected_and_also_set_the_hash @@ -833,7 +834,7 @@ class FinderTest < ActiveRecord::TestCase assert_equal "Fortune 1000", c.name assert_equal 1000, c.rating assert c.valid? - assert !c.new_record? + assert c.persisted? end def test_find_or_initialize_should_set_protected_attributes_if_given_as_block @@ -841,7 +842,7 @@ class FinderTest < ActiveRecord::TestCase assert_equal "Fortune 1000", c.name assert_equal 1000.to_f, c.rating.to_f assert c.valid? - assert c.new_record? + assert !c.persisted? end def test_find_or_create_should_set_protected_attributes_if_given_as_block @@ -849,7 +850,7 @@ class FinderTest < ActiveRecord::TestCase assert_equal "Fortune 1000", c.name assert_equal 1000.to_f, c.rating.to_f assert c.valid? - assert !c.new_record? + assert c.persisted? end def test_find_or_create_should_work_with_block_on_first_call @@ -860,21 +861,21 @@ class FinderTest < ActiveRecord::TestCase assert_equal "Fortune 1000", c.name assert_equal 1000.to_f, c.rating.to_f assert c.valid? - assert !c.new_record? + assert c.persisted? 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? + assert !another.persisted? 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? + assert !new_customer.persisted? end def test_find_or_initialize_from_one_attribute_and_hash @@ -882,7 +883,7 @@ class FinderTest < ActiveRecord::TestCase assert_equal "38signals", sig38.name assert_equal 17, sig38.firm_id assert_equal 23, sig38.client_of - assert sig38.new_record? + assert !sig38.persisted? end def test_find_or_initialize_from_one_aggregate_attribute_and_hash @@ -891,7 +892,7 @@ class FinderTest < ActiveRecord::TestCase 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? + assert !new_customer.persisted? end def test_find_with_bad_sql @@ -948,7 +949,7 @@ class FinderTest < ActiveRecord::TestCase # http://dev.rubyonrails.org/ticket/6778 def test_find_ignores_previously_inserted_record - post = Post.create!(:title => 'test', :body => 'it out') + Post.create!(:title => 'test', :body => 'it out') assert_equal [], Post.find_all_by_id(nil) end @@ -1010,6 +1011,15 @@ class FinderTest < ActiveRecord::TestCase end end + def test_find_one_message_with_custom_primary_key + Toy.set_primary_key :name + begin + Toy.find 'Hello World!' + rescue ActiveRecord::RecordNotFound => e + assert_equal 'Couldn\'t find Toy with name=Hello World!', e.message + end + end + protected def bind(statement, *vars) if vars.first.is_a?(Hash) diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb index d5ef30e137..9ce163a00f 100644 --- a/activerecord/test/cases/fixtures_test.rb +++ b/activerecord/test/cases/fixtures_test.rb @@ -58,7 +58,7 @@ class FixturesTest < ActiveRecord::TestCase end def test_inserts - topics = create_fixtures("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"]) @@ -114,7 +114,7 @@ class FixturesTest < ActiveRecord::TestCase end def test_insert_with_datetime - topics = create_fixtures("tasks") + create_fixtures("tasks") first = Task.find(1) assert first end @@ -240,7 +240,7 @@ if Account.connection.respond_to?(:reset_pk_sequence!) 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)| + max_id = create_fixtures(instance.class.table_name).inject(0) do |_max_id, (_, fixture)| fixture_id = fixture['id'].to_i fixture_id > _max_id ? fixture_id : _max_id end diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb index 2d3047c875..f9bbc5299b 100644 --- a/activerecord/test/cases/helper.rb +++ b/activerecord/test/cases/helper.rb @@ -13,11 +13,6 @@ require 'active_record' require 'active_support/dependencies' require 'connection' -begin - require 'ruby-debug' -rescue LoadError -end - # Show backtraces for deprecated behavior for quicker cleanup. ActiveSupport::Deprecation.debug = true @@ -48,6 +43,10 @@ end ActiveRecord::Base.connection.class.class_eval do IGNORED_SQL = [/^PRAGMA/, /^SELECT currval/, /^SELECT CAST/, /^SELECT @@IDENTITY/, /^SELECT @@ROWCOUNT/, /^SAVEPOINT/, /^ROLLBACK TO SAVEPOINT/, /^RELEASE SAVEPOINT/, /SHOW FIELDS/] + # FIXME: this needs to be refactored so specific database can add their own + # ignored SQL. This ignored SQL is for Oracle. + IGNORED_SQL.concat [/^select .*nextval/i, /^SAVEPOINT/, /^ROLLBACK TO/, /^\s*select .* from ((all|user)_tab_columns|(all|user)_triggers|(all|user)_constraints)/im] + def execute_with_query_record(sql, name = nil, &block) $queries_executed ||= [] $queries_executed << sql unless IGNORED_SQL.any? { |r| sql =~ r } @@ -55,6 +54,14 @@ ActiveRecord::Base.connection.class.class_eval do end alias_method_chain :execute, :query_record + + def exec_query_with_query_record(sql, name = nil, binds = [], &block) + $queries_executed ||= [] + $queries_executed << sql unless IGNORED_SQL.any? { |r| sql =~ r } + exec_query_without_query_record(sql, name, binds, &block) + end + + alias_method_chain :exec_query, :query_record end ActiveRecord::Base.connection.class.class_eval { diff --git a/activerecord/test/cases/inheritance_test.rb b/activerecord/test/cases/inheritance_test.rb index 31679b2efe..c3da9cdf53 100644 --- a/activerecord/test/cases/inheritance_test.rb +++ b/activerecord/test/cases/inheritance_test.rb @@ -16,7 +16,7 @@ class InheritanceTest < ActiveRecord::TestCase def test_class_with_blank_sti_name company = Company.find(:first) - company = company.clone + company = company.dup company.extend(Module.new { def read_attribute(name) return ' ' if name == 'type' diff --git a/activerecord/test/cases/invertible_migration_test.rb b/activerecord/test/cases/invertible_migration_test.rb new file mode 100644 index 0000000000..afec64750e --- /dev/null +++ b/activerecord/test/cases/invertible_migration_test.rb @@ -0,0 +1,57 @@ +require "cases/helper" + +module ActiveRecord + class InvertibleMigrationTest < ActiveRecord::TestCase + class SilentMigration < ActiveRecord::Migration + def write(text = '') + # sssshhhhh!! + end + end + + class InvertibleMigration < SilentMigration + def change + create_table("horses") do |t| + t.column :content, :text + t.column :remind_at, :datetime + end + end + end + + class NonInvertibleMigration < SilentMigration + def change + create_table("horses") do |t| + t.column :content, :text + t.column :remind_at, :datetime + end + remove_column "horses", :content + end + end + + def teardown + if ActiveRecord::Base.connection.table_exists?("horses") + ActiveRecord::Base.connection.drop_table("horses") + end + end + + def test_no_reverse + migration = NonInvertibleMigration.new + migration.migrate(:up) + assert_raises(IrreversibleMigration) do + migration.migrate(:down) + end + end + + def test_up + migration = InvertibleMigration.new + migration.migrate(:up) + assert migration.connection.table_exists?("horses"), "horses should exist" + end + + def test_down + migration = InvertibleMigration.new + migration.migrate :up + migration.migrate :down + assert !migration.connection.table_exists?("horses") + end + end +end diff --git a/activerecord/test/cases/locking_test.rb b/activerecord/test/cases/locking_test.rb index e7126964cd..f9678cb0c5 100644 --- a/activerecord/test/cases/locking_test.rb +++ b/activerecord/test/cases/locking_test.rb @@ -1,3 +1,4 @@ +require 'thread' require "cases/helper" require 'models/person' require 'models/reader' @@ -257,6 +258,7 @@ unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter) fixtures :people, :readers def setup + Person.connection_pool.clear_reloadable_connections! # Avoid introspection queries during tests. Person.columns; Reader.columns end @@ -306,8 +308,6 @@ unless current_adapter?(:SybaseAdapter, :OpenBaseAdapter) end if current_adapter?(:PostgreSQLAdapter, :OracleAdapter) - use_concurrent_connections - def test_no_locks_no_wait first, second = duel { Person.find 1 } assert first.end > second.end diff --git a/activerecord/test/cases/method_scoping_test.rb b/activerecord/test/cases/method_scoping_test.rb index f3d3d62830..0ffd0e2ab3 100644 --- a/activerecord/test/cases/method_scoping_test.rb +++ b/activerecord/test/cases/method_scoping_test.rb @@ -226,6 +226,12 @@ class MethodScopingTest < ActiveRecord::TestCase assert Post.find(1).comments.include?(new_comment) end + def test_scoped_create_with_join_and_merge + (Comment.where(:body => "but Who's Buying?").joins(:post) & Post.where(:body => 'Peace Sells...')).with_scope do + assert_equal({:body => "but Who's Buying?"}, Comment.scoped.scope_for_create) + end + end + def test_immutable_scope options = { :conditions => "name = 'David'" } Developer.send(:with_scope, :find => options) do diff --git a/activerecord/test/cases/migration/command_recorder_test.rb b/activerecord/test/cases/migration/command_recorder_test.rb new file mode 100644 index 0000000000..ea2292dda5 --- /dev/null +++ b/activerecord/test/cases/migration/command_recorder_test.rb @@ -0,0 +1,108 @@ +require "cases/helper" + +module ActiveRecord + class Migration + class CommandRecorderTest < ActiveRecord::TestCase + def setup + @recorder = CommandRecorder.new + end + + def test_respond_to_delegates + recorder = CommandRecorder.new(Class.new { + def america; end + }.new) + assert recorder.respond_to?(:america) + end + + def test_send_calls_super + assert_raises(NoMethodError) do + @recorder.send(:create_table, :horses) + end + end + + def test_send_delegates_to_record + recorder = CommandRecorder.new(Class.new { + def create_table(name); end + }.new) + assert recorder.respond_to?(:create_table), 'respond_to? create_table' + recorder.send(:create_table, :horses) + assert_equal [[:create_table, [:horses]]], recorder.commands + end + + def test_unknown_commands_raise_exception + @recorder.record :execute, ['some sql'] + assert_raises(ActiveRecord::IrreversibleMigration) do + @recorder.inverse + end + end + + def test_record + @recorder.record :create_table, [:system_settings] + assert_equal 1, @recorder.commands.length + end + + def test_inverse + @recorder.record :create_table, [:system_settings] + assert_equal 1, @recorder.inverse.length + + @recorder.record :rename_table, [:old, :new] + assert_equal 2, @recorder.inverse.length + end + + def test_inverted_commands_are_reveresed + @recorder.record :create_table, [:hello] + @recorder.record :create_table, [:world] + tables = @recorder.inverse.map(&:last) + assert_equal [[:world], [:hello]], tables + end + + def test_invert_create_table + @recorder.record :create_table, [:system_settings] + drop_table = @recorder.inverse.first + assert_equal [:drop_table, [:system_settings]], drop_table + end + + def test_invert_rename_table + @recorder.record :rename_table, [:old, :new] + rename = @recorder.inverse.first + assert_equal [:rename_table, [:new, :old]], rename + end + + def test_invert_add_column + @recorder.record :add_column, [:table, :column, :type, {}] + remove = @recorder.inverse.first + assert_equal [:remove_column, [:table, :column]], remove + end + + def test_invert_rename_column + @recorder.record :rename_column, [:table, :old, :new] + rename = @recorder.inverse.first + assert_equal [:rename_column, [:table, :new, :old]], rename + end + + def test_invert_add_index + @recorder.record :add_index, [:table, [:one, :two], {:options => true}] + remove = @recorder.inverse.first + assert_equal [:remove_index, [:table, {:column => [:one, :two]}]], remove + end + + def test_invert_rename_index + @recorder.record :rename_index, [:old, :new] + rename = @recorder.inverse.first + assert_equal [:rename_index, [:new, :old]], rename + end + + def test_invert_add_timestamps + @recorder.record :add_timestamps, [:table] + remove = @recorder.inverse.first + assert_equal [:remove_timestamps, [:table]], remove + end + + def test_invert_remove_timestamps + @recorder.record :remove_timestamps, [:table] + add = @recorder.inverse.first + assert_equal [:add_timestamps, [:table]], add + end + end + end +end diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index ef949300b0..3037d73a1b 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -18,10 +18,11 @@ if ActiveRecord::Base.connection.supports_migrations? class ActiveRecord::Migration class <<self attr_accessor :message_count - def puts(text="") - self.message_count ||= 0 - self.message_count += 1 - end + end + + def puts(text="") + self.class.message_count ||= 0 + self.class.message_count += 1 end end @@ -422,7 +423,7 @@ if ActiveRecord::Base.connection.supports_migrations? # Sybase, and SQLite3 will not allow you to add a NOT NULL # column to a table without a default value. - unless current_adapter?(:SybaseAdapter, :SQLiteAdapter) + unless current_adapter?(:SybaseAdapter, :SQLite3Adapter) def test_add_column_not_null_without_default Person.connection.create_table :testings do |t| t.column :foo, :string @@ -821,7 +822,7 @@ if ActiveRecord::Base.connection.supports_migrations? end end - if current_adapter?(:SQLiteAdapter) + if current_adapter?(:SQLite3Adapter) def test_rename_table_for_sqlite_should_work_with_reserved_words begin assert_nothing_raised do @@ -1131,7 +1132,7 @@ if ActiveRecord::Base.connection.supports_migrations? # so this happens there too assert_kind_of BigDecimal, b.value_of_e assert_equal BigDecimal("2.7182818284590452353602875"), b.value_of_e - elsif current_adapter?(:SQLiteAdapter) + elsif current_adapter?(:SQLite3Adapter) # - SQLite3 stores a float, in violation of SQL assert_kind_of BigDecimal, b.value_of_e assert_in_delta BigDecimal("2.71828182845905"), b.value_of_e, 0.00000000000001 @@ -1165,6 +1166,44 @@ if ActiveRecord::Base.connection.supports_migrations? assert_raise(ActiveRecord::StatementInvalid) { Reminder.find(:first) } end + class MockMigration < ActiveRecord::Migration + attr_reader :went_up, :went_down + def initialize + @went_up = false + @went_down = false + end + + def up + @went_up = true + super + end + + def down + @went_down = true + super + end + end + + def test_instance_based_migration_up + migration = MockMigration.new + assert !migration.went_up, 'have not gone up' + assert !migration.went_down, 'have not gone down' + + migration.migrate :up + assert migration.went_up, 'have gone up' + assert !migration.went_down, 'have not gone down' + end + + def test_instance_based_migration_down + migration = MockMigration.new + assert !migration.went_up, 'have not gone up' + assert !migration.went_down, 'have not gone down' + + migration.migrate :down + assert !migration.went_up, 'have gone up' + assert migration.went_down, 'have not gone down' + end + def test_migrator_one_up assert !Person.column_methods_hash.include?(:last_name) assert !Reminder.table_exists? @@ -1312,20 +1351,20 @@ if ActiveRecord::Base.connection.supports_migrations? def test_migrator_verbosity ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1) - assert PeopleHaveLastNames.message_count > 0 + assert_operator PeopleHaveLastNames.message_count, :>, 0 PeopleHaveLastNames.message_count = 0 ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0) - assert PeopleHaveLastNames.message_count > 0 + assert_operator PeopleHaveLastNames.message_count, :>, 0 PeopleHaveLastNames.message_count = 0 end def test_migrator_verbosity_off PeopleHaveLastNames.verbose = false ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", 1) - assert PeopleHaveLastNames.message_count.zero? + assert_equal 0, PeopleHaveLastNames.message_count ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 0) - assert PeopleHaveLastNames.message_count.zero? + assert_equal 0, PeopleHaveLastNames.message_count end def test_migrator_going_down_due_to_version_target @@ -1588,7 +1627,7 @@ if ActiveRecord::Base.connection.supports_migrations? end end - if current_adapter?(:PostgreSQLAdapter) || current_adapter?(:SQLiteAdapter) || current_adapter?(:MysqlAdapter) || current_adapter?(:Mysql2Adapter) + if current_adapter?(:PostgreSQLAdapter) || current_adapter?(:SQLite3Adapter) || current_adapter?(:MysqlAdapter) || current_adapter?(:Mysql2Adapter) def test_xml_creates_xml_column type = current_adapter?(:PostgreSQLAdapter) ? 'xml' : :text @@ -1947,7 +1986,7 @@ if ActiveRecord::Base.connection.supports_migrations? @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps" @existing_migrations = Dir[@migrations_path + "/*.rb"] - Time.travel_to(created_at = Time.utc(2010, 7, 26, 10, 10, 10)) do + Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.rb") assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.rb") @@ -1972,7 +2011,7 @@ if ActiveRecord::Base.connection.supports_migrations? sources[:bukkits] = MIGRATIONS_ROOT + "/to_copy_with_timestamps" sources[:omg] = MIGRATIONS_ROOT + "/to_copy_with_timestamps2" - Time.travel_to(created_at = Time.utc(2010, 7, 26, 10, 10, 10)) do + Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do copied = ActiveRecord::Migration.copy(@migrations_path, sources) assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.rb") assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.rb") @@ -1992,7 +2031,7 @@ if ActiveRecord::Base.connection.supports_migrations? @migrations_path = MIGRATIONS_ROOT + "/valid_with_timestamps" @existing_migrations = Dir[@migrations_path + "/*.rb"] - Time.travel_to(created_at = Time.utc(2010, 2, 20, 10, 10, 10)) do + Time.travel_to(Time.utc(2010, 2, 20, 10, 10, 10)) do ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) assert File.exists?(@migrations_path + "/20100301010102_people_have_hobbies.rb") assert File.exists?(@migrations_path + "/20100301010103_people_have_descriptions.rb") @@ -2024,11 +2063,26 @@ if ActiveRecord::Base.connection.supports_migrations? clear end + def test_copying_migrations_to_non_existing_directory + @migrations_path = MIGRATIONS_ROOT + "/non_existing" + @existing_migrations = [] + + Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do + copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) + assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.rb") + assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.rb") + assert_equal 2, copied.length + end + ensure + clear + Dir.delete(@migrations_path) + end + def test_copying_migrations_to_empty_directory @migrations_path = MIGRATIONS_ROOT + "/empty" @existing_migrations = [] - Time.travel_to(created_at = Time.utc(2010, 7, 26, 10, 10, 10)) do + Time.travel_to(Time.utc(2010, 7, 26, 10, 10, 10)) do copied = ActiveRecord::Migration.copy(@migrations_path, {:bukkits => MIGRATIONS_ROOT + "/to_copy_with_timestamps"}) assert File.exists?(@migrations_path + "/20100726101010_people_have_hobbies.rb") assert File.exists?(@migrations_path + "/20100726101011_people_have_descriptions.rb") diff --git a/activerecord/test/cases/named_scope_test.rb b/activerecord/test/cases/named_scope_test.rb index cc4438395e..6ac3e3fc56 100644 --- a/activerecord/test/cases/named_scope_test.rb +++ b/activerecord/test/cases/named_scope_test.rb @@ -122,7 +122,13 @@ class NamedScopeTest < ActiveRecord::TestCase :joins => 'JOIN authors ON authors.id = posts.author_id', :conditions => [ 'authors.author_address_id = ?', address.id ] ) - assert_equal posts_with_authors_at_address_titles, Post.with_authors_at_address(address).find(:all, :select => 'title') + assert_equal posts_with_authors_at_address_titles.map(&:title), Post.with_authors_at_address(address).find(:all, :select => 'title').map(&:title) + end + + def test_scope_with_object + objects = Topic.with_object + assert_operator objects.length, :>, 0 + assert objects.all?(&:approved?), 'all objects should be approved' end def test_extensions diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb index 8382ca048b..fb6a239545 100644 --- a/activerecord/test/cases/nested_attributes_test.rb +++ b/activerecord/test/cases/nested_attributes_test.rb @@ -139,6 +139,14 @@ class TestNestedAttributesInGeneral < ActiveRecord::TestCase assert_equal 'gardening', interest.reload.topic end + def test_reject_if_with_blank_nested_attributes_id + # When using a select list to choose an existing 'ship' id, with :include_blank => true + Pirate.accepts_nested_attributes_for :ship, :reject_if => proc {|attributes| attributes[:id].blank? } + + pirate = Pirate.new(:catchphrase => "Stop wastin' me time") + pirate.ship_attributes = { :id => "" } + assert_nothing_raised(ActiveRecord::RecordNotFound) { pirate.save! } + end end class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase @@ -163,7 +171,7 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase @ship.destroy @pirate.reload.ship_attributes = { :name => 'Davy Jones Gold Dagger' } - assert @pirate.ship.new_record? + assert !@pirate.ship.persisted? assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name end @@ -184,7 +192,7 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase def test_should_replace_an_existing_record_if_there_is_no_id @pirate.reload.ship_attributes = { :name => 'Davy Jones Gold Dagger' } - assert @pirate.ship.new_record? + assert !@pirate.ship.persisted? assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name assert_equal 'Nights Dirty Lightning', @ship.name end @@ -203,6 +211,12 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name end + def test_should_raise_RecordNotFound_if_an_id_is_given_but_doesnt_return_a_record + assert_raise_with_message ActiveRecord::RecordNotFound, "Couldn't find Ship with ID=1234567890 for Pirate with ID=#{@pirate.id}" do + @pirate.ship_attributes = { :id => 1234567890 } + end + end + def test_should_take_a_hash_with_string_keys_and_update_the_associated_model @pirate.reload.ship_attributes = { 'id' => @ship.id, 'name' => 'Davy Jones Gold Dagger' } @@ -250,7 +264,7 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase def test_should_also_work_with_a_HashWithIndifferentAccess @pirate.ship_attributes = HashWithIndifferentAccess.new(:id => @ship.id, :name => 'Davy Jones Gold Dagger') - assert !@pirate.ship.new_record? + assert @pirate.ship.persisted? assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name end @@ -342,7 +356,7 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase @pirate.destroy @ship.reload.pirate_attributes = { :catchphrase => 'Arr' } - assert @ship.pirate.new_record? + assert !@ship.pirate.persisted? assert_equal 'Arr', @ship.pirate.catchphrase end @@ -363,7 +377,7 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase def test_should_replace_an_existing_record_if_there_is_no_id @ship.reload.pirate_attributes = { :catchphrase => 'Arr' } - assert @ship.pirate.new_record? + assert !@ship.pirate.persisted? assert_equal 'Arr', @ship.pirate.catchphrase assert_equal 'Aye', @pirate.catchphrase end @@ -382,13 +396,10 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase assert_equal 'Arr', @ship.pirate.catchphrase end - def test_should_associate_with_record_if_parent_record_is_not_saved - @ship.destroy - @pirate = Pirate.create(:catchphrase => 'Arr') - @ship = Ship.new(:name => 'Nights Dirty Lightning', :pirate_attributes => { :id => @pirate.id, :catchphrase => @pirate.catchphrase}) - - assert_equal @ship.name, 'Nights Dirty Lightning' - assert_equal @pirate, @ship.pirate + def test_should_raise_RecordNotFound_if_an_id_is_given_but_doesnt_return_a_record + assert_raise_with_message ActiveRecord::RecordNotFound, "Couldn't find Pirate with ID=1234567890 for Ship with ID=#{@ship.id}" do + @ship.pirate_attributes = { :id => 1234567890 } + end end def test_should_take_a_hash_with_string_keys_and_update_the_associated_model @@ -455,7 +466,7 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase @pirate.delete @ship.reload.attributes = { :update_only_pirate_attributes => { :catchphrase => 'Arr' } } - assert @ship.update_only_pirate.new_record? + assert !@ship.update_only_pirate.persisted? end def test_should_update_existing_when_update_only_is_true_and_no_id_is_given @@ -518,11 +529,6 @@ module NestedAttributesOnACollectionAssociationTests assert_equal ['Grace OMalley', 'Privateers Greed'], [@child_1.reload.name, @child_2.reload.name] end - def test_should_assign_existing_children_if_parent_is_new - @pirate = Pirate.new({:catchphrase => "Don' botharr talkin' like one, savvy?"}.merge(@alternate_params)) - assert_equal ['Grace OMalley', 'Privateers Greed'], [@pirate.send(@association_name)[0].name, @pirate.send(@association_name)[1].name] - end - def test_should_also_work_with_a_HashWithIndifferentAccess @pirate.send(association_setter, HashWithIndifferentAccess.new('foo' => HashWithIndifferentAccess.new(:id => @child_1.id, :name => 'Grace OMalley'))) @pirate.save @@ -586,8 +592,8 @@ module NestedAttributesOnACollectionAssociationTests assert_equal ['Grace OMalley', 'Privateers Greed'], [@child_1.name, @child_2.name] end - def test_should_not_raise_RecordNotFound_if_an_id_is_given_but_doesnt_return_a_record - assert_nothing_raised ActiveRecord::RecordNotFound do + def test_should_raise_RecordNotFound_if_an_id_is_given_but_doesnt_return_a_record + assert_raise_with_message ActiveRecord::RecordNotFound, "Couldn't find #{@child_1.class.name} with ID=1234567890 for Pirate with ID=#{@pirate.id}" do @pirate.attributes = { association_getter => [{ :id => 1234567890 }] } end end @@ -598,10 +604,10 @@ module NestedAttributesOnACollectionAssociationTests association_getter => { 'foo' => { :name => 'Grace OMalley' }, 'bar' => { :name => 'Privateers Greed' }} } - assert @pirate.send(@association_name).first.new_record? + assert !@pirate.send(@association_name).first.persisted? assert_equal 'Grace OMalley', @pirate.send(@association_name).first.name - assert @pirate.send(@association_name).last.new_record? + assert !@pirate.send(@association_name).last.persisted? assert_equal 'Privateers Greed', @pirate.send(@association_name).last.name end @@ -821,7 +827,7 @@ class TestNestedAttributesWithNonStandardPrimaryKeys < ActiveRecord::TestCase fixtures :owners, :pets def setup - Owner.accepts_nested_attributes_for :pets + Owner.accepts_nested_attributes_for :pets, :allow_destroy => true @owner = owners(:ashley) @pet1, @pet2 = pets(:chew), pets(:mochi) @@ -838,6 +844,19 @@ class TestNestedAttributesWithNonStandardPrimaryKeys < ActiveRecord::TestCase @owner.update_attributes(@params) assert_equal ['Foo', 'Bar'], @owner.pets.map(&:name) end + + def test_attr_accessor_of_child_should_be_value_provided_during_update_attributes + @owner = owners(:ashley) + @pet1 = pets(:chew) + assert_equal nil, $current_user + attributes = {:pets_attributes => { "1"=> { :id => @pet1.id, + :name => "Foo2", + :current_user => "John", + :_destroy=>true }}} + @owner.update_attributes(attributes) + assert_equal 'John', $after_destroy_callback_output + end + end class TestHasOneAutosaveAssociationWhichItselfHasAutosaveAssociations < ActiveRecord::TestCase diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb index ffe6fb95b8..8ca9d626d1 100644 --- a/activerecord/test/cases/persistence_test.rb +++ b/activerecord/test/cases/persistence_test.rb @@ -192,7 +192,6 @@ class PersistencesTest < ActiveRecord::TestCase topic = Topic.create("title" => "New Topic") do |t| t.author_name = "David" end - topicReloaded = Topic.find(topic.id) assert_equal("New Topic", topic.title) assert_equal("David", topic.author_name) end @@ -241,6 +240,15 @@ class PersistencesTest < ActiveRecord::TestCase assert_nothing_raised { minimalistic.save } end + def test_update_sti_type + assert_instance_of Reply, topics(:second) + + topic = topics(:second).becomes(Topic) + assert_instance_of Topic, topic + topic.save! + assert_instance_of Topic, Topic.find(topic.id) + end + def test_delete topic = Topic.find(1) assert_equal topic, topic.delete, 'topic.delete did not return self' @@ -261,7 +269,7 @@ class PersistencesTest < ActiveRecord::TestCase end def test_record_not_found_exception - assert_raise(ActiveRecord::RecordNotFound) { topicReloaded = Topic.find(99999) } + assert_raise(ActiveRecord::RecordNotFound) { Topic.find(99999) } end def test_update_all diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb index 594db1d0ab..33916c4e46 100644 --- a/activerecord/test/cases/query_cache_test.rb +++ b/activerecord/test/cases/query_cache_test.rb @@ -22,6 +22,12 @@ class QueryCacheTest < ActiveRecord::TestCase end end + def test_find_queries_with_cache_multi_record + Task.cache do + assert_queries(2) { Task.find(1); Task.find(1); Task.find(2) } + end + end + def test_count_queries_with_cache Task.cache do assert_queries(1) { Task.count; Task.count } @@ -57,7 +63,7 @@ class QueryCacheTest < ActiveRecord::TestCase # Oracle adapter returns count() as Fixnum or Float if current_adapter?(:OracleAdapter) assert_kind_of Numeric, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks") - elsif current_adapter?(:SQLite3Adapter) && SQLite3::Version::VERSION > '1.2.5' or current_adapter?(:Mysql2Adapter) + elsif current_adapter?(:SQLite3Adapter) && SQLite3::Version::VERSION > '1.2.5' || current_adapter?(:Mysql2Adapter) || current_adapter?(:MysqlAdapter) # Future versions of the sqlite3 adapter will return numeric assert_instance_of Fixnum, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks") @@ -127,7 +133,6 @@ class QueryCacheExpiryTest < ActiveRecord::TestCase def test_cache_is_expired_by_habtm_delete ActiveRecord::Base.connection.expects(:clear_query_cache).times(2) ActiveRecord::Base.cache do - c = Category.find(1) p = Post.find(1) assert p.categories.any? p.categories.delete_all diff --git a/activerecord/test/cases/quoting_test.rb b/activerecord/test/cases/quoting_test.rb new file mode 100644 index 0000000000..2ef5b5a800 --- /dev/null +++ b/activerecord/test/cases/quoting_test.rb @@ -0,0 +1,220 @@ +require "cases/helper" + +module ActiveRecord + module ConnectionAdapters + class QuotingTest < ActiveRecord::TestCase + class FakeColumn < ActiveRecord::ConnectionAdapters::Column + attr_accessor :type + + def initialize type + @type = type + end + end + + def setup + @quoter = Class.new { include Quoting }.new + end + + def test_quoted_true + assert_equal "'t'", @quoter.quoted_true + end + + def test_quoted_false + assert_equal "'f'", @quoter.quoted_false + end + + def test_quote_column_name + assert_equal "foo", @quoter.quote_column_name('foo') + end + + def test_quote_table_name + assert_equal "foo", @quoter.quote_table_name('foo') + end + + def test_quote_table_name_calls_quote_column_name + @quoter.extend(Module.new { + def quote_column_name(string) + 'lol' + end + }) + assert_equal 'lol', @quoter.quote_table_name('foo') + end + + def test_quote_string + assert_equal "''", @quoter.quote_string("'") + assert_equal "\\\\", @quoter.quote_string("\\") + assert_equal "hi''i", @quoter.quote_string("hi'i") + assert_equal "hi\\\\i", @quoter.quote_string("hi\\i") + end + + def test_quoted_date + t = Date.today + assert_equal t.to_s(:db), @quoter.quoted_date(t) + end + + def test_quoted_time_utc + before = ActiveRecord::Base.default_timezone + ActiveRecord::Base.default_timezone = :utc + t = Time.now + assert_equal t.getutc.to_s(:db), @quoter.quoted_date(t) + ensure + ActiveRecord::Base.default_timezone = before + end + + def test_quoted_time_local + before = ActiveRecord::Base.default_timezone + ActiveRecord::Base.default_timezone = :local + t = Time.now + assert_equal t.getlocal.to_s(:db), @quoter.quoted_date(t) + ensure + ActiveRecord::Base.default_timezone = before + end + + def test_quoted_time_crazy + before = ActiveRecord::Base.default_timezone + ActiveRecord::Base.default_timezone = :asdfasdf + t = Time.now + assert_equal t.getlocal.to_s(:db), @quoter.quoted_date(t) + ensure + ActiveRecord::Base.default_timezone = before + end + + def test_quoted_datetime_utc + before = ActiveRecord::Base.default_timezone + ActiveRecord::Base.default_timezone = :utc + t = DateTime.now + assert_equal t.getutc.to_s(:db), @quoter.quoted_date(t) + ensure + ActiveRecord::Base.default_timezone = before + end + + ### + # DateTime doesn't define getlocal, so make sure it does nothing + def test_quoted_datetime_local + before = ActiveRecord::Base.default_timezone + ActiveRecord::Base.default_timezone = :local + t = DateTime.now + assert_equal t.to_s(:db), @quoter.quoted_date(t) + ensure + ActiveRecord::Base.default_timezone = before + end + + def test_quote_with_quoted_id + assert_equal 1, @quoter.quote(Struct.new(:quoted_id).new(1), nil) + assert_equal 1, @quoter.quote(Struct.new(:quoted_id).new(1), 'foo') + end + + def test_quote_nil + assert_equal 'NULL', @quoter.quote(nil, nil) + assert_equal 'NULL', @quoter.quote(nil, 'foo') + end + + def test_quote_true + assert_equal @quoter.quoted_true, @quoter.quote(true, nil) + assert_equal '1', @quoter.quote(true, Struct.new(:type).new(:integer)) + end + + def test_quote_false + assert_equal @quoter.quoted_false, @quoter.quote(false, nil) + assert_equal '0', @quoter.quote(false, Struct.new(:type).new(:integer)) + end + + def test_quote_float + float = 1.2 + assert_equal float.to_s, @quoter.quote(float, nil) + assert_equal float.to_s, @quoter.quote(float, Object.new) + end + + def test_quote_fixnum + fixnum = 1 + assert_equal fixnum.to_s, @quoter.quote(fixnum, nil) + assert_equal fixnum.to_s, @quoter.quote(fixnum, Object.new) + end + + def test_quote_bignum + bignum = 1 << 100 + assert_equal bignum.to_s, @quoter.quote(bignum, nil) + assert_equal bignum.to_s, @quoter.quote(bignum, Object.new) + end + + def test_quote_bigdecimal + bigdec = BigDecimal.new((1 << 100).to_s) + assert_equal bigdec.to_s('F'), @quoter.quote(bigdec, nil) + assert_equal bigdec.to_s('F'), @quoter.quote(bigdec, Object.new) + end + + def test_dates_and_times + @quoter.extend(Module.new { def quoted_date(value) 'lol' end }) + assert_equal "'lol'", @quoter.quote(Date.today, nil) + assert_equal "'lol'", @quoter.quote(Date.today, Object.new) + assert_equal "'lol'", @quoter.quote(Time.now, nil) + assert_equal "'lol'", @quoter.quote(Time.now, Object.new) + assert_equal "'lol'", @quoter.quote(DateTime.now, nil) + assert_equal "'lol'", @quoter.quote(DateTime.now, Object.new) + end + + def test_crazy_object + crazy = Class.new { def to_s; 'lol' end }.new + assert_equal "'lol'", @quoter.quote(crazy, nil) + assert_equal "'lol'", @quoter.quote(crazy, Object.new) + end + + def test_crazy_object_calls_quote_string + crazy = Class.new { def to_s; 'lo\l' end }.new + assert_equal "'lo\\\\l'", @quoter.quote(crazy, nil) + assert_equal "'lo\\\\l'", @quoter.quote(crazy, Object.new) + end + + def test_quote_string_no_column + assert_equal "'lo\\\\l'", @quoter.quote('lo\l', nil) + end + + def test_quote_as_mb_chars_no_column + string = ActiveSupport::Multibyte::Chars.new('lo\l') + assert_equal "'lo\\\\l'", @quoter.quote(string, nil) + end + + def test_quote_string_int_column + assert_equal "1", @quoter.quote('1', FakeColumn.new(:integer)) + assert_equal "1", @quoter.quote('1.2', FakeColumn.new(:integer)) + end + + def test_quote_string_float_column + assert_equal "1.0", @quoter.quote('1', FakeColumn.new(:float)) + assert_equal "1.2", @quoter.quote('1.2', FakeColumn.new(:float)) + end + + def test_quote_as_mb_chars_binary_column + string = ActiveSupport::Multibyte::Chars.new('lo\l') + assert_equal "'lo\\\\l'", @quoter.quote(string, FakeColumn.new(:binary)) + end + + def test_quote_binary_without_string_to_binary + assert_equal "'lo\\\\l'", @quoter.quote('lo\l', FakeColumn.new(:binary)) + end + + def test_quote_binary_with_string_to_binary + col = Class.new(FakeColumn) { + def string_to_binary(value) + 'foo' + end + }.new(:binary) + assert_equal "'foo'", @quoter.quote('lo\l', col) + end + + def test_quote_as_mb_chars_binary_column_with_string_to_binary + col = Class.new(FakeColumn) { + def string_to_binary(value) + 'foo' + end + }.new(:binary) + string = ActiveSupport::Multibyte::Chars.new('lo\l') + assert_equal "'foo'", @quoter.quote(string, col) + end + + def test_string_with_crazy_column + assert_equal "'lo\\\\l'", @quoter.quote('lo\l', FakeColumn.new(:foo)) + end + end + end +end diff --git a/activerecord/test/cases/reflection_test.rb b/activerecord/test/cases/reflection_test.rb index eeb619ac2f..3b9e4f42a6 100644 --- a/activerecord/test/cases/reflection_test.rb +++ b/activerecord/test/cases/reflection_test.rb @@ -24,25 +24,25 @@ class ReflectionTest < ActiveRecord::TestCase def test_read_attribute_names assert_equal( - %w( id title author_name author_email_address bonus_time written_on last_read content group approved replies_count parent_id parent_title type ).sort, + %w( id title author_name author_email_address bonus_time written_on last_read content group approved replies_count parent_id parent_title type created_at updated_at ).sort, @first.attribute_names ) end def test_columns - assert_equal 14, Topic.columns.length + assert_equal 16, 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 parent_title type group), column_names + assert_equal %w(id title author_name author_email_address written_on bonus_time last_read content approved replies_count parent_id parent_title type group created_at updated_at), column_names end def test_content_columns content_columns = Topic.content_columns content_column_names = content_columns.map {|column| column.name} - assert_equal 10, content_columns.length - assert_equal %w(title author_name author_email_address written_on bonus_time last_read content group approved parent_title).sort, content_column_names.sort + assert_equal 12, content_columns.length + assert_equal %w(title author_name author_email_address written_on bonus_time last_read content group approved parent_title created_at updated_at).sort, content_column_names.sort end def test_column_string_type_and_limit diff --git a/activerecord/test/cases/relation_scoping_test.rb b/activerecord/test/cases/relation_scoping_test.rb index 090e6c8bc9..dae9721a63 100644 --- a/activerecord/test/cases/relation_scoping_test.rb +++ b/activerecord/test/cases/relation_scoping_test.rb @@ -254,13 +254,11 @@ class HasManyScopingTest< ActiveRecord::TestCase end def test_should_maintain_default_scope_on_associations - person = people(:michael) magician = BadReference.find(1) assert_equal [magician], people(:michael).bad_references end def test_should_default_scope_on_associations_is_overriden_by_association_conditions - person = people(:michael) assert_equal [], people(:michael).fixed_bad_references end @@ -311,6 +309,35 @@ class DefaultScopingTest < ActiveRecord::TestCase assert_equal expected, received end + def test_default_scope_with_lambda + expected = Post.find_all_by_author_id(2) + PostForAuthor.selected_author = 2 + received = PostForAuthor.all + assert_equal expected, received + expected = Post.find_all_by_author_id(1) + PostForAuthor.selected_author = 1 + received = PostForAuthor.all + assert_equal expected, received + end + + def test_default_scope_with_thing_that_responds_to_call + klass = Class.new(ActiveRecord::Base) do + self.table_name = 'posts' + end + + klass.class_eval do + default_scope Class.new(Struct.new(:klass)) { + def call + klass.where(:author_id => 2) + end + }.new(self) + end + + records = klass.all + assert_equal 1, records.length + assert_equal 2, records.first.author_id + end + def test_default_scope_is_unscoped_on_find assert_equal 1, DeveloperCalledDavid.count assert_equal 11, DeveloperCalledDavid.unscoped.count @@ -364,6 +391,23 @@ class DefaultScopingTest < ActiveRecord::TestCase assert_equal 100000, klass.first.salary end + def test_default_scope_called_twice_in_different_place_merges_where_clause + Developer.destroy_all + Developer.create!(:name => "David", :salary => 80000) + Developer.create!(:name => "David", :salary => 100000) + Developer.create!(:name => "Brian", :salary => 100000) + + klass = Class.new(Developer) + klass.class_eval do + default_scope where("name = 'David'") + default_scope where("salary = 100000") + end + + assert_equal 1, klass.count + assert_equal "David", klass.first.name + assert_equal 100000, klass.first.salary + end + def test_method_scope expected = Developer.find(:all, :order => 'salary DESC, name DESC').collect { |dev| dev.salary } received = DeveloperOrderedBySalary.all_ordered_by_name.collect { |dev| dev.salary } @@ -384,18 +428,12 @@ class DefaultScopingTest < ActiveRecord::TestCase assert_equal expected, received end - def test_reorder_overrides_default_scope_order + def test_except_and_order_overrides_default_scope_order expected = Developer.order('name DESC').collect { |dev| dev.name } - received = DeveloperOrderedBySalary.reorder('name DESC').collect { |dev| dev.name } + received = DeveloperOrderedBySalary.except(:order).order('name DESC').collect { |dev| dev.name } assert_equal expected, received end - def test_reordered_scope_overrides_default_scope_order - not_expected = DeveloperOrderedBySalary.first # Jamis -> name DESC - received = DeveloperOrderedBySalary.reordered_by_name.first # David -> name - assert not_expected.id != received.id - end - def test_nested_exclusive_scope expected = Developer.find(:all, :limit => 100).collect { |dev| dev.salary } received = DeveloperOrderedBySalary.send(:with_exclusive_scope, :find => { :limit => 100 }) do diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index d642aeed8b..1682f34a1d 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -1,4 +1,5 @@ require "cases/helper" +require 'models/tag' require 'models/tagging' require 'models/post' require 'models/topic' @@ -13,11 +14,27 @@ require 'models/bird' require 'models/car' require 'models/engine' require 'models/tyre' +require 'models/minivan' class RelationTest < ActiveRecord::TestCase fixtures :authors, :topics, :entrants, :developers, :companies, :developers_projects, :accounts, :categories, :categorizations, :posts, :comments, - :taggings, :cars + :tags, :taggings, :cars, :minivans + + def test_do_not_double_quote_string_id + van = Minivan.last + assert van + assert_equal van.id, Minivan.where(:minivan_id => van).to_a.first.minivan_id + end + + def test_bind_values + relation = Post.scoped + assert_equal [], relation.bind_values + + relation2 = relation.bind 'foo' + assert_equal %w{ foo }, relation2.bind_values + assert_equal [], relation.bind_values + end def test_two_named_scopes_with_includes_should_not_drop_any_include car = Car.incl_engines.incl_tyres.first @@ -25,13 +42,6 @@ class RelationTest < ActiveRecord::TestCase assert_no_queries { car.engines.length } end - def test_apply_relation_as_where_id - posts = Post.arel_table - post_authors = posts.where(posts[:author_id].eq(1)).project(posts[:id]) - assert_equal 5, post_authors.to_a.size - assert_equal 5, Post.where(:id => post_authors).size - end - def test_dynamic_finder x = Post.where('author_id = ?', 1) assert x.klass.respond_to?(:find_by_id), '@klass should handle dynamic finders' @@ -135,12 +145,6 @@ class RelationTest < ActiveRecord::TestCase assert_equal topics(:fourth).title, topics.first.title end - def test_finding_with_reorder - topics = Topic.order('author_name').order('title').reorder('id') - assert_equal 4, topics.to_a.size - assert_equal topics(:first).title, topics.first.title - end - def test_finding_with_order_and_take entrants = Entrant.order("id ASC").limit(2).to_a @@ -148,6 +152,16 @@ class RelationTest < ActiveRecord::TestCase assert_equal entrants(:first).name, entrants.first.name end + def test_finding_with_complex_order_and_limit + tags = Tag.includes(:taggings).order("REPLACE('abc', taggings.taggable_type, taggings.taggable_type)").limit(1).to_a + assert_equal 1, tags.length + end + + def test_finding_with_complex_order + tags = Tag.includes(:taggings).order("REPLACE('abc', taggings.taggable_type, taggings.taggable_type)").to_a + assert_equal 2, tags.length + end + def test_finding_with_order_limit_and_offset entrants = Entrant.order("id ASC").limit(2).offset(1) @@ -376,7 +390,7 @@ class RelationTest < ActiveRecord::TestCase lifo = authors.find_or_initialize_by_name('Lifo') assert_equal "Lifo", lifo.name - assert lifo.new_record? + assert !lifo.persisted? assert_equal authors(:david), authors.find_or_initialize_by_name(:name => 'David') end @@ -386,7 +400,7 @@ class RelationTest < ActiveRecord::TestCase lifo = authors.find_or_create_by_name('Lifo') assert_equal "Lifo", lifo.name - assert ! lifo.new_record? + assert lifo.persisted? assert_equal authors(:david), authors.find_or_create_by_name(:name => 'David') end @@ -419,6 +433,52 @@ class RelationTest < ActiveRecord::TestCase assert_blank authors.all end + def test_where_with_ar_object + author = Author.first + authors = Author.scoped.where(:id => author) + assert_equal 1, authors.all.length + end + + def test_find_with_list_of_ar + author = Author.first + authors = Author.find([author]) + assert_equal author, authors.first + end + + class Mary < Author; end + + def test_find_by_classname + Author.create!(:name => Mary.name) + assert_equal 1, Author.where(:name => Mary).size + end + + def test_find_by_id_with_list_of_ar + author = Author.first + authors = Author.find_by_id([author]) + assert_equal author, authors + end + + def test_find_all_using_where_twice_should_or_the_relation + david = authors(:david) + relation = Author.unscoped + relation = relation.where(:name => david.name) + relation = relation.where(:name => 'Santiago') + relation = relation.where(:id => david.id) + assert_equal [david], relation.all + end + + def test_find_all_with_multiple_ors + david = authors(:david) + relation = [ + { :name => david.name }, + { :name => 'Santiago' }, + { :name => 'tenderlove' }, + ].inject(Author.unscoped) do |memo, param| + memo.where(param) + end + assert_equal [david], relation.all + end + def test_exists davids = Author.where(:name => 'David') assert davids.exists? @@ -504,6 +564,11 @@ class RelationTest < ActiveRecord::TestCase end end + def test_relation_merging_with_joins + comments = Comment.joins(:post).where(:body => 'Thank you for the welcome') & Post.where(:body => 'Such a lovely day') + assert_equal 1, comments.count + end + def test_count posts = Post.scoped @@ -615,10 +680,10 @@ class RelationTest < ActiveRecord::TestCase sparrow = birds.create assert_kind_of Bird, sparrow - assert sparrow.new_record? + assert !sparrow.persisted? hen = birds.where(:name => 'hen').create - assert ! hen.new_record? + assert hen.persisted? assert_equal 'hen', hen.name end @@ -629,7 +694,7 @@ class RelationTest < ActiveRecord::TestCase hen = birds.where(:name => 'hen').create! assert_kind_of Bird, hen - assert ! hen.new_record? + assert hen.persisted? assert_equal 'hen', hen.name end diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb index 66446b6b7e..9b2c7c00df 100644 --- a/activerecord/test/cases/schema_dumper_test.rb +++ b/activerecord/test/cases/schema_dumper_test.rb @@ -100,7 +100,7 @@ class SchemaDumperTest < ActiveRecord::TestCase assert_match %r{c_int_4.*}, output assert_no_match %r{c_int_4.*:limit}, output - elsif current_adapter?(:SQLiteAdapter) + elsif current_adapter?(:SQLite3Adapter) assert_match %r{c_int_1.*:limit => 1}, output assert_match %r{c_int_2.*:limit => 2}, output assert_match %r{c_int_3.*:limit => 3}, output @@ -109,7 +109,7 @@ class SchemaDumperTest < ActiveRecord::TestCase assert_match %r{c_int_without_limit.*}, output assert_no_match %r{c_int_without_limit.*:limit}, output - if current_adapter?(:SQLiteAdapter) + if current_adapter?(:SQLite3Adapter) assert_match %r{c_int_5.*:limit => 5}, output assert_match %r{c_int_6.*:limit => 6}, output assert_match %r{c_int_7.*:limit => 7}, output diff --git a/activerecord/test/cases/session_store/sql_bypass.rb b/activerecord/test/cases/session_store/sql_bypass.rb index f0ba166465..7402b2afd6 100644 --- a/activerecord/test/cases/session_store/sql_bypass.rb +++ b/activerecord/test/cases/session_store/sql_bypass.rb @@ -18,9 +18,9 @@ module ActiveRecord assert !Session.table_exists? end - def test_new_record? + def test_persisted? s = SqlBypass.new :data => 'foo', :session_id => 10 - assert s.new_record?, 'this is a new record!' + assert !s.persisted?, 'this is a new record!' end def test_not_loaded? diff --git a/activerecord/test/cases/timestamp_test.rb b/activerecord/test/cases/timestamp_test.rb index eb93761fb2..70c098bc6d 100644 --- a/activerecord/test/cases/timestamp_test.rb +++ b/activerecord/test/cases/timestamp_test.rb @@ -113,7 +113,7 @@ class TimestampTest < ActiveRecord::TestCase pet = Pet.first owner = pet.owner - owner.update_attribute(:happy_at, (time = 3.days.ago)) + owner.update_attribute(:happy_at, 3.days.ago) previously_owner_updated_at = owner.updated_at pet.name = "I'm a parrot" diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb index 9255190613..b0ccd71836 100644 --- a/activerecord/test/cases/transactions_test.rb +++ b/activerecord/test/cases/transactions_test.rb @@ -163,7 +163,7 @@ class TransactionTest < ActiveRecord::TestCase @first.author_name += '_this_should_not_end_up_in_the_db' @first.save! flunk - rescue => e + rescue assert_equal original_author_name, @first.reload.author_name assert_equal nbooks_before_save, Book.count ensure @@ -182,7 +182,7 @@ class TransactionTest < ActiveRecord::TestCase :bonus_time => "2005-01-30t15:28:00.00+01:00", :content => "Have a nice day", :approved => false) - new_record_snapshot = new_topic.new_record? + new_record_snapshot = !new_topic.persisted? id_present = new_topic.has_attribute?(Topic.primary_key) id_snapshot = new_topic.id @@ -195,7 +195,7 @@ class TransactionTest < ActiveRecord::TestCase 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 new_record_snapshot, !new_topic.persisted?, "The topic should have its old persisted 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 @@ -263,6 +263,27 @@ class TransactionTest < ActiveRecord::TestCase assert !@second.reload.approved? end if Topic.connection.supports_savepoints? + def test_force_savepoint_on_instance + @first.transaction do + @first.approved = true + @second.approved = false + @first.save! + @second.save! + + begin + @second.transaction :requires_new => true do + @first.happy = false + @first.save! + raise + end + rescue + end + end + + assert @first.reload.approved? + assert !@second.reload.approved? + end if Topic.connection.supports_savepoints? + def test_no_savepoint_in_nested_transaction_without_force Topic.transaction do @first.approved = true @@ -349,21 +370,21 @@ class TransactionTest < ActiveRecord::TestCase assert topic_2.save @first.save @second.destroy - assert_equal false, topic_1.new_record? + assert_equal true, topic_1.persisted? assert_not_nil topic_1.id - assert_equal false, topic_2.new_record? + assert_equal true, topic_2.persisted? assert_not_nil topic_2.id - assert_equal false, @first.new_record? + assert_equal true, @first.persisted? assert_not_nil @first.id assert_equal true, @second.destroyed? raise ActiveRecord::Rollback end - assert_equal true, topic_1.new_record? + assert_equal false, topic_1.persisted? assert_nil topic_1.id - assert_equal true, topic_2.new_record? + assert_equal false, topic_2.persisted? assert_nil topic_2.id - assert_equal false, @first.new_record? + assert_equal true, @first.persisted? assert_not_nil @first.id assert_equal false, @second.destroyed? end @@ -399,7 +420,7 @@ class TransactionTest < ActiveRecord::TestCase end def test_sqlite_add_column_in_transaction - return true unless current_adapter?(:SQLite3Adapter, :SQLiteAdapter) + return true unless current_adapter?(:SQLite3Adapter) # Test first if column creation/deletion works correctly when no # transaction is in place. @@ -529,8 +550,6 @@ end if Topic.connection.supports_savepoints? if current_adapter?(:PostgreSQLAdapter) class ConcurrentTransactionTest < TransactionTest - use_concurrent_connections - # This will cause transactions to overlap and fail unless they are performed on # separate database connections. def test_transaction_per_thread diff --git a/activerecord/test/cases/validations/association_validation_test.rb b/activerecord/test/cases/validations/association_validation_test.rb index 1246dd4276..56e345990f 100644 --- a/activerecord/test/cases/validations/association_validation_test.rb +++ b/activerecord/test/cases/validations/association_validation_test.rb @@ -17,7 +17,7 @@ class AssociationValidationTest < ActiveRecord::TestCase o = Owner.new('name' => 'nopets') assert !o.save assert o.errors[:pets].any? - pet = o.pets.build('name' => 'apet') + o.pets.build('name' => 'apet') assert o.valid? end @@ -27,7 +27,7 @@ class AssociationValidationTest < ActiveRecord::TestCase assert !o.save assert o.errors[:pets].any? - pet = o.pets.build('name' => 'apet') + o.pets.build('name' => 'apet') assert o.valid? 2.times { o.pets.build('name' => 'apet') } diff --git a/activerecord/test/cases/validations/uniqueness_validation_test.rb b/activerecord/test/cases/validations/uniqueness_validation_test.rb index 9a863c25a8..679d67553b 100644 --- a/activerecord/test/cases/validations/uniqueness_validation_test.rb +++ b/activerecord/test/cases/validations/uniqueness_validation_test.rb @@ -60,7 +60,7 @@ class UniquenessValidationTest < ActiveRecord::TestCase def test_validates_uniqueness_with_validates Topic.validates :title, :uniqueness => true - t = Topic.create!('title' => 'abc') + Topic.create!('title' => 'abc') t2 = Topic.new('title' => 'abc') assert !t2.valid? @@ -201,7 +201,7 @@ class UniquenessValidationTest < ActiveRecord::TestCase def test_validate_case_sensitive_uniqueness_with_attribute_passed_as_integer Topic.validates_uniqueness_of(:title, :case_sensitve => true) - t = Topic.create!('title' => 101) + Topic.create!('title' => 101) t2 = Topic.new('title' => 101) assert !t2.valid? diff --git a/activerecord/test/connections/native_oracle/connection.rb b/activerecord/test/connections/native_oracle/connection.rb index 9a717018b2..99f921879c 100644 --- a/activerecord/test/connections/native_oracle/connection.rb +++ b/activerecord/test/connections/native_oracle/connection.rb @@ -33,15 +33,3 @@ ActiveRecord::Base.configurations = { ActiveRecord::Base.establish_connection 'arunit' Course.establish_connection 'arunit2' -# for assert_queries test helper -ActiveRecord::Base.connection.class.class_eval do - IGNORED_SELECT_SQL = [/^select .*nextval/i, /^SAVEPOINT/, /^ROLLBACK TO/, /^\s*select .* from ((all|user)_tab_columns|(all|user)_triggers|(all|user)_constraints)/im] - - def select_with_query_record(sql, name = nil, return_column_names = false) - $queries_executed ||= [] - $queries_executed << sql unless IGNORED_SELECT_SQL.any? { |r| sql =~ r } - select_without_query_record(sql, name, return_column_names) - end - - alias_method_chain :select, :query_record -end diff --git a/activerecord/test/fixtures/comments.yml b/activerecord/test/fixtures/comments.yml index 97d77f8b9a..ddbb823c49 100644 --- a/activerecord/test/fixtures/comments.yml +++ b/activerecord/test/fixtures/comments.yml @@ -57,3 +57,9 @@ eager_other_comment1: post_id: 7 body: go crazy type: SpecialComment + +sub_special_comment: + id: 12 + post_id: 4 + body: Sub special comment + type: SubSpecialComment diff --git a/activerecord/test/models/comment.rb b/activerecord/test/models/comment.rb index 9f6e2d3b71..88061b2145 100644 --- a/activerecord/test/models/comment.rb +++ b/activerecord/test/models/comment.rb @@ -23,6 +23,9 @@ class SpecialComment < Comment end end +class SubSpecialComment < SpecialComment +end + class VerySpecialComment < Comment def self.what_are_you 'a very special comment...' diff --git a/activerecord/test/models/company.rb b/activerecord/test/models/company.rb index be6dd71e3b..ee5f77b613 100644 --- a/activerecord/test/models/company.rb +++ b/activerecord/test/models/company.rb @@ -107,6 +107,7 @@ class Client < Company belongs_to :firm_with_other_name, :class_name => "Firm", :foreign_key => "client_of" belongs_to :firm_with_condition, :class_name => "Firm", :foreign_key => "client_of", :conditions => ["1 = ?", 1] belongs_to :firm_with_primary_key, :class_name => "Firm", :primary_key => "name", :foreign_key => "firm_name" + belongs_to :firm_with_primary_key_symbols, :class_name => "Firm", :primary_key => :name, :foreign_key => :firm_name belongs_to :readonly_firm, :class_name => "Firm", :foreign_key => "firm_id", :readonly => true # Record destruction so we can test whether firm.clients.clear has diff --git a/activerecord/test/models/developer.rb b/activerecord/test/models/developer.rb index 947583af76..32d060cf09 100644 --- a/activerecord/test/models/developer.rb +++ b/activerecord/test/models/developer.rb @@ -88,7 +88,6 @@ class DeveloperOrderedBySalary < ActiveRecord::Base self.table_name = 'developers' default_scope :order => 'salary DESC' scope :by_name, order('name DESC') - scope :reordered_by_name, reorder('name') def self.all_ordered_by_name with_scope(:find => { :order => 'name DESC' }) do diff --git a/activerecord/test/models/eye.rb b/activerecord/test/models/eye.rb new file mode 100644 index 0000000000..dc8ae2b3f6 --- /dev/null +++ b/activerecord/test/models/eye.rb @@ -0,0 +1,37 @@ +class Eye < ActiveRecord::Base + attr_reader :after_create_callbacks_stack + attr_reader :after_update_callbacks_stack + attr_reader :after_save_callbacks_stack + + # Callbacks configured before the ones has_one sets up. + after_create :trace_after_create + after_update :trace_after_update + after_save :trace_after_save + + has_one :iris + accepts_nested_attributes_for :iris + + # Callbacks configured after the ones has_one sets up. + after_create :trace_after_create2 + after_update :trace_after_update2 + after_save :trace_after_save2 + + def trace_after_create + (@after_create_callbacks_stack ||= []) << !iris.persisted? + end + alias trace_after_create2 trace_after_create + + def trace_after_update + (@after_update_callbacks_stack ||= []) << iris.changed? + end + alias trace_after_update2 trace_after_update + + def trace_after_save + (@after_save_callbacks_stack ||= []) << iris.changed? + end + alias trace_after_save2 trace_after_save +end + +class Iris < ActiveRecord::Base + belongs_to :eye +end diff --git a/activerecord/test/models/pet.rb b/activerecord/test/models/pet.rb index a8bf94dd86..570db4c8d5 100644 --- a/activerecord/test/models/pet.rb +++ b/activerecord/test/models/pet.rb @@ -1,5 +1,13 @@ class Pet < ActiveRecord::Base + + attr_accessor :current_user + set_primary_key :pet_id belongs_to :owner, :touch => true has_many :toys + + after_destroy do |record| + $after_destroy_callback_output = record.current_user + end + end diff --git a/activerecord/test/models/pirate.rb b/activerecord/test/models/pirate.rb index d89c8cf381..f2c45053e7 100644 --- a/activerecord/test/models/pirate.rb +++ b/activerecord/test/models/pirate.rb @@ -48,7 +48,7 @@ class Pirate < ActiveRecord::Base end def reject_empty_ships_on_create(attributes) - attributes.delete('_reject_me_if_new').present? && new_record? + attributes.delete('_reject_me_if_new').present? && !persisted? end attr_accessor :cancel_save_from_callback diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb index a3cb9c724a..61e782ff14 100644 --- a/activerecord/test/models/post.rb +++ b/activerecord/test/models/post.rb @@ -113,3 +113,9 @@ class PostWithComment < ActiveRecord::Base self.table_name = 'posts' default_scope where("posts.comments_count > 0").order("posts.comments_count ASC") end + +class PostForAuthor < ActiveRecord::Base + self.table_name = 'posts' + cattr_accessor :selected_author + default_scope lambda { where(:author_id => PostForAuthor.selected_author) } +end diff --git a/activerecord/test/models/subject.rb b/activerecord/test/models/subject.rb index d4b8b91de8..8e28f8b86b 100644 --- a/activerecord/test/models/subject.rb +++ b/activerecord/test/models/subject.rb @@ -8,7 +8,7 @@ class Subject < ActiveRecord::Base protected def set_email_address - if self.new_record? + unless self.persisted? self.author_email_address = 'test@test.com' end end diff --git a/activerecord/test/models/topic.rb b/activerecord/test/models/topic.rb index ba2fe1987b..6496f36f7e 100644 --- a/activerecord/test/models/topic.rb +++ b/activerecord/test/models/topic.rb @@ -18,6 +18,13 @@ class Topic < ActiveRecord::Base 1 end end + + scope :with_object, Class.new(Struct.new(:klass)) { + def call + klass.where(:approved => true) + end + }.new(self) + module NamedExtension def two 2 @@ -82,7 +89,7 @@ class Topic < ActiveRecord::Base end def set_email_address - if self.new_record? + unless self.persisted? self.author_email_address = 'test@test.com' end end diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index ea62833d81..d4eb56c4d7 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -18,8 +18,13 @@ ActiveRecord::Schema.define do end - # Please keep these create table statements in alphabetical order - # unless the ordering matters. In which case, define them below + # ------------------------------------------------------------------- # + # # + # Please keep these create table statements in alphabetical order # + # unless the ordering matters. In which case, define them below. # + # # + # ------------------------------------------------------------------- # + create_table :accounts, :force => true do |t| t.integer :firm_id t.string :firm_name @@ -54,7 +59,6 @@ ActiveRecord::Schema.define do t.column :favorite_author_id, :integer end - create_table :auto_id_tests, :force => true, :id => false do |t| t.primary_key :auto_id t.integer :value @@ -78,6 +82,11 @@ ActiveRecord::Schema.define do t.boolean :value end + create_table :bulbs, :force => true do |t| + t.integer :car_id + t.string :name + end + create_table "CamelCase", :force => true do |t| t.string :name end @@ -194,15 +203,6 @@ ActiveRecord::Schema.define do t.integer :car_id end - create_table :tyres, :force => true do |t| - t.integer :car_id - end - - create_table :bulbs, :force => true do |t| - t.integer :car_id - t.string :name - end - create_table :entrants, :force => true do |t| t.string :name, :null => false t.integer :course_id, :null => false @@ -218,6 +218,9 @@ ActiveRecord::Schema.define do t.string :title, :limit => 5 end + create_table :eyes, :force => true do |t| + end + create_table :funny_jokes, :force => true do |t| t.string :name end @@ -227,13 +230,8 @@ ActiveRecord::Schema.define do t.string :info end - create_table :invoices, :force => true do |t| - t.integer :balance - t.datetime :updated_at - end - - create_table :items, :force => true do |t| - t.column :name, :string + create_table :guids, :force => true do |t| + t.column :key, :string end create_table :inept_wizards, :force => true do |t| @@ -242,6 +240,26 @@ ActiveRecord::Schema.define do t.column :type, :string end + create_table :integer_limits, :force => true do |t| + t.integer :"c_int_without_limit" + (1..8).each do |i| + t.integer :"c_int_#{i}", :limit => i + end + end + + create_table :invoices, :force => true do |t| + t.integer :balance + t.datetime :updated_at + end + + create_table :iris, :force => true do |t| + t.references :eye + t.string :color + end + + create_table :items, :force => true do |t| + t.column :name, :string + end create_table :jobs, :force => true do |t| t.integer :ideal_reference_id @@ -298,13 +316,6 @@ ActiveRecord::Schema.define do t.string :name end - create_table :references, :force => true do |t| - t.integer :person_id - t.integer :job_id - t.boolean :favourite - t.integer :lock_version, :default => 0 - end - create_table :minivans, :force => true, :id => false do |t| t.string :minivan_id t.string :name @@ -367,7 +378,6 @@ ActiveRecord::Schema.define do t.column :happy_at, :datetime end - create_table :paint_colors, :force => true do |t| t.integer :non_poly_one_id end @@ -454,6 +464,13 @@ ActiveRecord::Schema.define do t.boolean :skimmer, :default => false end + create_table :references, :force => true do |t| + t.integer :person_id + t.integer :job_id + t.boolean :favourite + t.integer :lock_version, :default => 0 + end + create_table :shape_expressions, :force => true do |t| t.string :paint_type t.integer :paint_id @@ -498,6 +515,18 @@ ActiveRecord::Schema.define do t.integer :book_id end + create_table :tags, :force => true do |t| + t.column :name, :string + t.column :taggings_count, :integer, :default => 0 + end + + create_table :taggings, :force => true do |t| + t.column :tag_id, :integer + t.column :super_tag_id, :integer + t.column :taggable_type, :string + t.column :taggable_id, :integer + end + create_table :tasks, :force => true do |t| t.datetime :starting t.datetime :ending @@ -523,18 +552,7 @@ ActiveRecord::Schema.define do t.string :parent_title t.string :type t.string :group - end - - create_table :taggings, :force => true do |t| - t.column :tag_id, :integer - t.column :super_tag_id, :integer - t.column :taggable_type, :string - t.column :taggable_id, :integer - end - - create_table :tags, :force => true do |t| - t.column :name, :string - t.column :taggings_count, :integer, :default => 0 + t.timestamps end create_table :toys, :primary_key => :toy_id ,:force => true do |t| @@ -556,6 +574,10 @@ ActiveRecord::Schema.define do t.column :looter_type, :string end + create_table :tyres, :force => true do |t| + t.integer :car_id + end + create_table :variants, :force => true do |t| t.references :product t.string :name @@ -573,17 +595,6 @@ ActiveRecord::Schema.define do create_table(t, :force => true) { } end - create_table :guids, :force => true do |t| - t.column :key, :string - end - - create_table :integer_limits, :force => true do |t| - t.integer :"c_int_without_limit" - (1..8).each do |i| - t.integer :"c_int_#{i}", :limit => i - end - end - # NOTE - the following 4 tables are used by models that have :inverse_of options on the associations create_table :men, :force => true do |t| t.string :name @@ -639,7 +650,6 @@ ActiveRecord::Schema.define do t.string :name end - except 'SQLite' do # fk_test_has_fk should be before fk_test_has_pk create_table :fk_test_has_fk, :force => true do |t| |