2017-08-02 7 views
0

J'essaie de sauvegarder une mise à jour vers un enregistrement (utilisateur) qui a un parent (état). L'enregistrement de l'utilisateur s'affiche correctement (en affichage, édition), y compris l'état. L'enregistrement utilisateur est correctement mis à jour pour ses propres attributs, mais toute modification de l'état sélectionné par l'utilisateur n'est pas conservée. Lors de la modification de l'état de l'utilisateur de 1 à 2, l'utilisateur params retourné au contrôleur de l'aspect belle vue ... du journal ->Ecto: modifications apportées au modèle parent

%{"email" => “[email protected]", "first_name" => “Abe", 
"last_name" => “Sam", "password" => “foobar", "state_id" => "2"} 

Mais quand cela est transmis au changeset utilisateur, il revient avec la modification du state_id est tombé ... du journal ->

#Ecto.Changeset<action: nil, 
changes: %{password: "foobar", 
password_hash: “xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx."}, 
errors: [], data: #SomeApp.User<>, valid?: true> 

la mise à jour dans le contrôleur est:

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 

...

Le code est changeset pertinent:

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 

Le schéma de l'utilisateur est:

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 

Qu'est-ce qui je fais mal ici? Ai-je manqué quelque chose dans mon changeset qui jette le user_id des params dans le changeset? Je m'attends à ce que je fasse quelque chose de simple et de stupide - j'ai vraiment passé des heures à essayer de lire ça et je suis coincé!

Répondre

1

Puisque vous voulez utiliser le state_id de params, vous devrez ajouter à la liste :state_id autorisés dans l'appel à cast. Sans :state_id dans la liste autorisée, la valeur sera ignorée, ce qui se passe actuellement.

|> cast(params, [:email, :first_name, :last_name, :password]) 

devrait être

|> cast(params, [:email, :first_name, :last_name, :password, :state_id]) 
+0

thankyou - j'ai essayé déjà, Phoenix lance une erreur sur ce disant que vous devez jeter les associations en utilisant cast_assoc. Je vais repro et obtenir l'erreur exacte donnée. Mais en essayant cela jette une erreur distincte en se plaignant que cast_assoc est pour les enfants. –

+0

Je me trompe, ça marche totalement maintenant, comme tu l'as dit. Aucune idée pourquoi cela n'a pas fonctionné avant (peut-être que je n'avais pas l'assoc_constraint dedans). Grand merci - vous avez fait ma journée! –

+0

Je l'ai compris: je pense que j'ai déjà ajouté: état à la distribution au lieu de: state_id. Je trouve que la dénomination de l'appartenance à vs la convention de colonne réelle (état vs state_id) n'est pas immédiatement intuitive. Je pense que je fais la bonne chose cependant? –