OmniAICreator/Qiita-1.07M huggingface dataset:
BeegoのORMの使い方(RAWで生のSQLを書く)

これはGolangのフレームワークBeegoで生のSQLを書きたいときに参考にできるソース

だれかBeegoのSQLインジェクションの詳細を調べてほしい…

公式サイト
[Beego Raw](https://beego.me/docs/mvc/model/rawsql.md)

・やっとくといいこと(Beegoのormをデバックモードにする)
　→これをすると発行されるSQLを確認できる。

```go
// これをconf/xxx.confとかに書いておくと環境別に分けられる
// database.debug = true

debug, _:= beego.AppConfig.Bool("database.debug");
if (debug == true) {
	orm.Debug = true
}
```

###  Raw関数を使用して直接SQLを発行

```go
package models

import (
	_ "errors"
	"fmt"
	_ "strings"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"
)

type User struct {
	Id       int
	Name     string `orm:"size(128)"`
	UserName string `orm:"size(128)"`
	Email    string `orm:"size(128)"`
	Token    string `orm:"size(128)"`
	Avatar   string `orm:"size(128)"`
}

func init() {
	orm.RegisterModel(new(User))
}

// 使用するサービス関数
func GetUserByEmail(email string)(v *User, err error) {
	// ほかのORM同様にnewする
	o := orm.NewOrm()
	// Raw関数を使用してSQLを発行
	err = o.Raw("SELECT * FROM user where email = ?", email).QueryRow(&v)
	if err == nil {
	}else{
		beego.Error(err)
		return nil, err
	}
	return v, nil
}

```

### NewQueryBuilderを使う

```go
func LoginSubmit(username string, email string)(user *User, err error) {

	qb, _ := orm.NewQueryBuilder("mysql")
	qb.Select("*").From("user_d_b").Where(fmt.Sprintf("name='%s'", username)).And(fmt.Sprintf("email='%s'", email))
	sql := qb.String()
	o.Raw(sql).QueryRow(&userDB)
	if user.Id == 0 {
		return false
	}
	return true
}
```
データの監視

[算出プロパティとウォッチャ — Vue\.js](https://jp.vuejs.org/v2/guide/computed.html)

`watch`や`computed`を使ってデータを監視するときにいろいろ大変だったのでメモ。
vueでは`data`や`computed`にあるデータを監視して、変更を検知して何かしらfunctionを起こしたりとかが出来る。

### 今回やりたいこと
`props[quote]`の変更を検知して、quote_controllerにPOSTしたい。
ただし、`quote`の中には`quote.choices`と`quote.room`がある。

### 元の状態
```javascript
watch: {
    quote: {
      handler: function(newValue) {
        this.$http.post('//localhost:3000/quote', {
          choices: this.choices,
          room: this.room
        }).then((res) => {
          this.quote.sections = res.data
        })
      },
      deep: true
    }
}
```

### 何が問題なの？
`handler`をつけると、<b>配列の要素そのものが変更されたことを検知する</b>。つまり、`this.room = room1 => this.room = room2`とか、this.choicesの要素の一つの内容だけ変わったとかも検知してくれる。`deep: true`がないと、配列の要素の増減は検知してくれるけれど内容が変わったことは検知しない。

今回、`room`に関しては内容の変更も検知してもらう必要がある。でないとroomに入っているのはいつも一つの要素だけだから永遠に検知されない。
でも、`choices`に関しては`pattern`を変更すると一気に要素が入れ替わる為、その時に要素が変わったのをいちいち検知して永遠にPOSTされてしまった。
しかし、`choices`と`room`は同時にPOSTする必要があるので別々にwatchしてPOSTアクションを起こすことは避けたい…

### 解決😇？
これで一旦正常に動いているように見える。

```javascript

watch: {
    choices: function(newVal, oldVal) {
      this.change = true
      console.log("heyyyyyy")
    },
    room: {
      handler: function(newVal, oldVal) {
        this.change = true
        console.log("wowowowowowo")
      },
       deep: true
    },
    change: {
      handler: function(newVal, oldVal) {
        if(this.change) {
          this.$http.post('//localhost:3000/quote', {
            choices: this.choices,
            room: this.room
          }).then((res) => {
            this.quote.sections = res.data
          })
          console.log("www")
          this.change = false
        }
      }
    }
}
```
まず。data`change`を置く。
`room`だけ`deep: true`の状態にして、`choices`と`room`の変更が検知されたら`change=true`として`change`自体の変更もwatchする。
[C#] mp3ファイルを再生する

**もくじ**
→https://qiita.com/tera1707/items/4fda73d86eded283ec4f

# やりたいこと
WPF(.net Framework4.7)のアプリで、mp3のサウンドファイルを鳴らしたい。

# やりかた
`Windows Media Player`を使用する。
具体的には、`C:\Windows\System32\wmp.dll`を使用する。

## 手順
下記のようにする。

- プロジェクトの参照に、`C:\Windows\System32\wmp.dll`を追加する。
- 使用するcsの先頭に`using WMPLib;`を追記する。
- 下記のサンプルのように、WindowsMediaPlayerクラスを使用し音声再生を実装する。

## サンプル

```cs
using System.Windows;
using WMPLib;

namespace WpfApp38
{
    public partial class MainWindow : Window
    {
        // メディアプレーヤークラスのインスタンスを作成する
        WindowsMediaPlayer _mediaPlayer = new WindowsMediaPlayer();

        public MainWindow() => InitializeComponent();

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            _mediaPlayer.URL = @"sound.wav";// mp3も使用可能
            _mediaPlayer.controls.play();
        }
    }
}

```

※今回試した時は、音声ファイルはプロジェクトの直下に「追加」して、「出力ディレクトリにコピー」の設定を「常にコピー」にして使用した。
そうすれば、ビルドするとexeと同じところにコピーされて、ファイル名だけ指定する形で使用できた。

# 他のやり方
音を鳴らす方法は、他のやり方もある様子。こちらのページがとても分かりやすい。
https://qiita.com/Oichan/items/b93e8e8ba8211b925d0a

できれば、
.NETの標準で用意されたものでやりたいので、上記記事にある**「System.Media.SoundPlayer」**でやりたい。いずれ試す。(mp3が使えないようだが...)


# 参照

第01回 プロジェクト作成と曲再生
https://www.usefullcode.net/2016/03/01_createproject.html

C#でサウンドを鳴らす
いくつかの方法が説明されている。
https://qiita.com/Oichan/items/b93e8e8ba8211b925d0a
ディレクターがgitを習得したらいろいろ捗る気がする


##まず前提
前提としてエンジニアとディレクターは敵ではないはずです。
ディレクターもエンジニアも限られた納期の中でできるだけ良いものを仕上げるという目的は同じはずです。
クライアントとエンジニアの間に立ってプロジェクトを円滑に回してくれたり、改善提案をしてくれるディレクターと一緒に仕事をしていると、そのサイトをもっと良くしていこうと思えるのでそういうディレクターの存在はとても有難く思います。

##ありがたい存在だけど
上記のように積極的にプロジェクトを回してくれるディレクターの存在は非常にありがたいです。
でも、文言修正とか「自分でやってくれたら嬉しいなぁ」と思う事がたまにあります。

##なぜそう思うか
もしディレクターが多少gitを操作する事が出来て、テキストの修正やバナーの差し替えなどの軽微な修正を対応してくれた場合、その分エンジニアのリソースが空く事になります。結果として社内のエンジニアはもっと開発に注力できます。

現在の会社で外注に頼らざるを得ない大きな理由一つが社内エンジニアのリソース不足かと思います。
軽微な修正というのは常日頃からパラパラと依頼が来ます。その一つ一つの修正内容は軽微なものですがチリも積もると文言修正だけでも半日くらいかかってしまう事もあります。しかし作業自体は簡単なものなので、指示書などを作成する時間で対応が完了するものがほとんどです。

リソース不足解消の為に社内のエンジニアの数をすぐに増やすというのも難しいと思います。
自社エンジニアが本来の業務へコミットできるリソースを確保する為、上記の作業をディレクターにカバーしてもらえれば、今まで外注に発注していた案件も自社内で対応できるかもしれません。
そして、自社内での対応が当たり前になり始めたら外注によってブラックボックス化していた箇所は徐々に減っていき、ゆくゆくは自社での改修がスムーズになって行くと思います。

##ディレクターの負担は増えるか？
修正作業まで対応していたらディレクター側の負担が増えるんじゃないかという懸念はありますが、軽微なテキスト修正程度であれば、むしろコミュニケーションコストもなくなり双方の負担が減ると思います。もちろん慣れるまでは開発のサポートは必要ですし、どの程度の修正まではディレクターが対応しても問題ないのかという線引きは難しいですし、万一事故が起きた場合の責任の所在などもあやふやになってしまう問題はあります。

##まとめ
実際にディレクターが軽微な修正対応をやるとしたら個々のスキルもバラバラで問題も色々発生するかと思いますし、万一事故が起きた場合の責任の所在などもあやふやになってしまう問題はあります。
また、そもそも両方の負担が本当に減るのか？という疑問もあります。でも、ディレクターがgitの操作を覚えたら、改行位置の調整や表記ゆれ、句読点の調整など、そういった事をわざわざ開発に依頼しないで即時反映できるのはお互いにストレスなく進められると思います。
Font > 東雲フォント > BDF形式をBMP形式にする (ツール: bdf2bmp)

```txt:動作環境
Windows 8.1 Pro(64bit)
```

### 概要

- 4D Systemsのタッチディスプレイgen4-uLCD-35DTにおいて日本語フォントを表示したい
- フォントは東雲フォントを使用してみる
    - http://openlab.ring.gr.jp/efont/
    - shinonome-0.9.11p1.tar.bz2 を取得
- BDF形式をBMP形式に変換することになる

### ツールと使用

- [bdf2bmp](http://hp.vector.co.jp/authors/VA013241/font/bdf2bmp.html)
    - CUIアプリ

ツール感謝です。

CUIアプリなのでPowerShellから実行しても良い。
今回はショートカットを作って「リンク先」に下記のように指定して変換をした。

```
E:\tool\bmpfont_191112\bdf2bmp\bdf2bmp.exe shnmk16.bdf shnmk16.bmp
```

対応するファイルごとにショートカットをコピーしてパラメータを変更して使った。
良く使うパスワードを保存しておいて、パスワード枠で【F1】を押せば保存しておいたパスワードを自動入力させる

;↓メニューを有効にしたい場合は先頭の【;】を削除
;===============================================
;Menu , skojima , Add , (&F1)  → PW【自動入力】,F1_
;Menu , skojima , Add ;
;Menu , skojima , Add , (&F3)  → PW【事前登録】【登録中のPWを確認】,F3_
;Menu , skojima , Add ;
;Menu , skojima , Add , (&F12)  →【このメニューを表示】　【ESC】→閉じる　Ver.2019-11-12,F12_
;return
;===============================================
;F12::
;F12_:
;Clipboard = 
;Menu , skojima , show  ; , 10 , 10
;↑メニューを有効にしたい場合は先頭の【;】を削除

;【重要】マイドキュメント内に暗号化されていない　SendPW.ini　に直接パスワードを保存するので自己責任でご使用下さい。

msgbox,,,【 F1 】　PW入力枠で→PWを自動送信　【 F3 】　パスワードを設定・更新　　　　【重要】これは無保証です！ By Skojima@kuhen.jp,10


IfNotExist, %A_MyDocuments%\SendPW.ini
{
msgbox, マイドキュメントにPW保存用　【%A_MyDocuments%\SendPW.ini】　がありません！

send , {F3}

}


return


F1::
F1_:
IfNotExist, %A_MyDocuments%\SendPW.ini
{
msgbox, マイドキュメントにPW保存用　【%A_MyDocuments%\SendPW.ini】　がありません！
msgbox, 【 F3 】を押して、事前送信パスワードを登録してから【 F1 】を実行！
}
Else
{

IniRead, sec1_key1,%A_MyDocuments%\SendPW.ini, sec1, key1

;msgbox,%sec1_key1%

IfEqual, sec1_key1,ERROR
{

msgbox, パスワードが登録されてません！ 　【 F3 】で設定してください！
}
else
{
    Sleep,500
    Send,%sec1_key1%
    Sleep,500
    Send, {Enter}
}

}

return


F3::
F3_:

IfNotExist, %A_MyDocuments%\SendPW.ini
{
FileAppend,,%A_MyDocuments%\SendPW.ini
msgbox, 今から送信PW保存用として　【%A_MyDocuments%\SendPW.ini】　を作成します！
}

IniRead, sec1_key1,%A_MyDocuments%\SendPW.ini, sec1, key1

IfEqual, sec1_key1,ERROR
{
}
else
{
msgbox,現在のPW：【　%sec1_key1%　】　　次の画面で新しいPWに更新出来ます！
}

InputBox, PW_var,PWを事前登録,自分のログイン用「パスワード」を入力,,360,150

If ErrorLevel = 0
{
IniWrite, %PW_Var% , %A_MyDocuments%\SendPW.ini, sec1, key1
IniRead, sec1_key1,%A_MyDocuments%\SendPW.ini, sec1, key1
  msgbox,登録パスワードは【　%sec1_key1%　】です。　PW入力画面の枠をクリックしたら【 F1 】を押す！
}
Else
{
  MsgBox,キャンセル：パスワードは更新しませんでした！
}

return
【TypeScript/JavaScript】Optional Chainingのトランスパイル後がわからなかったので調べてみた

[こちら](https://qiita.com/102Design/items/5f23f47f478ff845e3af)の記事で、TypeScript
 v3.7からの新機能「Optional Chaining」が解説されていました。
その中に「Optional Chaining」を使用したコードのトランスパイル結果が記載されています。  

> 例えばこんなコードがあるとして
> 
> ``` typescript
> interface Foo {
>     name: string
>     bar: {
>       name: string
>       baz?: {
>         name: string
>       }
>     }
>   }
> 
>   let foo: Foo
> 
>   foo = { name: 'a', bar: { name: 'bar' } }
> console.log(foo.bar.baz?.name)
> ```
> 
> トランスパイルするとどうなるかというと下記のようになります。
> 
> ``` typescript
> var _a;
> let foo;
> foo = { name: 'a', bar: { name: 'bar' } };
> console.log((_a = foo.bar.baz) === null || _a === void 0 ? void 0 : _a.name);
> ```

このトランスパイル後のソース、特に4行目のコード

``` typescript
console.log((_a = foo.bar.baz) === null || _a === void 0 ? void 0 : _a.name);
```

がどのような文法で成り立っているかわからなかったので、調査してみました。

※: 記事内に間違っている箇所があればコメントで教えてくださるとたすかります。

## 前提条件

以下の文法については理解している前提とします。

+ `==`と`===`の違い
+ 三項演算子

## ポイント

+ 代入式の返り値は「代入した値」
+ `void 0`は`undefined`と等価

## 代入式の返り値は「代入した値」

まず前半部分について注目してみます。

``` typescript
(_a = foo.bar.baz) === null
```

JavaScriptでは、代入式の返り値は「代入した値」になります。つまり、`(_a = foo.bar.baz)`の返り値は`foo.bar.baz`です。
また、`interface Foo`の定義により 、`foo.bar.baz`の型はTypeScript上では`string|undefined`であるため、
左辺`(_a = foo.bar.baz)`の返り値は`何らかの文字列`もしくは`undefined`です。
その返り値の値を`null`と厳密比較している、というのが上式の意味です。

ここで、`===`による厳密比較が`true`になるには両辺の型が一致している必要がありますが、
`string|undefined`と`null`では型がそれぞれ異なるためこの式の結果は必ず`false`になります。

つまりこの式は、`_a`に`foo.bar.baz`を代入した上で、`||`以降の式を必ず実行する仕掛けになっています。


## `void 0`は`undefined`と等価

次に後半部分です。

``` javascript
_a === void 0 ? void 0 : _a.name
```

`void 0`という見慣れない文法がありますが、これは`undefined`と等価です。
上式を`undefined`で置き換えるとわかりやすくなります。

``` javascript
_a === undefined ? undefined : _a.name
```

`_a`がundefinedなら`undefined`、そうでないなら`_a.name`を返す式ですね。
`undefined`でなく`void 0`を使用するのは、「`undefined`が書き換え可能である」というのが理由の一つとしてあると思います。

[参考: void(0)とundefinedの使い分け](https://qiita.com/vsanna/items/3daa7c4788d5480d964e)

> ## なぜundefinedの代わりに使うのか？
> jsではundefinedは値であり、すなわち上書きができる。そのため代わりとして、voidが使われる。
> 
> ```javascript:example
> console.log(a === undefined) // true
> console.log(a === void 0)    // true
> 
> // undefinedをうわがく
> var undefined = 100
> 
> console.log(a === undefined) // false
> console.log(a === void 0)    // true
> ```

`void 0`を使用することで`undefined`の書き換えがトランスパイルに影響されないようになっています。

## まとめ

以上より、トランスパイル後のコードは「`_a`に`foo.bar.baz`を代入し、`_a`が`undefined`でなければ`_a`のプロパティ`name`を返す。そうでなければ`undefined`を返す」という挙動であることがわかりました。

(※ でも、`foo.bar.baz`を直接比較せずに`_a`に代入してから比較するのはなんでだろう。。。。分かる人いたら教えてください。)
Ruby initializeメソッド

# initializeメソッドを使う
initializeメソッドは、他のインスタンスメソッドと同じように定義することができる。

#### [例1]
```ruby:hoge.rb
class Hoge
　# 〜###〜

  def initialize
    puts "インスタンスが生成されました"
  end

  # 〜###〜
end

hoge1 = Hoge.new
````
Hoge.newが実行されると自動でinitializeメソッドが呼び出されます。

+ 結果

```
インスタンスが生成されました
```
# initializeメソッドでインスタンス変数を使う
```ruby:fuga.rb
Class Fuga
  # ・・・・
  def initialize
    # インスタンス生成直後に "piyo"をインスタンス変数nameに代入している
    self.name = piyo
  end
  
  # ・・・

end
fuga1 = Fuga.new
puts menu1.name
````
インスタンスメソッド内では、```self.変数名```でインスタンス変数を使うことができる。
よって、```self.変数名 = 値```でインスタンス変数に値を代入することができる。

+ 結果

```
piyo
```
以上 initializeメソッドの簡単にしてみました。
VSCode tips（忘備録）

### ファイルを開く際に、現在開いているファイルが上書きされて描画されてしまうのを防ぐ

上書きされているのは、開いているエディターがプレビューモードで開かれているから
（ファイル名部分がイタリックになっていたらプレビューモード）なので、
プレビューモードをやめてしまう。

設定から、
`workbench.editor.enablePreview:false`
とする。

※但し、falseにすると、検索結果から表示したファイルも全て残っていくのでそこは慣れが必要ｗ
【簡単】ブックマークレットを使って、口コミを5秒で調べる！！【お手軽】


<br>

職場でブックマークレットの話が出てきたものの

え？え？何それ？？便利なの？？
説明聞いてもイメージ湧かない....

となり、茫然としたので、触ってみることに。


結論

$\huge{めちゃ便利でした😆}$



## ブックマークレットって？

ブックマークレットとは、ブラウザのブックマークにJSのコードを登録しておき、
クリックすることで実行できる技術です。

結構前からあったみたいですね。

具体的にどんなことできんの？って方は、
下の実例集みると、想像が膨らみます

### 実例集

- URLをHTML形式でコピー
- URLをMarkdown形式でコピー
- 日本語を含むURLをエンコードせずにコピー
- YouTubeを保存する
- 次/前のページへ
- ページの読み込み速度を計測する
- ページのHTMLチェック
- Webページで使われているフォントを調べる
- ページのレスポンシブチェック

などなど、便利なブックマークレットが紹介されていますね。

https://psephopaiktes.github.io/pages/bookmarklets/#bookmarklet-4


jsの知識とアイデア次第で、色々できそうです。

## 口コミ検索を５秒で実装する

ところで、皆さん口コミ調べる時ってどうしてますか？


私は、基本 

**Twitter** です。

Twitter で　「商品名　デメリット」　「商品名　良い」
などで検索することが多いです。

というわけで、今回は、
Twitterで検索を簡単にすること
を目標に作成していきます。

## 使い方と実装

ブックマークレットの良いところは、
環境構築なし
”ブックマークに登録する”だけで、プログラムが走ることですね。

### 実装

下記のリンクのボタンを、
ドラッグアンドドロップでブックマークバーに移動させるだけ！


<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="html,result" data-user="190131start" data-slug-hash="VwwBxqz" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="bookmarklet for twitter">
  <span>See the Pen <a href="https://codepen.io/190131start/pen/VwwBxqz">
  bookmarklet for twitter</a> by naoto190131 (<a href="https://codepen.io/190131start">@190131start</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

5秒で実装できましたね☺️


### 使い方

こんな形で、ブックマークに保存しておき、


<img width="345" alt="スクリーンショット 2019-11-12 10.19.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352124/4275a338-e4fc-ab74-603b-15965b3a1e78.png">

ポップアップに、検索したいワードを打ち込めば...

<img width="596" alt="スクリーンショット 2019-11-12 10.12.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352124/79209c6b-fe92-2a86-0942-2a226a174785.png">



Twitterの検索画面で、口コミを検索することができます！

<img width="712" alt="スクリーンショット 2019-11-12 10.14.18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352124/2e6f68c5-1dad-ed24-b4fe-70fec57fe9d1.png">


便利っ...！

## コード

```html
<button>
    <a href="javascript:!function(undefined){
        var q = prompt('単語を入力し、Enterキーを押してください','');
        var preference = ' 最高 ';
        if(q === '' || q === null){window.alert('キャンセルされました');
        }else{window.open('https://twitter.com/search?q='+q+preference+'&src=typed_query');}
        }();">Twitter メリット</a>
</button>
```

コードはこんな感じ

href属性にjsを書くだけですね。

ブックマークバーに、ドラッグアンドドロップで移動させて使いたかったので
buttonにしてますが、aタグだけでもいいです。

別タブで開かせたかったので、window.open（）使いましたが、
同じタブ内での遷移ならwindow.location.hrefにすると良いと思います。


あとはPreferenceを変更するだけで、
悪い口コミも作成できます。

```html
<button>
    <a href="javascript:!function(undefined){
        var q = prompt('単語を入力し、Enterキーを押してください','');
        var preference = ' 最悪 ';
        if(q === '' || q === null){window.alert('キャンセルされました');
        }else{window.open('https://twitter.com/search?q='+q+preference+'&src=typed_query');}
        }();">Twitter デメリット</a>
</button>
```


## 今後の課題

Chromeのコンテンツブロックに引っかかるので、
どなたか、回避方法教えてください...
joinsで複数のテーブルの結合をスマートに。

# はじめに
テーブルの結合に対して苦手意識があり、せっかく便利な`Activerecord`があるのに`find_by_sql`で逃げてしまい、sqlをゴリゴリに書いて結合させていた。

`joins`を使って、３つ以上のテーブルを結合する方法に向き合ったのでまとめる。

結合するうえで、`foreign_key`, `primary_key`をどう設定していくのかを絡めて、例をとりあげる。

# 取り上げた例
「本」「レビュー」「レビューした人」の３つテーブルを扱う。
DBは下の画像のとおりに設定する。

<img width="813" alt="スクリーンショット 2019-11-11 15.58.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475098/5868889d-784f-8b39-7041-0c9ce6d4905a.png">

取り出したい条件を
**「女性が評価4.0以上レビューした本のタイトル一覧」**とする。

つまり 
`where`句でgender = 'woman'　かつ evaluation >= 4.0　を指定して、
`select`をtitleとするイメージ。

ただ、これをどう結合して扱うかが問題。

# modelを整える
## 関係性を把握
あるユーザーはいくつもレビューする
あるレビューは一人のユーザーによって作られる
あるレビューは一つの本を対象にする

関係性は次のようになる。

<img width="847" alt="スクリーンショット 2019-11-11 16.33.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475098/e2613129-df76-a1e6-af4c-8f62cce5a65d.png">


## ひとつの結合

usersとreviewsの関係性だけみてみる。
まずusersのmodel

```users.rb
class User < ApplicationRecord
  has_many :reviews
end
```
`has_many`なので`reviews`と複数形。
これを設定すれば`User.joins(:reviews)`が使えるようになる。
`:reviews`はmodelで定義したとおりに複数形

```.rb
User.joins(:reviews)
=> "SELECT `users`.* FROM `users` 
    INNER JOIN `reviews` ON `reviews`.`user_id` = `users`.`id`"
```

reviewsのmodelも設定してみる。

```reviews.rb
class Review < ApplicationRecord
  belongs_to :user, optional: true
end
```
これを設定すれば`Review.joins(:user)`が使えるようになる。
`belongs_to`だから`user`と単数形。

```.rb
Review.joins(:user)
=> "SELECT `reviews`.* FROM `reviews` 
    INNER JOIN `users` ON `users`.`id` = `reviews`.`user_id`"
```

# 任意の主キー,外部キー
`primary_key`と`foreign_key`を使って、任意の外部キー code を設定する。

※　codeではなくbook_idとして紐付ければよいのだが、任意の外部キー設定をとりあげるためにcodeとしている。

```reviews.rb
class Review < ApplicationRecord
  belongs_to :user, optional: true
  belongs_to :book, primary_key: :id, foreign_key: :code, optional: true
end
```

```books.rb
class Book < ApplicationRecord
  has_many :reviews
end
```
このように設定すると複数の結合を`Book.joins(reviews: :user)`と書くことができる。

```.rb
Book.joins(reviews: :user)
=> "SELECT `books`.* FROM `books` 
    INNER JOIN `reviews` ON `reviews`.`code` = `books`.`id` 
    INNER JOIN `users` ON `users`.`id` = `reviews`.`user_id`"
```

# 目的の条件で取り出す

目的としていた**「女性が評価4.0以上レビューした本のタイトル一覧」**を取り出すには、

```.rb
Book
 .joins(reviews: :user)
 .select('books.title')
 .where('users.gender = ?', 'woman')
 .where('reviews.evaluation >= ?', 4.0)

=> "SELECT `books`.* FROM `books` 
    INNER JOIN `reviews` ON `reviews`.`code` = `books`.`id` 
    INNER JOIN `users` ON `users`.`id` = `reviews`.`user_id` 
    WHERE users.gender = 'woman' 
    AND reviews.evaluation >= 4.0"
```

以上。
これで複数にまたがる結合からの抽出が完了
jquery.ui.touch-punch.jsをSurfaceのタッチパネルでも使えるようにする

# 概要
jQuery UIをタッチイベントに対応させるライブラリに
jquery.ui.touch-punch.jsがあるが、
surfaceのタッチイベントでは動かないので
jquery.ui.touch-punch.jsを修正する。

# 施策
```javascript
  $.support.touch = 'ontouchend' in document;
```

上記スクリプトの下に追加

```javascript
  $.support.touch = 'ontouchend' in document;

  //追加
  if('onpointerenter' in window){
    $.support.touch = true;
  }
```


# 解説
「Ignore browsers without touch support」の行で
タッチデバイス以外は処理を中断するスクリプトが記述されているため、
ポインタデバイスであるsurfaceでは動かなくなる。

```javascript
  // Detect touch support
  $.support.touch = 'ontouchend' in document;

  if('onpointerenter' in window){
    $.support.touch = true;
  }

    // Ignore browsers without touch support
  if (!$.support.touch) {
    return;
  }
```
Substance Painter のレジストリ（TDRどうこう）をダブルクリックで解決するヤツ

<p><img src="https://dl.dropbox.com/s/uifydb8jd4uo0gr/SubstancePainter_TDR_Issue.png" /></p>


こいつです。

一度修正しても、グラボのドライバをアップデートしたりすると復活したりします（今日復活した）

※ 調べるの面倒だしダイジョブやろ！ と Continue anyway したらマシンが止まったので、ちゃんと設定やっといた方が良いです。



## レジストリを更新する .reg ファイルを作る

メモ帳などで、以下のテキストを `SubstancePainter_Fix_TDR_Issue.reg` など、拡張子を **.reg** にした状態のテキストファイルとして保存します。


```txt:SubstancePainter_Fix_TDR_Issue.reg

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\GraphicsDrivers]
"TdrDdiDelay"=dword:0000003c
"TdrDelay"=dword:0000003c
```



### .reg ファイルをダブルクリック


保存した .reg ファイルをダブルクリックします。

すると、


> 「このアプリがデバイスに変更を加えることを許可しますか？」
…
「レジストリエディター」
…

と出たり、

<p><img src="https://dl.dropbox.com/s/g1520rmd8tzfjyb/SubstancePainter_TDR_Issue_Confirm.png" /></p>


とか出たりするので、「はい」を選択。

以下のダイアログが出て、レジストリが更新されます。

<p><img src="https://dl.dropbox.com/s/v4jy09ukc883mqc/SubstancePainter_TDR_Issue_Done.png" /></p>


いつかまた忘れたころにダイアログが出ても、次からは .reg ファイルをダブルクリックするだけで TDR Issue を回避できるようになります。


以上です。お疲れさまでした。




--
## まとめ

- [#DCCツール＆アセット開発まとめ](https://qiita.com/sator_imaging/items/fd1d13649b5574c1c832)
   <iframe
      class="embed-card embed-webcard"
      scrolling="no"  frameborder="0"
      style="
         display: block;  border: none;
         margin: 10px 0px;
         width: 100%; height: 155px;
         max-width: 500px;
      "
      src="https://hatenablog-parts.com/embed?url=https://qiita.com/sator_imaging/items/fd1d13649b5574c1c832">
   </iframe>
Windows10で突然wifiに繋がらなくなった時の対処法

#Windows10で突然wifiに繋がらなくなった時の対処法
　ある日突然自分のpcがWifiに繋がらなくなって途方に暮れてしまったので、その時の対処法について述べます。
　いつものようにネットに繋ごうと思ったら、なぜかpcから「利用可能なWifiはありません」と表示され、ネットが使えなくなってしまいました。pcの再起動や、ルータの再起動、ネットワークアダプタを無効化してから有効化するなど、いろいろ試しましたが解決できませんでした。そこで、デバイスマネージャーからネットワークアダプタのドライバーを更新するとwifi接続が復活し、事なきを得ました。
nginx導入

# 参考URL

公式
https://nginx.org/en/

CentOS 7へのnginxのインストール。最短でバーチャルホストまでを利用する。
https://www.rem-system.com/centos-nginx-inst/

CentOS 7のnginxでPHP７を利用する。最短でPHP７系の環境を構築する手順。
https://www.rem-system.com/centos-nginx-php/

Nginxセキュリティ設定
https://qiita.com/hideji2/items/1421f9bff2a97a5e5794

SSL評価サイトでA+を取る設定
https://jyn.jp/ssl-aplus/

# インストール

```
vi /etc/yum.repos.d/nginx.repo

[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/mainline/centos/7/$basearch/
gpgcheck=0
enabled=1
```

```
yum install nginx
nginx -v
# nginx version: nginx/1.17.2
systemctl start nginx
systemctl enable nginx
```

http://IP
でウェルカムページが見れるはず。

# 設定

```
cd /etc/nginx/
cp -p nginx.conf nginx.conf.org
vi nginx.conf

# バージョンの非表示 server_tokens off;
http {
    server_tokens off;
    include       /etc/nginx/mime.types;

# gzip圧縮の有効化 コメントされている
gzip  on;

# 長いバーチャルホスト名への対応
# 日本語ドメインなどで見られる長いバーチャルホスト名を設定すると、エラーになることがあります。その回避として以下の設定を行います。
server_names_hash_bucket_size 128;

# キープアライブのタイムアウト秒数を変更
keepalive_timeout  3;
```

```
# 構文チェック（ファイルパスが間違っていても教えてくれないので、パスには注意）
nginx -t

systemctl restart nginx
```

# バーチャルホスト

```
vi /etc/nginx/conf.d/vhosts.conf

server {
    listen 80;
    server_name example.com;
    access_log /home/example/logs/access_log main;
    error_log /home/example/logs/error_log;
    root    /home/example/public_html;

    location / {
        index   index.php index.html index.htm;
    }

    location ~ \.php$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }
}
```

```
nginx -t
systemctl restart nginx
```

# SSL

```
vi /etc/nginx/conf.d/vhosts-ssl.conf

server {
    listen   443 ssl;
    server_name example.com;
    access_log /home/example/logs/ssl_access_log main;
    error_log /home/example/logs/ssl_error_log;
    root    /home/example/public_html;

    location / {
        index   index.php index.html index.htm;
    }

    location ~ \.php$ {
        fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
    }

    ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers HIGH:!RC4:!MD5:!aNULL:!eNULL:!EXP:!LOW:!MEDIUM;
    ssl_prefer_server_ciphers on;
    add_header Strict-Transport-Security 'max-age=31536000;';
}
```

# セキュリティ

- NginxはデフォルトでTRACEメソッドは許容していない
- デフォルトでインデックスページ(ディレクトリー内のファイル一覧)は非表示になっている
Salesforce提供しているAPI

| API 名             |プロトコル               |データの形式         |通信                         |
|:-------------------|:------------------------|:--------------------|:----------------------------|
| REST API           | REST                    | JSON、XML           | 同期                        |
| SOAP API           | SOAP (WSDL)             | XML                 | 同期                        |
| Chatter REST API   | REST                    | JSON、XML           | 同期 (写真の処理は非同期)   |
| ﾕｰｻﾞｲﾝﾀｰﾌｪｰｽ API   | REST                    | JSON                | 同期                        |
| Analytics REST API | REST                    | JSON、XML           | 同期                        |
| Bulk API           | REST                    | CSV、JSON、XML      | 非同期                      |
| ﾒﾀﾃﾞｰﾀ API         | SOAP (WSDL)             | XML                 | 非同期                      |
| ｽﾄﾘｰﾐﾝｸﾞ API       | Bayeux                  | JSON                | 非同期 (データのストリーム) |
| Apex REST API      | REST                    | JSON、XML、カスタム | 同期                        |
| Apex SOAP API      | SOAP (WSDL)             | XML                 | 同期                        |
| Tooling API        | REST または SOAP (WSDL) | JSON、XML、カスタム | 同期                        |

※参照URL（どの API を使用するか?）
https://help.salesforce.com/articleView?id=integrate_what_is_api.htm&type=5
強化学習１　Pythonのインストール

強化学習を学ぶために、１００回くらいに分けて進めます。
最初の１０回位は環境の準備になります。

最初のあたりは、Google　Colaboratoryを活用するほうがいいので、強化学習２８以降に進んだほうが楽かもしれません。
Google　Colaboratoryはバージョンが古い可能性もあるので、注意が必要です。
（２０１９年１２月４日追加）

以下は、パソコンに環境構築する場合です。
Pythonをインストールします。

最初のスタートは１０年前のノートパソコンです。
ASUS　ASPIRE1410
CPU Celeron SU2300
RAM 2GB
HDD 250Gb

とても古くて、低スペックです。
OS　Lubuntu　18.04

この低スペックでありながら、サクサク動くのはLubuntuの力によるところが大きい。

Pythonは最初から3.6.8が入っています。
コマンドはpython3のように３をつけます。

これはこれでいいのですが、Anacondaもインストールします。
Anacondaからダウンロードして、インストールします。
このあたりは、いろんなサイトに書かれているので、詳細は省きます。
Anacondaの最後にconda　initするかと聞いてきたので、yesしました。

```bash
conda -V
jupyter notebook
```
で確認します。
webブラウザで
http://localhost:8888
で開きます。
使い方は、たくさんあります。

Jupyter notebookを使うと、開発が楽になります。


Anacondaのインストールにより、baseが3.7.4になりました。

ちなみに本機ではここまではサクサクと動いてくれました。
THETA Vを延長USB＋USBハブ有線でUnityしたら動作不良

延長USBなしでは動作していたが

USBハブにバスパワーないタイプだったのが原因か
延長有線したらTHETAでLiveを設定してもカメラモードに勝手に戻ってしまった。。

延長USBしてるのを
PCに直接したら動作した。。
【vba】FunctionプロシージャとSubプロシージャの違いをまとめる【個人用】

# はじめに
vbaのFunctionプロシージャとSubプロシージャについて忘れないように使い方のポイントを軽くまとめます。

##プロシージャとは
プロシージャとはモジュール内にある
VBAの複数の処理のことである。

種類としてはSubプロシージャとFunctionプロシージャの2種類がある。

## SubプロシージャとFunctionプロシージャの違い

###Subプロシージャは
・単独で実行することができる
・マクロなどの実行画面ではSubプロシージャが出てくるがfunctionは出てこない
・返り値を返すことができない
・イベント系のプログラムは基本的にSubになっている

### Functionプロシージャは
・呼ばれて動く
・呼ばれるために作る
・functionは関数であるため引数が必要
・返り値を返すことができる
・Subプロシージャから呼ばれて使われることがほとんど(単独で動くことができないから)
・基本的にcallで呼ばれるのでプログラム開始時に利用できない
・基本的にcallで呼ばれるのでプログラム終了時に利用できない

##使いわけ
引数が必要かどうか、返り値を出すものなのか
呼ばれる前提の処理なのか
この辺で個人的にはsubかfunctionを使いわけていきたいと思っテイル。(今の段階では)

サブルーチン化されたプログラムではFunctionプロシージャのありがたみを感じるらい

終わり。
Ruby Seleniumで病院の予約を自動化(の一歩手前まで)

#自己紹介
当方、プログラミングはほぼ初心者です。
おかしなところなどありましたら、お教えいただけますとありがたいです。

#きっかけ
うちの子供が通っている小児科は、webの予約システムを導入しています。
ただ、こちらの小児科は予約が超激戦で…。
毎回手で操作して予約を取っては、予約番号に一喜一憂するのに限界を感じたため
自動化することにしました。
ドクターキューブという予約システムの、（ほぼ）自動化プログラムです。

メールアドレスの認証が済んでいる前提です。
最後の画面は自動化していません。
今後は、予約開始時間になったら自動的に動くようにしたいと思っていますが
そこまで至っていません。

#環境
Windows10
Ruby 2.5.5
Selenium-webdriver 3.142.6
Firefox 70.0.1

#準備

###gemをインストール
```
gem install selenium-webdriver
```

#実行
ID/PASSを同じプログラムで保存しているのは危ないと思いつつ
家庭内で回すだけのものなので、簡便に作りました。

```ruby:yoyaku.rb
driver = Selenium::WebDriver.for :firefox #firefox起動
driver.manage.timeouts.implicit_wait = 60 # driver全体に、wait処理をする(最大60秒)

#URL/ID/PASS
url = 'https://ssc●.doctorqube.com/●●●/'
id = '●●●'
pass = '●●●'


#サイトにアクセス
driver.navigate.to(url)

#「予約をとる」をクリック
driver.find_element(:xpath, '//*[@id="yoyakuset"]').click

#当院での受診ははじめてですか？「いいえ」をクリック
driver.find_element(:xpath, '//*[@id="yoyaku"]/div/div[2]/div[2]').click

#ID/PASSを入力
driver.find_element(:xpath, '//*[@id="c_code"]').send_key(id)
driver.find_element(:xpath, '//*[@id="c_pass"]').send_key(pass)
driver.find_element(:xpath, '//*[@id="yoyaku"]/div/div[2]/form/input[5]').click

#Emailアドレスを確認（アドレス欄がブランクになる場合は、send_keyでアドレスを送る）
driver.find_element(:xpath, '//*[@id="yoyaku"]/div/div[3]/form/input[5]').click

#当日の診療予約
driver.find_element(:xpath, '//*[@id="yoyaku"]/div/div[2]/ul/div[1]').click

#予約（ここは手で操作。2つめのリンクなら末尾がdiv[2]、3つめならdiv[3]）
#driver.find_element(:xpath, '//*[@id="yoyaku"]/div/div[2]/ul/div[1]').click

#ブラウザを終了する（↑を自動化するまでは使わない）
#driver.quit
```

##参考にした記事
・Seleniumコマンドチートシート【Ruby】
https://qiita.com/wMETAw/items/8ea0ff9c7a63ca6134b9

・RubyでSeleniumを使ってスクレイピング
https://qiita.com/tomerun/items/9cb81d7a98150ff22f53
processing-javaでスケッチを実行する方法(メモ)

# 授業でprocessingを使っている弊学の皆さん
- 標準エディタ使いにくくないですか?

# processingの標準エディタを使いたくない！！
- お好きなエデェタでprocessing-javaを使いましょう

# processing-javaのインストール方法
- macならprocessingをインストールした後、ツールから「processing-javaをインストール」を選択

# 実行方法
- ディレクトリ構造

```
    Processing                # 作業フォルダ
    ├─ sketch                 # スケッチ毎のフォルダ
        └─   sketch.pde       # スケッチ
```

- コマンド

```
$ processing-java --sketch=$(pwd)/sketch --run
```

- sketchがフォルダを指定していることに注意

# 感想
- proessingのファイル構造に一瞬戸惑ったけど、よくよく考えるとこういう構造だったなーと
Notice: Undefined indexエラー

気づけばプロ並みPHPを進める上で

$staff_code=$_POST['staffcode'])

の部分がなぜかNotice: Undefined indexエラーと表示されます。

綴りはあってるはずなのでググってみると
$_POSTなどで受け取る時によく発生するエラーらしい事が分かりました。

Notice: Undefined indexエラーとは、未定義の配列の要素を使用した時に出るエラー。

$staff_code=(!empty($_POST['staffcode']))

↑に変更する事で解決しました。





参考URL:https://qiita.com/wakahara3/items/bb7c8d7a1673b161abe7
AmazonPay導入

# 参考URL

Amazon Pay Self Check Sheet (Onetime Version)
https://pwa.geekylab.net/selfcheck/index.html

Amazon Pay API Reference Guide
https://developer.amazon.com/ja/docs/amazon-pay-api/intro.html

Amazon Pay インテグレーションガイド
https://developer.amazon.com/ja/docs/amazon-pay-onetime/intro.html

AmazonPay管理画面
https://sellercentral.amazon.co.jp/gp/homepage.html/ref=xx_home_logo_xx

Amazon Payを使ったカード決済(PHP)でハマった箇所と実装まとめ
https://qiita.com/arawow/items/8d9b4b5434a48332b246

Amazon Payの実装でつまづきやすいこと一覧
https://qiita.com/shg10/items/71f1eba9653732a7b45f

販売事業者向けヘルプ
https://pay.amazon.co.jp/help/201212200

Amazon Pay Widget Code Generator
http://amzn.github.io/amazon-pay-sdk-samples/code_generator/?region=JP

# Amazon Pay手数料

- デジタルコンテンツ以外（物理的商品・サービス等） : 4%
- デジタルコンテンツ : 4.5%

# 準備金

準備金とは
https://pay.amazon.co.jp/help/201212300

# 申し込み・審査

審査に2週間かかる。
その間もテストはできる。

# 注意点

Amazon Pay インテグレーションガイドに書いてあります。

- アドレス帳とお支払い方法ウィジェットが表示された場合は、購入者はセッションが切れるまでに60分間あります。
- **Amazon Payのポリシーでは、注文された商品を出荷してから売上請求しなければなりません。よって、商品を出荷する前に売上請求してはなりません。**
- 資金を回収するためには、本番環境モードではオーソリに成功してから30日以内に売上請求（Capture）APIを呼び出します。テスト環境モードでは2日以内です。30日を過ぎた場合は、Amazonによってオーソリオブジェクトは Closed状態にします。
- 注文商品の出荷が完了した場合にOrder ReferenceをOpenまたは Suspended状態からClosed に変更し、これ以上のオーソリをリクエストできないようにします。追加のオーソリを行う必要がない場合は Closed にすることをお勧めしますが、部分出荷などで分割請求した場合は残存する請求ができなくなりますので、すべてが完了するまで、もしくは、これ以上の金額追加がない場合のみOrder Referenceを Closedにしてください。
- Amazonは注文支払が完了したことをOrder ReferenceがClosed されたとして購入者に示します。別の方法では、購入者はAmazon PayのWebサイト上でトランザクションを確認できます。Order Referenceは Closedにしていなければ180日間はOpen 状態で表示され、180日以降はAmazonがOrder ReferenceオブジェクトをExpired の理由コードを付けて Closedにします。

# 流れ

1.ログインボタン表示
2.ログイン画面表示
3.ログインするとリダイレクト
4.URLのハッシュ（アンカー）として、アクセストークンが渡ってくるので、取得
5.住所ウィジェットとカードウィジェットを表示（住所に応じて使用可能なカードが変わるので、同時に表示する）
6.住所ウィジェットを表示するAPIをたたくと、orderReferenceIdを取得できるので、これも保存
7.アクセストークンとorderReferenceIdをPOSTするなどして次の画面へ遷移（どの住所・カードを選択したかは、（おそらくクッキーあたりに）保存されているので特に保存は必要なし）
8.アクセストークンとorderReferenceIdを使用して、GetOrderReferenceDetailsで住所を取得可能
9.注文内容が確定したら、setOrderReferenceDetails（注文セット）→confirmOrderReference（注文確定）→authorize（オーソリ）でオーソリまで行う
10.商品を発送したら、AmazonPayの管理画面で、売上請求処理でカードから引き落とし

以上

# インスタント支払通知

OrderReference通知
Authorization通知
Capture通知
Chargeback通知
Refund通知

それぞれ発生した場合やclose時に通知が来ます。
OrderReferenceからAuthorizationの情報（そこからさらにCaptureの情報も）は取得できるのですが、Refundの情報が取得できません。Chargebackは知りません。
ので、Capture通知とRefund通知は確認して、金額を保存したほうがいいです。
それぞれ複数発生するので、orderとの１対多で保存しましょう。

# 住所取得の際の注意

GetOrderReferenceDetails→$result['GetOrderReferenceDetailsResult']['OrderReferenceDetails']['Destination']['PhysicalDestination']
で取得します。その中身は
https://developer.amazon.com/ja/docs/amazon-pay-api/address.html
になってます。
テストアカウント住所と実際の自分のアカウント住所とでいくつか違いがありますので、注意が必要です。
特に

- City

は「日本では利用できません。」となっているように、取得できません（テストアカウント住所では取得できます）。

- AddressLine1

に市とか入っています。
基本的には、

```
'address' => @$PhysicalDestination['StateOrRegion'] . ' ' . @$PhysicalDestination['City'] . ' ' . @$PhysicalDestination['AddressLine1'] . ' ' . @$PhysicalDestination['AddressLine2'] . ' ' . @$PhysicalDestination['AddressLine3'],
```
という感じで大丈夫かと思います。
.NET CORE でXunitで単体テストをする

関わっている案件が半年ほど前に変わり、単体テストを作りながら実装するようになって思ったことをまとめます。

## そもそも単体テストとは
Googleで「単体テスト」で検索するとトップに出てきた記事の引用です。
>単体テスト（ユニットテストと呼ばれることもあります）は、プログラムを構成する比較的小さな単位（ユニット）が個々の機能を正しく果たしているかどうかを検証するテストです。
>通常、関数やメソッドが単体テストの単位（ユニット）となります。 プログラムが全体として正しく動作しているかを検証する結合テストは、開発の比較的後の段階でQAチームなどによって行なわれることが多いのとは対照的に、単体テストは、コード作成時などの早い段階で開発者によって実施されることが多いのが特徴です。
https://www.techmatrix.co.jp/t/quality/unittest.html

## 書いてみる
### 環境
- Visual Studio Code 1.40.0
- dotnet core 2.2
- Moq 4.13.1
- 拡張機能 .NET Core Test Explorer

### テスト
```TargetClassTest.cs
public class TargetClassTest
{
    [Fact(DisplayName = "名前が生成される")]
    public void Test1()
    {
        var mockservice = new Mock<IService>();
        mockservice.Setup(x => x.Exist(It.IsAny<string>())).Returns(false);
        var target = new TargetClass(mockservice.Object);
        var response = target.CreateName("hogehoge");
        Assert.True(response == "Test.hogehoge");
    }

    [Fact(DisplayName = "登録済みのためエラー")]
    public void Test2()
    {
        var mockservice = new Mock<IService>();
        mockservice.Setup(x => x.Exist(It.IsAny<string>())).Returns(true);
        var target = new TargetClass(mockservice.Object);
        var ex = Assert.Throws<Exception>(() => { return target.CreateName("hogehoge"); });
        Assert.True(ex.Message == "already exist.");
    }
}
```
### テスト対象
```TargetClass.cs
/// <summary>
/// テストするクラス
/// </summary>
public class TargetClass
{
    private readonly IService service;
    public TargetClass(IService service)
    {
        this.service = service;
    }

    public string CreateName(string name)
    {
        if (service.Exist(name) == true)
            throw new Exception("already exist.");

        var result = $"Test.{name}";
        return result;
    }
}

/// <summary>
/// Injectionされるサービス
/// </summary>
public interface IService
{
    bool Exist(string name);
}
```
### 要点
- アトリビュートでテストの内容がファイルを開かなくてもわかるように記述
- DIされるサービスはMockを使用してテスト項目は対象クラスのみに限定する
- Assertでレスポンスが期待値か確認する
- Exceptionを発生させる場合は、Throwsで何のExceptionか指定して受け取り、Message等を確認する


## 最後にテストの必要性
「対価」の有無で決まると思います。
クライアントがいて納品が発生するならテストは必要でしょうし、自身の業務の効率化・自動化のためのツール程度であれば不要。
（後者はテストしたいならしてもいいと思います）

テストは引用の中にもあるように「機能を正しく果たしているかどうか検証する」ことを目的としているので、
**「テスト」≒「設計」** であることを忘れないようにしたいです。
KubernetesにPVを利用してmattermostをdeployする

# 目的
mattermostの公式サイトのkubernetesのmanifestを参考にしながら、PVを使って永続データ化した形でmattermostをdeployする方法をまとめます。作ったmanifestは[iguchikoma/mattermost-kubernetes](https://github.com/iguchikoma/mattermost-kubernetes)に置いておきました。

# 参考
https://github.com/mattermost/mattermost-docker/tree/master/contrib/kubernetes
https://github.com/iguchikoma/mattermost-kubernetes

# 手順
## 1. PV用のdirectoryをnfs上に作る
mattermostが内部で使っているDB serverであるPostgreSQLのPVを作る。

```bash:bash
root@vagrant:/export/nfs# mkdir mattermost-postgres-pv
root@vagrant:/export/nfs# chmod 777 mattermost-postgres-pv
```

## 2. Manifest一式をgithubから取ってきてdeployする
```bash:bash
vagrant@vagrant:~/temp$ git clone https://github.com/iguchikoma/mattermost-kubernetes.git
vagrant@vagrant:~/temp$ cd mattermost-kubernetes/
vagrant@vagrant:~/temp/mattermost-kubernetes$ kubectl apply -f mattermost-ns.yaml
vagrant@vagrant:~/temp/mattermost-kubernetes$ kubectl apply -f .
```

## 3. Web browserでアクセスして起動確認
```bash:bash
vagrant@vagrant:~/temp/mattermost-kubernetes$ kubectl get svc -n mattermost
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
db           ClusterIP   10.108.192.27   <none>        5432/TCP       5m37s
mattermost   NodePort    10.102.40.36    <none>        80:30001/TCP   5m38s
vagrant@vagrant:~/temp/mattermost-kubernetes$
```
NodePortが30001であることを確認。

http://[k8s-node-ip-address]:30001　でWebアクセスする。

<img width="546" alt="スクリーンショット 2019-11-12 9.12.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76498/b9187850-563f-95d7-359d-86a7a93d1c05.png">
Vulcain - GraphQLとRESTの良いところを両立する通信プロトコルがすごい

Vulcain というHTTP2を使った通信プロトコルとそのリファレンス実装が先月発表されました。

このプロトコルはGraphQLとRESTの良いところを両立するという画期的なプロトコルです。
GraphQLは柔軟なクエリで通信のラウンドトリップを減らすことができますが、HTTPのキャッシュ機構が効かないなどHTTPの良さを潰してしまうという問題があります。Vulcainはドラフトなものを含むHTTP2の仕様をフル活用し、さらにいくつか仕様を追加することで、REST APIのままGraphQLのような柔軟なクエリを発行し、ラウンドトリップを減らすことができるというものです。通信プロトコルはIETFでの標準化を目指すようです。

そして素晴らしいことにGraphQLのクエリがそのまま使えるそうです。
https://github.com/dunglas/vulcain#see-also

[GitHub](https://github.com/dunglas/vulcain) にかなり詳しく図有りでプロトコルの説明が書かれています。図だけでもかなりイメージできると思います。

作者さま曰く 「you don't need #GraphQL anymore!」
https://twitter.com/dunglas/status/1182685694306721798

Vulcain はIssueやコードを見ると Cache-Digests や Early Hints など[@kazuho](https://twitter.com/kazuho)さんがHTTP2で提案したもののあまり進展しなかった仕様を積極的に参照しているのも非常に面白いところです。

[作者のKévin Dunglasさん](https://github.com/dunglas)は、PHPの有名なフレームワークであるSymfonyのコアチームの方で、他にも多数のOSSを開発している実力派です。GoのviperやcobraはGo開発者にはかなり有名なのではないでしょうか。

実利用にはまだまだ課題がありそうな気がしていますが、非常に画期的だと感じます。
これから発展していくプロダクトだと思いますが、期待して注視していきたいプロダクトです。

## その他

 - [Hacker News](https://news.ycombinator.com/item?id=21239932)
初心者がオススメするNuxt.jsの良いところ！

#はじめに
この記事はJavaScript初心者がNuxt.jsを触ってみて良いなと思ったところをオススメする記事です。
技術的な良いところについては深掘りしませんのでご了承ください。

#Nuxt.jsとは

###Nuxt.js
Nuxtは、Vueの公式ガイドラインに沿って強力なアーキテクチャを提供するように設計されたフレームワークです
[Nuxt公式ホームページ](https://ja.nuxtjs.org/guide/ "Nuxt公式ホームページ")

これだけでは「Vueってはじめて聞いたし、なんのこっちゃわからん」となった私。

そこで私なりにJavaScriptやVueとの関係性をまとめてみました

###私なりにまとめた図（個人の見解です）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528371/6a380bfc-5bce-dcd8-4dd1-563b1fd2926d.png)

ふむふむ、Nuxtとは、Vueフレームワークにさらに規約・設定を足して、強力なアーキテクチャを提供することができるんだな！と理解。

#Nuxt.jsの良いところ３つ

###(1) 学習導入コストが低い！
#### 導入に必要なもの
 * VSCode（他のでも良い）
    * VeturとJapaneseのみインストールしました
 * Node.js
 * 頑張る！という気持ち

#### create-nuxt-appパッケージをインストール

 * インストールしてすぐコマンドでサーバー起動ができる！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528371/462cf100-4dd9-82da-1c09-39a182d27728.png)

 * ソースを修正しながらすぐに動きを確認できる！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528371/2e6e7a54-7ec7-fc0d-64e1-cf4d4625a9ad.png)

細かいサーバー設定などが不要なので、すぐに動くプログラムを確認しながら
実際のソースコードを記載して試すことができます。

###(2) 公式ドキュメントの充実性

####日本語版対応の公式ドキュメント
[Vue.js公式ドキュメント]( https://jp.vuejs.org/v2/guide/ "Vue.js公式ドキュメント")
[Nuxt公式ドキュメント](https://ja.nuxtjs.org/guide/ "Nuxt公式ドキュメント")

チュートリアルから、教科書のような記載から、APIの詳細まで記載されているので
わざわざ参考書を購入する必要がありません！

###(3) 厳格な規約

####ディレクトリ構成
create-nuxt-appプロジェクト作成後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528371/fb99395f-f5fe-2bf2-21e9-a7839452a3fd.png)

Nuxt.jsでは、各ディレクトリに対して、役割・ルールが決められているため
開発者独自のローカルルールなどのディレクトリが存在しません！

 * pages
    * アプリケーションのページ ルーティングファイル
 * store
    * Vuexストアファイル（状態管理を扱う）

#最後に

今までJavaしか触ったことのない私でしたが、Nuxt.jsを1ヶ月触ってみて、「設定よりも規約」思考のフレームワークも良いところいっぱいあるなと思いました。
目的によって手段を使い分ける上では、いろんな選択肢を持つのは悪くないなと思いますので、引き続きNuxt触っていきますー！
【学習ノート】AWS SAA取得に向けて(CloudWatch,CloudTrail)

# 運用支援サービス

## CloudWatch

定期的にリソース状態を取得し、問題があれば運用者へ通知する
CloudWatchには安定運用をサポートする以下3つの機能がある

- CloudWatch
- CloudWatch Logs
- CloudWatch Events

## CloudWatch

CloudWatchのメイン機能
AWSリソース状態を定期的に取得し、この状態を***メトリクス***と呼ぶ

- 取得対象の例
    - EC2のCPU利用率
    - Lambda関数ごとのエラー回数

上記の例のようにaws側であらかじめ定義されているメトリクスを***標準メトリクス***と呼ぶ
[<標準メトリクスの一覧>](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/aws-services-cloudwatch-metrics.html)
一方、利用者が定義した値をCloudWatchへ引き渡すことで独自のメトリクスを作成できる。
これを***カスタムメトリクス***と呼ぶ。
これらのようなメトリクスを選択し、アラームを定義することができる。

- アラーム設定の例
    - 対象EC2インスタンスのCPU利用率が80%を上回るとき
    - 定期実行されるLambda関数が一定期間に3回以上エラーを出したとき

アラーム条件をみたした時、SNSへ通知するような設定も可能。
その場合、SNSからLambda関数を呼び出してEC2の設定を変更したり、運用担当者へメールを送信したりといった設定が可能。

## CloudWatch Logs

アプリケーションやApacheなどのログをモニタリングするサービス
収集したログに対してアラームを設定することができ、アプリケーションログに「ERROR」から始まる行があった場合、といったように閾値を設定できる。
CloudWatchと同様にアラームをトリガして処理を実行することが可能
***CloudWatch　Logsの導入により、アプリケーションレイヤーの監視も可能となる。***

- 利用準備
    - 独自エージェントをインストールが必要
        - エージェントを介してCloudWatchへログを送信する
    - ログ送信元のEC2インスタンスへCloudWatchのIAM権限を付与する

## CloudWatch Events

独自のトリガと何かしらの後続アクションとの組み合わせを定義するサービス
より疎結合な形でサービス間の連携をはじめ、後からターゲットを追加することも可能

- イベントソース
    - 大きく2つの独自トリガー
        - スケジュール
            - 期間・時間ベースのトリガー定義
        - イベント
            - AWSリソースの状態変化をベースとしたトリガー定義
- ターゲット
    - 後続アクション

# CloudTrail

- AWS上の操作ログを取得するサービス
    - 「誰が」「いつ」「どこで」「どのような操作をしたか」といった監査のログ
- CloudTrailで扱うログは以下の2種類
    - 管理ログ
        - コンソールログイン、EC2インスタンス作成など、AWS上の操作ログ
        - デフォルトで***有効***になっている
    - データログ
        - S3バケット上のファイル操作、Lambda関数の実行など
        - デフォルトでは***無効***になっている
- 取得したログはデフォルトで90日間コンソール上で確認できる
    - 90日以前のログは証跡を作成することでS3へ保存することができる
        - 有料になります。 [AWS CloudTrail の料金](https://aws.amazon.com/jp/cloudtrail/pricing/)
- CloudWatch Logsと連携して取得したログを、設定したキーワードで監視し、必要に応じて通知することも可能
    - 例としては特定の操作を行ったログが出力されたらメール通知するなど
適当コラムーエンジニアの戯言1 

# 師匠の格言
プログラムを作る際、苦労して作ってはダメだ。楽して作りなさい。そして、楽するために苦労しろ。

これは私の師匠から口すっぱく言われた言葉です。
楽して、というと怠けるイメージっぽくなってしまいがちですが、そういう意味ではありません。

これは私の座右の銘である「急がば回れ」と通じるものがあります。

基本的な動作があり、同じように振る舞う処理は何度もコーディングしてはいけません。それは初心者でも理解している事と思います。しかしながら、納期などの時間に迫られると、似たようなコードをコピペで貼り、その部分に必要な処理だけ修正して…一見別のコードを書いている気になります。

これが苦労にあたります。その場かぎり、今後修正する事は無いし…と思っていても、後に修正作業が発生する事がこの業界の常です。( ん、実は私だけ…？ )
同じ処理を何度も書くと、その分だけ修正する箇所が増え、更には何処が共通範囲かを見失ってしまいがちです。すると、たちまち「バグ」という程のいい言葉で周りに説得しながら、力技ごっこが始まります。

それを解決するのが、楽するために苦労する、という事になります。
これはプログラム言語によりません。またハード言語、更には回路図などソフト屋さん以外にも通じるものがあると思います。

予め仕様を考える段階でそれら共通部を網羅するのは凄く大変です。( 優秀な方は可能でしょうが… )
ですので、先ずはコピぺしたい！という思考が出てきたら実行していくのが良いと私考えます。

コピぺしたい=似た処理(またはほぼ同じ処理)
という事になります。
そこで先ず苦労をしましょう。共通化する関数なりライブラリなりを作りましょう。
引数は沢山とっても構いません。あまりに多い場合は構造体やクラスを作りましょう。分かっちゃいるけど面倒ですよね。苦労ですよね。ファイル分割すると、またひと手間…考えるだけでも面倒です。
ですが、実行しましょう。すると、後々、楽ができます。修正が生じても部分修正で済みます。文言でgrepしてくても良いのです。特に動作に問題が生じた場合、スコープ範囲を気にするのが最小限になります。
特に、何かと通信する部分、の処理がこういう場合に当てはまる場合が経験上多いです。
頑張って引数を取る関数なりを作って共通化で苦労して下さい。

「急がば回れ」
この言葉が凄く好きです。
苦労する前に一息ついて、楽するために遠回りをしてみる、というお話でした。

PS.
実際に実行できている割合は半分程度です笑
スキルを磨かなきゃ、また師匠にダメ出しされちゃう…
bundle installする際のtzinfo-dataのwarningがウザい

# 問題のエラーメッセージ

```
The dependency tzinfo-data (>= 0) will be unused by any of the platforms Bundler is installing for. Bundler is installing for ruby but the dependency is only for x86-mingw32, x86-mswin32, x64-mingw32, java. To add those platforms to the bundle, run `bundle lock --add-platform x86-mingw32 x86-mswin32 x64-mingw32 java`.
```

`bundle install`実行時に毎回上記warningが出ていたのだが、面倒なので後回しにしていた。
そろそろ重い腰を上げて調査・対処してみる。

### 実行環境
macOS Mojave 10.14.6
Ruby 2.6.1
Rails 6.0.1
Bundler 2.0.2

# 問題の原因

Railsアプリを作成した時にGemfileに書かれる下記行がwarningの原因。

```
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
```

[tzinfo-data](https://github.com/tzinfo/tzinfo-data)は[TZInfo](https://tzinfo.github.io/)が参照するタイムゾーン情報を提供するgem。
TZInfoはRubyからタイムゾーン情報を参照し、その情報に基づいて時間をコンバートするためのライブラリ。

# 解決方法

この問題についてググってみると、[githubのtzinfo-dataの作者のコメント](https://github.com/tzinfo/tzinfo-data/issues/12#issuecomment-279554001)に解決方法が書いてあった。

解決方法は4つあって下記の**いずれか**を実行すれば良い。

1. Gemfileのtzinfo-data行の`platforms: [:mingw, :mswin, :x64_mingw, :jruby]`を削除し、`bundle update`を実行。プラットフォーム関係なくtzinfo-dataのタイムゾーンを参照する設定。

2. Gemfileからtzinfo-data行を削除。tzinfo-dataではなくシステムのタイムゾーンを参照するようになる。Windowsの場合は、tzinfo-dataを削除すると、`TZInfo::DataSourceNotFound`例外が発生してしまう。

3. `bundle lock --add-platform mingw, mswin, x64_mingw, jruby`を実行。Gemfile.lockに依存プラットフォーム情報を記述してしまう方法。

4. `bundle config --local disable_platform_warnings true`を実行(Bundlerのバージョンが1.17.0以上であることが必須)。Bundler自体のwarningを出させないようにする設定。

4はカレントディレクトリのRailsアプリにだけ適用する方法で、システムのカレントユーザに対して非表示にしたければ、下記のように`--local`を省いて実行すればOK!

```
bundle config disable_platform_warnings true
```

# Gemfileにtzinfo-dataを指定している理由

解決方法と同じく、[githubのtzinfo-dataの作者のコメント](https://github.com/tzinfo/tzinfo-data/issues/12#issuecomment-279554001)に書いてある。

> The purpose of this line is to include the tzinfo-data gem in the bundle on Windows to act as a source of time zone data. This gem is unnecessary on Ubuntu (and Unix-based systems in general) because the system includes time zone data that can be read directly by tzinfo.

コメントによると、Windowsでタイムゾーン情報を取得することを目的として、tzinfo-dataを入れているらしい。Windowsでtzinfo-dataを削除すると例外が発生するのは、tzinfo-dataがないとタイムゾーン情報が取得できないからのようだ。
そもそもUnixベースのOSではtzinfoからシステムのタイムゾーン情報に直接アクセスできるので、このgemを入れる必要はないそう。
Git操作まとめ 〜Gitの基本コマンド(git add / git commit / git status)

この記事では、Ubuntu18.04LTSにインストールしたGit(version 2.17.1)を使用しています。

Gitを操作する上で、基本的なコマンドの3つを書いていきます。
これらは、開発を進めていく際に常に心がけておく最低限のものです。

個人でバージョン管理を行う上で３つの階層が存在します。開発履歴をそれらの階層を行ったり来たりさせることで、履歴を残して行けます。その3つの階層はいくつかの呼び方がありますが、以下のものになります。

- 作業ディレクトリ(ワークツリー)
- ステージングエリア(インデックス)
- リポジトリ(ローカルリポジトリ)

## コミット状況の確認
Gitの管理下にあるディレクトリの作業ディレクトリとステージングエリアの状態を確認するには、以下のコマンドを使用します。

```shell
git status
```

```shell:実行結果
ブランチ master

No commits yet

追跡されていないファイル:
  (use "git add <file>..." to include in what will be committed)

	README.md

nothing added to commit but untracked files present (use "git add" to track)
```

上記の実行結果では、README.mdというファイルが履歴の追跡対象になっていないことが示されました。
次項目のステージングを行うことで追跡対象に追加することができます。

---

## ステージング

作業ディレクトリで開発を進めたものを、ステージングエリアに移動させることを「ステージングする」といい、以下のコマンドで実行することができます。

```shell:任意のファイルやディレクトリをステージングする場合
git add ファイル名
```

```shell:全てのファイルやディレクトリをステージングする場合
git add .
```

追跡対象になっていなかったファイル"README.md"をステージングしてみます。

```shell
git add README.md
```
```shell
git status
```

```shell
ブランチ master

No commits yet

コミット予定の変更点:
  (use "git rm --cached <file>..." to unstage)

	new file:   README.md

```

これで、ステージングエリアにファイルREADME.mdが追加され、コミットの準備が整いました。
引き続いて、commitコマンドを使ってみます。

---

## コミット

ステージングエリアに追加されたファイルをコミットするまでが、履歴追跡の一連の流れになります。以下のコマンドでコミットが可能です。

```shell
git commit "コミット名"
```

```shell:コミットメッセージを一行に納める
git commit -m "コミット名"
```

実際にコミットしてみます。

```shell
git commit
```
コミットコマンドを実行すると、テキストエディタが起動してコミットメッセージの入力を求められます。
Ubuntuではデフォルトで起動するエディタは"nano"ですが設定を変更することで、Vimなどのエディタに変更できます。

初めてのコミットなので、コミットメッセージを"initial commit"として登録します。

登録したあと、確認してみます。

```shell
git status
```

```shell
ブランチ master
nothing to commit, working tree clean
```

これで、コミットできたことが確認できました。

---

### 本記事目次ページ
[Git操作まとめ](https://qiita.com/tsweblabo/items/6aec9d022c08954f5024)
Mysqlに入ってからAccess deniedやgrantないよが出たら

<h1>前提</h1>
・macユーザーでmysql内でアクセス拒否された、no grantが出て解決策見つからないという方向けの参考メモ。
・とはいえ、他にも似た記事があるので自分のメモ用という意味合いが強いです。

<h1>やり方</h1>

１、exitします。
２、以下のコマンドを打ちます。

```
mysqld_safe --skip-grant-tables &
```

３、rootユーザーで入ります。

```
mysql -u root
```

４、
https://qiita.com/yamateion/items/5509484aaf1a02e9cc57
にある文を打ち込みます...が、権限を全て付与したいときは以下のように打ち込みます。

```
create user 'user'@'localhost' identified by 'password';
grant all privileges on *.* to 'user'@'localhost';
```

参考記事との違いは、２文目で*.*としていることです。


<h1>追記</h1>
2番のコマンドを打ったあと、mysqlのプロセスをkillしておかないと、
mysqld_safe A mysqld process already exists
というエラーが出ます。
このエラーが存在していると、２回目以降mysql -uroot で入れなくなります。
よって、

```
ps aux| grep mysqld
```

コマンドをうってプロセスID一覧を取得し、一つ一つkillすると良いです。


<h1>参考文献</h1>
https://qiita.com/yamateion/items/5509484aaf1a02e9cc57
http://www.goofoo.jp/2011/11/1457
とりあえずESlistとprettierでコードフォーマットしたい人へ。Visual Studio Codeで動く設定ファイルをさらしてみる。

ESlintとprettierによるコードフォーマットに興味を持って調べていたのですが、
きっちりとした丁寧な解説をしている記事が多く、、
シンプルに導入方法だけを書いている記事があまりなかったので書いてみます。

##（１）準備
Visual Studio Codeをインストールして、eslintとprettierの拡張機能を入れる。

##（２）npm
npmを初期化する。
特定のプロジェクトフォルダを作り、Visual Studio Codeで開いてから、
コンソールで、以下入力

```
npm init -y
```

##（３）各種パッケージのインストール
```
npm install -D eslint prettier eslint-config-prettier eslint-plugin-prettier babel-eslint
```
eslint、prettier以外に、下記を入れました。

eslint-config-prettier・・・ESlint→Prettierの順に実行し、Prettierの整形ルールを優先する。
eslint-plugin-prettier・・・PrettierをESLint上で実行する
babel-eslint・・・非標準仕様のJSを使えるようにする

##（４）設定ファイルの設置
.eslintrc.jsをプロジェクトフォルダ直下に置きます。
個人的にはjsonよりjsの方が好き。コメントも書けるし。

.eslintrc.js

```
module.exports = {
  root: true, // ルートのルールと見なす。（これ以上上位のルールを確認しない）
  env: {
    browser: true,
    node: true,
    jquery: false, // jQueryを使う場合は、trueにする。
    es6: true
  },
  plugins: ['prettier'],
  extends: [
    'eslint:recommended', // eslint推奨のルールセットを読み込む
    'plugin:prettier/recommended', // prettier推奨のルールセットを読み込む
  ],
  parser: 'babel-eslint', // 非標準仕様で、NGを出さないようにする。
  parserOptions: {
    sourceType: 'module', // es6のモジュールで、NGを出さないようにする。
  },
  globals: { // グローバル変数
    $: false // envのjqueryがtrueなら、こちらはtrueにしなくてもOK
  },
  rules: { // 追加ルール
    'prettier/prettier': [
      "error", {
        "printWidth": 120, // 1行の最大文字数を120文字とする。
        "semi": false, // セミコロンは不要
        "singleQuote": true, // シングルクォーテーションはOK
      }
    ],
  },
}
```

これで、Visual Studio Codeでjsファイルを開くと、
エラーの箇所に赤い波下線が引かれるようになります。

個別に整形する場合は、波下線にマウスオーバーして、「クイックフィックス」を選択。
また、ファイル内全体を整形する場合は、ctrl + shift + pで、eslintと打ち、「ESlint:Fix all auto-fixable problems 」を選択すればOKです。

さらにファイル保存時に自動整形させたい場合は、設定 - 拡張機能 - ESlintから、「Eslint:Auto Fix On Save」にチェックを入れれば、自動整形されます。



（参考）

■ESLintのルールを全部手動で設定するのは大変だからやめておけ
https://qiita.com/khsk/items/0f200fc3a4a3542efa90

■ES5なJavaScriptをESLintとPrettierで改善する
https://www.wantedly.com/companies/askul/post_articles/155377

■Prettier 入門 ～ESLintとの違いを理解して併用する～
https://qiita.com/soarflat/items/06377f3b96964964a65d

■ESLintの設定
https://yokotakenji.me/log/?p=6021