Сообщение пользователя модели в рельсах 3
Я создал следующую модель для обмена сообщениями пользователей:
create_table "messages", :force => true do |t|
t.integer "source_id"
t.integer "destination_id"
t.string "object"
t.string "body"
t.datetime "created_at"
t.datetime "updated_at"
end
Это их ассоциации:
class Message < ActiveRecord::Base
belongs_to :sender, :class_name=>'User', :foreign_key=>'source_id'
belongs_to :reciever, :class_name=>'User', :foreign_key=>'destination_id'
end
И это другие ассоциации с другой стороны (модель пользователя):
has_many :sent_messages, :class_name=> 'Message', :foreign_key=>'source_id', :dependent=>:destroy
has_many :recieved_messages, :class_name=> 'Message', :foreign_key=>'destination_id', :dependent=>:destroy
Модель верна и работает правильно, ведь из сообщения, которое я могу получить, кто является отправителем, а кто является получателем и от пользователя, я могу получить все отправленные и полученные сообщения. К сожалению, он не справляется с какой-либо ситуацией: что, если получатель или отправитель удаляют сообщение? Сообщение уникально, поэтому оно исчезает с обеих сторон (плохое). Как узнать, прочитала ли одна из сторон сообщение?
Любое предложение? Как вы думаете, мне нужно перепланировать модель?
Tnx
Ответы
Ответ 1
Это хорошая проблема! Я бы смоделировал это, чтобы сравнить как можно ближе к модели электронной почты. Таким образом, сообщение всегда принадлежит одному пользователю, и оно было отправлено или получено.
Короче:
create_table "messages", :force => true do |t|
t.integer :user_id
t.string :subject
t.string :body
t.boolean :sent
end
И модель хотела бы:
class Message < ActiveRecord::Base
belongs_to :user
scope :sent, where(:sent => true)
scope :received, where(:sent => false)
end
И у пользователя:
class User
has_many :messages
end
Тогда вы просто сможете запросить все отправленные сообщения
user.messages.sent
и полученные сообщения
user.messages.received
Отправка сообщения становится немного более сложной, чем:
class Message
def send_message(from, recipients)
recipients.each do |recipient|
msg = self.clone
msg.sent = false
msg.user_id = recipient
msg.save
end
self.update_attributes :user_id => from.id, :sent => true
end
end
или что-то в этом роде: вы копируете сообщение и присоединяете его ко всем получателям и, наконец, отправляете исходное сообщение отправленное сообщение.
Таким образом, каждый пользователь имеет полный контроль над сообщением.
Возможные улучшения:
- также содержит явную ссылку на отправителя и получателя (ов) в сообщении, чтобы иметь возможность разрешать ответы и прочее
- вместо работы с одним булевым, возможно, разрешить работу с папками?
Надеюсь, что это поможет.
Ответ 2
Вы можете добавить два логических значения, чтобы пометить сообщение как удаленное как для отправителя, так и для получателя. Затем, установив любой из них, проверьте, может ли сообщение быть удалено навсегда.
Пример:
create_table "messages", :force => true do |t|
t.boolean :sender_deleted
t.boolean :receiver_deleted
end
И в модели:
class Message
def self.delete_message(id)
m = Message.find(id)
m.destroy if m.sender_deleted && m.receiver_deleted
end
end
Ответ 3
Вы можете свести на нет удаляемую запись с помощью :dependent=>:nullify
has_many :sent_messages, :class_name=> 'Message', :foreign_key=>'source_id', :dependent=>:nullify
has_many :recieved_messages, :class_name=> 'Message', :foreign_key=>'destination_id', :dependent=>:nullify
Вам нужно будет обработать при отображении сообщения о том, что отправитель/получатель сообщения был удален, поскольку sender_id или destination_id будут пустыми, но сообщение останется нетронутым.