OmniAICreator/Qiita-1.07M huggingface dataset:
Railsでメール受信とブラウザー通知


あるシステムから届くメール通知が不親切なので「メールを受信して、DB保存しそれを整形して表示させるサイト」を[Heroku]上で作成してました。その実装の中で、応用のききそうなメール受信とWebサイトのPush通知の方法についてメモしておきます。

### 使ったもの
* [Heroku]
* [Mail2Webhook]
* [Pusher]

# メール連携

[heroku]上にデプロイするので良いのが無いかAddonを探したところ無料プランでもそこそこ使えそうな[Mail2Webhook]に決定。

## 設定

https://devcenter.heroku.com/articles/mail2webhook

1.Addonの追加

> $ heroku addons:add mail2webhook

これだけで受信用メールアドレスが発行される。Configで確認する事も可能。このメールアドレスが長く、小文字Lとか数字１が混在しているので注意（これでハマった）

> $ heroku config:get MAIL2WEBHOOK_EMAIL

2.WebHookURLの設定

以下のコマンドでdashboardを開き、hook用のURLを設定する必要があります。設定されていないとメールが飛んできます。またpostした時にエラーが出ると送信者に診断用情報を含んだエラーメールが返送されます。

> $ heroku addons:open mail2webhook

![スクリーンショット_2014-08-28_12_35_18.jpg](https://qiita-image-store.s3.amazonaws.com/0/14768/1e7d4e8b-0ba8-68a5-57d3-4cf50746f9ac.jpeg "スクリーンショット_2014-08-28_12_35_18.jpg")

この下にRailsとNodeJSのサンプルがあるのでそのまま使えます。

```config/routes.rb
 post 'incoming_emails' => 'incoming_emails#create'
```

```ruby:app/controllers/incoming_emails_controller.rb
require 'mail'
require 'kconv'

class IncomingEmailsController < ApplicationController
  skip_before_filter :verify_authenticity_token, only: :create
  def create
    mail = Mail.new(params[:message])
	# ここに保存＆ブラウザー通知
    render text: "OK"
  end
end
```

## 注意点

mail.bodyを日本語でgrepしようとすると、ASCIIでセットされているためエンコーディングがうまくいかず失敗します。自分のプログラムではkconvを入れ下記のようにして対応しました。

```
	mail.body.to_s.toutf8
```

また、mail.subjectはエンコードはUTF8なのですが、文字列が切れてしまうようです。この辺りは後で検証する予定。

Mail(Ruby)
https://github.com/mikel/mail

※このような部分はローカルでテストできなので辛い...

# ブラウザー通知

単純な通知でよかったのでWebSocketで普通に通知機能を作ろうかとか思ったが、この機会に前から使ってみたかった[Pusher]を使うことにしました。

トップページよりフリーアカウントを作ると、自動的にAppsとしてMainというのが登録され、CodeExampleが表示されている...なんというお手軽モード。

##クライアント側（ブラウザー表示部）

hamlを使っているので以下のように書き換えて投入します。

```haml:application.html.haml
    %script{:src => "http://js.pusher.com/2.2/pusher.min.js", :type => "text/javascript"}
    :javascript
      $(document).ready(function(){
        var pusher = new Pusher(*****);
        var channel = pusher.subscribe('dashboard');
        channel.bind('new_event', function(data) {
          alert(data.message);
        });
      });
```

channnelとeventは好きに設定する（複数ページや機能やユーザーレベル別等）。実際はAlertでなく、デスクトップ通知や自動リロードなどにする方がスマートかと思います。


## サーバー側（システムからのトリガー部）

```config/initializers/pusher.rb
require 'pusher'

Pusher.url = "http://****@api.pusherapp.com/apps/****"
Pusher.logger = Rails.logger
````

ページには記述が無いようなきがしますが、requireするのだから当然Gemも指定しておく必要があります。

```Gemfile
gem 'pusher'
```

>$ bundle install

後は通知したい部分に下記のように書けば[Pusher]にて通知されます。

```
  Pusher['dashboard'].trigger('new_event', {
      message: '通知内容'
    })
```

[Pusher]のダッシュボードからも送信テストができます。

![Pusher__Ssalert_—_Debug_Console.jpg](https://qiita-image-store.s3.amazonaws.com/0/14768/9d6e30cd-4852-d266-f089-991d09ae2042.jpeg "Pusher__Ssalert_—_Debug_Console.jpg")

##ぶつぶつ

[mail2webhook]が便利だったので、送信先フィルターのサーバー側実装とか、ユーザー名振り分けのような仕組みを含めて自分で作ってみるのも楽しそうな気がしています。

[heroku]:http://heroku.com
[Mail2Webhook]:https://www.mail2webhook.com
[Pusher]:http://pusher.com
express-generator を使う

express-generator で生成したものには Express 4 の流儀っぽいものが含まれているので一回見てみるとよいかもしれない。

インストール
------------

みんなグローバルにつっこんでるけどローカルですむものはローカルにインストールしようよ。

```sh
cd /path/to/project
mkdir generator
cd generator
npm install express-generator
```

使い捨てる
----------

ひながた生成。

```sh
./node_modules/.bin/express ../app
```

必要なくなったら即パージ。

```sh
cd ..
rm -rf generator
```

アプリ起動
----------

かんたん。

```sh
cd app
npm install
npm start
```

みていくポイント
----------------

### ポートをいじりたい場合

<kbd>npm start</kbd> で起動される ./bin/www で指定されている。これはそれっぽく見えないけど JavaScript で書かれている。

### アプリの共通設定を変更したい場合

./app.js が該当する。

うえのほうにアプリ共通で利用する middleware の設定が、なかほどに共通のエラー処理が、したのほうに development 環境や production 環境の設定がある。

### 実処理

./app.js の <code>app.use('/', routes);</code> というところ。これが実処理を設定しているところになる。中身は ./routes/index.js に express.Router を使って書かれてる。

express.Router は Express 4 からの新機能で、リクエスト URL と実処理をうまいこと分離したもの。説明については以下が詳しい。

http://scotch.io/tutorials/javascript/learn-to-use-the-new-router-in-expressjs-4
パスワードを忘れたときの操作（Qiita編）

パスワードを忘れたときの操作について、Qiitaではどのような動きをするのかについてメモします。

* QiitaではGitHubアカウントかTwitterアカウントでログインする人が多そう
* そのためか、パスワードの再設定の操作はシンプルにできているように感じた
* 新パスワードを入力した後ログインした状態にはならない
* パスワード再設定ページの期限は10分以内

# Qiitaにてパスワードを忘れたときの操作

## ログイン画面にて

パスワードを忘れたユーザーのために、ログインボタンの右に「パスワードを忘れた場合」というリンクがある

![Qiitaのログイン画面](https://qiita-image-store.s3.amazonaws.com/0/43593/3817b448-b964-6810-d84f-e29c07525c49.png)


## パスワード再設定メールを送る画面

「パスワードを忘れた場合」というリンクをクリックすると、パスワード再設定メールを送るためのフォームが表示される。

![パスワード再設定 - Qiita](https://qiita-image-store.s3.amazonaws.com/0/43593/8bc66621-1ea8-f738-232a-37f04adcd213.png)

メールアドレスを入力して「送信」をクリックすると「◯◯へパスワード再設定メールを送信しました。しばらくしてもメールが届かない場合は、スパムフィルタをご確認ください」と画面が表示される。

![メール送信完了 - Qiita](https://qiita-image-store.s3.amazonaws.com/0/43593/e6e26fea-16b2-3fb3-1e61-d9dcbb2e5ee8.png)

## 送信されたメールの文面

10分以内、というのは、初めて見た気がする。1,2時間とか、24時間とかはよく見る。すぐメールを見れないようなユーザーはQiitaにはいないということ。

```
件名：Qiitaのパスワード設定

こんにちは、◯◯◯さん。

パスワードの設定は以下URLのページより、10分以内に行なってください。

http://qiita.com/sessions/reset_password/◯◯◯/なんとかなんとか

—
Qiita
```

## パスワードの再設定

メール内のリンクをクリックすると、パスワードの再設定画面が表示される。

![パスワード再設定 - Qiita](https://qiita-image-store.s3.amazonaws.com/0/43593/d2d6de0d-af6b-9b01-63c1-6476a778120e.png)

新しいパスワードを入力して「パスワードの変更」をクリックすると、ログイン画面へ遷移し「Updated successfully」とパスワードが変更されたことを明示する。ユーザー名は既に入った状態だが、ログインされた状態にはなっていない。再度新しいパスワードを入力する必要がある。

![ログイン - Qiita](https://qiita-image-store.s3.amazonaws.com/0/43593/7cc37b41-1249-1eea-a634-a154010a4110.png)
Node.js サーバーを 80 番ポートで動かす

実際はリバースプロキシかましたりして Node.js が動いてるサーバーが外に直接見えることはないんだろうけども。


well known port を使うにはスーパーユーザー権限が必要
----------------------------------------------------

ポート 80 はいわゆる well known port なので Linux ではスーパーユーザー権限が必要になる。他の OS は知らん。

なのでそもそも起動に sudo が必要になったりするわけだけどそのままだとサーバープロセスが root で動いてしまって不穏極まりない。

これをなんとかするためにサーバー起動したあとにプロセスの所有権を一般ユーザーに渡す。具体的には以下のようなコード。

```js:hello.js
var http = require('http');
var PORT = 80;
var HOSTNAME = '127.0.0.1';
var USER = 'nodejs';

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(PORT, HOSTNAME, function () {
    console.log('change user');
    process.setuid(USER);
});

console.log('Server running at http://' + HOSTNAME + ':' + PORT + '/');
```

<kbd>sudo node hello.js</kbd> して起動したあとに <kbd>ps aux | grep node | grep -v grep</kbd> してみるとユーザーが nodejs になっている。


設定ファイルを使おう
--------------------

実際はユーザーやポートを環境にあわせて変えたいだろうから設定ファイルとして外出しするのが楽。そんなときは node-config が使える。

https://github.com/lorenwest/node-config

前準備として <kbd>npm install config</kbd> してから config/default.json に以下のようなファイルを用意しておく。

```json:config/default.json
{
    "user": "vagrant",
    "port": 80
}
```

で、 node で以下を起動する。

```js:well-known-port.js
var WELL_KNOWN_PORT = 1024;

var config = require('config');
var port = config.port || 80;
var user = config.user || 'nodejs';

var os = require('os');
var hostname = os.hostname() || '127.0.0.1';

var http = require('http');

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(port, hostname, function () {
    if (port < WELL_KNOWN_PORT) {
        console.log('Attempting setuid to user "' + user + '"...');
        try {
            process.setuid(user);
            console.log('Succeeded to setuid');
        } catch (err) {
            console.log('Failed to setuid');
            process.exit(1);
        }
    }
});

console.log('Server running at http://' + hostname + ':' + port + '/');
```

何番を指定されるかわからないので well known port のチェックをしたり、怠惰を貫くためにホスト名を os.hostname を使って引っ張ってきてたりしてるけど、本質は変わってない。
MacやLinuxのTerminalは、Crtl + l でクリアできるよって話

Terminalが文字でわわわーっと埋まっちゃって、うざくなった時は、

```clear``` コマンドで画面をクリアできると思うんだけど、わざわざそんなことしなくても、
```Ctrl + l```でクリアできるよって話。

MacやLinuxにかぎらず大抵の環境でできると思うよ。

~~あ、Windowsは知らん。~~

Windowsでもできるらしい！（コメント欄より）  
tomstyle さんから指摘を頂きました。ありがとうございます！

すてきな記事をコメント欄に頂いたのでシェアします！[コマンドラインショートカット](http://qiita.com/s-age/items/0edc05f7aa94ea5e9d2d)
@s-ageさんありがとうございます！！


ღゝ◡╹)ノ♡ Have a nice day!
シーケンスと写像

Python を知る上で、たぶん重要な概念だと思ったので
記述して共有したいと思います＾＾
built-in オブジェクトに関する説明です。

* シーケンス
* 写像


という考え方があります。

シーケンスは、文字通り連番を表します。
写像は、私なりの言葉で説明すると「写真のような」、
もうちょっと言うと、切り離すことのできない(切り離すと意味のなくなってしまう)ものを指しています。

Pythonの文字列やリストは、シーケンスです。

つまり、以下のようなことができます。

文字列
【結果】
print u'まくらのそうし'[2:4]
らの

ですが、以下のような使い方はできません。
×
str = 'testing'
str[0] = 'a'
不変性のオブジェクトだからです。

リスト
【結果】
print [1, 2, 3, 4, 5, 6][5]
6

連番なので、シーケンスでスライスなどができます。
こちらは、可変性のオブジェクトなので、以下の操作が可能です。
array = [1, 2, 3, 4, 5, 6]
array[0] = 8
print array
[8, 2, 3, 4, 5, 6]

対して、
Pythonの辞書型は写像です。

key-value になっており、Perlなどで言うハッシュ、
PHPの連想配列にあたるのかと思います。

heights = {"john":182, "mike":173, "kevinn":190, "George":181, "Randy":184}
print heights["Randy"]
184

このような使い方ができます。

ですが、シーケンシャルにとりだすことはできません。
×
print heights["john":"kevinn"]

ですが、可変性なので要素の変更や追加ができます。
heights["mike"] = 175 # 2cm 伸びた！


今日はこのへんで＾＾
(個人メモ) CoffeeScript と Haml でどう書けばいいか分からない時


それぞれ JavaScript、HTML から変換してみて、フムフムする。

### CoffeeScript へしてくれるサービス

- http://js2coffee.org/

### Haml へ変換してくれるサービス

- http://html2haml.heroku.com/
Rails+Omniauth-openid+Nginx+SSL環境で認証できない時の対処法

ominiauth-yahoojpや、omniauth-facebookで、
**https**で通信しているのに、**redirect_uri**に「**:80**」が追加されてしまって、**認証が完了できない**場合は、
**nginxの設定ファイル**に下記を追加する

```nginx:myapp.conf
proxy_set_header X-Forwarded-Port 443;
```

**参考**
http://tech.riywo.com/blog/2013/08/24/omniauth-openid-with-pow-and-nginx-ssl-termination/
gitでさっきまでいたブランチに戻る

`git checkout -`で切り替え前のブランチに戻るみたい。

```console
$ git checkout AAA
Switched to branch 'AAA'
$ git checkout BBB
Switched to branch 'BBB'
$ git checkout -
Switched to branch 'AAA'
```

ディレクトリ移動も`cd -`で直前の場所に戻れるけど、同じ感じ？

ドキュメントにも書いてあった。

* [Git - git-checkout Documentation](http://git-scm.com/docs/git-checkout)

> ### \<branch\>
> 
> …
>
> As a special case, the `"@{-N}"` syntax for the N-th last branch/commit checks out branches (instead of detaching). You may also specify `-` which is synonymous with `"@{-1}"`.
MacOSXでstraceが欲しいけどdtrace意味わからん→dtruss使おう

Linux環境で`strace`を使ったことがあるとMacOSXでも同じことがしたくなりますよね。

とはいえ、MacOSXだと`dtrace`コマンドってのがあるらしいけど、オプション指定も複雑怪奇で意味わかんない、システムコールだけ気軽に見たいって人も多いのではないでしょうか。

そんなときは`dtruss`コマンドを使いましょう。このコマンドは`dtrace`と同じ仕組みでシステムコールだけ見せてくれます。

`strace`と違って、自分がownerのプロセスであってもroot権限が必要なことに注意してください。

```
$ sudo dtruss -p 452
Password:
（以下システムコールの羅列）
```

manpageを見ると`truss`（SysV系のコマンドなんすかね…？）のDTrace版だよ、なんてことが書いてあったりして、オプションは`strace`と違ったりもします。とはいえ`dtrace`コマンドを調べながら使うよりは断然楽なのでオススメです。

# dtruss経由でコマンド起動したい

`dtruss`はroot権限を要求するのですが、`sudo dtruss <command>`などとすると挙動が変わって不便だったりします。次のようにすればコマンド自体は元のユーザー権限で動かしつつdtrussすることが可能です。

```
$ sudo dtruss -f sudo -u $(id -u -n) <command>
```
PHPでcurlを使ってHTTPSにアクセスしてエラー出たときの回避策

OAuth2.0認証を利用して、Instagramでアプリ認証を行なう過程で
curl_exec()実行したら、bool(false)が返ってきた。
これはHTTPSにアクセスするときに起きる。
カールは、サーバのHTTPS証明書を信頼するように設定されていないので、"下記一行を追加"のコードを追加して対策。

```
$curl = curl_init();

curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($params));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
//下記一行を追加
curl_setopt($curl,CURLOPT_SSL_VERIFYPEER, false);

$res = curl_exec($curl);
curl_close($curl);
var_dump($res);
exit;
```
GO-MEMO:Golangで文字列の行分割


Qiita初投稿です。
今現在でGolang歴は約半年といったところでしょうか…。
最初は簡単なところから徐々にレベルの高いエントリが書けるように慣ればいいなと思っています。

今回は複数行の文字列を行で分割して文字列配列にしたいときのメモです。(string ===> []string)
本当はファイルや標準入力を読むときに分割して読み込む方がスマートなんですが、大量のデータでもない場合ならば一気に読み込んでから分割してもいいのかも思ったので…。


```Golang:main.go
package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"regexp"
)

func main() {
	var bytes []byte
	var err error

	if bytes, err = ioutil.ReadAll(os.Stdin); err != nil {
		log.Fatalln(err)
	}

	for i, v := range regexp.MustCompile("\r\n|\n\r|\n|\r").Split(string(bytes), -1) {
		fmt.Println(i+1, ":", v)
	}
}
```

初投稿なので、何かあればご指摘していただけると幸いです。
Vagrantfileでeachを使ってVMを量産する

Vagrant 環境で複数のVMが必要なとき、自分はこれまで Vagrantfile に config.vm.define ブロックを VM の台数分記述していました。ところが Vagrantfile 内で each を使ってループを記述することができるそうです。試してみました。

```ruby:host100からhost110まで作る
VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  (100..110).each do |i|
    config.vm.define "host#{i}" do |host|
      host.vm.hostname = "host#{i}"
      host.vm.network :private_network, ip: "192.168.0.#{i}"
      host.vm.network :forwarded_port, guest: 22, host: i*100+22, id: "ssh"
    end
  end
end
```

おおぉ、こりゃ楽チン。

### 参考
  * [Tips & Tricks - Vagrantfile - Vagrant Documentation] (https://docs.vagrantup.com/v2/vagrantfile/tips.html)
クロージャーで再帰する、ただし use 禁止

```php:1から100の整数を出力する
<?php
call_user_func(function($n){
    --$n && call_user_func(debug_backtrace()[1]['args'][0], $n);
    echo $n + 1 . PHP_EOL;
}, 100);
```

## 解説

`call_user_func` で呼べば `debug_backtrace()[1]['args'][0]` でクロージャーのインスタンスがとれます。

`$f()` のような呼び方だとダメです（なので実用性は無い）。
cabal updateが無限ループしていた

Haskell Platformを上書きアップデートしたつもりがcabalコマンドが返ってこないという謎の状態になりました。バージョン間の相性的な問題だったのかもしれませんが、同じ状態になった人の助けになればと考えて記録しておきます。

ちなみに環境はMacOSX 10.9です。

## cabalコマンドが返ってこない

cabalコマンドを打っても何も出力されず、CPUファンがブンブン回るようになりました。いつからこうなっていたかはわかりませんが、Haskell Platformを2014.2.0.0に上書きアップデートしたタイミングで発生したような気もします。


原因は、/Library/Haskell/bin/cabal.realがcabal.wrapへのシンボリックリンクになっていて、cabal.wrapからcabal.realを呼び出そうとして無限ループしてました。

```
$ ls -la /Library/Haskell/bin/
total 10112
drwxr-xr-x 11 root wheel     374  8 28 01:20 .
drwxr-xr-x  8 root wheel     272  7 28 14:13 ..
-rwxr-xr-x  1 root wheel 2412452  7 28 14:13 HsColour
-rwxr-xr-x  1 root wheel    9997  7 28 14:13 activate-hs
-rwxr-xr-x  1 root wheel 3634968  7 28 14:02 alex
lrwxr-xr-x  1 root wheel      10  8 28 01:20 cabal -> cabal.wrap
lrwxr-xr-x  1 root wheel      10  8 28 01:18 cabal.real -> cabal.wrap
-rwxr-xr-x  1 root wheel    6906  7 28 14:13 cabal.wrap
-rwxr-xr-x  1 root wheel    1184  7 28 14:13 ghc-clang-wrapper
-rwxr-xr-x  1 root wheel 2690020  7 28 14:13 happy
-rwxr-xr-x  1 root wheel 1577860  7 28 14:14 uninstall-hs
```

## アンインストールしてインストールした

手順として合っているかわかりませんが、下記のように再インストールしたら直りました。

```
$ sudo /Library/Haskell/bin/uninstall-hs thru 7.8.3 --remove
$ sudo rm -rf /Library/Haskell
```

としてからHaskell Platform 2014.2.0.0のpkgを使って再インストール。
Lightboxでタイトルにリンクをつけたいときの変更箇所


=============================================


モーダル・ダイアログを使って大きな画像を表示するのによく使われてる[Lightbox](https://github.com/lokesh/lightbox2)ですが、そのままだと写真の下のタイトルにリンクを張って別のページに飛ばすことができません。以下はそれを可能にするためのlightbox.jsの変更箇所です。

lightboxのバージョンは2.7.1です。

## lightbox.js

135-140行目：変更前

```JavaScript
      function addToAlbum($link) {
        self.album.push({
          link: $link.attr('href'),
          title: $link.attr('data-title') || $link.attr('title')
        });
      }
```

135-140行目：変更後

```JavaScript
      function addToAlbum($link) {
        self.album.push({
          link: $link.attr('href'),
          hyperref: $link.attr('hyperref'),
          title: $link.attr('data-title') || $link.attr('title')
        });
      }
```

hyperrefという属性を新たに追加しています。HTMLの方ではこの属性にリンク先を設定することになります。


323-332行目：変更前

```JavaScript
      // Enable anchor clicks in the injected caption html.
      // Thanks Nate Wright for the fix. @https://github.com/NateWr
      if (typeof this.album[this.currentImageIndex].title !== 'undefined' && this.album[this.currentImageIndex].title !== "") {
        this.$lightbox.find('.lb-caption')
          .html(this.album[this.currentImageIndex].title)
          .fadeIn('fast')
          .find('a').on('click', function(event){
            location.href = $(this).attr('href');
          });
      }
```

323-332行目：変更後

```JavaScript
      // Enable anchor clicks in the injected caption html.
      // Thanks Nate Wright for the fix. @https://github.com/NateWr
      if (typeof this.album[this.currentImageIndex].title !== 'undefined' && this.album[this.currentImageIndex].title !== "") {
        this.$lightbox.find('.lb-caption')
          .html('<a href="'+this.album[this.currentImageIndex].hyperref+'">'+this.album[this.currentImageIndex].title+'</a>')
          .fadeIn('fast')
          .find('a').on('click', function(event){
            location.href = $(this).attr('href');
          });
      }
```

.htmlの部分が変更されています。タイトルを追加する際にa要素で囲むようにしています。

jsファイルの変更箇所は以上です。


## HTMLファイル

HTMLの方では

```HTML
<a class="example-image-link" href="img/demopage/image-3.jpg" hyperref="リンク先のアドレス" data-lightbox="example-set" data-title="Click the right half of the image to move forward."><img class="example-image" src="img/demopage/thumb-3.jpg" alt=""/></a>
```

のようにhyperrefという属性を追加して、その値にリンク先のアドレスを書いてください。


## CSSファイル

また、a要素のスタイルを変更したい場合は、lightbox.cssに

```CSS
.lb-dataContainer > .lb-data > .lb-details > .lb-caption > a {
  text-decoration: none;
  display: block;
  margin-top: 5px;
  color: #ccc;
}

.lb-dataContainer > .lb-data > .lb-details > .lb-caption > a:hover {
  text-decoration: none;
  color: #ac3cbd;
}
```

を追加してください。色やマージン等は適宜調整してください。
Fusion IP-Phoneを複数登録する(1つのGmailアカウントで)

2014年8月27日開催の[第100回記念VoIP & Asterisk Lounge](http://www.denphone.com/voip-asterisk-lounge-jp)に参加してきました。
[IP-Phoone SMARTとは？ | FUSION IP-Phone SMART](http://ip-phone-smart.jp/smart/)

# 1つのGmailアカウントで複数アカウント登録するには

* 複数電話番号の発行をするには別のメールアドレスで登録する必要がある。
  * `fusion@gmail.com`だとしたら、
  * `fusion+1@gmail.com`
  * `fusion+2@gmail.com`
  * というように`+`をつけると登録ができる。

70契約くらいしたい場合は・・・営業に直接電話すると相談に乗ってくれる気がします。

# 複数電話番号発行について

* 1つのクレジットカードで5つまで番号発行が可能。
* 2つ目の電話番号発行から手数料500円(+税)がかかります。
* 月額料金無料。
* 番号は連番で発行されている様子。
  連番が欲しい場合は時間をおかず、他の人が利用してなさそうな時間(深夜？)に連続して登録するか、営業に相談・・・

# 長所

* スマートフォンにSIP登録せずとも、携帯キャリアの電話番号に即時転送できる。
  * 050plusにはない
* 国際電話設定がデフォルトで無効
* 留守番電話転送サービスがある。(着信の即時転送とは併用できません。)

Fusion IP-Phone間の通話は無料！

## ファイアウォールでブロックされる場合

RTPポート番号(UDPのこと)を通信許可しておく必要があります。
スマホのアプリ`SMARTalk`であれば、高度な設定 -> 開始RTPポート、終了RTPポート を通信許可にしておくこと。
ポート数は同時着信数 +1くらいでいいと思う。



# 動作確認

参考: [FUSION IP-Phone SMARTをMacで使う - まめ畑](http://d.conma.me/entry/20120519/1337439045)

[telephone](http://www.tlphn.com/)をAppStoreからインストール。

![スクリーンショット 2014-08-28 9.48.18.png](https://qiita-image-store.s3.amazonaws.com/0/25728/2668cb5b-12fb-9d90-32c0-2ea8d619b3d6.png)

* UserNameはFusion IP-Phoneから発行される数字8桁

![スクリーンショット 2014-08-28 9.48.50.png](https://qiita-image-store.s3.amazonaws.com/0/25728/211c92d5-9707-836f-7ffd-405204708947.png)
nvmを使って、Node.jsをインストールします


# はじめに

こんにちは。インフラエンジニアレベル１の[f_prg](http://twitter.com/f_prg "f_prg")です。
以前[rbenv](http://qiita.com/f_prg/items/00487ee8cad4bdd38f99 "http://qiita.com/f_prg/items/00487ee8cad4bdd38f99")で紹介したような、
Node.js版があったのでインストールしてみました。
nvmとは、Node Version Managerとのことです。

# インストール

## Githubからインストールする
今回は、rbenvに似せるためマニュアルインストールを選びました。

```bash
[15:28:17][f_prg@mba:~]# git clone https://github.com/creationix/nvm.git ~/.nvm
Cloning into '/Users/f_prg/.nvm'...
remote: Counting objects: 1969, done.
remote: Compressing objects: 100% (967/967), done.
remote: Total 1969 (delta 1047), reused 1865 (delta 985)
Receiving objects: 100% (1969/1969), 369.67 KiB | 423.00 KiB/s, done.
Resolving deltas: 100% (1047/1047), done.
Checking connectivity... done.
[15:28:39][f_prg@mba:~]# source .nvm/nvm.sh
```

curlのインストールスクリプトもあるようですね。

## bash_profileに追記しておきます。

```bash
[15:28:59][f_prg@mba:~]# vim .bash_profile
```

```.bash_profile
# nvm
[[ -s ~/.nvm/nvm.sh ]] && . ~/.nvm/nvm.sh
```

## Node.jsをインストールする
対象となるパッケージをリモート先から確認し、インストールします。

```bash
[15:40:35][f_prg@mba:~]# nvm ls-remote
     v0.1.14
     v0.1.15
     v0.1.16
     :
     :
     長いので省略してます
     :
     :
    v0.11.11
    v0.11.12
    v0.11.13
