How can I write a validation that will ensure an existing association cannot be changed in Rails 3?
I have seen many questions asking how to validate the presence of an association, but this question is a bit more complex.
Say I have three models, a Plane
, a Pilot
, and a Flight
.
A Plane
can have one Pilot
and one Flight
.
Once a Plane
has been assigned a Pilot
, it can then be assigned a Flight
.
I would like to write some validation code to ensure that once a Plane
has both a Flight
and a Pilot
, the Pilot
cannot be changed. So I would like this test to pass:
describe Plane do
context "before updating" do
it "ensures that the pilot cannot be changed if the plane has any flights" do
plane = Plane.create!
plane.pilot = Pilot.create!
plane.flight = Flight.create!
hijacker = Pilot.create!
plane.pilot = hijacker
plane.save.should be_false
plane.errors[:base].should include "Can't change the pilot while in-flight"
end
end
end
I would love some insight as to what techniques are available to accomplish this. Thanks all!
You could start with a custom validation that checks the changed record (sitting in memory) against the underlying record that's actually in the database.
class Plane < ActiveRecord::Base
validate_on_update :pilot_cannot_be_changed
def pilot_cannot_be_changed
errors.add(:pilot, "cannot be changed while in-flight.")
if pilot.id != Plane.find(id).pilot.id
end
you can write your own validation to ensure this.. but that wouldn't return false to you in the moment you assign a pilot, but at the end, when you save the plane.
So here is simpler version:
class Plane < ActiveRecord::Base
def pilot=(val)
return false if self.pilot && self.flight
@pilot = val
# I'm not sure about this line above, you can use something like this (or both lines)
# write_attribute(:pilot_id, val.id)
end
end
Hope this helps (or at least navigate you the right direction).
Regards, NoICE
精彩评论