OmniAICreator/Qiita-1.07M huggingface dataset:
【実験】GitLabのデータをNFSで管理する -事前準備-

GitLabのリポジトリデータ等を外部のNFSサーバーで管理する方法を試してみたいと思います。
今回はその事前準備としてNFSサーバーの使い方を学習します。

# NFSとは
NFS(Network File System)は、名前の通りネットワーク越しでファイルのやり取りが可能となるシステムです。
Windowsで言う共有フォルダのようなものです。Windowsの場合はSMBというプロトコルを使用しています。

# NFSサーバーの設定
それではNFSの設定を試していきたいと思います。
なお例として今回使用するNFSサーバーのIPは```192.168.0.2```、NFSクライアントのIPは```192.168.0.3```とします。
まずはNFSサーバー側にNFSサービスのインストールを行います。

```
sudo yum install -y nfs-utils
```

インストール完了後、共有ディレクトリを作成します。
ディレクトリの作成後、作成したディレクトリのパスをコピーしておきます。

```
mkdir <共有ディレクトリ名>
cd <共有ディレクトリ>
pwd #実行後に表示されたパスをコピー
例:
/home/nfs
```

続いて```/etc/exports```ファイルに以下のように共有させるディレクトリのパスと共有させたいクライアントのIPアドレスを記載します。
オプションを指定する場合は、クライアントのIPアドレスの後ろに()をつけて、その中にオプションを記載します。
オプションを複数指定する場合は、「,」で区切ります。

```ruby:/etc/exports
<pwdコマンドでコピーしたパス> <クライアントのIPアドレス>(<オプション>)
オプション一例
rw:クライアントに書き込みを許可
async:非同期書き込みを有効にする
no_root_squash:クライアント側のroot権限にて実行可能とする
例:
/home/nfs 192.168.0.3(rw,async,no_root_squash)
```

NFS自体の設定は完了ですが、Firewallを設定していない為このままではNFSの通信が弾かれてしまいます。
以下のコマンドを実行し、NFSの通信を許可します。
ちなみにクライアント側はFirewallの穴あけは必要無いみたいです。

```
sudo firewall-cmd --permanent --zone=public --add-service=nfs
sudo firewall-cmd --reload
sudo firewall-cmd --list-all #serviceにnfsが追加されていればOK
```

準備が完了しましたら、NFSのサービスを起動させます。
ついでにOS起動時に自動でサービスを立ち上げるようにしています。

```
sudo systemctl status nfs-server
sudo systemctl start nfs-server
sudo systemctl status nfs-server
sudo systemctl enable nfs-server
```

以上でNFSサーバー側の作業は完了です。

#NFSクライアントの設定
次にクライアント側の設定を実施します。
まずは共有ディレクトリをマウントする為のディレクトリを作成します。

```
mkdir <マウントディレクトリ名>
cd <マウントディレクトリ>
pwd #実行後に表示されたパスをコピー
```

続いて```mount```コマンドを使用してNFSサーバーの共有ディレクトリをマウントします。
この時、オプションで```-t nfs```を指定します。

```
sudo mount -t nfs -o rw <NFSサーバーのIPアドレス>:<NFSサーバーの共有ディレクトリへのパス> <コピーしたマウントディレクトリへのパス>
例:
sudo mount -t nfs -o rw 192.168.0.2:/home/nfs /mnt/nfs
```

上記コマンドがエラー無しで通ったら、```df -Th```コマンドを実行して正しくマウントされているか確認します。

```
sudo df -Th
例:
ファイルシス             タイプ   サイズ  使用  残り 使用% マウント位置
devtmpfs                 devtmpfs   3.9G     0  3.9G    0% /dev
tmpfs                    tmpfs      3.9G   12K  3.9G    1% /dev/shm
tmpfs                    tmpfs      3.9G  9.7M  3.9G    1% /run
tmpfs                    tmpfs      3.9G     0  3.9G    0% /sys/fs/cgroup
/dev/mapper/centos-root  xfs         17G  4.4G   13G   26% /
/dev/vda1                xfs       1014M  150M  865M   15% /boot
tmpfs                    tmpfs      783M     0  783M    0% /run/user/0
192.168.0.2:/home/nfs    nfs4        22G  1.4G   21G    6% /mnt/nfs
```

# 動作の確認
NFSサーバーとNFSクライアントにて設定が完了しましたら、クライアント側にて正しく共有ができているか確認してみます。
以下コマンドを実行します。

```
touch <マウントディレクトリへのパス>/test.txt
例:
touch /mnt/nfs/test.txt
```

エラーが返ってこなければ完了です。
続いて上記コマンドで作成したテストファイルが格納されているかサーバー側で確認します。

```
ll <共有ディレクトリへのパス>
例:
ll /home/nfs
```

上記コマンド実行後、クライアント側で作成したテストファイル```test.txt```が表示されていれば正しくNFSで共有できている事を確認できます。
以上で事前準備は完了です。
次回は今回実施した内容を応用し、GitLabのデータをNFSサーバーで管理するように設定します。
【備忘録】li要素を横並びに均等に並べる方法

htmlにおいて、liの要素を横並びで均等に並べたい時はflexを利用する。
htmlが次の通りの時、

```html
<ul class="list">
  <li>list1</li>
  <li>list2</li>
  <li>list3</li>
</ul>
```

CSSを下記の通り記述する。

```css
.list {
  display: flex;
}

.list li {
  flex: auto;
}
```

ちなみにリストごとに色をつけて表示するとわかりやすい。
<details><summary>HTMLファイル</summary><div>

```html
<html>
  <head>
    <link rel="stylesheet" type="text/css" href="index.css"/>
  </head>
  <body>
  <ul class="list">
    <li class="l1">list1</li>
    <li class="l2">list2</li>
    <li class="l3">list3</li>
  </ul>
  </body>
</html>
```
</div></details>
<details><summary>CSSファイル</summary><div>

```html
.list {
    display: flex;
}

.list li {
    flex: auto;
    height: 20vh;
    list-style-type: none;
    color: white;
}

.l1 {
    background: red;
}

.l2 {
    background: blue;
}

.l3 {
    background: green;
}
```
</div></details>

こんな感じになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147946/ebb789ac-b971-8951-e887-b2cad81d3f0b.png)
arc(),ellipse(),rect() だけでできるガチャピンプログラミング 



こんにちは！青山学院大学　古橋研究室 所属の神田洋輔と申します。
普段は研究室での活動をmediumへ投稿しております。ですのでQuiitaへの記事投稿は初めてです！
そんな記念すべき第一回目の記事は、ガチャピンプログラミングです！！

#なぜガチャピン？
んん？・・・
ガチャピンプログラミングとはなんぞや？...
そう「ガチャピンの顔をプログラミングで書いてみよう！」と、ただシンプルにそれだけです笑
なぜこんなにシンプルかというとそれは私自身プログラミング初心者だからなのです笑
そしてなぜガチャピンかというところですが、古橋研究室は2015年より、「みんなの防災＋ソナエ」プロジェクトでガチャピン・ムックと一緒に子どもたち向けの災害ドローン体験会を行っており二人とはそのような関係があるのです。
そして今回研究室内で行われた月例のハッカソンのテーマが「ガチャムクハッカソン」だったということです。私はデジタルファブリケーションの観点からものづくり部代表として取り組みました。

