OmniAICreator/Qiita-1.07M huggingface dataset:
AWS Amplifyを使用してReact製のアプリを手軽にホスティング

[公式チュートリアル(React)](https://aws-amplify.github.io/docs/js/start?platform=react)を参考に構築する。

# React Settings

Reactのテンプレートを使用して構築を行う。

```bash
# テンプレートを使用するためにインストール
yarn global add create-react-app
# Reactアプリのテンプレートを使用
create-react-app myapp && cd myapp
# 実行してみる
yarn start
```

# Amplify Settings

先にCLIのインストールを行う。

```bash
yarn global add @aws-amplify/cli
```

次に、必要なパッケージをインストール

```bash
yarn add aws-amplify
# 以下はUIコンポーネント
yarn add aws-amplify-react
```

Amplify CLIを使用してプロジェクトのセットアップを行う
設定値やコマンドについては以下のリンクが参考になりそう。  
<https://aws-amplify.github.io/docs/cli-toolchain/quickstart#environments--teams>

```bash
amplify init
```

※初めて構築する場合、途中でAWSへのログインを求められます。
事前にAWSアカウントの作成を行ってください。

■今回設定した内容

|メッセージ|設定値|
|:--|:--|
|Enter a name for the project|プロジェクト名|
|Enter a name for the environment|dev|
|Choose your default editor|Visual Studio Code|
|Choose the type of app that you're building|javascript|
|What javascript framework are you using|react|
|Source Directory Path|src|
|Distribution Directory Path|build|
|Build Command|npm run-script build|
|Start Command|npm run-script start|
|Do you want to use an AWS profile?|Y, default|

成功すると以下のメッセージが表示される

```none
✔ Successfully created initial AWS cloud resources for deployments.
✔ Initialized provider successfully.
Initialized your environment successfully.

Your project has been successfully initialized and connected to the cloud!
```

上記の作業だけで以下の内容がセットアップされる。

- IAM(ロールが作成される)
- S3(バケットが作成される)
- CloudFormation(テンプレート`team-provider-info.json`が作成される)

## init後の作業

`amplify status`で現在の状態を確認
何も行っていないため、ヘッダのみ表示される。

```bash
$ amplify status

Current Environment: dev

| Category | Resource name | Operation | Provider plugin |
| -------- | ------------- | --------- | --------------- |
```

`amplify add <category-name>`で追加したいバックエンドリソースを指定する。  

■バックエンドリソース一覧

- analytics
- api
- auth
- function
- hosting
- interactions
- notifications
- storage

`hosting`を実行する。

```bash
$ amplify add hosting
# 選択内容は以下。今回は参考用のため、DEV(HTTP)を指定
? Select the environment setup: DEV (S3 only with HTTP)
? hosting bucket name <デフォルト値を使用>
? index doc for the website index.html
? error doc for the website index.html
# 完了後、publish実行
$ amplify publish
```

publish完了後、自動でブラウザが立ち上がる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199056/10d47939-cb5f-fc1d-8e68-a15a8fca2c76.png)

ホスティング後のステータスを確認

```bash
$ amplify status

Current Environment: dev

| Category | Resource name   | Operation | Provider plugin   |
| -------- | --------------- | --------- | ----------------- |
| Hosting  | S3AndCloudFront | No Change | awscloudformation |

Hosting endpoint: <公開先URL>
```

今回はホスティングを試すためにHTTPを指定しましたが、認証機能を追加したりすることを考えるなら必ずHTTPSを指定しましょう！！！
ReactのComponent.setStateによるstateの書き換えは非同期処理である

# ReactのComponent.setStateによるstateの書き換えは非同期処理である
Reactはパフォーマンス最適化のために、setStateが呼ばれたからと言って、実際のstateを即書き換えるわけではありません。
stateの更新はReact内部でよろしくまとめられて非同期で行われます。
例えば、以下のコードはうまく動いてくれません。

``` js
// this.state.hoge = 'fuga'の状態とします。
this.setState({
  hoge:'piyo';
});
console.log(this.state.hoge);//出力されるのはpiyoではなくfuga

```

## 困りそうなケースと対応策

### state変更後、後続の処理でstateの値を参照して処理したい

```js
this.setState({
  hoge:'piyo';
});

fuga();//fugaの中でthis.state.hogeが参照される

```
気を付けていないと意外と書いてしまうかも知れません。

#### 対応策
同期処理が必要な場合はstate経由は不適切なので、素直にfugaの引数として渡しましょう。

### インクリメントなど前のstateに依存する処理

```js
this.setState({
  hoge:this.state.hoge + 1;
});

```
こんな感じの元のstateの値に依存する処理の場合、
連続で実行されると想定通りに動いてくれません。
例えば、`` this.state.hoge=3``の状態で連続して上記の処理を2回実行すると、
一回目は`` hoge: 3 + 1`` と想定通りに動いてくれますが、
二回目までの間にthis.state.hogeが4に切り替わらないので、
二回目も`` hoge: 3 + 1 `` をsetStateの引数として渡してしまいます。
こうなるとReactは「 `` hoge:4``が2回来たけど一回でいいな。」と考えてしまうので
hogeは5になりません。

#### 対応策
functionをsetStateの引数として渡しましょう。

```js
this.setState((state,prop) => {
  return {hoge:state.hoge + 1};
});
```
このようにstateとpropを引数に取ると、stateが切り替わってから関数を実行してくれるので、
前のstateに依存する処理を書いても正しくstateを変更できます。

### stateの変更によってComponentが再描画されてから処理したい場合
setStateの第二引数にコールバック関数を渡しましょう。


## まとめ
* setStateしてもthis.stateはすぐには書き換わらない
* 同期処理をしたい場合は素直に引数で
* インクリメント系処理は関数をsetStateに渡す
* 描画処理まで一通り終わってからの場合はコールバック関数
[ MacDown ] プレビューの見た目を変更する方法

**MacDown** は **Mac** で **Markdown** を書く際に使えるオープンソースのエディタです。

