Ruby on Rails チュートリアル

実例を使ってRailsを学ぼう

Michael Hartl (マイケル・ハートル)

第4版 目次

推薦の言葉

私が前にいた会社 (CD Baby) は、かなり早い段階でRuby on Railsに乗り換えたのですが、またPHPに戻ってしまいました (詳細は私の名前をGoogleで検索してみてください)。そんな私ですが、Michael Hartl 氏の本を強く勧められたので、その本を使ってもう一度試してみた結果、今度は無事に Rails に乗り換えることができました。それがこの Ruby on Rails チュートリアルという本です。

私は多くの Rails 関連の本を参考にしてきましたが、真の決定版と呼べるものは本書をおいて他にありません。本書では、あらゆる手順が「Rails 流」で行われています。最初のうちは慣れるまでに時間がかかりましたが、この本を終えた今、ついにこれこそが自然な方式だと感じられるまでになりました。また、本書は Rails 関連の本の中で唯一、多くのプロが推奨するテスト駆動開発 (TDD: Test Driven Development) を、全編を通して実践しています。実例を使ってここまで分かりやすく解説された本は、本書が初めてでしょう。極めつけは、Git や GitHub、Heroku の実例に含めている点です。このような、実際の開発現場で使わているツールもチュートリアルに含まれているため、読者は、まるで実際のプロジェクトの開発プロセスを体験しているかのような感覚が得られるはずです。それでいて、それぞれの実例が独立したセクションになっているのではなく、そのどれもがチュートリアルの内容と見事に一体化しています。

本書は、筋道だった一本道の物語のようになっています。私自身、章の終わりにある練習問題もやりながら、この Rails チュートリアルを3日間かけて一気に読破しました1。最初から最後まで、途中を飛ばさずにやるのが一番効果的で有益な読み方です。ぜひやってみてください。

それでは、楽しんでお読みください!

Derek Sivers (sivers.org) CD Baby 創業者

(訳注: たった3分のTEDの動画「社会運動をどうやって起こすか」を観たことがある方もいるのではないでしょうか。その方からの推薦の言葉です。)

謝辞

Ruby on Rails チュートリアルは、私の以前の著書「RailsSpace」と、その時の共著者 Aurelius Prochazka から多くを参考にさせてもらっています。Aure には、協力と本書への支援も含め、感謝したいと思います。また、RailsSpaceRails チュートリアルの編集を担当した Debra Williams Cauley 氏にも謝意を表したく思います。彼女が野球の試合に連れて行ってくれる限り、私は本を書き続けるでしょう。

私にインスピレーションと知識を与えてくれた Rubyist の方々にも感謝したいと思います: David Heinemeier Hansson, Yehuda Katz, Carl Lerche, Jeremy Kemper, Xavier Noria, Ryan Bates, Geoffrey Grosenbach, Peter Cooper, Matt Aimonetti, Mark Bates, Gregg Pollack, Wayne E. Seguin, Amy Hoy, Dave Chelimsky, Pat Maddox, Tom Preston-Werner, Chris Wanstrath, Chad Fowler, Josh Susser, Obie Fernandez, Ian McFarland, Steven Bristol, Pratik Naik, Sarah Mei, Sarah Allen, Wolfram Arnold, Alex Chaffee, Giles Bowkett, Evan Dorn, Long Nguyen, James Lindenbaum, Adam Wiggins, Tikhon Bernstam, Ron Evans, Wyatt Greene, Miles Forrest, Sandi Metz, Ryan Davis, Aaron Patterson, Pivotal Labs の方々、Heroku の方々、thoughtbot の方々、そして GitHub の方々、ありがとうございました。最後に、ここに書ききれないほど多くの読者からバグ報告や提案を頂きました。ご協力いただいた皆様のおかげで、本書の完成度をとことんまで高めることができました。

丁寧なレビュー、技術的なフィードバック、そして役立つ提案をしてくれた Andrew Thai に感謝します。また、Learn Enough to Be Dangerous の共同創業者である Nick Merwin と Lee Donahoe、日々のチュートリアルの制作をサポートしてくれてありがとう。

最後に、たくさんの読者の皆さん、そして、ここに挙げきれないほど多いコントリビューターのみんな、バグ報告や提案をしてくれてありがとう。彼ら/彼女らの多くの手助けに、最高の感謝を。

著者

マイケル・ハートル (Michael Hartl)Ruby on Rails Tutorial という、Web 開発を学ぶときによく参考にされる本の著者です。 また、Learn Enough to Be Dangerous (learnenough.com) 教育系ウェブサイトの創業者でもあります。 以前は、(今ではすっかり古くなってしまいましたが)「RailsSpace」という本の執筆および開発に携わったり、また、 一時人気を博した Ruby on Rails ベースのSNSプラットフォーム「Insoshi」の開発にも携わっていました。 2011年には、Rails コミュニティへの高い貢献が認められて、Ruby Hero Award を受賞しました。

ハーバード大学卒業後、カリフォルニア工科大学物理学博士号を取得。シリコンバレーの有名な起業プログラム Y Combinator の卒業生でもあります。

  1. 3日間で読破できる人は例外です! 実際には数週間〜数ヶ月をかけて読むのが一般的です。 

第4章Rails風味のRuby

この章では、3で使用した例を基に、Railsにおいて重要となるRubyのさまざまな要素について探っていくことにしましょう。Rubyは巨大な仕様を持つ言語ですが、幸い、Rails開発者にとって必要な知識は比較的少なくて済みます。 また、一般のRuby入門書で扱っている内容とも多少異なっています。 この章の目的は、「Rails風味のRuby」というものについての確固たる基盤を、皆さんのこれまでの言語経験に関わらず提供することです。 この章には多くの話題が盛り込まれていますが、一度読んだだけで理解する必要はまったくありません。 今後もこの章には頻繁に立ち戻って参照します。

4.1 動機

前章でお見せしたとおり、Rubyの基礎知識がまったくない状態であったにもかかわらずRailsアプリケーションの骨組みを作り上げ、さらにテストまで行うことができました。 このときは、本書が提供するテストコードと、テストスイートがパスするまでエラーメッセージの修正を繰り返すという方法だけを頼りに作業を進めました。 しかしこのような初歩的な作業をいつまでも続けるわけにはいきませんので、今の私たちのRubyに関する知識と経験の限界に真正面から挑み、これを乗り越えるためにこの章を割り当てることにします。

まずは3.2のときと同様にトピックブランチを作り、そこで変更をコミットしていきましょう。

$ git checkout -b rails-flavored-ruby

トピックブランチでコミットした変更は、4.5でマージすることにします。

4.1.1 組み込みヘルパー

前章の終わりでは、Railsのレイアウトを使用してビューでの重複を取り除くために、ほぼ静的なページを単に更新したにとどまりました (リスト 4.1)。これは、リスト 3.35と同じものです。

リスト 4.1: サンプルアプリケーションのレイアウト app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>
    <%= csrf_meta_tags %>
    <%= stylesheet_link_tag    'application', media: 'all',
                                              'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>

  <body>
    <%= yield %>
  </body>
</html>

リスト 4.1の次の行にご注目ください。

<%= stylesheet_link_tag 'application', media: 'all',
                                       'data-turbolinks-track': 'reload' %>

ここでは、Railsの組み込み関数stylesheet_link_tag (詳細はRails APIを参照) を使用して、application.cssをすべてのメディアタイプにインクルードしています (メディアタイプには、コンピュータの画面や印刷画面なども含まれます)。 Rails開発経験者にとってこの行は実にシンプルですが、しかしここには少なくとも混乱を生じる可能性のあるRubyの概念が4つあります。Railsの組み込み関数、かっこを使わない関数呼び出し、シンボル、そしてハッシュです。 これらの概念についてはこの章ですべて説明します。

4.1.2 カスタムヘルパー

Railsのビューでは膨大な数の組み込み関数が使えますが、それだけでなく、新しい関数を作成することもできます。新しく作った関数はカスタムヘルパー と呼ばれます。カスタムヘルパーの作成方法を学ぶため、まずはリスト 4.1のタイトル行に注目しましょう。

<%= yield(:title) %> | Ruby on Rails Tutorial Sample App

上の行は、ページタイトルの定義に依存しています。この定義は、次のようにビューでprovideを使用して行われています。

<% provide(:title, "Home") %>
<h1>Sample App</h1>
<p>
  This is the home page for the
  <a href="http://railstutorial.jp/">Ruby on Rails Tutorial</a>
  sample application.
</p>

このとき、もしタイトルをまったく与えていなければ、タイトルが空欄になってしまいます。 これを防ぐには、すべてのページで使用する基本タイトルを定め、特定のページでは異なるタイトルに変更できるようなオプションを与えるのが常套手段です。 これは現在のレイアウトでも、ある点を除いて達成されています。もしビューの1つからprovide呼び出しを削除すると、そのページ固有のタイトルの代わりに以下のタイトルが表示されます。

  | Ruby on Rails Tutorial Sample App

基本タイトルとしてはこれで正しいのですが、先頭に余分な縦棒 | が残ってしまっています。

