Ruby on Rails チュートリアルって長いのでサマリー(4章)〜ヘルパーとRubyの基本〜


Ruby on Rails チュートリアル
http://railstutorial.jp/

# 前提
* Mac OS X Yosemite
* Homebrewは入ってる
* gemは入ってる
* gitとかHerokuとかruby以外でも使うものは知ってる

# ヘルパー

ヘルパーの例。
要は、ApplicationHelperはrailsが自動でincludeしてくれるらしい。

```app/helpers/application_helper.rb
module ApplicationHelper

  # ページごとの完全なタイトルを返します。
  def full_title(page_title)
    base_title = "Ruby on Rails Tutorial Sample App"
    if page_title.empty?
      base_title
    else
      "#{base_title} | #{page_title}"
    end
  end
end
```

Viewでこんな風に使う。

```
<title><%= full_title(yield(:title)) %></title>
```

# Rubyの基本

`$ rails c`で試すといい。

## コメント

```ruby
# ページごとの完全なタイトルを返します。
  def full_title(page_title)
    .
    .
    .
  end
```

## 文字列

```ruby
first_name = "Michael"
last_name = "Hartl"

first_name + " " + last_name    # スペースをはさんで結合する
# => "Michael Hartl"

"#{first_name} #{last_name}"    # 式展開による同等のコード
# => "Michael Hartl"
```

## 出力

```ruby
puts "foo"     # put string
# foo
# => nil

print "foo"    # 文字列の出力 (putsと同じだが改行しない)
# foo=> nil

print "foo\n"  # puts "foo" と同等
# foo
# => nil
```

## シングルクォート内の文字列

シングルクォートで囲まれた文字列では式展開されない

```ruby
'foo'          # シングルクォートで囲んだ文字列
# => "foo"

'foo' + 'bar'
# => "foobar"

'#{foo} bar'     # シングルクォートで囲まれた文字列では式展開されない
# => "\#{foo} bar"

'\n'       # 'バックスラッシュ n' をそのまま扱う
# => "\\n"
```

## オブジェクト

### Rubyでは全てがオブジェクト(nilも)

```ruby
"foobar".length        # 文字列に "length" というメッセージを渡す
# => 6
nil.to_s
# => ""
nil.empty?
# NoMethodError: You have a nil object when you didn't expect it!
# You might have expected an instance of Array.
# The error occurred while evaluating nil.empty?
nil.to_s.empty?      # メッセージの連鎖
# => true
"foo".nil?
# => false
"".nil?
# => false
nil.nil?
# => true
```

### おしりに?がついたメソッドはtrue/falseを返す（慣習）
 
```ruby
s = "foobar"
if s.empty?
  "The string is empty"
else
  "The string is nonempty"
end
# => "The string is nonempty"
```

### && (“and”)、|| (“or”)、! ("not")と後置if

```ruby
x = "foo"
# => "foo"
y = ""
# => ""
puts "Both strings are empty" if x.empty? && y.empty?
# => nil
puts "One of the strings is empty" if x.empty? || y.empty?
# "One of the strings is empty"
# => nil
puts "x is not empty" if !x.empty?
# "x is not empty"
# => nil
```

### unless

```ruby
string = "foobar"
puts "The string '#{string}' is nonempty." unless string.empty?
# The string 'foobar' is nonempty.
# => nil
```

### rubyでfalseになるのはnilだけ

```ruby
if nil
  true
else
  false        # nilはfalse
end
# => false
if 0
  true        # 0 (を含むあらゆるオブジェクト、nilとfalseは除く) はtrue
else
  false
end
# => true
```

## メソッド

Rubyではreturnは省略できる。

```ruby
def string_message(string)
  if string.empty?
    "It's an empty string!"
  else
    "The string is nonempty."
  end
end
# => nil
puts string_message("")
# It's an empty string!
puts string_message("foobar")
# The string is nonempty.
```

returnを明示してこんな風にもかける。

```ruby
def string_message(string)
  return "It's an empty string!" if string.empty?
  return "The string is nonempty."
end
```

## 配列

### splitで配列生成

