2

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

class human < ActiveRecord::Base
   has_one :Animal
end

Animal 是一个抽象类 -

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

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

class dog < Animal

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

4

3 回答 3

2

按照 Ruby 中的约定,Animal 将引用一个类(实际上,它涉及更多一些 - 这个链接有更多详细信息)。在你原来的帖子中,“class dog”应该是“class Dog”b/c,类名是一个常量,如果你在人和动物之间有一个has_one关联,你可以说human.animal =(一些动物实例) ,但是 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
于 2013-11-03T07:34:45.587 回答
1

ActiveRecord 具有对多态关联的内置支持,因此您可以这样做:

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

于 2012-08-21T15:51:36.107 回答
0

ActiveRecord 默认从模型名称中获取表名。但是,您可以覆盖它。如果你想在一张桌子上放狗,在另一张桌子上放猫,等等,那么你可以这样做(在 Rails 3.2 中):

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

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

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

但是,如果您希望所有动物都存在于一张表中,则应查看 Single-Table-Inheritance。有关更多信息,请参阅ActiveRecord 文档

于 2012-08-21T16:32:51.627 回答