OmniAICreator/Qiita-1.07M huggingface dataset:
IQ89のスッと覚えられるLinuxコマンド - 001


## 概要

IQが高くなくてもLinuxは使えます。
意識が高くなくてもLinuxは使えます。

会話形式にLinuxコマンドをわかりやすく説明していきます。
最終的にCUIでドヤれるようになるのが目的です。

## 【 ls 】 - list segments

コンソール起動したぼく
「さーて、ここのセキュリティでもチェックするかな」

たかひろ
「えっ、これ文字だけじゃん。すげぇ」

ファイルの一覧を表示したいぼく
「ま、とりあえずはどんな構築してるのかな・・・っと」

```bash:ls
[guest@localhost ~]$ ls
[guest@localhost ~]$ 
```

たかひろ
「これだけ？あんま変わってないんだけど」

説明してあげるぼく
「いや、なんもないからなんも表示されてないだけなんですけど。これだと出るし」

```bash:ls　[name]
[guest@localhost ~]$ ls /usr
bin  etc  games  include  lib  lib64  
libexec  local  sbin  share  src  tmp
[guest@localhost ~]$
```

たかひろ
「あ、なんかちょっと出てきた」

ちょっとできるぼく
「まぁこれくらいは余裕だよね。こっからが本番だよ」

```bash:ls　-la　[name]
[guest@localhost ~]$ ls -la /usr
total 68
drwxr-xr-x. 13 root root  4096 May  1 10:10 .
dr-xr-xr-x. 23 root root  4096 May  1 10:10 ..
dr-xr-xr-x.  2 root root 12288 May  1 10:10 bin
drwxr-xr-x.  2 root root  4096 May  1 10:10 etc
drwxr-xr-x.  2 root root  4096 May  1 10:10 games
drwxr-xr-x.  3 root root  4096 May  1 10:10 include
dr-xr-xr-x.  9 root root  4096 May  1 10:10 lib
dr-xr-xr-x. 27 root root 12288 May  1 10:10 lib64
drwxr-xr-x.  9 root root  4096 May  1 10:10 libexec
drwxr-xr-x. 12 root root  4096 May  1 10:10 local
dr-xr-xr-x.  2 root root  4096 May  1 10:10 sbin
drwxr-xr-x. 63 root root  4096 May  1 10:10 share
drwxr-xr-x.  4 root root  4096 May  1 10:10 src
lrwxrwxrwx.  1 root root    10 May  1 10:10 tmp -> ../var/tmp
[guest@localhost ~]$ 
```

たかひろ
「すごい！ハッキングしたの？」

すごいできるぼく
「あーこんな感じのセキュリティなのか。まぁ悪くはないってとこかな」

たかひろ
「これって、全部どういう意味なの？」

ぼく
「えっ。いや、でもバーっと出てきてすごくない？全部文字だし」

### これだけ知ってれば大丈夫

+ lsコマンドはファイルの一覧を表示させる
+ lsの後に場所を指定すると、その場所のファイル一覧を表示する
+ lsの後に`-la`をつけると隠しファイルを含めた詳細な情報を表示する
+ 詳細情報を出すし、場所も指定する場合は`ls -la 場所`の順番で
+ このコマンドでパソコンが壊れたりはしないので好きなだけやろう

## 【 cd 】 - change directory

場所を変えたいぼく
「まぁ、わざわざファイル一覧の場所を指定する必要ないんだけどね」

たかひろ
「そうなんだ。じゃあしなきゃいいじゃん」

場所を変えるぼく
「いやだから、場所を指定せずに場所を変えるってことだよ」

```bash:cd　[directory]
[guest@localhost ~]$ cd /usr/
[guest@localhost usr]$ 
```

たかひろ
「ん？にょろっとしたところが変わったね」

場所を変えたぼく
「変わったところが現在の場所を表してたんだよ」

たかひろ
「だったらなんなの？」

調子が出てきたぼく
「わかんないかー。つまりこういうことだよ」

```bash:cd　[directory]
[guest@localhost ~]$ cd /usr/
[guest@localhost usr]$ ls
bin  etc  games  include  lib  lib64  
libexec  local  sbin  share  src  tmp
[guest@localhost usr]$
```

たかひろ
「あっ！場所指定してないのになんか出てきた」

説明してるぼく
「場所を移動してるからね。さっきは何もないとこで一覧出して、今は色々あるとこに移動してから一覧出したんだよ」

たかひろ
「へぇ。そうなんだ。」

説明してるぼく
「ちなみに、移動しすぎて元の場所に戻れなくなった時はこうやる」

```bash:cd
[guest@localhost usr]$ cd
[guest@localhost ~]$
```

たかひろ
「へぇ。そうなんだ。」

ぼく
「うん」

### これだけ知ってれば大丈夫

+ cdコマンドは現在の場所を変える
+ cdの後に場所を指定すると、その場所に移動する
+ cdの後に何も付けないと、元の場所(既定の場所)に移動する
+ lsコマンド同様に、どれだけやっても壊れないのでどんどんやろう

## 【 pwd 】 - print working directory

優しく教えるぼく
「移動しすぎで、今どこいったかわかんなくなったら困るよね？」

たかひろ
「いや、困るかどうかわかんないけど」

簡単に答えるぼく
「そんな時はこれだけでわかる」

```bash:pwd
[guest@localhost ~]$ pwd
/home/guest
[guest@localhost ~]$ 
```

色々できるぼく
「こんな感じで、今の場所がわかると便利でしょ？」

たかひろ
「便利かどうかわかんないけど。そもそも場所ってなんなの？パソコンの場所ってこと？」

ぼく
「いや、場所って言われても。でもすごいできる感じしたでしょ？すごくない？」

たかひろ
「まぁそれなりに」

### これだけ知ってれば大丈夫

+ pwdコマンドは現在の場所を表示する
+ pwdコマンドもどれだけやっても壊れない。というか表示するだけで何も変わらない
+ これでたかひろはlsもcdもpwdも扱えるLinuxユーザーになった！
初心者Vimmerに伝えたい地味に便利な.vimrcの設定


Vimmerのいろんな人の記述を見ながら.vimrcの設定をした。
とりわけ地味だけどちょっとVimライフが幸せになりそうな記述を並べてみる。
※自分はMacVimをVimの代わりにターミナル上で起動するようにしています。

## スクロール送りを開始する前後の行数を指定
いい感じにページが送られて地味にソース読みやすい。

```.vimrc
set scrolloff=5
```

## 検索結果のハイライトと取り消し
検索結果をハイライトして、その後ESC2回押しですぐ消せて地味に目に優しい。

```.vimrc
set hlsearch
nnoremap <ESC><ESC> :nohlsearch<CR>
```

##エラービープ音の全停止
トゥッ！トゥッ！てならなくて地味に耳に優しい。

```.vimrc
set visualbell t_vb=
set noerrorbells
```

## カーソル行の背景色変更
カーソルのある行がわかりやすくて地味に操作しやすい。

```.vimrc
set cursorline
```

## 検索結果の対象を中央に表示
検索対象がすぐ目について地味に親切。

```.vimrc
"検索語が画面の真ん中に来るようにする
nmap n nzz 
nmap N Nzz 
nmap * *zz 
nmap # #zz 
nmap g* g*zz 
nmap g# g#zz
```

##インサートモードから抜ける時に便利なキーバインド
jjでインサートモードからコマンドモードに戻れるのが、地味なようで便利すぎて考えた人神。

```.vimrc
inoremap <silent> jj <ESC>
```
参考：Vim幼稚園からVim小学校へ
http://qiita.com/hachi8833/items/7beeee825c11f7437f54

##全角スペースの可視化
地味に大事。

```.vimrc
highlight ZenkakuSpace cterm=underline ctermfg=lightblue guibg=#666666
au BufNewFile,BufRead * match ZenkakuSpace /　/
```

##ヤンクしたデータをクリップボードで使用＆選択範囲自動コピー
なんだかんだで地味に使用頻度高い。

```.vimrc
set clipboard=unnamed,autoselect
```
※使用できるかは環境による
参考：http://nanasi.jp/articles/howto/editing/clipboard.html

***

とりあえず地味シリーズはこんなもんでしょうか。
CapistranoのdeployタスクをVagrantマシンに適用して開発する

やりたいこと: capistrano のタスクを vagrant マシンに適用して開発したい。vagrant へのログイン情報を capistrano から取得したい

## 事前準備

vagrant 内で git clone などすると思うので、ssh agent forward の設定をしておく 

```diff:Vagrantfile
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
+  config.ssh.forward_agent = true
end
```

Mac の keychain に鍵を登録しておく. keychain に入れておくと毎回 ssh-add しなくてすむ。-K オプションを使う。

```
$ ssh-add -K .ssh/id_rsa
```

## やりかた

vagrant ssh-config で諸々情報が取れる

```
$ vagrant ssh-config
Host vagrant-centos
  HostName 127.0.0.1
  User vagrant
  Port 2200
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile /Users/seo.naotoshi/.vagrant/machines/vagrant-centos/virtualbox/private_key
  IdentitiesOnly yes
  LogLevel FATAL
  ForwardAgent yes
```

なので、これを capistrano の変数に設定するメソッドをちょろっと書いて利用する

