Search code examples
ruby-on-railsvalidationmodel-associations

Validating grandparent: two parents have the same parent?


So I'm writing an app with the following models and associations:

class Company < ActiveRecord::Base
  has_many :customers, :dependent => :destroy
  has_many :goals, :dependent => :destroy
end

class Customer < ActiveRecord::Base
  belongs_to :company
  has_many :tasks
  has_many :goals, through: :tasks
end

class Goal < ActiveRecord::Base
  has_many :tasks, :dependent => :destroy
  belongs_to :company
  has_many :customers, through: :tasks
end

class Task < ActiveRecord::Base
  belongs_to :goal
  belongs_to :customer
end

Now in the view, a form_for a new task already has the goal or customer selected and the other association select is a filtered set based on the other model. Theoretically it's impossible for the user to create a task under two different companies, i.e. the @task.goal.company == @task.customer.company.

But it seems like good practice to have a validation to check that there is only one grandparent. I understand using a Proc.new you can validate if a certain criteria is met but I want it to always validate so this isn't the solution I'm looking for.

Thanks.

BTW let me know if the model structure looks ridicules or if I've done something clearly against rails convention.


Solution

  • A proc.new and a method are exactly equivalent in terms of validation. That said, you're probably looking for something like this:

    class Task < ActiveRecord::Base
      belongs_to :goal
      belongs_to :customer
    
      validate :companies_match
    
      private
    
      def companies_match
        self.errors.add(:base, "Goal company and customer company must be equivalent") unless goal.company == customer.company
      end
    end