Ruby on Railsチュートリアル第6版 第4章まとめ

Ruby on Railsチュートリアル第6版の第4章のまとめです。

個人的に気になったところ、難しかったところ、わからなかったところを中心にまとめていきます。基本的に自分の理解を助けることと、復習しやすくすることを目的とした記事ですが、今Ruby on Railsチュートリアルをやってる人に役立つ情報があるかもしれません。

僕の学習の順番は、1周目はRailsチュートリアル第4版(Rails5.1)を使い、2周目で第6版を使うという感じになってます。これは1周目が終わったところで第6版のWebテキスト版がリリースされたからです。

ちなみに、2周目は解説動画を購入してやってます。オススメです。

第4章 Rails風味のRuby

第4章 Rails風味のRuby

第4章はRubyがメインの章です。これまでRailsアプリケーションを作ってきたので、それと比べると少し退屈かもしれません。でも、ここをしっかり理解しておかないと、先に進むほど混乱してくると思います。

章のタイトルに「Rails風味」とある理由は、解説動画を見るとよくわかります。

36時間以上の解説動画でオンライン学習 - Railsチュートリアル
図やイラストを使ってコーディングしながら解説する36時間の動画です。早く効率的に学びたい、動画を観ながら勉強したい、といった場面でお役立てください。

4.1 動機

Railsチュートリアルをやってる人はRailsを使ってアプリケーションを作りたいという動機を持ってると思います。僕もそうです。

なので、Rubyを学ぶ動機というのはいまいちだったりします。でも、Railsは「Ruby on Rails」なので、Rubyが全くわからないというのでは使いこなすのは難しいはずです。

ということで、モチベーションアップのために、なぜRubyを学ぶのかを知るところから始める感じです。

まずは、新しいブランチを作ります。

4.1.1 組み込みヘルパー

第3章で作ったapplication.html.erbを使って説明がされてますが、「組み込みヘルパー」が何かという説明は書かれてません。

次の「カスタムヘルパー」の説明から推測すると、組み込み関数(最初からRailsにある関数)のことを「組み込みヘルパー」と呼ぶんだと思います。

例としてstylesheet_link_tagが使われてますが、それを理解するにはRubyの4つの概念が重要になるようです。

4.1.2 カスタムヘルパー

組み込みヘルパーはその説明がありませんでしたが、カスタムヘルパーの説明もよくわからない感じになってます。

Railsのビューでは膨大な数の組み込み関数が使えますが、それだけでなく、新しく作成することもできます。新しく作ったメソッドはカスタムヘルパーと呼ばれます。

Ruby on Railsチュートリアル第6版 第4章

1文目に「関数を作ることができる」と書いてありますが、2文目は「作ったメソッドがカスタムヘルパー」と書いてあります。

関数とメソッドの関係はどうなってるんでしょうか。調べてみました。「Re: Rubyの関数とメソッドの違いってなんだろ!」から引用しつつ、見ていきましょう。

Rubyは「すべてがオブジェクト」として設計されている純粋なオブジェクト指向言語です。(中略)Rubyに出てくるものは関数ではなく、すべてメソッドと呼ぶのが正しい、ということになります。

Re: Rubyの関数とメソッドの違いってなんだろ!

これだけでは理解できないので、詳しくは「Re: Rubyの関数とメソッドの違いってなんだろ!」を見てほしいんですが、一般的に「関数」と「メソッド」がどういう意味、文脈で使われてるかということが関係してるようです。

とにかく、Rubyでは関数とメソッドはほぼ同じものとして理解しておいてよさそうなので、先に進みます。

Railsではカスタムヘルパーと呼ばれる、自分で作ったメソッドも使えるということのようです。

第3章では3つのページのタイトルをページごとに変更するようにしました。ここではカスタムヘルパーを使って改良します。

ここで作るヘルパーは「app/helpers/application_helper.rb」に書き込みます。このファイルをはRailsアプリケーションを作ったときに自動的に作られてます。

その中でメソッドを定義するわけですが、ここでRubyの知識が必要になります。ということで、指示通りにいろいろやって、Rubyの学習に入っていきます。

4.2 文字列とメソッド

ここからRailsコンソールを使い始めます。その前に、邪魔な自動インデント機能をオフにしたりという設定をします。

