Not allowing changes to be made to e.g. the login of the user only by the UI is in my eyes not enough.
The model should also ensure, that changes cannot be made once assigned.
So i tried to find an validation that does this for me.
But the once i found did not quite work as i expected.
So i wrote my own that i want to share:
class User < ActiveRecord::Base
validates_unchangeable :login
end
unchangeable_validation.rb
require 'active_support/concern'
require 'active_model'
require 'active_record/base'
module UnchangeableValidation
extend ActiveSupport::Concern
class UnchangeableValidator < ActiveModel::EachValidator
def initialize(options)
super(options)
end
def validate_each(object, attribute, value)
if(!object.new_record? && value.present?)
abChanged = attribute.to_s + "_changed?"
if(object.send(abChanged.to_sym))
object.errors[attribute] << (options[:message] || "cannot be changed once assigned")
end
end
end
end
module ClassMethods
def validates_unchangeable(*attr_names)
validates_with UnchangeableValidation::UnchangeableValidator, _merge_attributes(attr_names)
end
end
end
ActiveRecord::Base.send(:include, UnchangeableValidation)
unchangeable_validation_test.rb
require 'test_helper'
class UnchangeableValidationTest < ActiveSupport::TestCase
def test_login_unchangeable
instance = User.new
instance.login = "login"
instance.save!
instance.login = "changed"
instance.save
assert_equal instance.errors[:login].first, "cannot be changed once assigned"
end
end