surveyor 0.8.0 → 0.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +22 -5
- data/VERSION +1 -1
- data/app/models/dependency.rb +16 -32
- data/app/models/question.rb +1 -1
- data/app/models/question_group.rb +1 -1
- data/app/models/response.rb +1 -4
- data/app/models/response_set.rb +4 -3
- data/app/models/survey.rb +0 -1
- data/app/models/validation.rb +20 -0
- data/app/models/validation_condition.rb +19 -17
- data/generators/surveyor/surveyor_generator.rb +9 -5
- data/generators/surveyor/templates/migrate/add_display_order_to_surveys.rb +9 -0
- data/generators/surveyor/templates/surveys/kitchen_sink_survey.rb +15 -4
- data/lib/surveyor.rb +16 -0
- data/script/surveyor/answer.rb +32 -55
- data/script/surveyor/base.rb +61 -0
- data/script/surveyor/dependency.rb +4 -41
- data/script/surveyor/dependency_condition.rb +13 -38
- data/script/surveyor/question.rb +16 -50
- data/script/surveyor/question_group.rb +7 -19
- data/script/surveyor/specs/answer_spec.rb +15 -52
- data/script/surveyor/specs/question_spec.rb +37 -85
- data/script/surveyor/specs/spec_helper.rb +6 -0
- data/script/surveyor/specs/survey_section_spec.rb +23 -0
- data/script/surveyor/specs/validation_condition_spec.rb +20 -0
- data/script/surveyor/specs/validation_spec.rb +20 -0
- data/script/surveyor/survey.rb +10 -85
- data/script/surveyor/survey_parser.rb +160 -38
- data/script/surveyor/survey_section.rb +6 -130
- data/script/surveyor/validation.rb +19 -0
- data/script/surveyor/validation_condition.rb +19 -0
- data/spec/lib/surveyor_spec.rb +44 -0
- data/spec/models/dependency_spec.rb +9 -16
- data/spec/models/question_group_spec.rb +3 -3
- data/spec/models/question_spec.rb +1 -1
- data/spec/models/validation_condition_spec.rb +29 -0
- data/spec/models/validation_spec.rb +27 -0
- data/spec/spec_helper.rb +0 -2
- data/surveyor.gemspec +12 -7
- metadata +12 -7
- data/lib/tiny_code.rb +0 -58
- data/script/surveyor/columnizer.rb +0 -36
- data/script/surveyor/specs/question_dependency_spec.rb +0 -46
- data/script/surveyor/specs/question_group_spec.rb +0 -9
- data/script/surveyor/specs/section_spec.rb +0 -58
data/README.md
CHANGED
@@ -7,12 +7,12 @@ Surveyor is a rails (gem) plugin, that brings surveys to your rails app. Before
|
|
7
7
|
As a plugin:
|
8
8
|
|
9
9
|
sudo gem install haml
|
10
|
-
script/plugin install git://github.com/breakpointer/surveyor.git -r 'tag v0.
|
10
|
+
script/plugin install git://github.com/breakpointer/surveyor.git -r 'tag v0.9.0'
|
11
11
|
|
12
12
|
Or as a gem plugin:
|
13
13
|
|
14
14
|
# in environment.rb
|
15
|
-
config.gem "surveyor", :version => '>=0.
|
15
|
+
config.gem "surveyor", :version => '>=0.9.0', :source => 'http://gemcutter.org'
|
16
16
|
|
17
17
|
sudo gem install gemcutter
|
18
18
|
gem tumble
|
@@ -105,11 +105,28 @@ Surveyor depends on Rails 2.3 and the SASS style sheet language, part of HAML (h
|
|
105
105
|
|
106
106
|
# Changes
|
107
107
|
|
108
|
+
0.9.0
|
109
|
+
|
110
|
+
* validations in dsl and surveyor models
|
111
|
+
* preserve underscores in reference identifiers
|
112
|
+
* dsl specs, refactoring into base class
|
113
|
+
* adding display order to surveys
|
114
|
+
* moving columnizer and tiny column functionality to surveyor module
|
115
|
+
* columnizer (and tiny code) refactoring, columnizer spec extracted from answer spec
|
116
|
+
* cleanup of scopes with joins
|
117
|
+
* refactoring dependency
|
118
|
+
|
119
|
+
0.8.0
|
120
|
+
|
121
|
+
* question group dependencies
|
122
|
+
* expanded examples in kitchen sink survey
|
123
|
+
* specs
|
124
|
+
|
108
125
|
0.7.1
|
109
126
|
|
110
|
-
custom index page
|
111
|
-
custom classes and renderers
|
112
|
-
fixing typo in kitchen sink survey
|
127
|
+
* custom index page
|
128
|
+
* custom classes and renderers
|
129
|
+
* fixing typo in kitchen sink survey
|
113
130
|
|
114
131
|
0.7.0
|
115
132
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.9.0
|
data/app/models/dependency.rb
CHANGED
@@ -4,9 +4,6 @@ class Dependency < ActiveRecord::Base
|
|
4
4
|
belongs_to :question_group
|
5
5
|
has_many :dependency_conditions
|
6
6
|
|
7
|
-
# Scopes
|
8
|
-
named_scope :depending_on_questions, lambda {|question_ids| {:joins => :dependency_conditions, :conditions => {:dependency_conditions => {:question_id => question_ids}} }}
|
9
|
-
|
10
7
|
# Validations
|
11
8
|
validates_presence_of :rule
|
12
9
|
validates_format_of :rule, :with => /^(?:and|or|\)|\(|[A-Z]|\s)+$/ #TODO properly formed parenthesis etc.
|
@@ -26,37 +23,24 @@ class Dependency < ActiveRecord::Base
|
|
26
23
|
write_attribute(:question_id, i)
|
27
24
|
end
|
28
25
|
|
29
|
-
#
|
30
|
-
# the
|
31
|
-
def
|
32
|
-
|
33
|
-
|
34
|
-
else
|
35
|
-
return(false)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
# Pairs up the substitution key with the evaluated condition result for substitution into the rule
|
40
|
-
# Example: If you have two dependency conditions with rule keys "A" and "B" in the rule "A or B"
|
41
|
-
# calling keyed_condition_pairs will return {:A => true, :B => false}
|
42
|
-
def keyed_conditions(response_set)
|
43
|
-
keyed_pairs = {}
|
44
|
-
# logger.debug dependency_conditions.inspect
|
45
|
-
self.dependency_conditions.each do |dc|
|
46
|
-
keyed_pairs.merge!(dc.to_hash(response_set))
|
47
|
-
end
|
48
|
-
return(keyed_pairs)
|
49
|
-
end
|
50
|
-
|
51
|
-
# Does the substiution and evaluation of the dependency rule with the keyed pairs
|
52
|
-
def rule_evaluation(keyed_pairs)
|
53
|
-
# subtitute into rule for evaluation
|
54
|
-
rgx = Regexp.new(self.dependency_conditions.map{|dc| ["a","o"].include?(dc.rule_key) ? "#{dc.rule_key}(?!nd|r)" : dc.rule_key}.join("|")) # Making a regexp to only look for the keys used in the child conditions
|
26
|
+
# Has this dependency has been met in the context of response_set?
|
27
|
+
# Substitutes the conditions hash into the rule and evaluates it
|
28
|
+
def is_met?(response_set)
|
29
|
+
ch = conditions_hash(response_set)
|
30
|
+
return false if ch.blank?
|
55
31
|
# logger.debug "rule: #{self.rule.inspect}"
|
56
32
|
# logger.debug "rexp: #{rgx.inspect}"
|
57
|
-
# logger.debug "keyp: #{
|
58
|
-
# logger.debug "subd: #{self.rule.gsub(rgx){|m|
|
59
|
-
|
33
|
+
# logger.debug "keyp: #{ch.inspect}"
|
34
|
+
# logger.debug "subd: #{self.rule.gsub(rgx){|m| ch[m.to_sym]}}"
|
35
|
+
rgx = Regexp.new(self.dependency_conditions.map{|dc| ["a","o"].include?(dc.rule_key) ? "#{dc.rule_key}(?!nd|r)" : dc.rule_key}.join("|")) # exclude and, or
|
36
|
+
eval(self.rule.gsub(rgx){|m| ch[m.to_sym]})
|
37
|
+
end
|
38
|
+
|
39
|
+
# A hash of the conditions (keyed by rule_key) and their evaluation (boolean) in the context of response_set
|
40
|
+
def conditions_hash(response_set)
|
41
|
+
hash = {}
|
42
|
+
self.dependency_conditions.each{|dc| hash.merge!(dc.to_hash(response_set))}
|
43
|
+
return hash
|
60
44
|
end
|
61
45
|
|
62
46
|
end
|
data/app/models/question.rb
CHANGED
@@ -33,7 +33,7 @@ class Question < ActiveRecord::Base
|
|
33
33
|
self.dependency != nil
|
34
34
|
end
|
35
35
|
def triggered?(response_set)
|
36
|
-
dependent? ? self.dependency.
|
36
|
+
dependent? ? self.dependency.is_met?(response_set) : true
|
37
37
|
end
|
38
38
|
def css_class(response_set)
|
39
39
|
[(dependent? ? "dependent" : nil), (triggered?(response_set) ? nil : "hidden"), custom_class].compact.join(" ")
|
@@ -21,7 +21,7 @@ class QuestionGroup < ActiveRecord::Base
|
|
21
21
|
self.dependency != nil
|
22
22
|
end
|
23
23
|
def triggered?(response_set)
|
24
|
-
dependent? ? self.dependency.
|
24
|
+
dependent? ? self.dependency.is_met?(response_set) : true
|
25
25
|
end
|
26
26
|
def css_class(response_set)
|
27
27
|
[(dependent? ? "dependent" : nil), (triggered?(response_set) ? nil : "hidden"), custom_class].compact.join(" ")
|
data/app/models/response.rb
CHANGED
@@ -8,10 +8,7 @@ class Response < ActiveRecord::Base
|
|
8
8
|
|
9
9
|
# Validations
|
10
10
|
validates_presence_of :response_set_id, :question_id, :answer_id
|
11
|
-
|
12
|
-
# Named scopes
|
13
|
-
named_scope :in_section, lambda {|section_id| {:include => :question, :conditions => ['questions.survey_section_id =?', section_id.to_i ]}}
|
14
|
-
|
11
|
+
|
15
12
|
acts_as_response # includes "as" instance method
|
16
13
|
|
17
14
|
def selected
|
data/app/models/response_set.rb
CHANGED
@@ -100,11 +100,11 @@ class ResponseSet < ActiveRecord::Base
|
|
100
100
|
end
|
101
101
|
|
102
102
|
def unanswered_dependencies
|
103
|
-
dependencies.select{|d| d.
|
103
|
+
dependencies.select{|d| d.is_met?(self) and self.has_not_answered_question?(d.question)}.map(&:question)
|
104
104
|
end
|
105
105
|
|
106
106
|
def all_dependencies
|
107
|
-
arr = dependencies.partition{|d| d.
|
107
|
+
arr = dependencies.partition{|d| d.is_met?(self) }
|
108
108
|
{:show => arr[0].map{|d| d.question_group_id.nil? ? "question_#{d.question_id}" : "question_group_#{d.question_group_id}"}, :hide => arr[1].map{|d| d.question_group_id.nil? ? "question_#{d.question_id}" : "question_group_#{d.question_group_id}"}}
|
109
109
|
end
|
110
110
|
|
@@ -112,7 +112,8 @@ class ResponseSet < ActiveRecord::Base
|
|
112
112
|
|
113
113
|
def dependencies
|
114
114
|
question_ids = Question.find_all_by_survey_section_id(current_section_id).map(&:id)
|
115
|
-
|
115
|
+
depdendecy_ids = DependencyCondition.all(:conditions => {:question_id => question_ids}).map(&:dependency_id)
|
116
|
+
Dependency.find(depdendecy_ids, :include => :dependency_conditions)
|
116
117
|
end
|
117
118
|
end
|
118
119
|
|
data/app/models/survey.rb
CHANGED
data/app/models/validation.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
class Validation < ActiveRecord::Base
|
2
2
|
# Associations
|
3
3
|
belongs_to :answer
|
4
|
+
has_many :validation_conditions
|
4
5
|
|
5
6
|
# Scopes
|
6
7
|
|
@@ -10,4 +11,23 @@ class Validation < ActiveRecord::Base
|
|
10
11
|
validates_numericality_of :answer_id
|
11
12
|
|
12
13
|
# Instance Methods
|
14
|
+
def is_valid?(response_set)
|
15
|
+
ch = conditions_hash(response_set)
|
16
|
+
rgx = Regexp.new(self.validation_conditions.map{|vc| ["a","o"].include?(vc.rule_key) ? "#{vc.rule_key}(?!nd|r)" : vc.rule_key}.join("|")) # exclude and, or
|
17
|
+
# logger.debug "v: #{self.inspect}"
|
18
|
+
# logger.debug "rule: #{self.rule.inspect}"
|
19
|
+
# logger.debug "rexp: #{rgx.inspect}"
|
20
|
+
# logger.debug "keyp: #{ch.inspect}"
|
21
|
+
# logger.debug "subd: #{self.rule.gsub(rgx){|m| ch[m.to_sym]}}"
|
22
|
+
eval(self.rule.gsub(rgx){|m| ch[m.to_sym]})
|
23
|
+
end
|
24
|
+
|
25
|
+
# A hash of the conditions (keyed by rule_key) and their evaluation (boolean) in the context of response_set
|
26
|
+
def conditions_hash(response_set)
|
27
|
+
hash = {}
|
28
|
+
response = response_set.responses.detect{|r| r.answer_id.to_i == self.answer_id.to_i}
|
29
|
+
# logger.debug "r: #{response.inspect}"
|
30
|
+
self.validation_conditions.each{|vc| hash.merge!(vc.to_hash(response))}
|
31
|
+
return hash
|
32
|
+
end
|
13
33
|
end
|
@@ -13,27 +13,29 @@ class ValidationCondition < ActiveRecord::Base
|
|
13
13
|
validates_inclusion_of :operator, :in => OPERATORS
|
14
14
|
validates_uniqueness_of :rule_key, :scope => :validation_id
|
15
15
|
|
16
|
+
acts_as_response # includes "as" instance method
|
17
|
+
|
16
18
|
# Class methods
|
17
19
|
def self.operators
|
18
20
|
OPERATORS
|
19
21
|
end
|
20
22
|
|
21
23
|
# Instance Methods
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
24
|
+
def to_hash(response)
|
25
|
+
{rule_key.to_sym => (response.nil? ? false : self.is_valid?(response))}
|
26
|
+
end
|
27
|
+
|
28
|
+
def is_valid?(response)
|
29
|
+
klass = response.answer.response_class
|
30
|
+
case self.operator
|
31
|
+
when "==", "<", ">", "<=", ">="
|
32
|
+
response.as(klass).send(self.operator, self.as(klass))
|
33
|
+
when "!="
|
34
|
+
!(response.as(klass) == self.as(klass))
|
35
|
+
when "=~"
|
36
|
+
!(response.as(klass).to_s =~ Regexp.new(self.regexp || "")).nil?
|
37
|
+
else
|
38
|
+
false
|
39
|
+
end
|
40
|
+
end
|
39
41
|
end
|
@@ -25,12 +25,16 @@ class SurveyorGenerator < Rails::Generator::Base
|
|
25
25
|
# not using m.migration_template because all migration timestamps end up the same, causing a collision when running rake db:migrate
|
26
26
|
# coped functionality from RAILS_GEM_PATH/lib/rails_generator/commands.rb
|
27
27
|
m.directory "db/migrate"
|
28
|
-
[
|
29
|
-
|
30
|
-
|
28
|
+
[ "create_surveys", "create_survey_sections", "create_questions", "create_question_groups", "create_answers",
|
29
|
+
"create_response_sets", "create_responses",
|
30
|
+
"create_dependencies", "create_dependency_conditions",
|
31
|
+
"create_validations", "create_validation_conditions",
|
32
|
+
"add_display_order_to_surveys"].each_with_index do |model, i|
|
33
|
+
unless (prev_migrations = Dir.glob("db/migrate/[0-9]*_*.rb").grep(/[0-9]+_#{model}.rb$/)).empty?
|
34
|
+
prev_migration_timestamp = prev_migrations[0].match(/([0-9]+)_#{model}.rb$/)[1]
|
31
35
|
end
|
32
|
-
# raise "Another migration is already named
|
33
|
-
m.template("migrate
|
36
|
+
# raise "Another migration is already named #{model}" if not Dir.glob("db/migrate/[0-9]*_*.rb").grep(/[0-9]+_#{model}.rb$/).empty?
|
37
|
+
m.template("migrate/#{model}.rb", "db/migrate/#{(prev_migration_timestamp || Time.now.utc.strftime("%Y%m%d%H%M%S").to_i + i).to_s}_#{model}.rb")
|
34
38
|
end
|
35
39
|
|
36
40
|
# Generate CSS
|
@@ -23,7 +23,7 @@ survey "“Kitchen Sink” survey" do
|
|
23
23
|
|
24
24
|
# A dependent question, with conditions and rule to logically join them
|
25
25
|
# the question's reference identifier is "2a", and the answer's reference_identifier is "1"
|
26
|
-
# question reference identifiers used in conditions need to be unique for the lookups to work
|
26
|
+
# question reference identifiers used in conditions need to be unique on a survey for the lookups to work
|
27
27
|
q_2a "Please explain why you don't like this color?"
|
28
28
|
a_1 "explanation", :text
|
29
29
|
dependency :rule => "A or B or C or D"
|
@@ -62,22 +62,33 @@ survey "“Kitchen Sink” survey" do
|
|
62
62
|
a "what", :string
|
63
63
|
a "where", :string
|
64
64
|
|
65
|
-
# Various types of
|
65
|
+
# Various types of responses can be accepted, and validated
|
66
66
|
q "How many pets do you own?"
|
67
67
|
a :integer
|
68
|
+
validation :rule => "A"
|
69
|
+
condition_A ">=", :integer_value => 0
|
68
70
|
|
69
71
|
# Surveys, sections, questions, groups, and answers also take a custom css class for covenience in custom styling
|
70
72
|
q "What is your address?", :custom_class => 'address'
|
71
73
|
a :text, :custom_class => 'mapper'
|
74
|
+
# validations can use regexp values
|
75
|
+
validation :rule => "A"
|
76
|
+
condition_A "=~", :regexp => /[0-9a-zA-z\. #]/
|
72
77
|
|
73
78
|
# Questions, groups, and answers take a custom renderer (a partial in the application's views dir)
|
74
79
|
# defaults are "/partials/question_group", "/partials/question", "/partials/answer", so the custom renderers should have a different name
|
75
80
|
q "Pick your favorite date AND time" #, :custom_renderer => "/partials/custom_question"
|
76
81
|
a :datetime
|
77
82
|
|
78
|
-
|
79
|
-
|
83
|
+
q_time_lunch "What time do you usually take a lunch break?"
|
84
|
+
a_1 :time
|
80
85
|
|
86
|
+
# # validation conditions can look up the response to another question/answer pair
|
87
|
+
# q_time_dinner "What time do you usually take a dinner break?"
|
88
|
+
# a :time
|
89
|
+
# validation :rule => "A"
|
90
|
+
# condition_A ">=", :question_reference => "time_lunch", :answer_reference => "1"
|
91
|
+
|
81
92
|
q "When would you like to meet for dinner?"
|
82
93
|
a :date
|
83
94
|
|
data/lib/surveyor.rb
CHANGED
@@ -5,4 +5,20 @@ require 'surveyor/config'
|
|
5
5
|
require 'surveyor/acts_as_response'
|
6
6
|
|
7
7
|
module Surveyor
|
8
|
+
RAND_CHARS = [('a'..'z'), ('A'..'Z'), (0..9)].map(&:to_a).flatten.to_s
|
9
|
+
|
10
|
+
def self.make_tiny_code(len = 10)
|
11
|
+
len.times.map{|i| RAND_CHARS[rand(RAND_CHARS.size), 1] }.to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.to_normalized_string(text)
|
15
|
+
words_to_omit = %w(a be but has have in is it of on or the to when)
|
16
|
+
col_text = text.gsub(/(<[^>]*>)|\n|\t/s, ' ') # Remove html tags
|
17
|
+
col_text.downcase! # Remove capitalization
|
18
|
+
col_text.gsub!(/\"|\'/, '') # Remove potential problem characters
|
19
|
+
col_text.gsub!(/\(.*?\)/,'') # Remove text inside parens
|
20
|
+
col_text.gsub!(/\W/, ' ') # Remove all other non-word characters
|
21
|
+
cols = (col_text.split(' ') - words_to_omit)
|
22
|
+
(cols.size > 5 ? cols[-5..-1] : cols).join("_")
|
23
|
+
end
|
8
24
|
end
|
data/script/surveyor/answer.rb
CHANGED
@@ -1,75 +1,52 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
class Answer
|
4
|
-
include Columnizer
|
5
|
-
|
1
|
+
class Answer < SurveyParser::Base
|
6
2
|
# Context, Content, Reference, Display
|
7
3
|
attr_accessor :id, :parser, :question_id
|
8
4
|
attr_accessor :text, :short_text, :help_text, :weight, :response_class
|
9
5
|
attr_accessor :reference_identifier, :data_export_identifier, :common_namespace, :common_identitier
|
10
6
|
attr_accessor :display_order, :is_exclusive, :hide_label, :display_length, :custom_class, :custom_renderer
|
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
|
7
|
+
attr_accessor :validation
|
16
8
|
|
17
|
-
|
18
|
-
|
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,
|
9
|
+
def default_options
|
10
|
+
{ :is_exclusive => false,
|
26
11
|
:hide_label => false,
|
27
12
|
:response_class => "answer"
|
28
13
|
}
|
29
14
|
end
|
30
15
|
|
31
|
-
def
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
elsif a0.is_a?(String)
|
40
|
-
a1.is_a?(Symbol) ? {:text => a0, :response_class => a1.to_s}.merge(a2 || {}) : {:text => a0}.merge(a1 || {})
|
41
|
-
|
42
|
-
# (Symbol, Hash) or (Symbol, Symbol, Hash)
|
43
|
-
elsif a0.is_a?(Symbol)
|
44
|
-
shortcuts = case a0
|
45
|
-
when :other
|
46
|
-
{:text => "Other"}
|
47
|
-
when :other_and_string
|
48
|
-
{:text => "Other", :response_class => "string"}
|
49
|
-
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)
|
50
|
-
{:text => a0.to_s.humanize, :is_exclusive => true} # "omit" is no longer a response class... it's treated as any other answer type
|
51
|
-
when :integer, :date, :time, :datetime, :text, :datetime, :string
|
52
|
-
{:text => a0.to_s.humanize, :response_class => a0.to_s, :hide_label => true}
|
53
|
-
else
|
54
|
-
{:text => a0.to_s.humanize}
|
55
|
-
end
|
56
|
-
a1.is_a?(Symbol) ? shortcuts.merge({:response_class => a1.to_s}).merge(a2 || {}) : shortcuts.merge(a1 || {})
|
16
|
+
def parse_args(args)
|
17
|
+
case args[0]
|
18
|
+
when Hash # Hash
|
19
|
+
text_args(args[0][:text]).merge(args[0])
|
20
|
+
when String # (String, Hash) or (String, Symbol, Hash)
|
21
|
+
text_args(args[0]).merge(hash_from args[1]).merge(args[2] || {})
|
22
|
+
when Symbol # (Symbol, Hash) or (Symbol, Symbol, Hash)
|
23
|
+
symbol_args(args[0]).merge(hash_from args[1]).merge(args[2] || {})
|
57
24
|
else
|
58
|
-
|
25
|
+
text_args(nil)
|
59
26
|
end
|
60
27
|
end
|
61
|
-
|
62
|
-
def
|
63
|
-
|
28
|
+
|
29
|
+
def text_args(text = "Answer")
|
30
|
+
{:text => text.to_s, :short_text => text, :data_export_identifier => Surveyor.to_normalized_string(text)}
|
64
31
|
end
|
65
|
-
def
|
66
|
-
|
67
|
-
|
68
|
-
|
32
|
+
def hash_from(arg)
|
33
|
+
arg.is_a?(Symbol) ? {:response_class => arg.to_s} : arg.is_a?(Hash) ? arg : {}
|
34
|
+
end
|
35
|
+
def symbol_args(arg)
|
36
|
+
case arg
|
37
|
+
when :other
|
38
|
+
text_args("Other")
|
39
|
+
when :other_and_string
|
40
|
+
text_args("Other").merge({:response_class => "string"})
|
41
|
+
when :none, :omit # is_exclusive erases and disables other checkboxes and input elements
|
42
|
+
text_args(arg.to_s.humanize).merge({:is_exclusive => true})
|
43
|
+
when :integer, :date, :time, :datetime, :text, :datetime, :string
|
44
|
+
text_args(arg.to_s.humanize).merge({:response_class => arg.to_s, :hide_label => true})
|
45
|
+
end
|
69
46
|
end
|
70
|
-
|
71
47
|
def to_file
|
72
|
-
|
48
|
+
super
|
49
|
+
if self.validation then self.validation.to_file end
|
73
50
|
end
|
74
51
|
|
75
52
|
end
|