turkee-mongoid 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +5 -0
- data/.gitignore +27 -0
- data/.travis.yml +8 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +136 -0
- data/Guardfile +12 -0
- data/LICENSE +188 -0
- data/README.rdoc +219 -0
- data/Rakefile +50 -0
- data/VERSION +1 -0
- data/lib/generators/turkee/templates/turkee.rb +8 -0
- data/lib/generators/turkee/turkee_generator.rb +13 -0
- data/lib/helpers/turkee_forms_helper.rb +69 -0
- data/lib/models/turkee_imported_assignment.rb +19 -0
- data/lib/models/turkee_study.rb +17 -0
- data/lib/models/turkee_task.rb +273 -0
- data/lib/tasks/turkee.rb +29 -0
- data/lib/turkee.rb +9 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/survey.rb +6 -0
- data/spec/dummy/app/views/layouts/application.html.erb +20 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +21 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +24 -0
- data/spec/dummy/config/environments/production.rb +51 -0
- data/spec/dummy/config/environments/test.rb +37 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +10 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/mongoid.yml +21 -0
- data/spec/dummy/config/routes.rb +2 -0
- data/spec/dummy/db/seeds.rb +0 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/javascripts/application.js +2 -0
- data/spec/dummy/public/javascripts/controls.js +965 -0
- data/spec/dummy/public/javascripts/dragdrop.js +974 -0
- data/spec/dummy/public/javascripts/effects.js +1123 -0
- data/spec/dummy/public/javascripts/prototype.js +6001 -0
- data/spec/dummy/public/javascripts/rails.js +191 -0
- data/spec/dummy/public/stylesheets/.gitkeep +0 -0
- data/spec/dummy/public/stylesheets/scaffold.css +56 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/factories/survey_factory.rb +7 -0
- data/spec/factories/turkee_task_factory.rb +21 -0
- data/spec/helpers/turkee_forms_helper_spec.rb +75 -0
- data/spec/models/turkee_study_spec.rb +19 -0
- data/spec/models/turkee_task_spec.rb +139 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +49 -0
- data/turkee.gemspec +60 -0
- metadata +243 -0
data/Rakefile
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'bundler'
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
Bundler::GemHelper.install_tasks
|
6
|
+
|
7
|
+
$:.push File.expand_path("../lib", __FILE__)
|
8
|
+
|
9
|
+
desc "Run specs"
|
10
|
+
RSpec::Core::RakeTask.new(:spec)
|
11
|
+
|
12
|
+
desc 'Default: run specs.'
|
13
|
+
task :default => :spec
|
14
|
+
|
15
|
+
begin
|
16
|
+
INSTALL_MESSAGE = %q{
|
17
|
+
========================================================================
|
18
|
+
Turkee Installation Complete.
|
19
|
+
------------------------------------------------------------------------
|
20
|
+
If you're upgrading Turkee (1.1.1 and prior) or installing for the first time, run:
|
21
|
+
|
22
|
+
rails g turkee --skip
|
23
|
+
|
24
|
+
For full instructions on gem usage, visit:
|
25
|
+
http://github.com/aantix/turkee#readme
|
26
|
+
|
27
|
+
** If you like the Turkee gem, please click the "watch" button on the
|
28
|
+
Github project page. You'll make me smile and feel appreciated. :)
|
29
|
+
http://github.com/aantix/turkee
|
30
|
+
|
31
|
+
========================================================================
|
32
|
+
}
|
33
|
+
|
34
|
+
Gem::Specification.new do |gem|
|
35
|
+
gem.name = "turkee"
|
36
|
+
gem.summary = "Turkee makes dealing with Amazon's Mechnical Turk a breeze."
|
37
|
+
gem.description = "Turkee will help you to create your Rails forms, post the HITs, and retrieve the user entered values from Mechanical Turk."
|
38
|
+
gem.email = "jjones@aantix.com"
|
39
|
+
gem.homepage = "http://github.com/aantix/turkee"
|
40
|
+
gem.authors = ["Jim Jones"]
|
41
|
+
gem.add_dependency(%q<rails>, [">= 3.1.1"])
|
42
|
+
gem.add_dependency(%q<rturk>, [">= 2.4.0"])
|
43
|
+
gem.add_dependency(%q<lockfile>, [">= 1.4.3"])
|
44
|
+
|
45
|
+
gem.post_install_message = INSTALL_MESSAGE
|
46
|
+
gem.require_path = 'lib'
|
47
|
+
gem.files = %w(MIT-LICENSE README.textile Gemfile Rakefile init.rb) + Dir.glob("{lib,spec}/**/*")
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.0.0
|
@@ -0,0 +1,8 @@
|
|
1
|
+
# Go to this page https://aws-portal.amazon.com/gp/aws/developer/account/index.html?action=access-key
|
2
|
+
# to retrieve your AWS/Mechanical Turk access keys.
|
3
|
+
|
4
|
+
AWSACCESSKEYID = 'XXXXXXXXXXXXXXXXXX'
|
5
|
+
AWSSECRETACCESSKEY = 'YYYYYYYYYYYYYYYYYYYYYYYYYYYY'
|
6
|
+
|
7
|
+
RTurk::logger.level = Logger::DEBUG
|
8
|
+
RTurk.setup(AWSACCESSKEYID, AWSSECRETACCESSKEY, :sandbox => (Rails.env == 'production' ? false : true))
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
|
3
|
+
class TurkeeGenerator < Rails::Generators::Base
|
4
|
+
|
5
|
+
source_root File.expand_path("../templates", __FILE__)
|
6
|
+
|
7
|
+
desc "Creates initializer and migrations."
|
8
|
+
|
9
|
+
def create_initializer
|
10
|
+
template "turkee.rb", "config/initializers/turkee.rb"
|
11
|
+
end
|
12
|
+
|
13
|
+
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,19 @@
|
|
1
|
+
module Turkee
|
2
|
+
class TurkeeImportedAssignment
|
3
|
+
include Mongoid::Document
|
4
|
+
include Mongoid::Timestamps
|
5
|
+
|
6
|
+
field :assignment_id, type: String # TODO validates assignment_id, uniqueness: true ?
|
7
|
+
field :turkee_task_id, type: Integer
|
8
|
+
field :worker_id, type: String
|
9
|
+
field :result_id, type: Integer
|
10
|
+
|
11
|
+
def self.record_imported_assignment(assignment, result, turk)
|
12
|
+
TurkeeImportedAssignment.create!(:assignment_id => assignment.id,
|
13
|
+
:turkee_task_id => turk.id,
|
14
|
+
:worker_id => assignment.worker_id,
|
15
|
+
:result_id => result.id)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Turkee
|
2
|
+
class TurkeeStudy
|
3
|
+
include Mongoid::Document
|
4
|
+
include Mongoid::Timestamps
|
5
|
+
|
6
|
+
field :turkee_task_id, type: Integer
|
7
|
+
field :feedback, type: String
|
8
|
+
field :gold_response, type: String
|
9
|
+
|
10
|
+
GOLD_RESPONSE_INDEX = 3
|
11
|
+
|
12
|
+
def approve?
|
13
|
+
words = feedback.split(/\W+/)
|
14
|
+
gold_response.present? ? (gold_response == words[GOLD_RESPONSE_INDEX]) : true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,273 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'socket'
|
3
|
+
require 'rturk'
|
4
|
+
require 'lockfile'
|
5
|
+
require "active_support/core_ext/object/to_query"
|
6
|
+
require 'action_controller'
|
7
|
+
|
8
|
+
module Turkee
|
9
|
+
|
10
|
+
class TurkeeTask
|
11
|
+
include Mongoid::Document
|
12
|
+
include Mongoid::Timestamps
|
13
|
+
|
14
|
+
field :sandbox, type: Boolean
|
15
|
+
field :hit_title, type: String #TODO text
|
16
|
+
field :hit_description, type: String #TODO text
|
17
|
+
field :hit_reward, type: BigDecimal # :precision => 10, :scale => 2
|
18
|
+
field :hit_num_assignments, type: Integer
|
19
|
+
field :hit_lifetime, type: Integer
|
20
|
+
field :hit_duration, type: Integer
|
21
|
+
field :form_url, type: String
|
22
|
+
field :hit_url, type: String
|
23
|
+
field :hit_id, type: String
|
24
|
+
field :task_type, type: String
|
25
|
+
field :complete, type: Boolean
|
26
|
+
field :completed_assignments, type: Integer, default: 0
|
27
|
+
field :expired, type: Integer
|
28
|
+
|
29
|
+
HIT_FRAMEHEIGHT = 1000
|
30
|
+
|
31
|
+
scope :unprocessed_hits, lambda { where('complete = ? AND sandbox = ?', false, RTurk.sandbox?) }
|
32
|
+
|
33
|
+
# Use this method to go out and retrieve the data for all of the posted Turk Tasks.
|
34
|
+
# Each specific TurkeeTask object (determined by task_type field) is in charge of
|
35
|
+
# accepting/rejecting the assignment and importing the data into their respective tables.
|
36
|
+
def self.process_hits(turkee_task = nil)
|
37
|
+
|
38
|
+
begin
|
39
|
+
# Using a lockfile to prevent multiple calls to Amazon.
|
40
|
+
Lockfile.new('/tmp/turk_processor.lock', :max_age => 3600, :retries => 10) do
|
41
|
+
|
42
|
+
turks = task_items(turkee_task)
|
43
|
+
|
44
|
+
turks.each do |turk|
|
45
|
+
hit = RTurk::Hit.new(turk.hit_id)
|
46
|
+
|
47
|
+
callback_models = Set.new
|
48
|
+
hit.assignments.each do |assignment|
|
49
|
+
next unless submitted?(assignment.status)
|
50
|
+
next if assignment_exists?(assignment)
|
51
|
+
|
52
|
+
model, param_hash = map_imported_values(assignment, turk.task_type)
|
53
|
+
next if model.nil?
|
54
|
+
|
55
|
+
callback_models << model
|
56
|
+
|
57
|
+
result = save_imported_values(model, param_hash)
|
58
|
+
|
59
|
+
# If there's a custom approve? method, see if we should approve the submitted assignment
|
60
|
+
# otherwise just approve it by default
|
61
|
+
turk.process_result(assignment, result)
|
62
|
+
|
63
|
+
TurkeeImportedAssignment.record_imported_assignment(assignment, result, turk)
|
64
|
+
end
|
65
|
+
|
66
|
+
turk.set_expired?(callback_models) if !turk.set_complete?(hit, callback_models)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
rescue Lockfile::MaxTriesLockError => e
|
70
|
+
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."
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.save_imported_values(model, param_hash)
|
76
|
+
key = model.to_s.underscore.gsub('/','_') # Namespaced model will come across as turkee/turkee_study,
|
77
|
+
# we must translate to turkee_turkee_study"
|
78
|
+
model.create(param_hash[key])
|
79
|
+
end
|
80
|
+
|
81
|
+
# Creates a new Mechanical Turk task on AMZN with the given title, desc, etc
|
82
|
+
def self.create_hit(host, hit_title, hit_description, typ, num_assignments, reward, lifetime,
|
83
|
+
duration = nil, qualifications = {}, params = {}, opts = {})
|
84
|
+
model = typ.to_s.constantize
|
85
|
+
f_url = build_url(host, model, params, opts)
|
86
|
+
|
87
|
+
h = RTurk::Hit.create(:title => hit_title) do |hit|
|
88
|
+
hit.max_assignments = num_assignments if hit.respond_to?(:max_assignments)
|
89
|
+
hit.assignments = num_assignments if hit.respond_to?(:assignments)
|
90
|
+
|
91
|
+
hit.description = hit_description
|
92
|
+
hit.reward = reward
|
93
|
+
hit.lifetime = lifetime.to_i.days.seconds.to_i
|
94
|
+
hit.duration = duration.to_i.hours.seconds.to_i if duration
|
95
|
+
hit.question(f_url, :frame_height => HIT_FRAMEHEIGHT)
|
96
|
+
unless qualifications.empty?
|
97
|
+
qualifications.each do |key, value|
|
98
|
+
hit.qualifications.add key, value
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
TurkeeTask.create(:sandbox => RTurk.sandbox?,
|
104
|
+
:hit_title => hit_title, :hit_description => hit_description,
|
105
|
+
:hit_reward => reward.to_f, :hit_num_assignments => num_assignments.to_i,
|
106
|
+
:hit_lifetime => lifetime, :hit_duration => duration,
|
107
|
+
:form_url => f_url, :hit_url => h.url,
|
108
|
+
:hit_id => h.id, :task_type => typ,
|
109
|
+
:complete => false)
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
##########################################################################################################
|
114
|
+
# DON'T PUSH THIS BUTTON UNLESS YOU MEAN IT. :)
|
115
|
+
def self.clear_all_turks(force = false)
|
116
|
+
# Do NOT execute this function if we're in production mode
|
117
|
+
raise "You can only clear turks in the sandbox/development environment unless you pass 'true' for the force flag." if Rails.env == 'production' && !force
|
118
|
+
|
119
|
+
hits = RTurk::Hit.all
|
120
|
+
|
121
|
+
logger.info "#{hits.size} reviewable hits. \n"
|
122
|
+
|
123
|
+
unless hits.empty?
|
124
|
+
logger.info "Approving all assignments and disposing of each hit."
|
125
|
+
|
126
|
+
hits.each do |hit|
|
127
|
+
begin
|
128
|
+
hit.expire!
|
129
|
+
hit.assignments.each do |assignment|
|
130
|
+
logger.info "Assignment status : #{assignment.status}"
|
131
|
+
assignment.approve!('__clear_all_turks__approved__') if assignment.status == 'Submitted'
|
132
|
+
end
|
133
|
+
|
134
|
+
turkee_task = TurkeeTask.where(hit_id: hit.id).first
|
135
|
+
turkee_task.complete_task if turkee_task.present?
|
136
|
+
|
137
|
+
hit.dispose!
|
138
|
+
rescue Exception => e
|
139
|
+
# Probably a service unavailable
|
140
|
+
logger.error "Exception : #{e.to_s}"
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
|
147
|
+
def complete_task
|
148
|
+
self.complete = true
|
149
|
+
save!
|
150
|
+
end
|
151
|
+
|
152
|
+
def set_complete?(hit, models)
|
153
|
+
if completed_assignments?
|
154
|
+
hit.dispose!
|
155
|
+
complete_task
|
156
|
+
initiate_callback(:hit_complete, models)
|
157
|
+
return true
|
158
|
+
end
|
159
|
+
|
160
|
+
false
|
161
|
+
end
|
162
|
+
|
163
|
+
def set_expired?(models)
|
164
|
+
if expired?
|
165
|
+
self.expired = true
|
166
|
+
save!
|
167
|
+
initiate_callback(:hit_expired, models)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def initiate_callback(method, models)
|
172
|
+
models.each { |model| model.send(method, self) if model.respond_to?(method) }
|
173
|
+
end
|
174
|
+
|
175
|
+
def process_result(assignment, result)
|
176
|
+
if result.errors.size > 0
|
177
|
+
logger.info "Errors : #{result.inspect}"
|
178
|
+
assignment.reject!('Failed to enter proper data.')
|
179
|
+
elsif result.respond_to?(:approve?)
|
180
|
+
logger.debug "Approving : #{result.inspect}"
|
181
|
+
self.increment_complete_assignments
|
182
|
+
result.approve? ? assignment.approve!('') : assignment.reject!('Rejected criteria.')
|
183
|
+
else
|
184
|
+
self.increment_complete_assignments
|
185
|
+
assignment.approve!('')
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def increment_complete_assignments
|
190
|
+
raise "Missing :completed_assignments attribute. Please upgrade Turkee to the most recent version." unless respond_to?(:completed_assignments)
|
191
|
+
|
192
|
+
self.completed_assignments += 1
|
193
|
+
save
|
194
|
+
end
|
195
|
+
|
196
|
+
private
|
197
|
+
|
198
|
+
def logger
|
199
|
+
@logger ||= Logger.new($stderr)
|
200
|
+
end
|
201
|
+
|
202
|
+
def self.map_imported_values(assignment, default_type)
|
203
|
+
params = assignment_params(assignment.answers)
|
204
|
+
param_hash = Rack::Utils.parse_nested_query(params)
|
205
|
+
|
206
|
+
model = find_model(param_hash)
|
207
|
+
model = default_type.constantize if model.nil?
|
208
|
+
|
209
|
+
return model, param_hash
|
210
|
+
end
|
211
|
+
|
212
|
+
def self.assignment_exists?(assignment)
|
213
|
+
TurkeeImportedAssignment.find_by_assignment_id(assignment.id).present?
|
214
|
+
end
|
215
|
+
|
216
|
+
def completed_assignments?
|
217
|
+
completed_assignments == hit_num_assignments
|
218
|
+
end
|
219
|
+
|
220
|
+
def expired?
|
221
|
+
Time.now >= (created_at + hit_lifetime.days)
|
222
|
+
end
|
223
|
+
|
224
|
+
def self.task_items(turkee_task)
|
225
|
+
turkee_task.nil? ? TurkeeTask.unprocessed_hits : Array.new << turkee_task
|
226
|
+
end
|
227
|
+
|
228
|
+
def self.submitted?(status)
|
229
|
+
(status == 'Submitted')
|
230
|
+
end
|
231
|
+
|
232
|
+
def self.assignment_params(answers)
|
233
|
+
answers.to_query
|
234
|
+
end
|
235
|
+
|
236
|
+
# Method looks at the parameter and attempts to find an ActiveRecord model
|
237
|
+
# in the current app that would match the properties of one of the nested hashes
|
238
|
+
# x = {:submit = 'Create', :iteration_vote => {:iteration_id => 1}}
|
239
|
+
# The above _should_ return an IterationVote model
|
240
|
+
def self.find_model(param_hash)
|
241
|
+
param_hash.each do |k, v|
|
242
|
+
if v.is_a?(Hash)
|
243
|
+
model = k.to_s.camelize.constantize rescue next
|
244
|
+
return model if model.ancestors.include?(Mongoid::Document) rescue next
|
245
|
+
end
|
246
|
+
end
|
247
|
+
nil
|
248
|
+
end
|
249
|
+
|
250
|
+
# Returns custom URL if opts[:form_url] is specified. Otherwise, builds the default url from the model's :new route
|
251
|
+
def self.build_url(host, model, params, opts)
|
252
|
+
if opts[:form_url]
|
253
|
+
full_url(opts[:form_url], params)
|
254
|
+
else
|
255
|
+
form_url(host, model, params)
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
# Returns the default url of the model's :new route
|
260
|
+
def self.form_url(host, typ, params = {})
|
261
|
+
@app ||= ActionController::Integration::Session.new(Rails.application)
|
262
|
+
url = (host + @app.send("new_#{typ.to_s.underscore}_path"))
|
263
|
+
full_url(url, params)
|
264
|
+
end
|
265
|
+
|
266
|
+
# Appends params to the url as a query string
|
267
|
+
def self.full_url(u, params)
|
268
|
+
url = u
|
269
|
+
url = "#{u}?#{params.to_query}" unless params.empty?
|
270
|
+
url
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|