[16:16:26][f_prg@mba:~]# nvm install v0.11.13
######################################################################## 100.0%
Now using node v0.11.13
```

## 使用するパッケージを指定します
使用するバージョンを確認して
デフォルト設定をして
Node.jsのバージョン確認です。

```bash
[16:16:49][f_prg@mba:~]# nvm use v0.11.13
Now using node v0.11.13
[16:17:16][f_prg@mba:~]# nvm alias default v0.11.13
default -> v0.11.13
[16:17:32][f_prg@mba:~]# node -v
v0.11.13
```

最初のインストールで一つしか入れてないので
今v0.11.13使ってるとメッセージがでてますね。

# まとめ
これで、rbenvのようにパッケージを自由に使えそうです。
楽になりそうですね。

# 参考資料・リンク
[https://github.com/creationix/nvm](https://github.com/creationix/nvm "https://github.com/creationix/nvm")
Project Eulerをhaskellで練習していく日記: Problem 33

#問題
分母分子共に２桁の分数を約分する場合、例えば
89/92=8/2
のように分母分子に共通する数(9)を消してしまうと、算数問題としては間違いである。

しかし、分母分子共に２桁かつ分子＜分母となる分数のうち、４つだけこのような間違った約分をしてもたまたま正解になるパターンがある。

それら４つの分数の積を求め、その分母（最も約分された時の分母）の値を求めよ。
#回答
上下に同じ数が現れるパターンを以下の４パターンに分けると、
1. 21/81 のように１の位が同じ場合
2. 21/23 のように１０の位が同じ場合
3. 21/92 のように分子の１０の位と分母の１の位が同じ場合
4. 89/92 のように分子の１の位と分母の１０の位が同じ場合
の４通りがある。
しかし、このうち、1〜3のパターンは数学的に起こりえないことが証明できるので、4の場合に限って計算する。
（この証明は以下のプログラムのコメントにて。）

```hs
import Data.Ratio

-- パターン１があり得ないことの証明
-- (10a+b)/(10c+b)=a/c<1
-- このときa<cであるが、
-- c(10a+b)=a(10c+b)
-- 10ac+bc=10ac+ab
-- bc=ab
-- c=a
-- これはa<cに矛盾する

-- パターン２があり得ないことの証明
-- (10a+b)/(10a+c)=b/c<1
-- このときb<cであるが、
-- 10ac+bc = 10ab+bc
-- ac=ab
-- c=b
-- c=b これはb<cに矛盾する

-- パターン３があり得ないことの証明
-- (10a+b)/(10c+a) = b/c < 1
-- 10ac+bc=10bc+ab
-- 10(ac-bc)+bc-ab=0
-- 10(a-b)c+b(c-a)=0
-- b(c-a)=10(b-a)c>0
-- よって、 b>a
-- したがって、a<=b-1, また、もともとb<cなので、b<=c-1
-- 0=10ac+bc-10bc-ab<=10(b-1)c+bc-10bc-ab=-10c+bc-ab<=-10c+(c-1)c-ab=c^2-11c-ab
-- cの二次式の判別式を考えると、D=(-11)^2-4(-ab)=11^2+4ab<=0
-- となるが、a,b>0なので、D<=0となることはあり得ない。

-- 以上により、(10a+b)/(10b+c)=a/c<1 となるパターンのみから発見すれば良い。

kouho = [a%c| b<-[1..9], c<-[1..9], a<-[1..min (b-1) (c-1)], 
              b/=c, 
              (10*a+b) % (10*b+c) == a % c]

main = do
     print $ product kouho
```

#感想
Haskellの分数機能はすばらしい！！！
Pecoの不便なとこ


複数の要素を選択した場合に順序が指定できない。
例えば複数のファイルを選択して任意の順番に結合したいとかいうときに`ls -1`を渡して複数選択する感じだと、結合結果がファイルのソート順に依存する。

`ls -1`した結果を事前にソートしておけって話かもしれないけど単純なソートだけじゃ解決しない状況もあると思う。

正直に言うと、自分が困ってるのはニコニコの検索結果をpecoに渡してmplayerで再生してて再生順が検索結果に依存するのってところなので、誰か選択した順に要素を渡すように並ぶようにしてください。
クリップボード（GTK）のイメージをファイルに保存する Python スクリプト。

Ctrl+(Alt|Shift)+PrintScreen とかすると画面のスクリーンキャプチャが取れるわけですが、 Ctrl を押しているとスクリーンキャプチャはクリップボード上に保存されます。
(通常は Ctrl を押さずに (Alt|Shift)+PrintScreen とすることでダイアログが出てきてファイルに保存できると思います。)

今回はクリップボード上に保存してしまった画像を Python でファイルに保存します。ちなみにGTK環境がないと実行できません。

```python:clip2img.py
#! /usr/bin/env python
# -*- coding: utf-8 -*-
 
import sys
import gtk
 
 
def save_clipimg(filename):
  clipboard = gtk.clipboard_get()
  image = clipboard.wait_for_image()
 
  if image is not None:
    image.save(filename, "png")
  else:
    print("No image in clipborad.")
 
def main():
  save_clipimg((sys.argv+["clipboard.png"])[1])
 
 
main()
```

[Gist](https://gist.github.com/yanolab/db6f870ec08b58852e2f)

本来はおとなしくペイントソフト使えばいいんですけども。
MKMapViewの現在の方角を取得する


検索してもビックリするぐらい引っかからなかったので投稿してみる。
検索の仕方が悪いのか需要がないのか当たり前なのか…。

```
// 角度の単位はdegree
CLLocationDirection heading_deg = mapView.camera.heading;
```

ちなみに`CLLocationDirection`は`double`をtypedefしたやつ。

```CoreLocation/CLLocation.h
typedef double CLLocationDirection;
```
Chrome37で文字が表示されない件の対策

Yahooトップが文字表示されない・・・

![ng.png](https://qiita-image-store.s3.amazonaws.com/0/25728/0db99238-81ca-c441-128c-6fad8796fd9a.png)

* chrome://flags/ を開き、DirectWriteを有効にする

![スクリーンショット 2014-08-28 7.44.25.png](https://qiita-image-store.s3.amazonaws.com/0/25728/5e0b6550-6b8b-6400-2d17-fed7d6b1d63d.png)


ってさんざん既出のようですね
Ubuntu14.04 で外付けのマウスが検出された時はタッチパッドを無効にする方法

以下の udev ルールを追加する。
username のところは適宜置き換えること。

/etc/udev/rules.d/01-touchpad.rules

SUBSYSTEM=="input", KERNEL=="mouse[0-9]*", ACTION=="add", ENV{DISPLAY}=":0", ENV{XAUTHORITY}="/home/username/.Xauthority", RUN+="/usr/bin/synclient TouchpadOff=1"
SUBSYSTEM=="input", KERNEL=="mouse[0-9]*", ACTION=="remove", ENV{DISPLAY}=":0", ENV{XAUTHORITY}="/home/username/.Xauthority", RUN+="/usr/bin/synclient TouchpadOff=0"

[source](https://wiki.archlinux.org/index.php/Touchpad_Synaptics_(%E6%97%A5%E6%9C%AC%E8%AA%9E)#.E5.A4.96.E4.BB.98.E3.81.91.E3.81.AE.E3.83.9E.E3.82.A6.E3.82.B9.E3.81.8C.E6.A4.9C.E5.87.BA.E3.81.95.E3.82.8C.E3.81.9F.E6.99.82.E3.81.AF.E3.82.BF.E3.83.83.E3.83.81.E3.83.91.E3.83.83.E3.83.89.E3.82.92.E7.84.A1.E5.8A.B9.E3.81.AB.E3.81.99.E3.82.8B)
OSXでAtom Shellでネイティブモジュール動かす

# 背景

NodObjCが利用しているネイティブモジュールのnode-ffiがNAN化され、
nodeの0.11系でも動くようになり、Atom Shellでも動かせそうな状況になったので試した。

# 64ビットでうごかす？

[説明のページ](https://github.com/atom/atom-shell/blob/master/docs/tutorial/use-native-node-modules.md)だと32ビットなんだがうまくいかない。
以下ようにアーキテクチャの指定をx64指定したらうまく行ったので、最近はAtom ShellはOSXでは完全に64ビットで動いているのかも。

```bash
nodebrew use 0.10
npm install NodObjC
nodebrew use 0.11
```
node-ffiをNAN化した版をビルドしたもに差し替え、以下を実行

```
HOME=~/.atom-shell-gyp node-gyp rebuild --target=0.11.13 --arch=x64 --dist-url=https://gh-contractor-zcbenz.s3.amazonaws.com/atom-shell/dist
```

一旦0.10系でNodObjCをnpmでインストールして、バイナリを作り直している。

# まとめ

週末時間作って、ブログの方に、もう少し丁寧な記事を書きたい。
とにかく、node-ffiがNAN化されたので、Atom ShellからCocoa APIを叩けるようになった。

<iframe allowfullscreen="" frameborder="0" height="344" src="//www.youtube.com/embed/oRp-AwIA8-s" width="459"></iframe>

# Link

- [Atom Shell](https://github.com/atom/atom-shell)
- [nodebrew](https://github.com/hokaccha/nodebrew)


# 関連記事

- [Atom ShellでCocoa APIが叩けるようになった](http://kjunichi.cocolog-nifty.com/misc/2014/08/atom-shellcocoa.html)
windowsにeasy_installとpipをインストールする

1. https://bootstrap.pypa.io/ez_setup.py をダウンロード、実行
1. `C:\Python27\Scripts\` に easy_install.exe が生成される。
1. PATHに`C:\Python27\Scripts\`を追加
1. `easy_install pip`でpipがインストールされる。
MaxMindが提供しているGeoLite2をScalaから利用してみる


http://dev.maxmind.com/geoip/geoip2/downloadable/

GeoLite2のライセンスはCC BY-SA 3.0。

Java向けのライブラリを使う。
https://github.com/maxmind/GeoIP2-java

Scala向けの薄いラッパーの https://github.com/Sanoma-CDA/maxmind-geoip2-scala というのも見つけたけど、これくらいならJava APIを叩いてもいいかなと思った。

```scala
import java.io.File
import java.net.InetAddress
import com.maxmind.geoip2.DatabaseReader.Builder
import com.maxmind.geoip2.exception.AddressNotFoundException

