如何覆盖attr_protected?

时间:2010-03-26 22:17:07

标签: ruby-on-rails activerecord single-table-inheritance

我的STI实施如下:

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

我正在为用户创建汽车列表。对于每个汽车,UI设置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字段。

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

2 个答案:

答案 0 :(得分:1)

我最终这样做了:

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

答案 1 :(得分:0)

我会在User上添加一个帮助器方法来实例化相应的子类:

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

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