gooddata 0.6.18 → 0.6.19
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/.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
|