ページタイトルが正しく表示されない問題を解決するために、full_titleというヘルパーを作成することにします。 full_titleヘルパーは、ページタイトルが定義されていない場合は基本タイトル「Ruby on Rails Tutorial Sample App」を返し、定義されている場合は基本タイトルに縦棒とページタイトルを追加して返します (リスト 4.2)1

リスト 4.2: full_titleヘルパーを定義する app/helpers/application_helper.rb
module ApplicationHelper

  # ページごとの完全なタイトルを返します。
  def full_title(page_title = '')
    base_title = "Ruby on Rails Tutorial Sample App"
    if page_title.empty?
      base_title
    else
      page_title + " | " + base_title
    end
  end
end

ヘルパーを作成したので、これを使ってレイアウトをシンプルにすることができます。

<title><%= yield(:title) %> | Ruby on Rails Tutorial Sample App</title>

つまり、上のコードが下のようになります。

<title><%= full_title(yield(:title)) %></title>

置き換えた結果をリスト 4.3に示します。

リスト 4.3: full_titleヘルパーを使ったWebサイトのレイアウトgreen app/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title><%= full_title(yield(:title)) %></title>
    <%= csrf_meta_tags %>
    <%= stylesheet_link_tag    'application', media: 'all',
                                              'data-turbolinks-track': 'reload' %>
    <%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
  </head>
  <body>
    <%= yield %>
  </body>
</html>

このヘルパーを定義することで、Homeページにこれまで表示されていた余分な「Home」という単語を表示せず、基本タイトルのみを正しく表示することもできるようになります。 これを行うには、まずリスト 4.4に示すように以前のテストコードを更新し、"Home" という文字が表示されていないことを確認するテストを追加します。

リスト 4.4: Homeページのタイトル確認用にテストを更新する red test/controllers/static_pages_controller_test.rb
require 'test_helper'

class StaticPagesControllerTest < ActionDispatch::IntegrationTest
  test "should get home" do
    get static_pages_home_url
    assert_response :success
    assert_select "title", "Ruby on Rails Tutorial Sample App"
  end

  test "should get help" do
    get static_pages_help_url
    assert_response :success
    assert_select "title", "Help | Ruby on Rails Tutorial Sample App"
  end

  test "should get about" do
    get static_pages_about_url
    assert_response :success
    assert_select "title", "About | Ruby on Rails Tutorial Sample App"
  end
end

ここでテストスイートを実行して、テストが失敗することを確認します。

リスト 4.5: red
$ rails test
3 tests, 6 assertions, 1 failures, 0 errors, 0 skips

テストがパスするためには、リスト 4.6のようにHomeページのビューからprovide の行を削除する必要があります。

リスト 4.6: ページタイトルをカスタマイズせずに表示するHomeページ green app/views/static_pages/home.html.erb
<h1>Sample App</h1>
<p>
  This is the home page for the
  <a href="http://railstutorial.jp/">Ruby on Rails Tutorial</a>
  sample application.
</p>

この時点で、テストはパスするはずです。

リスト 4.7: green
$ rails test

注意: これまではrails testを実行した結果の一部 (成功結果や失敗結果など) も載せていましたが、紙幅の関係から、今後は実行結果を省略します。

Rails開発経験者にとって、4.1.1で紹介したリスト 4.2のコードは、スタイルシートをインクルードするのと大差ない単純なものですが、ここにもRubyの重要な概念が多数含まれています。具体的にはモジュール、メソッド定義、任意のメソッド引数、コメント、ローカル変数の割り当て、論理値 (boolean)、制御フロー、文字列の結合、そして戻り値です。これらの概念について、この章で理解していきましょう。

4.2 文字列とメソッド

Ruby を学ぶためのツールとして、主にRailsコンソールを使っていくことにします。これは2.3.3で登場した、Railsアプリケーションを対話的に操作するためのコマンドラインツールです。 Railsコンソールはirb (IRB: Interactive RuBy) を拡張して作られているため、Rubyの機能をすべて使うことができます (4.4.4でも説明しますが、RailsコンソールからRails環境にアクセスすることもできます)。

クラウドIDEをご利用の場合は、オススメのirbの設定があります。シンプルなテキストエディタ「nano」を使って、まずはホームディレクトリに「.irbrc」ファイルを作ってみましょう2

$ nano ~/.irbrc

次に、リスト 4.8のような設定を書きます。この設定によりirbのプロンプトが簡潔な表示に置き換えられ、irbの邪魔な自動インデント機能がオフになります。

リスト 4.8: irbの設定ファイルを追加する ~/.irbrc
IRB.conf[:PROMPT_MODE] = :SIMPLE
IRB.conf[:AUTO_INDENT_MODE] = false

最後に、Ctrl-Xと押してnanoエディタから離脱します。ファイルを保存するかどうか訊かれるので、yキーを押して~/.irbrcファイルを保存しましょう。

これで準備が整ったので、次のコマンドを実行して早速Railsコンソールを起動してみましょう。

$ rails console
Loading development environment
>>

デフォルトでは、コンソールはdevelopment (開発) 環境という、Railsによって定義された3種類の環境のうちの1つで起動します (他の2つはtest (テスト) 環境production (本番) 環境です)。この区別は本章においてあまり重要ではありません。ただ、次章以降では重要になってくるので、7.1.1でこれらの環境について詳しく説明することにします。

Railsコンソールは素晴しい学習ツールであり、その中を自由に探索できます。コンソールの中で何をしようとも、何かを壊すことは (まず) ありえないので、ご安心ください。もしRailsコンソールが何かおかしな挙動になったら、Ctrl-Cを押してコンソールから強制的に抜け出すことができます。もしくは、Ctrl-Dを押して正常にコンソールを終了させることもできます (このようなトラブルシューティングはCommand LineチュートリアルのGetting out of Trouble (英語) でまとめています)。なお、一般的なターミナルと同じで、Ctrl-Pまたは上矢印キーで以前に実行したコマンドを再利用することができます。時間の節約になるので、ぜひ活用してみてください。

また、本章を進めるにあたり気になるコードがあれば、有用なリソースであるRuby API (英語) を参照しながら学習することをぜひオススメします 。Ruby APIには高濃縮の情報が詰まっています (少々濃厚すぎるとも言えます)。たとえば、Rubyの文字列の詳細を知りたい場合は、Ruby APIエントリのStringクラスを参照すればよいのです。

訳注: 日本語ではRubyリファレンスマニュアル (通称: るりま))るりまサーチが大変便利です。

4.2.1 コメント

Rubyのコメントはナンバー記号# (「ハッシュマーク」や「オクトソープ」とも呼ばれます) から始まり、その行の終わりまでがコメントとして扱われます。Rubyはコメントの内容を実行することはありませんが、適切なコメントはそれを読む人間にとって (コードの作者にとっても) 非常に有用です。例えば次のコードの場合、

# ページごとの完全なタイトルを返します。
def full_title(page_title = '')
  .
  .
  .
end

最初の行が、その後に定義されている関数の目的を説明しているコメントになります。

コメントをコンソール内で入力する人は普通いませんが、ここでは学習のためにあえて次のようにコメントを追加してみましょう。

$ rails console
>> 17 + 42   # 整数の足し算
=> 59

この章のコードを (ファイルに保存するのでなく) Railsコンソールに入力したりコピペしたりするときであれば、コメントを省略してもかまいません。コメントをRailsコンソールに入力しても、コメントは常に無視されるので問題ありません。

4.2.2 文字列

文字列 (string) は、Webアプリケーションにおいておそらく最も重要なデータ構造です。これは、Webページというものが究極的にはサーバーからブラウザに送信された文字列にすぎないためです。 それでは、コンソールで文字列について調べてみましょう。

$ rails console
>> ""         # 空の文字列
=> ""
>> "foo"      # 空ではない文字列
=> "foo"

ここで入力したものは文字列リテラルと呼ばれ (面白いことにリテラル文字列とも呼ばれます)ダブルクォート " で囲むことで作成できます。このコンソールは、入力したそれぞれの行を評価した結果を表示しており、文字列リテラルの場合には文字列自身が表示されます。

+ 演算子を使用して、文字列を結合することもできます。

>> "foo" + "bar"    # 文字列の結合
=> "foobar"

評価の結果は、"foo""bar" を足した"foobar"になりました3

文字列を組み立てる他の方法として式展開 (interpolation) というものがあり、#{}という特殊な構文を使用します4

>> first_name = "Michael"    # 変数の代入
=> "Michael"
>> "#{first_name} Hartl"     # 文字列の式展開
=> "Michael Hartl"

例えば"Michael"という値をfirst_name変数に代入 (assign) し、この変数を "#{first_name} Hartl" という形で文字列の中に埋め込むと、文字列の中でその変数が展開されるようになります。同様にして、苗字と名前の両方を変数に割り当ててみましょう。

>> first_name = "Michael"
=> "Michael"
>> last_name = "Hartl"
=> "Hartl"
>> first_name + " " + last_name    # 苗字と名前の間に空白を入れた結合
=> "Michael Hartl"
>> "#{first_name} #{last_name}"    # 式展開を使って結合 (上と全く同じ)
=> "Michael Hartl"

