Skip to content

Instantly share code, notes, and snippets.

@darinwilson
Created December 21, 2015 22:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save darinwilson/2e407e31742c738312df to your computer and use it in GitHub Desktop.
Save darinwilson/2e407e31742c738312df to your computer and use it in GitHub Desktop.
Exercise using the NationBuilder Events API
#
# This is very rudimentary web app that allows you to create and update
# an Event record using the NationBuilder API. This covers just the
# basics - many details have been left out.
#
# The app was built in Ruby 2.2.0, using the Sinatra web framework, and the
# NationBuilder API Ruby gem.
#
# To run the app:
# * gem install sinatra
# * gem install nationbuilder-rb
# * set environment variables NB_SLUG and NB_API_KEY to your NationBuilder slug and
# API key respectively
# * ruby nation_builder_events.rb
# * point your browser to http://localhost:4567/people
#
require "sinatra"
require "nationbuilder"
# This class wraps the NationBuilder API gem, exposing an Event-centric interface
class NBClient
class << self
def create_event(event_params)
format_datetimes!(event_params)
execute_call do
client.call(:events, :create, site_slug: ENV["NB_SLUG"], event: event_params)["event"]
end
end
def fetch_event(id)
event = {}
execute_call do
event = client.call(:events, :show, site_slug: ENV["NB_SLUG"], id: id)["event"]
end
event.tap { format_datetimes!(event) }
end
def update_event(event_params)
format_datetimes!(event_params)
execute_call do
client.call(:events, :update, site_slug: ENV["NB_SLUG"], id: event_params["id"],
event: event_params)["event"]
end
end
private
def client
@client ||= NationBuilder::Client.new(ENV["NB_SLUG"], ENV["NB_API_KEY"], retries: 8)
end
def execute_call
result = {}
error = nil
begin
result = yield
rescue Exception => e
error = e.to_s
end
[result, error]
end
# convert date/time strings to and from form inputs; using UTC for the sake of brevity
def format_datetimes!(event)
if event.has_key?("start")
event["start_time"] = format_datetime(event["date"], event["start"])
event["end_time"] = format_datetime(event["date"], event["end"])
elsif event.has_key?("start_time")
start_time = DateTime.parse(event["start_time"]).to_time.utc()
end_time = DateTime.parse(event["end_time"]).to_time.utc()
event["date"] = start_time.strftime("%m/%d/%Y")
event["start"] = start_time.strftime("%H:%M")
event["end"] = end_time.strftime("%H:%M")
end
end
# again, for the sake of brevity, we're just assuming the input is clean; normally,
# you'd want to do a lot more sanity checking here
def format_datetime(date_str, time_str)
(month,date,year) = date_str.split("/")
(hour, minute) = time_str.split(":")
Time.new(year, month, date, hour, minute, 0, 0).strftime("%FT%T%:z")
end
end
end
###################################
# Web app pages
# displays an empty form for creating an Event
get "/events" do
html = <<-END_HTML
#{show_form(event: {})}
END_HTML
end
# uses the form data to create an Event in NationBuilder and display the results
post "/events/create" do
(result, error) = NBClient.create_event(params)
if error
show_form(event: result, error: error)
else
redirect to("/events/edit/#{result["id"]}?message=Created")
end
end
# displays the current Event record in an editable form
get "/events/edit/:id" do
(result, error) = NBClient.fetch_event(params[:id])
html = <<-END_HTML
#{show_form(event: result, error: error)}
END_HTML
end
# handles updating the Event record in NationBuilder
post "/events/update/:id" do
(result, error) = NBClient.update_event(request.params)
if error
show_form(event: result, error: error)
else
redirect to("/events/edit/#{result["id"]}?message=Updated")
end
end
private
# the main UI
def show_form(event: {}, error: "")
new_record = event["id"].nil?
method = new_record ? "/events/create" : "/events/update/#{event["id"]}"
form = <<-END_HTML
<form action="#{method}" method="post">
<p>#{params[:message]}</p>
<p>#{error}</p>
<table>
<tr>
<td>Event name:</td>
<td><input type="text" name="name" value="#{event["name"]}"></td>
</tr>
<tr>
<td>Headline:</td>
<td><input type="text" name="headline" value="#{event["headline"]}"></td>
</tr>
<tr>
<td>Date (mm/dd/yyyy):</td>
<td><input type="text" name="date" value="#{event["date"]}"></td>
</tr>
<tr>
<td>Start time (hh:mm):</td>
<td><input type="text" name="start" value="#{event["start"]}"></td>
</tr>
<tr>
<td>End time (hh:mm):</td>
<td><input type="text" name="end" value="#{event["end"]}"></td>
</tr>
<tr>
<td>Status:</td>
<td>
<select name="status">
#{status_options(event)}
</select>
</td>
</tr>
</table>
<input type="hidden" name="id" value="#{event["id"]}">
<input type="submit" value="#{new_record ? "Create" : "Update"}">
</form>
END_HTML
end
def status_options(event)
["published", "unlisted", "hidden"].map do |status|
"<option #{event["status"] == status ? "selected" : ""}>#{status}</option>"
end.join("\n")
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment