DEV: Hand-pick Rails/WhereNot autofixes (#35117)

We can't enable `Rails/WhereNot` lint/autofix, because it would break
code that uses mini_sql instead of AR (which rubocop, and tbh also we,
can't easily differentiate)

Those are safe because they either:
* are executed in AR model scope definitions
* are clearly chained starting from a AR model
* are less-clearly chained, but still can be traced to a AR model/scope

---------

Co-authored-by: Loïc Guitaut <loic@discourse.org>
This commit is contained in:
Jarek Radosz
2025-10-03 13:29:22 +02:00
committed by GitHub
co-authored by Loïc Guitaut
parent e5ca38d2be
commit a54e3208cb
62 changed files with 128 additions and 146 deletions
+1 -1
View File
@@ -117,7 +117,7 @@ class AdminUserIndexQuery
end
def filter_exclude
@query.where("users.id != ?", params[:exclude]) if params[:exclude].present?
@query.where.not(id: params[:exclude]) if params[:exclude].present?
end
def append(active_relation)
+1 -1
View File
@@ -155,7 +155,7 @@ module BackupRestore
SiteIconManager.ensure_optimized!
User
.where("uploaded_avatar_id IS NOT NULL")
.where.not(uploaded_avatar_id: nil)
.find_each do |user|
Jobs.enqueue(:create_avatar_thumbnails, upload_id: user.uploaded_avatar_id)
end
+1 -6
View File
@@ -33,12 +33,7 @@ module DiscourseDev
end
def self.create_needed_topics(count)
topics =
::Topic
.listable_topics
.where("id NOT IN (?)", ::Category.pluck(:topic_id))
.limit(count)
.to_a
topics = ::Topic.listable_topics.where.not(id: ::Category.pluck(:topic_id)).limit(count).to_a
(count - topics.size).times { topics << Topic.new.create! } if topics.size < count
+1 -1
View File
@@ -296,7 +296,7 @@ class PostActionCreator
}
# First try to revive a trashed record
post_action = PostAction.where(where_attrs).with_deleted.where("deleted_at IS NOT NULL").first
post_action = PostAction.where(where_attrs).with_deleted.where.not(deleted_at: nil).first
if post_action
post_action.recover!
+1 -1
View File
@@ -92,7 +92,7 @@ class S3Inventory
.joins(
"LEFT JOIN #{tmp_table_name} inventory2 ON inventory2.url = #{table_name}.url",
)
.where("inventory2.etag IS NOT NULL")
.where.not(inventory2: { etag: nil })
.pluck(:id)
# marking as verified/not verified
+7 -5
View File
@@ -472,7 +472,7 @@ class Search
advanced_filter(/\Ain:first|^f\z/i) { |posts| posts.where("posts.post_number = 1") }
advanced_filter(/\Ain:pinned\z/i) { |posts| posts.where("topics.pinned_at IS NOT NULL") }
advanced_filter(/\Ain:pinned\z/i) { |posts| posts.where.not(topics: { pinned_at: nil }) }
advanced_filter(/\Ain:wiki\z/i) { |posts, match| posts.where(wiki: true) }
@@ -570,7 +570,7 @@ class Search
end
end
advanced_filter(/\Awith:images\z/i) { |posts| posts.where("posts.image_upload_id IS NOT NULL") }
advanced_filter(/\Awith:images\z/i) { |posts| posts.where.not(posts: { image_upload_id: nil }) }
advanced_filter(/\Acategor(?:y|ies):(.+)\z/i) do |posts, terms|
category_ids = []
@@ -866,9 +866,11 @@ class Search
end
elsif @order == :read && @guardian.user
posts =
posts.joins(
"JOIN topic_users tu ON tu.topic_id = posts.topic_id AND tu.user_id = #{@guardian.user.id.to_i}",
).where("tu.last_visited_at IS NOT NULL")
posts
.joins(
"JOIN topic_users tu ON tu.topic_id = posts.topic_id AND tu.user_id = #{@guardian.user.id.to_i}",
)
.where.not(tu: { last_visited_at: nil })
if aggregate_search
posts = posts.order("MAX(tu.last_visited_at) DESC")
+1 -1
View File
@@ -15,7 +15,7 @@ class SuggestedTopicsBuilder
return unless results
# Only add results if we don't have those topic ids already
results = results.where("topics.id NOT IN (?)", @excluded_topic_ids).where(visible: true)
results = results.where.not(topics: { id: @excluded_topic_ids }).where(visible: true)
# If limit suggested to category is enabled, restrict to that category
if @category_id && SiteSetting.limit_suggested_to_category?
+1 -1
View File
@@ -71,7 +71,7 @@ end
task "topics:watch_all_replied_topics" => :environment do
puts "Setting all topics to Watching on which a user has posted at least once..."
topics = Topic.where("archetype != ?", Archetype.private_message)
topics = Topic.where.not(archetype: Archetype.private_message)
total = topics.count
count = 0
+1 -1
View File
@@ -313,7 +313,7 @@ def regenerate_missing_optimized
[
default_scope.where("optimized_images.upload_id IN (?)", avatar_upload_ids),
default_scope
.where("optimized_images.upload_id NOT IN (?)", avatar_upload_ids)
.where.not(upload_id: avatar_upload_ids)
.where("LENGTH(COALESCE(url, '')) > 0")
.where("width > 0 AND height > 0"),
].each do |scope|
+17 -14
View File
@@ -166,7 +166,7 @@ class TopicQuery
AND gu.user_id = #{@user.id.to_i}
",
)
.where("gu.group_id IS NOT NULL")
.where.not(gu: { group_id: nil })
.pluck(:group_id)
target_group_ids = topic.topic_allowed_groups.pluck(:group_id)
@@ -327,7 +327,7 @@ class TopicQuery
def list_read
create_list(:read, unordered: true) do |topics|
topics.where("tu.last_visited_at IS NOT NULL").order("tu.last_visited_at DESC")
topics.where.not(tu: { last_visited_at: nil }).order("tu.last_visited_at DESC")
end
end
@@ -701,7 +701,7 @@ class TopicQuery
)
end
result.where("topics.category_id != ?", drafts_category_id)
result.where.not(topics: { category_id: drafts_category_id })
end
def apply_ordering(result, options = {})
@@ -1025,7 +1025,7 @@ class TopicQuery
category_ids = SiteSetting.default_categories_muted.split("|").map(&:to_i)
category_ids -= [category_id] if category_id.present? && category_ids.include?(category_id)
list = list.where("categories.id NOT IN (?)", category_ids) if category_ids.present?
list = list.where.not(categories: { id: category_ids }) if category_ids.present?
end
list
@@ -1180,16 +1180,17 @@ class TopicQuery
if user_ids.present? && group_ids.present?
messages.where("ta2.topic_id IS NOT NULL OR tg2.topic_id IS NOT NULL")
elsif user_ids.present?
messages.where("ta2.topic_id IS NOT NULL")
messages.where.not(ta2: { topic_id: nil })
elsif group_ids.present?
messages.where("tg2.topic_id IS NOT NULL")
messages.where.not(tg2: { topic_id: nil })
end
end
def messages_for_groups_or_user(group_ids)
if group_ids.present?
base_messages.joins(
"
base_messages
.joins(
"
LEFT JOIN (
SELECT * FROM topic_allowed_groups _tg
LEFT JOIN group_users gu
@@ -1198,20 +1199,23 @@ class TopicQuery
WHERE #{DB.sql_fragment("gu.group_id IN (?)", group_ids)}
) tg ON topics.id = tg.topic_id
",
).where("tg.topic_id IS NOT NULL")
)
.where.not(tg: { topic_id: nil })
else
messages_for_user
end
end
def messages_for_user
base_messages.joins(
"
base_messages
.joins(
"
LEFT JOIN topic_allowed_users ta
ON topics.id = ta.topic_id
AND ta.user_id = #{@user.id.to_i}
",
).where("ta.topic_id IS NOT NULL")
)
.where.not(ta: { topic_id: nil })
end
def base_messages
@@ -1232,8 +1236,7 @@ class TopicQuery
else
excluded_topic_ids += Category.topic_ids.to_a
end
result =
result.where("topics.id NOT IN (?)", excluded_topic_ids) unless excluded_topic_ids.empty?
result = result.where.not(topics: { id: excluded_topic_ids }) unless excluded_topic_ids.empty?
result = remove_muted(result, @user, @options)
+1 -1
View File
@@ -106,7 +106,7 @@ class TopicQuery
list = user_personal_private_messages(user)
list = list.where("topics.subtype = ?", TopicSubtype.moderator_warning)
# Exclude official warnings that the user created, instead of received
list = list.where("topics.user_id <> ?", user.id)
list = list.where.not(topics: { user: })
create_list(:private_messages, {}, list)
end
+2 -2
View File
@@ -485,7 +485,7 @@ class TopicView
def has_deleted?
@predelete_filtered_posts
.with_deleted
.where("posts.deleted_at IS NOT NULL")
.where.not(deleted_at: nil)
.where("posts.post_number > 1")
.exists?
end
@@ -972,7 +972,7 @@ class TopicView
def unfiltered_posts
result = filter_post_types(@topic.posts)
result = result.with_deleted if @guardian.can_see_deleted_posts?(@topic.category)
result = result.where("user_id IS NOT NULL") if @exclude_deleted_users
result = result.where.not(user_id: nil) if @exclude_deleted_users
result = result.where(hidden: false) if @exclude_hidden
result
end
+2 -2
View File
@@ -140,7 +140,7 @@ class TopicsFilter
category = category_id.present? ? Category.find_by(id: category_id) : nil
if @guardian.can_see_deleted_topics?(category)
@scope = @scope.unscope(where: :deleted_at).where("topics.deleted_at IS NOT NULL")
@scope = @scope.unscope(where: :deleted_at).where.not(topics: { deleted_at: nil })
end
when "public"
@scope = @scope.joins(:category).where("NOT categories.read_restricted")
@@ -943,7 +943,7 @@ class TopicsFilter
scope: -> do
if @guardian.authenticated?
ensure_topic_users_reference!
@scope.where("tu.last_visited_at IS NOT NULL")
@scope.where.not(tu: { last_visited_at: nil })
else
# make sure this works for anon (particularly selection)
@scope.joins("LEFT JOIN topic_users tu ON 1 = 0")
+1 -1
View File
@@ -15,7 +15,7 @@ class UniqueAmongValidator < ActiveRecord::Validations::UniquenessValidator
if new_errors.size - old_errors.size != 0
# now look only in the collection we care about.
dupes = options[:collection].call(record).where("lower(#{attribute}) = ?", value.downcase)
dupes = dupes.where("id != ?", record.id) if record.persisted?
dupes = dupes.where.not(id: record.id) if record.persisted?
# pop off the error, if it was a false positive
if !dupes.exists?