プロを目指す人のためのRuby入門- 前半

以前に下記の記事に書いた通り写経を進めています jesus9387.hatenablog.com

5章まで解説を読むのと、写経が済んだので一旦ここで記事にしておきます。

自分の技術レベル

自分はAndroidエンジニアで、 プログラミングを初めてから今までほとんどJavaを使って日々業務を行なっています。 個人の趣味で、Swiftや、React、それこそRubyを触っていますが、やはり一番知識があるのはJavaだと思います。

本書では「JavaだとこうだけどRubyならこうかける」みたいな比較があり、個人的にかなり読みやすいです。

今転職を考えていて、Rubyを使いたいと思っている方ならまさしく「買い」な本です。 これを一通りやった後に「Railsチュートリアル」やってもよさそう。

ここまで読んでの感想

ここまで読んでの感想を書いていきたいと思います

「この書き方は混乱を招くのでやめておいた方がいいです。」などのやらない方がいいことも同時に教えてくれる

「この書き方は一般的には使わない」などの一般的ではない書き方ははっきり教えてくれるところが他の技術書にはないのでそこはすごくありがたいなと思いました。

Javaエンジニア、もしくは他言語のエンジニアからRubyに入門すると「なにが正解の書き方なのか」という観点が理解できません。 これをコードレビューとかで学んでいくことですが、Rubyを初めて入門するときにこれがあるとかなりありがたいとおもいます。

Javaと比較しながら教えてくれる

これは上にも「自分の技術レベル」のとこで買いたことと同じですが、かなりありがたかったです。

本書を読みながら個人的に書いたメモ

自分の書いたメモもここの残しておきます。 (誤字脱字がないか確認するときに読み返しながら復習するためです。)

変なことや、Rubyを学んでみての感想のところどころに書いていますのでよろしければどうぞ

例題の問題を写経したソースコードは下記におきました

github.com

メモ

ifの条件について

Rubyではfalseもしくはnilのときに偽を返す

これによってnilチェックはしなくてもよくなる

unlessについて

偽のときにかくやつ(これはJavaや、Swiftにはない構文なのでパッとわからないの注意)

status = 'error'

if status != 'ok'
  #エラー処理
end

上記の処理をRubyでは下記のように書ける

status = 'error'

unless status == `ok`
  # エラー処理
end

ただし、if文のelsifのような構文はないので注意

三項演算子

n = 11

n > 10 ? '10より大きい' : '10以下'

スッキリかけることはできるが、複雑な条件式だったら 逆に読みづらくなるので注意が必要

デフォルト値付き引数

def greeting(country = 'japan')
  if country == 'japan'
    'こんにちわ'
  else
    'hello'
  end
end

greeting # => こんにちわ
greeting('us') # => hello

これもRuby特有かな? これも初めての構文で便利だな〜と思う

?で終わるメソッド

Rubyでは?や!で終わるメソッドがいくつか用意されている これがつくメソッドは全て真偽値を返すメソッド

# 空かどうか返すメソッド

.empty? # => true
'abc'.empty? # => false

他にもinclude?nil?などいろいろ

?で終わるメソッドは自分で作成することも可能で 真偽値を返すメソッドであれば?を最後につけたメソッドを作成してもよいと思われる

!で終わるメソッド

!は「使用するには注意が必要」という意味

# 文字列を大文字にするメソッド
upcase # => 大文字にした新しい文字列を返す
upcase! # => 与えられた文字列を大文字に変換する

例

a = 'Ruby'

a.upcase # => RUBY
a # => Ruby

a.upcase! # => RUBY
a # => RUBY

このようなメソッドを「破壊的メソッド」と呼ばれる

その他基礎知識

  • ガーベジコレクション(GC)がある言語
  • エイリアスメソッド

    • まったく同じ処理をするメソッドに複数の名前がついているメソッドのこと(例:lengthsize)
  • requireloadrequire_relativeについて

    • require:現在実行しているファイルからの相対パスもしくは、絶対パスで指定する
    • loadrequireは1回しかライブラリを読み込まないが、loadを使いと毎回無条件にファイルを読み込むことができるようになる
    • require_relative:自分のファイルが存在するファイルが起点になる

テストしてみる

Fizz Buzzのサンプルソールを使ってテストを実行する

def fizz_buzz(n)
    if n % 15 == 0
        'Fizz Buzz'
    elsif n % 3 == 0
        'Fizz'
    elsif n % 5 == 0
        'Buzz'
    else
        n.to_s
    end

end

require 'minitest/autorun'

class FizzBuzzTest < Minitest::Test
    def test_fizz_buzz
        assert_equal '1', fizz_buzz(1)
        assert_equal '2', fizz_buzz(2)
        assert_equal 'Fizz', fizz_buzz(3)
        assert_equal '4', fizz_buzz(4)
        assert_equal 'Buzz', fizz_buzz(5)
        assert_equal 'Fizz', fizz_buzz(6)
        assert_equal 'Fizz Buzz', fizz_buzz(15)
    end
end

テストの種類は下記になる

assert_equal b,a # => aとbが等しかったらパスする

assert a # => aが真であればパスする

refuse a # => aが偽であればパスする

Rubyでの配列

  • 型の違う要素を混在させることが可能
a = [1, "test1", 2, "test3", 3]
  • 存在しない要素を指定したときにエラーではなくnilが返る
a = ["test1","test2","test3"]

a[100] #=> nil
  • 元の大きさよりも大きい添え字を指定すると間はnilで埋められる
a = [1, 2]

a[4] = 50

a #=> [1, 2, nil, 50]
  • << を使うと配列の最後に要素を追加することができる
a = [1, 2, 3]

a << 90

a #=> [1, 2, 3, 90]

ブロック

Rubyではfor文はかかない(まじか、、、すごい) Rubyでは配列に対して繰り返しを命令する

numberArray = [1, 2, 3, 4, 5]
sum = 0

numberArray.each do |n|
  sum += n
end

sum #=> 15
  • もしnが不要な場合は省略可能

  • do ~ end{}に置き換えることが可能

numberArray = [1, 2, 3, 4, 5]
sum = 0

numberArray.each { |n|
  sum += n
}

sum #=> 15

ここの使い分けは一般的に下記のようにするらしい

1. 改行含む長いブロックの場合は`do ~ end`でかく
2. 一行で書くような短い処理の場合は`{}`でかく

map/collect

ブロックの戻り値の配列の新しい要素になる場合はmapを使う (Javaではhashmapを連想してしまうが、Rubyでは違うらしい)

numberArray = [1, 2, 3]

new_numberArray = []

numberArray.each{ |n| new_numberArray << n * 10}

new_numberArray #=> [10, 20, 30]

上記のようなコードはmapを使うとよりスッキリかけるようになる

numberArray = [1, 2, 3]

new_numberArray = numberArray.each{|n| n * 10}

=> 他にも便利なメソッドがいろいろ用意されているのでその都度読むことにする(Rubyってすげーな) もうJavaやりたくねーー

2つの配列を連結する

Rubyでは二つの配列を連結するときはconcatもしくは+を使用する

この二つの違いは破壊的かどうかということ

a = [1, 4]
b = [2, 3]

a.concat(b)

a #=> [1, 4, 2, 4] 元の変数を変更する破壊的メソッド

c = [1, 4]
d = [2, 3]

c + d #=> [1, 4, 2, 3]

c #=> [1, 4]
d #=> [2, 3]

基本的にconcatはバグを生みやすいので使わない方がいいとのこと

ハッシュ

Javaでいうhashmapのこと

country = {'japan' => 'yen', 'us' => 'doller'}
country['japan'] #=> 'yen'
  • すでにキーが存在している場合は上書きされる
  • 存在しないキーを指定するとnilが返る

ハッシュを使った繰り返し

ブロックが2つになることに注意 ブロックを一つにするとキーと値が配列になるので注意

countries = {'japan' => 'yen', 'us' => 'doller', 'india' => 'rupee'}

countries.each do |key, n|
  puts "#{key} : #{n}"
end

# => japan : yen
# => us : doller
# => india : rupee

シンボル

使い所:名前を識別できるようにしたが、必ずしも文字列である必要がないときに場合

  • ハッシュのキーはシンボルを使った方がいい
countries = {:japan => 'yen', :us => 'doller', :india => 'rupee'}

countries[:japan] # => yen
  • ハッシュのキーにシンボルと文字列を混在させることはできるが、無用な混乱を招くので統一したほうがいい