Class: GoodData::Model::ProjectBlueprint

Inherits:
Object
  • Object
show all
Defined in:
lib/gooddata/models/blueprint/project_blueprint.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(init_data) ⇒ ProjectBlueprint

Constructor

definition. If passed a hash it is used as data for new instance. If there is a ProjectBlueprint passed it is duplicated and a new instance is created.

Parameters:



430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 430

def initialize(init_data)
  some_data = if init_data.respond_to?(:project_blueprint?) && init_data.project_blueprint?
                init_data.to_hash
              elsif init_data.respond_to?(:to_blueprint)
                init_data.to_blueprint.to_hash
              else
                init_data
              end
  @data = GoodData::Helpers.symbolize_keys(GoodData::Helpers.deep_dup(some_data))
  (@data[:datasets] || []).each do |d|
    d[:type] = d[:type].to_sym
    d[:columns].each do |c|
      c[:type] = c[:type].to_sym
    end
  end
  (@data[:date_dimensions] || []).each do |d|
    d[:type] = d[:type].to_sym
  end
  @data[:include_ca] = true if @data[:include_ca].nil?
end

Instance Attribute Details

#dataObject

Returns the value of attribute data.



8
9
10
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 8

def data
  @data
end

Class Method Details

.build(title, &block) ⇒ Object



28
29
30
31
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 28

def build(title, &block)
  pb = ProjectBuilder.create(title, &block)
  pb.to_blueprint
end

.dataset?(project, name, options = {}) ⇒ Boolean

Returns true if a dataset contains a particular dataset false otherwise

Parameters:

Options Hash (options):

  • :include_date_dimensions (Boolean)

    Specifies whether to include date dimensions

  • :dd (Boolean)

    Specifies whether to include date dimensions

Returns:

  • (Boolean)


123
124
125
126
127
128
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 123

def self.dataset?(project, name, options = {})
  find_dataset(project, name, options)
  true
rescue StandardError
  false
end

.datasets(project_blueprint, options = {}) ⇒ Array<Hash>

Returns datasets of blueprint. Those can be optionally including date dimensions

Parameters:

Options Hash (options):

  • :include_date_dimensions (Boolean)

    Specifies whether to include date dimensions

  • :dd (Boolean)

    Specifies whether to include date dimensions

Returns:

  • (Array<Hash>)


90
91
92
93
94
95
96
97
98
99
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 90

def self.datasets(project_blueprint, options = {})
  project_blueprint = project_blueprint.to_hash
  include_date_dimensions = options[:include_date_dimensions] || options[:dd]
  ds = (project_blueprint.to_hash[:datasets] || [])
  if include_date_dimensions
    ds + date_dimensions(project_blueprint)
  else
    ds
  end
end

.date_dimension?(project, name) ⇒ Boolean

Returns true if a date dimension of a given name exists in a bleuprint

Parameters:

Returns:

  • (Boolean)


161
162
163
164
165
166
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 161

def self.date_dimension?(project, name)
  find_date_dimension(project, name)
  true
rescue StandardError
  false
end

.date_dimensions(project_blueprint) ⇒ Array<Hash>

Returns list of date dimensions

Parameters:

Returns:

  • (Array<Hash>)


151
152
153
154
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 151

def self.date_dimensions(project_blueprint)
  project_blueprint.to_hash[:date_dimensions] || []
  # dims.map {|dim| DateDimension.new(dim, project_blueprint)}
end

.fields(project) ⇒ Array<Hash>

Returns fields from all datasets

Parameters:

Returns:

  • (Array<Hash>)


184
185
186
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 184

def self.fields(project)
  datasets(project).mapcat { |d| DatasetBlueprint.fields(d) }
end

.find_dataset(project_blueprint, obj, options = {}) ⇒ GoodData::Model::DatasetBlueprint

Returns dataset specified. It can check even for a date dimension

Parameters:

Options Hash (options):

  • :include_date_dimensions (Boolean)

    Specifies whether to include date dimensions

  • :dd (Boolean)

    Specifies whether to include date dimensions

Returns:



138
139
140
141
142
143
144
145
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 138

def self.find_dataset(project_blueprint, obj, options = {})
  return obj.to_hash if DatasetBlueprint.dataset_blueprint?(obj)
  all_datasets = datasets(project_blueprint, options)
  name = obj.respond_to?(:to_hash) ? obj.to_hash[:id] : obj
  ds = all_datasets.find { |d| d[:id] == name }
  fail "Dataset #{name} could not be found" if ds.nil?
  ds
end

.find_date_dimension(project, name) ⇒ Hash

Finds a date dimension of a given name in a bleuprint. If a dataset is not found it throws an exeception

Parameters:

Returns:

  • (Hash)


174
175
176
177
178
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 174

def self.find_date_dimension(project, name)
  ds = date_dimensions(project).find { |d| d[:id] == name }
  fail "Date dimension #{name} could not be found" unless ds
  ds
end

.from_json(spec) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 16

def from_json(spec)
  if spec.is_a?(String)
    if File.file?(spec)
      ProjectBlueprint.new(MultiJson.load(File.read(spec), :symbolize_keys => true))
    else
      ProjectBlueprint.new(MultiJson.load(spec, :symbolize_keys => true))
    end
  else
    ProjectBlueprint.new(spec)
  end
end

.remove_column!(project, dataset, column_id) ⇒ Hash | GoodData::Model::ProjectBlueprint

Removes column from from the blueprint

Parameters:

Returns:



40
41
42
43
44
45
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 40

def self.remove_column!(project, dataset, column_id)
  dataset = find_dataset(project, dataset)
  col = dataset[:columns].find { |c| c[:id] == column_id }
  dataset[:columns].delete(col)
  project
end

.remove_dataset(project, dataset_id, options = {}) ⇒ Hash

Removes dataset from blueprint. Dataset can be given as either a name or a DatasetBlueprint or a Hash representation.

Parameters:

Options Hash (options):

  • :include_date_dimensions (Boolean)

    Specifies whether to include date dimensions

  • :dd (Boolean)

    Specifies whether to include date dimensions

Returns:

  • (Hash)

    new project with removed dataset



56
57
58
59
60
61
62
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 56

def self.remove_dataset(project, dataset_id, options = {})
  dataset = dataset_id.is_a?(String) ? find_dataset(project, dataset_id, options) : dataset_name
  index = project[:datasets].index(dataset)
  dupped_project = GoodData::Helpers.deep_dup(project)
  dupped_project[:datasets].delete_at(index)
  dupped_project
end

.remove_dataset!(project, dataset_id, options = {}) ⇒ Hash

Removes dataset from blueprint. Dataset can be given as either a name or a DatasetBlueprint or a Hash representation. This version mutates the dataset in place

Parameters:

Options Hash (options):

  • :include_date_dimensions (Boolean)

    Specifies whether to include date dimensions

  • :dd (Boolean)

    Specifies whether to include date dimensions

Returns:

  • (Hash)

    project with removed dataset



74
75
76
77
78
79
80
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 74

def self.remove_dataset!(project, dataset_id, options = {})
  project = project.to_hash
  dataset = dataset_id.is_a?(String) ? find_dataset(project, dataset_id, options) : dataset_id
  index = project[:datasets].index(dataset)
  project[:datasets].delete_at(index)
  project
end

Instance Method Details

#==(other) ⇒ Object



778
779
780
781
782
783
784
785
786
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 778

def ==(other)
  # to_hash == other.to_hash
  return false unless id == other.id
  return false unless title == other.title
  left = to_hash[:datasets].map { |d| d[:columns].to_set }.to_set
  right = other.to_hash[:datasets].map { |d| d[:columns].to_set }.to_set
  return false unless left == right
  true
end

#add_column!(dataset, column_definition) ⇒ GoodData::Model::ProjectBlueprint

Adds column to particular dataset in the blueprint

Parameters:

Returns:



248
249
250
251
252
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 248

def add_column!(dataset, column_definition)
  ds = ProjectBlueprint.find_dataset(to_hash, dataset)
  ds[:columns] << column_definition
  self
end

#add_dataset!(a_dataset, index = nil) ⇒ GoodData::Model::ProjectBlueprint

Adds dataset to the blueprint

Parameters:

  • a_dataset (Hash | GoodData::Model::SchemaBlueprint)

    dataset to be added

  • index (Integer) (defaults to: nil)

    number specifying at which position the new dataset should be added. If not specified it is added at the end

Returns:



224
225
226
227
228
229
230
231
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 224

def add_dataset!(a_dataset, index = nil)
  if index.nil? || index > datasets.length
    data[:datasets] << a_dataset.to_hash
  else
    data[:datasets].insert(index, a_dataset.to_hash)
  end
  self
end

#add_date_dimension!(a_dimension, index = nil) ⇒ Object



233
234
235
236
237
238
239
240
241
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 233

def add_date_dimension!(a_dimension, index = nil)
  dim = a_dimension.to_hash
  if index.nil? || index > date_dimensions.length
    data[:date_dimensions] << dim
  else
    data[:date_dimensions].insert(index, dim)
  end
  self
end

#attributesArray<Hash>

Returns list of attributes from all the datasets in a blueprint

Returns:

  • (Array<Hash>)


323
324
325
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 323

def attributes
  datasets.reduce([]) { |acc, elem| acc.concat(elem.attributes) }
end

#attributes_and_anchorsArray<Hash>

Returns list of attributes and anchors from all the datasets in a blueprint

Returns:

  • (Array<Hash>)


330
331
332
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 330

def attributes_and_anchors
  datasets.mapcat(&:attributes_and_anchors)
end

#change(&block) ⇒ GoodData::Model::ProjectBlueprint

Changes the dataset through a builder. You provide a block and an istance of GoodData::Model::ProjectBuilder is passed in as the only parameter

Returns:



192
193
194
195
196
197
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 192

def change(&block)
  builder = ProjectBuilder.create_from_data(self)
  block.call(builder)
  @data = builder.to_hash
  self
end

#dataset?(name, options = {}) ⇒ Boolean

Returns true if a dataset contains a particular dataset false otherwise

Parameters:

Options Hash (options):

  • :include_date_dimensions (Boolean)

    Specifies whether to include date dimensions

  • :dd (Boolean)

    Specifies whether to include date dimensions

Returns:

  • (Boolean)


355
356
357
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 355

def dataset?(name, options = {})
  ProjectBlueprint.dataset?(to_hash, name, options)
end

#dataset_to_manifest(dataset, mode = 'FULL') ⇒ Array<Hash>

Returns SLI manifest for one dataset. This is used by our API to allow loading data. The method is on project blueprint because you need acces to whole project to be able to generate references

Parameters:

Returns:

  • (Array<Hash>)

    a title



366
367
368
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 366

def dataset_to_manifest(dataset, mode = 'FULL')
  ToManifest.dataset_to_manifest(self, dataset, mode)
end

#datasets(id = :all, options = {}) ⇒ Array<GoodData::Model::DatasetBlueprint>

Returns datasets of blueprint. Those can be optionally including date dimensions

Parameters:

  • options (Hash) (defaults to: {})

    options

Options Hash (options):

  • :include_date_dimensions (Boolean)

    Specifies whether to include date dimensions

  • :dd (Boolean)

    Specifies whether to include date dimensions

Returns:



206
207
208
209
210
211
212
213
214
215
216
217
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 206

def datasets(id = :all, options = {})
  id = id.respond_to?(:id) ? id.id : id
  dss = ProjectBlueprint.datasets(self, options).map do |d|
    case d[:type]
    when :date_dimension
      DateDimension.new(d, self)
    when :dataset
      DatasetBlueprint.new(d, self)
    end
  end
  id == :all ? dss : dss.find { |d| d.id == id }
end

#date_dimensionsArray<Hash>

Returns list of date dimensions

Returns:

  • (Array<Hash>)


344
345
346
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 344

def date_dimensions
  ProjectBlueprint.date_dimensions(self).map { |dd| GoodData::Model::DateDimension.new(dd, self) }
end

#dupGoodData::Model::DatasetBlueprint

Duplicated blueprint

Parameters:

Returns:



374
375
376
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 374

def dup
  ProjectBlueprint.new(GoodData::Helpers.deep_dup(data))
end

#duplicate!(col, from_dataset, to_dataset) ⇒ Object



297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 297

def duplicate!(col, from_dataset, to_dataset)
  from_dataset = find_dataset(from_dataset)
  to_dataset = find_dataset(to_dataset)
  column = if col.is_a?(String)
             from_dataset.find_column_by_id(col)
           else
             from_dataset.find_column(col)
           end
  fail "Column #{col} cannot be found in dataset #{from_dataset.id}" unless column
  stuff = case column.type
          when :attribute
            [column] + column.labels
          when :fact
            [column]
          when :reference
            [column]
          else
            fail 'Duplicate does not support moving #{col.type} type of field'
          end
  stuff.map(&:data).each { |c| add_column!(to_dataset, c) }
  self
end

#factsArray<Hash>

Returns list of facts from all the datasets in a blueprint

Returns:

  • (Array<Hash>)


381
382
383
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 381

def facts
  datasets.mapcat(&:facts)
end

#fieldsArray<Hash>

Returns list of fields from all the datasets in a blueprint

Returns:

  • (Array<Hash>)


388
389
390
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 388

def fields
  datasets.flat_map(&:fields)
end

#find_dataset(name, options = {}) ⇒ GoodData::Model::DatasetBlueprint

Returns dataset specified. It can check even for a date dimension

Parameters:

Options Hash (options):

  • :include_date_dimensions (Boolean)

    Specifies whether to include date dimensions

  • :dd (Boolean)

    Specifies whether to include date dimensions

Returns:



399
400
401
402
403
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 399

def find_dataset(name, options = {})
  ds = datasets(name, options)
  fail "Dataset \"#{name}\" could not be found" unless ds
  ds
end

#find_dataset_by_title(title) ⇒ Array<Hash>

Returns a dataset of a given name. If a dataset is not found it throws an exeception

Parameters:

  • project (String)

    Dataset title

Returns:

  • (Array<Hash>)


409
410
411
412
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 409

def find_dataset_by_title(title)
  ds = ProjectBlueprint.find_dataset_by_title(to_hash, title)
  DatasetBlueprint.new(ds)
end

#find_star_centersArray<Hash>

Return list of datasets that are centers of the stars in datamart. This means these datasets are not referenced by anybody else In a good blueprint design these should be fact tables

Returns:

  • (Array<Hash>)


419
420
421
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 419

def find_star_centers
  datasets.select { |d| d.referenced_by.empty? }
end

#idObject



451
452
453
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 451

def id
  data[:id]
end

#labelsArray<Hash>

Returns list of labels from all the datasets in a blueprint

Returns:

  • (Array<Hash>)


458
459
460
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 458

def labels
  datasets.mapcat(&:labels)
end

#lint(full = false) ⇒ Array<Hash>

Experimental but a basis for automatic check of health of a project

Parameters:

Returns:

  • (Array<Hash>)


466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 466

def lint(full = false)
  errors = []
  find_star_centers.each do |dataset|
    next unless dataset.anchor?
    errors << {
      type: :anchor_on_fact_dataset,
      dataset_name: dataset.name,
      anchor_name: dataset.anchor[:name]
    }
  end
  date_facts = datasets.mapcat(&:date_facts)
  date_facts.each do |date_fact|
    errors << {
      type: :date_fact,
      date_fact: date_fact[:name]
    }
  end

  unique_titles = fields.map { |f| Model.title(f) }.uniq
  (fields.map { |f| Model.title(f) } - unique_titles).each do |duplicate_title|
    errors << {
      type: :duplicate_title,
      title: duplicate_title
    }
  end

  datasets.select(&:wide?).each do |wide_dataset|
    errors << {
      type: :wide_dataset,
      dataset: wide_dataset.name
    }
  end

  if full
    # GoodData::Attributes.all(:full => true).select { |attr| attr.used_by}
  end
  errors
end

#merge(a_blueprint) ⇒ GoodData::Model::ProjectBlueprint

