ActiveRecord の特定モデルを ReadOnly にしたい

ActiveRecord に用意されているものが一部の挙動にしか効果がない
漏れがないか不安になるが頑張って封じるモジュールを作るしかなさそう

`lib/autoload/active_record_read_only.rb` あたりに配置して

```ruby
module ActiveRecordReadOnly
  extend ActiveSupport::Concern

  # ActiveRecord::ReadOnlyRecord エラーで rollback されるはずだが
  # 無駄に動かす必要もないのでもないので封じる
  included do
    before_save { self.class.raise_readonly! }
    before_create { self.class.raise_readonly! }
    before_update { self.class.raise_readonly! }
    before_destroy { self.class.raise_readonly! }
  end

  # 基本の ReadOnly 制御
  def readonly?
    true
  end

  # touch を封じる
  # 下記理由によりこれだけでは不足だが判定関数と実挙動を一致させるため上書き
  def no_touching?
    true
  end

  # touch を封じる
  # no_touching? で封じるだけだとエラーにならないので直接封じる
  def touch
    self.class.raise_readonly!
  end

  module ClassMethods
    # update_column や update_columns など readonly? 判定のないカラム指定処理を封じる
    def readonly_attributes
      attribute_names
    end

    # readonly? 判定のない単独処理なので直接封じる
    def delete(_id)
      raise_readonly!
    end

    # 一括操作でありカラムも指定しない処理なので直接封じる
    def delete_all
      raise_readonly!
    end

    # 一括操作でありカラムも指定しない処理なので直接封じる
    def update_all(_attributes)
      raise_readonly!
    end

    def raise_readonly!
      raise ActiveRecord::ReadOnlyRecord,
            "#{name}.included ActiveRecordReadOnly"
    end
  end
end
```

include するだけ

```ruby
class User < ApplicationRecord
  include ActiveRecordReadOnly
end
```

封鎖できてる

```irb
[1] pry(main)> ActiveRecord::Base.logger = nil
=> nil
[2] pry(main)> User.first.destroy
ActiveRecord::ReadOnlyRecord: User.included ActiveRecordReadOnly
from /app/lib/autoload/active_record_read_only.rb:52:in `raise_readonly!'
[3] pry(main)> User.first.update(code: 'test')
ActiveRecord::ReadOnlyRecord: User.included ActiveRecordReadOnly
from /app/lib/autoload/active_record_read_only.rb:52:in `raise_readonly!'
[4] pry(main)> User.first.update_columns(code: 'test')
ActiveRecord::ActiveRecordError: code is marked as readonly
from /usr/local/bundle/gems/activerecord-6.0.0/lib/active_record/persistence.rb:947:in `verify_readonly_attribute'
[5] pry(main)> User.first.update_column(:code, 'test')
ActiveRecord::ActiveRecordError: code is marked as readonly
from /usr/local/bundle/gems/activerecord-6.0.0/lib/active_record/persistence.rb:947:in `verify_readonly_attribute'
[6] pry(main)> User.first.touch
ActiveRecord::ReadOnlyRecord: User.included ActiveRecordReadOnly
from /app/lib/autoload/active_record_read_only.rb:52:in `raise_readonly!'
[7] pry(main)> User.create(code: 'test')
ActiveRecord::ReadOnlyRecord: User.included ActiveRecordReadOnly
from /app/lib/autoload/active_record_read_only.rb:52:in `raise_readonly!'
[8] pry(main)> User.delete(1)
ActiveRecord::ReadOnlyRecord: User.included ActiveRecordReadOnly
from /app/lib/autoload/active_record_read_only.rb:52:in `raise_readonly!'
[9] pry(main)> User.delete_all
ActiveRecord::ReadOnlyRecord: User.included ActiveRecordReadOnly
from /app/lib/autoload/active_record_read_only.rb:52:in `raise_readonly!'
[10] pry(main)> User.update_all(code: 'test')
ActiveRecord::ReadOnlyRecord: User.included ActiveRecordReadOnly
from /app/lib/autoload/active_record_read_only.rb:52:in `raise_readonly!'
```

## 【追記補足】コールバック封鎖の意図

モデル本体に適用する場合は封鎖後に定義できるので意味がありませんでした
下記のような閲覧用の継承モデルに分離する場合を想定しています

```ruby
class User < ApplicationRecord
  before_create -> { }
end

class ReadOnlyUser < User
  include ActiveRecordReadOnly
end
```