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 CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- merit (1.2.1)
4
+ merit (1.2.2)
5
5
  ambry (~> 0.3.0)
6
6
 
7
7
  GEM
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
- ```ruby
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
- You may also change user points "by hand":
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.
@@ -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.check_unprocessed_rules
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
- unless @prev_migration_nr
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
- unless @prev_migration_nr
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
- ::Merit::AppBadgeRules = ::Merit::BadgeRules.new.defined_rules
54
- ::Merit::AppPointRules = ::Merit::PointRules.new.defined_rules
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
- return unless rules_defined?
9
-
10
- Merit::Action.create(
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
- # Delegate relationship methods from meritable models to their sash
27
- # _sash initializes a sash if doesn't have one yet.
28
- # From Rails 3.2 we can override association methods to do so
29
- # transparently, but merit supports Rails ~> 3.0.0. See:
30
- # http://blog.hasmanythrough.com/2012/1/20/modularized-association-methods-in-rails-3-2
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.sash = Sash.create
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 = level_and_rules.sort
30
- level_and_rules.each do |level, rule|
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.1'
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'
@@ -21,4 +21,4 @@ module Merit
21
21
  end
22
22
  end
23
23
  end
24
- end
24
+ end
@@ -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.1
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: 2012-12-13 00:00:00.000000000 Z
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: