2008-12-31 84 views
2

我想知道什麼是最好的方式來建模關係,其中一個對象正好與另一個類的n個對象相關聯。我想將has_one關係擴展到n的特定值。ActiveRecord has_n關聯

例如,TopFiveMoviesList將屬於用戶並具有恰好五個電影。我會想象底層的sql表會有像movie_id_1,movie_id_2,... movie_id_5這樣的字段。

我知道我可以做一個has_many關係,並限制模型級別的孩子數量,但我寧願沒有中間表。

回答

1

我的第一個直覺是使用連接表,但如果這不合意User.movie[1-5]_id列將適合該法案。 (我認爲movie1_id適合用Rails約定比movie_id_1更好。)

既然你標記這個Rails和ActiveRecord的,我會添加一些沒有經過充分測試,可能有些錯誤的模型代碼我的答案。 :)

class User < ActiveRecord::Base 
    TOP_N_MOVIES = 5 
    (1..TOP_N_MOVIES).each { |n| belongs_to "movie#{n}".to_sym, :class_name => Movie } 
end 

你可以包裝在一個宏風格的方法行,但除非如果這是你的應用程序的通用模式,這樣做將可能只是讓你的代碼更難與小DRY利益閱讀。

您可能還需要添加驗證以確保用戶列表中沒有重複的影片。

將您的電影課程關聯回您的用戶是類似的。

class Movie < ActiveRecord::Base 

    (1..User::TOP_N_MOVIES).each do |n| 
    has_many "users_list_as_top_#{n}".to_sym, :class_name => User, :foreign_key => "movie#{n}_id" 
    end 

    def users_list_as_top_anything 
    ary = [] 
    (1..User::TOP_N_MOVIES).each {|n| ary += self.send("users_list_as_top_#{n}") } 
    return ary 
    end 

end 

(當然,這users_list_as_top_anything可能會更好寫出爲明確的SQL。今天我懶。)

1

我假設你的意思是「實施」而不是「模型」?在UML中建模非常簡單,比如說,您有一個由5個Movie實體組成的Person實體。

但是,當你說has_one時,難度會降到has_5。如果它是一個簡單的標量值,則has_one可能是父實體的屬性。 Has_5可能是2個通過UML中的「由...構成」關係相互關聯的實體。

要回答的主要問題可能是「你能保證它始終是'前5名'嗎?」如果是,請使用列進行建模,如您所述。如果不是,則用另一個實體進行建模。

另一個問題可能是「重構有多容易?」如果它很簡單,嘿,從5列開始,並重構分離的實體,如果它改變了。

像往常一樣,「最佳」取決於業務和技術環境。

2

我想通過一個連接模型實施這一模式將是你最好的在這裏下注。它允許List模型擔心List邏輯和Movie模型擔心Movie邏輯。您可以創建一個Nomination(名稱不是最偉大的,但您知道我的意思)模型來處理電影和列表之間的關係,並且當限制爲5時,您可以僅限制您撤回的提名數量。

有幾個原因我認爲這種方法更好。

首先,假設您希望能夠遍歷關係(movie.listslist.movies),那麼5列方法將變得更加複雜。

儘管ActiveRecord支持has n關係會更好,但它不會,所以你會在那個框架上打架。此外,在這種情況下,我與has n的關係似乎有點脆弱。我還沒有看到ActiveRecord中的那種實現,儘管我真的很感興趣看到它發生。 :)