OmniAICreator/Qiita-1.07M huggingface dataset:
Rails Vue の「Hello Vue!」が表示できない

# 起こっていたこと

## ブラウザ

なにも表示されない。真っ白のまま。

## 開発者コンソール

警告が表示されていた。

```
[Vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
```

### その訳

```
[Vue warn]。テンプレートコンパイラが利用できないVueの実行時のみのビルドを使用しています。テンプレートをレンダリング関数にプリコンパイルするか、コンパイラを含むビルドを使用します。
```

# ファイル内容


```hello_vue.js
import Vue from 'vue';
import App from './app.vue'

document.body.appendChild(document.createElement('hello'))

new Vue({
  el: 'hello',
  template: '<App/>',
  components: { App }
})
```

```app.vue
<template>
  <div id="app">
    Hello Vue!
  </div>
</template>
```

```app/views/home/index.html.erb
<%= javascript_pack_tag 'hello_vue' %>
```

# 解決方法

## ググる

```
rails You are using the runtime-only build of Vue where the template compiler is not available.
```

で、検索した結果、

webpack - Rails + webpacker + vue: "You are using the runtime-only build of Vue where the template compiler is not available." - Stack Overflow
https://stackoverflow.com/questions/50473630/rails-webpacker-vue-you-are-using-the-runtime-only-build-of-vue-where-the

の記事を発見。

## 具体的な解決方法

以下のファイルに、1行足せば良いらしい。

```config/webpack/environment.js
const { environment } = require('@rails/webpacker')
const { VueLoaderPlugin } = require('vue-loader')
const vue = require('./loaders/vue')

environment.plugins.prepend('VueLoaderPlugin', new VueLoaderPlugin())
environment.loaders.prepend('vue', vue)
environment.config.resolve.alias = { 'vue$': 'vue/dist/vue.esm.js' }; // <- add alias
module.exports = environment
```

## 採用理由

 `import Vue from 'vue';` がきれいに思えた。

# 採用に至らなかった方法

- `config/webpack/shared.js`に aliasを追加
- `import Vue from 'vue';`を`import Vue from 'vue/dist/vue.esm.js';`に書き換える。

のような修正案しかヒットしなかった。

## その不採用理由
- `config/webpack/shared.js` のファイルがそもそも、なかった。
- import時に`/dist/vue.esm.js`を追記しないといけないことが、めんどくさく思えた。

# 解決した感想
やった！
CREATE SCHEMA文とは

# はじめに
Oracle Databaseには、Oracle7(1992年リリース)の頃から存在しているにもかかわらず、知名度が非常に低い、CREATE SCHEMAというSQL文が存在します。地味すぎて格別にお勧めするほどの機能でもない(あくまでも個人的意見です)のですが、このコマンドが何をするものか、何の役に立つのか、少し光を当ててみよう、というのがこの記事の趣旨です。

