Created
December 21, 2015 22:31
-
-
Save darinwilson/2e407e31742c738312df to your computer and use it in GitHub Desktop.
Exercise using the NationBuilder Events API
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
# | |
# 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