Skip to content

Commit

Permalink
Reminder email with direct cancel
Browse files Browse the repository at this point in the history
* User is now permitted to cancel RSVP's without authentication via link in email
* RSVP now has a cancelation token that is sent through the email
* Created a view that confirms whether the user wishes to cancel their RSVP event
  • Loading branch information
Mikhail Delos Trinos and Rae Bonfanti authored and tjgrathwell committed Aug 18, 2015
1 parent 00b158d commit d4920be
Show file tree
Hide file tree
Showing 9 changed files with 100 additions and 13 deletions.
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -427,4 +427,4 @@ DEPENDENCIES
webmock

BUNDLED WITH
1.10.5
1.10.6
23 changes: 20 additions & 3 deletions app/controllers/rsvps_controller.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
class RsvpsController < ApplicationController
before_filter :authenticate_user!
before_filter :authenticate_user!, except: [:quick_destroy_confirm, :destroy]
before_filter :assign_event
before_filter :load_rsvp, except: [:volunteer, :learn, :create]
before_filter :load_rsvp, only: [:edit, :update]
before_filter :redirect_if_rsvp_exists, only: [:volunteer, :learn]
before_filter :redirect_if_event_in_past
before_filter :redirect_if_event_closed, only: [:volunteer, :learn, :create]
Expand All @@ -20,6 +20,7 @@ def learn

def create
@rsvp = Rsvp.new(rsvp_params)
@rsvp.token = SecureRandom.uuid.gsub(/\-/, '')
@rsvp.event = @event
@rsvp.user = current_user
if Role.attendee_role_ids.include?(params[:rsvp][:role_id].to_i)
Expand Down Expand Up @@ -69,13 +70,26 @@ def update
end
end

def quick_destroy_confirm
@rsvp = Rsvp.find_by(token: params[:token])
unless @rsvp
redirect_to events_path, notice: 'You are not signed up for this event'
end
end

def destroy
@rsvp = Rsvp.find_by(token: params[:token]) if params[:token]

if @rsvp.nil?
authenticate_user! && load_rsvp
end

Rsvp.transaction do
@rsvp.destroy
WaitlistManager.new(@event.reload).reorder_waitlist!
end

if @event.organizer?(current_user)
if current_user && @event.organizer?(current_user)
redirect_to event_attendees_path(@event), notice: "#{@rsvp.user.first_name} is no longer signed up for #{@event.title}"
else
redirect_to events_path, notice: "You are now no longer signed up for #{@event.title}"
Expand Down Expand Up @@ -142,5 +156,8 @@ def redirect_if_event_in_past

def assign_event
@event = Event.find_by_id(params[:event_id])
if @event.nil?
redirect_to events_path, notice: 'You are not signed up for this event'
end
end
end
2 changes: 1 addition & 1 deletion app/views/rsvp_mailer/_event_details.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ You'll be <%= verb(@rsvp.role) %> <%= pluralize(@rsvp.rsvp_sessions.count, 'sess

<p>If any of your details (childcare, class preference, food needs) change, you can <%= link_to 'update your RSVP here', edit_event_rsvp_url(@rsvp.event, @rsvp.id) %>.</p>

<p>If your plans change and you can't make it to the workshop, be sure to <%= link_to "cancel your RSVP on the event page", event_url(@rsvp.event) %><% if @rsvp.role_student? %> so that someone from the waitlist can have your spot<% end %>.</p>
<p>If your plans change and you can't make it to the workshop, be sure to <%= link_to "cancel your RSVP", event_rsvp_quick_destroy_confirm_url(@rsvp.event, @rsvp, token: @rsvp.token) %><% if @rsvp.role_student? %> so that someone from the waitlist can have your spot<% end %>.</p>

<% if @rsvp.role_student? %>
<%= simple_format_with_html(@rsvp.event.student_details) %>
Expand Down
2 changes: 1 addition & 1 deletion app/views/rsvp_mailer/_event_details.txt.erb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ You're signed up to <%= verb(@rsvp.role) %> <%= pluralize(@rsvp.rsvp_sessions.co

If any of your details (childcare, class preference, food needs) change, you can <%= link_to 'update your RSVP here', edit_event_rsvp_path(@rsvp.event, @rsvp.id) %>.

If your plans change and you can't make it to the workshop, be sure to <%= link_to "cancel your RSVP on the event page", event_url(@rsvp.event) %><% if @rsvp.role_student? %> so that someone from the waitlist can have your spot<% end %>.
If your plans change and you can't make it to the workshop, be sure to <%= link_to "cancel your RSVP", event_rsvp_quick_destroy_confirm_url(@rsvp.event, @rsvp, token: @rsvp.token) } %><% if @rsvp.role_student? %> so that someone from the waitlist can have your spot<% end %>.

