gooddata 0.6.18 → 0.6.19
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/.travis.yml +8 -19
- data/Guardfile +5 -0
- data/README.md +1 -3
- data/bin/gooddata +1 -1
- data/gooddata.gemspec +6 -4
- data/lib/gooddata.rb +1 -1
- data/lib/gooddata/bricks/middleware/aws_middleware.rb +24 -0
- data/lib/gooddata/cli/commands/console_cmd.rb +1 -1
- data/lib/gooddata/cli/commands/project_cmd.rb +29 -9
- data/lib/gooddata/cli/hooks.rb +9 -3
- data/lib/gooddata/commands/datawarehouse.rb +1 -7
- data/lib/gooddata/commands/project.rb +4 -3
- data/lib/gooddata/core/logging.rb +14 -2
- data/lib/gooddata/exceptions/execution_limit_exceeded.rb +9 -0
- data/lib/gooddata/exceptions/uncomputable_report.rb +8 -0
- data/lib/gooddata/exceptions/validation_error.rb +1 -1
- data/lib/gooddata/goodzilla/goodzilla.rb +5 -1
- data/lib/gooddata/helpers/data_helper.rb +40 -9
- data/lib/gooddata/mixins/md_finders.rb +35 -0
- data/lib/gooddata/models/blueprint/anchor_field.rb +46 -0
- data/lib/gooddata/models/blueprint/attribute_field.rb +25 -0
- data/lib/gooddata/models/blueprint/blueprint.rb +7 -0
- data/lib/gooddata/models/blueprint/blueprint_field.rb +66 -0
- data/lib/gooddata/models/{dashboard_builder.rb → blueprint/dashboard_builder.rb} +0 -0
- data/lib/gooddata/models/{schema_blueprint.rb → blueprint/dataset_blueprint.rb} +176 -117
- data/lib/gooddata/models/blueprint/date_dimension.rb +10 -0
- data/lib/gooddata/models/blueprint/fact_field.rb +16 -0
- data/lib/gooddata/models/blueprint/label_field.rb +39 -0
- data/lib/gooddata/models/{project_blueprint.rb → blueprint/project_blueprint.rb} +366 -168
- data/lib/gooddata/models/blueprint/project_builder.rb +79 -0
- data/lib/gooddata/models/blueprint/reference_field.rb +39 -0
- data/lib/gooddata/models/blueprint/schema_blueprint.rb +156 -0
- data/lib/gooddata/models/blueprint/schema_builder.rb +85 -0
- data/lib/gooddata/models/{to_manifest.rb → blueprint/to_manifest.rb} +25 -20
- data/lib/gooddata/models/{to_wire.rb → blueprint/to_wire.rb} +33 -52
- data/lib/gooddata/models/datawarehouse.rb +2 -2
- data/lib/gooddata/models/domain.rb +3 -2
- data/lib/gooddata/models/execution.rb +2 -2
- data/lib/gooddata/models/execution_detail.rb +7 -2
- data/lib/gooddata/models/from_wire.rb +60 -71
- data/lib/gooddata/models/from_wire_parse.rb +125 -125
- data/lib/gooddata/models/metadata.rb +14 -0
- data/lib/gooddata/models/metadata/dashboard.rb +2 -2
- data/lib/gooddata/models/metadata/label.rb +1 -1
- data/lib/gooddata/models/metadata/report.rb +6 -5
- data/lib/gooddata/models/metadata/report_definition.rb +44 -59
- data/lib/gooddata/models/model.rb +131 -43
- data/lib/gooddata/models/process.rb +13 -11
- data/lib/gooddata/models/profile.rb +12 -1
- data/lib/gooddata/models/project.rb +223 -19
- data/lib/gooddata/models/project_creator.rb +4 -15
- data/lib/gooddata/models/schedule.rb +1 -0
- data/lib/gooddata/models/user_filters/user_filter_builder.rb +2 -2
- data/lib/gooddata/rest/client.rb +18 -18
- data/lib/gooddata/rest/connection.rb +113 -94
- data/lib/gooddata/version.rb +1 -1
- data/lib/templates/project/model/model.rb.erb +15 -16
- data/spec/data/blueprints/additional_dataset_module.json +32 -0
- data/spec/data/blueprints/big_blueprint_not_pruned.json +2079 -0
- data/spec/data/blueprints/invalid_blueprint.json +103 -0
- data/spec/data/blueprints/m_n_model.json +104 -0
- data/spec/data/blueprints/model_module.json +25 -0
- data/spec/data/blueprints/test_blueprint.json +38 -0
- data/spec/data/blueprints/test_project_model_spec.json +106 -0
- data/spec/data/gd_gse_data_manifest.json +34 -34
- data/spec/data/manifests/test_blueprint.json +32 -0
- data/spec/data/{manifest_test_project.json → manifests/test_project.json} +9 -18
- data/spec/data/wire_models/test_blueprint.json +63 -0
- data/spec/data/wire_test_project.json +5 -5
- data/spec/environment/default.rb +33 -0
- data/spec/environment/develop.rb +26 -0
- data/spec/environment/environment.rb +14 -0
- data/spec/environment/hotfix.rb +17 -0
- data/spec/environment/production.rb +31 -0
- data/spec/environment/release.rb +17 -0
- data/spec/helpers/blueprint_helper.rb +10 -7
- data/spec/helpers/cli_helper.rb +24 -22
- data/spec/helpers/connection_helper.rb +27 -25
- data/spec/helpers/crypto_helper.rb +7 -5
- data/spec/helpers/csv_helper.rb +5 -3
- data/spec/helpers/process_helper.rb +15 -10
- data/spec/helpers/project_helper.rb +40 -33
- data/spec/helpers/schedule_helper.rb +15 -9
- data/spec/helpers/spec_helper.rb +11 -0
- data/spec/integration/blueprint_updates_spec.rb +93 -0
- data/spec/integration/command_datawarehouse_spec.rb +2 -1
- data/spec/integration/command_projects_spec.rb +9 -8
- data/spec/integration/create_from_template_spec.rb +1 -1
- data/spec/integration/create_project_spec.rb +1 -1
- data/spec/integration/full_process_schedule_spec.rb +1 -1
- data/spec/integration/full_project_spec.rb +91 -30
- data/spec/integration/over_to_user_filters_spec.rb +24 -28
- data/spec/integration/partial_md_export_import_spec.rb +4 -4
- data/spec/integration/project_spec.rb +1 -1
- data/spec/integration/rest_spec.rb +1 -1
- data/spec/integration/user_filters_spec.rb +19 -24
- data/spec/integration/variables_spec.rb +7 -9
- data/spec/logging_in_logging_out_spec.rb +1 -1
- data/spec/spec_helper.rb +10 -1
- data/spec/unit/bricks/middleware/aws_middelware_spec.rb +47 -0
- data/spec/unit/core/connection_spec.rb +2 -2
- data/spec/unit/core/logging_spec.rb +12 -4
- data/spec/unit/helpers/data_helper_spec.rb +60 -0
- data/spec/unit/models/blueprint/attributes_spec.rb +24 -0
- data/spec/unit/models/blueprint/dataset_spec.rb +116 -0
- data/spec/unit/models/blueprint/labels_spec.rb +39 -0
- data/spec/unit/models/blueprint/project_blueprint_spec.rb +643 -0
- data/spec/unit/models/blueprint/reference_spec.rb +24 -0
- data/spec/unit/models/{schema_builder_spec.rb → blueprint/schema_builder_spec.rb} +12 -4
- data/spec/unit/models/blueprint/to_wire_spec.rb +169 -0
- data/spec/unit/models/domain_spec.rb +13 -2
- data/spec/unit/models/from_wire_spec.rb +277 -98
- data/spec/unit/models/metadata_spec.rb +22 -4
- data/spec/unit/models/model_spec.rb +49 -39
- data/spec/unit/models/profile_spec.rb +1 -0
- data/spec/unit/models/project_spec.rb +7 -7
- data/spec/unit/models/schedule_spec.rb +20 -0
- data/spec/unit/models/to_manifest_spec.rb +31 -11
- data/spec/unit/rest/polling_spec.rb +86 -0
- metadata +102 -30
- data/lib/gooddata/models/project_builder.rb +0 -136
- data/lib/gooddata/models/schema_builder.rb +0 -77
- data/out.txt +0 -0
- data/spec/data/additional_dataset_module.json +0 -18
- data/spec/data/blueprint_invalid.json +0 -38
- data/spec/data/m_n_model/blueprint.json +0 -76
- data/spec/data/model_module.json +0 -18
- data/spec/data/test_project_model_spec.json +0 -76
- data/spec/unit/models/attribute_column_spec.rb +0 -7
- data/spec/unit/models/project_blueprint_spec.rb +0 -239
- data/spec/unit/models/to_wire_spec.rb +0 -71
@@ -0,0 +1,46 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require_relative 'attribute_field'
|
4
|
+
|
5
|
+
module GoodData
|
6
|
+
module Model
|
7
|
+
class AnchorBlueprintField < AttributeBlueprintField
|
8
|
+
# Returns true if it is an anchor
|
9
|
+
#
|
10
|
+
# @return [Boolean] returns true
|
11
|
+
def anchor?
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
# Removes all the labels from the anchor. This is a typical operation that people want to perform
|
16
|
+
#
|
17
|
+
# @return [GoodData::Model::ProjectBlueprint] Returns changed blueprint
|
18
|
+
def strip!
|
19
|
+
dataset_blueprint.strip_anchor!
|
20
|
+
end
|
21
|
+
|
22
|
+
# Alias for strip!. Removes all the labels from the anchor. This is a typical operation that people want to perform
|
23
|
+
#
|
24
|
+
# @return [GoodData::Model::ProjectBlueprint] Returns changed blueprint
|
25
|
+
def remove!
|
26
|
+
strip!
|
27
|
+
end
|
28
|
+
|
29
|
+
# Returns labels for anchor or empty array if there are none
|
30
|
+
#
|
31
|
+
# @return [Array<GoodData::Model::LabelBlueprintField>] Returns list of labels
|
32
|
+
def labels
|
33
|
+
dataset_blueprint.labels_for_attribute(self)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Validates the field for presence of mandatory fields
|
37
|
+
#
|
38
|
+
# @return [Array<Hash>] Returns list of errors as hashes
|
39
|
+
def validate
|
40
|
+
validate_presence_of(:id).map do |e|
|
41
|
+
{ type: :error, message: "Field \"#{e}\" is not defined or empty for anchor \"#{id}\"" }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require_relative 'blueprint_field'
|
4
|
+
|
5
|
+
module GoodData
|
6
|
+
module Model
|
7
|
+
class AttributeBlueprintField < BlueprintField
|
8
|
+
# Returns list of labels on the attribute. There has to be always at least one attribute
|
9
|
+
#
|
10
|
+
# @return [Array] returns list of the errors represented by hash structures
|
11
|
+
def labels
|
12
|
+
@dataset_blueprint.labels_for_attribute(self)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Validates the fields in the attribute
|
16
|
+
#
|
17
|
+
# @return [Array] returns list of the errors represented by hash structures
|
18
|
+
def validate
|
19
|
+
validate_presence_of(:id).map do |e|
|
20
|
+
{ type: :error, message: "Field \"#{e}\" is not defined or empty for attribute \"#{id}\"" }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module GoodData
|
4
|
+
module Model
|
5
|
+
class BlueprintField
|
6
|
+
attr_reader :dataset_blueprint, :data
|
7
|
+
|
8
|
+
def id
|
9
|
+
@data[:id]
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(data, dataset)
|
13
|
+
@data = data.symbolize_keys
|
14
|
+
@data[:type] = @data[:type].to_sym
|
15
|
+
@dataset_blueprint = dataset
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns the md object in associated project or throws error if not present
|
19
|
+
#
|
20
|
+
# @return [GoodData::MdObject] md object that is represented in the blueprint
|
21
|
+
def in_project(project)
|
22
|
+
GoodData::MdObject[id, project: project, client: project.client]
|
23
|
+
end
|
24
|
+
|
25
|
+
def method_missing(method_sym, *arguments, &block)
|
26
|
+
if @data.key?(method_sym)
|
27
|
+
@data[method_sym]
|
28
|
+
else
|
29
|
+
super
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def respond_to?(method_sym, *arguments, &block)
|
34
|
+
if @data.key?(method_sym)
|
35
|
+
true
|
36
|
+
else
|
37
|
+
super
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def title
|
42
|
+
@data[:title] || @data[:id].titleize
|
43
|
+
end
|
44
|
+
|
45
|
+
# Validates the fields in the field
|
46
|
+
#
|
47
|
+
# @return [Array] returns list of the errors represented by hash structures
|
48
|
+
def validate
|
49
|
+
[]
|
50
|
+
end
|
51
|
+
|
52
|
+
def ==(other)
|
53
|
+
return false unless other.respond_to?(:data)
|
54
|
+
@data == other.data
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def validate_presence_of(*fields)
|
60
|
+
fields.reduce([]) do |a, e|
|
61
|
+
data.key?(e) && !data[e].blank? ? a : a + [e]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
File without changes
|
@@ -1,11 +1,11 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
3
|
require_relative 'schema_builder'
|
4
|
+
require_relative 'schema_blueprint'
|
4
5
|
|
5
6
|
module GoodData
|
6
7
|
module Model
|
7
|
-
class DatasetBlueprint
|
8
|
-
attr_accessor :data
|
8
|
+
class DatasetBlueprint < SchemaBlueprint
|
9
9
|
# Checks if a dataset has an anchor.
|
10
10
|
#
|
11
11
|
# @param dataset [Hash] Dataset blueprint
|
@@ -19,7 +19,7 @@ module GoodData
|
|
19
19
|
# @param dataset [Hash] Dataset blueprint
|
20
20
|
# @return [Hash] returns the anchor or nil
|
21
21
|
def self.anchor(dataset)
|
22
|
-
find_column_by_type(dataset, :anchor
|
22
|
+
find_column_by_type(dataset, :anchor)
|
23
23
|
end
|
24
24
|
|
25
25
|
# Returns attributes of a dataset
|
@@ -27,7 +27,15 @@ module GoodData
|
|
27
27
|
# @param dataset [Hash] Dataset blueprint
|
28
28
|
# @return [Array<Hash>] returns the attribute or an empty array
|
29
29
|
def self.attributes(dataset)
|
30
|
-
|
30
|
+
find_columns_by_type(dataset, :attribute, :all)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns attributes and anchor defined on a dataset
|
34
|
+
#
|
35
|
+
# @param dataset [Hash] Dataset blueprint
|
36
|
+
# @return [Array<Hash>] returns the attributes
|
37
|
+
def self.attributes_and_anchors(dataset)
|
38
|
+
[anchor(dataset)] + attributes(dataset)
|
31
39
|
end
|
32
40
|
|
33
41
|
# Returns all labels that is referenced by a label
|
@@ -35,7 +43,7 @@ module GoodData
|
|
35
43
|
# @param dataset [Hash] Dataset blueprint
|
36
44
|
# @return [Array<Hash>] returns the labels or an empty array
|
37
45
|
def self.attribute_for_label(dataset, label)
|
38
|
-
|
46
|
+
find_columns_by_type(dataset, :attribute, :anchor).find { |a| label[:reference] == a[:id] }
|
39
47
|
end
|
40
48
|
|
41
49
|
# Returns all the fields of a dataset. This means facts, attributes, references
|
@@ -43,7 +51,7 @@ module GoodData
|
|
43
51
|
# @param ds [Hash] Dataset blueprint
|
44
52
|
# @return [Boolean]
|
45
53
|
def self.columns(ds)
|
46
|
-
ds[:columns] || []
|
54
|
+
(ds.to_hash[:columns] || [])
|
47
55
|
end
|
48
56
|
singleton_class.send(:alias_method, :fields, :columns)
|
49
57
|
|
@@ -67,7 +75,7 @@ module GoodData
|
|
67
75
|
# @param dataset [Hash] Dataset blueprint
|
68
76
|
# @return [Array<Hash>] returns the attribute or an empty array
|
69
77
|
def self.date_facts(dataset)
|
70
|
-
find_column_by_type(dataset, :date_fact
|
78
|
+
find_column_by_type(dataset, :date_fact)
|
71
79
|
end
|
72
80
|
|
73
81
|
# Returns label that is marked as default for a particular attribtue.
|
@@ -78,7 +86,7 @@ module GoodData
|
|
78
86
|
# @return [Array<Hash>] returns the labels or an empty array
|
79
87
|
def self.default_label_for_attribute(dataset, attribute)
|
80
88
|
default_label = labels_for_attribute(dataset, attribute).find { |l| l[:default_label] == true }
|
81
|
-
default_label
|
89
|
+
default_label
|
82
90
|
end
|
83
91
|
|
84
92
|
# Returns facts of a dataset
|
@@ -86,7 +94,7 @@ module GoodData
|
|
86
94
|
# @param dataset [Hash] Dataset blueprint
|
87
95
|
# @return [Array<Hash>] returns the attribute or an empty array
|
88
96
|
def self.facts(dataset)
|
89
|
-
|
97
|
+
find_columns_by_type(dataset, :fact, :date_fact)
|
90
98
|
end
|
91
99
|
|
92
100
|
# Finds a specific column given a name
|
@@ -96,33 +104,32 @@ module GoodData
|
|
96
104
|
# @param all [Symbol] if :all is passed all mathching objects are returned
|
97
105
|
# Otherwise only the first one is
|
98
106
|
# @return [Array<Hash>] matching fields
|
99
|
-
def self.
|
107
|
+
def self.find_column_by_id(dataset, name, all = nil)
|
100
108
|
if all == :all
|
101
|
-
columns(dataset).select { |c| c[:
|
109
|
+
columns(dataset).select { |c| c[:id].to_s == name }
|
102
110
|
else
|
103
|
-
columns(dataset).find { |c| c[:
|
111
|
+
columns(dataset).find { |c| c[:id].to_s == name }
|
104
112
|
end
|
105
113
|
end
|
106
114
|
|
107
|
-
# Returns
|
108
|
-
# as an array if you need more than one type.
|
115
|
+
# Returns first field of a specified type.
|
109
116
|
#
|
110
|
-
# @param dataset [Hash] Dataset blueprint
|
111
|
-
# @param
|
112
|
-
# @param all [Symbol] if :all is passed
|
117
|
+
# @param dataset [Hash | GoodData::Model::ProjectBlueprint] Dataset blueprint
|
118
|
+
# @param types [String | Symbol | Array[Symbol] | Array[String]] Type or types you would like to get
|
113
119
|
# as third parameter it return all object otherwise it returns the first one
|
114
120
|
# @return [Array<Hash>] matching fields
|
115
|
-
def self.find_column_by_type(dataset,
|
116
|
-
types
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
121
|
+
def self.find_column_by_type(dataset, *types)
|
122
|
+
columns(dataset).find { |c| types.any? { |t| t.to_s == c[:type].to_s } }
|
123
|
+
end
|
124
|
+
|
125
|
+
# Returns all the fields of a specified type. You can specify more types
|
126
|
+
# if you need more than one type.
|
127
|
+
#
|
128
|
+
# @param dataset [Hash | GoodData::Model::ProjectBlueprint] Dataset blueprint
|
129
|
+
# @param types [String | Symbol | Array[Symmbol] | Array[String]] Type or types you would like to get
|
130
|
+
# @return [Array<Hash>] matching fields
|
131
|
+
def self.find_columns_by_type(dataset, *types)
|
132
|
+
columns(dataset).select { |c| types.any? { |t| t.to_s == c[:type].to_s } }
|
126
133
|
end
|
127
134
|
|
128
135
|
# Returns labels facts of a dataset
|
@@ -130,7 +137,7 @@ module GoodData
|
|
130
137
|
# @param dataset [Hash] Dataset blueprint
|
131
138
|
# @return [Array<Hash>] returns the label or an empty array
|
132
139
|
def self.labels(dataset)
|
133
|
-
|
140
|
+
find_columns_by_type(dataset, :label)
|
134
141
|
end
|
135
142
|
|
136
143
|
# Returns labels for a particular attribute
|
@@ -139,7 +146,7 @@ module GoodData
|
|
139
146
|
# @param attribute [Hash] Attribute
|
140
147
|
# @return [Array<Hash>] returns the labels or an empty array
|
141
148
|
def self.labels_for_attribute(dataset, attribute)
|
142
|
-
labels(dataset).select { |l| l[:reference] == attribute[:
|
149
|
+
labels(dataset).select { |l| l[:reference] == attribute[:id] }
|
143
150
|
end
|
144
151
|
|
145
152
|
# Returns references of a dataset
|
@@ -147,39 +154,43 @@ module GoodData
|
|
147
154
|
# @param dataset [Hash] Dataset blueprint
|
148
155
|
# @return [Array<Hash>] returns the references or an empty array
|
149
156
|
def self.references(dataset)
|
150
|
-
|
157
|
+
find_columns_by_type(dataset, :reference, :date)
|
151
158
|
end
|
152
159
|
|
153
160
|
# Returns anchor of a dataset
|
154
161
|
#
|
155
162
|
# @return [Hash] returns the anchor or nil
|
156
163
|
def anchor
|
157
|
-
find_column_by_type(:anchor
|
164
|
+
find_column_by_type(:anchor)
|
158
165
|
end
|
159
166
|
|
160
167
|
# Checks if a dataset has an anchor.
|
161
168
|
#
|
162
169
|
# @return [Boolean] returns true if dataset has an anchor
|
163
170
|
def anchor?
|
164
|
-
columns.any? { |c| c
|
171
|
+
columns.any? { |c| c.type == :anchor }
|
165
172
|
end
|
166
173
|
|
167
174
|
# Returns attributes of a dataset
|
168
175
|
#
|
169
176
|
# @return [Array<Hash>] returns the attribute or an empty array
|
170
|
-
def attributes
|
171
|
-
|
177
|
+
def attributes(id = :all)
|
178
|
+
return id if id.is_a?(AttributeBlueprintField)
|
179
|
+
ats = find_columns_by_type(:attribute)
|
180
|
+
id == :all ? ats : ats.find { |a| a.id == id }
|
172
181
|
end
|
173
182
|
|
183
|
+
# Returns attributes and anchor defined on a dataset
|
184
|
+
#
|
185
|
+
# @return [Array<GoodData::Model::DatasetBlueprint>] returns the attributes
|
174
186
|
def attributes_and_anchors
|
175
|
-
|
187
|
+
attributes + [anchor]
|
176
188
|
end
|
177
189
|
|
178
|
-
# Changes the dataset through a builder. You provide a block
|
179
|
-
# GoodData::Model::SchemaBuilder
|
190
|
+
# Changes the dataset through a builder. You provide a block and an istance of
|
191
|
+
# GoodData::Model::SchemaBuilder is passed in as the only parameter
|
180
192
|
#
|
181
|
-
# @
|
182
|
-
# @return [Array<Hash>] returns the labels or an empty array
|
193
|
+
# @return [GoodData::Model::SchemaBlueprint] returns changed dataset blueprint
|
183
194
|
def change(&block)
|
184
195
|
builder = SchemaBuilder.create_from_data(self)
|
185
196
|
block.call(builder)
|
@@ -187,11 +198,29 @@ module GoodData
|
|
187
198
|
self
|
188
199
|
end
|
189
200
|
|
190
|
-
# Returns all the fields of a dataset. This means facts, attributes, references
|
201
|
+
# Returns all the fields of a dataset. This means anchor, facts, attributes, references
|
202
|
+
# This method will cast them to correct types
|
191
203
|
#
|
192
204
|
# @return [Boolean]
|
193
205
|
def columns
|
194
|
-
DatasetBlueprint.columns(to_hash)
|
206
|
+
DatasetBlueprint.columns(to_hash).map do |c|
|
207
|
+
case c[:type].to_sym
|
208
|
+
when :anchor
|
209
|
+
GoodData::Model::AnchorBlueprintField.new(c, self)
|
210
|
+
when :attribute
|
211
|
+
GoodData::Model::AttributeBlueprintField.new(c, self)
|
212
|
+
when :fact
|
213
|
+
GoodData::Model::FactBlueprintField.new(c, self)
|
214
|
+
when :label
|
215
|
+
GoodData::Model::LabelBlueprintField.new(c, self)
|
216
|
+
when :reference
|
217
|
+
GoodData::Model::ReferenceBlueprintField.new(c, self)
|
218
|
+
when :date
|
219
|
+
GoodData::Model::ReferenceBlueprintField.new(c, self)
|
220
|
+
else
|
221
|
+
GoodData::Model::BlueprintField.new(c, self)
|
222
|
+
end
|
223
|
+
end
|
195
224
|
end
|
196
225
|
alias_method :fields, :columns
|
197
226
|
|
@@ -200,87 +229,99 @@ module GoodData
|
|
200
229
|
#
|
201
230
|
# @return [Boolean]
|
202
231
|
def count(project)
|
203
|
-
|
204
|
-
GoodData::Model.identifier_for(to_hash, anchor)
|
205
|
-
else
|
206
|
-
GoodData::Model.identifier_for(to_hash, type: :anchor_no_label)
|
207
|
-
end
|
208
|
-
attribute = project.attributes(id)
|
209
|
-
attribute.create_metric.execute
|
232
|
+
anchor.in_project(project).create_metric.execute
|
210
233
|
end
|
211
234
|
|
212
235
|
# Returns date facts of a dataset
|
213
236
|
#
|
214
237
|
# @return [Array<Hash>] returns the attribute or an empty array
|
215
238
|
def date_facts
|
216
|
-
|
239
|
+
find_columns_by_type(:date_fact)
|
217
240
|
end
|
218
241
|
|
219
242
|
# Duplicates the DatasetBlueprint. It is done as a deep duplicate
|
220
243
|
#
|
221
244
|
# @return [GoodData::Model::DatasetBlueprint] matching fields
|
222
245
|
def dup
|
223
|
-
DatasetBlueprint.new(data.deep_dup)
|
246
|
+
DatasetBlueprint.new(data.deep_dup, project_blueprint)
|
224
247
|
end
|
225
248
|
|
226
|
-
#
|
227
|
-
# It has to be exacty identical including the order of the columns
|
249
|
+
# Returns facts of a dataset
|
228
250
|
#
|
229
|
-
# @
|
230
|
-
|
231
|
-
|
232
|
-
|
251
|
+
# @return [Array<Hash>] returns the attribute or an empty array
|
252
|
+
def facts(id = :all)
|
253
|
+
return id if id.is_a?(FactBlueprintField)
|
254
|
+
fs = find_columns_by_type(:fact)
|
255
|
+
id == :all ? fs : fs.find { |a| a.id == id }
|
233
256
|
end
|
234
257
|
|
235
|
-
#
|
258
|
+
# Finds a specific column given a col
|
236
259
|
#
|
237
|
-
# @
|
238
|
-
|
239
|
-
|
260
|
+
# @param col [GoodData::Model::BlueprintField | Hash] Field
|
261
|
+
# @return [GoodData::Model::BlueprintField] matching fields
|
262
|
+
def find_column(col)
|
263
|
+
columns.find { |c| c == col }
|
240
264
|
end
|
241
265
|
|
242
|
-
# Finds a specific column given
|
266
|
+
# Finds a specific column given an id
|
243
267
|
#
|
244
|
-
# @param
|
268
|
+
# @param id [String] Id of a field
|
245
269
|
# @param all [Symbol] if :all is passed all mathching objects are returned
|
246
270
|
# Otherwise only the first one is
|
247
271
|
# @return [Array<Hash>] matching fields
|
248
|
-
def
|
249
|
-
|
272
|
+
def find_column_by_id(id)
|
273
|
+
id = id.respond_to?(:id) ? id.id : id
|
274
|
+
columns.find { |c| c.id == id }
|
250
275
|
end
|
251
276
|
|
252
|
-
# Returns
|
253
|
-
# as an array if you need more than one type.
|
277
|
+
# Returns first field of a specified type.
|
254
278
|
#
|
255
279
|
# @param type [String | Symbol | Array[Symmbol] | Array[String]] Type or types you would like to get
|
256
|
-
# @
|
257
|
-
|
258
|
-
|
259
|
-
def find_column_by_type(type, all = nil)
|
260
|
-
DatasetBlueprint.find_column_by_type(to_hash, type, all)
|
280
|
+
# @return [GoodData::Model::BlueprintField] returns matching field
|
281
|
+
def find_column_by_type(*types)
|
282
|
+
columns.find { |c| types.any? { |t| t.downcase.to_sym == c.type } }
|
261
283
|
end
|
262
284
|
|
263
|
-
# Returns
|
285
|
+
# Returns all the fields of a specified type. You can specify more types
|
286
|
+
# as an array if you need more than one type.
|
264
287
|
#
|
265
|
-
# @
|
266
|
-
|
267
|
-
|
288
|
+
# @param type [String | Symbol | Array[Symmbol] | Array[String]] Type or types you would like to get
|
289
|
+
# as third parameter it return all object otherwise it returns the first one
|
290
|
+
# @return [Array<GoodData::Model::BlueprintField>] matching fields
|
291
|
+
def find_columns_by_type(*types)
|
292
|
+
columns.select { |c| types.any? { |t| t.downcase.to_sym == c.type } }
|
268
293
|
end
|
269
294
|
|
270
295
|
# Creates a DatasetBlueprint
|
271
296
|
#
|
272
297
|
# @param dataset [Hash] Dataset blueprint
|
273
298
|
# @return [DatasetBlueprint] returns the labels or an empty array
|
274
|
-
def initialize(init_data)
|
275
|
-
|
299
|
+
def initialize(init_data, blueprint)
|
300
|
+
super
|
301
|
+
@data[:type] = @data.key?('type') ? @data['type'].to_sym : @data[:type]
|
302
|
+
@data[:columns].each do |c|
|
303
|
+
c[:type] = c[:type].to_sym
|
304
|
+
end
|
276
305
|
end
|
277
306
|
|
278
307
|
# Returns labels facts of a dataset
|
279
308
|
#
|
280
309
|
# @param dataset [Hash] Dataset blueprint
|
281
310
|
# @return [Array<Hash>] returns the label or an empty array
|
282
|
-
def labels
|
283
|
-
|
311
|
+
def labels(id = :all)
|
312
|
+
return id if id.is_a?(LabelBlueprintField)
|
313
|
+
labs = find_columns_by_type(:label)
|
314
|
+
id == :all ? labs : labs.find { |l| l.id == id }
|
315
|
+
end
|
316
|
+
|
317
|
+
def attribute_for_label(label)
|
318
|
+
l = labels(label)
|
319
|
+
attributes_and_anchors.find { |a| a.id == l.reference }
|
320
|
+
end
|
321
|
+
|
322
|
+
def labels_for_attribute(attribute)
|
323
|
+
a = attributes(attribute)
|
324
|
+
labels.select { |l| l.reference == a.id }
|
284
325
|
end
|
285
326
|
|
286
327
|
# Merges two schemas together. This method changes the blueprint
|
@@ -295,18 +336,26 @@ module GoodData
|
|
295
336
|
self
|
296
337
|
end
|
297
338
|
|
298
|
-
# Returns name of the dataset
|
299
|
-
#
|
300
|
-
# @return [String]
|
301
|
-
def name
|
302
|
-
data[:name]
|
303
|
-
end
|
304
|
-
|
305
339
|
# Returns references of a dataset
|
306
340
|
#
|
307
341
|
# @return [Array<Hash>] returns the references or an empty array
|
308
342
|
def references
|
309
|
-
|
343
|
+
find_columns_by_type(:reference, :date)
|
344
|
+
end
|
345
|
+
|
346
|
+
# Removes column from from the blueprint
|
347
|
+
#
|
348
|
+
# @param id [String] Id of the column to be removed
|
349
|
+
# @return [GoodData::Model::ProjectBlueprint] Returns changed blueprint
|
350
|
+
def remove_column!(id)
|
351
|
+
@project_blueprint.remove_column!(self, id)
|
352
|
+
end
|
353
|
+
|
354
|
+
# Removes all the labels from the anchor. This is a typical operation that people want to perform
|
355
|
+
#
|
356
|
+
# @return [GoodData::Model::ProjectBlueprint] Returns changed blueprint
|
357
|
+
def strip_anchor!
|
358
|
+
@project_blueprint.strip_anchor!(self)
|
310
359
|
end
|
311
360
|
|
312
361
|
# Method for suggest a couple of metrics that might get you started
|
@@ -323,43 +372,62 @@ module GoodData
|
|
323
372
|
end
|
324
373
|
end
|
325
374
|
|
326
|
-
|
327
|
-
|
375
|
+
def to_blueprint
|
376
|
+
GoodData::Model::ProjectBlueprint.new(datasets: [to_hash])
|
377
|
+
end
|
378
|
+
|
379
|
+
# Validate the blueprint return array of errors that are found.
|
328
380
|
#
|
329
|
-
# @return [
|
330
|
-
def
|
331
|
-
|
381
|
+
# @return [Array] array of errors
|
382
|
+
def validate
|
383
|
+
errors = []
|
384
|
+
errors.concat(validate_more_anchors)
|
385
|
+
errors.concat(validate_some_anchors)
|
386
|
+
errors.concat(validate_label_references)
|
387
|
+
errors.concat(validate_gd_data_type_errors)
|
388
|
+
errors.concat(fields.flat_map(&:validate))
|
389
|
+
errors.concat(validate_attribute_has_one_label)
|
390
|
+
errors
|
332
391
|
end
|
333
392
|
|
334
|
-
#
|
393
|
+
# Validate if the dataset has more than zero anchors defined.
|
335
394
|
#
|
336
|
-
# @return [
|
337
|
-
def
|
338
|
-
|
395
|
+
# @return [Array] array of errors
|
396
|
+
def validate_some_anchors
|
397
|
+
find_columns_by_type(:anchor).count == 0 ? [{ type: :no_anchor, dataset: id }] : []
|
339
398
|
end
|
340
399
|
|
341
|
-
# Validate the
|
400
|
+
# Validate if the dataset does not have more than one anchor defined.
|
342
401
|
#
|
343
402
|
# @return [Array] array of errors
|
344
|
-
def
|
345
|
-
|
346
|
-
validate_label_references.concat(more_than_one_anchor)
|
403
|
+
def validate_more_anchors
|
404
|
+
find_columns_by_type(:anchor).count > 1 ? [{ type: :more_than_on_anchor, dataset: id }] : []
|
347
405
|
end
|
348
406
|
|
349
|
-
# Validate the
|
407
|
+
# Validate if the attribute does have at least one label
|
350
408
|
#
|
351
|
-
# @return [
|
352
|
-
def
|
353
|
-
|
409
|
+
# @return [Array] array of errors
|
410
|
+
def validate_attribute_has_one_label
|
411
|
+
find_columns_by_type(:attribute)
|
412
|
+
.select { |a| a.labels.empty? }
|
413
|
+
.map { |e| { type: :attribute_without_label, attribute: e.id } }
|
354
414
|
end
|
355
415
|
|
356
416
|
# Validate the that any labels are pointing to the existing attribute. If not returns the list of errors. Currently just violating labels.
|
357
417
|
#
|
358
418
|
# @return [Array] array of errors
|
359
419
|
def validate_label_references
|
360
|
-
labels.select
|
361
|
-
|
362
|
-
|
420
|
+
labels.select { |r| r.attribute.nil? }
|
421
|
+
.map { |er_ref| { type: :wrong_label_reference, label: er_ref.id, wrong_reference: er_ref.data[:reference] } }
|
422
|
+
end
|
423
|
+
|
424
|
+
# Validate the the used gd_data_types are one of the allowed types. The data types are checked on lables and facts.
|
425
|
+
#
|
426
|
+
# @return [Array] array of errors
|
427
|
+
def validate_gd_data_type_errors
|
428
|
+
(labels + facts)
|
429
|
+
.select { |x| x.gd_data_type && !GoodData::Model.check_gd_data_type(x.gd_data_type) }
|
430
|
+
.map { |e| { :error => :invalid_gd_data_type_specified, :column => e.id } }
|
363
431
|
end
|
364
432
|
|
365
433
|
# Helper methods to decide wheather the dataset is considered wide.
|
@@ -370,15 +438,6 @@ module GoodData
|
|
370
438
|
def wide?
|
371
439
|
fields.count > 32
|
372
440
|
end
|
373
|
-
|
374
|
-
# Compares two blueprints. This is done by comapring the hash represenatation.
|
375
|
-
# It has to be exacty identical including the order of the columns
|
376
|
-
#
|
377
|
-
# @param name [GoodData::Model::DatasetBlueprint] Name of a field
|
378
|
-
# @return [Boolean] matching fields
|
379
|
-
def ==(other)
|
380
|
-
to_hash == other.to_hash
|
381
|
-
end
|
382
441
|
end
|
383
442
|
end
|
384
443
|
end
|