Railsでのマスターデータ用モデルの管理


外部キーをかけられるなどで、マスターデータをDBに置いておくことも多いですが、モデルとしてハンドリングする際には注意したいことがあります。

…何もしなければ、ふつうのActiveRecordメソッドで、マスターデータの変更ができてしまいます

権限の不在

本来、アプリケーションから使うデータベースアカウントと、データベースの構築に使うアカウントは分けて、必要な権限だけを与えるべきものでしょうが、RailsやWordPressなど「データベースの構築まで自動で行うような環境」下では、それは理想論に近い扱いとなってしまいます1。ということで、「DBレベルでマスター系の書き換えを抑止する」という手段は、いったん置いておくことにします。

リードオンリーにはできる、けど

実は、ActiveRecord標準で、リードオンリーとする方法があります。

class Something < ActiveRecord::Base
  def readonly?
    true
  end
end

readonly?はレコード単位で設定できますが、常にtrueを返すようにしてしまえば、あとは書き込みのできないActiveRecordとなります。

これで一件落着と思いきや、もう1つ問題があって、このままだとRails内から初期データを入れられなくなってしまいます。

切り替え可能なreadonly

ということで、初期データのロード時にはreadonlyを外したくなります。そういう用途にぴったりなgemとして、garysweaver/activerecord-be_readonlyがありました。

まず、マスターにするレコード側では、宣言的なメソッドのbe_readonlyが用意してあって、これでモデルのリードオンリーがかかります。そして、初期データのロード時にはどうするのかというと、BeReadonly.enabled = falseとすれば、それだけですべてのbe_readonlyが無効となります。自分自身はseed_fuを使っていたので、db/fixtures/00_initialize.rbのように、ASCII順で先頭へ来るファイルを作っておいて、そこでBeReadonly.enabled = falseとすることで、seed_fu中にはbe_readonlyも支障しなくなります。


  1. Railsの場合、環境変数で接続を切り替えるなんて手もあるようですが、あまり普及しているとは言いづらいです。