gamification 0.0.2 → 1.0.0
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 +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
|