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.
- checksums.yaml +4 -4
- data/{LICENSE.txt → LICENSE} +0 -0
- data/Rakefile +1 -20
- data/datashift.thor +125 -0
- data/lib/applications/apache_poi_extensions.rb +21 -52
- data/lib/applications/excel.rb +64 -57
- data/lib/applications/hssf_row_extensions.rb +66 -0
- data/lib/applications/jexcel_file.rb +99 -95
- data/lib/applications/jexcel_file_extensions.rb +76 -83
- data/lib/applications/jruby/word.rb +36 -36
- data/lib/applications/ruby_poi_translations.rb +34 -32
- data/lib/applications/spreadsheet_extensions.rb +21 -19
- data/lib/datashift.rb +49 -59
- data/lib/datashift/binder.rb +217 -0
- data/lib/datashift/column_packer.rb +21 -72
- data/lib/datashift/configuration.rb +317 -0
- data/lib/datashift/context_factory.rb +88 -0
- data/lib/datashift/core_ext/array.rb +15 -0
- data/lib/datashift/core_ext/csv_ext.rb +46 -0
- data/lib/datashift/core_ext/string.rb +49 -0
- data/lib/datashift/core_ext/to_b.rb +11 -0
- data/lib/datashift/delimiters.rb +55 -61
- data/lib/datashift/doc_context.rb +137 -0
- data/lib/datashift/excel_base.rb +93 -81
- data/lib/datashift/exceptions.rb +30 -28
- data/lib/datashift/file_definitions.rb +44 -39
- data/lib/datashift/guards.rb +5 -5
- data/lib/datashift/header.rb +25 -0
- data/lib/datashift/headers.rb +94 -0
- data/lib/datashift/inbound_data/column.rb +44 -0
- data/lib/datashift/inbound_data/lookup_support.rb +33 -0
- data/lib/datashift/inbound_data/method_binding.rb +139 -0
- data/lib/datashift/load_object.rb +37 -12
- data/lib/datashift/logging.rb +54 -27
- data/lib/datashift/mandatory.rb +39 -0
- data/lib/datashift/mapping/data_flow_schema.rb +198 -0
- data/lib/datashift/{model_mapper.rb → mapping/mapper_utils.rb} +30 -10
- data/lib/datashift/model_methods/catalogue.rb +183 -0
- data/lib/datashift/model_methods/collection.rb +140 -0
- data/lib/datashift/model_methods/model_method.rb +162 -0
- data/lib/datashift/model_methods/model_methods_manager.rb +76 -0
- data/lib/datashift/model_methods/operator.rb +62 -0
- data/lib/datashift/node_collection.rb +26 -0
- data/lib/datashift/node_context.rb +68 -0
- data/lib/datashift/populator.rb +308 -282
- data/lib/datashift/progress_monitor.rb +91 -0
- data/lib/datashift/querying.rb +110 -52
- data/lib/datashift/templates/import_export_config.erb +55 -0
- data/lib/datashift/transformation/factory.rb +219 -0
- data/lib/datashift/transformation/remove.rb +44 -0
- data/lib/datashift/version.rb +3 -0
- data/lib/exporters/configuration.rb +84 -0
- data/lib/exporters/csv_exporter.rb +54 -52
- data/lib/exporters/excel_exporter.rb +80 -61
- data/lib/exporters/exporter_base.rb +8 -8
- data/lib/generators/config_generator.rb +218 -0
- data/lib/generators/csv_generator.rb +13 -70
- data/lib/generators/excel_generator.rb +23 -111
- data/lib/generators/generator_base.rb +15 -70
- data/lib/loaders/configuration.rb +90 -0
- data/lib/loaders/csv_loader.rb +63 -101
- data/lib/loaders/excel_loader.rb +71 -156
- data/lib/loaders/failure_data.rb +40 -0
- data/lib/loaders/file_loader.rb +16 -0
- data/lib/loaders/loader_base.rb +82 -410
- data/lib/loaders/loader_factory.rb +42 -0
- data/lib/loaders/paperclip/attachment_loader.rb +157 -140
- data/lib/loaders/paperclip/datashift_paperclip.rb +18 -35
- data/lib/loaders/paperclip/image_loading.rb +40 -35
- data/lib/loaders/reporters/basic_stdout_reporter.rb +40 -0
- data/lib/loaders/reporters/reporter.rb +26 -0
- data/lib/tasks/config.thor +65 -0
- data/{tasks → lib/tasks}/config/seed_fu_product_template.erb +0 -0
- data/{tasks → lib/tasks}/config/tidy_config.txt +0 -0
- data/lib/tasks/export.thor +192 -0
- data/lib/tasks/generate.thor +190 -0
- data/lib/tasks/import.thor +142 -0
- data/lib/{thor → tasks}/paperclip.thor +69 -69
- data/{tasks → lib/tasks/to_convert_to_thor}/db_tasks.rake +20 -20
- data/lib/tasks/tools.thor +109 -0
- data/spec/MissingAttachmentRecords/DEMO_001_ror_bag.jpeg +0 -0
- data/spec/MissingAttachmentRecords/DEMO_002_Powerstation.jpeg +0 -0
- data/spec/MissingAttachmentRecords/DEMO_003_ror_mug.jpeg +0 -0
- data/spec/MissingAttachmentRecords/DEMO_004_ror_ringer.jpeg +0 -0
- data/spec/datashift/binder_spec.rb +266 -0
- data/spec/datashift/config_generator_spec.rb +186 -0
- data/spec/datashift/configuration.rb +66 -0
- data/spec/datashift/context_factory_spec.rb +63 -0
- data/spec/datashift/data_flow_schema_spec.rb +150 -0
- data/spec/datashift/datashift_spec.rb +52 -0
- data/spec/datashift/excel_base_spec.rb +57 -0
- data/spec/datashift/excel_spec.rb +188 -0
- data/spec/datashift/failure_data_spec.rb +27 -0
- data/spec/{file_definitions.rb → datashift/file_definitions.rb} +9 -10
- data/spec/datashift/headers_spec.rb +56 -0
- data/spec/datashift/inbound_data_spec.rb +47 -0
- data/spec/datashift/mapper_utils_spec.rb +38 -0
- data/spec/datashift/method_binding_spec.rb +60 -0
- data/spec/datashift/model_method_spec.rb +109 -0
- data/spec/datashift/model_methods_catalogue.rb +111 -0
- data/spec/datashift/model_methods_collection_spec.rb +138 -0
- data/spec/datashift/model_methods_manager_spec.rb +329 -0
- data/spec/datashift/populator_spec.rb +117 -0
- data/spec/datashift/thor_spec.rb +314 -0
- data/spec/datashift/transformation/factory_spec.rb +195 -0
- data/spec/datashift/transformation/transformer_remove_spec.rb +43 -0
- data/spec/dummy/Gemfile +53 -0
- data/spec/dummy/Gemfile.lock +197 -0
- data/spec/dummy/README.rdoc +28 -0
- data/spec/dummy/Rakefile +6 -0
- data/spec/dummy/app/assets/javascripts/application.js +16 -0
- data/spec/dummy/app/assets/javascripts/categories.js +2 -0
- data/spec/dummy/app/assets/javascripts/digitals.js +2 -0
- data/spec/dummy/app/assets/javascripts/empties.js +2 -0
- data/spec/dummy/app/assets/javascripts/loader_releases.js +2 -0
- data/spec/dummy/app/assets/javascripts/long_and_complex_table_linked_to_versions.js +2 -0
- data/spec/dummy/app/assets/javascripts/milestones.js +2 -0
- data/spec/dummy/app/assets/javascripts/owners.js +2 -0
- data/spec/dummy/app/assets/javascripts/projects.js +2 -0
- data/spec/dummy/app/assets/javascripts/users.js +2 -0
- data/spec/dummy/app/assets/javascripts/versions.js +2 -0
- data/spec/dummy/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy/app/assets/stylesheets/categories.css +4 -0
- data/spec/dummy/app/assets/stylesheets/digitals.css +4 -0
- data/spec/dummy/app/assets/stylesheets/empties.css +4 -0
- data/spec/dummy/app/assets/stylesheets/loader_releases.css +4 -0
- data/spec/dummy/app/assets/stylesheets/long_and_complex_table_linked_to_versions.css +4 -0
- data/spec/dummy/app/assets/stylesheets/milestones.css +4 -0
- data/spec/dummy/app/assets/stylesheets/owners.css +4 -0
- data/spec/dummy/app/assets/stylesheets/projects.css +4 -0
- data/spec/dummy/app/assets/stylesheets/scaffold.css +56 -0
- data/spec/dummy/app/assets/stylesheets/users.css +4 -0
- data/spec/dummy/app/assets/stylesheets/versions.css +4 -0
- data/spec/dummy/app/controllers/application_controller.rb +5 -0
- data/spec/dummy/app/controllers/categories_controller.rb +58 -0
- data/spec/dummy/app/controllers/digitals_controller.rb +58 -0
- data/spec/dummy/app/controllers/empties_controller.rb +58 -0
- data/spec/dummy/app/controllers/loader_releases_controller.rb +58 -0
- data/spec/dummy/app/controllers/long_and_complex_table_linked_to_versions_controller.rb +58 -0
- data/spec/dummy/app/controllers/milestones_controller.rb +58 -0
- data/spec/dummy/app/controllers/owners_controller.rb +58 -0
- data/spec/dummy/app/controllers/projects_controller.rb +58 -0
- data/spec/dummy/app/controllers/users_controller.rb +58 -0
- data/spec/dummy/app/controllers/versions_controller.rb +58 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/helpers/categories_helper.rb +2 -0
- data/spec/dummy/app/helpers/digitals_helper.rb +2 -0
- data/spec/dummy/app/helpers/empties_helper.rb +2 -0
- data/spec/dummy/app/helpers/loader_releases_helper.rb +2 -0
- data/spec/dummy/app/helpers/long_and_complex_table_linked_to_versions_helper.rb +2 -0
- data/spec/dummy/app/helpers/milestones_helper.rb +2 -0
- data/spec/dummy/app/helpers/owners_helper.rb +2 -0
- data/spec/dummy/app/helpers/projects_helper.rb +2 -0
- data/spec/dummy/app/helpers/users_helper.rb +2 -0
- data/spec/dummy/app/helpers/versions_helper.rb +2 -0
- data/spec/dummy/app/models/category.rb +6 -0
- data/spec/dummy/app/models/digital.rb +22 -0
- data/spec/dummy/app/models/empty.rb +2 -0
- data/spec/dummy/app/models/loader_release.rb +10 -0
- data/spec/dummy/app/models/long_and_complex_table_linked_to_version.rb +6 -0
- data/spec/dummy/app/models/milestone.rb +15 -0
- data/spec/dummy/app/models/owner.rb +13 -0
- data/spec/dummy/app/models/project.rb +53 -0
- data/spec/dummy/app/models/user.rb +5 -0
- data/spec/dummy/app/models/version.rb +7 -0
- data/spec/dummy/app/views/categories/_form.html.erb +17 -0
- data/spec/dummy/app/views/categories/edit.html.erb +6 -0
- data/spec/dummy/app/views/categories/index.html.erb +25 -0
- data/spec/dummy/app/views/categories/new.html.erb +5 -0
- data/spec/dummy/app/views/categories/show.html.erb +4 -0
- data/spec/dummy/app/views/digitals/_form.html.erb +17 -0
- data/spec/dummy/app/views/digitals/edit.html.erb +6 -0
- data/spec/dummy/app/views/digitals/index.html.erb +25 -0
- data/spec/dummy/app/views/digitals/new.html.erb +5 -0
- data/spec/dummy/app/views/digitals/show.html.erb +4 -0
- data/spec/dummy/app/views/empties/_form.html.erb +17 -0
- data/spec/dummy/app/views/empties/edit.html.erb +6 -0
- data/spec/dummy/app/views/empties/index.html.erb +25 -0
- data/spec/dummy/app/views/empties/new.html.erb +5 -0
- data/spec/dummy/app/views/empties/show.html.erb +4 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/app/views/loader_releases/_form.html.erb +17 -0
- data/spec/dummy/app/views/loader_releases/edit.html.erb +6 -0
- data/spec/dummy/app/views/loader_releases/index.html.erb +25 -0
- data/spec/dummy/app/views/loader_releases/new.html.erb +5 -0
- data/spec/dummy/app/views/loader_releases/show.html.erb +4 -0
- data/spec/dummy/app/views/long_and_complex_table_linked_to_versions/_form.html.erb +17 -0
- data/spec/dummy/app/views/long_and_complex_table_linked_to_versions/edit.html.erb +6 -0
- data/spec/dummy/app/views/long_and_complex_table_linked_to_versions/index.html.erb +25 -0
- data/spec/dummy/app/views/long_and_complex_table_linked_to_versions/new.html.erb +5 -0
- data/spec/dummy/app/views/long_and_complex_table_linked_to_versions/show.html.erb +4 -0
- data/spec/dummy/app/views/milestones/_form.html.erb +17 -0
- data/spec/dummy/app/views/milestones/edit.html.erb +6 -0
- data/spec/dummy/app/views/milestones/index.html.erb +25 -0
- data/spec/dummy/app/views/milestones/new.html.erb +5 -0
- data/spec/dummy/app/views/milestones/show.html.erb +4 -0
- data/spec/dummy/app/views/owners/_form.html.erb +17 -0
- data/spec/dummy/app/views/owners/edit.html.erb +6 -0
- data/spec/dummy/app/views/owners/index.html.erb +25 -0
- data/spec/dummy/app/views/owners/new.html.erb +5 -0
- data/spec/dummy/app/views/owners/show.html.erb +4 -0
- data/spec/dummy/app/views/projects/_form.html.erb +17 -0
- data/spec/dummy/app/views/projects/edit.html.erb +6 -0
- data/spec/dummy/app/views/projects/index.html.erb +25 -0
- data/spec/dummy/app/views/projects/new.html.erb +5 -0
- data/spec/dummy/app/views/projects/show.html.erb +4 -0
- data/spec/dummy/app/views/users/_form.html.erb +17 -0
- data/spec/dummy/app/views/users/edit.html.erb +6 -0
- data/spec/dummy/app/views/users/index.html.erb +25 -0
- data/spec/dummy/app/views/users/new.html.erb +5 -0
- data/spec/dummy/app/views/users/show.html.erb +4 -0
- data/spec/dummy/app/views/versions/_form.html.erb +17 -0
- data/spec/dummy/app/views/versions/edit.html.erb +6 -0
- data/spec/dummy/app/views/versions/index.html.erb +25 -0
- data/spec/dummy/app/views/versions/new.html.erb +5 -0
- data/spec/dummy/app/views/versions/show.html.erb +4 -0
- data/spec/dummy/bin/bundle +3 -0
- data/spec/dummy/bin/rails +9 -0
- data/spec/dummy/bin/rake +9 -0
- data/spec/dummy/bin/setup +29 -0
- data/spec/dummy/bin/spring +16 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +26 -0
- data/spec/dummy/config/boot.rb +3 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +41 -0
- data/spec/dummy/config/environments/production.rb +79 -0
- data/spec/dummy/config/environments/test.rb +42 -0
- data/spec/dummy/config/initializers/assets.rb +11 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy/config/initializers/inflections.rb +16 -0
- data/spec/dummy/config/initializers/mime_types.rb +4 -0
- data/spec/dummy/config/initializers/session_store.rb +3 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +23 -0
- data/spec/dummy/config/routes.rb +76 -0
- data/spec/dummy/config/secrets.yml +22 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/migrate/20110803201325_create_test_bed.rb +98 -0
- data/spec/dummy/db/migrate/20121009161700_add_digitals.rb +24 -0
- data/spec/dummy/db/migrate/20161005123106_create_digitals.rb +8 -0
- data/spec/dummy/db/migrate/20161005123106_create_long_and_complex_table_linked_to_versions.rb +8 -0
- data/spec/dummy/db/migrate/20161005123107_create_loader_releases.rb +8 -0
- data/spec/dummy/db/migrate/20161005123108_create_owners.rb +8 -0
- data/spec/dummy/db/migrate/20161005123109_create_empties.rb +8 -0
- data/spec/dummy/db/migrate/20161005123110_create_projects.rb +8 -0
- data/spec/dummy/db/migrate/20161005123111_create_users.rb +8 -0
- data/spec/dummy/db/migrate/20161005123111_create_versions.rb +8 -0
- data/spec/dummy/db/migrate/20161005123112_create_milestones.rb +8 -0
- data/spec/dummy/db/migrate/20161005123113_create_categories.rb +8 -0
- data/spec/dummy/db/schema.rb +93 -0
- data/spec/dummy/db/seeds.rb +9 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/test.log +69 -0
- data/spec/dummy/public/404.html +67 -0
- data/spec/dummy/public/422.html +67 -0
- data/spec/dummy/public/500.html +66 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/public/robots.txt +5 -0
- data/spec/dummy/sandbox_example.thor +4 -0
- data/spec/dummy/test/controllers/categories_controller_test.rb +49 -0
- data/spec/dummy/test/controllers/digitals_controller_test.rb +49 -0
- data/spec/dummy/test/controllers/empties_controller_test.rb +49 -0
- data/spec/dummy/test/controllers/loader_releases_controller_test.rb +49 -0
- data/spec/dummy/test/controllers/long_and_complex_table_linked_to_versions_controller_test.rb +49 -0
- data/spec/dummy/test/controllers/milestones_controller_test.rb +49 -0
- data/spec/dummy/test/controllers/owners_controller_test.rb +49 -0
- data/spec/dummy/test/controllers/projects_controller_test.rb +49 -0
- data/spec/dummy/test/controllers/users_controller_test.rb +49 -0
- data/spec/dummy/test/controllers/versions_controller_test.rb +49 -0
- data/spec/dummy/test/factories/categories.rb +5 -0
- data/spec/dummy/test/factories/digitals.rb +5 -0
- data/spec/dummy/test/factories/empties.rb +5 -0
- data/spec/dummy/test/factories/loader_releases.rb +5 -0
- data/spec/dummy/test/factories/long_and_complex_table_linked_to_versions.rb +5 -0
- data/spec/dummy/test/factories/milestones.rb +5 -0
- data/spec/dummy/test/factories/owners.rb +5 -0
- data/spec/dummy/test/factories/projects.rb +5 -0
- data/spec/dummy/test/factories/users.rb +5 -0
- data/spec/dummy/test/factories/versions.rb +5 -0
- data/spec/dummy/test/models/category_test.rb +7 -0
- data/spec/dummy/test/models/digital_test.rb +7 -0
- data/spec/dummy/test/models/empty_test.rb +7 -0
- data/spec/dummy/test/models/loader_release_test.rb +7 -0
- data/spec/dummy/test/models/long_and_complex_table_linked_to_version_test.rb +7 -0
- data/spec/dummy/test/models/milestone_test.rb +7 -0
- data/spec/dummy/test/models/owner_test.rb +7 -0
- data/spec/dummy/test/models/project_test.rb +7 -0
- data/spec/dummy/test/models/user_test.rb +7 -0
- data/spec/dummy/test/models/version_test.rb +7 -0
- data/spec/dummy/test/test_helper.rb +10 -0
- data/spec/exporters/csv_exporter_spec.rb +240 -0
- data/spec/exporters/csv_generator_spec.rb +139 -0
- data/spec/exporters/excel_exporter_spec.rb +193 -0
- data/spec/exporters/excel_generator_spec.rb +181 -0
- data/spec/exporters/generator_base_spec.rb +45 -0
- data/spec/factories/categories.rb +7 -0
- data/spec/factories/factories.rb +18 -0
- data/spec/factories/milestone.rb +16 -0
- data/spec/factories/projects.rb +41 -0
- data/spec/fixtures/BadAssociationName.xls +0 -0
- data/spec/fixtures/DemoNegativeTesting.xls +0 -0
- data/spec/fixtures/ProjectConfiguration.yml +18 -0
- data/spec/fixtures/ProjectsMultiCategories.xls +0 -0
- data/spec/fixtures/ProjectsMultiCategoriesHeaderLookup.xls +0 -0
- data/spec/fixtures/ProjectsSingleCategories.xls +0 -0
- data/spec/fixtures/ProjectsSingleCategories.xlsx +0 -0
- data/spec/fixtures/SimpleProjects.xls +0 -0
- data/spec/fixtures/config/database.yml +28 -0
- data/spec/fixtures/csv/BadAssociationName.csv +6 -0
- data/spec/fixtures/csv/DemoNegativeTesting.csv +6 -0
- data/spec/fixtures/csv/ProjectsMultiCategories.csv +5 -0
- data/spec/fixtures/csv/ProjectsMultiCategoriesHeaderLookup.csv +5 -0
- data/spec/fixtures/csv/ProjectsSingleCategories.csv +5 -0
- data/spec/fixtures/csv/SimpleProjects.csv +4 -0
- data/spec/fixtures/db/migrate/20110803201325_create_test_bed.rb +98 -0
- data/spec/fixtures/db/migrate/20121009161700_add_digitals.rb +24 -0
- data/spec/fixtures/db/seeds.rb +9 -0
- data/spec/fixtures/images/DEMO_001_ror_bag.jpeg +0 -0
- data/spec/fixtures/images/DEMO_002_Powerstation.jpeg +0 -0
- data/spec/fixtures/images/DEMO_003_ror_mug.jpeg +0 -0
- data/spec/fixtures/images/DEMO_004_ror_ringer.jpeg +0 -0
- data/spec/fixtures/load_datashift.thor +3 -0
- data/spec/fixtures/models/category.rb +6 -0
- data/spec/fixtures/models/digital.rb +22 -0
- data/spec/fixtures/models/empty.rb +2 -0
- data/spec/fixtures/models/loader_release.rb +10 -0
- data/spec/fixtures/models/long_and_complex_table_linked_to_version.rb +6 -0
- data/spec/fixtures/models/milestone.rb +15 -0
- data/spec/fixtures/models/owner.rb +13 -0
- data/spec/fixtures/models/project.rb +53 -0
- data/spec/fixtures/models/user.rb +5 -0
- data/spec/fixtures/models/version.rb +7 -0
- data/spec/fixtures/results/exp_project_assoc_headers.xls +0 -0
- data/spec/fixtures/results/exp_project_collection_spec.csv +2 -0
- data/spec/fixtures/results/exp_project_export.xls +0 -0
- data/spec/fixtures/results/exp_project_first_export.xls +0 -0
- data/spec/fixtures/results/exp_project_plus_assoc.xls +0 -0
- data/spec/fixtures/results/exp_project_plus_assoc_export_spec.csv +9 -0
- data/spec/fixtures/results/gen_project_plus_assoc_template.xls +0 -0
- data/spec/fixtures/results/gen_project_plus_some_assoc_template.xls +0 -0
- data/spec/fixtures/results/gen_project_template.xls +0 -0
- data/spec/fixtures/results/project_and_assoc_in_hash_export.xls +0 -0
- data/spec/fixtures/results/project_and_assoc_in_json_export.csv +9 -0
- data/spec/fixtures/results/project_and_assoc_in_json_export.xls +0 -0
- data/spec/fixtures/results/project_export_spec_with_custom_delim_,.csv +2 -0
- data/spec/fixtures/results/project_export_spec_with_custom_delim_/302/243.csv +2 -0
- data/spec/fixtures/results/project_export_spec_with_custom_delim_/302/247.csv +2 -0
- data/spec/fixtures/results/project_plus_assoc_template.csv +1 -0
- data/spec/fixtures/results/project_plus_some_assoc_template.csv +1 -0
- data/spec/fixtures/results/project_remove_export_spec.csv +2 -0
- data/spec/fixtures/results/project_template.csv +1 -0
- data/spec/fixtures/results/project_with_methods_export_spec.csv +2 -0
- data/spec/fixtures/results/thor_spec_gen_project.csv +1 -0
- data/spec/fixtures/sandbox_example.thor +4 -0
- data/spec/fixtures/simple_export_spec.xls +0 -0
- data/spec/fixtures/simple_template_spec.xls +0 -0
- data/spec/fixtures/test_model_defs.rb +7 -0
- data/spec/loaders/csv_loader_spec.rb +206 -0
- data/spec/loaders/data_flow_excel_loader_spec.rb +290 -0
- data/spec/loaders/excel_loader_failures_spec.rb +67 -0
- data/spec/loaders/excel_loader_spec.rb +294 -0
- data/spec/loaders/loader_base_spec.rb +29 -0
- data/spec/loaders/paperclip_loader_spec.rb +106 -0
- data/spec/log/datashift.log +14930 -0
- data/spec/private/digitals/1/DEMO_003_ror_mug.jpeg +0 -0
- data/spec/private/digitals/2/DEMO_002_Powerstation.jpeg +0 -0
- data/spec/private/digitals/3/DEMO_004_ror_ringer.jpeg +0 -0
- data/spec/private/digitals/4/DEMO_001_ror_bag.jpeg +0 -0
- data/spec/spec_helper.rb +26 -230
- data/spec/support/clear_and_manage_contexts.rb +25 -0
- data/spec/support/database_cleaner.rb +32 -0
- data/spec/support/datashift_test_helpers.rb +153 -0
- data/spec/support/files_paths_helper.rb +13 -0
- data/spec/support/fixtures/results/mapping_template.yaml +15 -0
- data/spec/support/sandbox.rb +136 -0
- metadata +804 -85
- data/README.markdown +0 -274
- data/README.rdoc +0 -19
- data/VERSION +0 -1
- data/datashift.gemspec +0 -48
- data/lib/applications/jruby/old_pre_proxy_jexcel_file.rb +0 -437
- data/lib/datashift/data_transforms.rb +0 -83
- data/lib/datashift/mapping_file_definitions.rb +0 -88
- data/lib/datashift/mapping_service.rb +0 -91
- data/lib/datashift/method_detail.rb +0 -165
- data/lib/datashift/method_details_manager.rb +0 -95
- data/lib/datashift/method_dictionary.rb +0 -281
- data/lib/datashift/method_mapper.rb +0 -174
- data/lib/datashift/thor_base.rb +0 -38
- data/lib/generators/mapping_generator.rb +0 -112
- data/lib/helpers/core_ext/csv_file.rb +0 -33
- data/lib/helpers/core_ext/to_b.rb +0 -24
- data/lib/loaders/reporter.rb +0 -58
- data/lib/thor/export.thor +0 -175
- data/lib/thor/generate.thor +0 -191
- data/lib/thor/import.thor +0 -110
- data/lib/thor/mapping.thor +0 -65
- data/lib/thor/tools.thor +0 -84
- data/spec/Gemfile +0 -31
- data/spec/Gemfile.lock +0 -134
- data/spec/csv_exporter_spec.rb +0 -144
- data/spec/csv_generator_spec.rb +0 -159
- data/spec/csv_loader_spec.rb +0 -212
- data/spec/datashift_spec.rb +0 -55
- data/spec/excel_exporter_spec.rb +0 -199
- data/spec/excel_generator_spec.rb +0 -203
- data/spec/excel_loader_spec.rb +0 -237
- data/spec/excel_spec.rb +0 -203
- data/spec/loader_base_spec.rb +0 -166
- data/spec/mapping_spec.rb +0 -117
- data/spec/method_dictionary_spec.rb +0 -300
- data/spec/method_mapper_spec.rb +0 -100
- data/spec/model_mapper_spec.rb +0 -41
- data/spec/paperclip_loader_spec.rb +0 -92
- data/spec/populator_spec.rb +0 -128
- data/spec/thor_spec.rb +0 -90
- data/tasks/file_tasks.rake +0 -37
- data/tasks/word_to_seedfu.rake +0 -167
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# Copyright:: (c) Autotelik Media Ltd 2016
|
|
2
|
+
# Author :: Tom Statter
|
|
3
|
+
# Date :: Aug 2016
|
|
4
|
+
# License:: MIT
|
|
5
|
+
#
|
|
6
|
+
# Details:: Holds the current context - the node we are dealing with
|
|
7
|
+
# so requires the Inbound Column details, the associated ModelMethod
|
|
8
|
+
# and the row node containing the actual data to apply via the model method operator
|
|
9
|
+
#
|
|
10
|
+
|
|
11
|
+
module DataShift
|
|
12
|
+
|
|
13
|
+
class NodeContext
|
|
14
|
+
|
|
15
|
+
include DataShift::Logging
|
|
16
|
+
|
|
17
|
+
attr_accessor :doc_context, :method_binding, :row_index
|
|
18
|
+
|
|
19
|
+
attr_accessor :populator
|
|
20
|
+
|
|
21
|
+
attr_reader :data
|
|
22
|
+
|
|
23
|
+
def initialize(doc_context, method_binding, row_idx, data)
|
|
24
|
+
@doc_context = doc_context
|
|
25
|
+
@method_binding = method_binding
|
|
26
|
+
@row_index = row_idx
|
|
27
|
+
@data = data
|
|
28
|
+
|
|
29
|
+
@populator = ContextFactory.get_populator(method_binding)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
delegate :model_method, :operator, to: :method_binding
|
|
33
|
+
|
|
34
|
+
def contains_data?
|
|
35
|
+
!(data.nil? || data.to_s.empty?)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def next_update?
|
|
39
|
+
false # for now create only
|
|
40
|
+
# TODO : Support UPDATES
|
|
41
|
+
# next = ProcessingRules.next_action(method_binding )
|
|
42
|
+
# next == :update
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def process
|
|
46
|
+
populator.prepare_and_assign(self, doc_context.load_object, data)
|
|
47
|
+
rescue => x
|
|
48
|
+
|
|
49
|
+
failed = FailureData.new( doc_context.load_object, self, x.message)
|
|
50
|
+
|
|
51
|
+
failed.error_messages << "Failed to process node : #{method_binding.pp}"
|
|
52
|
+
|
|
53
|
+
doc_context.progress_monitor.failure(failed)
|
|
54
|
+
|
|
55
|
+
logger.error("#{x.backtrace.first} : #{x.message}")
|
|
56
|
+
raise x
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
class EmptyContext < NodeContext
|
|
62
|
+
|
|
63
|
+
def initialize
|
|
64
|
+
super(NilClass, DataShift::NoMethodBinding.new, -1, [])
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
end
|
data/lib/datashift/populator.rb
CHANGED
|
@@ -4,24 +4,23 @@
|
|
|
4
4
|
# License:: MIT
|
|
5
5
|
#
|
|
6
6
|
# Details:: The default Populator class for assigning data to models
|
|
7
|
-
#
|
|
7
|
+
#
|
|
8
8
|
# Provides individual population methods on an AR model.
|
|
9
9
|
#
|
|
10
10
|
# Enables users to assign values to AR object, without knowing much about that receiving object.
|
|
11
11
|
#
|
|
12
|
-
require 'to_b'
|
|
13
|
-
require 'logging'
|
|
14
|
-
|
|
15
12
|
module DataShift
|
|
16
13
|
|
|
17
|
-
Struct.new("Substitution", :pattern, :replacement)
|
|
18
|
-
|
|
19
14
|
class Populator
|
|
20
15
|
|
|
21
16
|
include DataShift::Logging
|
|
17
|
+
extend DataShift::Logging
|
|
18
|
+
|
|
19
|
+
include DataShift::Delimiters
|
|
20
|
+
extend DataShift::Delimiters
|
|
22
21
|
|
|
23
22
|
def self.insistent_method_list
|
|
24
|
-
@insistent_method_list ||= [:to_s, :to_i, :to_f, :to_b]
|
|
23
|
+
@insistent_method_list ||= [:to_s, :downcase, :to_i, :to_f, :to_b]
|
|
25
24
|
end
|
|
26
25
|
|
|
27
26
|
# When looking up an association, when no field provided, try each of these in turn till a match
|
|
@@ -30,211 +29,215 @@ module DataShift
|
|
|
30
29
|
@insistent_find_by_list ||= [:name, :title, :id]
|
|
31
30
|
end
|
|
32
31
|
|
|
32
|
+
attr_reader :value, :attribute_hash
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
# to teh whole column - hence class methods
|
|
36
|
-
def self.set_header_default_data(operator, data )
|
|
37
|
-
header_default_data[operator] = data
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def self.header_default_data
|
|
41
|
-
@header_default_data ||= {}
|
|
42
|
-
end
|
|
34
|
+
attr_accessor :previous_value, :original_data
|
|
43
35
|
|
|
36
|
+
def initialize(transformer = nil)
|
|
37
|
+
# reset
|
|
38
|
+
@transformer = transformer || Transformation.factory
|
|
44
39
|
|
|
45
|
-
|
|
46
|
-
|
|
40
|
+
@attribute_hash = {}
|
|
41
|
+
end
|
|
47
42
|
|
|
48
|
-
|
|
49
|
-
attr_reader :current_method_detail
|
|
43
|
+
# Main client hooks :
|
|
50
44
|
|
|
51
|
-
|
|
52
|
-
@current_value = nil
|
|
53
|
-
@current_method_detail = nil
|
|
54
|
-
@original_value_before_override = nil
|
|
55
|
-
@current_attribute_hash = {}
|
|
45
|
+
# Prepare the data to be populated, then assign to the Db record
|
|
56
46
|
|
|
47
|
+
def prepare_and_assign(context, record, data)
|
|
48
|
+
prepare_and_assign_method_binding(context.method_binding, record, data)
|
|
57
49
|
end
|
|
58
50
|
|
|
59
|
-
#
|
|
60
|
-
#
|
|
61
|
-
#
|
|
62
|
-
# "{:name => 'autechre'}" => Hash['name'] = autechre'
|
|
63
|
-
# "{:cost_price => '13.45', :price => 23, :sale_price => 4.23 }"
|
|
51
|
+
# This is the most pertinent hook for derived Processors, where you can provide custom
|
|
52
|
+
# population messages for specific Method bindings
|
|
64
53
|
|
|
65
|
-
def
|
|
66
|
-
|
|
67
|
-
str.gsub(/[{}:]/,'').split(', ').map do |e|
|
|
68
|
-
k,v = e.split('=>')
|
|
54
|
+
def prepare_and_assign_method_binding(method_binding, record, data)
|
|
55
|
+
prepare_data(method_binding, data)
|
|
69
56
|
|
|
70
|
-
|
|
71
|
-
|
|
57
|
+
assign(method_binding, record)
|
|
58
|
+
end
|
|
72
59
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
60
|
+
def reset
|
|
61
|
+
@value = nil
|
|
62
|
+
@previous_value = nil
|
|
63
|
+
@original_data = nil
|
|
64
|
+
@attribute_hash = {}
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def value?
|
|
68
|
+
!value.nil?
|
|
69
|
+
end
|
|
82
70
|
|
|
83
|
-
|
|
71
|
+
def self.attribute_hash_const_regexp
|
|
72
|
+
@attribute_hash_const_regexp ||= Regexp.new( attribute_list_start + '.*' + attribute_list_end)
|
|
84
73
|
end
|
|
85
74
|
|
|
86
|
-
# Set member variables to hold details, value and optional attributes,
|
|
87
|
-
# to be set on the 'value' once created
|
|
88
|
-
#
|
|
89
75
|
# Check supplied value, validate it, and if required :
|
|
90
76
|
# set to provided default value
|
|
91
|
-
# prepend any provided prefixes
|
|
77
|
+
# prepend any provided prefixes
|
|
92
78
|
# add any provided postfixes
|
|
93
|
-
|
|
79
|
+
#
|
|
80
|
+
# Rtns : tuple of [:value, :attribute_hash]
|
|
81
|
+
#
|
|
82
|
+
def prepare_data(method_binding, data)
|
|
83
|
+
|
|
84
|
+
connection_adapter_column = method_binding.model_method.connection_adapter_column
|
|
85
|
+
|
|
94
86
|
|
|
95
|
-
raise NilDataSuppliedError
|
|
87
|
+
raise NilDataSuppliedError, 'No method_binding supplied for prepare_data' unless method_binding
|
|
88
|
+
|
|
89
|
+
@original_data = data
|
|
96
90
|
|
|
97
91
|
begin
|
|
98
|
-
@prepare_data_const_regexp ||= Regexp.new( Delimiters::attribute_list_start + ".*" + Delimiters::attribute_list_end)
|
|
99
|
-
|
|
100
|
-
if( value.is_a? ActiveRecord::Relation ) # Rails 4 - query no longer returns an array
|
|
101
|
-
@current_value = value.to_a
|
|
102
|
-
elsif( !DataShift::Guards.jruby? && value.class.ancestors.include?(Spreadsheet::Formula))
|
|
103
|
-
@current_value = value.value
|
|
104
|
-
elsif( value.class.ancestors.include?(ActiveRecord::Base) || value.is_a?(Array))
|
|
105
|
-
@current_value = value
|
|
106
|
-
else
|
|
107
|
-
@current_value = value.to_s
|
|
108
92
|
|
|
109
|
-
|
|
93
|
+
if(data.is_a?(ActiveRecord::Relation)) # Rails 4 - query no longer returns an array
|
|
94
|
+
@value = data.to_a
|
|
110
95
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
logger.info "Populator for #{@current_value} has attributes #{@current_attribute_hash.inspect}"
|
|
114
|
-
end
|
|
115
|
-
end
|
|
96
|
+
elsif(data.class.ancestors.include?(ActiveRecord::Base) || data.is_a?(Array))
|
|
97
|
+
@value = data
|
|
116
98
|
|
|
117
|
-
|
|
99
|
+
elsif(!DataShift::Guards.jruby? &&
|
|
100
|
+
(data.is_a?(Spreadsheet::Formula) || data.class.ancestors.include?(Spreadsheet::Formula)) )
|
|
118
101
|
|
|
119
|
-
|
|
102
|
+
@value = data.value # TOFIX jruby/apache poi equivalent ?
|
|
120
103
|
|
|
121
|
-
|
|
104
|
+
elsif(connection_adapter_column && connection_adapter_column.cast_type.is_a?(ActiveRecord::Type::Boolean))
|
|
122
105
|
|
|
123
|
-
|
|
106
|
+
# DEPRECATION WARNING: You attempted to assign a value which is not explicitly `true` or `false` ("0.00")
|
|
107
|
+
# to a boolean column. Currently this value casts to `false`.
|
|
108
|
+
# This will change to match Ruby's semantics, and will cast to `true` in Rails 5.
|
|
109
|
+
# If you would like to maintain the current behavior, you should explicitly handle the values you would like cast to `false`.
|
|
124
110
|
|
|
125
|
-
|
|
126
|
-
|
|
111
|
+
@value = if(data.in? [true, false])
|
|
112
|
+
data
|
|
113
|
+
else
|
|
114
|
+
(data.to_s.downcase == "true" || data.to_s.to_i == 1) ? true : false
|
|
115
|
+
end
|
|
127
116
|
else
|
|
128
|
-
|
|
129
|
-
if(default_value(operator))
|
|
130
|
-
@current_value = default_value(operator)
|
|
131
|
-
elsif(Populator::header_default_data[operator])
|
|
132
|
-
@current_value = Populator::header_default_data[operator].to_s
|
|
133
|
-
elsif(Populator::header_default_data[operator])
|
|
134
|
-
@current_value = Populator::header_default_data[operator].to_s
|
|
135
|
-
elsif(method_detail.find_by_value)
|
|
136
|
-
@current_value = method_detail.find_by_value
|
|
137
|
-
end if(value.nil? || value.to_s.empty?)
|
|
138
|
-
end
|
|
117
|
+
@value = data.to_s
|
|
139
118
|
|
|
140
|
-
|
|
119
|
+
@attribute_hash = @value.slice!( Populator.attribute_hash_const_regexp )
|
|
141
120
|
|
|
142
|
-
|
|
143
|
-
|
|
121
|
+
if attribute_hash && !attribute_hash.empty?
|
|
122
|
+
@attribute_hash = Populator.string_to_hash( attribute_hash )
|
|
123
|
+
logger.info "Populator found attribute hash :[#{attribute_hash.inspect}]"
|
|
124
|
+
else
|
|
125
|
+
@attribute_hash = {}
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
run_transforms(method_binding)
|
|
144
130
|
|
|
145
131
|
rescue => e
|
|
146
|
-
logger.error(
|
|
147
|
-
logger.error("
|
|
148
|
-
|
|
149
|
-
raise DataProcessingError.new("opulator failed to prepare data #{value} for operator #{method_detail.operator}")
|
|
132
|
+
logger.error(e.message)
|
|
133
|
+
logger.error("Populator stacktrace: #{e.backtrace.first}")
|
|
134
|
+
raise DataProcessingError, "Populator failed to prepare data [#{value}] for #{method_binding.pp}"
|
|
150
135
|
end
|
|
151
136
|
|
|
152
|
-
|
|
137
|
+
[value, attribute_hash]
|
|
153
138
|
end
|
|
154
139
|
|
|
155
|
-
|
|
140
|
+
def assign(method_binding, record)
|
|
156
141
|
|
|
157
|
-
|
|
142
|
+
model_method = method_binding.model_method
|
|
158
143
|
|
|
159
|
-
|
|
144
|
+
operator = model_method.operator
|
|
160
145
|
|
|
161
|
-
|
|
162
|
-
end
|
|
146
|
+
klass = model_method.klass
|
|
163
147
|
|
|
164
|
-
|
|
148
|
+
if model_method.operator_for(:belongs_to)
|
|
149
|
+
insistent_belongs_to(method_binding, record, value)
|
|
150
|
+
elsif model_method.operator_for(:has_many)
|
|
151
|
+
assign_has_many(method_binding, record)
|
|
152
|
+
elsif model_method.operator_for(:has_one)
|
|
165
153
|
|
|
166
|
-
|
|
154
|
+
if value.is_a?(model_method.klass)
|
|
155
|
+
record.send(operator + '=', value)
|
|
156
|
+
else
|
|
157
|
+
logger.error("Cannot assign value [#{value.inspect}]")
|
|
158
|
+
logger.error("Value was Type (#{value.class}) - Required Type for has_one #{operator} is [#{klass}]")
|
|
159
|
+
end
|
|
167
160
|
|
|
168
|
-
|
|
161
|
+
elsif model_method.operator_for(:assignment)
|
|
169
162
|
|
|
170
|
-
|
|
163
|
+
if model_method.connection_adapter_column
|
|
171
164
|
|
|
172
|
-
|
|
165
|
+
return if check_process_enum(record, model_method ) # TOFIX .. enum section probably belongs in prepare_data
|
|
173
166
|
|
|
174
|
-
|
|
167
|
+
assignment(record, value, model_method)
|
|
175
168
|
|
|
176
|
-
|
|
169
|
+
else
|
|
170
|
+
logger.debug("Brute force assignment of value #{value} => [#{operator}]")
|
|
171
|
+
# brute force case for assignments without a column type (which enables us to do correct type_cast)
|
|
172
|
+
# so in this case, attempt straightforward assignment then if that fails, basic ops such as to_s, to_i, to_f etc
|
|
173
|
+
insistent_assignment(record, value, operator)
|
|
174
|
+
end
|
|
177
175
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
# so how do we get from 'taxons' to Spree::Taxons ? .. check if further info in reflect_on_all_associations
|
|
176
|
+
elsif model_method.operator_for(:method)
|
|
177
|
+
logger.debug("Method delegation assignment of value #{value} => [#{operator}]")
|
|
178
|
+
insistent_assignment(record, value, operator)
|
|
182
179
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
logger.error e.inspect
|
|
187
|
-
logger.error "Cannot assign #{current_value.inspect} (#{current_value.class}) to has_many association [#{operator}] "
|
|
188
|
-
end
|
|
180
|
+
else
|
|
181
|
+
logger.warn("Cannot assign via [#{operator}] to #{record.inspect} ")
|
|
182
|
+
end
|
|
189
183
|
|
|
190
|
-
|
|
184
|
+
end
|
|
191
185
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
186
|
+
def assignment(record, value, model_method)
|
|
187
|
+
|
|
188
|
+
operator = model_method.operator
|
|
189
|
+
connection_adapter_column = model_method.connection_adapter_column
|
|
190
|
+
|
|
191
|
+
begin
|
|
192
|
+
if(connection_adapter_column.respond_to? :type_cast)
|
|
193
|
+
logger.debug("Assignment via [#{operator}] to [#{value}] (CAST TYPE [#{model_method.connection_adapter_column.type_cast(value).inspect}])")
|
|
194
|
+
|
|
195
|
+
record.send( operator + '=', model_method.connection_adapter_column.type_cast( value ) )
|
|
199
196
|
|
|
200
|
-
elsif( current_method_detail.operator_for(:assignment) && current_col_type)
|
|
201
|
-
# 'type_cast' was changed to 'type_cast_from_database'
|
|
202
|
-
if Rails::VERSION::STRING < '4.2.0'
|
|
203
|
-
logger.debug("Assign #{current_value} => [#{operator}] (CAST 2 TYPE #{current_col_type.type_cast( current_value ).inspect})")
|
|
204
|
-
record.send( operator + '=' , current_method_detail.col_type.type_cast( current_value ) )
|
|
205
197
|
else
|
|
206
|
-
logger.debug("
|
|
207
|
-
record.send( operator + '=' , current_method_detail.col_type.type_cast_from_database( current_value ) )
|
|
208
|
-
end
|
|
198
|
+
logger.debug("Assignment via [#{operator}] to [#{value}] (NO CAST)")
|
|
209
199
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
200
|
+
# Good guide on diff ways to set attributes
|
|
201
|
+
# http://www.davidverhasselt.com/set-attributes-in-activerecord/
|
|
202
|
+
if(DataShift::Configuration.call.update_and_validate)
|
|
203
|
+
record.update( operator => value)
|
|
204
|
+
else
|
|
205
|
+
record.send( operator + '=', value)
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
rescue => e
|
|
209
|
+
logger.error e.backtrace.first
|
|
210
|
+
logger.error("Assignment failed #{e.inspect}")
|
|
211
|
+
raise DataProcessingError, "Failed to set [#{value}] via [#{operator}] due to ERROR : #{e.message}"
|
|
218
212
|
end
|
|
219
213
|
end
|
|
220
214
|
|
|
221
215
|
def insistent_assignment(record, value, operator)
|
|
222
216
|
|
|
223
|
-
op = operator + '=' unless
|
|
217
|
+
op = operator + '=' unless operator.include?('=')
|
|
224
218
|
|
|
219
|
+
# TODO: - fix this crap - perhaps recursion ??
|
|
225
220
|
begin
|
|
226
221
|
record.send(op, value)
|
|
227
|
-
rescue
|
|
222
|
+
rescue
|
|
223
|
+
begin
|
|
224
|
+
op = operator.downcase
|
|
225
|
+
op += '=' unless operator.include?('=')
|
|
228
226
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
227
|
+
record.send(op, value)
|
|
228
|
+
|
|
229
|
+
rescue => e
|
|
230
|
+
|
|
231
|
+
Populator.insistent_method_list.each do |f|
|
|
232
|
+
begin
|
|
233
|
+
record.send(op, value.send(f) )
|
|
234
|
+
break
|
|
235
|
+
rescue => e
|
|
236
|
+
if f == Populator.insistent_method_list.last
|
|
237
|
+
logger.error(e.inspect)
|
|
238
|
+
logger.error("Failed to assign [#{value}] via operator #{operator}")
|
|
239
|
+
raise DataProcessingError, "Failed to assign [#{value}] to #{operator}" unless value.nil?
|
|
240
|
+
end
|
|
238
241
|
end
|
|
239
242
|
end
|
|
240
243
|
end
|
|
@@ -242,48 +245,41 @@ module DataShift
|
|
|
242
245
|
end
|
|
243
246
|
|
|
244
247
|
# Attempt to find the associated object via id, name, title ....
|
|
245
|
-
def insistent_belongs_to(
|
|
248
|
+
def insistent_belongs_to(method_binding, record, value )
|
|
249
|
+
|
|
250
|
+
operator = method_binding.operator
|
|
246
251
|
|
|
247
|
-
|
|
252
|
+
klass = method_binding.model_method.operator_class
|
|
248
253
|
|
|
249
|
-
if
|
|
254
|
+
if value.class == klass
|
|
250
255
|
logger.info("Populator assigning #{value} to belongs_to association #{operator}")
|
|
251
256
|
record.send(operator) << value
|
|
252
257
|
else
|
|
253
258
|
|
|
254
|
-
|
|
255
|
-
|
|
259
|
+
unless method_binding.klass.respond_to?('where')
|
|
260
|
+
raise CouldNotAssignAssociation, "Populator failed to assign [#{value}] to belongs_to [#{operator}]"
|
|
261
|
+
end
|
|
256
262
|
|
|
257
|
-
|
|
263
|
+
# Try the default field names
|
|
258
264
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
else
|
|
263
|
-
logger.error("Could not find or create [#{value}] for belongs_to association [#{operator}]")
|
|
264
|
-
raise CouldNotAssignAssociation.new "Populator failed to assign [#{value}] to belongs_to association [#{operator}]"
|
|
265
|
-
end
|
|
265
|
+
# TODO: - add find by operators from headers or configuration to insistent_find_by_list
|
|
266
|
+
Populator.insistent_find_by_list.each do |find_by|
|
|
267
|
+
begin
|
|
266
268
|
|
|
267
|
-
|
|
268
|
-
#try the default field names
|
|
269
|
-
Populator::insistent_find_by_list.each do |x|
|
|
270
|
-
begin
|
|
269
|
+
item = klass.where(find_by => value).first_or_create
|
|
271
270
|
|
|
272
|
-
|
|
271
|
+
next unless item
|
|
273
272
|
|
|
274
|
-
|
|
273
|
+
logger.info("Populator assigning #{item.inspect} to belongs_to association #{operator}")
|
|
274
|
+
record.send(operator + '=', item)
|
|
275
|
+
break
|
|
275
276
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
logger.error(e.inspect)
|
|
283
|
-
logger.error("Failed attempting to find belongs_to for #{method_detail.pp}")
|
|
284
|
-
if(x == Populator::insistent_method_list.last)
|
|
285
|
-
raise CouldNotAssignAssociation.new "Populator failed to assign [#{value}] to belongs_to association [#{operator}]" unless value.nil?
|
|
286
|
-
end
|
|
277
|
+
rescue => e
|
|
278
|
+
logger.error(e.inspect)
|
|
279
|
+
logger.error("Failed attempting to find belongs_to for #{method_binding.pp}")
|
|
280
|
+
if find_by == Populator.insistent_method_list.last
|
|
281
|
+
raise CouldNotAssignAssociation,
|
|
282
|
+
"Populator failed to assign [#{value}] to belongs_to association [#{operator}]" unless value.nil?
|
|
287
283
|
end
|
|
288
284
|
end
|
|
289
285
|
end
|
|
@@ -291,154 +287,184 @@ module DataShift
|
|
|
291
287
|
end
|
|
292
288
|
end
|
|
293
289
|
|
|
294
|
-
def
|
|
290
|
+
def check_process_enum(record, model_method)
|
|
295
291
|
|
|
296
|
-
|
|
292
|
+
klass = model_method.klass
|
|
293
|
+
operator = model_method.operator
|
|
297
294
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
295
|
+
if klass.respond_to?(operator.pluralize)
|
|
296
|
+
|
|
297
|
+
enums = klass.send(operator.pluralize)
|
|
298
|
+
|
|
299
|
+
logger.debug("Checking for enum - #{enums.inspect} - #{value.parameterize.underscore}" )
|
|
300
|
+
|
|
301
|
+
if enums.is_a?(Hash) && enums.keys.include?(value.parameterize.underscore)
|
|
302
|
+
# ENUM
|
|
303
|
+
logger.debug("[#{operator}] Appears to be an ENUM - setting to [#{value}])")
|
|
304
|
+
|
|
305
|
+
# TODO: - now we know this column is an enum set operator type to :enum to save this check in future
|
|
306
|
+
# probably requires changes above to just assign enum directly without this check
|
|
307
|
+
model_method.operator_for(:assignment)
|
|
308
|
+
|
|
309
|
+
record.send( operator + '=', value.parameterize.underscore)
|
|
310
|
+
return true
|
|
311
311
|
end
|
|
312
312
|
end
|
|
313
313
|
end
|
|
314
314
|
|
|
315
|
+
def self.string_to_hash( str )
|
|
316
|
+
str.to_hash_object
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
private
|
|
315
320
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
#
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
# datashift_defaults:
|
|
322
|
-
# value_as_string: "Default Project Value"
|
|
323
|
-
# category: reference:category_002
|
|
324
|
-
#
|
|
325
|
-
# datashift_overrides:
|
|
326
|
-
# value_as_double: 99.23546
|
|
327
|
-
#
|
|
328
|
-
def configure_from(load_object_class, yaml_file)
|
|
321
|
+
attr_writer :value, :attribute_hash
|
|
322
|
+
|
|
323
|
+
# TOFIX - Does not belong in this class
|
|
324
|
+
def run_transforms(method_binding)
|
|
325
|
+
default( method_binding ) if value.blank?
|
|
329
326
|
|
|
330
|
-
|
|
327
|
+
override( method_binding )
|
|
331
328
|
|
|
332
|
-
|
|
329
|
+
substitute( method_binding )
|
|
330
|
+
|
|
331
|
+
prefix( method_binding )
|
|
332
|
+
|
|
333
|
+
postfix( method_binding )
|
|
334
|
+
|
|
335
|
+
# TODO: - enable clients to register their own transformation methods and call them here
|
|
336
|
+
end
|
|
333
337
|
|
|
334
|
-
|
|
338
|
+
# A single column can contain multiple lookup key:value definitions.
|
|
339
|
+
# These are delimited by special char defined in Delimiters
|
|
340
|
+
#
|
|
341
|
+
# For example:
|
|
342
|
+
#
|
|
343
|
+
# size:large | colour:red,green,blue |
|
|
344
|
+
#
|
|
345
|
+
def split_multi_assoc_value
|
|
346
|
+
value.to_s.split( multi_assoc_delim )
|
|
347
|
+
end
|
|
335
348
|
|
|
336
|
-
|
|
349
|
+
def assign_has_many(method_binding, load_object)
|
|
337
350
|
|
|
338
|
-
|
|
339
|
-
|
|
351
|
+
# there are times when we need to save early, for example before assigning to
|
|
352
|
+
# has_and_belongs_to associations which require the load_object has an id for the join table
|
|
340
353
|
|
|
341
|
-
|
|
354
|
+
load_object.save_if_new
|
|
342
355
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
logger.info("Set Populator overrides: #{override_values.inspect}")
|
|
356
|
+
collection = []
|
|
357
|
+
columns = []
|
|
346
358
|
|
|
347
|
-
|
|
359
|
+
if value.is_a?(Array)
|
|
348
360
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
361
|
+
value.each do |record|
|
|
362
|
+
if record.class.ancestors.include?(ActiveRecord::Base)
|
|
363
|
+
collection << record
|
|
364
|
+
else
|
|
365
|
+
columns << record
|
|
366
|
+
end
|
|
367
|
+
end
|
|
353
368
|
|
|
369
|
+
else
|
|
370
|
+
# A single column can contain multiple lookup key:value definitions, delimited by special char
|
|
371
|
+
# size:large | colour:red,green,blue => [where size: 'large'], [where colour: IN ['red,green,blue']
|
|
372
|
+
columns = split_multi_assoc_value
|
|
354
373
|
end
|
|
355
374
|
|
|
356
|
-
|
|
375
|
+
operator = method_binding.operator
|
|
357
376
|
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
substitutions[operator] ||= []
|
|
377
|
+
columns.each do |col_str|
|
|
378
|
+
# split into usable parts ; size:large or colour:red,green,blue
|
|
379
|
+
field, find_by_values = Querying.where_field_and_values(method_binding, col_str )
|
|
362
380
|
|
|
363
|
-
|
|
364
|
-
end
|
|
381
|
+
raise "Cannot perform DB find by #{field}. Expected format key:value" unless field && find_by_values
|
|
365
382
|
|
|
366
|
-
|
|
367
|
-
@substitutions ||= {}
|
|
368
|
-
end
|
|
383
|
+
found_values = []
|
|
369
384
|
|
|
370
|
-
|
|
371
|
-
|
|
385
|
+
# we are looking up an association so need the Class of the Association
|
|
386
|
+
klass = method_binding.model_method.operator_class
|
|
372
387
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
@current_value = @original_value_before_override.gsub(s.pattern.to_s, s.replacement.to_s)
|
|
376
|
-
end
|
|
377
|
-
end
|
|
388
|
+
raise CouldNotDeriveAssociationClass,
|
|
389
|
+
"Failed to find class for has_many Association : #{method_binding.pp}" unless klass
|
|
378
390
|
|
|
391
|
+
logger.info("Running where clause on #{klass} : [#{field} IN #{find_by_values.inspect}]")
|
|
379
392
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
393
|
+
find_by_values.each do |v|
|
|
394
|
+
begin
|
|
395
|
+
found_values << klass.where(field => v).first_or_create
|
|
396
|
+
rescue => e
|
|
397
|
+
logger.error(e.inspect)
|
|
398
|
+
logger.error("Failed to find or create #{klass} where #{field} => #{v}")
|
|
399
|
+
# TODO: some way to define if this is a fatal error or not ?
|
|
400
|
+
end
|
|
401
|
+
end
|
|
385
402
|
|
|
386
|
-
|
|
387
|
-
@override_values ||= {}
|
|
388
|
-
end
|
|
403
|
+
logger.info("Scan result #{found_values.inspect}")
|
|
389
404
|
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
405
|
+
unless find_by_values.size == found_values.size
|
|
406
|
+
found = found_values.collect { |f| f.send(field) }
|
|
407
|
+
load_object.errors.add( operator, "Association with key(s) #{(find_by_values - found).inspect} NOT found")
|
|
408
|
+
logger.error "Association [#{operator}] with key(s) #{(find_by_values - found).inspect} NOT found - Not added."
|
|
409
|
+
next if found_values.empty?
|
|
410
|
+
end
|
|
393
411
|
|
|
394
|
-
|
|
395
|
-
end
|
|
396
|
-
end
|
|
412
|
+
logger.info("Assigning to has_many [#{operator}] : #{found_values.inspect} (#{found_values.class})")
|
|
397
413
|
|
|
414
|
+
begin
|
|
415
|
+
load_object.send(operator) << found_values
|
|
416
|
+
rescue => e
|
|
417
|
+
logger.error e.inspect
|
|
418
|
+
logger.error "Cannot assign #{found_values.inspect} to has_many [#{operator}] "
|
|
419
|
+
end
|
|
398
420
|
|
|
399
|
-
|
|
400
|
-
|
|
421
|
+
logger.info("Assignment to has_many [#{operator}] COMPLETE)")
|
|
422
|
+
end # END HAS_MANY
|
|
401
423
|
end
|
|
402
424
|
|
|
403
|
-
#
|
|
404
|
-
# Generally defaults will be used when no value supplied.
|
|
405
|
-
def set_default_value(operator, value )
|
|
406
|
-
default_values[operator] = value
|
|
407
|
-
end
|
|
425
|
+
# Transformations
|
|
408
426
|
|
|
409
|
-
def
|
|
410
|
-
|
|
411
|
-
end
|
|
427
|
+
def default( method_binding )
|
|
428
|
+
default = Transformation.factory.default(method_binding)
|
|
412
429
|
|
|
413
|
-
|
|
414
|
-
def default_value(operator)
|
|
415
|
-
default_values[operator]
|
|
416
|
-
end
|
|
430
|
+
return unless default
|
|
417
431
|
|
|
418
|
-
|
|
419
|
-
|
|
432
|
+
@previous_value = value
|
|
433
|
+
@value = default
|
|
420
434
|
end
|
|
421
435
|
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
436
|
+
# Checks Transformation for a substitution for column defined in method_binding
|
|
437
|
+
def substitute( method_binding )
|
|
438
|
+
sub = Transformation.factory.substitution(method_binding)
|
|
425
439
|
|
|
426
|
-
|
|
427
|
-
@
|
|
440
|
+
return unless sub
|
|
441
|
+
@previous_value = value
|
|
442
|
+
@value = previous_value.gsub(sub.pattern.to_s, sub.replacement.to_s)
|
|
428
443
|
end
|
|
429
444
|
|
|
430
|
-
def
|
|
431
|
-
|
|
445
|
+
def override( method_binding )
|
|
446
|
+
override = Transformation.factory.override(method_binding)
|
|
447
|
+
|
|
448
|
+
return unless override
|
|
449
|
+
@previous_value = value
|
|
450
|
+
@value = override
|
|
432
451
|
end
|
|
433
452
|
|
|
434
|
-
def
|
|
435
|
-
|
|
453
|
+
def prefix( method_binding )
|
|
454
|
+
prefix = Transformation.factory.prefix(method_binding)
|
|
455
|
+
|
|
456
|
+
return unless prefix
|
|
457
|
+
@previous_value = value
|
|
458
|
+
@value = prefix + @value
|
|
436
459
|
end
|
|
437
460
|
|
|
438
|
-
def
|
|
439
|
-
|
|
461
|
+
def postfix( method_binding )
|
|
462
|
+
postfix = Transformation.factory.postfix(method_binding)
|
|
463
|
+
|
|
464
|
+
return unless postfix
|
|
465
|
+
@previous_value = value
|
|
466
|
+
@value += postfix
|
|
440
467
|
end
|
|
441
468
|
|
|
442
469
|
end
|
|
443
|
-
|
|
444
470
|
end
|