有任何用于检测孤立记录的 Rails 插件/gems 吗?
寻找可以遍历模型中定义的关系并可以检查数据库中的孤立记录/表之间断开的链接的东西。
Looking for something that can go through the relationships defined in models and can check the DB for orphaned records/broken links between tables.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
(有关以下脚本的最新版本,请参阅 https://gist.github.com/KieranP/3849777< /a>)
Martin 脚本的问题在于它使用 ActiveRecord 首先提取记录,然后查找关联,然后获取关联。它为每个关联生成大量 SQL 调用。对于小型应用程序来说这还不错,但是当您有多个包含 100k 条记录的表并且每个表都有 5 个以上的 own_to 时,它可能需要 10 分钟以上才能完成。
以下脚本使用 SQL,在 Rails 应用程序内的 app/models 中查找所有模型的孤立的 own_to 关联。它处理简单的belongs_to、belongs_to using :class_name 和多态belongs_to 调用。在我使用的生产数据上,Martin 脚本的稍微修改版本的运行时间从 9 分钟减少到仅 8 秒,并且发现了与以前相同的所有问题。
享受 :-)
(for the latest version of the script below, see https://gist.github.com/KieranP/3849777)
The problem with Martin's script is that it uses ActiveRecord to first pull records, then find the associations, then fetch the associations. It generates a ton of SQL calls for each of the associations. It's not bad for a small app, but when you have a multiple tables with 100k records and each with 5+ belongs_to, it can take well into the 10+ minute mark to complete.
The following script uses SQL instead, looks for orphaned belongs_to associations for all models in app/models within a Rails app. It handles simple belongs_to, belongs_to using :class_name, and polymorphic belongs_to calls. On the production data I was using, it dropped the runtime of a slightly modified version of Martin's script from 9 minutes to just 8 seconds, and it found all the same issues as before.
Enjoy :-)
这可能取决于您想对孤儿采取什么行动。也许您只是想删除它们?通过几个 SQL 查询就可以轻松解决这个问题。
This might depend on what action you want to take with the orphans. Perhaps you just want to delete them? That would be easily solved with a couple of SQL queries.
具有相同的任务,并且当前的发现者以以下方式结束:
摆脱所有同时失去其类别的产品。
Had the same task and with the current finders ended along the lines of:
to get rid of all Products, which have lost their Category meanwhile.
您可以创建 Rake 任务来搜索和处理孤立记录,例如:
You can create a Rake task to search for and handle orphaned records, for example:
假设您有一个用户可以订阅杂志的应用程序。对于 ActiveRecord 关联,它看起来像这样:
不幸的是,有人忘记将 dependent: :destroy 添加到 has_many :subscriptions 中。当删除用户或杂志时,会留下孤立的订阅。
这个问题已被 dependent: :destroy 修复,但仍然存在大量孤立记录。
您可以使用两种方法来删除孤立记录。
方法 1 — 不良气味
这对每条记录执行单独的 SQL 查询,检查它是否是孤立的,如果是则销毁它。
方法 2 — 好闻
这种方法首先获取所有用户和杂志的 ID,然后执行一个查询来查找不属于用户或查询的所有订阅。
Let’s say you have an application where a User can subscribe to a Magazine. With ActiveRecord associations, it would look something like this:
Unfortunately, someone forgot to add dependent: :destroy to the has_many :subscriptions. When a user or magazine was deleted, an orphaned subscription was left behind.
This issue was fixed by dependent: :destroy, but there was still a large number of orphaned records lingering around.
There are two ways you can use to remove the orphaned records.
Approach 1 — Bad Smell
This executes a separate SQL query for each record, checks whether it is orphaned, and destroys it if it is.
Approach 2 — Good Smell
This approach first gets the IDs of all Users and Magazines, and then executes one query to find all Subscriptions that don’t belong to either a User or a Query.
KieranP 的回答对我有很大帮助,但他的脚本不处理命名空间类。我添加了几行来执行此操作,同时忽略关注目录。如果您想删除所有孤立记录,我还添加了一个可选的 DELETE=true 命令行参数。
KieranP's answer was a big help for me but his script does not handle namespaced classes. I added a few lines to do so, whilst ignoring the concerns directory. I also added an optional DELETE=true command line arg if you want to nuke all orphaned records.
我创建了一个名为 OrphanRecords 的 gem。它提供了用于显示/删除孤立记录的 rake 任务。目前不支持 HABTM 关联,如果您有兴趣,请随时贡献 :)
I have created a gem called OrphanRecords. It provides rake tasks for show/delete the orphan records. Currently it is not supporting HABTM association, if you are interested please feel free to contribute :)
我在我的 gem 中编写了一个方法来执行此操作 PolyBelongsTo
您可以通过调用来查找所有孤立记录任何 ActiveRecord 模型上的 pbt_orphans 方法。
Gemfile
代码示例
返回所有孤立记录。
如果您只想检查单个记录是否为孤立记录,可以使用 :orphan? 方法来完成。
适用于多态关系和非多态关系。
作为奖励,如果您想查找具有无效类型的多态记录,您可以执行以下操作:
返回 Story 记录中使用的无效 ActiveRecord 模型名称的记录数组。记录的类型如 [“Object”、“Class”、“Storyable”]。
I've written a method to do just this in my gem PolyBelongsTo
You can find all orphaned records by calling the pbt_orphans method on any ActiveRecord model.
Gemfile
Code example
All orphaned records are returned.
If you just want to check if a single record is orphaned you can do it with the :orphan? method.
Works for both polymorphic relations and non-polymorphic relations.
As a bonus if you want to find polymorphic records with invalid types you can do the following:
Returns an Array of records of invalid ActiveRecord model names used in your Story records. Records with types like ["Object", "Class", "Storyable"].