Как мне применить закон Деметры к этому?
У меня есть заведомо некрасивый запрос, чтобы найти определенную роль, связанную с текущей ролью. Эта строка дает правильный результат:
@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