OmniAICreator/Qiita-1.07M huggingface dataset:
acts_as_votable の upvote_by / downvote_by はエラーハンドリングすべきか？

acts_as_votable のモデルに対し upvote_by / downvote_by などを呼び出す際、その戻り値 (boolean) に対しエラーハンドリング処理をすべきかどうか気になったので調査してみました。

## TL; NR
エラーハンドリングしなくても問題なさそう。(自信ない)

## 調査・考察

https://github.com/ryanto/acts_as_votable/blob/master/lib/acts_as_votable/votable.rb
Line: 96 - 103

```ruby
      ActiveRecord::Base.transaction do
        self.vote_registered = false
        return false unless vote.save

        self.vote_registered = true if last_update != vote.updated_at
        update_cached_votes(options[:vote_scope])
        return true
      end
```

### vote.save が false を返すと commit されて return false されるのではないか？

return false だろうと commit される。
ただし、後続の処理は実行されない。

#### そもそも false になるのか？

vote は ActsAsVotable:Vote クラスで、Gem が管理しているモデル。(votable <=> voter 間の関連テーブル)
validate は votable_id / voter_id の必須チェックのみで、コールバック処理もないため、return false は想定しにくい。(でも NOT NULL 制約ないんだよなぁ)

### update_cached_votes は必ず成功するのか？

内部で Gem 用のキャッシュカラムに対し update_attributes (default) / update_columns が実行される。
! はないので true / false が戻る。
Gem 用のキャッシュカラムのみ更新されるため、validation やコールバック処理によって false になることは想定しにくい。
よって、常に true になる前提ではないかと思われる。（そうでないのは使い方がおかしいというスタンス？）

## 結論・・・？
2つのDB更新処理はシステムエラーをのぞいて必ず true になる。(false になる状況が想定できない、していない)
よって、upvote_by / downvote_by の戻り値によりエラーハンドリングする必要はない、と思う。

save / update_attributes でシステムエラー(DB接続エラーやタイムアウトエラーなど)が発生した場合に、return false ではなく例外が発生するかどうか、ちょっとあやふやなのでこれも調査しておきます。
gitで空ブランチを作る

gitで空の新規ブランチを作ったときの備忘録。

# やりたいこと

Testプロジェクトに空のブランチを作成する。作成する空ブランチには元になる親ブランチの歴史・ファイルを引き継がせず、新規の歴史をもたせる。

# 手順

まずはTestプロジェクトのクローン

```
$ git clone https://github.com/Test.git
$ cd Test
```

空ブランチkaraを作成してpush

```
$ git checkout --orphan kara       #親の歴史を引き継いでいないブランチを作成
$ git reset --hard                 #親のファイルを引き継いでるのでreset
$ touch README.md                  #READMEを追加
$ vim README.md
$ git add README.md
$ git commit -m "initial commit" 
$ git push origin kara　　　　　　　 #サーバー側へpush　　
```
AADにPowerShellで接続する

# やりたかったこと
AzureのADのユーザーを管理するために、登録されているユーザ一覧が欲しかった。
AzurePortal上ではスクロールでしか確認できないので、数百人～数千人のユーザーを一括で取得するためにWindows　PowerShellからエクスポートを行った。
そのときはまったことと、備忘のまとめ。
##PowerShellの起動
管理者権限で起動すること。
Windowsの窓からWindowsPowerShellを検索し、右クリックで管理者権限で起動する。
##AzureADのモジュールインストール
```cmd:cmd
Install-Module -Name AzureAD
```
プロバイダが必要、といわれるのでYまｇたはAで許可。
AADモジュールのインストールが行われる。
##AzureADへの接続
```cmd:cmd
Connect-AzureAD -TenantId ***
 ```
***は接続したいテナントを指定。

このとき、ハイフンでテナントIDを指定しないと既定のテナントに飛ばされる。
既定といっても、何で既定と判断されているかはわからなかったが、
テナントを複数所持している場合、この指定を付けた方が効率良いはず。
##csv出力

```cmd:cmd
$users = Get-AzureADUser -All $true
$users | Select-Object DisplayName, Surname, GivenName, Mail, UserType,JobTitle | Export-csv -NoTypeInformation -Encoding UTF8 c:\ADDcsv\OutPut.csv
```
Select以降はcsvに出力したい値を指定する。今回は、セキュリティ管理としてユーザーの情報が必要だったため、属性までを取得している。
c:\ADDcsv\OutPut.csvの部分は任意のディレクトリと出力したいファイル名を指定。
Encodingはいくつかあるが、今回はUTF8で取得した。
##ハマったこと
AzureADを一度アンインストールし、再度最新をインストールしようとしたとき、どうしてもうまくいかなかった。色々やったが以下のエラーから抜け出せなかった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/353603/7745b746-9bb0-e790-741c-878ec336d0e5.png)
署名が無効といわれる。おそらく署名認証のための連続仮想メモリが足りないことが原因と思われるが、時間がなかったため以下のコマンドで抜け出した。

```cmd:cmd
Install-Module -Name AzureAD -SkipPublisherCheck
```
もっといいやり方があると思うが。。
Windowsでファイルのアクセス権変更

# Windowsでファイルのアクセス権変更

以前、ファイル名変更のためにアクセス権を修正しました。手順について書き残しておきます。細かい説明は記事最後の補足に記載していますので、余裕があればご覧ください。

## 動作確認環境

* Windows 10
* 変更対象のファイルはローカルに存在する場合[^remote_file]
* ファイル名を変更するユーザは標準ユーザ

