6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

attr_readerがActiveRecordのカラムをnilにする理由

Last updated at Posted at 2025-12-14

はじめに

こんにちは! @Yu_yukk_Y です。
突然ですが、ActiveRecordモデルにDBカラムと同じ名前のattr_readerを設定すると何が起きるか知っていますか?
なんと、そのカラムは確定でnilが返されるようになるのです!

具体的には、下記のようなモデルがあった時textカラムが確定でnilになります。

class Memo < ApplicationRecord
  attr_reader :text
end

memo = Memo.first
memo.text  # => nil(DBに値があっても nil が返る)

この記事では、初心者の自分がびっくりした上記の挙動について、内部では何が起きていたのかを探っていきます。

Rubyのattr_readerの挙動

Rubyのattr_readerでは、指定された名前に対して下記のようなメソッドを生成します

def text
  @text
end

つまり、attr_readerを指定してカラムにアクセスする場合、内部的にはそのカラム名のメソッド経由でインスタンス変数にアクセスしているのです。

ActiveRecordのカラムの挙動

まず、ActiveRecordでアクセスするDBカラムはそのカラム名(@カラム名)のインスタンス変数には保存されません。
実際には内部の@attributes変数(ActiveModel::AttributeSet)に保存されます。

そして、下記のような処理で属性名のメソッドを作成し、@attributes変数から指定された値を読み取っているのです。

なぜattr_readerで指定したカラムはnilになったのか

Rubyのメソッドの探索順序の優先度が
attr_reader > includeされたメソッド
だからです。
また、ActiveRecordでは@カラム名のインスタンス変数に値を保存しないため、常にnilが返されていたのでした。

それぞれのカラム読み込みの仕組みさえわかればあとはシンプルですね!

ちなみにどうしてもDBカラムと同名のattr_readerを設定する必要がある場合、DBカラムはread_attributeというメソッドを用いることで読み取ることができます。

余談

ActiveRecordモデルにおいて、DBカラムと同名のattr_readerが設定されているとattr_readerによって生成されたメソッドが優先されることがわかりました。
では、そもそもActiveRecordによるメソッド生成は行われているのでしょうか?

実は、attr_readerが設定されていてもメソッドの生成は行われます。
attr_readerによって作成されたメソッドを動的に削除することで確かめることができます。

adcale2025(dev)> Memo.first.text
  Memo Load (0.3ms)  SELECT "memos".* FROM "memos" ORDER BY "memos"."id" ASC LIMIT 1 /*application='Adcale2025'*/
=> nil
adcale2025(dev)> Memo.class_eval { remove_method :text  }
=> Memo(id: integer, text: string, created_at: datetime, updated_at: datetime)
adcale2025(dev)> Memo.method_defined? :text
=> true
adcale2025(dev)> Memo.first.text
  Memo Load (0.3ms)  SELECT "memos".* FROM "memos" ORDER BY "memos"."id" ASC LIMIT 1 /*application='Adcale2025'*/
=> "from ActiveRecord"

まとめ

今回の記事ではActiveRecordモデルにDBカラムと同じ名前のattr_readerを設定したときの挙動について深掘りしました。
アドカレという機会を借りて以前から気になっていたことを調査できてよかったです!
また、今回の調査ではDeepWikiをフル活用しました!AIの力で大規模なソースコードを効率的に探索できるので大変便利でありがたいです🙌

6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?