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
@@ -0,0 +1,91 @@
1
+ # Copyright:: (c) Autotelik Media Ltd 2016
2
+ # Author :: Tom Statter
3
+ # Date :: Dec 2016
4
+ # License:: MIT
5
+ #
6
+ # Details:: Store and report stats on the current load
7
+ #
8
+ module DataShift
9
+
10
+ class ProgressMonitor
11
+
12
+ include DataShift::Logging
13
+
14
+ # actual data rows/objects inbound
15
+ attr_accessor :processed_object_count
16
+ alias processed_inbound_count processed_object_count
17
+
18
+ # DB objects created, updated etc
19
+ attr_accessor :loaded_objects, :failed_objects
20
+
21
+ # Actual number of data rows processed
22
+ # Bearing in mind things like updates, these can be greater than loaded/failed objects
23
+ attr_accessor :success_inbound_count, :failed_inbound_count
24
+
25
+ attr_reader :current_status
26
+
27
+ def initialize
28
+ reset
29
+ end
30
+
31
+ def reset
32
+ @processed_object_count = 0
33
+ @loaded_objects = []
34
+ @failed_objects = []
35
+
36
+ @success_inbound_count = 0
37
+ @failed_inbound_count = 0
38
+
39
+ @current_status = :success
40
+ end
41
+
42
+ def start_monitoring
43
+ @current_status = :success
44
+ end
45
+
46
+ def success(reportable_object)
47
+ add_loaded_object(reportable_object)
48
+ end
49
+
50
+ # Loading failed. Store a failed object and if requested roll back (destroy) the current load object
51
+ # For use case where object saved early but subsequent required columns fail to process
52
+ # so the load object is invalid
53
+
54
+ def failure(failure_data)
55
+
56
+ @current_status = :failure
57
+
58
+ logger.error 'Failure(s) reported :'
59
+ [*failure_data.errors].each { |e| logger.error "\t#{e}" }
60
+
61
+ add_failed_object(failure_data)
62
+
63
+ failure_data.destroy_failed_object if(DataShift::Loaders::Configuration.call.destroy_on_failure)
64
+ end
65
+
66
+ def add_loaded_object(object)
67
+ @success_inbound_count += 1
68
+ @processed_object_count += 1
69
+
70
+ @loaded_objects << object.id unless object.nil? || @loaded_objects.include?(object)
71
+ end
72
+
73
+ def add_failed_object(object)
74
+ @failed_inbound_count += 1
75
+ @processed_object_count += 1
76
+
77
+ @failed_objects << object unless object.nil? || @failed_objects.include?(object)
78
+ end
79
+
80
+ # The database objects created or rejected
81
+
82
+ def loaded_count
83
+ loaded_objects.size
84
+ end
85
+
86
+ def failed_count
87
+ failed_objects.size
88
+ end
89
+
90
+ end
91
+ end
@@ -7,81 +7,130 @@
7
7
  # based on a method map and supplied value from a file - i.e a single column/row's string value.
8
8
  # Note that although a single column, the string can be formatted to contain multiple values.
9
9
  #
10
- # Tightly coupled with MethodMapper classes (in lib/engine) which contains full details of
10
+ # Tightly coupled with Binder classes (in lib/engine) which contains full details of
11
11
  # a file's column and it's correlated AR associations.
12
12
  #
13
13
  module DataShift
14
14
 
15
- require 'datashift/method_mapper'
15
+ require 'datashift/binder'
16
16
 
17
17
  module Querying
