OmniAICreator/Qiita-1.07M huggingface dataset:
abstractのOrganizationロゴが変更できない

## 事象
- abstractのOrganizationロゴが変更できない
- 具体的には、Adminアカウントで `https://app.goabstract.com/organizations/hogehoge/edit` のCHANGE LOGO に画像をアップロードすると、下記のような表示になりその先に遷移できない
- <img width="469" alt="abst.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317327/bf2c6778-a5dc-c887-01e9-582b28ec1ab0.png">
- sizeの変更等は色々頑張ったけど、どうにもならん・・

## 問い合わせてみると
- 半日もたたずに回答あり！親切！

```
Hi,

Thanks for writing in. Can you please confirm which browser you are attempting to make the change in? 

There is a known issue with Chrome and some users not being able to update logos and avatars. We are currently working on a fix, but in the meantime using another browser such as Safari has been a workaround. 

Looking forward to hearing back.
```

- 要はChrome依存のissueなので、Safariとかでもう一度やってみてねとのこと

## 回答通りにやってみると
- 変更できました！ Thanks!

- 回答の明確さとスピード感に感動して、記事にしてしまった。ニッチなお困りだが、届く人に届くといい。
WindowsにPython3とOpenCVをインストールする

こんにちは。Ideagearの林です。
今回はオープンソースの画像動画ライブラリであるOpenCVと、そのインストールに必要なPython3のインストール方法についてまとめていきたいと思います。

#環境
Windows7 32ビット版(XP以前ではインストールできないようです)
今回インストールしたバージョンはPython 3.7.4です。

#python3のインストール
まず[ここ](https://www.python.org/downloads/windows/)からパッケージをダウンロードします。

基本的に左側のStable Releasesの中から上部の一番バージョンが高いものを選べばOKです(下図ではPython 3.7.4)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488218/7a32c7d1-dbbc-a999-b4e3-09280ceaec26.png)


32bit版Windowsにインストールするなら

**Windows x86 web-based installer**

64bit版なら

**Windows x86-64 web-based installer**

をダウンロードします。
___

次に、ダウンロードしたパッケージを実行します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488218/b0b92ec1-62f3-7da8-9060-3c2eb07fd2b6.png)

**Add Python 3.x to PATH** をチェックします。

**Install now** をクリックしてインストールを開始します。

#OpenCVのインストール

Python 3がインストールできたら、pipコマンドを利用して、OpenCVをインストールできます。

コマンドプロンプトを開き、(Windowsキー+rを押し、cmdと入力する等)

`pip install opencv-python`

を実行すると、インストールが開始されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488218/a34c1ad3-c8fb-155c-b767-0a7042f42b7a.png)


OpenCVのライブラリが利用できるかをthon確かめて、正しくOpenCVがインストールされているかどうかを確認できます。コマンドプロンプトで

`python`

を入力して対話型実行環境を起動し、

`import cv2`

を入力してエラーが出なければ成功です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488218/77fadcd2-b3da-e977-3cd6-4379eceb271a.png)


以上で、無事にインストールできました。
おつかれさまでした。

#参考にしたサイト様
https://www.python.jp/install/windows/install_py3.html
https://news.mynavi.jp/article/zeropython-34/
Spring Data JPAサンプルプログラム

前僕が掲示板というSpring bootサンプルアプリケーションを作った。最近Spring Data JPAの使い方を示すため、以下のことをした

-   リポジトリで直接にJDBCを使うからSpring Data JPAを使うへ
-   ログインの時Spring Data JPAを使ってユーザーデータをもらう

ソースコードは[ここ](https://github.com/saladlam/spring-noticeboard/tree/spring-data-jpa)でダウンロードできる。
IntelliJのフォントをツールウィンドウも含めて見えやすいサイズまで拡大してみた

# なぜフォントを拡大したかったのか
最近すっかり視力が悪くなってしまって、目を凝らさないと十分に文字を認識することができず、またそのための疲労がとてつもないことになっていました。
そのためブラウザやエディタのサイズを拡大して疲労感を軽減したいと考えました。

# IntteliJのフォント拡大について
IntelliJのフォント拡大機能は、IntelliJ内の表示項目別に別れており、それぞれの設定を変更しないと適切なサイズになりません。
`エディタのフォント拡大`と`それ以外の部分のフォント拡大`があるようです。
`IntelliJ フォント拡大`などで検索すると、`エディタのフォント拡大`についてはヒットするのですが、これだけでは`それ以外の部分`の拡大はできません。
そのためこの両方について以下記載したいと思います。また言語設定はpleiadesにより日本語化されているものを使用します。

# エディタのフォント拡大について
いくつか方法があるようです。

1.一時的に拡大したい場合
　こちらは現在開いているタブを拡大したい場合に使用できる機能です。
　タブを変更すると変更したサイズは元に戻ります。
　ユースケースとしては一時的に他人にコードを見せたい場合などでしょうか。

 - 環境設定→エディター→一般→コマンド＋マウス・ホイールでフォントサイズ（ズーム）を変更するにチェックを入れる。
 - `⌘ ⇧ A`コマンドを押して`フォント・サイズを拡大`を入力する。
https://pleiades.io/help/rider/Zooming_in_the_Editor.html

2.恒久的に拡大したい場合
　こちらはエディタ部分について恒久的に拡大します。
　私はこちらの設定を変更しました。

- 環境設定→エディター→サイズ
https://pleiades.io/help/idea/settings-editor-font.html


# それ以外の部分のフォント拡大について
- 環境設定→外観振る舞い→外観→カスタムフォントサイズの使用→サイズ
  
　これでツールウィンドウやターミナルのフォントサイズを併せて拡大できます。
https://pleiades.io/help/idea/settings-appearance.html

# おまけ
　詳しく調べていないのですが、`プレゼンテーションモード`というものを使用するとフォントサイズが24まで拡大されるようです。（デフォルト設定）
LT等にご登壇される方が一時的に拡大するなどの用途で用いられそうですね。

- 表示設定→プレゼンテーションモードにする
 
https://pleiades.io/help/idea/ide-viewing-modes.html#presentation
新しいMacがきたので作業をメモしておきます~xcode編~

# はじめに
新しいMacがきたので作業工程とかメモしておこうと思います。
後から、あれなんだっけってなりがちなので。

また完全に初期状態なのでパラメータとかも覚えておきたいので。

## Xcodeを入れる

```
$ xcode-select --install
xcode-select: note: install requested for command line developer tools
```

使用許諾の画面が出てくる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134077/705fb5ad-927b-b8f7-e713-a2a6dc5a85ac.png)

「同意する」を押下する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134077/c01b1139-6c49-a897-d6ae-d22ba7d04442.png)

「インストール」を押下する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134077/9fa38a81-a301-92f4-161d-c509f35913e7.png)

インストール中ってなる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134077/3faad57e-7f30-0eac-e320-fff4cb4da316.png)

そのうち1分くらいで終わるので「完了」を押下して終了

これだけ
AWS EC2 EIP使わずに起動時CNAME自動更新

#節約
インスタンスにEIPをつけたまま停止すると、EIP費用が発生する。
https://aws.amazon.com/jp/premiumsupport/knowledge-center/elastic-ip-charges/
それでなくてもクラウドなら固定IPをできる限り避けたい。

#タスク
起動時付くパブリックDNSは停止・起動するだびに変わるので起動時CNAMEを更新する。
（Azureは自動更新してくれる）
### インスタンスにIAM Roleを割り当て

```json
{
    "Statement": [
        {
            "Sid": "Sxxxxxxxx",
            "Action": [
                "route53:ChangeResourceRecordSets",
                "route53:GetHostedZone",
                "route53:ListResourceRecordSets",
            ],
            "Effect": "Allow",
            "Resource": "*"
        }
    ]
}
```
### /home/ec2-user/update-cname.sh

```bash
#!/bin/bash

#例 hoge-service.domain.com

export AWS_DEFAULT_REGION=ap-northeast-1

DOMAIN_NAME="domain.com"
HOST_NAME="hoge-service"
#IP_ADDRESS=`curl -s http://169.254.169.254/latest/meta-data/public-ipv4`
PHOST_NAME=`curl -s http://169.254.169.254/latest/meta-data/public-hostname`
HOSTED_ZONE_ID=`aws route53 list-hosted-zones | grep ${DOMAIN_NAME} | awk '{print $3}' | sed -e 's/\/hostedzone\///'`

BATCH_JSON='{
  "Changes": [
    { "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "'${HOST_NAME}'.'${DOMAIN_NAME}'",
        "Type": "CNAME",
        "TTL" : 60,
        "ResourceRecords": [
          { "Value": "'${PHOST_NAME}'" }
        ]
      }
    }
  ]
}'

/usr/bin/aws route53 change-resource-record-sets --hosted-zone-id ${HOSTED_ZONE_ID} --change-batch "${BATCH_JSON}"

```
### ユニットファイルを作成

```bash:/etc/systemd/system/update-cname.service
[Unit]
Description = update_cname_shell

[Service]
ExecStart = /home/ec2-user/update_cname.sh
Restart = always
Type = simple

