[Ruby] Rails & React & Webpacker & MySQL Environment Construction Manual

9 minute read

Suddenly, building an environment is as troublesome and weak as shaving every morning.
If you are reading this article, you may be not good at building an environment.

We often hear from members of the company that they are not as good at building an environment as a Yankee who hangs out at a convenience store.
I think this first hurdle to building an environment is hampering creative behavior!
I am confident that more services will be created in this world if we save the trouble of building an environment!
Therefore, this time, we will release an environment construction manual for creating a service that “uses Rails as an API server” and “draws with React”!

The target readers of this article are those who apply to all of the following:

――I’m using a Mac because it looks fashionable!
――Since I graduated from programming school, I want to make a personal app!
――I want to learn a modern Javascript framework called React.js and make a difference!
――I want to loosely couple the interaction between Rails and React by a method that does not use Gem such as react-rails!
–Docker? What is it delicious? (This article does not explain Docker)

0. Pre-install

name Description
Ruby I don’t know
Rails I don’t know
MySQL I don’t know
brew Package management (mainly server side)
yarn Package management (mainly front side)

1. Create a Rails app

rails new app name-–skip-turbolinks --webpack=react --database=mysql --api

It’s rumored that how many times in your life you hit this “rails new” command will determine your value as a Rails engineer.
By the way, you can rewrite the options if necessary.

2. Install Webpacker

Webpacker is a module bundler that comes standard with Rails and is a wrapper for Webpack.
A bundler is a person who bundles.
It is a guy that bundles files in various formats such as HTML, CSS, and JS.

By the way, a rapper is not a person who steps on the rhyme.
It’s a rapper like Saran Wrap. It means “wrap”.
Webpacker is a wrapper for Webpack because it calls Webpack internally.

By the way, if you are interested in the front end, you should have some knowledge of Webpack.
It’s GOOD if you remember it as a set with words like “Babel” and “ES6”!

rails webpacker:install
rails webpacker:install:react

3. Install MySQL

This time I will use MySQL for DB.
I use PostgreSQL for my daily work, but I think programming school graduates are used to MySQL.
I feel that many new product DB selections use the ones that are familiar to the site.
I’m sorry if it’s different.
By the way, as an aside of aside, I’m personally interested in NoSQL’s MongoDB.
The reason is, “It looks like a cool engineer if you know it somehow.”

This time I will install MySQL via a package manager called brew

brew install mysql

4. Create a MySQL user

After installing MySQL, create a user for use with this app.
I will omit each command because it seems that it is not necessary to explain it in detail.

-Log in to the root user

mysql -u root -p

・ User creation

Set your favorite user name and password

create user'username' @'localhost' identified by'password';

・ Confirmation of the created user

Success if the created user is displayed

select User,Host from mysql.user;

·Authorization

grant all on *. * To'[username]' @'localhost';

-Change settings in config / database.yml

After creating the user, link the created user with Rails.
The rule is to describe Rails DB settings in database.yml.

default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: <%= ENV['DATABASE_USERNAME'] %>
  password: <%= ENV['DATABASE_PASSWORD'] %>
  host: <%= ENV['DATABASE_HOST'] %>

development:
  <<: *default
  database: app_name_development

test:
  <<: *default
  database: app_name_test

production:
  <<: *default
  database: app_name_production
  username: <%= ENV['APP_NAME_DATABASE_USERNAME'] %>
  password: <%= ENV['APP_NAME_DATABASE_PASSWORD'] %>

Please replace “app_name_ ○○” with the app name when Rails new was done.
Since the username and password will be visible if you publish them on GitHub
It is recommended to hide it using gem “dotenv” etc.
By the way, it is meaningless unless you remove the “.env” file created by dotenv from Git management, so be sure to add “.env” to “.gitignore” once you have created it!
If you don’t know what you’re talking about, check out “dotenv environment variables”!
“Finding what you don’t understand” is the basis of an engineer!
I feel that how we can dig deeper into this “investigation” is a shortcut for growth.

5. Creating a database

rake db:create

6. Start Rails server

rails s

7. Check on the web

http://localhost:3000/

Success if “Yay! You’re on Rails!” Is displayed

Environment construction will continue a little longer.
It’s already about the 6th station. A little more.

8. Webpacker settings (optional)

・ Splitchunks

A Webpack plugin that automatically splits chunks.
You can save the file size, but you don’t have to.

Changes to config / webpack / environment.js
const { environment } = require('@rails/webpacker');
environment.splitChunks();
module.exports = environment;

app/views/top/show.html.erb
It means to refer to the file named “index” in javascript / packs /.

<%#When using split chunks%>
<%= javascript_packs_with_chunks_tag 'index' %>

<%#When not using split chunks%>
<%= javascript_pack_tag 'index' %>

Reference: splitchunks

9. Routing settings

config/routes.rb

Rails.application.routes.draw do
  #Root page settings
  root "top#show"
end

10. Creating an entry point

・ Creating a stove torah for the route page

app/controllers/top_controller.rb

class TopController < ApplicationController

  def show
  end

end

-Added id attribute for drawing with React

app/views/layouts/application.html.erb

<!DOCTYPE html>
<html>
  <head>
    <title>Application title</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <%= javascript_pack_tag 'application' %>
  </head>

  <body>
    <div id="root"> This is
      <%= yield %>
    </div>
  </body>
</html>

・ Create entry point for React