Merging two blueprints. A new blueprint is created. The self one is nto mutated

Parameters:

Returns:



655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 655

def merge(a_blueprint)
  temp_blueprint = dup
  return temp_blueprint unless a_blueprint
  a_blueprint.datasets.each do |dataset|
    if temp_blueprint.dataset?(dataset.id)
      local_dataset = temp_blueprint.find_dataset(dataset.id)
      index = temp_blueprint.datasets.index(local_dataset)
      local_dataset.merge!(dataset)
      temp_blueprint.remove_dataset!(local_dataset.id)
      temp_blueprint.add_dataset!(local_dataset, index)
    else
      temp_blueprint.add_dataset!(dataset.dup)
    end
  end
  a_blueprint.date_dimensions.each do |dd|
    if temp_blueprint.dataset?(dd.id, dd: true)
      local_dim = temp_blueprint.data[:date_dimensions].find { |d| d[:id] == dd.id }
      local_dim[:urn] = dd.urn
    else
      temp_blueprint.add_date_dimension!(dd.dup)
    end
  end
  temp_blueprint
end

#merge!(a_blueprint) ⇒ GoodData::Model::ProjectBlueprint

Merging two blueprints. The self blueprint is changed in place

Parameters:

Returns:



509
510
511
512
513
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 509

def merge!(a_blueprint)
  temp_blueprint = merge(a_blueprint)
  @data = temp_blueprint.data
  self
end

#move!(col, from_dataset, to_dataset) ⇒ GoodData::Model::ProjectBlueprint

Moves column to particular dataset in the blueprint. It currently supports moving of attributes and facts only. The rest of the fields probably does not make sense In case of attribute it moves its labels as well.

Parameters:

Returns:



272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 272

def move!(col, from_dataset, to_dataset)
  from_dataset = find_dataset(from_dataset)
  to_dataset = find_dataset(to_dataset)
  column = if col.is_a?(String)
             from_dataset.find_column_by_id(col)
           else
             from_dataset.find_column(col)
           end
  fail "Column #{col} cannot be found in dataset #{from_dataset.id}" unless column
  stuff = case column.type
          when :attribute
            [column] + column.labels
          when :fact
            [column]
          when :reference
            [column]
          else
            fail 'Duplicate does not support moving #{col.type} type of field'
          end
  stuff = stuff.map(&:data)
  stuff.each { |c| remove_column!(from_dataset, c[:id]) }
  stuff.each { |c| add_column!(to_dataset, c) }
  self
end

#project_blueprint?Boolean

Is this a project blueprint?

Returns:

  • (Boolean)

    if it is



337
338
339
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 337

def project_blueprint?
  true
end

#refactor_split_df(dataset) ⇒ Object



616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 616

def refactor_split_df(dataset)
  fail ValidationError unless valid?
  o = find_dataset(dataset)
  new_dataset = GoodData::Model::DatasetBlueprint.new({ type: :dataset, id: "#{o.id}_dim", columns: [] }, self)
  new_dataset.change do |d|
    d.add_anchor('vymysli_id')
    d.add_label('label.vymysli_id', reference: 'vymysli_id')
  end
  nb = merge(new_dataset.to_blueprint)
  o.attributes.each { |a| nb.move!(a, o, new_dataset.id) }
  old = nb.find_dataset(dataset)
  old.attributes.each do |a|
    remove_column!(old, a)
  end
  old.change do |d|
    d.add_reference(new_dataset.id)
  end
  nb
end

#refactor_split_facts(dataset, column_names, new_dataset_title) ⇒ Object



636
637
638
639
640
641
642
643
644
645
646
647
648
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 636

def refactor_split_facts(dataset, column_names, new_dataset_title)
  fail ValidationError unless valid?
  change do |p|
    p.add_dataset(new_dataset_title) do |d|
      d.add_anchor("#{new_dataset_title}.id")
    end
  end
  dataset_to_refactor = find_dataset(dataset)
  new_dataset = find_dataset(new_dataset_title)
  column_names.each { |c| move!(c, dataset_to_refactor, new_dataset) }
  dataset_to_refactor.references.each { |ref| duplicate!(ref, dataset_to_refactor, new_dataset) }
  self