```ruby
"foo bar     baz".split     # 文字列を3つの要素を持つ配列に分割する
# => ["foo", "bar", "baz"]
"fooxbarxbazx".split('x')
# => ["foo", "bar", "baz"]
```

### 添字は0オリジン

```ruby
a = [42, 8, 17]
# => [42, 8, 17]
a[0]               # 配列へのアクセスには [ ] を使用する
# => 42
a[1]
# => 8
a[2]
# => 17
a[-1]              # 負の値を持つインデックスも使用できる
# => 17
```

### firstとかlastとか

```ruby
a                  # 'a' の内容に注目
# => [42, 8, 17]
a.first
# => 42
a.second
# => 8
a.last
# => 17
a.last == a[-1]    # ==演算子による比較
# => true
```

### 配列のメソッド

a自身は変更されないことに注意

```ruby
a
# => [42, 8, 17]
x = a.length       # 配列も文字列と同様 'length' メソッドに応答する
# => 3
a.sort
# => [8, 17, 42]
a.reverse
# => [17, 8, 42]
a.shuffle
# => [17, 42, 8]
a
# => [42, 8, 17]
```

### 破壊的メソッド（おしりに!がつく）

a自身の値が変更される

```ruby
a
# => [42, 8, 17]
a.sort!
# => [8, 17, 42]
a
# => [8, 17, 42]
```

### pushと<<

```ruby
a = [42, 8, 17]
# => [42, 8, 17]
a.push(6)                  # 配列に6を追加
# => [42, 8, 17, 6]
a << 7                     # 配列に7を追加
# => [42, 8, 17, 6, 7]
a << "foo" << "bar"        # 配列に連続プッシュ
# => [42, 8, 17, 6, 7, "foo", "bar"]
```

### 様々な型の共存とjoin

```ruby
a
# => [42, 8, 17, 7, "foo", "bar"]
a.join                       # 区切り文字なしで連結
# => "428177foobar"
a.join(', ')                 # カンマとスペースで区切って連結
# => "42, 8, 17, 7, foo, bar"
```

### rangeとto_a

```ruby
0..9
# => 0..9
0..9.to_a              # 配列でない数字の9にto_aを実行してしまった
# NoMethodError: undefined method `to_a' for 9:Fixnum
(0..9).to_a            # 範囲にto_aを実行するには丸括弧で囲む
# => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
```

### %wと配列の範囲指定

```ruby
a = %w[foo bar baz quux]         # %wを使用して文字列の配列に変換
# => ["foo", "bar", "baz", "quux"]
a[0..2]
# => ["foo", "bar", "baz"]
```

### 配列添字-1の便利な使い方

```ruby
a = (0..9).to_a
# => [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 
a[2..(a.length-1)]               # 配列の長さを明示的に使用している。
# => [2, 3, 4, 5, 6, 7, 8, 9]
a[2..-1]                         # index -1の使用例。
# => [2, 3, 4, 5, 6, 7, 8, 9]
```

### 文字列にも範囲が使える

```ruby
('a'..'e').to_a
# => ["a", "b", "c", "d", "e"]
```

## ブロック

### {}でブロックをつくる

ブロックの中が短い1行のときはこうする慣習

```ruby
(1..5).each { |i| puts 2 * i }
# 2
# 4
# 6
# 8
# 10
# => 1..5
```

### do endでブロックをつくる

ブロックの中が長い1行、複数行のときはこうする慣習

```ruby
(1..5).each do |number|
  puts 2 * number
  puts '--'
end
# 2
# --
# 4
# --
# 6
# --
# 8
# --
# 10
# --
# => 1..5
```

### timesとmap

```ruby
3.times { puts "Betelgeuse!" }   # 3.timesではブロックに変数を使用していない
# "Betelgeuse!"
# "Betelgeuse!"
# "Betelgeuse!"
# => 3
(1..5).map { |i| i**2 }          # **は累乗を表す
# => [1, 4, 9, 16, 25]
%w[a b c]                        # %wは文字列配列への変換であることを思い出そう
# => ["a", "b", "c"]
%w[a b c].map { |char| char.upcase }
# => ["A", "B", "C"]
%w[A B C].map { |char| char.downcase }
# => ["a", "b", "c"]
```

### メソッドチェーン

```ruby
('a'..'z').to_a.shuffle[0..7].join
# => "mznpybuj"

