OmniAICreator/Qiita-1.07M huggingface dataset:
td-agentへのfluent-plugin追加に失敗した件＋解決策


## 事象
fluent-plugin-mysqlを使ってみようと思って、td-agentにインストールしようとしたところ。

```
# /usr/lib64/fluent/ruby/bin/fluent-gem install fluent-plugin-mysql
# vi /etc/td-agent/td-agent.conf
```

ここで、/etc/td-agent/td-agent.confにmysqlに関する追記。

```
# service td-agent restart
Starting td-agent: 2013-02-14 18:14:40 +0900: fluent/supervisor.rb:187:rescue in main_process: config error file="/etc/td-agent/td-agent.conf" error="Unknown output plugin 'mysql'. Run 'gem search -rd fluent-plugin' to find plugins"
                                                           [FAILED]
```

という感じでプラグインを認識していなかった。

## 原因
よくよくfluent-gemのenvironmentsをみてみると、

```
# /usr/lib64/fluent/ruby/bin/gem environment
~~~~~中略~~~~~~~~~~~~~
  - GEM PATHS:
     - /usr/local/rvm/gems/ruby-1.9.3-p327
     - /usr/local/rvm/gems/ruby-1.9.3-p327@global
~~~~~中略~~~~~~~~~~~~~
```

のようになっていた。
td-agentが見に行くgemのpathは

```
/usr/lib64/fluent/ruby/lib/ruby/gems/1.9.1/gems
```
のようなので、これではgemをinstallしても認識されない。

## 解決策
急場凌ぎの対策です。

```
GEM_HOME="/usr/lib64/fluent/ruby/lib/ruby/gems/1.9.1/"
GEM_PATH="/usr/lib64/fluent/ruby/lib/ruby/gems/1.9.1/"
/usr/lib64/fluent/ruby/bin/fluent-gem install fluent-plugin-mysql
```

こんな感じで無理やりGEM_HOMEとGEM_PATHを変更してinstallするとpluginが認識されました。

## 雑感
td-agent用にfluent-gemコマンドとは分離したtd-gemみたいなコマンドを用意して、GEM_HOME、GEM_PATHを明示的に指定したほうがいい気もする。
Detect array manipulation by observer pattern


```coffeescript:detectArrayChanges.js
detectArrayChanges = (array)->
    observers = []
    
    emit = (array, operation, elements)->        
        observer(array, operation, elements) for observer in observers

    Object.defineProperty array, 'watch',
        value:(observer)->
            observers.push(observer)

    Object.defineProperty array, 'push',
        value: ()->
            Array::push.call(array, arguments...)
            emit(array, 'push', [arguments...])

    Object.defineProperty array, 'pop',
        value: ()->
            poped = Array::pop.call(array)
            emit(array, 'pop', [poped])

    Object.defineProperty array, 'shift',
        value: ()->
            shifted = Array::shift.call(array)
            emit(array, 'shift', [shifted])

    Object.defineProperty array, 'splice',
        value: ()->
            removed = Array::splice.call(array, arguments...)
            emit(array, 'splice', removed)

    Object.defineProperty array, 'unshift',
        value: ()->
            Array::unshift.call(array, arguments...)
            emit(array, 'unshift', [arguments...])
```

## Example code

```coffeescript:example
array = []

detectArrayChanges(array)

array.watch (array, operation, elements)->
    console.log operation, elements, array

array.push(1)
array.push(2, 3, 4, 5, 6, 7, 8, 9)
array.pop()
array.shift()
array.splice(3, 3)
array.unshift(-1, 0)
```

## Results

The output becomes like:

```txt:output
push [ 1 ] [ 1 ]
push [ 2, 3, 4, 5, 6, 7, 8, 9 ] [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
pop [ 9 ] [ 1, 2, 3, 4, 5, 6, 7, 8 ]
shift [ 1 ] [ 2, 3, 4, 5, 6, 7, 8 ]
splice [ 5, 6, 7 ] [ 2, 3, 4, 8 ]
unshift [ -1, 0 ] [ -1, 0, 2, 3, 4, 8 ]
```

## Followings are not detected

```coffeescript
# Followings are not detected
array[0] = 9999
delete array[0]
array[20] = 123
```
How to detect object's property changes using Object.defineProperty()


```coffee:detectChange.coffee
detectChange = (object)->
    changed = false

    Object.defineProperty object, '__changed__',
        get: ()-> return changed
        
    Object.defineProperty object, '__resetChanged__',
        value: ()-> changed = false

    for own prop of object
        do ()->
            current = object[prop]
            Object.defineProperty object, prop, 
                enumerable: true
                configurable: true
                get: ()-> return current
                set: (newval)->
                    changed = true if newval != current
                    current = newval


# Bound object
obj = {foo: 'foo'}
console.log obj.__changed__ # undefined
console.log JSON.stringify(obj) # {"foo":"foo"}

# Start to detect object property changes
detectChange(obj)
console.log obj.__changed__ # false
console.log JSON.stringify(obj) # {"foo":"foo"}

# Set same value for the property
obj.foo = 'foo'
console.log obj.__changed__ # false
console.log JSON.stringify(obj) # {"foo":"foo"}

# Change the property of obj
obj.foo = 'bar'
console.log obj.__changed__ # true
console.log JSON.stringify(obj) # {"foo":"foo"}

# Reset changed status
obj.__resetChanged__()
console.log obj.__changed__ # false
console.log JSON.stringify(obj) # {"foo":"foo"}
```

## A Known Problem

