OmniAICreator/Qiita-1.07M huggingface dataset:
Slackチームに新しくユーザが参加したらダイレクトラブメールを新規さんに送りつける


## はじめに

私は `kosen11s` という某超次元サッカーアニメチームのような名前の変態しかいない団体に属しているわけですが、
そこで「 __自動化！自動化！自動化ッ！！！__ 」と当初は騒がれていたので自動化をしました。

![main.jpg](https://qiita-image-store.s3.amazonaws.com/0/97280/4a2f0457-1e8d-9a44-a888-66f0f54a33e4.jpeg "main.jpg")

(レベルファイブさんごめんなさい！！！)

## ソースコード

[kosen11s/slack_welcome_kosen11s](https://github.com/kosen11s/slack_welcome_kosen11s)

ぶっちゃけいうとGitHubのリポジトリをみてくれ！！って言う感じにしたい

### 環境

Python 3.5.1
pip 8.1.2

### 実装

```bash
$ git clone https://github.com/kosen11s/slack_welcome_kosen11s.git
$ cd slack_welcome_kosen11s
$ pip install -r requiredments.txt
```

SlackのAPIキー等は今回省略させていただきます！！申し訳な〜い！

```python:run.py
from slackbot.bot import Bot
import slackbot_settings

if __name__ == "__main__":
	bot = Bot()
	bot.run()
```

これをずっと動かしている意味はあるのかどうかはわかりませんが、なんかログインユーザがいるのはなんか嬉しいやん？

```python:welcome_bot.py
from slacker import Slacker
import json, requests
import slackbot_settings

welcomeMessage = """
Welcome to kosen11s:tada::tada::tada::tada:\n
まずは #profile チャンネルで簡単に自己紹介してね:heart:\n
他にも #github , #muscle , #nsfw , #skype があるよ！適当に入ってね:raryosu:\n
それとこれが最後！以下のリンクのスキルシートに記入をお願いしてるから記入お願いします！\n
URLはひ・み・つ♡\n
それじゃよろしくね:octocat:
"""

class Member(object):
	memberCount = 0
	def setMember(self):
		data = getJson()
		self.memberCount = len(data['channel']['members'])

def getJson():
	url = 'https://slack.com/api/channels.join'
	parameters = {
		'token' : slackbot_settings.API_TOKEN_TEAM,
		'name' : 'random'}
	r = requests.get(url, params = parameters)
	data = json.loads(r.text)
	mem = Member()
	if mem.memberCount == 0:
		mem.memberCount = len(data['channel']['members'])
	return data

def welcomePost(user):
	slack = Slacker(slackbot_settings.API_TOKEN)
	slack.chat.post_message(
		'@' + user,
		'Hi! ' + user + " " + welcomeMessage,
		as_user = True,
		link_names = 1
	)

if __name__ == '__main__':
	mem = Member()
	mem.setMember()
	while True:
		jsonChannel = getJson()
		if mem.memberCount < len(jsonChannel['channel']['members']):
			print(mem.memberCount)
			mem.memberCount = len(jsonChannel['channel']['members'])
			url = 'https://slack.com/api/users.info'
			parameters = {
				'token' : slackbot_settings.API_TOKEN_TEAM,
				'user' : jsonChannel['channel']['members'][0]}
			r_2 = requests.get(url, params = parameters)
			jsonUser = json.loads(r_2.text)
			welcomePost(jsonUser['user']['name'])
```

THE適当ですね。

```python:slackbot_settings.py
API_TOKEN = 'xoxb-***********-************************'
API_TOKEN_TEAM = 'xoxp-***********-***********-***********-**********'
```

これで実行すると？？？

![スクリーンショット_2016-08-02_午後8_40_51.png](https://qiita-image-store.s3.amazonaws.com/0/97280/561f00e6-f908-c442-c5ad-260e97727b7d.png "スクリーンショット_2016-08-02_午後8_40_51.png")

新規さんに分身した私のもと(テストのためユーザを直接指定)へこんな感じにメッセージが来ましたわ！！！

## 終わりに

チャットボットが熱くなる前に何故か片足突っ込んでしまった私ですがみなさんもまずは簡単にSlackBOTとか作ってみてはいかがでしょうか？

![スクリーンショット 2016-08-02 午後8.51.12.png](https://qiita-image-store.s3.amazonaws.com/0/97280/5764ce1f-8802-11e6-ca21-950d991cec6f.png "スクリーンショット 2016-08-02 午後8.51.12.png")
PHPで通常関数とジェネレータ関数を実行せずに識別する

# 言葉の定義

- 通常関数 … ごく普通の関数
- ジェネレータ関数 … `yield`キーワードを含む関数
- ジェネレータ … ジェネレータ関数が実行されると返り値となるイテレータ
  - 但し`send` `throw` `getReturn`など特殊なメソッドを持つ

# 識別方法

## `Closure`のみを対象にする

**「実行せずに」**というのがなかなか難しそうで諦めていたんですけど，リフレクション使えばできるみたいです。

- [StackOverflow - Is there a way to test if a closure is also a generator?](http://stackoverflow.com/questions/25144939/is-there-a-way-to-test-if-a-closure-is-also-a-generator)

```php
<?php

function is_generator_closure(\Closure $closure)
{
    return (new \ReflectionFunction($closure))->isGenerator();
}

$closures = [
    'normal' => function () {
        assert(false, 'This should not be invoked');
    },
    'generator' => function () {
        assert(false, 'This should not be invoked');
        yield;
    },
];

var_dump(array_map('is_generator_closure', $closures));

/*
array(2) {
  ["normal"]=>
  bool(false)
  ["generator"]=>
  bool(true)
}
*/
```

では[「PHP 文字列リテラルにおける変数展開ノ全テ」](http://d.hatena.ne.jp/do_aki/20131218/1387335279)で紹介されているひねくれたジェネレータ関数はどうなるか？バグとかありそう…？

```php
<?php

function is_generator_closure(\Closure $closure)
{
    return (new \ReflectionFunction($closure))->isGenerator();
}

var_dump(is_generator_closure(
    function () {
        assert(false, 'This should not be invoked');
        "${_[yield]}";
    }
));

/*
bool(true)
*/
```

大丈夫でした！

## 全ての`callable`を対象にする

```php
<?php

function is_generator_callable(callable $callable)
{
    if (is_string($callable) && strpos($callable, '::')) {
        $callable = explode('::', $callable);
    } elseif (!$callable instanceof \Closure && is_object($callable)) {
        $callable = [$callable, '__invoke'];
    }
    $reflector = $callable instanceof \Closure || is_string($callable)
        ? new \ReflectionFunction($callable)
        : new \ReflectionMethod($callable[0], $callable[1]);
    return $reflector->isGenerator();
}
```

なんと汚い条件分岐…
[Linux] NFSのバージョンについて調べたことのメモ

## NFSバージョンの違い

### NFSv2
* 昔のバージョン。最近のNFSDではデフォルトで無効にされている

### NFSv3
* 完全な非同期書き込みに対応
* エラー処理機能強化
* 64ビットのファイルサイズ対応 (2GBを超えるファイルを扱える)

### NFSv4
* インターネット上で動作可能
* rpcbindが不要となった
* ACLに対応

参考
https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/7/html/Storage_Administration_Guide/ch-nfs.html

## サーバーが対応するバージョンを確認するには

rpcinfoコマンドに p オプションを付けて実行する

<pre>
# rpcinfo -p
   program vers proto   port  service
    100000    4   tcp    111  portmapper
    100000    3   tcp    111  portmapper
    100000    2   tcp    111  portmapper
    100000    4   udp    111  portmapper
    100000    3   udp    111  portmapper
    100000    2   udp    111  portmapper
    100024    1   udp  39325  status
    100024    1   tcp  39688  status
    100011    1   udp    703  rquotad
    100011    2   udp    703  rquotad
    100011    1   tcp    706  rquotad
    100011    2   tcp    706  rquotad
    100003    2   tcp   2049  nfs
    100003    3   tcp   2049  nfs
    100003    4   tcp   2049  nfs
    100003    2   udp   2049  nfs
    100003    3   udp   2049  nfs
    100003    4   udp   2049  nfs
    100021    1   udp  41793  nlockmgr
    100021    3   udp  41793  nlockmgr
    100021    4   udp  41793  nlockmgr
    100021    1   tcp  38927  nlockmgr
    100021    3   tcp  38927  nlockmgr
    100021    4   tcp  38927  nlockmgr
    100005    1   udp  35020  mountd
    100005    1   tcp  38999  mountd
    100005    2   udp  47400  mountd
    100005    2   tcp  33395  mountd
    100005    3   udp  51781  mountd
    100005    3   tcp  48243  mountd
</pre>

上の場合 nfs サービスの vers に 2、3、4 があるので、NFSv2、NFSv3、NFSv4 がサポートされる

## NFSサーバーでNFSv2をサポートするには

デフォルトではバージョン3と4しかサポートされない。バージョン2でマウントできるようにするには rpc.nfsd の -V オプションで2を指定する

```
# /usr/sbin/rpc.nfsd -V 2
```

※ RedHat7ではNFSv2をサポートしていないようで、他のディストリビューションでも最近ではもしかしたらサポートされなくなっているかもしれない

## NFSバージョンを指定してマウントする

マウントオプションに"nfsvers"を指定する

```
# mount -t nfs -v -o nfsvers=2 192.168.56.64:/srv/share /mnt
```

RedHat6の情報を元にしている
https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/6/html/Storage_Administration_Guide/s1-nfs-client-config-options.html

環境によっては nfsvers に4が指定出来ない場合がある。その時はnfsversを指定せずに '-t nfs' の代わりに '-t nfs4' を指定すればよい

## マウントポイントからNFSバージョンを確認するには

クライアントからどのバージョンでマウントしているのかを確認するには nfsstat コマンドを使う

```
# nfsstat -m

/mnt/floppy from 192.168.56.64:/srv/share
 Flags: rw,relatime,vers=3,rsize=65536,wsize=65536,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=192.168.56.64,mountvers=3,mountport=41602,mountproto=udp,local_lock=none,addr=192.168.56.64
```

Flagsの値の中から、vers=をみる

## 補足

### いつの間にかportmapが無くなった

今後は portmap の代わりに rpcbind が使われるようになる。portmapがインストールされていたら削除する
Mac版 Office で Ctrl-H で 1文字削除する


たいそうわかりにくくてイライラするのでメモ。
 ```ツール ＞ ショートカット キーのユーザー設定…```
から、```編集``` の ```EditReplace``` を探します。

```Ctrl-H``` はこの機能に割り当たっているので ```Control-H``` を削除します。

![スクリーンショット 2016-08-02 20.04.45.png](https://qiita-image-store.s3.amazonaws.com/0/16860/558ecff2-b8f1-2cec-a77d-6df08cae21ec.png "スクリーンショット 2016-08-02 20.04.45.png")

自分の環境、Office (Word) 15.22.1 です。
bacula-fd, dir間の通信暗号化

ネット上の情報ではどうにも上手くいかなかったので、上手くできた設定を載せます。構築は[こちら](http://goo.gl/c6SX8O)。

# 事前準備
認証用に証明書・秘密鍵を生成しておきます。[この辺り](http://goo.gl/fhzxlz)や[この辺り](https://goo.gl/XycFJh)を参考にさせていただきました。
サーバ、クライアントに共通な証明書・秘密鍵を使います。

# bacula-fdの設定
DirectorリソースとFileDeamonリソースにTLSの項目が必要です。

```
Director {
  Name = bacula-dir
  Password = "baculafd"
  TLS Enable = yes
  TLS Require = yes
  TLS Certificate = /etc/bacula/certs/bacula.crt
  TLS Key = /etc/bacula/certs/bacula.key
  TLS CA Certificate File = /etc/bacula/certs/bacula_ca_file
}

FileDaemon {
  Name = bacula-fd
  FDport = 9102
  WorkingDirectory = /var/spool/bacula
  Pid Directory = /var/run
  Maximum Concurrent Jobs = 20
  TLS Enable = yes
  TLS Require = yes
  TLS Certificate = /etc/bacula/certs/bacula.crt
  TLS Key = /etc/bacula/certs/bacula.key
  TLS CA Certificate File = /etc/bacula/certs/bacula_ca_file
}

Messages {
  Name = Standard
  director = bacula-dir = all, !skipped, !restored
}
```

# bacula-dirの設定
ClientリソースにTLSの項目が必要です。

```
Client {
  Name = bacula-fd
  Address = talt.jp
  FDPort = 9102
  Catalog = MyCatalog
  Password = "baculafd" # password for FileDaemon
  File Retention = 7 days
  Job Retention = 7 days
  AutoPrune = yes
  TLS Enable = yes
  TLS Require = yes
  TLS Allowed CN = "bacula" # サーバとクライアントで同一の証明書を使う場合、証明書作成時に入力したCommon Nameを指定する。
  TLS Certificate = /etc/bacula/certs/bacula.crt
  TLS Key = /etc/bacula/certs/bacula.key
  TLS CA Certificate File = /etc/bacula/certs/bacula_ca_file
}
```

# 確認
tcpdumpしながらstatus確認したりすると、暗号化されているのが分かると思います。

```
# tcpdump -i enp7s0f0 port 9102 -A
```

# 関連
- [Baculaの構築 - Qiita](http://goo.gl/c6SX8O)

# 参考
- [Configuring Bacula to Use TLS to Encrypt Connections - Earth-Works Tips & Tricks for IT Pros](http://goo.gl/fhzxlz)
- [~nabeken/diary/ : Bacula + TLS でインターネット越しのリモートバックアップ](http://goo.gl/y9dXsf)
- [Bacula TLS – Communications Encryption | Bacula](https://goo.gl/BVUORs)
- [Zabbix 3.0 通信の暗号化設定（RSA証明書ベースの暗号化） | あぱーブログ](https://goo.gl/XycFJh)
- [プライベート認証局の証明書、サーバー証明書、クライアント証明書の作成方法について | レンタルサーバー・自宅サーバー設定・構築のヒント](http://goo.gl/bKIXac)
CentOS6.8にPython 2.7を入れた

##概要
gcloudコマンドを実行した際に下記の警告が表示されたので対応した。
警告を消すにはPython 2.6をPython 2.7にアップデートする必要がある。

```bash
WARNING: You are running Python 2.6, which is no longer receiving security
patches as of October 2013.  The Cloud SDK will stop supporting Python 2.6 on
September 1, 2016.  Please update your Python installation to 2.7 to ensure
compatibility with future Cloud SDK versions.
```

###環境
CentOS6.8

##Python 2.7のインストール

[SoftwareCollections](https://www.softwarecollections.org/en/)を入れる
比較的新しいComponentが提供されている
`$ sudo yum install centos-release-scl-rh`

Python27をインストール
`$ sudo yum install python27`

有効化
`$ scl enable python27 bash`

確認

```
$ python -V
Python 2.7.8
```

再起動後も有効にするために下記を追記する

```~/.bashrc
source /opt/rh/python27/enable
```

### 入れたはいいもののエラーが出るようになってしまった
```
$ gsutil -v
Traceback (most recent call last):
  File "/usr/local/share/google/google-cloud-sdk/platform/gsutil/gsutil", line 22, in <module>
    gsutil.RunMain()
  File "/usr/local/share/google/google-cloud-sdk/platform/gsutil/gsutil.py", line 107, in RunMain
    import gslib.__main__
  File "/usr/local/share/google/google-cloud-sdk/platform/gsutil/gslib/__main__.py", line 39, in <module>
    import boto
  File "/usr/local/share/google/google-cloud-sdk/platform/gsutil/third_party/boto/boto/__init__.py", line 1216, in <module>
    boto.plugin.load_plugins(config)
  File "/usr/local/share/google/google-cloud-sdk/platform/gsutil/third_party/boto/boto/plugin.py", line 93, in load_plugins
    _import_module(file)
  File "/usr/local/share/google/google-cloud-sdk/platform/gsutil/third_party/boto/boto/plugin.py", line 75, in _import_module
    return imp.load_module(name, file, filename, data)
  File "/usr/lib/python2.6/site-packages/google_compute_engine/boto/compute_auth.py", line 19, in <module>
    from google_compute_engine import logger
ImportError: No module named google_compute_engine
```

Python 2.6へ戻した。
kintone とクローバ PAGEの連携 

#クローバ PAGE

Web ページ作成ツールですが、標準機能で kintone 連携可能です。
２ページまでは、無料で使用できますので、早速使ってみました。
用途によっては、業務でも使えるかもしれません。
※[アンケートアプリ](http://qiita.com/rex0220/items/3732e8d7e6bcab10d435)版の試作も試作しています。

#ページトップ画面
ページのデザインはいくつかのパターンから選べますが、kintone 連携できるパーツは、右下に配置されるようです。

![image](https://qiita-image-store.s3.amazonaws.com/0/100572/00f74232-d5a2-e2ac-7bb4-076756a1e3de.png)


#お問い合わせダイアログ表示（kintone連携）

設定された入力項目に入力して、送信します。
メールアドレスが未登録のユーザーは、確認メールが送信されます。
不正なメールアドレスでは、登録ができない仕組みになっています。

![image](https://qiita-image-store.s3.amazonaws.com/0/100572/4634aadc-af3c-6c8f-bb09-c4af3be221d5.png)

#入力詳細画面

入力内容が表示されます。

![image](https://qiita-image-store.s3.amazonaws.com/0/100572/6d04603a-5738-89bd-6b96-7536e5ece0db.png)

#kintone アプリ詳細画面

入力された内容が、kintone アプリに自動で登録されます。

![image](https://qiita-image-store.s3.amazonaws.com/0/100572/5c1ebb68-6d1d-79ea-0ddd-a56d0b8dc26a.png)


#クローバ PAGEの設定

[クローバ PAGE ヘルプ](http://help.qloba.com/index.htm)の通りに設定すると、簡単に kintone 連携ができます。

ページは、プロジェクトという単位で管理します。
無料枠では、２プロジェクトまで

![image](https://qiita-image-store.s3.amazonaws.com/0/100572/b1116245-7405-80dc-675e-3fe498e86381.png)


#プロジェクトの設定

kintone 連携に関連するのは、フォームとサービス連携です。

![image](https://qiita-image-store.s3.amazonaws.com/0/100572/9d2a958a-4b72-606b-bae6-21927970514a.png)

#フォーム設定

![image](https://qiita-image-store.s3.amazonaws.com/0/100572/4b1f2308-5568-2b26-2b4d-ab14fe29fc75.png)

#フォームの項目設定

必須項目と追加項目を設定できます。
「[kintone向けのWebフックを追加する](http://help.qloba.com/integrations.htm)」に指定できる項目の説明があります。
追加項目のフィールドコードは、field_1、field_2 ... になります。

![image](https://qiita-image-store.s3.amazonaws.com/0/100572/afeb7b89-8a91-9b26-c3c8-8cb46155236d.png)

#サービス連携

Web フックの設定で kintone 連携の設定を行います。

![image](https://qiita-image-store.s3.amazonaws.com/0/100572/ae8ded3e-8de7-0ed0-35b8-d42e4406791f.png)


#Web フック

サービスに kintone を選択して、URL, アプリID, APIトークンを指定します。

![image](https://qiita-image-store.s3.amazonaws.com/0/100572/b1c44dab-f3d2-b39d-0b8d-866bca9c7633.png)

#まとめ

kintone 外部連携は、いろいろな仕組みがありますが、無料で簡単に使用できるのは大きなメリットだと思います。
項目のカスタマイズも可能ですので、簡単な入力フォームとして活用できます。
Raspberry Pi 2でLチカ　個人的まとめ

#Vimのコマンド
(C言語使用の場合はwiringPiのインストールが必須)

方法➀　GPIOピンを出力モードに初期化 　    $gpio -g mode ピン番号 out

     　LED点灯   $gpio -g write ピン番号 1
       LED消灯　 $gpio -g write ピン番号 0

方法➁　Pythonで記述
       1,おまじない                 #!/usr/bin/python
       2,GPIOライブラリのインポート
import RPi.GPIO as GPIO
       3,チャンネルの指定
GPIO.setmode(GPIO.BCM)
       4,チャンネルのモード設定
GPIO.setup([GPIOピン番号, GPIO.OUT)
5,デジタル出力
GPIO.output([GPIOピン番号, GPIO.True/False)
　　　　
GPIO入力
GPIO.input(GPIOピン番号)   

方法➂　C言語で記述
       1,wiringPiの初期化
if(wiringPiSetupGpio() == -1) return 1;
       2,チャンネルのモード設定
pinMode(GPIOピン番号, OUTPUT/INPUT);
       3,出力
digitalWrite(GPIOピン番号, 0/1);

その他は随時追加

#ブレッドボード配線
・マイナス端子をラズパイのグランド端子に接続(グラウンド端子は8つしかないので、ブレッドボードのグラウンド線を使用) (画像は、ツール・ラボ第23回 https://tool-lab.com/make/raspberrypi-startup-23/ より)
![bb-61.png](https://qiita-image-store.s3.amazonaws.com/0/135833/2fc4cf7a-8932-cf28-b00f-0634a46a6c03.png)


・プラス端子をラズパイの3.3V/5V端子に接続

・実体配線図(画像は ツール・ラボ 第17回 https://tool-lab.com/make/raspberrypi-startup-17/ より)
![circuit-real.png](https://qiita-image-store.s3.amazonaws.com/0/135833/4ada2543-7d5b-f9ec-84ee-ec4356120c6a.png)

・ラズパイ2のGPIOピン配置(画像は、http://elinux.org/File:Pi-GPIO-header.png より)
![Pi-GPIO-header.png](https://qiita-image-store.s3.amazonaws.com/0/135833/241f0097-2ca9-4919-0477-871d6a8e715d.png)
semaphore setup


## why semaphore

semaphoreはansible towerというwebGUIからansible-playbookを実行するツールのOSS版です。

[github:semahore](https://github.com/ansible-semaphore/semaphore)

## dependencies

+ MySQL >= 5.6.4/MariaDB >= 5.3

+ ansible in $PATH

+ git >= 2.x in $PATH

## setup

公式ではmysqlはdockerでセットアップしています

```docker
docker run -d --name=mysql -p 127.0.0.1:3306:3306 -e MYSQL_ROOT_PASSWORD=my-secret-pw mysql
```

普通にサーバ上に入れる場合は``` yum ``` などを使ってください。

+ mysql

```install.sh
sudo yum install mysql-community-server mysql-community-client mysql-community-common mysql-community-libs mysql-community-libs-compat
```

+ ansible

epel repoで提供されているので追加しinstallする

```install.sh
wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm  
rpm -ivh epel-release-6-8.noarch.rpm  
yum install ansbile
```

+ semaphore

[release](https://github.com/ansible-semaphore/semaphore/releases) ここからディストリビューションにあったバイナリを取得

```install.sh
curl -L https://github.com/ansible-semaphore/semaphore/releases/download/v2.0.4/semaphore_linux_amd64 > /usr/bin/semaphore
```

あとは下記でsetupが開始されます

```setup
/usr/bin/semaphore -setup
```

setup中、mysqlの情報やアカウント情報などの入力が求められるので、自分の環境に沿ったものを入力(入力した情報はconfig.jsonに記載される)

以上でsetupは完了
あとはconsoleに出力されている通り起動する

```execute
/usr/bin/semaphore -config /tmp/semaphore/semaphore_config.json
```

```background
nohup /usr/bin/semaphore -config /tmp/semaphore/semaphore_config.json > /dev/null 2>&1 &
```
Raspberry Pi 2でvim操作　個人的まとめ

ソースファイル新規作成(既存ファイル指定で編集可)　　　　$ vim ファイル名

ソースファイル保存＆終了　　　ノーマルモード(Escキー)で　:wq

ソースファイル編集　　Insertモード(iキー)で文字入力

ディレクトリ参照　　$ls (アルファベット小文字ｴﾙｴｽ)

ファイル名変更   $vim 変更前ファイル名　変更後ファイル名

ファイルの中身確認(編集不可)  $cat ファイル名

~.cファイル コンパイル　 $sudo gcc ファイル名 -o ファイル名 -lwiringPi

~.cファイル　実行   $sudo ./ファイル名

~.pyファイル　コンパイル　　$chmod a+x ファイル名.py

~.pyファイル　実行　　$./ファイル名.py
Railsでskip_before_actionにてifとonly(except)を併用できない

# 問題
```rb
skip_before_action :hoge, only: :method_a, if: -> { condition }
```

とすると`if`オプションが無視される。`skip_before_action`コールバックに限った話では無さそうだが、検証していないのでここでは一般化しない。[claudiob氏のコメント](https://github.com/rails/rails/pull/18404#issuecomment-172461316)を読むにRails 5で修正されているかもしれない。
一応その時点でのドキュメントには以下のように書いてあった

> Note that <tt>:only</tt> has priority over <tt>:if</tt> in case they
> are used together.
>
>   only: :index, if: -> { true } # the :if option will be ignored.
>
> Note that <tt>:if</tt> has priority over <tt>:except</tt> in case they
> are used together.
>
>   except: :index, if: -> { true } # the :except option will be ignored.
>

# 回避策
あまり気が進まない方法ではあるが、

```rb
skip_before_action :hoge, if: proc { condition && action_name == 'method_a' }
```

とするという[issue](https://github.com/rails/rails/issues/9703#issuecomment-223574827)を見ているとコメントが見られた。
# 参考
- [skip_before_filter strange behavior when using if and only together](https://github.com/rails/rails/issues/9703#issuecomment-223574827)
- [Add test case and documentation for skip_before_filter.](https://github.com/rails/rails/pull/18404#issuecomment-129390803)
bitmapリサイズ

存在するbitmapから新たなbitmapに大きさを変えたデータを入れる処理です

```java
        //前提としてoriginal_imgに何かデータが入っているとします

        Bitmap img;

        //元の画像用の縦横の大きさを取得するための変数
        int width;
        int height;

        //元のbitmapから横幅と縦幅を取得
        width = original_img.getWidth();
        height = original_img.getHeight();

        //この辺で取得した横幅と縦幅を変えてリサイズします
        //例として今回は元データの1/4の画素数に変換します
        width=width/4;
        height=height/4;

        //imgにリサイズしたデータを入れます
        img= Bitmap.createScaledBitmap(original_img,width,height,false);
```

img= Bitmap.createScaledBitmap(original_img,100,100,false);
とかにすると100×100で精製されます


物忘れはよくないね
Virtualboxのvdi（Linux guest + LVM）を圧縮する

#はじめに
VirtualBoxの仮想ディスクを圧縮したい場合はディスクをゼロクリアするわけですが、この投稿では以下の条件下で実行する場合を想定した説明をいたします。

- ホストOSはWindows
- ゲストOSはLinux系
- ゲストのディスクフォーマットはLVMであること
- LVMであるかぎり、ディストリは問わない（UbuntuだろうがCentOSだろうが可）

#準備
- [SystemRescueCD](https://www.system-rescue-cd.org/SystemRescueCd_Homepage)のISOをDLする
- VMの不必要なデータ（yumやaptのキャッシュなど）をクリーニングしておく
    - 特に古くて使っていないカーネルは削除推奨
- VMをシャットダウンする

# 作業開始までの手順

1. SystemRescueCDのISOをVMの仮想CDにマウントする
2. VMを起動
3. 起動中にキーボードロケールを選択する（作業に影響はないので任意）

# ゼロクリアの作業
`# fdisk -l`
で該当パーティション確認後、
`# zerofree -v /dev/mapper/該当するLV-ROOT`
を実行してゼロクリアを行う。終わったらVMをシャットダウンする（落としたらCDのマウント解除を忘れずに！）。

# 圧縮
1. 仮想ディスクマネージャを起動し、圧縮するディスクを選択する。
2. ディスクの情報が現れるので、VDIのパスかUUIDのどちらかをコピーする。
3. コマンドプロンプトを立ち上げ、VirtualBoxのディレクトリ（Windows Hostである場合、デフォルトはC:\Program files\Oracle\VirtualBox\）に入る。
4. 以下のコマンドを入力して圧縮開始。
    `> vboxmanage modifyhd --compact UUIDまたはパス`
5. 実行後、ディスク容量が減っているかを確認しておしまい。

# おわりに（おまけ）
FreeBSD＋ZFSの組み合わせでゼロクリを試みようとしたのですが、CoWの関係から不可能なようです。。。。

(2017/10/10追記)
公式のフォーラムでも今年5月に（改めて）議論があり、できないとの結論が出ていた模様です。
https://forums.freebsd.org/threads/60737/
shiny::tabsetPanelの再描画

# shiny::tabsetPanelのふるまい
s1とs2の二つのタブを持つ`shiny::tabsetPanel`を作りました。

![2.png](https://qiita-image-store.s3.amazonaws.com/0/134781/0d12c0a8-9ac5-5c4d-0e91-914acd3ea79c.png)

```r
library(shiny)
ui <- shiny::shinyUI(fluidPage(
    shiny::tabsetPanel(id='tabset',type = "tabs", 
                shiny::tabPanel('s1', verbatimTextOutput("vTO1")),
                shiny::tabPanel('s2', verbatimTextOutput("vTO2"))
    )
))
server <- shiny::shinyServer(function(input, output) {
    output$vTO1<-shiny::renderText({
        d<-"1"
        str(d)
        return(d)
    })
    output$vTO2<-shiny::renderText({
        d<-"2"
        str(d)
        return(d)
    })
})
shiny::shinyApp(ui = ui, server = server)
```
shinyは賢くて、描画のために`shiny::renderText`を一度だけしか呼び出しません。二回目以降に描画する際にはキャッシュを使っているのでしょう。
s1とs2を交互に複数回クリックしても、Consoleの表示は以下のままで変わりません。

```
> runApp('20160802')

Listening on http://127.0.0.1:7074
 chr "1"
 chr "2"
```

# shiny::reactiveValuesの導入
タブをクリックした際に必ずアクションを起こしたかったので、`shiny::reactiveValues`をグローバル定数のように使ってみました。`shiny::shinyServer`を以下のように変更しました。

```r
server <- shiny::shinyServer(function(input, output) {
    #
    d<-shiny::reactiveValues()
    #
    output$vTO1<-shiny::renderText({
        d$clicked<-"1"
        str(d$clicked)
        return(d$clicked)
    })
    output$vTO2<-shiny::renderText({
        d$clicked<-"2"
        str(d$clicked)
        return(d$clicked)
    })
})
```

こうすると、クリック時に`d`を更新する必要があるので、`shiny::renderText`が毎回呼び出されることになります。以下がConsoleの表示です。

```
> runApp('20160802')

Listening on http://127.0.0.1:7074
 chr "1"
 chr "2"
 chr "1"
 chr "2"
 chr "1"
```
[java] Enum の「equals」vs「==」(右の勝ち)

結論だけ知りたい人のためにタイトルに結論を書いておきました。

## Enumでは「equals」と「==」はどちらが強いのか

```java
public void hoge(Code code) {
	
	// equalsの場合　〜〜
	if (Code.Success.equals(code)) {
		// 成功
	}

	// ==の場合　〜〜
	if (Code.Success == code) {
		// 成功
	}
}

enum Code {
	Error,
	Success,
}
```

# 結論
Enumのequalsの実装を見れば一目瞭然ですね

```java:Enum.java
@Override
public final boolean equals(Object other) {
    return this == other;
}
```

## [補足] == の方が強い理由その1
```java:文字数比較.java
if (code.equals(Code.Success)) { }
if (code == Code.Success) { }
                          // 1   5文字少ない!!!
                          //  2 4
                          //   3
```

## [補足] == の方が強い理由その2
```java:ぬるぽ.java
Code code = null;

// NullPointerException発生
if (code.equals(Code.Success)) { }

// こっちは大丈夫
if (code == Code.Success) { }
```

## [補足] == の方が強い理由その3
~~今時はLintが指摘してくれるからあまり意味は無いが……~~

```java:コンパイル.java
String code = "Error";

// コンパイルが通ってしまう
if (Code.Success.equals(code)) { }

// コンパイルエラーになるのでバグの混入を防げる　
if (Code.Success == code) { }
```
JavaScript 連想配列の任意のキーでのソート方法


## 固定のキー

```js
// ソート対象のデータ
let users = [
    {id: 1, name: "ジャック", birthdate: "1996/10/01", age: 20},
    {id: 2, name: "ジョン", birthdate: "1990/05/05", age: 26},
    {id: 3, name: "ボブ", birthdate: "1996/11/14", age: 20},
    {id: 4, name: "マイケル", birthdate: "1995/10/01", age: 21},
    {id: 5, name: "アルバート", birthdate: "1984/09/10", age: 32},
    {id: 6, name: "メアリー", birthdate: "1994/07/22", age: 22},
    {id: 7, name: "ジョン", birthdate: "1997/08/02", age: 19},
    {id: 8, name: "フランク", birthdate: "1990/09/10", age: 26},
    {id: 9, name: "ボブ", birthdate: "1988/08/02", age: 28},
    {id: 10, name: "ダニエル", birthdate: "1994/04/02", age: 22}
];

// age, idの順にソート（昇順）
users.sort((a, b) => {
	if (a.age < b.age) return -1;
	if (a.age > b.age) return 1;
	if (a.id < b.id) return -1;
	if (a.id > b.id) return 1;
	return 0;
});
```

## 任意のキー

```js
// ソート対象のデータ
let users = [
    {id: 1, name: "ジャック", birthdate: "1996/10/01", age: 20},
    {id: 2, name: "ジョン", birthdate: "1990/05/05", age: 26},
    {id: 3, name: "ボブ", birthdate: "1996/11/14", age: 20},
    {id: 4, name: "マイケル", birthdate: "1995/10/01", age: 21},
    {id: 5, name: "アルバート", birthdate: "1984/09/10", age: 32},
    {id: 6, name: "メアリー", birthdate: "1994/07/22", age: 22},
    {id: 7, name: "ジョン", birthdate: "1997/08/02", age: 19},
    {id: 8, name: "フランク", birthdate: "1990/09/10", age: 26},
    {id: 9, name: "ボブ", birthdate: "1988/08/02", age: 28},
    {id: 10, name: "ダニエル", birthdate: "1994/04/02", age: 22}
];

// ソートの優先するキーと順序のリスト
// age, name, idの順にソート
const order = [
	{key: "age", reverse: false},
	{key: "name", reverse: false},
	{key: "id", reverse: false}
];

// ソート関数（デフォルトで昇順）
function sort_by(list) {
	return (a, b) => {
		for (let i=0; i<list.length; i++) {
			const order_by = list[i].reverse ? 1 : -1;
			if (a[list[i].key] < b[list[i].key]) return order_by;
			if (a[list[i].key] > b[list[i].key]) return order_by * -1;
		}
		return 0;
	};
}

// ソート
users.sort(sort_by(order));
```

ソート用の関数に`{key: "ソート対象のキー", reverse: false}`形式のオブジェクトのリストを渡すことでそのキーを基準にソートする。
リストの前の方が優先度が高い、`reverse: false`が昇順で`true`に変えると降順になる。
Ruby 2.4.0の新機能 「String supports Unicode case mappings」 を試す


先日Ruby2.4.0-preview1がリリースされましたね。

https://www.ruby-lang.org/en/news/2016/06/20/ruby-2-4-0-preview1-released/

大きな機能変更の一つとして、**String supports Unicode case mappings**があります。要するに、**upcase、 downcase、swapcase、capitalizeがunicode文字に対応した**ということです。

試しにRuby2.4.0-preview1で、以下の文字をswapcaseしてみました。

```rb
p 'ⅵ'.swapcase
p 'Ⅸ'.swapcase
p 'Å'.swapcase # オングストローム
p 'ａ'.swapcase # 全角小文字
p 'Ａ'.swapcase # 全角大文字
```

以下が結果です。

```rb
"Ⅵ" # 2.3.0では "ⅵ"
"ⅸ" # 2.3.0では"Ⅸ"
"å" # 2.3.0では "Å"
"Ａ" # 2.3.0では "ａ"
"ａ" # 2.3.0では "Ａ"
```

unicode文字でも変換できました。
あんまり使う機会なさそうですけど・・・
JavaScriptのフレームワーク、 Meteor を試してみる 

Node.jsで動くフレームワーク、[Meteor](https://www.meteor.com/) :stars: のチュートリアルにチャレンジしてみた。

https://www.meteor.com/tutorials/blaze/creating-an-app

* Ubuntu 16.04 でチャレンジ。
* コードサンプルはファイル名をクリックして、diffを見ながらやったほうがよさげ。コードの削除がdiffのほうでしか見られません。

## Meteor の特徴

* サーバサイド・クライアントサイド両方込みのNode.jsなフレームワーク。
    * サーバ・クライアント両サイドでのコード共有が簡単。互いの `{server,client}/main.js` からimportするだけ。
* `meteor` コマンドで依存性追加とか起動とかデプロイとか全部賄う系。
* Hot code push
    * ようするにライブリロード＋ホットコードデプロイ。
    * エディタで更新したら、即画面に反映。（WebSocketで更新もらってるっぽい。）
    * 特に自分でブラウザをリロードしたり、サーバを再起動させたりするほとんど必要なさそう。
* データストアはMongoDB。

エディタ開きながら画面見つつ、テキトーにプロトタイピングしつつプログレッシブに開発できそうです。

Meteorで作られたものといえば、代表的なものに [RocketChat](http://rocket.chat) があります。個人的にも使ってますが、なかなか出来がよく、アプリの設定を変えると即画面に反映されたり、アプリをアップデートしてもクライアントの画面を明示的にリフレッシュしないままクライアント側のアップデートが完了するのが驚きですね。

## meteor立ち上げてるのに、別ターミナルでMongoDBにつながらねえ。

* meteorは起動時にローカルでMongoDBを立ち上げますが、`meteor mongo`で繋がらん。
* たぶんmeteorのバグ。 `ps ax | grep -P '^\s*(\d+).+mongod .+--port (\d+) --dbpath (.+(?:\/|\\)db)'` 相当の検索をして、そこで取れたポートやDBパスをプロジェクトのものと比較するようだが、それの比較に失敗していると思う。
* 自前でMongoDBクライアントインストールしてつなぎましょう。
    * `sudo apt install -y mongodb-clients` してから、 `mongo localhost:$(cat .meteor/local/db/METEOR-PORT)/meteor`
    * ポートは多くの場合、3001だと思います。 `.meteor/local/db/METEOR-PORT` に書いてあります。（普通にこっちに繋いでくれりゃいいのに…）


## 感想

* Webアプリをプロトタイピングしながら高速に作りたい人向け。
    * ライブリローディング。
    * MongoDBがスキーマレス。
    * ログイン用のUIと仕組みとか最初から用意されてる。
    * おそらくミッションクリティカルなシステムには向いてないと思う。
    * Meteorから外れた使い方をしたい場合には向いてなさそう。
* ↓いつ画面にリロードかかってもいいような書き方を強制されている気がする。

```js
Template.task.events({
  'foo'() {
    //
  },
  'bar'() {
    //
  },
});
```

* スタック、コードの置き方がまとめられていて応用しやすい。まさにフレームワーク！
* MongoDBの高性能さをうまく利用したリアクティブな使い方をしている。（MongoDBの中の値を変更 → 画面に即反映とか。）
* テンプレート用ミニ言語が嫌いなんですが、どうにかなりませんか？

```html:テンプレートの例
  <ul>
    {{#each tasks}}
      {{> task}}
    {{/each}}
  </ul>
```

近々しょぼい社内システムを作るかもしれないので、Meteorでチャレンジしてみるかもしれません。

## 参考

* [フルスタックJSフレームワークMeteorのメリット＆デメリット](http://qiita.com/ytakzk/items/f5417c1fe3cc9b5e80c8)
* [体感！JavaScriptで超速アプリケーション開発 －Meteor完全解説](http://gihyo.jp/dev/serial/01/meteor/0012)
ScalaのAkkaで実行途中で終了する

Akkaプロジェクトを開発している時、環境によってはCtrl-Cで終了が出来ません。なので、Enterを押すとAkkaを終了させるようなコードを書きます。

以下は簡単なSprayプロジェクトです。Bootオブジェクトの最後2行でEnterが押された時の処理を記述しています。

```scala
import akka.actor.{Actor, ActorSystem, Props}
import akka.io.IO
import spray.can.Http
import akka.pattern.ask
import akka.util.Timeout
import spray.http.MediaTypes._
import spray.routing.HttpService
import scala.concurrent.duration._

object Boot extends App {
  implicit val system = ActorSystem("on-spray-can")
  val service = system.actorOf(Props[MyServiceActor], "demo-service")
  implicit val timeout = Timeout(5.seconds)
  IO(Http) ? Http.Bind(service, interface = "localhost", port = 8080)


  // Enterを押したら終了する Docker等の場合Nullが帰る
  if(io.StdIn.readLine() != null)
    system.terminate()
}

class MyServiceActor extends Actor with MyService {
  def actorRefFactory = context
  def receive = runRoute(myRoute)
}
trait MyService extends HttpService {
  val myRoute =
    path("") {
      get {
        respondWithMediaType(`text/html`) {
          complete {
            <html>
              <body>
                <h1>Say hello to <i>spray-routing</i> on <i>spray-can</i>!</h1>
              </body>
            </html>
          }
        }
      }
    }
}
```

build.sbt

```scala
libraryDependencies ++= {
  val akkaV = "2.4.8"
  val sprayV = "1.3.3"
  Seq(
    "io.spray" %% "spray-can" % sprayV,
    "io.spray" %% "spray-routing" % sprayV,
    "io.spray" %%  "spray-json" % "1.3.2"
  )
}

Revolver.settings

fork in run := true
connectInput in run := true
```
Springboot1.4でテストを階層化

SpringbootでHierarchicalContextRunnerを使用して、テストの階層化を実現します。
## 依存関係
```XML:pom.xml
<dependency>
  <groupId>de.bechte.junit</groupId>
  <artifactId>junit-hierarchicalcontextrunner</artifactId>
  <version>4.12.1</version>
  <scope>test</scope>
</dependency>
```
## 実装
* Controllerクラスのテストを想定してます。

```java:HogeControllerTest.java
@RunWith(HierarchicalContextRunner.class) --(1)
public class HogeControllerTest {
    /**
     * ベースクラス
     */
    @RunWith(SpringRunner.class)
    @SpringBootTest
    @AutoConfigureMockMvc
    @WebAppConfiguration
    public static class HogeControllerTestBase { --(2)
        @ClassRule
        public static final SpringClassRule SPRING_CLASS_RULE = new SpringClassRule(); --(3)
 
        @Rule
        public final SpringMethodRule springMethodRule = new SpringMethodRule(); --(3)
 
        @Autowired
        protected MockMvc mockMvc;
 
        @MockBean
        protected HogeService service;
    }
 
    /**
     * 一覧画面のテスト
     */
    public class HogeControllerTest_ほげ一覧画面 extends HogeControllerTestBase { --(4)
        @Test
        @WithMockUser(username="test")
        public void indexTest_正常系() throws Exception {
            // 何かしらのテストコード
        }
    }
 
    /**
     * 編集画面のテスト
     */
    public class HogeControllerTest_ほげ編集画面 extends HogeControllerTestBase { --(4)
        @Test
        @WithMockUser(username="test")
        public void updateTest_正常系() throws Exception {
            // 何かしらのテストコード
        }
    }
}
```
#### (1) ランナー指定
* 階層化を実現するためにHierarchicalContextRunnerをランナーとして指定します。
* 階層化する手法としてはenclosed.classもありますが、こちらのほうが柔軟に階層化することができるようです。

#### (2) 基底クラス
* 非テスト対象として宣言するため、staticなインナークラスとして定義します。
* 付与するアノテーションはお決まりのやつです。ここらへんはメタアノテーション化してもいいかも。

#### (3) SpringClassRule、SpringMethodRule
* JUnitが提供しているTheoriesやParameterizedランナーを使用したいときや、Mockitoなどのサードパーティが提供しているランナーを使用したい時に指定します。   
[Spring JUnit 4 Rules](http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#testcontext-junit4-rules)

#### (4) テスト実装クラス
* 基底クラスを継承して、publicで非staticなクラスとします。

## 参考
* [JUnit 4.12 の階層構造と JMockit を組み合わせて使う](http://qiita.com/opengl-8080/items/780511744253fc91a7ec)
【Swift】WKWebViewでCookieを全削除する方法

## 背景
iPhoneでデモアプリを作成している際に、Cookieをすべて削除する必要が出てきました。

```swift
let storage = NSHTTPCookieStorage.sharedHTTPCookieStorage()
for cookie in storage.cookies!{
    storage.deleteCookie(cookie)
}
```

こんな感じのことも試したんですが、そもそもCookie作ってるのに、存在していない模様。いろいろ調べたんですがObjective-Cの記事ばかりだったので、それを参考にして解決しました。

## 解決方法

```swift
let libraryPath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.LibraryDirectory, NSSearchPathDomainMask.UserDomainMask, true)[0]
let cookiesFolderPath = libraryPath.stringByAppendingString("/Cookies")
do {
   try NSFileManager.defaultManager().removeItemAtPath(cookiesFolderPath)
}catch {
   // error handling
}
```

Cookieはシミュレータ上では、Mac上のディレクトリに保存されているようです。ですので、そのディレクトリのパスを取得し、その中身をすべて消すという方でとりあえず解決しました。

実機でやったらどうなるんでしょうか、やってみた方がいらっしゃればコメントいただけると幸いです。
Pythonで書いた指数移動平均(EMA)のコードの比較

移動平均のなかで、単純移動平均(SMA)の次によく使われるのは指数移動平均(EMA)でしょう。EMAを使うテクニカル指標として有名なMACDをはじめ、EMAを複数回使うDEMA、TEMA、TriXというのもあるし、AMA、FrAMA、VIDyAのように適応型移動平均は、計算方法としてEMAを利用しています。

今回は、
[IIRフィルタ型の移動平均をpandasとscipyで比較してみた](http://qiita.com/toyolab/items/9906573cfcd379f3eff8)
の続きとして、EMAのコードをいくつか比較してみます。

# EMAの計算式

EMAを実際に使う際には期間をパラメータとして入れますが、ここではEMA本体のパフォーマンスを調べるために計算式を直接使います。

$$y(n)=\alpha x(n)+(1-\alpha)y(n-1)$$

つまり、EMAのパラメータは上式の$\alpha$とします。

# pandasによる実装

まず、EMAをかける入力データを
[Numba使用を前提とした単純移動平均のPythonコードについて](http://qiita.com/toyolab/items/8d30183dae162e53de24)
と同じくランダムウォークとして作っておきます。

````py
import numpy as np
import pandas as pd

dn = np.random.randint(2, size=100000)*2-1
gwalk = np.cumprod(np.exp(dn*0.01))*100
````
pandasでは、Seriesクラスに変換して`ewm`と`mean`メソッドで簡単にEMAを実行できます。`ewm`のパラメータとして`alpha`を直接代入することもできます。`alpha`は0から1の範囲で特に値による違いはないので、ここでは0.15を入れておきます。

````py
def EMA1(x, alpha):
    return pd.Series(x).ewm(alpha=alpha).mean()

%timeit y1 = EMA1(gwalk, 0.15)
````
実行時間は以下の通りです。

    100 loops, best of 3: 8.62 ms per loop

# scipyのlflterによる実装

[IIRフィルタ型の移動平均をpandasとscipyで比較してみた](http://qiita.com/toyolab/items/9906573cfcd379f3eff8)
と同じようにscipyのフィルタ関数lfilterを使った実装です。

````py
from scipy.signal import lfilter
def EMA2(x, alpha):
    y,zf = lfilter([alpha], [1,alpha-1], x, zi=[x[0]*(1-alpha)])
    return y

%timeit y2 = EMA2(gwalk, 0.15)
````
実行時間は次のようになりました。

    1000 loops, best of 3: 631 µs per loop

前回の記事はここまでで、scipy速いということだったのですが、今回は続きがあります。

# Numbaを利用した計算式の直接実装

EMAの計算式を直接コーディングします。ただし、そのままだとすごく遅くなるので、Numbaを使って高速化します。

````py
from numba import jit
@jit(nopython=True)
def EMA3(x, alpha):
    y = np.empty_like(x)
    y[0] = x[0]
    for i in range(1,len(x)):
        y[i] = alpha*x[i] + (1-alpha)*y[i-1]
    return y

%timeit y3 = EMA3(gwalk, 0.15)
````
`@jit`の引数に`nopython=True`をつけてエラーが出なければ高速化が期待できます。実際、実行時間は

    1000 loops, best of 3: 227 µs per loop

となり、scipyより速くなりました。

EMAの場合も、Numbaを使えば直接コーディングが最速という結果となりました。
【Swift】WKWebViewのリダイレクト先URL（URLスキーム）に応じて動作したい時にハマったこと

## 背景
iPhoneアプリで、WKWebViewでとあるURLを開き、何度かリダイレクトを挟んだ後に最終的にURLスキームにたどりついたときに、そのURLスキームに応じた動作をする必要がありました。しかし、URLスキームはリダイレクトしてくれなかったのでその解決方法です。

```swift:ViewController.swift
// リダイレクト時に呼ばれる関数
func webView(webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) {
        if let url = webView.URL?.absoluteString {
            // ここでURLに応じた処理を書く
        }
}
```


## 解決方法
didReceiveServerRedirectForProvisionalNavigationはデフォルトでは、http~とhttps~のみをリダイレクト対象として呼び出されるようでした。どのURLをリダイレクトとして扱うかのハンドリングをしている関数が、func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void)です。使い方は以下のとおり。

```swift:ViewController.swift
func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {
        if let url = navigationAction.request.URL?.absoluteString{
            if(url.hasPrefix("URLスキーム")){//この部分を処理したいURLにする
                // リダイレクトとして扱う
                decisionHandler(WKNavigationActionPolicy.Allow)
            }else if(url.hasPrefix("http")){
                decisionHandler(WKNavigationActionPolicy.Allow)
            }else{
                // リダイレクトとして扱わない
                decisionHandler(WKNavigationActionPolicy.Cancel)
            }
        }
}
```

この関数内でハンドリングを行うのですが、特定のURLリクエストに対して、Allowしてあげるとリダイレクトとして扱われ、didReceiveServerRedirectForProvisionalNavigationが呼び出されます。特定のURLやhttp~以外を弾きたかったので、今回はelseにCancelを書いています。

参考になれば幸いです。
EPPlusでちょっとばっかし注意すること　その2

#どー言うことだってばよ

追加で検証するため､EPPlusのソースコード読んでいたら､おやと思うことがあったので､とりあえずまとめておく｡

#何が起きるのか
下記のような操作をしたとする｡

```csharp

using System;
using System.IO;
using OfficeOpenXml;

namespace EPPlusSurvey
{
	class Program
	{
		static void Main(string[] args)
		{
			using (var package = new ExcelPackage(new FileInfo("Sample.xlsx")))
			{
				var sheet = package.Workbook.Worksheets[1];

				//A1:B10の矩形範囲にはすべて値が詰まっている｡
				var range = sheet.Cells["A1:B10"];

				var foo = range.GetEnumerator();
				var bar = range.GetEnumerator();


				foo.MoveNext();
				foo.MoveNext();

				bar.MoveNext();
				bar.MoveNext();

				//こいつはTrueになる｡
				Console.WriteLine(ReferenceEquals(foo, bar));

				//だもんで､foo及びbarをMoveNextした結果が､それぞれにに反映される｡

				//foo:B2
				Console.WriteLine($"foo:{foo.Current.Address}");

				//bar:B2
				Console.WriteLine($"bar:{bar.Current.Address}");
			}
		}
	}
}

```

コメントでネタバレしてるけど､GetEnumeratorで取得できるEnumeratorが独立していない｡
なので､上記サンプルで､`foo`及び`bar`に対する操作の結果が､それぞれに反映されてしまうことになる(つまり､MoveNextの結果が累積している)｡
このような操作をするシナリオはそんなに無いだろうけど､ステートの保持を目的としてEnumeratorを保持して､長い間使い回したりすると､問題が起きるかも知れないのでご注意の程｡

#回避策
じゃあ､回避策はあるのかというと､`range`変数を使わずに､都度都度`sheet.Cells`プロパティでRangeを取得すれば回避できる｡

```csharp
using System;
using System.IO;
using OfficeOpenXml;

namespace EPPlusSurvey
{
	class Program
	{
		static void Main(string[] args)
		{
			using (var package = new ExcelPackage(new FileInfo("Sample.xlsx")))
			{
				var sheet = package.Workbook.Worksheets[1];

				//A1:B10の矩形範囲にはすべて値が詰まっている｡
				var rangeA = sheet.Cells["A1:B10"];
				var rangeB = sheet.Cells["A1:B10"];

				//Falseになる｡
				Console.WriteLine(ReferenceEquals(rangeA, rangeB));

				var foo = rangeA.GetEnumerator();
				var bar = rangeB.GetEnumerator();

				foo.MoveNext();
				foo.MoveNext();

				bar.MoveNext();


				//当然こいつはFalseになる｡
				Console.WriteLine(ReferenceEquals(foo, bar));

				//共々独立しているのでめでたしめでたし

				//foo:B1
				Console.WriteLine($"foo:{foo.Current.Address}");
				//bar:A1
				Console.WriteLine($"bar:{bar.Current.Address}");
			}
		}
	}
}
```

こんなケースはまれだろうけど､一般的なGetEnumeratorの戻り値と異なっているので､その点注意しないとマズいかと思って一応まとめてみた｡
[Linux][Python][Pandas] Microsoft Accessのデータベース(*.mdb)をPandasで読み込む

Microsoft Access (*.mdb) のデータを読み込んで解析したい機会があったのでメモ
基本的には pandas_access を使用すれば良かった。

[jbn/pandas_access: A tiny, subprocess-based tool for reading a MS Access database (.rdb) as a Pandas DataFrame.](https://github.com/jbn/pandas_access)

※mdbtoolsのWindowsでの動作確認ができていないため、これはLinux限定の記事になります。

# 実行手順
## mdbtoolsのインストール

pandas_access は mdbtools のラッパーのようなものらしいので、mdbtoolsが必須。

[brianb/mdbtools: MDB Tools - Read Access databases on *nix](https://github.com/brianb/mdbtools)

```console:mdbtoolsのインストール（Ubuntu）
$ sudo apt-get install mdbtools
```

## pandas_acccessの使用

[jbn/pandas_access: A tiny, subprocess-based tool for reading a MS Access database (.rdb) as a Pandas DataFrame.](https://github.com/jbn/pandas_access)

```console:pandas_accessのインストール
$ pip install pandas_access
```

以下実装例

```py3:実装例
import pandas as pd
import pandas_access as mdb

# mdb から dataframe の取得
df = mdb.read_table("DB.mdb", "MyTableName")
```

上記の用に `read_table` をすれば `Dataframe` が取得できるので、あとは通常のpandasの手順で解析を行える

# 補足
ソースを見ればわかるが、`read_table` は `pandas.read_csv` のラッパーなので、第三引数以降に `read_csv` と同じ引数を使用することができる。`read_csv` で使用できる引数は以下などを参照。

[Pythonコーディング備忘録　～その３～（pandasのread_csvを使いこなす） - 自調自考の旅](http://rosyuku.hatenablog.com/entry/2015/09/03/002203)
mysql ターミナルから見た時の文字化けの直し方

ターミナルからSELECT文で見た時に日本語が文字化けしていて ???　で表示されるのでちゃんと表示されるように修正するやり方。

```
$ sudo vi /etc/my.cnf

character_set_server=utf8
skip-character-set-client-handshake
```

my.cnfに上の二行を加えmysqlを再起動だけでなおる。
Vue.js Component Slot によるコンテンツ配信とハマりどころ


https://jp.vuejs.org/guide/components.html#スロットによるコンテンツ配信

Vue.jsでは コンポーネント内の要素に、親要素からコンテンツ(DOM的な)を投げ込む事が出来る。

## slotによるコンテンツ配信


例えば以下の様なテンプレートのコンポーネントを考える。

````
var template = `
<div>
  <h2>私のコンポーネント!</h2>
  <slot></slot>
</div>
`;

const component = {
	template
}
````

親による表記が以下の様なケースでは

````
<body>
	<h1>私のアプリケーション！</h1>
	<my-component>
	  <p>配信コンテンツその１</p>
	  <p>配信コンテンツその２</p>
	</my-component>
</body>
````

以下の様なレンダリングが行われる。

````
<body>
	<h1>私のアプリケーション！</h1>
	<h2>私のコンポーネント!</h2>
	<p>配信コンテンツその１</p>
	<p>配信コンテンツその２</p>
</body>
````

name属性を使用して、複数のslotを使用する事も可能なよう。

## ハマりどころ

最初はコレを、子テンプレートの`template`内slotを単純に置換する類のものだと思っていた。

例えば以下の様なslot配信付きコンポーネント利用の記述を考えた場合、

````
<body>
	<h1>私のアプリケーション！</h1>
	<my-component>
	  <p>配信コンテンツその１</p>
	  <a @click="submit()">CLICK ME!</a>
	</my-component>
</body>
````

`@click="submit()"`のsubmitは親のスコープでの参照となる。

つまり親レベルでコンパイルされた結果が子コンポーネントに配信される。

この辺は「親コンポーネントが子コンポーネントの詳細を知るべきではない(注入に徹する)、的な考えに基づくものなのかなぁ…と思ったり。

あくまで「コンテンツを配信(注入)」するための機能として扱うのが良さそう。

んじゃあテンプレート注入するにはどうすれば良いんよ？って所になるけど、素直にid付きtemplateタグで注入とかするのが良さそう。
MauticでQuick AddしたリードをSegmentに追加する


地味に初見殺しっぽい挙動だったのでメモ。

##Contactは手動で追加できる
なんとなくフォーム問い合わせから追加するのが基本かなと勝手に思ってましたが、管理画面から手作業で追加することも可能です。
展示会などで交換した、名刺はここから追加しましょう。
![スクリーンショット 2016-08-02 14.54.24.png](https://qiita-image-store.s3.amazonaws.com/0/23936/6d2cf666-0426-def0-a2da-c5ac87b5930a.png "スクリーンショット 2016-08-02 14.54.24.png")

## Quick Addでお手軽リード作成
![スクリーンショット 2016-08-02 14.54.33.png](https://qiita-image-store.s3.amazonaws.com/0/23936/1c5ee75f-e33d-fe19-309c-757f48c06ca0.png "スクリーンショット 2016-08-02 14.54.33.png")
サクッと追加したい場合はQuick Addが便利です。

![スクリーンショット 2016-08-02 14.55.03.png](https://qiita-image-store.s3.amazonaws.com/0/23936/25503911-7246-3960-d29b-bd3fc8d02743.png "スクリーンショット 2016-08-02 14.55.03.png")

氏名メールアドレス+αを簡単に追加できます。 


##Segmentを追加するボタン
問題は作ったContactをSegmentに所属させる場合です。
どこから追加したらいいのかなかなかわかりにくいですが、一覧画面右上の円グラフアイコンです。

![Mautic.png](https://qiita-image-store.s3.amazonaws.com/0/23936/d8e2e4fa-f85e-0419-1c89-f90f6104443f.png "Mautic.png")


初見殺しですね。

Segmentを変更したいContactを選択した状態にしてクリックしましょう。

クリックすると、追加するセグメント・削除するセグメントが選べます。
![スクリーンショット 2016-08-02 14.57.39.png](https://qiita-image-store.s3.amazonaws.com/0/23936/38dad88b-df4d-6e85-b861-ee2137b6851c.png "スクリーンショット 2016-08-02 14.57.39.png")

これで保存すればSegmentへの追加完了です。
![スクリーンショット 2016-08-02 14.57.49.png](https://qiita-image-store.s3.amazonaws.com/0/23936/1b5df4eb-557a-5422-2ed8-8391ab8e0171.png "スクリーンショット 2016-08-02 14.57.49.png")
追加されました。
Elastic beanstalk で大きいデータを POST したら nginx が 413 Request Entity Too Large

.ebextensions/01-nginx-max-body.config として次のファイルを突っ込む。

```yaml:.ebextensions/01-nginx-max-body.config
files:
  "/etc/nginx/conf.d/client-max-body-size.conf":
     mode: "000644"
     owner: root
     group: root
     content: "client_max_body_size 10m;"
```
RoBoHoNめも_02：スリープのこととか

# RoBoHon開発めも
RoBoHoN開発のことをめもしていきます！

# スリープ早すぎない？
スリープ時間は１分に設定されてるみたい（なんとなく）
これだと、アプリの実行中にスリープしちゃうので調べてみました。

# マニュアルを見てみる

>6.4.1 プロジェクター照射中のWakeLock について
>プロジェクターマネージャーでは照射中にWakeLock をかけない仕様のため、一定時間無操作の画面OFF 時はプロジ
>ェクター照射を終了します。一定時間以上プロジェクター照射を継続したい場合は、アプリ側にて適宜WakeLock を
>かける必要があります。その際、設定するWakeLock は「SCREEN_DIM_WAKE_LOCK」としてください。

引用：0401_SR01MW_Application_Programming_Guide_V01_00_00.pdf

これしかみあたらなかった。普通のアプリの時はどうすればいいのかな？

# サンプルプログラムを見てみる

WakeLock_Onっていう、なぜか命名規約がほかと違うメソッドを呼んでました。

```java:MainActivity.java(SampleProjector)
    /**
     * WakeLock開始
     */
    private void WakeLock_On() {
        Log.d(TAG, "WakeLock_On()");
        PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
        synchronized (mLock) {
            if (mWakelock == null || !mWakelock.isHeld()) {
                mWakelock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK
                        | PowerManager.ACQUIRE_CAUSES_WAKEUP
                        | PowerManager.ON_AFTER_RELEASE, MainActivity.class.getName());
                mWakelock.acquire();
            }
        }
    }
    /**
     * WakeLock終了
     */
    private void WakeLock_Off() {
        Log.d(TAG, "WakeLock_Off()");
        synchronized (mLock) {
            if (mWakelock != null && mWakelock.isHeld()) {
                mWakelock.release();
                mWakelock = null;
            }
        }
    }
```

SCREEN_DIM_WAKE_LOCKは非推奨ですね。

<img width="783" alt="スクリーンショット 2016-08-02 14.48.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/40994/c32bc221-7266-24d5-bd70-311ab03bfecb.png">

でもまあ、とりあえず、プロジェクターを使う際には、プロジェクター起動時にWakeLock_On()して、プロジェクター終了時にWakeLock_Off()すればいいみたい！

# アプリ実行中のスリープ解除って出来るの？
素朴な疑問が・・・そもそもスリープ解除ってできるのでしょうか？タッチパネルも効かなくなるし、頭のボタンや電源ボタンを押すとホームに戻るから解除できない？そのへんも、マニュアルを探したけどよくわかりませんでした。

# まとめ
プロジェクターじゃないときは結局どうすればいいかわからなかった。

なぜ非推奨の命令をあえて使ってるのか？

```
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
```
FLAG_KEEP_SCREEN_ON じゃだめなのかが知りたい。

よくわかんないなー。

# ロボホンテストルームで聞いてきた！（追記）

SCREEN_DIM_WAKE_LOCKだと画面をちょびっと暗くできるので、こっちを推しているそうです。
電池の減りをすこしでも少なくする工夫とのこと。
別に、FLAG_KEEP_SCREEN_ONでもいけるとのことでした。

ちなみに、アプリ実行中のスリープ解除は話を聞いた限り出来なそう。
なので、スリープしたらアプリ終了させるのが正解みたい。（たぶん）
basic認証のかけかた

すぐ忘れるのでメモ。

```htpasswd -c ファイル名 ユーザ名```

後はパスワードを設定するだけ。

そしてプロジェクトディレクトリ直下の.htaccessに記述してあげる。

```
AuthType        Basic
AuthName        "Input your ID and Password."
AuthUserFile    /file/dir/passfile.dat
require valid-user
```
MAMPのバーチャルホスト + phpstormでどハマりしたので自分ようにメモ。


[xdebug]
zend_extension="/Applications/MAMP/bin/php/php5.6.10/lib/php/extensions/no-debug-non-zts-20131226/xdebug.so"
 xdebug.remote_enable=1
 ;xdebug.remote_host=hoge.localhost
;バーチャルホストの設定を書いてもだめだったので、

xdebug.remote_host=127.0.0.1
;ip決め打ちで対応。
 xdebug.remote_port=9000
 xdebug.remote_autostart=1

よくわからないが動いてるよう。
【メモ】Linux圧縮/解凍コマンド

このドキュメントでは、Linuxで一般的に使用される圧縮・解凍コマンドの一覧を紹介します。

## コマンドオプションの説明

### tar コマンドのオプション
- `-x`: 解凍（extract）
- `-c`: 圧縮（create）
- `-v`: 詳細表示（verbose）
- `-f`: ファイル名指定（file）
- `-z`: gzip形式の圧縮/解凍
- `-j`: bzip2形式の圧縮/解凍
- `-J`: xz形式の圧縮/解凍

## 解凍コマンド例

|解凍対象ファイルの拡張子|コマンド                    |備考                      |
|:---------------------|:-----------------------------|:-------------------------|
|.tar                  |tar -xvf ファイル名           |アーカイブのみ（圧縮なし）|
|.tar.gz .tgz          |tar -xzvf ファイル名          |gzip圧縮されたtarアーカイブ|
|.tar.bz2 .tbz         |tar -xjvf ファイル名          |bzip2圧縮されたtarアーカイブ|
|.tar.xz               |tar -xJvf ファイル名          |xz圧縮されたtarアーカイブ|
|.gz                   |gunzip ファイル名 または gzip -d ファイル名 |単一ファイルのgzip圧縮|
|.bz2                  |bzip2 -d ファイル名 または bunzip2 ファイル名 |単一ファイルのbzip2圧縮|
|.xz                   |xz -d ファイル名 または unxz ファイル名 |単一ファイルのxz圧縮|
|.lha .lzh             |lha x ファイル名              |LHAアーカイブ（要インストール）|
|.zip                  |unzip ファイル名              |ZIPアーカイブ|
|.rar                  |unrar x ファイル名            |RARアーカイブ（要インストール）|
|.7z                   |7z x ファイル名               |7-Zipアーカイブ（要インストール）|


## 圧縮コマンド例

|圧縮対象ファイルの拡張子|コマンド                     |備考                      |
|:---------------------|:------------------------------|:-------------------------|
|.tar                  |tar -cvf ファイル名.tar ファイル名またはディレクトリ|アーカイブのみ（圧縮なし）|
|.tar.gz .tgz          |tar -zcvf ファイル名.tar.gz ファイル名またはディレクトリ|gzip圧縮のtarアーカイブ|
|.tar.bz2 .tbz         |tar -jcvf ファイル名.tar.bz2 ファイル名またはディレクトリ|bzip2圧縮のtarアーカイブ（高圧縮率）|
|.tar.xz               |tar -Jcvf ファイル名.tar.xz ファイル名またはディレクトリ|xz圧縮のtarアーカイブ（最高圧縮率）|
|.gz                   |gzip ファイル名                |単一ファイルの圧縮（元ファイルは削除）|
|.bz2                  |bzip2 ファイル名               |単一ファイルの圧縮（元ファイルは削除）|
|.xz                   |xz ファイル名                  |単一ファイルの圧縮（元ファイルは削除）|
|.lha .lzh             |lha c ファイル名.lzh ファイル名またはディレクトリ|LHAアーカイブ（要インストール）|
|.zip                  |zip -r ファイル名.zip ファイル名またはディレクトリ|ZIPアーカイブ（-rはディレクトリを再帰的に圧縮）|
|.rar                  |rar a ファイル名.rar ファイル名またはディレクトリ|RARアーカイブ（要インストール）|
|.7z                   |7z a ファイル名.7z ファイル名またはディレクトリ|7-Zipアーカイブ（要インストール）|

## 注意事項

- 一部のコマンド（lha, unrar, rar, 7z）は標準でインストールされていない場合があります。必要に応じてパッケージマネージャーでインストールしてください。
  - Debian/Ubuntu: `apt-get install lhasa rar unrar p7zip-full`
  - CentOS/RHEL: `yum install lha unrar p7zip p7zip-plugins`

- 圧縮率と処理速度の一般的な関係:
  - 高速・低圧縮率: gzip
  - 中速・中圧縮率: bzip2
  - 低速・高圧縮率: xz