jQuery使ってこなかった自分がついにReact.jsに触れてみるまでの話

HelloWorld編

node.jsをインストール...する前にnvm(https://github.com/nvm-sh/nvm)というnode.jsのバージョン管理をするものをインストールする。

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.35.3/install.sh | bash

 

nvmでインストールできるnodeのバージョンを確認する

nvm ls-remote

 

nodeをインストール

nvm install v12.18.3

 

使うnodeのバージョンを選択

nvm use v12.18.3

 

npmでyarnをインストール

npm install -g yarn

 

一瞬にしてプロジェクトが作成できる

create-react-app(https://github.com/facebook/create-react-app)をインストール

yarn global add create-react-app

 

プロジェクト作成

やり方は3通りあってyarnが無くてもできる。詳しくは

https://github.com/facebook/create-react-app#creating-an-app

 

yarn create react-app helloworld

 

とりあえずsrcとpublic内のファイル全部消す

rm helloworld/src/*
rm helloworld/public/*

 

新規ファイル作成

cd helloworkd/src
touch index.js Hello.js
cd ../public
touch index.html

 

src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import Hello from './Hello';

ReactDOM.render(
  <div>
    <Hello />
  </div>,
  document.getElementById('root')
);

 

src/Hello.js

import React from 'react';

function Hello() {
  return (
    <p>Hello React</p>
  );
}

export default Hello;

 

public/index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>Reactアプリ</title>
  </head>
  <body>
    <div id="root"></div>
    <!--
      This HTML file is a template.
      If you open it directly in the browser, you will see an empty page.

      You can add webfonts, meta tags, or analytics to this file.
      The build step will place the bundled scripts into the <body> tag.

      To begin the development, run `npm start` or `yarn start`.
      To create a production bundle, use `npm run build` or `yarn build`.
    -->
  </body>
</html>

 

動かす

yarn run start

 

役割を果たす部品(コンポーネント)を作って組み合わせていく感じなのかな...?

 

GoでCRUD処理をする簡単なAPIを作った話

※注意

Ginというフレームワークを使います。

環境

WSL2 Ubuntu20.04LTS

mongoDB

go version go1.14.7 linux/amd64

 

ディレクトリ構成

recipes/

 controllers/controller.go

 models/models.go

 router/router.go

 main.go

 

コード

 main.go

package main

import (
	"recipes/router"
)

func main() {
	router.Router()
}

Router()という関数を呼び出すだけ。

 

router.go

package router

import(
	"time"

	"recipes/controllers"

	"github.com/gin-gonic/gin"
	"gopkg.in/mgo.v2"
)

func Router() {
	mongoInfo := &mgo.DialInfo{
		Addrs:    []string{"localhost:27017"},
		Timeout:  20 * time.Second,
		Database: "cook-suggestioner",
		Username: "",
		Password: "",
		Source: "cook-suggestioner",
	}
	
	session, err := mgo.DialWithInfo(mongoInfo)
	if err != nil {
		panic(err)
	}
	defer session.Close()
	db := session.DB("cook-suggestioner").C("recipes")

	r := gin.Default()
	recipesGroup := r.Group("/recipes")
	recipesGroup.Use(Middleware(db))
	{
		recipesGroup.GET("", controllers.GetAll)
		recipesGroup.GET("/:id", controllers.Get)
		recipesGroup.POST("", controllers.Create)
		recipesGroup.PUT("/:id", controllers.Update)
		recipesGroup.DELETE("/:id", controllers.Delete)
	}
	
	r.Run() // listen and serve on 0.0.0.0:8080
}

func Middleware(db *mgo.Collection) gin.HandlerFunc {
    return func(c *gin.Context) {
	c.Set("db", db)
        c.Next()
    }
}

DBのセッションを取得して各エンドポイントとハンドラを記述。

 

controllers.go

package controllers

import(
	"errors"
	"net/http"
	"strings"

	"recipes/models"

	"github.com/google/uuid"
	"github.com/gin-gonic/gin"
	"gopkg.in/mgo.v2"
)

func GetAll(c *gin.Context) {
	db := models.DbCollection{}
	db.DB = c.MustGet("db").(*mgo.Collection)
	var results []models.Recipe
	results, err := db.GetAll()
	if err != nil {
		c.AbortWithStatusJSON(http.StatusInternalServerError, err)
		return
	}
	c.JSON(http.StatusOK, results)
	return
}

func Create(c *gin.Context){
	db := models.DbCollection{}
	db.DB = c.MustGet("db").(*mgo.Collection)

	var request models.PostForm
	err := c.ShouldBindJSON(&request)
	if err != nil {
		c.AbortWithStatusJSON(http.StatusBadRequest, err)
		return
	}

	err = db.Create(request)
	if err != nil {
		c.AbortWithStatusJSON(http.StatusInternalServerError, err)
		return
	}
	c.JSON(http.StatusOK,"")
	return
}

func Get(c *gin.Context) {
	db := models.DbCollection{}
	db.DB = c.MustGet("db").(*mgo.Collection)
	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.AbortWithStatusJSON(http.StatusBadRequest, err)
		return
	}
	result, err := db.Get(id)
	if err != nil {
		if strings.Contains(err.Error(), "not found"){
			c.AbortWithStatusJSON(http.StatusNotFound, errors.New("Not found"))
			return
		}
		c.AbortWithStatusJSON(http.StatusInternalServerError, err)
		return
	}
	c.JSON(http.StatusOK, *result)
	return
}

func Update(c *gin.Context) {
	db := models.DbCollection{}
	db.DB = c.MustGet("db").(*mgo.Collection)

	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.AbortWithStatusJSON(http.StatusBadRequest, err)
		return
	}

	_, err = db.Get(id)
	if err != nil {
		if strings.Contains(err.Error(), "not found"){
			c.AbortWithStatusJSON(http.StatusNotFound, errors.New("Not found"))
			return
		}
		c.AbortWithStatusJSON(http.StatusInternalServerError, err)
		return
	}

	var request models.PostForm
	err = c.ShouldBindJSON(&request)
	if err != nil {
		c.AbortWithStatusJSON(http.StatusBadRequest, err)
		return
	}
	err = db.Update(id, request)
	if err != nil {
		c.AbortWithStatusJSON(http.StatusInternalServerError, err)
	}
	c.JSON(http.StatusOK, "") 
}

func Delete(c *gin.Context) {
	db := models.DbCollection{}
	db.DB = c.MustGet("db").(*mgo.Collection)

	id, err := uuid.Parse(c.Param("id"))
	if err != nil {
		c.AbortWithStatusJSON(http.StatusBadRequest, err)
		return
	}

	_, err = db.Get(id)
	if err != nil {
		if strings.Contains(err.Error(), "not found"){
			c.AbortWithStatusJSON(http.StatusNotFound, errors.New("Not found"))
			return
		}
		c.AbortWithStatusJSON(http.StatusInternalServerError, err)
		return
	}

	err = db.Delete(id)
	if err != nil {
		c.AbortWithStatusJSON(http.StatusInternalServerError, err)
	}
	c.JSON(http.StatusOK, "") 
}

エンドポイントにリクエストが来たら呼び出されるハンドラ達

 

model.go

package models

import(
	"github.com/google/uuid"
	"gopkg.in/mgo.v2"
	"gopkg.in/mgo.v2/bson"
)

type PostForm struct {
	Name string `json:"name" binding:"required"`
	Foods []string `json:"foods" binding:"required"`
}

type Recipe struct {
	Id	uuid.UUID	`json:"id" bson:"id"`
	Name  string `json:"name" bson:"name"`
	Foods []string `json:"foods" bson: "foods"`
}

type DbCollection struct{
	DB *mgo.Collection
}

func (db DbCollection) GetAll() ([]Recipe, error) {
	var results []Recipe
	err := db.DB.Find(bson.M{}).All(&results)
	if err != nil {
		return nil, err
	}
	return results, nil
}

func (db DbCollection) Create(request PostForm) error {
	var recipe Recipe
	recipe.Id = uuid.New()
	recipe.Name = request.Name
	recipe.Foods = request.Foods

	err := db.DB.Insert(&recipe)
	if err != nil {
		return err
	}
	return nil
}

func (db DbCollection) Get(id uuid.UUID) (*Recipe, error) {
	var result Recipe
	err := db.DB.Find(bson.M{"id": id}).One(&result)
	if err != nil {
		return nil, err
	}
	return &result, nil
}

func (db DbCollection) Update(id uuid.UUID, request PostForm) error {
	update := bson.M{"$set": bson.M{"name": request.Name, "foods": request.Foods}}
	err := db.DB.Update(bson.M{"id": id}, update)
	if err != nil {
		return err
	}
	return nil
}

func (db DbCollection) Delete(id uuid.UUID) error {
	err := db.DB.Remove(bson.M{"id": id})
	if err != nil {
		return err
	}
	return nil
}

ハンドラ内でDBとやり取りをする処理をここに記述

色々足りなさ過ぎて丸一日かかった...

WSL2でDockerを動かすまでの話

環境

ubuntu20.04LTS

 

とりあえずDockerをインストール

sudo apt install docker.io

 

sudoなしでDockerを使いたい人は以下のコマンドを実行 

sudo usermod -aG docker [ユーザ名]

 

素の状態だとsystemctlが使えないので色々設定する

まずはgenieというものを使うためのdotnet-runtime-3.1のインストール

ここに書いてあるコマンドを実行https://docs.microsoft.com/en-us/dotnet/core/install/linux-ubuntu

wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb
sudo dpkg -i packages-microsoft-prod.deb
sudo apt-get update; \
  sudo apt-get install -y apt-transport-https && \
  sudo apt-get update && \
  sudo apt-get install -y dotnet-sdk-3.1
sudo apt-get update; \
  sudo apt-get install -y apt-transport-https && \
  sudo apt-get update && \
  sudo apt-get install -y aspnetcore-runtime-3.1

sudo apt-get install -y dotnet-runtime-3.1

 

genieのインストール

ここに書いてあるコマンドを実行https://github.com/arkane-systems/genie

curl -s https://packagecloud.io/install/repositories/arkane-systems/wsl-translinux/script.deb.sh | sudo bash
sudo apt install -y systemd-genie

 

genie実行。

genie -s

 

動いた

docker version
Client:
 Version:           19.03.8
 API version:       1.40
 Go version:        go1.13.8
 Git commit:        afacb8b7f0
 Built:             Tue Jun 23 22:26:12 2020
 OS/Arch:           linux/amd64
 Experimental:      false

Server:
 Engine:
  Version:          19.03.8
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.13.8
  Git commit:       afacb8b7f0
  Built:            Thu Jun 18 08:26:54 2020
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.3.3-0ubuntu2
  GitCommit:        
 runc:
  Version:          spec: 1.0.1-dev
  GitCommit:        
 docker-init:
  Version:          0.18.0
  GitCommit:        

0からGo言語

環境

WSL2 ubuntu20.04LTS

 

Goのインストール

まずはGoのインストール...の前に

gvmというGoのバージョン管理をするものを以下のコマンドでインストール。

bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)

インストールできたら設定を反映

source ~/.gvm/scripts/gvm

gvmに必要なものをインストール

sudo apt-get install binutils bison gcc make

インストールできるGoのバージョン一覧を見る

gvm listall

バイナリーでGoをインストール

gvm install go1.14.7 -B

常にこのバージョンを使うように設定

gvm use go1.14.7 --default

Goのバージョンを確認

go version

 

Goのプロジェクトの作成

適当にディレクトリを作成して移動

mkdir test-project
cd test-project

go.modを作成。

go.modがあるとプロジェクト内で作成した独自のパッケージが参照できる。

また、ビルド時にインポートした外部のパッケージや依存パッケージを勝手にインストールしてくれる。

go mod init test-project

gitでコード管理する人はgitの新規リポジトリ作成とリモートリポジトリの登録

git init
git remote add origin [GithubリポジトリURL]

最近観たオタク向け?海外ドラマ

注意

小学生並みの感想を垂れ流します。

 

THE FLASH

The Flash | Netflix

事故がきっかけで主人公がめっちゃ速く動けるようになる超能力を授かる。

基本的に他の超能力者(メタヒューマン)と戦う。

1シーズンごとに強敵が変わっていく。

主人公がタイムトラベルをしてなんかグチャグチャになる。

 

プリズン・ブレイク

Prison Break | Netflix

主人公が切れ者で兄を救うためにわざと捕まって刑務所に入って脱獄をする。

ことごとく主人公が練った計画がうまくいかないのでハラハラした。

 

ウィッチャー

The Witcher | Netflix Official Site

ウィッチャーは危険な仕事を引き受けることが多いため短命であるが、

主人公はウィッチャーの中でも珍しく長生きをしているため白髪である。

美女の魔術師の過去を見るのはしんどかった~、結構えぐいので。

 

スーパーナチュラ

Supernatural | Netflix

母親が不可解な超常現象に殺されたので兄弟が幽霊を退治しまくる。

幽霊を退治していく過程で母親を殺した者の手がかりを見つけて物語が進行していく。

シーズン15まであるので覚悟の準備をしておいてください。

たびたび兄弟がゲイのカップルと間違えられる。

 

アンブレラアカデミー

The Umbrella Academy | Netflix Official Site

超能力を使う兄弟がわちゃわちゃして世界を救う話。

これもタイムトラベルする

NetflixとAmazonPrimeVideo、Hulu、Paraviの個人的な使用感

とりあえず値段を比較

Netflixベーシックコース:880円(税込)

PrimeVideo(Prime会員):500円(税込)

Hulu:1026円(税込)

Paravi:1017円(税込) 

 

Netflixの強いところ

海外ドラマのラインナップが充実している。

Netflix限定の面白い映画やドラマ、アニメがある。

 

Netflixの弱いところ

PrimeVideoと比べると値段が2倍近くある。

Netflixベーシックコースだと一度に1画面でしか見られない。

複数の画面で見たいときなどは注意。

若干アニメのラインナップが弱い?

 

PrimeVideo(Prime会員)の強いところ

とにかくコスパが良い。

Prime会員というだけでAmazonのあらゆるサービスが開放される。

PrimeReading、PrimeMusic、PrimeVideo、送料無料などなど。

 

PrimeVideoの弱いところ

ラインナップが弱い。

また、ラインナップの入れ替わりが激しいため。

前見れていた映画やアニメなどがPrime会員でも有料になってしまったりする。

 

Huluの強いところ

日本のドラマ以外ほぼなんでも観れる。

倍速で観れる。

 

Huluの弱いところ

値段

 

Paraviの強いところ

日本のドラマが観れる。

倍速で観れる。

 

Paraviの弱いところ

海外ドラマが見れない。

値段。

 

 

VRchatのアバターを作ろうとしてblenderの起動でこけてしまった話

blenderをインストールしたのはいいものの、

起動するとすぐに画面が閉じてしまって何もできない状態だった。

 

コマンドプロンプトblender.exeがいるディレクトリに移動して

blender.exeと打って実行してみたら以下のエラーが原因で起動に失敗していた。

GPUTexture: texture alloc failed. Likely not enough Video Memory.

ビデオメモリが不足している・・・? グラフィックの設定でちゃんとblender.exeの起動時に外付けのGPUを使う設定になっているはずなのに~!

使用しているGPUがローエンドのやつ(GT1030)だったからそれが原因かと思って普通にあきらめかけていたが、その後もいろいろ調べた。

なんとすごくあっさり解決した。 右が内蔵GPUで出力した画面、左が外付けGPUで出力した画面。

f:id:gyudonsenpai:20200623131327p:plain

左の画面を選んで、「これをメインディスプレイにする」にチェックを入れたら問題なく起動した。