2010-02-08 63 views
6

我有兩個班,我想說明如下:多個關聯到同一型號

class Club < ActiveRecord::Base 
    belongs_to :president, :class_name => "Person", :foreign_key => "president_id" 
    belongs_to :vice_president, 
      :class_name => "Person", 
      :foreign_key => "vice_president_id" 
end 

class Person < ActiveRecord::Base 
    has_one :club, :conditions => 
    ['president_id = ? OR vice_president_id = ?', '#{self.id}', '#{self.id}'] 
end 

試圖從人對象的俱樂部協會時不工作,給我一個錯誤。這個錯誤是因爲當我查看SQL時正在查找club_table中的person_id。我可以通過聲明多個has_one關聯來解決它,但感覺這是不正確的做法。

一個人只能是一個俱樂部的總裁或副總裁。

任何人都可以就這個問題提供一些建議,我會非常感激。

回答

8

has_one條件絕不會在Rails的工作,因爲據我所知。

在兩個表上,您需要一個明確的has_onebelongs_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表示vice_president,可以使用這樣的:

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人成爲總裁一個俱樂部或同一個俱樂部的同一個員工兩次,後來,如果你開始獲得一個人需要在兩個地方的「例外情況」,那麼你只需要修改你的驗證。
+0

好吧,這絕對是一個更好的結構。不過,我不確定員工的工作是如何工作的。如果員工的名字是俱樂部的一部分,那麼他們真的是獨立的,所以我認爲它不應該是會員表的一部分。順便說一句,我已經爲我們擁有的不同員工角色使用了角色模型。所以也許在Person模型中應該有一個與has_one EmployeeRole的關聯,並且它給出了他們的僱員類型? – adimitri 2010-02-10 18:38:04

+0

你好!我不確定我是否明白'如果他們是俱樂部的一部分,那麼'真正的獨立'是什麼意思'。如果你有一個包含員工角色的角色表,你可以再添加2個(「總裁」和「副總裁」),只用一件事。爲什麼你想讓他們分開? – kikito 2010-02-10 20:40:48

+0

此應用程序適用於大學校園內的學生政府組織。他們資助了許多由學生管理的俱樂部,並擁有4個電子董事會職位(總裁,副總裁,祕書財務主任)。員工是學生政府和學生,但與俱樂部無關。所以他們可能是俱樂部電子白板和員工的一部分。 – adimitri 2010-02-10 22:09:39

0

我認爲你的關聯是錯誤的。你的方式很難派任總裁或副總裁。

我會做這樣的:

class Club < ActiveRecord::Base 
    has_one :president, 
      :class_name => "Person", 
      :foreign_key => 'president_club_id' 
    has_one :vice_president, 
      :class_name => "Person", 
      :foreign_key => 'vice_president_club_id' 
end 

class Person < ActiveRecord::Base 
    belongs_to :club 
end 

現在你可以指定這樣的角色:

club.president = Person.create(:name => 'Tom') 
club.vice_president = Person.create(:name => 'Andrew') 
+0

雖然這不起作用,因爲那時我需要在People表中有一個president_club_id和vice_president_club_id(並且在我的實際應用中還有兩個位置)。另外,我必須在Person類中擁有多個belongs_to去工作 另外一些人樂可能不是負責俱樂部,而是負責'員工',所以我想保留foreign_key的模型。 – adimitri 2010-02-08 16:30:30

0

我建議你介紹一個叫角色新模式。然後得到以下內容:

class Club 
    has_many :roles 

    def president 
    end 

    def vice_president 
    end 

end 

class Person 
    belongs_to :role 
end 

class Role 
    has_one :person 
    belongs_to :club 
end 
0

這是多態關聯的經典用例。 這裏是鏈接: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

喜歡的東西..

class Club < ActiveRecord::Base 
    belongs_to :person, :polymorphic => true 

class Person < ActiveRecord::Base 
    has_one :club, :as => :position 
+0

多態協會不會幫助解決這裏的問題,因爲它的多個人從相同的模型訪問。多態關聯適用於您的foreign_key可能是不同模型的情況。 – adimitri 2010-02-10 18:55:22