The result of `console.log` is not pretty…:( All properties appear as `[Getter/Setter]` like following. Does anyone how to solve this issue?

```
{ foo: [Getter/Setter] }
```
ホームディレクトリにアプリケーションフォルダを作る方法


なぜかMountain Lionでは無くなってしまった`~/Applications`ディレクトリ。
eclipseやAndroid SDKを置くのに便利なので↓のようにして作ってます。

![](https://dl.dropbox.com/u/32205774/20130214_how_to_create_applications_folder_in_homedir/00006.png)

```
Yoichi:~ mazgi$ pwd
/Users/mazgi
Yoichi:~ mazgi$ mkdir -p Applications
Yoichi:~ mazgi$ touch Applications/.localized
Yoichi:~ mazgi$ open .
```
sublime text 2で<br>タグを自動挿入

[【Sublime Text 2】改行タグ&lt;br&gt;をDreamweaverでのショートカットと同じようにキーバインドを設定する](http://c-brains.jp/blog/wsg/13/02/13-203004.php)
上のやつ確かにSublimeで出来ないの不便だったんで試してみたら動かなかったので下のように書き換えた。

{ "keys": ["shift+enter"], "command": "insert", "args": {"characters": "&lt;br /&gt;" } },
{ "keys": ["ctrl+enter"], "command": "insert", "args": {"characters": "&lt;br&gt;" } }
ファイルサーバーのユーザー移行


sambaのファイルサーバーのユーザー移行手順めも

##前提条件
####移行前サーバー

centOS4.9
samba3.0
sambaユーザーのパスワード管理は「smbpasswd」でファイル管理

####移行後サーバー

cantOS6.3
samba3.5
sambaユーザーのパスワード管理は「smbpasswd」でファイル管理のままにする

## 必要ファイルの取得

####移行前サーバーでの作業

移行のために必要なユーザー情報の取得

```
cd
mkdir userdate
cd userdate
cp /etc/group .
cp /etc/gshadow .
cp /etc/passwd .
cp /etc/shadow .
cp /etc/samba/secrets.tdb .
cp /etc/samba/smbpasswd .
cp /etc/samba/smbusers .
cp /etc/samba/smb.conf .
cd ..
tar zcvf userdate.tar.gz userdate
```

`scp`なりなんなりでローカルに持ってくる

## ユーザー情報ファイルの設置

####移行後サーバーでの作業

`scp`なりなんなりで固めたファイルをあらかじめ置いておく

```
tar zxvf userdate.tar.gz
cd userdate
mv /etc/group /etc/group.def
mv /etc/gshadow /etc/gshadow.def
mv /etc/passwd /etc/passwd.def
mv /etc/shadow /etc/shadow.def
cp group /etc/
cp gshadow /etc/
cp passwd /etc/
cp shadow /etc/
chmod 000 /etc/shadow
chmod 000 /etc/gshadow
mv /etc/samba/secrets.tdb /etc/samba/secrets.tdb.def
mv /etc/samba/smbpasswd /etc/samba/smbpasswd.def
mv /etc/samba/smbusers /etc/samba/smbusers.def
mv /etc/samba/smb.conf /etc/samba/smb.conf.def
cp secrets.tdb /etc/samba/
cp smbpasswd /etc/samba/
cp smbusers /etc/samba/
cp smb.conf /etc/samba/

```

念のため置いてきたファイルの権限がdefに変えた元ファイルと変わりがないか確認しておく(重要)

`smbpasswd`を読むようにconfの記述追加

```
vi /etc/samba/smb.conf
[global]
…
        passdb backend = smbpasswd
        smb passwd file = /etc/samba/smbpasswd
…

testparm -v #sambaのデフォルトの設定も表示
```

`testparm -v`の出力内容を見て記述変更した内容に書き変わっていればOK

```
shutdown -r now
```

願いながら再起動を行い、移行したユーザーでsamba接続が行えれば無事終了。
Net::Twitter::Lite + Twitter API 1.1

Net::Twitter::Lite は Twitter API 1.1 に対応していない。

- http://shibayu36.hatenablog.com/entry/2013/02/13/072947
- http://shibayu36.hatenablog.com/entry/2013/02/14/104829

という風にすると対応させることができる。そしてその結果できあがったものが

- https://github.com/hatena/net-twitter-lite

に置いてある。今までの Net::Twitter::Lite をこれに差し替えればOK。注意事項として

- $twitter->friends という昔あったメソッドが (Twitter API 自体なくなって) 削除されてる
- $twitter->show_user($id) や $twitter->show_user({id => $id}) が動かなくなって $twitter->show_user({user_id => $id}) と書かないといけない

というのがある (他にも何かあるかも?)。


その後本家が 1.1 に対応したけど、 API が変わっていてそのまま更新するだけでは 1.1 対応にならないので注意。 https://github.com/semifor/net-twitter-lite
オフラインリアルタイムどう書く第8回の参考問題をscalaで解く

問題はこちら
http://nabetani.sakura.ne.jp/hena/ord8entco/
パターンマッチするのにListに変換してるのがいまいち。

```scala
object Main extends App{
	def charToBinStr(c:Char):String = List(1,2,4,8).map(x=>"0123456789abcdef".indexOf(c)&x).mkString.replaceAll("[^0]","1")

	def decode(s:String,result:String,bits:Int):(String,String,Int) = {
		s.toList match {
		  case '0'::'0'::'0'::xs => decode(xs.mkString, result + "t", bits + s.size - xs.size)
		  case '0'::'0'::'1'::'0'::xs => decode(xs.mkString, result + "s", bits + s.size - xs.size)
		  case '0'::'0'::'1'::'1'::xs => decode(xs.mkString, result + "n", bits + s.size - xs.size)
		  case '0'::'1'::'0'::'0'::xs => decode(xs.mkString, result + "i", bits + s.size - xs.size)
		  case '0'::'1'::'0'::'1'::'0'::xs => decode(xs.mkString, result + "d", bits + s.size - xs.size)
		  case '0'::'1'::'0'::'1'::'1'::'0'::'1'::xs => decode(xs.mkString, result + "c", bits + s.size - xs.size)
		  case '0'::'1'::'0'::'1'::'1'::'1'::xs => decode(xs.mkString, result + "l", bits + s.size - xs.size)
		  case '0'::'1'::'1'::'0'::xs => decode(xs.mkString, result + "o", bits + s.size - xs.size)
		  case '0'::'1'::'1'::'1'::xs => decode(xs.mkString, result + "a", bits + s.size - xs.size)
		  case '1'::'0'::xs => decode(xs.mkString, result + "e", bits  + s.size - xs.size)
		  case '1'::'1'::'0'::'0'::xs => decode(xs.mkString, result + "r", bits + s.size - xs.size)
		  case '1'::'1'::'0'::'1'::xs => decode(xs.mkString, result + "h", bits + s.size - xs.size)
		  case '1'::'1'::'1'::xs => ("", result, bits  + s.size - xs.size)
		  case _ => ("","",0)
		}
	}

	def solve(q:String):String = {
	  val (s,result,bits) = decode(q.map(charToBinStr).mkString, "", 0)
	  if (bits == 0) "*invalid*" else result + ":" + bits.toString
	}

	probs.split("\n").foreach(line => line.split("\\s+").toList match {
		case List(no,q,a) => {
			var ans = solve(q)
		 	println(no + "\t" + ans + "\t" + (if (ans==a) "o" else "x"))
		 }
		 case _ =>
	})

	def probs =
	"""
0	16d9d4fbd	ethanol:30
1	df	e:5
2	ad7	c:10
3	870dcb	t:6
4	880f63d	test:15
5	a57cbe56	cat:17
6	36abef2	roll:23
7	ad576cd8	chant:25
8	3e2a3db4fb9	rails:25
9	51aa3b4c2	eeeteee:18
10	ad5f1a07affe	charset:31
11	4ab8a86d7afb0f	slideshare:42
12	ac4b0b9faef	doctor:30
13	cafebabe	nlh:17
14	43e7	sra:15
15	53e7	eera:15
16	86cf	tera:16
17	b6cf	hon:15
18	0	*invalid*
19	c	*invalid*
20	d	*invalid*
21	e	*invalid*
22	babecafe	*invalid*
23	8d	*invalid*
24	ad	*invalid*
25	af	*invalid*
26	ab6e0	*invalid*
27	a4371	*invalid*
28	a4371	*invalid*
29	96e3	*invalid*
30	0dc71	*invalid*
31	2a9f51	*invalid*
32	a43fb2	*invalid*
33	ab6e75	*invalid*
34	a5dcfa	*invalid*
35	ca97	*invalid*
36	6822dcb	*invalid*
	"""
}
```
オフラインリアルタイムどう書く第8回の参考問題を Haskell で解く

問題は http://nabetani.sakura.ne.jp/hena/ord8entco/


```off-line08_ref.hs
import Data.Char
import Data.List

codeTable :: [(String, Char, Int)]
codeTable = [("000",     't', 3),
             ("0010",    's', 4),
             ("0011",    'n', 4),
             ("0100",    'i', 4),
             ("01010",   'd', 5),
             ("0101101", 'c', 7),
             ("010111",  'l', 6),
             ("0110",    'o', 4),
             ("0111",    'a', 4),
             ("10",      'e', 2),
             ("1100",    'r', 4),
             ("1101",    'h',4)]

-- ex : stringToBit "1a"  =>  "10000110"
stringToBit :: String -> String
stringToBit cs = concatMap digitToBit cs
  where
    digitToBit x = take 4 $ loop (digitToInt x) ++ repeat '0'
    loop n
      | n < 2 = [intToDigit n]
      | otherwise = (intToDigit $ rem n 2) : loop (div n 2)

-- ex : inputToString "16d9d4fbd"  =>  "ethanol:30"
inputToString :: String -> String
inputToString cs = loop (stringToBit cs) "" 0
  where
    loop "" _ _ = "*invalid*"
    loop bit str n
      | isPrefixOf "111" bit = (reverse str) ++ (':' : show (n + 3))
      | otherwise = search codeTable bit str n

    search [] _ _ _ = "*invalid*"
    search ((cd, c, m) : tbl) bit str n
      | isPrefixOf cd bit = loop (drop m bit) (c : str) (n + m)
      | otherwise = search tbl bit str n

main :: IO ()
main = do
  strs <- readFile "off-line08_ref_testData.txt"
  mapM_ f $ map words $ lines strs
    where f [n, i, o] = putStrLn (n ++ " " ++ (show $ inputToString i == o))
```

``` off-line08_ref_testData.txt
0	16d9d4fbd	ethanol:30
1	df	e:5
2	ad7	c:10
3	870dcb	t:6
4	880f63d	test:15
5	a57cbe56	cat:17
6	36abef2	roll:23
7	ad576cd8	chant:25
8	3e2a3db4fb9	rails:25
9	51aa3b4c2	eeeteee:18
10	ad5f1a07affe	charset:31
11	4ab8a86d7afb0f	slideshare:42
12	ac4b0b9faef	doctor:30
13	cafebabe	nlh:17
14	43e7	sra:15
15	53e7	eera:15
16	86cf	tera:16
17	b6cf	hon:15
18	0	*invalid*
19	c	*invalid*
20	d	*invalid*
21	e	*invalid*
22	babecafe	*invalid*
23	8d	*invalid*
24	ad	*invalid*
25	af	*invalid*
26	ab6e0	*invalid*
27	a4371	*invalid*
28	a4371	*invalid*
29	96e3	*invalid*
30	0dc71	*invalid*
31	2a9f51	*invalid*
32	a43fb2	*invalid*
33	ab6e75	*invalid*
34	a5dcfa	*invalid*
35	ca97	*invalid*
36	6822dcb	*invalid*
```
WebStormの設定を共有する

チームで開発しているとIDEの設定を共有したくなりますよね。
ならないとしたら、今すぐこの記事を読むのをやめて病院に行って下さい。

## バージョン管理する対象に.idea/以下を含める
http://devnet.jetbrains.com/docs/DOC-1186
下記の「設定をエクスポートしてインポート」より良い方法として、プロジェクトの.ideaディレクトリ以下をバージョン管理対象に含める方法がありました。

## Mavenで管理する → ダメだった
eclipseにはmaven-eclipse-pluginという設定ファイルを生成してくれたりする便利なMavenプラグインがあります。WebStormにも似たものがないか探しました。で、あったには[あった](http://maven.apache.org/plugins/maven-idea-plugin/)のですが、codestyleなどの設定ファイルは作ってくれないみたいで目的に合いませんでした。

## 設定をエクスポートしてインポート → できた
[File] - [Export Settings]でエクスポートする項目を選んでください。コードのタブやインデントの設定はCode style schemesあたりです。

![export settings](http://farm9.staticflickr.com/8377/8472862912_b3322f5717.jpg)

[File] - [Import Settings]でエクスポートしてきたjarを指定してください。このjarをチーム内で共有しましょう。

## IntelliJ Configuration Server Plugin
上記の方法はチーム内での設定の共有に使いますが、1人の開発者が複数のPC間でIDEの設定を共有したいときに便利なプラグインがあります。それが[IntelliJ Configuration Server Plugin](http://devnet.jetbrains.com/docs/DOC-1143)です。

1. JetBrainsのアカウントを作る
2. プラグインをインストールする
3. ログインする
4. 同期できるか確かめる

### JetBrainsのアカウントを作る

http://account.jetbrains.com/

このためだけにアカウントを作りましたが定期的に送られてくるNews Letterがためになってます。

### プラグインをインストールする

[Settings] - [Plugins]でIntelliJ Configuration Serverを探してインストールしてください。

### ログインする

WebStormを再起動するとログイン窓が出てきます。先ほど作成したアカウントID/PASSを入力してください。
WebStormが起動して、ステータスバーに緑色のアイコンが出ればログイン成功です。
![loginok](http://farm9.staticflickr.com/8093/8472864340_db3ffbb9f1_o.png)

### 同期できるか確かめる

今回はマシンを初期化したという設定でWebStormを再インストールしてちゃんと設定が同期できてるか確かめました。
なので、WebStorm.appだけでなく設定ファイルを削除しました。

```Bash:
$ cd; find . -name "*WebIde*"
./Library/Application Support/WebIde50
./Library/Application Support/WebIde60
./Library/Caches/WebIde60
./Library/Logs/WebIde50
./Library/Logs/WebIde60
./Library/Preferences/WebIde50
./Library/Preferences/WebIde60
```

再インストール後の初期状態の設定画面
![initial](http://farm9.staticflickr.com/8112/8471772215_86622210b6_c.jpg)

もう一度プラグインをインストールしてログインした後の設定画面
![loginok](http://farm9.staticflickr.com/8233/8471772879_fdf44ab48c_c.jpg)

同期できた！
[Windows 8] 「通知(右上隅)」(Notification)　をタッチ操作で消したいとき

右上に表示される「通知」、タッチ操作で消したいときは、画面端（右）にスワイプです！

簡単！◖|･ω･|◗♪

思わずタッチすると、そのアプリを開いてしまうんですよね～
NSURLConnection sendAsynchronousRequestをリトライ機能付きでリクエストする

今回も線形反復のサンプルです。

NSURLConnectionを何度かリトライ込みで記述してみます。

```
@interface DownloadUtility : NSObject
+ (void)downloadAndRetryWithURL:(NSURL *)url retryCount:(int)retryCount completion:(void(^)(NSURLResponse *response, NSData *data))completion failue:(void(^)())failure;
@end
@implementation DownloadUtility
+ (void)downloadAndRetryWithURL:(NSURL *)url retryCount:(int)retryCount completion:(void(^)(NSURLResponse *response, NSData *data))completion failue:(void(^)())failure
{
    completion = [completion copy];
    failure = [failure copy];
    
    NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:5];
    [NSURLConnection sendAsynchronousRequest:request
                                       queue:[NSOperationQueue mainQueue]
                           completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
     {
         if(error)
         {
             if(retryCount > 0)
             {
                 NSLog(@"retry");
                 [DownloadUtility downloadAndRetryWithURL:url
                                               retryCount:retryCount - 1
                                               completion:completion
                                                   failue:failure];
             }
             else
             {
                 if(failure)
                     failure();
             }
         }
         else
         {
             if(completion)
                 completion(response, data);
         }
     }];
}
@end


    //呼び出し側
    [DownloadUtility downloadAndRetryWithURL:[NSURL URLWithString:@"http://www.google.co.jp"]
                                  retryCount:5
                                  completion:^(NSURLResponse *response, NSData *data)
    {
        NSLog(@"complete!");
    } failue:^{
        NSLog(@"failure...");
    }];
```

呼び出し側が非常にシンプルになります。

簡単なフローチャートです。
ただこのコードはフローチャートとの乖離が激しいです
https://cacoo.com/diagrams/wveKhJQz9S00oIMG
Linuxのハードディスク要領がいっぱいになった時に使ったコマンド


まず大まかな要領使用率を把握

```
#パーティション別のディスク使用量を表示
df -h
```

パーティション別である程度の要領が多そうなディレクトリを調べ、そこに移動してから下記のコマンド

```
# ディレクトリ別の要領を出力させ、多いものだけを表示
sudo du -m | sort -n | tail
```

```
# 要領が多いファイルを特定
ls -lah
```

特定したらそれを削除なり移動なりさせればOK
Viewをパスに沿ってアニメーションさせる

Viewに複雑な動きを要求されたことはないですか。
そういう時に複雑な動きを簡単に実現させる方法を紹介します。

下記よりPathAnimation.javaをダウンロードし、プロジェクトにインポートします。
- https://github.com/coocood/PathAnimation

Activityに以下のように書けばViewがパスに沿ってアニメーションします。
- パスはPathクラスのインスタンスに設定していきます。

```java
Path path = new Path();
path.moveTo(0, 0);
path.addArc(new RectF(120, 63, 190, 127), 180, 180);
PathAnimation animation = new PathAnimation(path);
animation.setRepeatCount(1);
animation.setDuration(1000);
view.startAnimation(animation);
```

アニメーションの時間や繰り返し回数はPathAnimationクラスに設定します。これでかなり複雑な動きもあらかじめパスとして与えるだけで実現できるようになります。
Windowsでアクセス権をいじるときはicaclsコマンドを使う

Windows周りでアクセス権に関するプログラムを書くときはicaclsコマンドを使う。
例としてはフォルダ内にある全てのファイルのhogeユーザのアクセス権を拒否したいときは。

icacls * /deny hoge:F

のように書く。
cartonでライブラリ管理してるperlプロジェクトでvimにパスを通す

http://qiita.com/items/abfb9f2664ee0a93b82e

https://github.com/walf443/perl-local-lib-path.vim
を使えば以下のことをする必要はなくなります。

------------------------------

path固定だったりすると、プロジェクト内の他の人が使えなかったりリポジトリ内にコミットできなかったりして悲しいので、pathを切り離してみました

```vim:.local.perl.vimrc
function! l:set_path_directory()
    let target_dir = expand("%:p:h")
    let project_root = substitute(target_dir, "lib/.*", "", "")
    let libdir = project_root . "/lib"
    let localperl5dir = project_root . "/local/lib/perl5"
    let localperl5archdir = project_root . "/local/lib/perl5/darwin-2level"
    let perlbrewdir = $HOME . "/perl5/lib/perl5"
    let perlbrewarchdir = $HOME . "/perl5/lib/perl5/darwin-2level"
    execute "setlocal path =" . libdir
    execute "setlocal path +=" . localperl5dir
    execute "setlocal path +=" . localperl5archdir
    execute "setlocal path +=" . perlbrewdir
    execute "setlocal path +=" . perlbrewarchdir
endfunction

call l:set_path_directory()
```

perlbrewのパスとか、OSX限定になっているので、その辺もいい感じにまとまっているcarton.vimつくりたいけど、今はちょっと時間ないのですが、とりあえずまぁこんな感じで便利になります。
WYSIWYGエディタで書いたHTMLをメール送信する時のタグ除去と実体参照文字変換


WYSIWYGエディタで書いたHTMLをメールでも内容を通知することがあったので、strip_tagsでタグだけ除去してたら、実体参照文字がまざったまま送信されちゃってました。

これも変換するなら次のようなコードを。

```php
$before = '<p>Test&nbsp;Foo</p>'; // これを　"Test Foo" にしたい

$strip = strip_tags($before);
$after = html_entity_decode($body, ENT_QUOTES, 'UTF-8');
```

これで　$afterが Test Fooになる。
rakeのruleをもっと柔軟に使う

rakeにはtaskやfile以外に、ruleという定義が使えます。簡単に言うとmakeのサフィックスルールで、こういうファイルだったら、こういうファイルにしますよ、という正しくルールを定義するためのものです。以下簡単に使い方。

```ruby
rule '.o' => '.c' do |t|
  sh "gcc -o #{t.name} #{t.source}"
end
```

上記は「".o"で終わるタスク名（ファイル名じゃない！）が与えられ、そのタスク名の".o"を".c"に置き換えたものをソースファイルとし、そのソースファイルが存在するならタスクを実行する」という意味になります。実際に実行してみた方が分かりやすいですね。

```
$ ls src
hello.c
$ rake --rules src/hello.o # --rulesオプションをつけると実際どうやってruleが解決されているか分かる
Attempting Rule src/hello.o => src/hello.c
(src/hello.o => src/hello.c ... EXIST)
gcc -o src/hello.o src/hello.c
$ rake --rules src/world.o
Attempting Rule src/world.o => src/world.c
(src/world.o => src/world.c ... FAIL)
rake aborted!
Don't know how to build task 'src/world.o'

(See full trace by running task with --trace)
```

これ、パッと見ると、拡張子でしか定義できないように見えます。実は正規表現を与えることが出来るので、そうすれば自在にパターンを定義できます。

```ruby
rule %r{^dist/.+\.o} => '%{^dist,src}X.c' do |t|
  sh "gcc -o #{t.name} #{t.source}"
end
```

```
$ rake --rules dist/hello.o
Attempting Rule dist/hello.o => src/hello.c
(dist/hello.o => src/hello.c ... EXIST)
gcc -o dist/hello.o src/hello.c
```

ちなみに変換方法に指定されている"%{^dist,src}X"はpathmapという仕組みで、"%X"だけ指定するとマッチしたタスク名をファイル名と見立て、「拡張子を取り除いた文字列」を意味し、"%{正規表現,置換文字列}X"とすると、「拡張子を取り除き、正規表現にマッチした文字列を置換文字列に置き換えた文字列」となります。ぐっちゃぐちゃですね。まあ上記の例を見ていただければと思います。

ちなみに変換方法にはProcのインスタンスを与えることが出来るので、そちらを与えると自由自在に変換できますね。

ちょっと前にruleについて調べていたら、なかなか融通効かないなーと思っていましたが、正規表現とProcを使えばやりたい放題でした。
MacVimをTerminal標準のVimとしてインストールする


[The best way to make MacVim's vim (console, not mvim) the default instead of Mac OS X's vim? - Super User](http://superuser.com/questions/334252/the-best-way-to-make-macvims-vim-console-not-mvim-the-default-instead-of-mac)

上記サイトより、
以下のようにインストールすると良い。

```sh:
brew install macvim --override-system-vim
```
GoogleAnalyticsを使ったメールマガジン等からのトラフィック分析

GoogleAnalyticsのカスタムキャンペーンを利用することで、
リファラーなしの遷移や、出稿した有料のWeb広告からのトラフィック分析を
することができる。

この機能はURLクエリパラメータ上に`utm_campaign`や`utm_medium`等
を含めることで使えるようになる。

Qiitaのメールマガジン上のURLをクリックした際にも、utm_campaign等が付与されていますね。

AdWordsへ出稿した場合はこれらのパラメータが自動で付与されます。

http://support.google.com/analytics/bin/answer.py?hl=ja&answer=1033863

上記URLの例に記載されている

`http://www.example.com/?utm_campaign=spring&utm_medium=email&utm_source=newsletter1`

がクリックされた場合、GoogleAnalyticsには以下の`2.`が記載される。
(GoogleAnalytics上で[トラフィック]=>[参照元]=>[キャンペーン]と選択)

![Example1](http://kengos.github.com/images/qiita/ga_02.png)

設定可能なパラメータ

* 必須: `utm_source`,`utm_medium`,`utm_campaign`
* オプション: `utm_term`, `utm_content`

`utm_content`は、メールマガジン等で2箇所以上同一のページヘ遷移するURLが
設定されている場合、`utm_content=imagelink`, `utm_content=textlink`などのように
設定する。
この場合、画像リンクの場合のクリック数、テキストリンクの場合のクリック数を分析できるようになる。

## 雑記

自社サイトの特定領域に広告掲載スペースを用意する場合においては、
上記パラメータを付与したURLが自動発行されるようにするととても親切になる。

また、検索キーワードに連動した広告掲載スペースを作成する場合は、
`utm_term`が設定されたURLへ遷移させてあげると良い。

また、広告へ出稿する際に、上記のような仕組みがないサイトの場合は、ランディングページのURLに`utm_campaign`等のパラメータを付与したものを遷移先として指定してあげる事で
きちんと広告の効果分析ができるようになる。

Twitter等へつぶやく場合においても、(一応ソーシャル分析の機能がAnalyticsについているが)
以下のようにすると、よいかもしれない。

* `utm_medium=twitter`
* `utm_campaign=social`
* `utm_source=tweet001` : つぶやきごとにユニークにする

Facebook等の場合は`utm_medium=facebook`とし、`utm_campaign=social`としておくと、キャンペーン: `social`での効果分析が可能となる。
(広告出稿と手間をかけたTwitterやFacebookでの宣伝活動どちらが効果的かなどの分析)
Parsecのソースちら見


> 教科書的なパーサーと言えばStateT s []モナドをよく見るけど、今のParsecって全然そんな雰囲気ないんだなあ。
> https://twitter.com/hiratara/status/297541496217927683

モナド本体は継続モナド×4的な構造をしている。継続となる関数を4本渡せば、結果を得ることができる。

```haskell:Text-Parsec-Prim.html
newtype ParsecT s u m a
    = ParsecT {unParser :: forall b .
                 State s u
              -> (a -> State s u -> ParseError -> m b) -- consumed ok
              -> (ParseError -> m b)                   -- consumed err
              -> (a -> State s u -> ParseError -> m b) -- empty ok
              -> (ParseError -> m b)                   -- empty err
              -> m b
             }
```

起動用に用意されている関数では、最終的にどの継続を経由して結果を得たのかわかるようにラップをしている。ラップは各2項目×2段階。

```haskell:Text-Parsec-Prim.html
runParsecT :: Monad m => ParsecT s u m a -> State s u -> m (Consumed (m (Reply s u a)))
runParsecT p s = unParser p s cok cerr eok eerr
    where cok a s' err = return . Consumed . return $ Ok a s' err
          cerr err = return . Consumed . return $ Error err
          eok a s' err = return . Empty . return $ Ok a s' err
          eerr err = return . Empty . return $ Error err
```

ラップの1段階目。パーサが入力を消費したか否か。

```haskell:Text-Parsec-Prim.html
data Consumed a  = Consumed a
                 | Empty !a
```

ラップの2段階目。パースが成功したか否か。これで2*2=4通りのパターンを表せた。

```haskell:Text-Parsec-Prim.html
data Reply s u a = Ok a !(State s u) ParseError
                 | Error ParseError
```

逆にこのラップされた型から`ParsecT`型を復元する関数も定義されている。ラップされた型を展開して、4つ渡された継続のどれをキックするか判別するだけ。

```haskell:Text-Parsec-Prim.html
mkPT :: Monad m => (State s u -> m (Consumed (m (Reply s u a)))) -> ParsecT s u m a
mkPT k = ParsecT $ \s cok cerr eok eerr -> do
           cons <- k s
           case cons of
             Consumed mrep -> do
                       rep <- mrep
                       case rep of
                         Ok x s' err -> cok x s' err
                         Error err -> cerr err
             Empty mrep -> do
                       rep <- mrep
                       case rep of
                         Ok x s' err -> eok x s' err
                         Error err -> eerr err
```
ActiveRecordで複数レコード、BULK INSERTする方法とパフォーマンスについて

あるテーブルに対して複数のレコードを同時に登録したいことがあります。
このときに登録する数だけINSERTを発行するのはあまり効率がよくありません。
そこでBULK INSERTと言われる単発のSQLで一括登録する方法がよく使われます。

## BULK INSERTとは

単純なbooksというテーブルを使い、BULK INSERTはどういうものか確認する。

```sql:books.sql
CREATE TABLE `books` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
```

複数のINSERTを発行する。

```sql:insert.sql
INSERT INTO books (columns) VALUES (values);
INSERT INTO books (columns) VALUES (values);
INSERT INTO books (columns) VALUES (values);
```

BULK INSERTで一括登録する。

```sql:bulkinsert.sql
INSERT INTO books (columns) VALUES (values), (values), (values);
```

それぞれのSQLでこのような違いがありますが、登録されるレコード結果は同じになります。


## RailsでBULK INSERTを使う

RailsのActiveRecordでBULK INSERTを使うには、**activerecord-import**という大変便利なgemがあるので利用させていただきます。
[activerecord-import](https://github.com/zdennis/activerecord-import)

使い方はとても簡単で、登録するレコード（model）のインスタンスをすべて配列にいれて、クラスメソッドのimportにそれを渡すだけです。

```ruby:activerecord-import.rb
books = []
10.times do |i| 
  books << Book.new(:name => "book #{i}")
end
Book.import books
```

これで10回分のINSERT文が1つにまとめられます。


## パフォーマンスを検証する

1度に登録する数を100レコードにし、それを100回繰り返す処理で計測してみる。


Railsの通常処理でINSERTを繰り返すパターン。

```ruby:insert.rb
100.times do |i|
    100.times do |_i|
      Book.create! :name => "book_#{i}_#{_i}"
    end
 end
```

```sql:insert.sql
BEGIN;
INSERT INTO books (...) VALUES (...);
COMMIT;
BEGIN;
INSERT INTO books (...) VALUES (...);
COMMIT;
BEGIN;
INSERT INTO books (...) VALUES (...);
COMMIT;
...
```


activerecord-importを使って、BULK INSERTするパターン。

```ruby:bulkinsert.rb
100.times do |i|
  books = []
  100.times do |_i|
    books << Book.new(:name => "book_#{i}_#{_i}")
  end
  Book.import books
end
```

```sql:bulkinsert.sql
INSERT INTO `books` (...) VALUES (...), (...), (...), ...;
```


Railsの通常パターンでは毎回COMMITされてしまうので、TRANSACTIONを使ったパターンも追加する。

```ruby:transaction.rb
100.times do |i|
  ActiveRecord::Base.transaction do
    100.times do |_i|
      Book.create! :name => "book_#{i}_#{_i}"
    end
  end
end
```

```sql:transaction.sql
BEGIN
INSERT INTO books (...) VALUES (...);
INSERT INTO books (...) VALUES (...);
INSERT INTO books (...) VALUES (...);
...
COMMIT
```


### 計測結果

| Insert        | BulkInsert    | Transaction   |
|:---------------:|:---------------:|:---------------:|
| 10.6876sec | 4.0554sec | 7.1316sec |

それぞれ7回計測し、1番速いものと遅いものを除外した5回平均のデータ。
**実行環境** MacBookPro, Core i7 2.9GHz, SSD256GB, Mem8GB


単純なテーブルでの比較ですが、BULK INSERTを使うとパフォーマンスは大きく向上しました。
複数レコードを登録するときは、ぜひBULK INSERTで処理しましょう！
[phpmig]PHPでマイグレーション

# phpmig

簡単に実行できる、ベンダーやフレームワークへの依存の少ないPHPのマイグレーションツール
(READMEから意訳

ここに書いてあるメモは全部READMEに書いてある

後々確実にお世話になるので今のうちに軽く触れてめもめも

## 参考

* [PHPで使えるDBマイグレーションツール phpmig - エンジニアきまぐれTips](http://d.hatena.ne.jp/okinaka/20120514/1336951360)

* [https://github.com/davedevelopment/phpmig](https://github.com/davedevelopment/phpmig)

## インストールから初期化まで

PEARかcomposerを利用してphpmigをインストール

composerでのインストールがベストらしい

### composerでインストール

プロジェクト用にローカライズされたphpmigが利用できるようになる(直訳

```
$ cd /path/to/project
$ echo <<EOT > composer.json
{
    "require": {
        "php": ">=5.3.1",
            "davedevelopment/phpmig": "*"
    },

        "config": {
            "bin-dir": "bin/"
        }
}

$ wget http://getcomposer.org/composer.phar
$ php composer.phar install
```

### PEARでインストール

PEAR 1.0用のパッケージはないらしい

    $ sudo pear channel-discover pear.atstsolutions.co.uk
    $ sudo pear install atst/phpmig-alpha


## 初期化

PEARでインストールした場合は_bin/phpmig_は_phpmig_に置き換わる

    $ cd /path/to/project
    $ phpmig init

簡単な動作確認を兼ねてバージョンチェック

    $ bin/phpmig --version

## 簡易チートシート

マイグレーション実行時はup()メソッド、ロールバック時にはdown()メソッドが呼び出される

コマンド実行前後に_$ bin/phpmig status_で確認しながらやると感覚が掴みやすいかもしれない

* マイグレーション用の雛形を生成

./migrationディレクトリに作成される

```
$ bin/phpmig generate AddRatingToLolCats ./migrations/
```


* ステータス確認

_down_: 未実行
_up_: 実行済み

```
$ bin/phpmig status
```


* マイグレーション実行

/migrationディレクトリ内のファイルが順次実行される

```
$ bin/phpmig migration
```


* 1つ戻る

```
$ bin/phpmig rollback
```


* 全て戻る

```
$ bin/phpmig rollback -t 0
```

* 指定のMigration IDの**完了時点**まで戻る

```
$ bin/phpmig rollback [MigrationID]
```


* 指定のMigration IDのみを_up_ or _down_

```
$ bin/phpmig [up|down] [MigrationID]
```

## データベースの接続とか

bin/phpmig initで生成される_phpmig.php_の$container['db']にDBアダプターを入れてやるとmigrations/内のクラスでDBが扱えるようになる
他にも、$containerの配列の要素にオブジェクトなりを入れればmigrations/内で使えるようになる

下の例で行くと、migrations/内で$container['db']や$container['app']が使えるようになる

```
<?php //phpmig.php

$application = new Zend_Application(
    APPLICATION_ENV,
    $app_ini
);

use \Phpmig\Adapter,
    \Phpmig\Pimple\Pimple;

$container = new Pimple();

$container['app'] = $application;
$container['db'] = Zend_Db::factory($adapterName, $params);

$container['phpmig.adapter'] = $container->share(function () {
    // replace this with a better Phpmig\Adapter\AdapterInterface 
    return new Adapter\File\Flat(__DIR__ . DIRECTORY_SEPARATOR . 'migrations/.migrations.log');
});

$container['phpmig.migrations'] = function() {
    return glob(__DIR__ . DIRECTORY_SEPARATOR . 'migrations/*.php');
};

return $container;
```

migrations/内のクラスからphpmig.phpの$containerを呼び出すには、$this->getContainer()を利用する


```
<?php // ./migrations/20130217150827_AddSomeTableMigration.php

use Phpmig\Migration\Migration;

class AddSomeTableMigration extends Migration
{
    /** 
     * Do the migration
     */
    public function up()
    {   
        $container = $this->getContainer();
        $container['db']->query('CREATE TABLE IF NOT EXISTS some_table ( id int )');
    }   


    /** 
     * Undo the migration
     */
    public function down()
    {   
        $container = $this->getContainer();
        $container['db']->query('DROP TABLE IF EXISTS phpmig_test');
    }
}
```
C#でRubyっぽいデバッグ表示(List編)


## List (Rubyでいう所のArray)
Rubyの場合

```ruby:list.rb
list = [1, 2, 3]
puts list
```

C#の場合は[LINQ](http://msdn.microsoft.com/ja-jp/library/vstudio/bb397927.aspx) , [コレクション初期化子](http://www.atmarkit.co.jp/fdotnet/dotnettips/721dictinit/dictinit.html), [String.Join](http://msdn.microsoft.com/ja-jp/library/dd783876.aspx)  を組み合わせると近い事が出来る。

```csharp:List.cs
using System;
using System.Collections.Generic;
using System.Linq;

var list = new List<int>() { 1, 2, 3 };
Console.WriteLine("[" + String.Join(", ", from v in list select v) + "]");
```

出力はどちらも以下のようになる。

```
[1, 2, 3]
```

## おまけ: Rubyで`p`や`inspect`を使わずに自力で書く場合
C#が頑張ってる感じが伝わると思う。

```ruby:jiriki.rb
puts "[" + list.map{|v| v}.join(", ") + "]"
```
静的言語でここまで出来るのは結構すごいなぁと思う。

## C#でRubyっぽいデバッグ表示一覧
* [List(Array)](http://qiita.com/items/5c67c6a9766712851fcc)
* [Dictionary(Hash)](http://qiita.com/items/b7f0765537c8f0212f78)
Boost.Coroutineでitertools.permutations

[こいつ](http://docs.python.jp/3/library/itertools.html#itertools.permutations)をC++で書いたもの。
糞汚いコードだがとりあえずMSVCで動いた。

```cpp
#include "stdafx.h"
#include <functional>
#include <boost/coroutine/all.hpp>
#include <iostream>
#include <iterator>
#include <numeric>
#include <algorithm>
#include <vector>
#include <boost/bind.hpp>

template<typename T>
void iter_permutations(typename boost::coroutines::coroutine<std::vector<T>()>::caller_type& yield, std::vector<T> pool){
	const size_t n = pool.size();
	const size_t r = n;
	if(r > n)return;
	std::vector<size_t> indices(n);
	std::iota(indices.begin(), indices.end(), 0);
	std::vector<size_t> cycles(r);
	std::iota(cycles.begin(), cycles.end(), n-r+1);
	std::reverse(cycles.begin(), cycles.end());
	{
		std::vector<T> ret(r);
		ret.assign(pool.begin(), pool.begin()+r);
		yield(ret);
	}
	while(n){
		auto fl = true;
		for(int i = r - 1; i >= 0 ; --i){
			cycles[i] -= 1;
			if(cycles[i] == 0){
				std::vector<size_t>::iterator tmp = indices.begin();
				std::advance(tmp, i);
				auto tmp_val = *tmp;
				indices.erase(tmp);
				indices.push_back(tmp_val);
				cycles[i] = n - i;
			}else{
				auto j = cycles[i];
				auto k = n - j;
				boost::swap(indices[i], indices[k]);
				{
					std::vector<T> ret(r);
					for(size_t m = 0; m < r; ++m){
						ret[m] = pool[indices[m]];
					}
					yield(ret);
				}
				fl = false;
				break;
			}
		}
		if(fl){
			break;	
		}
	}
}


int _tmain(int argc, _TCHAR* argv[])
{
	using namespace std;

	vector<int> a(3);
	iota(a.begin(), a.end(), 0);
	boost::coroutines::coroutine<std::vector<int>()> mycol(boost::bind(iter_permutations<int>, _1, a));

	while(mycol){
		auto b = mycol.get();
		copy(b.begin(), b.end(), ostream_iterator<int>(cout, ","));
		cout << endl;
		mycol();
	}
	return 0;
}
```
Bundlerで使ってるgemに脆弱性がないかチェックするツール


最近、railsやらjsonやらの広く使われているgemに頻繁に脆弱性が見つかってます。[bundler-audit](https://github.com/postmodern/bundler-audit
)というgemを使うと、簡易的ですが既知の脆弱性があるgemをGemfile.lockで参照していないかをチェック出来ます。

```console
$ gem install bundler-audit
$ bundle-audit 
Name: rack
Version: 1.4.3
CVE: 2013-0263
Criticality: High
URL: http://osvdb.org/show/osvdb/89939
Title: Rack Rack::Session::Cookie Function Timing Attack Remote Code Execution 
Solution: upgrade to ~> 1.1.6, ~> 1.2.8, ~> 1.3.10, ~> 1.4.5, >= 1.5.2

Name: rails
Version: 3.2.11
CVE: 2013-0276
Criticality: Medium
URL: http://direct.osvdb.org/show/osvdb/90072
Title: Ruby on Rails Active Record attr_protected Method Bypass
Solution: upgrade to ~> 2.3.17, ~> 3.1.11, >= 3.2.12

Unpatched versions found!
```

https://github.com/postmodern/bundler-audit/tree/master/data/bundler/audit

上のソースを見てもらえればわかるのですが、マニュアルでデータが管理されてるだけなので、本当の意味で安全かを確認することは当然できないですが。。。
オフラインリアルタイムどう書く第8回の参考問題をRubyで解く

問題は
http://nabetani.sakura.ne.jp/hena/ord8entco/

```ruby
BIN=
[
['000','t'],
['0010','s'],
['0011','n'],
['0100','i'],
['01010','d'],
['0101101','c'],
['010111','l'],
['0110','o'],
['0111','a'],
['10','e'],
['1100','r'],
['1101','h'],
['111',nil]
]


def solve(q)
  qbin = q.split('').map{|e| ('000'+e.to_i(16).to_s(2))[-4..-1].reverse}.join
  result = ''
  bits = 0
  while qbin.size > 0
    is_valid = false
    BIN.each do |pat,c|
      if qbin.start_with? pat
        bits += pat.size
        return "#{result}:#{bits}" if c.nil?
        result += c
        qbin = qbin[pat.size..-1]
        is_valid = true
      end
    end
    return "*invalid*" unless is_valid
  end
  "*invalid*"
end

DATA.readlines.each do |line|
  no,q,a = line.chop.split(/\s+/)
  ans = solve(q)
  print no + "\t" + ans
  puts ans == a ? 'o' : 'x'
end

__END__
0	16d9d4fbd	ethanol:30
1	df	e:5
2	ad7	c:10
```
thin と rack-reverse-proxy でサクっと https リバースプロキシ 

開発(デバッグ)中のローカルサーバーを https で動かしたいだけなので、Apache や Nginx 面倒な人用。

~~~sh
gem install rack-reverse-proxy
~~~

~~~ruby:config.ru
require 'rack'
require 'rack/reverse_proxy'

use Rack::ReverseProxy do 
  reverse_proxy '/', ENV['TO']
end
run Proc.new{}
~~~

まずは SSL なしでテスト。 localhost:8082 -> localhost:8081

~~~:sh
TO=http://localhost:8081 thin -p 8082 start
~~~

OK だったら、 https://devcenter.heroku.com/articles/ssl-certificate-self などを参考にオレオレ証明書を config.ru と同じディレクトリに生成。

この場合は https の標準ポート `443` は特権ポートなので `rvmsudo` で実行。

~~~:sh
rvmsudo env TO=http://localhost:8081 thin --ssl -p 443 start
~~~
東京Ruby会議10（3日目）参加レポート

<br>
<h3 style="text-align:right">izuta.hiroyuki</h3>
<br>

## 東京Ruby会議とは？
[公式サイト](http://tokyo10.rubykaigi.info/)より

```
「東京Ruby会議10」は東京地域で10個目となる国内最大級の地域Ruby会議です。

東京圏で在住・活動している方を中心に会期二日間のべ800人規模で一同に会し、日々の活動や技術についての発表、議論、参加者同士の交流を行う大規模な催しカンファレンスです。

Rubyに興味がある人たちで集まり、日頃行なっていることや普段活用している技術についての話をして、2013年の活動をブーストしていきましょう！
```
<br>


## セッション概要
<br>
#### 1.Railsプログラマーの日常 - @joker1007さん
#### 2.沖縄に集まってRails Hackathonをやってみた。 - @yasulabさん
#### 3.Introduction to Ember.js - @ursmさん
#### 4.RubyMotionではじめる！楽しいiOSアプリ開発 - @satococoaさん
#### 5.巻き込まれ型人間のボッチ脱出計画 - @sugamasaoさん
#### 6.自分の道具を知る - @ryopekoさん 
<br><br>
<br>


## 1.Railsプログラマーの日常　　　@joker1007さん
### プログラマ歴１年でこれまでやってきたこと
 - 要件定義
 - 入力と出力を考える
 - 概要設計、モデリング、UML、ペーパープロトタイプ、アーキテクチャ設計

### 大事なこと
メンタルモデル（設計）と実装の一致
モデリングの技術と実装の技術の双方が必要
まずモデルから考える

### 参考になった書籍
　★Rubyによるデザインパターン
　★リファクタリング：Rubyエディション
　★継続的デリバリー

### Q&A

Q.RubyistはJOJOを読むべきか？
A.Rubyistに限らずエンジニアは全員読むべき。

<br>
## 2.沖縄に集まってRails Hackathonをやってみた。 @yasulabさん
### okinawa.rbについて
毎週集まって海辺でコーディングするコミュニティ
<br>
### 台風そんとは？
- 沖縄は台風が多いので、家にこもることも多い。それを逆手にとり、ハッカソンをやってエンジニアのモチベーションをあげよう！という取組み。
- 沖縄が暴風域にはいったらハッカソンが開始される
<br>

### 沖縄ハッカソン成果発表会
優勝：**ScreenXTV**

```
ローカルのターミナル画面をWEB上に公開できるサービス。
gemとして配布されている。

`gem install screenxtv`

Railsとnode.jsで構成
ペアプロなどで効果的
```

### 懇親会

ギークハウス沖縄　→　そのまま泊まれる

### Q&A

Q.沖縄はRubyやRailsの開発案件（企業）が少ないのでは？
A.その通りだが、Remote環境で仕事している人はいる。
<br><br>

## 3.Introduction to Ember.js   @ursmさん
### Ember.jsとは？
- Client-side MVC Framework
- 最近は動的でリッチなWebアプリケーションが台頭している
- それをjQueryでごりごり作るのは結構大変


### Client-side MVCの例
- Backbone.js
- AnglarJS
- Ember.js

<br>
### jQueryで作る場合
　要素にidをつけてそれを加工する
　⇒徐々に、何をしてるかわからなくなる
<br>

### Ember.jsで作る場合
- DOMを操作するコードが無い

<br>
### Ember.jsでの制作物
　IRCに変わる社内チャットシステムを探したが、どれも微妙だったので自作した。
<br><br>

## 4.RubyMotionではじめる！楽しいiOSアプリ開発   @satococoaさん
### RubyMotionとは？
- RubyでiOSアプリが作れるフレームワーク
- 買い切り有償。(¥18,417)

### Live Cording
- タスク管理アプリを作ってくれました
<br>

### Q&A
Q.RubyMotionにサポートは付くのか？
A.オプションで付けることが可能。
<br>
　
## 5.巻き込まれ型人間のボッチ脱出計画  @sugamasaoさん
### セミナー等でボッチの人が声をかけてもらうのを待つ（=待ちガイル）になるためには？
- コードを書こう
- ブログを書こう
- 勉強会に参加しよう
<br><br>

### コードを書こう
- [ひばりやさんのスライド](https://speakerdeck.com/hibariya/code)が大変参考になる
- 自分のためのCodeを書こう
- 自分に必要なものを自分でつくる。これが大事。
<br><br>


### 勉強会に行こう
どういった勉強会に行けばよいのか？
　⇒　例えば、100人規模の勉強会は避ける(交流が難しい)
　⇒　部屋の片隅でビール片手に「ビールなう」とつぶやくはめになる
　⇒　10数人くらいのヤツがベスト。テーマはなんでもよい。
<br>
### ブログを書こう
- 読み返す、される事を考えるとストック型が良い。
- メモでも良い。自分のメモが、人の助けになることも。
- 最近だとQiitaとか@ITでも良いかも
<br><br><br>


## 6.自分の道具を知る　 @ryopekoさん

### 言語とライブラリについて
最近はgemのドキュメントがしっかりしてるのも多いが、仕事ではRailsによらない技術や知識が必要
開発において重要なこと

- 保守性
- テストのしやすさ
- DRY


エンジニアが学ぶべきことは沢山ある。サバンナ状態。
<br>


### サバンナを生きる技術

　⇒　ドキュメントを読まない(当てにしすぎない)

<br>

### 人がつくるものは２つある
　１．コード
　２．ドキュメント

　Q.仕事でドキュメントをしっかりと書いてると自信を持って言える人はいるか？ (挙手)
　⇒ほとんどいない

　**仕事ですらドキュメントをきちんと用意しないのに、それをオープンソースに求めるのはおかしい**

　せめて、自分が使ってる部分はコードを読む。
　コードを読む力、書く力の両方が身につく。
　コードもドキュメントだと思え。

　※ただし、自動生成されるドキュメントは信頼に足る
  

### 副産物
- ドキュメントにない使い方や引数を発見することがある
- スーパーハッカーが書いた**生きたコード**を読める
- **生きたデザインパターン**の用例を見る 

### まとめ
 　みんなもっとコードを読もう！

<br>

## 個人的な感想 - 東京Ruby会議に初参加してみて
- Rubyistがまだ少ないためか、集まる人の仲間意識が強い
- モチベーションがあがった
- 技術力がなくても、自分から発信していこうと思った
- 今回ぼっちで終わってしまったので、友達をつくりたい
git logでコミットの差分の中身で絞り込む


git logの検索オプションとしては、コミッタ名で絞り込む`--author`やコミットメッセージの内容で絞り込む`--grep`が有名だと思いますが、各コミットの差分で追加されたり削除された行の内容で絞り込む`-S`というオプションもあります。

似たようなコマンドとして、`git blame`もありますがこちらは現時点で存在する行が最後に更新されたリビジョンが分かるだけなので、`git log -S`の方が

* ある特定の内容が削除されたリビジョンを知りたい時
* ある特定の内容が更新されたリビジョン全てを知りたい時

といった場合に便利です。

## 使い方

```
$ git log -S"hogehoge"
```

このように指定すると、コミットの中で"hogehoge"という文字列を含む行が追加もしくは削除されたものだけで絞り込んでくれます。

もちろん、ある特定のファイルに対する変更だけを絞り込むこともできます。

```
$ git log -S"hogehoge" ./test.java
```

この場合だと、./test.javaというファイルの中でhogehogeという内容の差分があったリビジョンを表示してくれます。

その他、git logの他のオプションと組み合わせることも可能です。 
## tigと組み合わせると更に便利

tigコマンドでも`-S`オプションを使うことができ、かなり便利です。

※ tigについてはこの辺りを参照すると良いです。http://blog.yuyat.jp/archives/557

```
$ tig -S"hogehoge"
```

とやると、各コミットの変更内容の中に"hogehoge"を含むものだけをtigで表示してくれます。
tigでは各コミットの変更内容を見るのも簡単にできるので、変更内容を追いかけるのが素早く出来ます。

## まとめ

ある特定の内容の差分を含むリビジョンを知りたい場合は`git log -S`を使うのが吉。
tigと組み合わせると更に吉。
オフラインリアルタイムどう書く第8回の参考問題


オフラインでリアルタイムに「どう書く」をやるぬるいイベント：
http://atnd.org/events/36783
をまたやります。8回目です。

これまで同様参考問題を出します。
難易度と分量はこれを目安に。
参加予定の方は、何分で解けたとかいう情報を付けてくださると、本番用の問題の参考になりますので出来ればお願いします。

問題は「エントロピー符号」という難しそうな名前になってますが、内容は難しくないつもりです。
http://nabetani.sakura.ne.jp/hena/ord8entco/
におきました。

実装ができた方はこちらのコメント欄からリンクを張っていただくと見つけやすくて助かります。
ubuntu 11.10 にmecab, mecab-rubyをインストールする

以前セットアップを行った時はapt-getが全てに使えて楽に出来たのですが、`apt-get install mecab-ipadic`すると
`package 'mecab-ipadic' has no installation candidate`
と言われてしまい、困ったので少しうろうろしてしまいました。どうやらmecab-ipadic, mecab-ipadic-utf8の両方が現在利用不可能な状態らしく、自分でインストールする必要があるようです。
序に手順を忘れないようにメモしておきます。

###mecabのインストール

```bash
# mecab自体はapt-get出来る状態だったので、それを利用します。
$ sudo apt-get install mecab
$ sudo apt-get install libmecab-dev
# ipaの辞書ファイルを落としてきます
$ wget http://mecab.googlecode.com/files/mecab-ipadic-2.7.0-20070801.tar.gz
$ tar zxvf mecab-ipadic-2.7.0-20070801.tar.gz
$ cd mecab-ipadic-2.7.0-20070801/
# carsetにutf-8を指定します
$ sudo ./configure --with-charset=utf8
$ make
# 標準では別の辞書ファイルがインストールされるため、設定を編集してipadicに変更します。
$ sudo vim /etc/mecabrc
# setup時に'dicdir'でなく'dicrc'となっていたのだけどタイポかな…
- dicdir = /var/lib/mecab/dic/debian
+ dicdir = /usr/lib/mecab/dic/ipadic
$ sudo make install
```

これでmecab自体は利用可能な状態になります。terminal上で`mecab`を実行し、適応な日本語を入力するとパースしてくれます。

###mecab-rubyをインストール
毎回この作業をやるたびに「なんでgem install出来るようになってないんだろう…」と思うわけですが、まぁ。

```bash
# mecab-rubyは利用するmecabのバージョンを確認し、それに合わせたバージョンを利用するのが良いみたいです。
#今回のapt-getでは0.98がインストールされたので、それに合わせます。
$ wget http://mecab.googlecode.com/files/mecab-ruby-0.98.tar.gz
$ tar zxvf mecab-ruby-0.98.tar.gz
$ cd mecab-ruby-0.98/
# gemspecのバージョンが間違っていて気持ち悪いので直します。
$ vim mecab-ruby.gemspec
- s.version = '0.97'
+ s.version = '0.98'
$ gem build mecab-ruby.gemspec
$ gem install mecab-ruby-0.98.gem
```

これでrubyから利用可能になりました！後はGemfileに'mecab-ruby'とでも記述してNokogiriでパースしたコンテンツを形態素解析しようがTwitterのストリームを解析しようがご自由に！Yay!


####うろうろしたURL
[バージョン違いのmecab-rubyを共存させる with Homebrew ](http://qiita.com/items/2dfba4b23ab974240d38)
[mecabのインストールについて](https://forums.ubuntulinux.jp/viewtopic.php?id=13547)
[Linux Mint - Ruby で形態素解析 MeCab を使う！](http://www.mk-mode.com/octopress/2013/01/08/linux-mint-ruby-mecab/)
[MeCab: Yet Another Japanese Dependency Structure Analyzer](http://code.google.com/p/mecab/)
[Ubuntuで環境構築のメモAdd Star](http://d.hatena.ne.jp/christopher6/20111130/1322662557)
[Ubuntu 10.04にMeCabをインストールAdd Star](http://d.hatena.ne.jp/cupnes/20110201/1296574516)
[MeCab: Yet Another Part-of-Speech and Morphological Analyzer](http://mecab.googlecode.com/svn/trunk/mecab/doc/index.html)
Github.css in Stylus

## What is Stylus

Check this [page](http://learnboost.github.com/stylus/), it's well documented.

// Convert this http://softwaremaniacs.org/media/soft/highlight/styles/github.css
// to Github.styl
// For use with Hexo -- a node.js blog framework (it's awesome!)

Here you go:

```Github.styl
pre
  // Theme: GitHub (c) Vasily Polovnyov <vast@whiteants.net>
  // More theme here: http://bit.ly/b0uq5L
  code
    display: block
    padding: 0.5em
    color: #333
    background: #f8f8ff

  .comment
  .template_comment
  .diff .header
  .javadoc
    color: #998
    font-style: italic

  .keyword
  .css .rule .keyword
  .winutils
  .javascript .title
  .nginx .title
  .subst
  .request
  .status
    color: #333
    font-weight: bold

  .number
  .hexcolor
  .ruby .constant
    color: #099

  .string
  .tag .value
  .phpdoc
  .tex .formula
    color: #d14

  .title
  .id
    color: #900
    font-weight: bold

  .javascript .title
  .lisp .title
  .clojure .title
  .subst
    font-weight: normal


  .class .title
  .haskell .type
  .vhdl .literal
  .tex .command
    color: #458
    font-weight: bold

 .tag
 .tag .title
 .rules .property
 .django .tag .keyword
    color: #000080
    font-weight: normal

  .attribute
  .variable
  .lisp .body
    color: #008080

  .regexp
    color: #009926


  .class
    color: #458
    font-weight: bold


  .symbol
  .ruby .symbol .string
  .lisp .keyword
  .tex .special
  .prompt
    color: #990073


  .built_in
  .lisp .title
  .clojure .built_in
    color: #0086b3

  .preprocessor
  .pi
  .doctype
  .shebang
  .cdata
    color: #999
    font-weight: bold

  .deletion
    background: #fdd

  .addition
    background: #dfd

  .diff .change
    background: #0086b3

  .chunk
    color: #aaa

```
メモ：fluentでログの保存先にriakを使う

試しに動かして見たのでメモ

## riakのインストール
riakのインストールは前回の記事で。
[Ubuntuにriakインストールしたメモ](http://qiita.com/items/08c1776e1a0b72fab0e2)

## fluentのインストール
fluentはgemからインストールします。

``` $ sudo gem install fluentd ```

## fluentのriakプラグインをインストール

```
$ sudo gem install fluent-plugin-riak
```

## fluentがログ保存先にriakを使うように設定
まだ作ってないなら設定ファイル生成
``` $ sudo fluentd --setup ```

[githubのREADME.md](https://github.com/kuenishi/fluent-plugin-riak/blob/master/README.md)を参考にして、riakを使うように設定ファイルを編集

```/etc/fluent/fluent.conf
<match hoge_app.**>
  type riak

  buffer_type memory
  flush_interval 10s
  retry_limit 5
  retry_wait 1s
  buffer_chunk_limit 256m
  buffer_queue_limit 8096

  # pb port
  nodes 127.0.0.1:8087
</match>
```

nodesは自分の環境のRiakのホストとポートに。複数設定する場合はスペースで区切るようです。

## fluent起動
``` $ /usr/local/bin/fluentd ```

## 試しにログを保存してみる

試しにやるならfluent-catで試せるようです。

```
$ echo "{\"name\": \"shin\", \"age\":37}" | fluent-cat hoge_app.debug
```

## Rubyからログを保存してみる
[github](https://github.com/fluent/fluent-logger-ruby/blob/master/README.rdoc) にやり方が書いてあります。

```
$ sudo gem install fluent-logger
```

```
require 'fluent-logger'

log = Fluent::Logger::FluentLogger.new(nil, :host=>'localhost', :port=>24224)
log.post("myapp.access", {"agent"=>"foo"})
```

## 保存の確認
riakからキーのリストを取得してみます。

```
$ curl --insecure https://localhost:8098/buckets/fluentlog/keys?keys=true
```

キーは **"yyyy-mm-dd-uuid"** のようなフォーマットになっていました。

```
{"keys":["2013-02-13-c58a2fdf-04a0-41ff-8080-e25927c07c4d",
"2013-02-13-f2cc72df-fce4-4f47-87c0-81090c021f3d","2013-02-13-
de5b48ea-fb28-4022-9840-87e0953452e7",
....
```

キーから値を取得してみる

```
$ curl --insecure https://localhost:8098/buckets/fluentlog/keys/2013-02-13-f2cc72df-fce4-4f47-87c0-83090a023f3d
```

ひとつのキーに対して、複数のログがリストで保存されていました。

0.0.1の時はキーがTime.now.to_iしたものでしたが、0.0.2からは"yyyy-mm-dd-uid"フォーマットの文字列に変わりました。
まだしばらくは大きな仕様変更があるかもしれません。
ボタンの同時押しをできないようにする

ボタンを同時に押せてしまうと処理が複雑になりとても不便です。そこで、同時に2つ以上のボタンを押しても初めに押されたボタンの処理だけを実行する方法を紹介します。

## 初めにタッチした指を検出する
ViewGroup(LinearLayout, FrameLayoutなど)にはsplitMotionEventsという属性があります。この属性にfalseを指定することで、そのViewGroup内のボタンのMotionEventを一括で検出できます。

```xml:layout.xml
<LinearLayout 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:splitMotionEvents="false">
	<Button android:id="@+id/button1"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content" />
	<Button android:id="@+id/button2"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content" />
</LinearLayout>
```
```java:MainActivity.java
public void onCreate(Bundle savedInstanceState) {
	~ 省略 ~
	Button button1 = (Button)findViewById(R.id.button1);
	button1.setOnTouchListener(this);
	Button button2 = (Button)findViewById(R.id.button2);
	button2.setOnTouchListener(this);
}

public boolean onTouch(View view, MotionEvent event) {
	int touchedAction = event.getAction();
	Log.d("MainActivity", touchedAction);
}
```

このようにsplitMotionEventsにfalseを指定することで、LinearLayout内のボタンという範囲でMotionEventを検出することができます。そのため、LinearLayout内のボタンに1本目の指が触れた場合はMotionEventのACTION_DOWN、さらに1本目を触れたまま2本目を触れるとACTION_POINTER_DOWNがtouchedActionに入ります。

### 補足
splitMotionEventがtrueの場合(デフォルト)はボタンごとにMotionEventが検出されるため、button1とbutton2を同時に押してもそれぞれのtouchedActionにはACTION_DOWNが入ります。

## 初めに押された指の番号を取得する
初めの指か他の指かは検出できるようになりました。次に初めの指が離されたら処理を実行するため、初めの指の番号を覚えておく必要があります。

```java:MainActivity.java
private static final int INVALID_POINTER_ID = -1;
private static int mActivePointerId = INVALID_POINTER_ID;

public boolean onTouch(View view, MotionEvent event) {
	int touchedAction = event.getAction();
	if (touchedAction == MotionEvent.ACTION_DOWN) {
		mActivePointerId = me.getPointerId(0);
	}
}
```
今回は初めにタッチされた時に指の番号を覚える必要があるので、ACTION_DOWNの中で今タッチされている初めの指の番号を取得して覚えておきます。0は一番初めに触れたタッチになります。

## 初めにタッチされたボタンだけ処理を実行する
最後に初めにタッチされたボタンが離された時に処理を実行します。初めにタッチされた指の番号は覚えておいたので、指を離した時に覚えておいた指の番号かどうかで処理を実行します。

```java:MainActivity.java
private static final int INVALID_POINTER_ID = -1;
private static int mActivePointerId = INVALID_POINTER_ID;

public boolean onTouch(View view, MotionEvent event) {
	int touchedAction = event.getAction();
	if ( touchedAction== MotionEvent.ACTION_DOWN) {
		mActivePointerId = me.getPointerId(0);
	} else if (( touchedAction == MotionEvent.ACTION_UP) || 
			( touchedAction == MotionEvent.ACTION_POINTER_UP)) {
		int pointerIndex = (touchedAction & MotionEvent.ACTION_POINTER_INDEX_MASK)
                    >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
		if (mActivePointerId == me.getPointerId(pointerIndex)) {
			mActivePointerId = INVALID_POINTER_ID;
			onClick();
			return true;
		}
	}
	return false;
}
```

離された指の番号は、離された指のindexを取得してそこから求ることができます。ここでは説明を避けます。そして、同じだった場合に処理(onClick)を実行しています。こうすれば複数の指で同時に押されても、初めにタッチされたボタンに関連した処理だけを実行することができます。

### 補足
指が離された場合は、 touchedActionにACTION_UP(他に指が触れていない場合)、またはACTION_POINTER_UP(他にも指が触れている場合)が入ります。