Use excluding instead of where.not(id:

This method was added in Rails 7.0 and makes the code slihgtly more
readable.

The downside is that it generates two queries instead of one, so it
might generate some confusion when debugging SQL queries. Its impact on
performance is probably negligible.
This commit is contained in:
Javi Martín
2024-04-06 18:51:52 +02:00
parent 9841a9b03a
commit 38ad65605e
14 changed files with 19 additions and 23 deletions

View File

@@ -164,7 +164,7 @@ class ProposalsController < ApplicationController
.sort_by_confidence_score .sort_by_confidence_score
.limit(Setting["featured_proposals_number"]) .limit(Setting["featured_proposals_number"])
if @featured_proposals.present? if @featured_proposals.present?
@resources = @resources.where.not(id: @featured_proposals) @resources = @resources.excluding(@featured_proposals)
end end
end end
end end

View File

@@ -43,7 +43,7 @@ module ActsAsParanoidAliases
end end
def without_confirmed_hide def without_confirmed_hide
where(confirmed_hide_at: nil) excluding(with_confirmed_hide)
end end
def with_hidden def with_hidden

View File

@@ -20,7 +20,7 @@ class Banner < ApplicationRecord
has_many :web_sections, through: :sections has_many :web_sections, through: :sections
scope :with_active, -> { where(post_started_at: ..Date.current, post_ended_at: Date.current..) } scope :with_active, -> { where(post_started_at: ..Date.current, post_ended_at: Date.current..) }
scope :with_inactive, -> { where.not(id: with_active) } scope :with_inactive, -> { excluding(with_active) }
scope :in_section, ->(section_name) do scope :in_section, ->(section_name) do
joins(:web_sections, :sections).where("web_sections.name ilike ?", section_name) joins(:web_sections, :sections).where("web_sections.name ilike ?", section_name)
end end

View File

@@ -47,7 +47,7 @@ class Budget < ApplicationRecord
accepts_nested_attributes_for :phases accepts_nested_attributes_for :phases
scope :published, -> { where(published: true) } scope :published, -> { where(published: true) }
scope :drafting, -> { where.not(id: published) } scope :drafting, -> { excluding(published) }
scope :informing, -> { where(phase: "informing") } scope :informing, -> { where(phase: "informing") }
scope :accepting, -> { where(phase: "accepting") } scope :accepting, -> { where(phase: "accepting") }
scope :reviewing, -> { where(phase: "reviewing") } scope :reviewing, -> { where(phase: "reviewing") }

View File

@@ -73,7 +73,7 @@ class Budget
scope :valuation_open, -> { where(valuation_finished: false) } scope :valuation_open, -> { where(valuation_finished: false) }
scope :with_admin, -> { where.not(administrator_id: nil) } scope :with_admin, -> { where.not(administrator_id: nil) }
scope :without_admin, -> { where(administrator_id: nil) } scope :without_admin, -> { excluding(with_admin) }
scope :without_valuator_group, -> { where(valuator_group_assignments_count: 0) } scope :without_valuator_group, -> { where(valuator_group_assignments_count: 0) }
scope :without_valuator, -> { without_valuator_group.where(valuator_assignments_count: 0) } scope :without_valuator, -> { without_valuator_group.where(valuator_assignments_count: 0) }
scope :under_valuation, -> { valuation_open.valuating.with_admin } scope :under_valuation, -> { valuation_open.valuating.with_admin }
@@ -87,7 +87,7 @@ class Budget
scope :valuation_finished_feasible, -> { where(valuation_finished: true, feasibility: "feasible") } scope :valuation_finished_feasible, -> { where(valuation_finished: true, feasibility: "feasible") }
scope :feasible, -> { where(feasibility: "feasible") } scope :feasible, -> { where(feasibility: "feasible") }
scope :unfeasible, -> { where(feasibility: "unfeasible") } scope :unfeasible, -> { where(feasibility: "unfeasible") }
scope :not_unfeasible, -> { where.not(feasibility: "unfeasible") } scope :not_unfeasible, -> { excluding(unfeasible) }
scope :undecided, -> { where(feasibility: "undecided") } scope :undecided, -> { where(feasibility: "undecided") }
scope :with_supports, -> { where(cached_votes_up: 1..) } scope :with_supports, -> { where(cached_votes_up: 1..) }

View File

@@ -3,7 +3,7 @@ module Verification
included do included do
scope :residence_verified, -> { where.not(residence_verified_at: nil) } scope :residence_verified, -> { where.not(residence_verified_at: nil) }
scope :residence_unverified, -> { where(residence_verified_at: nil) } scope :residence_unverified, -> { excluding(residence_verified) }
scope :residence_and_phone_verified, -> { residence_verified.where.not(confirmed_phone: nil) } scope :residence_and_phone_verified, -> { residence_verified.where.not(confirmed_phone: nil) }
scope :residence_or_phone_unverified, -> { residence_unverified.or(where(confirmed_phone: nil)) } scope :residence_or_phone_unverified, -> { residence_unverified.or(where(confirmed_phone: nil)) }
scope :phone_not_fully_confirmed, -> { where(unconfirmed_phone: nil).or(where(confirmed_phone: nil)) } scope :phone_not_fully_confirmed, -> { where(unconfirmed_phone: nil).or(where(confirmed_phone: nil)) }

View File

@@ -6,8 +6,8 @@ class Dashboard::AdministratorTask < ApplicationRecord
default_scope { order(created_at: :asc) } default_scope { order(created_at: :asc) }
scope :pending, -> { where(executed_at: nil) }
scope :done, -> { where.not(executed_at: nil) } scope :done, -> { where.not(executed_at: nil) }
scope :pending, -> { excluding(done) }
def title def title
"#{source.proposal.title} #{source.action.title}" "#{source.proposal.title} #{source.action.title}"

View File

@@ -80,7 +80,7 @@ class Poll < ApplicationRecord
where("? < ends_at and ? >= starts_at", where("? < ends_at and ? >= starts_at",
poll.starts_at.beginning_of_day, poll.starts_at.beginning_of_day,
poll.ends_at.end_of_day) poll.ends_at.end_of_day)
.where.not(id: poll.id) .excluding(poll)
.where(related: poll.related) .where(related: poll.related)
end end

View File

@@ -20,7 +20,7 @@ class Poll::Question::Option < ApplicationRecord
validates_translation :title, presence: true validates_translation :title, presence: true
validates :given_order, presence: true, uniqueness: { scope: :question_id } validates :given_order, presence: true, uniqueness: { scope: :question_id }
scope :with_content, -> { where.not(id: without_content) } scope :with_content, -> { excluding(without_content) }
scope :without_content, -> do scope :without_content, -> do
where(description: "") where(description: "")
.where.missing(:images) .where.missing(:images)

View File

@@ -79,14 +79,14 @@ class Proposal < ApplicationRecord
scope :not_archived, -> { where(created_at: Setting.archived_proposals_date_limit..) } scope :not_archived, -> { where(created_at: Setting.archived_proposals_date_limit..) }
scope :last_week, -> { where(created_at: 7.days.ago..) } scope :last_week, -> { where(created_at: 7.days.ago..) }
scope :retired, -> { where.not(retired_at: nil) } scope :retired, -> { where.not(retired_at: nil) }
scope :not_retired, -> { where(retired_at: nil) } scope :not_retired, -> { excluding(retired) }
scope :successful, -> { where(cached_votes_up: Proposal.votes_needed_for_success..) } scope :successful, -> { where(cached_votes_up: Proposal.votes_needed_for_success..) }
scope :unsuccessful, -> { where(cached_votes_up: ...Proposal.votes_needed_for_success) } scope :unsuccessful, -> { where(cached_votes_up: ...Proposal.votes_needed_for_success) }
scope :public_for_api, -> { all } scope :public_for_api, -> { all }
scope :selected, -> { where(selected: true) } scope :selected, -> { where(selected: true) }
scope :not_selected, -> { where(selected: false) } scope :not_selected, -> { where(selected: false) }
scope :published, -> { where.not(published_at: nil) } scope :published, -> { where.not(published_at: nil) }
scope :draft, -> { where(published_at: nil) } scope :draft, -> { excluding(published) }
scope :not_supported_by_user, ->(user) { where.not(id: user.find_voted_items(votable_type: "Proposal")) } scope :not_supported_by_user, ->(user) { where.not(id: user.find_voted_items(votable_type: "Proposal")) }
scope :created_by, ->(author) { where(author: author) } scope :created_by, ->(author) { where(author: author) }
@@ -108,15 +108,11 @@ class Proposal < ApplicationRecord
tagged_with(user.interests, any: true) tagged_with(user.interests, any: true)
.where.not(author_id: user.id) .where.not(author_id: user.id)
.unsuccessful .unsuccessful
.not_followed_by_user(user) .excluding(followed_by_user(user))
.not_archived .not_archived
.not_supported_by_user(user) .not_supported_by_user(user)
end end
def self.not_followed_by_user(user)
where.not(id: followed_by_user(user).ids)
end
def to_param def to_param
"#{id}-#{title}".parameterize "#{id}-#{title}".parameterize
end end

View File

@@ -16,7 +16,7 @@ class ProposalNotification < ApplicationRecord
scope :sort_by_moderated, -> { reorder(moderated: :desc) } scope :sort_by_moderated, -> { reorder(moderated: :desc) }
scope :moderated, -> { where(moderated: true) } scope :moderated, -> { where(moderated: true) }
scope :not_moderated, -> { where(moderated: false) } scope :not_moderated, -> { excluding(moderated) }
scope :pending_review, -> { moderated.where(ignored_at: nil) } scope :pending_review, -> { moderated.where(ignored_at: nil) }
scope :ignored, -> { moderated.where.not(ignored_at: nil) } scope :ignored, -> { moderated.where.not(ignored_at: nil) }

View File

@@ -104,8 +104,8 @@ class User < ApplicationRecord
where(document_type: document_type, document_number: document_number) where(document_type: document_type, document_number: document_number)
end end
scope :email_digest, -> { where(email_digest: true) } scope :email_digest, -> { where(email_digest: true) }
scope :active, -> { where(erased_at: nil) }
scope :erased, -> { where.not(erased_at: nil) } scope :erased, -> { where.not(erased_at: nil) }
scope :active, -> { excluding(erased) }
scope :public_for_api, -> { all } scope :public_for_api, -> { all }
scope :by_authors, ->(author_ids) { where(id: author_ids) } scope :by_authors, ->(author_ids) { where(id: author_ids) }
scope :by_comments, ->(commentables) do scope :by_comments, ->(commentables) do

View File

@@ -1,19 +1,19 @@
section "Flagging Debates & Comments" do section "Flagging Debates & Comments" do
40.times do 40.times do
debate = Debate.sample debate = Debate.sample
flagger = User.where.not(id: debate.author_id).sample flagger = User.excluding(debate.author).sample
Flag.flag(flagger, debate) Flag.flag(flagger, debate)
end end
40.times do 40.times do
comment = Comment.sample comment = Comment.sample
flagger = User.where.not(id: comment.user_id).sample flagger = User.excluding(comment.user).sample
Flag.flag(flagger, comment) Flag.flag(flagger, comment)
end end
40.times do 40.times do
proposal = Proposal.sample proposal = Proposal.sample
flagger = User.where.not(id: proposal.author_id).sample flagger = User.excluding(proposal.author).sample
Flag.flag(flagger, proposal) Flag.flag(flagger, proposal)
end end
end end

View File

@@ -1,5 +1,5 @@
section "Voting Debates, Proposals & Comments" do section "Voting Debates, Proposals & Comments" do
not_org_users = User.where.not(id: User.organizations) not_org_users = User.excluding(User.organizations)
100.times do 100.times do
voter = not_org_users.level_two_or_three_verified.sample voter = not_org_users.level_two_or_three_verified.sample
vote = [true, false].sample vote = [true, false].sample