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)

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

  1. Ruby

  2. Rails 

  3. PostgreSQL

  4. Github

Ruby gems

The ruby gems listed below may change/add  in development

  1. gem 'pg' - Use postgresql as database for activerecord

  2. gem 'bcrypt' - Use  has_secure_password in authentication

  3. gem 'whenever' - To schedule an monthly emails to user with reminder details 

  4. gem 'rspec' - Rspec

Tasks 

  1. Create new rails app

    1. Create a new rails application. 

    2. Database setup PostgreSQL

    3. Create an initial commit

  2. User registration

    1. Database schema - Create table users

    2. Model validations

    3. Use has_many reminders

    4. User should signup with email id and password

    5. User should authenticate with email and password

  3. Reminders

    1. Database schema - Create table reminders

    2. Model validations

    3. Reminder belongs_to user

    4. It should accept time of a day (:time)

    5. It should accept a relative day of month 

      1. nth day of the month

      2. Last day of the month

      3. nth  day before end of month

    6. List user’s reminders 

    7. User should delete reminders

  4. Rspec

    1. Write Rspec for user authentication 

    2. Write Rspec for user signup.

    3. Write Rspec for reminders.

    4. Write Rspec for notifications.

  5. Send email

    1. An application should send an email to the user for his reminder.

    2. Setup actionmailer

    3. Write an email template with the remainder title and body.

  6. Schedule an email

    1. Requirement : Application should send an email once a month

    2. Write a rake task to send an email

    3. Automate “Send email” task 

      1. Install  gem 'whenever'

      2. Schedule a cron job

Database Schema

Steps to check for student understanding

users

  • id

  • email

  • password_digest

  • created_at

  • updated_at

reminders

  • id

  • user_id

  • title

  • body

  • time

  • start_date

  • end_date

  • day_of_month

  • day_before_eom

-    last_day_month

  • created_at

  • updated_at

notifications

  • id

  • date

  • time

  • reminder_id

  • is_sent

  • is_active

  • created_at

  • updated_at

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


users

  • id

  • email

  • password_digest

  • created_at

  • updated_at


 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

reminders

  • id

  • user_id

  • title

  • body

  • time

  • start_date

  • end_date

  • day_of_month

  • day_before_eom

-    last_day_month

  • created_at

  • updated_at


  • Implementation of reminder CRUD

  • Model validations

  • Create new reminder

  • List Reminders

  • Show Reminder

  • Edit reminder

  • User can delete reminders created by him

  • Git commit

  • 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


notifications

  • id

  • date

  • time

  • reminder_id

  • is_sent

  • is_active

  • created_at

  • updated_at


  • 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

  • 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

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 

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

  • 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

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

Notification is sent flag

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

Popular posts from this blog

PERSONAL ACCESS TOKEN ON GITHUB

PostgreSQL Commands

Rails Application with Docker