object GeoipSample {
  def main(args: Array[String]): Unit ={
    val database = new File("/tmp/GeoLite2-Country.mmdb")
    // This creates the DatabaseReader object, which should be reused across lookups.
    val reader = new Builder(database).build()

    val ipAddresses = Seq("128.101.101.101", "192.168.100.1", "183.79.135.206", "212.58.244.18")
    ipAddresses foreach { ip =>
      try {
        println(reader.country(InetAddress.getByName(ip)))
      } catch {
        case e: AddressNotFoundException => println(e)
      }
    }
  }
}
```

`AddressNotFoundException`をキャッチしないといけない。
実行結果は以下。

> Country [getContinent()=North America, getCountry()=United States, getRegisteredCountry()=United States, getRepresentedCountry()=, getTraits()=Traits [ipAddress=128.101.101.101, anonymousProxy=false, satelliteProvider=false, ]]
com.maxmind.geoip2.exception.AddressNotFoundException: The address 192.168.100.1 is not in the database.
Country [getContinent()=Asia, getCountry()=Japan, getRegisteredCountry()=Japan, getRepresentedCountry()=, getTraits()=Traits [ipAddress=183.79.135.206, anonymousProxy=false, satelliteProvider=false, ]]
Country [getContinent()=Europe, getCountry()=United Kingdom, getRegisteredCountry()=United Kingdom, getRepresentedCountry()=, getTraits()=Traits [ipAddress=212.58.244.18, anonymousProxy=false, satelliteProvider=false, ]]

GeoLiteはLegacyになったので、GeoLite2を使おう。
メモ帳

##謎
夏休みに関数型言語でも勉強してみようかと思い、よく分からないので国産 ML の SML# というのを選んでみました。

##座学
- 総合的感想：特殊な規則や場合分けが多い問題に適している気がしました。

倒叙的て明晰でない説明がなされる末尾再帰ですが、要するに JMP Label0001 もしくは goto 1 のようなジャンプ型の構造で、しかも唯一の構造なのだと思いました。

末尾再帰のようなジャンプ構造で DO LOOP を実現しようとすると、ループ変数等の本来隠蔽されるべき変数を関数の引数としてあらわに外部に晒す必要が出てきます。それを包む外側の関数を書いて本来の引数のみにするのですから、ローカル変数宣言を内側の関数の引数で代用している形になっています。（終端値を兼用する形をとることが多いようですが）

また型と演算のファンクターを言うなら、初めに整数型や文字型などを出す前に、単なるビット列の集合を出して、同一のビット列を複数の解釈でみて（多価写像として整数や実数や文字列として解釈して）同一の演算子で演算した結果がそれぞれ異なるビット列に移されるという話にした方が、型がビット列の解釈と演算を規定するという意味がはっきりして分かりやすい気がしました。

一番よく分からないのが、はじめの方で全順序集合としてのリスト構造が、暗黙裡に導入されて前面に出てくるところです。一般論としては、まず順序のない集合を出して、それに色々な位相構造を導入して見せるという形で話が進んだ方が分かりやすい気がしました。その位相構造の一つが一次元リストの全順序集合で、次が二進木などの半順序束構造という感じに・・・

ところが、いきなり全順序リスト構造が断りもなしに出てきますし、整数と同型な構造であることもいつの間にか持ち出してくるので、とりあえずわかりやすい例としてリスト構造を出しているのか、それともリスト構造がコンピュータ用言語として固有の重要性を持つものなので、初めから出してきているのかが判断しづらく、謎としか言いようがなく感じました。

たとえば数学的帰納法が必須というならば、全順序集合が必須ということになってくる気もしますが、読んでる私としてはコンピュータのメモリ番地が一次元的になっていることをモデル化して全順序一次元リスト構造を出しているのかと思って読み進んでいました。結局どうなのかは未だにわかりません。

また全順序集合を基本にループ構造を再帰による漸化式構造にしたため、配列の代入のように本来順序によらない並行動作までもが順序に依存した形になることもよくないと思いました。Fortran では20年前からこれらを区別して別々の表現で書くような方向へ進んでいて、別々の直観的イメージを持てるようになっています。

無論漸化式の形でも場合によっては並行動作に直せるので、その説明がグダグダとなされますが、それは80年代ベクトル計算機用の Fortran コンパイラでも使われていた回帰（再帰）演算の定式化に過ぎないのに、関数型言語の説明と渾然一体に入り混じって出てきて本質が見分けにくくなっているように思いました。

Foldr は、Fortran の世界では多項式計算のところで必ず出てくる Honer 法そのものですが、群論で出てくる半直積とも同じ形だなと思いました。

##実践
とりあえずガウスの掃き出し法でも書いてみるかと思いましたが、配列の取り方が分からず挫折。次に Fortran で書いたシダ植物でも移植しようかと思いましたが、今度はバイナリファイルの I/O がよく分からなくてまたもや挫折。一応備忘代わりに、以下に断片をメモしておきます。

###バイナリファイル読み込み
```
# val f = openIn("shida.bmp");
val f = _ : TextIO.instream
# inputN(f, 2);
val it = "BM" : string
# inputN(f, 4);
val it = "�q\v\^@" : string
# String.explode(w);
val it = [#"\230",#"q",#"\v",#"\^@"] : char list
# val e = it;
val e = [#"\230",#"q",#"\v",#"\^@"] : char list
# val (x1::x2::x3::x4) = e;
(interactive):83.5-83.23 Warning: binding not exhaustive
      :: (x1, :: (x2, :: (x3, x4))) => ...
val x1 = #"\230" : char
val x2 = #"q" : char
val x3 = #"\v" : char
val x4 = [#"\^@"] : char list
# val y1 = ord x1;
val y1 = 230 : int
# val y2 = x2;      
val y2 = #"q" : char
# val y3 = ord x3;
val y3 = 11 : int
# hd x4;
val it = #"\^@" : char
# val x4 = it; 
val x4 = #"\^@" : char
# val y4 = ord x4;
val y4 = 0 : int
# y1 + 256 * (y2 + 256 * y3);
val it = 750054 : int
# y1::y2::y3::y4::nil;
val it = [230,113,11,0] : int list
# val p = y1::y2::y3::y4::nil;
val p = [230,113,11,0] : int list
# val int4 = foldr (fn (x, y) => x + 256 * y) 0;
val int4 = fn : int list -> int
# int4 p;
val it = 750054 : int
```
なんとかバイナリファイルを少しだけ読みこんで、リトルエンディアン整数にすることに成功したところで時間切れ終了。あとは BMP データを書き込む配列を学べば何とかなる？

n個の1バイト符号なし整数のリストを引数として、nバイト符号なしリトルエンディアン整数を返す関数。
```sml
val to_int = foldr (fn (x, y) => x + 256 * y) 0 
```
パララックススクロールが可能なサイトでスクロール途中に固定ナビゲーションを出したいときの設定


## 概要

タイトルのとおり、パララックススクロールができる縦長のウェブページで、スクロール途中から固定ナビゲーションバーを出したいときの簡単な設定の仕方です。

## HTML

ナビゲーションのHTML部分は次のようなリストで作成します。hrefの値にはジャンプ先のidなどを入れてください。

```HTML
<header id="gnav">
  <ul>
    <li><a href="#">Page I</a></li>
    <li><a href="#">Page II</a></li>
    <li><a href="#">Page III</a></li>
    <li><a href="#">Page IV</a></li>
  </ul>
</header>
```

## CSS

次いでCSSです。ポイントは#gnavのtopにマイナスの値が入っていることです。マイナス値の大きさは#gnavのheightと同じで良いと思います。これでウィンドウ外に#gnavが表示される状態になります。colorやfontなどは適宜書き換えてください。

```CSS
header#gnav {
  width: 100%;
  height: 10%;
  position: fixed;
  top: -10%;
  z-index: 100;
  opacity: 0.7;
  color: #fff;
}

header#gnav ul {
  list-style-type: none;
  width: 100%;
  height: 100%;
}

header#gnav ul li {
  width: 20%;
  float: left;
  margin: 1% 0 0 5%;
}

header#gnav ul li a {
  font-size: 1.7rem;
  font-family: "Hiragino Mincho Pro", serif;
  font-weight: bold;
  color: #fff;
  text-decoration: none;
}

