La mise à jour des attributs imbriqués au lieu de la mise à jour comporte de nombreuses relations que j'essaie d'utiliser Rails 4 Update_attributes
Class Person <ActiveRecord::Base
has_many :pets
accepts_nested_attributes_for :pets
end
Class Pet < ActiveRecord::Base
belongs_to :person
end
Dans mon contrôleur, je reçois les paramètres comme {id: 23, house_no: '22A', animaux de compagnie: [{nom: 'jeffy', tapez: 'chien'}, {nom: 'sharky', tapez: 'poisson'} ]}
et ma méthode de mise à jour est
def update
@Person = Person.find(params[:id])
if @Person.update(person_params)
@Person.save
render 'persons/create', status 200
else
render 'persons/create', status 400
end
end
private
def person_params
person_params = params.permit(:house_no)
person_params.merge! ({pets_attributes: params[:pets]}) if params[:pets].present?
person_params
end
Maintenant, lorsque je le mets à jour et si la personne a déjà un animal de compagnie, les nouveaux animaux de compagnie sont ajoutés au lieu d'être mis à jour, par exemple si une personne avec l'identifiant 1 a 1 animal nommé "Tiger" et je mets à jour cette personne avec 2 animaux nommés "Shasha" et "Monti" alors le dossier de la personne a 3 animaux (Tiger, Shasha et Monti) au lieu de le mettre à jour à 2 (Shasha et Monti)
voir le manuel:
http://api.rubyonrails.org/v4.0.1/classes/ActiveRecord/NestedAttributes/ClassMethods.html
vous devez envoyer vos attributs comme pets_attributes:[{name:'jeffy', type:'dog'}, {name:'sharky', type:'fish'}]
et cela devrait bien fonctionner.
Lisez s'il vous plaît
Vous pouvez maintenant définir ou mettre à jour des attributs sur les publications associées via un hachage d'attribut pour un membre: incluez la clé: posts_attributes avec un tableau de hachages d'attributs de publication en tant que valeur. Pour chaque hachage qui n'a pas de clé id, un nouvel enregistrement sera être instancié, sauf si le hachage contient également une clé _destroy qui prend la valeur true.
Mettez à jour le modèle Person
comme ci-dessous:
class Person < ActiveRecord::Base ## NOTE: class (c lowercase) and NOT Class
has_many :pets
accepts_nested_attributes_for :pets, allow_destroy: true ## Added allow_destroy
end
Pour détruire le modèle associé, c'est-à-dire Pet
via le hachage des attributs, vous devez d'abord l'activer en utilisant le :allow_destroy
option.
De votre point de vue, vous devrez ensuite passer le _destroy
attribut pour les animaux que vous souhaitez supprimer.
Depuis, vous n'avez pas partagé le code spécifique à la vue. Voici un exemple de la façon dont il doit être implémenté dans votre vue. Modifiez-le selon vos besoins:
<%= form_for @person do |f| %>
<%## .. %>
<%= f.fields_for :pets do |builder| %>
<%## .. %>
<%= builder.check_box :_destroy %>
<%= builder.label :_destroy, "Remove Pet" %>
<% end %>
<% end %>
Dans le code ci-dessus, vous devez ajouter checkbox
et label
pour passer _destroy
valeur.
Après cela, mettez à jour le person_params
méthode dans votre contrôleur comme ci-dessous:
def person_params
params.require(:person).permit(:house_no, pets_attributes: [:id, :name, :type, :person_id, :_destroy])
end
REMARQUE:
Vous ne devriez pas définir instance variables
avec en majuscule nom. Les noms en majuscules sont utilisés pour déclarer Constants
dans Ruby
.
def update
@person = Person.find(params[:id])
if @person.update(person_params)
@person.save
render 'persons/create', status 200
else
render 'persons/create', status 400
end
end
Pouvez-vous essayer d'ajouter le :id
attribut à :pets_attributes
tableau dans person_params
?
Vous devez autoriser l'attribut id.
Probablement 1. vous voudriez attribuer des animaux de compagnie séparément,
@Person.pets = Pets.find(params[:pets])
Ou 2. nettoyez les animaux avant d'enregistrer la personne.
@Person.pets.destroy
Vous devez modifier vos paramètres avec des attributs d'animaux de compagnie
Vous devez également ajouter le paramètre: id dans les objets pour animaux de compagnie.
Essayez de changer votre person_params
as
def person_params
person_params = params.require(:person).permit(:house_no ,pets_attributes: [:name,:type])
end
Et supprimez @person.save
à partir de la méthode de mise à jour.Vous n'en avez pas besoin.Et utilisez également !
pour update
def update
@Person = Person.find(params[:id])
if @Person.update!(person_params)
render 'persons/create', status 200
else
render 'persons/create', status 400
end
end
Mise à jour
Et aussi, comme je peux voir, il n'y a pas de belongs_to :person
association dans le modèle Pet
, ajoutez-le dans le modèle
Class Pet < ActiveRecord::Base
belongs_to :person
end
Et maintenant autorisez le person_id
attribut en l'ajoutant dans le params
def person_params
person_params = params.require(:person).permit(:house_no,pets_attributes: [:name,:type,:person_id])
end