Reputation: 1934
I am trying to create a personal inbox message system but couple question are on my mind. First let me explain my system.
Here is my table model
create_table "inboxmessages", :force => true do |t|
t.integer "receiver_id"
t.integer "sender_id"
t.integer "message_id"
t.boolean "isread"
t.boolean "isstarred"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
create_table "messages", :force => true do |t|
t.string "subject"
t.text "body"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
The relationship would be has follow
inboxmessages
belongs_to :message
belongs_to :user, :class_name => "User", :foreign_key => "sender_id"
belongs_to :user, :class_name => "User", :foreign_key => "receiver_id"
messages
has_many :inboxmessages
user
has_many :inboxmessages
The problem that i am having his i am uncertain on how to create a message which allows me multiple users. here the schema of the form i am trying to have
Message.subject
Inboxmessage.receiver # but have multiple different user
------------------------------------------------------------------------
Message.body
Inboxmessage.sender = current_user # hidden field
Here are the question that I have regarding building this model/controller/app
1 - Should my new form be in inboxmessages or messages?
2 - Should I use accept_nested_for or should I use nested resources
3 - Is my model/database is okay or not the best?
4 - Are my foreign_key relationship well define?
Thanks in advance!!
Upvotes: 3
Views: 1761
Reputation: 35453
I would do something like this:
class User
has_many :mailboxes
has_many :messages, :through => :tags
has_many :tags
end
class Message
has_many :users, :through => :tags
has_many :mailboxes, :through => :tags
has_many :tags
end
class Mailbox
has_many :tags
has_many :messages, :through => :tags
has_many :users, :through => tags
end
class Tag
belongs_to :user
belongs_to :message
belongs_to :mailbox
# this class has "read?", "starred", etc.
end
This enables a message to appear in multiple mailboxes, for multiple users, and each user can have his/her own "read?", "starred", etc. You can limit the logic if you want to ensure that a user has only one copy of a message, i.e. the message is not in two or more mailboxes for the same user.
To improve your schema, read the Rails Guides, especially about associations like these:
Also look at the Rails gem acts-as-taggable-on
One way to think of a message schema is "a message belongs to a mailbox, and a mailbox has many messages" (this is how Yahoo does it). Another way to think of a message is "a message has many tags, and a mailbox is simply a search by tag" (this is how Gmail does it).
By the way, the Ruby mail gem is excellent. You can use it for creating messages, and look at how it converts headers like from, to, cc, etc.
You asked good questions:
1 - Should my new form be in inboxmessages or messages?
My opinion is that you will get the most benefit if you have a model for the message that is like an email, have a model for a mailbox (or tag). To create a new message, the new form would typically be in ./messages/new.html.erb
2 - Should I use accept_nested_for or should I use nested resources?
Nested resources are fine; see the Rails guide here:
http://guides.rubyonrails.org/routing.html#nested-resources
Nested attributes are also fine; see the API here:
A good rule of thumb is to only nest one level down, because after that it gets more complicated than its worth.
Not the best. A real-world message will typically have a sender and receiver(s). But you're modeling the sender and receiver in the inboxmessages table. Better to model the message with has_many receivers, and use a separate model for the user's interaction with the message for example a table called "marks" with fields "starred", "isread", etc. A mark belongs to a message and belongs to a user. A message has_many marks, and a user has_many marks.
In general, yes. Just be aware that email is surprisingly hard to model. A good rule of thumb is to index your foreign keys. Also look at Rails associations "inverse_of" and use it; this will help with speed and memory use.
Upvotes: 4
Reputation: 9170
I would have my classes set up something like this.
class Inbox
has_many :messages
belongs_to :user
end
class User
has_many :messages
has_one :inbox
end
class Message
belongs_to :user
belongs_to :inbox
has_many recipients, class_name: "User", foreign_key: "recipient_id"
end
Upvotes: 1