在ActiveRecord上遍历HABTM关系
时间:2020-03-06 15:00:34 来源:igfitidea点击:
我正在为我的学校在Rails上开发一个项目(不用担心这不会在代码上评分),并且我正在寻找一种干净的方法来遍历ActiveRecord中的关系。
我有一个称为用户,组和分配的ActiveRecord类。用户和组以及组和分配具有HABTM关系。现在,我需要的是一个用户函数get_group(aid),其中"给了一个用户,找到分配了任务的组"。
简单的路线是:
def get_group(aid) group = nil groups.each { |g| group = g if g.assignment.find(aid).id == aid } return group end
是否有一种更清洁的实现方式可以利用组和分配之间的HABTM关系,而不仅仅是迭代?我还尝试过的一件事是find()的:include选项,如下所示:
def get_group(aid) user.groups.find(:first, :include => :assignments, :conditions => ["assignments.id = ?", aid]) end
但这似乎不起作用。有任何想法吗?
解决方案
首先,要小心。由于我们在两种关系中都使用了" has_and_belongs_to_many",因此对于给定的"用户"和"分配",可能会有多个"组"。因此,我将实现一个返回" Group"数组的方法。
其次,采用赋值ID的方法User#get_group的名称极具误导性,且不像Ruby。
这是使用交集运算符Ruby的" Array#&"获取所有公共组的一种干净方法。由于该方法返回的是Group实例,因此我给该方法起了一个更显眼的名称,并将其放在Group上。但是请注意,它会加载与一个人相关但与另一个不相关的Group
:
class Group < ActiveRecord::Base has_and_belongs_to_many :assignments has_and_belongs_to_many :users # Use the array intersection operator to find all groups associated with both the User and Assignment # instances that were passed in def self.find_all_by_user_and_assignment(user, assignment) user.groups & assignment.groups end end
然后,如果我们确实需要User#get_groups
方法,则可以这样定义:
class User < ActiveRecord::Base has_and_belongs_to_many :groups def get_groups(assignment_id) Group.find_all_by_user_and_assignment(self, Assignment.find(assignment_id)) end end
尽管我可能将其命名为User#groups_by_assignment_id
。
我的"分配"模型很简单:
class Assignment < ActiveRecord::Base has_and_belongs_to_many :groups end