merit 1.2.1 → 1.2.2
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.
- data/Gemfile.lock +1 -1
- data/README.md +7 -22
- data/app/models/merit/action.rb +1 -1
- data/lib/generators/active_record/install_generator.rb +2 -6
- data/lib/generators/active_record/merit_generator.rb +2 -6
- data/lib/merit.rb +8 -2
- data/lib/merit/controller_extensions.rb +14 -13
- data/lib/merit/model_additions.rb +22 -10
- data/lib/merit/rules_rank_methods.rb +22 -16
- data/merit.gemspec +1 -1
- data/test/dummy/app/models/merit/rank_rules.rb +1 -1
- data/test/merit_unit_test.rb +13 -0
- metadata +3 -2
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -42,6 +42,7 @@ holds. Badges may have levels, and may be temporary. Define rules on
|
|
|
42
42
|
## Examples
|
|
43
43
|
|
|
44
44
|
```ruby
|
|
45
|
+
# app/models/merit/badge_rules.rb
|
|
45
46
|
grant_on 'comments#vote', :badge => 'relevant-commenter', :to => :user do |comment|
|
|
46
47
|
comment.votes.count == 5
|
|
47
48
|
end
|
|
@@ -51,23 +52,12 @@ grant_on ['users#create', 'users#update'], :badge => 'autobiographer', :temporar
|
|
|
51
52
|
end
|
|
52
53
|
```
|
|
53
54
|
|
|
54
|
-
### Check granted badges
|
|
55
|
-
|
|
56
55
|
```ruby
|
|
56
|
+
# Check granted badges
|
|
57
57
|
current_user.badges # Returns an array of badges
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
### Grant manually
|
|
61
|
-
|
|
62
|
-
You may also grant badges "by hand":
|
|
63
58
|
|
|
64
|
-
|
|
59
|
+
# Grant or remove manually
|
|
65
60
|
current_user.add_badge(badge.id)
|
|
66
|
-
```
|
|
67
|
-
|
|
68
|
-
Similarly you can remove badges that have been granted:
|
|
69
|
-
|
|
70
|
-
```ruby
|
|
71
61
|
current_user.rm_badge(badge.id)
|
|
72
62
|
```
|
|
73
63
|
|
|
@@ -90,6 +80,7 @@ action user or to the method(s) defined in the `:to` option. Define rules on
|
|
|
90
80
|
## Examples
|
|
91
81
|
|
|
92
82
|
```ruby
|
|
83
|
+
# app/models/merit/point_rules.rb
|
|
93
84
|
score 10, :to => :post_creator, :on => 'comments#create' do |comment|
|
|
94
85
|
comment.title.present?
|
|
95
86
|
end
|
|
@@ -102,19 +93,12 @@ score 20, :on => [
|
|
|
102
93
|
score 15, :on => 'reviews#create', :to => [:reviewer, :reviewed]
|
|
103
94
|
```
|
|
104
95
|
|
|
105
|
-
### Check awarded points
|
|
106
|
-
|
|
107
96
|
```ruby
|
|
97
|
+
# Check awarded points
|
|
108
98
|
current_user.points # Returns an integer
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
### Score manually
|
|
112
99
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
```ruby
|
|
100
|
+
# Score manually
|
|
116
101
|
current_user.add_points(20, 'Optional log message')
|
|
117
|
-
|
|
118
102
|
current_user.substract_points(10)
|
|
119
103
|
```
|
|
120
104
|
|
|
@@ -159,4 +143,5 @@ end
|
|
|
159
143
|
|
|
160
144
|
# To-do list
|
|
161
145
|
|
|
146
|
+
* Improve model_additions with http://blog.8thlight.com/josh-cheek/2012/02/03/modules-called-they-want-their-integrity-back.html
|
|
162
147
|
* Should namespace Badge, BadgesSash and Sash into Merit module.
|
data/app/models/merit/action.rb
CHANGED
|
@@ -17,7 +17,7 @@ module Merit
|
|
|
17
17
|
attr_accessible :user_id, :action_method, :action_value, :had_errors,
|
|
18
18
|
:target_model, :target_id, :processed, :log
|
|
19
19
|
|
|
20
|
-
def self.
|
|
20
|
+
def self.check_unprocessed
|
|
21
21
|
where(:processed => false).map &:check_all_rules
|
|
22
22
|
end
|
|
23
23
|
|
|
@@ -4,16 +4,12 @@ module ActiveRecord
|
|
|
4
4
|
module Generators
|
|
5
5
|
class InstallGenerator < Rails::Generators::Base
|
|
6
6
|
include Rails::Generators::Migration
|
|
7
|
+
|
|
7
8
|
source_root File.expand_path('../templates', __FILE__)
|
|
8
9
|
desc "add active_record merit migrations for the root objects"
|
|
9
10
|
|
|
10
11
|
def self.next_migration_number(path)
|
|
11
|
-
|
|
12
|
-
@prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
|
|
13
|
-
else
|
|
14
|
-
@prev_migration_nr += 1
|
|
15
|
-
end
|
|
16
|
-
@prev_migration_nr.to_s
|
|
12
|
+
ActiveRecord::Generators::Base.next_migration_number(path)
|
|
17
13
|
end
|
|
18
14
|
|
|
19
15
|
def copy_migrations_and_model
|
|
@@ -4,16 +4,12 @@ module ActiveRecord
|
|
|
4
4
|
module Generators
|
|
5
5
|
class MeritGenerator < ActiveRecord::Generators::Base
|
|
6
6
|
include Rails::Generators::Migration
|
|
7
|
+
|
|
7
8
|
source_root File.expand_path('../templates', __FILE__)
|
|
8
9
|
desc "add active_record merit migrations"
|
|
9
10
|
|
|
10
11
|
def self.next_migration_number(path)
|
|
11
|
-
|
|
12
|
-
@prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
|
|
13
|
-
else
|
|
14
|
-
@prev_migration_nr += 1
|
|
15
|
-
end
|
|
16
|
-
@prev_migration_nr.to_s
|
|
12
|
+
ActiveRecord::Generators::Base.next_migration_number(path)
|
|
17
13
|
end
|
|
18
14
|
|
|
19
15
|
def copy_migrations_and_model
|
data/lib/merit.rb
CHANGED
|
@@ -35,6 +35,7 @@ module Merit
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
class BadgeNotFound < Exception; end
|
|
38
|
+
class RankAttributeNotDefined < Exception; end
|
|
38
39
|
|
|
39
40
|
class Engine < Rails::Engine
|
|
40
41
|
config.app_generators.orm Merit.orm
|
|
@@ -50,8 +51,13 @@ module Merit
|
|
|
50
51
|
|
|
51
52
|
ActiveSupport.on_load(:action_controller) do
|
|
52
53
|
# Load application defined rules on application boot up
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
# Test if constant exists (doesn't while installing/generating files)
|
|
55
|
+
if defined? '::Merit::BadgeRules'
|
|
56
|
+
::Merit::AppBadgeRules = ::Merit::BadgeRules.new.defined_rules
|
|
57
|
+
end
|
|
58
|
+
if defined? '::Merit::PointRules'
|
|
59
|
+
::Merit::AppPointRules = ::Merit::PointRules.new.defined_rules
|
|
60
|
+
end
|
|
55
61
|
|
|
56
62
|
include Merit::ControllerExtensions
|
|
57
63
|
end
|
|
@@ -5,25 +5,26 @@ module Merit
|
|
|
5
5
|
module ControllerExtensions
|
|
6
6
|
def self.included(base)
|
|
7
7
|
base.after_filter do |controller|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
:user_id => send(Merit.current_user_method).try(:id),
|
|
12
|
-
:action_method => action_name,
|
|
13
|
-
:action_value => params[:value],
|
|
14
|
-
:had_errors => had_errors?,
|
|
15
|
-
:target_model => controller_path,
|
|
16
|
-
:target_id => target_id
|
|
17
|
-
).id
|
|
18
|
-
|
|
19
|
-
if Merit.checks_on_each_request
|
|
20
|
-
Merit::Action.check_unprocessed_rules
|
|
8
|
+
if rules_defined?
|
|
9
|
+
log_merit_action
|
|
10
|
+
Merit::Action.check_unprocessed if Merit.checks_on_each_request
|
|
21
11
|
end
|
|
22
12
|
end
|
|
23
13
|
end
|
|
24
14
|
|
|
25
15
|
private
|
|
26
16
|
|
|
17
|
+
def log_merit_action
|
|
18
|
+
Merit::Action.create(
|
|
19
|
+
:user_id => send(Merit.current_user_method).try(:id),
|
|
20
|
+
:action_method => action_name,
|
|
21
|
+
:action_value => params[:value],
|
|
22
|
+
:had_errors => had_errors?,
|
|
23
|
+
:target_model => controller_path,
|
|
24
|
+
:target_id => target_id
|
|
25
|
+
).id
|
|
26
|
+
end
|
|
27
|
+
|
|
27
28
|
def rules_defined?
|
|
28
29
|
action = "#{controller_path}\##{action_name}"
|
|
29
30
|
AppBadgeRules[action].present? || AppPointRules[action].present?
|
|
@@ -9,6 +9,21 @@ module Merit
|
|
|
9
9
|
# https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/1079-belongs_to-dependent-destroy-should-destroy-self-before-assocation
|
|
10
10
|
belongs_to :sash
|
|
11
11
|
|
|
12
|
+
merit_orm_specific_config
|
|
13
|
+
|
|
14
|
+
merit_delegate_methods_to_sash
|
|
15
|
+
merit_sash_initializer
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Delegate methods from meritable models to their sash
|
|
19
|
+
def merit_delegate_methods_to_sash
|
|
20
|
+
methods = %w(badge_ids badges points
|
|
21
|
+
add_badge rm_badge
|
|
22
|
+
add_points substract_points)
|
|
23
|
+
methods.each { |method| delegate method, to: :_sash }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def merit_orm_specific_config
|
|
12
27
|
if Merit.orm == :mongo_mapper
|
|
13
28
|
plugin Merit
|
|
14
29
|
key :sash_id, String
|
|
@@ -22,19 +37,16 @@ module Merit
|
|
|
22
37
|
where(:_id => id).first
|
|
23
38
|
end
|
|
24
39
|
end
|
|
40
|
+
end
|
|
25
41
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
%w(badge_ids badges points add_badge rm_badge add_points substract_points).each do |method|
|
|
32
|
-
delegate method, to: :_sash
|
|
33
|
-
end
|
|
42
|
+
# _sash initializes a sash if doesn't have one yet.
|
|
43
|
+
# From Rails 3.2 we can override association methods to do so
|
|
44
|
+
# transparently, but merit supports Rails ~> 3.0.0. See:
|
|
45
|
+
# http://blog.hasmanythrough.com/2012/1/20/modularized-association-methods-in-rails-3-2
|
|
46
|
+
def merit_sash_initializer
|
|
34
47
|
define_method(:_sash) do
|
|
35
48
|
if sash.nil?
|
|
36
|
-
self.
|
|
37
|
-
self.save(:validate => false)
|
|
49
|
+
self.update_attribute :sash_id, Sash.create.id
|
|
38
50
|
end
|
|
39
51
|
self.sash
|
|
40
52
|
end
|
|
@@ -26,22 +26,8 @@ module Merit
|
|
|
26
26
|
# Merit::RankRules.new.check_rank_rules
|
|
27
27
|
def check_rank_rules
|
|
28
28
|
defined_rules.each do |scoped_model, level_and_rules|
|
|
29
|
-
level_and_rules
|
|
30
|
-
|
|
31
|
-
begin
|
|
32
|
-
if Merit.orm == :mongoid
|
|
33
|
-
items = scoped_model.where(:"#{rule.level_name}".lt => level)
|
|
34
|
-
else
|
|
35
|
-
items = scoped_model.where("#{rule.level_name} < #{level}")
|
|
36
|
-
end
|
|
37
|
-
items.each do |obj|
|
|
38
|
-
if rule.applies?(obj)
|
|
39
|
-
obj.update_attribute rule.level_name, level
|
|
40
|
-
end
|
|
41
|
-
end
|
|
42
|
-
rescue ActiveRecord::StatementInvalid
|
|
43
|
-
Rails.logger.warn "[merit] Please add #{rule.level_name} column/attribute to #{scoped_model.new.class.name}"
|
|
44
|
-
end
|
|
29
|
+
level_and_rules.sort.each do |level, rule|
|
|
30
|
+
grant_when_applies(scoped_model, rule, level)
|
|
45
31
|
end
|
|
46
32
|
end
|
|
47
33
|
end
|
|
@@ -50,5 +36,25 @@ module Merit
|
|
|
50
36
|
def defined_rules
|
|
51
37
|
@defined_rules ||= {}
|
|
52
38
|
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def grant_when_applies(scoped_model, rule, level)
|
|
43
|
+
scope_to_promote(scoped_model, rule.level_name, level).each do |object|
|
|
44
|
+
if rule.applies?(object)
|
|
45
|
+
object.update_attribute rule.level_name, level
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
rescue ActiveRecord::StatementInvalid => msg
|
|
49
|
+
raise RankAttributeNotDefined, "Add #{rule.level_name} column to #{scoped_model.new.class.name}\n[#{msg}]"
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def scope_to_promote(scope, level_name, level)
|
|
53
|
+
if Merit.orm == :mongoid
|
|
54
|
+
scope.where(:"#{level_name}".lt => level)
|
|
55
|
+
else
|
|
56
|
+
scope.where("#{level_name} < #{level}")
|
|
57
|
+
end
|
|
58
|
+
end
|
|
53
59
|
end
|
|
54
60
|
end
|
data/merit.gemspec
CHANGED
|
@@ -4,7 +4,7 @@ Gem::Specification.new do |s|
|
|
|
4
4
|
s.description = "Manage badges, points and rankings (reputation) of resources in a Rails application."
|
|
5
5
|
s.homepage = "http://github.com/tute/merit"
|
|
6
6
|
s.files = `git ls-files`.split("\n").reject{|f| f =~ /^\./ }
|
|
7
|
-
s.version = '1.2.
|
|
7
|
+
s.version = '1.2.2'
|
|
8
8
|
s.authors = ["Tute Costa"]
|
|
9
9
|
s.email = 'tutecosta@gmail.com'
|
|
10
10
|
s.add_dependency 'ambry', '~> 0.3.0'
|
data/test/merit_unit_test.rb
CHANGED
|
@@ -47,4 +47,17 @@ class MeritUnitTest < ActiveSupport::TestCase
|
|
|
47
47
|
badge_sash.set_notified!
|
|
48
48
|
assert badge_sash.notified_user
|
|
49
49
|
end
|
|
50
|
+
|
|
51
|
+
test 'unknown ranking should raise merit exception' do
|
|
52
|
+
class WeirdRankRules
|
|
53
|
+
include Merit::RankRulesMethods
|
|
54
|
+
def initialize
|
|
55
|
+
set_rank :level => 1, :to => User, :level_name => :clown do |user|
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
assert_raises Merit::RankAttributeNotDefined do
|
|
60
|
+
WeirdRankRules.new.check_rank_rules
|
|
61
|
+
end
|
|
62
|
+
end
|
|
50
63
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: merit
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.2.
|
|
4
|
+
version: 1.2.2
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,7 +9,7 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date:
|
|
12
|
+
date: 2013-01-03 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: ambry
|
|
@@ -328,3 +328,4 @@ signing_key:
|
|
|
328
328
|
specification_version: 3
|
|
329
329
|
summary: General reputation Rails engine.
|
|
330
330
|
test_files: []
|
|
331
|
+
has_rdoc:
|