OmniAICreator/Qiita-1.07M huggingface dataset:
[BUKURO.swift]WWDC2017

<p>MOSA BUKURO.swift #10 の発表資料。WWDC2017からきになる項目をリストアップした。</p>

<ul>
<li>WWDC.family</li>
	<ul>
	<li>https://wwdc.family/</li>
	<li>参加者同士で位置情報を共有。</li>
	</ul>
<li>Apple File System (APFS) </li>
	<ul>
	<li>macOSでもAPFSが標準に。</li>
	</ul>
<li>What's New in Audio</li>
	<ul>
	<li>AVAudioEngine</li>
		<ul>
		<li>OS8から存在していたが気づいていませんでした。</li>
		<li>AudioUnitのCocoa版？</li>
		</ul>
	<li>AudioUnit Ver.3</li>
		<ul>
		<li>AudioUnit がバージョンアップ。</li></li>
		<li>そもそも、バージョン番号があることを知らなかった。
		</ul>
	</ul>
<li>Metal 2</li>
	<ul>
	<li>virtual reality (VR) 対応</li>
	<li>Debug</li>
	<li>最適化</li>
	</ul>
<li>MusicKit</li>
	<ul>
	<li>API for the Apple Music subscription service</li>
	<li>簡単に分かりやすく説明すると、アプリからiPodが利用できるということ？</li>
	</ul>
<li>Core ML</li>
	<ul>
	<li>Machine learning</li>
	</ul>
<li>High Efficiency Image File Format (HEIF) and High Efficiency Video Coding (HEVC)</li>
	<ul>
	<li>画像ファイルの書式</li>
	<li>H.265</li>
	</ul>
<li>ARKit</li>
	<ul>
	<li>カメラとモーション機能の統合</li>
	<li>https://developer.apple.com/documentation/arkit/understanding_augmented_reality</li>
	</ul>
<li>natural language processing (NLP) API</li>
	<ul>
	<li>自然言語処理のフレームワーク</li>
	</ul>
<li>new Drag and Drop APIs</li>
	<ul>
	<li>iOSでドラッグ＆ドロップ実装をサポートするAPIが追加？</li>
	</ul>
<li>Vision
	<ul>
	<li>特徴の検出など</li>
	<li>Core MLが利用されている。</li>
	</ul>
<li>Depth API</li>
	<ul>
	<li>iPhone 7 Plus のカメラで測定されたデータを利用するフレームワーク。</li>
	</ul>
<li>Filesアプリ</li>
	<ul>
	<li>各機器のストレージの内容をクラウド経由で同期させる。</li>
	<li>これを想定したファイル管理APIが？</li>
	</ul>
<li>ColorSync</li>
	<ul>
	<li>APIがCocoaフレームワークされた？</li>
	</ul>
<li>PDFKit</li>
	<ul>
	<li>ついに、iOSでも。</li>
	</ul>
<li>Identity Lookup</li>
	<ul>
	<li>メッセージのフィルタ</li>
	</ul>
<li>DeviceCheck</li>
	<ul>
	<li>サーバでの利用も想定</li>
	<li>初回起動判定などで利用できる</li>
	</ul>
<li>FileProvider</li>
	<ul>
	<li>Filesアプリ関連で、異なるアプリ間でファイルを共有する口？</li>
	</ul>
<li>Core NFC</li>
	<ul>
	<li>iOSをメンバー管理や、鉄道の利用状況アクセスが期待できる？</li>
	<li>Suicaの乗車履歴が読み取れる？</li>
	</ul>
<li>StoreKit</li>
	<ul>
	<li>変更があった？</li>
	</ul>
<li>Xcode</li>
	<ul>
	<li>GitHub</li>
	<li>Debugging and Analysis</li>
	<li>Runtime Sanitizers</li>
	<li>Testing and Continuous Integration</li>
	<li>Wireless Development</li>
	</ul>
<li>App Store</li>
	<ul>
	<li>段階的アップデート</li>
	<li>使用していないアプリの削除機能</li>
	</ul>
</ul>

関連情報
<a href="https://mosa.connpass.com/event/56250/">MOSA BUKURO.swift #10 【WWDC2017特集！】</a><br />
<a href="https://cocoa-study.connpass.com">Cocoa勉強会 BUKURO.swift (connpass)</a><br />
<a href="https://connpass.com/series/499/">Swift勉強会 関東 (connpass)</a><br />
<a href="https://atnd.org/groups/cocoa-study">Cocoa勉強会 BUKURO.swift (ATND)</a><br />
<a href="https://mosa.connpass.com">MOSA BUKURO.swift (connpass)</a><br />

【Cocoa練習帳】
<a href="http://www.bitz.co.jp/weblog/">http://www.bitz.co.jp/weblog/</a><br />
<a href="http://ameblo.jp/bitz/">http://ameblo.jp/bitz/</a>（ミラー・サイト）<br />
<a href="https://t.co/6P3h2jtbRk</a>note<br />
障害解析初動用問いかけテンプレート

これはシステムやプログラムの障害（と思われる現象）に遭遇したとき、あるいは障害解析を依頼された特にはじめに確認することリストです。これ全てが必要だとは限らないし、これで十分だとも限りません。テンプレート代わりにして適宜カスタマイズして利用してもらえればと。

* いつ？
* どこで？
* だれが？
* 何をしようとした？
* なぜ？
* 具体的にどんな操作をした？
* 本来どうなるはず？
* 実際どうなった？
* 再現する？
* 何か思い当たることはある？

質問形式にしてみました。問いかける相手はお客さんかもしれないし、運用チームかもしれないし、後輩かもしれないし、あるいは自分にかも知れない。

テスターの立場の場合この問いかけを参考に報告すれば喜ばれるかもしれない。

## いつ
障害に遭遇した時間。大抵は年月日時分がだいたいわかれば良い（秒まであっても時計がずれてたりするし）。

### 回答例
2017年6月15日8:35頃

### 質問の狙い
* どのバージョンでの障害かを特定する際のキーとなる
* 膨大なログ解析する時に該当箇所を特定するキーとなる
* 遭遇時期だけで原因が推測できることもある
    *  その時間はメンテナンス中です とか
    *  あ、リリース直後だ とか


## どこで
障害に遭遇した場所。開発環境なのか、テスト環境なのか、はたまた実働環境か。複数サーバーが立ってたら、何号機でおきたのまでわかると嬉しい

### 回答例
連結環境B号機

### 質問の狙い
* ログなどを引っこ抜く場所を特定する
* 再現できる環境を得る
* 改修後にどこでテストしなければいけないか把握する
    * 開発環境でのバグなら開発環境で修正が確認できればいいし、実環境なら受け入れテストの環境でテストしないと


## だれが
障害に遭遇した人。お客様かテスターか自分かになると思う。可能なら氏名で書くこと。

### 回答例
山田太郎

### 質問の狙い
* ヒアリングできるように

## 何をしようとした？
大きなくくりで何をしようとしたのか。ざっくりでいい。

### 回答例
商品データゼロ件にして商品検索をしようとした

### 質問の狙い
* 障害のイメージを把握するため


## なぜ？
なぜそれをしようとしたのか。ここは「連結テスト項目表のNo3を実施するため」とかでよい。ここに関してはお客様にはきけないかな（業務のためだろうし）。

### 回答例 
連結テスト項目表のNo3を実施するため

### 質問の狙い
* 手っ取り早く話をすすめるため(「どうなった？」以外の殆どがここに書いてある)
* すぐ対応する必要があるのかの切り分け
    * この障害のせいで他のテストが止まらないか


## 具体的に何をした？
やったことをはっきりさせる。
場合によるが、概ね下のような情報があればベスト

* どのモジュールを使って
* どんな設定をして
* どんなデータを入れて
* どんな画面操作を行った？

可能ならこの時点で集められるものは集めておいたほうが良い。使ったモジュールのバージョン、設定ファイル、あるならオペレーション時の画面キャプチャ（エクセルに貼りける必要はない）。

### 回答例
* 使用モジュール：ver1.3
* 設定：application.propertiesの標準データ
* 投入データ： 連結テスト用標準データを投入した後、商品テーブルを全て削除
* オペレーション
    * ログイン画面を表示
    * TESTUSER, passwordでログイン
    * メニューから商品検索画面をクリック
    * 「歯磨き粉」で検索実行 

### 質問の狙い
* 再現方法をはっきりさせる
* 操作方法に間違いはないか判断する

## 本来どうなるはず？
本来期待される挙動。

### 回答例
画面に「該当する商品がありません」と表示される。

### 質問の狙い
* オペレータとの認識合わせ
 

## 実際どうなった？
実際になにがおきたのか。

* 画面はどうなった？
    * システムエラー画面に飛んだ
        * 画面にメッセージは表示されていないか
* コンソールには何か出てる？
    * とくに何も出ていない
* ログは？
    * スタックトレースは出てる？
   
ログに関しても、残しておくのが良い。どのログかははっきりさせること。「ログって、具体的になにがあります？」とか認識合わせしておいたほうがいい。「（サーバ）ログ見ました？」「（アプリログは）見ました。」というすれ違いは避けたい。

### 回答例
システム画面に遷移した。エラーメッセージは
「システムでエラーが発生しました。管理者にお問い合わせください。（エラーコード：8080）」

コンソールにはなにも出力されていない。

syse.logに以下のエラーが出力されている
(スタックトレースを貼り付けるが)

### 質問の狙い
* これがないと始まらない
* 再現させる手間を省ける

## 再現する？
同じ方法でやってみて、再現するか。

### 回答例
必ず発生する。