('a'..'z').to_a                     # アルファベットの配列
# => ["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z"]
('a'..'z').to_a.shuffle             # シャッフルする
# => ["c", "g", "l", "k", "h", "z", "s", "i", "n", "d", "y", "u", "t", "j", "q", "b", "r", "o", "f", "e", "w", "v", "m", "a", "x", "p"]
('a'..'z').to_a.shuffle[0..7]       # 最初の8つの要素を取り出す
# => ["f", "w", "i", "a", "h", "p", "c", "x"]
('a'..'z').to_a.shuffle[0..7].join  # つなげて1つの文字列にする
# => "mznpybuj"
```

## ハッシュとシンボル

### ハッシュ

```ruby
user = {}                          # {}は空のハッシュ
# => {}
user["first_name"] = "Michael"     # キー: "first_name"、値: "Michael"
# => "Michael"
user["last_name"] = "Hartl"        # キー: "last_name"、値: "Hartl"
# => "Hartl"
user["first_name"]                 # 配列と同じ方法で要素にアクセスできる
# => "Michael"
user                               # ハッシュのリテラルな表記
# => {"last_name"=>"Hartl", "first_name"=>"Michael"}
user = { "first_name" => "Michael", "last_name" => "Hartl" }
# => {"last_name"=>"Hartl", "first_name"=>"Michael"}
```

### シンボル（:name など、頭に:つきの文字列）

シンボルって何かは今は気にしない

```ruby
"name".split('')
# => ["n", "a", "m", "e"]
:name.split('')
# NoMethodError: undefined method `split' for :name:Symbol
"foobar".reverse
# => "raboof"
:foobar.reverse
# NoMethodError: undefined method `reverse' for :foobar:Symbol
```

### ハッシュのキーにシンボル（:name など）を使うのが普通

```ruby
user = { :name => "Michael Hartl", :email => "michael@example.com" }
# => {:name=>"Michael Hartl", :email=>"michael@example.com"}
user[:name]              # :name に一致する値にアクセスします。
# => "Michael Hartl"
user[:password]          # 未定義のキーの値にアクセスします。
# => nil
```

### シンボルをキーにしたときの別の書き方

```ruby
h1 = { :name => "Michael Hartl", :email => "michael@example.com" }
# => {:name=>"Michael Hartl", :email=>"michael@example.com"}
h2 = { name: "Michael Hartl", email: "michael@example.com" }
# => {:name=>"Michael Hartl", :email=>"michael@example.com"}
h1 == h2
# => true
```

### ハッシュのネスト

```ruby
params = {}        # 'params' というハッシュを定義する ('parameters' の略)。
# => {}
params[:user] = { name: "Michael Hartl", email: "mhartl@example.com" }
# => {:name=>"Michael Hartl", :email=>"mhartl@example.com"}
params
# => {:user=>{:name=>"Michael Hartl", :email=>"mhartl@example.com"}}
params[:user][:email]
# => "mhartl@example.com"
```

### ハッシュとeach

```ruby
flash = { success: "It worked!", error: "It failed." }
# => {:success=>"It worked!", :error=>"It failed."}
flash.each do |key, value|
   puts "Key #{key.inspect} has value #{value.inspect}"
end
# Key :success has value "It worked!"
# Key :error has value "It failed."
```

### inspect

要求されたオブジェクトを表現する文字列を返す

```ruby
puts (1..5).to_a            # 配列を文字列として出力
# 1
# 2
# 3
# 4
# 5
puts (1..5).to_a.inspect    # 配列のリテラルを出力
# [1, 2, 3, 4, 5]
puts :name, :name.inspect
# name
# :name
puts "It worked!", "It worked!".inspect
# It worked!
# "It worked!"
```

### p関数

inspectとputsのショートカット

```ruby
p :name             # 'puts :name.inspect' と同等
# :name
```

# stylesheet_link_tag関数の解説

3章の`app/views/layouts/application.html.erb`にでてきた次の部分を解読する。

```ruby
<%= stylesheet_link_tag "application", media: "all",
                                       "data-turbolinks-track" => true %>
