2009-11-23 140 views
0

我必須舉起雙手,宣佈我完全沉迷於此!通過has_many的屬性查找

我有以下型號:

Chat: 
    has_many :messages 

Message: 
    belongs_to :chat, :counter_cache => true 
    belongs_to :authorable, :polymorphic => true 

User: 
    has_many :messages, :as => :authorable 
    has_many :chats, :through => :messages, :uniq => true 

Guest: 
    has_many :messages, :as => :authorable 

我試圖寫一個聊天named_scope給我「懸而未決」的聊天記錄(其中懸而未決意味着有沒貼由該聊天的任何消息用戶) - 到目前爲止,我只能設法在很多圈子中轉圈!

任何幫助將非常感謝! FWIW我不是特別重視它是命名範圍,如果它可以更容易(甚至是不可能的!)

感謝, 灰

回答

3

的關鍵,命名範圍是將它們,它們就會返回到模型。要獲得未答覆的聊天記錄,您的命名範圍應該放在您的聊天模式中。不幸的是,通過查找關聯空白的情況,您並不容易。

這樣做與命名範圍涉及左/右外聯合和GROUP_BY運算符。它不會很漂亮,並不比編寫自己的SQL更好。您可能會發現使用計數器緩存更容易。但是,您的多態關聯可能意味着直接的計數器緩存也不起作用。

的問題是有點不清楚,是沒有答案的聊天記錄那些沒有消息什麼那麼或者只是那些沒有與用戶的消息(與消息聊天的客人只創作仍然被認爲是沒有答案?

如果它比前者一個簡單的計數器緩存會做,其他明智的你有一點點更多的工作要做

公共代碼爲兩種情況:

添加一列名爲MESSAGE_COUNT與此遷移的聊天記錄表:

class AddCounterCache < ActiveRecord::Migration 
    def self.up 
    add_column :chats, :message_count, :integer, :default => 0 
    end 

    def self.down 
    remove_column :chats, :message_count 
    end 
end 

然後在Chat模型中創建指定範圍。

class Chat < ActiveRecord::Base 
    ... 
    named_scope :unanswered, :conditions => {:message_count => 0} 
end 

對於其中一個懸而未決的聊天有0消息

class Message < ActiveRecord::Base 
    belongs_to :chat, :counter_cache => true 
end 

對於其中一個懸而未決的聊天可以由客人撰寫消息的情況下唯一代碼的情況下唯一的編碼,而不是用戶:

我們只想在某些情況下更新計數器緩存,所以我們需要重寫ActiveRecord用於增加計數器緩存的方法所以它只會在我們想要的時候觸發。 Rails提供了一種方便的方式重命名方法,並通過ActiveSupport's alias_method_chain將它們包裝在其他方法中。因此,此代碼會創建新方法,僅在必要時觸發用於更新計數器緩存的現有方法。然後使用alias_method_chain重命名這些方法,以便調用我們的新方法來代替ActiveRecord提供的方法。

class Message < ActiveRecord::Base 
    belongs_to :chat, :counter_cache => true 

    def belongs_to_counter_cache_after_create_for_chat_with_users_only 
    if authorable_type == "User" 
     belongs_to_counter_cache_after_create_for_chat_without_users_only 
    end 
    end 

    def belongs_to_counter_cache_before_destroy_for_chat_with_users_only 
    if authorable_type == "User" 
     belongs_to_counter_cache_before_destroy_for_chat_without_users_only 
    end 
    end 

    alias_method_chain :belongs_to_counter_cache_before_destroy_for_chat, :users_only 
    alias_method_chain :belongs_to_counter_cache_after_create_for_chat, :users_only 

end 

一旦完成這一切。 Chat.unanswered將列出符合您標準的所有聊天。您還可以獲得無需第二次查詢即可獲取聊天中消息數量的獎勵。

+0

哇...這當然解釋了爲什麼我沒有得到任何地方 - 我向你的Rails技能鞠躬!今晚我會說這個 - 非常感謝!當用戶發佈0條帖子時,Fwiw聊天沒有得到答覆 - 它可以包含任意數量的帖子,但在用戶收到至少一條帖子後纔會被視爲無人答覆。 – Ash 2009-11-24 13:16:02

+0

我花了一段時間纔將自己的頭腦圍繞在這裏 - 但我現在明白了 - 盡情享受!謝謝! – Ash 2009-11-30 13:04:04

+0

我想我可以更好地解釋高級代碼如何實現其目標。我將爲那些將來遇到類似問題的人更新解決方案。 – EmFi 2009-11-30 13:53:34