OmniAICreator/Qiita-1.07M huggingface dataset:
劇的ビフォーアフターJS編

自分が書いたコード(全部の絵文字を出力するjs)をリファクタリングした https://qiita.com/taroyanaka/items/21b044d84dcf9a65dfb0
この記事凄い良かったから古い書き方のJS各位読んだら嬉しいはず
https://ginpen.com/2017/12/03/arrow-funcitons/
http://js-next.hatenablog.com/entry/2014/07/23/173147



```before.js
[...Array(10000000).keys()].map(function(value){
  return String.fromCharCode(value)
}).filter(function(value){
  return /\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F/gu.test(value);
})
```


```after.js
[...Array(10000000).keys()]
.map(v=>String.fromCharCode(v))
.filter(v=>/\p{Emoji_Modifier_Base}\p{Emoji_Modifier}|\p{Emoji_Presentation}|\p{Emoji}\uFE0F/gu.test(v))
```

5行(222文字)→3行(164文字)。匠の手にかかって簡潔になり可読性も向上しました。

余談。chromeのconsoleはshift+enterで改行。知らなかった。
Rails5.1のform_withはデフォルトでremote: true

Rails5.1から`form_with`が追加されているが、これがデフォルトオプションが`remote: true`（つまりXMLHTTPRequestオブジェクトリクエストを送っている。ajaxでよく使うやつ。）になっている。

> By default form_with attaches the data-remote attribute submitting the form via an XMLHTTPRequest in the background if an Unobtrusive JavaScript driver, like rails-ujs, is used. See the :local option for more.

ref: https://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_with

前バージョンまでの`form_for`や`form_tag`はデフォルトでは、上記のようになってないので、たまに「あれ！submitしてるのにページが遷移しない！！！なんでや！！！」って２〜３回なったので備忘録として残しておく。
（ちなみに、ドキュメント見たり、ググればこれ関連はたくさん出てくるが、`remote: true`をオフにしたければ、`local: true`オプションを追加する必要がある。）
Nginxでgeoモジュールを使ってメンテナンス中にIP制限をかける

# やりたいこと
- メンテナンスモード時に一部のアクセスは許可(200)し、それ以外はメンテナンス(503)を返すようにしたい

# 実現方法
- Nginxのgeoモジュールを利用する


# 設定(geoモジュールを使う)
- Nginxドキュメント(geo)
  - http://nginx.org/en/docs/http/ngx_http_geo_module.html 
- `$ nginx -V` でモジュールが利用できるか確認する
 - `--with-http_geoip_module` が出力されればok!

- 許可するIPを指定する(今回はVPC内は許可にした)
  - デフォルトは0 ( False )
  - マッチしたら1 ( True )

```
geo $allow_ip {
     default 0;
     10.0.0.0/16 1;
}
```

- `$allow_ip`が 
  - `true`だったら（許可リストに有）、通常モードにする
  - `false`だったら、(許可リストに無)、メンテナンスモードする

```
if ($allow_ip) {
      set $maintenance false;
}
```

- 検証で設定したconfファイルの全体

```
server {
	listen 80 default_server;
	listen [::]:80 default_server;

	root /var/www/html;
	index index.html index.htm index.nginx-debian.html;
	server_name 10.0.1.113;
	error_page 503 @maintenance;

  recursive_error_pages on;
  if (-e /var/www/html/maintenance.html) {
        set $maintenance true;
  }
  if ($allow_ip) {
         set $maintenance false;
  }
  if ($maintenance = true) {
        return 503;
  }

	location / {
		try_files $uri $uri/ =404;
	}

  location @maintenance {
  expires 0;
  internal;
  if (-f $request_filename) {
     break;
  }
    error_page 405 = /maintenance.html;
    rewrite ^(.*)$ /maintenance.html break;
  }
}
```

## 実行結果(vpc内から接続)
```
<!DOCTYPE html>
<html>
<title>Welcome to nginx!</title>
<p><em>Thank you for using nginx.</em></p>
</html>
```

## 実行結果(vpc外から接続)
```
<html>
<p> This is Maintenance Page </p>
</html>
```

# 関連
- Nginxでメンテナンスページの設定をする
  - https://qiita.com/yhidetoshi/items/7314b944e1c4edd974db
- Nginxで静的ページにPostすると405で取得できない場合の対処
  - https://qiita.com/yhidetoshi/items/8ce869e76427f0c4acc9
【Swift4】UIPopoverPresentationControllerを使ってiPhone/iPad両対応のPopoverを出してみた

iPhone/iPad両対応のPopoverを試してみました。
※キャプチャにすると影の部分が不自然に映りますが、実際は気にならないのでご安心ください

