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 CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- merit (0.6.3)
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
@@ -0,0 +1,11 @@
1
+ cd test/dummy
2
+ rails g merit:install # Next n's for not overriding already defined rules
3
+ n
4
+ n
5
+ n
6
+ rails g merit user
7
+ rake db:migrate ; rake db:seed
8
+ # see it in the browser
9
+ rails server
10
+ # or run tests
11
+ cd ../.. ; rake test
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
- if sash.badge_ids.include?(id)
31
- return false
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
@@ -0,0 +1,4 @@
1
+ en:
2
+ merit:
3
+ flashs:
4
+ badge_granted: "Congratulations! You've just earned '%{badge}' badge."
@@ -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
- value = params[:value]
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
@@ -16,7 +16,7 @@ module Merit
16
16
 
17
17
  def badges
18
18
  create_sash_if_none
19
- Badge.find_by_id(sash.badge_ids)
19
+ sash.badge_ids.collect{|b_id| Badge.find(b_id) }
20
20
  end
21
21
 
22
22
  # Create sash if doesn't have
@@ -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
- # Is this rule's badge temporary?
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.grant_to(sash)
38
- action.log!("badge_granted:#{badge.name}")
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.name}")
44
+ action.log!("badge_removed:#{badge.id}")
43
45
  end
44
46
  end
45
47
  end
@@ -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.6.3"
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
- grant_on 'users#create', :badge => 'just-registered', :to => :itself
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
- badges.collect{|b| "#{b.name.capitalize} (#{b.level})" }.join(', ')
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,4 +1,4 @@
1
- <% obj = params[:action] == :new ? @user : [:registrations, @user] %>
1
+ <% obj = params[:action] == 'new' ? @user : [:registrations, @user] %>
2
2
  <%= form_for obj do |f| %>
3
3
  <% if @user.errors.any? %>
4
4
  <div id="error_explanation">
@@ -29,6 +29,9 @@ badge_id = 0
29
29
  }, {
30
30
  :id => (badge_id = badge_id+1),
31
31
  :name => 'just-registered'
32
+ }, {
33
+ :id => (badge_id = badge_id+1),
34
+ :name => 'gossip'
32
35
  }].each do |badge|
33
36
  Badge.create! badge
34
37
  end
@@ -1,15 +1,27 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class NavigationTest < ActiveSupport::IntegrationCase
4
- setup do
5
- User.create(:name => 'test-user')
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 'user workflow should grant some badges at some times' do
9
- user = User.first
10
- assert user.badges.empty?
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.first
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.first
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
@@ -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.6.3
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-04-28 00:00:00.000000000 Z
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: &70291939751160 !ruby/object:Gem::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: *70291939751160
24
+ version_requirements: *70355964823460
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rails
27
- requirement: &70291939744340 !ruby/object:Gem::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: *70291939744340
35
+ version_requirements: *70355964822720
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: sqlite3
38
- requirement: &70291939743780 !ruby/object:Gem::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: *70291939743780
46
+ version_requirements: *70355964822080
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: haml
49
- requirement: &70291939743320 !ruby/object:Gem::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: *70291939743320
57
+ version_requirements: *70355964821480
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: capybara
60
- requirement: &70291939742900 !ruby/object:Gem::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: *70291939742900
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.haml
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