Rails App to schedule reminders & email notifications
Scheduled Reminder
DEVELOPER: Amruta Ashish Pednekar
Git Repository : https://github.com/amrutapednekar/ScheduledReminders
OVERVIEW & PURPOSE
Build a small, simple Ruby on Rails application that sends monthly scheduled reminders to usersOverall requirements
A user should be able to register with an email and password
After signing in, the user should see a list of their existing reminders
The user should be able to create a new reminder (see below for details)
Once a month, on a configurable day and time, the application should send the user an email with the reminder title and text
The user should be able to delete existing reminders
There should be basic tests in place for the core functionality (ideally in RSpec, but alternatives are fine if you're more comfortable with them)
A user should be able to register with an email and password
After signing in, the user should see a list of their existing reminders
The user should be able to create a new reminder (see below for details)
Once a month, on a configurable day and time, the application should send the user an email with the reminder title and text
The user should be able to delete existing reminders
There should be basic tests in place for the core functionality (ideally in RSpec, but alternatives are fine if you're more comfortable with them)
Reminder Configuration Requirements:
The user should be able to add a title (i.e. subject line)
The user should be able to add body text
The user should be able to select a time of day when the email will be sent
The user should be able to select a day of the month when the email should be sent, and it should be possible for them to set that date relative to either the beginning of the month or the end of the month. Use your best judgment for how to represent these options in the UI, but the important thing is for the user to be able to select any day of the month from either direction (e.g. 1st of the month, last day of the month, 15th of the month, third to last day of the month, etc.), and for this information to be saved in the database and used to trigger the reminder emails in a way that's flexible and maintainable.
Prerequisites
Ruby
Rails
PostgreSQL
Github
Ruby
Rails
PostgreSQL
Github
Ruby gems
The ruby gems listed below may change/add in development
gem 'pg' - Use postgresql as database for activerecord
gem 'bcrypt' - Use has_secure_password in authentication
gem 'whenever' - To schedule an monthly emails to user with reminder details
gem 'rspec' - Rspec
gem 'pg' - Use postgresql as database for activerecord
gem 'bcrypt' - Use has_secure_password in authentication
gem 'whenever' - To schedule an monthly emails to user with reminder details
gem 'rspec' - Rspec
Tasks
Create new rails app
Create a new rails application.
Database setup PostgreSQL
Create an initial commit
User registration
Database schema - Create table users
Model validations
Use has_many reminders
User should signup with email id and password
User should authenticate with email and password
Reminders
Database schema - Create table reminders
Model validations
Reminder belongs_to user
It should accept time of a day (:time)
It should accept a relative day of month
nth day of the month
Last day of the month
nth day before end of month
List user’s reminders
User should delete reminders
Rspec
Write Rspec for user authentication
Write Rspec for user signup.
Write Rspec for reminders.
Write Rspec for notifications.
Send email
An application should send an email to the user for his reminder.
Setup actionmailer
Write an email template with the remainder title and body.
Schedule an email
Requirement : Application should send an email once a month
Write a rake task to send an email
Automate “Send email” task
Install gem 'whenever'
Schedule a cron job
Database Schema
Steps to check for student understanding
Create Rails app
Create a new rails app and commit to github repository..
Create rails app
rails new ScheduledReminders
cd ScheduledReminders
Created new github repository named ScheduledReminders
git remote add origin https://github.com/amrutapednekar/ScheduledReminders.git
git add -A
git commit -m "Initial commit"
git push -u origin main
Setup PostgreSQL database
Edit Gemfile
Comment gem 'sqlite3' and add below code
# Use postgresql as the database for Active Record
gem 'pg', '~> 1.1'
Uncomment
gem 'bcrypt', '~> 3.1.7'
Edit Gemfile for PostgreSQL
Run command
Bundle install
rake db:create
rake db:migrate
rails s
Application is running on http://localhost:3000/
User authentication
Create user model, users controller and sessions controller
rails g model user email password_digest
Add has_secure_password in users model and model validations
rails g controller users new create
rails db:migrate
rails g controller sessions new create login welcome
Implemented user authentication.
Welcome page
User Signup
User login
User welcome page
Git commit
Validations
Validates uniqueness of email id
Validates presence of email id
Validates presence of password
Authenticates if email id and password matches
Redirects to login if authentication fails
Stores hashed version of password in database
Reminder Create Read Update Delete
User has many reminders
Generated scaffold for Reminder
rails generate scaffold Reminder title:string body:text user:references time:time start_date:date end_date:date day_of_month:integer day_before_eom:integer last_day_month:boolean
rails db:migrate
Implementation of reminder CRUD
Model validations
Create new reminder
List Reminders
Show Reminder
Edit reminder
User can delete reminders created by him
Git commit
https://github.com/amrutapednekar/ScheduledReminders/commit/dfe0052a35f306320e2d5d35c31cced7ff2fcb23
Validations
Validates presence of title
Validates presence of body
Validates presence of time
Validates presence of start date
Validates presence of end date
Validates numericality of day_of_month
Validates day_of_month is less than or equal to 25
Allows nil to day_of_month
Validates numericality of day before end of the month - day_before_eom
Validates day_before_eom is greater than or equal to 1 and less than or equal to 5
Allows nil to day_before_eom
Validates only one relative date is entered among below three
Day of month
Day before end of month
Last day of month
If not , it displays an appropriate error message.
Validates if the end date is greater than start date. If not, it displays an appropriate error message.
Add notifications on create/edit reminder
Reminder has many notifications
Generated scaffold for Reminder
rails g model notification date:date time:time reminder:references is_sent:boolean is_active:boolean
rails db:migrate
Implementation of adding records in notification table
On create of new reminder
On edit of existing reminder
It calculates all possible dates of reminder depending on start_date , end_date and relative day. Adds one record each for calculated dates.
If a user edits a reminder , it deletes old records from the notifications table for that reminder, calculates new reminder dates and adds new records.
On #create of Reminder
Calculates number of months
For every month , it calculates a date
Creates an entry in notification table date = calculated date
On #edit of Reminder
Deletes old notifications
Calculates number of months
For every month , it calculates a date
Creates an entry in notification table date = calculated date
On deleting reminder , it deletes all associated notifications
Git commit
https://github.com/amrutapednekar/ScheduledReminders/commit/509c078420e0f9e057088ec80364ecd62e16c9d5
Note
Notification table is created to separate out functionality of sending emails from main application
Column Is_active is created, if in case developer decides to unflag old notifications instead of hard delete
Send email for each notification
Create the Mailer
rails generate mailer Notification
Implementation of ActionMailer
Action Mailer Configuration for Gmail
Setup of Google account App password for Windows Mail
It's not my GMAIL account password. For Action Mailer we need to create new App password through Gmail account,
This app password is created for a short time and temporarily. You may need to create your own app password.
Run rake task in console
rake send_reminder_email:my_task
User gets email notification for reminder on selected date and time
Git commit
User model Rspec
Add below code in Gemfile under development ENV
#Rspec
gem 'rspec-rails', '~> 5.0.0'
Add below code in Gemfile under test ENV
gem 'shoulda-matchers'
gem install shoulda-matchers -v 5.1.0
This Gem version is specially require to check
it { should validate_numericality_of(:day_before_eom).is_greater_than_or_equal_to(1) }
Generated rspec for User
bundle install
rails generate rspec:install
rails db:migrate RAILS_ENV=test
rails generate rspec:model user
Add Below code in spec/rails_helper.rb
RSpec.configure do |config|
config.include(Shoulda::Matchers::ActiveModel, type: :model)
config.include(Shoulda::Matchers::ActiveRecord, type: :model)
End
bundle exec rspec spec/models
Git commit
Reminder model Rspec
Generated rspec for Reminder
rails generate rspec:model reminder
bundle exec rspec spec/models
Git commit
Schedule a rake task to send reminder email with whenever gem
Add whenever gem in GemFile
gem 'whenever', require: false
bundle instal
bundle exec wheneverize .
Add rake task in config/schedule.rb that will run once in every 5 minute
Git commit
https://github.com/amrutapednekar/ScheduledReminders/commit/b847f0f0aed1bb9af1791efee86fe83ca396e17d
Convert schedule file into cron syntax
bundle exec whenever
Set crontab
whenever --update-crontab
Set crontab
the whenever gem only runs on *nix systems (Linux, Mac OSX, BSD, ...) and not on windows.
Or schedule it through Task Scheduler if you are using Windows
Task scheduled in Windows
Rspec
Session is not accessible in spec/requests
To access session and check user authenticate before any action
user one has to write controller spec instead of requests spec
Tried to create spec/controller
rails g rspec:controller sessions
rails g rspec:controller users
gem 'rails-controller-testing’
bundle install
Rails 6 does not create any controller rspec. It creates by default requests rspec which doesn't allow you to set a session.
Tried same with test/controllers/sessions_controller_test.rb
It doesn't allow you to set a session.
Error : undefined method session' for nil:NilClass
To write controller and integration test case (both inside test and spec) need to set session
Git commit
Created README file
Invalid authentication error message
Invalid authentication error message
If user enters incorrect email id/ password on login
If users does not enter email id or password on login
Git commit
Notification is sent flag
After sending email notification set is_sent to true
Git commit
Reminders & Notifications Rspec
Created module to access session in test environment
Created separate route of session controller for test env
Reminder Rspec
Notifications Rspec
Run Rspec
bundle exec rspec spec
Comments
Post a Comment