scorecard 0.0.1
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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.travis.yml +10 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +68 -0
- data/Rakefile +6 -0
- data/app/models/scorecard/point.rb +25 -0
- data/config.ru +7 -0
- data/db/migrate/1_create_points.rb +21 -0
- data/lib/scorecard.rb +16 -0
- data/lib/scorecard/engine.rb +7 -0
- data/lib/scorecard/point_rule.rb +46 -0
- data/lib/scorecard/points.rb +18 -0
- data/lib/scorecard/rules.rb +19 -0
- data/lib/scorecard/subscriber.rb +29 -0
- data/lib/scorecard/worker.rb +14 -0
- data/scorecard.gemspec +22 -0
- data/spec/acceptance/points_spec.rb +112 -0
- data/spec/internal/app/models/post.rb +7 -0
- data/spec/internal/app/models/user.rb +3 -0
- data/spec/internal/config/database.yml +3 -0
- data/spec/internal/config/routes.rb +3 -0
- data/spec/internal/db/schema.rb +13 -0
- data/spec/internal/log/.gitignore +1 -0
- data/spec/internal/public/favicon.ico +0 -0
- data/spec/spec_helper.rb +18 -0
- metadata +149 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5d64b389e1a10a193f8d53fb445000f19b15b3c8
|
4
|
+
data.tar.gz: 426aaad02a63b1c11904ff53f4a8f4795f895e25
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1de862ba8ae7f660ec7b39e03d045f676c9f5658f1057d2768562cc764c7f430632bf3be98a91d4189253c92573f8309c36545ed0a3c85b9884dac61b16bf82c
|
7
|
+
data.tar.gz: 754029cc38373c33d8a3487093f3988688fbfdeec2b0dfb44e4d3dbdb88acaa01111efcec7756729b212bb89a780a4656d5227b02b19f5f37e5b5e3dd9f5355a
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
language: ruby
|
2
|
+
rvm:
|
3
|
+
- 1.9.3
|
4
|
+
- 2.0.0
|
5
|
+
notifications:
|
6
|
+
campfire:
|
7
|
+
rooms:
|
8
|
+
- secure: "nK5kN3xf43qNUzQ2e+3hCD1Iy/XzqMS1EOm1aDyvbi1nv4xHD7ZkKTRgFAPYGJj/SpuSkIlWbFybYUfeGe9SVrg9/C70vlNmmuNkK2YV106qd5IemB65qzVb35yU7kyF84u5/kAHg8EdWfXsBYxB6KoXJoql1lGCYQMaH0L6Rb8="
|
9
|
+
on_success: change
|
10
|
+
on_failure: change
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Inspire9 and Pat Allan
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# Scorecard
|
2
|
+
|
3
|
+
A Rails engine for tracking points, badges and levels for gamification.
|
4
|
+
|
5
|
+
For anyone who comes across this, please note this is not yet feature complete, and the API will very likely change.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'scorecard'
|
12
|
+
|
13
|
+
Don't forget to bundle:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Then, add the migrations to your app and update your database accordingly:
|
18
|
+
|
19
|
+
$ rake scorecard:install:migrations db:migrate
|
20
|
+
|
21
|
+
## Rules
|
22
|
+
|
23
|
+
In an initializer, define the events that points are tied to - with a unique context and the number of points:
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
Scorecard::PointRule.new :new_post, 50
|
27
|
+
```
|
28
|
+
|
29
|
+
You can also provide a block with logic for whether to award the points, the maximum number of points allowed to be awarded for this rule, and the timeframe for that limit:
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
Scorecard::PointRule.new :new_post, 50, limit: 100, timeframe: :day,
|
33
|
+
if: lambda { |payload| payload[:user].posts.count <= 1 }
|
34
|
+
```
|
35
|
+
|
36
|
+
The payload object contains the context plus every option you send through to `score` call (see below).
|
37
|
+
|
38
|
+
## Scoring
|
39
|
+
|
40
|
+
And then, when you want to fire those events, use code much like the following:
|
41
|
+
|
42
|
+
```ruby
|
43
|
+
Scorecard::Points.score :new_post, gameable: post
|
44
|
+
```
|
45
|
+
|
46
|
+
This presumes that the user the points are for is a method on the gameable object. If that's not the case, you can pass in a custom user:
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
Scorecard::Points.score :new_post, gameable: post, user: user
|
50
|
+
```
|
51
|
+
|
52
|
+
If you're using Sidekiq, you can push the scoring behaviour into a background worker using `score_async` instead. Make sure `scorecard` is listed below `sidekiq` in your `Gemfile`.
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
Scorecard::Points.score_async :new_post, gameable: post
|
56
|
+
```
|
57
|
+
|
58
|
+
## Contributing
|
59
|
+
|
60
|
+
1. Fork it
|
61
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
62
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
63
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
64
|
+
5. Create new Pull Request
|
65
|
+
|
66
|
+
## Licence
|
67
|
+
|
68
|
+
Copyright (c) 2013, Scorecard is developed and maintained by [Inspire9](http://inspire9.com), and is released under the open MIT Licence.
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
class Scorecard::Point < ActiveRecord::Base
|
2
|
+
self.table_name = 'scorecard_points'
|
3
|
+
|
4
|
+
belongs_to :user, polymorphic: true
|
5
|
+
belongs_to :gameable, polymorphic: true
|
6
|
+
|
7
|
+
validates :context, presence: true
|
8
|
+
validates :identifier, presence: true, uniqueness: {
|
9
|
+
scope: [:context, :user_type, :user_id]
|
10
|
+
}
|
11
|
+
validates :amount, presence: true
|
12
|
+
validates :user, presence: true
|
13
|
+
|
14
|
+
def self.for_user(context, user)
|
15
|
+
where(
|
16
|
+
context: context,
|
17
|
+
user_id: user.id,
|
18
|
+
user_type: user.class.name
|
19
|
+
)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.for_user_in_timeframe(context, user, timeframe)
|
23
|
+
for_user(context, user).where(created_at: timeframe)
|
24
|
+
end
|
25
|
+
end
|
data/config.ru
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
class CreatePoints < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :scorecard_points do |table|
|
4
|
+
table.string :context, null: false
|
5
|
+
table.string :identifier, null: false
|
6
|
+
table.integer :amount, null: false
|
7
|
+
table.string :user_type, null: false
|
8
|
+
table.integer :user_id, null: false
|
9
|
+
table.string :gameable_type
|
10
|
+
table.integer :gameable_id
|
11
|
+
table.timestamps
|
12
|
+
end
|
13
|
+
|
14
|
+
add_index :scorecard_points, :context
|
15
|
+
add_index :scorecard_points, :identifier
|
16
|
+
add_index :scorecard_points, [:user_type, :user_id]
|
17
|
+
add_index :scorecard_points, [:gameable_type, :gameable_id]
|
18
|
+
add_index :scorecard_points, [:context, :identifier, :user_type, :user_id],
|
19
|
+
unique: true, name: :unique_points
|
20
|
+
end
|
21
|
+
end
|
data/lib/scorecard.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
module Scorecard
|
2
|
+
def self.configure
|
3
|
+
yield self
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.rules
|
7
|
+
@rules ||= Scorecard::Rules.new
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
require 'scorecard/engine'
|
12
|
+
require 'scorecard/points'
|
13
|
+
require 'scorecard/point_rule'
|
14
|
+
require 'scorecard/rules'
|
15
|
+
require 'scorecard/subscriber'
|
16
|
+
require 'scorecard/worker' if defined?(Sidekiq)
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class Scorecard::PointRule
|
2
|
+
TIMESPANS = [:day, :week, :month, :year]
|
3
|
+
|
4
|
+
attr_accessor :context, :amount, :options
|
5
|
+
|
6
|
+
def initialize(context, amount, options = {})
|
7
|
+
@context, @amount, @options = context, amount, options
|
8
|
+
end
|
9
|
+
|
10
|
+
def allowed?(payload)
|
11
|
+
if limit
|
12
|
+
return false unless current_points(payload).sum(:amount) < limit
|
13
|
+
elsif timeframe
|
14
|
+
return false unless current_points(payload).count.zero?
|
15
|
+
end
|
16
|
+
|
17
|
+
options[:if].nil? || options[:if].call(payload)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def current_points(payload)
|
23
|
+
if timeframe.nil?
|
24
|
+
Scorecard::Point.for_user(payload[:context], payload[:user])
|
25
|
+
else
|
26
|
+
Scorecard::Point.for_user_in_timeframe(payload[:context], payload[:user], time_range)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def limit
|
31
|
+
options[:limit]
|
32
|
+
end
|
33
|
+
|
34
|
+
def timeframe
|
35
|
+
options[:timeframe]
|
36
|
+
end
|
37
|
+
|
38
|
+
def time_range
|
39
|
+
unless TIMESPANS.include? timeframe
|
40
|
+
raise ArgumentError, "Unknown timeframe argument #{timeframe.inspect}"
|
41
|
+
end
|
42
|
+
|
43
|
+
now = Time.zone.now
|
44
|
+
now.send("beginning_of_#{timeframe}")..now.send("end_of_#{timeframe}")
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Scorecard::Points
|
2
|
+
def self.score(context, options)
|
3
|
+
ActiveSupport::Notifications.instrument 'points.scorecard',
|
4
|
+
options.merge(context: context)
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.score_async(context, options)
|
8
|
+
[:gameable, :user].each do |prefix|
|
9
|
+
next unless options[prefix]
|
10
|
+
|
11
|
+
options["#{prefix}_id"] = options[prefix].id
|
12
|
+
options["#{prefix}_type"] = options[prefix].class.name
|
13
|
+
options.delete prefix
|
14
|
+
end
|
15
|
+
|
16
|
+
Scorecard::Worker.perform_async context, options.stringify_keys
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class Scorecard::Rules
|
2
|
+
attr_reader :point_rules
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
@point_rules = []
|
6
|
+
end
|
7
|
+
|
8
|
+
def add_rule_for_points(context, amount, options = {})
|
9
|
+
point_rules << Scorecard::PointRule.new(context, amount, options)
|
10
|
+
end
|
11
|
+
|
12
|
+
def find_rule_for_points(context)
|
13
|
+
point_rules.detect { |rule| rule.context == context }
|
14
|
+
end
|
15
|
+
|
16
|
+
def clear
|
17
|
+
point_rules.clear
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class Scorecard::Subscriber
|
2
|
+
def self.attach_to(suffix)
|
3
|
+
subscriber = new
|
4
|
+
subscriber.public_methods(false).each do |event|
|
5
|
+
next if event.to_s == 'call'
|
6
|
+
|
7
|
+
ActiveSupport::Notifications.subscribe "#{event}.#{suffix}", subscriber
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(message, *args)
|
12
|
+
method = message.split('.').first
|
13
|
+
send method, ActiveSupport::Notifications::Event.new(message, *args)
|
14
|
+
end
|
15
|
+
|
16
|
+
def points(event)
|
17
|
+
rule = Scorecard.rules.find_rule_for_points event.payload[:context]
|
18
|
+
|
19
|
+
event.payload[:amount] ||= rule.amount
|
20
|
+
event.payload[:identifier] ||= event.payload[:gameable].id
|
21
|
+
event.payload[:user] ||= event.payload[:gameable].user
|
22
|
+
|
23
|
+
return unless rule && rule.allowed?(event.payload)
|
24
|
+
|
25
|
+
Scorecard::Point.create(
|
26
|
+
event.payload.slice(:context, :amount, :identifier, :user, :gameable)
|
27
|
+
)
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class Scorecard::Worker
|
2
|
+
include Sidekiq::Worker
|
3
|
+
|
4
|
+
def perform(context, options)
|
5
|
+
%w(gameable user).each do |prefix|
|
6
|
+
next unless options["#{prefix}_type"]
|
7
|
+
|
8
|
+
klass = options.delete("#{prefix}_type").constantize
|
9
|
+
options[prefix] = klass.find options.delete("#{prefix}_id")
|
10
|
+
end
|
11
|
+
|
12
|
+
Scorecard::Points.score context.to_sym, options.symbolize_keys
|
13
|
+
end
|
14
|
+
end
|
data/scorecard.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
Gem::Specification.new do |spec|
|
3
|
+
spec.name = 'scorecard'
|
4
|
+
spec.version = '0.0.1'
|
5
|
+
spec.authors = ['Pat Allan']
|
6
|
+
spec.email = ['pat@freelancing-gods.com']
|
7
|
+
spec.summary = 'Rails Engine for common scorecard patterns'
|
8
|
+
spec.description = 'Use an engine to track points, badges and levels in your Rails app.'
|
9
|
+
spec.homepage = 'https://github.com/inspire9/scorecard'
|
10
|
+
spec.license = 'MIT'
|
11
|
+
|
12
|
+
spec.files = `git ls-files`.split($/)
|
13
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
14
|
+
spec.require_paths = ['lib']
|
15
|
+
|
16
|
+
spec.add_runtime_dependency 'rails', '>= 3.2'
|
17
|
+
|
18
|
+
spec.add_development_dependency 'combustion', '~> 0.5.1'
|
19
|
+
spec.add_development_dependency 'rspec-rails', '~> 2.14.0'
|
20
|
+
spec.add_development_dependency 'sidekiq', '~> 2.15'
|
21
|
+
spec.add_development_dependency 'sqlite3', '~> 1.3.8'
|
22
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Scorecard' do
|
4
|
+
before :each do
|
5
|
+
Scorecard.rules.clear
|
6
|
+
end
|
7
|
+
|
8
|
+
it "stores points for configured behaviour" do
|
9
|
+
Scorecard.configure do |config|
|
10
|
+
config.rules.add_rule_for_points :new_post, 50
|
11
|
+
end
|
12
|
+
|
13
|
+
user = User.create!
|
14
|
+
post = Post.create! user: user
|
15
|
+
|
16
|
+
Scorecard::Point.where(
|
17
|
+
context: 'new_post',
|
18
|
+
amount: 50,
|
19
|
+
identifier: post.id.to_s,
|
20
|
+
user_id: user.id,
|
21
|
+
user_type: 'User',
|
22
|
+
gameable_id: post.id,
|
23
|
+
gameable_type: 'Post'
|
24
|
+
).should_not be_empty
|
25
|
+
end
|
26
|
+
|
27
|
+
it "only stores points when provided logic passes" do
|
28
|
+
Scorecard.configure do |config|
|
29
|
+
config.rules.add_rule_for_points :new_post, 50,
|
30
|
+
if: lambda { |payload| Post.count <= 1 }
|
31
|
+
end
|
32
|
+
|
33
|
+
user = User.create!
|
34
|
+
post = Post.create! user: user
|
35
|
+
post = Post.create! user: user
|
36
|
+
|
37
|
+
Scorecard::Point.where(
|
38
|
+
context: 'new_post',
|
39
|
+
amount: 50
|
40
|
+
).count.should == 1
|
41
|
+
end
|
42
|
+
|
43
|
+
it "does not double-up on points for the same event" do
|
44
|
+
Scorecard.configure do |config|
|
45
|
+
config.rules.add_rule_for_points :new_post, 50
|
46
|
+
end
|
47
|
+
|
48
|
+
user = User.create!
|
49
|
+
post = Post.create! user: user
|
50
|
+
Scorecard::Points.score :new_post, gameable: post
|
51
|
+
|
52
|
+
Scorecard::Point.where(
|
53
|
+
context: 'new_post',
|
54
|
+
amount: 50,
|
55
|
+
identifier: post.id.to_s,
|
56
|
+
user_id: user.id,
|
57
|
+
user_type: 'User',
|
58
|
+
gameable_id: post.id,
|
59
|
+
gameable_type: 'Post'
|
60
|
+
).count.should == 1
|
61
|
+
end
|
62
|
+
|
63
|
+
it "respects limit options" do
|
64
|
+
Scorecard.configure do |config|
|
65
|
+
config.rules.add_rule_for_points :new_post, 50, limit: 100
|
66
|
+
end
|
67
|
+
|
68
|
+
user = User.create!
|
69
|
+
post = Post.create! user: user
|
70
|
+
post = Post.create! user: user
|
71
|
+
post = Post.create! user: user
|
72
|
+
|
73
|
+
Scorecard::Point.where(
|
74
|
+
context: 'new_post',
|
75
|
+
amount: 50
|
76
|
+
).count.should == 2
|
77
|
+
end
|
78
|
+
|
79
|
+
it "respects timeframe options" do
|
80
|
+
Scorecard.configure do |config|
|
81
|
+
config.rules.add_rule_for_points :new_post, 50, timeframe: :day
|
82
|
+
end
|
83
|
+
|
84
|
+
user = User.create!
|
85
|
+
post = Post.create! user: user
|
86
|
+
post = Post.create! user: user
|
87
|
+
|
88
|
+
Scorecard::Point.where(
|
89
|
+
context: 'new_post',
|
90
|
+
amount: 50
|
91
|
+
).count.should == 1
|
92
|
+
end
|
93
|
+
|
94
|
+
it "allows for processing via Sidekiq" do
|
95
|
+
Scorecard.configure do |config|
|
96
|
+
config.rules.add_rule_for_points :new_user, 20
|
97
|
+
end
|
98
|
+
|
99
|
+
user = User.create!
|
100
|
+
Scorecard::Points.score_async :new_user, gameable: user, user: user
|
101
|
+
|
102
|
+
Scorecard::Point.where(
|
103
|
+
context: 'new_user',
|
104
|
+
amount: 20,
|
105
|
+
identifier: user.id.to_s,
|
106
|
+
user_id: user.id,
|
107
|
+
user_type: 'User',
|
108
|
+
gameable_id: user.id,
|
109
|
+
gameable_type: 'User'
|
110
|
+
).should_not be_empty
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
ActiveRecord::Schema.define do
|
2
|
+
create_table :posts, :force => true do |table|
|
3
|
+
table.string :subject
|
4
|
+
table.text :content
|
5
|
+
table.integer :user_id
|
6
|
+
table.timestamps
|
7
|
+
end
|
8
|
+
|
9
|
+
create_table :users, :force => true do |table|
|
10
|
+
table.string :email
|
11
|
+
table.timestamps
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
*.log
|
File without changes
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
|
3
|
+
Bundler.setup :default, :development
|
4
|
+
|
5
|
+
require 'combustion'
|
6
|
+
require 'sidekiq'
|
7
|
+
require 'sidekiq/testing/inline'
|
8
|
+
require 'scorecard'
|
9
|
+
|
10
|
+
Combustion.initialize! :active_record
|
11
|
+
|
12
|
+
require 'rspec/rails'
|
13
|
+
|
14
|
+
Dir["./spec/support/**/*.rb"].each { |file| require file }
|
15
|
+
|
16
|
+
RSpec.configure do |config|
|
17
|
+
config.use_transactional_fixtures = true
|
18
|
+
end
|
metadata
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: scorecard
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Pat Allan
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-10-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '3.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '3.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: combustion
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.5.1
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.5.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec-rails
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.14.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.14.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: sidekiq
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.15'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '2.15'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: sqlite3
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ~>
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 1.3.8
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ~>
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 1.3.8
|
83
|
+
description: Use an engine to track points, badges and levels in your Rails app.
|
84
|
+
email:
|
85
|
+
- pat@freelancing-gods.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- .gitignore
|
91
|
+
- .travis.yml
|
92
|
+
- Gemfile
|
93
|
+
- LICENSE.txt
|
94
|
+
- README.md
|
95
|
+
- Rakefile
|
96
|
+
- app/models/scorecard/point.rb
|
97
|
+
- config.ru
|
98
|
+
- db/migrate/1_create_points.rb
|
99
|
+
- lib/scorecard.rb
|
100
|
+
- lib/scorecard/engine.rb
|
101
|
+
- lib/scorecard/point_rule.rb
|
102
|
+
- lib/scorecard/points.rb
|
103
|
+
- lib/scorecard/rules.rb
|
104
|
+
- lib/scorecard/subscriber.rb
|
105
|
+
- lib/scorecard/worker.rb
|
106
|
+
- scorecard.gemspec
|
107
|
+
- spec/acceptance/points_spec.rb
|
108
|
+
- spec/internal/app/models/post.rb
|
109
|
+
- spec/internal/app/models/user.rb
|
110
|
+
- spec/internal/config/database.yml
|
111
|
+
- spec/internal/config/routes.rb
|
112
|
+
- spec/internal/db/schema.rb
|
113
|
+
- spec/internal/log/.gitignore
|
114
|
+
- spec/internal/public/favicon.ico
|
115
|
+
- spec/spec_helper.rb
|
116
|
+
homepage: https://github.com/inspire9/scorecard
|
117
|
+
licenses:
|
118
|
+
- MIT
|
119
|
+
metadata: {}
|
120
|
+
post_install_message:
|
121
|
+
rdoc_options: []
|
122
|
+
require_paths:
|
123
|
+
- lib
|
124
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
+
requirements:
|
126
|
+
- - '>='
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
requirements: []
|
135
|
+
rubyforge_project:
|
136
|
+
rubygems_version: 2.1.2
|
137
|
+
signing_key:
|
138
|
+
specification_version: 4
|
139
|
+
summary: Rails Engine for common scorecard patterns
|
140
|
+
test_files:
|
141
|
+
- spec/acceptance/points_spec.rb
|
142
|
+
- spec/internal/app/models/post.rb
|
143
|
+
- spec/internal/app/models/user.rb
|
144
|
+
- spec/internal/config/database.yml
|
145
|
+
- spec/internal/config/routes.rb
|
146
|
+
- spec/internal/db/schema.rb
|
147
|
+
- spec/internal/log/.gitignore
|
148
|
+
- spec/internal/public/favicon.ico
|
149
|
+
- spec/spec_helper.rb
|