[Install]
WantedBy = multi-user.target
```
### サービス起動と活性化

```bash
systemctl enable update-cname
systemctl start update-cname
systemctl status update-cname
```

#参考
https://www.kabegiwablog.com/entry/2018/03/23/090000

この間、AWS東京リージョンに大規模障害があった。MZなら問題なかったと発表があったが、うちはMZでも障害が発生した。
AWSにそこを問い詰めると、他のサービス絡みで障害になったかもしれないとステム構成図を求められた。
原因なんか知りたくない。分かってどうする。AWSさんが改善すると信じるし、信じるしかない。クラウドだから。

言い訳を聞かれる時間の最後にショックなことがあった。
サポートプランだが、企業はビジネスかエンタープライズの選択が必須になるらしい。
完全にロックオンされてしまった。
代理店を挟んだらどうかとあきれる話もあった。複雑なAzure契約がいやでAWSを押してきた過去が恥ずかしくなった。
一晩悩んで次の朝、ノートPCにベタベタ貼ったAWSシールをすべて剥がした。
もう・・・誰も愛さない。
FirestoreではMapデータの値としてundefinedは使っちゃダメですよ

怒られました。

## nullは大丈夫
data = {key:null}ではちゃんと登録されます。

<img width="547" alt="名称未設定.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51116/b7a886b1-3f9a-b97b-10bf-fa21ce2e1bd2.png">

## undefinedはダメ

data = {key:undefined}

怒られます。

```sh
Value for argument "data" is not a valid Firestore document. Cannot use "undefined" as a Firestore value (found in field key).
```

エラーメッセージが親切なのがありがたいです。

ドキュメントはここ<[https://firebase.google.com/docs/firestore/manage-data/data-types](https://firebase.google.com/docs/firestore/manage-data/data-types)>です。

使っていいのはこれらの種類です...との説明がありますが、undefinedはダメ！とまでは書いてありません。

MongoDBとかだとundefinedがnullとして登録されることもありますが、Firestoreでは注意しましょう。
Automation Anywhere　★基本入門★「Files/Folders」

「Files/Folders」です
FileとFolder操作コマンドです


作業用にFolderを作成し、前回作成しているExcelファイルを入れておきます。
これでPC側の準備は完了です:v_tone1:


「Files/Folders」はその名の通、ファイル・フォルダ操作のみを行うコマンドです。
まずコマンドを探してください。

探し出せたら「Open　Folders」をダブルクリックして開きます。

作成したFolderのパスをコピーして、コマンド内に入力します。
※""はいりません。。。エラーでます。

「Folder」操作なので、「Folder」にチェックが入っているはずです。
なおかつ「Open　Folders」にもチェックがされているはず。

「Save」クリック→AAのSaveをしてRunしてみてください

<img width="299" alt="1__AA.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489732/00901b8b-3c0f-150c-c58c-bcb5c3ede017.png">


無事にFolderが開きましたでしょうか？

Folderパスの指定の仕方ですが、パス入力欄の右「Browse」をクリックしても指定は可能です。



<img width="374" alt="5__AA.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489732/34fa8840-9cf8-fddf-2a28-aa249d907ce3.png">


次はFileを開きます。

「Open　Files」をダブルクリックして開きます。

今回は「File」操作なので、「File」にチェック。
「Open File」にチェック。

入力欄へは開きたいファイルのフルパスを入力します。
※Folderと同じに「Browse」でも指定は可能です。

コマンド・AAともにSaveしてRunしてみて下さい。
Fileが開きます。


<img width="299" alt="2__AA.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489732/44f95282-1034-22cc-a722-e1f1dafafba8.png">


注意事項です。
Fileを開くコマンドがあれば、Excelコマンドで開く必要あるの？と疑問が出ますが、ExcelはExcelコマンドでないと処理続行不可です。
開くだけなら、この「Open File」でもOKです。
BatやVBSファイルを単に開いて実行させたいだけの場合も「Open File」で対応は可能です。




次はFileコピーです。

「Copy　Files」をチェックします。
コピーですので、コピー元とコピー先が存在します。

「Sauce Files(s):」へコピー元ファイルのフルパスを入力
「Destination File(S)/Folder:」へコピー先の「Folderパス\xxxxx.xlsx」を入力します。
※「Browse」でもパス指定は可能です。

コピー先のFile名は別名である場合の想定で、ここで名前の変更を行います。



<img width="247" alt="3__AA.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489732/0edfea8b-c315-b632-997c-33e4f5e37fc8.png">


コマンド・AAともにSaveしてRunしてみて下さい。
Fileが指定したFolder内にコピーされます。


他にもサブコマンドはありますが、よく使用する「Open/Copy(Rename)」について記載いたしました。
他のサブコマンドも試してみて下さい。




さてここで「Copy　Files」に関しての追記です。

★「Copy　Files」の隣にある「Rename Files」そのまま名前の変更サブコマンドです。
Fileの名前を変更します。
変更前の元ファイル：フルパスを指定し、変更後(Rename後)のファイル名を入力します。
同一Folder内での操作となるはずなので、ファイル名.拡張子で変更可能です。

※コピーは行いませんので、コピーしてRenameしたい場合は「Copy Files」を使用します。

★業務において「コピー元にファイルは残さない」という場合、AAには「Move(移動)」が現時点では見当たらないので、Fileをコピーしたのち「残したくないFileの削除」が必要です。

≪処理工程≫
・ファイルコピーを行う
・コピー先へファイルがコピーされる
・元ファイルは残っている(不要)
・元ファイルを「Delete Files」する

処理工程を記載すると、これがAAのFile移動手段であると分かります。

★「Copy　Files」のSave上の「Overwrite  Files/Folders」ですが、コピー先に同名のファイルがある場合に「上書き」を行います。チェックをいれないと、エラーでます。


・おまけ・
★「Un Zip Files」ですが、現時点で解消されている場合と、そうでない場合が混在しているようなので記載しておきます。
日本語Zipの解凍を行うと、外も中も文字化けしていました(逆におもしろい)
原因は「AAが日本語対応でなかったから」のようです。
もし、Zip解凍で文字化けする方は、地道に「右クリック→すべてを展開」処理を組んでください。。





Automation Anywhere　★基本入門★
「Files/Folders」これにて終了！
お読みいただき、ありがとうございました

次回は「Insert KeyStroke」でExcelファイルに何かを入力します。
vue.jsの開発環境をdocker上に構築した際にhot-reloadが効かない際の対策【windows】

## 対策
vue.config.jsに記載する

```js:vue.config.js
module.exports = {
  // ...
  devServer: {
    // ...
    watchOptions: {
      poll: 500
    }
  }
}

```
## 余談
+ 異なるファイルシステム間だとファイルの変更をうまく検知できないらしい。
+ vuetify2の導入のために、`webpack.config.js`も作成していたが、
こちらに記載しても効果がなかった...
+ コンテナ内で変更を検知する目的でinotify-toolsを導入してみたが、無くても動いたので必要なさそう


## 参考
+ [ファイルシステムが異なる環境下でwebpackのwatchが動かない](https://qiita.com/kheiakiyama/items/0d0dbe21d850c5ff0848)
+ [webpackの設定とinotify-toolsでの変更検知](https://stackoverflow.com/questions/42445288/enabling-webpack-hot-reload-in-a-docker-application)
Spring Data JPA demonstration

On before I made a Spring boot example application, now I made a change on it to show how to use Spring Data JPA. Following change is made

-   change repository layer from by using JDBC directly to by using Spring Data JPA
-   get user information by using Spring Data JPA when login

You may download source code from [here](https://github.com/saladlam/spring-noticeboard/tree/spring-data-jpa).
Cordovaのプラグインinappbrowserのmessageイベントのやり方

Cordovaのプラグインinappbrowserでwebviewアプリを作成した時にinappbrowser内のリンクを端末の標準ブラウザで開く方法にもの凄く苦戦したのでやり方を残します。

# ■ 構築環境
**・Cordova9.0.0**
**・inappbrowser3.1.0**

# ■ メッセージを送る側(inappbrowser内)

```
var value = 'value';

var messageObj = {hoge: value};

var stringifiedMessageObj = JSON.stringify(messageObj);
        
window.webkit.messageHandlers.cordova_iab.postMessage(stringifiedMessageObj);
```

# ■ メッセージを受け取る側(アプリ内)
受け取る側での変数の参照の仕方ですが今回は送る側で `hoge` という名前で送信したので
参照する時は `event.data.hoge` です。

```
var hoge = cordova.InAppBrowser.open('url', '_blank');
hoge.addEventListener('message', function(event) {
    // ここに処理を書く
    console.log(event.data.hoge);
});
```

# ■ 注意点
inappbrowserのversionのみです！versionは `3.1.0` 以上でないと動きません。自分はこのやり方をすぐに見つけたのにversionのせいだと気付かず色々なやり方を試していました。cordovaはたまにプラグインのversionを変えた時によくわからないバグが発生するのでその時は新しいプロジェクトからやると楽です。
imput method を受け付けないQLineEdit

備忘録です。
本当は制御するものが欲しくていろいろ探しています。

```
import sys
from PySide2 import QtCore
from PySide2 import QtGui
from PySide2 import QtWidgets


