Rails Changing Polymorphic Type Of An Object
We have a parent model Vehicle that is inherited to make classes Car, Truck, SUV. In our form, we allow the user to edit the data for a bunch of Vehicles, and one of the attributes for each vehicle is a select menu for "type". The HTML attribute is named vehicle_type and updates the actual Polymorphic type attribute in the Vehicle Model:
# Get/Set Type bc rails doesnt allow :type to be set in mass
def vehicle_type
self.type
end
def vehicle_type=(type)
self.type = type
end
The problem we're having is that when we call update_attributes on form data and the type of an existing vehicle has been changed, rails is calling the validation for the old class (not new type) which results in errors. What we need to do is when vehicle_type is changed, that the model is changed to 开发者_JAVA百科that new type as well.
Is there a way to do this?
Here is the update action (fleet has_many vehicles):
# PUT /fleet/1
# PUT /fleet/1.xml
def update
@fleet = Fleet.find(params[:id])
respond_to do |format|
if @fleet.update_attributes(params[:fleet])
flash[:notice] = 'Fleet of vehicles was successfully updated.'
format.html { render :action => "edit" }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => @fleet.errors, :status => :unprocessable_entity }
end
end
end
Here is Fleet:
class Fleet < ActiveRecord::Base
has_many :vehicles, :dependent => :destroy, :order => 'position ASC'
accepts_nested_attributes_for :vehicles,
:reject_if => proc { |attrs| attrs['name'].blank? },
:allow_destroy => true
You could use a factory method to create the right type of vehicle, then assign the attributes.
def Vehicle.factory(type)
type.constantize.new
end
When you call @vehicle.save
, you could add false
as the first parameter to skip validation (@vehicle.save(false)
). Another option is to use ActiveRecord::Base#update_attribute
-- which skips validation.
So you could save your model without the type column changing, then add a @vehicle.update_attribute(:type, "Truck")
in the same action. Two SQL queries, but may be necessary for your situation.
精彩评论