gamification 0.0.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/gamification/application_controller.rb +1 -1
- data/app/controllers/gamification/rewards_controller.rb +46 -0
- data/app/helpers/gamification/application_helper.rb +24 -0
- data/app/helpers/gamification/rewards_helper.rb +20 -0
- data/app/models/gamification/goal.rb +5 -0
- data/app/models/gamification/medal.rb +5 -0
- data/app/models/gamification/reward.rb +5 -0
- data/app/uploaders/gamification/image_uploader.rb +47 -0
- data/app/views/gamification/rewards/_presentation.html.erb +7 -0
- data/app/views/gamification/rewards/_reward.html.erb +9 -0
- data/app/views/gamification/scorings/create.html.erb +2 -0
- data/config/initializers/routing.rb +15 -0
- data/config/locales/en.yml +3 -0
- data/config/locales/nb.yml +35 -0
- data/config/routes.rb +1 -0
- data/db/migrate/20140310081749_rename_everything.rb +10 -0
- data/db/migrate/20140313134259_create_gamification_medals.rb +11 -0
- data/db/migrate/20140314132611_add_description_to_gamification_medals.rb +5 -0
- data/db/migrate/20140315142524_rename_gamification_tasks_to_goals.rb +7 -0
- data/db/migrate/20140318220723_add_seen_at_to_gamification_rewards.rb +9 -0
- data/lib/gamification.rb +1 -0
- data/lib/gamification/activerecord.rb +13 -0
- data/lib/gamification/concerns.rb +2 -0
- data/lib/gamification/concerns/models.rb +3 -2
- data/lib/gamification/concerns/models/goal.rb +44 -0
- data/lib/gamification/concerns/models/medal.rb +13 -0
- data/lib/gamification/concerns/models/reward.rb +33 -0
- data/lib/gamification/concerns/rewardable.rb +12 -0
- data/lib/gamification/concerns/rewarding.rb +7 -0
- data/lib/gamification/engine.rb +10 -0
- data/lib/gamification/version.rb +1 -1
- data/spec/controllers/gamification/rewards_controller_spec.rb +57 -0
- data/spec/dummy/app/assets/javascripts/articles.js +2 -0
- data/spec/dummy/app/assets/stylesheets/articles.css +4 -0
- data/spec/dummy/app/controllers/articles_controller.rb +5 -0
- data/spec/dummy/app/helpers/articles_helper.rb +2 -0
- data/spec/dummy/app/models/article.rb +2 -2
- data/spec/dummy/app/models/user.rb +2 -2
- data/spec/dummy/app/views/articles/show.html.erb +1 -0
- data/spec/dummy/config/routes.rb +1 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/schema.rb +25 -12
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +3893 -1707
- data/spec/dummy/log/test.log +22080 -2888
- data/spec/dummy/spec/controllers/articles_controller_spec.rb +15 -0
- data/spec/dummy/spec/helpers/articles_helper_spec.rb +14 -0
- data/spec/dummy/spec/models/article_spec.rb +0 -1
- data/spec/dummy/spec/models/user_spec.rb +0 -1
- data/spec/dummy/spec/views/articles/show.html.erb_spec.rb +4 -0
- data/spec/factories/gamification_goals.rb +14 -0
- data/spec/factories/gamification_medals.rb +10 -0
- data/spec/factories/gamification_rewards.rb +8 -0
- data/spec/helpers/gamification/application_helper_spec.rb +14 -0
- data/spec/helpers/gamification/rewards_helper_spec.rb +18 -0
- data/spec/lib/gamification/concerns/rewardable_spec.rb +17 -0
- data/spec/models/gamification/goal_spec.rb +65 -0
- data/spec/models/gamification/medal_spec.rb +6 -0
- data/spec/models/gamification/reward_spec.rb +102 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/views/gamification/rewards/_presentation.html.erb_spec.rb +23 -0
- metadata +173 -28
- data/MIT-LICENSE +0 -20
- data/app/models/gamification/scoring.rb +0 -5
- data/app/models/gamification/task.rb +0 -5
- data/app/views/layouts/gamification/application.html.erb +0 -14
- data/lib/gamification/concerns/models/scoring.rb +0 -8
- data/lib/gamification/concerns/models/task.rb +0 -50
- data/spec/factories/gamification_scorings.rb +0 -8
- data/spec/factories/gamification_tasks.rb +0 -8
- data/spec/models/gamification/scoring_spec.rb +0 -7
- data/spec/models/gamification/task_spec.rb +0 -77
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e19cbb64dd5e16388ffd8fd52c48622bc621569b
|
4
|
+
data.tar.gz: 07ebce2bd2b9751f6e21cd0dc6c5e59c5da9d33b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 883c53868ccb30f0eced71df269ca966cd27d19f05e30cae810cd6458eb577ed35e0c9858992e21d4ab2f992e37991ab50979835bfccb1a66dcdbbf32021f65a
|
7
|
+
data.tar.gz: 1a34ab955a1a55eae840c0f2d5546f81cc2a7ee8605970b456642b73a6fcf309386c4322d493e49d4a40844ca117e9064ffaa8772de50817fae183b93159a97f
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require_dependency "gamification/application_controller"
|
2
|
+
|
3
|
+
module Gamification
|
4
|
+
class RewardsController < ApplicationController
|
5
|
+
def create
|
6
|
+
if rewarding.is_a? ::Gamification::Goal
|
7
|
+
rewarding.complete_for rewardable
|
8
|
+
else
|
9
|
+
rewarding.goals.each do |goal|
|
10
|
+
goal.complete_for rewardable
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
respond_to do |format|
|
15
|
+
format.json { render json: {}, status: :created }
|
16
|
+
format.html { redirect_to redirect_url }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def redirect_url
|
23
|
+
params[:redirect_url] || request.env['HTTP_REFERER']
|
24
|
+
end
|
25
|
+
|
26
|
+
def rewarding
|
27
|
+
rewarding_model.find reward_params[:rewarding_id]
|
28
|
+
end
|
29
|
+
|
30
|
+
def rewardable
|
31
|
+
rewardable_model.find reward_params[:rewardable_id]
|
32
|
+
end
|
33
|
+
|
34
|
+
def rewarding_model
|
35
|
+
reward_params[:rewarding_type].constantize
|
36
|
+
end
|
37
|
+
|
38
|
+
def rewardable_model
|
39
|
+
reward_params[:rewardable_type].constantize
|
40
|
+
end
|
41
|
+
|
42
|
+
def reward_params
|
43
|
+
params.require(:reward).permit(:rewarding_type, :rewarding_id, :rewardable_type, :rewardable_id)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -1,4 +1,28 @@
|
|
1
1
|
module Gamification
|
2
2
|
module ApplicationHelper
|
3
|
+
|
4
|
+
# Create a form to reward someone for something.
|
5
|
+
#
|
6
|
+
# rewardable - A model that is rewardable (e.g. a user)
|
7
|
+
# options - A Hash of options:
|
8
|
+
# :for - A model that is rewarding (e.g. an article)
|
9
|
+
# :redirect - A String describing a URL to redirect to.
|
10
|
+
def reward rewardable, options
|
11
|
+
rewarding = options[:for]
|
12
|
+
redirect = options[:redirect]
|
13
|
+
|
14
|
+
form_tag Gamification::Engine.routes.url_helpers.rewards_path, method: :post do
|
15
|
+
concat hidden_field_tag 'reward[rewarding_type]', rewarding.class.name
|
16
|
+
concat hidden_field_tag 'reward[rewarding_id]', rewarding.id
|
17
|
+
concat hidden_field_tag 'reward[rewardable_type]', rewardable.class.name
|
18
|
+
concat hidden_field_tag 'reward[rewardable_id]', rewardable.id
|
19
|
+
|
20
|
+
if redirect
|
21
|
+
concat hidden_field_tag 'redirect_url', redirect
|
22
|
+
end
|
23
|
+
|
24
|
+
concat submit_tag I18n.t 'gamification.complete'
|
25
|
+
end
|
26
|
+
end
|
3
27
|
end
|
4
28
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Gamification
|
2
|
+
module RewardsHelper
|
3
|
+
|
4
|
+
# Present unseen rewards for the given user.
|
5
|
+
#
|
6
|
+
# options - A Hash of options:
|
7
|
+
# for: A rewardable model.
|
8
|
+
#
|
9
|
+
# Returns HTML.
|
10
|
+
def present_rewards options
|
11
|
+
rewardable = options[:for]
|
12
|
+
rewards = rewardable.rewards.unseen
|
13
|
+
presentation = render partial: 'gamification/rewards/presentation', locals: { rewards: rewards }
|
14
|
+
|
15
|
+
rewards.see
|
16
|
+
|
17
|
+
presentation
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'carrierwave'
|
3
|
+
|
4
|
+
class Gamification::ImageUploader < CarrierWave::Uploader::Base
|
5
|
+
|
6
|
+
# Include MiniMagick support
|
7
|
+
include CarrierWave::MiniMagick
|
8
|
+
|
9
|
+
# Override the directory where uploaded files will be stored.
|
10
|
+
# This is a sensible default for uploaders that are meant to be mounted:
|
11
|
+
def store_dir
|
12
|
+
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
|
13
|
+
end
|
14
|
+
|
15
|
+
# Provide a default URL as a default if there hasn't been a file uploaded:
|
16
|
+
# def default_url
|
17
|
+
# # For Rails 3.1+ asset pipeline compatibility:
|
18
|
+
# # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
|
19
|
+
#
|
20
|
+
# "/images/fallback/" + [version_name, "default.png"].compact.join('_')
|
21
|
+
# end
|
22
|
+
|
23
|
+
# Process files as they are uploaded:
|
24
|
+
# process :scale => [200, 300]
|
25
|
+
#
|
26
|
+
# def scale(width, height)
|
27
|
+
# # do something
|
28
|
+
# end
|
29
|
+
|
30
|
+
# Create different versions of your uploaded files:
|
31
|
+
version :small do
|
32
|
+
process :resize_to_fit => [150, 150]
|
33
|
+
end
|
34
|
+
|
35
|
+
# Add a white list of extensions which are allowed to be uploaded.
|
36
|
+
# For images you might use something like this:
|
37
|
+
# def extension_white_list
|
38
|
+
# %w(jpg jpeg gif png)
|
39
|
+
# end
|
40
|
+
|
41
|
+
# Override the filename of the uploaded files:
|
42
|
+
# Avoid using model.id or version_name here, see uploader/store.rb for details.
|
43
|
+
# def filename
|
44
|
+
# "something.jpg" if original_filename
|
45
|
+
# end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<% if reward.medal %>
|
2
|
+
<div class="medal">
|
3
|
+
<div class="image"><%= image_tag reward.medal.image %></div>
|
4
|
+
<div class="name"><%= reward.medal.name %></div>
|
5
|
+
<div class="description"><%= reward.medal.description %></div>
|
6
|
+
</div>
|
7
|
+
<% end %>
|
8
|
+
|
9
|
+
<div class="points"><%= reward.points %></div>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Gamification
|
2
|
+
module ApplicationHelper
|
3
|
+
|
4
|
+
# Knowledge base uses the layout of the client application, which causes Rails' url helpers to get confused
|
5
|
+
# and require you to prepend 'main_app' to your own routes. This hack allows developers to keep referring to
|
6
|
+
# routes without a prefix by sending undefined routes to 'main_app' before failing.
|
7
|
+
def method_missing(method, *args, &block)
|
8
|
+
if (method.to_s.end_with?('_path') || method.to_s.end_with?('_url')) && main_app.respond_to?(method)
|
9
|
+
main_app.send(method, *args)
|
10
|
+
else
|
11
|
+
super
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
nb:
|
2
|
+
activerecord:
|
3
|
+
models:
|
4
|
+
gamification/goal:
|
5
|
+
one: Mål
|
6
|
+
other: Mål
|
7
|
+
gamification/reward:
|
8
|
+
one: Belønning
|
9
|
+
other: Belønninger
|
10
|
+
gamification/medal:
|
11
|
+
one: Medalje
|
12
|
+
other: Medaljer
|
13
|
+
attributes:
|
14
|
+
common: &common
|
15
|
+
created_at: Opprettet
|
16
|
+
updated_at: Sist oppdatert
|
17
|
+
gamification/goal:
|
18
|
+
<<: *common
|
19
|
+
rewarding: Mål for
|
20
|
+
rewarding_id: Mål for
|
21
|
+
rewarding_type: Mål for
|
22
|
+
points: Poeng
|
23
|
+
gamification/reward:
|
24
|
+
<<: *common
|
25
|
+
goal: Mål
|
26
|
+
rewardable: Mottaker
|
27
|
+
rewardable_id: Motakker
|
28
|
+
rewardable_type: Mottaker
|
29
|
+
seen_at: Sett
|
30
|
+
gamification/medal:
|
31
|
+
<<: *common
|
32
|
+
goal: Mål
|
33
|
+
name: Navn
|
34
|
+
image: Bilde
|
35
|
+
description: Beskrivelse
|
data/config/routes.rb
CHANGED
@@ -0,0 +1,10 @@
|
|
1
|
+
class RenameEverything < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
rename_table :gamification_scorings, :gamification_rewards
|
4
|
+
rename_column :gamification_rewards, :subjectable_id, :rewardable_id
|
5
|
+
rename_column :gamification_rewards, :subjectable_type, :rewardable_type
|
6
|
+
|
7
|
+
rename_column :gamification_tasks, :taskable_id, :rewarding_id
|
8
|
+
rename_column :gamification_tasks, :taskable_type, :rewarding_type
|
9
|
+
end
|
10
|
+
end
|
data/lib/gamification.rb
CHANGED
@@ -0,0 +1,13 @@
|
|
1
|
+
module Gamification::ActiveRecord
|
2
|
+
module Extensions
|
3
|
+
def rewarding
|
4
|
+
include Gamification::Concerns::Rewarding
|
5
|
+
end
|
6
|
+
|
7
|
+
def rewardable
|
8
|
+
include Gamification::Concerns::Rewardable
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
::ActiveRecord::Base.send :extend, Gamification::ActiveRecord::Extensions if defined?(ActiveRecord)
|
@@ -1,4 +1,5 @@
|
|
1
1
|
module Gamification::Concerns::Models
|
2
|
-
require "gamification/concerns/models/
|
3
|
-
require "gamification/concerns/models/
|
2
|
+
require "gamification/concerns/models/goal"
|
3
|
+
require "gamification/concerns/models/reward"
|
4
|
+
require "gamification/concerns/models/medal"
|
4
5
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Gamification::Concerns::Models::Goal
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
belongs_to :rewarding, polymorphic: true
|
6
|
+
has_one :medal, dependent: :destroy
|
7
|
+
has_many :rewards, dependent: :destroy
|
8
|
+
|
9
|
+
accepts_nested_attributes_for :medal, allow_destroy: true, reject_if: :all_blank
|
10
|
+
|
11
|
+
# TODO: These should be SQL. But that's hard.
|
12
|
+
scope :completed_by, ->(subject) { all.select { |goal| goal.completed_by? subject }}
|
13
|
+
scope :incomplete_by, ->(subject) { all.reject { |goal| goal.completed_by? subject }}
|
14
|
+
|
15
|
+
# Determine whether the given subject has completed the goal.
|
16
|
+
#
|
17
|
+
# subject - An ActiveRecord model that can receive rewards.
|
18
|
+
def completed_by? subject
|
19
|
+
!!reward_for(subject)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Complete the goal for the given subject.
|
23
|
+
#
|
24
|
+
# subject - An ActiveRecord model that can receive rewards.
|
25
|
+
def complete_for subject
|
26
|
+
if completed_by? subject
|
27
|
+
raise Completed, "#{self} is already completed for #{subject}"
|
28
|
+
else
|
29
|
+
::Gamification::Reward.create! goal: self, rewardable: subject
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
# Find the Reward for the given subject.
|
36
|
+
#
|
37
|
+
# subject - A rewardable model.
|
38
|
+
def reward_for rewardable
|
39
|
+
rewards.find_by rewardable: rewardable
|
40
|
+
end
|
41
|
+
|
42
|
+
class Completed < StandardError; end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Gamification::Concerns::Models::Reward
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
belongs_to :goal, class_name: 'Gamification::Goal'
|
6
|
+
belongs_to :rewardable, polymorphic: true, inverse_of: :rewards
|
7
|
+
|
8
|
+
scope :unseen, -> { where seen_at: nil }
|
9
|
+
scope :seen, -> { where.not seen_at: nil }
|
10
|
+
|
11
|
+
scope :with_medals, -> { all.select &:medal }
|
12
|
+
scope :without_medals, -> { all.reject &:medal }
|
13
|
+
|
14
|
+
validates :rewardable_id, uniqueness: { scope: [:rewardable_type, :goal] }
|
15
|
+
|
16
|
+
delegate :points, to: :goal
|
17
|
+
delegate :medal, to: :goal
|
18
|
+
|
19
|
+
def see
|
20
|
+
touch :seen_at
|
21
|
+
end
|
22
|
+
|
23
|
+
def seen?
|
24
|
+
!!seen_at
|
25
|
+
end
|
26
|
+
|
27
|
+
class << self
|
28
|
+
def see
|
29
|
+
all.map { |reward| reward.see }
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|