snippet: ruby

## CentOS6でRuby2系を入れる

* 公式パッケージが1.8止まり
* [CentOS 6でrubyのRPMパッケージを作る - ソフトウェアエンジニアリング - Torutk](http://www.torutk.com/projects/swe/wiki/CentOS_6%E3%81%A7ruby%E3%81%AERPM%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%82%92%E4%BD%9C%E3%82%8B)

から ruby-2.2.3-1.el6.x86_64.rpm, ruby-2.1.7-1.el6.x86_64.rpm を利用させてもらうか、

* [RPM resource Ruby](http://rpmfind.net/linux/rpm2html/search.php?query=Ruby)からsrpmとってきてビルドする。
* rbenvで入れるのもよいかと

## ファイル書き込み

```rb
File.open("tmp.txt", "a+") do |f|
  f.print "あいうえお"
end
```


## カレントディレクトリ

```rb:
Dir.pwd

Dir.glob(Dir.pwd+"/img/1*.jpg").sort.each do |img|
  p img
end
```

## bundleコマンド

* `Gemfile`に書いてあるgemをインストールする。

```bash:bundleコマンドのインストール
gem install bundler
```

```bash:
# システム全体に入ってしまうため、カオスになる！
bundle install

# gemをvendor/bundlerにまとめて保管。
bundle install --path=vendor/bundler

# vendor/bundler/ruby/2.0.0/bin/ のコマンドを使えるようにいい感じにしてくれる君
bundle exec qiita_scouter a yokomotod
```

## bundle installが失敗する場合

```bash:エラー内容
$ sudo bundle install
Gem::RemoteFetcher::FetchError: bad response Not Found 404 (https://rubygems.global.ssl.fastly.net/gems/rspec-core-3.3.1.gem)
An error occurred while installing rspec-core (3.3.1), and Bundler cannot continue.
Make sure that `gem install rspec-core -v '3.3.1'` succeeds before bundling.
```

```bash:対処
gem install rubygems-update
update_rubygems
```

## rspec入門

* 参考: [Ruby - はじめてのRSpec - まずテスト書いてからコード書くシンプルなチュートリアル - Qiita](http://qiita.com/luckypool/items/e3662170033347510c3c)

```bash:rspecコマンドを入れる
gem install rspec
```

```bash:ディレクトリ作成
rspec --init
```

```bash:使い方
rspec spec/〜.rb
```

## 端数を切り捨てて単位をつける方法

```rb:
def to_jpn_unit(num)
  if num > 10**12
      (num/10**12).to_s + "兆"
  elsif num > 10**8
      (num/10**8).to_s + "億"
  elsif num > 10**4
      (num/10**4).to_s + "万"
  end
end

p to_jpn_unit(12312133) #"1231万"
p to_jpn_unit(12312133000) #"123億"
p to_jpn_unit(1231213000003) #"1兆"
```

## 改行を置換

```bash:
ruby -pe 'gsub(/\n/,"")' a.txt
```

## gemをオフラインインストール

* [gem をオフラインでインストールする方法 - present](http://tnakamura.hatenablog.com/entry/2014/07/03/113000)

```rb:
bundle package
```

vendor/cache/ を新しいrailsプロジェクトにコピー

```rb:
bundle install --local
```

## 変数

* [staedy - Ruby Steady 1 変数と代入 - Qiita](http://qiita.com/kyohei8/items/5941477037df9b6cde98)

```rb:グローバル変数(先頭が$)
def foo
 $greeting = "Hello"
end
p $greeting #Hello"
```

```rb:定数(先頭がアルファベットの大文字)
Const = "Hello Ruby!"
p Const #Hello Ruby!
```

```rb:現在実行されているプログラムのファイル名
p __FILE__
```

```rb:現在実行されている行
p __LINE__
```

## インクリメント・デクリメント

* [Rubyにないもの - Qiita](http://qiita.com/jkr_2255/items/cb05789a8abd163bb87d#%E3%82%A4%E3%83%B3%E3%82%AF%E3%83%AA%E3%83%A1%E3%83%B3%E3%83%88%E3%83%87%E3%82%AF%E3%83%AA%E3%83%A1%E3%83%B3%E3%83%88)

```rb:
a += 1
```

## 処理の中断

* [module function Kernel.#abort](http://docs.ruby-lang.org/ja/2.2.0/method/Kernel/m/abort.html)

```rb:
exit 0
```

```rb:
exit 1
```

```rb:
abort "終了します"
```

## 引数

```rb:
if ARGV.length != 1 then
  abort "引数の数が1ではないので終了します。"
end
```

```rb:
yyyymmdd = ARGV[0]
p yyyymmdd
```

## ヒアドキュメント

```rb:
body <<-EOS
こんにちは
こんばんわ
EOS
```

## if

* [制御構造](http://docs.ruby-lang.org/ja/2.2.0/doc/spec=2fcontrol.html)

```rb:
age = 1
if age >= 12 then
  p "adult fee\n"
else
  p "child fee\n"
end
```

```rb:三項演算子
age = 1
p (age >= 12) ? "adult" : "child"
```

## mail送信

* [Rubyでメールを送る - Qiita](http://qiita.com/KitaitiMakoto/items/688d383dc831c8b9a7f9)
* [Ruby + gem mailでメール送信時、「post_connection_check」「Non US-ASCII detected 」 - Symfoware](http://symfoware.blog68.fc2.com/blog-entry-1355.html)

```rb:send.rb
require "mail"

mail = Mail.new do
  from    "user1"
  to      "user2"
  subject "kenmei"
  body    "honbun"
end

mail.delivery_method :smtp, {
  enable_starttls_auto: false,
}
mail.charset = 'utf-8'
mail.deliver!
```

> /usr/lib/ruby/2.1.0/openssl/ssl.rb:232:in `post_connection_check': hostname "127.0.0.1" does not match the server certificate (OpenSSL::SSL::SSLError)

と出るときは`enable_starttls_auto: false,`つければ送れる。

* archlinuxの場合`pacman -Sy ruby-mail`しておく。

### mail送信2

* [Ruby mailに添付ファイルをつける - Qiita](http://qiita.com/azusanakano/items/b6b5f4371937b7df0650)

```send.rb
require "mail"

mail = Mail.new do
  from    "from@example.co.jp"
  to      "to@example.co.jp"
  subject "subject text"
  body    File.read("body.txt")
  add_file "picture.jpg"
end

mail.delivery_method :smtp, {
  address:   'example.co.jp',
  port:      587,
  domain:    'example.co.jp',
  user_name: 'user1'
  password: 'oodieQu3'
  enable_starttls_auto: false,
}

mail.deliver!
```

## ruby1.8以下のハッシュの書き方

* [ruby - odd number list for Hash on very basic script - Stack Overflow](http://stackoverflow.com/questions/18032777/odd-number-list-for-hash-on-very-basic-script)

```rb:1.8まで
mail.delivery_method :smtp, {
  :enable_starttls_auto => false,
}
```

```rb:1.9以降
mail.delivery_method :smtp, {
  enable_starttls_auto: false,
}
```

## mailcatcher

* [MailCatcher](http://mailcatcher.me/)

![m1.png](https://qiita-image-store.s3.amazonaws.com/0/25728/b05ef340-9985-1a2d-7fed-fd9bb535dbfe.png)


```bash:
gem install mailcatcher
mailcatcher -f
```

* http://127.0.0.1:1025/  : smtpポート
* http://127.0.0.1:1080/  : mailcatcherのWebUI

### 例

* [File: README — Documentation for mail-iso-2022-jp (1.1.4)](http://www.rubydoc.info/gems/mail-iso-2022-jp/1.1.4)

```rb:mailtest.rb
require 'mail'
require 'mail-iso-2022-jp'

mail = Mail.new(:charset => 'ISO-2022-JP') do
  from    'fromer@aaa.com'
  to      'toer@bbb.com'
  subject 'メールです'
  body <<-EOS
本文です
ああ
EOS
end

mail.delivery_method :smtp, {
  address:   '127.0.0.1',
  port:      1025,
  domain:    'bbb',
  user_name: 'tester',
  password:  ''
}

mail.deliver!
```

### htmlメールの例

```diff:mailtest.rb
  mail = Mail.new(:charset => 'ISO-2022-JP') do
    from    'fromer@aaa.com'
    to      'toer@bbb.com'
    +   format  'html'
    subject 'メールです'
    body <<-EOS
  本文です
- ああ
+ <font color="blue">ああ</font>
  EOS
  end
```


## クラス

* [Rubyのクラスメソッドとインスタンスメソッドの例 - Qiita](http://qiita.com/tbpgr/items/56eb65c0ea5882abbb07)

```rb:クラスメソッド
class Hoge
  def self.hoge
    puts "hoge"
  end
end
Hoge.hoge # => hoge
```

```rb:クラスメソッド
class Hoge
  class << self
    def hoge
      puts "hoge"
    end
  end
end
Hoge.hoge # => hoge
```

```rb:インスタンスメソッド
class Hoge
  def hoge
    puts "hoge"
  end
end
Hoge.new.hoge # => hoge
```


```rb:initialize
class Foo
  def initialize
    @foo = "first"
  end
  def getFoo
    @foo
  end
end

f1= Foo.new()
p f1.getFoo #first
```

```rb:クラス変数(先頭にアットマーク2つ(@@)。クラス内からのみ参照可能。インスタンス間で共有)
class Foo
  @@foo = "first"
  def bar 
    p @@foo
  end
  def change
    @@foo = "second"
  end
end

f1 = Foo.new()
f1.bar #first

f2 = Foo.new()
f2.bar #first
f2.change
f1.bar #second
f2.bar #second
#f1.foo や f1.@@fooはエラー
```

```rb:インスタンス変数(先頭に@。インスタンス間で共有されない)
class Foo
  def initialize
    @foo = "first"
  end
  def getFoo 
    @foo
  end
  def setFoo(val)
    @foo = val
  end
end

f1 = Foo.new()
p f1.getFoo

f2 = Foo.new()
p f2.getFoo #first
f2.setFoo('second')
p f2.getFoo #second
p f1.getFoo #first
```

## invalid multibyte char (US-ASCII)

```rb:
# encoding: utf-8
```

すればよいです。

## case

```rb:
# encoding: utf-8

def road_signal(color)
  case color
  when "赤"
    p "stop"
  when "黄色"
    p "warning"
  else
    p "go"
  end
end

road_signal("青")
```

## 2つの配列を合体(transpose)

* [Class: Array (Ruby 2.2.0)](http://ruby-doc.org/core-2.2.0/Array.html#method-i-transpose)

```rb:
colors = ["blue", "yellow", "red"]
actions = ["go", "warning", "stop"]
road_signals = [colors,actions].transpose

p road_signals
# [["blue", "go"], ["yellow", "warning"], ["red", "stop"]]
```

```rb:ランダム
r = road_signals
p r[rand(0..(r.length) -1)]
```

```rb:配列のハッシュ化
h = Hash[*road_signals.flatten]
p h
# {"blue"=>"go", "yellow"=>"warning", "red"=>"stop"}
```

## サンプル

```rb:例1
#encoding : utf-8

def current_signal()
    road_signals = [
      ["赤", "止まれ"],
      ["青", "行け"],
      ["黄色", "止まれなければ注意して行け"],
      ["桃色", "帰れ"]
    ]
    max = (road_signals.length) -1
    num = rand(0..max)
    color = road_signals[num][0]
    action = road_signals[num][1]
    message = "%sです。「%s」" % [color, action]
end

p current_signal()
p current_signal()
```

```rb:例2
#encoding : utf-8

def current_signal(r)
    num = rand(0..(r.length) -1)
    message = "%sです。「%s」" % [r[num][0], r[num][1]]
end

colors = ["赤", "青", "黄色", "桃色"]
actions = ["止まれ", "行け", "止まれなければ注意して行け", "帰れ"]
road_signals = [colors,actions].transpose

p current_signal(road_signals)
p current_signal(road_signals)
```

```rb:例3
#encoding : utf-8

class RoadSignal
  def initialize()
    @colors = ["赤", "青", "黄色", "桃色"]
    @actions = ["止まれ", "行け", "止まれなければ注意して行け", "帰れ"]
  end
  def look()
    num = rand(0..(@colors.length) -1)
    message = "%sです。「%s」" % [@colors[num], @actions[num]]
  end
end

signal = RoadSignal.new()
p signal.look
p signal.look
```