子类继承的父类中的STI has_many关系

时间:2015-10-07 20:45:11

标签: ruby-on-rails activerecord

说我有以下STI模型

class Parent < ActiveRecord::Base
  has_many :childs, foreign_key: 'parent_id' # forgive the english for sake of simplicity

  #def childs
  #  Child.where(parent_id: id) # this works just fine BTW
  #end
end

class BadParent < Parent
end

class GoodParent < Parent
end

以及以下Child类

class Child
  belongs_to :parent # parent_id lives on this
end

我不关心在Child上设置类型,所以我不关心创建多态关联。

bad_parent = BadParent.create(name: 'Michael Jackson')
child = Child.create(name: 'Bobby', parent: bad_parent)

如果我跑

child.parent #=> <# BadParent > # AWESOME

bad_parent.childs #=> [] NO BUENO!!!

sql_statement = bad_parent.childs.to_sql #=> "SELECT `childs`.* FROM `childs` WHERE `childs`.`parent_id` = 1"

Child.find_by_sql(sql_statement) #=> [<# Child Object #>] BUENO!!!

我是否有必要添加到关联中以使其像find_by_sql一样工作?

2 个答案:

答案 0 :(得分:3)

根据其他评论,你不应该同时拥有一个名称相同的方法和关联,因为它不清楚会被执行的内容 - 我会假设在这里你将摆脱<div class="like-buttons"> <img src="up.png" onclick="onClick(this)" /> <span id="clicks">0</span> <img src="down.png" onclick="onClick(this)" /> </div>除了我认为你的问题与缓存有关,即如果知道某些内容已发生变化,则只会触及数据库。在您的示例中,bad_parent不知道已添加新子项。您可以重新加载,如:

def childs ...

或强制调用数据库,如:

bad_parent.reload
bad_parent.childs #> should show child object now

请查看rials指南的3.1控制缓存部分以获取更多信息:http://guides.rubyonrails.org/association_basics.html

答案 1 :(得分:1)

这就是我要做的......

#app/models/person.rb
class Person < ActiveRecord::Base
  #columns id | type | parent_id | type_id | name | created_at | updated_at
end

#app/models/parent.rb
class Parent < Person
   belongs_to :type
   has_many :children, foreign_key: 'parent_id'
end

#app/models/child.rb
class Child < Parent
    belongs_to :parent
end

#app/models/type.rb
class Type < ActiveRecord::Base
   #columns id | type
   #values good/bad (probably overkill to have DB for this)
   has_many :parents
end

这应该允许您调用以下内容:

@parent = Parent.find params[:id]
@parent.children #-> collection of Person model with parent_id attribute for parent

关于你的具体问题 - 关于eager loading等 - 我没有大量的经验。

hierarchy gems可以帮助解决这个问题。

我们之前使用过ClosureTree - 它创建了一个单独的表,使您可以更轻松地遍历层次结构。另一个名为ancestry,非常受欢迎(更容易实现)。

我建议您在“父”模型中使用ancestry之类的内容。我调用了父模型Parent,因为我认为它将为您提供更深入的范围来处理不同类型的数据。

例如,您的Child模型完全属于它,应该由与Parent相同的数据组成。