[Rails API x Docker] Construction facile de l'environnement avec contrôle de la coque et du fonctionnement avec Flutter

La procédure est soigneusement effectuée afin que même les débutants puissent continuer.

Choses à faire

スクリーンショット 2020-09-13 13.42.28.png

Ceux qui veulent voir uniquement le shell pour démarrer le conteneur API → [ici](https://qiita.com/drafts/942ad5fe5c13f70a19c5/edit#1-2-%E3%82%B7%E3%82%A7%E3%83%AB % E3% 81% A7railsapi% E3% 82% B3% E3% 83% B3% E3% 83% 86% E3% 83% 8A% E3% 83% 93% E3% 83% AB% E3% 83% 89) Pour le moment, Rails API source code et Flutter source code sont également disponibles (* déconner) Il y a une possibilité de

procédure

supposition

1. Jusqu'à ce que le conteneur Docker côté API soit démarré

Nous allons créer un conteneur Docker pour l'API Rails.

Cependant, il est inefficace de taper des commandes à partir de 1, les bases sont donc résumées dans le shell.

1-1. Création d'un répertoire

Préparez un répertoire en appliquant le nom du projet à app_name.

$ mkdir app_name  #Préparer un répertoire pour mettre les applications API
$ cd app_name

1-2. Conteneur de l'API Rails intégré à Shell

Vous trouverez ci-dessous le shell qui construit même le conteneur d'API. (Article de référence)

** Shell pour le lancement de l'exemple d'API **

set_up_rails.sh


#!/bin/bash

#config setting#############
APP_NAME="app_name"            #← N'hésitez pas à le changer (peut-être avec le nom du répertoire)
MYSQL_PASSWORD="password"      #← Veuillez changer librement
###########################

echo "docker pull ruby2.6.6"
docker pull ruby:2.6.6

echo "docker pull mysql:5.7"
docker pull mysql:5.7

echo "docker images"
docker images

echo "make Dockerfile"

cat <<EOF > Dockerfile
FROM ruby:2.6.6
ENV LANG C.UTF-8
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
#configuration du fil
RUN curl -o- -L https://yarnpkg.com/install.sh | bash
ENV PATH /root/.yarn/bin:/root/.config/yarn/global/node_modules/.bin:\$PATH
#Créer et définir un répertoire de travail
RUN mkdir /${APP_NAME}
ENV APP_ROOT /${APP_NAME}
WORKDIR \$APP_ROOT
#Ajouter Gemfile côté hôte (local)
ADD ./Gemfile \$APP_ROOT/Gemfile
ADD ./Gemfile.lock \$APP_ROOT/Gemfile.lock
#Installation du bundle Gemfile
RUN bundle install
ADD . \$APP_ROOT
#Parce qu'une erreur se produit lors de la désinstallation des rails 6 de la version gem
RUN gem uninstall yarn -aIx
#paramètres Webpacker
#RUN rails webpacker:install
EOF

echo "make Gemfile"
cat <<EOF > Gemfile
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
gem 'rails', '~> 6.0.3.2'
EOF

echo "make Gemfile.lock"
touch Gemfile.lock

echo "make docker-compose.yml"
cat <<EOF > docker-compose.yml
version: '3'
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_PASSWORD}
      MYSQL_DATABASE: root
    ports:
      - '3306:3306'
  api:
    build: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    volumes:
      - .:/${APP_NAME}
    ports:
      - '3000:3000'
    links:
      - db
EOF

echo "docker-compose run api rails new . --api --force --database=mysql --skip-bundle"
docker-compose run api rails new . --api --force --database=mysql --skip-bundle

echo "docker-compose run api bundle exec rails webpacker:install"
docker-compose run api bundle exec rails webpacker:install

docker-compose build

# fix config/database.yml
echo "fix config/database.yml"
cat config/database.yml | sed "s/password:$/password: ${MYSQL_PASSWORD}/" | sed "s/host: localhost/host: db/" > __tmpfile__
cat __tmpfile__ > config/database.yml
rm __tmpfile__

echo "docker-compose run api rails db:create"
docker-compose run api rails db:create

Créez un nouveau fichier directement sous le projet depuis l'éditeur & copiez et collez ↑ et enregistrez-le sous set_up_rails.sh etc. Veuillez éditer le app_name etc. qui dit" Veuillez changer librement ".

