OmniAICreator/Qiita-1.07M huggingface dataset:
コマンドラインのショートカット

コマンド | 内容
--- | ---
Ctrl+b | 後方に一文字分移動する
Ctrl+f | 前方に一文字分移動する
Ctrl+a | 行頭に移動する
Ctrl+e | 行末に移動する
Alt+b | 後方に単語一つ分移動する
Alt+f | 前方に単語一つ分移動する
BS, Ctrl+h | カーソル位置の後方に一文字削除する
Delete, Ctrl+d | カーソルの位置の一文字を削除する
Ctrl+w | 後方にスペース区切りで1単語ぶんを削除する
Ctrl+k | カーソル位置から行末までを削除する
Ctrl+u | カーソル位置から行頭までを削除する
Ctrl+y | 最後に削除した内容を挿入する
Ctrl+s | 画面表示をロックする
Ctrl+q | 画面表示のロックを解除する
Ctrl+l | 画面を消去する
Ctrl+p, ↑ | 一つ前のコマンド履歴に移動する
Ctrl+n, ↓ | 次のコマンド履歴に移動する
Ctrl+r | 履歴をさかのぼってインクリメンタル検索する
(インクリメンタル検索時)文字の入力 | 検索語を追加して再検索
(インクリメンタル検索時)Ctrl+r | 一つ前の検索結果へ移動
(インクリメンタル検索時)Enter | 現在の検索結果をそのまま実行
(インクリメンタル検索時)Esc | 現在の検索結果を表示したまま、コマンドラインに戻る
(インクリメンタル検索時)Ctrl+g | 検索結果を破棄し、プロンプトに戻る
【GAS】Gmailにファイルが添付されてたらGDriveに保存する

# IFTTTでGmailトリガーが廃止されると聞いて
IFTTTで使ってたのはファイルの保存だけでしたのでGASで書きました。
LINEもStackもなんでもAPI叩けばなんとでもなる思います。
# GAS
```javascript
function saveFilesToDriveFromGmail() {
  const folderId = '保存先フォルダーID';
  
//1時間ごとにトリガー実行1h、2時間なら2h、一日なら1d
  const keyword = 'has:attachment -is:sent newer_than:1h' 

  const myThreads = GmailApp.search(keyword, 0, 30);
  const myMsgs = GmailApp.getMessagesForThreads(myThreads);

  if(myMsgs.length == 0)
    return null;
    
  //添付ファイルの配列
  const attachments = myMsgs.reduce(function(pre, cur) {
    return pre.concat(cur.reduce(function(pre, cur) {
      return pre.concat(cur.getAttachments());
    },[]))
  },[]);
 
  attachments.map(function(file) {
    DriveApp.getFolderById(folderId).createFile(file); 
  });
}
```

