Как мне применить закон Деметры к этому? - PullRequest
0 голосов
/ 21 января 2012

У меня, по общему признанию, ужасный запрос, чтобы найти определенную роль, связанную с текущей ролью. Эта строка дает правильный результат:

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

(Вы можете вывести ассоциации из множества этих вызовов)

Единственный способ получить эту информацию требует тонны знаний о структуре базы данных, но удалить связь ... Это потребовало бы заполнения набора вспомогательных функций на каждом шаге этой цепочки, чтобы вернуть нужна информация ...

1 Ответ

1 голос
/ 21 января 2012

Я думаю, что здесь нужно создать вспомогательные функции там, где это необходимо. Мне неясно, с чего начинается ваша цепочка ассоциаций, но я, вероятно, назначил бы ей метод #event, который возвращает event_role.event. Оттуда event имеет #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
...