header#gnav ul li a:hover {
  color: #0f0;
}
```

## JavaScript

最後にJavaScriptです。やっていることは単純で、あるところまで画面がスクロールするとid="gnav"をもった要素のtopを0にしてウィンドウ上部に表示させるようにし、もとに戻るとtopの値をマイナス値に表示させないようにしています。ここではページの一番上から1500pxまでスクロールしたところでナビゲーションが出るようにしています。

```JavaScript
$(document).ready(function(){

    $(window).scroll(function () {
        if ( $(window).scrollTop() > 1500 ) {
            $('#gnav').css({'top':'0'});
        } else {
            $('#gnav').css({'top':'-10%'});
        }
    });

});
```

ブラウザのウィンドウサイズ分移動したらナビゲーションが出るようにしたい場合は、1500のところを

```
$(window).height()
```
に変えてください。
中規模cookbook開発のためのversioning policy

# 概要
cookbookのversionを使って、安全に他のcookbookを使ったり、他のcookbookに影響を及ぼさずにcookbookに修正を入れることができるようにします。
また、cookbookのversioning policyについても紹介します。

# cookbookの変更と後方互換性
複数のcookbookを組み合わせて一つのcookbookを書いていると、ある日突然、使用しているcookbookに仕様変更が入り、
作っているcookbookに動かなくなったり意図しない動作をするようになってしまうことがあります。
逆も同じで、cookbookに仕様変更を入れてしまうと、それを使っているcookbook全てに修正を入れなくてはいけなくなります。

つまり、cookbookに後方互換性の無い修正が入り、その影響を未然に防ぐことができなかったということです。
recipeを使うのに必須だったattributeの名前が変わったり、recipe名が変わったり、librariesで提供されている関数名が変わったり。。。

使っているcookbookは全て自社製で、変更は全て把握しているので互換性のない変更が入るときは全cookbookをチェックしているぜ！
というのであれば問題無いですが。OSSのcookbookを使っていたり、社内の別のチームが作ったcookbookを使っていたりすると、すぐこの問題にぶち当たります。~~てめえふざけんなよ、予告なしにこんなクソ変更入れやがって！~~

こういった問題をcookbookのversionを使って解決します。

# cookbookのversion
cookbookにはversioningの仕組みがあります。
metadata.rbに

````ruby
version '0.0.1'
````

のように書くことで、cookbookにversionをつけることができます。
また、他のcookbookを使うときにmetadata.rbに

````ruby
depends 'other-cookbook'
````
と書いていると思いますが、下のように書くことで他のcookbookのversionを指定することができます。

````ruby
depends 'other-cookbook', '~> 0.1.2'
````

上の例では、"'other-cookbook'というcookbookのバージョン0.1.2以上0.2.0未満"を指定しています。
Gemfileを使ったことがある人はわかると思いますが、gemのversionの指定の仕方と大体同じです。
詳しくはこちら。
http://docs.getchef.com/essentials_cookbook_versions.html

metadata.rbのdependsに使うcookbook versionの条件を指定しておくと、chef-clientやberks installなどを使った時に
このversion条件を満たすversionのcookbookをダウンロードしてくるようになります。

こうすることで、cookbookが突然version upしてもその変更を受けないようにすることができます。

# cookbookのversioning policy
これで万事解決かというとそうではありません。
当初の問題は、後方互換性の無い変更が入ると困るのであって、裏を返せば後方互換性の無い変更が入るまでは別にどうでもいいです。
それに、依存するcookbookのversion up毎に後方互換性があるか無いかチェックするのは面倒臭すぎます。

そこで、cookbookのversionの付け方のガイドラインを決め、version番号から後方互換性のある変更なのか無い変更なのかを見分けられるようにします。

Cookbook Versioning Policy
http://chef-community.github.io/cvp/

上のページでは、cookbookのversionにSemantic Versioningの考え方を導入しています。
cookbook versionの各桁をそれぞれmajor, minor, patch versionとし、
recipeやattribute、librariesをAPIに見立て、その変更内容によってversionのどの桁を上げるかを決定します。

- 後方互換性の無い変更が入る時はmajor番号を上げる
    - 例: recipe名の変更、必須なattributeの名前の変更、recipe/attributeの削除、libraries関数のシグニチャの変更
- 後方互換性のある機能追加が入る場合はminor番号を上げる
    - 例: recipeの追加、libraries関数の追加、
- 後方互換性のあるバグ修正が入る場合はpatch番号を上げる

詳細な内容は上のページを見てください。

このポリシーに従っているcookbookを使うときは、

````ruby
depends 'hoge', '~> 1.2'
````
のように指定しておくと、
バグ修正と機能追加は自動で取り込むが、後方互換性の無い変更は(metadata.rbを更新しない限り)取り込まないようにできます。

このポリシーをcookbookを書く人全員で共有しておけば、後方互換性の無い変更をしても他チームに影響を及ぼさずに済むし、
他チームが後方互換性の無い変更をしてきても、きちんと事前にテストしてからcookbookを更新することができるようになります。

# CHANGELOGのすゝめ
cookbookの分散開発で起きそうな問題を、cookbookのversionを使うことで解決を図りましたが、もう一点
cookbookに変更を入れるときは、CHANGELOGを書いておくことをオススメします。

cookbookは普通のプログラミング言語のAPIと違い、シグニチャがわかりづらいです。
recipeの書き方が悪いと、どのようなattributeが必須なのかがすぐにわかりません。cookbook中をくまなく調べないとわからないこともあります。

なるべくシンプルにrecipeを構成するのも重要ですが、ドキュメント(README.md)を詳細に書くのも効果的です。
(recipeやresourceの中でattributeをassertしたりするとより効果的です。)

これはcookbookに変更が入った時も同様です。どのようにシグニチャが変わったのか、後方互換性はあるのかを
cookbookの変更の度にCHANGELOGに書いておくと、cookbookを使っている人たちが変更に追従しやすくなります。

CHANGELOGの書き方は、各version毎に
- Breaking changes
- Enhancements
- Bugfix
のような変更の種類毎に分けて書くとよいと思います。

# まとめ
- cookbookに後方互換性の無い変更が入ると辛い
- cookbookのversionを付けよう
- 他のcookbookを使うときはversionを指定しよう
- 後方互換性に着目してcookbookのversioningをしよう
- READMEやCHANGELOGを書こう
EC2のhostsをまとめて書き換えるscript

とりあえず、EC2のhostsをまとめてさらっと書き換えたいときのscript

```ruby:gen_hosts.rb
#!/usr/bin/ruby

puts "127.0.0.1   localhost localhost.localdomain"
puts ""

STDIN.each do | line |
  line.chomp!
  next if line.length == 0 || line =~ /^#/
  remote_host, label = line.split(/\s+/)
  ip = `ssh #{remote_host} curl http://169.254.169.254/latest/meta-data/local-ipv4/ 2>/dev/null`
  puts "#{ip}\t#{label}"
end
```

```bash:update_hosts.sh
#!/bin/sh

if [ `id -u` -ne 0 ];then
  echo "error"
  exit
fi

BIN_PATH=`dirname $0`
echo $BIN_PATH

$BIN_PATH/gen_hosts.rb  < $BIN_PATH/node_list >/etc/hosts.new

if [ $? -eq 0 ]; then
  cp /etc/hosts /etc/hosts.bak
  mv /etc/hosts.new /etc/hosts
else
  exit 1
fi

for host_ip in `cat /etc/hosts |grep -v ^127.0.0.1 |grep -P "^\d+" |awk '{print $1}'`; do
  echo $host_ip ..
  host_name=`cat /etc/hosts |grep ${host_ip} |awk '{print $2}'`
  rsync -avr /etc/hosts ${host_ip}:/etc/hosts
  ssh $host_ip "hostname ${host_name}"
