achievable 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. data/.gitignore +6 -0
  2. data/Gemfile +10 -0
  3. data/Gemfile.lock +149 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.markdown +53 -0
  6. data/Rakefile +29 -0
  7. data/achievable.gemspec +25 -0
  8. data/lib/achievable/achieve_manager.rb +28 -0
  9. data/lib/achievable/achiever.rb +35 -0
  10. data/lib/achievable/dsl.rb +23 -0
  11. data/lib/achievable/engine.rb +18 -0
  12. data/lib/achievable/version.rb +3 -0
  13. data/lib/achievable.rb +19 -0
  14. data/lib/generators/achievable_generator.rb +26 -0
  15. data/lib/generators/templates/achievement.rb +11 -0
  16. data/lib/generators/templates/achieving.rb +4 -0
  17. data/lib/generators/templates/migration.rb +29 -0
  18. data/test/achievable_test.rb +103 -0
  19. data/test/dummy/Rakefile +7 -0
  20. data/test/dummy/app/controllers/application_controller.rb +3 -0
  21. data/test/dummy/app/helpers/application_helper.rb +2 -0
  22. data/test/dummy/app/models/achievement.rb +11 -0
  23. data/test/dummy/app/models/achieving.rb +4 -0
  24. data/test/dummy/app/models/post.rb +3 -0
  25. data/test/dummy/app/models/user.rb +4 -0
  26. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  27. data/test/dummy/config/application.rb +48 -0
  28. data/test/dummy/config/boot.rb +10 -0
  29. data/test/dummy/config/database.yml +22 -0
  30. data/test/dummy/config/environment.rb +5 -0
  31. data/test/dummy/config/environments/development.rb +26 -0
  32. data/test/dummy/config/environments/production.rb +49 -0
  33. data/test/dummy/config/environments/test.rb +35 -0
  34. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  35. data/test/dummy/config/initializers/inflections.rb +10 -0
  36. data/test/dummy/config/initializers/mime_types.rb +5 -0
  37. data/test/dummy/config/initializers/secret_token.rb +7 -0
  38. data/test/dummy/config/initializers/session_store.rb +8 -0
  39. data/test/dummy/config/locales/en.yml +5 -0
  40. data/test/dummy/config/routes.rb +58 -0
  41. data/test/dummy/config.ru +4 -0
  42. data/test/dummy/db/migrate/20110411195814_create_achievements.rb +17 -0
  43. data/test/dummy/db/migrate/20110411200936_create_achievings.rb +15 -0
  44. data/test/dummy/db/migrate/20110411201748_create_users.rb +14 -0
  45. data/test/dummy/db/migrate/20110411233641_add_achiever_type_to_achievings.rb +9 -0
  46. data/test/dummy/db/migrate/20110412000011_create_posts.rb +14 -0
  47. data/test/dummy/db/migrate/20110412000430_add_user_id_to_posts.rb +9 -0
  48. data/test/dummy/db/schema.rb +49 -0
  49. data/test/dummy/public/404.html +26 -0
  50. data/test/dummy/public/422.html +26 -0
  51. data/test/dummy/public/500.html +26 -0
  52. data/test/dummy/public/favicon.ico +0 -0
  53. data/test/dummy/public/javascripts/application.js +2 -0
  54. data/test/dummy/public/javascripts/controls.js +965 -0
  55. data/test/dummy/public/javascripts/dragdrop.js +974 -0
  56. data/test/dummy/public/javascripts/effects.js +1123 -0
  57. data/test/dummy/public/javascripts/prototype.js +6001 -0
  58. data/test/dummy/public/javascripts/rails.js +191 -0
  59. data/test/dummy/public/stylesheets/.gitkeep +0 -0
  60. data/test/dummy/script/rails +6 -0
  61. data/test/dummy/spec/models/post_spec.rb +1 -0
  62. data/test/dummy/spec/spec_helper.rb +0 -0
  63. data/test/integration/navigation_test.rb +5 -0
  64. data/test/support/fixture.rb +24 -0
  65. data/test/support/integration_case.rb +5 -0
  66. data/test/test_helper.rb +23 -0
  67. metadata +203 -0
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ .bundle/
2
+ log/*.log
3
+ pkg/
4
+ test/dummy/db/*.sqlite3
5
+ test/dummy/log/*.log
6
+ test/dummy/tmp/
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source "http://rubygems.org"
2
+
3
+ gem "rails", "3.0.5"
4
+ gem "capybara", ">= 0.4.0"
5
+ gem "sqlite3"
6
+ gem "rspec", '2.2.0'
7
+ gem "rspec-rails", '2.2.1'
8
+ gem 'resque', :require => 'resque/server'
9
+ gem 'resque_spec'
10
+ gem 'sourcify'
data/Gemfile.lock ADDED
@@ -0,0 +1,149 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ abstract (1.0.0)
5
+ actionmailer (3.0.5)
6
+ actionpack (= 3.0.5)
7
+ mail (~> 2.2.15)
8
+ actionpack (3.0.5)
9
+ activemodel (= 3.0.5)
10
+ activesupport (= 3.0.5)
11
+ builder (~> 2.1.2)
12
+ erubis (~> 2.6.6)
13
+ i18n (~> 0.4)
14
+ rack (~> 1.2.1)
15
+ rack-mount (~> 0.6.13)
16
+ rack-test (~> 0.5.7)
17
+ tzinfo (~> 0.3.23)
18
+ activemodel (3.0.5)
19
+ activesupport (= 3.0.5)
20
+ builder (~> 2.1.2)
21
+ i18n (~> 0.4)
22
+ activerecord (3.0.5)
23
+ activemodel (= 3.0.5)
24
+ activesupport (= 3.0.5)
25
+ arel (~> 2.0.2)
26
+ tzinfo (~> 0.3.23)
27
+ activeresource (3.0.5)
28
+ activemodel (= 3.0.5)
29
+ activesupport (= 3.0.5)
30
+ activesupport (3.0.5)
31
+ arel (2.0.9)
32
+ builder (2.1.2)
33
+ capybara (0.4.1.2)
34
+ celerity (>= 0.7.9)
35
+ culerity (>= 0.2.4)
36
+ mime-types (>= 1.16)
37
+ nokogiri (>= 1.3.3)
38
+ rack (>= 1.0.0)
39
+ rack-test (>= 0.5.4)
40
+ selenium-webdriver (>= 0.0.27)
41
+ xpath (~> 0.1.3)
42
+ celerity (0.8.9)
43
+ childprocess (0.1.8)
44
+ ffi (~> 1.0.6)
45
+ culerity (0.2.15)
46
+ diff-lcs (1.1.2)
47
+ erubis (2.6.6)
48
+ abstract (>= 1.0.0)
49
+ ffi (1.0.7)
50
+ rake (>= 0.8.7)
51
+ file-tail (1.0.5)
52
+ spruz (>= 0.1.0)
53
+ i18n (0.5.0)
54
+ json (1.4.6)
55
+ json_pure (1.5.1)
56
+ mail (2.2.15)
57
+ activesupport (>= 2.3.6)
58
+ i18n (>= 0.4.0)
59
+ mime-types (~> 1.16)
60
+ treetop (~> 1.4.8)
61
+ mime-types (1.16)
62
+ nokogiri (1.4.4)
63
+ polyglot (0.3.1)
64
+ rack (1.2.2)
65
+ rack-mount (0.6.14)
66
+ rack (>= 1.0.0)
67
+ rack-test (0.5.7)
68
+ rack (>= 1.0)
69
+ rails (3.0.5)
70
+ actionmailer (= 3.0.5)
71
+ actionpack (= 3.0.5)
72
+ activerecord (= 3.0.5)
73
+ activeresource (= 3.0.5)
74
+ activesupport (= 3.0.5)
75
+ bundler (~> 1.0)
76
+ railties (= 3.0.5)
77
+ railties (3.0.5)
78
+ actionpack (= 3.0.5)
79
+ activesupport (= 3.0.5)
80
+ rake (>= 0.8.7)
81
+ thor (~> 0.14.4)
82
+ rake (0.8.7)
83
+ redis (2.2.0)
84
+ redis-namespace (0.10.0)
85
+ redis (< 3.0.0)
86
+ resque (1.15.0)
87
+ json (~> 1.4.6)
88
+ redis-namespace (>= 0.10.0)
89
+ sinatra (>= 0.9.2)
90
+ vegas (~> 0.1.2)
91
+ resque_spec (0.4.2)
92
+ resque (>= 1.6.0)
93
+ rspec (>= 2.0.0.beta.12)
94
+ rspec (2.2.0)
95
+ rspec-core (~> 2.2)
96
+ rspec-expectations (~> 2.2)
97
+ rspec-mocks (~> 2.2)
98
+ rspec-core (2.5.1)
99
+ rspec-expectations (2.5.0)
100
+ diff-lcs (~> 1.1.2)
101
+ rspec-mocks (2.5.0)
102
+ rspec-rails (2.2.1)
103
+ actionpack (~> 3.0)
104
+ activesupport (~> 3.0)
105
+ railties (~> 3.0)
106
+ rspec (~> 2.2.0)
107
+ ruby2ruby (1.2.5)
108
+ ruby_parser (~> 2.0)
109
+ sexp_processor (~> 3.0)
110
+ ruby_parser (2.0.6)
111
+ sexp_processor (~> 3.0)
112
+ rubyzip (0.9.4)
113
+ selenium-webdriver (0.1.4)
114
+ childprocess (>= 0.1.7)
115
+ ffi (>= 1.0.7)
116
+ json_pure
117
+ rubyzip
118
+ sexp_processor (3.0.5)
119
+ sinatra (1.2.1)
120
+ rack (~> 1.1)
121
+ tilt (>= 1.2.2, < 2.0)
122
+ sourcify (0.4.2)
123
+ file-tail (>= 1.0.5)
124
+ ruby2ruby (>= 1.2.5)
125
+ sexp_processor (>= 3.0.5)
126
+ spruz (0.2.5)
127
+ sqlite3 (1.3.3)
128
+ thor (0.14.6)
129
+ tilt (1.2.2)
130
+ treetop (1.4.9)
131
+ polyglot (>= 0.3.1)
132
+ tzinfo (0.3.25)
133
+ vegas (0.1.8)
134
+ rack (>= 1.0.0)
135
+ xpath (0.1.3)
136
+ nokogiri (~> 1.3)
137
+
138
+ PLATFORMS
139
+ ruby
140
+
141
+ DEPENDENCIES
142
+ capybara (>= 0.4.0)
143
+ rails (= 3.0.5)
144
+ resque
145
+ resque_spec
146
+ rspec (= 2.2.0)
147
+ rspec-rails (= 2.2.1)
148
+ sourcify
149
+ sqlite3
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2011 Qi He
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,53 @@
1
+ # Achievable
2
+
3
+ This is a simple achievement builder for rails
4
+
5
+
6
+ ## Installation
7
+
8
+ To install Achievable, simply install the gem:
9
+
10
+ gem install achievable
11
+
12
+ Run generator to generate config information in `application.rb`, migration file `achievable_migration`, and model files `achievement.rb` and `achieving.rb`
13
+
14
+ rails g achievable
15
+
16
+ ## Configuration for [resque](https://github.com/defunkt/resque)
17
+
18
+ Achievable also provides resque functionality. Enable or disable resque in `config/application.rb`:
19
+
20
+ config.achievable.resque_enable = false
21
+
22
+ ## Usage
23
+
24
+ ### Specify which model is used for the achiever, take user for example:
25
+
26
+ class User < ActiveRecord::Base
27
+ include Achievable::Achiever
28
+ has_many :posts
29
+ end
30
+
31
+ ### Specify which column to check for achievement of in a model, the name of the achievement, receiver of achievement and condition in which achiever has to meet. If receiver is not set, then the model itself is the receiver.
32
+
33
+ class User < ActiveRecord::Base
34
+ ...
35
+ achievable :image_url, "first_time_edit_avatar"
36
+ ...
37
+ end
38
+
39
+ class Post < ActiveRecord::Base
40
+ ...
41
+ achievable :description, "first_time_edit_description", :receiver => :user
42
+ ...
43
+ end
44
+
45
+ class User < ActiveRecord::Base
46
+ ...
47
+ achievable :tags_count, "tags_500_times" :condition => lambda { |u| u.tags_count = 500 }
48
+ ...
49
+ end
50
+
51
+ ## TODO
52
+
53
+
data/Rakefile ADDED
@@ -0,0 +1,29 @@
1
+ # encoding: UTF-8
2
+ require 'rubygems'
3
+ begin
4
+ require 'bundler/setup'
5
+ rescue LoadError
6
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
7
+ end
8
+
9
+ require 'rake'
10
+ require 'rake/rdoctask'
11
+
12
+ require 'rake/testtask'
13
+
14
+ Rake::TestTask.new(:test) do |t|
15
+ t.libs << 'lib'
16
+ t.libs << 'test'
17
+ t.pattern = 'test/**/*_test.rb'
18
+ t.verbose = false
19
+ end
20
+
21
+ task :default => :test
22
+
23
+ Rake::RDocTask.new(:rdoc) do |rdoc|
24
+ rdoc.rdoc_dir = 'rdoc'
25
+ rdoc.title = 'Achievable'
26
+ rdoc.options << '--line-numbers' << '--inline-source'
27
+ rdoc.rdoc_files.include('README.rdoc')
28
+ rdoc.rdoc_files.include('lib/**/*.rb')
29
+ end
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "achievable/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "achievable"
7
+ s.version = Achievable::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Qi He"]
10
+ s.email = ["qihe229@gmail.com"]
11
+ s.homepage = "http://rubygems.org/gems/achievable"
12
+ s.summary = %q{A simple achievment gem for rails.}
13
+ s.description = %q{This provides achievement features for rails app.}
14
+
15
+ s.rubyforge_project = "achievable"
16
+
17
+ s.add_dependency 'sourcify'
18
+ s.add_dependency 'resque'
19
+
20
+ s.files = `git ls-files`.split("\n")
21
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
22
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
23
+ s.require_paths = ["lib"]
24
+
25
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ module Achievable
3
+ module AchieveManager
4
+ extend ActiveSupport::Concern
5
+
6
+ @queue = :achievable
7
+
8
+ def achieveit!(name)
9
+ raise NotImplementedError
10
+ end
11
+
12
+ def achieveit(name, &block)
13
+ block_source = block_given? ? block.to_source : nil
14
+ Resque.enqueue(AchieveManager, {"name" => name, "id" => self.id, "class" => self.class.to_s, "condition" => block_source})
15
+ end
16
+
17
+ def self.perform(opts={})
18
+ inst = opts["class"].constantize.find(opts["id"])
19
+ condition = eval(opts["condition"]) if opts["condition"]
20
+ if condition
21
+ inst.achieveit!(opts["name"], &condition)
22
+ else
23
+ inst.achieveit!(opts["name"])
24
+ end
25
+ end
26
+
27
+ end # AchieveManager
28
+ end # Jobs
@@ -0,0 +1,35 @@
1
+ module Achievable
2
+ module Achiever
3
+ extend ActiveSupport::Concern
4
+ include Achievable::AchieveManager
5
+
6
+ included do
7
+ has_many :achievements, :through => :achievings
8
+ has_many :achievings, :dependent => :destroy, :as => :achiever
9
+ end
10
+
11
+ def achieve(name, options = {})
12
+ condition = options[:condition] ? options[:condition] : ( lambda { |u| true } )
13
+ if Achievable.resque_enable
14
+ achieveit(name, &condition)
15
+ else
16
+ achieveit!(name, &condition)
17
+ end
18
+ end
19
+
20
+ def achieveit!(name, &block)
21
+ achievement = Achievement.find_by_name!(name)
22
+ unless achieved?(achievement)
23
+ achievement.achieve(self) if ( block_given? ? block.call(self) : true )
24
+ end
25
+ end
26
+
27
+ def achieved?(achievement)
28
+ if achievement.is_a? String
29
+ achievement = Achievement.find_by_name!(achievement)
30
+ end
31
+ achievements.include?(achievement)
32
+ end
33
+
34
+ end # Achiever
35
+ end # Achievable
@@ -0,0 +1,23 @@
1
+ module Achievable
2
+ module DSL
3
+ extend ActiveSupport::Concern
4
+
5
+ module ClassMethods
6
+ def achievable(attribute, achievement, options = {})
7
+ options.assert_valid_keys(:receiver, :condition)
8
+ method_name = :"achieve_#{achievement}"
9
+
10
+ define_method(method_name) do |*args|
11
+ attr_changed = :"#{attribute.to_s}_changed?"
12
+ return unless (respond_to? attr_changed) && send(attr_changed)
13
+ receiver = options[:receiver] ? send(options[:receiver]) : self
14
+ raise 'object must respond to achieve' unless receiver.respond_to? :achieve
15
+ receiver.achieve(achievement, options)
16
+ end
17
+
18
+ send(:"after_update", method_name)
19
+ end
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,18 @@
1
+ module Achievable
2
+ class Engine < ::Rails::Engine
3
+ config.achievable = ActiveSupport::OrderedOptions.new
4
+
5
+ initializer "achievable.active_record" do
6
+ ActiveSupport.on_load(:active_record) do
7
+ include Achievable::DSL
8
+ end
9
+ end
10
+
11
+ initializer "achievable.resque_enable" do |app|
12
+ if app.config.achievable.resque_enable
13
+ Achievable.set_resque_enable(app.config.achievable.resque_enable )
14
+ end
15
+ end
16
+
17
+ end # Engine
18
+ end # Achievable
@@ -0,0 +1,3 @@
1
+ module Achievable
2
+ VERSION = "0.0.1"
3
+ end
data/lib/achievable.rb ADDED
@@ -0,0 +1,19 @@
1
+ module Achievable
2
+ autoload :DSL, 'achievable/dsl'
3
+ autoload :Achiever, 'achievable/achiever'
4
+ autoload :AchieveManager, 'achievable/achieve_manager'
5
+
6
+ # Set which enable resque.
7
+ #
8
+ # Achievable.set_resque_enable
9
+ #
10
+ def self.set_resque_enable(true_or_false)
11
+ singleton_class.send :define_method, :resque_enable, lambda { true_or_false }
12
+ end
13
+
14
+ def self.resque_enable; false; end
15
+
16
+ end
17
+
18
+ require 'achievable/engine'
19
+
@@ -0,0 +1,26 @@
1
+ class AchievableGenerator < Rails::Generators::NamedBase
2
+
3
+ source_root File.expand_path("../templates", __FILE__)
4
+
5
+ class_option :migration, :type => :boolean, :default => true
6
+
7
+ def manifest
8
+ record do |m|
9
+ m.migration_template 'migration.rb', 'db/migrate', :migration_file_name => "achievable_migration"
10
+ end
11
+ end
12
+
13
+ def copy_achievable_models
14
+ template "achievement.rb", "app/models/achievement.rb"
15
+ template "achieving.rb", "app/models/achieving.rb"
16
+ end
17
+
18
+ def add_application_config
19
+ inject_into_class "config/application.rb", "Application", <<-CONTENT
20
+ # Set achievable resque
21
+ config.achievable.resque_enable = false
22
+
23
+ CONTENT
24
+ end
25
+
26
+ end
@@ -0,0 +1,11 @@
1
+ class Achievement < ActiveRecord::Base
2
+ has_many :achievings
3
+
4
+ validates_presence_of :name, :category
5
+ validates_uniqueness_of :name
6
+
7
+ def achieve(achiever)
8
+ achievings << Achieving.new(:achiever => achiever, :achievement => self)
9
+ end
10
+
11
+ end
@@ -0,0 +1,4 @@
1
+ class Achieving < ActiveRecord::Base
2
+ belongs_to :achiever, :polymorphic => true
3
+ belongs_to :achievement, :class_name => "Achievement", :foreign_key => "achievement_id", :counter_cache => true
4
+ end
@@ -0,0 +1,29 @@
1
+ class AchievableMigration < ActiveRecord::Migration
2
+
3
+ def self.up
4
+ create_table :achievements do |t|
5
+ t.string :name
6
+ t.string :image_url
7
+ t.string :description
8
+ t.integer :achievings_count, :default => 0
9
+ t.string :category
10
+ t.timestamps
11
+ end
12
+
13
+ create_table :achievings do |t|
14
+ t.integer :achiever_id
15
+ t.integer :achievement_id
16
+ t.boolean :notify, :default => false
17
+ t.string :achiever_type
18
+ t.timestamps
19
+ end
20
+
21
+ add_index :achievements, :name
22
+ end
23
+
24
+ def self.down
25
+ drop_table :achievings
26
+ drop_table :achievements
27
+ end
28
+
29
+ end
@@ -0,0 +1,103 @@
1
+ require 'test_helper'
2
+
3
+ describe "Achievable" do
4
+
5
+ before do
6
+ @achieve1 = Achievement.create!(:name => "achievement1", :description => "test achievement 1", :category => "achi")
7
+ @achieve2 = Achievement.create!(:name => "achievement2", :description => "test achievement 2", :category => "achi")
8
+ @achieve3 = Achievement.create!(:name => "achievement3", :description => "test achievement 3", :category => "achi")
9
+ @user1 = User.create!(:name => "he9qi", :image_url => "1.png")
10
+ @user2 = User.create!(:name => "he9lin", :image_url => "2.png")
11
+ @post1 = Post.create!(:name => "post1", :user => @user1)
12
+ @post2 = Post.create!(:name => "post2", :user => @user2)
13
+ Achievable.set_resque_enable(false)
14
+ end
15
+
16
+ after do
17
+ Achievement.destroy_all
18
+ Achieving.destroy_all
19
+ User.destroy_all
20
+ Post.destroy_all
21
+ end
22
+
23
+ it "should return true if user has the achievemnt it is asking for" do
24
+ @achieve1.achieve(@user1)
25
+ @user1.achieved?("achievement1").should be_true
26
+ end
27
+
28
+ context "When user update image_url" do
29
+ before do
30
+ User.class_eval do
31
+ achievable :image_url, "achievement1"
32
+ end
33
+ end
34
+
35
+ it "should give user an achievement" do
36
+ with_resque do
37
+ @user1.image_url = "2.png"
38
+ @user1.save!
39
+ end
40
+ @user1.achieved?("achievement1").should be_true
41
+ end
42
+
43
+ end
44
+
45
+ context "Conditional achievement" do
46
+ context "When user update posts and the user is not he9qi" do
47
+ before do
48
+ Post.class_eval do
49
+ achievable :name, "achievement2", :receiver => :user, :condition => lambda { |u| u.name = "he9qi" }
50
+ end
51
+ end
52
+
53
+ it "should not give user an achievement" do
54
+ with_resque do
55
+ @post2.name = "post3"
56
+ @post2.save!
57
+ end
58
+ @user1.achieved?("achievement2").should be_false
59
+ end
60
+ end
61
+
62
+ context "When user update posts and the user is he9qi" do
63
+ before do
64
+ Post.class_eval do
65
+ achievable :name, "achievement2", :receiver => :user, :condition => lambda { |u| u.name = "he9qi" }
66
+ end
67
+ end
68
+
69
+ it "should give user an achievement" do
70
+ with_resque do
71
+ @post1.name = "post2"
72
+ @post1.save!
73
+ end
74
+ @user1.achieved?("achievement2").should be_true
75
+ end
76
+ end
77
+ end
78
+
79
+ context "Resque Enable: When user update posts and the user is he9qi" do
80
+ before do
81
+ Achievable.set_resque_enable(true)
82
+ Post.class_eval do
83
+ achievable :name, "achievement2", :receiver => :user, :condition => lambda { |u| u.name = "he9qi" }
84
+ end
85
+ end
86
+
87
+ it "should not give user an achievement if resque not started" do
88
+ @post1.name = "post2"
89
+ @post1.save!
90
+ @user1.achieved?("achievement2").should be_false
91
+ end
92
+
93
+ it "should give user an achievement" do
94
+ with_resque do
95
+ @post1.name = "post2"
96
+ @post1.save!
97
+ end
98
+ @user1.achieved?("achievement2").should be_true
99
+ end
100
+
101
+ end
102
+
103
+ end
@@ -0,0 +1,7 @@
1
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
2
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
+
4
+ require File.expand_path('../config/application', __FILE__)
5
+ require 'rake'
6
+
7
+ Dummy::Application.load_tasks
@@ -0,0 +1,3 @@
1
+ class ApplicationController < ActionController::Base
2
+ protect_from_forgery
3
+ end
@@ -0,0 +1,2 @@
1
+ module ApplicationHelper
2
+ end
@@ -0,0 +1,11 @@
1
+ class Achievement < ActiveRecord::Base
2
+ has_many :achievings
3
+
4
+ validates_presence_of :name, :category
5
+ validates_uniqueness_of :name
6
+
7
+ def achieve(achiever)
8
+ achievings.create!(:achiever => achiever, :achievement => self)
9
+ end
10
+ end
11
+
@@ -0,0 +1,4 @@
1
+ class Achieving < ActiveRecord::Base
2
+ belongs_to :achiever, :polymorphic => true
3
+ belongs_to :achievement, :class_name => "Achievement", :foreign_key => "achievement_id", :counter_cache => true
4
+ end
@@ -0,0 +1,3 @@
1
+ class Post < ActiveRecord::Base
2
+ belongs_to :user
3
+ end
@@ -0,0 +1,4 @@
1
+ class User < ActiveRecord::Base
2
+ include Achievable::Achiever
3
+ has_many :posts
4
+ end
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Dummy</title>
5
+ <%= stylesheet_link_tag :all %>
6
+ <%= javascript_include_tag :defaults %>
7
+ <%= csrf_meta_tag %>
8
+ </head>
9
+ <body>
10
+
11
+ <%= yield %>
12
+
13
+ </body>
14
+ </html>