gooddata 0.6.0 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -8,9 +8,9 @@ module GoodData
|
|
8
8
|
@data = {}
|
9
9
|
items.values[0]['links'].each do |item|
|
10
10
|
category = item['category']
|
11
|
-
if @data[category]
|
12
|
-
if @data[category]['category'] == category
|
13
|
-
@data[category] = {@data[category]['identifier'] => @data[category]}
|
11
|
+
if @data[category]
|
12
|
+
if @data[category]['category'] == category
|
13
|
+
@data[category] = { @data[category]['identifier'] => @data[category] }
|
14
14
|
end
|
15
15
|
@data[category][item['identifier']] = item
|
16
16
|
else
|
@@ -29,12 +29,12 @@ module GoodData
|
|
29
29
|
@data[category]
|
30
30
|
end
|
31
31
|
|
32
|
-
def
|
32
|
+
def unique?(category)
|
33
33
|
@data[category]['link'].is_a? String
|
34
34
|
end
|
35
35
|
|
36
|
-
def
|
37
|
-
!
|
36
|
+
def ambiguous?(category)
|
37
|
+
!unique?(category)
|
38
38
|
end
|
39
39
|
|
40
40
|
def get(category, identifier)
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module GoodData
|
4
|
+
module Model
|
5
|
+
class MdObject
|
6
|
+
attr_accessor :name, :title
|
7
|
+
|
8
|
+
def visual
|
9
|
+
"TITLE \"#{title_esc}\""
|
10
|
+
end
|
11
|
+
|
12
|
+
def title_esc
|
13
|
+
title.gsub(/"/, "\\\"")
|
14
|
+
end
|
15
|
+
|
16
|
+
##
|
17
|
+
# Generates an identifier from the object name by transliterating
|
18
|
+
# non-Latin character and then dropping non-alphanumerical characters.
|
19
|
+
#
|
20
|
+
def identifier
|
21
|
+
@identifier ||= "#{type_prefix}.#{name}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -1,38 +1,62 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
|
-
require_relative '
|
3
|
+
require_relative '../core/connection'
|
4
|
+
require_relative '../core/project'
|
4
5
|
|
5
6
|
module GoodData
|
6
7
|
class MdObject
|
7
8
|
MD_OBJ_CTG = 'obj'
|
8
9
|
IDENTIFIERS_CFG = 'instance-identifiers'
|
9
10
|
|
11
|
+
attr_reader :json
|
12
|
+
|
13
|
+
alias_method :raw_data, :json
|
14
|
+
alias_method :to_hash, :json
|
15
|
+
alias_method :data, :json
|
16
|
+
|
10
17
|
class << self
|
11
18
|
def root_key(a_key)
|
12
|
-
define_method :root_key,
|
19
|
+
define_method :root_key, proc { a_key.to_s }
|
20
|
+
end
|
21
|
+
|
22
|
+
def metadata_property_reader(*props)
|
23
|
+
props.each do |prop|
|
24
|
+
define_method prop, proc { meta[prop.to_s] }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def metadata_property_writer(*props)
|
29
|
+
props.each do |prop|
|
30
|
+
define_method "#{prop}=", proc { |val| meta[prop.to_s] = val }
|
31
|
+
end
|
13
32
|
end
|
14
33
|
|
15
|
-
|
16
|
-
|
17
|
-
|
34
|
+
# Returns either list of objects or a specific object. This method is reimplemented in subclasses to leverage specific implementation for specific type of objects. Options is used in subclasses specifically to provide shorthand for getting a full objects after getting a list of hashes from query resource
|
35
|
+
# @param [Object] id id can be either a number a String (as a URI). Subclasses should also be abel to deal with getting the instance of MdObject already and a :all symbol
|
36
|
+
# @param [Hash] options the options hash
|
37
|
+
# @option options [Boolean] :full if passed true the subclass can decide to pull in full objects. This is desirable from the usability POV but unfortunately has negative impact on performance so it is not the default
|
38
|
+
# @return [MdObject] if id is a String or number single object is returned
|
39
|
+
# @return [Array] if :all was provided as an id, list of objects should be returned. Note that this is implemented only in the subclasses. MdObject does not support this since API has no means to return list of all types of objects
|
40
|
+
def [](id, options = {})
|
41
|
+
fail "Cannot search for nil #{self.class}" unless id
|
42
|
+
uri = if id.is_a?(Integer) || id =~ /^\d+$/
|
18
43
|
"#{GoodData.project.md[MD_OBJ_CTG]}/#{id}"
|
19
44
|
elsif id !~ /\//
|
20
45
|
identifier_to_uri id
|
21
46
|
elsif id =~ /^\//
|
22
47
|
id
|
23
48
|
else
|
24
|
-
|
49
|
+
fail 'Unexpected object id format: expected numeric ID, identifier with no slashes or an URI starting with a slash'
|
25
50
|
end
|
26
|
-
|
51
|
+
new(GoodData.get uri) unless uri.nil?
|
27
52
|
end
|
28
53
|
|
29
|
-
def
|
30
|
-
self[:all
|
54
|
+
def all(options = {})
|
55
|
+
self[:all, options]
|
31
56
|
end
|
32
57
|
|
33
|
-
def
|
34
|
-
|
35
|
-
self[uri] unless uri.nil?
|
58
|
+
def find_by_tag(tag)
|
59
|
+
self[:all].select { |r| r['tags'].split(',').include?(tag) }
|
36
60
|
end
|
37
61
|
|
38
62
|
def find_first_by_title(title)
|
@@ -45,10 +69,26 @@ module GoodData
|
|
45
69
|
self[item['link']] unless item.nil?
|
46
70
|
end
|
47
71
|
|
72
|
+
# Finds a specific type of the object by title. Returns all matches. Returns full object.
|
73
|
+
#
|
74
|
+
# @param title [String] title that has to match exactly
|
75
|
+
# @param title [Regexp] regular expression that has to match
|
76
|
+
# @return [Array<GoodData::MdObject>] Array of MdObject
|
77
|
+
def find_by_title(title)
|
78
|
+
all = self[:all]
|
79
|
+
items = if title.is_a?(Regexp)
|
80
|
+
all.select { |r| r['title'] =~ title }
|
81
|
+
else
|
82
|
+
all.select { |r| r['title'] == title }
|
83
|
+
end
|
84
|
+
items.map { |item| self[item['link']] unless item.nil? }
|
85
|
+
end
|
86
|
+
|
87
|
+
# TODO: Add test
|
48
88
|
def identifier_to_uri(*ids)
|
49
|
-
|
89
|
+
fail(NoProjectError, 'Connect to a project before searching for an object') unless GoodData.project
|
50
90
|
uri = GoodData.project.md[IDENTIFIERS_CFG]
|
51
|
-
response = GoodData.post uri,
|
91
|
+
response = GoodData.post uri, 'identifierToUri' => ids
|
52
92
|
if response['identifiers'].empty?
|
53
93
|
nil
|
54
94
|
else
|
@@ -57,11 +97,20 @@ module GoodData
|
|
57
97
|
end
|
58
98
|
end
|
59
99
|
|
60
|
-
|
100
|
+
alias_method :id_to_uri, :identifier_to_uri
|
101
|
+
|
102
|
+
alias_method :get_by_id, :[]
|
61
103
|
end
|
62
104
|
|
63
|
-
|
64
|
-
|
105
|
+
metadata_property_reader :uri, :identifier, :title, :summary, :tags, :deprecated, :category
|
106
|
+
metadata_property_writer :tags, :summary, :title
|
107
|
+
|
108
|
+
def root_key
|
109
|
+
raw_data.keys.first
|
110
|
+
end
|
111
|
+
|
112
|
+
def initialize(data)
|
113
|
+
@json = data.to_hash
|
65
114
|
end
|
66
115
|
|
67
116
|
def delete
|
@@ -72,13 +121,13 @@ module GoodData
|
|
72
121
|
end
|
73
122
|
end
|
74
123
|
|
75
|
-
def
|
76
|
-
if saved?
|
77
|
-
@json = GoodData.get(uri)
|
78
|
-
end
|
124
|
+
def reload!
|
125
|
+
@json = GoodData.get(uri) if saved?
|
79
126
|
self
|
80
127
|
end
|
81
128
|
|
129
|
+
alias_method :refresh, :reload!
|
130
|
+
|
82
131
|
def obj_id
|
83
132
|
uri.split('/').last
|
84
133
|
end
|
@@ -87,40 +136,30 @@ module GoodData
|
|
87
136
|
data['links']
|
88
137
|
end
|
89
138
|
|
90
|
-
def uri
|
91
|
-
meta && meta['uri']
|
92
|
-
end
|
93
|
-
|
94
139
|
def browser_uri
|
95
140
|
GoodData.connection.url + meta['uri']
|
96
141
|
end
|
97
142
|
|
98
|
-
def
|
99
|
-
meta['
|
100
|
-
end
|
101
|
-
|
102
|
-
def title
|
103
|
-
meta['title']
|
104
|
-
end
|
105
|
-
|
106
|
-
def summary
|
107
|
-
meta['summary']
|
108
|
-
end
|
109
|
-
|
110
|
-
def title=(a_title)
|
111
|
-
data['meta']['title'] = a_title
|
143
|
+
def updated
|
144
|
+
Time.parse(meta['updated'])
|
112
145
|
end
|
113
146
|
|
114
|
-
def
|
115
|
-
|
147
|
+
def created
|
148
|
+
Time.parse(meta['created'])
|
116
149
|
end
|
117
150
|
|
118
|
-
def
|
119
|
-
|
151
|
+
def deprecated=(flag)
|
152
|
+
if flag == '1' || flag == 1
|
153
|
+
meta['deprecated'] = '1'
|
154
|
+
elsif flag == '0' || flag == 0
|
155
|
+
meta['deprecated'] = '0'
|
156
|
+
else
|
157
|
+
fail 'You have to provide flag as either 1 or "1" or 0 or "0"'
|
158
|
+
end
|
120
159
|
end
|
121
160
|
|
122
|
-
def
|
123
|
-
|
161
|
+
def data
|
162
|
+
raw_data[root_key]
|
124
163
|
end
|
125
164
|
|
126
165
|
def meta
|
@@ -132,34 +171,36 @@ module GoodData
|
|
132
171
|
end
|
133
172
|
|
134
173
|
def project
|
135
|
-
@project ||= Project[uri.gsub(
|
174
|
+
@project ||= Project[uri.gsub(%r{\/obj\/\d+$}, '')]
|
136
175
|
end
|
137
176
|
|
138
|
-
def
|
139
|
-
|
140
|
-
result['entries']
|
177
|
+
def usedby(key = nil)
|
178
|
+
dependency("#{GoodData.project.md['usedby2']}/#{obj_id}", key)
|
141
179
|
end
|
142
180
|
|
143
|
-
|
144
|
-
|
145
|
-
|
181
|
+
alias_method :used_by, :usedby
|
182
|
+
|
183
|
+
def using(key = nil)
|
184
|
+
dependency("#{GoodData.project.md['using2']}/#{obj_id}", key)
|
146
185
|
end
|
147
186
|
|
148
|
-
def
|
149
|
-
|
187
|
+
def usedby?(obj)
|
188
|
+
dependency?(:usedby, obj)
|
150
189
|
end
|
151
190
|
|
152
|
-
|
153
|
-
|
191
|
+
alias_method :used_by?, :usedby?
|
192
|
+
|
193
|
+
def using?(obj)
|
194
|
+
dependency?(:using, obj)
|
154
195
|
end
|
155
196
|
|
156
|
-
def
|
157
|
-
|
158
|
-
raw_data[key]
|
197
|
+
def to_json
|
198
|
+
@json.to_json
|
159
199
|
end
|
160
200
|
|
161
201
|
def saved?
|
162
|
-
|
202
|
+
res = uri.nil?
|
203
|
+
!res
|
163
204
|
end
|
164
205
|
|
165
206
|
def save
|
@@ -168,15 +209,36 @@ module GoodData
|
|
168
209
|
if saved?
|
169
210
|
GoodData.put(uri, to_json)
|
170
211
|
else
|
212
|
+
explicit_identifier = meta['identifier']
|
213
|
+
# Pre-check to provide a user-friendly error rather than
|
214
|
+
# failing later
|
215
|
+
if explicit_identifier && MdObject[explicit_identifier]
|
216
|
+
fail "Identifier '#{explicit_identifier}' already in use"
|
217
|
+
end
|
171
218
|
result = GoodData.post(GoodData.project.md['obj'], to_json)
|
172
219
|
saved_object = self.class[result['uri']]
|
220
|
+
# TODO: add test for explicitly provided identifier
|
173
221
|
@json = saved_object.raw_data
|
222
|
+
if explicit_identifier
|
223
|
+
# Object creation API discards the identifier. If an identifier
|
224
|
+
# was explicitely provided in the origina object, we need to set
|
225
|
+
# it explicitly with an extra PUT call.
|
226
|
+
meta['identifier'] = explicit_identifier
|
227
|
+
begin
|
228
|
+
GoodData.put(uri, to_json)
|
229
|
+
rescue => e
|
230
|
+
# Cannot change the identifier (perhaps because it's in use
|
231
|
+
# already?), cleaning up.
|
232
|
+
GoodData.delete(uri)
|
233
|
+
raise e
|
234
|
+
end
|
235
|
+
end
|
174
236
|
end
|
175
237
|
self
|
176
238
|
end
|
177
239
|
|
178
240
|
def ==(other)
|
179
|
-
other.uri == uri
|
241
|
+
other.uri == uri && other.respond_to?(:to_hash) && other.to_hash == to_hash
|
180
242
|
end
|
181
243
|
|
182
244
|
def validate
|
@@ -187,5 +249,41 @@ module GoodData
|
|
187
249
|
false
|
188
250
|
end
|
189
251
|
|
252
|
+
# TODO: generate fill for other subtypes
|
253
|
+
def fact?
|
254
|
+
false
|
255
|
+
end
|
256
|
+
|
257
|
+
def attribute?
|
258
|
+
false
|
259
|
+
end
|
260
|
+
|
261
|
+
def metric?
|
262
|
+
false
|
263
|
+
end
|
264
|
+
|
265
|
+
private
|
266
|
+
|
267
|
+
def dependency(uri, key = nil)
|
268
|
+
result = GoodData.get("#{uri}/#{obj_id}")['entries']
|
269
|
+
if key.nil?
|
270
|
+
result
|
271
|
+
elsif key.respond_to?(:category)
|
272
|
+
result.select { |item| item['category'] == key.category }
|
273
|
+
else
|
274
|
+
result.select { |item| item['category'] == key }
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
def dependency?(type, uri)
|
279
|
+
objs = case type
|
280
|
+
when :usedby
|
281
|
+
usedby
|
282
|
+
when :using
|
283
|
+
using
|
284
|
+
end
|
285
|
+
uri = uri.respond_to?(:uri) ? uri.uri : uri
|
286
|
+
objs.any? { |obj| obj['link'] == uri }
|
287
|
+
end
|
190
288
|
end
|
191
|
-
end
|
289
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require_relative 'metadata'
|
4
|
+
|
5
|
+
module GoodData
|
6
|
+
class Attribute < MdObject
|
7
|
+
root_key :attribute
|
8
|
+
|
9
|
+
ATTRIBUTE_BASE_AGGREGATIONS = [:count]
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def [](id, options = {})
|
13
|
+
if id == :all
|
14
|
+
attrs = GoodData.get(GoodData.project.md['query'] + '/attributes/')['query']['entries']
|
15
|
+
options[:full] ? attrs.map { |a| Attribute[a['link']] } : attrs
|
16
|
+
else
|
17
|
+
super
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def find_element_value(uri)
|
22
|
+
matches = uri.match(/(.*)\/elements\?id=(\d+)$/)
|
23
|
+
Attribute[matches[1]].primary_label.find_element_value(matches[2].to_i)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def display_forms
|
28
|
+
content['displayForms'].map { |df| GoodData::DisplayForm[df['meta']['uri']] }
|
29
|
+
end
|
30
|
+
alias_method :labels, :display_forms
|
31
|
+
|
32
|
+
# Returns the first display form which is the primary one
|
33
|
+
# @return [GoodData::DisplayForm] Primary label
|
34
|
+
def primary_display_form
|
35
|
+
labels.first
|
36
|
+
end
|
37
|
+
alias_method :primary_label, :primary_display_form
|
38
|
+
|
39
|
+
def attribute?
|
40
|
+
true
|
41
|
+
end
|
42
|
+
|
43
|
+
def create_metric(options = {})
|
44
|
+
an_attribute = options[:attribute]
|
45
|
+
a_type = options[:type] || :count
|
46
|
+
fail "Suggested aggreagtion function (#{a_type}) does not exist for base metric created out of attribute. You can use only one of #{ATTRIBUTE_BASE_AGGREGATIONS.map { |x| ":" + x.to_s }.join(',')}" unless ATTRIBUTE_BASE_AGGREGATIONS.include?(a_type)
|
47
|
+
a_title = options[:title] || "#{a_type} of #{title}"
|
48
|
+
if an_attribute
|
49
|
+
an_attribute = Attribute[an_attribute] if an_attribute.is_a?(String)
|
50
|
+
Metric.xcreate(:expression => "SELECT #{a_type.to_s.upcase}(![#{identifier}], ![#{an_attribute.identifier}])", :title => a_title)
|
51
|
+
else
|
52
|
+
Metric.xcreate(:expression => "SELECT #{a_type.to_s.upcase}(![#{identifier}])", :title => a_title)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# For an element id find values (titles) for all display forms. Element id can be given as both number id or URI as a string beginning with /
|
57
|
+
# @param [Object] element_id Element identifier either Number or a uri as a String
|
58
|
+
# @return [Array] list of values for certain element. Returned in the same order as is the order of labels
|
59
|
+
def values_for(element_id)
|
60
|
+
element_id = element_id.is_a?(String) ? element_id.match(/\?id=(\d)/)[1] : element_id
|
61
|
+
labels.map do |label|
|
62
|
+
label.find_element_value(element_id)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns all values for all labels. This is for inspection purposes only since obviously there can be huge number of elements.
|
67
|
+
# @param [Hash] options the options to pass to the value list
|
68
|
+
# @option options [Number] :limit limits the number of values to certain number. Default is 100
|
69
|
+
# @return [Array]
|
70
|
+
def values(options = {})
|
71
|
+
results = labels.map do |label|
|
72
|
+
label.values(options)
|
73
|
+
end
|
74
|
+
results.first.zip(*results[1..-1])
|
75
|
+
end
|
76
|
+
|
77
|
+
def label_by_name(name)
|
78
|
+
labels.find { |label| label.title.downcase =~ /#{name}/ || label.identifier.downcase =~ /#{name}/ }
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|