RailsのActiveModelでもattr_accessorは使える

バックエンド

何についての記事か

当たり前のことをタイトルにしましたが、意外と盲点だったので、記事にまとめます。
RailsのActiveModelでattr_accessorを利用することで得られるメリットについて考えられたらなと思ってます。

一応attr_accessorについて知らない方向けに軽い説明も末尾に記載いたします。

使い方

ActiveModelでattr_accessorはこんな感じで、普通に使えます。
ActiveModelがクラスなので、当然なんですが。。。

class User < ApplicationRecord
  attr_accessor :name
end

この例のようにnameなどの変数はテーブルにカラムとして用意することが多いため、attr_accessorを使うことはないと思います。
なので、ActiveModelでattr_accessorを使うべきケースを考えてみたいと思います。

ActiveModelでattr_accessorを使うべき状況

フラグとして

1つ目はフラグとしての用途です。
例えば、1度だけ実行すれば良い処理があるとして、その処理が実行済みであることを保存しておく用途です。

例えば、以下のコードのようにUserクラスにパスワードを初期化するメソッドが複数箇所存在しているとします。
すでに他のメソッドでパスワードリセットが済んでいる場合、2回目は実施しないということがフラグを用いて実現できています。
その処理中にパスワードをリセットしたかという情報はわざわざテーブルに残さないので、フラグとして管理するのが適切だと思います。

class User < ApplicationRecord
  attr_accessor :is_completed_password_reset

  def reset_auth
    self.password = "initial_password" unless @is_completed_reset_password
    self.login_id = "initial_login_id"
    @is_completed_password_reset = true
  end

  def reset_password
    self.password = "initial_password" unless @is_completed_reset_password
    @is_completed_reset_password = true
  end
end

同じ処理ならメソッドを使いまわせばいいですし、値代入くらいなら複数回実施しても問題ないですが、
これはただ例が悪いだけです。思いつきませんでした。。

メモ化として

重い演算があったとして、実行結果のメモ化用変数としても十分適切だと思います。

以下の例では、very_very_long_taskは呼び出すたびに演算を実施するのではなく、2度目以降は1度目の結果を使いまわしています。

class User < ApplicationRecord
  attr_accessor :results

  def very_very_long_task
    return results if results.exists?
    # めちゃくちゃ時間がかかる処理
    @results = xxxxx
    return @results
  end
end

メソッドに呼び出す順序を指定したい時

メソッドを定義する際に、このメソッドはあのメソッドを実施していること前提なんだよなって時に使えます。

class User < ApplicationRecord
  attr_accessor :is_processed

  def pre_processor
    # 事前にこの関数を読んでおきたい
    @is_processed = true
  end

  def main_processor
    pre_processor unless @is_processed
    # 処理
  end

end

注意点

attr_accessorはインスタンス変数を宣言する関数です。
そのため、異なるインスタンス間では値が共有されないことに注意が必要です。

もし異なるインスタンス間や、タスク間で値を共有したい場合は、テーブルにカラムを追加するや、redisなどのストレージを検討する必要があります。

attr_accessorとは

まず、attr_accessorについてです。attr_accessorはクラスにフィールドを追加するメソッドです。
以下のように使用することができます。

class User
  attr_accessor :name
end

hanako = User.new
hanako.name = "hanako"
puts hanako.name
# => hanako

このような感じでUserクラスにnameというフィールドを追加し、name=.nameという感じで利用することができるようになります。

rubyは動的型付け言語なので、変数を宣言しなくても例えば以下のように@を接頭辞とすることで、変数に値を格納・取得することは可能です。

class User
  def set_name(str)
    @name = str
  end

  def name
    @name
  end
end

hanako = User.new
hanako.set_name("hanako")
puts hanako.name
# => hanako

しかしながら、クラスが長くなると、そのクラスがどんな変数を持っているのか一目で分かりづらくなってしまいます。また、全ての変数について格納用関数(セッター)と取得用変数(ゲッター)を作成するのは面倒です。
そこで、attr_accessorを使えば一箇所で変数一覧を記述することができ、便利だねって感じです。

attr_accessorには他にも類似メソッドがあります。

メソッド外部から書き込み可能外部から読み取り可能
attr_accessor
attr_writer×
attr_reader×
タイトルとURLをコピーしました