Насколько я знаю, ваше условие has_one
никогда не будет работать в Rails.
Вам нужно одно явное has_one
или belongs_to
или has_many на каждую "ссылку" в обеих таблицах. Так что если у вас есть две «ссылки», вам нужно две has_one
и две belongs_to
. Вот как это работает.
Во-вторых, я думаю, вы должны пересмотреть свои модели. Как вы это делаете, один человек не может быть президентом клуба и сотрудником одновременно. Или быть президентом двух клубов. Даже если у вас их нет прямо сейчас, они могут прийти в будущем - проще оставаться гибким прямо сейчас.
Гибкий способ сделать это - использовать has_many :through
с промежуточной таблицей, в которой указана роль. Другими словами:
# The memberships table has a person_id, club_id and role_id, all integers
class Membership < ActiveRecord::Base
belongs_to :club
belongs_to :person
validates_presence_of :role_id
validates_numericality_of :role_id
end
class Club < ActiveRecord::Base
has_many :memberships, :dependent => :delete_all
has_many :people, :through => :memberships
end
class Person < ActiveRecord::Base
has_many :memberships, :dependent => :delete_all
has_many :clubs, :through => :memberships
end
Теперь, предполагая, что role_id = 0 означает сотрудника, role_id = 1 означает президента, а role_id = 2 означает вице-президента, вы можете использовать его следующим образом:
tyler = Person.find(1) # person_id is 1
other = Person.find(2) # person_id is 2
c = Club.find(1) # club_id is 1
tyler.clubs # returns all the clubs this person is "member" of
c.people # returns all the "members" of this club, no matter their role
#make tyler the president of c
tyler.memberships.create(:club_id => 1, :role_id => 1)
#make other the vicepresident of c
#but using c.memberships instead of other.memberships (works both ways)
c.memberships.create(:person_id => 2, :role_id => 1)
#find the (first) president of c
c.memberships.find_by_role_id(1).person
#find the (first) vicepresident of c
c.memberships.find_by_role_id(2).person
#find all the employees of c
c.memberships.find_all_by_role_id(0).collect { |m| m.person }
#find all the clubs of which tyler is president
tyler.memberships.find_all_by_role_id(1).collect { |m| m.club }
Дополнительные примечания:
- Вы можете дополнить это таблицей ролей и моделью. Роли будут иметь только имя, роли будут иметь отношения
have_many
, а членство будет belong_to
ролью. Или вы можете определить методы в членстве для получения имени роли (если 0, он возвращает «сотрудник», если 1, «президент» и т. Д.
- Вы можете добавить проверки членства, чтобы не более 1 человека мог быть назначен президентом данного клуба, или один и тот же сотрудник в одном клубе дважды. Позже, если вы начнете получать «исключительные случаи», когда человек должен находиться в двух местах, вам просто придется адаптировать свои проверки.