coupler 0.0.1-java
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.gitmodules +3 -0
- data/.rvmrc +1 -0
- data/.vimrc +40 -0
- data/Gemfile +27 -0
- data/Gemfile.lock +71 -0
- data/LICENSE +20 -0
- data/NOTES +6 -0
- data/README.rdoc +18 -0
- data/Rakefile +42 -0
- data/TODO +11 -0
- data/VERSION +1 -0
- data/bin/coupler +7 -0
- data/db/.gitignore +6 -0
- data/db/migrate/001_initial_schema.rb +166 -0
- data/db/migrate/002_stub.rb +4 -0
- data/db/migrate/003_stub.rb +4 -0
- data/db/migrate/004_create_comparisons.rb +28 -0
- data/db/migrate/005_move_database_name.rb +19 -0
- data/db/migrate/006_upgrade_comparisons.rb +34 -0
- data/db/migrate/007_add_which_to_comparisons.rb +23 -0
- data/db/migrate/008_add_result_field_to_transformations.rb +33 -0
- data/db/migrate/009_add_generated_flag_to_fields.rb +13 -0
- data/db/migrate/010_create_imports.rb +24 -0
- data/db/migrate/011_add_primary_key_type.rb +13 -0
- data/db/migrate/012_add_transformed_with_to_resources.rb +13 -0
- data/db/migrate/013_add_run_count_to_scenarios.rb +13 -0
- data/db/migrate/014_add_last_accessed_at_to_some_tables.rb +13 -0
- data/db/migrate/015_add_run_number_to_results.rb +15 -0
- data/db/migrate/016_fix_scenario_run_count.rb +27 -0
- data/db/migrate/017_rename_comparison_columns.rb +14 -0
- data/db/migrate/018_fix_scenario_linkage_type.rb +8 -0
- data/db/migrate/019_add_columns_to_imports.rb +24 -0
- data/db/migrate/020_rename_import_columns.rb +12 -0
- data/db/migrate/021_add_fields_to_connections.rb +15 -0
- data/db/migrate/022_remove_database_name_from_resources.rb +11 -0
- data/features/connections.feature +28 -0
- data/features/matchers.feature +35 -0
- data/features/projects.feature +11 -0
- data/features/resources.feature +62 -0
- data/features/scenarios.feature +45 -0
- data/features/step_definitions/coupler_steps.rb +145 -0
- data/features/step_definitions/matchers_steps.rb +26 -0
- data/features/step_definitions/resources_steps.rb +12 -0
- data/features/step_definitions/scenarios_steps.rb +7 -0
- data/features/step_definitions/transformations_steps.rb +3 -0
- data/features/support/env.rb +128 -0
- data/features/transformations.feature +22 -0
- data/features/wizard.feature +10 -0
- data/gfx/coupler-header.svg +213 -0
- data/gfx/coupler-sidebar.svg +656 -0
- data/gfx/coupler.svg +184 -0
- data/gfx/icon.svg +75 -0
- data/lib/coupler/base.rb +63 -0
- data/lib/coupler/config.rb +128 -0
- data/lib/coupler/data_uploader.rb +20 -0
- data/lib/coupler/database.rb +31 -0
- data/lib/coupler/extensions/connections.rb +57 -0
- data/lib/coupler/extensions/exceptions.rb +58 -0
- data/lib/coupler/extensions/imports.rb +43 -0
- data/lib/coupler/extensions/jobs.rb +21 -0
- data/lib/coupler/extensions/matchers.rb +64 -0
- data/lib/coupler/extensions/projects.rb +62 -0
- data/lib/coupler/extensions/resources.rb +89 -0
- data/lib/coupler/extensions/results.rb +100 -0
- data/lib/coupler/extensions/scenarios.rb +50 -0
- data/lib/coupler/extensions/transformations.rb +70 -0
- data/lib/coupler/extensions/transformers.rb +58 -0
- data/lib/coupler/extensions.rb +16 -0
- data/lib/coupler/helpers.rb +121 -0
- data/lib/coupler/import_buffer.rb +48 -0
- data/lib/coupler/logger.rb +16 -0
- data/lib/coupler/models/common_model.rb +104 -0
- data/lib/coupler/models/comparison.rb +166 -0
- data/lib/coupler/models/connection.rb +59 -0
- data/lib/coupler/models/field.rb +55 -0
- data/lib/coupler/models/import.rb +238 -0
- data/lib/coupler/models/job.rb +42 -0
- data/lib/coupler/models/jobify.rb +17 -0
- data/lib/coupler/models/matcher.rb +36 -0
- data/lib/coupler/models/project.rb +40 -0
- data/lib/coupler/models/resource.rb +287 -0
- data/lib/coupler/models/result.rb +92 -0
- data/lib/coupler/models/scenario/runner.rb +357 -0
- data/lib/coupler/models/scenario.rb +115 -0
- data/lib/coupler/models/transformation.rb +117 -0
- data/lib/coupler/models/transformer/runner.rb +28 -0
- data/lib/coupler/models/transformer.rb +110 -0
- data/lib/coupler/models.rb +30 -0
- data/lib/coupler/runner.rb +76 -0
- data/lib/coupler/scheduler.rb +56 -0
- data/lib/coupler.rb +34 -0
- data/log/.gitignore +1 -0
- data/misc/README +5 -0
- data/misc/jruby-json.license +57 -0
- data/misc/rack-flash.license +22 -0
- data/script/dbconsole.rb +5 -0
- data/src/edu/vanderbilt/coupler/Main.java +116 -0
- data/src/edu/vanderbilt/coupler/jruby.properties +1 -0
- data/tasks/annotations.rake +84 -0
- data/tasks/db.rake +120 -0
- data/tasks/environment.rake +12 -0
- data/tasks/jeweler.rake +43 -0
- data/tasks/package.rake +58 -0
- data/tasks/rdoc.rake +13 -0
- data/tasks/test.rake +63 -0
- data/tasks/vendor.rake +43 -0
- data/test/README.txt +6 -0
- data/test/config.yml +9 -0
- data/test/coupler/models/test_import.rb +221 -0
- data/test/factories.rb +91 -0
- data/test/fixtures/duplicate-keys.csv +5 -0
- data/test/fixtures/no-headers.csv +50 -0
- data/test/fixtures/people.csv +51 -0
- data/test/fixtures/varying-row-size.csv +4 -0
- data/test/helper.rb +156 -0
- data/test/integration/extensions/test_connections.rb +80 -0
- data/test/integration/extensions/test_imports.rb +94 -0
- data/test/integration/extensions/test_jobs.rb +52 -0
- data/test/integration/extensions/test_matchers.rb +134 -0
- data/test/integration/extensions/test_projects.rb +82 -0
- data/test/integration/extensions/test_resources.rb +150 -0
- data/test/integration/extensions/test_results.rb +89 -0
- data/test/integration/extensions/test_scenarios.rb +88 -0
- data/test/integration/extensions/test_transformations.rb +113 -0
- data/test/integration/extensions/test_transformers.rb +80 -0
- data/test/integration/test_field.rb +45 -0
- data/test/integration/test_import.rb +78 -0
- data/test/integration/test_running_scenarios.rb +379 -0
- data/test/integration/test_transformation.rb +56 -0
- data/test/integration/test_transforming.rb +154 -0
- data/test/table_sets.rb +76 -0
- data/test/unit/models/test_common_model.rb +130 -0
- data/test/unit/models/test_comparison.rb +619 -0
- data/test/unit/models/test_connection.rb +115 -0
- data/test/unit/models/test_field.rb +99 -0
- data/test/unit/models/test_import.rb +130 -0
- data/test/unit/models/test_job.rb +115 -0
- data/test/unit/models/test_matcher.rb +82 -0
- data/test/unit/models/test_project.rb +102 -0
- data/test/unit/models/test_resource.rb +564 -0
- data/test/unit/models/test_result.rb +90 -0
- data/test/unit/models/test_scenario.rb +199 -0
- data/test/unit/models/test_transformation.rb +193 -0
- data/test/unit/models/test_transformer.rb +188 -0
- data/test/unit/test_base.rb +60 -0
- data/test/unit/test_data_uploader.rb +27 -0
- data/test/unit/test_database.rb +23 -0
- data/test/unit/test_helpers.rb +58 -0
- data/test/unit/test_logger.rb +10 -0
- data/test/unit/test_models.rb +12 -0
- data/test/unit/test_runner.rb +76 -0
- data/test/unit/test_scheduler.rb +66 -0
- data/uploads/.gitignore +2 -0
- data/vendor/java/.gitignore +5 -0
- data/webroot/public/css/960.css +1 -0
- data/webroot/public/css/dataTables.css +1057 -0
- data/webroot/public/css/jquery-ui.css +572 -0
- data/webroot/public/css/jquery.treeview.css +68 -0
- data/webroot/public/css/reset.css +1 -0
- data/webroot/public/css/style.css +504 -0
- data/webroot/public/css/text.css +1 -0
- data/webroot/public/favicon.ico +0 -0
- data/webroot/public/images/12_col.gif +0 -0
- data/webroot/public/images/16_col.gif +0 -0
- data/webroot/public/images/add.png +0 -0
- data/webroot/public/images/ajax-loader.gif +0 -0
- data/webroot/public/images/cog.png +0 -0
- data/webroot/public/images/coupler.png +0 -0
- data/webroot/public/images/foo.png +0 -0
- data/webroot/public/images/hammer.png +0 -0
- data/webroot/public/images/header.png +0 -0
- data/webroot/public/images/home.gif +0 -0
- data/webroot/public/images/jobs.gif +0 -0
- data/webroot/public/images/sidebar-bottom.png +0 -0
- data/webroot/public/images/sidebar.png +0 -0
- data/webroot/public/images/treeview-default-line.gif +0 -0
- data/webroot/public/images/treeview-default.gif +0 -0
- data/webroot/public/images/ui-anim_basic_16x16.gif +0 -0
- data/webroot/public/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
- data/webroot/public/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
- data/webroot/public/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
- data/webroot/public/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/webroot/public/images/ui-bg_glass_75_dadada_1x400.png +0 -0
- data/webroot/public/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
- data/webroot/public/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
- data/webroot/public/images/ui-bg_highlight-hard_30_565356_1x100.png +0 -0
- data/webroot/public/images/ui-bg_highlight-hard_75_888588_1x100.png +0 -0
- data/webroot/public/images/ui-bg_highlight-soft_30_6e3b3a_1x100.png +0 -0
- data/webroot/public/images/ui-bg_highlight-soft_35_8e8b8e_1x100.png +0 -0
- data/webroot/public/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
- data/webroot/public/images/ui-icons_222222_256x240.png +0 -0
- data/webroot/public/images/ui-icons_2e83ff_256x240.png +0 -0
- data/webroot/public/images/ui-icons_454545_256x240.png +0 -0
- data/webroot/public/images/ui-icons_888888_256x240.png +0 -0
- data/webroot/public/images/ui-icons_cd0a0a_256x240.png +0 -0
- data/webroot/public/images/ui-icons_ffffff_256x240.png +0 -0
- data/webroot/public/js/ajaxupload.js +673 -0
- data/webroot/public/js/application.js +40 -0
- data/webroot/public/js/jquery-ui.combobox.js +98 -0
- data/webroot/public/js/jquery-ui.js +9867 -0
- data/webroot/public/js/jquery-ui.min.js +559 -0
- data/webroot/public/js/jquery.dataTables.min.js +587 -0
- data/webroot/public/js/jquery.min.js +154 -0
- data/webroot/public/js/jquery.timeago.js +140 -0
- data/webroot/public/js/jquery.tooltip.min.js +19 -0
- data/webroot/public/js/jquery.treeview.min.js +15 -0
- data/webroot/public/js/resource.js +11 -0
- data/webroot/public/js/results.js +56 -0
- data/webroot/public/js/transformations.js +95 -0
- data/webroot/views/connections/index.erb +5 -0
- data/webroot/views/connections/list.erb +34 -0
- data/webroot/views/connections/new.erb +55 -0
- data/webroot/views/connections/show.erb +36 -0
- data/webroot/views/imports/edit.erb +60 -0
- data/webroot/views/imports/form.erb +81 -0
- data/webroot/views/imports/new.erb +89 -0
- data/webroot/views/index.erb +12 -0
- data/webroot/views/jobs/index.erb +7 -0
- data/webroot/views/jobs/list.erb +24 -0
- data/webroot/views/layout.erb +38 -0
- data/webroot/views/matchers/form.erb +250 -0
- data/webroot/views/matchers/list.erb +32 -0
- data/webroot/views/projects/form.erb +14 -0
- data/webroot/views/projects/index.erb +96 -0
- data/webroot/views/projects/show.erb +24 -0
- data/webroot/views/resources/edit.erb +88 -0
- data/webroot/views/resources/index.erb +5 -0
- data/webroot/views/resources/list.erb +27 -0
- data/webroot/views/resources/new.erb +121 -0
- data/webroot/views/resources/show.erb +86 -0
- data/webroot/views/resources/transform.erb +2 -0
- data/webroot/views/results/csv.erb +12 -0
- data/webroot/views/results/details.erb +15 -0
- data/webroot/views/results/index.erb +2 -0
- data/webroot/views/results/list.erb +22 -0
- data/webroot/views/results/record.erb +24 -0
- data/webroot/views/results/show.erb +68 -0
- data/webroot/views/scenarios/index.erb +5 -0
- data/webroot/views/scenarios/list.erb +20 -0
- data/webroot/views/scenarios/new.erb +99 -0
- data/webroot/views/scenarios/run.erb +2 -0
- data/webroot/views/scenarios/show.erb +50 -0
- data/webroot/views/sidebar.erb +106 -0
- data/webroot/views/transformations/create.erb +115 -0
- data/webroot/views/transformations/for.erb +16 -0
- data/webroot/views/transformations/index.erb +2 -0
- data/webroot/views/transformations/list.erb +29 -0
- data/webroot/views/transformations/new.erb +126 -0
- data/webroot/views/transformations/preview.erb +46 -0
- data/webroot/views/transformers/edit.erb +6 -0
- data/webroot/views/transformers/form.erb +58 -0
- data/webroot/views/transformers/index.erb +2 -0
- data/webroot/views/transformers/list.erb +25 -0
- data/webroot/views/transformers/new.erb +5 -0
- data/webroot/views/transformers/preview.erb +23 -0
- data/webroot/views/transformers/show.erb +0 -0
- 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
|