![popover.gif](https://qiita-image-store.s3.amazonaws.com/0/112818/057f7930-7953-3778-e030-4444c4deb629.gif)



# 環境
Swift4.2
Xcode10.0

# コード
コピペで動くと思います。

```Swift:ViewController
import UIKit

class ViewController: UIViewController, UIPopoverPresentationControllerDelegate{

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    @IBAction func btnTapped(_ sender: UIButton) {
        let contentVC = ContentViewController()
        // スタイルの指定
        contentVC.modalPresentationStyle = .popover
        // サイズの指定
        contentVC.preferredContentSize = CGSize(width: 200, height: 200)
        // 表示するViewの指定
        contentVC.popoverPresentationController?.sourceView = view
        // ピヨッと表示する位置の指定
        contentVC.popoverPresentationController?.sourceRect = sender.frame
        // 矢印が出る方向の指定
        contentVC.popoverPresentationController?.permittedArrowDirections = .any
        // デリゲートの設定
        contentVC.popoverPresentationController?.delegate = self
        //表示
        present(contentVC, animated: true, completion: nil)
    }
    
    // iPhoneで表示させる場合に必要
    func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
        return .none
    }
}
```
ポイントは、iPhoneでも表示させたいときには、`UIPopoverPresentationControllerDelegate`で`UIModalPresentationStyle.none`を返してあげること。

`.permittedArrowDirections`には`.up`、`.down`、`.left`、`.right`などが指定でき、`.any`を使うと勝手に判断していい感じのところから矢印を出してくれます。
上下どっちかから出したいという場合は、`[.up, .down]`のように配列で指定することもできます。

```swift:ContentViewController
import UIKit

class ContentViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        view.backgroundColor = UIColor.red
    }
}
```
ContentViewControllerでは背景色のみ設定しています。

# 参考資料
[Popoverの2つの実装方法を比較する](https://qiita.com/hsylife/items/9df3dee1fc70b244da8c)
before_action :authenticate_user!をコントローラごとに書かない方法

###authenticate_user!とは
***authenticate_user!***はdeviseを入れると使えるようになるヘルパーの一つ。
コントローラーに設定して、ログイン済ユーザーのみにアクセスを許可する。

ただしこれを全てのコントローラごとに設定するのは、見栄えが悪い。

なので継承を使って修正していく。

###ディレクトリを作ってその中にapplication.controller.rbを作る
例えば```before_action :authenticate_user!```を通常のcontroller/application_controller.rbに書いてしまうと、
全コントローラに適用されて（homeとかtopとか）、ログインが関係ないところにも実行されてしまう。

なので、例えば***usersディレクトリを作り、その中にapplication_controller.rbを作る。***

```users/application_controller.rb
Class Users::ApplicationController  < ApplicationController
end
```

クラス名はディレクトリ構造を揃えないといけないので
　```Users::ApplicationController```となる。(usersディレクトリの中のapplication_controllerってこと)
で、下記のようにbefore_action :authenticate_user!を入れる。

```user/application_controller.rb
Class Users::ApplicationController  < ApplicationController
before_action :authenticate_user!
end
```

##継承元を変える
次に、もともとbefore_action :authenticate_user!を使用していたusers_controller.rbの継承元を変更する

```users_controller.rb
class UserController < ApplicationController
```

これを下記のように変更する。

```users_controller.rb
class UserController < User::ApplicationController
```

このようにして継承先をUser::ApplicationControllerに変更することで、
before_action :authenticate_user!が実行されるようになる（homeとかtopとかには実行されずに済む）
Rails x Ajaxでスマートに「もっと見る機能」を実装する

# はじめに
- 巷でよく見るAjaxでの「もっと見る」機能を一つのページ内で複数種類設置する依頼が来て、色々調べたので共有。
- 完成形としてはこんな感じになります。（見やすさ的に１つずつ出すようにしていますが、適宜数は変えられます）

![](https://dl.dropboxusercontent.com/s/5c1skx7fnbtpwbo/more_demo.gif?dl=0)

- 予備知識として以下のものを頭に入れておく必要があります。

1. Kaminariによるページネーション。
2. RailsのAjax通信。（`index.js.erb`のこととか）
3. BootStrap4（ビューの整形に使っているだけなので、詳しくなくていいけども）
4. Slimテンプレート（３と同様）

# 環境
```
$ ruby -v
ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-linux]

$ rails -v
Rails 5.2.1
```

# 準備
- 以下のものを必要とします。

```rb
gem 'kaminari'
# seedを使うなら
gem 'seed-fu' 
```

# 実装
## モデル
- ここでは例として`Dog`と`Cat`を使いますが、存在としてあればいいので実装は割愛します。
- `seed-fu`とかを使って、前もってページネーション用のインスタンスをDBに作っておきましょう。

## コントローラー
- まずはコントローラーから。今回のページを`sample#index`アクションとします。
- このアクションでは、**htmlフォーマット（通常）**と**jsフォーマット（Ajax）**の二種類のリクエストを扱うことになります。
- 通常アクセスの場合は`guard`（`return unless request.xhr?`）で止まるので、**インスタンス変数を受け取ってページをレンダーするだけ**です。
- しかしAjax通信の場合は`guard`を通過して、**`params[:type]`毎に、異なるJSファイルを実行します**。
- JSファイルの中には、**「特定の一覧リストに新しい要素をAppendして、特定の「もっと見る」ボタンを更新する」**処理が入っているため、**渡したパラメーターによって挙動を変えることができる**のです。

```rb
class SampleController < ApplicationController
  def index
    @dogs = Dog.all.page(params[:page]).per(1)
    @cats = Cat.all.page(params[:page]).per(1)

    # これ以下はAjax通信の場合のみ通過
    return unless request.xhr?

    case params[:type]
    when 'dog', 'cat'
      render "sample/#{params[:type]}"
    end
  end
end
```

## ビュー
- ビューは今回の場合、全部で５つ用意します。

```
app/views/sample/
├── _cat.html.slim
├── _dog.html.slim
├── cat.js.erb
├── dog.js.erb
└── index.html.slim
```
- 基本私は`Slim`を使っているのですが、JSファイルを書く際には`Erb`で書くことを**強く**お勧めします。（調べたらわかりますがとても描きにくい‥‥）
- 余談ですが、**`Slim`使ってても、拡張子に`erb`ってつければ動いてくれる**のでとても助かってます！

### HTMLフォーマット側
```slim
/ index.html.slim
.container.my-5
  .row
    .col-md-6
      #dog-list
        = render partial: 'sample/dog', collection: @dogs
        = link_to_next_page @dogs, 'もっと見る', id: 'more-dog', class: 'btn btn-light w-100', params: { type: :dog }, remote: true
    .col-md-6
      #cat-list
        = render partial: 'sample/cat', collection: @cats
        = link_to_next_page @cats, 'もっと見る', id: 'more-cat', class: 'btn btn-light w-100', params: { type: :cat }, remote: true
```

```slim
/ _cat.html.slim, _dog.html.slim　（cat -> dogに書き換えるだけ）
.border.mb-1
  p cat
```

- パーシャルビューに関しては、存在が確認できればいいだけなので適当です。
- ポイントは以下の通り。
    - それぞれのリストが入る`大元のDivタグ`に`ユニークなID`を付与。
    - `link_to_next_page`メソッドに`ユニークID`と`typeパラメーター`を付与。

### JSフォーマット側
```erb
/ cat.js.erb, dog.js.erb　（cat -> dogに書き換えるだけ）
$('#more-cat').remove();
$('#cat-list').append("<%= j render partial: 'sample/cat', collection: @cats %>")
$('#cat-list').append("<%= j link_to_next_page(@cats, 'もっと見る', id: 'more-cat', class: 'btn btn-light w-100', params: { type: :cat }, remote: true) %>")
```

- ご覧の通り、特定のリストに新しい要素を追加しているだけです。
- Ajaxを呼ぶたびに「もっと見る」ボタンが更新され、もしこれ以上データがないようであれば**自動でレンダーされなくなります**。~~神かよ~~

# おわりに
- こんな感じで想像以上にすっきりとAjaxでの「もっと見る」を実装することができるようになりました。
- 今回は**１ページに「もっと見る」が二つ**という特殊な場合を扱いましたが、別に一つでも全然動きます。
- 皆様良いRailsライフをー👍
PHP基礎（１０）公開レベル

#公開レベル
クラスのなかで定義されたメソッドや変数に対し、外からのアクセスを制限することができます。

|アクセス権|説明|
|:----|:------|
|public	|クラスの外からでもアクセス可能|
|private|定義されたクラス内でのみアクセス可能|
|protected|定義されたクラス内、あるいはそのクラスを継承した子クラスからアクセス可能|

```php
<?php
class Book {
	function begin(){ //アクセス権を省略するとpublicメソッドで定義される
		echo "国境の長いトンネルを抜けると雪国であった。";
	}
	private function neko(){
		echo "吾輩は猫である。";
	}
}

$b = new Book();
$b->begin();
$b->neko();//ここでエラーになります。
?>
```

#演習
【演習2-4】
自動車クラスCarを１つ作り、「走る」「止まる」「給油」というpublicメソッドを実装したクラスを作成してください。

【演習2-5】
【演習2-4】で作成したCarを継承したセダンクラスSedanとトラッククラスTrackを作成し、それぞれのクラスで、「走る」「止まる」「給油」という親のメソッドをオーバーライドしてparentを使って親クラスのメソッドを呼び出しつつ子クラスのメソッドとして「走る」「止まる」「給油」を実装して、インスタンス化して挙動を確認してください。

【演習2-6】
【演習2-5】で作成した継承関係を使って、親クラスの各メソッドのアクセス権をprivateやprotectedに変更して、どのアクセス権の時エラーが出るか実験してください。

[＜＜PHP基礎（９）コンストラクタ]
(https://qiita.com/taka027/items/c1c49c8decd3cea7dbc4)

[PHP基礎（１１）変数たち＞＞]
(https://qiita.com/taka027/items/8beccec15fde098067df)
【ExcelVBA】明細集計処理の戦術メモ

# はじめに
MKが1000番の、ある部品の製造ステータスがBという工程に入った――。
下図右側に、いわゆる未完成部品リストというものがある。この未完成部品リストは毎日サーバー上で生成され、その「未完成の量」という情報を使ってバーンダウンチャートを作成するのだ。そのバーンダウンチャート作成ツールのお話。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/94562/e433021e-8ae2-56b7-cac7-4fa7cd3b7601.png)

# ところでこのプログラム...
全部Excelで処理しようとしていて、毎日5時間かかる処理だ。
1日8時間のなかで毎日5時間っていうのはなかなかタフだろう。実際はタスクスケジューラでキックがかかるので2時間ぐらい稼げるけどそれでも3時間パソコンさわれないのはキツいで...

# 仕事場のパソコンのスペックは高いとは限らない
Celeronの1.9...だったなぁたしか:thinking: えっぐい
エクスペリエンスインデックスとかいうあの数字のヤツは評価が算出できないほど低い...わかるね？OSはWindows7だ。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/94562/ac79c21c-f2d8-47f3-c566-7a0ed992d8bf.png)

# やってることはホンマにただの集計
もう一回同じ図を持ってくるけど、本来はSQLでサーバーからカウント取ってまとめればいいだけの話。最初どうしてこんなに時間がかかるかわからなかった。この遅さは、未完成部品リストのシートAを集計していたいつもの処理に加えて、ちょっと条件の異なるシートBもやってほしいという改修の中で発覚した（処理量が倍以上になるため）。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/94562/e433021e-8ae2-56b7-cac7-4fa7cd3b7601.png)

# 時間がないしドキュメントもない
SQLから持ってくる形にしたいが、そのSQL（ストアドプロシージャ）がこれまた鬼畜なことになっている。現場入って数か月では業務データのロジックなんてわかるわけがない。ドキュメントもなくソース嫁状態で、与えられた期間は5日。おおもとのSQLを解析している時間の余裕はない...。「結果セット」として生成された日次Excelを読んでひとつひとつ加算処理をするというつくりが心臓部になっている以上は、この流れを利用するしかない。

# 処理の重さの分析
いま家にいるし細かいところは忘れちゃったんだけど（まぁ細かく話しても今度はコンプラだしな...）、だいたいの流れとして未完成部品リストをループの軸にして、全量まわって Find で集計シートから key を検索して 1を足す みたいなことをしているからクソ重いわけだ。おまけにこのループのなかでクソ重いテーブルにSELECTを投げる処理があった。ただでさえ量が多い未完成部品リスト側でループをかけているし、つまり未完成部品リストが15,000明細あったらSQLServerに15,000回SELECTを投げてるわけだ。これはネゴっていったんやめにしてもらったが、それにしてもひどい。

# 改修方針
この場合、つくりとしては、左側の集計シート側をループの軸にしなければならない。集計keyが1に対して明細はnなんだから。間違いない...「作っちゃいけない人間」が作っている（しかも例によって作成者本人はもういないし会ったこともない）

[(togetter)流しのプログラマーはメキシコの荒野みたいな現場に行かされがちで着いてみると大体こうなる](https://togetter.com/li/1271782)

# ソースコード
[GitHub](https://github.com/duri0214/VBA/blob/master/%E6%98%8E%E7%B4%B0%E3%81%AE%E3%82%AB%E3%82%A6%E3%83%B3%E3%83%88%E3%82%92%E5%B1%9E%E6%80%A7%E5%88%A5%E3%81%AB%E9%9B%86%E8%A8%88%E3%81%99%E3%82%8B.md) にあります（クロス集計版を追加）
クロス集計版は [ExcelManipulator](https://github.com/duri0214/VBA/blob/master/ExcelManipulator) を使用します

# これ便利だった
[Excelの表をMarkdown形式に変換](https://qiita.com/QUENCH/items/d77d0983d4a6d9d7de8e)

# さいごに
Qiitaに書いたらドキュメント書いてるようなもんやなｗｗ
休みに仕事した分は、せめて汎用化してオープンにさせてもらうわ
週明け楽しみになってきたぞ

# 縮小された時間を計ってみた
4:53:35 かかっていたのが 0:41:33。
3:21:10 縮めたことになる:relaxed:
Array.ofのgenerator版

自動テスト用に引数で受け取ったものをそのまま返す`Array.of`のgenerator版が必要になりました。

## 単純な書き方

```ts
namespace Generator {
  export function* of0(...args: any[]) {
    yield* args;
  }
}
const g0 = Generator.of0(1, '2', true, false, null, undefined, [1], {a:1});
// g0: IterableIterator<any>
```

適当に作ったのはいいんですが、せっかくTypeScriptで書くのだから、受け取った引数の型を返値の型に反映したいですね。

## 素直にジェネリクスを使ってみる

```ts
namespace Generator {
  export function* of1<T>(...args: T[]) {
    yield* args;
  }
}
//const g1 = Generator.of1(1, '2', true, false, null, undefined, [1], {a:1});
// 違う型を指定すると2番目の引数(正確には2種類目の型の引数)でエラー
const g1 = Generator.of1(1,2,3); // 一種類の型しか指定できない
// g1: IterableIterator<number>
```

うーむ…一種類だけしか指定できないのではデグレードです。

## もうちょっと工夫してジェネリクスを使う

```ts
namespace Generator {
  export function* of2<T extends any[]>(...args: T) {
    yield* args;
  }
}

const g2 = Generator.of2(1, '2', true, false, null, undefined, [1], {a:1});
// g2: IterableIterator<any> // やっぱりanyになってしまう
```

元に戻ってしまいました。

## Conditional typesと infer を使う(TypeScript 2.8以降)

```ts
namespace Generator {
  export function* of<T extends any[]>(...args: T): IterableIterator<T extends (infer R)[] ? R : never> {
    yield* args;
  }
}

const g = Generator.of(1, '2', true, false, null, undefined, [1], {a:1});
// g: IterableIterator<string | number | boolean | number[] | {a: number;} | null | undefined>
// やった!
```

ようやくできました。

## (おまけ) Array.concatのgenerator版

`concat`も同じような感じで作れます。
※正確にはArrayのconcatはインスタンスメソッドですが

```ts
namespace Generator {
  export function* concat<T extends IterableIterator<any>[]>(...generators: T): IterableIterator<T extends IterableIterator<infer R>[] ? R : never> {
    for (const g of generators) {
      yield* g;
    }
  }
}

const gg = Generator.concat(
  Generator.of(1, '2', true, false),
  Generator.of(null, undefined, [1], {a:1})
);
// gg: IterableIterator<string | number | boolean | number[] | {a: number;} | null | undefined>
```
PHP基礎（９）コンストラクタ

#コンストラクタ
コンストラクタとはオブジェクトをインスタンス化するときに初回だけ呼び出される特別なメソッドです。newを使った直後に、そのオブジェクトの初期化として呼び出されます。
コンストラクタは省略可能です。
PHPの場合、名称は固定的に`__construct`とします。
メソッドと違う点は戻り値を返せません。メソッドと同じ点は引数を渡せるところです。

```php
<?php
class Figure {
  function __construct($v) {
    echo "頂点の数は$v";
  }
}

$n = new Figure(3);
?>
```

コンストラクタは、インスタンスの初期状態を決めるために使われます。
上の例では、図形クラスFigureが最初に頂点数$vをもらってインスタンス化されています。頂点数を初期時に決めることで図形クラスが三角形を扱うオブジェクトになったとも言えます。（もちろん、実務的にはもっと多くのコードを書いてより図形の振る舞いを実現できるクラスにする必要がありますが）

言わばインスタンス（オブジェクト）は初期値をもらって生まれ、活動し、死んでいく存在です。
オブジェクト指向的考え方として、オブジェクトのライフサイクルを設計し、クラスをプログラミングする時にコンストラクタで初期値として何をもらって、どのようにオブジェクトの最初の状態を決めるか、そこから始めるといいと思います。ちょうどコンストラクタはオブジェクトの始まりでもありますし。

#演習
【演習２−１】
自分の好きな物をターゲットにして適当なクラスを定義し、そこにコンストラクタを用意して、クラスがインスタンス化されるときにそのコンストラクタが呼び出されていることを確認するプログラムを作成してください。


【演習２−２】
【演習２−１】で作成したコード内に新しいインスタンスメソッドを作り、自由な引数を受け取り、戻り値を文字列として任意の文字列を返すようにし、そのメソッドを呼び出して戻り値を確認できるプログラムを作成してください。


【演習２−３】
【演習２−２】で作成したコード内に新しいクラスメソッドを作り、自由な引数を受け取り、戻り値を数値として任意の値を返すようにし、そのメソッドを呼び出して戻り値を確認できるプログラムを作成してください。

[＜＜PHP基礎（８）メソッド]
(https://qiita.com/taka027/items/b5170bf702582e214db6)

[PHP基礎（１０）公開レベル＞＞]
(https://qiita.com/taka027/items/7937ad9ea1130d73feb2)
[rails]rails立ち上げメモ

# 立ち上げしたのでメモ
今回新規プロジェクトを立ち上げたのでメモ。

##コマンド
```terminal
rails new application_name --database=mysql --skip-test-unit --skip-sprockets --webpack=react --webpack=vue
```
## 解説
- rails new
  - railsの立ち上げ。
- application_name
  - ここはプロジェクトネーム
- --database=mysql
  - データベースの設定
- --skip-test-unit
  - デフォルトのテストをスキップする(後々rspecで書くため)
- --skip-sprockets
  - sprocketsをスキップ
- --webpack=react
   - webpackerを入れる
- --webpack=vue
  - vueも入れておく
Xcode10でopenframeworksがビルド出来ない夜に

**追記あり**

https://github.com/openframeworks/openFrameworks/issues/6139

応急処置.

<img width="308" alt="スクリーンショット 2018-10-13 11.10.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/4206/5f2eb0c9-15e4-9329-1522-fb23a5a3023a.png">
ここから

<img width="536" alt="スクリーンショット 2018-10-13 11.10.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/4206/3d28b595-5c50-dab7-949f-c3c655c0649a.png">
こうやって

<img width="603" alt="スクリーンショット 2018-10-13 11.11.10.png" src="https://qiita-image-store.s3.amazonaws.com/0/4206/d5a24117-5b7d-fe9c-dba4-6a336c06b4cd.png">
openFrameworksLib.xcodeproj のここら辺の `-framework QuickTime` を消したら 多分ビルド出来ます.

追記:
<img width="908" alt="スクリーンショット 2018-10-15 11.23.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/4206/d893edf5-bcec-52d9-557a-b840e29ceed3.png">
ここもこうしないとですね.
Python3.6/3.7をインストールするときにハマったところ

#概要
MacOSでhomebrewとpyenvを利用したPythonのインストールを行ったところエラーが発生したため、対応方法を残しておきます。

#環境
| ソフトウェア名 | バージョン |
|:-:|:-:|
| OS | macOS Mojave |
| homebrew | 1.7.7 |
| pyenv | 1.2.7 |

#エラーの内容
```terminal
$ pyenv install 3.6.6

BUILD FAILED (OS X 10.14 using python-build 20180424)

Inspect or clean up the working tree at /var/folders/gy/5g7l9s2n3sjckk4pd92338p40000gn/T/python-build.20181012015323.68978
Results logged to /var/folders/gy/5g7l9s2n3sjckk4pd92338p40000gn/T/python-build.20181012015323.68978.log

Last 10 log lines:
  File "/private/var/folders/gy/5g7l9s2n3sjckk4pd92338p40000gn/T/python-build.20181012015323.68978/Python-3.6.6/Lib/ensurepip/__main__.py", line 5, in <module>
    sys.exit(ensurepip._main())
  File "/private/var/folders/gy/5g7l9s2n3sjckk4pd92338p40000gn/T/python-build.20181012015323.68978/Python-3.6.6/Lib/ensurepip/__init__.py", line 204, in _main
    default_pip=args.default_pip,
  File "/private/var/folders/gy/5g7l9s2n3sjckk4pd92338p40000gn/T/python-build.20181012015323.68978/Python-3.6.6/Lib/ensurepip/__init__.py", line 117, in _bootstrap
    return _run_pip(args + [p[0] for p in _PROJECTS], additional_paths)
  File "/private/var/folders/gy/5g7l9s2n3sjckk4pd92338p40000gn/T/python-build.20181012015323.68978/Python-3.6.6/Lib/ensurepip/__init__.py", line 27, in _run_pip
    import pip._internal
zipimport.ZipImportError: can't decompress data; zlib not available
make: *** [install] Error 1
```

#対処法
2つの情報が載っていました。以下の記載した順に試したら私はインストールができたので、以下の順に皆さんも試してみてください。
###Xcode開発者ツールのインストール
[MacでPython 3.5.0インストールに失敗したら](https://qiita.com/maosanhioro/items/bf93540515d4ea75b222)より抜粋

```terminal
$ xcode-select --install
```

GUIでインストーラが起動するので、指示に従ってインストールしてください。インストールが完了したら、再度Pythonのインストールをします。

```terminal
$ pyenv install 3.6.6
```

###インストール時にマジックワードをつける
[Github:pyenv/Common build problems](https://github.com/pyenv/pyenv/wiki/Common-build-problems#build-failed-error-the-python-zlib-extension-was-not-compiled-missing-the-zlib)より抜粋

インストールする際のコマンドを以下のように指定します。

```terminal
$ CFLAGS="-I$(xcrun --show-sdk-path)/usr/include" pyenv install 3.6.6
```

以上です。ここまでの手順で私はPythonのインストールをすることができました。

#最後に
もしかしたらまだ私が踏んでいない地雷があるかもしれません。
その時はこの記事にコメントするなり、新しい記事を立てるなりしてバグの内容や対策をみんなで共有しましょう。
PHP基礎（８）メソッド

#メソッドの呼び出し方法
クラスの中で定義されるメソッドは３種類の呼び出し方があります。

##1.インスタンスメソッドを呼び出す

クラスの普通の使い方です。基本はこのように使います。

```php
<?php
/* 四角クラス */
class Square {
  /* 面積計算 */
  function calcArea($height,$width) {
    return $height * $width;
  }
}
//クラスをインスタンス化して使う
$sq = new Square();
//こういう形でインスタンス化したオブジェクトのメソッドを呼ぶ
$area = $sq->calcArea(40,30);
echo "area = $area ";
?>
```

##2.継承関係にある親のメソッドを子インスタンスが呼び出す

extendsという構文を使って、クラスの定義の時に親のクラスを継承させるところがポイントです。
子クラスのメソッドの中でparent変数を使い、親クラスのメソッドが呼べるのです。また子インスタンスは親のメソッドをインスタンスメソッドとして呼び出せます。

```php
<?php
# 伝票クラス（親クラス）
class Denpyo {
  private $title;
  # 作成メソッド
  function create($title) {
   $this->title = $title;
  }
  # 印刷メソッド
  function print() {
    echo "This is Denpyo [TITLE]:" . $this->title . "\n";
  }
}
# 伝票クラスを継承した納品書クラス（子クラス）
class Nohinsho extends Denpyo {
  # 子クラス用の印刷メソッド
  function print () {
   //親クラスのprint()メソッドを呼び出す
   parent::print();
   echo "This is Nohinsho\n";
  }
}

//呼び出し
# （子クラスをインスタンス化）伝票を納品書として作成
$n = new Nohinsho();
//こういう形で親クラスのインスタンスメソッドを呼ぶ
$n->create("納品書");
$n->print();

?>
```

継承とは既存のクラスをもとに新しいクラスを作る仕組みのことです。このとき既存のクラスをスーパークラスといい、新しいクラスをサブクラスといいます。スーパークラスを継承してサブクラスを作ると表現します。サブクラスが作られることを派生といいます。
サブクラスではスーパークラスで定義された変数やメソッドをコーディングすることなく持ち合わせています。
継承はオブジェクト指向言語の特徴のひとつで、開発効率（コーディングの手間と可読性、再利用性）を上げることを目的に考えられています。

上の例ではDenpyoクラスを継承したNohinshoはそれぞれprintという伝票印刷メソッドが用意されています。このときこのサブクラスのprintメソッドはスーパークラスのprintメソッドをオーバーライド（塗り替え）しています。一方createメソッドはオーバーライドされていません。継承によりDenpyoクラスのcreateメソッドを実装しているのと同じことになります。

##3.クラスメソッドを呼び出す

スタティック（静的）なメソッドを定義しそれを呼び出します。

```php
<?php
class Circle {
  public static function pi() {
    return 3.14159;
  }
}

$p = Circle::pi();
echo $p;
?>
```
インスタンス化せず（newせず）に使えるところがポイントです。

[＜＜PHP基礎（７）クラス]
(https://qiita.com/taka027/items/3802b7b48b881ab6f48e)

[PHP基礎（９）コンストラクタ＞＞]
(https://qiita.com/taka027/items/c1c49c8decd3cea7dbc4)
mac osのbrew install がうまくいかない

気がついたらbrew installがうまくいかなくなっていたので調べてみました。
OSversion: 10.13.6

### 以下実行とエラー

```
$ brew install libsub pkg-config
```

```
touch: /usr/local/Homebrew/.git/FETCH_HEAD: Permission denied
touch: /usr/local/Homebrew/Library/Taps/caskroom/homebrew-cask/.git/FETCH_HEAD: Permission denied
touch: /usr/local/Homebrew/Library/Taps/caskroom/homebrew-versions/.git/FETCH_HEAD: Permission denied
touch: /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core/.git/FETCH_HEAD: Permission denied
touch: /usr/local/Homebrew/Library/Taps/homebrew/homebrew-services/.git/FETCH_HEAD: Permission denied
touch: /usr/local/Homebrew/Library/Taps/homebrew/homebrew-versions/.git/FETCH_HEAD: Permission denied
fatal: Unable to create '/usr/local/Homebrew/.git/index.lock': Permission denied
error: could not lock config file .git/config: Permission denied
Error: No available formula with the name "libsub"
```

### 解決方法

```
sudo chown -R $(whoami) $(brew --prefix)/*
```
iPhone等の頑固なキャッシュ対策(Wordpress)

# 「表示変わってないんだけど」
よく言われます。特にiPhoneのお客様。
iPhoneは妙にガンコなキャッシュをお持ちらしい。
以下が代表的な対策例。

## cssパラメータを付ける
https://qiita.com/chikaxxx/items/8a3b2acca3209f2d31b4

## 強制reloadさせる
https://www.ituki-yu2.net/entry/iPhone_no_cache

ただ、これらの対策をやっても効かないときは効かない。
それで仕方なく以下の手段をお願いすることになっていた。

# プライベートブラウズで確認してもらう
https://qiita.com/Shoesk/items/be9673def1d8ce6e674b

# キャッシュや閲覧履歴を消してもらう
https://blog.skeg.jp/archives/2017/11/safari-super-reload-iphone.html

最終手段。
でも以下の問題が。

## 「お客さん（本顧客）にキャッシュ消して確認して貰うのは無理」
これ。
iPhoneを持ってるお客さん（非デジタルネイティブ）にキャッシュ消して確認して貰うのはまず無理で、話が分かるお客様でも毎回はさすがにうんざりされる。

# Wordpressならキャッシュ系プラグインを使う手も
WPならなんらかのものがあるはずと思って探してみたが、キャッシュ制御そのものずばりはなかった。
ただ、思うところあり、[WP-Super-Cache](https://ja.wordpress.org/plugins/wp-super-cache/)を入れてみた。[Clear Cache for Me](https://ja.wordpress.org/plugins/clear-cache-for-widgets/)も。

表示のスピードアップ目的でなく、キャッシュシステムを利用してCSSやjs等々を副次的に再読み込みさせられないかと思った。

## 一応、思惑通り動いてくれている模様。
プラグインを入れてからお客様から「表示変わってないよ」と言われることがなくなった。
更新時も、意識してキャッシュクリアしなくとも一応反映されている模様？
怖いのでまだ毎回キャッシュクリアボタン押してます。←何回か忘れたように思うけど大丈夫な模様。

ただ、表示が早くなったと言われることもなかったりして。
Wordpressならこういう手もあるよということでひとつ。


# Wordpressでキャッシュプラグインを入れる前に
Wordpressの場合は以下の方法で更新日時を強制的にパラメータ付与するのを試すといいかも。
PHPが使えれば同じ方法でいけるかも、絶対パスでルートURL取得して、、相対パスの構成の場合はまた別で、、

```php:function.php
// css, jsの更新反映対策
function with_modified_param($path) {
	// return get_template_directory_uri().$path."?"."201810201200"; // 重い場合
	return get_template_directory_uri().$path."?".filemtime(get_template_directory().$path);
}
```

```php:header.php
<link rel="stylesheet" type="text/css" href="<?php echo with_modified_param('/css/xxx.css'); ?>"/>
<script src="<?php echo with_modified_param('/js/xxx.js'); ?>"></script>
```

# cssをimport文でまとめて読み込んでるのが原因だったかも。。？
上記のパラメータ対策を入れる前にimport記述をバラしてみた。
するとあっさりキャッシュ無視して読み込んでくれるようになったり。。
こういう記述はやめたほうがいいのかもしれない。

```html:header.php
<link rel="stylesheet" href="/common/css/import.css?201812261230toka">
<!--↓import.cssの中身-->
@import "reset.css";
@import "fontawesome-all.min.css";
@import "style.css";
@import "print.css";
<!--↓import.cssをばらした記述-->
<link rel="stylesheet" href="<?php echo with_modified_param('/common/css/reset.css'); ?>">
<link rel="stylesheet" href="<?php echo with_modified_param('/common/css/fontawesome-all.min.css'); ?>">
<link rel="stylesheet" href="<?php echo with_modified_param('/common/css/style.css'); ?>">
<link rel="stylesheet" href="<?php echo with_modified_param('/common/css/print.css'); ?>">
```
laravel5のviewで変数に代入する代わりの短縮形

laravel5のbladeテンプレート内で変数が空の場合は初期値0を代入する場合、

```php
@if(empty($number)) <?php $number = 0; ?> @endif

会員No {{ $number }}
```

という記述をしていましたが、綺麗ではないのでbladeならではの記法はないかと調べました。
以下のような三項演算子の代わりになる短縮形が用意されていました。

```php

会員No {{ $number or 0 }}
```  
  
<br>  
参考にしたページ
https://readouble.com/laravel/5.1/ja/blade.html
curl オプションメモ

備忘

* **-I** : ヘッダのみ表示
* **-H** : Hostでホスト指定

```shell
$ curl -I http://192.168.0.100/myindex.html -H 'Host: test.example.com'
```

* **-D -** : ヘッダ含んで標準出力ダンプ

```shell
$ curl -D - http://test.example.com/
```

* **-O** : ファイルのダウンロード

```shell
$ curl http://test.example.com/myindex.html -O
```

* **-o** : ファイル名指定しダウンロード

```shell
$ curl http://test.example.com/myindex.html -o aaa.html
```
PHP基礎（７）クラス

#クラスとオブジェクトの関係

クラスを理解するためにまずクラスとオブジェクトの関係を説明します。

クラスとは、オブジェクトの振る舞いを定義するクッキーの型抜き器具のようなものです。
 	![image.png](https://qiita-image-store.s3.amazonaws.com/0/6363/d52eff67-0522-ece3-cd54-9d545ebb6830.png)　型抜きによって出来上がるクッキー自体がオブジェクトです。
そしてクッキーを抜く行為をインスタンス化といいます。インスタンス化はオブジェクトを生成する行為です。つまり、型抜き（クラス）は唯一のもので、出来上がるクッキー（オブジェクト）は、抜く行為（インスタンス化）によって複数個を作ることが可能です。



そしてインスタンスという言葉は、コンピュータ上で動いているクラスの実行単位という意味が含まれています。なのでオブジェクト＝インスタンスと解釈することができます。同じクラスでもインスタンスはそれぞれ別々の状態を持っていることになります。同じ型抜きを使っても、焼き上がったクッキーはそれぞれ微妙に形が違うのと同じです。


さて、クラスの記述は次のとおりです。クラスは0以上の関数を持ちます。つまり関数のないクラスもあります。関数は処理ですので、このクラスで何かやらせたい処理がなければ関数はなくてもいいわけです。クラス内の関数は特にメソッドとも表現します。（関数＝メソッドと解釈して問題ないです）

```php

<?php
/* 四角クラス */
class Square {
  /* 面積計算 */
  function calcArea($height,$width) {
    return $height * $width;
  }
}

//呼び出し
$sq = new Square();
$area = $sq->calcArea(40,30);
echo "area = $area ";

?>
```
クラスを実際に使うとき（呼び出す時）は、new演算子でインスタンス化させます。newによってインスタンスの実行に必要なメモリ領域がコンピュータの中で確保されます。

上の例では、

`$sq = new Square();`

でSquareというクラスをインスタンス化し、\$sqという変数にオブジェクトを代入し以降、オブジェクト変数$sqが使えます。

[＜＜PHP基礎（６）関数]
(https://qiita.com/taka027/items/dcd266c607ceb14da28e)

[PHP基礎（８）メソッド＞＞]
(https://qiita.com/taka027/items/b5170bf702582e214db6)
ネットワークが何%理解できるかは個人差がありますな記事

# 前置き

この記事は「ネットワークのこと教えてくださーい」とやってきた学生君に対してアドリブで対応した記録になります。不正確な部分、あえて詳細に触れていない部分、また間違ってる部分などがあると思います。間違っている部分についてはご指摘いただけると幸いです。

# はじまり

学「澤田さ～ん、今お時間よろしいですか」
私「いーよ」
学「ネットワークについて教えてほしいのですが」
私（アバウトに来たな）「ネットワークって具体的に何を？」
学「先輩が話していることを理解したくて、ネットワークをどう学べばいいのかと」
学「例えば、サーバってなんですか？コンピュータと違うのですか？」
学「メールってどうなってるんですか？クライアントって、僕のマシンでメール書いてますけど、これはクライアントですよね？この書いたメールがどうやって相手に届いているんですか？」
私「なるほど、じゃあ一から説明することにしますか」

# ネットワーク階層モデルの話

私「確か基本情報処理技術者の資格持ってるって言ってなかった？当然ネットワークも範囲に入ってるはずだけど」
IPAのページ検索
私「サーバはコンピュータであり、情報の提供者、ここでいうIPAね。で、それを受け取って表示する側がクライアント、具体的に言うとこのブラウザ」
私「クライアントからサーバに向けて、これくださいというリクエストが送られて、サーバから、はいどうぞとレスポンスが返される。これが基本」

私「で、どっちから話すか、上からでいいか。具体的にどのような形式でリクエストを送り、どのような形式でレスポンスが返されるかが決まっている。それが**プロトコル**というもの。HTTPのPはprotocolのP」
私「で、このサーバのコンピュータではいろんなプログラムが動いているわけだけど、・・・あーやっぱり下から説明した方がいいな」
私「情報処理技術者試験の勉強してたときにOSI参照モデルっての出てこなかった？」
学「ありました」
私「今ネットワークについて説明しようとする際に、全部まとめてごちゃっと説明しようとするとすごい説明しにくいのね。それを切り分けて説明するために階層構造が作られているというわけ」

# 物理層～データリンク層（イーサネット）

## 物理的な接続

私「そこにケーブルが下がってるわけだけど、通信をするためにはともかくつながっていないといけないわけね。まあ今どきは無線もあるわけだけど」
私「で、ともかくつなぐことができたら0,1が送れると。例えば電圧が高いのを1、低いのを0みたいに。これが**物理層**」

## 非常に雑なイーサネットの説明

私「で、0,1は送れるようになったわけだけどそれだと使いにくいからある程度まとまった単位でやり取りをするようにしたわけで、現実世界だとハガキを送るみたいなもん。層によってハガキの名前が違うのだけど、イーサネットだとフレームと言う」

私「さっきは線がつながっていれば通信できると言ったけど、実際にはネットワーク内にコンピュータが何台もあるから誰に送るかを決めないといけない。誰に送るかというのがアドレス」
学「172なんとかってやつですか？」
私「それはIPアドレス。イーサネットだと**MACアドレス**と言う」
学「MACアドレスってコンピュータに一つなんですか？」
私「いや、ネットワークカードに一つ。だからネットワークカードを2つ挿してたら2つMACアドレスがある。このポート1つにMACアドレス1つな感じ」
学「僕のマシンはポートないんですけど」
私「それって無線だよね。まあ無線のモジュールに対してMACアドレスが付いてる」

※通信全体の話をしたかったので、MACアドレスの形式、アドレス長などの話はざっくり省略です

# ネットワーク層（IP）

私「データリンク層で通信はできるようになったわけだけど、このIPAのサーバ、そこら辺にありそう？」
学「ないですね」
私「そう、IPAのサーバは別ネットワークにある。つまり、IPAのネットワークまでリクエストを届けないといけない。それをやってるのがネットワーク層、TCP/IPで言うとIP。ここで使われるのが**IPアドレス**」
学「あー、だからインターネットって言うんですね」
私「別ネットワークに届けるってどうやってるのとか色々話すと長くなるのでざっくり省略する。ともかく相手までは届くようになったわけだ」

※同様に、IPアドレスの話等はざっくり省略です

# トランスポート層（TCP）

私「相手まで届くようになったので、やっと話が戻ってくるわけだけど、サーバコンピュータで動いてるどのプログラムに届けるか決めなければいけない。これを扱うのがトランスポート層」
学「どうやってるんですか」
私「ああ、言い忘れてた。**ポート番号**で識別する。HTTPだと80ね」
学「プロキシだと8080ですよね」
私「まあ基本的に自由に使っていいのだけど、自由過ぎるとつなぎ先がわからなくなるからこのサービスにはこの番号ってのが決まってる」

※TCPのハンドシェイク等については以下同文

# アプリケーション層（HTTP）

私「ここまでで送る先のプログラムが決まったので、後は個別のアプリケーションの処理になる」
学「セッション層とプレゼンテーション層はどうなってるんですか？」
私「OSI参照モデルだとあるけど、現実の世界だとぶっちゃけそんなきれいに分けれないからセッション層～アプリケーション層がごちゃっとなってる」
学「アプリケーション層のプロトコルっていくつあるんですか」
私「むっちゃある」

## HTTPは何をしているのか

学「HTTPってHTMLやり取りするプロトコルですよね」
私「まあHTML以外も送受信できるけど」
学「HTMLの解析結果が送られてくるんですか？」
私「ああそういうこと、HTTPではくださいといったもの、index.htmlくださいとリクエストしたら、index.htmlの内容が送られてくる。それを読み込んで表示するのはクライアント側（ブラウザ）の仕事」

# トンネリング？

学「ここまではわかりました。ところで先輩はマシンAで取った画像をマシンBで見れないとおっしゃってるのですが」
私「それだけだと何がいけないのかわからないけど、ネットワークプログラムがちゃんとできてないのか、さっきは難しくなるから略したけど、ファイアウォールがあってIPもしくはTCPレベルではねられているのか」
学「トンネリングがなんとかっておっしゃってたんですけど」
私「そっちの方。ふーむ、その話に進むと一段難しくなるわけだけど、具体的に何がしたいかにもよるし」

# 次回予告？

というわけでネットワークの基礎について対話形式（学生君の相づちや簡単な質問は省いているので大体私がしゃべっていますが）で説明してきました。
結局のところ学生君の聞きたかったのはややこしくなるから省いたプライベートネットワークとその接続のことのようです（まあそれを理解するための前提となる基本的な通信について説明したわけですが）。おそらく次週もやってくると思うのでそれを反映した各層の深掘りについて記事を上げる、かもしれません。
RubyMineでコミットメッセージだけをamendで修正する方法

## はじめに
Gitでは`--amend`オプションを使って直前のコミット内容やコミットメッセージを修正することができます。

```
# amendオプションを使って直前のコミットメッセージを修正する
git commit --amend -m "Fix bug"
```

RubyMineでもコミットダイアログに"Amend commit"オプションがあるので、これにチェックを入れれば直前のコミット内容を修正できます。
![Screen Shot 2018-10-13 at 8.53.53.png](https://qiita-image-store.s3.amazonaws.com/0/7465/6f63924f-fead-7771-afe6-6dad7446ffdb.png)

ただし、コミットダイアログを表示できるのは、ファイルに何か変更があった場合だけです。
単純に **コミットメッセージだけ** を修正したい場合はこの方法が使えません。

というわけで、この記事ではRubyMineでコミットメッセージだけをamendで修正する方法を紹介します。

### 対象バージョン

- RubyMine 2018.2.3

ただし、RubyMineだけでなく、IntelliJ IDEAやPhpStormなど、JetBrains社製のIDE全体で共通すると思います）。

## 手順

Command+9でVersion Controlペインを開く。
![Screen Shot 2018-10-13 at 8.37.39.png](https://qiita-image-store.s3.amazonaws.com/0/7465/15c5ffa8-1348-ba34-ad96-45f907931bd2.png)

Logタブを開く。
![Screen Shot 2018-10-13 at 8.37.48.png](https://qiita-image-store.s3.amazonaws.com/0/7465/e6b623a6-afed-1085-26ca-d33c041e6f8e.png)

メッセージを変更したいコミットを右クリックし、Rewordを選択する。
（ただし、すでにorigin等へpush済みのコミットはRewordを選択できない）
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f373436352f64626138336233662d663565322d373766662d383262612d3135653465323563383361612e706e67.png](https://qiita-image-store.s3.amazonaws.com/0/7465/9e9b7d25-2d13-afd4-2fc8-e715cbb91b53.png)


新しいメッセージを入力し、OKボタンをクリックする。
![Screen Shot 2018-10-13 at 8.43.39.png](https://qiita-image-store.s3.amazonaws.com/0/7465/43ecbb24-2e4a-62b6-bed3-9a961617e6c4.png)

手順は以上です！

## まとめ
僕はつい最近までこの方法を知らなくて、ターミナルから`git commit --amend -m "Fix bug"`のようなコマンドを入力していました。
僕と同じように、「IDE上でamendしたい！」と考えていた人は参考にしてやってください。

### 参考文献

- [RubyMine 2017\.2 EAP 3: Change Commit Messages \| RubyMine Blog](https://blog.jetbrains.com/ruby/2017/06/rubymine-2017-1-eap-3-change-commit-messages/)
- [pycharm \- Using IntelliJ to amend git commit message \- Stack Overflow](https://stackoverflow.com/questions/14075919/using-intellij-to-amend-git-commit-message)
Nginxで静的ページにPostすると405で取得できない場合の対処

# 課題(やりたいこと)
Nginxでメンテナンスモードで503を返すようにしたかった。Getリクエストであれば、503を返すことができるが、静的ページにPostリクエストすると405になってしまった(´; ω ;`)。これはNginxの仕様らしい...

# 実施方法
- `recursive_error_pages on`
  - nginxドキュメント
     - http://nginx.org/en/docs/http/ngx_http_core_module.html#recursive_error_pages 　
  - error_pageを使用して複数回リダイレクトさせることを有効とする
- 503の処理の中で405を静的ページに指定して静的ファイルにリダイレクトさせる

```
recursive_error_pages on;

  location @maintenance {
  if (-f $request_filename) {
     break;
  }
    error_page 405 = /maintenance.html;
    rewrite ^(.*)$ /maintenance.html break;
  }
```


- 検証で設定したconfファイルの全体

```
server {
	listen 80 default_server;
	listen [::]:80 default_server;

	root /var/www/html;
	index index.html index.htm index.nginx-debian.html;
	server_name localhost;
	error_page 503 @maintenance;

  recursive_error_pages on;
  if (-e /var/www/html/maintenance.html) {
        set $maintenance true;
  }
  if ($maintenance = true) {
        return 503;
  }

	location / {
		try_files $uri $uri/ =404;
	}

  location @maintenance {
  if (-f $request_filename) {
     break;
  }
    error_page 405 = /maintenance.html;
    rewrite ^(.*)$ /maintenance.html break;
  }
}
```


## 実行結果 ( 対策前 )
- `$ curl -X POST localhost -d id=hoge`

```
<html>
<head><title>405 Not Allowed</title></head>
<body bgcolor="white">
<center><h1>405 Not Allowed</h1></center>
<hr><center>nginx/1.14.0</center>
</body>
</html>
```

## 実行結果 ( 対策後 )
- `$ curl -X POST localhost -d id=hoge`

```
<html>
<p> This is Maintenance Page </p>
</html>
```

# 関連
- Nginxでメンテナンスページの設定をする
  - https://qiita.com/yhidetoshi/items/7314b944e1c4edd974db
[メモ] ラズパイとPiカメラにて、手間を掛けずに物体認識

RasPi3B+で、1fpsくらい
![image.png](https://qiita-image-store.s3.amazonaws.com/0/75594/1e109d82-ab5f-1718-539a-002d8c4c514f.png)
※ Youtubeにて、"スクランブル交差点" で検索。

# 概要
- **手間をかけずに**、ハヤり[^1]の物体認識したい.
- "*手間を掛けずに*" ...
	- OpenCV 3.3 以降で使える[DNN(=Deep Neural Networks, ディープ・ニューラル・ネットワーク)モジュール](https://docs.opencv.org/3.4.3/d2/d58/tutorial_table_of_content_dnn.html)を使用
	- RaspberryPi2/3向けビルド済み [OpenCV 3.4.3](https://github.com/mt08xx/files/raw/master/opencv-rpi/libopencv3_3.4.3-20180907.1_armhf.deb)使用
		- 関連:[ラズパイ3にOpenCV3を簡単に導入](https://qiita.com/mt08/items/e8e8e728cf106ac83218)
	- 学習済みモデルを使用
		- https://github.com/chuanqi305/MobileNet-SSD

		```py:20種類の物体
		classNames = { 0: 'background',
			1: 'aeroplane', 2: 'bicycle', 3: 'bird', 4: 'boat',
			5: 'bottle', 6: 'bus', 7: 'car', 8: 'cat', 9: 'chair',
			10: 'cow', 11: 'diningtable', 12: 'dog', 13: 'horse',
			14: 'motorbike', 15: 'person', 16: 'pottedplant',
			17: 'sheep', 18: 'sofa', 19: 'train', 20: 'tvmonitor' }
		```
- ちょっと試したいだけなのに、動かすまでの環境を立ち上げるのが、めんどう、という方に。


[^1]: 出遅れ感が...

# 環境

- RaspberryPi 3B /3B+ と PiCamera V2 <br>(カメラ有効化を忘れずに。`sudo raspi-config nonint do_camera 0`)
- Raspbian: [`2018-10-09-raspbian-stretch`](https://www.raspberrypi.org/downloads/raspbian/)



# TL;DR

```shell:Terminalを開いて以下こぴぺ(初回時)
# Raspbianのネットワーク設定・カメラ有効化などを済ませたら.
cd ${HOME} ; \
  git clone https://github.com/mt08xx/rpi-objdet.git ; \
  cd rpi-objdet ; \
  ./setup.sh ; \
  ./rpi-objdet.py
```


```shell:２回目以降はこちらで。
cd ${HOME}/rpi-objdet && ./rpi-objdet.py
```

# その他
- アンインストール<br>
`sudo apt autoremove -y --purge libopencv3 ; git clean -fdx`

- "馬" でぐーぐる画像検索<br>![image.png](https://qiita-image-store.s3.amazonaws.com/0/75594/a1a2b7dd-657b-16b5-0448-ce7925d2d690.png)

- ちなみに、PiZero + PiCamera 1.3 + RPi-Zero/1向けOpenCV 3.4.3 では、画像の認識に、15秒くらいかかりました。


<!--
# 手順
1. ラズパイ初期設定: Raspbian導入・システム設定・カメラ設定・確認
    - ラズパイ本体にカメラ接続 (ケーブルの向きを気をつける。金属むき出た端子が、microSD側を向く)
    - RaspbianをmicroSD焼いて、起動。
    - 初期設定
        - カメラを有効に
        - 無線使用の場合、ネットワークの設定
2. OpenCV 3.4.3導入

    ```shell:OpenCV3.4.3インストール
wget https://github.com/mt08xx/files/raw/master/opencv-rpi/libopencv3_3.4.3-20180907.1_armhf.deb
sudo apt install -y ./libopencv3_3.4.3-20180907.1_armhf.deb
sudo ldconfig
```

3. 学習済みモデルを入手

    ```shell:コピペ
cd ${HOME}
git clone https://github.com/chuanqi305/MobileNet-SSD
```

4. 以下コピペ
-->
jsdoでweb3.js その2

#概要

jsdoでweb3.jsやってみた。
remixやってみた。

#写真

![image](https://qiita-image-store.s3.amazonaws.com/0/18104/7dc870ae-e90b-c361-2d74-73cad6912960.png)


#成果物

http://jsdo.it/ohisama1/UwXH/fullscreen

以上。
CentOS7でResourceSpaceのインストールを行う

# ResouceSpaceとは

Digital Asset Management (DAM) のオープンソースソフトウェアです。
ライセンスはBSD Licenseを採用しています。

# 実行環境の構築

システム要件は以下URLに記載されております。
https://www.resourcespace.com/knowledge-base/systemadmin/general_requirements

今回の構築要件は以下になります。
- CentOS7.5
- Apache2.4
- PHP7.2
- MariaDB10.3
- ResourceSpace8.6

##### 1. EPELリポジトリを追加
```
yum install -y epel-release
```

##### 2. vimとnanoのインストール
```
yum install -y vim nano
```

##### 3. MariaDBのインストール

https://downloads.mariadb.org/mariadb/repositories/#mirror=yamagatauniversity&distro=CentOS&distro_release=centos7-amd64--centos7&version=10.3

```
vi /etc/yum.repos.d/MariaDB.repo
-------------------------
# MariaDB 10.3 CentOS repository list - created 2018-10-12 16:41 UTC
# http://downloads.mariadb.org/mariadb/repositories/
[mariadb]
name = MariaDB
baseurl = http://yum.mariadb.org/10.3/centos7-amd64
gpgkey=https://yum.mariadb.org/RPM-GPG-KEY-MariaDB
gpgcheck=1
-------------------------

yum install -y MariaDB-server MariaDB-client
```

##### 4. PHP7.2のインストール

```
yum install -y https://rpms.remirepo.net/enterprise/remi-release-7.rpm

vi /etc/yum.repos.d/remi-php72.repo
-------------------------
[remi-php72]
enabled=1 # 0→1に変更
-------------------------

yum install -y php php-gd php-mysqlnd php-mbstring php-opcache
```

##### 5. ImageMagickのインストール

```
yum install -y ImageMagick ImageMagick-devel
yum install -y php72-php-pecl-imagick
```

##### 6. ExifToolのインストール

```
yum install -y perl-Image-ExifTool
```


##### 7. popplerのインストール

```
yum install -y poppler
```

##### 8. FFmpegのインストール

```
yum install -y http://li.nux.ro/download/nux/dextop/el7/x86_64/nux-dextop-release-0-5.el7.nux.noarch.rpm
yum install -y ffmpeg ffmpeg-devel
```

##### 9. Subversionのインストール

```
yum install -y subversion
```

##### 10. ResourceSpaceの取得

```
mkdir /var/www/resourcespace/
cd /var/www/resourcespace/
svn checkout http://svn.resourcespace.com/svn/rs/releases/8.6/ .
mkdir filestore
chmod 777 filestore/ include/
chown -R apache: /var/www/resourcespace
restorecon -R ./*
```

##### 11. MariaDBにResourceSpaceのデータベースを作成

```
mysql -u root
-------------------------
create database `resoucespace`;
-------------------------
```

##### 12. Apacheの設定を追加

```
vi /etc/httpd/conf.d/resourcespace.conf
-------------------------
<VirtualHost _default_:80>
  ServerName localhost
  DocumentRoot /var/www/resourcespace/
  <Directory /var/www/resourcespace/>
    AllowOverride all
    Require all granted
  </Directory>
</VirtualHost>
-------------------------
```

##### 13. PHPの設定変更 (環境に合わせて修正)

```
vi /etc/php.ini
-------------------------
memory_limit = 1024M       # 128Mから1024M(1GB)に変更  ※ 200M以上が推奨
post_max_size = 512M       # 8Mから512Mに変更          ※ 100M以上が推奨
upload_max_filesize = 512M # 2Mから512Mに変更          ※ 100M以上が推奨
-------------------------
```

##### 14. Apacheの再起動

```
systemctl restart httpd.service
```

##### 15. ファイアウォールの通過設定

```
firewall-cmd --add-service=http --permanent
firewall-cmd --reload
```

以上で環境構築は終了です。
web.configを使って、別ドメインへリダイレクトさせる方法

# やりたいこと
開発中のテストアドレスを本番アドレスへリダイレクトさせる。
web.configを使うと結構簡単にできます。
正規表現でマッチさせるので、汎用性も高いですね。

```web.config
﻿<?xml version="1.0"?>
<configuration>
  <system.webServer>
    <rewrite>
      <rules>
        <rule name="sevengods-web" stopProcessing="true">
          <match url="(.*)" />
          <conditions>
            <add input="{HTTP_HOST}" pattern="^7test-web\.trafficmanager\.net$" />
          </conditions>
          <action type="Redirect" url="https://www.production-web.jp/{R:1}" redirectType="Permanent" />
        </rule>
      </rules>
    </rewrite>
  </system.webServer>
</configuration>
```
コマンドプロンプトで補完機能が効かない場合の対処[Windows 10]

先日Windowsのコマンドプロンプトで補完機能が効かなくなっていることに気付きました。
Googleで検索したところ、どうも[Gitツール](https://git-scm.com/downloads)をインストールする際に、[コマンドプロンプトをカスタマイズ指定でインストールしてしまったのが原因らしい](https://ameblo.jp/vsts/entry-12390667455.html)です（私自身、デフォルトではなく、カスタマイズ指定してインストールしたかは覚えていませんが、きっとカスタマイズ指定したのでしょう・・）。

#対処方法
レジストリエディタ（**regedit**）を起動します。

以下のレジストリ情報を探します。
**HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Command Processor**
![image.png](https://qiita-image-store.s3.amazonaws.com/0/100712/cb07e636-2d66-b7e5-b9d4-515a09b0676b.png)

**CompletionChar**と**PathCompletionChar**の値が**0x40**になっているのが問題のようで、***Tabキー***で補完するには**0x09**にする必要があるようです。

|キー名|現状の値|変更後の設定値|
|:--|:--|:--|
|CompletionChar|0x40|0x09|
|PathCompletionChar|0x40|0x09|

レジストリエディタを閉じて、コマンドプロンプトを再起動すると補完機能が効くようになりました。

#参考にさせて頂いたページ
[Windows10のコマンドプロンプトで ファイル名を補完する機能のキーをTABに戻そう@vstsさん](https://ameblo.jp/vsts/entry-12390667455.html)
Googleアカウント(Chrome)にGoogleアカウントのパスワードを保存した話

# 役に立つ（かも知れない）人

- **Google Chrome利用時に、Googleアカウントのパスワードを自動入力したい！**
- **Googleアカウントのパスワードを変更したので、Chromeに保存済みのパスワードを変更したい！**
- よその
 
# ぼくの経緯
Googleアカウントのパスワードを変更したけど、Chromeが自動入力してくれるのは変更前の古いパスワードのまま。
Googleにログインするたびに古いパスワードが自動入力されるので、いちいち消して書いてが面倒！

Chromeにログインしていれば、基本的なGoogle系サービスにはログイン状態になるので、普段は気にならないけど、
お仕事用の複数のGoogleアカウントを行き来するので、ログイン&ログアウトが多いのです。

変更後のGoogleアカウントのパスワードを、Chromeが自動入力してくれると便利！
古いパスワードが自動入力されるってことは、ChromeにGoogleアカウントのパスワードが保存できるってことだよね！

# 古いパスワード情報を何とかしよう！
そのへんのサイトであれば、変更後のパスワードでログインすると、Chromeは保存されているパスワードと違うパスワードを検知して、
「変更されたパスワードを保存しますか？」
的なダイアログが出て、新しいパスワードを保存し直してくれる。

なのでやってみる。

・ Googleアカウントからログアウト。
・ Googleアカウントにログイン。
・ パスワードを求められる。
・ 自動入力されてる古いパスワードを消して、今のパスワードを入力

**ログイン成功！**
でも、変更されたパスワードをどうこうするかのダイアログは出ない。

パスワードが変更されたことを検知できないのかな？

まずはスタンダードな解決法として、パスワードの変更ではなく、新規でパスワードを保存する流れをやってみる。

・ Googleアカウントに保存されてる古いパスワード情報を削除([https://passwords.google.com/](https://passwords.google.com/))
・ Googleアカウントからログアウト。
・ Googleアカウントにログイン。
・ パスワードを求められる。
・ 自動入力されてる古いパスワードを消して、今のパスワードを入力

**ログイン成功！**

こっちでも、このサイトのパスワードをどうこうするかのダイアログは出ない。

当然のことながら、ログインしようとするたびに、いちいち入力を求められるようになった…
![クリップボード111.png](https://qiita-image-store.s3.amazonaws.com/0/66548/2a8eca48-063f-511b-003a-2157f1385598.png)
古いパスワードが自動入力されるよりは手間は減ったけど、便利ではないよね。

#パスワード情報をインポートしちゃえ！
Google Chromeには、隠し機能としてパスワードを外部からインポートする機能がある。

普通にやっていると機能が非表示になっているので、Chromeのフラグをいじってみる。

Chromeの様々なフラグの設定場所
[chrome://flags/](chrome://flags/)
にて、パスワード関連のフラグを探して(Search flagsにpasswordとでも入れれば簡単)
・　Password import
をDefaultからEnableに変更。
![クリップボード03.png](https://qiita-image-store.s3.amazonaws.com/0/66548/db8d239d-accf-e61a-862b-1b91ab612515.png)
すると、Chromeの設定-パスワード([chrome://settings/passwords](chrome://settings/passwords))内の、
「保存したパスワード」の右にあるテンテン（・・・の縦のやつ）をクリックで、に「インポート」が出現するようになる。
![クリップボード04.png](https://qiita-image-store.s3.amazonaws.com/0/66548/7b6528ed-3f20-1163-2270-548d0fd6f324.png)

ひとまず、パスワードをエクスポートして、中を見てみると、
`name,url,username,password`
の形式のcsvで書かれているようなので、
`accounts.google.com,https://accounts.google.com/ServiceLogin,ユーザー名,パスワード`
`accounts.google.com,https://accounts.google.com/signin/v2/sl/pwd,ユーザー名,パスワード`
と記入し、インポートしてみる。

# できたよー
![クリップボード022.png](https://qiita-image-store.s3.amazonaws.com/0/66548/bcf64c3f-168d-b14d-eab3-c0919bf2f08a.png)
無事、ログイン時にパスワードが自動入力されるようになり、複数アカウントの行き来もだいぶ楽になりました。

# おわり
古いパスワードを設定したときは、ChromeにGoogleアカウントのパスワードを保存できたけど、
おそらく今はGoogleのポリシーが変わって、保存が出来なくなったんでしょうね。

明示的にログアウトしない限り自動ログインしっぱなしなので、不便さが増しただけにも感じますが、
「明示的にログアウトした」って所がポイントなのかなーとは思います。

ちなみに、自動入力できるようになっても、セキュアさが必要になるサービス（それこそGoogleアカウントでのパスワードの管理とか）では、
本人確認のためのパスワード入力は求められるので、そこは自動入力そのものが塞がれているようです。よかった。
iOS12のShortcutsで今日の金曜ロードショウを確認するショートカット作ってみた

#経緯
毎週見なくても、たまーに「今日はどんな~~ジブリ~~映画やってるかな？」って気になるのが金曜ロードショウ。
けどSiriに「今日の金曜ロードショウは？」って聞いても、Wikiのページしか教えてくれないという悲しい子ちゃんなので、ショートカットアプリを使って調教することにした。
とはいえあんまし時間かけたくないので風呂に入っている間でサクッと作ることにした。

#作成したショートカットのリンク
https://www.icloud.com/shortcuts/380a9b3fc8b54174884832973d2b4b06
こちら開いて取り込んでもらえれば使えるようになります。
基本的な使い方はその他サイトでご確認頂ければ、と。。

#呼び出す呪文
（結局Siriからはちゃんと動かなかったけど。。）
「ヘイSiri、今日の金曜ロードショウは？」
で呼び出す。

#結果
WEBサイトにのってる4週間先くらいまでの映画一覧がリスト表示されて、選択するとその詳細ページが開く。

#解説

1、まずURLを開いて内容を取得する。~~というかこれをブラウザで開くだけでいいんじゃないか。~~
2、そして結果をマークダウン形式に変換する。
3、「2018.XX.XX放送」と言うあたりに欲しい情報あるのでそれをマッチテキストで切り出す。ちなみに、Shortcutsの正規表現はICU Regexとか言うタイプらしく、^を使う場合には(?m)を頭に入れてあげないといけないそうな。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/116534/da161e5b-0b6a-1c4e-50e7-5bfea2beb2b4.png)

4、マッチテキスト結果に）が入ってしまうので削除。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/116534/4a5f49f7-f02b-0952-6885-361376d53b42.png)

5、改行を次の処理のために;;をデリミタとして置換。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/116534/719f1539-9e5c-77f2-e61f-86baf6c96f37.png)

6、この後のリスト選択とグループ取得の時に便利なように並べ替え＆見た目の整形。（空白がたくさんあるのは、まぁ苦肉の策です）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/116534/3347adcc-9c9c-7660-fa8e-28cf4a6d473e.png)

7、一見謎ですが、これでグループ分けをしております。と言うか、イマイチ意味不明なんだけど、このマッチテキスト処理では結果の選択肢ダイアログが勝手に出てくる。3のところのマッチテキストでは出てこないのに。。ここが一番よくわからない。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/116534/77b129dd-a0e7-fdcb-8d5c-fafaf6e62990.png)

8、7で選んだ選択肢のグループ2、つまりアドレスを取得して、それをURLに入れる。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/116534/94c0cf40-872f-baef-4287-60a3d1ff9af4.png)

9、あとはサファリで開いて終わり。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/116534/45809c23-ebb9-e624-0015-ea76edcff3cd.png)

#よくわからなかった点、イケテナイ点
 - グループと辞書とリストがなんかごちゃごちゃしてしまったので、とりあえずゴリ押しで実装した。その内気が向いたらちゃんと取り組んでみる。
 - 7のダイアログはSiriから動かした時には出てこない。なので、処理で失敗するけど、どう扱って良いかわからない。
 - そもそもAppleのShortcutsのガイドが結構ざっくりとしていて、Regexの件とか全然出てこない。Workflowの時から思ってたけど、これコード書きなれてない＆英語リソース探せない人にはトコトン使いこなすの無理だろ。。
 - Siriから動かした時に（そもそもURL開くのに時間がかかるので）処理が止まっているのか分からない。プログレスバー欲しい。
 - ~~というかやっぱり単純にURL開くだけで良いんじゃないか。。~~
 - ~~というか最初の1個だけにすればSiriからもちゃんと開くんじゃないか。。~~
 


#面白かった点
 - とはいえ、SSHでリモートのシェル動かしたりできるとか、JSONいじれるとか頑張れば色々出来そう。もう少し何で使えるか考えてみよう。

以上です。
Slack — 新しいチャンネルを探す時にクイックスイッチャーを使ってはいけない (注意喚起)

# クイックスイッチャー

クイックスイッチャー「参加していないチャンネル一覧も」出てくるのだが、かなり数が少ないことに今日気付いて驚愕した。

社内で趣味系のチャンネルがたくさんあるのだが、いつも「気になるものがないな」と思って、すぐにスイッチャーを閉じていた。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/9bcfe2a1-ab00-fb45-d6ad-98bc7f5afbf9.png)

ヒット数は今数えてみると20個ぐらい。

改めてカウントしてみると、会社の規模からいってそんなに少ないはずはないのだ。

# Brows All Channels

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/54fecf64-c02a-fc28-a427-c5b541f8e622.png)


![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/8cdb95aa-8442-aa80-6960-a68ab5d0dfe2.png)

ヒット数を数えると160個ぐらい。

## うそ‥だろ‥

なんと140個ほどのチャンネルを見逃していた‥！！！！！

自分が真面目にチャンネルを探していなかったのもあるけれど、ここまでの取りこぼしをしているとは。

# Brows All Channels のショートカットは？

割り当てられていないかもしれない。開くのが大変だ。Slackはチャンネル数が膨大になってくると、新規チャンネル探訪が難しい仕組みみたいだ。少なくとも通常UIからは。

## ヘルプにもそんなこと書いてない

「不参加チャンネルも検索できるんだ」と思ったら「全ての不参加チャンネルが見つかるんだろうな」と思うじゃないですか。そうじゃないですか。

[クイックスイッチャーの使い方 – Slack](https://get.slack.help/hc/ja/articles/226599368-%E3%82%AF%E3%82%A4%E3%83%83%E3%82%AF%E3%82%B9%E3%82%A4%E3%83%83%E3%83%81%E3%83%A3%E3%83%BC%E3%81%AE%E4%BD%BF%E3%81%84%E6%96%B9-)

## これは不注意なのだろか？

そうだ。

だがこれは同時に「不注意なユーザーは気づけないUI」になっているということだ。

## 環境

- Macアプリ 3.3.2

![image.png](https://qiita-image-store.s3.amazonaws.com/0/89618/65fb8423-206a-b908-fdd6-d195dd3fca16.png)








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
テキストベースで画面遷移図が書けるuiflowをブラウザ上で動かす

# ウェブ上で動くようにした
### uiflow-web

[とりあえず使ってみる](https://ytoune.github.io/uiflow-web/)
[ソースコードを見る](https://github.com/ytoune/uiflow-web/)

みんな画面遷移図を描こう。

# 経緯
[もう保守されない画面遷移図は嫌なので、UI Flow図を簡単にマークダウンぽく書くエディタ作った](http://qiita.com/hirokidaichi/items/ff54a968bdd7bcc50d42)
上記のツールは良さそうだったがインストールが面倒だった。

# 大変だったこと

`node` の `fs` や `util` などへのアクセスを無効化やモックを割り当てるのに苦労した。
最終的には下記のようになった。

```js:webpack.prod.jsより抜粋
{
	/* 省略 */
	node: {
		fs: 'empty',
		child_process: 'empty',
		// util は npm install --save util した
	},
	resolve: {
		alias: {
			// png 対応をあきらめているため使わない
			'spawn-stream': 'node-libs-browser/mock/empty',
		},
	},
	/* 省略 */
}
```