18
-
18
+
19
+ include DataShift::Logging
20
+ extend DataShift::Logging
21
+
22
+ include Delimiters
23
+ extend Delimiters
24
+
25
+ # Return arrays 'where' clause field(s), and the value(s) to search for
26
+ #
27
+ # If not contained within inbound_data, check the Inbound Column headings
28
+ #
29
+ # Where field embedded in row ,takes precedence over field in column heading
30
+ #
31
+ # Treat rest of the node as the value to use in the where clause e.g
32
+ # price:0.99 => Product.where( price: 0.99)
33
+ #
34
+ # Column headings will be used, if the row only contains data e.g
35
+ # 0.99
36
+ #
37
+ def self.where_field_and_values(method_binding, inbound_data)
38
+
39
+ part1, part2 = inbound_data.split(name_value_delim)
40
+
41
+ heading_lookups = method_binding.inbound_column.lookup_list
42
+
43
+ if (part1.nil? || part1.empty?) && (part2.nil? || part2.empty?)
44
+
45
+ # Column completely empty - check for lookup supplied via the
46
+ # inbound column headers/config
47
+
48
+ # TODO: - how best to support multipel lookup fields?
49
+ # part1 = heading_lookups.collect {|lookup| lookup.field }
50
+ part1 = heading_lookups.find_by_operator
51
+ part2 = heading_lookups.collect(&:value)
52
+
53
+ elsif part2.nil? || part2.empty?
54
+
55
+ # Only **value(s)** in column, so use field from header/config field
56
+
57
+ logger.debug("No part2e [#{part1}][#{part1.class}] - [#{part2}][#{part2.class}]")
58
+
59
+ part2 = part1.split(multi_value_delim)
60
+ part1 = method_binding.inbound_column.find_by_operator
61
+
62
+ else
63
+ part2 = part2.split(multi_value_delim)
64
+
65
+ end
66
+
67
+ logger.debug("Where clause [#{part1}][#{part1.class}] - [#{part2}][#{part2.class}]")
68
+
69
+ [part1, [*part2]]
70
+ end
71
+
19
72
  # Options:
20
- #
73
+ #
21
74
  # :case_sensitive : Default is a case insensitive lookup.
22
- # :use_like : Attempts a lookup using ike and x% rather than equality
75
+ # :use_like : Attempts a lookup using ike and x% rather than equality
23
76
  #
24
77
  def search_for_record(klazz, field, search_term, options = {})
25
-
78
+
26
79
  begin
27
-
28
- if(options[:case_sensitive])
29
- return klazz.send("find_by_#{field}", search_term)
30
- elsif(options[:use_like])
31
- return klazz.where("#{field} like ?", "#{search_term}%").first
32
- else
33
- return klazz.where("lower(#{field}) = ?", search_term.downcase).first
34
- end
35
-
80
+ return klazz.send("find_by_#{field}", search_term) if options[:case_sensitive]
81
+
82
+ return klazz.where("#{field} like ?", "#{search_term}%").first if options[:use_like]
83
+
84
+ return klazz.where("lower(#{field}) = ?", search_term.downcase).first
36
85
  rescue => e
37
- puts e.inspect
38
- logger.error("Exception attempting to find a record for [#{search_term}] on #{klazz}.#{field}")
39
- logger.error e.backtrace
86
+ logger.error("Querying - Failed to find a record for [#{search_term}] on #{klazz}.#{field}")
40
87
  logger.error e.inspect
88
+ logger.error e.backtrace.last
41
89
  end
42
-
90
+
43
91
  nil
44
92
  end
45
-
93
+
46
94
  # Find a record for model klazz, looking up on field containing search_terms
47
95
  # Responds to global Options :
48
- #
96
+ #
49
97
  # :add_prefix : Add a prefix to each search term
50
98
  # :case_sensitive : Default is a case insensitive lookup.
51
- # :use_like : Attempts a lookup using like and x% rather than equality
99
+ # :use_like : Attempts a lookup using like and x% rather than equality
52
100
  #
53
101
  # Returns nil if no record found
54
102
  def get_record_by(klazz, field, search_term, split_on = ' ', options = {})
55
-
103
+
104
+ split_on_prefix = options[:add_prefix]
105
+
106
+ find_search_term = split_on_prefix ? "#{split_on_prefix}#{search_term}" : search_term
107
+
108
+ logger.info("Scanning for record where #{klazz}.#{field} ~= #{find_search_term}")
109
+
56
110
  begin
