Best way to model rules in Rails?

I have a Contract class, along the lines of:

class Contract < ActiveRecord::Base   validates_associated :signatures   validates_presence_of :title   # ... end

One or more Conditions might apply to a Contract. Each Condition imposes some kind of restriction or rule on the Contract it applies to. There are about ten different Conditions that may apply. A Contract is invalid if any of its Conditions are not met.

For example, a DurationCondition may specify that a Contract is only valid within some window, while a CreditCheckCondition may specify that a Contract is only valid if all of the signatories have passed a credit check. There may be multiple conditions of a given kind on a Contract. Conditions are permitted to contain other conditions (for example, you may have an OrCondition which is true if at least one of its subordinate Conditions is true).

The current tentative implementation uses STI, but I'm not sure this is the right approach. There are also some issues with getting accepts_nested_attributes_for to instantiate the correct derived Condition type (DurationCondition, etc.) instead of always #new-ing up Conditions.

Given that I'm constrained to a single Postgres datastore, what's the best way to model my Conditions and store this data?

~ jf

So surely a Contract has many Conditions (and that relationship is polymorphic: DurationCondition, CreditCheckCondition, etc)? And you can validate_associated conditions. That way each condition checks itself for validity. The contract shouldn't have anything to do with its conditions' validity - just pass the responsibility down to them.

So surely a Contract has many Conditions (and that relationship is polymorphic: DurationCondition, CreditCheckCondition, etc)?

Correct.

And you can validate_associated conditions. That way each condition checks itself for validity. The contract shouldn't have anything to do with its conditions' validity - just pass the responsibility down to them.

Sure, but what about actually modeling the Conditions themselves? Use STI? Have a #serialize and keep their columns dynamic? etc. They each store very distinct kinds of information.

~ jf

If the data is that different then have each sub-typed model have a child-model for its specific information. For example, I do this for one model this way:

class Attaching < ActiveRecord::Base   belongs_to :file_attachment, :dependent => :destroy   validates_associated :file_attachment end

class AttachingTypeStock < Attaching   belongs_to :stock, :foreign_key => :attached_to_id   def attached_from     self.stock   end end

class AttachingTypePerson < Attaching   belongs_to :person, :foreign_key => :attached_to_id   def attached_from     self.person   end end

class Person < ActiveRecord::Base   has_many :attaching_type_people, :foreign_key => :attached_to_id   has_many :file_attachments, :through => :attaching_type_people end

I could just as easily say that Model has_many Attachings, and that wouldn't matter whether those Attachings were of type Person, or Stock. Each type has its own validation, but shares a common interface, so I can call attaching.attached_from to navigate back up the relationships.

HTH