mirror of
https://github.com/discourse/discourse.git
synced 2025-02-25 18:55:32 -06:00
FEATURE: Badge progress
- Refactor model so it stores backfill query - Implement autobiographer - Remove sample badge - Correct featured badges to only include a badge once
This commit is contained in:
parent
8701a39044
commit
9a9ad9bda8
@ -233,7 +233,7 @@ class UsersController < ApplicationController
|
|||||||
end
|
end
|
||||||
|
|
||||||
flash[:success] = I18n.t(message)
|
flash[:success] = I18n.t(message)
|
||||||
end
|
end
|
||||||
|
|
||||||
def change_email
|
def change_email
|
||||||
params.require(:email)
|
params.require(:email)
|
||||||
|
@ -28,11 +28,11 @@ module Jobs
|
|||||||
# Grant "Welcome" badge to the user if they do not already have it.
|
# Grant "Welcome" badge to the user if they do not already have it.
|
||||||
BadgeGranter.grant(Badge.find(5), user)
|
BadgeGranter.grant(Badge.find(5), user)
|
||||||
|
|
||||||
Badge.like_badge_info.each do |b|
|
Badge.like_badge_counts.each do |badge_id, count|
|
||||||
if post.like_count >= b[:count]
|
if post.like_count >= count
|
||||||
BadgeGranter.grant(Badge.find(b[:id]), user, post_id: post.id)
|
BadgeGranter.grant(Badge.find(badge_id), user, post_id: post.id)
|
||||||
else
|
else
|
||||||
user_badge = UserBadge.find_by(badge_id: b[:id], user_id: user.id, post_id: post.id)
|
user_badge = UserBadge.find_by(badge_id: badge_id, user_id: user.id, post_id: post.id)
|
||||||
user_badge && BadgeGranter.revoke(user_badge)
|
user_badge && BadgeGranter.revoke(user_badge)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -4,7 +4,9 @@ module Jobs
|
|||||||
every 1.day
|
every 1.day
|
||||||
|
|
||||||
def execute(args)
|
def execute(args)
|
||||||
BadgeGranter.backfill_like_badges
|
Badge.all.each do |b|
|
||||||
|
BadgeGranter.backfill(b)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -1,4 +1,58 @@
|
|||||||
class Badge < ActiveRecord::Base
|
class Badge < ActiveRecord::Base
|
||||||
|
|
||||||
|
# badge ids
|
||||||
|
Welcome = 5
|
||||||
|
NicePost = 6
|
||||||
|
GoodPost = 7
|
||||||
|
GreatPost = 8
|
||||||
|
Autobiographer = 9
|
||||||
|
|
||||||
|
# other consts
|
||||||
|
AutobiographerMinBioLength = 10
|
||||||
|
|
||||||
|
|
||||||
|
module Queries
|
||||||
|
Welcome = <<SQL
|
||||||
|
SELECT p.user_id, min(post_id) post_id, min(pa.created_at) granted_at
|
||||||
|
FROM post_actions pa
|
||||||
|
JOIN posts p on p.id = pa.post_id
|
||||||
|
JOIN topics t on t.id = p.topic_id
|
||||||
|
WHERE p.deleted_at IS NULL AND
|
||||||
|
t.deleted_at IS NULL AND
|
||||||
|
t.visible AND
|
||||||
|
post_action_type_id = 2
|
||||||
|
GROUP BY p.user_id
|
||||||
|
SQL
|
||||||
|
|
||||||
|
Autobiographer = <<SQL
|
||||||
|
SELECT u.id user_id, current_timestamp granted_at
|
||||||
|
FROM users u
|
||||||
|
JOIN user_profiles up on u.id = up.user_id
|
||||||
|
WHERE bio_raw IS NOT NULL AND LENGTH(TRIM(bio_raw)) > #{Badge::AutobiographerMinBioLength} AND
|
||||||
|
uploaded_avatar_id IS NOT NULL
|
||||||
|
SQL
|
||||||
|
|
||||||
|
def self.like_badge(count)
|
||||||
|
# we can do better with dates, but its hard work
|
||||||
|
"
|
||||||
|
SELECT p.user_id, p.id post_id, p.updated_at granted_at FROM posts p
|
||||||
|
JOIN topics t on p.topic_id = t.id
|
||||||
|
WHERE p.deleted_at IS NULL AND
|
||||||
|
t.deleted_at IS NULL AND
|
||||||
|
t.visible AND
|
||||||
|
p.like_count >= #{count.to_i}
|
||||||
|
"
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.trust_level(level)
|
||||||
|
# we can do better with dates, but its hard work figuring this out historically
|
||||||
|
"
|
||||||
|
SELECT u.id user_id, current_timestamp granted_at FROM users u
|
||||||
|
WHERE trust_level >= #{level.to_i}
|
||||||
|
"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
belongs_to :badge_type
|
belongs_to :badge_type
|
||||||
has_many :user_badges, dependent: :destroy
|
has_many :user_badges, dependent: :destroy
|
||||||
|
|
||||||
@ -7,15 +61,19 @@ class Badge < ActiveRecord::Base
|
|||||||
validates :allow_title, inclusion: [true, false]
|
validates :allow_title, inclusion: [true, false]
|
||||||
validates :multiple_grant, inclusion: [true, false]
|
validates :multiple_grant, inclusion: [true, false]
|
||||||
|
|
||||||
Welcome = 5
|
|
||||||
NicePost = 6
|
|
||||||
GoodPost = 7
|
|
||||||
GreatPost = 8
|
|
||||||
|
|
||||||
def self.trust_level_badge_ids
|
def self.trust_level_badge_ids
|
||||||
(1..4).to_a
|
(1..4).to_a
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.like_badge_counts
|
||||||
|
@like_badge_counts ||= {
|
||||||
|
NicePost => 10,
|
||||||
|
GoodPost => 25,
|
||||||
|
GreatPost => 50
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
def reset_grant_count!
|
def reset_grant_count!
|
||||||
self.grant_count = UserBadge.where(badge_id: id).count
|
self.grant_count = UserBadge.where(badge_id: id).count
|
||||||
save!
|
save!
|
||||||
@ -25,14 +83,6 @@ class Badge < ActiveRecord::Base
|
|||||||
!self.multiple_grant?
|
!self.multiple_grant?
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.like_badge_info
|
|
||||||
[
|
|
||||||
{id: NicePost, count: 10},
|
|
||||||
{id: GoodPost, count: 25},
|
|
||||||
{id: GreatPost, count: 100}
|
|
||||||
]
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# == Schema Information
|
# == Schema Information
|
||||||
@ -49,9 +99,11 @@ end
|
|||||||
# allow_title :boolean default(FALSE), not null
|
# allow_title :boolean default(FALSE), not null
|
||||||
# multiple_grant :boolean default(FALSE), not null
|
# multiple_grant :boolean default(FALSE), not null
|
||||||
# icon :string(255) default("fa-certificate")
|
# icon :string(255) default("fa-certificate")
|
||||||
|
# listable :boolean default(TRUE)
|
||||||
|
# target_posts :boolean default(FALSE)
|
||||||
|
# query :text
|
||||||
#
|
#
|
||||||
# Indexes
|
# Indexes
|
||||||
#
|
#
|
||||||
# index_badges_on_badge_type_id (badge_type_id)
|
# index_badges_on_name (name) UNIQUE
|
||||||
# index_badges_on_name (name) UNIQUE
|
|
||||||
#
|
#
|
||||||
|
@ -359,10 +359,12 @@ end
|
|||||||
# email_in_allow_strangers :boolean default(FALSE)
|
# email_in_allow_strangers :boolean default(FALSE)
|
||||||
# topics_day :integer default(0)
|
# topics_day :integer default(0)
|
||||||
# posts_day :integer default(0)
|
# posts_day :integer default(0)
|
||||||
|
# logo_url :string(255)
|
||||||
|
# background_url :string(255)
|
||||||
#
|
#
|
||||||
# Indexes
|
# Indexes
|
||||||
#
|
#
|
||||||
# index_categories_on_email_in (email_in) UNIQUE
|
# index_categories_on_email_in (email_in) UNIQUE
|
||||||
# index_categories_on_parent_category_id_and_name (parent_category_id,name) UNIQUE
|
# index_categories_on_topic_count (topic_count)
|
||||||
# index_categories_on_topic_count (topic_count)
|
# unique_index_categories_on_name (name) UNIQUE
|
||||||
#
|
#
|
||||||
|
@ -10,6 +10,8 @@ end
|
|||||||
#
|
#
|
||||||
# category_id :integer not null, primary key
|
# category_id :integer not null, primary key
|
||||||
# search_data :tsvector
|
# search_data :tsvector
|
||||||
|
# raw_data :text
|
||||||
|
# locale :text
|
||||||
#
|
#
|
||||||
# Indexes
|
# Indexes
|
||||||
#
|
#
|
||||||
|
@ -587,6 +587,8 @@ end
|
|||||||
# cook_method :integer default(1), not null
|
# cook_method :integer default(1), not null
|
||||||
# wiki :boolean default(FALSE), not null
|
# wiki :boolean default(FALSE), not null
|
||||||
# baked_at :datetime
|
# baked_at :datetime
|
||||||
|
# baked_version :integer
|
||||||
|
# hidden_at :datetime
|
||||||
#
|
#
|
||||||
# Indexes
|
# Indexes
|
||||||
#
|
#
|
||||||
|
@ -10,6 +10,8 @@ end
|
|||||||
#
|
#
|
||||||
# post_id :integer not null, primary key
|
# post_id :integer not null, primary key
|
||||||
# search_data :tsvector
|
# search_data :tsvector
|
||||||
|
# raw_data :text
|
||||||
|
# locale :string(255)
|
||||||
#
|
#
|
||||||
# Indexes
|
# Indexes
|
||||||
#
|
#
|
||||||
|
@ -227,6 +227,7 @@ end
|
|||||||
#
|
#
|
||||||
# Indexes
|
# Indexes
|
||||||
#
|
#
|
||||||
|
# index_topic_links_on_post_id (post_id)
|
||||||
# index_topic_links_on_topic_id (topic_id)
|
# index_topic_links_on_topic_id (topic_id)
|
||||||
# unique_post_links (topic_id,post_id,url) UNIQUE
|
# unique_post_links (topic_id,post_id,url) UNIQUE
|
||||||
#
|
#
|
||||||
|
@ -495,7 +495,13 @@ class User < ActiveRecord::Base
|
|||||||
end
|
end
|
||||||
|
|
||||||
def featured_user_badges
|
def featured_user_badges
|
||||||
user_badges.joins(:badge).order('badges.badge_type_id ASC, badges.grant_count ASC').includes(:user, :granted_by, badge: :badge_type).limit(3)
|
user_badges
|
||||||
|
.joins(:badge)
|
||||||
|
.order('badges.badge_type_id ASC, badges.grant_count ASC')
|
||||||
|
.includes(:user, :granted_by, badge: :badge_type)
|
||||||
|
.where("user_badges.id in (select min(u2.id)
|
||||||
|
from user_badges u2 where u2.user_id = ? group by u2.badge_id)", id)
|
||||||
|
.limit(3)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.count_by_signup_date(sinceDaysAgo=30)
|
def self.count_by_signup_date(sinceDaysAgo=30)
|
||||||
@ -605,10 +611,23 @@ class User < ActiveRecord::Base
|
|||||||
|
|
||||||
if !self.uploaded_avatar_id && gravatar_downloaded
|
if !self.uploaded_avatar_id && gravatar_downloaded
|
||||||
self.update_column(:uploaded_avatar_id, avatar.gravatar_upload_id)
|
self.update_column(:uploaded_avatar_id, avatar.gravatar_upload_id)
|
||||||
|
grant_autobiographer
|
||||||
|
else
|
||||||
|
if uploaded_avatar_id_changed?
|
||||||
|
grant_autobiographer
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def grant_autobiographer
|
||||||
|
if self.user_profile.bio_raw &&
|
||||||
|
self.user_profile.bio_raw.strip.length > Badge::AutobiographerMinBioLength &&
|
||||||
|
uploaded_avatar_id
|
||||||
|
BadgeGranter.grant(Badge.find(Badge::Autobiographer), self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def update_tracked_topics
|
def update_tracked_topics
|
||||||
|
@ -45,5 +45,4 @@ end
|
|||||||
# Indexes
|
# Indexes
|
||||||
#
|
#
|
||||||
# index_user_badges_on_badge_id_and_user_id (badge_id,user_id)
|
# index_user_badges_on_badge_id_and_user_id (badge_id,user_id)
|
||||||
# index_user_badges_on_user_id (user_id)
|
|
||||||
#
|
#
|
||||||
|
@ -3,6 +3,7 @@ class UserProfile < ActiveRecord::Base
|
|||||||
|
|
||||||
validates :user, presence: true
|
validates :user, presence: true
|
||||||
before_save :cook
|
before_save :cook
|
||||||
|
after_save :assign_autobiographer
|
||||||
|
|
||||||
def bio_excerpt
|
def bio_excerpt
|
||||||
excerpt = PrettyText.excerpt(bio_cooked, 350)
|
excerpt = PrettyText.excerpt(bio_cooked, 350)
|
||||||
@ -35,6 +36,14 @@ class UserProfile < ActiveRecord::Base
|
|||||||
self.save!
|
self.save!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
protected
|
||||||
|
|
||||||
|
def assign_autobiographer
|
||||||
|
if bio_raw_changed?
|
||||||
|
user.grant_autobiographer
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def cook
|
def cook
|
||||||
@ -51,10 +60,11 @@ end
|
|||||||
#
|
#
|
||||||
# Table name: user_profiles
|
# Table name: user_profiles
|
||||||
#
|
#
|
||||||
# user_id :integer not null, primary key
|
# user_id :integer not null, primary key
|
||||||
# bio_cooked :text
|
# location :string(255)
|
||||||
# bio_raw :text
|
# website :string(255)
|
||||||
# location :string(255)
|
# bio_raw :text
|
||||||
# website :string(255)
|
# bio_cooked :text
|
||||||
# profile_background :string(255)
|
# dismissed_banner_key :integer
|
||||||
|
# profile_background :string(255)
|
||||||
#
|
#
|
||||||
|
@ -9,6 +9,8 @@ end
|
|||||||
#
|
#
|
||||||
# user_id :integer not null, primary key
|
# user_id :integer not null, primary key
|
||||||
# search_data :tsvector
|
# search_data :tsvector
|
||||||
|
# raw_data :text
|
||||||
|
# locale :text
|
||||||
#
|
#
|
||||||
# Indexes
|
# Indexes
|
||||||
#
|
#
|
||||||
|
@ -55,49 +55,36 @@ class BadgeGranter
|
|||||||
Jobs.enqueue(:update_badges, args)
|
Jobs.enqueue(:update_badges, args)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def self.backfill(badge)
|
||||||
|
return unless badge.query.present?
|
||||||
|
|
||||||
def self.backfill_like_badges
|
post_clause = badge.target_posts ? "AND q.post_id = ub.post_id" : ""
|
||||||
Badge.like_badge_info.each do |info|
|
post_id_field = badge.target_posts ? "q.post_id" : "NULL"
|
||||||
sql = "
|
|
||||||
DELETE FROM user_badges
|
|
||||||
WHERE badge_id = :id AND
|
|
||||||
NOT EXISTS (SELECT 1 FROM posts p
|
|
||||||
JOIN topics t on p.topic_id = t.id
|
|
||||||
WHERE p.deleted_at IS NULL AND
|
|
||||||
t.deleted_at IS NULL AND
|
|
||||||
t.visible AND
|
|
||||||
post_id = p.id AND
|
|
||||||
p.like_count >= :count
|
|
||||||
)
|
|
||||||
"
|
|
||||||
|
|
||||||
Badge.exec_sql(sql, info)
|
sql = "DELETE FROM user_badges
|
||||||
|
WHERE id in (
|
||||||
|
SELECT ub.id
|
||||||
|
FROM user_badges ub
|
||||||
|
LEFT JOIN ( #{badge.query} ) q
|
||||||
|
ON q.user_id = ub.user_id
|
||||||
|
#{post_clause}
|
||||||
|
WHERE ub.id = :id AND q.user_id IS NULL
|
||||||
|
)"
|
||||||
|
|
||||||
sql = "
|
Badge.exec_sql(sql, id: badge.id)
|
||||||
INSERT INTO user_badges(badge_id, user_id, granted_at, granted_by_id, post_id)
|
|
||||||
SELECT :id, p.user_id, :now, -1, p.id
|
|
||||||
FROM posts p
|
|
||||||
JOIN topics t on p.topic_id = t.id
|
|
||||||
WHERE p.deleted_at IS NULL AND
|
|
||||||
t.deleted_at IS NULL AND
|
|
||||||
t.visible AND
|
|
||||||
p.like_count >= :count AND
|
|
||||||
NOT EXISTS (SELECT 1 FROM user_badges ub
|
|
||||||
WHERE ub.post_id = p.id AND
|
|
||||||
ub.badge_id = :id AND
|
|
||||||
ub.user_id = p.user_id)
|
|
||||||
"
|
|
||||||
|
|
||||||
Badge.exec_sql(sql, info.merge(now: Time.now))
|
sql = "INSERT INTO user_badges(badge_id, user_id, granted_at, granted_by_id, post_id)
|
||||||
|
SELECT :id, q.user_id, q.granted_at, -1, #{post_id_field}
|
||||||
|
FROM ( #{badge.query} ) q
|
||||||
|
LEFT JOIN user_badges ub ON
|
||||||
|
ub.id = :id AND ub.user_id = q.user_id
|
||||||
|
#{post_clause}
|
||||||
|
WHERE ub.id IS NULL"
|
||||||
|
|
||||||
sql = "
|
Badge.exec_sql(sql, id: badge.id)
|
||||||
UPDATE badges b
|
|
||||||
SET grant_count = (SELECT COUNT(*) FROM user_badges WHERE badge_id = :id)
|
badge.reset_grant_count!
|
||||||
WHERE b.id = :id
|
|
||||||
"
|
|
||||||
|
|
||||||
Badge.exec_sql(sql, info)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
@ -1947,6 +1947,9 @@ en:
|
|||||||
welcome:
|
welcome:
|
||||||
name: Welcome
|
name: Welcome
|
||||||
description: Received a like.
|
description: Received a like.
|
||||||
|
autobiographer:
|
||||||
|
name: Autobiographer
|
||||||
|
description: Filled user profile information.
|
||||||
nice_post:
|
nice_post:
|
||||||
name: Nice Post
|
name: Nice Post
|
||||||
description: Received 10 likes on a post. This badge can be granted multiple times.
|
description: Received 10 likes on a post. This badge can be granted multiple times.
|
||||||
|
@ -6,49 +6,35 @@ trust_level_badges = [
|
|||||||
{id: 4, name: "Elder", type: 1}
|
{id: 4, name: "Elder", type: 1}
|
||||||
]
|
]
|
||||||
|
|
||||||
backfill_trust_level_badges = false
|
|
||||||
|
|
||||||
trust_level_badges.each do |spec|
|
trust_level_badges.each do |spec|
|
||||||
backfill_trust_level_badges ||= Badge.find_by(id: spec[:id]).nil?
|
|
||||||
|
|
||||||
Badge.seed do |b|
|
Badge.seed do |b|
|
||||||
b.id = spec[:id]
|
b.id = spec[:id]
|
||||||
b.name = spec[:name]
|
b.name = spec[:name]
|
||||||
b.badge_type_id = spec[:type]
|
b.badge_type_id = spec[:type]
|
||||||
|
b.query = Badge::Queries.trust_level(spec[:id])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if backfill_trust_level_badges
|
Badge.seed do |b|
|
||||||
puts "Backfilling trust level badges!"
|
b.id = Badge::Welcome
|
||||||
|
b.name = "Welcome"
|
||||||
|
b.badge_type_id = 3
|
||||||
Badge.trust_level_badge_ids.each do |badge_id|
|
b.multiple_grant = false
|
||||||
sql = <<SQL
|
b.target_posts = true
|
||||||
DELETE FROM user_badges
|
b.query = Badge::Queries::Welcome
|
||||||
WHERE badge_id = :badge_id AND
|
|
||||||
user_id NOT IN (SELECT id FROM users WHERE trust_level <= :badge_id)
|
|
||||||
SQL
|
|
||||||
|
|
||||||
User.exec_sql(sql, badge_id: badge_id)
|
|
||||||
|
|
||||||
sql = <<SQL
|
|
||||||
INSERT INTO user_badges(badge_id, user_id, granted_at, granted_by_id)
|
|
||||||
SELECT :badge_id, id, :now, :system_id
|
|
||||||
FROM users
|
|
||||||
WHERE trust_level >= :trust_level AND
|
|
||||||
id NOT IN (SELECT user_id FROM user_badges WHERE badge_id = :badge_id) AND
|
|
||||||
id <> :system_id
|
|
||||||
SQL
|
|
||||||
User.exec_sql(sql, badge_id: badge_id, now: Time.now, system_id: Discourse.system_user.id, trust_level: badge_id)
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
Badge.where(id: Badge.trust_level_badge_ids).each {|badge| badge.reset_grant_count! }
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Badge.seed do |b|
|
||||||
|
b.id = Badge::Autobiographer
|
||||||
|
b.name = "Autobiographer"
|
||||||
|
b.badge_type_id = 3
|
||||||
|
b.multiple_grant = false
|
||||||
|
b.query = Badge::Queries::Autobiographer
|
||||||
|
end
|
||||||
|
|
||||||
#
|
#
|
||||||
# Like system badges.
|
# Like system badges.
|
||||||
like_badges = [
|
like_badges = [
|
||||||
{id: 5, name: "Welcome", type: 3, multiple: false},
|
|
||||||
{id: 6, name: "Nice Post", type: 3, multiple: true},
|
{id: 6, name: "Nice Post", type: 3, multiple: true},
|
||||||
{id: 7, name: "Good Post", type: 2, multiple: true},
|
{id: 7, name: "Good Post", type: 2, multiple: true},
|
||||||
{id: 8, name: "Great Post", type: 1, multiple: true}
|
{id: 8, name: "Great Post", type: 1, multiple: true}
|
||||||
@ -60,14 +46,7 @@ like_badges.each do |spec|
|
|||||||
b.name = spec[:name]
|
b.name = spec[:name]
|
||||||
b.badge_type_id = spec[:type]
|
b.badge_type_id = spec[:type]
|
||||||
b.multiple_grant = spec[:multiple]
|
b.multiple_grant = spec[:multiple]
|
||||||
end
|
b.target_posts = true
|
||||||
end
|
b.query = Badge::Queries.like_badge(Badge.like_badge_counts[spec[:id]])
|
||||||
|
|
||||||
# Create an example badge if one does not already exist.
|
|
||||||
if Badge.find_by(id: 101).nil?
|
|
||||||
Badge.seed do |b|
|
|
||||||
b.id = 101
|
|
||||||
b.name = "Example Badge"
|
|
||||||
b.badge_type_id = 3
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
7
db/migrate/20140703022838_add_fields_to_badges.rb
Normal file
7
db/migrate/20140703022838_add_fields_to_badges.rb
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
class AddFieldsToBadges < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_column :badges, :listable, :boolean, default: true
|
||||||
|
add_column :badges, :target_posts, :boolean, default: false
|
||||||
|
add_column :badges, :query, :text
|
||||||
|
end
|
||||||
|
end
|
@ -5,14 +5,31 @@ describe BadgeGranter do
|
|||||||
let(:badge) { Fabricate(:badge) }
|
let(:badge) { Fabricate(:badge) }
|
||||||
let(:user) { Fabricate(:user) }
|
let(:user) { Fabricate(:user) }
|
||||||
|
|
||||||
before do
|
describe 'backfill' do
|
||||||
SiteSetting.enable_badges = true
|
|
||||||
end
|
it 'has no broken badge queries' do
|
||||||
|
Badge.all.each do |b|
|
||||||
|
BadgeGranter.backfill(b)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'can backfill the welcome badge' do
|
||||||
|
post = Fabricate(:post)
|
||||||
|
user2 = Fabricate(:user)
|
||||||
|
PostAction.act(user2, post, PostActionType.types[:like])
|
||||||
|
|
||||||
|
UserBadge.destroy_all
|
||||||
|
BadgeGranter.backfill(Badge.find(Badge::Welcome))
|
||||||
|
|
||||||
|
b = UserBadge.first
|
||||||
|
b.user_id.should == post.user_id
|
||||||
|
b.post_id.should == post.id
|
||||||
|
end
|
||||||
|
|
||||||
describe 'backfill like badges' do
|
|
||||||
it 'should grant missing badges' do
|
it 'should grant missing badges' do
|
||||||
post = Fabricate(:post, like_count: 30)
|
post = Fabricate(:post, like_count: 30)
|
||||||
BadgeGranter.backfill_like_badges
|
BadgeGranter.backfill(Badge.find(Badge::NicePost))
|
||||||
|
BadgeGranter.backfill(Badge.find(Badge::GoodPost))
|
||||||
|
|
||||||
# TODO add welcome
|
# TODO add welcome
|
||||||
post.user.user_badges.pluck(:badge_id).sort.should == [Badge::NicePost,Badge::GoodPost]
|
post.user.user_badges.pluck(:badge_id).sort.should == [Badge::NicePost,Badge::GoodPost]
|
||||||
@ -22,6 +39,21 @@ describe BadgeGranter do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe 'autobiographer' do
|
||||||
|
it 'grants autobiographer correctly' do
|
||||||
|
user = Fabricate(:user)
|
||||||
|
user.user_profile.bio_raw = "I filled my bio"
|
||||||
|
user.user_profile.save!
|
||||||
|
|
||||||
|
Badge.find(Badge::Autobiographer).grant_count.should == 0
|
||||||
|
|
||||||
|
user.uploaded_avatar_id = 100
|
||||||
|
user.save
|
||||||
|
|
||||||
|
Badge.find(Badge::Autobiographer).grant_count.should == 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'grant' do
|
describe 'grant' do
|
||||||
|
|
||||||
it 'grants a badge' do
|
it 'grants a badge' do
|
||||||
@ -111,11 +143,11 @@ describe BadgeGranter do
|
|||||||
BadgeGranter.update_badges(action: :post_like, post_id: post.id)
|
BadgeGranter.update_badges(action: :post_like, post_id: post.id)
|
||||||
UserBadge.find_by(user_id: user.id, badge_id: 7).should_not be_nil
|
UserBadge.find_by(user_id: user.id, badge_id: 7).should_not be_nil
|
||||||
# Great post badge
|
# Great post badge
|
||||||
post.update_attributes like_count: 100
|
post.update_attributes like_count: 50
|
||||||
BadgeGranter.update_badges(action: :post_like, post_id: post.id)
|
BadgeGranter.update_badges(action: :post_like, post_id: post.id)
|
||||||
UserBadge.find_by(user_id: user.id, badge_id: 8).should_not be_nil
|
UserBadge.find_by(user_id: user.id, badge_id: 8).should_not be_nil
|
||||||
# Revoke badges on unlike
|
# Revoke badges on unlike
|
||||||
post.update_attributes like_count: 99
|
post.update_attributes like_count: 49
|
||||||
BadgeGranter.update_badges(action: :post_like, post_id: post.id)
|
BadgeGranter.update_badges(action: :post_like, post_id: post.id)
|
||||||
UserBadge.find_by(user_id: user.id, badge_id: 8).should be_nil
|
UserBadge.find_by(user_id: user.id, badge_id: 8).should be_nil
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user