OmniAICreator/Qiita-1.07M huggingface dataset:
さくらのクラウドのオートスケールをやんわり試す

# 概要

さくらのクラウドでautoscaleを実現する何だかすごそうなのを
\#さくらのマイクロコミュニティ （CLI/APIユーザの会） vol.2 で知ったので試してみた。

- 何だかすごそうなの: https://github.com/sacloud/autoscaler
- さくらのマイクロコミュニティ （CLI/APIユーザの会）: https://twitter.com/sakura_users

# この記事の前提

- とにかく試したかったのでスケールアップダウンのトリガーは手動  
https://github.com/sacloud/autoscaler にもあるように本当は監視ツールからの  
アラートとかをトリガーにするのが想定されている。
- APIキーは準備済み
- スケールアップダウンしたいインスタンスは最小(1Core1GB)でubuntu20.04LTSをインストールしただけで起動済み。名前はautoscaled01。
- スケールアップダウンを指示するサーバも最小(1Core1GB)でubuntu20.04LTSをインストールしてdockerをインストールしただけで起動済み。
- READMEに書いている手段のうち、Dockerで試す
- インスタンスは全部同じローカルネットワーク内にいる

# 準備

## yamlを書く
スケールアップダウンを指示するサーバにて書く。
書き方は、[getting_started.md](https://github.com/sacloud/autoscaler/blob/main/docs/getting_started.md) に載ってます。
ファイル名は autoscaler.yaml にしておくとちょっとだけ後で楽です。
tokenにはアクセストークンを、secretにはアクセストークンシークレットをそれぞれ書く。

今回書いたのは以下の感じ。
autoscaled01 という名前のis1bになるインスタンスを

- 1core 1GB
- 2core 4GB
- 4core 8GB

の範囲で垂直スケールさせる。
すぐに何回もアップしたりダウンしたりしたいので、cooldownの時間は短くしている。

```yaml
# 操作対象のリソースの定義
resources:
  tmkgrp: 
    resources:
      # サーバ(垂直スケール)
      - type: Server
        selector:
          names: ["autoscaled01"]
          zone: "is1b"
        plans:
        - core: 1
          memory: 1
        - core: 2
          memory: 4
        - core: 4
          memory: 8
        option:
          shutdown_force: true

autoscaler:
  cooldown: 1 # デフォルト: 6000(10分)

sakuracloud:
  token: "himitsu"
  secret : "superhimitsu"
```

# 実行する

作ったyamlと同じディレクトリで実行する。

```shell
# coreの起動
sudo docker run --rm -w /work -v ${PWD}/:/work ghcr.io/sacloud/autoscaler:v0.0.1 server start
```

もしもyamlのファイル名を変えている場合は、 --config string でyamlのファイル名を指定しよう。
`e.g. server start --config ownyaml.yaml`

次にターミナルをもう一つ開いて、トリガーを引くための別のコンテナを作る。(コマンドの違いは最後のupかdownかって部分だけ)

```shell
# スケールアップしたい場合  
sudo docker run --rm -w /work -v ${PWD}/test_autoscale_sacloud:/work ghcr.io/sacloud/autoscaler:v0.0.1 inputs direct up

# スケールダウンしたい場合
sudo docker run --rm -w /work -v ${PWD}/test_autoscale_sacloud:/work ghcr.io/sacloud/autoscaler:v0.0.1 inputs direct down
```

# ログを見てみる

トリガーを引くとcoreの方のコンテナのログに

```shell
timestamp=2021-06-24T11:22:21Z level=info message="request received" request-type=Up
timestamp=2021-06-24T11:22:21Z level=info request-type=Up scaling-job-id=default-default-default status=JOB_ACCEPTED
```

とか出ている。

コントロールパネルを眺めているとインスタンスがシャットダウンされて
インスタンスのサイズが変更され、インスタンスが起動してくるのが分かる。

ログも

```shell
=Server zone=is1b id=113301188092 step=Handle handler=server-vertical-scaler log="shutting down server: 113301188092"
(中略)
=Server zone=is1b id=113301188092 step=Handle handler=server-vertical-scaler log="server plan changing - to {Core: 4, Memory: 8}"
```

とか出てて分かりやすい。

# 最後に

ツールの想定通りに監視ツールを使うとCPUのアラートとかメモリのアラートとかをトリガーにしゅしゅっとインスタンスを大きくできそう！
今度は監視ツールを使って試してみたいところ。
【GROMACS Tutorial】BAR法で溶媒和自由エネルギーを計算する チュートリアル"Solvation free energy of ethanol"実施メモ

#はじめに

以下のチュートリアルを実施したメモ。GROMACSでエタノールの溶媒和自由エネルギーを求める。

http://www.gromacs.org/@api/deki/files/262/=gromacs-free-energy-tutorial.pdf

下記記事ではメタンの溶媒和自由エネルギーを求めた

https://qiita.com/tacoma/items/1982a93c60c9aa408d66



#実施

前回も似たような内容を行ったが、こちらのほうは分子がエタノールなので、クーロン相互作用も含める必要がある。ただ、このチュートリアルでは計算資源節約のためにVDWとクーロン相互作用を同時に小さくしていく近道をしている。実際にはVDWとクーロンで分けるほうがよい（たしかクーロンを小さくして0にしたあと、VDWを小さくしていく）ということ。

チュートリアルのデータをダウンロードする。

```bash
$ wget http://www.gromacs.org/@api/deki/files/261/=gromacs-free-energy-tutorial.tgz
$ tar xzvf \=gromacs-free-energy-tutorial.tgz
$ cd gromacs-free-energy-tutorial/
```

ethanol0.gro および topol.topがある。ethanolの周りに水分子を置いていく。


```bash
#エタノール分子をdodecahedron型のセルに入れる
$ gmx editconf -f ethanol.gro -o box.gro -bt dodecahedron -d 1
#セルに水分子を設置する
$ gmx solvate -cp box.gro -cs -o solvated.gro -p topol.top 
```

エネルギー最小化を実施する。

```
$ gmx grompp -f em.mdp -c solvated.gro -o em.tpr
$ gmx mdrun -v -deffnm em
```

なお、コア数が多過ぎてジョブが流れない場合はmdrunのオプションで-nt 4などして並列数を指定するとよい。
続いて系を平衡化する。

```bash
$ gmx grompp -f equil.mdp -c em.gro -o equil.tpr
$ gmx mdrun -deffnm equil -v
```

シェルを実行して各ラムダの値のディレクトリとmdpファイルを生成する。

```bash
$ ./mklambdas.sh run.mdp topol.top equil.gro
```

lambda_00 - lambda_06 のディレクトリが生成されます。

```bash
$ grep init-lambda lambda_*/grompp.mdp
lambda_00/grompp.mdp:init-lambda-state        = 0
lambda_01/grompp.mdp:init-lambda-state        = 1
lambda_02/grompp.mdp:init-lambda-state        = 2
lambda_03/grompp.mdp:init-lambda-state        = 3
lambda_04/grompp.mdp:init-lambda-state        = 4
lambda_05/grompp.mdp:init-lambda-state        = 5
lambda_06/grompp.mdp:init-lambda-state        = 6
```

芸がなくてすみませんが、ともかく以下のシェルで各ディレクトリのジョブを実行できます。
各ジョブ200psと短いです。

```bash
#!/bin/bash

cd lambda_00
gmx grompp
gmx mdrun >& run.log
cd ..

cd lambda_01
gmx grompp
gmx mdrun >& run.log
cd ..

cd lambda_02
gmx grompp
gmx mdrun >& run.log
cd ..

cd lambda_03
gmx grompp
gmx mdrun >& run.log
cd ..

cd lambda_04
gmx grompp
gmx mdrun >& run.log
cd ..

cd lambda_05
gmx grompp
gmx mdrun >& run.log
cd ..

cd lambda_06
gmx grompp
gmx mdrun >& run.log
cd ..

```

色々オプションが足りない気がするが、topol.topなどデフォルトのファイル名を使っているので、省略されている。
BAR法により自由エネルギーを求める。

```bash
$ gmx bar -b 100 -f lambda_*/dhdl.xvg

Final results in kJ/mol:

point      0 -      1,   DG -20.49 +/-  0.10
point      1 -      2,   DG -14.59 +/-  0.06
point      2 -      3,   DG  4.58 +/-  0.12
point      3 -      4,   DG 18.32 +/-  1.53
point      4 -      5,   DG  4.03 +/-  0.35
point      5 -      6,   DG -6.79 +/-  0.69

total      0 -      6,   DG -14.95 +/-  2.02

```

ちなみに-b 100は100psから解析を始める、つまり最初の100psは無視するということ。
チュートリアルでは-20.6 kJ/mol ということだが、私の環境では-14.95となった。
ちなみに実験値は-20.9 kJ/molだそう。
【DevOpsエンジニア – プロフェッショナル】ピアソンVUEでAWS試験をオンライン受験してみた

![スクリーンショット 2021-06-24 193948.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/588367/5b11a428-035a-dce8-4ebf-7f756523ed88.png)

#1-はじめに
AWS DOPに合格したので体験記を投稿します。
自宅受験についても簡単に記載してみます。

#2-試験勉強

試験合格後に振り返ってみて、役に立ったものをまとめてみます。

###①参考サイト
以下のサイトが網羅的にまとめられており、最も参考にさせて頂きました。

https://tech.nri-net.com/entry/aws_certified_devops_engineer_professional

###②AWS公式の情報
以下に、受験する人の全員が実施したほうがいいと思われるものをまとめます。

+ [AWSトレーニング E-ラーニング](https://www.aws.training/Details/eLearning?id=40664)
    + 無料で試験の概要を知ることができます。
    + 各試験分野(SDLC自動化など)におけるベストプラクティスを丁寧に説明してくれます。
    + 試験で重要になるサービス知識が説明されます。
    + 日本語字幕があるので助かりました。
    + 体系立てて説明されるので、まず初めに実施したいコンテンツです。
    + 各章で数問ずつサンプル問題があります。めちゃ難しいです。
+ 模擬試験
    + 初期段階で受けておいて、試験の難易度を確認しました。
+ サンプル問題
    + サンプルとはいえ、重要な情報のため解いてみました。
+ [とくある質問](https://aws.amazon.com/jp/faqs/)
    + 特に経験のないサービスについては、世の中で一般的にどういったことを気にしているのか知るために役立ちました。

深堀りのために個人的に実施した内容は以下の通りです。

+ **1.0  SDLC Automation:**
    + BeanstalkとCode系サービスの差分
    + サーバとコンテナの差分
        + 特にデプロイポリシーはややこしく、何回も確認して覚えました。
    + リポジトリ(CodeCommit)とCodePipelineの連携方法
    + Gitリポジトリのブランチに関する基礎知識
+ **2.0  Configuration Management and Infrastructure as Code**
    + セキュアな設定値の保持の仕方（SystemsManagerのSecureString、SecretManager）
+ **3.0  Monitoring and Logging**
    + EMR、Redshift
+ **4.0  Policies and Standards Automation**
    + CloudFormation, Beanstalk, Code系それぞれの自動化
    + 各サービスごとのライフサイクルフックの流れ
+ **5.0  Incident and Event Response**
    + SNS、EventBridgeなど処理の統合サービスの理解
        + 特に、どのサービスとSNSは連携できる、どのサービスとEventBridgeは連携できるなどの整理
+ **6.0  High Availability, Fault Tolerance, and Disaster Recovery**
    + Route53のそれぞれのルーティング方法、設定方法
    + DynamoDBのテーブル設計の方法
    + その他、関連サービスの設定方法、詳細なパラメータ理解
+ **全体を通して、なるべく多くのアンチパターンを把握するようにしました**

###③そもそもの基礎知識について
以下リンクのようなシステム開発におけるベース知識があると良いと思いました。

https://cloud.google.com/architecture/application-deployment-and-testing-strategies?hl=ja

https://12factor.net/ja/

https://www.slideshare.net/SatoshiTabeta/ss-119947628


#3-当日の試験について

+ 問題の難易度

　勉強した内容で解ける問題：　3割
　勉強不足を感じた問題：　5割
　日本語がおかしい問題：　2割

個人的には、業務上の経験が少ない分、SAP認定よりも難しく感じました。
特に、CI/CD関連の問題はどれも似たように見えてしまって集中力を削がれました。


#4-自宅受験の様子
###試験前
・30分前から直前のシステムテストやチェックイン作業を実施できます。
・免許証の提示などは、スマホで撮影したものをWebアプリで送付する形式でした。

###試験中
・スマホは手の届かないところに置いておくのですが、画面フリーズの際には電話で対応して頂けました。
・OnVUEの動作が重く、何度もフリーズしながらなんとか受験しました。
　特にチャット機能と問題画面を同時表示するとフリーズが続きました。


###試験後
・特に監督官の方にあいさつすることもなく、
　終了ボタンを押したらOnVUEもクローズしました。
　呆気ない終わりでした。


#まとめ
個人的にはSAP認定よりも難しかったです。
仕事で通用するスキルに昇華するために、勉強は続けたいと思いました。
Vue - data() { return {} } vs data:() => ({ })

# Problem

The ***this.stuffProp*** won't reflect the vue instance in arrow functions.

```javascript
export default {
    props: ['stuffProp'],
    data: () => ({
      myData: 'someData',
      myStuff: this.stuffProp // The this.stuffProp won't get the stuffProp prop's value.
    })
}
```

# Suggest

```javascript
export default {
    props: ['stuffProp'],
    data() {                                   // <== changed this line
      return {
        myData: 'someData',
        myStuff: this.stuffProp
      }
    }
}
```

https://stackoverflow.com/questions/48980865/vue-js-difference-of-data-return-vs-data
Easy-ISLispでベンチマークテスト(3)

#はじめに
Easy-ISLispはPoldyさんの貢献により処理速度が向上しています。現在のver2.11でのベンチマークの結果をご紹介します。

#ベンチマーク
Open-Lispの作者のJulienさんが公開しているものです。

#結果

```
eisl -s bench/runbench.lsp

Test 01: Fib     -> ok, time =   00000s.
Test 02: Tak     -> ok, time =   0.015625s.
Test 03: Stak    -> 12, time =   00000s.
Test 04: Ctak    -> ok, time =   00000s.
Test 05: Takl    -> ok, time =   0.015625s.
Test 06: Takr    -> ok, time =   00000s.
Test 07: Boyer   -> T, time =   0.046875s.
Test 08: Browse  -> ok, time =   00000s.
Test 09: Destru  -> ok, time =   00000s.
Test 10: Travini -> ok, time =   0.015625s.
Test 11: Travrun -> ok, time =   0.359375s.
Test 12: Deriv   -> ok, time =   0.015625s.
Test 13: Dderiv  -> ok, time =   0.03125s.
Test 14: Divit   -> ok, time =   00000s.
Test 15: Divrec  -> ok, time =   00000s.
Test 16: FFT     -> ok, time =   0.0625s.
Test 17: Puzzle  -> ok, time =   0.078125s.
Test 18: Triang  -> ok, time =   1.625s.
Test 19: Fprint  -> ok, time =   00000s.
Test 20: Fread   -> ok, time =   00000s.
Test 21: Tprint  -> ok, time =   00000s.
Test 22: Frpoly  -> ok, time =   0.03125s.

Total   2.29688s.


```

PoldyさんはかなりC,C++そしてUNIXに精通した方です。ソースコードをご覧いただくと、いろいろと工夫がなされてるのがわかると思います。（私にはよくわからないところもあるんですけれども）

Open-Lispとの差もかなり縮まりました。十分に実用速度が出ていると思います。
C言語のgetenv関数と環境変数の設定

# getenv関数について

getenv関数はC言語の関数で、環境変数から情報を取得します。

```c:getenv.c
getenv( "PATH" );
```

環境変数に、引数に一致する情報があれば、その情報の文字列で返し、
失敗した場合には、NULLが返されます。


# 環境変数について

環境変数を設定する為には、Windowsの検索で「ENV」と入力して実行します。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1667007/ea8d1149-11d0-5b3c-6062-3e5f32e9f54b.png)


# ユーザ環境変数とシステム環境変数の違い

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1667007/41d83dd1-c5e2-05b6-d814-9bdcd0a4c07b.png)



個人のマシンであれば、大抵の場合システム環境変数に設定したほうが良いです。
すべてのユーザに反映されるからです。 

ユーザ環境変数は、そのユーザにしか適用されないので、共用マシンで、きわめて個人的にしか使わない変数の場合に限ります。

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1667007/341a4031-cb5d-c864-fa81-1511dd844fb3.png)
　設定方法はいずれも同じで、変数を選択して[編集]もしくは[新規]ボタンを押します。

