自分用・Rubyチートシート

# 概要
　読んで字の如し(※時々書き換えます)

# 基本
- 三項演算子は判定式?真の場合:偽の場合
- <=>演算子は「左が大きければ 1, 等しければ0, 右が大きければ -1」という意味
- sprintfはC言語と大体一緒。**#で接頭辞、+で符号(' 'で符号分の空白)、-で左寄せ、.で精度**
- 外部ファイル実行は**system(何か)**とすれば幾らでも可能。標準出力を垂れ流す場合はリダイレクトで握り潰せる
- Marshal.dump(hoge)でオブジェクトhogeをStringにできる。逆にMarshal.load(str)とすると元に戻せるので**ディープコピーに使える**
- 多次元配列の初期化で```Array.new(3,Array.new(3))```などとするのはNG。```Array.new(3){Array.new(3)}```と書こう
- 複数行改行は**=beginで初めて=endまで。**C++等より不便なのはご愛嬌
- **複数の戻り値を関数から返す**場合、Rubyの場合は**多重代入**で書ける。つまり、`return a,b`を`a,b=func()`で受け取れる。
- 無限ループを書く場合、イテレータ不要なら`loop{ブロック}`か`while true ～ end`、必要なら`1.upto(0/0.0){|i|ブロック}`とする
- 複数行の標準入力を受け取る場合、`STDIN`をファイル扱いできるので`STDIN.each`や`STDIN.read.split("\n")`できる
- 破壊的メソッドを自作する場合は、自作クラスの場合フツーにメンバ変数(@xなど)を書き換えれば良し、モンキーパッチの場合はself.replace(新しい中身)とすれば良し
- Object#cloneおよびObject#dupメソッドは[オブジェクトを「浅く」コピーする](http://ref.xaio.jp/ruby/classes/object/clone)。
- 乱数の基本：`random = Random.new`してから`random.rand`や`random.rand(1..6)`など

# 正規表現
- 正規表現内に**文字列変数を埋め込む場合は/#{str}/**などとする
- \wは[a-zA-Z0-9_]、\sは空白文字[\t\r\n\f\v]、\dは10進数字[0-9]、\hは16進数字[0-9a-fA-F]に対応する
- {n}はちょうどn回、{n,}はn回以上、{,n}はn回以下、{n,m}はn～m回
- \*・+・?・{}は**末尾に?を追加すると最短マッチング**する
- **正規表現における「.」は通常改行の\nにマッチしない。**`/hoge./m`のように、`/～/`を`/～/m`とすればマッチするようになる

|pattern|名称|意味|
|:------|:-----|:--|
|(?=pat)|肯定先読み|ある位置から続く文字列とマッチする|
|(?!pat)|否定先読み|ある位置から続く文字列とマッチしない|
|(?<=pat)|肯定後読み|ある位置の直前までの文字列とマッチする|
|(?<!pat)|否定後読み|ある位置の直前までの文字列とマッチしない|

# String
##検索系
- empty?：**空文字列ならtrue**
- include?(str)：**strが含まれていたらtrue**
- index(pattern[,int])：**patternが含まれる位置を返す**(無ければnil)**。intは最初の検索位置で、負数だと末尾からの位置**
- [int]：**その位置の文字を返す。負数だと末尾から数える**
- [pos,len]：**posからlen文字**
- [pattern]：**マッチした最初の部分**
- str=~regexp：**マッチしたらその位置を整数で返す**
- match(pattern)：**hogeとマッチした部分を返す。()を使うと該当箇所が配列で取得できる**
- scan(pattern)：**hogeとマッチしたすべての部分を配列で返す**
- StringにStringを末尾に足す場合、+=より<<を使う方が速い。つまり「str+=a」より「str<<a」の方が良い

##変換系
- [pattern]=str：**patternとマッチした部分文字列をstrで置き換える**
- gsub(pattern,str)：**patternとマッチした全ての部分をstrで置き換える**
- gsub(pattern,hash)：**hashは{マッチした文字列=>置換文字列}と指定**
- gsub(pattern){|match| block}：**マッチ箇所に対してブロックを実行**
- sub：**hogeとマッチした最初の部分をfugaで置き換える**
- split(pattern)：**分割して配列を返す**(未指定なら空白、""なら1文字づつ区切る)
- strip：**先頭と末尾の空白文字(半角空白と制御文字)を除去**
- each_line{|line| block}：**改行で分割してブロック処理**
- each_line(str){|line| block}：**strを改行文字とする**
- chomp：**末尾の改行を取り除く**
- upcase,downcase：**小文字を大文字にする,大文字を小文字にする**
- swapcase：**小文字を大文字に、大文字を小文字にする**
- capitalize：**英字を先頭大文字・後小文字に変換する**
- 全角英数字を半角英数字に(その1)：`str.tr('０-９ａ-ｚＡ-Ｚ', '0-9a-zA-Z')`
- 全角英数字を半角英数字に(その2)：`NKF.nkf('-m0Z1 -Ww', "ガルパン")` ※文字コード依存。入力がSJISなら-S、出力がEUCなら-eとなる
- とりあえず一通り正規化させたい(unf)：`UNF::Normalizer.normalize(text, :nfkc)`
- とりあえず一通り正規化させたい(unicode)：`Unicode::nfkc('㈱㌧㌦Ⅲ')`
- 濁点半濁点を弾きたい：まず`require 'unf'`してから`str.to_nfd`で**「ガルパン」を「カ゛ルハ゜ン」に変換**。その後は濁点と半濁点をgsub等で排除すればいい。ただし、この際の**濁点と半濁点はUnicodeの奴**なので`\u3099`と`\u309A`として扱うこと。

