web-dev-qa-db-fra.com

Comment tout mettre à jour lorsque vous avez besoin d'être rappelé?

Disons que j'ai 15 identifiants utilisateur dans un tableau appelé user_ids.

Si je veux, disons, changer tous leurs noms en "Bob", je pourrais faire:

users = User.find(user_ids)
users.update_all( :name => 'Bob' )

Cependant, cela ne déclenche pas de rappel. Si je dois déclencher des rappels sur la sauvegarde de ces enregistrements, à ma connaissance la seule façon est d'utiliser:

users = User.find(user_ids)
users.each do |u|
  u.name = 'Bob'
  u.save
end

Cependant, cela signifie potentiellement une tâche très longue dans une action de contrôleur.

Donc, ma question est, existe-t-il un autre moyen meilleur/plus performant/plus efficace pour déclencher une mise à jour par lots vers un ensemble d'enregistrements qui fait déclenche les rappels sur les enregistrements?

45
Andrew

Non, pour exécuter des rappels, vous devez instancier un objet qui est une opération coûteuse. Je pense que la seule façon de résoudre votre problème est de refactoriser les actions que vous effectuez en rappel dans une méthode distincte qui pourrait utiliser les données récupérées par la méthode select_all sans instanciation d'objet.

20
iafonov

Au lieu d'utiliser chaque/find_each, essayez plutôt d'utiliser la méthode update:

models.update(column: value)
51
untitled

Voici une autre façon de déclencher des rappels. À la place d'utiliser

models.update_all(params)

vous pouvez utiliser

models.find_each { |m| m.update_attributes(params) }

Cependant, je ne recommanderais pas cette approche si vous traitez de très grandes quantités de données.
J'espère que ça aide!

20
maxhm10