'Rails: undefined method `primary_key' for ActiveSupport::HashWithIndifferentAccess:Class

I have a polymorphic relationship for my User model. I am using Devise.

When I try to edit the user's details, I get the following error:

undefined method `primary_key' for ActiveSupport::HashWithIndifferentAccess:Class

The data submitted through the form is:

{"utf8"=>"✓",
 "_method"=>"put",
 "authenticity_token"=>"Ap0JP2bs/w9J6iI9rZahiKR1K8UEIi7rp33a4OutMbo=",
 "user"=>{"email"=>"[email protected]",
 "rolable"=>{"first_name"=>"Christopher",
 "last_name"=>"Columbus",
 "city"=>"16"}},
 "commit"=>"Update"}

The controller method is:

  def update
    @user = User.find(current_user.id)

    if @user.update_attributes(params[:user])
      redirect_to edit_user_registration_path, notice: 'Your profile was successfully updated.'
    else
      redirect_to edit_user_registration_path, error: "Something went wrong, couldn't update your profile!."
    end
  end

The models:

1. User

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

  # Devise business
  devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable

  # Setup accessible (or protected) attributes for your model
  attr_accessible :remote_avatar_url, :avatar, :login, :username, :email, :password, :password_confirmation, :remember_me

  # For authenticating with facebook
  attr_accessible :provider, :uid, :rolable
  devise :omniauthable, :omniauth_providers => [:facebook]

  # For authenticating with both username or email
  attr_accessor :login

  # Upload avatar
  mount_uploader :avatar, AvatarUploader

  # Makes username necessary
  validates :username, :presence => true
end

2. Customer

class Customer < ActiveRecord::Base
  has_one :user, :as => :rolable
  has_one :preferences, :class_name => "CustomerPreferences"
  belongs_to :city

  attr_accessible :first_name, :last_name
end

What's the problem?



Solution 1:[1]

Based on your request hash, you are passing the rolable attribute as:

"rolable"=>{"first_name"=>"Cristian",
           "last_name"=>"Gavrila",
           "city"=>"16"}

You can't do this unless you specify that the User model accepts nested attributes for rolable. However, you have setup your User as belonging to a Rolable rather than the other way around. Nested attributes aren't designed to handle this inverse relationship - you may want to reconsider what you are trying to accomplish here, and modify the relationship accordingly.

For instance, you may want to turn your hash inside out and pass the rolable attributes with the user attributes embedded within. Or you may want to turn rolable into a has_one association.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 PinnyM