我必须举起双手,宣布我完全被这一个难住了!
我有以下型号:
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
我正在尝试在Chats上写一个named_scope给我“无人接听”的聊天(未答复意味着没有任何用户发布的聊天消息) - 到目前为止我只是设法绕过很多圈子!
任何帮助都会非常非常感谢! fwiw如果它变得更容易(甚至可能!),我并不特别喜欢它是一个命名的范围。
谢谢, 灰
答案 0 :(得分:3)
命名范围的关键是将它们放在它们将返回的模型中。要获得未答复的聊天记录,您的命名范围应该放在聊天模型中。不幸的是,通过查找关联为空的情况,您并不是很容易。
使用命名范围执行此操作涉及LEFT / RIGHT OUTER连接和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
然后在聊天模型中创建命名范围。
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
会列出符合条件的所有聊天记录。您还可以获得不需要第二个查询来获取聊天中的消息数量的奖励。
答案 1 :(得分:1)
你可以在has_many模型本身上定义named_scope。
Chat.messages.unanswered
或者,您可以在SQL中编写named_scope,这样您就可以进行Chat.unanswered,但这对我来说感觉就像是错误的api。
更多示例:http://blog.peelmeagrape.net/2008/6/21/named_scope-is-super-awsome-with-has_many