merit 3.0.3 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -9
  3. data/NEWS.md +7 -0
  4. data/README.md +14 -2
  5. data/app/models/merit/badge.rb +1 -9
  6. data/lib/merit.rb +6 -36
  7. data/lib/merit/{rules_badge_methods.rb → badge_rules_methods.rb} +0 -0
  8. data/lib/merit/base_target_finder.rb +1 -6
  9. data/lib/merit/{model_additions.rb → class_methods.rb} +0 -11
  10. data/lib/merit/controller_extensions.rb +4 -22
  11. data/lib/{generators → merit/generators}/active_record/install_generator.rb +8 -8
  12. data/lib/{generators → merit/generators}/active_record/merit_generator.rb +3 -3
  13. data/lib/{generators → merit/generators}/active_record/remove_generator.rb +5 -5
  14. data/lib/{generators/active_record/templates/add_merit_fields_to_model.rb → merit/generators/active_record/templates/add_merit_fields_to_model.erb} +0 -0
  15. data/lib/{generators/active_record/templates/create_badges_sashes.rb → merit/generators/active_record/templates/create_badges_sashes.erb} +0 -0
  16. data/lib/{generators/active_record/templates/create_merit_actions.rb → merit/generators/active_record/templates/create_merit_actions.erb} +0 -0
  17. data/lib/{generators/active_record/templates/create_merit_activity_logs.rb → merit/generators/active_record/templates/create_merit_activity_logs.erb} +0 -0
  18. data/lib/{generators/active_record/templates/create_sashes.rb → merit/generators/active_record/templates/create_sashes.erb} +0 -0
  19. data/lib/{generators/active_record/templates/create_scores_and_points.rb → merit/generators/active_record/templates/create_scores_and_points.erb} +1 -1
  20. data/lib/{generators/active_record/templates/remove_merit_fields_from_model.rb → merit/generators/active_record/templates/remove_merit_fields_from_model.erb} +0 -0
  21. data/lib/{generators/active_record/templates/remove_merit_tables.rb → merit/generators/active_record/templates/remove_merit_tables.erb} +0 -0
  22. data/lib/merit/generators/install_generator.rb +18 -0
  23. data/lib/{generators/merit → merit/generators}/merit_generator.rb +3 -1
  24. data/lib/{generators/merit → merit/generators}/remove_generator.rb +3 -1
  25. data/lib/{generators/merit/templates/merit.rb → merit/generators/templates/merit.erb} +0 -3
  26. data/lib/{generators/merit/templates/merit_badge_rules.rb → merit/generators/templates/merit_badge_rules.erb} +0 -0
  27. data/lib/{generators/merit/templates/merit_point_rules.rb → merit/generators/templates/merit_point_rules.erb} +0 -0
  28. data/lib/{generators/merit/templates/merit_rank_rules.rb → merit/generators/templates/merit_rank_rules.erb} +0 -0
  29. data/{app/models/merit/action.rb → lib/merit/models/action_concern.rb} +12 -10
  30. data/lib/merit/models/active_record/{merit/action.rb → action.rb} +5 -1
  31. data/lib/merit/models/active_record/{merit/activity_log.rb → activity_log.rb} +3 -1
  32. data/lib/merit/models/active_record/{merit/badges_sash.rb → badges_sash.rb} +4 -2
  33. data/lib/merit/models/active_record/{merit/sash.rb → sash.rb} +5 -2
  34. data/lib/merit/models/active_record/{merit/score.rb → score.rb} +4 -1
  35. data/lib/merit/models/badges_sash_concern.rb +13 -0
  36. data/lib/merit/models/base/badges_sash.rb +1 -1
  37. data/lib/merit/models/base/sash.rb +1 -1
  38. data/lib/merit/models/sash_concern.rb +53 -0
  39. data/lib/merit/{rules_points_methods.rb → point_rules_methods.rb} +0 -0
  40. data/lib/merit/{rules_rank_methods.rb → rank_rules_methods.rb} +3 -18
  41. data/merit.gemspec +4 -2
  42. data/test/dummy/app/models/address.rb +1 -12
  43. data/test/dummy/app/models/comment.rb +3 -21
  44. data/test/dummy/app/models/user.rb +1 -14
  45. data/test/dummy/config/application.rb +5 -1
  46. data/test/dummy/config/application_api_only.rb +1 -1
  47. data/test/dummy/db/schema.rb +1 -6
  48. data/test/integration/navigation_test.rb +2 -2
  49. data/test/test_helper.rb +0 -2
  50. data/test/unit/base_target_finder_test.rb +7 -26
  51. data/test/unit/merit_unit_test.rb +6 -8
  52. data/test/unit/rule_unit_test.rb +8 -8
  53. data/test/unit/rules_matcher_test.rb +9 -6
  54. data/test/unit/sash_finder_test.rb +5 -5
  55. data/test/unit/score_test.rb +1 -1
  56. data/test/unit/target_finder_test.rb +13 -13
  57. metadata +47 -59
  58. data/UPGRADING.md +0 -256
  59. data/lib/generators/active_record/templates/add_target_data_to_merit_actions.rb +0 -5
  60. data/lib/generators/active_record/upgrade_generator.rb +0 -40
  61. data/lib/generators/merit/install_generator.rb +0 -16
  62. data/lib/generators/merit/upgrade_generator.rb +0 -7
  63. data/lib/merit/models/mongoid/merit/action.rb +0 -18
  64. data/lib/merit/models/mongoid/merit/activity_log.rb +0 -11
  65. data/lib/merit/models/mongoid/merit/badges_sash.rb +0 -20
  66. data/lib/merit/models/mongoid/merit/sash.rb +0 -30
  67. data/lib/merit/models/mongoid/merit/score.rb +0 -45
  68. data/test/dummy/db/migrate/20140906225844_create_players.rb +0 -8
  69. data/test/dummy/public/javascripts/application.js +0 -2
  70. data/test/dummy/public/javascripts/controls.js +0 -965
  71. data/test/dummy/public/javascripts/dragdrop.js +0 -974
  72. data/test/dummy/public/javascripts/effects.js +0 -1123
  73. data/test/dummy/public/javascripts/prototype.js +0 -6001
  74. data/test/dummy/public/javascripts/rails.js +0 -191
  75. data/test/orm_models/active_record.rb +0 -11
  76. data/test/orm_models/mongoid.rb +0 -15
