Ruby チートシート

cheatsheet

基本操作 🔰

Rubyの基本的な構文やデータ型に関する操作です。

変数と定数

種類 命名規則 説明 コード例
ローカル変数 小文字 or `_` で始まる メソッド内やブロック内など、定義されたスコープでのみ有効。
message = "こんにちは"
_internal_val = 10
インスタンス変数 `@` で始まる オブジェクトごとに存在する変数。クラスのメソッド内で使用。
class User
  def initialize(name)
    @name = name
  end
end
クラス変数 `@@` で始まる クラスとそのサブクラス、インスタンス間で共有される変数。
class Counter
  @@count = 0
  def initialize
    @@count += 1
  end
  def self.count
    @@count
  end
end
グローバル変数 `$` で始まる プログラム全体からアクセス可能。使用は推奨されないことが多い。
$program_status = "running"
定数 大文字で始まる 一度代入すると再代入時に警告が出る。クラス名やモジュール名も定数。
PI = 3.14159
AppName = "MyApp"

主なデータ型

説明 リテラル例
整数 (Integer) 整数を表す。FixnumとBignumが内部的に使われる(Ruby 2.4以降はIntegerに統合)。 100, -5, 1_000_000
浮動小数点数 (Float) 実数を表す。 3.14, -0.5, 1.0e-5
文字列 (String) 文字の並び。シングルクォートとダブルクォートで挙動が異なる。 'hello', "world\n", %q{Ruby}, %Q| #{Time.now} |
配列 (Array) 順序付けられたオブジェクトの集まり。異なる型の要素を混在可能。 [1, "two", 3.0], %w[a b c], %i[x y z]
ハッシュ (Hash) キーと値のペアの集まり。順序はRuby 1.9以降保持される。 {'key1' => 'value1', :key2 => 2}, {key1: 'value1', key2: 2}
シンボル (Symbol) 文字列に似ているが、内部的には整数で管理される。効率的な識別子。 :success, :error_code, :"a symbol"
真偽値 (TrueClass/FalseClass) 真 (true) または偽 (false) を表す。 true, false
nil (NilClass) 何もないことを表す特別な値。 nil
範囲 (Range) 開始値から終了値までの範囲を表す。 1..10 (10を含む), 1...10 (10を含まない)

演算子

算術演算子 (+, -, *, /, %, **), 比較演算子 (==, !=, >, <, >=, <=, <=>), 論理演算子 (&&, ||, !, and, or, not), 代入演算子 (=, +=, -=, etc.), 三項演算子 (条件 ? 真の場合 : 偽の場合) などがあります。

# 算術
a = 10 + 5  # a は 15
b = 10 * 2  # b は 20
c = 10 / 3  # c は 3 (整数除算)
d = 10.0 / 3 # d は 3.333...
e = 10 % 3  # e は 1 (剰余)
f = 2 ** 3  # f は 8 (べき乗)

# 比較
puts 5 == 5 # true
puts 5 != 4 # true
puts 5 < 10 # true
puts 5 <=> 10 # -1 (左が小さい)
puts 10 <=> 5 # 1 (左が大きい)
puts 5 <=> 5 # 0 (等しい)

# 論理
age = 25
is_student = false
puts age >= 20 && !is_student # true

# 代入
count = 0
count += 1 # count = count + 1 と同じ

# 三項演算子
status = age >= 18 ? "adult" : "minor"
puts status # "adult"

コメント

# から行末までがコメントになります。複数行コメントは =begin=end で囲みますが、あまり使われません。

# これは一行コメントです
puts "Hello" # ここもコメント

=begin
これは
複数行の
コメントです
=end

制御構造 🚦

プログラムの流れを制御するための構文です。

条件分岐

if / elsif / else / end

score = 75
if score >= 80
  puts "優"
elsif score >= 60
  puts "良"
else
  puts "可"
end

# 後置if (修飾子)
puts "合格" if score >= 60

unless / else / end

if not と同様ですが、条件が偽のときに実行されます。

is_logged_in = false
unless is_logged_in
  puts "ログインしてください"
end

# 後置unless (修飾子)
puts "処理を実行します" unless is_logged_in == true

case / when / else / end

signal = "red"
case signal
when "red"
  puts "止まれ"
when "yellow"
  puts "注意"
when "green", "blue" # 複数の値を指定可能
  puts "進め"
else
  puts "不明な信号"
end

# オブジェクトや範囲も使用可能
age = 15
case age
when 0..5
  puts "幼児"
when 6..12
  puts "小学生"
else
  puts "中学生以上"
end

# === 演算子が使われる
value = "text"
case value
when String
  puts "文字列です"
when Integer
  puts "整数です"
end

繰り返し

while / end

条件が真の間、繰り返し実行します。

count = 0
while count < 3
  puts "カウント: #{count}"
  count += 1
end

# 後置while (修飾子)
balance = 1000
balance *= 1.05 while balance < 1500

until / end

条件が偽の間、繰り返し実行します (while not と同様)。

counter = 5
until counter == 0
  puts counter
  counter -= 1
end

# 後置until (修飾子)
sleep(1) until File.exist?("result.txt")

for / in / end

コレクション (配列や範囲など) の要素を反復処理します。内部的には each が呼ばれます。

numbers = [1, 2, 3]
for num in numbers
  puts num * 2
end

for i in 0..2
  puts "Index: #{i}"
end

each (イテレータ)

コレクションの各要素に対してブロックを実行します。最もRubyらしい繰り返し方法です。

fruits = ["apple", "banana", "cherry"]
fruits.each do |fruit|
  puts "I like #{fruit}."
end

# ブロックを {} で書くことも可能 (通常1行の場合)
(1..3).each { |n| puts n }

# インデックス付き
fruits.each_with_index do |fruit, index|
  puts "#{index}: #{fruit}"
end

times

指定した回数だけブロックを実行します。

5.times do |i|
  puts "#{i+1}回目の繰り返し"
end

3.times { puts "Hello!" }

loop / do / end

無限ループを作成します。break で脱出する必要があります。

count = 0
loop do
  puts "Looping..."
  count += 1
  break if count >= 3 # 脱出条件
end

繰り返し制御

キーワード 説明 コード例
break 最も内側のループを中断し、ループの次の処理へ移る。
[1, 2, 3, 4, 5].each do |n|
  break if n == 3
  puts n # 1, 2 が出力される
end
puts "ループ終了"
next 現在の繰り返し処理をスキップし、次の繰り返しへ移る。
[1, 2, 3, 4, 5].each do |n|
  next if n.even? # 偶数はスキップ
  puts n # 1, 3, 5 が出力される
end
redo 現在の繰り返し処理を、条件評価などをやり直さずに最初からもう一度実行する。
attempts = 0
data = [1, 2, 'stop', 3]
data.each do |item|
  begin
    puts "Processing: #{item}"
    raise "Error on stop" if item == 'stop' && attempts == 0
    attempts = 0 # 成功したらリセット
  rescue
    attempts += 1
    puts "Retry attempt: #{attempts}"
    redo # 同じ item で再試行
  end
end

メソッド 🔧

処理をまとめたものです。関数とも呼ばれます。

メソッド定義と呼び出し

# メソッド定義
def greet(name)
  puts "Hello, #{name}!"
end

# メソッド呼び出し
greet("Alice") # "Hello, Alice!" と出力
greet "Bob"    # 括弧は省略可能 (引数がある場合)

# 引数なしメソッド
def say_goodbye
  puts "Goodbye!"
end

say_goodbye # 括弧なしで呼び出し

引数

デフォルト引数

def welcome(user = "Guest")
  puts "Welcome, #{user}!"
end

welcome # "Welcome, Guest!"
welcome("Admin") # "Welcome, Admin!"

可変長引数

def print_args(*args)
  puts "引数の数: #{args.length}"
  args.each { |arg| puts "- #{arg}" }
end

print_args(1, "two", :three)

キーワード引数

# デフォルト値付きキーワード引数
def create_user(name:, email:, admin: false)
  puts "Name: #{name}, Email: #{email}, Admin: #{admin}"
end

create_user(name: "Eve", email: "eve@example.com")
create_user(name: "Frank", email: "frank@example.com", admin: true)
# 順番は関係ない

# デフォルト値なしキーワード引数 (呼び出し時に必須)
def configure(host:, port:)
  puts "Connecting to #{host}:#{port}"
end
configure(host: "localhost", port: 8080)

# 可変長キーワード引数
def print_options(id, **options)
  puts "ID: #{id}"
  options.each { |key, value| puts "#{key}: #{value}" }
end
print_options(101, color: "red", size: "large")
通常の引数、デフォルト引数、可変長引数、キーワード引数、可変長キーワード引数を組み合わせる際の順序に注意が必要です (通常 -> デフォルト -> 可変長 -> キーワード(デフォルトなし) -> キーワード(デフォルトあり) -> 可変長キーワード)。

戻り値

メソッド内で最後に評価された式の結果が暗黙的に戻り値となります。return キーワードで明示的に値を返すこともできます。

def add(a, b)
  a + b # この結果が戻り値
end

result = add(3, 4) # result は 7

def check_status(code)
  if code == 0
    return "Success" # 明示的に返す
  end
  # codeが0でない場合、ここが評価される (nilが返る)
  "Error or Unknown" # これを書けば nil ではなくこの文字列が返る
end

status1 = check_status(0) # status1 は "Success"
status2 = check_status(1) # status2 は "Error or Unknown"

ブロック付きメソッド (yield)

メソッド呼び出し時にコードブロック (do..end または {..}) を渡し、メソッド内でそのブロックを実行できます。

def process_data
  puts "処理開始"
  result = yield # ブロックを実行し、その結果を受け取る
  puts "ブロックの結果: #{result}"
  puts "処理終了"
end

process_data do
  # このブロックが yield で実行される
  data = [1, 2, 3]
  data.sum # このブロックの戻り値
end
# 出力:
# 処理開始
# ブロックの結果: 6
# 処理終了

# ブロックに引数を渡す
def repeat(n)
  n.times do |i|
    yield i # ブロックに現在のカウントを渡す
  end
end

repeat(3) do |count|
  puts "繰り返し #{count + 1} 回目"
end

# ブロックが渡されたか確認
def maybe_yield
  if block_given?
    yield
  else
    puts "ブロックが渡されませんでした"
  end
end

maybe_yield { puts "ブロック実行!" }
maybe_yield

クラスとモジュール 🏛️

オブジェクト指向プログラミングの基本的な構成要素です。

クラス定義とインスタンス化

# クラス定義
class Dog
  # 初期化メソッド (コンストラクタ)
  def initialize(name, breed)
    @name = name # インスタンス変数
    @breed = breed
  end

  # インスタンスメソッド
  def bark
    puts "#{@name} says Woof!"
  end

  # クラスメソッド (self.メソッド名)
  def self.info
    puts "This is a Dog class."
  end

  # アクセサメソッドの定義 (後述)
  attr_reader :name, :breed
  attr_writer :name # name を変更可能にする
  # attr_accessor :name # 読み書き両方可能にする場合
end

# インスタンス化 (オブジェクト生成)
my_dog = Dog.new("Pochi", "Shiba Inu")

# インスタンスメソッドの呼び出し
my_dog.bark # "Pochi says Woof!"

# クラスメソッドの呼び出し
Dog.info # "This is a Dog class."

# アクセサ経由でのアクセス
puts my_dog.name # "Pochi"
my_dog.name = "Taro" # attr_writer があるので可能
puts my_dog.name # "Taro"
# puts my_dog.breed = "Akita" # エラー (attr_writer :breed がない)

インスタンス変数とクラス変数

  • インスタンス変数 (@variable): 各オブジェクトが個別に持つデータ。initialize メソッドで初期化されることが多い。
  • クラス変数 (@@variable): クラスとその全てのインスタンス、サブクラスで共有されるデータ。
class Car
  @@total_cars = 0 # クラス変数

  def initialize(make)
    @make = make # インスタンス変数
    @@total_cars += 1
  end

  def display_make
    puts "This car is a #{@make}"
  end

  def self.total_cars
    @@total_cars
  end
end

car1 = Car.new("Toyota")
car2 = Car.new("Honda")
car1.display_make # "This car is a Toyota"
car2.display_make # "This car is a Honda"
puts Car.total_cars # 2
クラス変数は継承関係で意図しない挙動を示すことがあるため、注意深く使用するか、代替手段(クラスインスタンス変数など)を検討することがあります。

アクセサメソッド

インスタンス変数へのアクセス(読み取り・書き込み)を提供するメソッド。

  • attr_reader :var1, :var2 : 読み取りメソッド (var1, var2) を自動生成。
  • attr_writer :var1, :var2 : 書き込みメソッド (var1=, var2=) を自動生成。
  • attr_accessor :var1, :var2 : 読み取り・書き込み両方のメソッドを自動生成。
class Book
  attr_accessor :title # 読み書き可能
  attr_reader :author # 読み取り専用
  attr_writer :isbn   # 書き込み専用 (あまり使わない)

  def initialize(title, author)
    @title = title
    @author = author
  end

  def set_isbn(code)
    # attr_writer :isbn があれば self.isbn = code と書ける
    @isbn = code # 直接代入も可能
  end

  def get_isbn
    @isbn # 直接アクセスは可能だが、アクセサ経由が一般的
  end
end

book = Book.new("Ruby Guide", "Yukihiro Matsumoto")
puts book.title  # "Ruby Guide"
book.title = "Revised Ruby Guide"
puts book.title  # "Revised Ruby Guide"
puts book.author # "Yukihiro Matsumoto"
# book.author = "Matz" # エラー (attr_writerがない)

book.set_isbn("978-4-...")
puts book.get_isbn

継承

既存のクラス (スーパークラス) の機能を引き継いだ新しいクラス (サブクラス) を作成します。

class Animal
  def initialize(name)
    @name = name
  end

  def speak
    puts "#{@name} makes a sound."
  end
end

# Animalクラスを継承したDogクラス
class Dog < Animal
  # speakメソッドをオーバーライド(上書き)
  def speak
    puts "#{@name} barks!"
  end

  def fetch
    puts "#{@name} fetches the ball."
  end
end

# Animalクラスを継承したCatクラス
class Cat < Animal
  def speak
    # スーパークラスの同名メソッドを呼び出す
    super
    puts "(Specifically, meows)"
  end
end

dog = Dog.new("Buddy")
dog.speak # "Buddy barks!"
dog.fetch # "Buddy fetches the ball."

cat = Cat.new("Whiskers")
cat.speak
# "Whiskers makes a sound."
# "(Specifically, meows)"

モジュールとMix-in

モジュールはメソッドや定数の集まりです。クラスにincludeprependすることで、モジュールの機能を追加 (Mix-in) できます。extendはクラスメソッドとして追加します。

module Loggable
  def log(message)
    puts "[LOG] #{Time.now}: #{message}"
  end
end

module Flyable
  def fly
    puts "I'm flying!"
  end
end

class Product
  include Loggable # インスタンスメソッドとしてlogを追加

  def initialize(name)
    @name = name
  end

  def save
    log("Saving #{@name}...")
    # 保存処理...
    log("#{@name} saved.")
  end
end

class Bird
  extend Flyable # クラスメソッドとしてflyを追加 (特異メソッド)

  def self.description
    "Birds can often fly."
  end
end

class Airplane
    include Flyable # インスタンスメソッドとしてflyを追加

    def take_off
        puts "Taking off..."
        fly # include されたメソッドを呼び出す
    end
end


product = Product.new("Book")
product.save # Loggableのlogメソッドが使える

# extend はクラス自体にメソッドを追加する
# Bird.fly # "I'm flying!"

# include はインスタンスにメソッドを追加する
plane = Airplane.new
plane.take_off

# 名前空間としてのモジュール
module NetworkUtils
  class Connection
    def connect
      puts "Connecting..."
    end
  end

  def self.ping(host)
    puts "Pinging #{host}..."
  end
end

conn = NetworkUtils::Connection.new
conn.connect
NetworkUtils.ping("google.com")
Mix-in方法 挙動 メソッド探索順序 (例: Class A include M)
include M モジュールMのメソッドをインスタンスメソッドとして追加。継承チェーンにおいて、クラスの直後(スーパークラスの前)にモジュールが挿入される。 A -> M -> スーパークラス -> …
prepend M モジュールMのメソッドをインスタンスメソッドとして追加。継承チェーンにおいて、クラスの直前にモジュールが挿入される。同名メソッドがあればモジュールのものが優先される。 M -> A -> スーパークラス -> …
extend M モジュールMのメソッドをクラスメソッド(特異メソッド)として追加。クラスオブジェクト自体に追加される。 (クラスオブジェクトの特異クラス) -> M -> …

文字列操作 📜

文字列 (String) に関する様々な操作です。

目的 メソッド例 コード例
生成・結合 +, <<, concat, 式展開#{}
s1 = "Hello"
s2 = " World"
puts s1 + s2      # "Hello World" (新しい文字列)
puts s1 << s2     # "Hello World" (s1自体を変更)
s1.concat("!")    # "Hello World!" (s1自体を変更)
name = "Ruby"
puts "Lang: #{name}" # "Lang: Ruby"
繰り返し *
puts "Go! " * 3 # "Go! Go! Go! "
長さ・空か判定 length, size, empty?
str = "abc"
puts str.length  # 3
puts "".empty?   # true
文字・部分文字列アクセス [], slice
str = "abcdef"
puts str[0]    # "a"
puts str[1..3] # "bcd"
puts str[-1]   # "f"
puts str.slice(2, 3) # "cde"
置換 sub, gsub, sub!, gsub!
text = "apple orange apple"
puts text.sub("apple", "banana") # "banana orange apple" (最初のみ)
puts text.gsub("apple", "banana") # "banana orange banana" (全て)
# `!` 付きは自身を変更
検索 include?, index, rindex, start_with?, end_with?, match, scan
str = "Ruby Programming"
puts str.include?("Pro")   # true
puts str.index("gram")     # 8
puts str.start_with?("Ruby") # true
puts str.match?(/Pro(gram)+/) # true
puts str.scan(/\w+/) # ["Ruby", "Programming"]
分割・結合 split, join (配列メソッド)
csv = "a,b,c"
parts = csv.split(',') # ["a", "b", "c"]
puts parts.join('-')   # "a-b-c"
大文字/小文字変換 upcase, downcase, capitalize, swapcase
str = "hELLo WoRLd"
puts str.upcase    # "HELLO WORLD"
puts str.downcase  # "hello world"
puts str.capitalize # "Hello world"
puts str.swapcase  # "Hello wOrlD"
空白除去 strip, lstrip, rstrip
str = "  text  "
puts str.strip  # "text" (両端)
puts str.lstrip # "text  " (左端)
puts str.rstrip # "  text" (右端)
文字コード変換 encode
# UTF-8 から EUC-JP へ
# utf8_str = "こんにちは"
# euc_str = utf8_str.encode("EUC-JP")
ヒアドキュメント <<IDENTIFIER, <<-IDENTIFIER, <<~IDENTIFIER
query = <<SQL
SELECT *
FROM users
WHERE age > 20;
SQL

# <<- は終端識別子前のインデントを無視
message = <<-MSG
  This is a message.
  Indentation is kept.
  MSG

# <<~ は先頭のインデントと終端識別子前のインデントを無視
code = <<~CODE
      def example
        puts "Indented code"
      end
    CODE
# code は "def example\n  puts \"Indented code\"\nend" になる

配列 (Array) に関する様々な操作です。

目的 メソッド例 コード例
生成 [], Array.new, %w, %i
arr1 = [1, 2, 3]
arr2 = Array.new(3, "a") # ["a", "a", "a"]
arr3 = %w[red green blue] # ["red", "green", "blue"] (文字列の配列)
arr4 = %i[x y z]        # [:x, :y, :z] (シンボルの配列)
要素アクセス・代入 [], []=, at, first, last, fetch
arr = [:a, :b, :c, :d]
puts arr[0]      # :a
puts arr[-1]     # :d
puts arr[1..2]   # [:b, :c]
arr[1] = :B      # arr は [:a, :B, :c, :d]
puts arr.first   # :a
puts arr.last    # :d
puts arr.fetch(1) # :B
# puts arr.fetch(10) # エラー (IndexError)
puts arr.fetch(10, "default") # "default" (デフォルト値指定)
要素の追加 push (<<), unshift, insert
arr = [1, 2]
arr.push(3)    # [1, 2, 3] (末尾に追加)
arr << 4       # [1, 2, 3, 4] (同上)
arr.unshift(0) # [0, 1, 2, 3, 4] (先頭に追加)
arr.insert(2, 1.5) # [0, 1, 1.5, 2, 3, 4] (指定位置に追加)
要素の削除 pop, shift, delete, delete_at, compact, uniq
arr = [0, 1, nil, 2, 1, nil]
puts arr.pop      # nil (末尾を削除して返す) arr は [0, 1, nil, 2, 1]
puts arr.shift    # 0 (先頭を削除して返す) arr は [1, nil, 2, 1]
arr.delete(1)     # arr は [nil, 2] (指定した値を全て削除)
arr.delete_at(0)  # arr は [2] (指定インデックスを削除)
arr = [1, nil, 2, nil]
arr.compact!      # arr は [1, 2] (nil要素を削除, `!`は自身を変更)
arr = [1, 2, 2, 3, 1]
arr.uniq!         # arr は [1, 2, 3] (重複要素を削除, `!`は自身を変更)
繰り返し・走査 each, reverse_each, each_with_index, cycle
nums = [10, 20, 30]
nums.each { |n| puts n }
nums.reverse_each { |n| puts n } # 30, 20, 10
nums.each_with_index { |n, i| puts "#{i}: #{n}" }
# nums.cycle(2) { |n| puts n } # 10, 20, 30, 10, 20, 30
変換・選択 (イテレータ) map (collect), select (filter), reject, find (detect), grep
nums = [1, 2, 3, 4, 5]
squares = nums.map { |n| n * n }     # [1, 4, 9, 16, 25]
evens = nums.select { |n| n.even? } # [2, 4]
odds = nums.reject { |n| n.even? }  # [1, 3, 5]
first_even = nums.find { |n| n.even? } # 2
words = ["apple", "banana", "apricot"]
a_words = words.grep(/^a/) # ["apple", "apricot"] (正規表現にマッチ)
畳み込み (イテレータ) inject (reduce)
nums = [1, 2, 3, 4]
sum = nums.inject(0) { |result, n| result + n } # 10 (初期値0)
product = nums.inject(1) { |result, n| result * n } # 24 (初期値1)
# シンボルで演算子を指定も可能
sum_short = nums.inject(:+) # 10
product_short = nums.inject(:*) # 24
結合 +, concat, | (和集合), & (積集合), - (差集合)
a1 = [1, 2]
a2 = [2, 3]
puts (a1 + a2).inspect    # [1, 2, 2, 3] (単純結合)
a1.concat(a2)             # a1 は [1, 2, 2, 3] (破壊的)
a1 = [1, 2]; a2 = [2, 3]
puts (a1 | a2).inspect    # [1, 2, 3] (和集合、重複削除)
puts (a1 & a2).inspect    # [2] (積集合)
puts ([1, 2, 3] - [2, 4]).inspect # [1, 3] (差集合)
ソート sort, sort!, sort_by, sort_by!, reverse, reverse!
arr = [3, 1, 4, 1, 5, 9]
puts arr.sort.inspect     # [1, 1, 3, 4, 5, 9]
arr.sort!                 # 自身をソート
words = ["banana", "apple", "cherry"]
puts words.sort_by { |w| w.length }.inspect # ["apple", "banana", "cherry"] (長さ順)
puts arr.reverse.inspect  # 元の配列の逆順 (ソートではない)
検索・判定 include?, index, find_index, any?, all?, none?, one?
arr = ["a", "b", "c"]
puts arr.include?("b") # true
puts arr.index("c")    # 2
nums = [1, 2, 3, 4]
puts nums.any? { |n| n > 3 } # true (一つでも条件を満たすか)
puts nums.all? { |n| n > 0 } # true (全て条件を満たすか)
puts nums.none? { |n| n < 0 } # true (一つも条件を満たさないか)
その他 flatten, join, zip, transpose, sample
nested = [1, [2, 3], [4, [5]]]
puts nested.flatten.inspect # [1, 2, 3, 4, 5] (一次元化)
chars = ["R", "u", "b", "y"]
puts chars.join         # "Ruby" (文字列に結合)
a = [1, 2]; b = [3, 4]
puts a.zip(b).inspect   # [[1, 3], [2, 4]] (対応する要素でペア配列作成)
matrix = [[1, 2], [3, 4], [5, 6]]
puts matrix.transpose.inspect # [[1, 3, 5], [2, 4, 6]] (行列転置)
puts [1,2,3,4,5].sample # ランダムに1要素取得
puts [1,2,3,4,5].sample(2).inspect # ランダムに2要素取得

ハッシュ操作 🔑

ハッシュ (Hash) に関する様々な操作です。

目的 メソッド例 コード例
生成 {}, Hash.new
h1 = { "key1" => "value1", :key2 => 2 }
h2 = { key1: "value1", key2: 2 } # Ruby 1.9以降のシンボルキー記法
h3 = Hash.new("default") # 存在しないキーアクセス時のデフォルト値
要素アクセス・代入 [], []=, fetch, values_at
h = { name: "Alice", age: 30 }
puts h[:name]      # "Alice"
h[:city] = "Tokyo" # ハッシュに新しいキーと値を追加
puts h.fetch(:age) # 30
# puts h.fetch(:country) # エラー (KeyError)
puts h.fetch(:country, "Unknown") # "Unknown"
puts h.values_at(:name, :city).inspect # ["Alice", "Tokyo"]
キー/値の取得 keys, values, to_a
h = { a: 1, b: 2 }
puts h.keys.inspect   # [:a, :b]
puts h.values.inspect # [1, 2]
puts h.to_a.inspect   # [[:a, 1], [:b, 2]] (キーと値のペアの配列)
削除 delete, delete_if, keep_if
h = { a: 10, b: 20, c: 30 }
h.delete(:b) # h は { a: 10, c: 30 }
h.delete_if { |key, value| value < 15 } # h は { c: 30 }
h = { a: 10, b: 20, c: 30 }
h.keep_if { |key, value| value > 15 } # h は { b: 20, c: 30 }
繰り返し・走査 each, each_pair, each_key, each_value
h = { name: "Bob", age: 25 }
h.each do |key, value|
  puts "#{key} is #{value}"
end
h.each_key { |key| puts "Key: #{key}" }
h.each_value { |value| puts "Value: #{value}" }
変換・選択 (イテレータ) map, select (filter), reject, transform_keys, transform_values
h = { a: 1, b: 2, c: 3 }
arr = h.map { |k, v| "#{k}-#{v}" } # ["a-1", "b-2", "c-3"]
selected = h.select { |k, v| v > 1 } # { b: 2, c: 3 }
rejected = h.reject { |k, v| k == :a } # { b: 2, c: 3 }
up_keys = h.transform_keys { |k| k.to_s.upcase } # { "A"=>1, "B"=>2, "C"=>3 }
val_sq = h.transform_values { |v| v * v } # { a: 1, b: 4, c: 9 }
結合・マージ merge, merge! (update)
h1 = { a: 1, b: 2 }
h2 = { b: 3, c: 4 }
merged = h1.merge(h2) # { a: 1, b: 3, c: 4 } (h2の値が優先)
# ブロックで衝突時の処理を定義可能
merged_block = h1.merge(h2) { |key, old_val, new_val| old_val + new_val }
# merged_block は { a: 1, b: 5, c: 4 }
h1.merge!(h2) # h1 が { a: 1, b: 3, c: 4 } になる (破壊的)
検索・判定 key? (has_key?, member?), value? (has_value?), empty?, size (length)
h = { x: 100, y: 200 }
puts h.key?(:x)     # true
puts h.value?(300)  # false
puts {}.empty?      # true
puts h.size         # 2
その他 invert, dig
h = { a: 1, b: 2 }
puts h.invert.inspect # { 1=>:a, 2=>:b } (キーと値を反転)
data = { user: { address: { city: "Kyoto" } } }
puts data.dig(:user, :address, :city) # "Kyoto"
puts data.dig(:user, :name)           # nil (途中でキーがなくてもエラーにならない)

正規表現 🔤

文字列のパターンマッチングに使用します。

基本

要素 説明
リテラル /.../ または %r{...} /ruby/i, %r{^start}
マッチング演算子 =~ (マッチ位置 or nil), !~ (マッチしないか) "Hello Ruby" =~ /Ruby/ # => 6
メソッド match, match?, scan, [], String#gsub, String#split など "abc".match?(/b/) # true
"12 34 56".scan(/\d+/) # ["12", "34", "56"]

メタ文字と量指定子

記号 意味 記号 意味
.任意の一文字(改行除く) *直前の要素の0回以上の繰り返し
^行の先頭 +直前の要素の1回以上の繰り返し
$行の末尾 ?直前の要素の0回または1回の繰り返し
[...]角括弧内の任意の1文字 {n}直前の要素のn回の繰り返し
[^...]角括弧内を除く任意の1文字 {n,}直前の要素のn回以上の繰り返し
|左右いずれかのパターン (OR) {n,m}直前の要素のn回以上m回以下の繰り返し
(...)グループ化、キャプチャ *?, +?, ??, {n,m}?最短一致(欲張らない)量指定子
\d数字 [0-9] \w英数字とアンダースコア [a-zA-Z0-9_]
\s空白文字 (スペース, タブ, 改行など)\D, \W, \Sそれぞれ \d, \w, \s の否定
\A文字列の先頭 \Z文字列の末尾(改行直前でも可)
\z文字列の完全な末尾 \b単語境界

オプション

オプション 意味
i 大文字小文字を区別しない "Ruby" =~ /ruby/i # マッチする
m マルチラインモード (.が改行にもマッチする) "a\nb" =~ /^a.b$/m # マッチする
x 拡張モード (パターン内の空白と#コメントを無視する) pattern = / \d+ # 1つ以上の数字 \s+ # 1つ以上の空白 \w+ # 1つ以上の単語文字 /x "123 abc" =~ pattern # マッチする

キャプチャと後方参照

str = "Name: Alice, Age: 30"
match_data = str.match(/Name: (\w+), Age: (\d+)/)

if match_data
  puts "全体: #{match_data[0]}" # Name: Alice, Age: 30
  puts "名前: #{match_data[1]}" # Alice (最初のキャプチャ)
  puts "年齢: #{match_data[2]}" # 30 (2番目のキャプチャ)

  # 名前付きキャプチャ (?<name>...)
  md = str.match(/Name: (?<name>\w+), Age: (?<age>\d+)/)
  puts "名前(名前付き): #{md[:name]}" # Alice
  puts "年齢(名前付き): #{md[:age]}"   # 30
end

# gsub での後方参照
puts "abc".gsub(/(.)/, '\\1\\1') # "aabbcc" (\1 は最初のキャプチャ)
puts "abc".gsub(/(.)/) { $1 * 2 } # "aabbcc" (ブロック内では $1, $2...)

ファイル操作 📁

ファイルやディレクトリの読み書き、操作を行います。

ファイル読み込み

ブロック形式 (推奨)

ファイルが自動的にクローズされます。

# 全体を一度に読み込む
begin
  content = File.read("my_file.txt")
  puts content
rescue Errno::ENOENT
  puts "ファイルが見つかりません。"
end

# 一行ずつ読み込む
begin
  File.foreach("my_file.txt") do |line|
    puts "Line: #{line.chomp}" # chompで末尾の改行を削除
  end
rescue Errno::ENOENT
  puts "ファイルが見つかりません。"
end

# File.open を使ったブロック形式
begin
  File.open("my_file.txt", "r") do |file| # "r"は読み込みモード(デフォルト)
    file.each_line do |line|
      # 各行に対する処理
    end
  end
rescue Errno::ENOENT
  puts "ファイルが見つかりません。"
end

手動クローズ

ensure で確実にクローズする必要があります。

file = nil
begin
  file = File.open("my_file.txt", "r")
  # ファイル操作...
  content = file.read
  puts content
rescue Errno::ENOENT
  puts "ファイルが見つかりません。"
ensure
  file&.close # fileがnilでない場合のみcloseを呼ぶ
end

ファイル書き込み

モード 説明 コード例 (ブロック形式)
w 書き込みモード。ファイルが存在すれば上書き、なければ新規作成。
File.open("output.txt", "w") do |file|
  file.puts "これは最初の行です。"
  file.write "これは2行目です。(改行なし)"
  file.print "これも2行目。\n" # printは改行しない
end
a 追記モード。ファイルが存在すれば末尾に追加、なければ新規作成。
File.open("output.txt", "a") do |file|
  file.puts "これは追記された行です。"
end
r+ 読み書きモード。ファイルの先頭から開始。ファイルが存在する必要あり。
# 注意: 使い方によっては複雑になる
File.open("data.txt", "r+") do |file|
  content = file.read
  file.seek(0, IO::SEEK_SET) # ファイルポインタを先頭に移動
  file.write("Overwritten!\n" + content)
end
w+ 読み書きモード。ファイルを上書きまたは新規作成。
File.open("temp.txt", "w+") do |file|
  file.puts "Line 1"
  file.rewind # ポインタを先頭に戻す
  puts file.read # "Line 1\n" が出力される
end
a+ 読み書きモード。ファイルの末尾から開始または新規作成。
File.open("log.txt", "a+") do |file|
  file.puts "New log entry at #{Time.now}"
  file.rewind
  puts "Current log content:\n#{file.read}"
end

ファイル・ディレクトリ操作 (File, Dir, FileUtils)

目的 メソッド例 コード例
存在確認 File.exist?(path), Dir.exist?(path), File.file?(path), File.directory?(path)
puts File.exist?("my_file.txt")
puts Dir.exist?("/tmp")
ファイル情報取得 File.size(path), File.mtime(path), File.basename(path), File.dirname(path), File.extname(path)
puts File.size("my_file.txt") rescue 0
puts File.basename("/path/to/file.rb") # "file.rb"
puts File.dirname("/path/to/file.rb")  # "/path/to"
puts File.extname("/path/to/file.rb")  # ".rb"
ディレクトリ操作 Dir.mkdir(path), Dir.rmdir(path), Dir.entries(path), Dir.glob(pattern), Dir.pwd, Dir.chdir(path)
# Dir.mkdir("new_dir") unless Dir.exist?("new_dir")
puts Dir.entries(".").inspect # カレントディレクトリの内容
puts Dir.glob("*.rb").inspect # カレントの .rb ファイル一覧
puts Dir.pwd # カレントディレクトリ表示
ファイル/ディレクトリ操作 (高レベル) FileUtils モジュール (require 'fileutils' が必要)
require 'fileutils'
# FileUtils.cp("source.txt", "destination.txt") # コピー
# FileUtils.mv("old_name.txt", "new_name.txt") # 移動/リネーム
# FileUtils.rm("temp.txt")                     # 削除 (ファイル)
# FileUtils.rm_r("dir_to_remove")              # 削除 (ディレクトリとその中身)
# FileUtils.mkdir_p("path/to/nested/dir")      # 再帰的にディレクトリ作成

例外処理 ⚠️

エラー発生時の処理を記述します。

begin – rescue – else – ensure – end

begin
  # 例外が発生する可能性のある処理
  result = 10 / 0 # ZeroDivisionError が発生
  puts "計算結果: #{result}" # ここは実行されない

rescue ZeroDivisionError => e
  # ZeroDivisionError が発生した場合の処理
  puts "ゼロで除算しようとしました: #{e.message}"
  puts e.backtrace.join("\n") # バックトレース表示

rescue ArgumentError => e
  # ArgumentError が発生した場合の処理
  puts "引数エラー: #{e.message}"

rescue StandardError => e # 一般的なエラーを捕捉 (省略した場合のデフォルト)
  puts "予期せぬエラーが発生しました: #{e.class} - #{e.message}"

else
  # 例外が発生しなかった場合の処理 (rescue節のどれも実行されなかった場合)
  puts "処理は正常に完了しました。"

ensure
  # 例外の発生有無に関わらず、必ず実行される処理
  puts "クリーンアップ処理などを実行します。"
end

例外の発生 (raise)

def check_age(age)
  if age < 0
    raise ArgumentError, "年齢が負の値です: #{age}" # エラーメッセージ付きで発生
  elsif age < 18
    raise "未成年です" # RuntimeError を発生 (メッセージのみ)
  else
    puts "成人です"
  end
end

begin
  check_age(-5)
rescue ArgumentError => e
  puts "エラー捕捉: #{e.message}"
end

begin
  check_age(15)
rescue RuntimeError => e
  puts "エラー捕捉: #{e.message}"
end

retry

rescue節の中で使うと、begin節の最初から処理をやり直します。無限ループにならないよう注意が必要です。

attempts = 0
max_attempts = 3

begin
  attempts += 1
  puts "#{attempts}回目の試行..."
  # 失敗する可能性のある処理
  raise "接続エラー" if attempts < max_attempts
  puts "成功しました!"

rescue => e
  puts "エラー発生: #{e.message}"
  if attempts < max_attempts
    puts "リトライします..."
    sleep(1) # 少し待つ
    retry # begin からやり直し
  else
    puts "最大試行回数に達しました。"
  end
end

メソッド全体での例外処理 (暗黙のbegin)

メソッド定義全体が暗黙的にbeginブロックで囲まれているとみなせます。

def process_file(filename)
  file = File.open(filename)
  # 処理...
  puts "ファイル処理完了: #{filename}"
rescue Errno::ENOENT
  puts "ファイルが見つかりません: #{filename}"
ensure
  file&.close # メソッド終了時に必ず呼ばれる
end

process_file("existent.txt")
process_file("non_existent.txt")

その他 ✨

その他の重要な要素や便利な機能です。

項目 説明 コード例
シンボル (Symbol) :symbol_name の形式。文字列より軽量で、ハッシュのキーや状態を表すのに使われる。内部的には整数。
status = :pending
puts status == :pending # true
config = { db_host: "localhost", db_port: 5432 }
範囲オブジェクト (Range) 連続した値の範囲を表す。.. は終端を含む、... は終端を含まない。
numbers = 1..5   # 1, 2, 3, 4, 5
exclusive = 1...5 # 1, 2, 3, 4
puts numbers.include?(3) # true
puts exclusive.include?(5) # false
('a'..'d').each { |c| print c } # abcd
Proc オブジェクト コードブロックをオブジェクト化したもの。proc, lambda, -> (stabby lambda) で生成。&でブロックとProcを相互変換。
# Proc生成
my_proc = Proc.new { |x| puts "Proc: #{x}" }
my_lambda = lambda { |x| puts "Lambda: #{x}" }
stabby = ->(x) { puts "Stabby: #{x}" }

# 呼び出し
my_proc.call(10)
my_lambda.call(20)
stabby.(30) # .() でも呼び出せる

# lambdaは引数の数に厳密、Procは寛容
# my_lambda.call # エラー
# my_proc.call # エラーにならない (nil が渡される)

# & ブロック引数
def run_block(&block)
  puts "Running block..."
  block.call("from method") if block
end

run_block { |msg| puts "Block executed: #{msg}" }
run_block(&my_proc) # Procオブジェクトをブロックとして渡す
日時 (Time, Date, DateTime) 日時を扱うクラス。DateDateTime を使うには require 'date' が必要。
require 'date'

now = Time.now
puts "Time: #{now}"
puts "Year: #{now.year}"

today = Date.today
puts "Date: #{today}"
puts "Next day: #{today + 1}"

dt_now = DateTime.now
puts "DateTime: #{dt_now}"
puts "Hour: #{dt_now.hour}"

# 書式設定
puts now.strftime("%Y-%m-%d %H:%M:%S") # "2025-04-03 09:12:00" (例)
requireload 他のRubyファイルやライブラリを読み込む。require は一度だけ読み込む(同じファイルを再度 require しても無視される)。load は毎回読み込む。拡張子 .rbrequire では省略可能。
require 'set' # 標準ライブラリのSetクラスを使う
# require_relative 'my_module' # 同じディレクトリ内のmy_module.rbを読み込む

# load 'config.rb' # config.rbを読み込む (実行するたびに再読み込み)
ブロック (Block) do...end または {...} で囲まれたコードの塊。メソッドに渡され、yield で実行されるか、& でProcオブジェクト化される。
# each メソッドにブロックを渡す
[1, 2, 3].each do |n|
  puts n * 10
end

# map メソッドにブロックを渡す (一行なので {} を使用)
squares = [1, 2, 3].map { |n| n**2 }
puts squares.inspect # [1, 4, 9]

コメント

タイトルとURLをコピーしました