end

#referenced_by(dataset) ⇒ Array<Hash>

Returns list of datasets which are referenced by given dataset. This can be optionally switched to return even date dimensions

Parameters:

Returns:

  • (Array<Hash>)


520
521
522
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 520

def referenced_by(dataset)
  find_dataset(dataset, include_date_dimensions: true).referencing
end

#referencing(dataset) ⇒ Object



524
525
526
527
528
529
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 524

def referencing(dataset)
  datasets(:all, include_date_dimensions: true)
    .flat_map(&:references)
    .select { |r| r.dataset == dataset }
    .map(&:dataset_blueprint)
end

#remove_column!(dataset, id) ⇒ GoodData::Model::ProjectBlueprint

Removes column to particular dataset in the blueprint

Parameters:

Returns:



259
260
261
262
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 259

def remove_column!(dataset, id)
  ProjectBlueprint.remove_column!(to_hash, dataset, id)
  self
end

#remove_dataset(dataset_name, options = {}) ⇒ Hash

Removes dataset from blueprint. Dataset can be given as either a name or a DatasetBlueprint or a Hash representation.

Parameters:

Options Hash (options):

  • :include_date_dimensions (Boolean)

    Specifies whether to include date dimensions

  • :dd (Boolean)

    Specifies whether to include date dimensions

Returns:

  • (Hash)

    project with removed dataset



539
540
541
542
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 539

def remove_dataset(dataset_name, options = {})
  ProjectBlueprint.remove_dataset(to_hash, dataset_name, options)
  self
end

#remove_dataset!(dataset_id, options = {}) ⇒ Hash

Removes dataset from blueprint. Dataset can be given as either a name or a DatasetBlueprint or a Hash representation.

Parameters:

Options Hash (options):

  • :include_date_dimensions (Boolean)

    Specifies whether to include date dimensions

  • :dd (Boolean)

    Specifies whether to include date dimensions

Returns:

  • (Hash)

    project with removed dataset



552
553
554
555
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 552

def remove_dataset!(dataset_id, options = {})
  ProjectBlueprint.remove_dataset!(to_hash, dataset_id, options)
  self
end

#store_to_file(filename) ⇒ Object

Helper for storing the project blueprint into a file as JSON.

Parameters:

  • filename (String)

    Name of the file where the blueprint should be stored



683
684
685
686
687
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 683

def store_to_file(filename)
  File.open(filename, 'w') do |f|
    f << JSON.pretty_generate(to_hash)
  end
end

#strip_anchor!(dataset) ⇒ GoodData::Model::ProjectBlueprint

Removes all the labels from the anchor. This is a typical operation that people want to perform on fact tables

Returns:



561
562
563
564
565
566
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 561

def strip_anchor!(dataset)
  from_dataset = find_dataset(dataset)
  stuff = dataset.anchor.labels.map(&:data)
  stuff.each { |column| remove_column!(from_dataset, column[:id]) }
  self
end

#suggest_metricsArray<Hash> Also known as: suggest_measures

Returns some metrics that might get you started. They are just simple reports. Currently it is implemented by getting facts from star centers and randomly picking attributes form referenced datasets.

Returns:

  • (Array<Hash>)


604
605
606
607
608
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 604

def suggest_metrics
  stars = find_star_centers
  metrics = stars.map(&:suggest_metrics)
  stars.zip(metrics)
end

#suggest_reports(options = {}) ⇒ Array<Hash>

Returns some reports that might get you started. They are just simple reports. Currently it is implemented by getting facts from star centers and randomly picking attributes form referenced datasets.

Returns:

  • (Array<Hash>)


573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 573

def suggest_reports(options = {})
  strategy = options[:strategy] || :stupid
  case strategy
  when :stupid
    reports = suggest_metrics.reduce([]) do |a, e|
      star, metrics = e
      metrics.each(&:save)
      reports_stubs = metrics.map do |m|
        breaks = broken_by(star).map { |ds, a_m| ds.identifier_for(a_m) }
        [breaks, m]
      end
      a.concat(reports_stubs)
    end
    reports.reduce([]) do |a, e|
      attrs, metric = e

      attrs.each do |attr|
        a << GoodData::Report.create(:title => 'Fantastic report',
                                     :top => [attr],
                                     :left => metric)
      end
      a
    end
  end
