是否有一种简单的方法使Rails ActiveRecord模型成为只读的?

时间:2022-06-01 20:26:53

I want to be able to create a record in the DB but then prevent Rails from making changes from that point on. I understand changes will still be possible at the DB level.

我希望能够在DB中创建一个记录,但是这样就可以防止Rails从那时起进行更改。我知道在DB级别上仍然可以进行更改。

I believe attr_readonly does what I want on an attribute level, but I don't want to have to manually specify fields... I would rather have more of a white-list approach.

我相信attr_readonly在属性级别上做了我想做的事情,但是我不想手工指定字段……我宁愿有更多的白名单。

Also, I know there is a :read_only option for associations, but I don't want to limit the "readonlyness" of the object to if it was fetched via an association or not.

另外,我知道有一个:read_only选项用于关联,但是我不想限制对象的“readonlyness”,如果它是通过关联来获取的。

Finally, I want to be able to still destroy a record so stuff like :dependent => :destroy works in the associations.

最后,我希望仍然能够销毁一个记录,比如:dependency =>:destroy works in the associations。

So, to summarize: 1) allow the creation of records, 2) allow the deletion of records, and 3) prevent changing records that have been persisted.

因此,总结:1)允许创建记录,2)允许删除记录,3)防止更改保存的记录。

7 个解决方案

#1


70  

Looking at ActiveRecord::Persistence, everything ends up calling create_or_update behind the scenes.

查看ActiveRecord::持久性,所有东西都在后台调用create_or_update。

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

So! Just:

如此!只是:

def readonly?
  !new_record?
end

#2


37  

I've found a more concise solution, which uses the after_initialize callback:

我找到了一个更简洁的解决方案,它使用after_initialize回调:

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

#3


25  

Why not just create a user on the database that has read only access, and have rails use that account.

为什么不直接在数据库上创建一个只有读权限的用户,并让rails使用这个帐户呢?

However if you want model level access, you can add the following to a specific model:

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

 def readonly?
    true
  end

  def before_destroy
    raise ActiveRecord::ReadOnlyRecord
  end

#4


13  

This blog post is still valid: http://ariejan.net/2008/08/17/activerecord-read-only-models/

这篇博文仍然有效:http://ariejan.net/2008/08/17/activerecord- read-onmodels/

Basically you can rely on ActiveRecord's validation if you add a method:

基本上,如果你添加一个方法,你可以依赖ActiveRecord的验证:

def readonly?
  true
end

#5


4  

TL;DR for OP's

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

  # ... 
end

Generally

  • To prevent creates only: before_create { false }
  • 要防止只创建:before_create {false}
  • To prevent updates only: before_update { false }
  • 仅防止更新:before_update {false}
  • To prevent destroys only: before_destroy { false } # does not prevent delete
  • 要防止仅破坏:before_destroy {false} #不阻止删除

See also: http://guides.rubyonrails.org/active_record_callbacks.html

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

#6


1  

This seems to be fairly effective and is probably a bit overkill, but for my case, I really want to be sure my application will never create, save, update, or destroy any records in the model, ever.

这似乎相当有效,而且可能有点过了头,但对于我来说,我真的希望确保我的应用程序永远不会创建、保存、更新或销毁模型中的任何记录。

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

Since OP asked to be able to create and destroy but not save or update I believe this will work

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

module SaveAndDestroyOnlyModel
  before_save { raise ActiveRecord::ReadOnlyRecord }
  before_update { raise ActiveRecord::ReadOnlyRecord }
end

class MyModel < ActiveRecord::Base
  include SaveAndDestroyOnlyModel
  # ...
end

Not exactly the right exception, but close enough I think.

不完全是正确的例外,但我认为已经足够接近了。

#7


0  

A custom validator can do this:

一个自定义验证器可以这样做:

validate :nothing_changed, unless: :new_record? # make immutable

...

def nothing_changed
  errors.add(:base, "Record is read-only") if self.changed?
end

#1


70  

Looking at ActiveRecord::Persistence, everything ends up calling create_or_update behind the scenes.

查看ActiveRecord::持久性,所有东西都在后台调用create_or_update。

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

So! Just:

如此!只是:

def readonly?
  !new_record?
end

#2


37  

I've found a more concise solution, which uses the after_initialize callback:

我找到了一个更简洁的解决方案,它使用after_initialize回调:

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

#3


25  

Why not just create a user on the database that has read only access, and have rails use that account.

为什么不直接在数据库上创建一个只有读权限的用户,并让rails使用这个帐户呢?

However if you want model level access, you can add the following to a specific model:

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

 def readonly?
    true
  end

  def before_destroy
    raise ActiveRecord::ReadOnlyRecord
  end

#4


13  

This blog post is still valid: http://ariejan.net/2008/08/17/activerecord-read-only-models/

这篇博文仍然有效:http://ariejan.net/2008/08/17/activerecord- read-onmodels/

Basically you can rely on ActiveRecord's validation if you add a method:

基本上,如果你添加一个方法,你可以依赖ActiveRecord的验证:

def readonly?
  true
end

#5


4  

TL;DR for OP's

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

  # ... 
end

Generally

  • To prevent creates only: before_create { false }
  • 要防止只创建:before_create {false}
  • To prevent updates only: before_update { false }
  • 仅防止更新:before_update {false}
  • To prevent destroys only: before_destroy { false } # does not prevent delete
  • 要防止仅破坏:before_destroy {false} #不阻止删除

See also: http://guides.rubyonrails.org/active_record_callbacks.html

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

#6


1  

This seems to be fairly effective and is probably a bit overkill, but for my case, I really want to be sure my application will never create, save, update, or destroy any records in the model, ever.

这似乎相当有效,而且可能有点过了头,但对于我来说,我真的希望确保我的应用程序永远不会创建、保存、更新或销毁模型中的任何记录。

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

Since OP asked to be able to create and destroy but not save or update I believe this will work

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

module SaveAndDestroyOnlyModel
  before_save { raise ActiveRecord::ReadOnlyRecord }
  before_update { raise ActiveRecord::ReadOnlyRecord }
end

class MyModel < ActiveRecord::Base
  include SaveAndDestroyOnlyModel
  # ...
end

Not exactly the right exception, but close enough I think.

不完全是正确的例外,但我认为已经足够接近了。

#7


0  

A custom validator can do this:

一个自定义验证器可以这样做:

validate :nothing_changed, unless: :new_record? # make immutable

...

def nothing_changed
  errors.add(:base, "Record is read-only") if self.changed?
end