Commit 4fa3b9844fa825008461f2759896cb77a2e30cbf

Authored by Victor Costa
1 parent 0fc833ce

Add badges with an organization as owner

lib/ext/environment.rb
@@ -3,5 +3,6 @@ require_dependency 'environment' @@ -3,5 +3,6 @@ require_dependency 'environment'
3 class Environment 3 class Environment
4 4
5 has_many :gamification_plugin_badges, :class_name => 'GamificationPlugin::Badge', :foreign_key => 'owner_id', :source => :owner 5 has_many :gamification_plugin_badges, :class_name => 'GamificationPlugin::Badge', :foreign_key => 'owner_id', :source => :owner
  6 + has_many :gamification_plugin_organization_badges, :through => :organizations
6 7
7 end 8 end
lib/ext/organization.rb 0 → 100644
@@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
  1 +require_dependency 'organization'
  2 +
  3 +class Organization
  4 +
  5 + has_many :gamification_plugin_organization_badges, :class_name => 'GamificationPlugin::Badge', :foreign_key => 'owner_id', :source => :owner
  6 +
  7 +end
lib/merit/badge_rules.rb
@@ -14,6 +14,7 @@ module Merit @@ -14,6 +14,7 @@ module Merit
14 action: 'comment#create', 14 action: 'comment#create',
15 default_threshold: 5, 15 default_threshold: 5,
16 to: :author, 16 to: :author,
  17 + target_profile: lambda {|comment| comment.profile },
17 value: lambda { |comment, author| author.present? ? author.comments.count : 0 } 18 value: lambda { |comment, author| author.present? ? author.comments.count : 0 }
18 } 19 }
19 ], 20 ],
@@ -22,6 +23,7 @@ module Merit @@ -22,6 +23,7 @@ module Merit
22 action: 'comment#create', 23 action: 'comment#create',
23 default_threshold: 5, 24 default_threshold: 5,
24 to: lambda {|comment| comment.source.author}, 25 to: lambda {|comment| comment.source.author},
  26 + target_profile: lambda {|comment| comment.profile },
25 value: lambda { |comment, author| author.present? ? Comment.where(source_id: Article.where(author_id: author.id)).count : 0 } 27 value: lambda { |comment, author| author.present? ? Comment.where(source_id: Article.where(author_id: author.id)).count : 0 }
26 } 28 }
27 ], 29 ],
@@ -30,6 +32,7 @@ module Merit @@ -30,6 +32,7 @@ module Merit
30 action: 'article#create', 32 action: 'article#create',
31 default_threshold: 5, 33 default_threshold: 5,
32 to: :author, 34 to: :author,
  35 + target_profile: lambda {|article| article.profile },
33 value: lambda { |article, author| author.present? ? TextArticle.where(author_id: author.id).count : 0 } 36 value: lambda { |article, author| author.present? ? TextArticle.where(author_id: author.id).count : 0 }
34 }, 37 },
35 ], 38 ],
@@ -38,6 +41,7 @@ module Merit @@ -38,6 +41,7 @@ module Merit
38 action: 'vote#create', 41 action: 'vote#create',
39 default_threshold: 5, 42 default_threshold: 5,
40 to: lambda {|vote| vote.voteable.author}, 43 to: lambda {|vote| vote.voteable.author},
  44 + target_profile: lambda {|vote| vote.voteable.profile },
41 value: lambda { |vote, author| vote.voteable ? Vote.for_voteable(vote.voteable).where('vote > 0').count : 0} 45 value: lambda { |vote, author| vote.voteable ? Vote.for_voteable(vote.voteable).where('vote > 0').count : 0}
42 } 46 }
43 ], 47 ],
@@ -46,6 +50,7 @@ module Merit @@ -46,6 +50,7 @@ module Merit
46 action: 'vote#create', 50 action: 'vote#create',
47 default_threshold: 5, 51 default_threshold: 5,
48 to: lambda {|vote| vote.voteable.author}, 52 to: lambda {|vote| vote.voteable.author},
  53 + target_profile: lambda {|vote| vote.voteable.profile },
