web-dev-qa-db-fra.com

Rails 4 Mettre à jour les attributs imbriqués

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)

23
Kush Jain

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.

15
Suchit Puri

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  
14
Kirti Thorat

Pouvez-vous essayer d'ajouter le :id attribut à :pets_attributes tableau dans person_params?

Vous devez autoriser l'attribut id.

12
Panos Malliakoudis

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.

1
faisal bhatti

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
1
Pavan