balinterdi-acts_as_trivia 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +1 -0
- data/Manifest +24 -0
- data/README.markdown +97 -0
- data/Rakefile +16 -0
- data/acts_as_trivia.gemspec +31 -0
- data/generators/acts_as_trivia/USAGE +22 -0
- data/generators/acts_as_trivia/acts_as_trivia_generator.rb +110 -0
- data/generators/acts_as_trivia/templates/answers_controller.rb +6 -0
- data/generators/acts_as_trivia/templates/controller.rb +4 -0
- data/generators/acts_as_trivia/templates/trivias_migration.rb +29 -0
- data/generators/acts_as_trivia/templates/view.html.erb +1 -0
- data/generators/acts_as_trivia_record/USAGE +8 -0
- data/generators/acts_as_trivia_record/acts_as_trivia_record_generator.rb +12 -0
- data/generators/acts_as_trivia_record/templates/migration.rb +8 -0
- data/lib/acts_as_trivia.rb +40 -0
- data/lib/acts_as_trivia/trivia.rb +37 -0
- data/lib/acts_as_trivia/trivia_answer.rb +8 -0
- data/lib/acts_as_trivia/trivia_answers_controller.rb +4 -0
- data/lib/acts_as_trivia/trivias_helper.rb +18 -0
- data/lib/acts_as_trivia/user.rb +16 -0
- data/spec/acts_as_trivia_spec.rb +144 -0
- data/spec/database.yml +3 -0
- data/spec/spec_helper.rb +54 -0
- data/tasks/acts_as_trivia.rake +6 -0
- data/todos.markdown +26 -0
- metadata +90 -0
data/CHANGELOG
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
v0.1 Initial release.
|
data/Manifest
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
CHANGELOG
|
2
|
+
generators/acts_as_trivia/acts_as_trivia_generator.rb
|
3
|
+
generators/acts_as_trivia/templates/answers_controller.rb
|
4
|
+
generators/acts_as_trivia/templates/controller.rb
|
5
|
+
generators/acts_as_trivia/templates/trivias_migration.rb
|
6
|
+
generators/acts_as_trivia/templates/view.html.erb
|
7
|
+
generators/acts_as_trivia/USAGE
|
8
|
+
generators/acts_as_trivia_record/acts_as_trivia_record_generator.rb
|
9
|
+
generators/acts_as_trivia_record/templates/migration.rb
|
10
|
+
generators/acts_as_trivia_record/USAGE
|
11
|
+
lib/acts_as_trivia/trivia.rb
|
12
|
+
lib/acts_as_trivia/trivia_answer.rb
|
13
|
+
lib/acts_as_trivia/trivia_answers_controller.rb
|
14
|
+
lib/acts_as_trivia/trivias_helper.rb
|
15
|
+
lib/acts_as_trivia/user.rb
|
16
|
+
lib/acts_as_trivia.rb
|
17
|
+
Manifest
|
18
|
+
Rakefile
|
19
|
+
README.markdown
|
20
|
+
spec/acts_as_trivia_spec.rb
|
21
|
+
spec/database.yml
|
22
|
+
spec/spec_helper.rb
|
23
|
+
tasks/acts_as_trivia.rake
|
24
|
+
todos.markdown
|
data/README.markdown
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
* NoMethodError (undefined method `acts\_as\_trivia' for #<Class:0x253e9fc>):
|
2
|
+
|
3
|
+
Make sure you have the config.gem "acts\_as\_trivia" line in your environment.rb
|
4
|
+
|
5
|
+
* Trivia will have its own model:
|
6
|
+
|
7
|
+
create_table :trivias, :force => true do |t|
|
8
|
+
t.string :on, :null => false
|
9
|
+
t.string :about, :null => false
|
10
|
+
end
|
11
|
+
|
12
|
+
e.g
|
13
|
+
|
14
|
+
Trivia.new(:on => "country", :about => "hdi")
|
15
|
+
|
16
|
+
class Trivia < ActionRecord::Base
|
17
|
+
|
18
|
+
def to\_param
|
19
|
+
#{on}-#{about} # e.g country-hdi
|
20
|
+
end
|
21
|
+
|
22
|
+
And requests to trivias will have a routing like this:
|
23
|
+
|
24
|
+
/trivias/1, or which is the same
|
25
|
+
/trivias/country-hdi (and that latter will be generated)
|
26
|
+
|
27
|
+
|
28
|
+
* The User class will have the following added associations:
|
29
|
+
|
30
|
+
class User < ActiveRecord::Base
|
31
|
+
|
32
|
+
has_many :trivia_answers
|
33
|
+
has_many :trivias, :through => :trivia_answers
|
34
|
+
has_many :correct_trivia_answers, :through => :trivia_answers, :condition => { "state = ?", 'correct' }
|
35
|
+
|
36
|
+
* And the join model will be the TriviaAnswers class:
|
37
|
+
|
38
|
+
create_table :trivia_answers, :force => true do |t|
|
39
|
+
t.string :trivia_id, :null => false
|
40
|
+
t.string :user_id, :null => false
|
41
|
+
t.integer :points # how many points the user received for his answer
|
42
|
+
end
|
43
|
+
|
44
|
+
* when the geneation script is called with the following:
|
45
|
+
|
46
|
+
./script/generate acts_as_trivia country hdi
|
47
|
+
|
48
|
+
then the following things will be generated:
|
49
|
+
|
50
|
+
* a new trivia model OK
|
51
|
+
|
52
|
+
class Trivia < ActiveRecord::Base
|
53
|
+
def to\_param
|
54
|
+
#{on}-#{about} # e.g country-hdi
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
* a new controller (if it does not exist yet) OK
|
59
|
+
|
60
|
+
class TriviaController
|
61
|
+
end
|
62
|
+
|
63
|
+
* new resource routes for trivia OK
|
64
|
+
|
65
|
+
map.resources :trivias
|
66
|
+
|
67
|
+
* in the model (country.rb) OK:
|
68
|
+
|
69
|
+
class Country < ActiveRecord::Base
|
70
|
+
acts_as_trivia :hdi
|
71
|
+
...
|
72
|
+
end
|
73
|
+
|
74
|
+
* added associations in the user model OK
|
75
|
+
|
76
|
+
has_many :trivia_answers
|
77
|
+
has_many :trivias, :through => :trivia_answers
|
78
|
+
<!-- has_many :correct_trivia_answers, :through => :trivia_answers, :condition => { "state = ?", 'correct' } -->
|
79
|
+
|
80
|
+
* db migrations
|
81
|
+
|
82
|
+
* for the trivia class itself OK
|
83
|
+
|
84
|
+
create_table :trivias, :force => true do |t|
|
85
|
+
t.string :on, :null => false
|
86
|
+
t.string :about, :null => false
|
87
|
+
t.timestamps
|
88
|
+
end
|
89
|
+
|
90
|
+
* for the join model between the user and the trivia OK
|
91
|
+
|
92
|
+
create_table :trivia_answers, :force => true do |t|
|
93
|
+
t.string :trivia_id, :null => false
|
94
|
+
t.string :user_id, :null => false
|
95
|
+
t.integer :points # how many points the user received for his answer
|
96
|
+
end
|
97
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'echoe'
|
4
|
+
|
5
|
+
Echoe.new('acts_as_trivia', '0.1') do |p|
|
6
|
+
p.description = <<-EOS
|
7
|
+
This gem will add the possibility to turn your Rails application into a trivia game with the ease of generating a migration. The only thing you need is a model class with a sortable attribute and this gem.
|
8
|
+
EOS
|
9
|
+
p.url = "http://github.com/balinterdi/acts_as_trivia"
|
10
|
+
p.author = "Balint Erdi"
|
11
|
+
p.email = "balint.erdi@gmail.com"
|
12
|
+
p.ignore_pattern = ["tmp/*", "script/*"]
|
13
|
+
p.development_dependencies = []
|
14
|
+
end
|
15
|
+
|
16
|
+
Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{acts_as_trivia}
|
5
|
+
s.version = "0.1"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Balint Erdi"]
|
9
|
+
s.date = %q{2009-05-04}
|
10
|
+
s.description = %q{This gem will add the possibility to turn your Rails application into a trivia game with the ease of generating a migration. The only thing you need is a model class with a sortable attribute and this gem.}
|
11
|
+
s.email = %q{balint.erdi@gmail.com}
|
12
|
+
s.extra_rdoc_files = ["CHANGELOG", "lib/acts_as_trivia/trivia.rb", "lib/acts_as_trivia/trivia_answer.rb", "lib/acts_as_trivia/trivia_answers_controller.rb", "lib/acts_as_trivia/trivias_helper.rb", "lib/acts_as_trivia/user.rb", "lib/acts_as_trivia.rb", "README.markdown", "tasks/acts_as_trivia.rake"]
|
13
|
+
s.files = ["CHANGELOG", "generators/acts_as_trivia/acts_as_trivia_generator.rb", "generators/acts_as_trivia/templates/answers_controller.rb", "generators/acts_as_trivia/templates/controller.rb", "generators/acts_as_trivia/templates/trivias_migration.rb", "generators/acts_as_trivia/templates/view.html.erb", "generators/acts_as_trivia/USAGE", "generators/acts_as_trivia_record/acts_as_trivia_record_generator.rb", "generators/acts_as_trivia_record/templates/migration.rb", "generators/acts_as_trivia_record/USAGE", "lib/acts_as_trivia/trivia.rb", "lib/acts_as_trivia/trivia_answer.rb", "lib/acts_as_trivia/trivia_answers_controller.rb", "lib/acts_as_trivia/trivias_helper.rb", "lib/acts_as_trivia/user.rb", "lib/acts_as_trivia.rb", "Manifest", "Rakefile", "README.markdown", "spec/acts_as_trivia_spec.rb", "spec/database.yml", "spec/spec_helper.rb", "tasks/acts_as_trivia.rake", "todos.markdown", "acts_as_trivia.gemspec"]
|
14
|
+
s.has_rdoc = true
|
15
|
+
s.homepage = %q{http://github.com/balinterdi/acts_as_trivia}
|
16
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Acts_as_trivia", "--main", "README.markdown"]
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.rubyforge_project = %q{acts_as_trivia}
|
19
|
+
s.rubygems_version = %q{1.3.1}
|
20
|
+
s.summary = %q{This gem will add the possibility to turn your Rails application into a trivia game with the ease of generating a migration. The only thing you need is a model class with a sortable attribute and this gem.}
|
21
|
+
|
22
|
+
if s.respond_to? :specification_version then
|
23
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
24
|
+
s.specification_version = 2
|
25
|
+
|
26
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
27
|
+
else
|
28
|
+
end
|
29
|
+
else
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Description:
|
2
|
+
|
3
|
+
The acts_as_trivia generator will generate a controller for the model class that is given as the first parameter. For each action (trivia question) passed in the command line it will also generate a view with the corresponding name, a route in the routes file and the acts_as_trivia line itself in the model.
|
4
|
+
|
5
|
+
Example:
|
6
|
+
./script/generate acts_as_trivia country hdi name
|
7
|
+
...
|
8
|
+
create app/controllers/country_trivia_controller.rb
|
9
|
+
create app/views/country_trivia/hdi.html.erb
|
10
|
+
create app/views/country_trivia/population.html.erb
|
11
|
+
create app/views/country_trivia/gdp.html.erb
|
12
|
+
route map.with_options(:controller => 'country_trivia') do ...
|
13
|
+
|
14
|
+
In routes.rb it will add the following:
|
15
|
+
|
16
|
+
ActionController::Routing::Routes.draw do |map|
|
17
|
+
|
18
|
+
map.with_options(:controller => 'country_trivia') do |trivia|
|
19
|
+
trivia.country_hdi_trivia '/countries/trivia/hdi', :action => "hdi"
|
20
|
+
trivia.country_hdi_trivia '/countries/trivia/population', :action => "population"
|
21
|
+
trivia.country_hdi_trivia '/countries/trivia/hdi', :action => "gdp"
|
22
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require 'rails_generator'
|
2
|
+
|
3
|
+
module ActsAsTriviaAddedContent
|
4
|
+
|
5
|
+
def route_trivia_answers_as_nested_resource
|
6
|
+
sentinel = "ActionController::Routing::Routes.draw do |map|"
|
7
|
+
unless options[:pretend]
|
8
|
+
gsub_file "config/routes.rb", /(#{Regexp.escape(sentinel)})/mi do |match|
|
9
|
+
<<-EOS
|
10
|
+
#{match}
|
11
|
+
map.resources :users do |users|
|
12
|
+
users.resources :trivias do |trivias|
|
13
|
+
trivias.resources :trivia_answers
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
EOS
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
def model_acts_as_trivia_includes(questions)
|
24
|
+
acts_as_trivia_calls = questions.map do |question|
|
25
|
+
"acts_as_trivia :#{question}"
|
26
|
+
end
|
27
|
+
logger.modify acts_as_trivia_calls.join(", ")
|
28
|
+
|
29
|
+
sentinel = "class #{class_name} < ActiveRecord::Base"
|
30
|
+
unless options[:pretend]
|
31
|
+
gsub_file File.join("app/models", class_path, "#{singular_name}.rb"), /(#{Regexp.escape(sentinel)})/mi do |match|
|
32
|
+
<<-EOS
|
33
|
+
#{match}
|
34
|
+
#{acts_as_trivia_calls.join("\n")}
|
35
|
+
EOS
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
class ActsAsTriviaGenerator < Rails::Generator::NamedBase # ControllerGenerator
|
43
|
+
|
44
|
+
# this is snatched from the resource generator in the Rails source
|
45
|
+
default_options :skip_timestamps => false, :skip_migration => false
|
46
|
+
|
47
|
+
attr_reader :controller_name,
|
48
|
+
:controller_class_path,
|
49
|
+
:controller_file_path,
|
50
|
+
:controller_class_nesting,
|
51
|
+
:controller_class_nesting_depth,
|
52
|
+
:controller_class_name,
|
53
|
+
:controller_singular_name,
|
54
|
+
:controller_plural_name
|
55
|
+
alias_method :controller_file_name, :controller_singular_name
|
56
|
+
alias_method :controller_table_name, :controller_plural_name
|
57
|
+
|
58
|
+
def initialize(runtime_args, runtime_options = {})
|
59
|
+
super
|
60
|
+
|
61
|
+
@controller_name = @name.pluralize
|
62
|
+
|
63
|
+
base_name, @controller_class_path, @controller_file_path, @controller_class_nesting, @controller_class_nesting_depth = extract_modules(@controller_name)
|
64
|
+
@controller_class_name_without_nesting, @controller_singular_name, @controller_plural_name = inflect_names(base_name)
|
65
|
+
|
66
|
+
if @controller_class_nesting.empty?
|
67
|
+
@controller_class_name = @controller_class_name_without_nesting
|
68
|
+
else
|
69
|
+
@controller_class_name = "#{@controller_class_nesting}::#{@controller_class_name_without_nesting}"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def manifest
|
74
|
+
record do |m|
|
75
|
+
# Check whether the given class names are already taken by
|
76
|
+
# Ruby or Rails. In the future, expand to check other namespaces
|
77
|
+
# such as the rest of the user's app.
|
78
|
+
# m.class_collisions "Trivia", "TriviaAnswer"
|
79
|
+
# m.class_collisions "TriviasController", "TriviaAnswersController"
|
80
|
+
m.class_collisions "TriviaTest"
|
81
|
+
|
82
|
+
# Controller directories.
|
83
|
+
m.directory 'app/views/trivias'
|
84
|
+
m.directory 'app/views/trivia_answers'
|
85
|
+
|
86
|
+
# Controllers
|
87
|
+
m.template 'controller.rb', 'app/controllers/trivias_controller.rb'
|
88
|
+
m.template 'answers_controller.rb', 'app/controllers/trivia_answers_controller.rb'
|
89
|
+
|
90
|
+
m.route_resources "trivias"
|
91
|
+
m.route_trivia_answers_as_nested_resource
|
92
|
+
|
93
|
+
m.model_acts_as_trivia_includes actions
|
94
|
+
|
95
|
+
unless options[:skip_migration]
|
96
|
+
m.migration_template 'trivias_migration.rb', 'db/migrate', :assigns => {
|
97
|
+
:migration_name => "CreateTrivias",
|
98
|
+
:trivia_on => singular_name,
|
99
|
+
:trivia_about => actions.first,
|
100
|
+
:trivia_displayed => actions.last,
|
101
|
+
}, :migration_file_name => "create_trivias"
|
102
|
+
end
|
103
|
+
|
104
|
+
path = File.join('app/views/trivias/show.html.erb')
|
105
|
+
m.template 'view.html.erb', path
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
Rails::Generator::Commands::Base.send(:include, ActsAsTriviaAddedContent)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class <%= migration_name %> < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :trivias do |t|
|
4
|
+
t.string :on, :null => false
|
5
|
+
t.string :about, :null => false
|
6
|
+
t.string :displayed, :null => false
|
7
|
+
t.integer :length, :default => 3, :null => false
|
8
|
+
<% unless options[:skip_timestamps] %>
|
9
|
+
t.timestamps
|
10
|
+
<% end -%>
|
11
|
+
end
|
12
|
+
|
13
|
+
create_table :trivia_answers, :force => true do |t|
|
14
|
+
t.string :trivia_id, :null => false
|
15
|
+
t.string :user_id, :null => false
|
16
|
+
t.integer :points
|
17
|
+
<% unless options[:skip_timestamps] %>
|
18
|
+
t.timestamps
|
19
|
+
<% end -%>
|
20
|
+
end
|
21
|
+
|
22
|
+
Trivia.create(:on => <%= %("#{trivia_on}") %>, :about => <%= %("#{trivia_about}") %>, :displayed => <%= %("#{trivia_displayed}") %>)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.down
|
26
|
+
drop_table :trivias
|
27
|
+
drop_table :trivia_answers
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
|
@@ -0,0 +1,8 @@
|
|
1
|
+
Description:
|
2
|
+
|
3
|
+
The acts_as_trivia_record generator creates a trivia record in the database. It should be passed the class on which the trivia operates, the attribute which is the basis of the ranking and the attribute which is displayed when the trivia question is presented.
|
4
|
+
|
5
|
+
Example:
|
6
|
+
./script/generate acts_as_trivia_record country population name
|
7
|
+
...
|
8
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class ActsAsTriviaRecordGenerator < Rails::Generator::NamedBase
|
2
|
+
def manifest
|
3
|
+
record do |m|
|
4
|
+
m.migration_template 'migration.rb', 'db/migrate', :assigns => {
|
5
|
+
:migration_name => "CreateTriviaFor#{plural_name.capitalize}#{actions.first.capitalize}",
|
6
|
+
:trivia_on => singular_name,
|
7
|
+
:trivia_about => actions.first,
|
8
|
+
:trivia_displayed => actions.last
|
9
|
+
}, :migration_file_name => "create_trivia_for_#{plural_name}_#{actions.first}"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require "acts_as_trivia/trivia"
|
2
|
+
require "acts_as_trivia/trivia_answer"
|
3
|
+
require "acts_as_trivia/user"
|
4
|
+
require "acts_as_trivia/trivias_helper"
|
5
|
+
|
6
|
+
module ActsAsTrivia
|
7
|
+
module ClassMethods
|
8
|
+
def acts_as_trivia(method)
|
9
|
+
class << self
|
10
|
+
define_method(:trivia_answer_for) do |name|
|
11
|
+
self.scoped(:order => "#{name} DESC")
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class << self
|
18
|
+
def included(base)
|
19
|
+
base.extend(ClassMethods)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
if Object.const_defined?("ActiveRecord")
|
26
|
+
ActiveRecord::Base.send(:include, ActsAsTrivia)
|
27
|
+
end
|
28
|
+
|
29
|
+
#NOTE: at this point, the controllers of the app (e.g TriviaAnswersController) are not yet defined
|
30
|
+
# so the helpers can not be included. On the other hand, if I define the controller class here
|
31
|
+
# the controller will not be defined in the app and so the actions will not be available.
|
32
|
+
# Thus the autoload solution.
|
33
|
+
#NOTE: autoload does not play well with the class reloading that Rails does in the dev. environment
|
34
|
+
# the helper methods that TriviaAnswersController includes will only be available
|
35
|
+
# at the first request after the server request (when autoload is executed)
|
36
|
+
# autoload :TriviaAnswersController, "acts_as_trivia/trivia_answers_controller"
|
37
|
+
|
38
|
+
if Object.const_defined?("ActionView")
|
39
|
+
ActionView::Base.send(:include, TriviasHelper)
|
40
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class Trivia < ActiveRecord::Base
|
2
|
+
has_many :trivia_answers
|
3
|
+
|
4
|
+
def to_param
|
5
|
+
"#{id}-#{on}-#{about}"
|
6
|
+
end
|
7
|
+
|
8
|
+
def assess_answer_ids(answer_ids)
|
9
|
+
assess_answer(trivia_link_class.find(answer_ids))
|
10
|
+
end
|
11
|
+
|
12
|
+
def assess_answer(answer)
|
13
|
+
correct_answer = get_solution.scoped(:limit => answer.length)
|
14
|
+
score = 0
|
15
|
+
answer.each_with_index do |elt, idx|
|
16
|
+
score += elt == correct_answer[idx] ? 1 : 0
|
17
|
+
end
|
18
|
+
score
|
19
|
+
end
|
20
|
+
|
21
|
+
def get_subjects
|
22
|
+
trivia_link_class.find(:all)
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_solution_values
|
26
|
+
solution = get_solution.scoped(:limit => length)
|
27
|
+
solution.map { |elt| [elt.send(displayed.to_sym), elt.send(about.to_sym)] }
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def get_solution
|
32
|
+
trivia_link_class.trivia_answer_for(about.to_sym)
|
33
|
+
end
|
34
|
+
def trivia_link_class
|
35
|
+
on.capitalize.constantize
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module TriviasHelper
|
2
|
+
def trivia_user_panel(trivia)
|
3
|
+
(1..trivia.length).inject("") { |out, i| out + content_tag(:div, "#{i}. #{trivia_dropdown(trivia)}")}
|
4
|
+
# (1..trivia.length).map { content_tag(:div, trivia_dropdown(trivia)) }
|
5
|
+
end
|
6
|
+
def trivia_dropdown(trivia)
|
7
|
+
#TODO: the get_subjects call will query all instances of a model class (e.g Country.find(:all))
|
8
|
+
#That may be too exhaustive
|
9
|
+
select_tag("#{trivia.on}[#{trivia.about}][]", options_from_collection_for_select(trivia.get_subjects, :id, trivia.displayed.to_sym))
|
10
|
+
end
|
11
|
+
|
12
|
+
def with_each_solution_value(trivia)
|
13
|
+
trivia.get_solution_values.each_with_index do |name_and_value, i|
|
14
|
+
name, value = name_and_value
|
15
|
+
yield i+1, name, value
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class User < ActiveRecord::Base
|
2
|
+
has_many :trivia_answers
|
3
|
+
has_many :trivias, :through => :trivia_answers
|
4
|
+
|
5
|
+
def add_trivia(trivia)
|
6
|
+
trivia_answers.create(:trivia => trivia)
|
7
|
+
end
|
8
|
+
|
9
|
+
def played_trivia?(trivia)
|
10
|
+
trivias.include?(trivia)
|
11
|
+
end
|
12
|
+
|
13
|
+
def trivia_points
|
14
|
+
trivia_answers.sum(:points)
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
require "rubygems"
|
2
|
+
require "spec"
|
3
|
+
require "mocha"
|
4
|
+
|
5
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
6
|
+
|
7
|
+
# use mocha for mocking instead of
|
8
|
+
# Rspec's own mock framework
|
9
|
+
Spec::Runner.configure do |config|
|
10
|
+
config.mock_with :mocha
|
11
|
+
end
|
12
|
+
|
13
|
+
class Country < ActiveRecord::Base
|
14
|
+
include ActsAsTrivia
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "A Trivia" do
|
18
|
+
before do
|
19
|
+
rebuild_trivias_table
|
20
|
+
rebuild_countries_table
|
21
|
+
@trivia = Trivia.create(:on => "country", :about => "hdi", :displayed => "name", :length => 3)
|
22
|
+
Country.class_eval do
|
23
|
+
acts_as_trivia :hdi
|
24
|
+
end
|
25
|
+
@iceland = Country.create(:hdi => 0.968, :name => "Iceland")
|
26
|
+
@canada = Country.create(:hdi => 0.967, :name => "Canada")
|
27
|
+
@new_zealand = Country.create(:hdi => 0.944, :name => "New Zealand")
|
28
|
+
@cyprus = Country.create(:hdi => 0.903, :name => "Cyprus")
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "when assessing" do
|
32
|
+
before do
|
33
|
+
Country.expects(:find).returns([@iceland, @canada, @new_zealand])
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should give top score for the correct one" do
|
37
|
+
score = @trivia.assess_answer([@iceland, @canada, @new_zealand])
|
38
|
+
score.should equal(3)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should give a point for each correct position" do
|
42
|
+
score = @trivia.assess_answer([@canada, @iceland, @new_zealand])
|
43
|
+
score.should equal(1)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should return zero if none of the positions is asserted" do
|
47
|
+
score = @trivia.assess_answer([@canada, @new_zealand, @iceland])
|
48
|
+
score.should equal(0)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should get the trivia subjects of the right class" do
|
53
|
+
Country.expects(:find).with(:all).returns([@iceland, @canada, @new_zealand])
|
54
|
+
@trivia.get_subjects
|
55
|
+
end
|
56
|
+
|
57
|
+
describe "fetching the solution" do
|
58
|
+
before do
|
59
|
+
@solution = @trivia.get_solution_values
|
60
|
+
end
|
61
|
+
it "should have the length of the trivia" do
|
62
|
+
@solution.should have(3).items
|
63
|
+
end
|
64
|
+
it "should fetch the correct one" do
|
65
|
+
@solution.should eql([["Iceland", 0.968], ["Canada", 0.967], ["New Zealand", 0.944]])
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "A TriviaAnswer" do
|
72
|
+
before do
|
73
|
+
rebuild_all_tables
|
74
|
+
@user = User.create(:login => "bob")
|
75
|
+
@trivia = Trivia.create(:on => "country", :about => "hdi", :displayed => "name", :length => 3)
|
76
|
+
@trivia_answer = TriviaAnswer.create(:user => @user, :trivia => @trivia)
|
77
|
+
|
78
|
+
@iceland = Country.create(:hdi => 0.968)
|
79
|
+
@canada = Country.create(:hdi => 0.967)
|
80
|
+
@new_zealand = Country.create(:hdi => 0.944)
|
81
|
+
end
|
82
|
+
|
83
|
+
describe "being assessed" do
|
84
|
+
describe "by ids" do
|
85
|
+
it "should return the correct score" do
|
86
|
+
@trivia_answer.assess([@iceland.id, @canada.id, @new_zealand.id]).should equal(3)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "An acts_as_trivia enabled model class" do
|
93
|
+
before do
|
94
|
+
Country.class_eval do
|
95
|
+
acts_as_trivia :hdi
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should respond to the generated trivia accessor" do
|
100
|
+
Country.should respond_to(:trivia_answer_for)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
describe "a user" do
|
105
|
+
before do
|
106
|
+
rebuild_all_tables
|
107
|
+
class User < ActiveRecord::Base
|
108
|
+
has_many :trivia_answers
|
109
|
+
has_many :trivias, :through => :trivia_answers
|
110
|
+
end
|
111
|
+
@user = User.create(:login => "bob")
|
112
|
+
@trivia = Trivia.create(:on => "country", :about => "hdi", :displayed => "name", :length => 3)
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should be easily added a trivia he played" do
|
116
|
+
@user.add_trivia(@trivia)
|
117
|
+
@user.trivias.should include(@trivia)
|
118
|
+
end
|
119
|
+
|
120
|
+
it "should return true when asked if played a trivia he played" do
|
121
|
+
@user.trivias << @trivia
|
122
|
+
@user.played_trivia?(@trivia).should be_true
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should return false when asked if played a trivia he did not play" do
|
126
|
+
another_trivia = Trivia.create(:on => "country", :about => "population")
|
127
|
+
@user.played_trivia?(another_trivia).should be_false
|
128
|
+
end
|
129
|
+
|
130
|
+
it "should have 0 trivia points when he has not played any trivia" do
|
131
|
+
@user.trivia_answers = []
|
132
|
+
@user.trivia_points.should eql(0)
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should be able to tell the total trivia points he earned" do
|
136
|
+
a_trivia = Trivia.create(:on => "country", :about => "hdi")
|
137
|
+
another_trivia = Trivia.create(:on => "country", :about => "population")
|
138
|
+
@user.trivia_answers.create(:trivia => a_trivia, :points => 2)
|
139
|
+
@user.trivia_answers.create(:trivia => another_trivia, :points => 3)
|
140
|
+
@user.trivia_points.should eql(5)
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
data/spec/database.yml
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require "active_record"
|
3
|
+
|
4
|
+
# setting up test environment is snatched from how Paperclip does it
|
5
|
+
ROOT = File.join(File.dirname(__FILE__), '..')
|
6
|
+
$LOAD_PATH << File.join(ROOT, 'lib')
|
7
|
+
$LOAD_PATH << File.join(ROOT, 'lib', 'acts_as_trivia')
|
8
|
+
|
9
|
+
require File.join(ROOT, "lib", "acts_as_trivia.rb")
|
10
|
+
|
11
|
+
ENV['RAILS_ENV'] ||= 'test'
|
12
|
+
|
13
|
+
config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
|
14
|
+
ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
|
15
|
+
ActiveRecord::Base.establish_connection(config['test'])
|
16
|
+
|
17
|
+
def rebuild_trivias_table
|
18
|
+
ActiveRecord::Base.connection.create_table :trivias, :force => true do |table|
|
19
|
+
table.column :on, :string
|
20
|
+
table.column :about, :string
|
21
|
+
table.column :displayed, :string
|
22
|
+
table.column :length, :integer
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def rebuild_trivia_answers_table
|
27
|
+
ActiveRecord::Base.connection.create_table :trivia_answers, :force => true do |table|
|
28
|
+
table.column :user_id, :string
|
29
|
+
table.column :trivia_id, :string
|
30
|
+
table.column :points, :integer, :default => 0
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def rebuild_countries_table
|
35
|
+
ActiveRecord::Base.connection.create_table :countries, :force => true do |table|
|
36
|
+
table.column :hdi, :float
|
37
|
+
table.column :population, :integer
|
38
|
+
table.column :area, :integer
|
39
|
+
table.column :name, :string
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def rebuild_users_table
|
44
|
+
ActiveRecord::Base.connection.create_table :users, :force => true do |table|
|
45
|
+
table.column :login, :string
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def rebuild_all_tables
|
50
|
+
rebuild_trivias_table
|
51
|
+
rebuild_trivia_answers_table
|
52
|
+
rebuild_countries_table
|
53
|
+
rebuild_users_table
|
54
|
+
end
|
data/todos.markdown
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
TODO
|
2
|
+
====
|
3
|
+
|
4
|
+
* the show action of the trivia should only be shown to users who have already played that trivia.
|
5
|
+
* set up a template to generate a country-trivia site for quick testing
|
6
|
+
* find a solution so that the methods defined in TriviasHelper are only available to the trivias and trivia_answers controller. Currently, it is available to all controllers. Maybe set up an app structure in the gem like in tog plugins? (In tog plugins, controllers in the host app can extend/overwrite those defined in the plugin)
|
7
|
+
|
8
|
+
DONE
|
9
|
+
====
|
10
|
+
|
11
|
+
* a user should not be able to answer a question more than once
|
12
|
+
* rewrite the trivia_answer/assess spec to actually test the result, not the delegation
|
13
|
+
* the @trivia.length.times <%= trivia_dropdown(@trivia) %> could be rewritten into a simpler <%= trivia_panel(@trivia) %> helper.
|
14
|
+
* autoload does not play well with Rails's autoload in dev. environment, so it has to be rewritten
|
15
|
+
* the show action of the trivia should show the correct solution and the page should
|
16
|
+
* the trivia will have to include how many items have to be asserted (that is, the length of the trivia) since that has to be known on many screens. A sensitive default can be three. Rewrite methods where an actual number is written instead of this value.
|
17
|
+
* get the trivia and trivia answer views use the trivias_helper.rb file and so helper.rb does not have to be generated into the host app's code
|
18
|
+
* the show page of the trivia answer should show the solution of the trivia and mark which ones the user got right. After a user answered a trivia question, the redirect should land here. So does the answer have to be stored in the TriviaAnswer instance to make this detailed assessment? The other solution is to tell him how many he got right and then have a link to the trivia where the solution is presented.
|
19
|
+
The solution should not be stored in the trivia answer. Rather, the show action of the trivia should show the correct solution and the page should only be shown to users who have already played that trivia.
|
20
|
+
|
21
|
+
* generate a migration that creates the trivia record(s) itself (themselves)
|
22
|
+
|
23
|
+
e.g Trivia.create(:on => "country", :about => "hdi")
|
24
|
+
|
25
|
+
This generator can be another one since this one should be called for each subsequent trivia question the developer comes up with.
|
26
|
+
|
metadata
ADDED
@@ -0,0 +1,90 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: balinterdi-acts_as_trivia
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "0.1"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Balint Erdi
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-05-04 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: This gem will add the possibility to turn your Rails application into a trivia game with the ease of generating a migration. The only thing you need is a model class with a sortable attribute and this gem.
|
17
|
+
email: balint.erdi@gmail.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- CHANGELOG
|
24
|
+
- lib/acts_as_trivia/trivia.rb
|
25
|
+
- lib/acts_as_trivia/trivia_answer.rb
|
26
|
+
- lib/acts_as_trivia/trivia_answers_controller.rb
|
27
|
+
- lib/acts_as_trivia/trivias_helper.rb
|
28
|
+
- lib/acts_as_trivia/user.rb
|
29
|
+
- lib/acts_as_trivia.rb
|
30
|
+
- README.markdown
|
31
|
+
- tasks/acts_as_trivia.rake
|
32
|
+
files:
|
33
|
+
- CHANGELOG
|
34
|
+
- generators/acts_as_trivia/acts_as_trivia_generator.rb
|
35
|
+
- generators/acts_as_trivia/templates/answers_controller.rb
|
36
|
+
- generators/acts_as_trivia/templates/controller.rb
|
37
|
+
- generators/acts_as_trivia/templates/trivias_migration.rb
|
38
|
+
- generators/acts_as_trivia/templates/view.html.erb
|
39
|
+
- generators/acts_as_trivia/USAGE
|
40
|
+
- generators/acts_as_trivia_record/acts_as_trivia_record_generator.rb
|
41
|
+
- generators/acts_as_trivia_record/templates/migration.rb
|
42
|
+
- generators/acts_as_trivia_record/USAGE
|
43
|
+
- lib/acts_as_trivia/trivia.rb
|
44
|
+
- lib/acts_as_trivia/trivia_answer.rb
|
45
|
+
- lib/acts_as_trivia/trivia_answers_controller.rb
|
46
|
+
- lib/acts_as_trivia/trivias_helper.rb
|
47
|
+
- lib/acts_as_trivia/user.rb
|
48
|
+
- lib/acts_as_trivia.rb
|
49
|
+
- Manifest
|
50
|
+
- Rakefile
|
51
|
+
- README.markdown
|
52
|
+
- spec/acts_as_trivia_spec.rb
|
53
|
+
- spec/database.yml
|
54
|
+
- spec/spec_helper.rb
|
55
|
+
- tasks/acts_as_trivia.rake
|
56
|
+
- todos.markdown
|
57
|
+
- acts_as_trivia.gemspec
|
58
|
+
has_rdoc: true
|
59
|
+
homepage: http://github.com/balinterdi/acts_as_trivia
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options:
|
62
|
+
- --line-numbers
|
63
|
+
- --inline-source
|
64
|
+
- --title
|
65
|
+
- Acts_as_trivia
|
66
|
+
- --main
|
67
|
+
- README.markdown
|
68
|
+
require_paths:
|
69
|
+
- lib
|
70
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: "0"
|
75
|
+
version:
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: "1.2"
|
81
|
+
version:
|
82
|
+
requirements: []
|
83
|
+
|
84
|
+
rubyforge_project: acts_as_trivia
|
85
|
+
rubygems_version: 1.2.0
|
86
|
+
signing_key:
|
87
|
+
specification_version: 2
|
88
|
+
summary: This gem will add the possibility to turn your Rails application into a trivia game with the ease of generating a migration. The only thing you need is a model class with a sortable attribute and this gem.
|
89
|
+
test_files: []
|
90
|
+
|