datashift 0.16.0 → 0.40.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (422) hide show
  1. checksums.yaml +4 -4
  2. data/{LICENSE.txt → LICENSE} +0 -0
  3. data/Rakefile +1 -20
  4. data/datashift.thor +125 -0
  5. data/lib/applications/apache_poi_extensions.rb +21 -52
  6. data/lib/applications/excel.rb +64 -57
  7. data/lib/applications/hssf_row_extensions.rb +66 -0
  8. data/lib/applications/jexcel_file.rb +99 -95
  9. data/lib/applications/jexcel_file_extensions.rb +76 -83
  10. data/lib/applications/jruby/word.rb +36 -36
  11. data/lib/applications/ruby_poi_translations.rb +34 -32
  12. data/lib/applications/spreadsheet_extensions.rb +21 -19
  13. data/lib/datashift.rb +49 -59
  14. data/lib/datashift/binder.rb +217 -0
  15. data/lib/datashift/column_packer.rb +21 -72
  16. data/lib/datashift/configuration.rb +317 -0
  17. data/lib/datashift/context_factory.rb +88 -0
  18. data/lib/datashift/core_ext/array.rb +15 -0
  19. data/lib/datashift/core_ext/csv_ext.rb +46 -0
  20. data/lib/datashift/core_ext/string.rb +49 -0
  21. data/lib/datashift/core_ext/to_b.rb +11 -0
  22. data/lib/datashift/delimiters.rb +55 -61
  23. data/lib/datashift/doc_context.rb +137 -0
  24. data/lib/datashift/excel_base.rb +93 -81
  25. data/lib/datashift/exceptions.rb +30 -28
  26. data/lib/datashift/file_definitions.rb +44 -39
  27. data/lib/datashift/guards.rb +5 -5
  28. data/lib/datashift/header.rb +25 -0
  29. data/lib/datashift/headers.rb +94 -0
  30. data/lib/datashift/inbound_data/column.rb +44 -0
  31. data/lib/datashift/inbound_data/lookup_support.rb +33 -0
  32. data/lib/datashift/inbound_data/method_binding.rb +139 -0
  33. data/lib/datashift/load_object.rb +37 -12
  34. data/lib/datashift/logging.rb +54 -27
  35. data/lib/datashift/mandatory.rb +39 -0
  36. data/lib/datashift/mapping/data_flow_schema.rb +198 -0
  37. data/lib/datashift/{model_mapper.rb → mapping/mapper_utils.rb} +30 -10
  38. data/lib/datashift/model_methods/catalogue.rb +183 -0
  39. data/lib/datashift/model_methods/collection.rb +140 -0
  40. data/lib/datashift/model_methods/model_method.rb +162 -0
  41. data/lib/datashift/model_methods/model_methods_manager.rb +76 -0
  42. data/lib/datashift/model_methods/operator.rb +62 -0
  43. data/lib/datashift/node_collection.rb +26 -0
  44. data/lib/datashift/node_context.rb +68 -0
  45. data/lib/datashift/populator.rb +308 -282
  46. data/lib/datashift/progress_monitor.rb +91 -0
  47. data/lib/datashift/querying.rb +110 -52
  48. data/lib/datashift/templates/import_export_config.erb +55 -0
  49. data/lib/datashift/transformation/factory.rb +219 -0
  50. data/lib/datashift/transformation/remove.rb +44 -0
  51. data/lib/datashift/version.rb +3 -0
  52. data/lib/exporters/configuration.rb +84 -0
  53. data/lib/exporters/csv_exporter.rb +54 -52
  54. data/lib/exporters/excel_exporter.rb +80 -61
  55. data/lib/exporters/exporter_base.rb +8 -8
  56. data/lib/generators/config_generator.rb +218 -0
  57. data/lib/generators/csv_generator.rb +13 -70
  58. data/lib/generators/excel_generator.rb +23 -111
  59. data/lib/generators/generator_base.rb +15 -70
  60. data/lib/loaders/configuration.rb +90 -0
  61. data/lib/loaders/csv_loader.rb +63 -101
  62. data/lib/loaders/excel_loader.rb +71 -156
  63. data/lib/loaders/failure_data.rb +40 -0
  64. data/lib/loaders/file_loader.rb +16 -0
  65. data/lib/loaders/loader_base.rb +82 -410
  66. data/lib/loaders/loader_factory.rb +42 -0
  67. data/lib/loaders/paperclip/attachment_loader.rb +157 -140
  68. data/lib/loaders/paperclip/datashift_paperclip.rb +18 -35
  69. data/lib/loaders/paperclip/image_loading.rb +40 -35
  70. data/lib/loaders/reporters/basic_stdout_reporter.rb +40 -0
  71. data/lib/loaders/reporters/reporter.rb +26 -0
  72. data/lib/tasks/config.thor +65 -0
  73. data/{tasks → lib/tasks}/config/seed_fu_product_template.erb +0 -0
  74. data/{tasks → lib/tasks}/config/tidy_config.txt +0 -0
  75. data/lib/tasks/export.thor +192 -0
  76. data/lib/tasks/generate.thor +190 -0
  77. data/lib/tasks/import.thor +142 -0
  78. data/lib/{thor → tasks}/paperclip.thor +69 -69
  79. data/{tasks → lib/tasks/to_convert_to_thor}/db_tasks.rake +20 -20
  80. data/lib/tasks/tools.thor +109 -0
  81. data/spec/MissingAttachmentRecords/DEMO_001_ror_bag.jpeg +0 -0
  82. data/spec/MissingAttachmentRecords/DEMO_002_Powerstation.jpeg +0 -0
  83. data/spec/MissingAttachmentRecords/DEMO_003_ror_mug.jpeg +0 -0
  84. data/spec/MissingAttachmentRecords/DEMO_004_ror_ringer.jpeg +0 -0
  85. data/spec/datashift/binder_spec.rb +266 -0
  86. data/spec/datashift/config_generator_spec.rb +186 -0
  87. data/spec/datashift/configuration.rb +66 -0
  88. data/spec/datashift/context_factory_spec.rb +63 -0
  89. data/spec/datashift/data_flow_schema_spec.rb +150 -0
  90. data/spec/datashift/datashift_spec.rb +52 -0
  91. data/spec/datashift/excel_base_spec.rb +57 -0
  92. data/spec/datashift/excel_spec.rb +188 -0
  93. data/spec/datashift/failure_data_spec.rb +27 -0
  94. data/spec/{file_definitions.rb → datashift/file_definitions.rb} +9 -10
  95. data/spec/datashift/headers_spec.rb +56 -0
  96. data/spec/datashift/inbound_data_spec.rb +47 -0
  97. data/spec/datashift/mapper_utils_spec.rb +38 -0
  98. data/spec/datashift/method_binding_spec.rb +60 -0
  99. data/spec/datashift/model_method_spec.rb +109 -0
  100. data/spec/datashift/model_methods_catalogue.rb +111 -0
  101. data/spec/datashift/model_methods_collection_spec.rb +138 -0
  102. data/spec/datashift/model_methods_manager_spec.rb +329 -0
  103. data/spec/datashift/populator_spec.rb +117 -0
  104. data/spec/datashift/thor_spec.rb +314 -0
  105. data/spec/datashift/transformation/factory_spec.rb +195 -0
  106. data/spec/datashift/transformation/transformer_remove_spec.rb +43 -0
  107. data/spec/dummy/Gemfile +53 -0
  108. data/spec/dummy/Gemfile.lock +197 -0
  109. data/spec/dummy/README.rdoc +28 -0
  110. data/spec/dummy/Rakefile +6 -0
  111. data/spec/dummy/app/assets/javascripts/application.js +16 -0
  112. data/spec/dummy/app/assets/javascripts/categories.js +2 -0
  113. data/spec/dummy/app/assets/javascripts/digitals.js +2 -0
  114. data/spec/dummy/app/assets/javascripts/empties.js +2 -0
  115. data/spec/dummy/app/assets/javascripts/loader_releases.js +2 -0
  116. data/spec/dummy/app/assets/javascripts/long_and_complex_table_linked_to_versions.js +2 -0
  117. data/spec/dummy/app/assets/javascripts/milestones.js +2 -0
  118. data/spec/dummy/app/assets/javascripts/owners.js +2 -0
  119. data/spec/dummy/app/assets/javascripts/projects.js +2 -0
  120. data/spec/dummy/app/assets/javascripts/users.js +2 -0
  121. data/spec/dummy/app/assets/javascripts/versions.js +2 -0
  122. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  123. data/spec/dummy/app/assets/stylesheets/categories.css +4 -0
  124. data/spec/dummy/app/assets/stylesheets/digitals.css +4 -0
  125. data/spec/dummy/app/assets/stylesheets/empties.css +4 -0
  126. data/spec/dummy/app/assets/stylesheets/loader_releases.css +4 -0
  127. data/spec/dummy/app/assets/stylesheets/long_and_complex_table_linked_to_versions.css +4 -0
  128. data/spec/dummy/app/assets/stylesheets/milestones.css +4 -0
  129. data/spec/dummy/app/assets/stylesheets/owners.css +4 -0
  130. data/spec/dummy/app/assets/stylesheets/projects.css +4 -0
  131. data/spec/dummy/app/assets/stylesheets/scaffold.css +56 -0
  132. data/spec/dummy/app/assets/stylesheets/users.css +4 -0
  133. data/spec/dummy/app/assets/stylesheets/versions.css +4 -0
  134. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  135. data/spec/dummy/app/controllers/categories_controller.rb +58 -0
  136. data/spec/dummy/app/controllers/digitals_controller.rb +58 -0
  137. data/spec/dummy/app/controllers/empties_controller.rb +58 -0
  138. data/spec/dummy/app/controllers/loader_releases_controller.rb +58 -0
  139. data/spec/dummy/app/controllers/long_and_complex_table_linked_to_versions_controller.rb +58 -0
  140. data/spec/dummy/app/controllers/milestones_controller.rb +58 -0
  141. data/spec/dummy/app/controllers/owners_controller.rb +58 -0
  142. data/spec/dummy/app/controllers/projects_controller.rb +58 -0
  143. data/spec/dummy/app/controllers/users_controller.rb +58 -0
  144. data/spec/dummy/app/controllers/versions_controller.rb +58 -0
  145. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  146. data/spec/dummy/app/helpers/categories_helper.rb +2 -0
  147. data/spec/dummy/app/helpers/digitals_helper.rb +2 -0
  148. data/spec/dummy/app/helpers/empties_helper.rb +2 -0
  149. data/spec/dummy/app/helpers/loader_releases_helper.rb +2 -0
  150. data/spec/dummy/app/helpers/long_and_complex_table_linked_to_versions_helper.rb +2 -0
  151. data/spec/dummy/app/helpers/milestones_helper.rb +2 -0
  152. data/spec/dummy/app/helpers/owners_helper.rb +2 -0
  153. data/spec/dummy/app/helpers/projects_helper.rb +2 -0
  154. data/spec/dummy/app/helpers/users_helper.rb +2 -0
  155. data/spec/dummy/app/helpers/versions_helper.rb +2 -0
  156. data/spec/dummy/app/models/category.rb +6 -0
  157. data/spec/dummy/app/models/digital.rb +22 -0
  158. data/spec/dummy/app/models/empty.rb +2 -0
  159. data/spec/dummy/app/models/loader_release.rb +10 -0
  160. data/spec/dummy/app/models/long_and_complex_table_linked_to_version.rb +6 -0
  161. data/spec/dummy/app/models/milestone.rb +15 -0
  162. data/spec/dummy/app/models/owner.rb +13 -0
  163. data/spec/dummy/app/models/project.rb +53 -0
  164. data/spec/dummy/app/models/user.rb +5 -0
  165. data/spec/dummy/app/models/version.rb +7 -0
  166. data/spec/dummy/app/views/categories/_form.html.erb +17 -0
  167. data/spec/dummy/app/views/categories/edit.html.erb +6 -0
  168. data/spec/dummy/app/views/categories/index.html.erb +25 -0
  169. data/spec/dummy/app/views/categories/new.html.erb +5 -0
  170. data/spec/dummy/app/views/categories/show.html.erb +4 -0
  171. data/spec/dummy/app/views/digitals/_form.html.erb +17 -0
  172. data/spec/dummy/app/views/digitals/edit.html.erb +6 -0
  173. data/spec/dummy/app/views/digitals/index.html.erb +25 -0
  174. data/spec/dummy/app/views/digitals/new.html.erb +5 -0
  175. data/spec/dummy/app/views/digitals/show.html.erb +4 -0
  176. data/spec/dummy/app/views/empties/_form.html.erb +17 -0
  177. data/spec/dummy/app/views/empties/edit.html.erb +6 -0
  178. data/spec/dummy/app/views/empties/index.html.erb +25 -0
  179. data/spec/dummy/app/views/empties/new.html.erb +5 -0
  180. data/spec/dummy/app/views/empties/show.html.erb +4 -0
  181. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  182. data/spec/dummy/app/views/loader_releases/_form.html.erb +17 -0
  183. data/spec/dummy/app/views/loader_releases/edit.html.erb +6 -0
  184. data/spec/dummy/app/views/loader_releases/index.html.erb +25 -0
  185. data/spec/dummy/app/views/loader_releases/new.html.erb +5 -0
  186. data/spec/dummy/app/views/loader_releases/show.html.erb +4 -0
  187. data/spec/dummy/app/views/long_and_complex_table_linked_to_versions/_form.html.erb +17 -0
  188. data/spec/dummy/app/views/long_and_complex_table_linked_to_versions/edit.html.erb +6 -0
  189. data/spec/dummy/app/views/long_and_complex_table_linked_to_versions/index.html.erb +25 -0
  190. data/spec/dummy/app/views/long_and_complex_table_linked_to_versions/new.html.erb +5 -0
  191. data/spec/dummy/app/views/long_and_complex_table_linked_to_versions/show.html.erb +4 -0
  192. data/spec/dummy/app/views/milestones/_form.html.erb +17 -0
  193. data/spec/dummy/app/views/milestones/edit.html.erb +6 -0
  194. data/spec/dummy/app/views/milestones/index.html.erb +25 -0
  195. data/spec/dummy/app/views/milestones/new.html.erb +5 -0
  196. data/spec/dummy/app/views/milestones/show.html.erb +4 -0
  197. data/spec/dummy/app/views/owners/_form.html.erb +17 -0
  198. data/spec/dummy/app/views/owners/edit.html.erb +6 -0
  199. data/spec/dummy/app/views/owners/index.html.erb +25 -0
  200. data/spec/dummy/app/views/owners/new.html.erb +5 -0
  201. data/spec/dummy/app/views/owners/show.html.erb +4 -0
  202. data/spec/dummy/app/views/projects/_form.html.erb +17 -0
  203. data/spec/dummy/app/views/projects/edit.html.erb +6 -0
  204. data/spec/dummy/app/views/projects/index.html.erb +25 -0
  205. data/spec/dummy/app/views/projects/new.html.erb +5 -0
  206. data/spec/dummy/app/views/projects/show.html.erb +4 -0
  207. data/spec/dummy/app/views/users/_form.html.erb +17 -0
  208. data/spec/dummy/app/views/users/edit.html.erb +6 -0
  209. data/spec/dummy/app/views/users/index.html.erb +25 -0
  210. data/spec/dummy/app/views/users/new.html.erb +5 -0
  211. data/spec/dummy/app/views/users/show.html.erb +4 -0
  212. data/spec/dummy/app/views/versions/_form.html.erb +17 -0
  213. data/spec/dummy/app/views/versions/edit.html.erb +6 -0
  214. data/spec/dummy/app/views/versions/index.html.erb +25 -0
  215. data/spec/dummy/app/views/versions/new.html.erb +5 -0
  216. data/spec/dummy/app/views/versions/show.html.erb +4 -0
  217. data/spec/dummy/bin/bundle +3 -0
  218. data/spec/dummy/bin/rails +9 -0
  219. data/spec/dummy/bin/rake +9 -0
  220. data/spec/dummy/bin/setup +29 -0
  221. data/spec/dummy/bin/spring +16 -0
  222. data/spec/dummy/config.ru +4 -0
  223. data/spec/dummy/config/application.rb +26 -0
  224. data/spec/dummy/config/boot.rb +3 -0
  225. data/spec/dummy/config/database.yml +25 -0
  226. data/spec/dummy/config/environment.rb +5 -0
  227. data/spec/dummy/config/environments/development.rb +41 -0
  228. data/spec/dummy/config/environments/production.rb +79 -0
  229. data/spec/dummy/config/environments/test.rb +42 -0
  230. data/spec/dummy/config/initializers/assets.rb +11 -0
  231. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  232. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  233. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  234. data/spec/dummy/config/initializers/inflections.rb +16 -0
  235. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  236. data/spec/dummy/config/initializers/session_store.rb +3 -0
  237. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  238. data/spec/dummy/config/locales/en.yml +23 -0
  239. data/spec/dummy/config/routes.rb +76 -0
  240. data/spec/dummy/config/secrets.yml +22 -0
  241. data/spec/dummy/db/development.sqlite3 +0 -0
  242. data/spec/dummy/db/migrate/20110803201325_create_test_bed.rb +98 -0
  243. data/spec/dummy/db/migrate/20121009161700_add_digitals.rb +24 -0
  244. data/spec/dummy/db/migrate/20161005123106_create_digitals.rb +8 -0
  245. data/spec/dummy/db/migrate/20161005123106_create_long_and_complex_table_linked_to_versions.rb +8 -0
  246. data/spec/dummy/db/migrate/20161005123107_create_loader_releases.rb +8 -0
  247. data/spec/dummy/db/migrate/20161005123108_create_owners.rb +8 -0
  248. data/spec/dummy/db/migrate/20161005123109_create_empties.rb +8 -0
  249. data/spec/dummy/db/migrate/20161005123110_create_projects.rb +8 -0
  250. data/spec/dummy/db/migrate/20161005123111_create_users.rb +8 -0
  251. data/spec/dummy/db/migrate/20161005123111_create_versions.rb +8 -0
  252. data/spec/dummy/db/migrate/20161005123112_create_milestones.rb +8 -0
  253. data/spec/dummy/db/migrate/20161005123113_create_categories.rb +8 -0
  254. data/spec/dummy/db/schema.rb +93 -0
  255. data/spec/dummy/db/seeds.rb +9 -0
  256. data/spec/dummy/db/test.sqlite3 +0 -0
  257. data/spec/dummy/log/test.log +69 -0
  258. data/spec/dummy/public/404.html +67 -0
  259. data/spec/dummy/public/422.html +67 -0
  260. data/spec/dummy/public/500.html +66 -0
  261. data/spec/dummy/public/favicon.ico +0 -0
  262. data/spec/dummy/public/robots.txt +5 -0
  263. data/spec/dummy/sandbox_example.thor +4 -0
  264. data/spec/dummy/test/controllers/categories_controller_test.rb +49 -0
  265. data/spec/dummy/test/controllers/digitals_controller_test.rb +49 -0
  266. data/spec/dummy/test/controllers/empties_controller_test.rb +49 -0
  267. data/spec/dummy/test/controllers/loader_releases_controller_test.rb +49 -0
  268. data/spec/dummy/test/controllers/long_and_complex_table_linked_to_versions_controller_test.rb +49 -0
  269. data/spec/dummy/test/controllers/milestones_controller_test.rb +49 -0
  270. data/spec/dummy/test/controllers/owners_controller_test.rb +49 -0
  271. data/spec/dummy/test/controllers/projects_controller_test.rb +49 -0
  272. data/spec/dummy/test/controllers/users_controller_test.rb +49 -0
  273. data/spec/dummy/test/controllers/versions_controller_test.rb +49 -0
  274. data/spec/dummy/test/factories/categories.rb +5 -0
  275. data/spec/dummy/test/factories/digitals.rb +5 -0
  276. data/spec/dummy/test/factories/empties.rb +5 -0
  277. data/spec/dummy/test/factories/loader_releases.rb +5 -0
  278. data/spec/dummy/test/factories/long_and_complex_table_linked_to_versions.rb +5 -0
  279. data/spec/dummy/test/factories/milestones.rb +5 -0
  280. data/spec/dummy/test/factories/owners.rb +5 -0
  281. data/spec/dummy/test/factories/projects.rb +5 -0
  282. data/spec/dummy/test/factories/users.rb +5 -0
  283. data/spec/dummy/test/factories/versions.rb +5 -0
  284. data/spec/dummy/test/models/category_test.rb +7 -0
  285. data/spec/dummy/test/models/digital_test.rb +7 -0
  286. data/spec/dummy/test/models/empty_test.rb +7 -0
  287. data/spec/dummy/test/models/loader_release_test.rb +7 -0
  288. data/spec/dummy/test/models/long_and_complex_table_linked_to_version_test.rb +7 -0
  289. data/spec/dummy/test/models/milestone_test.rb +7 -0
  290. data/spec/dummy/test/models/owner_test.rb +7 -0
  291. data/spec/dummy/test/models/project_test.rb +7 -0
  292. data/spec/dummy/test/models/user_test.rb +7 -0
  293. data/spec/dummy/test/models/version_test.rb +7 -0
  294. data/spec/dummy/test/test_helper.rb +10 -0
  295. data/spec/exporters/csv_exporter_spec.rb +240 -0
  296. data/spec/exporters/csv_generator_spec.rb +139 -0
  297. data/spec/exporters/excel_exporter_spec.rb +193 -0
  298. data/spec/exporters/excel_generator_spec.rb +181 -0
  299. data/spec/exporters/generator_base_spec.rb +45 -0
  300. data/spec/factories/categories.rb +7 -0
  301. data/spec/factories/factories.rb +18 -0
  302. data/spec/factories/milestone.rb +16 -0
  303. data/spec/factories/projects.rb +41 -0
  304. data/spec/fixtures/BadAssociationName.xls +0 -0
  305. data/spec/fixtures/DemoNegativeTesting.xls +0 -0
  306. data/spec/fixtures/ProjectConfiguration.yml +18 -0
  307. data/spec/fixtures/ProjectsMultiCategories.xls +0 -0
  308. data/spec/fixtures/ProjectsMultiCategoriesHeaderLookup.xls +0 -0
  309. data/spec/fixtures/ProjectsSingleCategories.xls +0 -0
  310. data/spec/fixtures/ProjectsSingleCategories.xlsx +0 -0
  311. data/spec/fixtures/SimpleProjects.xls +0 -0
  312. data/spec/fixtures/config/database.yml +28 -0
  313. data/spec/fixtures/csv/BadAssociationName.csv +6 -0
  314. data/spec/fixtures/csv/DemoNegativeTesting.csv +6 -0
  315. data/spec/fixtures/csv/ProjectsMultiCategories.csv +5 -0
  316. data/spec/fixtures/csv/ProjectsMultiCategoriesHeaderLookup.csv +5 -0
  317. data/spec/fixtures/csv/ProjectsSingleCategories.csv +5 -0
  318. data/spec/fixtures/csv/SimpleProjects.csv +4 -0
  319. data/spec/fixtures/db/migrate/20110803201325_create_test_bed.rb +98 -0
  320. data/spec/fixtures/db/migrate/20121009161700_add_digitals.rb +24 -0
  321. data/spec/fixtures/db/seeds.rb +9 -0
  322. data/spec/fixtures/images/DEMO_001_ror_bag.jpeg +0 -0
  323. data/spec/fixtures/images/DEMO_002_Powerstation.jpeg +0 -0
  324. data/spec/fixtures/images/DEMO_003_ror_mug.jpeg +0 -0
  325. data/spec/fixtures/images/DEMO_004_ror_ringer.jpeg +0 -0
  326. data/spec/fixtures/load_datashift.thor +3 -0
  327. data/spec/fixtures/models/category.rb +6 -0
  328. data/spec/fixtures/models/digital.rb +22 -0
  329. data/spec/fixtures/models/empty.rb +2 -0
  330. data/spec/fixtures/models/loader_release.rb +10 -0
  331. data/spec/fixtures/models/long_and_complex_table_linked_to_version.rb +6 -0
  332. data/spec/fixtures/models/milestone.rb +15 -0
  333. data/spec/fixtures/models/owner.rb +13 -0
  334. data/spec/fixtures/models/project.rb +53 -0
  335. data/spec/fixtures/models/user.rb +5 -0
  336. data/spec/fixtures/models/version.rb +7 -0
  337. data/spec/fixtures/results/exp_project_assoc_headers.xls +0 -0
  338. data/spec/fixtures/results/exp_project_collection_spec.csv +2 -0
  339. data/spec/fixtures/results/exp_project_export.xls +0 -0
  340. data/spec/fixtures/results/exp_project_first_export.xls +0 -0
  341. data/spec/fixtures/results/exp_project_plus_assoc.xls +0 -0
  342. data/spec/fixtures/results/exp_project_plus_assoc_export_spec.csv +9 -0
  343. data/spec/fixtures/results/gen_project_plus_assoc_template.xls +0 -0
  344. data/spec/fixtures/results/gen_project_plus_some_assoc_template.xls +0 -0
  345. data/spec/fixtures/results/gen_project_template.xls +0 -0
  346. data/spec/fixtures/results/project_and_assoc_in_hash_export.xls +0 -0
  347. data/spec/fixtures/results/project_and_assoc_in_json_export.csv +9 -0
  348. data/spec/fixtures/results/project_and_assoc_in_json_export.xls +0 -0
  349. data/spec/fixtures/results/project_export_spec_with_custom_delim_,.csv +2 -0
  350. data/spec/fixtures/results/project_export_spec_with_custom_delim_/302/243.csv +2 -0
  351. data/spec/fixtures/results/project_export_spec_with_custom_delim_/302/247.csv +2 -0
  352. data/spec/fixtures/results/project_plus_assoc_template.csv +1 -0
  353. data/spec/fixtures/results/project_plus_some_assoc_template.csv +1 -0
  354. data/spec/fixtures/results/project_remove_export_spec.csv +2 -0
  355. data/spec/fixtures/results/project_template.csv +1 -0
  356. data/spec/fixtures/results/project_with_methods_export_spec.csv +2 -0
  357. data/spec/fixtures/results/thor_spec_gen_project.csv +1 -0
  358. data/spec/fixtures/sandbox_example.thor +4 -0
  359. data/spec/fixtures/simple_export_spec.xls +0 -0
  360. data/spec/fixtures/simple_template_spec.xls +0 -0
  361. data/spec/fixtures/test_model_defs.rb +7 -0
  362. data/spec/loaders/csv_loader_spec.rb +206 -0
  363. data/spec/loaders/data_flow_excel_loader_spec.rb +290 -0
  364. data/spec/loaders/excel_loader_failures_spec.rb +67 -0
  365. data/spec/loaders/excel_loader_spec.rb +294 -0
  366. data/spec/loaders/loader_base_spec.rb +29 -0
  367. data/spec/loaders/paperclip_loader_spec.rb +106 -0
  368. data/spec/log/datashift.log +14930 -0
  369. data/spec/private/digitals/1/DEMO_003_ror_mug.jpeg +0 -0
  370. data/spec/private/digitals/2/DEMO_002_Powerstation.jpeg +0 -0
  371. data/spec/private/digitals/3/DEMO_004_ror_ringer.jpeg +0 -0
  372. data/spec/private/digitals/4/DEMO_001_ror_bag.jpeg +0 -0
  373. data/spec/spec_helper.rb +26 -230
  374. data/spec/support/clear_and_manage_contexts.rb +25 -0
  375. data/spec/support/database_cleaner.rb +32 -0
  376. data/spec/support/datashift_test_helpers.rb +153 -0
  377. data/spec/support/files_paths_helper.rb +13 -0
  378. data/spec/support/fixtures/results/mapping_template.yaml +15 -0
  379. data/spec/support/sandbox.rb +136 -0
  380. metadata +804 -85
  381. data/README.markdown +0 -274
  382. data/README.rdoc +0 -19
  383. data/VERSION +0 -1
  384. data/datashift.gemspec +0 -48
  385. data/lib/applications/jruby/old_pre_proxy_jexcel_file.rb +0 -437
  386. data/lib/datashift/data_transforms.rb +0 -83
  387. data/lib/datashift/mapping_file_definitions.rb +0 -88
  388. data/lib/datashift/mapping_service.rb +0 -91
  389. data/lib/datashift/method_detail.rb +0 -165
  390. data/lib/datashift/method_details_manager.rb +0 -95
  391. data/lib/datashift/method_dictionary.rb +0 -281
  392. data/lib/datashift/method_mapper.rb +0 -174
  393. data/lib/datashift/thor_base.rb +0 -38
  394. data/lib/generators/mapping_generator.rb +0 -112
  395. data/lib/helpers/core_ext/csv_file.rb +0 -33
  396. data/lib/helpers/core_ext/to_b.rb +0 -24
  397. data/lib/loaders/reporter.rb +0 -58
  398. data/lib/thor/export.thor +0 -175
  399. data/lib/thor/generate.thor +0 -191
  400. data/lib/thor/import.thor +0 -110
  401. data/lib/thor/mapping.thor +0 -65
  402. data/lib/thor/tools.thor +0 -84
  403. data/spec/Gemfile +0 -31
  404. data/spec/Gemfile.lock +0 -134
  405. data/spec/csv_exporter_spec.rb +0 -144
  406. data/spec/csv_generator_spec.rb +0 -159
  407. data/spec/csv_loader_spec.rb +0 -212
  408. data/spec/datashift_spec.rb +0 -55
  409. data/spec/excel_exporter_spec.rb +0 -199
  410. data/spec/excel_generator_spec.rb +0 -203
  411. data/spec/excel_loader_spec.rb +0 -237
  412. data/spec/excel_spec.rb +0 -203
  413. data/spec/loader_base_spec.rb +0 -166
  414. data/spec/mapping_spec.rb +0 -117
  415. data/spec/method_dictionary_spec.rb +0 -300
  416. data/spec/method_mapper_spec.rb +0 -100
  417. data/spec/model_mapper_spec.rb +0 -41
  418. data/spec/paperclip_loader_spec.rb +0 -92
  419. data/spec/populator_spec.rb +0 -128
  420. data/spec/thor_spec.rb +0 -90
  421. data/tasks/file_tasks.rake +0 -37
  422. data/tasks/word_to_seedfu.rake +0 -167
