1

I have a model Todo with self referential parents and children

has_and_belongs_to_many :children, class_name: "Todo", join_table: "todos_todos", foreign_key: "parent_id", association_foreign_key: :child_id
has_and_belongs_to_many :parents, class_name: "Todo", join_table: "todos_todos", foreign_key: "child_id", association_foreign_key: :parent_id

I want do something like before_add on both of them that will throw a validation error. I've tried before_add: [:parent_due_after_or_on_self] with

def parent_due_after_or_on_self(parent)
    if parent.due < self.due 
        self.errors.add(:parents, "Parent cannot be due before child")
    end 
end 

But that does nothing. I've tried adding raise "Parent cannot be due before child" right after adding the error, and that gets me the error message, but now I can't rescue it to return the user to the form to fix their mistake. I'm positive I got this working earlier this week, but I've lost the code and can't remember what it was exactly.

daraul
  • 174
  • 5
  • 16

1 Answers1

0

As @meagar♦ wrote in Rails 4 HABTM custom validation on associations, there is no valid way to use validations on HABTM associations.

In my opinion, the best option is to use has_many :through =>, and use your connecting model (in your case TodosTodo) for validations.

Community
  • 1
  • 1
Shalev Shalit
  • 1,945
  • 4
  • 24
  • 34
  • TodosTodos isn't another model, but just a join table. If I switch to something like `has_many :parents, class_name: "Todo", :through => TodosTodos` will I be able to perform validations on add like I want to? – daraul Feb 12 '16 at 18:11
  • Rails associations guide tells me "If a before_add callback throws an exception, the object does not get added to the collection". Couldn't I do this instead? Something like `raise "Parent not added"`? – daraul Feb 12 '16 at 18:14
  • First of all, you can create a TodosTodos model for the solution. with your solution you need to make the callback on the association arguments: `has_and_belongs_to_many :children, before_add: parent_due_after_or_on_self`, but adding errors won't help. you can raise and exception and catch it with an actual error on the adding method. – Shalev Shalit Feb 13 '16 at 21:06