0

我有一个公认的丑陋查询要做,以找到与当前角色相关的特定角色。此行产生正确的结果:

@person_event_role.event_role.event.event_roles.
  joins(:mission_role).where(:mission_roles => {:title => 'Boss'}).
  first.person_event_roles.first.person

(您可以从多个调用中推断出关联)

获取此信息的唯一方法需要大量了解数据库的结构,但要消除耦合......它需要在该链的每个步骤中填写一堆帮助函数以返回所需的信息。 ..

4

1 回答 1

1

我认为这里要做的是在适当的地方创建辅助函数。我不清楚您的关联链的开头是什么,但我可能会为其分配一个#event返回的方法event_role.event。从那里开始, anevent有一个#boss_role,或者在语义上有意义的任何东西,并且该方法是

event_roles.joins(:mission_role).where(:mission_roles => {:title => 'Boss'}).first 

最后,同样在Event模型上,有一个#boss方法,它得到

boss_roles.first.person_event_roles.first.person

因此,您的原始查询变为

@person_event_role.event.boss

然后,链条的每条腿都是独立的且易于理解,并且不需要您的链条的开头对它的结尾无所不知。我不完全理解这些关联的全部范围,但我很确定只需将其分解为三个或四个模型方法,就可以让您清楚地阅读和分离您正在寻找的关注点。你甚至可以进一步分解它以增加阅读的便利性,但这变成了风格问题。

希望有帮助!

以下由提问者原创

我想我遵循了这个建议并最终得到:

@person_event_role.get_related_event_roles_for('Boss').first.filled_by.first

#person_event_role:
def get_related_event_roles_for(role)
  event.event_roles_for(role)
end

def event
 event_role.event
end

#event:
def event_roles_for(role)
  event_roles.for_role(role)
end

#event_role:
scope :for_role, lambda {|role| joins(:mission_role).where(:mission_roles => {:title => role})}
def filled_by
  person_event_roles.collect {|per| per.person}
end
于 2012-01-21T02:53:01.617 回答