> **MacDown**
> The open source Markdown editor for macOS.
> [Project site](https://macdown.uranusjr.com/)
> [GitHub](https://github.com/MacDownApp/macdown)

無料なうえに使いやすいので非常に重宝してます。ただ、使っていくとだんだんプレビューの見た目をいじりたくなってきました。

MacDownはプレビューのスタイルを設定画面から変更できる機能が備わっていて、自分でスタイルを作ることもできるようになっています。

## スタイル変更

> 環境設定 > レンダリング

<img width="435" alt="環境設定.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130681/a704ad9d-29e1-8508-7f45-49bb5ee8d773.png">

各スタイルはCSSファイルになっており、[**表示**] ボタンを押すと格納ディレクトリが表示されます。自分だけのカスタムスタイルにしたい場合は、CSSファイルを用意してこのディレクトリに入れることで CSSプルダウン にファイル名（拡張子なし）が表示されるようになります。（再度設定画面を開き直す必要あり）プルダウンから選択し [**リロード**] ボタンを押すことで反映されます。

## HTMLコードの確認方法

MacDownには作ったファイルをHTMLやPDFでエクスポートする機能があり、プレビュースタイルを作る上でHTMLでエクスポートしてコード確認をしていました。が！そんな必要はありませんでした。。。

GitHub にある [help.md](https://github.com/MacDownApp/macdown/blob/master/MacDown/Resources/help.md) に↓こんな記述が。

> **Hidden preference**
> You can see the HTML behind a preview by enabling the OS X built-in WebKit developer tools for MacDown in a terminal window:
>
> ```:bash
> defaults write com.uranusjr.macdown WebKitDeveloperExtras -bool true
> ```
> Then select “Inspect Element” in the right-click context menu inside the preview pane.
> 
> This is the exact same inspector you find in Safari if you turn on the developer tools.

要は「Safari で使える **Webインスペクタ** が使えるよ！」って書いてありました。もっと早く知ってれば。。。orz

上記を１回 Terminal で叩けば、 MacDown のプレビュー画面で右クリックすると「**要素の詳細を表示**」というメニューが表示されるようになります。これをクリックすると Webインスペクタ が表示されます。

Webインスペクタ 上でスタイル試しながらCSSを作っていけます。楽チンです。
railsでリダイレクトしない問題を解決

# はじめに
今回初めてform_withを使いrailsアプリを作った。

今まで通りアプリを作成していたが今回、今まで(form_for)で出てこなかった不具合があったので
form_withを使う時は
「こんなことになるのかな？」とこの記事に記録として残し、
近いうちにrails (5.2.3)でまた作るのでその時に同じことが起こるのか確認したい。

## 開発環境
- ruby 2.5.1
- Rails 5.2.3

# 今回起こったこと
今回起こったことは端的に言うとリダイレクトしないということです。

```ruby.rb
def destroy
    binding.pry
    tweet = Tweet.find(params[:id])
    if tweet.user.id == current_user.id
      tweet.destroy
    end
    redirect_to tweets_path, notice:'投稿を削除しました'
end
```
binding.pryを仕込んで処理が間違いなくきてることが確認できているが
その先の
redirect_to tweets_path, notice:'投稿を削除しました'
が動かない

ページをリロードする処理が動く。


色々調べてみるとform_withが悪さをしていそう

## form_withのデフォルトremote: true

調べてみるとform_withにはremote: trueと言うオプションがついている。
### 変更前
```ruby.rb
= form_with(model: @tweet) do |form|
```
表示させるビューはこちら
<img width="814" alt="スクリーンショット 2019-07-11 10.55.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346005/2f3a94e0-3d05-88ce-9ad9-3e9958299bc1.png">

### 変更後
```ruby.rb
= form_with(model: @tweet,data: { remote: false }) do |form|
```
表示させるビューはこちら
<img width="824" alt="スクリーンショット 2019-07-11 10.56.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/346005/53c7cba4-d42c-bb0a-a01b-1cc8191863dd.png">

これで正常に動きました。
エラーが出ないのに動かないのは原因が特定しずらく嫌ですね。

ちょうどturbolinksを削除した時だったので
「turbolinks消すとrails動かなくなるの!?」と混乱していまいましたが
原因がわかってよかったです。

まだform_withを使って全然コードかけてないので
これから知識を深めて行きたいです。

## 最後に
最後まで読んでいただきありがとうございました。
barryvdh/laravel-cors の allowedOriginsPatterns オプション

barryvdh/laravel-cors については、以下記事に詳しい。

https://qiita.com/okashoi/items/026b2d810201555da84d

で、実際に使ったとき、`allowedOriginsPatterns` オプションに
どんな文字列を具体的に渡せばいいかわからなかったので
該当ライブラリのソースコード調べた時のメモ。

- 書式は、`preg_match()` の第１引数に書く形式で。デリミタも必要。
- `allowedOriginsPatterns` は配列なので、複数正規表現パターンの指定が可能。

ちなみに、これを処理しているのは、barryvdh/laravel-cors が依存しているライブラリ
asm89/stack-cors の
`src/Asm89/Stack/CorsService.php` `checkOrigin（）` メソッド。
zip コマンドの -P と -e オプションを同時に指定した時の挙動がバージョンによって異なる

## 発生した事象

とある、ちょっと古めのOSバージョン使ってるサーバから、
新しいサーバにアプリケーションを移管した際に遭遇した事象。

そのプログラムでは、OS側のzipコマンドを呼び出して、
パスワード付きzipファイルを生成する処理をしていたのだが
古いサーバでは正常に動作するのに、
新しいサーバではzipファイルが生成されない現象が発生していた。

そのソースコードでは、以下のようなコマンドをOSに投げていた。

```
zip -j -P "password" -e "awesome.zip" "awesome.csv"
```

アプリケーションからの動作テストではどうにも原因がわからなかったので
サーバに入って該当コマンドを直接叩いてみた。

移行前のサーバ

```
old$ zip -j -P "password" -e "awesome.zip" "awesome.csv" 

  adding: awesome.csv (stored 0%)
```

移行後のサーバ

```
new$ zip -j -P "password" -e "awesome.zip" "awesome.csv" 
Enter password: 
Verify password: 
  adding: awesome.csv (stored 0%)
```

移行後のサーバでは、-Pオプションを指定しているにもかかわらず
プロンプトでパスワード入力を求められた。

## zipコマンドのオプションについて調査

プログラム中では、zipの実行オプションで、e と P を渡しているが、これらの意味は以下の通り：

       -e     Encrypt the contents of the zip archive using a password which is entered on the terminal in response to a prompt (this
          will not be echoed; if standard error is not a tty, zip will exit with an error).  The password prompt is  repeated  to
          save the user from typing errors.

       -P password
          use  password  to  encrypt zipfile entries (if any).  THIS IS INSECURE!  Many multi-user operating systems provide ways
          for any user to see the current command line of any other user; even on stand-alone systems there is always the  threat
          of  over-the-shoulder peeking.  Storing the plaintext password as part of a command line in an automated script is even
          worse.  Whenever possible, use the non-echoing, interactive prompt to enter passwords.  (And where  security  is    truly
          important,  use  strong  encryption  such  as Pretty Good Privacy instead of the relatively weak encryption provided by
          standard zipfile utilities.)

-Pは オプション引数からパスワードを渡すもの。
一方 -e は、対話式にパスワードを与えるもの。
なので、当該のコマンドでは、共存できないオプション指定がバッティングしていたことがわかった。

で、この２つのオプションを同時に指定した場合に、どちらが優先されるかが
zipのバージョンによって異なっているのでは、と推測。

移管前、移管後それぞれのzipのバージョンは以下であった。

```
old$ zip -?
Copyright (C) 1990-2005 Info-ZIP
Type 'zip "-L"' for software license.
Zip 2.31 (March 8th 2005). Usage:
```

```
new$ zip -?
Copyright (c) 1990-2008 Info-ZIP - Type 'zip "-L"' for software license.
Zip 3.0 (July 5th 2008). Usage:
```

やはりバージョンが違った。

## 解決策

-e オプションを削除してコマンドを実行。
移管前、移管後どちらのサーバでもパスワードを聞かれることなく、パスワード付きZipファイルを生成できた。

```
old$ zip -j -P "password" "awesome.zip" "awesome.csv" 
  adding: awesome.csv (stored 0%)
```

```
new$ zip -j -P "password" "awesome.zip" "awesome.csv" 
  adding: awesome.csv (stored 0%)
```

それにしても、もとのアプリケーション実装者は、どのような意図で -e、-Pの両オプションを指定したのだろうか…
今となっては実装者がいないため、真相はわからなかった。
OracleDBにおける日本語の文字列格納用カラムのデータ型について

OracleDB（11g）を利用することになり、日本語文字列を格納するカラムのデータ型をどうすればよいか悩んで調べたので、自身の備忘録として。


## データ型の選択肢

例えば20文字の文字列を格納するカラムとした場合

- VARCHAR2(20 CHAR)
- NVARCHAR2(20)

※ VARCHAR型の CHAR は、BYTE数カウントではなく文字数カウントであるという指定。


## 検討要素

### 1. Charset

|データ型|Charset|
|:------|:------|
|VARCHAR2|DatabaseのCharset依存|
|NVARCHAR2|Unicodeのみ(Oracleを含む大抵のDBではUTF-16でエンコードする)|

システム要件として、使用するキャラセットに制限がある場合はそれに従うのが吉。


### 2. サロゲートペア文字

|データ型|サロゲートペア1文字の扱い|
|:------|:------|
|VARCHAR2|VARCHAR(1)に格納可能|
|NVARCHAR2|2文字として扱われるため、NVARCHAR(1)には格納できない|

人名など（他は思いつかないが）で、一般的ではない漢字であってもそのまま扱わないといけない場合は、VARCHAR2にしておくほうが吉。
一般的な漢字のみを格納する前提であればどちらでも。


### 3. バイト数

|データ型|1文字のバイト数の扱い|
|:------|:------|
|VARCHAR2|1～4バイト（一般的な全角文字は3バイト）|
|NVARCHAR2|2または4バイト（一般的な全角文字は2バイト）|

全角文字が多く格納される場合は、NVARCHAR2の方がバイト数が少なくなる。
半角文字の数値やアルファベットが多く格納される場合は、VARCHAR2の方がバイト数が少なくなる。
DB容量のシビアな問題があれば考慮すべきだが、そこまでギリギリの環境自体がそもそも良くない。


## 参考URL
- [Oracle DatabaseでのUnicode設計](https://qiita.com/kawasima/items/e958adb75cfd64be45fd)
デスクトップで変えた設定をCUIでやりたい!(gnome限定)

業務上しょっちゅう環境立て直すので最低限の環境構築はスクリプト化してますが、
GUIで変えた設定を落とし込むのに手間取ったのでメモ。

例：ブランクスクリーンを無効にしたい

* ターミナルでdconfの挙動を確認する

```
dconf watch /
```
* その間に設定を変更すると変更した項目と値が表示される

```
/org/gnome/desktop/session/idle-delay
  uint32 0
```
* gnomeのdconfインタフェースコマンド(gsettings)で書き換えられる

!項目(正確にはスキーマとパス)の表現方法が違うので注意!

```
gsettings set org.gnome.desktop.session idle-delay 0
```
(別にdconfで変えても良いのですが、挙動を理解してないのでgnome関連の設定ならgsettingsの方が良いかなって…)


#補足
dconfはWindowsのレジストリエディタみたいな機構のLinux版。
各ソフトウェアが****.confとかを置きまくる傾向を止めたかったらしい。
所詮オープンソースなので全てのソフトウェアが採用している訳ではない。
(と言うかgnome以外そんなに無い)

dconfとgsettingsの関係はこのあたりが分かりやすいです。
[GSettings と dconf の関係 | 穀風](https://kokufu.blogspot.com/2018/11/gsettings-dconf.html)
「Raspbian Buster with desktop and recommended software」の2019-06-20版でインストールウィザードのUpdate Softwareがエラーで停止する問題

## 2019/7/16更新
7/13にリリースされた「Raspbian Buster 2019-07-10」のイメージでは以下の症状は発生しません。これから導入されるかたは2019-07-10版で導入されることをお勧めします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/94bbbe84-252f-4866-b2d9-67bc6616a301.png)

参考: [Raspbian Buster 2019-07-10 Release-note 翻訳](https://qiita.com/utaani/items/2d4e641eba3d2e46d9f3)


## 症状
「Raspbian Buster with desktop and recommended software」2019-06-20のイメージをダウンロードして、microSDに書き込み起動、自動起動されるpiwizから初期導入作業を実施すると、Update Softwareの項目で

```
Error checking for updates.
E:Repository 'http://raspbian.raspberrypi.org/raspbian
buster InRelease' changed its 'Suite' value from 'testing' to
'stable'
```
と表示され、Update Softwareが実施できない。 (2019/7/12現在発生中)
![error1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/642141a1-a563-6e9f-b0ef-e8fb7f068e97.png)

## 原因
2019-06-20に含まれるリポジトリリストのSuiteがtestingだが、7/12よりInReleaseのSuiteがStableに更新された。piwizのUpdate SoftwareがSuiteの変更に対応できていない。

## 暫定対策
piwizのエラー画面で「OK」とし、Update Softwareまで戻る。そのまま表示しておいて、Terminalを起動して、コマンドラインから ```sudo apt update``` を実行する。
```Do you want to accept these changes and contiune updating from this repository?[y/N] ```が表示されるのでyと入力する。 ``` xxx packages can be upgraded. Run 'apt list --upgradable' to see them.``` が表示されたら、あらためてpiwizのUpdate Softwareを実行する。
![fix1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/bba17b6a-023a-c755-d256-3c01271225eb.png)
VSCodeで桜のテーマ



### 設定
```settings.json

    "workbench.colorCustomizations": {
        "[Visual Studio Light]": {
            // 満ち桜テーマ
            // Visual Studio Light でも可
            //タイトルバー
            "titleBar.activeBackground": "#ffe5e5", // 背景色
            "titleBar.inactiveBackground": "#fff6f6", // 背景色
            // アクティビティバー
            "activityBar.foreground": "#ff0000a0", // 選択アイコンの色
            "activityBar.inactiveForeground": "#ff00002e", // アイコンの色
            "activityBar.background": "#ffe9e9", // 背景色
            "activityBarBadge.background": "#ff9292", // 通知バッジの背景色
            // サイドバー
            "sideBar.background": "#fff5f5", // 背景色
            // サイドバーのセクションヘッダー
            "sideBarSectionHeader.background": "#ff000011", // 背景色
            // リスト
            "list.hoverBackground": "#ff000010", // ホバー中の背景色
            "list.focusBackground": "#ff000034", // 選択中の項目の背景色
            "list.activeSelectionBackground": "#ff000066", // 選択中の項目の背景色
            "list.inactiveSelectionBackground": "#ff000034", // 選択中の項目の背景色(リスト非アクティブ)
            // タブグループヘッダー
            "editorGroupHeader.tabsBackground": "#ff000011", // 背景色
            // タブ
            "tab.activeBackground": "#ffffffa8", // アクティブ背景色
            "tab.inactiveBackground": "#ff000013", // 非アクティブ背景色
            // エディタ
            "editor.background": "#fffafa",
            // スクロールバー
            "scrollbarSlider.hoverBackground": "#ff000055", // ホバー中の背景色
            "scrollbarSlider.activeBackground": "#ff000088", // アクティブ背景色
            "scrollbarSlider.background": "#ff000044", // 背景色
            // ステータスバー
            "statusBar.background": "#ff6767", // 背景色
            "statusBar.noFolderBackground": "#ff6767", // フォルダ開いてない状態での背景色
            // ボタン
            "button.background": "#ff000088", // 背景色
        },
    },

```


### 参考
- https://qiita.com/Azoson/items/9e06099ea738cf450c73
公開鍵を使ったSSH接続のやり方

## 経緯
Ansibleを実行するためには、構築対象のマシンへ公開鍵でSSH接続する必要があるためと、 ssh-keygenとssh-copy-idコマンドを忘れそうだから備忘録を兼ねて。

## 鍵を作ろう
鍵はホスト側で作ります。
※お試しなんでkeyは空ですが、keyは設定するようにしましょう

```Console:command
$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):  #何も入れずにエンター
Enter passphrase (empty for no passphrase):               #何も入れずにエンター
Enter same passphrase again:                              #何も入れずにエンター
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx root@localhost.localdomain
The key's randomart image is:
+---[RSA 2048]----
+----[SHA256]-----+
```
## ssh-copy-idを使って鍵を送り込もう
これもホスト側でやります

```none:command
$ ssh-copy-id ${USER}@${ssh_target}
~~~省略~~~
Are you sure you want to continue connecting (yes/no)?     #yesを入力してエンター
~~~省略~~~
${USER}@${ssh_target}'s password:                          #接続先のパスワードを入力してエンター
```
これでパスワードなしでSSH接続ができるようになりました。
ScoopでインストールしたgitbashをVSCodeのデフォルトのターミナルにしようとしてハマった

Git Bashって便利ですね。文字コードもフォントも選び放題。

scoop\shims\git-bash.exe
だと別窓で開いちゃうのでだめ。

scoop\apps\git\current\bin\bash.exe
だと上手くいくけどこれでいいのか心配。
VCCWでWordPress環境構築

## 前提
Vagrant, VirtualBoxはインストール済みであること
VirtualBox...PC内に仮想的なPCを作成し、元のOSとは別のOSを起動させることができるソフトのこと。

---
### VCCWとは
- V
Vagrant...
普通、VirtualBoxで仮想マシンを構築する際、様々な設定を手動で行わなけばならないが、Vagrantを使用すると設定ファイルに基づいて自動的に環境を構築してくれる。簡略化ツール。


- C
Chef...
サーバー管理ツール。ファイルに記述した設定内容に応じて自動的にユーザーの作成やパッケージのインストール、設定ファイルの編集などを行うツール。


- C
CentOS...Linuxディストリビューションのひとつ。


- W
WordPress...オープンソースのブログ投稿管理システム。CMS。

VCCWとは、これらの頭文字を取ったものでVirtualBox上で動く、WordPressの開発環境のこと。


### vagrant-hostupdaterのインストール
Q.何それ？
A.virtual mchineの起動/停止をおこなった時に、ホストOSの/etc/hostsへゲストOSの情報を追加/削除してくれる。仮想マシンにアクセスするときにホスト名から接続できるようになります。
vagrantfileに特別なオプションを設定する必要がないので便利。(仮想マシンを作成するたびに、/etc/hosts を開いて、ドメインや ip アドレスを設定する手間が省けます。)
ただし、ゲストOSのhosts書き換えには未対応。

```
$ vagrant plugin install vagrant-hostsupdater
```


### Vagrant Boxのダウンロード
```
$ vagrant box add vccw-team/xenial64
```
少し時間がかかります。


### VCCWのダウンロード
[VCCW公式サイト](http://vccw.cc/)

必要なファイルが「vccw」というフォルダに入っているので適当な名前に変更してvagrantのディレクトリ下に置きます。


### Vagrantの起動
cdコマンドで先ほどのディレクトリ内に移動してvagrantを起動します。
途中、パスワードを聞かれるので、自分のMacのパスワードを入力します。

これでwordpress環境が構築されました。
アクセスしてみましょう。どちらかでアクセスできるはずです。
http://vccw.test
http://192.168.33.10


### WordPress環境に触れる
WordPressの管理画面にログインできます。
http://vccw.test/wp-login.php
http://192.168.33.10/wp-login.php

デフォルトでは以下の通りです。
Username:admin
Password:admin


## 参考サイト
[WordPressをVagrant環境にらくらくインストールする。 - VCCW - Qiita](https://qiita.com/naru0504/items/58011181f2c271808c7f)
[WordPressをローカル環境で使う方法解説【令和元年版・初心者向け】](https://miyukimedaka.com/2019/05/10/blog-0033-wordpress-local/)
Spring Boot > Spring メモ



[Spring初学者が最初に知るべき責務とレイヤー](https://www.yo1000.com/spring-responsibilities/)


以下を抑えておけばよさそう

## Controller

@RestController()
@Controller()


## Service

@Service()



## Repository

@Repository()



## AOP

AOPはアスペクト指向プログラミングの略称で、横断的関心事(共通的なロギング、例外ハンドリング、メッセージの加工等)を一元的に記述できるようにします。
AOPを使用することで、サービスやリポジトリーから、煩雑で共通的な手続きを追い出すことができ、各レイヤーの責務に集中して開発できるようになります。

@Aspect()
@ControllerAdvice()
@RestControllerAdvice()



## Configuration

コンフィグレーションは、DIコンテナに登録されるBeanオブジェクトを構成、定義します。

@Configuration()
AWSクラウドプラクティショナー認定

# クラウドプラクティショナーとは

AWS 認定クラウドプラクティショナー試験は、AWS クラウドの知識とスキルを身に付け、全体的な理解を効果的に説明できる個人が対象です。
その他の AWS 認定で扱われる特定の技術的役割からは独立しています。

数ある認定試験の中でも一番基礎となる試験です。AWSとは何か、クラウドとは何かといった知識を問われるものになるので、どちらかと言うと非エンジニアではあるけれどAWSの知識を深めたい人向けの試験かなと思います。

試験概要としては、以下の通り。
**試験形式：複数の選択肢と複数の答えがある問題**
**試験時間：90分**
**受験料：11,000円（税別）**
**合格ライン：700点以上**
 問題数について特に明記はありませんが、私が受験した際は65問ありました。

全て試験が終了するとその場で画面上に合否の表示が出てきます。
スコアやその他詳細については後日メールで結果が送られてきます。

# 試験に向けての学習方法

今回の学習期間は、1ヶ月半程度でした。
ちなみに私はエンジニアではありません。が、エンジニアサポート的な立ち位置で業務をしている中でインフラの基礎については日頃から触れているかな、、と言うレベルです。
AWSに関してもサービス内容はもちろんのこと、マネジメントコンソールへログインして、、と言うところはちょこちょこ触れてはいます。

## 試験対策本を読む！
一番効率的で分かりやすかったのが以下の対策本を読むことでした。

[AWS認定資格試験テキスト AWS認定 クラウドプラクティショナー ](https://www.amazon.co.jp/AWS%E8%AA%8D%E5%AE%9A%E8%B3%87%E6%A0%BC%E8%A9%A6%E9%A8%93%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88-AWS%E8%AA%8D%E5%AE%9A-%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89%E3%83%97%E3%83%A9%E3%82%AF%E3%83%86%E3%82%A3%E3%82%B7%E3%83%A7%E3%83%8A%E3%83%BC-%E5%B1%B1%E4%B8%8B-%E5%85%89%E6%B4%8B/dp/4797397403/ref=asc_df_4797397403/?tag=jpgo-22&linkCode=df0&hvadid=295691444786&hvpos=1o1&hvnetw=g&hvrand=1796575075725705771&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009343&hvtargid=pla-718362586207&psc=1&th=1&psc=1)

クラウドプラクティショナーの対策本は今の所この一冊しか出ていないようです。
Amazonでも評価は良かったですよ。

## AWSトレーニングクラスを受講する

所要時間6時間
AWS Cloud Practitioner Essentials (Second Edition) (Japanese)

一通り受けました！日本語ではありますが、日本語も若干分かりづらくとにかく長いので、、頭に入りづらいです。
最初はこのトレーニングクラスの受講から勉強を始めましたが、気が遠くなってきてしまい、試験対策本の購入を決意しましたw

##模擬試験

試験前には必ずこちらの模擬試験は受けるべき！
実際の試験より問題数も少なく時間も短いです。問題もこちらの方が簡単なように感じました。
ただ、出題形式を事前に確認できるのでおすすめです。

##オンラインセミナー
本認定を受けている方のブログで紹介されていた以下を閲覧しました。
試験の概要はもちろんのこと出題範囲や試験準備について紹介されています。
最後には例題がいくつか紹介されているので、その部分もとても参考になりました。

[[AWS Black Belt Online Seminar] AWS 認定クラウドプラクティショナー取得に向けて 資料及び QA 公開](https://aws.amazon.com/jp/blogs/news/webinar-bb-practitioner-2018/)

#試験の予約

AWSの試験と言えば目の前に監視カメラがついていて、常に監視され少しうつむいて考え事をしているだけでも英語で注意される、と聞いたりしていたのでちょっと怯えていました。

試験会場としてはPSIとピアソンVUEの二通りあるようですが、今回はピアソンVUEの横浜で試験を受けてきました。

試験会場に着くと同意書と注意事項を読み、カメラで証明写真の撮影をします。
その後はロッカーに荷物を預け、試験会場へ入室して試験を開始します。

今回予約していた時間より30分ほど早く会場に着いてしまいましたが、予約時間前に試験を受けることは可能なので準備が出来次第受けてもらって構わないとの事。でした。

試験前にメモに使用するため、ホワイトボードとペンを渡されます。
指定された席に着き試験を開始します。

話に聞いていた小型カメラは無く、試験中に何か注意されることもなかったので落ち着いて試験を受けることができました。

#おわりに

本試験は模擬試験に比べて難易度も高く、受かるかどうか微妙なラインだな、、と思いながら受験していましたが無事一発合格できて本当に安心しました。
試験時間は90分と長いので、しっかり見直しし、不安な問題はよく考えて回答するといいかと思います。
わたしは割とギリギリまで見直しを行なっていましたがそれが功を奏したのかもしれません。

今回クラウドプラクティショナー試験の勉強をしたことでAWSについてより理解が深まりました。これからAWSについて学びたい、という人にはオススメの試験です。
Vision.frameworkで画像解析の入門

# 本稿について
Vision.frameworkを通じて機械学習について触れる、くらいの簡単な内容になっているわ。
簡単にどんなことができるのかな？くらいのレベルなのでまったくのど素人だぜ！って人向けよ。
多分ググっていくらでも出てくる情報なので過度な期待はしちゃいやよ。

# Vision.frameworkとは
画像を解析したりしてくれる便利なフレームワークだわ。
CoreML（機械学習）のお手軽インターフェースって感じかしら。。
もっと深入りしたい人はCoreMLの学習が必要そうね。

# 何ができるのかしら？
Apple のリファレンス（https://developer.apple.com/documentation/vision?language=objc）
によると、

| 名前 | 内容 |
|:--|:--|
| Object Tracking| カメラでオブジェクトをトラッキングする |
| Rectangle Detection| 長方形検出 |
| Face Detection| 顔検出 |
| Barcode Detection| バーコード検出 |
| Human and Animal Detection| 人間と動物の検出 |
| Text Recognition | テキスト認識 |
| Text Detection| テキスト検出 |

この辺がフレームワークに組み込まれている機械学習モデルを使ってできるようね。
もちろん、モデルをつくって独自に行うこともできるわ！

ちなみに
https://developer.apple.com/machine-learning/models/
こちらからモデルをダウンロードすることも可能となっているわ。
ぜひ使ってみてね☆

# 実装
今回は参考までに、顔検出のVNDetectFaceLandmarksのソースコードを貼っておくわね。
最低限な感じになっているから、この先にどんな実装をするかはあなた次第だわ。

```swift
@IBAction func leftEyebrow() {
    let request = VNDetectFaceLandmarksRequest { (request, error) in
        for observation in request.results as! [VNFaceObservation] {
            let points = observation.landmarks?.leftEyebrow?.pointsInImage(imageSize: self.originalImageView.frame.size)
            
            // points（CGPointの配列）で、imageViewに描画していくなどの処理を行う
        }
    }
    if let cgImage = self.originalImageView.image?.cgImage {
        let handler = VNImageRequestHandler(cgImage: cgImage, options: [:])
        try? handler.perform([request])
    }
}
```

超簡単に説明すると、適当なボタンを用意してタップすると、
1. VNRequestのサブクラスのオブジェクトを作る（ここではVNDetectFaceLandmarksRequest）
2. request発行
3. 返却されたCGpointの配列を取得
4. 描画など何かしらの処理
上記が行われます。

このサンプルではleftEyebrow（向かって左眉）の座標を取得することができます。

今回はself.originalImageViewというUIImageViewのプロパティをを使っていますが、
応用していろいろなことをやってみると面白いですね。

# 今後は...
今回はVNDetectFaceLandmarksRequestでしたが、上述の通りVNTrackObjectRequestなど色々な解析方法があります。
だいたい同じような感じでいけると思いますので、。ぜひ試してみてください。

個人的には早く日本語のテキストの検出ができたら色々なところで使えそうだなーって思っています。
お楽しみに。
日本語が使えない

タグのところに入れたワードはタイトルに入れなくてもいいかなって思ってますが、どうなんでしょう。

windows7のPowerShellを5.1にしたあとから、UTF-8で日本語が使えなくなった気がするけど、定かではありません。

これは確実ですが、コードページ932(Shift-JIS)でも日本語が使えなくなったのでレジストリを修正。
![レジストリ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107052/d4629327-a014-fbe6-4818-7b1442d2ece4.png)

932の値のところにMSゴシック入ってるのに選べないから、0のところを上書きした。:expressionless:
※Wow6432Nodeの方は勝手に書き換わる。どのタイミングかはわからないけど

↓ちなみに変更前
![レジストリ変更前.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107052/992d42f7-fd60-c832-0655-eadf1577164d.png)

それと、レジストリに65001を追加しても効果なし。
そもそも、無理な気がしたので、とりあえず、あきらめて、git bashを使おうとしたがそこでもハマった。

※windows10だとこんなことなかった気がするので、PC買い替えた方がいい気がする。
グレースケールをRGB変換してGIST特徴量を抽出(Python)

# グレースケール画像をRGB変換させて、特徴量の抽出をしたい
機械学習に興味を持ち、画像分類に手を出したのがはじまり。GIST特徴量をpythonで取得したいけど、画像データがグレースケールしかない！って場合におススメ。
### 動作確認環境
- Google Colaboratory(Python 3)

>https://colab.research.google.com/notebooks/welcome.ipynb?hl=ja

## グレースケール画像をRGB変換する
### OpenCVを入れる
```python
!pip install opencv-python
```
### 必要なものをインポート
※筆者の場合は、numpyに格納しています

```python
import cv2
import PIL
import numpy as np
```
### グレースケール画像をRGB変換
```python
#グレースケール画像を読み込む
grayImg = np.array(PIL.Image.open('画像のパス'))
print(grayImg.shape) # (height, width)
#RGB変換
rgbImg = cv2.cvtColor(grayImg,cv2.COLOR_GRAY2RGB)
print(rgbImg.shape) # (height, width, 3)
```
cvtColorはRGB変換を含め多くに対応しているらしいです。
>http://imagingsolution.blog.fc2.com/blog-entry-242.html

リファレンスはこちら
>http://opencv.jp/opencv-2svn/c/miscellaneous_image_transformations.html#cvtcolor

## GIST特徴量の抽出
GISTについて詳しい説明はこちら
>http://lang.sist.chukyo-u.ac.jp/Classes/ComputerVision/KeypointDescription.html#GIST%E8%A8%98%E8%BF%B0%E5%AD%90

### lear-gist-pythonのダウンロード
※pipではインストールできません。

```python
!git clone https://github.com/tuttieee/lear-gist-python.git
```
### 作業ディレクトリの移動
```python
cd  ./lear-gist-python/
```
### libfftw3-devのダウンロード
```python
!sudo apt-get install libfftw3-dev
```
### GISTのダウンロード
```python
! ./download-lear.sh
```
### GISTのセットアップ
```python
!python setup.py build_ext
!python setup.py install
```
### GIST特徴量の抽出
使い方はGitHubを見てください。
>https://github.com/tuttieee/lear-gist-python

```python
feature = gist.extract(rgbImg, 16)
```
### GIST特徴量のメリット
- 特徴量が固定長で出力される
- グリッドにする際のセル数の指定が容易（APIがある）

## さいごに
グレースケールをRGB変換する機会はあまりないと思います。筆者の場合は、マルウェア解析の精度比較のため、画像化した際に使用しました。
>https://www.kaggle.com/c/malware-classification/

今後、マルウェアの分類について時間があったらどこかで書き残しておきます。
Spring Boot > Actuator




Actuatorでアプリケーションをモニタリング



build.gradle.kt > dependenciesに以下を追加

```kotlin
dependencies {
...
  implementation('org.springframework.boot:spring-boot-starter-actuator')
...
}
```


これで実行するだけでモニタリング可能になる

* http://localhost:8080/actuator/health
* http://localhost:8080/actuator/info



[endpoints 一覧](https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#production-ready-endpoints)



actuatorの設定を変更するにはapplication.ymlに追記する

以下のようにbaseのPathを変更するには
http://localhost:8080/actuator/health
　↓
http://localhost:8080/other/health


management > endpoints > webに追加する。


```kotlin:src/main/resources/application.yml
management:
  endpoints:
    web:
      base-path: /other # → Default is /actuator
```



### エンドポイントの公開

デフォルトで有効になっているエンドポイントは以下の２つ

* `/health`
* `/info`

management > endpoints > exposure > include に追加する。

`include: "*"`

または
include: エンドポイント名, エンドポイント名

ex. `include: beans, env`



以下のような感じ

```kotlin:src/main/resources/application.yml
spring:
  application:
    name: Message API
server:
  port: 8080
management:
  endpoints:
    web:
      exposure:
        include: health, info, beans, env, scheduledtasks
      base-path: /other # → Default is /actuator
```



# 参考


[Spring Boot Actuator Web API Documentation](https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/actuator-api//html/)



[ことりんと一緒 Springもね - 5. Actuator - Qiita](https://qiita.com/shinyay/items/4e1e36f2f975e37dc0ab)
URLのレスポンス値の監視

#改善要望
単純なcurlで取得するスクリプトだったが、リクエストのヘッダーにトークンを追加したい要望があった。
別スクリプトにしようかと思ったら要望ごと分けるときりがないので既存スクリプトを改善することに。

#http_get.sh

```bash
#!/bin/bash

url="$1"
token="$2"

if [ -n "$token" ]; then
    fmt="curl -sSL ${url} -H \"Content-Type:application/json\" -H \"access-token:${token}\""
    ret=$($fmt)
else
    ret=`curl -sSL $url`
fi

echo $ret


```

#アイテム

```
http_get.sh["https://www.hoge.com/api/func1","tokenXXXXXXXXXXXXXXXX"]
```

#メモ
bashはたまに書くので文字連結して実行する方法が分からず時間がかかった。

#参照
https://teratail.com/questions/1731
https://unix.stackexchange.com/questions/30903/how-to-escape-quotes-in-shell
JFreeChart-平均と標準偏差のチャート-DefaultStatisticalCategoryDataset


目次 ⇒ [JFreeChartサンプル](https://qiita.com/artery/items/3e9c63e5c14a9e965c97)

```java
package jp.avaj.lib.chart;

import org.jfree.chart.ChartFrame;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.renderer.category.StatisticalBarRenderer;
import org.jfree.data.statistics.DefaultStatisticalCategoryDataset;

/**
■ JFreeChart-平均と標準偏差のチャート-DefaultStatisticalCategoryDataset
・レンダラにはStatisticalBarRendererを使用する

 */
public class Chart12_01 {
  // 目次-平均と標準偏差のチャート-DefaultStatisticalCategoryDataset
  A_Chart12 a_Chart12;
  // 目次-Artery-JFreeChart用のライブラリ
  A_Chart00 a_LibChartSampeContents;

  public static void main(String[] args) {
    // 表示データの作成
	  DefaultStatisticalCategoryDataset dataSet = new DefaultStatisticalCategoryDataset();
    {
      // 日ごとの売り上げの平均
      final double[][] means =  {
        {50,30,34,33,60}, // 1-3
        {55,40,45,37,60}  // 4-6
      };
      // 日ごとの売り上げの標準偏差
      final double[][] devis = {
        {5,2,4,3,5}, // 1-3
        {4,3,3,5,6}, // 4-6
      };
      // 商品名
      final String[] catKeys = {"A","B","C","D","E"};
      // 期間
      String[] serKeys = new String[]{"1月～3月","4月～6月"};
      // データを設定する
      for (int i=0; i<serKeys.length; i++) {
        for (int j=0; j<catKeys.length; j++) {
          dataSet.add(means[i][j],devis[i][j], serKeys[i],catKeys[j]);
        }
      }
    }
    // 軸の設定
    CategoryAxis xAxis = new CategoryAxis("商品");
    NumberAxis yAxis = new NumberAxis("売上");
    // レンダラの設定
    StatisticalBarRenderer renderer = new StatisticalBarRenderer();
    // Plotの作成
    CategoryPlot plot = new CategoryPlot(dataSet,xAxis,yAxis,renderer);
    //
    JFreeChart jfreeChart = new JFreeChart("売上の平均と標準偏差",(Plot)plot);
    ChartFrame cFrame = new ChartFrame("売上の平均と標準偏差",(JFreeChart)jfreeChart);
    cFrame.pack();
    cFrame.setVisible(true);
  }
}

```

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278568/c737da14-6803-7dec-53dd-133a16c7413a.png)
ubuntu16.04にdockerとdocker-composeインストール（忙しい人向け）



参考：https://qiita.com/Nonchalant/items/50f200c130968b42dbb5
参考：https://qiita.com/tkomagata/items/6e856b79cfc08f43fed3


docker入れる記事とdocker-composeコマンド入れる記事が、バラバラだったのでまとめただけ


## dockerインストール

```bash
sudo apt install docker.io
```






## sudoめんどくさいので消す


```bash
sudo groupadd docker
sudo gpasswd -a $USER docker
sudo service docker restart
exit
```

docker再起動してログアウトしないとダメらしい








## docker-composeインストール
[docker-composeのversion一覧](https://github.com/docker/compose/releases/)

```bash

# 2019/07/12時点での最新バージョンdocker-composeをインストール
sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
````

#### docker-composeコマンドが使えるか確認
```
docker-compose --version
```


終了
WEBエンジニアの私が現場で手放させない相棒(ツール)達を紹介するお話【macOS環境】

現在WEB開発現場に在籍している私が頻繁に利用するツールやらソフトやらをまとめました。
同業の方やこれから学習しようとする方の参考になればと思います。
対象OSはmacOSです。
Windowの方も使用できるものもあると思いますが未確認です。
ご了承ください。

## 本文

### エディタ関係

#### [Visual Studio Code](https://azure.microsoft.com/ja-jp/products/visual-studio-code)
最高のエディタ
一時期ATOMやSublimeTextに流れてた時期もありますが今はvscode一択です。
起動が早く自分好みのカスタマイズも出来ます。
Gitとの連携も取りやすいです。

#### [CotEditor](https://coteditor.com/)
txtファイルやCSVファイルを開く際に多様してます
デザインもシンプルで気に入ってます

### ブラウザ関係

#### [Google Chrome](https://www.google.co.jp/chrome/?brand=CHBD&gclid=EAIaIQobChMIjdPls9Ws4wIVA7aWCh0aFgHnEAAYASAAEgKpyfD_BwE&gclsrc=aw.ds)
最も使用頻度の高いブラウザ
クロスブラウザチェックのとき以外は基本的にChromeしか使用してません。
特によく使用するのがDeveloperToolのsearch機能です。


#### [Chromium](https://www.chromium.org/)
PuppeteerによるChrome操作で使用してます。
headlessモードをOFFにすると視覚的に操作の流れを追えます。

### 開発関係

#### [VirtualBOX](https://www.virtualbox.org/)
Vagrantを使用する為に入れていると言っても過言ではないソフトウェア
そういえばmodern.IEでクロスブラウザチェックする為にも使ってました。

#### [Vagrant](https://www.vagrantup.com/)
作業環境が基本的にLAMPなのでローカルでサクッと作れてすぐに破棄できるVagrantは多様してます。
最近の流行りはScotchBoxでお手軽LAMP環境です。~~こっそり自分の記事に誘導する~~
[【開発環境構築】誰でもお手軽LAMP環境Scotch-box 3.5 使ってみる](https://qiita.com/unique_innovation/items/f7ae54ab24088dedfe85)


### デバッグ関係

#### [DiffMerge](https://sourcegear.com/diffmerge/)
コード差分を出力してくれるツール
フォルダでの差分,ファイルでの差分を抽出してくれる
マージ機能もあるらしいですが僕は使ったことが無いです。

#### [Mergely](http://mergely.com/editor)
オンラインDiffツール
軽いコードの差分を出したい時はDiffMergeでは無くこちらを使用してます。

#### [Regulex](https://jex.im/regulex/#!flags=&re=%5E(a%7Cb)*%3F%24)
正規表現の範囲を視覚的に確認する事ができる

#### [jsoneditoronline](http://jsoneditoronline.org/)
JSONの整形ツール

### ファイル転送ツール
#### [Transmit](https://panic.com/jp/transmit/)
有料だがGUIソフトとしては直感的ですごく使いやすい。
私は諸事情で使用はできなかったが独自の「Panic Sync」という同期機能がとても良いらしい。

#### [cyberduck](https://cyberduck.io/)
無料。
アプリケーション終了時に寄付の通知が来るが強制では無い。
個人開発や自宅でのプライベート開発で使用する分はこちらで問題無いと思う。

### その他

#### [Station](https://getstation.com/)
ツール一括管理アプリ
* Gmail
* GoogleCalendar
* 各種slack
* AWS Root Console
* GitHub
* GItlab
* Heroku
* Netlify
を入れてます。
前は「Franz」使ってましたが操作性がStationの方が快適 + 待機時間が無いっていう理由で乗り換えました。

#### [Automator](https://ja.wikipedia.org/wiki/Automator)
シェルやnodejsを知らなかった時に自動化操作型のapp作ってました。
「すべてのソフトウェアを終了させる」「特定のアプリケーションを立ち上げる」自作appは今も現役です。
なおマシン起動時にアプリケーションを自動で立ち上げたい場合は下記のような環境設定の方がおすすめです。
[Macの起動時に自動的に開くアプリケーションを整理する方法](http://inforati.jp/apple/mac-tips-techniques/system-hints/identify-login-items-of-macos-account.html)

#### [QuickTime Player](https://support.apple.com/ja_JP/downloads/quicktime)
特に会社入りたての頃、覚えきれない画面操作のフローを録画して見返せるようにしてました。
動画データがかなり容量を圧迫するのでオススメは出来ないですがメモとるより画面収録した方が早いこともあります。
Microsoft Surface Pro でスクリーンキャプチャを取る方法

Microsoft Surfaceだけではなく
PrtScn（プリントスクリーンキー）が無い環境でスクリーンキャプチャを取る方法
(いくつかありますが、覚えやすくて使いやすいのは)
###「Windows+Shift+S」

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102740/b80dd233-b0e2-fa24-8e40-c00acfc93f39.png" width="30%">

2017年4月から配信しているWindows 10の「Creators Update」のキーボードショートカットではありますが、Windowsが入っていなくてもOneNoteがインストールされていればOneNoteのショートカットとして同様の画面キャプチャ機能として動作します。
スプレッドシートで今日の日付を自動で入力する【誰でも出来るGAS】

このレベルなら誰でも出来るので、軽い気持ちでやってみましょ。
スプレッドシートに入力したら、同じ行の日付欄に自動で日付が入ってほしい。

1.スプレッドシートの「ツール」→「スクリプトエディタ」を開き、下記コードを入力する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307024/3c6e5414-be67-b7a4-5000-1112c4735264.png)

```javascript:コード.gas
function setDate() {
  // 開いているスプレッドシートを取得
  var activeSpreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  // 現在開いているシートを取得
  var sheet = activeSpreadsheet.getActiveSheet();
  // 現在選択している範囲を取得
  var activeRange = sheet.getActiveRange();
  // 現在選択している行を取得
  var row = activerange.getRow();
  // 選択している行の1列目に現在時刻を入力する
  sheet.getRange( row, 1 ).setValue( new Date() );
}
```

2.スクリプトエディタの「編集」→「現在のプロジェクトのトリガー」でG suite developer hubを開く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307024/8bce153b-2b56-e277-9807-e8b73611c4d3.png)

3.G suite developer hubでトリガーを追加する。イベントの種類は「変更時」か「編集時」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307024/ac5132c3-d08c-fa81-cd45-72eb634465c1.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307024/ca27cb9c-f071-9fba-e3b9-ee6a5c7f684b.png)

4.完成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307024/33972c56-ecf6-c6c8-ec2c-fc50e92b58f4.png)

特定のシートだけにしたり、入力済みの場合は上書きしないようにしたりは、if文で条件をつけましょ。
GithubにDS.storeなどの不要ファイルが行ってしまう問題


gitignoreに記載されているファイルがcommitされてしまう。
→Github上にキャッシュが残っている為。
下記の記事を参考にキャッシュを削除。

<参考>
https://qiita.com/fuwamaki/items/3ed021163e50beab7154

もしくはGithubDesktopで
[change]に出ているファイルを右クリックで、discardを選択すると[change]から消えて変更されない。
GCP - Cloud Shellのアクセス元グローバルIPを特定する方法

## 概要
sshのための22番ポートでアクセス元制限をする際、ホワイトリスト方式で制限するとGCPコンソールやCloud Shellからのssh接続ができない問題に直面すると思います。

その際にGoogleからのアクセス元IP Rangeを特定する方法を説明していきます。

## 目次
- Cloud Shellとは
- Googleのアクセス元IPアドレスのRangeを特定する方法
    - Googleのアクセス元IPアドレスの一覧

## Cloud Shellとは
Cloud Shellの説明は[弊社記事](https://www.topgate.co.jp/gcp09-how-to-use-cloud-shell)を参照ください。

## Googleのアクセス元IPアドレスのRangeを特定する方法
Googleのアクセス元IPアドレスのRangeはGoogleの公開SPFレコードに記載されているIPアドレスとなります。

https://cloud.google.com/compute/docs/ssh-in-browser#ssherror
https://support.google.com/a/answer/60764?hl=ja

<b>なお、アクセス元IPのRangeは予告なく変更される可能性があります。</b>

それでは実際に特定してみましょう。

まずはSPFのアクセス元のドメイン一覧を特定します。

```bash
$ nslookup -q=TXT _spf.google.com 8.8.8.8

#出力結果
Server:		8.8.8.8
Address:	8.8.8.8#53

Non-authoritative answer:
_spf.google.com	text = "v=spf1 include:_netblocks.google.com include:_netblocks2.google.com include:_netblocks3.google.com ~all"

Authoritative answers can be found from:
```

対象のドメインは以下となります。
_netblocks.google.com
_netblocks2.google.com
_netblocks3.google.com

次にこのドメインのtxtレコードを参照し、アクセス元のIPを特定していきます。

```bash
nslookup -q=TXT _netblocks.google.com 8.8.8.8

#出力結果
Server:		8.8.8.8
Address:	8.8.8.8#53

Non-authoritative answer:
_netblocks.google.com	text = "v=spf1 ip4:35.190.247.0/24 ip4:64.233.160.0/19 ip4:66.102.0.0/20 ip4:66.249.80.0/20 ip4:72.14.192.0/18 ip4:74.125.0.0/16 ip4:108.177.8.0/21 ip4:173.194.0.0/16 ip4:209.85.128.0/17 ip4:216.58.192.0/19 ip4:216.239.32.0/19 ~all"

Authoritative answers can be found from:
```

```bash
nslookup -q=TXT _netblocks2.google.com 8.8.8.8

#出力結果
Server:		8.8.8.8
Address:	8.8.8.8#53

Non-authoritative answer:
_netblocks2.google.com	text = "v=spf1 ip6:2001:4860:4000::/36 ip6:2404:6800:4000::/36 ip6:2607:f8b0:4000::/36 ip6:2800:3f0:4000::/36 ip6:2a00:1450:4000::/36 ip6:2c0f:fb50:4000::/36 ~all"

Authoritative answers can be found from:
```

```bash
nslookup -q=TXT _netblocks3.google.com 8.8.8.8

#出力結果
Server:		8.8.8.8
Address:	8.8.8.8#53

Non-authoritative answer:
_netblocks3.google.com	text = "v=spf1 ip4:172.217.0.0/19 ip4:172.217.32.0/20 ip4:172.217.128.0/19 ip4:172.217.160.0/20 ip4:172.217.192.0/19 ip4:108.177.96.0/19 ip4:35.191.0.0/16 ip4:130.211.0.0/22 ~all"

Authoritative answers can be found from:
```

### Googleのアクセス元IPアドレスの一覧
現在の(2019/07/12)のGoogleのアクセス元IPアドレスは以下の通り。

<b>IPv4</b>
35.190.247.0/24
64.233.160.0/19
66.102.0.0/20
66.249.80.0/20
72.14.192.0/18
74.125.0.0/16
108.177.8.0/21
173.194.0.0/16
209.85.128.0/17
216.58.192.0/19
216.239.32.0/19
172.217.0.0/19
172.217.32.0/20
172.217.128.0/19
172.217.160.0/20
172.217.192.0/19
108.177.96.0/19
35.191.0.0/16
130.211.0.0/22

<b>IPv6</b>
2001:4860:4000::/36
2404:6800:4000::/36
2607:f8b0:4000::/36
2800:3f0:4000::/36
2a00:1450:4000::/36
2c0f:fb50:4000::/36
scipy.misc.imread の import エラー

## 実行コード

```python
import scipy.misc
scipy.misc.imread
```

### エラーログ

```bash
AttributeError                            Traceback (most recent call last)
<ipython-input-16-d0d6bba8d490> in <module>()
      1 import scipy.misc
----> 2 scipy.misc.imread

AttributeError: 'module' object has no attribute 'imread'
```

## 改善策

```bash
$ pip install scipy==1.1.0
$ python -m pip install pillow
```
【Golang】javaのenumっぽい実装よくある記事から + α（ぜひご意見下さい）

#Golangでenum

golang初心者なのと、初登校なので温かく見て下さい

そう聞くと、下記のような実装を思い浮かべる方が多いのではないでしょうか？
せっかくなら、もう少し柔軟に扱えるようにしたいなと思っていて、思いついた記事をメモがてら残します。
沢山ご意見ください。
※気出でしたらすみません。

##よくあるenum
```


type Fruits int

const (

    Apple Fruits = iota

    Banana

    Lemon

)

func (c Fruits) String() string {
	switch c {
	case Apple :
		return "りんご"
	case Banana:
		return "ばなな"
	case Lemon:
		return "れもん"
	}
　　　　return ""
}


```

この実装の場合、共通的な処理を実装する場合に少し扱いずらいなと感じていました。

なので、こんな形にしてはどうだろうかと思いました。
##よくあるenum + α

```

type fruits int

const (

    None fruits = iota
    
    Apple

    Banana

    Lemon

)

func (c fruits) String() string {
	switch c {
	case Apple :
		return "りんご"
	case Banana:
		return "ばなな"
	case Lemon:
		return "れもん"
	}
　　　　return ""
}

var FruitsEnum fruitsEnum

type fruitsEnum struct{}

func init() {
	FruitsEnum = fruitsEnum {}
}

func (f fruitsEnum) ValueOf(fruits　string) fruits {
	switch strings.ToLower(fruits) {
	case "apple":
		return Apple 

	case "banana":
		return Banana

	case "lemon":
		return Lemon

	}

	return None
}

---使う側

func main() {
    fruits := FruitsEnum.ValueOf("lemon")
    println(fruits.String())
}

```

こうしておくと、共通的な処理を実装する場合に、実態を意識せずに使えて結構便利だなと思っています。

#さいごに
こんな実装べんりかなと思い、書いてみました。ぜひぜひ色々と意見交換できればと思っています。
意見を頂き少しづつ磨き上げていきたいです！
また何か思いついたら書きますので、きになったらどんどんご意見ください！
よろしくお願いいたします！
Dartのenumを文字列と相互変換できるようにする

:::note alert
注意：現在はDartでExtensionをかけるため、無理にこの方法を取る必要はないと思います。
:::

Flutter(Dart)を書いていて、どうしても不便に感じるひとつが、enumで出来ることが少ない点です。
KotlinやSwiftであれば、enumと画面に表示する文字列であったり画像などのリソースを紐づけることも可能ですが、Dartの場合、enumを拡張することはできません。

そのため、せめてJsonをパースするときのように
`enum -> String`の変換と、`String -> enum`が出来るように苦し紛れで作ったのが以下のコードです。

```dart:enum_helper.dart
// [T] はenumを継承していることを前提としています
// (ここをコードレベルで書く方法が分かりませんでした…)
abstract class EnumHelper<T> {
  // 基本的には[enum.values()]になります
  List<T> values();

  T valueOf(String value) {
    return values().firstWhere((item) {
      return name(item) == value;
    }, orElse: () => null);
  }

  String name(T enumValue) {
    // enumをtoStringすると<型名>.<列挙子名>となるため、[.]でsplitしたのち、lastをnameとして返却します。
    return enumValue?.toString()?.split('.')?.last;
  }
}
```

使い方は以下の通りです。

```dart:fruits.dart
enum Fruits {
  apple,
  orange,
  strawberry
}

class FruitsHelper extends EnumHelper<Fruits> {
  @override
  List<Fruits> values() => Fruits.values;
}
```

```dart
// SharedPreferenceを使ってenumを管理するケースを想定します
Future<Fruits> getFruits() async {
  SharedPreferences prefs = await SharedPreferences.getInstance();
  final fruitsString = prefs.getString("pref_key");
  // 文字列からenumに変換
  return FruitsHelper().valueOf(fruitsString);
}

Future<bool> setFruits(Fruits fruits) async {
  SharedPreferences prefs = await SharedPreferences.getInstance();
  final fruitsString = FruitsHelper().name(fruits);
  // enumをPreferencesに保存するため、文字列に変換
  return prefs.setString("pref_key", fruitsString);
}
```

もっといいやり方や、enumをもっと便利に使えるtipsとかあったら教えてください。
適当なHooks入門【useEffect後編】

## 概要
Reactで開発するにあたってHooksちゅう新しい機能を使うので、公式ドキュメントで勉強したことを投稿していこうと思います。

[公式ドキュメント](https://ja.reactjs.org/docs/hooks-effect.html)
[前回のあらすじ](https://qiita.com/kouhei19920522/items/1cfbc9dd921e9b111c85)

以下はライフサイクルの処理をuseEffectを用いて記述した方法です。

#### ComponentDidMount/componentWillUnmount
~~~JSX
useEffect(() => {
    // componentDidMountでしたい処理
    const componentDidMount = () => {
        // 処理
    }
    componentDidMount();
    
    return () => {
        // componentWillUnmountでしたい処理
    };
}, []);
~~~

第二引数に空配列([])を指定することで、副作用とそのクリーンアップを 1 度だけ（マウント時とアンマウント時にのみ）実行されます。
つまりcomponentDidMount と componentWillUnmount による処理をしたい場合は、空の配列 ([]) を渡せば似たような表現が出来ます。

#### ComponentDidUpdate/setStateのコールバック
~~~JSX
const [count, setCount] = useState(0); // countの初期値は『0』

const plus = () => {
    setCount(count++)
}

useEffect(() => {
    // componentDidUpdateでしたい処理
    const componentDidUpdate = () => {
        // 処理
        document.title = count;
    }
    componentDidUpdate();
}, [count]);

return (
    <>
        <div>{ count }</div>
        <button onclick="plus()">+</button>
    </>
)
~~~

第二引数にcountを渡すことでsetCountが実行されcountが変更された場合に、処理が実行されます。
つまりcomponentDidUpdate や setStateのコールバックによる処理をしたい場合は、配列内に副作用を起こしたい場合に比較する値（上記の例だと「count」）を渡すことで、countの値が前回のレンダリング前と同一でなければ副作用が実行されます。

## ざっくりまとめ
１, componentDidMountをuseEffectで表現したい場合は第二引数に空配列を渡せすんや
２, componentWillUnmountをuseEffectで表現したい場合は副作用内で関数を返すんや
３, ComponentDidUpdateやsetStateのコールバックをuseEffectで表現したい場合は第二引数に副作用を起こしたい場合に比較する値を渡すんや

## 終わりに
自分なりの解釈ですので、いい方法などありましたら教えていただければ幸いです。
デザインパターン入門_Template Method

# Javaで学ぶデザインパターン入門

結城浩「Javaで学ぶデザインパターン入門」をC#で勉強

# Template Methodパターン

スーパークラスで処理の枠組みを定め、サブクラスでその具体的内容を定めるパターン

## 実装

```C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DesignPatternLearn.TemplateLearn
{
    public class TemplateLearn
    {
        public static void Main(string[] args)
        {
            AbstractDisplay d1 = new CharDisplay('A');
            AbstractDisplay d2 = new StringDisplay("Hello, World!");
            d1.Display();
            d2.Display();
            Console.Read();
        }
    }

    public abstract class AbstractDisplay
    {
        public abstract void Open();
        public abstract void Print();
        public abstract void Close();
        public void Display()
        {
            Open();
            for (int i = 0; i <= 5; i++)
            {
                Print();
            }
            Close();
        }
    }

    public class CharDisplay : AbstractDisplay
    {
        private char Ch { get; set; }

        public CharDisplay(char ch)
        {
            this.Ch = ch;
        }

        public override void Open()
        {
            Console.Write("<<");
        }

        public override void Print()
        {
            Console.Write(this.Ch);
        }
        public override void Close()
        {
            Console.WriteLine(">>");
        }
    }

    public class StringDisplay : AbstractDisplay
    {
        private string Str { get; set; }
        private int Width { get; set; }

        public StringDisplay (string str)
        {
            this.Str = str;
            this.Width = this.Str.Length;
        }

        public override void Open()
        {
            PrintLine();
        }

        public override void Print()
        {
            Console.WriteLine("|" + Str + "|");
        }

        public override void Close()
        {
            PrintLine();
        }

        private void PrintLine()
        {
            Console.Write("+");
            for (int i = 0; i < Width; i++)
            {
                Console.Write("-");
            }
            Console.WriteLine("+");
        }
    }
}

```

## 重要な点
<p>
抽象クラス(AbstractDisplay)でテンプレートメソッド(共通した処理の流れ)を実装し、テンプレート
メソッドで使用するメソッドは具象クラス(CharDisplay, StringDisplay)で実装する。これにより、テンプレートメソッド(共通した処理の流れ)に問題が見つかっても、修正が少なくて済む。
</p>
Java tips - JavaMailでClassNotFoundExceptionが起こったときは依存関係を疑う

# JavaMailでClassNotFoundExceptionが起こったときは依存関係を疑う

JavaのバッチでJavaMailを使用してメール送信する処理を作成していたら、ClassNotFoundExceptionが起きたので、その時の原因と解決法をまとめる。

## 原因
原因は単純で読み込むライブラリを間違えていました。
元々はGradleのdependenciesに以下のように書いて、ライブラリを読み込んでいました。

```gradle
compile group: 'javax.mail', name: 'javax.mail-api', version: '1.6.2'
```

これで、落ちてくるライブラリは以下のみになります。
javax.mail-api-1.6.2.jar

このライブラリに含まれるクラスは「javax.mail~」に関連するクラスだけになり、メールを送るときにクラス足りなくて怒られる、、、（maven repositoryのdependecyには何も書かれてないが）

## 改善
以下のように読み込むJavaMailのライブラリを変えます。

```gradle
compile group: 'com.sun.mail', name: 'javax.mail', version: '1.6.2'
```

これで落ちてくるライブラリは以下の２つになります。
javax.mail-1.6.2.jar
activation-1.1.jar

この「javax.mail」ライブラリに含まれるクラスは「javax.mail~」関連のクラスと「com.sun.mail～」関連クラスになります。
このライブラリを使用するとClassNotFoundException関連のエラーがすっきりしました。

## まとめ
java mail関連のライブラリは似たようなグループ構成でけっこう戸惑ってしまいます。
けっこう動きそうなパッケージ名しているし、すごくわかりにくい、、、
[PostgreSQL]結合テーブルでの2カラムGroupByをシンプルに書く

#### 背景
お気に入り数/フォロー数など、ユーザーマイページで使う
ユーザーIDに紐づく集計されたデータ件数をSQLで取得したい場面がありました。

今回、テーブル構成がユーザーIDに対して
 `お気に入りレシピ (1:n) ` と`レシピ (1:n)`となっており、
それぞれが持つ集計カラムのグルーピングが必要になったため、その取得例を記載します。

#### 取得したいデータ
対象：Aさんがお気に入りに登録しているレシピ
条件：調理時間を5分以内 / 10分 / 15分 / 20分 / 25分 / 30分 / 31分以上~ の区分として集計
　　 ※以内・以上について、データには細かい刻みも存在する(1分,4分,60分,120分など)

#### テーブルA (お気に入りレシピ)
誰が何のレシピをお気に入りしているかの情報。
`user_id`単位でグルーピングして集計したい。

|id  |user_id|recipe_id |delete_flag|...|
|---|---|---|---|---|
|1  |51|10000|0
|2  |54|10001|0
|3  |51|10002|0
|4  |51|10003|0
|5  |54|10004|0

#### テーブルB (レシピ)
各レシピの情報。
`調理時間(cook_time)`をグルーピングさせて集計したい。
テーブルAとは`id`=`A.recipe_id`で結合

|id  |title  |cook_time  |delete_flag|...|
|---|---|---|---|---|
|10000  |hoge焼き  |5  |0
|10001  |fuga麺  |10  |0
|10002  |piyo巻き  |15  |0
|10003  |foo和え  |15  |0
|10004  |barおろし  |10  |0

#### GroupByの場合

```sql
SELECT
  recipes.cook_time Recipe__cook_time,
  count(*)
FROM
  recipe_cooks, recipes
WHERE
  recipe_cooks.recipe_id = recipes.id
  AND recipes.delete_flag = 0
  AND recipe_cooks.delete_flag = 0
  AND recipe_cooks.user_id = ?
GROUP BY recipes.cook_time
ORDER BY recipes.cook_time ASC
```
　　　　　　　↓↓↓
![スクリーンショット 2019-07-12 13.22.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239110/010ffabb-b71c-29b9-f3b0-60fa92883e01.png)

とれた！でもこれじゃない・・・
このままだと再度、5分以内・31分以上の集計をさせないといけなくなる。

#### 結果
case文で条件を当てる形で取得できました。

```sql
SELECT
  sum(case when recipes.cook_time <= 5 then 1 else 0 end) as "5分以下",
  sum(case when recipes.cook_time = 10 then 1 else 0 end)as "10分",
  sum(case when recipes.cook_time = 15 then 1 else 0 end)as "15分",
  sum(case when recipes.cook_time = 20 then 1 else 0 end)as "20分",
  sum(case when recipes.cook_time = 30 then 1 else 0 end)as "30分",
  sum(case when recipes.cook_time >= 31 then 1 else 0 end)as "31分以上"
FROM recipe_cooks, recipes
WHERE
  recipe_cooks.recipe_id = recipes.id
  AND recipes.delete_flag = 0
  AND recipe_cooks.delete_flag = 0
  AND recipe_cooks.user_id = ?
```
　　　　　　　　　　　　　　　　↓↓↓
![スクリーンショット 2019-07-08 17.46.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239110/1e78122a-a856-15f0-e16c-594d8c44eaaf.png)

case文で範囲指定して真なら(+1)する形で集計が取れた。
ただカラム名にStringが入るため、取り扱い時に注意が必要。