diff options
author | Gonçalo Silva <goncalossilva@gmail.com> | 2011-05-08 03:54:55 +0100 |
---|---|---|
committer | Gonçalo Silva <goncalossilva@gmail.com> | 2011-05-08 03:54:55 +0100 |
commit | aec7456f81985b88d6d604679d754636183b5b3a (patch) | |
tree | 798fcab8ae0c6e2c8c5a63e1f39308ff4bb5a20c /activerecord/test | |
parent | 1c2b2233c3a7ec76c0a0eddf5b8be45c489be133 (diff) | |
parent | 70f9558d0e4b8e605576693cbb489caa5cf6a2bc (diff) | |
download | rails-aec7456f81985b88d6d604679d754636183b5b3a.tar.gz rails-aec7456f81985b88d6d604679d754636183b5b3a.tar.bz2 rails-aec7456f81985b88d6d604679d754636183b5b3a.zip |
Merge branch 'master' of https://github.com/rails/rails into performance_test
Conflicts:
activesupport/lib/active_support/testing/performance.rb
Diffstat (limited to 'activerecord/test')
40 files changed, 1173 insertions, 364 deletions
diff --git a/activerecord/test/cases/adapters/mysql/reserved_word_test.rb b/activerecord/test/cases/adapters/mysql/reserved_word_test.rb index 43015098c9..292c7efebb 100644 --- a/activerecord/test/cases/adapters/mysql/reserved_word_test.rb +++ b/activerecord/test/cases/adapters/mysql/reserved_word_test.rb @@ -138,7 +138,7 @@ class MysqlReservedWordTest < ActiveRecord::TestCase private # custom fixture loader, uses Fixtures#create_fixtures and appends base_path to the current file's path def create_test_fixtures(*fixture_names) - Fixtures.create_fixtures(FIXTURES_ROOT + "/reserved_words", fixture_names) + ActiveRecord::Fixtures.create_fixtures(FIXTURES_ROOT + "/reserved_words", fixture_names) end # custom drop table, uses execute on connection to drop a table if it exists. note: escapes table_name diff --git a/activerecord/test/cases/adapters/mysql/schema_test.rb b/activerecord/test/cases/adapters/mysql/schema_test.rb index c6c1d1dad5..a2155d1dd1 100644 --- a/activerecord/test/cases/adapters/mysql/schema_test.rb +++ b/activerecord/test/cases/adapters/mysql/schema_test.rb @@ -31,6 +31,6 @@ module ActiveRecord def test_table_exists_wrong_schema assert(!@connection.table_exists?("#{@db_name}.zomg"), "table should not exist") end - end if current_adapter?(:MysqlAdapter) + end end end diff --git a/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb b/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb index 1efa7deaeb..752b864818 100644 --- a/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb +++ b/activerecord/test/cases/adapters/mysql2/reserved_word_test.rb @@ -138,7 +138,7 @@ class MysqlReservedWordTest < ActiveRecord::TestCase private # custom fixture loader, uses Fixtures#create_fixtures and appends base_path to the current file's path def create_test_fixtures(*fixture_names) - Fixtures.create_fixtures(FIXTURES_ROOT + "/reserved_words", fixture_names) + ActiveRecord::Fixtures.create_fixtures(FIXTURES_ROOT + "/reserved_words", fixture_names) end # custom drop table, uses execute on connection to drop a table if it exists. note: escapes table_name diff --git a/activerecord/test/cases/adapters/mysql2/schema_test.rb b/activerecord/test/cases/adapters/mysql2/schema_test.rb new file mode 100644 index 0000000000..858d1da2dd --- /dev/null +++ b/activerecord/test/cases/adapters/mysql2/schema_test.rb @@ -0,0 +1,36 @@ +require "cases/helper" +require 'models/post' +require 'models/comment' + +module ActiveRecord + module ConnectionAdapters + class Mysql2SchemaTest < ActiveRecord::TestCase + fixtures :posts + + def setup + @connection = ActiveRecord::Base.connection + db = Post.connection_pool.spec.config[:database] + table = Post.table_name + @db_name = db + + @omgpost = Class.new(Post) do + set_table_name "#{db}.#{table}" + def self.name; 'Post'; end + end + end + + def test_schema + assert @omgpost.find(:first) + end + + def test_table_exists? + name = @omgpost.table_name + assert @connection.table_exists?(name), "#{name} table should exist" + end + + def test_table_exists_wrong_schema + assert(!@connection.table_exists?("#{@db_name}.zomg"), "table should not exist") + end + end + end +end diff --git a/activerecord/test/cases/adapters/postgresql/datatype_test.rb b/activerecord/test/cases/adapters/postgresql/datatype_test.rb index 5bb8fa2f93..ce08e4c6a7 100644 --- a/activerecord/test/cases/adapters/postgresql/datatype_test.rb +++ b/activerecord/test/cases/adapters/postgresql/datatype_test.rb @@ -3,6 +3,9 @@ require "cases/helper" class PostgresqlArray < ActiveRecord::Base end +class PostgresqlTsvector < ActiveRecord::Base +end + class PostgresqlMoney < ActiveRecord::Base end @@ -34,6 +37,9 @@ class PostgresqlDataTypeTest < ActiveRecord::TestCase @connection.execute("INSERT INTO postgresql_arrays (commission_by_quarter, nicknames) VALUES ( '{35000,21000,18000,17000}', '{foo,bar,baz}' )") @first_array = PostgresqlArray.find(1) + @connection.execute("INSERT INTO postgresql_tsvectors (text_vector) VALUES (' ''text'' ''vector'' ')") + @first_tsvector = PostgresqlTsvector.find(1) + @connection.execute("INSERT INTO postgresql_moneys (wealth) VALUES ('567.89'::money)") @connection.execute("INSERT INTO postgresql_moneys (wealth) VALUES ('-567.89'::money)") @first_money = PostgresqlMoney.find(1) @@ -62,6 +68,10 @@ class PostgresqlDataTypeTest < ActiveRecord::TestCase assert_equal :string, @first_array.column_for_attribute(:nicknames).type end + def test_data_type_of_tsvector_types + assert_equal :tsvector, @first_tsvector.column_for_attribute(:text_vector).type + end + def test_data_type_of_money_types assert_equal :decimal, @first_money.column_for_attribute(:wealth).type end @@ -95,11 +105,26 @@ class PostgresqlDataTypeTest < ActiveRecord::TestCase assert_equal '{foo,bar,baz}', @first_array.nicknames end + def test_tsvector_values + assert_equal "'text' 'vector'", @first_tsvector.text_vector + end + def test_money_values assert_equal 567.89, @first_money.wealth assert_equal(-567.89, @second_money.wealth) end + def test_update_tsvector + new_text_vector = "'new' 'text' 'vector'" + assert @first_tsvector.text_vector = new_text_vector + assert @first_tsvector.save + assert @first_tsvector.reload + assert @first_tsvector.text_vector = new_text_vector + assert @first_tsvector.save + assert @first_tsvector.reload + assert_equal @first_tsvector.text_vector, new_text_vector + end + def test_number_values assert_equal 123.456, @first_number.single assert_equal 123456.789, @first_number.double diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb index 9006914508..ddcc36c841 100644 --- a/activerecord/test/cases/associations/belongs_to_associations_test.rb +++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb @@ -580,7 +580,7 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase post = posts(:welcome) comment = comments(:greetings) - assert_difference 'post.reload.taggings_count', -1 do + assert_difference lambda { post.reload.taggings_count }, -1 do assert_difference 'comment.reload.taggings_count', +1 do tagging.taggable = comment end diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb index 40c82f2fb8..3e92a77830 100644 --- a/activerecord/test/cases/associations/eager_test.rb +++ b/activerecord/test/cases/associations/eager_test.rb @@ -171,6 +171,16 @@ class EagerAssociationTest < ActiveRecord::TestCase end end + def test_associations_loaded_for_all_records + post = Post.create!(:title => 'foo', :body => "I like cars!") + SpecialComment.create!(:body => 'Come on!', :post => post) + first_category = Category.create! :name => 'First!', :posts => [post] + second_category = Category.create! :name => 'Second!', :posts => [post] + + categories = Category.where(:id => [first_category.id, second_category.id]).includes(:posts => :special_comments) + assert_equal categories.map { |category| category.posts.first.special_comments.loaded? }, [true, true] + end + def test_finding_with_includes_on_has_many_association_with_same_include_includes_only_once author_id = authors(:david).id author = assert_queries(3) { Author.find(author_id, :include => {:posts_with_comments => :comments}) } # find the author, then find the posts, then find the comments diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index 007f11b535..247decc67b 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -605,6 +605,30 @@ class HasManyAssociationsTest < ActiveRecord::TestCase assert_equal number_of_clients + 1, companies(:first_firm, :reload).clients.size end + def test_find_or_initialize_updates_collection_size + number_of_clients = companies(:first_firm).clients_of_firm.size + companies(:first_firm).clients_of_firm.find_or_initialize_by_name("name" => "Another Client") + assert_equal number_of_clients + 1, companies(:first_firm).clients_of_firm.size + end + + def test_find_or_create_with_hash + post = authors(:david).posts.find_or_create_by_title(:title => 'Yet another post', :body => 'somebody') + assert_equal post, authors(:david).posts.find_or_create_by_title(:title => 'Yet another post', :body => 'somebody') + assert post.persisted? + end + + def test_find_or_create_with_one_attribute_followed_by_hash + post = authors(:david).posts.find_or_create_by_title('Yet another post', :body => 'somebody') + assert_equal post, authors(:david).posts.find_or_create_by_title('Yet another post', :body => 'somebody') + assert post.persisted? + end + + def test_find_or_create_should_work_with_block + post = authors(:david).posts.find_or_create_by_title('Yet another post') {|p| p.body = 'somebody'} + assert_equal post, authors(:david).posts.find_or_create_by_title('Yet another post') {|p| p.body = 'somebody'} + assert post.persisted? + end + def test_deleting force_signal37_to_load_all_clients_of_firm companies(:first_firm).clients_of_firm.delete(companies(:first_firm).clients_of_firm.first) 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 1efe3420a0..89117593fd 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -44,7 +44,7 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase end def test_associate_existing - assert_queries(2) { posts(:thinking); people(:david) } + posts(:thinking); people(:david) # Warm cache assert_queries(1) do posts(:thinking).people << people(:david) @@ -760,7 +760,7 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase def test_primary_key_option_on_source post = posts(:welcome) category = categories(:general) - categorization = Categorization.create!(:post_id => post.id, :named_category_name => category.name) + Categorization.create!(:post_id => post.id, :named_category_name => category.name) assert_equal [category], post.named_categories assert_equal [category.name], post.named_category_ids # checks when target loaded diff --git a/activerecord/test/cases/associations/inner_join_association_test.rb b/activerecord/test/cases/associations/inner_join_association_test.rb index e2228228a3..124693f7c9 100644 --- a/activerecord/test/cases/associations/inner_join_association_test.rb +++ b/activerecord/test/cases/associations/inner_join_association_test.rb @@ -34,6 +34,17 @@ class InnerJoinAssociationTest < ActiveRecord::TestCase assert_no_match(/JOIN/i, sql) end + def test_join_conditions_added_to_join_clause + sql = Author.joins(:essays).to_sql + assert_match(/writer_type.*?=.*?Author/i, sql) + assert_no_match(/WHERE/i, sql) + end + + def test_join_conditions_allow_nil_associations + authors = Author.includes(:essays).where(:essays => {:id => nil}) + assert_equal 2, authors.count + end + def test_find_with_implicit_inner_joins_honors_readonly_without_select authors = Author.joins(:posts).to_a assert !authors.empty?, "expected authors to be non-empty" diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index e57c5b3b87..1775ba9999 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -18,7 +18,7 @@ require 'models/comment' require 'models/minimalistic' require 'models/warehouse_thing' require 'models/parrot' -require 'models/loose_person' +require 'models/person' require 'models/edge' require 'models/joke' require 'rexml/document' @@ -489,6 +489,12 @@ class BasicsTest < ActiveRecord::TestCase assert_equal 'value2', weird.send('a$b') end + def test_attributes_guard_protected_attributes_is_deprecated + attributes = { "title" => "An amazing title" } + topic = Topic.new + assert_deprecated { topic.send(:attributes=, attributes, false) } + end + def test_multiparameter_attributes_on_date attributes = { "last_read(1i)" => "2004", "last_read(2i)" => "6", "last_read(3i)" => "24" } topic = Topic.find(1) @@ -569,6 +575,29 @@ class BasicsTest < ActiveRecord::TestCase assert_equal Time.local(2004, 6, 24, 16, 24, 0), topic.written_on end + def test_multiparameter_attributes_on_time_with_no_date + ex = assert_raise(ActiveRecord::MultiparameterAssignmentErrors) do + attributes = { + "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "00" + } + topic = Topic.find(1) + topic.attributes = attributes + end + assert_equal("written_on", ex.errors[0].attribute) + end + + def test_multiparameter_attributes_on_time_with_invalid_time_params + ex = assert_raise(ActiveRecord::MultiparameterAssignmentErrors) do + attributes = { + "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24", + "written_on(4i)" => "2004", "written_on(5i)" => "36", "written_on(6i)" => "64", + } + topic = Topic.find(1) + topic.attributes = attributes + end + assert_equal("written_on", ex.errors[0].attribute) + end + def test_multiparameter_attributes_on_time_with_old_date attributes = { "written_on(1i)" => "1850", "written_on(2i)" => "6", "written_on(3i)" => "24", @@ -580,6 +609,82 @@ class BasicsTest < ActiveRecord::TestCase assert_equal "1850-06-24 16:24:00", topic.written_on.to_s(:db) end + def test_multiparameter_attributes_on_time_will_raise_on_big_time_if_missing_date_parts + ex = assert_raise(ActiveRecord::MultiparameterAssignmentErrors) do + attributes = { + "written_on(4i)" => "16", "written_on(5i)" => "24" + } + topic = Topic.find(1) + topic.attributes = attributes + end + assert_equal("written_on", ex.errors[0].attribute) + end + + def test_multiparameter_attributes_on_time_with_raise_on_small_time_if_missing_date_parts + ex = assert_raise(ActiveRecord::MultiparameterAssignmentErrors) do + attributes = { + "written_on(4i)" => "16", "written_on(5i)" => "12", "written_on(6i)" => "02" + } + topic = Topic.find(1) + topic.attributes = attributes + end + assert_equal("written_on", ex.errors[0].attribute) + end + + def test_multiparameter_attributes_on_time_will_ignore_hour_if_missing + attributes = { + "written_on(1i)" => "2004", "written_on(2i)" => "12", "written_on(3i)" => "12", + "written_on(5i)" => "12", "written_on(6i)" => "02" + } + topic = Topic.find(1) + topic.attributes = attributes + assert_equal Time.local(2004, 12, 12, 0, 12, 2), topic.written_on + end + + def test_multiparameter_attributes_on_time_will_ignore_hour_if_blank + attributes = { + "written_on(1i)" => "", "written_on(2i)" => "", "written_on(3i)" => "", + "written_on(4i)" => "", "written_on(5i)" => "12", "written_on(6i)" => "02" + } + topic = Topic.find(1) + topic.attributes = attributes + assert_equal 1, topic.written_on.year + assert_equal 1, topic.written_on.month + assert_equal 1, topic.written_on.day + assert_equal 0, topic.written_on.hour + assert_equal 12, topic.written_on.min + assert_equal 2, topic.written_on.sec + end + + def test_multiparameter_attributes_on_time_will_ignore_date_if_empty + attributes = { + "written_on(1i)" => "", "written_on(2i)" => "", "written_on(3i)" => "", + "written_on(4i)" => "16", "written_on(5i)" => "24" + } + topic = Topic.find(1) + topic.attributes = attributes + assert_equal 1, topic.written_on.year + assert_equal 1, topic.written_on.month + assert_equal 1, topic.written_on.day + assert_equal 16, topic.written_on.hour + assert_equal 24, topic.written_on.min + assert_equal 0, topic.written_on.sec + end + def test_multiparameter_attributes_on_time_with_seconds_will_ignore_date_if_empty + attributes = { + "written_on(1i)" => "", "written_on(2i)" => "", "written_on(3i)" => "", + "written_on(4i)" => "16", "written_on(5i)" => "12", "written_on(6i)" => "02" + } + topic = Topic.find(1) + topic.attributes = attributes + assert_equal 1, topic.written_on.year + assert_equal 1, topic.written_on.month + assert_equal 1, topic.written_on.day + assert_equal 16, topic.written_on.hour + assert_equal 12, topic.written_on.min + assert_equal 02, topic.written_on.sec + end + def test_multiparameter_attributes_on_time_with_utc ActiveRecord::Base.default_timezone = :utc attributes = { @@ -686,6 +791,42 @@ class BasicsTest < ActiveRecord::TestCase assert_equal address, customer.address end + def test_multiparameter_assignment_of_aggregation_out_of_order + customer = Customer.new + address = Address.new("The Street", "The City", "The Country") + attributes = { "address(3)" => address.country, "address(2)" => address.city, "address(1)" => address.street } + customer.attributes = attributes + assert_equal address, customer.address + end + + def test_multiparameter_assignment_of_aggregation_with_missing_values + ex = assert_raise(ActiveRecord::MultiparameterAssignmentErrors) do + customer = Customer.new + address = Address.new("The Street", "The City", "The Country") + attributes = { "address(2)" => address.city, "address(3)" => address.country } + customer.attributes = attributes + end + assert_equal("address", ex.errors[0].attribute) + end + + def test_multiparameter_assignment_of_aggregation_with_blank_values + customer = Customer.new + address = Address.new("The Street", "The City", "The Country") + attributes = { "address(1)" => "", "address(2)" => address.city, "address(3)" => address.country } + customer.attributes = attributes + assert_equal Address.new(nil, "The City", "The Country"), customer.address + end + + def test_multiparameter_assignment_of_aggregation_with_large_index + ex = assert_raise(ActiveRecord::MultiparameterAssignmentErrors) do + customer = Customer.new + address = Address.new("The Street", "The City", "The Country") + attributes = { "address(1)" => "The Street", "address(2)" => address.city, "address(3000)" => address.country } + customer.attributes = attributes + end + assert_equal("address", ex.errors[0].attribute) + end + def test_attributes_on_dummy_time # Oracle, and Sybase do not have a TIME datatype. return true if current_adapter?(:OracleAdapter, :SybaseAdapter) @@ -895,7 +1036,7 @@ class BasicsTest < ActiveRecord::TestCase assert g.save # Reload and check that we have all the geometric attributes. - h = Geometric.find(g.id) + h = ActiveRecord::IdentityMap.without { Geometric.find(g.id) } assert_equal '(5,6.1)', h.a_point assert_equal '[(2,3),(5.5,7)]', h.a_line_segment @@ -923,7 +1064,7 @@ class BasicsTest < ActiveRecord::TestCase assert g.save # Reload and check that we have all the geometric attributes. - h = Geometric.find(g.id) + h = ActiveRecord::IdentityMap.without { Geometric.find(g.id) } assert_equal '(5,6.1)', h.a_point assert_equal '[(2,3),(5.5,7)]', h.a_line_segment diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb index 655437318f..be4ba18555 100644 --- a/activerecord/test/cases/finder_test.rb +++ b/activerecord/test/cases/finder_test.rb @@ -1045,6 +1045,29 @@ class FinderTest < ActiveRecord::TestCase :order => ' author_addresses_authors.id DESC ', :limit => 3).size end + def test_find_with_nil_inside_set_passed_for_one_attribute + client_of = Company.find( + :all, + :conditions => { + :client_of => [2, 1, nil], + :name => ['37signals', 'Summit', 'Microsoft'] }, + :order => 'client_of DESC' + ).map { |x| x.client_of } + + assert client_of.include?(nil) + assert_equal [2, 1].sort, client_of.compact.sort + end + + def test_find_with_nil_inside_set_passed_for_attribute + client_of = Company.find( + :all, + :conditions => { :client_of => [nil] }, + :order => 'client_of DESC' + ).map { |x| x.client_of } + + assert_equal [], client_of.compact + end + def test_with_limiting_with_custom_select posts = Post.find(:all, :include => :author, :select => ' posts.*, authors.id as "author_id"', :limit => 3, :order => 'posts.id') assert_equal 3, posts.size diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb index fa40fad56d..2bf192e2c6 100644 --- a/activerecord/test/cases/fixtures_test.rb +++ b/activerecord/test/cases/fixtures_test.rb @@ -36,7 +36,7 @@ class FixturesTest < ActiveRecord::TestCase FIXTURES.each do |name| fixtures = nil assert_nothing_raised { fixtures = create_fixtures(name).first } - assert_kind_of(Fixtures, fixtures) + assert_kind_of(ActiveRecord::Fixtures, fixtures) fixtures.each { |_name, fixture| fixture.each { |key, value| assert_match(MATCH_ATTRIBUTE_NAME, key) @@ -45,11 +45,16 @@ class FixturesTest < ActiveRecord::TestCase end end + def test_create_fixtures + ActiveRecord::Fixtures.create_fixtures(FIXTURES_ROOT, "parrots") + assert Parrot.find_by_name('Curious George'), 'George is in the database' + end + def test_multiple_clean_fixtures fixtures_array = nil assert_nothing_raised { fixtures_array = create_fixtures(*FIXTURES) } assert_kind_of(Array, fixtures_array) - fixtures_array.each { |fixtures| assert_kind_of(Fixtures, fixtures) } + fixtures_array.each { |fixtures| assert_kind_of(ActiveRecord::Fixtures, fixtures) } end def test_attributes @@ -70,7 +75,7 @@ class FixturesTest < ActiveRecord::TestCase if ActiveRecord::Base.connection.supports_migrations? def test_inserts_with_pre_and_suffix # Reset cache to make finds on the new table work - Fixtures.reset_cache + ActiveRecord::Fixtures.reset_cache ActiveRecord::Base.connection.create_table :prefix_topics_suffix do |t| t.column :title, :string @@ -145,11 +150,11 @@ class FixturesTest < ActiveRecord::TestCase end def test_empty_yaml_fixture - assert_not_nil Fixtures.new( Account.connection, "accounts", 'Account', FIXTURES_ROOT + "/naked/yml/accounts") + assert_not_nil ActiveRecord::Fixtures.new( Account.connection, "accounts", 'Account', FIXTURES_ROOT + "/naked/yml/accounts") end def test_empty_yaml_fixture_with_a_comment_in_it - assert_not_nil Fixtures.new( Account.connection, "companies", 'Company', FIXTURES_ROOT + "/naked/yml/companies") + assert_not_nil ActiveRecord::Fixtures.new( Account.connection, "companies", 'Company', FIXTURES_ROOT + "/naked/yml/companies") end def test_nonexistent_fixture_file @@ -159,23 +164,23 @@ class FixturesTest < ActiveRecord::TestCase assert Dir[nonexistent_fixture_path+"*"].empty? assert_raise(FixturesFileNotFound) do - Fixtures.new( Account.connection, "companies", 'Company', nonexistent_fixture_path) + ActiveRecord::Fixtures.new( Account.connection, "companies", 'Company', nonexistent_fixture_path) end end def test_dirty_dirty_yaml_file - assert_raise(Fixture::FormatError) do - Fixtures.new( Account.connection, "courses", 'Course', FIXTURES_ROOT + "/naked/yml/courses") + assert_raise(ActiveRecord::Fixture::FormatError) do + ActiveRecord::Fixtures.new( Account.connection, "courses", 'Course', FIXTURES_ROOT + "/naked/yml/courses") end end def test_empty_csv_fixtures - assert_not_nil Fixtures.new( Account.connection, "accounts", 'Account', FIXTURES_ROOT + "/naked/csv/accounts") + assert_not_nil ActiveRecord::Fixtures.new( Account.connection, "accounts", 'Account', FIXTURES_ROOT + "/naked/csv/accounts") end def test_omap_fixtures assert_nothing_raised do - fixtures = Fixtures.new(Account.connection, 'categories', 'Category', FIXTURES_ROOT + "/categories_ordered") + fixtures = ActiveRecord::Fixtures.new(Account.connection, 'categories', 'Category', FIXTURES_ROOT + "/categories_ordered") i = 0 fixtures.each do |name, fixture| @@ -215,7 +220,7 @@ if Account.connection.respond_to?(:reset_pk_sequence!) def setup @instances = [Account.new(:credit_limit => 50), Company.new(:name => 'RoR Consulting')] - Fixtures.reset_cache # make sure tables get reinitialized + ActiveRecord::Fixtures.reset_cache # make sure tables get reinitialized end def test_resets_to_min_pk_with_specified_pk_and_sequence @@ -519,13 +524,13 @@ class FasterFixturesTest < ActiveRecord::TestCase def load_extra_fixture(name) fixture = create_fixtures(name).first - assert fixture.is_a?(Fixtures) + assert fixture.is_a?(ActiveRecord::Fixtures) @loaded_fixtures[fixture.table_name] = fixture end def test_cache - assert Fixtures.fixture_is_cached?(ActiveRecord::Base.connection, 'categories') - assert Fixtures.fixture_is_cached?(ActiveRecord::Base.connection, 'authors') + assert ActiveRecord::Fixtures.fixture_is_cached?(ActiveRecord::Base.connection, 'categories') + assert ActiveRecord::Fixtures.fixture_is_cached?(ActiveRecord::Base.connection, 'authors') assert_no_queries do create_fixtures('categories') @@ -533,7 +538,7 @@ class FasterFixturesTest < ActiveRecord::TestCase end load_extra_fixture('posts') - assert Fixtures.fixture_is_cached?(ActiveRecord::Base.connection, 'posts') + assert ActiveRecord::Fixtures.fixture_is_cached?(ActiveRecord::Base.connection, 'posts') self.class.setup_fixture_accessors('posts') assert_equal 'Welcome to the weblog', posts(:welcome).title end @@ -543,17 +548,17 @@ class FoxyFixturesTest < ActiveRecord::TestCase fixtures :parrots, :parrots_pirates, :pirates, :treasures, :mateys, :ships, :computers, :developers, :"admin/accounts", :"admin/users" def test_identifies_strings - assert_equal(Fixtures.identify("foo"), Fixtures.identify("foo")) - assert_not_equal(Fixtures.identify("foo"), Fixtures.identify("FOO")) + assert_equal(ActiveRecord::Fixtures.identify("foo"), ActiveRecord::Fixtures.identify("foo")) + assert_not_equal(ActiveRecord::Fixtures.identify("foo"), ActiveRecord::Fixtures.identify("FOO")) end def test_identifies_symbols - assert_equal(Fixtures.identify(:foo), Fixtures.identify(:foo)) + assert_equal(ActiveRecord::Fixtures.identify(:foo), ActiveRecord::Fixtures.identify(:foo)) end def test_identifies_consistently - assert_equal 207281424, Fixtures.identify(:ruby) - assert_equal 1066363776, Fixtures.identify(:sapphire_2) + assert_equal 207281424, ActiveRecord::Fixtures.identify(:ruby) + assert_equal 1066363776, ActiveRecord::Fixtures.identify(:sapphire_2) end TIMESTAMP_COLUMNS = %w(created_at created_on updated_at updated_on) diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb index fd20f1b120..fbb4ee6f7b 100644 --- a/activerecord/test/cases/helper.rb +++ b/activerecord/test/cases/helper.rb @@ -104,7 +104,7 @@ class ActiveSupport::TestCase self.use_transactional_fixtures = true def create_fixtures(*table_names, &block) - Fixtures.create_fixtures(ActiveSupport::TestCase.fixture_path, table_names, fixture_class_names, &block) + ActiveRecord::Fixtures.create_fixtures(ActiveSupport::TestCase.fixture_path, table_names, fixture_class_names, &block) end end diff --git a/activerecord/test/cases/identity_map/middleware_test.rb b/activerecord/test/cases/identity_map/middleware_test.rb new file mode 100644 index 0000000000..60dcad4586 --- /dev/null +++ b/activerecord/test/cases/identity_map/middleware_test.rb @@ -0,0 +1,71 @@ +require "cases/helper" + +module ActiveRecord + module IdentityMap + class MiddlewareTest < ActiveRecord::TestCase + def setup + super + @enabled = IdentityMap.enabled + IdentityMap.enabled = false + end + + def teardown + super + IdentityMap.enabled = @enabled + IdentityMap.clear + end + + def test_delegates + called = false + mw = Middleware.new lambda { |env| + called = true + } + mw.call({}) + assert called, 'middleware delegated' + end + + def test_im_enabled_during_delegation + mw = Middleware.new lambda { |env| + assert IdentityMap.enabled?, 'identity map should be enabled' + } + mw.call({}) + end + + class Enum < Struct.new(:iter) + def each(&b) + iter.call(&b) + end + end + + def test_im_enabled_during_body_each + mw = Middleware.new lambda { |env| + [200, {}, Enum.new(lambda { |&b| + assert IdentityMap.enabled?, 'identity map should be enabled' + b.call "hello" + })] + } + body = mw.call({}).last + body.each { |x| assert_equal 'hello', x } + end + + def test_im_disabled_after_body_close + mw = Middleware.new lambda { |env| [200, {}, []] } + body = mw.call({}).last + assert IdentityMap.enabled?, 'identity map should be enabled' + body.close + assert !IdentityMap.enabled?, 'identity map should be disabled' + end + + def test_im_cleared_after_body_close + mw = Middleware.new lambda { |env| [200, {}, []] } + body = mw.call({}).last + + IdentityMap.repository['hello'] = 'world' + assert !IdentityMap.repository.empty?, 'repo should not be empty' + + body.close + assert IdentityMap.repository.empty?, 'repo should be empty' + end + end + end +end diff --git a/activerecord/test/cases/identity_map_test.rb b/activerecord/test/cases/identity_map_test.rb index 199e59657d..a0e16400d2 100644 --- a/activerecord/test/cases/identity_map_test.rb +++ b/activerecord/test/cases/identity_map_test.rb @@ -1,4 +1,5 @@ require "cases/helper" + require 'models/developer' require 'models/project' require 'models/company' @@ -128,6 +129,41 @@ class IdentityMapTest < ActiveRecord::TestCase end ############################################################################## + # Tests checking if IM is functioning properly on classes with multiple # + # types of inheritance # + ############################################################################## + + def test_inherited_without_type_attribute_without_identity_map + ActiveRecord::IdentityMap.without do + p1 = DestructivePirate.create!(:catchphrase => "I'm not a regular Pirate") + p2 = Pirate.find(p1.id) + assert_not_same(p1, p2) + end + end + + def test_inherited_with_type_attribute_without_identity_map + ActiveRecord::IdentityMap.without do + c = comments(:sub_special_comment) + c1 = SubSpecialComment.find(c.id) + c2 = Comment.find(c.id) + assert_same(c1.class, c2.class) + end + end + + def test_inherited_without_type_attribute + p1 = DestructivePirate.create!(:catchphrase => "I'm not a regular Pirate") + p2 = Pirate.find(p1.id) + assert_not_same(p1, p2) + end + + def test_inherited_with_type_attribute + c = comments(:sub_special_comment) + c1 = SubSpecialComment.find(c.id) + c2 = Comment.find(c.id) + assert_same(c1, c2) + end + + ############################################################################## # Tests checking dirty attribute behaviour with IM # ############################################################################## @@ -137,8 +173,6 @@ class IdentityMapTest < ActiveRecord::TestCase assert_equal(["name"], swistak.changed) assert_equal({"name" => ["Marcin Raczkowski", "Swistak Sreberkowiec"]}, swistak.changes) - s = Subscriber.find('swistak') - assert swistak.name_changed? assert_equal("Swistak Sreberkowiec", swistak.name) end @@ -149,8 +183,6 @@ class IdentityMapTest < ActiveRecord::TestCase Subscriber.update_all({:name => "Raczkowski Marcin"}, {:name => "Marcin Raczkowski"}) - s = Subscriber.find('swistak') - assert_equal({"name"=>["Marcin Raczkowski", "Swistak Sreberkowiec"]}, swistak.changes) assert_equal("Swistak Sreberkowiec", swistak.name) end @@ -163,8 +195,6 @@ class IdentityMapTest < ActiveRecord::TestCase Subscriber.update_all({:name => "Swistak Sreberkowiec"}, {:name => "Marcin Raczkowski"}) - s = Subscriber.find('swistak') - assert_equal("Swistak Sreberkowiec", swistak.name) assert_equal({"name"=>["Marcin Raczkowski", "Swistak Sreberkowiec"]}, swistak.changes) assert swistak.name_changed? @@ -175,7 +205,7 @@ class IdentityMapTest < ActiveRecord::TestCase pirate.birds.create!(:name => 'Posideons Killer') pirate.birds.create!(:name => 'Killer bandita Dionne') - posideons, killer = pirate.birds + posideons, _ = pirate.birds pirate.reload @@ -388,15 +418,6 @@ class IdentityMapTest < ActiveRecord::TestCase assert_not_nil post.title end - def test_log - log = StringIO.new - ActiveRecord::Base.logger = Logger.new(log) - ActiveRecord::Base.logger.level = Logger::DEBUG - Post.find 1 - Post.find 1 - assert_match(/Post with ID = 1 loaded from Identity Map/, log.string) - end - # Currently AR is not allowing changing primary key (see Persistence#update) # So we ignore it. If this changes, this test needs to be uncommented. # def test_updating_of_pkey diff --git a/activerecord/test/cases/lifecycle_test.rb b/activerecord/test/cases/lifecycle_test.rb index 6cd8494c9e..643e949087 100644 --- a/activerecord/test/cases/lifecycle_test.rb +++ b/activerecord/test/cases/lifecycle_test.rb @@ -107,6 +107,23 @@ class ValidatedCommentObserver < ActiveRecord::Observer end end + +class AroundTopic < Topic +end + +class AroundTopicObserver < ActiveRecord::Observer + observe :around_topic + def topic_ids + @topic_ids ||= [] + end + + def around_save(topic) + topic_ids << topic.id + yield(topic) + topic_ids << topic.id + end +end + class LifecycleTest < ActiveRecord::TestCase fixtures :topics, :developers, :minimalistics @@ -206,6 +223,14 @@ class LifecycleTest < ActiveRecord::TestCase assert_equal developer, SalaryChecker.instance.last_saved end + test "around filter from observer should accept block" do + observer = AroundTopicObserver.instance + topic = AroundTopic.new + topic.save + assert_nil observer.topic_ids.first + assert_not_nil observer.topic_ids.last + end + def test_observer_is_called_once observer = DeveloperObserver.instance # activate observer.calls.clear diff --git a/activerecord/test/cases/log_subscriber_test.rb b/activerecord/test/cases/log_subscriber_test.rb index 5f55299065..c6c6079490 100644 --- a/activerecord/test/cases/log_subscriber_test.rb +++ b/activerecord/test/cases/log_subscriber_test.rb @@ -1,11 +1,14 @@ require "cases/helper" require "models/developer" +require "models/post" require "active_support/log_subscriber/test_helper" class LogSubscriberTest < ActiveRecord::TestCase include ActiveSupport::LogSubscriber::TestHelper include ActiveSupport::BufferedLogger::Severity + fixtures :posts + def setup @old_logger = ActiveRecord::Base.logger @using_identity_map = ActiveRecord::IdentityMap.enabled? @@ -91,4 +94,13 @@ class LogSubscriberTest < ActiveRecord::TestCase def test_initializes_runtime Thread.new { assert_equal 0, ActiveRecord::LogSubscriber.runtime }.join end + + def test_log + ActiveRecord::IdentityMap.use do + Post.find 1 + Post.find 1 + end + wait + assert_match(/From Identity Map/, @logger.logged(:debug).last) + end end diff --git a/activerecord/test/cases/mass_assignment_security_test.rb b/activerecord/test/cases/mass_assignment_security_test.rb index 025ec1d3fa..fbbae99e8b 100644 --- a/activerecord/test/cases/mass_assignment_security_test.rb +++ b/activerecord/test/cases/mass_assignment_security_test.rb @@ -3,8 +3,65 @@ require 'models/company' require 'models/subscriber' require 'models/keyboard' require 'models/task' +require 'models/person' + + +module MassAssignmentTestHelpers + def setup + # another AR test modifies the columns which causes issues with create calls + TightPerson.reset_column_information + LoosePerson.reset_column_information + end + + def attributes_hash + { + :id => 5, + :first_name => 'Josh', + :gender => 'm', + :comments => 'rides a sweet bike' + } + end + + def assert_default_attributes(person, create = false) + unless create + assert_nil person.id + else + assert !!person.id + end + assert_equal 'Josh', person.first_name + assert_equal 'm', person.gender + assert_nil person.comments + end + + def assert_admin_attributes(person, create = false) + unless create + assert_nil person.id + else + assert !!person.id + end + assert_equal 'Josh', person.first_name + assert_equal 'm', person.gender + assert_equal 'rides a sweet bike', person.comments + end + + def assert_all_attributes(person) + assert_equal 5, person.id + assert_equal 'Josh', person.first_name + assert_equal 'm', person.gender + assert_equal 'rides a sweet bike', person.comments + end +end + +module MassAssignmentRelationTestHelpers + def setup + super + @person = LoosePerson.create(attributes_hash) + end +end + class MassAssignmentSecurityTest < ActiveRecord::TestCase + include MassAssignmentTestHelpers def test_customized_primary_key_remains_protected subscriber = Subscriber.new(:nick => 'webster123', :name => 'nice try') @@ -30,6 +87,120 @@ class MassAssignmentSecurityTest < ActiveRecord::TestCase end end + def test_assign_attributes_uses_default_scope_when_no_scope_is_provided + p = LoosePerson.new + p.assign_attributes(attributes_hash) + + assert_default_attributes(p) + end + + def test_assign_attributes_skips_mass_assignment_security_protection_when_without_protection_is_used + p = LoosePerson.new + p.assign_attributes(attributes_hash, :without_protection => true) + + assert_all_attributes(p) + end + + def test_assign_attributes_with_default_scope_and_attr_protected_attributes + p = LoosePerson.new + p.assign_attributes(attributes_hash, :as => :default) + + assert_default_attributes(p) + end + + def test_assign_attributes_with_admin_scope_and_attr_protected_attributes + p = LoosePerson.new + p.assign_attributes(attributes_hash, :as => :admin) + + assert_admin_attributes(p) + end + + def test_assign_attributes_with_default_scope_and_attr_accessible_attributes + p = TightPerson.new + p.assign_attributes(attributes_hash, :as => :default) + + assert_default_attributes(p) + end + + def test_assign_attributes_with_admin_scope_and_attr_accessible_attributes + p = TightPerson.new + p.assign_attributes(attributes_hash, :as => :admin) + + assert_admin_attributes(p) + end + + def test_new_with_attr_accessible_attributes + p = TightPerson.new(attributes_hash) + + assert_default_attributes(p) + end + + def test_new_with_attr_protected_attributes + p = LoosePerson.new(attributes_hash) + + assert_default_attributes(p) + end + + def test_create_with_attr_accessible_attributes + p = TightPerson.create(attributes_hash) + + assert_default_attributes(p, true) + end + + def test_create_with_attr_protected_attributes + p = LoosePerson.create(attributes_hash) + + assert_default_attributes(p, true) + end + + def test_new_with_admin_scope_with_attr_accessible_attributes + p = TightPerson.new(attributes_hash, :as => :admin) + + assert_admin_attributes(p) + end + + def test_new_with_admin_scope_with_attr_protected_attributes + p = LoosePerson.new(attributes_hash, :as => :admin) + + assert_admin_attributes(p) + end + + def test_create_with_admin_scope_with_attr_accessible_attributes + p = TightPerson.create(attributes_hash, :as => :admin) + + assert_admin_attributes(p, true) + end + + def test_create_with_admin_scope_with_attr_protected_attributes + p = LoosePerson.create(attributes_hash, :as => :admin) + + assert_admin_attributes(p, true) + end + + def test_new_with_without_protection_with_attr_accessible_attributes + p = TightPerson.new(attributes_hash, :without_protection => true) + + assert_all_attributes(p) + end + + def test_new_with_without_protection_with_attr_protected_attributes + p = LoosePerson.new(attributes_hash, :without_protection => true) + + assert_all_attributes(p) + end + + def test_create_with_without_protection_with_attr_accessible_attributes + p = TightPerson.create(attributes_hash, :without_protection => true) + + assert_all_attributes(p) + end + + def test_create_with_without_protection_with_attr_protected_attributes + p = LoosePerson.create(attributes_hash, :without_protection => true) + + assert_all_attributes(p) + end + def test_protection_against_class_attribute_writers [:logger, :configurations, :primary_key_prefix_type, :table_name_prefix, :table_name_suffix, :pluralize_table_names, :default_timezone, :schema_format, :lock_optimistically, :record_timestamps].each do |method| @@ -40,4 +211,268 @@ class MassAssignmentSecurityTest < ActiveRecord::TestCase end end -end
\ No newline at end of file +end + + +class MassAssignmentSecurityHasOneRelationsTest < ActiveRecord::TestCase + include MassAssignmentTestHelpers + include MassAssignmentRelationTestHelpers + + # build + + def test_has_one_build_with_attr_protected_attributes + best_friend = @person.build_best_friend(attributes_hash) + assert_default_attributes(best_friend) + end + + def test_has_one_build_with_attr_accessible_attributes + best_friend = @person.build_best_friend(attributes_hash) + assert_default_attributes(best_friend) + end + + def test_has_one_build_with_admin_scope_with_attr_protected_attributes + best_friend = @person.build_best_friend(attributes_hash, :as => :admin) + assert_admin_attributes(best_friend) + end + + def test_has_one_build_with_admin_scope_with_attr_accessible_attributes + best_friend = @person.build_best_friend(attributes_hash, :as => :admin) + assert_admin_attributes(best_friend) + end + + def test_has_one_build_without_protection + best_friend = @person.build_best_friend(attributes_hash, :without_protection => true) + assert_all_attributes(best_friend) + end + + # create + + def test_has_one_create_with_attr_protected_attributes + best_friend = @person.create_best_friend(attributes_hash) + assert_default_attributes(best_friend, true) + end + + def test_has_one_create_with_attr_accessible_attributes + best_friend = @person.create_best_friend(attributes_hash) + assert_default_attributes(best_friend, true) + end + + def test_has_one_create_with_admin_scope_with_attr_protected_attributes + best_friend = @person.create_best_friend(attributes_hash, :as => :admin) + assert_admin_attributes(best_friend, true) + end + + def test_has_one_create_with_admin_scope_with_attr_accessible_attributes + best_friend = @person.create_best_friend(attributes_hash, :as => :admin) + assert_admin_attributes(best_friend, true) + end + + def test_has_one_create_without_protection + best_friend = @person.create_best_friend(attributes_hash, :without_protection => true) + assert_all_attributes(best_friend) + end + + # create! + + def test_has_one_create_with_bang_with_attr_protected_attributes + best_friend = @person.create_best_friend!(attributes_hash) + assert_default_attributes(best_friend, true) + end + + def test_has_one_create_with_bang_with_attr_accessible_attributes + best_friend = @person.create_best_friend!(attributes_hash) + assert_default_attributes(best_friend, true) + end + + def test_has_one_create_with_bang_with_admin_scope_with_attr_protected_attributes + best_friend = @person.create_best_friend!(attributes_hash, :as => :admin) + assert_admin_attributes(best_friend, true) + end + + def test_has_one_create_with_bang_with_admin_scope_with_attr_accessible_attributes + best_friend = @person.create_best_friend!(attributes_hash, :as => :admin) + assert_admin_attributes(best_friend, true) + end + + def test_has_one_create_with_bang_without_protection + best_friend = @person.create_best_friend!(attributes_hash, :without_protection => true) + assert_all_attributes(best_friend) + end + +end + + +class MassAssignmentSecurityBelongsToRelationsTest < ActiveRecord::TestCase + include MassAssignmentTestHelpers + include MassAssignmentRelationTestHelpers + + # build + + def test_has_one_build_with_attr_protected_attributes + best_friend = @person.build_best_friend_of(attributes_hash) + assert_default_attributes(best_friend) + end + + def test_has_one_build_with_attr_accessible_attributes + best_friend = @person.build_best_friend_of(attributes_hash) + assert_default_attributes(best_friend) + end + + def test_has_one_build_with_admin_scope_with_attr_protected_attributes + best_friend = @person.build_best_friend_of(attributes_hash, :as => :admin) + assert_admin_attributes(best_friend) + end + + def test_has_one_build_with_admin_scope_with_attr_accessible_attributes + best_friend = @person.build_best_friend_of(attributes_hash, :as => :admin) + assert_admin_attributes(best_friend) + end + + def test_has_one_build_without_protection + best_friend = @person.build_best_friend_of(attributes_hash, :without_protection => true) + assert_all_attributes(best_friend) + end + + # create + + def test_has_one_create_with_attr_protected_attributes + best_friend = @person.create_best_friend_of(attributes_hash) + assert_default_attributes(best_friend, true) + end + + def test_has_one_create_with_attr_accessible_attributes + best_friend = @person.create_best_friend_of(attributes_hash) + assert_default_attributes(best_friend, true) + end + + def test_has_one_create_with_admin_scope_with_attr_protected_attributes + best_friend = @person.create_best_friend_of(attributes_hash, :as => :admin) + assert_admin_attributes(best_friend, true) + end + + def test_has_one_create_with_admin_scope_with_attr_accessible_attributes + best_friend = @person.create_best_friend_of(attributes_hash, :as => :admin) + assert_admin_attributes(best_friend, true) + end + + def test_has_one_create_without_protection + best_friend = @person.create_best_friend_of(attributes_hash, :without_protection => true) + assert_all_attributes(best_friend) + end + + # create! + + def test_has_one_create_with_bang_with_attr_protected_attributes + best_friend = @person.create_best_friend!(attributes_hash) + assert_default_attributes(best_friend, true) + end + + def test_has_one_create_with_bang_with_attr_accessible_attributes + best_friend = @person.create_best_friend!(attributes_hash) + assert_default_attributes(best_friend, true) + end + + def test_has_one_create_with_bang_with_admin_scope_with_attr_protected_attributes + best_friend = @person.create_best_friend!(attributes_hash, :as => :admin) + assert_admin_attributes(best_friend, true) + end + + def test_has_one_create_with_bang_with_admin_scope_with_attr_accessible_attributes + best_friend = @person.create_best_friend!(attributes_hash, :as => :admin) + assert_admin_attributes(best_friend, true) + end + + def test_has_one_create_with_bang_without_protection + best_friend = @person.create_best_friend!(attributes_hash, :without_protection => true) + assert_all_attributes(best_friend) + end + +end + + +class MassAssignmentSecurityHasManyRelationsTest < ActiveRecord::TestCase + include MassAssignmentTestHelpers + include MassAssignmentRelationTestHelpers + + # build + + def test_has_one_build_with_attr_protected_attributes + best_friend = @person.best_friends.build(attributes_hash) + assert_default_attributes(best_friend) + end + + def test_has_one_build_with_attr_accessible_attributes + best_friend = @person.best_friends.build(attributes_hash) + assert_default_attributes(best_friend) + end + + def test_has_one_build_with_admin_scope_with_attr_protected_attributes + best_friend = @person.best_friends.build(attributes_hash, :as => :admin) + assert_admin_attributes(best_friend) + end + + def test_has_one_build_with_admin_scope_with_attr_accessible_attributes + best_friend = @person.best_friends.build(attributes_hash, :as => :admin) + assert_admin_attributes(best_friend) + end + + def test_has_one_build_without_protection + best_friend = @person.best_friends.build(attributes_hash, :without_protection => true) + assert_all_attributes(best_friend) + end + + # create + + def test_has_one_create_with_attr_protected_attributes + best_friend = @person.best_friends.create(attributes_hash) + assert_default_attributes(best_friend, true) + end + + def test_has_one_create_with_attr_accessible_attributes + best_friend = @person.best_friends.create(attributes_hash) + assert_default_attributes(best_friend, true) + end + + def test_has_one_create_with_admin_scope_with_attr_protected_attributes + best_friend = @person.best_friends.create(attributes_hash, :as => :admin) + assert_admin_attributes(best_friend, true) + end + + def test_has_one_create_with_admin_scope_with_attr_accessible_attributes + best_friend = @person.best_friends.create(attributes_hash, :as => :admin) + assert_admin_attributes(best_friend, true) + end + + def test_has_one_create_without_protection + best_friend = @person.best_friends.create(attributes_hash, :without_protection => true) + assert_all_attributes(best_friend) + end + + # create! + + def test_has_one_create_with_bang_with_attr_protected_attributes + best_friend = @person.best_friends.create!(attributes_hash) + assert_default_attributes(best_friend, true) + end + + def test_has_one_create_with_bang_with_attr_accessible_attributes + best_friend = @person.best_friends.create!(attributes_hash) + assert_default_attributes(best_friend, true) + end + + def test_has_one_create_with_bang_with_admin_scope_with_attr_protected_attributes + best_friend = @person.best_friends.create!(attributes_hash, :as => :admin) + assert_admin_attributes(best_friend, true) + end + + def test_has_one_create_with_bang_with_admin_scope_with_attr_accessible_attributes + best_friend = @person.best_friends.create!(attributes_hash, :as => :admin) + assert_admin_attributes(best_friend, true) + end + + def test_has_one_create_with_bang_without_protection + best_friend = @person.best_friends.create!(attributes_hash, :without_protection => true) + assert_all_attributes(best_friend) + end + +end diff --git a/activerecord/test/cases/named_scope_test.rb b/activerecord/test/cases/named_scope_test.rb index 2880fdc651..8fd1fc2577 100644 --- a/activerecord/test/cases/named_scope_test.rb +++ b/activerecord/test/cases/named_scope_test.rb @@ -471,12 +471,6 @@ class NamedScopeTest < ActiveRecord::TestCase require "models/without_table" end end - - def test_scopes_with_callables_are_deprecated - assert_deprecated do - Post.scope :WE_SO_EXCITED, lambda { |partyingpartyingpartying, yeah| fun!.fun!.fun! } - end - end end class DynamicScopeMatchTest < ActiveRecord::TestCase diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb index 9aa13f04cd..b066575af8 100644 --- a/activerecord/test/cases/persistence_test.rb +++ b/activerecord/test/cases/persistence_test.rb @@ -12,7 +12,7 @@ require 'models/minimalistic' require 'models/warehouse_thing' require 'models/parrot' require 'models/minivan' -require 'models/loose_person' +require 'models/person' require 'rexml/document' require 'active_support/core_ext/exception' @@ -491,6 +491,26 @@ class PersistencesTest < ActiveRecord::TestCase assert_equal "The First Topic", topic.title end + def test_update_attributes_as_admin + person = TightPerson.create({ "first_name" => 'Joshua' }) + person.update_attributes({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :as => :admin) + person.reload + + assert_equal 'Josh', person.first_name + assert_equal 'm', person.gender + assert_equal 'from NZ', person.comments + end + + def test_update_attributes_without_protection + person = TightPerson.create({ "first_name" => 'Joshua' }) + person.update_attributes({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :without_protection => true) + person.reload + + assert_equal 'Josh', person.first_name + assert_equal 'm', person.gender + assert_equal 'from NZ', person.comments + end + def test_update_attributes! Reply.validates_presence_of(:title) reply = Reply.find(2) @@ -512,6 +532,26 @@ class PersistencesTest < ActiveRecord::TestCase Reply.reset_callbacks(:validate) end + def test_update_attributes_with_bang_as_admin + person = TightPerson.create({ "first_name" => 'Joshua' }) + person.update_attributes!({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :as => :admin) + person.reload + + assert_equal 'Josh', person.first_name + assert_equal 'm', person.gender + assert_equal 'from NZ', person.comments + end + + def test_update_attributestes_with_bang_without_protection + person = TightPerson.create({ "first_name" => 'Joshua' }) + person.update_attributes!({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :without_protection => true) + person.reload + + assert_equal 'Josh', person.first_name + assert_equal 'm', person.gender + assert_equal 'from NZ', person.comments + end + def test_destroyed_returns_boolean developer = Developer.first assert_equal false, developer.destroyed? diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb index 287f7e255b..a61180cfaf 100644 --- a/activerecord/test/cases/query_cache_test.rb +++ b/activerecord/test/cases/query_cache_test.rb @@ -10,6 +10,70 @@ class QueryCacheTest < ActiveRecord::TestCase def setup Task.connection.clear_query_cache + ActiveRecord::Base.connection.disable_query_cache! + end + + def test_middleware_delegates + called = false + mw = ActiveRecord::QueryCache.new lambda { |env| + called = true + } + mw.call({}) + assert called, 'middleware should delegate' + end + + def test_middleware_caches + mw = ActiveRecord::QueryCache.new lambda { |env| + Task.find 1 + Task.find 1 + assert_equal 1, ActiveRecord::Base.connection.query_cache.length + } + mw.call({}) + end + + def test_cache_enabled_during_call + assert !ActiveRecord::Base.connection.query_cache_enabled, 'cache off' + + mw = ActiveRecord::QueryCache.new lambda { |env| + assert ActiveRecord::Base.connection.query_cache_enabled, 'cache on' + } + mw.call({}) + end + + def test_cache_on_during_body_write + streaming = Class.new do + def each + yield ActiveRecord::Base.connection.query_cache_enabled + end + end + + mw = ActiveRecord::QueryCache.new lambda { |env| + [200, {}, streaming.new] + } + body = mw.call({}).last + body.each { |x| assert x, 'cache should be on' } + body.close + assert !ActiveRecord::Base.connection.query_cache_enabled, 'cache disabled' + end + + def test_cache_off_after_close + mw = ActiveRecord::QueryCache.new lambda { |env| } + body = mw.call({}).last + + assert ActiveRecord::Base.connection.query_cache_enabled, 'cache enabled' + body.close + assert !ActiveRecord::Base.connection.query_cache_enabled, 'cache disabled' + end + + def test_cache_clear_after_close + mw = ActiveRecord::QueryCache.new lambda { |env| + Post.find(:first) + } + body = mw.call({}).last + + assert !ActiveRecord::Base.connection.query_cache.empty?, 'cache not empty' + body.close + assert ActiveRecord::Base.connection.query_cache.empty?, 'cache should be empty' end def test_find_queries diff --git a/activerecord/test/cases/relation_scoping_test.rb b/activerecord/test/cases/relation_scoping_test.rb index 5079aec9ba..864b3d4846 100644 --- a/activerecord/test/cases/relation_scoping_test.rb +++ b/activerecord/test/cases/relation_scoping_test.rb @@ -308,6 +308,22 @@ class DefaultScopingTest < ActiveRecord::TestCase assert_equal expected, received end + def test_default_scope_as_class_method + assert_equal [developers(:david).becomes(ClassMethodDeveloperCalledDavid)], ClassMethodDeveloperCalledDavid.all + end + + def test_default_scope_with_lambda + assert_equal [developers(:david).becomes(LazyLambdaDeveloperCalledDavid)], LazyLambdaDeveloperCalledDavid.all + end + + def test_default_scope_with_block + assert_equal [developers(:david).becomes(LazyBlockDeveloperCalledDavid)], LazyBlockDeveloperCalledDavid.all + end + + def test_default_scope_with_callable + assert_equal [developers(:david).becomes(CallableDeveloperCalledDavid)], CallableDeveloperCalledDavid.all + end + def test_default_scope_is_unscoped_on_find assert_equal 1, DeveloperCalledDavid.count assert_equal 11, DeveloperCalledDavid.unscoped.count @@ -339,6 +355,18 @@ class DefaultScopingTest < ActiveRecord::TestCase assert_equal 50000, wheres[:salary] end + def test_default_scope_with_module_includes + wheres = ModuleIncludedPoorDeveloperCalledJamis.scoped.where_values_hash + assert_equal "Jamis", wheres[:name] + assert_equal 50000, wheres[:salary] + end + + def test_default_scope_with_multiple_calls + wheres = MultiplePoorDeveloperCalledJamis.scoped.where_values_hash + assert_equal "Jamis", wheres[:name] + assert_equal 50000, wheres[: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 } @@ -435,174 +463,3 @@ class DefaultScopingTest < ActiveRecord::TestCase assert_equal 10, DeveloperCalledJamis.unscoped.poor.length end end - -class DeprecatedDefaultScopingTest < ActiveRecord::TestCase - fixtures :developers, :posts - - def test_default_scope - expected = Developer.find(:all, :order => 'salary DESC').collect { |dev| dev.salary } - received = DeprecatedDeveloperOrderedBySalary.find(:all).collect { |dev| dev.salary } - assert_equal expected, received - end - - def test_default_scope_is_unscoped_on_find - assert_equal 1, DeprecatedDeveloperCalledDavid.count - assert_equal 11, DeprecatedDeveloperCalledDavid.unscoped.count - end - - def test_default_scope_is_unscoped_on_create - assert_nil DeprecatedDeveloperCalledJamis.unscoped.create!.name - end - - def test_default_scope_with_conditions_string - assert_equal Developer.find_all_by_name('David').map(&:id).sort, DeprecatedDeveloperCalledDavid.find(:all).map(&:id).sort - assert_equal nil, DeprecatedDeveloperCalledDavid.create!.name - end - - def test_default_scope_with_conditions_hash - assert_equal Developer.find_all_by_name('Jamis').map(&:id).sort, DeprecatedDeveloperCalledJamis.find(:all).map(&:id).sort - assert_equal 'Jamis', DeprecatedDeveloperCalledJamis.create!.name - end - - def test_default_scoping_with_threads - 2.times do - Thread.new { assert DeprecatedDeveloperOrderedBySalary.scoped.to_sql.include?('salary DESC') }.join - end - end - - def test_default_scoping_with_inheritance - # Inherit a class having a default scope and define a new default scope - klass = Class.new(DeprecatedDeveloperOrderedBySalary) - ActiveSupport::Deprecation.silence { klass.send :default_scope, :limit => 1 } - - # Scopes added on children should append to parent scope - assert_equal [developers(:jamis).id], klass.all.map(&:id) - - # Parent should still have the original scope - assert_equal Developer.order('salary DESC').map(&:id), DeprecatedDeveloperOrderedBySalary.all.map(&:id) - end - - def test_default_scope_called_twice_merges_conditions - 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) - ActiveSupport::Deprecation.silence do - klass.__send__ :default_scope, :conditions => { :name => "David" } - klass.__send__ :default_scope, :conditions => { :salary => 100000 } - end - assert_equal 1, klass.count - assert_equal "David", klass.first.name - 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) - ActiveSupport::Deprecation.silence do - klass.class_eval do - default_scope where("name = 'David'") - default_scope where("salary = 100000") - end - 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 = DeprecatedDeveloperOrderedBySalary.all_ordered_by_name.collect { |dev| dev.salary } - assert_equal expected, received - end - - def test_nested_scope - expected = Developer.find(:all, :order => 'salary DESC, name DESC').collect { |dev| dev.salary } - received = DeprecatedDeveloperOrderedBySalary.send(:with_scope, :find => { :order => 'name DESC'}) do - DeprecatedDeveloperOrderedBySalary.find(:all).collect { |dev| dev.salary } - end - assert_equal expected, received - end - - def test_scope_overwrites_default - expected = Developer.find(:all, :order => 'salary DESC, name DESC').collect { |dev| dev.name } - received = DeprecatedDeveloperOrderedBySalary.by_name.find(:all).collect { |dev| dev.name } - assert_equal expected, received - end - - def test_reorder_overrides_default_scope_order - expected = Developer.order('name DESC').collect { |dev| dev.name } - received = DeprecatedDeveloperOrderedBySalary.reorder('name DESC').collect { |dev| dev.name } - assert_equal expected, received - end - - def test_nested_exclusive_scope - expected = Developer.find(:all, :limit => 100).collect { |dev| dev.salary } - received = DeprecatedDeveloperOrderedBySalary.send(:with_exclusive_scope, :find => { :limit => 100 }) do - DeprecatedDeveloperOrderedBySalary.find(:all).collect { |dev| dev.salary } - end - assert_equal expected, received - end - - def test_order_in_default_scope_should_prevail - expected = Developer.find(:all, :order => 'salary desc').collect { |dev| dev.salary } - received = DeprecatedDeveloperOrderedBySalary.find(:all, :order => 'salary').collect { |dev| dev.salary } - assert_equal expected, received - end - - def test_default_scope_using_relation - posts = DeprecatedPostWithComment.scoped - assert_equal 2, posts.to_a.length - assert_equal posts(:thinking), posts.first - end - - def test_create_attribute_overwrites_default_scoping - assert_equal 'David', DeprecatedPoorDeveloperCalledJamis.create!(:name => 'David').name - assert_equal 200000, DeprecatedPoorDeveloperCalledJamis.create!(:name => 'David', :salary => 200000).salary - end - - def test_create_attribute_overwrites_default_values - assert_equal nil, DeprecatedPoorDeveloperCalledJamis.create!(:salary => nil).salary - assert_equal 50000, DeprecatedPoorDeveloperCalledJamis.create!(:name => 'David').salary - end - - def test_default_scope_attribute - jamis = DeprecatedPoorDeveloperCalledJamis.new(:name => 'David') - assert_equal 50000, jamis.salary - end - - def test_where_attribute - aaron = DeprecatedPoorDeveloperCalledJamis.where(:salary => 20).new(:name => 'Aaron') - assert_equal 20, aaron.salary - assert_equal 'Aaron', aaron.name - end - - def test_where_attribute_merge - aaron = DeprecatedPoorDeveloperCalledJamis.where(:name => 'foo').new(:name => 'Aaron') - assert_equal 'Aaron', aaron.name - end - - def test_create_with_merge - aaron = DeprecatedPoorDeveloperCalledJamis.create_with(:name => 'foo', :salary => 20).merge( - DeprecatedPoorDeveloperCalledJamis.create_with(:name => 'Aaron')).new - assert_equal 20, aaron.salary - assert_equal 'Aaron', aaron.name - - aaron = DeprecatedPoorDeveloperCalledJamis.create_with(:name => 'foo', :salary => 20). - create_with(:name => 'Aaron').new - assert_equal 20, aaron.salary - assert_equal 'Aaron', aaron.name - end - - def test_create_with_reset - jamis = DeprecatedPoorDeveloperCalledJamis.create_with(:name => 'Aaron').create_with(nil).new - assert_equal 'Jamis', jamis.name - end -end diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb index 9b2c7c00df..e8f2f44189 100644 --- a/activerecord/test/cases/schema_dumper_test.rb +++ b/activerecord/test/cases/schema_dumper_test.rb @@ -203,6 +203,13 @@ class SchemaDumperTest < ActiveRecord::TestCase assert_match %r{t.xml "data"}, output end end + + def test_schema_dump_includes_tsvector_shorthand_definition + output = standard_dump + if %r{create_table "postgresql_tsvectors"} =~ output + assert_match %r{t.tsvector "text_vector"}, output + end + end end def test_schema_dump_keeps_large_precision_integer_columns_as_decimal diff --git a/activerecord/test/cases/validations/uniqueness_validation_test.rb b/activerecord/test/cases/validations/uniqueness_validation_test.rb index b4f3dd034c..0f1b3667cc 100644 --- a/activerecord/test/cases/validations/uniqueness_validation_test.rb +++ b/activerecord/test/cases/validations/uniqueness_validation_test.rb @@ -162,6 +162,32 @@ class UniquenessValidationTest < ActiveRecord::TestCase end end + def test_validate_case_sensitive_uniqueness_with_special_sql_like_chars + Topic.validates_uniqueness_of(:title, :case_sensitive => true) + + t = Topic.new("title" => "I'm unique!") + assert t.save, "Should save t as unique" + + t2 = Topic.new("title" => "I'm %") + assert t2.save, "Should save t2 as unique" + + t3 = Topic.new("title" => "I'm uniqu_!") + assert t3.save, "Should save t3 as unique" + end + + def test_validate_case_insensitive_uniqueness_with_special_sql_like_chars + Topic.validates_uniqueness_of(:title, :case_sensitive => false) + + t = Topic.new("title" => "I'm unique!") + assert t.save, "Should save t as unique" + + t2 = Topic.new("title" => "I'm %") + assert t2.save, "Should save t2 as unique" + + t3 = Topic.new("title" => "I'm uniqu_!") + assert t3.save, "Should save t3 as unique" + end + def test_validate_case_sensitive_uniqueness Topic.validates_uniqueness_of(:title, :case_sensitive => true, :allow_nil => true) diff --git a/activerecord/test/fixtures/mateys.yml b/activerecord/test/fixtures/mateys.yml index 9ecdd4ecd5..d3690955fc 100644 --- a/activerecord/test/fixtures/mateys.yml +++ b/activerecord/test/fixtures/mateys.yml @@ -1,4 +1,4 @@ blackbeard_to_redbeard: - pirate_id: <%= Fixtures.identify(:blackbeard) %> - target_id: <%= Fixtures.identify(:redbeard) %> + pirate_id: <%= ActiveRecord::Fixtures.identify(:blackbeard) %> + target_id: <%= ActiveRecord::Fixtures.identify(:redbeard) %> weight: 10 diff --git a/activerecord/test/fixtures/parrots_pirates.yml b/activerecord/test/fixtures/parrots_pirates.yml index 6b17a37d68..66472243c7 100644 --- a/activerecord/test/fixtures/parrots_pirates.yml +++ b/activerecord/test/fixtures/parrots_pirates.yml @@ -1,7 +1,7 @@ george_blackbeard: - parrot_id: <%= Fixtures.identify(:george) %> - pirate_id: <%= Fixtures.identify(:blackbeard) %> + parrot_id: <%= ActiveRecord::Fixtures.identify(:george) %> + pirate_id: <%= ActiveRecord::Fixtures.identify(:blackbeard) %> louis_blackbeard: - parrot_id: <%= Fixtures.identify(:louis) %> - pirate_id: <%= Fixtures.identify(:blackbeard) %> + parrot_id: <%= ActiveRecord::Fixtures.identify(:louis) %> + pirate_id: <%= ActiveRecord::Fixtures.identify(:blackbeard) %> diff --git a/activerecord/test/models/bulb.rb b/activerecord/test/models/bulb.rb index 89ee5416bf..c68d008c26 100644 --- a/activerecord/test/models/bulb.rb +++ b/activerecord/test/models/bulb.rb @@ -1,8 +1,5 @@ class Bulb < ActiveRecord::Base - def self.default_scope - where :name => 'defaulty' - end - + default_scope where(:name => 'defaulty') belongs_to :car attr_reader :scope_after_initialize diff --git a/activerecord/test/models/car.rb b/activerecord/test/models/car.rb index a978debb58..b036f0f5c9 100644 --- a/activerecord/test/models/car.rb +++ b/activerecord/test/models/car.rb @@ -15,13 +15,9 @@ class Car < ActiveRecord::Base end class CoolCar < Car - def self.default_scope - order 'name desc' - end + default_scope :order => 'name desc' end class FastCar < Car - def self.default_scope - order 'name desc' - end + default_scope :order => 'name desc' end diff --git a/activerecord/test/models/categorization.rb b/activerecord/test/models/categorization.rb index 39441e8610..4bd980e606 100644 --- a/activerecord/test/models/categorization.rb +++ b/activerecord/test/models/categorization.rb @@ -12,10 +12,7 @@ end class SpecialCategorization < ActiveRecord::Base self.table_name = 'categorizations' - - def self.default_scope - where(:special => true) - end + default_scope where(:special => true) belongs_to :author belongs_to :category diff --git a/activerecord/test/models/comment.rb b/activerecord/test/models/comment.rb index 3bd7db7834..2a4c37089a 100644 --- a/activerecord/test/models/comment.rb +++ b/activerecord/test/models/comment.rb @@ -1,8 +1,5 @@ class Comment < ActiveRecord::Base - def self.limit_by(l) - limit(l) - end - + scope :limit_by, lambda {|l| limit(l) } scope :containing_the_letter_e, :conditions => "comments.body LIKE '%e%'" scope :not_again, where("comments.body NOT LIKE '%again%'") scope :for_first_post, :conditions => { :post_id => 1 } diff --git a/activerecord/test/models/developer.rb b/activerecord/test/models/developer.rb index 10385ba899..152f804e16 100644 --- a/activerecord/test/models/developer.rb +++ b/activerecord/test/models/developer.rb @@ -1,3 +1,5 @@ +require 'ostruct' + module DeveloperProjectsAssociationExtension def find_most_recent find(:first, :order => "id DESC") @@ -86,10 +88,7 @@ end class DeveloperOrderedBySalary < ActiveRecord::Base self.table_name = 'developers' - - def self.default_scope - order('salary DESC') - end + default_scope :order => 'salary DESC' scope :by_name, order('name DESC') @@ -102,74 +101,68 @@ end class DeveloperCalledDavid < ActiveRecord::Base self.table_name = 'developers' - - def self.default_scope - where "name = 'David'" - end + default_scope where("name = 'David'") end -class DeveloperCalledJamis < ActiveRecord::Base +class LazyLambdaDeveloperCalledDavid < ActiveRecord::Base self.table_name = 'developers' + default_scope lambda { where(:name => 'David') } +end - def self.default_scope - where :name => 'Jamis' - end +class LazyBlockDeveloperCalledDavid < ActiveRecord::Base + self.table_name = 'developers' + default_scope { where(:name => 'David') } +end - scope :poor, where('salary < 150000') +class CallableDeveloperCalledDavid < ActiveRecord::Base + self.table_name = 'developers' + default_scope OpenStruct.new(:call => where(:name => 'David')) end -class AbstractDeveloperCalledJamis < ActiveRecord::Base - self.abstract_class = true +class ClassMethodDeveloperCalledDavid < ActiveRecord::Base + self.table_name = 'developers' def self.default_scope - where :name => 'Jamis' + where(:name => 'David') end end +class DeveloperCalledJamis < ActiveRecord::Base + self.table_name = 'developers' + + default_scope where(:name => 'Jamis') + scope :poor, where('salary < 150000') +end + class PoorDeveloperCalledJamis < ActiveRecord::Base self.table_name = 'developers' - def self.default_scope - where :name => 'Jamis', :salary => 50000 - end + default_scope where(:name => 'Jamis', :salary => 50000) end class InheritedPoorDeveloperCalledJamis < DeveloperCalledJamis self.table_name = 'developers' - def self.default_scope - super.where :salary => 50000 - end + default_scope where(:salary => 50000) end -ActiveSupport::Deprecation.silence do - class DeprecatedDeveloperOrderedBySalary < ActiveRecord::Base - self.table_name = 'developers' - default_scope :order => 'salary DESC' +class MultiplePoorDeveloperCalledJamis < ActiveRecord::Base + self.table_name = 'developers' - def self.by_name - order('name DESC') - end + default_scope where(:name => 'Jamis') + default_scope where(:salary => 50000) +end - def self.all_ordered_by_name - with_scope(:find => { :order => 'name DESC' }) do - find(:all) - end - end - end +module SalaryDefaultScope + extend ActiveSupport::Concern - class DeprecatedDeveloperCalledDavid < ActiveRecord::Base - self.table_name = 'developers' - default_scope :conditions => "name = 'David'" - end + included { default_scope where(:salary => 50000) } +end - class DeprecatedDeveloperCalledJamis < ActiveRecord::Base - self.table_name = 'developers' - default_scope :conditions => { :name => 'Jamis' } - end +class ModuleIncludedPoorDeveloperCalledJamis < DeveloperCalledJamis + self.table_name = 'developers' - class DeprecatedPoorDeveloperCalledJamis < ActiveRecord::Base - self.table_name = 'developers' - default_scope :conditions => { :name => 'Jamis', :salary => 50000 } - end + include SalaryDefaultScope end + + diff --git a/activerecord/test/models/loose_person.rb b/activerecord/test/models/loose_person.rb deleted file mode 100644 index 256c281d0d..0000000000 --- a/activerecord/test/models/loose_person.rb +++ /dev/null @@ -1,24 +0,0 @@ -class LoosePerson < ActiveRecord::Base - self.table_name = 'people' - self.abstract_class = true - - attr_protected :credit_rating, :administrator -end - -class LooseDescendant < LoosePerson - attr_protected :phone_number -end - -class LooseDescendantSecond< LoosePerson - attr_protected :phone_number - attr_protected :name -end - -class TightPerson < ActiveRecord::Base - self.table_name = 'people' - attr_accessible :name, :address -end - -class TightDescendant < TightPerson - attr_accessible :phone_number -end
\ No newline at end of file diff --git a/activerecord/test/models/person.rb b/activerecord/test/models/person.rb index ad59d12672..a58c9bf572 100644 --- a/activerecord/test/models/person.rb +++ b/activerecord/test/models/person.rb @@ -1,6 +1,6 @@ class Person < ActiveRecord::Base has_many :readers - has_one :reader + has_one :reader has_many :posts, :through => :readers has_many :posts_with_no_comments, :through => :readers, :source => :post, :include => :comments, :conditions => 'comments.id is null' @@ -8,23 +8,23 @@ class Person < ActiveRecord::Base has_many :references has_many :bad_references has_many :fixed_bad_references, :conditions => { :favourite => true }, :class_name => 'BadReference' - has_one :favourite_reference, :class_name => 'Reference', :conditions => ['favourite=?', true] + has_one :favourite_reference, :class_name => 'Reference', :conditions => ['favourite=?', true] has_many :posts_with_comments_sorted_by_comment_id, :through => :readers, :source => :post, :include => :comments, :order => 'comments.id' has_many :jobs, :through => :references - has_many :jobs_with_dependent_destroy, :source => :job, :through => :references, :dependent => :destroy + has_many :jobs_with_dependent_destroy, :source => :job, :through => :references, :dependent => :destroy has_many :jobs_with_dependent_delete_all, :source => :job, :through => :references, :dependent => :delete_all - has_many :jobs_with_dependent_nullify, :source => :job, :through => :references, :dependent => :nullify + has_many :jobs_with_dependent_nullify, :source => :job, :through => :references, :dependent => :nullify belongs_to :primary_contact, :class_name => 'Person' has_many :agents, :class_name => 'Person', :foreign_key => 'primary_contact_id' has_many :agents_of_agents, :through => :agents, :source => :agents belongs_to :number1_fan, :class_name => 'Person' - has_many :agents_posts, :through => :agents, :source => :posts + has_many :agents_posts, :through => :agents, :source => :posts has_many :agents_posts_authors, :through => :agents_posts, :source => :author - scope :males, :conditions => { :gender => 'M' } + scope :males, :conditions => { :gender => 'M' } scope :females, :conditions => { :gender => 'F' } end @@ -48,3 +48,33 @@ class PersonWithDependentNullifyJobs < ActiveRecord::Base has_many :references, :foreign_key => :person_id has_many :jobs, :source => :job, :through => :references, :dependent => :nullify end + + +class LoosePerson < ActiveRecord::Base + self.table_name = 'people' + self.abstract_class = true + + attr_protected :comments + attr_protected :as => :admin + + has_one :best_friend, :class_name => 'LoosePerson', :foreign_key => :best_friend_id + belongs_to :best_friend_of, :class_name => 'LoosePerson', :foreign_key => :best_friend_of_id + + has_many :best_friends, :class_name => 'LoosePerson', :foreign_key => :best_friend_id +end + +class LooseDescendant < LoosePerson; end + +class TightPerson < ActiveRecord::Base + self.table_name = 'people' + + attr_accessible :first_name, :gender + attr_accessible :first_name, :gender, :comments, :as => :admin + + has_one :best_friend, :class_name => 'TightPerson', :foreign_key => :best_friend_id + belongs_to :best_friend_of, :class_name => 'TightPerson', :foreign_key => :best_friend_of_id + + has_many :best_friends, :class_name => 'TightPerson', :foreign_key => :best_friend_id +end + +class TightDescendant < TightPerson; end
\ No newline at end of file diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb index a91c10276b..80296032bb 100644 --- a/activerecord/test/models/post.rb +++ b/activerecord/test/models/post.rb @@ -8,13 +8,12 @@ class Post < ActiveRecord::Base scope :containing_the_letter_a, where("body LIKE '%a%'") scope :ranked_by_comments, order("comments_count DESC") - def self.limit_by(l) - limit(l) - end - - def self.with_authors_at_address(address) - where('authors.author_address_id = ?', address.id).joins('JOIN authors ON authors.id = posts.author_id') - end + scope :limit_by, lambda {|l| limit(l) } + scope :with_authors_at_address, lambda { |address| { + :conditions => [ 'authors.author_address_id = ?', address.id ], + :joins => 'JOIN authors ON authors.id = posts.author_id' + } + } belongs_to :author do def greeting @@ -29,10 +28,9 @@ class Post < ActiveRecord::Base scope :with_special_comments, :joins => :comments, :conditions => {:comments => {:type => 'SpecialComment'} } scope :with_very_special_comments, joins(:comments).where(:comments => {:type => 'VerySpecialComment'}) - - def self.with_post(post_id) - joins(:comments).where(:comments => { :post_id => post_id }) - end + scope :with_post, lambda {|post_id| + { :joins => :comments, :conditions => {:comments => {:post_id => post_id} } } + } has_many :comments do def find_most_recent @@ -159,10 +157,7 @@ end class FirstPost < ActiveRecord::Base self.table_name = 'posts' - - def self.default_scope - where(:id => 1) - end + default_scope where(:id => 1) has_many :comments, :foreign_key => :post_id has_one :comment, :foreign_key => :post_id diff --git a/activerecord/test/models/reference.rb b/activerecord/test/models/reference.rb index 76c0a1a32e..c5af0b5d5f 100644 --- a/activerecord/test/models/reference.rb +++ b/activerecord/test/models/reference.rb @@ -19,8 +19,5 @@ end class BadReference < ActiveRecord::Base self.table_name = 'references' - - def self.default_scope - where :favourite => false - end + default_scope where(:favourite => false) end diff --git a/activerecord/test/models/topic.rb b/activerecord/test/models/topic.rb index 60e750e6c4..6440dbe8ab 100644 --- a/activerecord/test/models/topic.rb +++ b/activerecord/test/models/topic.rb @@ -1,20 +1,10 @@ class Topic < ActiveRecord::Base scope :base - - ActiveSupport::Deprecation.silence do - scope :written_before, lambda { |time| - if time - { :conditions => ['written_on < ?', time] } - end - } - - scope :with_object, Class.new(Struct.new(:klass)) { - def call - klass.where(:approved => true) - end - }.new(self) - end - + scope :written_before, lambda { |time| + if time + { :conditions => ['written_on < ?', time] } + end + } scope :approved, :conditions => {:approved => true} scope :rejected, :conditions => {:approved => false} @@ -29,6 +19,12 @@ class Topic < ActiveRecord::Base end end + scope :with_object, Class.new(Struct.new(:klass)) { + def call + klass.where(:approved => true) + end + }.new(self) + module NamedExtension def two 2 diff --git a/activerecord/test/models/without_table.rb b/activerecord/test/models/without_table.rb index 1a63d6ceb6..184ab1649e 100644 --- a/activerecord/test/models/without_table.rb +++ b/activerecord/test/models/without_table.rb @@ -1,5 +1,3 @@ class WithoutTable < ActiveRecord::Base - def self.default_scope - where(:published => true) - end + default_scope where(:published => true) end diff --git a/activerecord/test/schema/postgresql_specific_schema.rb b/activerecord/test/schema/postgresql_specific_schema.rb index f38f4f3b44..5cf9a207f3 100644 --- a/activerecord/test/schema/postgresql_specific_schema.rb +++ b/activerecord/test/schema/postgresql_specific_schema.rb @@ -1,6 +1,6 @@ ActiveRecord::Schema.define do - %w(postgresql_arrays postgresql_moneys postgresql_numbers postgresql_times postgresql_network_addresses postgresql_bit_strings + %w(postgresql_tsvectors postgresql_arrays postgresql_moneys postgresql_numbers postgresql_times postgresql_network_addresses postgresql_bit_strings postgresql_oids postgresql_xml_data_type defaults geometrics postgresql_timestamp_with_zones).each do |table_name| execute "DROP TABLE IF EXISTS #{quote_table_name table_name}" end @@ -55,6 +55,14 @@ _SQL nicknames TEXT[] ); _SQL + + execute <<_SQL + CREATE TABLE postgresql_tsvectors ( + id SERIAL PRIMARY KEY, + text_vector tsvector + ); +_SQL + execute <<_SQL CREATE TABLE postgresql_moneys ( id SERIAL PRIMARY KEY, diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index ceadb05644..9479242e4f 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -438,6 +438,8 @@ ActiveRecord::Schema.define do t.references :number1_fan t.integer :lock_version, :null => false, :default => 0 t.string :comments + t.references :best_friend + t.references :best_friend_of t.timestamps end |