rails console
Railsチュートリアル本文にあるとおり、これから「rails consoleをツールとしてRubyを学んでいこう」というパートになります。
~/.irbrcを編集し、irbにRailsチュートリアルの推奨設定を適用する
irbにおけるRailsチュートリアルの推奨設定の内容は以下です。
- irbのプロンプトを簡潔な表示に置き換える
- irbの自動インデント機能をオフにする
当該設定を適用するためには、Railsが動作している環境で~/.irbrcを編集する必要があります。
私がセットアップしたDocker環境では、nanoエディタがインストールされておらず、先にインストールする必要がありました。当該Docker環境のOSはDebian 9.5なので、nanoエディタは以下の手順でインストールできました。
# apt-get update
# apt-get install -y nano
nanoエディタをインストールしたら、~/.irbrcの内容を以下のように書き換え、変更を保存します。
IRB.conf[:PROMPT_MODE] = :SIMPLE
IRB.conf[:AUTO_INDENT_MODE] = false
# pwd
/var/www/sample_app
# rails console
Running via Spring preloader in process 948
Loading development environment (Rails 5.1.6)
>>
Railsチュートリアルの推奨設定が適用されたようです。
文字列の連結
ここから、rails consoleの中でRuby言語の世界を探索してみることにします。
>> first_name = "Michael"
=> "Michael"
>> "#{first_name} Hertl"
=> "Michael Hertl"
↑「文字列の式展開」というやり方があるのですね。実は初めて知りました。
>> first_name = "Michael"
=> "Michael"
>> last_name = "Hertl"
=> "Hertl"
>> first_name + " " + last_name
=> "Michael Hertl"
>> "#{first_name} #{last_name}"
=> "Michael Hertl"
↑「文字列変数と空白文字と文字列変数を結合する」「式展開を使って文字列変数を結合する」両方の方式で文字列変数を結合してみています。
文字列の画面出力
>> puts "foo"
foo
=> nil
>> print "foo"
foo=> nil
>> print "foo\n"
foo
=> nil
-
putsやprintの戻り値はnilであり、標準出力への文字列の出力は副作用としてのものである -
putsは文字列の最後に自動で改行コードを追加する一方、printは文字列の最後に自動で改行コードを追加しない
シングルクォート内の文字列
>> 'foo'
=> "foo"
>> 'foo' + 'bar'
=> "foobar"
>> '#{foo} bar'
=> "\#{foo} bar"
>> '\n'
=> "\\n"
>> 'Newlines (\n) and tabs (\t) both use the backslash character \.'
=> "Newlines (\\n) and tabs (\\t) both use the backslash character \\."
- シングルクォート内の文字列では、特殊文字が解釈されない
- 特殊文字の解釈の有無以外は、シングルクォート内の文字列もダブルクォート内の文字列も挙動は同じである
日本語が入力できない…?
私のDockerコンテナにおいては、次の演習に取り掛かるのに際して、シェル・Railsコンソールで日本語が入力できないことが問題になりました。
どうやら原因は、「使用していたDockerコンテナに、日本語を含むロケール関係の機能一式がインストールされていなかった」ということのようでした。
以下の通り、ロケール関係の機能一式をインストールした上で、Dockerコンテナ上で動いているDebianの環境変数LANGを変更することにより、シェル・Railsコンソール日本語入力ができるようになりました。
# apt-get update
# apt-get install locales locales-all
# export LANG=en_US.UTF-8
問題解決にあたっては、以下のWebサイトを参考にさせていただきました。ありがとうございます。
演習
1.city変数に適当な市区町村を、prefecture変数に適当な都道府県を代入してください。
市区町村を越谷市、都道府県を埼玉県にしてやってみます。
>> city = "越谷市"
=> "越谷市"
>> prefecture = "埼玉県"
=> "埼玉県"
2. 先ほど作った変数と式展開を使って、「東京都 新宿区」のような住所の文字列を作ってみましょう。出力にはputsを使ってください。
以下に示す通り、方法は2つあります。両方やってみます。
>> puts prefecture + " " + city
埼玉県 越谷市
=> nil
>> puts "#{prefecture} #{city}"
埼玉県 越谷市
=> nil
3. 上記の文字列の間にある半角スペースをタブに置き換えてみてください。(ヒント: 改行文字と同じで、タブも特殊文字です)
タブ文字は\tという特殊文字として表されます。
>> puts "#{prefecture}\t#{city}"
埼玉県 越谷市
=> nil
4. タブに置き換えた文字列を、ダブルクォートからシングルクォートに置き換えてみるとどうなるでしょうか?
>> puts prefecture + '\t' + city
埼玉県\t越谷市
=> nil
>> puts '#{prefecture}\t#{city}'
# {prefecture}\t#{city}
=> nil
シングルクォート内においては、そもそも#{}も展開されないのですね。その点を見落としており、puts '#{prefecture}\t#{city}'の結果に最初驚きました。
オブジェクト
オブジェクトとメッセージの受け渡し
Rubyでは、全ての値はオブジェクトです。例えば、true、nil、""(空文字列)、RUBY_VERSION(Rubyの組み込み定数の一種)といったものもオブジェクトです。
あらゆるオブジェクトはメソッドを持ちます。例えば、文字列はlengthというメソッドやempty?というメソッドに応答できます。
>> "".length
=> 0
>> "".empty?
=> true
>> "foobar".length
=> 6
>> "foobar".empty?
=> false
分岐構文の例
以下は分岐構文の例です。irb内でブロック形式の分岐構文を書けるのですね。
>> s = "foobar"
=> "foobar"
>> if s.empty?
>> "The string is empty"
>> else
>> "The string is nonempty"
>> end
=> "The string is nonempty"
これまた分岐構文の例です。elsifで条件文を複数連ねていっています。
>> s = "foobar"
=> "foobar"
>> 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'"
falsyな値
Javascript界隈において、「booleanとして評価した場合にfalseとして評価される値」のことを「falsyな値」といいます。falsyの対義語はtruthyで、こちらは「booleanとして評価した場合にtrueとして評価される値」を意味します。
Rubyにおけるfalsyなオブジェクト(Rubyでは、全ての値はオブジェクトです)は、false自身とnilの2つしか存在しません。
!!false
=> false
!!nil
=> false
Javascriptでfalsyとされるオブジェクトに相当する0、-0、""(空文字列)、Float::NAN(非数)といったオブジェクトも、Rubyではtruthyです。
>> !!0
=> true
>> !!-0
=> true
>> !!""
=> true
>> !!Float::NAN
=> true
演習…オブジェクトとメッセージ受け渡し
1. "racecar" の文字列の長さはいくつですか? lengthメソッドを使って調べてみてください。
>> "racecar".length
=> 7
2. reverseメソッドを使って、"racecar"の文字列を逆から読むとどうなるか調べてみてください。
>> "racecar".reverse
=> "racecar"
3. 変数sに "racecar" を代入してください。その後、比較演算子 (==) を使って変数sとs.reverseの値が同じであるかどうか、調べてみてください。
>> s = "racecar"
=> "racecar"
>> s == s.reverse
=> true
4. リスト 4.9を実行すると、どんな結果になるでしょうか? 変数sに "onomatopoeia" という文字列を代入するとどうなるでしょうか?
>> s = "racecar"
=> "racecar"
>> 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
irb内でのメソッド定義
以下のように、irb内でメソッドを定義することも可能です。
>> 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
- メソッドの引数は省略できる
- Rubyのメソッドには「暗黙の戻り値がある」
- メソッドで引数の変数名にどんな名前を使っても、メソッドの呼び出し側には何の影響も生じない
上述の点が大切なポイントでしょうか。
演習…メソッドの定義
1. リスト 4.10のFILL_INの部分を適切なコードに置き換え、回文かどうかをチェックするメソッドを定義してみてください。
>> def palindrome_tester(s)
>> if s.reverse == s
>> puts "It's a palindrome!"
>> else
>> puts "It's not a palindrome."
>> end
>> end
=> :palindrome_tester
2. 上で定義したメソッドを使って “racecar” と “onomatopoeia” が回文かどうかを確かめてみてください。
>> palindrome_tester("racecar")
It's a palindrome!
=> nil
>> palindrome_tester("onomatopoeia")
It's not a palindrome.
=> nil
3. palindrome_tester("racecar")に対してnil?メソッドを呼び出し、戻り値がnilであるかどうかを確認してみてください。
>> palindrome_tester("racecar").nil?
It's a palindrome!
=> true
-
putsは副作用で標準出力に文字列が出力されるのであり、戻り値はnilである - Rubyのメソッドは、明示的に戻り値を指定しなければ、メソッド内で最後に評価された式の値が戻り値となる
上述の挙動を考えると、1.で定義したpalindrome_testerの戻り値は、確かに常にnilになりますね。
余談…演算子もメソッドである
余談ですが、Rubyにおいては、演算子もメソッドの一種として実装されています。例えば、以下の2つの表現は同じメソッドの呼び出しになります。
>> 17 + 42
=> 59
>> 17.+(42)
=> 59