LoginSignup
0
0

More than 3 years have passed since last update.

Ruby on Rails Tutorial 学習メモ 4章

Last updated at Posted at 2019-05-11

4章

演習
city変数に適当な市区町村を、prefecture変数に適当な都道府県を代入してください。
先ほど作った変数と式展開を使って、「東京都 新宿区」のような住所の文字列を作ってみましょう。出力にはputsを使ってください。
上記の文字列の間にある半角スペースをタブに置き換えてみてください。(ヒント: 改行文字と同じで、タブも特殊文字です)
タブに置き換えた文字列を、ダブルクォートからシングルクォートに置き換えてみるとどうなるでしょうか?

Onenoteからコピペすると画像扱いになることが分かった。
一度テキストエディタにコピペしてからコピーしなおすと


>> cty = "東京"
=> "東京"
>> prefecture = "新宿区"
=> "新宿区"
>> puts "#{city}#{prefecture}"                                                
Traceback (most recent call last):
        1: from (irb):3
NameError (undefined local variable or method `city' for main:Object)
Did you mean?  cty
>> puts "#{city}+#{prefecture}"
Traceback (most recent call last):
        2: from (irb):4
        1: from (irb):4:in `rescue in irb_binding'
NameError (undefined local variable or method `city' for main:Object)

変数cityと定義するところをctyとしてしまったがそのまま続行。

>> puts "#{cty}+#{prefecture}"                                                
東京+新宿区
=> nil
>> puts "#{cty} #{prefecture}"                                                
東京 新宿区
=> nil
>> puts #{cty}\t#{prefecture}

=> nil
>> puts #{cty} \t #{prefecture}

=> nil
>> puts #{cty} \t #{prefecture}                                               

=> nil
>> puts #{cty} \n #{prefecture}

=> nil
>> puts "#{cty} \n #{prefecture}"                                             
東京 
 新宿区
=> nil
>> puts "#{cty}\t#{prefecture}"                                               
東京    新宿区
=> nil
>> puts `#{cty}\t#{prefecture}`                                               
rails_console: No such file or directory - 東京

=> nil
>> puts `#{cty} \t #{prefecture}`                                             
rails_console: No such file or directory - 東京

=> nil
>> puts `#{cty} "\t" #{prefecture}`                                           
sh: $'\346\235\261\344\272\254': command not found

=> nil
>> puts `#{cty}#{prefecture}`                                                 
rails_console: No such file or directory - 東京新宿区

演習4.2.3

"racecar" の文字列の長さはいくつですか? lengthメソッドを使って調べてみてください。
reverseメソッドを使って、"racecar"の文字列を逆から読むとどうなるか調べてみてください。
変数sに "racecar" を代入してください。その後、比較演算子 (==) を使って変数sとs.reverseの値が同じであるかどうか、調べてみてください。
リスト 4.9を実行すると、どんな結果になるでしょうか? 変数sに "onomatopoeia" という文字列を代入するとどうなるでしょうか? ヒント: 上矢印 (またはCtrl-Pコマンド) を使って以前に使ったコマンドを再利用すると一からコマンドを全部打ち込む必要がなくて便利ですよ。)

>> "racecar".length
=> 7
>> "racecar".reverse
=> "racecar"
>> s = "racecar"
=> "racecar"
>> s == s.reverse
=> true
>> 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

image.png

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

演習
1. リスト 4.10のFILL_INの部分を適切なコードに置き換え、回文かどうかをチェックするメソッドを定義してみてください。ヒント: リスト 4.9の比較方法を参考にしてください。
2. 上で定義したメソッドを使って “racecar” と “onomatopoeia” が回文かどうかを確かめてみてください。1つ目は回文である、2つ目は回文でない、という結果になれば成功です。
3. palindrome_tester("racecar")に対してnil?メソッドを呼び出し、戻り値がnilであるかどうかを確認してみてください (つまりnil?を呼び出した結果がtrueであることを確認してください)。このメソッドチェーンは、nil?メソッドがリスト 4.10の戻り値を受け取り、その結果を返しているという意味になります。

リスト 4.10: 回文に対する簡単なテスト
>> def palindrome_tester(s)
>>   if FILL_IN
>>     puts "It's a palindrome!"
>>   else
>>     puts "It's not a palindrome."
>>   end
>> end

2

>> 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("racecar")
It's a palindrome!
=> nil
>> palindrome_tester("onomatopoeia")
It's not a palindrome.
=> nil

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

4.3.1演習

  1. 文字列「A man, a plan, a canal, Panama」を ", " で分割して配列にし、変数aに代入してみてください。
  2. 今度は、変数aの要素を連結した結果 (文字列) を、変数sに代入してみてください。
  3. 変数sを半角スペースで分割した後、もう一度連結して文字列にしてください (ヒント: メソッドチェーンを使うと1行でもできます)。リスト 4.10で使った回文をチェックするメソッドを使って、(現状ではまだ) 変数sが回文ではないことを確認してください。downcaseメソッドを使って、s.downcaseは回文であることを確認してください。 aからzまでの範囲オブジェクトを作成し、7番目の要素を取り出してみてください。同様にして、後ろから7番目の要素を取り出してみてください。(ヒント: 範囲オブジェクトを配列に変換するのを忘れないでください)
>> "A man, a plan, a canal, Panama".split(",")
=> ["A man", " a plan", " a canal", " Panama"]
>> a = "A man, a plan, a canal, Panama".split(",")                            
=> ["A man", " a plan", " a canal", " Panama"]
>> s = a.join
=> "A man a plan a canal Panama"
>> puts s
A man a plan a canal Panama
=> nil
>> 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.split.join.downcase)
It's a palindrome!
=> nil
>> 

