开发者

model user's message in rails 3

I have built the following model to handle user's message exchange:

 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

These are its associations:

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

And these other are the associations on the other side (the user model):

 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

The model is correct and work properly, in fact from the message 开发者_StackOverflow中文版I can retrieve who is the sender and who is the receiver and from the user, I can get all the sent and received messages. Unfortunately, It does not handle any situation: What if the receiver or the sender delete the message ? The message is unique so it disappear in both sides (bad thing). How to know if one of the side had already read the message ? Any suggestion ? Do you think I have to replan the model ? Tnx


this is a nice problem! I would model that to compare as closely as possible to the e-mail model. So a message always belongs to a single user, and it was either sent or received.

In short:

 create_table "messages", :force => true do |t|
    t.integer  :user_id
    t.string   :subject
    t.string   :body
    t.boolean  :sent
  end

And the model would like:

class Message < ActiveRecord::Base
  belongs_to :user

  scope :sent, where(:sent => true)
  scope :received, where(:sent => false)

end

And in the user:

class User    
  has_many :messages
end

You would then simply be able to query all sent messages by

user.messages.sent

and the received messages

user.messages.received

Sending a message does become a bit more complicated then:

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

or something along those lines: you copy the message and attach it to all recipients, and lastly make the original message the sent message.

This way each user has total control over the message.

Possible improvements:

  • also keep an explicit reference to the sender and receiver(s) in the message, to be able to allow replies and stuff
  • instead of working with a single boolean, maybe allow working with folders?

Hope this helps.


You can add two booleans to mark the message as deleted for both sender and receiver. Then after setting either of them check if the message can be deleted permanently.

Example:

create_table "messages", :force => true do |t|
  t.boolean :sender_deleted
  t.boolean :receiver_deleted
end

And in model:

class Message
  def self.delete_message(id)
    m = Message.find(id)
    m.destroy if m.sender_deleted && m.receiver_deleted
  end
end


You can nullify on a deleted record with :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

You'll need to handle when displaying the message that the sender/receiver of the message has been deleted, since the sender_id or destination_id will be null, but the message will stay intact.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