How to implement a simple notification system in Rails?
This is possible since Rails 5 and Action Cable. A good tutorial can be found here:
https://blog.heroku.com/real_time_rails_implementing_websockets_in_rails_5_with_action_cable
It involves creating a 'channel' which each user subscribes to, however it's far easier to run through a tutorial like the one above rather than have me explain step by step. The above is for creating a chat room, so you'd just swap the new message for a new notification.
notification system in application
You need to store a reference to the recipient in the notification.
t.integer :recipient_id
class Notification < ActiveRecord::Base
belongs_to :recipient, class_name: 'User'
end
Also don't set the user_id in the form, set it in the controller.
( Otherwise anybody could create a notification for anybody else, just by sending wrong input ).
class NotificationsController < ApplicationController
def create
@user = User.find(session[:user_id])
@notification = @user.notifications.new notification_params
# ...
end
end
Not a complete solution, but will point you to the right direction.
How to create notification system in rails?
I think you are on the right path.
A slightly better notifications#index
def index
@notifications = current_user.notications
@notifications.update_all checked: true
end
Notify this users
User.uniq.joins(:comments).where(comments: {id: @comment.post.comment_ids}).reject {|user| user == current_user }
Unique users that participated in the @comment's post comments, reject (remove from result) current_user.
- An observer as pointed out by João Daniel, it is preferred over an after_create. This "Rails best practice" describes it pretty well: http://rails-bestpractices.com/posts/2010/07/24/use-observer
Approach to a Notifications system with Rails 4
If you are open to using a gem, I would use the Public Activity gem for this. The architecture for Public Activity creates an activity record based on a recipient, an owner and a key, i.e owner: "User 1" key: commented on recipient: "User 2" post.
The benefit to this is that there is only one record in the database for the activity and you can present it any way you like through different views for each type of activity.
Public Activity allows you to render different partials based on the activity key and access any of the data of the action referenced in the database. You can even create different views for a newsfeed(activities that involve the users followed by the current user) and a notification feed (activities that directly involve the current user).
This allows your notification feed to remain flexible.
Further, if you combine it with the Unread gem and some javascript you can even mark read and unread notifications (for each particular user) just like Facebook. The only drawback is that the activities would appear only on refresh or visiting the page rather than constant polling like facebook does. There is an excellent tutorial on Public Activity here.
Notification System in Rails
There is a gem called Mailboxer which has similar functionalities.
Add notification to RoR messaging inbox system
I would recommend you to go through this tutorial to build nice notification system
https://www.devwalks.com/lets-build-instagram-part-6-notifications/
Basically, you have to create new model, set dependencies with your Message
model and integrate to the controller
For the email notifications, it's even simpler.
Just create new mailer and fire it on create action in messages_controller
def create
@message = @conversation.messages.new(message_params)
if @message.save
SendMessageMailer.new_message(@message).deliver_later
redirect_to conversation_messages_path(@conversation)
end
end
EDIT:
To create mailer, you should do something like this:
rails g mailer SendMessage
Go to /app/mailers/send_message_mailer.rb and add action, same type of building as controllers
def new_message(message)
@message = message
mail(to: @message.user.email, subject: 'Hey! Here is what you missed')
end
Also, create an view (email template) and code with erb code
app/views/send_message_mailer/new_message.html.erb
Im not going deep into this, I guess you can figure out how to pass interval (let's say don't send if user is online or have read the message) and differentiate with receiver/sender users
Mailer, once again, is just same type of controller. You can pass as many params as you need and use model nesting inside mailer controller and views
mailer
def new_message(message, sender, receiver)
end
controller
SendMessageMailer.new_message(@message, @message.user, params[:receiver]).deliver_later
Related Topics
What Purpose Can Anonymous Modules Serve
How to Use Coffeescript in the Views Executed on Render.Js
Vim Syntax Highlighting for Ruby 1.9
Robustly Call a Flaky API: Proper Error Handling with Net::Http
Text_Field_With_Auto_Complete Inside Form_For
Benefits of Using 'Hash#Fetch' Over 'Hash#[]'
Open a File Case-Insensitively in Ruby Under Linux
When Do You Need to Pass Arguments to 'Thread.New'
Celluloid Async Inside Ruby Blocks Does Not Work
How to Upload a Local File to a Carrierwave Model
How to Use Your Own MySQL Database Server with Heroku
Carrierwave Cannot Remove Image
How to Create a Dynamic Regular Expression in Ruby
Check If the Sum of Two Different Numbers in an Array Equal a Variable Number