Supprimer définitivement les publications supprimées en masse ?

If I am not mistaken there is a field called deleted_at

If it is deleted, then there should be a date time Stamp.

If it is not deleted then is null

Maybe look for the entry that is <> Null and delete

1 « J'aime »

Thanks Gav, but the ones that I am targeting aren’t marked as deleted. Rather, their Topic has been deleted and then destroy_all’d.

2 « J'aime »

I was playing around with this and i notice that part of your query was not returning the response you need.

SELECT topic_id from posts does not return an integer, but it returned a string

image

This might be the cause that your db still contains orphaned posts.

2 « J'aime »

Je pense que vous voyez l’Explorateur de données convertir automatiquement l’entier en URL, ce qu’il fait lorsque le libellé est topic_id.

Lorsque j’exécute cette requête dans l’Explorateur de données, tous les messages que j’essaie d’identifier sont capturés (bien plus de 5000) :

SELECT id, topic_id
FROM posts
WHERE topic_id not in (select id from topics)
ORDER by id

Je fais clairement quelque chose de mal avec ma syntaxe Rails car c’est ce que j’obtiens :

[1] pry(main)=> Target = Post.where('topic_id not in (select id from topics)')
=> []

Quelqu’un peut-il me dire ce que je fais de mal ?

1 « J'aime »

Eh bien, grâce à @pfaffman, j’ai identifié les publications pertinentes en utilisant ceci :

Post.find_by_sql("select id from posts where topic_id not in (select id from topics)")

J’obtiens ce résultat :

