merit 2.1.2 → 2.2.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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +10 -0
  3. data/Gemfile +7 -4
  4. data/Rakefile +4 -7
  5. data/UPGRADING.md +14 -0
  6. data/app/models/merit/badge.rb +1 -1
  7. data/lib/generators/active_record/templates/add_target_data_to_merit_actions.rb +5 -0
  8. data/lib/generators/active_record/templates/create_merit_actions.rb +1 -0
  9. data/lib/generators/active_record/upgrade_generator.rb +36 -0
  10. data/lib/generators/merit/upgrade_generator.rb +7 -0
  11. data/lib/merit.rb +7 -2
  12. data/lib/merit/base_target_finder.rb +19 -3
  13. data/lib/merit/controller_extensions.rb +16 -3
  14. data/lib/merit/model_additions.rb +1 -1
  15. data/lib/merit/models/active_record/merit/action.rb +1 -1
  16. data/lib/merit/models/base/badges_sash.rb +1 -1
  17. data/lib/merit/models/mongoid/merit/action.rb +1 -0
  18. data/lib/merit/rule.rb +1 -1
  19. data/lib/merit/rules_rank_methods.rb +11 -2
  20. data/lib/merit/sash_finder.rb +4 -0
  21. data/lib/merit/target_finder.rb +2 -3
  22. data/merit.gemspec +2 -3
  23. data/test/dummy/app/models/merit/point_rules.rb +4 -0
  24. data/test/dummy/app/models/user.rb +1 -1
  25. data/test/dummy/app/views/layouts/application.html.erb +0 -1
  26. data/test/dummy/db/migrate/20140819133931_add_target_data_to_merit_actions.rb +5 -0
  27. data/test/dummy/db/migrate/20140906225844_create_players.rb +8 -0
  28. data/test/dummy/db/schema.rb +36 -30
  29. data/test/integration/navigation_test.rb +39 -32
  30. data/test/orm_models/active_record.rb +0 -4
  31. data/test/orm_models/mongoid.rb +0 -5
  32. data/test/support/integration_case.rb +1 -1
  33. data/test/test_helper.rb +8 -13
  34. data/test/unit/action_test.rb +12 -0
  35. data/test/unit/base_target_finder_test.rb +39 -4
  36. data/test/unit/merit_unit_test.rb +12 -10
  37. data/test/unit/sash_finder_test.rb +2 -2
  38. data/test/unit/score_test.rb +3 -3
  39. data/test/unit/target_finder_test.rb +11 -10
  40. metadata +11 -20
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d1c7ff1372bb3ca30c5c71a235ebfbaa285be9a6
4
- data.tar.gz: 93f9531439ccb6efd93c8a3092e46016d328283e
3
+ metadata.gz: bceef6c4f4123e4b5aa45f35c90f51779803eccb
4
+ data.tar.gz: f64bea2e08e184c8b413e5410c02424f51b44c35
5
5
  SHA512:
