【Railsチュートリアル】第4章 演習問題解答 2/2

【Railsチュートリアル】第4章 演習問題解答 2/2

【Railsチュートリアル】第4章 演習問題解答 1/2
の続きです。
ここからクラスを扱いだします。

目次

4.4.1 コンストラクタ

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

解答

リテラルコンストラクタってのはnewとかしないでクラス作ってくれちゃうやつ
そんな認識でいいんじゃないかな。ざっくりわかることも大事です。

つまりはRange.new(〜〜)ってしないでどうやってRangeオブジェクト作ってましたか?
って問題

こうやってやってましたね。

irb(main):166:0> a = 1..10
=> 1..10
irb(main):167:0> a.class
=> Range

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

解答

Rangeは引数は始まり終わりの2つ引数が必要です。
以下のようになります。

irb(main):169:0> b = Range.new(1,10)
=> 1..10

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

解答

変数名適当すぎたのを今になって後悔w
1.ではa,2.ではbとしていたので、以下のようになります。

irb(main):170:0> a == b
=> true

4.4.2 クラス継承

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

解答

先ほどのbを使って調べてみます。

irb(main):174:0> b.class
=> Range
irb(main):175:0> b.class.superclass
=> Object
irb(main):176:0> b.class.superclass.superclass
=> BasicObject
irb(main):177:0> b.class.superclass.superclass.superclass
=> nil

Range=>Object=>BasicObject
となることがわかりました。

ハッシュも同様に

irb(main):180:0> h = {}
=> {}
irb(main):181:0> h.class
=> Hash
irb(main):182:0> h.class.superclass
=> Object
irb(main):183:0> h.class.superclass.superclass
=> BasicObject
irb(main):184:0> h.class.superclass.superclass.superclass
=> nil

Hash=>Object=>BasicObject
となります。

シンボルも同様に

irb(main):185:0> s = :symbol
=> :symbol
irb(main):186:0> s.class
=> Symbol
irb(main):187:0> s.class.superclass
=> Object
irb(main):188:0> s.class.superclass.superclass
=> BasicObject
irb(main):189:0> s.class.superclass.superclass.superclass
=> nil

となるので
Symbol=>Object=>BasicObject
となることがわかります。

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

解答

self.reverseをreverseとして定義しました。

irb(main):190:0> class Word < String
irb(main):191:1> def palindrome?
irb(main):192:2> self == reverse
irb(main):193:2> end
irb(main):194:1> end
=> :palindrome?

Stringクラスを継承したWordクラスのインスタンスは
palindrome?というメソッドを使うことで回文かどうか調べられるようになったわけなので、
それを確かめたいと思います。

irb(main):201:0> ss = Word.new("abc")
=> "abc"
irb(main):202:0> ss.palindrome?
=> false
irb(main):203:0> ss = Word.new("abcba")
=> "abcba"
irb(main):204:0> ss.palindrome?
=> true

最初はabcは回文でないのでfalse、abcbaは回文となるのでtrueを返します。
OKですね。

4.4.3 組み込みクラスの変更

Rubyは基本クラスまでいじれるんですよ。というのがミソ。

irb(main):205:0> class String
irb(main):206:1> def palindrome?
irb(main):207:2> self == self.reverse
irb(main):208:2> end
irb(main):209:1> end
=> :palindrome?

Stringクラスにpalindromeメソッドを追加しました。

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

解答

ほぼ復習ですね。

irb(main):210:0> "racecar".palindrome?
=> true
irb(main):211:0> "onomatopoeia".palindrome?
=> false
irb(main):212:0> "Malayalam".downcase.palindrome?
=> true

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

解答

これも復習ですね。

irb(main):213:0> class String
irb(main):214:1> def shuffle
irb(main):215:2> self.split('').shuffle.join
irb(main):216:2> end
irb(main):217:1> end
=> :shuffle
irb(main):218:0> "foobar".shuffle
=> "fraoob"

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

解答

selfは省略できるというお話です。

irb(main):219:0> class String
irb(main):220:1> def shuffle
irb(main):221:2> split('').shuffle.join
irb(main):222:2> end
irb(main):223:1> end
=> :shuffle
irb(main):224:0> "foobar".shuffle
=> "fobroa"

4.4.4 コントローラクラス

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

解答

実際に確かめてみればOKです。

$ cd ../toy_app/
$ rails c
Running via Spring preloader in process 25622
Loading development environment (Rails 5.1.4)
irb(main):001:0> User.new
=> #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil>

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

解答

手順は変わりません。

