The design varies depend on your requirements: for instance, can a message be addressed to multiple recipients? Can it have multiple senders? Can users rearrange messages into "folders" within their own inbox? Is "unread" state necessary?
In the most basic version, you want two models: a Message and a User. The message belongs_to an author (of class User) and also to a recipient (of class User). It has, presumably, a subject, body and created_at timestamp.
# app/models/message.rb
class Message < ActiveRecord::Base
belongs_to :author, :class_name => "User"
belongs_to :recipient, :class_name => "User"
end# app/models/user.rb
class User < ActiveRecord::Base
has_many :sent_messages, :class_name => "Message", :foreign_key => "author_id"
has_many :received_messages, :class_name => "Message", :foreign_key => "recipient_id"
# presumably this class would be more complex to handle authentication, etc.
end
# db/migrate/001_add_messages.rb
class AddMessages < ActiveRecord::Migration
def self.up
create_table "messages" do |t|
t.integer :author_id, :recipient_id
t.string :subject
t.text :body
t.timestamps!
end
end
def self.down
drop_table "messages"
end
end
# db/migrate/002_add_users.rb
class AddUsers < ActiveRecord::Migration
def self.up
create_table "users" do |t|
t.string :login
# (whatever else you need for authentication, etc)
end
end
def self.down
drop_table "users"
end
end
But you could certainly make it more complex. To implement all of the "bonus" features above, you'll need something considerably more complex. Something like this:
# app/models/message.rb
class Message < ActiveRecord::Base
belongs_to :author, :class_name => "User"
has_many :message_copies
has_many :recipients, :through => :message_copies
before_save :prepare_copies
attr_accessor :to # array of people to send to
attr_protected :author_id def prepare_copies
return if to.nil?
to.each do |recipient|
message_copies.build(:recipient_id => recipient, :folder_id => recipient.inbox)
end
end
end
# app/models/message_copy.rb
# represents an individual recipient's copy of a message
class MessageCopy < ActiveRecord::Base
belongs_to :message
belongs_to :recipient, :class_name => "User"
belongs_to :folder
delegate :author, :created_at, :subject, :body, :recipients, :to => :message
end
# app/models/user.rb
class User < ActiveRecord::Base
has_many :sent_messages, :class_name => "Message", :foreign_key => "author_id"
has_many :received_messages, :class_name => "MessageCopy", :foreign_key => "recipient_id"
has_many :folders
def inbox; folders.find_by_name("Inbox"); end
# presumably this class would be more complex to handle authentication, etc.
end
# app/models/folder.rb
class Folder < ActiveRecord::Base
acts_as_tree
belongs_to :user
has_many :messages, :class_name => "MessageCopy"
end
# db/migrate/001_add_messages.rb
class AddMessages < ActiveRecord::Migration
def self.up
create_table "messages" do |t|
t.integer :author_id
t.string :subject
t.text :body
t.timestamps!
end
end
def self.down
drop_table "messages"
end
end
# db/migrate/002_add_users.rb
class AddUsers < ActiveRecord::Migration
def self.up
create_table "users" do |t|
t.string :login
# (whatever else you need for authentication, etc)
end
end
def self.down
drop_table "users"
end
end
# db/migrate/003_add_message_copies.rb
class AddMessageCopies < ActiveRecord::Migration
def self.up
create_table "message_copies" do |t|
t.integer :recipient_id, :folder_id, :message_id
end
end
def self.down
drop_table "message_copies"
end
end
# db/migrate/004_add_message_copies.rb
class AddFolders < ActiveRecord::Migration
def self.up
create_table "folders" do |t|
t.integer :user_id, :parent_id
t.string :name
end
end
def self.down
drop_table "folders"
end
end
You could further extend this to allow To/Cc/Bcc, etc. It's more flexible than the first, but also more complex. It does, however, allow the usual pleasantries (deleting a message without deleting it for everyone else, for instance). I hope that gets you started.
P.S: This will allow you to create messages using mass-assignment, as I'm sure you're used to.
Last edited by manitoba98 (2008-02-22 12:32:14)