Après l'enregistrement, modifiez les autorisations du shell comme indiqué ci-dessous et exécutez-le (cela prend environ 5 minutes).

$ chmod 755 set_up_rails.sh  #Modifier les autorisations
$ ./set_up_rails.sh          #Exécuter le shell de configuration
docker pull ruby2.6.6
2.6.6: Pulling from library/ruby
57df1a1f1ad8: Pull complete
71e126169501: Pull complete
1af28a55c3f3: Pull complete
・
・
・

Après avoir exécuté le shell, vérifiez l'état du conteneur avec $ docker-compose ps. Il n'y a pas de problème si cela ressemble à ce qui suit.

$ docker-compose ps
     Name             Command       State       Ports
----------------------------------------------------------
app_name_db_1     docker-           Up      0.0.0.0:3306->
                  entrypoint.sh             3306/tcp,
                  mysqld                    33060/tcp

1-3. Démarrage et confirmation du conteneur

Ensuite, démarrez le conteneur construit dans le shell.

$ docker-compose up
rails-api-handson_db_1 is up-to-date
Creating rails-api-handson_api_1 ... done
Attaching to rails-api-handson_db_1, rails-api-handson_api_1
db_1   | 2020-09-12 08:27:00+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 5.7.31-1debian10 started.
・
・
・
api_1  | * Environment: development
api_1  | * Listening on tcp://0.0.0.0:3000
api_1  | Use Ctrl-C to stop    #← Si cela sort, c'est OK!

Il y aura beaucoup de journaux pour le conteneur Docker, mais si le dernier ** Utiliser Ctrl-C pour arrêter ** apparaît, le conteneur est en cours d'exécution et c'est OK.

Maintenant que nous avons confirmé que le conteneur a démarré, accédons à http: // localhost: 3000 et voyons s'il renvoie correctement une réponse en tant que Rails. Si cela ressemble à ce qui suit, le fonctionnement du conteneur API est correct.

スクリーンショット 2020-09-12 17.38.44.png

2. Implémentation de l'API Rails

Comme il s'agit de la vérification des opérations, utilisons des données utilisateur simples. Cette fois,

User ( id, name, email )

Je vais essayer de le mettre en œuvre avec des ressources comme.

2-1. Création du modèle utilisateur et préparation de la table de base de données

Préparez le modèle et la table utilisateur.

Seulement ici, je présenterai séparément ** Comment utiliser la migration ** et ** Comment utiliser Ridgepole ** (les deux refléteront le même modèle et schéma en conséquence).

Ridgepole est un outil qui vous permet de gérer votre schéma sans utiliser la migration. Je vais procéder ici, mais si vous êtes un utilisateur régulier de la migration, il n'y a pas de problème.

Modèle 1) Créer un modèle et une table par migration

Entrez dans le conteneur et créez un modèle utilisateur avec le générateur.

$ docker-compose exec api bash     #Entrez dans le conteneur
# rails g model user name:string email:string
#↑ Si vous ne pouvez pas, essayez-le via Bundle (# bundle exec rails)....Comme)
# exit                             #Sortie du conteneur (après cela, entrer et sortir du conteneur n'est pas spécifié.
                                   #Ligne de commande "$"Et" # "pour distinguer. )
$

Tout ce que vous avez à faire est de migrer.

# rake db:migrate

Motif 2) Créer un modèle et une table avec Ridgepole

Créez un modèle en ignorant la migration.

# rails g model user --skip-migration

Ajoutez gem'ridgepole ','> = 0.8.0' au Gemfile directement sous le projet. Il ne devrait y avoir aucun problème sous mysql2.

Gemfile


gem 'mysql2', '>= 0.4.4'     #À l'origine
gem 'ridgepole', '>= 0.8.0'  #Ajoute ça

Installez la gemme ajoutée.

# bundle install

Ensuite, créez un fichier appelé Schemafile.rb dans db / (Ridgepole gère le schéma de manière centralisée ici).

Écrivez ce qui suit dans db / Schemafile.rb et enregistrez-le.

db/Schemafile.rb


create_table "users", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
  t.string "name"
  t.string "email"
  t.timestamps
end

Reflétez le fichier de schéma avec la commande ridgepole.

