marty 0.5.12
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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +84 -0
- data/Rakefile +29 -0
- data/app/assets/javascripts/marty/application.js +15 -0
- data/app/assets/stylesheets/marty/application.css +13 -0
- data/app/components/marty/api_auth_view.rb +32 -0
- data/app/components/marty/auth_app.rb +55 -0
- data/app/components/marty/auth_app.rb~ +51 -0
- data/app/components/marty/auth_app/javascripts/auth_app.js +91 -0
- data/app/components/marty/auth_app/javascripts/auth_app.js~ +91 -0
- data/app/components/marty/cm_form_panel.rb~ +5 -0
- data/app/components/marty/cm_grid_panel.rb~ +35 -0
- data/app/components/marty/data_import_view.rb~ +142 -0
- data/app/components/marty/extras/layout.rb +46 -0
- data/app/components/marty/extras/layout.rb~ +46 -0
- data/app/components/marty/extras/misc.rb +18 -0
- data/app/components/marty/form.rb +6 -0
- data/app/components/marty/grid.rb +45 -0
- data/app/components/marty/grid_append_only.rb +12 -0
- data/app/components/marty/import_type_view.rb +53 -0
- data/app/components/marty/live_search_grid_panel.rb +46 -0
- data/app/components/marty/live_search_grid_panel.rb~ +49 -0
- data/app/components/marty/main_auth_app.rb +269 -0
- data/app/components/marty/main_auth_app.rb~ +238 -0
- data/app/components/marty/mcfly_grid_panel.rb +62 -0
- data/app/components/marty/mcfly_grid_panel.rb~ +80 -0
- data/app/components/marty/new_posting_form.rb +46 -0
- data/app/components/marty/new_posting_form.rb~ +46 -0
- data/app/components/marty/new_posting_window.rb +21 -0
- data/app/components/marty/new_posting_window.rb~ +21 -0
- data/app/components/marty/panel.rb +12 -0
- data/app/components/marty/pivot_grid.rb +52 -0
- data/app/components/marty/pivot_grid/endpoints.rb +45 -0
- data/app/components/marty/pivot_grid/javascripts/extensions.js +150 -0
- data/app/components/marty/pivot_grid/javascripts/pivot_grid.js +86 -0
- data/app/components/marty/pivot_grid/services.rb +44 -0
- data/app/components/marty/posting_grid.rb +139 -0
- data/app/components/marty/posting_grid.rb~ +140 -0
- data/app/components/marty/posting_window.rb +27 -0
- data/app/components/marty/promise_view.rb +177 -0
- data/app/components/marty/promise_view.rb~ +157 -0
- data/app/components/marty/promise_view/stylesheets/promise_view.css +26 -0
- data/app/components/marty/promise_view/stylesheets/promise_view.css~ +15 -0
- data/app/components/marty/report_form.rb +225 -0
- data/app/components/marty/report_form.rb~ +217 -0
- data/app/components/marty/report_select.rb +145 -0
- data/app/components/marty/report_select.rb~ +133 -0
- data/app/components/marty/reporting.rb +39 -0
- data/app/components/marty/reporting.rb~ +39 -0
- data/app/components/marty/script_detail.rb~ +430 -0
- data/app/components/marty/script_form.rb +233 -0
- data/app/components/marty/script_form.rb~ +233 -0
- data/app/components/marty/script_form/javascripts/Ext.ux.form.field.CodeMirror.js +698 -0
- data/app/components/marty/script_form/javascripts/Ext.ux.form.field.CodeMirror.js~ +909 -0
- data/app/components/marty/script_form/javascripts/codemirror.js +3130 -0
- data/app/components/marty/script_form/javascripts/mode/clike/clike.js +284 -0
- data/app/components/marty/script_form/javascripts/mode/clike/index.html +102 -0
- data/app/components/marty/script_form/javascripts/mode/clike/scala.html +766 -0
- data/app/components/marty/script_form/javascripts/mode/clojure/clojure.js +206 -0
- data/app/components/marty/script_form/javascripts/mode/clojure/index.html +67 -0
- data/app/components/marty/script_form/javascripts/mode/coffeescript/LICENSE +22 -0
- data/app/components/marty/script_form/javascripts/mode/coffeescript/coffeescript.js +346 -0
- data/app/components/marty/script_form/javascripts/mode/coffeescript/index.html +728 -0
- data/app/components/marty/script_form/javascripts/mode/commonlisp/commonlisp.js +101 -0
- data/app/components/marty/script_form/javascripts/mode/commonlisp/index.html +165 -0
- data/app/components/marty/script_form/javascripts/mode/css/css.js +448 -0
- data/app/components/marty/script_form/javascripts/mode/css/index.html +58 -0
- data/app/components/marty/script_form/javascripts/mode/css/test.js +501 -0
- data/app/components/marty/script_form/javascripts/mode/delorean/delorean.js +189 -0
- data/app/components/marty/script_form/javascripts/mode/diff/diff.js +32 -0
- data/app/components/marty/script_form/javascripts/mode/diff/index.html +105 -0
- data/app/components/marty/script_form/javascripts/mode/ecl/ecl.js +203 -0
- data/app/components/marty/script_form/javascripts/mode/ecl/index.html +42 -0
- data/app/components/marty/script_form/javascripts/mode/erlang/erlang.js +463 -0
- data/app/components/marty/script_form/javascripts/mode/erlang/index.html +63 -0
- data/app/components/marty/script_form/javascripts/mode/gfm/gfm.js +150 -0
- data/app/components/marty/script_form/javascripts/mode/gfm/index.html +48 -0
- data/app/components/marty/script_form/javascripts/mode/go/go.js +170 -0
- data/app/components/marty/script_form/javascripts/mode/go/index.html +73 -0
- data/app/components/marty/script_form/javascripts/mode/groovy/groovy.js +210 -0
- data/app/components/marty/script_form/javascripts/mode/groovy/index.html +72 -0
- data/app/components/marty/script_form/javascripts/mode/haskell/haskell.js +242 -0
- data/app/components/marty/script_form/javascripts/mode/haskell/index.html +61 -0
- data/app/components/marty/script_form/javascripts/mode/haxe/haxe.js +429 -0
- data/app/components/marty/script_form/javascripts/mode/haxe/index.html +91 -0
- data/app/components/marty/script_form/javascripts/mode/htmlembedded/htmlembedded.js +72 -0
- data/app/components/marty/script_form/javascripts/mode/htmlembedded/index.html +50 -0
- data/app/components/marty/script_form/javascripts/mode/htmlmixed/htmlmixed.js +84 -0
- data/app/components/marty/script_form/javascripts/mode/htmlmixed/index.html +52 -0
- data/app/components/marty/script_form/javascripts/mode/javascript/index.html +78 -0
- data/app/components/marty/script_form/javascripts/mode/javascript/javascript.js +361 -0
- data/app/components/marty/script_form/javascripts/mode/jinja2/index.html +38 -0
- data/app/components/marty/script_form/javascripts/mode/jinja2/jinja2.js +42 -0
- data/app/components/marty/script_form/javascripts/mode/less/index.html +740 -0
- data/app/components/marty/script_form/javascripts/mode/less/less.js +266 -0
- data/app/components/marty/script_form/javascripts/mode/lua/index.html +73 -0
- data/app/components/marty/script_form/javascripts/mode/lua/lua.js +140 -0
- data/app/components/marty/script_form/javascripts/mode/markdown/index.html +343 -0
- data/app/components/marty/script_form/javascripts/mode/markdown/markdown.js +382 -0
- data/app/components/marty/script_form/javascripts/mode/markdown/test.js +1084 -0
- data/app/components/marty/script_form/javascripts/mode/mysql/index.html +42 -0
- data/app/components/marty/script_form/javascripts/mode/mysql/mysql.js +186 -0
- data/app/components/marty/script_form/javascripts/mode/ntriples/index.html +33 -0
- data/app/components/marty/script_form/javascripts/mode/ntriples/ntriples.js +172 -0
- data/app/components/marty/script_form/javascripts/mode/ocaml/index.html +130 -0
- data/app/components/marty/script_form/javascripts/mode/ocaml/ocaml.js +114 -0
- data/app/components/marty/script_form/javascripts/mode/pascal/LICENSE +7 -0
- data/app/components/marty/script_form/javascripts/mode/pascal/index.html +49 -0
- data/app/components/marty/script_form/javascripts/mode/pascal/pascal.js +94 -0
- data/app/components/marty/script_form/javascripts/mode/perl/LICENSE +19 -0
- data/app/components/marty/script_form/javascripts/mode/perl/index.html +63 -0
- data/app/components/marty/script_form/javascripts/mode/perl/perl.js +816 -0
- data/app/components/marty/script_form/javascripts/mode/php/index.html +49 -0
- data/app/components/marty/script_form/javascripts/mode/php/php.js +148 -0
- data/app/components/marty/script_form/javascripts/mode/pig/index.html +43 -0
- data/app/components/marty/script_form/javascripts/mode/pig/pig.js +172 -0
- data/app/components/marty/script_form/javascripts/mode/plsql/index.html +63 -0
- data/app/components/marty/script_form/javascripts/mode/plsql/plsql.js +217 -0
- data/app/components/marty/script_form/javascripts/mode/properties/index.html +41 -0
- data/app/components/marty/script_form/javascripts/mode/properties/properties.js +63 -0
- data/app/components/marty/script_form/javascripts/mode/python/LICENSE.txt +21 -0
- data/app/components/marty/script_form/javascripts/mode/python/index.html +123 -0
- data/app/components/marty/script_form/javascripts/mode/python/python.js +338 -0
- data/app/components/marty/script_form/javascripts/mode/r/LICENSE +24 -0
- data/app/components/marty/script_form/javascripts/mode/r/index.html +74 -0
- data/app/components/marty/script_form/javascripts/mode/r/r.js +141 -0
- data/app/components/marty/script_form/javascripts/mode/rpm/changes/changes.js +19 -0
- data/app/components/marty/script_form/javascripts/mode/rpm/changes/index.html +54 -0
- data/app/components/marty/script_form/javascripts/mode/rpm/spec/index.html +100 -0
- data/app/components/marty/script_form/javascripts/mode/rpm/spec/spec.css +5 -0
- data/app/components/marty/script_form/javascripts/mode/rpm/spec/spec.js +66 -0
- data/app/components/marty/script_form/javascripts/mode/rst/index.html +526 -0
- data/app/components/marty/script_form/javascripts/mode/rst/rst.js +326 -0
- data/app/components/marty/script_form/javascripts/mode/ruby/LICENSE +24 -0
- data/app/components/marty/script_form/javascripts/mode/ruby/index.html +172 -0
- data/app/components/marty/script_form/javascripts/mode/ruby/ruby.js +195 -0
- data/app/components/marty/script_form/javascripts/mode/rust/index.html +49 -0
- data/app/components/marty/script_form/javascripts/mode/rust/rust.js +432 -0
- data/app/components/marty/script_form/javascripts/mode/scheme/index.html +65 -0
- data/app/components/marty/script_form/javascripts/mode/scheme/scheme.js +230 -0
- data/app/components/marty/script_form/javascripts/mode/shell/index.html +50 -0
- data/app/components/marty/script_form/javascripts/mode/shell/shell.js +118 -0
- data/app/components/marty/script_form/javascripts/mode/sieve/LICENSE +23 -0
- data/app/components/marty/script_form/javascripts/mode/sieve/index.html +81 -0
- data/app/components/marty/script_form/javascripts/mode/sieve/sieve.js +156 -0
- data/app/components/marty/script_form/javascripts/mode/smalltalk/index.html +56 -0
- data/app/components/marty/script_form/javascripts/mode/smalltalk/smalltalk.js +139 -0
- data/app/components/marty/script_form/javascripts/mode/smarty/index.html +83 -0
- data/app/components/marty/script_form/javascripts/mode/smarty/smarty.js +148 -0
- data/app/components/marty/script_form/javascripts/mode/sparql/index.html +41 -0
- data/app/components/marty/script_form/javascripts/mode/sparql/sparql.js +143 -0
- data/app/components/marty/script_form/javascripts/mode/stex/index.html +98 -0
- data/app/components/marty/script_form/javascripts/mode/stex/stex.js +182 -0
- data/app/components/marty/script_form/javascripts/mode/stex/test.js +343 -0
- data/app/components/marty/script_form/javascripts/mode/tiddlywiki/index.html +141 -0
- data/app/components/marty/script_form/javascripts/mode/tiddlywiki/tiddlywiki.css +14 -0
- data/app/components/marty/script_form/javascripts/mode/tiddlywiki/tiddlywiki.js +384 -0
- data/app/components/marty/script_form/javascripts/mode/tiki/index.html +83 -0
- data/app/components/marty/script_form/javascripts/mode/tiki/tiki.css +26 -0
- data/app/components/marty/script_form/javascripts/mode/tiki/tiki.js +309 -0
- data/app/components/marty/script_form/javascripts/mode/vb/LICENSE.txt +21 -0
- data/app/components/marty/script_form/javascripts/mode/vb/index.html +89 -0
- data/app/components/marty/script_form/javascripts/mode/vb/vb.js +260 -0
- data/app/components/marty/script_form/javascripts/mode/vbscript/index.html +43 -0
- data/app/components/marty/script_form/javascripts/mode/vbscript/vbscript.js +26 -0
- data/app/components/marty/script_form/javascripts/mode/velocity/index.html +104 -0
- data/app/components/marty/script_form/javascripts/mode/velocity/velocity.js +146 -0
- data/app/components/marty/script_form/javascripts/mode/verilog/index.html +211 -0
- data/app/components/marty/script_form/javascripts/mode/verilog/verilog.js +194 -0
- data/app/components/marty/script_form/javascripts/mode/xml/index.html +45 -0
- data/app/components/marty/script_form/javascripts/mode/xml/xml.js +318 -0
- data/app/components/marty/script_form/javascripts/mode/xquery/LICENSE +20 -0
- data/app/components/marty/script_form/javascripts/mode/xquery/index.html +223 -0
- data/app/components/marty/script_form/javascripts/mode/xquery/test/index.html +27 -0
- data/app/components/marty/script_form/javascripts/mode/xquery/test/testBase.js +42 -0
- data/app/components/marty/script_form/javascripts/mode/xquery/test/testEmptySequenceKeyword.js +16 -0
- data/app/components/marty/script_form/javascripts/mode/xquery/test/testMultiAttr.js +16 -0
- data/app/components/marty/script_form/javascripts/mode/xquery/test/testNamespaces.js +91 -0
- data/app/components/marty/script_form/javascripts/mode/xquery/test/testProcessingInstructions.js +16 -0
- data/app/components/marty/script_form/javascripts/mode/xquery/test/testQuotes.js +19 -0
- data/app/components/marty/script_form/javascripts/mode/xquery/xquery.js +451 -0
- data/app/components/marty/script_form/javascripts/mode/yaml/index.html +68 -0
- data/app/components/marty/script_form/javascripts/mode/yaml/yaml.js +95 -0
- data/app/components/marty/script_form/javascripts/util/closetag.js +164 -0
- data/app/components/marty/script_form/javascripts/util/dialog.css +27 -0
- data/app/components/marty/script_form/javascripts/util/dialog.js +70 -0
- data/app/components/marty/script_form/javascripts/util/foldcode.js +196 -0
- data/app/components/marty/script_form/javascripts/util/formatting.js +193 -0
- data/app/components/marty/script_form/javascripts/util/javascript-hint.js +134 -0
- data/app/components/marty/script_form/javascripts/util/loadmode.js +51 -0
- data/app/components/marty/script_form/javascripts/util/match-highlighter.js +44 -0
- data/app/components/marty/script_form/javascripts/util/multiplex.js +77 -0
- data/app/components/marty/script_form/javascripts/util/overlay.js +54 -0
- data/app/components/marty/script_form/javascripts/util/pig-hint.js +123 -0
- data/app/components/marty/script_form/javascripts/util/runmode-standalone.js +90 -0
- data/app/components/marty/script_form/javascripts/util/runmode.js +53 -0
- data/app/components/marty/script_form/javascripts/util/search.js +118 -0
- data/app/components/marty/script_form/javascripts/util/searchcursor.js +119 -0
- data/app/components/marty/script_form/javascripts/util/simple-hint.css +16 -0
- data/app/components/marty/script_form/javascripts/util/simple-hint.js +97 -0
- data/app/components/marty/script_form/javascripts/util/xml-hint.js +137 -0
- data/app/components/marty/script_form/stylesheets/codemirror.css +172 -0
- data/app/components/marty/script_form/stylesheets/delorean.css +10 -0
- data/app/components/marty/script_form/stylesheets/theme/ambiance.css +81 -0
- data/app/components/marty/script_form/stylesheets/theme/blackboard.css +25 -0
- data/app/components/marty/script_form/stylesheets/theme/cobalt.css +18 -0
- data/app/components/marty/script_form/stylesheets/theme/eclipse.css +25 -0
- data/app/components/marty/script_form/stylesheets/theme/elegant.css +10 -0
- data/app/components/marty/script_form/stylesheets/theme/erlang-dark.css +21 -0
- data/app/components/marty/script_form/stylesheets/theme/lesser-dark.css +44 -0
- data/app/components/marty/script_form/stylesheets/theme/monokai.css +28 -0
- data/app/components/marty/script_form/stylesheets/theme/neat.css +9 -0
- data/app/components/marty/script_form/stylesheets/theme/night.css +21 -0
- data/app/components/marty/script_form/stylesheets/theme/rubyblue.css +21 -0
- data/app/components/marty/script_form/stylesheets/theme/vibrant-ink.css +27 -0
- data/app/components/marty/script_form/stylesheets/theme/xq-dark.css +46 -0
- data/app/components/marty/script_grid.rb +104 -0
- data/app/components/marty/script_grid.rb~ +99 -0
- data/app/components/marty/script_tester.rb +114 -0
- data/app/components/marty/script_tester.rb~ +213 -0
- data/app/components/marty/scripting.rb +132 -0
- data/app/components/marty/scripting.rb~ +124 -0
- data/app/components/marty/select_report.rb~ +143 -0
- data/app/components/marty/simple_app.rb +97 -0
- data/app/components/marty/simple_app.rb~ +101 -0
- data/app/components/marty/simple_app/javascripts/simple_app.js +50 -0
- data/app/components/marty/simple_app/javascripts/statusbar_ext.js +8 -0
- data/app/components/marty/tag_grid.rb +83 -0
- data/app/components/marty/tag_grid.rb~ +89 -0
- data/app/components/marty/tree_panel.rb~ +256 -0
- data/app/components/marty/tree_panel/javascripts/tree_panel.js~ +317 -0
- data/app/components/marty/user_pivot.rb +128 -0
- data/app/components/marty/user_view.rb +181 -0
- data/app/components/marty/user_view.rb~ +188 -0
- data/app/controllers/marty/application_controller.rb +124 -0
- data/app/controllers/marty/application_controller.rb~ +133 -0
- data/app/controllers/marty/components_controller.rb +41 -0
- data/app/controllers/marty/components_controller.rb~ +37 -0
- data/app/controllers/marty/job_controller.rb +28 -0
- data/app/controllers/marty/job_controller.rb~ +28 -0
- data/app/controllers/marty/rpc_controller.rb +64 -0
- data/app/controllers/marty/rpc_controller.rb~ +61 -0
- data/app/helpers/marty/application_helper.rb +4 -0
- data/app/helpers/marty/script_set.rb +57 -0
- data/app/helpers/marty/script_set.rb~ +59 -0
- data/app/models/marty/api_auth.rb +44 -0
- data/app/models/marty/api_auth.rb~ +48 -0
- data/app/models/marty/base.rb +4 -0
- data/app/models/marty/data_change.rb +179 -0
- data/app/models/marty/data_change.rb~ +141 -0
- data/app/models/marty/enum.rb +22 -0
- data/app/models/marty/enum.rb~ +16 -0
- data/app/models/marty/import_type.rb +44 -0
- data/app/models/marty/import_type.rb~ +48 -0
- data/app/models/marty/poop.rb~ +169 -0
- data/app/models/marty/posting.rb +101 -0
- data/app/models/marty/posting.rb~ +86 -0
- data/app/models/marty/posting_type.rb +12 -0
- data/app/models/marty/posting_type.rb~ +21 -0
- data/app/models/marty/promise.rb +252 -0
- data/app/models/marty/promise.rb~ +196 -0
- data/app/models/marty/role.rb +6 -0
- data/app/models/marty/role.rb~ +10 -0
- data/app/models/marty/script.rb +144 -0
- data/app/models/marty/script.rb~ +62 -0
- data/app/models/marty/tag.rb +96 -0
- data/app/models/marty/tag.rb~ +91 -0
- data/app/models/marty/token.rb +30 -0
- data/app/models/marty/user.rb +146 -0
- data/app/models/marty/user.rb~ +148 -0
- data/app/models/marty/user_role.rb +7 -0
- data/app/models/marty/user_role.rb~ +13 -0
- data/app/views/layouts/marty/application.html.erb +12 -0
- data/app/views/layouts/marty/application.html.erb~ +11 -0
- data/config/locales/en.yml +134 -0
- data/config/routes.rb +6 -0
- data/config/routes.rb~ +10 -0
- data/db/migrate/001_create_marty_scripts.rb +14 -0
- data/db/migrate/003_create_marty_users.rb +12 -0
- data/db/migrate/004_create_marty_roles.rb +7 -0
- data/db/migrate/005_create_marty_user_roles.rb +14 -0
- data/db/migrate/006_create_marty_tokens.rb +14 -0
- data/db/migrate/008_create_marty_posting_types.rb +7 -0
- data/db/migrate/019_create_marty_postings.rb +18 -0
- data/db/migrate/019_create_marty_postings.rb~ +19 -0
- data/db/migrate/068_create_marty_import_types.rb +12 -0
- data/db/migrate/069_create_marty_import_synonyms.rb +15 -0
- data/db/migrate/070_create_versions.rb +18 -0
- data/db/migrate/071_add_object_changes_column_to_versions.rb +9 -0
- data/db/migrate/072_add_validation_function_to_import_types.rb +6 -0
- data/db/migrate/073_add_preprocess_function_to_import_types.rb +5 -0
- data/db/migrate/090_create_delayed_jobs.rb +22 -0
- data/db/migrate/091_create_marty_promises.rb +36 -0
- data/db/migrate/095_create_marty_tags.rb +14 -0
- data/db/migrate/095_create_marty_tags.rb~ +19 -0
- data/db/migrate/096_add_user_roles_to_import_types.rb +11 -0
- data/db/migrate/097_drop_versions.rb +9 -0
- data/db/migrate/098_create_marty_api_auths.rb +20 -0
- data/db/seeds.rb +48 -0
- data/lib/marty.rb +18 -0
- data/lib/marty.rb~ +13 -0
- data/lib/marty/content_handler.rb +97 -0
- data/lib/marty/content_handler.rb~ +93 -0
- data/lib/marty/data_conversion.rb +298 -0
- data/lib/marty/data_exporter.rb +150 -0
- data/lib/marty/data_exporter.rb~ +137 -0
- data/lib/marty/data_importer.rb +122 -0
- data/lib/marty/data_importer.rb~ +114 -0
- data/lib/marty/data_row_processor.rb~ +206 -0
- data/lib/marty/drop_folder_hook.rb~ +17 -0
- data/lib/marty/engine.rb +10 -0
- data/lib/marty/folder_hook.rb~ +9 -0
- data/lib/marty/lazy_column_loader.rb +57 -0
- data/lib/marty/lazy_column_loader.rb~ +47 -0
- data/lib/marty/mcfly_query.rb +189 -0
- data/lib/marty/mcfly_query.rb~ +188 -0
- data/lib/marty/migrations.rb +108 -0
- data/lib/marty/migrations.rb~ +65 -0
- data/lib/marty/monkey.rb +163 -0
- data/lib/marty/monkey.rb~ +160 -0
- data/lib/marty/permissions.rb +64 -0
- data/lib/marty/permissions.rb~ +69 -0
- data/lib/marty/promise.rb~ +41 -0
- data/lib/marty/promise_job.rb +123 -0
- data/lib/marty/promise_job.rb~ +121 -0
- data/lib/marty/promise_proxy.rb +94 -0
- data/lib/marty/promise_proxy.rb~ +69 -0
- data/lib/marty/railtie.rb +5 -0
- data/lib/marty/relation.rb +39 -0
- data/lib/marty/util.rb +110 -0
- data/lib/marty/util.rb~ +80 -0
- data/lib/marty/version.rb +3 -0
- data/lib/marty/version.rb~ +3 -0
- data/lib/marty/xl.rb +527 -0
- data/lib/marty/xl.rb~ +526 -0
- data/lib/pyxll/README.txt +19 -0
- data/lib/pyxll/README.txt~ +16 -0
- data/lib/pyxll/gemini.py +155 -0
- data/lib/pyxll/gemini.py~ +110 -0
- data/lib/pyxll/pyxll.cfg +12 -0
- data/lib/pyxll/pyxll.cfg~ +12 -0
- data/lib/pyxll/sample.xlsx +0 -0
- data/lib/tasks/marty_tasks.rake +37 -0
- metadata +517 -0
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
require 'base64'
|
|
2
|
+
require 'zlib'
|
|
3
|
+
require 'csv'
|
|
4
|
+
require 'marty/data_conversion'
|
|
5
|
+
|
|
6
|
+
class Marty::DataExporter
|
|
7
|
+
# given an array of hashes, return set of all keys
|
|
8
|
+
def self.hash_array_keys(hl)
|
|
9
|
+
hl.each_with_object(Set.new) { |h, keys| keys.merge(h.keys) }
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def self.hash_array_merge(hl, transpose)
|
|
13
|
+
# given a list of hashes hl, generates a merged hash. The
|
|
14
|
+
# resulting hash contains a superset of all the hash keys. The
|
|
15
|
+
# values are corresponding values from each hash in hl.
|
|
16
|
+
# e.g. the following
|
|
17
|
+
#
|
|
18
|
+
# [{"a"=>1, "b"=>2}, {"a"=>11, "c"=>33}, {"a"=>1111, "b"=>222, "c"=>333}]
|
|
19
|
+
#
|
|
20
|
+
# maps to ...
|
|
21
|
+
#
|
|
22
|
+
# [["a", "b", "c"], [1, 2, nil], [11, nil, 33], [1111, 222, 333]]
|
|
23
|
+
|
|
24
|
+
keys = hash_array_keys(hl)
|
|
25
|
+
|
|
26
|
+
return keys.each_with_object({}) { |k, rh|
|
|
27
|
+
rh[k] = hl.map { |h| h[k] }
|
|
28
|
+
} if transpose
|
|
29
|
+
|
|
30
|
+
[keys.to_a] + hl.map {|h| keys.map {|k| h[k]}}
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.encode_json(s)
|
|
34
|
+
Base64.strict_encode64 Zlib.deflate(s)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.decode_json(s)
|
|
38
|
+
Zlib.inflate Base64.strict_decode64(s)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def self.to_csv(obj, config=nil)
|
|
42
|
+
obj = [obj] unless obj.respond_to? :map
|
|
43
|
+
|
|
44
|
+
config ||= {}
|
|
45
|
+
|
|
46
|
+
# if all array items are hashes, we merge them
|
|
47
|
+
obj = hash_array_merge(obj, config["transpose"]) if
|
|
48
|
+
obj.is_a?(Array) && obj.map {|x| x.is_a? Hash}.all?
|
|
49
|
+
|
|
50
|
+
# symbolize config keys as expected by CSV.generate
|
|
51
|
+
conf = config.each_with_object({}) { |(k,v), h|
|
|
52
|
+
h[k.to_sym] = v unless k.to_s == "transpose"
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
# FIXME: very hacky to default row_sep to CRLF
|
|
56
|
+
conf[:row_sep] ||= "\r\n"
|
|
57
|
+
|
|
58
|
+
# FIXME: the following is ridiculously complex. We have different
|
|
59
|
+
# data paths for hashes and arrays. Also, arrays can turn into
|
|
60
|
+
# hashes is all their items are hashes! We map to complex objects
|
|
61
|
+
# to JSON when inside hashes, but not arrays. Really need to
|
|
62
|
+
# rethink this. Probably should have separate functions for
|
|
63
|
+
# to_csv for hash and arrays.
|
|
64
|
+
|
|
65
|
+
return CSV.generate(conf) do |csv|
|
|
66
|
+
obj.each do |x|
|
|
67
|
+
csv << x.flatten(1).map(&:to_s)
|
|
68
|
+
end
|
|
69
|
+
end if obj.is_a?(Hash)
|
|
70
|
+
|
|
71
|
+
CSV.generate(conf) do |csv|
|
|
72
|
+
obj.each do |x|
|
|
73
|
+
x = [x] unless x.respond_to? :map
|
|
74
|
+
csv << x.map { |v|
|
|
75
|
+
v.is_a?(Array) || v.is_a?(Hash) ? encode_json(v.to_json) : v.to_s
|
|
76
|
+
}
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def self.export_attrs(klass, obj, attrs=nil)
|
|
82
|
+
col_types = Marty::DataConversion.col_types(klass)
|
|
83
|
+
|
|
84
|
+
(attrs || col_types.keys).map do
|
|
85
|
+
|c|
|
|
86
|
+
|
|
87
|
+
v = obj.send(c.to_sym)
|
|
88
|
+
|
|
89
|
+
c = c.to_s
|
|
90
|
+
type = col_types[c]
|
|
91
|
+
|
|
92
|
+
# return [value] if not assoc or nil
|
|
93
|
+
next [v] if v.nil? || !type.is_a?(Hash)
|
|
94
|
+
|
|
95
|
+
assoc_keys = type[:assoc_keys]
|
|
96
|
+
assoc_class = type[:assoc_class]
|
|
97
|
+
assoc_obj = assoc_class.find(v)
|
|
98
|
+
|
|
99
|
+
# FIXME: this recursion will fail if a reference which then
|
|
100
|
+
# makes sub-references is nil. To handle this, we'd need to
|
|
101
|
+
# create the export structure first.
|
|
102
|
+
export_attrs(assoc_class, assoc_obj, assoc_keys).flatten(1)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def self.export_headers(klass, attrs=nil)
|
|
107
|
+
col_types = Marty::DataConversion.col_types(klass)
|
|
108
|
+
|
|
109
|
+
(attrs || col_types.keys).map do
|
|
110
|
+
|c|
|
|
111
|
+
|
|
112
|
+
c = c.to_s
|
|
113
|
+
type = col_types[c]
|
|
114
|
+
|
|
115
|
+
next c unless type.is_a?(Hash)
|
|
116
|
+
|
|
117
|
+
# remove _id
|
|
118
|
+
c = c[0..-4]
|
|
119
|
+
|
|
120
|
+
assoc_keys = type[:assoc_keys]
|
|
121
|
+
|
|
122
|
+
# if association has a single key, just use col name
|
|
123
|
+
next c if assoc_keys.length == 1
|
|
124
|
+
|
|
125
|
+
assoc_class = type[:assoc_class]
|
|
126
|
+
|
|
127
|
+
export_headers(assoc_class, assoc_keys).map {|k| "#{c}__#{k}"}
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Given a Mcfly klass, generate an export array. Can potentially
|
|
132
|
+
# use up a lot of memory if the result set is large.
|
|
133
|
+
def self.do_export(ts, klass, sort_field=nil)
|
|
134
|
+
query = klass
|
|
135
|
+
|
|
136
|
+
if Mcfly.has_mcfly?(klass)
|
|
137
|
+
ts = Mcfly.normalize_infinity(ts)
|
|
138
|
+
query = query.where("obsoleted_dt >= ? AND created_dt < ?", ts, ts)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
do_export_query_result(klass, query.order(sort_field || :id))
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def self.do_export_query_result(klass, qres)
|
|
145
|
+
# strip _id from assoc fields
|
|
146
|
+
header = [ export_headers(klass).flatten ]
|
|
147
|
+
|
|
148
|
+
header + qres.map {|obj| export_attrs(klass, obj).flatten(1)}
|
|
149
|
+
end
|
|
150
|
+
end
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
require 'base64'
|
|
2
|
+
require 'zlib'
|
|
3
|
+
|
|
4
|
+
class Marty::DataExporter
|
|
5
|
+
# given an array of hashes, return set of all keys
|
|
6
|
+
def self.hash_array_keys(hl)
|
|
7
|
+
hl.each_with_object(Set.new) { |h, keys| keys.merge(h.keys) }
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def self.hash_array_merge(hl, transpose)
|
|
11
|
+
# given a list of hashes hl, generates a merged hash. The
|
|
12
|
+
# resulting hash contains a superset of all the hash keys. The
|
|
13
|
+
# values are corresponding values from each hash in hl.
|
|
14
|
+
keys = hash_array_keys(hl)
|
|
15
|
+
|
|
16
|
+
if transpose
|
|
17
|
+
keys.each_with_object({}) { |k, rh|
|
|
18
|
+
rh[k] = hl.map { |h| h[k] }
|
|
19
|
+
}
|
|
20
|
+
else
|
|
21
|
+
[keys.to_a] + hl.map {|h| keys.map {|k| h[k]}}
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.encode_json(s)
|
|
26
|
+
Base64.strict_encode64 Zlib.deflate(s)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def self.decode_json(s)
|
|
30
|
+
Zlib.inflate Base64.strict_decode64(s)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.to_csv(obj, config=nil)
|
|
34
|
+
obj = [obj] unless obj.respond_to? :map
|
|
35
|
+
|
|
36
|
+
config ||= {}
|
|
37
|
+
|
|
38
|
+
# if all array items are hashes, we merge them
|
|
39
|
+
obj = hash_array_merge(obj, config["transpose"]) if
|
|
40
|
+
obj.is_a?(Array) && obj.map {|x| x.is_a? Hash}.all?
|
|
41
|
+
|
|
42
|
+
# symbolize config keys as expected by CSV.generate
|
|
43
|
+
conf = config.each_with_object({}) { |(k,v), h|
|
|
44
|
+
h[k.to_sym] = v unless k.to_s == "transpose"
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
# FIXME: very hacky to default row_sep to CRLF
|
|
48
|
+
conf[:row_sep] ||= "\r\n"
|
|
49
|
+
|
|
50
|
+
# FIXME: the following is ridiculously complex. We have different
|
|
51
|
+
# data paths for hashes and arrays. Also, arrays can turn into
|
|
52
|
+
# hashes is all their items are hashes! We map to complex objects
|
|
53
|
+
# to JSON when inside hashes, but not arrays. Really need to
|
|
54
|
+
# rethink this. Probably should have separate functions for
|
|
55
|
+
# to_csv for hash and arrays.
|
|
56
|
+
|
|
57
|
+
if obj.is_a? Hash
|
|
58
|
+
csv_string = CSV.generate(conf) do |csv|
|
|
59
|
+
obj.each do |x|
|
|
60
|
+
csv << x.flatten(1).map(&:to_s)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
else
|
|
64
|
+
csv_string = CSV.generate(conf) do |csv|
|
|
65
|
+
obj.each do |x|
|
|
66
|
+
x = [x] unless x.respond_to? :map
|
|
67
|
+
csv << x.map { |v|
|
|
68
|
+
v.is_a?(Array) || v.is_a?(Hash) ? encode_json(v.to_json) : v.to_s
|
|
69
|
+
}
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def self.class_info(klass)
|
|
76
|
+
@class_info ||= {}
|
|
77
|
+
|
|
78
|
+
return @class_info[klass] if @class_info[klass]
|
|
79
|
+
|
|
80
|
+
associations = klass.reflect_on_all_associations.map(&:name)
|
|
81
|
+
|
|
82
|
+
@class_info[klass] = {
|
|
83
|
+
cols:
|
|
84
|
+
klass.columns.map(&:name) - Marty::DataRowProcessor::MCFLY_COLUMNS.to_a,
|
|
85
|
+
|
|
86
|
+
assoc:
|
|
87
|
+
associations.each_with_object({}) { |a, h|
|
|
88
|
+
h["#{a}_id"] = Marty::DataRowProcessor.assoc_info(klass, a)
|
|
89
|
+
},
|
|
90
|
+
}
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def self.export_attr(obj, c, info)
|
|
94
|
+
v = obj.send(c.to_sym)
|
|
95
|
+
assoc_info = info[:assoc][c] unless v.nil?
|
|
96
|
+
return [v] unless assoc_info
|
|
97
|
+
|
|
98
|
+
assoc_obj = assoc_info[:assoc_class].find(v)
|
|
99
|
+
|
|
100
|
+
assoc_info[:assoc_keys].map {|k| assoc_obj.send(k.to_sym)}
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def self.export_header_attr(c, info)
|
|
104
|
+
assoc_info = info[:assoc][c]
|
|
105
|
+
return c unless assoc_info
|
|
106
|
+
|
|
107
|
+
# remove _id
|
|
108
|
+
c = c[0..-4]
|
|
109
|
+
|
|
110
|
+
assoc_keys = assoc_info[:assoc_keys]
|
|
111
|
+
|
|
112
|
+
# FIXME: this doesn't work if k is also an association. Needs to
|
|
113
|
+
# be recursive.
|
|
114
|
+
assoc_keys.length > 1 ? assoc_keys.map {|k| "#{c}__#{k}"} : c
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# Given a Mcfly klass, generate an export array. Can potentially
|
|
118
|
+
# use up a lot of memory if the result set is large.
|
|
119
|
+
def self.do_export(ts, klass, sort_field=nil)
|
|
120
|
+
info = class_info(klass)
|
|
121
|
+
|
|
122
|
+
# strip _id from assoc fields
|
|
123
|
+
header = [ info[:cols].map {|c| export_header_attr(c, info)}.flatten(1) ]
|
|
124
|
+
|
|
125
|
+
query = klass
|
|
126
|
+
|
|
127
|
+
# is it Mcfly?
|
|
128
|
+
if (klass.const_get(:MCFLY_UNIQUENESS) rescue nil)
|
|
129
|
+
ts = Mcfly.normalize_infinity(ts)
|
|
130
|
+
query = query.where("obsoleted_dt >= ? AND created_dt < ?", ts, ts)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
header + query.
|
|
134
|
+
order(sort_field || :id).
|
|
135
|
+
map {|obj| info[:cols].map {|c| export_attr(obj, c, info)}.flatten(1)}
|
|
136
|
+
end
|
|
137
|
+
end
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
require 'csv'
|
|
2
|
+
require 'marty/data_conversion'
|
|
3
|
+
|
|
4
|
+
module Marty
|
|
5
|
+
class DataImporterError < StandardError
|
|
6
|
+
attr_reader :lines
|
|
7
|
+
|
|
8
|
+
def initialize(message, lines)
|
|
9
|
+
msg = lines && lines.respond_to?(:join) ?
|
|
10
|
+
"#{message} - lines: #{lines.join(',')}" : message
|
|
11
|
+
|
|
12
|
+
super(msg)
|
|
13
|
+
@lines = lines
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class DataImporter
|
|
18
|
+
# perform cleaning and do_import and summarize its results
|
|
19
|
+
def self.do_import_summary(klass,
|
|
20
|
+
data,
|
|
21
|
+
dt = 'infinity',
|
|
22
|
+
cleaner_function = nil,
|
|
23
|
+
validation_function = nil,
|
|
24
|
+
col_sep = "\t",
|
|
25
|
+
allow_dups = false,
|
|
26
|
+
preprocess_function = nil
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
recs = self.do_import(klass,
|
|
30
|
+
data,
|
|
31
|
+
dt,
|
|
32
|
+
cleaner_function,
|
|
33
|
+
validation_function,
|
|
34
|
+
col_sep,
|
|
35
|
+
allow_dups,
|
|
36
|
+
preprocess_function,
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
recs.each_with_object(Hash.new(0)) {|(op, id), h|
|
|
40
|
+
h[op] += 1
|
|
41
|
+
}
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Given a Mcfly klass and CSV data, import data into the database
|
|
45
|
+
# and report on affected rows. Result is an array of tuples.
|
|
46
|
+
# Each tuple is associated with one data row and looks like [tag,
|
|
47
|
+
# id]. Tag is one of :same, :update, :create and "id" is the id
|
|
48
|
+
# of the affected row.
|
|
49
|
+
def self.do_import(klass,
|
|
50
|
+
data,
|
|
51
|
+
dt = 'infinity',
|
|
52
|
+
cleaner_function = nil,
|
|
53
|
+
validation_function = nil,
|
|
54
|
+
col_sep = "\t",
|
|
55
|
+
allow_dups = false,
|
|
56
|
+
preprocess_function = nil
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
parsed = data.is_a?(Array) ? data :
|
|
60
|
+
CSV.new(data, headers: true, col_sep: col_sep)
|
|
61
|
+
|
|
62
|
+
# run preprocessor
|
|
63
|
+
parsed = klass.send(preprocess_function.to_sym, parsed) if
|
|
64
|
+
preprocess_function
|
|
65
|
+
|
|
66
|
+
klass.transaction do
|
|
67
|
+
cleaner_ids = cleaner_function ? klass.send(cleaner_function.to_sym) :
|
|
68
|
+
[]
|
|
69
|
+
|
|
70
|
+
raise "bad cleaner function result" unless
|
|
71
|
+
cleaner_ids.all? {|id| id.is_a?(Fixnum) }
|
|
72
|
+
|
|
73
|
+
eline = 0
|
|
74
|
+
|
|
75
|
+
begin
|
|
76
|
+
res = parsed.each_with_index.map do
|
|
77
|
+
|row, line|
|
|
78
|
+
eline = line
|
|
79
|
+
|
|
80
|
+
# skip lines which are all nil
|
|
81
|
+
next :blank if row.to_hash.values.none?
|
|
82
|
+
|
|
83
|
+
Marty::DataConversion.create_or_update(klass, row, dt)
|
|
84
|
+
end
|
|
85
|
+
rescue => exc
|
|
86
|
+
# to find problems with the importer, comment out the rescue block
|
|
87
|
+
raise Marty::DataImporterError.new(exc.to_s, [eline])
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
ids = {}
|
|
91
|
+
|
|
92
|
+
# raise an error if record referenced more than once.
|
|
93
|
+
res.each_with_index do
|
|
94
|
+
|(op, id), line|
|
|
95
|
+
raise Marty::DataImporterError.
|
|
96
|
+
new("record referenced more than once", [ids[id], line]) if
|
|
97
|
+
op != :blank && ids.member?(id) && !allow_dups
|
|
98
|
+
|
|
99
|
+
ids[id] = line
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
begin
|
|
103
|
+
# Validate affected rows if necessary
|
|
104
|
+
klass.send(validation_function.to_sym, ids.keys) if
|
|
105
|
+
validation_function
|
|
106
|
+
rescue => exc
|
|
107
|
+
raise Marty::DataImporterError.new(exc.to_s, [])
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
remainder_ids = cleaner_ids - ids.keys
|
|
111
|
+
|
|
112
|
+
raise Marty::DataImporterError.
|
|
113
|
+
new("Missing import data. " +
|
|
114
|
+
"Please provide header line and at least one data line.", [1]) if
|
|
115
|
+
ids.keys.compact.count == 0
|
|
116
|
+
|
|
117
|
+
klass.delete(remainder_ids)
|
|
118
|
+
res + remainder_ids.map {|id| [:clean, id]}
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
module Marty
|
|
2
|
+
class DataImporterError < StandardError
|
|
3
|
+
attr_reader :lines
|
|
4
|
+
|
|
5
|
+
def initialize(message, lines)
|
|
6
|
+
super(message)
|
|
7
|
+
@lines = lines
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class DataImporter
|
|
12
|
+
# perform cleaning and do_import and summarize its results
|
|
13
|
+
def self.do_import_summary(klass,
|
|
14
|
+
data,
|
|
15
|
+
dt='infinity',
|
|
16
|
+
cleaner_function=nil,
|
|
17
|
+
validation_function=nil,
|
|
18
|
+
col_sep="\t",
|
|
19
|
+
allow_dups=false
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
recs = self.do_import(klass,
|
|
23
|
+
data,
|
|
24
|
+
dt,
|
|
25
|
+
cleaner_function,
|
|
26
|
+
validation_function,
|
|
27
|
+
col_sep,
|
|
28
|
+
allow_dups,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
recs.each_with_object(Hash.new(0)) {|(op, id), h|
|
|
32
|
+
h[op] += 1
|
|
33
|
+
}
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Given a Mcfly klass and CSV data, import data into the database
|
|
37
|
+
# and report on affected rows. Result is an array of tuples.
|
|
38
|
+
# Each tuple is associated with one data row and looks like [tag,
|
|
39
|
+
# id]. Tag is one of :same, :update, :create and "id" is the id
|
|
40
|
+
# of the affected row.
|
|
41
|
+
def self.do_import(klass,
|
|
42
|
+
data,
|
|
43
|
+
dt='infinity',
|
|
44
|
+
cleaner_function=nil,
|
|
45
|
+
validation_function=nil,
|
|
46
|
+
col_sep="\t",
|
|
47
|
+
allow_dups=false
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
parsed = data.is_a?(Array) ? data :
|
|
51
|
+
CSV.new(data, headers: true, col_sep: col_sep)
|
|
52
|
+
|
|
53
|
+
klass.transaction do
|
|
54
|
+
cleaner_ids = cleaner_function ? klass.send(cleaner_function.to_sym) :
|
|
55
|
+
[]
|
|
56
|
+
|
|
57
|
+
raise "bad cleaner function result" unless
|
|
58
|
+
cleaner_ids.all? {|id| id.is_a?(Fixnum) }
|
|
59
|
+
|
|
60
|
+
row_proc = nil
|
|
61
|
+
eline = 0
|
|
62
|
+
|
|
63
|
+
begin
|
|
64
|
+
res = parsed.each_with_index.map { |row, line|
|
|
65
|
+
eline = line
|
|
66
|
+
|
|
67
|
+
row_proc ||= Marty::DataRowProcessor.
|
|
68
|
+
new(klass,
|
|
69
|
+
row.respond_to?(:headers) ? row.headers : row.keys,
|
|
70
|
+
dt,
|
|
71
|
+
)
|
|
72
|
+
# skip lines which are all nil
|
|
73
|
+
next :blank if row.to_hash.values.none?
|
|
74
|
+
|
|
75
|
+
row_proc.create_or_update(row)
|
|
76
|
+
}
|
|
77
|
+
rescue => exc
|
|
78
|
+
# to find problems with the importer, comment out the rescue block
|
|
79
|
+
raise Marty::DataImporterError.new(exc.to_s, [eline])
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
ids = {}
|
|
83
|
+
|
|
84
|
+
# raise an error if record referenced more than once.
|
|
85
|
+
res.each_with_index do
|
|
86
|
+
|(op, id), line|
|
|
87
|
+
raise Marty::DataImporterError.
|
|
88
|
+
new("record referenced more than once", [ids[id], line]) if
|
|
89
|
+
op != :blank && ids.member?(id) && !allow_dups
|
|
90
|
+
|
|
91
|
+
ids[id] = line
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
begin
|
|
95
|
+
# Validate affected rows if necessary
|
|
96
|
+
klass.send(validation_function.to_sym, ids.keys) if
|
|
97
|
+
validation_function
|
|
98
|
+
rescue => exc
|
|
99
|
+
raise Marty::DataImporterError.new(exc.to_s, [])
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
remainder_ids = cleaner_ids - ids.keys
|
|
103
|
+
|
|
104
|
+
raise Marty::DataImporterError.
|
|
105
|
+
new("Missing import data. " +
|
|
106
|
+
"Please provide header line and at least one data line.", [1]) if
|
|
107
|
+
ids.keys.compact.count == 0
|
|
108
|
+
|
|
109
|
+
klass.delete(remainder_ids)
|
|
110
|
+
res + remainder_ids.map {|id| [:clean, id]}
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|