Как мне применить закон Деметры к этому?

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

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

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

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

1 ответ

Решение

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