honor 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +20 -0
- data/.rspec +2 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +155 -0
- data/Rakefile +6 -0
- data/honor.gemspec +26 -0
- data/honor.sqlite3 +0 -0
- data/lib/generators/install_generator.rb +40 -0
- data/lib/generators/templates/active_record/create_points.rb +13 -0
- data/lib/generators/templates/active_record/create_scorecards.rb +15 -0
- data/lib/honor.rb +25 -0
- data/lib/honor/model_additions.rb +51 -0
- data/lib/honor/point.rb +51 -0
- data/lib/honor/scorecard.rb +51 -0
- data/lib/honor/version.rb +3 -0
- data/rails/init.rb +1 -0
- data/spec/config/database.yml.sample +19 -0
- data/spec/config/models.rb +7 -0
- data/spec/config/schema.rb +34 -0
- data/spec/generators/install_generator_spec.rb +27 -0
- data/spec/honor/model_additions_spec.rb +115 -0
- data/spec/honor/point_spec.rb +117 -0
- data/spec/honor/scorecard_spec.rb +119 -0
- data/spec/spec_helper.rb +63 -0
- metadata +177 -0
data/.gitignore
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/*.log
|
15
|
+
spec/config/database.yml
|
16
|
+
spec/reports
|
17
|
+
test/tmp
|
18
|
+
test/version_tmp
|
19
|
+
tmp
|
20
|
+
.DS_Store
|
data/.rspec
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Jeremy Ward
|
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,155 @@
|
|
1
|
+
# Honor
|
2
|
+
|
3
|
+
Honor adds support for common gamification features such as points, leaderboards, and achievements.
|
4
|
+
|
5
|
+
## Overview
|
6
|
+
|
7
|
+
Honor allows you to easily integrate points, rankings, and leaderboards into your Rails application.
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
To use Honor, first add it to you Gemfile:
|
12
|
+
|
13
|
+
```ruby
|
14
|
+
gem 'honor'
|
15
|
+
```
|
16
|
+
|
17
|
+
And then intall it with bundler by executing:
|
18
|
+
|
19
|
+
```shell
|
20
|
+
bundle install
|
21
|
+
```
|
22
|
+
|
23
|
+
Install and run the migrations:
|
24
|
+
|
25
|
+
```shell
|
26
|
+
rails g honor:install
|
27
|
+
rails db:migrate
|
28
|
+
```
|
29
|
+
|
30
|
+
## Usage
|
31
|
+
|
32
|
+
Honor is meant to be used with a **single model** (eg. User, Employee, Person, Company, etc). At this time, using Honor with multiple models is NOT supported.
|
33
|
+
|
34
|
+
```ruby
|
35
|
+
class User < ActiveRecord::Base
|
36
|
+
include Honor
|
37
|
+
end
|
38
|
+
```
|
39
|
+
|
40
|
+
Honor adds two new relationships to the receiving model.
|
41
|
+
|
42
|
+
1. `has_many :points`
|
43
|
+
2. `has_one :scorecard`
|
44
|
+
|
45
|
+
### Points
|
46
|
+
|
47
|
+
Points are generally awarded for various User interactions throughout an application. Honor gives you the ability to provide a message as well as a classification to each point block awarded.
|
48
|
+
|
49
|
+
```ruby
|
50
|
+
class User < ActiveRecord::Base
|
51
|
+
include Honor
|
52
|
+
end
|
53
|
+
|
54
|
+
@user = User.new
|
55
|
+
|
56
|
+
# add points to a user
|
57
|
+
@user.add_points(25)
|
58
|
+
|
59
|
+
# add points to a user with a bit more description
|
60
|
+
@user.add_points(25, "Awarded for some awesome action", "Social")
|
61
|
+
|
62
|
+
# subtract points to a user
|
63
|
+
@user.subtract_points(25)
|
64
|
+
|
65
|
+
# subtract points to a user with a bit more description
|
66
|
+
@user.subtract_points(25, "Awarded for some awesome action", "Social")
|
67
|
+
|
68
|
+
# Quick Accessors for commone point totals
|
69
|
+
@user.points_total
|
70
|
+
@user.points_today
|
71
|
+
@user.points_this_week
|
72
|
+
@user.points_this_month
|
73
|
+
@user.points_this_year
|
74
|
+
|
75
|
+
# If you're fastidious about keeping business logic categories semantic (same case, same spelling, etc), then you can easily total points for a given point category by passing a string representing the category into any of the accessors above:
|
76
|
+
@user.points_total("Social") # => returns total for points with a category matcing "Social"
|
77
|
+
|
78
|
+
```
|
79
|
+
|
80
|
+
There's bond to be situations where you don't have or don't want to instantiate a new "honorable" object (User in the above example), but have access to the User's id....Honorable has you covered. In these cases, Honorable provides class methods similar to the above:
|
81
|
+
|
82
|
+
```ruby
|
83
|
+
# example user id, could come from an array or whatever
|
84
|
+
user_id = 1
|
85
|
+
|
86
|
+
# add points to a user
|
87
|
+
Honor::Point.give_to(user_id, 25)
|
88
|
+
|
89
|
+
# add points to a user with a bit more description
|
90
|
+
Honor::Point.give_to(user_id, 25, "Awarded for some awesome action", "Social")
|
91
|
+
|
92
|
+
# subtract points to a user
|
93
|
+
Honor::Point.take_from(user_id, 25)
|
94
|
+
|
95
|
+
# subtract points to a user with a bit more description
|
96
|
+
Honor::Point.take_from(user_id, 25, "Awarded for some awesome action", "Social")
|
97
|
+
|
98
|
+
|
99
|
+
# Quick Accessors for commone point totals (does NOT accept a category at this time)
|
100
|
+
Honor::Point.points_total
|
101
|
+
Honor::Point.points_today
|
102
|
+
Honor::Point.points_this_week
|
103
|
+
Honor::Point.points_this_month
|
104
|
+
Honor::Point.points_this_year
|
105
|
+
|
106
|
+
```
|
107
|
+
|
108
|
+
### Scorecards
|
109
|
+
|
110
|
+
Every "honorable" object (User in the above examples) has one scorecard that is continually updated whenever a point record is saved. Scorecards keep a running tally of points for:
|
111
|
+
|
112
|
+
1. daily
|
113
|
+
2. weekly
|
114
|
+
3. monthly
|
115
|
+
4. yearly
|
116
|
+
5. lifetime
|
117
|
+
|
118
|
+
From these subsets you can quickly and easily make Ranked Leaderboards that complies with the Standard Competition Ranking system. That is, it takes tied positions into account and adjusts ranks accordingly.
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
user_ids = current_user.friend_ids_and_me # => an array of user_ids (eg. [1, 5, 2, 23])
|
122
|
+
@daily_leaderboard = Honor::Scorecard.leaderboard(user_ids, rank_by: 'daily', sort_direction: 'desc')
|
123
|
+
@weekly_leaderboard = Honor::Scorecard.leaderboard(user_ids, rank_by: 'weekly', sort_direction: 'desc')
|
124
|
+
@monthly_leaderboard = Honor::Scorecard.leaderboard(user_ids, rank_by: 'monthly', sort_direction: 'desc')
|
125
|
+
@yearly_leaderboard = Honor::Scorecard.leaderboard(user_ids, rank_by: 'yearly', sort_direction: 'desc')
|
126
|
+
```
|
127
|
+
|
128
|
+
Honor provides the Scorecards class with some utility methods useful for setting cron jobs to automate cleaning-up the scorecards.
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
Honor::Scorecard.reset_daily_scores
|
132
|
+
Honor::Scorecard.reset_weekly_scores
|
133
|
+
Honor::Scorecard.reset_monthly_scores
|
134
|
+
Honor::Scorecard.reset_yearly_scores
|
135
|
+
```
|
136
|
+
|
137
|
+
## Testing
|
138
|
+
|
139
|
+
Honor uses RSpec for its test coverage. Inside the gem directory, you can run the specs with:
|
140
|
+
|
141
|
+
```shell
|
142
|
+
rake
|
143
|
+
```
|
144
|
+
|
145
|
+
## TODO
|
146
|
+
|
147
|
+
- Add Badges / Achievement functionality
|
148
|
+
|
149
|
+
## Contributing
|
150
|
+
|
151
|
+
1. Fork it
|
152
|
+
2. Create your feature branch `git checkout -b my-new-feature`
|
153
|
+
3. Commit your changes `git commit -am 'Add some feature'`
|
154
|
+
4. Push to the branch `git push origin my-new-feature`
|
155
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/honor.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'honor/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "honor"
|
8
|
+
gem.version = Honor::VERSION
|
9
|
+
gem.authors = ["Jeremy Ward"]
|
10
|
+
gem.email = ["jrmy.ward@gmail.com"]
|
11
|
+
gem.description = %q{Adds support for common gamification features such as points, leaderboards, and achievements.}
|
12
|
+
gem.summary = %q{General gamification-centric reputation system for Rails Applications.}
|
13
|
+
gem.homepage = "https://github.com/jrmyward/honor"
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
|
20
|
+
gem.add_runtime_dependency 'rails', '~> 3.0'
|
21
|
+
gem.add_development_dependency "rspec"
|
22
|
+
gem.add_development_dependency 'ammeter'
|
23
|
+
gem.add_development_dependency "supermodel"
|
24
|
+
gem.add_development_dependency "database_cleaner"
|
25
|
+
gem.add_development_dependency "timecop"
|
26
|
+
end
|
data/honor.sqlite3
ADDED
Binary file
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/active_record'
|
3
|
+
require 'rails/generators/migration'
|
4
|
+
|
5
|
+
module Honor
|
6
|
+
class InstallGenerator < Rails::Generators::Base
|
7
|
+
include Rails::Generators::Migration
|
8
|
+
|
9
|
+
desc "Generates migration for Points and Scorecard"
|
10
|
+
|
11
|
+
def self.orm
|
12
|
+
Rails::Generators.options[:rails][:orm]
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.source_root
|
16
|
+
File.join(File.dirname(__FILE__), 'templates', (orm.to_s unless orm.class.eql?(String)) )
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.orm_has_migration?
|
20
|
+
[:active_record].include? orm
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.next_migration_number(dirname)
|
24
|
+
if ActiveRecord::Base.timestamped_migrations
|
25
|
+
migration_number = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
|
26
|
+
migration_number += 1
|
27
|
+
migration_number.to_s
|
28
|
+
else
|
29
|
+
"%.3d" % (current_migration_number(dirname) + 1)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def create_migration_file
|
34
|
+
if self.class.orm_has_migration?
|
35
|
+
migration_template 'create_points.rb', 'db/migrate/create_honor_points.rb'
|
36
|
+
migration_template 'create_scorecards.rb', 'db/migrate/create_honor_scorecards.rb'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class CreateHonorScorecardsMigration < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :scorecards do |t|
|
4
|
+
t.integer :user_id
|
5
|
+
t.integer :daily
|
6
|
+
t.integer :weekly
|
7
|
+
t.integer :monthly
|
8
|
+
t.integer :yearly
|
9
|
+
t.integer :lifetime
|
10
|
+
|
11
|
+
t.timestamps
|
12
|
+
end
|
13
|
+
add_index :scorecards, :user_id
|
14
|
+
end
|
15
|
+
end
|
data/lib/honor.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require "active_record"
|
2
|
+
require "active_record/version"
|
3
|
+
require "honor/version"
|
4
|
+
require "honor/model_additions"
|
5
|
+
require "honor/point"
|
6
|
+
require "honor/scorecard"
|
7
|
+
|
8
|
+
module Honor
|
9
|
+
|
10
|
+
def self.included(receiver)
|
11
|
+
receiver.class_eval %Q{
|
12
|
+
has_many :points, :class_name => "Honor::Point", :foreign_key => "user_id", :dependent => :destroy
|
13
|
+
has_one :scorecard, :class_name => "Honor::Scorecard", :foreign_key => "user_id", :dependent => :destroy
|
14
|
+
}
|
15
|
+
|
16
|
+
Honor::Point.class_eval %Q{
|
17
|
+
belongs_to :#{receiver.to_s.underscore}, :class_name => "#{receiver.to_s}", :foreign_key => "user_id"
|
18
|
+
}
|
19
|
+
|
20
|
+
Honor::Scorecard.class_eval %Q{
|
21
|
+
belongs_to :#{receiver.to_s.underscore}, :class_name => "#{receiver.to_s}", :foreign_key => "user_id"
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Honor
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
def add_points(number_of_points, message = "Manually granted through 'add_points'", category = 'default' )
|
5
|
+
points.create!({value: number_of_points, message: message, category: category})
|
6
|
+
end
|
7
|
+
|
8
|
+
def subtract_points(number_of_points, message = "Manually granted through 'add_points'", category = 'default' )
|
9
|
+
add_points -number_of_points, message, category
|
10
|
+
end
|
11
|
+
|
12
|
+
def points_total(category = nil)
|
13
|
+
if category.nil?
|
14
|
+
points.sum(:value)
|
15
|
+
else
|
16
|
+
points.where("points.category = ?", category).sum(:value)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def points_today(category = nil)
|
21
|
+
if category.nil?
|
22
|
+
points.where(:created_at => Time.zone.now.beginning_of_day..Time.zone.now.end_of_day).sum(:value)
|
23
|
+
else
|
24
|
+
points.where(:created_at => Time.zone.now.beginning_of_day..Time.zone.now.end_of_day).where("points.category = ?", category).sum(:value)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def points_this_week(category = nil)
|
29
|
+
if category.nil?
|
30
|
+
points.where(:created_at => Time.zone.now.beginning_of_week..Time.zone.now.end_of_week).sum(:value)
|
31
|
+
else
|
32
|
+
points.where(:created_at => Time.zone.now.beginning_of_week..Time.zone.now.end_of_week).where("points.category = ?", category).sum(:value)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def points_this_month(category = nil)
|
37
|
+
if category.nil?
|
38
|
+
points.where(:created_at => Time.zone.now.beginning_of_month..Time.zone.now.end_of_month).sum(:value)
|
39
|
+
else
|
40
|
+
points.where(:created_at => Time.zone.now.beginning_of_month..Time.zone.now.end_of_month).where("points.category = ?", category).sum(:value)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def points_this_year(category = nil)
|
45
|
+
if category.nil?
|
46
|
+
points.where(:created_at => Time.zone.now.beginning_of_year..Time.zone.now.end_of_year).sum(:value)
|
47
|
+
else
|
48
|
+
points.where(:created_at => Time.zone.now.beginning_of_year..Time.zone.now.end_of_year).where("points.category = ?", category).sum(:value)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/lib/honor/point.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
module Honor
|
2
|
+
class Point < ActiveRecord::Base
|
3
|
+
attr_accessible :category, :message, :user_id, :value
|
4
|
+
|
5
|
+
after_save :update_scorecard
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def give_to(user_id, number_of_points, message = "Manually granted through 'add_points'", category = 'default')
|
9
|
+
create!({user_id: user_id, value: number_of_points, message: message, category: category})
|
10
|
+
end
|
11
|
+
|
12
|
+
def take_from(user_id, number_of_points, message = "Manually granted through 'add_points'", category = 'default')
|
13
|
+
give_to user_id, -number_of_points, message, category
|
14
|
+
end
|
15
|
+
|
16
|
+
def user_points_total(user_id)
|
17
|
+
where(:user_id => user_id).sum(:value)
|
18
|
+
end
|
19
|
+
|
20
|
+
def user_points_today(user_id)
|
21
|
+
where(:user_id => user_id).where(:created_at => Time.zone.now.beginning_of_day..Time.zone.now.end_of_day).sum(:value)
|
22
|
+
end
|
23
|
+
|
24
|
+
def user_points_this_week(user_id)
|
25
|
+
where(:user_id => user_id).where(:created_at => Time.zone.now.beginning_of_week..Time.zone.now.end_of_week).sum(:value)
|
26
|
+
end
|
27
|
+
|
28
|
+
def user_points_this_month(user_id)
|
29
|
+
where(:user_id => user_id).where(:created_at => Time.zone.now.beginning_of_month..Time.zone.now.end_of_month).sum(:value)
|
30
|
+
end
|
31
|
+
|
32
|
+
def user_points_this_year(user_id)
|
33
|
+
where(:user_id => user_id).where(:created_at => Time.zone.now.beginning_of_year..Time.zone.now.end_of_year).sum(:value)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def update_scorecard
|
41
|
+
scorecard = Honor::Scorecard.find_or_initialize_by_user_id(user_id)
|
42
|
+
scorecard.daily = Honor::Point.user_points_today(user_id)
|
43
|
+
scorecard.weekly = Honor::Point.user_points_this_week(user_id)
|
44
|
+
scorecard.monthly = Honor::Point.user_points_this_month(user_id)
|
45
|
+
scorecard.yearly = Honor::Point.user_points_this_year(user_id)
|
46
|
+
scorecard.lifetime = Honor::Point.user_points_total(user_id)
|
47
|
+
scorecard.save!
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Honor
|
2
|
+
|
3
|
+
class Scorecard < ActiveRecord::Base
|
4
|
+
attr_accessible :daily, :lifetime, :monthly, :user_id, :weekly, :yearly, :position
|
5
|
+
attr_accessor :position
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def leaderboard(scorecard_user_ids, opt={})
|
9
|
+
opt.reverse_merge! :rank_by => 'daily',
|
10
|
+
:sort_direction => 'desc'
|
11
|
+
scorecards = team_scorecards(scorecard_user_ids, rank_by: opt[:rank_by], sort_direction: opt[:sort_direction])
|
12
|
+
rankings = []
|
13
|
+
scorecards.each_with_index do |scorecard, i|
|
14
|
+
if i == 0
|
15
|
+
scorecard.position = 1
|
16
|
+
elsif scorecard[opt[:rank_by]] == scorecards[i-1][opt[:rank_by]]
|
17
|
+
scorecard.position = rankings[i-1]
|
18
|
+
else
|
19
|
+
scorecard.position = i + 1
|
20
|
+
end
|
21
|
+
rankings[i] = scorecard.position
|
22
|
+
end
|
23
|
+
return scorecards
|
24
|
+
end
|
25
|
+
|
26
|
+
def reset_daily_scores
|
27
|
+
where("updated_at < ?", Time.zone.now.beginning_of_day).update_all(:daily => 0)
|
28
|
+
end
|
29
|
+
|
30
|
+
def reset_weekly_scores
|
31
|
+
where("updated_at < ?", Time.zone.now.beginning_of_week).update_all(:weekly => 0)
|
32
|
+
end
|
33
|
+
|
34
|
+
def reset_monthly_scores
|
35
|
+
where("updated_at < ?", Time.zone.now.beginning_of_month).update_all(:monthly => 0)
|
36
|
+
end
|
37
|
+
|
38
|
+
def reset_yearly_scores
|
39
|
+
where("updated_at < ?", Time.zone.now.beginning_of_year).update_all(:yearly => 0)
|
40
|
+
end
|
41
|
+
|
42
|
+
def team_scorecards(scorecard_user_ids, opt={})
|
43
|
+
opt.reverse_merge! :rank_by => 'daily',
|
44
|
+
:sort_direction => 'desc'
|
45
|
+
includes(:user).where('user_id IN (?)', scorecard_user_ids).order("#{opt[:rank_by]} #{opt[:sort_direction]}")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
data/rails/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'honor'
|
@@ -0,0 +1,19 @@
|
|
1
|
+
sqlite3:
|
2
|
+
adapter: sqlite3
|
3
|
+
database: honor.sqlite3
|
4
|
+
|
5
|
+
mysql:
|
6
|
+
adapter: mysql2
|
7
|
+
hostname: localhost
|
8
|
+
username: root
|
9
|
+
password:
|
10
|
+
database: honor
|
11
|
+
charset: utf8
|
12
|
+
|
13
|
+
postgresql:
|
14
|
+
adapter: postgresql
|
15
|
+
hostname: localhost
|
16
|
+
username: postgres
|
17
|
+
password:
|
18
|
+
database: honor
|
19
|
+
encoding: utf8
|
@@ -0,0 +1,34 @@
|
|
1
|
+
ActiveRecord::Schema.define :version => 0 do
|
2
|
+
create_table "employees", :force => true do |t|
|
3
|
+
t.string "first_name"
|
4
|
+
t.string "last_name"
|
5
|
+
end
|
6
|
+
|
7
|
+
create_table "points", :force => true do |t|
|
8
|
+
t.integer "user_id"
|
9
|
+
t.integer "value"
|
10
|
+
t.string "category"
|
11
|
+
t.text "message"
|
12
|
+
t.datetime "created_at", :null => false
|
13
|
+
t.datetime "updated_at", :null => false
|
14
|
+
end
|
15
|
+
add_index "points", ["user_id"], :name => "index_points_on_user_id"
|
16
|
+
|
17
|
+
create_table "scorecards", :force => true do |t|
|
18
|
+
t.integer "user_id"
|
19
|
+
t.integer "daily"
|
20
|
+
t.integer "weekly"
|
21
|
+
t.integer "monthly"
|
22
|
+
t.integer "yearly"
|
23
|
+
t.integer "lifetime"
|
24
|
+
t.datetime "created_at", :null => false
|
25
|
+
t.datetime "updated_at", :null => false
|
26
|
+
end
|
27
|
+
add_index "scorecards", ["user_id"], :name => "index_scorecards_on_user_id"
|
28
|
+
|
29
|
+
create_table "users", :force => true do |t|
|
30
|
+
t.string "first_name"
|
31
|
+
t.string "last_name"
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
# Generators are not automatically loaded by Rails
|
4
|
+
require 'generators/install_generator'
|
5
|
+
|
6
|
+
describe Honor::InstallGenerator do
|
7
|
+
# Tell the generator where to put its output (what it thinks of as Rails.root)
|
8
|
+
destination File.expand_path("../../../../../tmp", __FILE__)
|
9
|
+
|
10
|
+
before do
|
11
|
+
prepare_destination
|
12
|
+
Rails::Generators.options[:rails][:orm] = :active_record
|
13
|
+
end
|
14
|
+
describe 'no arguments' do
|
15
|
+
before { run_generator }
|
16
|
+
|
17
|
+
describe 'db/migrate/create_honor_points.rb' do
|
18
|
+
subject { file('db/migrate/create_honor_points.rb') }
|
19
|
+
it { should be_a_migration }
|
20
|
+
end
|
21
|
+
|
22
|
+
describe 'db/migrate/create_honor_scorecards.rb' do
|
23
|
+
subject { file('db/migrate/create_honor_scorecards.rb') }
|
24
|
+
it { should be_a_migration }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Honor do
|
4
|
+
let(:user) { User.create!({ first_name: 'James', last_name: 'Bond' }) }
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
Time.zone = "Central Time (US & Canada)"
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should create an instance attribute for points" do
|
11
|
+
user.should respond_to(:points)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should create an instance attribute for scorecard" do
|
15
|
+
user.should respond_to(:scorecard)
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "Method" do
|
19
|
+
describe "add_points()" do
|
20
|
+
it "should add points through the current user" do
|
21
|
+
expect {
|
22
|
+
user.add_points(25, 'Manual Add', 'Test')
|
23
|
+
}.to change(Honor::Point, :count).by(1)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
describe "subtract_points()" do
|
27
|
+
it "should subtract points through the current user" do
|
28
|
+
expect {
|
29
|
+
user.subtract_points(25, 'Manual Add', 'Test')
|
30
|
+
}.to change(Honor::Point, :count).by(1)
|
31
|
+
end
|
32
|
+
it "should set the value to a negative number" do
|
33
|
+
p = user.subtract_points(25, 'Manual Add', 'Test')
|
34
|
+
p.value.should == -25
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "Scopes" do
|
40
|
+
before(:each) do
|
41
|
+
seed_points(user.id)
|
42
|
+
Timecop.freeze(2012, 11, 5, 16, 00)
|
43
|
+
end
|
44
|
+
|
45
|
+
after(:each) do
|
46
|
+
Timecop.return
|
47
|
+
end
|
48
|
+
|
49
|
+
context "User" do
|
50
|
+
describe "points_total" do
|
51
|
+
it "should return a sum of all of the user's points" do
|
52
|
+
user.points_total.should == 150
|
53
|
+
end
|
54
|
+
it "should return a sum of user points for a given category" do
|
55
|
+
user.points_total('Test 2').should == 75
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "points_today" do
|
60
|
+
it "should return a sum of all of the user's points" do
|
61
|
+
user.points_today.should == 50
|
62
|
+
end
|
63
|
+
it "should return a sum of user points for a given category" do
|
64
|
+
user.points_today('Test 2').should == 25
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "points_this_week" do
|
69
|
+
it "should return a sum of all of the user's points" do
|
70
|
+
user.points_this_week.should == 50
|
71
|
+
end
|
72
|
+
it "should return a sum of user points for a given category" do
|
73
|
+
user.points_this_week('Test 2').should == 25
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "points_this_month" do
|
78
|
+
it "should return a sum of all of the user's points" do
|
79
|
+
user.points_this_month.should == 150
|
80
|
+
end
|
81
|
+
it "should return a sum of user points for a given category" do
|
82
|
+
user.points_this_month('Test 2').should == 75
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "points_this_year" do
|
87
|
+
it "should return a sum of all of the user's points" do
|
88
|
+
user.points_this_year.should == 150
|
89
|
+
end
|
90
|
+
it "should return a sum of user points for a given category" do
|
91
|
+
user.points_this_year('Test 2').should == 75
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
def seed_points(user_id)
|
100
|
+
Timecop.freeze(2012, 1, 15, 12, 05)
|
101
|
+
Honor::Point.create!({user_id: user_id, value: -25, category: 'Test', message: ''})
|
102
|
+
Honor::Point.create!({user_id: user_id, value: -25, category: 'Test 2', message: ''})
|
103
|
+
Timecop.freeze(2012, 11, 5, 12, 05)
|
104
|
+
Honor::Point.create!({user_id: user_id, value: 25, category: 'Test', message: ''})
|
105
|
+
Honor::Point.create!({user_id: user_id, value: 25, category: 'Test 2', message: ''})
|
106
|
+
Timecop.freeze(2012, 11, 12, 12, 05)
|
107
|
+
Honor::Point.create!({user_id: user_id, value: 25, category: 'Test', message: ''})
|
108
|
+
Honor::Point.create!({user_id: user_id, value: 25, category: 'Test 2', message: ''})
|
109
|
+
Timecop.freeze(2012, 11, 19, 12, 05)
|
110
|
+
Honor::Point.create!({user_id: user_id, value: 25, category: 'Test', message: ''})
|
111
|
+
Honor::Point.create!({user_id: user_id, value: 25, category: 'Test 2', message: ''})
|
112
|
+
Timecop.freeze(2012, 12, 4, 12, 05)
|
113
|
+
Honor::Point.create!({user_id: user_id, value: 25, category: 'Test', message: ''})
|
114
|
+
Honor::Point.create!({user_id: user_id, value: 25, category: 'Test 2', message: ''})
|
115
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Honor::Point do
|
4
|
+
let(:user) { User.create!({ first_name: 'James', last_name: 'Bond' }) }
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
Time.zone = "Central Time (US & Canada)"
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should respond to the reciever" do
|
11
|
+
Honor::Point.new.should respond_to(:user)
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "Method" do
|
15
|
+
describe "#give_to()" do
|
16
|
+
it "should add points to a given user" do
|
17
|
+
expect {
|
18
|
+
Honor::Point.give_to(user.id, 25, 'Manual give to', 'Test')
|
19
|
+
}.to change(Honor::Point, :count).by(1)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
describe "#take_from()" do
|
23
|
+
it "should add points to a given user"do
|
24
|
+
expect {
|
25
|
+
Honor::Point.take_from(user.id, 25, 'Manual take away', 'Test')
|
26
|
+
}.to change(Honor::Point, :count).by(1)
|
27
|
+
end
|
28
|
+
it "should set the value to a negative number" do
|
29
|
+
p = Honor::Point.take_from(user.id, 25, 'Manual take away', 'Test')
|
30
|
+
p.value.should == -25
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "Scorecard" do
|
36
|
+
before(:each) do
|
37
|
+
seed_points(user.id)
|
38
|
+
Timecop.freeze(2012, 12, 4, 16, 00)
|
39
|
+
end
|
40
|
+
|
41
|
+
after(:each) do
|
42
|
+
Timecop.return
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should update after Points are saved" do
|
46
|
+
sc = Honor::Scorecard.find_by_user_id(user.id)
|
47
|
+
sc.should_not be_nil
|
48
|
+
sc.daily.should == 50
|
49
|
+
sc.weekly.should == 50
|
50
|
+
sc.monthly.should == 50
|
51
|
+
sc.yearly.should == 150
|
52
|
+
sc.lifetime.should == 150
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "Scopes" do
|
57
|
+
before(:each) do
|
58
|
+
seed_points(user.id)
|
59
|
+
Timecop.freeze(2012, 11, 5, 16, 00)
|
60
|
+
end
|
61
|
+
|
62
|
+
after(:each) do
|
63
|
+
Timecop.return
|
64
|
+
end
|
65
|
+
|
66
|
+
context "Self" do
|
67
|
+
describe "user_points_total" do
|
68
|
+
it "should return a sum of all of the user's points" do
|
69
|
+
Honor::Point.user_points_total(user.id).should == 150
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "user_points_today" do
|
74
|
+
it "should return a sum of all of the user's points" do
|
75
|
+
Honor::Point.user_points_today(user.id).should == 50
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "user_points_this_week" do
|
80
|
+
it "should return a sum of all of the user's points" do
|
81
|
+
Honor::Point.user_points_this_week(user.id).should == 50
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "user_points_this_month" do
|
86
|
+
it "should return a sum of all of the user's points" do
|
87
|
+
Honor::Point.user_points_this_month(user.id).should == 150
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "user_points_this_year" do
|
92
|
+
it "should return a sum of all of the user's points" do
|
93
|
+
Honor::Point.user_points_this_year(user.id).should == 150
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def seed_points(user_id)
|
102
|
+
Timecop.freeze(2012, 1, 15, 12, 05)
|
103
|
+
Honor::Point.create!({user_id: user_id, value: -25, category: 'Test', message: ''})
|
104
|
+
Honor::Point.create!({user_id: user_id, value: -25, category: 'Test 2', message: ''})
|
105
|
+
Timecop.freeze(2012, 11, 5, 12, 05)
|
106
|
+
Honor::Point.create!({user_id: user_id, value: 25, category: 'Test', message: ''})
|
107
|
+
Honor::Point.create!({user_id: user_id, value: 25, category: 'Test 2', message: ''})
|
108
|
+
Timecop.freeze(2012, 11, 12, 12, 05)
|
109
|
+
Honor::Point.create!({user_id: user_id, value: 25, category: 'Test', message: ''})
|
110
|
+
Honor::Point.create!({user_id: user_id, value: 25, category: 'Test 2', message: ''})
|
111
|
+
Timecop.freeze(2012, 11, 19, 12, 05)
|
112
|
+
Honor::Point.create!({user_id: user_id, value: 25, category: 'Test', message: ''})
|
113
|
+
Honor::Point.create!({user_id: user_id, value: 25, category: 'Test 2', message: ''})
|
114
|
+
Timecop.freeze(2012, 12, 4, 12, 05)
|
115
|
+
Honor::Point.create!({user_id: user_id, value: 25, category: 'Test', message: ''})
|
116
|
+
Honor::Point.create!({user_id: user_id, value: 25, category: 'Test 2', message: ''})
|
117
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Honor::Scorecard do
|
4
|
+
let(:valid_user) { FactoryGirl.attributes_for(:user) }
|
5
|
+
let (:valid_friend) { FactoryGirl.attributes_for(:user, username: 'goldfinger', email: Faker::Internet.email) }
|
6
|
+
|
7
|
+
before(:each) do
|
8
|
+
Time.zone = "Central Time (US & Canada)"
|
9
|
+
Timecop.freeze(2011, 12, 4, 16, 00)
|
10
|
+
@user_1 = User.create!({ first_name: 'Bruce', last_name: 'Wayne' })
|
11
|
+
@user_2 = User.create!({ first_name: 'Clark', last_name: 'Kent' })
|
12
|
+
Honor::Scorecard.create!({user_id: @user_1.id, daily: 25, weekly: 100, monthly: 350, yearly: 1250, lifetime: 1375})
|
13
|
+
Honor::Scorecard.create!({user_id: @user_2.id, daily: 50, weekly: 100, monthly: 350, yearly: 1250, lifetime: 1375})
|
14
|
+
Timecop.return
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should respond to the reciever" do
|
18
|
+
Honor::Scorecard.new.should respond_to(:user)
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "Ranking" do
|
22
|
+
it "should produce rankings with correctly calculated tied positions" do
|
23
|
+
user_ids = [@user_2.id, @user_1.id]
|
24
|
+
daily_rankings = Honor::Scorecard.leaderboard(user_ids, rank_by: 'daily', sort_direction: 'desc')
|
25
|
+
daily_rankings[0].position.should == 1
|
26
|
+
daily_rankings[1].position.should == 2
|
27
|
+
weekly_rankings = Honor::Scorecard.leaderboard(user_ids, rank_by: 'weekly', sort_direction: 'desc')
|
28
|
+
weekly_rankings[0].position.should == 1
|
29
|
+
weekly_rankings[1].position.should == 1
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
describe "Methods" do
|
34
|
+
describe "#reset_daily_scores" do
|
35
|
+
it "should set the daily attribute to 0 if no updates have been made today" do
|
36
|
+
Honor::Scorecard.reset_daily_scores
|
37
|
+
sc = Honor::Scorecard.find_by_user_id(@user_1.id)
|
38
|
+
sc.daily.should == 0
|
39
|
+
sc.weekly.should == 100
|
40
|
+
sc.monthly.should == 350
|
41
|
+
sc.yearly.should == 1250
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should NOT change the daily attribute if an update was made today" do
|
45
|
+
sc_before = Honor::Scorecard.find_by_user_id(@user_1.id)
|
46
|
+
sc_before.update_attribute(:daily, 30)
|
47
|
+
Honor::Scorecard.reset_daily_scores
|
48
|
+
sc_after = Honor::Scorecard.find_by_user_id(@user_1.id)
|
49
|
+
sc_after.daily.should == 30
|
50
|
+
sc_after.weekly.should == 100
|
51
|
+
sc_after.monthly.should == 350
|
52
|
+
sc_after.yearly.should == 1250
|
53
|
+
end
|
54
|
+
end
|
55
|
+
describe "#reset_weekly_scores" do
|
56
|
+
it "should set the weekly attribute to 0 if no updates have been made this week" do
|
57
|
+
Honor::Scorecard.reset_weekly_scores
|
58
|
+
sc = Honor::Scorecard.find_by_user_id(@user_1.id)
|
59
|
+
sc.daily.should == 25
|
60
|
+
sc.weekly.should == 0
|
61
|
+
sc.monthly.should == 350
|
62
|
+
sc.yearly.should == 1250
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should NOT change the weekly attribute if an update was made this week" do
|
66
|
+
sc_before = Honor::Scorecard.find_by_user_id(@user_1.id)
|
67
|
+
sc_before.update_attribute(:weekly, 125)
|
68
|
+
Honor::Scorecard.reset_weekly_scores
|
69
|
+
sc_after = Honor::Scorecard.find_by_user_id(@user_1.id)
|
70
|
+
sc_after.daily.should == 25
|
71
|
+
sc_after.weekly.should == 125
|
72
|
+
sc_after.monthly.should == 350
|
73
|
+
sc_after.yearly.should == 1250
|
74
|
+
end
|
75
|
+
end
|
76
|
+
describe "#reset_monthly_scores" do
|
77
|
+
it "should set the monthly attribute to 0 if no updates have been made this month" do
|
78
|
+
Honor::Scorecard.reset_monthly_scores
|
79
|
+
sc = Honor::Scorecard.find_by_user_id(@user_1.id)
|
80
|
+
sc.daily.should == 25
|
81
|
+
sc.weekly.should == 100
|
82
|
+
sc.monthly.should == 0
|
83
|
+
sc.yearly.should == 1250
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should NOT change the monthly attribute if an update was made this month" do
|
87
|
+
sc_before = Honor::Scorecard.find_by_user_id(@user_1.id)
|
88
|
+
sc_before.update_attribute(:monthly, 400)
|
89
|
+
Honor::Scorecard.reset_monthly_scores
|
90
|
+
sc_after = Honor::Scorecard.find_by_user_id(@user_1.id)
|
91
|
+
sc_after.daily.should == 25
|
92
|
+
sc_after.weekly.should == 100
|
93
|
+
sc_after.monthly.should == 400
|
94
|
+
sc_after.yearly.should == 1250
|
95
|
+
end
|
96
|
+
end
|
97
|
+
describe "#reset_yearly_scores" do
|
98
|
+
it "should set the yearly attribute to 0 if no updates have been made this year" do
|
99
|
+
Honor::Scorecard.reset_yearly_scores
|
100
|
+
sc = Honor::Scorecard.find_by_user_id(@user_1.id)
|
101
|
+
sc.daily.should == 25
|
102
|
+
sc.weekly.should == 100
|
103
|
+
sc.monthly.should == 350
|
104
|
+
sc.yearly.should == 0
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should NOT change the yearly attribute if an update was made this year" do
|
108
|
+
sc_before = Honor::Scorecard.find_by_user_id(@user_1.id)
|
109
|
+
sc_before.update_attribute(:yearly, 1300)
|
110
|
+
Honor::Scorecard.reset_yearly_scores
|
111
|
+
sc_after = Honor::Scorecard.find_by_user_id(@user_1.id)
|
112
|
+
sc_after.daily.should == 25
|
113
|
+
sc_after.weekly.should == 100
|
114
|
+
sc_after.monthly.should == 350
|
115
|
+
sc_after.yearly.should == 1300
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'honor'
|
3
|
+
require 'ammeter/init'
|
4
|
+
require 'timecop'
|
5
|
+
require 'database_cleaner'
|
6
|
+
|
7
|
+
# set adapter to use, default is sqlite3
|
8
|
+
# to use an alternative adapter run => rake spec DB='postgresql'
|
9
|
+
db_name = ENV['DB'] || 'sqlite3'
|
10
|
+
database_yml = File.expand_path('../config/database.yml', __FILE__)
|
11
|
+
|
12
|
+
if File.exists?(database_yml)
|
13
|
+
active_record_configuration = YAML.load_file(database_yml)
|
14
|
+
|
15
|
+
ActiveRecord::Base.configurations = active_record_configuration
|
16
|
+
config = ActiveRecord::Base.configurations[db_name]
|
17
|
+
|
18
|
+
begin
|
19
|
+
ActiveRecord::Base.establish_connection(db_name)
|
20
|
+
ActiveRecord::Base.connection
|
21
|
+
rescue
|
22
|
+
case db_name
|
23
|
+
when /mysql/
|
24
|
+
ActiveRecord::Base.establish_connection(config.merge('database' => nil))
|
25
|
+
ActiveRecord::Base.connection.create_database(config['database'], {:charset => 'utf8', :collation => 'utf8_unicode_ci'})
|
26
|
+
when 'postgresql'
|
27
|
+
ActiveRecord::Base.establish_connection(config.merge('database' => 'postgres', 'schema_search_path' => 'public'))
|
28
|
+
ActiveRecord::Base.connection.create_database(config['database'], config.merge('encoding' => 'utf8'))
|
29
|
+
end
|
30
|
+
|
31
|
+
ActiveRecord::Base.establish_connection(config)
|
32
|
+
end
|
33
|
+
|
34
|
+
ActiveRecord::Base.logger = Logger.new(File.join(File.dirname(__FILE__), "debug.log"))
|
35
|
+
ActiveRecord::Base.default_timezone = :utc
|
36
|
+
|
37
|
+
ActiveRecord::Base.silence do
|
38
|
+
ActiveRecord::Migration.verbose = false
|
39
|
+
|
40
|
+
load(File.expand_path('../config/schema.rb', __FILE__))
|
41
|
+
load(File.expand_path('../config/models.rb', __FILE__))
|
42
|
+
end
|
43
|
+
|
44
|
+
else
|
45
|
+
raise "Please create #{database_yml} first to configure your database. Take a look at: spec/config/#{database_yml}.sample"
|
46
|
+
end
|
47
|
+
|
48
|
+
RSpec.configure do |config|
|
49
|
+
config.mock_with :rspec
|
50
|
+
|
51
|
+
config.before(:suite) do
|
52
|
+
DatabaseCleaner.strategy = :transaction
|
53
|
+
DatabaseCleaner.clean_with(:truncation)
|
54
|
+
end
|
55
|
+
|
56
|
+
config.before(:each) do
|
57
|
+
DatabaseCleaner.start
|
58
|
+
end
|
59
|
+
|
60
|
+
config.after(:each) do
|
61
|
+
DatabaseCleaner.clean
|
62
|
+
end
|
63
|
+
end
|
metadata
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: honor
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jeremy Ward
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-03-03 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rails
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3.0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rspec
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: ammeter
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: supermodel
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: database_cleaner
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
- !ruby/object:Gem::Dependency
|
95
|
+
name: timecop
|
96
|
+
requirement: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ! '>='
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
description: Adds support for common gamification features such as points, leaderboards,
|
111
|
+
and achievements.
|
112
|
+
email:
|
113
|
+
- jrmy.ward@gmail.com
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- .gitignore
|
119
|
+
- .rspec
|
120
|
+
- CHANGELOG.md
|
121
|
+
- Gemfile
|
122
|
+
- LICENSE.txt
|
123
|
+
- README.md
|
124
|
+
- Rakefile
|
125
|
+
- honor.gemspec
|
126
|
+
- honor.sqlite3
|
127
|
+
- lib/generators/install_generator.rb
|
128
|
+
- lib/generators/templates/active_record/create_points.rb
|
129
|
+
- lib/generators/templates/active_record/create_scorecards.rb
|
130
|
+
- lib/honor.rb
|
131
|
+
- lib/honor/model_additions.rb
|
132
|
+
- lib/honor/point.rb
|
133
|
+
- lib/honor/scorecard.rb
|
134
|
+
- lib/honor/version.rb
|
135
|
+
- rails/init.rb
|
136
|
+
- spec/config/database.yml.sample
|
137
|
+
- spec/config/models.rb
|
138
|
+
- spec/config/schema.rb
|
139
|
+
- spec/generators/install_generator_spec.rb
|
140
|
+
- spec/honor/model_additions_spec.rb
|
141
|
+
- spec/honor/point_spec.rb
|
142
|
+
- spec/honor/scorecard_spec.rb
|
143
|
+
- spec/spec_helper.rb
|
144
|
+
homepage: https://github.com/jrmyward/honor
|
145
|
+
licenses: []
|
146
|
+
post_install_message:
|
147
|
+
rdoc_options: []
|
148
|
+
require_paths:
|
149
|
+
- lib
|
150
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
151
|
+
none: false
|
152
|
+
requirements:
|
153
|
+
- - ! '>='
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
version: '0'
|
156
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
157
|
+
none: false
|
158
|
+
requirements:
|
159
|
+
- - ! '>='
|
160
|
+
- !ruby/object:Gem::Version
|
161
|
+
version: '0'
|
162
|
+
requirements: []
|
163
|
+
rubyforge_project:
|
164
|
+
rubygems_version: 1.8.23
|
165
|
+
signing_key:
|
166
|
+
specification_version: 3
|
167
|
+
summary: General gamification-centric reputation system for Rails Applications.
|
168
|
+
test_files:
|
169
|
+
- spec/config/database.yml.sample
|
170
|
+
- spec/config/models.rb
|
171
|
+
- spec/config/schema.rb
|
172
|
+
- spec/generators/install_generator_spec.rb
|
173
|
+
- spec/honor/model_additions_spec.rb
|
174
|
+
- spec/honor/point_spec.rb
|
175
|
+
- spec/honor/scorecard_spec.rb
|
176
|
+
- spec/spec_helper.rb
|
177
|
+
has_rdoc:
|