## その他
- 文字列内に**文字列でない変数を埋め込む場合は"#{val}"**などとする

# Array
- index(obj)：**objがある位置を返す**(存在しない場合はnil)
- [index, length]：**index番目の要素からlength個だけ抜き出す**
- slice!(index)：**index番目の要素を削除する**。
- slice!(index, length)：**index番目の要素からlength個だけ削除する**。
- all?{|item| block}：**ブロックの戻り値が全て真ならtrue**
- uniq：**重複を削除した配列を返す**
- count(obj)：**objと同じ要素の数**(ブロックを渡すと、ブロックが真になった要素数)
- shuffle：**要素をシャッフルする**
- sample：**要素をランダムに返す**
- array.product(other_array, ...)：**要素積を作成する**
- unshift,push：**配列の先頭および末尾に要素を追加する**
- shift,pop：**配列の先頭および末尾の要素を削除する**
- rotate(int)：**intだけ要素を循環シフトする(正の数で左向き)**
- transpose：**配列の行と列を入れ替える**
- permutation([n]){|arr| block}：**順列を生成してarrに順次代入する**
- combination([n]){|arr| block}：**組み合わせを生成してarrに順次代入する**
- repeated_combination([n]){|arr| block}：**重複組合せを生成してarrに順次代入する**
- 逆順にソートしたい：`array.sort{|a, b|b <=> a}`**のようにする**
- 2次元配列：`Array.new(3){Array.new(4)}`と、**ブロックを作成して初期化すること**

# Hash
- has_key?(key)：**keyと同じキーがあればtrue**
- hash.has_value?(val)：**valと同じ値があればtrue**
- merge(other_hash)：**他のハッシュと結合する**
- delete(key)：**指定したキーに一致する{キー => 内容}を削除する**(戻り値はキーの値だがキーが存在しない場合はnil)
- Hash.new(obj)：**ハッシュのデフォルト値をobjとする**
- default(obj)：**ハッシュのデフォルト値を返す(=演算子で変更可能)**
- keys,values：**キーや値の一覧を配列で返す**
- assoc(key)：**あるキーを持つキー・値のペアを配列として取り出す**(配列版もある)
- rassoc(val)：**ある値を持つキー・値のペアを配列として取り出す**(配列版もある)
- 配列をハッシュにその1：**配列ary=[[key1,val1],[key2,val2],...]を用意して「```hash=Hash[*ary.flatten]」```**
- 配列をハッシュにその2：**配列keyとvalを用意して「```ary=[key,val].transpose;hash=Hash[*ary.flatten]」```**
- ハッシュを配列に：**個別ならkeysかvaluesメソッド、両方ならto_aメソッドでいい**
- キーでソート：**hash.sort_by{|key,val| key}とする**(これをすると配列に変換されるので注意)
- 値でソート：**hash.sort_by{|key,val| val}とする**(これをすると配列に変換されるので注意)

# Enumerable
選択系

- select：**trueになる要素だけ**：```[1,2,3,4,5,6].select{|n| n%2==0} => [2,4,6]```
- reject：**falseになる要素だけ**：```[1,2,3,4,5,6].reject{|n| n%2==0} => [1,3,5]```
- find：**trueになる最初の要素**：```[1,5,8,2,6,3].find{|n| n%3==0} => 6```
- find_index：**trueになる最初の要素のインデックス**：```[1,5,8,2,6,3].find_index{|n| n%3==0} => 4```
- grep：**マッチする要素だけ**：```['a1','bb','c2','dd','5e'].grep(/[0-9]/) => ["a1","c2","5e"]```
- take_while：**falseになる手前の要素まで**：```[1,2,3,4,5,6].take_while{|i| i<3} => [1,2]```
- drop_while：**falseになった以降の要素すべて**：```[1,2,3,4,5,6].drop_while{|i| i<3} => [3,4,5,6]```
- min,max,minmax：**最小値,最大値,最小値と最大値の配列**：```[1,"3",5].max{|a, b|a.to_i<=>b.to_i} => 5```
- join：**配列全体をto_sして結合する**：``[1,2,3,4,5,6].join =>'123456'``