### 質問の狙い
* もう一度やってみてもらうことで手間を省ける
* オペレータの勘違いをフィルタする
    * もう一回やってみたらボタンまちがえてました
* 初期切り分けの判断材料になる
    * この内容で常に再現するなら単純なコーディングミスだろう
    * たまに発生するとなると厄介な問題かもしれない
    * 絶対に発生するならすぐ直さなければならない
    * 頻度が少ないなら優先度を下げて一旦再現待ちとするか（見なかったことにはしないこと）


## 何か思い当たることはある？
ここまでで原因に心当たりがない場合、とにかく何か情報をもらう。

### 回答例
* リリース直後に発生した
* 設定を変えた直後に発生した
* そういえば午前中には起きなかった気がする
* 実はサーバー起動方法に自信がない
* 2つ前のバージョンではよく発生してました

### 質問の狙い
* 原因の切り分け
    * ああ、新モジュールが原因か
    * それは設定不正だな
    * 時間が絡んだ処理？もしかいて日付計算間違えてる？
    * 起動するときにデバッグオプション渡してる？
    * え？デグレ？

----

ざっとこれくらい情報が集まればスムーズに障害解析にうつれて8割型解決するんじゃなかろうか？
WebpackでAWS SDKをバンドルするとサイズが大きいのでダイエットする

## 経緯

サーバレス、流行ってますね。
ウェブホスティングしたS3上にReactやRiot.jsなどでSPAを作って、認証はCognito UserPoolというのがテッパン構成でしょう。

* http://qiita.com/jobbin/items/d2fc0f714eb1f1cfc965
* http://dev.classmethod.jp/cloud/aws/login-form-by-using-aws-sdk-for-javascript/

そして、SPAを作るならWebpackでES6で書いたソースをトランスパイルして、バンドル（ひとつの*.jsファイルにまとめること）して…というのが通例ですね。（サーバーサイドの人にはこの辺がツラい）

* http://qiita.com/clown0082/items/ba9177eb26b09baa668b

しかしながら、いざやってみると...でかいよバンドルされたJSファイル。minifyして2MB近くとか…。