最後の2つの結果は、全く同じ結果 (「等価」と言います) になっていますね。なお、著者は後者の式展開の方が好みです。空白を" "のように直接加えるのはどうもぎこちなく思えるからです。

出力

文字列を出力したい (画面に表示したい) ときに 、Rubyの関数で最も一般に使われるのはputsです (putの三人称単数現在形ではなく「put string」の略なので、本来は「put ess」と発音しますが、最近は「puts」と発音されることも多くなってきました)。

>> puts "foo"     # 文字列を出力する
foo
=> nil

putsメソッドでは副作用が重要な役割を果たします。どういうことかと言うと、puts "foo"は文字列「"foo"」を副作用としてスクリーンに表示しますが、戻り値には「文字どおりの無」であるnilを返します。nilは「何にもない」ことを表すRubyの特別な値です。 なお、=> nil という結果は、簡素化のために今後省略することがあります。

上の例からも分かるように、putsを使用して出力すると、改行文字である\nが自動的に出力の末尾に追加されます (これはターミナルのechoコマンドと同じ振る舞いになります)。printメソッドも同様の出力を行いますが、次のように、改行文字を追加しない点が異なります。

>> print "foo"    # 文字列の画面出力 (putsと同じだが改行がない)
foo=> nil

上の例が示すように、fooが出力された後に改行が入らないため、そのまま => nil が続いてしまっています。

意図的に改行を追加したいときは、「バックスラッシュ (\) + n」( \n) という改行文字を使います。この改行文字とprintを組み合わせると、putsと同じ振る舞いを再現することができます。

>> print "foo\n"  # puts "foo" と等価
foo
=> nil

シングルクォート内の文字列

これまでの例ではすべてダブルクォート文字列を使用していましたが、Rubyではシングルクォートもサポートしています。 ほとんどの場合、ダブルクォートとシングルクォートのどちらを使用しても実質的に同じです。

>> 'foo'          # シングルクォートの文字列
=> "foo"
>> 'foo' + 'bar'
=> "foobar"

ただし、1つ重要な違いがあります。Rubyはシングルクォート文字列の中では式展開を行いません。

>> '#{foo} bar'     # シングルクォート内の文字列では式展開ができない
=> "\#{foo} bar"

逆に言えば、ダブルクォート文字列を用いた文字列で#のような特殊な文字を使いたい場合は、この文字をバックスラッシュでエスケープ (escape) する必要があります。

ダブルクォート文字列でもシングルクォート文字列と同じことができ、ダブルクォート文字列では式展開もできるのであれば、シングルクォート文字列にはどのような使い道があるのでしょうか。シングルクォートは、入力した文字をエスケープせずに「そのまま」保持するときに便利です。たとえば、いわゆる「バックスラッシュ」文字は、改行文字 \nと同様に多くのシステム上で特殊な文字として扱われます。なお、シングルクォートで文字列を囲めば、簡単にバックスラッシュ文字のような特殊文字をそのまま変数に含めることができます。

>> '\n'       # 'バックスラッシュ n' をそのまま扱う
=> "\\n"

前述の#{文字と同様、Rubyでバックスラッシュそのものをエスケープする場合は、バックスラッシュがもう1つ必要です。ダブルクォート文字列の中では、バックスラッシュ文字そのものは2つのバックスラッシュによって表されます。このような些細な例の場合はそれほど問題になりませんが、次のようにエスケープの必要な文字が大量にある場合には、シングルクォートは非常に便利です。

>> 'Newlines (\n) and tabs (\t) both use the backslash character \.'
=> "Newlines (\\n) and tabs (\\t) both use the backslash character \\."

最後にもう一度申し上げます。ほとんどの場合、シングルクォートとダブルクォートのどちらを使おうと大きな違いはありません。実際、一般のソースコードでは、明確な理由もなく両者が混用されているケースをよく見かけます。 以上でRubyの文字列に関する説明は終わりです。あ、言い忘れていたことがありましたね。「Rubyの世界へようこそ!」

演習

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

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

Rubyでは、あらゆるものがオブジェクトです。文字列やnilですらオブジェクトです。このことの技術的な意味は4.4.2で説明しますが、オブジェクトに関する意味や定義は、本を読んだだけでは中々わかりません。様々なオブジェクトの例に触れることで、「オブジェクトとは何であるか」という直感を養う必要があります。

逆に、オブジェクトが何をするかを説明するのは簡単です。オブジェクトとは (いついかなる場合にも) メッセージに応答するものです。 文字列のようなオブジェクトは、たとえばlengthというメッセージに応答できますが、これは文字列の文字数を返します。

>> "foobar".length        # 文字列に "length" というメッセージを送る
=> 6

オブジェクトに渡されるメッセージは、一般にはメソッドと呼ばれます。メソッドの実体は、そのオブジェクト内で定義された関数です5。Rubyの文字列は、次のようにempty?メソッドにも応答することができます。

>> "foobar".empty?
=> false
>> "".empty?
=> true

empty?メソッドの末尾にある疑問符にご注目ください。 Rubyでは、メソッドがtrueまたはfalseという論理値 (boolean) を返すことを、末尾の疑問符で示す慣習があります。 論理値は、特に処理の流れを変更するときに有用です。

>> s = "foobar"
>> if s.empty?
>>   "The string is empty"
>> else
>>   "The string is nonempty"
>> end
=> "The string is nonempty"

条件文を2つ以上含めたい場合は、elsif (else + if) という文を使います。

>> if s.nil?
>>   "The variable is nil"
>> elsif s.empty?
>>   "The string is empty"
>> elsif s.include?("foo")
>>   "The string includes 'foo'"
>> end
=> "The string includes 'foo'"

なお、論理値はそれぞれ && (and) や || (or)、! (not) オペレーターで表すこともできます。

>> x = "foo"
=> "foo"
>> y = ""
=> ""
>> puts "Both strings are empty" if x.empty? && y.empty?
=> nil
>> puts "One of the strings is empty" if x.empty? || y.empty?
"One of the strings is empty"
=> nil
>> puts "x is not empty" if !x.empty?
"x is not empty"
=> nil

Rubyでは、あらゆるものがオブジェクトです。したがって、nilもオブジェクトであり、これも多くのメソッドに応答できます。 ほぼあらゆるオブジェクトを文字列に変換するto_sメソッドを使用して、nilがメソッドに応答する例をお目にかけましょう。

>> nil.to_s
=> ""

確かに空文字列が出力されました。今度はnilに対してメソッドをチェーン (chain) して渡せることを確認します。

