coupler 0.0.1-java

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.
Files changed (258) hide show
  1. data/.document +5 -0
  2. data/.gitmodules +3 -0
  3. data/.rvmrc +1 -0
  4. data/.vimrc +40 -0
  5. data/Gemfile +27 -0
  6. data/Gemfile.lock +71 -0
  7. data/LICENSE +20 -0
  8. data/NOTES +6 -0
  9. data/README.rdoc +18 -0
  10. data/Rakefile +42 -0
  11. data/TODO +11 -0
  12. data/VERSION +1 -0
  13. data/bin/coupler +7 -0
  14. data/db/.gitignore +6 -0
  15. data/db/migrate/001_initial_schema.rb +166 -0
  16. data/db/migrate/002_stub.rb +4 -0
  17. data/db/migrate/003_stub.rb +4 -0
  18. data/db/migrate/004_create_comparisons.rb +28 -0
  19. data/db/migrate/005_move_database_name.rb +19 -0
  20. data/db/migrate/006_upgrade_comparisons.rb +34 -0
  21. data/db/migrate/007_add_which_to_comparisons.rb +23 -0
  22. data/db/migrate/008_add_result_field_to_transformations.rb +33 -0
  23. data/db/migrate/009_add_generated_flag_to_fields.rb +13 -0
  24. data/db/migrate/010_create_imports.rb +24 -0
  25. data/db/migrate/011_add_primary_key_type.rb +13 -0
  26. data/db/migrate/012_add_transformed_with_to_resources.rb +13 -0
  27. data/db/migrate/013_add_run_count_to_scenarios.rb +13 -0
  28. data/db/migrate/014_add_last_accessed_at_to_some_tables.rb +13 -0
  29. data/db/migrate/015_add_run_number_to_results.rb +15 -0
  30. data/db/migrate/016_fix_scenario_run_count.rb +27 -0
  31. data/db/migrate/017_rename_comparison_columns.rb +14 -0
  32. data/db/migrate/018_fix_scenario_linkage_type.rb +8 -0
  33. data/db/migrate/019_add_columns_to_imports.rb +24 -0
  34. data/db/migrate/020_rename_import_columns.rb +12 -0
  35. data/db/migrate/021_add_fields_to_connections.rb +15 -0
  36. data/db/migrate/022_remove_database_name_from_resources.rb +11 -0
  37. data/features/connections.feature +28 -0
  38. data/features/matchers.feature +35 -0
  39. data/features/projects.feature +11 -0
  40. data/features/resources.feature +62 -0
  41. data/features/scenarios.feature +45 -0
  42. data/features/step_definitions/coupler_steps.rb +145 -0
  43. data/features/step_definitions/matchers_steps.rb +26 -0
  44. data/features/step_definitions/resources_steps.rb +12 -0
  45. data/features/step_definitions/scenarios_steps.rb +7 -0
  46. data/features/step_definitions/transformations_steps.rb +3 -0
  47. data/features/support/env.rb +128 -0
  48. data/features/transformations.feature +22 -0
  49. data/features/wizard.feature +10 -0
  50. data/gfx/coupler-header.svg +213 -0
  51. data/gfx/coupler-sidebar.svg +656 -0
  52. data/gfx/coupler.svg +184 -0
  53. data/gfx/icon.svg +75 -0
  54. data/lib/coupler/base.rb +63 -0
  55. data/lib/coupler/config.rb +128 -0
  56. data/lib/coupler/data_uploader.rb +20 -0
  57. data/lib/coupler/database.rb +31 -0
  58. data/lib/coupler/extensions/connections.rb +57 -0
  59. data/lib/coupler/extensions/exceptions.rb +58 -0
  60. data/lib/coupler/extensions/imports.rb +43 -0
  61. data/lib/coupler/extensions/jobs.rb +21 -0
  62. data/lib/coupler/extensions/matchers.rb +64 -0
  63. data/lib/coupler/extensions/projects.rb +62 -0
  64. data/lib/coupler/extensions/resources.rb +89 -0
  65. data/lib/coupler/extensions/results.rb +100 -0
  66. data/lib/coupler/extensions/scenarios.rb +50 -0
  67. data/lib/coupler/extensions/transformations.rb +70 -0
  68. data/lib/coupler/extensions/transformers.rb +58 -0
  69. data/lib/coupler/extensions.rb +16 -0
  70. data/lib/coupler/helpers.rb +121 -0
  71. data/lib/coupler/import_buffer.rb +48 -0
  72. data/lib/coupler/logger.rb +16 -0
  73. data/lib/coupler/models/common_model.rb +104 -0
  74. data/lib/coupler/models/comparison.rb +166 -0
  75. data/lib/coupler/models/connection.rb +59 -0
  76. data/lib/coupler/models/field.rb +55 -0
  77. data/lib/coupler/models/import.rb +238 -0
  78. data/lib/coupler/models/job.rb +42 -0
  79. data/lib/coupler/models/jobify.rb +17 -0
  80. data/lib/coupler/models/matcher.rb +36 -0
  81. data/lib/coupler/models/project.rb +40 -0
  82. data/lib/coupler/models/resource.rb +287 -0
  83. data/lib/coupler/models/result.rb +92 -0
  84. data/lib/coupler/models/scenario/runner.rb +357 -0
  85. data/lib/coupler/models/scenario.rb +115 -0
  86. data/lib/coupler/models/transformation.rb +117 -0
  87. data/lib/coupler/models/transformer/runner.rb +28 -0
  88. data/lib/coupler/models/transformer.rb +110 -0
  89. data/lib/coupler/models.rb +30 -0
  90. data/lib/coupler/runner.rb +76 -0
  91. data/lib/coupler/scheduler.rb +56 -0
  92. data/lib/coupler.rb +34 -0
  93. data/log/.gitignore +1 -0
  94. data/misc/README +5 -0
  95. data/misc/jruby-json.license +57 -0
  96. data/misc/rack-flash.license +22 -0
  97. data/script/dbconsole.rb +5 -0
  98. data/src/edu/vanderbilt/coupler/Main.java +116 -0
  99. data/src/edu/vanderbilt/coupler/jruby.properties +1 -0
  100. data/tasks/annotations.rake +84 -0
  101. data/tasks/db.rake +120 -0
  102. data/tasks/environment.rake +12 -0
  103. data/tasks/jeweler.rake +43 -0
  104. data/tasks/package.rake +58 -0
  105. data/tasks/rdoc.rake +13 -0
  106. data/tasks/test.rake +63 -0
  107. data/tasks/vendor.rake +43 -0
  108. data/test/README.txt +6 -0
  109. data/test/config.yml +9 -0
  110. data/test/coupler/models/test_import.rb +221 -0
  111. data/test/factories.rb +91 -0
  112. data/test/fixtures/duplicate-keys.csv +5 -0
  113. data/test/fixtures/no-headers.csv +50 -0
  114. data/test/fixtures/people.csv +51 -0
  115. data/test/fixtures/varying-row-size.csv +4 -0
  116. data/test/helper.rb +156 -0
  117. data/test/integration/extensions/test_connections.rb +80 -0
  118. data/test/integration/extensions/test_imports.rb +94 -0
  119. data/test/integration/extensions/test_jobs.rb +52 -0
  120. data/test/integration/extensions/test_matchers.rb +134 -0
  121. data/test/integration/extensions/test_projects.rb +82 -0
  122. data/test/integration/extensions/test_resources.rb +150 -0
  123. data/test/integration/extensions/test_results.rb +89 -0
  124. data/test/integration/extensions/test_scenarios.rb +88 -0
  125. data/test/integration/extensions/test_transformations.rb +113 -0
  126. data/test/integration/extensions/test_transformers.rb +80 -0
  127. data/test/integration/test_field.rb +45 -0
  128. data/test/integration/test_import.rb +78 -0
  129. data/test/integration/test_running_scenarios.rb +379 -0
  130. data/test/integration/test_transformation.rb +56 -0
  131. data/test/integration/test_transforming.rb +154 -0
  132. data/test/table_sets.rb +76 -0
  133. data/test/unit/models/test_common_model.rb +130 -0
  134. data/test/unit/models/test_comparison.rb +619 -0
  135. data/test/unit/models/test_connection.rb +115 -0
  136. data/test/unit/models/test_field.rb +99 -0
  137. data/test/unit/models/test_import.rb +130 -0
  138. data/test/unit/models/test_job.rb +115 -0
  139. data/test/unit/models/test_matcher.rb +82 -0
  140. data/test/unit/models/test_project.rb +102 -0
  141. data/test/unit/models/test_resource.rb +564 -0
  142. data/test/unit/models/test_result.rb +90 -0
  143. data/test/unit/models/test_scenario.rb +199 -0
  144. data/test/unit/models/test_transformation.rb +193 -0
  145. data/test/unit/models/test_transformer.rb +188 -0
  146. data/test/unit/test_base.rb +60 -0
  147. data/test/unit/test_data_uploader.rb +27 -0
  148. data/test/unit/test_database.rb +23 -0
  149. data/test/unit/test_helpers.rb +58 -0
  150. data/test/unit/test_logger.rb +10 -0
  151. data/test/unit/test_models.rb +12 -0
  152. data/test/unit/test_runner.rb +76 -0
  153. data/test/unit/test_scheduler.rb +66 -0
  154. data/uploads/.gitignore +2 -0
  155. data/vendor/java/.gitignore +5 -0
  156. data/webroot/public/css/960.css +1 -0
  157. data/webroot/public/css/dataTables.css +1057 -0
  158. data/webroot/public/css/jquery-ui.css +572 -0
  159. data/webroot/public/css/jquery.treeview.css +68 -0
  160. data/webroot/public/css/reset.css +1 -0
  161. data/webroot/public/css/style.css +504 -0
  162. data/webroot/public/css/text.css +1 -0
  163. data/webroot/public/favicon.ico +0 -0
  164. data/webroot/public/images/12_col.gif +0 -0
  165. data/webroot/public/images/16_col.gif +0 -0
  166. data/webroot/public/images/add.png +0 -0
  167. data/webroot/public/images/ajax-loader.gif +0 -0
  168. data/webroot/public/images/cog.png +0 -0
  169. data/webroot/public/images/coupler.png +0 -0
  170. data/webroot/public/images/foo.png +0 -0
  171. data/webroot/public/images/hammer.png +0 -0
  172. data/webroot/public/images/header.png +0 -0
  173. data/webroot/public/images/home.gif +0 -0
  174. data/webroot/public/images/jobs.gif +0 -0
  175. data/webroot/public/images/sidebar-bottom.png +0 -0
  176. data/webroot/public/images/sidebar.png +0 -0
  177. data/webroot/public/images/treeview-default-line.gif +0 -0
  178. data/webroot/public/images/treeview-default.gif +0 -0
  179. data/webroot/public/images/ui-anim_basic_16x16.gif +0 -0
  180. data/webroot/public/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  181. data/webroot/public/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  182. data/webroot/public/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  183. data/webroot/public/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  184. data/webroot/public/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  185. data/webroot/public/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  186. data/webroot/public/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  187. data/webroot/public/images/ui-bg_highlight-hard_30_565356_1x100.png +0 -0
  188. data/webroot/public/images/ui-bg_highlight-hard_75_888588_1x100.png +0 -0
  189. data/webroot/public/images/ui-bg_highlight-soft_30_6e3b3a_1x100.png +0 -0
  190. data/webroot/public/images/ui-bg_highlight-soft_35_8e8b8e_1x100.png +0 -0
  191. data/webroot/public/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  192. data/webroot/public/images/ui-icons_222222_256x240.png +0 -0
  193. data/webroot/public/images/ui-icons_2e83ff_256x240.png +0 -0
  194. data/webroot/public/images/ui-icons_454545_256x240.png +0 -0
  195. data/webroot/public/images/ui-icons_888888_256x240.png +0 -0
  196. data/webroot/public/images/ui-icons_cd0a0a_256x240.png +0 -0
  197. data/webroot/public/images/ui-icons_ffffff_256x240.png +0 -0
  198. data/webroot/public/js/ajaxupload.js +673 -0
  199. data/webroot/public/js/application.js +40 -0
  200. data/webroot/public/js/jquery-ui.combobox.js +98 -0
  201. data/webroot/public/js/jquery-ui.js +9867 -0
  202. data/webroot/public/js/jquery-ui.min.js +559 -0
  203. data/webroot/public/js/jquery.dataTables.min.js +587 -0
  204. data/webroot/public/js/jquery.min.js +154 -0
  205. data/webroot/public/js/jquery.timeago.js +140 -0
  206. data/webroot/public/js/jquery.tooltip.min.js +19 -0
  207. data/webroot/public/js/jquery.treeview.min.js +15 -0
  208. data/webroot/public/js/resource.js +11 -0
  209. data/webroot/public/js/results.js +56 -0
  210. data/webroot/public/js/transformations.js +95 -0
  211. data/webroot/views/connections/index.erb +5 -0
  212. data/webroot/views/connections/list.erb +34 -0
  213. data/webroot/views/connections/new.erb +55 -0
  214. data/webroot/views/connections/show.erb +36 -0
  215. data/webroot/views/imports/edit.erb +60 -0
  216. data/webroot/views/imports/form.erb +81 -0
  217. data/webroot/views/imports/new.erb +89 -0
  218. data/webroot/views/index.erb +12 -0
  219. data/webroot/views/jobs/index.erb +7 -0
  220. data/webroot/views/jobs/list.erb +24 -0
  221. data/webroot/views/layout.erb +38 -0
  222. data/webroot/views/matchers/form.erb +250 -0
  223. data/webroot/views/matchers/list.erb +32 -0
  224. data/webroot/views/projects/form.erb +14 -0
  225. data/webroot/views/projects/index.erb +96 -0
  226. data/webroot/views/projects/show.erb +24 -0
  227. data/webroot/views/resources/edit.erb +88 -0
  228. data/webroot/views/resources/index.erb +5 -0
  229. data/webroot/views/resources/list.erb +27 -0
  230. data/webroot/views/resources/new.erb +121 -0
  231. data/webroot/views/resources/show.erb +86 -0
  232. data/webroot/views/resources/transform.erb +2 -0
  233. data/webroot/views/results/csv.erb +12 -0
  234. data/webroot/views/results/details.erb +15 -0
  235. data/webroot/views/results/index.erb +2 -0
  236. data/webroot/views/results/list.erb +22 -0
  237. data/webroot/views/results/record.erb +24 -0
  238. data/webroot/views/results/show.erb +68 -0
  239. data/webroot/views/scenarios/index.erb +5 -0
  240. data/webroot/views/scenarios/list.erb +20 -0
  241. data/webroot/views/scenarios/new.erb +99 -0
  242. data/webroot/views/scenarios/run.erb +2 -0
  243. data/webroot/views/scenarios/show.erb +50 -0
  244. data/webroot/views/sidebar.erb +106 -0
  245. data/webroot/views/transformations/create.erb +115 -0
  246. data/webroot/views/transformations/for.erb +16 -0
  247. data/webroot/views/transformations/index.erb +2 -0
  248. data/webroot/views/transformations/list.erb +29 -0
  249. data/webroot/views/transformations/new.erb +126 -0
  250. data/webroot/views/transformations/preview.erb +46 -0
  251. data/webroot/views/transformers/edit.erb +6 -0
  252. data/webroot/views/transformers/form.erb +58 -0
  253. data/webroot/views/transformers/index.erb +2 -0
  254. data/webroot/views/transformers/list.erb +25 -0
  255. data/webroot/views/transformers/new.erb +5 -0
  256. data/webroot/views/transformers/preview.erb +23 -0
  257. data/webroot/views/transformers/show.erb +0 -0
  258. metadata +558 -0
