marty 0.5.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (345) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +84 -0
  4. data/Rakefile +29 -0
  5. data/app/assets/javascripts/marty/application.js +15 -0
  6. data/app/assets/stylesheets/marty/application.css +13 -0
  7. data/app/components/marty/api_auth_view.rb +32 -0
  8. data/app/components/marty/auth_app.rb +55 -0
  9. data/app/components/marty/auth_app.rb~ +51 -0
  10. data/app/components/marty/auth_app/javascripts/auth_app.js +91 -0
  11. data/app/components/marty/auth_app/javascripts/auth_app.js~ +91 -0
  12. data/app/components/marty/cm_form_panel.rb~ +5 -0
  13. data/app/components/marty/cm_grid_panel.rb~ +35 -0
  14. data/app/components/marty/data_import_view.rb~ +142 -0
  15. data/app/components/marty/extras/layout.rb +46 -0
  16. data/app/components/marty/extras/layout.rb~ +46 -0
  17. data/app/components/marty/extras/misc.rb +18 -0
  18. data/app/components/marty/form.rb +6 -0
  19. data/app/components/marty/grid.rb +45 -0
  20. data/app/components/marty/grid_append_only.rb +12 -0
  21. data/app/components/marty/import_type_view.rb +53 -0
  22. data/app/components/marty/live_search_grid_panel.rb +46 -0
  23. data/app/components/marty/live_search_grid_panel.rb~ +49 -0
  24. data/app/components/marty/main_auth_app.rb +269 -0
  25. data/app/components/marty/main_auth_app.rb~ +238 -0
  26. data/app/components/marty/mcfly_grid_panel.rb +62 -0
  27. data/app/components/marty/mcfly_grid_panel.rb~ +80 -0
  28. data/app/components/marty/new_posting_form.rb +46 -0
  29. data/app/components/marty/new_posting_form.rb~ +46 -0
  30. data/app/components/marty/new_posting_window.rb +21 -0
  31. data/app/components/marty/new_posting_window.rb~ +21 -0
  32. data/app/components/marty/panel.rb +12 -0
  33. data/app/components/marty/pivot_grid.rb +52 -0
  34. data/app/components/marty/pivot_grid/endpoints.rb +45 -0
  35. data/app/components/marty/pivot_grid/javascripts/extensions.js +150 -0
  36. data/app/components/marty/pivot_grid/javascripts/pivot_grid.js +86 -0
  37. data/app/components/marty/pivot_grid/services.rb +44 -0
  38. data/app/components/marty/posting_grid.rb +139 -0
  39. data/app/components/marty/posting_grid.rb~ +140 -0
  40. data/app/components/marty/posting_window.rb +27 -0
  41. data/app/components/marty/promise_view.rb +177 -0
  42. data/app/components/marty/promise_view.rb~ +157 -0
  43. data/app/components/marty/promise_view/stylesheets/promise_view.css +26 -0
  44. data/app/components/marty/promise_view/stylesheets/promise_view.css~ +15 -0
  45. data/app/components/marty/report_form.rb +225 -0
  46. data/app/components/marty/report_form.rb~ +217 -0
  47. data/app/components/marty/report_select.rb +145 -0
  48. data/app/components/marty/report_select.rb~ +133 -0
  49. data/app/components/marty/reporting.rb +39 -0
  50. data/app/components/marty/reporting.rb~ +39 -0
  51. data/app/components/marty/script_detail.rb~ +430 -0
  52. data/app/components/marty/script_form.rb +233 -0
  53. data/app/components/marty/script_form.rb~ +233 -0
  54. data/app/components/marty/script_form/javascripts/Ext.ux.form.field.CodeMirror.js +698 -0
  55. data/app/components/marty/script_form/javascripts/Ext.ux.form.field.CodeMirror.js~ +909 -0
  56. data/app/components/marty/script_form/javascripts/codemirror.js +3130 -0
  57. data/app/components/marty/script_form/javascripts/mode/clike/clike.js +284 -0
  58. data/app/components/marty/script_form/javascripts/mode/clike/index.html +102 -0
  59. data/app/components/marty/script_form/javascripts/mode/clike/scala.html +766 -0
  60. data/app/components/marty/script_form/javascripts/mode/clojure/clojure.js +206 -0
  61. data/app/components/marty/script_form/javascripts/mode/clojure/index.html +67 -0
  62. data/app/components/marty/script_form/javascripts/mode/coffeescript/LICENSE +22 -0
  63. data/app/components/marty/script_form/javascripts/mode/coffeescript/coffeescript.js +346 -0
  64. data/app/components/marty/script_form/javascripts/mode/coffeescript/index.html +728 -0
  65. data/app/components/marty/script_form/javascripts/mode/commonlisp/commonlisp.js +101 -0
  66. data/app/components/marty/script_form/javascripts/mode/commonlisp/index.html +165 -0
  67. data/app/components/marty/script_form/javascripts/mode/css/css.js +448 -0
  68. data/app/components/marty/script_form/javascripts/mode/css/index.html +58 -0
  69. data/app/components/marty/script_form/javascripts/mode/css/test.js +501 -0
  70. data/app/components/marty/script_form/javascripts/mode/delorean/delorean.js +189 -0
  71. data/app/components/marty/script_form/javascripts/mode/diff/diff.js +32 -0
  72. data/app/components/marty/script_form/javascripts/mode/diff/index.html +105 -0
  73. data/app/components/marty/script_form/javascripts/mode/ecl/ecl.js +203 -0
  74. data/app/components/marty/script_form/javascripts/mode/ecl/index.html +42 -0
  75. data/app/components/marty/script_form/javascripts/mode/erlang/erlang.js +463 -0
  76. data/app/components/marty/script_form/javascripts/mode/erlang/index.html +63 -0
  77. data/app/components/marty/script_form/javascripts/mode/gfm/gfm.js +150 -0
  78. data/app/components/marty/script_form/javascripts/mode/gfm/index.html +48 -0
  79. data/app/components/marty/script_form/javascripts/mode/go/go.js +170 -0
  80. data/app/components/marty/script_form/javascripts/mode/go/index.html +73 -0
  81. data/app/components/marty/script_form/javascripts/mode/groovy/groovy.js +210 -0
  82. data/app/components/marty/script_form/javascripts/mode/groovy/index.html +72 -0
  83. data/app/components/marty/script_form/javascripts/mode/haskell/haskell.js +242 -0
  84. data/app/components/marty/script_form/javascripts/mode/haskell/index.html +61 -0
  85. data/app/components/marty/script_form/javascripts/mode/haxe/haxe.js +429 -0
  86. data/app/components/marty/script_form/javascripts/mode/haxe/index.html +91 -0
  87. data/app/components/marty/script_form/javascripts/mode/htmlembedded/htmlembedded.js +72 -0
  88. data/app/components/marty/script_form/javascripts/mode/htmlembedded/index.html +50 -0
  89. data/app/components/marty/script_form/javascripts/mode/htmlmixed/htmlmixed.js +84 -0
  90. data/app/components/marty/script_form/javascripts/mode/htmlmixed/index.html +52 -0
  91. data/app/components/marty/script_form/javascripts/mode/javascript/index.html +78 -0
  92. data/app/components/marty/script_form/javascripts/mode/javascript/javascript.js +361 -0
  93. data/app/components/marty/script_form/javascripts/mode/jinja2/index.html +38 -0
  94. data/app/components/marty/script_form/javascripts/mode/jinja2/jinja2.js +42 -0
  95. data/app/components/marty/script_form/javascripts/mode/less/index.html +740 -0
  96. data/app/components/marty/script_form/javascripts/mode/less/less.js +266 -0
  97. data/app/components/marty/script_form/javascripts/mode/lua/index.html +73 -0
  98. data/app/components/marty/script_form/javascripts/mode/lua/lua.js +140 -0
  99. data/app/components/marty/script_form/javascripts/mode/markdown/index.html +343 -0
  100. data/app/components/marty/script_form/javascripts/mode/markdown/markdown.js +382 -0
  101. data/app/components/marty/script_form/javascripts/mode/markdown/test.js +1084 -0
  102. data/app/components/marty/script_form/javascripts/mode/mysql/index.html +42 -0
  103. data/app/components/marty/script_form/javascripts/mode/mysql/mysql.js +186 -0
  104. data/app/components/marty/script_form/javascripts/mode/ntriples/index.html +33 -0
  105. data/app/components/marty/script_form/javascripts/mode/ntriples/ntriples.js +172 -0
  106. data/app/components/marty/script_form/javascripts/mode/ocaml/index.html +130 -0
  107. data/app/components/marty/script_form/javascripts/mode/ocaml/ocaml.js +114 -0
  108. data/app/components/marty/script_form/javascripts/mode/pascal/LICENSE +7 -0
  109. data/app/components/marty/script_form/javascripts/mode/pascal/index.html +49 -0
  110. data/app/components/marty/script_form/javascripts/mode/pascal/pascal.js +94 -0
  111. data/app/components/marty/script_form/javascripts/mode/perl/LICENSE +19 -0
  112. data/app/components/marty/script_form/javascripts/mode/perl/index.html +63 -0
  113. data/app/components/marty/script_form/javascripts/mode/perl/perl.js +816 -0
  114. data/app/components/marty/script_form/javascripts/mode/php/index.html +49 -0
  115. data/app/components/marty/script_form/javascripts/mode/php/php.js +148 -0
  116. data/app/components/marty/script_form/javascripts/mode/pig/index.html +43 -0
  117. data/app/components/marty/script_form/javascripts/mode/pig/pig.js +172 -0
  118. data/app/components/marty/script_form/javascripts/mode/plsql/index.html +63 -0
  119. data/app/components/marty/script_form/javascripts/mode/plsql/plsql.js +217 -0
  120. data/app/components/marty/script_form/javascripts/mode/properties/index.html +41 -0
  121. data/app/components/marty/script_form/javascripts/mode/properties/properties.js +63 -0
  122. data/app/components/marty/script_form/javascripts/mode/python/LICENSE.txt +21 -0
  123. data/app/components/marty/script_form/javascripts/mode/python/index.html +123 -0
  124. data/app/components/marty/script_form/javascripts/mode/python/python.js +338 -0
  125. data/app/components/marty/script_form/javascripts/mode/r/LICENSE +24 -0
  126. data/app/components/marty/script_form/javascripts/mode/r/index.html +74 -0
  127. data/app/components/marty/script_form/javascripts/mode/r/r.js +141 -0
  128. data/app/components/marty/script_form/javascripts/mode/rpm/changes/changes.js +19 -0
  129. data/app/components/marty/script_form/javascripts/mode/rpm/changes/index.html +54 -0
  130. data/app/components/marty/script_form/javascripts/mode/rpm/spec/index.html +100 -0
  131. data/app/components/marty/script_form/javascripts/mode/rpm/spec/spec.css +5 -0
  132. data/app/components/marty/script_form/javascripts/mode/rpm/spec/spec.js +66 -0
  133. data/app/components/marty/script_form/javascripts/mode/rst/index.html +526 -0
  134. data/app/components/marty/script_form/javascripts/mode/rst/rst.js +326 -0
  135. data/app/components/marty/script_form/javascripts/mode/ruby/LICENSE +24 -0
  136. data/app/components/marty/script_form/javascripts/mode/ruby/index.html +172 -0
  137. data/app/components/marty/script_form/javascripts/mode/ruby/ruby.js +195 -0
  138. data/app/components/marty/script_form/javascripts/mode/rust/index.html +49 -0
  139. data/app/components/marty/script_form/javascripts/mode/rust/rust.js +432 -0
  140. data/app/components/marty/script_form/javascripts/mode/scheme/index.html +65 -0
  141. data/app/components/marty/script_form/javascripts/mode/scheme/scheme.js +230 -0
  142. data/app/components/marty/script_form/javascripts/mode/shell/index.html +50 -0
  143. data/app/components/marty/script_form/javascripts/mode/shell/shell.js +118 -0
  144. data/app/components/marty/script_form/javascripts/mode/sieve/LICENSE +23 -0
  145. data/app/components/marty/script_form/javascripts/mode/sieve/index.html +81 -0
  146. data/app/components/marty/script_form/javascripts/mode/sieve/sieve.js +156 -0
  147. data/app/components/marty/script_form/javascripts/mode/smalltalk/index.html +56 -0
  148. data/app/components/marty/script_form/javascripts/mode/smalltalk/smalltalk.js +139 -0
  149. data/app/components/marty/script_form/javascripts/mode/smarty/index.html +83 -0
  150. data/app/components/marty/script_form/javascripts/mode/smarty/smarty.js +148 -0
  151. data/app/components/marty/script_form/javascripts/mode/sparql/index.html +41 -0
  152. data/app/components/marty/script_form/javascripts/mode/sparql/sparql.js +143 -0
  153. data/app/components/marty/script_form/javascripts/mode/stex/index.html +98 -0
  154. data/app/components/marty/script_form/javascripts/mode/stex/stex.js +182 -0
  155. data/app/components/marty/script_form/javascripts/mode/stex/test.js +343 -0
  156. data/app/components/marty/script_form/javascripts/mode/tiddlywiki/index.html +141 -0
  157. data/app/components/marty/script_form/javascripts/mode/tiddlywiki/tiddlywiki.css +14 -0
  158. data/app/components/marty/script_form/javascripts/mode/tiddlywiki/tiddlywiki.js +384 -0
  159. data/app/components/marty/script_form/javascripts/mode/tiki/index.html +83 -0
  160. data/app/components/marty/script_form/javascripts/mode/tiki/tiki.css +26 -0
  161. data/app/components/marty/script_form/javascripts/mode/tiki/tiki.js +309 -0
  162. data/app/components/marty/script_form/javascripts/mode/vb/LICENSE.txt +21 -0
  163. data/app/components/marty/script_form/javascripts/mode/vb/index.html +89 -0
  164. data/app/components/marty/script_form/javascripts/mode/vb/vb.js +260 -0
  165. data/app/components/marty/script_form/javascripts/mode/vbscript/index.html +43 -0
  166. data/app/components/marty/script_form/javascripts/mode/vbscript/vbscript.js +26 -0
  167. data/app/components/marty/script_form/javascripts/mode/velocity/index.html +104 -0
  168. data/app/components/marty/script_form/javascripts/mode/velocity/velocity.js +146 -0
  169. data/app/components/marty/script_form/javascripts/mode/verilog/index.html +211 -0
  170. data/app/components/marty/script_form/javascripts/mode/verilog/verilog.js +194 -0
  171. data/app/components/marty/script_form/javascripts/mode/xml/index.html +45 -0
  172. data/app/components/marty/script_form/javascripts/mode/xml/xml.js +318 -0
  173. data/app/components/marty/script_form/javascripts/mode/xquery/LICENSE +20 -0
  174. data/app/components/marty/script_form/javascripts/mode/xquery/index.html +223 -0
  175. data/app/components/marty/script_form/javascripts/mode/xquery/test/index.html +27 -0
  176. data/app/components/marty/script_form/javascripts/mode/xquery/test/testBase.js +42 -0
  177. data/app/components/marty/script_form/javascripts/mode/xquery/test/testEmptySequenceKeyword.js +16 -0
  178. data/app/components/marty/script_form/javascripts/mode/xquery/test/testMultiAttr.js +16 -0
  179. data/app/components/marty/script_form/javascripts/mode/xquery/test/testNamespaces.js +91 -0
  180. data/app/components/marty/script_form/javascripts/mode/xquery/test/testProcessingInstructions.js +16 -0
  181. data/app/components/marty/script_form/javascripts/mode/xquery/test/testQuotes.js +19 -0
  182. data/app/components/marty/script_form/javascripts/mode/xquery/xquery.js +451 -0
  183. data/app/components/marty/script_form/javascripts/mode/yaml/index.html +68 -0
  184. data/app/components/marty/script_form/javascripts/mode/yaml/yaml.js +95 -0
  185. data/app/components/marty/script_form/javascripts/util/closetag.js +164 -0
  186. data/app/components/marty/script_form/javascripts/util/dialog.css +27 -0
  187. data/app/components/marty/script_form/javascripts/util/dialog.js +70 -0
  188. data/app/components/marty/script_form/javascripts/util/foldcode.js +196 -0
  189. data/app/components/marty/script_form/javascripts/util/formatting.js +193 -0
  190. data/app/components/marty/script_form/javascripts/util/javascript-hint.js +134 -0
  191. data/app/components/marty/script_form/javascripts/util/loadmode.js +51 -0
  192. data/app/components/marty/script_form/javascripts/util/match-highlighter.js +44 -0
  193. data/app/components/marty/script_form/javascripts/util/multiplex.js +77 -0
  194. data/app/components/marty/script_form/javascripts/util/overlay.js +54 -0
  195. data/app/components/marty/script_form/javascripts/util/pig-hint.js +123 -0
  196. data/app/components/marty/script_form/javascripts/util/runmode-standalone.js +90 -0
  197. data/app/components/marty/script_form/javascripts/util/runmode.js +53 -0
  198. data/app/components/marty/script_form/javascripts/util/search.js +118 -0
  199. data/app/components/marty/script_form/javascripts/util/searchcursor.js +119 -0
  200. data/app/components/marty/script_form/javascripts/util/simple-hint.css +16 -0
  201. data/app/components/marty/script_form/javascripts/util/simple-hint.js +97 -0
  202. data/app/components/marty/script_form/javascripts/util/xml-hint.js +137 -0
  203. data/app/components/marty/script_form/stylesheets/codemirror.css +172 -0
  204. data/app/components/marty/script_form/stylesheets/delorean.css +10 -0
  205. data/app/components/marty/script_form/stylesheets/theme/ambiance.css +81 -0
  206. data/app/components/marty/script_form/stylesheets/theme/blackboard.css +25 -0
  207. data/app/components/marty/script_form/stylesheets/theme/cobalt.css +18 -0
  208. data/app/components/marty/script_form/stylesheets/theme/eclipse.css +25 -0
  209. data/app/components/marty/script_form/stylesheets/theme/elegant.css +10 -0
  210. data/app/components/marty/script_form/stylesheets/theme/erlang-dark.css +21 -0
  211. data/app/components/marty/script_form/stylesheets/theme/lesser-dark.css +44 -0
  212. data/app/components/marty/script_form/stylesheets/theme/monokai.css +28 -0
  213. data/app/components/marty/script_form/stylesheets/theme/neat.css +9 -0
  214. data/app/components/marty/script_form/stylesheets/theme/night.css +21 -0
  215. data/app/components/marty/script_form/stylesheets/theme/rubyblue.css +21 -0
  216. data/app/components/marty/script_form/stylesheets/theme/vibrant-ink.css +27 -0
  217. data/app/components/marty/script_form/stylesheets/theme/xq-dark.css +46 -0
  218. data/app/components/marty/script_grid.rb +104 -0
  219. data/app/components/marty/script_grid.rb~ +99 -0
  220. data/app/components/marty/script_tester.rb +114 -0
  221. data/app/components/marty/script_tester.rb~ +213 -0
  222. data/app/components/marty/scripting.rb +132 -0
  223. data/app/components/marty/scripting.rb~ +124 -0
  224. data/app/components/marty/select_report.rb~ +143 -0
  225. data/app/components/marty/simple_app.rb +97 -0
  226. data/app/components/marty/simple_app.rb~ +101 -0
  227. data/app/components/marty/simple_app/javascripts/simple_app.js +50 -0
  228. data/app/components/marty/simple_app/javascripts/statusbar_ext.js +8 -0
  229. data/app/components/marty/tag_grid.rb +83 -0
  230. data/app/components/marty/tag_grid.rb~ +89 -0
  231. data/app/components/marty/tree_panel.rb~ +256 -0
  232. data/app/components/marty/tree_panel/javascripts/tree_panel.js~ +317 -0
  233. data/app/components/marty/user_pivot.rb +128 -0
  234. data/app/components/marty/user_view.rb +181 -0
  235. data/app/components/marty/user_view.rb~ +188 -0
  236. data/app/controllers/marty/application_controller.rb +124 -0
  237. data/app/controllers/marty/application_controller.rb~ +133 -0
  238. data/app/controllers/marty/components_controller.rb +41 -0
  239. data/app/controllers/marty/components_controller.rb~ +37 -0
  240. data/app/controllers/marty/job_controller.rb +28 -0
  241. data/app/controllers/marty/job_controller.rb~ +28 -0
  242. data/app/controllers/marty/rpc_controller.rb +64 -0
  243. data/app/controllers/marty/rpc_controller.rb~ +61 -0
  244. data/app/helpers/marty/application_helper.rb +4 -0
  245. data/app/helpers/marty/script_set.rb +57 -0
  246. data/app/helpers/marty/script_set.rb~ +59 -0
  247. data/app/models/marty/api_auth.rb +44 -0
  248. data/app/models/marty/api_auth.rb~ +48 -0
  249. data/app/models/marty/base.rb +4 -0
  250. data/app/models/marty/data_change.rb +179 -0
  251. data/app/models/marty/data_change.rb~ +141 -0
  252. data/app/models/marty/enum.rb +22 -0
  253. data/app/models/marty/enum.rb~ +16 -0
  254. data/app/models/marty/import_type.rb +44 -0
  255. data/app/models/marty/import_type.rb~ +48 -0
  256. data/app/models/marty/poop.rb~ +169 -0
  257. data/app/models/marty/posting.rb +101 -0
  258. data/app/models/marty/posting.rb~ +86 -0
  259. data/app/models/marty/posting_type.rb +12 -0
  260. data/app/models/marty/posting_type.rb~ +21 -0
  261. data/app/models/marty/promise.rb +252 -0
  262. data/app/models/marty/promise.rb~ +196 -0
  263. data/app/models/marty/role.rb +6 -0
  264. data/app/models/marty/role.rb~ +10 -0
  265. data/app/models/marty/script.rb +144 -0
  266. data/app/models/marty/script.rb~ +62 -0
  267. data/app/models/marty/tag.rb +96 -0
  268. data/app/models/marty/tag.rb~ +91 -0
  269. data/app/models/marty/token.rb +30 -0
  270. data/app/models/marty/user.rb +146 -0
  271. data/app/models/marty/user.rb~ +148 -0
  272. data/app/models/marty/user_role.rb +7 -0
  273. data/app/models/marty/user_role.rb~ +13 -0
  274. data/app/views/layouts/marty/application.html.erb +12 -0
  275. data/app/views/layouts/marty/application.html.erb~ +11 -0
  276. data/config/locales/en.yml +134 -0
  277. data/config/routes.rb +6 -0
  278. data/config/routes.rb~ +10 -0
  279. data/db/migrate/001_create_marty_scripts.rb +14 -0
  280. data/db/migrate/003_create_marty_users.rb +12 -0
  281. data/db/migrate/004_create_marty_roles.rb +7 -0
  282. data/db/migrate/005_create_marty_user_roles.rb +14 -0
  283. data/db/migrate/006_create_marty_tokens.rb +14 -0
  284. data/db/migrate/008_create_marty_posting_types.rb +7 -0
  285. data/db/migrate/019_create_marty_postings.rb +18 -0
  286. data/db/migrate/019_create_marty_postings.rb~ +19 -0
  287. data/db/migrate/068_create_marty_import_types.rb +12 -0
  288. data/db/migrate/069_create_marty_import_synonyms.rb +15 -0
  289. data/db/migrate/070_create_versions.rb +18 -0
  290. data/db/migrate/071_add_object_changes_column_to_versions.rb +9 -0
  291. data/db/migrate/072_add_validation_function_to_import_types.rb +6 -0
  292. data/db/migrate/073_add_preprocess_function_to_import_types.rb +5 -0
  293. data/db/migrate/090_create_delayed_jobs.rb +22 -0
  294. data/db/migrate/091_create_marty_promises.rb +36 -0
  295. data/db/migrate/095_create_marty_tags.rb +14 -0
  296. data/db/migrate/095_create_marty_tags.rb~ +19 -0
  297. data/db/migrate/096_add_user_roles_to_import_types.rb +11 -0
  298. data/db/migrate/097_drop_versions.rb +9 -0
  299. data/db/migrate/098_create_marty_api_auths.rb +20 -0
  300. data/db/seeds.rb +48 -0
  301. data/lib/marty.rb +18 -0
  302. data/lib/marty.rb~ +13 -0
  303. data/lib/marty/content_handler.rb +97 -0
  304. data/lib/marty/content_handler.rb~ +93 -0
  305. data/lib/marty/data_conversion.rb +298 -0
  306. data/lib/marty/data_exporter.rb +150 -0
  307. data/lib/marty/data_exporter.rb~ +137 -0
  308. data/lib/marty/data_importer.rb +122 -0
  309. data/lib/marty/data_importer.rb~ +114 -0
  310. data/lib/marty/data_row_processor.rb~ +206 -0
  311. data/lib/marty/drop_folder_hook.rb~ +17 -0
  312. data/lib/marty/engine.rb +10 -0
  313. data/lib/marty/folder_hook.rb~ +9 -0
  314. data/lib/marty/lazy_column_loader.rb +57 -0
  315. data/lib/marty/lazy_column_loader.rb~ +47 -0
  316. data/lib/marty/mcfly_query.rb +189 -0
  317. data/lib/marty/mcfly_query.rb~ +188 -0
  318. data/lib/marty/migrations.rb +108 -0
  319. data/lib/marty/migrations.rb~ +65 -0
  320. data/lib/marty/monkey.rb +163 -0
  321. data/lib/marty/monkey.rb~ +160 -0
  322. data/lib/marty/permissions.rb +64 -0
  323. data/lib/marty/permissions.rb~ +69 -0
  324. data/lib/marty/promise.rb~ +41 -0
  325. data/lib/marty/promise_job.rb +123 -0
  326. data/lib/marty/promise_job.rb~ +121 -0
  327. data/lib/marty/promise_proxy.rb +94 -0
  328. data/lib/marty/promise_proxy.rb~ +69 -0
  329. data/lib/marty/railtie.rb +5 -0
  330. data/lib/marty/relation.rb +39 -0
  331. data/lib/marty/util.rb +110 -0
  332. data/lib/marty/util.rb~ +80 -0
  333. data/lib/marty/version.rb +3 -0
  334. data/lib/marty/version.rb~ +3 -0
  335. data/lib/marty/xl.rb +527 -0
  336. data/lib/marty/xl.rb~ +526 -0
  337. data/lib/pyxll/README.txt +19 -0
  338. data/lib/pyxll/README.txt~ +16 -0
  339. data/lib/pyxll/gemini.py +155 -0
  340. data/lib/pyxll/gemini.py~ +110 -0
  341. data/lib/pyxll/pyxll.cfg +12 -0
  342. data/lib/pyxll/pyxll.cfg~ +12 -0
  343. data/lib/pyxll/sample.xlsx +0 -0
  344. data/lib/tasks/marty_tasks.rake +37 -0
  345. 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
@@ -0,0 +1,10 @@
1
+ module Marty
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Marty
4
+
5
+ # generators add rspec tests
6
+ config.generators do |g|
7
+ g.test_framework :rspec, :view_specs => false
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,9 @@
1
+ class Marty::FolderHook
2
+ def initialize
3
+ end
4
+
5
+ def run(res)
6
+ p 'H.'*10, res
7
+ end
8
+
9
+ end
@@ -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