ActiveRecord Subclassing困境

时间:2012-08-21 15:44:07

标签: ruby-on-rails ruby ruby-on-rails-3 activerecord subclassing

所以我们走了。我有一个Activerecord :: Base模型,让它被称为人类。

class human < ActiveRecord::Base
   has_one :Animal
end

Animal是一个抽象类 -

class animal < ActiveRecord::Base
   self.abstract_class = true;
 end

我有一个动物的子类,让它成为狗

class dog < Animal

如果我不使用抽象类,我不能将实例变量添加到'Dog'(因为它存储在'Animal'表中)。如果我使用抽象类,我不能将'Animal'添加到'Human' - 因为rails不知道,如何存储,例如'Dog'(ActiveRecord错误:找不到表'') 。这种情况让我发疯,我无法克服它。 我错过了什么或只是做错了吗?

3 个答案:

答案 0 :(得分:2)

按照Ruby中的惯例,Animal会引用一个类(实际上,它涉及的更多 - 这个链接还有一些detail)。在你原来的帖子中,“班级狗”应该是“班级狗”b / c班级名称是一个常数,如果你在人类和动物之间有一个has_one关联,你可以说是human.animal =(某些动物实例)但是人类。动物很可能会产生奇怪的效果,如果它不会立即崩溃。其他人推荐的STI方法将完全符合您的要求,但您可以设置“类型”值,而不是“动物”(请不要直接执行此操作)。

您应该阅读Ruby和RoR,STI,活动记录关联和多态关联中大写的含义。这样的事情应该有效(没有经过测试,这是不正常的规范化 - 你可以使用has_one关联和一个称为委托的模式来设置一般情况下一般动物特征在一个表中的情况,并且'人类特定'特征在另一个表中以避免数据库中的一堆NULL列:

# remember to set up your migrations to add a 'type' column to your Animal table
# if animals can own other animals who own other animals, you may want to look at
# acts_as_tree, which does trees in relational databases efficiently 

class Animal < ActiveRecord::Base 
  self.abstract_class = true
end

class Dog < Animal
  # this is bad normalization - but you can keep this simple by adding 
  # a human_id field in your animal table (don't forget to index)
  # look into the 'belongs_to' / 'references' type available for DB migrations   
  belongs_to :human
end

class Human < Animal
  has_one :dog, :autosave => true # or you could use 'has_many :dogs' 
end

human = Human.new # => adds record to Animal table, with type = 'human'
dog = Dog.new
human.dog = dog
human.save

答案 1 :(得分:1)

ActiveRecord内置了对多态关联的支持,所以你可以这样做:

http://guides.rubyonrails.org/association_basics.html#polymorphic-associations

答案 2 :(得分:0)

默认情况下,ActiveRecord从模型名称中获取表名。但是,您可以覆盖它。如果你想在一个表中使用Dogs,在其他表中使用Cats等,那么你可以(在Rails 3.2中):

class Dog < Animal
  self.table_name = 'dogs'
end

class Cat < Animal
  self.table_name = 'cats'
end

(您必须添加迁移才能创建这些表。)

但是,如果您希望所有动物都存在于一个表中,则应该查看单表继承。有关详情,请参阅ActiveRecord docs