<% if @rsvp.role_student? %>
<%= @rsvp.event.student_details %>
Expand Down
12 changes: 12 additions & 0 deletions app/views/rsvps/quick_destroy_confirm.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<h1>
Are you sure you want to cancel?
</h1>

<ul class="actions no-margin">
<li>
<%= link_to 'Yes', event_rsvp_path(@event, @rsvp, token: @rsvp.token), class: 'btn btn-submit', method: :delete %>
</li>
<li>
<%= link_to 'No', root_path, class: 'btn' %>
</li>
</ul>
3 changes: 3 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,13 @@
end

resources :rsvps, except: [:show, :index, :new] do
get :quick_destroy_confirm

new do
get :volunteer
get :learn
end

resources :surveys, only: [:new, :create]
end

Expand Down
7 changes: 7 additions & 0 deletions db/migrate/20150726194812_add_token_to_rsvp.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class AddTokenToRsvp < ActiveRecord::Migration
def change
add_column :rsvps, :token, :string

add_index :rsvps, :token, unique: true
end
end
2 changes: 2 additions & 0 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -207,8 +207,10 @@
t.integer "section_id"
t.boolean "checkiner", default: false
t.text "plus_one_host"
t.string "token"
end

add_index "rsvps", ["token"], name: "index_rsvps_on_token", unique: true
add_index "rsvps", ["user_id", "event_id", "user_type"], name: "index_rsvps_on_user_id_and_event_id_and_event_type", unique: true

create_table "sections", force: :cascade do |t|
Expand Down
60 changes: 53 additions & 7 deletions spec/controllers/rsvps_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,22 @@ def extract_rsvp_params(rsvp)
@event = create(:event, title: 'The Best Railsbridge')
end

describe "#quick_destroy_confirm" do
def make_request
get :quick_destroy_confirm, event_id: @event.id, rsvp_id: rsvp.id, token: rsvp.token
end

let!(:rsvp) { create(:rsvp,
event: @event,
token: 'IamAtoken'
)}

it "assigns the rsvp" do
make_request
assigns(:rsvp).should == rsvp
end
end

describe "when signed in" do
before do
@user = create(:user)
Expand Down Expand Up @@ -188,7 +204,13 @@ def extract_rsvp_params(rsvp)
def do_request
post :create, event_id: @event.id, rsvp: @rsvp_params, user: { gender: "human" }
end


it "should generate a token for the RSVP" do
allow(SecureRandom).to receive(:uuid) { 'thisisatoken' }
do_request
expect(Rsvp.last.token).to eq 'thisisatoken'
end

it "should allow the user to newly volunteer for an event" do
expect { do_request }.to change { Rsvp.count }.by(1)
end
Expand Down Expand Up @@ -497,13 +519,10 @@ def do_request
end

describe "#destroy" do
before do
@user = create(:user)
sign_in @user
end

context "when an organizer deletes by id" do
before do
@user = create(:user)
sign_in @user
create(:organizer_rsvp, event: @event, user: @user)
@rsvp = create(:student_rsvp, event: @event, user: create(:user))
end
Expand All @@ -524,8 +543,30 @@ def do_request
flash[:notice].should match(/no longer signed up/i)
end
end


context "when not signed in and an RSVP token is available" do
before do
@user = create(:user)
end

let!(:rsvp) { create(:student_rsvp, event: @event, user: @user, token: 'iamatoken') }

def request_delete
delete :destroy, event_id: @event.id, id: rsvp.id, token: rsvp.token
end

it "should destroy the rsvp and reorder the waitlist" do
expect { request_delete }.to change { Rsvp.count }.by(-1)
expect { rsvp.reload }.to raise_error(ActiveRecord::RecordNotFound)
end
end

context "when a user has an existing rsvp" do
before do
@user = create(:user)
sign_in @user
end

it "should destroy the rsvp" do
@rsvp = create(:student_rsvp, event: @event, user: @user)

Expand Down Expand Up @@ -578,6 +619,11 @@ def do_request
end

context "when there is no RSVP for this user" do
before do
@user = create(:user)
sign_in @user
end

it "should notify the user s/he has not signed up to volunteer for the event" do
expect {
delete :destroy, event_id: 3298423, id: 29101
Expand Down

0 comments on commit d4920be

Please sign in to comment.