有没有简单的方法来使Rails的ActiveRecord模型只读?

我希望能够在数据库中创build一个logging,但是阻止Rails从这一点进行更改。 我知道在数据库层面上的变化仍然是可能的。

我相信attr_readonly在属性级别上做我想要的,但我不想手动指定字段…我宁愿有更多的白名单方法。

此外,我知道有一个:read_only选项的关联,但我不想限制对象的“只读”,如果它是通过关联获取或不。

最后,我希望能够继续销毁一个logging,例如:dependent =>:destroy在关联中工作。

所以,总结一下:1)允许创buildlogging,2)允许删除logging,3)防止更改logging已被保留。

看着ActiveRecord::Persistence ,所有事情最终都会在幕后调用create_or_update

 def create_or_update raise ReadOnlyRecord if readonly? result = new_record? ? create : update result != false end 

所以! 只是:

 def readonly? !new_record? end 

我find了一个更简洁的解决scheme,它使用after_initializecallback:

 class Post < ActiveRecord::Base after_initialize :readonly! end 

为什么不只在具有只读访问权限的数据库上创build用户,并且使用该帐户的导轨。

但是,如果您想要访问模型级别,则可以将以下内容添加到特定的模型中:

  def readonly? true end def before_destroy raise ActiveRecord::ReadOnlyRecord end 

此博客文章仍然有效: http : //ariejan.net/2008/08/17/activerecord-read-only-models/

基本上你可以依靠ActiveRecord的validation,如果你添加一个方法:

 def readonly? true end 

TL; OP为OP的DR

 class YourModel < ActiveRecord::Base before_save { false } # prevent create & update, allows destroy # ... end 

通常

  • 为了防止创build: before_create { false }
  • 仅防止更新: before_update { false }
  • 为了防止破坏: before_destroy { false } # does not prevent delete

另见: http : //guides.rubyonrails.org/active_record_callbacks.html

这似乎是相当有效的,可能有点矫枉过正,但对我来说,我真的想确保我的应用程序永远不会创build,保存,更新或销毁模型中的任何logging。

 module ReadOnlyModel def readonly?() true end def create_or_update() raise ActiveRecord::ReadOnlyRecord end before_create { raise ActiveRecord::ReadOnlyRecord } before_destroy { raise ActiveRecord::ReadOnlyRecord } before_save { raise ActiveRecord::ReadOnlyRecord } before_update { raise ActiveRecord::ReadOnlyRecord } end class MyModel < ActiveRecord::Base include ReadOnlyModel # ... end 

由于OP要求能够创build和销毁,但不保存或更新,我相信这将工作

 module SaveAndDestroyOnlyModel before_save { raise ActiveRecord::ReadOnlyRecord } before_update { raise ActiveRecord::ReadOnlyRecord } end class MyModel < ActiveRecord::Base include SaveAndDestroyOnlyModel # ... end 

完全正确的例外,但我认为足够接近。

自定义validation器可以这样做:

 validate :nothing_changed, unless: :new_record? # make immutable ... def nothing_changed errors.add(:base, "Record is read-only") if self.changed? end