6
- metadata.gz: 66770fcab721991a7c18ecc53d6e0bbb7190775404db8ceddd39605d32e300c1d6b1c61fa16d07a9075718777f3d093dbd72a4b1873901c367a1111fdab8713c
7
- data.tar.gz: 7f4b0660da679fb7551208aa268121c9f41bd91967fed1963a2972081f8dee27941bcf6b20d97c6c37776e81f84a7ac30af33d9a5de18f3fcaaaac7c85f3cdf3
6
+ metadata.gz: 22924df6b8915eb8dde70a0360141d2551eaf42d21cc8c45fbd8375354ff5897bd8e68433963cf426265be38eac3adfe4487c7c95376739b43f93d7d297bc075
7
+ data.tar.gz: 9d1324c2c32759030bb54e7aa9b37face51cf7e82da3ab53462b818a200e1efbb9d05d83fb896345cb112dfab21047c38bcd1c348e7175de72337df67b6f4007
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.2.0
4
+
5
+ - [#181] Rescue `ActiveRecord` only if constant is defined (doesn't trigger
6
+ errors in other ORMs).
7
+ - [#184] Namespaces `Badge` calls inside of `Merit::`. Prevents errors if the
8
+ app using merit has a model named Badge
9
+ - [#189] Fixes issue when objects needed to grant reputation are already deleted
10
+ from the database. Before, merit was either failing with exceptions or
11
+ ignoring reputation changes; now it works as expected.
12
+
3
13
  ## 2.1.2
4
14
 
5
15
  - Improves observer API.
data/Gemfile CHANGED
@@ -2,15 +2,17 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
- version = ENV['RAILS_VERSION'] || '3.2'
5
+ version = ENV['RAILS_VERSION'] || '4.1'
6
6
  rails = case version
7
7
  when 'master'
8
8
  { github: 'rails/rails' }
9
9
  when '4.0-protected-attributes'
10
10
  gem 'protected_attributes'
11
+ "~> 4.0.0"
12
+ when /4\.0|4\.1/
11
13
  "~> #{version}.0"
12
- when '4.0'
13
- "~> #{version}.0"
14
+ when /4\.2/
15
+ "~> #{version}.0.beta1"
14
16
  when '3.2'
15
17
  gem 'strong_parameters'
16
18
  "~> #{version}.0"
@@ -22,7 +24,7 @@ case ENV['ORM']
22
24
  when 'active_record'
23
25
  gem 'activerecord'
24
26
  when 'mongoid'
25
- gem 'mongoid', '3.1.0'
27
+ gem 'mongoid'
26
28
  end
27
29
 
28
30
  group :development, :test do
@@ -32,6 +34,7 @@ end
32
34
 
33
35
  platforms :rbx do
34
36
  gem 'rubysl', '~> 2.0'
37
+ gem 'psych'
35
38
  gem 'racc'
36
39
  gem 'minitest'
37
40
  gem 'rubinius-developer_tools'
data/Rakefile CHANGED
@@ -1,27 +1,24 @@
1
1
  # encoding: UTF-8
2
- require 'rubygems'
3
2
  begin
4
3
  require 'bundler/setup'
5
4
  rescue LoadError
6
5
  puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
7
6
  end
8
7
 
9
- require 'rake'
10
-
11
8
  require 'rake/testtask'
12
9
 
10
+ desc 'Default: run tests for all ORMs.'
11
+ task default: :test
12
+
13
13
  Rake::TestTask.new(:test) do |t|
14
14
  t.libs << 'lib'
15
15
  t.libs << 'test'
16
16
  t.pattern = 'test/**/*_test.rb'
17
- t.verbose = false
17
+ t.verbose = true
18
18
  end
19
19
 
20
- task :default => :test
21
-
22
20
  begin
23
21
  require 'rdoc/task'
24
-
25
22
  Rake::RDocTask.new(:rdoc) do |rdoc|
26
23
  rdoc.rdoc_dir = 'rdoc'
27
24
  rdoc.title = 'Merit'
@@ -1,5 +1,19 @@
1
1
  # Main Changes / Upgrading Notes
2
2
 
3
+ ## 2.1.0
4
+
5
+ Adds serialisation of destroyed target models so that reputation can be awarded
6
+ when the item is already deleted from the DB. For this to work you need a new
7
+ column, to add it you can run:
8
+
9
+ ```
10
+ rails generate merit:upgrade
11
+ rake db:migrate
12
+ ```
13
+
14
+ This is a backwards compatible addition, so if you don't add the column but
15
+ upgrade, your application should continue to work well, without the new feature.
16
+
3
17
  ## 2.0.0
4
18
 
5
19
  * Removes deprecated methods: `Merit::Badge.last_granted` and
@@ -36,7 +36,7 @@ module Merit
36
36
 
37
37
  class << self
38
38
  def find_by_name_and_level(name, level)
39
- badges = Badge.by_name(name)
39
+ badges = Merit::Badge.by_name(name)
40
40
  badges = badges.by_level(level) unless level.nil?
41
41
  if (badge = badges.first).nil?
42
42
  str = "No badge '#{name}' found. Define it in initializers/merit.rb"
@@ -0,0 +1,5 @@
1
+ class AddTargetDataToMeritActions < ActiveRecord::Migration
2
+ def change
3
+ add_column :merit_actions, :target_data, :text
4
+ end
5
+ end
@@ -7,6 +7,7 @@ class CreateMeritActions < ActiveRecord::Migration
7
7
  t.boolean :had_errors, default: false
8
8
  t.string :target_model
9
9
  t.integer :target_id
10
+ t.text :target_data
10
11
  t.boolean :processed, default: false
11
12
  t.timestamps
12
13
  end
@@ -0,0 +1,36 @@
1
+ require 'rails/generators/active_record'
2
+
3
+ module ActiveRecord
4
+ module Generators
5
+ class UpgradeGenerator < Rails::Generators::Base
6
+ include Rails::Generators::Migration
7
+
8
+ source_root File.expand_path('../templates', __FILE__)
9
+ desc 'Makes Active Record migrations to handle upgrades between versions'
10
+
11
+ def self.next_migration_number(path)
12
+ ActiveRecord::Generators::Base.next_migration_number(path)
13
+ end
14
+
15
+ def copy_migrations_and_model
16
+ if merit_actions_exists? && target_data_column_doesnt_exist?
17
+ migration_template 'add_target_data_to_merit_actions.rb',
18
+ 'db/migrate/add_target_data_to_merit_actions.rb'
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def target_data_column_doesnt_exist?
25
+ !ActiveRecord::Base.connection.column_exists?(:merit_actions,
26
+ :target_data)
27
+ end
28
+
29
+ # Might be foolishly running this before install. Ugly error if we don't
30
+ # check.
31
+ def merit_actions_exists?
32
+ ActiveRecord::Base.connection.table_exists? :merit_actions
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,7 @@
1
+ module Merit
2
+ module Generators
3
+ class UpgradeGenerator < Rails::Generators::Base
4
+ hook_for :orm
5
+ end
6
+ end
7
+ end
@@ -49,6 +49,11 @@ module Merit
49
49
  @config.add_observer(class_name)
50
50
  end
51
51
 
52
+ def self.upgrade_target_data_warning
53
+ Rails.logger.warn '[merit] Missing column: target_data. Run `rails ' \
54
+ 'generate merit:upgrade` and `rake db:migrate` to add it.'
55
+ end
56
+
52
57
  class Configuration
53
58
  attr_accessor :checks_on_each_request, :orm, :user_model_name, :observers,
54
59
  :current_user_method
@@ -68,8 +73,8 @@ module Merit
68
73
  setup
69
74
  add_observer('Merit::ReputationChangeObserver')
70
75
 
71
- class BadgeNotFound < Exception; end
72
- class RankAttributeNotDefined < Exception; end
76
+ class BadgeNotFound < StandardError; end
77
+ class RankAttributeNotDefined < StandardError; end
73
78
 
74
79
  class Engine < Rails::Engine
75
80
  config.app_generators.orm Merit.orm
@@ -10,11 +10,27 @@ module Merit
10
10
  end
11
11
 
12
12
  def find
13
- klass_name = (@rule.model_name || @action.target_model).singularize
14
- klass = klass_name.camelize.constantize
15
- klass.find_by_id @action.target_id
13
+ get_target_from_database || reanimate_target_from_action
16
14
  rescue => e
17
15
  Rails.logger.warn "[merit] no target found: #{e}. #{caller.first}"
18
16
  end
17
+
18
+ def get_target_from_database
19
+ model_class.find_by_id(@action.target_id)
20
+ end
21
+
22
+ def model_class
23
+ klass_name = (@rule.model_name || @action.target_model).singularize
24
+ klass_name.camelize.constantize
25
+ end
26
+
27
+ def reanimate_target_from_action
28
+ if @action.respond_to? :target_data
29
+ YAML.load(@action.target_data)
30
+ else
31
+ Merit.upgrade_target_data_warning
32
+ nil
33
+ end
34
+ end
19
35
  end
20
36
  end
@@ -15,14 +15,27 @@ module Merit
15
15
  private
16
16
 
17
17
  def log_merit_action
18
- Merit::Action.create(
18
+ Merit::Action.create(merit_action_hash)
19
+ end
20
+
21
+ def merit_action_hash
22
+ {
19
23
  user_id: send(Merit.current_user_method).try(:id),
20
24
  action_method: action_name,
21
25
  action_value: params[:value],
22
26
  had_errors: had_errors?,
23
27
  target_model: controller_path,
24
- target_id: target_id
25
- ).id
28
+ target_id: target_id,
29
+ }.merge(target_data_hash)
30
+ end
31
+
32
+ def target_data_hash
33
+ if Merit::Action.new.respond_to? :target_data
34
+ { target_data: target_object.to_yaml }
35
+ else
36
+ Merit.upgrade_target_data_warning
37
+ {}
38
+ end
26
39
  end
27
40
 
28
41
  def rules_defined?
@@ -35,7 +35,7 @@ module Merit
35
35
 
36
36
  def _merit_define_badge_related_entries_method
37
37
  meritable_class_name = name.demodulize
38
- Badge._define_related_entries_method(meritable_class_name)
38
+ Merit::Badge._define_related_entries_method(meritable_class_name)
39
39
  end
40
40
 
41
41
  def show_attr_accessible?
@@ -6,7 +6,7 @@ module Merit
6
6
 
7
7
  if show_attr_accessible?
8
8
  attr_accessible :user_id, :action_method, :action_value, :had_errors,
9
- :target_model, :target_id, :processed, :log
9
+ :target_model, :target_id, :processed, :log, :target_data
10
10
  end
11
11
  end
12
12
  end
@@ -8,7 +8,7 @@ module Merit
8
8
  end
9
9
 
10
10
  def badge
11
- Badge.find(badge_id)
11
+ Merit::Badge.find(badge_id)
12
12
  end
13
13
  end
14
14
  end
@@ -11,6 +11,7 @@ module Merit
11
11
  field :had_errors, type: Boolean
12
12
  field :target_model
13
13
  field :target_id
14
+ field :target_data
14
15
  field :processed, type: Boolean, default: false
15
16
  field :log
16
17
  end
@@ -25,7 +25,7 @@ module Merit
25
25
 
26
26
  # Get rule's related Badge.
27
27
  def badge
28
- @badge ||= Badge.find_by_name_and_level(badge_name, level)
28
+ @badge ||= Merit::Badge.find_by_name_and_level(badge_name, level)
29
29
  end
30
30
  end
31
31
  end
@@ -48,11 +48,20 @@ module Merit
48
48
  next unless rule.applies?(object)
49
49
  object.update_attribute rule.level_name, level
50
50
  end
51
- rescue ActiveRecord::StatementInvalid
52
- str = "Add #{rule.level_name} column to #{scoped_model.class.name}"
51
+ rescue rank_exception
52
+ str = "Error while granting rankings. Probably you need to add
53
+ #{rule.level_name} column to #{scoped_model.class.name}."
53
54
  raise RankAttributeNotDefined, str
54
55
  end
55
56
 
57
+ def rank_exception
58
+ if defined? ActiveRecord
59
+ ActiveRecord::StatementInvalid
60
+ else
61
+ Exception
62
+ end
63
+ end
64
+
56
65
  def scope_to_promote(scope, level_name, level)
57
66
  if Merit.orm == :mongoid
58
67
  scope.where(:"#{level_name}".lt => level)
@@ -2,6 +2,10 @@ module Merit
2
2
  class SashFinder
3
3
  def self.find(rule, action)
4
4
  targets(rule, action).map(&:_sash)
5
+ rescue NoMethodError
6
+ Rails.logger.warn "[merit] Couldn't find model to grant reputation to. " \
7
+ "Refer to https://github.com/tute/merit/issues/171#issuecomment-44185696."
8
+ []
5
9
  end
6
10
 
7
11
  def self.targets(rule, action)
@@ -35,9 +35,8 @@ module Merit
35
35
  def other_target
36
36
  base_target.send rule.to
37
37
  rescue NoMethodError
38
- str = '[merit] NoMethodError on'
39
- str << " `#{base_target.class.name}##{rule.to}`"
40
- str << ' (called from Merit::TargetFinder#other_target)'
38
+ str = "[merit] NoMethodError on `#{base_target.class.name}##{rule.to}`" \
39
+ ' (called from Merit::TargetFinder#other_target)'
41
40
  Rails.logger.warn str
42
41
  end
43
42
  end
@@ -5,7 +5,7 @@ Gem::Specification.new do |s|
5
5
  s.homepage = "http://github.com/tute/merit"
6
6
  s.files = `git ls-files`.split("\n").reject{|f| f =~ /^\./ }
7
7
  s.license = 'MIT'
8
- s.version = '2.1.2'
8
+ s.version = '2.2.0'
9
9
  s.authors = ["Tute Costa"]
10
10
  s.email = 'tutecosta@gmail.com'
11
11
 
@@ -13,10 +13,9 @@ Gem::Specification.new do |s|
13
13
 
14
14
  s.add_dependency 'ambry', '~> 0.3.0'
15
15
  s.add_development_dependency 'rails', '>= 3.2.0'
16
- s.add_development_dependency 'jquery-rails', '~> 2.1'
17
16
  s.add_development_dependency 'capybara'
18
17
  s.add_development_dependency 'simplecov'
19
18
  s.add_development_dependency 'rubocop'
20
19
  s.add_development_dependency 'minitest-rails'
21
- s.add_development_dependency 'mocha', '0.14'
20
+ s.add_development_dependency 'mocha', '1.1.0'
22
21
  end
@@ -35,6 +35,10 @@ module Merit
35
35
  score lambda { |comment| comment.comment.to_i }, to: :user, on: 'comments#create' do |object|
36
36
  object.comment.to_i > 0
37
37
  end
38
+
39
+ score -5, to: :user, on: 'comments#destroy' do |comment|
40
+ comment.present?
41
+ end
38
42
  end
39
43
  end
40
44
  end
@@ -26,7 +26,7 @@ class User
26
26
  end
27
27
 
28
28
  def show_badges
29
- badges_uniq = Badge.find_by_id(badge_ids)
29
+ badges_uniq = Merit::Badge.find_by_id(badge_ids)
30
30
  badges_uniq.collect{|b| "#{b.name.capitalize}#{badge_status(b)}" }.join(', ')
31
31
  end
32
32
 
@@ -3,7 +3,6 @@
3
3
  <head>
4
4
  <meta charset="utf-8" />
5
5
  <title>Merit Dummy app</title>
6
- <%= stylesheet_link_tag :all %>
7
6
  <script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
8
7
  <script src="/rails.js"></script>
9
8
  <%= csrf_meta_tag %>
@@ -0,0 +1,5 @@
1
+ class AddTargetDataToMeritActions < ActiveRecord::Migration
2
+ def change
3
+ add_column :merit_actions, :target_data, :text
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ class CreatePlayers < ActiveRecord::Migration
2
+ def change
3
+ create_table :players do |t|
4
+ t.integer :sash_id
5
+ t.integer :level, default: 0
6
+ end
7
+ end
8
+ end
@@ -9,49 +9,50 @@
9
9
  # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10
10
  # you'll amass, the slower it'll run and the greater likelihood for issues).
11
11
  #
12
- # It's strongly recommended to check this file into your version control system.
12
+ # It's strongly recommended that you check this file into your version control system.
13
13
 
14
- ActiveRecord::Schema.define(:version => 20140211144001) do
14
+ ActiveRecord::Schema.define(version: 20140906225844) do
15
15
 
16
- create_table "addresses", :force => true do |t|
16
+ create_table "addresses", force: true do |t|
17
17
  t.integer "user_id"
18
18
  end
19
19
 
20
- create_table "badges_sashes", :force => true do |t|
20
+ create_table "badges_sashes", force: true do |t|
21
21
  t.integer "badge_id"
22
22
  t.integer "sash_id"
23
- t.boolean "notified_user", :default => false
23
+ t.boolean "notified_user", default: false
24
24
  t.datetime "created_at"
25
25
  end
26
26
 
27
- add_index "badges_sashes", ["badge_id", "sash_id"], :name => "index_badges_sashes_on_badge_id_and_sash_id"
28
- add_index "badges_sashes", ["badge_id"], :name => "index_badges_sashes_on_badge_id"
29
- add_index "badges_sashes", ["sash_id"], :name => "index_badges_sashes_on_sash_id"
27
+ add_index "badges_sashes", ["badge_id", "sash_id"], name: "index_badges_sashes_on_badge_id_and_sash_id"
28
+ add_index "badges_sashes", ["badge_id"], name: "index_badges_sashes_on_badge_id"
29
+ add_index "badges_sashes", ["sash_id"], name: "index_badges_sashes_on_sash_id"
30
30
 
31
- create_table "comments", :force => true do |t|
31
+ create_table "comments", force: true do |t|
32
32
  t.string "name"
33
33
  t.text "comment"
34
34
  t.integer "user_id"
35
- t.integer "votes", :default => 0
36
- t.datetime "created_at", :null => false
37
- t.datetime "updated_at", :null => false
35
+ t.integer "votes", default: 0
36
+ t.datetime "created_at", null: false
37
+ t.datetime "updated_at", null: false
38
38
  t.integer "sash_id"
39
- t.integer "level", :default => 0
39
+ t.integer "level", default: 0
40
40
  end
41
41
 
42
- create_table "merit_actions", :force => true do |t|
42
+ create_table "merit_actions", force: true do |t|
43
43
  t.integer "user_id"
44
44
  t.string "action_method"
45
45
  t.integer "action_value"
46
- t.boolean "had_errors", :default => false
46
+ t.boolean "had_errors", default: false
47
47
  t.string "target_model"
48
48
  t.integer "target_id"
49
- t.boolean "processed", :default => false
50
- t.datetime "created_at", :null => false
51
- t.datetime "updated_at", :null => false
49
+ t.boolean "processed", default: false
50
+ t.datetime "created_at", null: false
51
+ t.datetime "updated_at", null: false
52
+ t.text "target_data"
52
53
  end
53
54
 
54
- create_table "merit_activity_logs", :force => true do |t|
55
+ create_table "merit_activity_logs", force: true do |t|
55
56
  t.integer "action_id"
56
57
  t.string "related_change_type"
57
58
  t.integer "related_change_id"
@@ -59,29 +60,34 @@ ActiveRecord::Schema.define(:version => 20140211144001) do
59
60
  t.datetime "created_at"
60
61
  end
61
62
 
62
- create_table "merit_score_points", :force => true do |t|
63
+ create_table "merit_score_points", force: true do |t|
63
64
  t.integer "score_id"
64
- t.integer "num_points", :default => 0
65
+ t.integer "num_points", default: 0
65
66
  t.string "log"
66
67
  t.datetime "created_at"
67
68
  end
68
69
 
69
- create_table "merit_scores", :force => true do |t|
70
+ create_table "merit_scores", force: true do |t|
70
71
  t.integer "sash_id"
71
- t.string "category", :default => "default"
72
+ t.string "category", default: "default"
72
73
  end
73
74
 
74
- create_table "sashes", :force => true do |t|
75
- t.datetime "created_at", :null => false
76
- t.datetime "updated_at", :null => false
75
+ create_table "players", force: true do |t|
76
+ t.integer "sash_id"
77
+ t.integer "level", default: 0
78
+ end
79
+
80
+ create_table "sashes", force: true do |t|
81
+ t.datetime "created_at", null: false
82
+ t.datetime "updated_at", null: false
77
83
  end
78
84
 
79
- create_table "users", :force => true do |t|
85
+ create_table "users", force: true do |t|
80
86
  t.string "name"
81
- t.datetime "created_at", :null => false
82
- t.datetime "updated_at", :null => false
87
+ t.datetime "created_at", null: false
88
+ t.datetime "updated_at", null: false
83
89
  t.integer "sash_id"
84
- t.integer "level", :default => 0
90
+ t.integer "level", default: 0
85
91
  end
86
92
 
87
93
  end
@@ -1,16 +1,16 @@
1
1
  require 'test_helper'
2
2
 
3
- class NavigationTest < ActiveSupport::IntegrationCase
4
- def tear_down
3
+ class NavigationTest < ActionDispatch::IntegrationTest
4
+ def teardown
5
5
  DummyObserver.unstub(:update)
6
6
  end
7
7
 
8
8
  test 'user sign up should grant badge to itself' do
9
9
  DummyObserver.any_instance.expects(:update).times(1).with do |hash|
10
- hash[:description] == 'granted just-registered badge' &&
11
- hash[:sash_id] == user('Jack').sash_id &&
12
- hash[:granted_at].to_date == Date.today
13
- end
10
+ hash[:description] == 'granted just-registered badge' &&
11
+ hash[:sash_id] == user('Jack').sash_id &&
12
+ hash[:granted_at].to_date == Time.now.utc.to_date
13
+ end
14
14
 
15
15
  visit '/users/new'
16
16
  fill_in 'Name', with: 'Jack'
@@ -48,18 +48,16 @@ class NavigationTest < ActiveSupport::IntegrationCase
48
48
 
49
49
  test 'users#index should grant badge multiple times' do
50
50
  DummyObserver.any_instance.expects(:update).times(1).with do |hash|
51
- hash[:description] == 'granted visited_admin badge' &&
52
- hash[:sash_id] == user.sash_id
53
- end
51
+ hash[:description] == 'granted visited_admin badge' &&
52
+ hash[:sash_id] == user.sash_id
53
+ end
54
54
  DummyObserver.any_instance.expects(:update).times(5).with do |hash|
55
- hash[:description] == 'granted gossip badge' &&
56
- hash[:sash_id] == user.sash_id
57
- end
58
- 8.times do |merit_action_id|
59
- DummyObserver.any_instance.expects(:update).times(1).with do |hash|
60
- hash[:description] == 'granted wildcard_badge badge' &&
61
- hash[:sash_id] == user.sash_id
62
- end
55
+ hash[:description] == 'granted gossip badge' &&
56
+ hash[:sash_id] == user.sash_id
57
+ end
58
+ DummyObserver.any_instance.expects(:update).times(8).with do |hash|
59
+ hash[:description] == 'granted wildcard_badge badge' &&
60
+ hash[:sash_id] == user.sash_id
63
61
  end
64
62
 
65
63
  # Multiple rule
@@ -221,6 +219,15 @@ class NavigationTest < ActiveSupport::IntegrationCase
221
219
  user = User.where(name: 'a').first
222
220
  assert_equal 51, user.points, 'Commenting should grant the integer in
223
221
  comment points if comment is an integer'
222
+
223
+ # Destroying a comment should remove points from the comment creator.
224
+ comment_to_destroy = user.comments.last
225
+ visit '/comments'
226
+ assert_difference lambda { user.reload.points }, -5 do
227
+ within("tr#c_#{comment_to_destroy.id}") do
228
+ click_link 'Destroy'
229
+ end
230
+ end
224
231
  end
225
232
 
226
233
  test 'user workflow should grant levels at some times' do
@@ -262,21 +269,21 @@ class NavigationTest < ActiveSupport::IntegrationCase
262
269
 
263
270
  test 'assigning points to a group of records' do
264
271
  DummyObserver.any_instance.expects(:update).times(2).with do |hash|
265
- hash[:description] == 'granted 1 points' &&
266
- hash[:sash_id] == user('commenter').sash_id
267
- end
272
+ hash[:description] == 'granted 1 points' &&
273
+ hash[:sash_id] == user('commenter').sash_id
274
+ end
268
275
  DummyObserver.any_instance.expects(:update).times(1).with do |hash|
269
- hash[:description] == 'granted 2 points' &&
270
- hash[:sash_id] == user('commenter').comments.first.sash_id
271
- end
276
+ hash[:description] == 'granted 2 points' &&
277
+ hash[:sash_id] == user('commenter').comments.first.sash_id
278
+ end
272
279
  DummyObserver.any_instance.expects(:update).times(1).with do |hash|
273
- hash[:description] == 'granted 2 points' &&
274
- hash[:sash_id] == user('commenter').comments.last.sash_id
275
- end
280
+ hash[:description] == 'granted 2 points' &&
281
+ hash[:sash_id] == user('commenter').comments.last.sash_id
282
+ end
276
283
  DummyObserver.any_instance.expects(:update).times(1).with do |hash|
277
- hash[:description] == 'granted 5 points' &&
278
- hash[:sash_id] == user('commenter').sash_id
279
- end
284
+ hash[:description] == 'granted 5 points' &&
285
+ hash[:sash_id] == user('commenter').sash_id
286
+ end
280
287
 
281
288
  comment_1 = user('commenter').comments.create(name: 'a', comment: 'a')
282
289
  comment_2 = user('commenter').comments.create(name: 'b', comment: 'b')
@@ -296,9 +303,9 @@ class NavigationTest < ActiveSupport::IntegrationCase
296
303
 
297
304
  test 'api/comments#show should grant 1 point to user' do
298
305
  DummyObserver.any_instance.expects(:update).times(1).with do |hash|
299
- hash[:description] == 'granted 1 points' &&
300
- hash[:sash_id] == user.sash_id
301
- end
306
+ hash[:description] == 'granted 1 points' &&
307
+ hash[:sash_id] == user.sash_id
308
+ end
302
309
 
303
310
  assert_equal 0, user.points
304
311
  comment = user.comments.create!(name: 'test-comment', comment: 'comment body')
@@ -1,9 +1,5 @@
1
1
  require 'test_helper'
2
2
 
3
- class User < ActiveRecord::Base
4
- has_merit
5
- end
6
-
7
3
  class Fruit < ActiveRecord::Base
8
4
  end
9
5
 
@@ -1,10 +1,5 @@
1
1
  require 'test_helper'
2
2
 
3
- class User
4
- include Mongoid::Document
5
- has_merit
6
- end
7
-
8
3
  class Fruit
9
4
  include Mongoid::Document
10
5
  end
@@ -1,5 +1,5 @@
1
1
  # Define a bare test case to use with Capybara
2
- class ActiveSupport::IntegrationCase < ActiveSupport::TestCase
2
+ class ActionDispatch::IntegrationTest < ActiveSupport::TestCase
3
3
  include Capybara::DSL
4
4
  include Rails.application.routes.url_helpers
5
5
  end
@@ -2,11 +2,12 @@
2
2
  ENV['RAILS_ENV'] = 'test'
3
3
  RUBYOPT="-w $RUBYOPT"
4
4
 
5
- require 'coveralls'
6
- Coveralls.wear!('rails')
7
-
8
5
  if ENV["COVERAGE"]
6
+ require 'coveralls'
9
7
  require 'simplecov'
8
+
9
+ Coveralls.wear!('rails')
10
+
10
11
  SimpleCov.adapters.define 'rubygem' do
11
12
  # Add app to Merit group
12
13
  # https://github.com/colszowka/simplecov/pull/104
@@ -17,10 +18,10 @@ if ENV["COVERAGE"]
17
18
  SimpleCov.start 'rubygem'
18
19
  end
19
20
 
20
-
21
21
  require File.expand_path('../dummy/config/environment.rb', __FILE__)
22
22
  require 'rails/test_help'
23
23
  require 'minitest/rails'
24
+ require "orm/#{Merit.orm}"
24
25
 
25
26
  Rails.backtrace_cleaner.remove_silencers!
26
27
 
@@ -29,17 +30,11 @@ require 'capybara/rails'
29
30
  Capybara.default_driver = :rack_test
30
31
  Capybara.default_selector = :css
31
32
 
33
+ # Load support files
34
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
35
+
32
36
  Merit.orm = :active_record if Merit.orm.nil?
33
37
 
34
38
  def active_record_orm?
35
39
  Merit.orm == :active_record
36
40
  end
37
-
38
- def mongoid_orm?
39
- Merit.orm == :mongoid
40
- end
41
-
42
- require "orm/#{Merit.orm}"
43
-
44
- # Load support files
45
- Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
@@ -0,0 +1,12 @@
1
+ require 'test_helper'
2
+
3
+ describe Merit::Action do
4
+ it 'saves correctly with a serialised model' do
5
+ comment = Comment.new(name: 'the comment name')
6
+ action = Merit::Action.create(target_model: 'comment',
7
+ target_id: 2,
8
+ target_data: comment.to_yaml)
9
+ comment_yaml = Merit::Action.find(action.id).target_data
10
+ assert_equal comment.name, YAML::load(comment_yaml).name
11
+ end
12
+ end
@@ -22,17 +22,17 @@ describe Merit::BaseTargetFinder do
22
22
  it 'should fall back to the action#target_model' do
23
23
  rule = Merit::Rule.new
24
24
  rule.to = :itself
25
- action = Merit::Action.new(target_model: 'users', target_id: 3)
26
- user = Comment.new(id: 3)
25
+ action = Merit::Action.new(target_model: 'players', target_id: 3)
26
+ user = Player.new(id: 3)
27
27
 
28
- User.stubs(:find_by_id).with(3).returns(user)
28
+ Player.stubs(:find_by_id).with(3).returns(user)
29
29
 
30
30
  finder = Merit::BaseTargetFinder.new(rule, action)
31
31
  finder.find.must_be :==, user
32
32
  end
33
33
  end
34
34
 
35
- describe 'when the targetted class is not meritable' do
35
+ describe 'when the targeted class is not meritable' do
36
36
  it 'should warn and return' do
37
37
  rule = Merit::Rule.new
38
38
  rule.to = :itself
@@ -44,5 +44,40 @@ describe Merit::BaseTargetFinder do
44
44
  finder.find.must_be_nil
45
45
  end
46
46
  end
47
+
48
+ describe 'target was destroyed' do
49
+ it 'gets the object from the JSON data in the merit_actions table' do
50
+ comment = Comment.new(name: 'the comment name')
51
+
52
+ rule = Merit::Rule.new
53
+ rule.to = :itself
54
+ rule.model_name = 'comment'
55
+ action = Merit::Action.new(target_model: 'comment',
56
+ target_id: 2,
57
+ target_data: comment.to_yaml)
58
+
59
+ finder = Merit::BaseTargetFinder.new(rule, action)
60
+ finder.find.name.must_be :==, 'the comment name'
61
+ end
62
+ end
63
+
64
+ describe 'warns when the target_data column has not been created' do
65
+ it 'sends a message to the logger' do
66
+ comment = Comment.new(name: 'the comment name')
67
+
68
+ rule = Merit::Rule.new
69
+ rule.to = :itself
70
+ rule.model_name = 'comment'
71
+ action = Merit::Action.new(target_model: 'comment',
72
+ target_id: 2,
73
+ target_data: comment.to_yaml)
74
+ action.stubs(:respond_to?).with(:target_data).returns(false)
75
+
76
+ Rails.logger.expects(:warn)
77
+
78
+ finder = Merit::BaseTargetFinder.new(rule, action)
79
+ finder.reanimate_target_from_action
80
+ end
81
+ end
47
82
  end
48
83
  end
@@ -5,7 +5,7 @@ class MeritUnitTest < ActiveSupport::TestCase
5
5
  require "orm_models/#{Merit.orm}"
6
6
 
7
7
  test 'extends only meritable models' do
8
- assert User.method_defined?(:points), 'has_merit adds methods'
8
+ assert Player.method_defined?(:points), 'has_merit adds methods'
9
9
  assert !Fruit.method_defined?(:points), 'other models aren\'t extended'
10
10
  end
11
11
 
@@ -14,17 +14,19 @@ class MeritUnitTest < ActiveSupport::TestCase
14
14
  assert Merit::Badge.method_defined?(:players), 'Badge#players should be defined'
15
15
  end
16
16
 
17
- test 'unknown ranking raises exception' do
18
- class WeirdRankRules
19
- include Merit::RankRulesMethods
20
- def initialize
21
- set_rank level: 1, to: User, level_name: :clown
17
+ if active_record_orm?
18
+ test 'unknown ranking raises exception' do
19
+ class WeirdRankRules
20
+ include Merit::RankRulesMethods
21
+ def initialize
22
+ set_rank level: 1, to: Player, level_name: :clown
23
+ end
24
+ end
25
+ assert_raises Merit::RankAttributeNotDefined do
26
+ WeirdRankRules.new.check_rank_rules
22
27
  end
23
28
  end
24
- assert_raises Merit::RankAttributeNotDefined do
25
- WeirdRankRules.new.check_rank_rules
26
- end
27
- end if active_record_orm?
29
+ end
28
30
 
29
31
  test 'Badge#custom_fields_hash saves correctly' do
30
32
  Merit::Badge.create(id: 99,
@@ -3,11 +3,11 @@ require 'test_helper'
3
3
  describe Merit::SashFinder do
4
4
  it 'should return an array of sashes of the target objects' do
5
5
  sash_1 = Merit::Sash.new
6
- user_1 = User.new
6
+ user_1 = Player.new
7
7
  user_1.stubs(:_sash).returns(sash_1)
8
8
 
9
9
  sash_2 = Merit::Sash.new
10
- user_2 = User.new
10
+ user_2 = Player.new
11
11
  user_2.stubs(:_sash).returns(sash_2)
12
12
 
13
13
  # TODO: With stub we are not exercising compact
@@ -2,11 +2,11 @@ require 'test_helper'
2
2
 
3
3
  describe Merit::Score do
4
4
  it 'Point#sash_id delegates to Score' do
5
- score = mock()
6
- score.stubs(:sash_id).returns(33)
5
+ score = Merit::Score.new
6
+ score.sash_id = 33
7
7
 
8
8
  point = Merit::Score::Point.new
9
- point.stubs(:score).returns(score)
9
+ point.score = score
10
10
 
11
11
  point.sash_id.must_be :==, score.sash_id
12
12
  end
@@ -23,16 +23,20 @@ describe Merit::TargetFinder do
23
23
  end
24
24
 
25
25
  describe 'rule#to is :action_user' do
26
+ before do
27
+ Merit.setup { |config| config.user_model_name = 'Player' }
28
+ end
29
+ after do
30
+ Merit.setup { |config| config.user_model_name = 'User' }
31
+ end
32
+
26
33
  it 'should return an array including user that executed the action' do
27
- Merit.setup do |config|
28
- config.user_model_name = 'User'
29
- end
30
34
  rule = Merit::Rule.new
31
35
  rule.to = :action_user
32
36
  action = Merit::Action.new(user_id: 22)
33
- user = User.new
37
+ user = Player.new
34
38
 
35
- User.stubs(:find_by_id).with(22).returns(user)
39
+ Player.stubs(:find_by_id).with(22).returns(user)
36
40
 
37
41
  finder = Merit::TargetFinder.new(rule, action)
38
42
  collection = finder.find
@@ -42,14 +46,11 @@ describe Merit::TargetFinder do
42
46
 
43
47
  describe 'when user does not exist' do
44
48
  it 'should return warn and return an empty array' do
45
- Merit.setup do |config|
46
- config.user_model_name = 'User'
47
- end
48
49
  rule = Merit::Rule.new
49
50
  rule.to = :action_user
50
51
  action = Merit::Action.new(user_id: 22)
51
52
 
52
- Rails.logger.expects(:warn).with('[merit] no User found with id 22')
53
+ Rails.logger.expects(:warn).with('[merit] no Player found with id 22')
53
54
  finder = Merit::TargetFinder.new(rule, action)
54
55
  finder.find.must_be_empty
55
56
  end
@@ -63,7 +64,7 @@ describe Merit::TargetFinder do
63
64
  rule.model_name = 'comments'
64
65
  action = Merit::Action.new(target_id: 40)
65
66
 
66
- user = User.new
67
+ user = Player.new
67
68
  comment = Comment.new
68
69
  comment.stubs(:user).returns(user)
69
70
  Comment.stubs(:find_by_id).with(40).returns(comment)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: merit
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.2
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tute Costa
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-06 00:00:00.000000000 Z
11
+ date: 2014-09-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ambry
@@ -38,20 +38,6 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: 3.2.0
41
- - !ruby/object:Gem::Dependency
42
- name: jquery-rails
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '2.1'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '2.1'
55
41
  - !ruby/object:Gem::Dependency
56
42
  name: capybara
57
43
  requirement: !ruby/object:Gem::Requirement
@@ -114,14 +100,14 @@ dependencies:
114
100
  requirements:
115
101
  - - '='
116
102
  - !ruby/object:Gem::Version
117
- version: '0.14'
103
+ version: 1.1.0
118
104
  type: :development
119
105
  prerelease: false
120
106
  version_requirements: !ruby/object:Gem::Requirement
121
107
  requirements:
122
108
  - - '='
123
109
  - !ruby/object:Gem::Version
124
- version: '0.14'
110
+ version: 1.1.0
125
111
  description: Manage badges, points and rankings (reputation) of resources in a Rails
126
112
  application.
127
113
  email: tutecosta@gmail.com
@@ -142,6 +128,7 @@ files:
142
128
  - lib/generators/active_record/merit_generator.rb
143
129
  - lib/generators/active_record/remove_generator.rb
144
130
  - lib/generators/active_record/templates/add_fields_to_model.rb
131
+ - lib/generators/active_record/templates/add_target_data_to_merit_actions.rb
145
132
  - lib/generators/active_record/templates/create_badges_sashes.rb
146
133
  - lib/generators/active_record/templates/create_merit_actions.rb
147
134
  - lib/generators/active_record/templates/create_merit_activity_logs.rb
@@ -149,6 +136,7 @@ files:
149
136
  - lib/generators/active_record/templates/create_scores_and_points.rb
150
137
  - lib/generators/active_record/templates/remove_fields_from_model.rb
151
138
  - lib/generators/active_record/templates/remove_merit_tables.rb
139
+ - lib/generators/active_record/upgrade_generator.rb
152
140
  - lib/generators/merit/install_generator.rb
153
141
  - lib/generators/merit/merit_generator.rb
154
142
  - lib/generators/merit/remove_generator.rb
@@ -156,6 +144,7 @@ files:
156
144
  - lib/generators/merit/templates/merit_badge_rules.rb
157
145
  - lib/generators/merit/templates/merit_point_rules.rb
158
146
  - lib/generators/merit/templates/merit_rank_rules.rb
147
+ - lib/generators/merit/upgrade_generator.rb
159
148
  - lib/merit.rb
160
149
  - lib/merit/base_target_finder.rb
161
150
  - lib/merit/controller_extensions.rb
@@ -237,6 +226,8 @@ files:
237
226
  - test/dummy/db/migrate/20130329224409_create_badges_sashes.rb
238
227
  - test/dummy/db/migrate/20130329224410_create_scores_and_points.rb
239
228
  - test/dummy/db/migrate/20140211144001_create_addresses.rb
229
+ - test/dummy/db/migrate/20140819133931_add_target_data_to_merit_actions.rb
230
+ - test/dummy/db/migrate/20140906225844_create_players.rb
240
231
  - test/dummy/db/schema.rb
241
232
  - test/dummy/db/seeds.rb
242
233
  - test/dummy/public/404.html
@@ -260,6 +251,7 @@ files:
260
251
  - test/orm_models/mongoid.rb
261
252
  - test/support/integration_case.rb
262
253
  - test/test_helper.rb
254
+ - test/unit/action_test.rb
263
255
  - test/unit/base_target_finder_test.rb
264
256
  - test/unit/merit_unit_test.rb
265
257
  - test/unit/rule_unit_test.rb
@@ -288,9 +280,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
288
280
  version: '0'
289
281
  requirements: []
290
282
  rubyforge_project:
291
- rubygems_version: 2.2.2
283
+ rubygems_version: 2.4.1
292
284
  signing_key:
293
285
  specification_version: 4
294
286
  summary: General reputation Rails engine.
295
287
  test_files: []
296
- has_rdoc: