census 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (79) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +5 -0
  3. data/Rakefile +70 -0
  4. data/VERSION +1 -0
  5. data/app/controllers/census/data_groups_controller.rb +44 -0
  6. data/app/helpers/census_helper.rb +15 -0
  7. data/app/models/answer.rb +43 -0
  8. data/app/models/choice.rb +9 -0
  9. data/app/models/data_group.rb +10 -0
  10. data/app/models/question.rb +54 -0
  11. data/app/views/census/_question_fields.html.erb +40 -0
  12. data/app/views/census/_user_answers.html.erb +10 -0
  13. data/app/views/census/_user_questions.html.erb +10 -0
  14. data/app/views/census/data_groups/_choice_fields.html.erb +4 -0
  15. data/app/views/census/data_groups/_form.html.erb +11 -0
  16. data/app/views/census/data_groups/_question_fields.html.erb +22 -0
  17. data/app/views/census/data_groups/edit.html.erb +7 -0
  18. data/app/views/census/data_groups/index.html.erb +10 -0
  19. data/app/views/census/data_groups/new.html.erb +7 -0
  20. data/config/routes.rb +8 -0
  21. data/generators/census/USAGE +1 -0
  22. data/generators/census/census_generator.rb +39 -0
  23. data/generators/census/lib/insert_commands.rb +33 -0
  24. data/generators/census/lib/rake_commands.rb +22 -0
  25. data/generators/census/templates/README +29 -0
  26. data/generators/census/templates/census.js +10 -0
  27. data/generators/census/templates/census.rb +14 -0
  28. data/generators/census/templates/factories.rb +24 -0
  29. data/generators/census/templates/migrations/with_users.rb +60 -0
  30. data/generators/census/templates/migrations/without_users.rb +54 -0
  31. data/generators/census/templates/user.rb +3 -0
  32. data/lib/census/data_type.rb +33 -0
  33. data/lib/census/user.rb +85 -0
  34. data/lib/census.rb +1 -0
  35. data/rails/init.rb +7 -0
  36. data/shoulda_macros/census.rb +35 -0
  37. data/test/controllers/data_groups_controller_test.rb +165 -0
  38. data/test/models/answer_test.rb +44 -0
  39. data/test/models/choice_test.rb +24 -0
  40. data/test/models/data_group_test.rb +12 -0
  41. data/test/models/question_test.rb +213 -0
  42. data/test/models/user_test.rb +9 -0
  43. data/test/rails_root/app/controllers/application_controller.rb +10 -0
  44. data/test/rails_root/app/helpers/application_helper.rb +3 -0
  45. data/test/rails_root/app/models/user.rb +3 -0
  46. data/test/rails_root/config/boot.rb +110 -0
  47. data/test/rails_root/config/environment.rb +8 -0
  48. data/test/rails_root/config/environments/development.rb +17 -0
  49. data/test/rails_root/config/environments/production.rb +28 -0
  50. data/test/rails_root/config/environments/test.rb +32 -0
  51. data/test/rails_root/config/initializers/backtrace_silencers.rb +7 -0
  52. data/test/rails_root/config/initializers/census.rb +14 -0
  53. data/test/rails_root/config/initializers/inflections.rb +10 -0
  54. data/test/rails_root/config/initializers/mime_types.rb +5 -0
  55. data/test/rails_root/config/initializers/new_rails_defaults.rb +21 -0
  56. data/test/rails_root/config/initializers/session_store.rb +15 -0
  57. data/test/rails_root/config/routes.rb +43 -0
  58. data/test/rails_root/db/migrate/20100406160306_create_census_tables.rb +60 -0
  59. data/test/rails_root/db/schema.rb +58 -0
  60. data/test/rails_root/test/factories/census.rb +24 -0
  61. data/test/rails_root/test/performance/browsing_test.rb +9 -0
  62. data/test/rails_root/test/test_helper.rb +38 -0
  63. data/test/rails_root/vendor/gems/acts_as_list-0.1.2/lib/acts_as_list.rb +254 -0
  64. data/test/rails_root/vendor/gems/acts_as_list-0.1.2/test/list_test.rb +369 -0
  65. data/test/rails_root/vendor/gems/inverse_of-0.0.1/install.rb +1 -0
  66. data/test/rails_root/vendor/gems/inverse_of-0.0.1/lib/inverse_of.rb +293 -0
  67. data/test/rails_root/vendor/gems/inverse_of-0.0.1/rails/init.rb +1 -0
  68. data/test/rails_root/vendor/gems/inverse_of-0.0.1/test/cases/helper.rb +28 -0
  69. data/test/rails_root/vendor/gems/inverse_of-0.0.1/test/cases/inverse_associations_test.rb +567 -0
  70. data/test/rails_root/vendor/gems/inverse_of-0.0.1/test/models/club.rb +13 -0
  71. data/test/rails_root/vendor/gems/inverse_of-0.0.1/test/models/face.rb +7 -0
  72. data/test/rails_root/vendor/gems/inverse_of-0.0.1/test/models/interest.rb +5 -0
  73. data/test/rails_root/vendor/gems/inverse_of-0.0.1/test/models/man.rb +9 -0
  74. data/test/rails_root/vendor/gems/inverse_of-0.0.1/test/models/sponsor.rb +4 -0
  75. data/test/rails_root/vendor/gems/inverse_of-0.0.1/test/models/zine.rb +3 -0
  76. data/test/rails_root/vendor/gems/inverse_of-0.0.1/test/schema/schema.rb +32 -0
  77. data/test/rails_root/vendor/gems/inverse_of-0.0.1/uninstall.rb +1 -0
  78. data/test/test_helper.rb +19 -0
  79. metadata +190 -0
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Envy Labs LLC
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.rdoc ADDED
@@ -0,0 +1,5 @@
1
+ = Census
2
+
3
+ Census is a Rails plugin that collects searchable demographics data for each
4
+ of your application's users. The data to be collected is defined using a simple
5
+ admin interface that Census provides.
data/Rakefile ADDED
@@ -0,0 +1,70 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+
5
+ begin
6
+ require 'jeweler'
7
+ Jeweler::Tasks.new do |gem|
8
+ gem.name = "census"
9
+ gem.summary = %Q{Rails user demographics collection and searching}
10
+ gem.description = %Q{Census is a Rails plugin that collects searchable demographics data for each of your application's users.}
11
+ gem.email = "mark@envylabs.com"
12
+ gem.homepage = "http://github.com/envylabs/census"
13
+ gem.authors = ["Mark Kendall"]
14
+ gem.files = FileList["[A-Z]*", "{app,config,generators,lib,shoulda_macros,rails}/**/*"]
15
+
16
+ gem.add_dependency "acts_as_list", ">= 0.1.2"
17
+ gem.add_dependency "inverse_of", ">= 0.0.1"
18
+
19
+ gem.add_development_dependency "shoulda", ">= 0"
20
+ gem.add_development_dependency "factory_girl", ">= 0"
21
+ end
22
+ Jeweler::GemcutterTasks.new
23
+ rescue LoadError
24
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
25
+ end
26
+
27
+ namespace :test do
28
+ Rake::TestTask.new(:basic => ["check_dependencies",
29
+ "generator:cleanup",
30
+ "generator:census"]) do |task|
31
+ task.libs << "lib"
32
+ task.libs << "test"
33
+ task.pattern = "test/{controllers,models}/*_test.rb"
34
+ task.verbose = false
35
+ end
36
+ end
37
+
38
+ task :default => ['test:basic']
39
+
40
+ generators = %w(census)
41
+
42
+ namespace :generator do
43
+ desc "Cleans up the test app before running the generator"
44
+ task :cleanup do
45
+ FileList["test/rails_root/db/**/*"].each do |each|
46
+ FileUtils.rm_rf(each)
47
+ end
48
+
49
+ FileUtils.rm_rf("test/rails_root/vendor/plugins/census")
50
+ FileUtils.mkdir_p("test/rails_root/vendor/plugins")
51
+ census_root = File.expand_path(File.dirname(__FILE__))
52
+ system("ln -s \"#{census_root}\" test/rails_root/vendor/plugins/census")
53
+ end
54
+
55
+ desc "Run the census generator"
56
+ task :census do
57
+ system "cd test/rails_root && ./script/generate census -f && rake gems:unpack && rake db:migrate db:test:prepare"
58
+ end
59
+
60
+ end
61
+
62
+ require 'rake/rdoctask'
63
+ Rake::RDocTask.new do |rdoc|
64
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
65
+
66
+ rdoc.rdoc_dir = 'rdoc'
67
+ rdoc.title = "Census #{version}"
68
+ rdoc.rdoc_files.include('README*')
69
+ rdoc.rdoc_files.include('lib/**/*.rb')
70
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,44 @@
1
+ class Census::DataGroupsController < ApplicationController
2
+
3
+ def index
4
+ @data_groups = DataGroup.all(:order => :position)
5
+ end
6
+
7
+ def new
8
+ @data_group = DataGroup.new(params[:data_group])
9
+ end
10
+
11
+ def create
12
+ @data_group = DataGroup.new(params[:data_group])
13
+
14
+ if @data_group.save
15
+ flash[:notice] = "Created #{@data_group.name}"
16
+ redirect_to census_admin_path
17
+ else
18
+ render :action => 'new', :status => :unprocessable_entity
19
+ end
20
+ end
21
+
22
+ def edit
23
+ @data_group = DataGroup.find(params[:id])
24
+ end
25
+
26
+ def update
27
+ @data_group = DataGroup.find(params[:id])
28
+
29
+ if @data_group.update_attributes(params[:data_group])
30
+ flash[:notice] = "Saved #{@data_group.name}"
31
+ redirect_to census_admin_path
32
+ else
33
+ render :action => 'edit', :status => :unprocessable_entity
34
+ end
35
+ end
36
+
37
+ def destroy
38
+ @data_group = DataGroup.find(params[:id])
39
+ @data_group.destroy
40
+ flash[:notice] = "Deleted #{@data_group.name}"
41
+ redirect_to census_admin_path
42
+ end
43
+
44
+ end
@@ -0,0 +1,15 @@
1
+ module CensusHelper
2
+
3
+ def link_to_remove_fields(name, form)
4
+ form.hidden_field(:_destroy) + link_to_function(name, "remove_fields(this)")
5
+ end
6
+
7
+ def link_to_add_fields(name, form, association)
8
+ new_object = form.object.class.reflect_on_association(association).klass.new
9
+ fields = form.fields_for(association, new_object, :child_index => "new_#{association}") do |builder|
10
+ render(association.to_s.singularize + "_fields", :form => builder)
11
+ end
12
+ link_to_function(name, h("add_fields(this, \"#{association}\", \"#{escape_javascript(fields)}\")"))
13
+ end
14
+
15
+ end
@@ -0,0 +1,43 @@
1
+ class Answer < ActiveRecord::Base
2
+
3
+ belongs_to :question
4
+ belongs_to :user
5
+
6
+ validates_presence_of :question,
7
+ :user
8
+
9
+ validate :ensure_valid_choice
10
+ validate :ensure_valid_data_type
11
+ validate :check_multiple_answers
12
+
13
+ named_scope :for_user, lambda { |user| { :conditions => {:user_id => user.id} } }
14
+
15
+ def formatted_data
16
+ question.format_data(self.data)
17
+ end
18
+
19
+ def to_s
20
+ question.to_s(self.data)
21
+ end
22
+
23
+
24
+ private
25
+
26
+
27
+ def ensure_valid_choice
28
+ return if question.blank? || data.blank?
29
+ errors.add_to_base("Invalid choice for #{question.prompt}") if question.restrict_values? && !question.choices.map(&:value).include?(self.data)
30
+ end
31
+
32
+ def ensure_valid_data_type
33
+ return if question.blank? || data.blank?
34
+ message = question.validate_data(data)
35
+ errors.add_to_base("#{question.prompt} #{message}") if message
36
+ end
37
+
38
+ def check_multiple_answers
39
+ return if question.blank? || user.blank?
40
+ errors.add_to_base("Only one answer allowed for #{question.prompt}") if new_record? && question.answers.for_user(user).size > 0 && !question.multiple?
41
+ end
42
+
43
+ end
@@ -0,0 +1,9 @@
1
+ class Choice < ActiveRecord::Base
2
+
3
+ belongs_to :question, :inverse_of => :choices
4
+ acts_as_list :scope => :question
5
+
6
+ validates_presence_of :value,
7
+ :question
8
+
9
+ end
@@ -0,0 +1,10 @@
1
+ class DataGroup < ActiveRecord::Base
2
+
3
+ acts_as_list
4
+
5
+ has_many :questions, :dependent => :destroy, :inverse_of => :data_group
6
+ accepts_nested_attributes_for :questions, :reject_if => lambda { |a| a[:prompt].blank? }, :allow_destroy => true
7
+
8
+ validates_presence_of :name
9
+
10
+ end
@@ -0,0 +1,54 @@
1
+ class Question < ActiveRecord::Base
2
+
3
+ belongs_to :data_group, :inverse_of => :questions
4
+ acts_as_list :scope => :data_group
5
+
6
+ has_many :choices, :dependent => :destroy, :inverse_of => :question
7
+ accepts_nested_attributes_for :choices, :reject_if => lambda { |a| a[:value].blank? }, :allow_destroy => true
8
+
9
+ has_many :answers, :dependent => :destroy
10
+
11
+ validates_presence_of :prompt,
12
+ :data_group
13
+
14
+ def sql_transform(column_name = '?')
15
+ data_type_definition.sql_transform.call(column_name)
16
+ end
17
+
18
+ def format_data(data)
19
+ data_type_definition.format_data.call(data)
20
+ end
21
+
22
+ def validate_data(data)
23
+ data_type_definition.validate_data.call(data)
24
+ end
25
+
26
+ def to_s(data)
27
+ format_data(data).to_s
28
+ end
29
+
30
+ def find_answers_matching(value)
31
+ answers.find(:all, :conditions => conditions_for(value), :include => :user)
32
+ end
33
+
34
+ def restrict_values?
35
+ choices.present? && !other?
36
+ end
37
+
38
+
39
+ private
40
+
41
+
42
+ def data_type_definition
43
+ Census::DataType.find(data_type) || Census::DataType.find('String')
44
+ end
45
+
46
+ def conditions_for(value)
47
+ if value.kind_of?(Range) || value.kind_of?(Array)
48
+ ["#{sql_transform('data')} IN (?)", value]
49
+ else
50
+ ["#{sql_transform('data')} = #{sql_transform}", value]
51
+ end
52
+ end
53
+
54
+ end
@@ -0,0 +1,40 @@
1
+ <% if question.choices.empty? -%>
2
+ <% answer = user.first_answer_for(question) -%>
3
+ <% fields_for "user[answers_attributes][#{user.answers.index(answer)}]", answer do |builder| -%>
4
+ <%= builder.hidden_field :id %>
5
+ <%= builder.hidden_field :question_id %>
6
+ <div class="text_field">
7
+ <%= builder.label :data, question.prompt %>
8
+ <%= builder.text_field :data %>
9
+ </div>
10
+ <% end -%>
11
+
12
+ <% elsif question.multiple? -%>
13
+ <div class="checkboxes">
14
+ <%= label_tag question.prompt %>
15
+ <ul>
16
+ <% question.choices.each do |choice| -%>
17
+ <% answer = user.answer_for_choice(choice) -%>
18
+ <% fields_for "user[answers_attributes][#{user.answers.index(answer)}]", answer do |builder| -%>
19
+ <%= builder.hidden_field :id %>
20
+ <%= builder.hidden_field :question_id %>
21
+ <li>
22
+ <%= builder.check_box :data, {}, choice.value, '' %>
23
+ <%= builder.label :data, choice.value %>
24
+ </li>
25
+ <% end -%>
26
+ <% end -%>
27
+ </ul>
28
+ </div>
29
+
30
+ <% else -%>
31
+ <% answer = user.first_answer_for(question) -%>
32
+ <% fields_for "user[answers_attributes][#{user.answers.index(answer)}]", answer do |builder| -%>
33
+ <%= builder.hidden_field :id %>
34
+ <%= builder.hidden_field :question_id %>
35
+ <div class="select_field">
36
+ <%= builder.label :data, question.prompt %>
37
+ <%= builder.collection_select :data, question.choices, :value, :value, :include_blank => true %>
38
+ </div>
39
+ <% end -%>
40
+ <% end -%>
@@ -0,0 +1,10 @@
1
+ <div class="census_answers">
2
+ <% DataGroup.all.each do |group| -%>
3
+ <h3><%=h group.name %></h3>
4
+ <ul>
5
+ <% group.questions.each do |question| -%>
6
+ <li><b><%=h question.prompt %></b> <%=h user.all_answers_for(question).map(&:data).join(', ') %></li>
7
+ <% end -%>
8
+ </ul>
9
+ <% end -%>
10
+ </div>
@@ -0,0 +1,10 @@
1
+ <div class="census_questions">
2
+ <% DataGroup.all.each do |group| -%>
3
+ <fieldset>
4
+ <legend><%=h group.name %></legend>
5
+ <% group.questions.each do |question| -%>
6
+ <%= render 'census/question_fields', :question => question, :user => user %>
7
+ <% end -%>
8
+ </fieldset>
9
+ <% end -%>
10
+ </div>
@@ -0,0 +1,4 @@
1
+ <div class="fields">
2
+ <%= form.text_field :value %>
3
+ <%= link_to_remove_fields "remove", form %>
4
+ </div>
@@ -0,0 +1,11 @@
1
+ <%= form.error_messages %>
2
+ <div class="text_field">
3
+ <%= form.label :name, "Group Name" %>
4
+ <%= form.text_field :name %>
5
+ </div>
6
+ <% form.fields_for :questions do |builder| %>
7
+ <%= render "question_fields", :form => builder %>
8
+ <% end %>
9
+ <div>
10
+ <%= link_to_add_fields "Add Question", form, :questions %>
11
+ </div>
@@ -0,0 +1,22 @@
1
+ <fieldset class="fields">
2
+ <legend>Question <%= form.object.position %></legend>
3
+ <div class="question">
4
+ <%= form.label :prompt, "Label" %>
5
+ <%= form.text_field :prompt %>
6
+ <%= link_to_remove_fields "remove", form %>
7
+ <br/>
8
+ <%= form.label :data_type %>
9
+ <%= form.collection_select :data_type, Census::DataType.all, :name, :name %>
10
+ </div>
11
+ <fieldset>
12
+ <legend>Answer Choices (leave empty to allow freeform text entry)</legend>
13
+ <% form.fields_for :choices do |builder| %>
14
+ <%= render 'choice_fields', :form => builder %>
15
+ <% end %>
16
+ <div>
17
+ <%= link_to_add_fields "Add Answer", form, :choices %>
18
+ </div>
19
+ <%= form.check_box :multiple %>
20
+ <%= form.label :multiple, "Allow multiple selections" %>
21
+ </fieldset>
22
+ </fieldset>
@@ -0,0 +1,7 @@
1
+ <% form_for [:census, @data_group], :html => { :class => "census_data_group_form" } do |form| %>
2
+ <fieldset>
3
+ <legend>Edit Census Data Group</legend>
4
+ <%= render :partial => 'form', :object => form %>
5
+ <%= form.submit 'Save', :disable_with => 'Please wait...' %>
6
+ </fieldset>
7
+ <% end %>
@@ -0,0 +1,10 @@
1
+ <h2>Census Data Groups</h2>
2
+ <ul class="census_data_group_list">
3
+ <% @data_groups.each do |group| %>
4
+ <li>
5
+ <%=link_to group.name, edit_census_data_group_path(group) %>
6
+ </li>
7
+ <% end %>
8
+ </ul>
9
+
10
+ <%= link_to 'New Group', new_census_data_group_path %>
@@ -0,0 +1,7 @@
1
+ <% form_for [:census, @data_group], :html => { :class => "census_data_group_form" } do |form| %>
2
+ <fieldset>
3
+ <legend>New Census Data Group</legend>
4
+ <%= render :partial => 'form', :object => form %>
5
+ <%= form.submit 'Save', :disable_with => 'Please wait...' %>
6
+ </fieldset>
7
+ <% end %>
data/config/routes.rb ADDED
@@ -0,0 +1,8 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+
3
+ map.namespace :census do |census|
4
+ census.resources :data_groups, :except => [:index, :show]
5
+ census.admin 'admin', :controller => 'data_groups', :action => 'index'
6
+ end
7
+
8
+ end
@@ -0,0 +1 @@
1
+ script/generate census
@@ -0,0 +1,39 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/lib/insert_commands.rb")
2
+ require File.expand_path(File.dirname(__FILE__) + "/lib/rake_commands.rb")
3
+
4
+ class CensusGenerator < Rails::Generator::Base
5
+
6
+ def manifest
7
+ record do |m|
8
+ m.directory File.join("config", "initializers")
9
+ m.file "census.rb", "config/initializers/census.rb"
10
+
11
+ m.directory File.join("public", "javascripts")
12
+ m.file "census.js", "public/javascripts/census.js"
13
+
14
+ user_model = "app/models/user.rb"
15
+ if File.exists?(user_model)
16
+ m.insert_into user_model, "include Census::User"
17
+ else
18
+ m.directory File.join("app", "models")
19
+ m.file "user.rb", user_model
20
+ end
21
+
22
+ m.directory File.join("test", "factories")
23
+ m.file "factories.rb", "test/factories/census.rb"
24
+
25
+ if ActiveRecord::Base.connection.table_exists?(:users)
26
+ m.migration_template "migrations/without_users.rb",
27
+ 'db/migrate',
28
+ :migration_file_name => "create_census_tables"
29
+ else
30
+ m.migration_template "migrations/with_users.rb",
31
+ 'db/migrate',
32
+ :migration_file_name => "create_census_tables"
33
+ end
34
+
35
+ m.readme "README"
36
+ end
37
+ end
38
+
39
+ end
@@ -0,0 +1,33 @@
1
+ # Mostly pinched from http://github.com/ryanb/nifty-generators/tree/master
2
+
3
+ Rails::Generator::Commands::Base.class_eval do
4
+ def file_contains?(relative_destination, line)
5
+ File.read(destination_path(relative_destination)).include?(line)
6
+ end
7
+ end
8
+
9
+ Rails::Generator::Commands::Create.class_eval do
10
+ def insert_into(file, line)
11
+ logger.insert "#{line} into #{file}"
12
+ unless options[:pretend] || file_contains?(file, line)
13
+ gsub_file file, /^(class|module|.*Routes).*$/ do |match|
14
+ "#{match}\n #{line}"
15
+ end
16
+ end
17
+ end
18
+ end
19
+
20
+ Rails::Generator::Commands::Destroy.class_eval do
21
+ def insert_into(file, line)
22
+ logger.remove "#{line} from #{file}"
23
+ unless options[:pretend]
24
+ gsub_file file, "\n #{line}", ''
25
+ end
26
+ end
27
+ end
28
+
29
+ Rails::Generator::Commands::List.class_eval do
30
+ def insert_into(file, line)
31
+ logger.insert "#{line} into #{file}"
32
+ end
33
+ end
@@ -0,0 +1,22 @@
1
+ Rails::Generator::Commands::Create.class_eval do
2
+ def rake_db_migrate
3
+ logger.rake "db:migrate"
4
+ unless system("rake db:migrate")
5
+ logger.rake "db:migrate failed. Rolling back"
6
+ command(:destroy).invoke!
7
+ end
8
+ end
9
+ end
10
+
11
+ Rails::Generator::Commands::Destroy.class_eval do
12
+ def rake_db_migrate
13
+ logger.rake "db:rollback"
14
+ system "rake db:rollback"
15
+ end
16
+ end
17
+
18
+ Rails::Generator::Commands::List.class_eval do
19
+ def rake_db_migrate
20
+ logger.rake "db:migrate"
21
+ end
22
+ end
@@ -0,0 +1,29 @@
1
+
2
+ *******************************************************************************
3
+
4
+ Next:
5
+
6
+ 1. In order for the question admin views to work, you'll need to include both
7
+ jQuery and the census.js file in your application layout:
8
+
9
+ <%= javascript_include_tag 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js' %>
10
+ <%= javascript_include_tag 'census' %>
11
+
12
+ 2. Add a link to the question admin page somewhere in your app:
13
+
14
+ <%= link_to 'Set up questions', census_admin_path %>
15
+
16
+ 3. Include the partial that displays answers in your user show page:
17
+
18
+ <%= render 'census/user_answers', :user => @user %>
19
+
20
+ 4. Include the partial that allows the user to enter answers in your user
21
+ edit page:
22
+
23
+ <%= render 'census/user_questions', :user => @user %>
24
+
25
+ 5. Migrate your database:
26
+
27
+ rake db:migrate
28
+
29
+ *******************************************************************************
@@ -0,0 +1,10 @@
1
+ function remove_fields(link) {
2
+ $(link).prev("input[type=hidden]").val("1");
3
+ $(link).closest(".fields").hide();
4
+ }
5
+
6
+ function add_fields(link, association, content) {
7
+ var new_id = new Date().getTime();
8
+ var regexp = new RegExp("new_" + association, "g")
9
+ $(link).parent().before(content.replace(regexp, new_id));
10
+ }
@@ -0,0 +1,14 @@
1
+ Census::DataType.define("String")
2
+
3
+ Census::DataType.define(
4
+ "Number",
5
+ :sql_transform => lambda {|column_name| "CAST(#{column_name} AS SIGNED INTEGER)"},
6
+ :format_data => lambda {|data| data.to_i unless data.blank? },
7
+ :validate_data => lambda {|data| "must be a number" unless data =~ /^\d*$/}
8
+ )
9
+
10
+ Census::DataType.define(
11
+ "Yes/No",
12
+ :sql_transform => lambda {|column_name| "CAST(#{column_name} AS CHAR)"},
13
+ :format_data => lambda {|data| %w(1 T t Y y).include?(data) unless data.blank? }
14
+ )
@@ -0,0 +1,24 @@
1
+ Factory.define :answer do |answer|
2
+ answer.association :question
3
+ answer.association :user
4
+ answer.data 'Factory Answer'
5
+ end
6
+
7
+ Factory.define :choice do |choice|
8
+ choice.association :question
9
+ choice.value 'Factory Choice'
10
+ end
11
+
12
+ Factory.define :data_group do |group|
13
+ group.name 'Factory Data Group'
14
+ end
15
+
16
+ Factory.define :question do |question|
17
+ question.association :data_group
18
+ question.prompt 'Enter your response'
19
+ question.multiple false
20
+ question.other false
21
+ end
22
+
23
+ Factory.define :user do |user|
24
+ end
@@ -0,0 +1,60 @@
1
+ class CreateCensusTables < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :data_groups do |t|
4
+ t.string :name
5
+ t.integer :position
6
+ t.timestamps
7
+ end
8
+
9
+ create_table :questions do |t|
10
+ t.integer :data_group_id
11
+ t.string :data_type
12
+ t.string :prompt
13
+ t.boolean :multiple
14
+ t.boolean :other
15
+ t.integer :position
16
+ t.timestamps
17
+ end
18
+
19
+ add_index :questions, :data_group_id
20
+
21
+ create_table :choices do |t|
22
+ t.integer :question_id
23
+ t.string :value
24
+ t.integer :position
25
+ t.timestamps
26
+ end
27
+
28
+ add_index :choices, :question_id
29
+
30
+ create_table(:users) do |t|
31
+ t.timestamps
32
+ end
33
+
34
+ create_table :answers do |t|
35
+ t.integer :question_id
36
+ t.integer :user_id
37
+ t.string :data
38
+ end
39
+
40
+ add_index :answers, :question_id
41
+ add_index :answers, :user_id
42
+
43
+ end
44
+
45
+ def self.down
46
+ remove_index :answers, :question_id
47
+ remove_index :answers, :user_id
48
+ drop_table :answers
49
+
50
+ drop_table :users
51
+
52
+ remove_index :choices, :question_id
53
+ drop_table :choices
54
+
55
+ remove_index :questions, :data_group_id
56
+ drop_table :questions
57
+
58
+ drop_table :data_groups
59
+ end
60
+ end