# Oracle Databaseにおけるスキーマとは
まず、スキーマとは何でしょう?　特にOracle Databaseしか知らない方には、理解しにくい概念だと思われます。
[マニュアル](https://docs.oracle.com/cd/F19136_01/cncpt/introduction-to-oracle-database.html#GUID-35C20601-E266-486E-987B-7F355DB10DD4)にはスキーマ(データベース・スキーマ)の説明としてこう書かれています。

「Oracle Databaseにおいて、データベース・スキーマとは、論理データ構造またはスキーマ・オブジェクトの集合です。データベース・スキーマはデータベース・ユーザーによって所有され、そのユーザー名と同じ名前になります。 」

この説明ではわかりにくいかもかもしれませんが、テーブルやインデックスのようなデータベースのオブジェクトを格納するための、論理的な集合ないし領域だとお考え下さい。もう少し言い換えると、名前空間とご理解いただくのもいいかもしれません。
他のデータベース製品だとユーザーとスキーマが分かれているものもありますが、Oracle Databaseにおいては、上記引用のとおり、ユーザーとスキーマの名称が常に同じになります。常に同じなのでわかりにくいですし、同じと理解しても特段詰まることもないのですが、厳密には異なる概念です。
実際、マニュアルではユーザーとスキーマを細かく使い分けています。一例を挙げると、`SELECT * FROM SCOTT.EMP`の「SCOTT」はスキーマですし、`GRANT SELECT ON EMP TO KING`の「KING」はユーザーです(ロールでしょ、という茶々はなしで)。

# CREATE SCHEMA文とは
コマンド名称から器としてのスキーマを作るんだな、という想像をするかもしれませんが、実際には、ユーザーを作成すると同時に暗黙的にスキーマも作成されるため、このSQLコマンドでスキーマを改めて作成することはできません。実際、存在しないスキーマ(ユーザー)を指定してもエラーになります。
マニュアルにはスキーマはスキーマ・オブジェクトの集合と書かれていますが、このSQLコマンドは、複数のスキーマ・オブジェクトと、関連する権限を一度にまとめて作成するSQLコマンドとなります。といっても、作成できるスキーマ・オブジェクトは、テーブルとビューだけです。インデックスさえ作成できません。だったらSQLスクリプトでCREATE文を一気に流せばいいのでは、という話になるのですが、CREATE SCHEMA文には以下の利点が存在します。

### CREATE SCHEMA文内のDDL文全体をトランザクションとして扱える
Oracle Databaseは複数のDDL文を一つのトランザクションとしてまとめてコントロールすることができません。しかし、CREATE SCHEMA文はその例外となります。例として、2番目のCREATE VIEW文の内容が誤っているCREATE SCHEMA文を実行した後、構文的に問題のないはずのTEST表を検索してみましたが、作成されていません。
なお、作成先のスキーマは存在している必要があると言いますか、そのスキーマのユーザーで接続しなければいけません。当然ながら、CREATE SESSION, CREATE TABLE, CREATE VIEWの権限も必要です。

```SQL:
SQL> create schema authorization nakaie
  2    create table test (col1 number primary key, col2 varchar2(100))
  3    create view v_test as select * from test where col3 < 10
  4    grant select on v_test to sh
  5  ;
create schema authorization nakaie
*
ERROR at line 1:
ORA-02427: create view failed


SQL> select * from test;
select * from test
              *
ERROR at line 1:
ORA-00942: table or view does not exist
```

SQLスクリプトで1文ずつ実行する場合、失敗した個所と、そこに依存している個所だけ流し直す、という形になります。一方、CREATE SCHEMA文は、問題個所を修正して全体を流し直す形となります。比較すると、CREATE SCHEMA文は再実行が簡単、という利点があります。再実行の処理時間そのものは全体を流し直すCREATE SCHEMA文が不利と言えば不利ですが、問題個所だけうまく抜き出して再実行する作業自体、何度もやり直してようやく成功、というパターンもあるので、修正作業時間全体の観点では、どらかが絶対的に有利、というのはないと思います。


### CREATE SCHEMA文内の実行順を気にする必要がない
先の不成功スクリプトの問題個所を修正した上で、作成順を入れ替えて実行してみます。上から順番に文を眺めると、一見正しくない順番で実行しているSQLに見えますが、以下の通り成功します。

```SQL:
SQL> create schema authorization nakaie
  2    grant select on v_test to sh
  3    create view v_test as select * from test where col1 < 10
  4    create table test (col1 number primary key, col2 varchar2(100))
  5  ;

Schema created.
```

各文をSQLスクリプトで実行する場合は実行順を考慮する必要がありますが、CREATE SCHEMA文の場合、同一文内なら実行順を考慮する必要はありません。上記例のようにビューを先に記述したり、他には参照整合性制約を持つ子表から先に記述してもエラーにならない、といった利点が考えられます。

以上、存在がマイナーすぎて何かを見落としている気がしてならないのですが、CREATE SCHEMA文の紹介でした。
Rangeオブジェクトを配列に変換

```VB
'#######################################
'#
'# Rangeの重複排除配列変換
'# 引数（一列のRangeオブジェクトの.valueプロパティ）
'# 戻値 一次配列
'#
'#######################################

Function RtoA_Uniq(args As Variant) As Variant

    Dim Dict  As Object
    Set Dict = CreateObject("scripting.dictionary")

    Dim arg As Variant

    For Each arg In args
    
        If Not Dict.Exists(arg) Then
        
            Dict.Add arg, 0
            
        End If
        
    Next arg

    RtoA_Uniq = Dict.Keys

End Function
```

```VB
'#####################################
'#
'# Rangeの単純配列変換
'# 引数（一列のRangeオブジェクトの.valueプロパティ）
'# 戻値 一次配列
'#
'#####################################

Function RtoA(args As Variant) As Variant

    RtoA = WorksheetFunction.Transpose(args)

End Function
```

```VB
'指定列で最終行チェック
Function EndRow(x As Integer) As Integer

    EndRow = Cells(Rows.Count, x).End(xlUp).Row

End Function
```


```VB
    'Rangeにドロップリスト配列指定
    RngA.Validation.Delete '既存の入力規則を削除
    RngA.Validation.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Formula1:=Join(items, ",")
```
Arden's rule

正則言語について調べていたら，Arden's ruleというものを見つけたのでメモ．

#Arden's rule
$\Sigma$ をアルファベットの集合とし，$A, B\subset \Sigma^{\ast}$ とする．方程式

```math
X=A+BX
```

を考える．
$(1)$ $\varepsilon \not\in B$ なら，解は $X_0:=B^{\ast}A$ のみ．
$(2)$ $\varepsilon \in B$ なら，解は$A \subset \tilde{A} \subset \Sigma^{\ast}$ なる $\tilde{A}$ を用いて $B^{\ast}\tilde{A}$ と書ける．特に，解のうち（包含関係 $\subset$ について）最小のものは $X_0$ である． 

証明
$X_0$ が解であることは

```math
\begin{align}
A+BX_0
&=A+B(B^{\ast}A)\\
&=A+B^{+}A\\
&=(\varepsilon+B^{+})A\\
&=B^{\ast}A
=X_0
\end{align}
```

となることから従う．
$(1)$ 一意性を示せば良い．任意の$n \in \mathbb{N}$ に対し

```math
\begin{align}
X
&=A+BX
=A+B(A+BX)\\
&=A+BA+B^{2}X\\
&=\cdots \\
&=\sum_{k=0}^{n}B^{k}A+B^{n+1}X
\end{align}
```

である．
今 $n \in \mathbb{N}$ を任意に固定する．$|w|=n$ となる $w \in X$ を任意に取ると，$\varepsilon \not \in B$ より任意の $B^{n+1}X$ の元の長さは $n+1$ 以上であるから，$w \in \sum_{k=0}^{n}B^{k}A \subset X_0.$ $n$は任意だから $X \subset X_0.$
逆の包含関係を示す．$w \in X_0$ とすると $X_0$ の定義から，$n \in \mathbb{N}$ があって $w \in \sum_{k=0}^{n}B^{k}A$ となるが，

```math
\sum_{k=0}^{n}B^{k}A
\subset \sum_{k=0}^{n}B^{k}A + B^{n+1}X
=X
```

だから $w \in X.$ よって $X_0 \subset X.$
$(2)$ まず $X_0$ が最小の解であることを示す．$X$ を任意の解とする．$w \in X$ に対し $Bw \subset BX \subset A+BX =X$ だから，任意の $Y \subset X$ に対し $BY \subset X$ となる． 特に $BX \subset X.$ 帰納的に $B^{k}X \subset X$ となるので $B^{\ast}X \subset X.$ これと $A \subset A+BX=X$ より

```math
X_0
=B^{\ast}A
\subset B^{\ast}X
\subset X.
```

よって $X_0$ が最小の解である．
これにより，任意の解は $X=X_0+Y \ (Y\subset \Sigma^{\ast})$ と書けるので，$Y$ は $Y=BY$ を満たす．従って $Y_0 \subset \Sigma^{\ast}$ を任意として $Y=B^{\ast}Y_0.$ よって $\tilde{A}=A+Y_0$ とおけば

```math
X
=X_0+Y
=B^{\ast}A+B^{\ast}Y_0
=B^{\ast}(A+Y_0)
=B^{\ast}\tilde{A}.
```
カラムのdefault制約をマイグレーションで変更する

### emailカラムのDEFAULT制約を消す

```diff:schema.rb
create_table "users", force: :cascade do |t|
-  t.string "email", null: false, default: ""
+  t.string "email", null: false
end
```

```ruby
class RemoveDefaultRestrictFromUsers < ActiveRecord::Migration[6.0]
  def change
    change_column_default :users, :email, from: "", to: nil
  end
end
```

補足：from-toを省略した `change_column_default :users, :email, nil` の書き方でもdefault制約を消すことはできたのですが、`db:rollback`が失敗します。（元の値が分からなくなるため）

### adminカラムの初期値をtrueからfalseに変える


```diff:schema.rb
create_table "users", force: :cascade do |t|
-  t.string "admin", null: false, default: true
+  t.string "admin", null: false, default: false
end
```

```ruby
class RemoveDefaultRestrictFromUsers < ActiveRecord::Migration[6.0]
  def change
    change_column_default :users, :admin, from: true, to: false
  end
end
```


[Railsでカラムのデフォルト値を変更する方法 \- Qiita](https://qiita.com/toda-axiaworks/items/dcc24c8e4b23318e37f4) にもあるように、`up`, `down`を記述することなくrollbackできる書き方なので便利です :yum:
原因調査の手順

## はじめに

開発したシステムに対して「項目Xの値が10なのはなぜですか？」という問い合わせや、「テスト結果の検証や不具合調査をする際に。こうしたらよいかもという段取りをまとめてみました。


## 1. 状況を確認する

### 確認内容の意図を把握する

「項目Xの値が10なのはなぜですか？」という問い合わせは

  - 単純になぜその値になるのかを知りたい。
  - 10 ではなく20になるはず。
  - 10 になった結果、やりたい作業ができない。

など、様々です。特に３つめのは、項目Xの値が10になることを調査しなくても、やりたい作業ができるようになれば解決します。逆に、項目Xの値が10になる理由が分かっても、やりたい作業ができなければ解決にはなりません。


### 仕様を確認する

正解が分からない状態で調査しても事実が分かるだけで解決しない場合があります。また、「こうなるはずだ」の思い込みで調査をするのは間違った結果につながる恐れがあり危険です。


### 前提条件を確認する

「IEでは動作を保証していないのにIEで動かしている」とか「ゲストユーザーでログインしている」とか、そもそもの前提がダメだからできないということが多々あります。
「それ早く言ってよ」とこちらは思うのですが、問い合わせている方は、いつもやっていることなので「そんなの当たり前じゃん」の一言で済まします。


## ２．データを調査する

### 結果に影響を与える全てのデータを確認する

源泉となるデータ、条件となるデータなど、結果に影響を与える全てのデータの状態を１つずつ確認していきます。ここで重要なのは、「結果に与える全ての値」が「事実としてどのような状態になっているか」を確認することです。
調査の途中で想定と異なる値が見つかっても、まずは全ての値がどうなっているかを確認してください。想定が間違っていることもあります。思い込みで調査をすると深みにハマると抜け出せなくなります。「こうなっているはず」ではなく「こうなっている」という事実の部分を明確にしてください。

### 同じように想定と異なっているデータを探す

DBに登録されているデータであるならば、同じように想定と異なっているデータを探します。そして、そのデータに共通点がないかを探します。

- 同じユーザから登録されているデータ
- 同じ条件値のデータ　など

また、これらのデータを想定通りになっているデータと比較することで、どのような条件のデータが想定通りになっていないかを予測できないか検討します。

### 設定されたタイミングを確認する

不具合が起きた時と現時点では値が変化していることがあります。現時点のデータの状態では想定通りの結果になるが、不具合が起きた時点では、異なる結果になる場合があります。

- 不具合が起きた時は、設定Aの値は別の値だった。
- 不具合が起きた時は、影響を与えるデータが存在していなかった。

ログやバックアップ、データに更新日、更新者、更新機能といった項目を記録している場合もあるので、これらを有効活用しましょう。また、調査を開始するまでの間に他のプログラムが値を変えている可能性がないかも考慮しましょう。

### 他に結果を影響を与えているデータがないかを確認する

「設定Bがされている場合は、設定Aの値に関係なく項目Aの値は10になる」といった自分が知らない仕様がないかを確認しましょう。仕様書にない後付けルールは意外と多かったりします。

有識者に聞くかプログラムを追う、場合によっては議事録を漁らないと分からない内容ですが、可能性として考慮する必要はあります。お客さんのシステム担当者に聞くと「そういえば、追加要望で特別ルール追加されてますよ」みたいな回答が返ってくることもあります。


## ３．プログラムを調査する

### 想定通りに動いているか確認する

プログラムを追えば、なぜそうなっているかは確実に分かります。
但し、検証環境で再現させるまでが大変だったりするので、デバッグ実行での調査は最終手段とした方がよいと思います。デバック実行するにしても、それ以前に仕様の把握やデータの状況を確認しておけば調査はスムーズに進みます。

ここで注意が必要なのは、プログラムの結果は事実であって、想定通りの動作をしていなくてもバグとは限りません。運用直後はともかく、一定期間稼働しているシステムは、その動作で運用が回っています。仕様書のメンテが追い付いていないだけで、何らかの理由で現在の動作をしている可能性も十分考えられるため、安易に修正すると二次災害を招くことになります。


## おわりに

調査は、結果が分かってしまえば大した原因でないけれど、その結果を見つける観点に気づかなかったばっかりに膨大な時間を費やすことが多々あります。みなさんの「調査の際の勘所」があれば、ぜひともコメントよろしくお願いします。
[備忘録]Emacs上でBibTeX管理：Ebib

#1. はじめに
この記事はEmacs上でBibTeXファイルの管理を行うためのパッケージEbibのインストール手順を整理した備忘録です．

現時点ではインストールするだけの内容です．今後，設定や使い方について，適宜加筆するかもしれません．


##1.1 環境
作業環境は以下の通りです．

- MacOS: Catalina 10.15.5
- Emacs: emacsport (Emacs 26.3)

##1.2 関連記事

- macOSへのTeX-Emacs環境の構築全体の流れについては[こちらの記事](https://qiita.com/walking_with_models/items/52a0d0c00aec88903e4b)．

#2. Ebib
BibTeX/BibLaTeXのデータベースを編集するためのプログラム[Ebib](http://joostkremers.github.io/ebib/)をインストールします．[マニュアル](http://joostkremers.github.io/ebib/ebib-manual.html)によれば，Emacsのバージョンは25.1以上であれば利用できます．パッケージリポジトリのMELPAからインストールすることができるとのこと（MELPA-stableにもEbibがありますが，特に指定しない場合はMELPAの方がインストールされます）．そのため，`use-package`を利用しますが，そのインストールやMELPAの登録については[こちらの記事](https://qiita.com/walking_with_models/items/66bedf2316859ae3657e)を参照してください．

##2.1 インストール
###2.1.1 手順
**Step 1:** Emacsで初期化ファイル`init.el`を開き，以下を追加する．

```emacs-lisp:~/.emacs.d/init.el
(use-package ebib
  :ensure t)
```
**Step 2:** 設定を保存し（`C-x C-s`），Emacsを閉じる（`C-x C-c`）．再度，Emacsを起動する．

####コメント
- **Step 1**は，`ebib`がない場合，`:ensure t`で自動的に`ebib`をインストールしてくれます．
- **Step 2**のEmacs再起動時にインストールされます．

###2.1.2 結果
`~/.emacs.d/elpa/`に`ebib`と`parsebib`がインストールされます．

```terminal:~/.emacs.d/elpa/
$ ls -l
drwxr-xr-x  22 hoge  staff   704  6  7 04:21 ebib-20200522.632
drwxr-xr-x   6 hoge  staff   192  6  7 04:21 parsebib-20200513.2352
```

#A. 付録
##A.1 出力結果
###A.1.1 Ebib

```emacs-lisp
Leaving directory ‘/Users/hoge/.emacs.d/elpa/parsebib-20200513.2352’

Compiling file /Users/hoge/.emacs.d/elpa/parsebib-20200513.2352/parsebib.el at Sun Jun  7 04:21:50 2020
Entering directory ‘/Users/hoge/.emacs.d/elpa/parsebib-20200513.2352/’

Compiling no file at Sun Jun  7 04:21:53 2020
Leaving directory ‘/Users/hoge/.emacs.d/elpa/ebib-20200522.632’

Compiling file /Users/hoge/.emacs.d/elpa/ebib-20200522.632/ebib-db.el at Sun Jun  7 04:21:53 2020
Entering directory ‘/Users/hoge/.emacs.d/elpa/ebib-20200522.632/’

Compiling file /Users/hoge/.emacs.d/elpa/ebib-20200522.632/ebib-filters.el at Sun Jun  7 04:21:53 2020

Compiling file /Users/hoge/.emacs.d/elpa/ebib-20200522.632/ebib-keywords.el at Sun Jun  7 04:21:53 2020

Compiling file /Users/hoge/.emacs.d/elpa/ebib-20200522.632/ebib-notes.el at Sun Jun  7 04:21:53 2020

Compiling file /Users/hoge/.emacs.d/elpa/ebib-20200522.632/ebib-reading-list.el at Sun Jun  7 04:21:53 2020

Compiling file /Users/hoge/.emacs.d/elpa/ebib-20200522.632/ebib-utils.el at Sun Jun  7 04:21:53 2020

Compiling file /Users/hoge/.emacs.d/elpa/ebib-20200522.632/ebib.el at Sun Jun  7 04:21:53 2020

Compiling file /Users/hoge/.emacs.d/elpa/ebib-20200522.632/org-ebib.el at Sun Jun  7 04:21:53 2020

Compiling no file at Sun Jun  7 04:21:54 2020
Warning (bytecomp): the function ‘ebib--notes-buffer’ is not known to be defined.
Warning (bytecomp): reference to free variable ‘ivy-minibuffer-map’
Warning (bytecomp): Unused lexical variable ‘ivy-sort-max-size’
Warning (bytecomp): the following functions are not known to be defined: ivy-read,
    helm-marked-candidates, helm-build-sync-source, helm
```
PHP 名前空間を変更した時に一括置換するtips(ripgrep, sd)

ディレクトリ配下のファイル内の特定の文字列を再起的に置換したいことがよくあります。
`grep` と `sed` を使っても良いですが今回は ripgrep と sd コマンドを組み合わせて一括置換します。

## ripgrep

https://github.com/BurntSushi/ripgrep

## sd

https://github.com/chmln/sd

## 例

### 置換する

`Apple` => `Google` に書き換えたい場合

```
> rg 'Apple' -l | xargs sd 'Apple' 'Google'
```

短く書けるので覚えられる！

### 置換する(grep, sed)

同じことをgrep, sedを使ってやるとこんな感じになります。

```
> grep -l 'Apple' ./* | xargs sed -i -e 's/Apple/Google/g'
```

すぐ忘れるので毎回置換方法をググってしまう...。

## 本題

### 名前空間を変更した時に一括置換

`App\UseCase\HogeHoge` から `App\UseCase\Foo\Bar` に
移動した場合

```
> SEARCH='use App\\UseCase\\HogeHoge'
> REPLACE='use App\\UseCase\\Foo\\Bar'
> rg $SEARCH -l | xargs sd $SEARCH $REPLACE
```

名前空間は長くなりがちなので、変数作っていれておくといいかも。
`\` は特殊文字なのでエスケープする。
【Laravel】 MiddlewareのUnit Testで、テストスイート毎に使い捨てのSessionを使う

下記のようなMiddlewareのクラスがあったとします。
リクエストで渡ってきたパラメータの `token`の値を、sessionの中に入れるMiddlewareです。

```TokenToSession.php
<?php
namespace App\Http\Middleware;

use Closure;

class TokenToSession
{
    public function handle($request, Closure $next)
    {
        if (!is_null($request->input('token'))) {
            $request->session()->put('token', $request->input('token'));
        }

        return $next($request);
    }
}
```

## 検証したいこと
そのため、このメソッドをテストするとしたら、

* リクエストパラメータに `token` が入ってきたら、セッションの `token` にトークンが入る
* リクエストパラメータに `token` が入ってこなければ、セッションの `token` に値が存在しない

のテストスイートを書くことになるでしょう。

## セッションのチェック方法
セッションはモック化させるでも良いのですが、ここは「セッションのフリをして、putが呼ばれたら何かしらの場所に実際にtokenを保存してくれるもの」があると便利です。

こういった場合に便利なのが、Laravelで提供されている `NullSessionHandler` を使います。
`NullSessionHandler` は、セッションの永続化をしないハンドラーです。
他には `FileSessionHandler` などがあります。

requestオブジェクトが`handler` の引数に入ってくるので、モック化させたrequestの中に、`NullSessionHandler`を使って生成したセッションオブジェクトを入れてあげれば良さそうです。

## テスト実装
```TokenToSessionTest.php
<?php

namespace Tests\Unit;

use Tests\TestCase;
use Mockery;
use Illuminate\Session\Store;
use Illuminate\Contracts\Session\Session;
use Illuminate\Http\Request;
use Illuminate\Session\NullSessionHandler;
use App\Http\Middleware\TokenToSession;

class TokenToSessionTest extends TestCase
{
    public function setUp()
    {
        parent::setUp()

        // どちらのテストスイートでも必ずセッションを使うので、setUp内でセッションオブジェクトを生成する
        $session_handler = new NullSessionHandler();
        $this->session = new Store('test', $session_handler);
    }

    // GETパラメータにtokenが入っている時は、セッションにtokenが保存される
    public function testHandleTokenIsInSessionWhenTokenIsInGetParams()
    {
        $token = 'dummy_token';

        // requestオブジェクトをモック化
        $request = Mockery::mock(Request::class);

        // $request->input('token') が dummy_token を常に返す
        $request->shouldReceive('input')
                ->with('token')
                ->andReturn($token);

        // $request->session() が setUpで生成したセッションオブジェクトを常に返す
        $request->shouldReceive('session')
                ->andReturn($this->session);

        // action
        $middleware = new TokenToSession();
        $middleware->handle($request, function () {
        });

        // sessionオブジェクトの token の中に、 dummy_tokenが入っている
        $this->assertEquals($token, $this->session->get('token'));
    }

    // GETパラメータにtokenが入っていない時は、セッションにtokenが入らない
    public function testHandleTokenIsNullSessionWhenTokenIsNotInGetParams()
    {
        $request = Mockery::mock(Request::class);

        // $request->input('token') が 何も返さない
        $request->shouldReceive('input')
                ->with('token')
                ->andReturn(null);

        $request->shouldReceive('session')
                ->andReturn($this->session);

        // action
        $middleware = new TokenToSession();
        $middleware->handle($request, function () {
        });

        // sessionオブジェクトの中には token が存在しない
        $this->assertFalse($this->session->has('token'));
    }
}
```
【Swift】構造体のArrayから重複要素を除去する

## はじめに

次のように、重複要素を持つ `Array` から順序を維持して重複要素を除去したい場合を考えます。

```swift:before
["a", "x", "b", "x", "c", "x", "a", "x", "d"]
```

```swift:after
["a", "x", "b", "c", "d"]
```

## NSOrderedSet を使う

Foundation フレームワークには順序付き集合を扱うためのクラス `NSOrderedSet` が提供されています。これを用いることで、順序を維持したまま重複要素を除去できます。

```swift:実装例
extension Array {
  func uniqued() -> Array {
    return NSOrderedSet(array: self).array as! [Element]
  }
}
```

```swift:利用例
let uniqued = ["a", "x", "b", "x", "c", "x", "a", "x", "d"].uniqued()
dump(uniqued)
```

```sh:出力結果
▿ 5 elements
  - "a"
  - "x"
  - "b"
  - "c"
  - "d"
```

とてもカンタンで、とても便利ですね。

## 構造体の Array から重複要素を除去する

ところで、`NSOrderedSet` は Foundation フレームワークで提供されたクラスです。ということは、つまり、Objective-C 互換なオブジェクトでないと使えないのでは？と考えていたのですが、`Hashable` に適合していれば、`NSOrderedSet` を利用することができます。

こんなカンジの適当な Hashable な構造体があって、

```swift:適当なHashable
struct Foo: Hashable {
  var foo: Int
  var bar: Int
}
```

適当に重複要素を持つリストを作ります。

```swift:適当な重複要素を持つリスト
let array: [Foo] = (0...99999).map {
  Foo(foo: $0 % 2, bar: $0 % 3)
}
```

すると、たしかに順序を維持して、重複を除去することが確認できました。

```swift:重複を除去して出力
dump(array.uniqued())
```

```sh:出力結果
▿ 6 elements
  ▿ ***.Foo
    - foo: 0
    - bar: 0
  ▿ ***.Foo
    - foo: 1
    - bar: 1
  ▿ ***.Foo
    - foo: 0
    - bar: 2
  ▿ ***.Foo
    - foo: 1
    - bar: 0
  ▿ ***.Foo
    - foo: 0
    - bar: 1
  ▿ ***.Foo
    - foo: 1
    - bar: 2
```

純粋な Swift の値型にも適用できて、とても便利ですね。

## なぜ構造体を Foundation フレームワークで扱えるのか？
`NSOrderedSet` は Foundation フレームワークで提供されたクラスなので、Objective-C 互換なオブジェクトでないと使えないのでは？と、考えていたのですが、**実はこれ自体は正しいです。**

Swift では、構造体を暗黙的に Objective-C 互換なオブジェクトに変換する仕組みを提供しています。
値型をいったん `Any` 型に変換して、更に `AnyObject` に変換することで、値型から参照型を生成することが可能です。

```swift:参照型を生成して出力する
let foo = (Foo(foo: 0, bar: 1) as Any) as AnyObject
dump(foo)
```

出力結果から、NSObject のサブクラスであることがわかります。

```sh:出力結果
- ***.Foo(foo: 0, bar: 1) #0
  - super: NSObject
```

また、クラス名は `type(of:)` 関数を使用することで、 `__SwiftValue` であることがわかります。

```swift:参照型を生成してクラス名を出力する
let foo = (Foo(foo: 0, bar: 1) as Any) as AnyObject
dump(type(of: foo))
```

```sh:出力結果
- __SwiftValue #0
```

逆に、このオブジェクトに対して、`Any` → `Foo` の順番で変換することで、もとの値型として扱うこともできるみたいです。

```swift:もとの値型を出力する
let foo = (Foo(foo: 0, bar: 1) as Any) as AnyObject
let value = (foo as Any) as! Foo
dump(value)
```

```sh:出力結果
▿ ***.Foo
  - foo: 0
  - bar: 1
```

## `__SwiftValue` と `Hashable`

`__SwiftValue` は NSObject のサブクラスなので、`isEqual` メソッドと `hash` メソッドを実装しています。

`isEqual` と `hash` の実装は、変換前の値型が `Hashable` かどうか判定して、Hashable な場合はこの `==` と `hash(into:)` の実装を呼び出しているように見えました。

**swift/SwiftValue.mm at swift-5.2-RELEASE · apple/swift**

- https://github.com/apple/swift/blob/swift-5.2-RELEASE/stdlib/public/runtime/SwiftValue.mm#L314#L324
- https://github.com/apple/swift/blob/swift-5.2-RELEASE/stdlib/public/runtime/SwiftValue.mm#L328#L336

この実装のおかげで、Swift の `Hashable` が、Objective-C 側の世界の一意性やハッシュ値に一致するので `NSOrderedSet` で重複要素を除去することができるみたいです。

`Hashable` な構造体はこのように、`isEqual`、`hash` を実装した NSObject に変換されるので、`NSOrderedSet` に限らず、Foundation のコレクションの要素として自由に扱えるみたいです。
たとえば、`NSCache<AnyObject, AnyObject>` のキーとしても機能することが確認できました。

とても便利なので、使っていきたい機能だと思いました。
[備忘録]Emacsでスペルチェック

#1. はじめに
この記事はEmacsでスペルチェックを行うための機能の拡張を行う手順を整理した備忘録です．

##1.1 環境
作業環境は以下の通りです．

- MacOS: Catalia 10.15.5
- Emacs: emacsport (Emacs26.3)
- Homebrew: 2.3.0

##1.2 関連記事

- macOSへのTeX-Emacs環境の構築全体の流れについては[こちらの記事](https://qiita.com/walking_with_models/items/52a0d0c00aec88903e4b)．

#2. Aspell
ここではスペルチェッカーIspellの後継であるAspellのインストールと初期設定を行います．Live TeXやEmacsのパッケージではなく，ターミナルから呼び出すことのできるプログラムです．これをEmacsの英作文で利用するというのが私の利用目的です．

##2.1 参考資料
インストール方法や使い方についてはTeX Wikiを参考にしました．

- [Aspell @ TeX Wiki](https://texwiki.texjp.org/?Aspell)

##2.2 インストールの手順
**Step 1:** ターミナルを起動し，以下を入力して実行する．

```terminal
$ brew install aspell
```
**Step 2:** Emacsを起動し，初期化ファイル`init.el`を開いて，以下を追加する．

```emacs-lisp:~/.emacs.d/init.el
(setq-default ispell-program-name "aspell")
(with-eval-after-load "ispell"
  (setq ispell-local-dictionary "en_US")
  (add-to-list 'ispell-skip-region-alist '("[^\000-\377]+")))
```
**Step 3:** 初期化ファイル`init.el`への変更を保存し（`C-x C-s`），Emacsを閉じる（`C-x C-c`）．

####コメント

- **Step 1**では，Homebrewを使ってAspellをインストールします．
 - [Aspell @ TeX Wiki](https://texwiki.texjp.org/?Aspell)にあるように`brew install aspell --lang=en`とオプションで言語を指定するように書いています．これは[hgshrs氏の記事](http://hgshrs.hatenablog.com/entry/20120107/1325922559)の問題を回避するためだと思われます．しかし，このオプションを付けてインストールしようとしたら，`Error: invalid option: --lang=en`というエラーが出てインストールできませんでした．
 - [こちら](https://github.com/Homebrew/homebrew-core/issues/38848)のGitHub上のHomebrewのフォーラムから，そのようなオプションを付けなくても良いっぽいので，とりあえず`--lang=en`オプションを付けずにインストールして，無事スペルチェックできるかを確認します．
- **Step 2**では，一行目でEmacsに組み込まれているIspell用のキーバインドを利用する際にAspellを呼び出すようにしています．3行目では，言語を英語にするように設定しています（[StackExchangeへの投稿](https://emacs.stackexchange.com/questions/30008/hunspell-flyspell-and-emacs-on-windows)を参考にしました）．
 - ターミナルで`$ aspell -c -t hoge.tex`のように言語指定のオプション`--lang=en`を付けない場合，`Error: No word lists can be found for the language "ja_JP".`というエラーが返ってきます．これは[keisanbutsuriya氏の記事](http://keisanbutsuriya.hateblo.jp/entry/2015/02/10/152543)にあるように，日本語の辞書を探してしまっているんだと思います．
 - 上記のkeisanbutsuriya氏の記事では`~/.aspell.conf`というファイルに言語の設定を書くようにしていますが，私の場合，基本的にEmacs上でしか使わないこともあって，無駄に設定ファイルを増やしたくない（できるだけ`init.el`で終わらす）ために3行目`(setq ispell-local-dictionary "en_US")`を書いています．4行目は日本語混じりのTeX文書をチェックするためで，これは日本語の部分をスキップするように指定していると思われます．
- **Step 3**後にEmacsを再起動した段階からAspellを利用できるようになります．


##2.3 Emacs上での使い方

自分の場合，単純に`M-x ispell`と入力して使っています．もっと細かな使い方についてはググりましょう．


#3. Flyspellの設定

Flyspellは文章作成時，誤った単語を入力した場合にリアルタイムでスペルミスを教えてくれる機能です（Microsoft Wordのようにスペルミスの単語に印が付きます）．

これはEmacsにデフォルトで同梱されているモードで，特別インストールは必要ありません．私の場合，`.tex`ファイルをYaTeXモードで開いた際に自動でFlyspellの機能を有効にする形で使います．

##3.1 参考資料
設定にあたっては次の資料を参考にしました．

- [keisanbutsuriya氏のブログ記事「Emacsでスペルチェック」](http://keisanbutsuriya.hateblo.jp/entry/2015/02/10/152543)（2019年12月29日追記部分）

##3.2 設定の手順
**Step 1:** Emacsで初期化ファイル`init.el`を開き，以下をYaTeX呼び出し部分より後に追加する．

```emacs-lisp:~/.emacs.d/init.el
(use-package flyspell
  :hook (yatex-mode . flyspell-mode))
```
**Step 2:** 変更を保存し（`C-x C-s`），Emacsを閉じる（`C-x C-c`）．
要約MEMO: イベント駆動マイクロサービスのセンス、ナンセンス、歩み方

> カンファレンス動画や記事等で中長期の観点でためになりそうなものの要約MEMOです。

以下の動画の要約MEMOです。

[GOTO 2019 • Event-Driven Microservices, the Sense, the Non-sense and a Way Forward • Allard Buijze](https://www.youtube.com/watch?v=jrbWIS7BH70)


Event, Event Sourcing, CQRS等を学んで、とにかく使いたくて仕方ない人にお勧めの動画です。DDD(ドメイン駆動設計)の用語もいくつか出てくるため、そのあたりも知っていた方が良いです。
というかEvent-Driven MicroserviceのためにDDDを学ぶのもありです。

# 要約MEMO

## Box + Box + Cylinderによるアーキテクチャ

- どんどんBoxを追加することでレイヤを増やして依存関係を見えなくする従来のアーキテクチャ。
- フンコロガシが転がす玉のようにフン団子が肥大化していく。ちなみにフン団子に乗っているフンコロガシがアーキテクトとのこと。

## マイクロサービスが救いになる？

- マイクロサービスはAgility + Team Scalabilityを提供してくれるが、新たな複雑性を追加することになる。
- マイクロサービスをどう分けるかが重要となる。
- 名詞でマイクロサービスを作るNoun Driven Designが横行。
- モノリシックサービスのフン団子をマイクロサービスにしても、大量の小さなフン団子になるだけ。
- 大量の小さなフン団子を避けるためにはモジュール性を高める必要がある。
- モジュール性を高めても、怠惰や技術負債などの様々な要因でフン団子になる可能性がある。

## マイクロサービスを救いにするためには？

- カラテキッドという映画における「ワックスがけ」を先に学ぶ。(まずは自己制御などの規律を身につける)
- マイクロサービスを作る前に、まともなモノリシックサービスの作り方を先に学ぶ。
- マイクロサービスの旅(Journey)は、モノリシックサービスから始めて、少しずつマイクロサービスへと発展させていく。あわよくばサーバーレスへと歩む。
- 旅の歩みを着実に進めるために、サービスのLocation Transparencyを保つことが重要となる。
    - Location Transparency: コンポーネントは自分も相手もどのロケーション(ex. マシン、VM)にいるかを意識する必要がない。

## Eventが救いになる？

- Eventを導入することにより、サービスの依存性を逆転させて疎結合にできる。
- 全てをEventにすればいいのか？マズローのハンマーのような確証バイアスに陥る危険がある。
    - Event通知、Event Sourcingなどで全ての釘/問題に対応したくなる？
- 例えばサービス間で全てのEventのデータを複製する仕組みを取ると、各サービスが興味のないEventまで意識する必要が出てくる。
- 複数のサービス間で双方向のやりとりをEventでやるのは、各サービスが「ノドが渇いた！」と宣言した後で口を開けて水を待つような滑稽さ。水を直接飲めばいい。
- Eventで双方向のやりとりをした場合、前述した依存性の逆転は意味をなさなくなる。(双方向を逆転しても双方向)

## マイクロサービスのMessaging種類

- マイクロサービスのMessagingはEventだけではない。
    - Event: 全ての対象サービスに通知する。結果は返らない。
    - Command: 一つのサービスに発行する。確認/結果が返る。
    - Query: ロードバランシングで一つ以上のサービスに発行する。必要に応じて集約したりする。結果が返る。
- Message = Eventではないことを理解する必要がある。
- あるサービスに通知する場合はEventを使用し、情報を取得する場合はQueryを使用する。適材適所。

## Event Sourcingの誤解

- ただ単にEventをストアすればEvent Sourcingなのか？
- 全体の事実をキャプチャするのがEvent Sourcingである。
- Event Sourcingでは状態を保持せず、状態に導くEventを全て保存する。
- Event Sourcingにはビジネス面、技術面の様々な利点がある。(このあたりは色々な記事や動画で言及されてる)
- ストレージサイズや実装の複雑性は既に大きな課題ではない。課題はEventという考え方のみ。状態を考えるのではなく、振る舞いを考えてEventを抽出する。
- では全てをEvent Sourcingにすればいいのか？答えはもちろんNOである。マズローのハンマーに陥ってはいけない。
- 一つのEntityの変化を処理するようなCommandとの相性は良いが、汎用的なQueryとの相性は悪い。
- 上記のQueryとの親和性を高くするためにCQRSを導入すれば良い。
- では全てをEvent Sourcing + CQRSにすればいいのか？答えはもちろんNOである。

## Eventという契約/婚姻

- サービス間でコミュニケーションを行うということは一種の契約であり、婚姻のようなものである。
- Eventが他のサービスに流れたら、その時点でEventが流れたサービスに対して契約/婚姻の関係が発生する。
- Event Sourcingの場合はその中の些細な詳細すらもEventとなるため、意図しない形で上記の契約/婚姻が発生する可能性がある。
- この契約/婚姻の範囲を制限するためにBounded Contextを設けることが重要となる。Bounded Context内のサービスのみがEventという契約/婚姻を結べばよい。
- Bounded Contextを設けるだけでは関係のないサービスにEventが流れることは防げない。このためAnti-Corruptionレイヤを設けて、Bounded Context外のサービスへのEventをフィルタリングしたり変換したりする必要がある。

## まとめ

- Eventだけではなく、CommandとQueryも考慮して使用すること。
- 共有すること(Sharing)は介護すること(Caring)と同じ。Eventは流れたところ全てで共有したことになる。
- Bounded Context間の結合/連結に注意すること。
- マイクロサービスは旅である。はじめにモノリシックサービスからスタートし、マイクロサービスに発展させる。ワックスがけ(Wax-On)から始めよう。
go修行7日目 loggingとか

## 宿題

### 問1: continueとbreakの違いは？
- continue → ループ中の今差し掛かっている処理は実行されず、次のループへ
- break → ループ終了

### 問2: Go言語におけるスイッチ文ではケース式に合致したらそのケースしか実行されない。しかし他の言語ではどうなっているか？複数のケースが実行されてしまうことがある。この言語仕様の名称はなにか？
- 名称 fallthrough（落ちるという意味）
- bashだとGoと同じな気がします

### 問3: 問2における機能をGo言語で実装する方法を答えよ。

```golang

package main

import "fmt"

func main() {
	i := 1
	switch {
	case i < 5:
		fmt.Println("<5")
		fallthrough
	case i < 7:
		fmt.Println("<7")
	default:
		fmt.Println("")
	}
}
```

```
<5
<7
```


## 遅延実行

- 関数内の最後に実行される

```go

package main

import "fmt"

func getOsName() string {
    return "windows"
}
func main() {
    // os := "windows"
    os := getOsName()
    switch os {
    case "mac":
        fmt.Println("Mac")
    case "windows":
        fmt.Println("Windows")
        // defaultなくても大丈夫
    default:
        fmt.Println("Default")
    }
}
```

```
hello foo
world foo
hello
world
```

ファイルを開く処理などで使う

```golang

package main

import (
	"fmt"
	"os"
)

func main() {
	// ファイルを開く
	file, _ := os.Open("./test.go")
	// 処理終了後にファイルを閉じる必要があるのでdeferを使う
	defer file.Close()
	data := make([]byte, 100)
	file.Read(data)
	fmt.Println(string(data))
}
```

```
package main

import (
	"fmt"
	"os"
)

func main() {
	// ファイルを開く
	file, _ := 
```

## ロギング

```golang

package main

import (
	"log"
	"os"
)

func main() {
	// でたらめなファイルを開く
	_, err := os.Open("aaaaa")
	// エラー処理
	if err != nil {
		log.Fatalln("exit", err)
	}
	log.Println("logging")
	log.Println("%T %v", "test", "test")

	// Fatalが実行されると処理が終了する
	log.Fatalf("%T %v", "test", "test")
	log.Fatalln("error")
}
```

```
2020/06/18 21:50:01 exit open aaaaa: The system cannot find the file specified.
```

ファイル書き込み

```golang

package main

import (
	"io"
	"log"
	"os"
)

// loggin関数
func LoggingSettings(logFile string) {
	// 666、読み書き追記できるように作る
	logfile, _ := os.OpenFile(logFile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
	// Stdoutで標準出力もしつつlogging
	multilogFile := io.MultiWriter(os.Stdout, logfile)
	// 時間とか、Llongfileは絶対パス表記
	log.SetFlags(log.Ldate | log.Ltime | log.Llongfile)
	log.SetOutput(multilogFile)
}

func main() {
	LoggingSettings("test.log")
	// でたらめなファイルを開く
	_, err := os.Open("aaaaa")
	// エラー処理
	if err != nil {
		log.Fatalln("exit", err)
	}
}

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293481/ca4d1638-d6a5-d9e3-c91d-fa85bf3234bf.png)
【Rails】多対多のカテゴリー機能の実装

# 目標

![ezgif.com-video-to-gif (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/579893/8224071c-70fc-f8dd-c7b3-4ec67f19d85f.gif)

# 開発環境
・Ruby: 2.5.7
・Rails: 5.2.4
・Vagrant: 2.2.7
・VirtualBox: 6.1
・OS: macOS Catalina

# 前提

下記実装済み。

・[Slim導入](https://qiita.com/matsubishi5/items/b639ffddecc626856039)
・[Bootstrap3導入](https://qiita.com/matsubishi5/items/b117c95f4dd71340cc80)
・[投稿機能実装](https://qiita.com/matsubishi5/items/1a5aeab651b5822d1f2c)
・[カテゴリー機能実装](https://qiita.com/matsubishi5/items/79bd889b57e207d5a2c9)

# 実装

### 1.中間テーブルを作成

```terminal:ターミナル
$ rails g model BookCategory book_id:integer category_id:integer
```

```terminal:ターミナル
$ rails db:migrate
```

```ruby:schema.rb
create_table "book_categories", force: :cascade do |t|
  t.integer "book_id"
  t.integer "category_id"
  t.datetime "created_at", null: false
  t.datetime "updated_at", null: false
end
```

### 2.カラムを削除

```terminal:ターミナル
$ rails g migration RemoveCategoryIdFromBooks category_id:integer
```

```ruby:~_remove_category_id_from_books
class RemoveCategoryIdFromBooks < ActiveRecord::Migration[5.2]
  def change
    remove_column :books, :category_id, :integer
  end
end
```

```terminal:ターミナル
$ rails db:migrate
```

### 3.各モデルを編集

```ruby:book.rb
has_many :book_categories
has_many :categories, through: :book_categories
```

```ruby:category.rb
has_many :book_categories
has_many :books, through: :book_categories
```

```ruby:book_category.rb
# 追記
belongs_to :book
belongs_to :category
```

### 4.コントローラーを編集

`books_controller.rb`のストロングパラメーターで`category_id`を配列可にする。

```ruby:books_controller.rb
def book_params
  params.require(:book).permit(:title, :body, { category_ids: [] })
end
```

### 5.ビューを編集

**①フォームを編集**

```slim:books/index.html.slim
/ 変更前
= f.label :category_id, 'カテゴリー'
br
= f.collection_select :category_id, Category.all, :id, :name, { prompt: '選択してください' }, class: 'form-control'
br

/ 変更後
= label_tag 'カテゴリー'
br
= collection_check_boxes(:book, :category_ids, Category.all, :id, :name) do |cb|
  = cb.label { cb.check_box + ' ' + cb.text }
br
```

`= collection_check_boxes(:book, :category_ids, Category.all, :id, :name) do |cb|`
➡︎ 全カテゴリーの名前をチェックボックスとして表示し、値をidに設定している。

**②テーブルを編集**

```slim:books/index.html.slim
/ 変更前
td
  = category.name

/ 変更後
td
  - book.categories.each do |category|
    = category.name
    | /
```
PRML　演習問題  5.2（基本）　解答

## はじめに
本記事は, 機械学習の教科書の決定版ともいえる, **Christopher Bishop先生**による[**『Pattern Recognition and Machine Learning （パターン認識と機械学習）』**]( https://www.microsoft.com/en-us/research/people/cmbishop/prml-book/), 通称**PRML**の演習問題のうち, 私が解いた問題の解答を記したものです. これは, 私の所属する[生物測定学研究室](https://www.ut-biomet.org/)の輪読会で**PRML**を取り扱っており, その勉強の一環として演習問題を解いたときのものです. なお, 他の演習問題の解答例に関する記事については, [PRML　演習問題　解答集　まとめ](https://qiita.com/Lab_of_Biomet/items/15e38ca34fafa8176d89)をご覧ください.



## 問題
複数の出力を持つニューラルネットワークについて, 条件付き分布

$$
p\left ( \mathbf t ~ | ~ \mathbf x, \mathbf w \right )= N\left ( \mathbf t ~ | ~ \mathbf y\left ( \mathbf x, \mathbf w \right ), ~ \beta^{-1} \mathbf I \right )
\tag{5.16}
$$

の尤度関数最大化は, 二乗和誤差関数

$$
E\left ( \mathbf w \right ) = \frac{1}{2} \sum_{n=1}^{N} \left | \left |\mathbf y\left ( \mathbf x _ { n }, \mathbf w \right )-\mathbf t_n \right | \right |^2
\tag{5.11}
$$

の **最小化（問題文では最大化となっているがおそらく誤植）** と等価であることを示せ。


## 解答
$\left ( 5.16 \right )$ で与えられる条件付き確率分布における尤度は, 以下の式で表される。

$$
\prod_{n=1}^{N} N\left ( \mathbf t_n ~ | ~ \mathbf y\left ( \mathbf x_n, \mathbf w \right ), ~  \beta^{-1} \mathbf I \right )
\tag{5.2.1}
$$
ここで $\left ( 5.2.1 \right )$ を最大化することは, 当然 $\left ( 5.2.1 \right )$ に対数を取ったものを最大化することと等価であるため, $\left ( 5.2.1 \right )$ の対数を取ることを考える。
 すると、

$$
\frac{NK}{2} \ln \left ( \frac{\beta}{2 \pi} \right )-\frac{\beta}{2} \sum_{n=1}^{N} \left | \left |\mathbf y\left ( \mathbf x _ { n }, \mathbf w \right )-\mathbf t_n \right | \right |^2
\tag{5.2.2}
$$

$\mathbf w$ に関して尤度を最大化することを考えると, $\left ( 5.2.2 \right )$ の第1項は無視でき, $\left ( 5.2.2 \right )$ の第2項を最大化することと等価となる。
これは, 二乗和誤差関数 $\left ( 5.11 \right )$ を最小化すること等価であるため, 題意は示された。$\left ( 証明終 \right )$ 

※問題文では $\mathbf w$ に関しての最大化と明言されていないが, そうでなければ問題が成り立たないため, $\mathbf w$ に関しての最大化と考えるのが妥当であろう。
GASでSpreadsheetのデータをGoogle Chatに投稿


# はじめに
スプレッドシートのデータを、Google Chatに投稿したい。
チームのコミュニケーションツールとして、Google Chatを利用している。
スプレッドシートでQA表管理をしていて、未回答のものをGoogle Chatに投稿して回答を促すことに使いたい。


# 手順
1. Webhook URLの取得
やり方は以下参照
[Hangouts ChatにWebhookを使ってメッセージを通知する](https://webree.jp/article/hangouts-webhook/)

2. GASから実行
やり方は以下参照
[Google Apps Script(GAS)からHangoutchatにメッセージを送る](https://webree.jp/article/gas-hangoutchat/)

3. スプレッドシートに登録した内容を取得し、ハングアウトチャットに投稿
上記の投稿するコードに、今まで作ってきたスプレッドシートのデータ取得のコードを組み合わせて完成。
参考）
[【GAS】Googleフォームからの問い合わせをスプレッドシートで管理し、未回答のものだけメール送信する](https://qiita.com/Shin/items/afb6e8ad18a9cade9254)


# コード
```javascript
function sheetsToHangout() {

/* Spreadsheet */
  let sheetName = 'シート1';
  let sheet = SpreadsheetApp.getActive().getSheetByName(sheetName);
  // データ取得範囲指定
  const row = 2;
  const column = 1;  
  const LastRow = sheet.getDataRange().getLastRow();
  const LastColumn = sheet.getDataRange().getLastColumn();
  const numRows = LastRow - row + 1;
  const numColumns = LastColumn - column + 1;

  // データ取得
  let data = sheet.getRange(row, column, numRows, numColumns).getValues();


/* Hangout Chat */  
  // 投稿先指定
  const url = 'WebhookのURL'; // 手順1で取得したURLをセット
  
  for (i=0; i < data.length; i++) {
    // 送信内容作成
    let text = data[i][0];
    let message = {'text' : text}
    let params = {
      'method': 'POST',
      'headers' : {
        'Content-Type': 'application/json; charset=UTF-8'
      },
      'payload':JSON.stringify(message)
    };

    // 送信
    UrlFetchApp.fetch(url, params);
  }
}
```
Storyboard Referenceを使ってつまずいたところ

#はじめに
アプリ制作をしているとMain.storyboardにいろんなViewControllerが並んでしまいメンテナンスがしにくくなったので
StoryBoardを分けることができる```Storyboard Reference```を使ってリファクタリングしてみようと思い、
いろんな記事を参考にしながらサンプルプログラムを動かしてみた。
エラーが出てそれを解決したので記事を書いてみた。

Storyboard Referenceを使ったことがない人は以下の参考文献を参考にしてください！
##参考文献
- [【Xcode】Storyboard Referenceを活用してみた](https://qiita.com/chubura/items/03a3cddf8fe17361c5b2)
- [Storyboard Referenceを使ってみた](https://qiita.com/y-okudera/items/aeef6b2b71088e1e3a7e)


今回は下のエラーが出た人用に記事を書いてみる。
↓↓↓
#エラー文

```swift
: error: Main.storyboard references the initial view controller of A.storyboard, but no designated entry point was found.
Command LinkStoryboards failed with a nonzero exit code
```



#解決方法
1. StoryBoard Referenceの遷移先に移動
2. is Initial View Controllerに✅チェックを入れる
3. 以上

<img width="400" alt="A_storyboard.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/240708/9a02454e-55a0-aaaa-9fe5-4e4986be8ff5.png">


エラー文を読んでもらうとわかるが、

```
Main.storyboardはA.storyboardの初期ビューコントローラを参照していますが、指定されたエントリポイントが見つかりませんでした。コマンドLinkStoryboardsがゼロ以外の終了コードで失敗しました
```

「A.storyboardのinitial Veiwがどれか分からないから指定してね」といった内容だと思う。

考えてみれば当然だけど、まず```is Initial View Controller```を知らない人はつまずくと思うので同じエラーが出た人のために残しておく。

#最後に
初歩的なミスで内容の薄い記事なのでこの記事を書くのを迷ったけど、久しぶりに投稿してみようと思い書いてみた。
これからは```StoryBoard Reference```を使って開発していこうと思う。
StoryBoard Referenceを使うと、画面がみやすくなるだけではなくGitでの共同作業でのコンフリクトが起きにくくなるので、
活用しない手はない。

無事に**脱 Main.storyboard**ができた。おしまい。
番外編　仮想と物理の違いを簡単に説明してみた

## 次の記事を書く前に・・・

皆さんこんにちは。
次回の第３回の記事でEBSなどAWSの仮想外付けハードディスクに関してブログを書こうと思ったのですが、ふと**仮想**という言葉を目にして今から２年前、、
最初の24H365Dのクラウドサービス監視の現場で手順書や参考書でもよく**仮想**という言葉があり、それらがどういう意味を成すのか本当にわからなく、先輩に聞いてもなかなか理解できず苦労した経験を思い出しました。

そこで
・これからITエンジニアを目指す人
・今日が最初の現場デビューの人
そういう方のために仮想と物理の考え方をなるべくわかりやすくこの記事に残しておこうと思います。

## **※仮想ってどうやって考えたらいいの？**
文系からITエンジニアになった人なら一度は疑問に思うこの**仮想**という単語
よく仮想通貨や仮想サーバ、ネットワークでは仮想ポートなど参考書やOJTでも頻繁に耳にし目に留まりますが。。。。
先輩に「仮想って何ですか？」って聞くとだいたいこう答えます。。
「仮想とは論理的な～(ry」
いやいやその論理的ってどういう意味よ？ついでに物理ポートって？
新人の時にこのような経験をした人も多いのではないでしょうか？
ここでなるべくかみ砕いて説明します。

### 仮想(論理)＝手で実際に触ることが出来ず、システムとして起動しているもの
### 物理＝手で実際に触ることができるもの

例えばひと昔前に、巷で話題になった仮想通貨:moneybag:
これは**インターネット上で取引**をし送受信するコインです。
しかし財布の中に入っていて**手で取り出すことのできる**10円玉などとは異なり、実際にインターネット上にあるコインを手で触れることはできません。
~~パソコンの画面を手で触れることできるじゃんとかは言わないでください~~
考え方は同じで、仮想サーバーにくっつけるハードディスクや仮想(論理)ポートもすべてインターネットや機械の内部にシステムとして存在し、私たちが**実際に触って**設定や取り付けをすることができません。
仮想という言葉を理解するには、これ以上難しく考えるとややこしくなるので
**手で触れるかor触れないか**この2択でまず考えていくとわかりやすいです。
## 参考図
<img width="536" alt="物理仮想.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559536/f228801f-e7d8-c9bc-cc51-25c871211c4e.png">
[光-Hikari-のPython]06章-04 関数（引数と戻り値3）

#[Python]06章-04 引数と戻り値3
今まで書いた関数では、引数が数値や文字列の変数の場合だった場合について説明しました。
今回はリストの変数を渡すことを考えてみましょう。特に難しいことはなく、今まで通りにリストを作成し、リストの変数を渡すのみです。


##リストの受け取り
今回は以下の要件のプログラムを作成します。

<font color="blue">国語・数学・英語のテストの点数を入力し、それを1つのリストにまとめて関数内で平均点を求めるプログラムを作成してください。なお、平均点の出力は関数内で行わないようにしてください。
</font>

<font color="#00cccc">chap06</font>の中に、<font color="#00cccc">samp06-04-01.py</font>というファイル名でファイルを作成し、以下のコードを書いてください。

```samp06-04-01.py
def test_clac_func(test_data_ls):
    #いったん、リストの中身を出力します。
    print(test_data_ls)

    #sum関数でリスト内の数値をすべて足すことができる。以下は平均を求める。
    avg = sum(test_data_ls) / len(test_data_ls)

    return avg  #求めた平均を呼び出し元の関数へ返す


##各科目の点数を入力
jpn = int(input('国語の点数：'))
math = int(input('数学の点数：'))
eng = int(input('英語の点数：'))

##点数をリスト化
test_data_ls = [jpn, math, eng]
##リストを実引数として、関数を呼び出す
avg = test_clac_func(test_data_ls)

print(f'平均点：{avg}')
```

><font color="#090" bgcolor="black">【実行結果】</font>
国語の点数：75
数学の点数：80
英語の点数：72
[75, 80, 72]
平均点：75.66666666666667

今回、3科目の入力後に、それら値を**test_data_ls**という変数として**リスト化**しています。このリストを**test_clac_func関数**の実引数として関数を呼び出しています。
関数内での処理は特に問題ないかと思いますが、**sum関数**でリスト内の数値をすべて足すことができます。

リストを渡しても呼び出される関数は仮引数としてリストを受け取っていることがわかったかと思います。

##演習問題
演習問題を用意しました。ぜひ解いてみてください。プログラムは<font color="00cccc">chap06</font>内に作成してください。使用する変数名は好きな変数名を指定してかまいません。
<font color="3333ff">
【1】2つの数値a, bを入力して、大きい値を出力するプログラムを作成してください。ただし、関数を利用するようにしてください。
</font>
><font color="#090" bgcolor="black">【実行結果】</font>
数値aを入力してください：2
数値bを入力してください：4
4のほうが大きいです。


##最後に
リストは本当によく出てくるので、実際にそれを関数に適用するといったことは多々あります。
特に今まで学んだ文字列や数値の変数と扱いは同じなので、特に迷うことはなかったかと思います。リストを引数として渡すこともできるということを覚えておいてください。

###[【目次リンク】へ戻る](https://qiita.com/ko0821/items/379e8bd9e6ea01089419)
rails メモ化とは

どうもチャンクノです！
今回は前職の同僚にメモ化というものを教えてもらったのでそれについて書こうと思います。
その同僚いわく知っていたらドヤ顔できるらしいです。
できなくても僕のことは責めないで下さい。

まずメモ化ってなんだと思いますよね。
メモ化とは

```
メソッドが最初に呼び出されたときに戻り値がキャッシュされ、
それ以降、同じスコープ内でメソッドが呼び出されるたびにキャッシュされた値が返されることを意味します。
```
とのこと。
なるほど。分からんですね。

コードを見た方が手っ取り早いかもしれません。
簡単な例で書くと

```
 def update
  user.comment.update(comment_params)
 end

 private

 def user
    @user ||= User.find(params[:id])
 end
```

色々省いて書きましたがこんな感じです。
注目する部分は

```
@user ||= User.find(params[:id])
```
ここですね。
||= この記述なんやねん、そう思うのではないでしょうか。
そうでしょうそうでしょう。
||= これは@userがnillの場合 User.find(params[:id])が@userに代入されます。
大事なのはこの後です。
これ二回目同じメソッドを呼び出した時にUser.find(params[:id])この部分の処理が走らないんですね。
なぜかと言うと一回目処理が走った時に、@userにキャッシュされてずっと残ってるらしいです。
つまり二回目以降はクエリが走らないのでアプリケーションのパフォーマンスが上がります。

ちなみにキャッシュとは

```
キャッシュ（caching）」とは、リクエスト・レスポンスのサイクルの中で生成されたコンテンツを保存しておき、
次回同じようなリクエストが発生したときのレスポンスでそのコンテンツを再利用することを指します。
```
とのこと。
これはなんとなく分かりました。
chromeでも画像のキャッシュとかありますよね。
あれと同じです。

つまりメモ化とは同じ処理を走らせる場合に、1回目の処理で返したレスポンスをキャッシュとして残しておいて、それ以降の処理パフォーマンスを上げようねってことだと思います。
処理速度が速くなればなるほど僕たちユーザーにとっても嬉しいことになるので積極的に使っていくといいのではないでしょうか。
自分もこれから意識していこうと思います。
使い方としてはsetterとして使うとのことでした！！！
開発者側もユーザー側も幸せになれるコードを書いていきましょう🙌

それでは今回はこの辺で。
皆様よきプログラミングライフを🙏
【備忘録】Javascript : Generatorの基礎・応用に挑戦(1)

## はじめに
今回はJavascriptのGeneratorに付いて触れていきます。理解するのに時間がかかった上、実務で弄ったことがないので間違えている箇所があればコメントでご指摘いただけると幸いです。

## ジェネレータとは
一言でいうと何回でも処理の途中で抜けたり入ったりできる関数の事。`for of`文と相性が良く、実装次第では自分の意図する等に処理できる。

## ジェネレーターを作ってみる

下記の通り、`function`の後に`*`を付けて宣言すればジェネレータの完成です。

```javascript.js

function* numbers(){
    yield;
 }
```

証拠に下記の通り、このジェネレータをコンソール上に出力すればジェネレーターが作成されていることがわかります。

```javascript.js
console.log(numbers()); //=> __proto__: Generator が生成される。
```

関数の中に記述されている`yield`は通常の関数で使われている`return`の代わりになるもので`next`メソッドを使うたびに実行してくれます。

下記が例の構文です。

```javascript.js
function* colors(){
   yield 'red';
   yield 'blue';
   yield 'green';
}

const colorGen = colors();
console.log(colorGen.next()); //{value: "red", done: false}
console.log(colorGen.next()); //{value: "blue", done: false}
console.log(colorGen.next()); //{value: "green", done: false}
console.log(colorGen.next()); //{value: undefined, done: true}
```
見てもらえればわかる通り、1回目のnextメソッド実行時に`colors`ジェネレーターの処理内の一つ目の`yield`が実行されており、2回目、3回目と実行するたびに今度は`blue`と`green`が出力されるようになりました。注目していただきたいのがnextメソッドの返り値は常に`value`と`done`プロパティからなるオブジェクトを返しており、`yield`の返り値がある時は`false`となっていますが返り値がなくなると`true`を返しています。

## generatorの実行途中に任意の値を渡せる

上記の例文でgeneretorの実行の方法と返り値を知ることができました。今度は上の例文にまた処理を付け加えて一癖加えていきたいと思います。

```javascript.js
function* shopping(){
    
    const stuffFromStore = yield 'お金' ;
    const clothes =　yield '服';
    return [stuffFromStore, clothes]; 
 }

const shoppingGen = shopping();
 console.log(shoppingGen.next()); // {value: "お金", done: false} ---(1)
 console.log(shoppingGen.next('品物')); //{value: "服", done: false} ---(2)
 console.log(shoppingGen.next('綺麗な服')); //{value: Array, done: true} ,value: ["品物", "綺麗な服"]

```

上の処理中の(1)は単純にnextメソッドを呼び出し、最初のyieldまで処理しています。よって出力結果は普通に`お金`が出力されるはずです。次の(2)の処理ですがここではnextメソッドを呼び出す際に引数に`品物`を渡しています。このnextメソッドの呼び出しによって今度は`yield 'お金'`以降から処理が再開されるのですがこの時に`品物`が定数`stuffFromStore`に入っていきます。
以降同じように処理しておくと最後のreturn文では`品物`と`綺麗な服`の配列を返すようになりました。

このようにgeneretorを使うことによって処理の途中に任意の変数を代入して処理結果を変えることができることがわかりました。

## 最後
今回はgeneratorの基礎の部分について復習してみました。長くなるので実際の応用方法は次回の記事に回します。
ありがとうございました。
エンジニアのタイプ別育成

エンジニアを育てるのは難しい・・・。
昔同じ部署のチームリーダーに自身のチームメンバー（新卒エンジニア）があまり育っていないと相談を受けた。

事情を聞くと教え方がその人に合っていなかったようだった。
「自分がそう教えられて育ったから」という理由で育成方針を1つに決めてしまっている人が思わぬ壁に当たるかもしれないため、個人的なタイプ別の考え方を書きたいと思います。

※個人の考え + 極端な紹介なので参考程度にとらえていただければと思います。


# 挑戦タイプ
- どんどん先に進めたい
- 積極性、行動力が高い
- 先頭を道を切り開く

このタイプは積極性や自主性が高く、どんどん課題をこなしていきます。
反面、細かいミスなどは気にしない事もあり、同じようなミスや細かい不具合などが考えられます。
課題に対して進捗や達成度を重視するタイプのため、新規開発やアジャイル開発に適しています。
育成時には細かい部分をフォローする形で伝えるとスムーズ。


# 堅実タイプ
- しっかり調査や設計してから進めたい
- 堅実性、論理性が高い
- 安定して縁の下を支える

このタイプは調査や設計をしっかりと行い、スケジュール遅延や不具合などが少ない。
反面、しっかりとした準備や期間を気にすることもあります。
課題に対して計画的な進捗や完成を重視するタイプのため、運用案件やウォーターフォール開発に適しています。
育成時には具体的な目標を設定するとスムーズ。


# 遊撃タイプ
- 効率化や便利さ高めたい
- 協力性、把握能力が高い
- サポート的な貢献をする

このタイプは周りやプロダクトの状況を把握し、新しい機能や技術を通じてサポート的な動きをしてくれます。
反面、古い技術や長く1つの事をし続ける事が苦手な場合もあります。
課題に対して効率さを重視するため、複数プロジェクトや横断業務に適しています。
育成時には新しいミッションや課題を複数依頼するとスムーズ。


# 管理タイプ
- 全体を把握し判断したい
- 計画性、責任感が強い
- チームやプロダクト、組織として考える

このタイプは複数の課題や目標を管理/進行する動きをしてくれます。
反面、専門性や1つの技術を深く行うことが苦手なケースがあります。
課題に対してグループとしての成果や成長を重視するため、チームやプロジェクトの管理や進行に適しています。
育成時には抽象的な目標を依頼し、具体的な方法や進行はある程度お任せするとスムーズ。
Rails環境でER図自動化についての調査の共有

#はじめに
業務でER図を自動化したいという要件があってその時に調査した内容をせっかくなのでこちらでも共有したいと思います。

#調査の結果
まず調査の結果からですがやはり業務で使ってるデータベースのテーブル数やカラム数はかなりの数なので正式なER図として認定するには少し難しいという結論になりました。
まあというより不必要なテーブルやカラムまで表示されてしまうので全部出力するのもそれはそれで無駄だよね。だけど今更切り分けも難しいという感じになりました。
ただローカルで確認する分には結構いい物もあったので今回共有しようかなと思うに至った所存です。

#前提
どの方法も**graphviz**を使用するため、以下コマンドで**graphviz**をOSにインストールします。

```terminal
$ brew install graphviz
```

##案1 rails ERD(Gem)
個人開発レベルならこれでも全然見やすいんですけど業務で使うとなるとフォーマットが見づらくてざっくりしたテーブルの関係性しか見れませんでした。

https://github.com/voormedia/rails-erd

```ruby:Gemfile
group :development, :test do
  gem 'rails-erd'
end
```

```terminal
$ bundle exec erd
```

##案2 RailRoady(Gem)
これも個人開発レベルならこれでも全然見やすいですし、モデルとコントローラーでそれぞれ出力できるので結構いいなぁと思ったんですけど業務で使うとなると同じくフォーマットが見づらい。

https://github.com/preston/railroady

```ruby:Gemfile
group :development, :test do
    gem 'railroady'
end
```

```terminal
$ bundle exec rake diagram:all
```

Railsエンジン使用してる方は以下。

```terminal
$ bundle exec rake diagram:all_with_engines
```

##案3 Sequel Proのエクスポート機能を使ってER図を出力
全体のテーブル構造をざっくり見るならこれが一番見やすかったかも。

suinさんの以下記事の通りにやれば行けるのでこれも良かったら、、、
[SequelProでER図を出力する方法](https://qiita.com/suin/items/25cc0e9d6670a62f4d8e)

##案4 DBeaverを使用
各テーブル単位で外部キーやリレーションを見るなら多分これが一番いいかも。
以下記事のER図の表示の部分を見てもらえるとこんな感じのER図が見れるんだというのが分かります。
[DBeaver使い方メモ](https://qiita.com/12345/items/48f6856e32fd618ea307)

#最後に
こんな感じで意外にも色々な方法があるんだなぁと新たな発見があったりそれぞれの手法で実際に見てみると得手不得手があるんだなというのも面白かったですね。

ちなみに個人では[DBeaver](https://dbeaver.io/)を使用してます。
参考になれば嬉しいです。
position:relative な要素が overflow:auto領域にあるときスクロールバーが出る問題を解決する

#解決したい課題
あるdiv要素の上に、`position:relative`な要素をオーバーレイ表示させたいとします。
（例: 地図の上にツールバーを表示させたい、など）

このとき両要素の親要素に`overflow:auto`が設定されていると、**見た目上は要素が範囲内におさまっているのにスクロールバーが出る**という現象が起きます。

![scrollbar.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44264/0c92bb7a-8f18-501a-ad89-96367e6dcc0f.gif)

`overflow:hidden`にできればいいのですが、ウィンドウを縮小されたときなどにはスクロールバーが必要になります。

`overflow:auto`は維持したまま、不要なスクロールバーを非表示にしたい。

```HTML
<div class="container">
  <div class="text">
    This content should not have a vertical scrollbar.
  </div>
   <div class="relative"></div>
</div>
```
```css
.container {
  width: 500px;
  height: 200px;
  margin: 10px;
  border: 2px solid blue;
  overflow: auto;
}

.text {
  width: 90%;
  height: 80%;
  padding: 10px;
  border: 2px solid black;
  margin: 5px;
}

.relative {
  width: 50px;
  height: 50px;
  bottom: 80px;
  left: 80px;
  position: relative;
  border: 2px solid red;
  background-color: red;
}
```
#解決策
以下のコードのように、`position:relative`要素にラッパーを用意し、**ラッパーを`height:0px; width:0px;`に設定する**と、縦横ともに不要なスクロールバーをなくすことができます。

```HTML
<div class="container">
  <div class="text">
    Relative wrapper class can avoid the scrollbar.
  </div>
  <div class="relative-wrapper">
    <div class="relative-inner"></div>   
  </div>
</div>
```

```css
/* Trick! */
.relative-wrapper {
  height: 0px;
  width: 0px;
  bottom: 80px;
  left: 80px;
  position: relative;
}

 .relative-inner {
  width: 50px;
  height: 50px;
  border: 2px solid red;
  background-color: red;
}
```

紹介したコードは以下のCodepenで動かせますので、よろしければ覗いてみてください。
[Avoid scroll bar with a relative element in overflow:auto area](https://codepen.io/hashikuchi/pen/jOWVoJb)
Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)の解決

# 問題
ソケット'/tmp/mysql.sock'を通じてローカルのMySQLサーバーに接続することができない。

下記の図で言うと、クライエント側からMySQLサーバーに接続しようとしていて、接続するためには'/tmp/mysql.sock'というファイルを出力する必要があるのだが、それができない状態。

### ソケットとは何か？

![スクリーンショット 2021-01-21 午後8.37.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547640/be2859e9-c160-97e0-da90-d12fd73bc313.png)

ソケットはプロセスやネットワーク間の通信を行う部分のこと。
MySQLではこのソケットを通してサーバーとクライアントが接続される。

※と書いてみたものの、まだネットワークの理解も、MySQLのクライエント側とサーバー側というのもよくわかっていないので、また調べて追記する。

# 問題の原因は？
MAMPを起動して、そちらでポート番号(3306)を開いていて重複してしまったため。
MySQLのポート番号は3306と決まってお利、特定のポート番号は重複して使えない。

今回はPHPの学習をするためにMAMPを起動していたので、一旦MAMPを停止しポート番号の重複を避ける必要があった。

# 原因を知るまでに試したこと
### ①MySQLを起動できているか確認

```
$ mysql -u root -p
```
このコマンドでMySQLに入ろうとしたが、冒頭のと同じエラーが出てしまった。

```
ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2)
naota7118@Naotas-MacBook-Air-6 pfc-master % 
```

### ②database.ymlを確認

```ruby:config/database.yml
default:
  adapter: mysql2
  encoding: utf8mb4
  charset: utf8mb4
  collation: utf8mb4_unicode_ci
  pool: 5
  username: root
  password: password
  host: db
  wait_timeout: 180
  # socket: /tmp/mysql.sock←
```
←の部分をコメントにしたりコメントではなくしてみたり試したが、変わらなかった。
この設定はいらなかったようだ。

### ③MySQLサーバーが起動しているか確認
MySQLサーバーは起動していてポート番号3306が使われていることに気づいた。

```
naota7118@Naotas-MacBook-Air-6 pfc-master % ps ax | grep mysqld
28532   ??  S      0:00.07 /bin/sh /Applications/MAMP/Library/bin/mysqld_safe --port=3306 --socket=/Applications/MAMP/tmp/mysql/mysql.sock --pid-file=/Applications/MAMP/tmp/mysql/mysql.pid --log-error=/Applications/MAMP/logs/mysql_error_log
28824   ??  S      0:01.92 /Applications/MAMP/Library/bin/mysqld --basedir=/Applications/MAMP/Library --datadir=/Applications/MAMP/db/mysql57 --plugin-dir=/Applications/MAMP/Library/lib/plugin --log-error=/Applications/MAMP/logs/mysql_error_log.err --pid-file=/Applications/MAMP/tmp/mysql/mysql.pid --socket=/Applications/MAMP/tmp/mysql/mysql.sock --port=3306
31583 s002  R+     0:00.00 grep mysqld
```

# 解決方法
MAMPを停止させた。
もし同じエラーが出たら、別のところでMySQLを起動していないか確認してみるといいかもしれない。

# 参考記事
http://www.hi-ho.ne.jp/tsumiki/book_sup2.html