gooddata 0.6.4 → 0.6.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.markdown +4 -0
- data/README.md +1 -0
- data/lib/gooddata/cli/commands/project_cmd.rb +2 -7
- data/lib/gooddata/client.rb +0 -2
- data/lib/gooddata/commands/project.rb +10 -0
- data/lib/gooddata/core/rest.rb +12 -2
- data/lib/gooddata/exceptions/attr_element_not_found.rb +12 -0
- data/lib/gooddata/extensions/enumerable.rb +12 -0
- data/lib/gooddata/helpers/global_helpers.rb +20 -0
- data/lib/gooddata/mixins/author.rb +16 -0
- data/lib/gooddata/mixins/content_getter.rb +11 -0
- data/lib/gooddata/mixins/content_property_reader.rb +13 -0
- data/lib/gooddata/mixins/content_property_writer.rb +13 -0
- data/lib/gooddata/mixins/contributor.rb +16 -0
- data/lib/gooddata/mixins/data_getter.rb +11 -0
- data/lib/gooddata/mixins/data_property_reader.rb +13 -0
- data/lib/gooddata/mixins/data_property_writer.rb +13 -0
- data/lib/gooddata/mixins/is_attribute.rb +13 -0
- data/lib/gooddata/mixins/is_fact.rb +13 -0
- data/lib/gooddata/mixins/is_label.rb +15 -0
- data/lib/gooddata/mixins/links.rb +11 -0
- data/lib/gooddata/mixins/md_finders.rb +36 -0
- data/lib/gooddata/mixins/md_id_to_uri.rb +29 -0
- data/lib/gooddata/mixins/md_json.rb +11 -0
- data/lib/gooddata/mixins/md_object_id.rb +11 -0
- data/lib/gooddata/mixins/md_object_indexer.rb +36 -0
- data/lib/gooddata/mixins/md_object_query.rb +83 -0
- data/lib/gooddata/mixins/md_relations.rb +39 -0
- data/lib/gooddata/mixins/meta_getter.rb +11 -0
- data/lib/gooddata/mixins/meta_property_reader.rb +13 -0
- data/lib/gooddata/mixins/meta_property_writer.rb +13 -0
- data/lib/gooddata/mixins/mixins.rb +15 -0
- data/lib/gooddata/mixins/not_attribute.rb +13 -0
- data/lib/gooddata/mixins/not_exportable.rb +11 -0
- data/lib/gooddata/mixins/not_fact.rb +13 -0
- data/lib/gooddata/mixins/not_label.rb +15 -0
- data/lib/gooddata/mixins/not_metric.rb +13 -0
- data/lib/gooddata/mixins/obj_id.rb +11 -0
- data/lib/gooddata/mixins/rest_getters.rb +13 -0
- data/lib/gooddata/mixins/rest_resource.rb +19 -0
- data/lib/gooddata/mixins/root_key_getter.rb +11 -0
- data/lib/gooddata/mixins/root_key_setter.rb +11 -0
- data/lib/gooddata/mixins/timestamps.rb +15 -0
- data/lib/gooddata/models/from_wire.rb +153 -0
- data/lib/gooddata/models/metadata.rb +28 -230
- data/lib/gooddata/models/metadata/attribute.rb +4 -6
- data/lib/gooddata/models/metadata/fact.rb +4 -6
- data/lib/gooddata/models/metadata/{display_form.rb → label.rb} +17 -11
- data/lib/gooddata/models/metadata/metric.rb +1 -1
- data/lib/gooddata/models/metadata/report_definition.rb +2 -2
- data/lib/gooddata/models/model.rb +55 -23
- data/lib/gooddata/models/models.rb +0 -2
- data/lib/gooddata/models/module_constants.rb +0 -2
- data/lib/gooddata/models/process.rb +1 -1
- data/lib/gooddata/models/project.rb +117 -76
- data/lib/gooddata/models/project_blueprint.rb +322 -42
- data/lib/gooddata/models/project_creator.rb +5 -4
- data/lib/gooddata/models/project_role.rb +20 -55
- data/lib/gooddata/models/schema_blueprint.rb +287 -84
- data/lib/gooddata/models/schema_builder.rb +0 -4
- data/lib/gooddata/models/to_manifest.rb +160 -0
- data/lib/gooddata/models/to_wire.rb +150 -0
- data/lib/gooddata/version.rb +1 -1
- data/spec/data/blueprint_invalid.json +3 -1
- data/spec/data/gd_gse_data_blueprint.json +1370 -0
- data/spec/data/gd_gse_data_manifest.json +1424 -0
- data/spec/data/gd_gse_data_model.json +1772 -0
- data/spec/data/manifest_test_project.json +116 -0
- data/spec/data/model_view.json +1772 -0
- data/spec/data/superfluous_titles_view.json +81 -0
- data/spec/data/test_project_model_spec.json +7 -4
- data/spec/data/wire_test_project.json +143 -0
- data/spec/helpers/crypto_helper.rb +9 -0
- data/spec/helpers/project_helper.rb +2 -0
- data/spec/integration/command_projects_spec.rb +4 -2
- data/spec/integration/full_project_spec.rb +51 -18
- data/spec/integration/partial_md_export_import_spec.rb +1 -1
- data/spec/spec_helper.rb +2 -1
- data/spec/unit/models/attribute_column_spec.rb +7 -7
- data/spec/unit/models/domain_spec.rb +2 -2
- data/spec/unit/models/from_wire_spec.rb +119 -0
- data/spec/unit/models/metadata_spec.rb +4 -2
- data/spec/unit/models/project_blueprint_spec.rb +32 -16
- data/spec/unit/models/project_role_spec.rb +6 -4
- data/spec/unit/models/project_spec.rb +26 -3
- data/spec/unit/models/schema_builder_spec.rb +5 -6
- data/spec/unit/models/to_manifest_spec.rb +24 -0
- data/spec/unit/models/to_wire_spec.rb +63 -0
- metadata +53 -29
- data/lib/gooddata/models/attributes/anchor.rb +0 -37
- data/lib/gooddata/models/attributes/attributes.rb +0 -8
- data/lib/gooddata/models/attributes/date_attribute.rb +0 -25
- data/lib/gooddata/models/attributes/time_attribute.rb +0 -24
- data/lib/gooddata/models/columns/attribute.rb +0 -71
- data/lib/gooddata/models/columns/columns.rb +0 -8
- data/lib/gooddata/models/columns/date_column.rb +0 -63
- data/lib/gooddata/models/columns/fact_model.rb +0 -54
- data/lib/gooddata/models/columns/label.rb +0 -55
- data/lib/gooddata/models/columns/reference.rb +0 -57
- data/lib/gooddata/models/facts/facts.rb +0 -8
- data/lib/gooddata/models/facts/time_fact.rb +0 -20
- data/lib/gooddata/models/folders/attribute_folder.rb +0 -20
- data/lib/gooddata/models/folders/fact_folder.rb +0 -20
- data/lib/gooddata/models/folders/folders.rb +0 -8
- data/lib/gooddata/models/metadata/column.rb +0 -61
- data/lib/gooddata/models/metadata/data_set.rb +0 -32
- data/lib/gooddata/models/metadata/date_dimension.rb +0 -26
- data/lib/gooddata/models/metadata/schema.rb +0 -227
- data/lib/gooddata/models/references/date_reference.rb +0 -44
- data/lib/gooddata/models/references/references.rb +0 -8
- data/lib/gooddata/models/references/time_reference.rb +0 -13
- data/spec/helpers/schema_helper.rb +0 -16
- data/spec/unit/models/anchor_spec.rb +0 -32
- data/spec/unit/models/tools_spec.rb +0 -95
- data/test/test_upload.rb +0 -79
|
@@ -5,6 +5,11 @@ module GoodData
|
|
|
5
5
|
class ProjectBlueprint
|
|
6
6
|
attr_accessor :data
|
|
7
7
|
|
|
8
|
+
# Instantiates a project blueprint either from a file or from a string containing
|
|
9
|
+
# json. Also eats Hash for convenience.
|
|
10
|
+
#
|
|
11
|
+
# @param spec [String | Hash] value of an label you are looking for
|
|
12
|
+
# @return [GoodData::Model::ProjectBlueprint]
|
|
8
13
|
def self.from_json(spec)
|
|
9
14
|
if spec.is_a?(String)
|
|
10
15
|
if File.file?(spec)
|
|
@@ -17,6 +22,131 @@ module GoodData
|
|
|
17
22
|
end
|
|
18
23
|
end
|
|
19
24
|
|
|
25
|
+
# Removes dataset from blueprint. Dataset can be given as either a name
|
|
26
|
+
# or a DatasetBlueprint or a Hash representation.
|
|
27
|
+
#
|
|
28
|
+
# @param project [Hash] Project blueprint
|
|
29
|
+
# @param dataset_name [GoodData::Model::DatasetBlueprint | String | Hash] Dataset to be removed
|
|
30
|
+
# @return [Hash] project with removed dataset
|
|
31
|
+
def self.remove_dataset(project, dataset_name)
|
|
32
|
+
dataset = dataset_name.is_a?(String) ? find_dataset(project, dataset_name) : dataset_name
|
|
33
|
+
index = project[:datasets].index(dataset)
|
|
34
|
+
dupped_project = project.deep_dup
|
|
35
|
+
dupped_project[:datasets].delete_at(index)
|
|
36
|
+
dupped_project
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Removes dataset from blueprint. Dataset can be given as either a name
|
|
40
|
+
# or a DatasetBlueprint or a Hash representation. This version mutates
|
|
41
|
+
# the dataset in place
|
|
42
|
+
#
|
|
43
|
+
# @param project [Hash] Project blueprint
|
|
44
|
+
# @param dataset_name [GoodData::Model::DatasetBlueprint | String | Hash] Dataset to be removed
|
|
45
|
+
# @return [Hash] project with removed dataset
|
|
46
|
+
def self.remove_dataset!(project, dataset_name)
|
|
47
|
+
dataset = dataset_name.is_a?(String) ? find_dataset(project, dataset_name) : dataset_name
|
|
48
|
+
index = project[:datasets].index(dataset)
|
|
49
|
+
project[:datasets].delete_at(index)
|
|
50
|
+
project
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Returns datasets of blueprint. Those can be optionally including
|
|
54
|
+
# date dimensions
|
|
55
|
+
#
|
|
56
|
+
# @param project [GoodData::Model::ProjectBlueprint | Hash] Project blueprint
|
|
57
|
+
# @param options [Hash] options
|
|
58
|
+
# @return [Array<Hash>]
|
|
59
|
+
def self.datasets(project, options = {})
|
|
60
|
+
include_date_dimensions = options[:include_date_dimensions] || options[:dd]
|
|
61
|
+
ds = (project.to_hash[:datasets] || [])
|
|
62
|
+
if include_date_dimensions
|
|
63
|
+
ds + date_dimensions(project)
|
|
64
|
+
else
|
|
65
|
+
ds
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Returns true if a dataset contains a particular dataset false otherwise
|
|
70
|
+
#
|
|
71
|
+
# @param project [GoodData::Model::ProjectBlueprint | Hash] Project blueprint
|
|
72
|
+
# @param name [GoodData::Model::DatasetBlueprint | String | Hash] Dataset
|
|
73
|
+
# @return [Boolean]
|
|
74
|
+
def self.dataset?(project, name)
|
|
75
|
+
find_dataset(project, name)
|
|
76
|
+
true
|
|
77
|
+
rescue
|
|
78
|
+
false
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Returns dataset specified. It can check even for a date dimension
|
|
82
|
+
#
|
|
83
|
+
# @param project [GoodData::Model::ProjectBlueprint | Hash] Project blueprint
|
|
84
|
+
# @param name [GoodData::Model::DatasetBlueprint | String | Hash] Dataset
|
|
85
|
+
# @param options [Hash] options
|
|
86
|
+
# @return [GoodData::Model::DatasetBlueprint]
|
|
87
|
+
def self.find_dataset(project, name, options = {})
|
|
88
|
+
include_date_dimensions = options[:include_date_dimensions] || options[:dd]
|
|
89
|
+
return name.to_hash if DatasetBlueprint.dataset_blueprint?(name)
|
|
90
|
+
all_datasets = if include_date_dimensions
|
|
91
|
+
datasets(project) + date_dimensions(project)
|
|
92
|
+
else
|
|
93
|
+
datasets(project)
|
|
94
|
+
end
|
|
95
|
+
ds = all_datasets.find { |d| d[:name] == name }
|
|
96
|
+
fail "Dataset #{name} could not be found" if ds.nil?
|
|
97
|
+
ds
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Returns list of date dimensions
|
|
101
|
+
#
|
|
102
|
+
# @param project [GoodData::Model::ProjectBlueprint | Hash] Project blueprint
|
|
103
|
+
# @return [Array<Hash>]
|
|
104
|
+
def self.date_dimensions(project)
|
|
105
|
+
project.to_hash[:date_dimensions] || []
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# Returns true if a date dimension of a given name exists in a bleuprint
|
|
109
|
+
#
|
|
110
|
+
# @param project [GoodData::Model::ProjectBlueprint | Hash] Project blueprint
|
|
111
|
+
# @param name [string] Date dimension
|
|
112
|
+
# @return [Boolean]
|
|
113
|
+
def self.date_dimension?(project, name)
|
|
114
|
+
find_date_dimension(project, name)
|
|
115
|
+
true
|
|
116
|
+
rescue
|
|
117
|
+
false
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Finds a date dimension of a given name in a bleuprint. If a dataset is
|
|
121
|
+
# not found it throws an exeception
|
|
122
|
+
#
|
|
123
|
+
# @param project [GoodData::Model::ProjectBlueprint | Hash] Project blueprint
|
|
124
|
+
# @param name [string] Date dimension
|
|
125
|
+
# @return [Hash]
|
|
126
|
+
def self.find_date_dimension(project, name)
|
|
127
|
+
ds = date_dimensions(project).find { |d| d[:name] == name }
|
|
128
|
+
fail "Date dimension #{name} could not be found" if ds.nil?
|
|
129
|
+
ds
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Returns fields from all datasets
|
|
133
|
+
#
|
|
134
|
+
# @param project [GoodData::Model::ProjectBlueprint | Hash] Project blueprint
|
|
135
|
+
# @return [Array<Hash>]
|
|
136
|
+
def self.fields(project)
|
|
137
|
+
datasets(project).mapcat { |d| DatasetBlueprint.fields(d) }
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Returns a dataset of a given name. If a dataset is not found it throws an exeception
|
|
141
|
+
#
|
|
142
|
+
# @param project [GoodData::Model::ProjectBlueprint | Hash] Project blueprint
|
|
143
|
+
# @param project [String] Dataset title
|
|
144
|
+
# @return [Array<Hash>]
|
|
145
|
+
def find_dataset_by_title(project, title)
|
|
146
|
+
ds = datasets(project).find { |d| Model.title(d) == title }
|
|
147
|
+
fail "Dataset #{title} could not be found" if ds.nil?
|
|
148
|
+
end
|
|
149
|
+
|
|
20
150
|
def change(&block)
|
|
21
151
|
builder = ProjectBuilder.create_from_data(self)
|
|
22
152
|
block.call(builder)
|
|
@@ -24,9 +154,13 @@ module GoodData
|
|
|
24
154
|
self
|
|
25
155
|
end
|
|
26
156
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
157
|
+
# Returns datasets of blueprint. Those can be optionally including
|
|
158
|
+
# date dimensions
|
|
159
|
+
#
|
|
160
|
+
# @param options [Hash] options
|
|
161
|
+
# @return [Array<GoodData::Model::DatasetBlueprint>]
|
|
162
|
+
def datasets(options = {})
|
|
163
|
+
ProjectBlueprint.datasets(to_hash, options).map { |d| DatasetBlueprint.new(d) }
|
|
30
164
|
end
|
|
31
165
|
|
|
32
166
|
def add_dataset(a_dataset, index = nil)
|
|
@@ -37,10 +171,22 @@ module GoodData
|
|
|
37
171
|
end
|
|
38
172
|
end
|
|
39
173
|
|
|
174
|
+
# Removes dataset from blueprint. Dataset can be given as either a name
|
|
175
|
+
# or a DatasetBlueprint or a Hash representation.
|
|
176
|
+
#
|
|
177
|
+
# @param dataset_name [GoodData::Model::DatasetBlueprint | String | Hash] Dataset to be removed
|
|
178
|
+
# @return [Hash] project with removed dataset
|
|
40
179
|
def remove_dataset(dataset_name)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
180
|
+
ProjectBlueprint.remove_dataset(to_hash, dataset_name)
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
# Removes dataset from blueprint. Dataset can be given as either a name
|
|
184
|
+
# or a DatasetBlueprint or a Hash representation.
|
|
185
|
+
#
|
|
186
|
+
# @param dataset_name [GoodData::Model::DatasetBlueprint | String | Hash] Dataset to be removed
|
|
187
|
+
# @return [Hash] project with removed dataset
|
|
188
|
+
def remove_dataset!(dataset_name)
|
|
189
|
+
ProjectBlueprint.remove_dataset!(to_hash, dataset_name)
|
|
44
190
|
end
|
|
45
191
|
|
|
46
192
|
# Is this a project blueprint?
|
|
@@ -50,18 +196,36 @@ module GoodData
|
|
|
50
196
|
true
|
|
51
197
|
end
|
|
52
198
|
|
|
199
|
+
# Returns list of date dimensions
|
|
200
|
+
#
|
|
201
|
+
# @return [Array<Hash>]
|
|
53
202
|
def date_dimensions
|
|
54
|
-
|
|
203
|
+
ProjectBlueprint.date_dimensions(to_hash)
|
|
55
204
|
end
|
|
56
205
|
|
|
206
|
+
# Returns true if a dataset contains a particular dataset false otherwise
|
|
207
|
+
#
|
|
208
|
+
# @param name [GoodData::Model::DatasetBlueprint | String | Hash] Dataset
|
|
209
|
+
# @return [Boolean]
|
|
57
210
|
def dataset?(name)
|
|
58
|
-
|
|
59
|
-
found != nil
|
|
211
|
+
ProjectBlueprint.dataset?(to_hash, name)
|
|
60
212
|
end
|
|
61
213
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
214
|
+
# Returns dataset specified. It can check even for a date dimension
|
|
215
|
+
#
|
|
216
|
+
# @param name [GoodData::Model::DatasetBlueprint | String | Hash] Dataset
|
|
217
|
+
# @param options [Hash] options
|
|
218
|
+
# @return [GoodData::Model::DatasetBlueprint]
|
|
219
|
+
def find_dataset(name, options = {})
|
|
220
|
+
DatasetBlueprint.new(ProjectBlueprint.find_dataset(to_hash, name, options))
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
# Returns a dataset of a given name. If a dataset is not found it throws an exeception
|
|
224
|
+
#
|
|
225
|
+
# @param project [String] Dataset title
|
|
226
|
+
# @return [Array<Hash>]
|
|
227
|
+
def find_dataset_by_title(title)
|
|
228
|
+
ds = ProjectBlueprint.find_dataset_by_title(to_hash, title)
|
|
65
229
|
DatasetBlueprint.new(ds)
|
|
66
230
|
end
|
|
67
231
|
|
|
@@ -87,12 +251,12 @@ module GoodData
|
|
|
87
251
|
if datasets.count == 1
|
|
88
252
|
[]
|
|
89
253
|
else
|
|
90
|
-
x = datasets.reduce([]) { |a, e| e.anchor? ? a << [e.name
|
|
254
|
+
x = datasets.reduce([]) { |a, e| e.anchor? ? a << [e.name] : a } + date_dimensions.map { |y| [y[:name]] }
|
|
91
255
|
refs = datasets.reduce([]) do |a, e|
|
|
92
256
|
a.concat(e.references)
|
|
93
257
|
end
|
|
94
258
|
refs.reduce([]) do |a, e|
|
|
95
|
-
x.include?([e[:dataset]
|
|
259
|
+
x.include?([e[:dataset]]) ? a : a.concat([e])
|
|
96
260
|
end
|
|
97
261
|
end
|
|
98
262
|
end
|
|
@@ -113,29 +277,59 @@ module GoodData
|
|
|
113
277
|
validate.empty?
|
|
114
278
|
end
|
|
115
279
|
|
|
280
|
+
# Returns list of datasets which are referenced by given dataset. This can be
|
|
281
|
+
# optionally switched to return even date dimensions
|
|
282
|
+
#
|
|
283
|
+
# @param project [GoodData::Model::DatasetBlueprint | Hash | String] Dataset blueprint
|
|
284
|
+
# @return [Array<Hash>]
|
|
116
285
|
def referenced_by(dataset)
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
find_dataset(ds[:dataset])
|
|
286
|
+
find_dataset(dataset).references.map do |ref|
|
|
287
|
+
find_dataset(ref[:dataset], include_date_dimensions: true)
|
|
120
288
|
end
|
|
121
289
|
end
|
|
122
290
|
|
|
291
|
+
# Returns list of attributes from all the datasets in a blueprint
|
|
292
|
+
#
|
|
293
|
+
# @return [Array<Hash>]
|
|
123
294
|
def attributes
|
|
124
295
|
datasets.reduce([]) { |a, e| a.concat(e.attributes) }
|
|
125
296
|
end
|
|
126
297
|
|
|
298
|
+
# Returns list of attributes and anchors from all the datasets in a blueprint
|
|
299
|
+
#
|
|
300
|
+
# @return [Array<Hash>]
|
|
127
301
|
def attributes_and_anchors
|
|
128
|
-
datasets.
|
|
302
|
+
datasets.mapcat(&:attributes_and_anchors)
|
|
129
303
|
end
|
|
130
304
|
|
|
305
|
+
# Returns list of labels from all the datasets in a blueprint
|
|
306
|
+
#
|
|
307
|
+
# @return [Array<Hash>]
|
|
131
308
|
def labels
|
|
132
|
-
datasets.
|
|
309
|
+
datasets.mapcat(&:labels)
|
|
133
310
|
end
|
|
134
311
|
|
|
312
|
+
# Returns list of facts from all the datasets in a blueprint
|
|
313
|
+
#
|
|
314
|
+
# @return [Array<Hash>]
|
|
135
315
|
def facts
|
|
136
|
-
datasets.
|
|
316
|
+
datasets.mapcat(&:facts)
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
# Returns list of fields from all the datasets in a blueprint
|
|
320
|
+
#
|
|
321
|
+
# @return [Array<Hash>]
|
|
322
|
+
def fields
|
|
323
|
+
ProjectBlueprint.fields(to_hash)
|
|
137
324
|
end
|
|
138
325
|
|
|
326
|
+
# Returns list of attributes that can break facts in a given dataset.
|
|
327
|
+
# This basically means that it is giving you all attributes from the
|
|
328
|
+
# datasets that are references by given dataset. Currently does not
|
|
329
|
+
# work transitively
|
|
330
|
+
#
|
|
331
|
+
# @param project [GoodData::Model::DatasetBlueprint | Hash | String] Dataset blueprint
|
|
332
|
+
# @return [Array<Hash>]
|
|
139
333
|
def can_break(dataset)
|
|
140
334
|
dataset = find_dataset(dataset) if dataset.is_a?(String)
|
|
141
335
|
referenced_by(dataset).reduce([]) do |a, e|
|
|
@@ -146,13 +340,68 @@ module GoodData
|
|
|
146
340
|
end
|
|
147
341
|
end
|
|
148
342
|
|
|
343
|
+
# Experimental but a basis for automatic check of health of a project
|
|
344
|
+
#
|
|
345
|
+
# @param project [GoodData::Model::DatasetBlueprint | Hash | String] Dataset blueprint
|
|
346
|
+
# @return [Array<Hash>]
|
|
347
|
+
def lint(full = false)
|
|
348
|
+
errors = []
|
|
349
|
+
find_star_centers.each do |dataset|
|
|
350
|
+
if dataset.anchor?
|
|
351
|
+
errors << {
|
|
352
|
+
type: :anchor_on_fact_dataset,
|
|
353
|
+
dataset_name: dataset.name,
|
|
354
|
+
anchor_name: dataset.anchor[:name]
|
|
355
|
+
}
|
|
356
|
+
end
|
|
357
|
+
end
|
|
358
|
+
|
|
359
|
+
date_facts = datasets.mapcat { |d| d.date_facts }
|
|
360
|
+
date_facts.each do |date_fact|
|
|
361
|
+
errors << {
|
|
362
|
+
type: :date_fact,
|
|
363
|
+
date_fact: date_fact[:name]
|
|
364
|
+
}
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
unique_titles = fields.map { |f| Model.title(f) }.uniq
|
|
368
|
+
(fields.map { |f| Model.title(f) } - unique_titles).each do |duplicate_title|
|
|
369
|
+
errors << {
|
|
370
|
+
type: :duplicate_title,
|
|
371
|
+
title: duplicate_title
|
|
372
|
+
}
|
|
373
|
+
end
|
|
374
|
+
|
|
375
|
+
datasets.select(&:wide?).each do |wide_dataset|
|
|
376
|
+
errors << {
|
|
377
|
+
type: :wide_dataset,
|
|
378
|
+
dataset: wide_dataset.name
|
|
379
|
+
}
|
|
380
|
+
end
|
|
381
|
+
|
|
382
|
+
if full
|
|
383
|
+
# GoodData::Attributes.all(:full => true).select { |attr| attr.used_by}
|
|
384
|
+
end
|
|
385
|
+
errors
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
# Return list of datasets that are centers of the stars in datamart.
|
|
389
|
+
# This means these datasets are not referenced by anybody else
|
|
390
|
+
# In a good blueprint design these should be fact tables
|
|
391
|
+
#
|
|
392
|
+
# @return [Array<Hash>]
|
|
149
393
|
def find_star_centers
|
|
150
|
-
referenced = datasets.
|
|
394
|
+
referenced = datasets.mapcat { |d| referenced_by(d) }
|
|
151
395
|
referenced.flatten!
|
|
152
396
|
res = datasets.map(&:to_hash) - referenced.map(&:to_hash)
|
|
153
397
|
res.map { |d| DatasetBlueprint.new(d) }
|
|
154
398
|
end
|
|
155
399
|
|
|
400
|
+
# Returns some reports that might get you started. They are just simple
|
|
401
|
+
# reports. Currently it is implemented by getting facts from star centers
|
|
402
|
+
# and randomly picking attributes form referenced datasets.
|
|
403
|
+
#
|
|
404
|
+
# @return [Array<Hash>]
|
|
156
405
|
def suggest_reports(options = {})
|
|
157
406
|
strategy = options[:strategy] || :stupid
|
|
158
407
|
case strategy
|
|
@@ -181,18 +430,32 @@ module GoodData
|
|
|
181
430
|
end
|
|
182
431
|
end
|
|
183
432
|
|
|
433
|
+
# Returns some metrics that might get you started. They are just simple
|
|
434
|
+
# reports. Currently it is implemented by getting facts from star centers
|
|
435
|
+
# and randomly picking attributes form referenced datasets.
|
|
436
|
+
#
|
|
437
|
+
# @return [Array<Hash>]
|
|
184
438
|
def suggest_metrics
|
|
185
439
|
stars = find_star_centers
|
|
186
440
|
metrics = stars.map { |s| s.suggest_metrics }
|
|
187
441
|
stars.zip(metrics)
|
|
188
442
|
end
|
|
189
443
|
|
|
444
|
+
# Merging two blueprints. The self blueprint is changed in place
|
|
445
|
+
#
|
|
446
|
+
# @param a_blueprint [GoodData::Model::DatasetBlueprint] Dataset blueprint to be merged
|
|
447
|
+
# @return [GoodData::Model::ProjectBlueprint]
|
|
190
448
|
def merge!(a_blueprint)
|
|
191
449
|
temp_blueprint = merge(a_blueprint)
|
|
192
450
|
@data = temp_blueprint.data
|
|
193
451
|
self
|
|
194
452
|
end
|
|
195
453
|
|
|
454
|
+
# Merging two blueprints. A new blueprint is created. The self one
|
|
455
|
+
# is nto mutated
|
|
456
|
+
#
|
|
457
|
+
# @param a_blueprint [GoodData::Model::DatasetBlueprint] Dataset blueprint to be merged
|
|
458
|
+
# @return [GoodData::Model::ProjectBlueprint]
|
|
196
459
|
def merge(a_blueprint)
|
|
197
460
|
temp_blueprint = dup
|
|
198
461
|
a_blueprint.datasets.each do |dataset|
|
|
@@ -209,34 +472,51 @@ module GoodData
|
|
|
209
472
|
temp_blueprint
|
|
210
473
|
end
|
|
211
474
|
|
|
475
|
+
# Duplicated blueprint
|
|
476
|
+
#
|
|
477
|
+
# @param a_blueprint [GoodData::Model::DatasetBlueprint] Dataset blueprint to be merged
|
|
478
|
+
# @return [GoodData::Model::DatasetBlueprint]
|
|
212
479
|
def dup
|
|
213
480
|
ProjectBlueprint.new(data.deep_dup)
|
|
214
481
|
end
|
|
215
482
|
|
|
483
|
+
# Returns title of a dataset. If not present it is generated from the name
|
|
484
|
+
#
|
|
485
|
+
# @return [String] a title
|
|
216
486
|
def title
|
|
217
|
-
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
'dateDimensions' => date_dimensions.map do |d|
|
|
227
|
-
{
|
|
228
|
-
'dateDimension' => {
|
|
229
|
-
'name' => d[:name],
|
|
230
|
-
'title' => d[:title] || d[:name].humanize
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
end
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
487
|
+
Model.title(to_hash)
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
# Returns Wire representation. This is used by our API to generate and
|
|
491
|
+
# change projects
|
|
492
|
+
#
|
|
493
|
+
# @return [Hash] a title
|
|
494
|
+
def to_wire
|
|
495
|
+
ToWire.to_wire(data)
|
|
238
496
|
end
|
|
239
497
|
|
|
498
|
+
# Returns SLI manifest representation. This is used by our API to allow
|
|
499
|
+
# loading data
|
|
500
|
+
#
|
|
501
|
+
# @return [Array<Hash>] a title
|
|
502
|
+
def to_manifest
|
|
503
|
+
ToManifest.to_manifest(to_hash)
|
|
504
|
+
end
|
|
505
|
+
|
|
506
|
+
# Returns SLI manifest for one dataset. This is used by our API to allow
|
|
507
|
+
# loading data. The method is on project blueprint because you need
|
|
508
|
+
# acces to whole project to be able to generate references
|
|
509
|
+
#
|
|
510
|
+
# @param dataset [GoodData::Model::DatasetBlueprint | Hash | String] Dataset
|
|
511
|
+
# @param mode [String] Method of loading. FULL or INCREMENTAL
|
|
512
|
+
# @return [Array<Hash>] a title
|
|
513
|
+
def dataset_to_manifest(dataset, mode = 'FULL')
|
|
514
|
+
ToManifest.dataset_to_manifest(self, dataset, mode)
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
# Returns hash representation of blueprint
|
|
518
|
+
#
|
|
519
|
+
# @return [Hash] a title
|
|
240
520
|
def to_hash
|
|
241
521
|
@data
|
|
242
522
|
end
|