Railsチュートリアル 第4章
Railsチュートリアルの第4章です. この章はわりと演習が楽しかったですね.
4.1 動機
トピックブランチを作成し, チェックアウトします.
4.1.1
省略.
4.1.2
カスタムヘルパーの作成は, 4.2を終えてからにします.
4.2 文字列とメソッド
4.2.1
省略.
4.2.2
省略.
4.2.3
ぱっと見, 文字列展開ちゃんとされるの?と思いましたが大丈夫でしたね.
>> string = "foobar" >> puts "The string '#{string}' is nonempty." unless string.empty?
演習1
省略.
演習2
リバースしたかどうかが分かる単語でも試してみるとよいですね.
演習3
true
が返ってきました.
演習4
nil
が返ってきました.
>> s = "onomatopoeia" >> puts "It's a palinrome!" if s == s.reverse => nil
4.2.4
演習1, 2
真似して書くだけですね.
演習3
次のようになりました.
>> palindrome_tester("racecar").nil? It's a palindrome! => true
4.2.5
ここでやり残していたカスタムヘルパーの作成を行いました.
テストコードを書き直します.
# test/controllers/static_pages_controller_test.rb # の一部を抜粋しています def setup @base_title = "Ruby on Rails Tutorial Sample App" end test "should get root" do get root_url assert_response :success end test "should get home" do get static_pages_home_url assert_response :success assert_select "title", @base_title #書き直し end
レイアウトを変更します.
# app/views/layouts/application.html.erb # の一部を抜粋しています <title><%= full_title(yield(:title)) %></title>
Home
ではbase_title
しか表示させないので, タイトル設定を消します.
# app/views/static_pages/home.html.erb <% provide(:title, "Home") %> # この行を削除 <h1>Sample App</h1> <p> This is the home page for the <a href="https://railstutorial.jp/">Ruby on Rails Tutorial</a> sample application. </p>
4.3 他のデータ構造
4.3.1
演習1, 2, 3
# 指定された文字列を変数sに格納 >> s = "A man, a plan, a canal, Panama" => "A man, a plan, a canal, Panama" # 文字列を分割して配列にする >> a = s.split(", ") => ["A man", "a plan", "a canal", "Panama"] # 再びひとつの文字列に >> s = a.join => "A mana plana canalPanama" # スペースを無くします >> s = s.split.join => "AmanaplanacanalPanama" # このままでは回文ではありませんが, >> s == s.reverse => false # 小文字に揃えれば回文です # メソッドチェーンの順番を変えたものもチェックしておきました. >> s.downcase == s.downcase.reverse => true >> s.downcase == s.reverse.downcase => true
演習4
# 範囲オブジェクトを配列に変換し, 変数tに格納 >> t = ("a".."z").to_a => ["a", "b", (途中省略), "z"] # 指定された2つとも取り出せるかと思いきやダメ >> t[7,-7] => nil >> t[7] => "h" >> t[-7] => "t" # インデックス2以降から3つ取り出す, という意味なんですね >> t[2,3] => ["c", "d", "e"]
4.3.2
演習1
範囲オブジェクトをかっこで囲うのを忘れてはいけませんね. またputs
を書かないと出力が目に見えません.
>> (0..16).each {|n| puts n**2} 0 1 4 9 16 25 36 49 64 81 100 121 144 169 196 225 256 => 0..16
演習2
ブロックを使わずとも定義できてしまいますね.
>> def yeller (array) >> array.join.upcase >> end => :yeller >> yeller("abc".split) => "ABC"
ブロックを使うなら以下のようになりますかね.
>> def yeller (array) >> array.map {|s| s.upcase}.join >> end => :yeller >> yeller("abc".split) => "ABC"
演習3
本文中にある方法だと, 異なる8文字の順列を作ることになります. ここはもう一歩踏み込んで, 重複ありの文字列を生成させてみます. 以下のような実装を思いつきました.
>> def random_dubdomain >> (0..7).map do >> ("a".."z").to_a.shuffle[0] >> end >> .join >> end => :random_dubdomain >> random_dubdomain => "uknjxsoa" >> random_dubdomain => "htoenews"
はじめ8.times
を使うことを思いつきましたが, 無駄にローカル変数を定義することになりそうです.
>> def random_subdomain >> tmp = [] >> 8.times do >> tmp << ("a".."z").to_a.shuffle[0] >> end >> tmp.join >> end => :random_subdomain >> random_subdomain => "xruoispc" >> random_subdomain => "wqdizcoc"
演習4
ヒント通りにやりました. split('')
がポイントですね.
>> def string_shuffle (s) >> s.split('').shuffle.join >> end => :string_shuffle >> string_shuffle("foobar") => "ofbaro"
4.3.3
演習1
rails console
では日本語が打てないので英語で対処しました.
>> hash = { "one" => "uno", "two" => "dos", "three" => "tres" } => {"one"=>"uno", "two"=>"dos", "three"=>"tres"} >> hash.each do |key, value| >> puts "'#{key}' is '#{value}' in Spanish" >> end 'one' is 'uno' in Spanish 'two' is 'dos' in Spanish 'three' is 'tres' in Spanish => {"one"=>"uno", "two"=>"dos", "three"=>"tres"}
演習2
サザエさんにご登場いただきました. 本文にあるように, 中括弧{ }
の内側には空白を入れています.
>> person1 = { first: "Masuo", last: "Fuguta" } => {:first=>"Masuo", :last=>"Fuguta"} >> person2 = { first: "Sazae", last: "Fuguta" } => {:first=>"Sazae", :last=>"Fuguta"} >> person3 = { first: "Tarao", last: "Fuguta" } => {:first=>"Tarao", :last=>"Fuguta"} >> params = { father: person1, mather: person2, child: person3 } => {:father=>{:first=>"Masuo", :last=>"Fuguta"}, :mather=>{:first=>"Sazae", :last=>"Fuguta"}, :child=>{:first=>"Tarao", :last=>"Fuguta"}} >> params[:father][:first] == person1[:first] => true
演習3
ランダムな文字列を作るメソッドを定義します.
>> def random_string >> (0..15).map do >> ("a".."z").to_a.shuffle[0] >> end >> .join >> end => :random_string
user
を作ります.
>> user = { name: "logicoffee", email: "logicoffee@example.com", password_digest: random_string } => {:name=>"logicoffee", :email=>"logicoffee@example.com", :password_digest=>"wjvqvczpmxmmvdwe"}
演習4
ここを見てみると, 2つのハッシュを組み合わせて新たなハッシュを返すメソッドのようですね. キーが重複している場合は上書きされるようです. やってみましょう.
>> { "a" => 100, "b" => 200 }.merge({ "b" => 300 }) => {"a"=>100, "b"=>300}
やはりそのようですね.
4.4 Rubyにおけるクラス
4.4.1
演習1, 2, 3
範囲オブジェクトの比較には注意が必要ですね.
>> r = Range.new(0,10) => 0..10 >> r == 0..10 Traceback (most recent call last): 1: from (irb):4 ArgumentError (bad value for range) >> r == (0..10) => true
4.4.2
演習1
>> r = 0..10 => 0..10 >> r.class => Range >> r.class.superclass => Object >> r.class.superclass.superclass => BasicObject >> h = { name: "Taro" } => {:name=>"Taro"} >> h.class => Hash >> h.class.superclass => Object >> h.class.superclass.superclass => BasicObject >> s = :name => :name >> s.class => Symbol >> s.class.superclass => Object >> s.class.superclass.superclass => BasicObject
演習2
たしかにself
キーワードを省略できますね.
>> class Word < String >> def palindrome? >> self == reverse >> end >> end => :palindrome? >> s = Word.new("level") => "level" >> s.palindrome? => true
4.4.3
演習1
例のように=> :String
とはなりませんでした.
>> class String >> def palindrome? >> self == self.reverse >> end >> end => :palindrome? >> "racecar".palindrome? => true >> "onomatopoeia".palindrome? => false >> "Malayalam".downcase.palindrome? => true
演習2, 3
>> class String >> def shuffle >> self.split("").shuffle.join >> end >> end => :shuffle >> "abcdefg".shuffle => "dgcbeaf" >> class String >> def shuffle >> split("").shuffle.join >> end >> end => :shuffle >> "onomatopoeia".shuffle => "eopiooataonm"
4.4.4
省略します.
4.4.5
演習1, 2, 3
example_user.rb
を用意します. full_name
メソッドと, alphabetical_name
メソッドで, インスタンス変数へのアクセス方法を変えてみました.
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.rb' => true >> user = User.new(first_name: "Michael", last_name: "Hartle", email: "mhartl@example.com") => #<User:0x000055993280b6c0 @first_name="Michael", @last_name="Hartle", @email="mhartl@example.com"> >> user.full_name => "Michael Hartle" >> user.alphabetical_name => "Hartle, Michael" >> user.formatted_email => "Michael Hartle <mhartl@example.com>" >> user.full_name.split == user.alphabetical_name.split(', ').reverse => true