2

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.

Harish Shetty
  • 64,083
  • 21
  • 152
  • 198

2 Answers2

1

I ended up doing this:

class Automobile < ActiveRecord::Base
private
  def attributes_protected_by_default
    super - [self.class.inheritance_column]
  end
end
Harish Shetty
  • 64,083
  • 21
  • 152
  • 198
  • I tried this but apparently Automobile.new(params[:automobile]) does not work in my create controller-action. – Pedro Rolo May 18 '11 at 15:00
0

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.

François Beausoleil
  • 16,265
  • 11
  • 67
  • 90
  • My scenario is bit more complicated. I have three layers of nesting in my submission. I have to recreate the whole structure to perform this validation. I have resorted to adding a format validation for the `type` field in the Automobile class. – Harish Shetty Mar 27 '10 at 14:25