# bundle exec ridgepole --config ./config/database.yml --file ./db/Schemafile.rb --apply
Apply `./db/Schemafile.rb`
-- create_table("users", {:options=>"ENGINE=InnoDB DEFAULT CHARSET=utf8"})
   -> 0.0716s

2-2. Création du contrôleur utilisateur

Reportez-vous à cet article et incluez la version principale de l'API (1 partie pour la v1.3) dans l'URI. Cependant, cet article utilise l'espace de noms api pour l'URI.

Ceci est mon opinion personnelle, mais je vais l'implémenter en supposant qu'il sera indiqué par un sous-domaine, etc. au lieu de spécifier api dans l'URI.

example.com/api/vi/users  #Afficher l'API dans l'URI
api.example.com/vi/users  #Montré par sous-domaine

Maintenant, revenons au sujet principal de la création de contrôleurs.

Avant le contrôleur, créez un v1 / indiquant la version principale, et créez-y un contrôleur d'utilisateurs.

$ mkdir app/controllers/v1
$ rails g controller v1::users

Le contenu du fichier du contrôleur est le suivant.

*/v1/users_controller.rb


class V1::UsersController < ApplicationController
  before_action :set_user, only: [:show, :update, :destroy]

  def index
    users = User.order(created_at: :desc)
    render json: { status: 'SUCCESS', message: 'Loaded user', data: users }
  end

  def show
    render json: { status: 'SUCCESS', message: 'Loaded the user', data: @user }
  end

  def create
    user = User.new(user_params)
    if user.save
      render json: { status: 'SUCCESS', data: user }
    else
      render json: { status: 'ERROR', data: user.errors }
    end
  end

  def destroy
    @user.destroy
    render json: { status: 'SUCCESS', message: 'Deleted the user', data: @user }
  end

  def update
    if @user.update(user_params)
      render json: { status: 'SUCCESS', message: 'Updated the user', data: @user }
    else
      render json: { status: 'SUCCESS', message: 'Not updated', data: @user.errors }
    end
  end

  private

  def set_user
    @user = User.find(params[:id])
  end

  def user_params
    params.require(:user).permit(:name, :email)
  end
end

2-3. Paramètres de routage

Créez config / routes.rb comme suit.

config/routes.rb


Rails.application.routes.draw do
  namespace 'v1' do
    resources :users
  end
end

Après ↑, vous devriez pouvoir vérifier le routage avec la commande rake routes. C'est OK si le routage suivant est reflété.

# rake routes
  Prefix Verb    URI Pattern               Controller#Action
v1_users GET     /v1/users(.:format)       v1/users#index
         POST    /v1/users(.:format)       v1/users#create
 v1_user GET     /v1/users/:id(.:format)   v1/users#show
         PATCH   /v1/users/:id(.:format)   v1/users#update
         PUT     /v1/users/:id(.:format)   v1/users#update
         DELETE  /v1/users/:id(.:format)   v1/users#destroy

3. Vérifiez le fonctionnement de l'API avec Postman

Postman est l'un des services client de test de l'API Web. Utilisez ceci pour vérifier le fonctionnement de l'API.

3-1. Installation du facteur

