OmniAICreator/Qiita-1.07M huggingface dataset:
NeoBundle から vim-plug に乗り換えてみた

![スクリーンショット 2015-11-17 0.41.00.png](https://qiita-image-store.s3.amazonaws.com/0/92474/8f51c078-cff0-a2e1-b106-2db0bf20ab0e.png)

タイトルですが, 本当は
おい、NeoBundle もいいけど vim-plug 使えよ
にしたかったです. 勇気が足りなかった

紹介するPlugin
---

[vim-plug](https://github.com/junegunn/vim-plug)

これなに
---

Vundle , NeoBundle と同じ vim plugin manager になります.
一応, NeoBundle より後発[^1]という形になるみたいです.
1ファイルオンリーで管理しているのが特徴.

乗り換えた理由
---

- junegunn world にハマった
- 人と違うのを使いたい
- 早いらしい
  - http://junegunn.kr/images/vim-startup-time.png
  - https://raw.githubusercontent.com/junegunn/i/master/vim-plug/40-in-4.gif
- やりたかったことができる
  - parallel installation
  - lazy load
  - self management
- 設定ファイルの記述が簡単

Install
---

autoload に置いてね, とのこと

```shell
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
    https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
```

vim-plug に管理させたいなら, ディレクトリを指定する

```.vim
if has('vim_starting')
  set rtp+=~/.vim/plugged/vim-plug
  if !isdirectory(expand('~/.vim/plugged/vim-plug'))
    echo 'install vim-plug...'
    call system('mkdir -p ~/.vim/plugged/vim-plug')
    call system('git clone https://github.com/junegunn/vim-plug.git ~/.vim/plugged/vim-plug/autoload')
  end
endif

call plug#begin('~/.vim/plugged')
  Plug 'junegunn/vim-plug',
        \ {'dir': '~/.vim/plugged/vim-plug/autoload'}
  ...
call plug#end()

```

Usage
---

```.vim
call plug#begin('~/.vim/plugged')

" Vundle/NeoBundle と同じように
Plug 'junegunn/seoul256.vim'

" コマンド実行時に読み込む
Plug 'scrooloose/nerdtree', { 'on':  ['NERDTreeToggle'] }

" 指定したファイルタイプを開いたときに読み込む
Plug 'tpope/vim-fireplace', { 'for': ['clojure'] }

" X | Y の時, X をインストールした後に Y をインストール
Plug 'SirVer/ultisnips' | Plug 'honza/vim-snippets'

call plug#end()
```

```
:PlugInstall
```

遅延読み込みできてるかどうかは ```:PlugStatus``` で確認しながらできるのがいいですね

Tips
----

一度プラグインを読み込むとonに指定したコマンドは削除されてしまうよう..
なので依存するプラグインは一緒のタイミングを指定しないとだめっぽい.

```.vim
" Good?Bad? Practice
let b:commandDepends = ['Unite', 'UniteWithBufferDir',
      \ 'VimFilerCurrentDir', 'VimFilerBufferDir']
Plug 'Shougo/unite.vim', {'on': b:commandDepends, 'for': ['unite']}
      \ | Plug 'Shougo/vimfiler', {'on': b:commandDepends}
unlet b:commandDepends

" Bad
Plug 'Shougo/unite.vim', {'on': ['Unite'], 'for': ['unite']}
      \ | Plug 'Shougo/vimfiler', {'on': ['VimFilerCurrentDir', 'VimFilerBufferDir']}
" -> Unite 実行後に VimFiler を実行しないと駄目

" Bad
Plug 'Shougo/unite.vim', {'on': ['Unite', 'VimFilerCurrentDir', 'VimFilerBufferDir'], 'for': ['unite']}
      \ | Plug 'Shougo/vimfiler', {'on': ['VimFilerCurrentDir', 'VimFilerBufferDir']}
" -> Unite を先に実行してしまうと vimfiler の on がなくなってしまう...
```

[^1]: 後発といっても2013年ぐらいからあるみたいですが...
リンスタカフェ ユーザテスト見学会 参加レポート

# 勉強会タイトル

**リンスタカフェ vol8 「特別編：ユーザーテスト見学会～みんなでピザとビールとUTを楽しもう！」**

# 日時

2015-10-30（金）19:30 - 22:30

# 勉強会ページURL

https://devlove.doorkeeper.jp/events/32887

# タイムスケジュール

19:00 - 開場
19:30 - はじまりの言葉 (市谷さん／志田さん)
19:35 - 各自、飲み物と料理を手に取る & 乾杯!
19:40 - 本日のテストの解説（樽本さん他）
20:00 - ユーザーテスト見学（3セッションの予定）
21:00 - 観察結果ふりかえり & ディスカッション
21:30 - 懇親会 & ディスカッション続き
22:30 - お片づけタイム & 閉会

# ユーザーテスト見学

## 1分間ユーザテスト

ミニライトを被験者に渡し、「ライトをつけてください」というタスクを実行してもらう。

### 被験者数
5人

### テストした物(ライト)
* 手の指くらいのサイズ感。
* 頭(ライト部分)と柄の部分から成る。
* ライトがつきそうなスイッチは見当たらず。
* 頭と柄の境に蛇腹が一段存在。
* ライトをつけるためには縦方向に押し込む必要がある。
(そうすることで蛇腹が縮まる)

### 被験者の主な行動
(→の後には事後インタビューで明らかになった被験者の心理等)

* ライトを一通り見回す。

→スイッチを探すためと判明。

* 頭部分をひねる。

→ひねるとライトがつく類似品を見たことがあるから。
(頭部分が外れるだけの結果に。)

* お尻部分を押してみる。

→特にボタンはないが、他にスイッチのようなものがないので押してみた。

### 改善するとしたらどのようにしたらいいと思うか
* 蛇腹の幅を広くしてもう少し押し込める感を出す。
* (コストを抑えて改善するには)蛇腹の付近に矢印のマークを印字する。
* (押しても固かったので)もう少し柔らかい押し心地に。

### このUTを通して学んだこと
* 事後インタビューで「なぜ◯◯ということをしたのですか？」と聞かれたときに返答に困っていたり、考え込んでいる様子だったことから、被験者は自分がやったことを覚えていないことがわかる。
そのため、事後インタビューに頼りすぎることはよくなく、できるだけ思考発話をしてもらえるようにする。
* 当たり前ではあるが、他の類似品から目の前にある物の操作を推測しているので、デザイン、操作感において既存のものと異なりすぎることは好ましくない。

## スマホユーザテスト

### テストしたアプリ
30days Album

### 被験者数
2人

### アプリの概要
無料で使える写真・動画の共有・保存サービス。
友達と写真を共有できる。

### タスク概要
(※第6回ユーザテスト見学会とシナリオ、タスク内容はほぼ同内容)

* 友達から「30days Albumに写真をアップしたよ」という連絡をもらったので、アプリをダウンロードして
　(指定されたアルバムの)写真を見る。
* 自分が撮った写真をそのアルバムに追加する。
* 自分でアルバムを作ってみて写真を追加する。

### 被験者の主な行動
(→の後には事後インタビューで明らかになった被験者の心理等)

* 「3枚まとめてアルバムにある写真を自分の端末に保存してください」というタスクで
1人目：1枚ずつ保存し、3枚保存し終えたときに「まとめて」というタスクだったことを(タスクが書かれている紙を見て？)思い出し、それを口に出していた。
2人目：「まとめて保存？え？」と思考発話しつつまとめて保存できるようなボタン等を探していたが、その後、1枚ずつ保存していた。

→2人目に関しては、まとめて保存しなかった理由を聞かれると、「最初はまとめて保存を探していたけど、あまりにも見つからなかったから、タスクが間違っているのかと思って1枚ずつ保存した」と言っていた。

* 自分でアルバムを作成して写真を2枚アップするというタスクでなかなかタスクを実行できなかった。

→ここにアルバム作成の導線があるだろうと思っていたところに何もなかった。ユーザ登録をしなければアルバムを作成することができないという発想がなかった。

### このUTを通して学んだこと
* タスクが書かれた紙を横に置いていてもタスクを間違えていた(3枚まとめて保存、の1人目)ことから、被験者に複雑なタスクを課してもその通りにやってくれない可能性があるのだと思った(このタスク自体は悪くない)。

## PCユーザテスト

### テストしたサイト
DocBase

### 被験者数
1人

### 概要
必要な情報を必要なメンバー間で共有するためのサービス。

### タスク概要
異動先にて、「開発環境の構築の仕方がDocBaseに載っているので

* 新規ユーザ登録をして
* その資料読んどいて

と言われた。また、

* 日報をテンプレートを参考にして書いておいて

と言われた、という想定。

### 被験者の主な行動
(→の後には事後インタビューで明らかになった被験者の心理等)

* 新規登録に苦戦していた。

→ログインボタンは画面上部にあるが、新規登録ボタンは下にスクロールしないと見えないところにあった(スクロールせずに見えている画面は、その下にまだ何かが書かれていそうな雰囲気は出ていなかった)。

* 記事を検索することによってテンプレートを苦戦することなく見つけ出せていた。

→類似のサービスを使ったことがあるのである程度操作の予想がついた、とのこと。
また、タスクが書かれた紙かwebサイトに「検索機能が充実している」と書かれていたため、検索をすればどうにかなるだろうと思ったと思ったとのこと。

## その他特記すべきこと

- 思考発話をうまくやってもらうためには、思考発話がうまい人の動画を見てもらう。そうすることでどのようにやればいいのかを理解することができる。あとは練習あるのみ。
- テストするサービスによってはわざと急かしたりプレッシャーをかけたりすることもある。

## 質問したこと

* 今回の30days Albumの「自分でアルバムを作成してください」というタスクのように、おそらく自分ではその機能に気づかなかったであろうことをタスクに設定して、無理やりその機能に気づかせて使ってもらう、というのはタスクとしてありなのか？

→あり。今回の場合だと、ユーザは使っているうちに「私もアルバムを作って共有したい」という気分になり、アプリをいろいろと触っているうちにアルバム作成機能に気づく。ユーザテストではその気づくタイミングを早めただけ。
既定のマクロとか

なんだろうね。すぐ忘れる。

```shell-session
$ cpp -dM /dev/null
#define __DBL_MIN_EXP__ (-1021)
#define __UINT_LEAST16_MAX__ 65535
#define __ATOMIC_ACQUIRE 2
#define __FLT_MIN__ 1.17549435082228750797e-38F
#define __UINT_LEAST8_TYPE__ unsigned char
#define __INTMAX_C(c) c ## L
#define __CHAR_BIT__ 8
#define __UINT8_MAX__ 255
```

こういうこともできるかな。

```shell-session
$ echo "#include <limits.h>" | cpp -dM | grep PATH_MAX
#define PATH_MAX 4096
#define _POSIX_PATH_MAX 256
```
コーシー・シュワルツの不等式(テスト投稿)

# コーシー・シュワルツの不等式
　コーシー・シュワルツの不等式は下記のような形をしている。

```math
( \sum_{k=1}^n a_k b_k )^2 \leq
( \sum_{k=1}^n a_k^2 ) ( \sum_{k=1}^n b_k^2 )
```
これを証明してみよう。まず下三角集合$S_L$, 対角集合$S_D$, 上三角集合$S_U$を次のように定義しておく。

```math
S_{L} = \left \{ (i, j) | 1 \le i \le n, 1 \le j \le n, i > j \right \}
```
```math
S_{D} = \left \{ (i, j) | 1 \le i \le n, 1 \le j \le n, i = j \right \}
```
```math
S_{U} = \left \{ (i, j) | 1 \le i \le n, 1 \le j \le n, i < j \right \}
```
もちろん、正方集合$S$を次のように定義すると、$S$は$S_L, S_D, S_U$の直和である。

```math
S = \left \{ (i, j) | 1 \le i \le n, 1 \le j \le n \right \}
```
すなわち、次が成り立つ。

```math
\begin{align}
S &= S_L \cup S_D \cup S_U \\
\emptyset &= S_L \cap S_D = S_D \cap S_U = S_U \cap S_L
\end{align}
```

右辺は次のように変形できる。

```math
\begin{align}
&( \sum_{k=1}^n a_k^2 ) ( \sum_{k=1}^n b_k^2 ) \\
=& ( \sum_{i=1}^n a_i^2 ) ( \sum_{j=1}^n b_j^2 ) \\
=& \sum_{i=1}^n \sum_{j=1}^n a_i^2 b_j^2 \\
=& \sum_{(i, j) \in S_L} a_i^2 b_j^2 + \sum_{(i, j) \in S_D} a_i^2 b_j^2 + \sum_{(i, j) \in S_U} a_i^2 b_j^2 \\
=& \sum_{(i, j) \in S_L} (a_i^2 b_j^2 + a_j^2b_i^2) + \sum_{(i, j) \in S_D} a_i^2 b_j^2
\end{align}
```

左辺は次のように変形できる。

```math
\begin{align}
&( \sum_{k=1}^n a_k b_k )^2 \\
=& ( \sum_{i=1}^n a_ib_i ) ( \sum_{j=1}^n a_jb_j ) \\
=& \sum_{i=1}^n \sum_{j=1}^n a_ia_jb_ib_j \\
=& \sum_{(i, j) \in S_L} a_ia_jb_ib_j + \sum_{(i, j) \in S_D} a_ia_jb_ib_j + \sum_{(i, j) \in S_U} a_ia_jb_ib_j \\
=& \sum_{(i, j) \in S_L} (a_ib_ia_jb_j+a_jb_ja_ib_i) + \sum_{(i, j) \in S_D} a_ia_jb_ib_j \\
=& 2 \sum_{(i, j) \in S_L} a_ib_ia_jb_j + \sum_{(i, j) \in S_D} a_ia_jb_ib_j \\
\end{align}
```
よって、次の結果が得られる。

```math
\begin{align}
&(右辺) - (左辺) \\
=& \sum_{(i, j) \in S_L} (a_i^2 b_j^2 - 2a_ib_ia_jb_j + a_j^2b_i^2) \\
=& \sum_{(i, j) \in S_L} (a_i b_j - a_jb_i)^2 \ge 0
\end{align}
```
【設定シェルファイル】git-2.X.0 インストール

```
# setup_git.shの準備
rm -f setup_git.sh; touch setup_git.sh; chmod u+x setup_git.sh; vi setup_git.sh
```

```
#!/bin/bash

echo "＋------------------------------------------------------------------------------------------------------------＋";
echo "■setup start " ${0};
echo "＋------------------------------------------------------------------------------------------------------------＋";

# 変数設定
URL_GIT="https://www.kernel.org/pub/software/scm/git/git-2.9.0.tar.gz"

# アップデート
sudo yum -y update

echo ;
echo "□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□";
echo "【git-2.4.0 インストール】";
echo "□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□";

echo "【アンストール git】"
sudo yum -y remove git

echo "【確認 git アンストール】"
git --version


echo "【ファイル取得 git-2.4.0.tar.gz】"
cd ~/
sudo yum -y install gcc curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-ExtUtils-MakeMaker
wget $URL_GIT
tar zxvf git-*.tar.gz
rm -rf git-*.tar.gz

echo "【コンパイル】"
cd git-*
sudo make prefix=/usr/local all
sudo make prefix=/usr/local install

sudo ln -s /usr/local/bin/git /usr/bin/git

cd ~/
sudo rm -rf git-*

echo "【確認 git インストール】"
git --version
```



```
#!/bin/bash


echo "＋------------------------------------------------------------------------------------------------------------＋";
echo "■setup start " ${0};
echo "＋------------------------------------------------------------------------------------------------------------＋";

echo ;
echo "□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□";
echo "【git-2.X.X インストール】";
echo "□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□□";

func_GitInstall (){
    if [ "$UID" -eq 0 ];then
        echo "root!"

        # 定数設定
        URL_GIT="https://www.kernel.org/pub/software/scm/git/git-2.9.0.tar.gz"

        echo "【アンストール git】"
        yum -y remove git

        echo "【確認 git アンストール】"
        git --version

        echo "【ファイル取得 git-2.X.X.tar.gz】"
        cd ~/
        yum -y install gcc curl-devel expat-devel gettext-devel openssl-devel zlib-devel perl-ExtUtils-MakeMaker
        wget $URL_GIT
        tar zxvf git-*.tar.gz
        rm -rf git-*.tar.gz

        echo "【コンパイル】"
        cd git-*
        make prefix=/usr/local all
        make prefix=/usr/local install

        echo "【シンボリックリンク】"
        sudo ln -s /usr/local/bin/git /usr/bin/git

        echo "【不要ファイル削除】"
        rm -rf git-*

        echo "【確認 git インストール】"
        git --version

    else
      echo "non-root user!"
    fi

}

#２重確認
#
#インストール済みか確認
if !(git --version)
then
  echo "gitインストールされていません インストールする必要があります"
  func_GitInstall
else
  echo "gitインストールされています"
    if (git --version | grep "git version 1")
    then
      echo "1.7.1なので古いです インストールする必要があります"
      func_GitInstall
    else
      echo "新しいgitインストールされています "
    fi
fi

#バージョンが低いか確認



echo "＋------------------------------------------------------------------------------------------------------------＋";
echo "■setup end";
echo "＋------------------------------------------------------------------------------------------------------------＋";

```
エンドツーエンドテストの fixtures をfactory_girl でセットアップする

モバイルアプリのREST クライアントをテストするとき Rails サーバーのモデル群をEnd to End テスト用の内容に登録しておきたいことがあります。

test/fixturesやseeds.rb を使うことも考えたのですが、今ある factories でモデルを作りたいことと今ある spec を直したくないことから、今回は factory_girl を使って fixtures を作成する rake タスクを作ることにしました。

# 環境

- rails (4.2.4)
- factory_girl_rails (4.5.0)

# やりたいこと

End to End テストの環境をセットアップするのは db:populate タスクを実行するだけにしたい:

```
$ ./bin/rake db:populate
```

# factory_girl のインストール

Gemfile の development group に factory_girl_rails を追加します:

```
# Gemfile
group :development, :test do
  gem 'rspec-rails'
end
```

# Rake ファイルの作成

populate.rake ファイルを次の内容で作成します:

```
# lib/tasks/db/populate.rake
require 'factory_girl'
 
namespace :db do
  desc "Populate the database for end-to-end testing"
  task :populate do |t, args|
    puts "Resetting the database"
    Rake::Task['db:reset'].invoke
    puts "Creating the user"
    users = FactoryGirl.create_list(:user, 2)
    users = users.map do |user|
      puts "-- #{user.username}'s token is: #{user.token}"
      user
    end
    puts "Creating a hoge for user"
    users.each do |user|
      FactoryGirl.create(:hoge, user: user)
      puts "-- #{user.username}'s hoge is: #{hoge.inspect}"
    end

    puts "Done!"
  end
end
```

もちろん spec/factories に users.rb と hoges.rb を作成する必要があります。

```
# spec/factories/users.rb
FactoryGirl.define do
  factory :user do
  	sequence(:token) {|n| "token#{n}" }
# ..
  end
end
```

# Rake タスクの実行

あとは db:populate タスクを実行するだけです:

```
$ ./bin/rake db:populate
Resetting the database
Creating the user
-- user_1's token is: yyGsiDQ7azGN8-hQGGCPzRV2K4zarkHA
..
Done!
```

# 参考資料

- http://jonathanvingiano.com/work/rake-task-factory-girl-polymorphic/
PHP5.5系からPHP5.6系へ移行するための準備


## はじめに
現在、自分の会社ではPHP5.5による開発を実施しています。先日、チームメンバーよりサポート期間も踏まえてバージョンをあげましょうと提案いただきました。今回はその対応で動作検証したときのお話しです。

> PHP5.6系の話は今更感ありますが、やらないよりはやりましょうということで整理してみました。

## PHPのリリース及びサポート期間
下記、wikipedia にて整理されています。

* [PHP Release_history](https://en.wikipedia.org/wiki/PHP#Release_history)

![スクリーンショット 2015-11-16 14.58.07.png](https://qiita-image-store.s3.amazonaws.com/0/39380/b809a71b-d795-f21a-a011-b1e43b9266ff.png "スクリーンショット 2015-11-16 14.58.07.png")


PHP5.4以降を抜き出すとこんな感じです。

・5.4系のサポートは2015年9月3日に終了している
・5.5系のサポートは2016年6月まで
・5.6系のサポートは2017年8月まで
・7.0,7.1系のサポートはリリースから3年

5.5系だと残り7ヶ月となりますので、早めに5.6系への準備をしても良さそうです。ちなみに7系は、利用しているフレームワークのメジャーバージョンアップが伴ったり、影響範囲が大きそうですので今回はパスしました。

## PHP 5.5 系から PHP5.6系への移行
5.5系と5.6系の違いは下記を見てもらえればまとまっています。日本語です。

* [PHP 5.5.x から PHP 5.6.x への移行](http://php.net/manual/ja/migration56.php)

![スクリーンショット 2015-11-16 23.44.32.png](https://qiita-image-store.s3.amazonaws.com/0/39380/9eefb0d9-8779-647c-32f9-34b8bc269e58.png "スクリーンショット 2015-11-16 23.44.32.png")

特に確認しておくべき点は、次でしょうか。

* [下位互換性のない変更点](http://php.net/manual/ja/migration56.incompatible.php)

互換性が無いとのことですので、注意してください。下記でもまとめられています。上記リンクと似ていますので適宜参考にしてください。

* [PHP 5.5.x から PHP 5.6.x への移行のまとめ](http://qiita.com/alegriaghost/items/85caf303abe63d1ac3a3)


## 動作検証の環境
* iMac OS X EI Capitan(10.11.1)
* Vagrant + CentOS7.0 + Nginx1.8 + PHP5.6 + PHP-fpm5.6

環境構築方法については、また別途共有しようと思います。仮想環境って素敵です。

## 検証ではまったところ（個人の環境に依存してます）

自分達は、開発の一環としてテストコードを書いていますので、5.6系の環境を構築しテストを実行することで動作検証を実施しました。

全然別のところですが、次の点で少しハマってしまいました。

API系のテストで cURL にてHTTPリクエストを発行しているところがあるのですが、今までは問題なく動いていたのに、新しい環境だと動かない・エラーになるということがありました。こういうとき、テストを書いていて良かったと思える瞬間です。

問題の箇所は、リクエストパラメータがnullの場合、POSTフィールドの指定しなくても PHP5.5系では動作したのですが、5.6系ではnullでも明示的に指定しないとレスポンスを正しく受け取ることができませんでした。「json_decodeがより厳格」になったことで、影響を受けていたようです。

上記以外については、特に問題なくテストも通りました。

## まとめ
* テストコードを書いているとこういうときにも大変有効だということが身を持って知ることができました。
* 1、2年くらいするとPHP7対応のフレームワークが揃い、事例も増えてくると思います。しかし既存コードの見直しは多くなるかもしれません。
* バージョン移行は計画性を持って進めたいですが、アプリケーション実装もあると忘れがちですので気を付けたいですね。（自戒もこめて）
Spring Tool Suiteのインストール

# はじめに
* 仕事（半分趣味）の調査向けにWebアプリケーションを作成する。
* Spring Bootのイニシャルコストが低い（らしい）ので、その調査を兼ねての実装。
* Eclipseでの開発が多いけど、Spring特化のIDEと戯れてみよう！

# 設定
## インストールマシン
* OS : Windows7(64bit)
* Java8
* C:\develop を開発ディレクトリとしている。

## ダウンロード
* 最新版をダウンロードする
    * https://spring.io/tools
        * version 3.7.1 RELEASE
        * spring-tool-suite-3.7.1.RELEASE-e4.5.1-win32-x86_64.zip
        * (このバージョンのSTSの実態はEclipse Mars 4.5.1）

## インストール
* ZIPファイルを解凍する。
    * sts-bundle ディレクトリができる。
    * 解凍したディレクトリを開発ディレクトリに移動する。
    * こうなっていればＯＫ
        * C:\develop\sts-bundle。

## 起動
* 下記のexeを起動する。
    * C:\develop\sts-bundle\sts-3.7.1.RELEASE\STS.exe
* 起動時に「Workspace Launcher」が起動する。
    * ワークスペースを聞かれるので、下記のディレクトリを指定する。（workspaceディレクトリは新規で作成する）
        * C:\develop\workspace
* あとは、起動すればＯＫ

## 日本語化
* そのままでもいけるけど、日本語化しておいた方が便利なので。
* ド定番のPleiadesを利用する。

### ダウンロード
* MergeDoc Project
    * http://mergedoc.osdn.jp/
    * STSインストール済みなので、ALL in Oneは落とさない。
    * Pleiades プラグイン・ダウンロードの下の「安定版」リンクを押下する。
    * pleiades_1.6.0.zipをダウンロードする。
    * 解凍する。
        * 解凍ソフトだと失敗することがあるので注意

### インストール
* 基本的には「readme_pleiades.txt」の内容を実施する。
* STSの場合は「eclipse.ini」　→　「STS.ini」となっていることに注意。
* それ以外は、「readme_pleiades.txt」の内容でOK
.DS_Storeを含めずにzip圧縮する方法

「__送ってもらったzipファイルを開いたら、変なファイル(.DS_Storeのこと)が入ってる！__」

Mac環境で作ったzipをWindows環境の人に送った時に言われた事がある人はいるのではないでしょうか。
あるからといって、害を及ぼすファイルではないですが、Window環境の人には邪魔なファイルでしかないので、.DS_Storeを含めずにzipを作って渡してあげましょう。

# 特定のファイルを含めずにzip圧縮
```
zip directory-name.zip -r directory-name/ -x "*.DS_Store"
```
※directory-nameの部分は読み替えてください。

.DS_Storeを含めずにディレクトリをzip圧縮するコマンドです。
zipコマンドの「-x」オプションを使うことで、ファイルを明示的に除外しています。

# 特定のファイルを含めずにzip圧縮しつつ、パスワードをかける
```
zip -e directory-name.zip -r directory-name/ -x "*.DS_Store"
```

「パスワードをかけて、パスワードを別メールで送る」

この行為に意味があるのかはさておき、zipにパスワードをかけないといけない場面はたまにあります。
そんな時は-eオプションを付与して、パスワードをかけましょう。

# zipファイルから特定のファイルを取り除く
```
zip -d filename.zip '*.DS_Store'
```

上のやり方で圧縮をおこなっていれば使うことは多分無いですが、一応。
「-d」オプションでzip内の.DS_Storeを消しています。
-xオプション付けずに圧縮してしまった場合にでも使ってみてください。
Eclipseの「リソースを開く」でclassファイルを表示しないようにしたい

## やりたいこと

リソースを開く(Open Resource)ダイアログで「*.class」が表示されるのが鬱陶しい。
「*.class」は表示されないようにしたい。

## やり方

- OpenResouceダイアログを開く
- 右上の矢印をクリック
- 「Show Derived Resouece」のチェックをオフにする
- これで自動生成ファイルは表示されなくなる

## まだ、classファイルが表示されている場合

それはEclipseにclassファイルが自動生成のものだと認識されていないため。
classファイルが自動生成のものだとEclipseに教える必要がある。

- classファイルが出力されているフォルダを右クリック
- 「Resource」を選択
- 「Derived」を選択
- そうするとOpenResouceダイアログでclassファイルが表示されなくなる。はず。
JSで要素の組み合わせを列挙する

下記のような、キーの数や要素数が可変のデータの組み合わせを、列挙するjavascriptコードです。
pythonには順列・組み合わせ計算にはitertoolなどの定番ライブラリがあるようです。

やっている事としては、組み合わせを数列に置き換えるイメージです。
1桁目が2進数、3桁目が3進数、3桁目が4進数の不規則な進法で表現されていると捉えて、
n[1..2*3*4=24]までループでひたすら列挙します。

## コード 
```combination.js
var data = { 
  "1.ドリンク": ["チャイ", "ラッシー"],
  "2.副菜": ["サモサ", "ティッカマサラ", "サブジ"],
  "3.主菜": ["バターチキン", "キーマ", "ダール", "マトン"]
}

// 実行毎に結果の出力順序が一意になるようにソート
var keys = Object.keys(data).sort();

// 組み合わせの総数を事前に計算
var total = 1;
for (var key in data) {
  total *= data[key].length;
}

var q, // 商, ループ中の配列で表現できない数
    r, // 余り, ループ中の配列で表現する数
    result = []; // 組み合わせを格納する配列

// 組み合わせの総数回ループして、n番目にどの組み合わせが来るかどうかを求める
for (var n=0; n < total; n++) {
  result[n] = {};
  q = n;

  // dataのキー毎にループして、どの要素を使うか決定
  for (i=0; i<keys.length; i++) {
    key = keys[i];

    // ループ対象の配列の要素数で割った余り = その配列で表現できる数 
    r = q % data[key].length;

    // ループ対象の配列の要素数で割った商 = その配列で表現できない数
    q = Math.floor(q / data[key].length);

    result[n][key] = data[key][r];
  }
}

// 出力
for (var i=0; i < result.length; i++) {
   console.log(i+':'+JSON.stringify(result[i]));
}

/*
0:{"1.ドリンク":"チャイ","2.副菜":"サモサ","3.主菜":"バターチキン"}
1:{"1.ドリンク":"ラッシー","2.副菜":"サモサ","3.主菜":"バターチキン"}
2:{"1.ドリンク":"チャイ","2.副菜":"ティッカマサラ","3.主菜":"バターチキン"}
3:{"1.ドリンク":"ラッシー","2.副菜":"ティッカマサラ","3.主菜":"バターチキン"}
4:{"1.ドリンク":"チャイ","2.副菜":"サブジ","3.主菜":"バターチキン"}
5:{"1.ドリンク":"ラッシー","2.副菜":"サブジ","3.主菜":"バターチキン"}
6:{"1.ドリンク":"チャイ","2.副菜":"サモサ","3.主菜":"キーマ"}
7:{"1.ドリンク":"ラッシー","2.副菜":"サモサ","3.主菜":"キーマ"}
8:{"1.ドリンク":"チャイ","2.副菜":"ティッカマサラ","3.主菜":"キーマ"}
9:{"1.ドリンク":"ラッシー","2.副菜":"ティッカマサラ","3.主菜":"キーマ"}
10:{"1.ドリンク":"チャイ","2.副菜":"サブジ","3.主菜":"キーマ"}
11:{"1.ドリンク":"ラッシー","2.副菜":"サブジ","3.主菜":"キーマ"}
12:{"1.ドリンク":"チャイ","2.副菜":"サモサ","3.主菜":"ダール"}
13:{"1.ドリンク":"ラッシー","2.副菜":"サモサ","3.主菜":"ダール"}
14:{"1.ドリンク":"チャイ","2.副菜":"ティッカマサラ","3.主菜":"ダール"}
15:{"1.ドリンク":"ラッシー","2.副菜":"ティッカマサラ","3.主菜":"ダール"}
16:{"1.ドリンク":"チャイ","2.副菜":"サブジ","3.主菜":"ダール"}
17:{"1.ドリンク":"ラッシー","2.副菜":"サブジ","3.主菜":"ダール"}
18:{"1.ドリンク":"チャイ","2.副菜":"サモサ","3.主菜":"マトン"}
19:{"1.ドリンク":"ラッシー","2.副菜":"サモサ","3.主菜":"マトン"}
20:{"1.ドリンク":"チャイ","2.副菜":"ティッカマサラ","3.主菜":"マトン"}
21:{"1.ドリンク":"ラッシー","2.副菜":"ティッカマサラ","3.主菜":"マトン"}
22:{"1.ドリンク":"チャイ","2.副菜":"サブジ","3.主菜":"マトン"}
23:{"1.ドリンク":"ラッシー","2.副菜":"サブジ","3.主菜":"マトン"}
*/
```

## 説明
例のデータで言えば2 * 3 * 4通りの組み合わせを求めているので、
例えば15番目の組み合わせをを求める場合、「ドリンク」で表現できる要素の数=2で割ると
商が7、余りが1、…となり、
<em>商の7 = 「副菜」以降で表現しなければならない数
余りの1 = 「ドリンク」で表現する数</em>
よって「ドリンク」は配列の添字[1]の要素「ラッシー」に決定します。

同様にして、商の7を「副菜」で表現できる3で割ると
商が2、余りが1、…となり、
「副菜」は配列の添字[1]の要素「ティッカマサラ」を使います。

最後の主菜では、2 / 4
商は勿論0、余りは[2]となり、
「主菜の」は配列の添字2の要素の「ダール」に決定します。
R言語のインストールと動作確認

# はじめに
R言語の勉強を始めたので、簡単にだが環境作りの備忘として。
(Windows版のお話し。Linux版、Mac版ではありません。)

## 私のインストール環境
Windows8.1 (64bit)

## 参考
[R - Official Site](https://www.r-project.org/)
[R言語(Wikipedia)](https://ja.wikipedia.org/wiki/R%E8%A8%80%E8%AA%9E "R言語")

# 1.R言語インストール
## 1.1.インストーラーのダウンロード
1. [R - Official Site](https://www.r-project.org/)の[Download - CRAN]へ移動

2. 好きなMirrorサイトへ移動(Japanのどっかとか)

3. インストールするOSに該当するリンクを選んでダウンロード
(Windows版であればその後に、[base]->[Download R x.x.x for Windows]でダウンロード)

## 1.2.インストール
1. ダウンロードしたR-x.x.x-win.exeを実行

2. 「次へ」を押し続けて終了

## 1.3.動作確認
1. Rを起動
>たぶん、↓のように32bit版、64bit版がインストールされるので、好きなほうを起動
>
>![r.png](https://qiita-image-store.s3.amazonaws.com/0/99926/24d01983-f33a-0e95-a8e3-edd30c7988bf.png)
>
>以下の画面が起動すればOK
>
>![r-1.png](https://qiita-image-store.s3.amazonaws.com/0/99926/1ece795f-500c-3bda-322a-d07241db4456.png)
>

2. 動作確認
>plot(cars) と入力しEnter
>
>![r-2.png](https://qiita-image-store.s3.amazonaws.com/0/99926/75317376-7799-b684-35b2-f6a0c9dcd5b8.png)
>
>何かグラフが表示されれば動作確認としてはOK
line monitor > コア部分 (v0.3, v0.4) > シリアルリレー (+UDP送信) + UDPコマンド受信 + com baud変更


```txt:端末
a. line monitor本体実行 : RaspberryPi2 + raspbian (IP: 192.168.10.3)
b. COM送信 : Windows 8.1pro + TeraTerm
c. UDPコマンド送信 : CentOS 6.5 (IP: 192.168.10.8)
d. UDPモニタ出力先 : CentOS 6.5 (IP: 192.168.10.8)
```

```txt:治具
A. Win8.1 : SRC06-USB (USBシアリルケーブル)
B-1. RPi2 : VE488 (USBシリアルケーブル)
B-2. RPi2 : VE488 (USBシリアルケーブル)
X : TX-RX変換用治具 (`AとB-1` または `AとB-2`を接続に使用)
```

http://qiita.com/7of9/items/028556c5a819a6a8de96
で記載したRPi2動作のコア部分


## プログラム

[ソフト設計 @ mindmup](https://atlas.mindmup.com/2015/11/81979a106e980133fb1f6d2fd968b733/151112_line_monitor/index.html)

[v0.3 @ github](https://github.com/yasokada/python-151113-lineMonitor/releases/tag/v0.3)

プログラムの構成は現状、以下となっている。

- dummySerial.py : CentOS上で開発するためのダミー
- linemonitor.py : プログラム本体
- utilComRelay.py : COM通信関連
- utilSetting.py : 設定のget/set用
- utilUdpCmd.py : UDPコマンド通信用


## 使用手順

1. RPi2 において、linemonitor.pyを起動する (`$python linemonitor.py`). 
2. CentOSにおいて、`echo "set,combaud,2400" | nc -w 1 -u 192.168.10.3 7000` を実行して、combaudを2400bpsにしておく (しない場合は9600bps)
3. CentOSにおいて、UDPの出力を受けるため root権限で `# tcpdump -A -n udp portrange 9000`を実行しておく
4. Win8.1のTeraTermを起動する。[端末]->[CRLF送信]の設定をしておく
5. Win8.1のTeraTermの通信速度を2400bpsにする
6. Win8.1のTeraTermから`from win`という文字を入力 (文字列は任意)してEnterを押す

以上でそれぞれの端末は以下の状態になっている。

```txt:RPi2
$ python linemonitor.py 
cmdport= 7000
rcvd:[ set,combaud,2400 ]
set combaud
2400
rcvd= from win
```

```txt:CentOSでtcpdumpによるUDP出力の受け
# tcpdump -A -n udp portrange 9000
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
22:46:50.861640 IP 192.168.10.3.53357 > 192.168.10.8.cslistener: UDP, length 12
E..(..@.@..g..
...
..m#(....2:from win
......
```

## 現状
とりあえず`<CR><LF>`終端のCOM通信に対しては、当初の予定通りの実装ができたと思う。

もう1本のUSBシリアルおよび、TX-RX変換治具を用意することで、実際の動作検証ができるようになると思う。

RPi2のプログラムとしては以下の課題があるが、当面、Unity(UI)側の実装を優先的に行っていく。

- バイナリ文字列通信の対応 > 低優先度で実装予定
- フロー制御 > 多分実装しない
- reboot処理 > 必要なのだろうか...

## 未消化

linemonitor.pyにおいて comReopen()をコールしたらエラーが出た。
結局、動作優先として、comReopen()の中身をlinemonitor.pyに書くことで対応した。

## v0.4

[v0.4 @ github](https://github.com/yasokada/python-151113-lineMonitor/releases/tag/v0.4)

- monport関連で`TypeError: an integer is required`が出てしまうバグを修正した。
Docker コンテナで exit を実行しても停止しないようにする

# 背景

Docker コンテナに attach した際、コンソールで exit を実行するとコンテナが停止し、それまでの変更内容も保存されません。

慣れればよいのですが、大規模システムのテスト環境などでコンテナベースの環境運営を行う場合、外注先のエンジニアがたくさん出入りします。その際、Docker に不慣れなエンジニア（受託開発の場合はほぼ全員でしょう）が勢いで exit をタイプしてしまうことは容易に想像できます。

よって、コンテナの停止はホストからの docker stop のみに限定し、exit は無効とします。

# 前提

本投稿では Docker 1.9.0 を前提とします。使用する Docker image は ubuntu:latest(2015/11/16現在)です。

# 実現方式

alias を定義して、代わりに usage を表示します。

```bash
alias exit='echo Do not use command `exit` for logout operation. Use Ctrl-p,Ctrl-q.'
```

最初、Dockerfile に以下のように定義して、/etc/bashrc の最後に追記することを考えました。

```bash:Dockerfileの定義内容
CMD "echo alias exit='echo Do not use command `exit` for logout operation. Use Ctrl-p,Ctrl-q.'"
```

しかし、上記 Dockerfile を用いて docker build したところ、出来上がった Docker イメージには上記コマンド文が反映されていませんでした。

```bash:Dockerfileに定義した内容が反映されていない
host# docker run -it test/ctn /bin/bash
ctn# tail -1 /etc/bashrc

```

原因はわかっていませんが、docker run を実行した際にイメージ内のファイルからプロビジョニングされ上書きされてしまっているのかもしれません。

暫定対応として、ホスト側に ToBe の bashrc ファイルをもっておき、COPY コマンドで置き換えるよう Dockerfile に記述しました。

```bash:Dockerfileの定義内容
COPY resource/bashrc /etc/bashrc
```

上記の Dockerfile を用いてコンテナ生成したところ、無事 exit の alias が有効になりました。

```bash
host# docker attach test_ctn
ctn# exit
echo Do not use command `exit` for logout operation. Use Ctrl-p,Ctrl-q.
```

# 改善点

以上で目的は果たしていますが、bashrc の構成管理を Docker イメージの外で行わねばならないのが少々億劫です。引き続き対処を検討していきます。
[elixir]phoenixとRedisでAPI作成


elixirのWeb,APIフレームワークであるphoenixと、
KVSのRedisを使用しAPIを作成する。

```
mix phoenix.new api_sample
cd api_sample
```

依存ライブラリに`exredis`を追加

```mix.exs
  defp deps do
    [{:phoenix, "~> 1.0.3"},
     {:phoenix_ecto, "~> 1.1"},
     {:postgrex, ">= 0.0.0"},
     {:phoenix_html, "~> 2.1"},
     {:phoenix_live_reload, "~> 1.0", only: :dev},
     {:cowboy, "~> 1.0"},
     {:exredis, ">= 0.2.2"}
   ]
  end
```

```
mid deps.get
```

redisの接続情報を追加

```config.exs
config :exredis,
  host: "127.0.0.1",
  port: 6379,
  password: "",
  db: 0,
  reconnect: :no_reconnect,
  max_queue: :infinity
```

pipe_through :browserを:apiに変更
PageControllerは一旦このままで。

```router.ex
  scope "/", ApiSample do
    pipe_through :api # Use the default browser stack

    get "/", PageController, :index
  end
```

indexの戻り値をjsonにします。

```page_controller.ex
defmodule ApiSample.PageController do
  use ApiSample.Web, :controller

  def index(conn, _params) do
    json conn, %{params: _params}
  end
end
```

サーバーを起動します。

```
mix phoenix.server
```

http://localhost:4000/?a=b
等へアクセス

以下の結果が取れました。

```
{
  params: {
    a: "b"
  }
}
```

testも書きます。

```page_controller_test.ex
defmodule ApiSample.PageControllerTest do
  use ApiSample.ConnCase

  test "GET /" do
    conn = get conn(), "/?a=b"

    assert json_response(conn,200) == %{"params" => %{"a" => "b"}}
  end
end
```

Ectoの設定を色々コメントアウト等しないとテストが実行できないかもしれません。

```
mix test

Finished in 0.3 seconds (0.2s on load, 0.1s on tests)
1 test, 0 failures
```

無事テストが通りました。

では、次にRedisにデータをセットしたりゲットしたりしていきます。

```router.ex
  scope "/", ApiSample do
    pipe_through :api # Use the default browser stack

    get "/", PageController, :index
    get "/get", PageController, :get 
  end
```

router.exにroutingを追加します。
/getを追加しました。

再びpage_controllerを修正します。

```page_controller.ex
defmodule ApiSample.PageController do
  use ApiSample.Web, :controller
  import Exredis

  def index(conn, _params) do
    _params |> Enum.map fn {k, v} -> start_link |> elem(1) |> query ["SET", k, v] end
    json conn, %{params: _params}
  end

  def get(conn, %{"key" => key}) do
    json conn, %{ key: start_link |> elem(1) |> query ["GET", key] }
  end
end
```

単純に、setしてgetできるやつです。
indexは受け取ったパラメーターをredisにsetします。
getでは、パターンマッチで、keyというパラメータを受けています。
受け取ったkeyでredisからデータをgetします。

続いてテストも合わせて直します。（本当はテストから作るべきですね）

```page_controller_test.exs
defmodule ApiSample.PageControllerTest do
  use ApiSample.ConnCase

  test "GET /" do
    conn = get conn(), "/?a=b"

    assert json_response(conn,200) == %{"status" => "ok"}
  end

  test "GET /get" do
    get conn(), "/a=b"
    conn = get conn(), "/get?key=a"
    
    assert json_response(conn,200) == %{"status" => "ok", "key" => "b"}
  end
end
```

出来ました！

まとめ

Redisの呼び方がいまいちですが、目的は達成です。
Redisのいい呼び方を考えます。
「配列がうまくsortできない！」「な、何だってー！」

[昨日](http://qiita.com/jkr_2255/items/1f49df1c9146f32a6480)に引き続き、JavaScriptの配列の話です[^1]。そして、ECMA-262の仕様書では昨日ソースコードに展開した`Array.prototype.slice`の次に当たる、`Array.prototype.sort`に関する話です。

# デフォルトでの挙動
何も指定せずに`.sort()`を実行すると、中身の**文字列表現**に対して並べ替えを行うこととなります。また、EcmaScriptとしてはソートが安定であることは保証されません（[関連](http://qiita.com/falsandtru/items/41591040633bc88fcde7)）[^2]。

もちろんこれで事足りればそれでもいいのですが、数値やオブジェクトなどを並べ替えるには、このままでは全く役に立ちません。

# 実装定義となってしまう場合
そうなれば、引数として比較関数を与えることになるのですが、その前に実装定義な部分について考えておきましょう。

まず、具体的なソートアルゴリズムには何も言及がなく、実装定義で好きなように実装できます（もちろん、結果については仕様で決まっているので、それが定める結果を生成する必要はあります）。

また、0〜length-1のプロパティの中に以下のようなプロパティがある場合、振る舞いは実装定義となります。

* `Object.defineProperty`などでWritableをfalseにしたもの
* アクセサプロパティ

また、疎な配列の場合、並べ替え後も疎な配列となることになっています。ただし、疎な配列については、以下のいずれかような場合、振る舞いは実装定義となります。

* 0〜length-1のプロパティの中に、プロトタイプから継承したものがある
* `Object.preventExtension()`などで拡張不可となっている
* 0〜length-1のプロパティの中に、`Object.defineProperty`などでConfigurableをfalseにしたものがある

## 比較関数について
比較関数を指定する場合、その関数が以下のような挙動を示す場合、sortの振る舞いは実装定義となります。

* 配列自体を書き換えてしまう
* 正の数、負の数、0のどれでもない値を返す
* 両方に同じ引数を与えた時に、0以外の値を返す
* 同じ引数のペアを与えた時に、違う値を返すことがある
* 推移則を満たさない（$a < b$かつ$b < c$なのに$a = c$や$a > c$という結果を返してしまうなど）

## 実装定義って？
ECMAの仕様書ではC言語の仕様も参照するようになっていたのでそちらも確認したのですが、

> 処理系定義の動作（implementation-defined behavior）  未規定の動作のうち，各処理系が選択した動作を文書化するもの。
> 未規定の動作（unspecified behavior）  この規格が，二つ以上の可能性を提供し，個々の場合にどの可能性を選択するかに関して何ら要求を課さない動作。

というようになっています。JavaScriptの場合、各処理系がどのような動作をするのか明確に文書化されていることをみることは少ないのですが、とりわけクライアントサイドで使う場合、**実装を選ぶことが難しい**という事情があります。そして、sortでの「振る舞いは実装定義」となっているものは、「出力は入力の並べ替え」より前に来ていますので、**並べ替えであることすら保証されません**。例外を投げておしまい、なんてことも考えられますし、そのような領域に入り込むようなコードは、基本的には書くべきでないでしょう。

# 数値の比較関数〜タイトル回収
で、数値を並べ替えるような場合、よく下のような比較関数が使われます（MDNにも載っていました）。

```js:比較関数の例
arr.sort(function(a, b){ return a - b; });
```

`arr`に数値が入っているのは前提とするにしても、このままではうまく動かない事例が出てきます。

先ほど、比較関数が「正の数、負の数、0のどれでもない値を返す」場合は実装定義となる、と書きました。もちろん返り値が数値でなければこれを満たしてしまうのですが、実は数値にも、1つだけ「正でも負でも0でもない」数（？）があります。**`NaN`**です。

JavaScriptに限らず、IEEE 754で浮動小数点数を実装している環境にはたいてい`NaN`がありますが、相当に特殊な数です。

* `NaN === NaN`がfalse（JavaScriptの値の中で、`x !== x`となるものは`NaN`のみです）
* `NaN > (任意の数)`、`NaN < (任意の数)`、`NaN == (任意の数)`、すべてがfalse
* `NaN`と他の値との四則演算も、すべて結果が`NaN`

つまり、元の配列に`NaN`が1つでも入っていれば、比較関数も`NaN`を返してしまい、`.sort()`は結果を何も保証しなくなってしまいます[^3]。ということで、`NaN`が入りうる場合、それを考えて比較関数を書く必要があります（なお、無限大は正負の符号を付けられることからわかるように、比較関数の返り値としてもなんら問題ありません）。NaNが来る可能性があるなら、それを意識した比較関数を書く必要があります。

```js:NaNを最後にした昇順
arr.sort(function(a, b){
  var a_nan = (a !== a);
  var b_nan = (b !== b);
  if (a_nan && b_nan) return 0;
  if (a_nan) return 1;
  if (b_nan) return -1;
  //ここまで来ればaもbもNaNの可能性はない
  if (a < b) return -1;
  if (a > b) return 1;
  return 0;
});
```


[^1]: 昨日の件とは全く別な事情で知ったことなのですが、不思議と近い分野のことが連続していろいろと起きる気がします。
[^2]: [Firefoxでは安定性を保証してくれる](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/sort)そうです。
[^3]: 実際にうっかり使ってしまったのですが、`NaN`でない値の順序すら不定となりました。
Pillowで読み込んだ画像をS3にアップロードする

以下の関数を実行すればOKです．

```py3
def upload_image_to_s3(img, bucket_name, key_name):
    """
    imgはPillowのImageオブジェクト
    """
    conn = S3Connection(AWS_ACCESS_ID, AWS_SECRET_KEY)
    bucket = conn.get_bucket(bucket_name)
    k = Key(bucket, key_name)
    image_buffer = io.BytesIO()
    img.save(image_buffer, 'JPEG')
    image_buffer.seek(0)  # これを忘れると空データがs3に送られる
    k.set_contents_from_string(image_buffer.read())
```

## ポイント: image_buffer.seek(0)を忘れない

seek(0)の存在を忘れており，１時間もハマってしまいました．
PillowのImageでsaveメソッドを使った時，ファイルのカーソル？がファイルの末尾に来るらしく，カーソルを最初に戻してあげる必要があるみたいですね．忘れると，いきなり`EOF`，つまり終わりということでS3に空っぽの画像ファイルがアップロードされました．
Googleが出してるAndroidStyle(コードフォーマット)を使えるようにする


## とりあえず結果

1.ターミナルで下記コマンド実行
`curl -L https://gist.githubusercontent.com/futabooo/20513ee54c8afd05b4b8/raw/67670d97f060b5dbe8d590e8c9700855d8decd99/AndroidStyleCodeStyleInstall.sh | sh`

2.AndroidStudio > Preferences > Code Style > Scheme　でAndroidStyleを選択してOK
![スクリーンショット 2015-11-16 22.33.00.png](https://qiita-image-store.s3.amazonaws.com/0/9143/d1df1d48-1b66-0b8f-7a52-f64328380ea7.png "スクリーンショット 2015-11-16 22.33.00.png")


## 詳細
OSクリーンインストールしたり、AndroidStudio再インストールしたりなんかでちょいちょい設定しなおしてるので、スクリプトを用意してみました。

https://gist.github.com/futabooo/20513ee54c8afd05b4b8

```
#!/bin/bash
# Installs AndroidStyle IntelliJ configs into your user configs.
# Reference https://github.com/square/java-code-styles/blob/master/install.sh

echo "Installing AndroidStyle IntelliJ configs..."

for dirs in $HOME/Library/Preferences/IntelliJIdea*  \
         $HOME/Library/Preferences/IdeaIC*        \
         $HOME/Library/Preferences/AndroidStudio* \
         $HOME/.IntelliJIdea*/config              \
         $HOME/.IdeaIC*/config                    \
         $HOME/.AndroidStudio*/config
do
  if [ -d $dirs ]; then

    # Install codestyles
    mkdir -p $dirs/codestyles
    curl -L https://raw.githubusercontent.com/android/platform_development/master/ide/intellij/codestyles/AndroidStyle.xml \
    > $dirs/codestyles/AndroidStyle.xml

  fi
done

echo "Done."
echo ""
echo "Restart IntelliJ and/or AndroidStudio, go to preferences, and apply 'AndroidStyle' or '."
```
swiftでstoryboardの画面よりspritekitの画面を手前にしたい

 当方、swift初心者です。
現在、spriteKitを使って、タップした場所にnodeを表示するcodeを書いています。

背景はstoryboardにimageを貼り付けたのですが、
ビルドすると、imageの方がspriteKitより手前に表示されてしまいます。

どなたか？これを解決する方法をご教授下さい。
お願いします。
RailsでAjaxとjs個別読み込み？を試してみた備忘録

# はじめに
初投稿 & だいぶ既出
備忘録だから許してください〜
FXの現在レート取得APIを一定間隔で叩いてグラフ出したいな〜って思って始めてみました
ホントにこれでいいのか謎なのでツッコミお待ちしております

# やること
- ページロード後、Ajax使って一定間隔でpタグを書き換え
- jsをコントローラ毎に処理を変える

# Ajaxで一定間隔でページ一部ロード
まずこんなコントローラを用意します

```xxx_controller.rb
# 大本のページのやつ
def yyy
  @time = Time.now()
end

# ajaxリクエストを受け取って実行するやつ
def ajax_action
  @time = Time.now()
end
```

setIntervalで５秒毎にAjaxのリクエストをするcoffeescriptを作成

```xxx.js.coffee
$ ->
  timer = setInterval ->
    update()
  , 5000

update = ->
  $.ajax
    url: 'xxx/ajax_action'
    type: 'GET'
  return
```

routesも追加記述(scaffoldで作り始めちゃったのでこんな書き方に)

```routes.rb
resources :xxx do
  get "ajax_action", to: "xxx#ajax_action", on: :collection
end
```

viewをこんな感じにやると完成です
ちなみに最初はerbではなくslimを使ってたのですが、hoge.js.slimがちょっと上手くいかなかったのでerbに戻しました

```ajax_action.js.erb
$("#time").html("<%= @time %>");
```

```yyy.html.erb
<p id="time"><%= @time %></p>
```

これで5秒毎にpタグの部分だけ変わります

# jsをコントローラ毎に処理を変える
なんかこんな感じでいっぱいajax書いてたら、一辺に読み込み＆実行されて嫌だなって思って、個別でなんとか読み込ませて実行します
なるべく元の状態(rails newした状態)から変えずにやりたかったので、こんな感じ↓の方法をとってみました

jquery.readyselectorってのを使います
https://github.com/Verba/jquery-readyselector
からjquery.readyselector.jsを持ってきて、assets/javascript配下に置きます

application.html.erbのbodyの部分をちょっとだけ変更

```application.html.erb
<body class="<%= controller_name -%> <%= action_name -%>">
```

上で書いたcoffeescriptを次のように変更

```xxx.js.coffee
$('.xxx.yyy').ready ->
  timer = setInterval ->
```

このままでいけるんですが、turbolinksのせいでリンクから飛んできたら動いてくれないので

```
gem 'jquery-turbolinks'
```
を入れたらいい感じになるらしいです

# 参考
http://www.upty.jp/railsandajax-2-create-sample-ajax/
http://blog.hello-world.jp.net/javascript/1673/
http://o.inchiki.jp/obbr/97#toc_4
InnoDBの設定変数について

*半年間、MySQLを基礎からやり直すことにしたので、その間に勉強したことをQiitaに投稿していきます。*

**InnoDBの設定変数で気になるものを個人の記録用に、適当にピックアップして書いてます。**

## innodb_buffer_pool_size
このバッファ設定は最も重要なInnoDBに関する変数の1つであり、InnoDBテーブルデータとインデックスのキャッシュに使用するメモリ量を制御します。
ただ設定する際に注意しておいた方が良いのは、MyISAMはキーのみをキャッシュし、後はOSがデータをキャッシュするが、InnoDBはOSを信頼することなく、InnoDB自体がデータをキャッシュするという違いがあります。

## innodb_flush_log_at_trx_commit
InnoDBは設計上、MyISAMよりずっと厳格なデータ安全性の要件を持っており、たとえトランザクション最中に電源が落ちても最小損失によってデータの一貫性を維持しようとしてくれます。
ですが、パフォーマンスとデータ安全性を考えた上での設定が必要になります。
InnoDBでは、サーバ起動時にリカバリに使用されるトランザクションログを管理しており、トランザクションログの整合性を保つ為に、トランザクションがコミットされるたびにディスクにログをフラッシュします。
ただ、この方法は頻繁に短いトランザクションを実行するアプリケーションの場合は、パフォーマンスの低下に繋がるので、ログのフラッシュの間隔（回数／時間）を制御するなどの対応が必要になります。

|値|ログファイルへの書き込み間隔|ディスクへのフラッシュ処理          |個々のトランザクションコミット|
|:--|:-----------------------:|:-------------------------------|:--------------------------|
| 0 | 1回/毎秒                 |ファイルディスクリプタで実行される  |何も実行しない            |
| 1 | 1回/毎秒                 |ファイルディスクリプタで実行される  |ログファイルに書き込まれる |
| 2 | 1回/毎秒                 |ファイルディスクリプタで実行されない|ファイルディスクリプタに書き込まれる|

秒あたり1回のフラッシュは、100%保証されるものではないが、極端にCPU負荷がある場合以外は、実施間隔はほぼ1秒に近いということを頭に入れておいて下さい。

## innodb_file_per_table
innodb_file_per_table を有効にした場合、新しいテーブルではインデックスとデータが別個のファイルであるtable_name.ibdに格納されることになり、利点としては、同一サーバにある各テーブルのバックアップとリストアに貢献できます。
しかし、バックアップにも制限があり、サーバがダウンしているときか、またはすべてのトランザクションがコミットされてかつ新しいトランザクションが開始していないときに行う必要があります。
また、リストアする時も、まずALTER TABLE tbl_name DISCARD TABLESPACEを実行し、次に.ibdファイルを適切なデータベースディレクトリにコピーし、その後にALTER TABLE tbl_name IMPORT TABLESPACEを実行する必要がある。
NO_ARGタイプなので、オプションが存在している場合はONになり、オプションが存在していない場合はOFFになる。ただし、任意で1または0のBoolean引数を取ることも出来ます。

## innodb_lock_wait_timeout
innodb_lock_wait_timeoutは、潜在的なデッドロックを回避する為にあえて意図的にデットロックを発生させ、定期的にロック検出モニタを実行し、ロックの待機時間の制限枠を超えた場合に異常終了したことをクライアントに通知する設定変数です。

## innodb_force_recovery
このオプションは、消失データを回復させる際の強さの度合いを0〜6の7段階で設定し、InnoDBに指示します。
3以下のinnodb_force_recovery値を使用してテーブルをダンプできる場合は、破損した個々のページ上の一部のデータしか失われないため、比較的安全に行うことが出来ますが、4以上の値は、データファイルが永続的に破損する場合があるため、危険であるとみなされています。

|値 |それぞれの機能                                                |
|:--|:------------------------------------------------------------|
| 0 |リカバリが強制的に実行されない通常の起動                        |
| 1 |破損したページを検出した場合でも、サーバーが動作できるようにする  |
| 2 |マスタースレッドや、すべてのパージスレッドが実行されないようにする（パージ操作中にクラッシュが発生しそうになった時に有効）                                      |
| 3 |クラッシュリカバリのあとにトランザクションロールバックを実行しない|
| 4 |挿入バッファーのマージ操作を回避する。すべてのセカンダリインデックスを削除して再作成する必要がある|
| 5 |データベースを起動するときに、Undoログを参照せずに、InnoDBに、未完了のトランザクションでさえコミット済みとして処理させる。|
| 6 |リカバリに関連したRedoログのロールフォワードを実行しないようにする。データベースページを廃止された状態のままにし、それによってBツリーやその他のデータベース構造にさらに多くの破損が発生する可能性がある。|

**大きい方の値には、小さい方の値の機能が全て含まれています
4〜6の値は、指定すると、データファイルが永続的に破損する場合があります。
また、MySQL 5.6.15の時点では、InnoDBを読み取り専用に設定します。**
vim(自分用めもめも

##vim使ってて、何かにつけてrecordingが現れる
【問題点】　
　:pwdしてもrecording中でpwdできない。

【解決策】
　recording中にqを押す、それだけ。

【詳しく】
　recodingというのは、、、
　　操作がすべて記録される機能。
　　escキーで編集モードに入った後、コマンドqaでスタート、qでストップ。
　　記録したものを再生するには、@a、@bなどを打てばおけ。
　　単純作業の繰り返し等に便利。

【参考】
https://thinkit.co.jp/article/123/2?page=0%2C2
http://blog.bonar.jp/entry/20060828/1156827277
http://qiita.com/taketin/items/aa6cc363f84f6090f1c0
phpのちょっとしたメモ

## PATH_SEPARATOR(定数)
OSによって左右される。
windowsなら、";"
macなら":"になる。

## ライブラリの使い方
ライブラリを読み込みには、include_pathに追加されている必要がある。

## ライブラリの読み込み方法
```php
// PHP 4.3.0以後
set_include_path(get_include_path().PATH_SEPARATOR.$lib_path);

// すべてのバージョン
init_set("include_path", get_include_path().PATH_SEPARATOR.$lib_path);
```

## zend framewordでhttp clientを使った時、basic認証を行うときに使った方法

```php
$client->setHeaders("Authorization", "Basic ".base64_encode("<user>:<passwd>"))
```
iOS の UITableView や UICollectionView で表示するデータが無い時の画面を簡単に作る方法

**TL;DR: [DZNEmptyDataSet](https://github.com/dzenbot/DZNEmptyDataSet) を使おう。**

---

iOS で UITableView や UICollectionView を使うときは多いと思います。

表示するデータがある場合がほとんどだと思いますが、状況によっては表示するデータが存在しないこともあります。

例えば、検索した結果が0件の場合や通信に失敗してデータが取れなかった時、アプリをインストールした直後でまだデータが無いときなどです。

[こちらの記事ではそのような状況をエンプティーステートと呼んでいます。](http://postd.cc/how-to-fix-a-bad-user-interface-part1/#empty)

そのような何も表示するものがない状態の時に空の View を表示するだけではユーザーは何がどうなっているのかよく分からなくて混乱してしまいます。

例えば以下の様な画面がいきなり出てくるとびっくりします(ツイートを検索した結果が0件だった場合)。

![Simulator_Screen_Shot_2015_11_16_21_13_58.png](https://qiita-image-store.s3.amazonaws.com/0/17704/3c9d6a99-037a-eaaf-0b56-0ef84b2fdb70.png)

こういう場合には「何も表示するものがないよ！」 と表示してあげるだけでもかなり UX が向上します。

しかし表示するものが無いときの為に View を作ったり条件分岐するのは面倒です。

そんな面倒さを解決するのが [DZNEmptyDataSet](https://github.com/dzenbot/DZNEmptyDataSet) です。

リポジトリの README.md のサンプルコードやスクリーンショットを見ていただくとどういうものなのか分かると思います。

弊社で開発している iOS のツイッタークライアントの [feather](http://covelline.com/feather/) も以前は表示するツイートが0件のときは先ほど貼ったスクリーンショットの様に何も表示していない寂しい画面でした。

現在は [DZNEmptyDataSet](https://github.com/dzenbot/DZNEmptyDataSet) を使って簡単ではありますが、 `No Tweets` と表示しています。

![Simulator_Screen_Shot_2015_11_16_21_09_16.png](https://qiita-image-store.s3.amazonaws.com/0/17704/3f5a1602-020b-7269-462c-9726e2affb99.png)

非常に些細な事ですがこれだけで UX が上がりました。

また、API へリクエスト中はエンプティーステートとして扱わないと言った制御は `- (BOOL)emptyDataSetShouldDisplay:(UIScrollView *)scrollView` で制御することができるので、データを取得した結果が0件だったのか、まだ取得が完了していないから0件なのかなどの制御も簡単に行うことができます。

delegate のメソッドがたくさん用意してあるので場面に合わせて細かい制御ができるのも嬉しいです。

面倒で後回しにしがちなエンプティーステートの表示ですが、[DZNEmptyDataSet](https://github.com/dzenbot/DZNEmptyDataSet) を使うと非常にお手軽にできるのでおすすめです。
PHP で Soracom API クライアントを書いてみた


https://github.com/CoachUnited/soracom-php

誰かつくるだろうと思っていたけれど、なかなか出てこないので書いてみた.
Guzzle (の新しいやつ)と戦っている時間のほうが長かった..

# インストール

```
$ composer require cu/soracom:dev-master
```

もしくは composer.json に以下を書いて `composer update`.

```
"require": {
  "cu/soracom": "dev-master"
}
```

# 使い方

## 認証情報の設定

環境変数から Operator の認証情報を取得するので、設定してから使う.

```
$ export SORACOM_EMAIL=example@example.com
$ export SORACOM_PASSWORD=thisispassword
```

## クライアント初期化

```
$c = new CU\Soracom\Client();
```

## subscriber 一覧の取得

```
$c->subscribers();
```

## subscriber の登録

```
$c->registerSubscriber(['imsi' => '<IMSI>', 'registrationSecret' => '<PASSCODE>']);
```

## subscriber を無効化

```
$c->deactivateSubscriber('<IMSI>');
```

その他いろいろ、とりあえず書いてみたけど、動作確認は中途半端です.

# 注意

まだAPIでできること完全にわかってないので、ぜんぶ動くかどうかはわからない.

# 参考

* [API Reference](https://dev.soracom.io/jp/docs/api/)
deviseを使って認証している場合のログイン前提のコントローラのテスト


Railsの認証系の定番ライブラリDeviseでコントローラをテストする場合、 
ログインした状態のテストをしたい場合の対処方法を確立した。


公式のが一番確実だけれども、公式の方法だと作ったユーザオブジェクトの属性を変更することが出来ない。
例) 有料ユーザや無料ユーザの振る舞いや、退会ユーザの場合など

参考: How To: Test controllers with Rails 3 and 4 (and RSpec)
https://github.com/plataformatec/devise/wiki/How-To:-Test-controllers-with-Rails-3-and-4-(and-RSpec)

そこで上記リンクのものを修正/拡張した

## ログイン用のモジュールを作る

spec/support/controller_macros.rb にログイン用のモジュールを作る

```
module ControllerMacros
  def login_admin(admin)
    @request.env["devise.mapping"] = Devise.mappings[:admin]
    sign_in admin
  end

  def login_user(user)
    @request.env["devise.mapping"] = Devise.mappings[:user]
    user.confirm!
    sign_in user
  end
end

```


## helperファイルに設定を追加

Rspec2ならspec_helper、Rspec3ならrails_helperにdeviseを読んであげる

```rails_helper.rb

#deviseを読み込ませる
require 'devise'

RSpec.configure do |config|

　＃ deviseのテストヘルパーをロードする
  config.include Devise::TestHelpers, :type => :controller
　＃ 作成したログインモジュールを追加する
  config.include ControllerMacros, :type => :controller
end

```

## specファイル例
```xxx_controller_spec.rb
require 'rails_helper'

RSpec.describe XxxxController, :type => :controller do
  describe "GET #show" do
    # userをFactoryGirlで作る
    let(:user) { FactoryGirl.build(:user) }
　　# 作ったユーザでログインする
    before do
      login_user user
    end

    it "can get it" do
      get :show, id: 1
      
	  # 出力結果
      p response
    end
  end
end

```

refs:

Featureテストの場合はこちらを参考にすると良い
* "Rails + RSpec + Capybara で Devise での認証ログインが必要なインテグレーションテスト（RequestSpec）を行う"　http://easyramble.com/request-spec-on-devise-login.html
Erlang - EUnitで単体テスト

足し算関数をeunitでテスト
eunitは実行するとモジュール内のtest関数を探して試験してくれます

```erlang:main.erl
-module(main).
-author("haminiku").

%% API
-export([add/2]).
add(A, B) -> A + B.
```

```erlang:tests.erl
-module(tests).
-include_lib("eunit/include/eunit.hrl").
-author("haminiku").

%% API
-export([test/0]).

%% テスト実行
%% erl -noshell -pa ebin -eval "eunit:test(test_module, [verbose])" -s init stop

test() ->
  add_test(),
  assert_test().

add_test() ->
  4 = main:add(2, 2),
  5 = main:add(2, 2).

assert_test() ->
  ?assertEqual(4, main:add(2, 2)),
  ?assertEqual(5, main:add(2, 2)).

%% 関数名にtestが無いので実行されない
sample() -> ?assertEqual(1000, main:add(2, 2)).
```

```shell-session
# コンパイル
>>>erlc ./tests.erl 

# テスト実行
>>>erl -noshell -pa ebin -eval "eunit:test(tests, [verbose])" -s init stop
======================== EUnit ========================
module 'tests'
  tests: add_test...*failed*
in function tests:add_test/0 (tests.erl, line 17)
**error:{badmatch,4}
  output:<<"">>

  tests: assert_test...*failed*
in function tests:'-assert_test/0-fun-1-'/1 (tests.erl, line 21)
**error:{assertEqual,[{module,tests},
              {line,21},
              {expression,"main : add ( 2 , 2 )"},
              {expected,5},
              {value,4}]}
  output:<<"">>

  [done in 0.009 s]
=======================================================
  Failed: 2.  Skipped: 0.  Passed: 0.
```
Follower DatabasesでHerokuのPostgreSQLを冗長化


### 前提条件
* Herokuに課金利用していること
* HerokuのPostgreSQL Add-onであるHeroku Postgresを利用していること

### 目的
Follower databaseを設定することで、スレーブのDBをでホットスタンバイにする
HerokuのPostgreで読み取り専用で本番DBに安全にアクセスできる


マスターのDBのプラランは、以下のようにスタンダードプラン以上だと使うことが出来る

> Followers are only supported on Standard, Premium, and Enterprise tier database plans. Follow these steps to upgrade from a Hobby tier (dev or basic) plan to a production plan.


また副作用的に読み取り専用のDBができるので、問い合わせ調査などSelectするだけの場合はこちらを利用すると良いだろう
> A database follower is a read-only copy of the master database that stays up-to-date with the master database data. As writes and other data modifications are committed in the master database, the changes are streamed, in real-time, to the follower databases.


```
heroku pg:info -a アプリ名
=== HEROKU_POSTGRESQL_PURPLE_URL (DATABASE_URL)
...
Fork/Follow: Available
```

同じプランである必要な無い。パフォーマンスに影響が無いのかはよくわからなかった


```
heroku addons:create heroku-postgresql:standard-0 --follow HEROKU_POSTGRESQL_CHARCOAL_URL -a アプリ名

Adding postgresql-rigid-xxxx to app_name... done
Setting HEROKU_POSTGRESQL_COLOR_URL and restarting app_name... done, vXXX
Follower will become available for read-only queries when up-to-date.
Use `heroku pg:wait` to track status
Use `heroku addons:docs heroku-postgresql` to view documentation.
```

### まさかの時のフェイルオーバー

#### マスタのDBがStandardプランの場合はマニュアルでフェイルオーバー
プランがStandardの場合はマニュアルでフェイルオーバーする必要がある。
マニュアルで実行する手順は以下の通り
https://devcenter.heroku.com/articles/upgrading-heroku-postgres-databases#upgrade-with-follower-changeovers-2-prevent-new-database-updates

#### マスタのDBがPremiumプランの場合は自動でフェイルオーバー

> Heroku Postgres premium plans have the HA feature with automated failover. R


ref: https://devcenter.heroku.com/articles/heroku-postgres-follower-databases


## スレーブを読み取り専用のDBとして接続する手順

Herokuの環境変数から、DBの接続上を情報を取得しPostgresのクライアントで接続する

```
heroku config -s -a アプリ名| grep HEROKU_POSTGRESQL_COLOR_URL
```

MacだとPsequelが一番使いやすい気がする。MySQLのSequel Proと似た使い心地
http://www.psequel.com/
Node.js稼働用の仮想サーバーvagrant初期設定（自分用）

vagrant destroyしちゃった場合に目的の環境に戻す備忘録

（サーバーの用途）
Node.jsでWEBサイトスクレイピングして、結果をMySQLに保存するエージェント。
・インストールしてたシステム


・使ってたライブラリ
>cheerio
>request
>sequelize

(Vagrantfileへの変更)※file消したりinitする場合

```text:Vagrantfile
 config.vm.box = "bento/centos-6.7"
 config.vm.network "private_network", ip: "192.168.33.10"
 config.vm.synced_folder "data", "/path/to/guest/dir",
  type: "rsync",
  owner: "vagrant",
  group: "vagrant",
  rsync__exclude: [".git/", "vendor/"]
```

(vagrant sshで入った後の各種実行コマンド)

①とりあえずyum 最新に(長い。。。)

```text:tarminal
sudo yum -y update
```

②rootに昇格

```text:tarminal
sudo su -
```

③MySQLインストール

```test:ダウンロードする
wget http://dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm
```

```test:yumリポジトリを追加する
sudo rpm -Uvh mysql-community-release-el6-5.noarch.rpm
```

```test:インストールする
sudo yum install mysql-community-server
```

```test:確認
rpm -qa | grep mysql
```

```test:起動確認
sudo service mysqld start
```

```test:パスワード確認
sudo cat /root/.mysql_secret
※(local time):hogehogeを記録
```

```test:mySQL起動
mysql -u root -p
```

```test:mySQL起動
mysql -u root -p
```


④いろいろインストール＆設定

```text:tarminal
sudo yum -y install httpd
sudo yum -y install php

sudo service httpd start
sudo chkconfig httpd on
sudo service iptables stop
sudo chkconfig iptables off
```

⑤シンボリックリンク設定

```text:tarminal
cd /vagrant
sudo rm -rf /var/www/html
sudo ln -fs /vagrant /var/www/html

```

⑥PHPバージョンアップ（5.3だとphpmyadmin動かんから）

```text:tarminal
rpm -ivh --force http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
rpm -ivh --force http://rpms.famillecollet.com/enterprise/remi-release-6.rpm

yum install --enablerepo=remi --enablerepo=remi-php55 php php-devel php-mbstring php-fpm php-mysql php-mcrypt
```

⑦phpmyadminインストール
１：公式からファイルダウンロード
２：Vagrantfileと同じDirに解凍後のファイルおく（短い名前にリネームしてもOK）
３：インストール

```test:terminal
sudo yum -y install php-mbstring
sudo yum -y install php-mysql
```

４：httpd再起動

```test:terminal
sudo service httpd restart
```

⑧いろいろON (順番どうなの？)

```test:terminal
sudo chkconfig httpd on
sudo chkconfig mysqld on
cronの設定方法

## crontabでcronを操作

crontabコマンドでcronを操作します。

```bash
crontab [ -u ユーザ名 ] { -l | -r | -e }
```

[option]

```
-u: cronを設定するユーザーを指定
-l: cronを一覧で表示
-r: cronの設定を全消去
-e: cronを設定するエディタを起動する
```

## cron設定手順

### 1. cronを設定するためのエディタを起動

`-uオプション`で指定したユーザーで
cronを設定したコマンドが実行されます。

```bash
crontab -u root -e
```

### 2. cronの設定を記述

以下の書式に従って記述します。

```cron
分 時 日 月 曜日 <実行コマンド>
```

#### 固定指定

以下のように設定すると、15時になる度に実行されます。

```cron
0 15 * * * echo "hello."
```

#### 間隔指定

間隔を指定したい場合は、以下のようにします。
例では、5分毎に実行されます。

```cron
*/5 * * * * echo "hello."
```

#### 複数指定

複数時間を設定したい場合はカンマ(,)で区切ります。
例では、午前2時5分と午前2時10分に実行されます。

```cron
5,10 2 * * * echo "hello."
```

#### 範囲指定

複数指定よりも範囲で指定した方がいい場合があります。
以下のようにすると、指定範囲で実行できます。
例では、午前2時5分、午前3時5分、午前4時5分、午前5時5分に実行されます。

```cron
5 2-5 * * * echo "hello."
```

上記の書式で記述後、保存してエディタを閉じると設定完了です。

## 設定ファイルの読み込み
cronの設定を記述したファイルを読み込むことで、cronを設定できます。

```bash
echo '*/5 * * * * echo "hello."' > cron.conf
crontab cron.conf
```

crontabで、`-rオプション`を誤ってつけてしまうと、設定が全て消去されてしまいます。
設定ファイルを読み込むことで、消してしまってもすぐに復旧でき、Gitなどでバージョン管理も行えます。

## 補足

* cronで実行されるコマンドは、実行ユーザーのホームディレクトリで実行されます。（都合が悪い場合は、実行するコマンド内で、`cd`しましょう。）
* cronの標準出力、標準出力エラーは、mailコマンドを経由して実行ユーザーのメールボックスに送信されます。
* 標準出力を別の場所に吐き出したい場合は`リダクレクト`すると良いです。