#つくりかた
つくりかたはとってもとってもシンプルです。今回使用した関数はarc() 弧、ellipse() 円（楕円、正円）、rect() 矩形(長方形、正方形）のみです。ガチャピンの顔は単純化するとこのくらいの要素があれば描けてしまうことがわかりました笑
![1_gaq42S6txl0p2XqU6gVExQ (1).jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/911603/2d1095b5-c63f-8e11-216e-42ee90443c1b.jpeg)

[こちらの記事](https://www.d-improvement.jp/learning/processing/2011-a/02.html)を参考にしますとProcessingで図形を描くにはあらかじめ用意されているこのような関数を組み合わせることでオリジナルのイラストを表現することができます。ぜひ色々な関数を試してみてください！
#### 要素は簡単だけど配置や配色も考えないと...
使う関数は決めましたが今度はそれぞれの図形を置く場所についてや配置も検討しなければいけません。最初はx,y,zの座標を想像しながら大体の位置決めをします。それから色付けをRGBで決めていきます。この過程が一番重要でどうやったら似せることができるかと、かなり試行錯誤しました笑
一部コードはこんな感じになります。

```
// ガチャピンSVG
import processing.svg.PGraphicsSVG;

// PApplet
beginRecord(SVG, "PApplet.svg");
size(600, 600);
//noStroke();
background(255);

//eyes
fill(255,255,255);
ellipse( 230, 240, 80, 80 );
ellipse( 370, 240, 80, 80 );

//mini eyes
fill(0,0,0);
ellipse( 370, 245, 50, 50 );
ellipse( 230, 245, 50, 50 );
```



#プログラミング初体験作品
###口が微妙ですがほぼ完成！
![95683111-2be95500-0c24-11eb-9a6b-d75a46f94246.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/911603/108a151b-ea2d-dc0b-58ed-61620fdc4b00.png)



バリバリの文系である私は去年の10月頃に大学の研究室の活動でプログラミングというものに出会いました。なのでプログラミング歴でいうと0.5年にも至らない超初心者です笑　
[Processingはじめました](https://medium.com/furuhashilab/processing%E3%81%AF%E3%81%98%E3%82%81%E3%81%BE%E3%81%97%E3%81%9F-1051af3660d)　←そのころのmedium記事です
本当は高度な関数を駆使してジェネラティブアートのような要素も入れて、もう少しプログラムを使う意味を出したかったんですが勉強不足により今回はここまでになります。。

しかしProcessingは電子アートとビジュアルデザインのためのプログラミング言語なのでそんな私にもとても易しく、イラストを描くように楽しみながら挑戦することができました。この記事がこれからプログラミングを始めてみたいけれどなにからすれば...という方の一助になれば幸いです！
ここまで読んでいただいてありがとうございました！
[ガチャピンSVGほぼ完成]
(https://medium.com/furuhashilab/%E3%82%AC%E3%83%81%E3%83%A3%E3%83%94%E3%83%B3svg%E3%81%BB%E3%81%BC%E5%AE%8C%E6%88%90-78406cdc3fe)

####  code はこちらにありますのでぜひご覧ください

https://github.com/furuhashilab/fabla-bu/issues/5#issuecomment-706724268
Laravelで画像を保存 / 取得する

<h2>Laravelで画像の保存 / 取得を実装する</h2>
<h3>記事内容</h3>
Laravelではデータベースを使って、画像の保存/取得などを実装できます。
今回は画像の保存から表示まで実装していきます。
<h2>開発環境</h2>
Laravel 8.22.1
PHP：8.0.1
MySQL：8.0.23
MacOS：11.1 ( Big Sur )
<h2>やろうとしていること</h2>
<ol><li>ビューでformを作り、画像をアップロード。</li><li>Controllerで画像を保存。</li><li>保存した画像を取得。</li><li>画像をビューで表示。</li></ol>

<h2>画像のアップロード</h2>
<h3>ビューでformを作る</h3>

```○○.blade.php
<form action="/任意のurl" method="post" enctype='multipart/form-data'>
  <input type="file" name="thumbnail" />
  <button>登録</button>
  {{ csrf_field() }}
</form>
```

type="file"とすることで、ファイルを選択できるようになります。
formタグにenctype=“multipart/form-data”を書く必要があります。
enctypeは送信データのエンコードタイプを指定しており、
multipart/form-dataは、データをマルチパートデータとして送信します。
フォーム内にファイルの送信欄を配置する場合は、上記形式を指定しておく必要があります。
また、enctype属性が記述されている場合、formのmethod属性はpostを指定しておく必要があります。
<h2>Controllerで画像を保存</h2>

```○○Controller.php
public function store(Request $request)
    {
        $user = new User;
 
        // name属性が'thumbnail'のinputタグをファイル形式に、画像をpublic/avatarに保存
        $image_path = $request->file('thumbnail')->store('public/avatar/');

        // 上記処理にて保存した画像に名前を付け、userテーブルのthumbnailカラムに、格納
        $user->thumbnail = basename($image_path);

        $user->save();

        return redirect()->route('任意のビュー');
    }
```
\$request->file('name')->store('任意のディレクトリ');とすることでstorage/app直下の任意のディレクトリにユニークなファイル名で保存されます。
画像は、storage/app直下のpublic/avatarに保存されています。

今回、上記のファイル名を、\$image_pathという変数に格納しています。

そして、\$user->thumbnail = basename(\$image_path);の記述で、Userモデルのthumbnailカラムにファイル名、つまり\$image_pathを保存します。

つまりデータベースに保存するのは、画像ではなく画像に任意でつけたファイル名ということです。
※画像を表示するのにヘルパ関数のassetを使うことを前提にしているため。

<h2>Controllerで画像を取得</h2>
<h3>データベースに保存したファイル名を取得する</h3>
先ほど、users_table ( Userモデル ) のthumbnailカラムにファイル名を保存したので、そこから取得してビューへ渡します。

```○○Controller.php
public function index(){
  $user = User::all();

  return view('任意のビュー', $user);
}
```
<h2>画像をビューで表示</h2>
<h3>viewファイルで画像を表示する</h3>

先ほどのControllerの記述では、画像はstorage/app/public/配下のディレクトリ (今回の場合だと"avatar" ) に保存されています。
しかし、このディレクトリはwebからのアクセスを許可しません。
そのため、データベースからファイル名を取得しても画像は表示されません。

artisanコマンドでstorage:linkとすることでstorageのファイルがpublic直下に同期されます（publicディレクトリの直下にstorageが追加されています)。

<ul><li>画像が保存されている場所：storage/app/public/avatar</li><li>画像を取得する場所：public/storage/avatar</li></ul>


```
public artisan storage:link
```
CLIで上記のコマンドを通すことで、public/storage配下に保存されている画像にアクセスできるようになりました。

あとはビューでassetを使って画像を表示します。

```○○.blade.php
<img src="{{ asset('storage/avatar' . $user->thumbnail) }}" />
```
<span></span>
これで画像の保存から表示まで実装できました。
Vue.jsが効かない時はelが親子関係になっていないかチェックしよう

入力フォーム要素の位置を変更したら、Vue.jsが効かなくなった！ということがあったので共有します。
#原因：elの指定部分が親子関係になっている
入力フォームの位置を変更したところ、元々機能していたv-onディレクティブが機能しなくなるということがありました。
試行錯誤の末、たどり着いた結論は「フォームの移動先が別のVueインスタンスのelで指定されていたことが原因」でした。
簡単な例で示すと

```html:
    <div id="parent">
        {{greet}}
        <div id="children">
            {{number}}
        </div>
    </div>
```
に対して、

```javascript:
new Vue({
    el:'#parent',
    data:{
        greet:'hello'
    }
});
new Vue({
    el:'#children',
    data:{
        number:'123'
    }
});
```
では
![helloonly.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1110285/56ebfab9-9760-c8f4-aac1-693c1c38d56f.png)

とparent部分しか機能しません。
Vue.jsがうまく効かない時は、elの指定部分もチェックするようにしましょう。
[Kotlin]Android StudioでToDoアプリを作るまで

#はじめに、作り方を解説するものではなく調べた軌跡を残したもの
AndroidStudioでアプリ開発をしてみたいと思います。

しかし未経験なので何か簡単なものから始めたいです。

ということでToDoアプリなら簡単に作れるのでは？という思いからToDoアプリの構造として欠かせないリストを作る方法を調べていきます。

##リストには昔はListViewを使っていたみたい、だけどRecyclerViewのほうがよさそう
AndroidStudioにはListViewとRecyclerViewがあるのですが

[RecyclerViewはListViewの代替ではないよねという話](https://sys1yagi.hatenablog.com/entry/2015/01/09/090000)

らしく

>RecyclerViewはListViewでは解決出来ない or より自由にカスタマイズしたい場合に使う

「え！？結果どっち使えばわからねえ」

となったので、これはどっちも作ってみるかあと

##簡単そうなListViewから作ろうと思う

##作りたいものは共通させてどちらがふさわしいか決める

・リスト表示
・リストの要素を追加
・リストの要素を編集
　Ⅼリストの要素を削除

最低限これがあれば、ToDoとしての役目を果たすのでこれを目標に作ります。


##ListViewの使い方

[KotlinでAndroidアプリのlistviewを実装する方法を現役エンジニアが解説【初心者向け】](https://techacademy.jp/magazine/32252)

これコピッた

AndroidStudioでEmptyで作成して、最初にactivity_main.xmlを作りました

最初にあるTextViewは削除してListViewを追加しました。

ListViewはLegacyってとこにあるのでそれをDDしてidが未設定なのでListViewと名付けます。

レイアウト系の設定は丸こぴしました。

MainActivityをつくっていきます。

これもほぼまるこぴです。

最後のListView.adapter = adapterでエラー発生

.adapterのところが赤字になっている

おそらくこれじゃ実行できないと思いつつ実行

案の定実行できませんでした

エラーメッセージは
Unresolved reference: adapter

調べるとこの名前は定義されていないから駄目だよと言われているらしい

確かにlistViewの定義がされていないので

```kotlin:MainActivity.kt
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        var listView = findViewById<ListView>(R.id.listView)

        val data = arrayOf("あり", "いもむし", "だんごむし", "てんとうむし")

        val adapter = ArrayAdapter(
                this,
                android.R.layout.simple_list_item_1,
                data
        )

        listView.adapter = adapter
    }
}
```

最初の行にfindViewByIdをつけてあげる

エラーがなくなり実行できました。

![listview_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1110207/eab920d1-03e4-4ee1-354e-111426e3d4c4.png)

リスト表示はできますが、クリックしたときの処理などをしていないのでタッチしてもなにも起きません。

参照サイトにクリックしたときの処理があったので試しに書いてみます。

これを核とタッチした要素がトーストされるらしい。

トーストってなんだ？

実行した結果は要素をタッチしたら画面下にそのテキストが表示される感じ、トーストってこんなことができると記憶しておく

![listview_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1110207/54512549-686d-7163-fc85-bf76cf4436a7.png)

リストの表示はできた、あとは追加と編集（削除）ができれば文句ない

でも要素をタッチして編集はいいけど追加などはほかにプラスボタンとかがあると便利である。

具体的な内容を定義しよう
・追加ボタンを作成
・要素をタッチすると編集できる、要素を左にスライドさせるとその要素を削除する

これは勘だけどスライドしたら要素を削除はListViewでできない気がする。

編集はトーストの要領でその命令を変更すればいいだけだと思う

追加はボタンを作成して、それを押したら配列に対して追加するように命令を出せばいいと思う。

ここで詰まる

setOnItemClickListenerで配列をいじれないかもしれない問題、というかいじり方がわからない問題が発生中

元のコードではタッチされた要素に対する処理だから元の配列については関与していないためだと思われる。

とはいえよくわからないので、ネットサーフィンしてきます。
Windows10でpoetry

Pythonのパッケージ管理はpoetryが便利です。
`poetry install`ですぐに環境を再現できます。
pipを利用するためpyenvとの相性がいいです。
そんなpoetryをWindows10でも使うための方法です。
（公式にもあるので新しい情報はないです。）

# インストールのコマンドまとめ

サクッとインストールしたい人はこちらを参照してください。

```powershell
# powershell
python -V
(Invoke-WebRequest -Uri https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py -UseBasicParsing).Content | python -
poetry --version
poetry config virtualenvs.in-project true
```

# インストール方法

## 前提条件
Pythonがpowershellで使えること。
具体的には次のコマンドでバージョンが確認できること。（3.xを推奨します。）

```powershell
python -V
```

## poetry
基本的には公式に従います。
公式にあるようにpipでのインストールは推奨しません。
（poetryのパッケージ管理にpoetryが含まれてしまうため。）

poetry：https://python-poetry.org/docs/

powershellで以下のコマンドを実行すれば、ほぼ終了です。

```powershell
# powershell
(Invoke-WebRequest -Uri https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py -UseBasicParsing).Content | python -
exit
```

一度powershellを終了し、以下のコマンドでpoetryがインストールしていることを確認します。

```powershell
poetry --version
```

もしうまくインストールされていないようであれば、
アンインストールして環境を確認してみましょう。
アンインストールは`--uninstall`を付けるだけです。
参考：https://qiita.com/makuramoto1/items/b3f4a0d610e4f97ef3f8

```powershell
(Invoke-WebRequest -Uri https://raw.githubusercontent.com/python-poetry/poetry/master/get-poetry.py -UseBasicParsing).Content | python - --uninstall
```

最後に、プロジェクト内に仮想環境を作成するように設定することをお勧めします。
これを実行しておくとプロジェクトのルートに`.venv`が作られるようになります。

```powershell
poetry config virtualenvs.in-project true
```

# ちょっと使ってみる

```powershell
# 新しくプロジェクトを作る(ディレクトリが作成されます)
poetry new

# 新しくパッケージ管理を行う(tomlファイルができます)
poetry init

# すでに管理されているプロジェクトにパッケージ情報を反映(tomlをもとにインストールします)
poetry install

# パッケージを追加(tomlファイルも更新されます)
poetry add [module]
```

# まとめ
まとめるほど内容はないですが、poetryは1行で導入できます。
Pythonの環境はpyenv-winで導入するといいと思います。
シンボリックリンクとか自分で張ったりするのは大変なので。
1500円で完成！子ども達が玄関前から親にLINEメッセージを送るIoTボタンの作成(ATOM Liteにて)

#課題
子どもがまだ小学生で我が家の方針としては基本的にカギを持たせていません。落とす可能性を心配して。
妻と私が不在の時にはカギを渡します。
しかしながらトラブルなどで二人共戻るのが遅くなった場合子どもが玄関前で待ちぼうけということが過去何度かありました。

#解決策
玄関前に「子ども達が先に帰宅した時に玄関前から親にLINEメッセージを送るボタン」を設置する
#当初構想
micro:bitとESP32-WROOM-32などを組み合わせて、、、
どうせなら基盤を作って、、、ESP32のイメージはデフォルトのままで、、、ATコマンドを使って、、、
など色々と理想を掲げてはや数年。思うようなものは完成せず。
その間に待ちぼうけ問題は継続して発生していました。(年1～2回)

#決断
2021年2月の寒いある日、同様の待ちぼうけ問題が発生、我が家の喫緊の課題となったためなるはやの完成を決断。

#構成
ハードウェア：ATOM Lite([価格と機能で選択 税込み968円！](https://www.switch-science.com/catalog/6262/)、玄関前に置いておいて盗まれても痛くない。Wi-Fi内蔵)、これにモバイルバッテリ－500円。合計1500円。
システム：ATOM Lite >> 家のWi-Fi >> IFTTT >> LINE Notify >> 家族のLINEグループ

#IFTTTでの設定
[IFTTT](https://ifttt.com/)上で Webhook >> LINE Notifyの設定を行う。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71746/c5fc275d-4d81-6818-482a-65ee801d72f0.png)

#コード
[UIFlow](https://flow.m5stack.com/)にてブロックプログラミングで作成。楽ですね。
空白部分はWi-FiのID・パスワードをインプットします。
![wifi22.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71746/924a100e-cef6-b1cb-30e9-24b72d7fd81f.png)

#完成イメージ
モバイルバッテリーに接続して利用します。
動画は[こちら](https://youtu.be/iVwyrL06FBo)。
[![](https://img.youtube.com/vi/iVwyrL06FBo/0.jpg)](https://www.youtube.com/watch?v=iVwyrL06FBo)


#設置イメージ
タッパに入れたコレを玄関前のボックス(施錠なし)に入れておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71746/0c7c11e6-e677-8c54-2b0c-30545782a6af.png)
レジストリ管理のメモ書き

# リポジトリ、レジストリを説明できる程度に理解する
あくまで自分の理解のためなので、メモ書きとしてご覧ください。
何か追加情報があり次第、その都度更新する予定

# 目次
+ レジストリ、リポジトリとは
+ 今回注目するサービスの利用フロー
    + dockerhub
    + Amazon ECR 

# レジストリ、リポジトリとは
人に説明できるように意味合いのブレイクダウンは必須

### リポジトリとは

↓一般的にな意味合い
>英語で「貯蔵庫」「収納庫」の意味。アプリケーション開発の際に、システムを構成するデータやプログラムの情報が納められたデータベースのことを指す

↓Dockerリポジトリとは
>名前が同じでタグが異なるコンテナー イメージまたはその他の成果物のコレクション

例：リポジトリが**dokaben**
dokaben:v1.0
dokaben:v1.1

### レジストリとは

↓一般的にな意味合い
>Microsoft Windows オペレーティングシステム(OS)で用いられている設定情報のデータベースである

↓Dockerレジストリとは
>Dockerイメージを保存するサービス

↓レジストリサービス
Docker Hub、Quay、Google Container Registry、AWS Container Registry など

※ github : コードのバージョン管理システム

# 今回注目するサービスの利用フロー

### dockerhub

※何かあり次第、更新

### Amazon ECR

※何かあり次第、更新

**注意点**
1. docker/awsのconfigファイル設定必須
2. awsログインセッションは12時間で消える
- 対処法として、cronを用いた
- kubernetes環境上では、cronjobを活用（まだ試せていない）
RedHat8でsudoにてコマンド実行時に[No protocol specified]が表示される

Red Hat Enterprise Linux release 8.3
※以下の方法はセキュリティに影響があるため、注意する必要があります。

以下のような事象の場合
sudo <コマンド>
No protocol specified
Error: couldn't open display

対応方法：
ログインしているユーザにて、以下のコマンドを実施する。
xhost +si:localuser:root

ログイン時に自動設定する場合は、以下へ追記する。
/home/<ログインユーザ>/.bash_profile

/usr/bin/xhost +si:localuser:root

参考：
Root で X アプリケーションを起動
https://wiki.archlinux.jp/index.php/Root_で_X_アプリケーションを起動
WoWLANで勝手にスリープ解除される原因がライブタイルだった話

WoWLANで勝手にスリープ解除される事象が発生し、スリープが使い物にならなくなっていたが原因が判明した。タイトルでネタバレしているように意外なものが原因であったため、ここにまとめる。

# 事象
WoWLAN (Wake on Wireless LAN) で30分に1回程度勝手にスリープ解除される。

# 環境
下記スペックの自作PCにて事象の発生を確認。

* AMD Ryzen 9 5950X
* NVIDIA GeForce RTX 3080
※Wi-FiのネットワークアダプターはIntel Wi-Fi 6 AX200
* DDR4-4000 16GBx2
* ASUS ROG STRIX X570-I GAMING

# 原因
Windows 10のライブタイルにより設定されたStartMenuExperienceHost.exeのタイマーが原因。管理者モードでコマンドプロンプトまたはPowerShellを開き、`powercfg -waketimers`でStartMenuExperienceHost.exeが登録されていることを確認。

```
PS C:\Windows\system32> powercfg -waketimers
[PROCESS] \Device\HarddiskVolume3\Windows\SystemApps\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\StartMenuExperienceHost.exe によって設定されたタイマーは 4:00:00 () で有効期限が切れます。
```

ここではメッセージに4:00と出力されているが、事象が発生する時刻はこの時刻と無関係。

# 解決策
ライブタイルからフォト、天気を削除してOS再起動を実施。

![スクリーンショット 2021-02-13 180208-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/115445/e77e48a0-16ec-c947-c4ec-509c285c5cdf.png)

再起動後、再度管理者モードでコマンドプロンプトまたはPowerShellを開き、`powercfg -waketimers`でStartMenuExperienceHost.exeが登録されていないことを確認。

```
PS C:\Windows\system32> powercfg -waketimers
システムにアクティブなスリープ解除タイマーがありません。
```
WindowsのPCからコマンドでgithubと連携

githubのデスクトップアプリ（mac）ばかり使っていて
gitについてまったく理解していなかったので、自分のメモとして投稿します。

# ターミナル上にて
まずはターミナル上で、githubとリモート連携したいフォルダへ移動します。
コマンドはここでは解説しないので、[ターミナル（コマンド）](https://qiita.com/yoshi-2015/items/90e463a264b041b4f5e3)の記事を参照ください。

# gitの初期設定をする

```console
$ git init
$ git add .
$ git commit -m 'xxx'
```
`git init`でgitファイルを追加し、`git add .`、`git commit -m 'xxx'`してpush手前までもっていきます。

# github上で受け入れ準備

![20210214-01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480700/48a7ab9d-e49c-5873-4704-c772d06f425c.jpeg)

「New repository」でリポジトリ追加画面へ移動。

![20210214-02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480700/64bc2cb1-ecf9-0de3-64a1-1396f37f3f0e.jpeg)

1.「Repository name」を入力。（レギュレーションはgithubに従う。緑チェックがでれば使用可能）
2.公開ステータスを設定。「Public」「Private」の2種類から選べます。「Public」にすると全世界に公開されてしまいます。危険性については下記の記事が有名ですね。（遠い目）
[【SMBC漏洩 騒動まとめ】三井住友銀行のソースコードを年収300万の艦これユーザーが無断で公開](https://matomame.jp/user/mixmio/cb93bf4e85c072b4a2a3)
3.「Create repository」でリポジトリを作成

githubへの受け入れ準備はこれでOK

# またまたターミナルで操作

```console
$ git remote add origin https://github.com/kaorioka/hogehoge.git
```
1.リモートリポジトリを追加するコマンドを入力。
`https://github.com/~`の部分を今回連携するリポジトリのものにする。
URLはgithubで「Create repository」押下後に表示される画面にでてくるものを使用。
下記の画像のHTTPSのURLをコピー！

![20210214-03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480700/0f8fc323-5ef7-b8cb-541a-a28f0c117ceb.jpeg)

2.プッシュ！

```console
$ git push origin master
```
上記のコマンドでgithubのリモートリポジトリにプッシュできていれば完了です。
AKBONE2020 用の Windows ポータブル開発環境を構築する ( LGT8F328P - Arduino の設定 )

# 環境 
Arduino 1.8.13

# ダウンロード

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/a2910433-f2c8-9201-7746-497699cde98e.png)

Windows ZIP版をダウンロードします

# 展開

7-zip を使って展開します。デスクトップに Arduino-portable というフォルダを作りそこに展開します。
デスクトップの Arduino-portable の中は以下のようになるようにしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/4a1547b5-466d-b808-ca2f-0ef52dbd3513.png)

# portable 設定

Arduino-portable に portable というフォルダを作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/a8ebe6b5-e7ed-8e28-d0c1-60b15f046032.png)

arduino.exe をダブルクリックして実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/4f81187d-a643-5222-9ac7-07a621dccf73.png)


以下の表示が出たら許可をします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/ee176c36-6a75-d001-11c3-3adf2c5716b2.png)

Arduino IDEが起動しました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/6f319309-b613-06fd-2447-17f748190337.png)

一旦 Arduino IDE を終了します。

# LGT8F328P の設定

http://www.lgtic.com/downloads/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/f26a75cc-fde5-c842-ca65-61030be0634c.png)


から、

「Arduino开发平台相关」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/c0044439-e62d-39d5-5bb6-03a8ad0419b9.png)

をダウンロードします。
解凍します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/07911f80-d43b-2a3c-76e3-9cdeb6441e3c.png)
解凍したものを、デスクトップの  Arduino-portable の Sketchbook 
に移動します。

libraries が既にあるので結合で「はい」とします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/d252b67c-e0a4-dbe6-56d0-5cd363be8be4.png)
移動した結果はこのようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/a7fff610-21ad-f369-ff3d-6b5ccf6f32c1.png)

このようになります。


もう一度、arduino.exe を実行します。

「ツール」- 「ボード」-「Arduino AVR Boards(in sketchbook)」で、「LGT8F328P-SSOP20 MiniEVB」を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/8a57f422-6a41-6ff8-ed15-3bcfaa1026b9.png)



# ライブラリの設定

LEDストリップのライブラリを追加します。
「ツール」-「ライブラリを管理...」でライブラリマネージャを起動、「NeoPixel」と打ち込んで「Adafruit NeoPixel」を「インストール」します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/07939210-7f66-ac72-6bef-03b2c08e0e5e.png)

# arduino-portable 環境の完成

デスクトップにできた arduino-portable は、USBメモリなどにコピーして、USBメモリから実行することができます。
ルート定義のパラメータに制約を設定することの重要性【例：Laravel5.5】

ルート定義の制約なしのパラメータ設定には危険が潜んでいます。
制約をつけておかないと、意図していないURLまで通ってしまうことがあります。

自分一人で開発していて小規模の案件であればURLを把握しているかもしれませんが、把握しきれていない場合に自分の担当ページのことだけを考えてルート定義に制約なしのパラメータを設定すると、既存のページに影響を及ぼすことがあります。（ありました。←）

本記事ではLaravel5.5を例に挙げて記載していきます。

##制約なしのパラメータの記述

```.php
// 必須パラメータの場合
Route::get('user/{id}', function ($id) {
    return 'User '.$id;
});
// 任意パラメータの場合 ? を記載します
Route::get('user/{id?}', function ($id = null) {
    return $id;
});
```
参照：https://readouble.com/laravel/5.5/ja/routing.html
見出し【必須パラメータ / 任意パラメータ】

上記のように、制約なしのルート定義の場合、例えばURLの『user/`hoge`』`hoge`の部分に何が入っても、上記のルート定義を通るようになってしまいます。

idなので、数字のみ通るように制約を付けておきたいと思います。

##パラメータの制約設定

制約をつけるには、ルートインスタンスの`where`メソッドを使用し、定義する正規表現を引数に設定します。

```.php
Route::get('user/{id}', function ($id) {
    // {id}が数値の場合のみ実行される
})->where('id', '[0-9]+');
```
参照：https://readouble.com/laravel/5.5/ja/routing.html
見出し【正規表現制約】

`->where('id', '[0-9]+')`の追記により、URLが『user/数値』の場合のみ、上記のルート定義を通るようになります。

正規表現で定義することが出来るので、特定のアルファベット＋数値、とかも設定できます。

##グローバル制約

『グローバル制約』を設定しておけば、毎回制約を記述する必要がなくなります。`RouteServiceProvider`の`boot`メソッドの中で、このようなパターンを定義します。

```.php
/**
 * ルートモデル結合、パターンフィルタなどの定義
 *
 * @return void
 */
public function boot()
{
    Route::pattern('id', '[0-9]+');

    parent::boot();
}
```
パターンを定義すると、パラメータ名を使用している全ルートで、自動的に提供されます。

```.php
Route::get('user/{id}', function ($id) {
    // {id}が数値の場合のみ実行される
});
```
参照：https://readouble.com/laravel/5.5/ja/routing.html
見出し【グローバル制約】

##最後に

『グローバル制約』については、本記事を作成する際にドキュメントを見て初めて知りました。（知らんかったんかい）

Laravel学び始めの頃はドキュメントを読んでみても何のことだかさっぱり分からない、という感じでしたが、触るようになってやっと少しは理解できる所が出てきたのだなと思います。他にも色々勉強してみたいと思います。
【unity】VSCodeで保管を機能させる

初書：2021/2/14
PC：macOS 10.15.7
unity: 2019.4.20f1

# 前書き

久々にunityを触ってみた。エディタは少し前にVSCodeに変更していた。
なので、特に問題なく使えるかなーと思って新規csファイルを作成し、
コードを書いてみると、「public」すら予測変換に出てこないではないですか！
ということで設定を見直してみる

# monoをインストール

まずはmonoが入っているかを確認。

```zsh
% mono --version
Mono JIT compiler version 6.10.0.104 (2019-12/5d03a6fe116 Wed Apr 29 20:51:09 EDT 2020)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
// 略
```
入っていた。
では大丈夫かと思いきやそうでもなかった。
調べるとhomebrewで入れようと書いていたので、`brew list`で入れていたのかチェックすると、リストに存在していなかった。
`which mono`をしてみると、`/Library/Frameworks/Mono.framework/Versions/Current/Commands/mono`と出たので、
おそらくVisual Studio for Macが入れたものだろう。

ということでbrewからインストール。

```zsh
% brew install mono
...
Error: The `brew link` step did not complete successfully
...
==> Caveats
To use the assemblies from other formulae you need to set:
  export MONO_GAC_PREFIX="/usr/local"
==> Summary
🍺  /usr/local/Cellar/mono/6.12.0.90: 3,992 files, 428.1MB
```

インストールはできるものの、リンクがうまく行ってなさそう。
.zshrcに`export MONO_GAC_PREFIX="/usr/local"`を追加し、再起動してみたが特に変化が無かったのでリンクはうまく行ってない。まあunity以外でC#扱わないしいいや、、

# monoをVSCodeに認識してもらう

あとはvscode側に先程インストールしたmonoを認識してもらう。
コマンドパレットから`Preferences: Open Settings (JSON)`を入力して`setting.json`を開き、以下を追加する

```json
    "omnisharp.useGlobalMono": "always",
    "omnisharp.monoPath": "/usr/local/Cellar/mono/6.12.0.90",
```
`omnisharp.monoPath`はインストールされたバージョンを指定すること。インストール時のSummaryに書いてある。

これで保存すると、予測変換が出るようになった。

# 終わりに

安定感はVisual Studio for Macの方が良いのだが、何せ重い…
VSCode一択になるような環境構築が出来る様になるといいな…


# 参考サイト

[MacでVSCodeがうまくUnityのコードを補完してくれないとき - Qiita](https://qiita.com/kyasbal_1994/items/ecf19a3feb60a12a61f9)
pythonでのデータ管理 dict vs list

# Pythonのデータ管理
pythonはデータdictが非常に使いやすく、ある程度のデータの固まりを扱うときにわざわざ専用のクラスやc言語のstructのようなものを作らなくても、dictやdictを収容したlistなどで十分代用できてしまう。

なのだけれど、よく以下のどちらの構造を取るかで迷うことがある。

1. dictで表現する
2. listでdictを収容して表現する

例えば、yamlで例を書いてみるとこんな感じ。

dictで表現

```yaml:data
’0001':
  id: '0001'
  name: user01
'0002':
  id: '0002'
  name: user02
```

listで表現

```yaml:data
- id: '0001'
  name: user01
- id: '0002'
  name: user02
```

APIでデータ引っこ抜く系だと後者で見かけることが多い気もするけれど、prosとconsをまとめてみる。

## dict表現の特徴
### pros
#### データの検索性が良い
data[\<id>]あるいはdata.get(\<id>, None)などとすれば、ほしいデータを一発で引き抜ける。
listだと、1つ1つのデータを調べて、idがほしい値に一致するものを探さないといけない。

### cons
#### keyにできる共通の要素が必要
keyを設定するために、全部のデータが共通で持ち、かつ一意性のある情報が必要。
例のようにidみたいな重複しない一位識別子があるデータならいいけれど、nameだけ（同姓同名があり得る）というようなケースに対応できない。
また、keyは1つしか設定できないため、一位識別子が複数ある場合にどっちを使う、、？という問題にぶつかる。

#### 順序を保持できない
「最新のもの1件を引き抜きたい」という用途に使うことができない。

## list表現の特徴
### pros
#### データの構造を気にせず格納できる
dictのkeyのように、全データが共通かつ一位的に持たないといけないデータが無いので、自由なフォーマットで格納できる。

#### 順序を保持できる。

### cons
#### 検索性
処理自体はそう重くないのだろうけれど、コードが野暮ったくなる。

# まとめ
データがしっかりフォーマットに則っていて、わかりやすい一意識別子があるときはdict。
それ以外はlistかな。。

listのときは検索性が課題になる。
forループ回してヒットするものを見つけるか、並べ直すか。
...まぁそりゃ重複は考慮できんけど。

```
genkey = labmda x: x.get('id', str(x))
dict_data = dict([(genkey(x), x) for x in data])
```

ん？あ、これでいいのか。

```
search_result = [x for x in data if isinstance(x, dict) and <key> == x.get('<key>', None)])
```

気持ちはちょっと悪いけど、、処理不可が気にならんならこれで検索すりゃいいから、listのほうが無難、、なのかな。。
なんか気持ち悪いけど。
地震で停電した後、独自ドメインのアプリにアクセスできなくなった話

# 開発環境
Mac OS Catalina 10.15.7
ruby 2.6系
rails 6.0系

# 前提

- 記事投稿型のアプリを作成
- EC2にデプロイ済み
- Route53で名前解決済み(ドメインはお名前ドットコムで取得しました)

# ことの発端

昨日の夜、東北地方を震源とした比較的大きな地震が発生し、その結果私の家が停電になってしまいました。
そして、その停電を境に、転職活動用に作成したポートフォリオにアクセスできなくなる事態が発生しました。

IPアドレスからだとアクセスできるので、サーバーは正常に動いていると思うのですが、SSL化した独自ドメインからのアクセスができません。


chrome画面のエラー文は```ERR_CONNECTION_TIMED_OUT```とのこと
```応答時間が長すぎます```とも言われてしまいました。

# 解決法

結論から書くと、ロードバランサーでSSL化した際に作成したセキュリティグループのインバウンドルールを編集して、ソースを「任意の場所」に変えることで解決しました。

![スクリーンショット 2021-02-14 18.32.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1035658/9c959e09-0f7d-a2a3-1a1a-50fb464e7c57.png)

原因としては、ソースにカスタムでIPアドレスを指定してしまっていたことでした。接続先を制限してしまったため、停電でwifi接続が切れたことが発端となり、ネットワークがうまくいってなかったのだと思われます。

本番環境でのエラーは毎回ヒヤヒヤしますね笑
以上です。
参考になれば幸いです。
第九章　管理タスク

/etc/passwdにはユーザーアカウントに関する情報があります。
passwdはパスワードだけではなく
ユーザー名、パスワード、ユーザーID、グループID、コメント、ホームディレクトリ、デフォルトのシェルが入ってます
ただ、一般ユーザーでも、このファイル読み取れるのでrootユーザーしか入れない/etc/shadowに記載されています
passwdフォルダを読み取り禁止にすると色々不都合が怒るらしい。

似たような感じで、グループに関しては
/etc/groupに入ってます

またグループは一人で参加せずに、サークル感覚で複数のグループにぞくせます。
基本所属してるグループがプライマリグループ。それ以外はサブグループです。

useraddコマンドでユーザーアカウントを作成したい
useradd -cコメントフィールドを指定
ユーザーが新しくできたら、ホームディレクトリに新しいユーザーのディレクトリができる。
ちなみにこれは元の雛形があってその雛形を元に新しい、ホームディレクトリができる

usermod　ユーザー名コマンドで、既存のユーザーの設定を変える
使い道）あるユーザーが長期休暇でお休みになってしまった。一時的にアカウントを使えなくしてしまおう！とか
usermod -L lpicコマンドでアカウントを一時無効にできる

userdelコマンド
userdel -r lpicjp

グループでも同じようなことができます
groupaddコマンド
groupmodコマンド
groupdelコマンド

俺どこのグループだっけ？って調べたい時は　id　ユーザー名コマンドで調べられます。
linux界では何らかのグループに所属しているからいい世界ですね

getendコマンドを使うと、LDAPサーバーに記載されている、ユーザー情報、グループ情報などが出てくる。でもLDAPサーバーってどういう時に使うのだろう。
調べたら、ユーザー情報を一元管理するのにいいらしい。
確かにいろんなPCを持ってて、そのうちの１つのPCにいろんなアカウント情報を入れてたら、いちいちそのPCに接続しなくちゃいけないし。

/etc/shadowディレクトリには、パスワードが入ってる
→暗号化されてるから安心！

####9.2ジョブスケジューリング
バックアップ、ログファイルのメンテナンスが必要。
メンテナンスってよくわからないけど。

＊定期的にメンテする時はcron。1回限りのメンテはat

/var/spool/cron(crontab)/

要約するとこんなかのファイルの内容は指定した時間に、スクリプトに書いたことをやってくれよ。っという意味。
でも、vi何やらで直接編集できないよ
crontab　-eコマンドを使って編集してよね。っていう意味

決まった時間にコマンドを実行するというか、決まった時間に、あるスクリプトファイルを実行するよって言う意味かな。

ファイルの中身
#Daily Backup （タイトル）
15 23*** /usr/local/bin/backup
って書いてあったら、この指定した時間に、 /usr/local/bin/backupのパスを通って、ファイルを実行するよ
って言う意味かな

システム用のcrontabっていうのもあって/etc/crontabの中にある
上記の違いは、
①ファイルの中に実行ユーザー名を記載するところがある
②ディレクトリーのパスによって、実行される感覚が変わる
/etc/cron.hourly
/etc/cron.daily
などなど

atコマンド
atコマンドは、ターミナルのなかで、対話式で実行されます。

対話式とはaiboみたいなもんかな。
俺）コマンドを打つ
ターミナル）誕生日は
俺）1987。。。とか

①at 5:00（時間）tomorrow(日付)コマンド　＊いつやんの
②at> /usr/local/sbin/backup(パス)　　　＊どこ見りゃいいの？
てな流れ

（atrmコマンドで削除もできる）

cronやatの利用制限は、ユーザー単位で実施できる。
誰でもいじっていいわけじゃない。

優先順位は
1.allow 2.denyだから

①etc/cron.allowにユーザー名が入ってた→そいつだけ使える
②etc/cron.allowにユーザー名が入ってない→/etc/cron.denyに入っていた→そいつ以外使える
的な感じ

その他は、systemdを使ってもタイマーが使える
/etc/systemd/system/lpic.timer

system-runコマンド使うと、もっと簡単に動かせる

####9.3 ローカライゼーションと国際化
internationalizationをi18nと訳した。
ロケールによって表示言語や書式を変更可能
どうやって変更するかというと、これは環境変数に収められている
LC_CTYPE 文字の種類やその比較とかを入れる
LC_COLLATE　
LC_TIME 日付の書式とか

んで、ロケールをまとめて確認したい時は
localeコマンドを使えばよす。

文字コードは
ASCLL
UTF-8とかある
iconv -fコマンド　入力する（パソコンカタカタとはHeysiriとか）言語を決める
iconv -tコマンド　出力する（表示されたりボイスとか）の言語を決める

世界には、時差があるのはみんな知ってるだろうが、当然PCにもタイムゾーンは設定する

今のタイムゾーンを見るには
/usr/share/zoneinfoディレクトリのファイルに入っている。

変更する手順
方法①　cp /usr/share/zoneinfo/Asia/Tokyo(コピーして) etc/localtimeに貼り付ける
方法②　export TZ ="Asia/Tokyo"(環境変数TZに入れとく方法)
【TypeScript】はじめてのHello World！！



**※ node.jsインストール済前提です**

## TypeScriptのインストール


```:ターミナル
$ npm i -g typescript

// tscコマンドが使える
$ tsc -v
Version 4.1.3
```

## 任意のディレクトリ直下に"index.ts"ファイルを作成

**変数`hello`に`string`型を指定**

```typescript:index.ts
let hello: string = 'Hello World！'
console.log(hello)
```

## TypeScriptをJavaScriptに変換（コンパイル）

```:ターミナル
$ tsc index.ts
```
***
すると`index.js`が自動で生成！

```javascript:index.js
var hello = 'Hello World！';
console.log(hello);
```

***

**実行する**

```:ターミナル
$ node index.js

=> Hello World！
```

# 成功！

ブラウザで実行するときは・・・

```html:index.js
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>Document</title>
  </head>
  <body>
    <script src="index.js"></script>
  </body>
</html>
```

いつも通りですね！^^
Windows10でpyenv

Windows10でのpyenvのインストール方法まとめです。
公式のインストール方法にのっとっているだけなので新しい情報はありませんが、
必要な要素だけ抜き出しましたのでサクッと環境を作りたい方は参考にしてみてください。

# インストールのコマンドまとめ
本当にサクッと作りたい方向けの、コピペで行けるやつです。
環境変数の関係でpowershellを再起動する方がいいので、2回に分けて実行してください。

**pyenvインストール**

```powershell
# powershell
git --version
git clone https://github.com/pyenv-win/pyenv-win.git "$HOME/.pyenv"
[System.Environment]::SetEnvironmentVariable('PYENV',$env:USERPROFILE + "\.pyenv\pyenv-win\","User")
[System.Environment]::SetEnvironmentVariable('PYENV_HOME',$env:USERPROFILE + "\.pyenv\pyenv-win\","User")
[System.Environment]::SetEnvironmentVariable('path', $HOME + "\.pyenv\pyenv-win\bin;" + $HOME + "\.pyenv\pyenv-win\shims;" + $env:Path,"User")
exit
```

**Pythonインストール**

```powershell
pyenv --version
pyenv rehash
pyenv update
pyenv install -l
pyenv install 3.8.7
pyenv global 3.8.7
pyenv rehash
```


# インストール方法

## 前提条件
gitが使えること。
下のコマンドでバージョンが出ない人は、
インストールしたりパスを通したりしてみてください。
Git for Windows: https://gitforwindows.org/

```powershell
git --version
```

## pyenv-win

Windows10のpyenvは、pyenv-winを利用します。
インストールは基本的に下のリンクに従います。
最初のインストール作業はpowershellでやってしまうのが楽だと思います。
左下のスタートボタンの横にある検索バーにpowershellと打ち込み、
右クリックして「管理者として実行」を選択します。
（管理者とするのは環境変数の設定のためです。）

pyenv-win: https://github.com/pyenv-win/pyenv-win

```powershell
# powershellで実行します

# gitでインストールします
git clone https://github.com/pyenv-win/pyenv-win.git "$HOME/.pyenv"

# 環境変数を設定します
[System.Environment]::SetEnvironmentVariable('PYENV',$env:USERPROFILE + "\.pyenv\pyenv-win\","User")
[System.Environment]::SetEnvironmentVariable('PYENV_HOME',$env:USERPROFILE + "\.pyenv\pyenv-win\","User")
[System.Environment]::SetEnvironmentVariable('path', $HOME + "\.pyenv\pyenv-win\bin;" + $HOME + "\.pyenv\pyenv-win\shims;" + $env:Path,"User")
```

これが実行できたら一度powershellを閉じます。
そのあと、powershellでもcmdでもいいので起動してインストールできたかを確認します。

```powershell
pyenv --version
```

ここでバージョンが表示されればOKです。
もし、コマンドが見つからないなどのエラーが出る場合には
環境変数がうまく設定されているかをGUIで確認してください。
Visual Studio Codeなどのターミナルで実行している場合は、
環境変数が更新されていない可能性があるのでアプリ自体を再起動してください。

ここまで出来たらインストールを完了させます。
ホームディレクトリで以下のコマンドを走らせれば完了です。

```powershell
pyenv rehash
```

## Python
ここまでで、pyenvのインストールができましたがまだPythonのインストールはできていません。
pyenvを使ってPythonをインストールしてみましょう。

まず、pyenvから見えるPythonのバージョンを最新にします。

```powershell
pyenv update
```

次に、インストールできるPythonのバージョンを確認します。

```powershell
pyenv install -l
```

たくさんのバージョンのリストが出てくるので、好きなバージョンをインストールします。

```powershell
pyenv install 3.8.7
```

しばらく待つと指定したバージョンのPythonがインストールされます。
あとは、今インストールしたPythonを使うように指定するだけです。
複数バージョンのPythonをインストールした場合も、
このコマンドで使用するバージョンを切り替えられます。
(デフォルトでは何も指定されていないと思うので、
このままではPythonが見えず使用できません。)

```powershell
pyenv global 3.8.7
pyenv rehash
```

`pyenv rehash`はバージョン切り替えの後と`pip install`の後は必ず実行するように公式で言われているので、一応しておきましょう。シンポリックリンクを更新しているみたいなので、これをしないと正しくバージョンが切り替わらない可能性があります。

# まとめ
以上がpyenvとpyenvを利用したPythonのインストール方法でした。
WindowsではAnacondaやPython launcherも使えますが、
Poetryなどを利用したパッケージ管理をしたい場合はpyenvが便利だと思います。

# 参考
https://qiita.com/akym03/items/3576842eed0e9d28cf82
【Go】文字列を一部置換と全置換する方法

## 準備
文字列の置換には`strings`と言うpackageを使用する為、まずはimportを行います。
https://golang.org/pkg/strings/

```go:import
import "strings"
// 以下でも良い
import ("strings")
```

## 特定の数のみ置換したい場合
1つだけ置換したい場合や2つなど複数置換したい場合は、`replace関数`を使います。
### 軽く説明
```go
func Replace(s, old, new string, n int) string
```
第1引数：置換したい文字列
第2引数：置換前の値
第3引数：置換後の値
第4引数：置換したい数（int型）
返り値：置換された結果の文字列
（stringsのReplace関数なので`strings.Replace()`と言う使い方）

### 具体例
```go:一部置換
var title string = "SSSS.GRIDMAN"
fmt.Println(title) // => SSSS.GRIDMAN

// 1つのみ置換
oneReplace := strings.Replace(title, "S", "X", 1)
fmt.Println(oneReplace) // => XSSS.GRIDMAN

// 複数置換
multipleReplace := strings.Replace(title, "S", "X", 3)
fmt.Println(multipleReplace) // => XXXS.GRIDMAN
```

## 全て置換したい場合
ドキュメントの`Replace関数`部分に
>If n < 0, there is no limit on the number of replacements.

と言う記述があります。
つまり、`replace関数`の**第４引数が0未満**だったら制限がない(=**全置換**)と言うことですね。
### 具体例
```go:全置換
var title string = "SSSS.GRIDMAN"
fmt.Println(title) // => SSSS.GRIDMAN

allReplace := strings.Replace(title, "S", "X", -1) // -2でも-100でもOK
fmt.Println(allReplace) // => XXXX.GRIDMAN
```

もしくは`replaceAll関数`と言うのもあります。

### 軽く説明
```go
func ReplaceAll(s, old, new string) string
```
第1引数：置換したい文字列
第2引数：置換前の値
第3引数：置換後の値
返り値：置換された結果の文字列
（`strings.ReplaceAll()`と言う使い方）

### 具体例
```go:全置換
var title string = "SSSS.GRIDMAN"
fmt.Println(title) // => SSSS.GRIDMAN

allReplace := strings.ReplaceAll(title, "S", "X")
fmt.Println(allReplace) // => XXXX.GRIDMAN
```
[Ruby on Rails]  金額のバリデーション(¥300~¥9,999,999) と テストコード

金額のバリデーションで
##¥300~¥9,999,999


**こういった設定を設ける時の記述**。



![スクリーンショット 2021-02-14 18.17.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1078698/040b5a1f-f90d-85c2-79ef-055a7798d501.png)
　

　
・**numericality**で整数のみにする設定や数値の最大値、最小値を設定できる。

・**only_integer: true**で整数値のみに設定。

・ **greater_than_or_equal_to: 300, less_than_or_equal_to: 9999999}**で最小値、最大値を設定。
　
　

ちなみに上記は**正規表現**で**半角数字のみ**というバリデーションもかけている。



　　
###こちらが金額のテストコード
![スクリーンショット 2021-02-14 18.14.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1078698/5967ff3e-26d5-37db-409e-17741c8ed72c.png)
「値を返す」の意味

メインプログラムが動作し、関数（サブのプログラム）に対して
ある数値やポインタ値を要求します。

（メインプログラムが動作を一時止めて、サブプログラムが動作します。）
サブプログラムは、求められた値を所定の場所に格納し、動作を終了します。
メインプログラムが動作し、格納された値を読み取ります。

メインプログラムがサブプログラムに値などを要求し、
サブプログラムはそれに応えて値を作って渡します。

要求に応えるこの動作を「（値を）返す」と呼びます。
M5StickV+TOPPERSでI2Sを使う

# 久しぶりの投稿

昨年、[M5StickV で TOPPERS BASE PLATFORM を動かしてみる](https://qiita.com/fukuebiz/items/016f88bbd48aa89a7226) を書いた以降、なかなかM5StickV+TOPPERSでI2Sを使って音を出すことができなかったが、ようやく音を出すことに成功したので久しぶりの投稿してみる。

# デモ(FM音源)

こちらの [FMmelodyのFM音源版](http://pcm1723.g3.xrea.com/html/fmmelody.htm) をM5StickV+TOPPPERSに移植してみました。
音色を変えながら「きらきら星」のメロディーを演奏し続けます。

I2Sのドライバは [こちら](https://github.com/fukuen/toppers-m5stickv-patch/tree/main/asp/pdic/k210/i2s.c)

ソースは [こちら](https://github.com/fukuen/toppers-m5stickv-demo/tree/main/asp/OBJ/K210_GCC/FMMELODY)

実行方法は [M5StickV で TOPPERS BASE PLATFORM を動かしてみる](https://qiita.com/fukuebiz/items/016f88bbd48aa89a7226) 同様、BASE PLATFORMを展開した上に、M5StickV用のパッチとデモを追加で上書きします。

# デモ（FFT）

今のM5StickVはマイクもついているので、マイク入力からのFFTデモ。

FFTのドライバは [こちら](https://github.com/fukuen/toppers-m5stickv-patch/tree/main/asp/pdic/k210/fft.c)

ソースは [こちら](https://github.com/fukuen/toppers-m5stickv-demo/tree/main/asp/OBJ/K210_GCC/FFFT)
Djangoでアプリをアプリだけのフォルダににまとめる方法

#経緯
Djangoで一つのプロジェクト下に複数のアプリを作成した場合、ディレクトリ構成が乱雑になってどれがアプリのフォルダなのかぱっと見わからなくなることはないだろうか。
他人が作ったプロジェクトだと尚更だと思うが、それを解決する方法を見つけたため備忘録として記述しておく。
#アプリをアプリだけのフォルダにまとめる
仮に,appというフォルダにまとめるとする
プロジェクト名/settings.pyに以下の記述を追加する

```python:settings.py
import sys
sys.path.insert(0, os.path.join(BASE_DIR, 'app'))
```

アプリの場所を変えた際、from〜以下の記述も変えなければならないし、
settings.pyのINSTALLED_APPのAppConfigの場所も変えないといけないと思われがちだが、
これを追加するだけでアプリの場所を変えても他を変える必要がない

#最後に
Qiitaの記事を書くのは初めてでしたが簡単でした！
皆さんもどんどん書いて欲しいですね！

初めて書くにあたって参考にした記事
[Markdown記法 チートシート](https://qiita.com/Qiita/items/c686397e4a0f4f11683d)

リンクを貼る時、カッコの全角半角わかりづらいけど
半角じゃないと適用されないから気をつけよう・・・
VSCode Remote ContainersからWSL2上のdockerで起動しているmysqlに手軽に接続する

# 前提環境
* Windows10
* WSL2/docker
* VSCode Remote Containers

# mysqlの設定（設定済みの人は読み飛ばしてください）
## WSL2/dockerでのmysqlを起動する
WSL2上でdockerコマンドを使ってmysqlのイメージを取得・起動します。ホスト側の3306ポートとdocker内の3306ポートを接続しておきます。

```shell
docker pull mysql:5.6
docker run -it --name test-mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=mysql -d mysql:5.6
docker exec -it test-mysql bash -p

## mysqlへのログイン
mysql -u root -p -h 127.0.0.1
```

## mysqlの設定

mysqlにログインして、ユーザの作成・権限の付与を行う。

```sql
-- version 確認
select version();

-- データベース作成
create database db1;
show databases;

-- ユーザの作成・権限付与
create user 'user'@'%' identified by 'password';
grant all on db1.* to 'user'@'%';
```

外部から接続できるようにmysqlの設定を変更する。

```shell
echo "bind-address = 0.0.0.0" >> /etc/mysql/conf.d/mysql.cnf
```

# devcontainer(docker)でmysql-clientをインストール

## mysql-clientのインストール
本当は`.devcontainer/Dockerfile`を修正してReopenしてあげるべきなのでしょうが、開きなおすのが手間なので、直接devcontainer内で実行してしまいます。

```shell
sudo apt update
sudo apt install default-mysql-client-core
```

# devcontainerからmysqlへ接続

mysqlのdockerを起動する際にホスト（Windows）の3306ポートとdockerの3306ポートを接続しているので、devcontainerからホストの3306ポートに向けて接続をすると、ホスト経由でmysqlのdockerにアクセスできます。

```shell
mysql -u remoteuser -p -h host.docker.internal
```

3306ポートがmysqlのデフォルトなので特に指定する必要はありません。また、ホストのipは`host.docker.internal`を利用して接続することができます。


# 参考

* https://dev.mysql.com/doc/refman/5.6/ja/account-names.html
* https://dev.mysql.com/doc/refman/5.6/ja/grant.html
* https://dev.mysql.com/doc/refman/5.6/ja/server-options.html#option_mysqld_bind-address
* https://docs.docker.com/docker-for-windows/networking/#use-cases-and-workarounds
Raspberry Pi+RubyでSwitchBotから温度湿度を受信する

# 実装例
[SwitchBot 温湿度計の測定値を BLE Advertisement パケットから直接読み取る](https://qiita.com/warpzone/items/11ec9bef21f5b965bce3)を参考に実装。

```ruby:scan_beacon01.rb
require 'scan_beacon'
scanner = ScanBeacon::DefaultScanner.new

scanner.each_advertisement{|ad_data,mac,rssi,ad_type|
  if mac == "xx:xx:xx:xx:xx:xx" and ad_type == 213 # MACアドレスを事前に調べておく
    t2 = ad_data[16].unpack("C*")[0] & 0b00001111
    t1 = ad_data[17].unpack("C*")[0] & 0b01111111
    temperature = t1 + t2/10.0
    humidity = ad_data[18].unpack("C*")[0]& 0b01111111
    puts [temperature,humidity].join("\t")
  end
}
```
## 事前準備
- SwitchBotの温湿度計のMACアドレスを調べる  
MACアドレスはスマホのアプリの設定画面で確認できる。
- hciuartサービスを起動する
 
```bash
sudo systemctl start hciuart
```

## 実行
```bash
$ sudo ruby scan_beacon01.ruby
21.8    58
21.8    58
```

# 補足
## 方式の検討
[SwitchBotの温湿度計](https://www.switchbot.jp/meter)から温度/湿度を受信するには、Pythonだと公式ライブラリが使えるがRubyだとそれが無い。
SwitchBotの温湿度計は仕組み的にはBLEのAdvertisingが使われており、一昔前に少し流行ったBeacon関連の先駆者の実装や記事が参考にできる。

|方式|実現性|コスト|補足|
|:--|:--|:--|:--|
|[scan_beacon gem](https://github.com/RadiusNetworks/scanbeacon-gem) |○|○||
|hcidumpをパース|○|○||
|Bluez API|○|×|Ruby以外に低レイヤの実装が必要そう|
|D-Bus|？|？|実現性が不明。D-BusでBLEのAdvertiingを扱えるのか不明|
|rfcommでBluetoothをdevにマッピングさせる|？|？|実現性が不明。rfcommとBLE Advertisingが合わない？|

今回は、[scan_beacon gem](https://github.com/RadiusNetworks/scanbeacon-gem) を利用した。

## Raspberry Pi zeroでBluetoothのscanをするとWifiが切れる事が有るので注意
Raspberry Pi zeroのwifiは5GHzに対応しておらず2.4GHzしか使えない。
またBluetoothのscanは強い電波を発するためWifiの2.4GHzと干渉し繋がらなくなる場合が有る。
Raspberry Pi zeroでBluetoothのscanをする際には、PCからRaspberryPiへの接続にはGPIO等のwifi以外の接続方法を利用するのが望ましい。
ただし今回の記事の範囲ではscan動作は行わないので2.4GHzのWifiでのRaspberry Pi zeroの利用に問題は無い。
[FPGA] 擬似乱数を作る


擬似乱数を作成する方法はいくつかありますが、
FPGAと相性が良い「**Xorshift**」を紹介します。

## Xorshift

[Wikipedia[1]](https://ja.wikipedia.org/wiki/Xorshift)によると、George Marsagliaが2003年に提案したアルゴリズムらしいです。排他的論理和とビットシフトの２つの演算で構成されるため、FPGAで実装するのに最適です。

## モジュール定義

以下、定義です（ベタ書きで申し訳ないです）。
多分有名なので、他のgitには上がっていると思います。
こちらでもそのうちgitにアップします。

```
module xorshift(
    input clk,
    input rstn,
    output reg [31:0] rand
    );
    
reg [31:0] x;
reg [31:0] y;
reg [31:0] z;
reg [31:0] w;
reg [31:0] t;

always @ (posedge clk)
begin
    if (!rstn)
    begin
        x <= 123456789;
        y <= 362436069;
        z <= 521288629;
        w <= 88675123;
        t <= 0;
        rand <= 0;
    end
    else
    begin
        t <= x ^ (x << 11);
        x <= y; 
        y <= z; 
        z <= w;
        w <= (w ^ (w >> 19)) ^ (t ^ (t >> 8));
        rand <= w;
    end
end // always

endmodule
```

## 参考URL
[1][Xorshift Wikipedia](https://ja.wikipedia.org/wiki/Xorshift)
Linux常用文件操作

## 文件操作相关命令
| 命令 | 作用 |
|:--|:-:|
| $ vim [文件名]  | 使用vim打开文件 （文件不存在时则新建文件）  |
| $ cat [-n] [文件名]| 保存并关闭  |
| $ more [文件名]  | 查看长文件 |
| $ head [-x] [文件名]  | 查看文件前x行  |
| $ tail [-x] [文件名]  | 查看文件后x行  |
| $ [内容] > [文件名]  | 重定向  |
| $ cp [-r] [文件名/目录名] | 复制文件/目录（-r 递归复制） |
| $ rm [-r][-rf] [文件名/目录名] | 删除文件/目录（-r 递归删除，-rf 强制递归删除） |
| $ find [目录] [-name] [查找内容] | 查找文件 |


## vim常用命令
### 命令模式
| 命令 | 作用 |
|:--|:-:|
| i  | 进入编辑模式  |
| :q!  | 不保存强制关闭  |
| :w!| 保存  |
| :wq!| 保存并关闭  |
| :set number  | 显示行号 |
| :set nonumber  | 隐藏行号  |
|   |   |

### 编辑模式
| 命令 | 作用 |
|:-:|:-:|
| esc  | 退出编辑模式  |
HandS (Henkan/muhenkan and Shift)

## はじめに

スペースキーをシフトキーの代わりに使える、通称SandS(Space and Shift)という仕組みが気に入っていました。スペースキーにスペースとシフトの2つの役割を兼ねてもらうものです。キーを単体で押したときはスペースキーとして機能させ、他のキーと同時に押したときにはシフトキーとして機能させる仕組みです。貧弱な小指の代わりにマッチョな親指でシフトできるので理にかなった仕組みだと思っています。シフトキーを多用する環境(SKKなど)では特に効果的です。ちなみに表現的には親指シフトに似ていますが別物です。

## SandSの課題

少し早めにタイピングしているときなど、スペースキーを押したつもりがシフト扱いになってしまったり、シフトを効かせたつもりがスペースになってしまったり、意図と反する挙動がときどき起こって気が散りました。また、日本語キーボードは英語キーボードに比べてスペースキーの幅が狭いため、シフトを押したいときに親指を少しだけずらさないといけません。

## 提案: HandS

日本語キーボードを眺めたとき、親指に最も近いキーはスペースキーではなく、変換キーと無変換キーであることに気づきました(Appleユーザは除く)。これらをシフトキーの代わりに使えればより捗るのでは？と考えた次第です。実際これが個人的にはとても手に馴染みました。

既にIMEの設定で、変換はIMEオン、無変換はIMEオフに割り当てていました。なので今回のHandS導入によって変換/無変換キーは以下のような役割を兼ねることになります。

|   |単独で押したとき|他キーと同時に押したとき|
|:-:|:-:|:-:|
|**変換キー**|IMEオン|右シフト|
|**無変換キー**|IMEオフ|左シフト|
|(参考)SandS|スペース|シフト|

右シフトと左シフトを使い分けることは無いので、わざわざ対応付ける意味は無いのですが、単に気分的にそうしています。

SandSの課題であった「スペースを押したつもりがシフトになってしまう問題(またはその逆)」についてはHandSでも同様です。しかしながら変換/無変換キーはスペースキーとは違って、押しただけでは文字としては入力されません。そのために誤操作時の手戻り(バックスペース)が少ないのが利点かなと感じます。

## 実装

### windows + keyhac + fakeymacs

Windowsでは元々[Keyhac](https://sites.google.com/site/craftware/keyhac-ja)と[fakeymacs](https://github.com/smzht/fakeymacs)を使っていたので、そこに少し設定を付け加えて実現しました。[fakeymacs](https://github.com/smzht/fakeymacs)の`config_personal.py`の`[section-base-2]`に以下を足すだけです。

```py:config_personal.py
# [section-base-2] ---------------------------------------------------------------------------------
##################################################
## HandS (Henkan/Muhenkan and Shift)
##################################################

# 変換キーを右シフトキー、無変換キーを左シフトキーとして使えるように
# それぞれ単独で押した場合は元の役割(変換/無変換)が機能

if is_japanese_keyboard:
    keymap.replaceKey("(28)", "RShift")
    keymap.replaceKey("(29)", "LShift")
    define_key(keymap_global, "O-Rshift", self_insert_command("(28)"))
    define_key(keymap_global, "O-Lshift", self_insert_command("(29)"))
else:
    keymap.replaceKey("(255)", "RShift")
    keymap.replaceKey("(235)", "LShift")
    define_key(keymap_global, "O-Rshift", enable_input_method)
    define_key(keymap_global, "O-Lshift", disable_input_method)
```

わざわざ日本語キーボード判定で場合分けしているのは、Windowsの設定で日本語キーボードをUS配列にして使っている場合にも対応するためです。私がそうしています。キー配置はUSの方が好みで、見た目もUSの方がシンプルでかっこいいと思うのですが、無変換/変換キーという唯一無二の存在をもった日本語キーボードが最強だと思っています(隙自語)

### linux + xkeysnail

Linuxでは[xkeysnail](https://github.com/mooz/xkeysnail)を使って実現できました。`config.py`に以下を足せばOKです。

```py:config.py
# HandS (変換/無変換 and Space) Keys
define_multipurpose_modmap({
    Key.MUHENKAN: [Key.MUHENKAN, Key.LEFT_SHIFT],
    Key.HENKAN: [Key.HENKAN, Key.RIGHT_SHIFT]
})
```

### mac

Macは持っていないので分かりません。disってるわけではないです！！！
登録対象が複数必要な場合のdevise導入について

#この記事において紹介する内容
この記事はdeviseを用いて複数のテーブルにデータを保存する方法を紹介するものであります。修正点等あれば教えていただけますと幸いです。
rails (6.0.3.5)
ruby (2.6.5)

##gemfileへのの記述
・railsのgemfilenに`gem 'devise'`と入力する。

##deviseの導入
・`bundle install`を実行した後、`rails g devise:install`を実行。ここからはコードエディタをしていきます。

##コードエディタの記述
・`config/initializers/devise.rb`に手を加えます。

    config.scoped_views = true
上記の用に記述する。
（ここをtrueにすることでviewsが編集可能となります。）
##モデル/コントローラー/ビューファイルの作成
・こちらに関しては

    rails g devise "モデル名"
    rails g devise controllers "コントローラー名"
    rails g devise views "モデル名"

上記コマンドで作成します。


##ルーティングの設定
ここに修正を加えていきます。現時点で`rails routes`を使用してターミナルを見てみると、重複したルーティングを見つけることができると思います。
　ex)userとadminの２者でdeviseを実装しようとした場合を考えていきます。

    Rails.application.routes.draw do
      devise_for :users, controllers: {
        sessions:'users/sessions',
        passwords:'users/passwords',
        registrations:'users/registrations',
      }

      devise_for :'admins,controllers: {
        sessions:'admins/sessions',
        passwords:'admins/passwords',
        registrations:'admins/registrations',
      }
    end

#一言
何気に初めての事でしたので備忘録も兼ねて本記事を作成しました。
RailsのAPIアプリをwebmockでモック化

webmockを使ってRailsのAPIのアプリケーションをモック化したので、その備忘録です。

モックとは、簡単に言うとテスト用のダミーアプリケーションです。
APIを利用したサービスのテストで使うことがあります。

今回は以前作ったこちらのAPIアプリをモック化しました。
https://qiita.com/Lmachi/items/464c3cbb9eeb86457935

##スタブ作成

```test/stub/bookmark_stub.rb
require 'webmock'

module BookMarkStub
  WebMock.enable!
  WebMock.allow_net_connect!

  WebMock.stub_request(:get, 'http://www.example.com/bookmarks' )
          .to_return(
            body: File.read("#{Rails.root}/test/fixtures/files/get_bookmarks.json"),
            status: 200,
            headers: { 'Content-Type' => 'application/json' }
          )
end
```
スタブを作成します。
スタブもモック同様にテスト用のダミーです。

モックとスタブの違いについてはこちらの記事をご覧ください。
https://qiita.com/hirohero/items/3ab63a1cdbe32bbeadf1

stub_requestでダミーのエンドポイントを指定しています。
body: File.read()にモックに返すダミーデータのパスを書きます。Bodyを返さない場合はこの行は不要です。

WebMock.allow_net_connect!はstub登録したホスト以外へのアクセスを許可します。
これがないと以下のエラーが発生します。

```
Real HTTP connections are disabled.
 Unregistered request: GET http://localhost:3000/bookmarks with headers 
{'Accept'=>'application/json', 
'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
 'User-Agent'=>'Ruby'} 
You can stub this request with the following snippet: stub_request
(:get, "http://localhost:3000/bookmarks")
. with( headers: { 'Accept'=>'application/json', 
'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 
'User-Agent'=>'Ruby' })
. to_return(status: 200, body: "", headers: {})
 registered request stubs: stub_request
(:get, "http://localhost:3001/bookmarks") 
============================================================
```

##ダミーデータ作成
```test/fixture/files/get_bookmarks.json
[
  {
      "id": 1,
      "title": “hoge”,
      "url": "https://www.hoge.co.jp/",
      "comment": "テスト",
      "created_at": "2021-02-11T09:15:09.492Z",
      "updated_at": "2021-02-11T09:15:09.492Z"
  },
  {
      "id": 2,
      "title": “hogehoge”,
      "url": "https://www.hogehoge.co.jp/",
      "comment": "test",
      "created_at": "2021-02-11T09:15:24.677Z",
      "updated_at": "2021-02-11T09:15:24.677Z"
  }
]
```

json形式でダミーデータを用意します。
ダミーデータの中身は、元になるAPIサーバーで確認してください。

##スタブを読み込ませる
```models/application_resource.rb
require "#{Rails.root}/test/stub/bookmark_stub"

class ApplicationResource < ActiveResource::Base
  self.include_format_in_path = false
end
```

application_resource.rbを作成し、bookmark_stub.rbを読み込ませます。

##モデル編集
```models/bookmark.rb
class Bookmark < ApplicationResource
  self.site = 'http://www.example.com/'.freeze
end
```

ApplicationResourceを読み込ませ、self.siteをダミーサイトに書き換えます。

以上でモック化は完了です。
##参考
https://qiita.com/ogawatti/items/58bd4fe1180a0acfdd5e