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.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/gamification/application_controller.rb +1 -1
  3. data/app/controllers/gamification/rewards_controller.rb +46 -0
  4. data/app/helpers/gamification/application_helper.rb +24 -0
  5. data/app/helpers/gamification/rewards_helper.rb +20 -0
  6. data/app/models/gamification/goal.rb +5 -0
  7. data/app/models/gamification/medal.rb +5 -0
  8. data/app/models/gamification/reward.rb +5 -0
  9. data/app/uploaders/gamification/image_uploader.rb +47 -0
  10. data/app/views/gamification/rewards/_presentation.html.erb +7 -0
  11. data/app/views/gamification/rewards/_reward.html.erb +9 -0
  12. data/app/views/gamification/scorings/create.html.erb +2 -0
  13. data/config/initializers/routing.rb +15 -0
  14. data/config/locales/en.yml +3 -0
  15. data/config/locales/nb.yml +35 -0
  16. data/config/routes.rb +1 -0
  17. data/db/migrate/20140310081749_rename_everything.rb +10 -0
  18. data/db/migrate/20140313134259_create_gamification_medals.rb +11 -0
  19. data/db/migrate/20140314132611_add_description_to_gamification_medals.rb +5 -0
  20. data/db/migrate/20140315142524_rename_gamification_tasks_to_goals.rb +7 -0
  21. data/db/migrate/20140318220723_add_seen_at_to_gamification_rewards.rb +9 -0
  22. data/lib/gamification.rb +1 -0
  23. data/lib/gamification/activerecord.rb +13 -0
  24. data/lib/gamification/concerns.rb +2 -0
  25. data/lib/gamification/concerns/models.rb +3 -2
  26. data/lib/gamification/concerns/models/goal.rb +44 -0
  27. data/lib/gamification/concerns/models/medal.rb +13 -0
  28. data/lib/gamification/concerns/models/reward.rb +33 -0
  29. data/lib/gamification/concerns/rewardable.rb +12 -0
  30. data/lib/gamification/concerns/rewarding.rb +7 -0
  31. data/lib/gamification/engine.rb +10 -0
  32. data/lib/gamification/version.rb +1 -1
  33. data/spec/controllers/gamification/rewards_controller_spec.rb +57 -0
  34. data/spec/dummy/app/assets/javascripts/articles.js +2 -0
  35. data/spec/dummy/app/assets/stylesheets/articles.css +4 -0
  36. data/spec/dummy/app/controllers/articles_controller.rb +5 -0
  37. data/spec/dummy/app/helpers/articles_helper.rb +2 -0
  38. data/spec/dummy/app/models/article.rb +2 -2
  39. data/spec/dummy/app/models/user.rb +2 -2
  40. data/spec/dummy/app/views/articles/show.html.erb +1 -0
  41. data/spec/dummy/config/routes.rb +1 -0
  42. data/spec/dummy/db/development.sqlite3 +0 -0
  43. data/spec/dummy/db/schema.rb +25 -12
  44. data/spec/dummy/db/test.sqlite3 +0 -0
  45. data/spec/dummy/log/development.log +3893 -1707
  46. data/spec/dummy/log/test.log +22080 -2888
  47. data/spec/dummy/spec/controllers/articles_controller_spec.rb +15 -0
  48. data/spec/dummy/spec/helpers/articles_helper_spec.rb +14 -0
  49. data/spec/dummy/spec/models/article_spec.rb +0 -1
  50. data/spec/dummy/spec/models/user_spec.rb +0 -1
  51. data/spec/dummy/spec/views/articles/show.html.erb_spec.rb +4 -0
  52. data/spec/factories/gamification_goals.rb +14 -0
  53. data/spec/factories/gamification_medals.rb +10 -0
  54. data/spec/factories/gamification_rewards.rb +8 -0
  55. data/spec/helpers/gamification/application_helper_spec.rb +14 -0
  56. data/spec/helpers/gamification/rewards_helper_spec.rb +18 -0
  57. data/spec/lib/gamification/concerns/rewardable_spec.rb +17 -0
  58. data/spec/models/gamification/goal_spec.rb +65 -0
  59. data/spec/models/gamification/medal_spec.rb +6 -0
  60. data/spec/models/gamification/reward_spec.rb +102 -0
  61. data/spec/spec_helper.rb +2 -0
  62. data/spec/views/gamification/rewards/_presentation.html.erb_spec.rb +23 -0
  63. metadata +173 -28
  64. data/MIT-LICENSE +0 -20
  65. data/app/models/gamification/scoring.rb +0 -5
  66. data/app/models/gamification/task.rb +0 -5
  67. data/app/views/layouts/gamification/application.html.erb +0 -14
  68. data/lib/gamification/concerns/models/scoring.rb +0 -8
  69. data/lib/gamification/concerns/models/task.rb +0 -50
  70. data/spec/factories/gamification_scorings.rb +0 -8
  71. data/spec/factories/gamification_tasks.rb +0 -8
  72. data/spec/models/gamification/scoring_spec.rb +0 -7
  73. data/spec/models/gamification/task_spec.rb +0 -77
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ff0f5c1e1337b6cf63206c829cc642f095b94621
4
- data.tar.gz: c264313d9ed05c33287888e0e9e81ebc99ba4f58
3
+ metadata.gz: e19cbb64dd5e16388ffd8fd52c48622bc621569b
4
+ data.tar.gz: 07ebce2bd2b9751f6e21cd0dc6c5e59c5da9d33b
5
5
  SHA512:
