Hi,
QUESTION: How can establishing validation that spans multiple models be achieved in Rails? That is in such a fashion that it is not possible for a developer to break the validation via using any of the public model methods (e.g. update_attribute, save, create etc).
EXAMPLE:
- Concept: MAGAZINE can contain multiple ARTICLES, and an ARTICLE can be associated with multiple MAGAZINE (i.e. many to many). Cost of Magazine = Sum(Cost of Articles)
- Tables: (a) magazines (has “cost” field) (b) articles_magazines (to map the many-to-many) (c) articles (has “total_cost” field)
BUSINESS RULE to be implemented: Not possible for a database update that would end up with a Magazine’s “total_cost” not being equal to the Sum(associated articles "cost"s)
ISSUES / QUESTIONS: (1) Assume would not try to implement rules at database constraint level??? (2) Use of Model “before_create” - but I’m assuming here if the Article is generated (Article.new), and then validation occurs, the code has NOT yet got to the bit where it updates the Magazine? (3) Use of “after_create” - Add a check for both Magazine and Article perhaps here, noting the database record has been created by transaction NOT finalised yet. So would the following be the best way:
-----example------- class Magazine < ActiveRecord::Base after_save :business_rule_validation def business_rule_validation sum_of_articles = << INSERT code that calculates SUM of Articles costs for all articles that are associated with the Magazine >> errors.add_to_base(“business rules fail”) if self.total_cost != sum_of_articles end end
class Article < ActiveRecord::Base << Add Same Concept as per Magazine >> end -----example-------
BUT wouldn’t this fail, as it assumes the Article create/update/delete and the Magazine create/update/delete is in the SAME transaction no??? Does this mean you really have to create an overarching facade that handles creates/updates/deletes for Article/Magazines and somehow hide the normal per model save/update/delete???