何が大きいのか[webpack-bundle-size-analyzerを使って](http://qiita.com/wadahiro/items/c633e4c7c44154238397)見てみましょう。

```shell-session
$ $(npm bin)/webpack --json | webpack-bundle-size-analyzer 
aws-sdk: 2.2 MB (79.8%)
lodash: 100.65 KB (3.56%)
amazon-cognito-identity-js: 94.85 KB (3.36%)
node-libs-browser: 84.87 KB (3.00%)
  buffer: 47.47 KB (55.9%)
  url: 23.08 KB (27.2%)
  punycode: 14.33 KB (16.9%)
  <self>: 0 B (0.00%)
riot: 80.64 KB (2.85%)
jmespath: 56.94 KB (2.02%)
xmlbuilder: 47.82 KB (1.69%)
util: 16.05 KB (0.568%)
  inherits: 672 B (4.09%)
  <self>: 15.4 KB (95.9%)
crypto-browserify: 14.8 KB (0.524%)
riot-route: 8.92 KB (0.316%)
debug: 8.91 KB (0.316%)
events: 8.13 KB (0.288%)
uuid: 5.54 KB (0.196%)
process: 5.29 KB (0.187%)
querystring-es3: 5.06 KB (0.179%)
obseriot: 4.43 KB (0.157%)
<self>: 27.78 KB (0.983%)
```

なるほど、AWS SDKですね、やっぱり。

## なぜ大きくなっちゃうのか

Webpackによるバンドルでは`npm install`したモジュールが全て闇雲にバンドルされるわけではありません。
結構賢くて実際に使われているものだけがバンドルされるように考えられています。具体的にはimport(require)されているモジュールだけを再帰的にたどって１つのJSファイルにまとめていきます。
つまり、importしているファイル数が多ければ多いほどバンドルされたファイルは大きくなります。

```
import AWS from "aws-sdk"
```

普通のサンプルだとAWS SDKを使うときはこのようにimportすると思います。これが大きな罠なのです。
AWS SDKのソースを見てみましょう。

* https://github.com/aws/aws-sdk-js/blob/master/index.js
* https://github.com/aws/aws-sdk-js/blob/master/lib/aws.js#L6

```js:lib/aws.js
// Load all service classes
require('../clients/all');
```

ここがサイズを肥大化させる要因となっています。全てのモジュールを読み込んでいるので使いもしないAWSの機能も含めて全て読み込んでしまっているのです。

## どうしたらダイエットできるのか

http://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v2/developer-guide/webpack.html#webpack-importing-services

を見てみると書いてあります。

> The require() function specifies the entire SDK. A webpack bundle generated with this code would include the full SDK but the full SDK is not required when only the Amazon S3 client class is used.

`require("aws-sdk")`と書いてしまうと、たとえS3しか使わなくても全部の機能を読み込んでしまいます。
注） `import from "aws-sdk"`と書いても同じ意味になります。

その下の方に、

> Here is what the same code looks like when it includes only the Amazon S3 portion of the SDK.

```js
// Import the Amazon S3 service client
var S3 = require('aws-sdk/clients/s3');
 
// Set credentials and region
var s3 = new S3({
    apiVersion: '2006-03-01',
    region: 'us-west-1', 
    credentials: {YOUR_CREDENTIALS}
  });
```

と答えが載っています。

[clientsディレクトリ](https://github.com/aws/aws-sdk-js/tree/master/clients)以下のファイルを個別にimportすることができるようになっているということです。

## なるほど、試してみた

https://github.com/NewGyu/riot-sample/compare/cognito-login...fat-cognito-login

```shell-session
$ $(npm bin)/webpack --json | webpack-bundle-size-analyzer 
aws-sdk: 325.01 KB (36.3%)
lodash: 100.65 KB (11.2%)
amazon-cognito-identity-js: 94.85 KB (10.6%)
 :
```

2.2MB -> 325KB と激ヤセです！
MFCの CArray や CStringArray を拡張 for 文で回す

## 概要

CArray, CStringArray といったMFCコンテナは過去との互換性のために残されているものの、今後 begin, end といったメンバ関数が追加される見込みは限りなく低い。

だが自前で std::begin, std::end グローバル関数を適切に定義すると拡張 for 文を使うことができる。

## 方法

どっか見えるところに以下のように std::begin, std::end 関数を定義しておきます（begin と end の帳尻が合っていれば関数の中身は何でもいいです）。

```cpp
namespace std
{
	template<class T>
	T* begin(CArray<T>& _Cont)
	{
		return (&_Cont.GetAt(0));
	}

	template<class T>
	T* end(CArray<T>& _Cont)
	{
		T* last = &_Cont.GetAt(_Cont.GetSize() - 1);
		return (last + 1);
	}

	CString* begin(CStringArray& _Cont)
	{
		return (&_Cont[0]);
	}

	CString* end(CStringArray& _Cont)
	{
		CString* last = &_Cont[_Cont.GetSize() - 1];
		return (last + 1);
	}
}
```

そうすると以下のように拡張 for 文が使えます。

```cpp
cout << "=== Loop CArray ===" << endl;

CArray<int> arr;
arr.Add(1);
arr.Add(2);
arr.Add(3);
arr.Add(4);

// CArray を拡張 for で回す
for (int& v : arr) { cout << v << endl; }


cout << "\n=== Loop CStringArray ===" << endl;
wcout.imbue(std::locale(""));

CStringArray sarr;
sarr.Add(_T("hello, "));
sarr.Add(_T("world"));

// CStringArray を拡張 for で回す
for (CString& s : sarr) { wcout << (LPCTSTR)s << endl; }
```

```:Console出力
=== Loop CArray ===
1
2
3
4

=== Loop CStringArray ===
hello,
world
```

以上。
ZSHでタ-ミナルをカスタマイズしましょう^^

![ZSH](https://gist.githubusercontent.com/kevin-smets/9722391f8b3e4fa436b1c1dcf05ecd88/raw/14012c157e280684ae5c75686eef2e302123e51b/agnoster.png "ZSH")

こんにちは！ギと申します。

僕は仕事で主にウェブの開発・運用をしており、ターミナルをよく使っています。Macには標準でターミナルアプリがインストールされていますが、使い勝手があまりよくありません。ということで、最も使い勝手が良いと言われているiTerm2を入れてみました。今回はiTerm2のインストール・カスタマイズ方法を紹介いたします！

## Itermをインストール・カスタマイズしましょう

### [Iterm2](https://www.iterm2.com/index.html)をインストールするMacのbrewでインストールする方法

```
brew cask install iterm2
```

brewでインストールできない場合、[ここから](https://www.iterm2.com/downloads.html)ダウンロードして、インストールしてください！ 


Iterm2のデフォルトをSolarized Dark themeに差し替えましょう


![Solarized-Dark](http://tech.aainc.co.jp/wordpress/wp-content/uploads/2017/05/Solarized-Dark-1-1024x541.png "Solarized-Dark")

### zshをインストールする

```
brew install zsh zsh-completions
```

Zshのより詳細な情報は[ここに](http://technique.sonots.com/?UNIX%2F%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%2F%E3%82%B7%E3%82%A7%E3%83%AB%E3%83%BB%E3%82%B7%E3%82%A7%E3%83%AB%E7%B5%84%E3%81%BF%E8%BE%BC%E3%81%BF%2Fzsh#abf8c6b1)書いてあります


### Oh-My-Zshをインストールする

[Oh-My-Zsh](https://github.com/robbyrussell/oh-my-zsh)はZSHの設定を管理するフレームワークです

Macのbrewでインストールする方法:

```
sh -c "$(curl -fsSL https://raw.githubusercontent.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"
```

### テーマを差し替える

zshの設定ファイルを開いて、ZSH_THEMEの行のデフォルト値を｀agnoster｀に差し替えましょう。agnosterのテーマはかっこいいし、gitもサポートしているのでオススメです！


### SourceCodeProフォントをインストールする

[SourceCodePro](https://github.com/powerline/fonts/tree/master/SourceCodePro)をダウンロードして、インストールしてください

![SourceCodePro](http://tech.aainc.co.jp/wordpress/wp-content/uploads/2017/05/change_font-1-1024x575.png "SourceCodePro")


### 他にも、タ-ミナルを使いやすくする方法はたくさんあります

Auto suggestionsを設定する方法

[ここを](https://github.com/tarruda/zsh-autosuggestions#oh-my-zsh)参考にして、ダウンロ-ドと設定ができます

Macのデフォルトのキ-ボ-ドのリピ-ト速度を差し替える方法

```
defaults write -g InitialKeyRepeat -int 10 # normal minimum is 15 (225 ms)

defaults write -g KeyRepeat -int 1 # normal minimum is 2 (30 ms)
```

[参考](https://gist.github.com/kevin-smets/8568070)
RSpecをRailsプロジェクトに導入する

# はじめに:writing_hand:
弊社プロジェクトでRSpecを導入することになったので、
そのノウハウをとりあえず共有。
百番煎じだろうと役に立つ可能性は...あります:point_up:

# 必須設定:gear:
基本的にGemを追加するだけで使用可能
## Gemの追加

```rb:Gemfile
group :development, :test do
  gem "rspec-rails"
  gem "factory_girl_rails"
  gem "guard-rspec"
  gem "spring-commands-rspec"
end

group :test do
  gem "faker"
  gem "database_cleaner"
  gem "launchy"
  gem "selenium-webdriver"
  gem "shoulda-matchers"
end
```
## インストール
```sh
$bundle exec rails generate rspec:install
以下が追加される
create  .rspec
create  spec
create  spec/spec_helper.rb
```

これだけで使える状態まで持っていける。

# 便利な設定:robot:
## テスト結果をドキュメントっぽくする
デフォルトのテスト結果はこんな感じ
[f:id:oredeki:20170614233231p:plain]

.rspecに以下を追記するとドキュメントっぽくなる

```rb:.rspec
--format documentation
```
[f:id:oredeki:20170614233255p:plain]

## 不要なファイルを生成しないための設定

```rb:/config/application.rb
config.generators do |g|
  g.test_framework :rspec,
    fixtures: true,
    view_specs: false,
    helper_specs: false,
    routing_specs: false,
    controller_specs: true,
    request_specs: false
  g.fixture_replacement :factory_girl, dir: "spec/factories"
end
```
# 各ジェネレート:pick:
RSpecをインストールしている場合、railsのジェネレートコマンドを使うとそれに準じたテストファイルも作成される。
## Model
```sh
$rails g model User name:string
以下が追加される
Running via Spring preloader in process 34465
      invoke  active_record
      create    db/migrate/20170612075328_create_users.rb
      create    app/models/user.rb
      invoke    rspec
      create      spec/models/user_spec.rb
      invoke      factory_girl
      create        spec/factories/users.rb
```

## Contloller
```sh
$rails g controller UserList index
以下が追加される
Running via Spring preloader in process 61960
      create  app/controllers/user_list_controller.rb
       route  get 'user_list/index'
      invoke  erb
      create    app/views/user_list
      create    app/views/user_list/index.html.erb
      invoke  rspec
      create    spec/controllers/user_list_controller_spec.rb
      invoke  helper
      create    app/helpers/user_list_helper.rb
      invoke    rspec
      invoke  assets
      invoke    coffee
      create      app/assets/javascripts/user_list.coffee
      invoke    scss
      create      app/assets/stylesheets/user_list.scss
```
夜にネットが遅くなっていたのがパブリックDNSに変更して改善

# きっかけ
夜になると自宅のインターネット速度が異常に遅くなるという症状が続いていました。
遅くなるどころかWebサイトへのアクセスがタイムアウトしてしまうこともしばしば。

ChromeでWebサイトにアクセスすると左下に「ホストを解決しています」というメッセージが出続けるのが気になり、
nslookupで適当なドメインを検索してみるとタイムアウトが発生
どうやらプロバイダのDNSサーバが重たいようです

プロバイダが提供するDNS以外にも、googleなどがパブリックDNSを公開しているので、
そちらを使えばこの問題は解決するのではないかと思いました。

# Google Public DNSの情報
[Google Public DNSの公式ページ](https://developers.google.com/speed/public-dns/docs/using "Get Started  |  Public DNS  |  Google Developers")に記載されていますが、
IPv4とIPv6両方のDNSサーバを提供しています。

### IPv4
* 8.8.8.8
* 8.8.4.4

### IPv6
* 2001:4860:4860::8888
* 2001:4860:4860::8844

# 設定を変える前にベンチマークしてみた
ネットを調べてみると、Google以外にもパブリックDNSを公開しているところがあるようで、
どのDNSが速いかベンチマークするソフトがあったので試してみました。

[Domain Name Speed Benchmark](https://www.grc.com/dns/benchmark.htm "GRC's | DNS Nameserver Performance Benchmark")

ダウンロードしたexeファイルを起動すると、DNSサーバのリストを取得するまで少し待ちます。
取得し終わると「Nameservers」タブの「Run Benchmark」ボタンが押せるようになるので、クリック。
「Run Benchmark」ボタン左のゲージがMAXになれば終了です。

自宅で試した結果がこちら。
![2017-06-08_23h10_21.png](https://qiita-image-store.s3.amazonaws.com/0/181737/810e80f9-80c0-8e1f-9f7a-7d3c0581b69d.png)
googleが最速ではありませんでしたが、十分速そうなのでこちらに切り替えてみることにしました。

# 複数のPC/スマホがあってもルータの設定でOK
自宅にはWinが2台、スマホが2台あり、それぞれのDNS設定を変えるのは面倒ですが、
ルータがDNSフォワーダーになっていますので、
ルータの設定を変えるだけで済みました。

機種はRT-S300SEです。

基本設定 ＞ 接続先設定(IPv4 PPPoE)　＞　[ 接続先の選択設定 ]で接続中のセッションをクリック
![image.png](https://qiita-image-store.s3.amazonaws.com/0/181737/9c108e51-6d36-e3ca-edb6-e7f86370244f.png)

接続先設定(IPv6 PPPoE)　も同じように設定
![image.png](https://qiita-image-store.s3.amazonaws.com/0/181737/192fc94b-4094-797a-bf09-82b646ae9652.png)

# 効果
早朝に比べるとまだ遅い気はしますが、タイムアウトが発生することはなくなりました。

そもそも夜遅くなるプロバイダのDNSサーバっていかがなものでしょう。
大手プロバイダなのに・・・
paizaの問題を解くときに使えるテクニック2(Ruby編)

#Paizaの問題を解いていて、使えそうなテクニック(出力編)
自分用アウトプットメモです。
覚えておくと便利なものであり、解法ではありません。
ちなみに趣味でしかRubyを使ったことがありません。

前回
[paizaの問題を解くときに使えるテクニック1(Ruby編)
](http://qiita.com/yamakawa00/items/9da4f8b62d6af3f29b4a)

#レシーバのクラスを表示する
型が不一致になることが原因で、エラーになることがあります。

```hoge.rb
a = 1
b = "1"

p a + b
```

```bash
$ ruby hoge.rb 
hoge.rb:4:in `+': String can't be coerced into Fixnum (TypeError)
        from hoge.rb:4:in `<main>'
```

上記の様な単純な例だったら、すぐに解決できますが、
デバッグしてると、クラスがわからないことがあります。
そこで、`.class`メソッドを使用します。
`.class`メソッドは、レシーバのクラスを返します。

```hoge.rb
hoge = "ruby"
p hoge.class #=> String

p 999999999999999.class #=> Bignum
p ARGV.class #=> Array
p self.class #=> Object
p Class.class #=> Class
p Kernel.class #=> Module
```

#2次元配列を要素ごとに連結しつつ出力
たまに2次元配列の各要素を一行づつ連結して出力しなくてはならない場面があります。
その場合は下記のように記述すれば良いでしょう。

```hoge.rb
field = [[1,2],[3,4]]
# 連結
field.each { |f| puts f.join("")}
```

```bash
$ ruby hoge.rb 
12
34
```

#配列のnilを削除して計算を行う
問題を解いていると配列にnilが混ざることも多いと思います。
nilがあって一番困るのは`inject`を使う時です。
そのような場合は、`compact`を使ってnilを削除しましょう。

```hoge.rb
array = [nil, 1, 2, 3, nil]
# nilを削除して計算
p array.compact.inject(&:+)
```

```bash
$ ruby hoge.rb 
6
```

#最後に
適当でごめんなさい
出力編は、あんまりネタがなかったです。
適度なタイミングで、入力+出力+αでリライトしたい。
ES2015 Classでprivateメソッドであることを表明する

ES2015 Classでprivateメソッドについて考えた結果、[private-assertion](https://github.com/KeitaMoromizato/private-assertion)というモジュールを作ってみたのでまとめ。

## privateメソッド実現方法いろいろ

ES2015 Classでprivateメソッドってどうやって表現するの？と調べてみた。

### Underscore

古き良きJavaScriptのようにメソッド名の先頭をアンダースコアにする。

```js
class Hoge {
  _inner() {
  }
}
```

確かにわかりやすいっちゃわかりやすいんだけど、人間の手で守っていくしかない手法。というかクラスベースになったのにこんな書き方嫌だ！他にもクロージャー使う方法もあるけどそれも嫌だ！

### Symbol/WeekMap

どうやら調べてみるとSymbolやWeekMapを使った実装が一般的？らしい。

[JavaScriptのクラスでprivateを実現してみたかった人生だった](http://syossan.hateblo.jp/entry/2016/08/09/225016)

フィールドは簡単に定義できそうだけど、private methodの実装にはひと手間かかりそうだなという印象。

この記事にあるprivateメソッドの書き方ならそれほど手間なく書けそう。

[Private Methods In JavaScript](http://www.tysoncadenhead.com/blog/private-methods-in-javascript#.WUKM-CGLSis)

### TypeScriptを使う

いや本当にTypeScripts好きだし使えばいいと思うんだけど、プロジェクトによってはflowtypeだったりするよね。

### Decoratorを使う

こう色々と調べてみると、classの書き方を損なうことなくprivateメソッドを書くのは難しい感じがする。それをどうにかできないかと考えて作ったのが[private-assertion](https://github.com/KeitaMoromizato/private-assertion)。decoratorを使っている。

privateメソッドにどうアクセスさせないか、ではなく**privateメソッドであることを表明して、外からアクセスされたら落とせばいいじゃん**という発想。引数のチェックではないのでいわゆる表明プログラミングとはちょっと違うかもしれないけど、それに近い発想。

```js
import privateAssertion from 'private-assertion';

class Hoge {
  publicMethod() {
    return this.privateMethod();
  }

  @privateAssertion
  privateMethod() {
    return 'call from private only';
  }
}

const hoge = new Hoge();

hoge.privateMethod();
// => Error('Hoge#privateMethod is private method.')
```

privateMethodであることが明確であり、ES2015 classの構文を壊すことなく実装できるこういう書き方のほうが好み。ただ「stacktraceたどればprivate callか判定できるんじゃね？」という雑な考えで書いたので、うまく動かないパターンは普通にありそう...（書きながら、たぶん継承したら呼べてしまうことがわかったので直したい）。




## 標準化を待つ

private methodのproposalは出てるので早く標準化されるといいですね。

https://github.com/tc39/proposal-private-fields/blob/master/METHODS.md
Xcode9-beta起動後、Xcode8のシミュレーターが消えた場合の対処法

Xcode9-betaをインストールして起動後、共存させていたXcode8のシミュレーターが消え、デバッグできずハマったのでメモします。

# 事象

Xcode9-betaを起動後、Xcode8を起動すると、シミュレーターが全て表示されくなり、シミュレーターのでのデバッグができない状態となる。

<img width="302" alt="スクリーンショット 2017-06-15 23.18.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/113553/5a9eda29-4183-e224-6d15-e3b8a6c3a197.png">

<img width="279" alt="スクリーンショット 2017-06-15 23.18.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/113553/a59bcc0b-e040-7056-66cc-435ee07325a6.png">

# 対処方法

(1) Xcode、シミュレーターアプリをすべて終了する。
(2) 手順(1)をやっても直らない場合は、ターミナルアプリを起動し、以下のコマンドを入力する。

```bash
# Xcodeのビルド中間生成ファイルを全て削除する
$ rm -rf ~/Library/Developer/Xcode/DerivedData/*

# Xcode8のDeveloperディレクトリを再指定する。パスは適宜変更してください。
# （自分の場合はXcode8をXcode8.appに名称変更していたため、以下のパスでした）
$ sudo xcode-select --switch /Applications/Xcode8.app/Contents/Developer
```

(3) Xcode8を起動

シミュレーターが正常に表示され、選択できるようになります。
<img width="269" alt="スクリーンショット 2017-06-15 23.35.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/113553/2918a718-013a-6dfd-c2b5-bfd7a32f26fa.png">
VisualStudio for MacのSegueサンプル２(Mac Cocoa)

GitHubに置いてあります [TestSegueReplace](https://github.com/syumipg/selfnote/tree/Segue_Class)

[前回](http://qiita.com/grayhead0603/items/b21901bf0e86b5966385)に続いて、クラスによるカスタムSegueの例を書いておきます。
XamarinのWorking with Storyboards - [Creating Custom Segues](https://developer.xamarin.com/guides/mac/platform-features/storyboards/indepth/#Creating-Custom-Segues)に公開されているReplaceViewSeque.csを利用してMainViewの切り替えアプリを作成しました。

## アプリの概要
1. デバッグすると、MainViewが開きます。
2. ２つのボタンのいずれかをクリックするたびにViewが切り替わります。
3. ボタンからViewへ直接セグエを作成しています。

## 注意事項
このプロジェクトは、XamarinのGuidesページ[Creating Custom Segues](https://developer.xamarin.com/guides/mac/platform-features/storyboards/indepth/#Creating-Custom-Segues)で公開されているクラスを利用します。
XmarinのウェブはMITライセンスのようですが、このプロジェクトはUnlicenseにしていますのでクラスのソースコード自体は追加していません。
利用する場合には、Xamarinのページから「ReplaceViewSegue.cs」にコピペしてください。
なお、「ReplaceViewSeque」とsegueでなくsequeになっているのでそのまま利用します。

## 手順
[TestSegueReplace](https://github.com/syumipg/selfnote/tree/Segue_Class)参照

## 実行画面
![02TestSegueReplace03_run.gif](https://github.com/syumipg/selfnote/wiki/images/02TestSegueReplace03_run.gif)

## 開発環境
* Visual Studio Community for Mac 2017 Ver.7.0.1
* OSX ElCapitan
* MacBook Pro Retina model

## Reference:
1. Xamarin Guides  Mac - Working with Storyboards - [Segue](https://developer.xamarin.com/guides/mac/platform-features/storyboards/indepth/#Segues)
PHPで一次配列であればimplobe関数を使う

普通にformを使って作ると、Arrayに格納されます。

そして、＄_POSTにすべて格納されますが、
他のページ渡す場合は$_SESSIONが必要です。

この時、$_SESSIONに引き渡した時に
implobe関数を使って定義してArrayを取りだしても
次のページに行けば、結局またArrayに格納されたままなので
もう一度、使う場合はimplobe関数で取り出す必要があります。

例

```php
<?php

$example = implobe(',', $_SESSION(test));

?>
```
こうやって代入してあげないと、この後に使えません。
Google ChromeがHeadlessで使える様なのでnode.jsから動かしてみる

# Google ChromeがHeadlessで使える様なのでnode.jsから動かしてみる

Google Chrome 59からHeadlessモードで起動することができる様になりました。
そこで、node.jsからHeadlessモードのChromeを立ち上げ、ページにアクセスして見たいとおもいます。

# 注意事項
+ Google ChromeのVersion 59以降であること
+ MacとLinuxで提供されており、Windowsは未対応

# 使用モジュールのインストール

npmで以下をインストールしてください。

+ [chrome-launcher v0.1.1](https://github.com/GoogleChrome/lighthouse/tree/master/chrome-launcher)
+ [chrome-remote-interface v0.23.2](https://github.com/cyrus-and/chrome-remote-interface)

```
npm install chrome-launcher
npm install chrome-remote-interface
```

# 実行コード

javascriptの実行を待ってやる必要がありそうですが、今回はアクセスできたことが確認できるところまで。
どうやって待ってやれば良いのかな。。。

```
'use strict';

const chromeLauncher = require('chrome-launcher');
const CDP = require('chrome-remote-interface');

const targetUrl = 'https://www.google.co.jp';

async function startHeadlessChrome() {
  try {
    return await chromeLauncher.launch({
      startingUrl: 'target:brank',
      chromeFlags: ['--headless', '--disable-gpu']
    });
  } catch (error) {
    console.log(error);
  }
}

async function main() {
  const chrome = await startHeadlessChrome(targetUrl);
  const options = {
    port: chrome.port
  };

  CDP(options, async(client) => {
    try {
      // extract domains
      const {Network, Page} = client;
      // setup handlers
      Network.requestWillBeSent((params) => {
        console.log(params.request.url);
      });

      // enable events then start!
      await Promise.all([
        Network.enable(),
        Page.enable()
      ]);

      await Page.navigate({url: targetUrl});

      await Page.loadEventFired();
    } catch (error) {
      console.log(error);
    } finally {
        // close the connection to the remote instance.
        await client.close();
        // headless chrome close
        await chrome.kill();
    }
  }).on('error', (err) => {
    // cannot connect to the remote endpoint
    console.error(err);
  });
}

main();
```

# 参考

[ヘッドレス Chromeことはじめ](https://developers.google.com/web/updates/2017/04/headless-chrome?hl=ja)
一方向ハッシュ関数についてまとめてみた。

#前提
・一方向ハッシュ関数について調べていた時のものをまとめたものです。
・随時編集
・初投稿
・いいねしてくれると嬉しいです。（小並）

#まず一方向ハッシュ関数とは？
まずはじめに本題である、一方向ハッシュ関数について調べてみた。
[暗号学的ハッシュ関数(wikipedia)](https://ja.wikipedia.org/wiki/%E6%9A%97%E5%8F%B7%E5%AD%A6%E7%9A%84%E3%83%8F%E3%83%83%E3%82%B7%E3%83%A5%E9%96%A2%E6%95%B0)
[一方向性関数(wikipedia)](https://ja.wikipedia.org/wiki/%E4%B8%80%E6%96%B9%E5%90%91%E6%80%A7%E9%96%A2%E6%95%B0)
この二つによると、一方向ハッシュ関数は以上二つのキーワードの性質を併せ持つ関数であることがわかった。
注）ほんの少し使う言語はphp

#一方向ハッシュ関数の性質
**1.暗号など情報セキュリティの用途に適するような暗号数理的性質をもつハッシュ関数である。(暗号学的ハッシュ関数)**
○暗号数理的性質の条件
・同一のハッシュ値であるのに、そっくりだが実は異なるというようなメッセージの作成が不可能であること。
・ハッシュ値から、そのようなハッシュ値となるメッセージを得ることが事実上不可能であること。
（**原像計算困難性**、**弱衝突耐性**）
・同じハッシュ値となる、異なる2つのメッセージのペアを求めることが事実上不可能であること。
（**強衝突耐性**）
**2.簡単に計算できるが逆関数の計算は非常に困難である関数を指す。(一方向性関数)**

以上が揃って初めて一方向ハッシュ関数として成り立つと考えられる。

#一方向ハッシュ関数の種類
種類としてはあげられるものは以下のものがある。
・[md5](https://ja.wikipedia.org/wiki/MD5)
MessageDigestalgorythm5のことで、与えられた入力に対して128ビットのハッシュ値を出力するハッシュ関数である。出力128bitのハッシュアルゴリズムとなっている。 現在、安全でないため使用は推奨されていない。
```md5(hoge) => ea703e7aa1efda0064eaa507d9e8ab7e```

・[sha１](https://ja.wikipedia.org/wiki/SHA-1)
Secure Hash Algorithm-1からきている。[ソルト](https://ja.wikipedia.org/wiki/%E3%83%91%E3%82%B9%E3%83%AF%E3%83%BC%E3%83%89%E3%82%AF%E3%83%A9%E3%83%83%E3%82%AF#.E3.82.BD.E3.83.AB.E3.83.88)を使用し、160ビット（20バイト）のハッシュ値を生成する。
2005年、SHA-1に対する攻撃法が発見され、将来的な利用に十分な安全性を有していないことが示唆され、こちらも使用は推奨されていない。
```sha1(hoge) => 0b3b896804f7405b4452d49386912e1bf9e2dfac```
・[sha２](https://ja.wikipedia.org/wiki/SHA-2)
SHA-2にはSHA-224、SHA-256、SHA-384、SHA-512、SHA-512/224、SHA-512/256の6つのバリエーションがあり、それぞれハッシュのbit値が異なる([ソルト](https://ja.wikipedia.org/wiki/%E3%83%91%E3%82%B9%E3%83%AF%E3%83%BC%E3%83%89%E3%82%AF%E3%83%A9%E3%83%83%E3%82%AF#.E3.82.BD.E3.83.AB.E3.83.88)を使用)。SHA-2は、推奨暗号として採用されている。
```hash_hmac ('sha256' , "hoge" , False) =>  F9F2385A7D7CD1E6E9A801AB9BBBF7AE9998706AF0C2F8B608A39B42AB94D88F```


それぞれのハッシュ関数のbit数
<img width="315" alt="ハッシュ関数、MD5とSHAとは？_–_Cyber_Attack_dot_Net（サイバー攻撃_dot_Net）.png" src="https://qiita-image-store.s3.amazonaws.com/0/187338/3cfd1627-1708-3a1f-50c5-34aae1784034.png">


#実際の現場での使われ方
実際、それぞれがどのように使われているのかを調べてみた、
するとsha2以外はセキュリティ的に脆弱性が発見されたため全く使われなくなったのかという予想に反し、
セキュリティ的に、ユーザに直接入力を求めるところでは使えないが、処理がsha1やsha２よりも軽いこともあり
md5が攻撃等がされえない範囲での内部処理的にmatchをさせる際に、利用する例がある。
sha1はmd5ほど脆弱ではないが、処理が軽くもなく中途半端なため使いどころがない。
が、sha2に変更できていない会社が未だに使っているらしい、、、
もちろんsha2はバリバリ現役でパスワード認証などで使われている。
という感じで、現場は成り立っているそうだ。

#余談
最後まで読んでいただきありがとうございます。
なにせ初めての投稿で、右も左もわかっていない状況の中書いたものなので、拙い内容だったと思います。
今後さらに精進していこうと思います。宜しくお願いします。
Qiita「![Payload Too Large]()」エラー(1つでも記事を投稿すれば容量制限UPするらしい)

# あらすじ
「Qiitaデビューしちゃお:star::fire::star:」って
調子こいて必死に記事書き始めたけど、
画像が全然アップロードできなくなった・・:interrobang:

`![Payload Too Large]()`
`![Payload Too Large]()`
`![Payload Too Large]()`
`![Payload Too Large]()`
`![Payload Too Large]()`
`![Payload Too Large]()`

必死に画像小さくしても、
`![Payload Too Large]()`

はー！!??

# :sunny:記事を１つでも投稿すると画像容量UPするらしい:sunny:
初めてQiitaに投稿すると1ヶ月の画像アップロード制限が2MB→100MBにアップします
→http://blog.qiita.com/post/75674629515/image-capacity-expansion
> このたび、初めてQiitaに投稿するとアップロード可能な容量が月間2MBから100MBまでアップされるようになりました :)
> ※すでにQiitaに1件以上投稿したことがある方は、今日から無条件に100MBアップします。

ってことでこちらの記事を投稿してみました。

100MBゲット！！:100:
ES6でのクラスと継承…裏側を見てみる

なかなか書きづらいJavaScriptでのオブジェクト指向（特に、継承について）でしたが、ES6ではついに公式なクラス・継承機能が登場しています。

## ES6のクラスについて

とはいえ、プロトタイプベースという言語の本質はES6でも何ら変わらず、クラス構文と言っても中身はプロトタイプベースで動きます。

逆を返せば、「比較的容易に、従来のプロトタイプベースなコードに変換できる」「従来のコンストラクタ＆`prototype`で書いた『クラス』を、`class`構文で継承できる」などの融通無碍さはそのままです。

## Babelでの翻訳例

最近のブラウザでは直接`class`構文を投げても動くのですが、IE11を考えれば少なくともあと数年は、ブラウザ向けのJavaScriptに直接書けない状況が続きます。ということで、Babelなどのトランスパイラを使って、ES5に変換して使うこととなります（なお、同じように動けばいいので、変換後の関数名などは違うかもしれません）。


```js
// ES6でのclassを使ったコード
class Test{
  constructor(){
    this.foo();
  }

  foo(){
    alert('Test::foo()');
  }
}

class Child extends Test{
  foo() {
    alert('Child::foo()');
  }
}
```

```js
// ES5へのトランスパイル後

// ※この3関数は、読みやすさのため途中改行を入れています
function _possibleConstructorReturn(self, call) {
  if (!self) {
    throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  }
  return call && (typeof call === "object" || typeof call === "function") ? call : self;
}

function _inherits(subClass, superClass) {
  if (typeof superClass !== "function" && superClass !== null) {
    throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
  }
  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: { value: subClass, enumerable: false, writable: true, configurable: true }
  });
  if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}

function _classCallCheck(instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError("Cannot call a class as a function");
  }
}

var Test = function () {
  function Test() {
    _classCallCheck(this, Test);

    this.foo();
  }

  Test.prototype.foo = function foo() {
    alert('Test::foo()');
  };

  return Test;
}();

var Child = function (_Test) {
  _inherits(Child, _Test);

  function Child() {
    _classCallCheck(this, Child);

    return _possibleConstructorReturn(this, _Test.apply(this, arguments));
  }

  Child.prototype.foo = function foo() {
    alert('Child::foo()');
  };

  return Child;
}(Test);
```

### `class`構文
まず下の方にある`Test`の定義を見てもらいたいのですが、基底クラスのない`class`構文では、ほぼ「`constructor`→コンストラクタとなる関数」、「インスタンスメソッド→`prototype`のメソッド」と置き換えているだけです[^1]。

`_classCallCheck`が入っていますが、これは「ES6 classを`new`なしで呼ぶと`TypeError`になる」ので、それを再現するためのものです。

### 継承
ES5の鬼門だった継承は、どのようになっているでしょうか。これは`_inherits`関数で実現されています。中身としては、

0. 親クラスが`null`もしくは関数かをチェック→違えば`TypeError`
1. 親クラスのプロトタイプを引き継いで、そして`constructor`も正しく設定したオブジェクトを子クラスの`prototype`に設定
2. 子クラスの`__proto__`も親クラスに設定[^2]

そして、親クラスのコンストラクタを`apply`で呼んでいますが、`instanceof`はプロトタイプを遡るので、問題なく
`_classCallCheck`をクリアできます。`_possibleConstructorReturn`ですが、「`new`で呼ばれた関数は、内部でオブジェクトを`return`した場合は、新しく生成したオブジェクトの代わりにそれを返す」ということになっているので、その挙動を取り入れるためのものです。

なお、`super`で親クラスのメソッドを呼ぶと、`親クラス.prototype.method.call`のような形にコンパイルされます。そして、メソッド内の`this`は`this`のままなので、親クラスの中で呼んだメソッドも、そのオブジェクト自身で解決されます（子クラスやオブジェクト自体のメソッドがあれば、そっち優先）。

## まとめ
ES6の実装前には、継承の方法もライブラリや環境によって違うようなカオス状態でしたが、ようやく統一された形となって一件落着した気もします。

[^1]: 性質上、ES6時点でコンストラクタがなくても、`_classCallCheck`を呼ぶだけのコンストラクタが自動生成されます。
[^2]: これは、クラスオブジェクト自体（`static`メソッド）の継承のためで、インスタンスメソッドには影響しません。
PHPで複数単語のAND検索するSQLを作る方法を教えてください

これは「コードを書いていて困ったときに、suinがチャットで質問に答えたり相談に乗る[suinのプログラミング相談室(仮)](https://help.suin.io/)」で頂いた質問と僕の回答の要約です。

## 質問

「あああ いいい ううう」のようなスペース区切の単語をSQLでAND検索できるコードを書いてみたのですが、もっと良い書き方ってありませんか？

```php
$keywords = ['A', 'B', 'C', 'D', 'E']; // 回答者注:SQLインジェクションが発生しない安全な文字列と仮定します。

switch (count($keywords)) {
case 1:
	$sql = "SELECT * FROM products WHERE name LIKE '%$keywords[0]%'";
	break;
case 2:
	$sql = "SELECT * FROM products WHERE name LIKE '%$keywords[0]%' AND name LIKE '%$keywords[1]%'";
	break;
case 3:
	$sql = "SELECT * FROM products WHERE name LIKE '%$keywords[0]%' AND name LIKE '%$keywords[1]%' AND name LIKE '%$keywords[2]%'";
	break;
case 4:
	$sql = "SELECT * FROM products WHERE name LIKE '%$keywords[0]%' AND name LIKE '%$keywords[1]%' AND name LIKE '%$keywords[2]%' AND name LIKE '%$keywords[3]%'";
	break;
case 5:
	$sql = "SELECT * FROM products WHERE name LIKE '%$keywords[0]%' AND name LIKE '%$keywords[1]%' AND name LIKE '%$keywords[2]%' AND name LIKE '%$keywords[3]%' AND name LIKE '%$keywords[4]%'";
	break;
}
```

suin: この方法だと、無限に`case`を増やさないとだめですもんね。
質問者: はい、そうなんです。

## suinの回答

アルゴリズムに関する質問ですね。手順としては次のように実装します。

1. キーワードを`foreach`で回して、`name LIKE %xxx%`といったLIKE句の配列を作る。
2. 配列を文字列`"AND"`でくっつけて、WHERE句用の文字列を作る。
3. 作ったWHERE句用文字列を全体のSQLにくっつける。

```php
$keywords = ['A', 'B', 'C', 'D', 'E']; // 回答者注:SQLインジェクションが発生しない安全な文字列と仮定します。

// キーワードの数だけループして、LIKE句の配列を作る
$keywordCondition = [];
foreach ($keywords as $keyword) {
    $keywordCondition[] = 'name LIKE "%' . $keyword . '%"';
}

var_dump($keywordCondition); 
// ここで、 
// [ 'product_name LIKE "%hoge%"', 
//   'product_name LIKE "%fuga%"', 
//   'product_name LIKE "%piyo%"' ]
// という配列ができあがっている。

// これをANDでつなげて、文字列にする
$keywordCondition = implode(' AND ', $keywordCondition);

// あとはSELECT文にくっつけてできあがり♪
$sql = 'SELECT * FROM products WHERE ' . $keywordCondition . ' AND ... 他に条件があればここに書く ';
```

## 回答に対しての反応

なるほど！ やってみます！
Elecrow GPS shield with antenna



GPSの出力をSDカードに書き込むというのを手軽にやりたい。

Elecrowのシールドが良さそうだった購入してみた。今回はGenuino 101を使用しているが、Genuino 101ボードに搭載されたペリフェラルの機能は使用していない。

# Genuino 101

Intel製のArduino互換ボード。CPUにCurie, IMUにBosch BMI160を搭載している。さらに通信はBLEが利用できる。

写真中央の横長の長方形のチップがCrue本体、IMUは…どれだろう（Curieの左下の正方形のチップかな？）、右下の黄色の部分がBLEのアンテナ。

![2017-06-15 14.42.33.jpg](https://qiita-image-store.s3.amazonaws.com/0/29860/cb0e5231-0f0a-b11f-b2f6-b01b3b7fa0b9.jpeg "2017-06-15 14.42.33.jpg")

# Elecrow

[Elecrow GPS shield with antenna](https://www.elecrow.com/gps-shield-with-antenna-p-696.html)はublox NEO-6MとSDカードを搭載している。

写真中央の銀色のシールド部分がGPSで、μFLとSMAのアンテナコネクタが実装されている。それから、右下の光が反射している部分がSDカードスロット。microSDが使える。

![2017-06-15 21.16.55.jpg](https://qiita-image-store.s3.amazonaws.com/0/29860/c22ed5a6-3896-da49-fc34-4d7c08e08bb5.jpeg "2017-06-15 21.16.55.jpg")


# サンプルコード

[Elecrowのデモコード (zip注意)](http://www.elecrow.com/download/GPS%20demo%20code.zip)を拝借して改造した。

```clang
#include<SoftwareSerial.h>
#include<SD.h>

const int chipSelect = 10;        // SDピンセレクタ
SoftwareSerial SoftSerial(6, 7);  // GPS用ソフトウェアシリアルピン

char buffer[256]; // GPSデータ受信バッファ
int count = 0;    // バッファ格納時のカウンタ


void setup() {
  SoftSerial.begin(9600);           // the SoftSerial baud rate
  Serial.begin(115200);             // the Serial port of Arduino baud rate.

  // SDカードのピンセレクタを出力に変更する
  pinMode(10, OUTPUT);
  if (!SD.begin(chipSelect)) {
    return;
  }
}

void loop() {
  if (SoftSerial.available())  {
    // ソフトウェアシリアルからデータが届いたら実行される
    while (SoftSerial.available()) {
      buffer[count++] = SoftSerial.read();   // バッファにシリアルから取得した値を格納する
      if (count == 256) break;
    }
    Serial.write(buffer, count);   // バッファが一杯になったらPC向けのシリアルに送信する

    // SDカードのファイルを開く
    File dataFile = SD.open("datalog.txt", FILE_WRITE);
    if (dataFile) {
      // 開けたら書き込み。他にchar[]をStringに変換する方法がわからなかった…。
      String str(buffer);
      dataFile.print(str);
      dataFile.close();
    }

    // GPSデータ受信バッファとカウンタをクリアする
    clearBufferArray();              
    count = 0;
  }

  if (Serial.available()) {           // if data is available on hardwareserial port ==> data is comming from PC or notebook
    SoftSerial.write(Serial.read());       // write it to the SoftSerial shield
  }
}

void clearBufferArray() {
  // 受信バッファを0フィルする
  for (int i = 0; i < count; i++) {
    buffer[i] = 0;
  }
}
```
ZABBIX: NWのI/F情報をローレベルディスカバリ機能でうまい具合に料理する

# 問題

Zabbixのローレベルディスカバリ(LLD)は便利ですよね。

けど、ネットワーク機器に対してテンプレートをそのまま利用すると、
![image.png](https://qiita-image-store.s3.amazonaws.com/0/82244/cfb37e26-9a29-7fd8-69ae-c19365ce42a8.png)
上記のように、アイテム数が多くなって(１つのインターフェース毎に8アイテム)大変です。
本当にモニタリングしたいI/Fは、数ポートしかないのに…
かと言って、DiscoveryのFilterでいちいち、I/F情報を羅列するのも面倒。

そんな悩みありませんか？

# やりたいこと

モニタリングしたいI/Fって、通常であればコンフィグでDescriptionの記載をしているでしょう(下記のように)。だったら、Description記載＝（イコール）モニタリング対象にすれば良い!!
![image.png](https://qiita-image-store.s3.amazonaws.com/0/82244/3d8beb53-e0d9-8cf8-b9c3-0099b63101c6.png)

つまり、MIBの"ifAlias"の情報に、特定の文字"##"が含まれていれば、モニタリング対象のI/Fであると決めることで、アイテム数を最小限に抑えることができます。

これで、もし数十台のNW機器を監視することになっても、１秒あたりの"1秒あたりの監視項目数"を抑えることができます(やらなかったら50ぐらいすぐ超えちゃいます)。
パケット転送量・NW機器の負荷、なによりZabbixサーバの負荷軽減となります。

# 実現方法

簡単です。
ネットワーク機器用にテンプレート「Template SNMP Interfaces」を使用しているとします。
このテンプレートのディスカバリ部分を２点変更するのみで実現できます。

## テンプレート内のディスカバリルールを修正
項目”SNMP OID”の内容を以下の通り変更します。
これにより、ディスカバリ内でマクロ{#IFALIAS}が使用可能となります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/82244/900ba18b-e0ba-7347-2c92-16c04c7fbf76.png)

* discovery[{#SNMPVALUE},IF-MIB::ifDescr,{#IFALIAS},IF-MIB::ifAlias]

## テンプレート内のディスカバリルールのフィルタを修正

今まで、{#SNMPVALUE}(つまりifDescr)を正規表現対象としていましたが、ifAliasを正規表現対象とすることで、ディスクリプションに"##"が含まれるi/fのみを対象として抽出できます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/82244/f4b19441-7ac0-0e83-e20b-019eb557e964.png)


# どーでもいい疑問

みなさんも思われたかもしれませんが、
NW機器のI/Fコメント部分はDescriptionコマンドで記載しますが、
MIBのOID名では、ifAliasに登録されています。
下に例があるように、ifDescrは、I/F名(FastEthernet0等)が登録されています。
なんでだろ

```
[root@sv ~]# snmpwalk -v 1 -c public 192.168.10.2 ifDescr
IF-MIB::ifDescr.1 = STRING: FastEthernet0
IF-MIB::ifDescr.2 = STRING: FastEthernet1
IF-MIB::ifDescr.3 = STRING: BRI0
...
[root@sv ~]# snmpwalk -v 1 -c public 192.168.10.2 ifAlias
IF-MIB::ifAlias.1 = STRING: ## To SV#1
IF-MIB::ifAlias.2 = STRING: ## To SV#2
IF-MIB::ifAlias.3 = STRING: 
...
```

# 本番適用の際の考慮点

* テンプレート「Template SNMP Interfaces」はサーバ等と共用しているので、別テンプレートに複製してから修正する等の工夫が必要
* ディスカバリの{#SNMPVALUE}は名前変更したり、削除したりする際は気をつけましょう
* 今回作成した{#IFALIAS}を活用して、表示名を判り易くさせたりするのもよいかも
RailsからHer経由でAPIのResponse-Headerを取得する

## 動機は`X-WP-Total`
RailsからのHer経由でWP REST APIの[投稿総数X-WP-Total]("https://developer.wordpress.org/rest-api/using-the-rest-api/pagination/")を扱いたかった。

## バージョン
- Rails 4.2.8
- [Her 0.8.6]("https://github.com/remiprev/her")

## 要点
- [Herの標準機能ではResponse-Headerを取り出せない。]("https://github.com/remiprev/her/issues/16#issuecomment-6564759")
- [標準Parser]("https://github.com/remiprev/her/blob/master/lib/her/middleware/first_level_parse_json.rb")を基に独自Parserを追加すれば良い。
- Faradayから来るresponse_headersは[Faraday::Utils::Headers]("http://www.rubydoc.info/github/lostisland/faraday/Faraday/Utils/Headers")。
- [Faraday::Utils::Headers]("http://www.rubydoc.info/github/lostisland/faraday/Faraday/Utils/Headers")は.to_hashして扱うと楽。

## サンプル
``` ruby:lib/header_parser.rb
class HeaderParser < Her::Middleware::DefaultParseJSON
  def parse(env)
    json = parse_json(env[:body])
    # ↓Faraday::Utils::Headersをto_hash
    header = env[:response_headers].to_hash
    errors = json.delete(:errors) || {}
    metadata = json.delete(:metadata) || {}
    {
      :data => json,
      :errors => errors,
      # ↓適当に格納
      :metadata => {
        :response_headers => header,
        :additional_metadata => metadata
      }
    }
  end

  def on_complete(env)
    env[:body] = case env[:status]
    when 204
      parse('{}')
    else
      parse(env)
    end
  end
end
```

```ruby:config/initializers/her.rb
Her::API.setup url: "https://api.example.com" do |c|
  # Request
  c.use Faraday::Request::UrlEncoded

  # Response
  # c.use Her::Middleware::DefaultParseJSON
  # ↓独自パーサーを指定
  c.use Her::Middleware::HeaderParser

  # Adapter
  c.use Faraday::Adapter::NetHttp
end
```

```ruby:controller.rb
Model.all.metadata[:response_headers]
# ↑Response-Headerが入る
```

あとはよしなに。
laravel でフォームの post 先を任意で設定する


## 経緯
laravel でform を作ってpostできるようにはできたんですが、
form先のURLを指定する方法を見つけるのに少し時間がかかったので
大した手順じゃないんですがまとめておきます。
 
 
##参考サイト
- ララ帳
https://laravel10.wordpress.com/2015/03/08/初めてのlaravel-5-16-formの作成/

- laravel collective 公式リファレンス   https://laravelcollective.com/docs/5.1/html#opening-a-form 
 
##手順
###フォームを用意する
laravelでフォームを作ろうとすると、以下ページが出てくると思いますので、まずは手順通りにフォームのページを作ってください。
  https://laravel10.wordpress.com/2015/03/08/初めてのlaravel-5-16-formの作成/
  
###post先のURLを指定する
上の記事では以下のようなコードになっているかと思います。
```{!! Form::open() !!}```

これを以下の様に書き換えるだけのようです。
```{!! Form::open(['url' => 'post_url']) !!}```

##コードを確認する
ビルトインサーバーでサイトへアクセスし、htmlがどうなっているか確認島する。

```
    <body>

    <form method="POST" action="http://localhost:8080/post_url" accept-charset="UTF-8"><input name="_token" type="hidden" value="WB5YAcrCHuOEF0foIKVFJAR0pR3KSuooTyc1Qob9">
        <div class="form-group">

            <label for="title">Title:</label>
            <input class="form-control" name="title" type="text" id="title">
        </div>
        <div class="form-group">
            <label for="body">Body:</label>
            <textarea class="form-control" name="body" cols="50" rows="10" id="body"></textarea>
        </div>
        <div class="form-group">
            <input class="btn btn-primary form-control" type="submit" value="Add Article">
        </div>
    </form>

    </body>
```

action が/post_url になっていますね。

簡単ですが以上です。
ワイルドカードを用いて複数の条件に合致させる方法

![ワイルドカード.png](https://qiita-image-store.s3.amazonaws.com/0/160563/2c429c44-511f-be7a-cd88-64d5e7c2baf5.png)


#ワイルドカードとは？
特定の記述方法を用いて、色々なパターンにマッチされるように設定すること。

```html:qiita.rb
(例)
「abc」で始まる文字列の数を数えたい

<!-- 記述方法 -->
=COUNTIF(A1:A5,abc*)
<!-- 説明 -->
A1からA5の範囲でabcで始まる文字列が含んでいるものをカウントする。
「*」がワイルドカード。
abc以降はなんでも良いということ。
```

#ワイルドカードの記述方法
|ワイルドカード|記述方法|
|:---|:---|
|*|0文字以上の任意の文字列|
|?|1文字の任意の文字列|

##ワイルドカードの利用例
|利用例|記述方法|マッチパターン|解説|
|:---|:---|:---|:---|
|「A」を含む|\*A\*|A,AB,BAB|Aが含まれる文字列にマッチする|
|「A」で始まる|A\*|A,AB|Aから始まる文字列にマッチする|
|「A」で終わる|\*A|A,BA|Aで終わる文字列にマッチする|
|「A」と任意の1文字|A?|AB,AC|A+「任意の一文字」にマッチする|

#ワイルドカードが使える関数
ワイルドカードは全ての関数に利用できるわけではなく、特定の関数にしか適用されない

* SUMIF(s)
* COUNTIF(s)
* AVERAGEIF(s)
* SEARCH
* MATCH
* VLOOKUP
* HLOOKUP

#実例

* 特定の文字列を含む合計

```html:qiita.rb
<!-- 記述方法 -->
=COUNTIF(A2:A7,"*文字列*")
=SUMIF(A2:A7,"*文字列*")
```

>![sample01.png](https://qiita-image-store.s3.amazonaws.com/0/160563/3d2eef72-16a1-a867-bf2c-4939b2ead0b3.png)

#サンプル
* [Googleスプレッドシート](https://goo.gl/qqNwKd)
VisualStudio プロジェクトに既存のファイルを追加する時の注意点

##プロジェクトに既存のファイルを追加する時の注意点

プロジェクトに既存のファイルを追加する際に項目に「追加」と「リンクとして追加」があります。「追加」を押すとファイルがコピーされて追加されます。「リンクとして追加」はコピーされずに追加されます。

<img width="1118" alt="スクリーンショット 2017-06-15 20.49.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/182324/99a41b7f-65fd-69bf-f751-3663165828df.png">
getElementsBy**で取得したDOM要素をすべて削除するにはどうするの？

これは「コードを書いていて困ったときに、suinがチャットで質問に答えたり相談に乗る[suinのプログラミング相談室(仮)](https://help.suin.io/)」で頂いた質問と僕の回答の要約です。

## 質問

JavaScriptのgetElementsBy**で取得したDOM要素をすべて削除したいのですがうまくいません。
※提示していただいたコードの秘密を守るため、下記コードは実際のものとは異なります。

```html:ネコ科だけ取り除きたい
<div class="animals">
  <div class="nekoka">ネコ</div>
  <div class="inuka">オオカミ</div>
  <div class="inuka">イヌ</div>
  <div class="inuka">キツネ</div>
  <div class="nekoka">トラ</div>
  <div class="nekoka">ライオン</div>
</div>

<script>
// ネコ科の複数のDOM要素が取れる
const elements = document.getElementsByClassName('nekoka')

console.log(elements.length) // 3

Array.prototype.forEach.call(elements, e => {
  e.remove() // elements自体が減ることでうまくいかない
})
</script>
```

これを実行すると「オオカミ、イヌ、キツネ、ライオン」が残り、ネコ科の「ライオン」が残ってしまいます。いろいろ試してみてできる方法を見つけたのですが、コードが長くなってしまいます。シンプルに解決する良い方法はありませんでしょうか？


## suinの回答

`document.getElementBy**`の戻り値はHTMLCollectionオブジェクトです。この中に入っているDOM要素が削除されるとコレクションの長さが変わることを利用して、`while`で書くとシンプルに実現できます。

```js
const elements = document.getElementsByClassName('nekoka')
while (elements.length) {
  elements.item(0).remove()
}
```


## 回答に対しての反応

ループ対象の要素が減っていくのを利用して、要素が無くなるまで先頭の要素を削除し続けるわけですね！ シンプルで良さそうです。
Google API Design Guideを読んで気になった点


# モチベーション

- 最近公開されたAPIデザインガイド
- TechGiantのAPI設計から学びたい

# Google API Design Guideとは

- https://cloud.google.com/apis/design/
- 2017 2/20 に公開された
- 2014年からGoogle内部で実際に使われているAPIデザインガイド
- REST, gRPC どちらにでも使えるように作られて
- 決定版ではなく、日々追記されていく

# 基本はRESTful

https://cloud.google.com/apis/design/standard_methods

基本はRESTfulなので、知ってる人は見慣れた説明が並んでいる

# カスタムメソッド

```
https://service.name/v1/some/resource/name:customVerb
```

- httpメソッドにマッピングできない操作に対して、作って良い
- :動詞 を最後につけて示す
- メソッドは柔軟であるPOSTを推奨
- PATCHで使うべきではない

## カスタムメソッド使用例

- VM再起動
 - 状態の遷移を行うAPIや、再起動リソースを作るAPIよりも、カスタムメソッドの方が直感的
- メール送信
 - ドラフト→送信トレイへ移動、というデザインよりも、カスタムメソッドの方が直感的

RESTfulにこだわるよりも、ユーザが直感的にわかることが重要 

# エラー表現

https://cloud.google.com/apis/design/errors

- エラーコードは少なければ少ないほど、クライアントのロジックが複雑にならなくて済む
- status（エラーコード）は数列ではなく、人間でも読める英単語を使ってる

# ページネーション

- リスト化できるコレクションはどんな小さなものでもページネーションを実装しておくべき
    - 既存のAPIにページネーションを後から実装すると、元々全件返していたものが１ページ目（デフォルトページ）のみ返す、というような挙動の変更が発生してしまうから

Google API Design Guideに従ったAPIは

```
リクエスト： page_size と page_token パラメータ
 レスポンス： next_page_token を返す
```

を使った共通の実装にしている

# 他

- *ではなく-を使いましょう
    - URLエスケープの都合上
- リソースの一部のフィールドだけ返せるようにすると便利
- リソースをfullではなくbasicなものだけ受け取れるようにすると便利
- APIドキュメントの作り方

などなど・・・

# まとめ

- RESTfulを推奨しているが直感的な設計を重視
- 複数サービスで仕様が混濁しないように、ページネーションなどルールが厳格に決まっている
- 仕様とドキュメントはprotoファイルで管理
- API設計の資料として十分まとまっていて使えそう
JavaScriptでifを式として扱いたい

最近 Kotlin を触って、if を式として扱えることの美しさに気が付きました。
そこで、普段よく使う JavaScript でも if を式として扱えないか考えてみました。

# if を式として扱うとは？

if の各ブロックで最後に評価された結果を返すことを言います。
下記リンクが参考になると思います。
[Kotlinのif式とwhen式](http://saburesan.hatenablog.com/entry/2016/09/06/125833)

Kotlin の場合の if 式は下記のようになります。

```kotlin
val x: Int = 1;
val value =  
  if ( x == 1 ) {
    "true"     
  } else {
    "false"
  }

println(value) // "true"
```

また、Ruby も if を式として扱っているのですが、Ruby の場合は下記のようになります。

```rb
x = 1
value = 
  if ( x == 1 )
    "true"
  else
    "false"
  end

p value # "true"
```

# メリット

冗長でなくなり、コードの美しさが増す。

# if が式じゃないとどうなる？

JavaScript で普通に if を使うと、下記のように代入が2箇所で行われ冗長になります。
更に、変数宣言した後に値を代入をするため `value` を定数に出来なくなってしまいます。

```js
const x = 1;
var value;
if ( x == 1 ) {
  value = "true";
} else {
  value = "false";
}

console.log(value);
```

また、if ブロック内で定数定義をしてしまうと、ブロックスコープ になるので、if 文の外では参照できなくなります。 

```js
const x = 1;
if ( x == 1 ) {
  const value = "true";
} else {
  const value = "false";
}

console.log(value);
// ReferenceError: value is not defined
```

これで条件が更に増えた場合は更に冗長になってしまうので、if 式は是非欲しいところです。


# JavaScript で if を式として扱う

ラムダ式の中に if を置いて、if ブロックの中で return することで if を式っぽく扱ってみました。

```js
const x = 1;
const value = ((x) => {
  if ( x === 1 ) {
    return "true";
  } else {
    return "false";
  }
})(x);

console.log(value); // true
```

コード量は通常よりも多くなってしまいますが、スマートさで言えばこちらのほうが良いのでは無いかと思います。


# まとめ

ラムダ式の中で if を使って式っぽく扱う方法はなんとなく面倒に感じてしまうので、これよりも良い方法をご存知の方がいましたら是非教えて頂けると幸いです。
RailsアプリをCentOs上で動かす。

1か2のどっちかでやる

1)apacheにpassengerを入れてapache上で動かせるようにする。
http://qiita.com/tporange/items/9ab8ec21cbe4b0b29379
virtualhostsでドメインによって動的にディレクトリ変えられるから便利。

2)webrickで立ち上げる。

```bash
rails server --binding=0.0.0.0
```

ドメイン:3000でアクセスできる。
http://blog.toshimaru.net/publish-rails-app-in-lan/
--binding=0.0.0.0をいれないと、ローカルホストとして解釈されるので、指定する必要がある。
0.0.0.0はワイルドカードで、LAN内全て許可。
webrickのデフォルトポートは3000だが、オプション -pで指定のポートに変えられる。

```bash
rails s -p 8080 --binding=0.0.0.0
```
さくっと動かせて便利。
init.elをスモークテストする

## init.el編集後、Emacsを再起動できない！？
Emacsのinit.elを編集したあとEmacsを終了し、正常に起動できなくなってしまい困った経験はないでしょうか。
私はたくさんあります。編集しなおそうにも肝心のEmacsが思い通りに動いてくれないわけで、イライラと悲しみをかかえながら問題を解決することになるわけです。

こうした事態を避けるため、init.elを編集したあとは```byte-compile```をするとか、
```eval-buffer```をするとかして、早めにエラー検出するよう心がけていました。それでも起動できなくなることは多くありました。
eval-bufferなどで文法エラーなどは検出できるものの、必要なライブラリを読み込めてなかったり、ライブラリの仕様が変わったりしてエラーになることが多かったのです。特に、自作ライブラリを使ったりしているとそうした問題がよく発生します。

ソフトウェアテストでは、まっさらな環境を準備するのが大切と言われます。
init.elをテストする場合も、やはりまっさらな環境でテストすることが必要なわけです。

## スモークテスト
さて、ソフトウェアテストには「スモークテスト」と呼ばれるものがあります。もともとは、「水道管に煙を流し込んで漏れがないかをチェック」「ハードウェア製品／部品に電源を投入し、煙が出たり発火したりしないことを確認する」という意味だったそうで、ソフトウェアの世界では、とりあえず実行ができるかどうかを試すテストの意味で使われます。
詳しくは、[ITmrdiaの「情報システム用語事典」](http://www.itmedia.co.jp/im/articles/1111/07/news166.html)や[WEBサービスソリューションHeartsNの用語集](https://heartsn.com/management/web-consulting/it-glossary/su-line/smoke_test/)などを参照して下さい。[マイクロソフト社のドキュメント](https://msdn.microsoft.com/ja-jp/library/ms182613(v=vs.90).aspx)によれば、「コードを見直した後にソフトウェアの不具合を確認し修正する作業として、スモーク テストは最も費用効率の高い方法」だそうです。このスモークテストをinit.elに対して適用できないか、ということを考えました。

## init.elのスモークテスト

1. init.elで最終行に特定の文字列、たとえば"End of loading init.el."を出力するようにする
1. Emacsをバッチモードで実行し、init.elを読み込ませ、すぐに終了する

この手順でバッチモードのEmacsから、最終行が正しく出力されるかチェックすれば、まっさらな環境でinit.elの動作を確認できるはずです。

では、実際にやってみます。

### 最終行で "End of loading init.el."を出力
最終行で "End of loading init.el."を出力するには、init.elの最後の行に次の1行を追加します。

``` init.el
(message "End of loading init.el.")
```

Emacs Lispのmessage関数は、ヘルプに記載されているように、指定されたメッセージを通常は画面下部に表示し、\*Messages\*バッファに出力します。バッチモードでは、標準エラーに出力されるので、バッチモード時のメッセージの確認にも適した関数です。

### Emacsをバッチモードで実行

M-!で、shell-commandを呼び出し、次のコマンドを実行します。

```
emacs -batch -l ~/.emacs.d/init.el 2>&1
```

すると、\*Shell Command Output\*バッファにinit.elを読み込んだときのメッセージが出力されています。このバッファの最終行に"End of loading init.el."が出力されていれば、init.elは最後まで読み込まれたことになります。


出力されるメッセージが多く、最終行の確認が面倒な場合、LinuxやMacでは次のコマンドを実行すればいいでしょう。

```
emacs -batch -l ~/.emacs.d/init.el 2>&1 | tail -1
```

emacsの出力結果をパイプでtailコマンドに渡して、最終行だけを表示します。Emacs画面下部のミニバッファに```End of loading init.el.```が表示されていれば、init.elが最後まで読み込まれたことになります。異なるメッセージが表示される場合は、init.elの記述が正しいかを確認すべきです。

また、teeコマンドを使って次のコマンドを実行すると、実行ログをmessage.logファイルに保存しながら、スモークテストを実行できます。

```
emacs -batch -l ~/.emacs.d/init.el 2>&1 | tee message.log | tail -1
```

## 繰り返しテストするために

こうしたスモークテストは、init.elなどを修正するたびに行うべきです。そのためには、簡単な手順で実行でき、結果もわかりやすく確認できるのが望ましいです。

私は、自作のテストフレームワーク[Autotest.mk](http://www.j8takagi.net/autotest_mk/)を使い、init.elのあるディレクトリーでmakeを用いた```make check```を実行すれば、スモークテストを実行できるようにしています。Emacsでは、makeを用いたコマンドは```compile```というコマンドから実行すると便利です。

ほかに、Emacsのテストフレームワークである[ERT](https://www.gnu.org/software/emacs/manual/html_node/ert/)を使って、スモークテストを実行するコマンドを作ってもいいかもしれません。


## まとめ

init.elをスモークテストする仕組みを作れば、Emacsを再起動できなくなって悲しい思いをすることが少なくなります。