2013-06-04 3 views
0

Предположим, у нас есть тренеры, клиенты и пользователи.Какой самый идиоматический способ моделирования этих отношений в 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 для отношений, и если да, то как?

+1

Почему вы хотите, чтобы избежать использования ИППП? Это хороший случай для этого. – Substantial

+0

Из того, что я собираю, STI, как правило, плохое решение проблемы, но если это идеальный случай ... –

+0

STI работает хорошо, если все сделано правильно, несмотря на то, что его очень легко использовать. Обратите внимание, что 'User' станет абстрактным классом, и вы должны только взаимодействовать с ним через его подклассы. Например, необходимо создать экземпляр «Coach» или «Client», а не «User». Тем не менее, многие люди нарушают это правило, включая грязные хаки, чтобы ограничить встроенную поддержку Rails, расстраиваться и писать сообщения в блогах, наказывающие STI как «плохое решение». Если вы готовы отказаться от контроля над «Пользователем», я напишу вам ответ. – Substantial

ответ

1

Если client/coach - это всего лишь отношения, это может быть именно эта, а не отдельная модель. Таким образом, вы можете сделать связь has_and_belongs_to_many между Users. Создание миграции с:

def up 
    create_table :coaches_clients do |t| 
     t.integer :coach_id 
     t.integer :client_id 
    end 
    end 

и в вас модели:

has_and_belongs_to_many :clients, 
     :foreign_key => 'client_id', 
     :association_foreign_key => 'coach_id', 
     :class_name => 'User', 
     :join_table => 'coaches_clients' 

has_and_belongs_to_many :coaches, 
     :foreign_key => 'coach_id', 
     :association_foreign_key => 'client_id', 
     :class_name => 'User', 
     :join_table => 'coaches_clients' 
+0

Хорошо спасибо. Имеет смысл. Если вы должны принять меры предосторожности в отношении того, что клиенту или тренеру может понадобиться дополнительная логика, как бы вы могли моделировать его в этом смысле? –

+0

Это действительно зависит от ваших потребностей, но я считаю удобным иметь модель пользователя, модель 'has_one' и модель клиента' has_one'.Таким образом, вы можете иметь пользовательские детали и логику, связанные с этим в пользователе отдельно, и пользователь может быть тренером, клиентом, оба или ни одним из них. Таким образом, логика тренера может идти в модели «тренера». Не уверен, насколько идиоматично это, я думаю, вы будете называть 'user.coach.clients' и т. Д. – flyingjamus

Смежные вопросы