Search code examples
ruby-on-railsmodelassociationspolymorphic-associationsmass-assignment

Mass assignment error with polymorphic association


I'm getting a mass assignment error when submitting a nested form for a has_one polymorphic model. The form is trying to create Employee and Picture instances based on the polymorphic association Rails guide.

I would appreciate literally ANY functioning example of a nested creation form for a has_one polymorphic model! I know there are tons of questions on mass assignment errors but I've never seen a working example with polymorphic associations.

Models

class Picture < ActiveRecord::Base
    belongs_to :illustrated, :polymorphic => true
    attr_accessible :filename, :illustrated
end

class Employee < ActiveRecord::Base
    has_one :picture, :as => :illustrated
    accepts_nested_attributes_for :picture
    attr_accessible :name, :illustrated_attribute
end

Migrations

create_table :pictures do |t|
    t.string :filename
    t.references :illustrated, polymorphic: true
end

create_table :employees do |t|
    t.string :name
end

controllers/employees_controller.rb

...
def new
    @employee = Employee.new
    @employee.picture = Picture.new
end

def create
    @employee = Employee.new(params[:employee])
    @employee.save
end
...

Error

Can't mass-assign protected attributes: illustrated

app/controllers/employees_controller.rb:44:in `create'

{"utf8"=>"✓", "authenticity_token"=>"blah"
 "employee"=>{"illustrated"=>{"filename"=>"johndoe.jpg"},
 "name"=>"John Doe"},
 "commit"=>"Create Employee"}

In the models, I've tried every permutation of :illustrated, :picture, :illustrated_attribute, :illustrated_attributes, :picture_attribute, :picture_attributes, etc. Any tips or examples?

EDIT:

_form.html.erb

<%= form_for(@employee) do |f| %>

  <%= f.fields_for :illustrated do |form| %>
    <%= form.text_field :filename %>
  <% end %>

    <%= f.text_field :name %>
    <%= f.submit %>

<% end %>

Solution

  • You need to specify the nested_attributes appropriately. accepts_nested_attributes_for takes the name of the association as parameter and then you need to add the same assoc_attributes to your attr_accessible. So change your Employee model to

    class Employee < ActiveRecord::Base
      has_one :picture, :as => :illustrated
      accepts_nested_attributes_for :picture
      attr_accessible :name, :picture_attribute
    end
    

    And change the field_for line in the view code to

    <%= f.fields_for :picture do |form| %>