　PATHの設定の場合、既存パスを上書きしないで、うしろに追加するようにします。
（セミコロン;で区切る）

　環境変数は大文字と小文字を区別しないので、PATH と Path は同一として扱われます。


# 環境変数と設定されている値の一覧を表示する

　DOSプロンプトに引数無しで「SET」と入力し実行します。

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1667007/0e7e671c-6b0a-6356-3f2f-615343deee2d.png)

尚、環境変数を変更する前に起動したDOSプロンプトには反映されませんので、その場合は、新たにDOSプロンプトを開いて確認してください。


# PATHを通す

「PATH」は環境変数の中でも、もっとも良く使われる変数です。

そのファイルの存在するディレクトリをPATHに記述することで、実行ファイルを起動するときにフルパスで指定する代わりに、ファイル名だけで実行できるようになります。

例えば、ファイル名を指定して実行で「notepad」や「calc」や「cmd」と入力して実行するだけで実行出来るのもこのためです。
Windowsでよく使われる実行ファイルやDLLは%SystemRoot%system32でパスが設定されています。

![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1667007/69212dbc-b88d-f5da-0c4b-e63b23cd6236.png)

![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1667007/b0f5c091-28a5-13ab-200f-2869b12a52dd.png)

# JAVAの環境構築

また、JAVA環境構築において、よくパスを通すということが出てきますが、

Pathに、
JDKインストールパス\bin
例) C:\Program Files\Java\jdk1.8.0_231\bin

JAVA_HOMEを追加し
JDKインストールパス
例）C:\Program Files\Java\jdk1.8.0231\

を設定すればOKです。※バージョンは自分がインストールしたJAVAバージョンによります。

