diff --git a/app/logical/approver_pruner.rb b/app/logical/approver_pruner.rb index 03172f50f..0fc6cda6e 100644 --- a/app/logical/approver_pruner.rb +++ b/app/logical/approver_pruner.rb @@ -5,7 +5,7 @@ module ApproverPruner MINIMUM_APPROVALS = 30 def inactive_approvers - approvers = User.where("bit_prefs & ? > 0", User.flag_value_for("can_approve_posts")) + approvers = User.bit_prefs_match(:can_approve_posts, true) approvers = approvers.where("level < ?", User::Levels::MODERATOR) recently_promoted_approvers = UserFeedback.where("created_at >= ?", APPROVAL_PERIOD.ago).where_like(:body, "*You gained the ability to approve posts*").select(:user_id) diff --git a/app/logical/danbooru/has_bit_flags.rb b/app/logical/danbooru/has_bit_flags.rb index 6e7fa2ce7..b130e1cc6 100644 --- a/app/logical/danbooru/has_bit_flags.rb +++ b/app/logical/danbooru/has_bit_flags.rb @@ -5,18 +5,10 @@ module Danbooru module ClassMethods # NOTE: the ordering of attributes has to be fixed# # new attributes should be appended to the end. - def has_bit_flags(attributes, options = {}) - field = options[:field] || :bit_flags - + def has_bit_flags(attributes, field: :bit_flags) attributes.each.with_index do |attribute, i| bit_flag = 1 << i - define_singleton_method("flag_value_for") do |key| - index = attributes.index(key) - raise IndexError if index.nil? - 1 << index - end - define_method(attribute) do send(field) & bit_flag > 0 end @@ -33,6 +25,15 @@ module Danbooru end end end + + # bit_prefs_match + define_singleton_method("#{field}_match") do |flag, value| + value = value ? 1 : 0 + bits = attributes.length + bit_index = bits - attributes.index(flag.to_s) - 1 + + where(sanitize_sql(["get_bit(bit_prefs::bit(?), ?) = ?", bits, bit_index, value])) + end end end end diff --git a/app/models/user.rb b/app/models/user.rb index b5c8ecb09..c380e759a 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -730,35 +730,14 @@ class User < ApplicationRecord q = q.where("level <= ?", params[:max_level].to_i) end - bitprefs_length = BOOLEAN_ATTRIBUTES.length - bitprefs_include = nil - bitprefs_exclude = nil - - [:can_approve_posts, :can_upload_free, :is_super_voter].each do |x| - if params[x].present? - attr_idx = BOOLEAN_ATTRIBUTES.index(x.to_s) - if params[x].to_s.truthy? - bitprefs_include ||= "0" * bitprefs_length - bitprefs_include[attr_idx] = '1' - elsif params[x].to_s.falsy? - bitprefs_exclude ||= "0" * bitprefs_length - bitprefs_exclude[attr_idx] = '1' - end + %w[can_approve_posts can_upload_free is_super_voter].each do |flag| + if params[flag].to_s.truthy? + q = q.bit_prefs_match(flag, true) + elsif params[flag].to_s.falsy? + q = q.bit_prefs_match(flag, false) end end - if bitprefs_include - bitprefs_include.reverse! - q = q.where("bit_prefs::bit(:len) & :bits::bit(:len) = :bits::bit(:len)", - :len => bitprefs_length, :bits => bitprefs_include) - end - - if bitprefs_exclude - bitprefs_exclude.reverse! - q = q.where("bit_prefs::bit(:len) & :bits::bit(:len) = 0::bit(:len)", - :len => bitprefs_length, :bits => bitprefs_exclude) - end - if params[:current_user_first].to_s.truthy? && !CurrentUser.is_anonymous? q = q.order(Arel.sql("id = #{CurrentUser.id} desc")) end diff --git a/test/factories/user.rb b/test/factories/user.rb index 3d6741c43..3f9153cde 100644 --- a/test/factories/user.rb +++ b/test/factories/user.rb @@ -35,12 +35,12 @@ FactoryBot.define do factory(:contributor_user) do level {32} - bit_prefs {User.flag_value_for("can_upload_free")} + can_upload_free {true} end factory(:contrib_user) do level {32} - bit_prefs {User.flag_value_for("can_upload_free")} + can_upload_free {true} end factory(:moderator_user) do