app/javascript/packs/index.jsx
File referenced from app / views / top / show.html.erb
This file is the entrance to React.
Asynchronous, routing, state management, etc., packages for React are imported and set.
You will install each package later.

//This file is the very first file called by Rails View (EntryPoint)
import React from 'react';
import { render } from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk'
import {
  Router,
  Route,
  Switch,
  IndexRoute,
  useLocation
} from 'react-router-dom';
import { createBrowserHistory } from 'history';
import { composeWithDevTools } from 'redux-devtools-extension';

// reducer
import rootReducer from '~/src/reducers/';

// Component
import Top from '~/src/components/tops/';

const middleWares = [thunk];
//For development environment, settings for using development tools
const enhancer = process.env.NODE_ENV === 'development' ?
  composeWithDevTools(applyMiddleware(...middleWares)) : applyMiddleware(...middleWares);
const store = createStore(rootReducer, enhancer);
const customHistory = createBrowserHistory();

render(
  <Provider store={store}>
    <Router history={customHistory}>
      <Route render={({ location }) => (
        <div>
          <Switch location={location}>
            <Route exact path='/' component={Top} />
          </Switch>
        </div>
      )}/>
    </Router>
  </Provider>,
  document.getElementById('root')
)

-Create React component

app/javascript/src/components/tops/index.jsx
Use a file with the extension jsx to describe the React component.
Write HTML in the JS file.
At first, I feel uncomfortable writing HTML tags in JS, but I get used to it.

import React from 'react';

const Top = () => (
  <h1>
    <center>Application title</center>
  </h1>
)
export default Top;

-Creating a process to put together React reducers

app/javascript/src/reducers/index.js

import { combineReducers } from 'redux';
import { reducer as formReducer } from 'redux-form';

import top from '~/src/modules/tops/';

export default combineReducers({
  form: formReducer,
  top,
});

The summary here is stored in the Redux store.
Redux is a package that centrally manages the state.
A store is a box that stores state. This is the most important feature of Redux.
The use of Redux is not essential for React development, but it is better to include it from the beginning because it becomes difficult to manage the state as the scale of the product increases with React alone.
It doesn’t have to be LP or a small product.

・ React module creation

The directory structure uses the ducks pattern.
The ducks pattern is the idea of describing “action type”, “action creator”, and “reducer” in one file. It’s a design concept. It’s not about installing something.

app/javascript/src/modules/tops/index.js

// action-type
const TOP_INITIAL = 'TOP_INITIAL';

// reducer
const initialState = {
  top: null,
}

export default function top(state = initialState, action) {
  switch (action.type) {
    case TOP_INITIAL:
      return {
        ...state,
      }
    default:
      return state
  }
}

// action-creator
export const topInitial = () => ({
  type: TOP_INITIAL,
});

Normally, files are created for each of “action type”, “action creator”, and “reducer”, but if you incorporate the ducks pattern, they will be combined into one file, so you can simply reduce the number of files.
It is recommended because it is a design concept that can withstand even medium-sized products at all.
If you’re wondering what an action type is, check out Redux Official!

11. Required package installation

Install using a package manager called yarn.
There is a similar package manager with “npm”, but “yarn” is upward compatible with “npm”.
The package installed by yarn is automatically added to the file “package.json” directly under the root directory.
Add a package with “yarn add package name”
Remove the package with “yarn remove package name”.

yarn add redux react-redux react-router-dom redux-devtools-extension redux-form redux-thunk axios @babel/preset-react babel-plugin-root-import

If you are interested, “@ reduxjs / toolkit”, “@ material-ui / core” Is also recommended

12. Creating a path specification configuration file (optional)

If you’ve ever developed React on your own, you should have thought this once.
“React relative path tends to be hell.”
React tends to fall into the relative path specification hell when importing.
It is recommended to include “babel-plugin-root-import” to prevent this from happening.
Actually, it is secretly included in “yarn add” in 11. above, so the person who copied and executed the command is already included by my strategy.

Create a file called “.babelrc” and describe the settings there.
The location to create the “.babelrc” file is directly under the root directory.

.babelrc

{
  "plugins": [
    [
      "babel-plugin-root-import",
      {
        "paths": [
          {
            "rootPathSuffix": "./app/javascript/src",
            "rootPathPrefix": "~/src/"
          },
        ]
      }
    ]
  ]
}

The above setting only sets the path specification “./app/javascript/src” so that it can also be specified with the character string “~ / src /”.
Now you can use “~ / src / ○○” when importing with React component, so you can get out of relative path hell.
By the way, the “” ~ / src / “” part can be set as you like with either “” ~ / “” or “” @ / src / “”.

13. Start webpack-dev-server

./bin/webpack-dev-server

It is a development server that automatically compiles.
We also monitor the code all the time, so if you rewrite the React code, it will automatically rewrite the drawing on the browser.
(By the way, Rails Model, Controller, View, etc. are not monitored, so even if you change them, they will not be drawn automatically. Let’s update the browser with “command + R” obediently.)

Thank you for your hard work

You should now have a Rails & React development environment …
If “Application title” is displayed in http: // localhost: 3000 /, it is successful!
Let’s have fun 3R (Ruby on Rails on React) development!

trouble shooting

An error occurred while installing mysql2 (0.5.3), and Bundler cannot continue.
Make sure that gem install mysql2 -v '0.5.3' --source 'https://rubygems.org/' succeeds before bundling.

If the above error message is displayed and bundle install fails ↓

In some cases it can be resolved with sudo xcodebuild -license accept