Implementing conditional read-only attributes of ActiveRecord objects


#1

Hello,

my goal is to implement the option of specifying a condition in
attr_protected, attr_readonly and possibly other attribute methods in
ActiveRecord objects.

Rationale (example):

class User < AR:Base

User should not be able to modify fields any more once they have

been verified
attr_readonly :firstname, :lastname, :gender_id, :birthdate, :if
=> :passport_verified?

end

or, even better yet, attr_protected with the same options, since this
will allow an admin controller to directly write the attributes while
the “normal” user forms will just ignore them.

The “:if” option should, like in validations, accept a Proc, String,
Symbol or anything the calling object responds to. For validations,
this is currently implemented in activesupport/callbacks.rb in
evaluate_method(), unfortunately in a private method, so we cannot
just call this method.

The idea is that I can tell my custom FormBuilder to check for a
readonly flag on an AR instance object’s attribute, and set the
respective form field to “disabled”, so the user experience is
consistent. This, however, requires that the readonly state is
determined on object creation (or load time) and not only when
validation happens.
So the approach used in “attr_readonly” doesn’t work since it’s a
class method.

I could of course, do something like

ReadonlyAttributes = [:firstname, :lastname, :gender_id, :birthdate]
def is_readonly?(attr)
true if ReadonlyAttributes.include?(attr) and
self.passport_verified?
end
def validate
ReadonlyAttributes.each do |attr|
errors.add(attr, “You cannot change #{attr}!”) if attr.changed?
end
end

only that “changed?” in this context would probably not work since the
object in question would not be “changed”, but newly created from a
params Array.

But also IMHO, this concept should IMHO be extracted into a plugin.
Something like

acts_as_readonly_if :firstname, :lastname, :gender_id, :birthdate, :if
=> :passport_verified?

which would define is_readonly? and extend the validations.

My questions are -

  • does this make any sense?
  • has anything like this perhaps already been done (and if so, where)?
  • would anybody like to help? :wink: Maybe somebody with more Rails plugin
    experience …

Thanks!

Jens