Rails has_many / has_one相同的模型

时间:2011-03-03 22:56:59

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

所以,我有两个模型,Collection和Folder。

在每个Collection中都有一个根文件夹。文件夹都属于Collection,但也可以互相嵌套。

关注this question,我编写了如下所示的模型。我还添加了一个回调,因为我总是希望Collection以一个根文件夹开始。

class Folder < ActiveRecord::Base
  has_one :master_collection, :class_name => 'Collection', :foreign_key => :root_folder_id
  belongs_to :collection
  belongs_to :parent, :class_name => 'Folder'
  has_many :subfolders, :class_name => 'Folder', :foreign_key => :parent_id
  ...
end

class Collection < ActiveRecord::Base
  belongs_to :root_folder, :class_name => 'Folder'
  has_many :folders

  after_create :setup_root_folder

  private
  def setup_root_folder
    self.root_folder = Folder.create(:name => 'Collection Root', :collection => self )
  end
end

在文件夹中我有列:parent_id,folder_id 在集合中,我有列:root_folder_id

这似乎应该可行,但我在控制台中得到了这种奇怪的行为:

ruby-1.9.2-p0 :001 > c = Collection.create(:name=>"Example")
 => #<Collection id: 6, name: "Example", ...timestamps..., root_folder_id: 8> 
ruby-1.9.2-p0 :003 > f = c.root_folder
 => #<Folder id: 8, parent_id: nil, name: "Collection Root", ...timestamps..., collection_id: 6> 
ruby-1.9.2-p0 :004 > f.master_collection
 => nil 

所以,显然关联在收集端工作,但是根文件夹无法找到它是根的集合,即使外键可用且ActiveRecord在使用关联时没有引发任何错误...

有什么想法吗?

1 个答案:

答案 0 :(得分:2)

我怀疑这就是发生的事情:

  1. 您创建了Collection C
  2. C保存到数据库
  3. Rails调用C.after_create
  4. 您创建文件夹F
  5. F保存到数据库
  6. C root_folder_id设置为F id
  7. 此更改未保存到数据库
  8. 您致电F.master_collection
  9. F查询数据库,查找具有coleections.root_folder_id = folders.id
  10. 的集合
  11. 由于C的新root_folder_id尚未保存,因此F找不到任何内容
  12. 如果您要对此进行测试,请在调用c.save之前调用示例代码中的f.master_collection - 您应该像预期的那样获得该集合(您可能还需要f.reload )。

    那就是说,我从来没有喜欢过双belongs_to s(Folder belongs_to Collection + Collection belongs_to root_folder)。相反,我建议:

    class Collection < ActiveRecord::Base
        has_one :root_folder, :class_name => 'Folder', :conditions => {:parent_id => nil}
    
        # ...other stuff...
    end
    

    希望有所帮助!

    PS:如果您从根文件夹中调用它,您对Folder.master_collection的定义只会返回一个集合 - 所有其他文件夹只返回nil,因为没有集合root_folder_id 1}}指向他们的。那是你的意图吗?