merit 1.7.1 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -1
- data/Gemfile +7 -0
- data/README.md +31 -4
- data/app/models/merit/action.rb +2 -3
- data/app/models/merit/badge.rb +2 -2
- data/lib/generators/active_record/install_generator.rb +1 -1
- data/lib/generators/active_record/merit_generator.rb +2 -2
- data/lib/generators/active_record/remove_generator.rb +2 -2
- data/lib/generators/active_record/templates/create_badges_sashes.rb +1 -1
- data/lib/generators/active_record/templates/create_merit_actions.rb +3 -3
- data/lib/generators/active_record/templates/create_scores_and_points.rb +2 -2
- data/lib/generators/active_record/templates/remove_merit_tables.rb +1 -1
- data/lib/generators/merit/install_generator.rb +1 -1
- data/lib/generators/merit/merit_generator.rb +2 -3
- data/lib/generators/merit/remove_generator.rb +3 -3
- data/lib/generators/merit/templates/merit.rb +10 -4
- data/lib/merit.rb +43 -15
- data/lib/merit/base_target_finder.rb +1 -3
- data/lib/merit/judge.rb +26 -6
- data/lib/merit/model_additions.rb +10 -17
- data/lib/merit/models/active_record/merit/action.rb +1 -1
- data/lib/merit/models/active_record/merit/activity_log.rb +1 -0
- data/lib/merit/models/active_record/merit/badges_sash.rb +6 -10
- data/lib/merit/models/active_record/merit/sash.rb +2 -38
- data/lib/merit/models/active_record/merit/score.rb +6 -5
- data/lib/merit/models/base/merit/badges_sash.rb +15 -0
- data/lib/merit/models/base/merit/sash.rb +42 -0
- data/lib/merit/models/mongoid/merit/action.rb +8 -6
- data/lib/merit/models/mongoid/merit/activity_log.rb +11 -0
- data/lib/merit/models/mongoid/merit/badges_sash.rb +19 -0
- data/lib/merit/models/mongoid/merit/sash.rb +28 -0
- data/lib/merit/models/mongoid/merit/score.rb +41 -0
- data/lib/merit/reputation_change_observer.rb +11 -0
- data/lib/merit/rule.rb +1 -1
- data/lib/merit/rules_matcher.rb +0 -2
- data/lib/merit/rules_rank_methods.rb +1 -1
- data/lib/merit/target_finder.rb +1 -2
- data/merit.gemspec +2 -1
- data/test/dummy/app/models/comment.rb +16 -1
- data/test/dummy/app/models/dummy_observer.rb +3 -0
- data/test/dummy/app/models/user.rb +14 -1
- data/test/dummy/config/initializers/merit.rb +3 -4
- data/test/dummy/config/mongoid.yml +13 -0
- data/test/integration/navigation_test.rb +19 -2
- data/test/unit/merit_unit_test.rb +1 -1
- metadata +25 -56
- data/lib/merit/models/mongoid/sash.rb +0 -14
- data/lib/merit/observer.rb +0 -13
- data/test/dummy-mongoid/Rakefile +0 -7
- data/test/dummy-mongoid/app/controllers/application_controller.rb +0 -7
- data/test/dummy-mongoid/app/controllers/comments_controller.rb +0 -90
- data/test/dummy-mongoid/app/controllers/registrations_controller.rb +0 -15
- data/test/dummy-mongoid/app/controllers/users_controller.rb +0 -67
- data/test/dummy-mongoid/app/helpers/application_helper.rb +0 -2
- data/test/dummy-mongoid/app/models/comment.rb +0 -13
- data/test/dummy-mongoid/app/models/merit/badge_rules.rb +0 -49
- data/test/dummy-mongoid/app/models/merit/point_rules.rb +0 -20
- data/test/dummy-mongoid/app/models/merit/rank_rules.rb +0 -24
- data/test/dummy-mongoid/app/models/user.rb +0 -25
- data/test/dummy-mongoid/app/views/comments/_form.html.erb +0 -29
- data/test/dummy-mongoid/app/views/comments/edit.html.erb +0 -6
- data/test/dummy-mongoid/app/views/comments/index.html.erb +0 -35
- data/test/dummy-mongoid/app/views/comments/new.html.erb +0 -5
- data/test/dummy-mongoid/app/views/comments/show.html.erb +0 -23
- data/test/dummy-mongoid/app/views/layouts/application.html.erb +0 -24
- data/test/dummy-mongoid/app/views/users/_form.html.erb +0 -22
- data/test/dummy-mongoid/app/views/users/edit.html.erb +0 -6
- data/test/dummy-mongoid/app/views/users/index.html.erb +0 -26
- data/test/dummy-mongoid/app/views/users/new.html.erb +0 -5
- data/test/dummy-mongoid/app/views/users/show.html.erb +0 -18
- data/test/dummy-mongoid/config.ru +0 -4
- data/test/dummy-mongoid/config/application.rb +0 -22
- data/test/dummy-mongoid/config/boot.rb +0 -10
- data/test/dummy-mongoid/config/environment.rb +0 -5
- data/test/dummy-mongoid/config/environments/development.rb +0 -25
- data/test/dummy-mongoid/config/environments/production.rb +0 -49
- data/test/dummy-mongoid/config/environments/test.rb +0 -35
- data/test/dummy-mongoid/config/initializers/backtrace_silencers.rb +0 -7
- data/test/dummy-mongoid/config/initializers/inflections.rb +0 -10
- data/test/dummy-mongoid/config/initializers/merit.rb +0 -37
- data/test/dummy-mongoid/config/initializers/mime_types.rb +0 -5
- data/test/dummy-mongoid/config/initializers/secret_token.rb +0 -7
- data/test/dummy-mongoid/config/initializers/session_store.rb +0 -8
- data/test/dummy-mongoid/config/locales/en.yml +0 -5
- data/test/dummy-mongoid/config/mongoid.yml +0 -14
- data/test/dummy-mongoid/config/routes.rb +0 -9
- data/test/dummy-mongoid/db/seeds.rb +0 -17
- data/test/dummy-mongoid/public/404.html +0 -26
- data/test/dummy-mongoid/public/422.html +0 -26
- data/test/dummy-mongoid/public/500.html +0 -26
- data/test/dummy-mongoid/public/favicon.ico +0 -0
- data/test/dummy-mongoid/public/javascripts/application.js +0 -2
- data/test/dummy-mongoid/public/javascripts/controls.js +0 -965
- data/test/dummy-mongoid/public/javascripts/dragdrop.js +0 -974
- data/test/dummy-mongoid/public/javascripts/effects.js +0 -1123
- data/test/dummy-mongoid/public/javascripts/prototype.js +0 -6001
- data/test/dummy-mongoid/public/javascripts/rails.js +0 -191
- data/test/dummy-mongoid/public/stylesheets/.gitkeep +0 -0
- data/test/dummy-mongoid/public/stylesheets/scaffold.css +0 -56
- data/test/dummy-mongoid/script/rails +0 -6
@@ -17,16 +17,18 @@ module Merit
|
|
17
17
|
|
18
18
|
# Delegate methods from meritable models to their sash
|
19
19
|
def _merit_delegate_methods_to_sash
|
20
|
-
methods = %w(badge_ids badges points
|
21
|
-
|
22
|
-
add_points substract_points subtract_points)
|
20
|
+
methods = %w(badge_ids badges points add_badge rm_badge
|
21
|
+
add_points substract_points subtract_points)
|
23
22
|
methods.each { |method| delegate method, to: :_sash }
|
24
23
|
end
|
25
24
|
|
26
25
|
def _merit_orm_specific_config
|
27
|
-
if Merit.orm == :
|
28
|
-
|
29
|
-
|
26
|
+
if Merit.orm == :mongo_mapper
|
27
|
+
plugin Merit
|
28
|
+
key :sash_id, String
|
29
|
+
key :points, Integer, default: 0
|
30
|
+
key :level, Integer, default: 0
|
31
|
+
elsif Merit.orm == :mongoid
|
30
32
|
field :level, type: Integer, default: 0
|
31
33
|
def find_by_id(id)
|
32
34
|
where(_id: id).first
|
@@ -45,18 +47,9 @@ module Merit
|
|
45
47
|
# http://blog.hasmanythrough.com/2012/1/20/modularized-association-methods-in-rails-3-2
|
46
48
|
def _merit_sash_initializer
|
47
49
|
define_method(:_sash) do
|
48
|
-
|
49
|
-
|
50
|
-
end
|
51
|
-
self.sash
|
50
|
+
sash || update_attribute(:sash_id, Sash.create.id)
|
51
|
+
sash
|
52
52
|
end
|
53
53
|
end
|
54
54
|
end
|
55
55
|
end
|
56
|
-
|
57
|
-
if Object.const_defined?('ActiveRecord')
|
58
|
-
ActiveRecord::Base.send :include, Merit
|
59
|
-
end
|
60
|
-
if Object.const_defined?('Mongoid')
|
61
|
-
Mongoid::Document.send :include, Merit
|
62
|
-
end
|
@@ -6,7 +6,7 @@ module Merit
|
|
6
6
|
|
7
7
|
if defined?(ProtectedAttributes) || !defined?(ActionController::StrongParameters)
|
8
8
|
attr_accessible :user_id, :action_method, :action_value, :had_errors,
|
9
|
-
|
9
|
+
:target_model, :target_id, :processed, :log
|
10
10
|
end
|
11
11
|
end
|
12
12
|
end
|
@@ -4,6 +4,7 @@ module Merit
|
|
4
4
|
|
5
5
|
belongs_to :action, class_name: Merit::Action
|
6
6
|
belongs_to :related_change, polymorphic: true
|
7
|
+
has_one :sash, through: :related_change
|
7
8
|
|
8
9
|
if defined?(ProtectedAttributes) || !defined?(ActionController::StrongParameters)
|
9
10
|
attr_accessible :action_id, :related_change, :description, :created_at
|
@@ -1,9 +1,9 @@
|
|
1
1
|
module Merit
|
2
2
|
class BadgesSash < ActiveRecord::Base
|
3
|
-
|
3
|
+
include Base::BadgesSash
|
4
4
|
has_many :activity_logs,
|
5
|
-
|
6
|
-
|
5
|
+
class_name: Merit::ActivityLog,
|
6
|
+
as: :related_change
|
7
7
|
|
8
8
|
if defined?(ProtectedAttributes) || !defined?(ActionController::StrongParameters)
|
9
9
|
attr_accessible :badge_id
|
@@ -12,13 +12,9 @@ module Merit
|
|
12
12
|
def self.last_granted(options = {})
|
13
13
|
options[:since_date] ||= 1.month.ago
|
14
14
|
options[:limit] ||= 10
|
15
|
-
where("created_at > '#{options[:since_date]}'")
|
16
|
-
limit(options[:limit])
|
17
|
-
map(&:badge)
|
18
|
-
end
|
19
|
-
|
20
|
-
def badge
|
21
|
-
Badge.find(badge_id)
|
15
|
+
where("created_at > '#{options[:since_date]}'")
|
16
|
+
.limit(options[:limit])
|
17
|
+
.map(&:badge)
|
22
18
|
end
|
23
19
|
end
|
24
20
|
end
|
@@ -6,56 +6,20 @@ module Merit
|
|
6
6
|
# It's existence make join models like badges_users and scores_users
|
7
7
|
# unnecessary. It should be transparent at the application.
|
8
8
|
class Sash < ActiveRecord::Base
|
9
|
+
include Base::Sash
|
9
10
|
has_many :badges_sashes, dependent: :destroy
|
10
11
|
has_many :scores, dependent: :destroy, class_name: 'Merit::Score'
|
11
12
|
|
12
13
|
after_create :create_scores
|
13
14
|
|
14
|
-
def badges
|
15
|
-
badge_ids.map { |id| Badge.find id }
|
16
|
-
end
|
17
|
-
|
18
|
-
def badge_ids
|
19
|
-
badges_sashes.map(&:badge_id)
|
20
|
-
end
|
21
|
-
|
22
15
|
def add_badge(badge_id)
|
23
16
|
bs = BadgesSash.new(badge_id: badge_id)
|
24
|
-
|
17
|
+
badges_sashes << bs
|
25
18
|
bs
|
26
19
|
end
|
27
20
|
|
28
21
|
def rm_badge(badge_id)
|
29
22
|
badges_sashes.find_by_badge_id(badge_id).try(:destroy)
|
30
23
|
end
|
31
|
-
|
32
|
-
|
33
|
-
def points(category = 'default')
|
34
|
-
scores.where(category: category).first.points
|
35
|
-
end
|
36
|
-
|
37
|
-
def add_points(num_points, log = 'Manually granted', category = 'default')
|
38
|
-
point = Merit::Score::Point.new
|
39
|
-
point.log = log
|
40
|
-
point.num_points = num_points
|
41
|
-
self.scores.where(category: category).first.score_points << point
|
42
|
-
point
|
43
|
-
end
|
44
|
-
|
45
|
-
# DEPRECATED: Please use <tt>subtract_points</tt> instead.
|
46
|
-
def substract_points(num_points, log = 'Manually granted', category = 'default')
|
47
|
-
warn "[DEPRECATION] `substract_points` is deprecated. Please use `subtract_points` instead."
|
48
|
-
subtract_points num_points, log, category
|
49
|
-
end
|
50
|
-
|
51
|
-
def subtract_points(num_points, log = 'Manually granted', category = 'default')
|
52
|
-
add_points -num_points, log, category
|
53
|
-
end
|
54
|
-
|
55
|
-
private
|
56
|
-
|
57
|
-
def create_scores
|
58
|
-
self.scores << Merit::Score.create
|
59
|
-
end
|
60
24
|
end
|
61
25
|
end
|
@@ -3,8 +3,8 @@ module Merit
|
|
3
3
|
self.table_name = :merit_scores
|
4
4
|
belongs_to :sash
|
5
5
|
has_many :score_points,
|
6
|
-
|
7
|
-
|
6
|
+
dependent: :destroy,
|
7
|
+
class_name: 'Merit::Score::Point'
|
8
8
|
|
9
9
|
# Meant to display a leaderboard. Accepts options :table_name (users by
|
10
10
|
# default), :since_date (1.month.ago by default) and :limit (10 by
|
@@ -24,7 +24,7 @@ module Merit
|
|
24
24
|
sash_id_column = "#{options[:table_name]}.sash_id"
|
25
25
|
end
|
26
26
|
|
27
|
-
# MeritableModel
|
27
|
+
# MeritableModel - Sash -< Scores -< ScorePoints
|
28
28
|
sql_query = <<SQL
|
29
29
|
SELECT
|
30
30
|
#{options[:table_name]}.id AS #{alias_id_column},
|
@@ -50,9 +50,10 @@ SQL
|
|
50
50
|
|
51
51
|
class Point < ActiveRecord::Base
|
52
52
|
belongs_to :score, class_name: 'Merit::Score'
|
53
|
+
has_one :sash, through: :score
|
53
54
|
has_many :activity_logs,
|
54
|
-
|
55
|
-
|
55
|
+
class_name: Merit::ActivityLog,
|
56
|
+
as: :related_change
|
56
57
|
end
|
57
58
|
end
|
58
59
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Merit
|
2
|
+
module Base
|
3
|
+
module Sash
|
4
|
+
# Methods that are common between both the active_record and mongoid sash model
|
5
|
+
def badges
|
6
|
+
badge_ids.map { |id| Merit::Badge.find id }
|
7
|
+
end
|
8
|
+
|
9
|
+
def badge_ids
|
10
|
+
badges_sashes.map(&:badge_id)
|
11
|
+
end
|
12
|
+
|
13
|
+
def points(category = 'default')
|
14
|
+
scores.where(category: category).first.points
|
15
|
+
end
|
16
|
+
|
17
|
+
def add_points(num_points, log = 'Manually granted', category = 'default')
|
18
|
+
point = Merit::Score::Point.new
|
19
|
+
point.log = log
|
20
|
+
point.num_points = num_points
|
21
|
+
scores.where(category: category).first.score_points << point
|
22
|
+
point
|
23
|
+
end
|
24
|
+
|
25
|
+
# DEPRECATED: Please use <tt>subtract_points</tt> instead.
|
26
|
+
def substract_points(num_points, log = 'Manually granted', category = 'default')
|
27
|
+
warn '[DEPRECATION] `substract_points` is deprecated. Please use `subtract_points` instead.'
|
28
|
+
subtract_points num_points, log, category
|
29
|
+
end
|
30
|
+
|
31
|
+
def subtract_points(num_points, log = 'Manually granted', category = 'default')
|
32
|
+
add_points(-num_points, log, category)
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def create_scores
|
38
|
+
scores << Merit::Score.create
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -3,13 +3,15 @@ module Merit
|
|
3
3
|
include Mongoid::Document
|
4
4
|
include Mongoid::Timestamps
|
5
5
|
|
6
|
-
|
7
|
-
field :action_method
|
8
|
-
field :action_value, type: Integer
|
9
|
-
field :had_errors, type: Boolean
|
6
|
+
has_many :activity_logs, class_name: 'Merit::ActivityLog', as: :related_change
|
10
7
|
|
11
|
-
|
12
|
-
field :
|
8
|
+
field :user_id
|
9
|
+
field :action_method
|
10
|
+
field :action_value, type: Integer
|
11
|
+
field :had_errors, type: Boolean
|
12
|
+
field :target_model
|
13
|
+
field :target_id
|
14
|
+
field :processed, type: Boolean, default: false
|
13
15
|
field :log
|
14
16
|
end
|
15
17
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Merit
|
2
|
+
class BadgesSash
|
3
|
+
include Mongoid::Document
|
4
|
+
include Mongoid::Timestamps
|
5
|
+
include Base::BadgesSash
|
6
|
+
|
7
|
+
field :badge_id, type: Integer
|
8
|
+
attr_accessible :badge_id
|
9
|
+
has_many :activity_logs, class_name: 'Merit::ActivityLog', as: :related_change
|
10
|
+
|
11
|
+
def self.last_granted(options = {})
|
12
|
+
options[:since_date] ||= 1.month.ago
|
13
|
+
options[:limit] ||= 10
|
14
|
+
where(:created_at.lte => options[:since_date])
|
15
|
+
.limit(options[:limit])
|
16
|
+
.map(&:badge)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Merit
|
2
|
+
# Sash is a container for reputation data for meritable models. It's an
|
3
|
+
# indirection between meritable models and badges and scores (one to one
|
4
|
+
# relationship).
|
5
|
+
#
|
6
|
+
# It's existence make join models like badges_users and scores_users
|
7
|
+
# unnecessary. It should be transparent at the application.
|
8
|
+
class Sash
|
9
|
+
include Mongoid::Document
|
10
|
+
include Mongoid::Timestamps
|
11
|
+
include Base::Sash
|
12
|
+
|
13
|
+
has_many :badges_sashes, class_name: 'Merit::BadgesSash', dependent: :destroy
|
14
|
+
has_many :scores, class_name: 'Merit::Score', dependent: :destroy
|
15
|
+
|
16
|
+
after_create :create_scores
|
17
|
+
|
18
|
+
def add_badge(badge_id)
|
19
|
+
bs = Merit::BadgesSash.new(badge_id: badge_id)
|
20
|
+
badges_sashes.push(bs)
|
21
|
+
end
|
22
|
+
|
23
|
+
def rm_badge(badge_id)
|
24
|
+
bs = badges_sashes.where(badge_id: badge_id).first
|
25
|
+
badges_sashes.delete(bs)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Merit
|
2
|
+
class Score
|
3
|
+
include Mongoid::Document
|
4
|
+
include Mongoid::Timestamps
|
5
|
+
|
6
|
+
field :category, type: String, default: 'default'
|
7
|
+
|
8
|
+
belongs_to :sash
|
9
|
+
has_many :score_points, class_name: 'Merit::Score::Point', dependent: :destroy
|
10
|
+
|
11
|
+
# Meant to display a leaderboard. Accepts options :table_name (users by
|
12
|
+
# default), :since_date (1.month.ago by default) and :limit (10 by
|
13
|
+
# default).
|
14
|
+
#
|
15
|
+
# It lists top 10 scored objects in the last month, unless you change
|
16
|
+
# query parameters.
|
17
|
+
def self.top_scored(options = {})
|
18
|
+
options[:since_date] ||= 1.month.ago
|
19
|
+
options[:limit] ||= 10
|
20
|
+
Score.where(created_at: (options[:since_date]..Time.now))
|
21
|
+
.desc(:points)
|
22
|
+
.limit(options[:limit])
|
23
|
+
.flatten.map { |score| score.sash.user }
|
24
|
+
end
|
25
|
+
|
26
|
+
def points
|
27
|
+
score_points.sum(:num_points) || 0
|
28
|
+
end
|
29
|
+
|
30
|
+
class Point
|
31
|
+
include Mongoid::Document
|
32
|
+
include Mongoid::Timestamps
|
33
|
+
|
34
|
+
field :num_points, type: Integer, default: 0
|
35
|
+
field :log, type: String
|
36
|
+
|
37
|
+
belongs_to :score, class_name: 'Merit::Score'
|
38
|
+
has_many :activity_logs, class_name: 'Merit::ActivityLog', as: :related_change
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/merit/rule.rb
CHANGED
@@ -4,7 +4,7 @@ module Merit
|
|
4
4
|
# Could split this class between badges and rankings functionality
|
5
5
|
class Rule
|
6
6
|
attr_accessor :badge_name, :level, :to, :model_name, :level_name,
|
7
|
-
|
7
|
+
:multiple, :temporary, :score, :block
|
8
8
|
|
9
9
|
# Does this rule's condition block apply?
|
10
10
|
def applies?(target_obj = nil)
|
data/lib/merit/rules_matcher.rb
CHANGED
@@ -23,7 +23,7 @@ module Merit
|
|
23
23
|
end
|
24
24
|
|
25
25
|
defined_rules[options[:to]] ||= {}
|
26
|
-
defined_rules[options[:to]].merge!(
|
26
|
+
defined_rules[options[:to]].merge!(options[:level] => rule)
|
27
27
|
end
|
28
28
|
|
29
29
|
# Not part of merit after_filter. To be called asynchronously:
|
data/lib/merit/target_finder.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Merit
|
2
2
|
class TargetFinder < Struct.new(:rule, :action)
|
3
3
|
def self.find(*args)
|
4
|
-
|
4
|
+
new(*args).find
|
5
5
|
end
|
6
6
|
|
7
7
|
def find
|
@@ -40,6 +40,5 @@ module Merit
|
|
40
40
|
str << ' (called from Merit::TargetFinder#other_target)'
|
41
41
|
Rails.logger.warn str
|
42
42
|
end
|
43
|
-
|
44
43
|
end
|
45
44
|
end
|
data/merit.gemspec
CHANGED
@@ -5,7 +5,7 @@ Gem::Specification.new do |s|
|
|
5
5
|
s.homepage = "http://github.com/tute/merit"
|
6
6
|
s.files = `git ls-files`.split("\n").reject{|f| f =~ /^\./ }
|
7
7
|
s.license = 'MIT'
|
8
|
-
s.version = '1.
|
8
|
+
s.version = '1.8.0'
|
9
9
|
s.authors = ["Tute Costa"]
|
10
10
|
s.email = 'tutecosta@gmail.com'
|
11
11
|
|
@@ -15,6 +15,7 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.add_development_dependency 'rails', '>= 3.2.0'
|
16
16
|
s.add_development_dependency 'capybara'
|
17
17
|
s.add_development_dependency 'simplecov'
|
18
|
+
s.add_development_dependency 'rubocop'
|
18
19
|
s.add_development_dependency 'minitest-rails'
|
19
20
|
s.add_development_dependency 'mocha', '0.13.3'
|
20
21
|
end
|