有没有简单的方法来使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_initialize
callback:
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