49 value: lambda { |vote, author| Vote.for_voteable(vote.voteable).where('vote < 0').count } 54 value: lambda { |vote, author| Vote.for_voteable(vote.voteable).where('vote < 0').count }
50 } 55 }
51 ], 56 ],
@@ -54,6 +59,7 @@ module Merit @@ -54,6 +59,7 @@ module Merit
54 action: 'vote#create', 59 action: 'vote#create',
55 default_threshold: 5, 60 default_threshold: 5,
56 to: lambda {|vote| vote.voter}, 61 to: lambda {|vote| vote.voter},
  62 + target_profile: lambda {|vote| vote.voteable.profile },
57 value: lambda { |vote, voter| voter ? Vote.for_voter(voter).count : 0 } 63 value: lambda { |vote, voter| voter ? Vote.for_voter(voter).count : 0 }
58 } 64 }
59 ], 65 ],
@@ -72,12 +78,14 @@ module Merit @@ -72,12 +78,14 @@ module Merit
72 action: 'comment#create', 78 action: 'comment#create',
73 default_threshold: 5, 79 default_threshold: 5,
74 to: :author, 80 to: :author,
  81 + target_profile: lambda {|comment| comment.profile },
75 value: lambda { |comment, author| author.present? ? author.comments.count : 0 } 82 value: lambda { |comment, author| author.present? ? author.comments.count : 0 }
76 }, 83 },
77 { 84 {
78 action: 'article#create', 85 action: 'article#create',
79 default_threshold: 5, 86 default_threshold: 5,
80 to: :author, 87 to: :author,
  88 + target_profile: lambda {|article| article.profile },
81 value: lambda { |article, author| author.present? ? author.articles.count : 0 } 89 value: lambda { |article, author| author.present? ? author.articles.count : 0 }
82 }, 90 },
83 ], 91 ],
@@ -86,6 +94,7 @@ module Merit @@ -86,6 +94,7 @@ module Merit
86 action: 'articlefollower#create', 94 action: 'articlefollower#create',
87 default_threshold: 5, 95 default_threshold: 5,
88 to: lambda {|article| article.person }, 96 to: lambda {|article| article.person },
  97 + target_profile: lambda {|article_follower| article_follower.article.profile },
89 model: 'ArticleFollower', 98 model: 'ArticleFollower',
90 value: lambda { |article, person| person.present? ? person.article_followers.count : 0 } 99 value: lambda { |article, person| person.present? ? person.article_followers.count : 0 }
91 } 100 }
@@ -95,12 +104,14 @@ module Merit @@ -95,12 +104,14 @@ module Merit
95 action: 'Vote#create', 104 action: 'Vote#create',
96 default_threshold: 5, 105 default_threshold: 5,
97 to: lambda { |vote| vote.voter }, 106 to: lambda { |vote| vote.voter },
  107 + target_profile: lambda {|vote| vote.voteable.profile },
98 value: lambda { |vote, voter| Vote.for_voter(voter).count } 108 value: lambda { |vote, voter| Vote.for_voter(voter).count }
99 }, 109 },
100 { 110 {
101 action: 'Event#create', 111 action: 'Event#create',
102 default_threshold: 5, 112 default_threshold: 5,
103 to: lambda { |article| article.author }, 113 to: lambda { |article| article.author },
  114 + target_profile: lambda {|article| article.profile },
104 value: lambda { |event, author| author.events.count } 115 value: lambda { |event, author| author.events.count }
105 }, 116 },
106 ], 117 ],
@@ -109,12 +120,14 @@ module Merit @@ -109,12 +120,14 @@ module Merit
109 action: 'vote#create', 120 action: 'vote#create',
110 default_threshold: 5, 121 default_threshold: 5,
111 to: lambda {|vote| vote.voter}, 122 to: lambda {|vote| vote.voter},
  123 + target_profile: lambda {|vote| vote.voteable.profile },