yキーを押して保存するように指示がありますが、それだけだと元のコマンドラインに戻らず、さらにEnterキーを押したら戻りました。戸惑ったポイントです。

4.2.1 文字列

文字列に関していろいろ実験をします。文字列をそのまま表示したり、連結したり、変数に代入したり、式展開を使ったり、いろいろやります。

ダブルクォートとシングルクォートの違いもここで説明されてます。

>> puts "Ruby"
Ruby
=> nil

>> puts 'Ruby'
Ruby
=> nil

基本的にはこんな感じで同じように表示されますが、違いもあります。

>> puts "Ruby\non\nRails"
Ruby
on
Rails

=> nil
>> puts 'Ruby\non\nRails'
Ruby\non\nRails

ちょっと見にくいですが、RubyとonとRailsの間に「\n」を入れてみました。ダブルクォートで囲った方は改行されてますが、シングルクォートの方ではそのまま出力されてます。

バックスラッシュ(「\」)は環境によって円マークになったりするようです。僕の環境(Windows10)だと、ブログの投稿画面ではすべてバックスラッシュで、記事のページではコード部分だけ円マークになってます。詳しくは「円マーク(¥)とバックスラッシュ(\)は何が違う?」などを参照してください。

「\n」は改行コードなんですが、ダブルクォートではそれが機能して、シングルクォートでは機能しないという違いになってます。

>> str = "on"
=> "on"

>> puts "Ruby #{str} Rails"
Ruby on Rails
=> nil

>> puts 'Ruby #{str} Rails'                                                                    
Ruby #{str} Rails
=> nil

今度は式展開です。変数strに「on」を入れて、式展開を使って「Ruby on Rails」を出力しようとしましたが、ダブルクォートとシングルクォートで出力結果が違います。

「\n」のような特殊文字を表示したい、式展開をしたいというときはダブルクォートを使い必要があるようです。

ダブルクォート内で「\n」などをそのまま表示したい、式展開させたくない場合は、それらの前に「\」を入れます。

>> puts "Ruby\\non\nRails"
Ruby\non
Rails
=> nil

>> puts "Ruby \#{str} Rails"                                                                   
Ruby #{str} Rails
=> nil

4.2.2 オブジェクトとメッセージ受け渡し

Rubyはすべてがオブジェクトという説明がここで登場します。なぜnullじゃなくてnilなのかというのが気になってましたが、解説動画の説明で謎が解けました。完ぺきに理解できたかはわかりませんが。

36時間以上の解説動画でオンライン学習 - Railsチュートリアル
図やイラストを使ってコーディングしながら解説する36時間の動画です。早く効率的に学びたい、動画を観ながら勉強したい、といった場面でお役立てください。

ここでもいろいろ実験をやっていきます。ただ指示通りにやるよりも、それをやることで何を理解させようとしてるのかを意識しながら進めるといいかなと思います。

4.2.3 メソッドの定義

やっとメソッドが出てきました。カスタムヘルパーを理解するにはメソッドを理解する必要があります。

「暗黙の戻り値」がよくわかりませんでしたが、これも解説動画で何となくわかりました。

上のコードでは、putsで出力した文字列のあとに「nil」が出てますよね。これが戻り値で、putsは戻り値を持たないので「nil」ということみたいです。

詳しくは解説動画で!

36時間以上の解説動画でオンライン学習 - Railsチュートリアル
図やイラストを使ってコーディングしながら解説する36時間の動画です。早く効率的に学びたい、動画を観ながら勉強したい、といった場面でお役立てください。

4.2.4 titleヘルパー、再び

ここまで来れば、最初に出てきたカスタムヘルパーの意味がわかるようになります。

Rubyであればincludeメソッドが必要ですが、Railsだとヘルパーを自動的に読み込んでくれるそうです。便利ですね。その反面、それを理解してないと何をやってるのかわからなくなってしまいますが。

1周目で混乱したのはこの辺の「自動化された」ところと関係してそうな気がします。言われるがままにコードを書いて、「お、動いた」で進んだところがたくさんあったので。

ということで自分用に解説しておくと、