```

関数呼び出しの丸括弧は省略可能。

```ruby
# 関数呼び出しの丸括弧は省略可能。
stylesheet_link_tag "application", media: "all",
                                   "data-turbolinks-track" => true
stylesheet_link_tag("application", media: "all",
                                   "data-turbolinks-track" => true)
```

最後の引数がハッシュの場合、波括弧は省略可能。

```ruby
# 最後の引数がハッシュの場合、波括弧は省略可能。
stylesheet_link_tag("application", media: "all",
                                   "data-turbolinks-track" => true)
stylesheet_link_tag("application", { media: "all",
                                     "data-turbolinks-track" => true })
```

その他

* シンボルにはハイフンを使えない（そのため、data-turbolinks-trackは旧式のハッシュロケット (=>) スタイルになっている）

* Rubyでは改行の有無に左右されない

できるhtml

```html
<link data-turbolinks-track="true" href="/assets/application.css" media="all"
rel="stylesheet" />
```

# クラス

## リテラルコンストラクタ

```ruby
s = "foobar"       # ダブルクォートを使用した、文字列のリテラルコンストラクタ
# => "foobar"
s.class
# => String
```

## newメソッド

```ruby
s = String.new("foobar")   # 文字列の名前付きコンストラクタ
# => "foobar"
s.class
# => String
s == "foobar"
# => true
a = Array.new([1, 3, 2])
# => [1, 3, 2]
```

## ハッシュのnewメソッド

```ruby
h = Hash.new
# => {}
h[:foo]            # 存在しないキー :fooの値にわざとアクセスしてみる
# => nil
h = Hash.new(0)    # キーが存在しない場合のデフォルト値をnilから0に変更する
# => {}
h[:foo]
# => 0
```

# 継承

Stringクラスを継承したWordクラスを作ってみる

```ruby
class Word < String             # WordクラスはStringクラスを継承する。
  # 文字列が鏡文字であればtrueを返す。
  def palindrome?
    self == self.reverse        # selfは文字列自身を表す。
  end
end
# => nil
```

Wordクラスのメソッドを使う

```ruby
s = Word.new("level")    # 新しいWordを作成し、"level" で初期化する
# => "level"
s.palindrome?            # Wordが鏡文字かどうかmethod.
# => true
s.length                 # Wordがstringのすべてのメソッドも継承している
# => 5
```

superclassをみてみる

```ruby
s.class
# => Word
s.class.superclass
# => String
s.class.superclass.superclass
# => Object
```

# 組み込みクラスの変更

Rubyでは組み込みクラスを変更できてしまう
※でも、よっぽど出ない限り使わない用がいい

```ruby
class String
  # 文字列が回文であればtrueを返す
  def palindrome?
    self == self.reverse
  end
end
# => nil
"deified".palindrome?
# => true
```

# Userクラスの解説

```ruby
class User
  attr_accessor :name, :email

  def initialize(attributes = {})
    @name  = attributes[:name]
    @email = attributes[:email]
  end

  def formatted_email
    "#{@name} <#{@email}>"
  end
end
```

## アクセッサー

@nameと@emailにgetter(XXX.name, XXX.email)とsetter(XXX.name = YYY, XXX.email = YYYY)をつくる。

```ruby
attr_accessor :name, :email
```

## インスタンス変数

@が頭に付いているのはインスタンス変数。

## コンストラクタ

initializeはnewしたときに呼ばれるメソッド。
引数attributesはデフォルト値を{}（空ハッシュ）にしている。

## 使い方

```ruby
user = User.new(name: "Michael Hartl", email: "mhartl@example.com")
3 => #<User:0x225167c @email="mhartl@example.com", @name="Michael Hartl">
user.formatted_email
# => "Michael Hartl <mhartl@example.com>"
```