@@ -1,7 +1,11 @@
1
- module Merit
1
+ module Merit::Models::ActiveRecord
2
2
  class Action < ActiveRecord::Base
3
+ include Merit::Models::ActionConcern
4
+
3
5
  self.table_name = :merit_actions
4
6
 
5
7
  has_many :activity_logs, class_name: 'Merit::ActivityLog'
6
8
  end
7
9
  end
10
+
11
+ class Merit::Action < Merit::Models::ActiveRecord::Action; end
@@ -1,4 +1,4 @@
1
- module Merit
1
+ module Merit::Models::ActiveRecord
2
2
  class ActivityLog < ActiveRecord::Base
3
3
  self.table_name = :merit_activity_logs
4
4
 
@@ -7,3 +7,5 @@ module Merit
7
7
  has_one :sash, through: :related_change
8
8
  end
9
9
  end
10
+
11
+ class Merit::ActivityLog < Merit::Models::ActiveRecord::ActivityLog; end
@@ -1,6 +1,6 @@
1
- module Merit
1
+ module Merit::Models::ActiveRecord
2
2
  class BadgesSash < ActiveRecord::Base
3
- include Base::BadgesSash
3
+ include Merit::Models::BadgesSashConcern
4
4
 
5
5
  has_many :activity_logs,
6
6
  class_name: 'Merit::ActivityLog',
@@ -9,3 +9,5 @@ module Merit
9
9
  validates_presence_of :badge_id, :sash
10
10
  end
11
11
  end
12
+
13
+ class Merit::BadgesSash < Merit::Models::ActiveRecord::BadgesSash; end
@@ -1,4 +1,4 @@
1
- module Merit
1
+ module Merit::Models::ActiveRecord
2
2
  # Sash is a container for reputation data for meritable models. It's an
3
3
  # indirection between meritable models and badges and scores (one to one
4
4
  # relationship).
@@ -6,7 +6,8 @@ module Merit
6
6
  # It's existence make join models like badges_users and scores_users
7
7
  # unnecessary. It should be transparent at the application.
8
8
  class Sash < ActiveRecord::Base
9
- include Base::Sash
9
+ include Merit::Models::SashConcern
10
+
10
11
  has_many :badges_sashes, dependent: :destroy
11
12
  has_many :scores, dependent: :destroy, class_name: 'Merit::Score'
12
13
 
@@ -27,3 +28,5 @@ module Merit
27
28
  end
28
29
  end
29
30
  end
31
+
32
+ class Merit::Sash < Merit::Models::ActiveRecord::Sash; end
@@ -1,4 +1,4 @@
1
- module Merit
1
+ module Merit::Models::ActiveRecord
2
2
  class Score < ActiveRecord::Base
3
3
  self.table_name = :merit_scores
4
4
  belongs_to :sash
@@ -20,3 +20,6 @@ module Merit
20
20
  end
21
21
  end
22
22
  end
23
+
24
+ class Merit::Score < Merit::Models::ActiveRecord::Score; end
25
+ class Merit::Score::Point < Merit::Models::ActiveRecord::Score::Point; end
@@ -0,0 +1,13 @@
1
+ module Merit::Models
2
+ module BadgesSashConcern
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ belongs_to :sash
7
+ end
8
+
9
+ def badge
10
+ Merit::Badge.find(badge_id)
11
+ end
12
+ end
13
+ end
@@ -1,5 +1,5 @@
1
1
  module Merit
2
- module Base
2
+ module Models::Base
3
3
  module BadgesSash
4
4
  extend ActiveSupport::Concern
5
5
 
@@ -1,5 +1,5 @@
1
1
  module Merit
2
- module Base
2
+ module Models::Base
3
3
  module Sash
4
4
  def badges
5
5
  badge_ids.map { |id| Merit::Badge.find id }
@@ -0,0 +1,53 @@
1
+ module Merit::Models
2
+ module SashConcern
3
+ def badges
4
+ badge_ids.map { |id| Merit::Badge.find id }
5
+ end
6
+
7
+ def badge_ids
8
+ badges_sashes.map(&:badge_id)
9
+ end
10
+
11
+ def add_badge(badge_id)
12
+ bs = Merit::BadgesSash.new(badge_id: badge_id.to_i)
13
+ badges_sashes << bs
14
+ bs
15
+ end
16
+
17
+ def rm_badge(badge_id)
18
+ badges_sashes.where(badge_id: badge_id.to_i).first.try(:destroy)
19
+ end
20
+
21
+ # Retrieve the number of points from a category
22
+ # By default all points are summed up
23
+ # @param category [String] The category
24
+ # @return [Integer] The number of points
25
+ def points(options = {})
26
+ if (category = options[:category])
27
+ scores.where(category: category).first.try(:points) || 0
28
+ else
29
+ scores.reduce(0) { |sum, score| sum + score.points }
30
+ end
31
+ end
32
+
33
+ def add_points(num_points, options = {})
34
+ point = Merit::Score::Point.new
35
+ point.num_points = num_points
36
+ scores
37
+ .where(category: options[:category] || 'default')
38
+ .first_or_create
39
+ .score_points << point
40
+ point
41
+ end
42
+
43
+ def subtract_points(num_points, options = {})
44
+ add_points(-num_points, options)
45
+ end
46
+
47
+ private
48
+
49
+ def create_scores
50
+ scores << Merit::Score.create
51
+ end
52
+ end
53
+ end
@@ -44,30 +44,15 @@ module Merit
44
44
  private
45
45
 
46
46
  def grant_when_applies(scoped_model, rule, level)
