【Railsチュートリアル】第4章 Rails風味のRuby 演習と解答

## 4.2.1 文字列
### 4.2.1 - 1
city変数に適当な市区町村を、prefecture変数に適当な都道府県を代入してください。

```
> city = "たこ焼きが"
 => "大阪府" 
> prefecture = "おいしい県"
 => "大阪市" 
```

### 4.2.1 - 2
先ほど作った変数と式展開を使って、「東京都 新宿区」のような住所の文字列を作ってみましょう。出力にはputsを使ってください。

```
> puts "#{city} #{prefecture}"
たこ焼きが おいしい県
 => nil
```

### 4.2.1 - 3
上記の文字列の間にある半角スペースをタブに置き換えてみてください。（ヒント: 改行文字と同じで、タブも特殊文字です）

```
> puts city + " " + prefecture
たこ焼きが おいしい県
 => nil 
```

### 4.2.1 - 4
タブに置き換えた文字列を、ダブルクォートからシングルクォートに置き換えてみるとどうなるでしょうか?

```
> puts city + ' ' + prefecture                                              
たこ焼きが おいしい県
 => nil 
```

##4.2.2 オブジェクトとメッセージ受け渡し
###4.2.2 - 1
"racecar" の文字列の長さはいくつですか? lengthメソッドを使って調べてみてください。

```
> "racecar".length
 => 7 
```

###4.2.2 - 2
reverseメソッドを使って、"racecar"の文字列を逆から読むとどうなるか調べてみてください。

```
> "racecar".reverse
 => "racecar" 
```

###4.2.2 - 3
変数sに "racecar" を代入してください。その後、比較演算子（==）を使って変数sとs.reverseの値が同じであるかどうか、調べてみてください。

```
> s = "racecar"
 => "racecar" 
> s == s.reverse
 => true 
```

###4.2.2 - 3
リスト 4.9を実行すると、どんな結果になるでしょうか? 変数sに "onomatopoeia" という文字列を代入するとどうなるでしょうか?（ヒント: 上矢印（またはCtrl-Pコマンド）を使って以前に使ったコマンドを再利用すると一からコマンドを全部打ち込む必要がなくて便利ですよ。）

```
> puts "It's a palindrome!" if s == s.reverse
It's a palindrome!
 => nil

> s = "onomatopoeia"
 => "onomatopoeia" 
> puts "It's a palindrome!" if s == s.reverse
 => nil  
```
palindrome = 回文
onomatopoeia = 擬音、擬声、擬音語

## 4.2.3 メソッドの定義
### 4.2.3 - 1
リスト 4.10のFILL_INの部分を適切なコードに置き換え、回文かどうかをチェックするメソッドを定義してみてください。ヒント: リスト 4.9の比較方法を参考にしてください。

```
> def palindrome_tester(s)
>   if s == s.reverse
>     puts "It's a palindrome!"
>     else
>     puts "It's not a palindrome."
>     end
>   end
 => :palindrome_tester 
```

### 4.2.3 - 2
上で定義したメソッドを使って “racecar” と “onomatopoeia” が回文かどうかを確かめてみてください。１つ目は回文である、２つ目は回文でない、という結果になれば成功です。

```
> puts palindrome_tester("racecar")
It's a palindrome!
 => nil

> puts palindrome_tester("onomatopoeia")
It's not a palindrome.
 => nil 
``` 

### 4.2.3 - 3
palindrome_tester("racecar")に対してnil?メソッドを呼び出し、戻り値がnilであるかどうかを確認してみてください（つまりnil?を呼び出した結果がtrueであることを確認してください）。このメソッドチェーンは、nil?メソッドがリスト 4.10の戻り値を受け取り、その結果を返しているという意味になります。

```
> palindrome_tester("racecar").nil?
It's a palindrome!
 => true
```

## 4.3.1 配列と範囲演算子
### 4.3.1 - 1
文字列「A man, a plan, a canal, Panama」を ", " で分割して配列にし、変数aに代入してみてください。

```
> a = "A man, a plan, a canal, Panama".split(',')
 => ["A man", " a plan", " a canal", " Panama"]  
```

### 4.3.1 - 2
今度は、変数aの要素を連結した結果（文字列）を、変数sに代入してみてください。

```
> s = a.join
 => "A man a plan a canal Panama" 
```

### 4.3.1 - 3
変数sを半角スペースで分割した後、もう一度連結して文字列にしてください（ヒント: メソッドチェーンを使うと１行でもできます）。リスト 4.10で使った回文をチェックするメソッドを使って、（現状ではまだ）変数sが回文ではないことを確認してください。downcaseメソッドを使って、s.downcaseは回文であることを確認してください。

```
> s = s.split.join
 => "AmanaplanacanalPanama"

> def palindrome_tester(s)
>   if s == s.reverse
>     puts "It's a palindrome!"
>     else
>     puts "It's not a palindrome."
>     end
>   end
 => :palindrome_tester 
> palindrome_tester(s)
It's not a palindrome.
 => nil 

> palindrome_tester(s.downcase)
It's a palindrome!
 => nil 
```

### 4.3.1 - 4
aからzまでの範囲オブジェクトを作成し、7番目の要素を取り出してみてください。同様にして、後ろから７番目の要素を取り出してみてください。（ヒント: 範囲オブジェクトを配列に変換するのを忘れないでください）

```
> a = ('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[-7]
 => "t" 
```

## 4.3.2 ブロック
### 4.3.2 - 1
範囲オブジェクト0..16を使って、各要素の２乗を出力してください。

```
> (0..16).each{|i| puts i*i }
0
1
4
9
16
25
36
49
64
81
100
121
144
169
196
225
256
 => 0..16

# 下記でも同じ
> (0..16).each do |i|
>     puts i * i
>   end

```

### 4.3.2 - 2
yeller（大声で叫ぶ）というメソッドを定義してください。このメソッドは、文字列の要素で構成された配列を受け取り、各要素を連結した後、大文字にして結果を返します。例えばyeller(['o', 'l', 'd'])と実行したとき、"OLD"という結果が返ってくれば成功です。ヒント: mapとupcaseとjoinメソッドを使ってみましょう。

```
> def yeller(s)
>   s.map(&:upcase).join
>   end
 => :yeller 
> yeller(['o', 'l', 'd'])
 => "OLD" 
```

### 4.3.2 - 3
random_subdomainというメソッドを定義してください。このメソッドはランダムな8文字を生成し、文字列として返します。ヒント: サブドメインを作るときに使ったRubyコードをメソッド化したものです。

```
> def random_subdomain
>   ('a'..'z').to_a.shuffle[0..7].join
>   end
 => :random_subdomain 
> random_subdomain 
 => "mqntsphl" 
```

### 4.3.2 - 4
リスト 4.12の「?」の部分を、それぞれ適切なメソッドに置き換えてみてください。ヒント:split、shuffle、joinメソッドを組み合わせると、メソッドに渡された文字列（引数）をシャッフルさせることができます。

```
> def string_shuffle(s)
>   s.split('').shuffle.join
>   end
 => :string_shuffle 
> string_shuffle("foobar")
 => "boroaf" 
```

## 4.3.3 ハッシュとシンボル

### 4.3.3 - 1

キーが'one'、'two'、'three'となっていて、それぞれの値が'uno'、'dos'、'tres'となっているハッシュを作ってみてください。その後、ハッシュの各要素をみて、それぞれのキーと値を"'#{key}'のスペイン語は'#{value}'"といった形で出力してみてください。

```
> num = { one: "uno", two: "dos", three: "tres" }
 => {:one=>"uno", :two=>"dos", :three=>"tres"} 
> num.each do |key, value|
>     puts "'#{key}'のスペイン語は'#{value}'"
>   end
'one'のスペイン語は'uno'
'two'のスペイン語は'dos'
'three'のスペイン語は'tres'
 => {:one=>"uno", :two=>"dos", :three=>"tres"}
```

### 4.3.3 - 2

