J'ai un utilisateur et une classe de profil imbriquée comme suit:
class User < ActiveRecord::Base
has_one :profile
attr_accessible :profile_attributes
accepts_nested_attributes_for :profile
end
class Profile < ActiveRecord::Base
belongs_to :user
attr_accessible :name
end
user = User.find(1)
user.profile.id # => 1
user.update_attributes(profile_attributes: {name: 'some name'})
user.profile.id # => 2
Je ne comprends pas pourquoi Rails jette l'ancien profil et en crée un nouveau.
En utilisant
user.profile.update_attributes({name: 'some name'})
met à jour le profil actuel comme prévu. Mais dans ce cas, je ne profite pas de includes_nested_attributes_for
Est-ce que quelqu'un sait pourquoi la mise à jour se produit de cette façon? Je préférerais ne pas me retrouver avec une base de données de lignes de profil non connectées à un utilisateur.
J'ai résolu ce problème en ajoutant l'option update_only
:
accepts_nested_attributes_for :profile, update_only: true
Maintenant, un nouveau profil est créé uniquement s'il n'en existe pas déjà un.
Pour tous ceux qui ont le même problème dans Rails 4: fields_for ajoute déjà l'ID de vos formulaires imbriqués, mais vous devez autoriser le paramètre: id. J'ai seulement autorisé un paramètre: nom_objet_id et, comme cela ne génère aucune erreur, cela m'a pris un certain temps avant de voir cela dans les journaux du serveur. Espérons que cela aide quelqu'un à perdre moins de temps que moi à ce sujet :)
Si vous vérifiez votre formulaire, vous devez définir l'attribut id dans le hachage d'attribut imbriqué pour votre objet de profil. Si l'ID n'est pas défini, ActiveRecord considère qu'il s'agit d'un nouvel objet.
Par exemple, si un formulaire ERB crée un ensemble de paramètres "utilisateur" avec un hachage de paramètre "profile_attributes" imbriqué pour le profil imbriqué dans l'utilisateur, vous pouvez inclure une valeur cachée pour l'ID de profil, comme suit:
<%= hidden_field "user[profile_attributes][id]", @profile.id %>
Cela m'a frappé dans une autre version de Rails et je pensais que je vais perdre la tête. Tout en ajoutant update_only => true résolu, je pense que c'est un bogue quelque part dans Rails.
Symptômes dans mon cas: j'obtiendrais l'association avec la propriété includes_to et le nouvel objet imbriqué créé - jusqu'à ce que je régénère la page pour la première fois. Après cela a fonctionné correctement.
Dans mon cas, j'ai ajouté une méthode before_save à ma classe imbriquée et imprimé ce qu'elle a enregistré. J'ai également imprimé les attributs avant d'appeler update_attributes. Le "parent_id" est correctement défini. J'ai également inclus le champ d'identifiant masqué dans le formulaire, sans modification - ce qui était normal car il était déjà inclus à l'aide de fields_for ...
Surprise: j'ai vu un appel de mise à jour générer deux sauvegardes. La première sauvegarde aurait l'identifiant d'objet imbriqué, mais null pour l'identifiant d'appartenance. - donc, cela mettrait à jour l'enregistrement pour qu'il attribue la valeur null à "parent_id". La deuxième sauvegarde aurait le "parent_id" défini mais l'ID d'objet imbriqué serait défini sur null.
Comme je l'ai dit, je l'ai corrigé en ajoutant update_only => true, mais je pense que c'est toujours un bogue.
Je voudrais savoir si les symptômes ci-dessus s'appliquent à votre cas aussi pour confirmer qu'il s'agit d'un bogue.