OmniAICreator/Qiita-1.07M huggingface dataset:
機械学習 optimizer（最適化アルゴリズム）

optimizerについて学習したので，簡単にメモ．

# optimizerとは
損失を効率よく最小化するためのアルゴリズム．Kerasではoptimizerで指定．

## 勾配降下法（最急降下法）
<img title='image.png' alt='image' src='/attachments/f394f777-83f7-4058-a4d5-fd28fcb4c1a0' width="190" data-meta='{"width":190,"height":53}'>
傾きと逆向きに降りる．

## SGD（確率的勾配降下法）
訓練データからランダムに抽出し，学習する．局所解に陥りづらい．勾配降下法のランダム版．欠点は，1つの勾配の計算が終わらないと次の勾配に移れず，並列処理できないこと．

## ミニバッチ学習SGD
更新で使うデータ数を1つから16個や32個などに増やし，並列に学習させる．大分改善されたが，Pathological Curvatureの問題が残る（一度の更新幅が大きすぎると収束しない．オーバーシュート．）

## モーメンタム（Momentum）
<img title='image.png' alt='image' src='/attachments/934283ec-f90a-4771-9679-ff2f2858ba3d' width="267" data-meta='{"width":267,"height":59}'>

SGDに慣性的な性質を持たせたもの．今までの変化値を考慮することで，振動のような急激な変化の影響を抑える．移動平均．

## Nestrovの加速勾配法
<img title='image.png' alt='image' src='/attachments/86217788-2191-411a-a2ac-0dcef6187de1' width="348" data-meta='{"width":348,"height":66}'>

先に慣性項で重みを更新させてから勾配をとって更新する．あらかじめどの方向へ向かうのか考慮する．

## AdaGrad
<img title='image.png' alt='image' src='/attachments/b024e3f6-d894-435c-bb92-30dcf842982d' width="237" data-meta='{"width":237,"height":114}'>
1つ1つの重みの学習率を適応的に変化させる．大きく動いたパラメータの学習率は段々小さくなる（が，いずれ0になってしまい学習できなくなってしまう問題もあった）．なだらかな勾配に対応す

## RMSProp
<img title='image.png' alt='image' src='/attachments/94bd442c-7f9b-4527-b23c-68d41e068aae' width="234" data-meta='{"width":234,"height":94}'>

ε：ゼロ除算を避けるための極めて小さい値

SGDの振動を抑えるために，モーメンタムでは重みを調整したが，RMSPropでは学習率を調整する．
また，AdaGradでは過去の勾配を均一に加算していたが，指数移動平均によって直近の勾配を大きく反映させる．

### AdaDelta
<img title='image.png' alt='image' src='/attachments/826f2c51-c1b0-4dcd-af72-b28597d52635' width="276" data-meta='{"width":276,"height":204}'>

AdaGrad, RMSPropの改良．学習率ηもなくなっている．より直近の勾配を優先して反映させる．

## Adam
<img title='image.png' alt='image' src='/attachments/0664715b-c736-4b30-976a-0a63ed1751bb' width="239" data-meta='{"width":239,"height":124}'>

モーメンタムとRMSPropの良いとこどり．2014年から現在に至るまでデファクトとなっている．
Matlabのscatter/scatter3をPythonで

これができないと話にならない、2D / 3D 散布図。
MATLABでいうところのscatterやscatter3相当のもの。

matplotlibを使ってやる。
２D/3Dの差はaxisを2Dで作るか3Dで作るかを変えるだけで、あとはほとんど一緒。

#2次元の場合
```python
import numpy as np
import matplotlib.cm as cm
import matplotlib.pyplot as plt

x = np.random.rand(500, 2)
y=((x-0.5)**2).sum(axis=1)**0.5

fig = plt.figure(figsize=(6.4,4.8),dpi=72)
    # figsizeはインチ単位。デフォルト(6.4,4.8)　
    # dpiはデフォルト 100

#2d散布図
ax = fig.add_subplot(1, 1, 1, title='Title', xlabel='X', ylabel='Y')
    #titleなどはあとからax.set_title() ax.set_xlabel などで変更可
sc = ax.scatter(x[:, 0], x[:, 1], vmin=0, vmax=1, c=y, cmap=cm.jet)

#カラーバー
cb=fig.colorbar(sc)
plt.show()
fig.savefig('2d.png')
```
結果
![2d.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1063124/4c75e569-c338-b2e0-bd9b-375dc7932be6.png)


#3次元の場合
```python
#カラーバー
cb=fig.colorbar(sc)
plt.show()
fig.savefig('/Users/miyawaki/Desktop/2d.png')


import numpy as np
import matplotlib.cm as cm
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d.axes3d import Axes3D

x = np.random.rand(500, 3)
y=((x-0.5)**2).sum(axis=1)**0.5

fig = plt.figure(figsize=(6.4,4.8),dpi=72)
    # figsizeはインチ単位。デフォルト(6.4,4.8)　
    # dpiはデフォルト 100

#3D散布図
ax = Axes3D(fig)
sc=ax.scatter(x[:, 0], x[:, 1], x[:, 2], c=y, cmap=cm.jet)

#タイトルと軸ラベル
ax.set_title("Title", fontsize=8)
ax.set_xlabel("X", fontsize=7)
ax.set_ylabel("Y", fontsize=7)
ax.set_zlabel("Z", fontsize=7)
#tick labelのフォントサイズ
plt.tick_params(labelsize = 6)

#カラーバー　0.6倍に縮小
cb=fig.colorbar(sc,shrink = 0.6)
    #水平にするときはorientationにhorizontalを追加
    #cb=fig.colorbar(sc,shrink = 0.6, orientation="horizontal")

#カラーバーのlabel、tick label
cb.set_label("Color", fontsize=7)
cb.ax.tick_params(labelsize=6)

plt.show()
fig.savefig('3d.png')
```
結果
![3d.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1063124/ed703a2b-4a98-5b49-63cd-1e6d61daccb4.png)


…微調整はおいおい調べましょう。
CentOS8からJUNIPERにsshログインできなくなった

##はじめに

企業向けスイッチの大手のJUNIPER社のスイッチにCentOS7からsshでログインできてたのですが、CentOS8からはログイン出来ない事に気がつきました。

```
$ ssh USERNAME@HOSTNAME
Connection closed by 192.168.xx.xx port 22
```

OSはCentOS8 Streamの最新(2021年1月現在)です。

JUNIPERは JUNOS 12.3R12-S13.1です。

##SSHの設定の問題
最初アクセス制限してたかなぁと思ったのですが、sshのport forwardでCentOS7から22番を転送してみたのですが、ログインできました。

どうやらSSHクライアント側の問題のようです。

試行錯誤の結果、CentOS8では暗号化方式を明示的に指定(-c)したらログインに成功しました。引数で渡したchacha20-poly1305(?)というのは何なのか理解してないのですが、CentOS7でverboseモード(-v)にして確認したところchacha20-poly1305で暗号化されてました。

```
$ ssh USERNAME@HOSTNAME -c chacha20-poly1305@openssh.com
```

以上。
人感センサで動体を正確にカウントする

#この記事について
人感センサーを使って検知したことをプログラムで出力しようと思います

#環境
・Raspberry Pi zero
・HC-SR501

#実装
###センサの配置
![sensor_placement2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557268/28addb3d-9790-fc51-2ddc-e6447f8e16fb.png)
小型マイコンを動かすためにAC電源が一つ必要になるため，図のようにRaspberryPiはAC電源の付近に設置します．RaspberryPiにHC-SR501を接続し，モーション検知ができる状態にします．

###プログラム
```sensor.py
from datetime import datetime
import time
import RPi.GPIO as GPIO

#インターバル
INTERVAL = 2
#スリープタイム
SLEEPTIME = 10
#使用するGPIO
GPIO_PIN = 18

GPIO.setmode(GPIO.BCM)
GPIO.setup(GPIO_PIN,GPIO.IN)

if __name__ == '__main__':
    try:
        print("処理キャンセル：CTRL+C")
        cnt = 1
        while True:
            #　センサー感知
            if(GPIO.input(GPIO_PIN) == GPIO.HIGH):
                print(datetime.now().strftime('%Y/%m/%d %H:%M:%S') +
                " : " + str("{0:05d}".format(cnt)) + "回目の人感知")
                cnt = cnt + 1
                time.sleep(SLEEPTIME)
            else:
                print(GPIO.input(GPIO_PIN))
                time.sleep(INTERVAL)
    except KeyboardInterrupt:
        print("終了処理中...")
    finally:
        GPIO.cleanup()
        print("GPIO clean終了")
```

#実行結果
![sensor.py 実行結果.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/557268/38e24bbd-8d0a-329e-2bb9-84938b17ae77.png)

Pythonスクリプトを実行して、モーション検知すると、上の図のように出力されます．インターバルを2秒，スリープタイムを10秒に設定することで，一人に対しての検知が重複することを防いでいます．sensor.pyの実行により，人を検知した日時と何回目のカウントなのかを表示することができました．
firebase deploy で 「HTTP Error: 404, Requested entity was not found.」

※急にfirebase deployができなくなったのでメモ

firebase deploy でエラーになる。

``` bash
$ firebase deploy

=== Deploying to 'XXXXXXXX-app'...

i  deploying hosting

Error: HTTP Error: 404, Requested entity was not found.
```

## 解決策
firebase-toolsを最新化する。

``` bash
npm install -g firebase-tools
```
Apple Developer デバイスリセット

Apple Developerの年度更新に伴い、デバイスのリセットを行いました。

幾つかのブログやQiita記事を参考にしましたが、実施した際に気づいた事を記載します。

