OmniAICreator/Qiita-1.07M huggingface dataset:
Re:dashのAPI（検索/登録/編集/更新）をPHPでたたく


# 概要

PHPクライアントでググってみると一応あるにはあるがメンテされてないっぽいし、使いたいAPIについて機能がなかったので（登録、更新系のAPI）、自作してみた備忘録。

資料がほとんどなかったので、直接コードを読んだりしました。  
以下から追う。  
https://github.com/getredash/redash/blob/8b73a2b135aed8fcbca139380a959b9222ae0080/redash/handlers/api.py#L40

参考： https://qiita.com/ubonsa/items/9a7f4f1d020af88d70c4

## 追記

適当にまとめて公開しました。

https://github.com/sakatuki/redash-api-cli

composerから使えます。

```
# install
composer.json

{
	"require": {
		"sakatuki/redash-api-cli": "dev-master"
	}
}

# how to use
$queryId = 1;
$redashApiCli = new RedashApiClient(
    'https://your-redash',
    'your api key'
);
$apiQueries =  new RedashApiQueries($redashApiCli);
$data = $apiQueries->getQuery($queryId);
```

## 注意
以下で記しているのは実際に利用したコードではなく、そこから抽出したものなので、実行してみたらエラー出たりするかも。大筋では間違ってないので勘弁して。

## 利用してみるAPI
* GET : /api/queries/search
* POST: /api/queries
* POST: /api/queries/{query_id}
* POST: /api/queries/{query_id}/refresh

## 必要なもの
* API Key
* PHP環境
* めげない心

# 認証編

API Keyやら実行環境やらを用意したらあとはコードを書くだけ！

認証には、getパラメータにapi_keyを含める方法と、リクエストヘッダに含める方法があるようです。

getパラメータに含める方は、単にapi_keyとして送ればok。  
リクエストヘッダに入れて送る方法を調べてみると、サンプルコードは見つかったけど公式のドキュメントっぽいのがなかった。直接コードを読んだら以下のように送ればいいらしい。

```php
$client = new \GuzzleHttp\Client(
    [
        'base_uri' => 'http://your-redash.jp/api/queries',
        'headers' =>[
            'Authorization' => 'Key yourapikey',
        ]
    ]
);
// 検索api
$client->get('/api/queries/search', [
    'query' => [
        'q' => 'hello wolod'
    ]
]);
```

# 検索編 - /api/queries/search

検索はqに検索したい文字列を入れれば良いよう。name（クエリタイトル）から検索してくれる。

```php
$response = $client->get('/api/queries/search', [
    'query' => [
        'q' => 'hello wolod'
    ]
]);
// 中身はjson
echo $response->getBody();
```

# 登録編 - /api/queries

登録には/api/queriesへPOSTで送る。ちなみにこのapiにGETで送ると、閲覧できるクエリが全部返ってくるっぽい。

```php
$response = $client->post('/api/queries', [
    'json' => [
        'name'  => 'hello wolod',
        'query' => 'select * from test',
        'data_source_id' => 1, // データソースのid
        'description' => 'クエリの説明',
        'schedule' => '12:00' // UTCで解釈され、ユーザーのTimeZoneで変換される
    ]
]);
// jsonで登録内容が返ってくる
echo $response->getBody();
```

ドキュメントがなかったのでわからないが、登録する際に他の内容も入れられるかも。ただis_draft（publishでないかどうか）のフラグだけは、固定でtrue（not publish）になるようだった。

# 編集 - /api/queries/{query_id}
内容の更新は上記へpostで送る。getで送ると単にクエリの内容が、deleteで送るとアーカイブされるっぽい。  

`4/9追記` : deleteメソッドで送ってみても、削除されなかった。削除したい時は、is_archivedをtrueで更新すれば削除される。 

やりたかったのはpublish状態にすること（is_draft=falseの状態）。queryも更新できる。

```php
$response = $client->post('/api/queries/' . $queryId, [
    'json' => [
        'id'  => $queryId,
        'query' => 'select * from test2',
        'is_draft' => false,
    ]
]);
// jsonで登録内容が帰ってくる
echo $response->getBody();
```

# リフレッシュ（クエリの実行） - /api/queries/{query_id}/refresh
```php
$response = $client->post('/api/queries/' . $queryId . '/refresh', [
    'json' => [
        'id'  => $queryId
    ]
]);
// jsonで登録内容が帰ってくる
echo $response->getBody();
```

# まとめ

頑張ればコードから仕様を追える。最終的には、Redashのページを操作したときに出てくるリクエストを追うのが早かった（Redashの各操作はAPIを通して行われているようなので）。

ただレスポンスやリクエストが不明瞭なのがすごい辛い。ドキュメント欲しい。

そのうちその他のAPIもまとめて、composerで使える形にしてgithubにあげたい。
ターミナルを同時に複数tab開いてコマンド実行させたい

# Web開発がだるい...

最近nodeベースのweb開発をしているのですが、
その中で
1. **webpack動かして**
2. **server.js動かして**
3. **proxyサーバー動かして**
4. **ngrok起動して**
をする必要があり、いちいちterminalで新しいtabを開いて
コマンドを実行させていました。

