2

我試圖連接的兩個連接,我已經和展示基於條件的關係,結果表中的值......,我有一些問題HABTM關係和加入表

我有一個用戶模型(:名稱,密碼,電子郵件)和事件模型(:名稱,等)和興趣模型(:名稱)

我在每個模型中創建了約5條記錄。

然後我創建了兩個連接表 - > UsersInterests和EventsInterests;每個不包含主鍵並且分別僅由user_id/interest_id和event_id/interest_id組成。

然後我加入到模型文件的HABTM關係

users => has_and_belongs_to_many :interests 
events => has_and_belongs_to_many :interests 
interests => has_and_belongs_to_many :users 
     has_and_belongs_to_many :events 

現在我想創建一個控制器,發現只有在用戶利益的事件對應的事件感興趣

從這工作一會兒,我計算過,我需要的東西在

@Events = Event.User.find([condition]) 
[condition] = where users.interest == event.interest 

或類似的東西的地區...我是那種lost..How做你的狀態的網絡連接nd條件?...我知道如何做的內部連接在SQL中,但我正在尋找優雅的Rails的方式來做到這一點...任何提示球員?

+0

用戶可以有一個興趣或有多少?事件如何? – zetetic 2010-02-01 04:08:42

+0

興趣和事件都可以有很多興趣 – ChrisWesAllen 2010-02-01 17:45:35

+0

你可以更明確地定義你想要獲得的列表嗎?在「只有用戶興趣符合事件興趣的事件」中,你是指一組特定的用戶?或任何用戶? – EmFi 2010-02-01 22:55:28

回答

7

優雅的紅寶石方式是named scopes。但是,因爲您決定使用has_and_belongs_to_many關係而不是has_many:通過關係,您將需要使用原始SQL定義聯接,這不是很優雅。由於Rails處理SQL生成的方式,您將必須爲單個用戶創建一個範圍,併爲第二個命名範圍提供許多用戶的使用範圍。

Class Event < ActiveRecord::Base 
    ... 

    #find events that share an interest with a single user 
    named_scope :shares_interest_with_user, lambda {|user| 
    { :joins => "LEFT JOIN events_interests ei ON ei.event_id = events.id " + 
     "LEFT JOIN users_intersets ui ON ui.interest_id = ei.interest_id", 
     :conditions => ["ui.user_id = ?", user], :group_by => "events.id" 
    } 

    #find events that share an interest with a list of users 
    named_scope :shares_interest_with_users, lambda {|users| 
    { :joins => "LEFT JOIN events_interests ei ON ei.event_id = events.id " + 
     "LEFT JOIN users_intersets ui ON ui.interest_id = ei.interest_id", 
     :conditions => ["ui.user_id IN ?", users], :group_by => "events.id" 
    }  
    } 

    #find events that share an interest with any user 
    named_scope :shares_interest_with_any_user, lambda { 
    { :joins => "LEFT JOIN events_interests ei ON ei.event_id = events.id " + 
     "JOIN users_intersets ui ON ui.interest_id = ei.interest_id", 
     :conditions => "ui.user_id IS NOT NULL", :group_by => "events.id" 
    }  
    } 

end 

現在你可以這樣做是爲了讓所有的事件,一個用戶可能感興趣的:

@events = Event.shares_interest_with_user(@user) 

或者,這讓所有的活動用戶的列表可能感興趣的:

@events = Event.shares_interest_with_users(@users) 

但正如我所警告的那樣,那不是真的優雅

如果您通過與適當的連接模型而非HABTM關係的關係重新定義關係爲has_many,則可以大大簡化連接。你的情況將需要nested has many through plugin這個工作。注:您必須在所有其他模型中添加相應的has_many/belongs_to語句。即使是加入模型。

Class Event < ActiveRecord::Base 
    has_many :event_interests 
    has_many :interests, :through => :event_interests 
    has_many :user_interests, :through => :interests 
    has_many :users, :through => :user_interests 
    ... 

    #find events that share an interest with a list of users 
    named_scope :shares_interest_with_users, lambda {|user| 
    { :joins => :user_interests, :group_by => "events.id", 
     :conditions => {:user_interests => {:user_id => user}} 
    }  
    } 

    #find events that share an interest with any user 
    named_scope :shares_interest_with_any_user, lambda { 
    { :joins => :user_interests, :group_by => "events.id", 
     :conditions => "user_interests.user_id IS NOT NULL" 
    } 

end 

現在,下面的工作。

@user = User.first; @users = User.find(1,2,3) 

# @events = all events a single user would be interested in 
@events = Event.shares_interest_with_users(@user) 

# @events = all events any of the listed users would be interested in. 
@events = Event.shares_interest_with_users(@user) 

你甚至可以定義一個名爲範圍,選擇尚未發生的事件和連鎖兩種:

named_scope :future_events, lambda { 
    { :conditions => ["start_time > ?", Time.now]} 
} 

Events.future_events #=> Events that haven't started yet. 

# Events that a user would be interested in but only choose those 
# that haven't started yet. 
Events.future_events.shares_interest_with_user(@user) 
+0

這個問題有點含糊。所以如果我誤解了你的問題,請告訴我,我會更新解決方案。無論我是否正確理解問題,命名範圍可能是解決問題的最佳方法。 – EmFi 2010-02-01 04:47:26

+0

這真的好像很多我想做的事情... 我正在尋找一些東西在 @events = Event.find(:all,:conditions => {:users_interests ==:events_interests }) 但我得到錯誤=>「哈希奇數列表」? – ChrisWesAllen 2010-02-01 18:05:54

+0

'{:user_interests ==:events_interests}'即使在SQL中也沒有意義。首先它不是一個有效的散列。其次,users_interests和events_interests都是無效散列鍵,除非您明確加入這些表。 – EmFi 2010-02-01 22:55:54