OmniAICreator/Qiita-1.07M huggingface dataset:
FuelPHP1.8で大量のデータを処理する

![image.png](https://qiita-image-store.s3.amazonaws.com/0/94360/14b658f8-9e99-c158-8a11-6875bfcd2d92.png)

## 問題

データ変換のためのバッチ処理などのように、FuelPHPで大量のデータを総当たりで処理しようとするとメモリが足りずエラーになることがある。ギガを超える量のメモリを割り当てても動作しないので調べてみた。

```php
$query = DB::select('*')->from('member_data')->as_object()->execute();
```
データの件数は12万件くらい。ORMはオーバーヘッドが大きいのでクエリビルダーで書いたけど、それでも全然軽くならない。

```
Fatal Error!

ErrorException [ Fatal Error ]:
Allowed memory size of 134217728 bytes exhausted (tried to allocate 4194312 bytes)
COREPATH/classes/database/pdo/connection.php @ line 300
```

エラーの内容は上記のとおり。メモリーを使い切ってしまっている。

```php
// Convert the result into an array, as PDOStatement::rowCount is not reliable
if ($as_object === false)
{
    $result = $result->fetchAll(\PDO::FETCH_ASSOC);
}
elseif (is_string($as_object))
{
    $result = $result->fetchAll(\PDO::FETCH_CLASS, $as_object);
}
else
{
    $result = $result->fetchAll(\PDO::FETCH_CLASS, 'stdClass');
}
```
https://github.com/fuel/core/blob/1.8.0.4/classes/database/pdo/connection.php#L286-L298
FuelPHPのデータアクセスの仕組みはこんなふうになっている。fetchAllで全てのデータを一気に取り込んで配列化する。メモリを贅沢に使ってパワーで回す感じ？12万件のデータを処理するバッチだったら、12万件のデータで構成された巨大な配列を生成する。

メモリさえあればFuelPHPは軽快に動作するみたいだけど、数十万件を超える規模のデータをバッチで回すようなケースだと、いくらメモリを足しても限度がある。

## 解決方法

下記のように書き換えてみた。

```php
$db = Database_Connection::instance()->connection();
$result = $db->query('select * from member_data');
while($row = $result->fetch(PDO::FETCH_OBJ))
{
    echo sprintf('ID：%s 名前：%s<br />',$row->id,$row->name);
}
```

結果セットだけ取り寄せてカーソルを進めながら１件ずつ処理する。これならメモリを食わない。PDOとか生SQLをゴリゴリ書く人ならよく使う書き方。

一度ですませていたキャッチボールがループ回数ぶん増えるため、DBサーバとWebサーバが物理的に異なるロケーションにある場合は遅くなりそうだけど、メモリ不足で落ちることはなくなる。今回はレスポンスを気にしない変換バッチなので問題ない。

```php
$db = Database_Connection::instance()->connection();
$result = $db->query(
    DB::select('*')->from('member_data')->compile()
);
while($row = $result->fetch(PDO::FETCH_OBJ))
{
    echo sprintf('ID：%s 名前：%s<br />',$row->id,$row->name);
}
```

クエリビルダーでFuelっぽく書きたいなら、上記のようにcompile()を使う。

https://github.com/fuel/core/blob/1.9/develop/classes/database/pdo/result.php
開発中のv1.9ではこんな処理が加わっている。このファイル自体がv1.8の時点では存在しない。どうしたいのかまだよく分からないけど、もしかすると将来はこれが使えそう。
Slackで特定チャンネルの投稿を一括で削除する

# 概要
タイトル通りですが，Slackの特定のチャンネルの投稿を一括で削除するためのPythonスクリプトです．
もう少し工夫して，特定の条件で削除の条件を絞り込んだりbotにしたりが考えられますがとりあえず，基本的な部分だけをまとめます．

# 準備
##　Slack APIを使うためのTOKEN発行
Slackに関する記事は多いですが，最近若干仕様が変わっているっぽいです(?)．

[Slack Web API](https://api.slack.com)こちらからアプリの作成を行なって下さい

<img width="843" alt="0.png" src="https://qiita-image-store.s3.amazonaws.com/0/21312/53ab09f4-6fcc-f9fa-c844-b208a3970c77.png">

<img width="841" alt="1.png" src="https://qiita-image-store.s3.amazonaws.com/0/21312/5bcf2474-227d-0f44-d444-70fdf51e3f7f.png">

<img width="841" alt="3.png" src="https://qiita-image-store.s3.amazonaws.com/0/21312/6cee518f-3971-887e-0ddf-9fb43f884a44.png">

<img width="839" alt="4.png" src="https://qiita-image-store.s3.amazonaws.com/0/21312/94a3bf34-b541-d6e1-c099-97cc230966d3.png">

<img width="839" alt="5.png" src="https://qiita-image-store.s3.amazonaws.com/0/21312/18c1212b-0461-b085-466c-0bcd6d11952c.png">

今回の場合はこの3つの権限を与える必要があると思う

CHANNELS

* Access user’s public channels[channels:history]
* Access information about user’s public channels[channels:read]

CHAT

* Send messages as user[chat:write:user]


<img width="840" alt="Slack_API__Applications___mdg_Slack.png" src="https://qiita-image-store.s3.amazonaws.com/0/21312/2935aa38-3e04-6bfd-b193-273ffb3c9431.png">

この`xoxp-XXXXXXXXXX-XXXXXXXXXX-XXXXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXXX`

みたいな部分がアクセストークンになります．

##　環境
* Python 3.6.3

# コード

```Python
# encoding: utf-8

import requests
import json
from time import sleep

SLACK_ACCESS_TOKEN = "xoxp-ほげ-ほげ-ほげ-ほげ"

def main():
    res = requests.get('https://slack.com/api/channels.list?token=' + SLACK_ACCESS_TOKEN)
    channelsList = json.loads(res.text)
    channels = channelsList['channels']
    delete_channel_id = 0

    for c in channels:
        if c['name'] == '消したいチャンネル名':
            delete_channel_id = c['id']

    while True:
        res = requests.get('https://slack.com/api/channels.history?token=' + SLACK_ACCESS_TOKEN + '&channel=' + str(delete_channel_id) + '&count=' + '1000')
        channelMessages = json.loads(res.text)
        message_list = []
        for m in channelMessages['messages']:
            requests.post('https://slack.com/api/chat.delete?token=' + SLACK_ACCESS_TOKEN + '&channel=' + str(delete_channel_id) + '&ts=' + m['ts'])
            sleep(1)

if __name__ == "__main__":
    main()
```

# そのほか
というか，全ていらないならチャンネルごと削除しちゃうのが早いですが，何かまとめて削除したい場合の参考になれば．
[体験記]休学中の東大生がRailsチュートリアルをやってみた

# 自己紹介
- 現在大学二年生。
- インターンにて日々勉強中
- 一年間休学予定
- Rails歴は半年ちょっと
- Railsチュートリアルを一人でやるだけではつまらないので、日記として書いていきます
    - ツッコミどころがたくさんあると思います。ツッコミ待ってます。

# Railsチュートリアルって？
- 公式は[こちら](https://railstutorial.jp)
    - ここのスライドが非常にわかりやすいです。
- Ruby on Rails初心者のための書籍
    - でもすべてoWeb上に上がっている！
    - しかも、完全無料！
- Twitterのようなアプリを作成しながらRailsを学べる
- ドキュメントが充実
    - ソースよりも文章が充実している
    - 体系的に理解したい人へ
- 誰もが一度は聞いたことがあるチュートリアル
    - Railsでググるとすぐ出てくる
    - 有名なので、いろんな人がいろんなヒントや解説を書いている
- 意外と難しいらしい
    - ガチな初心者がやると死ぬらしい
        - Gitやテスト、Herokuまで含まれてる
    - 一通りできる人が改めて勉強する時に

# Youはどうしてチュートリアルを？
- 改めて自分で勉強したくなった
    - 業務ではアプリを1から全て作ることはできない
- ソース読んでるの退屈じゃない！？
    - 有名なgemのソースなどを読むことも考えたけど、自分で作る方が楽しい！（はず）
- チュートリアルくらいの有名さなら、「チュートリアルやりました！」って他の人に言える（不純な動機）

おし！やるぞ！！

# 第一章 ゼロからデプロイまで
第一章でいきなりデプロイするのか！と言う声が聞こえそう（僕も叫んだ）

## 思ったこと
- 長い！！！日本語が！！！
    - コード書くまでに20分くらい読んだ
- アプリを三つ作るらしい
    - 第一章でhello_app
    - 第二章でtoy_app
    - 第三章からsample_app

## やってみる！
- ローカルではなくcloud9でやるらしい
    - 現在のURLはもう新規登録できなくて、AWSの方でやった
    - チュートリアルの[リンク](https://c9.io/signup)ではなく、[AWS](https://aws.amazon.com/jp/cloud9)の方です
TypeScriptでFizzBuzz（generator, destructuringなどして)

TypeScriptでFizzBuzzしてみました。(target:ES2015以上）
targetがES5以下だとArray#keys()が空オブジェクトになってrange返してくれないのにちょっとはまりました。

```fizz.ts
class Fizz {
    public static spec: Array<[number, string]> = [[15, "FizzBuzz"], [5, "Buzz"], [3, "Fizz"]];
    public static *buzz(size: number) {
        for (const i of Array(size).keys()) {
            const [_, result] = Fizz.spec.find(([n, s]) => i % n === 0) || [0, i.toString()];
            yield result;
        }
    }
}

Array.from(Fizz.buzz(20)).forEach((i) => console.log(i));

```
jQuery display:noneのエレメントに.width().height()を使う時の注意

ボタンで表示/非表示ができるセル状に並んだボックスの、横一列で一番高いheightで高さを揃えようと、何も考えずに以下のように

```javascript
//高さ調整
var max_height = 0;
_parents.each( function(){
    if ($(this).height() > max_height) {
        max_height = $(this).height();
    }
});
_parents.height(max_height);
```

とやっていたら、もともと**display:inline-block**がCSSで定義されているのに、非表示から表示へ切り替えると
　■ ■ ■
と並んでいたものが
　■
　■
　■
となってしまう。

ブラウザでエレメントを眺めてみると、非表示のボックスのstyle属性に**``display:block``**が追加されていました。

謎を解明しようとググってみると[jQueryのリファレンス](http://api.jquery.com/height/)に以下の記述がありました。
**Note:** Although **``style``** and **``script``** tags will report a value for **.width()** or **.height()** when absolutely positioned and given **``display:block``**(抜粋)

てきとーほんやく
「残念ながら、**.width()**や**.height()**は値の報告の際に、**``style``**タグと**``script``**タグを絶対座標にして**``display:block``**を付与します」

なんと、破壊的なファンクションだったのね・・・
PIL で日本語の文字を書く

ツルータイプのフォントを使って PIL で画像を作成しました。

![out01.png](https://qiita-image-store.s3.amazonaws.com/0/179446/f23a3c02-5727-7f88-5e8d-a739c867610e.png)


```py:draw_text.py
#! /usr/bin/python
# -*- coding: utf-8 -*-
#
#	draw_text.py
#
#					Mar/20/2018
#
# ------------------------------------------------------------------
import sys
import numpy

import PIL.Image
import PIL.ImageDraw
import PIL.ImageFont

# ------------------------------------------------------------------
def draw_text_at_center(img, text):
	draw = PIL.ImageDraw.Draw(img)
	font_ttf = "/usr/share/fonts/OTF/TakaoPMincho.ttf"
	draw.font = PIL.ImageFont.truetype(font_ttf, 80)

	img_size = numpy.array(img.size)
	txt_size = numpy.array(draw.font.getsize(text))
	pos = (img_size - txt_size) / 2

	draw.text(pos, text, (0, 0, 255))

# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
img = PIL.Image.new("RGBA", (400, 300))
text = "こんにちは"
draw_text_at_center(img, text)
img.show()
filename = "out01.png"
img.save(filename)
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```
ASM(Android Screen Monitor)使ってみた

# 概要
Androidアプリのテストをエミュレーターではなく実機で行なう際、PCと実機を繋ぎPC上に実機の画面を表示したかったのでASM(Android Screen Monitor)を使ってみた。

<img src="https://qiita-image-store.s3.amazonaws.com/0/244012/e40920c9-59be-0f87-d5cd-1b96e3d00ef9.png" width=50%>

# 感想
- PCからもマウスで操作可能なので便利
- キャプチャ等エビデンス取りに使える
- 不具合再現手順をSkype等画面共有して伝えるのに便利

【参考】
以下サイトを参考にさせていただきました。
http://www.vuzix.jp/dev/asm.html
【2018年3月】SICPを始めるためのScheme処理系準備メモ


Rails がメイン言語の会社で SICP 読書会を始めることになったので、参加者の敷居を下げるために Scheme 処理系の準備メモです。[^1]

[^1]: カッコが多い言語が好きな方は環境構築するのは苦ではないかもしれませんが...

# どの処理系にするか？

Scheme にはたくさんの処理系が存在していて[^2]、最初はちょっと迷いました。

が、Web で調べたり、自社で SICP 読書会をやってる @lagenorhynque さんのおすすめもあって、Racket を使うことにしました。

[^2]: [フムフムヌクヌクアプアアの表紙](https://www.oreilly.co.jp/books/9784873113487/)でおなじみの Gauche や GNU Guile、Chickin、MIT/GNU Scheme など、ちょっと調べるだけでもいっぱいあることがわかります。

## 選んだ理由

- mac だと homebrew で簡単にインストールできる（弊社のエンジニアは mac ユーザが大多数を占めているので）
- DrRacket という IDE もついてくるので簡単にインタラクティブな開発が体験できそう[^3]
- [SICP Collection](https://docs.racket-lang.org/sicp-manual/index.html) というものが用意されていて、素の Scheme だと大変なところがカバーされているらしい（※ 要出典）

[^3]: 今回は気軽に SICP 学習を進めるられることに重きをおいてます

# インストール

処理系のインストール

```console
$ brew cask install racket
```

SICP Collection パッケージのインストール

```cosole
$ raco pkg install sicp
```

DrRacket を立ち上げて、コードを入れて Run すると、ちゃんと動くことが確認できます。
これで安心して SICP 読書会を進められそうですね

```console
$ drracket
```

![Untitled_-_DrRacket_and_1__tmux___Users_fumitaka_tokumitsu_works_classi_video__tmux_.png](https://qiita-image-store.s3.amazonaws.com/0/13998/d8b6d764-aac8-a23c-66a7-c2fe50b7a3e4.png)

---

DrRacket 使わないよ〜という人向け情報

# ミニマムインストール

DrRacket 使わない（全部 console 上の REPL でやる or Emacs & geiger 使う）という人は、以下のように必要最低限インストールしてください。

```cosole
$ brew install minimal-racket
$ raco pkg install sicp
```

REPL を開くときに lang: sicp を指定すれば OK

```console
$ racket -I sicp
```

![1__racket___Users_fumitaka_tokumitsu__racket_.png](https://qiita-image-store.s3.amazonaws.com/0/13998/53e107ac-fafa-7a2d-9da7-15b65d4b0a79.png)

# 各種エディタと連携する

## Emacs

[geiser](https://github.com/jaor/geiser) を使うと Cider や Slime のような感じで開発ができるようになります。

use-package を使っている人は以下の設定を .emacs.d に追加してください

```elisp
(use-package geiser
  :config
  (setq geiser-active-implementations '(racket)))
```

その他のインストールは本家サイトをご確認ください
→ http://www.nongnu.org/geiser/geiser_2.html#Installation

※ minimal-racket だと mzlib/thread が無いといって怒られるかもしれないので、その場合は ↓ のパッケージを入れれば OK

```console
$ raco pkg install compatibility-lib
```

こんな感じ
![Pasted_Image_2018_03_20_19_49.png](https://qiita-image-store.s3.amazonaws.com/0/13998/3862ceff-6765-d263-5133-9dd6f09eb20d.png)

マクロ展開もできます
![image.png](https://qiita-image-store.s3.amazonaws.com/0/13998/6dc45e91-49b3-d563-1761-c5518db76d4c.png)

---

**注意**
Emacs 以外はは未検証なのでちょっと調べて見つけたリンクだけ張っておきます...
どなたか編集リクエストで教えていただけるとうれしいです

## Vim

- https://github.com/wlangstroth/vim-racket

## Atom

- https://atom.io/packages/atom-ide-racket
- https://atom.io/packages/language-racket

## VS Code

- https://marketplace.visualstudio.com/items?itemName=karyfoundation.racket
ローカルで Rails アプリを production モードで起動する

# はじめに

Rails アプリケーションをローカル PC で production モードで起動する際の手順を整理しようと思います。

基本的に、サーバーにデプロイする前に、手元で productionモードで動かして、エラーは潰しておくのが良いと思います。

**※ API サーバーだけであれば、↓↓ に最新のバージョンで書き直したので、そちらを御覧ください。**
[ローカルで Rails アプリを production モードで起動する（API サーバー編） \- Qiita](https://qiita.com/mokuo/items/207144d6bb18967a9f62)

# バージョン

Ruby : 2.4.2
Rails : 5.1.4
React : 16.2.0
Redux : 3.7.2
Webpacker : 3.3.1
Heroku CLI : heroku-cli/6.15.35-cf39a29 (darwin-x64) node-v9.8.0

# 手順

## SECRET_KEY_BASE を設定する

`bin/rails secret` で出力された値を、環境変数 `SECRET_KEY_BASE` に設定する。
私は `dotenv-rails` gem を使用しているので、 `.env` に設定する。
※ `dotenv-rails` を使用していない場合 `export` とかで設定すれば良いはず。


```:.env
SECRET_KEY_BASE= xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

**参考**

- [Rails セキュリティガイド \| Rails ガイド](https://railsguides.jp/security.html#%E3%82%BB%E3%83%83%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%B9%E3%83%88%E3%83%AC%E3%83%BC%E3%82%B8)

## アセットプリコンパイル

```bash
$ RAILS_ENV=production bundle exec rails assets:precompile
```

ここで、実は複数回エラーになりました。詳細は以下をご覧ください。

- [Webpacker を 3\.0\.2 から 3\.3\.1 に上げたらアセットプリコンパイルで3連続エラーになった \- Qiita](https://qiita.com/mokuo/items/e07ab3f4531ba8108bd4)
- [アセットプリコンパイルで open\-iconic の読み込みエラー \- Qiita](https://qiita.com/mokuo/items/95dcd2a9dbfd833ab320)

## DBのセットアップ

### production 用の DB とユーザーを作成する

```bash
$ bin/rails db
mysql> create user 'your_user'@'localhost' IDENTIFIED BY 'your_password';
mysql> select User,Host from mysql.user;
+----------------+-----------+
| User           | Host      |
+----------------+-----------+
| mysql.sys      | localhost |
| your_user      | localhost |
| root           | localhost |
+----------------+-----------+
3 rows in set (0.00 sec)

### 権限設定
mysql> create database `your_database`;
mysql> use your_database;
mysql> grant all on * to 'your_database'@'localhost';
mysql> show grants for 'your_database'@'localhost';
+----------------------------------------------------------------------------------------------------------------+
| Grants for elm-asp-manager@localhost                                                                           |
+----------------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO 'pomodoro-rails'@'localhost'                                                            |
| GRANT ALL PRIVILEGES ON `pomodoro-rails_production`.* TO 'pomodoro-rails'@'localhost'                        |
+----------------------------------------------------------------------------------------------------------------+
mysql> exit
```

### database.yml の設定

先ほど作成したproduction用のDBユーザー・パスワードを `database.yml` に設定する。
`database.yml.sample` などを作成しておき、 `database.yml` は `.gitignore` しておくと良い。

### DBマイグレーション

```bash
$ RAILS_ENV=production bundle exec rails db:migrate
$ RAILS_ENV=production bundle exec rails db:seed # seedデータがない場合は不要
```

## サーバーを production モードで起動する

```bash
$ bundle exec rails s -e production
```

エラーなくアクセスできればOK!!
word2vecを実装してみて間違えたことリスト

[pytorch](http://pytorch.org/)を使ってword2vecを実装してみたので、実装しながら陥ったバグや大変だったとこをまとめます。

## 一覧

1. modelの保存方法
2. 最大化を最小化を間違えた
3. negative sampling用のtable作成
4. 初期値

## modelの保存方法

そのままモデルを保存するとGPU情報が含まれてしまい、ロードするときに自動的にGPUに乗ってしまう問題。
https://qiita.com/jyori112/items/aad5703c1537c0139edb
↑でまとめました。

## 最大化と最小化を間違えた

word2vec (CBoW)の最適化関数は

```math
\mathcal{O}=\log\sigma(w\cdot h)+\sum_{p=1}^P\log\sigma(-w_p\cdot h)
```

ですが、これは**最大化**。他のDeep Learning用のライブラリと同様にpytorchでも普通は**最小化**をするので、-1を掛けて

```math
\mathcal{O}=-\log\sigma(w\cdot h)-\sum_{p=1}^P\log\sigma(-w_p\cdot h)
```

を**最小化**するようにプログラムを組む必要がある。

## negative sampling用のtable作成

各ステップごとにnegative sampleを確率的に選ぶ必要がありますが、`np.random.choice`などを使うと非常に遅い。
そこで、事前に用意したtableからランダムにサンプルする。

実装するのが意外と大変で数時間溶ける。

いろいろ工夫して最終的にできたものがこちら。

```python:build_neg_table
def build_neg_table(self, power=3/4, table_size=10000000):
    powered_sum = sum(count ** power for wid, count in self.id2count.items())
    table = np.zeros(shape=(table_size, ),dtype=np.int32)

    idx = 0
    accum = 0.0

    for wid, count in self.id2count.items():
        freq = (count**power) / powered_sum
        accum += freq * table_size
        end_idx = int(accum)
        table[idx: int(accum)] = wid
        idx = end_idx

    return table
```

## 初期値

word2vecの学習では初期値が結果に大きく影響を与える。
pytorchのデフォルトの初期化では値が大きすぎて学習できないので、自前で実装。

```python
# Make embeddings
self.center_embed = nn.Embedding(n_vocab, dim, padding_idx=0)
self.context_embed = nn.Embedding(n_vocab, dim, padding_idx=0)

# Initialize Embeddings
self.center_embed.weight.data.uniform_(-0.5 / dim, 0.5 / dim)
self.context_embed.weight.data.zero_()
```

## 最後に

ニューラル系の実装のデバッグはどうやったらいいのか未だにわからない。

ソースコードは
https://github.com/jyori112/pytorch-word2vec
においてあります。
Talend Tips - tSendMail on EC2

TalendのtSendMailをEC2で利用する際にハマったので、対応方法を残しておきます。

# TL;DR

TalendのtSendMailをEC2で利用する際は/etc/hostsにちゃんとホスト名を書く

# 対象読者 or 前提条件 or 環境

Talendを知っている人。
確認環境は以下の通りですが、JavaMailで生じる一般的な事象だと思います。

- Talend Open Source for Big Data 6.5.1
- SES

```bash
$ cat /etc/system-release
Amazon Linux AMI release 2017.09
```

# 内容

## なにも設定しない場合のエラー

tSendMailにSESのSMTP設定を行ってメール送信を行うと以下のエラーが発生します。

```bash
javax.mail.MessagingException:501 Syntax: HELO <hostname>
```

## 対処方法
/etc/hosts に自ホスト名を明記します。
※以下の「ip-10-10-10-100」の箇所

```bash:/etc/hosts
127.0.0.1   ip-10-10-10-100 localhost localhost.localdomain localhost4 localhost4.localdomain4 AWSserver
::1         localhost6 localhost6.localdomain6
```

# 参考

- [技術めも - JavaMailでの501エラー](https://www.walksocket.com/archives/359)
世界最速で「Docker + PHP7 + CentOS7 +セキュリティーが担保されている]環境の構築方法

#答え

```shell:実際のコマンド
$ s2i build --copy ./html centos/php-70-centos7 php-image
$ docker run -p 80:8080 php-image
```
```shell:引数の説明
$ s2i build --copy "ドキュメントルートに配置したいソースコードがあるローカルフォルダ" centos/php-70-centos7 "docker イメージネーム"
$ docker run -p 80:8080 "docker イメージネーム"
```

以上、「Docker + PHP7 + CentOS7の環境を世界最速で作る方法」でした。

これで、http://localhost/
に接続できます。

#ここまでの経緯
[Docker + PHP7 + CentOS7]この環境を作りたいなと思って、色々と調べていて、個人でDockerのイメージをアップされている方の記事などを参考にさせて頂いていたのですが、私が一番気に食わなかったのが、ほとんどの情報が[--privileged]このオプションを指定してコンテナを特権モードで起動させていることです。

これは[systemctlでサービスの自動起動をon]→[/sbin/init]でサービスを起動させているからです、これをするためには特権モードが必要となります。

これは問題あるのではないか、コンテナから様々な資源にアクセスできてしまう、セキュリティ的に問題があるので、きっと別の方法があると思い、色々調べて見つけました。

#解説
dockerのインストールは飛ばします。

##s2i(source-to-image)
s2iとはソースからdockerイメージを作ってくれるフレームワークです。
これを用いて、CentOSが公式に様々な環境を用意してくれています。
https://hub.docker.com/u/centos/

**CentOS公式**これ重要
これだけで何も考えなくてもいいww

###インストール方法

```shell:いつもおなじみの
$ brew install source-to-image
```


今回はPHPと書きましたが、[python,ruby,nodejs]など様々な環境を用意してくれているので、上に書いたものと同じイメージでサクッと開発環境作れてしまいます。

###仕組みの概要
CentOSが開発環境を丸っと用意してくれているので、実際のアプリのソースコードだけ引数で渡してあげて、イメージを作っています。
で、そのイメージでコンテナを立ち上げるだけ。

###サービスの起動の仕方
もちろん特権モードの必要なくサービスが起動されるようになっています。
ソースコードを覗いてみると
[exec httpd -D FOREGROUND]
でサービス起動していました。
直接起動させているから特権モード必要ないわけですね。
僕はこれを探していました。

#まとめ
簡単に説明させていただきましたが、s2iコマンドでは今回の様なローカルのソースコードだけではなく、github上のリモートのソースコードを指定してイメージを作成することも可能です。
また、「centos/php-70-centos7」イメージも外側からApatchの設定をカスタマイズできるので、柔軟な設計になってます。
詳しくはこちらを参照ください
https://hub.docker.com/r/centos/php-70-centos7/
GitのRemote名変更（メモ）

# Remoteの追加
下記でoriginに、`https://xxxxxx/yyy.git`　を登録することで、pushをするときに、`git push origin master`などとすることで、GitHubなどに登録することができる。そうでなければ、毎回URLを打つ必要がある。便利ですね。

```:
git remote add origin https://xxxxxx/yyy.git
```

# 登録URLの変更
```:
git remote set-url origin https://zzzzz/wwww.git
```

# Remote名の変更
```ruby:
git remote rename origin newone
```
originからnewoneに名前を変更

# Remoteの削除
```:
git remote rm origin
```
originを削除

# 全てのRemoteを表示
```:
git remote
```

# 全てのRemoteの詳細を表示
```:
git remote　-v
```

# 特定のRemoteの超詳細を表示
```:
git remote origin
```

# Remote Trackingを表示
```:
git branch -vv
```
# 追記

## Remote Tracking Branch(追跡ブランチ)の方法

```
git checkout --track origin/develop  #ブランチ作成時、ブランチ名は同じ
git checkout -b new_name origin/develop　　#ブランチ作成時、ブランチ名指定
git branch --set-upstream-to origin/develp(とか) 　#ブランチがすでにあり、あとから追跡する時
```
## Remote Branchの削除
無事マージされたら、リモートブランチが不要になったら、削除してあげるのは人情かもしれませんね。ローカルもいらないかもしれません。
どんどん増えていきますから。下記コマンドで、削除してあげましょう。GitHubとかだったら、GUI画面で削除するかもしれませんね。

```
git push origin :削除したいbranch
```
コロン（：）の前は、空白です。これは、「こっちの (何もなし) で、向こうの [削除したいbranch] を更新しろ」と言っていることになります。なので、消えてしまうわけです。  `git push -D` とかでもできますよ。


参考
[5 Git のブランチ機能 - リモートブランチ](https://git-scm.com/book/ja/v1/Git-%E3%81%AE%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E6%A9%9F%E8%83%BD-%E3%83%AA%E3%83%A2%E3%83%BC%E3%83%88%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81)

##追記
例では、originをいろいろ変えていますが、削除などはoriginでやらないように。
pigpioをcmakeとともに使う

# pigpioをcmakeとともに使う

Raspberry Pi の GPIO をとても簡単・便利・お手軽に利用できる pigpio([本家](http://abyz.me.uk/rpi/pigpio/index.html), [GitHub](https://github.com/joan2937/pigpio) ) というライブラリがあります．

このライブラリを cmake から便利に使うためのユーティリティが GitHub で供給されているので紹介するだけの簡単な Tips です．
が，最後の部分はこれでいいのか感があるので誰かいい方法知ってたら教えてください．

# ユーティリティ

肝心のモノは前述のGitHubのリポジトリにあるこれです．
[https://github.com/joan2937/pigpio/blob/master/util/Findpigpio.cmake](https://github.com/joan2937/pigpio/blob/master/util/Findpigpio.cmake)

この ```Findhoge.cmake``` という形式のファイルは， cmake で find_package から検索できるようにします．
この形式のファイルを ```CMAKE_MODULE_PATH``` で指定されたディレクトに置いておくことで，はじめて検索されるようになるようです(参考 : [https://cmake.org/cmake/help/v3.5/command/find_package.html](https://cmake.org/cmake/help/v3.5/command/find_package.html))．

そのためのファイルが上記の ```Findpigpio.cmake``` となります．
ところが，せっかくの便利な util ですが，インストール時に何処かにコピーされるわけでもないようなので，自分で明示的に使う必要があります．

# CMakeLists.txt への追加行

まずは， pigpio を find_package します．
pigpio の GitHub を ```/home/strv/work/``` に clone した場合の説明です．

```cmake
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} /home/strv/work/pigpio/util)
find_package(pigpio REQUIRED)
```

以上をpigpioを使うCMakeLists.txtの最初の方に書いておけばOKです．

もしくは， ```Findpigpio.cmake``` ファイルを ```/usr/share/cmake-*/Modules/``` 以下にコピーしても大丈夫ですが， cmake のバージョンが変わるとコピーし直す必要があります．
コピーしないほうかいいような気もするのですが， CMakeLists.txt 中に環境依存なパスを書くのもなぁ，と思いつつ，どっちが良いのかイマイチわかりません．
正しい?良い?方法教えてください…

そもそもutilがMODULEではなくCONFIGとして配られていれば解決する話?

あとは，実際に pigpio (や，pigpiod) を使うコンパイル対象の依存関係に，find_package により利用可能になるパスを使って記述してやればOKです．
ゆるふわエンジニアでも作れるCLIツール

# Who？

twitter: @carimatics
気持ちよくエンジニアリングができる環境を作りたい
という気持ちを抱いて早幾星霜

仕事ではこんなのよく触ってる
- Shell script
- Perl
- Python
- JavaScript
- AWS
- Docker

---

# 今日のお話

---

# CLI

---

# つくる

---

# CLI
## Command Line Interface
行ごとにコマンドを実行するためのツールです（雑）
もっと雑に言うとmacOSのterminal、もしくはWindowsのcmdです

## 何でCLIツール作るのです？

shell script書きたくなさが臨界点を超えて爆発した
Pythonとかでもよかったんだけど何事も挑戦なので...

---

# 使うライブラリ
## urfave/cli
- `flag` （オプション）のパースが簡単にできる
- `subcommands` を作るのも簡単
    - `git` コマンドの `add` とか `commit` とか
- `Usage` を記述すればいい感じのヘルプも作ってくれるのでマニュアルが腐りにくい

---

# 簡単なコマンドを作る

---

# みんな大好き

---

# カウンター！

---

# 動作はこんな感じ（雑）

![mycmd.gif](https://qiita-image-store.s3.amazonaws.com/0/151514/5c6d75b9-0236-5830-6764-9406fbaa079f.gif)

---

# ディレクトリ構成

```
mycmd
├── Gopkg.lock   # 依存関係
├── Gopkg.toml   # プロジェクトの設定
├── count.txt    # ストレージ(雑)
├── main.go      # entry point
├── modules      # 今回作ったコマンド処理本体
│   └── commands
│       └── counter
│           └── counter_command.go
└── vendor       # 外部ライブラリ
    └── github.com
        └── urfave
            └── cli
```

---

# やること

これだけ！

- Application設定
- Command登録
- Action登録
- SubCommand登録

---

# Application設定

```go
app := cli.NewApp()
app.Name    = "mycmd"
app.Usage   = "The sample application"
app.Version = "0.0.1"
```

---


# Command登録

今回はcounterコマンドを追加する

```go
app.Commands = []cli.Command{
	counter.CounterCommand(count),
}
```

---

# コマンド叩いたときに以下のように表示される

```
$ mycmd 
NAME:
   mycmd - The sample application

USAGE:
   mycmd [global options] command [command options] [arguments...]

VERSION:
   0.0.1

COMMANDS:
     counter  Execute count up/down
     help, h  Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --help, -h     show help
   --version, -v  print the version
```

---

# Action登録
## CounterCommand

```go
cli.Command{
	Name:  "counter",
	Usage: "Execute count up/down",
	Action: func(context *cli.Context) error {
		printCurrentCount(count)
		return nil
	},
	Subcommands: []cli.Command{
		upCommand(count),
		downCommand(count),
	},
}
```

## コマンド叩くと

```
$ mycnt counter
current count: 0
```

---

# SubCommand登録

## down

```go
cli.Command{
	Name:  "down",
	Usage: "Down count",
	Action: func(context *cli.Context) error {
		count--
		printCurrentCount(count)

		saveCount(count)
		return nil
	},
}
```

## コマンドを叩くと

```
$ mycnt counter
current count: -1
```

---

# まとめ

CLIツール簡単に作れる〜！

みんなはもっと有益なコマンド作ろう！
PocketMine-MPのplugin.ymlのいろいろな話

# plugin.ymlの面白さを語る
plugin.ymlは想像以上に機能が多く、その機能を使うことでによってコードを簡略化することができます。

## depend
```yml:plugin.yml
depend: 
  - ChatChannel
  - PocketMoney
```
依存関係をかけます。
もう `if($this->getServer()->getPluginManager()->getPlugin("ChatChannel") == null)`なんて書かなくていい！
dependに書かれたプラグインがない時にプラグインが無効化されます

## softdepend
痒い所に手が届く。
入れる必要はないけど、ある時には連携できますという場合にはこちら

## prefix
```yml:plugin.yml
name: ChatChannel
prefix: ChatRoom
```
Loggerに表示される先頭の名前を変更できます。

## loadbefore
```yml:plugin.yml
loadbefore:
 - ChatChannel
 - PocketMoney
```
自分より前にプラグインを読み込ませたいときに使えます。
APIを使うときには書いておくと安全です。

## extensions
```yml:plugin.yml
extensions:
 - mysqli
 - sqlite3
```
対象のPHP拡張を入れてない場合にプラグインが無効化されます。


# plugin.ymlを活用しよう
コードだけですべてを管理してしまうと多くの量がかさみます。
できるだけ効率よくプラグインを作っていきましょう。
[Review] Beam Search

Link
https://machinelearningmastery.com/beam-search-decoder-natural-language-processing/

Beam Search is heavily related with RNN, especially language model.
It is a decoder process to transform the probabilities into a final sequence of words and returns a list of most likely following words.

```python
from math import log
from numpy import array
from numpy import argmax
import numpy as np

# beam search
def beam_search_decoder(data, k):
    sequences = [[list(), 1.0]]
    # walk over each step in sequence
    for row in data:
        all_candidates = list()
        # expand each current candidate
        for i in range(len(sequences)):
            seq, score = sequences[i]
            for j in range(len(row)):
                candidate = [seq + [j], score * -log(row[j])]
                all_candidates.append(candidate)
        # order all candidates by score
        ordered = sorted(all_candidates, key=lambda tup: tup[1])
        # select k best
        sequences = ordered[:k]
    return sequences


# define a sequence of 10 words over a vocab of 5 words
data = np.random.rand(10, 5)
data = array(data)
# decode sequence
result = beam_search_decoder(data, 4)
# print result
print(data)
for seq in result:
    print(seq)

```
こんにちは。変数の命名プログラムです。[CURIOUSTORE]

![image.png](https://qiita-image-store.s3.amazonaws.com/0/244751/65d50c39-9d06-10bc-3b48-e6ae5f0ec102.png)
http://www.curioustore.com/#!/util/naming

比較的簡単にインスタンス名やデータの物理モデルを出力するようにしてくれるプログラムです。

こんにちは。韓国の開発者です。
昨年から私が開発して運営しているサイトです。
韓国では、多くの開発者からの応援を受けて、
さらに育ててみようという趣旨で、日本語、中国語など多言語をサポートすることを決定しました。

私は日本語初心者です。
しかし、プログラムは、選ばないので、皆さんと共有したいと思います。

多くの意見をしてください。
ただ私が日本語をよくすることができないため、翻訳を容易にしていただければ幸いです。
kubernetesでpodをリロードする一番簡単な方法

kubernetesでconfigmap更新したからとか、何かとpodを一斉にリロードしたいときってありますよね？
そんなときは下記のコマンドが便利です。

``` sh
kubectl set env deploy/${your_deployment_name} RELOAD_DATE="$(date)"
```

これだけ

envを書き換えてるだけですが、これで全podリロードされます。ただし `kubectl rollout undo` を使えなくなってしまう点だけ注意が必要です。まー当たり前といえば当たり前ですが。あと元々`RELOAD_DATE`という環境変数を使ってると上書きされちゃうので別の変数に変えてください。

もし、一気にリロードされるのがいやだって場合はdeploymentに次の設定を入れると良いでしょう。

``` deployment.yaml
spec:
  replicas: 2
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 10%
      maxUnavailable: 1
```
type RoolingUpdateにするとすこじづつアップデートするモードになります。
`maxSurge`はどれだけの超過podを許すか。
`maxUnavailable`は使えなくなるpodの数です。

#### 参考
[Force pods to re-pull an image without changing the image tag #33664](https://github.com/kubernetes/kubernetes/issues/33664#issuecomment-369186203)
[Google Container Engineで安定してRolling Updateをさせる設定](https://qiita.com/esplo/items/b50d7284cb645977aa5e)
ROS用Ubuntuで最初にやることリスト

# ROS用Ubuntuで最初にやることリスト

ROSをインストールしてロボットに搭載するためのUbuntuで使い始めるために必要なことを備忘録としてまとめます．
適宜思い出したら追記していくと思います．

# シリアルポート関係

## modemmanager をアンインストールする

```
sudo apt purge modemmanager
```

こいつがいるとシリアルポートとして認識されるデバイスが認識されてから1分(だっけ?)間デバイスを専有されてしまい他で使えなくなる．
ロボットでこいつが必要になることは無いと思うので，アンインストール．

## ユーザをdialoutグループに追加する

```
sudo usermod -aG dialout ゆーざ名
```

シリアルポートデバイスは dialout グループとしてデバイスファイルができるので，ユーザを追加しておけば sudo しなくてもシリアルポートを使える．

# ネットワーク関係

## ホスト情報を設定する

```
/etc/hostname
```

にそのPCのユニークな名前を書く．
他のPCと被らない名前にする．
短いほうが楽．

```
/etc/hosts
```

の一行目にある

```
127.0.0.1 localhost
```

のしたに

```
127.0.1.1 なまえ
```

という感じでhostnameに書いたのと同じ名前を書く．

修正したら再起動する．

## IPv6 を無効化する

ROSはIPv4を使う前提だったはずなので，IPv6は無効化しておいたほうが面倒がない．

方法 : [https://qiita.com/RYOSKATE/items/dcd96d2d940cfd3197bc](https://qiita.com/RYOSKATE/items/dcd96d2d940cfd3197bc)

## apt update の自動実行を止める

```
sudo systemctl mask apt-daily.service
sudo systemctl mask apt-daily.timer
sudo systemctl mask apt-daily-upgrade.service
sudo systemctl mask apt-daily-upgrade.timer
```

起動時やネットワークがつながったときに勝手にapt updateされると非力なマシンではCPU使用率が食われるし，携帯電話回線で動かすロボットでは余計なパケットが発生するし，いいことがない．

## ssh key を交換する

ロボット上にPCが乗っていて，そこでROSが動いている場合，sshでログインすることが多いかと思います．
その場合に毎回パスワードを入力するのにも面倒なので，さっさとssh keyを交換してパスワード無しでセキュアにログインできるようにしたほうが楽です．

### ssh key でログインできるように設定する

ロボットＰＣ上の```/etc/ssh/sshd_config```を開いて，下記行にコメントがついてたら外す．

```
RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile     $h/.ssh/authorized_keys
```

その後，設定を有効にするため，sshdを再起動する．

```
$sudo systemctl restart sshd
```

### keyを作って交換する

1. ロボット上にssh keyを保存する場所を作る
```
$ mkdir ~/.ssh
$ touch ~/.ssh/authorized_keys
$ chmode 600 ~/.ssh/authorized_keys
```

1. 作業PC上でssh keyを作る
```
$ cd ~/.ssh
$ ssh-keygen -t rsa -f robo_rsa
```

1. ロボットに送る  
```
ssh-copy-id -i ~/.ssh/robo_rsa.pub ロボットのユーザ名@ロボットのIP
```


# その他

## タイムゾーンの設定と確認
GUIを使わない方法をよく忘れるのでメモ．

### 設定するとき

```
sudo timedatectl set-timezone Asia/Tokyo
```

### 確認するとき

```
timedatectl 
```

### NTPの設定 (おまけ)

```
sudo timedatectl set-ntp true
sudo timedatectl set-ntp false
```

これを使って，確認した結果が no になってても， chrony は生きて動くっぽい．
ntpd にだけ効果がある? 

## 細々した設定

GUI環境があるならTweak Toolを入れる。CAPSとCtrlの入れ替えとか、簡単。
Deployer でつまづいたポイント(Windows 10+さくらレンタルサーバー+GitHub)

# つまづきポイント :no_pedestrians:

1. `ssh`コマンドが使えるターミナルから`deploy`すること
    - 素の`cmd.exe`とかでは :no_good_tone1: 
    - 筆者は :octocat:  [GitHub Desktop](https://desktop.github.com/) 同梱の `Git Shell`を使用しました
2. `ssh user@domain.sakura.ne.jp -i ~/.ssh/id_rsa`でサーバーにログインできる状態であること
    - `user`、`domain`は適宜自分のものに書き換える
    - `~/.ssh/id_rsa`は後述の`deploy.php`の`identityFile`に指定する秘密鍵とおなじもの
3. サーバー側に最新の`Git`をインストールし
    - シェルをbashに変更し
    - パスを通しておく
    - `deploy.php`の`bin/git`環境変数で指定します
    - [さくらインターネットレンタルサーバにGitをインストールする - 高見知英のかいはつにっし(β)](http://blog.onpu-tamago.net/entry/2016/03/25/182707)
    - [さくらインターネットのデフォルトのシェルをbash に変更してみた – 極上の人生](https://kawairi.jp/weblog/vita/2014123118987)



# `deploy.php`
最終的に以下のようになりました。

```php
<?php
namespace Deployer;

require 'recipe/common.php';

// Hosts
host('user@domain.sakura.ne.jp')
    ->port(22)
    ->addSshOption('UserKnownHostsFile', '/dev/null')
    ->addSshOption('StrictHostKeyChecking', 'no')
    ->identityFile('~/.ssh/id_rsa')
    ->forwardAgent(true)
    ->multiplexing(false)
    ->set('deploy_path', '~/www/path/of/project')
    ->set('bin/git', '~/local/bin/git')
    ->set('application', 'project-name-here')
    ->set('repository', 'git@github.com:your/project.git')
    ;

// Tasks

desc('Deploy your project');
task('deploy', [
    'deploy:info',
    'deploy:prepare',
    'deploy:lock',
    'deploy:release',
    'deploy:update_code',
    'deploy:shared',
    'deploy:writable',
    'deploy:vendors',
    'deploy:clear_paths',
    'deploy:symlink',
    'deploy:unlock',
    'cleanup',
    'success'
]);

// [Optional] If deploy fails automatically unlock.
after('deploy:failed', 'deploy:unlock');

```

# `> php deployer.phar deploy`
```bash:すべてがうまくいったとき
✈︎ Deploying master on user@domain.sakura.ne.jp
➤ Executing task deploy:prepare
✔ Ok
➤ Executing task deploy:lock
✔ Ok
➤ Executing task deploy:release
✔ Ok
➤ Executing task deploy:update_code
✔ Ok
➤ Executing task deploy:shared
✔ Ok
➤ Executing task deploy:writable
✔ Ok
➤ Executing task deploy:vendors
✔ Ok
➤ Executing task deploy:clear_paths
✔ Ok
➤ Executing task deploy:symlink
✔ Ok
➤ Executing task deploy:unlock
✔ Ok
➤ Executing task cleanup
✔ Ok
Successfully deployed!
```

# それでもエラーが出たら

## `-vvv`オプションで実行してみる
`php deployer.phar deploy -vvv`
ステップのログが細かく出力されるので、どの部分で失敗しているのかが特定できるかもしれません。

## deployerレポジトリをcloneしてコード読んでみる。

PHPコードなので、読めないことはないという気持ちがたいせつ。
- :octocat: [deployphp/deployer: A deployment tool written in PHP with support for popular frameworks out of the box](https://github.com/deployphp/deployer)
オートコンプリートと改行を実装したTextBox

どこかのサイトからほぼ丸パクリしたけど、どこのサイトかわからなくなったのでメモ。

```vb

''' <summary>
''' マルチライン＆オートコンプリートテキストボックス
''' </summary>
Public Class MultiLineAndAutoCompleteTextBox
    Inherits TextBox

    'Enterキー押下時にキャレット位置に改行を差し込むため
    Private CaretPos As Integer = 0

    'ReadOnlyにしたい。要検討。
    Public Overrides Property Multiline As Boolean
        Get
            Return False
        End Get
        Set(value As Boolean)
            MyBase.Multiline = False
        End Set
    End Property

    Protected Overrides ReadOnly Property CreateParams As CreateParams
        'このSecurity...の部分は特に丸パクリすぎて意味不明
        <Security.Permissions.SecurityPermission(Security.Permissions.SecurityAction.LinkDemand, Flags:=Security.Permissions.SecurityPermissionFlag.UnmanagedCode)>
        Get
            Dim cp As CreateParams = MyBase.CreateParams
            cp.Style = cp.Style Or 4
            Return cp
        End Get
    End Property

    'これをオーバーライドしている理由を失念。なくてもいいのかも。
    Public Overrides Property AutoSize As Boolean
        Get
            Return MyBase.AutoSize
        End Get
        Set(value As Boolean)
            MyBase.AutoSize = value
        End Set
    End Property

    Private Sub MyPrevKeyDown(sender As Object, e As PreviewKeyDownEventArgs) Handles MyBase.PreviewKeyDown
        If e.KeyCode = Keys.Enter Then
            CaretPos = SelectionStart
            Text = Text.Insert(CaretPos, Environment.NewLine)
        End If
    End Sub

    Private Sub MyKeyDown(sender As Object, e As KeyEventArgs) Handles MyBase.KeyDown
        If e.KeyCode = Keys.Enter Then
            Try
                '文法的にはMeをつけなくてもいいはずなのだが、つけないとSelect Caseだと誤解される。
                Me.Select(CaretPos + Environment.NewLine.Length, 0)
                ScrollToCaret()
            Catch ex As Exception
                '適切な処理
            End Try
        End If
    End Sub
```

オートコンプリートの設定は割愛。
どうしてもと要望があったので作った。
AutoSizeプロパティをFalseに設定して、Heightプロパティを適当な値に設定すると、それっぽくなったと思う。
SIMを挿しているWindows10 PCに「APNを入力して、やり直してください。」と言われたら。

Windows10を使っていて、急にSIM経由で通信できなくなり、ネットワーク設定を見てみると以下のように表示されていることはありませんか？

```
このネットワークに接続できません
APNを入力して、やり直してください。
```

再起動しても治らない場合、以下の手順をお試しください。

1. シャットダウン
1. SIMを抜く
1. 起動
1. シャットダウン
1. SIMを挿す
1. 起動

キモは、SIMを挿していない状態で起動・シャットダウンを挟むことです。
起動時にSIMがなかったら、APNの設定を消去してくれるんですかね。。。わかりませんが。

このような事が起きる原因もよくわかっていないのですが、Windows Updateの後によく発生してる気がします。
FK(外部キー)ついて

はいどーも！本日はFKについてお話を進めていきたいと思います。
<h1>FOREIGN KEY とは</h1>
他のテーブルと関連付けされているキーである。

と記載されていましたが実際何のことだかあまり理解できないので図を使って噛み砕いて話していきます。
例ですが、このような形の派遣社員管理表があるとします。

シートA
<img width="359" alt="スクリーンショット 2018-03-20 18.05.42.png" src="https://qiita-image-store.s3.amazonaws.com/0/240422/0b8d17e3-d4d6-f4b8-2802-de9e88ff396a.png">

しかしこれだけでは個人の名前とIDがわかったとしても会社IDが数字なのでどこに属しているかわかりません。
そこでもう１つテーブルを用意してあげます。

シートB
<img width="180" alt="スクリーンショット 2018-03-20 18.08.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/240422/e452d9aa-c84a-7069-157b-ccb813984730.png">

これで全くわからなかった派遣社員が属してる会社がどこかわかりました。

このようにシートAとシートBを関連付けをすることで表の中を表示できるようにしてあげることができます。

外部キーのメリット
- 同じデータを登録せずに済む（例：株式会社!!!と複数回登録せずに済む)
- データの整合性を保証できる

ということがあるそうです。
自分も最近知ったのでなんのことだと思いいろいろな記事を参考にして書きました！
CircleCIでyarnが通らなくなって詰んだのでPATHを通して解決する

# 事象

突然CircleCI上でテストがコケるようになりました。

調べてみるとwebpackerがフックしている`assets:precompile`で失敗している様子。。

```sh
#!/bin/bash -eo pipefail
bundle exec rake assets:precompile
/home/circleci/my_project/vendor/bundle/ruby/2.5.0/bin/rake: No such file or directory - yarn
Yarn not installed. Please download and install Yarn from https://yarnpkg.com/lang/en/docs/install/
Exited with code 1
```

1. assets:precompileをフックしてwebpacker:compileが実行される
2. webpacker:compile内でyarnが実行される
3. yarnないよ！って怒られる

今まで何も言わないいい子だったのにどうして突然・・・ :sob: 

# 原因
CircleCIコミュニティにも報告が上がってました。
[Yarn missing from latest node 8 images? - Bug Reports - CircleCI Community Discussion](https://discuss.circleci.com/t/yarn-missing-from-latest-node-8-images/20783/6)

yarnのパスが通ってないバグがあったようです。（すでにmerge済）
[Fixed symbolic links to yarn and yarnpkg by cecton · Pull Request #650 · nodejs/docker-node](https://github.com/nodejs/docker-node/pull/650/files)

# 解決
とりあえずyarnが実行できるようにPATHを追加してあげればOK。

```yml
PATH: "/opt/yarn/yarn-v1.5.1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
```

もしくは

```yml
- run: PATH=$PATH:/opt/yarn/yarn-v1.5.1/bin
```

これ、CircleCIのキャッシュの運次第らしい :fearful: 
（dockerイメージは `circleci/ruby:2.5.0-node-browsers` を使ってました）

>最近のNode.js公式Dockerイメージでyarnのパスが通ってないバグ。最新では直ってるけどCircleCIのキャッシュガチャで当たると落ちる
http://b.hatena.ne.jp/entry/360606178/comment/teppeis

てんやわんやでしたー。

以上。
Dockerでローカル環境を汚さずにNuxt.jsを始めてみる

## 試した環境
Docker for windows (windows10)

## docker-compose.ymlの記述
```yaml:docker-compose.yml
version: "3"
services: 
  web:
    build: 
      context: ./
    privileged: true
    volumes:
      - "./:/usr/share/nginx/html"
    ports:
      - 80:80
      - 3000:3000
    container_name: "nuxt" # コンテナ名は適当に
```

## Dockerfileの記述
```sh:Dockerfile
FROM centos:7.4.1708

RUN yum -y update

RUN yum -y install epel-release
RUN yum -y install http://rpms.remirepo.net/enterprise/remi-release-7.rpm

RUN yum -y upgrade
RUN yum -y install nginx

RUN curl -sL https://rpm.nodesource.com/setup_9.x | bash -
RUN yum install -y gcc-c++ make
RUN yum install -y nodejs

RUN npm install -g vue-cli
RUN npm install -g nuxt
RUN npm install -g create-nuxt-app

ENV HOST 0.0.0.0

CMD ["nginx", "-g", "daemon off;"]

WORKDIR /usr/share/nginx/html
```


## Dockerfileのbuild・docker-composeの立ち上げ・webコンテナに入る

docker-compose.ymlの同ディレクトリで以下を実行

```
docker-compose build
docker-compose up -d
docker-compose exec web bash
```

## コンテナ内での操作

```
create-nuxt-app <任意のディレクトリ名>
cd <任意のディレクトリ名>
npm install
npm run dev
```
「create-nuxt-app <任意のディレクトリ名>」実行時に
色々選択肢が出てきますが、とりあえずNuxtアプリを作りたい場合は全てEnterを押す。
http://localhost:3000
にアクセスしてデフォルト画面が出れば、いったんは構築完了。

<img width="481" alt="2018-03-20 (1).png" src="https://qiita-image-store.s3.amazonaws.com/0/133718/58b743b1-17f4-c992-4bfc-1c7896fd2359.png">

## チュートリアルとか参考とか
https://www.youtube.com/watch?v=nteDXuqBfn0&t=606s
を始めるまでに時間がかかったので。

https://ja.nuxtjs.org/guide/installation/
定番の公式ドキュメント

## 更新
[もっと簡単にDockerでNuxt.jsを始めてみる(続Dockerでローカル環境を汚さずにNuxt.jsを始めてみる)](https://qiita.com/ProjectEuropa/items/4f141730c53754ca7dc2)
続編を書きました
Fitbitのアクティビティデータを他サービスへ連携したい！

# 何はともあれIFTTT
Webサービス同士のデータ連携をお手軽にするんだったらIFTTTだよね、とアプレットを作成してみた。

![IFTTT_title](https://qiita-image-store.s3.amazonaws.com/0/233979/04e2b952-49a5-9df7-9de8-3292bff04b11.png)

うん、これこれ。Fitbitとも連携できるしね。
![IFTTT_Fitbit](https://qiita-image-store.s3.amazonaws.com/0/233979/6e2f0fce-9b0f-7d4a-0c3d-235abb9996ef.png)　![Fitbit_DailyActivity](https://qiita-image-store.s3.amazonaws.com/0/233979/a617a2a5-6392-a977-7355-f6837b9f8dd1.png)

他サービスと連携するために「Webhoocks」を選ぶ。
![IFTTT_Webhoocks](https://qiita-image-store.s3.amazonaws.com/0/233979/4a7232c3-f2e1-f8f0-eb2b-11d505967c30.png)

# ん？
![IFTTT_Webhoocks_ContentType](https://qiita-image-store.s3.amazonaws.com/0/233979/2957679c-3760-c476-d5c5-72632983b48a.png)

application/xmlがない？

# おや困った。。。
連携先のWebサービスはXMLでデータを送る必要があって、これじゃ連携できないことが判明。。。

# そこで見つけたZapier
色々探していると、「XML送りたいならZapierでできるんじゃね？」というフォーラムを発見、さっそく試してみる。

[![Zapier_title](https://qiita-image-store.s3.amazonaws.com/0/233979/48b658f1-62af-5406-09dd-d03b504a54fc.png)](https://zapier.com/apps/integrations)

# Make a Zap!
IFTTTで言うところの「アプレット」のことを「Zap」と呼ぶ。

![Make_a_Zap](https://qiita-image-store.s3.amazonaws.com/0/233979/32fe2e68-6382-6d60-815a-f6902485aac6.png)

IFTTTと同様、トリガとアクションを設定する模様。
IFTTTと違うところは、![Add_Action](https://qiita-image-store.s3.amazonaws.com/0/233979/4d81b0ea-6ac9-cd2c-d529-a6db2c349c2e.png)をクリックすることでアクションを複数設定できることと、![Add_Filter](https://qiita-image-store.s3.amazonaws.com/0/233979/4c7230c5-cc00-c88e-ff8b-efae324fd2c5.png)をクリックするとフィルターを設定できること。

※IFTTT Platformを使えば同様のことは可能。

# さっそく作っていこう
まずはトリガから。「Choose App」でWebサービスを選ぶ。

![App_No_results](https://qiita-image-store.s3.amazonaws.com/0/233979/394af179-7aba-66c8-bd45-f939b8e2593a.png)

なんたること。。Fitbitが無いじゃない。。。

# まだあきらめない！
[Fitbitのアクティビティデータを他サービスへ連携したい！その２](https://qiita.com/ASLA/items/acb2df17e67e494a0f71)
へつづく
PHPStormでステップ実行（Docker For Mac(Windows)環境）

## Docker For Mac(Windows)環境でPHPStormでステップ実行

↓の記事の補足になります。
参考：PHPStormでステップ実行（Docker Toolbox環境）
https://qiita.com/yKanazawa/items/0655db2a14b842f80e03

Docker Toolbox環境の場合は、PHP Stormに対するIPアドレスがデフォルトで192.168.99.100になりますが、Docker For Mac(windows)では127.0.0.1になってしまうため、コンテナ内から9000番ポートでアクセスできません。

ホストPCのIPアドレスを指定すれば通信できるのですが、大抵のPC環境では、DHCPで動的にIPアドレスが割り振られているでしょうから、毎回設定する必要があり、不便です。

この場合、以下のように設定すれば毎回設定しなくても通信できるようになります。

```
[xdebug]
zend_extension="/usr/lib64/php/modules/xdebug.so"
xdebug.remote_enable = On
xdebug.remote_port = 9000
;xdebug.remote_autostart = On
xdebug.remote_host = host.docker.internal
xdebug.profiler_output_dir = "/tmp"
xdebug.max_nesting_level= 1000
xdebug.idekey = "PHPSTORM"
```
jupyter notebookで notebookが保存できない現象

dockerでマウントしているフォルダにグローバルで書き込み権限を与えるでOK


マウントしているディレクリで

```
# chmod 777 . 
# stat .

  File: ‘.’
  Size: 4096            Blocks: 8          IO Block: 4096   directory
Device: 870h/2160d      Inode: ** Links: 3
Access: (0777/drwxrwxrwx)  Uid: ( 1019/kawashima)   Gid: ( 1019/washim)

```

stat して、drwxrwxrwxになっていればOK
scope を指定したアソシエーションを nested_attributes_for に渡すとアソシエーションを save できない

# 問題

以下の 2 つのモデルが存在するとします。

```app/models/lesson.rb
class Lesson < ApplicationRecord
  has_many :lesson_schedules, dependent: :destroy
  accepts_nested_attributes_for :lesson_schedules, reject_if: :all_blank, allow_destroy: true
end
```

```app/models/lesson_schedule.rb
class LessonSchedule < ApplicationRecord
  belongs_to :lesson
end
```

`accepts_nested_attributes_for :lesson_schedules` の宣言により、`Lesson` とそれに紐づく `LessonSchedule` を次のコードで同時に作成することができます。

```rb
lesson =
  Lesson.create(
    title: '仏像彫刻',
    lesson_schedules_attributes: [
      { wday: 0, start_time: '13:00', end_time: '17:30' },
      { wday: 3, start_time: '19:00', end_time: '21:00' }
    ]
  )

lesson.persisted? #=> true
lesson.lesson_schedules.count #=> 2
```

だがしかし、`Lesson` モデルで `has_many :lesson_schedules` に scope を指定すると…

```rb
class Lesson < ApplicationRecord
  # has_many の第 2 引数に scope を渡すようにした。
  has_many :lesson_schedules, -> { order(:wday, :start_time, :end_time) }, dependent: :destroy
  accepts_nested_attributes_for :lesson_schedules, reject_if: :all_blank, allow_destroy: true
end
```

```rb
lesson =
  Lesson.create(
    title: '仏像彫刻',
    lesson_schedules_attributes: [
      { wday: 0, start_time: '13:00', end_time: '17:30' },
      { wday: 3, start_time: '19:00', end_time: '21:00' }
    ]
  )
lesson.persisted? #=> false
lesson.errors.full_messages #=> ["Lesson schedules lesson must exist"]
```

作成できなくなりました。エラーメッセージを確認すると、どうやら `LessonSchedule` の外部キーが設定できていないようです :sob:

# 解決策

`has_many` や `belongs_to` で `inverse_of` オプションを使います。 

```app/models/lesson.rb
class Lesson < ApplicationRecord
  has_many :lesson_schedules, -> { order(:wday, :start_time, :end_time) },
           inverse_of: :lesson, dependent: :destroy
  accepts_nested_attributes_for :lesson_schedules, reject_if: :all_blank, allow_destroy: true
end
```

```app/models/lesson_schedule.rb
class LessonSchedule < ApplicationRecord
  belongs_to :lesson, inverse_of: :lesson_schedules
end
```

こうすると `Lesson.create` が再び成功するようになりました :smile:

# 参考

* [rails/rails » Issue #20451 » has_many association bug: accepts_nested_attributes_for or adding a scope on association breaks the associations before objects are saved](https://github.com/rails/rails/issues/20451)
* [[rails] accepts_nested_attributes_for の場合は、inverse_of を付けておくと良い気がする](https://qiita.com/ryoff/items/e3ba4b8c8be117c79b73)
Electronで漫画ビュワーを作った話

Electron、TypeScript、React を使って、なにか作りたかったので漫画ビュワーアプリを作りました。
開発環境や、使用したライブラリーなどを書いていきたいと思います。

[GitHub: ElectronMangaViewer](https://github.com/bytefunc/ElectronMangaViewer)



※この記事のアプリのスクリーンショット内の漫画は、二次利用フリーの"ブラックジャックによろしく"を使用させて頂いてます。
![1.png](https://qiita-image-store.s3.amazonaws.com/0/147553/5f9b1b01-69e4-720a-452d-d3ee2a899bcc.png)

タイトル:ブラックジャックによろしく　著作者名:佐藤秀峰
[佐藤漫画製作所](http://mangaonweb.com/company/download.html)　からPDF形式版をダウンロードできます。


![1.png](https://qiita-image-store.s3.amazonaws.com/0/147553/6184bb85-ebd1-be5e-d3fd-40d4a11a7453.png)

![2.png](https://qiita-image-store.s3.amazonaws.com/0/147553/9798e8d4-b98d-a3b4-f7a5-a5aeed369ca0.png)




# 開発環境

プログラミング言語には[TypeScript](http://www.typescriptlang.org/)、TypeScriptの静的解析ツール[TSLint](https://palantir.github.io/tslint/)、モジュールバンドラに[webpack](https://webpack.js.org/)、コードフォーマッターには[Prettier](https://github.com/prettier/prettier)を使用。
TSLintでもコード整形できますが、なぜPrettierを利用するのかと言うと以下のページを参考

[Prettier 入門 ～ESLintとの違いを理解して併用する～]
(https://qiita.com/soarflat/items/06377f3b96964964a65d)

自分はTSLint、ESLint両方ともにPrettierを使用しています。

TSLint、ESLintでPrettierを使うには以下のページを参考
[ESLint(あるいはTSLint)とPrettierを併用する](http://tech-1natsu.hatenablog.com/entry/2018/01/07/154941)


# 使用したライブラリ

## 並べ替えをする為に [react-dnd](https://github.com/react-dnd/react-dnd) を使用
Reactで簡単にDrag and Dropで並べ替えが実装出来ます。

![1.gif](https://qiita-image-store.s3.amazonaws.com/0/147553/b2545b9a-f5ad-a367-b892-eb9f1e011ece.gif)


## スライダーに [rc-slider](https://github.com/react-component/slider) を使用
スライダーのライブラリは昔から色々とありますが、Reactで扱うならReactComponent 化されてる[rc-slider](https://github.com/react-component/slider) がオススメです。

![2.gif](https://qiita-image-store.s3.amazonaws.com/0/147553/f14dcf6f-ad2c-4ca2-c7a4-1d85da858994.gif)

## レイアウト幅を変更に [react-resize-layout](https://github.com/bytefunc/react-resize-layout) を使用
ReactでElectronアプリのレイアウト幅を変更するために自分で作りました。ブラウザでも使えます。

![3.gif](https://qiita-image-store.s3.amazonaws.com/0/147553/381eb55f-47f9-f077-6746-5e441617f469.gif)

# その他

* Reactまわりのメソッド順序は（componentDidMountとかその辺）、[Airbnb React/JSX Style Guide](https://github.com/airbnb/javascript/tree/master/react)を参考。
* CSSはSASSのSCSSで書き、コンポーネントのCSSをコンポーネントと同一ファルダーに置きCSS Modulesにした。コンパイルもバンドルもwebpackで簡単にできてよかった。
* ReactのHOCは便利、contextmenu周りはHOCにして色んなコンポーネントに使えるようにした。
* ReactやReduxで何か作るときはFacebook Samplesの[f8app](https://github.com/fbsamples/f8app)が参考になると思う。actionsやreducersが、かなり読みやすい。
* 小規模のアプリでもTypeScriptで型の定義などし、静的コード解析ツールのTSLintで開発していくのは非常に便利だった。
GCP に外部から RPC 接続可能にする


# きっかけ
Google Cloud Platform 上に用意したサーバで geth サーバを起動している。geth サーバに外部マシンから RPC 接続したい。

# 概要

- ファイアウォールルールを追加する（RPC ポートを許可）
- 上記で作成したルールを Compute Engine に設定する


# ファイアウォールルールを追加する
「ネットワーク」ー「ファイアウォール ルール」

- タグ名をつける
- tcp:8545 を 許可する

![firewall.png](https://qiita-image-store.s3.amazonaws.com/0/27486/e9f3c7d9-99e9-4fb4-db91-31fb5ba37909.png "firewall.png")


# Compute Engine にファイアウォールルールを設定する

対象のVMインスタンスのネットワークタグに、先ほど作成したファイアウォールのタグ名を指定する。

![Kobito.Usj0uZ.png](https://qiita-image-store.s3.amazonaws.com/0/27486/c297c888-d699-6704-e2aa-dc39869bd1a2.png "Kobito.Usj0uZ.png")

# 参考
https://qiita.com/ndxbn/items/7ef0a96e409a5b5837bd