如何连接两个活动记录结果以返回可以进一步过滤的新结果?

想象一下场景……

#models/user.rb class User  { :active => 1 } end #models/account.rb class Account  { public => true } end end 

现在想象一下,我想将User(.id).accounts与Account.public_accounts连接起来,以显示用户可用的所有帐户的列表。

所以你认为我能够将User模型更新为这样。

 #models/user.rb class User  { :active => 1 } def all_accounts self.accounts + Account.public end end 

但是,现在我将无法使用all()方法,因为它不再是那种类型的对象。

在控制器中我想这样做……

 #controllers/accounts_controller.rb def search_all User.find(params[:user_id]).all_accounts.all( :offset => params[:offset], :limit => params[:limit] ) end 

思考?

更新#1:范围不适用于我的方案。 我简化了我的方案,尝试着解决我的观点。 如上所述,我需要一种方法来组合两个活动记录结果,并保留在我的控制器中进一步过滤它们的能力。

所以问题是,“为什么?” 原因是,我试图将两组记录组合成一个完整的集合,其中一个集合根本不与用户相关联。

我已经重构了上面的场景,试图展示一个更精确的例子而不会过于复杂。

jklina的答案是正确的,在这种情况下最好使用范围。 范围提供了含糖的语法,并且更具可读性。 我将详细说明设置:

 class User < AR::Base has_many :accounts end class Account < AR::Base belongs_to :user scope :active, where(:active => true) scope :inactive, where(:active => false) end 

然后,您将访问帐户范围,如jklina所示: User.find(1).accounts.active等。访问所有用户的帐户,如: User.find(1).accounts

更新:

我修正了一些错误并在下面添加了更多内容。

根据您的问题的更新,我认为您需要将public方法作为类的方法:

 class Accounts < AR::Base ... # This is essentially a scope anyways def self.public where(:public => true) end end class User < AR::Base ... # This should return all the users accounts # and any public accounts def all_accounts Account.where("user_id = ? OR public is true", self.id) end end 

这可能是使用范围的好方案。

您可以在帐户模型中定义活动和非活动范围,然后使用以下内容:

 User.accounts User.accounts.active User.accounts.inactive 

您甚至可以将范围链接在一起,因此您可以执行以下操作:

 User.accounts.active.paid_up 

让我们看一下链中的返回值:

 User.find(params[:user_id]) # returns an instance of User class User.find(params[:user_id]).all_accounts # returns an array 

Array类没有名为all的实例方法,这就是您看到此错误的原因。 这不是一个错误。

你为什么不试试这个:

 class User has_many :accounts, :conditions => { :active => 1 } has_many :all_accounts :conditions => ["(active = ? OR public = ?)", true, true] end 

现在你可以:

 User.find(params[:user_id]).all_accounts.all(:limit => 10, :offset => 2) 

您尝试访问两个不同的表并将LIMIT / OFFSET作为组合联合应用于它们。 除非您在SQL层逻辑上将它们组合在一起,而不是在ActiveRecord层,否则不会发生这种情况。

听起来像写出SQL,可能使用UNION然后使用find_by_sql可能是你最好的。