
Rubyの構文を覚えるためにざっくり記事にまとめてみた
以前、業務でKotlinを扱うことになった際に、構文を覚えるためにKotlinの構文を覚えるためにざっくり記事にまとめてみたという記事を書きました。 そして今回は、業務でRubyを扱うことになったため、Rubyの基本構文を学びつつ、忘れたときに振り返られるように本記事を作成しました。 本記事ではRubyのすべてを網羅するのではなく、押さえておいたが良いもののみで、他の言語にも共通するような部分は割愛しています。 また、公開時点では書ききれていない部分もあるため、随時更新していく予定です。
Rubyとはどういう言語か
Rubyは、日本人のまつもとゆきひろ氏(Matz)によって開発されたオブジェクト指向スクリプト言語です。 Webアプリ開発に強く、特にRuby on Railsというフレームワークで一躍有名になりました。 また、豊富なライブラリ(Gem)や柔軟な構文により、自動化スクリプトやツール開発にも活用されています。 では実際にRubyの基本となる構文を見ていきましょう。
変数、定数の宣言
Rubyで変数、定数宣言は変数名、定数名のみで宣言ができます。 変数は小文字で定数は大文字で宣言します。
a = "佐賀"
TAX = 1.1
puts a, TAX
JSのように変数を宣言するだけの構文はないためRubyの場合、必ず何かしらの値を入れる必要があります。 そのため以下の場合、変数bはエラーとなります。
a = nil
b # エラー
変数名、定数名の先頭に数字をつけることはできません。
1a = nil # エラー
変数は再代入が可能です。 Rubyの場合、定数も変数同様に再代入が可能で、定数に代入したときは警告が出ます。
a = nil
a = "abc"
TAX = 1.05
TAX = 1.1
puts a, TAX # abc 1.1
命名する際に単語を繋げるときは、慣習的にスネークケースにするようです。 また予約語は変数名、定数名にすることができません。
数値リテラル
数値型には以下があります。NumericはInteger、Floatの親クラスになります。
型 | 概要 | 例 |
---|---|---|
Numeric | 数値 | numeric = 1 |
Integer | 整数 | integer = 1 |
Float | 浮動小数点数 | float = 1.1 |
変数名の先頭にマイナス記号をつけると負数に反転させることができます。
a = 100
puts -a # -100
整数動詞の割算には注意が必要で以下の場合は出力される値も整数になります。
a = 3 / 2
puts a # 1
小数点以下の値にするには一方または両方を浮動小数点数にすると良いです。
a = 3.0 / 2
puts a # 1.5
整数型を浮動小数点数にする場合、以下のようにメソッドを使用することもできます。
a = 3
puts a.to_f # 3.0
また数値がどのクラスになるかは以下のように確認することができます。
a = 3
b = 3.1
puts a.class, b.class # Integer Float
インクリメント、デクリメントを行なう際はJavaScriptのように++や--はないため以下のようにします。
a = 1
a = a + 1
b = 1
b += 1
c = 1
c = c - 1
d = 1
d -= 1
puts a, b, c, d # 2, 2, 0, 0
文字列リテラル
文字はシングルクォート、ダブルクォートで囲う必要があります。 文字列に改行文字の\nなどを埋め込みたい場合はダブルクォートで囲う必要があります。
a = '佐賀\n大好き'
# 佐賀\n大好き
b = "佐賀\n大好き"
# 佐賀
# 大好き
puts a, b
式展開
ダブルクォートで囲まれた文字列には#{式}で内容を埋め込むことができます。 JS/TSでいうテンプレートリテラルのような感じです。
first_name = '佐賀'
last_name = 'Webエンジニア'
puts "私は#{first_name}#{last_name}です" # 私は佐賀Webエンジニアです
ハッシュ
ハッシュはキーとバリューの組み合わせでデータ持つオブジェクトのことです。 キーには文字列やシンボルを使うことができます。 また文字列よりシンボルを使う方がハッシュのアクセスは早いようです。
a = { 'first_name' => '佐賀', last_name: 'Webエンジニア', :age => 20 }
puts a['first_name'], a[:last_name], a[:age]
また空のハッシュは{}
で作ることができます。
範囲オブジェクト
範囲オブジェクトは、連続する要素の範囲を表現するオブジェクトです。 Kotlinの範囲演算子と似ています。 以下のコードの場合だと1~3の範囲になります。
puts (1..3).to_a # 1, 2, 3
また...のように記述すると終点の直前になります。
puts (1...3).to_a # 1, 2
型について
RubyはJavaScriptなどと違って数値と文字列を結合することができません。
puts 1 + '1' # エラー
暗黙的な型変換は行なわれないので、結合する場合は以下のように変換する必要があります。
puts 1.to_s + '1' # 11
puts 1 + '1'.to_i # 2
Truthy / Falsy
RubyではJavaScriptとは異なり、false, nilがFalsyな値となり、それ以外がTruthyな値となります。
演算子
Rubyの演算子には以下があり、優先順位があります。
高い ::
[]
+(単項) ! ~
**
-(単項)
* / %
+ -
<< >>
&
| ^
> >= < <=
<=> == === != =~ !~
&&
||
.. ...
?:(条件演算子)
=(+=, -= ... )
not
低い and or
以下のコードの場合だとtrueが返ります。
a = true
b = true
c = false
puts a || b && c # a || (b && c)
&&は||より優先順位が高いため上記コメントのように解釈されます。
条件分岐
Rubyにはif, unless, caseの条件分岐があります。
if
if文はどの言語にもあると思うので詳細は割愛し、Rubyでの書き方のみ記載します。 条件を追加する場合はelsifはeをつけませんが、elseの場合はeが必要なのでスペルに注意が必要です。 また最後にendを付ける必要があります。
a = 70
if a === 100
puts '満点'
elsif a >= 50
puts '半分以上'
else
puts '頑張りましょう'
end
unless
unlessはifと反対の意味になります。 またifのelsifに相当するものはないようです。 以下の場合はelseのputsが出力されます。
a = 0
unless a.zero?
puts '0じゃない!'
else
puts '0です!'
end
case
caseは複数の条件をチェックすることができる条件分岐です。 Kotlinのwhen式に似ています。 下記の場合は2つ目のwhenのputsが出力されます。
a = 2
case a
when 1
puts '1です'
when 2
puts '2です'
else
puts '1, 2以外'
end
繰り返し処理
繰り返し処理はいくつかの構文があります。
each
eachは配列やハッシュをひとつずつ取り出します。 構文は以下です。
nums = [1, 2, 3]
nums.each do |num|
puts num
end
# 1, 2, 3
do ~ endを{}に置き換えることもできます。
nums = [1, 2, 3]
nums.each { |num|
puts num
}
ハッシュの場合は以下のように記述します。
obj = { a: 'A', b: 'B', c: 'C' }
obj.each { |key, value|
puts "#{key}: #{value}"
}
# a: A, b: B, c: C
for
forも同じく配列等の値をひとつずつ取り出し処理を実行できます。 構文は以下です。
nums = [1, 2, 3]
for num in nums do
puts num
end
# 1, 2, 3
times
timesは配列を用いずに特定回数ループしたい場合などに使用します。 下記の場合は引数でindexを取って出力していますが、必要ない場合は省略できます
3.times do |index|
puts index + 1
end
# 1, 2, 3
while
whileは条件式がtrueになるときに、処理の実行を繰り返します。 falseとなるまで繰り返すため無限ループに注意が必要です。
count = 0
while count < 3 do
puts count += 1
end
# 1, 2, 3
upto, downto
uptoは開始値から終了値まで数値を1ずつ増やしながら処理を実行したいときに使用します。
1.upto(3) { |i|
puts i
}
# 1, 2, 3
downtoはuptoと逆で1ずつ減らしながら処理を実行します。
3.downto(1) { |i|
puts i
}
# 3, 2, 1
step
stepは開始値から上限値まで値を増やしながら処理を実行したい時に使用します。
1.step(6, 2) { |num|
puts num
}
# 1, 3, 5
loop
loopは中断されない限り、無限に繰り返し処理を実行します。 breakやnextといった制御構造を用いて使用するかと思います。
count = 0
loop do
count += 1
puts count
break if count >= 3
end
# 1, 2, 3
map(collect)
mapは要素の数だけ繰り返し、戻り値を集めた配列を作成して返します。 JavaScriptのmapと似ているかと思います。
nums = [1, 2, 3]
new_nums = nums.map { |num|
num * 2
}
puts new_nums
# 2, 4, 6
collectはmapのエイリアスとなるため、mapと同じ動きをします。
nums = [1, 2, 3]
new_nums = nums.collect { |num|
num * 2
}
puts new_nums
# 2, 4, 6
break, next
breakはもっとも内側のループ処理を脱出し、nextは次のループへジャンプします。 breakはloopの例と同じものになります。 breakのifの条件がtrueの場合、ループ処理を抜けます。
count = 0
loop do
count += 1
puts count
break if count >= 3
end
# 1, 2, 3
nextの例は以下です。 偶数の場合は出力せず、次のループへジャンプするため奇数のみ出力されます。
nums = [1, 2, 3, 4, 5]
nums.each { |num|
next if num.even?
puts num
}
# 1, 3, 5
クラス、メソッド
クラスはオブジェクトの設計図のようなものです。 Rubyは純粋なオブジェクト指向言語なので、すべてがオブジェクトとして扱われます。 そのオブジェクトを作るためのテンプレートがクラスです。 Rubyでクラスを定義するときはパスカルケースで記述するようです。 メソッドはクラス内に定義する関数のようなものです。 クラス、メソッド構文は以下のようになります。 引数がない場合はカッコは省略でき、defはdefineの略だそうです。 またJavaScriptの場合はreturnで戻り値を返す必要がありますが、Rubyの場合は最後に評価された式がメソッドの戻り値になります。
class Saga
def message(text)
puts "佐賀#{text}"
end
end
saga = Saga.new
saga.message('最高')
# 佐賀最高
クラスのインスタンスは変数を使って値を保持することもできます。 下記のinitializeはnewが使われた時に呼ばれるメソッドになります。 newを使用するときに引数を渡すとinitializeに引数が渡ります。 そして@から始まるインスタンス変数に代入しています。
class Saga
def initialize(text)
puts 'init'
@text = text
end
def message
puts "佐賀#{@text}"
end
end
saga = Saga.new('最高')
saga.message
# init
# 佐賀最高
アクセサメソッド
アクセサメソッドは、クラスの外部から参照や書き換えをするために定義するメソッドです。 attr_accessorで定義でき、@ではなく:を使用します。
class Saga
attr_accessor :text
def initialize(text)
puts 'init'
@text = text
end
def message
puts "佐賀#{@text}"
end
end
saga = Saga.new('最高')
saga.message
saga.text = '超最高'
puts saga.text
# init
# 佐賀最高
# 超最高
読み取り専用の場合はattr_readerを使用し、書き込みだけをしたい場合はattr_writerを使用します。
クラス変数
クラス変数とは、クラス自体に値を保持することができる変数のことです。 先頭に@@
を付けます。
class Saga
@@count = 0
def initialize(text)
@text = text
@@count += 1
end
def city
puts "佐賀県#{@text} count: #{@@count}"
end
end
saga = Saga.new('佐賀市')
saga.city
# 佐賀県佐賀市 count: 1
saga = Saga.new('多久市')
saga.city
# 佐賀県多久市 count: 2
クラスメソッド
クラスメソッドとは、クラスそのものに紐づけられたメソッドのことです。 クラスの各インスタンスではなく、クラス自体に紐づいています。 クラスメソッドを定義するときはself.
を付けます。
class Saga
@@count = 0
def initialize(text)
@text = text
@@count += 1
end
def city
puts "佐賀県#{@text}"
end
def self.count
puts "count: #{@@count}"
end
end
Saga.count
# count: 0
saga_city = Saga.new('佐賀市')
saga_city.city
# 佐賀県佐賀市
taku_city = Saga.new('多久市')
taku_city.city
# 佐賀県多久市
Saga.count
# count: 2
継承
継承は、既存のクラス(親クラス)が持っているプロパティやメソッドを、別のクラス(子クラス)に引き継いで新しいクラスを定義する機能です。 これにより、共通する処理を親クラスにまとめておくことで、子クラス側では重複したコードを書く必要がなくなり、コードの再利用性や保守性が高まるというメリットがあります。 また、継承したメソッドは子クラスで**オーバーライド(上書き)**することができ、親クラスの処理を変更したり、拡張したりすることもできます。 以下の例では、UserNameクラスが名前の情報を扱い、UserProfileクラスがそれを継承して、年齢の情報も追加しています。 また、display_profileメソッドをオーバーライドして、名前に加えて年齢も表示するようにしています。
class UserName
def initialize(name)
@name = name
end
def display_profile
puts "名前:#{@name}"
end
end
class UserProfile < UserName
def initialize(name, age)
super(name)
@age = age
end
# display_profileメソッドをオーバーライド
def display_profile
super
puts "年齢:#{@age}"
end
end
user_profile = UserProfile.new('田中', 30)
user_profile.display_profile
# 名前:田中
# 年齢:30
モジュール
モジュールは、共通のメソッドや定数などをグループ化してまとめるための仕組みです。 クラスのようにインスタンス化することはできません。 下記のように、モジュール内でself.をつけて定義すれば、クラスメソッドのように呼び出すことができます。
module Saga
def self.city
puts "佐賀市"
end
end
Saga.city # 佐賀市
モジュールは、includeやextendを使ってクラスに機能を追加することができます。 includeは、モジュールのメソッドをインスタンスメソッドとしてクラスに取り込みます。 extendは、モジュールのメソッドをクラスメソッドとしてクラスに取り込みます。
module Saga
def city
puts "佐賀市"
end
end
class A
include Saga
end
class B
extend Saga
end
A.new.city # 佐賀市
B.city # 佐賀市
例外処理
例外とは、プログラムを実行している最中に、予期しないエラーが発生した場合に発生する特別なオブジェクトのことです。 例えば、存在しないファイルを開こうとしたり、数値を0で割ろうとしたりすると、プログラムはそのままではクラッシュしてしまいます。 そのようなエラーの発生を検知して安全に処理を続けるために使うのが例外処理です。 Rubyでは、begin~rescueを使って例外をキャッチして処理できます。
def divide(a, b)
begin
raise ArgumentError, "引数が数値ではありません" unless a.is_a?(Numeric) && b.is_a?(Numeric)
result = a / b
puts "計算結果:#{result}"
rescue ZeroDivisionError => e
puts "エラーが発生しました: #{e.message}"
rescue ArgumentError => e
puts "引数エラー: #{e.message}"
else
puts "エラーは発生しませんでした"
ensure
puts "処理を終了します"
end
end
divide(10, 2)
# 計算結果:5
# エラーは発生しませんでした
# 処理を終了します
divide(10, 0)
# エラーが発生しました: divided by 0
# 処理を終了します
divide(10, "a")
# 引数エラー: 引数が数値ではありません
# 処理を終了します
上記の例外処理のサンプルコードで使用しているそれぞれの構文の説明は以下です。
構文 | 説明 |
---|---|
rescue | 例外が発生した場合にその内容を補足して、適切な処理を行うためのブロック。例外クラスを指定することで、特定のエラーのみを補足できる。 |
else | 例外が発生しなかった場合のみ実行されるブロック。通常処理が成功したときの追加処理に使用。 |
ensure | 例外の有無に関係なく、必ず最後に実行されるブロック。ログ出力やファイルのクローズなど後処理に使用。 |
raise | 明示的に例外を発生させるときに使う。条件に応じてエラーを発生させたいときなどに使用。 |
いかがだったでしょうか。今回もRubyをやることとなった私自身が覚えるための記事になっています。 冒頭にも記載したように全てを網羅しているわけでなく最低限理解していれば何とか業務をこなせるのではないかと思ったところのみ掲載しています。 今後業務を進めていく中で新たに得た知見や、漏れているところがあれば追記していきます。