I’m having difficulty understanding how to make validation of facade
columns consistent with validation of other active record columns. To
illustrate this, I’m going to extend the facade column example
discussed on pp. 284-5 of AWDR. Let’s say that there is a “rectangles”
table that has width and height columns. For some unknown reason,
width is stored in inches and length is stored in cubits. Since I want
the model to expose both measurements in inches, I’ve made length a
facade column as discussed in AWDR:
class Rectangle < ActiveRecord::Base
validates_numericality_of :width, :length
CUBITS_TO_INCHES = 18 def length read_attribute("length") * CUBITS_TO_INCHES end def length=(inches) write_attribute("length", Float(inches) / CUBITS_TO_INCHES) end
Now let’s skip to the controller, and try to validate bogus length and
width values submitted from text fields on a form:
@rect.width = “BOGUS” # validation does not occur yet, and no errors
will be raised
@rect.length = “ALSO BOGUS” # error will be raised immediately
if @rect.save # validation of width occurs here
So the accessor for length will raise an error because of the Float
conversion, while width won’t be marked invalid until validation
occurs in save(). Ideally, we’d like validation of both fields to
populate @rect.errors so that we can present all input errors together
to the user in the view.
The best approach I could come up with was to delay the conversion to
cubits from length=() until the validate() method, although this
required using an instance variable to temporarily store
@length_in_inches. The advantage of this approach is that errors are
no longer raised from length=().
Has anyone found a better approach to this problem?
Thanks in advance.