Сообщение пользователя модели в рельсах 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 будут пустыми, но сообщение останется нетронутым.