2009-08-10 77 views
2

我是新手在rails中,並嘗試在mysql中執行左連接。左加入rails/mysql

有兩個對象 - 用戶和消息。

用戶has_and_belongs_to_many消息,消息has_and_belongs_to_many用戶

目前,通過簡單地寫user.messages我獲得以下具有受限==假未連接到任何用戶,但是在查詢控制檯

SELECT * FROM `messages` INNER JOIN `messages_users` ON `messages`.id = `messages_users`.message_id WHERE (`users_messages`.group_id = 1) 

消息任何用戶都可以訪問,我需要將收集Message.all(restricted => false)添加到user.messages

將解決我的問題的查詢將是:

select * from messages left join messages_users on messages_users.message_id=messages.id and messages_users.user_id=1 where (messages_users.user_id is NULL and messages.restricted=false) OR (messages_users.user_id=1 and messages.restricted=true); 

我如何儘可能優雅地在軌道上寫它?

它會像

Message.find(:all,:conditions => "(messages_users.user_id is NULL and messages.restricted=false) OR (messages_users.user_id=1 and messages.restricted=true)", :joins => "left join messages_groups on messages_users.message_id=messages.id and messages_users.user_id=1 ") 

,也可以是不便更好?

我使用的鐵軌2.3.2

感謝, 帕維爾

回答

1

在我看來,您試圖在該查詢中拉兩件事:1)所有與限制= false的用戶綁定的消息; 2)與restricted = true綁定到當前用戶的所有消息。

如果我正確地理解了這一點,如果您希望將其作爲單個查詢完成,我不會看到更好的方法。但是,如果您願意提出兩個查詢,則可以在代碼中稍微清理它(可能會減慢執行速度)。這裏是替代設置:

class Message < ActiveRecord:Base 
    has_and_belongs_to_many :users 

    named_scope :restricted, :conditions => {:restricted => true} 
    named_scope :unrestricted, :conditions => {:restricted => false} 
    named_scope :public, :conditions => "id NOT IN (SELECT DISTINCT message_id FROM messages_users)" 
end 

class User < ActiveRecord:Base 
    has_and_belongs_to_many :messages 
end 

要在更短的代碼清單,但需要兩個數據庫的訪問,你可以這樣做:

@current_user.messages.restricted + Message.unrestricted.public 

在這兩種情況下,如果在這些數據的任何大量的您需要確保表格已正確編制索引,否則這將會隨着任何負載而減慢。如果這是一個包含大量消息的應用程序,那麼使用單個查詢可能會更好。如果它只是一個不會使用太多的副功能,我可能會選擇更清晰的版本。

從模型的角度來看,更好的方法是擺脫HABTM關係並明確建立關係模型。然後,您有一個方便的地方來跟蹤有關郵件發送/傳送/接收過程的其他數據(如發送跟蹤時間,讀取時間等)。它不會改變上面的任何討論,我只是希望有許多通過HABTM。

class Message < ActiveRecord:Base 

    has_many :subscriptions 
    has_many :users, :through => :subscriptions 

    named_scope :restricted, :conditions => {:restricted => true} 
    named_scope :unrestricted, :conditions => {:restricted => false} 
    named_scope :public, :conditions => "id NOT IN (SELECT DISTINCT message_id FROM subscriptions)" 
end 

class User < ActiveRecord:Base 

    has_many :subscriptions 
    has_many :messages, :through => :subscriptions 

end 

class Subscription < ActiveRecord:Base 

    belongs_to :message 
    belongs_to :user 

end 
0

我想named_scopes可能是你的答案。在模型中把這樣的:

named_scope :restricted, :conditions => {:restricted => true} 
named_scope :unrestricted, :conditions => {:restricted => false} 

然後就可以調用之類的東西:

Message.restricted 
=> All restricted messages 

User.first.messages.unrestricted 
=> All unrestricted messages belonging to the first user. 

我相信通過HABTM協會這些工作。

1

爲什麼不使用:包括?

+0

...但不會':include'也做了相關記錄,這似乎並不希望在當前形勢下的迫切負荷。這是我想解決的問題。 – Purplejacket 2011-10-05 20:03:33