Skip to content

Instantly share code, notes, and snippets.

@darinwilson
Created December 21, 2015 22:29
Show Gist options
  • Save darinwilson/2be79d764f6f4a84554d to your computer and use it in GitHub Desktop.
Save darinwilson/2be79d764f6f4a84554d to your computer and use it in GitHub Desktop.
Exercise using the NationBuilder People API endpoint
#
# This is very rudimentary web app that allows you to create, update, and
# delete a Person 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_people.rb
# * point your browser to http://localhost:4567/people
#
require "sinatra"
require "nationbuilder"
# This class wraps the NationBuilder API gem, exposing a Person-centric interface
class NBClient
class << self
def create_person(person_params)
execute_call do
client.call(:people, :create, { person: person_params })["person"]
end
end
def fetch_person(id)
execute_call do
client.call(:people, :show, id: id)["person"]
end
end
def update_person(person_params)
execute_call do
client.call(:people, :update, id: person_params["id"], person: person_params)["person"]
end
end
def delete_person(id)
execute_call do
client.call(:people, :destroy, id: id)
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
end
end
###################################
# Web app pages
# displays an empty form for creating a new Person
get "/people" do
html = <<-END_HTML
#{show_form(person: {})}
END_HTML
end
# uses the form data to create a Person in NationBuilder and display the results
post "/people/create" do
(result, error) = NBClient.create_person(params)
if error
show_form(person: result, error: error)
else
redirect to("/people/edit/#{result["id"]}?message=Created")
end
end
# displays the current Person record in an editable form
get "/people/edit/:id" do
(result, error) = NBClient.fetch_person(params[:id])
html = <<-END_HTML
#{show_form(person: result, error: error)}
END_HTML
end
# handles updating the Person record in NationBuilder
post "/people/update/:id" do
(result, error) = NBClient.update_person(request.params)
if error
show_form(person: result, error: error)
else
redirect to("/people/edit/#{result["id"]}?message=Updated")
end
end
# deletes the Person record in NationBuilder and displays a new empty form
post "/people/delete/:id" do
(result, error) = NBClient.delete_person(params[:id])
if error
redirect to("/people/edit/#{params[:id]}?message=#{error}")
else
redirect to("/people?message=Deleted")
end
end
private
# the main UI
def show_form(person: {}, error: "")
new_record = person["id"].nil?
method = new_record ? "/people/create" : "/people/update/#{person["id"]}"
form = <<-END_HTML
<form action="#{method}" method="post">
<p>#{params[:message]}</p>
<p>#{error}</p>
<table>
<tr>
<td>First name:</td>
<td><input type="text" name="first_name" value="#{person["first_name"]}"></td>
</tr>
<tr>
<td>Last name:</td>
<td><input type="text" name="last_name" value="#{person["last_name"]}"></td>
</tr>
<tr>
<td>Email:</td>
<td><input type="text" name="email" value="#{person["email"]}"></td>
</tr>
<tr>
<td>Phone:</td>
<td><input type="text" name="phone" value="#{person["phone"]}"></td>
</tr>
</table>
<input type="hidden" name="id" value="#{person["id"]}">
<input type="submit" value="#{new_record ? "Create" : "Update"}">
</form>
#{ new_record ? "" : show_delete_form(person["id"]) }
END_HTML
end
def show_delete_form(id)
form = <<-END_HTML
<form action="/people/delete/#{id}" method="post">
<input type="submit" value="Delete">
</form>
END_HTML
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment