docbrown/app/models/audience_segment.rb
PJ cee84b49ef
Exclude manual segments from dropdown in billboard admin form (#19677)
* exclude manual segments from audience segments dropdown

* specs 🎉

* fix deleteDisplayAds specs

* add seed for display ad with manually managed segment

* moar specs
2023-07-12 20:23:50 +01:00

81 lines
2.6 KiB
Ruby

class AudienceSegment < ApplicationRecord
# enum does not like names that start with "not_"
enum type_of: {
manual: 0, # never matches anyone, used in test factory
trusted: 1,
posted: 2,
no_posts_yet: 3,
dark_theme: 4,
light_theme: 5,
no_experience: 6,
experience1: 7,
experience2: 8,
experience3: 9,
experience4: 10,
experience5: 11
}
has_many :segmented_users, dependent: :destroy
has_many :users, through: :segmented_users
after_validation :persist_recently_active_users, unless: :manual?
QUERIES = {
manual: ->(scope = User) { scope.where(id: nil) },
trusted: ->(scope = User) { scope.with_role(:trusted) },
no_posts_yet: ->(scope = User) { scope.where(articles_count: 0) },
posted: ->(scope = User) { scope.where("articles_count > 0") },
dark_theme: ->(scope = User) { scope.where(id: Users::Setting.dark_theme.select(:user_id)) },
light_theme: ->(scope = User) { scope.where(id: Users::Setting.light_theme.select(:user_id)) },
experience1: ->(scope = User) { scope.with_experience_level(1) },
# see SettingsHelper#user_experience_levels
experience2: ->(scope = User) { scope.with_experience_level(3) },
experience3: ->(scope = User) { scope.with_experience_level(5) },
experience4: ->(scope = User) { scope.with_experience_level(8) },
experience5: ->(scope = User) { scope.with_experience_level(10) },
no_experience: ->(scope = User) { scope.with_experience_level(nil) }
}.freeze
def self.scoped_users_in_segment(segment_type, scope: nil)
query_for_segment(segment_type)&.call(scope) || []
end
def self.all_users_in_segment(segment_type, scope: User)
query_for_segment(segment_type)&.call(scope) || []
end
def self.recently_active_users_in_segment(segment_type, scope: User.recently_active)
scoped_users_in_segment(segment_type, scope: scope)
end
def self.query_for_segment(segment_type)
QUERIES[segment_type.to_sym]
end
def self.human_readable_description_for(type)
I18n.t("models.#{model_name.i18n_key}.type_ofs.#{type}")
end
def self.including_user_counts
left_joins(:segmented_users)
.select("audience_segments.*, COUNT(segmented_users.id) AS user_count")
.group("audience_segments.id")
end
def persist_recently_active_users
self.users = self.class.recently_active_users_in_segment(type_of)
end
def all_users_in_segment
return users if manual?
self.class.all_users_in_segment(type_of)
end
def includes?(user_or_id)
user_id = user_or_id.respond_to?(:id) ? user_or_id.id : user_or_id
all_users_in_segment.exists?(user_id)
end
alias refresh! save!
end