```ruby:config/deploy.rb
set :application, 'oreno'
set :repo_url, 'git@github.com:sonots/oreno.git'
set :deploy_to, '/var/app/oreno'

def set_vagrant_user
  ssh_config = {}
  Bundler.with_clean_env do
    out = `vagrant ssh-config`
    out.split("\n").each do |line|
      line.strip!
      key, value = line.split(" ", 2)
      value.slice!(0) if value.start_with?('"')
      value.slice!(-1) if value.end_with?('"')
      ssh_config[key] = value
    end
  end

  set :user, ssh_config["User"]
  set :ssh_options,
    user: ssh_config["User"],
    port: ssh_config["Port"],
    keys: [ssh_config["IdentityFile"]],
    forward_agent: ssh_config["ForwardAgent"] == "yes" ? true : false
end
```

```ruby:config/deploy/development.rb
set_vagrant_user

roles :app, ['127.0.0.1']
```

これで、

```
$ cap development deploy
```

で vagrant にログインしてデプロイできる。

## ToDo

めっちゃ小さいメソッドだけど gem にしてもいいのかもね。
Bootstrapのレスポンシブなテーブルの列の幅を動的に変える


## やりたいこと
Bootstrapのレスポンシブ対応のテーブルで列の幅を自分が決めた幅で動的に変えたい！

bootstrapのバージョン: 3系
使うHTML

```html
<div class="alt-table-responsive">
  <table class="table">
    <thead>
  	  <tr>
  	   	  <th>th1</th>
  		  <th>th2</th>
  		  <th>th3</th>
  	  </tr>
    </thead>
    <tbody>
  	  <tr>
  		  <td>aaa</td>
  		  <td>bbb</td>
  		  <td>ccc</td>
  	  </tr>
  	  <tr>
  		  <td>ddd</td>
  		  <td>eee</td>
  		  <td>fff</td>
  	  </tr>
    </tbody>
  </table>
</div>
```

## 手順
①thタグにGrid systemのクラスを追加する
col-xs-3やcol-md-2のようなものですね。
これを付けることで、画面の大きさに合わせて列の幅が動的に変わります。

```html
<th class="col-xs-3 col-ms-3 col-md-4 col-lg-4">th1</th>
<th class="col-xs-3 col-ms-3 col-md-3 col-lg-4">th2</th>
<th class="col-xs-1 col-ms-1 col-md-1 col-lg-1">th3</th>
```

これだけでも良いのですが、tableタグをtable-responsiveのクラスを付けたdivタグで囲んで画面の幅が小さい時にスクロールするテーブルにした際、テーブルの要素が長すぎるため折り返してほしいという場面があると思います。