設定後は　set JAVA_HOMEで確認してください。

![Inked6_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1667007/a5297a2a-299f-1182-b9f0-e6985519e0bb.jpeg)

この仕組みは、GoやRubyやPythonやどの言語でも同様です。

system32にあるいろいろな実行ファイルを呼び出してみたり、
自分好みにPathを設定したり色々試してみてください。
M5Paperの簡単なリモコン実装に最適。グリッド対応のタッチエリアを実装する

素敵なM5Paperライフを楽しんでいらっしゃいますでしょうか？

処理の実装は上々、**手軽に自由に綺麗に**タッチコマンドを表示したい。という方にはおすすめの、
「M5Paperで5x9(9x5)のグリッドですっきりまとめられるボタン」を作りました。
![m5pta.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65983/7f91103e-7f90-bfc5-94e8-ac2522298132.jpeg)
色は都合によりダークになっていますが、好みで変えられます。
縦型・横型にも対応しております。

この場でこちらの実装方法を解説させていただきます。

## 導入の前に

ご興味頂く前に、M5Paperの画面実装は基本的には以下のソースをFork・または参考にして開発して頂く方が幸せになれる場合が多いです。（むしろそちらが推奨です）
「そこまで本格的でなくても」とか「グリッドでデザインしたい」という方は引き続きご参照ください

https://github.com/m5stack/M5Paper_FactoryTest

## Githubソース

https://github.com/RAWSEQ/M5PaperTouchArea

## 導入ガイド

導入例は `M5PaperTouchArea/M5PaperTouchArea.ino` に記載されております。
inoファイル以外は変更せずに同フォルダに配置して頂ければ動作します。

### タッチエリア：inoファイルの修正

```cpp:宣言部（setupやloopより外）
#include "M5PaperTouchArea.h"
// Module (Grid & TouchArea)
M5PaperTouchAreas _m5pta;
```

```cpp:setup(){
  _m5pta.current_canvas = &canvas;
  _m5pta.e_touch.func = bTouch;

  _m5pta.getGutil()->setVertical(true);

```

↑　`canvas` は任意に作ったキャンバスを設定
`bTouch` `bRelease` はタッチ（指を離）した場合の処理関数を後で記述して、その名前をセットしてください。（後述します）
`setVertical` の記述は元々デフォルト横型の設定を縦型にしたい場合にセットします。横型の場合は必要ないです。

```cpp:ボタンを足す（上記宣言のスコープ内ならどこでも可能）
  _m5pta.add_grid(1,1,1,1,"B1","b1");
  _m5pta.draw();
  canvas.pushCanvas(0,0,UPDATE_MODE_GC16);
```

↑　5x9(9x5) のグリッドの1から数えて `(x,y,横幅,高さ,ボタン名,押された時に流れる任意コード名)` を設定すれば描画されます。ピンタレストの様なタイルスタイルの方が簡単に実装できて良いのですが、**自由に敷き詰めたい** という気持があったので、上記の様なグリッドシステムとなりました。

`draw`コマンドは一括描画なので、`add_grid`を複数実施した最後に1回だけ設定＆キャンバスのプッシュをするとまとめて描画されます。プッシュのオプションはお好みで

```cpp:loop(){部
void loop() {
  _m5pta.loop();
}
```

↑　ループ部に1行足してください。

```cpp:関数（任意に追記します）
// Touch Event
void bTouch(M5PTAEventContext& ct) {
  Serial.println("T:"+ct.code);
}
```
↑　最後にイベントを足せば出来上がりです。この関数にボタンがタッチされた場合の処理を書きます。
`ct.code`にタッチされたコードが代入されています。

その他の設定は以下のものがあります。