47
- scope_to_promote(scoped_model, rule.level_name, level).each do |object|
47
+ scoped_model.where("#{rule.level_name} < #{level}").each do |object|
48
48
  next unless rule.applies?(object)
49
+
49
50
  object.update_attribute rule.level_name, level
50
51
  end
51
- rescue rank_exception
52
+ rescue ActiveRecord::StatementInvalid
52
53
  str = "Error while granting rankings. Probably you need to add
53
54
  #{rule.level_name} column to #{scoped_model.class.name}."
54
55
  raise RankAttributeNotDefined, str
55
56
  end
56
-
57
- def rank_exception
58
- if defined? ActiveRecord
59
- ActiveRecord::StatementInvalid
60
- else
61
- Exception
62
- end
63
- end
64
-
65
- def scope_to_promote(scope, level_name, level)
66
- if Merit.orm == :mongoid
67
- scope.where(:"#{level_name}".lt => level)
68
- else
69
- scope.where("#{level_name} < #{level}")
70
- end
71
- end
72
57
  end
73
58
  end
@@ -6,13 +6,15 @@ Gem::Specification.new do |s|
6
6
  s.files = `git ls-files`.split("\n").reject{|f| f =~ /^\./ }
7
7
  s.test_files = `git ls-files -- test/*`.split("\n")
8
8
  s.license = 'MIT'
9
- s.version = '3.0.3'
9
+ s.version = '4.0.0'
10
10
  s.authors = ["Tute Costa"]
11
11
  s.email = 'tutecosta@gmail.com'
12
12
 
13
13
  s.required_ruby_version = '>= 2.3.0'
14
14
 
15
- s.add_dependency 'ambry', '~> 1.0.0'
15
+ s.add_runtime_dependency 'ambry', '~> 1.0.0'
16
+ s.add_runtime_dependency 'zeitwerk'
17
+
16
18
  s.add_development_dependency 'rails', '>= 5.1.6'
17
19
  s.add_development_dependency 'capybara'
18
20
  s.add_development_dependency 'simplecov'
@@ -1,14 +1,3 @@
1
- case Merit.orm
2
- when :active_record
3
- class Address < ActiveRecord::Base
4
- end
5
- when :mongoid
6
- class Address
7
- include Mongoid::Document
8
- include Mongoid::Timestamps
9
- end
10
- end
11
-
12
- class Address
1
+ class Address < ActiveRecord::Base
13
2
  belongs_to :user
14
3
  end
@@ -1,26 +1,8 @@
1
- case Merit.orm
2
- when :active_record
3
- class Comment < ActiveRecord::Base
4
- def friend
5
- User.find_by_name('friend')
6
- end
1
+ class Comment < ActiveRecord::Base
2
+ def friend
3
+ User.find_by_name('friend')
7
4
  end
8
- when :mongoid
9
- class Comment
10
- include Mongoid::Document
11
- include Mongoid::Timestamps
12
5
 
13
- field :name, :type => String
14
- field :comment, :type => String
15
- field :votes, :type => Integer, :default => 0
16
-
17
- def friend
18
- User.find_by(name: 'friend')
19
- end
20
- end
21
- end
22
-
23
- class Comment
24
6
  has_merit
25
7
 
26
8
  belongs_to :user
@@ -1,17 +1,4 @@
1
- case Merit.orm
2
- when :active_record
3
- class User < ActiveRecord::Base
4
- end
5
- when :mongoid
6
- class User
7
- include Mongoid::Document
8
- include Mongoid::Timestamps
9
-
10
- field :name, :type => String
11
- end
12
- end
13
-
14
- class User
1
+ class User < ActiveRecord::Base
15
2
  has_merit
16
3
 
17
4
  has_many :addresses
@@ -10,11 +10,15 @@ Bundler.require
10
10
  require "merit"
11
11
 
12
12
  module Dummy
13
- class Application < Rails::Application
13
+ class Application < ::Rails::Application
14
14
  if Rails.version.match? "5.2.+"
15
15
  config.active_record.sqlite3.represent_boolean_as_integer = true
