Rails:对复杂的关联进行建模以适应现实世界中各代动物之间的关系

发布于 2024-12-10 10:02:20 字数 1369 浏览 0 评论 0原文

使用 Rails 3.1.1

我正在对动物(个体狗)和幼仔(后代群体)之间的关联进行建模。它变得很复杂,因为动物既出生一窝并且可以养育许多窝(作为母亲 > 父亲)。

以下是我的架构的相关部分:

ActiveRecord::Schema.define do

  create_table "animals", :force => true do |t|
    ...
    t.integer  "litter_id"
    t.string   "sex"
    ...
  end

  create_table "litters", :force => true do |t|
    ...
    t.integer  "father_id"
    t.integer  "mother_id"
    ...
  end
end

以下是适当的模型,以及我认为可以作为关联的模型:

class Animal < ActiveRecord::Base
  ...
  belongs_to :litter
  has_many   :litters, :foreign_key => :father_id
  has_many   :litters, :foreign_key => :mother_id
  has_one    :father,  :through => :litter, :foreign_key => :father_id
  has_one    :mother,  :through => :litter, :foreign_key => :mother_id
  ...
end

class Litter < ActiveRecord::Base
  ...
  has_many   :animals
  belongs_to :father, :class_name => 'Animal'
  belongs_to :mother, :class_name => 'Animal'    
  ...
end

如果我在 belongs_to上加倍,我会遇到问题吗?在各自的模型中有_many关联?如果是这样,我如何正确地对这些关联进行建模?


更新: 正如下面的评论中提到的,我使用 Litter 模型来跟踪大约 10 个常见的属性那窝里的每只动物。该软件将由狗饲养员运行,因此从多个角度来看,Litter 本身就是一个相关单元,并且在视图中显示数据时将承担很大的责任(超出父母/孩子的关系)。

Using Rails 3.1.1

I'm modeling associations between Animals (individual dogs) and Litters (groups of offspring). It gets complicated because an animal is both born into a litter and can parent many litters (as either a mother or a father).

Here are the relevant parts of my schema:

ActiveRecord::Schema.define do

  create_table "animals", :force => true do |t|
    ...
    t.integer  "litter_id"
    t.string   "sex"
    ...
  end

  create_table "litters", :force => true do |t|
    ...
    t.integer  "father_id"
    t.integer  "mother_id"
    ...
  end
end

And here are the appropriate models, with what I think could work as associations:

class Animal < ActiveRecord::Base
  ...
  belongs_to :litter
  has_many   :litters, :foreign_key => :father_id
  has_many   :litters, :foreign_key => :mother_id
  has_one    :father,  :through => :litter, :foreign_key => :father_id
  has_one    :mother,  :through => :litter, :foreign_key => :mother_id
  ...
end

class Litter < ActiveRecord::Base
  ...
  has_many   :animals
  belongs_to :father, :class_name => 'Animal'
  belongs_to :mother, :class_name => 'Animal'    
  ...
end

Will I run into problems if I double up on belongs_to and has_many associations in their respective models? If so, how can I properly model those associations?


UPDATE: As mentioned in a comment below, I'm using the Litter model to track about 10 attributes that are common to every Animal in that Litter. This software will be run by dog breeders, so the Litter is itself a relevant unit from several standpoints, and will carry a lot of weight (beyond parent/child relationships) when it comes to surfacing data in views.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

蓝咒 2024-12-17 10:02:20

虽然不了解 Ruby、Rails 或 ActiveRecord,但我仍然认为您需要一个图形库(数据结构而不是图片)和一个为您存储它的持久层。 这里是一个 Ruby Graph 库,持久性就在你身上。

Not knowing any of Ruby, Rails or ActiveRecord, still I think what you need a Graph library (the data-structure not the picture) and a persistence layer which stores it for you. Here is a Ruby Graph library, persistence is on you.

最丧也最甜 2024-12-17 10:02:20

您应该能够将所有狗视为动物。

每只动物都会像这样(未经测试):

belongs_to :mother, :class_name => "Animal", :foreign_key => "mother_id"
belongs_to :father, :class_name => "Animal", :foreign_key => "father_id"
has_many :children, :through => :animals # not sure if you need a foreign key specification here

Animals 表:

id | mother_id | father_id 

您跟踪的最古老的祖先不会有父母,因此他们的 mother_idfather_id 将为零。

我认为跟踪 litter_id 的唯一原因是跟踪兄弟姐妹,这可能是您需要的。在这种情况下,您可以让垃圾成为它自己的对象,如您的示例所示,或者您可以进行简单的检查,例如:

class Animal < ActiveRecord::Base
  ...

  def is_sibling_of(animal)
     self.mother == animal.mother
  end

  ...    
end

...或对象 scope (称为 named_scope 之前的 Rails3):

class Animal < ActiveRecord::Base
  ...

  scope :siblings, lambda {|animal| {:conditions => ["id not in (?) AND mother_id = ?", animal.id, animal.mother.id} }

  ...
end

这将为您提供指定动物的所有兄弟姐妹的列表,不包括动物本身。

You should be able to just treat all dogs as animals.

Each animal will go something like this (untested):

belongs_to :mother, :class_name => "Animal", :foreign_key => "mother_id"
belongs_to :father, :class_name => "Animal", :foreign_key => "father_id"
has_many :children, :through => :animals # not sure if you need a foreign key specification here

animals table:

id | mother_id | father_id 

The oldest ancestor that you keep track of won't have parents, so their mother_id and father_id will be nil.

The only reason I can see for keeping track of the litter_id is to keep track of siblings, which might be something you need. In that case you can have the litter be its own object, as in your example, or you can do a simple check like:

class Animal < ActiveRecord::Base
  ...

  def is_sibling_of(animal)
     self.mother == animal.mother
  end

  ...    
end

...or an object scope (was called named_scope previous to Rails3):

class Animal < ActiveRecord::Base
  ...

  scope :siblings, lambda {|animal| {:conditions => ["id not in (?) AND mother_id = ?", animal.id, animal.mother.id} }

  ...
end

Which would give you a list of all siblings of the specified animal, not including the animal itself.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文