OmniAICreator/Qiita-1.07M huggingface dataset:
[Windows・jupyter notebook]機械学習のモデル可視化に使えるソフト「Graphviz」をインストール・使用する方法


以前話題になった、東大松尾研究室公開の無料ディープラーニング教材「DL4US」を写経する際、Graphviz部分のエラーに悩まされたので、後の人が苦しまないようメモとして残します。


#インストール前に発生するエラー

```python3:1.1.4モデルの可視化
from IPython.display import SVG
from tensorflow.python.keras.utils.vis_utils import model_to_dot

SVG(model_to_dot(model).create(prog='dot', format='svg'))
```

Graphvizに関する設定が済んでいない場合、[Lesson1 手書き文字認識をしよう（ニューラルネットワーク入門）](https://github.com/matsuolab-edu/dl4us/blob/master/lesson1/lesson1_sec1_exercise.ipynb)において上記コードを実行すると、以下のような2つのエラーが出てくる。

```python3:エラー

InvocationException: "GraphViz's executables not found"

ImportError: Failed to import pydot. You must install pydot and graphviz for `pydotprint` to work.

```

1つ目のエラーは、Graphviz本体がインストールできてない事によるもの。
2つ目のエラーは、pydot・graphvizモジュールが見つからないことを示している。

これらを解消するためには、Graphviz本体がインストール・pydot・graphvizモジュールの導入が必要となる。**Graphviz本体とgraphvizモジュールは異なるもの**なので注意すること。


#Graphviz本体のインストール

いろいろ調べた際は公式サイトからインストールできるという記事が多かったが、ボタン1つでできる仕様でなかったためよくわからなかった。

今回は、PowerShellにて使えるパッケージ「chocolatey」を用いてインストールを行う。chocorateyとは、macにおけるHomebrewのようなwindows用パッケージマネージャである。

chocoratey自体を導入するには、PowerShellを管理者権限で開いて以下のコードを入力すればよい。

```:chocoratey導入コマンド
iwr https://chocolatey.org/install.ps1 -UseBasicParsing | iex
```

ただし、PowerShellの実行ポリシー設定によっては、以下のようなエラーが出て導入できない場合がある。

```:実行ポリシーによるエラー
& : このシステムではスクリプトの実行が無効になっているため、ファイル〇〇を読み込むことができません。
詳細については、「about_Execution_Policies」(https://go.microsoft.com/fwlink/?LinkID=135170) を参照してください。
```

これは、PowerShellの実行ポリシーが「restricted」になっているのが原因なので、以下のように「unrestricted」へ設定を変えることで、chocoratryを導入できるようになる。

```:設定の変更
Set-ExecutionPolicy unrestricted -Scope CurrentUser
```

念の為、導入が済んだら実行ポリシーの設定を「restricted」に戻しておく。



chocorateyが導入できたら、ようやくGraphviz本体のインストール。PowerShellを管理者権限で開き、pipと似たような形式でコードを書けばよい。

```
choco install graphviz
```

パッケージ名はchocoratryだが、実行する際のコードは「choco」なので注意。加えて、管理者権限で開いたPowerShellを使わないと、アクセス拒否によるエラーが発生する。




#pydot・graphvizモジュールのインストール

モジュールのインストールに関しては、王道とも言えるpipを使って簡単にインストールできる。

pydotモジュールが正常に動かない場合。代わりにpydotplusまたはpydot-ngを使うとよい。自分はpydotplusを使っている。



#動作確認

記事冒頭のコードを書き、以下のような出力が得られれば、無事インストールは成功である。

![NN_model.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/350483/ca611ffd-f445-2517-7952-cf2750218f1a.png)


#まとめ

機械学習のモデル可視化に使えるソフト「Graphviz」について、windows用パッケージ「chocolatey」を用いてインストールする方法を示しました。

10分程度で終わる作業なので、機械学習の勉強を試みる人はこれを機に「Graphviz」を使ってみてください。

記事を書くきっかけとなった「DL4US」は、機械学習の概要が大まかにわかる良質なコンテンツです。本1冊に相当するボリュームにもかかわらず無料で読めるとは素晴らしい。



#参考文献

[DL4US](https://github.com/matsuolab-edu/dl4us)
[Windows版homebrew的存在、Chocolateyを使う](http://byoma.hatenablog.com/entry/2016/08/21/124259)
[PowerShellでスクリプトを実行するとセキュリティエラーになるときの対策](https://www.gesource.jp/weblog/?p=8203)
[kerasのplot_modelでハマった話](https://qiita.com/hrs1985/items/7d923e9465985d6b8968)
PILで取得したEXIF情報を16進数から変換する

#画像に撮影時の設定を書き込みたい
皆さんおなじみの[フォトヨドバシ](http://photo.yodobashi.com/)に掲載されている作例っぽく、写真に撮影時の画像を書き込みたくなったので、ちょっとづつ調べながらコードを書いていくことにした。
#PILでEXIF情報を取り出す
調べるまでもなく先にやっている人が大勢いるので、コードをコピペして実行してみるのだが、気になったのがこれ。

```python:pori.py
from PIL import Image
from PIL.ExifTags import TAGS

def get_exif_of_image(file):
    """Get EXIF of an image if exists.

    指定した画像のEXIFデータを取り出す関数
    @return exif_table Exif データを格納した辞書
    """
    im = Image.open(file)

    # Exif データを取得
    # 存在しなければそのまま終了 空の辞書を返す
    try:
        exif = im._getexif()
        pprint.pprint(exif)
    except AttributeError:
        return {}
    

    # タグIDそのままでは人が読めないのでデコードして
    # テーブルに格納する
    exif_table = {}
    
    for tag_id, value in exif.items():
        tag = TAGS.get(tag_id, tag_id)
        exif_table[tag] = value

    return exif_table
```
出典:[Life with Python](https://www.lifewithpython.com/2014/12/python-extract-exif-data-like-data-from-images.html)


コメント欄いわく「タグIDそのままでは人が読めないのでデコードしてテーブルに格納する」らしい。
じゃあタグIDそのままだと何が出てくるのかというと、

**16進数**

```python:
{270: '                               ',
 271: 'SONY',
 272: 'ILCE-6000',
 282: (300, 1),
 283: (300, 1),
 296: 2,
 305: 'Capture One Express (for Sony) 10.1.2 Windows',
 33434: (1, 4000),
 33437: (18, 10),
 34665: 226,
 34850: 3,
 34855: 100,
以下略
```
読めません。ここで何をやっているのか調べてみる。
#答え:辞書に全部書いてあった。
TAGでPILのドキュメントを検索してもそれっぽい情報が出てこない。
しかしよく見てみると、"TAGS"は辞書らしい。インポートしているということは、ライブラリの中にあるということ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/425022/7eebcbe8-75a8-f4a7-4aba-f4ef2845017c.png)
中身を見てみると

```python:ExifTags.py
TAGS = {

    # possibly incomplete
    0x000b: "ProcessingSoftware",
    0x00fe: "NewSubfileType",
    0x00ff: "SubfileType",
    0x0100: "ImageWidth",
    0x0101: "ImageLength",
    0x0102: "BitsPerSample",
    0x0103: "Compression",
    0x0106: "PhotometricInterpretation",
    0x0107: "Thresholding",
    0x0108: "CellWidth",
    0x0109: "CellLength",
    0x010a: "FillOrder",
以下略
```
要するに取り出した16進数を、すでに用意されているTAGSの情報と一致する情報に置き換えているだけ。
ということはTAGSから必要な項目だけ抜粋してもいいし、何ならコードに直打ちしてもいい。面倒だからやらないけど。
docker-composeでredis環境をつくる

```yaml:docker-compose.yaml
version: '3'
services:
  redis:
    image: "redis:latest"
    ports:
      - "6379:6379"
    volumes:
      - "./data/redis:/data"
```

```console
$ docker-compose up -d
```

確認

```console
$ docker exec -it [CONTAINER ID] /bin/bash
root@46f68f517bf1:/data# redis-cli
127.0.0.1:6379> keys *
```

## redisのコマンド

|コマンド|説明|
|:--|:--|
|keys *	|redisに登録されているキーの一覧を取得する|
|type [key]	|`value` の `type` を返す|
|get [key]	|`type` が `string` の値を取得する|
usersテーブル以外のテーブルを使ったlaravelの認証機能

Laravelの認証機能を用いてログイン機能を実装しようとしたが、すでにusersという名前のテーブルを作成してしまっていたので、対応策を記録しておきます。

## 作りたいもの
- お問い合わせフォームの管理者用画面
- ログイン機能、新規登録機能、ログアウト機能の実装
- ログインの際はメールアドレス、パスワードを入力し、データベースにあるものと一致すれば問い合わせ一覧の画面に遷移する。
- 新規登録では、名前、メールアドレス、パスワードを入力し、データベース上に同メールアドレスが存在しなければ新たにデータベースに登録される

## 認証機能を生成する
マイグレーションを実行した後に、laravelのディレクトリ上で以下のコマンドを実行します。

```text
> php artisan make:auth
#実行結果が以下のようになれば成功です。
[demo@localhost laravel]$ php artisan make:auth
Authentication scaffolding generated successfully.
```
すると認証に必要なビューやコントローラーなどが作成され、ルート定義なども行ってくれます。

## 認証に使用するテーブルの変更
認証に使用するテーブルを変更するにはapp/User.phpを以下のように変更します。
今回は"register"という名前のテーブルを認証に使います。　

```php
<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

//以下を追加
    /**
     * The database table used by the model.
     *
     * @var string
     */
    protected $table = 'register';
}
```

$tableの値が使用するテーブル名になります。

## 注意点
既存の認証と同じカラムを持たせる必要があるので

- `id`(オートインクリメント）
- `name`
- `email`
- `password`
- `remember_token`

という名前のカラムを事前に作成しておかないと正しく認証が出来ないので注意しましょう。
Raspberry pi 3+にsshからメッセージを表示する

# <<<小技ネタ>>>

# sshから実行されるアプリからHDMI出力のMessageBoxを表示する。
まず、UIを取り扱うためにtkinterをインストールする。

```
$ sudo apt-get install python3-tk
```
動作チェック

#まず、GUIから実行テスト
```
$ python -m tkinter
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274715/54ebf6c9-c38f-dbf6-7a26-7a899aa5cf6a.png)
#以下が表示されれば成功
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274715/c35b25bc-13b6-ca08-a660-3496cbee0117.png)
sshターミナルからコマンドを打ち込むと

```
$ python -m tkinter
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/usr/local/lib/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/usr/local/lib/python3.6/tkinter/__main__.py", line 7, in <module>
    main()
  File "/usr/local/lib/python3.6/tkinter/__init__.py", line 3988, in _test
    root = Tk()
  File "/usr/local/lib/python3.6/tkinter/__init__.py", line 2023, in __init__
    self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
_tkinter.TclError: couldn't connect to display ""
```
# couldn't connect to displayと怒られてしまう。
sshは、CUIだから当たり前だ!
# HDMIモニターに表示するにはどうしたらよいだろうか?
```
$ DISPLAY=:0 python -m tkinter
```
### ディスプレイを指定するとHDMIに表示できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274715/a95d8766-6a20-dce5-9ee6-724b51560441.png)

##サンプルアプリを紹介しよう。

```alert.py
#!/usr/local/bin/python3.6
# -*- coding:utf-8 -*-
import tkinter as tk,os,sys
import tkinter.font as font
os.environ['DISPLAY']=':0' #ディスプレイの出力先
class Message(tk.Frame):
    def __init__(self, root):
        tk.Frame.__init__(self, root)
        w=tk.Message(root,text=Msg,font=("", 60, "bold"))
        w.pack(expand=1, fill="both")
if __name__ == '__main__':
    root = tk.Tk()
    root.title(sys.argv[1])
    root.attributes("-zoomed", "1")
    Msg=sys.argv[2]
    app = Message(root)
    while True:      #イベントループ
        try:
            root.update()
        except KeyboardInterrupt:
            break
    sys.exit()
```

### 実行させてみよう
実行権を付加する
$ sudo chmod 777 alert.py

```
./alert.py Alert CPU高温注意
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274715/4dfae674-c978-1776-56c1-bd2bab0e6cbe.png)
TypeScriptでPDFを生成して、FirebaseのStorageに格納する

Gakuです。
PDF系の生成処理が実装できるようになると、幅が広がるかなと思って勉強中です。
そんな中、[PDFKit](http://pdfkit.org/)の初期設定で結構ハマったので、やり方記載しておきます。

# パッケージのinstall
TypeScriptになるので、PDFKit本体と型定義パッケージをインストールしておきます。

```bash:install
npm install pdfkit
npm install @types/pdfkit
```

# 使い方

```typescript:sample.ts
import * as pdf from 'pdfkit';
import * as fs from 'fs';

export default function(){
    const stream = fs.createWriteStream('test.pdf');

    const doc = new pdf({ margin: 20 });
    doc.pipe(stream);
    doc.registerFont('regular', 'fonts/mplus-1p-regular.ttf'); // ここらへんはお好きなfontを指定
    doc.registerFont('bold', 'fonts/mplus-1p-bold.ttf');

    // title
    doc.font('bold').fontSize(25)
    .text('テ ス ト');

    doc.end();
};
```
このような感じで実装することで、プロジェクト内にPDFが生成されます。
注意点としては、PDFKitのデフォルトfontだと日本語が文字化けしてしまうので、日本語対応のfontを指定して使うようにしましょう。
記述方法は[PDFKit](http://pdfkit.org/)に詳しく記載されております。

# Firebase Storageに格納
PDFKitでは、doc.read()でBufferが取得できるのですが、日本語対応のfontを指定した場合、なぜか「壊れたPDFドキュメント」が生成されます。
なので、以下のようにstreamを取得し、doc.pipeで指定する形で実装します。
(S3等に保存する場合でも、同じような手順になるかと思います。)

```typescript:sample2.ts
import * as pdf from 'pdfkit';
import * as fs from 'fs';
import * as admin from 'firebase-admin';

export default function(){
    const filename =  'test.pdf';
    const file = admin.storage().bucket().file(filename);
    const stream = file.createWriteStream({
        metadata: {
            contentType: 'application/pdf',
        },
    });

    const doc = new pdf({ margin: 20 });
    doc.pipe(stream);
    doc.registerFont('regular', 'fonts/mplus-1p-regular.ttf'); // ここらへんはお好きなfontを指定
    doc.registerFont('bold', 'fonts/mplus-1p-bold.ttf');

    // title
    doc.font('bold').fontSize(25)
    .text('テ ス ト');

    doc.end();
};
```
これで、firebase storageに生成したPDFが格納されます🎉

# おわりに
PDFの生成が実装できるようになると、紙ベースでのやり取りが中心な日本社会ではいろいろ捗るかと思います。
面倒な書類作成業務はどんどんプログラム化して、楽していきましょう(/・ω・)/
Web技術でNativeアプリ関連の調査

# 概要

- AngularでWebアプリ作ってたらやっぱりiOSでもPush通知したいよねってなったので調査した。
- まだ実装はしていない。検証が終わり次第記事を削除/更新したい。

# 参考

- https://qiita.com/hosikiti/items/15755f929ff5e445ef43
- https://note.mu/rdlabo/n/n1e8e71228e21
- https://qiita.com/itagakishintaro/items/5b276a0ecee209d0c341
- https://press.monaca.io/bryan/2621
- 読み物: https://medium.com/airbnb-engineering/react-native-at-airbnb-f95aa460be1c

# まとめ

|項目|Cordova|NativeScript|Expo (React Native)|
|---|---|---|---|
|良い点|コンポーネントがWebなので勉強が楽そう|Angularが使える|ユーザーが多そう。環境設定不要？更新も早そう。|
|懸念|遅いらしい。Webコンポーネントな必要ある？|Angularがそもそも辛い。コンポーネントの再利用とかやっても結局コスト高そう。|Reactやったことない。|
|クラウドビルド<br>(ビルド回数)|Monaca(3/日）<br> PhoneGap(1つなら無制限)|[Sidekick](https://www.nativescript.org/nativescript-sidekick/purchase) (100/月)|無料|

# 共通

- ネイティブのプラグイン書く必要になったらネイティブに移ったほうがいらしい。
- Cordova, NativescriptではAndroid, iOSの開発環境が必要そう。当然のことだったらしい。
  - Cloud Build関連があるとそれをやってくれるらしいが、NativeScript Sidekickしか試していないがまあとても遅い。
  - Andoridの環境入れようとしたら結構容量食うので辛い。

# 抜け

- あとでXamarin, Flutter棟もあるのに気がついたので検討しないといけない。RubyMotionなんてのもあったらしいね。
  - https://qiita.com/knagauchi/items/9a57bf876b7e956065a4
  - https://qiita.com/hikarut/items/974e5782a3c0bf26f82a
  - https://speakerdeck.com/amay077/native-made-number-droidkaigi?slide=23

# 次

- 各環境で検証したい
  - Web APIを叩く
  - 通知(プッシュ/スケジュール)
  - サインアップ画面の実装
s3fsバージョンアップに関する試行錯誤メモ

## 背景
s3fsのバージョンが1.79未満だとs3にアクセスできなくなるらしい。

参考：[s3fs の利用者はいますぐバージョンを確認しないと使えなくなるかも？！](https://enomotodev.hatenablog.com/entry/2019/03/07/110418)



さっそくバージョン確認。

```
$ s3fs --v
Amazon Simple Storage Service File System V1.78 with OpenSSL
Copyright (C) 2010 Randy Rizun <rrizun@gmail.com>
License GPL2: GNU GPL version 2 <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
```

＿人人人人人人人人人人人＿
＞　ぎりアウト～！！　＜
￣Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^￣



## 結論(忙しい方用)
S3バケット名にドットが入っている場合、s3fsバージョンアップは1.81までにする。
(それより上げると、今まで通りの指定では接続できなくなりました)


## やったこと(詳しく知りたい方用)
[s3fs](https://github.com/s3fs-fuse/s3fs-fuse) のリポジトリによると、最新バージョンはv1.8.5らしい。
じゃあ最新を入れとけばええやろ、と軽率に決定。(**ミス1**)


### まずは今入ってるやつ(1.78)を消すぞ

```
sudo su
# service httpd stop　#念のため止めた
# cd /usr/local/src/s3fs-fuse-1.78
# make uninstall
# s3fs --v
# bash: s3fs: command not found　#消えた？
```

### 新しいの(1.85)を入れるよ
アップデート対象のインスタンスにはgitが入っていなかったため、githubからzipを落としてSFTPアップロードしました。
zipを `/usr/local/src` に置いて、

```
# unzip s3fs-fuse-master.zip -d s3fs-fuse-1.85
# rm -R s3fs-fuse-master.zip 
# cd s3fs-fuse-1.85/s3fs-fuse-master/
# ./autogen.sh 
# ./configure
# make
# make install
# s3fs --v
Amazon Simple Storage Service File System V1.85 (commit:unknown) with OpenSSL
Copyright (C) 2010 Randy Rizun <rrizun@gmail.com>
License GPL2: GNU GPL version 2 <https://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
```

1.85になったっぽい！
s3マウントしているディレクトリも参照できたため、OKとしました。(**ミス2**)

### その後何が起きたか
s3fsをアップデートしたインスタンスをしばらく使わないため、停止。
後日起動してみたら、s3fsマウントに失敗…！？

原因は、
旧バージョンでマウントしたディレクトリはs3fsバージョンアップ後も維持されていた
↓
インスタンス停止によりアンマウントされる
↓
インスタンス起動時、新バージョンでマウントを試行するも失敗

という流れのようでした。
アップデート後にリマウントして確認していればこんなことにはならなかった…
**s3fsのバージョンアップをしたらリマウントもしなきゃダメ絶対！！**(→ミス2)

### でもなんでマウントできないの？

マウントできない時に出たエラー

```
s3fs: BUCKET hoge.fuga.piyo -- cannot mount bucket with . while using HTTPS without use_path_request_style
```

`with .` …？
確かにバケット名にドットを含んでいるなあと「s3 バケット名 ドット」で検索したところ
出るわ　[Amazon S3のバケット名にドットを使ってしまいました](https://www.ncaq.net/2017/08/31/)
出るわ　[S3のバケット名はよく考えて命名しましょう！](http://blog.dateofrock.com/2012/02/s3.html)

なんでバケット名にドット使ってしまったん…というお気持ちになりました。

マウントできないことについても[s3fsのFAQ](https://github.com/s3fs-fuse/s3fs-fuse/wiki/FAQ#q-https-connecting-failed-if-bucket-name-includes-dot-) に記載がありました。
v1.82からs3fsはhttps接続するようになったとのことで、その際にバケット名のドットが悪さをしているそうな。
当たり前だけど、**軽率にバージョン上げまくっちゃダメ絶対！！**(→ミス1)
~~マイナーバージョンアップだからいいかと思ったんだよ…~~

FAQによれば、その場合でも `use_path_request_style` オプションと`endpoint`オプションを指定すればいいらしいのですが

```
# s3fs "hoge.fuga.piyo:/foo-bar" "/mnt/s3" -oallow_other -ouse_cache="/tmp" -oiam_role="hoge_admin" -ouse_path_request_style -oendpoint="ap-northeast-1"
# ll /mnt/s3/
total 0   #マウントされていればここに何らかディレクトリが出てくるはず
```

エラーも何も吐かずにマウント失敗…！
`-ouse_path_request_style` を指定しないと
前述のエラー `cannot mount bucket with .` が出てくるため、指定することで何かが変わっていることは推測できますが、解決はしない。

この現象が起きないv1.81までのバージョンアップで妥協することとなりました。
本番公開されているサイトで Vue devtools を使う裏技

#概要（Vue.js devtools とは）

Vue.js devtools は Vue.js のデバッグに用いられるブラウザ拡張です。

非常に便利ですが、デバッグツールなのでプロダクション環境では無効化されるようになっています。

![gdgd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123809/bcd1f718-16d7-1a07-59d8-3765b2fd7319.png)


本記事では、WEB上で本番公開されているサイトで Vue.js devtools を有効化する方法を解説します。

#検証環境

ブラウザ：Google Chrome74 

#有効化の手順

以下では[Vue Cliのドキュメントページ](https://cli.vuejs.org/)を対象として手順を説明します。

### 1. devtoolsの設定をしているコードを見つける

devtoolsの有効化・無効化の設定をしているJSファイルを探していきます。

まず Chrome のディベロッパーツール の Sources タブを開きます。

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123809/cee1ec41-f608-4f48-1afa-39cfa75ad24c.png)

目的のJSファイルの場所はサイトによって異なりますが、今回は`assets`というそれっぽいディレクトリがあるので、開いてみます。

![fdafadf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123809/10ff6d8a-dd4f-6465-1311-71b99a352cf2.png)

`assets > js`とディレクトリを辿ると、「appなんちゃら.js」みたいなメイン処理っぽいファイルがあるので開いてみます。

そのままだと読みづらいので、画像の右下らへんにある`{}`マークをクリックしてコードを整形しましょう。

そしてファイル内で「devtools」という文字列を検索します。
文字列は複数見つかるかもしれませんが、**以下のように`devtools`というプロパティを持つオブジェクトの宣言をしている部分が目的のコード**です。

![dev.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123809/fda3dc07-a02c-4482-9323-481e6ebb9d83.png)

サイトごとにコードの位置やオブジェクト名などは変わりますが、見つけるのはそう難しくないと思います。

このコードを書き換えることでdevtoolsを有効化します。

### 2. devtools の値を書き換える

上のコードをみると、`N`というオブジェクトの`devtools`プロパティの値が`!1`、すなわち`false`になっています。
これを`true`にすれば devtools が有効化されそうです。

そのため`N`が宣言されたすぐ後の箇所にブレークポイントを設けて、ページをリロードしましょう。

すると`N`が宣言されたタイミングで処理がストップするので、コンソールから値を書き換えられます。
`N.devtools = true`とコンソールに打ちましょう。

![N.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123809/ed3755f1-a6b8-137a-7d23-c124ebd35c0a.png)

処理を再開してVue.js devtools のアイコンをクリックすると、

![aaaaaaaaaaa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123809/8f1f4a43-d9be-5ec8-9631-d1902fa2ccbb.png)

メッセージが変化し、devtools が有効化されました！

ただしこのままだと開発者ツールにまだ Vue タブが出てきていないので、ツールを一旦閉じてまた開きなおしましょう。

開きなおすことで Vue タブが出てくるので、無事 Vue.js devtools を開くことができます。

![fws.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/123809/08a5d3f3-ff06-afee-c0a4-1802562ddd04.png)

これにより本番サイトの data や store を確認したり編集したりすることが可能になりました。

以上です。

##### 参考文献
- [Rahul Kadyan氏のツイート](https://twitter.com/znck0/status/1135651853776052224?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1135651853776052224%7Ctwgr%5E%7Ctwcon%5Es1_&ref_url=https%3A%2F%2Fqiita.com%2FPOPOPON%2Fitems%2F60010faae1eb4e4e67ac)
AWS でライブ配信システムを構築する （１） 概要

#1. この記事で扱う内容
この記事では、AWS の各種サービスを使用してライブ配信システムを構築する方法について紹介します。

このページでは、記事全体の概要について紹介します。　各作業の詳細について該当するページを参照してください。

記載した内容は、私が開発中に試行錯誤した結果であって、使用する環境や目的によっては必ずしも最善ではないかもしれませんので、その点をご注意ください。

##1-1. 環境
- AWS
 - Elemental MediaLive
 - Elemental MediaStore
 - CloudFront
 - S3
- 開発サーバー
 - CentOS 7
 - Rails 5.2

##1-2. この記事で構築しようとするシステムの構成
今回構築するライブ配信システムの構成は以下のようになっています。

![fig1-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413038/e0f526bf-429a-b578-89f7-d32533d45d3c.png)

1. カメラ等から送信されたライブ動画を MediaLive が HLS 形式に変換します
1. 変換された動画ファイルを MediaStore に配置します
1. ユーザーは CloudFront 経由で MediaStore の動画にアクセスします
1. MediaLive はオンデマンド配信用にライブ動画のアーカイブ（ HLS ファイル）を S3 上のバケットに保存します

なお、今回使用する MediaLive、MediaStore、S3 はすべて東京リージョンを使用します。

#2. 記事の構成
本記事では、システム構築の手順を以下のように数回に分けて紹介します。
（１）概要 ： このページ
（２）[MediaStore の設定](https://qiita.com/mas_yam/items/20c8b524ebd87595e88e)
動画ファイルを保管する MediaStore の設定について紹介します。
（３）[MediaLive の設定](https://qiita.com/mas_yam/items/ed01102b8a996bfc5774)
カメラからのライブ動画を受信して、動画ファイルに変換する MediaLive の設定について紹介します。
（４）[CloudFront による配信](https://qiita.com/mas_yam/items/c3d1dde987afa50479d1)
MediaStore に保管された動画ファイルを CloudFront を経由して配信する方法について紹介します。
（５）[MediaLive の設定 その２](https://qiita.com/mas_yam/items/9bdfdb2091fb12ab4c77)
MediaLive でアーカイブを出力する方法、 Railsアプリから Channel を操作する方法、ライブ配信の遅延軽減法について紹介します。

#3. 参照
- [【AWS Black Belt Online Seminar】AWS で実現するライブ動画配信とリアルタイムチャットのアーキテクチャパターン ｜ YouTube](https://www.youtube.com/watch?v=GUOyGWwzzVU)
- [【やってみた】AWS Elemental MediaLiveとAWS Elemental MediaStoreでライブ配信してみた #reinvent ｜ DevelopersIO](https://dev.classmethod.jp/cloud/aws/reinvent2017-awselemental-medialive-mediastore-livestreaming/)
文言の整理

システム開発して、改良していくうちにいくつか文言の設定があったりしますね。
書いておくべきか悩みましたがある程度こういう場合（ケースがある）というのを追加していきたいと思ったので気軽に追加してみてください

### ケース１
#システムの環境により切り分けによる文言例

|項目|例|
|:---:|:---|
|タイトル|システムOS お知らせ|
|詳細|本システムはパソコンの推奨動作環境をWindows OSのみとしております。それ以外のOSの場合、正常に動作しない可能性がございます。|


### ケース２
#スマートホンの対応による文言例

|項目|例|
|---|:---|
|タイトル|スマートホン対応 お知らせ|
|詳細|スマートフォンをお持ちの場合は、○○○○ アプリからお試しいただくこともご検討ください。動作環境についてはこちらのページをご参照ください。|
※ ○○○○ : 社名・団体・グループ名など

こんなケースがあるよっていうのがあったら教えてください！

またこれをデータベース化もしくは共通化して世の中に貢献できるようにしていきましょう！

## 文言事業


## 関連記事

【About】(http://qiita.com/sunstripe) - サンストライプ

---

## 制作チーム：サンストライプ

[![sunstripe_logo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80600/322f2d60-f19d-af9e-2b6f-7290ca546848.png)](http://sunstripe.main.jp/)
http://sunstripe.main.jp/

(月１WEBコンテンツをリリースして便利な世の中を作っていくぞ！！ボランティアプログラマー/デザイナー/イラストレーター/その他クリエイター声優募集中！!)

### 地域情報 THEメディア
THE メディア 地域活性化をテーマに様々なリリース情報も含め、記事をお届けしてます！！
https://the.themedia.jp/

### ゼロからはじめる演劇ワークショップ
多様化の時代に向けて他者理解を鍛える

https://workshop.themedia.jp/

### プログラミングワークショップ・ウェブ塾の開講！！！
様々なテーマでプログラミングに囚われずに取り組んでいきます。
詳しくはこちら　↓　↓　↓　↓　↓　↓　↓　↓
[プログラミングサロン 月１だけのプログラミング学習塾](https://workshop.themedia.jp/posts/7057553?fbclid=IwAR32CfRQ7RvDOhvuogoSwqxDLMOU7Jvuzljlnx-TMc27qBPX1BnWsfLcBR8
)

### 協力応援 / 支援者の集い
## チーム：サンストライプ
#### プログラミングラボ
https://twitter.com/sunstripe2011

一緒にポートフォリオを作りませんか？現場の体験やそれぞれの立場から年齢関係なく作品を作りたい方々と一緒にチームを作って、作品を作っています。現場に行きたい人には、職場紹介や職場の体験や悩み相談なども受けております。
様々な職種からプログラミングの知識を得たい、デザインの知識を得たい、データーベースの知識を得たいという人が集まっております。
週１のミーティングにそれぞれの近況と作業報告して、たまにリモート飲み会などをしております！！

興味がある方は、DMに話しかけてみてください。

## トラストヒューマン
http://trusthuman.co.jp/
私たちは何よりも信頼､人と考えてます｡

｢コンサルティング｣と｢クリエイティブ｣の両角度から｢人材戦略パートナー｣としてトータル的にサポートします！！

キャリア教育事業
広域学習支援プラットフォーム『のびのび日和』
https://slc-lab.amebaownd.com/

#スポンサー募集
IntelliJ Idea 2019.1からVM Opotionsが適用されずOutOfMemoryError: GC overhead limit exceededが発生する問題

# 解決法
<img width="1312" alt="スクリーンショット 2019-06-05 9.40.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/229617/8bc903a9-6336-87fd-304c-e04e5b887816.png">

# 問題？
2018.XXまでは Help > Edit Custom VM OptionsからMax Heapサイズを設定できていたが2019.1に移行してから適用されなくなった。写真の場所から設定すればOutOfMemoryErrorは発生しなくなる。
バグではなく私の勘違いである可能性もあるのでその場合はコメントで教えてください。
RailsのAuthlogicで任意のモデル名を使った実装をしたいとき

## 経緯

社内で、勤怠管理システムをRuby on Railsで構築しようということになり、先週末から本格的にコーディングをはじめました。
管理系のアプリなので認証機能を実装しようと思い、gemの`Authlogic`を用いて実装を行いました。
大きく困ったところはなかったのですが、一点躓いた点があったので記事にしました。

※本記事はAuthlogicの実装方法をある程度理解していることを前提に書いていますので、ご了承ください。

## バージョン情報

Ruby: 2.5.3
Ruby on Rails: 5.2.3
Authlogic: 5.0.2
OS: macOS Majave 10.14.5

## 躓いた点

* 社員を示すEmployeeモデルを作成し、そのモデルにAuthlogicを適用しようと思ったが
ログイン画面表示時に以下のエラーが発生した。

```
NameError in UserSessionsController#new

uninitialized constant User
```
![authlogic_error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312978/0c785384-7021-ae15-cc6f-288d54ada690.png)

## 解決方法

* 結論としては、Authlogic::Session::Baseを継承したUserSessionモデルに、Authlogicを適用するモデル名を以下のように明示的に指定する必要があった。

```Ruby
class UserSession < Authlogic::Session::Base
  authenticate_with Employee      #=> この行を追加
end
```

## 解決するまでの道のり

1. Google先生に聞いていみる  
→ なかなか、当該情報が見当たらず、Userモデルを例にしているチュートリアルがほとんどだった。
2. リファレンスを読み漁る  
→ 私自身、英語が得意というわけでもないので、なかなか見つけることができなかった。
3. teratailで質問をする  
→ 質問を投稿したが、自分の情報が足りなかったのか、この現象が当たり前すぎることなのか、回答が得られなかった
4. 再びリファレンスを読み漁る  
→ ここでようやく、`authenticate_with`をリファレンスから見つけることができました  
（ https://www.rubydoc.info/github/binarylogic/authlogic/master/Authlogic/Session/Klass/Config ）

## 反省

* 英語のリファレンスはなかなか読むのに苦労しましたが、キーワードで調べていくうちに見つけることができたので、
リファレンスを読むことの大切さを今更ながら、改めて実感しました。
* なかなか今回の現象の記事等が出てこなかったので、この記事が少しでもお役に立てれば幸いです。
xonshが超カッコイイ話

# はじめに
私事ですが無事就職しました(おめでとうございます(ありがとうございます))

さて、今回はxonshというシェルが最高にイケててカッコイイので、会社のいろんな人に布教出来たらいいなと思って記事を書くことにしました、勿論他の人にも。(xonshの記事はググッてもまだ少ないから今なら目立てるとかいう気持ちはありません)

# xonshって？

PythonistaのPythonistaのためのPythonistaによるシェルです(Pythonista以外にも便利ですが)

つまり、**Pythonで作られたPythonが直接動作するシェル**です。

え？？？？？Pythonが直接動くの？？？？？？めっちゃカッコよくない？？？？？？？？？

そうです、めっちゃカッコイイです。しかも、後で紹介しますがシェルスクリプトと直接連携もできちゃいます。

当然bashコマンドも実行可能。

# 導入
6/7 追記:前提環境としてPython3.x系を導入しておいてください

```bash
pip install xonsh
```

readlineshellとして使うならば追加で

```bash
pip install gnureadline
```

macの場合bash補完パッケージとして

```bash
brew install bash-completion2
```

# 起動

シェルで xonsh とコマンド名を打てば、Pythonで書かれた xonsh が起動する。

```console
$ xonsh

                       Welcome to the xonsh shell (0.9.5)                       

             ~ Python-powered, cross-platform, Unix-gazing shell ~              

--------------------------------------------------------------------------------
xonfig tutorial    ->    Launch the tutorial in the browser
xonfig wizard      ->    Run the configuration wizard and claim your shell 
(Note: Run the Wizard or create a ~/.xonshrc file to suppress the welcome screen)
```

# xonshによるシェルスクリプトとPythonの連携
xonsh上ではシェルスクリプトやコマンドとPythonの連携が死ぬほど簡単です。

例えば

```bash
$PATH
```

の実行結果はリスト型のオブジェクト

```Python
EnvPath([
'usr/bin',
'usr/local/bin'
])
```

のように返されます。
Pythonのリスト型オブジェクトなので当然次のような操作が出来ます。

```Python
$PATH.append('任意のパス')
```

これ、めっっっっっちゃエモく無いですか？

こうすることで起動中のシェルに一時的にパスが追加されます、.xonshrcに記述すればずっと追加され続けます。

他にも

```Python
print($(ls -la))
```

これでコマンドの実行結果を出力できるし、当然変数に格納できるので

```Python
cmd = $(ls -la)

print(cmd)
```

とかも出来る、type()でクラスも調べられる。
ちなみにxonshを起動しなくても

```bash
xonsh -c "print($(pwd))"
```

とかも出来る。

他にも、Pythonファイルからのimportとか、Pythonがインタプリンタで出来ることはなんでも出来ます。

# xonshrc
お察しの通りxonshrcはPythonで書ける。
例えば

```Python
def _hoge:
  return ('hogehoge', None)

aliases['hoge'] = _hoge
```

後はxonshで

```bash
hoge
```

と打ち込めばちゃんと出力される。
xonshrcの設定例に関しては先達がたくさんイケてるものを上げているのでそちらに譲ります(めんどくさかったわけではない)(そのうち記事を書くかも)

# [2019/6/10: 追記]強力な補完
めっちゃ大事なポイントなのに書き忘れていたんですが、Xonshのメリットはもう一つ、強力な補完機能です。
といってもXonshのプロジェクトから分離してすべてのシェルで使えるのですが、xonshでは未だに標準でサポートしています。

```bash
brew install bash_completion2
```

これだけで強力な補完がいつでも利用できるようになります、bashなどで使いたい場合はinstallメッセージの指示に従う必要があるようです。

# デメリット
こんだけとがってると、まあ当然いい事ばかりではないです、というわけでデメリットは以下

+ 起動が遅い
+ Pythonがわからないと恩恵が薄い

といったところです、起動に関してはmacでは不満を感じた事がないですが、wslで起動した時が顕著に遅いです(wsl自体が遅いのもありますがxonshは特に)
起動だけじゃなくスクリプトの実行もPython使ってる関係上どうしても他のシェルよりは遅くなります

2つ目に関しては…諦めるしかないですね、Pythonをしてください()

# 参考記事

## ほとんどここの記事しか見てない

https://qiita.com/advent-calendar/2017/xonsh
型変換

型変換のことをキャストといいます。
~~定義されていた変数の型を変換するということ。~~(コメントにてご指摘いただきました。)
##サンプルコード

```go
func main() {
	
	var x int = 1
	xx := float64(x)
	fmt.Printf("%T %v %f\n", xx, xx, xx) //float64 1 1.000000

	var y float64 = 1.2
	yy := int(y)
	fmt.Printf("%T %v %d\n", yy, yy, yy) //int 1 1
	//%d int表示

	var s string = "14"
	// z = int(s) とやると、stringをintに変換できずエラー
	i, _ := strconv.Atoi(s)
	fmt.Printf("%T %v\n", i, i)
	//Atoiは返り値がintとerrorの2つを返すので通常は下記のようにエラーハンドリングをつける。今回はerrを使わないのでそれを明示するアンスコを使ってi, _としてる。
	// var s string = "14"
	// i, err := strconv.Atoi(s)
	// if err != nil {
	// 	fmt.Println("ERROR")
	// }
	// fmt.Printf("%T %v", i, i)

	h := "Break It"
	//fmt.Println(h[0]) //アスキーコード出力される
	fmt.Println(string(h[0])) //B
	//文字列はバイト配列でできているので簡単にキャストできる。strconv使わなくてOK。
}
```
>【参考】
現役シリコンバレーエンジニアが教えるGo入門(https://www.udemy.com/share/100BhMB0obeFpbTX4=/)
Firewalld で特定の IP アドレスを拒否する

CentOS 7 で特定の IP アドレスを拒否する手順を解説する。
## lastb
```:出力例
最終ログイン: 1970/01/01 (木) 09:00:00 JST日時 pts/4
最後の失敗ログイン: 2019/06/05 (水) 07:19:18 JST 211.252.85.100から開始日時 ssh:notty
最後の正しいログインの後に 59 回の失敗ログインの試行があります
```
ログインすると失敗ログインの試行があるので `lastb` コマンドで確認する。

```bash
lastb | less
```
```:出力例
root     ssh:notty    211.252.85.100   Wed Jun  5 07:19 - 07:19  (00:00)
root     ssh:notty    211.252.85.100   Wed Jun  5 07:04 - 07:04  (00:00)
root     ssh:notty    211.252.85.100   Wed Jun  5 06:49 - 06:49  (00:00)
```
同じ IP アドレスから不正アクセスの試行が続いていたので IP アドレスを指定して拒否する。
通常は [Fail2ban](https://qiita.com/bezeklik/items/75d93d6bb1770bfa7c2e) で自動的に拒否するとよい。

## whois
```bash
yum --assumeyes install whois
whois 211.252.85.100 | less
whois 211.252.85.100 | grep 'IPv4 Address'
```
```:出力例
IPv4 Address       : 211.252.84.0 - 211.252.87.255 (/22)
```
`whois` または `jwhois` コマンドで IP アドレスの詳細を確認する。

## firewall-cmd で IP 拒否
```bash
firewall-cmd --zone=drop --permanent --add-source=211.252.84.0/22
firewall-cmd --reload
```
`firewall-cmd` コマンド の `--zone` オプションに `drop` を、 `--add-source` オプションで IP アドレスを CIDR 付きで指定することで設定できる。

`--permanent` オプションを指定することで永続的に拒否できるが、 `firewall-cmd --reload` で設定をリロードしないと反映されないので注意。

## 設定確認
```bash
firewall-cmd --get-active-zones
```
```:出力例
drop
  sources: 211.252.84.0/22
public
  interfaces: eth0
```

## 出力ファイル
```bash
cat /etc/firewalld/zones/drop.xml
```
```xml:出力例
<?xml version="1.0" encoding="utf-8"?>
<zone target="DROP">
  <short>Drop</short>
  <description>Unsolicited incoming network packets are dropped. Incoming packets that are related to outgoing network connections are accepted. Outgoing network connections are allowed.</description>
  <source address="211.252.84.0/22"/>
</zone>
```
設定は `/etc/firewalld/zones/drop.xml` に XML 形式で保存される。

## 拒否設定の解除
```bash
firewall-cmd --get-active-zones
firewall-cmd --zone=drop --permanent --remove-source=192.0.2.0/24
firewall-cmd --reload
firewall-cmd --get-active-zones
```
設定を解除するには `--remove-source` オプションで指定する。
GoogleTagManegerのメモ機能を有効活用しましょう

##メモ機能とは？
GTMのタグ、トリガー、変数にメモ機能があります。
これは名前の通り自由にテキストを入力できる機能です。
設定内容の説明や、更新履歴などを記載しておきましょう。
備忘録としてはもちろんのこと、メンバーへの共有、タグ精査などに大変役に立ちます。
メモの内容はコンテナサイズには含まれません。
また、メモに記載した内容は左メニューの検索フォームからの検索対象にはなりません。
メモに記載した内容を検索したい場合は管理画面からJSONとしてコンテナの設定内容一式をエクスポートしてそれを検索することが出来ます。

##メモ機能の使い方
###メモの表示
右上のメニューをクリックし、「メモを表示」を選択します。
![img01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421200/b7418f52-5d1a-f242-d44f-e6abd765f27f.png)

###メモの削除
既に登録してあるメモを削除する場合は
右上のメニューをクリックし「メモを表示」をクリックすると
「メモを削除しますか？」とポップアップが出ますので
「メモを削除」をクリックすると作成したメモが削除されます。
![img02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421200/ca95f7a4-743d-f020-9b5e-97f2adedca87.png)

##メモとして記載した方が良いもの
- 更新履歴（作成日、更新日など）
- 設定内容
- 注意点など特記事項
- スレッドごとにURLを生成するタイプの管理ツール（例えばBacklogなど）のURLを記載
- 依頼元や依頼経緯
- 対象ページ（トリガーや変数の場合は特に記載した方が良い）
    - 「カスタムイベントトリガー」は「どういった場合に（どこから）」呼び出されるのかメモが必要。
    - 「データレイヤー変数」「JS変数」「DOM要素変数」なども同様に対象ページやタイミングが重要だがGTM内だけでは完結していない場合もあるのでメモが必要。
    - 「ファーストパーティCookie」変数もどういう場合に生成されるCookieで、どういった役割を持っているのかなど、メモが必要。


##実際のメモ例
こちらのカスタムHTMLタグ「CHTML ErrorMessage for PC」は、
ページ側で出力されたエラーメッセージをGTMで参照可能な変数に変換するための処理を行っています。
また、エラー発生してる場合はdataLayer.push()関数でtrackErrorイベントを発生させています。
こちらのメモのように計測準備やdataLayerをpushするカスタムHTMLなど、わかりずらいものを
「こういう時に」「こういうことのために」「こういうことをしている」などを記載しておくとメモとして残すメリットがあるでしょう。
![img03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/421200/90c4722b-45fb-6c39-fef0-296e1eac20db.png)

##まとめ
日々膨大の作業の中で、設定したタグを後に見返してみると「これって何のためのタグ、トリガー、変数なんだっけ？」なんてことがありませんか？
貴重な時間を使って曖昧な記憶を辿るより、メモを書く習慣をつけて、無駄な作業を減らしましょう。
きっとメモに助けられる日がくるでしょう！
Vimにポップアップウィンドウが入りました

こんにちわ。
[ゴリラ.vim](https://gorillavim.connpass.com/)を運営している[ゴリラ](https://twitter.com/gorilla0513)です。

Vim 8.1.1391でポップアップウィンドウという機能が入りました。
これは名前の通り、ポップアップウィンドウを出すという機能です。

現在も実装が進められていてまだ完成ではないのですが、良い感じになってきたので紹介していこうと思います。

# どんな感じか？
こんな感じでポップアップウィンドウを出せます。

![popup.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66178/e1f307ce-d56a-1fa5-fbc7-11768c32e22e.gif)

こちらはゴリラ製翻訳プラグインです。
<a href="https://github.com/skanehira/translate.vim"><img src="https://github-link-card.s3.ap-northeast-1.amazonaws.com/skanehira/translate.vim.png" width="460px"></a>

翻訳結果をポップアップウィンドウに表示し、カーソルを動かしたら自動で閉じる様になっています。
わざわざバッファを作成して表示しなくて済むのはめちゃくちゃ便利です。

# ポップアップウィンドウの作り方
とっても簡単です。
これだけで作れます。

```vim
let winid = popup_create("hello gorilla", {})
```

第一引数は文字列、文字列の配列を渡します。
第二引数はポップアップウィンドウのオプションになります。

ポップアップウィンドウを閉じるには`popupc`か`popup_close(winid)`で閉じれます。

## オプション
詳しくはヘルプを引いて頂いたほうがわかりやすいので、ここでは軽く紹介します。

| オプション |設定値| 説明 |
|:-:|:-:|:-:|
| line  | 1, "corsor+1" |ポップアップの位置（横）,"corsor+1"だと現在のカーソルから1セル下になります  |
| col  |1,"cursor+1" |ポップアップの位置（縦）、"cursor+1"だと現在のカーソルから1セル横になります  |
| border  |[1,1,1,1]| ポップアップをボーダーで囲う、数値はボーダーの太さになります。  |
| moved  | "any","word"  |カーソルを動かしたときに自動で閉じるときに使用します|

他にも`filter` などありますがここ割愛します。

# 最後に
ポップアップウィンドウは現在も絶賛実装中でまだまだ良くなっていきます。
今後が楽しみですね。

ちなみに[vim-quickrun](https://github.com/thinca/vim-quickrun)もポップアップウィンドウ対応していたので興味ある方はアップデートして試してみてください。
単純な閉路

## 単純な閉路とは
与えられたN個の点をすべて通り、途中で交差せずに出発点に戻るような道を求める。
この道を**単純な閉路**(simple closed path)とよぶ。

## 計算の手順
1. 与えられた点の中で、yの値が最も小さい点を求めて**基準点**とする。（yが同じ場合はxが小さい方にする）
2. 各点と基準点を結んだ線分と、基準点から水平方向の向きに引いた直線とのなす角を計算する。
3. 2で求めた角度が小さい順に点を整列する。
4. 基準点を始点に整列した順に点を結ぶ

## 計算例
下図のような、点AからHまでの点の集合を考える。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384860/2bd1c8f7-2d39-26b0-31c1-644117245e0e.png">
1. yの値が最も小さい点Cを基準点とする。
2. 各点と点Cを結んだ線分と、点Cから水平方向の向きに引いた直線とのなす角を計算する。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384860/1c64a8e9-6fe5-5a24-34eb-17cefa46a396.png">
3. 2で求めた角度が小さい順に点を整列する。上図によると、C → H → D → A → G → F → B → E の順となる
4. C → H → D → A → G → F → B → E → C の順に点を結ぶ
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384860/cc4be95d-5d7e-483d-b804-cdaff0e6445b.png">
5. 完成 

## プログラム
( AutoLISP )
**比較用の角度を計算する関数**

```scheme
(defun point:GetComparisonAngle (p q / ax ay dx dy theta)
	(setq dx (- (car q) (car p))
		  ax (abs dx)
		  dy (- (cadr q) (cadr p))
		  ay (abs dy)
	)
	(if (zerop (+ ax ay))
		(setq theta 0)
		(setq theta (/ (* dy 1.) (+ ax ay)))
	)
	(if (< dx 0)
		(setq theta (- 2 theta))
		(if (< dy 0)
			(setq theta (+ 4 theta))
		)
	)
	(* theta 90.)
)
```

**単純な閉路となる順番に点を並べ替える**

```scheme
(defun point:GetSimpleClosedPath (points / basePoint)
	;; 基準点を取得(Y値が最小の点)
	(setq basePoint
			 (car
				 (vl-sort points
					 (function
						 (lambda (p q)
							 (if (= (cadr p) (cadr q))
								 (< (car p) (car q))
								 (< (cadr p) (cadr q))
							 )
						 )
					 )
				 )
			 )
	)
    ;; 基準点との角度を比較して点を並べ替える
	(vl-sort points
			 (function
				 (lambda (p q)
					 (<
						 (point:GetComparisonAngle basePoint p)
						 (point:GetComparisonAngle basePoint q)
					 )
				 )
			 )
	)
)

;; < Example >
(point:GetSimpleClosedPath '((11 6) (4 9) (8 1) (19 11) (2 2) (3 16) (12 15) (14 4)))
;; -> ((8 1) (14 4) (19 11) (11 6) (12 15) (3 16) (4 9) (2 2))
```
Ruby入門【クラス】



#クラス
クラス・・・設計図のようなもの
インスタンス・・・クラスから生み出された実体

##インスタンス変数
個々のインスタンス単位に用意される変数。**@変数名**で宣言する。
![スクリーンショット 2019-06-05 7.29.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423914/c06dd165-86fa-fcb0-a2f0-82feeb474f11.png)

##クラス変数
クラスとそのインスタンス全てでしようできる変数。**@@変数名**で表す。インスタンスを生成ごとに初期化処理をしなくていい。
![スクリーンショット 2019-06-05 7.36.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423914/45360593-e7ad-90f9-ea94-0ac08d80f9db.png)

##attr_accessor
インスタンス外から変数を操作したい時に使える。インスタンス変数の設定と取得を別々で行うところを行数を減らして書くことができる。

##クラスの継承
クラスの継承を行うと類似のデータに共通するメソッドをまとまることができる。
親クラスを定義した後に子クラスを定義する。
**class クラス名<親クラス名**で表される。

![スクリーンショット 2019-06-05 7.55.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/423914/e0d8c20f-7fe0-926b-8b46-4032ab079177.png)

##クラスとモジュールの違い
モジュールはメソッドをひとまとまりにするもの。用途や定義方法が似ている。
モジュールはクラスと違って、**インスタンスを生成できない、継承できない**。
オブジェクトに直接関連しない共通処理を複数の箇所から呼び出す時にモジュールを使う。
Google Search Consoleでできること

#概要
[公開したwebアプリケーション](https://snowboardapp.work)のseo対策、モバイルユーザビリティのチェックにGoogel Search Consoleを使いました。
上記webアプリケーションについての説明は[こちら](https://qiita.com/se_fy/items/223515b2049ce534c428)。
Google Search Consoleでできることをまとめます。

#Google Search Consoleとは
Google Search Console は、Google 検索結果でのサイトの掲載順位を監視、管理、改善するのに役立つ Google の無料サービスです。Search Console に登録しなくても Google 検索結果にサイトが表示されるようにすることはできますが、Search Console に登録することで、Google のサイトに対する認識を理解し、改善できるようになります。
引用元：[Search Console の概要](https://support.google.com/webmasters/answer/9128668?hl=ja)

#インデックス登録
インデックスとは、検索エンジンに、自分のWebサイトのページを登録する事を指します。
以下のようにGoogleのクローラーにインデックス登録をリクエストできます。
ページを更新した後に、すぐに反映して欲しい場合もクリック。
<img width="1430" alt="スクリーンショット 2019-06-02 11.52.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410068/9e925ad8-236e-5304-cd20-99a71b0fb397.png">


#検索パフォーマンスの確認
・ページのクリック数
・ページの表示回数
・ページのクリック率(クリック数/表示回数)
・掲載順位
・クエリ（ユーザーが検索時に入力する単語）
<img width="1440" alt="スクリーンショット 2019-06-02 14.21.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410068/58dbc5d1-03d8-7f20-e677-5505db2512c1.png">

#サイトマップの送信
webサイトのページ構成であるサイトマップを作成し、送信することで、Googleのウェブクローラーがサイトを正しく巡回できるようになります。
<img width="1439" alt="スクリーンショット 2019-06-02 11.41.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410068/06b740c8-df6a-4c74-817d-f6382b298399.png">

#モバイルユーザビリティの確認
モバイルフレンドリーではない状態がサイト内に見つかるとレポートに表示されます。
グラフに赤の棒線があるとサイト内に何らかのモバイルユーザビリティーに関するエラーがある状態。
エラー0件で有効のみであれば問題無しです。
<img width="1438" alt="スクリーンショット 2019-06-02 14.30.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/410068/ff45b9ec-da83-2349-f756-f6bba893563c.png">


#Tips
###「http:」,「https:」,「wwwありなし」全てを登録するべき
プロパティを追加する際にドメインで登録していれば問題ありませんが、URLプレフィックスで登録する場合は、同じサイトにアクセスできる全てのURLを登録した方が検索パフォーマンスが上がります。
私の場合、`snowboardapp.work`がドメイン名なので以下４つのURLを登録しています。
・http://snowboardapp.work
・http://www.snowboardapp.work
・https://snowboardapp.work
・https://www.snowboardapp.work

###Google Analyticsを登録していると所有権確認が楽

URLプレフィックスで登録する際に所有権の確認が必要になりますが、Google Analyticsのアカウントコードが登録してあると自動的に所有権を確認してくれます。
Rails6 のちょい足しな新機能を試す30（STI バグフィックス編）

# はじめに

Rails 6 に追加されそうな新機能を試す第30段。 今回は、 `STI バグフィックス` 編です。
Rails 6 では、 STI なクラスでネストしたモデルの更新などが正しくできるようになりました。

Ruby 2.6.3, Rails 6.0.0.rc1 で確認しました。Rails 6.0.0.rc1 は `gem install rails --prerelease` でインストールできます。

```shell
$  rails --version
Rails 6.0.0.rc1
```

# Rails プロジェクトを作る

```shell
$ rails new rails6_0_0rc1
$ cd rails6_0_0rc1
```

# Author モデル と Book モデルを作る

Author モデル と Book モデルを作ります。
Author は、STIなクラスを作れるように、 `type` を持つようにします。
Author は、Book を複数持つことができます。

```shell
$ bin/rails g model Author name type
$ bin/rails g model Book title author:references
```

# author.rb を編集する。

`Author` モデルに `has_many` を追加します。

```ruby:app/models/author.rb
class Author < ApplicationRecord
  has_many :books
end
```
# NonFictionAuthor モデルを作る

`Author` クラスから派生させた `NonFictionAuthor` クラスを作成します。
`has_many` と `accepts_nested_attributes_for` を追加します。

```ruby:app/models/non_fiction_author.rb
class NonFictionAuthor < Author
  has_many :books, foreign_key: :author_id
  accepts_nested_attributes_for :books
end
```

# seed データを作る

今回は、seed データを作ることによって試してみます。
`NonFictionAuthor` と `Book` を1つずつ作ったあと、`author.update` で `Book` オブジェクトの `title` を更新します。

```ruby:db/seeds.rb
author = NonFictionAuthor.create(name: 'Dave Thomas')
book = Book.create(title: 'The Pragmatic Programmer', author: author)

author.update(
  books_attributes: [
    { id: book.id, title: 'The Pragmatic Programmer, 20th Anniversary Edition' }
  ]
)
```

# migration の実行

```shell
$ bin/rails db:create db:migrate
```

# db:seed の実行

```shell
$ bin/rails db:seed
```

# title が更新されたか確認する

Rails console から title が更新されたかどうか確認します。

```irb
bash-4.4# bin/rails c
Running via Spring preloader in process 400
Loading development environment (Rails 6.0.0.rc1)
irb(main):001:0> Book.last.title
  Book Load (0.5ms)  SELECT "books".* FROM "books" ORDER BY "books"."id" DESC LIMIT $1  [["LIMIT", 1]]
=> "The Pragmatic Programmer, 20th Anniversary Edition"
```

title が "The Pragmatic Programmer, 20th Anniversary Edition"  に更新されています。


# Rails 5では、

Rails 5.2.3 で同じことを試すと、更新されません。

```irb
bash-4.4# bin/rails c
Running via Spring preloader in process 296
Loading development environment (Rails 5.2.3)
irb(main):001:0> Book.last.title
  Book Load (0.5ms)  SELECT  "books".* FROM "books" ORDER BY "books"."id" DESC LIMIT $1  [["LIMIT", 1]]
=> "The Pragmatic Programmer"
```

# 試したソース

試したソースは以下にあります。
https://github.com/suketa/rails6_0_0rc1/tree/try030_subclass

# 参考情報

* [What is new in Rails 6.0](https://bogdanvlviv.com/posts/ruby/rails/what-is-new-in-rails-6_0.html)
* [Allow subclasses to redefine autosave callbacks for associated records](https://github.com/rails/rails/pull/33378)
【Salesforce】項目の履歴管理が有効化されている一覧を取得するJS

# tl;td

Lightingの設定画面から。
有効になってる項目ってどれだっけ、みたいな時にすぐ出せると良いな、と。

## code

デベロッパーツールのコンソールから叩いてください。

```js
var elm = document.editPage.elements;
var count = 0;
var label_text = active_item = '';

for(var i=0;i<elm.length;i++) {
	if( elm[i].checked ) {
		// Excluding "Activate ○ ○ history"
		if ( elm[i].id.match('enable')) { continue }
		label_text = document.getElementById( elm[i].id ).labels[0].innerText;
        active_item += label_text + "\n"; 
        count += 1;
	}
}
console.log('Set Counts: ' + count)
console.log(active_item)
```



```
uncaught TypeError: Cannot read property 'elements' of undefined
```
が出るときはデベロッパーツール開きなおすか、form id='editPage'のところをインスペクトして見に行ってあげると取得できると思います。
【RubyOnRails】Cloud9で画像をリンクしようとして苦戦した話

初めまして。Rails初心者です。
標記の件ですが、結論を言うと[こちらの記事](https://qiita.com/Escape_goat/items/e72ef275ad950e1f04f3)で解決できました。


◆ ファイル構造
![qiita.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197143/856a16a4-c426-6929-1070-5b9fc90ba4fd.png)


```ruby:プログラミング経験者が想像するコード
<img src="/app/assets/images/sample1.jpg">
```

```ruby:正解
<%= image_tag("sample1.jpg") %>
```

便利なんでしょうが、慣れるまで時間がかかります。
StyleSheetやJavaScriptファイルなど、外部からファイルを結び付けようとすると
大体「link_tag」が絡んでくるようです。

RailsTutorialなんかをやる場合は、なんとなく流し見するのではなく、このあたり注意して学習していきたいですね（1敗）
Stone Monument

- [Stone Monument](https://atcoder.jp/contests/abc099/tasks/abc099_b)

## 考察(AC)

- 直感的に東に行くほど$b-a$が単調増加すると思った。だから、各$b-a$はユニークになる。
- なので、$b-a=B-A$となるようなBとAを全探索する（[コード](https://atcoder.jp/contests/abc099/submissions/5792000)）



## O(1)で解く

- $\frac{1}{2}(n+1)(n+2) - \frac{1}{2}n(n+1)=b-a$（nは初めから数えてn番目の柱aって意味）
- $n+1=b-a$
- $n=b-a-1$
- なので、柱aの元々の高さは$ \frac{1}{2}n(n+1)$になる(n=b-a-1）
- 元々の高さからaを引けば積雪量が求められる。

### [コード](https://atcoder.jp/contests/abc099/submissions/5792015)

```cpp
#include <bits/stdc++.h>
using namespace std;

#define int long long

int a, b;

signed main() {
	cin >> a >> b;

	int n = b - a - 1;
	int A = n * (n + 1) / 2;
	cout << A - a << endl;

	return 0;
}

```





## メモ

- 解説PDFっぽい解法
- いつか処理を高速化したいときに使えるかもしれないなぁと思った。
- 式変形頭いいなぁ。自然に思いつける気がしないなぁ。
Good Grid

- [Good Grid](https://atcoder.jp/contests/abc099/tasks/abc099_d)

## 考察(AC)

- うーん、わからん。全部試すしかなくないか？
- 全探索はTLEだからメモ化すればいい感じかな？とりま全探索書く。
- 全探索書いてる途中で気づいたけど、メモ化できねぇわ。ある時点でその色に変更することが最適かどうかはその時点ではわからないから。えーん。時間無駄になった
- 考察の方針を変える。
- $(i+j) \% 3 = 0$なら同じ色に、それ以外は別の適当な色で塗るという方針にした（これ誤読）。とりあえずこの方針でコード書いたけど答えが合わない（誤読してるので当然だけど）
- ここで誤読に気づく。modが同じなら同じ色、違うなら違う色に塗ればいいと気づく（気づくの遅すぎて最悪ですが）。
- とりあえず全探索を書く。サンプルも合う。制約小さいしとりあえず投げたらTLE。$O(C^3N^2)$で最大ループ数は大体$10^{10}$回だったからそりゃ間に合わんわ。でも、どこかしら計算量を落とせば行けそうだと思った。
- ここで、色に注目した。色の制約は30くらいで小さい。だからマスに関係なく、一気に処理できるのでは？と思った。mapで管理すればその部分は対数時間で処理できるので$O(C^3 N^2)$が$O(C^3 logC)$になって大勝利（入力らへんの計算量は無視してる）





## 反省

- 問題文を読み取れなさすぎる。問題文を要約すると「マス目を３色に塗り分けたい」ってだけなのに…えーん
- 何も思いつかないとすぐに全探索を書いてしまう。今回はDFS各途中で無理なの気づけたけどそれだけで30分くらいかかったのでダメダメすぎる。引数見てメモ化できなさそうだった時点で切り上げるのが良さげ？
- 1時間もかかってしまった。おえーん。



## 解法

- mod0, mod1, mod2のそれぞれのマスについて、どの色がいくつあるかをあらかじめ求めておく
- mod0の色、mod1の色、mod2の色を決め打つ。そのときに、決め打った色にするためにコストがいくらかかるかを求める。求めた結果を見て答えを更新する。



## [コード](https://atcoder.jp/contests/abc099/submissions/5791900)

- mapじゃなくて配列を使ったら$O(C^4)$になった（[コード](https://atcoder.jp/contests/abc099/submissions/5791968)）

```cpp
#include <bits/stdc++.h>
using namespace std;

#define int long long
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a = b; return 1; } return 0; }

int N, C;
int D[555][555];
int c[555][555];
map<int, int> mp0, mp1, mp2; // map<色, 個数>

// mod0の色、mod1の色、mod2の色を決め打った時の合計コスト
int solve(int zero, int one, int two) {
	int ret = 0;
	// mod0の色を変える合計コストを求める
	for (auto x : mp0) {
		int num = x.first;
		int cnt = x.second;
		ret += D[num-1][zero-1] * cnt;
	}

	// mod1の色を変える合計コストを求める
	for (auto x : mp1) {
		int num = x.first;
		int cnt = x.second;
		ret += D[num-1][one-1] * cnt;
	}

	// mod2の色を変える合計コストを求める
	for (auto x : mp2) {
		int num = x.first;
		int cnt = x.second;
		ret += D[num-1][two-1] * cnt;
	}

	return ret;
}

signed main() {
	cin >> N >> C;
	for (int i = 0; i < C; i++) {
		for (int j = 0; j < C; j++) {
			cin >> D[i][j];
		}
	}
	for (int i = 0; i < N; i++) {
		for (int j = 0; j < N; j++) {
			cin >> c[i][j];
			int I = i+1, J = j+1;
			// mod0, mod1, mod2ごとにその色が何個あるかを求める
			if ((I+J)%3 == 0) {
				mp0[c[i][j]]++;
			}
			if ((I+J)%3 == 1) {
				mp1[c[i][j]]++;
			}
			if ((I+J)%3 == 2) {
				mp2[c[i][j]]++;
			}
		}
	}

	int ans = 1e18;
	for (int c0 = 1; c0 <= C; c0++) { // mod0の色
		for (int c1 = 1; c1 <= C; c1++) { // mod1の色
			for (int c2 = 1; c2 <= C; c2++) { // mod2の色
				if (c0 == c1) continue;
				if (c0 == c2) continue;
				if (c1 == c2) continue;

				int t = solve(c0, c1, c2);
				chmin(ans, t);
			}
		}
	}

	cout << ans << endl;

	return 0;
}
```





## 要点

- 問題文の大枠を掴む
  - 今回の場合、「マスを３色に塗り分けたい」って感じになる
- 前処理で計算量を落とす

## その他記事
- http://drken1215.hatenablog.com/entry/2018/07/22/133200
- https://www.hamayanhamayan.com/entry/2018/06/16/091039
Twitter漫画「不器用な先輩。」が投稿される度にお知らせをしてくれるPythonスクリプトを作った

#Twitter漫画「不器用な先輩。」が投稿される度にお知らせをしてくれるPythonスクリプトを作った。
工藤マコト先生の描く「不器用な先輩。」を毎回Twitter巡回で見つけるのが面倒なので、自動的にお知らせするようにしてみた。(2019年6月10日時点バージョン)

##必要なもの
- Tweepy(Pipでインストール)
- mpg123(Homeberw、apt-getでインストール)
- TwitterのAPIに必要な情報

上記のインストールは他のウェブサイトの説明が優秀なので割愛。

###当のコード
```Python
import os
import tweepy

os.chdir(os.path.dirname(__file__))

# 認証キーの設定 https://masatoshihanai.com/php-twitter-bot-01/ を見ながら取得してください
consumer_key = "自分のconsumer_key"
consumer_secret = "自分のcustomer_secret"
access_token = "自分のaccess_token"
access_token_secret = "自分のaccess_tocken_secret"

# OAuth認証
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)

# APIのインスタンスを生成
api = tweepy.API(auth)

status_list = api.user_timeline(screen_name="m0721804")
#status_list = api.user_timeline(screen_name="Jikkenndesu")

with open("database.txt") as f:
    database_number = f.readline().strip()
    #　Number in database.txt is latest number on Twitter
for i, status in enumerate(status_list):
    with open("database.txt") as f:
        latest_number = f.readline().strip()
        #print(last_number)
        #last_number = "15"
        if "不器用な先輩。" + database_number in status.text:
            print("新規掲載！")
            os.system("mpg123 -C  fanfare.mp3")
            latest_number = int(database_number) + 1
            with open("database.txt", "w") as g:
                g.write(str(latest_number))
            break
    if database_number == str(latest_number):
        print("不器用な先輩。" + str(latest_number) + "話は既読です。")
        break
```

現時点の最新話は15話なので、database.txt は15としておく。
```database.txt
15
```

実行
```ターミナル
python main.py
```

これで、cronか何かで自動実行するようにすれば、「不器用な先輩。」がアップロードされる度に音でお知らせしてくれる。便利！！

#まさかり待ってます！
GO言語で"Hello World!"をHerokuへデプロイする。

#はじめに

Herokuの公式の手順が動画だったのでタイピングするのが面倒だなと思い記事にしました。

Heroku公式
https://jp.heroku.com/go

動画のみ
https://player.vimeo.com/video/143343818?api=1&byline=0&title=0&portrait=0&frameborder=0&player_id=go-hello-world&autoplay=1&loop=1

# 環境情報
OS X Mojave
go 1.12.5
GOPATH `~/go`

#手順

`~/go/src`にhelloディレクトリを作成します。その中に`main.go`を作成して以下のようにします。

```go
package main

import (
	"io"
	"net/http"
	"os"
)

func hello(w http.ResponseWriter, r *http.Request) {
	io.WriteString(w, "Hello, World!")
}

func main() {
	port := os.Getenv("PORT")
	http.HandleFunc("/", hello)
	http.ListenAndServe(":"+port, nil)
}

```

次にgovendorをインストールして初期化します。

```sh
# 動画にはないですが、入ってない人がほとんどだと思うので手順に追加
$ go get -u github.com/kardianos/govendor

$ cd ~/go/src/hello
$ govendor init
```

ソースをgitの管理下に置いてHerokuへデプロイ

```
$ git init && git add -A
$ git commit -m "init"
$ heroku create
$ git push heroku master
$ heroku open
```

`Hello World!`が表示されれば成功です。
pluckよりもmapのほうが高速なケース⇦今もそうなのか？

以下の記事(pluckよりもmapのほうが高速なケース)を見つけ、Railsのバーションアップがなされ今はどうなのか気になったので再計測しました。
-https://qiita.com/metheglin/items/18064851a8f00dab67f8

結論から言うと、結果は以前の記事の結果と同じ感じでした。

##pluckを使うべきケース
```
Profile.all.pluck(:id)
  # => SELECT "profiles"."id" FROM "profiles"
Profile.all.map(&:id)
  # => SELECT "profiles".* FROM "profiles"
```

####Benchmark
```
n = 2000
Benchmark.bm do |x|
  x.report { n.times { Profile.all.pluck(:id) } }
  x.report { n.times { Profile.all.map(&:id) } }
end
```

|             |    user  |  system  |  total  |     real|
|:------------|---------:|---------:|--------:|--------:|
| pluck(:id)  | 5.874142 | 1.085963 | 6.960105| 8.259476|
| map(&:id)   | 60.618729| 1.614024 |62.232753|65.682491|


##mapを使うべきケース
####Benchmark
```
profiles = Profile.all
n = 2000
Benchmark.bm do |x|
  x.report { n.times { profiles.pluck(:id) } }
  x.report { n.times { profiles.map(&:id) } }
end
```
|             |    user  |  system  |  total  |     real|
|:------------|---------:|---------:|--------:|--------:|
| pluck(:id)  |  5.392492|  0.977601| 6.370093| 7.496229|
| map(&:id)   | 1.595164 |  0.016207| 1.611371| 1.621283|

##Environment
※OSはMac OSX ver.10.14.5
※CPU2.3GHz Intel Corei5 / メモリ8G 
※DBはMySQL
※Railsバージョン "5.0.7.2"