43 votes

Problème avec l'implémentation de counter_cache

Je me fais 'râteau abandonnée! ... posts_count est marqué en lecture seule' erreurs.

J'ai deux modèles: l'utilisateur et le poste.

users has_many posts.

posts belongs_to :user, :counter_cache => true

J'ai une migration qui ajoute la posts_count colonne de la table des utilisateurs, puis calcule et enregistre le nombre de messages par utilisateur.

self.up
  add_column :users, :posts_count, :integer, :default => 0

  User.reset_column_information
  User.all.each do |u|
    u.update_attribute( :posts_count, u.posts.count)
  end
end

quand je lance la migration, je reçois l'erreur. C'est assez clair, bien sûr, et si je supprime le :counter_cache déclaration de l'postes de modèle, par exemple

belongs_to :user

la migration se passe bien. Cela, évidemment, ne signifie pas parce que vous ne pouvais pas vraiment mettre en œuvre cette façon. Ce qui me manque?

97voto

Adam Lassek Points 18918

Vous devriez utiliser User.reset_counters pour le faire. De plus, je vous recommanderais d'utiliser find_each au lieu de each car cela itérera la collection par lots plutôt que tout d'un coup.

 self.up
  add_column :users, :posts_count, :integer, :default => 0

  User.reset_column_information
  User.find_each do |u|
    User.reset_counters u.id, :posts
  end
end
 

3voto

Roadmaster Points 3533

OK, la documentation précise:

Compteur cache colonnes sont ajoutées à la contenant du modèle de liste de lecture seule attributs par attr_readonly.

Je pense que c'est ce qui se passe: vous déclarez le compteur dans le modèle de définition, rendant ainsi le "posts_count" attribut en lecture seule. Puis, dans la migration, vous pouvez tenter de mettre à jour directement, ce qui entraîne l'erreur que vous mentionnez.

Le quick-and-dirty solution est de supprimer le counter_cache déclaration à partir du modèle d'exécuter la migration (pour ajouter la colonne à la base de données ET le remplir avec le poste actuel compte), puis rajouter le counter_cache déclaration pour le modèle. Devrait fonctionner, mais est mauvais, et nécessite une intervention manuelle lors de la migration - pas une bonne idée.

J'ai trouvé ce blog qui suggère de modifier le modèle de la liste des attributs en lecture seule lors de la migration, c'est un peu ancienne, mais vous pourriez vouloir donner un essai.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X