聚合has_many与另一个has_many Rails

时间:2012-10-25 00:46:57

标签: ruby-on-rails relationship has-many

我有以下型号:

class User < ActiveRecord::Base
  has_many :subscriptions, as: :subscribable
  has_many :user_to_high_school_subscriptions
  has_many :high_school_subscriptions, through: :user_to_high_school_subscriptions

  def all_subscriptions
    self.subscriptions + self.high_school_subscriptions.subscriptions
  end
end

class UserToHighSchoolSubscription < ActiveRecord::Base
  belongs_to :user
  belongs_to :high_school_subscription
end

class HighSchoolSubscription < ActiveRecord::Base
  has_many :user_to_high_school_subscriptions
  has_many :users, through: :user_to_high_school_subscriptions
  has_many :subscriptions, as: :subscribable
end

class Subscription < ActiveRecord::Base
  belongs_to :subscribable, polymorphic: true
end

我是否有一种聪明的方式来获得Subscription所有的User

我试过

u = User.first
subs = u.all_subscriptions

但这是错误的(undefined method subscriptions' for #<ActiveRecord::Relation:)。当我尝试使用has_many :subscriptions HighSchoolSubscription因为user has_many :high_school_subscriptions时,我认为这很令人窒息。 (这一行:self.high_school_subscriptions.subscriptions)。

有没有办法在Rails中的has_many上聚合has_many?

运行rails 3.2.1

1 个答案:

答案 0 :(得分:1)

self.subscriptions不会返回Array,而是ActiveRecord::Relation。这就是为什么+方法不起作用并且你得到上述错误的原因。最简单的解决方法是这样做:

def all_subscriptions
  self.subscriptions.all + self.high_school_subscriptions.all.collect { |hss| hss.subscriptions.all }.flatten
end

all方法将触发数据库查询并返回一个数组。因为用户可能有许多高中订阅,并且这些订阅也可能有许多订阅,所以您必须遍历所有高中订阅并收集他们的订阅。如你所见,这是一个彻头彻尾的过度杀伤。

重新设计您的数据模型,或者只是采用不同的方式。

或许,确定Subscription模型的范围可能就是这样。添加一个属性,指定它的订阅类型,然后您可以完全删除HighSchoolSubscription模型。