>> 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]
=> "h"
>> a[-7]
=> "t"

4.3.2
演習
1. 範囲オブジェクト0..16を使って、各要素の2乗を出力してください。
2. yeller (大声で叫ぶ) というメソッドを定義してください。このメソッドは、文字列の要素で構成された配列を受け取り、各要素を連結した後、大文字にして結果を返します。例えばyeller([’o’, ’l’, ’d’])と実行したとき、"OLD"という結果が返ってくれば成功です。ヒント: mapとupcaseとjoinメソッドを使ってみましょう。
3. random_subdomainというメソッドを定義してください。このメソッドはランダムな8文字を生成し、文字列として返します。ヒント: サブドメインを作るときに使ったRubyコードをメソッド化したものです。
リスト 4.12の「?」の部分を、それぞれ適切なメソッドに置き換えてみてください。ヒント:split、shuffle、joinメソッドを組み合わせると、メソッドに渡された文字列 (引数) をシャッフルさせることができます。

1.

>> (0..16).map { |i| i**2 }                                                   
=> [0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256]
ほかの人の回答を見ると
>>(0..16).each do |i|
>> puts i*i
>>end

2.

>> def yeller(s)
>> s.join.upcase
>> end
=> :yeller
>> yeller([’o’, ’l’, ’d’])
Traceback (most recent call last):
        1: from (irb):40
