turkee_rails4 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. checksums.yaml +7 -0
  2. data/.document +5 -0
  3. data/.gitignore +27 -0
  4. data/.travis.yml +8 -0
  5. data/Gemfile +14 -0
  6. data/Gemfile.lock +121 -0
  7. data/Guardfile +12 -0
  8. data/LICENSE +20 -0
  9. data/README.rdoc +205 -0
  10. data/Rakefile +50 -0
  11. data/VERSION +1 -0
  12. data/lib/generators/turkee/templates/add_completed_tasks.rb.erb +17 -0
  13. data/lib/generators/turkee/templates/add_expired.rb.erb +15 -0
  14. data/lib/generators/turkee/templates/add_hit_duration.rb.erb +15 -0
  15. data/lib/generators/turkee/templates/add_imported_assignment_details.rb.erb +33 -0
  16. data/lib/generators/turkee/templates/create_turkee_study.rb.erb +18 -0
  17. data/lib/generators/turkee/templates/turkee.rb +8 -0
  18. data/lib/generators/turkee/templates/turkee_imported_assignments.rb.erb +16 -0
  19. data/lib/generators/turkee/templates/turkee_migration.rb.erb +25 -0
  20. data/lib/generators/turkee/turkee_generator.rb +51 -0
  21. data/lib/helpers/turkee_forms_helper.rb +69 -0
  22. data/lib/models/turkee_imported_assignment.rb +15 -0
  23. data/lib/models/turkee_study.rb +11 -0
  24. data/lib/models/turkee_task.rb +259 -0
  25. data/lib/tasks/turkee.rb +29 -0
  26. data/lib/turkee.rb +8 -0
  27. data/spec/dummy/Rakefile +7 -0
  28. data/spec/dummy/app/assets/javascripts/application.js +5 -0
  29. data/spec/dummy/app/assets/stylesheets/application.css +7 -0
  30. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  31. data/spec/dummy/app/controllers/surveys_controller.rb +7 -0
  32. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  33. data/spec/dummy/app/mailers/.gitkeep +0 -0
  34. data/spec/dummy/app/models/.gitkeep +0 -0
  35. data/spec/dummy/app/models/survey.rb +3 -0
  36. data/spec/dummy/app/views/layouts/application.html.erb +19 -0
  37. data/spec/dummy/config/application.rb +41 -0
  38. data/spec/dummy/config/boot.rb +10 -0
  39. data/spec/dummy/config/database.yml +25 -0
  40. data/spec/dummy/config/environment.rb +5 -0
  41. data/spec/dummy/config/environments/development.rb +26 -0
  42. data/spec/dummy/config/environments/production.rb +54 -0
  43. data/spec/dummy/config/environments/test.rb +38 -0
  44. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  45. data/spec/dummy/config/initializers/inflections.rb +10 -0
  46. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  47. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  48. data/spec/dummy/config/initializers/session_store.rb +8 -0
  49. data/spec/dummy/config/initializers/wrap_parameters.rb +12 -0
  50. data/spec/dummy/config/locales/en.yml +5 -0
  51. data/spec/dummy/config/routes.rb +61 -0
  52. data/spec/dummy/config.ru +4 -0
  53. data/spec/dummy/db/migrate/20110710143903_initial_tables.rb +23 -0
  54. data/spec/dummy/db/migrate/20120819164528_add_association_with_class_name.rb +12 -0
  55. data/spec/dummy/db/migrate/20130203095901_create_company.rb +14 -0
  56. data/spec/dummy/db/schema.rb +45 -0
  57. data/spec/dummy/public/404.html +26 -0
  58. data/spec/dummy/public/422.html +26 -0
  59. data/spec/dummy/public/500.html +26 -0
  60. data/spec/dummy/public/favicon.ico +0 -0
  61. data/spec/dummy/script/rails +6 -0
  62. data/spec/dummy/tmp/cache/.gitkeep +0 -0
  63. data/spec/factories/survey_factory.rb +7 -0
  64. data/spec/factories/turkee_task_factory.rb +21 -0
  65. data/spec/helpers/turkee_forms_helper_spec.rb +75 -0
  66. data/spec/models/turkee_study_spec.rb +19 -0
  67. data/spec/models/turkee_task_spec.rb +146 -0
  68. data/spec/spec.opts +1 -0
  69. data/spec/spec_helper.rb +89 -0
  70. data/turkee.gemspec +59 -0
  71. metadata +232 -0
