Pavel Perevezencev
Pavel Perevezencev

Reputation: 2978

ActiveRecord::AssociationTypeMismatch with accepts_nested_attributes_for

I have User and Email tables, with relation one User has one Email (as a login in a system). But user may has many Emails as own contacts.

class User < ApplicationRecord
  has_secure_password

  has_one :email
  # has_many :phones, as: :contactable

  accepts_nested_attributes_for :email
end

class Email < ApplicationRecord
  belongs_to :contactable, polymorphic: true

  accepts_nested_attributes_for :contactable

  validates :email, presence: true, uniqueness: true
end

and user_controller.rb

  def create
    @user = User.new(user_params)

    if @user.save
      render json: @user, except: :password_digest, status: :created, location: @user
    else
      render json: @user.errors, status: :unprocessable_entity
    end
  end

  private
    def user_params
      params.permit(
        :email,
        :password, 
        :first_name, 
        :last_name, 
        :patronymic, 
        email_attributes: [:email]
      )
    end

when I try send requests like this

{
    "email": "[email protected]",
    "phone": "+799999999999",
    "password": "test",
    "first_name": "First-name",
    "last_name": "Last-name",
    "patronymic": "Patronymic"
}

I have this error

"exception": "#<ActiveRecord::AssociationTypeMismatch: Email(#70266002240460) expected, got \"[email protected]\" which is an instance of String(#47039052873240)>" 

what I doing wrong?

UPDATE

  1. I replaced has_one relation by belongs_to
  2. and changed user_params function to this

    params.permit(:password, :first_name, :last_name, :patronymic, email_attributes: [:email])

but if I try to make a post request like this:

{
    "email_attributes": {
        "email": "[email protected]"
    },
    "phone": "+799999999999",
    "password": "test",
    "first_name": "First-name",
    "last_name": "Last-name",
    "patronymic": "Patronymic"
}

I have error

{
    "email.contactable": [
        "must exist"
    ]
}

And sub-question: how to get rid of email_attributes?

Upvotes: 0

Views: 649

Answers (1)

Taryn East
Taryn East

Reputation: 27747

Your user doesn't have a column called email, it has an association that is meant to be a new email object, with its own attributes.

If it were just a column, then you could have params come in something like:

user: { 
  name: 'Fred', # this is a column on users
  email: '[email protected]' # this is another column on users
}

But instead, you need it to act like a separate model. Now your email model is a database table on its own, and has a column, eg called 'email' right? If so, then you'd need the params to come in something ike this:

user: { 
  name: 'Fred', # this is a column on users
  email: { # this tells us that it's another object called 'email'
    email: '[email protected]' # this is a column on emails
  }
}

Obviously you'd need to rename columns to match your own.

I'll also point out that in your permit, you have both an email as a column on users and also as email_attributes - which says the attributes of a different, associated model called email

Upvotes: 1

Related Questions