モジュールは、関連したメソッドをまとめる方法の1つで、includeメソッドを使ってモジュールを読み込むことができます(ミックスイン(mixed in)とも呼びます)。(中略)Railsではヘルパーモジュールを読み込んでくれるので、include行をわざわざ書く必要がありません。

Ruby on Railsチュートリアル第6版 第4章

ということなので、どのヘルパーがどこで自動的に読み込まれるかが重要ということなのかもしれません。この先、ヘルパーにメソッドを追加することがあったと思うので、動きを注意深く見てく必要がありそうです。

4.3 他のデータ構造

またRubyに戻って、他のデータ構造を見ていきます。「他の」ってどういうことだろう?と思って確認したら、「4.2.1文字列」で出てきてました。

文字列もデータ構造だそうです。

4.3.1 配列と範囲演算子

他のプログラミング言語にもあるように、Rubyにも配列があります。その操作を実際に手を動かして学びます。

範囲演算子は面白いなと思いました。

この辺はProgateをやってたり、2周目だったり、他のプログラミング言語を勉強してたりすれば問題ないと思います。

念のため1周目はすべてやってみて、2周目以降は各自の判断という感じかなと思います。僕は面倒だったので2周目では一部を除いてやりませんでした。

演習はやってみると意外と難しかったりするので、やっといた方がいいかなと思います。

4.3.2 ブロック

ブロックは何やらすごいものらしいんですが、そのすごさがいまいち理解できません。解説動画によると、for文との関係で理解するとよさそうな感じです。

ブロックは見た目に反して奥が深く、ブロックを十分に理解するには相当なプログラミング経験が必要です。

Ruby on Railsチュートリアル第6版 第4章

こう書かれてるので、今理解できなくても問題ないんだと思います。

1つだけ覚えておいた方がよさそうなのは、ブロックの書き方です。すぐに忘れそうですが、何度も繰り返すことで記憶に定着させたいところです。

一応、Railsチュートリアルの説明を引用しておきます。

ブロックであることを示すには波カッコで囲みますが、次のようにdoとendで囲んで示すこともできます。

Ruby on Railsチュートリアル第6版 第4章

doとendの組み合わせはテストコードで出てきましたね。あれもブロックだったということです。1周目で何度もdoを書き忘れた記憶があるので、do-endはブロックであること、testはブロック付きメソッドであることを覚えておくと忘れにくくなるかもしれません。

4.3.3 ハッシュとシンボル

ハッシュは、他のプログラミング言語で連想配列と呼ばれたりするものです。

配列は0から始まる番号(インデックス)と文字列などをセットにしたものですが、ハッシュはその番号の代わりに別のものを使えるというものです。番号の代わりのものを「キー」と呼ぶそうです。

これはラベルに番号じゃなくて、名前を付ける、みたいな感じに覚えるとわかりやすいと思います。

配列の要素を取り出すには、

a[0]

のように、配列名[インデックス]という書き方をします。

ハッシュはというと、

a["hoge"]

のように、ハッシュ名[キー]と書きます。

配列とハッシュでは使うカッコが違います。配列は[]、ハッシュは{}です。

array = ["a", "b", "c"]

hash = { "key1" => "a", "key2" => "b", "key3" => "c" }

ハッシュではシンボルをキーとして使うことが一般的なようです。シンボルは「:key」のようにコロンが前に付いたものです。

なぜシンボルを使うのか、シンボルとは何か、ということについては解説動画を見るとわかります。

36時間以上の解説動画でオンライン学習 - Railsチュートリアル
図やイラストを使ってコーディングしながら解説する36時間の動画です。早く効率的に学びたい、動画を観ながら勉強したい、といった場面でお役立てください。

ハッシュの中には、ハッシュを入れることもできます。Railsではそういうのがたくさん使われてるようなので、しっかりと理解したいところです。

4.3.4 CSS、再び

ここでは、app/views/layouts/application.html.erbにあるスタイルシートを読み込むコードについて解説されてます。最初に出てきたやつですね。

ここのところがいまいちわからずに、何度も読み返してます。いまだに十分理解したとは言えない感じです。

stylesheet_link_tag 'application', media: 'all',
                                   'data-turbolinks-track': 'reload'

これがここで取り上げてるコードです。これまで学んできたことを使うと、このコードがわかるようになるらしいです。

media引数はハッシュのようですが、波カッコがない点が不思議です。

Ruby on Railsチュートリアル第6版 第4章

「media引数」を「mediaの引数」と読んで大混乱。よく見たら「media引数」で「の」はないんですよね。ということは、media引数はstylesheet_link_tagの第2引数という理解でいいんでしょうか。

そうだとしたら、ハッシュは「mediaとall」セットと、「data-turbolinks-trackとreload」セットということですね。

と思ったら、stylesheet_link_tagメソッドを2つの引数で呼んでるとちゃんと書いてありました。

data-turbolinks-trackについてはturbolinksを理解しないといけないようなので、とりあえず放置することにします。

4.4 Rubyにおけるクラス

Ruby on Railsチュートリアル第6版 第2章まとめ」でも軽く触れたクラスについてです。クラスの継承がわかれば、第2章まとめで何を追ってたのかわかると思います。

4.4.1 コンストラクタ

ここにはコンストラクタが何なのか書いてなかったので調べてみましたが、よくわかりませんでした。オブジェクトを作成するためのコードという感じでしょうか?

4.4.1の内容についても解説動画がわかりやすいと思います。

36時間以上の解説動画でオンライン学習 - Railsチュートリアル
図やイラストを使ってコーディングしながら解説する36時間の動画です。早く効率的に学びたい、動画を観ながら勉強したい、といった場面でお役立てください。

4.4.2 クラス継承

クラス継承に関する僕の理解は、「あるクラスの機能を引き継いで、新しいクラスを作ることをクラス継承と呼ぶ」というものです。

ここではクラス階層をsuperclassメソッドを使ってみていきます。なかなか興味深い感じです。

superclassメソッドでそのクラスの親クラスを見てくわけですが、逆に言えばそのクラスは親クラスを継承して作られてるということです。

Aクラスの親クラスがBクラスなのであれば、Bクラスを継承してAクラスが作られてるということですね。

クラスを作るときはこんなコードになります。

class ParentClass
  #何らかの処理とか
end

クラス名の頭文字は大文字になります。

このクラスを継承して新しいクラスを作るときは、

class ChildClass < ParentClass
  #何らかの処理とか
end

という感じで、「<」を使います。

4.4.3 組み込みクラスの変更

Rubyに元々あるクラスに新しいメソッドを付け加えることもできます。これはRailsでも使われてるようです。

もしかしたらいつか使うことになるかもしれませんが、今のところ使うことはないと思うので、「そんなこともできるんだ」くらいに思っておけばいいかなと思います。

4.4.4 コントローラクラス

クラスのことがわかれば、コントローラのコードが理解できるようになります。第3章で作ったコントローラのクラスは、クラス継承で作られてます。

4.4.5 ユーザークラス

Rubyのことが何となくわかってきたところで、Userクラスを作ってみます。ここで作ったファイルは最後に削除するので、この先に影響することはありません。

アプリケーションのルートディレクトリにファイルを作って、指示通りにやっていきます。

ここでよくわからなかったのが、attr_accessorとinitializeメソッドです。なので調べてみました。

まずはattr_accessorから。これは「attr_accessorの使い方を解説してみる」がわかりやすいと思います。

attr_accessorとはインスタンス変数を直接変更して操作できるようにするもの。

attr_accessorの使い方を解説してみる

これがattr_accessorの説明ですが、これだけではよくわかりません。でも、その記事には実例での説明があるので、それを読めばわかると思います。

クラス内で定義した変数に、クラス外からアクセスする(代入する?)ときにattr_accessorが必要なようです。

Railsチュートリアルでは次のようなコードが使われてます。

class User
  attr_accessor :name, :email

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

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

attr_accessorとして、:nameと:emailが設定されてますね(シンボルですね)。これをすることでクラス外からアクセスできるようになります。具体的に言うと、

example.name

これとかが機能するようになります。実際にattr_accessorを削除して試してみます。

>> example = User.new
=> #<User:0x00007ff48ca8ea70 @name=nil, @email=nil>
>> example.name
Traceback (most recent call last):
        1: from (irb):3