57
-
58
- split_on_prefix = options[:add_prefix]
59
-
60
- z = (split_on_prefix) ? "#{split_on_prefix}#{search_term}": search_term
61
-
62
- logger.info("Scanning for record where #{klazz}.#{field} ~= #{z}")
63
-
64
- record = search_for_record(klazz, field, z)
65
-
66
- # try individual portions of search_term, front -> back i.e "A_B_C_D" => A, B, C etc
67
- search_term.split(split_on).each do |str|
68
- z = (split_on_prefix) ? "#{split_on_prefix}#{str}": str
69
- record = search_for_record(klazz, field, z, options)
70
- break if record
71
- end unless(record)
72
-
111
+
112
+ record = search_for_record(klazz, field, find_search_term)
113
+
114
+ unless record
115
+ logger.info("Nothing found - trying split file_name to terms on [#{split_on}]")
116
+
117
+ # try individual portions of search_term, front -> back i.e "A_B_C_D" => A, B, C etc
118
+ search_term.split(split_on).each do |str|
119
+ find_search_term = split_on_prefix ? "#{split_on_prefix}#{str}" : str
120
+ logger.info("Scanning by term for record where #{field} ~= #{find_search_term}")
121
+ record = search_for_record(klazz, field, find_search_term, options)
122
+ break if record
123
+ end
124
+ end
125
+
73
126
  # this time try incrementally scanning i.e "A_B_C_D" => A, A_B, A_B_C etc
74
- search_term.split(split_on).inject("") do |str, term|
75
- z = (split_on_prefix) ? "#{split_on_prefix}#{str}#{split_on}#{term}": "#{str}#{split_on}#{term}"
127
+ search_term.split(split_on).inject('') do |str, term|
128
+ z = split_on_prefix ? "#{split_on_prefix}#{str}#{split_on}#{term}" : "#{str}#{split_on}#{term}"
76
129
  record = search_for_record(klazz, field, z, options)
77
130
  break if record
78
131
  term
79
- end unless(record)
80
-
81
- if(record && record.respond_to?(field))
82
- logger.info("Record found for #{klazz}.#{field} : #{record.send(field)}" )
83
- end
84
-
132
+ end unless record
133
+
85
134
  return record
86
135
  rescue => e
87
136
  logger.error("Exception attempting to find a record for [#{search_term}] on #{klazz}.#{field}")
@@ -90,14 +139,23 @@ module DataShift
90
139
  return nil
91
140
  end
92
141
  end
93
-
142
+
94
143
  def get_record_by!(klazz, field, search_terms, split_on = ' ', options = {} )
95
144
  x = get_record_by(klazz, field, search_terms, split_on, options)
96
-
97
- raise RecordNotFound, "No #{klazz} record found for [#{search_terms}] on #{field}" unless(x)
98
-
145
+
146
+ raise RecordNotFound, "No #{klazz} record found for [#{search_terms}] on #{field}" unless x
147
+
99
148
  x
100
149
  end
150
+
151
+ def find_or_new( klass, condition_hash = {} )
152
+ records = klass.where(condition_hash).all
153
+
154
+ return records.first if records.any?
155
+
156
+ klass.new
157
+ end
158
+
101
159
  end
102
160
 