@@ -0,0 +1,51 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+
4
+ class TurkeeGenerator < Rails::Generators::Base
5
+ include Rails::Generators::Migration
6
+
7
+ # Implement the required interface for Rails::Generators::Migration.
8
+ # taken from http://github.com/rails/rails/blob/master/activerecord/lib/generators/active_record.rb
9
+ def self.next_migration_number(dirname)
10
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
11
+ end
12
+
13
+ source_root File.expand_path("../templates", __FILE__)
14
+
15
+ desc "Creates initializer and migrations."
16
+
17
+ def create_migrations
18
+ migration_template "turkee_migration.rb.erb", "db/migrate/create_turkee_tasks.rb"
19
+
20
+ # Need this sleep so that we don't get the same migration timestamp for both migrations
21
+ sleep 1
22
+
23
+ migration_template "turkee_imported_assignments.rb.erb", "db/migrate/create_turkee_imported_assignments.rb"
24
+
25
+ sleep 1
26
+
27
+ migration_template "add_completed_tasks.rb.erb", "db/migrate/add_completed_tasks.rb"
28
+
29
+ sleep 1
30
+
31
+ migration_template "add_imported_assignment_details.rb.erb", "db/migrate/add_imported_assignment_details.rb"
32
+
33
+ sleep 1
34
+
35
+ migration_template "add_hit_duration.rb.erb", "db/migrate/add_hit_duration.rb"
36
+
37
+ sleep 1
38
+
39
+ migration_template "add_expired.rb.erb", "db/migrate/add_expired.rb"
40
+
41
+ sleep 1
42
+
43
+ migration_template "create_turkee_study.rb.erb", "db/migrate/create_turkee_study.rb"
44
+
45
+ end
46
+
47
+ def create_initializer
48
+ template "turkee.rb", "config/initializers/turkee.rb"
49
+ end
50
+
51
+ end
@@ -0,0 +1,69 @@
1
+ module Turkee
2
+
3
+ module TurkeeFormHelper
4
+ def turkee_form_for(record, params, options = {}, &proc)
5
+ raise ArgumentError, "turkee_form_for now requires that you pass in the entire params hash, instead of just the assignmentId value. " unless params.is_a?(Hash)
6
+
7
+ options.merge!({:url => mturk_url})
8
+
9
+ capture do
10
+ form_for record, options do |f|
11
+ params.each do |k,v|
12
+ unless ['action','controller'].include?(k) || !v.is_a?(String)
13
+ concat hidden_field_tag(k, v)
14
+ cookies[k] = v
15
+ end
16
+ end
17
+
18
+ ['assignmentId', 'workerId', 'hitId'].each do |k|
19
+ concat hidden_field_tag(k, cookies[k]) if !params.has_key?(k) && cookies.has_key?(k)
20
+ end
21
+
22
+ concat(capture(f, &proc))
23
+ end
24
+ end
25
+ end
26
+
27
+ def turkee_study(id = nil)
28
+ task = id.nil? ? Turkee::TurkeeTask.last : Turkee::TurkeeTask.find(id)
29
+ study = Turkee::TurkeeStudy.new
30
+ disabled = Turkee::TurkeeFormHelper::disable_form_fields?(params[:assignmentId])
31
+
32
+ if task.present?
33
+ style = "position: fixed; top: 120px; right: 30px; color: #FFF;"
34
+ style << "width: 400px; height: 375px; z-index: 100; padding: 10px;"
35
+ style << "background-color: rgba(0,0,0, 0.5); border: 1px solid #000;"
36
+
37
+ div_for(task, :style => style) do
38
+ capture do
39
+ concat content_tag(:h3, "DIRECTIONS", :style => 'text-align: right; color:#FF0000;')
40
+ concat task.hit_description.html_safe
41
+ concat '<hr/>'.html_safe
42
+ concat(turkee_form_for(study, params) do |f|
43
+ concat f.label(:feedback, "Feedback?:")
44
+ concat f.text_area(:feedback, :rows => 3, :disabled => disabled)
45
+ concat f.label(:gold_response, "Enter the fourth word from your above feedback :")
46
+ concat f.text_field(:gold_response, :disabled => disabled)
47
+ concat f.hidden_field(:turkee_task_id, :value => task.id)
48
+ concat '<br/>'.html_safe
49
+ concat f.submit('Submit', :disabled => disabled)
50
+ end)
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ # Returns the external Mechanical Turk url used to post form data based on whether RTurk is cofigured
57
+ # for sandbox use or not.
58
+ def mturk_url
59
+ RTurk.sandbox? ? "https://workersandbox.mturk.com/mturk/externalSubmit" : "https://www.mturk.com/mturk/externalSubmit"
60
+ end
61
+
62
+ # Returns whether the form fields should be disabled or not (based on the assignment_id)
63
+ def self.disable_form_fields?(assignment)
64
+ assignment_id = assignment.is_a?(Hash) ? assignment[:assignmentId] : assignment
65
+ (assignment_id.nil? || assignment_id == 'ASSIGNMENT_ID_NOT_AVAILABLE')
66
+ end
67
+ end
68
+
69
+ end
@@ -0,0 +1,15 @@
1
+ require 'active_record'
2
+
3
+ module Turkee
4
+ class TurkeeImportedAssignment < ActiveRecord::Base
5
+ attr_accessible :assignment_id, :turkee_task_id, :worker_id, :result_id if ActiveRecord::VERSION::MAJOR < 4
6
+
7
+ def self.record_imported_assignment(assignment, result, turk)
8
+ TurkeeImportedAssignment.create!(:assignment_id => assignment.id,
9
+ :turkee_task_id => turk.id,
10
+ :worker_id => assignment.worker_id,
11
+ :result_id => result.id)
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ module Turkee
2
+ class TurkeeStudy < ActiveRecord::Base
3
+ GOLD_RESPONSE_INDEX = 3
4
+ attr_accessible :turkee_task_id, :feedback, :gold_response if ActiveRecord::VERSION::MAJOR < 4
5
+
6
+ def approve?
7
+ words = feedback.split(/\W+/)
8
+ gold_response.present? ? (gold_response == words[GOLD_RESPONSE_INDEX]) : true
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,259 @@
1
+ require 'rubygems'
2
+ require 'socket'
3
+ require 'rturk'
4
+ require 'lockfile'
5
+ require 'active_record'
6
+ require "active_support/core_ext/object/to_query"
7
+ require 'action_controller'
8
+
9
+ module Turkee
10
+
11
+ class TurkeeTask < ActiveRecord::Base
12
+ attr_accessible :sandbox, :hit_title, :hit_description, :hit_reward, :hit_num_assignments, :hit_lifetime, :hit_duration,
13
+ :form_url, :hit_url, :hit_id, :task_type, :complete if ActiveRecord::VERSION::MAJOR < 4
14
+
15
+ HIT_FRAMEHEIGHT = 1000
16
+
17
+ scope :unprocessed_hits, lambda { where('complete = ? AND sandbox = ?', false, RTurk.sandbox?) }
18
+
19
+ # Use this method to go out and retrieve the data for all of the posted Turk Tasks.
20
+ # Each specific TurkeeTask object (determined by task_type field) is in charge of
21
+ # accepting/rejecting the assignment and importing the data into their respective tables.
22
+ def self.process_hits(turkee_task = nil)
23
+
24
+ begin
25
+ # Using a lockfile to prevent multiple calls to Amazon.
26
+ Lockfile.new('/tmp/turk_processor.lock', :max_age => 3600, :retries => 10) do
27
+
28
+ turks = task_items(turkee_task)
29
+
30
+ turks.each do |turk|
31
+ hit = RTurk::Hit.new(turk.hit_id)
32
+
33
+ callback_models = Set.new
34
+ hit.assignments.each do |assignment|
35
+ next unless submitted?(assignment.status)
36
+ next if assignment_exists?(assignment)
37
+
38
+ model, param_hash = map_imported_values(assignment, turk.task_type)
39
+ next if model.nil?
40
+
41
+ callback_models << model
42
+
43
+ result = save_imported_values(model, param_hash)
44
+
45
+ # If there's a custom approve? method, see if we should approve the submitted assignment
46
+ # otherwise just approve it by default
47
+ turk.process_result(assignment, result)
48
+
49
+ TurkeeImportedAssignment.record_imported_assignment(assignment, result, turk)
50
+ end
51
+
52
+ turk.set_expired?(callback_models) if !turk.set_complete?(hit, callback_models)
53
+ end
54
+ end
55
+ rescue Lockfile::MaxTriesLockError => e
56
+ logger.info "TurkTask.process_hits is already running or the lockfile /tmp/turk_processor.lock exists from an improperly shutdown previous process. Exiting method call."
57
+ end
58
+
59
+ end
60
+
61
+ def self.save_imported_values(model, param_hash)
62
+ key = model.to_s.underscore.gsub('/','_') # Namespaced model will come across as turkee/turkee_study,
63
+ # we must translate to turkee_turkee_study"
64
+ model.create(param_hash[key])
65
+ end
66
+
67
+ # Creates a new Mechanical Turk task on AMZN with the given title, desc, etc
68
+ def self.create_hit(host, hit_title, hit_description, typ, num_assignments, reward, lifetime,
69
+ duration = nil, qualifications = {}, params = {}, opts = {})
70
+ model = typ.to_s.constantize
71
+ f_url = build_url(host, model, params, opts)
72
+
73
+ h = RTurk::Hit.create(:title => hit_title) do |hit|
74
+ hit.max_assignments = num_assignments if hit.respond_to?(:max_assignments)
75
+ hit.assignments = num_assignments if hit.respond_to?(:assignments)
76
+
77
+ hit.description = hit_description
78
+ hit.reward = reward
79
+ hit.lifetime = lifetime.to_i.days.seconds.to_i
80
+ hit.duration = duration.to_i.hours.seconds.to_i if duration
81
+ hit.question(f_url, :frame_height => HIT_FRAMEHEIGHT)
82
+ unless qualifications.empty?
83
+ qualifications.each do |key, value|
84
+ hit.qualifications.add key, value
85
+ end
86
+ end
87
+ end
88
+
89
+ TurkeeTask.create(:sandbox => RTurk.sandbox?,
90
+ :hit_title => hit_title, :hit_description => hit_description,
91
+ :hit_reward => reward.to_f, :hit_num_assignments => num_assignments.to_i,
92
+ :hit_lifetime => lifetime, :hit_duration => duration,
93
+ :form_url => f_url, :hit_url => h.url,
94
+ :hit_id => h.id, :task_type => typ,
95
+ :complete => false)
96
+
97
+ end
98
+
99
+ ##########################################################################################################
100
+ # DON'T PUSH THIS BUTTON UNLESS YOU MEAN IT. :)
101
+ def self.clear_all_turks(force = false)
102
+ # Do NOT execute this function if we're in production mode
103
+ raise "You can only clear turks in the sandbox/development environment unless you pass 'true' for the force flag." if Rails.env == 'production' && !force
104
+
105
+ hits = RTurk::Hit.all
106
+
107
+ logger.info "#{hits.size} reviewable hits. \n"
108
+
109
+ unless hits.empty?
110
+ logger.info "Approving all assignments and disposing of each hit."
111
+
112
+ hits.each do |hit|
113
+ begin
114
+ hit.expire!
115
+ hit.assignments.each do |assignment|
116
+ logger.info "Assignment status : #{assignment.status}"
117
+ assignment.approve!('__clear_all_turks__approved__') if assignment.status == 'Submitted'
118
+ end
119
+
120
+ turkee_task = TurkeeTask.where(hit_id: hit.id).first
121
+ turkee_task.complete_task if turkee_task.present?
122
+
123
+ hit.dispose!
124
+ rescue Exception => e
125
+ # Probably a service unavailable
126
+ logger.error "Exception : #{e.to_s}"
127
+ end
128
+ end
129
+ end
130
+
131
+ end
132
+
133
+ def complete_task
134
+ self.complete = true
135
+ save!
136
+ end
137
+
138
+ def set_complete?(hit, models)
139
+ if completed_assignments?
140
+ hit.dispose!
141
+ complete_task
142
+ initiate_callback(:hit_complete, models)
143
+ return true
144
+ end
145
+
146
+ false
147
+ end
148
+
149
+ def set_expired?(models)
150
+ if expired?
151
+ self.expired = true
152
+ save!
153
+ initiate_callback(:hit_expired, models)
154
+ end
155
+ end
156
+
157
+ def initiate_callback(method, models)
158
+ models.each { |model| model.send(method, self) if model.respond_to?(method) }
159
+ end
160
+
161
+ def process_result(assignment, result)
162
+ if result.errors.size > 0
163
+ logger.info "Errors : #{result.inspect}"
164
+ assignment.reject!('Failed to enter proper data.')
165
+ elsif result.respond_to?(:approve?)
166
+ logger.debug "Approving : #{result.inspect}"
167
+ self.increment_complete_assignments
168
+ result.approve? ? assignment.approve!('') : assignment.reject!('Rejected criteria.')
169
+ else
170
+ self.increment_complete_assignments
171
+ assignment.approve!('')
172
+ end
173
+ end
174
+
175
+ def increment_complete_assignments
176
+ raise "Missing :completed_assignments attribute. Please upgrade Turkee to the most recent version." unless respond_to?(:completed_assignments)
177
+
178
+ self.completed_assignments += 1
179
+ save
180
+ end
181
+
182
+ private
183
+
184
+ def logger
185
+ @logger ||= Logger.new($stderr)
186
+ end
187
+
188
+ def self.map_imported_values(assignment, default_type)
189
+ params = assignment_params(assignment.answers)
190
+ param_hash = Rack::Utils.parse_nested_query(params)
191
+
192
+ model = find_model(param_hash)
193
+ model = default_type.constantize if model.nil?
194
+
195
+ return model, param_hash
196
+ end
197
+
198
+ def self.assignment_exists?(assignment)
199
+ TurkeeImportedAssignment.find_by_assignment_id(assignment.id).present?
200
+ end
201
+
202
+ def completed_assignments?
203
+ completed_assignments == hit_num_assignments
204
+ end
205
+
206
+ def expired?
207
+ Time.now >= (created_at + hit_lifetime.days)
208
+ end
209
+
210
+ def self.task_items(turkee_task)
211
+ turkee_task.nil? ? TurkeeTask.unprocessed_hits : Array.new << turkee_task
212
+ end
213
+
214
+ def self.submitted?(status)
215
+ (status == 'Submitted')
216
+ end
217
+
218
+ def self.assignment_params(answers)
219
+ answers.to_query
220
+ end
221
+
222
+ # Method looks at the parameter and attempts to find an ActiveRecord model
223
+ # in the current app that would match the properties of one of the nested hashes
224
+ # x = {:submit = 'Create', :iteration_vote => {:iteration_id => 1}}
225
+ # The above _should_ return an IterationVote model
226
+ def self.find_model(param_hash)
227
+ param_hash.each do |k, v|
228
+ if v.is_a?(Hash)
229
+ model = k.to_s.camelize.constantize rescue next
230
+ return model if model.descends_from_active_record? rescue next
231
+ end
232
+ end
233
+ nil
234
+ end
235
+
236
+ # Returns custom URL if opts[:form_url] is specified. Otherwise, builds the default url from the model's :new route
237
+ def self.build_url(host, model, params, opts)
238
+ if opts[:form_url]
239
+ full_url(opts[:form_url], params)
240
+ else
241
+ form_url(host, model, params)
242
+ end
243
+ end
244
+
245
+ # Returns the default url of the model's :new route
246
+ def self.form_url(host, typ, params = {})
247
+ @app ||= ActionDispatch::Integration::Session.new(Rails.application)
248
+ url = (host + @app.send("new_#{typ.to_s.underscore}_path"))
249
+ full_url(url, params)
250
+ end
251
+
252
+ # Appends params to the url as a query string
253
+ def self.full_url(u, params)
254
+ url = u
255
+ url = "#{u}?#{params.to_query}" unless params.empty?
256
+ url
257
+ end
258
+ end
259
+ end
@@ -0,0 +1,29 @@
1
+ require 'rake'
2
+ require 'turkee'
3
+
4
+ namespace :turkee do
5
+ desc "Post your form to Mechanical Turk (HIT). Task takes the application's host URL, HIT title, HIT description, model name, number of responses, reward for each response, number of days the HIT should be valid, and number of hours a worker has to complete the HIT."
6
+ task :post_hit, [:host, :title, :description, :model, :num_assignments, :reward, :lifetime] => :environment do |t, args|
7
+ hit = Turkee::TurkeeTask.create_hit(args[:host],args[:title], args[:description], args[:model],
8
+ args[:num_assignments], args[:reward], args[:lifetime])
9
+ puts "Hit created : #{hit.hit_url}"
10
+ end
11
+
12
+ desc "Retrieve all results from Mechanical Turk for all open HITs."
13
+ task :get_all_results => :environment do
14
+ Turkee::TurkeeTask.process_hits
15
+ end
16
+
17
+ desc "Create a usability study. Task takes the application's full url, HIT title, HIT description, model name, number of responses, reward for each response, number of days the HIT should be valid, and number of hours a worker has to complete the HIT."
18
+ task :create_study, [:url, :title, :description, :num_assignments, :reward, :lifetime] => :environment do |t, args|
19
+ qualifications = {:approval_rate => {:gt => 70}, :country => {:eql => 'US'}}
20
+
21
+ hit = Turkee::TurkeeTask.create_hit(args[:url], args[:title], args[:description], "Turkee::TurkeeStudy",
22
+ args[:num_assignments], args[:reward], args[:lifetime],
23
+ nil, qualifications, {}, {:form_url => args[:url]})
24
+ puts
25
+ puts "Study created : #{hit.hit_url}"
26
+ end
27
+
28
+
29
+ end
data/lib/turkee.rb ADDED
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+ require 'action_view'
3
+ require 'helpers/turkee_forms_helper'
4
+ require 'models/turkee_imported_assignment'
5
+ require 'models/turkee_task'
6
+ require 'models/turkee_study'
7
+
8
+ ActionView::Base.send :include, Turkee::TurkeeFormHelper
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env rake
2
+ # Add your own tasks in files placed in lib/tasks ending in .rake,
3
+ # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
4
+
5
+ require File.expand_path('../config/application', __FILE__)
6
+
7
+ Dummy::Application.load_tasks
@@ -0,0 +1,5 @@
1
+ // This is a manifest file that'll be compiled into including all the files listed below.
2
+ // Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
3
+ // be included in the compiled file accessible from http://example.com/assets/application.js
4
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
5
+ // the compiled file.
@@ -0,0 +1,7 @@
1
+ /*
2
+ * This is a manifest file that'll automatically include all the stylesheets available in this directory
3
+ * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
4
+ * the top of the compiled file, but it's generally better to create a new file per style scope.
5
+ *= require_self
6
+ *= require_tree .
7
+ */
@@ -0,0 +1,3 @@
1
+ class ApplicationController < ActionController::Base
2
+ protect_from_forgery
3
+ end
@@ -0,0 +1,7 @@
1
+ class SurveysController < ApplicationController
2
+
3
+ def new
4
+
5
+ end
6
+
7
+ end
@@ -0,0 +1,2 @@
1
+ module ApplicationHelper
2
+ end
File without changes
File without changes
@@ -0,0 +1,3 @@
1
+ class Survey < ActiveRecord::Base
2
+ attr_accessible :answer
3
+ end
@@ -0,0 +1,19 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Dummy</title>
5
+
6
+ <% if params[:type] == 'prototype' %>
7
+ <%= javascript_include_tag 'prototype', 'prototype_nested_form', 'prototype_events_test' %>
8
+ <% else %>
9
+ <%= javascript_include_tag 'jquery', 'jquery_nested_form', 'jquery_events_test' %>
10
+ <% end %>
11
+ </head>
12
+ <body>
13
+
14
+ <%= yield %>
15
+
16
+ <div id="console"></div>
17
+
18
+ </body>
19
+ </html>
@@ -0,0 +1,41 @@
1
+ require File.expand_path('../boot', __FILE__)
2
+
3
+ require 'rails/all'
4
+
5
+ Bundler.require
6
+
7
+ module Dummy
8
+ class Application < Rails::Application
9
+ # Settings in config/environments/* take precedence over those specified here.
10
+ # Application configuration should go into files in config/initializers
11
+ # -- all .rb files in that directory are automatically loaded.
12
+
13
+ # Custom directories with classes and modules you want to be autoloadable.
14
+ # config.autoload_paths += %W(#{config.root}/extras)
15
+
16
+ # Only load the plugins named here, in the order given (default is alphabetical).
17
+ # :all can be used as a placeholder for all plugins not explicitly named.
18
+ # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
19
+
20
+ # Activate observers that should always be running.
21
+ # config.active_record.observers = :cacher, :garbage_collector, :forum_observer
22
+
23
+ # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
24
+ # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
25
+ # config.time_zone = 'Central Time (US & Canada)'
26
+
27
+ # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
28
+ # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
29
+ # config.i18n.default_locale = :de
30
+
31
+ # Configure the default encoding used in templates for Ruby 1.9.
32
+ config.encoding = "utf-8"
33
+
34
+ # Configure sensitive parameters which will be filtered from the log file.
35
+ config.filter_parameters += [:password]
36
+
37
+ # Enable the asset pipeline
38
+ config.assets.enabled = true if config.respond_to?(:assets)
39
+ end
40
+ end
41
+
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+
3
+ gemfile = ENV['BUNDLE_GEMFILE'] || File.expand_path('../../../../Gemfile', __FILE__)
4
+ if File.exist?(gemfile)
5
+ ENV['BUNDLE_GEMFILE'] = gemfile
6
+ require 'bundler'
7
+ Bundler.setup
8
+ end
9
+
10
+ $:.unshift File.expand_path('../../../../lib', __FILE__)
@@ -0,0 +1,25 @@
1
+ # SQLite version 3.x
2
+ # gem install sqlite3
3
+ #
4
+ # Ensure the SQLite 3 gem is defined in your Gemfile
5
+ # gem 'sqlite3'
6
+ development:
7
+ adapter: sqlite3
8
+ database: ":memory:"
9
+ pool: 5
10
+ timeout: 5000
11
+
12
+ # Warning: The database defined as "test" will be erased and
13
+ # re-generated from your development database when you run "rake".
14
+ # Do not set this db to the same as development or production.
15
+ test:
16
+ adapter: sqlite3
17
+ database: ":memory:"
18
+ pool: 5
19
+ timeout: 5000
20
+
21
+ production:
22
+ adapter: sqlite3
23
+ database: ":memory:"
24
+ pool: 5
25
+ timeout: 5000
@@ -0,0 +1,5 @@
1
+ # Load the rails application
2
+ require File.expand_path('../application', __FILE__)
3
+
4
+ # Initialize the rails application
5
+ Dummy::Application.initialize!
@@ -0,0 +1,26 @@
1
+ Dummy::Application.configure do
2
+ # Settings specified here will take precedence over those in config/application.rb
3
+
4
+ # In the development environment your application's code is reloaded on
5
+ # every request. This slows down response time but is perfect for development
6
+ # since you don't have to restart the web server when you make code changes.
7
+ config.cache_classes = false
8
+
9
+ config.eager_load = false if Rails::VERSION::MAJOR >= 4
10
+
11
+ # Show full error reports and disable caching
12
+ config.consider_all_requests_local = true
13
+ config.action_controller.perform_caching = false
14
+
15
+ # Don't care if the mailer can't send
16
+ config.action_mailer.raise_delivery_errors = false
17
+
18
+ # Print deprecation notices to the Rails logger
19
+ config.active_support.deprecation = :log
20
+
21
+ # Only use best-standards-support built into browsers
22
+ config.action_dispatch.best_standards_support = :builtin
23
+
24
+ # Do not compress assets
25
+ config.assets.compress = false if config.respond_to?(:assets)
26
+ end