Skip to content

Commit e693eb5

Browse files
committed
2 parents e7b0d02 + ea590a9 commit e693eb5

File tree

1 file changed

+278
-1
lines changed

1 file changed

+278
-1
lines changed

README.md

Lines changed: 278 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
# Rails-API-React-Tutorial 💻 [![Open Source Love](https://badges.frapsoft.com/os/v1/open-source.svg?v=103)](https://github.com/ellerbrock/open-source-badges/)
22

33
Hey! This is a super-easy to follow Rails/React API tutorial that is fully in depth from start to finish. This guide shows you how to install Ruby
4-
and Rails 5 in a Virtual Box, React JS via create-react-app and connecting the frontend and backend.
4+
and Rails 5 in a Virtual Box, React JS via create-react-app and connecting the frontend and backend.<br>
5+
6+
<p align="center">
7+
<img width="460" height="320" src="https://media.giphy.com/media/oZKuC9DJUK2yc/giphy.gif">
8+
</p>
59

610
## Table of Contents
711
* Downloading Virtual Box
@@ -150,3 +154,276 @@ class Application < Rails::Application
150154
```
151155

152156
Since this tutorial is mainly for testing and toy projects, we are allowing ALL methods from another domain. You should tailor the header and methods to your liking.
157+
158+
## Rails API Versioning
159+
160+
Versioning is the process of seperating and creating new features/data/endpoints for your API. Since this is our first API, let's make our ```test-api``` v1.
161+
162+
1. Run the following in your terminal
163+
```shell
164+
mkdir mkdir app/controllers/api && mkdir app/controllers/api/v1
165+
```
166+
If everything looks right you should see your directory identical as below. <br><br>
167+
<a href="http://tinypic.com?ref=3589c11" target="_blank"><img src="http://i67.tinypic.com/3589c11.png" height="280" width="280" border="0" alt="Image and video hosting by TinyPic"></a>
168+
169+
Now that our versioning is complete, let's test out a model and controller to work with our new url of ```localhost:3000/api/v1```.
170+
171+
2. Let's scaffold a test model/controller and call it ```movies```
172+
173+
```ruby
174+
rails g scaffold Movies name:string rating:integer
175+
176+
rails db:migrate
177+
```
178+
179+
The Rails engine creates your controller in the default ```/controllers``` directory but we need to move our new controller into the ```api/v1``` directory.
180+
181+
3. You can either move it manually or the following:
182+
183+
```shell
184+
mv app/controllers/movies_controller.rb app/controllers/api/v1
185+
```
186+
4. Update the Movies Controller
187+
188+
Our newly generated controller does not properly inherit from the namespace api/v1 (We will update the routes later in the tutorial) so let's change our controller class from
189+
190+
```ruby
191+
class MoviesController < ApplicationController
192+
```
193+
TO
194+
195+
```ruby
196+
class Api::V1::MoviesController < ApplicationController
197+
```
198+
199+
5. Update the Routes
200+
Locate to your config folder and open your ```routes.rb``` file.
201+
202+
```ruby
203+
Rails.application.routes.draw do
204+
resources :movies
205+
end
206+
```
207+
208+
If we go to ```localhost:3000/movies``` we will not call the controller. We must update our Routes to:
209+
```ruby
210+
Rails.application.routes.draw do
211+
namespace :api do
212+
namespace :v1 do
213+
resources :movies
214+
end
215+
end
216+
end
217+
```
218+
which allows us to call the json data from ``` localhost:3000/api/v1/movies```
219+
220+
221+
6. Let's seed our sqlite database with some classic movies so we can practice getting data with GET requests to the API.
222+
223+
Copy and paste the following data to your ```config/seeds.rb``` file.
224+
225+
```ruby
226+
Movie.create(name: "The Nightmare Before Christmas", rating: 5)
227+
Movie.create(name: "Titanic", rating: 5)
228+
Movie.create(name: "Venom", rating: 4)
229+
Movie.create(name: "A Quiet Place", rating: 5)
230+
Movie.create(name: "Nobody's Fool", rating: 2)
231+
Movie.create(name: "Suspiria", rating: 4)
232+
Movie.create(name: "Hereditary", rating: 4)
233+
Movie.create(name: "Office Space", rating: 5)
234+
Movie.create(name: "Elf", rating: 4)
235+
Movie.create(name: "Dawn of the Planet of the Apes", rating: 3)
236+
Movie.create(name: "Secret life of Pets", rating: 4)
237+
Movie.create(name: "Overlord", rating: 3)
238+
Movie.create(name: "Wonder Woman", rating: 5)
239+
Movie.create(name: "Bohemian Rhapsody", rating: 4)
240+
Movie.create(name: "Ocean's 8", rating: 5)
241+
```
242+
243+
Seed the DB using ``` rails db:seed && rails db:migrate ```
244+
245+
7. Test the API using a GET request.
246+
247+
Start your Rails server ```rails s``` and navigate to ```localhost:3000/api/v1/movies``` and if it is successful you should see the following JSON output: <br><br>
248+
249+
(Optional) I'm using a pretty JSON viewer for chrome which you can download [here.](https://chrome.google.com/webstore/detail/jsonview/chklaanhfefbnpoihckbnefhakgolnmc)
250+
<a href="http://tinypic.com?ref=2m60ahx" target="_blank"><img src="http://i63.tinypic.com/2m60ahx.png" width="450" height="450" border="0" alt="Image and video hosting by TinyPic"></a>
251+
252+
Congrats! You have successfully created a Rails API and completed your first GET request!
253+
254+
## Downloading React into our Project
255+
256+
React is a component based front end framework that makes it easy to make frontend calls to our Rails API. Let's make this organized as possible and add our react directory inside our rails app.
257+
258+
1. Open your terminal and create a new project inside your API.
259+
```
260+
create-react-app client
261+
```
262+
<br>
263+
<a href="http://tinypic.com?ref=1zya22t" target="_blank"><img src="http://i64.tinypic.com/358xiu0.png" border="0" height="300" width="280" alt="Image and video hosting by TinyPic"></a>
264+
<br>
265+
266+
2. Download Boostrap into the react directory:
267+
268+
```
269+
npm install --save reactstrap bootstrap@4
270+
```
271+
272+
Then open your ```index.js``` file inside the ```/src``` directory and add the following import line:
273+
```javascript
274+
import React from 'react';
275+
import ReactDOM from 'react-dom';
276+
import './index.css';
277+
import App from './App';
278+
import * as serviceWorker from './serviceWorker';
279+
// Import goes below for Bootstrap
280+
import 'bootstrap/dist/css/bootstrap.css';
281+
```
282+
283+
284+
3. Let's proxy our client so we know where to get the requests from!
285+
286+
Open ```package.json``` from our react folder and add the following json code to your package.
287+
288+
```javascript
289+
"proxy": "http://127.0.0.1:3000",
290+
```
291+
292+
Heres mine as an example!
293+
```javascript
294+
{
295+
"name": "client",
296+
"version": "0.1.0",
297+
"private": true,
298+
"proxy": "http://127.0.0.1:3000",
299+
"dependencies": {
300+
"bootstrap": "^4.1.3",
301+
"react": "^16.6.3",
302+
"react-dom": "^16.6.3",
303+
"react-scripts": "2.1.1",
304+
"reactstrap": "^6.5.0"
305+
},
306+
307+
```
308+
309+
4. We'll make a default Component directory inside the ```/src``` folder and create our first component.
310+
311+
```
312+
cd client/src && mkdir components && cd components && touch Button.js
313+
```
314+
5. Open your ```Button.js``` file and lets create a sample button to activate our call function to the API.
315+
316+
```javascript
317+
import React, { Component } from 'react';
318+
319+
class Button extends Component {
320+
render() {
321+
return (
322+
<div>
323+
<div class="card container mt-3">
324+
<div class="card-body">
325+
<div class="row">
326+
<center>
327+
<button class="btn btn-primary">Test Call!</button>
328+
</center>
329+
</div>
330+
</div>
331+
</div>
332+
</div>
333+
);
334+
}
335+
}
336+
337+
export default Button;
338+
339+
```
340+
341+
6. Start your server `npm start` and check if your bootstrap import works as well as the test button! If all is displaying then we are almost done. We are sooooo close!
342+
343+
We want our button to actually call the API now so lets create the function with the appropriate call. We want to add an onclick event to the button html like so:
344+
345+
```javascript
346+
<button class="btn btn-primary" onClick={this.callApi}>Test Call!</button>
347+
```
348+
349+
and our custom function PLUS the initial state set to null
350+
351+
```javascript
352+
353+
state = {
354+
355+
results: []
356+
}
357+
358+
callApi = async() => {
359+
360+
const api_call = await fetch('http://localhost:3000/api/v1/movies');
361+
362+
const data = await api_call.json();
363+
364+
this.setState({
365+
366+
results: data
367+
});
368+
369+
}
370+
371+
```
372+
373+
After copying and pasting both snippets inside the `Button.js` file, we fetch from the url `http://localhost:3000/api/v1/movies` in a json format and once we return a true response we will set the response to the data variable and console log the results into the browser.
374+
375+
This should be the complete Button.js file below!
376+
377+
```javascript
378+
import React, { Component } from 'react';
379+
380+
class Button extends Component {
381+
382+
state = {
383+
384+
results: []
385+
}
386+
387+
388+
callApi = async() => {
389+
390+
const api_call = await fetch('http://localhost:3000/api/v1/movies');
391+
392+
const data = await api_call.json();
393+
394+
this.setState({
395+
396+
results: data
397+
});
398+
}
399+
400+
401+
render() {
402+
403+
return (
404+
<div>
405+
<div className="card container mt-3">
406+
<div className="card-body">
407+
<div className="row">
408+
<center>
409+
<button className="btn btn-primary" onClick={this.callApi}>Test Call!</button><br />
410+
</center><br /><br /><br /><br /><br />
411+
<p className="m-5">{this.state.results.map((obj) => <li>{obj.name}</li>)}</p>
412+
</div>
413+
</div>
414+
</div>
415+
</div>
416+
);
417+
}
418+
}
419+
420+
export default Button;
421+
422+
423+
```
424+
425+
This should be everything we need to setup the API. Simply click our test api call button and see the magic work!
426+
427+
<a href="http://tinypic.com?ref=ere5n5" target="_blank"><img src="http://i68.tinypic.com/ere5n5.png" height="300" width="310" border="0" alt="Image and video hosting by TinyPic"></a>
428+
429+
### Congratulations! Our Rails API and React Client is done!

0 commit comments

Comments
 (0)