app = QtWidgets.QApplication(sys.argv)

hello = QtWidgets.QLineEdit("")
hello.setAttribute(QtCore.Qt.WA_InputMethodEnabled,False)
hello.resize(200, 100)
hello.show()

sys.exit(app.exec_())


```
Android10でのTransitionエラー対策

Android10のアップデートすると、それまで動いていた遷移アニメがバグりました。

ほかのandroidxライブラリの`androidx.transition`はバージョンが低かったので
おとなしく [transition 1.2.0-rc01](https://developer.android.com/jetpack/androidx/releases/transition#1.2.0-rc01)本体、使いましょう。
TypeScriptでn未満の自然数を表す union 型を作る

JavaScript 標準の `Math.random` は小数を返しますが、「指定した n 未満の自然数」が欲しい場合があります。というかそれが便利です。

```ts
const a = randomInt(5); // 0, 1, 2, 3, 4 のいずれかが返る
```

その作り方はググれば出てくるのでそちらに任せるとして、今回はそれの型の付け方についての話。

上記の `randomInt` 関数の型、普通につけるなら下記のようになるでしょう。

```ts
function randomInt(n: number): number;
```

もちろんこれでいいと思いますが、今回はネタ的に「返ってくる可能性がある値」だけを戻り値の型にすることを考えます。

すなわち、先の例だと `// 0, 1, 2, 3, 4 のいずれかが返る` わけですから、本来は `0 | 1 | 2 | 3 | 4` が正しい(？)わけです。ということで、そうできないか挑戦してみました。

# やり方

