I have a Rails 3.2 application with a user model. I want to add a notification mechanism that can be triggered by the following use cases:
- Liking someone's profile
- Commenting on someone's profile
- Following someone
In all cases, one user generates a notification by his behavior that the other user will receive. So, there is a sender and a recipient of notifications.
I am now pondering how to structure my associations. So far, my models looks like the following:
Notification.rb
attr_accessible :content, :read_at, :recipient_id, :sender_id
belongs_to :sender, class: :user
belongs_to :recipient, class: :user
User.rb
has_many :notifications, as: :recipient, dependent: :destroy, foreign_key: :recipient_id
has_many :notifications, as: :sender, dependent: :destroy, foreign_key: :sender_id
This pseudocode shall only help understand what I need - what confuses me a lot is that I refer to the user model twice inside the notification model, and that a user has many notifications in two different ways.
So, my questions are:
- How would you adjust the above associations?
- What would you call them?
- How will I be able to call all sent notifications and all received notifications on a user model without having to write scopes?
- Is it the right approach at all, or should I use a join table somewhere two avoid referencing the user twice?
Thanks!
Solution
To put Shane's solution into words, this is what the models have to look like. It was really much easier than I thought. I assumed I would have to do some magic here - but Rails tricked me again with its stunning simplicity! Well, that's why I like it so much.
Thanks a lot, Shane!
Notification.rb
attr_accessible :content, :read_at, :recipient, :recipient_id, :sender, :sender_id
belongs_to :sender, class_name: "User"
belongs_to :recipient, class_name: "User"
User.rb
has_many :received_notifications, class_name: "Notification", foreign_key: "recipient_id", dependent: :destroy
has_many :sent_notifications, class_name: "Notification", foreign_key: "sender_id", dependent: :destroy