How can I set a model to be read-only every time that it is accessed if an attribute within the same model is set to true?
I have looked everywhere and the model read only seems to have very little documentation and even web results.
Edit (Additional Info): I have two methods in my Model (application.rb) - not in private
def lock()
self.locked = true
save(validate: false)
end
def unlock()
self.locked = false
save(validate: false)
end
I call them from my applications controller on update with:
if params[:application][:locked] == false
@application.unlock
return
elsif params[:application][:locked] == true
@application.lock
return
end
and in the Model (application.rb) I have - not in private:
def readonly?
locked == true
end
# app/models/application.rb
# I highly suggest renaming `Application` into something else because, Rails
# already has a same defined constant name `Application` which is defined in your
# app/config/application.rb
class Application < ApplicationRecord
def lock!
# depending on your use-case I'll do an `update` below instead
# self.lock = true
update!(locked: true)
end
def unlock!
# self.lock = false
update!(locked: false)
end
end
# app/models/user.rb
class User < ApplicationRecord
belongs_to :application
def readonly?
# this is still subject to race-condition even though already `reloaded`
application.reload.locked || some_user_attribute == 'HELLO WORLD!'
end
end
# app/models/comment.rb
class Comment < ApplicationRecord
belongs_to :application
def readonly?
# this is still subject to race-condition even though already `reloaded`
application.reload.locked || some_comment_attribute_like_is_disabled?
end
end
Notice that I added a belongs_to
association there because you'll most likely need this because your Application
as you said is actually already a normal model anyway. If you do not have this association, and are setting the locked
internally as a class instance variable of your Application
class (i.e. you have @locked
class instance variable), then (depending on your requirements), you'll have problems with 1) persistency because each request (per different process/server) will default to locked = nil
(which might or might not be a problem to you), and also 2) concurrency because threads share the value of this class instance variable, which means that simultaneous requests would need this @locked
value be evaluated independently; which becomes potentially dangerous if @locked
is set to true
in one thread, while on another @locked
is overidden and is set to false
. But if these are not a problem, I can still update my answer to not use belongs_to :application
; let me know.