gooddata 0.6.0 → 0.6.2
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 +13 -5
- data/.rubocop.yml +23 -0
- data/.travis.yml +9 -4
- data/CLI.md +439 -0
- data/Gemfile +0 -1
- data/README.md +2 -2
- data/Rakefile +60 -8
- data/doc/templates/default/module/setup.rb +1 -1
- data/examples.rb +2 -0
- data/gooddata +2 -0
- data/gooddata.gemspec +12 -8
- data/lib/gooddata.rb +0 -2
- data/lib/gooddata/bricks/base_downloader.rb +52 -47
- data/lib/gooddata/bricks/brick.rb +20 -31
- data/lib/gooddata/bricks/bricks.rb +1 -1
- data/lib/gooddata/bricks/middleware/base_middleware.rb +9 -7
- data/lib/gooddata/bricks/middleware/bench_middleware.rb +12 -10
- data/lib/gooddata/bricks/middleware/bulk_salesforce_middleware.rb +28 -28
- data/lib/gooddata/bricks/middleware/fs_upload_middleware.rb +20 -16
- data/lib/gooddata/bricks/middleware/gooddata_middleware.rb +21 -19
- data/lib/gooddata/bricks/middleware/logger_middleware.rb +10 -8
- data/lib/gooddata/bricks/middleware/restforce_middleware.rb +36 -34
- data/lib/gooddata/bricks/middleware/stdout_middleware.rb +11 -9
- data/lib/gooddata/bricks/middleware/twitter_middleware.rb +14 -12
- data/lib/gooddata/bricks/pipeline.rb +28 -0
- data/lib/gooddata/bricks/utils.rb +10 -8
- data/lib/gooddata/cli/cli.rb +1 -6
- data/lib/gooddata/cli/commands/auth_cmd.rb +1 -1
- data/lib/gooddata/cli/commands/console_cmd.rb +7 -5
- data/lib/gooddata/cli/commands/domain_cmd.rb +45 -0
- data/lib/gooddata/cli/commands/process_cmd.rb +42 -5
- data/lib/gooddata/cli/commands/project_cmd.rb +96 -36
- data/lib/gooddata/cli/commands/projects_cmd.rb +21 -0
- data/lib/gooddata/cli/commands/role_cmd.rb +28 -0
- data/lib/gooddata/cli/commands/run_ruby_cmd.rb +5 -5
- data/lib/gooddata/cli/commands/scaffold_cmd.rb +1 -1
- data/lib/gooddata/cli/commands/{profile_cmd.rb → user_cmd.rb} +7 -9
- data/lib/gooddata/cli/shared.rb +3 -2
- data/lib/gooddata/client.rb +16 -304
- data/lib/gooddata/commands/api.rb +13 -5
- data/lib/gooddata/commands/auth.rb +47 -40
- data/lib/gooddata/commands/base.rb +4 -2
- data/lib/gooddata/commands/commands.rb +1 -1
- data/lib/gooddata/commands/datasets.rb +20 -7
- data/lib/gooddata/commands/domain.rb +23 -0
- data/lib/gooddata/commands/process.rb +23 -117
- data/lib/gooddata/commands/project.rb +147 -0
- data/lib/gooddata/commands/projects.rb +8 -102
- data/lib/gooddata/commands/role.rb +26 -0
- data/lib/gooddata/commands/runners.rb +41 -38
- data/lib/gooddata/commands/scaffold.rb +46 -43
- data/lib/gooddata/commands/user.rb +33 -0
- data/lib/gooddata/connection.rb +43 -353
- data/lib/gooddata/core/connection.rb +389 -0
- data/lib/gooddata/core/core.rb +5 -4
- data/lib/gooddata/core/logging.rb +48 -0
- data/lib/gooddata/core/nil_logger.rb +13 -0
- data/lib/gooddata/core/project.rb +70 -0
- data/lib/gooddata/core/rest.rb +120 -0
- data/lib/gooddata/core/threaded.rb +14 -0
- data/lib/gooddata/core/user.rb +19 -0
- data/lib/gooddata/data/data.rb +2 -1
- data/lib/gooddata/data/guesser.rb +16 -12
- data/lib/gooddata/exceptions/command_failed.rb +1 -1
- data/lib/gooddata/exceptions/exceptions.rb +2 -1
- data/lib/gooddata/exceptions/no_project_error.rb +11 -0
- data/lib/gooddata/exceptions/project_not_found.rb +1 -1
- data/lib/gooddata/extensions/big_decimal.rb +6 -2
- data/lib/gooddata/extract.rb +10 -8
- data/lib/gooddata/goodzilla/goodzilla.rb +61 -59
- data/lib/gooddata/helpers.rb +15 -9
- data/lib/gooddata/models/account_settings.rb +124 -0
- data/lib/gooddata/models/attributes/anchor.rb +37 -0
- data/lib/gooddata/models/attributes/attributes.rb +8 -0
- data/lib/gooddata/models/attributes/date_attribute.rb +25 -0
- data/lib/gooddata/models/attributes/time_attribute.rb +24 -0
- data/lib/gooddata/models/columns/attribute.rb +71 -0
- data/lib/gooddata/models/columns/columns.rb +8 -0
- data/lib/gooddata/models/columns/date_column.rb +63 -0
- data/lib/gooddata/models/columns/fact_model.rb +54 -0
- data/lib/gooddata/models/columns/label.rb +55 -0
- data/lib/gooddata/models/columns/reference.rb +57 -0
- data/lib/gooddata/models/dashboard_builder.rb +26 -0
- data/lib/gooddata/models/data_result.rb +10 -9
- data/lib/gooddata/models/domain.rb +131 -0
- data/lib/gooddata/models/empty_result.rb +5 -8
- data/lib/gooddata/models/facts/facts.rb +8 -0
- data/lib/gooddata/models/facts/time_fact.rb +20 -0
- data/lib/gooddata/models/folders/attribute_folder.rb +20 -0
- data/lib/gooddata/models/folders/fact_folder.rb +20 -0
- data/lib/gooddata/models/folders/folders.rb +8 -0
- data/lib/gooddata/models/invitation.rb +78 -0
- data/lib/gooddata/models/links.rb +6 -6
- data/lib/gooddata/models/md_object.rb +25 -0
- data/lib/gooddata/models/metadata.rb +160 -62
- data/lib/gooddata/models/metadata/attribute.rb +81 -0
- data/lib/gooddata/models/metadata/column.rb +61 -0
- data/lib/gooddata/models/{dashboard.rb → metadata/dashboard.rb} +12 -7
- data/lib/gooddata/models/{data_set.rb → metadata/data_set.rb} +5 -4
- data/lib/gooddata/models/metadata/date_dimension.rb +26 -0
- data/lib/gooddata/models/metadata/display_form.rb +61 -0
- data/lib/gooddata/models/metadata/fact.rb +36 -0
- data/lib/gooddata/models/metadata/folder.rb +24 -0
- data/lib/gooddata/models/metadata/metadata.rb +8 -0
- data/lib/gooddata/models/metadata/metric.rb +197 -0
- data/lib/gooddata/models/metadata/report.rb +115 -0
- data/lib/gooddata/models/{report_definition.rb → metadata/report_definition.rb} +16 -10
- data/lib/gooddata/models/metadata/schema.rb +227 -0
- data/lib/gooddata/models/model.rb +38 -1339
- data/lib/gooddata/models/models.rb +5 -2
- data/lib/gooddata/models/module_constants.rb +29 -0
- data/lib/gooddata/models/process.rb +142 -13
- data/lib/gooddata/models/profile.rb +4 -6
- data/lib/gooddata/models/project.rb +406 -136
- data/lib/gooddata/models/project_blueprint.rb +221 -0
- data/lib/gooddata/models/project_builder.rb +136 -0
- data/lib/gooddata/models/project_creator.rb +138 -0
- data/lib/gooddata/models/project_metadata.rb +11 -10
- data/lib/gooddata/models/project_role.rb +92 -0
- data/lib/gooddata/models/references/date_reference.rb +44 -0
- data/lib/gooddata/models/references/references.rb +8 -0
- data/lib/gooddata/models/references/time_reference.rb +13 -0
- data/lib/gooddata/models/report_data_result.rb +11 -11
- data/lib/gooddata/models/schedule.rb +284 -0
- data/lib/gooddata/models/schema_blueprint.rb +158 -0
- data/lib/gooddata/models/schema_builder.rb +81 -0
- data/lib/gooddata/models/tab_builder.rb +23 -0
- data/lib/gooddata/models/user.rb +165 -0
- data/lib/gooddata/version.rb +1 -1
- data/lib/templates/project/data/devs.csv +1 -1
- data/lib/templates/project/data/repos.csv +1 -1
- data/lib/templates/project/model/model.rb.erb +7 -11
- data/spec/bricks/bricks_spec.rb +2 -0
- data/spec/data/test-ci-data.csv +2 -0
- data/spec/data/test_project_model_spec.json +7 -27
- data/spec/helpers/blueprint_helper.rb +2 -0
- data/spec/helpers/cli_helper.rb +2 -0
- data/spec/helpers/connection_helper.rb +14 -1
- data/spec/helpers/project_helper.rb +16 -0
- data/spec/helpers/schema_helper.rb +16 -0
- data/spec/integration/command_projects_spec.rb +7 -7
- data/spec/integration/create_from_template_spec.rb +2 -2
- data/spec/integration/full_project_spec.rb +160 -7
- data/spec/integration/partial_md_export_import_spec.rb +3 -3
- data/spec/logging_in_logging_out_spec.rb +2 -1
- data/spec/spec_helper.rb +26 -4
- data/spec/unit/bricks/bricks_spec.rb +15 -7
- data/spec/unit/bricks/middleware/bench_middleware_spec.rb +2 -0
- data/spec/unit/bricks/middleware/bulk_salesforce_middleware_spec.rb +2 -0
- data/spec/unit/bricks/middleware/gooddata_middleware_spec.rb +2 -0
- data/spec/unit/bricks/middleware/logger_middleware_spec.rb +2 -0
- data/spec/unit/bricks/middleware/restforce_middleware_spec.rb +2 -0
- data/spec/unit/bricks/middleware/stdout_middleware_spec.rb +2 -0
- data/spec/unit/bricks/middleware/twitter_middleware_spec.rb +2 -0
- data/spec/unit/cli/cli_spec.rb +2 -0
- data/spec/unit/cli/commands/cmd_api_spec.rb +23 -15
- data/spec/unit/cli/commands/cmd_auth_spec.rb +8 -4
- data/spec/unit/cli/commands/cmd_domain_spec.rb +82 -0
- data/spec/unit/cli/commands/cmd_process_spec.rb +29 -13
- data/spec/unit/cli/commands/cmd_project_spec.rb +51 -30
- data/spec/unit/cli/commands/cmd_role_spec.rb +44 -0
- data/spec/unit/cli/commands/cmd_run_ruby_spec.rb +8 -4
- data/spec/unit/cli/commands/cmd_scaffold_spec.rb +48 -11
- data/spec/unit/cli/commands/cmd_user_spec.rb +29 -0
- data/spec/unit/commands/command_api_spec.rb +1 -1
- data/spec/unit/commands/command_auth_spec.rb +100 -18
- data/spec/unit/commands/command_dataset_spec.rb +4 -0
- data/spec/unit/commands/command_process_spec.rb +9 -4
- data/spec/unit/commands/command_projects_spec.rb +10 -6
- data/spec/unit/commands/command_scaffold_spec.rb +5 -1
- data/spec/unit/commands/command_user_spec.rb +22 -0
- data/spec/unit/core/connection_spec.rb +35 -6
- data/spec/unit/core/logging_spec.rb +65 -0
- data/spec/unit/core/nil_logger_spec.rb +9 -0
- data/spec/unit/core/project_spec.rb +51 -0
- data/spec/unit/core/rest_spec.rb +33 -0
- data/spec/unit/data/guesser_spec.rb +5 -0
- data/spec/unit/godzilla/goodzilla_spec.rb +2 -0
- data/spec/unit/models/account_settings_spec.rb +28 -0
- data/spec/unit/models/anchor_spec.rb +32 -0
- data/spec/unit/models/attribute_column_spec.rb +7 -0
- data/spec/unit/models/domain_spec.rb +45 -0
- data/spec/unit/models/invitation_spec.rb +13 -0
- data/spec/unit/models/md_object_spec.rb +47 -0
- data/spec/unit/models/metric.rb +92 -0
- data/spec/unit/{model → models}/model_spec.rb +9 -7
- data/spec/unit/models/project_blueprint_spec.rb +202 -0
- data/spec/unit/models/project_creator.rb +73 -0
- data/spec/unit/models/project_role_spec.rb +90 -0
- data/spec/unit/models/project_spec.rb +143 -0
- data/spec/unit/models/schedule_spec.rb +491 -0
- data/spec/unit/{model → models}/schema_builder_spec.rb +2 -0
- data/spec/unit/{model → models}/tools_spec.rb +13 -7
- data/spec/unit/models/user_spec.rb +16 -0
- data/test/test_upload.rb +2 -0
- metadata +189 -86
- data/lib/gooddata/commands/profile.rb +0 -11
- data/lib/gooddata/models/attribute.rb +0 -29
- data/lib/gooddata/models/display_form.rb +0 -9
- data/lib/gooddata/models/fact.rb +0 -19
- data/lib/gooddata/models/metric.rb +0 -99
- data/lib/gooddata/models/report.rb +0 -89
- data/spec/data/blueprint_valid.json +0 -37
- data/spec/unit/cli/commands/cmd_profile_spec.rb +0 -16
- data/spec/unit/commands/command_profile_spec.rb +0 -18
- data/spec/unit/core/core_spec.rb +0 -7
- data/spec/unit/model/blueprint_spec.rb +0 -132
- data/spec/unit/model/project_blueprint_spec.rb +0 -44
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require_relative 'threaded'
|
|
4
|
+
|
|
5
|
+
module GoodData
|
|
6
|
+
# Assigns global/default GoodData project
|
|
7
|
+
def project=(project)
|
|
8
|
+
GoodData.project = project
|
|
9
|
+
GoodData.project
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
alias_method :use, :project=
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
# Sets the active project
|
|
16
|
+
#
|
|
17
|
+
# @param project A project identifier
|
|
18
|
+
#
|
|
19
|
+
# ### Examples
|
|
20
|
+
#
|
|
21
|
+
# The following calls are equivalent
|
|
22
|
+
#
|
|
23
|
+
# # Assign project ID
|
|
24
|
+
# GoodData.project = 'afawtv356b6usdfsdf34vt'
|
|
25
|
+
#
|
|
26
|
+
# # Use project ID
|
|
27
|
+
# GoodData.use 'afawtv356b6usdfsdf34vt'
|
|
28
|
+
#
|
|
29
|
+
# # Use project URL
|
|
30
|
+
# GoodData.use '/gdc/projects/afawtv356b6usdfsdf34vt'
|
|
31
|
+
#
|
|
32
|
+
# # Select project using indexer on GoodData::Project class
|
|
33
|
+
# GoodData.project = Project['afawtv356b6usdfsdf34vt']
|
|
34
|
+
#
|
|
35
|
+
def project=(project)
|
|
36
|
+
if project.is_a? Project
|
|
37
|
+
threaded[:project] = project
|
|
38
|
+
elsif project.nil?
|
|
39
|
+
threaded[:project] = nil
|
|
40
|
+
else
|
|
41
|
+
threaded[:project] = Project[project]
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
alias_method :use, :project=
|
|
46
|
+
|
|
47
|
+
# Returns the active project
|
|
48
|
+
#
|
|
49
|
+
def project
|
|
50
|
+
threaded[:project]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Perform block in context of another project than currently set
|
|
54
|
+
#
|
|
55
|
+
# @param project Project to use
|
|
56
|
+
# @param bl Block to be performed
|
|
57
|
+
def with_project(project, &bl)
|
|
58
|
+
fail 'You have to specify a project when using with_project' if project.nil? || (project.is_a?(String) && project.empty?)
|
|
59
|
+
old_project = GoodData.project
|
|
60
|
+
begin
|
|
61
|
+
GoodData.use(project)
|
|
62
|
+
bl.call(GoodData.project)
|
|
63
|
+
rescue RestClient::ResourceNotFound
|
|
64
|
+
raise(GoodData::ProjectNotFound, 'Project was not found')
|
|
65
|
+
ensure
|
|
66
|
+
GoodData.project = old_project
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require_relative 'connection'
|
|
4
|
+
|
|
5
|
+
module GoodData
|
|
6
|
+
class << self
|
|
7
|
+
# Performs a HTTP GET request.
|
|
8
|
+
#
|
|
9
|
+
# Retuns the JSON response formatted as a Hash object.
|
|
10
|
+
#
|
|
11
|
+
# @param path The HTTP path on the GoodData server (must be prefixed with a forward slash)
|
|
12
|
+
#
|
|
13
|
+
# ### Examples
|
|
14
|
+
#
|
|
15
|
+
# GoodData.get '/gdc/projects'
|
|
16
|
+
#
|
|
17
|
+
def get(path, options = {})
|
|
18
|
+
connection.get(path, options)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Performs a HTTP POST request.
|
|
22
|
+
#
|
|
23
|
+
# Retuns the JSON response formatted as a Hash object.
|
|
24
|
+
#
|
|
25
|
+
# @param path The HTTP path on the GoodData server (must be prefixed with a forward slash)
|
|
26
|
+
# @param data The payload data in the format of a Hash object
|
|
27
|
+
#
|
|
28
|
+
# ### Examples
|
|
29
|
+
#
|
|
30
|
+
# GoodData.post '/gdc/projects', { ... }
|
|
31
|
+
#
|
|
32
|
+
def post(path, data = {}, options = {})
|
|
33
|
+
connection.post path, data, options
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Performs a HTTP PUT request.
|
|
37
|
+
#
|
|
38
|
+
# Retuns the JSON response formatted as a Hash object.
|
|
39
|
+
#
|
|
40
|
+
# ### Parameters
|
|
41
|
+
#
|
|
42
|
+
# @param path The HTTP path on the GoodData server (must be prefixed with a forward slash)
|
|
43
|
+
# @param data The payload data in the format of a Hash object
|
|
44
|
+
#
|
|
45
|
+
# ### Examples
|
|
46
|
+
#
|
|
47
|
+
# GoodData.put '/gdc/projects', { ... }
|
|
48
|
+
#
|
|
49
|
+
def put(path, data, options = {})
|
|
50
|
+
connection.put path, data, options
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Performs a HTTP DELETE request.
|
|
54
|
+
#
|
|
55
|
+
# Retuns the JSON response formatted as a Hash object.
|
|
56
|
+
#
|
|
57
|
+
# @param path The HTTP path on the GoodData server (must be prefixed with a forward slash)
|
|
58
|
+
#
|
|
59
|
+
# ### Examples
|
|
60
|
+
#
|
|
61
|
+
# GoodData.delete '/gdc/project/1'
|
|
62
|
+
#
|
|
63
|
+
def delete(path, options = {})
|
|
64
|
+
connection.delete path, options
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def upload_to_user_webdav(file, options = {})
|
|
68
|
+
u = URI(connection.options[:webdav_server] || GoodData.project.links['uploads'])
|
|
69
|
+
url = URI.join(u.to_s.chomp(u.path.to_s), '/uploads/')
|
|
70
|
+
connection.upload(file, options.merge(
|
|
71
|
+
:directory => options[:directory],
|
|
72
|
+
:staging_url => url
|
|
73
|
+
))
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def get_project_webdav_path(file, options = {})
|
|
77
|
+
u = URI(connection.options[:webdav_server] || GoodData.project.links['uploads'])
|
|
78
|
+
URI.join(u.to_s.chomp(u.path.to_s), '/project-uploads/', "#{GoodData.project.pid}/")
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def upload_to_project_webdav(file, options = {})
|
|
82
|
+
url = get_project_webdav_path(file, options)
|
|
83
|
+
connection.upload(file, options.merge(
|
|
84
|
+
:directory => options[:directory],
|
|
85
|
+
:staging_url => url))
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def get_user_webdav_path(file, options = {})
|
|
89
|
+
u = URI(connection.options[:webdav_server] || GoodData.project.links['uploads'])
|
|
90
|
+
URI.join(u.to_s.chomp(u.path.to_s), '/uploads/')
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def download_from_user_webdav(file, where, options = {})
|
|
94
|
+
url = get_user_webdav_path(file, options)
|
|
95
|
+
connection.download(file, where, options.merge(:staging_url => url))
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def poll(result, key, options = {})
|
|
99
|
+
sleep_interval = options[:sleep_interval] || 10
|
|
100
|
+
link = result[key]['links']['poll']
|
|
101
|
+
response = GoodData.get(link, :process => false)
|
|
102
|
+
while response.code != 204
|
|
103
|
+
sleep sleep_interval
|
|
104
|
+
GoodData.connection.retryable(:tries => 3, :on => RestClient::InternalServerError) do
|
|
105
|
+
sleep sleep_interval
|
|
106
|
+
response = GoodData.get(link, :process => false)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def wait_for_polling_result(polling_url)
|
|
112
|
+
polling_result = GoodData.get(polling_url)
|
|
113
|
+
while polling_result['wTaskStatus'] && polling_result['wTaskStatus']['status'] == 'RUNNING'
|
|
114
|
+
sleep(3)
|
|
115
|
+
polling_result = GoodData.get(polling_url)
|
|
116
|
+
end
|
|
117
|
+
polling_result
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require_relative 'connection'
|
|
4
|
+
require_relative 'threaded'
|
|
5
|
+
|
|
6
|
+
module GoodData
|
|
7
|
+
class << self
|
|
8
|
+
# Attempts to log in
|
|
9
|
+
def test_login
|
|
10
|
+
connection.connect!
|
|
11
|
+
connection.logged_in?
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
# Returns the currently logged in user Profile.
|
|
15
|
+
def profile
|
|
16
|
+
threaded[:profile] ||= Profile.load
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
data/lib/gooddata/data/data.rb
CHANGED
|
@@ -24,8 +24,11 @@ module GoodData
|
|
|
24
24
|
|
|
25
25
|
def initialize(reader)
|
|
26
26
|
@reader = reader
|
|
27
|
-
@headers = reader.shift.map! { |h| h.to_s }
|
|
28
|
-
@pros = {}
|
|
27
|
+
@headers = reader.shift.map! { |h| h.to_s } || fail('Empty data set')
|
|
28
|
+
@pros = {}
|
|
29
|
+
@cons = {}
|
|
30
|
+
@seen = {}
|
|
31
|
+
|
|
29
32
|
@headers.map do |h|
|
|
30
33
|
@cons[h.to_s] = {}
|
|
31
34
|
@pros[h.to_s] = {}
|
|
@@ -35,21 +38,21 @@ module GoodData
|
|
|
35
38
|
|
|
36
39
|
def guess(limit)
|
|
37
40
|
count = 0
|
|
38
|
-
while row = @reader.shift
|
|
41
|
+
while (row = @reader.shift)
|
|
39
42
|
break unless row && !row.empty? && count < limit
|
|
40
|
-
|
|
43
|
+
fail '%i fields in row %i, %i expected' % [row.size, count + 1, @headers.size] if row.size != @headers.size
|
|
41
44
|
row.each_with_index do |value, j|
|
|
42
45
|
header = @headers[j]
|
|
43
46
|
number = check_number(header, value)
|
|
44
47
|
date = check_date(header, value)
|
|
45
|
-
store_guess header,
|
|
48
|
+
store_guess header, @pros => :attribute unless number || date
|
|
46
49
|
hash_increment @seen[header], value
|
|
47
50
|
end
|
|
48
51
|
count += 1
|
|
49
52
|
end
|
|
50
53
|
# fields with unique values are connection point candidates
|
|
51
54
|
@seen.each do |header, values|
|
|
52
|
-
store_guess header,
|
|
55
|
+
store_guess header, @pros => :connection_point if values.size == count
|
|
53
56
|
end
|
|
54
57
|
guess_result
|
|
55
58
|
end
|
|
@@ -59,7 +62,7 @@ module GoodData
|
|
|
59
62
|
def guess_result
|
|
60
63
|
result = {}
|
|
61
64
|
@headers.each do |header|
|
|
62
|
-
result[header] = Guesser
|
|
65
|
+
result[header] = Guesser.sort_types @pros[header].keys.select { |type| @cons[header][type].nil? }
|
|
63
66
|
end
|
|
64
67
|
result
|
|
65
68
|
end
|
|
@@ -76,7 +79,7 @@ module GoodData
|
|
|
76
79
|
if value.nil? || value =~ /^[\+-]?\d*(\.\d*)?$/
|
|
77
80
|
return store_guess(header, @pros => [:fact, :attribute])
|
|
78
81
|
end
|
|
79
|
-
store_guess header,
|
|
82
|
+
store_guess header, @cons => :fact
|
|
80
83
|
end
|
|
81
84
|
|
|
82
85
|
def check_date(header, value)
|
|
@@ -84,9 +87,10 @@ module GoodData
|
|
|
84
87
|
begin
|
|
85
88
|
DateTime.parse value
|
|
86
89
|
return store_guess(header, @pros => [:date, :attribute])
|
|
87
|
-
rescue ArgumentError
|
|
90
|
+
rescue ArgumentError => e
|
|
91
|
+
raise e
|
|
88
92
|
end
|
|
89
|
-
store_guess header,
|
|
93
|
+
store_guess header, @cons => :date
|
|
90
94
|
end
|
|
91
95
|
|
|
92
96
|
##
|
|
@@ -100,9 +104,9 @@ module GoodData
|
|
|
100
104
|
# * +guess+ - A hash with optional @pros and @cons keys
|
|
101
105
|
#
|
|
102
106
|
def store_guess(header, guess)
|
|
103
|
-
result =
|
|
107
|
+
result = guess[@pros]
|
|
104
108
|
[@pros, @cons].each do |hash|
|
|
105
|
-
if guess[hash]
|
|
109
|
+
if guess[hash]
|
|
106
110
|
guess[hash] = [guess[hash]] unless guess[hash].is_a? Array
|
|
107
111
|
guess[hash].each { |type| hash_increment hash[header], type }
|
|
108
112
|
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
module GoodData
|
|
4
|
+
class NoProjectError < RuntimeError
|
|
5
|
+
DEFAULT_MSG = 'You have to provide "project_id". You can either provide it through -p flag or even better way is to fill it in in your Goodfile under key "project_id". If you just started a project you have to create it first. One way might be through "gooddata project build"'
|
|
6
|
+
|
|
7
|
+
def initialize(msg = DEFAULT_MSG)
|
|
8
|
+
super(msg)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
data/lib/gooddata/extract.rb
CHANGED
|
@@ -2,14 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
require 'csv'
|
|
4
4
|
|
|
5
|
-
module GoodData
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
module GoodData
|
|
6
|
+
module Extract
|
|
7
|
+
class CsvFile
|
|
8
|
+
def initialize(file)
|
|
9
|
+
@file = file
|
|
10
|
+
end
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
12
|
+
def read(&block)
|
|
13
|
+
CSV.open @file, 'r', &block
|
|
14
|
+
end
|
|
13
15
|
end
|
|
14
16
|
end
|
|
15
|
-
end
|
|
17
|
+
end
|
|
@@ -1,72 +1,74 @@
|
|
|
1
1
|
# encoding: UTF-8
|
|
2
2
|
|
|
3
|
-
module GoodData
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
3
|
+
module GoodData
|
|
4
|
+
module SmallGoodZilla
|
|
5
|
+
# Get IDs from MAQL string
|
|
6
|
+
# @param a_maql_string Input MAQL string
|
|
7
|
+
# @return [Array<String>] List of IDS
|
|
8
|
+
def self.get_ids(a_maql_string)
|
|
9
|
+
a_maql_string.scan(/!\[([^\"]+)\]/).flatten
|
|
10
|
+
end
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
# Get Facts from MAQL string
|
|
13
|
+
# @param a_maql_string Input MAQL string
|
|
14
|
+
# @return [Array<String>] List of Facts
|
|
15
|
+
def self.get_facts(a_maql_string)
|
|
16
|
+
a_maql_string.scan(/#\"([^\"]+)\"/).flatten
|
|
17
|
+
end
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
19
|
+
# Get Attributes from MAQL string
|
|
20
|
+
# @param a_maql_string Input MAQL string
|
|
21
|
+
# @return [Array<String>] List of Attributes
|
|
22
|
+
def self.get_attributes(a_maql_string)
|
|
23
|
+
a_maql_string.scan(/@\"([^\"]+)\"/).flatten
|
|
24
|
+
end
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
# Get Metrics from MAQL string
|
|
27
|
+
# @param a_maql_string Input MAQL string
|
|
28
|
+
# @return [Array<String>] List of Metrics
|
|
29
|
+
def self.get_metrics(a_maql_string)
|
|
30
|
+
a_maql_string.scan(/\?"([^\"]+)\"/).flatten
|
|
31
|
+
end
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
def self.interpolate(values, dictionaries)
|
|
34
|
+
{
|
|
35
|
+
:facts => interpolate_values(values[:facts], dictionaries[:facts]),
|
|
36
|
+
:attributes => interpolate_values(values[:attributes], dictionaries[:attributes]),
|
|
37
|
+
:metrics => interpolate_values(values[:metrics], dictionaries[:metrics])
|
|
38
|
+
}
|
|
39
|
+
end
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
41
|
+
def self.interpolate_ids(*ids)
|
|
42
|
+
ids = ids.flatten
|
|
43
|
+
if ids.empty?
|
|
44
|
+
[]
|
|
45
|
+
else
|
|
46
|
+
res = GoodData::MdObject.identifier_to_uri(*ids)
|
|
47
|
+
fail 'Not all of the identifiers were resolved' if Array(res).size != ids.size
|
|
48
|
+
res
|
|
49
|
+
end
|
|
48
50
|
end
|
|
49
|
-
end
|
|
50
51
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
def self.interpolate_values(keys, values)
|
|
53
|
+
x = values.values_at(*keys)
|
|
54
|
+
keys.zip(x)
|
|
55
|
+
end
|
|
55
56
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
57
|
+
def self.interpolate_metric(metric, dictionary)
|
|
58
|
+
interpolated = interpolate({
|
|
59
|
+
:facts => GoodData::SmallGoodZilla.get_facts(metric),
|
|
60
|
+
:attributes => GoodData::SmallGoodZilla.get_attributes(metric),
|
|
61
|
+
:metrics => GoodData::SmallGoodZilla.get_metrics(metric)
|
|
62
|
+
}, dictionary)
|
|
62
63
|
|
|
63
|
-
|
|
64
|
-
|
|
64
|
+
ids = GoodData::SmallGoodZilla.get_ids(metric)
|
|
65
|
+
interpolated_ids = ids.zip(Array(interpolate_ids(ids)))
|
|
65
66
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
67
|
+
metric = interpolated[:facts].reduce(metric) { |a, e| a.sub("#\"#{e[0]}\"", "[#{e[1]}]") }
|
|
68
|
+
metric = interpolated[:attributes].reduce(metric) { |a, e| a.sub("@\"#{e[0]}\"", "[#{e[1]}]") }
|
|
69
|
+
metric = interpolated[:metrics].reduce(metric) { |a, e| a.sub("?\"#{e[0]}\"", "[#{e[1]}]") }
|
|
70
|
+
metric = interpolated_ids.reduce(metric) { |a, e| a.sub("![#{e[0]}]", "[#{e[1]}]") }
|
|
71
|
+
metric
|
|
72
|
+
end
|
|
71
73
|
end
|
|
72
|
-
end
|
|
74
|
+
end
|