16
16
  end
17
17
 
18
+ if Rails.version.match? "6.0.+"
19
+ config.load_defaults "6.0"
20
+ end
21
+
18
22
  config.i18n.enforce_available_locales = true
19
23
  config.encoding = "utf-8"
20
24
  config.filter_parameters += [:password]
@@ -19,7 +19,7 @@ Bundler.require
19
19
  require "merit"
20
20
 
21
21
  module Dummy
22
- class Application < Rails::Application
22
+ class Application < ::Rails::Application
23
23
  config.load_defaults 5.2 if ENV["RAILS_VERSION"] =~ /^5.2/
24
24
  config.api_only = true
25
25
  config.i18n.enforce_available_locales = true
@@ -10,7 +10,7 @@
10
10
  #
11
11
  # It's strongly recommended that you check this file into your version control system.
12
12
 
13
- ActiveRecord::Schema.define(version: 2014_09_06_225844) do
13
+ ActiveRecord::Schema.define(version: 2014_08_19_133931) do
14
14
 
15
15
  create_table "addresses", force: :cascade do |t|
16
16
  t.integer "user_id"
@@ -73,11 +73,6 @@ ActiveRecord::Schema.define(version: 2014_09_06_225844) do
73
73
  t.index ["sash_id"], name: "index_merit_scores_on_sash_id"
74
74
  end
75
75
 
76
- create_table "players", force: :cascade do |t|
77
- t.integer "sash_id"
78
- t.integer "level", default: 0
79
- end
80
-
81
76
  create_table "sashes", force: :cascade do |t|
82
77
  t.datetime "created_at", null: false
83
78
  t.datetime "updated_at", null: false
@@ -305,8 +305,8 @@ class NavigationTest < ActionDispatch::IntegrationTest
305
305
  end
306
306
  end
307
307
 
308
- comment_1.reload.points.must_be :==, 2
309
- comment_2.reload.points.must_be :==, 2
308
+ _(comment_1.reload.points).must_be :==, 2
309
+ _(comment_2.reload.points).must_be :==, 2
310
310
  end
311
311
 
312
312
  test 'api/comments#show should grant 1 point to user' do
@@ -38,5 +38,3 @@ Capybara.default_selector = :css
38
38
 
39
39
  # Load support files
40
40
  Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
41
-
42
- Merit.orm = :active_record if Merit.orm.nil?
@@ -14,7 +14,7 @@ describe Merit::BaseTargetFinder do
14
14
 
15
15
  finder = Merit::BaseTargetFinder.new(rule, action)
16
16
  collection = finder.find
17
- collection.must_be :==, comment
17
+ _(collection).must_be :==, comment
18
18
  end
19
19
  end
20
20
 
@@ -22,13 +22,13 @@ 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: 'players', target_id: 3)
26
- user = Player.new(id: 3)
25
+ action = Merit::Action.new(target_model: 'users', target_id: 3)
26
+ user = User.new(id: 3)
27
27
 
28
- Player.stubs(:find_by_id).with(3).returns(user)
28
+ User.stubs(:find_by_id).with(3).returns(user)
29
29
 
30
30
  finder = Merit::BaseTargetFinder.new(rule, action)
31
- finder.find.must_be :==, user
31
+ _(finder.find).must_be :==, user
32
32
  end
33
33
  end
34
34
 
@@ -41,7 +41,7 @@ describe Merit::BaseTargetFinder do
41
41
 
42
42
  finder = Merit::BaseTargetFinder.new(rule, action)
43
43
  Rails.logger.expects(:warn)
44
- finder.find.must_be_nil
44
+ _(finder.find).must_be_nil
45
45
  end
46
46
  end
47
47
 
@@ -57,26 +57,7 @@ describe Merit::BaseTargetFinder do
57
57
  target_data: comment.to_yaml)
58
58
 
59
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
60
+ _(finder.find.name).must_be :==, 'the comment name'
80
61
  end
81
62
  end
82
63
  end
@@ -1,24 +1,22 @@
1
1
  require 'test_helper'
