Skip to content

Instantly share code, notes, and snippets.

@harrisonmalone
Last active September 5, 2021 14:30
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save harrisonmalone/85055ca89aad17d357913232828f2bd0 to your computer and use it in GitHub Desktop.
Save harrisonmalone/85055ca89aad17d357913232828f2bd0 to your computer and use it in GitHub Desktop.
code for simple sinatra web app that returns json

Lecture ✍️

What is Sinatra

  • Sinatra is a framework that is considered by the ruby community as baby rails
  • It's not really baby by any means; it's more like a stripped back version of rails
  • You have to create more of the code yourself, rails comes bundled with more features that allows you to start coding quicker
  • But it is kind of nice to know that you wrote every line of code in the app

What is a framework

  • A framework is something that allows a programmer to handle all the aspects of what it takes to build an API or a web app
  • It usually consists of both a frontend and a backend
  • The backend is the way in which data is passed around, anything to do with the database
  • The frontend is where we pass the data to; we then structure the data on a page with html and make it pretty with css 🌹
  • A framework will usually have some kind of server that spins up when we ask it too
  • A framework usually allows for a separation of concerns whereby everything is abstracted into separate files, one file has a single responsibility

Request, response and servers

  • This terminology is something we'll keep seeing over and over
  • What is a server??
  • HTTP verbs
  • Postman
  • Server side languages like Ruby (or Python, Java, JavaScript via NodeJS etc) allow us to build servers

What is the difference between an API and a web app 🤷‍♂️

  • An API is something that responds with data, this data is typically in JSON format these days but it can be in XML or plain text
  • A web app is still an API (in taking requests and responding to those requests) but differs in that it responds with HTML instead of just pure data

Tying all of this back to MVC

  • We're about to do a code along building a really simple API (in that it will only return JSON)
  • Think of what we're about to do as the C (controller) in MVC
  • Later on we'll come back to this project again and turn it into a really simple web app, some of our API end points will return HTML

How you build a server without a framework in ruby

  • This is the code that it takes to build a server in pure ruby
  • This is the code that it takes to build a server with a framework like sinatra

Code along

  • require
  • Sinatra methods, http request methods which take a block
  • Fake database (an array of hashes)
  • return a string
  • return json
  • params
  • Add a user (POST) using query string and request body
  • return all the users including the ones just added

Task challenge

  • Create a todo list API
  • The todo list should have a fake database (an array of task hashes), one task hash should have an id, a name, a date (as a string) and a done attribute (as a boolean)
  • You should be able to create (POST) a new task with the same attributes
  • You should be able to GET all the tasks
  • You should be able to get one task
  • You should be able to delete one task
  • Optional: you should be able to edit (patch) one task, instead of passing a hard coded id create a method that auto increments the id to be the next number (if the last hash has an id of 5 then make the new one 6)

erb 🌿

  • Now we're going to move on from returning just JSON
  • As I mentioned before you can create an API service that returns JSON (like our task manager) or a a web app that returns HTML
  • How does HTML interact with our ruby server in sinatra... the answer is embedded ruby (or erb)
  • This was my ah ha moment where I realized why we need to learn all of this ruby and how it ties into a web app
  • Let's take a look at an example using our users database

erb example

  • Our erb pages will be GET requests
  • Our erb has access to any @ instance variables we define in our request blocks
  • To render the HTML we say erb and then the name of the HTML page as a symbol (it's a weird syntax... 🤪)
  • Our HTML files are now <something>.erb not <something>.html

Hitting an external API to get data and then inserting it into my erb

  • I'm going to demo getting some data from somewhere else (the Strava API) and then once I have this data inserting it into my .erb
  • http gem

erb challenge

  • Using either the Pokemon API or the Star Wars API GET some interesting data (like Pokemon or Star Wars characters) using the http gem
  • Store this data in an @ instance variable and return it as JSON
  • Instead of returning the JSON return a .erb
  • In this .erb use the Pokemon or Star Wars data you have to create an interesting page
  • Style this page with CSS
require 'sinatra'
require 'sinatra/json'
# database
user_profiles = [
{
id: '1',
name: 'harrison'
}
]
# return a string
get '/' do
return 'hello world'
end
# return json
get '/myhash' do
hash = {
key: 'value'
}
return json(hash)
end
# params
get '/profile/:id' do
p params
return 'hello'
end
# add a user using query string
post '/adduser' do
name = params['name']
user = {
id: '2',
name: name
}
user_profiles << user
return json(user)
end
# add a user using request body
post '/adduser' do
data = JSON.parse(request.body.read)
p data.class
name = data['name']
user = {
id: '2',
name: name
}
user_profiles << user
return json(data)
end
# return all users, including one just added
get '/getusers' do
return json(user_profiles)
end
# get running data and pass it to erb
get '/running_stuff' do
get_running_data = HTTP.auth("Bearer TOKEN").get("https://www.strava.com/api/v3/athlete").to_s
@running = JSON.parse(get_running_data)
erb :users
end
# pass variables to erb
get '/profile_page' do
@user_profiles = user_profiles
erb :index
end
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>Hello</h1>
<% @user_profiles.each do |profile| %>
<p><%= profile[:id] %></p>
<p><%= profile[:name] %></p>
<% end %>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div class="container">
<div class="information-container">
<h3>Name: <%= @running["firstname"] %> <%= @running["lastname"] %></h3>
<h5>Country: <%= @running["country"] %></h5>
<% if @running["sex"] == "M" %>
<h5>Sex: Male</h5>
<% else %>
<h5>Sex: Female</h5>
<% end %>
<h5>City: <%= @running["city"] %></h5>
<img src="<%= @running["profile"] %>" alt="profile_image">
</div>
</div>
<%= @running %>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment