基礎

Rubyのattr_accessor入門|プロパティの読み書きを簡単にする方法

attr_accessorはインスタンス変数のゲッター(読み取り)とセッター(書き込み)メソッドを自動生成するRubyの便利な機能です。手動でゲッターやセッターを定義する手間を省き、コードを大幅に短縮できます。この記事ではattr_accessorattr_readerattr_writerの使い方と違いを解説します。

基本的な使い方

手動で定義する場合(比較用)

Ruby
# ゲッターとセッターを手動で定義
class UserManual
  def initialize(name, age)
    @name = name
    @age = age
  end

  def name       # ゲッター
    @name
  end

  def name=(val)  # セッター
    @name = val
  end

  def age
    @age
  end

  def age=(val)
    @age = val
  end
end

user = UserManual.new('太郎', 25)
puts user.name
user.name = '次郎'
puts user.name
実行結果
太郎
次郎

attr_accessorで自動生成

attr_accessorを使うと、上記のゲッター・セッターをたった1行で自動生成できます。

Ruby
class User
  attr_accessor :name, :age

  def initialize(name, age)
    @name = name
    @age = age
  end
end

user = User.new('太郎', 25)
puts user.name    # ゲッター
puts user.age

user.name = '花子'  # セッター
user.age = 22
puts "#{user.name}(#{user.age}歳)"
実行結果
太郎
25
花子(22歳)

attr_accessor :name, :ageの1行で、name/name=age/age=の4つのメソッドが自動的に定義されます。

3つのアクセサの違い

Ruby
class Product
  attr_accessor :name    # 読み書き両方
  attr_reader :id        # 読み取りのみ
  attr_writer :stock     # 書き込みのみ

  def initialize(id, name, stock)
    @id = id
    @name = name
    @stock = stock
  end

  def info
    "ID:#{@id} #{@name}(在庫:#{@stock})"
  end
end

product = Product.new(1, 'ノートPC', 10)

# attr_accessor: 読み書き可能
puts product.name
product.name = 'ゲーミングPC'
puts product.name

# attr_reader: 読み取りのみ
puts product.id
# product.id = 2  # エラー!書き込み不可

# attr_writer: 書き込みのみ
product.stock = 5
# puts product.stock  # エラー!読み取り不可

puts product.info
実行結果
ノートPC
ゲーミングPC
1
ID:1 ゲーミングPC(在庫:5)

attr_readerは読み取り専用(ゲッターのみ生成)、attr_writerは書き込み専用(セッターのみ生成)、attr_accessorは両方を生成します。

実践的な使い方

Ruby
class Employee
  attr_accessor :name, :department
  attr_reader :id, :hire_date

  def initialize(id, name, department)
    @id = id
    @name = name
    @department = department
    @hire_date = '2026-02-19'
  end

  def to_s
    "[#{@id}] #{@name}(#{@department})入社日: #{@hire_date}"
  end
end

employees = [
  Employee.new(1, '田中太郎', '開発部'),
  Employee.new(2, '佐藤花子', '営業部'),
  Employee.new(3, '鈴木次郎', '開発部')
]

employees.each { |e| puts e }

puts '---'

# 部署変更
employees[1].department = '企画部'
puts "#{employees[1].name}の部署を変更: #{employees[1].department}"

# IDは変更不可(attr_reader)
# employees[0].id = 99  # NoMethodError
実行結果
[1] 田中太郎(開発部)入社日: 2026-02-19
[2] 佐藤花子(営業部)入社日: 2026-02-19
[3] 鈴木次郎(開発部)入社日: 2026-02-19
---
佐藤花子の部署を変更: 企画部
attr_readerを積極的に使おう

変更される必要がない属性にはattr_readerを使いましょう。IDや作成日時などは一度設定したら変更すべきでないため、読み取り専用にすることでバグを防げます。デフォルトはattr_readerにし、必要な場合のみattr_accessorにするのがベストプラクティスです。

カスタムセッターが必要な場合

バリデーション(値の検証)を行いたい場合はattr_accessorではなくセッターメソッドを手動で定義します。例えば、年齢に負の数を入れさせないなどの制約を加える場合は、def age=(val)を自分で書きましょう。

まとめ

  • attr_accessorはゲッターとセッターを自動生成する(読み書き可能)
  • attr_readerはゲッターのみ(読み取り専用)
  • attr_writerはセッターのみ(書き込み専用)
  • 変更不要な属性にはattr_readerを使うのがベストプラクティス
  • バリデーションが必要な場合はセッターを手動で定義する