[1] pry(main)> Post.find_by_sql(“select id from posts where topic_id not in (select id from topics)”)
=> [#<Post:0x000055df30d4ee90 id: 150>,
#<Post:0x000055df2e538ff0 id: 51097>,
#<Post:0x000055df2e50ba28 id: 83>,
#<Post:0x000055df2e4ee8b0 id: 40636>,
#<Post:0x000055df2e4a92d8 id: 62562>,
#<Post:0x000055df2e4b7978 id: 13522>,
etc.

Cependant, je n’arrive pas à comprendre comment appliquer destroy_all à cette sélection.

Ceci pourrait aider (pour mon propre bénéfice) :

Des suggestions ?

1 « J'aime »

Je pense que cela fonctionnera

posts=
Post.find_by_sql("select id from posts where topic_id not in (select id from topics)")


posts.destroy_all

Ou vous pourriez ajouter .destroy_all à votre find_by_sql

2 « J'aime »

J’ai essayé cela. Les données semblent être retournées sous forme de tableau avec un identifiant de publication et un ID (voir Delete deleted-posts permanently in bulk? - #45 by nathank).

Voici l’erreur que j’obtiens lorsque j’ajoute .destroy_all ou que j’utilise posts= que vous suggérez :

[2] pry(main)> posts.destroy_all
NoMethodError: undefined method destroy_all' for #<Array:0x000055fe7bc7fc98> from (pry):3:in pry

1 « J'aime »

Oh. Alors peut-être voir si

 p=posts.first

Est un post_id. Si c’est le cas, alors vous pouvez

x=Post.find(p)
x.destroy

Ensuite, vous pourriez parcourir ceux-ci.

Je pense que vous devriez encapsuler votre requête dans quelque chose pour en faire un tableau de posts plutôt que des identifiants de posts.

1 « J'aime »

Merci Jay. Voici ce que j’obtiens :

[3] pry(main)> p=
[3] pry(main)* posts.first
=> #<Post:0x0000563a24cab908 id: 150>
[4] pry(main)> x=Post.find(p)
ArgumentError: You are passing an instance of ActiveRecord::Base to find. Please pass the id of the object by calling .id.
from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activerecord-6.1.4.1/lib/active_record/relation/finder_methods.rb:467:in `find_one’

Maintenant, parlez-moi de ces choses d’encapsulation. C’est tellement énervant, parce que je sais que la commande Rails de @Sam ici devrait fonctionner, mais je pense que Rails a changé depuis :

1 « J'aime »

Qu’est-ce que cela a fait ? Je n’arrive pas à imaginer que Rails ait changé.

1 « J'aime »

Cela vous donne-t-il les publications que vous souhaitez supprimer ?

1 « J'aime »

J’ai lu quelque part en ligne en cherchant comment convertir un tableau Active Record en une relation Active Record que les choses avaient changé entre Rails 3.x et Rails 4 et que la syntaxe devait être différente, mais cela m’a dépassé.

Cela semblait en récupérer quelques-unes lorsque je l’ai exécuté pour la première fois, et je les ai dûment détruites. Mais il n’y en avait pas beaucoup. Maintenant, il n’en récupère aucune, alors que le SQL en récupère des milliers lorsqu’il est exécuté dans Data Explorer.

Ce sont des publications orphelines, où le sujet a été détruit.

1 « J'aime »

Pouvez-vous utiliser each{} pour parcourir les membres de ce tableau, en appelant destroy sur chaque publication individuellement ?

Post.find_by_sql(“select id from posts where topic_id not in (select id from topics)”).each { |p| p.destroy }
2 « J'aime »

Eh bien, j’ai essayé. D’abord, il n’a pas aimé le SQL enveloppé de cette façon ni la syntaxe :

Post.find_by_sql(“select id from posts where topic_id not in (select id from topics)”).each { |p| p.destroy_all }
SyntaxError : inattendu in', attendu (’
…rom posts where topic_id not in (select id from topics)”)…
… ^~
SyntaxError : variable locale ou méthode inattendue, attendu fin d’entrée
…t in (select id from topics)”).each { |p| p.destroy_all }

Alors j’ai essayé une autre astuce en le divisant :

posts=Post.find_by_sql("select id from posts where topic_id not in (select id from topics)")
posts.each do |p|
p.destroy
end

Cela a semblé fonctionner correctement, mais l’ajout de p.destroy provoque ceci :

ActiveModel::MissingAttributeError : attribut manquant : user_id
from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activemodel-6.1.4.1/lib/active_model/attribute.rb:222:in `value’

J’ai essayé plusieurs façons de l’intégrer, mais j’ai abandonné. @sam, pouvez-vous aider ?

P.S.

J’ai même essayé de convertir le SQL en AR via scuttle.io comme ceci :

Post.select([:id, :topic_id]).where(Topic.select(:id))

Hélas, j’obtiens cette erreur :

ArgumentError : type d’argument non pris en charge : #Topic::ActiveRecord_Relation:0x000055c67a7131d0 (Topic::ActiveRecord_Relation)

3 « J'aime »

Quand j’ai copié-collé cette partie d’un message précédent, il semble que les guillemets aient été convertis en guillemets typographiques quelque part, je suppose que c’est la vraie erreur. Désolé pour ça.

find_by_sql est décrit comme retournant un objet avec les valeurs spécifiées dans la requête SQL, ce qui signifie probablement que vous récupérez un objet Post qui n’a que la propriété id définie, user_id et tout le reste est manquant.

... find_by_sql("select * ... s’en chargera. Il y a probablement un sous-ensemble de valeurs que vous pourriez sélectionner pour obtenir une destruction, plutôt que de tout sélectionner, mais je ne sais pas quel serait ce sous-ensemble.

Donc, le tout : (sans guillemets typographiques cette fois…)

Post.find_by_sql("select * from posts where topic_id not in (select id from topics)").each { |p| p.destroy }
4 « J'aime »

:partying_face: Alléluia!!! :partying_face:

Merci Simon - ça a marché à merveille. Les publications orphelines ont toutes disparu et je m’attends à ce que mes téléchargements diminuent considérablement dans les prochaines 24 heures environ.

plus tard
Et ils l’ont fait ! 3,5 Go à 0,7 Go. Génial !!

7 « J'aime »

Excellent, je suis ravi d’apprendre que cela a fonctionné pour vous. Donc, pour combiner les réponses, on peut utiliser ce qui suit dans la console Rails pour détruire tous les sujets qui ont été supprimés il y a plus de 90 jours, en répétant autant de fois que nécessaire s’il y a plus de 1000 sujets :

Topic.with_deleted.where(deleted_at: ...90.days.ago).limit(1000).destroy_all

Une fois cela terminé, on peut utiliser ce qui suit pour détruire tous les messages orphelins de sujets détruits :

Post.find_by_sql("select * from posts where topic_id not in (select id from topics)").each { |p| p.destroy }

Il convient de noter que les commandes ci-dessus ne détruiront pas les messages supprimés, seulement les sujets supprimés et leurs messages orphelins. Pour détruire également les messages supprimés de plus de 90 jours, utilisez ce qui suit, en répétant à nouveau si nécessaire :

Post.with_deleted.where(deleted_at: ...90.days.ago).limit(1000).destroy_all

P.S. Par curiosité, avez-vous essayé destroy_all sans limit(1000) et rencontré des problèmes, ou ne l’avez-vous pas essayé sans la limite ?

8 « J'aime »

J’ai essayé sans la limite et quelque chose est devenu un peu fou - mais j’ai oublié les détails, désolé.

Pouvons-nous marquer votre publication comme solution ou utiliser celle de l’OP ?

image

3 « J'aime »

Pas de soucis. Si vous n’aviez pas essayé, j’aurais ajouté une note indiquant que la limite pourrait ne pas être nécessaire, mais puisque vous avez eu des problèmes, je peux simplement la laisser telle quelle.

1 « J'aime »

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.