OmniAICreator/Qiita-1.07M huggingface dataset:
zshとpecoでワンライナー呼び出し

## 動機
* zsh + pecoによるヒストリ呼び出しが便利
* 呼び出したヒストリを編集して使い回す　という作業を何度かやってる内に、ワンライナーをテンプレート管理して呼び出しても便利な気がしてきた
* 棲み分けとしては下記のようなケースを想定
    * ヒストリ呼び出し 
        * 過去と全く同じコマンドを叩く
        * 過去と全く同じではないが編集箇所が少ないコマンドを叩く
        * 叩く頻度もそこそこ高い
    * ワンライナー呼び出し
        * ヒストリ呼び出して使い回そうとすると編集箇所が結構多い
        * 何をやるコマンドだったかよく覚えてない
        * たまにしか叩かないけど便利なコマンド
* 「たまに叩く」「よく覚えてない」の気休め的対策として、コメントも残して管理出来ればベター


## 作るもの
* ワンライナーを可変パラメータを含めて登録
* 登録したワンライナーをpeco経由で呼び出し
* 呼び出したワンライナーの可変パラメータ部分を実際の内容に置き換えて実行


## 動作確認環境
* CentOS 6.5
* zsh 4.3.10


## 準備
* `.zshrc`に下記設定を追加

```zsh:.zshrc
ONELINER_DIR=~/.oneliner
ONELINER_TXT=${ONELINER_DIR}/oneliner.txt
ONELINER_PARAM_MARKER_PREFIX="%%"

# ワンライナー登録
function _insert-oneliner() {
  autoload -Uz read-from-minibuffer
  read-from-minibuffer "Insert oneliner comment:"
  if [ -n ${REPLY} ]
  then
    if [ ! -d ${ONELINER_DIR} ]
    then
      mkdir ${ONELINER_DIR}
    fi
    echo ${BUFFER}"\t#"${REPLY} >> ${ONELINER_TXT}
    zle -M "Inserted \"${BUFFER}\" >> ${ONELINER_TXT}"
  fi
}
zle -N _insert-oneliner
bindkey "^[i" _insert-oneliner

# pecoで選択したonelinerコマンドを表示
function peco-search-oneliner() {
  BUFFER=$(cat ${ONELINER_TXT} | sort | peco | awk -F"\t" '{print $1}')
  zle clear-screen
  zle beginning-of-line
}
zle -N peco-search-oneliner
bindkey "^po" peco-search-oneliner

# コマンドライン上の可変パラメータ(%%HOGE)を置換
function _kill-oneliner-param-forward() {
  local AT
  AT=$(echo ${RBUFFER} | awk -v marker="${ONELINER_PARAM_MARKER_PREFIX}" '{print index($0, marker)}')
  if [ $AT -ne 0 ]
  then
    CURSOR=$((CURSOR+AT-1))
    for i in {1..${#ONELINER_PARAM_MARKER_PREFIX}}
    do
      zle delete-char-or-list
    done
    zle kill-word
  else
    zle end-of-line
  fi
}
zle -N _kill-oneliner-param-forward
bindkey "^[j" _kill-oneliner-param-forward
```


## 使い方

