Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Changeset 5660

Show
Ignore:
Timestamp:
12/01/06 21:24:47 (2 years ago)
Author:
bitsweat
Message:

Subclasses of an abstract class work with single-table inheritance. Closes #5704.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/activerecord/CHANGELOG

    r5604 r5660  
    11*SVN* 
     2 
     3* Subclasses of an abstract class work with single-table inheritance.  #5704 [nick+rails@ag.arizona.edu, Ryan Davis, Jeremy Kemper] 
    24 
    35* Change fixture_path to a class inheritable accessor allowing test cases to have their own custom set of fixtures. #6672 [zdennis] 
  • trunk/activerecord/lib/active_record/base.rb

    r5593 r5660  
    817817 
    818818      def descends_from_active_record? # :nodoc: 
    819         superclass == Base || !columns_hash.include?(inheritance_column) 
     819        superclass.abstract_class? || !columns_hash.include?(inheritance_column) 
    820820      end 
    821821 
     
    11621162          segments << sanitize_sql(scope[:conditions]) if scope && scope[:conditions] 
    11631163          segments << sanitize_sql(conditions) unless conditions.nil? 
    1164           segments << type_condition unless descends_from_active_record?         
     1164          segments << type_condition unless descends_from_active_record? 
    11651165          segments.compact! 
    11661166          sql << "WHERE (#{segments.join(") AND (")}) " unless segments.empty? 
     
    13631363        # Returns the class descending directly from ActiveRecord in the inheritance hierarchy. 
    13641364        def class_of_active_record_descendant(klass) 
    1365           if klass.superclass == Base || klass.superclass.abstract_class? 
     1365          if klass.superclass.abstract_class? 
    13661366            klass 
    13671367          elsif klass.superclass.nil? 
     
    14831483        end 
    14841484    end 
     1485 
     1486    # ActiveRecord::Base is abstract. 
     1487    self.abstract_class = true 
    14851488 
    14861489    public 
  • trunk/activerecord/test/base_test.rb

    r5597 r5660  
    1111require 'fixtures/subscriber' 
    1212require 'fixtures/keyboard' 
     13require 'fixtures/post' 
    1314 
    1415class Category < ActiveRecord::Base; end 
     
    2930 
    3031class LoosePerson < ActiveRecord::Base 
     32  self.table_name = 'people' 
     33  self.abstract_class = true 
    3134  attr_protected :credit_rating, :administrator 
    32   self.abstract_class = true 
    3335end 
    3436 
     
    3840 
    3941class TightPerson < ActiveRecord::Base 
     42  self.table_name = 'people' 
    4043  attr_accessible :name, :address 
    4144end 
     
    13621365  end 
    13631366 
    1364   def test_base_class 
     1367  def test_abstract_class 
     1368    assert ActiveRecord::Base.abstract_class? 
    13651369    assert LoosePerson.abstract_class? 
    13661370    assert !LooseDescendant.abstract_class? 
     1371  end 
     1372 
     1373  def test_base_class 
    13671374    assert_equal LoosePerson,     LoosePerson.base_class 
    13681375    assert_equal LooseDescendant, LooseDescendant.base_class 
    13691376    assert_equal TightPerson,     TightPerson.base_class 
    13701377    assert_equal TightPerson,     TightDescendant.base_class 
     1378 
     1379    assert_equal Post, Post.base_class 
     1380    assert_equal Post, SpecialPost.base_class 
     1381    assert_equal Post, StiPost.base_class 
     1382    assert_equal SubStiPost, SubStiPost.base_class 
     1383  end 
     1384 
     1385  def test_descends_from_active_record 
     1386    # Tries to call Object.abstract_class? 
     1387    assert_raise(NoMethodError) do 
     1388      ActiveRecord::Base.descends_from_active_record? 
     1389    end 
     1390 
     1391    # Abstract subclass of AR::Base. 
     1392    assert LoosePerson.descends_from_active_record? 
     1393 
     1394    # Concrete subclass of an abstract class. 
     1395    assert LooseDescendant.descends_from_active_record? 
     1396 
     1397    # Concrete subclass of AR::Base. 
     1398    assert TightPerson.descends_from_active_record? 
     1399 
     1400    # Concrete subclass of a concrete class but has no type column. 
     1401    assert TightDescendant.descends_from_active_record? 
     1402 
     1403    # Concrete subclass of AR::Base. 
     1404    assert Post.descends_from_active_record? 
     1405 
     1406    # Abstract subclass of a concrete class which has a type column. 
     1407    # This is pathological, as you'll never have Sub < Abstract < Concrete. 
     1408    assert !StiPost.descends_from_active_record? 
     1409 
     1410    # Concrete subclasses an abstract class which has a type column. 
     1411    assert SubStiPost.descends_from_active_record? 
     1412  end 
     1413 
     1414  def test_find_on_abstract_base_class_doesnt_use_type_condition 
     1415    old_class = LooseDescendant 
     1416    Object.send :remove_const, :LooseDescendant 
     1417 
     1418    descendant = old_class.create! 
     1419    assert_not_nil LoosePerson.find(descendant.id), "Should have found instance of LooseDescendant when finding abstract LoosePerson: #{descendant.inspect}" 
     1420  ensure 
     1421    unless Object.const_defined?(:LooseDescendant) 
     1422      Object.const_set :LooseDescendant, old_class 
     1423    end 
    13711424  end 
    13721425 
  • trunk/activerecord/test/fixtures/db_definitions/mysql.sql

    r4808 r5660  
    160160  `title` VARCHAR(255) NOT NULL, 
    161161  `body` TEXT NOT NULL, 
    162   `type` VARCHAR(255) NOT NULL 
     162  `type` VARCHAR(255) default NULL 
    163163) TYPE=InnoDB; 
    164164 
     
    167167  `post_id` INTEGER NOT NULL, 
    168168  `body` TEXT NOT NULL, 
    169   `type` VARCHAR(255) NOT NULL 
     169  `type` VARCHAR(255) default NULL 
    170170) TYPE=InnoDB; 
    171171 
     
    185185  `id` int(11) NOT NULL auto_increment, 
    186186  `name` VARCHAR(255) NOT NULL, 
    187   `type` VARCHAR(255) NOT NULL, 
     187  `type` VARCHAR(255) default NULL, 
    188188  PRIMARY KEY  (`id`) 
    189189) TYPE=InnoDB; 
  • trunk/activerecord/test/fixtures/db_definitions/sqlite.sql

    r4596 r5660  
    145145  'author_id' INTEGER, 
    146146  'title' VARCHAR(255) NOT NULL, 
    147   'type' VARCHAR(255) NOT NULL, 
     147  'type' VARCHAR(255) DEFAULT NULL, 
    148148  'body' TEXT NOT NULL 
    149149); 
     
    152152  'id' INTEGER NOT NULL PRIMARY KEY, 
    153153  'post_id' INTEGER NOT NULL, 
    154   'type' VARCHAR(255) NOT NULL, 
     154  'type' VARCHAR(255) DEFAULT NULL, 
    155155  'body' TEXT NOT NULL 
    156156); 
  • trunk/activerecord/test/fixtures/post.rb

    r5116 r5660  
    4747end 
    4848 
    49 class SpecialPost < Post; end; 
     49class SpecialPost < Post; end 
    5050 
    5151class StiPost < Post 
     
    5555 
    5656class SubStiPost < StiPost 
     57  self.table_name = Post.table_name 
    5758end