achievable 0.0.1
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.
- data/.gitignore +6 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +149 -0
- data/MIT-LICENSE +20 -0
- data/README.markdown +53 -0
- data/Rakefile +29 -0
- data/achievable.gemspec +25 -0
- data/lib/achievable/achieve_manager.rb +28 -0
- data/lib/achievable/achiever.rb +35 -0
- data/lib/achievable/dsl.rb +23 -0
- data/lib/achievable/engine.rb +18 -0
- data/lib/achievable/version.rb +3 -0
- data/lib/achievable.rb +19 -0
- data/lib/generators/achievable_generator.rb +26 -0
- data/lib/generators/templates/achievement.rb +11 -0
- data/lib/generators/templates/achieving.rb +4 -0
- data/lib/generators/templates/migration.rb +29 -0
- data/test/achievable_test.rb +103 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/models/achievement.rb +11 -0
- data/test/dummy/app/models/achieving.rb +4 -0
- data/test/dummy/app/models/post.rb +3 -0
- data/test/dummy/app/models/user.rb +4 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config/application.rb +48 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +22 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +26 -0
- data/test/dummy/config/environments/production.rb +49 -0
- data/test/dummy/config/environments/test.rb +35 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/inflections.rb +10 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +58 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/db/migrate/20110411195814_create_achievements.rb +17 -0
- data/test/dummy/db/migrate/20110411200936_create_achievings.rb +15 -0
- data/test/dummy/db/migrate/20110411201748_create_users.rb +14 -0
- data/test/dummy/db/migrate/20110411233641_add_achiever_type_to_achievings.rb +9 -0
- data/test/dummy/db/migrate/20110412000011_create_posts.rb +14 -0
- data/test/dummy/db/migrate/20110412000430_add_user_id_to_posts.rb +9 -0
- data/test/dummy/db/schema.rb +49 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +26 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/public/javascripts/application.js +2 -0
- data/test/dummy/public/javascripts/controls.js +965 -0
- data/test/dummy/public/javascripts/dragdrop.js +974 -0
- data/test/dummy/public/javascripts/effects.js +1123 -0
- data/test/dummy/public/javascripts/prototype.js +6001 -0
- data/test/dummy/public/javascripts/rails.js +191 -0
- data/test/dummy/public/stylesheets/.gitkeep +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/dummy/spec/models/post_spec.rb +1 -0
- data/test/dummy/spec/spec_helper.rb +0 -0
- data/test/integration/navigation_test.rb +5 -0
- data/test/support/fixture.rb +24 -0
- data/test/support/integration_case.rb +5 -0
- data/test/test_helper.rb +23 -0
- metadata +203 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
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
|
data/achievable.gemspec
ADDED
|
@@ -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
|
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,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
|
data/test/dummy/Rakefile
ADDED
|
@@ -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
|