+ リセットのメニューが出るタイミング
　Membershipの表示が「Device Reset Date January 28, 2021」となっていました。
  実際にメニューが出たのを確認したのは 1/29 の　09:20　でした。
　1/28の 22:00頃に確認した際には表示されてなかったので、米国時間の 1/28 0:00からではないようです。
　GMT の翌日からなのでしょうか？

+ リセット処理を行うUI表示
　参考にしたブログ等では「Get Started」というボタンが表示されるとされていましたが、
　Before adding new devices, make sure your device list is updated for the new membership year. You have the option to remove devices from your list.
　のメッセージの右に「Continue」のボタンが表示されていました。
![deviceReset01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333360/3fd77abd-3fa9-1e25-13bb-d9c4525e4246.png)

　「Continue」ボタンを押すと
　Updete your device list
  という表示で
　　Select the devices you'd like to keep for this membership year and deselect the devices you'd like remove.　（以下略）
　と、繰り越したいなら選択、削除したいなら選択解除してね　とのコメントの下に、デバイスリストが表示されました。
　なお、デバイスは「すべて選択されて」表示されていました。
![deviceReset0b2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333360/c06b2bf4-6035-c36e-6a14-e80bbd92e70c.png)
　不要なデバイスのチェックを外して「Continue」を押すと確認ダイアログが表示されますので、そこで繰り越すデバイスを確認の上、リセットの実施が行いました。

 de
[Rails] Errno::ENOENT - No such file or directory - bs_fetch:atomic_write_cache_file:rename

キャッシュが残っているのが原因っぽい。だから、それを消したらok

```bash
 docker-compose down
 rm -rf tmp/cache/bootsnap-*
 docker-compose up -d 
```

参考
https://github.com/Shopify/bootsnap/issues/177#issuecomment-604981988
GraphQL-RubyでInterfaceTypeを活用する


Graphql-RubyでInterfaceTypeを使う方法を説明します。
#Interface Typeって?
Interface TypeはObjectTypeから呼び出して継承させることができます。
#例
と言ってもよくわからんので、実際にActiveRecordInterfaceを作ってみます。

```active_record_interface.rb
module InterfaceTypes
  module ActiveRecordInterface
    include InterfaceTypes::BaseInterface
    description 'Active Record Interface'

    field :id, ID, null: false
    field :updated_at, GraphQL::Types::ISO8601DateTime, null: false
    field :created_at, GraphQL::Types::ISO8601DateTime, null: false
  end
end
```
上記はactive recordを利用すると必ず生成されるカラムを定義しています。
ここで定義したInterfaceをObject Typeで継承することができます。

```object_type.rb
# frozen_string_literal: true

module ObjectTypes
  class UserType < ObjectTypes::BaseObject
    implements InterfaceTypes::ActiveRecordInterface

    field :name, String, null: false
  end
end
```
interfaceをimplementsすることで、idやupdate_atをわざわざ書かなくてもfieldとして定義してくれるので、非常に便利です。
interface typeに他にもいろいろ使い道がありそうですが、まだ使ってないのでこれからいろいろ試したいと思います。
GitHub Actionsでブランチ名を扱う方法

# イベント別解説

起点とするイベントによって方法が異なるため、イベント別に解説します。
全ての例でechoコマンドでブランチ名を出力しています。

## プルリクエストの時

```yaml
on:
  pull_request:
    types: [opened, closed]

jobs:
  debug:
    runs-on: ubuntu-20.04
    timeout-minutes: 3
    steps:
      - name: Print branch name
        env:
          BRANCH_NAME: ${{github.head_ref}}
        run: echo $BRANCH_NAME
```
- 以下2つの変数はプルリクエストを起点としたときだけ使用可能です。
    - マージするブランチ名は `${{github.head_ref}}`
    - マージ先のブランチ名は `${{github.base_ref}}`