>> nil.empty?
NoMethodError: undefined method `empty?' for nil:NilClass
>> nil.to_s.empty?      # メソッドチェーンの例
=> true

このように、nilオブジェクト自身はempty?メソッドには応答しないにもかかわらず、nil.to_sとすると応答することがわかります。

皆さんのご推察どおり、実はnilかどうかを調べるメソッドもあります。

>> "foo".nil?
=> false
>> "".nil?
=> false
>> nil.nil?
=> true

次のコードは、

puts "x is not empty" if !x.empty?

ifキーワードの別の使い方を示しています。Rubyではこのように、後続するifでの条件式が真のときにだけ実行される式 (後続if) を書くことができ、コードが非常に簡潔になります。 なお、unlessキーワードも同様に使用できます。

>> string = "foobar"
>> puts "The string '#{string}' is nonempty." unless string.empty?
The string 'foobar' is nonempty.
=> nil

Rubyにおいてnilは特別なオブジェクトです。Rubyのオブジェクトのうち、オブジェクトそのものの論理値がfalseになるのは、false自身とnilの2つしかありません。 なお、「!!」(「バンバン (bang bang)」と読みます) という演算子を使うと、そのオブジェクトを2回否定することになるので、どんなオブジェクトも強制的に論理値に変換できます。

>> !!nil
=> false

その他のあらゆるRubyのオブジェクトは、ゼロですらtrueです。

>> !!0
=> true

演習

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

4.2.4 メソッドの定義

Railsコンソールでも、リスト 3.8homeアクションや、リスト 4.2full_titleヘルパーと同じ方法でメソッドを定義することができます (メソッドの定義はファイルで行うのが普通なので、コンソールで行うのは少々面倒ですが、デモが目的であれば十分です)。例えば引数を1つ取り、引数が空かどうかに基づいたメッセージを返すstring_messageという関数を定義してみましょう。

>> 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.
>> puts string_message("")
It's an empty string!
>> puts string_message
It's an empty string!

最後の例を見ると分かるように、メソッドの引数を省略することも可能です (かっこですら省略可能です)。 これは、以下のコードでは

def string_message(str = '')

引数にデフォルト値を含めているからです (この例のデフォルト値は空の文字列です)。 このように指定すると、str変数に引数を渡すことも渡さないこともできます。引数を渡さない場合は、指定のデフォルト値が自動的に使用されます。

ここで、Rubyの関数には「暗黙の戻り値がある」ことにご注意ください。これは、関数内で最後に評価された式の値が自動的に返されることを意味します (訳注: 関数で戻り値を明示的に指定しなかった場合の動作です)。この場合、引数のstrが空かどうかに応じて、2つのメッセージ文字列のうちのいずれかを返します。 もちろん、Rubyでは戻り値を明示的に指定することもできます。以下の関数は上の関数と同じ結果を返します。

>> def string_message(str = '')
>>   return "It's an empty string!" if str.empty?
>>   return "The string is nonempty."
>> end

上の説明で気付いた方もいると思いますが、2番目のreturnは実はなくてもかまいません。関数中の最後に置かれた式 (この場合は "The string is nonempty.") は、returnキーワードがなくても暗黙で値を返すためです。ここでは、両方にreturnを使用する方が見た目の対称性が保たれるので好ましいと言えます。

メソッドで引数の変数名にどんな名前を使っても、メソッドの呼び出し側には何の影響も生じないという点にもご注目ください。 つまり、最初の例のstrを別の変数名 (the_function_argumentなど) に変更しても、メソッドの呼び出し方は全く同じです。

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

演習

  1. リスト 4.10FILL_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

4.2.5 titleヘルパー、再び

これでfull_titleヘルパー (リスト 4.2) のコードを理解するための準備が整いました6。コメントを使って、各行の振る舞いに注釈を加えてみました (リスト 4.11)。

リスト 4.11: 注釈付きのtitle_helper. app/helpers/application_helper.rb
module ApplicationHelper

  # ページごとの完全なタイトルを返します。                   # コメント行
  def full_title(page_title = '')                     # メソッド定義とオプション引数
    base_title = "Ruby on Rails Tutorial Sample App"  # 変数への代入
    if page_title.empty?                              # 論理値テスト
      base_title                                      # 暗黙の戻り値
    else 
      page_title + " | " + base_title                 # 文字列の結合
    end
  end
end

Webサイトのレイアウトで使用するコンパクトなヘルパーメソッドでは、関数定義、変数割り当て、論理評価、制御フロー、文字列の式展開7など、Rubyの様々な要素が投入されています。最後に、module ApplicationHelperという要素について解説します。モジュールは、関連したメソッドをまとめる方法のひとつで、Rubyのクラスでincludeを使用すると、このモジュールをミックスイン (mixed in)できます。 単なるRubyのコードを書くのであれば、モジュールを作成するたびに明示的にインクルードして使用するのが普通ですが、Railsでは自動的にヘルパーモジュールをインクルードしてくれるので、include行をわざわざ書く必要がありません。 つまり、このfull_titleメソッドは自動的にすべてのビューで利用できるようになっている、ということです。

4.3 他のデータ構造

Webアプリケーションは突き詰めればただの文字列に過ぎませんが、実際にはこれらの文字列を作るために文字列以外のデータ構造も必要となります。 この節では、Railsアプリケーションを書くために重要となる、いくつかのRubyのデータ構造について説明します。

4.3.1 配列と範囲演算子

配列 (array) は、特定の順序を持つ要素のリストです。 Railsチュートリアルではこれまで配列について解説していませんでしたが、配列を理解することは、ハッシュ (4.3.3) やRailsのデータモデルを理解するための重要な基盤となります (データモデルとはhas_manyなどの関連付けのことであり、2.3.313.1.3で詳しく説明します)。

Rubyの文字列の理解にだいぶ時間を使ってしまいましたので、次に進むことにします。splitメソッドを使用すると、文字列を自然に変換した配列を得ることができます。

>>  "foo bar     baz".split     # 文字列を3つの要素を持つ配列に分割する
=> ["foo", "bar", "baz"]

この操作によって、3つの文字列からなる配列が得られます。 splitで文字列を区切って配列にするときにはデフォルトで空白が使用されますが、以下のように他の文字を指定して区切ることもできます。

>> "fooxbarxbazx".split('x')
=> ["foo", "bar", "baz"]

多くのコンピュータ言語の慣習と同様、Rubyの配列でもゼロオリジンを採用しています。これは、配列の最初の要素のインデックスが0から始まり、2番目は1...と続くことを意味します。

>> a = [42, 8, 17]
=> [42, 8, 17]
>> a[0]               # Rubyでは角かっこで配列にアクセスする
=> 42
>> a[1]
=> 8
>> a[2]
=> 17
>> a[-1]              # 配列の添字はマイナスにもなれる!
=> 17

上で示したとおり、配列の要素にアクセスするには角かっこを使用します。 Rubyでは、角かっこ以外にも配列の要素にアクセスする方法が提供されています8

>> a                  # 配列「a」の内容を確認する
=> [42, 8, 17]
>> a.first
=> 42
>> a.second
=> 8
>> a.last
=> 17
>> a.last == a[-1]    # == を使って比較する
=> true

最後の行では、等しいことを確認する比較演算子==を使ってみました。この演算子や != (“等しくない”) などの演算子は、他の多くの言語と共通です。

>> x = a.length       # 配列も文字列と同様lengthメソッドに応答する
=> 3
>> x == 3
=> true
>> x == 1
=> false
>> x != 1
=> true
>> x >= 1
=> true
>> x < 1
=> false

配列は、上記コードの最初の行のlengthメソッド以外にも、さまざまなメソッドに応答します。

>> a
=> [42, 8, 17]
>> a.empty?
=> false
>> a.include?(42)
=> true
>> a.sort
=> [8, 17, 42]
>> a.reverse
=> [17, 8, 42]
>> a.shuffle
=> [17, 42, 8]
>> a
=> [42, 8, 17]

上のどのメソッドを実行した場合にも、a自身は変更されていないという点にご注目ください。 配列の内容を変更したい場合は、そのメソッドに対応する「破壊的」メソッドを使用します。破壊的メソッドの名前には、元のメソッドの末尾に「!」を追加したものを使用するのがRubyの慣習です。

>> a
=> [42, 8, 17]
>> a.sort!
=> [8, 17, 42]
>> a
=> [8, 17, 42]

また、pushメソッド (または同等の<<演算子) を使用して配列に要素を追加することもできます。

>> a.push(6)                  # 6を配列に追加する
=> [42, 8, 17, 6]
>> a << 7                     # 7を配列に追加する
=> [42, 8, 17, 6, 7]
>> a << "foo" << "bar"        # 配列に連続して追加する
=> [42, 8, 17, 6, 7, "foo", "bar"]

最後の例では、要素の追加をチェーン (chain) できることを示しました。他の多くの言語の配列と異なり、Rubyでは異なる型が配列の中で共存できます (上の場合は整数と文字列)。

上では、文字列を配列に変換するのにsplitを使用しました。 joinメソッドはこれと逆の動作です。

>> a
=> [42, 8, 17, 6, 7, "foo", "bar"]
>> a.join                       # 単純に連結する
=> "4281767foobar"
>> a.join(', ')                 # カンマ+スペースを使って連結する
=> "42, 8, 17, 6, 7, foo, bar"

範囲 (range) は、配列と密接に関係しています。to_aメソッドを使用して配列に変換すると理解しやすいと思います。

>> 0..9
=> 0..9
>> 0..9.to_a              # おっと、9に対してto_aを呼んでしまっていますね
NoMethodError: undefined method `to_a' for 9:Fixnum
>> (0..9).to_a            # 丸かっこを使い、範囲オブジェクトに対してto_aを呼びましょう
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

0..9 は範囲として有効ですが、上の2番目の表記ではメソッドを呼ぶ際にかっこを追加する必要があることを示しています。

範囲は、配列の要素を取り出すのに便利です。

>> a = %w[foo bar baz quux]         # %wを使って文字列の配列に変換
=> ["foo", "bar", "baz", "quux"]
>> a[0..2]
=> ["foo", "bar", "baz"]

インデックスに-1という値を指定できるのは極めて便利です。-1を使用すると、配列の長さを知らなくても配列の最後の要素を指定することができ、これにより配列を特定の開始位置の要素から最後の要素までを一度に選択することができます。

>> a = (0..9).to_a
=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>> a[2..(a.length-1)]               # 明示的に配列の長さを使って選択
=> [2, 3, 4, 5, 6, 7, 8, 9]
>> a[2..-1]                         # 添字に-1を使って選択
=> [2, 3, 4, 5, 6, 7, 8, 9]

次のように、文字に対しても範囲を使用できます。

>> ('a'..'e').to_a
=> ["a", "b", "c", "d", "e"]

演習

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

4.3.2 ブロック

配列と範囲はいずれも、ブロックを伴うさまざまなメソッドに対して応答することができます。ブロックは、Rubyの極めて強力な機能であり、かつわかりにくい機能でもあります。

>> (1..5).each { |i| puts 2 * i }
2
4
6
8
10
=> 1..5

上のコードでは、範囲オブジェクトである(1..5)に対してeachメソッドを呼び出しています。メソッドに渡されている{ |i| puts 2 * i }が、ブロックと呼ばれる部分です。|i|では変数名が縦棒「|」に囲まれていますが、これはブロック変数に対して使用するRubyの構文で、ブロックを操作するときに使用する変数を指定します。 この場合、範囲オブジェクトのeachメソッドは、iという1つのローカル変数を使用してブロックを操作できます。そして、範囲に含まれるそれぞれの値をこの変数に次々に代入してブロックを実行します。

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

>> (1..5).each do |i|
?>   puts 2 * i
>> end
2
4
6
8
10
=> 1..5

