Comment puis-je atteindre cet objectif?
essayé de créer 2 méthodes, appelées
def disable_timestamps
ActiveRecord::Base.record_timestamps = false
end
def enable_timestamps
ActiveRecord::Base.record_timestamps = true
end
et la méthode de mise à jour elle-même:
def increment_pagehit
update_attribute(:pagehit, pagehit+1)
end
activer et désactiver les horodatages à l'aide de rappels tels que:
before_update :disable_timestamps, :only => :increment_pagehit
after_update :enable_timestamps, :only => :increment_pagehit
mais il ne met rien à jour, même l'attribut souhaité (pagehit).
Aucun conseil? Je ne veux pas avoir à créer une autre table juste pour compter le nombre de pages.
Au lieu de update_attribute
, vous pouvez utiliser update_column
dans Rails 3.1+.
update_attribute
ignore les validations, mais touchera updated_at
et exécutera des rappels.
update_column
ignore les validations, ne touche pas updated_at
et n'exécute pas de rappels.
Ainsi, update_column
est un excellent choix si vous ne souhaitez pas affecter updated_at
et n'avez pas besoin de rappels.
Voir http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html pour plus d'informations.
Notez également que update_column
mettra à jour la valeur de l'attribut dans le modèle en mémoire et qu'il ne sera pas marqué comme sale. Par exemple:
p = Person.new(:name => "Nathan")
p.save
p.update_column(:name, "Andrew")
p.name == "Andrew" # True
p.name_changed? # False
Si tout ce que vous voulez faire, c'est incrémenter un compteur, utilisez plutôt la méthode increment_counter
ModelName.increment_counter :pagehit, id
ce n'est pas une bonne idée de faire ceci:
self.class.update_all({ pagehit: pagehit+1 }, { id: id })
cA devrait etre
self.class.update_all("pagehit = pagehit + 1", { id: id })
la raison en est que si deux requêtes sont parallèles, la première version mettra à jour les pageshits avec le même numéro, car elle utilise le numéro enregistré dans la mémoire de Ruby. La deuxième option utilise le serveur SQL pour augmenter le nombre de 1, au cas où deux de ces requêtes arriveraient en même temps, le serveur les traiterait les unes après les autres et se retrouverait avec le nombre correct de requêtes de page.
Pour éviter Monkeypatchingtroubles, vous pouvez également utiliser ModelName.update_all à cette fin:
def increment_pagehit
self.class.update_all({ pagehit: pagehit+1 }, { id: id })
end
Cela ne touche pas non plus les horodatages de l'enregistrement.
Si la précision n'est pas vraiment importante et que vous ne vous attendez pas à ce que le code soit exécuté plusieurs fois, vous pouvez essayer de modifier la valeur enregistrée dans la base de données updated_at
, comme suit:
u = User.first
u.name = "Alex 2" # make some changes...
u.updated_at = u.updated_at + 0.000001.second # alter updated_at
u.save
de sorte que Rails essaiera en réalité de sauvegarder la même valeur et non de la remplacer par Time.now
.