Order of Validation for Associated Models

I have an Account Model. It has a polymorphic association to an
Address model. The Address model validates on what you'd expect, and
the the issue comes about in the order of models and validations.

We are trying to wedge functionality into an existing design without
breaking a large system. The new requirement is that the address is
only validated if a boolean column (is_admin_account) is false.

Where I'm running into issue is that the Address model validates
before the values are updated in the Account model and, based on the
bool value, I want to validate or not.

The application uses InheritedResources, but I completely over-rode
the create and update functions to bypass this with the same result.
I'm not sure exactly where to dig into this. I considered a custom
validation function, but don't want to pitch the standard validations
that exist (and work with the biz rules as they stand).

Anyone have a good place for me to start?

Thanks in advance!

Ray Parker wrote in post #966033:

I have an Account Model. It has a polymorphic association to an
Address model. The Address model validates on what you'd expect, and
the the issue comes about in the order of models and validations.

We are trying to wedge functionality into an existing design without
breaking a large system.

How's your test coverage? If it's decent, you shouldn't need to worry
about breaking the system, or about "wedging in" functionality.

(The idea of "wedging in" functionality is itself scary. If something
is worth doing, it's usually worth doing right, with all the refactoring
that that implies.)

The new requirement is that the address is
only validated if a boolean column (is_admin_account) is false.

And which table is that field in?

(Style note: it's more Rubyish to leave the "is_" off the names of
booleans.)

Where I'm running into issue is that the Address model validates
before the values are updated in the Account model and, based on the
bool value, I want to validate or not.

So you want to validate the address, or not, depending on the contents
of a field in an associated record in a different table? That sounds
really, really smelly to me. I suspect it might be worth moving the
validation flag into the addresses table.

If you can explain more about the structure of your data, I can probably
be more helpful.

Best,

I agree, but there are a couple of issues with that. One is that the
flag would be so deep and obscured from the actual function of it that
it would be most magical. The flag is already one level deeper than
I'd prefer it to be. My design chops are pretty fair and this is the
best dress we can put on the pig. Second is that this database is not
my design, nor the application, and with 1000's of lines of code that
go in some pretty intense reporting, changing the structure in a way
that would satisfy the client's request elegantly would far outstrip
any budget that is allotted for the current iteration. If you'd
really like a rundown on the problem and our solution we can share
screens on Skype and I'll convince you that the solution is the
cleanest, given budget and requirement. Though application design
isn't really the question.

The 'is' prefix and its ilk for a bool field or function has been
working for me for 20 years and around 9 languages. I love Ruby and
Rails, but given that wisdom is having the experience to recognize a
mistake as you're about to make it again, I'll reserve the right to
adopt what is arguably better and ignore that which is not.

That said, and a bit exhausted from defending the irrelevant...how's
'bout that question?

Where I'm running into issue is that the Address model validates
before the values are updated in the Account model and, based on the
bool value, I want to validate or not.

I'm not sure what you mean by "the Address model validates before the
values are updated in the Account model" - can you extract some model
code to illustrate?

Anyone have a good place for me to start?

It occurs to me, that if an Address can be different depending on the
model it's associated with, the validation check needs to move to the
associated model maybe. How about adding something like this to
Account:

  validates :valid_address if :address

  private
  def valid_address
    errors.add_to_base "address is not valid for one reason or
another" unless address.valid_for_account
  end

... and this to Address:

  def valid_for_account
    return true if self.post_code.nil?
    return true if self.some_other_validation_check_returns_true
    return true if self.etc
  end

You could merge the Errors from Address into Account, rather than just
adding a generic one to base, to display "nice" messages to the user.
http://dev.rubyonrails.org/attachment/ticket/11394/merge_bang_errors.patch

We've scrapped the validations on Address in the project as it wasn't
important to the biz model. Here's some sudo-code (good pun?)