112 value: lambda { |vote, voter| voter ? voter.votes.where('vote > 0').count : 0 } 124 value: lambda { |vote, voter| voter ? voter.votes.where('vote > 0').count : 0 }
113 }, 125 },
114 { 126 {
115 action: 'comment#create', 127 action: 'comment#create',
116 default_threshold: 5, 128 default_threshold: 5,
117 to: :author, 129 to: :author,
  130 + target_profile: lambda {|comment| comment.profile },
118 value: lambda { |comment, author| author.present? ? author.comments.count : 0 } 131 value: lambda { |comment, author| author.present? ? author.comments.count : 0 }
119 } 132 }
120 ], 133 ],
@@ -123,6 +136,7 @@ module Merit @@ -123,6 +136,7 @@ module Merit
123 action: 'articlefollower#create', 136 action: 'articlefollower#create',
124 default_threshold: 5, 137 default_threshold: 5,
125 to: :person, 138 to: :person,
  139 + target_profile: lambda {|article_follower| article_follower.article.profile },
126 model: 'ArticleFollower', 140 model: 'ArticleFollower',
127 value: lambda { |article_follower, person| person.present? ? person.article_followers.count : 0 } 141 value: lambda { |article_follower, person| person.present? ? person.article_followers.count : 0 }
128 }, 142 },
@@ -130,11 +144,28 @@ module Merit @@ -130,11 +144,28 @@ module Merit
130 action: 'comment#create', 144 action: 'comment#create',
131 default_threshold: 5, 145 default_threshold: 5,
132 to: :author, 146 to: :author,
  147 + target_profile: lambda {|comment| comment.profile },
133 value: lambda { |comment, author| author.present? ? author.comments.count : 0 } 148 value: lambda { |comment, author| author.present? ? author.comments.count : 0 }
134 }, 149 },
135 ] 150 ]
136 } 151 }
137 152
  153 + def target_author(source, setting)
  154 + if setting[:to].is_a? Symbol
  155 + source.send(setting[:to])
  156 + else
  157 + setting[:to].call(source) rescue nil
  158 + end
  159 + end
  160 +
  161 + def target_profile(source, setting)
  162 + setting[:target_profile].present? ? setting[:target_profile].call(source) : nil
  163 + end
  164 +
  165 + def check_organization_badge(badge, source, setting)
  166 + !badge.owner.kind_of?(Organization) || badge.owner == target_profile(source, setting)
  167 + end
  168 +
138 def initialize(environment=nil) 169 def initialize(environment=nil)
139 return if environment.nil? 170 return if environment.nil?
140 @environment = environment 171 @environment = environment
@@ -142,7 +173,8 @@ module Merit @@ -142,7 +173,8 @@ module Merit
142 rules = AVAILABLE_RULES 173 rules = AVAILABLE_RULES
143 rules.merge! CONFERENCE_RULES if defined? CONFERENCE_RULES 174 rules.merge! CONFERENCE_RULES if defined? CONFERENCE_RULES
144 175
145 - environment.gamification_plugin_badges.all.each do |badge| 176 + gamification_plugin_badges = environment.gamification_plugin_badges + environment.gamification_plugin_organization_badges
  177 + gamification_plugin_badges.each do |badge|
146 next if rules[badge.name.to_sym].nil? 178 next if rules[badge.name.to_sym].nil?
147 rules[badge.name.to_sym].each do |setting| 179 rules[badge.name.to_sym].each do |setting|
148 options = {badge: badge.name, level: badge.level, to: setting[:to]} 180 options = {badge: badge.name, level: badge.level, to: setting[:to]}
@@ -150,18 +182,11 @@ module Merit @@ -150,18 +182,11 @@ module Merit
150 grant_on setting[:action], options do |source| 182 grant_on setting[:action], options do |source|
151 can_be_granted = true 183 can_be_granted = true
152 rules[badge.name.to_sym].each do |s| 184 rules[badge.name.to_sym].each do |s|
153 - if setting[:to].is_a? Symbol  
154 - to = source.send(setting[:to])  
155 - else  
156 - begin  
157 - to = setting[:to].call(source)  
158 - rescue  
159 - to = nil  
160 - end  
161 - end  
162 - # pass source and to for different situations 185 + to = target_author(source, setting)
  186 + # pass source and to for different situations
163 action = (badge.custom_fields || {}).fetch(s[:action], {}) 187 action = (badge.custom_fields || {}).fetch(s[:action], {})
164 can_be_granted &= s[:value].call(source, to) >= action.fetch(:threshold, s[:default_threshold]).to_i 188 can_be_granted &= s[:value].call(source, to) >= action.fetch(:threshold, s[:default_threshold]).to_i
  189 + can_be_granted &= check_organization_badge(badge, source, setting)
165 end 190 end
166 can_be_granted 191 can_be_granted
167 end 192 end
test/unit/badge_rules_test.rb 0 → 100644
@@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
  1 +require_relative "../test_helper"
  2 +
  3 +class BadgeRulesTest < ActiveSupport::TestCase
  4 +
  5 + def setup
  6 + @environment = Environment.default
  7 + end
  8 +
  9 + attr_accessor :environment
  10 +
  11 + should "define badge rules for environment's badges" do
  12 + badge = GamificationPlugin::Badge.create!(:owner => environment, :name => :comment_author)
  13 + badge_rules = Merit::BadgeRules.new(environment)
  14 + assert_equal [Merit::BadgeRules::AVAILABLE_RULES[badge.name].first[:action]], badge_rules.defined_rules.keys
  15 + end
  16 +
  17 + should "define badge rules for organization's badges" do
  18 + organization = fast_create(Organization)
  19 + badge = GamificationPlugin::Badge.create!(:owner => organization, :name => :comment_author)
  20 + badge_rules = Merit::BadgeRules.new(environment)
  21 + assert_equal [Merit::BadgeRules::AVAILABLE_RULES[badge.name].first[:action]], badge_rules.defined_rules.keys
  22 + end
  23 +
  24 + should 'check organization returns true when badge belongs to the environment' do
  25 + badge = GamificationPlugin::Badge.create!(:owner => environment, :name => :comment_author)
  26 + badge_rules = Merit::BadgeRules.new(environment)
  27 + comment = fast_create(Comment)
  28 + assert badge_rules.check_organization_badge(badge, comment, Merit::BadgeRules::AVAILABLE_RULES[badge.name].first)
  29 + end
  30 +
  31 + should 'check organization returns true when the comment belongs to the organization' do
  32 + organization = fast_create(Organization)
  33 + badge = GamificationPlugin::Badge.create!(:owner => organization, :name => :comment_author)
  34 + badge_rules = Merit::BadgeRules.new(environment)
  35 + article = fast_create(Article,:profile_id => organization.id)
  36 + comment = fast_create(Comment, :source_id => article.id)
  37 + assert badge_rules.check_organization_badge(badge, comment, Merit::BadgeRules::AVAILABLE_RULES[badge.name].first)
  38 + end
  39 +
  40 + should 'check organization returns false when the comment does not belongs to the organization' do
  41 + organization = fast_create(Organization)
  42 + badge = GamificationPlugin::Badge.create!(:owner => organization, :name => :comment_author)
  43 + badge_rules = Merit::BadgeRules.new(environment)
  44 + comment = fast_create(Comment)
  45 + assert !badge_rules.check_organization_badge(badge, comment, Merit::BadgeRules::AVAILABLE_RULES[badge.name].first)
  46 + end
  47 +
  48 +end
test/unit/badge_test.rb
@@ -5,9 +5,10 @@ class BadgeTest &lt; ActiveSupport::TestCase @@ -5,9 +5,10 @@ class BadgeTest &lt; ActiveSupport::TestCase
5 def setup 5 def setup
6 @person = create_user('testuser').person 6 @person = create_user('testuser').person
7 @environment = Environment.default 7 @environment = Environment.default
  8 + @organization = fast_create(Organization)
8 end 9 end
9 10
10 - attr_accessor :person, :environment 11 + attr_accessor :person, :environment, :organization
11 12
12 should 'add badge to person' do 13 should 'add badge to person' do
13 badge = GamificationPlugin::Badge.create!(:owner => environment) 14 badge = GamificationPlugin::Badge.create!(:owner => environment)
@@ -37,4 +38,10 @@ class BadgeTest &lt; ActiveSupport::TestCase @@ -37,4 +38,10 @@ class BadgeTest &lt; ActiveSupport::TestCase
37 assert_equal [badge2], person.badges.notification_pending 38 assert_equal [badge2], person.badges.notification_pending
38 end 39 end
39 40
  41 + should 'add badge to person with organization as the badge owner' do
  42 + badge = GamificationPlugin::Badge.create(:owner => organization)
  43 + person.add_badge(badge.id)
  44 + assert_equal [badge], person.badges
  45 + end
  46 +
40 end 47 end