@@ -0,0 +1,21 @@
1
+ module Coupler
2
+ module Extensions
3
+ module Jobs
4
+ def self.registered(app)
5
+ app.get "/jobs" do
6
+ @jobs = Models::Job.order("id DESC")
7
+ erb 'jobs/index'.to_sym
8
+ end
9
+
10
+ app.get "/jobs/count" do
11
+ Models::Job.filter(:completed_at => nil).count.to_s
12
+ end
13
+
14
+ app.get "/jobs/:id/progress" do
15
+ @job = Models::Job[:id => params[:id]]
16
+ { :completed => @job.completed, :total => @job.total }.to_json
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,64 @@
1
+ module Coupler
2
+ module Extensions
3
+ module Matchers
4
+ def self.registered(app)
5
+ app.get "/projects/:project_id/scenarios/:scenario_id/matchers/new" do
6
+ @scenario = @project.scenarios_dataset[:id => params[:scenario_id]]
7
+ raise ScenarioNotFound unless @scenario
8
+ @resources = @scenario.resources
9
+ @matcher = Models::Matcher.new
10
+ erb 'matchers/form'.to_sym
11
+ end
12
+
13
+ app.get "/projects/:project_id/scenarios/:scenario_id/matchers/:id/edit" do
14
+ @scenario = @project.scenarios_dataset[:id => params[:scenario_id]]
15
+ raise ScenarioNotFound unless @scenario
16
+ @matcher = @scenario.matcher_dataset[:id => params[:id]]
17
+ raise MatcherNotFound unless @matcher
18
+ @resources = @scenario.resources
19
+ erb 'matchers/form'.to_sym
20
+ end
21
+
22
+ app.post "/projects/:project_id/scenarios/:scenario_id/matchers" do
23
+ @scenario = @project.scenarios_dataset[:id => params[:scenario_id]]
24
+ raise ScenarioNotFound unless @scenario
25
+ @matcher = Models::Matcher.new(params[:matcher])
26
+ @matcher.scenario = @scenario
27
+
28
+ if @matcher.save
29
+ flash[:notice] = "Matcher was successfully created."
30
+ redirect "/projects/#{@project.id}/scenarios/#{@scenario.id}"
31
+ else
32
+ @resources = @scenario.resources
33
+ erb 'matchers/form'.to_sym
34
+ end
35
+ end
36
+
37
+ app.put "/projects/:project_id/scenarios/:scenario_id/matchers/:id" do
38
+ @scenario = @project.scenarios_dataset[:id => params[:scenario_id]]
39
+ raise ScenarioNotFound unless @scenario
40
+ @matcher = @scenario.matcher_dataset[:id => params[:id]]
41
+ raise MatcherNotFound unless @matcher
42
+ @matcher.set(params[:matcher])
43
+
44
+ if @matcher.valid?
45
+ @matcher.save
46
+ redirect "/projects/#{@project.id}/scenarios/#{@scenario.id}"
47
+ else
48
+ @resources = @scenario.resources
49
+ erb 'matchers/form'.to_sym
50
+ end
51
+ end
52
+
53
+ app.delete "/projects/:project_id/scenarios/:scenario_id/matchers/:id" do
54
+ @scenario = @project.scenarios_dataset[:id => params[:scenario_id]]
55
+ raise ScenarioNotFound unless @scenario
56
+ @matcher = @scenario.matcher_dataset[:id => params[:id]]
57
+ raise MatcherNotFound unless @matcher
58
+ @matcher.destroy
59
+ redirect "/projects/#{@project.id}/scenarios/#{@scenario.id}"
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,62 @@
1
+ module Coupler
2
+ module Extensions
3
+ module Projects
4
+ def self.registered(app)
5
+ app.before do
6
+ md = request.path_info.match(%r{/projects/(\d+)/?})
7
+ if md
8
+ # NOTE: Using regex matching here sucks, but apparently Sinatra
9
+ # calls before filters before params are parsed.
10
+ @project = Models::Project[:id => md[1]]
11
+ raise ProjectNotFound unless @project
12
+ @project.touch!
13
+ end
14
+ end
15
+
16
+ app.get "/projects" do
17
+ @projects = Models::Project.order(:id)
18
+ @resource_counts = Models::Resource.count_by_project
19
+ @scenario_counts = Models::Scenario.count_by_project
20
+ erb 'projects/index'.to_sym
21
+ end
22
+
23
+ app.get "/projects/new" do
24
+ @project = Models::Project.new
25
+ erb 'projects/form'.to_sym
26
+ end
27
+
28
+ app.post "/projects" do
29
+ @project = Models::Project.create(params['project'])
30
+ flash[:newly_created] = true
31
+ redirect "/projects/#{@project.id}"
32
+ end
33
+
34
+ app.get "/projects/:project_id" do
35
+ @resources = @project.resources
36
+ @scenarios = @project.scenarios
37
+ erb 'projects/show'.to_sym
38
+ end
39
+
40
+ app.get "/projects/:project_id/edit" do
41
+ erb 'projects/form'.to_sym
42
+ end
43
+
44
+ app.put "/projects/:project_id" do
45
+ @project.set(params[:project])
46
+ if @project.valid?
47
+ @project.save
48
+ redirect '/projects'
49
+ else
50
+ erb 'projects/form'.to_sym
51
+ end
52
+ end
53
+
54
+ app.delete "/projects/:project_id" do
55
+ @project.delete_versions_on_destroy = true if params[:nuke] == "true"
56
+ @project.destroy
57
+ redirect '/projects'
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,89 @@
1
+ module Coupler
2
+ module Extensions
3
+ module Resources
4
+ def self.registered(app)
5
+ app.get "/projects/:project_id/resources" do
6
+ @resources = @project.resources
7
+ erb 'resources/index'.to_sym
8
+ end
9
+
10
+ app.get "/projects/:project_id/resources/new" do
11
+ @connections = Models::Connection.all
12
+ @resource = Models::Resource.new
13
+ if @connections.empty?
14
+ @resource.connection_attributes = {}
15
+ end
16
+ erb 'resources/new'.to_sym
17
+ end
18
+
19
+ app.post "/projects/:project_id/resources" do
20
+ @resource = Models::Resource.new(params[:resource])
21
+ @resource.project = @project
22
+
23
+ if @resource.save
24
+ flash[:notice] = "Resource was created successfully! Now you can choose which fields you wish to select."
25
+ redirect "/projects/#{@project.id}/resources/#{@resource.id}/edit"
26
+ else
27
+ @connections = Models::Connection.all
28
+ erb 'resources/new'.to_sym
29
+ end
30
+ end
31
+
32
+ app.get "/projects/:project_id/resources/:id" do
33
+ @resource = @project.resources_dataset[:id => params[:id]]
34
+ raise ResourceNotFound unless @resource
35
+ @fields = @resource.fields_dataset.filter(:is_selected => 1).all
36
+ @transformers = Models::Transformer.all
37
+ @transformations = @resource.transformations_dataset.order(:position)
38
+ @scenarios = @resource.scenarios
39
+ @job = @resource.jobs_dataset[:status => %w{running scheduled}]
40
+ erb 'resources/show'.to_sym
41
+ end
42
+
43
+ app.get "/projects/:project_id/resources/:id/transform" do
44
+ @resource = @project.resources_dataset[:id => params[:id]]
45
+ raise ResourceNotFound unless @resource
46
+ Scheduler.instance.schedule_transform_job(@resource)
47
+ redirect "/projects/#{@project.id}/resources/#{@resource.id}"
48
+ end
49
+
50
+ app.get "/projects/:project_id/resources/:id/edit" do
51
+ @resource = @project.resources_dataset[:id => params[:id]]
52
+ raise ResourceNotFound unless @resource
53
+ @fields = @resource.fields
54
+ @selection_count = @resource.fields_dataset.filter(:is_selected => true).count
55
+ erb 'resources/edit'.to_sym
56
+ end
57
+
58
+ app.put "/projects/:project_id/resources/:id" do
59
+ @resource = @project.resources_dataset[:id => params[:id]]
60
+ raise ResourceNotFound unless @resource
61
+
62
+ @resource.set(params[:resource]) if params[:resource]
63
+ if @resource.valid?
64
+ # FIXME
65
+ #flash[:notice] = "Resource successfully created! Next, if you want to change this resource's fields, you'll need to add transformations."
66
+
67
+ @resource.save
68
+ redirect "/projects/#{@project.id}/resources/#{@resource.id}"
69
+ else
70
+ @fields = @resource.fields
71
+ @selection_count = @resource.fields_dataset.filter(:is_selected => true).count
72
+ erb 'resources/edit'.to_sym
73
+ end
74
+ end
75
+
76
+ app.get "/projects/:project_id/resources/:id/record/:record_id" do
77
+ @resource = @project.resources_dataset[:id => params[:id]]
78
+ raise ResourceNotFound unless @resource
79
+
80
+ @record = nil
81
+ @resource.final_dataset do |ds|
82
+ @record = ds.filter(@resource.primary_key_sym => params[:record_id]).first
83
+ end
84
+ @record.to_json
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,100 @@
1
+ module Coupler
2
+ module Extensions
3
+ module Results
4
+ module Helpers
5
+ def resource_optgroup_tag(resource_id)
6
+ if resource_id.is_a?(String)
7
+ id, which = resource_id.split(/_/).collect(&:to_i)
8
+ %{<optgroup class="resource-#{id}" label="#{@resources[id].name} [#{which+1}]">}
9
+ else
10
+ %{<optgroup class="resource-#{resource_id}" label="#{@resources[resource_id].name}">}
11
+ end
12
+ end
13
+ end
14
+
15
+ def self.registered(app)
16
+ app.helpers Helpers
17
+
18
+ app.get '/projects/:project_id/scenarios/:scenario_id/results' do
19
+ @scenario = @project.scenarios_dataset[:id => params[:scenario_id]]
20
+ raise ScenarioNotFound unless @scenario
21
+ @results = @scenario.results_dataset.order(:id.desc)
22
+ erb 'results/index'.to_sym
23
+ end
24
+
25
+ app.get '/projects/:project_id/scenarios/:scenario_id/results/:id' do
26
+ @scenario = @project.scenarios_dataset[:id => params[:scenario_id]]
27
+ raise ScenarioNotFound unless @scenario
28
+
29
+ id, format = params[:id].split('.')
30
+ @result = @scenario.results_dataset[:id => id]
31
+ raise ResultNotFound unless @result
32
+
33
+ if format == 'csv'
34
+ filename = "#{@scenario.slug}-run-#{@result.created_at.strftime('%Y%m%d-%H%M')}.csv"
35
+ content_type('text/csv')
36
+ attachment(filename)
37
+ @result.to_csv
38
+ else
39
+ html = nil
40
+ @result.groups_dataset do |groups_dataset|
41
+ html = erb(:"results/show", {}, {:groups_dataset => groups_dataset})
42
+ end
43
+ html
44
+ end
45
+ end
46
+
47
+ app.get '/projects/:project_id/scenarios/:scenario_id/results/:id/details/:group_id' do
48
+ @scenario = @project.scenarios_dataset[:id => params[:scenario_id]]
49
+ raise ScenarioNotFound unless @scenario
50
+ @result = @scenario.results_dataset[:id => params[:id]]
51
+
52
+ @scenario.local_database do |scenario_db|
53
+ groups_ds = scenario_db[@result.groups_table_name]
54
+ @group = groups_ds.filter(:id => params[:group_id]).first
55
+ end
56
+ erb(:"results/details", :layout => false)
57
+ end
58
+
59
+ app.post '/projects/:project_id/scenarios/:scenario_id/results/:id/details/:group_id/record' do
60
+ @scenario = @project.scenarios_dataset[:id => params[:scenario_id]]
61
+ raise ScenarioNotFound unless @scenario
62
+ @result = @scenario.results_dataset[:id => params[:id]]
63
+ @index = params[:index].to_i
64
+ @which = params[:which] ? params[:which].to_i : nil
65
+
66
+ # FIXME: this could be in a model method or stored in the resources table
67
+ @num_columns = @scenario.resources.collect { |r| r.selected_fields_dataset.count }.max
68
+
69
+ # Get total for group
70
+ # FIXME: Result method instead yo
71
+ @result.groups_dataset do |ds|
72
+ @total = ds.filter(:id => params[:group_id]).get(:"resource_#{@which ? @which + 1 : 1}_count")
73
+ end
74
+
75
+ # FIXME: Result method instead yo
76
+ record_id = nil
77
+ @result.groups_records_dataset do |ds|
78
+ record_id = ds.filter(:group_id => params[:group_id], :which => @which).
79
+ limit(1, @index).first[:record_id]
80
+ end
81
+ resource = @which == 1 ? @scenario.resource_2 : @scenario.resource_1
82
+ resource.final_dataset do |ds|
83
+ @columns = ds.columns
84
+ @record = ds.select(*@columns).filter(resource.primary_key_sym => record_id).first
85
+ end
86
+ erb(:"results/record", :layout => false)
87
+ end
88
+
89
+ app.get '/projects/:project_id/scenarios/:scenario_id/results/:id.csv' do
90
+ @scenario = @project.scenarios_dataset[:id => params[:scenario_id]]
91
+ raise ScenarioNotFound unless @scenario
92
+ @result = @scenario.results_dataset[:id => params[:id]]
93
+ raise ResultNotFound unless @result
94
+
95
+ #erb :'results/show', :layout => false
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
@@ -0,0 +1,50 @@
1
+ module Coupler
2
+ module Extensions
3
+ module Scenarios
4
+ def self.registered(app)
5
+ app.get '/projects/:project_id/scenarios' do
6
+ @scenarios = @project.scenarios
7
+ erb :'scenarios/index'
8
+ end
9
+
10
+ app.get '/projects/:project_id/scenarios/new' do
11
+ @scenario = Models::Scenario.new
12
+ erb 'scenarios/new'.to_sym
13
+ end
14
+
15
+ app.post "/projects/:project_id/scenarios" do
16
+ @scenario = Models::Scenario.new(params[:scenario])
17
+ @scenario.project = @project
18
+
19
+ if @scenario.save
20
+ flash[:newly_created] = true
21
+ redirect "/projects/#{@project.id}/scenarios/#{@scenario.id}"
22
+ else
23
+ erb 'scenarios/new'.to_sym
24
+ end
25
+ end
26
+
27
+ app.get '/projects/:project_id/scenarios/:id' do
28
+ @scenario = @project.scenarios_dataset[:id => params[:id]]
29
+ @resources = @scenario.resources
30
+ @matcher = @scenario.matcher
31
+ @results = @scenario.results
32
+ @running_jobs = @scenario.running_jobs
33
+ @scheduled_jobs = @scenario.scheduled_jobs
34
+ erb 'scenarios/show'.to_sym
35
+ end
36
+
37
+ app.get "/projects/:project_id/scenarios/:id/run" do
38
+ @scenario = @project.scenarios_dataset[:id => params[:id]]
39
+ Scheduler.instance.schedule_run_scenario_job(@scenario)
40
+ redirect "/projects/#{@project.id}/scenarios/#{@scenario.id}"
41
+ end
42
+
43
+ #app.get "/projects/:project_id/scenarios/:id/progress" do
44
+ #scenario = Models::Scenario[:id => params[:id], :project_id => params[:project_id]]
45
+ #(scenario[:completed] * 100 / scenario[:total]).to_s
46
+ #end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,70 @@
1
+ module Coupler
2
+ module Extensions
3
+ module Transformations
4
+ def self.registered(app)
5
+ app.get "/projects/:project_id/resources/:resource_id/transformations" do
6
+ @resource = @project.resources_dataset[:id => params[:resource_id]]
7
+ raise ResourceNotFound unless @resource
8
+ @transformations = @resource.transformations
9
+ erb('transformations/index'.to_sym)
10
+ end
11
+
12
+ app.get "/projects/:project_id/resources/:resource_id/transformations/new" do
13
+ @resource = @project.resources_dataset[:id => params[:resource_id]]
14
+ raise ResourceNotFound unless @resource
15
+ @fields = @resource.selected_fields_dataset.order(:id).all
16
+ @transformers = Models::Transformer.all
17
+ @transformation = Models::Transformation.new()
18
+ erb 'transformations/new'.to_sym
19
+ end
20
+
21
+ app.post "/projects/:project_id/resources/:resource_id/transformations" do
22
+ @resource = @project.resources_dataset[:id => params[:resource_id]]
23
+ raise ResourceNotFound unless @resource
24
+ @fields = @resource.selected_fields_dataset.order(:id).all
25
+ @transformation = Models::Transformation.new(params[:transformation])
26
+ @transformation.resource = @resource
27
+
28
+ if @transformation.save
29
+ flash[:notice] = "Transformation was successfully created."
30
+ redirect "/projects/#{@project.id}/resources/#{@resource.id}"
31
+ else
32
+ @transformers = Models::Transformer.all
33
+ @preview = @resource.preview_transformation(@transformation)
34
+ erb :'transformations/create'
35
+ end
36
+ end
37
+
38
+ app.delete "/projects/:project_id/resources/:resource_id/transformations/:id" do
39
+ @resource = @project.resources_dataset[:id => params[:resource_id]]
40
+ raise ResourceNotFound unless @resource
41
+ @transformation = @resource.transformations_dataset[:id => params[:id]]
42
+ raise TransformationNotFound unless @transformation
43
+ @transformation.destroy
44
+ redirect "/projects/#{@project.id}/resources/#{@resource.id}"
45
+ end
46
+
47
+ app.get "/projects/:project_id/resources/:resource_id/transformations/for/:field_name" do
48
+ @resource = @project.resources_dataset[:id => params[:resource_id]]
49
+ raise ResourceNotFound unless @resource
50
+ @field = @resource.fields_dataset[:name => params[:field_name]]
51
+ if @field
52
+ @transformations = @field.transformations
53
+ erb('transformations/for'.to_sym, :layout => false)
54
+ else
55
+ ''
56
+ end
57
+ end
58
+
59
+ app.post "/projects/:project_id/resources/:resource_id/transformations/preview" do
60
+ @resource = @project.resources_dataset[:id => params[:resource_id]]
61
+ raise ResourceNotFound unless @resource
62
+
63
+ @transformation = Models::Transformation.new(params[:transformation])
64
+ @preview = @resource.preview_transformation(@transformation)
65
+ erb(:"transformations/preview", :layout => false)
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,58 @@
1
+ module Coupler
2
+ module Extensions
3
+ module Transformers
4
+ def self.registered(app)
5
+ app.get "/transformers" do
6
+ @transformers = Models::Transformer.all
7
+ erb :'transformers/index'
8
+ end
9
+
10
+ app.post "/transformers/preview" do
11
+ @transformer = Models::Transformer.new(params[:transformer])
12
+ erb(:'transformers/preview', :layout => false)
13
+ end
14
+
15
+ app.get "/transformers/new" do
16
+ @transformer = Models::Transformer.new
17
+ erb :'transformers/new'
18
+ end
19
+
20
+ app.get '/transformers/:id' do
21
+ @transformer = Models::Transformer[:id => params[:id]]
22
+ erb :'transformers/show'
23
+ end
24
+
25
+ app.get "/transformers/:id/edit" do
26
+ @transformer = Models::Transformer[:id => params[:id]]
27
+ erb :'transformers/edit'
28
+ end
29
+
30
+ app.post "/transformers" do
31
+ @transformer = Models::Transformer.new(params[:transformer])
32
+ if @transformer.save
33
+ redirect "/transformers"
34
+ else
35
+ erb :'transformers/new'
36
+ end
37
+ end
38
+
39
+ app.put '/transformers/:id' do
40
+ @transformer = Models::Transformer[:id => params[:id]]
41
+ @transformer.set(params[:transformer])
42
+ if @transformer.valid?
43
+ @transformer.save
44
+ redirect '/transformers'
45
+ else
46
+ erb :'transformers/edit'
47
+ end
48
+ end
49
+
50
+ app.delete '/transformers/:id' do
51
+ @transformer = Models::Transformer[:id => params[:id]]
52
+ @transformer.destroy
53
+ redirect '/transformers'
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,16 @@
1
+ module Coupler
2
+ module Extensions
3
+ end
4
+ end
5
+
6
+ require File.dirname(__FILE__) + "/extensions/connections"
7
+ require File.dirname(__FILE__) + "/extensions/projects"
8
+ require File.dirname(__FILE__) + "/extensions/resources"
9
+ require File.dirname(__FILE__) + "/extensions/transformations"
10
+ require File.dirname(__FILE__) + "/extensions/scenarios"
11
+ require File.dirname(__FILE__) + "/extensions/matchers"
12
+ require File.dirname(__FILE__) + "/extensions/results"
13
+ require File.dirname(__FILE__) + "/extensions/jobs"
14
+ require File.dirname(__FILE__) + "/extensions/transformers"
15
+ require File.dirname(__FILE__) + "/extensions/imports"
16
+ require File.dirname(__FILE__) + "/extensions/exceptions"
@@ -0,0 +1,121 @@
1
+ module Coupler
2
+ module Helpers
3
+ def error_messages_for(object)
4
+ return "" if object.errors.empty?
5
+
6
+ retval = "<div class='errors'><h3>Errors detected:</h3><ul>"
7
+ object.errors.each do |(attr, messages)|
8
+ messages.each do |message|
9
+ retval += "<li>"
10
+ retval += attr.to_s.tr("_", " ").capitalize + " " if attr != :base
11
+ retval += "#{message}</li>"
12
+ end
13
+ end
14
+ retval += "</ul></div><div class='clear'></div>"
15
+
16
+ retval
17
+ end
18
+
19
+ def javascripts
20
+ @javascripts ||= %w{jquery.min.js jquery.timeago.js jquery-ui.min.js application.js}
21
+ end
22
+
23
+ def javascript_includes
24
+ javascripts.collect do |name|
25
+ %{<script type="text/javascript" src="/js/#{name}"></script>}
26
+ end.join("\n ")
27
+ end
28
+
29
+ def add_javascript(*names)
30
+ javascripts.push(*names)
31
+ end
32
+
33
+ def stylesheets
34
+ @stylesheets ||= %w{reset.css text.css 960.css jquery-ui.css jquery.treeview.css style.css}
35
+ end
36
+
37
+ def stylesheet_links
38
+ stylesheets.collect do |name|
39
+ %{<link rel="stylesheet" type="text/css" media="all" href="/css/#{name}" />}
40
+ end.join("\n ")
41
+ end
42
+
43
+ def add_stylesheet(*names)
44
+ stylesheets.push(*names)
45
+ end
46
+
47
+ def delete_link(text, url)
48
+ %^<a href="#{url}" onclick="if (confirm('Are you sure?')) { var f = document.createElement('form'); f.style.display = 'none'; this.parentNode.appendChild(f); f.method = 'POST'; f.action = this.href; var m = document.createElement('input'); m.setAttribute('type', 'hidden'); m.setAttribute('name', '_method'); m.setAttribute('value', 'delete'); f.appendChild(m); f.submit(); }; return false;">#{text}</a>^
49
+ end
50
+
51
+ def breadcrumbs
52
+ # This method is fun but silly.
53
+ if @breadcrumbs
54
+ url = ""
55
+ %{<div id="breadcrumbs">} +
56
+ @breadcrumbs.inject([]) do |arr, obj|
57
+ strings =
58
+ case obj
59
+ when String
60
+ [obj]
61
+ when nil
62
+ []
63
+ else
64
+ class_name = obj.class.to_s.split("::")[-1]
65
+ if obj.new?
66
+ ["New #{class_name}"]
67
+ elsif
68
+ url += "/#{class_name.downcase}s/#{obj.id}"
69
+ if obj.respond_to?(:name)
70
+ ["#{class_name}s", %{<a href="#{url}">#{obj.name}</a>}]
71
+ else
72
+ [%{<a href="#{url}">#{class_name} ##{obj.id}</a>}]
73
+ end
74
+ end
75
+ end
76
+ arr.push(*strings.collect { |x| %{<div class="crumb">#{x}</div>} })
77
+ end.join(%{<div class="crumb">/</div>}) +
78
+ %{</div><div class="clear"></div>}
79
+ end
80
+ end
81
+
82
+ def humanize(string)
83
+ string.to_s.gsub(/_+/, " ").capitalize
84
+ end
85
+
86
+ def timeago(time, klass = nil, tag = "div")
87
+ if time.nil?
88
+ "Never"
89
+ else
90
+ dt = time.send(:to_datetime)
91
+ klass = "timeago" + (klass.nil? ? "" : " #{klass}")
92
+ %{<#{tag} class="#{klass}" title="#{dt.to_s}">#{time.to_s}</#{tag}>}
93
+ end
94
+ end
95
+
96
+ def form_tag_for(obj, options)
97
+ base_url = options[:base_url]
98
+ action, method = if obj.new?
99
+ [base_url, ""]
100
+ else
101
+ ["#{base_url}/#{obj.id}", %{<div style="display: none;"><input type="hidden" name="_method" value="put" /></div>}]
102
+ end
103
+ %{<form action="#{action}" method="post">#{method}}
104
+ end
105
+
106
+ def local_ip
107
+ orig, Socket.do_not_reverse_lookup = Socket.do_not_reverse_lookup, true # turn off reverse DNS resolution temporarily
108
+
109
+ UDPSocket.open do |s|
110
+ s.connect '64.233.187.99', 1
111
+ s.addr.last
112
+ end
113
+ ensure
114
+ Socket.do_not_reverse_lookup = orig
115
+ end
116
+
117
+ def cycle(even, odd)
118
+ (@_cycle = !@_cycle) ? even : odd
119
+ end
120
+ end
121
+ end