问题
I have STI implementation as follows:
class Automobile < ActiveRecord::Base
end
class Car < Automobile
end
class Truck < Automobile
end
class User < ActiveRecord::Base
has_many :automobiles
accepts_nested_attributes_for :automobiles
end
I am creating a list of automobiles for a user. For each automobile, the UI sets the type
field and the properties associated with the automobile.While form submission, the type
field is ignored as it is a protected attribute.
How do I work around this issue? Is there a declarative way to unprotect
a protected attribute?
Edit:
This is my current solution for the problem:
I override the attributes_protected_by_default
private method in my model class.
class Automobile < ActiveRecord::Base
private
def attributes_protected_by_default
super - [self.class.inheritance_column]
end
end
This removes the type
field from the protected list.
I am hoping that there is a better way than this.
回答1:
I ended up doing this:
class Automobile < ActiveRecord::Base
private
def attributes_protected_by_default
super - [self.class.inheritance_column]
end
end
回答2:
I would add a helper method on User that instantiates the appropriate subclass:
class User < ActiveRecord::Base
def self.automobile_from_type(type)
self.automobiles << case type
when "Car"
Car.new
when "Truck"
Truck.new
else
raise ArgumentError, "Unknown automobile type: #{type.inspect}"
end
end
end
Use it like this:
class AutomobilesController < ApplicationController
def create
@automobile = current_user.automobile_from_type(params[:automobile][:type])
if @automobile.update_attributes(params[:automobile]) then
redirect_to @automobile
else
render :action => :new
end
end
end
The code above is "safe": an attacker can't inject arbitrary text into your automobiles.type column. Your solution, while it works, has the disadvantage of enabling attacks.
来源:https://stackoverflow.com/questions/2527126/how-to-override-the-attr-protected