merit 1.2.1 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
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: