2009-11-23 14 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 Я не особенно привязан к нему быть именованным, если это облегчает (или даже возможно!)

Спасибо, Ash

ответ

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 перечислит все чаты, соответствующие вашим критериям. Вы также получаете бонусы, не требующие второго запроса для получения количества сообщений в чате.

+0

Вау ... это, безусловно, объясняет, почему я никуда не денусь - я склоняюсь перед вашими навыками Rails! Я дам этот вечер сегодня - спасибо! Fwiw Chat не отвечает, когда у него есть 0 сообщений от пользователя - он может иметь любое количество гостевых сообщений, но считается без ответа, пока не получит хотя бы одно сообщение от пользователя. – Ash

+0

Мне понадобилось время, чтобы окунуться в то, что вы здесь делали, но я понимаю это сейчас - работает! Благодаря! – Ash

+0

Думаю, я мог бы лучше объяснить, как продвинутый код достигает своей цели. Я обновлю решение для тех, у кого есть аналогичная проблема в будущем. – EmFi

Смежные вопросы