2010-03-26 110 views
2

我有STI执行如下命令:如何覆盖attr_protected?

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 

我创建了一个用户的汽车的列表。对于每辆汽车,用户界面设置type字段和与汽车相关的属性。在表单提交时,type字段被忽略,因为它是受保护的属性。

我该如何解决此问题? unprotect受保护的属性是否有声明方式?

编辑: 这是我的问题,目前的解决方案: 我重写在我的模型类的attributes_protected_by_default私有方法。

class Automobile < ActiveRecord::Base 
private 
    def attributes_protected_by_default 
    super - [self.class.inheritance_column] 
    end 
end 

这将从受保护列表中删除type字段。

我希望有比这更好的方法。

回答

1

我落得这样做:

class Automobile < ActiveRecord::Base 
private 
    def attributes_protected_by_default 
    super - [self.class.inheritance_column] 
    end 
end 
+0

我试过这个,但显然Automobile.new(params [:汽车])不起作用,在我的创建控制器行动。 – 2011-05-18 15:00:12

0

我会在用户添加一个辅助方法来实例化相应的子类:

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 

使用方法如下:

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 

上面的代码是“安全”的:攻击者无法将任意文本注入汽车类型列。您的解决方案虽然有效,但具有启用攻击的缺点。

+0

我的情况是有点复杂。我在提交中有三层嵌套。我必须重新创建整个结构才能执行此验证。我采取了为汽车类中的'type'字段添加格式验证。 – 2010-03-27 14:25:20