end

#swap_date_dimension!(what, for_what) ⇒ GoodData::Model::ProjectBlueprint

Returns blueprint with all references to one date dimensions changed to reference to the other. Changes the Blueprint in place.

Parameters:

Returns:



106
107
108
109
110
111
112
113
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 106

def swap_date_dimension!(what, for_what)
  what_id = what.respond_to?(:id) ? what.id : what
  for_what_id = what.respond_to?(:id) ? for_what.id : for_what

  fields = to_hash[:datasets].flat_map { |x| x[:columns] }.select { |x| x[:type] == :date }.select { |i| i[:dataset] == what_id }
  fields.each { |f| f[:dataset] = for_what_id }
  self
end

#titleString

Returns title of a dataset. If not present it is generated from the name

Returns:

  • (String)

    a title



692
693
694
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 692

def title
  Model.title(to_hash) if to_hash[:title]
end

#title=(a_title) ⇒ String

Returns title of a dataset. If not present it is generated from the name

Returns:

  • (String)

    a title



699
700
701
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 699

def title=(a_title)
  @data[:title] = a_title
end

#to_blueprintObject



612
613
614
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 612

def to_blueprint
  self
end

#to_hashHash

Returns hash representation of blueprint

Returns:

  • (Hash)

    a title



724
725
726
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 724

def to_hash
  @data
end

#to_manifestArray<Hash>

Returns SLI manifest representation. This is used by our API to allow loading data

Returns:

  • (Array<Hash>)

    a title



716
717
718
719
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 716

def to_manifest
  validate
  ToManifest.to_manifest(to_hash)
end

#to_wireHash

Returns Wire representation. This is used by our API to generate and change projects

Returns:

  • (Hash)

    a title



707
708
709
710
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 707

def to_wire
  validate
  ToWire.to_wire(data)
end

#valid?Boolean

Validate the blueprint and all its datasets and return true if model is valid. False otherwise.

Returns:

  • (Boolean)

    is model valid?



774
775
776
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 774

def valid?
  validate.empty?
end

#validateArray

Validate the blueprint and all its datasets return array of errors that are found.

Returns:

  • (Array)

    array of errors



760
761
762
763
764
765
766
767
768
769
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 760

def validate
  errors = []
  errors.concat validate_identifiers
  errors.concat validate_references
  errors.concat datasets.reduce([]) { |acc, elem| acc.concat(elem.validate) }
  errors.concat datasets.reduce([]) { |acc, elem| acc.concat(elem.validate_gd_data_type_errors) }
  errors
rescue StandardError
  raise GoodData::ValidationError
end

#validate_identifiersArray

Validate the blueprint in particular if all ids must be unique and valid.

Returns:

  • (Array)

    array of errors



746
747
748
749
750
751
752
753
754
755
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 746

def validate_identifiers
  ids = datasets.flat_map { |dataset| dataset.columns.map(&:id) }.compact

  duplicated_ids = ids.select { |id| ids.count(id) > 1 }.uniq
  errors = duplicated_ids.map { |id| { type: :duplicated_identifier, id: id } } || []

  ids.uniq.each { |id| errors << { type: :invalid_identifier, id: id } if id !~ /^[\w.]+$/ }

  errors
end

#validate_referencesArray

Validate the blueprint in particular if all references reference existing datasets and valid fields inside them.

Returns:

  • (Array)

    array of errors



731
732
733
734
735
736
737
738
739
740
741
# File 'lib/gooddata/models/blueprint/project_blueprint.rb', line 731

def validate_references
  stuff = datasets(:all, include_date_dimensions: true).flat_map(&:references).select do |ref|
    begin
      ref.dataset
      false
    rescue RuntimeError
      true
    end
  end
  stuff.map { |r| { type: :bad_reference, reference: r.data, referencing_dataset: r.data[:dataset] } }
end