## ttab
これは流石にだるいのでなんとかならないかと探していたらnpmでありました
[ttab](https://www.npmjs.com/package/ttab)

```
ttab npm run client
ttab npm run server
ttab npm run proxy
ttab ngrok (略)

```
これでバッチリです:relaxed:
OSのパッケージをリストアップしたい！【Fish編】

Atomでは`apm list --installed --bare`コマンドを使うことで、現在使用している拡張機能のリストアップができます。
これをなんとかOSのパッケージマネージャーでも再現できないかな、という試みです。
必要なパッケージの吟味、再セットアップ用のバックアップなんかにきっと役立つと思います。

## 方針
リスト化する際はコマンドで入力したものだけを出力します。
依存パッケージはとくに知る必要がありませんし、眺めるにしても邪魔でしかありません。見るにも使うにも便利なものが欲しいんです。

さて、そうなると出力までの流れはこんな感じになりそうです。

> 1. fish_historyを見る
> 2. インストールコマンドとアンインストールコマンドを抽出
> 3. 現在使っているパッケージ名だけを残して出力

うーん、シンプル。すばらしい。
ただbashと違ってコマンドの抽出と加工にちょっと手間がかかります。しかたないね。

## やってみよう
まずはリソースとなるfish_historyを見てみましょう。

たとえばAntergos(マネージャーは`yaourt`)におけるfish_historyの中身はこんな感じ。
fish_historyは`$HOME/.local/share/fish`もしくは`$XDG_DATA_HOME/fish`の中にあります。

````fish_history(抜粋)
- cmd: yaourt -S vim
  when: 1511092067
- cmd: vim --version 
  when: 1511092088
- cmd: type git
  when: 1511092110
- cmd: yaourt -Ss git
  when: 1511092132
````

こいつを以下のような関数で処理すれば、うまくリスト化できそうです。

```fish:yaourt_file.fish
function yaourt_file
    # 1. fish_historyを探す
    set -l history_dir "$HOME/.local/share/fish"
    set -q XDG_DATA_HOME
        and test -d $XDG_DATA_HOME
        and set history_path "$XDG_DATA_HOME/fish"
    set -l history "$history_path/fish_history"
    if test ! -f $history
        echo "Error: fish_historyが見つかりませんでした。"
        return 128
    end

    # 2. コマンドを抽出する
    set -l commands (cat $history \
                        | grep -E "^- cmd: yaourt ((-S)|(-R)) " \
                         # 置換に使う文字をスペースにしてエラー回避
                        | sed -e 's/[\\\\|\/]/ /g' \
                         # コマンドの簡略化。手順3で使いやすいように
                        | sed -e "s/- cmd: yaourt -S /<S> /g" \
                        | sed -e "s/- cmd: yaourt -R /<R> /g")

    # 3. 現在インストールされているパッケージのみを抽出
    set -l result "|"
    set -l is_install_command 1
    for i in (string split " " $commands)
        switch $i
            case <S>
            set is_install_command 0
            case <R>
                set is_install_command 1
            case "" "-*"
                # 空行もしくはオプションなので無視
            case "*"
                if test $is_install_command -eq 0
                    if string match "*|$i|*" $result > /dev/null
                        # すでに追加済みのパッケージなので無視
                    else
                        # パッケージ名を確認
                        # 正しい名前ならリストに追加
                        yaourt -Q $i > /dev/null
                        and set result "$result$i|"
                    end
                else
                    set result (string replace -a "|$i|" '|')
                end
        end 
    end

    # リスト形式で出力
    test $result = "|"
        and echo "Notice: 該当するパッケージはありませんでした。"
        or  string trim -c "|" $result | string split "|"
end

```

実際にやってみるとこんな感じ。

<!-- 本来はfishターミナルだけど未対応なのでbashを使う -->
```bash:Terminal

$ yaourt_file
gvim
clang
python-pip
python2-pip
tig
stack
nim
ruby
julia

(以下略) 

```

これを使って再インストールするときはこんな風に。

```fish:yaourt_unfile.fish
function yaourt_unfile
    set -l list (yaourt_file | string join " ")
    eval "yaourt -S $list"
end
```

以上、ニッチすぎる内容ですが、ぜひお試しあれ。

## パッケージにしました
上記処理を汎用的に使えるようにした[lpkg](https://github.com/rkbk60/lpkg)というパッケージを作りました。ついでに再インストール用のコマンドも付けてます。
興味のある方はぜひご利用くださいませ。

```bash
# fishermanでインストールするなら
$ fisher rkbk60/lpkg
```
Rails チュートリアル メモ 第1章

# チュートリアルページ

* https://railstutorial.jp/chapters/beginning?version=5.1

# 必要だったライブラリ

各種 Gem をインストールする前に

* readline-devel
* sqlite-devel

の2つが必要だった。
環境によって違うと思うが、エラーメッセージに大抵ちゃんと書いてあるので、それを見て足りないものを適宜入れれば OK。

# rails new 時に Gem がグローバルインストールされないようにする

チュートリアルに沿って無邪気に `rails new` すると、プロジェクトのデフォルト Gem (Puma とか) がグローバル領域にごっそりインストールされる。できればプロジェクトの vendor 配下に入れたい。

そこで、`rails new` 時に `bundle install` を実行しないようにして、パスを指定しつつ手で `bundle install` する。

```bash
gem install rails -v 5.1.4
rails new hello_app --skip-bundle
cd hello_app
bundle install --path vendor/bundle
```

あるいは、そもそも rails をプロジェクトディレクトリ内にインストールしてもよい。こうすれば、プロジェクトごとに異なるバージョンの rails を使うことができる。ただし `rails` コマンドの前に `bundle exec` が必要になる。

```bash
mkdir hello_app
cd    hello_app

bundle init
echo "gem 'rails', '~> 5.1.4'" >> Gemfile

bundle install --path vendor/bundle
bundle exec rails new .
```

# うっかり pg gem の追加を忘れて git push heroku すると若干面倒なことになる

Gemfile に pg Gem を使う旨を書かずに heroku にデプロイすると、 https://qiita.com/taumu/items/b09ec1afd7a3b9c0edbf と同じエラーが起きる。

上記リンク先では設定変更で対応しているが、一度 heroku 上でアプリを消して、Gemfile の修正をコミットしてからデプロイすると、database.yml を変えなくても正常に動作する。なぜ database.yml を変えなくても正常に動作するのかは、https://qiita.com/youmts/items/39c3f4f8106c0968d57e が詳しい。
s3cmdでS3に差分だけアップする

動的ファイル以外を基本的にS3で管理することになったので覚書。
※AWS CLIのほうが転送速度が速い。どうしてもs3cmd使いたいなら。

####s3cmdをインストール

```
yum -y --enablerepo epel install s3cmd
``` 

####AWSアクセスキーの取得
AWSマネージメントコンソールのIAMの認証情報からアクセスキーを作成、取得する。

####s3cmdでアクセスキーとシークレットアクセスキーの設定

```

$ s3cmd --configure
Access Key: aaabbbccc
Secret Key: dddeeefff
``` 
※サーバーのユーザ単位でconfigは作られるので実際にshellを実行するユーザで作る。
その後の質問については無視しても問題ない。細かい調整もできる。

####ためしにS3バケットが取得できるかテスト

```
$ s3cmd ls
2018-02-08 02:52  s3://aaa
2018-02-08 02:55  s3://bbb
```

####shellスクリプト準備

```shell

#!/bin/sh

s3cmd sync --dry-run --no-preserve --no-check-md5 --no-mime-magic --guess-mime-type --acl-public --encoding=utf-8 --exclude-from=[exclude-file-path] [from-path] s3://aaa/

answer=$1

if [ "$answer" = "-y" ]; then
    answer="y"
else
    echo -n "are you sure you wanna release S3? [y/n]"
    read answer
fi

if [ "$answer" = "y" ]; then
    s3cmd sync --no-preserve --no-check-md5 --no-mime-magic --guess-mime-type --acl-public --encoding=utf-8 --exclude-from=[exclude-file-path] [from-path] s3://aaa/
fi

```

上記はfrom-pathからバケットaaaに対し、exclude-file-pathのファイルを除外しつつ、syncする例。
はじめにdry-runが走るので、アップされる予定のファイル一覧が表示される。

####実行

```
$ /bin/bash deploy_s3.sh 
exclude: index.php
exclude: bbb.html
upload: aaa.html
are you sure you wanna release S3? [y/n]
```

除外されるファイルはexcludeというprefixが付く。
ここでyを選択すると想いがS3に届くよ。
Webページ全体のScreenShot画像を１行で取得するDockerコンテナ

はじめに
=======
縦長のWebPageのスクリーンショット画像を取るのは実は地味に面倒です。phantomjsがそれをサポートしていたのですが、最近どうもメンテナンス終了になっているので、急ぎではないですが別の手段を模索する必要があります。

と言っている間に、必要が生まれてChrome Headlessで地道にScreenshot画像を取得することができるようになったので、その部分だけを切り出したDockerコンテナを公開したので共有します。

必要な環境
--------
以下の環境で動作を確認しています。 

* macOS High Sierra 0.13.3
* Docker Community Edition Version 18.03.0-ce-mac59

確認はしていませんが、Windowsでも動くと思います。

使い方
=====
Windowsの場合は、 \`pwd\` の部分を画像を出力したいフォルダーに置き換えてください。

PCっぽい画面のScreenshotをとる場合
-----------

```bash
docker run -v `pwd`:/tmp/screenshot mokemokechicken/capture_web "https://www.yahoo.co.jp/" yahoo_pc.png
```

<img height="300" src="https://qiita-image-store.s3.amazonaws.com/0/11124/1599fbf3-efe6-951e-1849-d78e58c92aa7.png">

click すると拡大します。

iPhoneっぽい画面のScreenshotをとる場合
----------
```bash
docker run -v `pwd`:/tmp/screenshot mokemokechicken/capture_web "https://www.yahoo.co.jp/" yahoo_sp.png -w 414x735 --ua 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1'
```
<img height="300" src="https://qiita-image-store.s3.amazonaws.com/0/11124/c04f4ea5-75af-a24a-368d-e195c36e7813.png">

click すると拡大します。

ソース
======
https://github.com/mokemokechicken/docker_capture_web

Chrome Extensionの [Full Page Screen Capture](https://github.com/mrcoles/full-page-screen-capture-chrome-extension) の JS部分を参考に作っています。

仕組み
--------
WebPageの下から順番に、キャプチャ画像を取得して、大きなCanvasにペタペタ貼っていきます。
なので、固定ヘッダーは大丈夫なのですが、固定フッターとか、動きがあるWebPageはやはり上手くは取得できないです。

まあ、そういう需要が出たら、今回のをちょいちょいいじればなんとかならないこともないでしょう。

さいごに
======

何かのお役に立てば。
正規表現を使った金額のカンマ編集の解読

どうも、超スーパー初心者ビギナーエンジニアだよ。
何回解読しても毎回忘れてしまうのでここに書くことにしたよ。

カーソルを外したときに金額にカンマがつくようにしたい！と思ったときにググると出てくるアレ。

```
amountStr.replace( /(\d)(?=(\d\d\d)+(?!\d))/g, '$1,');

```

いや、なんでよ。
なんでこれで3桁毎ににカンマつくのよ。?! じゃないよ、こっちが「！？」だよ。
というわけで解読していくよ。

#  正規表現
ここでは実際にここで出てくる正規表現しか出さないので注意してね。

正規表現では、パターンの各要素を 1 対の区切り記号で囲むよ。
JScript では、1 対のスラッシュ文字 (/) を区切り記号として使用するよ。
つまりは、正規表現を使用するときは / で囲んでねってことみたい。
## (~~)
~~と一致した文字列を記憶するよ。\$1,$2…に順番に代入されていくみたいだよ。
## \d
任意の10進文字と一致。[0-9] と同じ意味らしいよ。
yyyyMMddって書いてあったら、なんとなく「日付の並び、20180330って並びなんだろうな」って思うよね。
そんな感じで\d\d\dって書いてあったら、「3文字の数値が並んでいるんだろうな」って思えればいいかな？
## ?=
後ろに指定した文字列が続く場合に一致と見なされるらしいよ。
## +
直前のサブ式と1回以上一致するよ。
## ?!
後ろに指定した文字列が続かない場合に一致と見なされるらしいよ。
## g
正規表現の後の g はグローバルサーチを行うオプション/フラグで、全体の文字列を見てすべてのマッチを返すらしいよ。
gをつけないと最初の1回で処理を終えちゃうよ。
## '$1,'
(~~)で保存した文字列だよ。

# 解読するぞ！

まずはstr.replace(A,B)だよ。
「strにAがあったらBに変えるよ」ということだから、
「amountStrっていう文字列の中に、/(\d)(?=(\d\d\d)+(?!\d))/g ってのがあったら、'$1,'に書き換えるよ！」という意味だね。
 
次に/~~/gだよ。
正規表現を使うときは / で囲む！
正規表現のあとの g はマッチしなくなるまで繰り返すよ！ってことだね。

いよいよ正規表現使用箇所だよ。
落ち着いて少しずつ行こう。~~そうしないと僕が分からないから。~~

まずはこいつだよ。
(\d)
1文字の数字だよ！終わり。簡単だね！

次はこいつだよ。
(?=(\d\d\d)+(?!\d))

ハイ分かんなーい。なのでもっと分割するよ。
?=(\d\d\d)
+
(?!\d)

一個ずつ見ていくよ。

?=(\d\d\d)
?= は「後ろに指定した文字列が続く場合一致」ってヤツ。
後ろの文字の \d\d\d は3文字の数字って意味だね。
つまり、「後ろに3文字の数字が出た時に一致」ってことだね。

次いこう！
+
+は直前のサブ式と1回以上一致するよってヤツ。
つまり、さっきのと合わせると
?=(\d\d\d)+
で「後ろに3文字の数字が1回以上出た時に一致」ってことだね。

次！
(?!\d)
?! は「後ろに指定した文字列が続かない場合に一致」ってヤツ。
後ろの文字の \d は1文字の数字って意味だね。
つまり、「後ろに数字が続かなかったときに一致」ってことだね。

さっきのと合わせると
?=(\d\d\d)+(?!\d)
で「後ろに3文字の数字が1回以上出て、後ろに数字が続かなかったときに一致」ってことだね。

正規表現のところを全部くっつけて
/(\d)(?=(\d\d\d)+(?!\d))/
で
「(数字)(後ろに3文字の数字が1回以上出て、後ろに数字が続かなかったところ)」ってことだね！

最後に全部くっつけて！
str.replace( /(\d)(?=(\d\d\d)+(?!\d))/g, '\$1,')
で
「(数字)(後ろに3文字の数字が1回以上出て、後ろに数字が続かなかったところ)となるところを '$1,' に変えます！！！」
ってことだね！
解読完了！おめでとう僕。

#実際に処理を確認
数字の文字列 12345678 で考えてみよう。ゴールは 12,345,678

1文字目の1が(\d)(?=(\d\d\d)+(?!\d))の最初の(\d)だとして考えると
1     \d
234 \d\d\d
567 \d\d\d (「＋」で説明した通り3文字の数字は何回出てもいい。)
8    後ろが\d(数字)になってしまった！
これは条件に適さないのでreplaceしないよ。次いこう。

2文字目の2が(\d)(?=(\d\d\d)+(?!\d))の最初の(\d)だとして考えると
2        \d
345     \d\d\d
678     \d\d\d
(なし)  後ろが\d(数字)ではない！
これは条件に適してるね！さあreplaceしよう！
$1は最初の(\d)だから2だね！'2'を'2,'に置き換えよう。
すると、
12345678 → 12,345678
ようやく変換できたよ！

でもまだ終わらないよ。
何故なら該当するところは全て置き換えるって /~~/g が言ってるから。

3文字目の3が(\d)(?=(\d\d\d)+(?!\d))の最初の(\d)だとして考えると
3     \d
456 \d\d\d
78    後ろが\d(数字)
条件を満たさない！次！

4文字目の4が(\d)(?=(\d\d\d)+(?!\d))の最初の(\d)だとして考えると
4    \d
567 \d\d\d
8    後ろが\d(数字)
次次！

5文字目の5が(\d)(?=(\d\d\d)+(?!\d))の最初の(\d)だとして考えると
5         \d
678     \d\d\d
(空白)  後ろが\d(数字)じゃない！
条件を満たす！
$1は最初の(\d)だから5！'5'を'5,'に変換！
12,345678 → 12,345,678

6,7,8の後ろには3桁の数字が出ないので省略！

できた～～～～！無事12345678を12,345,678に変換できたね！
解読はできたけど、自分でこういうの作れる人ってヤバいなあ……。
rails scaffoldで作成したcontrollerに独自のactionを追加する場合の注意

# scaffold
```
$ rails g scaffold hoge a:integer b:string c:integer
```
上記のようなコマンドで基本的なMVCをまとめて作ってくれてありがたいのですが、初心者が故にこれで躓くことがあったので共有します。

# controllerにactionを追加するとエラーが発生
上記のコマンドで作成したモデルのcontrollerに独自のアクションを追加したところ、そのアクションにアクセスするところでエラーが出た。

1. ルートの宣言を忘れている場合。
2. ルートの宣言はしっかりしている場合。

私の場合は2のパターンだったため混乱しました。
scaffoldで作成すると、　以下のように`resources:`でルートが定義されます。

```route.rb
resources :hoge
```
この`hoge`モデルに`detail`というアクションを自分で追加した場合に私は思考停止で適当に以下のように書いていました。

```route.rb
resources :hoge
get 'hoge/detail'
```
そしてブラウザからアクセスすると、以下のようなエラーが発生し頭を抱えます。

```
ActiveRecord::RecordNotFound in MessagesController#show
Couldn't find Message with 'id'=detail
```
これが解決できなかったので（ググっても躓いている人すらいない笑）デフォルトのアクションを改造したりして逃げていたのですが、なんとか解決しました。
```route.rb
get 'hoge/detail'
resources :hoge
```
独自のアクションは`resource`より上に書かないといけないらしいです。これだけ。

# あとがき
普通なら躓くところではないかもしれませんが、　`route.rb`が複雑になっているとこういう部分を見落としたりするので今回気づけてよかったです。
Qiita初めた

#はじめまして
　snamonといいます。
　思い切ってQiita始めました。

##経歴のようなもの
　・インフラエンジニアとして3年目
　・ネットワーク(L2,L3)領域しか知らない。
　・最近pythonの資格をとって興味津々
　・サーバのことはよくわかってない
　・Ansibleにちょっと触ったことがある
　・自動化ってワードにあこがれる24歳


##はじめた目的
今後積極的に身に着けたい「自動化」についての記録残し&アウトプットの場所
ほぼ自分のため(アウトプット大事)


時間をみつけて細々と投稿していきます！
phpで先月頭の日付を取得する

# 気づき

毎年3月30日、31日に起こる問題で、

```php
echo date("Y-m-d", strtotime("- 1 month"));
```

と書くと、3月30日だと"2018-03-01 00:00:00"が返ってくる。

# 解決

```php
// 上記のまま実行すると、たぶん年に2日しか再現しないので日付指定で。
echo date("Y-m-01", strtotime("2018/03/30 - 1 month")); // "2018-03-01"

// 3月30日　- 30日　= 2月末の日付
echo date("Y-m-01", strtotime("2018/03/30 -" . date('d') . " day")); // "2018-02-01"
```

実際のコードは

```php
echo date("Y-m-d", strtotime("-" . date('d') . " day"));
```

なんでいまさらこんなの書いてるんだろうって思ってたら、今までは

```php
echo date("Y-m-01", strtotime(date('Y-m-01') . " - 1 day"));
```

って書いてた気がする。こっちのほうがわかりやすいなー
pm2で環境変数の変更が反映されない時の解決策

## 問題
pm2を用いてnode.jsのアプリを管理している場合、外部で環境変数を変更した際に、そのアプリ側では変更が反映されないことがあります。
私の場合、パソコンを再起動すらしても反映されず、弱りました。

## 解決策
そんなときは、`--update-env` を付けてアプリを再起動すればOKです。

```bash
$ pm2 restart 0 --update-env
```

上記は再起動するアプリのIDが0である場合です。
ちなみに、アプリのIDは下記で確認することができます。

```bash
$ pm2 list
```

## 参考
http://pm2.keymetrics.io/docs/usage/environment/
Rails Deviseのルートを最小限コードでわかりやすくする。

デフォルトでは、

```ruby:routes.rb
devise_for :users
```

パスは、

                  Prefix Verb   URI Pattern                    Controller#Action
        new_user_session GET    /users/sign_in(.:format)       devise/sessions#new
            user_session POST   /users/sign_in(.:format)       devise/sessions#create
    destroy_user_session DELETE /users/sign_out(.:format)      devise/sessions#destroy
       new_user_password GET    /users/password/new(.:format)  devise/passwords#new
      edit_user_password GET    /users/password/edit(.:format) devise/passwords#edit
           user_password PATCH  /users/password(.:format)      devise/passwords#update
                         PUT    /users/password(.:format)      devise/passwords#update
                         POST   /users/password(.:format)      devise/passwords#create
cancel_user_registration GET    /users/cancel(.:format)        devise/registrations#cancel
   new_user_registration GET    /users/sign_up(.:format)       devise/registrations#new
  edit_user_registration GET    /users/edit(.:format)          devise/registrations#edit
       user_registration PATCH  /users(.:format)               devise/registrations#update
                         PUT    /users(.:format)               devise/registrations#update
                         DELETE /users(.:format)               devise/registrations#destroy
                         POST   /users(.:format)               devise/registrations#create


こう変更。

```ruby:routes.rb
  devise_for :users,
         path: '',
         path_names: {sign_in: 'login', sign_out: 'logout', edit: 'profile', sign_up: 'registration'},
         controllers: {registrations: 'registrations'}

```


                  Prefix Verb   URI Pattern              Controller#Action
        new_user_session GET    /login(.:format)         devise/sessions#new
            user_session POST   /login(.:format)         devise/sessions#create
    destroy_user_session DELETE /logout(.:format)        devise/sessions#destroy
       new_user_password GET    /password/new(.:format)  devise/passwords#new
      edit_user_password GET    /password/edit(.:format) devise/passwords#edit
           user_password PATCH  /password(.:format)      devise/passwords#update
                         PUT    /password(.:format)      devise/passwords#update
                         POST   /password(.:format)      devise/passwords#create
cancel_user_registration GET    /cancel(.:format)        registrations#cancel
   new_user_registration GET    /registration(.:format)  registrations#new
  edit_user_registration GET    /profile(.:format)       registrations#edit
       user_registration PATCH  /                        registrations#update
                         PUT    /                        registrations#update
                         DELETE /                        registrations#destroy
                         POST   /                        registrations#create


スッキリ。
QiChatの使い所（2）

　本記事は以下の環境で動作を確認しています。

| |バージョン|
|:---|:---|
|NAOqi|2.5.5.5|
|Choregraphe|2.5.5.5|
----

# この記事の内容
　前回の記事『[QiChatの使い所（1）](https://qiita.com/Atelier-Akihabara/items/75a825c729dabf72f235)』では、ロボアプリを構成する特徴的な技術
としてChoregrapheダイアグラム、Python、QiChat、ALMemoryを紹介し、QiChatからChoregrapheダイアグラムを結びつける方法を紹介しました。今回はQiChatからNAOqi APIやALMemoryの使い方を結びつける方法を紹介したいと思います。

# APIを直接コールする
　QiChat関数で`^run`や`^start`を使いモーションが定義されているビヘイビアを実行させることができました。会話の進行に合わせたモーション制御ができました。ですが、モーションではなく、個別のAPIの呼び出しを会話の進行と共にできたら便利なはずです。
　QiChatの関数を使えばそんなことができてしまいます。

## QiChat関数 `^call`, `^pCall`
　QiChat関数 `^call`と`^pCall`はNAOqi APIを実行します。

**構文：**

```
^call(<NAOqiModule>.<Method>(<Params>))
^pCall(<NAOqiModule>.<Method>(<Params>))
```
　QiChat関数`^run`と`^start`のようにこちらも働きは同じで、非同期か同期かの違いになります。

|QiChat関数|処理内容の詳細|
|:--|:--|
|^call|同期処理。呼び出しAPIの終了を待ち後続処理が実行される。|
|^pCall|非同期処理。呼び出しAPIの終了を待たないで後続処理が実行される。|

　いくつか実際のAPIを実行させて動作を確認してみたいと思います。ALMemoryにデータを書き込んで見たいと思います。

```
u:(メモリに書き込んで) 書き込みます！ ^call(ALMemory.insertData("TestApp/TestKey", "TestData")) テストデータを書き込みました！
```

　上記のコードは、利用者の「メモリに書き込んで」との呼びかけにPepperが「書き込みます」と反応しAPIを呼び出し、書き込み完了後Pepperが「テストデータを書き込みました」と反応します。

**実行結果：**
![qichat-fig-1.png](https://qiita-image-store.s3.amazonaws.com/0/54394/d1327f02-3d40-e690-71c6-afdfc09bb615.png)

　QiChatから直接APIが実行され、ALMemory上にデータが書き込まれていることが確認できます。
　QiChatからPython側から処理を行うようなAPIコールが実現できますね。

# ALMemoyとの繋がり
　実は上記のような方法を行なわなくてもQiChat側からALMemoryを利用できます。今度はALMemoryへの書き込みを`^call`を使わずにQiChat変数`$`から行いたいと思います。

## QiChat変数 `$` 書き込み
　構文を説明する前に以下のコードを見てください。データが正しく書き込まれているか確認するため書き込む内容を”TestData2”とします。

```
u:(メモリに書き込んで) 書き込みます！ $TestApp/TestKey="TestData2" テストデータを書き込みました！
```

**実行結果：**
![qichat-fig-2.png](https://qiita-image-store.s3.amazonaws.com/0/54394/e517ce2a-8b07-1a2e-a20b-7ec4c79fe81c.png)

　API呼び出しのQiChat関数`^call`を使わなくても$だけでALMemoryにデータが書き込まれていることが確認できました。
　つまりここでのQiChatでいう変数はALMemory変数と結びついているということになります。

## QiChat変数 `$` 読み込み
　実は、このQiChatの`$`はデータの読み込みも行えるのです。QiChatスクリプトを以下のように書き換えます。

```
u:(メモリに書き込んで) 書き込みます！ $TestApp/TestKey="TestData2" テストデータを書き込みました！
$TestApp/TestKey
```

![qichat-fig-3.png](https://qiita-image-store.s3.amazonaws.com/0/54394/42369d80-1945-0af7-b033-c10bc7b1a505.png)

　書き込んだ"TestData2"が発話されています。
　書き込みだけでなく読み込みに関してもALMemoryと結びついていることが確認できました。

　Pepperに発話させるのではなく、QiChat変数`$`の値を関数呼び出しと組み合わせて使えるか試してみましょう。

```
u:(メモリに書き込んで) 書き込みます！ $TestApp/TestKey="TestData2" テストデータを書き込みました！
^call(ALMemory.insertData("TestApp/TestKey3", $TestApp/TestKey))
```

　こちらも変数"TestApp/TestKey3"に値"TestData2"が書き込まれていることが確認できます。

## 構文
　QiChatの変数構文をまとめると以下のようになります。

||構文|
|:--|:--|
|書き込み|`<ALMemoryKey> = <Data>` |
|読み込み|`<ALMemoryKey>`|

# まとめ
　いかがでしょうか。QiChat通して会話のみならず、Pythonで処理するようなAPI呼び出しやALMemoryの書き込み・読み込みができ、ロボアプリを構成する特徴的な技術を結びつける方法が理解いただけれたと思います。
Elasticsearchで簡単なアナライザを設定して日本語検索できるようにするまでの流れ

jupyter で動かした後、小分けにして頑張ってMDで書いてたんだけど、
gist に notebook をそのまま貼れることを知って衝撃を受けた。


[livedoor グルメの研究用データセット](https://github.com/livedoor/datasets) の中の ratings.csv のユーザーレビューを、
Elasticsearchに簡単なアナライザを設定して投入、検索できるようにするところまで。

https://gist.github.com/arc279/36535d8c2fa2dd3a429e4441cf58fb0d

Elasticsearchはdockerで立ててるので、動かす場合は `docker-compose up` してください。
QiChatの使い所（1）

　本記事は以下の環境で動作を確認しています。

| |バージョン|
|:---|:---|
|NAOqi|2.5.5.5|
|Choregraphe|2.5.5.5|
----

# この記事の内容
　Pepperの会話アプリには欠かせないQiChatの進んだ使い方を紹介したいと思います。QiChatはダイアグラムベースでは複雑になりがちな会話の分岐を、シンプルに記述する専用言語です。また、会話だけでなくアプリの制御も可能です。

# ロボアプリの特徴的な技術
　ロボアプリを構成する特徴的な技術には以下のものがあります。

+ Choregrapheダイアグラム
+ QiChat
+ Python
+ ALMemory

　Choregrapheダイアグラムはロボアプリの構成要素を束ねるプログラムそのものであり、ビヘイビアと呼ばれます。PythonやQiChatはそれらに関連づけられて処理されるプログラムです。Pythonは主にAPIの呼び出しや一般的な制御を担当し、QiChatは主に会話の制御を担当します。ALMemoryはロボアプリやNAOqiOS間でデータのやりとりを行う、データベースになります。

　QiChatは主に会話の制御を担当しますと述べましたが、会話だけでは片手落ちです。QiChatは会話と連動したロボアプリの制御を円滑にするための機能が備わっています。
　始めにQiChatからChoregrapheダイアグラム（モーション）の呼び出し方を紹介したいと思います。

# 会話と連動したモーション
　会話とモーションを連動させるには、QiChat関数`^run`や`^start`や`^wait`を使います。

## QiChat関数 `^run`, `^start`
　QiChat関数`^run`と`^start`はモーションが設定されたビヘイビアを実行させます。ビヘイビアの指定は`^run(<ビヘイビアパス>)`の形式で行います。ビヘイビアの名前だけでなく<ApplicationID>を含めた形になることに注意してください。

**構文：**

```
^run(<ApplicationID>/<BehaviorName>)
^start(<ApplicationID>/<BehaviorName>)
```
　`^run`と`^start`の違いは、同期か非同期かの違いになります。

|QiChat関数|処理内容の詳細|
|:--|:--|
|^run|同期処理。ビヘイビアの終了を待ち後続処理が実行される。|
|^start|非同期処理。ビヘイビアの終了を待たないで後続処理が実行される。|

## QiChat関数 `^wait`
　QiChat関数 `^wait`は`^start`で非同期実行されたビヘイビアの終了を待ちます。終了を待つビヘイビアは^startで指定した場合と同様です。わかりにくいと思いますので、ビヘイビアパスを`test-appid/behavior_1`とした場合の使い方の例を示します。`test-appid/behavior_1`は体を動かす動作が設定されているビヘイビアです。

```
Pepperです ^start(test-appid/behavior_1) 体を動かします ^wait(test-appid/behavior_1) 体を動かしました
```

　上記の場合、「Pepperです」とPepeprが発話し体を動かすモーション`test-appid/behavior_1`が実行されます。「体を動かします」とPepperが発話し、 `^wait(test-appid/behavior_1)`で体を動かすモーション`test-appid/behavior_1`の終了を待ち、最後に「体を動かしました」と発話します。

　これで会話とモーションを結びつけることができました。ロボアプリの可能性が広がりますね。ですが、QiChatの使い所はこれだけではありません。[次回](https://qiita.com/Atelier-Akihabara/items/52c3927b91f60a68d0fd)は、さらに進んだ内容を紹介したいと思います。
OracleMasterBronze SQL(1z0-017) を受験した


# 背景

自分のスキルアップを目指して取得する資格を探すなかで、
先輩のススメもあり「Oracle Master Bronze」を取得することにしました。
※Oracle Master Bronzeの概要は[こちら](http://oraclemaster.info/28/)をご覧ください。

そして先日無事に合格することができました。
新卒文系エンジニアがIT業界のことすらわからない中で取得してみて感じたことを受験記的に書いてみたいと思います。
問題の解説とかよりも心構え的な内容ですのでご了承ください。

# 受験概要

* 勉強期間： 約1ヶ月 (約80時間くらい)
* 獲得点数： 75%    (合格ライン: 75%)
* 事前知識： ほぼゼロ (文系でIT業界に入り現在1年目です)
* 使用教材：

1. Bronze 11g SQL基礎Ⅰ　完全詳解＋精選問題集(白本)
1. [めざせオラクルマスター](http://oraclemaster.info/exercise/)
1. [@IT](http://www.atmarkit.co.jp/ait/articles/0505/12/news124.html)

# 勉強方法

前提としてOracleに触ったことすらなければ、
データベースのこともよくわからないという方に向けて書いています。

## 4週間前~2週間前

### 実際に触ってみる
まずはOracle問わずなにかしらのDBに触れてみることから始めました。
PostgreSQLやSQL Serverを業務で使用していたので開発環境で実際に使用されているSELECT文等をコソコソみていました。
Oracleの試験といえど、Bronze程度では仕様の違いに苦しむ問題は殆どないとどこかで読んだ気がするからです。

正直Oracle受けるんだからOracleを触りたいと思いながらチラ見していましたが、
今となっては知識ゼロのクリーンな状態から雑食的に知識を入れていくことに抵抗を感じる必要性はエンジニアという職業においてはないと感じております。

そしてこの試験はSQLに対する理解を測る試験ですので、構造的な部分は気にしない方がよかったです。
GUIを触ればテーブルを開いてSQLを打ち込む前に、ビュー?シノニム?なんて疑問はたくさん生まれたのですが、わからないことを無理して読み解こうとするよりも今わかることを広げていく方が良い気がします。

### テキストを使用する
テキストを使用した勉強ですが、まずは白本を読み込んでいきました。
試験は1z0-017ですが、古い試験のため参考書がありませんでした。
9iの試験内容を踏襲したもののためです。

11gの参考書は1z0-017を包括していますので、
なにかしらの教材を使用する場合は、11gのものを選べば間違いないようです。

読み込んでいくわけですが、1,2日で読み終えられるわけではないので、
1週間かけて1周目、4日かけて2周目、2日かけて3周目、1日かけて4周目と区切った上で、
更に2日かけて1~n章...と細かく区切っていくことをお勧めします。
「あ、ここわかるから軽めでいいかな」とか私たち素人にはありません。

なにより社会人になり時間を確保することが難しくもなるので、
細かく計画を立てておけば万が一急用によって遅れが出ても取り戻せます。

## 2週間前~1週間前

### 問題を解く
白本の解読と業務の合間の触ってみる時間に注力すると、
中々実際の問題を解く時間がないのでここで集中的に問題に慣れていきました。

繰り返し解きすぎると問題を覚えてしまって効果が、、、
なんて心配もしましたが、問題に対する慣れが必要ですね。受験を思い出しました。

4択問題ではないこと、言葉の使い回しなど、
問題を理解しながら繰り返し繰り返し解いていきました。
とはいえ慣れすぎて反射的にしか答えられないとなってはいざ本番の時に困ってしまうので、
この時に、[めざせオラクルマスター](http://oraclemaster.info/exercise/)等の出題サイトにお世話になりました。

## 1週間前~本番

### 知識の補填をする
この期間は仕上げです。
白本しか殆ど使わなかった状況で、[@IT](http://www.atmarkit.co.jp/ait/articles/0505/12/news124.html)などに入っていくと知識が線で繋がっていくような気がして気持ちが良かったです。
基本的に終盤は知識に対する枠組みを外して柔軟に理解を広げることが大切だったと思います。


# 感想
知識ゼロで勉強する足がかりがほしいという状況で受けました。
正直言ってまだまだ業務で活用できるかといえば怪しいですが、まずは合格して一安心です。

個人的には、

* 1z0-017の教材がほとんど無い中でどういう切り分けで教材を使いこなすか
* 覚える量が膨大な中でどれだけ勉強時間の確保をできるか

この二点が上手くいったのではないかと考えております。


# 最後に試験というか受験する上でのポイント
* 1z0-051の試験よりはだいぶ易しいので、やはり1z0-017を受験することをオススメ。
* めざせオラクルマスターや白本問題の応用が多いので暗記するだけでは難しい。
* 会場で受けたほうがオンラインで受けたときよりも簡単(らしい)
* ビアゾンVUEの公式でチケットを買うより楽天で購入したほうが2,000円は安くなる(後から知る)
homesteadでPHPのバージョン指定が効かない

# 現象

Homestead.yamlでPHPのバーション指定しても
デフォルトのバージョンになってしまう

```ruby:Homestead.yaml
    - map: xxx.test
      to: /home/vagrant/code/xxx/html
      php: "5.6"
```

URLからxxx.testを開いて`phpinfo();` を表示させると
デフォルトの`PHP7.1`が表示されてしまう

なんで？

公式に書いてある通りにやったはずなのに・・・
https://readouble.com/laravel/5.4/ja/homestead.html


# 原因
１日かけて、英語のサイトも目がつるぐらい探しても見当たらず、
諦めかけた時に、ふとバージョンが気になった（いや、アドバイスをもらった）

WINDOWSではPHPバージョンの切り替えはできたのに
MACだけでできないっておかしくないか？

は？もしかしてバージョンが違うんじゃ？？？

調べた結果

| WINDOWS       　　　　　　| MAC | 
|:-----------------|:------------------|
| laravel/homestead (virtualbox, 5.0.1)|laravel/homestead (virtualbox, 5.2.0)|
| Vagrant 2.0.1          | Vagrant 2.0.3 |
| Laravel Homestead 7.0.1             |  Laravel Homestead 5.4.0 |

どう考えてもHomesteadのバージョンおかしいやろ
でも、公式に書かれたままやっただけやのに・・・

```ruby:
// クローンしたいリリースバージョン
git checkout v5.4.0`
```

これが同じページに書かれてるから混乱するねん

```ruby:
Homestead6から、同一仮想マシン上での複数PHPバージョンをサポートを開始しました。
Homestead.yamlファイルで、特定のサイトでどのバージョンのPHPを使用するのかを指定できます。
利用できるPHPバージョンは、"5.6"、"7.0"、"7.1"です。
```

でHomesteadのバージョンってどこで分かるねん？
って調べたらまさかのファイルを直接テキストで見るなんてびっくりや

`/Users/*username*/Homestead/bin/homestead`

```ruby:
$app = new Symfony\Component\Console\Application('Laravel Homestead', '5.4.0');
```

# 対応

ボックス入れるところからやり直しや

```ruby:
/ boxの削除 /
vagrant box remove **** 

/ boxの追加（バージョン指定） /
vagrant box add laravel/homestead --box-version 5.0.1

/ ディレクトリ移動 /
cd ~

/ 前の関係ファイルを削除（隠しファイルも含めて） /
/Users/*username*/Homestead　
をディレクトリごと削除

/ Homesteadをclone /
git clone https://github.com/laravel/homestead.git Homestead

/ 移動 /
cd Homestead

/ クローンしたいリリースバージョン /
git checkout v7.0.1

/ Homestead.yaml生成 /
bash init.sh

/ Homestead.yaml編集 /
    - map: xxx.test
      to: /home/vagrant/code/xxx/html
      php: "5.6"

/ homesteadのstatusを確認 /
vagrant global-status

/ 前のやつが残ってるのでIDを指定して削除　/
vagrant destroy xxxxxx

/ virtualboxを確認 /
vboxmanage list vms

/ 前のやつを掴んでるので削除 /
VirtualBox.app起動してhomestead-7を除去

/ ようやく起動 /
vagrant up
```

ここまでやってxxx.testを見たら、無事PHPバージョン指定が5.6になってた！！！

こういう細かいトラブルシューティングがなかなかズバリ見つからんからめっちゃ時間かかったわ
RailsアプリではJWTをcookie管理するしかない！！

## 発端
- JWTログインを、Railsで実装したかった（Gemは[jwt/ruby-jwt
](https://github.com/jwt/ruby-jwt)を利用）
- ペイロードを基にしたトークン発行まではできた（記事がたくさん書いてある）
- RFCを見ると、トークンはリクエストヘッダーの`Authorization`の`Bearer`スキーマに入れるのがお決まりらしい
- じゃあどうやって認証サーバから受け取ったトークンをリクエストヘッダに入れるのかな........ん？
- **入れ方がどこにも書いてない**
- **みんなトークン作った後はなぜかcurlで確認だけして文章終了してる**

```
$ curl example.com -H 'Authorization: Bearer <token>'
```
- **これをアプリでやりたいんだっちゅうに！！**
- **なんで誰もWebアプリでの実装方法書いてないの？？**
- （某有名プロジェクトに関わっている人）「**RailsじゃAuthorizationヘッダーに入れるの無理だよ**」
- **？！？！**

## 結論
- もうでていますが、Railsのロジック上、**受け取ったJWTトークンを`Authorization`ヘッダに入れてリクエストを飛ばすといったオシャレなことはできません**
- なので、**おとなしく`Cookie`に入れてそこで管理しましょう**
- ただ**セキュリティ対策として、`secure属性`と`httponly属性`はつけておきましょう！**

```rb
# bundle install
gem 'jwt'
```
```rb
# lib/json_web_token.rb（config/application.rbでlib配下をautoloadするようにしてください）
class JsonWebToken
  class << self
    def encode(payload, exp = 24.hours.from_now)
      payload[:exp] = exp.to_i
      JWT.encode(payload, secret)
    end
    
    def decode(token)
      body = JWT.decode(token, secret)[0]
      HashWithIndifferentAccess.new body
    end
    
    private
    
    def secret
      Rails.application.secrets.secret_key_base
    end
  end
end
```

```rb
# ApplicationController内でincludeしてください
module SessionHelper
  def current_user
    if (token = cookies[:jwt])
      decoded = JsonWebToken.decode(token)
      @current_user ||= User.find_by(id: decoded[:id])
    end
  rescue JWT::ExpiredSignature
    flash[:danger] = 'Token Expired'
    log_out
    @current_user = nil
    nil
  end
  
  def logged_in?
    current_user.present?
  end
  
  # before_actionでログインしていないと入れないページに設定
  def authenticate_user?
    redirect_to login_path unless logged_in?
  end
  
  def log_in(user)
    payload = { id: user.id }
    token = JsonWebToken.encode(payload)
    # もしhttps通信なら、secure属性もOnにすること
    cookies.permanent[:jwt] = { value: token, httponly: true }
  end
  
  def log_out
    cookies.delete(:jwt)
  end
end
```

- 「そんなことはない（RailsでもAuthorizationヘッダー使えるよ）」というお方、**是非とも反論してください！論破してください！お願いします！！**
言語選定とかしてみる

# 言語選定資料

## 目次

- [判断基準](#判断基準)
- 言語別
  - [Java/Kotlin](#javakotlin)
  - [Ruby](#ruby)
  - [Node.js](#nodejs)
  - [Go](#go)
- [まとめ](#まとめ)

## 判断基準

- BtoB等でのパッケージ提供時の考慮
  - コンパイル言語
  - マルチプラットフォーム

- 採用の為 (分母の多さ) 
  - ユーザー数

- 保守性 
  - コンパイル言語(コンパイルエラー判断)
  - OS依存度(rubyならOSにmysql入れないとライブラリ入れても動かないとか)
  - let などの再代入が不可能機能ありか
  - 言語のformatの自由度 (Pythonがうるさいみたいな) 
  - テスト、コードフォーマットはどれも入れる前提だが言語固有があれば◯という感じ
  
- 求められるセキュリティ基準実装?
  - 金融系とか　行政で採用されているか？

## Java/Kotlin

- オブジェクト指向・構造化・手続き型  
- 強い静的型付け
- コンパイラ言語、並列プログラミング

### メリット
- 人が多い！
- ライブラリはダントツ。
- 日本語の資料も多い。（調査時間少なくすむ）
- Androidエンジニアのデフォ言語
- 銀行系のシステムやら業務系システムでの実績の多さからセキュリティ面での実装対応も調べやすい
- web, batch共に多くの実績あり。
- ライブラリなどもOS側に依存が少ない
- version更新時に下位versionの互換には優れてる。
- コードを渡さずある程度まとめたjarで提供できる。

### デメリット
- 人が多いけど、スキルが低い人もめちゃ多い。
- 言語の仕様がかなりoldで縛られている。Kotlinで少し解消
- 古い印象はどうしようもない。

## Ruby

- 構造化、命令型、オブジェクト指向  
- 強い動的型付け

### メリット
- 人が多い！
- 日本発祥言語
- 日本語の資料も多い。（調査時間少なくすむ）
- Webアプリでは定番のRailsあり。ただフルスタックフレームワークだけど。
- ベンチャー採用に多い

### デメリット
- 人が多いけど、こちらも人が増えすぎて練度はバラバラ
- 言語の仕様の更新も激しいけどその分、versionアップがシビア。古いのは基本推奨されない
- OS依存が多いのでインフラも考慮。mysql等も基本osに入れないといけない。
- パッケージ提供時にはコードまるみえ。
- batch系の処理は少ないイメージ。主にweb系

## Node.js

- イベント駆動型プログラミング環境  
- altJSの選定を再度必要。 
  - TypeScript (静的型付けをしたいとき)
  - CoffeeScript
  - ES7なのかとか (まーデフォがこの基準でES5はなし)

※ 色々ライブラリを取り入れる事により書き方は異なる。

### メリット
- ブロックチェーン業界だと関連ライブラリ多し。
- frontと同じJavascriptで書ける。
- front側エンジニアだとそもそも開発時のツールとして必須
- ベンチャー採用増えてきてる。

### デメリット
- 現状人が集まらない。
- ES6から大きな変更がありversionの更新が激しい
- パッケージ提供時にはコードまるみえ 
- altJS等を入れるとやはりコンパイルが発生して遅かった。(TypeScript初期で導入経験あり。)

## Go

- 強い静的型付け
- コンパイラ言語、並列プログラミング

間違ってたらごめん。軽くは読んでる

### メリット
- ブロックチェーン業界だと関連ライブラリ多し。(gethがGoでの実装)
- 個人的には新しい言語でありモダンな言語という印象
- testやfmtなど言語レベルで用意。（他言語にも同様にあるがfmtはたぶんこいつが初かと）
- Pythonとかの影響か書き方に統一性がある。言語の書き方に縛りあり。
- ベンチャー採用増えてきてる。

### デメリット
- たぶん同様に人が少ない。
- コンパイルして納品可能なはず。 
- 今までと違いクラスとかの概念がなく言語の設計思想がだいぶ異なる。

## 参考URL
- [プログラミング言語の人気 2017/05](https://qiita.com/ty-edelweiss/items/b8172c2e22726bc08aeb)
- [Qiita Advent Calendar 2017ランキング](https://qiita.com/advent-calendar/2017/ranking/subscriptions)

## まとめ

個人的には言語の批判はないです。あくまでお硬い物を作る前提なので。
NodeやRubyは手軽に作るプロトタイプやサービスの初期開発などには
手軽に使えていいと思っています。  


下記は簡易ながら独断で表にしてます。

|言語 |ユーザー数 |pkg販売 |メンテナンス度 |セキュリティ面 |ドキュメント量 |
|:---|:-:|:-:|:-:|:-:|:-:|
|Java |◎ |◎ |◯ |◎ |◎ |
|Ruby |◯ |△ |△ |△ |◎ |
|Node |△ |△ |△ |△ |◯ |
|Go   |△ |◯ |◯ |◯ |△ |


## 2018/04/13 現在
そもそも今の時代にjarで固めてサービス提供ってのは古いと認識 
SaaSという選択肢を入れてコンパイルする事はpkg販売っていう項目は不要にしました 
Kotlinかなって思ったがGoの可能性とかGoのtest/fmtの用意は 
言い換えればgithubの他者のコードの可読性も高いと判断してます。 
java等でのレガシーコードの記事のフィルタ等も考えるとGoの将来性にかけるかと思います。
Ethereum(Geth)でwallet notify(のようなもの)を実現する


gethにはbitcoindのようにwallet notifyが実装されていません。
その代わりに、WebsocketによるPub/Subでトランザクションを受信できる仕組みが用意されています。

[RPC PUB SUB](https://github.com/ethereum/go-ethereum/wiki/RPC-PUB-SUB)
[https://github.com/ethereum/go-ethereum/wiki/RPC-PUB-SUB](https://github.com/ethereum/go-ethereum/wiki/RPC-PUB-SUB)

gethにWeboscketで接続して、"newPendingTransactions"の購読メッセージを送信すると、
Pending状態のトランザクションがプッシュされてきます。

#手順

### 1.起動時にWebsocketを有効にする

gethの起動時に、Websocketを有効にする為のオプションを指定する必要があります。
https://github.com/ethereum/go-ethereum/wiki/Command-Line-Options

例) ```geth --ws --wsaddr="127.0.0.1" --wsport "8546" --wsorigins "*"```

### 2.Websocketサーバに接続してnewPendingTransactionsの購読メッセージを送信する

1でWebsocketを有効にしたら、そこに接続して以下のJson形式の購読メッセージを送信して、トランザクションの受信を開始します。

```
{
    "id": 1,
    "method": "eth_subscribe",
    "params": [
        "newPendingTransactions"
    ]
}
```

購読に成功すると、以下のメッセージが返ってきます。

```
{
    "jsonrpc": "2.0",
    "id": 2,
    "result": "0xc3b33aa549fb9a60e95d21862596617c"
}
```

resultのハッシュはパブリッシュされてきたメッセージを識別する為に使用するので、保持しておきます。

購読を開始すると、以下のJson形式のメッセージがパブリッシュされてきます。

```
{
    "jsonrpc": "2.0",
    "method": "eth_subscription",
    "params": {
        "subscription": "0xc3b33aa549fb9a60e95d21862596617c",
        "result": "0xd6fdc5cc41a9959e922f30cb772a9aef46f4daea279307bc5f7024edc4ccd7fa"
    }
}
```

メッセージ中のparamsのsubscriptionが、購読した時のレスポンスのresultフィールドと同じハッシュになります。
購読できるメッセージの種類はnewPendingTransactions以外にも幾つかありますが、パブリッシュされてきたメッセージの中には、
それがどのメッセージなのかを直接に表すフィールはありません。
なので、subscriptionのハッシュをチェックして、どのメッセージかを判定する必要があります。

paramsのresultが目当てのトランザクションのハッシュになります。このハッシュを引数にeth.getTransaction()を呼び出せば、トランザクションの詳細が取得できます。後は、トランザクションの詳細を元にアプリケーションの処理をすれば、walletnotifyと同等のことが実現できると思います。

注意しないといけない点としては、パブリッシュされてくるトランザクションのハッシュをフィルターする手段がないということです。
自ノード以外の管理していないアカウントのトランザクションもパブリッシュされてきます。
なのでそのトランザクションが自分が管理しているウォレットのアドレス宛のものなのかどうかを判定する為には、
全てのハッシュに対して、eth.getTransaction()をする必要があります。

Livenetで数十件/秒がパブリッシュされてきますので、データベース等に保存した方が良いと思います。
Json-RPCで短期間に大量にeth.getTransaction()を発行すると、RPCがエラーを返すことがあるので、
適切な負荷になるように調整する必要があると思います。

また、稀に同じトランザクションがパブリッシュされてくることがありますので、そこもケアする必要があります。

動作確認で使用したサンプルを貼り付けておきます。
https://gist.github.com/myaaaaa-chan/4c75f112c32bbee6bb410036dd839cb8
Tampermonkey で作成したソースの実ファイルの場所

FireFox が Quantum になってから、Greasemonkey から Tampermonkey に乗り換えて簡単なソースコードの動作を試していました。

ただ、Tampermonkey はブラウザ上のエディタでソースを直さないといけない。Greasemonkey みたいに、作ったソースコードも普段使っているエディタで直したりしたいと思って、実ファイルを探しました。

(使用環境 Windows7 + FireFox)
結論からいうと、FireFoxのプロファイル配下の以下にファイルを見つけました。
<pre>
browser-extension-data\firefox@tampermonkey.net\storage.js
</pre>

こちらに全ソースの情報を一括で持っていました。個別にファイルとして保存しておいてほしかった..。
Swift4のExclusive Access to Memory問題

Swift2.x系で書かれていた既存のプロジェクトをSwift4へとコンバートしていたら、

```swift
var flag = true
    
func action(_ flag: inout Bool, completion: () -> Void) {
    flag = !flag
    completion()
}

action(&flag) {
    log.debug(flag) // ここでクラッシュ
}
```

というようなコードで

```console
Simultaneous accesses to ~, but modification requires exclusive access.
Previous access (a modification) started at ~.
```

というメッセージが出てクラッシュするようになりました。

どうやらSwift4ではメモリへの排他アクセスが強制されるようになり、
`inout`なパラメータに渡したポインタを中から参照しようとすると
同じメモリへの同時アクセスとみなされクラッシュしていた模様。

# 回避策

`TARGETS -> Build Settings -> Swift Compiler - Code Generation`
の
`Exclusive Access to Memory`
を
`Full Enforcement (Run-time Checks in Debug Builds Only)`
から
`No Enforcement`
に変更するとクラッシュしなくなります。

本当は同時アクセスにならないようにコード自体を見直す必要がありますが、
古いSwiftからのコンバートという点を鑑みた結果、上記の対応でお茶を濁すことにしました(

Swift4で新規アプリを開発する際はしっかり上記を意識した実装をする必要がありますね。

# 参考
[Conflicting Access to In-Out Parameters](https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/MemorySafety.html#//apple_ref/doc/uid/TP40014097-CH46-ID571)
[Enforce Exclusive Access to Memory](https://github.com/apple/swift-evolution/blob/master/proposals/0176-enforce-exclusive-access-to-memory.md)
git push エラー　Git RPC failed; HTTP 501 curl 22 requested URL returned error: 501 Not Implemented

#Git RPC failed; HTTP 501 curl 22 requested URL returned error: 501 Not Implemented
git push したらこんなエラーがでた

```

Counting objects: 8, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (8/8), done.
efatal: The remote end hung up unexpectedly
rror: RPC failed; HTTP 501 curl 22 The requested URL returned error: 501 Not Imp
lemented
Writing objects: 100% (8/8), 3.11 MiB | 0 bytes/s, done.
Total 8 (delta 0), reused 0 (delta 0)
fatal: The remote end hung up unexpectedly
Everything up-to-date
```

# 解決方法
以下、ように.gitconfigに書き込んだら解決しました。

```.gitconfig
.
.
.
[http]
        postBuffer = 500M
```

`git config http.postBuffer 524288000`
上記コマンドを打ってもでも解決できるようです。

[参考サイト](https://confluence.atlassian.com/fishkb/git-push-results-in-rpc-failed-result-22-http-code-411-298979775.html)
トレーサビリティを確保した仕様書作成をサポートするソフト(1)

#開発の目的
仕様書とか設計書とか書くのはいいんだけど、
開発が進むとソースコードやテストとの整合性が取れなくなってくる気がする。
何とか整合性を保ったまま開発を進められないだろうか。
ちょっと探してみたけど、マッチしそうなソフトはない。(または高そう)
いろいろやりたいこともあるので自分で開発してみようと思った。

#やりたいこと
1.仕様と設計の関係を明確にできるような仕組み
　要求→要件→設計の流れが追えること
2.要求、要件、設計を変更したときに、関連する要素がわかること。できれば自動で変更に追従すること。
3.基本的にテキスト編集だけど、画像や、ファイルも関連付けできること
4.変更が履歴管理できること
5.データをテキスト、excel、wordで出力できること

#開発環境・言語
新しいのに挑戦しようかなと思ったけど、
使い慣れてるMFCを採用。なので自動的にVisualStudio。
excelとかそのあたりはC#が便利っぽいからDLLとかで分離しとけば楽かな？

まぁまぁなんとなくこんな感じ。
まだ思いついただけで実行に移してないので続きはまた今度。
PetaLinuxを使ってみるメモ

試行錯誤も含めて書くので途中は間違った作業である可能性があります。

参考：
https://www.muo.jp/2017/01/petalinux-microzed.html
http://dora.bk.tsukuba.ac.jp/~takeuchi/?%E9%9B%BB%E6%B0%97%E5%9B%9E%E8%B7%AF%2Fzynq%2FPetalinux%20%E3%81%AE%E3%83%93%E3%83%AB%E3%83%89


1.ここからPetaLinuxのインストーラをダウンロードする。
https://japan.xilinx.com/products/design-tools/embedded-software/petalinux-sdk.html
MicroZedを使うときは2017.2じゃないとだめらしい。
なんのかんのと登録とかデータ入力を求められる。間違いや記入漏れがあると全部やり直しになる。
サイズは結構でかい。7Gぐらいある？

2.置く
windowsでダウンロードして、VM上のUbuntu(16.04 LTS 64bit版)に渡す。
VMで共有フォルダを作っておいたのでそこから。

```　
sudo mount vboxsf ubuntu_share /mnt
cd /mnt
```
3.下準備

```
sudo apt-get install bc lib32ncurses5 lib32tinfo5
```
と、してみたけどなんか失敗…

```
sudo apt-get update
```
してみるも失敗。
https://qiita.com/showsuzu/items/9ee031208d38ff8ac889
https://qiita.com/mrtry/items/99e2f912da4be2f8f48f
これらを参考にしてapt-getのproxy設定を追加。

4.インストール

```
./petalinux-v2017.2-final-installer.run
```
時間かかるっぽい。チェックサムの計算とかしてる。
途中で怒られて中断。
https://www.xilinx.com/support/documentation/sw_manuals/xilinx2017_3/ug1144-petalinux-tools-reference-guide.pdf#nameddest=PetaLinuxToolsInstallationSteps
(いまさら)ドキュメントを読む…

```
mkdir -p /opt/pkg/petalinux
./petalinux-v2017.3-final-installer.run /opt/pkg/petalinux
```

こうらしい。
インストールが進むと、途中でライセンスのテキストを読まされる。
:qとかで戻ろうとすると、Enterを押したときに次のY/NがNで実行されてしまって
インストールが中断してしまう。説明文にあるように'q'キーを押すだけで戻る。

とかやってたら、途中のmkdirに失敗してた。sudoでインストールしないといけなかったのか…ぐぬぬ。やりなおし。

```
sudo -E ./petalinux-v2017.3-final-installer.run /opt/pkg/petalinux
```

ここまでやって、VMに割り当ててたディスク容量がなくなった。可変にしたと思ったんだけどな…
仕方がないので40Gほど割り当ててubuntu再インストールからここまでやりなおし。

いろいろやり直して、容量も80Gまで増やした。
インストール先も/optから~/petalinuxに変えた。
インストーラも、2017.2じゃなくて2016.2だったよちくしょう。

このインストール作業は、かなり時間がかかるのでよく調べてから取り掛かろう。
OandaのAPIで開発する時の注意点(2018年03月30日時点)

#OandaのAPIで開発する時の注意点
Oanda Japanで口座を作った人はv20が使えません。
v1を使ってください。

英語版のアナウンスでは、2018年05月でv1終了とありますが、日本ではv1が引き続き使えます。

◯Introduction
http://developer.oanda.com/rest-live/introduction/
>The OANDA v1 REST API is deprecated
>The OANDA v1 REST API will cease to function for your account as early as May 2018.
>Please migrate your applications to use the v20 REST API.

v20で作ったソースが全然動かなかったので、コールセンターに問い合わせをしました。

今後ですが、Oanda Japanとしてはv20への移行をする予定ですが、現時点では時期が未定ということでした。

v20が使いたければ、海外に移住してOanda本体に口座を作るしかありません。
ロギングエージェントでGCEからStackDriverにRailsのアプリログを送る(カスタムログ設定)

# 概要
- railsのアプリログをstackdriverに送りたい
- Gemを使った方法がうまくいかなかった
- fluentdの設定追加であっさりできたので困ったらこっちのほうがいいよ

# やりかた
#### 1. Gem使う
  - 公式の[Ruby 用 Stackdriver Logging の設定](https://cloud.google.com/logging/docs/setup/ruby?hl=ja)で設定する
  - 一般的にはこっちのが楽だと思う。
  - このgemいれてUnicorn起動するとレスポンスが返ってこなくなる現象が解決できず諦めた
 
#### 2. ロギングエージェント(fluentd)のカスタム設定する
- 今回はこっちを採用した

# fluentdの設定追加方法
- 前提: GCEに[ロギングエージェントがインストール](https://cloud.google.com/logging/docs/agent/installation?hl=ja)されている
- fluentdのカスタム設定をする ->[ドキュメント](https://cloud.google.com/logging/docs/agent/installation#configure)
- `/etc/google-fluentd/config.d/*` にfluentd用の送信設定ファイルがおいてある。ここに送信したいログの設定を追加する。
- 例: /etc/google-fluentd/config.d/app.conf

```conf
<source>
  @type tail
  format none
  path /var/www/rails_project/log/app.log # 送信したいログのpath
  pos_file /var/lib/google-fluentd/pos/your_project_app_log.pos #posファイルの設定。1source設定に対し1pos_fileを設定。1pos_fileに複数source設定するとこけた。 
  read_from_head true
  tag your_project_app_tag # logのタグ名。stackdriverから見えるやつ。
</source>
```
- fluentdをreloadする

```
sudo service google-fluentd reload
```
MacOS high Sierraで`macOS could not be installed`と表示された。

# 症状
macOSのHighSierraを使っており、アプリやらOSやらのアップデートが溜まっていたので、App　Storeから実行した。
やけにアプリのアップデートに時間かかるなぁと思いつつ、アプリのアップデートはなんとか終了。
OSのアップデートに移り、再起動が必要ということで再起動した。
再起動し、ユーザにログインしようとすると画面には、

```
macOS could not be installed ...
```
のような文字列とRestartボタンが。
ん？と思い焦りながら何度かRestartして見るも、同様の画面が表示される。

# 対処
ググって見ると同様のエラーが出ている方が結構いるようだった。
メニューバーから`startup disk`を選択し、起動ディスクを選択、Restartした。
その結果なんとかログインでき（時間がかかったのでヒヤヒヤした）、今こうしてこの記事を書いているわけです。

# あとがき
2018/2月に購入したばかりのmacbook 12インチだったので購入時期にかかわらず生じる不具合だと思います。
Mac使いやすくていいんですけどこういうのが多くて肝冷やしますよほんとに。
テキストボックスから文字を入力してみよう

#　テキストボックスに入力された文字を取得する

　Webページでテキストボックスを表示するには、HTMLで以下のように書く。

![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/229736/4c8e2f33-3d1c-cfe9-cd9b-045c755518f8.png)
　
　JavaScriptでは、ここに入力された文字を、

![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/229736/0c5b44e1-60b6-7a3b-e861-ada8da66b8a5.png)

のように「.value」と記述することで取得できる。

　id属性に「mytext」という値を持つテキストボックスを配置したのであれば、ここに入力された文字は

　![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/229736/538043d8-3844-7887-a399-d605bdf584fc.png)

という表記で取得できる。

##　◆getElementByIdの注意点

　・"Id"の"I"は小文字のl(エル)ではなく大文字のI(アイ)である。

　・指定したID名がHTMLドキュメント内で見つからない場合、getElementByIdの戻り値としてnullが返る。

　・同じIDが同じドキュメント内に重複してしまった場合は、初回に合致した要素しか取得されない。

#　入力されたテキストを表示する

![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/229736/aff6784c-630e-95e9-5910-b16864f60c22.png)

　テキストボックスに文字を入力して、送信ボタンを押すと入力された文字を返すプログラムを考える(完成は上の図のコード)。

　1.　土台作成

　![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/229736/3c937f1b-0c84-e825-c174-ccbb64f0d6ce.png)

　特に言うことは無し。

　2.　head要素に文字コードとタイトル、body要素に見出しを加える。
　
　![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/229736/453cb723-8dbf-f669-8193-3c261f596aa4.png)


　3.　body要素に加えたいのは<br>
　　　・テキストボックス(id属性は「mytext」)<br>
　　　・送信ボタン(起動するスクリプトは"buttonclick()")<br>
　　の2つなのでこれを満たすコードを加える。
　
 ![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/229736/bae8196d-25a1-3560-6d3d-21366ae853f3.png)



　4.　buttonclick関数は「配置したテキストボックスに入力された文字を取得して、それを画面にポップアップ表示する」と定義するとコードは

　![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/229736/b25fa1b7-1e8b-e5dc-9235-708acc4414ea.png)


となる。これをブラウザで実行してみると

![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/229736/b6d9c94e-7eab-017d-80d3-ac4d5dab4223.png)

このようなものが表示される。これに少し手を加えると目標のコードになる事が分かる。

※　内容は[ちゃんと使える力を身につける JavaScriptのきほんのきほん](https://book.mynavi.jp/ec/products/detail/id=78352)のChapter3をまとめたものに少しアレンジを加えたものです。
MySQLのバージョン確認方法

接続前なら

```terminal
  $ mysql --version
  mysql  Ver 14.14 Distrib 5.7.21, for osx10.13 (x86_64) using  EditLine wrapper
```

接続後なら

```sql
  mysql> select version();
  +-----------+
  | version() |
  +-----------+
  | 5.7.21    |
  +-----------+
  1 row in set (0.01 sec)
```

mysqladminやstatusを使えばより詳細に色々分かる。

接続前

```terminal
  $ mysqladmin version
  mysqladmin  Ver 8.42 Distrib 5.7.21, for osx10.13 on x86_64
  Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

  Oracle is a registered trademark of Oracle Corporation and/or its
  affiliates. Other names may be trademarks of their respective
  owners.

  Server version		5.7.21
  Protocol version	10
  Connection		Localhost via UNIX socket
  UNIX socket		/tmp/mysql.sock
  Uptime:			4 min 53 sec

  Threads: 1  Questions: 2  Slow queries: 0  Opens: 105  Flush tables: 1  Open tables: 98  Queries per second avg: 0.006
```

接続後

```sql
  mysql> status
  --------------
  mysql  Ver 14.14 Distrib 5.7.21, for osx10.13 (x86_64) using  EditLine wrapper

  Connection id:		3
  Current database:
  Current user:		root@localhost
  SSL:			Not in use
  Current pager:		stdout
  Using outfile:		''
  Using delimiter:	;
  Server version:		5.7.21 Homebrew
  Protocol version:	10
  Connection:		Localhost via UNIX socket
  Server characterset:	utf8
  Db     characterset:	utf8
  Client characterset:	utf8
  Conn.  characterset:	utf8
  UNIX socket:		/tmp/mysql.sock
  Uptime:			6 min 14 sec

  Threads: 1  Questions: 7  Slow queries: 0  Opens: 105  Flush tables: 1  Open tables: 98  Queries per second avg: 0.018
  --------------
```

おしまい。
PHP7.0を7.1にしたときに valet install でちょっとハマった話。

valet 使ってる人、僕は主に laravel で使ってるんですけど。
同じところでハマった人のために、メモります。

laravel の最新バージョンが PHP7.1 でじゃないと動かないので、
php 自体は Homebrew で 7.1 にしました。
その辺りはたくさん記事が出てますが、一つ付け加えると。
```--with-fpm```は```brew install php71```で一緒に落とせるので不要です。

PHP および PHP-FPM を を7.1 にあげた後に、valet の環境も 7.1 対応したいので。

```composer global update```
の後
```valet install```
すると。

```
Error: homebrew/dupes was deprecated. This tap is now empty as all its formulae were migrated.
Error: homebrew/versions was deprecated. This tap is now empty as all its formulae were migrated.
 Unable to determine linked PHP. 
```
などが出て valet 動かない。

原因から言うと、valet のソースコードが
~/.composer/vendor/laravel/valet/cli/Valet/
以下にあるんですけど、その中の Brew.php に、対応する php のバージョンの配列があるんですね。
55 行目あたり。
```return collect(['php', 'php72', 'php71', 'php70', 'php56']);
```
んで エラーの出てる 186 行目あたりで
```return strpos($resolvedPath, "/$version/") !== false;```
がことごとく false になっているのが原因なんですけど、この行の1行上で
```var_dump($version);```
ってしてやると ```"php@7.1"``` って返ってきます、配列内にこれがないのが原因です。

なので、55行目に
```return collect(['php@7.1', 'php72', 'php71', 'php70', 'php56']);
// return collect(['php', 'php72', 'php71', 'php70', 'php56']);
```
として、無理やり足して、なおかつ
```PHP Notice:  Undefined index: php@7.1 in ~/.composer/vendor/laravel/valet/cli/Valet/PhpFpm.php on line 116```
「インデックスがないよー」と出るので
今度は ```~/.composer/vendor/laravel/valet/cli/Valet/PhpFpm.php``` に

```
function fpmConfigPath()
    {
        $confLookup = [
            'php@7.1' => '/usr/local/etc/php/7.1/php-fpm.d/www.conf', // <= こいつを足す
            'php' => '/usr/local/etc/php/7.2/php-fpm.d/www.conf',
            'php72' => '/usr/local/etc/php/7.2/php-fpm.d/www.conf',
            'php71' => '/usr/local/etc/php/7.1/php-fpm.d/www.conf',
            'php70' => '/usr/local/etc/php/7.0/php-fpm.d/www.conf',
            'php56' => '/usr/local/etc/php/5.6/php-fpm.conf',
        ];

        return $confLookup[$this->brew->linkedPhp()];
    }
```


で valet install したら、問題なくいけました。

今の所動いてますが、不具合があったら報告します。
おそらく PHP7.2系でも同じように行けると思います。