Предположим, у нас есть тренеры, клиенты и пользователи.Какой самый идиоматический способ моделирования этих отношений в Rails?
Каков идеальный способ моделирования этого способа, который не является наследованием? Я бы хотел избежать ИППП.
Сейчас у меня есть что-то вроде этого:
user.rb
has_many :coaches, :foreign_key => :client_id
has_many :coach_users, :through => :coaches, :source => :user
has_many :clients, :class_name => "Coach"
has_many :client_users, :through => :clients, :source => :client
def is_a_coach_of?(client)
self.client_users.include?(client)
end
def is_a_client_of?(coach)
self.coach_users.include?(coach)
end
coach.rb
belongs_to :user
belongs_to :client, :class_name => "User"
Но это чувствует себя очень неуклюжим, чтобы иметь дело с объектом пользователя, который, предположительно, «тренер» и должен вводить user.coach_users, чтобы получить коллекцию пользователей, которые тренируются этим конкретным пользователем.
Он чувствует себя очень идиоматичным и, честно говоря, просто путают, и я его ненавижу. Я хочу что-то более элегантное.
Я думал об удалении модели соединения и просто имел два has_many на модели user.rb, но все еще чувствует себя неуклюжим, особенно нехорошее чувство нарушения ролей объектов. Это разные роли, но они также очень похожи, потому что все они являются пользователями. Как вы отделяете такую общую логику элегантным способом, правильным идиоматическим способом с Rails и Ruby?
А «пользователь сайта» может существовать без будучи coach
или client
.
Если моделирование требует только отношений, то я вижу, что это HABTM, но что, если индивидуальные отношения требуют дополнительной логики? Например, дополнительная логика для клиента или тренера? Вы бы просто смешивали класс, определяющий логику в модели User? Или вы бы создали отдельные модели AR для отношений, и если да, то как?
Почему вы хотите, чтобы избежать использования ИППП? Это хороший случай для этого. – Substantial
Из того, что я собираю, STI, как правило, плохое решение проблемы, но если это идеальный случай ... –
STI работает хорошо, если все сделано правильно, несмотря на то, что его очень легко использовать. Обратите внимание, что 'User' станет абстрактным классом, и вы должны только взаимодействовать с ним через его подклассы. Например, необходимо создать экземпляр «Coach» или «Client», а не «User». Тем не менее, многие люди нарушают это правило, включая грязные хаки, чтобы ограничить встроенную поддержку Rails, расстраиваться и писать сообщения в блогах, наказывающие STI как «плохое решение». Если вы готовы отказаться от контроля над «Пользователем», я напишу вам ответ. – Substantial