ブロックには複数の行を記述できます (実際ほとんどのブロックは複数行です)。 RailsチュートリアルではRuby共通の慣習に従って、短い1行のブロックには波かっこを使用し、長い1行や複数行のブロックにはdo..end記法を使用しています。

>> (1..5).each do |number|
?>   puts 2 * number
>>   puts '--'
>> end
2
--
4
--
6
--
8
--
10
--
=> 1..5

今度はiの代わりにnumberを使用していることにご注目ください。この変数 (ブロック変数) の名前は固定されていません。

ブロックは見た目に反して奥が深く、ブロックを十分に理解するためには相当なプログラミング経験が必要です。そのためには、ブロックを含むコードをたくさん読みこなすことでブロックの本質を会得する以外に方法はありません9。幸いなことに、人間には個別の事例を一般化する能力というものがあります。ささやかですが、mapメソッドなどを使用したブロックの使用例を参考のためにいくつか挙げてみます。

>> 3.times { puts "Betelgeuse!" }   # 3.timesではブロックに変数を使用していない
"Betelgeuse!"
"Betelgeuse!"
"Betelgeuse!"
=> 3
>> (1..5).map { |i| i**2 }          # 「**」記法は冪乗 (べき乗) 
=> [1, 4, 9, 16, 25]
>> %w[a b c]                        # %w で文字列の配列を作成
=> ["a", "b", "c"]
>> %w[a b c].map { |char| char.upcase }
=> ["A", "B", "C"]
>> %w[A B C].map { |char| char.downcase }
=> ["a", "b", "c"]

上に示したように、mapメソッドは、渡されたブロックを配列や範囲オブジェクトの各要素に対して適用し、その結果を返します。また、後半の2つの例では、mapのブロック内で宣言した引数 (char) に対してメソッドを呼び出しています。こういったケースでは省略記法が一般的で、次のように書くこともできます (この記法を“symbol-to-proc”と呼びます)。

>> %w[A B C].map { |char| char.downcase }
=> ["a", "b", "c"]
>> %w[A B C].map(&:downcase)
=> ["a", "b", "c"]

(メソッド名にシンボルが使われているので奇妙に見えるかもしれません。これについては4.3.3で説明します)。 ひとつ面白い話があります。これは実は元々Ruby on Rails独自の記法でした。しかし多くの人がこの記法を好むようになったので、今ではRubyのコア機能として導入されています。

最後のブロックの例として、単体テストにも目を向けてみましょう (リスト 4.4)。

test "should get home" do
  get static_pages_home_url
  assert_response :success
  assert_select "title", "Ruby on Rails Tutorial Sample App"
end

ここでは動作をすみずみまで理解する必要はありません (実際、筆者もこのコードをひと目で完璧に把握できるなどとは言いません)。ここで重要なのは、テストコードにdoというキーワードがあることに気付き、そこからテストの本体が「そもそもブロックでできている」ことに気付くことです。 すなわち、このtestメソッドは文字列 (説明文) とブロックを引数にとり、テストが実行されるときにブロック内の文が実行される、ということが理解できます。

ところで、1.5.4でランダムなサブドメインを生成するために以下のRubyコードを紹介しましたが、このコードを理解するための準備が整ったので、今こそ読み解いてみましょう。

('a'..'z').to_a.shuffle[0..7].join

順を追ってこのコードを組み立ててみると、動作がよくわかります。

>> ('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'..'z').to_a.shuffle             # シャッフルする
=> ["c", "g", "l", "k", "h", "z", "s", "i", "n", "d", "y", "u", "t", "j", "q",
"b", "r", "o", "f", "e", "w", "v", "m", "a", "x", "p"]
>> ('a'..'z').to_a.shuffle[0..7]       # 配列の冒頭8つの要素を取り出す
=> ["f", "w", "i", "a", "h", "p", "c", "x"]
>> ('a'..'z').to_a.shuffle[0..7].join  # 取り出した要素を結合してひとつの文字列にする
=> "mznpybuj"

演習

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

4.3.3 ハッシュとシンボル

ハッシュは、本質的には配列と同じですが、インデックスとして整数値以外のものも使用できる点が配列と異なります (この理由から、いくつかの言語 (特にPerl) ではハッシュを連想配列と呼ぶこともあります)。 ハッシュのインデックス (キーと呼ぶのが普通です) は、通常何らかのオブジェクトです。例えば、次のように文字列をキーとして使用できます。

>> user = {}                          # {}は空のハッシュ
=> {}
>> user["first_name"] = "Michael"     # キーが "first_name" で値が "Michael"
=> "Michael"
>> user["last_name"] = "Hartl"        # キーが "last_name" で値が "Hartl"
=> "Hartl"
>> user["first_name"]                 # 要素へのアクセスは配列の場合と似ている
=> "Michael"
>> user                               # ハッシュのリテラル表記
=> {"last_name"=>"Hartl", "first_name"=>"Michael"}

ハッシュは、キーと値のペアを波かっこで囲んで表記します。キーと値のペアを持たない波かっこの組 ({}) は空のハッシュです。ここで重要なのは、ハッシュの波かっこは、ブロックの波かっことはまったく別物であるという点です (これは確かに紛らわしい点です) 。 ハッシュは配列と似ていますが、1つの重要な違いとして、ハッシュでは要素の「並び順」が保証されないという点があります10。もし要素の順序が重要である場合は、配列を使用する必要があります。

ハッシュの1要素を角かっこを使って定義する代わりに、以下のようにキーと値をハッシュロケットと呼ばれる=> によってリテラル表現するほうが簡単です。

>> user = { "first_name" => "Michael", "last_name" => "Hartl" }
=> {"last_name"=>"Hartl", "first_name"=>"Michael"}

ここではRubyにおける慣習として、ハッシュの最初と最後に空白を追加しています。この空白はあってもなくてもよく、コンソールでは無視されます (なぜスペースを置くようになったのかはわかりません。おそらく初期の有力な Rubyプログラマが好んだ結果、慣習となったのでしょう)。

ここまではハッシュのキーとして文字列を使用していましたが、Railsでは文字列よりもシンボルを使用する方が普通です。 シンボルは文字列と似ていますが、クォートで囲む代わりにコロンが前に置かれている点が異なります。 たとえば、:nameはシンボルです。 もちろん、余計なことを一切考えずに、シンボルを単なる文字列とみなしても構いません11

>> "name".split('')
=> ["n", "a", "m", "e"]
>> :name.split('')
NoMethodError: undefined method `split' for :name:Symbol
>> "foobar".reverse
=> "raboof"
>> :foobar.reverse
NoMethodError: undefined method `reverse' for :foobar:Symbol

シンボルは、Ruby以外ではごく一部の言語にしか採用されていない特殊なデータ形式です。最初は奇妙に思うかもしれませんが、Railsではシンボルをふんだんに使用しているので、すぐに慣れるでしょう。 ただし文字列と違って、全ての文字が使えるわけではないことに注意してください

>> :foo-bar
NameError: undefined local variable or method `bar' for main:Object
>> :2foo
SyntaxError

とはいえ、一般的なアルファベットなどを使っている限りにおいては、シンボルで困ることはないでしょう。

ハッシュのキーとしてシンボルを採用する場合、user のハッシュは以下のように定義できます。

>> user = { :name => "Michael Hartl", :email => "michael@example.com" }
=> {:name=>"Michael Hartl", :email=>"michael@example.com"}
>> user[:name]              # :name に対応する値にアクセスする
=> "Michael Hartl"
>> user[:password]          # 未定義のキーに対応する値にアクセスする
=> nil

最後の例を見ると、未定義のハッシュ値は単純にnilであることがわかります。

ハッシュではシンボルをキーとして使うことが一般的なので、Ruby 1.9からこのような特殊な場合のための新しい記法がサポートされました。

>> h1 = { :name => "Michael Hartl", :email => "michael@example.com" }
=> {:name=>"Michael Hartl", :email=>"michael@example.com"}
>> h2 = { name: "Michael Hartl", email: "michael@example.com" }
=> {:name=>"Michael Hartl", :email=>"michael@example.com"}
>> h1 == h2
=> true

2つ目の記法は、シンボルとハッシュロケットの組み合わせを、以下のようにキーの名前の (前ではなく) 後にコロンを置き、その後に値が続くように置き換えたものです。

{ name: "Michael Hartl", email: "michael@example.com" }

この構成は、JavaScriptなど他の言語のハッシュ記法により近いものになっており、Railsコミュニティでも人気が高まっています。 どちらの記法もよく使われているので、両方の見分けがつくことが重要です。 ただ最初は少し見分けづらいのも事実です。たとえば:nameはシンボルとして独立していますが、引数を伴わないname:では意味が成り立ちません。 以下のコードの:name =>name:は、ハッシュとしてのデータ構造は全く同じです。つまり、

{ :name => "Michael Hartl" }

上のコードと、

{ name: "Michael Hartl" }

というコードは等価になります (一般的には省略記法が好まれますが、明示的に接頭にコロンをつけてシンボル (:name) であることを強調するという考え方もあります)。

リスト 4.13に示したように、ハッシュの値にはほぼ何でも使用することができ、他のハッシュを使用することすらできます。

リスト 4.13: ハッシュの中のハッシュ
>> params = {}        # 'params' というハッシュを定義する ('parameters' の略)。
=> {}
>> params[:user] = { name: "Michael Hartl", email: "mhartl@example.com" }
=> {:name=>"Michael Hartl", :email=>"mhartl@example.com"}
>> params
=> {:user=>{:name=>"Michael Hartl", :email=>"mhartl@example.com"}}
>>  params[:user][:email]
=> "mhartl@example.com"

Railsでは、このようなハッシュのハッシュ (またはネストされたハッシュ) が大量に使われています。実際の使用例は7.3で説明します。

配列や範囲オブジェクトと同様、ハッシュもeachメソッドに応答します。 たとえば、:success:dangerという 2つの状態を持つ flash という名前のハッシュについて考えてみましょう。

>> flash = { success: "It worked!", danger: "It failed." }
=> {:success=>"It worked!", :danger=>"It failed."}
>> flash.each do |key, value|
?>   puts "Key #{key.inspect} has value #{value.inspect}"
>> end
Key :success has value "It worked!"
Key :danger has value "It failed."

ここで、配列のeachメソッドでは、ブロックの変数は1つだけですが、ハッシュのeachメソッドでは、ブロックの変数はキーの2つになっていることに注意してください。 従って、 ハッシュに対してeachメソッドを実行すると、ハッシュの1つの「キーと値のペア」ごとに処理を繰り返します。

最後の例として、便利なinspectメソッドを紹介します。これは要求されたオブジェクトを表現する文字列を返します。

>> puts (1..5).to_a            # 配列を文字列として出力
1
2
3
4
5
>> puts (1..5).to_a.inspect    # 配列のリテラルを出力
[1, 2, 3, 4, 5]
>> puts :name, :name.inspect
name
:name
>> puts "It worked!", "It worked!".inspect
It worked!
"It worked!"

ところで、オブジェクトを表示するためにinspectを使用することは非常によくあることなので、 p関数というショートカットがあります12

>> p :name             # 'puts :name.inspect' と同じ
:name

演習

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

4.3.4 CSS、再び

それでは、もう一度リスト 4.1に戻り、レイアウトに CSS (cascading style sheet) を追加する以下の行を見てみましょう。

<%= stylesheet_link_tag 'application', media: 'all',
                                       'data-turbolinks-track': 'reload' %>

今なら、このコードを理解できるようになったはずです。4.1でも簡単に説明した通り、Railsではスタイルシートを追加するための特別なメソッドを使用しています。

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

上のコードでは、この関数を呼んでいます。 しかし、ここで不思議な点がいくつもあります。 第一に、丸かっこがありません。 実は、Ruby では丸かっこは使用してもしなくても構いません。以下の2つの行は同等です。

# メソッド呼び出しの丸かっこは省略可能。
stylesheet_link_tag('application', media: 'all',
                                   'data-turbolinks-track': 'reload')
stylesheet_link_tag 'application', media: 'all',
                                   'data-turbolinks-track': 'reload'

次に、media引数はハッシュのようですが、波かっこがない点が不思議です。 実は、ハッシュが関数呼び出しの最後の引数である場合は、波かっこを省略できます。以下の2つの行は同等です。

# 最後の引数がハッシュの場合、波かっこは省略可能。
stylesheet_link_tag 'application', { media: 'all',
                                     'data-turbolinks-track': 'reload' }
stylesheet_link_tag 'application', media: 'all',
                                   'data-turbolinks-track': 'reload'

最後に、Rubyが以下のようなコードを正常に実行できているのが不思議です。

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

上のコードには途中に改行が含まれているにもかかわらずです。実は、Rubyは改行と空白を区別していません13。行を分割した理由は、1行を80字以内に収めてソースコードを読みやすくするためです14

したがって、

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

上のコードではstylesheet_link_tagメソッドを2つの引数で呼んでいます。最初の引数である文字列は、スタイルシートへのパスを示しています。次の引数であるハッシュには2つの要素があり、最初の要素はメディアタイプを示し、次の要素はRails 4.0で追加されたturbolinksという機能をオンにしています。この結果、<%= %> で囲まれているコードを実行した結果がERbのテンプレートに挿入されるようになります。ブラウザ上でこのページのソースを表示すると、必要なスタイルシートが含まれていることを確認できます (リスト 4.14)。(CSSファイル名の後に、?body=1のような行が余分に表示されていることがあります。 これらはRailsによって挿入されているもので、サーバー上で変更があった場合にブラウザがCSSを再読み込みするのに使用します。)

リスト 4.14: インクルードされたCSSによって生成されたHTMLソース。
<link data-turbolinks-track="true" href="/assets/application.css" media="all"
rel="stylesheet" />

4.4 Rubyにおけるクラス

Rubyではあらゆるものがオブジェクトであるということは既に説明しましたが、この節では実際にオブジェクトをいくつか定義してみましょう。 Rubyは、多くのオブジェクト指向言語と同様、メソッドをまとめるのにクラスを使用しています。これらのクラスからインスタンスが生成されることでオブジェクトが作成されます。 オブジェクト指向プログラミングの経験がない方にとっては何のことだかわからないと思いますので、いくつかの具体例を示すことにします。

4.4.1 コンストラクタ

実は、これまで示した多くの例の中でも、クラスを使用してオブジェクトのインスタンスを作成してきたのですが、オブジェクトを作成するところを明示的に説明していませんでした。 たとえば、ダブルクォートを使って文字列のインスタンスを作成しましたが、これは文字列のオブジェクトを暗黙で作成するリテラルコンストラクタです。

>> s = "foobar"       # ダブルクォートは実は文字列のコンストラクタ
=> "foobar"
>> s.class
=> String

上のコードでは、文字列がclassメソッドに応答しており、その文字列が所属するクラスを単に返していることがわかります。

暗黙のリテラルコンストラクタを使う代わりに、明示的に同等の名前付きコンストラクタを使うことができます。名前付きコンストラクタは、クラス名に対してnewメソッドを呼び出します15

>> s = String.new("foobar")   # 文字列の名前付きコンストラクタ
=> "foobar"
>> s.class
=> String
>> s == "foobar"
=> true

この動作はリテラルコンストラクタと同等ですが、動作の内容が明確に示されています。

配列でも、文字列と同様にインスタンスを生成できます。

>> a = Array.new([1, 3, 2])
=> [1, 3, 2]

ただし、ハッシュの場合は若干異なります。 配列のコンストラクタであるArray.new は配列の初期値を引数に取りますが、 Hash.new はハッシュのデフォルト 値を引数に取ります。これは、キーが存在しない場合のデフォルト値です。

>> h = Hash.new
=> {}
>> h[:foo]            # 存在しないキー (:foo) の値にアクセスしてみる
=> nil
>> h = Hash.new(0)    # 存在しないキーのデフォルト値をnilから0にする
=> {}
>> h[:foo]
=> 0

メソッドがクラス自身 (この場合はnew) に対して呼び出されるとき、このメソッドをクラスメソッドと呼びます。 クラスのnewメソッドを呼び出した結果は、そのクラスのオブジェクトであり、これはクラスのインスタンスとも呼ばれます。 lengthのように、インスタンスに対して呼び出すメソッドはインスタンスメソッドと呼ばれます。

演習

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

4.4.2 クラス継承

クラスについて学ぶとき、superclassメソッドを使ってクラス階層を調べてみるとよくわかります。

>> s = String.new("foobar")
=> "foobar"
>> s.class                        # 変数sのクラスを調べる
=> String
>> s.class.superclass             # Stringクラスの親クラスを調べる
=> Object
>> s.class.superclass.superclass  # Ruby 1.9からBasicObjectという新しい基底クラスが導入
=> BasicObject
>> s.class.superclass.superclass.superclass
=> nil

継承階層を図 4.1に示します。 ここでは、StringクラスのスーパークラスはObjectクラスで、ObjectクラスのスーパークラスはBasicObjectクラスですが、 BasicObjectクラスはスーパークラスを持たないことがわかります。 この図式は、すべての Ruby のオブジェクトにおいて成り立ちます。クラス階層をたどっていくと、 Rubyにおけるすべてのクラスは最終的にスーパークラスを持たないBasicObjectクラスを継承しています。 これが、"Rubyではあらゆるものがオブジェクトである" ということの技術的な意味です。

string_inheritance_ruby_1_9
図 4.1: Stringクラスの継承階層

クラスについての理解を深めるには、自分でクラスを作成してみるのが一番です。 そこで、Wordクラスを作成し、その中に、ある単語を前からと後ろからのどちらから読んでも同じ (つまり回文になっている) ならばtrueを返すpalindrome?メソッドを作成してみましょう。

>> class Word
>>   def palindrome?(string)
>>     string == string.reverse
>>   end
>> end
=> :palindrome?

このクラスとメソッドは以下のように使うことができます。

>> w = Word.new              # Wordオブジェクトを作成する
=> #<Word:0x22d0b20>
>> w.palindrome?("foobar")
=> false
>> w.palindrome?("level")
=> true

もし上の例が少し不自然に思えるならば、勘が鋭いといえます。というのも、これはわざと不自然に書いたからです。 文字列を引数に取るメソッドを作るためだけに、わざわざ新しいクラスを作るのは変です。 単語文字列なので、リスト 4.15のようにWordクラスは Stringクラスを継承するのが自然です (以下のリストを入力する前に、古いWordクラスの定義を消去するために、Railsコンソールをいったん終了してください)。

リスト 4.15: コンソールでWordクラスを定義する。
>> class Word < String             # WordクラスはStringクラスを継承する
>>   # 文字列が回文であればtrueを返す
>>   def palindrome?
>>     self == self.reverse        # selfは文字列自身を表します
>>   end
>> end
=> nil

3.2でも簡単に説明しましたが、上のコードは継承のためのRubyの Word < String 記法です。こうすることで、新しいpalindrome?メソッドだけではなく、Stringクラスで使用できるすべてのメソッドをWordクラスに対しても使用できるようになります。

>> s = Word.new("level")    # 新しいWordを作成し、"level" で初期化する
=> "level"
>> s.palindrome?            # Wordが回文かどうかを調べるメソッド
=> true
>> s.length                 # WordはStringで扱える全てのメソッドを継承している
=> 5

WordクラスはStringクラスを継承しているので、コンソールを使用してクラス階層を明示的に確認できます。

>> s.class
=> Word
>> s.class.superclass
=> String
>> s.class.superclass.superclass
=> Object

図 4.2にこのクラス階層を示します。

word_inheritance_ruby_1_9
図 4.2: リスト 4.15の (組み込みではない) Wordクラスの継承階層

リスト 4.15では、単語の文字を逆順にしたものが元の単語と同じであるかどうかのチェックを、Wordクラスの中から自分自身が持つ単語にアクセスすることで行なっていることにご注目ください。 Rubyでは、selfキーワードを使用してこれを指定することができます。Wordクラスの中では、selfはオブジェクト自身を指します。これはつまり、以下のコードを使用して、

self == self.reverse

単語が回文であるかどうかを確認できるということです16。なお、Stringクラスの内部では、メソッドや属性を呼び出すときのself.も省略可能です。

self == reverse

といった省略記法でも、うまく動きます。

演習

  1. Rangeクラスの継承階層を調べてみてください。同様にして、HashとSymbolクラスの継承階層も調べてみてください。
  2. リスト 4.15にあるself.reverseselfを省略し、reverseと書いてもうまく動くことを確認してみてください。

4.4.3 組み込みクラスの変更

継承は強力な概念ですが、もし仮に継承を使用せずにpalindrome?メソッドをStringクラス自身に追加する (つまりStringクラスを拡張する) という、より自然な方法を使用することが可能だとしたら、わざわざWordクラスを作らなくてもpalindrome?をリテラル文字列に対して直接実行できるようになるはずです。そんなことが可能なのでしょうか (なお、現在のコードはそのようになっていないため、以下のようにエラーになります)。

>> "level".palindrome?
NoMethodError: undefined method `palindrome?'  for "level":String

驚いたことに、Rubyでは組み込みの基本クラスの拡張が可能なのです。Ruby のクラスはオープンで変更可能であり、クラス設計者でない開発者でもこれらのクラスにメソッドを自由に追加することが許されています。

>> class String
>>   # 文字列が回文であればtrueを返す
>>   def palindrome?
>>     self == self.reverse
>>   end
>> end
=> nil
>> "deified".palindrome?
=> true

(Rubyで組み込みクラスにメソッドを追加できるということは実にクールですが、"deified" (=神格化された) という単語が回文になっていることも、それに劣らずクールではないでしょうか。)

組み込みクラスの変更はきわめて強力なテクニックですが、大いなる力には大いなる責任が伴います (訳注: 「スパイダーマン」の名台詞)。このため、真に正当な理由がない限り、組み込みクラスにメソッドを追加することは無作法であると考えられています。Railsの場合、組み込みクラスの変更を正当化できる理由がいくつもあります。たとえば、Web アプリケーションでは、変数が絶対に空白にならないようにしたくなることがよくあります (ユーザー名などはスペースやその他の空白文字になって欲しくないものです) ので、Railsはblank?メソッドをRuby に追加しています。 Railsの拡張は自動的にRailsコンソールにも取り込まれるので、以下のようにコンソールで拡張の結果を確認できます (注意: 次のコードは純粋な irb では動作しません)。

>> "".blank?
=> true
>> "      ".empty?
=> false
>> "      ".blank?
=> true
>> nil.blank?
=> true

スペースが集まってできた文字列は空 (empty) とは認識されませんが、空白 (blank) であると認識されていることがわかります。 ここで、nilは空白と認識されることに注意してください。nilは文字列ではないので、Railsが実はblank?メソッドをStringクラスではなく、そのさらに上の基底クラスに追加していることが推測できます。その基底クラスとは、(この章の最初で説明した) Object自身です。 RailsによってRubyの組み込みクラスに追加が行われている例については、9.1で説明します。

演習

  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"

4.4.4 コントローラクラス

これまでクラスや継承について説明してきましたが、これらの話は前の章にもあったような気がします。それもそのはずで、StaticPagesコントローラで継承やクラスについて触れたことがありました (リスト 3.20)。

class StaticPagesController < ApplicationController

  def home
  end

  def help
  end

  def about
  end
end

ここまでの説明を経て、ついに、Railsのコードが説明できるようになります。例えばStaticPagesControllerApplicationControllerを継承していて、homehelpaboutメソッドを定義している部分などについてです。 Railsコンソールは、セッションごとにローカルのRails環境を読み込むので、コンソール内で明示的にコントローラを作成したり、そのクラス階層を調べたりすることができます。早速、Railsのコードを調べてみましょう17

>> controller = StaticPagesController.new
=> #<StaticPagesController:0x22855d0>
>> controller.class
=> StaticPagesController
>> controller.class.superclass
=> ApplicationController
>> controller.class.superclass.superclass
=> ActionController::Base
>> controller.class.superclass.superclass.superclass
=> ActionController::Metal
>> controller.class.superclass.superclass.superclass.superclass
=> AbstractController::Base
>> controller.class.superclass.superclass.superclass.superclass.superclass
=> Object

継承の関係を図 4.3に示します。

static_pages_controller_inheritance
図 4.3: StaticPagesコントローラの継承階層

Railsコンソールでは、その中からコントローラのアクション (実はメソッド) を呼ぶこともできます。

>> controller.home
=> nil

ここでは、homeアクションの中身は空なのでnilが返されます。

ここで重要な点があります。Railsのアクションには戻り値がありません。少なくとも、返される値は重要ではありません。 3で示したとおり、home アクションはWebページを表示するためのものであり、値を返すためのものではありませんでした。 しかも、第3章では一度もStaticPagesController.newを実行しませんでした。 どうしてこれでうまくいっているのでしょうか。

実は、Railsは確かにRubyで書かれていますが、既にRubyとは別物なのです。 Railsのクラスは、普通のRubyオブジェクトと同様に振る舞うものもありますが、多くのクラスにはRailsの魔法の粉が振りかけられています。Railsは独特であり、Rubyとは切り離して学習する必要があります。

演習

  1. 2で作ったToyアプリケーションのディレクトリでRailsコンソールを開き、User.newと実行することでuserオブジェクトが生成できることを確認してみましょう。
  2. 生成したuserオブジェクトのクラスの継承階層を調べてみてください。

4.4.5 ユーザークラス

最後に完全なクラスを作成して、この章を終わりにしましょう。そこで、6で使用する User クラスを最初から作成することにします。

これまではコンソール上でクラスを定義しましたが、このような面倒な作業はもう行いたくありません。これからは、アプリケーションのルートディレクトリにexample_user.rbファイルを作成し、そこにリスト 4.17のように書くことにします。

リスト 4.17: example_userで使用するコード example_user.rb
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

ユーザー名とメールアドレス (属性: attribute) に対応するアクセサー (accessor) をそれぞれ作成します。 アクセサーを作成すると、そのデータを取り出すメソッド (getter) と、データに代入するメソッド (setter) をそれぞれ定義してくれます。具体的には、この行を実行したことにより、インスタンス変数@nameとインスタンス変数@emailにアクセスするためのメソッドが用意されます。2.2.2でも軽く触れましたが、Railsでは、インスタンス変数をコントローラ内で宣言するだけでビューで使えるようになる、といった点に主な利用価値があります。ただ一般的には、そのクラス内であればどこからでもアクセスできる変数として使われます (これについては後で詳しく説明します)。そしてインスタンス変数は常に@記号で始まり、まだ定義されていなければ値がnilになります。

次の行にあるinitializeは、Rubyの特殊なメソッドです。これは User.newを実行すると自動的に呼び出されるメソッドです。この場合のinitializeメソッドは、次のようにattributesという引数を1つ取ります。

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

上のコードで、attributes変数は空のハッシュをデフォルトの値として持つため、名前やメールアドレスのないユーザーを作ることができます (4.3.3を思い出してください。存在しないキーに対してハッシュはnilを返すので、:nameキーがなければattributes[:name]nilになり、同じことがattributes[:email]にも言えます)。

最後に、formatted_emailメソッドを定義しましょう (4.2.2)。このメソッドは、文字列の式展開を利用して、@name@emailに割り当てられた値をユーザーのメールアドレスとして構成します。

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

@ 記号によって示されているとおり、@name@emailは両方ともインスタンス変数なので、自動的にformatted_emailメソッドで使えるようになります。

Railsコンソールを起動し、example_userのコードをrequireして、自作したクラスを試しに使ってみましょう。

>> require './example_user'     # example_userのコードを読み込む方法
=> true
>> example = User.new
=> #<User:0x224ceec @email=nil, @name=nil>
>> example.name                 # attributes[:name]は存在しないのでnil
=> nil
>> example.name = "Example User"           # 名前を代入する
=> "Example User"
>> example.email = "user@example.com"      # メールアドレスを代入する
=> "user@example.com"
>> example.formatted_email
=> "Example User <user@example.com>"

上のコードで、requireのパスにある’.’は、Unixの “カレントディレクトリ” (現在のディレクトリ) を表し、’./example_user’というパスは、カレントディレクトリからの相対パスでexample_userファイルを探すようにRubyに指示します。 次のコードでは空のexample_userを作成します。次に、対応する属性にそれぞれ手動で値を代入することで、名前とメールアドレスを与えます (リスト 4.17attr_accessorを使用しているので、アトリビュートアクセサを使用して代入できます)。 以下のコードは、

example.name = "Example User"

@name変数に"Example User"という値を設定します。同様にemail属性にも値を設定します。これらの値はformatted_emailメソッドで使用されます。

4.3.4では、最後のハッシュ引数の波かっこを省略できることを説明しました。それと同じ要領でinitializeメソッドにハッシュを渡すことで、属性が定義済みの他のユーザを作成することができます。

>> user = User.new(name: "Michael Hartl", email: "mhartl@example.com")
=> #<User:0x225167c @email="mhartl@example.com",
@name="Michael Hartl">
>> user.formatted_email
=> "Michael Hartl <mhartl@example.com>"

これは一般にマスアサインメント (mass assignment) と呼ばれる技法で、Railsアプリケーションでよく使われます。例えば7は、実際にハッシュ引数を使ってオブジェクトを初期化するコードがあります。

演習

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

4.5 最後に

以上で、Ruby言語の概要の説明を終わります。 5では、この章で学んだ内容をサンプルアプリケーションの開発に活かしていきます。

4.4.5で作成したexample_user.rbファイルは今後使用することはありませんので、削除してください。

$ rm example_user.rb

次に、その他の変更はリポジトリにコミットして、masterブランチにマージしましょう。

$ git commit -am "Add a full_title helper"
$ git checkout master
$ git merge rails-flavored-ruby

慣習的なチェックとして、リモートリポジトリにpushしたりHerokuにデプロイする前に、テストスイートを流して既存の振る舞いに影響がないかを (念のため) 確認しておきます。

$ rails test

その後、Bitbucketにプッシュし、

$ git push

最後に、Herokuにデプロイして本章は終了です。

$ git push heroku

4.5.1 本章のまとめ

  • Rubyは文字列を扱うためのメソッドを多数持っている
  • Rubyの世界では、すべてがオブジェクトである
  • Rubyではdefというキーワードを使ってメソッドを定義する
  • Rubyではclassというキーワードを使ってクラスを定義する
  • Railsのビューでは、静的HTMLの他にERB (埋め込みRuby: Embedded RuBy) も使用できる。
  • Rubyの組み込みクラスには配列、範囲、ハッシュなどがある
  • Rubyのブロックは (他の似た機能と比べ) 柔軟な機能で、添え字を使ったデータ構造よりも自然にイテレーションができる
  • シンボルとはラベルである。追加的な構造を持たない (代入などができない) 文字列みたいなもの。
  • Rubyではクラスを継承できる
  • Rubyでは組み込みクラスですら内部を見たり修正したりできる
  • 「deified」という単語は回文である
  1. 特定のコントローラだけが使うヘルパーであれば、それに対応するヘルパーファイルを置くとよいです。例えばStaticPagesコントローラ用ヘルパーは、通常app/helpers/static_pages_helper.rbになります。今回の場合、full_titleヘルパーはサイトのすべてのページで使用することを前提にしていますが、Railsにはこのような場合のための特別なヘルパーファイルapp/helpers/application_helper.rbがあります。 
  2. nanoは初学者にうってつけではありますが、筆者は普段Vimというエディタを使うことが多いです。使い方が知りたい? Learn Enough Text Editor to Be Dangerousをどうぞ! (訳注: 他のチュートリアルも日本語にしていく予定ですので、今しばらくお待ちください!) 
  3. より詳細なfooやbarの起源についてJargon Fileの"foo"という記事 (英語) を参照してください。ちなみに"foobarと"FUBAR"には全く関係がありません。 
  4. PerlやPHPに精通した開発者であれば、"foo $bar"のようなドル記号による自動的な挿入を連想して比較することでしょう。 
  5. この章の全体にわたって、関数という言葉とメソッドという言葉が混在していることを前もってお詫びいたします。Rubyでは関数とメソッドには何の違いもありません。すべてのメソッドは関数であり、すべての関数はメソッドでもあります。それもこれも、あらゆるものがオブジェクトであるからです。 
  6. とはいうものの、まだ理解していないことが1つあります。Railsがどのようにしてこれらを結びつけているかということです。URLをアクションにマップする方法や、full_titleヘルパーをビューで利用できるようにする方法などがそうです。 
  7. 文字列の式展開は魅力的です。実際、以前のチュートリアルではこれを多用していました。しかし、 provideメソッドは内部で文字列オブジェクトをSafeBufferオブジェクトに変換してしまうので、注意が必要です。つまり、実は文字列オブジェクトではないため、ビューの中で式展開を使うと多くのエスケープ処理が実行されてしまう、ということです。例えば「Help’s on the way」は「Help&amp;#39;s on the way」といった具合にエスケープされてしまいます (この問題を指摘いただいたJeremy Fleischmanに感謝します)。 
  8. このコードで使用しているsecondメソッドは、実はRuby自身の一部ではなく、Railsが追加したものです。 このコードが動作するのは、RailsによるRubyの拡張がRailsコンソールによって自動的に反映されるからです。 
  9. なおエキスパート向けには、ブロックがクロージャになっているということを知っていただくと理解しやすいと思います。クロージャとは、データを伴う、その場限りの無名関数です。 
  10. 実はRuby 1.9以降では、ハッシュの要素の順序が入力順と同じであることを保証していますが、ハッシュを特定の順序に依存してカウントするのは得策ではありません。 
  11. 余計なものを削ぎ落した結果、シンボル同士の比較を容易に行えます。文字列は1文字ずつ比較する必要がありますが、シンボルは一度に全体を比較できます。 これはハッシュのキーとして理想的な性質です。 
  12. 実際には些細な違いがあり、pメソッドは画面出力だけでなく戻り値もオブジェクトになります。しかし、putsメソッドの場合は引数によらず必ずnilが戻り値になります。(指摘してくれたKatarzyna Siwekに感謝します) 
  13. 改行は、行の末尾と次の行の始まりを示します。4.2.2.1でも紹介した通り、改行は行の末尾と次の行の始まりを示します。コードの中では \n という文字列で表します。 
  14. もちろん、人間がいちいち文字数を数えていたら頭がどうにかなってしまいます。だからこそ、多くのテキストエディタにはこれらを支援する機能が備わっています。例えば、図 1.6をもう一度見てみると、スクリーンの右側に細い縦線があることに気づくかもしれません。これがコードを80文字以下に抑えやすくするための縦線です (ただ非常に細い線なので、スクリーンショットからは見つけられないかもしれません)。1.2.1で紹介したCloud IDEでは、デフォルトでこのような縦線が含まれます。Sublime Textを使用していれば、View > Ruler > 78、またはView > Ruler > 80で設定できます。 
  15. このメソッドの動作は、使用しているRubyのバージョンによって異なる可能性があります。 この例ではRuby 1.9.3以上のバージョンを前提としています。 
  16. Rubyのクラスやselfについてもっと詳しく知りたい場合は、RailsTipsに投稿された「Rubyにおけるクラスとインスタンス変数」(英語) を参照してください。 
  17. これらの階層にあるクラスの詳細を知る必要はないと思います。 私ですらそれらのクラスの詳細について知らないことがたくさんありますし、それでも私は2005年からRuby on Railsで問題なくプログラミングできています。 これは (a) 私がよほど無能であるか、(b) Railsの内部を知りつくさなくても熟練したRails開発者になれる、ということのどちらかでしょう。 私のためにも読者の皆様のためにも、後者であることを祈ります。 
Railsチュートリアルは,Ruby/Rails のアジャイル開発を得意とする YassLab によって運営・保守されております.
継続的に良いコンテンツを提供する為に,電子書籍解説動画のご購入を検討して頂けると幸いです m(_ _)m
スポンサーシップや商用利用などに関するご相談がありましたら,お問い合わせページよりお気軽にご連絡ください :)