```cpp:setup(){
  // Change Default Setting
  _m5pta.default_font_size = 48;
  _m5pta.default_radius = 15;
  _m5pta.default_font_linepos = 6;
  _m5pta.default_bc = {13,0,0};
```
|設定名|説明|
|-|-|
|default_font_size|フォントサイズ|
|default_radius|ボタンの角のまるみ|
|default_font_linepos|文字上下位置調整（位置がずれるときがあるので、調整の為）|
|default_bc|文字色設定（背景、枠色、文字色 (0～15の濃さです））|

こちらはデフォルト設定ですが、ボタン描画するごとに個別にも設定することが出来ます。

最後に、削除したい場合は

```cpp
_m5pta.clear();
```

で一括削除となります。

### グリッド機能のみ：inoファイルの修正

グリッド機能だけを利用したい（x,y,w,hを指定すれば、実際のx,y,w,hを返す単純なものです）
場合は以下の通り。（Githubのサンプルは両方実装されています。）

```cpp:宣言部（setupやloopより外）
#include "GridUtil.h"
// Module (Grid Only)
GridUtil _gu;
```

TouchAreaと両方使うのであれば`#include`宣言は必要ないです。

```cpp:setup(){
  _gu.setVertical(true);
```

`setVertical` の記述は元々デフォルト横型の設定を縦型にしたい場合にセットします。横型の場合は必要ないです。

```cpp:描画（スコープ内ならどこでも）
  GURect g = _gu.convert(3,5,3,2);
  canvas.fillRect(g.x, g.y, g.w, g.h, 0);
```
【Rails】ransack版検索フォーム

## 概要

ransackというgemを用いて、railsアプリケーション内にユーザー検索機能を実装する

##実装手順
#### Gemfile
```
gem 'ransack'
```
記述後にbundle install

####users_controller
```
def index
    @q = User.ransack(params[:q])
    @user = @q.result(distinct: true).includes(:user).order(created_at: :desc)
  end
```
・User.ransack(params[:q] で検索データを取得
・distinct: true を用いることで、重複したデータをまとめる

#### users/index.html.erb
```
<%= render 'search_form', q: @q, url: users_path' %>
```
パーシャルに切り分けることによって、再利用性の向上に繋がる

#### users/_search_form.html.erb
```
<%= search_form_for q, url: url do |f| %>
  <div class="input-group mb-3">
    <%= f.search_field :title_or_body_cont, class: 'form-control', placeholder: t('defaults.search_word') %>
    <div class="input-group-append">
      <%= f.submit class: 'btn btn-primary' %>
    </div>
  </div>
<% end %>
```
・title_or_body_cont により、titleとbodyのどちらかのカラムに含まれているかどうかを判定する検
　索フォームになっている
JavaScriptの配列操作で使える構文をまとめてみた。


JSの構文をいくつか備忘録としてまとめてみました。


# 配列基礎メソッド
## 先頭・末尾の削除

### push
末尾に追加

```js
const array = [1, 2, 3]
array.push(4)
=>[1, 2, 3, 4]
```

### unshift
先頭に追加

```js
const array = [1, 2, 3]
array.unshift(0)
=>[0, 1, 2, 3]
```
### pop
末尾の要素を削除

```js
const array = [1, 2, 3]
array.pop(3)
=>[1, 2]
```

### shift
先頭の要素を削除

```js
const array = [1, 2, 3]
array.shift(1)
=>[2, 3]
```
## 途中の要素に対して追加や削除をする
### splice


```js
配列.splice(インデックス番号, 0, 挿入する要素) // 挿入
配列.splice(インデックス番号, 1) // 削除（抽出）
```

```js
const array = [1, 2, 3];

array.splice(0, 0, 'B')
=> [ 'B', 1, 2, 3 ]

array.splice(3, 1)
=>[ 'B', 1, 2 ]
```



##分割代入
```javascript
const profile = {
  name: "aa",
  age: 24,
};

//オブジェクトから指定のプロパティを抜き出せる
const { name, age } = profile;
const message2 = `名前は${name}です。年齢は${age}歳です。`;
console.log(message2);
=> "名前はaaです。年齢は24歳です。"
```
###配列の分割代入
```javascript
const profile = ['aa',24];

//配列の場合順番で格納される
const [name, age] = profile

const message3 = `名前は${name}です。年齢は${age}歳です。`

console.log(message3);
=> "名前はaaです。年齢は24歳です。"
```

##スプレッド構文
#### 配列の展開
```javascript
const arr = [1, 2];
console.log(arr);
console.log(...arr);

=>[ 1, 2 ]
=> 1 2
```
#### 配列をまとめる
```javascript
const arr = [1,2,3,4,5];
//1,2以外の数値をまとめて格納する
const [num1,num2, ...arr2] = arr;

console.log(num1);
console.log(num2);
console.log(arr2);
=> 1
=> 2
=>[ 3, 4, 5 ]
```

#### 配列の結合
```javascript
const arr = [10, 20];
const arr2 = [30, 40];

const arr3 = [...arr, ...arr2];

console.log(arr3);
=> [10, 20, 30, 40]
```

#### 配列のコピー
```javascript
const arr1 = [10, 20];
const arr2 = [30, 40];
const arr3 = [...arr1];

console.log(arr3);
=>[ 10, 20 ]
```
### コピー時の参照問題
####イコールを使ってコピーすると元の配列も影響を受ける
```javascript
const arr = [10, 20];

const arr2 = arr;
arr2[0] = 100;
console.log(arr);
console.log(arr2);

=>[ 100, 20 ]
=>[ 100, 20 ]
```
####スプレッド構文を使ってコピーすると元の配列は影響を受けない

```javascript
const arr = [10, 20];
const arr2 = [...arr];
arr2[0] = 100;
console.log(arr);
console.log(arr2);

=> [100, 20]
=> [10, 20]
```

##map 
####新しい配列を生成する
```javascript
const nameArr = ["aa", "bb", "cc"];
const nameArr2 = nameArr.map(name => name);
console.log(nameArr2);

=> ["aa", "bb", "cc"]
```
####ループ処理
```javascript
const nameArr = ["aa", "bb", "cc"];
nameArr.map( name => console.log(name));

=> aa
=> bb
=> cc
```

##filter
####ある条件に一致したものを返却して、新しい配列を生成する
```javascript
const numArr = [1, 2, 3, 4, 5];
const newNumArr = numArr.filter(num => num % 2 === 1);
console.log(newNumArr);

=> [1, 3, 5]
```
パスを通す　環境変数　まとめ

# 概要

- 何となくパスを通すという言葉を解釈していた
- コマンドの実態はバイナリファイルであり、バイナリファイルの格納場所のエイリアスを登録するのがパスを通すという解釈だった
- もう少し調べたかったので、調べた内容をまとめる

### 参考資料：[Linux入門 ~「パスを通す」とは~](https://qiita.com/Naggi-Goishi/items/2c49ea50602ea80bf015)
### 参考資料２：[Pathを通すとは、環境変数とは](https://qiita.com/Islanders-Treasure/items/3d8af42cf7abee760a81)

# パスを通すとは

- 概要に記載の理解であっていた
- 環境変数（$PATH）にコマンド検索パスを追加すること

# 仕組み

1. シェルにパスが通っているコマンドを入力する

```例
printenv
```

2. 環境変数$PATHをシェルが参照する

- 以下は$PATHの中身(例であってすべてがこうなっているわけではない)

```
/Users/Islanders-Treasure/.rbenv/shims:/Users/Islanders-Treasure/.pyenv/bin:/Users/Islanders-Treasure/.phpbrew/php/php-5.6.23/bin:/Users/Islanders-Treasure/.phpbrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/local/bin:/usr/bin/xcodebuild:/usr/local/sbin
```

- パスは:で分けられているので分解すると以下

```
/Users/Islanders-Treasure/.rbenv/shims
/Users/Islanders-Treasure/.pyenv/bin
/Users/Islanders-Treasure/.phpbrew/php/php-5.6.23/bin
/Users/Islanders-Treasure/.phpbrew/bin
/usr/local/bin
/usr/bin
...省略
```

3. 通っているパスを参照する

- printenvは`/usr/bin/`直下なので、/usr/bin/printenvをさしているのと同じことになる
 
# パスの通し方

- /xxx/binを追加する
- :$PATHを忘れるとPATHを/xxx/binで上書くので他の設定がすべてなくなる

```
export PATH=/xxx/bin:$PATH #PATHに追加したいパスと元のPATHを連結することで追加できる
```

# 環境変数とは

- ~~Terminal環境内における変数のこと~~
- printenvで環境変数を確認できる
- 下記を見てもわかる通り、`PATH`は**環境変数の一部**である

## 2021/6/24 追記

@angel_p_57 さんからご指摘いただいた通り、あまり環境変数の意味について理解して書いていなかったので再度調べてまとめました!
ありがとうございました!

# 改めて環境変数とは

### 参考資料：[Wikipedia/環境変数](https://ja.wikipedia.org/wiki/%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0)

[IT用語辞典](https://e-words.jp/w/%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0.html)曰く

>環境変数とは、OSが設定値などを永続的に保存し、利用者や実行されるプログラムから設定・参照できるようにしたもの

- OS上で利用する変数ということ
- `変数名=設定値`の構成
- プロセス間でデータを共有するための仕組みとして存在する
- 例えば、親プロセスが参照している環境変数は、その子プロセスも参照できる

```printenv実行結果(一例(一部抜粋))
PWD=/Users/Islanders-Treasure
SHELL=/bin/zsh
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
COLORTERM=truecolor
HOME=/Users/Islanders-Treasure
USER=Islanders-Treasure
LOGNAME=Islanders-Treasure
ZSH=/Users/Islanders-Treasure/.oh-my-zsh
PAGER=less
LESS=-R
LC_CTYPE=en_US.UTF-8
LSCOLORS=Gxfxcxdxbxegedabagacad
_=/usr/bin/printenv
```

- SHELL:使用するシェル
- PWD:カレントディレクトリ 

等

# 環境変数を追加する

- exportコマンドで追加する
- よって、exportコマンドは環境変数を追加するコマンドである
- 参考：[export - 環境変数を定義・リスト表示する - Linuxコマンド](https://webkaru.net/linux/export-command/)
- 慣例として定数は大文字であることが望ましいので大文字で設定するようにする

```
export SAMPLE="sample"
```

# 永続的に環境変数を設定する

- 上記のexportコマンドでは現在立ち上げているシェルでしか使用できない一時的な変数のようなもの
- 永続的に使用する変数を設定する
- sourceコマンド詳細は[こちら](https://www.atmarkit.co.jp/ait/articles/1712/21/news015.html)

```
echo 'export SAMPLE="sample"' >> ~/.zshrc #シェルの設定ファイルに環境変数$SAMPLEをexportする設定を追加している。.zshrcはそれぞれ環境で異なる
sorurce ~/.zshrc #.zshrcを再読み込みする
```
# シェル変数

- 現在実行中のシェルでのみ使用できる変数
- 普通に変数に代入するように使用する

```
SAMPLE=sample
```

# まとめ

- あいまいな理解な割には本質は理解していたみたい
- 環境変数とシェル変数のこととかは知らなかった
- パスの通し方の注意事項とか永続的に環境変数を追加する方法とかが分かったのでよかった
Arduino UNOと秋月シリアル7セグで3分タイマー SPI


x Arduinoでのボード設定は、Arduino UNO
x 赤色７セグメントＬＥＤシリアルドライバモジュール　完成品
x OSL10564-74HC595-R M-12642
x Arduino_SPI

目的
SPIのテスト
軽量コンパクト化

説明
文字を文字パターンに変換する
64は、@の開始位置です。
7セグメントの文字パターンに変換
変換範囲は、32文字で5ビット分

メイン関数
setup()
いろいろ初期化
1から3までを1分毎に7セグに表示して
無限ループで停止する

D13 -> SCK
D12 ->
D11 -> SDI
D10 -> LATCH




参考


https://qiita.com/nanase/items/e74d2f828ab5cd1d3be6



```c++



#include <SPI.h>

char seg[32] = {
   0x00 , //0 @ -> ' '
   0x77 , //1 A  o
   0x7c , //2 B     　combined use "6"
   0x39 , //3 C
   0x5e , //4 D
   0x79 , //5 E  o
   0x71 , //6 F
   0x3d , //7 G

   0x76 , //8 H  o
   0x06 , //9 I    　combined use "1"
   0x1e , //10 J
   0x75 , //11 K 
   0x38 , //12 L  o
   0x15 , //13 M
   0x37 , //14 N  o
   0x3f , //15 O  o　combined use "0"

   0x73  , //16 P
   0x67  , //17 Q　combined use "9"
   0x50  , //18 R
   0x6d  , //19 S　combined use "5"
   0x78  , //20 T
   0x3e  , //21 U
   0x1c  , //22 V
   0x2a  , //23 W  o
   0x64  , //24 X

   0x6e  , //25 Y
   0x5b  , //26 Z　combined use "2"
   0x4f  , //27 [  --> "3"
   0x66  , //28 \  --> "4"
   0x27  , //29 ]  --> "7"
   0x7f  , //26 ^  --> "8"
   0x08    //31 _
};

#define DW    digitalWrite

#define s60() for(ii=0;ii<60;ii++)delay(1000);

void setup() {
  
  int ii; //ループカウンター
  
  // SPIの初期化
  SPI.begin(); // 11 12 13
  DW(SS, LOW); // 10
  SPI.setDataMode(SPI_MODE0);
  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV8);  // 2Mhz
  
  //0
  SPI.transfer(seg['O'-64]);DW(SS,HIGH);DW(SS,LOW);
  s60();
  
  //1
  SPI.transfer(seg['I'-64]);DW(SS,HIGH);DW(SS,LOW);
  s60();
  
  //2
  SPI.transfer(seg['Z'-64]);DW(SS,HIGH);DW(SS,LOW);
  s60();
  
  //3
  SPI.transfer(seg['['-64]);DW(SS,HIGH);DW(SS,LOW);
  
} //setup

void loop() {
} //loop



```
rbenv まとめ

#概要

- rubyのパッケージマネージャであることは知っている
- 新規で使うときに使い方を忘れていたのでこの際に調べたことをまとめる

### 参考資料：[rbenvでRubyバージョン切り替える【仕組みまで理解】](https://ichitasu.com/ruby-rbenv/)
### 参考資料：[rbenvの使い方と仕組みについて](https://qiita.com/Kodak_tmo/items/73147ed4f0eec54d6e94)

# rbenvとは

- [概要](#概要)に記載の通り

# 導入の流れ

## 1. インストール

```
brew install rbenv ruby-build
```

## 2. バージョンを切り替えれるようにするための設定

- 以下を最初に実行する
- rbenvの初期化？調べてもinitコマンドの意味が出てこない。。。
- evalは[こちら](https://www.atmarkit.co.jp/ait/articles/1712/22/news019.html)を参照 (文字列を評価して実行するコマンド)

```
eval "$(rbenv init -)"
```

## 3. バージョンの切り替え

- global(すべてのディレクトリ)の指定

```
rbenv global x.y.z #バージョンx.y.zを指定
```

- local(任意のディレクトリ直下)の指定
- localがglobalより優先される

```
vbenv local x.y.z
```

## 4. シェル起動時に[バージョン切り替え](# 2. バージョンを切り替えれるようにするための設定)を自動で行うように設定

- 使用しているシェルの設定ファイル(.zshrc等)に設定を追加するコマンドを打つ

```
echo 'eval "$(rbenv init -)"' >> ~/.zshrc
```

# 他コマンド

- 使用中のバージョンを表示

```
rbenv -v
```

- インストール済みのバージョン一覧を確認

```
rbenv versions
```

- 使用中のRubyのパスを確認

```
which ruby
```

# まとめ

- rbenvの基本的な使い方が分かった
- localとglobalのバージョン指定の方法が分かったのがよかった
homebrew まとめ

# 概要

- **Macのバージョン管理システム**という何となくの理解だけだった
- 久しぶりにbrewを使ってインストールするときに気になったので調べたことをまとめる

### 参考資料：[homebrewとは何者か。仕組みについて調べてみた](https://qiita.com/omega999/items/6f65217b81ad3fffe7e6)

# PKG管理システムとは [参考](https://ja.wikipedia.org/wiki/%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E7%AE%A1%E7%90%86%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0)

- PKGのインストール、依存関係の解決、設定管理をひとまとめに行うことができるツールのこと
- PKGは単体でもインストールできるが、Dependenciesの解決を自分で行うことは難しい
- その作業を肩代わりしてくれたり、設定ファイルを作成してDependenciesを見れたり、あると便利(というかないと超不便)

# homebrewとは

- Mac OS Xオペレーティングシステム上でソフトウェアの導入を単純化するパッケージ管理システムのひとつ

# グローバルインストールの際の保存場所

- /usr/local/Cellar 

コマンドの実態(バイナリファイルをビルドしたもの)が置かれる

- /usr/local/bin

コマンドのエイリアス

# 基本操作(homebrew自体のインストールは省略)

- PKGの検索

```
brew search #インストール可能なすべてのPKGを確認
brew search <PKG名> #インストール可能なPKGのバージョンを確認
```

- PKGのインストール、アンインストール

```
brew install <PKG名>
brew remove <PKG名>
```

- PKG一覧の更新 [参考](https://applica.info/brewupdate-2#:~:text=brew%20update%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6.%20%E3%80%8C%20brew%20update%20%E3%80%8D%E3%81%AFHomebrew%E8%87%AA%E4%BD%93%E3%82%92%E6%9B%B4%E6%96%B0%E3%81%99%E3%82%8B%E3%81%A8%E3%81%8D%E3%81%AB%E4%BD%BF%E3%81%86%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%A7%E3%81%99%E3%80%82.%20Homebrew%E3%81%AB%E3%80%8Cbrew,update%E3%80%8D%E3%81%A8%E5%85%A5%E5%8A%9B%E3%81%97%E3%81%A6%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B%E3%81%A8%E3%80%81Homebrew%E3%81%AB%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%81%AE%E3%83%AA%E3%82%B9%E3%83%88%E3%81%AF%E8%A1%A8%E7%A4%BA%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82.%20%E3%81%97%E3%81%8B%E3%81%97%E3%80%81%20%E3%80%8Cbrew%20update%E3%80%8D%E3%81%AFHomebrew%E3%81%A0%E3%81%91%E3%82%92%E3%82%A2%E3%83%83%E3%83%97%E3%83%87%E3%83%BC%E3%83%88%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%AE%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%20%E3%81%A7%E3%81%99%E3%80%82.%20%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%81%AE%E3%83%AA%E3%82%B9%E3%83%88%E3%81%8C%E8%A1%A8%E7%A4%BA%E3%81%95%E3%82%8C%E3%81%A6%E3%82%82%E3%80%81%E3%80%8Cbrew%20update%E3%80%8D%E3%81%A0%E3%81%91%E3%81%A7%E3%81%AF%E3%80%81Homebrew%E3%81%AB%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%82%8B%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%81%AF%E6%9B%B4%E6%96%B0%E3%81%95%E3%82%8C%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82.)

```
brew update　#homebrew自体のアップデート
brew upgrade #brew update + 更新する必要のあるPKGもまとめてupdate
```

- リストの表示

```
brew list #インストールしたPKGすべてを表示
brew list <PKG名> #インストールしたPKGのバージョンを表示
```
# まとめ

- 最初にセットアップしたらそこまで使用する機会がないのでうやむやになっていた
- まとめることができたので次使用するときのリファレンスとして使用できそうなのでよかった
Rails これから調べること

# 概要

- ポートフォリオとして作成するWebアプリケーションにバックエンドでRailsをAPIモードで使用することにしたので、調べたことをまとめる

# 基本方針

- API開発をするにあたって、最初に設定する内容のみを最低限行うこと
- その後の開発に必要になるGemについてはその時々で導入すること

そうすることで、最初にバグっていなければ、後からGemを追加してバグったら
どのGemが原因でバグっているのか見当がつきやすい
また、どの機能を実装したり、どのように改善したりするのにGemを導入するのかが
最初に入れるとlogを見たときにわかりづらい

- 最初はpry,ruboCop,annotate,sprint,jbuilderのみを入れる

- サインイン、サインアップ機能を実装するときにDevice,bcryptを入れる

- 画像アップロード処理を実装するときにcarrierwaveをいれる

# やること

https://kitsune.blog/rails-install

# リンク集

- Rails APIモード　環境構築
[【Rails】Rails6でAPIモードの環境構築をしっかりやる](https://zenn.dev/akino/articles/bf245128f390d7)
[Rails6をAPIモードで環境構築する](https://zenn.dev/dsakai07/articles/2598802e1e8af9) より詳しく書いている

- エンドポイント設計(URI + HTTP)
[バックエンドの設計を任されたので、エンドポイント設計をしっかり学んでみる](https://qiita.com/onikan/items/b6e76ff24daa2615b709)

- database.yml
Railsで使用するデータベースの設定を行うことができるファイル
[MySQL用のデータベース設定ファイル(database.yml)](https://www.javadrive.jp/rails/model/index2.html)

- Responceで返すJSONを加工する
[Rails – ActiveModelSerializers gemでサクサクAPI開発](active_model_serializers)

- Railsに必要なGem、テスト駆動開発の基本
[RailsでWEB API入門](https://qiita.com/yyh-gl/items/30bd91c2b33fdfbe49b5)

# Gem一覧

- pry
コードに`binding.pry`をコードに挿入することでブレイクポイントを設定することができるGem
[Rails で Pry を使う](https://qiita.com/silmisilon/items/8e08435204d8d08d09ff)

- Device
ユーザー認証用のGem
[Rails devise の使い方（導入からログアウトまで）](https://tech.mof-mof.co.jp/blog/devise-introduction/)

- annotate
Modelのスキーマ情報をファイルの上部や下部にコメントしてくれるGem
[【Rails】annotateの使い方](https://qiita.com/kou_pg_0131/items/ae6b5f41c18b2872d527)

- spring
ライブラリをプリロードすることでコマンドの実行時間を短くできる
[RailsでSpringを導入して開発効率を上げる](https://easyramble.com/install-spring-into-rails.html)

- Jbuilder
JSON構造を宣言するためのシンプルなDSL(ドメイン特化言語)を提供
[【Rails】JSONデータを返却する「gem jbuilder」の便利な使い方](https://opiyotan.hatenablog.com/entry/rails-gem-jbuilder)

- bcrypt
パスワードの暗号化
[bcrypt【Rubyのパスワード暗号化Gem】](https://ichitasu.com/ruby-bcrypt/)
[Gem Deviseによるパスワードの保存及び保安方法](https://freelance.techcareer.jp/skills/98/articles/9114/)

- carrierwave
画像のアップロード機能を提供
[Rails 画像アップロード機能の実装方法　メモ](https://qiita.com/STHEXA/items/05a492bd9cf4cf31ba98)
[Carrierwaveの使い方](https://yuruli.info/using-carrierwave-on-rails-6/)

- ruboCop
静的コード解析ツール
[RuboCop is 何？](https://qiita.com/tomohiii/items/1a17018b5a48b8284a8b)

- 

[]()
CORS まとめ

# 概要

- SPAで開発する際にフロントエンド側(React)とバックエンド側(Rails API)で疎通する際に問題になるのがCORSとかいうやつ
- 設定する内容は理解したが、原理が分かっていなかったので調べたことをまとめる

### 参考資料：[なんとなく CORS がわかる...はもう終わりにする。](https://qiita.com/att55/items/2154a8aad8bf1409db2b)
### 参考資料２：[MDN Web Docs](https://developer.mozilla.org/ja/docs/Web/HTTP/CORS)

# オリジンとは

- スキーム（http）
- ドメイン（example.com）
- ポート（8080）

の組み合わせのこと

# CORS(Cross-Origin Resource Sharing)とは

- 日本語訳するとオリジン間リソース共有
- 別々のオリジン同士のアクセスをHTTPリクエストによって許可できる仕組みのこと

# CORSが必要な理由

- セキュリティ上の理由([XSS (Cross Site Scripting)]()とか[CSRF (Cross-Site Request Forgeries)]()とかの対策らしい)
- これらの理由から`XMLHttpRequest`やFetchAPIは[同一オリジンポリシー](https://developer.mozilla.org/ja/docs/Web/Security/Same-origin_policy)に従うとのこと

# CORSの仕組み

- APIを使用するWebアプリは原則上記のように同一オリジンに対してのみリソースのリクエストができる
- それ以外のオリジンに対するリソースのリクエストについては、正しいCORSヘッダーを含んでいることが必要

# CORSの種類

## 1. Simple Request

以下に示すメソッドは`Simple Request`に分類される
[CORSプリフライト](https://developer.mozilla.org/ja/docs/Web/HTTP/CORS#preflighted_requests)を引き起こさないメソッドのこと

- GET
- POST
- HEAD

## 2. Prefilight Request

リクエストの始めに OPTIONS メソッドで対象の異なるオリジンにリクエストを送り、実際のリクエストを送っても問題ないか確認する
サイト間リクエストがユーザーデータに影響を与える可能性があるようなメソッドがこれにあたる

- PUT
- DELETE
- CONNECT
- OPTIONS
- TRACE
- PATCH

# 具体的な実装について

[wip]別の手順を記載するほうで実装していたらそれに対するリンクを貼ること
husky&lint-stagedでcommit時に自動でlinterを通す

# 概要

- [りあクト！](https://oukayuka.booth.pm/)という本で学んだことでコミット時に自動でLintを走らせる内容があった
- この時インストールしている`husky`と`lint-staged`について調べたことをまとめる

## 参考資料：[Husky (v5) と lint-staged を使ってコミットする前に Prettier を実行する](https://chocoby.com/blog/2021/02/26/husky-v5-lint-staged-prettier)

# huskyとは

- Gitのhookを管理するツール
- npmのパッケージ
- バージョン管理している場合に、コミットやプッシュを行うときに任意のコマンドを挟むことができる
- Lintツールなどと併用して使うことで有用性が高まる

# lint-stagedとは

- Gitにステージされているファイルに指定したスクリプトを実行するツール
- Lintをすべてに通すのではなく、**差分に対してのみ通す**ことで効率化できる

# 導入の流れ

## 1. パッケージのインストール

```
yarn add -D husky lint-staged
```
## 2. package.jsonに設定

```
     "devDependencies": {
      ︙
      "stylelint": "^13.8.0",
      "stylelint-config-recess-order": "^2.3.0",
      "stylelint-config-standard": "^20.0.0",
      "stylelint-order": "^4.1.0"
    },
+   "husky": {
+     "hooks": {
+       "pre-commit": "lint-staged"
+     }
+   },
+   "lint-staged": {
+     "src/**/*.{js,jsx,ts,tsx}": [
+       "prettier --write --loglevel=warn",
+       "eslint --fix"
+     ],
+     "src/**/*.css": [
+       "stylelint --fix"
+     ],
+     "src/**/*.{gql,graphql,json}": [
+       "prettier --write --loglevel=warn"
+     ]
+   }
  }
```

# まとめ

- commitしたときに自動でLintが走るだけでなく、開発時の差分に対してのみLintが走るようにできるがいいと思った
IBM Security Verify API で 10000件のイベントログをダウンロードする

# はじめに
以前ご紹介した通り、IBM Security VerifyのAPIを使ってログをダウンロードする場合、1回のリクエストでは10000件までログを取得できます。
今回は、10000件のログ生成し、ダウンロードした結果をご紹介いたします。

ログのダウンロード方法や、オプションについては以下の記事をご参照ください。

- [IBM Security Verify API で イベントログをダウンロードする](https://qiita.com/fitz/items/4f8731c8a91ffe632b49)
- [IBM Security Verify API で イベントログを抽出するためのオプションあれこれ](https://qiita.com/fitz/items/235e86b3c9a483cee929)

# 10000件のイベントログダウンロード結果

今回は、ヨーロッパのトライアルテナントを利用しています。(日本データセンターのテナントではありません。)

コマンドプロンプトを使って、5回試行し、時間計測しました。
10000件のデータダウンロード結果は以下の通りです。

|No|項目|結果|
|---|---|---|
|1  |ダウンロード時間  |約18秒 (1回目19秒、2回目16秒、3回目26秒、4回目15秒、5回目15秒) |
|2  |ファイルサイズ  |11.6MB  |
|3  |行数  |444830行  |

ログダウンロード時間計測(1回目。2回目以降は画面割愛)

|![qiita(1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/c72b4a07-aea2-d709-8eb9-f3a14ed5b306.png)
|:--|

ダウンロードしたファイルサイズ

|![qiita(2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/097a8151-2e3c-1370-b11a-12826c5145a1.png)
|:--|

JSONの行数

|![qiita(3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678692/371b70bd-a887-5d70-ecd7-2917ede09472.png)
|:--|



# 最後に

今回は、認証成功/失敗操作を繰り返し10000件超のログを準備しました。
ログの種類や、メッセージ内容によってサイズや行数は変化します。ログダウンロード運用を検討頂く際の参考情報になれば幸いです。
Prettier まとめ

# 概要

- prettierというコードフォーマッターがあり、何気なく使用している
- ESLintでもコードのフォーマットができるらしいが、併用する理由が気になったので調べたことをまとめる

### 参考資料：[Prettier 入門 ～ESLintとの違いを理解して併用する～](https://qiita.com/soarflat/items/06377f3b96964964a65d)

# prettierとは

- JavaScript,TypeScript,JSX,JSON,HTML,CSS,YAML,Markdown,etc...様々な形式のフォーマットに対応している

# (そもそも)なぜコードフォーマッターが必要なのか

- 同じチームの中でスタイルがバラバラでは困るため
- (フォーマッターがなければ)各自が独自の整形ルールを適用していると、更新するたびに余計な差分が発生し、本来の修正箇所がぼける
- ソースが整形されている前提で話せるので、レビューの際にはより本質的な内容にフォーカスできる
- 設定した後は特に何も考えていなくてもツールが自動で整形してくれる(品質が一定に保たれる)

# prettierの導入

## 1. 必要なプラグインのインストール

#### 必要なプラグイン 

- prettier(prettier本体)
- eslint-config-prettier(Prettierと競合するeslintのルールを無効にする)

```
yarn add -D prettier eslint-config-prettier
typesync #typescriptテンプレートの場合に必要なコマンド
yarn
```

## 2. .eslintrc.jsonに設定を追加

- extendsに追加したパッケージのルールが適用されるように設定を追加する
- eslintの設定に上書きされないように一番下に追加すること

```json:.eslintrc.json
extends:[
  
  ...
  'prettier',
],...
```

## 3. デフォルト設定を変更したい場合に追加するファイルを作成する

- これだけでもprettierのフォーマットはできる
- デフォルトルールを変更したい場合は.prettierrcを作成してルールを設定する
- デフォルトルールは[こちら](https://prettier.io/docs/en/options.html)

```
touch .prettierrc
```

```.prettierrc
singleQuote: true
trailingcomma: "all"
```
## 4. npm-scriptsにエイリアスを追加する

- eslint --fixとprettierのフォーマットが一緒に実行されるようにする

```json:package.json
"scripts":{
  "fix": "npm run -s format && npm run -s lint:fix"
  "format": "prettier --write --loglevel=warn 'src/**/*.{js,jsx,ts,tsx,gql,graphql,json}'",
  "lint:conflict": "eslint --print-config .eslintrc.js | eslint-config-prettier-check",
{
```

# コードエディターにVSCodeを使用している場合

- VSCodeと連携させることでさらなるDX向上することができる

## 1. VSCode拡張をインストール

- [prettier code-formatter](https://www.hiroshinopage.com/introduction-and-usage-of-the-extension-prettier-code-formatter/)拡張を入れる

## 2. 設定を追加する

- プロジェクトで使用するsettings.jsonに以下を追記する
- ここで設定した形式について自動フォーマットを走るようにする

```json:settings.json
“editor.defaultFormatter": "esbenp.prettier-vscode",
  "[graphql]": {
    "editor.formatOnSave": true
  },
  "[javascript]": {
    "editor.formatOnSave": true
  },
  "[javascriptreact]": {
    "editor.formatOnSave": true
  },
  "[json]": {
    "editor.formatOnSave": true
  },
  "[typescript]": {
    "editor.formatOnSave": true
  },
  "[typescriptreact]": {
    "editor.formatOnSave": true
  },
```

# まとめ

- ESLintでは静的解析、Prettierではフォーマッティングを行わせる
- Prettierを使うことで個人だけでなく、チームで開発するときも利点が多くあることが分かった
箱ひげ図（boxplot）で外れ値を除いて描画する方法

pythonで群間の分布を比較する際に箱ひげ図を利用した時の事。
データをそのままカテゴリ毎に箱ひげ図を描画すると・・・

```python
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

df = load_data() # データの読込

sns.boxplot(df["sim_free_flg"], df["price"])
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658983/6a205ec8-f826-f66d-b2cb-bb2a7e556ecb.png)

外れ値があまりにも大きくて、大事なところが潰れてしまい、比較がしにくい・・・
そんなときに外れ値を除去して表示する方法がないか調べたところ
matplotlibのドキュメントでこんなパラメータを見つけました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658983/83cdae10-ea10-0d55-3b33-d3b91fdf492a.png)

`
フライヤーポイントのデフォルトシンボルです。空の文字列('')はフライヤーを隠します。Noneの場合、フライヤーのデフォルトは'b+'となります。より詳細な制御は flierprops パラメータで行います。
`

引数に`sym=""`を設定すると外れ値を表現しないらしい

```python
sns.boxplot(df["sim_free_flg"], df["price"], sym="")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/658983/a5670da4-38cb-b2ec-2572-ef180d1b0348.png)

簡単にできた！！
Ruby 問題15 銀行からお金を引き出すプログラムを作成

#問題

銀行に100,000円預金残高があり、お金を引き出すプログラムを作成して下さい。

* お金を引き出すと手数料110円かかり、「◯◯円引き落としました。残高は◯◯円です」と表示する（残高は手数料を引いた額を表示）

* 引き落とし金額と手数料の合計が、預金残高より大きい場合は「残高不足です」と表示する

#ヒント

```.rb
def withdraw(balance, amount)
  fee = 110 #手数料


end

balance = 100000 #残高
puts "引き落とし金額を入力して下さい（手数料110円かかります）"
amount = gets.to_i
withdraw(balance, amount)
```

#解答

```.rb
def withdraw(balance, amount)
  fee = 110
  if balance >= (amount + fee)
    balance -= (amount + fee)
    puts "#{amount}円引き落としました。残高は#{balance}円です"
  else
    puts "残高不足です"
  end
end

balance = 100000
puts "引き落とし金額を入力して下さい（手数料110円かかります）"
amount = gets.to_i
withdraw(balance, amount)
```

引数として、
**balance**に100000が渡され、**amount**には入力した引き落とし金額を渡ります。

メソッド内で条件分岐をして、100,000円以上か否かを判断し処理します。

```.rb
if balance >= (amount + fee)
    balance -= (amount + fee)
    puts "#{amount}円引き落としました。残高は#{balance}円です"
  else
    puts "残高不足です"
  end
```
100,000円が引き落とし金額と手数料の合計より大きいか等しいときの条件分岐になります。

そして100,000以下の場合は、`balance = balance - (amount + fee)`が処理され、
残高が返り値として出力されます。

100,000円以上になった場合は残高不足のメッセージが表示されます。
phpでfirestoreに接続

## laravel環境用意
- Laravel Sail

https://qiita.com/kai_kou/items/0e773aaf50698dd5a93f

　　　私はphp8の方使用。

　　　groupadd: invalid group ID 'sail'　問題にぶつかる以下解決

https://laracasts.com/discuss/channels/laravel/groupadd-invalid-group-id-sail


## grpcインストール
         

  - DockerFileにgrpc、protobuf(grpcのパフォーマンスを向上させるライブラリ)をインストールするために記述追加

```docker
    pecl install grpc && \
    pecl install protobuf && \
```

- php.iniに追加

    ```php
    extension=grpc.so
    extension=protobuf.so
    ```

- docker build
- コンテナーに入ってcomposer require

    ```php
    composer require google/cloud-firestore
    composer require kreait/laravel-firebase
    ```

    composer require kreait/laravel-firebaseはいらないかもなあ

- .envファイルに追加 hogehoge.jsonは以下設定で取得したファイル

    ```php
    GOOGLE_APPLICATION_CREDENTIALS="/var/www/html/hogehoge.json"
    ```

## 設定

[Cloud Firestore を使ってみる | Firebase](https://firebase.google.com/docs/firestore/quickstart?hl=ja)

- Google アプリケーションのデフォルト認証情報
    - サービスアカウント作成画面に移動

        [Google Cloud Platform](https://console.cloud.google.com/projectselector2/iam-admin/serviceaccounts/create?supportedpurview=project&hl=ja&_ga=2.255998920.2115025888.1624495369-380559855.1617854088)

    - プロジェクトを選択

    - サービス アカウントの作成

        サービスカウント名、説明(必要なら)を入力、作成して実行押下。

    - ロールを選択
    cloud databastoreユーザ選択、続行、許可
    - サービス アカウント一覧画面で先程作成したメールアドレスを押下
    - キーを押下、鍵を追加、新しい鍵を作成、jsonが選択されている状態で作成押下
    - ここで作られたjsonファイルがGOOGLE_APPLICATION_CREDENTIALS
- Laravelでとりあえずデータを取得してみる

    Hogecontroller.php

    ```php
    <?php

    namespace App\Http\Controllers;

    use Google\Cloud\Firestore\FirestoreClient;

    class HogeController extends Controller
    {
        public function get() {
            // Create the Cloud Firestore client
            $db = new FirestoreClient();
            printf('Created Cloud Firestore client with default project ID.' . PHP_EOL);
            $usersRef = $db->collection('users');
            $snapshot = $usersRef->documents();

            return view('document', [
                'snapshot' => $snapshot,
            ]);
        }
    }
    ```
ブラウザでデータ取得できていること確認



## 参照
https://qiita.com/43z708/items/e91c53710ef8cec4a537
GitHub Desktop


Github Desktopを使い始めるのに参考にさせてもらった記事

#第1位
https://qiita.com/YutyuT/items/8fc8f7a9596c2d4d114b
#第2位
https://qiita.com/yukiyan/items/2ea3dc5813fdba5d9cd2
#第3位
https://qiita.com/key_it6/items/a0d3c3669e080b4d8217
#その他
https://qiita.com/4ma9147/items/3629c9235f46dc7ec58c
https://qiita.com/nakanowatari-taiki/items/188c614ce2e3a6c42123

いつもわかりやすい記事ありがとうございます。
[React]Cannot destructure property 'id' of '(intermediate value)' as it is undefined.

下記のエラーが出たときの対処法

```
Cannot destructure property 'id' of '(intermediate value)' as it is undefined. 
```



idがundifinedのときがあるからlintエラーが出る

```tsx
const { id } = router?.query
```

#### 修正後

```tsx
const { id } = router?.query || {};
```

## 参考記事
https://stackoverflow.com/questions/48433008/js-es6-destructuring-of-undefined/48433029
Cloudflare Pagesでビルド時にreplaceAll is not a function出ちゃう件

# はじめに
こんにちは。今月で楽天モバイルの1年無料が終わるので解約する予定です。wifi専用端末として使用してきました！

**<font color="red">...長い間！！！　くそお世話になりました！！！</font>** :bow:

さて、今回は、**Cloudflare Pages**でビルドの際に使用しているreplaceAllでエラーが出てしまう件について書きたいと思います。

# エラーはこれ
```sh
TypeError: $(...).html(...).replaceAll is not a function
```

# 結論
**Cloudflare Pages**でビルド時に使用しているNode.jsのバージョンがv15.0.0より古いため。

replaceAllはv15.0.0で追加された。

https://github.com/node.js/node/pull/35415

## ちなみにCloudflareのNode.jsのデフォルトバージョン
**v10**でした :innocent:

https://developers.cloudflare.com/pages/platform/build-configuration#language-support-and-tools

# よし、Node.jsのバージョンを最新まで上げよう(2021/06/24現在)！

最新のNode.jsのバージョン確認します。

```sh
$ nvm version-remote
v16.4.0
```

(知らないうちにどんどん新しくなるな:thinking:)

Cloudflare Pagesの環境変数に登録するとバージョンを変更できます。

![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86984/a850f06c-c6ee-0960-e548-0e6c2dd238b1.png)

# おわりに
そもそもreplaceAll使わないっていうのもありですが、別件でNode.jsのバージョン古くて**Cloudflare Pages**でお困りの方の手助けになっていれば幸いです:pray:

それでは！
【MySQL】grant文を使用してselectできない特定カラムをつくる

SQLでは特定のユーザーに権限を付けて、操作を制限することができます。
今回はMySQLを使い、特定のカラムだけselectできなくする方法をまとめました。

grant文を使用することを前提にするので、遠回りですが以下の手順で行います。
**権限を持たないユーザーを作成し、selectしないカラム以外にselect権限を付与する（grant文）という方法です。**


![スライド1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605915/274580f1-313a-12e7-44d5-d4e89831bdbe.jpeg)


#手順① 権限のないユーザーを作成する


```sql:
/*ユーザーの確認*/
select user, host from mysql.user;

/*ユーザーの作成*/　
/*hirakegomaというパスワードで、someuserというユーザーを作成*/
CREATE USER 'someuser'@'somehost' IDENTIFIED BY 'hirakegoma';
```

ユーザーを作成しました。
しかし、権限は何もつけていない状態です。ので、この「someuser」でDBにアクセスしようとしても、ログインできません。

#手順② カラムレベルでselectできる権限をユーザーに与える

```sql:
/*カラムレベルで SELECTの権限を付与*/
/*mytbl1というテーブルのcol1, col2, col3というカラムにselcetする権限をsomeuserに付与*/
GRANT SELECT (col1, col2, col3) ON mydb.mytbl1 TO 'someuser'@'somehost' ;

/*特定のユーザー(someuser)の権限を確認する*/
SHOW GRANTS FOR 'someuser'@'somehost';

```

権限を付与すると、someuserのユーザーでDBにアクセスできるようになります。
例えば、「col4」だけselectできないようにするのであれば、「col4」だけ権限を付けないようにします。

someuserでDBにアクセスし、selectできるか確認しましょう

```sql:
/*現在のユーザーを確認する*/
select user(), current_user();

/*selectできるcol1を取得*/
select col1 from mytbl1;

/*selectできないcol4を取得*/
/*エラーが発生します。*/
select col4 from mytbl1;

/*mytbl の定義を確認*/
show full columns from mytbl1;

/*前列検索*/
/*エラーが発生します。*/
select * from mytbl1;
```

col1, col2, col3はselectできるようになりました。

show full columns ~ を使うと、すべての定義を確認できます。
権限も見ることができます。

**また、テーブルの中に、selectできるカラムと、selectできないカラムがある場合、
「select * from mytbl1」はできないようです。エラーになります。**

#手順③ 他テーブルにselect権限を与える

```sql
/*テーブルレベルで mytbl2テーブルにselectの権限をsomeuserに付与*/
GRANT select ON mydb.mytbl2 TO 'someuser'@'somehost';
```

手順②でmytbl1にselectできる権限をsomeuserに付与しました。
この状況では、他テーブルには権限がありません。ので、テーブルレベルで権限を付与する必要があります。ここでは、select権限を付与しました。ちなみに、selectの部分をPRIVILEGESとすると、指定されたアクセスレベルにあるすべての権限を付与できるようです。


#ユーザーを削除

```sql
/*ユーザー（someuser）の削除*/
DROP USER 'someuser'@'somehost';
```

ユーザーを削除するときは、こちらを使用します。


***

GRANT文では、レベルによって制御できるものが異なります。
ので、テーブルレベルで制御するのか、カラムレベルで制御するのかなど確認しておきましょう。

[MySQL 5.6 リファレンスマニュアル
13.7.1.4 GRANT 構文
MySQL によってサポートされる権限](https://dev.mysql.com/doc/refman/5.6/ja/grant.html#grant-column-privileges)

今回はGRANT文を使用しましたが、REVOKE文を使用してもよさそうですね！

#参考
Qiita『MySQLユーザ作成について』（2021年6月13日利用）
https://qiita.com/gatapon/items/92b942fa7081cfe17482

DBOnline『ユーザーを作成する(CREATE USER文)』（2021年6月13日利用）
https://www.dbonline.jp/mysql/user/index1.html

HACKnote『【MySQL】 テーブル・カラム毎に権限を変更する』（2021年6月13日利用）
https://hacknote.jp/archives/24570/

Qiita『[MySQL]権限の確認と付与』（2021年6月13日利用）
https://hacknote.jp/archives/24570/

Qiita『MySQL の権限のコマンドまとめ。』（2021年6月13日利用）
https://qiita.com/PallCreaker/items/0b02c5f42be5d1a14adb

DBOnline『ユーザーに設定できる権限の種類と一覧』（2021年6月13日利用）
https://www.dbonline.jp/mysql/user/index5.html

MySQL 5.6 リファレンスマニュアル『13.7.1.4 GRANT 構文』（2021年6月13日利用）
https://dev.mysql.com/doc/refman/5.6/ja/grant.html#grant-column-privileges
MySQLのselect結果をcsvファイル出力し、文字コードを変更する

MySQLのselect結果をcsvファイル出力し、文字コードを変更する手順を記載します。
やり方はいくつか方法があるようなので、1例としてとらえていただきたいです。
備忘録として残しておきます。

#①MySQLのselect結果をcsvファイル出力する

```shell:
mysql -h {host名}  -u{user名} -p {DB名} -e "{select * from mytbl}" | sed -e 's/^/"/g' | sed -e 's/$/"/g' | sed -e 's/\t/","/g' > /tmp/test.csv
```

{select * from mytbl}の結果をcsv形式で、/tmpの配下に、「test.csv」という名前で出力されます。

#②出力されたCSVファイルの文字コードを変更する

```shell:
iconv -f UTF-8 -t SHIFT_JIS /tmp/test.csv > /tmp/test_shiftjis.csv
```

UTF-8からShift_JISに文字コードを変更します。UTF-8の「test.csv」をShift_JISの「test_shiftjis.csv」に名前を変えて文字コードを変更しました。
文字コードをShift_JISにすると、Excelで開いたときに、文字化けしなくなります。
※同じファイル名にして試したところ、うまくいかなかったです。

#参考文献
Qiita『MySQLのSELECT文でcsvを出力する』（2021年6月23日利用）
https://qiita.com/catatsuy/items/9fdf4423d5f4885b9bf9

WEB ARCH LABO『MySQLのSELECT結果をCSVファイルで出力する方法』（2021年6月23日利用）
https://weblabo.oscasierra.net/mysql-select-into-outfile/

Qiita『MySQLのCSV出力が権限によって出来ない場合の対処法』（2021年6月23日利用）
https://qiita.com/kurkuru/items/9daee5e9d18d0a7154d5

エンジニアへの道『Linux文字コードの確認と変換の方法』（2021年6月23日利用）
https://www.flyenginer.com/low/low_shell/linux%E6%96%87%E5%AD%97%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E7%A2%BA%E8%AA%8D%E3%81%A8%E5%A4%89%E6%8F%9B%E3%81%AE%E6%96%B9%E6%B3%95.html

ねこの足跡R『[Linux] 文字コードを変換する』（2021年6月23日利用）
https://blog.katsubemakito.net/linux/convert-character-encoding
强制覆盖标准tag的css，或者标准的slds


    renderedCallback() {
        //この段階で標準のコンポのスタイルを上書きします
        console.log(this.isRendered);
        if (this.isRendered) {
            return; 
        }
        this.isRendered = true;
    
        let style = document.createElement('style');
        style.innerText = '.slds-th__action:focus, .slds-th__action:hover {background-color: #F5C9C6; color: #000000;}';
        this.template.querySelector('c-cks_custom_table').appendChild(style);
        let style2 = document.createElement('style');
        style2.innerText = '.slds-th__action{background-color: #F5C9C6; color: #000000;}';
        this.template.querySelector('c-cks_custom_table').appendChild(style2);
        let style3 = document.createElement('style');
        style3.innerText = '.slds-scrollable_x,.slds-scrollable--x{padding-bottom:10px !important;}';
        this.template.querySelector('c-cks_custom_table').appendChild(style3);
    }
EDA-確率質量関数(PMF: Probability Mass Function)

## 確率質量関数(PMF: Probability Mass Function)とは

離散型確率変数：離散型変数Xの取りうる値(x1,x2,...xn)のそれぞれに対応する確率pが存在する場合、Pを離散型確率変数といいます。

|X|x1|x2|...|xn|
|---|---|---|---|---|
|P(X)|p1|p2|...|pn|

確率質量関数は、離散型確率変数にその値をとる確率を対応させる関数です。
離散型確率変数Xがある値xをとる確率を関数f(x)とした場合、f(x)が確率質量関数です。

```math
f(x) = P(X=x)
```

全事象が起こる確率は1です。

```math
\sum_{i=1}^{n}P(X=x_i) = P(X=x_1) + P(X=x_2) + ... + P(X=x_n) = 1 
```

## PMFプロット

```python
import seaborn as sns

probabilities = df['col'].value_counts(normalize=True)    
sns.barplot(probabilities.index, probabilities.values)

plt.xlabel('Col')
plt.ylabel('PMF')
plt.show()
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/260307/998a3032-29f7-85d8-cd37-21e7bcb3b88f.png)
【shellscript】外部ファイルから変数を取得する

外部ファイル（設定ファイル）にある変数を利用する方法を綴ります。

外部ファイルにパスやファイル名など設定値を持たせておきます。
変更が発生際に直接shellを書き直すのではなく、設定ファイルのみを書き直すことで変更が容易になります。また、環境が変わっても設定ファイルの変更のみで対応できます。

![スライド1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/605915/fa20436e-6e3a-0f20-931a-99d9d2762577.jpeg)

```shell:conf.txt
#FILE_PATHという名前で変数を設定する
FILE_PATH="/usr/local/sample"

```

「source 外部ファイルのパス」を記述すると、外部ファイルから変数を取得できます。
外部ファイルのパスは「絶対パス」ではなく、「相対パス」で書きましょう。ディレクトリ構成が変わっても、書き直す手間をおさえられます。

```shell:sample.sh
#!/bin/sh

#設定ファイルから変数を取得
source ./conf.txt

#外部ファイルの変数をechoで表示
echo "$FILE_PATH"
```

実行結果

```shell
#test.shを実行すると、以下のように表示されます。
/usr/local/sample
```

#参考文献
Udemyメディア『【入門者向け】シェルスクリプトの作成・実行方法をわかりやすく解説！』（2021年6月23日利用）
https://udemy.benesse.co.jp/development/system/shellscript.html

Qiita『初心者向けシェルスクリプトの基本コマンドの紹介』（2021年6月23日利用）
https://qiita.com/zayarwinttun/items/0dae4cb66d8f4bd2a337