question_chain 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. data/.gitignore +4 -0
  2. data/Gemfile +18 -0
  3. data/Licence.txt +20 -0
  4. data/README.rdoc +34 -0
  5. data/Rakefile +2 -0
  6. data/config/initializers/mustache.rb +2 -0
  7. data/lib/question_chain/answerable.rb +142 -0
  8. data/lib/question_chain/answers.rb +290 -0
  9. data/lib/question_chain/models/answers/question_view.rb +21 -0
  10. data/lib/question_chain/models/answers/ui_object_view.rb +67 -0
  11. data/lib/question_chain/models/answers/ui_objects_check_box_view.rb +17 -0
  12. data/lib/question_chain/models/answers/ui_objects_drop_down_view.rb +16 -0
  13. data/lib/question_chain/models/answers/ui_objects_hidden_field_view.rb +8 -0
  14. data/lib/question_chain/models/answers/ui_objects_object_reference_drop_down_view.rb +18 -0
  15. data/lib/question_chain/models/answers/ui_objects_object_search_view.rb +22 -0
  16. data/lib/question_chain/models/answers/ui_objects_relatable_category_drop_down_view.rb +18 -0
  17. data/lib/question_chain/models/answers/ui_objects_text_field_view.rb +8 -0
  18. data/lib/question_chain/models/chain_template.rb +43 -0
  19. data/lib/question_chain/models/question.rb +37 -0
  20. data/lib/question_chain/models/relatable_category_filter.rb +15 -0
  21. data/lib/question_chain/models/rule.rb +27 -0
  22. data/lib/question_chain/models/rules/attribute_change.rb +28 -0
  23. data/lib/question_chain/models/rules/choice_genenerator.rb +5 -0
  24. data/lib/question_chain/models/rules/populate_drop_down.rb +30 -0
  25. data/lib/question_chain/models/rules/search.rb +19 -0
  26. data/lib/question_chain/models/rules/value_change.rb +22 -0
  27. data/lib/question_chain/models/ui_group.rb +71 -0
  28. data/lib/question_chain/models/ui_object.rb +92 -0
  29. data/lib/question_chain/models/ui_object_answer.rb +17 -0
  30. data/lib/question_chain/models/ui_objects/check_box.rb +8 -0
  31. data/lib/question_chain/models/ui_objects/drop_down.rb +17 -0
  32. data/lib/question_chain/models/ui_objects/hidden_field.rb +5 -0
  33. data/lib/question_chain/models/ui_objects/object_reference_drop_down.rb +67 -0
  34. data/lib/question_chain/models/ui_objects/object_search.rb +44 -0
  35. data/lib/question_chain/models/ui_objects/radio_button.rb +5 -0
  36. data/lib/question_chain/models/ui_objects/radio_button_group.rb +5 -0
  37. data/lib/question_chain/models/ui_objects/relatable_category_drop_down.rb +70 -0
  38. data/lib/question_chain/models/ui_objects/text_field.rb +11 -0
  39. data/lib/question_chain/mongo_serialization.rb +62 -0
  40. data/lib/question_chain/mustache_handler.rb +16 -0
  41. data/lib/question_chain/mustache_rails.rb +50 -0
  42. data/lib/question_chain/state_machine.rb +29 -0
  43. data/lib/question_chain/stored_template.rb +30 -0
  44. data/lib/question_chain/version.rb +3 -0
  45. data/lib/question_chain/views/answers/_edit.html.haml +62 -0
  46. data/lib/question_chain/views/answers/_new.html.haml +62 -0
  47. data/lib/question_chain/views/answers/_question.html.mustache +11 -0
  48. data/lib/question_chain/views/answers/_ui_objects_check_box.html.mustache +19 -0
  49. data/lib/question_chain/views/answers/_ui_objects_drop_down.html.mustache +26 -0
  50. data/lib/question_chain/views/answers/_ui_objects_hidden_field.html.mustache +3 -0
  51. data/lib/question_chain/views/answers/_ui_objects_object_reference_drop_down.html.mustache +27 -0
  52. data/lib/question_chain/views/answers/_ui_objects_object_search.html.mustache +20 -0
  53. data/lib/question_chain/views/answers/_ui_objects_relatable_category_drop_down.html.mustache +26 -0
  54. data/lib/question_chain/views/answers/_ui_objects_text_field.html.mustache +19 -0
  55. data/lib/question_chain/views/layouts/application.html.haml +10 -0
  56. data/lib/question_chain.rb +35 -0
  57. data/question_chain.gemspec +31 -0
  58. data/test_app/.gitignore +4 -0
  59. data/test_app/Gemfile +29 -0
  60. data/test_app/Rakefile +16 -0
  61. data/test_app/app/controllers/answers_controller.rb +13 -0
  62. data/test_app/app/controllers/application_controller.rb +4 -0
  63. data/test_app/app/models/container.rb +10 -0
  64. data/test_app/app/models/flight.rb +20 -0
  65. data/test_app/app/views/answers/edit.html.haml +1 -0
  66. data/test_app/app/views/answers/new.html.haml +1 -0
  67. data/test_app/config/application.rb +18 -0
  68. data/test_app/config/boot.rb +13 -0
  69. data/test_app/config/database.yml +15 -0
  70. data/test_app/config/environment.rb +5 -0
  71. data/test_app/config/initializers/app.rb +5 -0
  72. data/test_app/config/initializers/cookie_verification_secret.rb +7 -0
  73. data/test_app/config/initializers/mongodb.rb +2 -0
  74. data/test_app/config/initializers/session_store.rb +3 -0
  75. data/test_app/config/routes.rb +30 -0
  76. data/test_app/config.ru +2 -0
  77. data/test_app/environments/development.rb +19 -0
  78. data/test_app/environments/test.rb +30 -0
  79. data/test_app/lib/tasks/rspec.rake +69 -0
  80. data/test_app/lib/tasks/yard.rake +4 -0
  81. data/test_app/public/.gitkeep +0 -0
  82. data/test_app/script/rails +10 -0
  83. data/test_app/spec/acceptance/new_spec +30 -0
  84. data/test_app/spec/factories.rb +81 -0
  85. data/test_app/spec/models/chain_template_spec.rb +53 -0
  86. data/test_app/spec/models/flight_spec.rb +101 -0
  87. data/test_app/spec/models/question_spec.rb +13 -0
  88. data/test_app/spec/models/rules/value_change_spec.rb +31 -0
  89. data/test_app/spec/models/ui_group_spec.rb +55 -0
  90. data/test_app/spec/models/ui_object_spec.rb +33 -0
  91. data/test_app/spec/models/ui_objects/drop_down_spec.rb +28 -0
  92. data/test_app/spec/models/ui_objects/relatable_category_drop_down_spec.rb +13 -0
  93. data/test_app/spec/spec_helper.rb +25 -0
  94. metadata +325 -0
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,18 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ # Will automatically pull in this gem and all its
6
+ # dependencies specified in the gemspec
7
+ gem "question_chain", :path => File.expand_path("..", __FILE__)
8
+ gem "yard"
9
+
10
+ # These are development dependencies
11
+ group :test do
12
+ gem "rake"
13
+ gem "rspec", "2.5.0"
14
+ gem 'vcr', '~> 1.5', :require => false
15
+ gem 'webmock', '~> 1.6', :require => false
16
+ gem "autotest"
17
+ end
18
+
data/Licence.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008-2010 Richard Hooker - richard.hookere@carboncalculated.com
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,34 @@
1
+ = QuestionChain
2
+
3
+ == What Am I?
4
+
5
+ This is not to be used currently! Work in Progress; Extracting not quite complete and SPECS
6
+
7
+ There will be guides on how to use this http://guides.carboncalculated.com
8
+
9
+ This is a Rails3 Gem to be used in conjunction with the soon to be released QuestionChainJS library
10
+ to be used with the CarbonCalculated API http://carboncalculated.com
11
+
12
+ This Gem allows you to create a forms for Carbon Calculations in like 2 sometimes 3 minutes depending on typing speed
13
+
14
+ At the minute this has dependencies on MongoMapper currently thinking about moving to more ORM agnostic approach
15
+
16
+ == Getting started
17
+
18
+ == UiObjects
19
+
20
+ === Drop Downs
21
+
22
+ === Object Reference Drop Downs
23
+
24
+ === Rules
25
+
26
+ === Attribute Change
27
+
28
+ === Search
29
+
30
+ === Markup
31
+
32
+ === CSS
33
+
34
+ === Bundling
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,2 @@
1
+ # == make sure we defined answers modules
2
+ ActionView::Template.register_template_handler(:mustache, MustacheHandler)
@@ -0,0 +1,142 @@
1
+ module QuestionChain
2
+ module Answerable
3
+ extend ActiveSupport::Concern
4
+ include MongoMapper::Serialize
5
+
6
+ included do
7
+ key :question_id, ObjectId
8
+ key :result, Hash
9
+ key :answer_params, Hash
10
+ key :answer_json, String
11
+ key :user_id, ObjectId
12
+ key :reference, String
13
+ key :stored_identifier, String
14
+ key :stored_variable_input, String
15
+ key :created_by, String
16
+ key :_extra_keywords, Array
17
+ timestamps!
18
+
19
+ cattr_accessor :_extra_keyword_methods
20
+ before_save :add_stored_identifier
21
+ before_save :add_extra_keywords
22
+ before_save :cache_attributes
23
+
24
+ # == Search
25
+ plugin Hunt
26
+ searches :reference, :created_by, :stored_variable_input, :stored_identifier, :_extra_keywords
27
+ ensure_index :'searches.default'
28
+
29
+ # == Indexes
30
+ ensure_index :reference
31
+ ensure_index :stored_identifier
32
+ ensure_index :stored_variable_input
33
+
34
+ # == Validations
35
+ validates_presence_of :question_id
36
+ validates_presence_of :answer_params
37
+ validates_presence_of :result
38
+ validates_true_for :answer, :logic => Proc.new {!answer_params.empty?}, :message => nil
39
+ validates_true_for :result, :logic => Proc.new {!result.empty?}, :message => nil
40
+
41
+ # == Associations
42
+ belongs_to :user
43
+
44
+ # == attr Protected
45
+ attr_protected :user_id
46
+
47
+ end
48
+
49
+ module ClassMethods
50
+ require "csv" #ruby19
51
+ def self.to_csv(options = {})
52
+ @csv_string ||= FasterCSV.generate do |csv|
53
+ # header row
54
+ csv << self.attributes_for_api
55
+
56
+ # data rows
57
+ self.all(options).each do |resource|
58
+ attributes = self.attributes_for_api.map do |key|
59
+ resource.send(key)
60
+ end
61
+ csv << attributes
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ module InstanceMethods
68
+ def add_extra_keywords
69
+ unless (self.class._extra_keyword_methods || []).empty?
70
+ self.class._extra_keyword_methods.each do |method|
71
+ self._extra_keywords << self.send(method)
72
+ end
73
+ end
74
+ end
75
+
76
+ def object_reference_characteristics(object_reference = self.object_reference)
77
+ object_reference["characteristics"]
78
+ end
79
+
80
+ def object_references
81
+ result["object_references"]
82
+ end
83
+
84
+ def object_reference(object_reference_id = self.object_reference_id)
85
+ result["object_references"] && result["object_references"][object_reference_id]
86
+ end
87
+
88
+ def object_reference_id(object_reference_name = self.object_reference_name)
89
+ answer_params[object_reference_name]
90
+ end
91
+
92
+ def object_reference_name
93
+ # should be set in the answerable if want to use
94
+ end
95
+
96
+ def variable_input
97
+ # should be set in the answerable if you want to use this
98
+ end
99
+
100
+ # you should set this to be what stored identifier you
101
+ # wish to have if you use more then 1 object in
102
+ # your calculation
103
+ def _identifier
104
+ idents = []
105
+ object_references.each_pair do |key, value|
106
+ idents << value["identifier"]
107
+ end
108
+ idents.join(" ")
109
+ end
110
+
111
+ def identifier
112
+ _identifier == read_attribute(:stored_identifier) ? read_attribute(:stored_identifier) : _identifier
113
+ end
114
+
115
+ def co2
116
+ (result["calculations"]["co2"]["value"] || 0).to_f
117
+ end
118
+
119
+ def ch4
120
+ (result["calculations"]["ch4"]["value"] || 0).to_f
121
+ end
122
+
123
+ def n2o
124
+ (result["calculations"]["n2o"]["value"]|| 0).to_f
125
+ end
126
+
127
+ def co2e
128
+ (result["calculations"]["co2e"]["value"] || 0).to_f
129
+ end
130
+
131
+ private
132
+ def add_stored_identifier
133
+ self.stored_identifier = self.identifier
134
+ end
135
+
136
+ def cache_attributes
137
+ write_attribute(:created_by, user.full_name)
138
+ write_attribute(:stored_variable_input, variable_input)
139
+ end
140
+ end
141
+ end
142
+ end
@@ -0,0 +1,290 @@
1
+ module QuestionChain
2
+ module Answers
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ before_filter :get_context
7
+ before_filter :load_contexts, :except => [:fire_object_search, :fire_populate_drop_down]
8
+ respond_to :json, :only => [:fire_object_search, :fire_populate_drop_down]
9
+ helper_method :question_chain_update_answer_path, :question_chain_answer_path, :collection_path
10
+ end
11
+
12
+ module InstanceMethods
13
+ def new
14
+ @answer = build_resource
15
+ enforce_permission
16
+ @question = question_from_context
17
+ new!
18
+ end
19
+
20
+ def edit
21
+ @answer = resource
22
+ enforce_permission
23
+ @question = Question.find!(resource.question_id).to_hash
24
+ @answer_params = @answer.answer_params # used for mustache templates
25
+ set_answer_values_on_question!(@question, @answer_params)
26
+ edit!
27
+ end
28
+
29
+ def update
30
+ @answer = resource
31
+ enforce_permission
32
+ @answer.user_id = current_user.id
33
+ @answer.answer_params = params[:answer]
34
+ @answer_params = params[:answer] # used for mustache templates
35
+ @question = Question.find!(resource.question_id).to_hash
36
+ @answer.result = get_answer(@question, @answer_params)
37
+ set_answer_values_on_question!(@question, @answer_params)
38
+ build_answer_errors!
39
+ update! do |success, failure|
40
+ success.html do
41
+ flash[:notice] = update_success_flash_message
42
+ @contexts << @answer
43
+ redirect_to update_success_path
44
+ end
45
+ end
46
+ end
47
+
48
+ def create
49
+ @answer = build_resource
50
+ enforce_permission
51
+ @answer.user_id = current_user.id
52
+ @answer.answer_params = params[:answer]
53
+ @answer_params = params[:answer] # used for mustache templates
54
+ @question = question_from_context
55
+ @answer.question_id = @question.id
56
+ @answer.result = get_answer(@question, @answer_params)
57
+ set_answer_values_on_question!(@question, @answer_params)
58
+ build_answer_errors!
59
+ create! do |success, failure|
60
+ success.html do
61
+ flash[:notice] = create_success_flash_message
62
+ @contexts << @answer
63
+ redirect_to create_success_path
64
+ end
65
+ end
66
+ end
67
+
68
+ # == Rule firing for drop down
69
+ def fire_populate_drop_down
70
+ if ui_object = UiObject.find(params[:ui_object_id])
71
+ if rule = ui_object.rules.find(params[:rule_id])
72
+ return render :json => {"options" => rule.get_options(params[:object_ids])}.to_json
73
+ end
74
+ end
75
+ render :json => {:error => "Could not find rule"}.to_json
76
+ end
77
+
78
+ # == Rule firing for search
79
+ def fire_object_search
80
+ if ui_object = UiObject.find(params[:ui_object_id])
81
+ if rule = ui_object.rules.find(params[:rule_id])
82
+ return render :json => {"options" => rule.get_options(params[:q], params[:relatable_category_values])}.to_json
83
+ end
84
+ end
85
+ render :json => {:error => "Could not find rule"}.to_json
86
+ end
87
+
88
+ # seems strange but its true allows
89
+ # for pagination link to work inside list view
90
+ # when editing
91
+ def show
92
+ end_of_association_chain
93
+ redirect_to edit_from_context_path
94
+ end
95
+
96
+ # seems strange but its true
97
+ # allows for pagination link to work
98
+ # when creating a new answer
99
+ def index
100
+ end_of_association_chain
101
+ redirect_to new_from_context_path
102
+ end
103
+
104
+ def enforce_permission
105
+ # override to force permission on the answer object
106
+ end
107
+
108
+ protected
109
+ def create_success_flash_message
110
+ "Your co2 was #{@answer.result["calculations"]["co2"]["value"]} #{@answer.result["calculations"]["co2"]["units"]}"
111
+ end
112
+
113
+ def update_success_flash_message
114
+ "Your co2 was updated to #{@answer.result["calculations"]["co2"]["value"]} #{@answer.result["calculations"]["co2"]["units"]}"
115
+ end
116
+
117
+ def question_chain_answer_path
118
+ contexts = @contexts.dup
119
+ contexts << :answers
120
+ self.send(path_method_from_contexts(contexts), {:context => @context, :question_id => @question.id})
121
+ end
122
+
123
+ def question_chain_update_answer_path
124
+ contexts = @contexts.dup
125
+ contexts << :answer
126
+ self.send(path_method_from_contexts(contexts), {:context => @context, :question_id => @question.id, :id => resource.id})
127
+ end
128
+
129
+ # allows the ui to know what values have been set
130
+ # and therefore sets the ui_objects values
131
+ #
132
+ # @param [Hash] question hash representation of the question
133
+ # @param [Hash] answer_params
134
+ def set_answer_values_on_question!(question_hash, answer)
135
+ answer.each_pair do |key, value|
136
+ question_hash.ui_groups.map{|group| group.ui_objects}.flatten.each do |ui_object|
137
+ if ui_object.name == key.to_s
138
+ ui_object.value = value
139
+ end
140
+ end
141
+ end
142
+ end
143
+
144
+ # @param [Question] calculator_id
145
+ # @param [Hash] answer_params
146
+ # @return [Hash] the result from the co2 computation
147
+ #  which many container errors
148
+ def get_answer(question, answer_params)
149
+ if computation_id = answer_params[:computation_id].blank? ? question.computation_id : answer_params[:computation_id]
150
+ QuestionChain.calculated_session.answer_for_computation(computation_id, answer_params)
151
+ elsif calculator_id = question.calculator_id
152
+ QuestionChain.calculated_session.answer_for_calculator(calculator_id, answer_params)
153
+ end
154
+ end
155
+
156
+ # we false the generation of any normal errors
157
+ # on the answer and merge in the carboncalculated
158
+ # errors as well
159
+ #
160
+ # base errors are in the form of an array
161
+ # errors that have fields are in the form of a hash
162
+ def build_answer_errors!
163
+ if @answer.result[:errors]
164
+ @answer.valid?
165
+ if @answer.result[:errors].is_a?(Hash)
166
+ @answer.errors.merge!(@answer.result[:errors])
167
+ else
168
+ @answer.errors.merge!({:base => @answer.result[:errors]})
169
+ end
170
+ @answer.errors.each_pair{|key, value| value.respond_to?(:flatten!) ? value.flatten! : value}
171
+ @answer.instance_exec(@answer) do |answer|
172
+ def answer.valid?
173
+ false
174
+ end
175
+ # we dont want this to update any attributes if its invalid!
176
+ # this results in a very strange BUG! if not applied
177
+ def answer.update_attributes(attributes)
178
+ false
179
+ end
180
+ end
181
+ end
182
+ end
183
+
184
+ def find_question_ids
185
+ if template = get_chain_template_for_resource(parent_type.to_s)
186
+ template["context"][params[:context]]
187
+ else
188
+ # render not found or something
189
+ end
190
+ end
191
+
192
+ def question_from_context
193
+ if question_id = params[:question_id]
194
+ Question.find!(question_id).to_hash
195
+ else
196
+ ids = find_question_ids
197
+ Question.find!(ids.first).to_hash
198
+ end
199
+ end
200
+
201
+ def resource_collection_name
202
+ @context
203
+ end
204
+
205
+ # handle single resource case scenerio via singularize
206
+ def resource
207
+ if resource_collection_name.singularize == resource_collection_name
208
+ get_resource_ivar || set_resource_ivar(end_of_association_chain)
209
+ else
210
+ get_resource_ivar || set_resource_ivar(end_of_association_chain.find(params[:id]))
211
+ end
212
+ end
213
+
214
+ def collection
215
+ get_collection_ivar || set_collection_ivar(end_of_association_chain.paginate(:page => params[:page], :per_page => 25, :order => :created_at.desc))
216
+ end
217
+
218
+ def get_context
219
+ @context = params[:context]
220
+ end
221
+
222
+ # Loads the contexts and any parent resources
223
+ # to allow easy generation of urls back to
224
+ # the context enclosing resources
225
+ def load_contexts(enclosed_parent = nil)
226
+ end_of_association_chain
227
+ @contexts = [] if @contexts.nil?
228
+ enclosed_parent = enclosed_parent.nil? ? self.parent : enclosed_parent
229
+ unless @contexts.include?(enclosed_parent)
230
+ @contexts << enclosed_parent
231
+ if chain_template = get_chain_template_for_resource(parent.class.name.downcase)
232
+ if parent_resource = chain_template.parent_resource
233
+ resource = parent.send(parent_resource)
234
+ instance_variable_set("@#{parent_resource}", resource)
235
+ load_contexts(resource)
236
+ end
237
+ end
238
+ end
239
+ @contexts.reverse!
240
+ end
241
+
242
+ def new_from_context_path
243
+ new_polymorphic_path(@contexts)
244
+ end
245
+
246
+ def edit_from_context_path
247
+ new_polymorphic_path(@contexts)
248
+ end
249
+
250
+ # if a method matching the context and action that will be called
251
+ # otherwise the polymorphic path is used
252
+ def create_success_path
253
+ if self.respond_to?(path_method_from_contexts(@contexts, "create_success_"))
254
+ self.send(path_method_from_contexts(@contexts, "create_success_"))
255
+ else
256
+ polymorphic_path(@contexts)
257
+ end
258
+ end
259
+
260
+ # builds a url method from the contexts and a given action
261
+ # @param [String] action
262
+ #
263
+ # @return [String] url method call
264
+ def path_method_from_contexts(contexts, action = "")
265
+ url_method = contexts.inject("#{action}") do |string, parent|
266
+ segment = (parent.is_a?(Symbol)) ? parent.to_s : ActiveModel::Naming.singular(parent)
267
+ string << segment
268
+ string << "_"
269
+ end
270
+ url_method << "path"
271
+ url_method
272
+ end
273
+
274
+ # if a method has been decleared of a specific update that is called
275
+ # otherwise the default polymophic path is used
276
+ def update_success_path
277
+ if self.respond_to?(path_method_from_contexts(@contexts, "update_success_"))
278
+ self.send(path_method_from_contexts(@contexts, "update_success_"))
279
+ else
280
+ polymorphic_path(@contexts)
281
+ end
282
+ end
283
+
284
+ def get_chain_template_for_resource(for_resource)
285
+ ChainTemplate.first(:model_state => "active", :for_resource => for_resource, :account_id => @account.try(:id)) ||
286
+ ChainTemplate.first(:model_state => "active", :for_resource => for_resource)
287
+ end
288
+ end
289
+ end
290
+ end
@@ -0,0 +1,21 @@
1
+ module Answers
2
+ class QuestionView < MustacheRails
3
+
4
+ def name
5
+ question.name
6
+ end
7
+
8
+ def label
9
+ question.label
10
+ end
11
+
12
+ def description
13
+ question.description
14
+ end
15
+
16
+ private
17
+ def question
18
+ @question ||= context[:_question]
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,67 @@
1
+ module Answers
2
+ class UiObjectView < MustacheRails
3
+
4
+ def dom_id
5
+ "ui_object_#{ui_object.id}"
6
+ end
7
+
8
+ def input_id
9
+ "ui_input_#{ui_object.id}"
10
+ end
11
+
12
+ def extra_info
13
+ ui_object.try(:extra_info)
14
+ end
15
+
16
+ def css_classes
17
+ ui_object.css_classes.join(" ")
18
+ end
19
+
20
+ def has_extra_info
21
+ !extra_info.blank?
22
+ end
23
+
24
+ def label
25
+ ui_object.label
26
+ end
27
+
28
+ def value
29
+ answer_params[ui_object_name] if answer_params
30
+ end
31
+
32
+ def ui_object_name
33
+ ui_object.name
34
+ end
35
+
36
+ def name
37
+ "answer[#{ui_object.name}]"
38
+ end
39
+
40
+ def default_value
41
+ ui_object.default_value
42
+ end
43
+
44
+ def default_styles
45
+ default_styles = ""
46
+ ui_object.ui_attributes.each_pair do |key, value|
47
+ if key.to_s == "visible" && value == "false"
48
+ default_styles << "display:none;visibility:hidden;"
49
+ end
50
+ end
51
+ default_styles
52
+ end
53
+
54
+ def disabled
55
+ ui_object.ui_attributes["disable"] == "true"
56
+ end
57
+
58
+ protected
59
+ def ui_object
60
+ @ui_object ||= context[:_ui_object]
61
+ end
62
+
63
+ def answer_params
64
+ @answer_params ||= context[:_answer_params]
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,17 @@
1
+ module Answers
2
+ class UiObjectsCheckBoxView < Answers::UiObjectView
3
+
4
+ def value
5
+ super || default_value
6
+ end
7
+
8
+ def checked
9
+ if value
10
+ !value.nil?
11
+ else
12
+ ui_object.ui_attributes[:checked]
13
+ end
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,16 @@
1
+ module Answers
2
+ class UiObjectsDropDownView < Answers::UiObjectView
3
+
4
+ def prompt
5
+ ui_object.prompt
6
+ end
7
+
8
+ def options
9
+ if answer_params
10
+ ui_object.options.map{|option| option.merge!(:selected => option["value"].to_s == value.to_s)}
11
+ else
12
+ ui_object.options
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,8 @@
1
+ module Answers
2
+ class UiObjectsHiddenFieldView < Answers::UiObjectView
3
+
4
+ def value
5
+ super || default_value
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,18 @@
1
+ module Answers
2
+ class UiObjectsObjectReferenceDropDownView < Answers::UiObjectView
3
+
4
+ def prompt
5
+ ui_object.prompt
6
+ end
7
+
8
+ # @return [Array<Hash<value => value, name => name>>]
9
+ def options
10
+ if answer_params
11
+ ui_object.options.map{|option| option.merge!(:selected => option["value"].to_s == value.to_s)}
12
+ else
13
+ ui_object.options
14
+ end
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ module Answers
2
+ class UiObjectsObjectSearchView < Answers::UiObjectView
3
+
4
+ def search_name
5
+ "answer[search_#{name}]"
6
+ end
7
+
8
+ def search_id
9
+ "search_#{dom_id()}"
10
+ end
11
+
12
+ def search_value
13
+ if answer_params
14
+ answer_params["search_answer"][ui_object_name]
15
+ end
16
+ end
17
+
18
+ def value
19
+ super || default_value
20
+ end
21
+ end
22
+ end