surveyor 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/MIT-LICENSE +20 -0
- data/README.md +104 -0
- data/Rakefile +50 -0
- data/VERSION +1 -0
- data/app/controllers/surveyor_controller.rb +117 -0
- data/app/helpers/survey_form_builder.rb +37 -0
- data/app/helpers/surveyor_helper.rb +66 -0
- data/app/models/answer.rb +21 -0
- data/app/models/dependency.rb +46 -0
- data/app/models/dependency_condition.rb +79 -0
- data/app/models/question.rb +54 -0
- data/app/models/question_group.rb +18 -0
- data/app/models/response.rb +47 -0
- data/app/models/response_set.rb +185 -0
- data/app/models/survey.rb +57 -0
- data/app/models/survey_section.rb +15 -0
- data/app/views/layouts/surveyor_default.html.erb +13 -0
- data/app/views/partials/_answer.html.haml +49 -0
- data/app/views/partials/_question.html.haml +73 -0
- data/app/views/partials/_question_group.html.haml +41 -0
- data/app/views/surveyor/edit.html.haml +32 -0
- data/app/views/surveyor/new.html.haml +17 -0
- data/app/views/surveyor/show.html.haml +12 -0
- data/config/routes.rb +10 -0
- data/generators/surveyor/EXTENDING_SURVEYOR +12 -0
- data/generators/surveyor/extend_surveyor_generator.rb +22 -0
- data/generators/surveyor/surveyor_generator.rb +60 -0
- data/generators/surveyor/templates/README +10 -0
- data/generators/surveyor/templates/assets/images/222222_11x11_icon_arrows_leftright.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_11x11_icon_arrows_updown.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_11x11_icon_close.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_11x11_icon_doc.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_11x11_icon_folder_closed.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_11x11_icon_folder_open.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_11x11_icon_minus.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_11x11_icon_plus.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_11x11_icon_resize_se.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_35x9_colorpicker_indicator.gif.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_7x7_arrow_down.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_7x7_arrow_left.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_7x7_arrow_right.gif +0 -0
- data/generators/surveyor/templates/assets/images/222222_7x7_arrow_up.gif +0 -0
- data/generators/surveyor/templates/assets/images/454545_11x11_icon_arrows_leftright.gif +0 -0
- data/generators/surveyor/templates/assets/images/454545_11x11_icon_arrows_updown.gif +0 -0
- data/generators/surveyor/templates/assets/images/454545_11x11_icon_close.gif +0 -0
- data/generators/surveyor/templates/assets/images/454545_11x11_icon_doc.gif +0 -0
- data/generators/surveyor/templates/assets/images/454545_11x11_icon_folder_closed.gif +0 -0
- data/generators/surveyor/templates/assets/images/454545_11x11_icon_folder_open.gif +0 -0
- data/generators/surveyor/templates/assets/images/454545_11x11_icon_minus.gif +0 -0
- data/generators/surveyor/templates/assets/images/454545_11x11_icon_plus.gif +0 -0
- data/generators/surveyor/templates/assets/images/454545_7x7_arrow_down.gif +0 -0
- data/generators/surveyor/templates/assets/images/454545_7x7_arrow_left.gif +0 -0
- data/generators/surveyor/templates/assets/images/454545_7x7_arrow_right.gif +0 -0
- data/generators/surveyor/templates/assets/images/454545_7x7_arrow_up.gif +0 -0
- data/generators/surveyor/templates/assets/images/888888_11x11_icon_arrows_leftright.gif +0 -0
- data/generators/surveyor/templates/assets/images/888888_11x11_icon_arrows_updown.gif +0 -0
- data/generators/surveyor/templates/assets/images/888888_11x11_icon_close.gif +0 -0
- data/generators/surveyor/templates/assets/images/888888_11x11_icon_doc.gif +0 -0
- data/generators/surveyor/templates/assets/images/888888_11x11_icon_folder_closed.gif +0 -0
- data/generators/surveyor/templates/assets/images/888888_11x11_icon_folder_open.gif +0 -0
- data/generators/surveyor/templates/assets/images/888888_11x11_icon_minus.gif +0 -0
- data/generators/surveyor/templates/assets/images/888888_11x11_icon_plus.gif +0 -0
- data/generators/surveyor/templates/assets/images/888888_7x7_arrow_down.gif +0 -0
- data/generators/surveyor/templates/assets/images/888888_7x7_arrow_left.gif +0 -0
- data/generators/surveyor/templates/assets/images/888888_7x7_arrow_right.gif +0 -0
- data/generators/surveyor/templates/assets/images/888888_7x7_arrow_up.gif +0 -0
- data/generators/surveyor/templates/assets/images/dadada_40x100_textures_02_glass_75.png +0 -0
- data/generators/surveyor/templates/assets/images/e6e6e6_40x100_textures_02_glass_75.png +0 -0
- data/generators/surveyor/templates/assets/images/ffffff_40x100_textures_01_flat_0.png +0 -0
- data/generators/surveyor/templates/assets/images/ffffff_40x100_textures_02_glass_65.png +0 -0
- data/generators/surveyor/templates/assets/javascripts/accessibleUISlider.jQuery.js +201 -0
- data/generators/surveyor/templates/assets/javascripts/jquery-1.2.6.js +3549 -0
- data/generators/surveyor/templates/assets/javascripts/jquery-ui-personalized-1.5.3.js +7616 -0
- data/generators/surveyor/templates/assets/javascripts/jquery.form.js +637 -0
- data/generators/surveyor/templates/assets/javascripts/surveyor.js +28 -0
- data/generators/surveyor/templates/assets/stylesheets/jquery-ui-slider-additions.css +71 -0
- data/generators/surveyor/templates/assets/stylesheets/reset.css +46 -0
- data/generators/surveyor/templates/assets/stylesheets/sass/surveyor.sass +245 -0
- data/generators/surveyor/templates/assets/stylesheets/surveyor.css +231 -0
- data/generators/surveyor/templates/assets/stylesheets/ui.theme.css +851 -0
- data/generators/surveyor/templates/extensions/survey_extensions.rb +18 -0
- data/generators/surveyor/templates/extensions/surveyor_controller_extensions.rb +28 -0
- data/generators/surveyor/templates/extensions/surveyor_custom.html.erb +13 -0
- data/generators/surveyor/templates/extensions/surveyor_helper_extensions.rb +18 -0
- data/generators/surveyor/templates/initializers/haml.rb +8 -0
- data/generators/surveyor/templates/initializers/surveyor.rb +11 -0
- data/generators/surveyor/templates/migrate/create_answers.rb +45 -0
- data/generators/surveyor/templates/migrate/create_dependencies.rb +21 -0
- data/generators/surveyor/templates/migrate/create_dependency_conditions.rb +29 -0
- data/generators/surveyor/templates/migrate/create_question_groups.rb +18 -0
- data/generators/surveyor/templates/migrate/create_questions.rb +33 -0
- data/generators/surveyor/templates/migrate/create_response_sets.rb +22 -0
- data/generators/surveyor/templates/migrate/create_responses.rb +33 -0
- data/generators/surveyor/templates/migrate/create_survey_sections.rb +25 -0
- data/generators/surveyor/templates/migrate/create_surveys.rb +25 -0
- data/generators/surveyor/templates/surveys/kitchen_sink_survey.rb +201 -0
- data/generators/surveyor/templates/tasks/surveyor.rb +4 -0
- data/init.rb +1 -0
- data/install.rb +1 -0
- data/lib/surveyor.rb +7 -0
- data/lib/surveyor/config.rb +45 -0
- data/lib/tasks/surveyor_tasks.rake +33 -0
- data/lib/tiny_code.rb +58 -0
- data/lib/xml_formatter.rb +12 -0
- data/script/surveyor/answer.rb +84 -0
- data/script/surveyor/columnizer.rb +36 -0
- data/script/surveyor/dependency.rb +43 -0
- data/script/surveyor/dependency_condition.rb +74 -0
- data/script/surveyor/question.rb +76 -0
- data/script/surveyor/question_group.rb +33 -0
- data/script/surveyor/specs/answer_spec.rb +66 -0
- data/script/surveyor/specs/question_dependency_spec.rb +46 -0
- data/script/surveyor/specs/question_group_spec.rb +9 -0
- data/script/surveyor/specs/question_spec.rb +111 -0
- data/script/surveyor/specs/section_spec.rb +58 -0
- data/script/surveyor/survey.rb +108 -0
- data/script/surveyor/survey_parser.rb +64 -0
- data/script/surveyor/survey_section.rb +153 -0
- data/script/surveyor/whr_dsl.tmproj +244 -0
- data/spec/controllers/surveyor_controller_spec.rb +328 -0
- data/spec/factories.rb +107 -0
- data/spec/models/answer_spec.rb +29 -0
- data/spec/models/dependency_condition_spec.rb +338 -0
- data/spec/models/dependency_spec.rb +82 -0
- data/spec/models/question_group_spec.rb +11 -0
- data/spec/models/question_spec.rb +75 -0
- data/spec/models/response_set_spec.rb +153 -0
- data/spec/models/response_spec.rb +94 -0
- data/spec/models/survey_section_spec.rb +34 -0
- data/spec/models/survey_spec.rb +72 -0
- data/spec/rcov.opts +2 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +14 -0
- data/surveyor.gemspec +187 -0
- data/uninstall.rb +1 -0
- metadata +211 -0
data/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Init hook code here
|
data/install.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Install hook code here
|
data/lib/surveyor.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
module Surveyor
|
2
|
+
#
|
3
|
+
# The Surveyor::Config object emulates a hash with simple bracket methods
|
4
|
+
# which allow you to get and set values in the configuration table:
|
5
|
+
#
|
6
|
+
# Surveyor::Config['setting.name'] = 'value'
|
7
|
+
# Surveyor::Config['setting.name'] #=> "value"
|
8
|
+
#
|
9
|
+
# Currently, there is not a way to edit configuration through the admin
|
10
|
+
# system so it must be done manually. The console script is probably the
|
11
|
+
# easiest way to this:
|
12
|
+
#
|
13
|
+
# % script/console production
|
14
|
+
# Loading production environment.
|
15
|
+
# >> Surveyor::Config['setting.name'] = 'value'
|
16
|
+
# => "value"
|
17
|
+
# >>
|
18
|
+
#
|
19
|
+
# Surveyor currently uses the following settings:
|
20
|
+
#
|
21
|
+
# defaults.title :: the title of the survey system
|
22
|
+
# defaults.layout :: the layout used by the survey system
|
23
|
+
|
24
|
+
class Config
|
25
|
+
@@config_hash = {}
|
26
|
+
|
27
|
+
class << self
|
28
|
+
def [](key)
|
29
|
+
@@config_hash[key]
|
30
|
+
end
|
31
|
+
|
32
|
+
def []=(key, value)
|
33
|
+
@@config_hash[key] = value
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_hash
|
37
|
+
@@config_hash
|
38
|
+
end
|
39
|
+
|
40
|
+
def run
|
41
|
+
yield self if block_given?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
desc "generate and load survey (specify FILE=surveys/your_survey.rb)"
|
2
|
+
task :surveyor => :"surveyor:default"
|
3
|
+
|
4
|
+
namespace :surveyor do
|
5
|
+
|
6
|
+
task :default => [:generate_fixtures, :load_fixtures]
|
7
|
+
|
8
|
+
desc "generate survey fixtures from survey file"
|
9
|
+
task :generate_fixtures => :environment do
|
10
|
+
require File.join(File.dirname(__FILE__), "../../script/surveyor/survey_parser")
|
11
|
+
raise "USAGE: file name required e.g. 'FILE=surveys/kitchen_sink_survey.rb'" if ENV["FILE"].blank?
|
12
|
+
fixture_dir = File.join(RAILS_ROOT, "surveys", "fixtures")
|
13
|
+
mkdir fixture_dir unless File.exists?(fixture_dir)
|
14
|
+
SurveyParser.parse(File.join(RAILS_ROOT, ENV["FILE"]))
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "load survey fixtures"
|
18
|
+
task :load_fixtures => :environment do
|
19
|
+
require 'active_record/fixtures'
|
20
|
+
|
21
|
+
ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
|
22
|
+
|
23
|
+
fixture_dir = File.join(RAILS_ROOT, "surveys", "fixtures")
|
24
|
+
fixtures = Dir.glob("#{fixture_dir}/*.yml")
|
25
|
+
raise "No fixtures found." if fixtures.empty?
|
26
|
+
|
27
|
+
fixtures.each do |file_name|
|
28
|
+
puts "Loading #{file_name}..."
|
29
|
+
Fixtures.create_fixtures(fixture_dir, File.basename(file_name, '.*'))
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
data/lib/tiny_code.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
module TinyCode
|
2
|
+
|
3
|
+
module ClassMethods
|
4
|
+
|
5
|
+
RAND_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "0123456789" + "abcdefghijklmnopqrstuvwxyz"
|
6
|
+
|
7
|
+
def make_tiny_code
|
8
|
+
random_string(10)
|
9
|
+
end
|
10
|
+
|
11
|
+
def random_string(len)
|
12
|
+
rand_max = RAND_CHARS.size
|
13
|
+
ret = ""
|
14
|
+
len.times{ ret << RAND_CHARS[rand(rand_max)] }
|
15
|
+
ret
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
def self.to_normalized_string(text)
|
20
|
+
words_to_omit = ["a", "to", "the", "of", "has", "have", "it", "is", "in", "on", "or", "but", "when", "be"]
|
21
|
+
|
22
|
+
# strip all the html tags from the text data
|
23
|
+
col_text = text.gsub(/(<[^>]*>)|\n|\t/s, ' ')
|
24
|
+
|
25
|
+
# Removing capitalization
|
26
|
+
col_text.downcase!
|
27
|
+
# Removing potential problem characters
|
28
|
+
col_text.gsub!(/\"|\'/, '')
|
29
|
+
# Removing text inside parens
|
30
|
+
col_text.gsub!(/\(.*?\)/,'')
|
31
|
+
|
32
|
+
# Removing all other non-word characters
|
33
|
+
col_text.gsub!(/\W/, ' ')
|
34
|
+
|
35
|
+
column_words = []
|
36
|
+
words = col_text.split(' ')
|
37
|
+
words.each do |word|
|
38
|
+
if !words_to_omit.include?(word)
|
39
|
+
column_words << word
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
#reducing the word list to limit column length
|
44
|
+
if column_words.length > 5
|
45
|
+
column_words.slice!(0, column_words.length - 5)
|
46
|
+
end
|
47
|
+
|
48
|
+
#re-assemble the string
|
49
|
+
column_words.join("_")
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.included(klass)
|
55
|
+
klass.extend(ClassMethods)
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module XmlFormatter
|
2
|
+
def to_xml(options = {})
|
3
|
+
options[:indent] ||= 2
|
4
|
+
xml = options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
|
5
|
+
xml.instruct! unless options[:skip_instruct]
|
6
|
+
xml.tag!(self.class.name.downcase.to_sym, self.attributes) do
|
7
|
+
self.class.reflect_on_all_associations.to_a.each do |assoc|
|
8
|
+
xml.tag!(assoc.name)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/columnizer'
|
2
|
+
|
3
|
+
class Answer
|
4
|
+
include Columnizer
|
5
|
+
|
6
|
+
# Context, Content, Display, Reference
|
7
|
+
attr_accessor :id, :question_id, :parser
|
8
|
+
attr_accessor :text, :short_text, :help_text, :numerical_value
|
9
|
+
attr_accessor :response_class, :display_order, :is_exclusive, :is_a_disabler, :hide_label
|
10
|
+
attr_accessor :reference_identifier, :data_export_identifier
|
11
|
+
|
12
|
+
def initialize(question, args, options)
|
13
|
+
self.parser = question ? question.parser : nil
|
14
|
+
self.id = parser ? parser.new_answer_id : nil
|
15
|
+
self.question_id = question ? question.id : nil
|
16
|
+
|
17
|
+
#self.text is set in args
|
18
|
+
args_options = parse_args_options(args)
|
19
|
+
self.default_options(args_options[:text]).merge(options).merge(args_options).each{|key,value| self.instance_variable_set("@#{key}", value)}
|
20
|
+
end
|
21
|
+
|
22
|
+
def default_options(text)
|
23
|
+
{ :short_text => text,
|
24
|
+
:data_export_identifier => Columnizer.to_normalized_column(text),
|
25
|
+
:is_exclusive => false,
|
26
|
+
:is_a_disabler => false,
|
27
|
+
:hide_label => false,
|
28
|
+
:response_class => "answer"
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def parse_args_options(args)
|
33
|
+
a0, a1, a2 = args
|
34
|
+
|
35
|
+
# Hash
|
36
|
+
if a0.is_a?(Hash)
|
37
|
+
{:text => "Answer"}.merge(a0)
|
38
|
+
|
39
|
+
# String, Hash || String, Symbol, Hash
|
40
|
+
elsif a0.is_a?(String)
|
41
|
+
a1.is_a?(Symbol) ? {:text => a0, :response_class => a1.to_s}.merge(a2 || {}) : {:text => a0}.merge(a1 || {})
|
42
|
+
|
43
|
+
# Symbol, Hash || Symbol, Symbol, Hash
|
44
|
+
elsif a0.is_a?(Symbol)
|
45
|
+
shortcuts = case a0
|
46
|
+
when :other
|
47
|
+
{:text => "Other"}
|
48
|
+
when :other_and_string
|
49
|
+
{:text => "Other", :response_class => "string"}
|
50
|
+
when :none, :omit #a disabler erases and disables all other answer options (text, checkbox, dropdowns, etc). Unchecking the omit box is the only way to enable other options (except in the case limit => :one)
|
51
|
+
{:text => a0.to_s.humanize, :is_exclusive => true} # "omit" is no longer a response class... it's treated as any other answer type
|
52
|
+
when :integer, :date, :time, :datetime, :text, :datetime, :string
|
53
|
+
{:text => a0.to_s.humanize, :response_class => a0.to_s, :hide_label => true}
|
54
|
+
else
|
55
|
+
{:text => a0.to_s.humanize}
|
56
|
+
end
|
57
|
+
a1.is_a?(Symbol) ? shortcuts.merge({:response_class => a1.to_s}).merge(a2 || {}) : shortcuts.merge(a1 || {})
|
58
|
+
else
|
59
|
+
{:text => "Answer"}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_yml
|
64
|
+
out =[ %(#{@data_export_identifier}_#{@id}:) ]
|
65
|
+
out << %( id: #{@id})
|
66
|
+
out << %( question_id: #{@question_id})
|
67
|
+
out << %( text: "#{@text}")
|
68
|
+
out << %( short_text: "#{@short_text}")
|
69
|
+
out << %( help_text: "#{@help_text}")
|
70
|
+
out << %( weight: #{@weight})
|
71
|
+
out << %( response_class: "#{@response_class}")
|
72
|
+
out << %( display_order: #{display_order} )
|
73
|
+
out << %( is_exclusive: #{@is_exclusive})
|
74
|
+
out << %( hide_label: #{@hide_label})
|
75
|
+
out << %( reference_identifier: #{@reference_identifier})
|
76
|
+
out << %( data_export_identifier: "#{@data_export_identifier}")
|
77
|
+
(out << nil ).join("\r\n")
|
78
|
+
end
|
79
|
+
|
80
|
+
def to_file
|
81
|
+
File.open(self.parser.answers_yml, File::CREAT|File::APPEND|File::WRONLY){ |f| f << to_yml }
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Columnizer
|
2
|
+
|
3
|
+
def self.to_normalized_column(text)
|
4
|
+
words_to_omit = ["a", "to", "the", "of", "has", "have", "it", "is", "in", "on", "or", "but", "when", "be"]
|
5
|
+
|
6
|
+
# strip all the html tags from the text data
|
7
|
+
col_text = text.gsub(/(<[^>]*>)|\n|\t/s, ' ')
|
8
|
+
|
9
|
+
# Removing capitalization
|
10
|
+
col_text.downcase!
|
11
|
+
# Removing potential problem characters
|
12
|
+
col_text.gsub!(/\"|\'/, '')
|
13
|
+
# Removing text inside parens
|
14
|
+
col_text.gsub!(/\(.*?\)/,'')
|
15
|
+
|
16
|
+
# Removing all other non-word characters
|
17
|
+
col_text.gsub!(/\W/, ' ')
|
18
|
+
|
19
|
+
column_words = []
|
20
|
+
words = col_text.split(' ')
|
21
|
+
words.each do |word|
|
22
|
+
if !words_to_omit.include?(word)
|
23
|
+
column_words << word
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
#reducing the word list to limit column length
|
28
|
+
if column_words.length > 5
|
29
|
+
column_words.slice!(0, column_words.length - 5)
|
30
|
+
end
|
31
|
+
|
32
|
+
#re-assemble the string
|
33
|
+
column_words.join("_")
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class Dependency
|
2
|
+
|
3
|
+
# Context, Conditional, Children
|
4
|
+
attr_accessor :id, :question_id, :parser
|
5
|
+
attr_accessor :rule
|
6
|
+
attr_accessor :dependency_conditions
|
7
|
+
|
8
|
+
# id, question, and rule required
|
9
|
+
def initialize(question, args, options)
|
10
|
+
self.parser = question.parser
|
11
|
+
self.id = parser.new_dependency_id
|
12
|
+
self.question_id = question.id
|
13
|
+
self.rule = (args[0] || {})[:rule]
|
14
|
+
self.dependency_conditions = []
|
15
|
+
self.default_options().merge(options).merge(args[1] || {}).each{|key,value| self.instance_variable_set("@#{key}", value)}
|
16
|
+
end
|
17
|
+
|
18
|
+
def default_options()
|
19
|
+
{}
|
20
|
+
end
|
21
|
+
|
22
|
+
# Injecting the id of the current dependency object into the dependency_condition on assignment
|
23
|
+
def add_dependency_condition(dc_obj)
|
24
|
+
dc_obj.dependency_id = self.id
|
25
|
+
self.dependency_conditions << dc_obj
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_yml
|
29
|
+
out =[ %(#{question_id}_#{@id}:) ]
|
30
|
+
out << %( id: #{@id})
|
31
|
+
out << %( question_id: #{@question_id})
|
32
|
+
out << %( rule: "#{@rule}")
|
33
|
+
(out << nil ).join("\r\n")
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_file
|
37
|
+
File.open(self.parser.dependencies_yml, File::CREAT|File::APPEND|File::WRONLY) {|f| f << to_yml}
|
38
|
+
self.dependency_conditions.compact.map(&:to_file)
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
class DependencyCondition
|
2
|
+
|
3
|
+
# Context, Conditional, Value
|
4
|
+
attr_accessor :id, :dependency_id, :rule_key, :parser
|
5
|
+
attr_accessor :question_id, :operator
|
6
|
+
attr_accessor :answer_id, :datetime_value, :integer_value, :float_value, :unit, :text_value, :string_value, :response_other
|
7
|
+
attr_accessor :question_reference, :answer_reference
|
8
|
+
|
9
|
+
# id, dependency, and question_id required
|
10
|
+
def initialize(dependency, args, options)
|
11
|
+
self.parser = dependency.parser
|
12
|
+
self.id = parser.new_dependency_condition_id
|
13
|
+
self.dependency_id = dependency.id
|
14
|
+
self.rule_key = options[:reference_identifier]
|
15
|
+
|
16
|
+
args_options = parse_args_options(args)
|
17
|
+
self.default_options().merge(options).merge(args_options).each{|key,value| self.instance_variable_set("@#{key}", value)}
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
def default_options()
|
22
|
+
{ :operator => "==" }
|
23
|
+
end
|
24
|
+
|
25
|
+
def parse_args_options(args)
|
26
|
+
a0, a1, a2 = args
|
27
|
+
options = {:question_reference => a0.to_s.gsub("q_", ""), :operator => a1}
|
28
|
+
a2.is_a?(Hash) ? options.merge(a2) : options.merge({:answer_reference => a2.to_s.gsub("a_", "")})
|
29
|
+
end
|
30
|
+
|
31
|
+
def to_yml
|
32
|
+
out =[ %(#{@question_id}_#{@dependency_id}_#{id}:) ]
|
33
|
+
out << %( id: #{@id})
|
34
|
+
out << %( dependency_id: #{@dependency_id})
|
35
|
+
out << %( rule_key: "#{@rule_key}")
|
36
|
+
out << %( question_id: #{@question_id})
|
37
|
+
out << %( operator: "#{@operator}")
|
38
|
+
out << %( answer_id: #{@answer_id})
|
39
|
+
out << %( datetime_value: #{@date_value})
|
40
|
+
out << %( integer_value: #{@integer_value})
|
41
|
+
out << %( float_value: #{@float_value})
|
42
|
+
out << %( unit: "#{@unit}")
|
43
|
+
out << %( text_value: "#{@text_value}")
|
44
|
+
out << %( string_value: "#{@string_value}")
|
45
|
+
out << %( response_other: "#{@response_other}")
|
46
|
+
(out << nil ).join("\r\n")
|
47
|
+
end
|
48
|
+
|
49
|
+
def reconcile_dependencies
|
50
|
+
# Looking up references to questions and answers for linking the dependency objects
|
51
|
+
puts "Looking up references for question: #{@question_reference} in Survey: #{Survey.current_survey.title}"
|
52
|
+
ref_question = Survey.current_survey.find_question_by_reference(@question_reference) # Argh. I can't think of a better way to get a hold of this reference here...
|
53
|
+
if ref_question
|
54
|
+
@question_id = ref_question.id
|
55
|
+
ref_answer = ref_question.find_answer_by_reference(@answer_reference)
|
56
|
+
if ref_answer
|
57
|
+
@answer_id = ref_answer.id
|
58
|
+
else
|
59
|
+
raise "Could not find referenced answer #{@answer_reference}"
|
60
|
+
end
|
61
|
+
|
62
|
+
else
|
63
|
+
raise "Could not find referenced question #{@question_reference}"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_file
|
68
|
+
# Reconciling the references used in the dsl to actual object ids
|
69
|
+
#puts "Reconcile of dependency:"
|
70
|
+
# reconcile_dependencies
|
71
|
+
File.open(self.parser.dependency_conditions_yml, File::CREAT|File::APPEND|File::WRONLY) {|f| f << to_yml}
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/columnizer'
|
2
|
+
|
3
|
+
class Question
|
4
|
+
include Columnizer
|
5
|
+
|
6
|
+
# Context, Content, Display, Reference, Children
|
7
|
+
attr_accessor :id, :survey_section_id, :parser
|
8
|
+
attr_accessor :text, :short_text, :help_text
|
9
|
+
attr_accessor :pick, :display_type, :display_order, :question_group_id, :is_mandatory
|
10
|
+
attr_accessor :reference_identifier, :data_export_identifier
|
11
|
+
attr_accessor :answers, :dependency
|
12
|
+
|
13
|
+
def initialize(section, args, options)
|
14
|
+
self.parser = section.parser
|
15
|
+
self.id = parser.new_question_id
|
16
|
+
self.display_order = self.id
|
17
|
+
self.survey_section_id = section.id
|
18
|
+
self.text = args[0]
|
19
|
+
self.answers = []
|
20
|
+
self.dependency = nil
|
21
|
+
self.default_options(text).merge(options).merge(args[1] || {}).each{|key,value| self.instance_variable_set("@#{key}", value)}
|
22
|
+
end
|
23
|
+
|
24
|
+
def default_options(text)
|
25
|
+
{ :short_text => text,
|
26
|
+
:pick => :none,
|
27
|
+
:display_type => :default,
|
28
|
+
:is_mandatory => true,
|
29
|
+
:data_export_identifier => Columnizer.to_normalized_column(text)
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
# Injecting the id of this question object into the dependency object on assignment
|
34
|
+
def dependency=(dep)
|
35
|
+
unless dep.nil?
|
36
|
+
dep.question_id = self.id
|
37
|
+
end
|
38
|
+
@dependency = dep
|
39
|
+
end
|
40
|
+
|
41
|
+
def find_answer_by_reference(ref_id)
|
42
|
+
answer = nil
|
43
|
+
count = 0
|
44
|
+
puts "Looking up answer with ref: #{ref_id}"
|
45
|
+
while answer.nil? and count < self.answers.size
|
46
|
+
answer = self.answers[count] if self.answers[count].reference_identifier == ref_id
|
47
|
+
count += 1
|
48
|
+
end
|
49
|
+
puts " found answer: '#{answer.text}' (id:#{answer.id})" unless answer.nil?
|
50
|
+
answer
|
51
|
+
end
|
52
|
+
|
53
|
+
def to_yml
|
54
|
+
out =[ %(#{@data_export_identifier}_#{@id}:) ]
|
55
|
+
out << %( id: #{@id})
|
56
|
+
out << %( survey_section_id: #{@survey_section_id})
|
57
|
+
out << %( text: "#{@text}")
|
58
|
+
out << %( short_text: "#{@short_text}")
|
59
|
+
out << %( help_text: "#{@help_text}")
|
60
|
+
out << %( pick: #{pick})
|
61
|
+
out << %( display_type: #{display_type})
|
62
|
+
out << %( display_order: #{display_order})
|
63
|
+
out << %( question_group_id: #{question_group_id})
|
64
|
+
out << %( is_mandatory: #{@is_mandatory})
|
65
|
+
out << %( reference_identifier: #{@reference_identifier})
|
66
|
+
out << %( data_export_identifier: "#{@data_export_identifier}")
|
67
|
+
(out << nil ).join("\r\n")
|
68
|
+
end
|
69
|
+
|
70
|
+
def to_file
|
71
|
+
File.open(self.parser.questions_yml, File::CREAT|File::APPEND|File::WRONLY){ |f| f << to_yml }
|
72
|
+
self.answers.compact.map(&:to_file)
|
73
|
+
if self.dependency then self.dependency.to_file end
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|