views:

407

answers:

2

I have a complex form for my Work model. It accepts nested attributes for Credits, Images and Videos. (it is a modified version of Eloy Duran's complex form example)

  • I want to validate presence of at least one Credit
  • I want to validate presence of at least one Image or one Video

When I do (in work.rb):

validates_presence_of :credits

it validates properly when I try to submit the form without any credits but it does not validate if I remove the last credit (by checking a check_box that adds "_delete" to credit's attributes). It submits the work deleting the one and only credit leaving the work without any credits.

Do you have any idea on how I can validate these properly?

A: 

Try using before_save in work.rb


 before_save :check_credits

private
 def check_credits
   self.credits > 0
 end

If credits are <= zero, the save won't go through.

klochner
No, that doesn't work. I think the problem is that as the credit is marked for deletion with a hidden checkbox value being set to 1 before the save, the credit still exists untill the save is completed. So self.credits.size > 0 or self.credits.blank? won't do the job. If I could access the _delete parameter of the submitted credits I could stop the save but I cant find a way to access that attribute from the model.
fahrio
fahrio is exactly right about the problem.
Peter Wagenet
+1  A: 

What you need is something along the lines of:

validate :credits_present

private

  def credits_present
    unless credits.any?{|c| !c.marked_for_destruction? }
      errors.add_to_base "You must provide at least one credit"
    end
  end

The conditional in credits_present may be a bit messy so let me break it down just in case you don't follow. The any? method returns true if any of the items in the Enumerable respond true to the block provided. In this case, we check that the item is not going to be deleted. So, if any of the credits are not going to be deleted we get true. If true, we're in good shape, we have at least one credit that won't be deleted. If, on the other hand, we get false we either know there aren't any credits or that any that are present will be deleted. In this case validation fails and we add the error.

Peter Wagenet
Thanks Peter, marked_for_destruction is what I was looking for, but the any? method you used is just brilliant.
fahrio
cool, nice work peter.
klochner