2
2
 
3
- # TODO: Split different objects tests in it's own files
4
3
  class MeritUnitTest < ActiveSupport::TestCase
5
- require "orm_models/#{Merit.orm}"
6
-
7
4
  test 'extends only meritable models' do
8
- assert Player.method_defined?(:points), 'has_merit adds methods'
9
- assert !Fruit.method_defined?(:points), 'other models aren\'t extended'
5
+ assert User.method_defined?(:points), 'has_merit adds methods'
6
+ assert !Address.method_defined?(:points), 'other models aren\'t extended'
10
7
  end
11
8
 
12
9
  test 'Badges get "related_models" methods' do
13
- assert Merit::Badge.method_defined?(:soldiers), 'Badge#soldiers should be defined'
14
- assert Merit::Badge.method_defined?(:players), 'Badge#players should be defined'
10
+ Comment.new; User.new # load meritable classes
11
+ assert Merit::Badge.method_defined?(:comments), 'Badge#comments should be defined'
12
+ assert Merit::Badge.method_defined?(:users), 'Badge#users should be defined'
15
13
  end
16
14
 
17
15
  test 'unknown ranking raises exception' do
18
16
  class WeirdRankRules
19
17
  include Merit::RankRulesMethods
20
18
  def initialize
21
- set_rank level: 1, to: Player, level_name: :clown
19
+ set_rank level: 1, to: User, level_name: :clown
22
20
  end
23
21
  end
24
22
  assert_raises Merit::RankAttributeNotDefined do
@@ -11,47 +11,47 @@ describe Merit::Rule do
11
11
  end
12
12
 
13
13
  it 'truthy block should make rule apply' do
14
- @rule.applies?('str').must_be :==, true
14
+ _(@rule.applies?('str')).must_be :==, true
15
15
  end
16
16
 
17
17
  it 'falsy block should make rule fail' do
18
- @rule.applies?('string').must_be :==, false
18
+ _(@rule.applies?('string')).must_be :==, false
19
19
  end
20
20
 
21
21
  it 'block needs parameter for rule to pass' do
22
- @rule.applies?.must_be :==, false
22
+ _(@rule.applies?).must_be :==, false
23
23
  end
24
24
  end
25
25
 
26
26
  describe '#applies (without block)' do
27
27
  it 'empty condition should make rule apply' do
28
- @rule.applies?.must_be :==, true
28
+ _(@rule.applies?).must_be :==, true
29
29
  end
30
30
  end
31
31
 
32
32
  describe '#badge' do
33
33
  it 'raises exception on inexistent badge' do
34
34
  @rule.badge_name = 'inexistent'
35
- -> { @rule.badge }.must_raise Merit::BadgeNotFound
35
+ _(-> { @rule.badge }).must_raise Merit::BadgeNotFound
36
36
  end
37
37
 
38
38
  it 'finds related badge by name, when the name is a string' do
39
39
  Merit::Badge.create(id: 98, name: 'test-badge-98')
40
40
  @rule.badge_name = "test-badge-98"
41
- @rule.badge.must_be :==, Merit::Badge.find(98)
41
+ _(@rule.badge).must_be :==, Merit::Badge.find(98)
42
42
  end
43
43
 
44
44
  it 'finds related badge by name, when the name is a symbol' do
45
45
  Merit::Badge.create(id: 100, name: :testbadge)
46
46
  @rule.badge_name = 'testbadge'
47
- @rule.badge.must_be :==, Merit::Badge.find(100)
47
+ _(@rule.badge).must_be :==, Merit::Badge.find(100)
48
48
  @rule.badge
49
49
  end
50
50
 
51
51
  it 'finds related badge by name' do
52
52
  Merit::Badge.create(id: 98, name: 'test-badge-98')
53
53
  @rule.badge_id = 98
54
- @rule.badge.must_be :==, Merit::Badge.find(98)
54
+ _(@rule.badge).must_be :==, Merit::Badge.find(98)
55
55
  end
56
56
  end
57
57
  end