person1、person2、person3という３つのハッシュを作成し、それぞれのハッシュに:firstと:lastキーを追加し、適当な値（名前など）を入力してください。その後、次のようなparamsというハッシュのハッシュを作ってみてください。1）キーparams[:father]の値にperson1を代入、2）キーparams[:mother]の値にperson2を代入、3）キーparams[:child]の値にperson3を代入。最後に、ハッシュのハッシュを調べていき、正しい値になっているか確かめてみてください。（例えばparams[:father][:first]がperson1[:first]と一致しているか確かめてみてください）

```
> person1 = { :first => "mou", :last => "toon" }
 => {:first=>"mou", :last=>"toon"} 
> person2 = { :first => "coco", :last => "toon" }                           
 => {:first=>"coco", :last=>"toon"} 
> person3 = { :first => "em", :last => "toon" }                             
 => {:first=>"em", :last=>"toon"} 
> params[:father] = person1
 => {:first=>"mou", :last=>"toon"} 
> params[:mother] = person2
 => {:first=>"coco", :last=>"toon"} 
> params[:child] = person3
 => {:first=>"em", :last=>"toon"} 
> params[:father][:first] == person1[:first]
 => true
```

### 4.3.3 - 3

```
> user = { name: "moutoon", email: "moutoon@example.com", password_digest: ('a'..'z').to_a.shuffle[0..15].join }
 => {:name=>"moutoon", :email=>"moutoon@example.com", :password_digest=>"frkwnzxbdlpmojhi"}
```

### 4.3.3 - 4

Ruby API（訳注: もしくはるりまサーチ）を使って、Hashクラスのmergeメソッドについて調べてみてください。次のコードを実行せずに、どのような結果が返ってくるか推測できますか? 推測できたら、実際にコードを実行して推測があっていたか確認してみましょう。

```
> { "a" => 100, "b" => 200 }.merge({ "b" => 300 })
 => {"a"=>100, "b"=>300}
```

## 4.4.1 コンストラクタ

### 4.4.1 - 1

1から10の範囲オブジェクトを生成するリテラルコンストラクタは何でしたか?（復習です）

```
> a = 1..10
 => 1..10
```

リテラルコンストラクタ 

Rubyでは、文字列(String)・配列(Array)・ハッシュ(Hash)・範囲(Range)などのクラスに対し、当該オブジェクトのインスタンスを暗黙的に作成する記法が存在します。 Railsチュートリアルでは、こうした記法を「リテラルコンストラクタ」と呼んでいます。

### 4.4.1 - 2

今度はRangeクラスとnewメソッドを使って、1から10の範囲オブジェクトを作ってみてください。ヒント: newメソッドに2つの引数を渡す必要があります

```
> b = Range.new(1,10)
 => 1..10
```

### 4.4.1 - 3

比較演算子==を使って、上記２つの課題で作ったそれぞれのオブジェクトが同じであることを確認してみてください。

```
> a == b
 => true
```

## 4.4.2 クラス継承

### 4.4.2 - 1

Rangeクラスの継承階層を調べてみてください。同様にして、HashとSymbolクラスの継承階層も調べてみてください。

```
> Range.class.superclass
 => Module 
> Range.class.superclass.superclass
 => Object 
> Range.class.superclass.superclass.superclass
 => BasicObject 
> Range.class.superclass.superclass.superclass.superclass
 => nil

# Hash, Symbolクラスも同様
```

### 4.4.2 - 1

リスト 4.15にあるself.reverseのselfを省略し、reverseと書いてもうまく動くことを確認してみてください。

```
> class Word < String
>   def palindrome?
>     self == reverse
>     end
>   end
 => :palindrome? 
> s = Word.new("level")
 => "level"
> s.palindrome?
 => true
```

## 4.4.3 組み込みクラスの変更

### 4.4.3 - 1

palindrome?メソッドを使って、“racecar”が回文であり、“onomatopoeia”が回文でないことを確認してみてください。南インドの言葉「Malayalam」は回文でしょうか? ヒント: downcaseメソッドで小文字にすることを忘れないで。

```
> class Strong
>   def palindrome?
>     self == self.reverse
>     end
>   end
 => :palindrome? 
> "racecar".palindrome?
 => true 
> "onomatopoeia".palindrome?
 => false 
> "Malayalam".downcase.palindrome?
 => true
```

### 4.4.3 - 2

リスト 4.16を参考に、Stringクラスにshuffleメソッドを追加してみてください。ヒント: リスト 4.12も参考になります。

```
> class String
>   def shuffle
>     self.split('').shuffle.join
>     end
>   end
 => :shuffle 
> "moutoon".shuffle
 => "uonomto"
```

### 4.4.3 - 3

リスト 4.16のコードにおいて、self.を削除してもうまく動くことを確認してください。

```
> class String
>   def shuffle
>     split('').shuffle.join
>     end
>   end
 => :shuffle 
> "moutoon".shuffle
 => "omnotou"
```

## 4.4.4 コントローラクラス

### 4.4.4 - 1

第2章で作ったToyアプリケーションのディレクトリでRailsコンソールを開き、User.newと実行することでuserオブジェクトが生成できることを確認してみましょう。

```
> user = User.new
 => #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil>
```

### 4.4.4 - 2

生成したuserオブジェクトのクラスの継承階層を調べてみてください。

```
> user.class
 => User(id: integer, name: string, email: string, created_at: datetime, updated_at: datetime)
> user.class.superclass
 => ApplicationRecord(abstract)
> user.class.superclass.superclass
 => ActiveRecord::Base
> user.class.superclass.superclass.superclass
 => Object
> user.class.superclass.superclass.superclass.superclass
 => BasicObject
> user.class.superclass.superclass.superclass.superclass.superclass
 => nil
```

## 4.4.5 ユーザークラス

### 4.4.5 - 1

Userクラスで定義されているname属性を修正して、first_name属性とlast_name属性に分割してみましょう。また、それらの属性を使って "Michael Hartl" といった文字列を返すfull_nameメソッドを定義してみてください。最後に、formatted_emailメソッドのnameの部分を、full_nameに置き換えてみましょう（元々の結果と同じになっていれば成功です）

```ruby
class User
  attr_accessor :first_name, :last_name, :email
  
  def initialize(attributes = {})
    @first_name = attributes[:first_name]
    @last_name = attributes[:last_name]
    @email = attributes[:email]
  end
  
  def full_name
    "#{@first_name} #{@last_name}"
  end
  
  def alphabetical_name
    "#{@last_name}, #{@first_name}"
  end
  
  def formatted_email
    "#{full_name} <#{@email}>"
  end
  
end
```

```
> require './example_user'
 => true
> user = User.new(first_name: "mou", last_name: "toon", email: "moutoon@example.com")
 => #<User:0x00007f3bd406ec50 @first_name="mou", @last_name="toon", @email="moutoon@example.com"> 
2.6.3 :004 > user.full_name
 => "mou toon"
> user.formatted_email
 => " <moutoon@example.com>"
```

### 4.4.5 - 2

"Hartl, Michael" といったフォーマット（苗字と名前がカンマ+半角スペースで区切られている文字列）で返すalphabetical_nameメソッドを定義してみましょう。

```
> user.alphabetical_name
 => "toon, mou"
```

### 4.4.5 - 3

full_name.splitとalphabetical_name.split(', ').reverseの結果を比較し、同じ結果になるかどうか確認してみましょう。

```
> user.full_name.split == user.alphabetical_name.split(', ').reverse
 => true
```



## memo
### unless文
条件式が偽の場合の処理を記述するのに使われる。

```
> string = "moutoon"
 => "moutoon" 
2.6.3 :043 > puts "The string '#{string}' is nonempty." unless string.empty?
The string 'moutoon' is nonempty.
 => nil 
```

`string(文字列)`が`empty?(空白)`でなければ`"The string '#{string}' is nonempty."`を出力せよ。

### 配列と範囲オブジェクト

```
> ('あ'..'お').to_a
 => ["あ", "ぃ", "い", "ぅ", "う", "ぇ", "え", "ぉ", "お"] 
```
ひらがなもできるのかな？と試してみたらできました。
捨て仮名も一緒に表示されるようですね。

## さいごに
Rubyの基礎のキ部分はProgateとドットインストールで学習してきましたが、ここにきて学習の点と点がつながった繋がった感じがして、とても楽しかったです。すべて理解できたとは言えませんが、少しずつ進んでいきたいと思います！