Implementing GET POST PUT DELETE with Ruby Sinatra
Run the App!
Let’s get down to the brass-ier tacks of building a client-server HTTP based programming !!
git clone [email protected]:jcdavison/fundamentals_of_web_programming.git
cd fundamentals_of_web_programming
cd spriggly-wiggly/
bundle install
bundle exec rerun 'ruby spriggly_wiggly_web_app.rb'
# woohoo !!
We are going to build a handful of features in a sequenced order :)
Snippets of code are located inside
/fundamentals_of_web_programming/spriggly-wiggly/building_blocks
Build Restaurant and Order object models
require 'data_mapper'
DataMapper.setup(:default, 'sqlite:spriggly-wiggly.db')
class Restaurant
include DataMapper::Resource
property :id, Serial
property :location, Text, required: true
property :name, Text, required: true
has n, :orders, :constraint => :destroy
end
class Order
include DataMapper::Resource
property :id, Serial
property :description, Text, required: true
property :restaurant_id, Integer, required: true
belongs_to :restaurant
end
DataMapper.finalize()
DataMapper.auto_upgrade!()
irb -r './spriggly_wiggly_web_app.rb'
Restaurant.new
Order.new
# create some new restaurants
# create some new orders with restaurant_ids that map to known restaurants
Implement /
# Enable the root server endpoint
get('/') do
restaurants = Restaurant.all
erb(:index, locals: { restaurants: restaurants })
end
<%# all restaurants %>
<% restaurants.each do |restaurant| %>
<div class='restaurant-display-tile'>
<p> Restaurant id: <%= restaurant.id %> '<%= restaurant.name %>' located at '<%= restaurant.location %>' </p>
<p>has <%= restaurant.orders.count %> order(s).</p>
</div>
<% end %>
Add some styles so that things look ‘better’ :)
/* assign a font and color to various html elements*/
p, h1, h2, h3, h4, ul, li, a {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
color: #157DA6;
text-align: center;
}
/* various css class definitions that allow for general styling */
.centered {
text-align: center;
}
.restaurant-display-tile {
border: 3px solid #75c196;
border-radius: 5px;
margin: 10px auto;
padding: 10px;
width: 50%;
}
.super-sport {
background-color: white;
border: 1px solid #157DA6;
border-radius: 5px;
cursor: pointer;
color: black;
font-size: 12px;
font-weight: normal;
text-decoration: none;
padding: 5px;
}
.inline {
display: inline;
}
.pull-right {
float: right;
}
.action-tile {
border: 3px solid #c14436;
border-radius: 5px;
margin: 10px auto;
padding: 10px;
width: 50%;
}
Implement POST /restaurants
# render the new restaurant form
get('/restaurants/create') do
erb(:create_restaurant)
end
<%# a form that can create a new restaurant%>
<form action='/restaurants' method='POST' class='centered'>
<label>name</label>
<input type='text' name='name' required/>
<label>location</label>
<input type='text' name='location' required/>
<input type='submit' value='create new restaurant' />
</form>
# create a new restaurant
post('/restaurants') do
new_restaurant = Restaurant.new
new_restaurant.name = params[:name]
new_restaurant.location = params[:location]
new_restaurant.save
redirect('/')
end
Implement PUT /restaurants
# render the restaurant of concern
get('/restaurants/:id/edit') do
restaurant = Restaurant.get(params[:id])
render(:edit_restaurant, locals: { restaurant: restaurant })
end
<%# a form that edits an existing restaurant %>
<form action='/restaurants/<%= restaurant.id %>' method='POST' class='centered'>
<label>name</label>
<input type='text' name='name' required value='<%= restaurant.name %>' />
<label>location</label>
<input type='text' name='location' value='<%= restaurant.location %>' required/>
<input type='hidden' name='_method' value='PUT'>
<input type='submit' value='edit restaurant' />
</form>
# update a restaurant
put('/restaurants/:id') do
restaurant = Restaurant.get(params[:id])
restaurant.name = params[:name]
restaurant.location = params[:location]
restaurant.save
redirect('/')
end
Implement DELETE /restaurants/:id
<%# a form that deletes an existing restaurant%>
<form action='/restaurants/<%= restaurant.id %>' method='POST' class='pull-right'>
<input type='hidden' name='_method' value='DELETE'/>
<button type='submit' class='super-sport'>X</button>
</form>
# delete restaurant
delete('/restaurants/:id') do
Restaurant.get(params[:id]).destroy
redirect('/')
end
Render a Restaurant’s Orders
<%# all orders for an individual restaurant %>
<% restaurant.orders.each do |order| %>
<h4>
Order id: <%= order.id %> is '<%= order.description %>'
</h4>
<% end %>
Implement POST /orders
# a form element to create a new order for a restaurant
<form action='/orders' method='POST' class='centered' >
<input type='text' name='description' required />
<input type='hidden' name='restaurant_id' value='<%= restaurant.id %>'>
<input type='submit' value='create order' class='super-sport'>
</form>
# create a new order
post('/orders') do
new_order = Order.new
new_order.description = params[:description]
new_order.restaurant_id = params[:restaurant_id]
new_order.save
redirect('/')
end
Implement PUT /orders
# render order to be edited
get('/orders/:id/edit') do
order = Order.get(params[:id])
erb(:edit_order, locals: { order: order })
end
<%# a link to visit a page that will render an update order form %>
<a href='/orders/<%= order.id %>/edit' class='super-sport'>edit order</a>
<%# a form to update an existing order %>
<form action='/orders/<%= order.id %>' method='POST' class='centered'>
<label>description</label>
<input type='text' name='description' required value='<%= order.description %>' />
<input type='hidden' name='_method' value='PUT'>
<input type='submit' value='edit order' />
</form>
# update an order
put('/orders/:id') do
order = Order.get(params[:id])
order.description = params[:description]
order.save
redirect('/')
end
Implement DELETE /orders/:id
<%# a form that allows an order to be destroyed %>
<form action='/orders' method='POST' class='inline' >
<input type='hidden' name='order_id' value='<%= order.id %>'>
<input type='hidden' name='_method' value='DELETE'>
<input type='submit' value='destroy order' class='super-sport'>
</form>
# delete order
delete('/orders') do
order_to_delete = Order.get(params[:order_id])
order_to_delete.destroy
redirect('/')
end