[TypeScriptで最低n個の要素を持った配列の型を宣言する方法](https://qiita.com/uhyo/items/80ce7c00f413c1d1be56) を参考に書いてみました。なお

> ちなみに、型レベル再帰の回数には制限があるので注意してください。今回の場合だと、AtLeast<46, number>のように要素数を46以上にすると再帰の限界を超えてエラーになりました。

らしいので、`randomInt` の戻り値としては実用的ではないかと思います。あくまで型パズルネタとしてお楽しみください。

以下で実現できました[^1]。

```ts
// 参考記事の Append そのままです
type PlusOne<Elm, T extends unknown[]> = ((
  arg: Elm,
  ...rest: T
) => void) extends ((...args: infer T2) => void)
  ? T2
  : never;

type NaturalNumberRec<
  N extends number, // randomInt に与えられた数
  I extends number, // カウンター
  C extends unknown[] // カウンター保持用配列
> = {
  0: never; // N === I のとき
  1: I | NaturalNumberRec<N, PlusOne<N, C>["length"], PlusOne<N, C>>;
}[N extends I ? 0 : 1];

type NaturalNumber<N extends number> = NaturalNumberRec<N, 0, []>;

function randomInt<N extends number>(n: N): NaturalNumber<N> {
  throw Error("Not implemented");
}

const a: 0 | 1 = randomInt(2);
const b: 0 | 1 | 2 | 3 | 4 = randomInt(5);
```

発想としては union 型の結合律（`0 | (1 | 2)` が `0 | 1 | 2` であること）を利用して、カウンター変数を使って再帰でループチックなことをしながら union に要素を追加していってるだけです。配列と数値の2つでカウンターを保持しているのは型システム上で数値の計算ができないため配列（タプル）の `length` を利用する[^2]という、参考サイトの発想そのままです。

`PlusOne<N, C>` を 2 回書いてる部分はもう少し工夫できそうな気がします。

実行コード風に書くと下記のイメージのことをしています。

```ts
function plusOne(i: number): number {
  return i + 1;
}

function naturalNumberRec(n: number, i: number): number[] {
  return (n === i) ?
    [] :
    [i].concat(naturalNumberRec(n, plusOne(i)));
}

function naturalNumber(n: number): number[] {
  return naturalNumberRec(n, 0);
}

naturalNumber(5); // -> [0, 1, 2, 3, 4]
```

いかがだったでしょうか？[^3] こんなことまで出来るなんて、TypeScript は凄いですね。TypeScript の柔軟な型システムを活かして良い TypeScript ライフを！

[^1]: が、最初の利用箇所で再帰の深すぎワロタエラーが出てしまいます。。。なぜ。。。
[^2]: 逆に配列だけあれば `I` は不要ですが、毎回 `length` を取るのも面倒なので冗長ですが変数に持たせてみました
[^3]: 一度言ってみたかった
EloquentModelを使ってエンティティを取得しているメソッドのユニットテストの書き方

# 背景
例えば`TestModel::findOrFail()`とか中でしているメソッドのユニットテストを書くと、どうしてもDBが絡んでユニットテストではなくなってしまう。
これの解決方法。

# 結論

```php5:ExampleService
use App\ExampleModel;

class ExampleService {
    private $exampleModel;

    public function __construct(ExampleModel $exampleModel)
    {
        $this->exampleModel = $exampleModel;
    }

    public function func()
    {
        ...
        $this->exampleModel->findOrfail($id);
        ...
    }
}
```

```php5:ExampleServiceTest
use App\ExampleModel;

...

    $exampleModel = Mockery::mock('\App\ExampleModel')
    $entity = new stdClass;
    $entity->name = $name;
    $exampleModel
        ->shouldReceive('findOrFail')
        ->with($id)
        ->andReturn($entity);
    app()->instance(ExampleModel::class, $exampleModel);
...

```

# 解説

## EloquentModelはコンストラクタインジェクションで入れておいて、builder機能をインスタンスメソッドで使う

例えば`findOrFail()`メソッドなんかはよくstaticメソッドとして実行されるが、内部的には`(new static)->$method()`とかやってるだけなので、インスタンスメソッドとして実行しても同じものが得られる。
それであればテストの観点からコンストラクタインジェクションで外部からオブジェクトをもらった方が良い。

## テストにおいてEloquentModelのクラス名でサービスコンテナに入れておく

Laravelのコンストラクタインジェクションは、そのクラス名でサービスコンテナに探し行く。つまり内部的には`app()->make(ExampleModel::class)`で取ってきていると考えられる。
そうであれば、そのクラス名でmockをサービスコンテナに登録しておけば、テスト時にDBが絡むことを防ぐことが出来る。
WSLのUbuntuを管理者権限で立ち上げたときの権限の見え方の違い

WSL[^1]便利だけどややこしい面も。詳しい人の解説コメントなんてくるといいなぁなんて（他力本願（誤用））。

## 前提

Windows10上でUbuntu 16.04.3です。バージョン詳細は[後述](#バージョン詳細)。

## C直下にファイルを置く

管理者権限で立ち上げてないとできない。これは当たり前っちゃ当たり前。

ユーザー権限で立ち上げたUbuntuコンソールから↓

```
/mnt/c$ touch a
touch: cannot touch 'a': Permission denied
```

管理者権限で立ち上げたUbuntuコンソールから↓

```
/mnt/c$ touch a
/mnt/c$
```

## 作ったファイルの権限の見え方の違い

タイトルにもしてるが、へぇとなったのはこちら。
**ユーザー権限だと555、管理者権限だと777と出る。**
Windows側の権限とLinux側の権限がどう仕組まれていてこうなるのかよく分からない。

ユーザー権限で立ち上げたUbuntuコンソールから↓

```
/mnt/c$ ll a
-r-xr-xr-x 1 user user 0 Sep 11 09:59 a*
```

管理者権限で立ち上げたUbuntuコンソールから↓

```
/mnt/c$ ll a
-rwxrwxrwx 1 user user 0 Sep 11 09:59 a*
```

## バージョン詳細

Ubuntuのバージョンはこんな感じ。

```
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="16.04.3 LTS (Xenial Xerus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04.3 LTS"
VERSION_ID="16.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
VERSION_CODENAME=xenial
UBUNTU_CODENAME=xenial
```

[^1]: WindowsでLinuxが使えるWindows Subsystem for Linux(WSL)。UbuntuとかSUSEとか使える。（Microsoft Storeからディストリビューションで検索すると出ます）
#AWS 初心者が キューイングサービス #SQS を初めてさわってみる

# SQS

https://aws.amazon.com/jp/sqs/

![image](https://user-images.githubusercontent.com/13635059/64657700-a23ee500-d46f-11e9-8460-1b7d1f5c1e4c.png)

# コンソールにサインインして SQS を選ぶ

![image](https://user-images.githubusercontent.com/13635059/64657712-aec33d80-d46f-11e9-8bec-24f2ed886077.png)
# 今すぐ始める

![image](https://user-images.githubusercontent.com/13635059/64657824-0feb1100-d470-11e9-84cb-6da1c74736a2.png)

# 新しいキューの作成でキューに名前をつける

![image](https://user-images.githubusercontent.com/13635059/64657733-cef2fc80-d46f-11e9-896d-56f25c56c4ac.png)

# 二種類のキューがあるっぽい

 
![image](https://user-images.githubusercontent.com/13635059/64657742-dadebe80-d46f-11e9-8413-44d31399d43c.png)

# 標準とFIFOの違いは？

順序の保証が大きそう。


# キューのクイック作成をする


![image](https://user-images.githubusercontent.com/13635059/64657845-24c7a480-d470-11e9-8083-2f5ea1558ff0.png)

# 作成された

![image](https://user-images.githubusercontent.com/13635059/64657982-bafbca80-d470-11e9-97f8-91cc6b695df5.png)

# キューの操作でメッセージの送信をしてみる

![image](https://user-images.githubusercontent.com/13635059/64658001-cd760400-d470-11e9-9a97-371b2a563c2b.png)

![image](https://user-images.githubusercontent.com/13635059/64658248-c3083a00-d471-11e9-8496-1038f1c8842a.png)

# 利用可能なメッセージが1件に増えた

![image](https://user-images.githubusercontent.com/13635059/64658037-f3030d80-d470-11e9-815f-afa66f5d54ff.png)

# メッセージってどうやって見るの？

# ポーリングを開始という扱いがあるらしい

受信できた

![image](https://user-images.githubusercontent.com/13635059/64658103-29d92380-d471-11e9-83d1-4b697994e25b.png)

![image](https://user-images.githubusercontent.com/13635059/64658118-378ea900-d471-11e9-9cb1-c77d80912975.png)

![image](https://user-images.githubusercontent.com/13635059/64658127-42e1d480-d471-11e9-885e-1b4d0ba4e291.png)

# 詳細確認、削除ができる

![image](https://user-images.githubusercontent.com/13635059/64658220-a8ce5c00-d471-11e9-91a3-8dc94e4357f4.png)

![image](https://user-images.githubusercontent.com/13635059/64658182-81778f00-d471-11e9-9f6b-465178f8aaa1.png)

# なんとなくわかったような

わからないような。

to be continued


# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2406








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Terraformで管理しているインフラのデプロイを自動化する

# はじめに
こんにちわ。Wano株式会社エンジニアのnariです。
今回は、GitFlowを利用して、CodeBuildで実行するCI上でterraformリソースをチェック/デプロイする仕組みをつくったのでその備忘録を残しておこうと思います。

# システム全体像
<img width="692" alt="スクリーンショット 2019-09-11 01.37.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321850/f844321f-a3c9-b197-b79a-563a19586d24.png">

# 何故作ろうと思ったか
- **オペレーションの履歴をslack上に残しておきたかった**
- 本番環境は、レビューチェック後そのままdeployされるようにしたかった
- 運用は他のチームに引き継ぐことになっているので、オペレーションはなるべく簡素にしたかった

# 懸念点

- [以前の記事](https://qiita.com/fukubaka0825/items/103c900a4072121bb4ae)のように、コンポーネント（tfstate）を分割して管理しているので、全部いちいちplanやapplyしていたら通知も煩雑になり、実行時間も長くなりそう
  - CI(テスト）時に使っていたbuild imageがあるのでそれさえ解決できればすぐに構築できそう

# どう懸念点を改善したか
- 以下の記事をかなり参考にし、コードの差分のあるディレクトリのみでplan/applyを実行するようにした  
[Terraform どこで実行していますか？ - mixi developers - Medium](https://medium.com/mixi-developers/terraform-on-aws-codebuild-44dda951fead)
- 上記の記事と違うのは、buildフェイズで走らせるrun.shでのplanとapplyの分岐を、branchの名前で実現したところ
  - ブランチ名がplanで始まる場合plan　そうではない場合はapplyを実行する
  
```run.sh

#!/bin/sh -xe
if echo $USER_BRANCH | grep -q 'plan/'; then
  /bin/sh script/tf_ci/plan.sh
else
  /bin/sh script/tf_ci/apply.sh
fi
```

- コマンド操作とuserを結びつけたかったのでmessageにuserの項目を追加 projectURLも追加
- ディレクトリで各環境を管理しているため、stage環境ならprodディレクトリを無視、prod環境ならstageディレクトリを無視する形でコマンドを実行する
- lambda系のリソースはeventsディレクトリ以下にてapexで管理しているため、eventsディレクトリではapexコマンドを打つように変更

```plan.sh

#!/bin/sh -xe
if [ $ENV = "stage" ]; then
    export EXCLUDE_ENV="prod"
elif [ $ENV = "prod" ]; then
    export EXCLUDE_ENV="stage"
fi

export EXCLUDE_DIRS='^\.|script|server_src|resources|playground|env|dockerfiles|modules|fluentd|nginx|test_ci_conf|tf_ci_conf|events|'$EXCLUDE_ENV
echo $EXCLUDE_DIRS
DIRS=$(git --no-pager diff origin/master..HEAD --name-only | xargs -I {} dirname {} | egrep -v "$EXCLUDE_DIRS" | uniq)
if [ -z "$DIRS" ]; then
  echo "No directories for plan."
  exit 0
fi

BUILD_URL="https://ap-northeast-1.console.aws.amazon.com/codesuite/codebuild/projects/${USER_CODEBUILD_PROJECT_NAME}/build/${CODEBUILD_BUILD_ID}"
for dir in $DIRS
do
  if [[ "`echo $dir | grep events`" ]] ;then
    echo "events"
    (cd $dir && cd ../ && apex deploy)
    (cd $dir && cd ../ && apex infra init -input=false -no-color)
    (cd $dir && cd ../ && apex infra plan -input=false -no-color | tfnotify --config ${REPOSITORY_ROOT}/${ENV}_tfnotify.yaml plan --message "dir : $dir  user : $USER_AUTHOR console : $BUILD_URL")
  else
    (cd $dir && terragrunt init -input=false -no-color)
    (cd $dir && terragrunt plan -input=false -no-color | tfnotify --config ${REPOSITORY_ROOT}/${ENV}_tfnotify.yaml plan --message "dir : $dir  user : $USER_AUTHOR console : $BUILD_URL")
  fi
done



```

# 今後の展望
- slack上でCI kickから結果確認まで完結させたい
- 差分のみplanといえど、バラバラにコンポーネントそれぞれの通知がきてしまうので、そこを統合したい

# 参考文献
- [Terraform どこで実行していますか？ - mixi developers - Medium](https://medium.com/mixi-developers/terraform-on-aws-codebuild-44dda951fead)
[Node.js 12] delete console.log

# 概要
Node.js 12のどのタイミングからか動きが変わったのでメモです。

# やってたこと

```javascript

> process.versions.node
'10.16.3'
> console.log('hoge')
hoge
undefined
> console.log = () => '無効化!'
[Function]
> console.log('hoge')
'無効化!'
> delete console.log
true
> console.log('hoge')
hoge
undefined
```

`console.log` を `() => {}` で上書きして何もしない関数にする。
（今回の例では `() => '無効化!'` で上書きしたけれども）

従来の `console.log` に戻したい時には `delete console.log` して上書き分を消す、というようなことをしていました。

参考: https://it7c.hatenadiary.org/entry/20140415/1397494773

# Node.js 12.6.0

```javascript
> process.versions.node
'12.6.0'
> console.log('hoge')
hoge
undefined
> console.log = () => '無効化!'
[Function]
> console.log('hoge')
'無効化!'
> delete console.log
true
> console.log('hoge')
Thrown:
TypeError: console.log is not a function
> console.log
undefined
```

deleteしたら全部消えた？

# まとめ
console.logの無効化の良いやり方があったら知りたい。
【Ruby基礎】文字をシャッフル！

##範囲オブジェクト0..16を使って、各要素の２乗を出力する

```ruby
>> (1..16).map{|i| i**2}                                                                 
=> [1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256]
```
mapメソッドは、渡されたブロックを配列や範囲オブジェクトの各要素に対して適用し、その結果を返します。




##('a'..'z').to_a.shuffle[0..7].joinを読み解く

```ruby

>> ('a'..'z').to_a                     # 英小文字を列挙した配列を作る
=> ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o",
"p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
>> ('a'..'z').to_a.shuffle             # シャッフルする
=> ["c", "g", "l", "k", "h", "z", "s", "i", "n", "d", "y", "u", "t", "j", "q",
"b", "r", "o", "f", "e", "w", "v", "m", "a", "x", "p"]
>> ('a'..'z').to_a.shuffle[0..7]       # 配列の冒頭8つの要素を取り出す
=> ["f", "w", "i", "a", "h", "p", "c", "x"]
>> ('a'..'z').to_a.shuffle[0..7].join  # 取り出した要素を結合して１つの文字列にする
=> "mznpybuj"
```




## mapとupcaseとjoinメソッド


map..上に書いた通り
upcase..小文字の文字を大文字に置き換える
join..上の通り


##yeller (大声で叫ぶ) というメソッドを定義

```ruby
def yeller(row)
  row.join.upcase  
end
```


```ruby
>> def yeller(s)
>>   s.map(&:upcase).join
>> end
=> :yeller

>> yeller(['o','l','d'])
=> "OLD"
```

##ランダムな8文字を生成し、文字列として返すメソッド

```ruby
>> def random_subdomain
>> ('a'..'z').to_a.shuffle[0..7].join
>> end
=> :random_subdomain
>> random_subdomain
=> "wcyerpiq"
```


##文字列をシャッフルするメソッド

```ruby
>>def string_shuffle(s)
>> s.split('').shuffle.join
>>end
=> :string_shuffle

>>string_shuffle("foobar")
=> "arobof"
```
打刻をよく忘れてしまう上司のために TeamSpirit の自動打刻アプリを作った話

## 作ったものはこちら

https://github.com/noritakaIzumi/autologin_salesforce

ここではソースコードの詳しい解説はしません．

## 背景

弊社では打刻システムに TeamSpirit (Salesforce 上で動いているアプリ) を使用していますが，朝来て打刻する際は **PC の電源を入れてログインページにアクセスしてから打刻ボタンを押さないとログインできない** というのが現状です．
上司がよく出勤の打刻を忘れていたこともあり，もっと楽に打刻できる方法はないだろうか，と思って今回の打刻アプリを作りました．

## 自動化の方針

TeamSpirit の API が公開されていなかったので，ブラウザでやっていたことを Selenium にやらせる方針で進めました．

### 必要な作業

大きく分けて，次の 2 点です．

- 今まで手動のときにやっていた動きを下記のように一つ一つかみ砕く
- その動きにあたるモジュールの関数を探す

#### 今まで手動のときにやっていた動きを下記のように一つ一つかみ砕く

ログイン方法は次のようになります．

1. ブラウザを開く
2. ログインページにアクセスする
3. ID / PW を入力する
4. ログインボタンを押す
5. 打刻ボタンを押す

#### その動きにあたるモジュールの関数を探す

Selenium のドキュメントを見たり，ググったり，いろいろな方法で探しました．

## 自動化してみて感じたこと

### モジュールの関数を学習できる

Selenium 自体は弊社の自動テストを通して存在を知ったのですが，実際に Selenium を使って何か作ったことはなかったので，いい経験になったと思います．

### 画面で見えていても，ブラウザのドライバには見えていないものがある

ログイン後の打刻ボタンが iframe の中に配置されていて，それがページにアクセスしたばかりの Selenium では見えず，最初に iframe にフォーカスを当てる必要がありました．それに気づくのに 1 日くらい時間がかかった気がします．

- 例

```ruby
frame = driver.find_element(:css, 'iframe[sample-area]')
driver.switch_to.frame(frame)
```

### 人にわかりやすく説明するスキルが間接的に身につく

手動でやっていた作業をかみ砕く上で必ず生じる作業が， **言語化** です．
言語化することで自分のやりたいことが明確になるので，人への説明をわかりやすくできたり，自分の考えを正確に人に伝えることができるようになります．
今回はそのトレーニングとしても良かったと感じています．

### 自動で動いているのを見るのがとても楽しい

独りでに動いているのを見たときの達成感は半端ないですね．

### ハッキングしている気分？

ハッキングは悪いこと，のイメージがありますが，今回 API がない状態でログインページの html や js ファイルを探りながら地道にコードを書いていっただけに，達成感は非常に大きかったです．

## 最後に

みなさんも身の回りの作業，自動化してみませんか？

P.S. 先輩社員がこのアプリを気に入って全社的に紹介したところ，人事部と情報システム室で軽く物議を醸して炎上案件になりました．めでたしめでたし．
Uber-LikeなUIのアプリを作る【考察編】

UIの勉強になるし、UI/UXとはなんなのかを再考するいい機会かと思って二、三日でやってみようかと思います。個人的なメモ程度なので。。。

# Uber-LikeなUIを作ってみたい

![a8a90d86216076645ef97e94dff254fb.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237569/cc7c6127-26e2-f76c-8ae4-2eb09f1b37b5.jpeg)
ようするにこういうUI。
Where to?を入力することで行き先の座標を取ってきて、NearByのタクシーが見えるという仕組み。

1. 下のWorkタブとかHomeタブはつけたい。
2. 左上のハンバーガーメニューをつけたい。（時代遅れかもしれないけど）
3. バックエンドを書かないけど、せめて現在位置とルートを表示したい。(Google MapsのAPIかなぁ）
4. せめてRequestを押すとこくらいまでは一通り。

っていう四つが目標。裏目標はMVCの理解だけど、多分ここめっちゃガバガバなので、ご指導ご鞭撻のほどお願いしたいと思ったりしている。

# Uber UIの分解

さて、UberのUIはどう作られているのだろうと、一旦考える。

## 1枚目
まず一つ目の画面。

![Screen Shot 2019-09-11 at 8.20.45 AM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237569/c29b63cf-d44c-8f74-d10b-f6e4022b58dd.png)

割とわかりやすい。
素人目の予想だとやっぱり UIButtonとUITextFieldの二つ。裏の地図は見た目きにするならGoogle MapsのAPI突っ込んだらいいんだろーなぁって感じ。

ハンバーガーメニューが個人的に謎い部分で、今実機でないから確認できないけど、多分むにゅっと横から出てくるんだろなぁって感じ。４段くらいで個人設定とかなんだろなぁって具合でしかわかんない。

現在位置ぶち込んで、ぷわぁってレーダー風にしてるのがちょっとタチ悪い気がするけどまぁなんとかなるかと思う。

## Where To?
How to "Where To"的な？的な？

![Screen Shot 2019-09-11 at 8.26.47 AM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237569/3d64fe6b-b340-9d22-d2ae-04ad80c1356b.png)

ルート周りは多分APIで対応できるだろうなー。金額周りもバックエンドだろーなー。正直カード型のプッシュアップで出てくるビューだけ。ここでハンバーガーメニューが消えて、矢印のバックになっているのは検索するときに別ビューに飛んでるからなのか？コスパ悪いよなぁ。。。だとするとルートを上に乗っけて、ハンバーガーを矢印に変えてルート取得できた時点で下からプッシュアップするけど、ハンバーガーメニューのView自体は消えてないのかな？うむぅ。。。

コレクションビューとUIButtonのSubviewだろな。

## ETAの画面
ETAってFTAみたいで、政治学系の学生はちょっと震えるんっすよね。。。
![Screen Shot 2019-09-11 at 8.29.24 AM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237569/c25905e2-b8de-1bcc-83f2-ec1176a50c26.png)

なんだかんだ一番バックエンドをやらない前提だと簡単かもしんない。
全体的にETAを動的にするのはめんどいけどフロントしか書かないからしらなぁい。カード型で情報保持してる画面。けどね。これ確かカード開くんすよね。しかも結構うほってなる開きかただった気がするけど、はっきり覚えてない。。。

上は多分UILabelかなんかに画像はっつけてバックグラウンドの色をいじっただけかなと。
下のSubViewは画像やらなんやらが乗っかってるけど、そんなビビることではない気がする。

実装 Part 1 へ
フットプリントと値でグループ化しつつリファレンスをソートするKiCadのBOM出力スクリプト

標準でついてくる`bom_csv_grouped_by_value_with_fp.py`の改造です。
標準はグループ内でコンポーネントを列挙して、列挙した順でリファレンスのテキストを生成してますが、
この列挙順はリファレンス順にはなっていないのでそのあたりをいじります。


```python
#
# Example python script to generate a BOM from a KiCad generic netlist
#
# Example: Sorted and Grouped CSV BOM
#

"""
    @package
    Generate a Tab delimited list (csv file type).
    Components are sorted by ref and grouped by value with same footprint
    Fields are (if exist)
    'Ref', 'Qnty', 'Value', 'Cmp name', 'Footprint', 'Description', 'Vendor'

    Command line:
    python "pathToFile/bom_csv_grouped_by_value_with_fp.py" "%I" "%O.csv"
"""

# Import the KiCad python helper module and the csv formatter
import kicad_netlist_reader
import csv
import sys
import re

def nautural_order_key(s, _split=re.compile(r'(\d+)').split, conv=int):
    it = _split(s)
    it[1::2] = map(conv, it[1::2])
    return it

# Generate an instance of a generic netlist, and load the netlist tree from
# the command line option. If the file doesn't exist, execution will stop
net = kicad_netlist_reader.netlist(sys.argv[1])

# Open a file to write to, if the file cannot be opened output to stdout
# instead
try:
    f = open(sys.argv[2], 'w')
except IOError:
    e = "Can't open output file for writing: " + sys.argv[2]
    print(__file__, ":", e, sys.stderr)
    f = sys.stdout

# Create a new csv writer object to use as the output formatter
out = csv.writer(f, lineterminator='\n', delimiter=',', quotechar='\"', quoting=csv.QUOTE_ALL)

# Output a set of rows for a header providing general information
out.writerow(['Source:', net.getSource()])
out.writerow(['Date:', net.getDate()])
out.writerow(['Tool:', net.getTool()])
out.writerow( ['Generator:', sys.argv[0]] )
out.writerow(['Component Count:', len(net.components)])
out.writerow(['Ref', 'Qnty', 'Value', 'Cmp name', 'Footprint', 'Description', 'Vendor'])

# Get all of the components in groups of matching parts + values
# (see ky_generic_netlist_reader.py)
grouped = net.groupComponents()

# Output all of the component information
for group in grouped:
    refs = []

    # Add the reference of every component in the group and keep a reference
    # to the component so that the other data can be filled in once per group
    for component in group:
        refs.append(component.getRef())
        c = component

    # Fill in the component groups common data
    refs.sort(key = nautural_order_key)
    refText = ", ".join(refs)
    out.writerow([refText, len(group), c.getValue(), c.getPartName(), c.getFootprint(),
        c.getDescription(), c.getField("Vendor")])



```

[Python で natural order](https://qiita.com/methane/items/f615230768ffff21d64c)
AWS 認定クラウドプラクティショナー について

# 概要

試験時間・・・90分
問題数・・・・不明
合格点・・・・700点以上

・日本語公式ページ
https://aws.amazon.com/jp/certification/certified-cloud-practitioner/

試験範囲等を上記リンク先の試験ガイドから抜粋。2019/9/11時点の情報。

# 範囲

1. クラウドの概念 （28％）
2. セキュリティ （24％）
3. テクノロジー （36％）
4. 請求と料金 （12％）

出題割合は３が多い。
以下、個々の範囲を確認。

# クラウドの概念 （28％）

1. AWS クラウドの概念とその価値提案について説明する
2. AWS クラウドエコノミクスの特徴を説明する
3. 多種多様なクラウドアーキテクチャの設計原理を定義する

# セキュリティ （24％）

1. AWS の責任共有モデルについて理解する
2. AWS クラウドのセキュリティとコンプライアンスに関するコンセプトを理解する
3. AWS のアクセス管理機能を特定する
4. セキュリティサポートのリソースを特定する

# テクノロジー （36％）

1. AWS クラウドにおけるデプロイと運用の方法を理解する
2. AWS のグローバルインフラストラクチャについて理解する
3. AWS の主要なサービスを識別する
4. テクノロジーサポートのリソースを特定する

# 請求と料金 （12％）

1. AWS のさまざまな料金モデルを比較対照する
2. AWS 請求と料金に関連した多様なアカウント構造を認識する
3. 請求サポートに利用できるリソースを特定する

# 学習リソース

AWS トレーニング (aws.amazon.com/training)

- AWS Cloud Practitioner Essentials コース https://aws.amazon.com/jp/training/course-descriptions/cloud-practitioner-essentials/
- AWS Technical Essentials 1 コース https://aws.amazon.com/jp/training/course-descriptions/essentials/
- AWS Business Essentials コース https://aws.amazon.com/jp/training/course-descriptions/business-essentials/

AWS ホワイトペーパー (aws.amazon.com/whitepapers) Kindle、.pdf およびその他の資料

- アマゾン ウェブ サービスの概要ホワイトペーパー、2017 年 4 月 https://d0.awsstatic.com/whitepapers/aws-overview.pdf
- クラウド向けのアーキテクチャ: AWS のベストプラクティスホワイトペーパー、2016 年 2 月 https://d0.awsstatic.com/whitepapers/AWS_Cloud_Best_Practices.pdf (リンク切れ？)
- AWS 料金体系の仕組みホワイトペーパー、2016 年 3 月 https://d0.awsstatic.com/whitepapers/aws_pricing_overview.pdf
- クラウド内のウェブアプリケーションの所有 (および非所有) の総コストホワイトペーパー、2012 年 8 月 https://d1.awsstatic.com/whitepapers/aws-tco-web-applications.pdf (リンク切れ？)
- AWS サポートのプラン比較ウェブページ https://aws.amazon.com/jp/premiumsupport/compare-plans/

# 書籍

- AWS認定資格試験テキスト　AWS認定 クラウドプラクティショナー https://www.sbcr.jp/product/4797397406/

# FAQ
- https://aws.amazon.com/jp/certification/faqs/
- https://www.aws.training/Support?src=training-faqs

# 感想

- 模擬試験は受験すべきか？
- 自宅でも受験可能？


以上
SSH で毎回パスフレーズを入れるのが面倒だと思ったときには

SSH で公開鍵認証を使う時に毎回パスフレーズを入れるのは面倒ですよね？
そこで、よい仕組みがあります。
それが
**ssh-agent**
と
**ssh-add**
です。

細かい話は置いておきますが、この二つを組み合わせるとパスフレーズを毎回入れる必要がなくなります。
まず、ssh-agent　を実行します。

```bash
$ ssh-agent
SSH_AUTH_SOCK=/tmp/ssh-YQW9LjOQAQSF/agent.3090; export SSH_AUTH_SOCK;
SSH_AGENT_PID=3091; export SSH_AGENT_PID;
echo Agent pid 3091;
```

なんか出てきましたね、これは、環境変数と PID(ProcessID)です。

難しい話は省きますが、これを Shell に覚えこませればよいので、*eval* を使用します。eval の解説はまた別の機会に。

```bash
$ eval `ssh-agent`
```

これでオーケーです。
次に ssh-add を使用します。

```bash
$ ssh-add ~/.ssh/id_rsa_hoge
```

ここで、SSH のエージェントに id_rsa_hoge という秘密鍵を教えさせます。教える際にはパスフレーズが必要です。

```bash
$ ssh-add ~/.ssh/id_rsa_hoge
Enter passphrase for /home/mishihara/.ssh/id_rsa_hoge: ←ここでパスフレーズの入力をする。 
Identity added: /home/mishihara/.ssh/id_rsa_hoge (/home/mishihara/.ssh/id_rsa_hoge)
```
これで、エージェントに鍵が登録できました。

#ワンライナーで鍵登録をもっと便利に
上記を組み合わせた複合技を私は使っています。

### 2020 年 4 月 11 日変更
```bash:~/.bashrc
alias ssh-add-normal='ssh-add -D > /dev/null 2>&1; kill -0 ${SSH_AGENT_PID} > /dev/null 2>&1; if [ $? -ne 0 ]; then eval `ssh-agent`; fi; ssh-add ~/.ssh/id_rsa'
```

これで、ssh-add を実行したときに ssh-agent が立ち上がっていないときには ssh-agent を立ち上げてから ssh-add を実行しているのです。

#毎回 SSH の鍵を指定してログインしている人にはこの処方箋
毎回 SSH の秘密鍵を

```bash
$ ssh -i ~/.ssh/id_rsa_hoge foo@bar
```
のように設定するのは面倒ですので、この場合には~/.ssh/config　を設定します。

```bash:~/.ssh/config
Host * ← すべてのログインに関して
ForwardX11 yes ←X11の転送をお願いする
ForwardAgent yes ←エージェントを使う(これはまたいつかの機会に)
ServerAliveInterval 120　←(これもまたの機会に)

Host bar ← barというサーバを示すための単なる識別子
Hostname 192.168.XXX.YYY ←サーバの名前または IP アドレス
User foo　←あなたがサーバにログインするときにユーザ名
IdentityFIle ~/.ssh/id_rsa_hoge　←秘密鍵
```

これを設定しておけば、パスフレーズを毎回打つことなくログイン可能になります。
以下のように打てばオーケー

```bash
$ ssh bar
```

簡単に入れるようになりました。

以上!!
railsのフォームヘルパーを使いながらもnameをカスタムする

### 要約
railsのフォームヘルパー(form_for, fields_for)を使いながらも、結果生成されるname属性をカスタムしたい時があったのでメモ
めったにないと思うけど、すでにフォームヘルパー使わずに書いてあるnewテンプレートがあって、それに対するcreateを別のテンプレートから再利用したくて、こちらはフォームヘルパー使いたいとおもった。

### ポイント
- 第一引数にstring渡せばカスタムできる
- urlが正しく行かない場合はurlオプションつける
- stringの最後に`[]`つければ配列つくれる
  →objectに対するFormHelper(ここではa)にfields_for :(has_many名)渡せば自動で`[0]`にしてくれるけど、fやuはobjectに対するものではないので、自力で配列化してやる

```ruby
= form_for 'my_users', url: my_users_path do |f|
  = f.fields_for 'my_users_attributes[]', @new_my_user do |u|
    = u.fields_for :profiles, @new_profile do |a|
      = a.text_field :content
=> name="my_users[my_users_attributes][][profiles_attributes][0][content]"
```

### 参考
https://railsguides.jp/form_helpers.html#フォームヘルパーを使う
Chromeアプリのライトモード（データセーバー）有効による不具合について

## 概要
2019年08月下旬に、不正操作等のエラーが頻発するお問い合わせが増えてきました。
調査により、Android版の Chromeアプリのライトモード（旧:データセーバー）を有効にしていると、不具合が発生することが判明しました。
ここでは、不具合の原因と、その対策を記しています。


## 不具合発生箇所の詳細
- GETリクエスト で 情報の更新処理を行っている
- リクエストが3秒以上かかる場合がある

## ライトモード（データセーバー）について
ライトモードとは、Googleサーバーにて、画像の圧縮やCSSやJavaScriptの圧縮をすることで、データ通信量を少なくすることができるモードです。

![ライトモード_仕組み.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494913/d955c097-68c8-e3f1-6f36-3c33ddf553a0.png)

Chromeアプリの設定から「ライトモード」を有効にした上で、以下条件のいずれかを満たした場合に、ライトモードが有効になります。

### ■有効になる条件
- 2G以下の通信速度でページを表示した
- Googleサーバーがページを表示するのに、5秒以上かかると判断したページを表示した
 
## 不正操作エラーが頻発した理由
ライトモードが有効な場合、端末からの1回のGETリクエストに対して、サーバー側に3回リクエスト（うち、2回がGooleサーバーからのアクセス）が来ていたのが原因でした。

2回目以降のものが連打扱いとなり、不正操作エラーとなっていました。

なお、POSTリクエストの場合は、上記の問題は発生していませんでした。

![ライトモード_GETでの挙動.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/494913/da38aecb-f8ec-941d-e8d2-1d4312273d32.png)

## 対応策について
### 方法1: 処理時間がかる処理をGETリクエストで呼び出している箇所をPOSTリクエストに置き換える
※そもそもGETリクエストは、情報の更新に使うべきではないのでないことが望ましいですが…

### 方法2:リクエストにかかる時間を短くする
1リクエストあたりの時間が短ければ、「ライトモード」が機能しないので、処理時間が短くなるよう改善する

## 効果が見られなかったもの
###HTMLに変換を許可しないメタタグを追加
 変換はされなくなったものの、リクエスト数は変わりませんでした。

```
<meta http-equiv="Cache-Control" content="no-transform">
```

## 今後について
固有の環境に起因した問題かの切り分けが完全にはできていないので、引き続き調査を行っていきます。
また、不具合箇所を逐一直していくような、場当たり的な対応ではない対応方法についても、引き続き調査していきます。
本件について、ご存知な事があればぜひコメントから教えて頂きたいです。
React Hooks（フック）

React 16.8から新機能hook(フック)が導入されました。
まだ、実務では使えてないですが、予習としてまとめを書いていきます。


# ステートフック(useState)
今までstateを使う場合は、クラスコンポーネントにする必要がありました。
しかし、`useState`フックを使うことで関数コンポーネントのままでもstateが使えるようにできます。

## useStateフックの使い方
関数コンポーネント内で以下のように記述すれば、stateを宣言できます。

```js
const [count, setCount] = useState(0);
```

- `useState`の引数にはstateの初期値を指定
- `useState`の返り値は、「現在のstate」と「stateを更新する関数」

## サンプルコード

複数のstateが必要な場合は、以下のように`useState`を複数回呼ぶことになります。
また、オブジェクトや配列でも保持することが可能です。

```jsx
import React, { useState } from 'react';

export default function UseStateSample() {
  const [count, setCount] = useState(0);
  const [user, setUser] = useState({ name: 'Joy', email: 'joy@example.com' });

  const handleUserChange = (e) => {
    const name = e.target.name;
    const value = e.target.value;
    setUser({ ...user, [name]: value });
  }

  return (
    <div>
      <p>クリック数: {count}回</p>
      <button type="button" onClick={() => setCount(count + 1)}>
        click!!
      </button>

      <p>ユーザー</p>
      <ul>
        <li>名前: {user.name}</li>
        <li>メール: {user.email}</li>
      </ul>
      <div>
        名前:
        <input type="text" value={user.name} name="name" onChange={handleUserChange} />
      </div>
      <div>
        メール:
        <input type="email" value={user.email} name="email" onChange={handleUserChange} />
      </div>
    </div>
  );
}

```

# 副作用フック（useEffect）
今まで、クラスコンポーネントを使って以下のような処理を実装していたと思います。

- `componentDidMount` でAPI実行、イベントを購読、
- `componentWillUnmount`でイベント購読解除などの後処理


`useEffect`フックはこういったライフサイクルメソッドを関数コンポーネントで使えるようにするもので、**`componentDidMount`, `componentDidUpdate`, `componentWillUnmount`がまとまったもの**です。
(render後に毎回呼ばれると考えた方がわかりやすいかも。)


## useEffectフックの使い方

以下のようにrender後に実行したい処理を定義するだけです。

```js
  useEffect(() => {
    // API実行やイベント購読・解除などの副作用処理を記述
    console.log('--- useEffect実行 ---');
  });
```

## サンプルコード
```jsx
import React, { useState, useEffect } from 'react';

export default function UseEffectSample(props) {
  const [count, setCount] = useState(0);
  useEffect(() => {
    // API実行やイベント購読などの副作用処理を記述
    console.log('--- useEffect実行 その1 ---');
    console.log(count);
  });

  useEffect(() => {
    // API実行やイベント購読・解除などの副作用処理を記述
    console.log('--- useEffect実行 その２ ---');
    console.log(count);
  });

  return (
    <div>
      <button type="button" onClick={() => setCount(count + 1)}>
        更新
      </button>
      {count}
    </div>
  );
}
```

## componentWillUnmountでやっていた後処理はどうすればよいか？

下のサンプルコードのように、`useEffect`内で、後処理する関数を返せばよい！。
こうすることで、イベント購読・解除のロジックを並べて書くことができます。

```jsx

export default function UseEffectSample(props) {
  const [count, setCount] = useState(0);
  useEffect(() => {
    // API実行やイベント購読などの副作用処理を記述
    console.log('--- useEffect ---');
    return () => {
      // イベント解除など、後処理
      console.log('--- useEffect cleanup ---');
    };
  });

  return (
    <div>
      <button type="button" onClick={() => setCount(count + 1)}>
        更新
      </button>
      {count}
    </div>
  );
}
```

`useEffect`はレンダーされるたびに実行されます。このため、一つ前のレンダー時の処理を次のレンダー時にクリーンアップすることになります。

以上、フックについてのまとめでした。

# 参考サイト
https://reactjs.org/docs/hooks-effect.html

# サンプルコード
https://github.com/nomuyoshi/react-hook-sample/tree/master
slimでiframeをレスポンシブ対応させる方法

最近の勉強で学んだ事を、ノート代わりにまとめていきます。
主に自分の学習の流れを振り返りで残す形なので色々、省いてます。
Webエンジニアの諸先輩方からアドバイスやご指摘を頂けたらありがたいです！

#slimでiframeを記述する
slimでiframeを記述する必要がありやってみました。
htmlではこれだからこんな感じかな？とコードを編集しました。

```html.slim
iframe src="https://www.youtube.com/embed/9No-FiEInLA" frameborder="0" width="100%" height="100%"
```

できた笑
コンパクトに記述できました。

レスポンシブ対応もさせたかったので調整しているの良い記事が合ったので
[iframeをレスポンシブWebデザインに対応する方法
](https://intellectual-curiosity.tokyo/2019/01/08/iframe%E3%82%92%E3%83%AC%E3%82%B9%E3%83%9D%E3%83%B3%E3%82%B7%E3%83%96web%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%81%AB%E5%AF%BE%E5%BF%9C%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/)

この記事通り

```blog.css
.iframe-parent {
   position: relative;
   height: 0;
   overflow: hidden;
   padding-top: 56.25%;
}
.iframe-parent iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}
```

```html.slim
div.iframe-parent
  iframe src="https://www.youtube.com/embed/9No-FiEInLA" frameborder="0" width="100%" height="100%"
```

上手くレスポンシブ対応もできました！
Power BI でも書式指定文字列を設定できるようになりましたよ

Power BI Desktop でカスタム書式を設定する。これまでは一覧の中から選ぶスタイルのみだったが、"書式指定文字列"を設定することもできるようになりましたよって話。もともと Power BI にもその素養はすでにあった。でも、定義する手段がとても限られていたんですよね。で、どう使うかをちょっと考えておく。自分ならこうするかなという指針。

**そのフォーマットは必要？**
なくても問題ないということもあるだろうし、仕込んでも見にくくなるてってこともあるでしょうし。

**必要ならメジャーに対してフォーマットを設定**
書式の変更ではデータ自体が変化することはないから"列"に対して設定してもよいけど、メジャー / Measure に対し設定したほうがよいよねと。使い分け簡単にできるし。

大事だなと思うことは以上のみ。

# 書式指定文字列とは
例えば数値であれば、集計された結果が 正のとき、負のとき、0(ゼロ)のときの書式を明示して定義できるということ
## こんなことできる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193509/6a604f43-dbd5-75f2-c560-87117859a607.png)

## これはできない
あまりいい例を思いつかなかったけど、合計 / Gtrand total 変化つけたいとか。
このタイプはメジャーでやりくり。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193509/13e383fa-8857-5cca-6ef1-6fc79e82d2e7.png)

## 定義はどこに？
Power BI Desktop の モデル ビュー
メジャー もしくは 列 を選択し [プロパティ] ペインの[書式設定]で定義を設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193509/cf63d600-a133-0510-b797-0b697f08c379.png)
カスタム書式の記述についてはよくあるものなので説明しないけれども、すべてが同じように使えるということではないでしょう。

# 思ったこと🙄
これまでは Power BI REST API を使ったり、この先の解放予定の XMLA エンドポイントを使うのかなぁと思ってたので少しやれやれって感じ。
数値に対する書式指定文字列の記述で 4つめセクションは使えないと思うよ。だって、0(ゼロ) と BLANK は別物だし。日付 もしくは 日付時刻に対する指定はそこそこ。

# その他
- [Power BI 勉強会 - connpass](https://powerbi.connpass.com/)
- [Power BI Desktop を使い始めるには](http://qiita.com/PowerBIxyz/items/6c4735cb5b5712e70981)
- [Excel で Power Query を使い始めるには](http://qiita.com/PowerBIxyz/items/52e563037b855a099ca9)
リモートホストの公開していないポートで待ち受けている Git リポジトリに Push する【Git, SSH, トンネリング】

## TL;DR

```sh
export REMOTE_GIT_PORT=3389   # ポート番号は任意
ssh -N -L $REMOTE_GIT_PORT:127.0.0.1:$REMOTE_GIT_POT ssh_user@remote_host &

cd /path/to/repository
git remote set-url origin ssh://git@127.0.0.1:$REMOTE_GIT_PORT/git_user/target_repo.git
git push
```

## 手順

1. リモートサーバに SSH で接続できるようにします。サーバによって異なるので手順は割愛します。
2. リモートサーバの Git が要求するポートを閉じます。今回の場合は 3389 番ポートです。
2. リモートサーバに Git をインストールします。Git の待ち受けポートを 3389 番に設定します。
3. ローカル PC より、ssh 経由でリモートサーバの 3389 ポートにアクセスできるように、以下のコマンドを実行します。（SSH Tunnel する）

    ```sh
    # ローカルホストの 3389 番ポート（左側）にアクセスすると、ssh 経由でリモートホストの
    # 3389 番ポート（右側）に接続される。（アクセスするアプリが何であっても）
    ssh -N -L 3389:127.0.0.1:3389 ssh_user@remote_host &
    ```

5. 以下のコマンドで `git push` 先をローカルホスト経由に変更します。`3389` はリモートの Git の待ち受けポートに、`git_user` は Git のユーザアカウント ID に、`target_repo.git` はコミット先のリポジトリ名にそれぞれご利用の環境に合わせて変更してください。

    ```sh
    git remote set-url origin ssh://git@127.0.0.1:3389/git_user/target_repo.git
    ```

6. あとはいつも通り、`git push` します。初回 Push 時には `git push -u origin master` とする必要があるかもしれません。

    ```sh
    git push
    ```

7. このままではローカルホストの 3389 番へのアクセスおよびローカルホスト経由の別の SSH トンネルが利用できなくなるので、利用後は速やかにバックグラウンド起動している ssh コマンドを終了させましょう。
別端末で ssh をフォアグラウンド起動しておき、Push した後 `Ctrl-C` するのが簡単かもしれません。

## なぜこんなややこしいことをしているのか

「Github 的なイシュートラッカーと Git がどこからでもアクセスできるようにしたいよね！　でもインターネットにリポジトリ＆イシュートラッカー公開したくないので、仲間内だけに SSH 秘密鍵を渡して遠隔地のサークルメンバとリポジトリを共有したいよね！」っていうのが動機です。

素直に Github や bitbucket 使えばいい？　はい、その通りです…😓

## 検証環境

VPSサービス: conoha VPS
リモートOS: CentOS7
Docker: 1.13.1
giteaコンテナ: gitea/gitea

ローカルOS: Windows10 バージョン 1903
Git for Windows: 2.19.1
パスワードとパスフレーズの違いは？-SSH で公開鍵を作る前に-

SSH 公開鍵を作成するときに
**パスフレーズ**
が必要になると思いますが、
**パスワード**
と何が違うのでしょう？

私がその昔学生だった頃に
**パスワードは比較的短いワード**
**パスフレーズは比較的長いフレーズ**
と教わったのですが、今やパスワードとパスフレーズの垣根はなくなってきていると思います。


ただ、パスワードは短いぶんへんちくりんな記号を入れておかないといけないのに比べて
パスワードは長い文字列で構成しているために妙ちくりんな特殊記号などを入れなくてもよい(？)と
私は考えています。

ちなみに、私のパスフレーズは好きな×××の名からいくつかピックアップして繋げてそこから少し記号を入れています。
数えてみたら23文字を毎回入力していますが、文字として覚えるのではなく、好きな×××の名を覚えているだけです。

これと秘密鍵さえ死守すれば比較的安全に過ごせそうです。
今はそれに加えて、多要素認証がよくつかわれるようになっています。
私は多要素認証に [Yubikey](https://www.yubico.com/) を使っています。
それはさておき、とりあえず自分にとって覚えやすく、かつ、長いパスフレーズを作っておきましょう。

以上!!

##追記
パスフレーズにはスペースが入れられるのも特徴らしいです。
参考URL：
https://docs.microsoft.com/ja-jp/security-updates/planningandimplementationguide/19871792

#2020年7月4追記と訂正
知人からダメ出しをもらいました。
**パスフレーズはあくまでも秘密鍵を解除するためのもの**
だそうです。
for...in と　if を設置した構文を略す


```swift
var allMusic = [Music]
for musicItem in musics {
	if !AudioDownloadService.shared.isDownloaded(title: musicItem.title){
         allMusics.append(musicItem)
    }
} 
```

これをもっとシンプルに書く

```swift
let allMusics = musics.filter { !AudioDownloadService.shared.isDownloaded(title: $0.title)}
```
JSCSSの提案

# はじめに

JSCSS(JavaScript CSS)は、FLOCSSやSMACSSのコンセプト[^コンセプト]を取り入れたCSS構成案だ。

[^コンセプト]: 取り入れたコンセプトはプレフィックスをつける命名規則だけ。

# TL; DR

JSCSSでは、JavaScriptの変数名や関数名として使うCSSの名前（ID変数のみ）に`js_*`を使用する。
それ以外のCSSは`l-*`を使用してJavaScriptの変数名や関数名にCSSの名前を使わせないようにする。


# なぜ"l-*"プレフィックスは使いにくいのか

JavaScriptのプログラムが`l-*`プレフィックスの`-`を引き算として解釈し、関数名や変数名が成立しないからだ。

## "l-*"プレフィックスの失敗例

```html:JavaScriptプログラム
<div class="l-header">
  <button id="l-header__button">
    ボタン
  </button>
</div>

<script>
  function l-header__button_click() {
    console.log('click');
  }
  l-header__button.addEventListener(
    'click',
    l-header__button_click
  );
</script>
```

JavaScriptはプレフィックスの`-`を引き算として解釈し、関数`l-header__button_click`とID変数`l-header__button`はエラーとなり成立しない ![sob](https://cdn.qiita.com/emoji/twemoji/unicode/1f62d.png)

## "js_*"プレフィックスの成功例

```html:JavaScriptプログラム
<body>
  <div class="l_header">
    <button id="js_header__button">
      ボタン
    </button>
  </div>

  <script>
    function js_header__button_click() {
      console.log('click');
    }
    js_header__button.addEventListener(
      'click',
      js_header__button_click
    );
  </script>
</body>
```

関数`js_header__button_click`とID変数`js_header__button`は成立し、一貫性がありエラーの起きにくいJavaScriptプログラムになった ![relaxed](https://cdn.qiita.com/emoji/twemoji/unicode/263a-fe0f.png)


# 感想

プレフィックスを付けるのがいいと思ってFLOCSSとSMACSSを使ってみたらJavaScriptプログラムを書くとき使いにくかった。

どうして`l_*`にしないのだろう ![thinking](https://cdn.qiita.com/emoji/twemoji/unicode/1f914.png)


## 感想のつづき

`#id`にスタイルをつけていたとき、同一ページ内に1個だけのときは問題がないが、方針が変わって他の要素にも`#id`と同じスタイルをつけたくなったとき問題が発生する。
スタイルを`.class`に変更すればいいが、`#id`の名前を変更するかしないかの選択に迫られる。
`#id`の名前を変更するとJavaScriptの修正が必要になってしまう。
JavaScriptの修正を避けたいといういうのが人情だ。

`l-*`の方式はJavaScriptの変数名や関数名としてCSSの名前を使用させないCSS構成案と考えられる。
そこにJSCSSの存在意義が生まれる。
JavaScriptの変数名や関数名としてCSSの名前を使用したい。[^JavaScriptからCSS]

[^JavaScriptからCSS]: とはいえ`document.getElementsByClassName`などでJavaScriptからクラスを使用していたらCSSだけの変更ができない。頭にlをつけてlayoutの意味を持たせていたものを`js-`や`js_`に変更するのもよくない。CSSをJavaScriptから完全に切り離すことはできない。JavaScriptもCSSも一人で開発しているときは問題にならないが、多人数で開発してるときは一度決めたCSSの名前を簡単に変更できないし変更すべきでない。

「頭に`js-`を付ける」のではなく、JSCSSでは「頭に`js_`を付ける」。
webarenaでubuntu その46

#概要

webarenaでubuntu18.04やってみた。
postfix3.3 dovecot2.2やってみた。
submissionでsmtp認証やってみた。
outlookでやってみた。

#10-auth.confの修正

```
auth_machanisms = login plain
!include auth_system.conf.ext
```

#10-master.confの修正

```
service auth {
unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
}
}
```

#main.cfの修正

```
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
```

#master.cfの修正

```
submission inet n - n - - smtpd
-o smtpd_sasl_auth_enable = yes
```

#outlookの設定

```
smtpポート　587
pop3ポート　110

送信メールサーバー　このサーバーは認証が必要。
```

以上。