Corin
Corin

Reputation:

Polymorphic nested form results in AssociationTypeMismatch

Models:

class User < ActiveRecord::Base
  belongs_to :role, :polymorphic => true

class Admin < ActiveRecord::Base
  has_one :user, :as => :role

class Dealer < ActiveRecord::Base
  has_one :user, :as => :role

class Buyer < ActiveRecord::Base
  has_one :user, :as => :role

Dealer controller:

  def new
    @dealer = Dealer.new
    respond_to do |format|
      format.html
      format.xml  { render :xml => @dealer }
    end
  end

  def create
    @dealer = Dealer.new(params[:dealer])
    respond_to do |format|
      if @dealer.save
        flash[:notice] = 'Dealer was successfully created.'
        format.html { redirect_to [:admin, @dealer] }
        format.xml  { render :xml => @dealer, :status => :created, :location => @dealer }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @dealer.errors, :status => :unprocessable_entity }
      end
    end
  end

Error message:

ActiveRecord::AssociationTypeMismatch in Admin/dealersController#create User(#41048900) expected, got HashWithIndifferentAccess(#23699520)

Request Parameters:

{"authenticity_token"=>"+GkeOOxVi1Fxl7ccbV0Ctt5R6shyMlF+3UWgRow2RdI=",
 "dealer"=>{"gender"=>"m",
 "forename"=>"",
 "surname"=>"",
 "company"=>"",
 "address1"=>"",
 "address2"=>"",
 "zipcode"=>"",
 "city"=>"",
 "country"=>"1",
 "user"=>{"email"=>"",
 "password"=>""},
 "phone"=>"",
 "mobile"=>"",
 "fax"=>""},
 "commit"=>"Submit"}

I guess my problem is that Rails doesn't convert the "user" hash inside the request hash into a User object — but why and how can I make Rails to do that?

Upvotes: 0

Views: 1569

Answers (1)

cudima
cudima

Reputation: 434

Just spent several hours on this including bumping into this thread. Finally found on another forum: the attribute setter expects to get your params in this form

{ ...,
  "user_attributes" => {"email" => "", "password" => ""},
  ... }

NOT

{ ...,
  "user" => {"email" => "", "password" => ""},
  ... }

In order to get this, your view should look something like this:

form_for @dealer do |f|
 ...
 f.fields_for :user, @dealer.user do |u|
   ...
 end
 ...
end

This works for me on Rails 3.0.3

Upvotes: 8

Related Questions