# あとがき
IFTTTのGmailトリガー廃止ですが、基本的にはGASの方が自由度が高いのでIFTTTで出来ることはGASでもできるとお思います。
実際にIFTTTでは文字化けでできなかったことをGASでは問題なくできたりしています。
[【GAS】GDriveにファイルが追加されたらGmailで添付してメールする](https://qiita.com/golyat/items/55a0946e7058edb99bbf)
一方で1分毎の実行が最小単位で即応性はありません。
Qiitaユーザのつながりを可視化するWebページを作成してみた

# はじめに
Qiitaでは、ユーザをフォローすることで、ユーザ間でつながりをもつことができます。今回は、指定したユーザの、フォローしているユーザとフォローされているユーザを、ネットワーク図で可視化するWebページを作成してみました。

# 作成物
ソースコード（HTMLとJavaScript）を、githubで公開しています。
https://github.com/t-mangoe/QiitaUserNetwork
作成したWebページには、以下からアクセスできます。
https://t-mangoe.github.io/QiitaUserNetwork/
Webページでは、以下の図のようにネットワーク図が表示されます。
![Qiita可視化.jpg](https://qiita-image-store.s3.amazonaws.com/0/189330/f6a04fca-b771-452e-78ae-8e255c3e3ebf.jpeg)

# 処理内容
QiitaのWebAPIを叩いて、フォローしているユーザとフォローされているユーザの情報を取得します。この情報を基に[vis.js](http://visjs.org/)でネットワーク図を作成し、表示しています。
Raspberry Pi Desktop で右クリックできるようにする

はじめに
----
古い Macbook に Raspberry Pi Desktop（Raspbian の x86 版）をインストールしたものの、右クリックできないことに気づき、どうすれば良いのか調べてみた。

Synaptic タッチパッドドライバをインストール
----
ググってみると「synclient」というコマンドで設定できることがわかったが、ターミナルで実行してみてもコマンドが存在しない。

「設定」にある「Add / Remove Software」を実行し「synclient」を検索してみると「Synaptic」というタッチパッドドライバが見つかるのでインストール。![screenshot20190323_001.png](https://qiita-image-store.s3.amazonaws.com/0/42215/105041ea-8a5c-27d6-2a5b-2b224d181152.png)
再起動後に「synclient」コマンドが実行できるようになる。

もちろん「apt-get」でインストールしても良い。

```
$ sudo apt-get install synaptic
```

設定
----
```
$ synclient TapButton1=1
$ synclient TapButton2=3
```
１行目の設定は、１本指タップで左クリック、２行目は２本指タップで右クリックとなる。

```
$ synclient TapButton1=1 TapButton2=3
```
このような書き方もできる。
「synclient」コマンドだけ実行すると現在の設定が確認できる。

起動時に自動で設定するには
----
Linux では起動時に何かを実行する手段はいくつかある。
「/etc/rc.local」「crontab」「/etc/init.d」「systemd」などでは駄目。
タッチパッドの設定なので X Window が起動した後に自動で設定する必要がある。
正解は、

```
$ sudo nano /etc/xdg/lxsession/LXDE-pi/autostart
```
である。
次のように編集する。

```
@lxpanel --profile LXDE-pi
@pcmanfm --desktop --profile LXDE-pi
@xscreensaver -no-splash
@synclient TapButton1=1 TapButton2=3
point-rpi
```
下から2行目を追記している。
他は最初から書いてあるものなので、いじらない。
プログラミング学習記録35〜道場コースをCloud9で〜

##今日やったこと
- ProgateのRailsで作ったアプリをCloud9で再現する

Progateで作ったTwitterっぽいアプリを道場コースの手順に従って、Cloud9で動かすことを試みました。

なんとか道場コース1の7まではうまくできました。

Progateではターミナルが最初からtweet_appがホームポジションになっていますが、Cloud9のターミナルでは自分でtweet_appまで移動する必要があります。

ついProgateのノリでやってしまい、何回かこれでミスしてしまいました。

あと、ミスした時にProgateだとどこがミスしているかわかりやすく教えてくれますが、Cloud9ではProgateほど丁寧にミスの場所を教えてくれません。

なので、'が１つ足りなかったり、/が抜けてたりして起こったエラーに気づくのに時間がかかりました。

このあたりまだまだ実践が足りてないですね。

データベースもProgateのようにわかりやすくチェックするページがないので、ターミナルでチェックしなければならないようです。

一応やり方を調べてみて、railsのレファレンスサイトにある手順でsqliteに入っているデータを見てみたのですが、思ってたのと違いました。

カラムごとにわかりやすく表示させたいですね。

明日はデータベース（テーブル）の確認方法を調べて、道場コースに従い、tweet_appを作っていきたいと思います。

おわり
VSCodeでプロジェクト単位の拡張機能を設定する

リポジトリごとに拡張機能を共通化したい時ってあると思います。

その時の設定を残しておきたいと思います:santa:

# TL;DR

- vscodeのワークスペースを使用する(限定的にする)
- vscodeを使用しているチームにおすすめ

### ※今回はPrettierを例にしていますが、

- 拡張機能を共通化（.vscode/extensions.json）
- リポジトリでVSCodeの挙動を共通化(.vscode/settings.json)

が目的であれば一読の余地ありかと！:santa:


# 対象読者
- vscode v1.52.1以上
- チームでvscodeを使用している


# 背景
例えば、チームで[Prettier](https://prettier.io/)を既存のプロジェクトに導入していくのが決まったとして、大体[Prettier](https://prettier.io/)を入れる目的って、フォーマッター使用してレビュー負担を減らしたいだったりすると思います:santa:

そうであれば、[Prettier](https://prettier.io/)を発動させるベストなタイミングは

1. プロジェクトを担当しているメンバーのエディター（vscode)上
2. ファイル保存したタイミング
3. 拡張機能もたっくさんあるから同じの使いたいね
4. でも、他のプロジェクトには影響させたくないね

上記の要望はjsonファイル用意して解決していきましょう:santa:


# ファイルを保存したタイミングでフォーマッターを適応させる

1. ```command + ,```で設定を開きましょう(Mac)
2. **ワークスペースの設定**のタブをクリック（これしないと、全体適応になってまう）
3. 検索欄に「onsave」とかいれると、「Format On Save」がデフォルトでチェック外れているので、チェックいれる

![スクリーンショット 2019-03-23 20.38.16.png](https://qiita-image-store.s3.amazonaws.com/0/183059/b4feac1b-ff9e-b0e0-e301-5838f870a54b.png)

すると、自動で```.vscode/settings.json```が作成されたと思います
それがあるフォルダ配下にだけ、ユーザー設定に上書きされて適応されます:santa:

これで、**ファイル保存時にPrettierを適応させる**準備が整いました:santa:

# 対象の拡張機能をおすすめさせる

Prettierの拡張機能たくさんありすぎて字が読めなーい！！！ってならないように拡張機能を選びましょう

今回は[公式で勧められている拡張機能](https://marketplace.visualstudio.com/items?itemName=esbenp.prettier-vscode)を選びます

VSCodeの拡張から、prettierを検索して、歯車マークを押すと、
「ワークスペースの推奨事項に追加する」を押すと、「.vscode/extension.json」に対象のIDが配列に追加されれば完了です
![スクリーンショット 2021-02-14 19.48.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183059/27025fc9-21b7-8c50-4c02-4d05f6c036cf.png)





# おすすめ強制機能オン設定

まだこれだけではおすすめ機能を出すことができません:santa:
```"extensions.ignoreRecommendations"```という項目を```false```にしないと、おすすめされないのです:santa::anger:


ということで、先ほどの```.vscode```フォルダにある```setting.json```に追記しましょう



```setting.json
{
  "editor.formatOnSave": true,
  "extensions.ignoreRecommendations": false
}

```

# 結果
上記設定がされたフォルダをvscodeで開くと・・・

vscodeの右下にダイアログが出て、
![スクリーンショット 2019-03-23 20.56.44.png](https://qiita-image-store.s3.amazonaws.com/0/183059/ed496310-02cb-06e2-6522-f3cf28e86a1a.png)

推奨事項を表示をクリックすると、
![スクリーンショット 2019-03-23 20.57.53.png](https://qiita-image-store.s3.amazonaws.com/0/183059/1627cf0f-1994-b7e6-39f3-671150819ae2.png)

インストールしてほしい、拡張機能を表示させることが出来ましたとさ:santa:


- `.vscode/extensions.json`
- `.vscode/settings.json`

をGitHubなどのリポジトリにプッシュすれば、これからプロジェクトに参加する人におすすめすることができましたとさ:santa:


めでたしめでたし:santa:

# 参考

- [Prettier](https://prettier.io/)
- [Prettierのおすすめ拡張機能](https://prettier.io/docs/en/editors.html#visual-studio-code)
- [チームでVSCodeを使用する際にインストールすべき拡張機能を設定する](https://qiita.com/Glavis/items/c3dac07e4bcf5c50db0a)
Heidi SQLのフィルタ履歴を消したい

# 前置き
データベースを参照、編集する際にGUIを備えたなんらかのツールで操作することも多いと思います。
SQL発行するだけなら困らないですが、表で見えた方がやっぱり便利ですからね。

そんなGUIを備えたツールの中でも今回は
**Heidi SQL**
についての記事です。


#何が起きたか
Heidi SQLはフィルタの自由度も高く、とても便利。
なんですが、その自由度の高さゆえにたまーにフィルタの設定をミスったりしてデータ表示ができない事象に陥ることがあります。

エラーが起きてもダイアログが出てきてそれを無理やりコンティニューしてやるとなんとかフィルタをクリアすることができて回復。
できることが多いんですが、ですが。。。

このなんかとコンティニューして無理やり回復！の技ができない状態に陥ってしまいました。
アプリケーションを一旦終了させてもフィルタは保存されているので次に開いたときにまた同じ状態＿|￣|○

さぁ、どうする。。。
インストールしなおすのか？
めんどくさすぎる。


#解決した
アンインストールまでしなくとも、フィルタの条件はどこかに保存されているはず！
保存されているフィルタの条件さえ削除できれば良いのです(｀・ω・´)

さて、ではどこに保存されているかが問題。

アプリケーション本体のディレクトか、
AppDataなどのディレクトリか、
とりあえず「Heidi」とかそれっぽい名前のディレクトリを探してみる。
・・・
・・・・・・
・・・・・・・・・
ない。

まさか、データ保存しているところが無いわけがない。
現にこうしてやらかしたフィルタが復元されているのだから。

もしやとレジストリを探検することに。
あった！あったよーーー

```script:
HKEY_CURRENT_USER\Software\HeidiSQL\Servers
```

こんなところにSever設定毎にテーブルの一覧が格納されてます。
そしてそのテーブル名に紐づいて「Filter」があり、こいつが初期表示時に適用されています。

これを「Filter」というキーごと削除してしまいましょう！
場合によってはサブキーにある「RecentFilters」に紐づいているキーも連番の整合性を保って消してやらないといけないかも。
めんどうなら「RecentFilters」ってキーごと削除でも。


#まとめ
Heidi SQLのフィルタに変なもの設定してしまったら、あせらずレジストリからそのフィルタを消そう。
そもそも変なフィルタを設定するなよっていうのはあるけども。
【JavaScript】条件分岐② switch【自己学習】

##switchでできること
ifと同じく、複数の条件によって処理を分岐させたい場合に用いる。

##switchの書き方

```switch-1.js
const rank = "A";
switch (rank) {
  case "A":
    console.log("あなたはAランクです");  // > あなたはAランクです
    break;
  case "B":
    console.log("あなたはBランクです");
    break;
  case "C":
    console.log("あなたはCランクです");
    break;
  default :
    console.log("あなたはランク外です");
    break;
}
```

switch()内の定数rankの値がcaseの値のいずれかと一致した場合、一致したcaseで指定した処理を実行される。

上記のコードの場合は定数rankの値はAであり、一番上のcaseの値と一致することから、コンソール上では「あなたはAランクです」と表示される。caseの値のいずれにも一致しなかった場合は、defaultを使うとこで処理を指定できる（省略可）。

####breakは必須
ifとは異なり、switchは最初に条件を満たした処理が実行された時点で終了せず、それ以降の処理が続けて実行されてしまう。

```switch-2.js
const rank = "B";
switch (rank) {
  case "A":
    console.log("あなたはAランクです");
  case "B":
    console.log("あなたはBランクです");  // > あなたはBランクです
  case "C":
    console.log("あなたはCランクです");  // > あなたはCランクです
  default :
    console.log("あなたはランク外です");  // > あなたはランク外です
}
```
上記のコードでは上から2番目のcaseの値が一致し、コンソール上で「あなたはBランクです」と表示されるが、breakが書かれていないため、値が一致していないそれ以降の処理も実行され「あなたはCランクです」「あなたはランク外です」も続けて表示されてしまう。

このような表示を避け、一致した値に対応した処理のみを実行するには、それぞれの処理の直後にbreakを記述して命令を終了させる必要がある。

####caseの値は同値演算子で比較されている
switch()内の値とcaseの値が一致しているかの判定は、等価演算子（==）ではなく同値演算子（===）で行われている。

```switch-3.js
const i = "1";
switch (i) {
  case 1:
    console.log("値が一致しています");
    break;
  default :
    console.log("値が一致していません");  // > 値が一致していません
}
```
switch()内の値は文字列の"1"に対してcaseの値は数値の1という違いがあり、同値演算子ではこれらを異なる値としてみなすため、caseで指定した処理ではなくdefaultで指定した処理が実行されてしまう。

##ifとの使い分け方
先述から、switchはifと比較し下記のメリットとデメリットがある。
######　メリット
　・条件式を記述しないので、シンプルでわかりやすいコードになる
######　デメリット
　・同値演算子でしか値を比較できない

そのため、同値演算子のみで条件分岐できる場合はswitch、できない場合はifを使うのが望ましいと考えられる。
rustでgithub上のクレートを依存関係に指定する

crate.ioに公開されていないrustのクレートをgithubから利用する方法。

# Cargo.tomlで指定する
[Specifying Dependencies - The Cargo Book](https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#specifying-dependencies-from-git-repositories)
cargoのドキュメントにgithubからもってくる方法が書かれています。

インストールしたいパッケージ名を指定します。
`git`にリポジトリのアドレスを値として渡します。
ブランチなどを指定したい場合はそれぞれの指定できます。
`{ git = "https://github.com/paritytech/parity-bitcoin.git" branch = <branch name> tag = <tag name> rev = <value>}`

```Cargo.toml
[dependencies]
keys = { git = "https://github.com/paritytech/parity-bitcoin.git" }
```
[parity](https://www.parity.io)のbitcoinライブラリを例にします。
[paritytech/parity-bitcoin: The Parity Bitcoin client](https://github.com/paritytech/parity-bitcoin)

これで`$ cargo build`すればクレートとしてインストールされます。

# インストールされたクレートを利用する
`keys`クレートを利用します。
`extern crate keys;`

```src/main.rs
extern crate keys;
use keys::generator::Generator;

fn main() {
   let keypair = keys::generator::Random::new(keys::Network::Mainnet); 
   let generated = keypair.generate();
   println!("{}", generated.unwrap())
}
```
これを実行するとsecp256k1のキーペアを生成してくれます。
MakefileのためのIntellijプラグイン「Makefile support」がおすすめ

本記事ではIntellijの[Makefile support](https://plugins.jetbrains.com/plugin/9333-makefile-support)プラグインの設定と使い方を紹介します。

# うれしいこと

* シンタックスハイライトができて可読性が向上する
* 補完機能が使える
* MakefileをIntellijで実行できる

# プラグインの導入と設定

まずはPreferences>Pluginsで「Makefile」を選択してインストール。

### ファイルパターンの確認と設定

プラグインをインストールするとFile Typesに「GNU Makefile」が追加され、
以下のファイルパターンがMakefileとしてサポートされます。

<img width="612" alt="File Types" src="https://qiita-image-store.s3.amazonaws.com/0/88483/33543563-819d-10ff-f976-1155539517c4.png">
必要に応じて上記のPreferences>Editor>File Types>GNU Makefileにパターンを追加します。

### シンタックスハイライト

デフォルトでもある程度色分けされるのですが、以下を変更すると可読性が向上します。
設定はPreferences>Editor>Color Scheme>Makefileから行います。

* Target
    * 「Inherit values from」 のチェックを外す
    * Foregroundを目立つ色に変える
    * Boldをチェック
* Variable Names
    * 同様にお好みに設定

<img width="749" alt="Color Scheme" src="https://qiita-image-store.s3.amazonaws.com/0/88483/102433e2-7e8e-ad27-41d1-f5131829221f.png">

# 使い方

こんな感じで色分け、補完などができます。※common.mkを同じディレクトリに配置してあります。

```common.mk
setup:
	@echo "setup"
```

![makefile_intellij.gif](https://qiita-image-store.s3.amazonaws.com/0/88483/79ccc2e9-a710-65f8-7bf9-f3875a57de25.gif)

includeしたファイル内のtargetは補完も解決もできないですが、十分便利です。

また、Makefileの実行には以下3つの方法などがあります。

1. targetの左にある▶をクリックして実行
2. 開いているファイルで右クリック>Run 'Makefile'
3. Run Configurationに登録して実行  
    開いているファイルで右クリック>Create 'Makefile'から登録。登録後はRunから実行

# その他

その他の機能はプラグインのREADMEを参照下さい。
https://github.com/kropp/intellij-makefile
Web上でカメラ撮影してJavaScriptで処理したい

最近、Webアプリでカメラで撮ったものをWebAPIに投げたい、というのを何度か書いており、ついでにここに書いておきます。

### PC

Media Streams APIを使って画像に変換する、ということにしました。

お役立ちドキュメントは以下です。

- https://developer.mozilla.org/ja/docs/Web/API/MediaDevices/getUserMedia
- https://developer.mozilla.org/ja/docs/Web/API/MediaDevices/enumerateDevices

雑に使うだけなら、`enumerateDevices`は使わなくてもできますが、カメラを選ばせたいときは必要です。

また、上記のサンプルコードには書いてないですが、MediaStreamもリソースなのでちゃんと閉じる処理を書く必要があります。
具体的には、Mediastream#getTracksでMediaTrackを複数取得し、その後、MediaTrack#stopを呼ぶ感じです。


以下、Vueでそれっぽく実装したデモです。
ボタンを押したらCanvasに転写して画像データをURLに変換してImageタグを埋め込むだけです。

Demo: https://jsfiddle.net/4r8djy7c/

カメラが無いデバイスだと、`mediaDevices.getUserMedia`で失敗するので、catchでいい感じにやりましょう。


### SmartPhone

なんでPCとSmartPhoneを分けているかというと、SmartPhoneではうまく動作しなかったからです。頑張って書いたのに！

同じコードで動かず悩みましたが、別のワークアラウンドを使う事にしました。
以下のように`<input type="file">`へ`capture`属性を付けるとカメラで撮影したものをファイルとして扱えるようになります。

https://www.w3.org/TR/html-media-capture/#the-capture-attribute

一応、すぐに試せるのがあったほうが良いと思い、簡単ですが動くやつを書きました。モバイル用にQRも乗っけておきます

Demo: https://jsfiddle.net/fw4jyn95/1/

![image.png](https://qiita-image-store.s3.amazonaws.com/0/52527/dfc5f817-8bd2-e01d-047d-4069fccdeb43.png)
https://fiddle.jshell.net/fw4jyn95/1/show/




これはW3Cの[Device and Sensors WG](https://www.w3.org/wiki/DAS/Implementations)の成果物で、現状、SmartphoneのAndroidやiPhone等で動作します。ステータスは・・・どうなんだろう？

また、`capture`属性には`environment`(リアカメラ)か`user`(フロントカメラ)のいずれかを与えます。大半は`environment`で問題ないですが、地鶏アプリなら`user`という感じです。
なお、PCで使ってたMediaStream APIでも同様にどちらのカメラを使うようにするか設定ができます。

このおかげで、導線はボタンを用意するだけで、UIもカメラの許可/拒否もデバイスに丸投げ出来ます。良いですね。


次に、`<input type="file">`の見た目が良くないのでボタンにしたい！となると思います。
そうなると、`display: none`で隠して別のボタンからclickさせる等をするのですが、もしcreateElementを使う方法でやる場合は、以下の点も注意してください。

iOS-Safariで`<input type="file">`のChangeイベントを拾うときの注意
https://qiita.com/fukasawah/items/b9dc732d95d99551013d

蛇足ですが、PCとSmartphoneの判断をUserAgentで行う場合、wootheeが便利です。
https://github.com/woothee/woothee
Node.jsのrequireの引数に変数を利用して動的に読み込む

## 環境

Node.js v10.13.0

## 本題

requireを使って他のモジュールやファイルを__動的に__読み込みたい場合、
変数をrequireの引数に利用することになる。

しかし、以下のようにすると上手くいかない。

```上手くいかない.js
let path = 'path/foo';
require('./' + path);
```
`require(...)`とした場合には引数は__静的__である必要があるらしい。

なので、以下のようにコールバックを利用して動的な読み込みをおこなう。

```正しく動く.js
let path = './path/foo';
require([path], function (foo)
    // path/fooモジュールが変数fooにロードされている
);
```

コールバックなので若干使い勝手は悪いけれど、
条件によって読み込むモジュールを変更できるのは便利。

## 参考文献

参考文献というか、公式サイトに上の内容がちゃんと書かれていた...

- [require.js](https://requirejs.org/docs/errors.html#notloaded)
Nuxt.jsでストアが動かなかった

# Nuxt.js触りたくなった

https://ja.nuxtjs.org/

# 起こったこと

試しにtodoアプリでも作ろうかな〜と思いプロジェクトを作成

```bash:プロジェクトの作成
$ npx create-nuxt-app nuxt-todo
npx: 379個のパッケージを9.455秒でインストールしました。
> Generating Nuxt.js project in /Users/aroma/work/nuxt-todo
? Project name nuxt-todo
? Project description todo app
? Use a custom server framework none
? Choose features to install (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Use a custom UI framework bootstrap
? Use a custom test framework none
? Choose rendering mode Single Page App
? Author name aromanokarisu
? Choose a package manager npm
```
```bash:プロジェクトを起動
$ cd nuxt-todo
$ npm run dev
```

ストアを確認してみようと、ドキュメントの通り `store/index.js` を作ってもストアが有効化されなかった。
https://ja.nuxtjs.org/guide/vuex-store/

```bash:ストアの有効化_./store/index.js作成
$ vim ./store/index.js
$ cat ./store/index.js
import Vuex from 'vuex'

const createStore = () => {
  return new Vuex.Store({
    state: () => ({
      counter: 0
    }),
    mutations: {
      increment (state) {
        state.counter++
      }
    }
  })
}

export default createStore
$
```
```bash:ストアの有効化_ストア使用
$ vim ./pages/index.vue
$ cat ./pages/index.vue
<template>
  <button @click="$store.commit('increment')">{{ $store.state.counter }}</button>
</template>
$
```
http://localhost:3000/
→ `Cannot read property 'state' of undefined`
stateが未定義...??
<img width="503" alt="スクリーンショット 2019-03-23 20.13.26.png" src="https://qiita-image-store.s3.amazonaws.com/0/224357/7712b6a5-6838-37d6-be8e-194c83984b58.png">

# 結論
アプリを終了して、また`npm run dev` やり直したら動いた...。
有効化したら再起動はよくある話だけど、ちょっとハマってしまった。
NW環境を作った時のまとめ

NW環境を作った時のまとめです<(_ _)>

今回はとあるきっかけで作ったNW環境を晒していきます。
本当に単純なものなのです<(_ _)>

# 全体図
まず全体図としてはこんな感じ↓↓↓　ほんとはちょっと違うけど・・

![トぽ図 - コピー.JPG](https://qiita-image-store.s3.amazonaws.com/0/380890/82d25f28-a33f-b915-7f5d-fe3fd6e59fcb.jpeg)



ルーターはcisco841Mを使用しました。
この環境だとただルーター挟んで優先で繋げただけなので`ACL(アクセスコントロールリスト)`の設定を
追加して特定のサイトに繋がらなくなるようにしました。

次はルーターについて触れていきたいと思います。


# 設定コマンド

次にルーターに打ち込んだコマンドです↓↓↓
`ACL(アクセスコントロールリスト)`の設定は下から3~4行の部分です。
再現しようと思うならXXX.XXX.XXX.XXXの部分を適当なサイトのIPアドレスをnslookupコマンドなりで調べて打てばいいと思います。

```
enable
conf ter

hostname cisco841M

ip dhcp pool aaaa
 network 192.168.10.0 255.255.255.0
 dns-server 8.8.8.8
 default-router 192.168.10.1

router ospf 1
 network 192.168.10.0 0.0.0.255 area 0
 network 192.168.24.0 0.0.0.255 area 0

int gi0/4
ip address 192.168.10.1 255.255.255.0
ip access-group 100 in
no shutdown

int gi0/5
ip address dhcp
no shutdown

access-list 1 permit any //以下の文からACLの設定
access-list 100 deny   tcp any host XXX.XXX.XXX.XXX　//アクセスを遮断したいサイトのIPアドレスを指定する。
access-list 100 permit ip any any
```



# ルーターのshow run
設定済みのルーターのshow runを上の方に貼ろうとしたが思ったより長くて邪魔に感じたので最後に貼っておきます。

```
cisco841M#sh running-config
Building configuration...

Current configuration : 1329 bytes
!
! Last configuration change at 14:12:18 UTC Tue Jan 8 2019
!
version 15.5
service timestamps debug datetime msec
service timestamps log datetime msec
no service password-encryption
!
hostname cisco841M
!
boot-start-marker
boot-end-marker
!
!
!
no aaa new-model
ethernet lmi ce
!
!
!
!
!
!
ip dhcp pool aaaa
 network 192.168.10.0 255.255.255.0
 dns-server 8.8.8.8
 default-router 192.168.10.1
!
!
!
ip cef
no ipv6 cef
!
!
license udi pid C841M-4X-JSEC/K9 sn FGL202920X1
!
!
!
redundancy
!
!
!
!
!
!
!
!
!
!
!
!
!
!
interface GigabitEthernet0/0
 no ip address
!
interface GigabitEthernet0/1
 no ip address
!
interface GigabitEthernet0/2
 no ip address
!
interface GigabitEthernet0/3
 no ip address
!
interface GigabitEthernet0/4
 ip address 192.168.10.1 255.255.255.0
 ip access-group 100 in
 duplex auto
 speed auto
!
interface GigabitEthernet0/5
 ip address dhcp
 duplex auto
 speed auto
!
interface Vlan1
 no ip address
!
router ospf 1
 network 192.168.10.0 0.0.0.255 area 0
 network 192.168.24.0 0.0.0.255 area 0
!
ip forward-protocol nd
no ip http server
no ip http secure-server
!
!
!
!
!
access-list 1 permit any
access-list 100 deny   tcp any host xxx.xxx.xxx.xxx
access-list 100 permit ip any any
!
 vstack
!
line con 0
 no modem enable
line vty 0 4
 login
 transport input none
!
scheduler allocate 20000 1000
!
end

```
【WordPress・プラグインなし】ページごとにmeta情報（keywords、description）を設定する方法

デフォルトのWordpressにはSEOに重要なkeywordsやdescriptionが含まれていないため追加する必要がありますが、
header.phpに直書きで追加すると全ページ同じmeta情報が表示されてしまいます。

そこで、固定ページや記事ごとにカスタムフィールドを設置してmetaを設定する方法を紹介します。

まず、以下のコードをfunctions.phpに追加します。

```functions.php
// keywords description
add_action('admin_menu', 'add_custom_fields');
add_action('save_post', 'save_custom_fields');

// 記事ページと固定ページでカスタムフィールドを表示
function add_custom_fields() {
  add_meta_box( 'my_sectionid', 'カスタムフィールド', 'my_custom_fields', 'post');
  add_meta_box( 'my_sectionid', 'カスタムフィールド', 'my_custom_fields', 'page');
}
function my_custom_fields() {
  global $post;
  $keywords = get_post_meta($post->ID,'keywords',true);
  $description = get_post_meta($post->ID,'description',true);
  echo '<p>キーワード（半角カンマ区切り）<br>';
  echo '<input type="text" name="keywords" value="'.esc_html($keywords).'" size="60"></p>';
  echo '<p>ページの説明（description）160文字以内<br>';
  echo '<input type="text" style="width: 600px;height: 40px;" name="description" value="'.esc_html($description).'" maxlength="160"></p>';
}

// カスタムフィールドの値を保存
function save_custom_fields( $post_id ) {
  if(!empty($_POST['keywords'])){
    update_post_meta($post_id, 'keywords', $_POST['keywords'] );
  }else{
    delete_post_meta($post_id, 'keywords');
  }
  if(!empty($_POST['description'])){
    update_post_meta($post_id, 'description', $_POST['description'] );
  }else{
    delete_post_meta($post_id, 'description');
  }
}
function MataTitle() {
  // カスタムフィールドの値を読み込む
  $custom = get_post_custom();
  if(!empty( $custom['keywords'][0])) {
    $keywords = $custom['keywords'][0];
  }
  if(!empty( $custom['description'][0])) {
    $description = $custom['description'][0];
  }
  if(is_home()){// トップページ
    echo '<meta name="keywords" content="'.$keywords.'">';
    echo '<meta name="description" content="'.$description.'">';
  }elseif(is_single()){// 記事ページ
    echo '<meta name="keywords" content="'.$keywords.'">';
    echo '<meta name="description" content="'.$description.'">';
  }elseif(is_page()){// 固定ページ
    echo '<meta name="keywords" content="'.$keywords.'">';
    echo '<meta name="description" content="'.$description.'">';
  }elseif(is_archive()){// 記事ページ
    echo '<meta name="keywords" content="'.$keywords.'">';
    echo '<meta name="description" content="'.$description.'">';
  }elseif(is_category()){// カテゴリーページ
    echo '<meta name="description" content="'.single_cat_title().'の記事一覧">';
  }elseif(is_tag()){// タグページ
    echo '<meta name="robots" content="noindex, follow">';
    echo '<meta name="description" content="'.single_tag_title("", true).'の記事一覧">';
  }elseif(is_404()){// 404ページ
    echo '<meta name="robots" content="noindex, follow">';
    echo '<title>404:お探しのページが見つかりませんでした</title>';
  }else{// その他ページ
    echo '<meta name="robots" content="noindex, follow">';
  };
}
```

次に、header.phpなどmetaを追加したい場所に作成した関数を設置します。

```header.php
<?php MataTitle(); ?>
```
Homebrew でパッケージの依存関係を調べる方法

`brew list` をすると見知らぬパッケージがあり、消してもいいものなのか迷ったのでメモ。

# インストール済みのすべてのパッケージの依存関係

```shell
$ brew deps --installed
```

`--tree` をつけると階層状に表示される。
<img width="311" alt="SS 2019-03-26 at 20.01.59.png" src="https://qiita-image-store.s3.amazonaws.com/0/155587/2062a6b6-b64d-7e88-dea4-c6fdadaf87e3.png">

# 指定したパッケージが何に依存しているか

```shell
$ brew deps <パッケージ>
```

同じく `--tree` をつけると階層状に表示される。

# 何が指定したパッケージに依存しているか

```shell
$ brew uses <パッケージ>
```

`--installed` をつけるとインストール済みのもののみ表示される。

# 他のパッケージと依存関係のないものを表示

```shell
$ brew leaves
```

# 参考
https://yu8mada.com/2018/06/08/how-to-list-homebrew-dependencies/
http://w6o6n.blog.fc2.com/blog-entry-153.html?sp
Windows10にvagrantでCentOS7環境を作ってTeraTermで接続する

#動機
これまで自宅でPHPコードを書くときはXAMPP+CodeIgniterだったのですが、
たまたまLaravelを学ぶ機会があり、自宅のWin10にもCentOS7上でPHPが動く環境が欲しくなりました。

#最初にダウンロードするもの
VirtualBox
https://www.oracle.com/technetwork/server-storage/virtualbox/downloads/index.html
Vagrant
https://www.vagrantup.com/downloads.html
TeraTerm
https://ja.osdn.net/projects/ttssh2/


#vagrantに使うディレクトリを決める
コマンドプロンプトを開き、`cd`でvagrantに使うディレクトリ（任意）に移動します。

#vagrant initする
今回はCentOS7のboxを作成したいので、以下のサイトからCentOS7を探します。
https://app.vagrantup.com/boxes/search

ページの上のほうに How to use this box with Vagrant: という項目があり、VagrantfileとNewのタブがあります。
今回はNewタブのほうを使います。
タブを選択し、必要なコマンドが`vagrant init centos/7`と`vagrant up`であることを確認します。

コマンドプロンプトに戻り、先ほどcdしたディレクトリにいることを確認したら、

```
vagrant init centos/7
```
を実行してください。うまくゆくとディレクトリの中にVagrantfileというファイルが生成されています。

#Vagrantfileを編集し、起動する
ローカル接続用のIPアドレスを変更します。
Vagrantfileを確認すると、

```
# config.vm.network "private_network", ip: "192.168.33.10"
```

という部分がありますが、コメントアウト用の`#`を外して記述を有効にしてください。
また、`192.168.33.10`以外で接続したい場合は任意のIPアドレスに変更します。

ここまで出来たらvagrantを起動します。コマンドプロンプトで以下のコマンドを入力します。

```
vagrant up --provider virtualbox
```

起動が完了したら、

```
vagrant ssh
```

を入力し、接続できることを確認します。


#TeraTermでSSH接続する
TeraTermで設定したIPアドレス（ポートは22）に、秘密鍵を使用してSSH接続できたら成功……なのですが、
秘密鍵はどこにあるのか？自分で生成するのか？といったことが分からず詰まっていました。

今回の私の場合ですが、
vagrantに使うディレクトリの中にある
`.vagrant\machines\default\virtualbox`
に、`private_key`というファイルがありました。
※拡張子.ppkがないため、Teratermから直接選択する場合は対象を`すべてのファイル(*.*)`にしないと表示されません

![1.png](https://qiita-image-store.s3.amazonaws.com/0/382896/c6056357-0027-9ae4-98c9-974e95d03ba4.png)

このprivate_keyをコピーし、拡張子`.ppk`を付けて秘密鍵として使用します。
ユーザー名`vagrant`、パスワード`vagrant`で、無事に接続できれば作業完了です。

※vagrantを終了するときはコマンドプロンプトで`vagrant halt`です。
Goのmodulesを試してみたメモ

最近、Goを勉強しているのですが、一番最初にハマったのは実は$GOPATH内で作業しなければならない、という部分でした。

個人的にはいろいろな技術を試す場所をPC内で独自に決めていたので(例えば~/workみたいに)、この制約苦しいな、と思っていたら、今はmodulesというものがあることを知りました。

これなら$GOPATHでない所でもパッケージが見つからない問題が解消しそうだと思い、試してました。

誰かの参考になれば、と思いメモしておきます。

# 環境
go version 1.12.1

# 作るもの
以下のような構成で、main.goからtest.goを呼び出すだけの簡単なプログラムを作ります。

```
.
├── main.go
└── test
    └── test.go
```


```main.go
package main

import (
  "fmt"
  "test"
)

func main() {
  fmt.Println("main")
  test.Test()
}
```

```test.go
package test

import "fmt"

func Test() {
  fmt.Println("test")
}
```

そしてmain.goを実行してみます。
するとtestなんてpackageはない、と怒られます。

```
:!go run main.go
main.go:5:3: cannot find package "test" in any of:
```

# modulesでpackage問題を解消する
ここでmodulesの出番です。

以下のようなコマンドを打つことで、ここが"modtest"というモジュールであることをどうやら指定する模様。

実行するとgo.modというファイルが出来ます。これがモジュールを宣言することになっているようです。

```
go mod init modtest
```

あとはimport部分を以下のように修正する。

```main.go
package main

import (
  "fmt"
  "modtest/test"  // この部分をmodtest/testに修正する
)

func main() {
  fmt.Println("main")
  test.Test()
}
```

正しく実行できました。

```
:!go run main.go
main
test
```

modulesのことを知るまではdirenvとかで$GOPATHに現在のパスを指定する、など微妙に面倒なことをしていました。

# 参考
https://qiita.com/yoshinori_hisakawa/items/268ba201611401ca7935
https://qiita.com/spiegel-im-spiegel/items/5cb1587cb55d6f6a34d7
[Homebrew] cannot load such fileなどのエラーの対処法

Homebrew を久しぶりに使おうとしたら以下のようなエラーが発生したのでメモ。

```shell
$ brew --help
/System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require': cannot load such file -- active_support/core_ext/object/blank (LoadError)
	from /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in `require'
	from /usr/local/Homebrew/Library/Homebrew/global.rb:10:in `<top (required)>'
	from /usr/local/Homebrew/Library/Homebrew/brew.rb:21:in `require_relative'
	from /usr/local/Homebrew/Library/Homebrew/brew.rb:21:in `<main>'
```

`brew style` を実行するも変わらず。
(https://stackoverflow.com/questions/54888582/ruby-cannot-load-such-file-active-support-core-ext-object-blank)

また、`sudo chown -R $(whoami):admin /usr/local` は権限がないと言われ、

```shell
$ sudo chown -R $(whoami):admin /usr/local
chown: /usr/local: Operation not permitted
```

`sudo chown -R $(whoami) $(brew --prefix)/*` を実行するも変わらず。
(https://qiita.com/k-hotta/items/7236f68ef26f7771b02f)

# 対処法

公式サイトのコマンドから再インストールすると解決した。
https://brew.sh/index_ja

```shell
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```
[Rails] TwitterAPI（omniauth-twitter）とdeviseを使用して新規登録（サインアップ）できないとき

# 問題
deviseとomniauth-twitterを使ってTwitterログインできるようにしようと
各種設定を行ったが、新規登録をするとエラーが発生してしまう。

自分は`models/user.rb`にはこのような記述をした

```ruby:models/user.rb
  def self.from_omniauth(auth)
    find_or_create_by(provider: auth[:provider], uid: auth[:uid]) do |user|
      user.uid = auth[:uid],
      user.provider = auth[:provider],
      user.username = auth[:username]
    end
  end
```

その結果、新規登録ボタンを押しても

```ruby:
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."provider" = ? AND "users"."uid" = ? LIMIT ?  [["provider", "twitter"], ["uid", "伏せますね"], ["LIMIT", 1]]
  ↳ app/models/user.rb:9
   (0.0ms)  begin transaction
  ↳ app/models/user.rb:9
   (0.0ms)  rollback transaction
```
とロールバックしてしまい登録できない。

<br>

# 原因
原因はすぐにわかった。
Userモデルには、Twitter登録用に`uid, provider, username`という3つの
カラムを登録したが、それとは別に通常ログイン用の `email`や `password`カラムもある。
（ `rails g devise:model User`時に自動設定されるはず）
<br>
てことは`email`や `password`にはvalidationが設定されているため、
`uid, provider, username`と一緒に<b>`email, password`にもvalidationを
満たすような値を設定しなければならない。</b>

<br>

# 解決策
<b>email, passwordにダミーの値を入れて解決した。</b>

```ruby:models/user.rb
#  def self.from_omniauth(auth)
#    find_or_create_by(provider: auth[:provider], uid: auth[:uid]) do |user|
#      user.uid      = auth[:uid],
#      user.provider = auth[:provider],
#      user.username = auth[:username],
      user.email    = self.dummy_email(auth),       #emailにダミーを設定する
      user.password = Devise.friendly_token[0, 10]  #passwordに適当な値を設定する
#    end
#  end

  private

  def self.dummy_email(auth)
    "#{auth[:username]}_#{auth[:uid]}@example.com"
  end
```

# ちなみに
`user`が一人も登録されていないとする。

`user.rb`に`uid, provider, username`だけ設定してTwitterでログインしようとすると、
登録失敗後、<b>`uid, provider, username`がキャッシュされる場合がある。</b>

その場合、その後に（通常の）新規登録画面で、`email`や`password`を入力して新規登録すると、
フォームで設定された値によっては<b>`uid, providerm username`がキャッシュされたまま
id=1のユーザとして登録されてしまう</b>ので、注意が必要。

つまり、`uid, provider, username`で登録（失敗）して、
それとは別に`email, password`で登録したはずなのに
<b>`uid, provider, username, email, password`をもつuserが作られてしまうということ。</b>

<br>
登録後にコンソールで`User.all`打って確認する必要がありそう。。

<br>
おわり
【WordPress・プラグインなし】ページタイプごとにタイトルを変更する方法



```functions.php
function change_document_title_parts( $title_parts ){
  // デフォルトタイトルをリセット
  $title_parts['title'] = '';
  $title_parts['tagline'] = '';
  $title_parts['site'] = '';

  $site_name = trim( get_bloginfo('name') );
  if(is_front_page()): //フロントページ
    $title_parts['title'] = trim( get_the_title() );
    $title_parts['site'] = $site_name;
  elseif(is_singular()): //投稿ページ
    $title_parts['title'] = trim( get_the_title() );
    $title_parts['site'] = $site_name;
  elseif(is_archive()): //アーカイブページ
    $title_parts['title'] = '「'.$title_parts['title'].'」のアーカイブ';
  elseif(is_search()): //検索結果ページ
    $title_parts['title'] = $title_parts['title'];
    $title_parts['site'] = $site_name;
  elseif(is_404()): //404
    $title_parts['title'] = 'お探しのページは見つかりませんでした';
    $title_parts['site'] = $site_name;
  endif;

  return $title_parts;
}
add_filter( 'document_title_parts', 'change_document_title_parts' );
```
argumentsプロパティの理解と使用例。

argumentsプロパティたるものと、その使用例を、感覚的に理解するためのメモ。
【前提知識】[for...of 文](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/for...of)
#argumentsとは？
- 実引数のこと。
- 関数を呼び出す際に入力される引数のこと。
- 実引数は、関数が持つプロパティのうちのひとつなので、積極的に取得できる。
 - argumentsというプロパティに、配列とおなじ形で代入されている。
 - 例：第一引数 → arguments[0]

##【使用例】

```javascript:使用例.js
const xxx = ()=> {
  for ( let index in xxx.arguments ) {
    console.log ( xxx.arguments[index] );
  }
};
//これで、渡された引数をすべてconsoleに表示することができる。
//map関数の引数バージョンのようなイメージ。

xxx(1,2,3,4,5); 
//1
//2
//3
//4
//5
```

##注
アロー関数では使用不可。
Eclipseの日本語化

## Eclipse IDEの表示を日本語化する
babelプロジェクトのランゲージパックを適用して日本語化したときのメモ。

- Eclipse IDE for Java Developers
- Version: 2019-03 (4.11.0)

[Eclipse Babelプロジェクト](https://www.eclipse.org/babel/downloads.php)
![babel](https://qiita-image-store.s3.amazonaws.com/0/383325/5a389676-a588-30db-fbdf-bbcffd1bbf5b.png)

## ワークスペースのエンコードをMS932からUTF8へ変更
利用上特にMS932である必要性が無いので、変更しています。
![Encode](https://qiita-image-store.s3.amazonaws.com/0/383325/ea9f38b3-8d5b-5c71-a1e9-495bb33f81d6.png)

## フォントがconsoalsだと日本語が文字化けしてしまうようだ
コメントが文字化けしている・・・
![bakebake](https://qiita-image-store.s3.amazonaws.com/0/383325/a019180f-897d-ccc6-454d-1017f266e5f5.png)
![Consolas](https://qiita-image-store.s3.amazonaws.com/0/383325/40e65104-7950-6dd6-3321-6560fea47edd.png)

## コメントの文字化けが解消した。これで準備完了。
![clear](https://qiita-image-store.s3.amazonaws.com/0/383325/58aa1116-88c6-b90c-2c8c-cdb0ebbc2e7a.png)
Materializeでcol系のクラスとvideo-containerを同じタグ内で使ってはいけない

### 概要
* Materializeのvideo-containerクラスを使うとyoutubeとかの動画埋め込みを簡単にレスポンシブにできて便利
  * https://materializecss.com/media-css.html
* でも使いかたをミスると動画が出てこなくなるので注意

### コード

だめな例、正しい例、video-container使わないで頑張る例、それぞれのコード

```video-container.html
<html>
    <head>
        <!-- Compiled and minified CSS -->
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">

        <!-- Compiled and minified JavaScript -->
        <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script> 
    </head>
    <body>
        <div class="row">
            <!-- colとvideo-containerを同じdivで使うと動画が出てこない -->
            <div class="col s4 video-container">
                <iframe src="https://www.youtube.com/embed/M1RIUrgJqWw" frameborder="0"></iframe>
            </div> 
            <!-- colとvideo-containerを入れ子にするとちゃんと出てくる -->
            <div class="col s4">
                <div class="video-container">
                    <iframe src="https://www.youtube.com/embed/M1RIUrgJqWw" frameborder="0"></iframe>
                </div>
            </div>
            <!-- 参考: 自力でレスポンシブ対応する場合 -->
            <div class="col s4">
                <div style="position: relative; width: 100%; height: 0; padding-top: 56.25%">
                    <iframe src="https://www.youtube.com/embed/M1RIUrgJqWw" frameborder="0" 
                    style="position:absolute; top:0; left: 0; width: 100%; height: 100%"></iframe>
                </div>
            </div>
        </div>
    </body>
</html>
```

### 実行例
間違った使い方をすると左側のように何も出てこなくなる
![video_container_sample.png](https://qiita-image-store.s3.amazonaws.com/0/176335/35fd53e6-9d33-fd97-a4eb-3174d98a5714.png)

### 備考

#### video-containerを使わない場合の説明

ググるといっぱい出てくるが、めんどいのでおとなしくフレームワークの機能に乗っかったほうがよさそう

上記のコードからMaterialize依存の部分を取り除くとこうなる

``` responsive-ganbaru.html
                <div style="position: relative; width: 100%; height: 0; padding-top: 56.25%">
                    <iframe src="https://www.youtube.com/embed/M1RIUrgJqWw" frameborder="0" 
                    style="position:absolute; top:0; left: 0; width: 100%; height: 100%"></iframe>
                </div>
```

ぱっと見、何でこれで動くのかわかりにくいが

* 外側のdivで要素の幅に合わせた高さの「箱」 をpadding-topで作る。元の要素の高さは邪魔なので0にしておく。
  * padding-topは%を指定すると要素のwidthに対する割合の値をpaddingしてくれる
  * なので、16:9の場合は 9/16 = 56.25% にしておくとwidthの56:25%の高さの箱ができていい感じになる
  * https://developer.mozilla.org/ja/docs/Web/CSS/padding-top
* 内側のiframeでは要素がピッタリ左上から始まるように位置調整する + 与えられた箱の大きさすべてを使うように指定

ということらしい。

 
#### サンプルで使ってる動画 is 何　という方へ

花譜　#17　「雛鳥」 【オリジナルMV】
https://www.youtube.com/watch?v=M1RIUrgJqWw

みんな聞きましょう。
【Wordpress】カスタムメニューを表示する2つの方法

カスタムメニュー（「外観」>「メニュー」）を使うとWordpress管理画面上でメニューの内容を編集したり自動追加したりできます。

###カスタムメニューを使うための設定

```functions.php
function menu_setup() {
  register_nav_menus( array(
    'header_menu' => 'ヘッダメニュー',
    'footer' => 'フッターメニュー',
  ) );
}
add_action( 'after_setup_theme', 'menu_setup' );
```

##1. 基本的な表示方法

メニューを表示したい箇所にwp_nav_menu関数を使います。

```header.php
<?php 
wp_nav_menu(array(
　'theme_location' => 'メニュー名'
));
?>
```
パラメータを追加する場合は以下のようなものがあります。

```header.php
$args = array(
	'menu'            => '',
	'menu_class'      => 'menu', // メニューを構成するul要素につけるCSSクラス名
	'menu_id'         => '{メニューのスラッグ}-{連番}', // メニュを構成するul要素につけるCSSI ID名
	'container'       => 'div', // ulを囲う要素を指定。div or nav。なしの場合には false
	'container_class' => 'menu-{メニューのスラッグ}-container', // コンテナに適用するCSSクラス名
	'container_id'    => '', // コンテナに適用するCSS ID名
	'fallback_cb'     => 'wp_page_menu', // メニューが存在しない場合にコールバック関数を呼び出す
	'before'          => '', // メニューアイテムのリンクの前に挿入するテキスト
	'after'           => '', // メニューアイテムのリンクの後に挿入するテキスト
	'link_before'     => '', // リンク内の前に挿入するテキスト
	'link_after'      => '', // リンク内の後に挿入するテキスト
	'echo'            => true, // メニューをHTML出力する（true）かPHPの値で返す（false）か
	'depth'           => 0, // 何階層まで表示するか。0は全階層、1は親メニューまで、2は子メニューまで
	'walker'          => '', // カスタムウォーカーを使用する場合
	'theme_location'  => '', // メニュー位置を指定
	'items_wrap'      => '<ul id="%1$s" class="%2$s">%3$s</ul>', // メニューアイテムのラップの仕方。%1$sには'menu_id'のパラメータ展開、%2$sには'menu_class'のパラメータ展開、%3$sはリストの項目が値として展開
);
wp_nav_menu($args);
```
[各パラメータの詳細](https://wpdocs.osdn.jp/%E3%83%86%E3%83%B3%E3%83%97%E3%83%AC%E3%83%BC%E3%83%88%E3%82%BF%E3%82%B0/wp_nav_menu#.E3.83.91.E3.83.A9.E3.83.A1.E3.83.BC.E3.82.BF)



##2. メニューにカスタムフィールドなどの値を表示したい場合
`wp_get_nav_menu_items`を使用して回します。

以下の例では、
カスタムメニューアイテムに設置したカスタムフィールド（画像）の値を
`$menu => 'カスタムフィールド名'`で取得しています。

```header.php
<ul>
<?php
$main_menu = wp_get_nav_menu_items('メニュー名', array());
  foreach($main_menu as $menu){
    $icon = wp_get_attachment_image_src($menu->icon, 'full');
    $alt = get_post_meta($menu->icon, '_wp_attachment_image_alt', true);
    echo '<li><a href="'.$menu->url.'"><img src="'.$icon[0].'" alt="'.$alt.'">'.$menu->title.'</a></li>';
}
?>
</ul>
```

###サブメニュー（副項目）がある場合
`$menu->ID`（各メニューのID）と`$menu->menu_item_parent`（親メニューのID）が一致するかどうかで出し分けます。

```header.php
<ul>
<?php
$main_menu = wp_get_nav_menu_items('メニュー名', array());
$count = 0;
$submenu = false;

foreach($main_menu as $menu){
  if(!$menu->menu_item_parent){
    $parent_id = $menu->ID;
    echo '<li><a href="'.$menu->url.'">'.$menu->title.'</a>';
  }
  if($parent_id == $menu->menu_item_parent){
    if(!$submenu){
      $submenu = true;
      echo '<ul class="footer_lower-menu">';
    }
    echo '<li><a href="'.$menu->url.'">'.$menu->title.'</a></li>';
    if($main_menu[$count + 1]->menu_item_parent != $parent_id && $submenu){
      echo '</ul>';
      $submenu = false;
    }
  }
  if($main_menu[$count + 1]->menu_item_parent != $parent_id){
    echo '</li>';
    $submenu = false;
  }
  $count++;
}
?>
</ul>
```
ローカル開発環境でApollo ClientからMicroへ通信するときのCORS設定

# はじめに
`node.js` によるGraphQLサーバーを実装している時にCORS関係のエラーで嵌ったので共有しておきます。
尚、`CORS`については既にいろいろな方が解説されているので説明は省きます。

# 前提
* サーバー側: `Micro`: v9.3.3
* クライアント側: `Apollo Client`: v2.4.8
* サーバー, クライアント共にローカル開発環境で動いている

# 症状
ローカル開発環境で、`GraphQL Playground` では動作確認できるのに `Apollo Client` から正しいGraphQLクエリを投げているのにも関わらず `Error: "Network error: NetworkError when attempting to fetch resource."` が出る。

# 原因 & 解決策
`CORS` の仕様で単純リクエストでないリクエストの時に発生する `preflight request` にサーバー側が対応できていなかったので対応できるようにする。

# `preflight request` とは
[この記事](https://qiita.com/nnishimura/items/1f156f05b26a5bce3672) などで詳しく解説されているので参考にしてください。要は `CORS` 時に発生することのある `OPTION` リクエストのことらしいです。 今回の場合は `micro-cors` によってレスポンスヘッダが適切に設定されているので `200` を返すだけで大丈夫です。

# 例
`micro-cors` を使用しています。

```typescript
import { send } from 'micro'
import { get, post, router, options } from 'microrouter'
import { ApolloServer } from 'apollo-server-micro'
import { schema } from './schema'

const apolloServer = new ApolloServer({ schema })
const graphqlPath = '/graphql'
const graphqlHandler = apolloServer.createHandler({ path: graphqlPath })

module.exports = cors({
  allowMethods: ['GET', 'POST']
})(
  router(
    post(graphqlPath, graphqlHandler),
    get(graphqlPath, graphqlHandler),
    // to respond with a preflight request
    options(graphqlPath, (_, res) => send(res, 200)),
    (_, res) => send(res, 404, 'Not Found'),
  )
)
```

若干説明不足な感じもしますが問題解決の一助となれば幸いです。

# 参考
* <https://stackoverflow.com/questions/11001817/allow-cors-rest-request-to-a-express-node-js-application-on-heroku>
* <https://stackoverflow.com/questions/53012629/apollo-client-sending-options-instead-of-get-http-method>
* <https://www.npmjs.com/package/micro-cors>
DB2についての個人的まとめ

#この記事について#
自分の備忘録として、DB2全般についての自分の考えや調べたことを記載していきます。
ほぼリンク集として使用。
経験が浅いので、間違っていることもあると思いますがご容赦ください。


#小技

| 事項       |       説明|       参照|
|:-----------------|:------------------|:------------------|
|SETコマンド(CLPPLUS)|使用例<br> SQL>SET HEADING OFF<br>列見出しの表示を使用不可にします。|[SET CLPPlus コマンド](https://www.ibm.com/support/knowledgecenter/ja/SSEPGG_9.7.0/com.ibm.swg.im.dbclient.clpplus.doc/doc/r0054132.html)|
PHP　3項演算子

# 3項演算子の使い方

知らなかったのでメモです。

## 要約
- 条件演算子のうちの一つ

~~~php
<?php
// 三項演算子の使用例
$action = (empty($_POST['action'])) ? 'default' : $_POST['action'];

// 上記は以下の if/else 式と同じです。
if (empty($_POST['action'])) {
    $action = 'default';
} else {
    $action = $_POST['action'];
}

?>
~~~


## 書き方
```(式１) ? (式2) : (式3);```
式1の条件がTRUE(つまり、合ってるよーって時)、式2が発動する。
式1の条件がFALSE(つまり、間違ってるよーって時)、式3が発動する。

そんな感じです。
Pythonを使ってターミナルサーバ経由でNW機器を操作する方法

# はじめに
Cisco IOSなどのNW機器を初期設定する際、USBコンソールケーブル経由で行うのが一般的かと思います。
他の方法として、以下の通りターミナルサーバ経由でSSH/Telnet接続し、「オンライン」の機器とほぼ同じ要領で初期設定することも可能です。

　[ 作業PC ] - ( Ethernet ) - [ ターミナルサーバ ] - ( コンソール ) - [ NW機器 ]

ただし、オンライン接続といくつか異なる点があり、スクリプトがそのまま使えなかったりします。

- ユーザ名/パスワードの入力方法の違い  
ターミナルサーバの設定で入力が省略できたり、プロンプトがターミナルサーバ側の仕様に依存するため、ユーザ名のプロンプトが`login:`になったりする。  
(IOSの場合は`Username:`や`username:`)
- プロンプト表示の違い  
オンライン接続の場合、ログイン時、自動的にプロンプトが表示されますが、ターミナルサーバの場合、明示的にEnterキーを押す必要がある。

NW機器を操作するためのPythonライブラリである`netmiko`は、ターミナルサーバ経由のログインもサポートしており、今回はログインしてshowコマンド実行までの例をご紹介します。


# 事前準備
あらかじめ、以下コマンドで`netmiko`をインストールします。

```
pip install netmiko
```

# Pythonコード
補足はコード内に記載していますが、ポイントは以下の3点です。

- `device_type`を`terminal_server`に指定 (SSHでターミナルサーバへ接続)
- 途中で改行コードを送信
- ログイン後、Redispatchという処理を行う


```python:terminal_server.py
from netmiko import ConnectHandler
from netmiko import redispatch
import time

# デバイス情報を指定
device = {
    'device_type': 'terminal_server',    # 'cisco_ios'ではなく必ずこの値に指定
    'ip': '192.168.100.200',   # terminal serverのIPアドレス
    'port': 3001,   # NW機器に割り当てられたTCPポート番号
    'username': 'admin',   # terminal serverのユーザ名
    'password': 'password',   # terminal serverのパスワード
    'secret': 'test',   # NW機器のenableパスワード
} 

# terminal server経由でNW機器に接続
net_connect = ConnectHandler(**device)

# 改行コードを送信し、後続処理のためにプロンプトを表示させる
net_connect.write_channel("\r")
time.sleep(1)
net_connect.write_channel("\r")
time.sleep(1)

# device_typeを`cisco_ios`に変更し、これ以降Cisco IOS用のクラスを使って処理を行う
redispatch(net_connect, device_type='cisco_ios')

# enableパスワードを入力
net_connect.enable()

# showコマンドを送信
output = net_connect.send_command('show run')
print(output)

# 切断
net_connect.disconnect()
```

# 実行結果
`send_command`で指定した、show runの出力結果が表示されます。

```
'Building configuration...\n\nCurrent configuration : 2601 bytes\n!
(省略)
```
CordovaでAndroidアプリを作る(Vue+Cordova入門)



前回の記事"[Vue.jsで画像を一覧表示する(vue入門)](https://qiita.com/mktshhr/items/5a6712f3122b5db6aee0)"でVueについて記載したが、ここではVueとCordovaを使ったAndroidアプリ開発について記す。

## Cordovaプロジェクト作成
以下のようなコマンドでプロジェクト(ここでは前回と同じ"my-project")を作成する。
事前にAndroid Studioをインストールして、デバッグできる環境を用意しておく。

```bash
# vue cli 3.0, Cordovaのインストール (インストール済みなら不要)
yarn global add @vue/cli
yarn global add cordova

# プロジェクト"my-project"作成 (*2)
vue create my-project

# cordovaのセットアップ（以前の記事(*)の続きの場合はここから）
cd my-project\
vue add cordova
# ここで質問されるため、デフォルトのまま以下のように回答した（適宜変更する）
# ? Name of folder where cordova should be installed src-cordova
# ? ID of the app com.vue.example.app
# ? Name of the app VueExampleAppName
# ? Select Platforms: Android, iOS, Browser, OSX
# 対応するプラットフォームとして全て(Android, iOS, Browser, OSX)のものを選択した。
```
(*1) [Vue.jsで画像を一覧表示する(vue入門)](https://qiita.com/mktshhr/items/5a6712f3122b5db6aee0)
(*2) vueコマンドが使えない場合、パスが通っていない可能性がある。`npm bin -g`で得られるパスを環境変数に追加する。

# デバッグ
デバッグはUSB接続したAndroid端末のアプリからHTTPでPCに接続することで行う。以下のコマンドでデバッグ用のAPKを作成し、Android端末にインストールするとともに、PCにWebサーバを立ち上げる。

```bash
npm run cordova-serve-android
```

画面表示はHTTPが利用されており、PCがWebサーバーとなり画面を提供する。PCにウイルス対策ソフトなどでファイヤーウォールが入っている場合は、該当するポートを開く必要がある。開いているポート(URL)は、`cordova-serve-android` の処理の中で次のように表示される。ここでの例では8080ポートにPCの外部(Androidスマホ)からアクセスできる必要がある。また、AndroidスマホがPCと同じLANに接続されていることに注意する。

```
App running at:
  - Local:   http://localhost:8080 
  - Network: http://192.168.100.135:8080
```

PCのChromeを立ち上げ、 `chrome://inspect` とURL部分に入れると、DevToolsの画面が開き、この中の"Remote Target" に表示されているアプリ（ここでは"my-project"）の下にある"inspect"という文字をクリックすることで新しいウインドウが開き、デバッグ画面が表示される。コンソールの内容が表示されるなど、デバッグ方法はWebアプリとよく似ている。
<img width="1192" alt="AndroidWebDebug.png" src="https://qiita-image-store.s3.amazonaws.com/0/123458/f6a2ae5c-d8d1-313a-114a-54be0d3353de.png">


# APKの作成
```
npm run cordova-build-android
```
でAndroid Studioで読み込めるAndroidプロジェクトフォルダ(/src-cordova/platforms/android)が生成される。このAndroidプロジェクトフォルダをAndroid Studioで開き、Releaseビルドで署名つきAPKを作成すれば、任意の端末にインストールできるAPKを生成できる。

# まとめ
**Webアプリ開発の知見であれば**、比較的簡単にスマートフォンアプリが開発できることがわかった。
DBのデータをコピーするためにasync clipboard APIを試す



The Clipboard API crashcourse - Frontend News #2
https://frontendnews.io/editions/2018-08-01-copy-and-paste-clipboard-api

フォーカスがタブにないとうまくいかないのでdevtoolsでは遅延させてフォーカスを切り替える必要がある。


Async Clipboard APIでJavaScriptからクリップボードを操作する
https://sbfl.net/blog/2018/03/03/async-clipboard-api/

使い方の具体例

IndexedDBの使い方 - Qiita
https://qiita.com/butakoma/items/2c1c956b63fcf956a137

いまはlevelDBというやつなのね

ChromeのIndexedDBの場所 (Mac・Windows) | EasyRamble
https://easyramble.com/path-to-chrome-indexeddb.html

ファイルの場所、でもchromeのは仕様が違うので通常のcliとかではそのままでは扱えない的なコメントをどこかでみた

Promises + IndexedDB Test
https://gist.github.com/robertknight/462d16b46a438ab67e29301861f5d55f

非同期処理をどうするかがよくわからなくて悩んだ。
プロミスの理解をしてこの変換ができるような頭になっておくと便利なのかもだけどよくわからぬ。

```hoge.js
openReq = await indexedDB.open("something");
openReq.onsuccess = async function (event) {
    //onupgradeneededの後に実行。更新がない場合はこれだけ実行
    console.log('db open success');
    //main
    // フォーカスをコンソールではなくタブにする必要がある
    const sleep = msec => new Promise(resolve => setTimeout(resolve, msec));
    console.log('スタート 3秒まつ');
    await sleep(3000);
    console.log('3秒経ってる!')
    function promiseReq(req) {
        return new Promise((resolve, reject) => {
            req.onsuccess = () => resolve(req.result);
            req.onerror = () => reject(req.error);
        });
    }
    let db = event.target.result;
    let objectStore = db.transaction('siteCache', 'readonly').objectStore('siteCache');
    let data = await promiseReq(objectStore.get('hoge'));
    console.log(data);
    await navigator.clipboard.writeText(JSON.stringify(data));
    console.log(JSON.stringify(data));
    // 接続を解除する
    db.close();
};
openReq.onupgradeneeded = function (event) {
    //onupgradeneededは、DBのバージョン更新(DBの新規作成も含む)時のみ実行
    console.log('db upgrade');
};
openReq.onerror = function (event) {
    // 接続に失敗
    console.log('db open error');
};
```
今からRailsを触る人が出くわすエラー集(2019/3)

タイトルの通りです。

## sqlite3 1.4.0
2019/2の時点ではRailsがsqlite3の1.4.0は対応していないらしく、nativeなんたらが「インストールできません」みたいなエラーが発生します。

### 解決策
Rails sで作ったアプリの中のgemfileで、古いバージョンのsqlite3を指定する。

例
gem 'sqlite3'
を
gem 'sqlite3', "1.3.13"
に変更

## rails2.6.1とbundler２
rails2.6.1はbundlerの古いバージョンを固定で使用するような仕様になっているらしく、エラーが発生することがあります。

### 解決策
rbenvを使って、古いバージョンのrubyを指定する。


他のエラーやもっといい解決策等あれば教えてください。

参考リンク
https://ja.stackoverflow.com/questions/52689/ruby-2-6-1-rails-%E3%81%A7-you-must-use-bundler-2-or-greater-with-this-lockfile-%E3%81%8C%E3%81%A7%E3%81%BE%E3%81%99

https://qiita.com/_am_/items/c1dbeb11f40bbbac8fd9
[Rails] deviseのセッション(session)はどのように決められているのか

# deviseが作成したsessionはどれだ？

<b>devise/lib/devise/controllers/helpers.rb</b>
https://github.com/plataformatec/devise/blob/40f02ae69baf7e9b0449aaab2aba0d0e166f77a3/lib/devise/controllers/helpers.rb


```:l.123
 def #{mapping}_session
   current_#{mapping} && warden.session(:#{mapping})
 end
```

`helpers.rb`の123行目には
`#{mapping}_sessionとすればそのセッションを見ることができる`
ということが書いてある。
（mappingは今はuserと考えておけば良い）
<br>

`user_session`を入力すると、

```
[16] pry(#<TopController>)> user_session
=> {"last_request_at"=>1553329704}
```

が返ってくる。

ちなみに先ほどのメソッドの内容から、`warden.session(:user)`としても同様。

```
[15] pry(#<TopController>)> warden.session
=> {"last_request_at"=>1553329704}
```

また、 `session.keys`と入力すると

```
[18] pry(#<TopController>)> session.keys
=> ["session_id", "flash", "warden.user.user.key", "warden.user.user.session"]
```

と返ってくるが、 `session["warden.user.user.session"]`としても同様に同じセッションが帰ってくる。

```
[19] pry(#<TopController>)> session["warden.user.user.session"]
=> {"last_request_at"=>1553329704}
```


てなると気になるのは、

# このsessionのHashはどこで設定されているのか？


という点。


まずは `warden`に `session`というメソッドらしきものがあるかを確認する。

<b>warden/lib/warden/proxy.rb</b>
https://github.com/wardencommunity/warden/blob/b7ff0f4ffacd7ad5a9b5a0191f1da0c7a64b2c2c/lib/warden/proxy.rb

```:l.244
  def session(scope = @config.default_scope)
    raise NotAuthenticated, "#{scope.inspect} user is not logged in" unless authenticated?(scope)
    raw_session["warden.user.#{scope}.session"] ||= {}
  end
```

`warden/proxy.rb`の244行目にsessionメソッドがあった。
ここには先ほど3番目に確認した `"warden.user.user.session"という名前の命名についてのルールが書かれてある。`
sessionのHashのルールについては書かれていないが、これもこれで勉強になる。

<br>
では肝心のHashについてはというと、
<br>


<b>devise/lib/devise/hooks/timeoutable.rb</b>
https://github.com/plataformatec/devise/blob/master/lib/devise/hooks/timeoutable.rb

```:l.31
  unless env['devise.skip_trackable']
    warden.session(scope)['last_request_at'] = Time.now.utc.to_i
  end
```

`timeoutable.rb`の31行目に答えが書いてあった。


Hashのkeyである `last_request_at`は、手入力で決められたもので、
valueは `UTCでの現在時刻`という変数だった。

<br>

お勉強になりました