Reputation: 3
I’m trying the save an update to a record (user) which has a parent (state). The user record displays fine (in show, edit) including the state. The user record updates fine for it’s own attributes, but any change to the state selected by the user is not persisted. When changing the user’s state from 1 to 2, the user params returned to the controller from the view look fine...from log ->
%{"email" => “[email protected]", "first_name" => “Abe",
"last_name" => “Sam", "password" => “foobar", "state_id" => "2"}
But when this is passed to the user changeset, it comes back with the change to the state_id dropped...from log ->
#Ecto.Changeset<action: nil,
changes: %{password: "foobar",
password_hash: “xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx."},
errors: [], data: #SomeApp.User<>, valid?: true>
The update in the controller is:
def update(conn, %{"id" => id, "user" => user_params}) do
user = Repo.get!(User, id)
changeset = User.changeset(user, user_params)
case Repo.update(changeset) do
…
The relevant changeset code is:
def changeset(model, params \\ %{}) do
model
|> cast(params, [:email, :first_name, :last_name, :password])
|> assoc_constraint(:state)
|> validate_required([:email, :first_name, :last_name, :password])
|> unique_constraint(:email)
|> validate_length(:password, min: 4, max: 100)
|> put_pass_hash()
end
The schema for the user is:
schema "users" do
field :email, :string
field :password, :string, virtual: true
field :password_hash, :string
field :first_name, :string
field :last_name, :string
belongs_to :state, SomeApp.State
timestamps()
end
What’s am i doing wrong here? Am i missing something in my changeset that casts the user_id from the params into the changeset? I expect I'm doing something simple and stupid - i've genuinely spent hours trying to read up pick this apart and i'm stuck!
Upvotes: 0
Views: 63
Reputation: 222368
Since you want to use the state_id
from params
, you'll need to add :state_id
to the allowed list in the call to cast
. Without :state_id
in the allowed list, the value will be ignored, which is what is happening right now.
|> cast(params, [:email, :first_name, :last_name, :password])
should be
|> cast(params, [:email, :first_name, :last_name, :password, :state_id])
Upvotes: 1