Skip to content

Instantly share code, notes, and snippets.

@codesnik
Created March 5, 2010 21:32
Show Gist options
  • Save codesnik/323175 to your computer and use it in GitHub Desktop.
Save codesnik/323175 to your computer and use it in GitHub Desktop.
class Message < ActiveRecord::Base
# обновляет updated_at у родительского сообщения, нужно для сортировки
belongs_to :parent, :class_name => "Message", :touch => true
belongs_to :sender, :class_name => "User"
belongs_to :recipient, :class_name => "User"
has_many :messages, :foreign_key => :parent_id, :dependent => :delete_all
default_scope order('created_at desc')
scope :threads, where(:parent_id => nil)
scope :unread, where(:unread => true)
scope :with_user, lambda { |user|
where(["recipient_id = ? or sender_id = ?", user.id, user.id])
}
scope :written_by, lambda { |user| where(:sender_id => user.id) }
scope :received_by, lambda { |user| where(:recipient_id => user.id) }
scope :unread_by, lambda { |user| unread.received_by(user) }
scope :ordered_by_activity, order('updated_at desc')
# что-то одно должно присутствовать
validates_presence_of :body, :if => proc {|msg| msg.subject.blank? }
validates_presence_of :sender, :recipient
def thread_starter?; !parent_id end
def reply?; !thread_starter? end
def thread; parent || self end
def thread_id; parent_id || id end
# TODO try to get this via association
def thread_messages
#thread.messages + [thread]
Message.where(["id = ? or parent_id = ?", thread_id, thread_id])
end
def thread_messages_count
thread.messages.count + 1
end
def new_reply(author)
msg = thread.messages.build :sender => author
# можно писать в свой же тред
msg.recipient = (thread.sender == author) ? thread.recipient : thread.sender
msg
end
delegate :subject, :to => :thread, :prefix => :thread
def unread_by?(reader)
unread? && reader != sender
end
def unread_count_for(reader)
thread_messages.unread_by(reader).count
end
def thread_unread_by?(reader)
unread_count_for(reader) != 0
end
def first_unread_or_last_read_for(reader)
# last и first имеют противоположный смысл из-за default_scope
# TODO избавиться от него?
thread_messages.unread_by(reader).last || thread_messages.first
end
def read!(reader)
thread_messages.unread_by(reader).update_all :unread => false
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment