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?)