NoMethodError (undefined method `name' for #<User:0x00007ff48ca8ea70 @name=nil, @email=nil>)

exampleに新しいユーザーを代入するところは成功してますが、「example.name」でエラーが出てます。「nameメソッドが定義されてないよ」と言われてますね。

attr_accessorを入れると機能するようになります。

次に、initializeメソッドです。

initializeメソッドを調べてみると、Railsチュートリアルの例とは少し違うものが出てくるので理解が大変です。ちゃんと理解できたかわからないのですが、その前提で説明してみたいと思います。

Let’sプログラミング」では、initializeメソッドは次のように説明されてます。

インスタンスメソッドの中で「initialize」と言う名前が付けられたメソッドは特殊なメソッドです。このメソッドをクラス内に記述した場合にはオブジェクトが作成される時に自動的に呼び出されます。

initializeメソッド – Let’sプログラミング

initializeメソッドはオブジェクトが作られたときに自動的に呼び出されるメソッドだそうです。User.newをすると、自動的にinitializeメソッドが呼び出されて、そこに書かれてる処理が実行されるということですね。

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

Railsチュートリアルでの例はこれです。

initilizeメソッドの引数は「attributes = {}」となってます。これはattributesという空のハッシュですね。

で、@nameにはattributesハッシュのキーが「:name」のもの、@emailにはキーが「:email」のものが代入されます。

attr_accessorの実験ではUser.newで引数を指定してないので、空のハッシュが自動的に使われます。ということで、

>> example = User.new
=> #<User:0x00007ff48ca8ea70 @name=nil, @email=nil>

というように、@nameと@emailはnilになるわけです。

もしこのinitializeメソッドがなかったらどうなるでしょうか。これも試してみました。試してみたコードはこれです。

class User
  attr_accessor :name, :email

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

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

initializeメソッドの代わりにnameメソッドにしてあります。これをさっきと同じように実行してみると、

example = User.new
=> #<User:0x00007ff48c4ca990>

こうなります。さっきはあった@nameと@emailが亡くなりましたね。exampleに入ってるものを表示してみます。

>> example
=> #<User:0x00007ff48c4ca990>

やっぱり@nameと@emailがありません。

でも、実験用コードにはnameメソッドがあるので、これを使って@nameと@emailに値を入れることができます。

>> example.name = "rails"
=> "rails"
>> example.email = "rails@rails.rails"
=> "rails@rails.rails"
>> example
=> #<User:0x00007ff48c4ca990 @name="rails", @email="rails@rails.rails">

次に、この状態で@nameと@emailに値を入れた状態でユーザーを作れるか実験してみます。

>> example = User.new(name: "rails", email: "rails@rails.rails")                               
Traceback (most recent call last):
        4: from (irb):12
        3: from (irb):12:in `rescue in irb_binding'
        2: from (irb):12:in `new'
        1: from (irb):12:in `initialize'
ArgumentError (wrong number of arguments (given 1, expected 0))

何やらエラーが出ました。調べてみるとargumentは引数のことのようです。それを踏まえてエラーの内容を読むと、「引数の数が間違ってるよ、与えられたのが1だけど期待されてるのは0だよ」みたいな感じですね。

ということは、この状態ではnewメソッドに引数を付けられないということですね。

今のところの理解はこんな感じで、間違いに気づいたり、より理解できたりしたら書き直そうと思います。

あとは実験用ファイルを削除して、コミット、マージ、GitHubにプッシュ、Herokuにデプロイして終了です。

まとめ

Railsチュートリアル第4章は主にRubyだったので、アプリケーション開発としてはあまり進んでません。そのせいで、なかなかしんどい章の1つでした。

でも、しっかり理解してなかったところを2周目で確認して、以前よりは理解できたかなと思ってます。

今はRailsの理解で精一杯というところがありますが、RubyはRubyで奥が深そうなので、このままRuby on Railsを使い続けるのであればどこかでしっかり学ぶ必要があるだろうなと思います。

今回まとめたattr_accessorとinitializeメソッドはまたわかんなくなりそうなので、この記事を見返すことになりそうな気がしてます。

ということで、次からはまたアプリケーション開発に戻るので、気合を入れていきましょう。

Ruby on Rails チュートリアル:実例を使って Rails を学ぼう
SNS 開発を題材にした大型チュートリアル。プロダクト開発の 0→1 を創りながら学びます。電子書籍や解説動画、質問対応、法人向けサービスも提供しています。