103
- end
161
+ end
@@ -0,0 +1,55 @@
1
+ # YAML Template for Datashift Import/Export Configuration
2
+ #
3
+ <%= @key -%>:
4
+ <%= @klass -%>:
5
+ defaults:
6
+ <%= "#<name>: <value>" if(@defaults.empty?) %>
7
+ <% @defaults.each do |k, v| -%>
8
+ <%= "#{k}: #{v}" %>
9
+ <% end %>
10
+
11
+ overrides:
12
+ <% if(@overrides.empty?) %>
13
+ <%= "#<name>: <value>" if(@overrides.empty?) %>
14
+ <% end %>
15
+ <% @overrides.each do |k, v| -%>
16
+ <% k %>: <% v %>
17
+ <% end -%>
18
+
19
+ # Expects a tuple (list with 2 entries), the rule and the replacement
20
+ substitutions:
21
+ <% if(@substitutions.empty?) %>
22
+ <%= "#- rule" %>
23
+ <%= "#- replacement" %>
24
+ <% end %>
25
+ <% @substitutions.each do |k, v| -%>
26
+ <% k %>:
27
+ - <% v.first %>
28
+ - <% v.last %>
29
+ <% end -%>
30
+
31
+ prefixes:
32
+ <%= "#<name>: <value>" if(@prefixs.empty?) %>
33
+ <% @prefixs.each do |k, v| -%>
34
+ <%= k %>: <%= v %>
35
+ <% end -%>
36
+
37
+ postfixes:
38
+ <%= " #<name>: <value>" if(@postfixs.empty?) %>
39
+ <% @postfixs.each do |k, v| -%>
40
+ <%= k %>: <%= v %>
41
+ <% end -%>
42
+
43
+ <% unless(@headers.empty?) %>
44
+ # Mappings between inbound column names and internal names
45
+ # are only required when datashift cannot guess the mapping itself
46
+ # It will automatically map headings like :
47
+ # 'Product properties' or 'Product_Properties', 'product Properties' etc to product_properties
48
+ nodes:
49
+ <% @headers.each_with_index do |s, i| %>
50
+ - <%= s %>:
51
+ heading:
52
+ source: <%= s %>
53
+ presentation: <%= s %>
54
+ <% end %>
55
+ <% end %>
@@ -0,0 +1,219 @@
1
+ # Copyright:: (c) Autotelik Media Ltd 2015
2
+ # Author :: Tom Statter
3
+ # License:: MIT
4
+ #
5
+ # Details:: Maps transformations to internal Class methods.
6
+ #
7
+ # Stores :
8
+ # substitutions
9
+ # over rides
10
+ # prefixes
11
+ # postfixes
12
+ #
13
+ # These are keyed on the associated method binding operator, which is
14
+ # essentially the method call/active record column on the class.
15
+ #
16
+ # Clients can decide exactly how these can be applied to incoming data.
17
+ #
18
+ # Usage::
19
+ #
20
+ # Provides a singleton instance of Transformations::Factory
21
+ # so you can specify additional transforms in .rb config as follows :
22
+ #
23
+ # IN : my_transformations.rb
24
+ #
25
+ # DataShift::Transformer.factory do |factory|
26
+ # factory.set_default_on(Project, 'value_as_string', 'default text' )
27
+ # end
28
+ #
29
+ # This global factory is automatically utilised by the default Populator
30
+ # during data load.
31
+ #
32
+ # If passed an optional locale, rules for other
33
+ # languages can be specified. If not specified, defaults to <tt>:en</tt>.
34
+ #
35
+ require 'thread_safe'
36
+ require 'active_support/inflector'
37
+
38
+ # Helper class
39
+ Struct.new('Substitution', :pattern, :replacement)
40
+
41
+ module DataShift
42
+
43
+ module Transformation
44
+
45
+ extend self
46
+
47
+ # Yields a singleton instance of Transformations::Factory
48
+ # so you can specify additional transforms in .rb config
49
+ # If passed an optional locale, rules for other
50
+ # languages can be specified. If not specified, defaults to <tt>:en</tt>.
51
+ #
52
+ # Only rules for English are provided.
53
+ #
54
+ def factory(locale = :en)
55
+ if block_given?
56
+ yield Factory.instance(locale)
57
+ else
58
+ Factory.instance(locale)
59
+ end
60
+ end
61
+
62
+ class Factory
63
+
64
+ TRANSFORMERS_HASH_INSTANCE_NAMES = [:default, :override, :substitution, :prefix, :postfix].freeze
65
+
66
+ include DataShift::Logging
67
+
68
+ @__instance__ = ThreadSafe::Cache.new
69
+
70
+ def self.instance(locale = :en)
71
+ @__instance__[locale] ||= new
72
+ end
73
+
74
+ def self.reset(locale = :en)
75
+ @__instance__[locale] = new
76
+ end
77
+
78
+ attr_reader :defaults, :overrides, :substitutions
79
+ attr_reader :prefixes, :postfixes
80
+
81
+ def initialize
82
+ clear
83
+ end
84
+
85
+ def clear
86
+ TRANSFORMERS_HASH_INSTANCE_NAMES.each do|h|
87
+ instance_variable_set("@#{h.to_s.pluralize}", ActiveSupport::HashWithIndifferentAccess.new({}))
88
+ end
89
+ end
90
+
91
+ # Default values and over rides per class can be provided in YAML config file.
92
+ #
93
+ # The locale_key for situations where the Class one level down, for example as per our own
94
+ # Template for Datashift Import/Export Configuration which has format :
95
+ #
96
+ # key:
97
+ # klass:
98
+ #
99
+ def configure_from(load_object_class, yaml_file, locale_key = nil)
100
+
101
+ data = YAML.load( ERB.new( IO.read(yaml_file) ).result )
102
+
103
+ class_name = load_object_class.name
104
+
105
+ data = data[locale_key] if(locale_key)
106
+
107
+ configure_from_yaml(load_object_class, data[class_name]) if(data[class_name])
108
+ end
109
+
110
+ def configure_from_yaml(load_object_class, yaml)
111
+
112
+ setter_method_map = {
113
+ defaults: :set_default_on,
114
+ overrides: :set_override_on,
115
+ substitutions: :set_substitution_on_list,
116
+ prefixes: :set_prefix_on,
117
+ postfixes: :set_postfix_on
118
+ }
119
+
120
+ setter_method_map.each do |key, call|
121
+ settings = yaml[key.to_s]
122
+
123
+ settings.each do |operator, value|
124
+ logger.info("Configuring Transform [#{key}] for [#{operator.inspect}] to [#{value}]")
125
+ send( call, load_object_class, operator, value)
126
+ end if(settings && settings.is_a?(Hash))
127
+ end
128
+
129
+ end
130
+
131
+ def hash_key(key)
132
+ return key if(key.is_a? String)
133
+ return key.class_name if(key.is_a? MethodBinding)
134
+ key.name # Class name
135
+ end
136
+
137
+ TRANSFORMERS_HASH_INSTANCE_NAMES.each do |tname|
138
+
139
+ plural_tname = tname.to_s.pluralize
140
+
141
+ # Example : defaults_for(key)
142
+ #
143
+ class_eval <<-end_eval
144
+ def #{plural_tname}_for(key)
145
+ #{plural_tname}[hash_key(key)] ||= new_hash_instance
146
+ end
147
+ end_eval
148
+
149
+ # Is there a transform for this MethodBinding ?
150
+ #
151
+ # Example : default?( method_binding )
152
+ #
153
+ class_eval <<-end_eval
154
+ def #{tname}?( method_binding )
155
+ #{plural_tname}_for(method_binding).key?(method_binding.operator)
156
+ end
157
+ end_eval
158
+
159
+ # RETURN a transform for this MethodBinding
160
+ #
161
+ # Example : default( method_binding )
162
+ #
163
+ class_eval <<-end_eval
164
+ def #{tname}( method_binding )
165
+ get_#{tname}_on(method_binding, method_binding.operator)
166
+ end
167
+ end_eval
168
+
169
+ # RETURN a transform for this key/operator pair
170
+ #
171
+ # Example : get_default_on(key, operator)
172
+ #
173
+ class_eval <<-end_eval
174
+ def get_#{tname}_on(key, operator)
175
+ #{plural_tname}_for(key)[operator]
176
+ end
177
+ end_eval
178
+
179
+ next if(tname == :substitution)
180
+
181
+ # Example : set_default_on(key, operator, default_value )
182
+ #
183
+ class_eval <<-end_eval
184
+ def set_#{tname}_on(key, operator, default_value )
185
+ #{plural_tname}_for(key)[operator] = default_value
186
+ end
187
+ end_eval
188
+
189
+ # Example : set_default(method_binding, default_value )
190
+ #
191
+ define_method("set_#{tname}") do |method_binding, default_value|
192
+ send("set_#{tname}_on", method_binding, method_binding.operator, default_value)
193
+ end
194
+
195
+ end
196
+
197
+ def set_substitution( method_binding, rule, replacement )
198
+ set_substitution_on( method_binding, method_binding.operator, rule, replacement)
199
+ end
200
+
201
+ def set_substitution_on(key, operator, rule, replacement )
202
+ substitutions_for(key)[operator] = Struct::Substitution.new(rule, replacement)
203
+ end
204
+
205
+ private
206
+
207
+ def set_substitution_on_list(key, operator, list )
208
+ substitutions_for(key)[operator] = Struct::Substitution.new(list[0], list[1])
209
+ end
210
+
211
+ def new_hash_instance
212
+ ActiveSupport::HashWithIndifferentAccess.new {}
213
+ end
214
+
215
+ end
216
+
217
+ end ## class
218
+
219
+ end