ActiveRecord Validation: based on attribute or function
I am looking for some clarification about what ActiveRecord is actually doing when it performs validation of an instance of a class that inherits from ActiveRecord::Base.
For the purpose of discussion here is an example (you can assume that bar is a column in the foos table generated by an AR migration)
class Foo < ActiveRecord::Base
def bar
read_attribute(:bar).length
end
end
f = Foo.new
f.bar = 'abcdefg'
f.bar => 7
f.read_attribute(:bar) => 'abcdefg'
What I want to understand is when ActiveRecord calls .valid? (or any method that invokes validation) is f.bar validated, or is f.read_attribute(:bar) validated?
Are there some special cases to the answer? For instance when using the uniqueness validator or a custom validator.
Equally important: when AR writes generates the insert or update statement to write the object to the database are the attribute values persisted, or are the values returned from the functions having the names of the table's columns used?
Interesting question, so I experimented.
Validation for presence is on the accessor method f.bar
not on the f.read_attribute(:bar)
However, uniqueness validation will test that a record with bar column value 7
is not in the database, so uniqueness validation will not work as expected.
For uniqueness, you may want to make a custom validation where you test that f.read_attribute(:bar)
is not already present (and that if it is present, it's not the same record)
The custom validator is, of course, custom, so you can explicitly use f.bar
or f.read_attribute(:bar)
depending on which best serves your needs.