NameError (undefined local variable or method `’o’' for main:Object)
手打ちでカンマ’’にすると
>> yeller(['o', 'l', 'd'])                                                    
=> "OLD"

4.3.3演習
キーが’one’、’two’、’three’となっていて、それぞれの値が’uno’、’dos’、’tres’となっているハッシュを作ってみてください。その後、ハッシュの各要素をみて、それぞれのキーと値を"’#{key}’のスペイン語は’#{value}’"といった形で出力してみてください。
person1、person2、person3という3つのハッシュを作成し、それぞれのハッシュに:firstと:lastキーを追加し、適当な値 (名前など) を入力してください。その後、次のようなparamsというハッシュのハッシュを作ってみてください。1.) キーparams[:father]の値にperson1を代入、2). キーparams[:mother]の値にperson2を代入、3). キーparams[:child]の値にperson3を代入。最後に、ハッシュのハッシュを調べていき、正しい値になっているか確かめてみてください。(例えばparams[:father][:first]がperson1[:first]と一致しているか確かめてみてください)
userというハッシュを定義してみてください。このハッシュは3つのキー:name、:email、:password_digestを持っていて、それぞれの値にあなたの名前、あなたのメールアドレス、そして16文字からなるランダムな文字列が代入されています。
Ruby API (訳注: もしくはるりまサーチ) を使って、Hashクラスのmergeメソッドについて調べてみてください。次のコードを実行せずに、どのような結果が返ってくるか推測できますか? 推測できたら、実際にコードを実行して推測があっていたか確認してみましょう。

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

1.2.3.

>> flash = {one: "uno", two:"dos",three:"tres"}
=> {:one=>"uno", :two=>"dos", :three=>"tres"}
>> flash.each do |key,value|
?> puts "`#{key}`のスペイン語
は`#{value}`"
>> end
`one`のスペイン語
は`uno`
`two`のスペイン語
は`dos`
`three`のスペイン語
は`tres`
=> {:one=>"uno", :two=>"dos", :three=>"tres"}
>> 
>> person1={ first:"sato",last:"ichiro" }
=> {:first=>"sato", :last=>"ichiro"}
>> person2={ first:"suzuki",last:"haha" }                                     
=> {:first=>"suzuki", :last=>"haha"}
>> person3={ first:"saito",last:"ichiko"}
=> {:first=>"saito", :last=>"ichiko"}
>> params ={}
=> {}
>> params[:father] =person1                                                   
=> {:first=>"sato", :last=>"ichiro"}
>> params[:mother] = person2
=> {:first=>"suzuki", :last=>"haha"}
>> params[:child] = person3
=> {:first=>"saito", :last=>"ichiko"}
>> params
=> {:father=>{:first=>"sato", :last=>"ichiro"}, :mother=>{:first=>"suzuki", :last=>"haha"}, :child=>{:first=>"saito", :last=>"ichiko"}}
>> params[:father][:first] == person1[:first]
=> true
>> params[:mother][:first] == person2[:first]                                
=> true
>> params[:child][:first] == person3[:first]                                  
=> true
>> usre = {name:"Yamada",email:"Yamada@example.com",password_digest:('a'..'z').to_a.shuffle[0..15].join}
=> {:name=>"Yamada", :email=>"Yamada@example.com", :password_digest=>"pzubtmqixgaofrcs"}

4.

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

演習

1から10の範囲オブジェクトを生成するリテラルコンストラクタは何でしたか? (復習です)
今度はRangeクラスとnewメソッドを使って、1から10の範囲オブジェクトを作ってみてください。ヒント: newメソッドに2つの引数を渡す必要があります
比較演算子==を使って、上記2つの課題で作ったそれぞれのオブジェクトが同じであることを確認してみてください

>> a = 1..10
=> 1..10
>> b =Range.new(1,10)
=> 1..10
>> a==b
=> true

>> w.palindrome?("doobar")
=> false
>> w.palindrome?("level")                                                     
=> true


>> Range.class
=> Class
>> Range.superclass
=> Object
>> Range.superclass.superclass
=> BasicObject
>> Hash.class
=> Class
>> Hash.superclass
=> Object
>> Hash.superclass.superclass
=> BasicObject
>> Symbol.class
=> Class
>> Symbol.superclass
=> Object
>> Symbol.superclass.superclass
=> BasicObject

>> def palindrome?
>> self ==reverse
>> end
=> :palindrome?

>> "level".palindrome?
=> true
>> "levela".palindrome?
=> false

演習
1. palindrome?メソッドを使って、“racecar”が回文であり、“onomatopoeia”が回文でないことを確認してみてください。南インドの言葉「Malayalam」は回文でしょうか? ヒント: downcaseメソッドで小文字にすることを忘れないで。
2. リスト 4.16を参考に、Stringクラスにshuffleメソッドを追加してみてください。ヒント: リスト 4.12も参考になります。
3. リスト 4.16のコードにおいて、self.を削除してもうまく動くことを確認してください。

リスト 4.16: Stringクラスにshuffleメソッドを定義する (「?」を適切なメソッドを置き換えてください)

class String
def shuffle
self.?('').?.?
end
end
"foobar".shuffle
=> "borafo"

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



class String
def shuffle
self.split('').shuffle.join
end
end
=> :shuffle
"foobar".shuffle
=> "rfooba"



>> class String
>> def shuffle
>> self.split('').shuffle.join  #シングルクォーテーションではなくカンマ
>> end
>> end
=> :shuffle
>> "foobar".shuffle
=> "abofor"

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

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

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

User => ApplicationRecord(abstract)=> ActiveRecord::Base=> Object=> BasicObject

4.4.5

  1. Userクラスで定義されているname属性を修正して、first_name属性とlast_name属性に分割してみましょう。また、それらの属性を使って "Michael Hartl" といった文字列を返すfull_nameメソッドを定義してみてください。最後に、formatted_emailメソッドのnameの部分を、full_nameに置き換えてみましょう (元々の結果と同じになっていれば成功です)
  2. "Hartl, Michael" といったフォーマット (苗字と名前がカンマ+半角スペースで区切られている文字列) で返すalphabetical_nameメソッドを定義してみましょう。
  3. full_name.splitとalphabetical_name.split(’, ’).reverseの結果を比較し、同じ結果になるかどうか確認してみましょう。

>> require './example_user'
=> true
>> example = User.new
=> #<User:0x00000000030aebe8 @first_name=nil, @last_name=nil, @email=nil>
>> example.first_name = "Michael"
=> "Michael"
>> example.last_name = "Hartl"                                                
=> "Hartl"
>> example.email =" mhartl@example.com"
=> " mhartl@example.com"
>> example.full_name
=> "Michael Hartl"
>> example.formatted_email
=> " < mhartl@example.com>"   フルネーム出てない
>> 

    "#{self.full_name} <#{@email}>" に変えたことによりselfで組み込み関数を使うのでできるようになる

>> require './example_user'
=> true
>> example = User.new
=> #<User:0x0000000003226b88 @first_name=nil, @last_name=nil, @email=nil>
>> example.first_name = "Michael"
=> "Michael"
>> example.last_name = "Hartl"
=> "Hartl"
>> example.email =" mhartl@example.com"
=> " mhartl@example.com"
>> example.full_name
=> "Michael Hartl"
>> example.formatted_email
=> "Michael Hartl < mhartl@example.com>"
>> 

自分の過去記事をサクッと解決+アクセスメソッド理解(インスタンス変数の@とself)

ここを参考にして考える

selfはオブジェクト自身を指します。と4.4.2にあるように
selfを使ってfull_nameメソッド地震を呼び出すためにselfにする
@full_nameとインスタンスメソッドを呼び出そうにもaccessorで設定してないのでセッターもゲッターもないし@full_nameというインスタンスメソッドも定義してないので呼び出せない。と思うのだけど違ったらご指摘ください。
2週目でここを理解しないで飛ばしていたことに気が付きいろいろ読み直してようやく理解した気になれた?

require './example_user'
=> true
user = User.new
=> #
user.first_name
=> nil
user.first_name = "Micheal"
=> "Micheal"
user.last_name = "Hartl"

=> "Hartl"
user.email = "mhartl@example.com"
=> "mhartl@example.com"
user.formatted_email
=> "Micheal Hartl mhartl@example.com"
user.alphabetical_name
=> "Hartl, Micheal"

2

>> user.full_name.split == user.alphabetical_name.split(',').reverse
=> false
なぜ?
>> user.full_name
=> "Micheal Hartl"
>> user.alphabetical_name
=> "Hartl, Micheal"

間違っていない気がする
悩んだ末もうtrueだったことにしようかなとそのときチュートリアルのページの
full_name.splitとalphabetical_name.split(’, ’).reverse
をコピペするとアポストロフィを打ち直さないとエラーが出るので打ち直すのですが
よく見るとカンマの後に半角スペースが!!これを消してた??

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

できた
二週目なのにこんなミスがまだある

0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0