merit 0.6.3 → 0.7.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.
- data/Gemfile.lock +6 -1
- data/README.md +2 -0
- data/TESTING.txt +11 -0
- data/app/models/badge.rb +2 -6
- data/config/locales/en.yml +4 -0
- data/lib/merit/controller_extensions.rb +12 -3
- data/lib/merit/model_additions.rb +1 -1
- data/lib/merit/models/active_record/sash.rb +1 -1
- data/lib/merit/rule.rb +7 -5
- data/lib/merit/rules_badge.rb +1 -0
- data/merit.gemspec +2 -1
- data/test/dummy/app/models/merit/badge_rules.rb +7 -1
- data/test/dummy/app/models/user.rb +11 -1
- data/test/dummy/app/views/layouts/application.html.erb +23 -0
- data/test/dummy/app/views/users/_form.html.erb +1 -1
- data/test/dummy/config/initializers/merit.rb +3 -0
- data/test/integration/navigation_test.rb +19 -7
- data/test/merit_unit_test.rb +7 -0
- data/test/test_helper.rb +12 -1
- metadata +26 -13
- data/test/dummy/app/views/layouts/application.html.haml +0 -18
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
merit (0.
|
4
|
+
merit (0.7.0)
|
5
5
|
ambry
|
6
6
|
|
7
7
|
GEM
|
@@ -96,6 +96,10 @@ GEM
|
|
96
96
|
libwebsocket (~> 0.1.3)
|
97
97
|
multi_json (~> 1.0)
|
98
98
|
rubyzip
|
99
|
+
simplecov (0.6.4)
|
100
|
+
multi_json (~> 1.0)
|
101
|
+
simplecov-html (~> 0.5.3)
|
102
|
+
simplecov-html (0.5.3)
|
99
103
|
sprockets (2.1.3)
|
100
104
|
hike (~> 1.2)
|
101
105
|
rack (~> 1.0)
|
@@ -118,4 +122,5 @@ DEPENDENCIES
|
|
118
122
|
haml
|
119
123
|
merit!
|
120
124
|
rails (~> 3.2.3)
|
125
|
+
simplecov
|
121
126
|
sqlite3
|
data/README.md
CHANGED
@@ -29,6 +29,7 @@ holds. Badges may have levels, and may be temporary. Define rules on
|
|
29
29
|
* <tt>:to</tt> method name over target_object which obtains object to badge
|
30
30
|
* <tt>:model_name</tt> (string) define controller's name if it differs from
|
31
31
|
the model (like <tt>RegistrationsController</tt> for <tt>User</tt> model).
|
32
|
+
* <tt>:multiple</tt> (boolean) badge may be granted multiple times
|
32
33
|
* <tt>:temporary</tt> (boolean) if the receiver had the badge but the
|
33
34
|
condition doesn't hold anymore, remove it. <tt>false</tt> by default (badges
|
34
35
|
are kept forever).
|
@@ -114,6 +115,7 @@ Check for rules on a rake task executed in background like:
|
|
114
115
|
|
115
116
|
# To-do list
|
116
117
|
|
118
|
+
* add an error handler for inexistent badges.
|
117
119
|
* rails g merit MODEL_NAME shouldn't create general migrations again.
|
118
120
|
* Abstract User (rule.rb#51 for instance) into a Merit option.
|
119
121
|
* Should namespace app/models into Merit module.
|
data/TESTING.txt
ADDED
data/app/models/badge.rb
CHANGED
@@ -27,12 +27,8 @@ class Badge
|
|
27
27
|
def grant_to(object_or_sash)
|
28
28
|
object_or_sash.create_sash_if_none unless object_or_sash.kind_of?(Sash)
|
29
29
|
sash = object_or_sash.respond_to?(:sash) ? object_or_sash.sash : object_or_sash
|
30
|
-
|
31
|
-
|
32
|
-
else
|
33
|
-
sash.add_badge(id)
|
34
|
-
return true
|
35
|
-
end
|
30
|
+
sash.add_badge(id)
|
31
|
+
return true
|
36
32
|
end
|
37
33
|
|
38
34
|
# Take out badge from sash
|
@@ -17,11 +17,10 @@ module Merit
|
|
17
17
|
end
|
18
18
|
|
19
19
|
# TODO: value should be configurable (now it's params[:value] set in the controller)
|
20
|
-
|
21
|
-
MeritAction.create(
|
20
|
+
merit_action_id = MeritAction.create(
|
22
21
|
:user_id => current_user.try(:id),
|
23
22
|
:action_method => action_name,
|
24
|
-
:action_value => value,
|
23
|
+
:action_value => params[:value],
|
25
24
|
:had_errors => target_object.try(:errors).try(:present?),
|
26
25
|
:target_model => controller_name,
|
27
26
|
:target_id => target_id
|
@@ -30,6 +29,16 @@ module Merit
|
|
30
29
|
# Check rules in after_filter?
|
31
30
|
if Merit.checks_on_each_request
|
32
31
|
badge_rules.check_new_actions
|
32
|
+
|
33
|
+
# Show flash msg?
|
34
|
+
if (log = MeritAction.find(merit_action_id).log)
|
35
|
+
# Badges granted to current_user
|
36
|
+
granted = log.split('|').select{|log| log =~ /badge_granted_to_action_user/ }
|
37
|
+
granted.each do |badge|
|
38
|
+
badge_id = badge.split(':').last.to_i
|
39
|
+
flash[:merit] = t('merit.flashs.badge_granted', badge: Badge.find(badge_id).name)
|
40
|
+
end
|
41
|
+
end
|
33
42
|
end
|
34
43
|
end
|
35
44
|
end
|
@@ -13,7 +13,7 @@ class Sash < ActiveRecord::Base
|
|
13
13
|
end
|
14
14
|
def rm_badge(badge_id)
|
15
15
|
badges_sashes = BadgesSash.where(:badge_id => badge_id, :sash_id => self.id)
|
16
|
-
# ActiveRecord::Relation#delete doesn't work with composite keys.
|
16
|
+
# ActiveRecord::Relation#delete|destroy(_all) doesn't work with composite keys.
|
17
17
|
# Badge is not AR model (Ambry) so can't do self.badges.find(badge_id).delete
|
18
18
|
badges_sash = badges_sashes.first
|
19
19
|
badges_sashes.delete_all
|
data/lib/merit/rule.rb
CHANGED
@@ -3,7 +3,7 @@ module Merit
|
|
3
3
|
# and a temporary option.
|
4
4
|
# Could split this class between badges and rankings functionality
|
5
5
|
class Rule
|
6
|
-
attr_accessor :badge_name, :level, :to, :temporary, :block, :model_name, :level_name
|
6
|
+
attr_accessor :badge_name, :level, :to, :multiple, :temporary, :block, :model_name, :level_name
|
7
7
|
|
8
8
|
# Does this rule's condition block apply?
|
9
9
|
def applies?(target_obj = nil)
|
@@ -22,7 +22,7 @@ module Merit
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
|
25
|
+
def multiple?; self.multiple; end
|
26
26
|
def temporary?; self.temporary; end
|
27
27
|
|
28
28
|
# Grant badge if rule applies. If it doesn't, and the badge is temporary,
|
@@ -34,12 +34,14 @@ module Merit
|
|
34
34
|
end
|
35
35
|
|
36
36
|
if applies? action.target_object(model_name)
|
37
|
-
if badge.
|
38
|
-
|
37
|
+
if !sash.badge_ids.include?(badge.id) || multiple?
|
38
|
+
badge.grant_to(sash)
|
39
|
+
to_action_user = (to.to_sym == :action_user ? '_to_action_user' : '')
|
40
|
+
action.log!("badge_granted#{to_action_user}:#{badge.id}")
|
39
41
|
end
|
40
42
|
elsif temporary?
|
41
43
|
if badge.delete_from(sash)
|
42
|
-
action.log!("badge_removed:#{badge.
|
44
|
+
action.log!("badge_removed:#{badge.id}")
|
43
45
|
end
|
44
46
|
end
|
45
47
|
end
|
data/lib/merit/rules_badge.rb
CHANGED
@@ -40,6 +40,7 @@ module Merit
|
|
40
40
|
rule.badge_name = options[:badge]
|
41
41
|
rule.level = options[:level]
|
42
42
|
rule.to = options[:to] || :action_user
|
43
|
+
rule.multiple = options[:multiple] || false
|
43
44
|
rule.temporary = options[:temporary] || false
|
44
45
|
rule.model_name = options[:model_name] || actions[0].split('#')[0]
|
45
46
|
rule.block = block
|
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 = "0.
|
7
|
+
s.version = "0.7.0"
|
8
8
|
s.authors = ["Tute Costa"]
|
9
9
|
s.email = 'tutecosta@gmail.com'
|
10
10
|
s.add_dependency 'ambry'
|
@@ -12,4 +12,5 @@ Gem::Specification.new do |s|
|
|
12
12
|
s.add_development_dependency 'sqlite3'
|
13
13
|
s.add_development_dependency 'haml'
|
14
14
|
s.add_development_dependency 'capybara'
|
15
|
+
s.add_development_dependency 'simplecov'
|
15
16
|
end
|
@@ -21,7 +21,13 @@ module Merit
|
|
21
21
|
def initialize
|
22
22
|
# If it creates user, grant badge
|
23
23
|
# Should be "current_user" after registration for badge to be granted.
|
24
|
-
|
24
|
+
# Example rule with block with no parameters
|
25
|
+
grant_on 'users#create', :badge => 'just-registered', :to => :itself do
|
26
|
+
Date.today > 1.year.ago.to_date
|
27
|
+
end
|
28
|
+
|
29
|
+
# Example rule for multiple badge granting
|
30
|
+
grant_on 'users#index', :badge => 'gossip', :multiple => true
|
25
31
|
|
26
32
|
# If it has 10 comments, grant commenter-10 badge
|
27
33
|
grant_on 'comments#create', :badge => 'commenter', :level => 10 do |comment|
|
@@ -6,6 +6,16 @@ class User < ActiveRecord::Base
|
|
6
6
|
attr_accessible :name
|
7
7
|
|
8
8
|
def show_badges
|
9
|
-
|
9
|
+
create_sash_if_none
|
10
|
+
badges_uniq = Badge.find_by_id(sash.badge_ids)
|
11
|
+
badges_uniq.collect{|b| "#{b.name.capitalize}#{badge_status(b)}" }.join(', ')
|
12
|
+
end
|
13
|
+
|
14
|
+
def badge_status(badge)
|
15
|
+
status = []
|
16
|
+
count = badges.select{|b| b.name == badge.name }.count
|
17
|
+
status << "level: #{badge.level}" if badge.level
|
18
|
+
status << "x#{count}" if count > 1
|
19
|
+
status.present? ? " (#{status.join(', ')})" : ''
|
10
20
|
end
|
11
21
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html lang="en">
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8" />
|
5
|
+
<title>Merit Dummy app</title>
|
6
|
+
<%= stylesheet_link_tag :all %>
|
7
|
+
<%= csrf_meta_tag %>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
<h1><%= link_to 'Dummy app', '/' %></h1>
|
11
|
+
|
12
|
+
<% flash.each do |name, msg| %>
|
13
|
+
<%= content_tag :p, msg, :class => (name == 'error' ? 'error' : 'notice') %>
|
14
|
+
<% end %>
|
15
|
+
|
16
|
+
<%= yield %>
|
17
|
+
|
18
|
+
<ul>
|
19
|
+
<li><%= link_to 'Users', users_url %></li>
|
20
|
+
<li><%= link_to 'Comments', comments_url %></li>
|
21
|
+
</ul>
|
22
|
+
</body>
|
23
|
+
</html>
|
@@ -1,15 +1,27 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class NavigationTest < ActiveSupport::IntegrationCase
|
4
|
-
|
5
|
-
|
4
|
+
test 'user sign up should grant badge to itself' do
|
5
|
+
visit '/users/new'
|
6
|
+
fill_in 'Name', :with => 'Jack'
|
7
|
+
click_button('Create User')
|
8
|
+
|
9
|
+
user = User.where(:name => 'Jack').first
|
10
|
+
assert_equal [Badge.by_name('just-registered').first], user.badges.to_a
|
6
11
|
end
|
7
12
|
|
8
|
-
test '
|
9
|
-
user = User.
|
10
|
-
|
13
|
+
test 'users#index should grant badge multiple times' do
|
14
|
+
user = User.create(:name => 'test-user')
|
15
|
+
visit '/users'
|
16
|
+
visit '/users'
|
17
|
+
visit '/users'
|
18
|
+
visit '/users'
|
19
|
+
assert_equal 4, User.first.badges.count
|
20
|
+
end
|
11
21
|
|
22
|
+
test 'user workflow should grant some badges at some times' do
|
12
23
|
# Commented 9 times, no badges yet
|
24
|
+
user = User.create(:name => 'test-user')
|
13
25
|
(1..9).each do |i|
|
14
26
|
Comment.create(
|
15
27
|
:name => "Title #{i}",
|
@@ -65,7 +77,7 @@ class NavigationTest < ActiveSupport::IntegrationCase
|
|
65
77
|
end
|
66
78
|
|
67
79
|
test 'user workflow should add up points at some times' do
|
68
|
-
user = User.
|
80
|
+
user = User.create(:name => 'test-user')
|
69
81
|
assert_equal 0, user.points, 'User should start with 0 points'
|
70
82
|
|
71
83
|
visit "/users/#{user.id}/edit"
|
@@ -96,7 +108,7 @@ class NavigationTest < ActiveSupport::IntegrationCase
|
|
96
108
|
end
|
97
109
|
|
98
110
|
test 'user workflow should grant levels at some times' do
|
99
|
-
user = User.
|
111
|
+
user = User.create(:name => 'test-user')
|
100
112
|
assert user.badges.empty?
|
101
113
|
|
102
114
|
# Edit user's name by 2 chars name
|
data/test/merit_unit_test.rb
CHANGED
@@ -12,4 +12,11 @@ class MeritUnitTest < ActiveSupport::TestCase
|
|
12
12
|
rule.block = lambda{|obj| obj.length >= 4 }
|
13
13
|
assert rule.applies?(str), 'block should make rule apply'
|
14
14
|
end
|
15
|
+
|
16
|
+
test "BadgeSash knows it's related badge" do
|
17
|
+
Badge.create(:id => 99, :name => 'test-badge')
|
18
|
+
badge_sash = BadgesSash.new
|
19
|
+
badge_sash.badge_id = 99
|
20
|
+
assert_equal Badge.find(99), badge_sash.badge
|
21
|
+
end
|
15
22
|
end
|
data/test/test_helper.rb
CHANGED
@@ -1,5 +1,16 @@
|
|
1
1
|
# Configure Rails Envinronment
|
2
2
|
ENV["RAILS_ENV"] = "test"
|
3
|
+
RUBYOPT="-w $RUBYOPT"
|
4
|
+
|
5
|
+
require 'simplecov'
|
6
|
+
SimpleCov.adapters.define 'rubygem' do
|
7
|
+
# Add app to Merit group
|
8
|
+
# https://github.com/colszowka/simplecov/pull/104
|
9
|
+
add_group 'Merit', 'lib'
|
10
|
+
add_group 'DummyApp', 'test/dummy'
|
11
|
+
add_filter 'test/dummy/config/initializers'
|
12
|
+
end
|
13
|
+
SimpleCov.start 'rubygem' if ENV["COVERAGE"]
|
3
14
|
|
4
15
|
require File.expand_path("../dummy/config/environment.rb", __FILE__)
|
5
16
|
require "rails/test_help"
|
@@ -19,4 +30,4 @@ Capybara.default_selector = :css
|
|
19
30
|
ActiveRecord::Migrator.migrate File.expand_path("../dummy/db/migrate/", __FILE__)
|
20
31
|
|
21
32
|
# Load support files
|
22
|
-
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
33
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
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: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-05-26 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ambry
|
16
|
-
requirement: &
|
16
|
+
requirement: &70355964823460 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70355964823460
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rails
|
27
|
-
requirement: &
|
27
|
+
requirement: &70355964822720 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: 3.2.3
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70355964822720
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: sqlite3
|
38
|
-
requirement: &
|
38
|
+
requirement: &70355964822080 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70355964822080
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: haml
|
49
|
-
requirement: &
|
49
|
+
requirement: &70355964821480 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70355964821480
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: capybara
|
60
|
-
requirement: &
|
60
|
+
requirement: &70355964821060 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,7 +65,18 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70355964821060
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: simplecov
|
71
|
+
requirement: &70355964820640 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *70355964820640
|
69
80
|
description: Manage badges, points and rankings (reputation) of resources in a Rails
|
70
81
|
application.
|
71
82
|
email: tutecosta@gmail.com
|
@@ -78,9 +89,11 @@ files:
|
|
78
89
|
- MIT-LICENSE
|
79
90
|
- README.md
|
80
91
|
- Rakefile
|
92
|
+
- TESTING.txt
|
81
93
|
- UPGRADING.md
|
82
94
|
- app/models/badge.rb
|
83
95
|
- app/models/merit_action.rb
|
96
|
+
- config/locales/en.yml
|
84
97
|
- lib/generators/active_record/merit_generator.rb
|
85
98
|
- lib/generators/active_record/templates/add_fields_to_model.rb
|
86
99
|
- lib/generators/active_record/templates/create_badges_sashes.rb
|
@@ -121,7 +134,7 @@ files:
|
|
121
134
|
- test/dummy/app/views/comments/index.html.erb
|
122
135
|
- test/dummy/app/views/comments/new.html.erb
|
123
136
|
- test/dummy/app/views/comments/show.html.erb
|
124
|
-
- test/dummy/app/views/layouts/application.html.
|
137
|
+
- test/dummy/app/views/layouts/application.html.erb
|
125
138
|
- test/dummy/app/views/users/_form.html.erb
|
126
139
|
- test/dummy/app/views/users/edit.html.erb
|
127
140
|
- test/dummy/app/views/users/index.html.erb
|
@@ -1,18 +0,0 @@
|
|
1
|
-
!!!
|
2
|
-
%html
|
3
|
-
%head
|
4
|
-
%title Dummy
|
5
|
-
= stylesheet_link_tag :all
|
6
|
-
= javascript_include_tag :defaults
|
7
|
-
= csrf_meta_tag
|
8
|
-
%body
|
9
|
-
%h1= link_to 'Dummy app', '/'
|
10
|
-
|
11
|
-
- flash.each do |name, msg|
|
12
|
-
= content_tag :p, msg, :class => (name == 'error' ? 'error' : 'notice')
|
13
|
-
|
14
|
-
= yield
|
15
|
-
|
16
|
-
%ul
|
17
|
-
%li= link_to 'Users', users_url
|
18
|
-
%li= link_to 'Comments', comments_url
|