- typesを指定することで対応するアクティビティを指定できます。詳しくは[こちら](https://docs.github.com/ja/actions/reference/events-that-trigger-workflows#pull_request)。
- 「プルリクエストがマージされた時」というアクティビティは存在しませんが、対応は可能です。詳しくは[こちら](https://qiita.com/okazy/items/7ab46f2c20ec341a2836#comment-5b11432f6d5376f635c6)。

## プッシュされた時

```yaml
on: push

jobs:
  print:
    runs-on: ubuntu-20.04
    timeout-minutes: 3

    steps:
      - name: Extract branch name
        shell: bash
        run: echo "::set-output name=branch::${GITHUB_REF#refs/heads/}"
        id: extract_branch

      - name: Print branch name
        env:
          BRANCH_NAME: ${{ steps.extract_branch.outputs.branch }}
        run: echo $BRANCH_NAME
```

https://stackoverflow.com/questions/58033366/how-to-get-current-branch-within-github-actions から引用、一部改変

- ブランチ名は環境変数 `GITHUB_REF` から抽出する必要があります。
- `::set-output name=branch::` の記法はGitHub Actionsのメタデータ構文です。詳しくは[こちら](https://docs.github.com/ja/actions/creating-actions/metadata-syntax-for-github-actions)。
- `${GITHUB_REF#refs/heads/}` の記法はShell Parameter Expantionを使ったものです。
- 使える環境変数については[こちら](https://docs.github.com/ja/actions/reference/environment-variables)。

## ブランチが削除された時

- リポジトリのデフォルトブランチ（main）しか取れないので省略します。

# もともとやりたかったこと

- [こちら](https://dev.classmethod.jp/articles/s3-file-up-down-from-github-actions/)の記事を元に、
    - GitHubへのプッシュ時に、S3にブランチ名でprefixを分けてファイル配置
    - GitHubでプルリクエストのクローズ時に、プッシュ時に配置したファイルを削除
【備忘録】Javascriptのshift, slice, spliceの違い

#shift
shiftを使った配列から１要素目を削除して、戻り値としてその要素を返す。
元配列への影響：有

```javascript
let a = [1,2,3];
let b = a.shift();  //a=[2,3] b=[1]
```

#slice
slice(start, [end])は 
start: 取り出す先頭のインデックス
end: 取り出す最後のインデックス＋１
元配列への影響：無

```javascript
let a = [1,2,3];
let b = a.slice(1);  //a=[1,2,3] b=[1]
let b = a.slice(0,1);  //a=[1,2,3] b=[1]
let b = a.slice(1,2);  //a=[1,2,3] b=[2]
```

#splice
slice(start, number)は 配列の一部を削除する。
(実際には置換や挿入もできる。ここでは比較のため削除のみ)
start: 取り出す先頭のインデックス
number: 取り出す要素数
元配列への影響：有

```javascript
let a = [1,2,3];
let b = a.splice(0,1);  //a=[2,3] b=[1]
let b = a.splice(1,2);  //a=[1] b=[2,3]
```
rubocopの「The use of eval is a serious security risk.」の私的解釈

### evalを使うとrubocopから以下の警告が出る
```
 C: Security/Eval: The use of eval is a serious security risk.
```

### evalの動作
　evalとはそもそもどんな動作をするのか？
 
> 文字列 expr を Ruby プログラムとして評価してその結果を返します。　

module function Kernel.#eval　より
https://docs.ruby-lang.org/ja/latest/method/Kernel/m/eval.html

 evalの引数に与えた文字列をrubyプログラムとして実行してくれる。

```
a = nil
eval('a = RUBY_RELEASE_DATE')
p a #=> "2007-03-13"
```

　便利。

### なぜevalを使うことがリスクなのか（私的解釈）
　rubocopから「The use of eval is a serious security risk.」の警告をもらった時は、なにがリスクなのか分からなかった。
　しかし、よくよく考えてみると以下のことをリスクと言っているのではないかと思ったのでまとめる。

#### 読みにくい
 evalを使う場合と使わない場合を比較してみる。

```
def fuga
　p 777 
end
# 実行
fuga
=> 777
```

```
eval('def fuga;p 777 end')
fuga #=> 777
```
　普通に書いてある方が読みやすいように思う。

#### 悪意あるコードが生成される可能性がある
 外部のファイルを読み込むeval

```
eval('raise RuntimeError', binding, 'XXX.rb', 4)
#=> XXX.rb:4: RuntimeError (RuntimeError)
#       from ..:9
```
　外部のデータからコードを生成し実行する場合、悪意あるコードが生成されないように細心の注意を払う必要がある。
　上記は外部のファイルを読み込んでいるが、他にもDBとかユーザの入力とか、外部のデータからコードを生成して実行することもできる。
　しかし、evalを使わないで書く場合と比べて読みにくいので、どのデータがどのように加工されるか覚えておいたり理解したりは難しい。なので悪意あるコードが実行される可能性が高くなる。

### まとめ
　evalを使ったコードは、多彩な動きができるためその動きを把握しにくいので悪意あるコードが生成される可能性があること、また読みにくいのでそれに気付きにくいということが「リスク」なんだと考えた。
　evalを使わずに済むなら使わないで実装を行いたい。
shift_jisのファイルをutf-8に変換する

お国のestatsあたりからダウンロードしたcsvファイル等が結構shift-jisだったりするので。

```
 ❯❯❯ iconv -f SHIFT_JIS -t UTF-8 before > after
```

SHIFT_JIS と UTF-8のところはタブ補完で行きました。
蛇足ですがtmuxのコピーモードがxselをインストールしてなかったので機能しなかったのはご愛嬌。
WSL2でhostsの書き換え

# やりたいこと

LinuxやMacみたいに、Windows + WSL2 でも hostsファイルを書き換えて、色んなドメイン名をローカルで使いたい

# How to

1. WSL2からWindowsのIPを確認
    - `cat /etc/resolv.conf | grep nameserver | cut -d ' ' -f 2`
2. `C:\Windows\System32\drivers\etc\hosts` を編集
    
    ```C:\Windows\System32\drivers\etc\hosts
172.21.160.1 kuchitama.com
172.21.160.1 test1.kuchitama.com
    ```
3. WSL2を再起動
    - `wsl --shutdown`
4. 完了



# 参考記事

[how to associate windows hosts file entry with process running on WSL](https://stackoverflow.com/questions/63890038/how-to-associate-windows-hosts-file-entry-with-process-running-on-wsl)
Raspberry Pi 4にのせたUbuntuMATEの解像度変更

## ラズパイの故障
Ubuntuサーバー+UbuntuMATEで使用していたRaspberry Pi 4が故障してしまい、起動時から勝手に解像度"640x480"で表示するように。解像度を変更しようにも設定には"640x480"の項目しかないため、元の"1920x1080"へ変更できない。画面に写り切れてない部分も多く使用できる状況ではなくなったので、調べることに。

## 結論
自分の場合は、以下のコマンドを端末で実行することで解決できました。

```
$ xrandr --newmode "1920x1080_60.00"  173.00  1920 2048 2248 2576  1080 1083 1088 1120 -hsync +vsync
$ xrandr --addmode HDMI-1 1920x1080_60.00
$ xrandr --output HDMI-1 --mode 1920x1080_60.00
```

## 経緯
Raspberry Piの解像度関係の問題は、多くが"raspi-config"か"/boot/config.txt"で治るよう。（Raspberry Pi OSの場合はこれだと思われる。）
しかし該当するコマンドやファイルが存在しなかったので、Ubuntuの解像度変更に関して調べてみたところ、再起動せずとも実行のできるxrandrというライブラリ・コマンドを発見。

### 新しい解像度を設定
新しい解像度を設定する際の出力モードの情報を確認します。

```
$ cvt 1920 1080
#1920x1080 59.96 Hz (CVT 2.07M9) hsync: 67.16 kHz; pclk: 173.00 MHz
Modeline "1920x1080_60.00"  173.00  1920 2048 2248 2576  1080 1083 1088 1120 -hsync +vsync
```

解像度を設定します。

```
$ xrandr --newmode "1920x1080_60.00"  173.00  1920 2048 2248 2576  1080 1083 1088 1120 -hsync +vsync
```

### 解像度をモニターに登録
モニターの名前を確認します。

```
$ xrandr
Screen 0: minimum 320 x 200, current 1920 x 1080, maximum 7680 x 7680
HDMI-1 connected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 0mm x 0mm
   1024x768      60.00  
   800x600       60.32    56.25  
   848x480       60.00  
   640x480       59.94  
   1920x1080_60.00  59.96* 
```

設定した解像度が表示されているのが分かると思います。
connectedの前に書かれている文字列がモニターの名前ですので、新規に設定した解像度をこれに登録します。

```
$ xrandr --addmode HDMI-1 1920x1080_60.00
```

### 解像度変更

ここまですれば、GUI操作（パソコン内のシステム設定画面）からも変更ができますが、コマンドラインからの変更方法も載せておきます。シェルスクリプト等で自動化する際に使えます。

```
$ xrandr --output HDMI-1 --mode 1920x1080_60.00
```


ディスプレイの解像度と接続されているモニターの名前さえ分かれば、その部分を差し替えることで対応可能かと思います。

## 終わりに
自分がうまく調べられずハマったので、後続の人の参考になれば幸いです。

## 参考サイト
https://ameblo.jp/ekispresso/entry-11532367928.html
https://www.bioerrorlog.work/entry/change-resolution
初めてのRaspberry Pi Pico ① C言語でLチカ　ver.2

　https://pico.raspberrypi.org/files/getting_started.pdf
に従って、ラズパイ4に開発、デバッグ環境をインストールします。この作業で必要なのは、次の三つです。

- ラズパイ
- USBケーブル
- Pico

![IMGP0132b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/721c99d7-d03b-1f65-66d2-3e709d994a2a.png)

###準備はたったの4ステップで完了
　ラズパイ4の2GBモデルを使っています。SDメモリは32GBです。現時点で、January 11th 2021が最新のOSですが、このマシンはその前のダウンロード版を、更新しながら使っています。

```shell
sudo apt-get update
sudo apt-get upgrade -y
```

　リブート後、まずwgetをインストールします。

```shell
sudo apt install wget
```

 　インストールに必要なことが記述されたスクリプトを取得します。

```shell
 wget https://raw.githubusercontent.com/raspberrypi/pico-setup/master/pico_setup.sh
```

　実行権を付けます。

```shell
 chmod +x pico_setup.sh
```

　実行します。

```shell
 ./pico_setup.sh
```

　全部コピペでターミナルに貼り付けています。
　30分ほどで作業が完了します。df -hで見ると残りの容量は45%ぐらいになっていました。VScodeやOpenOCDも入ります。
　リブートします。

```shell
reboot
```

###blinkをコンパイル
　ビルドされているので、何もしません。

~~　cmakeとGNU Embedded Toolchain for Armをインストールします。~~


~~sudo apt update~~
~~sudo apt install cmake gcc-arm-none-eabi libnewlib-arm-none-eabi build　essential~~


~~　移動します。~~

~~cd pico~~
~~cd pico-examples~~


~~　pathを通します。~~

~~export PICO_SDK_PATH=../../pico-sdk~~

~~cmake ..~~


~~　makeを実行します。~~


~~cd blink~~
~~make -j4~~


###ファイルをコピーして実行
　ボード上にあるBOOTSELを押したまま、USBケーブルでラズパイとPicoをつなぎます。ラズパイの画面上にドライブがマウントされます。BOOTSELから手を放します。
![pico201.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/abe73a65-9320-517a-6bca-61963262c004.png)

　File Managerを立ち上げます。/home/pi/pico/pico-examples/build/blinkまで下りていきます。ここにあるblink.uf2をRPI-RP2ドライブへドラッグします。
![pico202.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/407635/f128ec7e-545e-946b-c930-36ed3d5a4b61.png)

　RPI-RP2ドライブは画面から消え、Picoはリセットがかかって、USBコネクタの横にある黄色のLEDが点滅します。
　/home/pi/pico/pico-examples/blinkディレクトリのblink.cをテキスト・エディタで開き、sleep_ms()の時間を変更して保存します。
　/home/pi/pico/pico-examples/build/blinkのディレクトリで、

```make -j4
```

を実行し、そのディレクトリに作られた新しいblink.uf2をRPI-RP2ドライブへドラッグします。点滅の時間が変われば、うまく動いています。

```cpp
/**
 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include "pico/stdlib.h"

int main() {
    const uint LED_PIN = 25;
    gpio_init(LED_PIN);
    gpio_set_dir(LED_PIN, GPIO_OUT);
    while (true) {
        gpio_put(LED_PIN, 1);
        sleep_ms(1000);
        gpio_put(LED_PIN, 0);
        sleep_ms(2000);
    }
}
```
【Azure】Azure arcについて調べてみた

|切り口|内容|公開日時|ソース|URL|
|:----|:----|:----|:----|:----|
|マルチクラウドの定義|ARCは2019年11月に発表|2020.07.16|オンプレもエッジもクラウドも一元管理、MSやIBMが狙う「新たな囲い込み」|https://xtech.nikkei.com/atcl/nxt/column/18/01363/071400003/|
|Arcのコンセプト|クラウド、ユーザー企業のデータセンター、そしてエッジなどインフラの置かれた環境を問わず、すべての企業システムのインフラ管理を目指したサービス|2020.07.16|オンプレもエッジもクラウドも一元管理、MSやIBMが狙う「新たな囲い込み」|https://xtech.nikkei.com/atcl/nxt/column/18/01363/071400003/|
| |オンプレミス環境で自社製品を利用可能にするハイブリッドクラウド環境|2020.07.14|オンプレミスに残るシステムを奪え、クラウドベンダーが「地上戦」に注力|https://xtech.nikkei.com/atcl/nxt/column/18/01363/071200001/?P=2|
|なぜつかうのか|・既存のリソースを Azure Resource Manager に投影することで自分の環境全体を一元的に管理できます。
・Azure 内で実行されているかのように、仮想マシンや Kubernetes クラスター、データベースを管理できる|2020/09/23|Azure Arc の概要|https://docs.microsoft.com/ja-jp/azure/azure-arc/overview|
|どうやって使うのか（実装手順）|・Azure Stack HCI：オンプレミス、クラウドなど全体を管理できるようになる| | | |
|どのような機能があるか|・Azure Policy を使用して、Kubernetes クラスターのコンプライアンスと構成をゼロ タッチで実行する。|
||・Azure portal、Azure CLI、Azure PowerShell、Azure REST API のどれを使用していても、統合されたエクスペリエンスで Azure Arc 対応リソースを表示する。|2020/09/23|Azure Arc の概要|https://docs.microsoft.com/ja-jp/azure/azure-arc/overview|
| |・Azure Arcは開発ツールやCI（継続的インテグレーション）パイプラインを使い、複数のKubernetesクラスターにアプリを自動でデプロイする。|2020.12.07|コンテナ管理ツールのKubernetesがさらに進化、次世代の「OS」に|https://xtech.nikkei.com/atcl/nxt/column/18/01478/111800006/?P=4|
| |・ Azureの一部の機能をオンプレミス環境で利用可能にするAzure Stack Hub||||
||・エッジ向けの「Azure Stack IoT」||
||・Windowsベースのシステムを移行するための「Azure Stack HCI」|2020.07.16|オンプレもエッジもクラウドも一元管理、MSやIBMが狙う「新たな囲い込み」|https://xtech.nikkei.com/atcl/nxt/column/18/01363/071400003/|
|どこまでカバーできるか|オンプレ、他クラウド、エッジ|2020/09/23|Azure Arc の概要|https://docs.microsoft.com/ja-jp/azure/azure-arc/overview|
|Arcを一言でいうと？|マルチクラウドとオンプレミスの管理プラットフォーム|2020/09/23|Azure Arc の概要|https://docs.microsoft.com/ja-jp/azure/azure-arc/overview|
|何を管理できるか|サーバー - Windows または Linux を実行するマシン (物理マシンと仮想マシンの両方)。||
||Kubernetes クラスター - 複数の Kubernetes ディストリビューションをサポート。
||Azure データ サービス - Azure SQL Database および PostgreSQL Hyperscale サービス。|2020/09/23|Azure Arc の概要|https://docs.microsoft.com/ja-jp/azure/azure-arc/overview|
|コンテナへのマイグレーション機能はあるか？|・ない
||・しかし、VMの管理もできるので、必要ないのかもしれない| | | |
jqを使いながら、aws cliで取得した一時認証情報を環境変数に設定する

# はじめに
AWS CLIを使用してIAMロールを引き受ける方法は、公式ドキュメントの通り[^iam-assume-role-cli]ですが、コマンド結果から都度コピペで `AWS_ACCESS_KEY_ID` などの環境変数を設定するのは手間です。

本記事では、得られたjsonをjqでパースし、環境変数を設定する方法を説明します。

## 必要なもの
- awscli
- jq
 
AWS CloudShell には両方入っているので、とりあえず試すにはおすすめです。

## おことわり
`~/.aws/config` を使うことでより簡単に設定できます[^aws_config]が、一時的な対応とかで必要になるケースがあり、本記事を作成しました。

# 手順
以下のbashスクリプトのとおりです。
`ROLE_ARN` と `SESSION_NAME` を設定し実行するだけです。

```bash
# def var
ROLE_ARN=arn:aws:iam::${ACCOUNT_ID}:role/${ROLE_NAME}
SESSION_NAME=some-session

# command
eval $( 
  aws sts assume-role --role-arn $ROLE_ARN --role-session-name $SESSION_NAME \
  | jq -r '[
      "export AWS_ACCESS_KEY_ID=" + (.Credentials.AccessKeyId|tostring),
      "export AWS_SECRET_ACCESS_KEY=" + (.Credentials.SecretAccessKey|tostring),
      "export AWS_SESSION_TOKEN=" + (.Credentials.SessionToken|tostring)
    ]
    | join(";")
    '
)
```

正しく設定できているかは ```aws sts get-caller-identity``` で確認してください。

[^iam-assume-role-cli]: https://aws.amazon.com/jp/premiumsupport/knowledge-center/iam-assume-role-cli/
[^aws_config]: https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-role.html
【Unity uGUIメモ】上端は固定だけど下端は親UIに追従するAnchorの設定方法

#　はじめに
子UIの上端は固定・下端は親UIに追従するようなAnchorの設定方法を紹介します。
![03_stretch2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44288/4bf41e3e-5f23-1f4e-61e6-17bce25e2cc1.gif)

# 設定方法
子UIのAnchorをドラッグして、親UIの下端に合わせます。
![03_stretch_settings.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44288/fb17f948-c3a9-1254-8776-3ad85e7be9b1.gif)

親UIの高さが変化したとき、子UIの上端は固定、下端は親UIの下端に追従するようになります。
![03_stretch.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44288/c37a6a1e-a7ac-c266-68cb-c8f9cf658c9f.gif)
【Swift】Firebase StorageのデータをSDWebImageで表示する方法

#はじめに

画像をFirebase Storageにアップロードし、
SDWebImageで取得しようとしたところ表示されず・・・。

解決するのに3時間くらいかかりました・・・。

同じような状態の方の参考になればなと思い、
備忘録がてら共有します！

環境
・Swift version 5.3
・XCode version 12.3

##前提として

・Firebaseにアプリを登録していること
・CocoaPodsでFirebaseUIをインストールしていること
（Firebase/StorageやSDWebImageなど個別でも構いません）


##コード

Storageに画像データを格納する際は、
UIImage型ではなくData型で格納しなければいけません。

なので`jpegData()`メソッドでData型に変換しています。

`imageRef`は画像の格納先です。

`child()`メソッドで子フォルダを作成します。
profileImageフォルダを作成しさらにその下に、"uid".jpgで保存しています。

次のコードが**ハマりポイント①**の
`meta.contentType = "image/jpeg"`です。

これは、画像のファイルタイプをapplication/octet-streamから
"image/jpeg"に変換しています。

これをしておかないとSDWebImageで画像を表示することができません。

その後は、`imageRef.putData()`で画像をStorageに格納し、
`imageRef.downloadURL()`の結果を
`.setData(["imagePath" : "\(url)"])`でFirestoreに格納しています。

```swift:ViewController.swif

// 画像を.jpegData()メソッドでData型にする
let profileImage = icon.image!.jpegData(compressionQuality: 0.1)
        
// 格納先のパス
let imageRef = Storage.storage().reference().child("profileImage").child("\(uid!).jpg")
let meta = StorageMetadata()
// 画像データのタイプを変更する
meta.contentType = "image/jpeg"
        
imageRef.putData(profileImage!, metadata: meta) { (metaData, error) in
        guard metaData != nil else {
                print(error.debugDescription)
                return
        }
            
        imageRef.downloadURL { (url, error) in
                guard let url = url else {
                return
        }
                // FirestoreにURL格納
                self.db.collection("profileImage").document("\(self.uid!)").setData(["imagePath" : url.absoluteString])
        }
}
```

ここまでで、Firebase Storageに画像データを送ることができました。

私の場合は次の画面で画像を取得して表示しているのでそのまま記載します。

先ほどFirestoreに格納した値をimagePathに格納します。

Firestoreからデータを取得する方法は、
`getDocument()`メソッドを使用することで可能になります。

パスや値が存在した場合は、documentにデータが入るので、
`document.get()`のようにget( )メソッドでデータの中の値を取得します。

`icon.sd_setImage()`の箇所で画像を入れています。
(iconはUIImageView型です。)

```swift:NextViewController.swift

var imagePath = ""

db.collection("profileImage").document("\(uid!)").getDocument { (document, error) in
        guard let document = document else {
                return
        }
        self.imagePath = document.get("imagePath") as! String
}

icon.sd_setImage(with: URL(string: imagePath), completed: nil)
```

ただ、これだけだと表示されない可能性があります。

というのも、Firebase Storageのセキュリティルールに引っ掛かり
データへのアクセスが拒否されている可能性があるからです。

こちらが**ハマりポイント②**になります。

アクセス権限の変更方法は、FIrebaseのコンソールから行います。
Storage
-> Rules
-> ルールを編集　を選択します。

デフォルトだと下記のような状態かと思います。

```
rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /{allPaths=**} {
      allow read, write: if request.auth != null;
    }
  }
}
```

ここに`/public`を追加します。

```
rules_version = '2';
service firebase.storage {
  match /b/{bucket}/o {
    match /public/{allPaths=**} {   // この行に追加しました
      allow read, write: if request.auth != null;
    }
  }
}
```

##さいごに

publicを追加すると、公開フォルダ？的な感じになると思うので、
それだとセキュリティ的に不味い場合はやめた方がいいかもしれません。

おそらくですが、これでうまくいくと思います！
私の場合はこれで画像を取得することができました・・・。

冷静に考えれば分かることだったかもしれませんが、
なかなか気づかないものですね(笑)

以上、最後までご覧いただきありがとうございました。
Rails  デプロイ後 iPhoneでの閲覧時のみページ遷移の挙動がおかしい際の解決方法【turbolinks】

##環境
Rails 5.2.4.4

##起こったこと
デプロイ後、PCでは問題なく動くのに、iPhoneを使うと挙動がおかしくなりました。
原因発見にかなり時間がかかりましたので共有します。
まずは、具体的な事象を記載します。

+ Deviceで実装したユーザー登録画面にiPhoneでアクセスすると画面が真っ白に
+ 標準出力を見ると何度も同ページでリロードが行われている
+ エラーメッセージは出力されず
+ リンクからのアクセスではなく、URL直打ちの場合はアクセスできる
※ここが原因発見の鍵になりました。

##原因
結論から申し上げますと、ターボリンクスが影響していました。
ページ遷移の高速化のため、Rails4から標準で搭載されています（application.jsに記載があります）。
JQueryの挙動に影響があるという記事も多いですが、
スマートフォンで、入力フォーム等のページへ遷移する際にエラーが起きる場合があるようです。

[ターボリンクスについて](https://kray.jp/blog/must-know-about-turbolinks/)

##解決策
```php:_header.html.erb
<%= link_to "新規登録", new_user_registration_path, data: {"turbolinks" => false} %>
```
念のためログインページ等フォームが絡むページにも記載。
該当のリンクにターボリンクス無効化の記載をすれば問題なくアクセスできるようになりました。
VScodeで困った最初の壁（ Font Family: Ricty Diminished)について。

#はじめに  
私の現在の状況から記載させて頂きます。  
私は美容師をしながらエンジニアを目指している初学者です。
プログラミング歴はやっとひと月経つかな？ぐらいなもんです。なのでこの記事の対象は崇高なる先輩エンジニアの方々では無く、本当にプログラミングを始めたての方向けとさせて頂きます。  

#今記事の本題の前に
今記事の本題はというとタイトルにもあるように  

VScode（<font color="Red">V</font>isual Studio Code）で困った最初の壁（ Font Family: Ricty Diminished)についてです。`＊VScodeとは個人のPCでプログラミングをしていく為のエディターの1つです。`  
エディターは数多くありますので詳細は省かせてもらいますが、私がVScodeを選んだ理由は調べた中で一番メジャーだった事や、プログラミング学習サービスの1つ**「ドットインストール」**さんがこちらで教材を進めていた為です。  
このVScodeの初期設定の1つ**”Font Family”**を**”Ricty Diminished”**というものに変更することがドットインストールさんの教材で推奨されていたのでそちらを実行した際に、うまくフォントが適用されない。  
こういった事象があったので解決した経緯を記載して行きます。
  

##前記事項として  
私が使用しているPCはMac book air(13-inch, 2017), 
プロセッサ1.8 GHz Intel Core i5 
メモリ8 GB 1600 MHz DDR3です。　　

<br>
#解決方法  
さっそくになりますが、私が解決に至った方法を先にお伝えすると  
**"Font bookでRicty Diminishedを確認（クリック）した"**  
です。  
詳細に関しましては、`MacのLaunchpad＞ユーザ＞Ricty Diminishedを確認（クリック）`これだけです。  
このフォントがうまく設定できない事例は結構多く見られましたので、一定数このフェーズで躓く初学者の方もいらっしゃるのだと思います。  
又、調べると色々な解決事例がありましたので今回私が提示した方法はあくまで一例だということをご了承下さい。
#解決事例一覧
* 下記は調べた上で多そうだった解決例です。  
 * Ricty Diminishedの綴りを確認する
 * ダウンロードしたファイルを消去し、再ダウンロードしてみる
 * VScodeを再起動してみる
 * PCの再起動をしてみる
 * Ricty Diminishedのバージョンを確認する  

などが調べた結果回答として上がっていました。私はこれを全て試してみた結果どうしても解決に至らず、色々ともがいていたら偶然解決しました。  
私も何を隠そう初学者中の初学者なので何故解決したのか。そもそも何が原因で反映されていなかったのか。は皆目検討もつきませんが、誰かの助けになればと想い残させて頂きます。
typescript-fsa-redux-thunkの紹介

## はじめに
redux-thunkをtypescriptで使っていた時に、typescript-fsa-rudx-thunkというパッケージが便利だったので紹介します。
非同期処理のactionを作るactionCreatorを提供しています。

typescript-fsaやredux-thunkの説明を詳しくすると長くなるので端折りながら。

## typescript-fsaについて
Reduxの型定義をよしなにしてくれるパッケージはtypescript-fsaが有名。

```javascript
import actionCreatorFactory from 'typescript-fsa';

const actionCreator = actionCreatorFactory();
//{foo: string}型がパラメータの型になる。
const somethingHappend = actionCreator<{foo: string}>('SOMETHING_HAPPENED');
console.log(somethigHappend({foo:"hoge"}));
// { type: 'SOMETHING_HAPPENED', payload: {foo:"hoge"})
```
payloadの型がactionCreatorのジェネリックスで指定した型になります。
型をactionCreatorを通して定義できます。

## redux-thunkについて
redux-thunkはreduxで非同期処理を行う時に使用されるパッケージです。

redux-thunkを使わない場合

```javascript
const somethingHappend = actionCreator<{foo: string}>('SOMETHING_HAPPENED');

fetch("http://example.com")
  .then(response => response.text())
  .then(text => {
    store.dispatch(somthigHappend({foo:string});
  });
```

redux-thunkを使った場合

```javascript
const somethingHappend = actionCreator<{foo: string}>('SOMETHING_HAPPENED');

const asyncSomethingHappend = () => (dispatch: any) => any{
  fetch("http://example.com")
    .then(response => response.text())
    .then(text => {
      dispatch(somthigHappend({foo:string});
    });
}
//asyncSomethingHappendはreduxのactionと同じようにdispatchできます。
store.dispatch(asyncSomethingHappend());
```
redux-thunkを使うと非同期処理を行う関数(thunkと呼ぶらしい)をdispatchできるようになりました。

非同期処理を行う関数（thunk）自体がactionとなるので、管理がしやすくなります。

## typescript-fsa-redux-thunk
今までの説明では理解しやすくするために簡単な処理を書いていました。
しかし、私が実際に非同期処理をする時はいつも複雑になります。

通信が始まったときの処理だとか、終わったときの処理だとか、エラー時の処理だとか、
ただでさえ、reduxやredux-thunkを理解するのが大変なのに、、、

そこで、便利だったのがtypescript-fsa-redux-thunk。
非同期処理のaction(thunk)を作るactionCreaterを提供してくれています。

```typescript
import actionCreatorFactory from 'typescript-fsa';
import { asyncFactory } from 'typescript-fsa-redux-thunk';

//ジェネリックスで渡しているStateはReduxのstoreのstateと同じ型です。
const createAsync = asyncFactory<State>(create);

interface LoginParams {
  email: string;
  password: string;
}

const login = createAsync<LoginParam,UserToken,CustomError>(
  'Login',
  // 引数で取っているparamsがLoginPramになります。
  async(params,dispatch) => {
    const res = await fetch("http://example.com/login",{
     method: 'POST',
     body: JSON.stringfy(params)
    })
    if(!res.ok) {
     throw new CustomError();
    }
    //UserToken型を返します。
    retrun res.json() as UserToken
  }
);
const loginParam:LoginParam = {email:'hoge@example.om',password:'fuga'}
store.dispatch(login(loginParam));
//login.asyncの中
//{
//  started: f LOGIN_STARTED
//  done: f LOGIN_DONE
//  failed: f LOGIN_FAILED
//  type: 'LOGIN'
//}
```

createAsyncは非同期処理のaction（thunk）を作るactionCreaterになります。

createAsyncで作られたthunkはdispatchされると、
started:非同期処理が始まったとき
done:非同期処理が完了したとき
faild:非同期処理が失敗したとき
上記の三つのactionがdispatchされる。
これらの三つのactionはlogin.asyncの中に定義されている。
いちいち自分で記述しなくてよいので、楽です。

createAsyncの三つのジェネリックは順番に
1.createAsyncが作ったthunkの引数の型・createAsync第二引数の関数の第一引数
2.createAsyncの第2引数の返り値・doneアクションのparameter
3.エラーの型
になっている。

一番うれしいのが、started・done・faildのアクションを定義してくれていること。


## 最後に
説明難しい。
【GAS】nearMinute の挙動について

## 概要
nearMinute() によって時限式のトリガーを設定する場合、注意が必要
5:00 に設定した場合、トリガーが実行される範囲は、5:00~5:15, 5:45~5:59
5:55 に設定した場合、トリガーが実行される範囲は、5:00~5:10, 5:40~5:59


## [nearMinute(minute)](https://developers.google.com/apps-script/reference/script/clock-trigger-builder#nearminuteminute)
トリガーが実行される分を指定する **(±15分)**
呼び出されない場合、ランダムな分の値が使用される

```
# 毎日 5:30 頃に実行される
ScriptApp.newTrigger("myFunction")
  .timeBased()
  .atHour(5)
  .nearMinute(30)
  .everyDays(1)
  .create();
```

## ±15分 の範囲
試験的に実行してみた結果、この範囲で呼び出された

`nearMinute(0)`と指定した時、45分~15分
`nearMinute(25)`と指定した時、10分~40分
`nearMinute(50)`と指定した時、35分~5分

## ※注意
`.atHour(5).nearMinute(0)` と 5:00 にトリガーを設定した場合、5:00 ~ 5:15, 5:45 ~ 5:59 のいずれかで実行されてしまう
4:45 ~ 5:15ではない


## 実験
22:00 ~ 22:59 まで1分刻みでトリガーを設定し、実際に実行開始された時間を測定する
（1プロジェクト 20トリガーまでのため、3プロジェクトに分けて実行）

### 測定結果
- `.atHour()`で指定した時間は固定
- `.nearMinute()`で指定した 分 の ±15分 のブレがある
- 試行数が少ないので断言は出来ないが、±8分 くらいには収まる


|設定時間[A] |開始時間[B]  | [B] - [A] |
|:-:|:-:|:-:|
22:00	|	22:02:54	|	0:02:54
22:01	|	22:04:05	|	0:03:05
22:02	|	22:08:26	|	0:06:26
22:03	|	22:57:49	|	<font color="red">0:54:49</font>
22:04	|	22:59:45	|	<font color="red">0:55:45</font>
22:05	|	22:04:54	|	-0:00:06
22:06	|	22:01:26	|	-0:04:34
22:07	|	22:05:53	|	-0:01:07
22:08	|	22:14:31	|	0:06:31
22:09	|	22:13:12	|	0:04:12
22:10	|	22:16:31	|	0:06:31
22:11	|	22:13:53	|	0:02:53
22:12	|	22:12:29	|	0:00:29
22:13	|	22:14:47	|	0:01:47
22:14	|	22:17:39	|	0:03:39
22:15	|	22:22:51	|	0:07:51
22:16	|	22:22:17	|	0:06:17
22:17	|	22:22:18	|	0:05:18
22:18	|	22:16:31	|	-0:01:29
22:19	|	22:13:37	|	-0:05:23
22:20	|	22:27:46	|	0:07:46
22:21	|	22:24:52	|	0:03:52
22:22	|	22:17:44	|	-0:04:16
22:23	|	22:25:32	|	0:02:32
22:24	|	22:24:00	|	0:00:00
22:25	|	22:27:33	|	0:02:33
22:26	|	22:23:50	|	-0:02:10
22:27	|	22:27:47	|	0:00:47
22:28	|	22:29:42	|	0:01:42
22:29	|	22:32:18	|	0:03:18
22:30	|	22:35:09	|	0:05:09
22:31	|	22:30:31	|	-0:00:29
22:32	|	22:31:40	|	-0:00:20
22:33	|	22:35:57	|	0:02:57
22:34	|	22:40:50	|	0:06:50
22:35	|	22:31:39	|	-0:03:21
22:36	|	22:41:40	|	0:05:40
22:37	|	22:37:37	|	0:00:37
22:38	|	22:33:10	|	-0:04:50
22:39	|	22:34:10	|	-0:04:50
22:40	|	22:37:27	|	-0:02:33
22:41	|	22:42:24	|	0:01:24
22:42	|	22:48:06	|	0:06:06
22:43	|	22:49:06	|	0:06:06
22:44	|	22:48:37	|	0:04:37
22:45	|	22:38:50	|	-0:06:10
22:46	|	22:50:51	|	0:04:51
22:47	|	22:44:53	|	-0:02:07
22:48	|	22:46:53	|	-0:01:07
22:49	|	22:47:19	|	-0:01:41
22:50	|	22:52:45	|	0:02:45
22:51	|	22:49:02	|	-0:01:58
22:52	|	22:54:58	|	0:02:58
22:53	|	22:46:57	|	-0:06:03
22:54	|	22:50:09	|	-0:03:51
22:55	|	22:01:19	|	<font color="red">-0:53:41</font>
22:56	|	22:55:54	|	-0:00:06
22:57	|	22:54:32	|	-0:02:28
22:58	|	22:05:55	|	<font color="red">-0:52:05</font>
22:59	|	22:59:43	|	0:00:43

![グラフ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275134/5e31b8bd-af8b-26ec-f9da-a8b2d0209bed.jpeg)
【husky】commit時にESLintを、push時にJestを自動で走らせる

作成したNext.jsのプロジェクトに[husky](https://typicode.github.io/husky/#/)を用いて以下の機能を追加します。


- commit時に[ESLint](https://eslint.org/)を走らせてerrorがあればcommitさせない
- push時に[Jest](https://jestjs.io/ja/)を走らせてerrorがあればpushさせない





> **huskyとは**
コミットやプッシュの前にテストなどを実行して、失敗したら止めることができる Git hooks を簡単に設定することがツール。



# 導入手順
**※この記事ではhuskyの導入について説明していきます。**<br>

参考までに僕が実際に作成したリポジトリでございます。
↓
https://github.com/yuyaamano23/husky_nextJS

以下の記事を参考にNext.jsのプロジェクトにESLint,Jestを導入させていただきました。🙏🙏🙏
[2020年師走における Next.js をベースとしたフロントエンドの環境構築](https://zenn.dev/higa/articles/d7bf3460dafb1734ef43)


- [ESLintの導入箇所](https://zenn.dev/higa/articles/d7bf3460dafb1734ef43#10.-%E9%9D%99%E7%9A%84%E8%A7%A3%E6%9E%90%E3%81%A8%E6%95%B4%E5%BD%A2%E3%81%AE%E3%83%84%E3%83%BC%E3%83%AB%E3%82%92%E8%BF%BD%E5%8A%A0)
- [Jestの導入箇所](https://zenn.dev/higa/articles/d7bf3460dafb1734ef43#11.-%E3%83%86%E3%82%B9%E3%83%88%E3%81%AE%E8%BF%BD%E5%8A%A0)



<br>



**※以下yarnを使用したhuskyの導入についての説明をしていきます。**<br>
**①[lint-staged](https://github.com/okonet/lint-staged)の導入**

```zsh
$ npx mrm lint-staged
```

**②NPM スクリプトに追加**

```json:package.json
{
  "scripts": {
    "lint-staged": "lint-staged"
  }
}
```

**③husky の追加**

```zsh
$ yarn add -D  husky@next
```
**④Git hooks の有効化**

```zsh
$ yarn husky install
```

**⑤package.jsonに追加**

```json:package.json
・・・・・・
 "husky": {
    "hooks": {
      "pre-commit": "lint-staged",
      "pre-push": "yarn test"
    }
  }
・・・・・・・
```

以上です。

# 検証

`git commit -m "<message>"`を入力してESLintが走った様子↓

![スクリーンショット 2021-01-28 0.34.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/612915/1450be6b-d9f1-c493-4b7b-44874e63c06d.png)

`git push`を入力してJestが走った様子↓
![スクリーンショット 2021-01-28 0.34.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/612915/7a2ed9f2-ae28-addc-a1f7-937e7a27a7f9.png)


## もしhuskyが走らなかったら...
.git/hooksが正常に作成されていない可能性があります。
以下コマンドで確認しましょう。

```zsh
$ ls -la .git/hooks/ls -la .git/hooks/
```

.sampleしかなかったら再度huskyをインストールしましょう。

```zsh
$ yarn remove huksy
```

エラーについてこの記事で救われました。
[huskyのpre-commitで設定したlintチェックがVSCodeのGUIからのコミットだと動かない件](https://zenn.dev/nishinama/articles/e1095e7f2e50726c5319)
僕はhuskyのバージョンを下げてインストールしました。


# 参考

[【日本一わかりやすいTypeScript入門】ESLintとPrettierでコードの品質を高めよう](https://www.youtube.com/watch?v=R35LJL6a-p0&t=1629s)
[Next.js 10にTypeScriptとESLint, PrettierとJestを導入する](https://qiita.com/282Haniwa/items/dcce1ba6bb6ae541893e#husky%E3%81%AE%E5%B0%8E%E5%85%A5)
埋め込み実験用記事その2: 埋め込んだページの高さ調整

[高さを調整するリンク](https://gyoubumasataka.github.io/sidecode_hub/redirect.html?https://gyoubumasataka.github.io/sidecode_hub/ExportedTest.html)

[高さを調整しないリンク](https://gyoubumasataka.github.io/sidecode_hub/redirect.html?https://gyoubumasataka.github.io/sidecode_hub/ExportedTest_noH.html)
cakePHP4 ログイン時の認証条件追加

#はじめに
すぐ解決できなかった、そしてピンポイント記事が無いように感じたのでここに記録しておきます！
以下認証の実装はすでに行っていることとします。
きっとここから悩んでいる方が、
記事にきてくださっている気がするので、、、、
https://book.cakephp.org/4/ja/tutorials-and-examples/cms/authentication.html

参考
https://book.cakephp.org/authentication/2/en/identifiers.html


# コード

```Application.php
        // identifiers を読み込み、email と password のフィールドを確認します
        $authenticationService->loadIdentifier('Authentication.Password', [
            'fields' => [
                'username' => 'email',
                'password' => 'password',
            ],
            'resolver' => [
              'className' => 'Authentication.Orm', //ここ追加
              'finder' => 'auth' //ここ追加
            ],
        ]);
```



```Model/Table/UsersTable.php

    //チェックする取得レコード制限
    public function findAuth(Query $query, array $options)
    {
        $query
            ->where(['Users.is_temporary' => 0]); //本登録のみ ここの条件は適宜変更してください！

        return $query;
    }

```

# おまけ
:shamrock:コメントがあって調べたので追記します！

『コメント内容』
以下の『$options』の箇所に値を入れるにはどうするべきか？

```.php
public function findAuth(Query $query, array $options)
```

『回答』

```.PHP
'finder' => 'auth',
```

の箇所を以下に変更すると

```.PHP
'finder' => array('auth' => array('sample' => 13)),
```

以下のような感じで取得出来ます！

```.php
    public function findAuth(Query $query, array $options)
    {
      
      var_dump($options['sample']); //13

        $query
            ->where(['Users.is_temporary' => 0]); //本登録のみ

        return $query;
    }
```

ちなみに以下箇所が主な処理なのですが、これみると『auth』一つでなくても『auth』以外も入れて複数も指定出来そうです！ヽ(´▽｀)/便利ですね！

```.php
    public function find(array $conditions, $type = self::TYPE_AND)
    {
        $table = $this->getTableLocator()->get($this->_config['userModel']);

        $query = $table->query();
        $finders = (array)$this->_config['finder'];

        //ここでfinderに入れたものチェックしているようなので配列で複数入れて色々なチェックもためせそうです！
        foreach ($finders as $finder => $options) {
            if (is_string($options)) {
                $query->find($options);
            } else {
                $query->find($finder, $options);
            }
        }

        $where = [];
        foreach ($conditions as $field => $value) {
            $field = $table->aliasField($field);
            if (is_array($value)) {
                $field = $field . ' IN';
            }
            $where[$field] = $value;
        }

        return $query->where([$type => $where])->first();
    }

```

# 最後に
何かあれば追加します(｡･ω･｡)
テンション高くなくて面白みにかけると思った方、
私のテンションが高くなるようにほめてください。
心の中でよしよししてください、、
いつかテンションが上がるかもしれません、、
きっとここに来てくれた方も元気が無いので、
丶(・ω・｀) ﾖｼﾖｼ丶(・ω・｀) ﾖｼﾖｼ丶(・ω・｀) ﾖｼﾖｼ
もし少しでもこの記事で時間が空いたら身体をやすめましょう。
寝るのや、食べるの大事ですよ、、、、
丶(・ω・｀) ﾖｼﾖｼ丶(・ω・｀) ﾖｼﾖｼ丶(・ω・｀) ﾖｼﾖｼ
ArtisanコマンドをLaravel外のスクリプトから呼ぶときのメモ

ArtisanコマンドをLaravel外のスクリプトから呼びたくなったときに

```php
<?php
require_once(PATH_TO.'/vendor/autoload.php');
$app = require(PATH_TO.'/bootstrap/app.php');
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
// stdoutをstringで受け取りたいとき↓
$output = new Symfony\Component\Console\Output\BufferedOutput;
// そのままコンソールに表示したいとき↓
// $output = new Symfony\Component\Console\Output\ConsoleOutput;
$kernel->call('migrate', [ '--force'=>true, '--quiet'=>true ], $output);
// ↓ stringで取り出す
echo $output->fetch();
```
`shell_exec('php artisan migrate')`とかしてもいいのだろうけど…
意識高い系エンジニアになるために

##0.はじめに
**※この記事はクソです。**

意識高い系エンジニアとは何ぞやという話ですが、

最近、身の回りに意識の高い人たちが増えてきて、嫉妬？憧れ？のような感情を持って、

「あ～なにかやりたいな作りたいな」の波が来る頻度が非常に増えてきたので、

自分なりの意識高い系エンジニアの分析と、意識高い系エンジニアになるためには、

という備忘録を書かせていただきます。

##1.意識高い系エンジニアはイマドキサービスを作る

toC向けの開発で、そもそもイマドキの若者向けサービスの開発とかしてる人からしたら、

「トレンド追うのも大変なんだよ」とかあるのかもしれないですけど、

BtoBでひたすら利益だったり、保守運用を追い求めて毎日仕事してる人からしたら、
そういう人が滅茶苦茶眩しく見えて仕方ないのです。

周りから、こういうアプリあるんだけど、とか言われるとそのアプリをインストールすることよりも、誰が作ったのか、マネタイズの手段は…とかずっと考えてしまう。

イマドキのwebサービス、スマホアプリで成功してる人達と、自分がホントに同じ職業なのか分からなくなってしまう。

##2.意識高い系エンジニアは人と繋がる

エンジニアって言うと、イメージだとデスクに篭ってカタカタ、部屋に篭ってカタカタだったのが、

最近はコワーキングとかサロンとか、妙にコミュニティを作ってmacbookで隣の人と時々話しながら開発…
SNSでも意識高そうなグループとかで話してたり…

いや眩しい眩しい…嫉妬が入り交ざったような感覚に襲われます。

友達とかに、この人はね、このアプリ作った人だよ！とかメッセンジャーとか見せられながら言われると、

何も自分のサービスといえるものがないエンジニアで悪かったなって、また嫉妬の感情が生まれてしまう。

ただ横の繋がりって、情報のキャッチアップ以上に大事なものがあるなぁって思ったのです。

##3.BtoB会社員エンジニアが意識高い系エンジニアになるには

・アウトプットの場所を考える
⇒Qiitaってやっぱりギーク寄りな所があって、逆に意識高い系エンジニアからしたら、いやいやそんな事しなくてもとか思われてそう。
彼らからしたら、デプロイしてたくさん居そうな知り合い達に宣伝することが最高のアウトプットなのだろう。

・まず自分のサービスを作る
⇒これは普通にエンジニアとしてのレベル上げるために、インフラからアプリケーション、データベースまで、要件定義から実装まで、全てを一人でやるってのはもちろんいい経験になると思いますし、
一人じゃなくてもその段階で、デザイン力無いからデザイナー探すとか、コネクション作るキッカケにもなるよねって話。
そして名刺代わりに、こういうものを作ってますってポートフォリオに近い感覚で、ポンッと出せると「あ、意識高いっ！」って思ってもらえる…?

・とにかくサービス作るなら、フロントをイマドキっぽく、それっぽく
⇒正直サーバー側のフレームワークとか、レガシーだろうとモダンだろうと、Qiitaなら盛り上がるけど、意識高い系界隈では恐らく
「あのおじさん何言ってるんだろう…」みたいな腫物扱いされてしまうので、
とりあえず見た目をイマドキっぽく、あとwebならスマホ中心に考えたデザインで。
bootstapそのままみたいなデザインだけど、サービスめっちゃ凝ってます！とかより、
見た目めっちゃモダンだけどRailsチュートリアルレベルの内容です。の方がウケてしまうのが現実。

#99.終わりに

youtubeとか見てると眩しいエンジニアがよくオススメに出てきたりするんですけど、
結局世の中の9割以上のエンジニアは、サラリーマンらしいエンジニアなので、
いかに20代のうちに意識高い系エンジニアとして、それっぽくアウトプット、

30代超えた辺りから、ろくろを回しているインタビュー写真をたくさん掲載してもらえるようになるか、

大事なのかなと思いました。
プログラミングしたいけど題材がない奴はUNIXコマンドの再発明でもしてろ

# はじめに
* 妄想記事です
* 効果には個人差があります

# プログラミングしたいけど題材がない
とてもありがちである。プログラミングを身につけたくて入門書などを読んで勉強し基礎は身につけたものの、それ以降何をしていいかわからなくて立ち往生してしまう若きプログラマは多い。[^me]
[^me]:  俺である。若いかはさておき。

プログラミングはプログラムを作る行為であるため、題材となるプログラムを実装してみることが、身につけるための訓練として必要であろうことは想像に難くない。それは誰でもわかる。問題なのは、じゃあその題材とは何なのかということである。
よく聞かれるのは、「アイデアがない」といったものだろう。だがちょっと待って欲しい。そこには思い込みがないだろうか。つまり、オリジナリティのあるものを作らなければならないという思い込みである。しかし、そのような思い込みはとりあえず押し入れの中にでも押し込んでおくべきだ。つまりアイデアなんていらない、オリジナリティのあるプログラムなど作る必要はないということである。

オリジナリティのないプログラムを作れと言っているのか、それはどういうことなのかと訝しがっているかもしれない。しかし、難しく考える必要はない。我々には強力な武器があるではないか。そう、「車輪の再発明」である。

# 車輪の再発明
車輪の再発明とは、

> 車輪の再発明（しゃりんのさいはつめい、英: reinventing the wheel）とは、「広く受け入れられ確立されている技術や解決法を（知らずに、または意図的に無視して）再び一から作ること」を指すための慣用句。誰でも直観的にその意味が分かるように、車輪という誰でも知っていて古くから広く使われている既存の技術を比喩の題材として使った慣用表現で、世界中で使われている。

https://ja.wikipedia.org/wiki/%E8%BB%8A%E8%BC%AA%E3%81%AE%E5%86%8D%E7%99%BA%E6%98%8E

ということだ。つまり既にあるアプリケーションやライブラリのコピーを作ってしまおうということだ。これならオリジナルなアイデアは不要だ。車輪の再発明は一般的には厳に慎むべきものとされるが、練習目的であればむしろ積極的に車輪の再発明をすべきだ。
なに？それはわかったが何を再発明すればいいかわからない？仕方がない。それでは俺が一つアイデアを出そう。それはタイトルの通り、UNIXコマンドの再発明をすることだ。
何？何の言語を使えばいいかわからない？何でもいい。君が身につけたい言語を使えばいい。よくわからないなら、CLIツールの開発に向いているとされるGoでも使っとけ。

# UNIXコマンドの再発明が良い理由

## 比較的簡単に実装できる
UNIXコマンドはいわゆるCLIツールだ。コマンドによるが、コマンドライン引数や標準入力から値を受け取り、標準出力に結果を出力するシンプルな物が多い。GUIがないので難しいフレームワークも必要ない。君が使う言語によっては多少外部ライブラリを使ったほうが便利なケースはあるかもしれないが、ちょっとで済むだろう。とにかく、そういったものに振り回されず本質的なロジックの実装に集中できる。
また、基本的に一つ一つのコマンドの機能は小さく設計されているので、少ない行数のコードで実装できて敷居が低い。

## 難易度を選べる
ところでUNIXコマンドがいくつくらいあるのか君は知っているか？なに、知らないだと？そうか、俺も知らない。
ただ、たくさんあるってことはわかる。パッと思いつくだけでも１０個くらいはあるだろう。君がまず実装すべきは、その１０個のうち一番簡単なものだ。おそらくechoコマンドあたりがいいだろう。なに、簡単すぎるだと？
それならもう少し難しそうなコマンドを選んで実装してみればいいだけだ。君の腕に合ったコマンドを探して再発明するのだ。コマンドは無数にあるのだから何かちょうどいいのが見つかるはずだ。簡単すぎるコマンドや難しすぎるコマンドはスルーすればいい。

## 仕様や実装を調べる訓練になる
そういやさっきechoコマンドは簡単すぎると言ったな。本当にそう思うか？君が書いたmyechoに複数の引数を渡したらどうなる？-nオプションを渡した場合は？クオートに制御文字があれば解釈されるのだろうな？
普段使わなくても、実はそういう仕様が隠れていたりするものだ。manコマンドの出力を全て見て漏れなく実装するというのは良い訓練になるものだ。

## 長期的にプログラミングを続けることができる
UNIXコマンドがいくつ存在するのかという話が出たが、詳細な数はわからないまでも、たくさんあるということだけは間違いない。たくさんあるということは、つまりネタが豊富にあるということでもある。ネタが豊富だということは、全部とは言わないまでも相当数に対して取り組めばおそらくとても時間がかかり、かつたくさんの作品が生まれることだろう。（コピーとはいえ）
「継続は力なり」だとか「量は質に転化する」などといった言葉を知っているだろうか。それに則って言えば、それだけやればさぞかし君は「力」を得ており、創作物には「質」が宿っていることだろう。こんなに育ってくれてお父さんうれしいよ。

## 副次的な効果

### UNIXコマンドに詳しくなれる
君は特定のコマンドの仕様を調べ、実際に動かし、作り、テストを実施したのだ。詳しくならないはずがない。WSLによりWindows上でさえUNIXコマンドを使うことができるこの時代、UNIXコマンドの重要性は増している。ここで得た知識は間違いなく君の血となり肉となることだろう。

# 終わりに
* 俺もこの方法でGoを身につけたられたらいいな…
concurrent-rubyのConcurrent::PromisesはJavaScriptのPromiseと結構違う

```js
let print1 = new Promise((resolve) => {
  for (let i = 0; i < 10; i++) console.log(i)
  resolve();
})
let print2 = new Promise((resolve) => {
  for (let i = 0; i < 10; i++) console.log(-i)
  resolve();
})

Promise.all([print1, print2])
```

```ruby
require 'concurrent'

print1 = Concurrent::Promises.future {
  10.times { |i| puts i }
}
print2 = Concurrent::Promises.future {
  10.times { |i| puts -i }
}

Concurrent::Promises.zip(print1, print2).wait!
```

この2つのコードはとても似ているが、実は結構違った動きをする。

```
$ node a.js 
0
1
2
3
4
5
6
7
8
9
-0
-1
-2
-3
-4
-5
-6
-7
-8
-9
```

```
$ bundle exec ruby a.rb 
0
1
2
0
-1
-2
-3
-4
-5
3
4
-6
-7
5
6
7
8
9
-8
-9
```
条件分岐の条件分岐

# ifの中にif文があって...!?!?



if文に関しては以前も紹介しているので割愛
気になる方は[こちら](https://qiita.com/iamu_TECH_CAMP/items/ac97eeb3a839289f6ff5#if%E6%96%87--elsif)から

なかなかややこしかった印象。
現状の私には時間がかかりました。

[本題の解説はこちら](https://qiita.com/iamu_TECH_CAMP/items/5ffe8a8d896a7b0e0d53#%E6%9C%AC%E9%A1%8C%E3%81%AE%E8%A7%A3%E8%AA%AC)

# 実際のコード

```
<% if user_signed_in? && @item.record.nil?%>
  <% if current_user.id == @item.user_id %>
    <%= link_to '商品の編集', `~`_path, method: :get, class: "item-red-btn" %>
    <p class='or-text'>or</p>
    <%= link_to '削除', `~`_path, method: :delete, class:'item-destroy' %>
  <%else%>
    <%= link_to '購入画面に進む', item_records_path(@item.id),class:"item-red-btn"%>
  <% end %>
<% end %>
```


## まずは実現したいことを整理

**商品の編集** と **削除** と **購入画面に進む**
上記３つのボタンの表示条件を整理していく。

>実際に整理していった流れもせっかくなので記録してみます。

---

1. ログインしているユーザーなのか
2. itemは購入されているのか
3. ページを訪れたユーザーはitemの出品者か

>３つか？そんな単純じゃないだろ...

---

- 商品の編集と削除ボタン
  - ログインしている出品者本人限定の表示
  - 商品が売れて切れていれば表示はされなくても良い
- 購入画面へのボタン
  - ログインしている出品者本人以外にのみ表示
  - 商品が売れて切れていれば表示はされなくても良い

>共通のものがあるか...

---

**共通条件**
ログインしていなくてはいけない・商品が売れて切れていれば表示はされない

**パターン1**
ログインしている出品者本人限定の表示

**パターン2**
ログインしている出品者本人以外にのみ表示

>あ、きたかも...

---

### インデントを下げる/字下げする/ネストする/入れ子にする

言い方は色々あるようですが、要は...

- 親子関係がわかりやすいように
- 読みやすいように

主に上記の２点
可読性にもつながるのでチーム開発の際には特に注意したい所になるかな？

今回もまさにそれを使って上記で整理した内容を表現していきます。


# 本題の解説

```
 <% if user_signed_in? && @item.record.nil?%>
  <% if current_user.id == @item.user_id %>
    <%= link_to '商品の編集', **_path, method: :get, class: "item-red-btn" %>
    <p class='or-text'>or</p>
    <%= link_to '削除', **_path, method: :delete, class:'item-destroy' %>
  <%else%>
    <%= link_to '購入画面に進む', item_records_path(@item.id),class:"item-red-btn"%>
  <% end %>
<% end %>
```

親:`if user_signed_in? && @item.record.nil?`
**この条件がtrueでなかったら以下(子)の表示はされない**
`&&`は現状`尚且`といった捉え方をしている

>- サインインしているユーザーであれば
- 現状、購入情報テーブルにデータが無いのであれば



子 1:`if current_user.id == @item.user_id`

>- このページに訪れているユーザーのidと出品者のidが一致しているのであれば

子 2:`else`

>- 上記(子 1)の条件がtrueでないならば

---

<font color="Red">注意点</font>

- controller内のアクションに記載している変数名
- データベースの名称
- データベースのカラム名

などとも関係してくる
Reactのmap処理とkeyの使い方

# Reactの配列処理
Reactを使うとフロントエンドで同じ繰り返しの値の処理を簡単に実装することができます。
## 事前知識
- HTML基礎
- JavaScriptの基礎
- Reactの基礎

これらの前提知識がある定で話していきます。
今回はReactのフレームワークのNext.jsで実装していきます！！

```
npm init next-app アプリ名
```
まずさくっとNext.jsを立ち上げます。
エラー出た方は

```
node -v
yarn -v
npm -v
```
こちらを確かめましょう

次にcomponetsディレクトリーを作成し、その配下にitemsのコンポーネントのディレクトリを作成します。

```
cd アプリ名
mkdir components
cd conmponents
mkdir items
cd items
touch index.jsx
```

```items/index.jsx
import React from "react";
const ITEMS = [
  {
    id: 1,
    title: "一番最初のタイトルが入ります",
    body: "テキストが入りますテキストが入りますテキストが入ります"
  },
  {
    id: 2,
    title: "2番目のタイトルが入ります",
    body: "テキストが入りますテキストが入りますテキストが入ります"
  },
  {
    id: 3,
    title: "3番目のタイトルが入ります",
    body: "テキストが入りますテキストが入りますテキストが入ります"
  },
]
const Items = () => {
  return (
    <React.Fragment>
      {ITEMS.map((item) => {
        return (
        <div>
          <p>{ item.title }</p>
          <p>{ item.body }</p>
        </div>
        )
      })}
    </React.Fragment>

  )
}
export default Items
```

いったん実装します。
説明としてITEMSの配列を定義し、その中でループさせたい処理を書いていきます。
その後mapメソッドでITEMSの中身を返します。
(この時自分はmapの後のreturnを忘れて、永遠と表示されない自体がおきました、、、見逃さずに)

Itemsコンポーネントはしっかりexportしましょう。

```pages/index.js
import Items from "../components/items"

export default function Home() {
  return (
    <>
      <Items></Items>
    </>
  )
}


``` 
Itemsコンポーネントをインポートします。
<></>は<React.Fragment/>の省略記法です。
どちらでも大丈夫ですが、書く際はどちらかに統一しましょう。

![スクリーンショット 2021-01-29 0.37.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825833/690b6956-d87f-c1fd-7bac-109f69f20db0.png)
できたーー！！！
、、、、、、、むむっ
![スクリーンショット 2021-01-29 0.37.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/825833/ec394e6b-d6f7-63ae-4e9d-05d7658b21cc.png)
エラーが出ていますね。

Warning: Each child in a list should have a unique "key" prop
keyがないよーと警告が出ています。

https://reactjs.org/docs/lists-and-keys.html#keys-must-only-be-unique-among-siblings
参考記事
Keys used within arrays should be unique among their siblings. However they don’t need to be globally unique. We can use the same keys when we produce two different arrays:

配列の中のキーは兄弟間で一意である必要があります。

結論→親要素にkeyを設定すると解決する

```pages/index.jsx
import React from "react";
const ITEMS = [
  {
    id: 1,
    title: "一番最初のタイトルが入ります",
    body: "テキストが入りますテキストが入りますテキストが入ります"
  },
  {
    id: 2,
    title: "2番目のタイトルが入ります",
    body: "テキストが入りますテキストが入りますテキストが入ります"
  },
  {
    id: 3,
    title: "3番目のタイトルが入ります",
    body: "テキストが入りますテキストが入りますテキストが入ります"
  },
]
const Items = () => {
  return (
    <React.Fragment>
      {ITEMS.map((item) => {
        return (
        <div key={item.id}>
          <p>{ item.title }</p>
          <p>{ item.body }</p>
        </div>
        )
      })}
    </React.Fragment>

  )
}
export default Items

```

ちなみにキーはindexでも渡すことができますが、こちらはあまり推奨されていないようです。
wordpress編集時に絶対に気をつけるべきだが気づきにくい重大なポイント

wordpressは､phpや記事を直接編集できるという点でも非常に便利なCMSですが､
エディタではなくwordpress上で編集してしまうからこそ気づきにくい・陥りやすい､重大なポイントがあります｡

#スペースに気をつけろ！
はい｡超初歩的ですが､スペースです｡全角スペース/半角スペース/タブ｡VSCodeやAtomなどのエディタではプラグインで視覚的にわかるようにしている方も多いかと思います｡
しかし､wordpress上ではただの空白｡半角スペースで打ったつもりが､全角になってしまっている､ということも｡

#タグのミスマッチに気をつけろ！
これも超初歩的ですが､開始divタグは消したのに終了divタグを消していなかったり｡セットでコピペしたと思いきや､どちらかがミスマッチになってしまっていたり｡
いやそんなミスしないよ､というミスほど､行き詰まっているときに陥りやすく､しかも見直しにくいものだと思います｡(筆者だけ…？)

#不具合になりそうなとこ全部直したはずなのに｡直らない｡そんなときこそ｡
目に見える不具合箇所は全部修正した､なのに動作がおかしい｡
そんなときは一回､直近の動作OKだった時点以降にwordpress上で修正した箇所のコードを見直してみましょう｡
あなたの愛用のエディタに貼って､Ctrl+Sで保存｡
それだけで､どこがおかしいのかひと目でわかるように整形してくれるはずです｡

詰まっているときこそ､足元を見直す｡これ大切ですね｡