done
```

```text:node_list
ec2-XX-XX-XX-XX.ap-northeast-1.compute.amazonaws.com	node01
ec2-XX-XX-XX-XX.ap-northeast-1.compute.amazonaws.com	node02
..
```

実行
```$ update_hosts.sh
```
アプリケーション管理の利用状況について教えてください。

ショッピング APIを利用して、色々なAPIを利用してコードを作成・テストしていますが、正常に動作しないことがあり、アプリケーションの利用状況を見ると、思ったほど利用状況数が増えていませんでした。

利用状況にカウントされるのは、どのタイミングになるのか教えていただけないでしょうか。
１．認証時のリクエストをカウントしている。
２．認証後の各APIのリクエストをカウントしている。

上記で「２」であれば、リクエストが正常に行われていない為に正常に動作しないということで、各APIのリクエスト部分を再度確認したいと思っております。

お手数ですが、どのタイミングでカウントされているのか教えていただきますようお願いします。
コマンドラインからMavenのセントラルリポジトリを検索できるツールを作ってみた

あるんかなと思ったら、[なさそう](http://stackoverflow.com/questions/14465721/maven-browse-central-repository-via-command-line-client)だった。

[REST API](http://search.maven.org/#api) が提供されていたから、 Groovy で作ってみた。

[GitHub で公開してます](https://github.com/opengl-8080/MavenFind)

##使用例
###任意検索
```text
> groovy mvnfind -q "commons lang"
com.btmatthews.jaxb2_commons:jaxb2-commons-lang3:1.0.0
com.cedarsoft.commons:lang:6.0.1
com.mysema.commons:mysema-commons-lang:0.2.4
commons-lang:commons-lang:20030203.000129
fm.last.commons:lastcommons-lang:3.1.1
net.bramp.jackson:jackson-datatype-commons-lang3:0.1
net.dongliu.commons:commons-lang:1.0.3
net.sf.staccatocommons:commons-lang:1.2
org.andromda.thirdparty.jaxb2_commons:commons-lang-plugin:2.2
org.apache.commons:commons-lang3:3.3.2
org.apache.directory.studio:org.apache.commons.lang:2.6
org.apache.karaf.demos.deployer.wrap:osgi.commons-lang:2.3.6
org.apache.karaf.eik.plugins:org.apache.commons.lang:2.6
org.apache.servicemix.bundles:org.apache.servicemix.bundles.commons-lang:2.4_6
org.jvnet.jaxb2_commons:jaxb2-commons-lang:2.4
org.kie.modules:org-apache-commons-lang-main:6.2.0.Beta1
org.kie.modules:org-apache-commons-lang3:6.2.0.Beta1
org.mod4j.org.apache.commons:lang:2.1.0
```

###グループID などを指定
```text
> groovy mvnfind -g org.apache.commons -a commons-lang3
org.apache.commons:commons-lang3:3.3.2
```

###全バージョンを表示する
```text
> groovy mvnfind -g org.apache.commons -a commons-lang3 --allVersions
org.apache.commons:commons-lang3:3.0
org.apache.commons:commons-lang3:3.0.1
org.apache.commons:commons-lang3:3.1
org.apache.commons:commons-lang3:3.2
org.apache.commons:commons-lang3:3.2.1
org.apache.commons:commons-lang3:3.3
org.apache.commons:commons-lang3:3.3.1
org.apache.commons:commons-lang3:3.3.2
```

###表示件数を指定する
```text
> groovy mvnfind -g org.apache.commons --max 5
org.apache.commons:commons-compress:1.8.1
org.apache.commons:commons-csv:1.0
org.apache.commons:commons-dbcp2:2.0.1
org.apache.commons:commons-email:1.3.3
org.apache.commons:commons-math3:3.3
```
HDD情報の取得

# HDD情報取得
```
# hdparm -I /dev/sdb
```

# 確認するポイント
## HDDの型番
```
Model Number:       ST1000DM003-1CH162
```
自分の購入したHDDが何なのか知りたいことがたまにある
## セクタタイプ(HDDドライバの話)
```
        Logical  Sector size:                   512 bytes
        Physical Sector size:                  4096 bytes
```
この場合、Advanced Formatタイプです。
物理的には4KB単位で書き込みを行うが、ソフトウェア(OS)側では512Bとして認識しています。両方の値が512Bならば512Bセクタ、4046Bならば4Kセクタとなります。
あと、ここで出てくるサイズはドライバが読み書きする単位であってファイルシステム(ex2,ext3など)の単位とはまた別です。
[JavaScript]if,elseif,elseをメソッドチェーンで書く

_elseifとか_elseを単体で呼ばれないようにするために少し工夫しました。
_ifと_elseifはほぼ同じメソッドで誰から呼ばれているかをチェックしている部分のみ違います。

```js:method-chain-if-else.js
function _if(condition, callback){
	if(this === _if) throw '_ifは最初にのみ使えます';
	if(condition){
		callback();
		var nop = function(){ return nop };
		return nop;
	}else{
		return function(f, condition_or_callback, callback_or_none){
			return f.call(_if, condition_or_callback, callback_or_none);
		}
	}
}

function _elseif(condition, callback){
	if(this !== _if) throw '_elseifは単体では使えません';
	if(condition){
		callback();
		var nop = function(){ return nop };
		return nop;
	}else{
		return function(f, condition_or_callback, callback_or_none){
			return f.call(_if, condition_or_callback, callback_or_none);
		}
	}
}


function _else(callback){
	if(this !== _if) throw '_elseは単体では使えません';
	callback();
}

```

これを用いてFizzBuzzを書くと以下のようになる。

```js
// console.logをfunctionでラップしたものを返すヘルパー
function l(a){
	return function(){console.log(a)};
}

for(var i = 1;i <= 100;i++){
	_if(i % 3 == 0 && i % 5 == 0, l("fizzbuzz"))(
		_elseif,
		i % 3 == 0,
		l("fizz")
	)(
		_elseif,
		i % 5 == 0,
		l("buzz")
	)(
		_else,
		l(i)
	);
}
/*(実行結果)
1
2
fizz
4
buzz
fizz
7
8
fizz
buzz
11
fizz
13
14
fizzbuzz
16 
...中略...
97
98
fizz
buzz 
*/
```
ダイナミックリンクとスタティックリンクの混在(MinGW環境)

自身のブログからの転載。

結論から言うと、
あるライブラリはスタティックリンク、あるライブラリはダイナミックリンクしたいという場合
gccの-staticオプションは全体に効いちゃうから
以下のようにリンカに直接オプションを渡すといいよ。という話。
`gcc … -Wl,-lmigemo,-lonig,-dn,-llua …`
(migemo, onigrumaはダイナミック、luaはスタティック)

※『みたい』、『ようです』の憶測が多いのは
ちゃんとドキュメント見てなくて、実験的に調べた結果のため。

libhoge.aを探すかlibhoge.dll.aを探すか
------------------------------------
hogeというライブラリをダイナミックリンクする場合コンパイラ(リンカ)は
libhoge.dll.a → libhoge.aの順にインポートライブラリを探してくれますが、
スタティックリンクの場合は
libhoge.a
しか探しに行かないようです。
したがって、明示的にダイナミックリンクするライブラリならlib～.dll.aという名前を、
それ以外はlib～.aという名前を、両方あり得るなら二つとも用意すればいいわけです。

スタティックリンクを指定するオプション-static
----------------------------------------
さて、ライブラリのスタティックリンク/ダイナミックリンクを指定するオプションとして
gccには-staticというオプションがあるんですが、
これは-l<ライブラリ名>で与えられたライブラリ全体に効いてくるみたいです。
ですので、
`gcc … -lmigemo -llua -static -lonig`
としたら、onigrumaだけスタティックリンクにして欲しいところですが...
migemo, luaもスタティックリンクしようとしてlibmigemo.a, liblua.aだけ探しに行きます。
libmigemo.dll.aやliblua.dll.aしかない場合はスタティック用リンクライブラリが見つからず
-lmigemo(-llua)は無効だよ！ってことでコンパイルエラーになってしまいます。

リンカに直接オプションを渡そう
--------------------------
それに対して記事冒頭のようにリンカに直接オプションを渡した場合は
-dn(-Bstatic)オプションより前のライブラリはダイナミックリンク、
オプションより後ろのライブラリはスタティックリンクとして扱ってくれるみたいです。
多分デフォルトがダイナミックリンクなのでしょう。

ちなみに
`gcc … -Wl,-dy,-lmigemo,-dn,-lonig,-dy,-llua …`
このようなダイナミック(-dy)とスタティック(-dn)を混ぜた指定も可能です。
Travisでssh-agent/ssh-addするときに気を付けること！

# はじめに
* やりたかったことはシンプルで、ssh-agent/ssh-addをSSHの設定を入れようとしただけです
* Gemfileのソースにプライベートリポジトリを指定していたため、設定しなければgit cloneに失敗するのです
* そのため、SSHの設定をしなければならなかったのです
* ちなみに、~.netrcに書いてhttp経由でgit cloneする方法は試して問題なくできていましたが、TravisではやりたくなかったのでSSH経由を考えました

# なんら困らない書き方
* .travis.ymlに以下のようにべた書きする

```rb:.travis.yml
...
before_install:
  - eval `ssh-agent -s`
  - ssh-add [key path] #ex) .travis/travis_key