全体系

- collect/map：**式を実行した結果**：```[1,2,3].map{|n| n*3} => [3,6,9]```
- 全要素を整数に変換：```map(&:to_i)```
- inject/reduce：**最後までのブロックの実行結果**：``[1,2,3,4,5].inject(10){|result,item| result+item} => 25```
- group_by：**結果をキー、対応する要素の配列を値とするハッシュ**：``[1,2,3,4,5,6].group_by{|i| i%2} => {1=>[1,3,5],0=>[2,4,6]}```
- sort_by：**<=> 演算子で比較し、昇順にソート**：``[1,5,7,2,4,9].sort_by{|v| -v} => [9,7,5,4,2,1]```

RoR拡張

- include?：**含まれている場合true**：``[1,2,3].include?(5) => false``
- exclude?：**含まれていない場合true**：``[1,2,3].exclude?(5) => true``
- any?：**条件を満たす要素が1つ以上ある場合にtrue**：``[1,2,3,4,5].any?{|n| n<2} => true``
- many?：**条件を満たす要素が2つ以上ある場合にtrue**：``[1,2,3,4,5].many?{|n| n<2} => false``
- sum：**各要素内の合計**：``[1,2,3].sum => 6``

# ファイル関係

- File.exist?(path)：**ファイルやフォルダの存在を確認する**
- File.read(path)：**ファイルを読み込んで格納する**
- File.delete(path)：：**ファイルを削除する**
- ファイル書き込みその1：``io=File.open(path,"w")``**してから**``io.puts``**して``**io.close``**する**
- ファイル書き込みその2：``IO.write(path,x)``**とすれば式xをそのまま書き出せる**
- ファイル書き込みその3：``open(path, "w"){|f|f.putsなど}``**とすれば自動でcloseしてくれる**
- Shift_JISで入力：``'r:SHIFT_JIS'``**と指定する。UTF-8にしたい際は**``r:SHIFT_JIS:UTF-8``**とする**
- Shift_JISで出力：``'w:SHIFT_JIS'``**と指定する**
- 複雑な文字変換：``NKF.nkf(option, str)``
- 文字コード変換：**String#encodeを使う。**``str.encode("EUC-JP")``**など**
- 文字コード変換でエラー回避：``str.encode("Shift_JIS", :invalid => :replace, :undef => :replace)``
- 文字コード周りでArgumentError：``Encoding.default_external = "UTF-8"``
- ファイル名を取り出す：`File.basename("/home/user/bin/ruby/file.rb")`
- ディレクトリ名を取り出す：`File.dirname("/home/user/bin/ruby/file.rb")`
- 拡張子を取り出す：`File.extname("/home/user/bin/ruby/file.rb")`
- dirnameとbasenameした結果の配列を返す：`File.split("/home/user/bin/ruby/file.rb")`
- dirnameとbasenameを結合する：`File.join("/hoge", "hoge.txt")`
- 相対パスを絶対パスに変更：`File.expand_path("../../../bin")`

#Nokogiri
- データ分析：`doc = Nokogiri::HTML.parse(html, nil, charset)`
- タイトル：`doc.title`
- 要素取得(css)：`doc.css('dic[class="hoge"]')`
- 要素取得(xPath)：`doc.xpath('//div[@class="hoge"]')`
- 属性値の部分：`doc.css('a').attribute('href').value`

#Mechanize
- インスタンスの生成：`agent = Mechanize.new`
- ページの取得(Mechanize::Page)：`page = agent.get("http://hoge.com")`
- 要素取得(全て)：`elements = page.search('title')`
- 要素取得(最初の1件のみ)：`elements = page.at('li a')`
- タグ内部の部分：`text = ele.inner_text`
- 属性値の部分：`url = element.get_attribute(:href)`か`url = element[:href]`
- BASIC認証を行う：`agent.add_auth('http://example.org', 'admin', 'password')`
- UA偽装：`agent.user_agent_alias = 'Windows IE 9'`
- UA偽装例：`Windows Mozilla`、`iPhone`、`Mac Safari`
- プロキシサーバ(ユーザー名以降は端折れる)：`agent.set_proxy('proxy.example.com', 8080, 'admin', 'password')`
- 不正なSSL認証を無視する：`agent.verify_mode = OpenSSL::SSL::VERIFY_NONE`
- ファイルダウンロード：`data = agent.get_file('http://example.com/file.zip')`
- POSTでパラメータを指定して投げつけ、結果を受け取る：`response = agent.post("http://hoge.com/", {param1: "1", param2: "2"})`して、response.bodyが本体、response.codeがステータスコード？

# Capybara
- PhantomJSをpoltergeist経由で使用するための準備：

```
Capybara.register_driver :poltergeist do |app|
	Capybara::Poltergeist::Driver.new(app,
	{:js_errors => false, :timeout => 1000})
