Add scheduled email feature for reminders
This commit is contained in:
parent
e4a317111c
commit
9ee37b42d8
40
README.md
40
README.md
@ -3,5 +3,43 @@
|
||||
## Project Setup
|
||||
|
||||
```sh
|
||||
rails new -T -d sqlite3 scheduled_reminders
|
||||
rails db:create db:migrate
|
||||
```
|
||||
|
||||
## Running the tests
|
||||
|
||||
```sh
|
||||
rspec
|
||||
```
|
||||
|
||||
## Running app
|
||||
|
||||
```sh
|
||||
rails s
|
||||
```
|
||||
|
||||
## System dependencies
|
||||
|
||||
- sendmail
|
||||
|
||||
## Task
|
||||
|
||||
> In order to get some insight into your coding style and approach to problem solving, we would like to give you a small programming task for you to solve. You can either upload the project to Github or send it to us via mail. It’s not supposed to win any beauty contest either, so it doesn’t really matter how the views look, as long as the functionality is there.
|
||||
>
|
||||
> Ideally you create an initial commit after the invocation of`rails new`, so it’s easy to blank out the skeleton code.
|
||||
>
|
||||
> Here it goes:
|
||||
> Sample Task: Scheduled Reminders
|
||||
> Description: write an application that sends scheduled reminders to its users.
|
||||
>
|
||||
> Functionality:
|
||||
> - a user can register with email and password
|
||||
> - after signing in, they see a list of existing reminders and can set up new ones
|
||||
> - once a month, on a configurable day and time, the application sends them an email with the reminder title and text
|
||||
> - existing reminders can be deleted from the list
|
||||
> Configuration of the reminder:
|
||||
> - title
|
||||
> - description / text
|
||||
> - day and time of month. Should be any possible day of the month. I.e. “1st of month”, “2nd of month”, but also “last of month”, “2nd last month”
|
||||
>
|
||||
> Ideally, tests should be in place, too. If you have any questions, feel free to ask.
|
||||
|
@ -19,6 +19,7 @@ class RemindersController < ApplicationController
|
||||
|
||||
if @reminder.save
|
||||
redirect_to @reminder, notice: 'Reminder was successfully created.'
|
||||
set_email_schedule
|
||||
else
|
||||
render :new
|
||||
end
|
||||
@ -27,6 +28,7 @@ class RemindersController < ApplicationController
|
||||
def update
|
||||
if @reminder.update(reminder_params)
|
||||
redirect_to @reminder, notice: 'Reminder was successfully updated.'
|
||||
set_email_schedule
|
||||
else
|
||||
render :edit
|
||||
end
|
||||
@ -48,4 +50,8 @@ class RemindersController < ApplicationController
|
||||
def reminder_params
|
||||
params.require(:reminder).permit(:title, :body, :date, :user_id)
|
||||
end
|
||||
|
||||
def set_email_schedule
|
||||
ReminderMailer.schedule_email(@reminder, current_user.email).deliver_later!(wait_until: @reminder.date)
|
||||
end
|
||||
end
|
||||
|
6
app/mailers/reminder_mailer.rb
Normal file
6
app/mailers/reminder_mailer.rb
Normal file
@ -0,0 +1,6 @@
|
||||
class ReminderMailer < ApplicationMailer
|
||||
def schedule_email(reminder, recipient)
|
||||
@reminder = reminder
|
||||
mail to: recipient, subject: 'Reminder'
|
||||
end
|
||||
end
|
@ -11,10 +11,12 @@
|
||||
|
||||
<body>
|
||||
<%= yield %>
|
||||
<p class="notice"><%= notice %></p>
|
||||
<p class="alert"><%= alert %></p>
|
||||
|
||||
<hr>
|
||||
<% if user_signed_in? %>
|
||||
<p><%= link_to('Logout', destroy_user_session_path) %></p>
|
||||
<p><%= link_to('Logout', destroy_user_session_path, method: 'delete') %></p>
|
||||
<% end %>
|
||||
</body>
|
||||
</html>
|
||||
|
2
app/views/reminder_mailer/schedule_email.html.erb
Normal file
2
app/views/reminder_mailer/schedule_email.html.erb
Normal file
@ -0,0 +1,2 @@
|
||||
<h1><%= @reminder.title %></h1>
|
||||
<p><%= @reminder.body %></p>
|
3
app/views/reminder_mailer/schedule_email.text.erb
Normal file
3
app/views/reminder_mailer/schedule_email.text.erb
Normal file
@ -0,0 +1,3 @@
|
||||
<%= @reminder.title %>
|
||||
|
||||
<%= @reminder.body %>
|
@ -32,10 +32,14 @@ Rails.application.configure do
|
||||
config.active_storage.service = :local
|
||||
|
||||
# Don't care if the mailer can't send.
|
||||
config.action_mailer.raise_delivery_errors = false
|
||||
config.action_mailer.raise_delivery_errors = true
|
||||
|
||||
config.action_mailer.perform_caching = false
|
||||
|
||||
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
|
||||
|
||||
config.action_mailer.delivery_method = :sendmail
|
||||
|
||||
# Print deprecation notices to the Rails logger.
|
||||
config.active_support.deprecation = :log
|
||||
|
||||
|
@ -40,6 +40,8 @@ Rails.application.configure do
|
||||
# ActionMailer::Base.deliveries array.
|
||||
config.action_mailer.delivery_method = :test
|
||||
|
||||
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
|
||||
|
||||
# Print deprecation notices to the stderr.
|
||||
config.active_support.deprecation = :stderr
|
||||
|
||||
|
13
spec/features/password_reset_spec.rb
Normal file
13
spec/features/password_reset_spec.rb
Normal file
@ -0,0 +1,13 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe "ResetPassword", type: :feature do
|
||||
it "sends an email upon a password reset request" do
|
||||
user = create(:user)
|
||||
visit new_user_session_path
|
||||
click_link 'password'
|
||||
fill_in 'Email', with: user.email
|
||||
click_button 'reset password'
|
||||
expect(page).to have_content 'You will receive an email with instructions on how to reset your password in a few minutes.'
|
||||
expect(last_email).to have_content user.email
|
||||
end
|
||||
end
|
7
spec/mailers/previews/reminder_mailer_preview.rb
Normal file
7
spec/mailers/previews/reminder_mailer_preview.rb
Normal file
@ -0,0 +1,7 @@
|
||||
# Preview all emails at http://localhost:3000/rails/mailers/reminder_mailer
|
||||
class ReminderMailerPreview < ActionMailer::Preview
|
||||
# Preview this email at http://localhost:3000/rails/mailers/reminder_mailer/schedule_email
|
||||
def schedule_email
|
||||
ReminderMailer.schedule_email(FactoryBot.build(:reminder), 'to@example.com')
|
||||
end
|
||||
end
|
29
spec/mailers/reminder_mailer_spec.rb
Normal file
29
spec/mailers/reminder_mailer_spec.rb
Normal file
@ -0,0 +1,29 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe ReminderMailer, type: :mailer do
|
||||
describe 'Email delivery' do
|
||||
let(:reminder) { build :reminder }
|
||||
let(:mail) { ReminderMailer.schedule_email reminder, 'to@example.org' }
|
||||
|
||||
it 'renders the headers' do
|
||||
expect(mail.subject).to eq 'Reminder'
|
||||
expect(mail.to).to eq ['to@example.org']
|
||||
expect(mail.from).to eq ['from@example.com']
|
||||
end
|
||||
|
||||
it 'renders the body' do
|
||||
expect(mail.body.encoded).to have_content reminder.title
|
||||
expect(mail.body.encoded).to have_content reminder.body
|
||||
end
|
||||
end
|
||||
|
||||
describe 'Scheduled email' do
|
||||
before { clear_enqueued_jobs }
|
||||
let(:reminder) { create :reminder }
|
||||
|
||||
it 'queues the reminder' do
|
||||
expect { ReminderMailer.schedule_email(reminder, 'to@example.org').deliver_later(wait_until: reminder.date) }.to have_enqueued_job.on_queue('mailers')
|
||||
expect { ReminderMailer.schedule_email(reminder, 'to@example.org').deliver_later(wait_until: reminder.date) }.to have_enqueued_job.at(reminder.date)
|
||||
end
|
||||
end
|
||||
end
|
@ -35,7 +35,7 @@ rescue ActiveRecord::PendingMigrationError => e
|
||||
end
|
||||
RSpec.configure do |config|
|
||||
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
|
||||
config.fixture_path = "#{::Rails.root}/spec/fixtures"
|
||||
# config.fixture_path = "#{::Rails.root}/spec/fixtures"
|
||||
|
||||
# If you're not using ActiveRecord, or you'd prefer not to run each of your
|
||||
# examples within a transaction, remove the following line or assign false
|
||||
@ -63,5 +63,7 @@ RSpec.configure do |config|
|
||||
# config.filter_gems_from_backtrace("gem name")
|
||||
|
||||
config.include FactoryBot::Syntax::Methods
|
||||
config.include(MailerMacros)
|
||||
config.before(:each) { reset_email }
|
||||
config.include Devise::Test::IntegrationHelpers, type: :request
|
||||
end
|
||||
|
9
spec/support/mailer_macros.rb
Normal file
9
spec/support/mailer_macros.rb
Normal file
@ -0,0 +1,9 @@
|
||||
module MailerMacros
|
||||
def last_email
|
||||
ActionMailer::Base.deliveries.last
|
||||
end
|
||||
|
||||
def reset_email
|
||||
ActionMailer::Base.deliveries = []
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue
Block a user