=> #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil>
irb(main):002:0> user = User.new
=> #<User id: nil, name: nil, email: nil, created_at: nil, updated_at: nil>
irb(main):003:0> user.class
=> User(id: integer, name: string, email: string, created_at: datetime, updated_at: datetime)
irb(main):004:0> user.class.superclass
=> ApplicationRecord(abstract)
irb(main):005:0> user.class.superclass.superclass
=> ActiveRecord::Base
irb(main):006:0> user.class.superclass.superclass.superclass
=> Object
irb(main):007:0> user.class.superclass.superclass.superclass.superclass
=> BasicObject
irb(main):008:0> user.class.superclass.superclass.superclass.superclass.superclass
=> nil

User=>ApplicationRecord=>ActiveRecord::Base=>Object=>BasicObject
となります。

4.4.5 ユーザークラス

(オワビ)exsample_user.rbを作らずコンソールでやってしまいました…
結果は変わらないので、優しい目で見てください…

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

解答

ちょっと長いのでコメントいれてみました。

  • nameがfirst_nameとlast_nameに分かれること
  • formatted_emailで自クラスの関数を実行するためにselfを使用する

以上がポイントかと思います。

irb(main):444:0> class User
irb(main):445:1>   #nameを分割
irb(main):446:1*   attr_accessor :first_name,:last_name, :email
irb(main):447:1>
irb(main):448:1*   #nameを分割
irb(main):449:1*   def initialize(attributes = {})
irb(main):450:2>     @first_name = attributes[:first_name]
irb(main):451:2>     @last_name = attributes[:first_name]
irb(main):452:2>     @email = attributes[:email]
irb(main):453:2>   end
irb(main):454:1>
irb(main):455:1*   #full_nameメソッドを追加
irb(main):456:1*   def full_name
irb(main):457:2>      "#{@first_name} #{@last_name}"
irb(main):458:2>   end
irb(main):459:1>
irb(main):460:1*  #nameをfull_nameにした
irb(main):461:1*   def formatted_email
irb(main):462:2>     "#{self.full_name} <#{@email}>"
irb(main):463:2>   end
irb(main):464:1> end
=> :formatted_email
irb(main):465:0> user = User.new
=> #<User:0x007fc1897b2a80 @first_name=nil, @last_name=nil, @email=nil>
irb(main):466:0> user.first_name = "Michael"
=> "Michael"
irb(main):467:0> user.last_name = "Hartl"
=> "Hartl"
irb(main):468:0> user.email = "mhartl@example.com"
=> "mhartl@example.com"
irb(main):469:0> user.formatted_email
=> "Michael Hartl <mhartl@example.com>"

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

解答

クラスは拡張ができるので、1から宣言せずとも追加するものだけ書けばいいです。

irb(main):480:0> class User
irb(main):481:1>   def alphabetical_name
irb(main):482:2>     "#{@last_name}, #{@first_name}"
irb(main):483:2>   end
irb(main):484:1> end
=> :alphabetical_name
irb(main):485:0>
irb(main):486:0* user.alphabetical_name
=> "Hartl, Michael"

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

解答

両者実行して確かめれば良いです。
userを頭につけてくださいね。

irb(main):498:0> user.full_name.split
=> ["Michael", "Hartl"]
irb(main):499:0> user.alphabetical_name.split(', ').reverse
=> ["Michael", "Hartl"]

あーやっちまった。
まあいいでしょうということにしておきましょう(そうさせてください)

(おまけ)
一応ちゃんとやりなおしました。
よかったら見てやってください。

プログラム

class User
  attr_accessor :first_name,:last_name, :email

  def initialize(attributes = {})
    @first_name  = attributes[:firt_name]
    @last_name  = attributes[:last_name]
    @email = attributes[:email]
  end

  def full_name
    "#{@first_name} #{@last_name}"
  end

  def formatted_email
    "#{self.full_name} <#{@email}>"
  end

  def alphabetical_name
    "#{@last_name}, #{@first_name}"
  end
end

コンソール実行結果

irb(main):001:0> require './example_user'
=> true
irb(main):002:0> user = User.new
=> #<User:0x007fc189adae88 @first_name=nil, @last_name=nil, @email=nil>
irb(main):003:0> user.first_name = "Michael"
=> "Michael"
irb(main):004:0> user.last_name = "Hartl"
=> "Hartl"
irb(main):005:0> user.email = "mhartl@example.com"
=> "mhartl@example.com"
irb(main):006:0> user.formatted_email
=> "Michael Hartl <mhartl@example.com>"
irb(main):007:0> user.alphabetical_name
=> "Hartl, Michael"
irb(main):008:0> user.full_name.split
=> ["Michael", "Hartl"]
irb(main):009:0> user.alphabetical_name.split(', ').reverse
=> ["Michael", "Hartl"]

4章長かったぁ。。
でもこの章は2周目で理解が深まるゾーンですね。

以上、コジマでした。


Railsチュートリアルカテゴリの最新記事