end
```
- インスタンスの生成：`session = Capybara::Session.new(:poltergeist)`
- BASIC認証：`session.driver.basic_authorize('admin', 'password')`
- ページの遷移：`session.visit url`
- ボタンをクリック：`click_button 'button'`
- リンクをクリック：`click_link 'link'`
- ボタンかリンクをクリック：`click_on 'target'`
- リンク付き画像をクリック(Alt属性を参照)：`click_on 'Alt'`か`click_link 'Alt'`
- hiddenに値をセット：`find('#secret', visible: false).set('secret')`
- テキストボックスを埋める(idかnameかplace_holderで指定可能)：`fill_in 'user_name', with: '山田太郎'`
- セレクトボックスを選択：`select '項目1', from: 'list'`
- チェックボックスをチェック：`check 'use_option'`か`uncheck 'use_option'`
- HTMLソース：`session.body`
- HTMLソースを保存：`session.save_page('hoge.html')`
- スクショ(PhantomJSを操っている場合でも使える)：`session.save_screenshot('hoge.png')`
- タグ検索：

```
# 当てはまるタグ全て(Capybara::Elementを返す)
`session.all(:css, 'a#person_123')` //CSSセレクタ
`session.all(:xpath, '//a[@id="person_123"]')` //XPathセレクタ
# 当てはまる先頭タグ(Objectを返す)
`session.first(:css, 'a#person_123')` //CSSセレクタ
`session.first(:xpath, '//a[@id="person_123"]')` //XPathセレクタ
```
- タグから結果を抜き出す：`hoge[:attribute]`で要素の値、`hoge.value`でvalue要素、`hoge.text`でinner_textの値

# Date
- インスタンス作成1：`date = Date.new(2016,6,3)`
- インスタンス作成2：`date = Date.today`
- インスタンス作成3：`date = Date.strptime('2014年6月2日','%Y年%m月%d日')`
- 月末からのオフセット：`day = Date.new(2016, 5 , -1) #2016/5/31`
- 読み出し用メソッド：`year, month, day, wday(曜日), yday(通算日)`
- Date→文字列：`str = date.strftime("%Y-%m-%d %H:%M:%S")`
- 現在時刻：`Time.now`

# JSON
- JSON文字列→配列・ハッシュ：`data = JSON.parse(str)`
- 配列・ハッシュ→JSON文字列：`str = JSON.generate(data)`か`str = obj.to_json`
- 整形しつつJSON化：`str = JSON.pretty_generate(data)`
- parseとgenerateはJSON#[]で置き換えられる(省略記法)

# 参考資料
~~[Rubyリファレンス](http://ref.xaio.jp/ruby)~~
~~[Ruby 1.9.3 リファレンスマニュアル > 正規表現](http://docs.ruby-lang.org/ja/1.9.3/doc/spec=2fregexp.html)~~
[配列からハッシュを作成する](http://www.rubylife.jp/ini/hash_class/index7.html)
[selectなどの配列の抽出・検索を行うメソッドまとめ](http://qiita.com/shibukk/items/7dded3e74b0f7dbfb633)
[mapなどの配列の値を操作するメソッドまとめ](http://qiita.com/shibukk/items/d985d014de598d925b8b)
[Ruby on Railsで拡張されているEnumerableのメソッドまとめ](http://qiita.com/shibukk/items/f85808913060cbfca16e)
[【Ruby】よく使うFileクラスを使ったファイル読み込み処理](http://qiita.com/mogulla3/items/fbc2a46478872bebbc47)
[Rubyの破壊的メソッドと参照の値渡し](http://qiita.com/metheglin/items/ca452bc0a3866d2de7bf)
[Marshalで配列やハッシュをディープコピーする](http://rubytips86.hatenablog.com/entry/2014/04/06/215055)
[Rubyでかな/カタカナ（全角のみ）の濁点を本体の文字と分ける](http://kotatu.org/blog/2014/03/15/ruby-separate-dakuten/)
[Rails スクレイピング手法 Mechanizeの使い方](http://qiita.com/shizuma/items/d04facaa732f606f00ff)
[文字列の表記揺れをUnicode正規化で簡単に解決する方法](http://qiita.com/y-ken/items/d08eb7f66c8fb2fa7d21)
[ファイル名/フォルダ名の抽出など](http://blog.systemjp.net/entry/20100510/p4)
[使えるRSpec入門・その4「どんなブラウザ操作も自由自在！逆引きCapybara大辞典」](qiita.com/jnchito/items/607f956263c38a5fec24)