@@ -1,281 +0,0 @@
1
- # Copyright:: (c) Autotelik Media Ltd 2012
2
- # Author :: Tom Statter
3
- # Date :: Aug 2010
4
- # License:: MIT
5
- #
6
- # Details:: A cache type class that stores details of all possible associations on AR classes.
7
- #
8
- module DataShift
9
-
10
- class MethodDictionary
11
-
12
- include DataShift::Logging
13
- extend DataShift::Logging
14
-
15
- # Return true if dictionary has been populated for klass
16
- def self.for?(klass)
17
- any = has_many[klass] || belongs_to[klass] || has_one[klass] || assignments[klass]
18
- return any != nil
19
- end
20
-
21
- # Create simple picture of all the operator names for assignment available on an AR model,
22
- # grouped by type of association (includes belongs_to and has_many which provides both << and = )
23
- # Options:
24
- # :reload => clear caches and re-perform lookup
25
- # :instance_methods => if true include instance method type 'setters' as well as model's pure columns
26
- #
27
- def self.find_operators(klass, options = {} )
28
-
29
- raise "Cannot find operators supplied klass nil #{klass}" if(klass.nil?)
30
-
31
- logger.debug("MethodDictionary - building operators information for #{klass}")
32
-
33
- # Find the has_many associations which can be populated via <<
34
- if( options[:reload] || has_many[klass].nil? )
35
- has_many[klass] = klass.reflect_on_all_associations(:has_many).map { |i| i.name.to_s }
36
- klass.reflect_on_all_associations(:has_and_belongs_to_many).inject(has_many[klass]) { |x,i| x << i.name.to_s }
37
- end
38
-
39
- # Find the belongs_to associations which can be populated via Model.belongs_to_name = OtherArModelObject
40
- if( options[:reload] || belongs_to[klass].nil? )
41
- belongs_to[klass] = klass.reflect_on_all_associations(:belongs_to).map { |i| i.name.to_s }
42
- end
43
-
44
- # Find the has_one associations which can be populated via Model.has_one_name = OtherArModelObject
45
- if( options[:reload] || has_one[klass].nil? )
46
- has_one[klass] = klass.reflect_on_all_associations(:has_one).map { |i| i.name.to_s }
47
- end
48
-
49
- # Find the model's column associations which can be populated via xxxxxx= value
50
- # Note, not all reflections return method names in same style so we convert all to
51
- # the raw form i.e without the '=' for consistency
52
- if( options[:reload] || assignments[klass].nil? )
53
-
54
- assignments[klass] = klass.column_names
55
-
56
- # get into consistent format with other assignments names i.e remove the = for now
57
- assignments[klass] += setters(klass).map{|i| i.gsub(/=/, '')} if(options[:instance_methods])
58
-
59
- # Now remove all the associations
60
- assignments[klass] -= has_many[klass] if(has_many[klass])
61
- assignments[klass] -= belongs_to[klass] if(belongs_to[klass])
62
- assignments[klass] -= has_one[klass] if(has_one[klass])
63
-
64
- # TODO remove assignments with id
65
- # assignments => tax_id but already in belongs_to => tax
66
-
67
- assignments[klass].uniq!
68
-
69
- assignments[klass].each do |assign|
70
- column_types[klass] ||= {}
71
- column_def = klass.columns.find{ |col| col.name == assign }
72
- column_types[klass].merge!( assign => column_def) if column_def
73
- end
74
- end
75
- end
76
-
77
- def self.setters( klass )
78
-
79
- # N.B In 1.8 these return strings, in 1.9 symbols.
80
- # map everything to strings a
81
- #setters = klass.accessible_attributes.sort.collect( &:to_s )
82
-
83
- # remove methodsa that start with '_'
84
- @keep_only_pure_setters ||= Regexp.new(/^[a-zA-Z]\w+=/)
85
-
86
- setters = klass.instance_methods.grep(@keep_only_pure_setters).sort.collect( &:to_s )
87
- setters.uniq
88
- end
89
-
90
- def self.add( klass, operator, type = :assignment)
91
- method_details_mgr = get_method_details_mgr( klass )
92
- md = MethodDetail.new(operator, klass, operator, type)
93
- method_details_mgr << md
94
- return md
95
- end
96
-
97
- # Build a thorough and usable picture of the operators by building dictionary of our MethodDetail
98
- # objects which can be used to import/export data to objects of type 'klass'
99
- # Subsequent calls with same class will return existign mapping
100
- # To over ride this behaviour, supply :force => true to force regeneration
101
-
102
- def self.build_method_details( klass, options = {} )
103
-
104
- return method_details_mgrs[klass] if(method_details_mgrs[klass] && !options[:force])
105
-
106
- method_details_mgr = MethodDetailsManager.new( klass )
107
-
108
- method_details_mgrs[klass] = method_details_mgr
109
-
110
- assignments_for(klass).each do |n|
111
- method_details_mgr << MethodDetail.new(n, klass, n, :assignment, column_types[klass])
112
- end
113
-
114
- has_one_for(klass).each do |n|
115
- method_details_mgr << MethodDetail.new(n, klass, n, :has_one)
116
- end
117
-
118
- has_many_for(klass).each do |n|
119
- method_details_mgr << MethodDetail.new(n, klass, n, :has_many)
120
- end
121
-
122
- belongs_to_for(klass).each do |n|
123
- method_details_mgr << MethodDetail.new(n, klass, n, :belongs_to)
124
- end
125
-
126
- method_details_mgr
127
-
128
- end
129
-
130
- # TODO - check out regexp to do this work better plus Inflections ??
131
- # Want to be able to handle any of ["Count On hand", 'count_on_hand', "Count OnHand", "COUNT ONHand" etc]
132
- def self.substitutions(external_name)
133
- name = external_name.to_s
134
-
135
- [
136
- name.downcase,
137
- name.tableize,
138
- name.gsub(' ', '_'),
139
- name.gsub(' ', '_').downcase,
140
- name.gsub(/(\s+)/, '_').downcase,
141
- name.gsub(' ', ''),
142
- name.gsub(' ', '').downcase,
143
- name.gsub(' ', '_').underscore
144
- ]
145
- end
146
-
147
-
148
- # Dump out all available operators
149
- #
150
- def self.dump( klass )
151
- method_details_mgr = get_method_details_mgr( klass )
152
- #TODO
153
- end
154
-
155
-
156
- # For a client supplied name/header - find the operator i.e appropriate call + column type
157
- #
158
- # e.g Given users entry in spread sheet check for pluralization, missing underscores etc
159
- #
160
- # If not nil, returned method can be used directly in for example klass.new.send( call, .... )
161
- #
162
- def self.find_method_detail( klass, external_name, conditions = nil )
163
-
164
- method_details_mgr = get_method_details_mgr( klass )
165
-
166
- # first try for an exact match across all association types
167
- MethodDetail::supported_types_enum.each do |t|
168
- method_detail = method_details_mgr.find(external_name, t)
169
- return method_detail.clone if(method_detail)
170
- end
171
-
172
- # Now try various alternatives of the name
173
- substitutions(external_name).each do |n|
174
- # Try each association type, returning first that contains matching operator with name n
175
- MethodDetail::supported_types_enum.each do |t|
176
- method_detail = method_details_mgr.find(n, t)
177
- return method_detail.clone if(method_detail)
178
- end
179
- end
180
-
181
- nil
182
- end
183
-
184
- # Assignments can contain things like delegated methods, this returns a matching
185
- # method details only when a true database column
186
- def self.find_method_detail_if_column( klass, external_name )
187
-
188
- method_details_mgr = get_method_details_mgr( klass )
189
-
190
- # first try for an exact match across all association types
191
- MethodDetail::supported_types_enum.each do |t|
192
- method_detail = method_details_mgr.find(external_name, t)
193
- return method_detail.clone if(method_detail && method_detail.col_type)
194
- end
195
-
196
- # Now try various alternatives
197
- substitutions(external_name).each do |n|
198
- # Try each association type, returning first that contains matching operator with name n
199
- MethodDetail::supported_types_enum.each do |t|
200
- method_detail = method_details_mgr.find(n, t)
201
- return method_detail.clone if(method_detail && method_detail.col_type)
202
- end
203
- end
204
-
205
- nil
206
- end
207
-
208
-
209
- def self.clear
210
- belongs_to.clear
211
- has_many.clear
212
- assignments.clear
213
- column_types.clear
214
- has_one.clear
215
- method_details_mgrs.clear
216
- end
217
-
218
- def self.column_key(klass, column)
219
- "#{klass.name}:#{column}"
220
- end
221
-
222
- def self.get_method_details_mgr( klass )
223
- method_details_mgrs[klass] || MethodDetailsManager.new( klass )
224
- end
225
-
226
-
227
- # Store a Mgr per mapped klass
228
- def self.method_details_mgrs
229
- @method_details_mgrs ||= {}
230
- @method_details_mgrs
231
- end
232
-
233
- def self.belongs_to
234
- @belongs_to ||={}
235
- @belongs_to
236
- end
237
-
238
- def self.has_many
239
- @has_many ||= {}
240
- @has_many
241
- end
242
-
243
- def self.has_one
244
- @has_one ||= {}
245
- @has_one
246
- end
247
-
248
- def self.assignments
249
- @assignments ||= {}
250
- @assignments
251
- end
252
-
253
- def self.column_types
254
- @column_types ||= {}
255
- @column_types
256
- end
257
-
258
-
259
- def self.belongs_to_for(klass)
260
- belongs_to[klass] || []
261
- end
262
-
263
- def self.has_many_for(klass)
264
- has_many[klass] || []
265
- end
266
-
267
- def self.has_one_for(klass)
268
- has_one[klass] || []
269
- end
270
-
271
- def self.assignments_for(klass)
272
- assignments[klass] || []
273
- end
274
-
275
- def self.column_type_for(klass, column)
276
- column_types[klass] ? column_types[klass][column] : []
277
- end
278
-
279
- end
280
-
281
- end
@@ -1,174 +0,0 @@
1
- # Copyright:: (c) Autotelik Media Ltd 2011
2
- # Author :: Tom Statter
3
- # Date :: Aug 2010
4
- # License:: MIT
5
- #
6
- # Details:: A base class that stores details of all possible associations on AR classes and,
7
- # given user supplied class and name, attempts to find correct attribute/association.
8
- #
9
- # Derived classes define where the user supplied list of names originates from.
10
- #
11
- # Example usage, load from a spreadsheet where the column names are only
12
- # an approximation of the actual associations. Given a column heading of
13
- # 'Product Properties' on class Product, find_method_detail() would search AR model,
14
- # and return details of real has_many association 'product_properties'.
15
- #
16
- # This real association can then be used to send spreadsheet row data to the AR object.
17
- #
18
- module DataShift
19
-
20
- class MethodMapper
21
-
22
- include DataShift::Logging
23
-
24
- attr_accessor :method_details, :missing_methods
25
-
26
- def initialize
27
- @method_details = []
28
- end
29
-
30
- # Build complete picture of the methods whose names listed in columns
31
- # Handles method names as defined by a user, from spreadsheets or file headers where the names
32
- # specified may not be exactly as required e.g handles capitalisation, white space, _ etc
33
- #
34
- # The header can also contain the fields to use in lookups, separated with Delimiters ::column_delim
35
- # For example specify that lookups on has_one association called 'product', be performed using name'
36
- # product:name
37
- #
38
- # The header can also contain a default value for the lookup field, again separated with Delimiters ::column_delim
39
- #
40
- # For example specify lookups on assoc called 'user', be performed using 'email' == 'test@blah.com'
41
- #
42
- # user:email:test@blah.com
43
- #
44
- # Returns: Array of matching method_details, including nils for non matched items
45
- #
46
- # N.B Columns that could not be mapped are left in the array as NIL
47
- #
48
- # This is to support clients that need to map via the index on @method_details
49
- #
50
- # Other callers can simply call compact on the results if the index not important.
51
- #
52
- # The MethodDetails instance will contain a pointer to the column index from which it was mapped.
53
- #
54
- # Options:
55
- #
56
- # [:force_inclusion] : List of columns that do not map to any operator but should be included in processing.
57
- #
58
- # This provides the opportunity for loaders to provide specific methods to handle these fields
59
- # when no direct operator is available on the model or it's associations
60
- #
61
- # [:include_all] : Include all headers in processing - takes precedence of :force_inclusion
62
- #
63
- def map_inbound_headers_to_methods( klass, columns, options = {} )
64
-
65
- # If klass not in MethodDictionary yet, add to dictionary all possible operators on klass
66
- # which can be used to map headers and populate an object of type klass
67
- unless(MethodDictionary::for?(klass))
68
- DataShift::MethodDictionary.find_operators(klass)
69
-
70
- DataShift::MethodDictionary.build_method_details(klass)
71
- end
72
-
73
- mgr = DataShift::MethodDictionary.method_details_mgrs[klass]
74
-
75
- forced = [*options[:force_inclusion]].compact.collect { |f| f.to_s.downcase }
76
-
77
- @method_details, @missing_methods = [], []
78
-
79
- columns.each_with_index do |col_data, col_index|
80
-
81
- raw_col_data = col_data.to_s
82
-
83
- if(raw_col_data.nil? or raw_col_data.empty?)
84
- logger.warn("Column list contains empty or null column at index #{col_index}")
85
- @method_details << nil
86
- next
87
- end
88
-
89
- raw_col_name, where_field, where_value, *data = raw_col_data.split(Delimiters::column_delim)
90
-
91
- md = MethodDictionary::find_method_detail(klass, raw_col_name)
92
-
93
- if(md.nil?)
94
- if(options[:include_all] || forced.include?(raw_col_name.downcase))
95
- logger.debug("Operator #{raw_col_name} not found but forced inclusion operative")
96
- md = MethodDictionary::add(klass, raw_col_name)
97
- end
98
- end
99
-
100
- if(md)
101
-
102
- md.name = raw_col_name
103
- md.column_index = col_index
104
-
105
- # put data back as string for now - leave it to clients to decide what to do with it later
106
- Populator::set_header_default_data(md.operator, data.join(Delimiters::column_delim))
107
-
108
- if(where_field)
109
- logger.info("Lookup query field [#{where_field}] - specified for association #{md.operator}")
110
-
111
- md.find_by_value = where_value
112
-
113
- # Example :
114
- # Project:name:My Best Project
115
- # User (klass) has_one project (operator) lookup by name (find_by_operator) == 'My Best Project' (find_by_value)
116
- # User.project.where( :name => 'My Best Project')
117
-
118
- # check the finder method name is a valid field on the actual association class
119
-
120
- if(klass.reflect_on_association(md.operator) &&
121
- klass.reflect_on_association(md.operator).klass.new.respond_to?(where_field))
122
- md.find_by_operator = where_field
123
- logger.info("Complex Lookup specified for [#{md.operator}] : on field [#{md.find_by_operator}] (optional value [#{md.find_by_value}])")
124
- else
125
- logger.warn("Find by operator [#{where_field}] Not Found on association [#{md.operator}] on Class #{klass.name} (#{md.inspect})")
126
- logger.warn("Check column (#{md.column_index}) heading - e.g association field names are case sensitive")
127
- # TODO - maybe derived loaders etc want this data for another purpose - should we stash elsewhere ?
128
- end
129
- end
130
- else
131
- # TODO populate unmapped with a real MethodDetail that is 'null' and create is_nil
132
- logger.warn("No operator or association found for Header #{raw_col_name}")
133
- @missing_methods << raw_col_name
134
- end
135
-
136
- logger.debug("Column [#{col_data}] (#{col_index}) - mapped to :\n#{md.inspect}")
137
-
138
- @method_details << md
139
-
140
- end
141
-
142
- @method_details
143
- end
144
-
145
-
146
- # TODO populate unmapped with a real MethodDetail that is 'null' and create is_nil
147
- #
148
- # The raw client supplied names
149
- def method_names()
150
- @method_details.compact.collect( &:name )
151
- end
152
-
153
- # The true operator names discovered from model
154
- def operator_names()
155
- @method_details.compact.collect( &:operator )
156
- end
157
-
158
-
159
- # Returns true if discovered methods contain every operator in mandatory_list
160
- def contains_mandatory?( mandatory_list )
161
- a = [*mandatory_list].collect { |f| f.downcase }
162
- puts a.inspect
163
- b = operator_names.collect { |f| f.downcase }
164
- puts b.inspect
165
- (a - b).empty?
166
- end
167
-
168
- def missing_mandatory( mandatory_list )
169
- [ [*mandatory_list] - operator_names].flatten
170
- end
171
-
172
- end
173
-
174
- end