web-dev-qa-db-fra.com

Existe-t-il un moyen d'éviter de mettre à jour automatiquement les champs Rails timestamp?

Si vous avez des colonnes de base de données created_at et updated_at Rails définit automatiquement ces valeurs lorsque vous créez et mettez à jour un objet de modèle. Existe-t-il un moyen d'enregistrer le modèle sans toucher ces colonnes?

J'apporte des données héritées et je voudrais définir ces valeurs à partir des valeurs correspondantes dans les champs de données hérités (différemment nommés). Je trouve quand je les place sur le modèle et que j'enregistre le modèle, Rails semble remplacer les valeurs entrantes.

Bien sûr, je pourrais simplement nommer les colonnes du modèle Rails différemment pour éviter cela, mais après l'importation des données, je veux que Rails fasse son horodatage automatique).

66
Ethan

Faites-le dans une migration ou dans une tâche de râteau (ou dans les nouvelles graines de base de données si vous êtes sur Edge Rails):

ActiveRecord::Base.record_timestamps = false
begin
  run_the_code_that_imports_the_data
ensure
  ActiveRecord::Base.record_timestamps = true  # don't forget to enable it again!
end

Vous pouvez définir en toute sécurité created_at et updated_at manuellement, Rails ne se plaindra pas.

Remarque: Cela fonctionne également sur des modèles individuels, par ex. User.record_timestamps = false

73
August Lilleaas

utilisez plutôt la méthode update_column:

http://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-update_column

update_column(name, value)
# Updates a single attribute of an object, without calling save.

La validation est ignorée.

Les rappels sont ignorés.

la colonne updated_at/updated_on n'est pas mise à jour si cette colonne est disponible.

Déclenche une ActiveRecordError lorsqu'elle est appelée sur de nouveaux objets ou lorsque l'attribut name est marqué en lecture seule.

55
yawl

Rails 5 fournit un moyen pratique de mettre à jour un enregistrement sans mettre à jour son horodatage updated_at: https://api.rubyonrails.org/classes/ActiveRecord/Persistence.html#method-i-save

Vous avez juste besoin de passer touch:false lors de la mise à jour de votre dossier.

>> user = User.first
>> user.updated_at
=> Thu, 28 Apr 2016 20:01:57 IST +05:30
>> user.name = "Jose"
>> user.save(touch: false)
=> true

>> user.updated_at
=> Thu, 28 Apr 2016 20:01:57 IST +05:30
36
Subhash Chandra

Vous pouvez définir les éléments suivants dans votre migration:

ActiveRecord::Base.record_timestamps = false

Ou utilisez également update_all:

pdate_all (mises à jour, conditions = néant, options = {})

Met à jour tous les enregistrements avec les détails fournis s'ils correspondent à un ensemble de conditions fournies, des limites et une commande peuvent également être fournies. Cette méthode construit une seule instruction SQL UPDATE et l'envoie directement à la base de données. Il n'instancie pas les modèles impliqués et ne déclenche pas de rappels Active Record.

30
Toby Hede

Dans Rails 3+, pour un seul objet, définissez record_timestamps pour l'objet plutôt que pour la classe. C'est à dire.,

>> user = User.first
>> user.updated_at
=> Tue, 12 Apr 2016 22:47:51 GMT +00:00
>> user.name = "Jose"
=> "Jose"
>> user.record_timestamps = false
>> user.save
=> true
>> user.updated_at
=> Tue, 12 Apr 2016 22:47:51 GMT +00:00
>> User.record_timestamps
=> true

De cette façon, vous ne touchez pas à l'état global du modèle et vous n'avez pas à vous rappeler de restaurer le paramètre précédent dans un bloc ensure.

9
Chuck Batson

Comme il s'agit d'une importation unique, vous pouvez effectuer les opérations suivantes:

  1. Créer un modèle à l'aide de legacy_created_at et legacy_updated_at des champs.
  2. Chargez les données héritées. Mappez dans les champs du modèle comme vous le souhaitez. Vous pouvez utiliser #save et ne vous inquiétez généralement pas de l'utilisation de update_all ou similaire, et vous pouvez utiliser des rappels si vous le souhaitez.
  3. Créez une migration pour renommer les colonnes en created_at et updated_at.
3
runako

J'aime utiliser un module mixin pour désactiver temporairement l'horodatage dans un bloc:

module WithoutTimestamps
  def without_timestamps
    old = ActiveRecord::Base.record_timestamps
    ActiveRecord::Base.record_timestamps = false
    begin
      yield
    ensure
      ActiveRecord::Base.record_timestamps = old
    end
  end
end

Ensuite, vous pouvez l'utiliser où vous en avez besoin

class MyModel < ActiveRecord::Base
  include WithoutTimestamps

  def save_without_timestamps
    without_timestamps do
      save!
    end
  end
end

Ou tout simplement comme ceci:

m = MyModel.find(1)
WithoutTimestamps.without_timestamps do
  m.save!
end
3
nonrectangular

Lorsque vous n'êtes pas dans une importation en bloc, vous pouvez remplacer les should_record_timestamps? sur votre modèle pour ajouter de nouvelles vérifications sur le moment de la mise à jour de la colonne updated_at.

2
iwiznia

En me référant à d'autres réponses, j'ai trouvé à ma grande surprise que la désactivation des horodatages pour un seul modèle, comme dans:

User.record_timestamps = false

travaillé pour ma base de données de développement, mais pas sur ma base de données de pré-production, qui fonctionne sur un serveur différent. Cependant, cela fonctionne si je désactive les horodatages pour tous les modèles avec

ActiveRecord::Base.record_timestamps = false

(Situation: modification de l'attribut created_at dans une migration)

2
Christer Fernstrom

Je n'ai pas pu faire ActiveRecord::Base.record_timestamps flag change quoi que ce soit, et la seule façon de travailler est d'utiliser ActiveRecord::Base.no_touching {}:

ActiveRecord::Base.no_touching do
  Project.first.touch  # does nothing
  Message.first.touch  # does nothing
end

Project.no_touching do
  Project.first.touch  # does nothing
  Message.first.touch  # works, but does not touch the associated project
end

Tiré de ici .

Ceci est très utile pour les tâches de rake où vous devez remplacer certaines propriétés de modèles profondément liés et ne pas vous soucier des rappels internes, tandis que vos utilisateurs comptent sur created_at ou updated_at les attributs ou ceux-ci sont utilisés comme colonnes de tri.

1
victorpolko
1
Andrew