merit 2.1.2 → 2.2.0

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