6
- metadata.gz: fb23fabcb4db26e71e7001fb6f2c0e65c8fe2ebd2df47f0acf7b02c624a7b2ea9b3df665672094d1dc8e6b43e733fbd61221e13b07265dff1730d75a2313b6e3
7
- data.tar.gz: a344fdd6a6534e4065eaf6794d8e520bbf8ff9db4fd6e757f27a2834eb254928ac5b4b91b16f6516cd4798d6370f10870843575e2c668c0bebf60b62c07c160f
6
+ metadata.gz: 883c53868ccb30f0eced71df269ca966cd27d19f05e30cae810cd6458eb577ed35e0c9858992e21d4ab2f992e37991ab50979835bfccb1a66dcdbbf32021f65a
7
+ data.tar.gz: 1a34ab955a1a55eae840c0f2d5546f81cc2a7ee8605970b456642b73a6fcf309386c4322d493e49d4a40844ca117e9064ffaa8772de50817fae183b93159a97f
@@ -1,4 +1,4 @@
1
1
  module Gamification
2
- class ApplicationController < ActionController::Base
2
+ class ApplicationController < ::ApplicationController
3
3
  end
4
4
  end
@@ -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,5 @@
1
+ module Gamification
2
+ class Goal < ::ActiveRecord::Base
3
+ include Concerns::Models::Goal
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Gamification
2
+ class Medal < ::ActiveRecord::Base
3
+ include Concerns::Models::Medal
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module Gamification
2
+ class Reward < ::ActiveRecord::Base
3
+ include Concerns::Models::Reward
4
+ end
5
+ 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,7 @@
1
+ <% if rewards.any? %>
2
+ <div class="reward-presentation">
3
+ <% rewards.each do |reward| %>
4
+ <%= render reward %>
5
+ <% end %>
6
+ </div>
7
+ <% 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,2 @@
1
+ <h1>Scorings#create</h1>
2
+ <p>Find me in app/views/gamification/scorings/create.html.erb</p>
@@ -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,3 @@
1
+ en:
2
+ gamification:
3
+ complete: 'Complete goals'
@@ -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
@@ -1,2 +1,3 @@
1
1
  Gamification::Engine.routes.draw do
2
+ resources :rewards, only: [:create]
2
3
  end
@@ -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
@@ -0,0 +1,11 @@
1
+ class CreateGamificationMedals < ActiveRecord::Migration
2
+ def change
3
+ create_table :gamification_medals do |t|
4
+ t.references :task, index: true
5
+ t.string :name
6
+ t.string :image
7
+
8
+ t.timestamps
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ class AddDescriptionToGamificationMedals < ActiveRecord::Migration
2
+ def change
3
+ add_column :gamification_medals, :description, :text
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ class RenameGamificationTasksToGoals < ActiveRecord::Migration
2
+ def change
3
+ rename_table :gamification_tasks, :gamification_goals
4
+ rename_column :gamification_rewards, :task_id, :goal_id
5
+ rename_column :gamification_medals, :task_id, :goal_id
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ class AddSeenAtToGamificationRewards < ActiveRecord::Migration
2
+ def change
3
+ change_table :gamification_rewards do |t|
4
+ t.datetime :seen_at
5
+ end
6
+
7
+ add_index :gamification_rewards, :seen_at, name: 'index_gamification_rewards_on_seen_at'
8
+ end
9
+ end
data/lib/gamification.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "gamification/engine"
2
2
  require "gamification/concerns"
3
+ require "gamification/activerecord"
3
4
 
4
5
  module Gamification
5
6
  end
@@ -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,3 +1,5 @@
1
1
  module Gamification::Concerns
2
2
  require "gamification/concerns/models"
3
+ require "gamification/concerns/rewarding"
4
+ require "gamification/concerns/rewardable"
3
5
  end
@@ -1,4 +1,5 @@
1
1
  module Gamification::Concerns::Models
2
- require "gamification/concerns/models/task"
3
- require "gamification/concerns/models/scoring"
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,13 @@
1
+ require 'carrierwave'
2
+
3
+ module Gamification
4
+ module Concerns::Models::Medal
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ belongs_to :goal
9
+
10
+ mount_uploader :image, ::Gamification::ImageUploader
11
+ end
12
+ end
13
+ 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