Created
May 11, 2015 23:02
-
-
Save dogweather/e63e2adc93caede15df2 to your computer and use it in GitHub Desktop.
An example of a "wizard" in Rails
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'types' | |
class RsvpController < ApplicationController | |
include Wicked::Wizard | |
steps :get_visitor_kind, :get_gender, :choose_events, :confirmation, :thank_you, :cancel_visit | |
before_filter :get_user, :except => :sign_in | |
def show | |
case step | |
when :get_visitor_kind | |
# Clear any chosen events in case the user is coming back here | |
# from the next steps. | |
@user.clear_itinerary | |
@user.restart_visit # In case this user had canceled in the past | |
@user.save(:validate => false) | |
when :get_gender | |
unless @user.should_have_gender? | |
skip_step | |
end | |
# Show the gender dialog. | |
# Give the user a default gender. | |
if @user.gender.nil? | |
@user.gender = 'female' | |
@user.save(:validate => false) | |
end | |
@header = 'Please indicate your gender' | |
when :choose_events | |
# Set up the calendar. | |
@events = make_event_list | |
@notices = make_notice_list | |
when :confirmation | |
# Show the itinerary chosen in the previous step. | |
# Present the form for biographical data. | |
# Get the user's approval. | |
@submit_label = session[:updating] ? 'Save Changes' : 'Sign me up' | |
@header = session[:updating] ? 'Change Your Reservation' : 'Confirm Your Visit' | |
@back_label = session[:updating] ? '<i class="icon-chevron-left"></i> Make Changes'.html_safe : back_button_label | |
when :cancel_visit | |
# Delete the visit, update the spreadsheets and send emails. | |
# Finally, the cancel_visit template shows a "sorry to see you | |
# go" message. | |
@visit_date = @user.visit_date | |
@user.cancel_visit | |
Resque.enqueue(VisitSystem::ExportUserJob, @user.id, @site.id) | |
UserMailer.cancellation_confirmation(@user, @site, @visit_date).deliver | |
when :thank_you | |
# Update the visible capacity numbers, export the data, send out | |
# emails, and show a thank you page. | |
@user.update_capacities_for_current_itinerary | |
@return_url = update_rsvp_url(@user.sign_in_token) | |
UserMailer.signup_confirmation(@user, @return_url, session[:updating] == true, @site).deliver | |
Resque.enqueue(VisitSystem::ExportUserJob, @user.id, @site.id) | |
when :finish | |
# The wizard will automatically redirect to the home page. | |
else | |
raise "Unexpected step in show: #{step}" | |
end | |
render_wizard | |
end | |
def update | |
case step | |
when :get_visitor_kind | |
# Returning from the visitor kind buttons. | |
set_visitor_kind | |
when :get_gender | |
set_gender | |
when :confirmation | |
update_user | |
else | |
raise "Unexpected step: #{step}" | |
end | |
end | |
def index | |
# Should never be used | |
redirect_to root_path | |
end | |
def itinerary_done_button | |
render :partial => 'itinerary_done_button' | |
end | |
# Handle token-based sign-ins. Try to find a user matching the | |
# token. Set up the session and redirect to the confirmation screen. | |
def sign_in | |
u = User.find_by_sign_in_token params[:token] | |
unless u.nil? | |
set_user(u) | |
session[:updating] = true | |
# Now, if this returning user has canceled, we show them a | |
# special page. Otherwise, send them back to the | |
# confirmation/biographical info form. | |
if u.canceled? | |
u.restart_visit | |
redirect_to root_path #For now, not too special. :-) TODO: Make special. | |
else | |
redirect_to wizard_path(:confirmation) | |
end | |
else | |
render :nothing => true, :status => :forbidden | |
end | |
end | |
private | |
def set_visitor_kind | |
visitor_kind_id = params.keys.select{|k| k.start_with? 'commit'}.first.sub('commit-','') | |
visitor_kind = VisitorKind.find visitor_kind_id | |
raise "Couldn't find the visitor kind with id #{visitor_id} in #{params.inspect}" if visitor_kind.nil? | |
@user.visitor_kind = visitor_kind | |
@user.highschool_grad_year = visitor_kind.hs_graduation_year | |
@user.college_enrollment_year = visitor_kind.college_enrollment_year | |
@user.college_enrollment_semester = 'Fall' | |
@user.save(:validate => false) | |
skip_step | |
render_wizard | |
end | |
def set_gender | |
@user.update_attributes(params[:user]) | |
g = params[:gender_options] | |
unless g == 'specify' | |
@user.gender = g | |
end | |
@user.save(:validate => false) | |
skip_step | |
render_wizard | |
end | |
def update_user | |
@user.update_attributes(params[:user]) | |
unless @user.should_have_gender? | |
g = params[:gender_options] | |
unless g == 'specify' | |
@user.gender = g | |
end | |
end | |
render_wizard @user | |
end | |
def make_one_kind_per_day(events) | |
event_hash = {} | |
for e in events | |
index = [e.start_date, e.event_kind.name] | |
event_hash[index] = e.event_kind | |
end | |
return event_hash.values.sort | |
end | |
def make_notice_list | |
starting = Time.zone.now.to_date | |
starting += 1.week unless admin? | |
ending = (starting + 6.months).end_of_month | |
notices = Notice.where(:display_on=>(starting..ending)) | |
return notices | |
end | |
def make_event_list | |
starting = Time.zone.now.beginning_of_day | |
starting += 1.week unless admin? | |
ending = (starting + 6.months).end_of_month | |
events = Event.for_user(@user).where(:starts_at=>(starting..ending)) | |
# Convert from a flat list of events to an array-hash | |
# of event kinds keyed by date | |
event_hash = ArrayHash.new | |
for e in events | |
event_hash[e.start_date] << e.event_kind | |
end | |
# Process each day's event kinds: sort, make unique, | |
# and communicate the name and css class. | |
for day in event_hash.keys | |
event_hash[day].uniq! | |
event_hash[day].sort! | |
event_hash[day].map!{|ek| {name: ek.name, css_class: css_class_for_event_kind(ek)}} | |
end | |
return event_hash | |
end | |
def css_class_for_event_kind(e) | |
return "event-kind-#{e.id % COLORS.length}" | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment