0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ActiveRecord カラムのプライベート化

Last updated at Posted at 2023-05-16

はじめに

DB で利用しないカラムが発生して、プライベート化するということで他の方が対応していた

コードレビュー時に「ほんとにこれでいいの?」と思ったので検証および問題点の対応策を考えてみました

ActiveRecord のカラムについて

ActiveRecordは、Ruby on Railsの一部であり、
オブジェクト指向型データベースマッピングの実装を提供します

ActiveRecordを使用すると、
データベーステーブルの行が Ruby オブジェクトとして扱われます

ActiveRecordモデルのカラムには、
通常publicアクセス権が与えられており、どの部分からでもアクセスすることができます

他の方の対応内容

ActiveRecordでは、モデルクラスの各カラムには通常、
自動的にアクセサメソッドが定義されます

しかし、その中にはDB上で利用しなくなってしまったカラムが含まれる場合があります

このような場合、アクセサメソッドをprivateにすることで、
予期せぬ変更が加えられるのを防止することができます

検索してもこのような内容が多くでてきます

class Sample < ApplicationRecord
  private
  attr_accessor :unused_column
end

問題点

attr_accessorprivateにしても、クラス外からはアクセスできませんが、
ハッシュ構造でアクセスする場合はprivate化が効果を発揮しません。

class Sample < ApplicationRecord
  private
  attr_accessor :unused_column
end

sample = Sample.new()
sample.unused_column = "foo" # => NoMethodError (private method `unused_column=' called for #<Sample:0x00007fd0cc104e10>)
sample[:unused_column] = "foo"

解決策

hash アクセスを禁止する

[]=メソッドをオーバーライドして、ハッシュアクセス自体を禁止することで、
privateなカラムを保護することができます。

class Sample < ApplicationRecord
  private
  attr_accessor :unused_column

  def []=(key, value)
    raise 'Hash access is not allowed' if key == :unused_column

    super
  end
end

影響範囲

テストコードのデータ生成にFactoryBotを使用している場合には影響があります

FactoryBotではcreate時にunused_column=のメソッドが呼び出されるため、
別の方法を使用する必要があります

例えば、以下のようにtraitを定義することで、
create時にunused_columnに値を設定することができます

class Sample < ApplicationRecord
  def []=(key, value)
    raise 'Hash access is not allowed' if key == :unused_column

    super
  end

 private
 attr_accessor :unused_column
end

FactoryBot.define do
  factory :sample do
    trait 'unused_column_foo' do
      before(:build) do |sample|
        sample.send('unused_column=', 'foo')
      end
    end
  end
end

以下のようにcreateメソッドを使用してサンプルオブジェクトを作成することができます

sample = FactoryBot.create(:sample, :unused_column_foo)

おわりに

RailsにおけるActiveRecordカラムのプライベート化についてまとめてみました

これによって、モデルのカラムを適切に保護し予期しない変更を防ぐことができます

色々な事情でDBの構造の変更が難しいケースの場合の参考になれば

0
0
1

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?