### ワンライナーを登録する
![insert-oneliner.gif](https://qiita-image-store.s3.amazonaws.com/0/4516/8e56e7a7-ad65-e7fc-463d-e5cff5fb2b8a.gif)


* 登録したいコマンドを入力。実行はしない
    * 可変パラメータ部分がある場合は `%%NAME` 形式で記述する(%% がprefix)
* `ESC-I`を叩いてコメント入力プロンプトを起動 => コメントを入力
* 入力したら`~/.oneliner/oneliner.txt`に`COMMAND<TAB>#COMMENT`形式で追記される
* ※ 直接`~/.oneliner/oneliner.txt`を編集してもOK。その場合も`COMMAND<TAB>#COMMENT`形式は踏襲する


### pecoからワンライナーを呼び出す
![peco.gif](https://qiita-image-store.s3.amazonaws.com/0/4516/1d10efc5-93c2-7b8b-f5e1-8ca2fcd3e44a.gif)


* `Ctrl-P O`でpecoを起動してワンライナー一覧を表示
* 選択したワンライナーのコマンド部分だけがコマンドラインに表示される（実行はしない）


### ワンライナーの可変パラメータ部分を置換して実行する
![replace.gif](https://qiita-image-store.s3.amazonaws.com/0/4516/036b6b00-36a5-7a30-4708-ce215cfe65cd.gif)


* コマンドラインにワンライナーを表示した状態で`ESC-J`を叩くと、直近の可変パラメータにジャンプするので、実際の内容に置換する
* 以降、`ESC-J`を叩く => 置換する　を可変パラメータ部がなくなるまで繰り返す。最後に`ESC-J`を叩いた際は行末にジャンプする
    * 可変パラメータが最初から無い場合に`ESC-J`を叩いた場合は行末にジャンプするのみ
Rubyリファレンスマニュアル「るりま」の誤字などを見つけた時の貢献フロー

# Rubyリファレンスマニュアル「るりま」の誤字などを見つけた時の貢献フロー

## 概要

Rubyを継続的に使っている方なら、おそらく **誰もがお世話になっている** Rubyリファレンスマニュアル。
このRubyリファレンスマニュアル「るりま」の誤字などを見つけた時の貢献フローとして、
実際にプルリクエストをマージしていただいたので、例としてまとめます。

## 経緯
下記を確認していたところ、サンプルコードのインデントが揃っていない箇所をみつけました。

http://docs.ruby-lang.org/ja/2.0.0/class/UnboundMethod.html

~~~ruby
class Foo
  def foo
    p :foo
    end # => ここが揃っていない
  @@orig_foo = instance_method :foo
  def foo
    p :bar
    @@orig_foo.bind(self).call
  end
end
~~~

## 報告方法を確認
* 下記URLを確認

http://doc.okkez.net/2.0.0/view/help

~~~
間違いを見付けた場合は
https://github.com/rurema
へお願いします。
~~~

とのこと。

* 該当リポジトリをみてみる。

https://github.com/rurema

複数のリポジトリが一覧表示されている。 *doctree* が日本語マニュアルのプロジェクトのようなので移動。

https://github.com/rurema/doctree

* どうやって貢献するか確認

ここにまとめてありました。
https://github.com/rurema/doctree/wiki/HowToContribute

~~~
rurema/doctreeへのPull Requestだとより修正を適用するのが楽です。
~~~

と、記載されてあったことと、実際に過去のIssueの履歴を見ると typo の修正をプルリクエストとして
送っている方が複数名いらっしゃたので真似ることにする。

## プルリクエストまで

* 日本語リファレンスを下記ページから *Fork* します

https://github.com/rurema/doctree

* *Fork* されました

https://github.com/tbpgr/doctree

* ローカル環境に *clone* します

~~~bash
git clone git@github.com:tbpgr/doctree.git
~~~

* トピックブランチを作成します

~~~bash
$ git checkout -b fix_unbound_method_sample_indent
~~~

* 修正をします

doctree / refm / api / src / _builtin / UnboundMethod

diff

~~~ruby
     def foo
       p :foo
-      end
+    end
~~~

* commitします

~~~bash
$ git add -A
$ git commit -m "Fix sample code indent"
~~~

* トピックブランチをpushします

~~~bash
$ git push origin fix_unbound_method_sample_indent
~~~

* GitHubの *fork* したリポジトリで *Compare & pull request* を実行してプルリクエストを送る

* 翌日、マージしていただきました

https://github.com/rurema/doctree/pull/107

## 参照
るりま
http://docs.ruby-lang.org/ja/

るりまサーチ
http://docs.ruby-lang.org/ja/search/
TomcatをMacにインストール

ちょっと所用でTomcatをインストールしてみた。
環境はMac OS X 10.9.2

## 1. ひとまずMacのJavaのバージョンも上げておく

[Java SE Development Kit 8 Downloads](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html)から下図の Mac OS X x64 の項にあるjdk-8u5-macosx-x64.dmgをダウンロードしてインストール


![JDK_Download.png](https://qiita-image-store.s3.amazonaws.com/0/5798/047cce04-5f42-6400-8d9a-33ceb93085bf.png "JDK_Download.png")


## 2. Tomcatの導入

### 2-1. ダウンロード

[Apache Tomcat - Apache Tomcat 7 Downloads](http://tomcat.apache.org/download-70.cgi)から`tar.gz`をダウンロードして解凍しておく

![tomcat-targz.png](https://qiita-image-store.s3.amazonaws.com/0/5798/8e49df3e-c280-25c8-c81a-9de40eeeaf4b.png "tomcat-targz.png")


### 2-2. /usr/localへ配置

解答したapache-tomcat-<version>フォルダを/usr/localへ移動

```
$ sudo mv ~/Downloads/apache-tomcat-7.0.54 /usr/local
```

### 2-3. /Libraryにシンボリックリンク

作業しやすいように？/Library/tomcatへシンボリックリンクを貼る

```
$ sudo ln -s /usr/local/apache-tomcat-7.0.54 /Library/Tomcat
$ sudo chown -R <username> /Library/Tomcat
```

### 2-4. 起動・シャットダウンのシェルにアクセス権を付与

```
$ sudo chmod +x /Library/Tomcat/bin/*.sh
```

## 3. Tomcatを起動

```
$ /Library/Tomcat/bin/startup.sh
```

`http://localhost:8080`で起動される。

![tomcatserver.png](https://qiita-image-store.s3.amazonaws.com/0/5798/398bfd34-18fb-5828-d63d-e6f333088a50.png "tomcatserver.png")

## 4. Tomcatをシャットダウン

```
$ /Library/Tomcat/bin/shutdown.sh
```

コピーして起動するだけですよねって言われる内容ですが備忘録として。
Javaって一発でポンみたいなのがなくてめんどくさい。
【html】h*要素の横に要素を並べる

##概要
h*タグをdisplay:inline;でインライン化すると横に並べることができる。

##具体例

```html:html
<h3 id="hoge">タイトル</h3>日付
```
このままだと、タイトルと日付が2行で表示される。
タイトルと日付を1行で表示するには、h3タグをインライン化する。

```css:css
#hoge{
  display: inline;
}
```
Error: Failed to update tap: phinze/cask

`Error: Failed to update tap: phinze/cask` となったので、 https://github.com/phinze/homebrew-cask を開いて確認してみたところ、 https://github.com/caskroom/homebrew-cask にリダイレクトされたので、 `brew untap phinze/cask` して `brew tap caskroom/cask` とし直しました。

```
% brew update
Error: Failed to update tap: phinze/cask
Already up-to-date.
```

```
% brew untap phinze/cask
Untapped 1 formula
% brew tap caskroom/cask
Cloning into '/usr/local/Library/Taps/caskroom/homebrew-cask'...
remote: Reusing existing pack: 45287, done.
remote: Counting objects: 51, done.
remote: Compressing objects: 100% (50/50), done.
remote: Total 45338 (delta 17), reused 0 (delta 0)
Receiving objects: 100% (45338/45338), 14.39 MiB | 744.00 KiB/s, done.
Resolving deltas: 100% (28007/28007), done.
Checking connectivity... done.
Tapped 1 formula
```

余談ですが、 `brew tap` するよりも `brew install caskroom/cask/brew-cask` のように `brew install` を直接した方が良いかもしれません。

特に [`Brewfile` では `tap` を使わずに `brew install user/tap/formula` を使う](https://github.com/Homebrew/homebrew/issues/26851)方が良いようです。
grepのかわりに 高速検索 ag/the_silver_searcher を使う

https://github.com/ggreer/the_silver_searcher

とても早い、いろんな環境で使っていきたい。

##EXAMPLES

|コマンド|説明|
|:--|:--|
|$ag printf|カレントディレクトリから"printf"という文字列を検索する。|
|$ag foo /bar/|path /bar/ において、"foo" という文字列を検索する。|
|$ag foo /bar/|path /bar/ において、"foo" という文字列を検索する。|
|$ag class ~/src --ruby |~/src 以下のrbファイルから"class" という文字列を検索する。|
|$ag --list-file-types|オプション指定できるファイル形式の一覧を表示する。|
【PHP】コールバック系の配列関数


#array_map
各要素に対して、コールバック関数を適用する。

```php:配列の各要素を2倍にする
$hoge = array(5,4,7);

$hoge = array_map(function($arg){
  return $arg * 2;
},$hoge);

var_dump($hoge);
/*
 array(3) { [0]=> int(10) [1]=> int(8) [2]=> int(14) }
*/
```

スコープ外の変数を参照するには、use()を使用する。

```php:配列の要素をn倍する
$n = 3;
$hoge = array(5,4,7);

$hoge = array_map(function($arg) use($n){
  return $arg * $n;
},$hoge);

var_dump($hoge);
/*
 array(3) { [0]=> int(15) [1]=> int(12) [2]=> int(21) }
*/

```



その他随時追加予定。
実行環境付きクラウドIDEのCodebox.IOでGVM、Groovy、SpringBoot、Grailsを動かしてみた #yokohamagroovy

# Codebox.IO https://www.codebox.io/

結論から先に。

[GVM](http://gvmtool.net/) -> イケる。
Groovy -> イケる。
GroovyServ -> イケる。
SpringBoot -> イケる。
Grails -> 死んだ。

![new box](http://i.gyazo.com/65fd61a193adade96b1290c5d24c862c.png)
Codebox.IO は、PHP/Java/Dart/Node.js/Python/Ruby/Go/C/Scalaなどに対応したクラウドIDEですが、オンライン/オフラインエディタの提供だけではなく、boxと呼ばれる実行用インスタンスも提供してくれます。

Freeユーザは256MBのインスタンス1boxが利用できるようです。
まずはサインアップしてJavaのboxを。名前は適当に付けて「Create box」します。
Dashboardが表示されるので、そのままさきほどのbox名をクリックすると、ブラウザ内にオンラインIDEが立ち上がります。

![java ide](http://i.gyazo.com/6e550d4be8f5117350d280e1586f2001.png)

「File」メニューの中に「New Terminal」があり、ここからターミナルが開けます。

![terminal](http://i.gyazo.com/b4e2ea90fe0e6553c1fbaf547fdeabd5.png)

このターミナルは、ペーストにも対応してくれています。便利ですね。
さっそくペタりと。

```bash
> curl -s get.gvmtool.net | bash
(略)                                                                                                                                     
All done!                                                                                                                            
                                                                                                                                     
Please open a new terminal, or run the following in the existing one:                                                                
    source "/home/codebox/.gvm/bin/gvm-init.sh"                                                                                      
Then issue the following command:                                                                                                    
    gvm help                                                                                                                         
Enjoy!!!                            
>
```

すてき。
なんかダウンロードがバカっ早い。
同じ調子で、Groovy、GroovyServ、SpringBootもいけました。

たとえば `spring run` とかでポートがバインドされた場合、「Project」メニューの「Running Ports」でポート一覧が見れるようになっていて(「8080」とか出る)、そこをクリックすると、そのポートにリダイレクトされているURLにアクセスできた。

もちろんWeb IDEの方はJava向けなので快適にGroovy書けるわけではないですが、boxインスタンス便利。

そしてGrailsを試そうと `gvm i grails` 、`grails create-app` までやってみて、いざ `grails run-app` ！というところでインスタンスの応答がなくなってしまい。やはり256MBじゃGrailsみたいにメモリフットプリントでかいフレームワークは動かすことすらできないか。。

サクッとboxをDeleteしてなかったことに。

Codebox.IO自体については、わかりやすいhelpがあるのでそちらを。
http://help.codebox.io/
altチェッカー

ページ内でalt文言を付け忘れているimg要素の画像ファイル名を抽出する簡易チェッカーです。コンソールで下記コードをコピペして使います。
（jQueryを使っているページ限定）

```js
$('img').each(function(i, elm) {
  $elm = $(elm);
  if($elm.attr('alt') === void(0)) {
    console.log($elm.attr('src'));
  }
});
```
PHPのタイプヒントはキャッチ可能な例外をスローしない

ずっと勘違いしていたことがありました。
PHPのタイプヒントは例外をスローしません。

マニュアルなりエラーメッセージなりをしっかり読めばわかる話ですが…

php.netより
> タイプヒントの指定を満たさないとキャッチ可能な致命的エラーとなります。

エラーメッセージより
> Catchable fatal error: Argument ...

ずっと`catchable`というワードに注目していたために勝手に __捕捉可能な例外をスローする__ だと思っていた。
実際は __キャッチ可能な致命的エラー__ つまり`fatal error`を発行するわけだったのです。

# 致命的なエラーをキャッチする

タイプヒントによって出力されるエラーには`Catchable fatal error ...`とくっついてくるのですが、
なんとなくこのメッセージだと、 **ちゃんとエラーをキャッチして下さい** と言われているようで気分がよくありません。

タイプヒントで発生するエラーレベルは`E_RECOVERABLE_ERROR`です。
`set_error_hundler`を利用してエラー発生の動作を制御してみます。

```php
set_error_hundler(function($errorLevel, $errorMessage) {
  switch($errorLevel) {
    E_RECOVERABLE_ERROR:
      echo $errorMessage;
      exit(255);
      break;
  }
});
```

これで致命的なエラーをキャッチして処理を制御したことになるので出力されるエラーメッセージから`Catchable fatal error:`の箇所が抜けて通常のエラーメッセージ形式の出力になります。

# タイプヒントで例外をスローさせる

`set_error_hundler`で例外をスローすれいいだけです、難しいことを考える必要はないですね。

```php
set_error_hundler(function($errorLevel, $errorMessage) {
  switch($errorLevel) {
    E_RECOVERABLE_ERROR:
      throw new InvalidArgmentException($errorMessage, $errorLevel);
      break;
  }
});
```

# 他のE_RECOVERABLE_ERRORと区別する

`E_RECOVERABLE_ERROR`はタイプヒント以外でも発生する可能性があります。
タイプヒントのエラーであるかどうかはエラーメッセージをみて、そのエラーがタイプヒントのものであるかどうかを判定する必要があります。

```php
define('TYPEHINT_PCRE', '/^Argument (\d)+ passed to (?:(\w+)::)?(\w+)\(\) must be an instance of (\w+), (\w+) given/');

set_error_hundler(function($errorLevel, $errorMessage) {
  switch($errorLevel) {
    E_RECOVERABLE_ERROR:
      if (preg_match(TYPEHINT_PCRE, $errorMessage)) {
        throw new InvalidArgmentException($errorMessage, $errorLevel);
      } else {
        throw new ErrorException($errorMessage, $errorLevel);
      }
      break;
  }
});
```

# まとめ

* phpには __キャッチ可能な致命的エラー__ が存在する。
* __キャッチ可能な致命的エラー__ はエラーレベルが`E_RECOVERABLE_ERROR`になる。
* `E_RECOVERABLE_ERROR`は`ser_error_hundler`で処理を制御してあげないとエラーメッセージに`Catchable fatal error ...`と出力される（つまりfatal errorになる）
* タイプヒントで発生するエラーは`E_RECOVERABLE_ERROR`
C#で作るexeファイルにアイコンを埋め込んでみる

こちらの投稿ネタのパクリである
[goで作るexeファイルにアイコンを埋め込んでみる (Windows) - Qiita](http://qiita.com/zetamatta/items/4aa36661336a56b95e06)

```bat:make.bat
@echo off
path=%path%;C:\Windows\Microsoft.NET\Framework64\v4.0.30319

csc getopt.cs /resource:getopt.cs /resource:make.bat /win32icon:app.ico

PAUSE
```

ソースも埋め込んでる理由はこちら
[C# - ソースを実行ファイルに埋め込む方法 - Qiita](http://qiita.com/ymko/items/7cf9a19e03ba9dcebfaa)
HRForecastで歯抜けたデータを補充した

## なりゆき
- おいら: DBの接続エラーが累積してHRForecastがデータベースに接続できていない！
- お嬢: HRForecastのデータ歯抜けてるから補充して
- おいら: ラジャー！

## 概要
おいらの所ではcrontab (コード末尾参照) でmysql -eにて値を取得してcurlでHRForecastに記録しています。このcrontabを入力として、任意の期間の値を補充しました。かなり限定された用途にしか使えないと思うのですが、ご参考まで。

上記の状況を想定してWHERE句で期間を限定して値を取得し投げています。また私たちの所では前日との差分も必要となっていたので、そちらのデータも以下のスクリプトで記録するようにしています。

## コード
```rb
# -*- encoding: utf-8 -*-
require 'pp'
require 'net/http'
require 'uri'
require 'active_support'
require 'active_support/all'

HR_URL = 'http://hf-forecast.awesome-admin.com'
AUTH = ['hogehoge', 'hagehage']

Time.zone = 'UTC'
ENV['TZ'] = 'UTC'

def hr_post(path, data={})
  url = URI(HR_URL)
  http = Net::HTTP.new(url.host, url.port)
  request = Net::HTTP::Post.new(url.path + path)
  request.basic_auth(*AUTH)
  request.set_form_data(data)
  response = http.request(request)
end

begin_date = Date.parse '2014-05-04'
end_date = Date.parse '2014-05-07'

DATA.each_line do |line|
  post_cmd = line.split(' ')[6..-1].join(' ')
  (post_prefix, get_cmd, post_suffix) = post_cmd.split('`')
  (sql_prefix, base_sql_query, sql_suffix) = get_cmd.split('\'')
  next unless base_sql_query
  graph_path = post_suffix.split(' ')[0].split('/')[4..-1].join('/')

  base_sql_query += base_sql_query.index('WHERE') ? ' AND ' : ' WHERE '

  dailies = []
  ((begin_date - 1) .. (end_date + 1)).each do |date|
    filter_query = "created_at <= \"#{date.to_s}\""
    sql_query = base_sql_query + filter_query
    sql_cmd = [sql_prefix, sql_query, sql_suffix].join('\'')
    dailies.push([date, `#{sql_cmd}`.to_i])
  end

  dailies.each do |date, num|
    options = { number: num.to_i , datetime: date.to_s(:db) }
    hr_post("/api/#{graph_path}", options)
  end

  dailies.each_with_index do |value, i|
    date, num = *value
    next if i < 1
    options = { number: num.to_i - dailies[i-1][1].to_i, datetime: date.to_s(:db) }
    hr_post("/api/#{graph_path}-subtract", options)
  end
end
__END__
* * * * * nobody curl -F number=`mysql -hawesome-db.com -uhogehoge -phagehage awesome_db -BN -e 'SELECT COUNT(id) FROM access_log'` http://hf-forecast.awesome-admin.com/api/awesome_service/pv/all 2>&1 | logger -t post_gf -p local0.info
* * * * * nobody curl -F number=`mysql -hawesome-db.com -uhogehoge -phagehage awesome_db -BN -e 'SELECT COUNT(DISTINCT member_id) FROM acess_log'` http://hf-forecast.awesome-admin.com/api/awesome_service/pv/unique 2>&1 | logger -t post_gf -p local0.info
```

## おわりに
もっと汎用的なスクリプト書きたい・・・！crontabのパースとかかなり苦しい感じになってます。
ubuntuでモニターの輝度を起動時に下げる

ノートパソコンにインストールすると輝度が初期化されてしまうようです。

まず任意の明るさにバックライトの明るさを設定します。
設定したら現在の明るさの数値を確認します。

```
 cat /sys/class/backlight/acpi_video1/brightness 

```

rc.localを編集します
```
sudo vim /etc/rc.local
```

echo ユーザ定義 > /sys/class/backlight/acpi_video1/brightnessをexit0の上の行に追記します
ユーザ定義には明るさの値を入力します

```
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.
echo ユーザ定義 > /sys/class/backlight/acpi_video1/brightness
exit 0

```
Web Starter Kit 導入メモ

よーし、パパ [Web Starter Kit](https://developers.google.com/web/starter-kit/) 触っちゃうぞー。
ちゃんとしたドキュメト読みたい人は[こちら](https://developers.google.com/web/fundamentals/tools/setup/setup_kit)だよ！

## インストールだ！

まずは必要なもの入れましょう。

### まずは本体ファイルをクローン

$ git clone https://github.com/google/web-starter-kit.git

ファイルの中身見るだけならこれだけでもOKっぽい。でもいろいろしたいので他にも必要なものいれる。

### 次に Node.js と Ruby と Sass Gem と Gulp 入れる

- [Node.js](http://nodejs.org/)
- [Ruby](https://www.ruby-lang.org/en/downloads/)
- [Sass Gem](http://sass-lang.com/install)
- [Gulp](http://gulpjs.com/)

上記入れ終わったら

```
$ cd web-starter-kit
$ npm install
```

する。そうすると ``node_modules`` フォルダができる。これで Gulp 使えるようになるんかな。

ということでインストール完了。カンタン。

## プロジェクトつくる

``web-starter-kit/app`` の中で 

```
$ gulp 
```

ってコマンド打てばカレントのディレクトリに ``web-starter-kit/dist`` ができる。


（書いてる途中）
Attributeが未定義の場合にだけ定義したいとき


node['hoge']['web']['user'] が他のレシピで定義されていなかったら、'fuga'をdefaultに設定する方法は以下

```attributes/default.rb
default[:hoge][:web][:user] = (node['hoge']['web']['user'] rescue nil) || 'fuga'
```
Light Tableに入ってるNode.jsのバージョンはいくつ？（＋お遊び）

ClojureScript経由で調べてみました。
Light Table UIにconnectしてClojureScriptコードを評価するとNode.jsの[Globals](http://nodejs.jp/nodejs.org_ja/docs/v0.10/api/globals.html)のオブジェクトが使えます。

その中のprocessオブジェクトを使うと、Node.jsのバージョンは0.10.22だとわかりました。

![WS000000.JPG](https://qiita-image-store.s3.amazonaws.com/0/40558/a620ff50-350b-075e-7719-487a61d94f42.jpeg)

ついでにNode.jsの機能をお試し。OSモジュール

![WS000001.JPG](https://qiita-image-store.s3.amazonaws.com/0/40558/47329c1d-7969-c4ba-1107-016b5ea0b4c8.jpeg)

外部プロセスの起動はChild Processで

![WS000004.JPG](https://qiita-image-store.s3.amazonaws.com/0/40558/cff52645-c114-64cb-4121-a4266c450091.jpeg)

残念ながら指定できるエンコーディングはほとんどないようです。
Rubyチートシート


たまにしかRubyを触らないので毎回、調べ直す自分のためのチートシート

##コメント

"#"から行末まで。

複数行は下記で挟む。

```
=begin
・・・
=end
```


##変数各種
変数の扱いは最初の文字で決まるので注意する。

- ローカル変数(小文字で始まる) 
- グローバル変数(“$"で始まる) 
- インスタンス変数(“@"で始まる) 
- 定数(大文字で始まる)
- 疑似似変数(self、true、false、nil、__FILE__、__LINE__)


|変数|意味|
|---|---|
| $! |もっとも近い例外 |
| $~ |最後のパターンマッチに関するデータ |
| $& |最後のパターンマッチした文字列 |
| $. |最後に読んだファイルの行番号|
| $< |コマンドライン引数や標準入力の仮想ハンドル |
| $> |標準出力 |
| $_ |getsコマンドなどで読み込んだ文字列　|

##構文

### for〜in
```
for x in [ 1, 2, 3]
	puts(x)
end
```

### do
```
イテレータ do |i|
	i.xxxxx
end
```

### ループ制御

- break ループを中断終了
- next 以降のループの処理を行わず、次のループに

##クラス

###クラス

```
class Foo

	# new　で実行
	def initialize
		# メンバー変数は @つき
		@variable = 0	
	end
　

	#メソッド	
	def function1( foo , bar )
		x = ...
		#do something
		return x
	end

	#クラスメソッド
	def self.function2( foo , bar )
		#do something
	end

end
```

###インスタンス変数とアクセッサ

Fooクラスのオブジェクトにインスタンス変数barを作り、Fooクラスのインスタンスfooではfoo.barとしたいなどの場合、attr_reader,attr_writer,attr_accessorを使用する。

```
class Foo
	def initialize
		@bar = nil	
	end

	attr_accessor :bar
	...
end
```

###初期化

```
finstance = Foo.new
```

## 組み込みメソッド

標準的な処理は各クラスに自動的に組み込まれる組み込みメソッドが存在し、省略可能なselfオブジェクトの組み込みメソッドで呼び出される。つまり、print("xxxx")はself.print("xxxx")に同じである。


|組み込み関数|説明|
|---|---|
|chop|最後の文字を取り除く|
|eval(str)|文字列をRubyプログラムとして評価した結果を返す|
|exec(str)|文字列のコマンドを実行する|
|fork()|プロセスのフォーク|
|gets([rs])|コマンドラインの引数のファイルまたは標準入力から読み込む|
|sub(x,[y])|$_の先頭のxをyで置換する|
|gsub(x,[y])|$_の全てのxをyで置換する|
|open(path[,mode])|指定のパスを指定のモードでオープンする|
|print|標準出力へ表示|
|printf|C言語のprintfと同じ|
|puts|改行付き出力|
|sprintf|C言語のsprintfと同じ|

...


## 文字列

###文字列操作

|文字列の操作|意味|
|---|---|
| == |文字列が同じか|
| =~| パターンと同じか |
|a+b|文字列の連結|
|a*n|文字列の繰り返し|
|s.index(str[,pos])|文字列の場所を返却する|
|s.length|文字列の長さ|
|s.sub(reg[,str])|文字列の置き換え|

###パターンマッチ
|文字パターン|説明|
|---|---|
|.|任意の一文字|
|[]|文字クラス指定　[a-z]でaからzまで|
|[^]|文字列クラスの逆|
|\w|[0-0A-Za-z_]と同じ|
|\s|空白文字[\t\r\n\f]|
|\d|数字と同じ|
|*|直前の表現の0回以上の繰り返し|
|+|直前の表現の1回以上の繰り返し|
|?|直前の表現の0回または1回|
|^|行頭|
|$|行末|
| パイプ記号 | 選択|


### ありがちなパターンマッチ例


文字列の始まりがbarで始まる場合

```
if( str =~ /^bar/ ))
```

文字列の最後がfoo

```
if( str =~ /foo$/ )
```

### 文字列を使って正規表現を作成

```
regexp = Regexp.new( "^foo" )
str.scan( regexp )
```

### その他
数字を文字列に

```
num.to_s
```

日付を文字列に

```
d = Date.today
d.strftime("%Y/%m/%d")
```

## ファイル/ディレクトリ

### Dirクラス
|Dirクラスメソッド|説明|
|---|---|
|Dir.glob(pattern)|ワイルドカード展開を行った結果を配列で返す|
|Dir.chdir(path)|ディレクトリ移動|
|Dir.foreach(path)|ディレクトリの中の各要素をイテレータで取得|
|Dir.mkdir(path[,mode])|ディレクトリ作成|

## rdocの書き方

```
# コメント
# ==== Args
# 引数名1 :: 説明
# 引数名2 :: 説明
# 引数名3 :: 説明
# ==== Return
# 返り値の説明
# ==== Raise
# 例外の説明
```
WindowsのEmacs使いがMacに乗り換える時におすすめの設定

私は2009年10月ごろからWindows(Putty/Cygwn)上でEmacsを使いはじめたのでEmacs歴5年です。

最近MacBook Airに乗り換えたのですが、キーボードがあまりに違いすぎてものすごいストレスでした。
開発効率もがくんと落ちました。笑

このままではいかんと思いいろいろ設定してみたところ、やっと手に馴染むようになってきたので環境設定方法をメモしておきます。

(まだ試行錯誤中なのでこのコンテンツは随時書き換えます)

# 環境
* MacBook Air 2014年モデル
* 日本語キーボード
* iTerm2

## capsキーをcommandに割り当て
capsキーはまず使わないし誤爆してイライライするので、無効にするか別の機能を割り当てましょう。
私はいろいろ試した結果、capsキーを`command`に割り当てるのがシックリくることがわかりました。

理由は、Windowsに慣れた体にとってはGUIのコピペ(command + x,c,v)とアンドゥ(command + z)を押すときに、一番左下のキーでやるのが自然だからです。

システム環境設定 -> キーボード -> 修飾キー

で設定できます。

## MacOSXのiTerm2で command + wでタブを閉じないようにする

これ必須です。
http://dqn.sakusakutto.jp/2014/05/macosx-iterm2-command-w.html

## 「英数」キーを"alt option"に割り当て

これめちゃ重要です。WindowsでEmacsをヘビーに使っていた人は、meta(alt)キーを左親指で押していたと思います。MacBookでこの位置にあるキーは「英数」キーです。

KeyRemap4MacBook を使って「英数」キーをmeta(alt option)に割り当てましょう。

`Eisuu to Option_L (Only in terminal)` にチェックを入れておくと幸せになれます。
(「英数」を単独で押したときはちゃんと「英数」として機能してくれるのでご安心を。)

KeyRemap4MacBook
https://pqrs.org/macosx/keyremap4macbook/index.html.ja

## iTerm2でaltキーをmetaとして認識させる

http://qiita.com/DQNEO/items/524724982ef49beb7f56

## 他にもおすすめ設定があれば教えてください！

他にもこういうのやったらいいよってのがあればぜひコメントで教えてください！
PHP: 多次元配列でarray_searchを使えるようにする関数

1次元配列まで対応しているarray_searchを多次元配列に使えるようにする関数を作ってみました

in_arrayとarray_valuesと多次元配列についてのコチラの投稿を、参考にさせて頂いています
[多次元配列でもin_arrayを使えるようにする関数をクロージャを使って実装](http://qiita.com/srea/items/31d68239c42f14bbc15c)

```lang:array_search_recursive関数
function array_search_recursive($search_element, $array)
{
	$recursive_func = function ($search_element, $array) use (&$recursive_func) {
		foreach ($array as $key => $value) {
			if(is_array($value)){
				if($recursive_func($search_element, $value) !== false) return $key;
			}
			if ($search_element == $value) return $key;
		}
		return false;
	};
	return $recursive_func($search_element, $array);
}
```

それでは、この関数を多次元配列に適用してみます

```lang:例 
// 多次元配列
$array = [
	'a',
	'b',
	[
		'c',
		[
			'd',
			'e'
		]
	],
	'f'
];

// 適用
echo array_search_recursive('a', $array) . PHP_EOL;
echo array_search_recursive('b', $array) . PHP_EOL;
echo array_search_recursive('c', $array) . PHP_EOL;
echo array_search_recursive('d', $array) . PHP_EOL;
echo array_search_recursive('e', $array) . PHP_EOL;
echo array_search_recursive('f', $array) . PHP_EOL;
```

```lang:例の出力結果
/**
 * 要素が1次元目のどの要素番号にあるかを出力
 * (連想配列の場合、キー名を出力)
 */

0
1
2
2
2
3
```

改良点:
検索する多次元配列の要素番号を配列にして返したら、活用範囲が更に広がりそうな気がします
(例 上記の適用例の'c'を検索した場合、[2, 0]を返す)

現状では、1次元目の番号以上を求める場合、array_search_recursiveを複数回繰り返すことによって求めることになるので、オーバーヘッドがあります
Symfony2 + PHPUnitではじめてのテスト（モック編）


##はじめに
単体テスト、機能テストについては、下記を参照してください。
[Symfony2 + PHPUnitではじめてのテスト（単体テスト編）](http://qiita.com/imunew/items/cb8e9dac7361cee399ba)
[Symfony2 + PHPUnitではじめてのテスト（機能テスト編）](http://qiita.com/imunew/items/39ac9283d030a8c4f9d4)


##モックを使ってみる
依存しているオブジェクトをシミュレートするのが難しいときに、オブジェクトをモック（代用）に置き換えるのが非常に有効です。

[モックオブジェクト - phpunit](http://phpunit.de/manual/current/ja/test-doubles.html#test-doubles.mock-objects)

決済モジュールをモックに置き換えてテストします。
決済モジュールをテストする際は、サンドボックス環境を利用するのですが、エラーを細かくシミュレートできないので、エラーの内容ごとに分岐する処理を作る場合に困ってしまいます。

そこでPHPUnitのMockオブジェクトを利用し、期待通りの処理結果（エラーオブジェクト）を返却するようにテストケースを実装します。

###実装サンプル
実際、[sopra.jp](http://sopra.jp)で使っていたコードです。
課金バッチを実行するも、決済エラーになるというシナリオです。

```php
public function testExecute() {
        
        $members = $this->getEntityManager()->getRepository('SopraCoreBundle:Member')->findAll();
        foreach ($members as $member) {
            $creditCard = new CreditCard('4111111111111111', 2020, 12);
            $this->getMembershipManager()->upgrade($member, $creditCard);
        }
        
        $cardResponseDto = new CardCaptureResponseDto();
        $cardResponseDto->setMstatus('failure');
        $cardResponseDto->setVResultCode('NC04000000000000');
        
        $captureResponse = new CaptureResponse($cardResponseDto);
        
        $cardManager = $this->getMock('{Namespace}\Card\CardManager', array('capture'));
        $cardManager->expects($this->any())
          ->method('capture')
          ->will($this->returnValue($captureResponse));
        
        $captureCommand = new CaptureCommand();
        $captureCommand->setCardManager($cardManager);
        
        $application = new Application($this->getKernel());
        $application->add($captureCommand);
        
        $command = $application->find('sopra:batch:capture');
        $commandTester = new CommandTester($command);
        $commandTester->execute(array('command' => $command->getName()));
        
        $dispaly = $commandTester->getDisplay();
        echo PHP_EOL.$dispaly;
    }
```

##さいごに
自分自身、時間がないことを言い訳に、テストコードを書かずに、これまで過ごしてきましたが、一度はじめてしまうと、癖になりそうな感覚はあります。
テストを書いて良かったなと思うことは、以下のとおりです。

- テストコードを実行してみつかる不具合がある
- テストコードを書いているうちに、実装部分のリファクタリングが進むことがある
- 同じ条件で繰り返しテストを実行できる
- とにかく安心できる
- テストコードはときに取り扱い説明書になる

ただ、小さいチームがはじめてテストコードを書く場合は注意が必要かと思います。（あくまで個人的な意見です）

- はじめること、続けることが大事
- テストを義務にしない
- 自分のために書く
- いきなり大きなテストを書かない
- テストを書きすぎない（実装とのバランスを考える）
- 実環境でのテストが不要になるわけではない

これを機に社内にテストコードを書くエンジニアが増えてきたら、カバレッジ分析、自動テストなどに取り組んでいきたいと思います。
percol (peco)でニコニコ動画を選択して再生する

(2014/11/12追記 : [peco(percol)を使ってコマンドラインから作業用BGMを検索・再生する - Qiita](http://qiita.com/tigberd/items/af8e1ef9c151ee958cc7) を書きました、便利)

RSSを読み込んでpercolで絞り込み、curlで動画をdumpした結果をmplayerにパイプします。

こんな感じ
![スクリーンショット 2014-06-29 12.44.10.png](https://qiita-image-store.s3.amazonaws.com/0/32836/af3f6514-f17d-ddf6-52f4-49e8ff7eec01.png "スクリーンショット 2014-06-29 12.44.10.png")
![スクリーンショット 2014-06-29 12.45.53.png](https://qiita-image-store.s3.amazonaws.com/0/32836/3bb8a091-e318-04e9-ab79-750dc376f5ab.png "スクリーンショット 2014-06-29 12.45.53.png")


## 必要なもの
- percol (or peco)
- curl
- ruby
- mplayer

## 動画をdumpするシェルスクリプト
以下を適当にパスが通ってるところに置いてIDとパスワードを埋めておきます

```bash:nicovideo-dump
#! /bin/sh

if [ $# -eq 0 ]
then
    TARGET=$(cat -)
else
    TARGET=$1
fi

EMAIL="hoge"
PASS="hoge"

SAVEDIR=/tmp
COOKIE=/tmp/nico_cookie
FILENAME=`echo $TARGET | ruby -e "print $<.read.chomp.split('/')[-1]"`

curl -c $COOKIE -d "mail=$EMAIL" -d "password=$PASS" "https://secure.nicovideo.jp/secure/login?site=niconico" --ssl -i > /dev/null
curl -b $COOKIE -c $COOKIE $TARGET -i > /dev/null
FLAPI_POSTFIX=`echo $FILENAME | ruby -e "print $<.read.chomp[0,2] == \"nm\" ? \"?as3=1\" : \"\""`
FLAPI_RES=`curl -b $COOKIE "http://flapi.nicovideo.jp/api/getflv/$FILENAME$FLAPI_POSTFIX"`
VIDEO_URL=`echo $FLAPI_RES | ruby -e "require \"cgi\";print CGI.unescape(Hash[*($<.read.chomp.split(\"&\").map{|e| e.split(\"=\")}.flatten)][\"url\"])"`
curl -b $COOKIE $VIDEO_URL
curl -b $COOKIE "https://secure.nicovideo.jp/secure/logout" --ssl -i > /dev/null

exit 0
```

```bash
$ nicovideo-dump http://www.nicovideo.jp/watch/sm****
```

みたいにして取得出来てたら成功
※取得方法が違うので公式チャンネル動画は取得出来ません

## percolで動画を選んでmplayerに流す
適当にワンライナーでランキングを取得してpercolで選択してみます

```bash
$ ruby -r rss -e 'RSS::Parser.parse("http://www.nicovideo.jp/ranking/fav/daily/all?rss=2.0").channel.items.each {|item| puts item.link + "\t" + item.title}' | percol | awk '{print $1}'
```

これで選択した動画のURLが取得できていたらnicovideo-dumpとmplayerにパイプすると動画が再生できます

```bash
$ ruby -r rss -e 'RSS::Parser.parse("http://www.nicovideo.jp/ranking/fav/daily/all?rss=2.0").channel.items.each {|item| puts item.link + "\t" + item.title}' | percol | awk '{print $1}' | nicovideo-dump | mplayer -
```

## 参考

>[ニコニコ動画のダウンロード - noise](http://d.hatena.ne.jp/with137d/20120329/1332970974)
「画面端でクリックできる」ようにGtk2/Gtk3/xfwm4テーマを矯正する

# 概要

自分は主にXubuntu (Xfce)環境で生活してますが、Gtkやxfwm(ウィンドウマネージャ)のテーマ設定で、どうしても譲れない設定というのがあります。

* (Gtk) ウィンドウを最大化した時に、カーソルを画面右端にピッタリつけた状態で、スクロールバーをドラッグできる。
* (xfwm) ウィンドウを最大化した時に、カーソルを画面右上端にピッタリつけた状態で、クローズボタンをクリックできる。

自分はほとんどのウィンドウを最大化して使うので、このへんの挙動がユーザビリティに大きく影響するのです。

Windowsではこんなこと当然のようにできるんですが、Xfceでは不思議とこんなこともできてないテーマをちょいちょい見かけます。 あえてそうしてるのか、見落としているのかは分かりませんが。

ということで、ここでは既存のテーマをいじって上記の挙動を実現するための方法を書きます。

**なお、「こうやったらうまくいった」というだけで、自分はテーマエンジンについてそこまで深く理解できてないのでそのへんはご注意下さい。**

# テーマファイルの場所

Ubuntu系ディストロの場合、システムワイドのテーマファイルは`/usr/share/themes`ディレクトリ以下にあります。 また、ユーザ個別のテーマファイルは`~/.themes`に格納します。

まず、いじりたいテーマファイルディレクトリを`~/.themes`以下にコピーしておきましょう。

    $ mkdir ~/.themes
    $ cp -r /usr/share/themes/Adwaita ~/.themes/Adwaita-Modified

以降はこのコピーを編集すればOKです。

# Gtk2

Gtk2のテーマ設定はテーマファイルディレクトリ下の`gtk-2.0/gtkrc`ファイルで行います。

Gtk2のスクロールバーを右端で掴めるようにするには、`GtkRange::trough-border`を0に設定すればいいみたいです。

    GtkRange::trough-border = 0

テーマによっては`GtkRange`クラスとは別のクラスに設定しているかもしれないですが、とにかく"trough"(容れ物、溝)がキーワードになってるようです。

# Gtk3

Gtk3のテーマ設定はテーマファイルディレクトリ下の`gtk-3.0/gtk.css`ファイルで行います。 多くの場合、gtk.cssが他のCSSファイルをインポートしています。

Gtk3の場合、上記の`trough-border`に加えて`-GtkScrolledWindow-scrollbars-within-bevel`の設定が必要になります。

    -GtkRange-trough-border: 0;
    -GtkScrolledWindow-scrollbars-within-bevel: 0;

これを両方とも0にしておかないと、うまくスクロールバーを掴めないようです。

# xfwm4

xfwm4 (Xfceのウィンドウマネージャ)のテーマ設定はテーマファイルディレクトリ下の`xfwm4/themerc`ファイル及び各種画像ファイルです。

ウィンドウを最大化した時のクローズボタンと画面右端とのスキマはthemerc中の`maximized_offset`項目です。

    maximized_offset=0

一方、画面上端とのスキマはタイトルバー画像とボタン画像の縦幅で決まってるようです。

よって、画像ファイル群`title-*.{png,xpm}`と`close-*.{png,xpm}`の縦幅が等しくなるように加工すれば、縦方向のスキマが0になります。


# 参考

* http://askubuntu.com/questions/334283/gtk-scrollbar-with-transparent-or-no-trough
* https://bugs.launchpad.net/ubuntu/+source/human-theme/+bug/422511
* https://bugs.launchpad.net/egtk/+bug/606388
* https://developer.gnome.org/gtk3/stable/GtkScrolledWindow.html#GtkScrolledWindow--s-scrollbars-within-bevel
* http://wiki.xfce.org/howto/xfwm4_theme
* https://wiki.ubuntu.com/Artwork/Documentation/Murrine
* https://developer.gnome.org/gtk3/stable/GtkCssProvider.html
C+OpenCVでカメラキャプチャ

## 目標
C言語でOpenCVライブラリを用いて、ビデオキャプチャを行う。

## 準備
### 環境
* MacOSX Marvericks(10.9)
* Homebrew

### インストール
```bash
brew install opencv
```

## 使い方
### ヘッダーファイル
```c
#include <cv.h>
#include <ctype.h>
#include <highgui.h>
```

### コンパイル
```bash
gcc ${filename} `pkg-config opencv --cflags` `pkg-config opencv --libs`
```

${filename}の位置にコンパイルしたいファイル名を入力するとa.outという実行ファイルができる。
実行する場合は以下で実行できる。

```bash
./a.out
```

## 使用例
### カメラキャプチャ
```c:camera_capture.c
#include <cv.h>
#include <ctype.h>
#include <highgui.h>

int main() {
    int c = 0; // キーボード入力用
    CvCapture *capture=0; // カメラキャプチャ用
    IplImage *frame=0; // キャプチャ画像用

    // カメラキャプチャ取得用
    capture = cvCreateCameraCapture(0);

    // キャプチャ画像を表示するためのウィンドウを作成
    cvNamedWindow("Capture", CV_WINDOW_AUTOSIZE);

    while (1) {
        // キャプチャ画像を取得
        frame = cvQueryFrame(capture);

        // 取得したキャプチャ画像を表示
        cvShowImage("Capture", frame);

        // キーボード入力を待つ
        c = cvWaitKey (2);
        if (c == '\x1b') { // Escキー
            break;
        }
    }
}
```

## ソースコードなど
https://github.com/greeeenkew/c-opencv/tree/master/camera_capture
Symfony2 + PHPUnitではじめてのテスト（単体テスト編）


##まずは導入してみよう
なぜ、テストコードを書くのか、テストコードはどう書くべきか、といった話はおいといて、今回はとにかくテストコードを書いて実行してみるということを目的とします。

###PHPUnitのインストール(composer)
さっそくインストールからはじめましょう。
今回はタイトルにもあるようにSymfony2(2.3)環境にPHPUnit(3.7)を導入します。
composer.jsonに下記記述を追加し、updateすれば、インストールは完了です。

[第3章 PHPUnit のインストール - phpunit](http://phpunit.de/manual/3.7/ja/installation.html#installation.composer)


```javascript:composer.json
{
    "require-dev": {
        "phpunit/phpunit": "3.7.*"
    }
}
```


##さっそくやってみよう
はじめにこれを読みましょう。

* [Testing - Symfony(current)](http://symfony.com/doc/current/book/testing.html)
* [テスト - Symfony2日本語ドキュメント](http://docs.symfony.gr.jp/symfony2/book/testing.html)

###ユニットテスト
下記のようなシンプルなクラスがあるとします。
年月を指定して、月初もしくは月末を取得するだけのクラスですが、実際に使う前に単体である何パターンかテストしておきたいところです。

```php:DateTimeHelper.php
<?php
namespace Sopra\CoreBundle\Helper;
use DateTime;

class DateTimeHelper {
    
    private function __construct() {  }
    
    public static function getFirstDayInMonth($year, $month)
    {
        
        return new DateTime("$year-$month-01");
    }
    
    public static function getLastDayInMonth($year, $month) {
        
        return new DateTime(date('Y-m-d', mktime(0,0,0, $month + 1, 0, $year)));
    }
}
```

そこで、下記のようなテストケースを作成します。

```php:DateTimeHelperTest.php
<?php
namespace Sopra\CoreBundle\Tests\Helper;

use Sopra\CoreBundle\Helper\DateTimeHelper;
use Sopra\CoreBundle\Tests\TestCase\BaseTestCase;

class DateTimeHelperTest extends BaseTestCase {
    
    public function testGetFirstDayInMonth() {
        
        $firstDay = DateTimeHelper::getFirstDayInMonth(2013, 1);
        $this->assertEquals('2013-01-01', $firstDay->format('Y-m-d'));
        
        $firstDay = DateTimeHelper::getFirstDayInMonth(2013, 12);
        $this->assertEquals('2013-12-01', $firstDay->format('Y-m-d'));
        
        $firstDay = DateTimeHelper::getFirstDayInMonth(2014, 3);
        $this->assertEquals('2014-03-01', $firstDay->format('Y-m-d'));
    }
    
    public function testGetLastDayInMonth() {
        
        $lastDay = DateTimeHelper::getLastDayInMonth(2012, 2);
        $this->assertEquals('2012-02-29', $lastDay->format('Y-m-d'));
        
        $lastDay = DateTimeHelper::getLastDayInMonth(2013, 2);
        $this->assertEquals('2013-02-28', $lastDay->format('Y-m-d'));
        
        $lastDay = DateTimeHelper::getLastDayInMonth(2013, 12);
        $this->assertEquals('2013-12-31', $lastDay->format('Y-m-d'));
    }
}
```

####テストの実行
作成したテストを実行するために、phpunitコマンドを実行します。
phpunitコマンドについては、本家サイトに詳しい説明がありますので参照ください。


[コマンドラインのテストランナー - PHPUnit](http://phpunit.de/manual/3.7/ja/textui.html)

実際に上述のDateTimeHelperTestを実行してみると、下記のように出力されます。

```Shell
$ cd bin
$ ./phpunit -c ../app/ ../{path to test file}/DateTimeHelperTest.php
PHPUnit 3.7.27 by Sebastian Bergmann.

Configuration read from /path/to/Application Root/app/phpunit.xml

..

Time: 353 ms, Memory: 16.25Mb

OK (2 tests, 6 assertions)
```
機械学習をはじめよう

#Introduction

「機械学習」
みなさんはどうやってこの言葉に出逢いましたか？
最近よく聞くから？友達にやってみないかと誘われて？

もしあなたが今この記事を読んで機械学習という言葉を知ったのなら、それは私にとってとても喜ばしいことです。

でも、いざ始めてみると...
難しいですよね。

本屋で[パターン認識と機械学習](http://www.amazon.co.jp/%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E8%AA%8D%E8%AD%98%E3%81%A8%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92-%E4%B8%8A-C-M-%E3%83%93%E3%82%B7%E3%83%A7%E3%83%83%E3%83%97/dp/4621061224)をパラパラっとめくってみて「うっ...」っとなった方もいるんじゃないでしょうか。

じつは、機械学習の理論のかなりの部分は難解な数式で構成されています。
初めからその数式に挑もうとすると... 難しくて挫折しそうになります。

もしあなたが機械学習のアルゴリズムを完全に、どこまでも深く理解したいのなら数式をいじり倒す必要があります。
しかし、アルゴリズムを実装してみたり、実際に使ってみるだけなら、そんなに深く理解する必要はありません。数式を完全に理解しなくても、アルゴリズムの動作は理解できますし、実装もできます。

今回は、機械学習をこれから始める人、機械学習に興味はあるけどどういうものなのかを知らない人のために、機械学習とは何か、何ができて、何がすごいのかを解説していきます。
次回以降はアルゴリズムの実装も少しずつ上げていくつもりです。
機械学習に少しでも興味を持っていただければとても嬉しいです。

#機械学習って何？
そもそも機械学習って何でしょうか？

機械学習が使われている身近な例は、天気予報です。
「朝焼けは雨、夕焼けは晴れ」、「ツバメが低く飛ぶと雨」といったことわざを聞いたことがありますか？
ことわざというのは経験やエピソード(故事)から生まれますよね。
これは過去の経験に基づいて未来を予測しています。
例えば、「晴れの日の前日はいつも夕焼けがきれいだった」といったものを経験として、「じゃあ今日は夕焼けがきれいだから明日は晴れだろうな」といったかんじで未来を予測するわけです。

天気予報はこれをコンピュータにやらせています。
天気予報は、過去の気象データ(気温とか湿度とか)を使って未来の天気を予測しています。扱うものが気象データという数値になっただけで、やっていることはことわざによる天気の予測と同じです。

「過去の経験に基づいて未来を予測する」
これがまさに機械学習のやっていることです。
扱うデータが過去のものだけではなかったり、予測するものが未来のものだけではなかったりするので、これをもう少し一般的な言い方に変えてやると、
__「経験によって賢くなるコンピュータをつくるためのアルゴリズムの研究」__
となります。
これが機械学習の定義です。

#機械学習でできること
では次は機械学習が具体的にどういったことに使えるのかを見てみましょう。

機械学習の目的は「経験によって賢くなるコンピュータを作ること」なので、機械学習を行うにはコンピュータに経験を与える(学習させる)ためのデータが必要になります。天気予報では過去の気象データがそれにあたります。
逆に、十分な量と質のある学習データさえ準備できれば機械学習は何にでも使えるということです。
この性質が、応用分野が非常に広いという機械学習の利点を生み出していると言えるでしょう。

機械学習の応用には、先ほど述べた天気予報を含め以下のようなものがあります。

* 文字認識
* 人物、物体認識
* 検索システム
* スパムフィルタ
* 自己学習するロボット
* 市場予測
* 病気の自動診断 (MRI画像の解析)
* 遺伝子分析
* レコメンデーションシステム (適切な人への適切な広告の提示)
* 自然言語処理 (対話システムや翻訳など)


#機械学習のすごいところ
機械学習の最大の利点は、従来のアルゴリズムではうまく扱えない、しかし人間が処理するにはあまりにも多すぎるデータを、コンピュータの圧倒的な計算速度を活用して高速に処理できることです。
最近話題になっているコンピュータ将棋は、機械学習の強みをうまく活かしている好例だといえます。

ハードウエアの進化はもちろんですが、機械学習のアルゴリズムが高速になれば、当然もっと多くのデータを処理できるようになります。また、アルゴリズムの精度が向上すれば、少ないデータでより良い予測ができるようになります。

例えばGoogleの[自動運転](https://www.youtube.com/watch?v=CqSDWoAhvLU)。
この車は、車上のカメラを使って周囲の物体を認識し、車をどう制御すればいいかを判断しています。
車を自動運転させるには、さまざまな種類の物体を高速かつ高精度に検出、認識する必要があります。
この自動運転は機械学習のアルゴリズムが進化したからこそ実現できたことなのです。

#まとめ
機械学習のアルゴリズムの性能は日々向上し続けてしています。 
アルゴリズムがより軽量に、かつ高精度になれば、機械学習はさらに身近なもの、より多くのものに応用できるはずです。
機械学習がより身近なものとなれば、私たちの生活はより便利で、楽しいものとなるでしょう。
Ruby on Rails v4.1.2 【DB】

厳密にはonetomanyの関係ではないですが、私の故郷にはお菓子屋さんが１つしかなかたのでｗ
#models
##多対１、１対多
|model1|model2|
|:----:|:-----|
|お菓子屋さん|お菓子.チョコレート
||お菓子.ポテチ
||お菓子.クッキー

```
$ ./bin/rails generate model お菓子屋さん name:string, address:string
$ ./bin/rake db:migrate
```


```rb:okashiyasan.rb
class Okashiyasan < ActiveRecord::Base
  #１対多
  has_many :お菓子
end
```

```rb:okashi.rb
class Okashi < ActiveRecord::Base
  #多対１
  belongs_to :お菓子屋さん
end
```


##多対多
|model1|model2|
|:----:|:-----|
|お菓子.チョコレート|商品成分.エネルギー
|お菓子.チョコレート|商品成分.炭水化物
|お菓子.チョコレート|商品成分.脂質
|お菓子.ポテチ|商品成分.脂質
|お菓子.クッキー|商品成分.脂質

```
./bin/rails generate model お菓子の商品成分 お菓子:references 商品成分:references
./bin/rake db:migrate
```

```rb:okashi.rb
class Okashi < ActiveRecord::Base
  has_many :お菓子の商品成分
  has_many :商品成分, through: :お菓子の商品成分
end
```

```rb:shouhinseibun.rb
class Shouhinseibun < ActiveRecord::Base
  has_many :お菓子の商品成分
  has_many :お菓子, through: :お菓子の商品成分
end
```

##コールバックポイント

|name|create|update|destroy|
|:--:|:----:|:----:|:-----:|
|{before, after}_validation|o|o|x
|{before, after}_create|o|x|x
|{before, after}_save|o|o|x
|{before, after}_update|x|o|x
|{before, after}_destroy|x|x|o

他にもありますが、ここらへんはよく使います

##実際に作成

```
$ rails c
```
コンソールを立ち上げます

```
> Okashiyasan.new
> Okashiyasan.create(name: "近所のお菓子屋", address: "tokyo")
```
こちらでレコードを１つ作成します

```
> Okashiyasan.find(1)
```
autoincrementsのため、先ほど作成されたレコードのunique idは1になっているはずなので、find(1)でひっぱってこれます

#migrate

##schema.rbを編集して反映する場合

```
rake db:reset
rake db:migrate
```
cuiで使えるgitブラウザ


最近ターミナル＋vimでコードを書くことになったが、gitだけGUIだと切り替えが面倒だったがtigというcuiで使えるgitブラウザを使うことでcui上でも楽にgitの細かい操作ができて便利だったので使い方に関してまとめ


##インストール
macであればhomebrewを使うことで簡単にインストールすることが可能

```ターミナル
brew install tig
```


##使い方

git管理されているディレクトリ以下で

```ターミナル
tig
```
とするだけ

![スクリーンショット 2014-06-29 6.18.55.png](https://qiita-image-store.s3.amazonaws.com/0/17175/0aa4b51a-1c49-a5b2-05f8-5f05d1a7aa1f.png "スクリーンショット 2014-06-29 6.18.55.png")
このような画面が表示される
この画面ではgitのコミットログを確認できる
ターミナルでgitのログをtree表示できる画面だと思っておけばよさそう

一度tigを立ち上げてしまえば各画面にはショートカットで切り替えができる

|コマンド|内容|
|:-----------|------------:|:------------:|
|s|git status|
|l|git log|
|m|tigで立ち上がる画面|
|y|git stash|
|h|tig help|


（自分で今のところ使うのがこの辺りなので増えてきたら修正）

tigを立ち上げる時に

```ターミナル
tig status
```
とすることで一気にstatus確認の表示にすることもできる。
(ちなみにカーソルの移動はvimと同じ操作方法)

##tig statusの使い方
logとかはまあ見るだけで終わったりするがtig statusでは

* インデックスへの登録（git add）
* インデックスへの登録解除(unstage)
* 変更の取り消し(git checkout)

を行うことができる

tig statusを立ち上げると
![kobito.1403992110.086956.png](https://qiita-image-store.s3.amazonaws.com/0/17175/5aadebab-9ddc-e10e-9fb0-5aad40479734.png "kobito.1403992110.086956.png")

見たまんまで
ステージに挙げられているファイルは
**Changes to be committed**
管理下のファイルでステージに上げられていないファイルは
**Changed but not updated**
管理下に無いファイルは
**Untracked files**
以下に表示される

カーソルを移動してファイルを選択して **enter** を入力するとで差分の確認が行える。

![kobito.1403992784.141182.png](https://qiita-image-store.s3.amazonaws.com/0/17175/489d2b43-8665-4fd2-eb19-9a629527f943.png "kobito.1403992784.141182.png")


### git add
tig statusの画面でファイルを選択して **u** を入力することで
ステージに上ってないファイルは **git add** が行われ
既にステージに上がっているファイルはステージから降ろされる

差分表示中にカーソルを移動させて変更箇所にカーソルを合わせて **u** を入力しても
差分単位でステージに上げたりすることができる。

### 変更の取り消し
管理下のファイルであれば変更の取り消しが行える。
tig statusの画面でファイルを選択して **!** を入力することで
選択したファイルの変更を取り消すことができる。

差分表示中にカーソルを移動させて変更箇所にカーソルを合わせて **!** を入力しても
差分単位で変更の取り消しを行うことができる。
NSDateFormatter / 日付フォーマットについて

# Unicode Technical Standard #35 Unicode Locale Data Markup Language

日付表記の RFC 3339 とか ISO 8601 とかなんかあれ系のやつ。
それぞれの規格の区別は正直よくわからないが、NSDateFormatter は Unicode の規格に対応している。
> https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/DataFormatting/Articles/dfDateFormatting10_4.html#//apple_ref/doc/uid/TP40002369-SW13

## 表記

### 年月日
`yyyy-MM-dd`
*例：2014-06-29*

### 年月日T時分秒および時間帯
`yyyy-MM-ddTHH:mm:ssZ`
*例：2014-06-29T18:20:46+0900*

### 二桁の年
`yy`
*例：14*

### 大文字の YYYY

その日が木曜日〜土曜日なら、前年の週とみなす。
年が明けたのに前年の表記になる可能性があるので、日本の文化的には小文字を使った方が良いかもしれない。

### ミリ秒

`S`
*例：12.678 → ss.SSS*

### +09:00 のようなコロン区切りの時間帯表記

ISO8601 の表記法で、WebAPI でよく使われる。これは `ZZZZZ` で対応できるらしい。
http://www.unicode.org/reports/tr35/tr35-25.html#Date_Format_Patterns

### 和暦

`G` で元号表示できる。
*例：`GGyy/MM/dd HH:mm:ss` → 平成28年/00/00 23:59:59*


```swift
let dateFormatter = NSDateFormatter()
dateFormatter.locale = NSLocale.currentLocale()

if NSCalendar.currentCalendar().calendarIdentifier == NSCalendarIdentifierJapanese {
    // 元号表示
    dateFormatter.dateFormat = "GGyy/MM/dd HH:mm:ss"
}
else {
    // 西暦表示
    dateFormatter.dateFormat = "yyyy/MM/dd HH:mm:ss"
}
```

## 例

```
[rfc3339DateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ss'Z'"];
```
```
NSString *dateString = @"Sun, 29 Jun 2014 06:34:30 +0900";
[formatter setDateFormat:@"EEE, dd MMM yyyy HH:mm:ss ZZZZ"];
```

`''`は無くてもたぶん動く。

## 参考文献

https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/DataFormatting/Articles/dfDateFormatting10_4.html#//apple_ref/doc/uid/TP40002369-SW1
http://www.kanzaki.com/docs/html/dtf.html#w3cdtf
http://www.unicode.org/reports/tr35/
http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns

### Date Format を即席で検証するときに便利

http://nsdateformatter.com
※ZZZZZ には対応していない

### W3C 表記に対応する場合など
[iOS][Mac] ISO 8601 相当の日付文字列を NSDateFormatter で変換する
http://cocoadays.blogspot.jp/2011/03/iosmac-iso-8601-nsdateformatter.html

### iOS で実装する場合やフォーマットの指定方法など
NSDateFormatter - 文字列と日付の変換
http://d.hatena.ne.jp/nakamura001/20100525/1274802305

### 日付形式の違い
http://d.hatena.ne.jp/katona/20080507/p2

> ISO8601/RFC3339/W3CDTF: 2001-02-03T04:05:06+09:00
> RFC2822: Sat, 03 Feb 2001 04:05:06 +0900
> ctime: Sat Feb 03 04:05:06 JST 2001
Javascriptを使うのをやめろ：Railsの時代遅れ云々についての結論

**結論: Javascriptの乱用をやめるのが一番。**

はじめに書いておきますがしょうもない話です。
結論、開発者としてはどのような方向性でやるべきか、を書いています。
JS多い時代でのフレームワークの根本的な問題云々のことは書いてません。

さて、現状、モバイルにおいて、Javascriptでまともに動くものを作ることは難しいです。
Twitterから引き抜いた超優秀なWebエンジニアを多数抱えるMediumですら、未だにモバイルで多数のバグを抱えています。
超優秀なエンジニアを世界一抱えているであろうGoogleのGmailですら、モバイル版のWebはすぐクラッシュします。また、自前スクロールに致命的なバグも抱えています。

正確には「UIが不審な挙動をする」ですが、エンドユーザにとっては同じことで、「バグ」です。
サーバサイドで起こるバグと同じ程度、いやそれ以上に、サービスに影響を与えます。

####UIのバグ

UIのバグは計測が難しいこともあり、あまり意識されることがありません。
サーバサイドの例外をキャッチして計測している人は多いですが、フロントエンドの例外をキャッチしている人は珍しい部類に入ると思います。
現在ではユーザの報告に頼るところが大きいでしょう。

また、UIの応答性についても言及する必要があります。
つまり、ユーザが操作したと感じた瞬間から、何ミリ秒以内に操作が完了するのか。
これも、サーバサイドのパフォーマンスをNew Relic等で計測している人は多いですが、「操作」に関しての応答性を取っている人を、私は見たことがありません。
遅いUIも、ユーザには「UIの挙動不審」であり、バグと同じです。

フロントエンドにJavascriptを乱用することは、常にこれらのデメリットを伴います。
また、冒頭で述べた通り、現状モバイル上でまともに動作するリッチなUIをJavascriptで「ちゃんと」実現することは、非常に難しい。
時価総額1兆円をゆうに超えるTwitterですら、そのモバイルWebはすぐにクラッシュし、すぐにスクロールがおかしくなるゴミです。

クラッシュは最悪のバグです。
iOSのブラウザはクラッシュしたらクッキーが吹き飛び、再度ログインをさせられるので更に業が深い。
Javascriptたくさんは、常にこの最悪のバグとの付き合いであることを意識したほうがいいです。

####なので

結論、現状Javascriptをたくさん書くことは、費用対効果が見合いづらい。

ほとんどのJS Heavyなサイトは、JSで実現される「操作感」よりも、JSのバグが産み出すユーザ離脱や、JSで産み出されるUI遅延のほうが大きいのが現実です。
JSで速度を向上させることを狙っているサイトでも、初期ロードが長かったり、JSのパース自体で端末の操作に遅延が生じ、結果逆に遅くなっていることも多いです。

そして、メンテナンスの問題があります。
現状のエコシステムでは、Javascriptコードの見通しが非常に悪い。
「[RailsでJS辛い問題](http://qiita.com/kaiinui@github/items/2781219340d427543d08)」です。

「避けることが出来る面倒は避ける」ことは常に正しいです。
有限のリソースを使って戦う必要はありません。

Javascriptを書かないにこしたことはありません。
特に、ロジックにJavascriptを噛ませるのは泥沼への一歩目だと言ってもよいです。
ドキュメントもされにくいし、テストもされにくい、構造化もされにくいことが相まり、一瞬で泥沼になります。

JavascriptライブラリはUIコンポーネントやTurbolinks, FastClick等十分テストされていて、かつロジックに一切絡まないものを使いましょう。
特にTurbolinksは良いです。ロジックに絡まない唯一のパフォーマンス向上手段といってもよい。

UIコンポーネントに関しては、例えばカレンダーとか標準のUIゴミなのでJSライブラリを使うのは良い判断だと思います。疎結合になるよう上手くRailsと連携しましょう。
自身のUIをJSで書けという話ではないです。

Javascriptは実行環境により実行結果が異なる可能性のあるクソ言語であることを思い出した方がいいです。（言語自体は悪くないです。）
使うべきところは使い、使わなくてもいいところは避ける。
適材適所でいきましょう。
当たり前の話になりましたが、JSが快適に書けすぎる環境が整ってしまったがために乱用してしまいがちになりましたので、定期的に見直すことは必要だという話でした。

####GitHubは

GitHubなどはよく考えていて、Javascriptも多数使っていますが、使わなくて済む部分は使うことを避けています。
リポジトリのStarボタンなどは、POSTを発行するただのリンクです。
ここはつい簡単だからといってJavascriptで書こうとしてしまいがちです。が、GitHubはそれを避けサーバサイドでやっている。
Railsだけで出来ることはRailsでやろうという指針が垣間見えます。
（GitHubがRailsかどうかは知りません。）

GitHubのような巨大なサイトだと、Javascriptの量もとんでもないことになりますので、大変良い判断だと思います。

####まとめ

以上、無駄にJavascriptをたくさん書くことを考え直す必要があるな、と思った次第です。
特にクライアントMVCは泥沼へ百歩入ってると個人的に思います。
書くまではいい。書くまでは。その後は知らん。

####APIに関する問題

これは今後RailsのエコシステムにおいてもJSON Schema等で解決されていくでしょうし、絶賛contribute募集中なので突っ込める方は突っ込みましょう。
成熟されるまでは、サーバサイドもクライアントサイドも不必要なコードを書かずに済ませる決定的な手段はありません。

サーバサイドは、Concernで上手くコード重複をかわす等、上手くやりましょう。あまり規約的ではありません。
クライアントサイドは、iOSならRestKitとか使って上手くコードを書かずにやるのがいいでしょう。面倒くさくなるのでRESTから逸脱するのは避けたほうがいいです。
または、Parse.comのiOSクライアントみたいな、自由度高めでイイ感じにRESTリクエストを発行するクライアントを書いても良いと思います。

Appが主でParse.comを使うことが出来るなら、使いましょう。外しません。
API開発しながらAPIクライアント書いたりして頑張る苦行は避けたほうがいい。
特にPush通知とかStoreとか独特すぎて死にたくなるの必至なので。

####結論

レールに乗ろう
ksnctf q12 Hypertext Preprocessor

http://ksnctf.sweetduet.info/problem/12
index.phpでなんか動いている。
## やったこと（ネタバレ）
PHP脆弱性あたりで適当にぐぐる。
それっぽい脆弱性としてCVE-2012-1823が見つかるのでさらにぐぐる。
ぐぐったら徳丸先生が記事を書いていたのでそれを参考にしてやった。
ksnctf q27 Lives out

http://ksnctf.sweetduet.info/problem/27
プログラムを走らせるとライフゲームが始まる。
## やったこと（ネタバレ）
何も考えずにIDAに入れると64bit版なので動かない。
仕方が無いのでVisual Studioにアタッチさせて、ブレークポイントを仕掛けつつ、ライフゲームの条件分岐の部分を探す。
頑張ったら見つかったので、Stirlingでバイナリパッチを当てて条件分岐を潰して終了。
オプション解析をしてみる

とりあえずなにか作るとなったら基本事項のオプション解析をやってみる

```text
C:\temp\>getopt.exe getopt.exe /n 4 /h /s /w /sw
file : getopt.exe
lines : 4
usage : 1
空 : 1
白 : 1
空白 : ふたりは
```

```csharp
using System;
using System.IO;
using System.Collections.Generic; // Dictionary クラス使用

class MainClass
{
  static int Main(string[] args)
  {
    var opt = new Dictionary<string, string>();

    // 引数解析
    ParseArg(args, opt);
    foreach (var dict in opt)
    {
      Console.WriteLine("{0} : {1}", dict.Key, dict.Value);
    }

    return 0;
  }

  static void ParseArg(string[] args, Dictionary<string, string> opt)
  {
    //foreach (string s in args)
    for(int i=0; i<args.Length; i++)
    {
      switch(args[i])
      {
        case "/f":
          opt["follow"] = "1";
          break;
        case "/h":
          opt["usage"] = "1";
          break;
        case "/n":
          opt["lines"] = args[++i];
          break;
        default:
          if (File.Exists(args[i])) {
            opt["file"] = args[i];
          }
          break;
      }
    }
  }
}
```
view.loadMoreTask 改良版

2個前の記事で作った loadMoreTask に不具合が見つかったので改善してみた。

修正前

```coffeescript
# views/loadMore.coffee
angular.module("app").factory "view.loadMoreTask", ->
  return (startPage, loader) ->
    self =
      pageNo: startPage
      items: []
      isComplete: false
      loadMore: ->
        loader(self.pageNo++).then (response) ->
          Array.prototype.push.apply(self.items, response.items)
          self.isComplete = response.isComplete
    return self
```

この実装では、 loader の response が page = 1 の時だけ異様に遅く、先に page = 2 の方が返ってきてしまった場合、items の中身がてれこになってしまう。

改良版はこちら

```coffeescript
angular.module("amo.view", []).factory "amo.view.loadMoreTask", ["$q", ($q) ->
  return (startPage, loader) ->
    _current = _start = $q.when startPage
    self =
      items: []
      isComplete: false
      loadMore: ->
        _current = _current.then (page) ->
          loader(page).then (response) ->
            Array.prototype.push.apply self.items, response.items
            self.isComplete = response.isComplete
            return page + 1
      reset: ->
        self.items = []
        self.isComplete = false
        _current = _start
]
```

- `_current` は `promise` であり、`page` を包み込んでいる
- `loadMore` が呼ばれると、まず `_current.then` を使って 現在の `page` を受け取る
- `loader` を使ってその `page` の内容を読み込む
- 結果を元に `self.items`, `self.isComplete` を更新し、`page + 1` を返す
- この時点で、`loader(page).then (response) -> return page + 1` は値 `page + 1` を包み込んだ `promise` である
- この `promise` をさらに `_current.then (page) -> ...` の部分が返している。promise は 2 重に重ねても 1 度だけ重ねたのと同じであるから、結局この部分は `page + 1` を包み込んだ `promise` になる
- 最後に、これをまた `_current` に入れているのだから、`_current` は promise であり、`page + 1` を包み込んでいる
- `loadMore` を実行するたび確実に `page` がインクリメントされ、`then` を使っているおかげで順番がてれこになることもない。
- `reset` を押せば _current がはじめの状態に戻る。loader は同じ `page` に対しては同じ結果を返すようにするべきであり、そのポリシーさえ守れば、この `loadMoreTask` は何度でも実行できる。

いやー `promise` 便利だわ。