How do I apply the Law of Demeter to this?

删除回忆录丶 提交于 2019-12-12 03:18:01

问题


I have an admittedly ugly query to do, to find a particular role related to the current role. This line produces the correct result:

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

(You can infer the associations from the plurality of those calls)

The only way to get this information requires a ton of knowledge of the structure of the database, but to remove the coupling... It would require filling in a bunch of helper functions in each step of that chain to give back the needed info...


回答1:


I think the thing to do here is to create the helper functions where appropriate. I'm unclear what the beginning of your association chain is here, but I'd probably assign it a method #event that returns event_role.event. From there, an event has an #boss_role, or whatever makes sense semantically, and that method is

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

Finally, also on the Event model, there's a #boss method, which gets

boss_roles.first.person_event_roles.first.person

So, your original query becomes

@person_event_role.event.boss

Each leg of the chain is then self-contained and easy to understand, and it doesn't require the beginning of your chain to be omniscient about the end of it. I don't fully comprehend the full reach of these associations, but I'm pretty sure that just breaking it into three or four model methods will give you the clean reading and separation of concerns you're looking for. You might even break it down further for additional ease of reading, but that becomes a question of style.

Hope that helps!

The following is by the original questioner

I think I followed this advice and ended up with:

@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


来源:https://stackoverflow.com/questions/8950122/how-do-i-apply-the-law-of-demeter-to-this

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!