title | type | duration | creator | competencies | ||||
---|---|---|---|---|---|---|---|---|
Rails API |
Lesson |
"1:25" |
|
Databases |
In Unit 3 we're gonna learn how to create and consume an API. As an intro, we're gonna see what this looks like using Rails since you should be intimately familar with the framework by now. This Rails app will have no views, however, we'll test our API using Insominia. Later, we'll use jQuery to access it and render data onto a page.
The original idea behind Rails API was to serve as a starting point for a version of Rails better suited for JS-heavy apps. As of today, Rails API provides: trimmed down controllers and middleware stack together with a matching set of generators, all specifically tailored for API type applications.
You can actually check this out by going to an index view of your Project 2 and typing .json
to the end of the URL. Note- this should work if you scaffolded your resources.
Objectives
- Create a Rails API to serve JSON data only (no views)
- Test our REST-ful endpoints using Insominia
- Consume our API using jQuery
Check out the Rails API Gem documentation.
-
Run
rails new my_api --api -d postgresql -T
to create a new API only Rails app. -
Add the following lines to
config/env/development.rb
# Add Rails 4.2 serverside rendered errors
config.debug_exception_response_format = :default
- Uncomment
rack-cors
in theGemfile
thenbundle install
:
rack-cors will help us with CORS request errors. Serialize will help us serve our data as a serialized JSON object.
-
To scaffold our Todo resource:
rails g scaffold todo title completed:boolean order:integer
-
Run
rails db:create db:migrate
-
Take a look at
controllers/todos_controller.rb
- What do you notice that's different from a regular scaffolded controller?
- Which actions are we missing? Why?
- Why do the actions only respond with JSON?
-
Next, check out
config/routes.rb
then runrake routes
. What is different and why?
Now that we've set up our database/model/controller let's seed our database using the seeds.rb file and a gem called Faker generates dummy data to test your app (https://github.com/stympy/faker#fakername).
- Add the
gem 'faker'
to the Gemfile around line 8 - Run
bundle install
- Add this to
db/seeds.rb
:
10.times do
Todo.create(
title: Faker::Hipster.sentence(2),
completed: Faker::Boolean.boolean(0.3),
order: Faker::Number.number(4)
)
end
- Run
rails db:seed
-
Fire up our
rails s
and gotohttp://localhost:3000/todos
. What is returned? -
Add the Chrome extension Insominia and open it. We're gonna use Insomnia to make HTTP requests and interact with our Rails server via the API we created. There will be a little bit of set-up involved the first time you open it. We will walk through it.
-
Let's make a
GET
request for all the todos. It's essentially the same URL to grab an index view, only we add.json
to the end of it.http://localhost:3000/todos
-
This should return an empty array because we have no todos in our database. How could we
POST
a newTodo
to our database?# send a POST request to this route http://localhost:3000/todos # Our Todo object, just like what we'd see in our params hash. { "todo": { "title": "Adding our First Todo!", "completed": false, "order": 20 } }
-
After step 4 we should see a
Success 201
message! Try theGET
request from step 3 again. You should now have oneTodo
in your array.
YOU DO
- Using Insomnia, add two more todos to the database
- Using Insomnia,
UPDATE
one of the todos - Using Insomnia,
DELETE
one of the todos - Add a
location
field to our Todo model and make it accessible to our API for all CRUD actions.
##Part 2 - Using Angular to access our DB
The beauty of hosting our database separately is that it is decoupled from the client. This gives us flexibility and options. We could create an Angular front-end, an Ionic mobile app, or a static html page and they can all access our API.
We're gonna dive into AngularJS in unit 4. However, we can accomplish some of the same behavior using jQuery. Let's see what that looks like by building a basic index.html
page that will consume our API.
-
In your
ga
folder, create a new folder calledrails_api_frontend_sample
. Create anindex.html
file and add the code below.
</script>
<ul ng-repeat="todo in ctrl.all">
<li>{{todo.title}}</li>
<li>{{todo.completed}}</li>
<li>{{todo.order}}</li>
</ul>
```
-
Create an
app.js
file for our Angular module:angular.module('Rails5App', []) .controller('todosController', todosController); todosController.$inject = ['$http']; function todosController($http){ var self = this; self.all = []; function getTodos(){ $http.get('http://localhost:3000/todos') .then(function(response){ console.log(response); self.all = response.data; }); } getTodos(); }
-
Start
http-server
. This is a basic HTTP server that you have installed on your Mac. It's a simple, lightweight option to serve static assets (HTML, CSS, JS). We need a server in order to make$http
requests. -
If you encounter any CORS errors or issues, add this Chrome extension called Allow-Control-Request-Origin and turn it on.
-
In
config/initializers/cors.rb
uncomment the following code and update theorigins
value:
Rails.application.config.middleware.insert_before 0, Rack::Cors do
allow do
origins '*'
resource '*',
headers: :any,
methods: [:get, :post, :put, :patch, :delete, :options, :head]
end
end
- Add forms and finish full CRUD for a todo in Angular hitting the Rails API backend.
- Create a Node/Express/Angular app to hit your Rails API backend.
Using the lesson above, see if you can access a movie from the Open Movie Database and render some data.
Using the lesson above, see if you can render Atlanta's current weather data from the Open Weather Map API. NOTE - You'll need to register for an API key.
Possible solution to Bonuses
<!DOCTYPE html>
<html>
<head>
<title>AJAX!</title>
</head>
<body>
<h1>AJAX!</h1>
<div id="todo"></div><br>
<div id="movie"></div><br>
<div id="weather"></div>
<script type="text/javascript" src='https://code.jquery.com/jquery-2.2.0.min.js'></script>
<script type="text/javascript">
$.getJSON('http://localhost:3000/todos.json', function(data){
$('#todo').text("Todo location: " + data.todos[1].location);
console.log(data);
});
$.getJSON('http://www.omdbapi.com/?t=batman&y=1989&plot=full&r=json', function(data){
$("#movie").html("<div>Title: " + data.Title + "</div><div>Release: " + data.Released + "</div>");
})
$.getJSON('http://api.openweathermap.org/data/2.5/weather?q=Atlanta&appid=< YOUR-API-KEY-HERE >', function(data){
$("#weather").text("Atlanta's current weather is: " + data.weather[0].description);
})
</script>
</body>
</html>