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,61 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require_relative '../md_object'
|
|
4
|
+
require_relative '../../helpers'
|
|
5
|
+
|
|
6
|
+
module GoodData
|
|
7
|
+
module Model
|
|
8
|
+
##
|
|
9
|
+
# This is a base class for server-side LDM elements such as attributes, labels and
|
|
10
|
+
# facts
|
|
11
|
+
#
|
|
12
|
+
class Column < MdObject
|
|
13
|
+
attr_accessor :folder, :name, :title, :schema
|
|
14
|
+
|
|
15
|
+
def initialize(hash, schema)
|
|
16
|
+
super()
|
|
17
|
+
fail(ArgumentError, "Schema must be provided, got #{schema.class}") unless schema.is_a? Schema
|
|
18
|
+
fail('Data set fields must have their names defined') if hash[:name].nil?
|
|
19
|
+
|
|
20
|
+
@name = hash[:name]
|
|
21
|
+
@title = hash[:title] || hash[:name].humanize
|
|
22
|
+
@folder = hash[:folder]
|
|
23
|
+
@schema = schema
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
##
|
|
27
|
+
# Generates an identifier from the object name by transliterating
|
|
28
|
+
# non-Latin character and then dropping non-alphanumerical characters.
|
|
29
|
+
#
|
|
30
|
+
def identifier
|
|
31
|
+
@identifier ||= "#{type_prefix}.#{@schema.name}.#{name}"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def to_maql_drop
|
|
35
|
+
"DROP {#{identifier}};\n"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def visual
|
|
39
|
+
visual = super
|
|
40
|
+
visual += ", FOLDER {#{folder_prefix}.#{(folder)}}" if folder
|
|
41
|
+
visual
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def to_csv_header(row)
|
|
45
|
+
name
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def to_csv_data(headers, row)
|
|
49
|
+
row[name]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Overriden to prevent long strings caused by the @schema attribute
|
|
53
|
+
#
|
|
54
|
+
def inspect
|
|
55
|
+
to_s.sub(/>$/, " @title=#{@title.inspect}, @name=#{@name.inspect}, @folder=#{@folder.inspect}," \
|
|
56
|
+
" @schema=#{@schema.to_s.sub(/>$/, ' @title=' + @schema.name.inspect + '>')}" \
|
|
57
|
+
">")
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
# encoding: UTF-8
|
|
2
2
|
|
|
3
|
+
require_relative '../../core/core'
|
|
4
|
+
require_relative '../metadata'
|
|
3
5
|
require_relative 'metadata'
|
|
6
|
+
require_relative 'report'
|
|
7
|
+
|
|
8
|
+
require 'multi_json'
|
|
4
9
|
|
|
5
10
|
module GoodData
|
|
6
11
|
class Dashboard < GoodData::MdObject
|
|
7
12
|
root_key :projectDashboard
|
|
8
13
|
|
|
9
14
|
class << self
|
|
10
|
-
def [](id)
|
|
15
|
+
def [](id, options = {})
|
|
11
16
|
if id == :all
|
|
12
17
|
GoodData.get(GoodData.project.md['query'] + '/projectdashboards/')['query']['entries']
|
|
13
18
|
else
|
|
@@ -23,7 +28,7 @@ module GoodData
|
|
|
23
28
|
}
|
|
24
29
|
end
|
|
25
30
|
|
|
26
|
-
def create_report_tab_item(options={})
|
|
31
|
+
def create_report_tab_item(options = {})
|
|
27
32
|
title = options[:title]
|
|
28
33
|
|
|
29
34
|
report = GoodData::Report.find_first_by_title(title)
|
|
@@ -53,7 +58,7 @@ module GoodData
|
|
|
53
58
|
}
|
|
54
59
|
end
|
|
55
60
|
|
|
56
|
-
def create(options={})
|
|
61
|
+
def create(options = {})
|
|
57
62
|
stuff = {
|
|
58
63
|
'projectDashboard' => {
|
|
59
64
|
'content' => {
|
|
@@ -75,16 +80,16 @@ module GoodData
|
|
|
75
80
|
true
|
|
76
81
|
end
|
|
77
82
|
|
|
78
|
-
def export(format, options={})
|
|
83
|
+
def export(format, options = {})
|
|
79
84
|
supported_formats = [:pdf]
|
|
80
85
|
fail "Wrong format provied \"#{format}\". Only supports formats #{supported_formats.join(', ')}" unless supported_formats.include?(format)
|
|
81
86
|
tab = options[:tab] || ''
|
|
82
87
|
|
|
83
88
|
req_uri = "/gdc/projects/#{GoodData.project.uri}/clientexport"
|
|
84
|
-
x = GoodData.post(req_uri, {'clientExport' => {'url' => "https://secure.gooddata.com/dashboard.html#project=#{GoodData.project.uri}&dashboard=#{uri}&tab=#{tab}&export=1", 'name' => title}}, :process => false)
|
|
85
|
-
while
|
|
89
|
+
x = GoodData.post(req_uri, { 'clientExport' => { 'url' => "https://secure.gooddata.com/dashboard.html#project=#{GoodData.project.uri}&dashboard=#{uri}&tab=#{tab}&export=1", 'name' => title } }, :process => false)
|
|
90
|
+
while x.code == 202
|
|
86
91
|
sleep(1)
|
|
87
|
-
uri = MultiJson.load(x.body)[
|
|
92
|
+
uri = MultiJson.load(x.body)['asyncTask']['link']['poll']
|
|
88
93
|
x = GoodData.get(uri, :process => false)
|
|
89
94
|
end
|
|
90
95
|
x
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
# encoding: UTF-8
|
|
2
2
|
|
|
3
|
-
require_relative 'metadata.rb'
|
|
3
|
+
require_relative '../metadata.rb'
|
|
4
|
+
require_relative 'metadata'
|
|
4
5
|
|
|
5
6
|
module GoodData
|
|
6
|
-
class DataSet < MdObject
|
|
7
|
+
class DataSet < GoodData::MdObject
|
|
7
8
|
root_key :dataSet
|
|
8
9
|
|
|
9
10
|
SLI_CTG = 'singleloadinterface'
|
|
@@ -14,7 +15,7 @@ module GoodData
|
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
def sli
|
|
17
|
-
|
|
18
|
+
fail(NoProjectError, 'Connect to a project before searching for an object') unless GoodData.project
|
|
18
19
|
slis = GoodData.project.md.links(Model::LDM_CTG).links(SLI_CTG)[DS_SLI_CTG]
|
|
19
20
|
uri = slis[identifier]['link']
|
|
20
21
|
MdObject[uri]
|
|
@@ -28,4 +29,4 @@ module GoodData
|
|
|
28
29
|
content['facts'].map { |a| GoodData::Attribute[a] }
|
|
29
30
|
end
|
|
30
31
|
end
|
|
31
|
-
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require_relative '../md_object'
|
|
4
|
+
|
|
5
|
+
module GoodData
|
|
6
|
+
module Model
|
|
7
|
+
class DateDimension < MdObject
|
|
8
|
+
def initialize(spec = {})
|
|
9
|
+
super()
|
|
10
|
+
@name = spec[:name]
|
|
11
|
+
@title = spec[:title] || @name
|
|
12
|
+
@urn = spec[:urn] || 'URN:GOODDATA:DATE'
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_maql_create
|
|
16
|
+
# urn = "urn:chefs_warehouse_fiscal:date"
|
|
17
|
+
# title = "title"
|
|
18
|
+
# name = "name"
|
|
19
|
+
|
|
20
|
+
maql = ''
|
|
21
|
+
maql += "INCLUDE TEMPLATE \"#{@urn}\" MODIFY (IDENTIFIER \"#{@name}\", TITLE \"#{@title}\");"
|
|
22
|
+
maql
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require_relative '../metadata'
|
|
4
|
+
require_relative 'metadata'
|
|
5
|
+
|
|
6
|
+
module GoodData
|
|
7
|
+
class DisplayForm < GoodData::MdObject
|
|
8
|
+
root_key :attributeDisplayForm
|
|
9
|
+
|
|
10
|
+
# Finds an attribute element URI for given value. This URI can be used by find_element_value to find the original value again
|
|
11
|
+
# @param [String] value value of an label you are looking for
|
|
12
|
+
# @return [String]
|
|
13
|
+
def find_value_uri(value)
|
|
14
|
+
value = CGI.escapeHTML(value)
|
|
15
|
+
results = GoodData.post("#{uri}/validElements?limit=30&offset=0&order=asc&filter=#{value}", {})
|
|
16
|
+
items = results['validElements']['items']
|
|
17
|
+
if items.empty?
|
|
18
|
+
fail "#{value} not found"
|
|
19
|
+
else
|
|
20
|
+
items.first['element']['uri']
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# For an element id find values (titles) for this label. Element id can be given as both number id or URI as a string beginning with /
|
|
25
|
+
# @param [Object] element_id Element identifier either Number or a uri as a String
|
|
26
|
+
# @return [String] value of the element if found
|
|
27
|
+
def find_element_value(element_id)
|
|
28
|
+
element_id = element_id.is_a?(String) ? element_id.match(/\?id=(\d)/)[1] : element_id
|
|
29
|
+
uri = links['elements']
|
|
30
|
+
result = GoodData.get(uri + "/?id=#{element_id}")
|
|
31
|
+
items = result['attributeElements']['elements']
|
|
32
|
+
if items.empty?
|
|
33
|
+
fail "Element id #{element_id} was not found"
|
|
34
|
+
else
|
|
35
|
+
items.first['title']
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Returns all values for this label. This is for inspection purposes only since obviously there can be huge number of elements.
|
|
40
|
+
# @param [Hash] options the options to pass to the value list
|
|
41
|
+
# @option options [Number] :limit limits the number of values to certain number. Default is 100
|
|
42
|
+
# @return [Array]
|
|
43
|
+
def values(options = {})
|
|
44
|
+
limit = options[:limit] || 100
|
|
45
|
+
results = GoodData.post("#{uri}/validElements?limit=#{limit}&offset=0&order=asc", {})
|
|
46
|
+
results['validElements']['items'].map do |el|
|
|
47
|
+
v = el['element']
|
|
48
|
+
{
|
|
49
|
+
:value => v['title'],
|
|
50
|
+
:uri => v['uri']
|
|
51
|
+
}
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Gives an attribute of current label
|
|
56
|
+
# @return [GoodData::Attibute]
|
|
57
|
+
def attribute
|
|
58
|
+
GoodData::Attribute[content['formOf']]
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require_relative '../metadata'
|
|
4
|
+
require_relative '../../core/rest'
|
|
5
|
+
require_relative 'metadata'
|
|
6
|
+
|
|
7
|
+
module GoodData
|
|
8
|
+
class Fact < GoodData::MdObject
|
|
9
|
+
root_key :fact
|
|
10
|
+
|
|
11
|
+
# TODO: verify that we have all (which we do not right now)
|
|
12
|
+
FACT_BASE_AGGREGATIONS = [:sum, :min, :max, :avg, :median]
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
def [](id, options = {})
|
|
16
|
+
if id == :all
|
|
17
|
+
facts = GoodData.get(GoodData.project.md['query'] + '/facts/')['query']['entries']
|
|
18
|
+
options[:full] ? facts.map { |f| Fact[f['link']] } : facts
|
|
19
|
+
else
|
|
20
|
+
super
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def fact?
|
|
26
|
+
true
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def create_metric(options = {})
|
|
30
|
+
a_type = options[:type] || :sum
|
|
31
|
+
fail "Suggested aggreagtion function (#{a_type}) does not exist for base metric created out of fact. You can use only one of #{FACT_BASE_AGGREGATIONS.map { |x| ":" + x.to_s }.join(',')}" unless FACT_BASE_AGGREGATIONS.include?(a_type)
|
|
32
|
+
a_title = options[:title] || "#{a_type} of #{title}"
|
|
33
|
+
Metric.xcreate(:expression => "SELECT #{a_type.to_s.upcase}(![#{identifier}])", :title => a_title)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require_relative '../md_object'
|
|
4
|
+
|
|
5
|
+
module GoodData
|
|
6
|
+
module Model
|
|
7
|
+
##
|
|
8
|
+
# Base class for GoodData attribute and fact folder abstractions
|
|
9
|
+
#
|
|
10
|
+
class Folder < MdObject
|
|
11
|
+
def initialize(title)
|
|
12
|
+
# TODO: should a super be here?
|
|
13
|
+
# how to deal with name vs title?
|
|
14
|
+
@title = title
|
|
15
|
+
@name = GoodData::Helpers.sanitize_string(title)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def to_maql_create
|
|
19
|
+
"CREATE FOLDER {#{type_prefix}.#{name}}" \
|
|
20
|
+
+ " VISUAL (#{visual}) TYPE #{type};\n"
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# encoding: UTF-8
|
|
2
|
+
|
|
3
|
+
require_relative '../../goodzilla/goodzilla'
|
|
4
|
+
require_relative '../metadata'
|
|
5
|
+
require_relative 'metadata'
|
|
6
|
+
|
|
7
|
+
module GoodData
|
|
8
|
+
# Metric representation
|
|
9
|
+
class Metric < MdObject
|
|
10
|
+
root_key :metric
|
|
11
|
+
|
|
12
|
+
PARSE_MAQL_OBJECT_REGEXP = /\[([^\]]+)\]/
|
|
13
|
+
|
|
14
|
+
class << self
|
|
15
|
+
def [](id, options = {})
|
|
16
|
+
if id == :all
|
|
17
|
+
metrics = GoodData.get(GoodData.project.md['query'] + '/metrics/')['query']['entries']
|
|
18
|
+
options[:full] ? metrics.map { |m| Metric[m['link']] } : metrics
|
|
19
|
+
else
|
|
20
|
+
super
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def xcreate(options)
|
|
25
|
+
if options.is_a?(String)
|
|
26
|
+
create(:expression => options, :extended_notation => true)
|
|
27
|
+
else
|
|
28
|
+
create(options.merge(:extended_notation => true))
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def create(options = {})
|
|
33
|
+
if options.is_a?(String)
|
|
34
|
+
expression = options
|
|
35
|
+
extended_notation = false
|
|
36
|
+
title = nil
|
|
37
|
+
else
|
|
38
|
+
title = options[:title]
|
|
39
|
+
summary = options[:summary]
|
|
40
|
+
expression = options[:expression] || fail('Metric has to have its expression defined')
|
|
41
|
+
extended_notation = options[:extended_notation] || false
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
expression = if extended_notation
|
|
45
|
+
dict = {
|
|
46
|
+
:facts => GoodData::Fact[:all].reduce({}) do |memo, item|
|
|
47
|
+
memo[item['title']] = item['link']
|
|
48
|
+
memo
|
|
49
|
+
end,
|
|
50
|
+
:attributes => GoodData::Attribute[:all].reduce({}) do |memo, item|
|
|
51
|
+
memo[item['title']] = item['link']
|
|
52
|
+
memo
|
|
53
|
+
end,
|
|
54
|
+
:metrics => GoodData::Metric[:all].reduce({}) do |memo, item|
|
|
55
|
+
memo[item['title']] = item['link']
|
|
56
|
+
memo
|
|
57
|
+
end
|
|
58
|
+
}
|
|
59
|
+
interpolated_metric = GoodData::SmallGoodZilla.interpolate_metric(expression, dict)
|
|
60
|
+
interpolated_metric
|
|
61
|
+
else
|
|
62
|
+
expression
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
metric = {
|
|
66
|
+
'metric' => {
|
|
67
|
+
'content' => {
|
|
68
|
+
'format' => '#,##0',
|
|
69
|
+
'expression' => expression
|
|
70
|
+
},
|
|
71
|
+
'meta' => {
|
|
72
|
+
'tags' => '',
|
|
73
|
+
'summary' => summary,
|
|
74
|
+
'title' => title
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
# TODO: add test for explicitly provided identifier
|
|
79
|
+
metric['metric']['meta']['identifier'] = options[:identifier] if options[:identifier]
|
|
80
|
+
Metric.new(metric)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def execute(expression, options = {})
|
|
84
|
+
m = if expression.is_a?(String)
|
|
85
|
+
tmp = {
|
|
86
|
+
:title => 'Temporary metric to be deleted',
|
|
87
|
+
:expression => expression
|
|
88
|
+
}.merge(options)
|
|
89
|
+
|
|
90
|
+
GoodData::Metric.create(tmp)
|
|
91
|
+
else
|
|
92
|
+
tmp = {
|
|
93
|
+
:title => 'Temporary metric to be deleted'
|
|
94
|
+
}.merge(expression)
|
|
95
|
+
GoodData::Metric.create(tmp)
|
|
96
|
+
end
|
|
97
|
+
m.execute
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def xexecute(expression)
|
|
101
|
+
if expression.is_a?(String)
|
|
102
|
+
execute(:expression => expression, :extended_notation => true)
|
|
103
|
+
else
|
|
104
|
+
execute(expression.merge(:extended_notation => true))
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def execute
|
|
110
|
+
res = GoodData::ReportDefinition.execute(:left => self)
|
|
111
|
+
res[0][0]
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def expression
|
|
115
|
+
content['expression']
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def expression=(value)
|
|
119
|
+
content['expression'] = value
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def validate
|
|
123
|
+
fail 'Meric needs to have title' if title.nil?
|
|
124
|
+
true
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def metric?
|
|
128
|
+
true
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
# Checks that the expression contains certain metadata object. The difference between this and used_by using is in the fact that this is not a transitive closure. it searches only inside the expression
|
|
132
|
+
# @param [GoodData::MdObject] item Object that is going to be looked up
|
|
133
|
+
# @return [Boolean]
|
|
134
|
+
def contain?(item)
|
|
135
|
+
uri = item.respond_to?(:uri) ? item.uri : item
|
|
136
|
+
expression[uri] != nil
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
# Checks that the expression contains certain element of an attribute. The value is looked up through given label.
|
|
140
|
+
# @param [GoodData::DisplayForm] label Label though which the value is looked up
|
|
141
|
+
# @param [String] value Value that will be looked up through the label.
|
|
142
|
+
# @return [Boolean]
|
|
143
|
+
def contain_value?(label, value)
|
|
144
|
+
uri = label.find_value_uri(value)
|
|
145
|
+
contain?(uri)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
# Method used for replacing objects like Attribute, Fact or Metric.
|
|
149
|
+
# @param [GoodData::MdObject] what Object that should be replaced
|
|
150
|
+
# @param [GoodData::MdObject] for_what Object it is replaced with
|
|
151
|
+
# @return [GoodData::Metric]
|
|
152
|
+
def replace(what, for_what)
|
|
153
|
+
uri_what = what.respond_to?(:uri) ? what.uri : what
|
|
154
|
+
uri_for_what = for_what.respond_to?(:uri) ? for_what.uri : for_what
|
|
155
|
+
self.expression = expression.gsub(uri_what, uri_for_what)
|
|
156
|
+
self
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Method used for replacing attribute element values. Looks up certain value of a label in the MAQL expression and exchanges it for a different value of the same label.
|
|
160
|
+
# @param [GoodData::DisplayForm] label Label through which the value and for_value are resolved
|
|
161
|
+
# @param [String] value value that is going to be replaced
|
|
162
|
+
# @param [String] for_value value that is going to be the new one
|
|
163
|
+
# @return [GoodData::Metric]
|
|
164
|
+
def replace_value(label, value, for_label, for_value = nil)
|
|
165
|
+
label = label.respond_to?(:primary_label) ? label.primary_label : label
|
|
166
|
+
if for_value
|
|
167
|
+
for_label = for_label.respond_to?(:primary_label) ? for_label.primary_label : for_label
|
|
168
|
+
value_uri = label.find_value_uri(value)
|
|
169
|
+
for_value_uri = for_label.find_value_uri(for_value)
|
|
170
|
+
self.expression = expression.gsub(value_uri, for_value_uri)
|
|
171
|
+
self.expression = expression.gsub(label.attribute.uri, for_label.attribute.uri)
|
|
172
|
+
else
|
|
173
|
+
for_value = for_label
|
|
174
|
+
value_uri = label.find_value_uri(value)
|
|
175
|
+
for_value_uri = label.find_value_uri(for_value)
|
|
176
|
+
self.expression = expression.gsub(value_uri, for_value_uri)
|
|
177
|
+
end
|
|
178
|
+
self
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Looks up the readable values of the objects used inside of MAQL epxpressions. Labels and elements titles are based on the primary label.
|
|
182
|
+
# @return [String] Ther resulting MAQL like expression
|
|
183
|
+
def pretty_expression
|
|
184
|
+
temp = expression.dup
|
|
185
|
+
expression.scan(PARSE_MAQL_OBJECT_REGEXP).each do |uri|
|
|
186
|
+
uri = uri.first
|
|
187
|
+
if uri =~ /elements/
|
|
188
|
+
temp.sub!(uri, Attribute.find_element_value(uri))
|
|
189
|
+
else
|
|
190
|
+
obj = GoodData::MdObject[uri]
|
|
191
|
+
temp.sub!(uri, obj.title)
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
temp
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|