[^remote_file]: リモートのファイルを扱う場合、CIFSというプロトコルを用いてリモートPCの共有フォルダにアクセスしますが、まずはCIFSアクセス権を適切に修正します。その上でNTFSによるアクセス権の修正を行ってください。CIFSアクセス権については[こちらの記事](https://milestone-of-se.nesuke.com/sv-basic/windows-basic/ntfs-cifs-permission/ "【図解】初心者向けWindowsアクセス権～NTFSとCIFS(共有フォルダ)の優先順位や動作〜")がわかりやすいです。変更方法は本記事では扱いません。


## 手順

例として今回は「%windir%\System32\termsv.dll」のアクセス権を変更します[^access_control]。所有者をまず使用ユーザに変更してアクセス権を「フルコントロール」に変更してファイル名を変更し、その後アクセス権を元に戻します。以下に手順を示します。

[^access_control]: アクセス権はNTFSやext4などのファイルシステムが管理しています。OSが直接管理しているわけではありません(OSより低レベル)。[こちらの記事](https://milestone-of-se.nesuke.com/sv-basic/architecture/os-and-filesystem/ "図解】初心者向けファイルシステムの基礎知識〜仕組み, OSとの関係, アクセス権との連携〜")がわかりやすいです。

1. 変更対象ファイルのバックアップをとる。
2. ファイルを右クリックして表示されるプロパティを押下してダイアログを表示して「セキュリティ」タブに移動、そして「詳細設定」ボタンを押下。

![詳細設定ボタンを押下](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326185/4f3555e5-423b-0743-8d65-eb297209137a.png "詳細設定ボタンを押下")
3. 所有者(TrustedInstaller)と「アクセス許可エントリ」内にある「Users」のアクセス項目(読み取りと実行)を確認してメモをとり、所有者を変更するため「変更」をクリックする[^confirm_entry]

![所有者の変更を押下](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326185/f338c9dd-4b9f-f566-575d-ff77eadf9223.png "所有者の変更を押下")
4. 「選択するオブジェクト名を入力してください」にファイル変更を行うユーザのユーザ名を入力して「名前の確認」ボタンを押下して「OK」ボタンを押下する。

![使用ユーザ名を入力してOKを押下](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326185/1ecfe164-828f-264a-1808-6f1fc20ed7db.png "使用ユーザ名を入力してOKを押下")
5. 所有者が変更されていることを確認する。

![所有者が変更されている](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326185/d0ef5f0b-7c2b-ab1e-1873-e07e1bb58d72.png "所有者が変更されている")
6. 「グループ名またはユーザ名」から「Users」を選択し、「編集」ボタンを押下する。

![Usersを選択して編集ボタンを押下](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326185/2b513a08-ee05-ba94-cd30-065b974d9d40.png "Usersを選択して編集ボタンを押下")
7. ポップされるダイアログの「アクセス許可」から「フルコントロール」のチェックボックスを有効にして「OK」を押下する[^ntfs_setting]。

![Usersを選択して編集ボタンを押下](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326185/9dde195a-989f-5f81-df1a-17132088e6f2.png "Usersを選択して編集ボタンを押下")
8. ファイル名を変更する。
9. 手順4から手順8を参考にして元の状態に戻す[^termsv_default_user]

[^confirm_entry]: アクセス権の変更を行うため。今回は「Users」グループのアクセス権を変更しました。標準ユーザが属しているグループです。実行ユーザが属しているグループであればOKです。エントリにユーザを直接加えることも出来ます。

[^ntfs_setting]: 詳細設定でなくてもある程度アクセス権の変更操作は出来ますが、NTFSによるアクセス権をきちんと設定したい場合は詳細設定で行いましょう。現在WindowsではファイルシステムとしてNTFSが主流ですが、昔はFATでした。FAT時代のUIと互換性を持たせるために存在しているようです。

[^termsv_default_user]: アクセス権の修正方法とは関係ありませんが、例として登場した「termsv.dll」のデフォルトの所有者は「TrustedInstaller」です。元に戻す際に「NT SERVICE\TrustedInstaller」と入力する必要があります。[TrustedInstallerについて](https://qiita.com/shojit/items/f863ef3f56057a7e36d6)の説明がQiitaの記事で公開されています。

## 参考資料

* [【図解】初心者向けファイルシステムの基礎知識〜仕組み, OSとの関係, アクセス権との連携〜](https://milestone-of-se.nesuke.com/sv-basic/architecture/os-and-filesystem/)
* [【図解】初心者向けWindowsアクセス権～NTFSとCIFS(共有フォルダ)の優先順位や動作〜](https://milestone-of-se.nesuke.com/sv-basic/windows-basic/ntfs-cifs-permission/)
* [ファイルサーバ整理術@2008](https://www.teppi.com/category/column/file_mgmt/)
【Unity】プロジェクトをOculus Go用にビルドするまでに個人的に詰まったところまとめ

# 背景

「Unity Oculus Go」でググって、3ページほど参考にしながら進めていました。
たぶん自分が悪いのですが、いろいろなところに詰まってしまいました。
なので、トラブルシューティングとしてまとめました。

いろいろ試行錯誤していたので、情報不足感とスクショ不足感が否めませんが、ご了承ください…

# 開発環境

- Windows 10
- Unity 2018.3.1f1
- Android Studio Version 3.2.1

# Oculus Goを開発者モードにする

1. Oculusアプリを起動する
2. 「設定」→「その他の設定」→「開発者モード」をONにする

## 団体登録していない場合
<font color="Red">**1回目のつまづきポイント**</font>
![Screenshot_20190509-233813.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233011/3b6c07c3-04ba-c4ad-06a1-c533ae07ea37.png)
団体登録をしていないと、上記のような「開発者になろう」というポップアップが表示されます。
作成開始ボタンを押下すると、[Device Setup - Oculus Go](https://developer.oculus.com/documentation/mobilesdk/latest/concepts/mobile-device-setup-go/)に遷移します。
（スマホよりPCで先に登録することをオススメします。）

自分は団体登録していなかったので、[Oculus開発者ダッシュボード](https://dashboard.oculus.com/organizations/create/)で新しい団体を作成しました。
なんでもよかったので、「riekure」で登録しました。
![new organiton.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233011/5b463787-c39f-c47e-853c-e80ab3e1559b.png)

# Android SDK(API Level 25)をインストール

※ Android Studioをインストール済という前提。
<font color="Red">**2回目のつまづきポイント。API 25を入れるべし。**</font>
Oculus GoはAndroidのAPI Level 25で動くので、該当するSDKをインストールします。

1. Android Studioを起動する
![android studio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233011/3f374ad6-0b40-1840-bb8c-3757655a4c32.png)
2. 右下にある「Configure」→「SDK Manager」を押下
3. Android 7.1.1（Nougat）をチェックしてApply
4. 時間がかかるので待つ

# Oculus Go ADB Driverをインストール（Windows限定）

<font color="Red">**3回目のつまづきポイント。存在を忘れがち。**</font>

1. https://developer.oculus.com/downloads/package/oculus-go-adb-drivers/ からダウンロード
2. ZIPファイルがダウンロードされるので、解凍する。
3. 解凍したファイル/usb_driver/android_winusb.infというファイルがあるので、右クリック→インストール

# UnityプロジェクトをAndroid用にビルド

1. 「File」→「Build Settings」を押下
2. 「Android」を選択して、「Player Setting」を押下
3. 「other Settings」→「Minimum API Level」をAndroid 7.1 'Nought'（API level 25）を選択 ※もっと下げたほうがいいのかも…？
4. 「XR Settings」→「Virtual Reality Supported」をチェック
5. 「Virtual Reality SDK」で＋ボタンを押下、Oculusを選択
6. 「File」→「Build Settings」→「Build and run」を実行する

<font color="Red">**4回目のつまづきポイント。API Levelを間違いがち。**</font>

初回のAPI Levelを26にして実行したら、下記のような「No compatible Android device found.」というWarningが出力されてしまいました。
![No compatible Android device found.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/233011/6ed1263a-51f6-5e2d-cec1-93764671c50b.png)
Oculus GoはAndroid 7.1.1らしいので、注意しましょう。

# 参考文献
[Unity＋Oculus Go開発メモ - フレームシンセシス](https://framesynthesis.jp/tech/unity/oculusgo/)
[【VR開発入門】Unityで作ったゲームをOculus Goにビルドする方法 \| FREE SWORDER](https://freesworder.net/unity-oculus-go-build/)
[Device Setup - Oculus Go](https://developer.oculus.com/documentation/mobilesdk/latest/concepts/mobile-device-setup-go/)
Laravelで「Formクラスが無い」とエラーが出た時の対処法

#Class 'Form' not foundと出た

チュートリアルを元にLaravelでアプリを作っていた際に、Formという機能を使ったのですが使用できなくて焦りました。
Laravelのバージョンは5.7だったので古いという訳でも無いです。

どうも各種追記をしないといけないようです。

## composer.jsonに追記

```composer.json
    "require": {
        "laravelcollective/html": "~5.0"
    },
```
```
$ composer update
```

## app.phpに追記

```app.php
   'providers' => [
        Collective\Html\HtmlServiceProvider::class,
    ],

    'aliases' => [
        'Form' => Collective\Html\FormFacade::class,
        'Html' => Collective\Html\HtmlFacade::class,
    ],
```

これでFormが使えるようになりました！
Githubにpushしようと思ったらfetch firstうんたらかんたらでrejectedされた

#初めてのQiita投稿です
稚拙極まりない文章、内容も疾っくの疾うに既出と思われますが、どうか温かい目で見守って頂けたら嬉しいです。

#Githubにpushしようとして詰まるまで
途中に明らかな詰まりの原因があるので、分かる方はツッコミ入れたくなると思います。じゃ、行きマース。

##Ruby on Railsでブログを作りたい
とにかく何かWebアプリケーションをこの手で作ってみたかったので、手っ取り早くて比較的挫折しなさそうなRailsでブログを作ることにしました。
その過程で行き詰ったことをこんな感じでQiitaに記録していこうと思います。
初歩的な地雷は虱潰しに踏んで回ると思いますので、先輩方にはお手数おかけしますがご指導ご鞭撻のほど宜しくお願いいたします。


じゃ、色々飛ばしマース。

```
$ rails new blog
$ cd blog
$ git init
$ git add -A
$ git commit -m "Initialize repository"
```
Gitについては(僕自身が理解するために)また別の記事でシッカリまとめたいのですが、とりあえずは“手元にもリポジトリのある”バージョン管理システムというぼやっとした認識でいます。
ここでは```$git init```で作ったローカルリポジトリ(手元のリポジトリ)にcommitしただけです。個人開発なので必要ないかもしれませんが、どうせならリモートリポジトリ(共有のリポジトリ)にもpushしたい。

##Githubにリポジトリ作った
![README.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416797/0e2daacb-6e2b-b9ec-985b-1c389caa7ac6.jpeg)
というわけで、まずはGithubにリモートリポジトリを作りました。
無料会員だから公開設定はPublicで、「READMEを勝手に作ってくれる」という項目にもなんとなくチェックしときました。

##リモートリポジトリ(Github)にpushしようとした
```
$git remote add origin https://github.com/TaskEngineer/TaskWorksPortfolio
$git push origin master 
```
リモートリポジトリの情報を追加し、pushで反映させます。
普通はこれで上手くいくそうなのですが、、、

##そしたら思っきし蹴られた
```
! [rejected] master -> master (fetch first)
error: failed to push some refs to ‘https://github.com/TaskEngineer/TaskWorksPortfolio’
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushin
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., ‘git pull …’) before pushing again.
hint: See the ‘Note about fast-forwards’ in ‘git push –help’ for details.
```
よくよくググってみると、このエラーはリモート(リポジトリ)をpullしてからpushするまでに他のpushがあるなどしてリモートが変更されたために起こるものとのこと。
でも、リモートは作ったばかりでまだ一度もpushしていないのにpullしなくてはいけないというのはどういうこと？？？

#解決編
**ついさっきGithubでリモートを作るときになんとなくREADMEを作ってもらいましたが、実はその操作で一度commitしたことになっているらしいのです。**
なので、まずはfetchしてね、というエラーメッセージでした。
pullはfetch+mergeなのですが、ここは楽しようとせずに、確実にfetch→mergeしていきます。

```
$git fetch
$git merge origin/master
```
これで上手くいきました。こんな初歩的なエラーで何時間も悩んで、先が思いやられます。。。

#参考
* https://stackoverflow.com/questions/20939648/issue-pushing-new-code-in-github
kali linuxのrootのpasswordを忘れたときの再設定方法

# 参考
[★こちらを参考にさせていただきました。★](https://amzn.to/3e9SE8h)

#流れ
Step 1: Boot Into GRUB menu
Step 2: Edit GRUB menu
Step 3: Check RW permissions on root partition
Step 4: Reset Kali root password
Step 5: Reboot Kali

#ちょっと詳しく
GRUB boot menuで `e` を押す。

GRUB menu edit modeに移行したら、linuxと書いてある行にある以下の文字を次のように置き換える。
`ro` → `rw` 
`quiet` →　`init=/bin/bash`
`ctrl+x` で編集を終了する。

CLIの画面に移行したら、`passwd`コマンドでパスワードを再設定して`exec /sbin/init`で再起動する。
Javaで暗号化しC#で復号する

Javaで動くAndroidと.NETで動くAPIサーバーの認証のためにJava側で暗号化した文字列を.Net側で復号して認証処理を行うという仕組みを構築するために、Javaで暗号化するコード、C#で復号するコードを作りました。


``` Encrypt.java

    @TargetApi(Build.VERSION_CODES.O)
    @RequiresApi(api = Build.VERSION_CODES.O)
    public static String Encrypt(String text, String key)
            throws Exception {
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        byte[] keyBytes= new byte[16];
        byte[] b= key.getBytes(StandardCharsets.UTF_8);
        int len= b.length;
        if (len > keyBytes.length) len = keyBytes.length;
        System.arraycopy(b, 0, keyBytes, 0, len);
        SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
        IvParameterSpec ivSpec = new IvParameterSpec(keyBytes);
        cipher.init(Cipher.ENCRYPT_MODE,keySpec,ivSpec);

        byte[] results = cipher.doFinal(text.getBytes(StandardCharsets.UTF_8));
        String result = Base64.getEncoder().encodeToString(results);
        return result;
    }
 
```

``` Decrypt.cs

       public static string Decrypt(string textToDecrypt, string key)
        {
            System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();

            RijndaelManaged rijndaelCipher = new RijndaelManaged();
            rijndaelCipher.Mode = CipherMode.CBC;
            rijndaelCipher.Padding = PaddingMode.PKCS7;

            rijndaelCipher.KeySize = 0x80;
            rijndaelCipher.BlockSize = 0x80;

            //string decodedUrl = HttpUtility.UrlDecode(textToDecrypt);
            byte[] encryptedData = Convert.FromBase64String(textToDecrypt);
            byte[] pwdBytes = Encoding.UTF8.GetBytes(key);
            byte[] keyBytes = new byte[0x10];
            int len = pwdBytes.Length;
            if (len > keyBytes.Length)
            {
                len = keyBytes.Length;
            }
            Array.Copy(pwdBytes, keyBytes, len);
            rijndaelCipher.Key = keyBytes;
            rijndaelCipher.IV = keyBytes;
            byte[] plainText = rijndaelCipher.CreateDecryptor().TransformFinalBlock(encryptedData, 0, encryptedData.Length);
            return encoding.GetString(plainText);
        }

```
LaTexの数式で斜体の太字を書く

# はじめに #

物理学の論文などを書くときの一般的なルールとして
- 変数は斜体
- 単位・普通の言葉は立体
と言うルールがある。

例えば、速度は$v = 10\ \mathrm{cm\ s^{-1}}$と$v$は斜体、$\mathrm{cm\ s^{-1}}$は立体で書くのが正しいとされている。
数式モードで、文字を書けば、勝手に斜体になるので、立体にしたいときのみ`\mathrm`を用いてやれば良い。

しかし、Latexでベクトルを斜体にするのが一苦労なので、メモしておくことにした。

# 問題と実直な解決法 #
Latexにて、以下のように書くとベクトルは、立体になる。`\bf`コマンドは文字を太字にするとともに立体にしてしまう。

```LaTeX
\begin{equation*}
{\bf v}
\end{equation*}
```

この方法で太字にしてしまうと、斜体にする方法はない。一方、`\boldmath`コマンドでは、文字を斜体のまま太字にしてくれるが、これは数式モードの中では使えない。

よって、数式モードのなかで`\boldmath`を使うために、一度数式モードを抜けるという荒技を使う。以下のようにする。

```latex
\begin{equation*}
\mbox{\boldmath $v$}
\end{equation*}
```
文字が多くなってくるとかなり面倒になる。

# マクロを使う #

上記の面倒を回避するために、「斜体で太字」というマクロを用意する。
Latexのプリアンブルに以下のように書く

```latex
\newcommand{\bm}[1]{{\mbox{\boldmath $#1$}}}
```
すると

```latex
\begin{equation*}
\bm{v}
\end{equation*}
```
とするだけで、太字で斜体となる。

# 参考 #

数式モードにおける斜体
http://www27.cs.kobe-u.ac.jp/~masa-n/misc/cmc/j-kiso2001/iabasic/jlshort/node33.html

完全攻略！ LaTeX のマクロ定義
https://qiita.com/zr_tex8r/items/5067307890d36c0e4882
ジョブ運用について勉強

■勉強の目的
・システム間連携処理の運用(誰が(何が)、いつ、どうやって、何をトリガーに、どの単位で、何を実行するのか、結果をどう判定するか、結果によってどう分岐するのか、リカバリはどうするのか)の検討事項の想定ができるようになるため

■勉強の完了基準
・ジョブフローやジョブネットが月次、日次など適切な粒度で作成できるようになること
・異常時のリカバリのフローが書けること

■開始当初の理解状況
・ジョブが依存しているといえるケースを把握できてるか自信がない(ex.前のジョブが完了しないとできない だけ?)
・データ連携においては一般にどういう異常が発生しうるのかわかってない(ex.ファイルの読み書き中異常、先祖返り、データ不正系異常、通信異常、権限異常?)
・上記の各異常終了発生時の検知方法のバリエーションがわかってない
・上記の各異常終了発生時のRERUNポイントがわかってない
・自動連携の方がよいケース、手動連携の方がよいケースは何かわかってない (ex.必ずこけるケースはやめた方がよい?)

■利用予定資料
・利用資料①(JP1MS3):http://itdoc.hitachi.co.jp/manuals/3020/30203S0133/AJSZ0001.HTM
・利用資料②(JP1MS2):http://itdoc.hitachi.co.jp/manuals/3020/30203K2143/AJSF0001.HTM 

　※19/05/15時点のJP1の最新がJP1MS3のようなので、基本的に利用資料①を参照
■目次
1.用語の定義の確認
2.概要の確認
3.検討事項の確認

■本論
1.用語の定義の確認
▼基本用語
　ジョブ：コマンド，シェルスクリプト，Windows実行ファイルなどの集まり
　ジョブネット：実行順序を関連づけたジョブの集まりです。ジョブネットを実行すると，ジョブネット中のジョブが実行順序に従って自動的に実行されます。

▼ジョブの定義編
　


★疑問点・気になること
・実行順序を意識する(結果的に並列であっても)ならば、ジョブネットとして整理すべき??

2.概要の確認
　※利用資料②(JP1MS2):http://itdoc.hitachi.co.jp/manuals/3020/30203K2143/AJSF0001.HTMを参照した

　①ジョブを列挙する
　②複数のジョブを実行順序順に並べて、関連性を見てグルーピング。
PostGISで多角形内にある点を探す

# はじめに
PostGISってなに？、環境構築？から１歩進んで、実際にPostGISを試す流れを紹介します。

# 環境
以下の記事を参考にDocker環境を構築します。
[dockerでPostGISを入れたPostgreSQL環境構築](https://qiita.com/A-Kira/items/3339e902e7a8fca8fdf6)

# 多角形内にある点を探す
※以下は、先の[参考記事](https://qiita.com/A-Kira/items/3339e902e7a8fca8fdf6)のファイル名やデータベース構成を元に作成しています。
## 検索対象となる点を登録します
対象となる点は、緯度経度を示す点を 3 x 3 のマトリクスとします。

| 緯度経度 | 133 | 134 | 135 |
| :-: | :-: | :-: | :-: |
| 35 | POINT(133, 35) | POINT(134, 35) | POINT(135, 35) |
| 34 | POINT(133, 34) | POINT(134, 34) | POINT(135, 34) |
| 33 | POINT(133, 33) | POINT(134, 33) | POINT(135, 33) |

```sql:insert
INSERT INTO test_table (gid, geom) VALUES
(1, ST_GeomFromText('POINT(135 35)', 4612)),
(2, ST_GeomFromText('POINT(135 34)', 4612)),
(3, ST_GeomFromText('POINT(135 33)', 4612)),
(4, ST_GeomFromText('POINT(134 35)', 4612)),
(5, ST_GeomFromText('POINT(134 34)', 4612)),
(6, ST_GeomFromText('POINT(134 33)', 4612)),
(7, ST_GeomFromText('POINT(133 35)', 4612)),
(8, ST_GeomFromText('POINT(133 34)', 4612)),
(9, ST_GeomFromText('POINT(133 33)', 4612));
```

## 抽出条件となる多角形は？
先の 3 x 3 のマトリクスから中央の`POINT(134, 34)`を抽出するとして、それを囲む多角形を定義します。

### 抽出イメージ
<img width="340" alt="Screen Shot 2019-05-15 at 8.37.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73365/24c062ba-bec3-631e-98ce-1e2bf2eb78eb.png">

### 抽出対象の点
| 緯度経度 | 133 | 134 | 135 |
| :-: | :-: | :-: | :-: |
| 35 |  |  |  |
| 34 | | POINT(134, 34) <br>↑これを抽出したい | |
| 33 | |  |  |

### 抽出条件となる多角形
「◇」みたいな`ひし形`をイメージしています

| 緯度経度 | 133 | 134 | 135 |
| :-: | :-: | :-: | :-: |
| 35 |  | POINT(134, 35) |  |
| 34 | POINT(133, 34) |  | POINT(135, 34) |
| 33 |  | POINT(134, 33) |  |




## 検索クエリ
```sql:select
SELECT
  gid,
  ST_Astext(ST_Transform(geom, 4612))
FROM test_table
WHERE ST_Contains(
    ST_Transform(
      ST_GeomFromText('POLYGON((135 34, 134 35, 133 34, 134 33, 135 34))', 4612),
      4612
    ),
    geom
  );
```
※読み方

- `ST_Astext(ST_Transform(geom, 4612))`
  - geomフィールドを、空間参照系識別コード（SRID）を4612：JGD2000（地理座標系）に変換して、テキストに変換します。
- `ST_Contains(A, B)`
  - Aに含まれるBを探す
- `ST_GeomFromText('POLYGON((135 34, 134 35, 133 34, 134 33, 135 34))', 4612),`
  - 始点と終点が同じある輪で囲まれた多角形を示すテキストを、4612：JGD2000（地理座標系）に変換します。

## 検索結果
<img width="333" alt="Screen Shot 2019-05-15 at 8.29.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73365/65fbbe92-ed7e-f8d1-3758-6959ba4a30b8.png">


想定した値が返ってきましたね！


## 蛇足
`ST_Astext(ST_Transform(geom, 4612))`の個所を
`ST_Transform(geom, 4612)`とすると
<img width="558" alt="Screen Shot 2019-05-15 at 8.29.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73365/9ae7b863-642b-6b4d-0610-0d38faf62141.png">
何を言っているかさっぱり
Active Directory のユーザー情報を PowerShell 操作で LINE WORKS に一括で連携

#Active Directory のユーザー情報を PowerShell 操作で LINE WORKS に一括で連携

Active Directory のユーザー情報を PowerShell 操作で LINE WORKS に一括で連携する手順の一例を説明します。

##Get-ADUser コマンドレット

Get-ADUser コマンドレットで、AD 上のユーザーを取得できます。

TITLE: Get-ADUser
URL: https://docs.microsoft.com/en-us/powershell/module/addsadministration/get-aduser?view=win10-ps

本記事では一例として "LWUsers" OU に所属のユーザーを取得します。

```
Get-ADUser -Filter * -SearchBase "OU=LWUsers,DC=example,DC=com"

```

##LINE WORKS メンバー追加 API

LINE WORKS の組織連携 API でメンバー追加できます。

TITLE: メンバー追加
URL: https://developers.worksmobile.com/jp/document/100300501?lang=ja

Inveke-RestMethod コマンドレットで PowerShell から LINE WORKS の組織連携 API を実行します。

ここでは、必須パラメータのみ利用しています。

mail -> email
sn -> name.lastName
givenName -> name.firstName

Get-ADUser コマンドレットで取得したユーザーの メール、姓、名の情報を LINE WORKS の属性値に連携しています。

SSO を想定したスクリプト例を記載していますが、SSO でない場合には上記に加えて privateEmail パラメータの指定が必要です。

スクリプト例は以下のとおりです。

```
Get-ADUser -Filter * -SearchBase "OU=LWUsers,DC=example,DC=com"| 
%{
$header = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$header.Add("Content-Type","application/json; charset=UTF-8")
$header.Add("consumerKey","<Server API Consumer Key>")
$header.Add("Authorization","Bearer <Server Token>")
$json = @"
{
"email": "$($_.mail)",
 "name": {
 "lastName": "$($_.sn)",
 "firstName": "$($_.givenName)"
 }
}
"@
$Uri = "https://apis.worksmobile.com/r/<API ID>/organization/v2/domains/<domainID>/users/$($_.UserPrincipalName)"
Invoke-RestMethod -Uri $Uri -ContentType 'application/json' -Method Post -Header $header -Body $json
}

```

##動作確認

スクリプト実行後に管理画面でユーザーが作成されていることを確認します。
また、それぞれのユーザーがログイン可能であることを確認します。
wordpressブログを立ち上げる流れ

エックスサーバーでサーバを借りる

お名前.comでドメインを取得

エックスサーバー内でドメインを設定

お名前.comでドメインのネームサーバを設定

テーマを購入、アップロードして適用
プラグインを適用

wordpress管理画面
設定>一般設定から、
アドレスをhttp > httpsにして、ちょっと待ってからリロード。
ベンダープレフィックについて　IEじゃ使えないもの結構ある

#ベンダープレフィックス
`CSS3で採用予定（草案段階）の機能を各ブラウザが先行的に実装し、その先行実装した機能を有効化させるために`必要な各ブラウザ毎の「-moz-」や「-webkit-」という接頭辞のことをいいます

CSSのプロパティには`ブラウザごとに異なるベンダープレフィックス（接頭辞）を記述するものがあります。こうすることで異なるブラウザ間でも正しく表示できるようになります。`
（現在はブラウザの進化でベンダープレフィックスを必要とするプロパティも少なくなってきましたが）

なぜベンダープレフィックスが必要かというと、CSS3になり様々なプロパティの登場で各ブラウザが独自のアプローチで試験的に実装してきたという経緯があります。そのためブラウザ別にプロパティを区別するベンダープレフィックスをつけるようになりました。


#基本不要なイメージ
最近のブラウザーではよく使われるＣＳＳ３のプロパティが実装可能ですので、ベンダープレフィックスを付ける必要はありませんが、中にはブラウザーでサポートされていないプロパティもあります。プロパティごとに草案段階なこともあるので、確認しつつつける
⇨
ここで確認した：https://caniuse.com/#search=rgb

＊接頭辞とは：それ自身単独で発話されることがなく，常に語根や自立語 (または自立語に音形も意味も似た形態素 ) に前接して全体で一語を形成し，その語根や単語に語義的特徴ないしは文法的特徴を加える役割を果す言語形式をいう。「お-寺」「まん-中」



| 接頭辞 | 対応ブラウザー |
| -webkit- | Google Chrome、Safari |
| -moz- | Mozilla Firefox |
| -ms- | Microsoft Internet Explorer |
| -o- | Opera |

#最後にはベンダープレフィックスが付かないプロパティを書く
`必ずベンダープレフィックスが付かないプロパティを最後に書くようにしてください。`

ブラウザのバージョンアップによりプロパティがサポートされた場合、ベンダープレフィックスが付いていると正しく表示されない場合があります。
それを避ける為に、 最後にベンダープレフィックスが付かないプロパティを記述する必要があります。


#確認サイトで確認する
cssを入れるときには以下サイトなどで確認すると良い。
https://caniuse.com/#search=rgb

参考：https://designsupply-web.com/knowledgeside/3059/
https://ysklog.net/html_css/5492.html
LookingGlassの基礎データ

#概要

Looking Glass の基礎データのまとめ。

#Hardware

|        |外寸<br>mm × mm × mm|傾斜角<br>deg|質量<br>kg|
|:------:|:----------------------------------------------:|:---------------------:|:------------------:|
|Standard|209 × 154 × &nbsp;93                            |30                     |2.2                 |
|Large   |368 × 244 × 175                                 |25                     |8.4                 |

|        |ガラス寸法<br>$W × H × T$<br>mm × mm × mm|Aspect ratio<br>$W:H=A$<br>&nbsp;|対角線寸法<br>$ D=\sqrt{W^2+H^2}\ $<br>inch|
|:------:|:----------------------------------------------:|:-:|:-:|
|Standard|192 × 120 × 51|8:5 = 1.6|9|
|Large   |346 × 192 × 71|3:2 = 1.5|15.6|

- Standard は現物での実測値。
- Large は図面から測定しての試算。

#Software
- OS ≧ Win10 64bit
- CPU ≧ Intel Core i5
- GPU ≧ NVIDIA GeForce GTX 1060
- RAM ≧ 4GB
- Strage ≧ 128GB

|        |Display<br>Resolution|Display<br>aspect ratio|
|:------:|:-------:|:---:|
|Standard|2560×1600|16:10 = 1.60|
|Large   |3840×2160|16:9&nbsp; = 1.78|

|Quilt<br>preset<br>&nbsp;|Quilt<br>size<br>$p×q$|Tiling<br>number<br>$c×r=v$|View<br>size<br>$w×h$|View<br>aspect ratio<br>$w:h=a$|
|:-------:|:-------------:|:-------------:|:-------------:|:-------------:|
|Extra Low|1600×1440|4×6 = 24| 400×240|&nbsp;&nbsp;5:3&nbsp; = 1.67|
|Standard |2018×2048|4×8 = 32| 512×256|&nbsp;&nbsp;2:1&nbsp; = 2.00|
|Hi Res   |4096×4096|5×9 = 45| 819×455|20:13 = 1.53|
|Ultra Hi |7680×6400|6×8 = 48|1280×800|&nbsp;&nbsp;8:5&nbsp; = 1.60|

- $p = c × w $
- $q = r × h $

# Reference
- https://www.makuake.com/project/lookingglass/
- https://docs.lookingglassfactory.com/Gettingstarted/standard/
- https://docs.lookingglassfactory.com/Gettingstarted/large/
- https://docs.lookingglassfactory.com/ja/Appendix/how-it-works/
オブジェクト指向でなぜつくるのかまとめ

![image.png](https://qiita-image-store.s3.amazonaws.com/0/257568/f6f3faf9-308b-9d06-19c9-fb9936d1b5ef.png)

重要だと思った部分を抜粋しつつまとめ

## 目的
「オブジェクト指向」そのものに対する視点と知識量を増やす。

## 理解が難しくなる理由
- 混乱したまま理解しようとする為
- どう混乱しているかを上手く整理できない、もしくは説明者もどう混乱しがちかを把握していない為
- 現実世界と共通点ばかりにフォーカスしてしまう

## 混乱要因
1. 用語の洪水
オブジェクト指向を説明する対象とする分野の広さから、特殊用語のオンパレードすぎる

2. 比喩の乱用
比喩だけが強烈な印象としてのこってしまい、聞く側がそれぞれ解釈し、誤解を生みがち

3. なんでもオブジェクト症候群
「オブジェクト思考を使えば、現実世界をそのままプログラムに表現できる」という考え方を鵜呑みにしてしまい、オブジェクト指向という技術を説明する1側面である事を認識できない

上記3点が一度にきてしまう

## 混乱要因を排除する方法
1. 紹介する用語や概念は最小限にする。
2. 比喩による説明は最小限に抑える。比喩を使う場合にはその旨を明示する。
3. プログラミングの仕組みと、「モノ中心」で汎用的に物事をとらえる考え方は別物として、分けて説明する。


## オブジェクト指向の三大要素
- クラス
- ポリモーフィズム
- 継承

## 概念とプログラミング技術の2軸で理解する
当たり前ではあるが、初学時はプログラミングにおけるオブジェクト指向技術を指す部分(コード)をはっきり認識できていないケースがある為、抽象表現との紐付けが上手くできずに混乱する

### 共通点
オブジェクト指向は現実世界をそのまま反映したものである

- 現実世界に存在する固有の物体を全てオブジェクト考えること
- これがプログラミング技術におけるインスタンス化した実体と通じる

### 相違点
オブジェクト指向は現実世界と似て非なる部分がある

- 現実世界の人やモノはクラスから作らない(概念先行ではない)
- 現実世界の人やモノはメッセージだけでは行動しない(自立した行動もする)

### プログラミングのための仕組みという事を割り切って抽象表現とは別軸でも理解する
- クラスは変数と関数をひとまとめにして独立性の高い部品を作る仕組み
- ポリモーフィズムと継承はコードの重複を排除して汎用性の高い部品を作る仕組み

### プログラミングは現実世界全てではなく、一部が実現された世界であることを認識する
人間の仕事の一部の世界を実現している

- 覚える仕事
- 決まり切った仕事

## オブジェクト指向とは
- 無駄を省いて整理整頓するもの

## プログラミング技術の側面からみたオブジェクト指向の三大要素の利用
- クラス
  - クラスからインスタンスを作成して、メソッドと変数定義をまとめて利用する
- ポリモーフィズム
  - 親クラスのインスタンス生成時のメッセージの変更によって、呼び出される側のロジックをアプリケーション固有の処理で置き換える
- 継承
  - クラス定義の共通部分を親クラスにまとめて、コードの重複を排除する
blueqatで量子ゲート その4

#概要

blueqatで量子ゲートやってみた。
全加算器作ってみた。

#全加算器

| carry       |     a |    b    | carry | c |
|:-----------------:|:------------------:|:------------------:|:------------------:|:------------------:|
| 0     |  0 |   0  |0|0|
| 0     |  0 |   1  |0|1|
| 0     |  1 |   0  |0|1|
| 0     |  1 |   1  |1|0|
| 1     |  0 |   0  |0|1|
| 1     |  0 |   1  |1|0|
| 1     |  1 |   0  |1|0|
| 1     |  1 |   1  |1|1|


![zen.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/13ccd6ce-f150-3028-1f19-bab418bcae9d.jpeg)

#サンプルコード

```
c0 = Circuit(8).h[1 : 3].cx[1, 3].cx[2, 3].ccx[1, 2, 4].ccx[0, 3, 5].ccx[5, 4, 6].cx[5, 6].cx[4, 6].cx[0, 7].cx[3, 7].m[:].run(shots = 100)
for cnt in c0:
  print("{} + {} = {}".format(int(cnt[1], 2), int(cnt[2], 2), int(cnt[6 : 8], 2)))


c0 = Circuit(8).x[0].h[1 : 3].cx[1, 3].cx[2, 3].ccx[1, 2, 4].ccx[0, 3, 5].ccx[5, 4, 6].cx[5, 6].cx[4, 6].cx[0, 7].cx[3, 7].m[:].run(shots = 100)
for cnt in c0:
  print("{} + {} = {}".format(int(cnt[1], 2), int(cnt[2], 2), int(cnt[6 : 8], 2)))


```

#結果

```
1 + 1 = 2
0 + 1 = 1
0 + 0 = 0
1 + 0 = 1

0 + 1 = 2
0 + 0 = 1
1 + 1 = 3
1 + 0 = 2
```

以上。
blueqatで量子ゲート その3

# 概要

blueqatで量子ゲートやってみた。
半加算器作ってみた。三日、掛かった。

# 半加算器

| a       |       b |    carry    | c |
|:-----------------:|:------------------:|:------------------:|:--:|
| 0     |   0 |  0        | 0|
| 0     |   1 |  0        | 1|
| 1     |   0 |  0        | 1|
| 1     |   1 |  1        | 0|

![han.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/78a91676-5f18-beec-9357-4aa42bb712d2.jpeg)

# サンプルコード

```
c0 = Circuit(4).h[ : 2].cx[1, 3].cx[0, 3].ccx[0, 1, 2].m[:].run(shots = 100)
for cnt in c0:
	print("{} + {} = {}".format(int(cnt[0], 2), int(cnt[1], 2), int(cnt[2 : 4], 2)))
```

# 結果

```
1 + 1 = 2
0 + 1 = 1
1 + 0 = 1
0 + 0 = 0
```

以上。
[mocky] スタブREST-APIサーバを構築する 

Node.jsパッケージ「mocky」を使用して、スタブREST-APIを構築します。

mocky
https://www.npmjs.com/package/mocky

今回使用したNode.jsパッケージのバージョンは下記の通りです。

```Markdown:Node.jsパッケージ
fs: 0.0.1
mocky: 0.1.11
querystring: 0.2.0
url: 0.11.0
```

# スタブREST-APIサーバとは

WEBサービス開発で、クライアントサイドとサーバーサイドの開発が同時並行することが多いです。クライアントサイドは、サーバーサイドがある前提で動作することになりますが、完成を待ってから開発に取り掛かるのでは時間がありません。そのときに活躍するのがスタブ（ダミー）として動作するサーバーとなります。

# mockeyとは

mockeyとは、簡単にスタブREST-API環境を構築することができるNode.jsパッケージです。

以前、node-easymockを使用してスタブREST-APIサーバを構築していました。node-easymockはJSONファイルを作成するだけで構築することができます。とても簡単なのですが、特定のリクエストに対して異なるレスポンスを返すというような痒い所に手が届くことができません。

mockeyでnode-easymockと同じようにJSONファイル作成するだけで構築できるようにして、特定のリクエストにも対応できるように実装しました。

ソースコードは下記の場所にあります。
[ソースファイルはこちら](https://github.com/yunbow/sample-mocky/tree/master/server/01/)

## 仕様

1. `response/user/GET.json`のようにJSONファイルを格納すると`GET http://localhost:8888/user/`のRESTリクエストに対応したレスポンスを返します。POST、PUT、DELETEも同様です。
2. 特定のリクエストをカスタマイズする場合は、`mock_server.js`を修正します。

## インストール

まず、Node.js をインストールしてください。次に、`package.json`があるフォルダに移動して、下記のコマンドを実行してください。

```bash:サーバーをインストールする
$ npm install
```

```bash:サーバーを起動する
$ node mock_server.js
```

## 実装

`mock_server.js`の実装について説明します。mockyの`createServer`で初期化します。共通処理は、`doRes`関数に実装しています。

```JavaScript:createServer
mocky.createServer([{
  url: new RegExp('\\/' + priv.getRegExpOrStrings(CONST.PATH.APIS) + '\\/*'),
  method: 'options',
  res: priv.doRes
}, {
  url: new RegExp('\\/' + priv.getRegExpOrStrings(CONST.PATH.APIS) + '\\/*'),
  method: 'get',
  res: priv.doRes
}, {
  url: new RegExp('\\/' + priv.getRegExpOrStrings(CONST.PATH.APIS) + '\\/*'),
  method: 'post',
  res: priv.doRes
}, {
  url: new RegExp('\\/' + priv.getRegExpOrStrings(CONST.PATH.APIS) + '\\/*'),
  method: 'put',
  res: priv.doRes
}, {
  url: new RegExp('\\/' + priv.getRegExpOrStrings(CONST.PATH.APIS) + '\\/*'),
  method: 'delete',
  res: priv.doRes
}]).listen(CONST.PORT.API);
```

CORS(Cross-Origin Resource Sharing)のエラーに対応します。CORSの詳細は下記のサイトにあります。
[CORSまとめ](https://qiita.com/tomoyukilabs/items/81698edd5812ff6acb34)

```JavaScript:CORS対応のヘッダーを設定する
var headers = {
  'Access-Control-Allow-Origin': '*',
  'Cache-Control': 'no-cache',
  'Cache-Control': 'no-store',
   'Content-Type': 'application/json;charset=UTF-8'
};
```

リクエストURLのパスから`response`フォルダ配下のJSONファイルを読み込みます。

```JavaScript:JSONファイルを読み込む
fs.readFile(filePath, 'utf-8', function (err, fileData) {
  callback(null, {
    status: CONST.STATUS.HTTP,
    headers: headers,
    body: fileData
  });
});
```

以上です。
プランニングポーカーについて

![image.png](https://qiita-image-store.s3.amazonaws.com/0/257568/ee32535c-742f-0205-28eb-9df594bd818f.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/257568/09e40c4a-71a0-d845-7bd8-0ec5e07fe82e.png)

現場で以前取り入れる話が上がったのでまとめ

# プランニングポーカーとは
相対見積もり

## 目的
開発メンバーである自分たちで見積もり、現場感のある値を出すこと

## 効果
- 低コストで素早く、現場として価値のある見積もりが出せる
- メンバーの技術スタックや得意領域の違いから生まれる見解の相違を知り、議論ができる = 認識のギャップを埋められる
- 規模を見積もっているのか個々のスキルと合わせて見積もっているのかが分かる

## 手順
1. 全員に1組のカードを配る（このカードには、1、2、3、5、8）
2. プロダクトオーナーが対象のユーザーストーリーを読み上げる
3. プロダクトオーナーは開発チームからの概要の把握のため、質問に答える
4. 開発チームメンバーは各自カードを選ぶ
5. 選んだカードを一斉にオープンする
6. 全員のカードの見積もり数値を確認する
7. 全員が同じ数値ならその値を見積もり結果とし、次のユーザーストーリーに移り2から始める
8. 異なれば、一番高い人と低い人の見解と根拠を聞く
9. その根拠や懸念点などの学びをチームで話し合う
10. 再度、開発チームメンバー全員でカードを選び直す
11. 5.に戻る

## 書籍情報
市谷 聡啓, 新井 剛, カイゼン・ジャーニー
https://amzn.to/2sRNCqA

JonathanRasmusson,西村直人,角谷信太郎 アジャイルサムライ
https://amzn.to/2RXHso3

## 雑感
説明の過程で懸念事項や過去の失敗談を共有できると、すごく聞く側も為になる
心理的安全性を持って出せるという観点から良いと思う
一時変数のインライン化(Inline Temp)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/257568/fdaf5b9d-a029-52fa-35b6-44022684defa.png)


1つずつリファクタリング技法まとめ
個人的に簡単かつ取り入れ易いと思うものから

## 目的
すぐ引き出せるようにする

## 基本作業サイクル
- システムを動かして仕様を精査
- テストメソッドを作成
- テストの失敗を確認
- テストの成功を確認
- 小さい変更、随時テスト実行(パターン追加失敗確認->成功確認)
- 最後テスト実行
- 最後動作確認

## 一時変数のインライン化(Inline Temp)とは
一時変数への参照を取り除くこと
 
## ポイント
- メソッドの戻り値に一時変数が含まれている時(だけ)
- メソッドの抽出時の一時変数スコープ考慮の懸念をなくしておける

## 例
```
require "date"

def tokyo_olympic?
  year = Date.today.year
  year == 2019
end

puts tokyo_olympic?
```
　　　↓

```
require "date"

def tokyo_olympic?
  Date.today.year == 2019
end

puts tokyo_olympic?
```

## 書籍情報
Jay Fields (著), Shane Harvie (著), Martin Fowler (著), Kent Beck (著),
長尾 高弘(訳), リファクタリング:Rubyエディション
https://amzn.to/2VlyWML

## 雑感
チェーンが長すぎて分かりにくかったら更にメソッドの抽出となりそう
[ubuntu18.04]python3.7でopencv-pythonをimport出来ない時

# 症状

```python
import cv2
>>>
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/ユーザ名/.pyenv/versions/3.7.3/lib/python3.7/site-packages/cv2/__init__.py", line 3, in <module>
    from .cv2 import *
ImportError: libSM.so.6: cannot open shared object file: No such file or directory
```

この時点でふぁっきゅーなので、なんとか直しましょう。どうやら`libSM`とかいうモジュールっぽいのが無いらしいので、インストールします。

`apt search`とかでそれっぽいモジュールを探してインストールします...

```bash
sudo apt install libsm-dev
```

今回の場合、`libsm-dev`をインストールすることで無事`cv2`のインポートが出来ました...。centOS7ではこんなトラブルなかったのに...という備忘録でした。
複数の戻り値の返し方についての備忘録

カンマ区切りはpythonソース上でタプルと見なされます。
()をつけた方が親切なのでつけてもいいと思います。

```python
def hoge():
    # ("id", "name")とみなされる
    return "id", "name"

# タプルをアンパック
id, name = hoge()
```

タプルはimmutableであり、hasableな値です。
listと違い、
後からの要素の変更や追加が不可であり、
タプルごと辞書のキーに使うことができます。

参考
---
[Pythonの関数で複数の戻り値を返す方法](https://note.nkmk.me/python-function-return-multiple-values/)
WebSocket、Socket.ioとは何か？（railsも絡めてざっくりと解説）

## はじめに
今回サーバサイドはrails、フロントエンドはvue.jsでリアルタイム双方向通信を扱ったものを作る機会があり、websocket,Socket.ioについて再学習したので、忘備録兼、僕と同じようにWebSocket、Socket.ioを知りたい方へ情報のシェアをするために投稿させてもらいます。
実は前にも趣味でwebsocket、Socket.ioに触れて簡単にコーディングした機会もあったんですが、当時の理解が浅い＋すっかり内容を忘れていたので、今回は復習です。

当方浅学なため、もし間違っていたりしたら、ご指摘お待ちしております。


## リアルタイム双方向通信
基本的にwebアプリケーションというのは、http通信でクライアントとサーバー間でリクエストとレスポンスによって情報をやりとりしています。つまり、クライアント側からサーバー側にアクセスして情報を読み込むしかなく、例えばチャットやネットワークゲーム等のリアルタイム性、双方向性が必要なものは実現に工夫が必要でした。

###ポーリング
大昔はリアルタイム双方向通信を実現させるためにはポーリングという技術を使っていました。
例えば、Ajax等でms単位で定期的にサーバーにアクセスして情報を引っ張ってくるなど手法がポーリングになります。
しかし、サーバーに変化がなくとも強制的かつ頻繁にアクセスを繰り返すため、ネットワーク帯域とサーバリソースを無駄に消費してしまい、また同時にアクセスしているユーザー数が多くなると、サーバーが負荷に対応できずパンクしてしまう、という問題が発生してしまいます。

###websocket
上記のようにHTTP通信だけだとリアルタイム双方向通信はしんどいよね、という事で登場したのがWebSocketというJavaScriptからサーバーとの双方向通信を行うためのプロトコルです。
実現にはTCP通信を使っています（最初のハンドシェイクのみHTTP通信）。

具体的には以下の流れで実現しています
1. HTTP 通信でクライアントからサーバーにリクエストを送ってコネクションを確立する。（ハンドシェイクと表現される）
2. それ以降はサーバーとクライントを接続しっぱなしにして、TCP により双方向通信。

サーバから情報のプッシュができるため通信コストが低くリアルタイム性が高いこと、またTCPを使っているため軽量なことが特徴なプロトコルです。


railsにおいては**ActionCable**というWebSocketとRailsのその他の部分をシームレスに統合するためのものが用意されており、これを使って実現します。
https://railsguides.jp/action_cable_overview.html


###socket.io
以上のようにリアルタイム双方向通信を実現する技術は（他にもロングポーリング, ストリーミング等)色々あるのですが、これら「複雑なリアルタイムWeb技術の実装方式を隠蔽し、すべてのブラウザ・モバイルデバイスでリアルタイム通信を可能とすること」を目的に開発されているnode.js用サーバー側ライブラリとブラウザ用JavaScriptライブラリのセットがsocket.ioです。
ブラウザの種類やユーザーのPC環境などの違いを吸収して、データの双方向通信の開発を強力にサポートしてくれるも、と表現して良いかと思います。




以上がwebscoket,socket.ioの大まかな概要です。
[Mac]Rails コマンドでエラー /usr/local/bin/rbenv-communal-gem-home Permission denied



# 起こったこと

Gemfile にgem 追加して、bundle install でインストールしてたら、
Rails コマンドでエラー(Permission denied) がでる


```Bash
$ rails
/usr/local/bin/rbenv-communal-gem-home: line 21: /usr/local/bin/../version_cache/2.6.3: Permission denied
```



```Bash
$ rails
Failed loading /usr/local/Cellar/php/7.3.3/pecl/20180731/xdebug.so:  dlopen(/usr/local/Cellar/php/7.3.3/pecl/20180731/xdebug.so, 9): image not found
PHP Warning:  PHP Startup: Unable to load dynamic library 'imap' (tried: /usr/local/lib/php/pecl/20180731/imap (dlopen(/usr/local/lib/php/pecl/20180731/imap, 9): image not found), /usr/local/lib/php/pecl/20180731/imap.so (dlopen(/usr/local/lib/php/pecl/20180731/imap.so, 9): image not found)) in Unknown on line 0
usage: dirname path
mkdir: /../version_cache: Permission denied
/usr/local/bin/rbenv-communal-gem-home: line 22: /../version_cache/2.6.3: No such file or directory
```

## 解決策

/usr/local/bin/rbenv-communal-gem-home 内部の キャッシュのPath が違うらしいので変更。 (例)

```Ruby:/usr/local/bin/rbenv-communal-gem-home
 14 +  cachedir="$RBENV_ROOT/.communal-gem-version-cache"
 15   # cachedir="${BASH_SOURCE%/*}/../version_cache"
```



## 参考

https://github.com/tpope/rbenv-communal-gems/issues/12
【iOS】UITextFieldの入力中にカンマをつける

# 実装

```CommaTextField.swift

import UIKit

// テキスト入力にカンマを含めるTextField
class CommaTextField: UITextField {
    private let numberFormatter: NumberFormatter
    // カンマを含めるかどうか
    internal var isEnable: Bool = true
    
    override init(frame: CGRect) {
        self.numberFormatter = NumberFormatter()
        super.init(frame: frame)
        self.initialize()
    }
    required init?(coder aDecoder: NSCoder) {
        self.numberFormatter = NumberFormatter()
        super.init(coder: aDecoder)
        self.initialize()
    }
    @objc private func textDidChange() {
        if !self.isEnable { return }
        guard let text: String = self.text else { return }
        let noCommaText: String = text.replacingOccurrences(of: ",", with: "")
        if let sValue: Int = self.numberFormatter.number(from: noCommaText)?.intValue {
            self.text = self.numberFormatter.string(from: NSNumber(integerLiteral: sValue))
        }
    }
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}

extension CommaTextField {
    private func initialize() {
        self.numberFormatter.numberStyle = .decimal
        self.keyboardType = .numberPad
        NotificationCenter.default.addObserver(self, selector: #selector(textDidChange), name: NSNotification.Name(rawValue: "UITextFieldTextDidChangeNotification"), object: self)
    }
}

```

# 解説
テキストの入力完了後にNumberFormatterでカンマ表示しているだけ。
すでにカンマが表示されていることもあるので一旦削除してからカンマ変換している。
Docker プライベートレジストリのWebUI調査 (6)

[Docker プライベートレジストリのWebUI調査 (1)](https://qiita.com/rururu_kenken/items/4ab319877dcdd750b2ab)
[Docker プライベートレジストリのWebUI調査 (2)](https://qiita.com/rururu_kenken/items/ff9b5b755d7c5735065e)
[Docker プライベートレジストリのWebUI調査 (3)](https://qiita.com/rururu_kenken/items/996076daaea11e657995)
[Docker プライベートレジストリのWebUI調査 (4)](https://qiita.com/rururu_kenken/items/fb7e6758a3fa60a83314)
[Docker プライベートレジストリのWebUI調査 (5)](https://qiita.com/rururu_kenken/items/b5b6b754774d76b08c53)

#konradkleine/docker-registry-frontend

[Dockerイメージ](https://hub.docker.com/r/konradkleine/docker-registry-frontend/)

**OS**
　Amazon Linux release 2 (Karoo)
**Docker**
　Docker version 18.06.1-ce, build e68fc7a215d7133c34aa18e3b72b4a21fd0c6136

**■前提条件**

docker network作成、プライベートレジストリのコンテナ作成、イメージ登録済

```
docker network create registry-ui-net

docker run -d \
  -p 5000:5000 \
  --net registry-ui-net \
  --name registry-srv \
  registry:latest

docker pull ubuntu:16.04
docker tag ubuntu:16.04 localhost:5000/ubuntu:16.04
docker push localhost:5000/ubuntu:16.04
```

コンテナ起動

```
docker run \
  -d \
  -p 8086:80 \
  --net registry-ui-net \
  --name docker-registry-frontend \
  -e ENV_DOCKER_REGISTRY_HOST=registry-srv \
  -e ENV_DOCKER_REGISTRY_PORT=5000 \
  konradkleine/docker-registry-frontend:v2
```
![image1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208807/6e9b8b3d-5eb8-9c62-f414-584352da51ac.png)
![image2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208807/696e2386-b756-f051-207f-912b871bc7b2.png)
![image3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208807/993bffec-f134-9188-f348-8a4c642d24de.png)
![image4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208807/68e043bb-5ca7-d114-8a89-9a43cedf30ea.png)

[bpholt/docker-registry-frontend](https://hub.docker.com/r/bpholt/docker-registry-frontend/tags)
→konradkleine/docker-registry-frontendと同じ

```
docker run \
  -d \
  -p 8088:80 \
  --net registry-ui-net \
  --name davidcollom \
  -e ENV_DOCKER_REGISTRY_HOST=registry-srv \
  -e ENV_DOCKER_REGISTRY_PORT=5000 \
  davidcollom/docker-registry-frontend:v2
```
[ekazakov/docker-registry-frontend](https://hub.docker.com/r/ekazakov/docker-registry-frontend/tags)
→konradkleine/docker-registry-frontendベース。削除ボタンがある

```
docker run \
  -d \
  -p 8089:80 \
  --net registry-ui-net \
  --name ekazakov \
  -e ENV_DOCKER_REGISTRY_HOST=registry-srv \
  -e ENV_DOCKER_REGISTRY_PORT=5000 \
  ekazakov/docker-registry-frontend
```
![image1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208807/28ee6f60-8d88-3b29-5c49-7f768e1750b4.png)
タグ、リポジトリの削除ボタンがありますが、削除ボタンを押しても削除できませんでした
![image2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208807/dc63b27b-f968-e61a-2942-1dce82a5f102.png)
![image3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208807/d831becb-4221-a0b8-eb3b-15414abac551.png)
![image4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208807/eb42e34a-6cab-36b0-af5f-514b2f0d15da.png)
あんまり意識しない #!/bin/sh はシバンという 

シェルスクリプトを書く時、よく `#!/bin/bash` とか `#!/bin/sh` とか書くけど、これが何かっていうとそのファイルを実行するためのインタプリタのパスを指定している。シバンとかシェバンとか言うらしいけど、日常生活で用いたことは余裕で一度もない。 `!`をBangって言うから、シェル・バンとか、`#` と `!` でハッシュバンとか言う[らしい](https://ja.wikipedia.org/wiki/%E3%82%B7%E3%83%90%E3%83%B3_(Unix))。

例えば下記のコマンドは自分のプロセスを表示する。ログインシェルはzshを使っている。

```shell
$ ps -p $$
  PID TTY           TIME CMD
48577 ttys004    0:00.46 -zsh
```

これを下記のようにシェルスクリプトにして、`chmod +x a.sh` とかで実行権限を与える。シバンはbashのパスを指定している。

```a.sh
#!/bin/bash

ps -p $$
```

これを実行すると

```
$ ./a.sh
  PID TTY           TIME CMD
49563 ttys004    0:00.00 /bin/bash ./a.sh
```

bashで実行されている。

このシバンを下記のように変更する。

```
#!/bin/sh

ps -p $$
```

で、実行する。

```
$ ./a.sh
  PID TTY           TIME CMD
49698 ttys004    0:00.00 /bin/sh ./a.sh
```

shで実行されている。じゃあ、シバンを `#!/bin/zsh` にするとどうなるかっていうと、

```
$ ./a.sh
  PID TTY           TIME CMD
49812 ttys004    0:00.01 /bin/zsh ./a.sh
```

大方の予想通りzshで実行される。ちなみに実行時パスが通っていても、シバンは絶対パスじゃないと動かないらしい。

```a.sh
#!zsh

ps -p $$
```

```
$ ./a.sh
zsh: can't open input file: \nps -p $$\n\M-|:D^E^A
```

要するにシバンとはスクリプトを実行するために、どのパスのインタプリタを使用するかということを絶対パス指定している。込み入ったシェルスクリプトを書くことはあんまりないけど、ときどき、 `#!/usr/bin/env ruby` とか指定されていることがある。これは `env` コマンドはパスの通ってるコマンドを実行するので、各環境のパスが通ったインタプリタにスクリプトを渡す、ということを表している。

シバンにはオプションも使える。（ものがある）例えばbashのシェルスクリプトは、ケースによって、よく `-eux` を渡すようにしている。 `e` はシェルスクリプト内で実行されたコマンドの返り値が0以外だったらシェルスクリプトを停止させる、 `u` は未定義の変数参照を許さない、 `x` はデバッグ情報を出力する。

**変数未定義**

```
$ cat a.sh
#!/bin/bash -eux

echo $HOGE
$ ./a.sh
./a.sh: line 3: HOGE: unbound variable
```

**エラー時シェルスクリプト停止**

```
$ cat a.sh
#!/bin/bash -eux

command_arimasen
echo "todoke"
$ ./a.sh
+ nainai_command
./a.sh: line 3: command_arimasen: command not found
```

ちなみにどうやって実行されているかというと

```
 cat a.sh
#!/bin/bash -eux

ps -p $$
```

上記を実行すると単純にオプションが渡されているのが分かる。

```
$ ./a.sh
+ ps -p 50934
  PID TTY           TIME CMD
50934 ttys004    0:00.00 /bin/bash -eux ./a.sh
```
Docker プライベートレジストリのWebUI調査 (5)

[Docker プライベートレジストリのWebUI調査 (1)](https://qiita.com/rururu_kenken/items/4ab319877dcdd750b2ab)
[Docker プライベートレジストリのWebUI調査 (2)](https://qiita.com/rururu_kenken/items/ff9b5b755d7c5735065e)
[Docker プライベートレジストリのWebUI調査 (3)](https://qiita.com/rururu_kenken/items/996076daaea11e657995)
[Docker プライベートレジストリのWebUI調査 (4)](https://qiita.com/rururu_kenken/items/fb7e6758a3fa60a83314)
[Docker プライベートレジストリのWebUI調査 (6)](https://qiita.com/rururu_kenken/items/530ef38fe0342d6e2bfa)

#parabuzzle/craneoperator

[Dockerイメージ](https://hub.docker.com/r/parabuzzle/docker-registry-ui)

**OS**
　Amazon Linux release 2 (Karoo)
**Docker**
　Docker version 18.06.1-ce, build e68fc7a215d7133c34aa18e3b72b4a21fd0c6136

**■前提条件**

docker network作成、プライベートレジストリのコンテナ作成、イメージ登録済

```
docker network create registry-ui-net

docker run -d \
  -p 5000:5000 \
  --net registry-ui-net \
  --name registry-srv \
  registry:latest

docker pull ubuntu:16.04
docker tag ubuntu:16.04 localhost:5000/ubuntu:16.04
docker push localhost:5000/ubuntu:16.04
```

コンテナ起動

```
docker run -d \
  -p 8085:80 \
  --net registry-ui-net \
  --name craneoperator \
  -e REGISTRY_HOST=registry-srv \
  -e REGISTRY_PORT=5000 \
  -e REGISTRY_PROTOCOL=http \
  -e SSL_VERIFY=false \
  -e ALLOW_REGISTRY_LOGIN=true \
  -e REGISTRY_ALLOW_DELETE=true \
  parabuzzle/craneoperator:latest
```

![image1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208807/f375fbfc-676d-ca79-cd7b-781dc7631d0d.png)
Createdの日付は、元データはグリニッジ標準時間 (GMT)となっていますが、
ブラウザの表示では、ブラウザのタームゾーン設定？を見て表示を切り替えているような動きです。ただし「UTC」という表示はソースコードにべた書き
![image2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208807/21b35949-99d4-85a9-ad1e-91af86e4e3c8.png)
![image3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208807/203088ab-2004-b9ba-6c49-7c8381f0f3fe.png)

**バグ？**
tagをを削除して対象のリポジトリに1件もない状態
例えば、ubuntuというリポジトリに16.04のタグだけあった状態で
削除ボタンで16.04を削除すると404ページに飛ぶ。
また、リポジトリのボタン削除がない。
Docker プライベートレジストリのWebUI調査 (4)

[Docker プライベートレジストリのWebUI調査 (1)](https://qiita.com/rururu_kenken/items/4ab319877dcdd750b2ab)
[Docker プライベートレジストリのWebUI調査 (2)](https://qiita.com/rururu_kenken/items/ff9b5b755d7c5735065e)
[Docker プライベートレジストリのWebUI調査 (3)](https://qiita.com/rururu_kenken/items/996076daaea11e657995)
[Docker プライベートレジストリのWebUI調査 (5)](https://qiita.com/rururu_kenken/items/b5b6b754774d76b08c53)
[Docker プライベートレジストリのWebUI調査 (6)](https://qiita.com/rururu_kenken/items/530ef38fe0342d6e2bfa)

#joxit/docker-registry-ui

[Dockerイメージ](https://hub.docker.com/r/joxit/docker-registry-ui)

**OS**
　Amazon Linux release 2 (Karoo)
**Docker**
　Docker version 18.06.1-ce, build e68fc7a215d7133c34aa18e3b72b4a21fd0c6136

**■前提条件**

docker network作成、プライベートレジストリのコンテナ作成、イメージ登録済

```
docker network create registry-ui-net

docker run -d \
  -p 5000:5000 \
  --net registry-ui-net \
  --name registry-srv \
  registry:latest

docker pull ubuntu:16.04
docker tag ubuntu:16.04 localhost:5000/ubuntu:16.04
docker push localhost:5000/ubuntu:16.04
```

コンテナ起動

```
docker run -d \
  -p 8084:80 \
  --net registry-ui-net \
  --name docker-registry-ui \
  -e REGISTRY_URL=http://registry-srv:5000 \
  -e DELETE_IMAGES=true \
  -e REGISTRY_TITLE="My registry" \
  joxit/docker-registry-ui:static
```
![image1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208807/adef45f6-0b65-20b3-3b6c-987c27db7954.png)
削除ボタンはありますが、押すとエラーがでました。時間があるときに調査予定
![image2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208807/938b8957-4aa1-b17e-48f7-c4d690caf4b7.png)
Railsのテスト環境  RSpec とは？！

#RSpecとは
RSpec とは Ruby プログラマー向けの BDD(Behaviour-Driven Development) ツールです。
事前にエラーになる可能性がある箇所を発見後修正したり、要件の漏れを防ぐことができます。
例えば、現在数万人を超える自社WEBアプリを運用していてテストコードなしで、本番アプリケーションに適用してしまいバグが発生しそのサービスが停止してしまった場合、損失は計り知れないものになります。
エンジニアは、あらゆるケースを想定しテストコードを書く必要があります。

##gemのインストール
※テスト環境に追記します。

```
gem 'rspec-rails'
group :development do
  gem 'web-console'
end
```
ターミナルでこちらのコマンドの実行をお忘れなく

```
$ bundler install
```
##web-console
##RSpecの基本設定をする

```:Gemfile
$ rails g rspec:install
Running via Spring preloader in process 17507
      create  .rspec
      create  spec
      create  spec/spec_helper.rb
      create  spec/rails_helper.rb
```
RSpecで必要なファイルが複数できました。

>【rails_helper.rb】
Railsで、RSpecを使う際に共通の設定を書いておくファイルです。各テスト用ファイルでこちらのファイルを読み込むことで、共通の設定や、メソッドを適用します。

>【spec_helper.rb】
RSpec用の共通の設定を書いておくファイルですが、こちらはRSpecをRails無しで利用する際に利用します。

オプションを追加するとテキスト出力や、並行表示とかもできるようになる。
以下を追加しましょう。

```:.rspec
--format documentation
```
##RSpecが正常に動作するか確認する

```
$ bundle exec rspec

Finished in 0.00053 seconds (files took 0.21178 seconds to load)
0 examples, 0 failures
```
##RSpecのディレクトリ構造

```
spec/rails_helper.rb
spec/spec_helper.rb
```
#単体テスト
Docker プライベートレジストリのWebUI調査 (3)

[Docker プライベートレジストリのWebUI調査 (1)](https://qiita.com/rururu_kenken/items/4ab319877dcdd750b2ab)
[Docker プライベートレジストリのWebUI調査 (2)](https://qiita.com/rururu_kenken/items/ff9b5b755d7c5735065e)
[Docker プライベートレジストリのWebUI調査 (4)](https://qiita.com/rururu_kenken/items/fb7e6758a3fa60a83314)
[Docker プライベートレジストリのWebUI調査 (5)](https://qiita.com/rururu_kenken/items/b5b6b754774d76b08c53)
[Docker プライベートレジストリのWebUI調査 (6)](https://qiita.com/rururu_kenken/items/530ef38fe0342d6e2bfa)

#jc21/registry-ui

[Dockerイメージ](https://hub.docker.com/r/jc21/registry-ui)

**OS**
　Amazon Linux release 2 (Karoo)
**Docker**
　Docker version 18.06.1-ce, build e68fc7a215d7133c34aa18e3b72b4a21fd0c6136

**■前提条件**

docker network作成、プライベートリポジトリのコンテナ作成、イメージ登録済

```
docker network create registry-ui-net

docker run -d \
  -p 5000:5000 \
  --net registry-ui-net \
  --name registry-srv \
  registry:latest

docker pull ubuntu:16.04
docker tag ubuntu:16.04 localhost:5000/ubuntu:16.04
docker push localhost:5000/ubuntu:16.04
```

コンテナ起動

```
docker run -d \
  -p 8083:80 \
  --net registry-ui-net \
  --name registry-ui \
  -e REGISTRY_HOST=registry-srv:5000 \
  -e REGISTRY_SSL=false \
  -e REGISTRY_DOMAIN=registry-srv:5000 \
  -e REGISTRY_STORAGE_DELETE_ENABLED=true \
  jc21/registry-ui
```
![image1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208807/61adeddb-3588-d73a-d196-b85a03df5623.png)
![image2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/208807/3e456f1a-e7f1-11cd-9eff-0124a23f9697.png)