gooddata-edge 0.6.27.edge
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.document +5 -0
- data/.gitignore +36 -0
- data/.rspec +3 -0
- data/.rubocop.yml +89 -0
- data/.yardopts +22 -0
- data/CHANGELOG.md +196 -0
- data/CLI.md +439 -0
- data/DEPENDENCIES.md +817 -0
- data/Gemfile +4 -0
- data/Guardfile +5 -0
- data/LICENSE +22 -0
- data/LICENSE.rb +5 -0
- data/README.md +75 -0
- data/Rakefile +179 -0
- data/TODO.md +32 -0
- data/authors.sh +4 -0
- data/bin/gooddata +7 -0
- data/dependency_decisions.yml +104 -0
- data/gooddata +9 -0
- data/gooddata.gemspec +63 -0
- data/lib/gooddata.rb +31 -0
- data/lib/gooddata/app/app.rb +16 -0
- data/lib/gooddata/bricks/base_downloader.rb +86 -0
- data/lib/gooddata/bricks/brick.rb +38 -0
- data/lib/gooddata/bricks/bricks.rb +15 -0
- data/lib/gooddata/bricks/middleware/aws_middleware.rb +29 -0
- data/lib/gooddata/bricks/middleware/base_middleware.rb +56 -0
- data/lib/gooddata/bricks/middleware/bench_middleware.rb +24 -0
- data/lib/gooddata/bricks/middleware/bulk_salesforce_middleware.rb +37 -0
- data/lib/gooddata/bricks/middleware/decode_params_middleware.rb +20 -0
- data/lib/gooddata/bricks/middleware/fs_download_middleware.rb +48 -0
- data/lib/gooddata/bricks/middleware/fs_upload_middleware.rb +36 -0
- data/lib/gooddata/bricks/middleware/gooddata_middleware.rb +39 -0
- data/lib/gooddata/bricks/middleware/logger_middleware.rb +29 -0
- data/lib/gooddata/bricks/middleware/middleware.rb +12 -0
- data/lib/gooddata/bricks/middleware/restforce_middleware.rb +61 -0
- data/lib/gooddata/bricks/middleware/stdout_middleware.rb +23 -0
- data/lib/gooddata/bricks/middleware/twitter_middleware.rb +29 -0
- data/lib/gooddata/bricks/middleware/undot_params_middleware.rb +37 -0
- data/lib/gooddata/bricks/pipeline.rb +32 -0
- data/lib/gooddata/bricks/utils.rb +18 -0
- data/lib/gooddata/cli/cli.rb +27 -0
- data/lib/gooddata/cli/commands/auth_cmd.rb +29 -0
- data/lib/gooddata/cli/commands/domain_cmd.rb +28 -0
- data/lib/gooddata/cli/commands/project_cmd.rb +45 -0
- data/lib/gooddata/cli/hooks.rb +57 -0
- data/lib/gooddata/cli/shared.rb +61 -0
- data/lib/gooddata/cli/terminal.rb +20 -0
- data/lib/gooddata/client.rb +67 -0
- data/lib/gooddata/commands/api.rb +64 -0
- data/lib/gooddata/commands/auth.rb +107 -0
- data/lib/gooddata/commands/base.rb +12 -0
- data/lib/gooddata/commands/commands.rb +12 -0
- data/lib/gooddata/commands/datasets.rb +148 -0
- data/lib/gooddata/commands/datawarehouse.rb +20 -0
- data/lib/gooddata/commands/domain.rb +40 -0
- data/lib/gooddata/commands/process.rb +67 -0
- data/lib/gooddata/commands/project.rb +175 -0
- data/lib/gooddata/commands/projects.rb +20 -0
- data/lib/gooddata/commands/role.rb +36 -0
- data/lib/gooddata/commands/runners.rb +47 -0
- data/lib/gooddata/commands/scaffold.rb +69 -0
- data/lib/gooddata/commands/user.rb +39 -0
- data/lib/gooddata/connection.rb +127 -0
- data/lib/gooddata/core/core.rb +12 -0
- data/lib/gooddata/core/logging.rb +105 -0
- data/lib/gooddata/core/nil_logger.rb +23 -0
- data/lib/gooddata/core/project.rb +74 -0
- data/lib/gooddata/core/rest.rb +149 -0
- data/lib/gooddata/core/user.rb +20 -0
- data/lib/gooddata/data/data.rb +12 -0
- data/lib/gooddata/data/guesser.rb +122 -0
- data/lib/gooddata/exceptions/attr_element_not_found.rb +16 -0
- data/lib/gooddata/exceptions/command_failed.rb +11 -0
- data/lib/gooddata/exceptions/exceptions.rb +12 -0
- data/lib/gooddata/exceptions/execution_limit_exceeded.rb +13 -0
- data/lib/gooddata/exceptions/filter_maqlization.rb +16 -0
- data/lib/gooddata/exceptions/malformed_user.rb +15 -0
- data/lib/gooddata/exceptions/no_project_error.rb +15 -0
- data/lib/gooddata/exceptions/object_migration.rb +32 -0
- data/lib/gooddata/exceptions/project_not_found.rb +13 -0
- data/lib/gooddata/exceptions/segment_not_empty.rb +18 -0
- data/lib/gooddata/exceptions/uncomputable_report.rb +13 -0
- data/lib/gooddata/exceptions/user_in_different_domain.rb +15 -0
- data/lib/gooddata/exceptions/validation_error.rb +16 -0
- data/lib/gooddata/extensions/big_decimal.rb +17 -0
- data/lib/gooddata/extensions/enumerable.rb +39 -0
- data/lib/gooddata/extensions/extensions.rb +10 -0
- data/lib/gooddata/extensions/false.rb +15 -0
- data/lib/gooddata/extensions/hash.rb +38 -0
- data/lib/gooddata/extensions/nil.rb +15 -0
- data/lib/gooddata/extensions/numeric.rb +15 -0
- data/lib/gooddata/extensions/object.rb +27 -0
- data/lib/gooddata/extensions/symbol.rb +15 -0
- data/lib/gooddata/extensions/true.rb +15 -0
- data/lib/gooddata/extract.rb +21 -0
- data/lib/gooddata/goodzilla/goodzilla.rb +159 -0
- data/lib/gooddata/helpers/auth_helpers.rb +75 -0
- data/lib/gooddata/helpers/csv_helper.rb +61 -0
- data/lib/gooddata/helpers/data_helper.rb +116 -0
- data/lib/gooddata/helpers/global_helpers.rb +331 -0
- data/lib/gooddata/helpers/global_helpers_params.rb +172 -0
- data/lib/gooddata/helpers/helpers.rb +10 -0
- data/lib/gooddata/mixins/author.rb +26 -0
- data/lib/gooddata/mixins/content_getter.rb +15 -0
- data/lib/gooddata/mixins/content_property_reader.rb +17 -0
- data/lib/gooddata/mixins/content_property_writer.rb +17 -0
- data/lib/gooddata/mixins/contributor.rb +20 -0
- data/lib/gooddata/mixins/data_getter.rb +15 -0
- data/lib/gooddata/mixins/data_property_reader.rb +19 -0
- data/lib/gooddata/mixins/data_property_writer.rb +19 -0
- data/lib/gooddata/mixins/inspector.rb +53 -0
- data/lib/gooddata/mixins/is_attribute.rb +17 -0
- data/lib/gooddata/mixins/is_dimension.rb +17 -0
- data/lib/gooddata/mixins/is_fact.rb +17 -0
- data/lib/gooddata/mixins/is_label.rb +19 -0
- data/lib/gooddata/mixins/links.rb +15 -0
- data/lib/gooddata/mixins/md_finders.rb +77 -0
- data/lib/gooddata/mixins/md_grantees.rb +42 -0
- data/lib/gooddata/mixins/md_id_to_uri.rb +34 -0
- data/lib/gooddata/mixins/md_json.rb +15 -0
- data/lib/gooddata/mixins/md_lock.rb +87 -0
- data/lib/gooddata/mixins/md_object_id.rb +15 -0
- data/lib/gooddata/mixins/md_object_indexer.rb +64 -0
- data/lib/gooddata/mixins/md_object_query.rb +128 -0
- data/lib/gooddata/mixins/md_relations.rb +43 -0
- data/lib/gooddata/mixins/meta_getter.rb +17 -0
- data/lib/gooddata/mixins/meta_property_reader.rb +19 -0
- data/lib/gooddata/mixins/meta_property_writer.rb +19 -0
- data/lib/gooddata/mixins/mixins.rb +19 -0
- data/lib/gooddata/mixins/not_attribute.rb +17 -0
- data/lib/gooddata/mixins/not_exportable.rb +15 -0
- data/lib/gooddata/mixins/not_fact.rb +17 -0
- data/lib/gooddata/mixins/not_group.rb +17 -0
- data/lib/gooddata/mixins/not_label.rb +19 -0
- data/lib/gooddata/mixins/not_metric.rb +19 -0
- data/lib/gooddata/mixins/obj_id.rb +15 -0
- data/lib/gooddata/mixins/rest_getters.rb +17 -0
- data/lib/gooddata/mixins/rest_resource.rb +47 -0
- data/lib/gooddata/mixins/root_key_getter.rb +15 -0
- data/lib/gooddata/mixins/root_key_setter.rb +15 -0
- data/lib/gooddata/mixins/timestamps.rb +19 -0
- data/lib/gooddata/mixins/to_json.rb +11 -0
- data/lib/gooddata/mixins/uri_getter.rb +9 -0
- data/lib/gooddata/models/blueprint/anchor_field.rb +64 -0
- data/lib/gooddata/models/blueprint/attribute_field.rb +29 -0
- data/lib/gooddata/models/blueprint/blueprint.rb +11 -0
- data/lib/gooddata/models/blueprint/blueprint_field.rb +70 -0
- data/lib/gooddata/models/blueprint/dashboard_builder.rb +30 -0
- data/lib/gooddata/models/blueprint/dataset_blueprint.rb +449 -0
- data/lib/gooddata/models/blueprint/date_dimension.rb +14 -0
- data/lib/gooddata/models/blueprint/fact_field.rb +20 -0
- data/lib/gooddata/models/blueprint/label_field.rb +43 -0
- data/lib/gooddata/models/blueprint/project_blueprint.rb +746 -0
- data/lib/gooddata/models/blueprint/project_builder.rb +83 -0
- data/lib/gooddata/models/blueprint/reference_field.rb +43 -0
- data/lib/gooddata/models/blueprint/schema_blueprint.rb +160 -0
- data/lib/gooddata/models/blueprint/schema_builder.rb +89 -0
- data/lib/gooddata/models/blueprint/to_manifest.rb +181 -0
- data/lib/gooddata/models/blueprint/to_wire.rb +154 -0
- data/lib/gooddata/models/client.rb +182 -0
- data/lib/gooddata/models/client_synchronization_result.rb +31 -0
- data/lib/gooddata/models/client_synchronization_result_details.rb +41 -0
- data/lib/gooddata/models/datawarehouse.rb +92 -0
- data/lib/gooddata/models/domain.rb +479 -0
- data/lib/gooddata/models/execution.rb +115 -0
- data/lib/gooddata/models/execution_detail.rb +81 -0
- data/lib/gooddata/models/from_wire.rb +160 -0
- data/lib/gooddata/models/invitation.rb +75 -0
- data/lib/gooddata/models/links.rb +50 -0
- data/lib/gooddata/models/membership.rb +441 -0
- data/lib/gooddata/models/metadata.rb +272 -0
- data/lib/gooddata/models/metadata/attribute.rb +134 -0
- data/lib/gooddata/models/metadata/dashboard.rb +108 -0
- data/lib/gooddata/models/metadata/dashboard/dashboard_item.rb +76 -0
- data/lib/gooddata/models/metadata/dashboard/filter_apply_item.rb +37 -0
- data/lib/gooddata/models/metadata/dashboard/filter_item.rb +64 -0
- data/lib/gooddata/models/metadata/dashboard/geo_chart_item.rb +56 -0
- data/lib/gooddata/models/metadata/dashboard/headline_item.rb +56 -0
- data/lib/gooddata/models/metadata/dashboard/iframe_item.rb +46 -0
- data/lib/gooddata/models/metadata/dashboard/report_item.rb +92 -0
- data/lib/gooddata/models/metadata/dashboard/text_item.rb +55 -0
- data/lib/gooddata/models/metadata/dashboard_tab.rb +141 -0
- data/lib/gooddata/models/metadata/dataset.rb +64 -0
- data/lib/gooddata/models/metadata/dimension.rb +54 -0
- data/lib/gooddata/models/metadata/fact.rb +44 -0
- data/lib/gooddata/models/metadata/label.rb +128 -0
- data/lib/gooddata/models/metadata/metadata.rb +12 -0
- data/lib/gooddata/models/metadata/metric.rb +198 -0
- data/lib/gooddata/models/metadata/report.rb +247 -0
- data/lib/gooddata/models/metadata/report_definition.rb +264 -0
- data/lib/gooddata/models/metadata/scheduled_mail.rb +274 -0
- data/lib/gooddata/models/metadata/scheduled_mail/dashboard_attachment.rb +62 -0
- data/lib/gooddata/models/metadata/scheduled_mail/report_attachment.rb +64 -0
- data/lib/gooddata/models/metadata/variable.rb +91 -0
- data/lib/gooddata/models/model.rb +282 -0
- data/lib/gooddata/models/models.rb +12 -0
- data/lib/gooddata/models/module_constants.rb +31 -0
- data/lib/gooddata/models/process.rb +316 -0
- data/lib/gooddata/models/profile.rb +426 -0
- data/lib/gooddata/models/project.rb +1514 -0
- data/lib/gooddata/models/project_creator.rb +126 -0
- data/lib/gooddata/models/project_metadata.rb +67 -0
- data/lib/gooddata/models/project_role.rb +79 -0
- data/lib/gooddata/models/report_data_result.rb +266 -0
- data/lib/gooddata/models/schedule.rb +518 -0
- data/lib/gooddata/models/segment.rb +201 -0
- data/lib/gooddata/models/tab_builder.rb +27 -0
- data/lib/gooddata/models/user_filters/mandatory_user_filter.rb +76 -0
- data/lib/gooddata/models/user_filters/user_filter.rb +100 -0
- data/lib/gooddata/models/user_filters/user_filter_builder.rb +512 -0
- data/lib/gooddata/models/user_filters/user_filters.rb +13 -0
- data/lib/gooddata/models/user_filters/variable_user_filter.rb +31 -0
- data/lib/gooddata/models/user_group.rb +241 -0
- data/lib/gooddata/rest/README.md +37 -0
- data/lib/gooddata/rest/client.rb +389 -0
- data/lib/gooddata/rest/connection.rb +765 -0
- data/lib/gooddata/rest/object.rb +69 -0
- data/lib/gooddata/rest/object_factory.rb +76 -0
- data/lib/gooddata/rest/resource.rb +27 -0
- data/lib/gooddata/rest/rest.rb +24 -0
- data/lib/gooddata/version.rb +23 -0
- data/lib/templates/bricks/brick.rb.erb +7 -0
- data/lib/templates/bricks/main.rb.erb +5 -0
- data/lib/templates/project/Goodfile.erb +4 -0
- data/lib/templates/project/data/commits.csv +4 -0
- data/lib/templates/project/data/devs.csv +4 -0
- data/lib/templates/project/data/repos.csv +3 -0
- data/lib/templates/project/model/model.rb.erb +20 -0
- data/spec/bricks/bricks_spec.rb +112 -0
- data/spec/bricks/default-config.json +8 -0
- data/spec/data/.gooddata +4 -0
- data/spec/data/blueprints/additional_dataset_module.json +32 -0
- data/spec/data/blueprints/big_blueprint_not_pruned.json +2079 -0
- data/spec/data/blueprints/invalid_blueprint.json +103 -0
- data/spec/data/blueprints/m_n_model.json +104 -0
- data/spec/data/blueprints/model_module.json +25 -0
- data/spec/data/blueprints/test_blueprint.json +38 -0
- data/spec/data/blueprints/test_project_model_spec.json +106 -0
- data/spec/data/cc/data/source/commits.csv +4 -0
- data/spec/data/cc/data/source/devs.csv +4 -0
- data/spec/data/cc/data/source/repos.csv +3 -0
- data/spec/data/cc/devel.prm +0 -0
- data/spec/data/cc/graph/graph.grf +11 -0
- data/spec/data/cc/workspace.prm +19 -0
- data/spec/data/column_based_permissions.csv +7 -0
- data/spec/data/column_based_permissions2.csv +6 -0
- data/spec/data/gd_gse_data_blueprint.json +1371 -0
- data/spec/data/gd_gse_data_manifest.json +1424 -0
- data/spec/data/gd_gse_data_model.json +1772 -0
- data/spec/data/gooddata_version_process/gooddata_version.rb +9 -0
- data/spec/data/gooddata_version_process/gooddata_version.zip +0 -0
- data/spec/data/hello_world_process/hello_world.rb +9 -0
- data/spec/data/hello_world_process/hello_world.zip +0 -0
- data/spec/data/line_based_permissions.csv +3 -0
- data/spec/data/manifests/test_blueprint.json +32 -0
- data/spec/data/manifests/test_project.json +107 -0
- data/spec/data/reports/left_attr_report.json +108 -0
- data/spec/data/reports/metric_only_one_line.json +83 -0
- data/spec/data/reports/report_1.json +197 -0
- data/spec/data/reports/top_attr_report.json +108 -0
- data/spec/data/ruby_params_process/ruby_params.rb +9 -0
- data/spec/data/ruby_process/deep_files/deep_stuff.txt +1 -0
- data/spec/data/ruby_process/process.rb +8 -0
- data/spec/data/ruby_process/stuff.txt +1 -0
- data/spec/data/superfluous_titles_view.json +81 -0
- data/spec/data/test-ci-data.csv +2 -0
- data/spec/data/users.csv +12 -0
- data/spec/data/wire_models/model_view.json +1775 -0
- data/spec/data/wire_models/nu_model.json +3046 -0
- data/spec/data/wire_models/test_blueprint.json +63 -0
- data/spec/data/wire_test_project.json +150 -0
- data/spec/environment/default.rb +41 -0
- data/spec/environment/develop.rb +31 -0
- data/spec/environment/environment.rb +18 -0
- data/spec/environment/hotfix.rb +21 -0
- data/spec/environment/production.rb +35 -0
- data/spec/environment/release.rb +21 -0
- data/spec/environment/staging.rb +30 -0
- data/spec/environment/staging_3.rb +36 -0
- data/spec/helpers/blueprint_helper.rb +26 -0
- data/spec/helpers/cli_helper.rb +36 -0
- data/spec/helpers/connection_helper.rb +41 -0
- data/spec/helpers/crypto_helper.rb +17 -0
- data/spec/helpers/csv_helper.rb +18 -0
- data/spec/helpers/process_helper.rb +33 -0
- data/spec/helpers/project_helper.rb +59 -0
- data/spec/helpers/schedule_helper.rb +31 -0
- data/spec/helpers/spec_helper.rb +15 -0
- data/spec/integration/blueprint_updates_spec.rb +101 -0
- data/spec/integration/blueprint_with_grain_spec.rb +72 -0
- data/spec/integration/clients_spec.rb +134 -0
- data/spec/integration/command_datawarehouse_spec.rb +39 -0
- data/spec/integration/command_projects_spec.rb +32 -0
- data/spec/integration/create_from_template_spec.rb +22 -0
- data/spec/integration/create_project_spec.rb +24 -0
- data/spec/integration/date_dim_switch_spec.rb +142 -0
- data/spec/integration/deprecated_load_spec.rb +58 -0
- data/spec/integration/full_process_schedule_spec.rb +298 -0
- data/spec/integration/full_project_spec.rb +569 -0
- data/spec/integration/over_to_user_filters_spec.rb +94 -0
- data/spec/integration/partial_md_export_import_spec.rb +42 -0
- data/spec/integration/project_spec.rb +264 -0
- data/spec/integration/rest_spec.rb +213 -0
- data/spec/integration/schedule_spec.rb +626 -0
- data/spec/integration/segments_spec.rb +141 -0
- data/spec/integration/user_filters_spec.rb +290 -0
- data/spec/integration/user_group_spec.rb +127 -0
- data/spec/integration/variables_spec.rb +188 -0
- data/spec/logging_in_logging_out_spec.rb +93 -0
- data/spec/spec_helper.rb +95 -0
- data/spec/unit/bricks/bricks_spec.rb +35 -0
- data/spec/unit/bricks/middleware/aws_middelware_spec.rb +51 -0
- data/spec/unit/bricks/middleware/bench_middleware_spec.rb +15 -0
- data/spec/unit/bricks/middleware/bulk_salesforce_middleware_spec.rb +15 -0
- data/spec/unit/bricks/middleware/gooddata_middleware_spec.rb +15 -0
- data/spec/unit/bricks/middleware/logger_middleware_spec.rb +15 -0
- data/spec/unit/bricks/middleware/restforce_middleware_spec.rb +15 -0
- data/spec/unit/bricks/middleware/stdout_middleware_spec.rb +15 -0
- data/spec/unit/bricks/middleware/twitter_middleware_spec.rb +15 -0
- data/spec/unit/cli/cli_spec.rb +17 -0
- data/spec/unit/cli/commands/cmd_auth_spec.rb +17 -0
- data/spec/unit/commands/command_projects_spec.rb +22 -0
- data/spec/unit/core/connection_spec.rb +57 -0
- data/spec/unit/core/logging_spec.rb +133 -0
- data/spec/unit/core/nil_logger_spec.rb +13 -0
- data/spec/unit/core/project_spec.rb +54 -0
- data/spec/unit/extensions/hash_spec.rb +23 -0
- data/spec/unit/godzilla/goodzilla_spec.rb +78 -0
- data/spec/unit/helpers/csv_helper_spec.rb +22 -0
- data/spec/unit/helpers/data_helper_spec.rb +61 -0
- data/spec/unit/helpers/global_helpers_spec.rb +111 -0
- data/spec/unit/helpers_spec.rb +86 -0
- data/spec/unit/models/blueprint/attributes_spec.rb +29 -0
- data/spec/unit/models/blueprint/dataset_spec.rb +121 -0
- data/spec/unit/models/blueprint/labels_spec.rb +44 -0
- data/spec/unit/models/blueprint/project_blueprint_spec.rb +648 -0
- data/spec/unit/models/blueprint/reference_spec.rb +29 -0
- data/spec/unit/models/blueprint/schema_builder_spec.rb +38 -0
- data/spec/unit/models/blueprint/to_wire_spec.rb +174 -0
- data/spec/unit/models/domain_spec.rb +144 -0
- data/spec/unit/models/execution_spec.rb +108 -0
- data/spec/unit/models/from_wire_spec.rb +296 -0
- data/spec/unit/models/invitation_spec.rb +17 -0
- data/spec/unit/models/membership_spec.rb +132 -0
- data/spec/unit/models/metadata_spec.rb +104 -0
- data/spec/unit/models/metric_spec.rb +117 -0
- data/spec/unit/models/model_spec.rb +82 -0
- data/spec/unit/models/params_spec.rb +118 -0
- data/spec/unit/models/profile_spec.rb +215 -0
- data/spec/unit/models/project_creator_spec.rb +127 -0
- data/spec/unit/models/project_role_spec.rb +94 -0
- data/spec/unit/models/project_spec.rb +162 -0
- data/spec/unit/models/report_result_data_spec.rb +199 -0
- data/spec/unit/models/schedule_spec.rb +418 -0
- data/spec/unit/models/to_manifest_spec.rb +63 -0
- data/spec/unit/models/unit_project_spec.rb +125 -0
- data/spec/unit/models/user_filters_spec.rb +95 -0
- data/spec/unit/models/variable_spec.rb +265 -0
- data/spec/unit/rest/polling_spec.rb +89 -0
- data/spec/unit/rest/resource_spec.rb +10 -0
- data/yard-server.sh +3 -0
- metadata +1125 -0
@@ -0,0 +1,126 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
#
|
3
|
+
# Copyright (c) 2010-2015 GoodData Corporation. All rights reserved.
|
4
|
+
# This source code is licensed under the BSD-style license found in the
|
5
|
+
# LICENSE file in the root directory of this source tree.
|
6
|
+
|
7
|
+
require_relative 'project'
|
8
|
+
require_relative 'blueprint/project_blueprint'
|
9
|
+
|
10
|
+
require 'open-uri'
|
11
|
+
|
12
|
+
module GoodData
|
13
|
+
module Model
|
14
|
+
class ProjectCreator
|
15
|
+
class << self
|
16
|
+
def migrate(opts = {})
|
17
|
+
opts = { client: GoodData.connection }.merge(opts)
|
18
|
+
client = opts[:client]
|
19
|
+
fail ArgumentError, 'No :client specified' if client.nil?
|
20
|
+
|
21
|
+
spec = opts[:spec] || fail('You need to provide spec for migration')
|
22
|
+
bp = ProjectBlueprint.new(spec)
|
23
|
+
fail GoodData::ValidationError, "Blueprint is invalid #{bp.validate.inspect}" unless bp.valid?
|
24
|
+
spec = bp.to_hash
|
25
|
+
|
26
|
+
project = opts[:project] || client.create_project(opts.merge(:title => spec[:title], :client => client, :environment => opts[:environment]))
|
27
|
+
|
28
|
+
begin
|
29
|
+
migrate_datasets(spec, opts.merge(project: project, client: client))
|
30
|
+
load(p, spec)
|
31
|
+
migrate_metrics(p, spec[:metrics] || [])
|
32
|
+
migrate_reports(p, spec[:reports] || [])
|
33
|
+
migrate_dashboards(p, spec[:dashboards] || [])
|
34
|
+
execute_tests(p, spec[:assert_tests] || [])
|
35
|
+
project
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def migrate_datasets(spec, opts = {})
|
40
|
+
opts = { client: GoodData.connection }.merge(opts)
|
41
|
+
dry_run = opts[:dry_run]
|
42
|
+
|
43
|
+
client, project = GoodData.get_client_and_project(opts)
|
44
|
+
|
45
|
+
bp = ProjectBlueprint.new(spec)
|
46
|
+
uri = "/gdc/projects/#{project.pid}/model/diff?includeGrain=true"
|
47
|
+
result = client.post(uri, bp.to_wire)
|
48
|
+
|
49
|
+
link = result['asyncTask']['link']['poll']
|
50
|
+
response = client.get(link, :process => false)
|
51
|
+
|
52
|
+
while response.code != 200
|
53
|
+
sleep 1
|
54
|
+
GoodData::Rest::Client.retryable(:tries => 3) do
|
55
|
+
sleep 1
|
56
|
+
response = client.get(link, :process => false)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
response = client.get(link)
|
61
|
+
|
62
|
+
chunks = pick_correct_chunks(response['projectModelDiff']['updateScripts'], opts)
|
63
|
+
if !chunks.nil? && !dry_run
|
64
|
+
chunks['updateScript']['maqlDdlChunks'].each do |chunk|
|
65
|
+
result = project.execute_maql(chunk)
|
66
|
+
fail 'Creating dataset failed' if result['wTaskStatus']['status'] == 'ERROR'
|
67
|
+
end
|
68
|
+
end
|
69
|
+
chunks
|
70
|
+
end
|
71
|
+
|
72
|
+
def migrate_reports(project, spec)
|
73
|
+
spec.each do |report|
|
74
|
+
project.add_report(report)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def migrate_dashboards(project, spec)
|
79
|
+
spec.each do |dash|
|
80
|
+
project.add_dashboard(dash)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def migrate_metrics(project, spec)
|
85
|
+
spec.each do |metric|
|
86
|
+
project.add_metric(metric)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
alias_method :migrate_measures, :migrate_metrics
|
91
|
+
|
92
|
+
def load(project, spec)
|
93
|
+
if spec.key?(:uploads) # rubocop:disable Style/GuardClause
|
94
|
+
spec[:uploads].each do |load|
|
95
|
+
schema = GoodData::Model::Schema.new(spec[:datasets].find { |d| d[:name] == load[:dataset] })
|
96
|
+
project.upload(load[:source], schema, load[:mode])
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
def execute_tests(_project, spec)
|
102
|
+
spec.each do |assert|
|
103
|
+
result = GoodData::ReportDefinition.execute(assert[:report])
|
104
|
+
fail "Test did not pass. Got #{result.table.inspect}, expected #{assert[:result].inspect}" if result.table != assert[:result]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def pick_correct_chunks(chunks, opts = {})
|
109
|
+
preference = opts[:preference] || {}
|
110
|
+
# first is cascadeDrops, second is preserveData
|
111
|
+
rules = [
|
112
|
+
{ priority: 1, cascade_drops: false, preserve_data: true },
|
113
|
+
{ priority: 2, cascade_drops: false, preserve_data: false },
|
114
|
+
{ priority: 3, cascade_drops: true, preserve_data: true },
|
115
|
+
{ priority: 4, cascade_drops: true, preserve_data: false }
|
116
|
+
]
|
117
|
+
stuff = chunks.select { |chunk| chunk['updateScript']['maqlDdlChunks'] }.map { |chunk| { cascade_drops: chunk['updateScript']['cascadeDrops'], preserve_data: chunk['updateScript']['preserveData'], maql: chunk['updateScript']['maqlDdlChunks'], orig: chunk } }
|
118
|
+
results = GoodData::Helpers.join(rules, stuff, [:cascade_drops, :preserve_data], [:cascade_drops, :preserve_data], inner: true).sort_by { |l| l[:priority] }
|
119
|
+
|
120
|
+
pick = results.find { |r| r.values_at(:cascade_drops, :preserve_data) == preference.values_at(:cascade_drops, :preserve_data) } || results.first
|
121
|
+
pick[:orig] if pick
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
#
|
3
|
+
# Copyright (c) 2010-2015 GoodData Corporation. All rights reserved.
|
4
|
+
# This source code is licensed under the BSD-style license found in the
|
5
|
+
# LICENSE file in the root directory of this source tree.
|
6
|
+
|
7
|
+
module GoodData
|
8
|
+
class ProjectMetadata
|
9
|
+
class << self
|
10
|
+
def keys(opts = { :client => GoodData.connection, :project => GoodData.project })
|
11
|
+
ProjectMetadata[:all, opts].keys
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](key, opts = { :client => GoodData.connection, :project => GoodData.project })
|
15
|
+
client, project = GoodData.get_client_and_project(opts)
|
16
|
+
|
17
|
+
get_opts = {
|
18
|
+
do_not_log: [
|
19
|
+
RestClient::ResourceNotFound
|
20
|
+
]
|
21
|
+
}
|
22
|
+
|
23
|
+
if key == :all
|
24
|
+
uri = "/gdc/projects/#{project.pid}/dataload/metadata"
|
25
|
+
res = client.get(uri, get_opts)
|
26
|
+
res['metadataItems']['items'].reduce({}) do |memo, i|
|
27
|
+
memo[i['metadataItem']['key']] = i['metadataItem']['value']
|
28
|
+
memo
|
29
|
+
end
|
30
|
+
else
|
31
|
+
uri = "/gdc/projects/#{project.pid}/dataload/metadata/#{key}"
|
32
|
+
res = client.get(uri, get_opts)
|
33
|
+
res['metadataItem']['value']
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
alias_method :get, :[]
|
38
|
+
alias_method :get_key, :[]
|
39
|
+
|
40
|
+
def key?(key, opts = { :client => GoodData.connection, :project => GoodData.project })
|
41
|
+
ProjectMetadata[key, opts]
|
42
|
+
true
|
43
|
+
rescue RestClient::ResourceNotFound
|
44
|
+
false
|
45
|
+
end
|
46
|
+
|
47
|
+
def []=(key, opts = { :client => GoodData.connection, :project => GoodData.project }, val = nil)
|
48
|
+
client, project = GoodData.get_client_and_project(opts)
|
49
|
+
|
50
|
+
data = {
|
51
|
+
:metadataItem => {
|
52
|
+
:key => key,
|
53
|
+
:value => val
|
54
|
+
}
|
55
|
+
}
|
56
|
+
uri = "/gdc/projects/#{project.pid}/dataload/metadata/"
|
57
|
+
update_uri = uri + key
|
58
|
+
|
59
|
+
if key?(key, opts)
|
60
|
+
client.put(update_uri, data)
|
61
|
+
else
|
62
|
+
client.post(uri, data)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
#
|
3
|
+
# Copyright (c) 2010-2015 GoodData Corporation. All rights reserved.
|
4
|
+
# This source code is licensed under the BSD-style license found in the
|
5
|
+
# LICENSE file in the root directory of this source tree.
|
6
|
+
|
7
|
+
require 'pmap'
|
8
|
+
|
9
|
+
require_relative 'profile'
|
10
|
+
|
11
|
+
require_relative '../rest/rest'
|
12
|
+
|
13
|
+
require_relative '../mixins/rest_resource'
|
14
|
+
|
15
|
+
module GoodData
|
16
|
+
class ProjectRole < Rest::Resource
|
17
|
+
include Mixin::Author
|
18
|
+
include Mixin::Contributor
|
19
|
+
include Mixin::Timestamps
|
20
|
+
|
21
|
+
EMPTY_OBJECT = {
|
22
|
+
'projectRole' => {
|
23
|
+
'permissions' => {},
|
24
|
+
'links' => {},
|
25
|
+
'meta' => {}
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
def self.create_object(data)
|
30
|
+
meta_data = {}.tap do |d|
|
31
|
+
d[:created] = data[:created] || Time.now
|
32
|
+
d[:identifier] = data[:identifier]
|
33
|
+
d[:updated] = data[:updated] || d[:created] || Time.now
|
34
|
+
d[:title] = data[:title]
|
35
|
+
d[:summary] = data[:summary]
|
36
|
+
end
|
37
|
+
new_data = GoodData::Helpers.deep_dup(EMPTY_OBJECT).tap do |d|
|
38
|
+
d['projectRole']['links']['self'] = data[:uri] if data[:uri]
|
39
|
+
d['projectRole']['meta'] = d['projectRole']['meta'].merge(GoodData::Helpers.stringify_keys(meta_data))
|
40
|
+
d['projectRole']['permissions'] = d['projectRole']['permissions'].merge(GoodData::Helpers.stringify_keys(data[:permissions] || {}))
|
41
|
+
end
|
42
|
+
new(new_data)
|
43
|
+
end
|
44
|
+
|
45
|
+
def initialize(json)
|
46
|
+
@json = json
|
47
|
+
end
|
48
|
+
|
49
|
+
data_property_reader :permissions
|
50
|
+
|
51
|
+
metadata_property_reader :identifier, :title, :summary
|
52
|
+
|
53
|
+
# Gets Users with this Role
|
54
|
+
#
|
55
|
+
# @return [Array<GoodData::Profile>] List of users
|
56
|
+
def users
|
57
|
+
url = data['links']['roleUsers']
|
58
|
+
tmp = client.get url
|
59
|
+
tmp['associatedUsers']['users'].pmap do |user_url|
|
60
|
+
url = user_url
|
61
|
+
user = client.get url
|
62
|
+
client.create(GoodData::Profile, user)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Gets Raw object URI
|
67
|
+
#
|
68
|
+
# @return [string] URI of this project role
|
69
|
+
def uri
|
70
|
+
return @json['projectRole']['links']['self'] if @json['projectRole']['links']['self']
|
71
|
+
return nil unless @json['projectRole']['links']['roleUsers']
|
72
|
+
@json['projectRole']['links']['roleUsers'].split('/')[0...-1].join('/')
|
73
|
+
end
|
74
|
+
|
75
|
+
def ==(other)
|
76
|
+
uri == other.uri
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,266 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
#
|
3
|
+
# Copyright (c) 2010-2015 GoodData Corporation. All rights reserved.
|
4
|
+
# This source code is licensed under the BSD-style license found in the
|
5
|
+
# LICENSE file in the root directory of this source tree.
|
6
|
+
|
7
|
+
module GoodData
|
8
|
+
class ReportDataResult < Rest::Resource
|
9
|
+
class << self
|
10
|
+
# Does all the needed parsing on the apyload coming from the API and returns an instance of ReportDataResult
|
11
|
+
#
|
12
|
+
# @param [Hash] data Data coming from the API
|
13
|
+
# @return [GoodData::ReportDataResult] Returns new report data result
|
14
|
+
def from_xtab(data)
|
15
|
+
top = top_headers(data)
|
16
|
+
left = left_headers(data)
|
17
|
+
jank = GoodData::Helpers.zeroes(rows(top), cols(left), nil)
|
18
|
+
d = data(data)
|
19
|
+
stuff = d.empty? ? GoodData::Helpers.zeroes(rows(left), cols(top), nil) : d
|
20
|
+
|
21
|
+
a = jank.zip(top).map { |x, y| x + y }
|
22
|
+
b = left.zip(stuff).map { |x, y| x + y }
|
23
|
+
result = a + b
|
24
|
+
ReportDataResult.new(data: result, top: rows(top), left: cols(left))
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def line(child)
|
30
|
+
children = child['children'] || []
|
31
|
+
return (child['first']..child['last']).to_a.map { [child['id']] } if children.empty?
|
32
|
+
children.flat_map { |c| line(c) }.map do |x|
|
33
|
+
child['id'].nil? ? x : [child['id']] + x
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def root_line(root)
|
38
|
+
lookups = root['lookups']
|
39
|
+
header = line(root['tree'])
|
40
|
+
header.map { |l| l.each_with_index.map { |item, index| lookups[index][item] } }
|
41
|
+
end
|
42
|
+
|
43
|
+
def top_headers(data)
|
44
|
+
root = data['xtab_data']['columns']
|
45
|
+
root_line(root).transpose
|
46
|
+
end
|
47
|
+
|
48
|
+
def left_headers(data)
|
49
|
+
root = data['xtab_data']['rows']
|
50
|
+
root_line(root)
|
51
|
+
end
|
52
|
+
|
53
|
+
def cols(stuff)
|
54
|
+
stuff.first.count
|
55
|
+
end
|
56
|
+
|
57
|
+
def rows(stuff)
|
58
|
+
stuff.count
|
59
|
+
end
|
60
|
+
|
61
|
+
def data(data)
|
62
|
+
data['xtab_data']['data'].map { |row| row.map { |i| i ? BigDecimal(i) : i } }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns
|
67
|
+
#
|
68
|
+
# @param [Hash] opts Data for the report
|
69
|
+
# @option opts [Array<Array>] :data The data as a matrix. First rows then cols
|
70
|
+
# @option opts [Number] :top Number of rows that are representing the top header
|
71
|
+
# @option opts [Number] :left Number of cols that are representing the left header
|
72
|
+
# @return [GoodData::ReportDataResult] Returns new report data result
|
73
|
+
def initialize(opts)
|
74
|
+
@data = opts[:data]
|
75
|
+
@top_headers_rows_nums = opts[:top]
|
76
|
+
@left_headers_cols_nums = opts[:left]
|
77
|
+
end
|
78
|
+
|
79
|
+
# Gives you new report result with top headers removed
|
80
|
+
#
|
81
|
+
# @return [GoodData::ReportDataResult] Returns new report data result
|
82
|
+
def without_top_headers
|
83
|
+
slice(@top_headers_rows_nums, 0)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Gives you new report result with left headers removed
|
87
|
+
#
|
88
|
+
# @return [GoodData::ReportDataResult] Returns new report data result
|
89
|
+
def without_left_headers
|
90
|
+
slice(0, @left_headers_cols_nums)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Gives you left headers as an Array
|
94
|
+
#
|
95
|
+
# @return [Array] Return left headers as Array of Arrays. The notation is of a matrix. First rows then cols.
|
96
|
+
def left_headers
|
97
|
+
return nil if @left_headers_cols_nums == 0
|
98
|
+
top = @left_headers_cols_nums - 1
|
99
|
+
without_top_headers.slice(0, [0, top]).to_a
|
100
|
+
end
|
101
|
+
|
102
|
+
# Gives you right headers as an Array
|
103
|
+
#
|
104
|
+
# @return [Array] Return top headers as Array of Arrays. The notation is of a matrix. First rows then cols.
|
105
|
+
def top_headers
|
106
|
+
return nil if @top_headers_rows_nums == 0
|
107
|
+
top = @top_headers_rows_nums - 1
|
108
|
+
without_left_headers.slice([0, top], 0).to_a
|
109
|
+
end
|
110
|
+
|
111
|
+
# Gives you data as a new ReportDataResult
|
112
|
+
#
|
113
|
+
# @return [Array] Return left headers as Array of Arrays. The notation is of a matrix. First rows then cols.
|
114
|
+
def data
|
115
|
+
slice(@top_headers_rows_nums, @left_headers_cols_nums)
|
116
|
+
end
|
117
|
+
|
118
|
+
def each
|
119
|
+
to_a.each
|
120
|
+
end
|
121
|
+
alias_method :each_line, :each
|
122
|
+
alias_method :each_row, :each
|
123
|
+
|
124
|
+
def each_column
|
125
|
+
size.last.times.map do |i|
|
126
|
+
col = map { |row| row[i] }
|
127
|
+
yield(col)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# Gives you data as a new ReportDataResult
|
132
|
+
#
|
133
|
+
# @return [Array] Return left headers as Array of Arrays. The notation is of a matrix. First rows then cols.
|
134
|
+
def to_a
|
135
|
+
@data
|
136
|
+
end
|
137
|
+
alias_method :to_table, :to_a
|
138
|
+
|
139
|
+
# Gives report as a table suitable for printing out
|
140
|
+
#
|
141
|
+
# @return [String]
|
142
|
+
def to_s(options = {})
|
143
|
+
with_indices = options[:index]
|
144
|
+
|
145
|
+
a = to_table.to_a
|
146
|
+
data = a.transpose
|
147
|
+
data.unshift((1..a.length).to_a) if with_indices
|
148
|
+
processed_data = data.each_with_index.map do |col, i|
|
149
|
+
col.unshift(i.zero? ? nil : i) if with_indices # inserts row labels #
|
150
|
+
w = col.map { |cell| cell.to_s.length }.max # w = "column width" #
|
151
|
+
col.each_with_index.map do |cell, j|
|
152
|
+
j.zero? ? cell.to_s.center(w) : cell.to_s.ljust(w)
|
153
|
+
end # alligns the column #
|
154
|
+
end
|
155
|
+
processed_data.transpose.map { |row| "[#{row.join(' | ')}]" }.unshift('').join("\n")
|
156
|
+
end
|
157
|
+
|
158
|
+
# Allows to pick particular row inside the report result
|
159
|
+
#
|
160
|
+
# @return [Array] Returns a row of data
|
161
|
+
def [](index)
|
162
|
+
@data[index]
|
163
|
+
end
|
164
|
+
alias_method :row, :[]
|
165
|
+
|
166
|
+
# Allows to pick particular column inside the report result
|
167
|
+
#
|
168
|
+
# @return [Array] Returns a column of data. The column is returned transposed
|
169
|
+
def column(index)
|
170
|
+
transpose[index]
|
171
|
+
end
|
172
|
+
|
173
|
+
# Is the report without any data? This can be caused by the fact that the filters are too restrictive or data are not loaded in
|
174
|
+
#
|
175
|
+
# @return [Array] Returns true if data result is empty
|
176
|
+
def empty?
|
177
|
+
row, cols = size
|
178
|
+
row == 0 && cols == 0
|
179
|
+
end
|
180
|
+
|
181
|
+
# Allows you to test if a report contains a row.
|
182
|
+
#
|
183
|
+
# @param [Array<String | Number>] row Row that you want to test. It is looking for the whole row. If the headers are getting in the way use #without_left_headers or #without_top_headers
|
184
|
+
# @return [Array] Returns true if data are inside a report
|
185
|
+
def include_row?(row)
|
186
|
+
@data.include?(row)
|
187
|
+
end
|
188
|
+
|
189
|
+
# Allows you to test if a report contains a column.
|
190
|
+
#
|
191
|
+
# @param [Array<String | Number>] row Row that you want to test. It is looking for the whole row. If the headers are getting in the way use #without_left_headers or #without_top_headers
|
192
|
+
# @return [Array] Returns true if data are inside a report
|
193
|
+
def include_column?(col)
|
194
|
+
transpose.include_row?(col)
|
195
|
+
end
|
196
|
+
|
197
|
+
# Returns the size of the report
|
198
|
+
#
|
199
|
+
# @return [Array<Number>] The size of the report result as an array. First element is rows second is columns
|
200
|
+
def size
|
201
|
+
[@data.size, @data.empty? ? 0 : @data.first.size]
|
202
|
+
end
|
203
|
+
|
204
|
+
# Transposes data and returns as new data result
|
205
|
+
#
|
206
|
+
# @return [GoodData::ReportDataResult] Returns new report data result with flipped columns and rows
|
207
|
+
def transpose
|
208
|
+
ReportDataResult.new(data: to_a.transpose, top: @left_headers_cols_nums, left: @top_headers_rows_nums)
|
209
|
+
end
|
210
|
+
|
211
|
+
# Gives you report result with a subset of data starting at position rows, cols
|
212
|
+
#
|
213
|
+
# @param [Number] rows Position where you want to slice your row. Currently accepts only number
|
214
|
+
# @param [Number] cols Position where you want to slice your row. Currently accepts only number
|
215
|
+
# @return [GoodData::ReportDataResult] Returns new report data result sliced data
|
216
|
+
def slice(rows, cols)
|
217
|
+
rows = rows.is_a?(Enumerable) ? rows : [rows, size.first]
|
218
|
+
cols = cols.is_a?(Enumerable) ? cols : [cols, size.last]
|
219
|
+
new_data = @data[rows.first..rows.last].map { |col| col[cols.first..cols.last] }
|
220
|
+
if client
|
221
|
+
client.create(ReportDataResult, data: new_data, top: @top_headers_rows_nums - rows.first, left: @left_headers_cols_nums - cols.first, project: project)
|
222
|
+
else
|
223
|
+
ReportDataResult.new(data: new_data, top: @top_headers_rows_nums - rows.first, left: @left_headers_cols_nums - cols.first, project: project)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
# Returns the size of the the data portion of report
|
228
|
+
#
|
229
|
+
# @return [Array<Number>] The size of the report result as an array. First element is rows second is columns
|
230
|
+
def data_size
|
231
|
+
data.size
|
232
|
+
end
|
233
|
+
|
234
|
+
def ==(other)
|
235
|
+
return false if size != other.size
|
236
|
+
@data == other.to_a
|
237
|
+
end
|
238
|
+
|
239
|
+
def eq?(other)
|
240
|
+
self == other
|
241
|
+
end
|
242
|
+
|
243
|
+
# Implements subtraction. Works only on reports that have same number of columns. Gives you columns that are not in other.
|
244
|
+
#
|
245
|
+
# @param [GoodData::ReportDataResult] other The other report result
|
246
|
+
# @return [Array<Array>] Returns rows that are not contained in other
|
247
|
+
def -(other)
|
248
|
+
fail 'Seems you are not using a data result as a parameter' unless other.respond_to?(:size)
|
249
|
+
message = 'Results do not have compatible sizes. Subtracting the dataresults works row wise so you have to have the same number of columns'
|
250
|
+
fail message if size.last != other.size.last
|
251
|
+
to_a - other.to_a
|
252
|
+
end
|
253
|
+
|
254
|
+
# Implements diff. Works only on reports that have same number of columns (because it uses #- behind the scene).
|
255
|
+
#
|
256
|
+
# @param [GoodData::ReportDataResult] other The other report result
|
257
|
+
# @return [Hash] Returns a hash that gives you the differences in the report results
|
258
|
+
def diff(other)
|
259
|
+
{
|
260
|
+
added: other - self,
|
261
|
+
removed: self - other,
|
262
|
+
same: @data & other.to_a
|
263
|
+
}
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|