②CSSを追加
折り返されない原因は、table-responsiveによって中のthタグとtdタグに「white-space: nowrap;」が指定されてしまうからだそうです。(参考：http://stackoverflow.com/questions/25916530/keep-column-width-using-responsive-table-bootstrap3)
なので、table-responsiveは使わずにCSSで

```css
.alt-table-responsive {
    width: 100%;
    overflow-y: hidden;
    overflow-x: auto;
    -ms-overflow-style: -ms-autohiding-scrollbar;
    -webkit-overflow-scrolling: touch;
}
```

を指定すると、画面幅が小さい時に要素を折り返してくれるためスクロールする範囲を狭められます。
Objective-CのBlocksとSwiftのクロージャでは変数のキャプチャが違う


まず、Swiftで以下のコードを実行してみる。

```swift

var sampleStr = "ABCD"

let showCaptureString = {(number:Int) -> String in
    sampleStr + String(number)
}

showCaptureString(99)
sampleStr = "DCBA"
showCaptureString(99)

```
まず、showCaptureStringというクロージャを定義。
これは受け取った数字とキャプチャしたsampleStrを連結して返すもの。
１行だけなのでreturnは省略できる。

実行結果は、最初のshowCaptureString(99)ではABCD99が返る。
そして、sampleStrをDCBAに書き換えた後、もう一度同じようにshowCaptureString(99)を実行すると、DCBA99が返る。
これと同じような事をObjective-CのBlocks構文を用いて実装してみる。



```objc
    NSString *sampleStr = @"ABCD";
    
    NSString *(^showCaptureString)(int) = ^(int number){
        return [NSString stringWithFormat:@"%@%d",sampleStr,number];
    };
    
    NSLog(showCaptureString(99));
    sampleStr = @"DCBA";
    NSLog(showCaptureString(99));
    
```

最初のshowCaptureString(99)はABCD99が返る、これは自然。
しかし、sampleStrをDCBAに書き換えた後、showCaptureString(99)を実行しても同じようにABCD99という値が返る。

このような結果になる理由は、Objective-CのBlocksとSwiftのクロージャでは変数のキャプチャが異なるから。

Objective-Cでは一度キャプチャした値は後から変更されず、実行時にはキャプチャした時の値が使われる。
一方、Swiftではキャプチャした変数は実行時のものが使われる。

Objective-CでSwiftのクロージャのようにBlock内でキャプチャ変数を書き換えるには、__blockをつければ良い。

```objc
    __block NSString *sampleStr = @"ABCD";
    
    NSString *(^showCaptureString)(int) = ^(int number){
        return [NSString stringWithFormat:@"%@%d",sampleStr,number];
    };
    
    NSLog(showCaptureString(99)); //ABCD99
    sampleStr = @"DCBA";
    NSLog(showCaptureString(99)); //DCBA99
    
```
Created @ChromiumDev slack. A place for web devs to talk dev and chrome.

Tweetされてたので共有して大丈夫ですよね?

[@Paul_Kinlan](https://twitter.com/Paul_Kinlan)氏がChromiumのSlackを開設しました。

<blockquote class="twitter-tweet" lang="ja"><p lang="en" dir="ltr">Created <a href="https://twitter.com/ChromiumDev">@ChromiumDev</a> slack. A place for web devs to talk dev and chrome&#10;&#10;Join ☞ <a href="https://t.co/RAr4iTzesM">https://t.co/RAr4iTzesM</a>&#10;Login ☞ <a href="https://t.co/8xLiIpC0F8">https://t.co/8xLiIpC0F8</a></p>&mdash; Paul Kinlan (@Paul_Kinlan) <a href="https://twitter.com/Paul_Kinlan/status/598494432321773569">2015, 5月 13</a></blockquote>

Join !!
UnityでParseから1000件以上のデータをまとめて取得する

UnityでParseのデータを取得する場合に標準では100件ずつになっています。
QueryのLimit()で最大1000まで増やすことができますが、1000件以上取得する場合
やり方が分からなくて悩んだのでメモします。


```C#
// データ取得用クエリ
    ParseQuery<ParseObject> query = new ParseQuery<ParseObject>(ObjectName);
    query = query.OrderBy("createdAt");
    query = query.Limit(1000);

// データ件数をカウントするクエリ
    ParseQuery<ParseObject> countquery = new ParseQuery<ParseObject>(ObjectName);
    var ResultCount = countquery.CountAsync();

    while (!countresult.IsCompleted) yield return null;
    int cnt = countresult.Result;

    while( cnt/1000 > loop )
    {
        //1000件毎にSkipする
        if (loop != 0) query = query.Skip(1000);
        var task = query.FindAsync();
        ...
        //データを取得して、処理する
    }
```

データ件数カウントと実際のデータ検索用にQueryを2つ用意するのが正しいのか？
わかりませんが、とにかくQuery.Limit()は1000が上限なので
1000件毎にLoopしながらSkip()をしていけばOKということが無事分かりました。
データ件数が多い場合はやばいかもしれませんがそれはおいておきます。
Slackで特定の名前を持つボットやユーザーをミュートするブックマークレット

Slack皆さん使われてると思いますが、Botなどが非常に作りやすいということもあって、特定の単語に反応する多くのボットが作られているよ、という方もいるのではと思います。

多分に漏れず自分が利用しているSlackの環境もBot類が非常に多いのですが、特に誤爆反応がつらいボットがいて、それはslackbotです。

このボットはグローバルに単語に反応するくせに、Slackには個々人でこのslackbotをミュートしたりブロックしたりする機能がないのです...(なんでだろう...)


というわけでslackbotをミュートしてくれるブックマークレット作りました。ブックマークレットのslackbotという文字列をユーザーのIDに書き換えると特定のユーザーもミュートしてくれます。需要があるかどうかは謎ですが、必要な方はご利用下さい。

### slackbot向け

```js
javascript:(function(){$("#msgs_div").on('DOMSubtreeModified propertychange', function() {$("div.message > *.message_sender:contains(slackbot)").parent().hide();});})();
```
### ユーザー向け

```js
javascript:(function(){$("#msgs_div").on('DOMSubtreeModified propertychange', function() {$("div.message > .message_aria_label.hidden > strong:contains(username)").parent().parent().hide();});})();
```

使い方は、ブックマークのページを作ってURLのところを上記JSに置き換えるだけです。あとはSlackのページを開いた後にこのブックマークレットを一度だけ実行します。チャンネルを切り替えたりメッセージが読み込まれると最初に動きます。ユーザー向けは、usernameを変更してください。

とりあえず、最新のFirefoxとChromeでしか動作確認しておりませんが、こうすると良いよなどアドバイスあれば教えて下さい。

では良いSlackライフを。
Remottyを使ってみた

数名で[Remotty](http://www.sonicgarden.jp/20150416_remotty)を使ってみました。
かなり低頻度ですが使ってみた感触などをメモしておきます。

##ネット情報
* [Remotty - リモートワークのためのバーチャルオフィス](http://www.slideshare.net/kuranuki/remotty-140302)
* [無料で使えるチャットツール「Remotty」人数制限なしで気軽な雑談を実現する仕組み](http://peacepopo.blog.fc2.com/blog-entry-190.html)
* [ソニックガーデン、離れた場所のチームをつなぐ無料ツール「Remotty」をリリース](http://www.netventure-news.com/news_bQXsTsNI9W.html)
* [リモートワークにおけるチームワークの課題を解決できる「Remotty」を無期限・無制限・無料で提供開始](http://www.sonicgarden.jp/20150416_remotty)
* [高速で無駄のない開発をするチームのための"７つ道具"（2014/03/08 - Websig）](http://www.slideshare.net/kuranuki/20140308-websig-kuranuki)

##特徴
　・ウェブカメラで定期的に顔写真が更新され続ける
　・個人のルーム（誰でも見れる、見ている人が誰かわかる）
　・ダイレクトメッセージ機能がある
　・スレッド形式のグループというのが作れる
　・グループは非公開にもできる（特定メンバーのみ閲覧可能）
　・非公開グループとDM以外のコメントは全てタイムラインに流れる

##感触
　メンバーの顔が見えるのは新鮮で何をしているのかわかって良いです。
　流れるチャットだけでなく、スレッドが立ててアーカイブ出来る点も使い分けができて良いです。
　一応ビデオ通話もできるようですが試してません。
　
　基本スタイルとして自分のルームに独り言を書く、
　しかしタイムラインに発言が流れるので発言が非常にオープンになります。
　会話が流れていく場所が専用であるイメージ。
　
　残念な点はファイル添付機能がありません。(?)
　なのでメインチャットとして使えるか悩ましいところです。
　流石に複数チャットツールの併用は厳しいです。

　当然ながら基本全員ウェブカメラ有りで価値を発揮すると思います。
　写真はボタンを押して再撮影したり、プロフィール画像に切替えられるので、
　ニヤニヤした顔が写っていても安心です。

##その他
　問い合わせもチャットベースで気軽に行えます。
　また、スピーディーに返答をもらえる点は素晴らしいと思います。
　今後どうなるか期待も高く、機会があれば仕事でも試してみたいかなと思います。
kobito for windowsを使ってみたのでtest


~~あれ？アップロード失敗するのはなぜ？~~
できた。なんか不安定です。

#test1(見出し1)
##test2(見出し2)

箇条書き関係
1. test1
2. test2
3. test3　長くすれば　改行された時の　挙動がわかる。長くすれば　改行された時の　挙動がわかる。長くすれば　改行された時の　挙動がわかる。長くすれば　改行された時の　挙動がわかる。長くすれば　改行された時の　挙動がわかる。　
↑箇条書きがだめだ。

* test
* test
* test

**ボールド**
_イタリック_

```javascript:test.js
var foo ;
var bar ;
```

[link](http://kobito.qiita.com/win)
#感想
* マークダウンとしては他のeditでもいいが、Qiitaに直接投稿できるのは楽。使いやすい。
* Qiitaとの連携が超絶楽。気持ちいくらい。また、過去の投稿もlocalで編集できるのはgood。
* Qiitaへの投稿はこれにする。
* ~~コードを埋め込む際の、ソース名の埋め込みのやり方が分からない~~
* 戻るのが、画面最下部に行かなきゃいけないのがめんどう。
* これからの改善に期待。
* トータルして多分使う機会が増える。

***
以上
s3fsがメモリリークするバグが解消したみたい

# s3fsとは
S3バケットをEC2からマウントすることができる便利ソフト。
長い間、AWSにはNFSマウントが可能なストレージサービスが登場する気配がなく、複数のEC2から同じファイルを参照したいけど各サーバでファイルを共有したい（ローカルにファイル置きたくない）ようなケースで、s3fsを利用してS3バケットをDISKとみなしてマウントすることで解決していたのです。

s3fsには、**動作が非常に不安定**という欠点がありました。
勝手にマウントが外れるとか、メモリ使用量が異常に多いとか、大事な本番サービスにそんなソフト普通は使いたくありませんが、他に代替手段がないので、[使うときだけautofsでマウントする](http://qiita.com/butayan0/items/4820e48420fb737cf79f)といったTipsを併用して使うというのが慣例でした。
私自身もマウント外れ問題への対処のため、定期的にumount→mountする＆プロセス生死確認→死んでたら前述の処理を実行するお手製バッチを動かしていました。

しかし先日ついに[Elastic File System](http://aws.typepad.com/aws_japan/2015/04/amazon-elastic-file-system-shared-file-storage-for-amazon-ec2.html)が発表されました。年内には正式利用開始がアナウンスされているので、今後はこちらの利用が増えていくでしょう。
EFSの普及に伴いs3fsの利用が減っていくことは想像に難くなく、これから書くことが誰かの役に立つ可能性は非常に低いです…。

とはいえ、仮にEFSの利用料金がS3のそれと大きく乖離した場合、s3fsをこれまで通り使いたい方もいるかもしれませんので、s3fsがこれまで抱えていた問題とその解決についてまとめたいと思います。

# s3fsのメモリリーク問題
## 放っておくとメモリがどんどん減っていく
私が管理していたサーバでは、HTTPSでマウントするオプションを使っていましたが、s3fsを使用している間メモリ使用量が毎日右肩上がりになっていき、だいたい1週間で空きメモリを食いつぶしてs3fsがOOM-Killerに殺されるという現象が起きていました。
`Nov 26 07:15:09 ip-***-***-***-*** kernel: [1540952.633902] Killed process 3434 (s3fs) total-vm:622496kB, anon-rss:247320kB, file-rss:0kB`
始めはzabbixから空きメモリ低下のアラートを受けて再マウントしていましたが、面倒になって**メモリがどうであろうと日次でマウントを外して再度マウントするバッチを回しておく**というバッドノウハウで乗り切っていました…
## issueは立っているけど解決出来てなかった
根本的に解決する方法を探したところ、Google Codeで同様のケースを扱ったissueを発見！
[Issue 314:Out of Memory process killed](https://code.google.com/p/s3fs/issues/detail?id=314&q=Killed%20process)
SSL経由で利用していると、HEAD（lsするなど）リクエストが行われるたびにメモリ消費量が増えていくバグが存在している模様です。修正が試みられますが、libcurlとlibnssを組み合わせて使用した場合に起きるバグっぽいから、ライブラリが直らないとs3fsもどうにもならないぜ。とのこと。
>（前略）
>So, I think that this means leaking memory at libnss+libcurl.
>But it is not enough solution for this problem, the cause is deep in lib curl and libnss.
>I think it is hard to fix this issue and takes a lot of times.
https://code.google.com/p/s3fs/issues/detail?id=314#c18

ここでissueは途切れており…というのが筆者の認識だったのですが、今日久々に見に来たら約5ヶ月後に解決策が提示されていました！
7.21.4より新しいバージョンの（最新の）libcurlをwith NSSでビルドすれば良いようです。
>On my case, the libcurl version is under 7.21.4, this version has a bug about memory leaking.
>(For example, cent-os uses yum repository, it does not have latest curl(libcurl) version.)
>The bug is only a case of built with NSS library.

>I tried to update latest libcurl with NSS, and test with s3fs.
>After that, it worked good for me, it seems memory leaking does not increase.
https://code.google.com/p/s3fs/issues/detail?id=314#c19

#まだ試してないです
解消方法をがんばって調べたりしたので、再現環境を作って試してみたいんですが一旦ここまで！
Live2Dで描画したキャラの上でドラッグ(フリック)するとパーティクルがでるようにしてみた

## 概要
Live2D SDKに入っているSampleApp1にキャラの上でドラッグ(フリック)するとパーティクルがでるようにしてみた．
Live2D_SDK_Unity_2.0.08_1_jp/sample/SampleApp1を改造して作成する．
※以下説明ではドラッグとフリックをフリックに統一

## 開発環境
* Live2D_SDK_Unity_2.0.08_1_jp
* Unity 5.0.1f1

## 完成するDEMO
![スクリーンショット 2015-05-13 23.38.14.png](https://qiita-image-store.s3.amazonaws.com/0/76553/c8318854-5c52-886f-57fb-f521db956192.png)

## 作り方
PlatformManager.csとLAppView.csを編集し，
モデルの描画モード，フリックなどの処理を変更，パーティクルの設定をする．

####モデルの描画モードを変える
パーティクルを表示するときにLive2Dモデルが最前面に出てしまう問題を回避するために，
RenderModeを変更する(UnityのAPIで非推奨のものを利用している．

```csharp:sample/PlatformManager.cs
public ALive2DModel loadLive2DModel(string path){
    // -- 省略 --
    live2DModel.setRenderMode(Live2D.L2D_RENDER_DRAW_MESH);　//追加
    return live2DModel;
}
```

####パーティクルをプロジェクトに追加
Hierarchy > Create > Particle Systemを選択してパーティクルシステムを作成．
Inspectorは以下のように設定した．
![スクリーンショット 2015-05-13 23.30.22.png](https://qiita-image-store.s3.amazonaws.com/0/76553/adcda8c1-c2ee-6e33-2c9b-ec9ace555e77.png)


LAppViewのメンバに以下を追加

```csharp:sample/LAppView.cs
    ParticleSystem ps;
```

LAppViewのコンストラクタに以下を追加

```csharp:sample/LAppView.cs
    ps = GameObject.Find("Particle System").GetComponent<ParticleSystem> ();
```

####フリックイベントの修正とパーティクルの操作

```csharp:sample/LAppView.cs

// タッチ中
public void TouchesMoved(Vector3 inputPos) 
{
    // -- 省略 --
    Camera c = GameObject.Find("Main Camera").GetComponent<Camera>();

    dragMgr.Set(x, y);
    const int FLICK_DISTANCE = 100;// この値以上フリックしたらイベント発生

    // フリックイベントの判定
    if (touchMgr.IsSingleTouch() && touchMgr.IsFlickAvailable())
    {
        ps.Play();
        ps.transform.position = c.ScreenToWorldPoint(new Vector3(inputPos.x,inputPos.y, 0));

        float flickDist = touchMgr.GetFlickDistance();
        if (flickDist > FLICK_DISTANCE) {
            float touchPos_plane2x2_X = touchPos_onPlane.x * 2 - 1;
            float touchPos_plane2x2_Y = -touchPos_onPlane.y * 2 + 1;
            model.FlickEvent(touchPos_plane2x2_X, touchPos_plane2x2_Y);
            //touchMgr.DisableFlick(); //コメントアウト
        }
    }
    // -- 省略 --
}

// タッチ終了
public void TouchesEnded(Vector3 inputPos)
{
    // -- 省略 --
    touchMgr.DisableFlick();
    ps.Stop();
    ps.Clear();
}

```
Google Driveのマイドライブに共有フォルダのショートカットを追加

## やりたいこと

マイドライブに共有フォルダ（ファイル）へのショートカットを追加して「あれ、あのフォルダ（ファイル）どこだっけ？」と共有フォルダ内を探しまわる時間を削減したい。
マイドライブから該当フォルダ（ファイル）に素早くアクセス。

## 方法

下記URLが大変参考になります。

> http://matsu.teraren.com/blog/2014/02/24/google-docs-my-drive-shortcut/

要するに普通にフォルダ（ファイル）をマイドライブにドラッグアンドドロップすると共有フォルダ（ファイル）を移動させてしまうのに対して、`Option(alt)`を押しながらドラッグアンドドロップするとショートカットを追加できるということ。

## 画像イメージ

* 普通にドラッグした場合

![スクリーンショット 2015-05-13 23.34.46.png](https://qiita-image-store.s3.amazonaws.com/0/67471/ebb4102e-d71c-4a10-e77f-26fdbe7f4c41.png)

* ドラッグ中に`Option(alt)`を押した場合

![スクリーンショット 2015-05-13 23.34.06.png](https://qiita-image-store.s3.amazonaws.com/0/67471/651a6be1-ee8d-5bd2-ae37-e5c42580c8ac.png)

この状態でマイドライブ上でドロップすればOK。

## おわりに

Google公式のヘルプなどの情報を探したが`Option(alt)`を使った方法は発見できず。
下記のヘルプのやり方では上手くいかなかった。

> https://support.google.com/drive/answer/2375057?hl=ja

非公式なのかヘルプが足りてないのか私がヘルプを発見できてないだけなのか…。
私の周辺でも困ってる人がいたので、この際なので備忘録として書いておきました。
Kobito for Windows のCSS設定

## 日本語のフォント
Windows7環境で確認。
一部、日本語の字形がおかしい（中華っぽい字形で表示される）。
問題の部分は、一応デフォルトのスタイルで「MS ゴシック」が設定されているようだ。
試しに「開発者ツール」で「MS ゴシック」→「MS Gothic」に書き換えたらちゃんと表示された。
うーん。
Kobito for Windows の改善要望の受付とか無いの？

## user.cssを設置してコード部分のフォントを変更する
追記: バージョンが上がってからなんか変更できないです。

ユーザー環境変数へ %HOME% を追加

- 変数: `HOME`
- 値: `C:\Users\<ユーザー名>\Work` (例)

`%HOME%/_kobito/user.css` を設置

```css:user.css
.markdown-content pre,
.markdown-content code {
  font-family: "MS Gothic";
}

.markdown-editor span.cm-comment {
  font-family: "MS Gothic";
}
```

編集モードでのプレビュー側のコードブロックがiframeを使っているため、そこだけフォントが変更できなかった。

### 参考
- https://twitter.com/mizchi/statuses/597932416833949697
DMDで小さなバイナリを作る

標準出力に Hello! を返すだけのプログラムをDMDが生成するオブジェクトファイルからどれだけ最小化していけるか、ということをやって、最終的に 192 バイトまで小さくしました。

具体的な内容はこちらのレポジトリにまとめています。 https://github.com/kubo39/tiny-d-demo

行ったこととしては、プログラムの実行に必要な最小構成をひとつのセクションにまとめて、プログラムの実行に必要ない部分をざっくり削ってしまう、ということだけです。

注意すべき点としてはカスタムELFヘッダがエントリポイントのアドレスを事前に知っている必要があるため、
シンボル情報から `_Dmain` (D言語のvoid main()のC表現)のアドレス情報を抜き出して渡しているところくらいでしょうか。


四方山話としては、

* gcc のオプションに `-Xlinker -static` を渡したところ `undefined reference to `__tls_get_addr'` というのでどうやってもうまくいかず、これはdmdにバグ報告だ！と思ったらすでにあった http://forum.dlang.org/thread/bug-12268-3@https.d.puremagic.com%2Fissues%2F

* 自作の [syscall.d](https://github.com/kubo39/syscall.d) を使いたかったけれど、dmdが `-inline` オプションを渡してもインライン化してくれないので泣く泣くインラインアセンブラをベタ書き。

といったあたりです。

(こんな小ネタでよかったのかな。。
mixinでfont-sizeとline-heightをremでうまく吐き出す


## Vertical Rhythm Designとremの相性
マテリアルデザインをベースにコーディングを進めるにあたって、ベースとなる行間が完全に計算されたフォントサイズの設計をめちゃくちゃ簡単に設定できないかと考えた自分用メモですが、何かの参考になればと思い投稿しておくことにしました。

もちろん、Compassを使えばいくつかのmixinが用意されていてどうにかなりますが、場合によってはフォントも行間もコントロールしたくなることがある。
ということで、rem指定したフォントに対して、均一にline-heightが付与されつつも、こっちでも指定することの出来る変数を考えてみました。

基本、px感覚で指定ができつつも、remの効かないブラウザの場合、font-sizeも書き出してくれます。

## 前準備
全体のfont-sizeをremで書き出せるように調整をします。

```css
html {
  font-size: 62.5%;
}
```

### mixin

```scss
@mixin fts($fts, $lin: 24) {
  $rem: $fts / 10;
  $linS: $lin / $fts;
  font-size: #{$fts}px;
  font-size: #{$rem}rem;
  line-height: $linS;
}
```
` $lin: 24`の指定に、基本的に取りたいベースユニット（ベースとなる行間）を指定する。
あとは勝手に` font-size`のpxとremの両方を書き出して、line-heightを計算してくれる。

### 使い方

```scss
// font-sizeを14pxにしたい場合
.hoge {
  @include fts(14);
}

// line-heightを故意的に変えたい場合
.hoge {
  @include fts(10,28);
}

// line-heightを取りたくない場合、font-sizeと同じ数字を入れるとline-height: 1が返る
.hoge {
  @include fts(14,14);
}
```

引数としてfont-sizeとline-heightを渡せば勝手に計算してくれます。

### 実際の出力

```scss
.hoge {
  @include fts(14,18);
}
```

```css
.hoge {
  font-size: 14px;
  font-size: 1.4rem;
  line-height: 1.28571;
}
```

使いどころがあれば使ってください！
Android Wearに向かって「OK, Google, 進捗どうですか？」と聞くと・・・！？


![s1.jpg](https://qiita-image-store.s3.amazonaws.com/0/26528/b99bc22d-8191-b010-6cb6-1076b8bd3e8c.jpeg)


![s2.jpg](https://qiita-image-store.s3.amazonaws.com/0/26528/2994bf3a-fe90-8c92-3673-15f87edb85bf.jpeg)
LVM概要

# LVM 概要 
従来の一般的なボリューム構成では、物理ボリュームにパーティションやRAID デバイスを作成し、それら物理的な環境をマウントしてファイルを保存する構成となっています。
そのため、物理的なデバイスパーティションやRAID デバイスは1対1の関係になります。
* 1対1 な関係
![InThePastPhisicalVolumes0000.png](https://qiita-image-store.s3.amazonaws.com/0/70152/0fb63770-2865-fb72-dd83-9708cbeb7c89.png)



LVM では、次の図のように1個以上の物理デバイスから構成される論理的なデバイスを作成することにより、n対1 の関係でデバイス構成を作ることができるようになります。
それにより、1つの物理デバイスのキャパシティを超えた容量のデバイスを作成したり、論理デバイスの下で柔軟な物理RAID 構成を構築したりすることができるようになります。
* n対1 な関係を作成することもできる
![LVM_CreateLVMNormal0000.png](https://qiita-image-store.s3.amazonaws.com/0/70152/fd684956-8233-6725-6b06-e2e007a48a46.png)


物理デバイスは、例えばHDD のようなデバイスで、異なる物理的な複数のHDD を1 つの論理ボリュームとして使用することができるようになります。
そのため、物理ボリューム環境では1 つのボリュームで1 つのHDD 容量を越える容量のボリュームを作成することはできませんでしたが、論理ボリュームを使用することで複数の物理的なHDD の容量を合わせた大きさのボリュームを作成することができるようになります。

## extent について 
LVM では、データの区切りの単位をextent と呼びます(物理デバイスのブロックのような概念です)。
デフォルトでは1 extent は4 MiB で、物理extent と論理extent に分かれています。
物理extent は物理ボリューム上に割り当てられるextent で、論理extent は論理ボリューム上に割り当てられるextent となり、論理extent は物理extent を柔軟に割り当てることが可能になっています。

物理extent は通常、論理extent と1 対1 の関係でマッピングされます。
ミラーリングを使用することで、2 つ以上の物理extent を1 つの論理extent とマッピングすることができるようになります。

## 論理ボリュームグループと論理ボリュームについて 
論理ボリュームは、論理ボリュームグループからパーティションを作成することで容量を割り当てられ、作成されます。
注意点として、論理ボリュームはraw デバイスとしては使用できない点に注意してください。
そのため、論理ボリュームはswap 領域のようなボリュームとして使用することはできません。
※LVM2 からできるようになった！？！？Fedora21 では、swap 領域にLVM が使用できている。
また、論理ボリュームとファイルシステムとの間に中間層を構築することも可能で、`dm-crypt` を使用して暗号化ファイルシステムを作成することもできます。
![InThePastPhisicalVolumes0002.png](https://qiita-image-store.s3.amazonaws.com/0/70152/425745ba-df8f-5d37-3b1b-4bae9f05fc6f.png)


また、連続するextent を異なる物理ボリュームで構成し、ストライピングすることでシーケンシャルリードの性能を向上させることも可能となります。

## リサイズについて 
論理ボリュームは論理extent を更に割り当てて論理ボリュームを拡張したり、論理extent の割り当てを解除することで論理ボリュームを縮小したりすることもできます。
論理ボリュームの容量の変更は、ext3, ext4 等のオンラインリサイズに対応しているファイルシステムが乗っている場合、アプリケーションの処理を阻害することなく行うことができます。

## スナップショット 
物理ボリュームと論理ボリュームは異なるボリュームグループをまたがって、共有することはできません(幾つかのボリュームマネージャ同じホスト上の異なるボリュームグループ間のデータの移行ができるものもあります)。
スナップショット機能は、オンライン、オフラインのボリュームグループを1 つの管理単位としてホスト間を転送できるようになります。
スナップショットは論理ボリュームのある時の状態を写真のように保持しておくもので、それを利用することにより、同じ論理ボリュームの2 つ以上のコピーを提供することができるようになります。

## 次の記事
[論理ボリュームの作成、拡張、縮小、複製](http://qiita.com/TsutomuNakamura/items/93c6333c8dd32aeb197a "論理ボリュームの作成、拡張、縮小、複製")
削除されたリモートブランチの同期

## Gitの毎日作業系備忘録

毎日の `fetch` 作業

```
git fetch origin
```
を続けるとローカルにリモートのブランチが残るのでたまに下記で削除されたリモートブランチを削除する。

```
git remote prune origin
Pruning origin
URL: git@github.com:hoge/hoge.git
 * [pruned] origin/deploy

```
CentOS7 で FDclone

#### 準備

```bash:
sudo yum install wget
sudo yum install rpm-build
```

#### 作業ディレクトリを作成し、移動する。  

```bash:
mkdir -p ~/src/FDclone
cd ~/src/FDclone
```

#### [作者サイト](http://hp.vector.co.jp/authors/VA012337/soft/fd/) から ソースをダウンロード  

```bash:
wget http://hp.vector.co.jp/authors/VA012337/soft/fd/FD-3.01b.tar.gz
```

#### ダウンロードしたファイルを展開する。

```bash:
tar -xvzf FD-3.01b.tar.gz
```

#### rpm ファイルを作成する。  
#### インストールする。  
#### 設定ファイルを変更する。  

-----
```bash:FDclone_install.sh
#!/bin/sh
# FDclone を CentOS 7 にインストール

# インストールに必要な各種ファイルのインストール

# wget:webサイトからファイルをダウンロードする。
# rpm-build:rpmファイルを作成する。
# gcc:C-コンパイラ
# ncurses-devel:FDcloneのコンパイルに必要なライブラリ
# nano:テキストエディタ:設定ファイル編集用
sudo yum install wget
sudo yum install rpm-build
sudo yum install gcc
sudo yum install ncurses-devel
sudo yum install nano

# ソースファイルの保存用フォルダを作成し、移動する。
mkdir -p ~/src/FDclone
cd ~/src/FDclone

# ソースファイルをダウンロードし、rpmファイルを作成する。
wget http://hp.vector.co.jp/authors/VA012337/soft/fd/FD-3.01b.tar.gz
rpmbuild -tb --clean FD-3.01b.tar.gz

# 作成した rpm ファイルを元にインストールする。
cd ~/rpmbuild/RPMS/x86_64/
sudo yum install FDclone-3.01b-1.x86_64.rpm

# 設定ファイルを編集する。
sudo nano -w /etc/fd2rc
```
-----
```diff:fd2rc.patch
--- fd2rc.orig	2015-05-14 05:51:29.298738457 +0900
+++ fd2rc	2015-05-14 05:56:53.265719377 +0900
@@ -17,6 +17,7 @@
 #	200-213: preserve previous sort type also in the archive browser
 #		(the least 2 digits are effective just after initialize)
 #SORTTYPE=0
+SORTTYPE=1
 
 # default display mode
 #	0: normal (Default)
@@ -33,6 +34,7 @@
 #	0: not sort (Default)
 #	>= 1: sort according to SORTTYPE
 #SORTTREE=0
+SORTTREE=1
 
 # behavior about writing over directory on file system
 #	0: confirm to write or not, after directory arranged (Default)
@@ -184,6 +186,7 @@
 #	2: color & force background to blacken
 #	3: color & force foreground to blacken
 #ANSICOLOR=0
+ANSICOLOR=1
 
 # color palette in the ANSI color mode
 #	Default: none
```
-----
[こっち](https://github.com/conan-hdk/fdclone-ForCentOS)に Makefile とかを作ってみた。
-----
# 参考サイト
* http://hp.vector.co.jp/authors/VA012337/soft/fd/
* http://osdn.jp/magazine/14/01/10/090000/3
* http://www.xyzi.org/?p=471
Gmail APIを使う時のBase64エンコード


## 追記
パッケージ作って公開した

[gmail_message_factory 0.0.1 | Pub Package Manager](https://pub.dartlang.org/packages/gmail_message_factory)

こんなかんじで使える

```dart
import 'package:gmail_message_factory/gmail_message_factory.dart';
    
main() {
  var mf = new MessageFactory.UTF8("me", "to@example.com", "件名", "本文");
  var message = new Message();
  message.raw = mf.toRawMessage();
  api.users.messages.send(message, "me");
}
```

---

DartのWeb Appから`googleapi`を使ってGmail APIを叩いたけど日本語のメールを文字化けさせないようにするのに苦労した。

```dart
sendMail(GmailApi api) {
  var to = toInput.value;
  var subject = subjectInput.value;
  subject = CryptoUtils.bytesToBase64(UTF8.encode(subject));
  var text = textInput.value;

  var mail = "To: $to\n"
  "Subject: =?utf-8?B?$subject?=\n"
  "MIME-Version: 1.0\n"
  "Content-Type: text/plain; charset=${UTF8.name}\n"
  "Content-Transfer-Encoding: 7bit\n"
  "\n"
  "$text";
  mail = CryptoUtils.bytesToBase64(UTF8.encode(mail), urlSafe:true);
  var message = new Message();
  message.raw = mail;
  return api.users.messages.send(message, "me");
}
```

ポイントはヘッダ部分には`Content-Type`のエンコードは無効であるということ。

`=?文字コード?符号方式?符号化された文字列?=`という形式にすることでヘッダ部分にもUTF-8などのエンコードの文字列を使うことができる

Gmail APIのメール作成でAPIに渡すメールオブジェクトはUrl-SafeなBase64エンコードされた文字列である必要があるので、

`CryptoUtils.bytesToBase64(UTF8.encode(subject));`
`CryptoUtils.bytesToBase64(UTF8.encode(mail), urlSafe:true);`
でUTF8で書かれた文字列をBase64にする
sbt runでprovidedな依存ライブラリをクラスパスに含める

本番環境ではライブラリがインストールされているからそれを使いたいけど、ローカルで実行/テストするときは環境作るの面倒だからsbt管理のライブラリを使いたいよってケースです。

`build.sbt`で以下のように設定すると`sbt run`および`sbt run-main`でprovidedにしたライブラリもクラスパスに含めて実行されます。

```scala
libraryDependencies ++= Seq(
  "org.apache.spark" %% "spark-core" % "1.3.1" % "provided",
  "org.apache.spark" %% "spark-mllib"  % "1.3.1" % "provided",
  "com.github.scopt" %% "scopt" % "3.3.0"
)

run in Compile <<= Defaults.runTask(fullClasspath in Compile, mainClass in (Compile, run), runner in (Compile, run))
runMain in Compile <<= Defaults.runMainTask(fullClasspath in Compile, runner in (Compile, run))
```

# 参考

以下の記事だと`sbt run-main`のときにクラスパスに含まれないので、それだけ補足しました。

- [scala - How to add "provided" dependencies back to run/test tasks' classpath? - Stack Overflow](http://stackoverflow.com/questions/18838944/how-to-add-provided-dependencies-back-to-run-test-tasks-classpath/21803413#21803413)
【Android】ロリポップからのSoundPool

今まで`SoundPool`のインスタンス化は下記のような方法でした。

```java
final int SOUND_POOL_MAX = 6;

SoundPool pool = new SoundPool(SOUND_POOL_MAX, AudioManager.STREAM_MUSIC, 0);
```

`Android 5.0 ロリポップ (API Level 21)` からこの方法は非推奨になり、次の様な書き方が推奨されます。

```java
final int SOUND_POOL_MAX = 6;

AudioAttributes attr = new AudioAttributes.Builder()
    .setUsage(AudioAttributes.USAGE_MEDIA)
    .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
    .build();

SoundPool pool = new SoundPool.Builder()
    .setAudioAttributes(attr)
    .setMaxStreams(SOUND_POOL_MAX)
    .build();
```

互換性を保つ場合は下記の様な感じになると思います。

```java
@SuppressWarnings("deprecation")
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private SoundPool buildSoundPool(int poolMax)
{
    SoundPool pool = null;

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
        pool = new SoundPool(poolMax, AudioManager.STREAM_MUSIC, 0);
    }
    else {
        AudioAttributes attr = new AudioAttributes.Builder()
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
            .build();

        pool = new SoundPool.Builder()
            .setAudioAttributes(attr)
            .setMaxStreams(poolMax)
            .build();
    }

    return pool;
}

final int SOUND_POOL_MAX = 6;
SoundPool pool = buildSoundPool(SOUND_POOL_MAX);
```
OpenGL (GLUT) で正方形が動くだけのアニメーション

[GLUTによる「手抜き」OpenGL入門](http://www.wakayama-u.ac.jp/~tokoi/opengl/libglut.html)
OpenGL についてはこのサイトが大変詳しい。あまりに詳しくて読むのが面倒な人のために、アニメーションで正方形が動くだけの最小限のコードをメモ。

筆者環境は Linux (Ubuntu 14.04).

# GLUT のインストール

```
$ sudo apt-get install freeglut3 freeglut3-dev
```

# とりあえずウィンドウを開くだけ

```c:minimum.c
#include <GL/glut.h>

/* 再描写時に実行される関数*/
void display(void) {
	/* 画面全体を指定した色で塗りつぶす */
	glClear(GL_COLOR_BUFFER_BIT);
	/* まだ実行されていない命令をすべて実行 */
	glFlush();
}

int main(int argc, char **argv){
	glutInit(&argc, argv);

	/* ウィンドウの位置とサイズを指定 */
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(400, 400);

	/* ウィンドウを生成 */
	glutCreateWindow("test");

	/* 背景色を指定: 白 */
	glutInitDisplayMode(GLUT_RGBA);
	glClearColor(1.0, 1.0, 1.0, 1.0);

	/* 画面を再描写するときに実行される関数を指定 
	   (初期化、ウィンドウサイズ変更時など) */ 
	glutDisplayFunc(display);

	/* ウィンドウが閉じられるまでループ */
	glutMainLoop();
	return 0;
}
```

コンパイルはいくつかオプションが要る

```
$ gcc minimum.c -lglut -lGLU -lGL -lm
```

# 正方形を書くだけ

```c:square.c
#include <GL/glut.h>

/* 正方形のサイズを指定 */
GLdouble s = 0.5;

/* 再描写時に実行される関数*/
void display(void) {
	/* 画面全体を指定した色で塗りつぶす */
	glClear(GL_COLOR_BUFFER_BIT);

	/* 線の色を指定: 赤 */
	glColor3d(1.0, 0.0, 0.0);

	/* 描写 */
	glBegin(GL_LINE_LOOP);

	/* 図形の頂点を指定 */
	glVertex2d(-s,-s);
	glVertex2d(-s, s);
	glVertex2d( s, s);
	glVertex2d( s,-s);

	glEnd();

	/* まだ実行されていない命令をすべて実行 */
	glFlush();
}

int main(int argc, char **argv){
	glutInit(&argc, argv);

	/* ウィンドウの位置とサイズを指定 */
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(400, 400);

	/* ウィンドウを生成 */
	glutCreateWindow("test");

	/* 背景色を指定: 白 */
	glutInitDisplayMode(GLUT_RGBA);
	glClearColor(1.0, 1.0, 1.0, 1.0);

	/* 画面を再描写するときに実行される関数を指定 
	   (初期化、ウィンドウサイズ変更時など) */ 
	glutDisplayFunc(display);

	/* ウィンドウが閉じられるまでループ */
	glutMainLoop();
	return 0;
}
```

# 正方形が膨らむアニメーション
先の正方形描写はサイズをグローバル変数 `s` で指定したので、この `s` の値を一定時間ごとに変更して画面を再描写すればアニメになる。

```c:animation.c
#include <GL/glut.h>

/* 正方形のサイズを指定 */
GLdouble s = 0.2;

/* 再描写時に実行される関数*/
void display(void) {
	/* 画面全体を指定した色で塗りつぶす */
	glClear(GL_COLOR_BUFFER_BIT);

	/* 線の色を指定: 赤 */
	glColor3d(1.0, 0.0, 0.0);

	/* 描写 */
	glBegin(GL_LINE_LOOP);

	/* 図形の頂点を指定 */
	glVertex2d(-s,-s);
	glVertex2d(-s, s);
	glVertex2d( s, s);
	glVertex2d( s,-s);

	glEnd();

	/* まだ実行されていない命令をすべて実行 */
	glFlush();
}

/* 100ミリ秒ごとに実行される関数 */
void timer(int value) {
	/* 正方形のサイズを増加 */
	s += 0.01;
	/* 画面を再描写 */
	glutPostRedisplay();
	/* 100ミリ秒後に再実行 */
	glutTimerFunc(100, timer, 0);
}

int main(int argc, char **argv){
	glutInit(&argc, argv);

	/* ウィンドウの位置とサイズを指定 */
	glutInitWindowPosition(100, 100);
	glutInitWindowSize(400, 400);

	/* ウィンドウを生成 */
	glutCreateWindow("test");

	/* 背景色を指定: 白 */
	glutInitDisplayMode(GLUT_RGBA);
	glClearColor(1.0, 1.0, 1.0, 1.0);

	/* 画面を再描写するときに実行される関数を指定 
	   (初期化、ウィンドウサイズ変更時など) */ 
	glutDisplayFunc(display);

	/* 100ミリ秒後に timer() を実行 */
	glutTimerFunc(100, timer, 0);

	/* ウィンドウが閉じられるまでループ */
	glutMainLoop();
	return 0;
}
```
S3 + Lambdaを使って、バックアップ完了をhipchatに通知する

バックアップしてますか？してますよね（自戒）

いざリカバリをする際に、肝心のバックアップジョブが正しく機能していなくて、「データがなかった」「あったあった、、、あれ、、、0byteだと...(;´༎ຶД༎ຶ`)」。。なんてことも。
しかし一々、巡回チェックはしたくありません。

そこでLambdaを使って、バックアップファイルがS3にuploadされるのをトリガーに、hipchatに自動通知してもらいましょう。

# 準備

以下2つのLibraryを開発環境にインストールしましょう

- [Hipchatter](https://github.com/charltoons/hipchatter)

```
npm install hipchatter --save
```

- [AWS-SDK](http://aws.amazon.com/jp/sdk-for-node-js/)

```
npm install aws-sdk
```

以上をインストールすると以下の通りnode_modulesディレクトリ以下に保存されます。

```
[~] ls node_modules
aws-sdk    hipchatter
```

# Lambda function

Lambda functionは以下のような感じです。

```js:index.js
console.log("Loading event")
var aws = require('aws-sdk');
var s3 = new aws.S3({apiVersion: '2006-03-01'});
var Hipchatter = require('hipchatter');

exports.handler = function(event, context) {
    console.log('Received event:', JSON.stringify(event, null, 2));
    var bucket = event.Records[0].s3.bucket.name;
    var key = event.Records[0].s3.object.key;
    var size = event.Records[0].s3.object.size;
    var hipchatter = new Hipchatter('hipchatのAPIトークン');
    s3.getObject({Bucket: bucket, Key: key},
        // hipchatへの通知処理
        function(err, data) {
            if (err){
                context.done('error', 'error getting file' + err);
            } else {
                hipchatter.notify('hipchatルームID', 
                    {
                        message: 'Backup completed : ' + key + ', file size: ' + size , // ファイル名とファイルサイズを通知
                        color: 'green',
                        token: 'hipchatルームのトークン', // 
                        notify: true
                    })
                }
        }
    );
};
```

バックアップデータのファイル名とファイルサイズをhipchatの特定ルームに通知する内容です。

## Lambda Functionのupload手順

1: Lambda Function Listの追加

詳細は省略します

2: Function Codeのupload

先ほどインストールしたnode_modules（aws-sdk, hipchatter）, index.jsをまるっとzipで固めて、uploadします

```
zip -r bkup_hipchat.zip index.js node_modules
```

3: 対象S3バケットのイベントフック作成

最後に対象S3バケットで、下図の通りEvent Notificationsを設定します。

![lambda1](https://s3-ap-northeast-1.amazonaws.com/qiita-3-shake.com/lambda_bkup_hipchat1.png)

## 確認

hipchatで確認すると...

![lambda2](https://s3-ap-northeast-1.amazonaws.com/qiita-3-shake.com/lambda_bkup_hipchat2.png)

こんな感じでお知らせしてくれました！

### 注意点

- AWS Lambdaは、2015/05現在、バージニア、オレゴン、アイルランドにしか対応していません。つまり対応するS3バケットもそこにする必要があります。

- バックアップデータが大きい場合、Lambdaがタイムアウトしてしまいます（default: 3秒）。ぐいっと30秒ぐらいにしましょう
Unityで適当に誘導ミサイル作ってみた

http://youtu.be/N-H4ytYvqN0

位置関係によってはうまく追尾できないなど問題はあります
（前方にあるうちはそこそこいける？）。
でも適当なコードで意外とそれっぽく動いて面白いです。

四方に設置した噴射器のパワーを制御して方向を変えるというモデル。
本物がどうなってるかは知りません( ˘ω˘ )
謎力で回転させるよりは説得力がある感じかな？

オブジェクトにはRigidbodyをアタッチ、半径0.5程度の物体を前提としてあります。
targetにはシーンに配置した適当なオブジェクトを設定してください。

```
using UnityEngine;
using System.Collections;

[RequireComponent(typeof(Rigidbody))]
public class MissileControl : MonoBehaviour {

    public GameObject target;
    Rigidbody _rigidbody;

    Vector3 _upEngine = Vector3.up*0.5f;
    Vector3 _downEngine = Vector3.down*0.5f;
    Vector3 _leftEngine = Vector3.left*0.5f;
    Vector3 _rightEngine = Vector3.right*0.5f;

    public float enginePower = 10.0f;

	// Use this for initialization
	void Start () {
        _rigidbody = GetComponent<Rigidbody>();
	}
	
	// Update is called once per frame
	void Update () {
        Vector3 dif = target.transform.position - transform.position;

        Vector3 difLocal = transform.InverseTransformVector(dif);

        float upPower;
        float downPower;
        float leftPower;
        float rightPower;

        float difX = difLocal.x;
        if( difX > 0 )
        {
            leftPower = 1.1f;
            rightPower = 0.9f;
        }
        else if( difX < 0 )
        {
            leftPower = 0.9f;
            rightPower = 1.1f;
        }
        else
        {
            leftPower = rightPower = 1.0f;
        }
        
        float difY = difLocal.y;
        if( difY > 0 )
        {
            upPower = 0.9f;
            downPower = 1.1f;
        }
        else if( difY < 0 )
        {
            upPower = 1.1f;
            downPower = 0.9f;
        }
        else
        {
            upPower = downPower = 1.0f;
        }

        Vector3 forward = transform.forward;
        _rigidbody.AddForceAtPosition(enginePower * upPower * forward, transform.TransformPoint( _upEngine ), ForceMode.Force);
        _rigidbody.AddForceAtPosition(enginePower * downPower * forward, transform.TransformPoint( _downEngine ), ForceMode.Force);
        _rigidbody.AddForceAtPosition(enginePower * leftPower * forward, transform.TransformPoint( _leftEngine ), ForceMode.Force);
        _rigidbody.AddForceAtPosition(enginePower * rightPower * forward, transform.TransformPoint( _rightEngine ), ForceMode.Force);
	}
}

```
PhotoshopとIllustratorで描いた円をcssで書き出してみた。


今回はPhotoshopやIllustratorに搭載しているcss書き出し機能がどれくらい使えるものか実験をしてみました。

css3をガンガン使っても問題なさそうな空気が出来上がってきたので、今まで画像で書き出していた丸い形もcss3で作っていきたいと思います。
ほとんどのブラウザで丸い形を作るためのプロパディである「border-radius」がベンダープレフィックスなしで使えるので、この記事の中ではベンダープレフィックスを付けずに書いていきます。例外として、生成されたコードにベンダープレフィックスがついていた場合は、そのまま記載していきます。

## まずは手書き
普段、手書きでcssを書いているんですが、私ならこんなかんじでcssを書いて丸い形を再現します。あっ、セレクタ部分は適当です。

	.tegaki {
		border-radius: 50%;
		width: 100px;
		height: 100px;
		background-color: pink;
	}
	
border-radiusの値を50％に指定。それから要素の幅と高さを指定して、最後に背景色をつけるという感じです。

これがPhotoshopやIllustratorだとどういうコードを生成してくれるのか？
PhotoshopやIllustratorで円を書く方法はいくつもあると思いますが、今回は「楕円形ツール」で円を書く方法と「長方形ツール」で正方形を描き角丸で円にしていく方法の2パターンでやってみました。

※PhotoshopとIllustratorのバージョンですが、どちらもcc2014の最新版で行っています。

## Photoshopで生成されるcss
最初にPhotoshopで円を描き、cssを生成しました。
### 楕円形ツールで描いた円から生成されるcss
	.ps-circle {
		border-radius: 50%;
		background-color: rgb(29, 32, 136);
		width: 100px;
		height: 100px;
	}
こんなコードになります。次に長方形ツールで描いた正方形に角丸を適用させて円にした場合。
### 長方形ツールで描いた正方形を角丸で円にしたものから生成されるcss
	.ps-square {
		border-radius: 50%;
		background-color: rgb(87, 134, 206);
		width: 100px;
		height: 100px;
	}
こんなコードになります。どちらのコードも同じものが書き出されていますよね。（色が違うのは特に意味は無いです。）

ひとつお断りをしておくと、Photoshopで生成されたcssにはこれ以外に位置や重なり順を指定するようなcssもついてきます。具体的に言えばpositonであったりz-indexだったり。
円を書くためのcssとは直接関係ないので、記述しているコードからは削除をしています。

## Illustratorで生成されるcss
次にIllustratorで円を描き、cssを生成しました。
### 楕円形ツールで描いた円から生成されるcss
	.ai-circle {
		background : #F15A24;
		background : rgba(241, 90, 36, 1);
		width: 100px;
		height: 100px;
	}
こんなコードになります。次に長方形ツールで描いた正方形に角丸を適用させて円にした場合。
### 長方形ツールで描いた正方形を角丸で円にしたものから生成されるcss
	.ai-square {
		background : #F7931E;
		background : rgba(247, 147, 30, 1);
		border-radius : 50px;
		-moz-border-radius : 50px;
		-webkit-border-radius : 50px;
		width: 100px;
		height: 100px;
	}
こんなコードになります。

Aiの楕円形ツールで書いた円は、border-radius自体が書き出されていないため、このままcssを適用しても円にはならないです。このあたりはIllustratorにもっと頑張ってもらいたいところですね。
## 考察
Photoshopが生成したコードは普段手書きするコードと似たような感じで出てきました。特にborder-radiusの値が％指定なので、円の大きさが変わっても柔軟に対応出来ます。

Illustratorが生成したコードはborder-radiusの値がpx指定。なので円の大きさが変わるたびに数値を書き換える必要が出てきます。

個人的にはwebデザインはIllustratorでと思っています。
しかし円を描くときも楕円形ツールで描くとcssが生成できないというのは衝撃的な結果でした。
わざわざ正方形を書いて角丸で丸くして円を描くなんてかなり面倒な作業ですよね。

cssの生成という点ではいまのところPhotoshopの方が柔軟に対応してくれそうです。
繰り返しになりますが、、、もう少しIllustratorには頑張ってもらいたいところです。
#pragma markで見通しを良くする


**#pragma mark** とは、ソースコード上に記載することで、
Xcode 上の Function Menu? (Function List?) に見出しを付けることができます。

小さいクラスにはあまり効果を発揮しませんが、
メソッドがたくさん増えた大きなクラスには効果があります。

こんな感じです。

**Before**
![20150513183318.png](https://qiita-image-store.s3.amazonaws.com/0/53393/3b3b1893-e514-2e01-c54d-04f91e34c9d6.png)

**After**
![20150513183224.png](https://qiita-image-store.s3.amazonaws.com/0/53393/23be2d0b-10b4-0862-45a5-5ed620fbc594.png)

今回利用したソースコードは、
ViewControllerにTableViewとButtonを貼りつけただけの単純なものです。

TableViewを利用するときは、
dataSourceやdelegateプロトコルを使うので、
**#pragma mark** を付けやすそうだったのでサンプルに採用しました。

# 使い方

「区切り線あり」と「区切り線なし」の2種類があります。

```objc:区切り線あり
#pragma mark - 区切り線あり
```

```objc:区切り線なし
#pragma mark 区切り線なし
```

表示のされ方は以下の通りです。
区切り線ありの場合は自分の頭に区切り線が入ります。
![20150513190411.png](https://qiita-image-store.s3.amazonaws.com/0/53393/4b82b96f-d580-084c-d545-8d11372e3c71.png)

# その他

```objc
// MARK: message
// TODO: message
// FIXME: message
// !!!: message
// ???: message
```

上記を入れることで同じようにFunction Menuに表示することができます。
上記以外はただのコメントとして扱われるようです。
ついでに「**//MARK: - message**」では、区切り線は付きませんでした。

![20150513192838.png](https://qiita-image-store.s3.amazonaws.com/0/53393/c0dc2850-d381-72a1-7a0f-cfae64ea0e05.png)

# Swiftでは...

**#pragma mark** は使えません。
代わりに

```swift
// MARK: mark
// MARK: - mark
```

が使うことができました。
補足として、Swiftでは「**// MARK: - mark**」で区切り線が付くようです。

その他、
// TODO: message
// FIXME: message
もFunction Menuに表示されます。

!!!と???は対応していないようです。

# 最後に
[Swiftで #pragma mark - を使う](http://qiita.com/nacika_ins/items/b9ac96bc4e22d974cd00) も参考にさせて頂きました。
さくらのVPSにnginxとNode.jsの環境を構築したメモ

サーバ：さくらのVPS 1G HDDプラン
OS：標準OS（CentOS 6 x86_64）

OSのインストール、サーバの起動と[初期設定](https://help.sakura.ad.jp/app/answers/detail/a_id/2429/)は完了しているものとして。あと、80番ポートをiptablesで開けておく。

## nginxのインストール
```text:command
# rpm -ivh http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm
# yum -y install nginx
```

## nginxを起動する
```text:command
# /etc/init.d/nginx start
```

「http://<配布されたグローバルIP>」 にアクセスして、ブラウザの中央に以下のようなものが表示されていればOK。

![WS000005.jpg](https://qiita-image-store.s3.amazonaws.com/0/21867/53f9c16a-89d9-f764-449a-e262a3bfff14.jpeg)


## Node.jsとnpmのインストール
```text:command
# curl -L https://www.npmjs.com/install.sh | sh
# npm update -g npm
# npm cache clean
# npm install -g n
# n stable
# node -v
# npm -v
```

## expressとpm2のインストール
```text:command
# npm install -g express
# npm install -g express-generator
# npm install -g pm2
```

## 適当な場所にexpressのプロジェクトを作成する
```text:command
# express sample_app
```

## pm2を利用してexpressのプロジェクトを起動する
```text:command
# cd sample_app
# pm2 start bin/www
```

## 動作確認
```text:command
# curl http://localhost:3000
```

わざわざポートを開けて、あれこれするのが面倒だったため、curlで内部から動作確認するのみで。HTMLのタグが表示され、さらに「Express」と書かれている部分があればOK。

## nginxの設定ファイルを修正する
```text:command
# cd /etc/nginx/conf.d
# vi default.conf
```

```text:/etc/nginx/conf.d/default.conf
upstream node-backend {
    server localhost:3000;
}

server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/log/host.access.log  main;
    charset utf-8;
    access_log /var/log/nginx/default.access.log main;
    error_log /var/log/nginx/default.error.log;

    proxy_redirect                      off;
    proxy_set_header Host               $host;
    proxy_set_header X-Real-IP          $remote_addr;
    proxy_set_header X-Forwarded-Host   $host;
    proxy_set_header X-Forwarded-Server $host;
    proxy_set_header X-Forwarded-For    $proxy_add_x_forwarded_for;

    location / {
        #root   /usr/share/nginx/html;
        #index  index.html index.htm;
        proxy_pass http://node-backend;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    #（以下略）
}
```

nginxを再起動する。

```text:command
# /etc/init.d/nginx restart
```

先ほどのページに再度アクセスし、ブラウザの左側に以下のような表示がされれば、全て終了。お疲れさまでした。

![WS000006.jpg](https://qiita-image-store.s3.amazonaws.com/0/21867/2acae2ed-8d35-2e46-5493-177b4a240965.jpeg)
PHP trait の罠

### 罠ってほどでもない
例えば下のようなコードがあったとします。

```php
<?php
trait A
{
    public function hoge()
    {
        echo 'hoge' . PHP_EOL;
    }

    public function fuga()
    {
        echo 'fuga' . PHP_EOL;
    }
}

trait B
{
    public function hoge()
    {
        echo 'hogeB' . PHP_EOL;
    }

    public function fuga()
    {
        $this->hoge();
    }
}

class C
{
    use A, B {
        A::hoge insteadof B;
        A::fuga insteadof B;
        B::hoge as hoge2;
        B::fuga as fuga2;
    }

    public function main()
    {
        $this->hoge();
        $this->fuga();
        $this->hoge2();
        $this->fuga2();
    }
}

$instance = new C();
$instance->main();

```

要するに、同じメソッド名を持つトレイトをクラスに取り込んだ上で、Aのメソッドを優先し、Bのメソッドにはエイリアスをつける、というようなコードです。
さて、上記のコードを実行すると何が出力されるでしょう？

### 答え
```
% php test.php
hoge
fuga
hogeB
hoge
```

### どういうことだってばよ…
つまり、```C::main()``` で ```$this->fuga2()``` を呼んだとき、```B::fuga2()``` の中身は「```B::hoge()``` を実行せよ」という意味ではなく「```C::hoge()```（つまり ```A::hoge()```）を実行せよ」と解釈されるため、```B::hoge()``` が呼ばれることはない、ということなんですねー。

### 応用
以下の様な感じでインターフェイスとトレイトを使えばこんなことも。

```php
<?php
interface A
{
    public function hoge();
    public function fuga();
    public function piyo();
}

trait B
{
    public function hoge()
    {
        return 'hoge';
    }
}

trait C
{
    public function fuga()
    {
        echo $this->hoge() . PHP_EOL;
        echo $this->piyo() . PHP_EOL;
    }
}

class D implements A
{
    use B;
    use C;

    public function main()
    {
        $this->fuga();
    }

    public function piyo()
    {
        return 'piyo';
    }
}

$instance = new D();
$instance->main();
```

```
% php test.php
hoge
piyo
```
【Rails】Turnip + RSpec + Capybara + Selenium でエンドツーエンドテスト

RailsでTurnip + RSpec + Capybara + Seleniumを使ってエンドツーエンドテストを書いていこうと始めてみたので方法をメモしてみます。

今回はエンドツーエンドテストをして失敗したところや詳しくテストしていきたいところに関してユニットテストを書いていく感じにしようと思ってます。

![64e2ae34-63f4-490a-8c8d-a5dc557509d5.png](https://qiita-image-store.s3.amazonaws.com/0/47886/27063dea-5233-4811-92dd-1a69649fb19f.png)

Turnipでシナリオを作成して、RSpec,Capybaraで実際にブラウザを操作しながらテストしてく感じだと思います。その際Capybaraでスクリーンショット撮ったりしながら進めます。

# 設定

まずは今回使用したgemたちです。

```rb:Gemfile
group :development, :test do
  gem 'rspec-rails', '~> 3.1.0'
  gem 'factory_girl_rails', '~> 4.4.1'
  gem 'capybara', '~> 2.4.3'
  gem 'selenium-webdriver'
  gem 'turnip'
end
```

```bash
bundle
rails g rspec:install # rspecのインストール
```

.rspecに以下を追加します。

```txt:.rspec
-r turnip/rspec
```
spec_helper.rbに以下を追加します。

```rb:spec_helper.rb
Dir.glob("spec/**/*steps.rb") { |f| load f, true }

  require 'capybara/dsl'
  require 'capybara/rspec'
  require 'turnip'
  require 'turnip/capybara'

  Capybara.default_driver = :selenium
  Capybara.ignore_hidden_elements = true
  Capybara.run_server = false

  # Chrome
  Capybara.register_driver :selenium do |app|
    Capybara::Selenium::Driver.new(app, browser: :chrome)
  end
```

specディレクトリ配下に以下のディレクトリを作成します。

```
spec/features  # .featureファイル置き場
spec/steps     # steps.rbファイル置き場
```

selenium用にchromeドライバをインストールします。

[chromedriver](http://chromedriver.storage.googleapis.com/index.html)をダウンロード）してきます。

```bash
sudo mv ~/Downloads/chromedriver /usr/bin/
```

ここまでで準備は完了です。

# サンプル

ディレクトリ構成

```
spec/features/login.feature
spec/steps/login_steps.rb
```

```feature:login.feature
# encoding: utf-8
# language: ja
機能:　ログイン画面からログイン
  シナリオ:　ログイン画面にアクセスしてログインする
    前提 hogehogeにアクセスする
    もし ログイン画面を表示する
    ならば ログイン画面が表示されていること
    かつ emailとpasswordを入力する
    かつ ログインボタンをクリックする
    ならば 画面に username が表示されること
```

```rb:login_steps.rb
# coding: utf-8
require 'rails_helper'

step 'hogehogeにアクセスする' do
  Capybara.app_host = 'http://localhost:3000/'
end

step 'ログイン画面を表示する' do
  visit 'http://localhost:3000/users/sign_in'
  page.save_screenshot 'spec/tmp/screenshots/login/page.png'
end

step 'システムログインが表示されていること' do
  expect(page).to have_content 'システムログイン'

end

step 'emailとpasswordを入力する' do
  fill_in 'user[email]', with: 'exapmle@hogehoge.com'
  fill_in 'user[password]', with: 'hogehoge'
  page.save_screenshot 'spec/tmp/screenshots/login/input.png'
end

step 'ログインボタンをクリックする' do
  click_on 'ログイン'
end

step "画面に :user が表示されること" do |user|
  expect(page).to have_content (user)
  page.save_screenshot 'spec/tmp/screenshots/login/success.png'
end
```

# 参考

Rails - Selenium(Capybara)でChromeを使う - Qiita
http://qiita.com/quattro_4/items/561c145fcbca28718ac7

Rubyist Magazine - エンドツーエンドテストの自動化は Cucumber から Turnip へ
http://magazine.rubyist.net/?0042-FromCucumberToTurnip#l36

Amazon.co.jp： Ruby徹底攻略 (WEB+DB PRESS plus): 角 征典, 成瀬 ゆい, そらは(福森 匠大), 田中 哲, 笹田 耕一, 村田 賢太, まつもと ゆきひろ, 松田 明, 後藤 大輔, 浦嶌 啓太, 高橋 健一, 柴田 博志, 近藤 宇智朗, 大和田 純, 白土 慧, 原 悠(yhara), 伊藤 直也, WEB+DB PRESS編集部: 本
http://www.amazon.co.jp/Ruby%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5-WEB-DB-PRESS-plus/dp/4774165344