views:

108

answers:

2

I have the following contrived example in Rails. I want to make sure the Garage model has at least one car with this.

class Garage
    has_many :cars
    validate :at_least_one_car
    accepts_nested_attributes_for :cars, :allow_destroy => true

    def at_least_one_car
        if cars.count == 0
          errors.add_to_base("needs at least one car")
        end
    end
end

class Car
    belongs_to :garage
end

In my form I have a remove button that will set the hidden field _delete to true for an existing car. Let's say there is only one car object and I "delete" it in my form, if I do garage_object.update_attributes(params[:garage]), it will delete the car model and make the garage object invalid. Is there to a way to make it not update the attributes if it will make the model invalid?

params = {
  :garage => {
    :car_attributes => {
      ["0"] => {
        _delete => true,
        # other attributes here
      }
    }
  }
}
A: 

From the little i know your question following will help you.

You want some validation which should check when you creating object and not when you update it. use validate_on_create and validate_on_update methods for that

class Garage
    has_many :cars


    def validate_on_create
        if cars.count == 0
          errors.add_to_base("needs at least one car")
        end
    end
end

class Car
    belongs_to :garage
end

Hope that helps :)

EDITED

What you are using to delete the object

destroy or delete

when you are using 'delete' no callbacks are get fire off

when you are using 'destroy' all callbacks and filters are fired off before the object is deleted.

so check and use 'destroy'

Salil
It doesn't work, the _delete = true in params deletes the model, makes the object invalid, and doesn't restore the deleted model.
Timothy
It's set in the form. params[:garage][:car_attributes][0][:_delete] == true leads to update_attributes deleting the object. I forgot to add that there is an accepts_nested_attributes_for :cars, :allow_destroy = true
Timothy
+1  A: 

I believe you can add a validates_presence_of :car, so the garage_object won't be updated if there's no associated cars.

class Garage
    has_many :cars
    validates_presence_of :cars
end

class Car
    belongs_to :garage
end
j.
It doesn't work. update_attributes will return false to indicate that it isn't valid but the car will still be deleted.
Timothy
You can use a `transaction` in your controller and raise an exception if something goes wrong... with this, if the garage_object is invalid, the exception will force a roolback and the car will remain in the database. I'm just not sure if this is the best method... but I personally use it.
j.
Ah, thanks that worked.
Timothy
You should accept the answer then :]
j.