...
```

# 今回はまった書き方
* .travis.ymlにすべてを書きつくせば１ファイルですみますが、ドエライ量になります
* おまけに、ここは条件分岐、ここは関数でと考えていけば複雑になってきて１ファイルでは辛くなってきますよね
* そこで、私はRAILS_ROOTに.travisディレクトリを作って、その下にスクリプトファイルを突っ込んで.travis.ymlではそれを実行するようにしました
* すると以下のようになります

```:.travis.yml
...
before_install: ruby .travis/before_install.rb
...
```

```rb:.travis/before_install.rb
[ 'eval `ssh-agent -s`',
  'ssh-add .travis/travis_key'
].each {|c| system(c)}
```

* その他にも色々なコマンドをこの形式で書いていたので、これで大丈夫だと思ったのですがダメでした
* どうダメだったかというと、エラーなどは出ることなくAGENT PIDも出力されていたのですがSSHで失敗するのです
* 余談ですが、.travis/xxxx.rbのファイル名はbefore_script.rb/after_success.rbなど.travis.yml内に登場するものと一致させておいたらどこに何がかいてあるか一目瞭然ですね！

## 追っかけてみた
* ```echo $SSH_AGENT_PID```を追加して```eval `ssh-agent -s` ```の前後で比べてみる
* 「なんら困らない書き方」のほうはssh-agentで出力されたPIDが$SSH_AGENT_PIDになっていた
* 一方、「今回はまった書き方」のほうは$SSH_AGENT_PIDが変更されていなかった。。
 * すなわち、ssh-agent/ssh-addが効いていないm(__)m
* Rubyのsystem()とか使わず、Shellのファイルで実行すればと思ったのですが結果は同じでした
* おそらくはシステムの環境変数絡みのものはTravisの親プロセス(.travis.yml側)で書かなければならないのかなと

# 結論
* 私はどっぷり１日はまっていたので、ほかの人そうならず幸せになれればと思い記事に残しました
* そして、この１行くらい.travis.ymlに書けばいいじゃない！キリッという結論に至りました
* そう、長ったらしいコマンドでもなくパッと見て意味の分からないコマンドでもないのだから

----

### 参考文献
* http://www.gfd-dennou.org/arch/morikawa/memo/ssh-agent.txt
* http://tipspc.blogspot.jp/2010/02/ssh-agent.html

# ～ただの宣伝～
* [全国のSeleniumer必読](http://qiita.com/oh_rusty_nail/items/b8ba525d31ea7c522856)
* Selenium, SauceLabs, Travis, Jenkinsに関するノウハウ書いているのでよかったら参考にしてみてください
Ansibleのテンプレートファイルを分割する際はJinja2のmacroが便利でした

# はじめに

この記事はAnsibleのタグを付けていますが、Ansible特有の話は無くてJinja2のmacroの話です。

Ansibleのplaybookを書いていて、テンプレートファイルが大きくなってくると共通部分を別ファイルにして読み込むようにしたくなってきます。複数箇所で読み込む際にパラメータを渡してテンプレート内の変数を違う値に展開したいと思いました。

# Jinja2のincludeにはパラメータを渡せない

[Ansibleのtemplateモジュールのドキュメント]( http://docs.ansible.com/template_module.html )からリンクされている
[Jinja2のTemplate Designer Documentation]( http://jinja.pocoo.org/docs/dev/templates/ )を見てみました。

[Include]( http://jinja.pocoo.org/docs/dev/templates/#include )といういかにもな名前のステートメントがあるので使い方を見てみました。が、下記の例のように変数コンテキストを引き継ぐという指定はできますが、パラメータを渡すことは出来ないようです。

```jinja
{% include "sidebar.html" ignore missing with context %}
```

# Jinja2のユーザ定義マクロならパラメータを渡せる

さらに見ていくと[Import]( http://jinja.pocoo.org/docs/dev/templates/#import )というステートメントがありました。

以下の例のようにマクロを定義します。

```jinja2:forms.j2
{% macro input(name, value='', type='text') -%}
    <input type="{{ type }}" value="{{ value|e }}" name="{{ name }}">
{%- endmacro %}
```

使う側は[Import Context Behavior]( http://jinja.pocoo.org/docs/dev/templates/#import-visibility )の説明にあるように、```from ファイル名 import マクロ名 with context``` として読み込みます。

```jinja
{% from 'forms.j2' import input with context %}
```

後は使いたい箇所で以下のようにパラメータを渡して呼び出せばOKです。

```jinja
{{ input('username', value='John') }}
```

あるいは

```jinja
{% import 'forms.j2' as forms with context %}
```

としてインポートして

```jinja
{{ forms.input('username', value='John') }}
```

のように呼び出すことも可能です。Pythonのimportと同じですね。

## with context無しだとエラーになった

```with context```を付けずに試してみると、以下の様なエラーが出ました。

```
fatal: [cent65] => {'msg': "AttributeError: 'NoneType' object has no attribute 'add_locals'", 'failed': True}
```

よくわかっていませんが、```with context```は必要なようです。

# まとめ

ということで、Ansibleでテンプレートファイルを分割する場合は、Jinja2のマクロ機能を使うのがお勧めです。
Titanium StudioでCompiling localization filesでビルドが止まったら


strings.xmlのxmlタグが間違ってないか確認.
\<string\>としないといけないところ\<sring\>となってビルドが止まってた。
過去にも一度これでハマったので、他の人が無駄な時間を過ごさないですむように共有。
vagrant+CentOSにmysql5.6を導入

前提
　vagrantにsshで入って、ルートユーザになっている。

mysql5.6のインストール
<pre>yum install http://repo.mysql.com/mysql-community-release-el6-5.noarch.rpm
yum install mysql mysql-devel mysql-server mysql-libs</pre>

mysql起動
<pre>/etc/init.d/mysqld start</pre>

ここでエラー！！！
Google先生で探したら、全く同じ問題を解決した人がいて、
分かりやすく解説してくれてました！
<pre>Vagrant+VirtualBox+CentOS環境でMySQL5.6が起動しない場合の対処法
http://nekopunch.hatenablog.com/entry/2014/03/22/020507</pre>

ってなわけで、上記サイトを参考に下記を実施！

・仮想OSのメモリサイズを増やす
　Vagrantfileに下記を記述する。
<pre>config.vm.provider :virtualbox do |v|
v.customize ["modifyvm", :id, "--memory", 1024]<br>end</pre>

vagrant再起動
<pre>vagrant halt
vagrant up</pre>

mysql起動(前提条件の状態で)
<pre>/etc/init.d/mysqld start</pre>

起動した！！！
Mavericksにアップデートしたら？Titanium Studioが起動するたびにUpdateダイアログを表示するようになった


全く同じ症状の人がいた.

[Mac OS X] Can't install Titanium CLI & Alloy - Invalid Password
https://developer.appcelerator.com/question/145775/mac-os-x-cant-install-titanium-cli--alloy---invalid-password

以下で直った。この前にnodeをbrewでインストールし直したけど、それが関係あるか不明。

```bash

$sudo npm install -g alloy titanium acs

```
rails4でのcookieの設定・取得

Rails4でのCookieの利用方法を調べたのでついでにメモしておく。

## 署名無しCookieの場合
* 設定

```rb
cookie["Cookie名指定"] = "値"
cookies[:hoge3] = "hoge3"
```
* 取得

```rb
cookies["Cookie名指定"]
cookies[:hoge3]
```

## 署名ありCookieの場合
* 設定

```rb
cookie.signed["Cookie名指定"] = "値"
cookie.signed[:abc] = {:value => "abc", :expires => 1.year.from_now } #←このようにexpireなども設定できる
```
* 取得

```rb
cookies.signed["Cookie名指定"]
cookies.signed[:abc]
cookies["Cookie名指定"] #← これでも取れるが暗号化されたままの値になる

```
Rails で複数の CacheStore を同時に扱う方法

Rails で目的別に CacheStore を使い分けたい場合どうするか。

## 想定する状況

例えば、普段は MemCacheStore を CacheStore として使っているけど、一部のキャッシュはもっと高速にしたいので MemoryStore を使いたい場合。

具体的に起こった事例でいうと、MemCacheStore にキャッシュしていたが、計測してみると memcached とのネットワーク転送に若干時間がかかっていた。ネットワークコストをなくすため、そこだけ MemoryStore したい。幸い MemoryStore のデメリットも、そこだけに限れば問題にならなそう。というケース。

## 使いたい CacheStore を個別に作ればよい

上のケースだと、`ActiveSupport::Cache::MemoryStore` を使いたいので、`config/initializers/` 下に適当な ruby ファイルを作って `MemoryStore` を生成してやる。

```rb:config/initializers/hoge_memory_store.rb
::HOGE_MEMORY_STORE = ActiveSupport::Cache.lookup_store(:memory_store)
```

<small>Rails の中で ActiveSupport::Cache.lookup_store 経由で CacheStore を作っていたので真似しているが、直接 `ActiveSupport::Cache::MemoryStore.new` でもよい。</small>

使う側では普段使っている `Rails.cache` の代わりに上記で生成した CacheStore を使ってやればよい。

```rb
::HOGE_MEMORY_STORE.write('hoge', 'nya-')
```

## まとめ

- 使いたい CacheStore を自分で生成して、使い分ければよい
- というのをこれから実践する(実践したので後述)
- 記事とは関係ないですが、キャッシュの利用は計画的に

## 追記
上の具体例に対して実践したところ、そこまで大きな効果はなかった。
というのも実際の production 環境ではネットワーク速度も早いため。
もう少ししっかり計測してから取り組む価値があるか判断した方がよかったです。
とは言えメモリストアは最速なので、速いは速いですよ。
ということで、キャッシュの利用は計画的に。。。自戒の意味を込めて書いたのに早速ブーメランとは。。。

## 参考リンク

[ActiveSupport::Cache](http://api.rubyonrails.org/classes/ActiveSupport/Cache.html)
gem install経由のbundlerがcommand not foundになった時の対処

bundlerに限らずgem installでインストールしたのにcommand not foundになってしまった時の対処です。


インストールは問題なく成功

```
$ gem install bundler
Fetching: bundler-1.7.2.gem (100%)
Successfully installed bundler-1.7.2
Parsing documentation for bundler-1.7.2
Installing ri documentation for bundler-1.7.2
Done installing documentation for bundler after 6 seconds
1 gem installed
```

いざコマンドを実行してみると・・・

```
$ bundle install
-bash: bundle: command not found
```

PATHが通ってないかと確認すると、以下の通りの状況。

```
$ gem contents bundler | grep bin
/Users/user/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/bundler-1.7.2/bin/bundle

$ echo $PATH
/Users/user/.rbenv/bin:/Users/user/.rbenv/shims:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
```

```
$ ls $HOME/.rbenv/shims
berks			chef-solo		ffi-yajl-bench		ldiff			rake			shef
chef-apply		chef-zero		gem			minitar			rdoc			testrb
chef-client		coderay			htmldiff		ohai			restclient		thor
chef-service-manager	erb			irb			pry			ri
chef-shell		erubis			knife			rackup			ruby
```

はい、そうです。rbenvを使用しているのにrehashしていないだけです。
意外と忘れがちで、気づきづらいのでメモしておきます。

```
$ rbenv rehash 
$ ls $HOME/.rbenv/shims
berks			chef-service-manager	erb			irb			pry			ri
bundle			chef-shell		erubis			knife			rackup			ruby
bundler			chef-solo		ffi-yajl-bench		ldiff			rake			shef
chef-apply		chef-zero		gem			minitar			rdoc			testrb
chef-client		coderay			htmldiff		ohai			restclient		thor
```