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,206 @@
|
|
|
1
|
+
class Marty::DataRowProcessor
|
|
2
|
+
attr_accessor :klass, :headers, :dt, :key_attrs, :hmap
|
|
3
|
+
|
|
4
|
+
EXCEL_START_DATE = Date.parse('1/1/1900')-2
|
|
5
|
+
|
|
6
|
+
MCFLY_COLUMNS = Set[
|
|
7
|
+
"id",
|
|
8
|
+
"group_id",
|
|
9
|
+
"user_id",
|
|
10
|
+
"created_dt",
|
|
11
|
+
"obsoleted_dt",
|
|
12
|
+
"o_user_id",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
# Given a Mcfly class, return the set of attributes (excluding id)
|
|
16
|
+
# used to uniquely identify an instance.
|
|
17
|
+
def self.get_keys(klass)
|
|
18
|
+
raise "bad class arg #{klass}" unless
|
|
19
|
+
klass.is_a?(Class) && klass < ActiveRecord::Base
|
|
20
|
+
|
|
21
|
+
attrs = klass.const_get(:MCFLY_UNIQUENESS)
|
|
22
|
+
|
|
23
|
+
raise "class has no :MCFLY_UNIQUENESS" unless attrs
|
|
24
|
+
|
|
25
|
+
attrs = attrs[0..-2] + attrs.last.fetch(:scope, []) if
|
|
26
|
+
attrs.last.is_a?(Hash)
|
|
27
|
+
attrs -= [:obsoleted_dt]
|
|
28
|
+
|
|
29
|
+
raise "key list for #{klass} is empty" if attrs.empty?
|
|
30
|
+
attrs
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.assoc_info(klass, a)
|
|
34
|
+
assoc_class = klass.reflect_on_association(a.to_sym).klass
|
|
35
|
+
keys = self.get_keys(assoc_class) rescue nil
|
|
36
|
+
|
|
37
|
+
assoc_keys = keys || [assoc_class.attribute_names.reject{|x| x=="id"}.first]
|
|
38
|
+
|
|
39
|
+
{assoc_keys: assoc_keys, assoc_class: assoc_class, mcfly: keys}
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
FLOAT_PAT = /^-?\d+(\.\d+)?$/
|
|
43
|
+
|
|
44
|
+
PATS = {
|
|
45
|
+
integer: /^-?\d+(\.0+)?$/,
|
|
46
|
+
float: FLOAT_PAT,
|
|
47
|
+
decimal: FLOAT_PAT,
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
def convert(v, type)
|
|
51
|
+
pat = PATS[type]
|
|
52
|
+
|
|
53
|
+
raise "bad #{type} #{v.inspect}" if
|
|
54
|
+
v.is_a?(String) && pat && !(v =~ pat)
|
|
55
|
+
|
|
56
|
+
case type
|
|
57
|
+
when :boolean
|
|
58
|
+
case v.downcase
|
|
59
|
+
when "true" then true
|
|
60
|
+
when "false" then false
|
|
61
|
+
else raise "unknown boolean #{v}"
|
|
62
|
+
end
|
|
63
|
+
when :string, :text
|
|
64
|
+
v
|
|
65
|
+
when :integer
|
|
66
|
+
v.to_i
|
|
67
|
+
when :float
|
|
68
|
+
v.to_f
|
|
69
|
+
when :decimal
|
|
70
|
+
v.to_d
|
|
71
|
+
when :date
|
|
72
|
+
# Dates are kept as float in Google spreadsheets. Need to
|
|
73
|
+
# convert them to dates. FIXME: 'infinity' as a date in
|
|
74
|
+
# Rails 3.2 appears to be broken. Setting a date field to
|
|
75
|
+
# 'infinity' sets it to nil.
|
|
76
|
+
v =~ FLOAT_PAT ? EXCEL_START_DATE + v.to_f :
|
|
77
|
+
Mcfly.is_infinity(v) ? 'infinity' : v.to_date
|
|
78
|
+
when :datetime
|
|
79
|
+
Mcfly.is_infinity(v) ? 'infinity' : v.to_datetime
|
|
80
|
+
when :numrange, :int4range, :int8range
|
|
81
|
+
v.to_s
|
|
82
|
+
when :float_array, :json
|
|
83
|
+
JSON.parse Marty::DataExporter.decode_json(v)
|
|
84
|
+
else
|
|
85
|
+
raise "unknown type #{type} for #{v}"
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def initialize(klass, headers, dt)
|
|
90
|
+
@klass = klass
|
|
91
|
+
@headers = headers
|
|
92
|
+
@dt = dt
|
|
93
|
+
@key_attrs = self.class.get_keys(klass)
|
|
94
|
+
|
|
95
|
+
# # HACK: not sure why there's a nil at the end of headers sometimes
|
|
96
|
+
# headers.pop if headers[-1].nil?
|
|
97
|
+
|
|
98
|
+
raise "row headers have nil! #{headers.inspect}" unless headers.all?
|
|
99
|
+
|
|
100
|
+
associations = klass.reflect_on_all_associations.map(&:name)
|
|
101
|
+
|
|
102
|
+
cols = klass.columns.each_with_object({}) { |c, h|
|
|
103
|
+
h[c.name] = c
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
@hmap = headers.each_with_object({}) do
|
|
107
|
+
|a, h|
|
|
108
|
+
# handle klass__attr type headers generated by Netzke. Just
|
|
109
|
+
# keeps klass since we should be able to find the key attr.
|
|
110
|
+
aclass = a.split('__').first
|
|
111
|
+
|
|
112
|
+
if associations.member?(aclass.to_sym)
|
|
113
|
+
h[a] = self.class.assoc_info(klass, aclass)
|
|
114
|
+
next
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
raise "unknown column #{a}" unless cols[a]
|
|
118
|
+
|
|
119
|
+
# for JSON fields in Rails 3.x type is nil, so use sql_type
|
|
120
|
+
type = cols[a].type || cols[a].sql_type
|
|
121
|
+
type = "#{type}_array" if cols[a].array
|
|
122
|
+
h[a] = type.to_sym
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def create_or_update(row)
|
|
127
|
+
assoc_options = {}
|
|
128
|
+
|
|
129
|
+
options = row.each_with_object({}) do |(a, v), h|
|
|
130
|
+
# ignore Mcfly columns
|
|
131
|
+
next if MCFLY_COLUMNS.member? a
|
|
132
|
+
|
|
133
|
+
if hmap[a].is_a?(Hash)
|
|
134
|
+
assoc_options[a] = v
|
|
135
|
+
else
|
|
136
|
+
raise "bad col #{a} value #{v}, row: #{row}" unless hmap[a]
|
|
137
|
+
|
|
138
|
+
# if it's not a hash (association) then its a type symbol
|
|
139
|
+
h[a] = v && convert(v, hmap[a])
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
assoc_groups = assoc_options.keys.group_by {|x| x.split('__').first}
|
|
144
|
+
|
|
145
|
+
assoc_groups.each do |aclass, attrs|
|
|
146
|
+
# if group has only one attr and the attr is nil or AR obj, then
|
|
147
|
+
# we don't need to search.
|
|
148
|
+
if attrs.length == 1
|
|
149
|
+
a = attrs.first
|
|
150
|
+
v = assoc_options[a]
|
|
151
|
+
|
|
152
|
+
if v.nil? || v.is_a?(ActiveRecord::Base)
|
|
153
|
+
options["#{aclass}_id"] = v && v.id
|
|
154
|
+
next
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
srch = attrs.each_with_object({}) do |a, h|
|
|
159
|
+
v = assoc_options[a]
|
|
160
|
+
ac, aa = a.split('__')
|
|
161
|
+
|
|
162
|
+
aa ||= hmap[a][:assoc_keys].first
|
|
163
|
+
|
|
164
|
+
h[aa] = v
|
|
165
|
+
h[:obsoleted_dt] = 'infinity' if hmap[a][:mcfly]
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
srch_class = hmap[attrs.first][:assoc_class]
|
|
169
|
+
|
|
170
|
+
av = srch_class.where(srch).first
|
|
171
|
+
|
|
172
|
+
raise "#{aclass} not found #{srch}" unless av
|
|
173
|
+
|
|
174
|
+
options[ "#{aclass}_id" ] = av.id
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
find_options = options.select { |k,v| key_attrs.member? k.to_sym }
|
|
178
|
+
|
|
179
|
+
raise "invalid entry" if find_options.empty?
|
|
180
|
+
|
|
181
|
+
find_options['obsoleted_dt'] = 'infinity'
|
|
182
|
+
|
|
183
|
+
obj = klass.where(find_options).first || klass.new
|
|
184
|
+
|
|
185
|
+
options.each do
|
|
186
|
+
|k, v|
|
|
187
|
+
# For each attr, check to see if it's begin changed before
|
|
188
|
+
# setting it. The AR obj.changed? doesn't work properly
|
|
189
|
+
# with array, JSON or lazy attrs.
|
|
190
|
+
obj.send("#{k}=", v) if obj.send(k) != v
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
# FIXME: obj.changed? doesn't work properly for timestamp
|
|
194
|
+
# fields in Rails 3.2. It evaluates to true even when datetime
|
|
195
|
+
# is not changed. Caused by lack of awareness of timezones.
|
|
196
|
+
tag = obj.new_record? ? :create : (obj.changed? ? :update : :same)
|
|
197
|
+
|
|
198
|
+
raise "old created_dt >= current #{obj} #{obj.created_dt} #{dt}" if
|
|
199
|
+
(tag == :update) && !Mcfly.is_infinity(dt) && (obj.created_dt > dt)
|
|
200
|
+
|
|
201
|
+
obj.created_dt = dt unless tag == :same || Mcfly.is_infinity(dt)
|
|
202
|
+
obj.save!
|
|
203
|
+
|
|
204
|
+
[tag, obj.id]
|
|
205
|
+
end
|
|
206
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
class Marty::DropFolderHook
|
|
2
|
+
def initialize(login)
|
|
3
|
+
@login = login
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def run(res)
|
|
7
|
+
p 'H.'*10, res
|
|
8
|
+
drop_path = "/tmp/#{@login}"
|
|
9
|
+
|
|
10
|
+
begin
|
|
11
|
+
Dir.mkdir(drop_path) unless File.directory?(drop_path)
|
|
12
|
+
rescue => exc
|
|
13
|
+
Marty::Util.logger.error "Can't create
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|
data/lib/marty/engine.rb
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# ATTRIBUTION NOTE: This module has been mostly copied from the
|
|
2
|
+
# lazy_columns gem. The original code can be found at:
|
|
3
|
+
# https://github.com/jorgemanrubia/lazy_columns
|
|
4
|
+
|
|
5
|
+
module Marty
|
|
6
|
+
module LazyColumnLoader
|
|
7
|
+
extend ActiveSupport::Concern
|
|
8
|
+
|
|
9
|
+
module ClassMethods
|
|
10
|
+
def lazy_load(*columns)
|
|
11
|
+
return unless table_exists?
|
|
12
|
+
columns = columns.collect(&:to_s)
|
|
13
|
+
exclude_columns_from_default_scope columns
|
|
14
|
+
define_lazy_accessors_for columns
|
|
15
|
+
|
|
16
|
+
# allow introspection of lazy-loaded column list
|
|
17
|
+
const_set(:LAZY_LOADED, columns)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
private
|
|
21
|
+
def exclude_columns_from_default_scope(columns)
|
|
22
|
+
default_scope {
|
|
23
|
+
select((column_names - columns).map {
|
|
24
|
+
|column_name|
|
|
25
|
+
"#{table_name}.#{column_name}"
|
|
26
|
+
})
|
|
27
|
+
}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def define_lazy_accessors_for(columns)
|
|
31
|
+
columns.each { |column| define_lazy_accessor_for column }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def define_lazy_accessor_for(column)
|
|
35
|
+
define_method column do
|
|
36
|
+
unless has_attribute?(column)
|
|
37
|
+
changes_before_reload = self.changes.clone
|
|
38
|
+
self.reload
|
|
39
|
+
changes_before_reload.each{
|
|
40
|
+
|attribute_name, values|
|
|
41
|
+
self.send("#{attribute_name}=", values[1])
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
read_attribute column
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
if ActiveRecord::Base.respond_to?(:lazy_load)
|
|
52
|
+
$stderr.puts "ERROR: Method `.lazy_load` already defined in " +
|
|
53
|
+
"`ActiveRecord::Base`. This is incompatible with LazyColumnLoader " +
|
|
54
|
+
"and the module will be disabled."
|
|
55
|
+
else
|
|
56
|
+
ActiveRecord::Base.send :include, Marty::LazyColumnLoader
|
|
57
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module Marty
|
|
2
|
+
module LazyColumnLoader
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
module ClassMethods
|
|
6
|
+
def lazy_load(*columns)
|
|
7
|
+
return unless table_exists?
|
|
8
|
+
columns = columns.collect(&:to_s)
|
|
9
|
+
exclude_columns_from_default_scope columns
|
|
10
|
+
define_lazy_accessors_for columns
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
def exclude_columns_from_default_scope(columns)
|
|
15
|
+
default_scope select((
|
|
16
|
+
column_names - columns).map {
|
|
17
|
+
|column_name|
|
|
18
|
+
"#{table_name}.#{column_name}"
|
|
19
|
+
})
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def define_lazy_accessors_for(columns)
|
|
23
|
+
columns.each { |column| define_lazy_accessor_for column }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def define_lazy_accessor_for(column)
|
|
27
|
+
define_method column do
|
|
28
|
+
unless has_attribute?(column)
|
|
29
|
+
changes_before_reload = self.changes.clone
|
|
30
|
+
self.reload
|
|
31
|
+
changes_before_reload.each{|attribute_name, values|
|
|
32
|
+
self.send("#{attribute_name}=", values[1])}
|
|
33
|
+
end
|
|
34
|
+
read_attribute column
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
if ActiveRecord::Base.respond_to?(:lazy_load)
|
|
42
|
+
$stderr.puts "ERROR: Method `.lazy_load` already defined in " +
|
|
43
|
+
"`ActiveRecord::Base`. This is incompatible with LazyColumnLoader " +
|
|
44
|
+
"and the module will be disabled."
|
|
45
|
+
else
|
|
46
|
+
ActiveRecord::Base.send :include, Marty::LazyColumnLoader
|
|
47
|
+
end
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
require 'mcfly'
|
|
2
|
+
|
|
3
|
+
module Mcfly
|
|
4
|
+
module Model
|
|
5
|
+
|
|
6
|
+
def self.included(base)
|
|
7
|
+
base.send :extend, ClassMethods
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
module ClassMethods
|
|
11
|
+
def clear_lookup_cache!
|
|
12
|
+
@LOOKUP_CACHE.clear if @LOOKUP_CACHE
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
# Implements a VERY HACKY class-based caching mechanism for
|
|
16
|
+
# database lookup results. Issues include: cached values are
|
|
17
|
+
# ActiveRecord objects. Not sure if these should be shared
|
|
18
|
+
# across connections. Query results can potentially be very
|
|
19
|
+
# large lists which we simply count as one item in the cache.
|
|
20
|
+
# Caching mechanism will result in large processes. Caches are
|
|
21
|
+
# not sharable across different Ruby processes.
|
|
22
|
+
def cached_delorean_fn(name, options = {}, &block)
|
|
23
|
+
@LOOKUP_CACHE ||= {}
|
|
24
|
+
|
|
25
|
+
delorean_fn(name, options) do |ts, *args|
|
|
26
|
+
cache_key = [name, ts] + args.map{ |a|
|
|
27
|
+
a.is_a?(ActiveRecord::Base) ? a.id : a
|
|
28
|
+
} unless Mcfly.is_infinity(ts)
|
|
29
|
+
|
|
30
|
+
next @LOOKUP_CACHE[cache_key] if
|
|
31
|
+
cache_key && @LOOKUP_CACHE.has_key?(cache_key)
|
|
32
|
+
|
|
33
|
+
res = block.call(ts, *args)
|
|
34
|
+
|
|
35
|
+
if cache_key
|
|
36
|
+
# Cache has >1000 items, clear out the oldest 200. FIXME:
|
|
37
|
+
# hard-coded, should be configurable. Cache
|
|
38
|
+
# size/invalidation should be per lookup and not class.
|
|
39
|
+
# We're invalidating cache items simply based on age and
|
|
40
|
+
# not usage. This is faster but not as fair.
|
|
41
|
+
if @LOOKUP_CACHE.count > 1000
|
|
42
|
+
@LOOKUP_CACHE.keys[0..200].each{|k| @LOOKUP_CACHE.delete(k)}
|
|
43
|
+
end
|
|
44
|
+
@LOOKUP_CACHE[cache_key] = res
|
|
45
|
+
|
|
46
|
+
# Since we're caching this object and don't want anyone
|
|
47
|
+
# changing it. FIXME: ideally should freeze this object
|
|
48
|
+
# recursively.
|
|
49
|
+
res.freeze unless res.is_a?(ActiveRecord::Relation)
|
|
50
|
+
end
|
|
51
|
+
res
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# FIXME: duplicate code from Mcfly's mcfly_lookup.
|
|
56
|
+
def cached_mcfly_lookup(name, options = {}, &block)
|
|
57
|
+
cached_delorean_fn(name, options) do |ts, *args|
|
|
58
|
+
raise "time cannot be nil" if ts.nil?
|
|
59
|
+
|
|
60
|
+
ts = Mcfly.normalize_infinity(ts)
|
|
61
|
+
|
|
62
|
+
where("obsoleted_dt >= ? AND created_dt < ?", ts, ts).scoping do
|
|
63
|
+
block.call(ts, *args)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# FIXME: for validation purposes, this mechanism should make
|
|
69
|
+
# sure that the allable attrs are not required.
|
|
70
|
+
def gen_mcfly_lookup(name, attrs, options={})
|
|
71
|
+
raise "bad options" unless options.is_a?(Hash)
|
|
72
|
+
|
|
73
|
+
# FIXME: mode should be sent later, not as a part of
|
|
74
|
+
# gen_mcfly_lookup. i.e. we just generate the search and the
|
|
75
|
+
# mode is applied at runtime by delorean code. That would
|
|
76
|
+
# allow lookups to be used in either mode dynamically.
|
|
77
|
+
mode = options.fetch(:mode, :first)
|
|
78
|
+
|
|
79
|
+
assoc = Set.new(self.reflect_on_all_associations.map(&:name))
|
|
80
|
+
attr_names = attrs.keys
|
|
81
|
+
|
|
82
|
+
allables = attrs.select {|k, v| v}
|
|
83
|
+
|
|
84
|
+
order = allables.keys.reverse.map { |k|
|
|
85
|
+
k = "#{k}_id" if assoc.member?(k)
|
|
86
|
+
"#{k} NULLS LAST"
|
|
87
|
+
}.join(", ")
|
|
88
|
+
|
|
89
|
+
qstr = attrs.map {|k, v|
|
|
90
|
+
k = "#{k}_id" if assoc.member?(k)
|
|
91
|
+
v ? "(#{k} = ? OR #{k} IS NULL)" : "(#{k} = ?)"
|
|
92
|
+
}.join(" AND ")
|
|
93
|
+
|
|
94
|
+
cached_mcfly_lookup(name, sig: attrs.length+1) do
|
|
95
|
+
|t, *attr_list|
|
|
96
|
+
|
|
97
|
+
attr_list_ids = attr_list.each_with_index.map {|x, i|
|
|
98
|
+
assoc.member?(attr_names[i]) ?
|
|
99
|
+
(attr_list[i] && attr_list[i].id) : attr_list[i]
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
q = self.where(qstr, *attr_list_ids)
|
|
103
|
+
q = q.order(order) unless order.empty?
|
|
104
|
+
mode = :to_a if mode == :all
|
|
105
|
+
mode ? q.send(mode) : q
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
######################################################################
|
|
110
|
+
|
|
111
|
+
# Generates categorization lookups. For instance,
|
|
112
|
+
# suppose we have the following in class GFee:
|
|
113
|
+
#
|
|
114
|
+
# gen_mcfly_lookup_cat :lookup_q,
|
|
115
|
+
# [:security_instrument,
|
|
116
|
+
# 'Gemini::SecurityInstrumentCategorization',
|
|
117
|
+
# :g_fee_category],
|
|
118
|
+
# {
|
|
119
|
+
# entity: true,
|
|
120
|
+
# security_instrument: true,
|
|
121
|
+
# coupon: true,
|
|
122
|
+
# },
|
|
123
|
+
# nil
|
|
124
|
+
|
|
125
|
+
# In the above case,
|
|
126
|
+
# rel_attr = :security_instrument
|
|
127
|
+
# cat_assoc_klass = Gemini::SecurityInstrumentCategorization
|
|
128
|
+
# cat_attr = :g_fee_category
|
|
129
|
+
# name = :lookup_q
|
|
130
|
+
# pc_name = :pc_lookup_q
|
|
131
|
+
# pc_attrs = {entity: true, security_instrument: true,
|
|
132
|
+
# g_fee_category: true, coupon: true}
|
|
133
|
+
|
|
134
|
+
def gen_mcfly_lookup_cat(name, catrel, attrs, options={})
|
|
135
|
+
rel_attr, cat_assoc_name, cat_attr = catrel
|
|
136
|
+
|
|
137
|
+
raise "#{rel_attr} should be mapped in attrs" if
|
|
138
|
+
attrs[rel_attr].nil?
|
|
139
|
+
|
|
140
|
+
cat_assoc_klass = cat_assoc_name.constantize
|
|
141
|
+
|
|
142
|
+
raise "need lookup method on #{cat_assoc_klass}" unless
|
|
143
|
+
cat_assoc_klass.respond_to? :lookup
|
|
144
|
+
|
|
145
|
+
# replace rel_attr with cat_attr in attrs
|
|
146
|
+
pc_attrs = attrs.each_with_object({}) {|(k, v), h|
|
|
147
|
+
h[k == rel_attr ? cat_attr : k] = v
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
pc_name = "pc_#{name}".to_sym
|
|
151
|
+
gen_mcfly_lookup(pc_name, pc_attrs, options)
|
|
152
|
+
|
|
153
|
+
lpi = attrs.keys.index rel_attr
|
|
154
|
+
|
|
155
|
+
raise "should not include #{cat_attr}" if
|
|
156
|
+
attrs.member?(cat_attr)
|
|
157
|
+
|
|
158
|
+
raise "need #{rel_attr} argument" unless lpi
|
|
159
|
+
|
|
160
|
+
delorean_fn(name, sig: attrs.length+1) do |ts, *args|
|
|
161
|
+
# Example: rel is a Gemini::SecurityInstrument instance.
|
|
162
|
+
rel = args[lpi]
|
|
163
|
+
raise "#{rel_attr} can't be nil" unless rel
|
|
164
|
+
|
|
165
|
+
# Assumes there's a mcfly :lookup function on
|
|
166
|
+
# cat_assoc_klass.
|
|
167
|
+
categorizing_obj = cat_assoc_klass.lookup(ts, rel)
|
|
168
|
+
raise "no categorization #{cat_assoc_klass} for #{rel}" unless
|
|
169
|
+
categorizing_obj
|
|
170
|
+
|
|
171
|
+
pc = categorizing_obj.send(cat_attr)
|
|
172
|
+
raise ("#{categorizing_obj} must have assoc." +
|
|
173
|
+
" #{cat_attr}/#{rel.inspect}") unless pc
|
|
174
|
+
|
|
175
|
+
args[lpi] = pc
|
|
176
|
+
self.send(pc_name, ts, *args)
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
module Mcfly::Controller
|
|
185
|
+
# define mcfly user to be Flowscape's current_user.
|
|
186
|
+
def user_for_mcfly
|
|
187
|
+
find_current_user rescue nil
|
|
188
|
+
end
|
|
189
|
+
end
|