OmniAICreator/Qiita-1.07M huggingface dataset:
Fastlaneを使って、Firebase App Distributionを自動化する

Fabric終了に伴い、Firebase App Distributionを用いてアプリを配布しているプロジェクトは数多くあると思います。
手動で配布することもできるのですが、その場合、
1. ipaファイル作成
2. Firebaseコンソールに移動
3. ファイルのアップロード
4. テスターの指定
などと毎回同じ作業をするのは面倒です。

そこで個人プロジェクトでこちらの作業をfastlaneコマンド一発でできるようにしたので、その時の手順を記します。

今回解説するのは
- fastlaneのセットアップ
- fastlaneによるipa作成、アップロード方法
です。

# Installing fastlane

まずはHomebrew経由でfastlaneをインストール

```
brew install fastlane
```

プロジェクトのルートディレクトリで下記コマンドを実行。
fastfileが作成され、こちらに後ほど配布するためのコードを記述します。

```
fastlane init
```

プラグインを追加

```
fastlane add_plugin firebase_app_distribution
```

# ローカルマシンでFirebaseにログインできるようにする

[ドキュメント](https://firebase.google.com/docs/cli?hl=ja#install-cli-mac-linux)に従います

Firebase CLIをダウンロード


```
curl -sL https://firebase.tools | bash
```

以下コマンドで確認

```
firebase login
```

# firebase-toolsのインストール

まずはNode.jsをダウンロードします。
https://nodejs.org/ja/download/

プロジェクトのルートディレクトリで以下コマンドを入力。package.jsonが作成されます。

```
npm init
```

これでfirebase-toolsをインストールすることができます。

```
npm install firebase-tools
```

以下のパスはgitignoreに追記。

```
node_modules/
```

# fastfileへの記述

```
platform :ios do
  desc "deploy DEV on Firebase App Distribution"
  lane :distribution do
    # .ipaファイルの作成
    gym(
      workspace: "hoge.xcworkspace",
      scheme: "hoge",
      export_method: "ad-hoc",
      export_options: {
        method: 'ad-hoc',
        teamID: 'hoge',
        provisioningProfiles: {
          'bundle identifier name' => 'provisioning profile name'
        }
      }
    )

    # firebase app distributionに.ipaアップロード
    firebase_app_distribution(
      app: "1:1234567890:ios:0a1b2c3d4e5f67890",
      testers: "emailadress@gmail.com, emailadress2@gmail.com",
      release_notes: "hoge",
      firebase_cli_path: "node_modules/.bin/firebase"
    )
  end
end
```

## firebase_app_distributionについて
appの引数にはFirebaseのプロジェクト設定画面にあるアプリIDを指定。(プロジェクトIDじゃないよ)

# Provisioning Profileの作成
Dev環境かつAutoでやってたので、appleのdeveloperサイトから手動で作成する必要があった。
Dev環境用のProvisioning Profileを作成し、その名前をFastfileに記述。
ダウンロードしたら、起動して、キーチェーンに登録までする。

# 実行
`fastlane distribution`で実行できます。
実行したら、Firebaseコンソール -> プロジェクト -> App Distributionで新たなバイナリーができているかを確認しましょう。

# 参考
https://firebase.google.com/docs/app-distribution/ios/distribute-fastlane?hl=ja
https://qiita.com/fuwamaki/items/a9745e1242e24430eb4c#fastlane%E3%82%92%E7%94%A8%E3%81%84%E3%81%9Ffirebase-app-distribution%E3%82%A2%E3%83%83%E3%83%97%E3%83%AD%E3%83%BC%E3%83%89%E6%96%B9%E6%B3%95
TKG Service(vSphere with kubernetes)を触ってみた

TKG Service (vSphere with k8s)はvSphere ESXi上にVMとPodが同居するという今までにないソリューションでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666491/09f99891-891c-fefd-cf8a-8b3a2e924566.png)
出典：https://blogs.vmware.com/vsphere/2020/04/vsphere-7-kubernetes-namespaces.html

# 触ってみた

TKG ServiceをESXiで試したい方はこちらを[参照](https://qiita.com/hmachi/items/2e55031b17ff55723fed)してください。

環境ができあがると、vCenterから[Workload Management] > [NEW NAMESPACE]からNamespaceを作れすようになります。

<img width="1778" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666491/abaaac4d-52b7-cdcb-1358-d5d44730fe1b.png">
<img width="587" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666491/1381d564-fe2f-fbd8-1c94-ef7f7c380d56.png">

できあがると、まず[Permisson]を与えるよう促されます。
<img width="1149" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666491/ddffa319-094d-3f23-7fff-86512919bd11.png">

この画面で、vCenter上のどのユーザーにパーミッションに与えるかを聞かれます。
**Can viewかCan Editで選択します。**
<img width="587" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666491/15587002-71a5-d924-6fdc-c5385cbc5fdb.png">

ここではCan Viewを選択します。
そして、ここからはkubectlコマンドを使います。

以下のコマンドでvCenterのkubernetesにログインします。

```bash

kubectl vsphere login --server=<k8s> --insecure-skip-tls-verify
```

すると、以下のようにNamespaceが選択できます。

```bash

% kubectl vsphere login --server=<k8s> --insecure-skip-tls-verify

Username: administrator@vsphere.local
Password:
Logged in successfully.

You have access to the following contexts:
   k8s
   hoge

If the context you wish to use is not in this list, you may need to try
logging in again later, or contact your cluster administrator.

To change context, use `kubectl config use-context <workload name>`
```

つくったネームスペースにログインします。

```bash

% kubectl config use-context hoge
Switched to context "hoge".
```

そうするとコンテナーをはしらせることができます。

```bash

% kubectl run --image=alpine test sleep 3600
kubectl run --generator=deployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubectl run --generator=run-pod/v1 or kubectl create instead.
deployment.apps/test created
```

すると、当たり前のようにコンテナーが起動します。

```
% kubectl get po
NAME                    READY   STATUS    RESTARTS   AGE
test-848b8fb677-ssvp5   1/1     Running   0          85s
```

すごいのが、vCenterからもみえるようになります。

<img width="429" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666491/644d115f-dd40-aecb-9fd0-554f161a36a5.png">

そして、これはVMではなく、Hypervisor上に直接Podが起動します。
すごい、新しい時代を感じる。

# まとめ

この記事をベースより細かい検証を別記事で取り上げます。
Laravel クエリビルダを用いてNULLを判定する

## 目的

- クエリビルダを用いたNULLの判定方法をまとめる

## 実施環境

- ハードウェア環境

| 項目 | 情報 |
| --- | --- |
| OS | macOS Catalina(10.15.5) |
| ハードウェア | MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) |
| プロセッサ | 2 GHz クアッドコアIntel Core i5 |
| メモリ | 32 GB 3733 MHz LPDDR4 |
| グラフィックス | Intel Iris Plus Graphics 1536 MB |

- ソフトウェア環境

