论坛首页 编程语言技术论坛

ActiveRecord中表关联的一个问题,belongs_to和has_many不是一一对应的情况。

浏览 5693 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-07-19  
一个挺有意思的问题,想了半天没有解决办法。

情景是这样的:系统中有两种category,system_category和user_category,所有属性都一样,只是一个是系统分类,一个是用户自己的分类。比如javaeye就是有这样的机制。用户发文时可以同时选择system_category和user_category。假如数据库的设计是system_category和user_category都在一张表categories中。那么Category和Article类的代码大致如下:
# Category.rb
class Category < ActiveRecord::Base
  has_many :articles
end

# Article.rb
class Article < ActiveRecord::Base
  belongs_to  :system_category, :class_name   => "Category", :foreign_key => "system_category_id"
  belongs_to  :user_category,   :class_name   => "Category", :foreign_key => "user_category_id"
end

各位肯定已经注意到了,两边的has_many和belongs_to不是一一对应的。这个时候执行一些语句,结果如下(假设id为1的user cateogry有两个article,id分别为1,2):
Article.find_by_id(1).user_category.id  # => 1
Article.find_by_id(2).user_category.id  # => 1
Category.find_by_id(1).articles            # 出错,说articles没有category_id。

出现以上错误是正常的,但是有什么方法可以解决这个问题吗?当然,我可以在category中声明两个has_many,但是这样显然不符合应用逻辑。我也尝试过使用:finder_sql,但是不知道怎么得到当前category的id,也就没办法手工做查询了。
   发表时间:2007-07-19  
has_many :articles, :finder_sql=>...
0 请登录后投票
   发表时间:2007-07-19  
像这种外键不是缺省的modelname_id的,要用has_many :foreign_key的吧。

但是你的例子就算用has_many :foreign_key也不知道foreign_key是哪个。按照Rails的mapping规则,这应该是以个多对多(实际上是二对多,不管,也是多对多)。

三个表categories、articles、articles_categories,其中categories有一个属性category_type = [USER|SYSTEM];articles没有xxxx_category_id字段;articles_categories包括两个字段article_id和category_id。

然后,model Category:
  has_many :articles, :through => :article_categories
model Article:
  has_one :system_category, :through => :article_categories, :condition => "category_type = 'SYSTEM'"
  has_one :user_category, :through => :article_categories, :condition => "category_type = 'USER'"

以上伪代码,没有调试过。
0 请登录后投票
   发表时间:2007-07-19  
感觉数据库这样设计很别扭,给category加一个flag用来区分system_cate和user_cate会清晰很多
0 请登录后投票
   发表时间:2007-07-20  
yehs220 写道
has_many :articles, :finder_sql=>...

麻烦你来告诉我finder_sql里面怎么写?
0 请登录后投票
   发表时间:2007-07-20  
cvu 写道
像这种外键不是缺省的modelname_id的,要用has_many :foreign_key的吧。

但是你的例子就算用has_many :foreign_key也不知道foreign_key是哪个。按照Rails的mapping规则,这应该是以个多对多(实际上是二对多,不管,也是多对多)。

三个表categories、articles、articles_categories,其中categories有一个属性category_type = [USER|SYSTEM];articles没有xxxx_category_id字段;articles_categories包括两个字段article_id和category_id。

然后,model Category:
  has_many :articles, :through => :article_categories
model Article:
  has_one :system_category, :through => :article_categories, :condition => "category_type = 'SYSTEM'"
  has_one :user_category, :through => :article_categories, :condition => "category_type = 'USER'"

以上伪代码,没有调试过。

这个好像挺有意思,我去试试看。
0 请登录后投票
   发表时间:2007-07-20  
hideto 写道
感觉数据库这样设计很别扭,给category加一个flag用来区分system_cate和user_cate会清晰很多

这样需要一个多对多的关系,我不想用,因为代码里面比较麻烦。
0 请登录后投票
   发表时间:2007-07-20  
给categories加一个type的column,就可以使用rails提供的polymorphic功能。
详见belong_to中对:polymorphic的解释。
也可以参考acts_as_taggable的实现。
0 请登录后投票
   发表时间:2007-07-20  
AllenYoung 写道
yehs220 写道
has_many :articles, :finder_sql=>...

麻烦你来告诉我finder_sql里面怎么写?

...articles.system_category_id=... OR articles.user_category_id=...
0 请登录后投票
论坛首页 编程语言技术版

跳转论坛:
Global site tag (gtag.js) - Google Analytics