I have different sessions in my mongoid.yml
, where one session provides data from a static mongo database. I was wondering if it is possible, to "load" a session in read only mode, so that no changes with save
, create
, destroy
or destroy_all
can be made. My mongoid.yml
looks like this:
production:
sessions:
default:
database: my_app_production
hosts:
- localhost:27017
options:
read: primary
static_content:
database: static_content_db
hosts:
- localhost:27017
options:
read: primary
options:
use_utc: true
I have special models for the static_content
session, they look like this:
class StaticMappings
include Mongoid::Document
include Mongoid::Attributes::Dynamic
store_in collection: "static_mappings", session: "static_content"
end
I want to prevent myself form accidentially calling things like StaticMappings.destroy_all
or a StaticMappings.create(...)
. Is this possible?
I found this Making an entire model read-only with Mongoid, but this won't prevent someone from calling create
or destroy
on a model instance.
That's an old question, but I met the same problem recently, so decided to share. Although, I want to notice, that this is not a per-sesson solution, but a per-model one.
As I figured out, there are two ways to make it possible:
1. Redefine readonly?
If you look through the Mongoid code, you'll see that all functions that save, delete or update, call readonly?
to check if the model is read-only. Not really documented and has a drawback -- create and create! are allowed on this model (destroys, updates, saves won't run though).
private
def readonly?
true
end
2. A custom callback
In addition to the previous method you can add callback(s) to ensure that even creates won't pass through:
before_create :readonly_secret
private
def readonly?
true
end
def readonly_secret
raise Mongoid::Errors::ReadonlyDocument, self.class if readonly?
end
Essentialy, you can get rid of readonly?
method alltogether, and add other callbacks such as before_save
, before_destroy
, before_update
, before_create
Manipulate "readonliness"
if you feel a need to manipulate read-only state from a runtime code, you can define an attribute for your model's class:
before_create :readonly_secret
class << self
attr_accessor :readonly
end
private
def readonly?
self.class.readonly.nil? ? true : self.class.readonly
end
def readonly_secret
raise Mongoid::Errors::ReadonlyDocument, self.class if readonly?
true
end