Installez Postman sur le site officiel (https://www.postman.com/). Je l'ai installé avant, donc je ne me souviens pas beaucoup, mais je pense que c'était OK si je me suis enregistré et que je continuais ...

Après avoir installé Postman, préparez d'abord un enregistrement utilisateur sur la console. Je pense que la sensation suivante est bonne.

# rails c
Loading development environment (Rails 6.0.3.3)
irb(main):001:0> User.create(name: "hoge", email: "[email protected]")

3-2. Obtenir la ressource utilisateur de la base de données avec GET

Dans Postman, spécifiez la méthode GET et URI comme indiqué ci-dessous, puis appuyez sur le bouton Envoyer.

Ensuite, vous pouvez vérifier le corps de la réponse renvoyée par le corps en bas de l'écran. Si vous pouvez le faire jusqu'à présent, c'est un succès de vérifier le fonctionnement de l'API!

スクリーンショット 2020-09-12 21.15.09.png

3-3. Ajouter une ressource utilisateur de base de données avec POST

Spécifions maintenant la méthode POST et incluons les données dans le corps de la requête comme indiqué ci-dessous. À ce stade, assurez-vous que le format est JSON (où" JSON "dans l'image est orange).

En cas de succès, vous pouvez vérifier l'enregistrement utilisateur enregistré dans le corps de la réponse.

スクリーンショット 2020-09-12 21.21.14.png

Si vous essayez à nouveau d'accéder avec la méthode GET, vous pouvez également voir l'enregistrement ajouté par la méthode POST.

スクリーンショット 2020-09-12 21.22.33.png

4. Frappez l'API avec Flutter

Le résultat ressemble à ceci

--Afficher les données utilisateur dans la base de données lors du lancement de l'application

Puisqu'il s'agit d'un contrôle de fonctionnement, cela semble être un minimum.

スクリーンショット 2020-09-12 23.28.18.png

4-1. Création de projet

Créez un projet Flutter à partir de ** Fichier> Nouveau> Nouveau projet Flutter ... **. C'est OK si le simulateur iPhone ou Android (émulateur) peut être démarré.

4-2. Activer la communication Http

Si c'est la valeur par défaut, une erreur se produira lors de l'importation d'un package qui exécute http, donc une petite opération est nécessaire.

Tout d'abord, ajoutez ce qui suit à dependencies: of pubspec.yaml.

pubspec.yaml


# ~réduction~
dependencies:
  http: ^0.12.0   #← Ajouter
  flutter:
    sdk: flutter
# ~réduction~

Ensuite, la commande Flutter suivante apparaîtra en haut de l'éditeur Android Studio. Cette fois, sélectionnez ** Pub get **.

Si vous obtenez une erreur autour de Http dans les travaux futurs, vous pouvez également consulter le cet article auquel j'ai fait référence. Je ne sais pas.

スクリーンショット 2020-09-12 22.35.18.png

4-3. Modifier main.dart

Si vous voulez juste vérifier l'opération, réécrivez lib / main.dart comme suit et cela fonctionnera.

De plus, puisque Flutter est une école élémentaire rudimentaire, veuillez commenter si vous avez des suggestions.

lib/main.dart


import 'dart:async';
import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  MyApp({Key key}) : super(key: key);

  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  Future<GetResults> res;
  @override
  void initState() {
    super.initState();
    res = getUsers();
  }

  // postUser()Enregistrez l'utilisateur avec. Récupérez à nouveau la liste des utilisateurs dans setState
  void _postUser() {
    postUser();
    setState(() {
      res = getUsers();
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Appeler l'API avec POST et transmettre les paramètres JSON',
      theme: ThemeData(
        primarySwatch: Colors.yellow,
      ),
      home: Scaffold(
        appBar: AppBar(
          title: Text('RailsAPI x Flutter'),
        ),
        body: Center(
          child: FutureBuilder<GetResults>(
            future: getUsers(),
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                return Text(
                    snapshot.data.message.toString()
                );
              } else if (snapshot.hasError) {
                return Text("${snapshot.error}");
              }
              return CircularProgressIndicator();
            },
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: _postUser,
          tooltip: 'Increment',
          child: Icon(Icons.add),
        ),
      ),
    );
  }
}

class GetResults {
  final String message;
  GetResults({
    this.message,
  });
  factory GetResults.fromJson(Map<String, dynamic> json) {
    var datas = '';
    json['data'].forEach((item) => datas += 'id: ' + item['id'].toString() + ', name: ' + item['name'] + ', email: ' + item['email'] + '\n');
    return GetResults(
      message: datas,
    );
  }
}

class PostResults {
  final String message;
  PostResults({
    this.message,
  });
  factory PostResults.fromJson(Map<String, dynamic> json) {
    return PostResults(
      message: json['message'],
    );
  }
}

class SampleRequest {
  final String name;
  final String email;
  SampleRequest({
    this.name,
    this.email,
  });
  Map<String, dynamic> toJson() => {
    'name': name,
    'email': email,
  };
}

Future<GetResults> getUsers() async {
  var url = 'http://127.0.0.1:3000/v1/users';
  final response = await http.get(url);
  if (response.statusCode == 200) {
    return GetResults.fromJson(json.decode(response.body));
  } else {
    throw Exception('Failed');
  }
}

Future<PostResults> postUser() async {
  var url = "http://127.0.0.1:3000/v1/users";                             //URI de l'API
  var request = new SampleRequest(name: 'foo', email: '[email protected]'); //Paramètres utilisateur. Vous pouvez le changer librement
  final response = await http.post(url,
      body: json.encode(request.toJson()),
      headers: {"Content-Type": "application/json"});
  if (response.statusCode == 200) {
    return PostResults.fromJson(json.decode(response.body));
  } else {
    throw Exception('Failed');
  }
}

Lorsque vous démarrez le simulateur, l'utilisateur enregistré est renvoyé correctement!

スクリーンショット 2020-09-12 21.30.54.png

Lorsque vous appuyez sur le bouton Ajouter en bas à droite, vous pouvez voir que les données utilisateur spécifiées dans main.dart ont été enregistrées et acquises!

スクリーンショット 2020-09-12 21.58.37.png

la fin

Si vous avez des questions ou des suggestions, veuillez laisser un commentaire.

Recommended Posts

[Rails API x Docker] Construction facile de l'environnement avec contrôle de la coque et du fonctionnement avec Flutter
[Docker] Construction de l'environnement Rails 5.2 avec docker
Environnement Build Rails (API) x MySQL x Nuxt.js avec Docker
[Construction de l'environnement avec Docker] Rails 6 et MySQL 8
Construction d'environnement de rails avec Docker (apocalypse personnelle)
Créer un environnement de vérification des opérations TensorFlow avec Docker
Procédure de construction de l'environnement Docker "Rails 6 x MySQL 8" à partager avec les équipes
Construction de l'environnement Rails Docker
Créez un environnement de développement d'applications Rails avec Docker [Docker, Rails, Puma, Nginx, MySQL]
Rails sur la procédure de construction de l'environnement Docker
Création d'un environnement de développement pour Ruby on Rails à l'aide de Docker + VSCode (Remote Container)
Construction de l'environnement GPU avec Docker [version d'octobre 2020]
Construction de Rails 6 et environnement PostgreSQL avec Docker
Construction de l'environnement de développement Laravel avec Docker (Mac)
Construire un environnement Rails 6 + MySQL avec Docker compose
[Docker] Construction de l'environnement de développement Rails6 / Ruby2.7 / MySQL8
Construire un environnement pour Laravel + MySQL + phpMyadmin avec Docker
Construction de l'environnement CentOS8.2 (x86_64) + ruby2.5 + Rails5.2 + MariaDB (10.3.17)
Comment créer un environnement Rails 6 avec Docker
Comment créer un environnement de développement Ruby on Rails avec Docker (Rails 6.x)
Créez une API de tableau d'affichage avec certification et autorisation avec Rails 6 # 1 Construction de l'environnement
Comment créer un environnement de développement Ruby on Rails avec Docker (Rails 5.x)
J'ai essayé de créer une application d'apprentissage automatique avec Dash (+ Docker) part1 ~ Construction de l'environnement et vérification du fonctionnement ~
Présentation de Rspec avec Ruby on Rails x Docker
[Rails] Comment créer un environnement avec Docker
Procédure de construction et de développement de l'environnement local Wordpress avec Docker
Facile à afficher Hello World avec Rails + Docker
Manuel de construction de l'environnement de développement stable pour "Rails6" avec "Docker-compose"
Créer un environnement de test E2E avec Docker x Cypress
Rails5 + MySQL8.0 + Construction d'environnement de volumes de premier niveau avec docker-compose
Création d'un environnement de base de données avec Docker dans Spring Boot (IntellJ)
[Flutter] Construction de l'environnement Ubuntu 20.04
Docker x Rails 6 (Mémo)
J'ai créé un environnement de développement avec rails6 + docker + postgreSQL + Materialise.
Créez un environnement pour Rails5 et postgresql avec Docker afin que pgadmin puisse également être utilisé
Construction de l'environnement de développement Rails6 [Mac]
Ingénieur Rails Environnement Construction Ruby2.7.1
Construction de l'environnement des rails Rails5.2.1 ruby2.5.1 Catalina
Mémo de construction de l'environnement MySQL 5.7 (Docker)
Exécuter des rails à chaque fois dans le docker
Mémo de construction de l'environnement Redmine (Docker)
Créer un environnement Docker avec WSL
Construction de l'environnement Docker × Spring Boot
[Super facile] Construction de l'environnement Ruby
[Rails / MySQL] Construction de l'environnement Mac