| 項目 | 情報 | 備考 |
| --- | --- | --- |
| PHP バージョン | 7.4.3 | Homwbrewを用いて導入 |
| Laravel バージョン | 7.0.8 | commposerを用いてこちらの方法で導入→[Mac Laravelの環境構築を行う](https://qiita.com/miriwo/items/adaaaeecae69d6392e08) |
| MySQLバージョン | 8.0.19 for osx10.13 on x86_64 | Homwbrewを用いてこちらの方法で導入→[Mac HomebrewでMySQLをインストールする](https://qiita.com/miriwo/items/ef6a064bc545fbea29d9) |

## 前提環境

- 先に記載した実施環境に近い環境で実施すること。

## 前提情報

- 下記の内容をすでに実施していると理解が早いかもしれない。
    - [Laravel クエリビルダを駆使する](https://qiita.com/miriwo/items/c850a62c3e3496f62dd7)

## 読後感

- NULLを用いた条件を使ってクエリビルダでデータの取得をすることができる様になる。

## 例

- 判定対象カラムがNULLであるレコードのみ取得する。

    ```php
    $query = モデルファイル名::select('*');
    $query->whereNull('判定対象カラム名');
    $query->get();
    ```

- 判定対象カラムがNULLではないレコードのみ取得する。

    ```php
    $query = モデルファイル名::select('*');
    $query->whereNotNull('判定対象カラム名');
    $query->get();
    ```

## 具体例

- usersテーブルの「user_name」カラムがNULLのレコードのみ取得する際は下記の様になる。
- usersテーブルのモデルファイル名はUser.phpとして、`アプリ名ディレクトリ/app`直下に存在するものとする。当該モデルファイルのuse宣言はすでに実施されている物とする。

    ```php
    $query = User::select('*');
    $query->whereNull('user_name');
    $query->get();
    ```

- usersテーブルの「user_name」カラムがNULLではないレコードのみ取得する際は下記の様になる。
- usersテーブルのモデルファイル名はUser.phpとして、`アプリ名ディレクトリ/app`直下に存在するものとする。当該モデルファイルのuse宣言はすでに実施されている物とする。

    ```php
    $query = User::select('*');
    $query->whereNotNull('user_name');
    $query->get();
    ```

## 参考文献

- [Laravel 7.x データベース：クエリビルダ](https://readouble.com/laravel/7.x/ja/queries.html)
Windows上のPythonアプリからAmazon RedshiftにODBCでデータ連携

#はじめに
この記事では、DataDirectドライバを利用し、Windows上のPythonアプリケーションからAmazon RedshiftにODBCで簡単にデータ連携する方法を解説します。


#Amazon Redshift用DataDirectドライバのインストール

１、<a href="https://www.ashisuto.co.jp/datadirect/app_download/" target="_blank">Windows用DataDirect ODBC Driver for Amazon Redshift</a>をダウンロードします。

２、手順通りドライバをインストールします。

#RedShift接続を設定する

１、ODBC Administratorより「追加」をクリックし、接続定義します。
ドライバは DataDirect 7.1 Amazon Redshift Wire Protocol を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662096/3edbceec-8b26-c3f9-96c6-ac773863ed44.png)

２、設定ウィンドウで、以下のようにホスト名、ポート、データソースを入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/662096/02f11524-db90-dcd2-3e09-70c5b5482104.png)

３、Test Connectをクリックし、ユーザー名とパスワードで正常に接続できるか確認します。


#PythonからRedshiftに接続する

１、PythonからRedshiftにアクセスするには、pyodbcパッケージをインストールします。
以下のコマンドでインストールしてください。

```console
pip install pyodbc
```

２、以下のようなPythonプログラムで、Redshiftデータにアクセスします。（接続設定を変更ください）

```console
import pyodbc
 
conn = pyodbc.connect('DSN=Redshift;UID=awsuser;PWD=awsPassword')
 
cursor = conn.cursor()
 
## Create Tables
cursor.execute("CREATE TABLE Track ( TrackId INT NOT NULL, Name VARCHAR(200) NOT NULL, AlbumId INT, MediaTypeId INT NOT NULL, GenreId INT, Composer VARCHAR(220), Milliseconds INT NOT NULL, Bytes INT, UnitPrice NUMERIC(10,2) NOT NULL);")
 
cursor.execute("INSERT INTO Track (TrackId, Name, AlbumId, MediaTypeId, GenreId, Composer, Milliseconds, Bytes, UnitPrice) VALUES (1, 'For Those About To Rock (We Salute You)', 1, 1, 1, 'Angus Young, Malcolm Young, Brian Johnson', 343719, 11170334, 0.99);")
 
conn.commit()
 
##Access Data using SQL
cursor.execute("select * from Track")
while True:
    row = cursor.fetchone()
    if not row:
        break
    print(row)
 
##Access Data using SQL
cursor.execute("select * from Artist")
while True:
    row = cursor.fetchone()
    if not row:
        break
    print(row)
```


３、上記のように接続文字列を定義するか、以下の接続文字列を使用しODBC Administratorでの接続設定を省略できます。

```console
Driver={DataDirect 7.1 Amazon Redshift Wire Protocol}; HostName=ホスト名を設定ください; Database=DB名を設定ください; UID=ユーザIDを設定ください; PWD=パスワードを設定ください; Port=5439
```



非常に簡単ですね。

参考記事

<A href="https://www.ashisuto.co.jp/datadirect/connectors/amazon-redshift.html" target="_blank">Amazon Redshiftへのリアルタイムアクセス
</a>

<A href="https://www.progress.com/tutorials/odbc/connect-to-amazon-redshift-using-odbc-from-python-on-windows" target="_blank">DataDirect for Redshift チュートリアル
</a>
Minecraft PE統合版サーバをDocker for Macで起動、バックアップ、レストア

Docker for Mac で Minecraft 統合版のサーバを立てます。
あわせてデータ領域のバックアップとレストアする手順も記載します。

![logo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12419/2739732a-fdc8-4e85-27c1-17d8733681ce.png)

Minecraft 統合版（PE版、iPad・iPhone・Android 等）のサーバは、
Windows 版と Ubuntu 版の alpha バージョンが公開されています。
https://www.minecraft.net/en-us/download/server/bedrock/
そのままでは Mac で実行できないので、[Docker for Mac](https://hub.docker.com/editions/community/docker-ce-desktop-mac/) を使います。

Docker イメージは下記を使いました。
https://hub.docker.com/r/itzg/minecraft-bedrock-server

```sh
mkdir minecraft-bedrock-server
cd minecraft-bedrock-server

curl -o docker-compose.yml https://raw.githubusercontent.com/itzg/docker-minecraft-bedrock-server/master/examples/docker-compose.yml

docker-compose up --build --no-start
docker-compose start
docker-compose logs -f
```

docker-compose.yml の中身 → [github 参照](https://github.com/itzg/docker-minecraft-bedrock-server/blob/master/examples/docker-compose.yml)

```sh
version: '3.4'

services:
  bds:
    image: itzg/minecraft-bedrock-server:latest
    environment:
      EULA: "TRUE"
      GAMEMODE: survival
      DIFFICULTY: normal
    ports:
      - 19132:19132/udp
    volumes:
      - bds:/data
    stdin_open: true
    tty: true

volumes:
  bds: {}
```

起動すると、こんなログが表示されて、統合版から接続できるようになります。

```
bds_1  | Starting Bedrock server...
bds_1  | NO LOG FILE! - setting up server logging...
bds_1  | [2020-07-28 11:50:24 INFO] Starting Server
bds_1  | [2020-07-28 11:50:24 INFO] Version 1.16.1.2
bds_1  | [2020-07-28 11:50:24 INFO] Session ID f130158c-xxxx-xxxx-xxxx-199a89746d3e
bds_1  | [2020-07-28 11:50:24 INFO] Level Name: Bedrock level
bds_1  | [2020-07-28 11:50:24 INFO] Game mode: 0 Survival
bds_1  | [2020-07-28 11:50:24 INFO] Difficulty: 2 NORMAL
bds_1  | [2020-07-28 11:50:24 INFO] opening worlds/Bedrock level/db
bds_1  | [2020-07-28 11:50:28 INFO] IPv4 supported, port: 19132
bds_1  | [2020-07-28 11:50:28 INFO] IPv6 not supported
bds_1  | [2020-07-28 11:50:28 INFO] IPv4 supported, port: 33126
bds_1  | [2020-07-28 11:50:28 INFO] IPv6 not supported
bds_1  | [2020-07-28 11:50:29 INFO] Server started.
```

設定ファイル server.properties の編集

```sh
docker-compose exec bds apt update 
docker-compose exec bds apt install vim 
docker-compose exec bds vi server.properties
docker-compose restart
```

データ領域のバックアップ手順

```sh
docker-compose stop

docker run -it --rm -v minecraft-bedrock-server_bds:/data -v ${PWD}:/dump debian \
tar zcvf /dump/bds.tar.gz -C /data .
```

データ領域のレストア手順

```sh
docker-compose stop

docker run -it --rm -v minecraft-bedrock-server_bds:/data -v ${PWD}:/dump debian \
tar zxvf /dump/bds.tar.gz
```

上記手順で使用中のワールドのデータを別ホストに移動することもできます。

なお、上記で debian イメージを使っているのは、itzg/minecraft-bedrock-server が `FROM debian` のためです。→ [Dockerfile](https://hub.docker.com/r/itzg/minecraft-bedrock-server/dockerfile)
HTTP/2導入の説得マニュアル

偉い人からHTTP/2導入の許可を得るための想定問答集

## なぜ導入したいの？
## 1. ユーザの待ち時間が減るから
以下の理由により待ち時間が減ることで、顧客満足度の向上、離脱率低下などが見込めます。
1. リクエストの多重化
2. 接続のオーバーヘッド削減
2. ヘッダ圧縮
3. フロー制御（重い処理のせいで他が待たされることが減る）
4. HTTP/2 Server Push（htmlが要求された段階で画像やcssも返す）


## 2. Googleのページランクが上がる（はずだ）から
未使用だとLighthouseで改善事項として指摘されます。
https://web.dev/uses-http2/
対応するとPerformanceとBest Practicesのスコアが大きく上がりました。
（ローカルで試したときはPerformance+20くらい）

## ブラウザが対応してないとだめなんでしょ？
IE11とOpera mini以外は対応済みです。
https://caniuse.com/#feat=http2

## そんなに流行ってるの？
[HTTP/2 and SPDY indicator](https://chrome.google.com/webstore/detail/http2-and-spdy-indicator/mpbpobfflnpcgagjijhmgnchggcjblin?hl=ja)プラグインを入れると、
閲覧しているサイトが対応しているかどうかブラウザ上で確認可能です。

## サーバの負荷上がらない？
基本的には減ります。
今まではリソースごとに作成していたTCPコネクションを1つにまとめ、
代わりにその中でストリームと呼ばれる仮想的な接続を行うことによりオーバーヘッドが減るためです。

設定項目が増えるため、設定次第ではもちろん増える場合もあります。

## 他にデメリットはある？
（ほとんど）ありません。

厳密には…

1TCPコネクションで通信する関係上、パケットロスが発生した場合、コネクション内のストリーム全てが再送待ちになるため、
通常6TCPコネクション使えるHTTP/1より影響が大きく、
回線品質がうんこで2%以上ロスがあるとHTTP/1より遅くなってしまうらしいです。

また、ワイルドカード証明書を使っていて複数のドメインを1IPで管理している場合、
サブドメイン間でコネクションを使い回すのでSSL設定を揃えて置かないといけないらしいです。
ただし、あえて設定変えるケースはあまり思いつきません。

## 導入の手間はどのくらい？
使えるようにするだけならapacheの場合以下の4点を設定するだけです。
HTTP/2が有効になっていなくても、前者2つは有効化済みの場合が多いと思います。
・SSLを有効化
・eventMPMを有効化
・mod_http2をインストール
・VirtualHostディレクティブに以下の設定を追加
```Protocols h2 http/1.1```

ただし、mod_http2を入れるにはapacheのバージョンが2.4.17以上である必要があるため、
CentOS7などの場合はapacheのバージョンが2.4.6と古くてそのままでは入りません。

HTTP/2用の設定も変更したほうがもちろんいいですが、デフォルトでもかなり速くなります。

## HTTP/3(HTTP over QUIC)は？
主要ブラウザではサポートされたもののデフォルト有効化はされていませんし、
ひとまずHTTP/2に対応すべきです。
https://caniuse.com/#feat=http3

## 参考
https://http3-explained.haxx.se/ja/why-quic/why-tcphol
Boto3 に追加されたリトライ処理モードを利用する


## はじめに
AWS SDK は [Exponential Backoff](https://docs.aws.amazon.com/ja_jp/general/latest/gr/api-retries.html) による自動再試行ロジックが実装されていますが、
Boto3 では 3 つのリトライ処理モードを選択できます。

* legacy (デフォルト)
* standard
* adaptive 

botocore の GitHub リポジトリを確認すると、2020年2月ごろに standard および adaptive が
追加され、それ以前の実装は legacy という名称になっています。

[Add support for new retry modes #1972](https://github.com/boto/botocore/pull/1972)

互換性のため、デフォルトが legacy となっており、standard/adaptive で追加された機能を
利用するにはリトライ処理モードを明示的に変更する必要があります。

## リトライ処理モードの変更方法
botocore の config オブジェクトをインスタンス化し、設定情報をクライアントに
渡すことができます。利用可能なオプションは `max_attempts` と `mode` です。
リトライ処理モードによってデフォルトの最大試行回数は異なりますが、
max_attempts によってカスタマイズできます。

```python
import boto3
from botocore.config import Config

config = Config(
   retries = {
      'max_attempts': 10,
      'mode': 'standard'
   }
)

ec2 = boto3.client('ec2', config=config)
```

## 各リトライ処理モードの概要
### Legacy retry mode
Boto3 クライアントでデフォルトで使用されるモードです。
バックオフ時間の計算に使用される係数は 2 です。
[v1 リトライハンドラー](https://github.com/boto/botocore/blob/master/botocore/retryhandler.py) が使用されます。
再試行に対応する errors/exceptions の数が限られています。

### Standard retry mode
多言語の AWS SDK と一貫性のあるロジックにより、再試行ルールが標準化されています。
legacy モードよりも多くの throttling/limit エラーや例外に対応しています。
バックオフ時間の計算に使用される係数は legacy モード同様 2 ですが、最大値は 20 秒です。
[v2 リトライハンドラー](https://github.com/boto/botocore/tree/master/botocore/retries) が使用されます。

||legacy|standard|
|---|---|---|
|デフォルトの最大試行回数|5|3|
|一時的な接続エラーへの対応|ConnectionError<br>ConnectionClosedError<br>ReadTimeoutError<br>EndpointConnectionError|RequestTimeout<br>RequestTimeoutException<br>PriorRequestNotComplete<br>ConnectionError<br>HTTPClientError|
|throttling/limitエラーおよび例外への対応外|Throttling<br>ThrottlingException<br>ThrottledException<br>RequestThrottledException<br>ProvisionedThroughputExceededException|Throttling<br>ThrottlingException<br>ThrottledException<br>RequestThrottledException<br>TooManyRequestsException<br>ProvisionedThroughputExceededException<br>TransactionInProgressException<br>RequestLimitExceeded<br>BandwidthLimitExceeded<br>LimitExceededException<br>RequestThrottled<br>SlowDown<br>EC2ThrottledException|
|ステータスコードによる再試行|429/500/502/503/504/509 など|500/502/503/504|
|遅延時間の計算式|rand(0, 1) * (2 ^ (attempts - 1))|min(rand(0, 1) * 2 ^ attempt, 20)|

### Adaptive retry mode
Standard モードの機能に加えて、トークンバケットアルゴリズムによるクライアント側の
自動レート制限機能や、再試行の毎に AWSサービス側のエラー/例外/HTTPステータスコード
に基づいてレート制限変数を変更する機能が追加されています。
クライアント側でエラー内容に応じて柔軟な再実行を行なうことができますが、
**実験的なモードであるため、将来的に機能と動作が変わる可能性があります。**

## 参考
**Retries - Boto3 Docs**
https://boto3.amazonaws.com/v1/documentation/api/latest/guide/retries.html

以上です。
参考になれば幸いです。
React初学者によるReactについて（感性独特）

都内のIT企業でデザイナー兼フロントエンジニア（見習い）をやってます。
前職ではHTML、CSS、PHPを触ってた僕にとってReactの壁は厚い。。。。
そんな経験からReactってこういうものなんだよ！！！ってことをまとめておきます。

#そもそもReactってなんぞや？
おそらくですが、Reactってなんなん？？って初学者はめちゃめちゃいると思ってます。
僕自身がそうだったこと、前職同期に話しても分かってもらえなかったことからなんとなく想像してます。
というわけでまずはReactってなんぞや？って話から。

とりあえず、公式です、お納めください。
[React](https://ja.reactjs.org/)

とまあ、アクセスしていただいてなんとなくわかる方もいるかもわかりませんが、
Reactって**ユーザインターフェース構築のための JavaScript ライブラリ**なんですねぇ〜〜。

世間でいうところのUIをいい感じにすることに特化したJSのライブラリということなわけです。
ライブラリっていうのはLibraryっていうように図書館みたいな感じ。
よく使うよねっていうものをまとめて、使えるようにしてくれています。

だから、利用者である我々はそのライブラリに準じた書き方をすることでライブラリにある機能を使用することができるようになっています。（実際は）
Reactはその中でもJSでUIを構築していくのに便利なものを提供してくれているライブラリということです。

ライブラリは当然Reactだけではないので、何を使うかは所属している組織だったり用途によって検討して決定すれば良いかと思っています。

#具体的にReactは何をしてくれるの？
じゃあ、Reactがそういうライブラリなんだ〜〜ってのは分かってもらえたと仮定しまして。
Reactを使うと、HTMLをごりっごり書くのと何が違うの？？って思わない人はいないと思います、僕も正直そう思ってました。

でも正直、すんげぇ捗るからトライしてみて欲しいなぁて思うんで、React初学者の僕でさえ「これええなぁ」って思ったことを書きたいなって思います。

#コンポーネントって考え方

コンポーネントはComponentなんですが、直訳すると構成子と訳すことができます。
そう、ウェブサイトやサービスを組んでいく中で繰り返し使用される構成要素があるじゃないですか。

これHTMLとかで書いていくと

```
<a class="button">
  お申し込みはこちら
</a>
```

にみたいなことにして、

```
.button {
  display: block;
  width: 300px;
  padding: 10px 50px;
}
```

みたいなスタイルをつけるってのをたくさん書かなくちゃいけないわけです。
書かなくてなんとかすることもできんのかな？？って思ってはいますが、調べてません。

でも、Reactだったらこれをコンポーネントとして定義しておくことができるんで、一度作成したらそれを呼び出して使用することができます。
スタイルもコンポーネントに対して行うことができるので、一括で変更することができます。
僕はここに感動を覚えました、楽やし管理楽やな〜〜って。

#業務分担みたいな考え方
Reactはそもそも、**ユーザインターフェース構築のための JavaScript ライブラリ**ってだけあって
状態を保持したりだとかは業務範囲じゃなくて、描画していくことが業務範囲だそうです。
いわゆるビューを作っていく部分ですかね。

**「でも、ぶっちゃけ状態保持したりできないなら実務で使えないんじゃ。。。」**
ってなったらしく、そこから**flux**ってアーキテクチャが生まれて、Reactでも状態管理ができるようになったんですね。

このfluxってアーキテクチャが僕はすごくスッキリしていて好きで、また今度かければいいなって思うんですが
すんごいざっくり言うともうフォルダを役割で分けちゃって、そこに各役割を担当するファイルを置いて書いていきましょう！！みたいな感じ。

そのスッキリさが気に入っています。
初学者の僕にとって関数とかが入り乱れてると頭ごちゃごちゃになるんで。。。

#他にもたくさんいいことがあるから勉強していきます
上司からも言われていることなんですが、まだまだReactにはすごい機能が盛り沢山です。
Hooksだったり。

そこら辺はまだ理解できてないから今後の課題にしていくとします。
[メモ] useState をラップしたようなフック

# [メモ] useState をラップしたようなフック

`useState` をラップしたようなフックです。
親子関係のコンポーネントにて子側で `props.value` を処理するような際に使用します。

- 親側からの `props.value` の変更を受けて値を同期
    - 値の比較により同期するかを制御
- `propsOnChange` を関数として確定した `onChange` を第三要素として返す

```ts:useValue
import { useState, useEffect, Dispatch, SetStateAction } from 'react'

/** オプション指定 */
type Options = {
  /** `propsValue` に変更があった場合 `setValue` による同期を行う (デフォルトは `true` 扱い) */
  sync?: boolean
  /**
   * `useEffect` にて `value` と `propsValue` を比較して差があった場合に更新する制御
   * - `boolean` 指定の場合そのまま更新制御に使用
   */
  diff?: (<T = unknown>(value: T, propsValue: T) => boolean) | boolean
}

/** 値の比較にデフォルトで使用する関数 */
const diffDefault = <T>(val: T, pVal: T): boolean => {
  if (Array.isArray(val) && Array.isArray(pVal)) {
    const unified = Array.from(new Set([...val, ...pVal]))
    return unified.length !== val.length || unified.length !== pVal.length
  }
  // オブジェクトの場合の比較
  if (typeof val === 'object' || typeof pVal === 'object') {
    return JSON.stringify(val) !== JSON.stringify(pVal)
  }
  return val !== pVal
}

/**
 * `useState` をラップしたような関数
 * - `propsValue` の変更が立った場合 `options?.sync` 次第で同期する (デフォルト同期)
 * - 戻り値として `onChange` を関数として確定したものを返す
 * - `options` の構成
 * -- `sync`: `boolean`\
 *    `propsValue` に変更がある場合に同期するフラグ
 * -- `diff`: `((value: unknown, propsValue: unknown) => boolean) | boolean`\
 *    関数指定により `propsValue` との差分抽出のロジックを指定可能
 */
const useValue = <T, F extends Function | undefined>(
  /** useState に渡す値 */
  propsValue: T,
  /** props などで渡される `onChange` を `Function` として確定させてから返す */
  propsOnChange: F,
  /** オプション指定 */
  options?: Options,
): [T, Dispatch<SetStateAction<T>>, NonNullable<F>] => {
  const [value, setValue] = useState<T>(propsValue)
  const sync = options?.sync ?? true
  const onChange = propsOnChange ?? (() => {})
  const optionsDiff = options?.diff ?? diffDefault
  const diff = typeof optionsDiff === 'boolean' ? () => optionsDiff : optionsDiff
  useEffect(() => {
    if (sync && diff(value, propsValue)) {
      setValue(propsValue)
    }
  }, [propsValue, sync])
  return [value, setValue, onChange as NonNullable<F>]
}

export default useValue
```

`options.diff` の指定の事例

```ts:options.diff
const [value, setValue, onChange] = useValue(props.value, props.onChange, {
  diff<T = string>(val: T, pVal: T) {
    return val !== pVal
  },
})
```
【Elasticsearch入門】速習Elasticsearch Aggregation 概要編

# ゴール
本記事ではElasticsearchで頻繁に使用されるAggregationの概要を理解してもらうことが目的となります。
CRUDやSearchと少し異なり新しい概念のため、まずは概要から説明していこうと思います。

- CRUD
- Search
    - query
    - aggregation
        - 概要
        - Metrics
        - Buckets

# Elasticsearch
Elasticsearch は オープンソースの全文検索エンジンです。
Apache LuceneをベースとしたJavaで書かれたソフトウェアでElastic社により開発が進められています。
登録したドキュメントから目的の単語を含むドキュメントを高速に検索することができます。
基本的にElasticsearchではRestful APIを使って操作します。


# Aggregationとは
Aggregationとは、検索の結果に対して分類や集計を行うことができる機能です。
通常の検索では、ユーザがあらかじめ指定したクエリに基づいてヒットしたドキュメントを結果として返します。
一方でAggregationでは、ドキュメントを特定のグループに分類したり、分類したグループごとの最大値や最小値、平均値などの統計量の値を返すことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119747/b00b996d-71d2-3f87-bf95-f64734951b7d.png)

Elasticsearchと頻繁に用いられるKibanaではデータの可視化を行うことができます。
その際の裏側ではElasticsearchにクエリが投げられているのですが、
このようなAggregationのクエリが頻繁に投げられ、分類・集計が行われています。

# Aggregationの構成
Aggregationでは分類や集計を行うための多くのタイプがあります。
これらをカテゴリ分けするといくつかのカテゴリに分かれますが、
Kibanaとの連携も含め重要なものを３つ挙げると以下の３つとなります。

- Metrics
- Buckets
- Pipeline

それぞれを説明すると以下のようになります。
## Metrics
分類されたグループに対して、最小、最大、平均などの統計値を計算します。

## Buckets
ドキュメントをフィールド値に基づきグループ化するための分類方法です。
ブログ記事のカテゴリフィールドに基づく分類を行う。といった場合などに使用します。
他にもいいね数でヒストグラムで分けるといったような分類方法などもあります。

BucketsとMetricsを図で示すと以下のような分かれ方となります。

## Pipeline
PipelineはBucketsなどの他のAggregationの結果を用いてさらに集計する機能となります。
Kibanaでの可視化で移動平均や前日との差分を取りたいといった用途で使うことが多いです。

## MetricsとBuckets
ElasticsearchやKibanaを勉強する際は基本的にはMetricsとBucketsの概念を抑えておけば問題ありません。
よくあるやり方としてドキュメントをBucketsをグループに分割してグループごとの統計値を計算するという用途です。（もちろん個別に使うこともできます。）
以下は「ブログ記事をカテゴリごとに**分類**し、平均購読数を**集計**する」といった例になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119747/5969b38e-8d6c-140d-596d-e1b47c3749d4.png)

以上がAggregationの基本的な概要となります。

次回から実際にAggregationの中身について解説していきます。
よろしくお願いします。

# おすすめ教材


- [はじめてのElasticsearch](https://www.udemy.com/course/elasticsearch/?couponCode=3BE4592DF570D6DA69CF)
- [はじめてのKibana](https://www.udemy.com/course/kibana-jap/?couponCode=E59890B71A886D5A1CED)
自分の気持ちをMr.Childrenの歌詞で表現したい

# はじめに
この人は何を言ってるんだ..?といったタイトルですが（笑）..自然言語処理の勉強も兼ねて、４連休を利用してつくってみました。近々、どこかしらにWebで見られるようにしようと思います。

# コンセプトと完成イメージ
このネタを見つけた瞬間、現状(As is)→課題→あるべき姿(To be)を書き出していました。
さすがビジネスマン（笑）
<img width="900" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635959/5cfcfb1c-914c-a457-4f32-2a4964d3af9e.png">

どんな感じでつくろうかなと考えて思いついたのが以下の様な仕組みです。↓
<img width="880" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635959/af6ba283-5b6f-5a28-1cea-3499b8c766ac.png">
内部でミスチル歌詞データセットの作成およびWord2Vec化。自分の感情も同様にWord2Vec処理し、cos類似度にて似ている歌詞を引っ張ってきます。

# PoCできた！
上記の全体像が実現できそうかさくっとトライしました。
結果...**「寝れなくてしんどいなぁ」**という自分の感情に対して **「社会人になって 重荷を背負って 思い知らされてらぁ -光の射す方へ」** が一番目に返ってきました。え...恐いぐらい深読みしてくる...笑
<img width="1109" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635959/b44eee0b-4a12-3045-fa77-2b99f0b3d171.png">

# 使っているもの
形態素解析：janome.tokenizer
Word2Vec：gensim.modelsのword2vec

```python
from janome.tokenizer import Tokenizer
from gensim.models import word2vec
```

形態素解析で歌詞を細切れにし、その一言ごとにWord2Vecしています。
最終的にベクトルの平均を取得する事で、歌詞１セットのWord2Vecができあがるという魂胆です。

<img width="538" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635959/e9b91f85-1819-28cf-6df9-e74f0866e3f4.png">
↓形態素解析をした結果
<img width="528" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635959/2cd94d9a-4b0d-401c-c4d7-c4f75c52ba41.png">

文章をWord2Vecする部分

```python
# skip-gram Mr.Childrenの歌詞(sentences)で、w2vのモデルをつくる。
skipgram_model = word2vec.Word2Vec(sentences,
                                   sg=1,
                                   size=250,
                                   min_count=2,
                                   window=10, seed=1234)



#形態素解析をした１単語ごとにWord2Vecを行い、最後に平均をとる関数＝＞歌詞の文脈を反映したWord2Vecができる？
def avg_document_vector(data, num_features):
    document_vec = np.zeros((len(data), num_features))
    for i, doc_word_list in enumerate(data):
        feature_vec = np.zeros((num_features,), dtype="float32")
        for word in doc_word_list:
            try:
                feature_vec = np.add(
                    feature_vec, skipgram_model.wv.__getitem__(word))
            except:
                pass

        feature_vec = np.divide(feature_vec, len(doc_word_list))
        document_vec[i] = feature_vec
    return document_vec

```

# おわりに
言葉をベクトルに変換して、一致度を見るというのが面白いなぁと思いました。
BERTとかも勉強してみたいなぁ〜と。
このお遊びをサービスにしていくためには曲数の拡張が急務です。（2020/7/29現在：5曲..笑）
コツコツと曲を貯めていきます。

にしても、こういったお遊びが４連休のスキマ時間でできるようになってきたのが、スキルが付いてきている様で嬉しいですね！！
FlutterでAndroid部分を開けない！「open android module in android studio」が表示されない場合の対処法

Flutter開発をしている際にiOS部分はXCode、Android部分はAndroid Studioで個別に開くケースがあると思います。
通常はAndroid Studioにてそれぞれのフォルダを右クリック→Flutter→Open XX module in XXという形で開くことが可能なのですが、
たまにそこの項目が出てこない場合があります。（以下画像）そんなときの対処法です。

![00 2020-07-29 6.28.28.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503496/0b48cd94-4c64-1f73-efa7-68fe467617ba.jpeg)

環境はMacOSですがWindowsも同じかと思います。

#Fileから開く
まず、上部のFile→Openを選びます。以下画像の場所です。
![00 2020-07-29 6.28.43.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503496/5da96ce5-9e90-d42f-efcb-1b01925da557.jpeg)



そして、開きたいFlutter Project名→androidを選択して開くとAndroid部分を個別に開くことが可能です。
![00 2020-07-29 6.29.06.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503496/48930a34-af49-70de-0c70-02ff24e484ee.jpeg)


他にもやり方があるかと思いますが、この方法が確実かと思いシェアさせて頂きました。
VS Code: 拡張機能がインストールできなくなった時の対処

# VS Code の拡張機能がインストールできなくなった時の対処方法
## 症状
- install をクリックしてもインストールされない
- install をクリックすると，**Failed to install** となり，手動でのインストールを促してくる
    - 手動でインストールするように警告されるので，vsixファイルをダウンロードし，vsixからインストールを試みるも失敗
- ExtensionsのRECOMMENDEDをみてみると，**we cannot connect to the extensions marketplace at this time**というような文面が表示される．

## 解決法
Macであればおそらく，**/Users/[User Name]/.vscode/extensions**下に**.obsolete**というファイルが存在する．
このファイルを削除( $ rm .obsolete )すれば解決するはずである．
- .obsolete: アンインストールした拡張機能のリストが保存されている
なぜobsoleteファイルを削除すると直るのかは不明.
D言語でも、GoToキャンペーンを活用したい

#はじめに

自宅に居ながらも、GoToキャンペーンにあやかりたいです。
まだ間に合うでしょうか。

```d:go2travel.d
import std.stdio;
import std.traits;

enum CITY { OSAKA, ITAMI, FUKUOKA, SAPPORO, NAHA }

void gotoKyoto(CITY city)
{
	string[] route;
	switch (city)
	{
		case CITY.SAPPORO:
			route ~= "札幌🛫";
			goto case CITY.ITAMI;
		case CITY.FUKUOKA:
			route ~= "福岡🚅";
			goto default;
		case CITY.NAHA:
			route ~= "那覇🛫";
			goto case;
		case CITY.ITAMI:
			route ~= "伊丹🚃";
			goto default;
		default:
			route ~= "大阪🚃";
			break;
	}
	route ~= "京都⛩️";
	writefln("  %-(%s ➡ %)", route);
}

void main()
{
	writeln("ＧｏＴｏ トラベル ～ Ｄ言語編 ～");
	foreach (city; [EnumMembers!CITY])
	{
		gotoKyoto(city);
	}
}
```
```txt:実行結果
ＧｏＴｏ トラベル ～ Ｄ言語編 ～
  大阪🚃 ➡ 京都⛩️
  伊丹🚃 ➡ 大阪🚃 ➡ 京都⛩️
  福岡🚅 ➡ 大阪🚃 ➡ 京都⛩️
  札幌🛫 ➡ 伊丹🚃 ➡ 大阪🚃 ➡ 京都⛩️
  那覇🛫 ➡ 伊丹🚃 ➡ 大阪🚃 ➡ 京都⛩️
```
#D言語でのフォールスルー
D言語でフォールスルー(※)を使う際は、`break`がないのが、意図的なのか、うっかりミスかがわかるよう、`goto case` や `goto default` の使用を推奨しています。

私がC言語でフォールスルーを使う際は、コメントを書くので、`goto ～`を明示するのは、アリだと思っています。

ちなみに、`case CITY.NAHA`や`case CITY.ITAMI`に`goto ～`を記載しなくても同じ処理結果になりますが、以下のようにコンパイル時にワーニングで知らせてくれます。

```txt:コンパイル結果
code.d(19): Deprecation: switch case fallthrough - use 'goto case;' if intended
code.d(21): Deprecation: switch case fallthrough - use 'goto default;' if intended
```
（※）`switch`文の中で、とある`case`に`break`を入れずに、次の`case`内の処理もあわせて実行させること。

#参考
[[一発ネタ]GolangでGoToキャンペーン](https://qiita.com/Mister_K/items/ff4f405089416fc412c6)
[すごいswitch文に出会った](https://qiita.com/segur/items/b11702d5360feeeab0f9)
Rootless Docker導入

### インストール
```sh
sudo apt-get -y install uidmap
curl -fsSL https://get.docker.com/rootless | sh
# 表示に従い下記2行を.bashrcに
export PATH=$HOME/bin:$PATH
#export DOCKER_HOST=unix:///run/user/`id -u`//docker.sock
```

~/bin 以下にインストールされる
<details><summary>
(必要なら)Proxy設定追加
</summary>

```~/.config/systemd/user/docker.service
[Service]
Environment="HTTP_PROXY=http://proxy.example.com:8080"
Environment="HTTPS_PROXY=http://proxy.example.com:8080"
Environment="NO_PROXY=localhost,127.0.0.1,.internal.example.com"
```
</details>


```sh:設定後再起動
systemctl --user daemon-reload
systemctl --user restart docker.service
systemctl --user status docker # 起動確認
```
### 実行確認
```sh
docker run --rm -it -v $PWD:/root ubuntu touch /root/xxx 
ls -al xxx
# 生成された./xxxのownerが自分であることを確認
```

### rootfulモードとの切り替え
```sh
docker context list # defaultとrootlessがあるはず
docker context use default #デフォルト(Rootful)に切り替え

sudo docker run --rm -it -v $PWD:/root ubuntu touch /root/xxx 
# 生成された./xxxのownerがrootであることを確認
```
DynamodbにPython:floatを入れる場合

# 結論
値として挿入する場合はサポートされていないため、一旦文字列>Decimalにしてから挿入すること。

```python
item={
"val":Decimal(str(float_val))
}
```

参照：
https://stackoverflow.com/questions/49633504/python-and-dynamodb-decimal-inexact#comment93902878_52450303
railsのlocal環境をhttpsにしてみた。

## 環境

>ruby 2.5.1
rails 6.0.3.2
mac catalina 10.15.5

## mkcert install
[Git mkcert](https://github.com/FiloSottile/mkcert) 

```
$ brew install mkcert
```
↑私の場合はprojectsフォルダで実行
↓localにCA(認証局)を作成

```
$ mkcert -install
```
## 証明書とキー発行
作成中のapplicationのフォルダへ移動
該当アプリの.gitignoreに下記追加。※Gitに挙げないため。

```
localhost.pem
localhost-key.pem
```
以下を実行

```
$ mkcert localhost
```
Sudo password:を求められます。
これは自身のmacのpasswordです。

これで、
localhost.pem
localhost-key.pem
の2つのファイルが出来上がります。

## config/puma.rbに追記

```ruby:config/puma.rb
if ENV.fetch('RAILS_ENV') { 'development' } == 'development'
  ssl_bind '0.0.0.0', '9292', key: './localhost-key.pem', cert: './localhost.pem'
end
```
## 以上で準備終了
rails起動して以下をポチっ
[https://localhost:9292/](https://localhost:9292/) 


追記
## アンインスト
```ターミナル:ターミナル／私の場合はprojectsフォルダ
mkcert -uninstall
```
config/puma.rbから上記を削除
##ブラウザの設定を変更する
ブラウザは一度httpsで接続したサイトはhttpsで接続しようとします(仮にアドレスバーにhttp://localhost:3000/と直接入力しても)。
その設定が簡単に変わらないようです。
安易に変更するともとに戻せなくなります。私のように。
お気をつけください。
【cygwin】飽きの来ない背景画像にしたい。

- ```2020-08-13```　USERもHOMEもcron実行中は未設定になるようです。

# 1. 背景

- 飽きの来ない、Windows10の背景画像を求める。

# 2. 方針

- Windowsスポットライトの画像を使ってスライドショーにする。
- もしかしたら便利なソフトがあるかもしれなけど、cygwin+cronで解決したい。
    - 参考）https://qiita.com/koKekkoh/items/33163cc76fe9bb9b76a2
- Sylphyhornはcygwinを使う場合に問題がある。

# 3. Windows10の設定

## 3.1. Windows スポットライト

1. 【Win】キー
2. 設定→個人用設定→ロック画面
3. 「Windows スポットライト」にする

## 3.2. スラライドショー

1. 【Win】キー
2. 設定→個人用設定→背景
3. 「スライドショー」にする

# 4. スクリプト

- ```$HOME/logs``` ディレクトリがある前提
- ```exiftool``` は別途インストールしてください。
    - これがないと縦長の画像も背景になります。
- ```cron``` で動きます。→エラーになっていました…orz（修正）

```bash
#!/usr/bin/bash

########## DEFINE

readonly BASENAME=`basename $0 | cut -d. -f1`
readonly LOG_FILE="$HOME/logs/${BASENAME}.log.`date '+%Y%m'`"

#readonly THE_NAME=`basename $HOME`
readonly THE_NAME="username"
readonly SRC_DIR="/cygdrive/c/Users/$THE_NAME/AppData/Local/Packages/Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy/LocalState/Assets"
readonly DST_DIR="/cygdrive/c/Users/$THE_NAME/Documents/Background"
readonly EXIFCMD="/cygdrive/c/Local/bin/exiftool"

readonly IMG_SIZE="1920x1080"

########## MAIN

_copy_()
{
        local jpg dst size

        date '+%Y/%m/%d %H:%M:%S start'

        for jpg in `find . -mtime -21 -size +300k -print`
        do
                dst=$DST_DIR/`echo ${jpg} | cut -c3-12`.jpg

                if [ -f $dst ]
                then
                        echo "found: $jpg"
                else
                        size=`$EXIFCMD $jpg | egrep '^Image Size ' | sed -e 's/\r$//; s/^.*: //;'`

                        if [ $size = $IMG_SIZE ]
                        then
                                echo "copy: $jpg"
                                cp $jpg $dst
                        else
                                echo "skip: $jpg"
                        fi
                fi
        done

        date '+%Y/%m/%d %H:%M:%S done'
}

##########

main()
{
        local mode rtn
        mode=$1

        [ ${mode:-__null__} = "debug" ] \
                && ( _copy_ || rtn=$? ) \
                || ( _copy_ >> $LOG_FILE 2>&1 || rtn=$? )

        if [ ${rtn:-0} != 0 ]
        then
                echo "_copy_: error: rtn=$rtn"
        fi

        return $rtn
}

########## EXEC

cd $SRC_DIR
main "$@"
exit $?

########## END
```

# 5. 備考

## 5.1. Sylphyhorn

- 仮想デスクトップ毎に背景画像を変えてくれるソフト。なかなか良いです。
- 切り替え直後、体感で３秒くらいcygwinが入力を受け付けなくなるので諦めました。

# 以上
ReactでAPIを使用する際によく見る"fetch(URL).then"のメソッドチェーンについて

#背景
Reactからjson形式のAPIを利用する方法として下記のような方法が挙げられている。 (Reactに限った書き方ではないが)

```js:useApi.js

1 fetch('http://example.com/api/')
2   .then((response) => response.json())
3   .then((response) => {
4     console.log(response.hoge);
5   })
```

しかし、データ(response.hoge)のみを利用するのであれば、2行目は不要なのでは？と思い、コメントアウトした。

```js:useApi.js

1 fetch('http://example.com/api/')
2   //.then((response) => response.json())
3   .then((response) => {
4     console.log(response.hoge);
5   })
```

しかし、

```js:useApi.js
4     console.log(response.hoge);
```

がundefinedとなった。
2行目の有無で3行目の引数の中身が変わっているような挙動だ。

#調べた結果
Promiseの.then(というより、アロー関数)には、下記の特徴があるようだ。

* 単文の場合は、{}を省略可能。
* {}を省略した場合は、単文の処理結果をPromiseでwrapしたもの(?)が自動でreturnされる。

この特徴をメソッドチェーンとして活用したのが冒頭のコードとなっている。

ちなみに、自分で

```js:useApi_2.js
1 fetch('http://example.com/api/')
2   .then((response) => {
3     const res_json = response.json()
4     console.log(res_json.hoge);
5   })
```

としても同じ実行結果にはならない。(Promiseでwrapしていないため)

#結論
自分でPromise返す処理を書くより、メソッドチェーンを活用したほうが楽。

```js:useApi.js

1 fetch('http://example.com/api/')
2   .then((response) => response.json())
3   .then((response) => {
4     console.log(response.hoge);
5   })
```

#参考にさせていただいたサイト様
* [https://sbfl.net/blog/2019/11/04/promise-cookbook/](https://sbfl.net/blog/2019/11/04/promise-cookbook/#gatsby-focus-wrapper:~:text=%E3%80%8C1%E8%A1%8C%E3%81%AE%E5%A0%B4%E5%90%88%E3%81%AFreturn%E3%82%92%E7%9C%81%E7%95%A5%E3%81%A7%E3%81%8D%E3%82%8B%E3%80%8D)
* [https://www.l08084.com/entry/2018/10/14/161406](https://www.l08084.com/entry/2018/10/14/161406#returnなし:~:text=then%E3%81%8C%E6%96%B0%E3%81%97%E3%81%84Promise%E3%82%92%E8%BF%94%E3%81%97%E3%81%A6%E3%81%8F%E3%82%8C%E3%82%8B%E3%81%AE%E3%81%A7%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%83%81%E3%82%A7%E3%83%BC%E3%83%B3%E3%81%8C%E5%8F%AF%E8%83%BD%E3%81%A7%E3%81%99)
こんなタイトルで質問してはいけない

# はじめに

[teratail](https://teratail.com/)に参加して、世の中にはダメダメなタイトルがつけられた残念過ぎる質問がたくさんあることに気づきました。

残念過ぎる質問は質問者・回答者それぞれの時間を浪費し、お互いを不幸にします。

質問者予備軍の皆さんに良質な質問を繰り出してもらうための切っ掛けになればとの思いで、本記事ではそうした「ダメダメなタイトル」の類型を列挙し、筆者としての所見を述べます。

# ダメダメなタイトルいろいろ

## 「質問です」・「＊がうまくいきません」

回答側の心の声： **それで？**

タイトルにまともな情報が含まれていません。

回答する側としては、何をしたらいいのか、いやそれ以前に、自分に何とかなりそうな質問なのか、本文を読まないと見当がつきません。本文を読むまでもなくスルーしてしまう人も少なくないでしょう。

良い情報をもたらしてくれる人との出会いのチャンスを滅してしまう、良くないタイトルです。

## 「初心者です」・「【初心者】＊」

回答側の心の声： **あまえてんじゃないよ**

QAサイトで回答する側に回るタイプの人々の中には、いつまでも自分の足で歩こうとしないヒトの赤ん坊よりは、生まれ落ちるやいなや走り回る鹿の仔のようなタイプの人を好む傾向があります。こういうタイプの人々は、端から初心者アピールしてくる人を「自分の足を使おうとしない」怠慢な人間のように見てしまいます。

回答に応じてくれるとしても、残念ながら必要以上に「厳しい」口調になってしまいがちです。

もちろん全員がというわけではなく、分け隔てなく自称初心者に接している人たちもいますが、私の印象では、全体の半数以下です。

## 「【至急】＊」

回答側の心の声： **あんたの都合なんぞ、こっちは知らんわ!**


至急とか言われても、回答する側に急がされる筋合いも義務も義理もないのです。急ぎの対応を一方的に要求してくんじゃねえよとなります。

また、この種のタイトルの印象は前述の初心者アピールと重なります。つまり、自分自身での勉強に時間を使うことを厭うて安易に人に頼ろうとする「自分の足を使おうとしない」怠慢な人間とみなされてしまいます。

## 「課題が解けません」

回答側の心の声： **正直すぎるだろ。オブラートに包めや!**

宿題は自分でやるものです。知っていても教えません。

## 「おすすめの本を教えてください」

回答側の心の声： **そもそも何が知りたいの？**

質問者にとって自分の疑問は当然の疑問かもしれませんが、回答する側は知った話ではありません。どういう本がおすすめできるのかは、読み手の知識量・興味の方向・目的等々によって千差万別となるのであって、それをすっ飛ばしておすすめはと聞かれても、答えられるものではありません。

そして、このタイトルにも自助努力を回避したいという匂いが感じ取られるところです。

## 「なぜ＊は廃れたのでしょうか」・「なぜ＊では＊ができないのでしょうか」

回答側の心の声：

* **廃れたと思ってるのはお前とお前の取り巻きだけだわ!**
* **する必要がないか、お前ができないと思いこんでるかのどちらかやわ。**

表面上は質問の形を取っていますが、自分の考えを吐露したいだけに見えますね。

# タイトルをダメにする要素

まとめると、以下のいずれかに該当するタイトルはダメなタイトルと言えましょう。

* 説明的でない
* 丸投げ感が漂う
* 主張がむき出し

そんな意図はない。その批判は当たらない。そう思うかもしれません。心外かもしれません。ですが、回答する側はボランティアです。その気になってくれなければあなたを助けてはくれないのです。「誤解」をうまないよう、タイトルから質問の末尾まで、隅々まで気を使って質問してほしい。

はっきり言って、回答するより10倍気を使う面倒を乗り越えないとダメです。
【Python】UserWarning: Selenium support for PhantomJS has been deprecated, please use headless versions of Chrome or Firefox instead

スクレイピングをしようとしたら、`UserWarning: Selenium support for PhantomJS has been deprecated, please use headless versions of Chrome or Firefox instead`のエラーが出た

## 原因

PhantomJSが開発を中断しているため、この警告メッセージが出るらしいです。

## 対策

警告メッセージ通り、PhantomJSの代わりに、**Chrome**や**Firefox**のヘッドレスモードを用いるようにしましょう。

参考
https://techacademy.jp/magazine/21493
PlantUMLと俺と彼女の危険なシーケンス図

## シーケンス図とは
UMLの中で一番利用頻度が高い図（俺調べ）。

[wikipedia シーケンス図](https://ja.wikipedia.org/wiki/%E3%82%B7%E3%83%BC%E3%82%B1%E3%83%B3%E3%82%B9%E5%9B%B3)
> オブジェクト間のメッセージの流れを時系列的に表現する。イベントの発生順序やオブジェクトの生存（ライフライン、lifeline）、メッセージ（message）、イベントオカレンス（event occurrence）、実行オカレンス（execution occurrence）、相互作用オカレンス（interaction occurrence）などの記述によって、もっぱら時系列にもとづいたシステム分析・設計に使用する。

**オブジェクト間のメッセージの流れを時系列に**表現できるのが大変便利で設計の際には欠かせないが、**描くのが大変面倒くさい**という欠点がある。しょぼいツールで描くと、脳内の整理を行いながら設計をするのが目的なのか、納品物として誰も読まないキレイな図を後仕様として書くのが目的なのか分からなくなる事態に陥る事がある。

賢明な読者諸兄にはそのような不毛な作業ではなく、有益な設計作業に集中してもらいたいので**PlantUML**をオススメしたい。

## シーケンス図の大変面倒くさいところ
シーケンス図はその性質上、検討しながら作成を行うと大きな修正が発生することが多い。この無駄作業工数とストレスからシーケンスを書くのをやめる人間も多いのではないかと推察する。

品質を上げるために最も重要な事は**試行錯誤が容易にできること**、つまりは大きな修正を苦もなくできることと常々思っているが、**PlantUML**ではその試行錯誤が大変容易にできるのである。

## PlantUML
[VS code](https://code.visualstudio.com/) と [PlantUML](https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml) を利用すると大変面倒くさいシーケンス図が大変簡単に書ける。
[astah*](https://astah.change-vision.com/ja/manual/434-sequence-diagram.html) を使うと普通に書けるし、お金があれば Visio を使って少しだけ面倒くさくなく書くこともできるし Excel 方眼紙で楽しく書くこともできるが、**PlantUML**を利用すると**大変簡単に**書ける。

## 俺と彼女の危険なシステム図
UMLには興味があるしPlantUMLも使ってみたいが、シーケンス図を書くテーマが見つからない。そんな時には身近な題材を扱うとよいだろう。

身近な題材の例として、ある日の俺と彼女の危険なシーケンス図[^1]を示す。PlantUMLの文法は特に説明しないが読めばすぐに理解できると思う。

``` PlantUML
@startuml

hide footbox

title 危険なシステム

actor 俺 as me
participant TV as tv
participant 飯 as food
participant ソシャゲ as game
actor 彼女 as gf

me <<- gf :LINE
activate me
me -> tv : つける
activate tv
me -> food : 食う
me -> tv : 見る
me -->> gf : スタンプ
me <<- gf :LINE
me -> food : 食う
me -> tv : 見る
me -> game : ログイン
activate game
me <-- game : ログボ
me -> food : 食う
me -> tv : 見る
me -> food : 食う
me <- game : 広告
me -->> gf : スタンプ
me <<- gf :LINE
me -> me : 既読
me -> tv : 見る
me -> food : 食う
me <- game : リワード
me -> game : ガチャ
me <-- game : N
me -> game : やめる
deactivate game

@enduml
```

このソースコードで危険なシーケンス図が自動生成される。VS code であれば、ライブプレビューを表示しながら描ける。

![2020-07-29_02h14_22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136165/ce09fa3a-bf40-d65e-b839-be60b9182ee5.png)

そうこうしながら完成したシーケンス図は以下の様になった。

![危険なシステム.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136165/e91ecbc0-4e4c-a618-ef03-4b6f6a6a11ac.png)

## まとめ
[VS code](https://code.visualstudio.com/) と [PlantUML](https://marketplace.visualstudio.com/items?itemName=jebbs.plantuml) を利用すると大変面倒くさいシーケンス図が大変簡単に書ける。
今すぐVS code と PlantUMLをダウンロードしてシーケンス図を書いてみてはいかがだろうか。


[^1]: フィクションですよ
Raspberry Pi4で自動ログインを停止(ユーザー名=pi)

### 課題
Raspberry Pi4をセットアップ後、piユーザーを削除。
別ユーザー名で利用しているにも関わらずpiユーザーでの自動ログインで失敗していた。

### 対策試行
下記ファイルを修正すると良いと書いてある記事をトレースしたが変化なし....

```text
/etc/lightdm/lightdm.conf
/etc/systemd/system/autologin@.service
```

### 対策
```bash
$ sudo raspi-config
# テキストメニューが出るので 3 → 1 → B1 or その他 の順番で設定する
```

何が起きて是正されたのか確認したいところだが、もはや確認するスベ無し...
Railsでhamlを使う

#プログラミングの勉強日記
2020年7月29日　Progate Lv.226

#概要
　[こちらの記事](https://qiita.com/mzmz__02/items/61423e7259c4624f3010)で扱ったgemのhamlを説明する。hamlはHTML Abstraction Markup Languageの略で、簡単にHTMLのコードを書くことができる。erbと同じでRubyのコードを埋め込むこともできる。
　hamlには閉じタグが存在しないので、コードを簡単かつすっきり書くことができる。


#使い方
　hamlを使うためにGemfileを編集する

```:Gemfile
gem 'haml-rails'
```

 Gemfileを編集したら、hamlをインストールする。

```:ターミナル
bundle install
```

　これで、`index.html.haml`といったビューファイルの拡張子に`haml`を使えるようになる。

##すでにあるerbファイルをhamlファイルに変えたい場合

```:Gemfile
gem 'haml-rails'
gem 'erb2haml'
```

```:ターミナル
  erbファイルを残して変換
$ rake haml:convert_erbs

  erbを削除して変換
$ rake haml:replace_erbs
```

#基本的な書き方
　`%タグ名`と記述することで、開始タグと閉じタグに変換する。

```haml:index.html.haml
%html
 %body
  %div
   Hello World!
```


HTMLで以下のように変換されている

```html:index.html
<html>
 <body>
  <div>
   Hello World!
  </div>
 </body>
</html>
```

#hamlの書き方

##各タグの書き方

| hamlでの書き方     |   コンパイル後のコード(HTML) |  
|:-----------------:|:------------------:|
|  `%div`  |  `<div></div>`  |
|  `%html` |  `<html></html>`  |
|  `%meta` |  `<meta></meta>`  |
|  `%header`  |  `<header></header>`  |
|  `%footer`  |  `<footer></footer>`  |
|  `%table`  |  `<table></table>`  |
|  `%h1`  |  `<h1></h1>`  |
|  `%p`  |  `<p></p>`  |
|  `%a`  |  `<a></a>`  |
|  `%ul`  |  `<ul></ul>`  |
|  `%li`  |  `<li></li>`  |


##属性の書き方
　タグ内の属性は2つの書き方がある。

```haml:haml
%a(href='http://www~')
  リンク先の名前

%a{ href: 'http://www~' }
　リンク先の名前
```

HTMLでは以下のように変換されている


```html:html
<a href="http://www~">
  リンク先の名前
</a>
```

##IDとclassの書き方

```haml:haml
# idの指定
%div#id_name
  idを指定する

# クラスの指定
%div.class_name
  クラスを指定する
```

HTMLでは以下のように変換されている。

```html:html
<div id="id_name">idを指定する</div>

<div class="class_name">クラスを指定する</div>
```

idとクラスを両方指定することもできる。

```haml:haml
%div.contemt#content1
```

HTMLでは以下のように変換されている。

```htmll:html
<div class="content" id="content1">
</div>
```
MySQLインストール後、アクセス拒否 (Access denied for user ‘root’@’localhost’)

#myqslを起動し、アクセスする時、拒否られた。

```
$ mysql -u root
ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)
```
rootユーザーにアクセス権限がない

#mysql一旦停止

```
$ mysql.server stop
```

#権限を回避してアクセス

```
$ mysqld_safe --skip-grant-tables
2020-07-27T12:14:14.6NZ mysqld_safe Logging to '/usr/local/var/mysql/XXXX.err'.
2020-07-27T12:14:14.6NZ mysqld_safe Starting mysqld daemon with databases from /usr/local/var/mysql
```
mysqld_safe 
-> mysqldサーバーを起動するためのスクリプト

--skip-grant-tables 
-> 権限なしで起動

上記コマンドを入力したら、新しくターミナルタブを開いてください。(`command` + `T`)
#mysqlへアクセス
```
$ mysql -u root

mysql>
```

#権限確認

```
mysql> use mysql;
Database changed
mysql> select * from user;
```
use （データベース名）;
-> データベース選択

select (カラム) from (テーブル); 
-> 指定したテーブルから指定したカラムの情報取得
#userテーブル削除
```
mysql> truncate table user;
Query OK, 0 rows affected (0.00 sec)
mysql> flush privileges;
Query OK, 0 rows affected (0.01 sec)
```
truncate table （テーブル）; 

-> テーブル内のデータ全て削除

flush privileges; 
-> テーブルを再ロード

#rootユーザーを作成し、権限付与
```
mysql> create user 'root' identified by 'password';
Query OK, 0 rows affected (0.04 sec)

mysql> SELECT user, host FROM mysql.user;
+------+------+
| user | host |
+------+------+
| root | %    |
+------+------+
1 row in set (0.01 sec)

mysql> grant all privileges on *.* to 'root';
Query OK, 0 rows affected (0.01 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)

mysql> quit;
Bye

```
create user 'ユーザー名' identified by 'パスワード'; 
-> ユーザー作成 & パスワード設定

grant all privileges 
-> GRANT OPTION を除き、指定されたアクセスレベルにあるすべての権限を付与します。

on *.* to 'ユーザー名';
-> 特定のサーバー上のすべてのデータベースに適用されるグローバル権限を割り当てます。

#mysqld_sefe プロセス終了
```
$ ps
  PID TTY           TIME CMD
  508 ttys000    0:00.55 -bash
76932 ttys001    0:01.19 -bash
98076 ttys001    0:00.04 /bin/sh /usr/local/opt/mysql@8.0/bin/mysqld_safe --skip-grant-tables
98176 ttys001    1:03.36 /usr/local/opt/mysql@8.0/bin/mysqld --basedir=/usr/local/opt/mysql@8.0 --datadir=/usr/local/var/mysql --plugin-dir=/usr/local/opt/mysql@8.0/lib/plugin --skip-grant-tables --log-e
81032 ttys002    0:00.36 -bash
$ KILL 98076
$ KILL 98176
```
ps 
-> 現在実行されているプロセス一覧表示

KILL (PID) 
-> プロセス終了

#mysql再起動、再アクセス
```
$ mysql.server start
Starting MySQL
.. SUCCESS! 

$ mysql -u root -p
Enter password: 
```
docker-composeで超簡単にNuxt.jsで静的サイトの開発環境を構築する方法

# はじめに
今回用意するコンテナは4つです
必要なタイミングに応じてdocker-compose upコマンドで1つずつコンテナを起動します

1. nodeコンテナ
create-nuxt-appするために使用

1. devコンテナ
yarn devを実行し、サーバーを起動する
アプリ開発中に使用します

1. generateコンテナ
静的ファイルを出力するために使用します

1. dev_staticコンテナ
出力した静的ファイルをApatchサーバーを立ててローカルで確認するために使用します
出力結果はdevコンテナで起動中のものと同じ結果なはずなので、必要に応じて使用してください

# 環境

- Windows10 Pro バージョン2004
- WSL2
- Docker For Windows


# 1. docker-composeファイル準備

指定するimageのタグはこちらから最新版を取得
おすすめはalpineの最新です
https://hub.docker.com/_/node/

```yml:docker-compose.yml
version: '3'

services:
  node: &app_base
    image: node:14.5.0-alpine3.10
    tty: true
    working_dir: /var/www
    volumes:
      - ./src:/var/www # ./srcをコンテナ内の/var/wwwにマウントする
    environment:
      PORT: 3000
      HOST: 0.0.0.0
    restart: always # エラーなどでコンテナが落ちた際に自動で再起動してくれる
  dev:
    <<: *app_base
    ports:
      - "3000:3000"
    command: yarn dev # upする際に実行されるコマンド
  generate:
    <<: *app_base
    command: yarn generate # upする際に実行されるコマンド
  dev_static:
    image: httpd
    volumes:
      - ./src/dist:/usr/local/apache2/htdocs/
    ports:
      - "8080:80"
```

# 2. Nuxt.jsのプロジェクト作成
1. こちらでコンテナ内に入ります
`docker-compose run --rm node sh`

2. 必要なパッケージをインストール
`yarn global add create-nuxt-app`

    ※Nuxt.js modulesで`Vuetify.js`を選択する場合
    `apk add python make g++`


1. プロジェクトの作成

`create-nuxt-app ./`コマンドを実行し、対話形式でアプリのベースを作成

    ```
    $ create-nuxt-app ./
    ? Project name: test
    > test
    ? Programming language: JavaScript 
    > JavaScript
    ? Package manager: Yarn
    > Yarn
    ? UI framework: None
    > None
    ? Nuxt.js modules: (Press <space> to select, <a> to toggle all, <i> to invert selection)
    > 未選択でEnter
    ? Linting tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
    > 未選択でEnter
    ? Testing framework: None
    > None
    ? Rendering mode: Universal (SSR / SSG)
    > Universal (SSR / SSG)
    ? Deployment target: Static (Static/JAMStack hosting)
    > Static (Static/JAMStack hosting)
    ? Development tools: (Press <space> to select, <a> to toggle all, <i> to invert selection)
    > 未選択でEnter
    ```

1. コンテナから出る

```
exit
```


# 3. 実行

## 追記：ホットリロード有効化のため設定
Docker For Windows使用の場合、下記設定を追加実施

nuxt.config.jsに下記設定追加

```bash
watchers: {
    webpack: {
        poll: true
    }
}
```

1. 下記コマンドで起動します

    ```
    docker-compose up dev
    ```

1. アクセス

http://localhost:3000

# 4. 静的ファイル出力

1. 下記コマンドを実行すると`/dist`に出力される

```
docker-compose up generate
```

# 5. 出力した静的ファイルをApacheサーバーで確認

1. 下記コマンドで起動します

    ```
    docker-compose up dev_static
    ```

2. アクセス

http://localhost:8080/


# 6.参考
- [docker-composeで始めるnuxt.js](https://qiita.com/fussy113/items/ed7f56ff647a7f853bc9)
- [Nuxt.jsでさくっと静的サイトを作ってみよう](https://blog.photosynthesic.jp/2018/11/nuxt-js%E3%81%A7%E3%81%95%E3%81%8F%E3%81%A3%E3%81%A8%E9%9D%99%E7%9A%84%E3%82%B5%E3%82%A4%E3%83%88%E3%82%92%E4%BD%9C%E3%81%A3%E3%81%A6%E3%81%BF%E3%82%88%E3%81%86/)
- [Windows Docker環境でNuxtjsのhotreloadさせる方法](https://px-wing.hatenablog.com/entry/2019/12/23/001501)

以上です、お疲れさまでした。
エンジニアのための転職のための情報整理


・自分の情報・スキルの棚卸し

現在の職種：コーダー（4年目）
携わりたい業務：Vue.js、React、Laraelを利用したWebサイト／サービスの開発、Javaを利用したシステム開発

■ テクニカルスキル
【CSS】3.5年／スクラッチでの制作経験、指導経験
　複数のCSS設計の経験（SMACSS、BEM、OOCSS）、500ページを超えたサイトでも破綻しないCSS設計の経験
【HTML】3.5年／スクラッチでの制作経験、指導経験
【jQuery】3.5年／スクラッチでの制作経験、プラグインのカスタム経験
【Javascript】1年／参考サイトを見ながらの制作経験
【Bootstrap】1年／スクラッチでの制作経験、指導経験
【Git／GitHub】2年／commit、push、PullRequest、Merge、Issuesなどを使った開発経験、指導経験、コードレビュー経験
【nodejs／npm／gulp】2年／参考サイトを見ながらの環境構築、開発経験
【Sketch／Photoshop／Illustrator／XD】3.5年／スライス可能



転職活動
「転職 フロントエンド 東京」で検索

・doda
https://doda.jp/keyword/%E3%83%95%E3%83%AD%E3%83%B3%E3%83%88%E3%82%A8%E3%83%B3%E3%83%89%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%80%80%E6%9D%B1%E4%BA%AC/

・mynavi
https://tenshoku.mynavi.jp/shutoken/list/p13/o1G145/

・indeed
https://jp.indeed.com/%E3%83%95%E3%83%AD%E3%83%B3%E3%83%88%E3%82%A8%E3%83%B3%E3%83%89%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E9%96%A2%E9%80%A3%E3%81%AE%E6%B1%82%E4%BA%BA%E6%9D%B1%E4%BA%AC%E9%83%BD

・find-job
https://www.find-job.net/word/hu/%E3%83%95%E3%83%AD%E3%83%B3%E3%83%88%E3%82%A8%E3%83%B3%E3%83%89%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2/

・Wantedly



「マイナビ転職エージェント」に登録してみた

■ エージェントとのやりとりの流れ
・良いと思った求人情報にエントリーする
・エージェントから電話がくる（求人情報を出している会社の人）
・エージェントとZoomなどで会話する（過去の経歴や転職理由など色々話す1-2時間）
・エージェントがオススメの転職先を見つけてくる（5 - 10社）
・勧めてくれた会社に順位をつけて、応募したい旨をつたえる（履歴書と職務経歴書を提出）
・書類選考→社長面接→内定

転職エージェントを使うメリット
数ある求人の中から、自分に合いそうな求人を見つけてくれる情報力と職務経歴書の書き方のアドバイスをもらえること

＜職務経歴書を書くときの注意点＞
・職務経歴はWEB以外も含めて全て記入
・スキルを書くときは、何年携わってどんなことができるようになったか記述
・SESは業務委託とは言わずに常駐という
・今までの経験を語る
・今後のなりたい姿を語る

行動することが転職への一番の近道！！！