Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge [5660] from trunk.

git-svn-id: http://svn-commit.rubyonrails.org/rails/branches/1-2-pre-release@5661 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
commit 2890b9648e43793ba3f8bb8124701f33f3381127 1 parent 98a0440
@jeremy jeremy authored
View
2  activerecord/CHANGELOG
@@ -1,5 +1,7 @@
*1.15.0 RC2*
+* Subclasses of an abstract class work with single-table inheritance. #5704 [nick+rails@ag.arizona.edu, Ryan Davis, Jeremy Kemper]
+
* Support nil and Array in :conditions => { attr => value } hashes. #6548 [Assaf, Jeremy Kemper]
find(:all, :conditions => { :topic_id => [1, 2, 3], :last_read => nil }
View
9 activerecord/lib/active_record/base.rb
@@ -816,7 +816,7 @@ def human_attribute_name(attribute_key_name) #:nodoc:
end
def descends_from_active_record? # :nodoc:
- superclass == Base || !columns_hash.include?(inheritance_column)
+ superclass.abstract_class? || !columns_hash.include?(inheritance_column)
end
@@ -1161,7 +1161,7 @@ def add_conditions!(sql, conditions, scope = :auto)
segments = []
segments << sanitize_sql(scope[:conditions]) if scope && scope[:conditions]
segments << sanitize_sql(conditions) unless conditions.nil?
- segments << type_condition unless descends_from_active_record?
+ segments << type_condition unless descends_from_active_record?
segments.compact!
sql << "WHERE (#{segments.join(") AND (")}) " unless segments.empty?
end
@@ -1362,7 +1362,7 @@ def compute_type(type_name)
# Returns the class descending directly from ActiveRecord in the inheritance hierarchy.
def class_of_active_record_descendant(klass)
- if klass.superclass == Base || klass.superclass.abstract_class?
+ if klass.superclass.abstract_class?
klass
elsif klass.superclass.nil?
raise ActiveRecordError, "#{name} doesn't belong in a hierarchy descending from ActiveRecord"
@@ -1483,6 +1483,9 @@ def encode_quoted_value(value) #:nodoc:
end
end
+ # ActiveRecord::Base is abstract.
+ self.abstract_class = true
+
public
# New objects can be instantiated as either empty (pass no construction parameter) or pre-set with
# attributes but not yet saved (pass a hash with key names matching the associated table column names).
View
57 activerecord/test/base_test.rb
@@ -10,6 +10,7 @@
require 'fixtures/column_name'
require 'fixtures/subscriber'
require 'fixtures/keyboard'
+require 'fixtures/post'
class Category < ActiveRecord::Base; end
class Smarts < ActiveRecord::Base; end
@@ -28,8 +29,9 @@ class NonExistentTable < ActiveRecord::Base; end
class TestOracleDefault < ActiveRecord::Base; end
class LoosePerson < ActiveRecord::Base
- attr_protected :credit_rating, :administrator
+ self.table_name = 'people'
self.abstract_class = true
+ attr_protected :credit_rating, :administrator
end
class LooseDescendant < LoosePerson
@@ -37,6 +39,7 @@ class LooseDescendant < LoosePerson
end
class TightPerson < ActiveRecord::Base
+ self.table_name = 'people'
attr_accessible :name, :address
end
@@ -1332,13 +1335,63 @@ def test_scoped_find_order_including_has_many_association
end
end
- def test_base_class
+ def test_abstract_class
+ assert ActiveRecord::Base.abstract_class?
assert LoosePerson.abstract_class?
assert !LooseDescendant.abstract_class?
+ end
+
+ def test_base_class
assert_equal LoosePerson, LoosePerson.base_class
assert_equal LooseDescendant, LooseDescendant.base_class
assert_equal TightPerson, TightPerson.base_class
assert_equal TightPerson, TightDescendant.base_class
+
+ assert_equal Post, Post.base_class
+ assert_equal Post, SpecialPost.base_class
+ assert_equal Post, StiPost.base_class
+ assert_equal SubStiPost, SubStiPost.base_class
+ end
+
+ def test_descends_from_active_record
+ # Tries to call Object.abstract_class?
+ assert_raise(NoMethodError) do
+ ActiveRecord::Base.descends_from_active_record?
+ end
+
+ # Abstract subclass of AR::Base.
+ assert LoosePerson.descends_from_active_record?
+
+ # Concrete subclass of an abstract class.
+ assert LooseDescendant.descends_from_active_record?
+
+ # Concrete subclass of AR::Base.
+ assert TightPerson.descends_from_active_record?
+
+ # Concrete subclass of a concrete class but has no type column.
+ assert TightDescendant.descends_from_active_record?
+
+ # Concrete subclass of AR::Base.
+ assert Post.descends_from_active_record?
+
+ # Abstract subclass of a concrete class which has a type column.
+ # This is pathological, as you'll never have Sub < Abstract < Concrete.
+ assert !StiPost.descends_from_active_record?
+
+ # Concrete subclasses an abstract class which has a type column.
+ assert SubStiPost.descends_from_active_record?
+ end
+
+ def test_find_on_abstract_base_class_doesnt_use_type_condition
+ old_class = LooseDescendant
+ Object.send :remove_const, :LooseDescendant
+
+ descendant = old_class.create!
+ assert_not_nil LoosePerson.find(descendant.id), "Should have found instance of LooseDescendant when finding abstract LoosePerson: #{descendant.inspect}"
+ ensure
+ unless Object.const_defined?(:LooseDescendant)
+ Object.const_set :LooseDescendant, old_class
+ end
end
def test_assert_queries
View
6 activerecord/test/fixtures/db_definitions/mysql.sql
@@ -159,14 +159,14 @@ CREATE TABLE `posts` (
`author_id` INTEGER,
`title` VARCHAR(255) NOT NULL,
`body` TEXT NOT NULL,
- `type` VARCHAR(255) NOT NULL
+ `type` VARCHAR(255) default NULL
) TYPE=InnoDB;
CREATE TABLE `comments` (
`id` INTEGER NOT NULL auto_increment PRIMARY KEY,
`post_id` INTEGER NOT NULL,
`body` TEXT NOT NULL,
- `type` VARCHAR(255) NOT NULL
+ `type` VARCHAR(255) default NULL
) TYPE=InnoDB;
CREATE TABLE `authors` (
@@ -184,7 +184,7 @@ CREATE TABLE `tasks` (
CREATE TABLE `categories` (
`id` int(11) NOT NULL auto_increment,
`name` VARCHAR(255) NOT NULL,
- `type` VARCHAR(255) NOT NULL,
+ `type` VARCHAR(255) default NULL,
PRIMARY KEY (`id`)
) TYPE=InnoDB;
View
4 activerecord/test/fixtures/db_definitions/sqlite.sql
@@ -144,14 +144,14 @@ CREATE TABLE 'posts' (
'id' INTEGER NOT NULL PRIMARY KEY,
'author_id' INTEGER,
'title' VARCHAR(255) NOT NULL,
- 'type' VARCHAR(255) NOT NULL,
+ 'type' VARCHAR(255) DEFAULT NULL,
'body' TEXT NOT NULL
);
CREATE TABLE 'comments' (
'id' INTEGER NOT NULL PRIMARY KEY,
'post_id' INTEGER NOT NULL,
- 'type' VARCHAR(255) NOT NULL,
+ 'type' VARCHAR(255) DEFAULT NULL,
'body' TEXT NOT NULL
);
View
3  activerecord/test/fixtures/post.rb
@@ -46,7 +46,7 @@ def self.what_are_you
end
end
-class SpecialPost < Post; end;
+class SpecialPost < Post; end
class StiPost < Post
self.abstract_class = true
@@ -54,4 +54,5 @@ class StiPost < Post
end
class SubStiPost < StiPost
+ self.table_name = Post.table_name
end

0 comments on commit 2890b96

Please sign in to comment.
Something went wrong with that request. Please try again.