Inputs_for error with Phoenix Nested Form for has one relationship: expected personal_profile to be a map/struct, got

Hi, please i’m having issue with nesting an has one relationship model to a form.

Error: expected personal_profile to be a map/struct, got:

I have a user schema

schema "users" do
    field(:active, :boolean, default: false)
    field(:email, :string)
    field(:last_login, :naive_datetime)
    field(:password, :string)
    has_one(:personal_profile, App.Accounts.PersonalProfile)

    timestamps()
  end

and a personal_profile schema

schema "personal_profiles" do
    field(:first_name, :string)
    field(:last_name, :string)
    
    belongs_to(:user, App.Accounts.User)

    timestamps()
  end

The Registration Controller has action new as

def new(conn, _params) do
    changeset =
      Accounts.change_user(%User{
        personal_profile: [
          %PersonalProfile{}
        ]
      })

    render(conn, "new.html", changeset: changeset)
  end

and my form inside new.html.eex is

<%= form_for @changeset, registration_path(@conn, :create), [class: "needs-validation", novalidate: ""], fn f -> %>

		<%= inputs_for f, :personal_profile, fn p -> %>
			<div class="form-group">
				<div class="input-group input-group-seamless">
					  <span class="input-group-prepend">
						<span class="input-group-text">
						  <i class="feather icon-user"></i>
						</span>
					  </span>
					<%= text_input p, :first_name, class: "form-control letters-input #{has_error(p, :first_name)}", placeholder: "First Name", required: "required" %>
				</div>
			</div>

			<div class="form-group">
				<div class="input-group input-group-seamless">
					  <span class="input-group-prepend">
						<span class="input-group-text">
						  <i class="feather icon-user"></i>
						</span>
					  </span>
					<%= text_input p, :last_name, class: "form-control letters-input #{has_error(p, :last_name)}", placeholder: "Last Name", required: "required" %>
				</div>
			</div>
		<% end %>

		<div class="form-group">
			<div class="input-group input-group-seamless">
				  <span class="input-group-prepend">
					<span class="input-group-text">
					  <i class="feather icon-at-sign"></i>
					</span>
				  </span>
				<%= email_input f, :email, class: "form-control #{has_error(f, :email)}", placeholder: "Email", required: "required" %>
			</div>
		</div>

		<div class="form-group">
			<div class="input-group input-group-seamless">
				  <span class="input-group-prepend">
					<span class="input-group-text">
					  <i class="feather icon-lock"></i>
					</span>
				  </span>
				<%= password_input f, :cpassword, placeholder: "Password", required: "required", class: "form-control password-toggle #{has_error(f, :cpassword)}" %>
				<div class="input-group-append">
					<button class="btn btn-outline-secondary toggle-password" type="button"><i class="feather icon-eye"></i></button>
				</div>
			</div>
		</div>

		<div class="form-group text-right mt-4">
			<button class="btn btn-primary">Create Account</button>
		</div>
	<% end %>

Please how can i resolve this?

Can you please provide the full error message? Especially the part where it tells you what it got isntead of a struct?

Thanks immensely for your quick response. Please find below the full error message.

expected personal_profile to be a map/struct, got: [%App.Accounts.PersonalProfile{meta: #Ecto.Schema.Metadata<:built, “personal_profiles”>, about_me: nil, address: nil, date_of_birth: nil, facebook_url: nil, first_name: nil, gender: nil, id: nil, inserted_at: nil, last_name: nil, linkedin_url: nil, marital_status: nil, phone_number: nil, slug: nil, twitter_url: nil, updated_at: nil, user: #Ecto.Association.NotLoaded, user_id: nil}]

The message tells you to expect a single struct but you are passing in a list. Pass only the item in the list should work.

3 Likes

Thanks immensely for this insight. Everything is working fine now.

1 Like