gooddata 0.6.4 → 0.6.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (116) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.markdown +4 -0
  3. data/README.md +1 -0
  4. data/lib/gooddata/cli/commands/project_cmd.rb +2 -7
  5. data/lib/gooddata/client.rb +0 -2
  6. data/lib/gooddata/commands/project.rb +10 -0
  7. data/lib/gooddata/core/rest.rb +12 -2
  8. data/lib/gooddata/exceptions/attr_element_not_found.rb +12 -0
  9. data/lib/gooddata/extensions/enumerable.rb +12 -0
  10. data/lib/gooddata/helpers/global_helpers.rb +20 -0
  11. data/lib/gooddata/mixins/author.rb +16 -0
  12. data/lib/gooddata/mixins/content_getter.rb +11 -0
  13. data/lib/gooddata/mixins/content_property_reader.rb +13 -0
  14. data/lib/gooddata/mixins/content_property_writer.rb +13 -0
  15. data/lib/gooddata/mixins/contributor.rb +16 -0
  16. data/lib/gooddata/mixins/data_getter.rb +11 -0
  17. data/lib/gooddata/mixins/data_property_reader.rb +13 -0
  18. data/lib/gooddata/mixins/data_property_writer.rb +13 -0
  19. data/lib/gooddata/mixins/is_attribute.rb +13 -0
  20. data/lib/gooddata/mixins/is_fact.rb +13 -0
  21. data/lib/gooddata/mixins/is_label.rb +15 -0
  22. data/lib/gooddata/mixins/links.rb +11 -0
  23. data/lib/gooddata/mixins/md_finders.rb +36 -0
  24. data/lib/gooddata/mixins/md_id_to_uri.rb +29 -0
  25. data/lib/gooddata/mixins/md_json.rb +11 -0
  26. data/lib/gooddata/mixins/md_object_id.rb +11 -0
  27. data/lib/gooddata/mixins/md_object_indexer.rb +36 -0
  28. data/lib/gooddata/mixins/md_object_query.rb +83 -0
  29. data/lib/gooddata/mixins/md_relations.rb +39 -0
  30. data/lib/gooddata/mixins/meta_getter.rb +11 -0
  31. data/lib/gooddata/mixins/meta_property_reader.rb +13 -0
  32. data/lib/gooddata/mixins/meta_property_writer.rb +13 -0
  33. data/lib/gooddata/mixins/mixins.rb +15 -0
  34. data/lib/gooddata/mixins/not_attribute.rb +13 -0
  35. data/lib/gooddata/mixins/not_exportable.rb +11 -0
  36. data/lib/gooddata/mixins/not_fact.rb +13 -0
  37. data/lib/gooddata/mixins/not_label.rb +15 -0
  38. data/lib/gooddata/mixins/not_metric.rb +13 -0
  39. data/lib/gooddata/mixins/obj_id.rb +11 -0
  40. data/lib/gooddata/mixins/rest_getters.rb +13 -0
  41. data/lib/gooddata/mixins/rest_resource.rb +19 -0
  42. data/lib/gooddata/mixins/root_key_getter.rb +11 -0
  43. data/lib/gooddata/mixins/root_key_setter.rb +11 -0
  44. data/lib/gooddata/mixins/timestamps.rb +15 -0
  45. data/lib/gooddata/models/from_wire.rb +153 -0
  46. data/lib/gooddata/models/metadata.rb +28 -230
  47. data/lib/gooddata/models/metadata/attribute.rb +4 -6
  48. data/lib/gooddata/models/metadata/fact.rb +4 -6
  49. data/lib/gooddata/models/metadata/{display_form.rb → label.rb} +17 -11
  50. data/lib/gooddata/models/metadata/metric.rb +1 -1
  51. data/lib/gooddata/models/metadata/report_definition.rb +2 -2
  52. data/lib/gooddata/models/model.rb +55 -23
  53. data/lib/gooddata/models/models.rb +0 -2
  54. data/lib/gooddata/models/module_constants.rb +0 -2
  55. data/lib/gooddata/models/process.rb +1 -1
  56. data/lib/gooddata/models/project.rb +117 -76
  57. data/lib/gooddata/models/project_blueprint.rb +322 -42
  58. data/lib/gooddata/models/project_creator.rb +5 -4
  59. data/lib/gooddata/models/project_role.rb +20 -55
  60. data/lib/gooddata/models/schema_blueprint.rb +287 -84
  61. data/lib/gooddata/models/schema_builder.rb +0 -4
  62. data/lib/gooddata/models/to_manifest.rb +160 -0
  63. data/lib/gooddata/models/to_wire.rb +150 -0
  64. data/lib/gooddata/version.rb +1 -1
  65. data/spec/data/blueprint_invalid.json +3 -1
  66. data/spec/data/gd_gse_data_blueprint.json +1370 -0
  67. data/spec/data/gd_gse_data_manifest.json +1424 -0
  68. data/spec/data/gd_gse_data_model.json +1772 -0
  69. data/spec/data/manifest_test_project.json +116 -0
  70. data/spec/data/model_view.json +1772 -0
  71. data/spec/data/superfluous_titles_view.json +81 -0
  72. data/spec/data/test_project_model_spec.json +7 -4
  73. data/spec/data/wire_test_project.json +143 -0
  74. data/spec/helpers/crypto_helper.rb +9 -0
  75. data/spec/helpers/project_helper.rb +2 -0
  76. data/spec/integration/command_projects_spec.rb +4 -2
  77. data/spec/integration/full_project_spec.rb +51 -18
  78. data/spec/integration/partial_md_export_import_spec.rb +1 -1
  79. data/spec/spec_helper.rb +2 -1
  80. data/spec/unit/models/attribute_column_spec.rb +7 -7
  81. data/spec/unit/models/domain_spec.rb +2 -2
  82. data/spec/unit/models/from_wire_spec.rb +119 -0
  83. data/spec/unit/models/metadata_spec.rb +4 -2
  84. data/spec/unit/models/project_blueprint_spec.rb +32 -16
  85. data/spec/unit/models/project_role_spec.rb +6 -4
  86. data/spec/unit/models/project_spec.rb +26 -3
  87. data/spec/unit/models/schema_builder_spec.rb +5 -6
  88. data/spec/unit/models/to_manifest_spec.rb +24 -0
  89. data/spec/unit/models/to_wire_spec.rb +63 -0
  90. metadata +53 -29
  91. data/lib/gooddata/models/attributes/anchor.rb +0 -37
  92. data/lib/gooddata/models/attributes/attributes.rb +0 -8
  93. data/lib/gooddata/models/attributes/date_attribute.rb +0 -25
  94. data/lib/gooddata/models/attributes/time_attribute.rb +0 -24
  95. data/lib/gooddata/models/columns/attribute.rb +0 -71
  96. data/lib/gooddata/models/columns/columns.rb +0 -8
  97. data/lib/gooddata/models/columns/date_column.rb +0 -63
  98. data/lib/gooddata/models/columns/fact_model.rb +0 -54
  99. data/lib/gooddata/models/columns/label.rb +0 -55
  100. data/lib/gooddata/models/columns/reference.rb +0 -57
  101. data/lib/gooddata/models/facts/facts.rb +0 -8
  102. data/lib/gooddata/models/facts/time_fact.rb +0 -20
  103. data/lib/gooddata/models/folders/attribute_folder.rb +0 -20
  104. data/lib/gooddata/models/folders/fact_folder.rb +0 -20
  105. data/lib/gooddata/models/folders/folders.rb +0 -8
  106. data/lib/gooddata/models/metadata/column.rb +0 -61
  107. data/lib/gooddata/models/metadata/data_set.rb +0 -32
  108. data/lib/gooddata/models/metadata/date_dimension.rb +0 -26
  109. data/lib/gooddata/models/metadata/schema.rb +0 -227
  110. data/lib/gooddata/models/references/date_reference.rb +0 -44
  111. data/lib/gooddata/models/references/references.rb +0 -8
  112. data/lib/gooddata/models/references/time_reference.rb +0 -13
  113. data/spec/helpers/schema_helper.rb +0 -16
  114. data/spec/unit/models/anchor_spec.rb +0 -32
  115. data/spec/unit/models/tools_spec.rb +0 -95
  116. data/test/test_upload.rb +0 -79
@@ -1,54 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require_relative '../metadata/column'
4
-
5
- module GoodData
6
- module Model
7
- ##
8
- # GoodData fact abstraction
9
- #
10
- class Fact < Column
11
- def type_prefix
12
- FACT_PREFIX
13
- end
14
-
15
- def column_prefix
16
- FACT_COLUMN_PREFIX
17
- end
18
-
19
- def folder_prefix
20
- FACT_FOLDER_PREFIX
21
- end
22
-
23
- def table
24
- @schema.table
25
- end
26
-
27
- def column
28
- @column ||= table + '.' + column_prefix + name
29
- end
30
-
31
- def to_maql_create
32
- "CREATE FACT {#{identifier}} VISUAL (#{visual})" \
33
- + " AS {#{column}};\n"
34
- end
35
-
36
- def to_manifest_part(mode)
37
- {
38
- 'populates' => [identifier],
39
- 'mode' => mode,
40
- 'columnName' => name
41
- }
42
- end
43
-
44
- def to_wire_model
45
- {
46
- 'fact' => {
47
- 'identifier' => identifier,
48
- 'title' => title
49
- }
50
- }
51
- end
52
- end
53
- end
54
- end
@@ -1,55 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require_relative '../metadata/column'
4
-
5
- module GoodData
6
- module Model
7
- ##
8
- # GoodData display form abstraction. Represents a default representation
9
- # of an attribute column or an additional representation defined in a LABEL
10
- # field
11
- #
12
- class Label < Column
13
- attr_accessor :attribute
14
-
15
- def type_prefix
16
- 'label'
17
- end
18
-
19
- # def initialize(hash, schema)
20
- def initialize(hash, attribute, schema)
21
- super hash, schema
22
- attribute = attribute.nil? ? schema.fields.find { |field| field.name == hash[:reference] } : attribute
23
- @attribute = attribute
24
- attribute.labels << self
25
- end
26
-
27
- def identifier
28
- @identifier ||= @attribute.name == name ? super : "#{type_prefix}.#{@schema.name}.#{@attribute.name}.#{name}"
29
- end
30
-
31
- def to_maql_create
32
- "# LABEL FROM LABEL\nALTER ATTRIBUTE {#{@attribute.identifier}} ADD LABELS {#{identifier}}" \
33
- + " VISUAL (TITLE #{title.inspect}) AS {#{column}};\n"
34
- end
35
-
36
- def to_manifest_part(mode)
37
- {
38
- 'populates' => [identifier],
39
- 'mode' => mode,
40
- 'columnName' => name
41
- }
42
- end
43
-
44
- def column
45
- "#{@attribute.table}.#{LABEL_COLUMN_PREFIX}#{name}"
46
- end
47
-
48
- alias_method :inspect_orig, :inspect
49
-
50
- def inspect
51
- inspect_orig.sub(/>$/, " @attribute=#{@attribute.to_s.sub(/>$/, " @name=#{@attribute.name}")}>")
52
- end
53
- end
54
- end
55
- end
@@ -1,57 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require_relative '../metadata/column'
4
-
5
- module GoodData
6
- module Model
7
- ##
8
- # Reference to another data set
9
- #
10
- class Reference < Column
11
- attr_accessor :reference, :schema_ref
12
-
13
- def initialize(column, schema)
14
- super column, schema
15
- # pp column
16
- @name = column[:name]
17
- @reference = column[:reference]
18
- @schema_ref = column[:dataset]
19
- @schema = schema
20
- end
21
-
22
- ##
23
- # Generates an identifier of the referencing attribute using the
24
- # schema name derived from schemaReference and column name derived
25
- # from the reference key.
26
- #
27
- def identifier
28
- @identifier ||= "#{ATTRIBUTE_PREFIX}.#{@schema_ref}.#{@reference}"
29
- end
30
-
31
- def key
32
- "#{@name}_id"
33
- end
34
-
35
- def label_column
36
- "#{LABEL_PREFIX}.#{@schema_ref}.#{@reference}"
37
- end
38
-
39
- def to_maql_create
40
- "ALTER ATTRIBUTE {#{identifier}} ADD KEYS {#{@schema.table}.#{key}};\n"
41
- end
42
-
43
- def to_maql_drop
44
- "ALTER ATTRIBUTE {#{identifier} DROP KEYS {#{@schema.table}.#{key}};\n"
45
- end
46
-
47
- def to_manifest_part(mode)
48
- {
49
- 'populates' => [label_column],
50
- 'mode' => mode,
51
- 'columnName' => name,
52
- 'referenceKey' => 1
53
- }
54
- end
55
- end
56
- end
57
- end
@@ -1,8 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require 'pathname'
4
-
5
- base = Pathname(__FILE__).dirname.expand_path
6
- Dir.glob(base + '*.rb').each do |file|
7
- require file
8
- end
@@ -1,20 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require_relative '../metadata/fact'
4
-
5
- module GoodData
6
- module Model
7
- ##
8
- # Fact representation of a time of a day
9
- #
10
- class TimeFact < Fact
11
- def column_prefix
12
- TIME_COLUMN_PREFIX
13
- end
14
-
15
- def type_prefix
16
- TIME_FACT_PREFIX
17
- end
18
- end
19
- end
20
- end
@@ -1,20 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require_relative '../metadata/folder'
4
-
5
- module GoodData
6
- module Model
7
- ##
8
- # GoodData attribute folder abstraction
9
- #
10
- class AttributeFolder < Folder
11
- def type
12
- 'ATTRIBUTE'
13
- end
14
-
15
- def type_prefix
16
- 'dim'
17
- end
18
- end
19
- end
20
- end
@@ -1,20 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require_relative '../metadata/folder'
4
-
5
- module GoodData
6
- module Model
7
- ##
8
- # GoodData fact folder abstraction
9
- #
10
- class FactFolder < Folder
11
- def type
12
- 'FACT'
13
- end
14
-
15
- def type_prefix
16
- 'ffld'
17
- end
18
- end
19
- end
20
- end
@@ -1,8 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require 'pathname'
4
-
5
- base = Pathname(__FILE__).dirname.expand_path
6
- Dir.glob(base + '*.rb').each do |file|
7
- require file
8
- end
@@ -1,61 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require_relative '../md_object'
4
- require_relative '../../helpers/helpers'
5
-
6
- module GoodData
7
- module Model
8
- ##
9
- # This is a base class for server-side LDM elements such as attributes, labels and
10
- # facts
11
- #
12
- class Column < MdObject
13
- attr_accessor :folder, :name, :title, :schema
14
-
15
- def initialize(hash, schema)
16
- super()
17
- fail(ArgumentError, "Schema must be provided, got #{schema.class}") unless schema.is_a? Schema
18
- fail('Data set fields must have their names defined') if hash[:name].nil?
19
-
20
- @name = hash[:name]
21
- @title = hash[:title] || hash[:name].humanize
22
- @folder = hash[:folder]
23
- @schema = schema
24
- end
25
-
26
- ##
27
- # Generates an identifier from the object name by transliterating
28
- # non-Latin character and then dropping non-alphanumerical characters.
29
- #
30
- def identifier
31
- @identifier ||= "#{type_prefix}.#{@schema.name}.#{name}"
32
- end
33
-
34
- def to_maql_drop
35
- "DROP {#{identifier}};\n"
36
- end
37
-
38
- def visual
39
- visual = super
40
- visual += ", FOLDER {#{folder_prefix}.#{(folder)}}" if folder
41
- visual
42
- end
43
-
44
- def to_csv_header(row)
45
- name
46
- end
47
-
48
- def to_csv_data(headers, row)
49
- row[name]
50
- end
51
-
52
- # Overriden to prevent long strings caused by the @schema attribute
53
- #
54
- def inspect
55
- to_s.sub(/>$/, " @title=#{@title.inspect}, @name=#{@name.inspect}, @folder=#{@folder.inspect}," \
56
- " @schema=#{@schema.to_s.sub(/>$/, ' @title=' + @schema.name.inspect + '>')}" \
57
- ">")
58
- end
59
- end
60
- end
61
- end
@@ -1,32 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require_relative '../metadata.rb'
4
- require_relative 'metadata'
5
-
6
- module GoodData
7
- class DataSet < GoodData::MdObject
8
- root_key :dataSet
9
-
10
- SLI_CTG = 'singleloadinterface'
11
- DS_SLI_CTG = 'dataset-singleloadinterface'
12
-
13
- def sli_enabled?
14
- content['mode'] == 'SLI'
15
- end
16
-
17
- def sli
18
- fail(NoProjectError, 'Connect to a project before searching for an object') unless GoodData.project
19
- slis = GoodData.project.md.links(Model::LDM_CTG).links(SLI_CTG)[DS_SLI_CTG]
20
- uri = slis[identifier]['link']
21
- MdObject[uri]
22
- end
23
-
24
- def attributes
25
- content['attributes'].map { |a| GoodData::Attribute[a] }
26
- end
27
-
28
- def facts
29
- content['facts'].map { |a| GoodData::Attribute[a] }
30
- end
31
- end
32
- end
@@ -1,26 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require_relative '../md_object'
4
-
5
- module GoodData
6
- module Model
7
- class DateDimension < MdObject
8
- def initialize(spec = {})
9
- super()
10
- @name = spec[:name]
11
- @title = spec[:title] || @name
12
- @urn = spec[:urn] || 'URN:GOODDATA:DATE'
13
- end
14
-
15
- def to_maql_create
16
- # urn = "urn:chefs_warehouse_fiscal:date"
17
- # title = "title"
18
- # name = "name"
19
-
20
- maql = ''
21
- maql += "INCLUDE TEMPLATE \"#{@urn}\" MODIFY (IDENTIFIER \"#{@name}\", TITLE \"#{@title}\");"
22
- maql
23
- end
24
- end
25
- end
26
- end
@@ -1,227 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require_relative '../../helpers/helpers'
4
-
5
- require_relative '../attributes/anchor'
6
- require_relative '../columns/columns'
7
- require_relative '../md_object'
8
-
9
- module GoodData
10
- module Model
11
- ##
12
- # Server-side representation of a local data set; includes connection point,
13
- # attributes and labels, facts, folders and corresponding pieces of physical
14
- # model abstractions.
15
- #
16
- class Schema < MdObject
17
- attr_reader :fields, :attributes, :facts, :folders, :references, :labels, :name, :title, :anchor
18
-
19
- def self.load(file)
20
- Schema.new JSON.load(open(file))
21
- end
22
-
23
- def initialize(a_config, a_name = 'Default Name', a_title = 'Default Title')
24
- super()
25
- @fields = []
26
- @attributes = []
27
- @facts = []
28
- @folders = {
29
- :facts => {},
30
- :attributes => {}
31
- }
32
- @references = []
33
- @labels = []
34
-
35
- a_config[:name] = a_name unless a_config[:name]
36
- a_config[:title] = a_config[:name] unless a_config[:title]
37
- a_config[:title] = a_title unless a_config[:title]
38
- a_config[:title] = a_config[:title].humanize
39
-
40
- fail 'Schema name not specified' unless a_config[:name]
41
- @name = a_config[:name]
42
- @title = a_config[:title]
43
- self.config = (a_config)
44
- end
45
-
46
- def config=(config)
47
- config[:columns].each do |c|
48
- case c[:type].to_s
49
- when 'attribute'
50
- add_attribute c
51
- when 'fact'
52
- add_fact c
53
- when 'date'
54
- add_date c
55
- when 'anchor'
56
- set_anchor c
57
- when 'label'
58
- add_label c
59
- when 'reference'
60
- add_reference c
61
- else
62
- fail "Unexpected type #{c[:type]} in #{c.inspect}"
63
- end
64
- end
65
- @anchor = Anchor.new(nil, self) unless @anchor
66
- end
67
-
68
- def type_prefix
69
- 'dataset'
70
- end
71
-
72
- ##
73
- # Underlying fact table name
74
- #
75
- def table
76
- @table ||= FACT_COLUMN_PREFIX + name
77
- end
78
-
79
- ##
80
- # Generates MAQL DDL script to drop this data set and included pieces
81
- #
82
- def to_maql_drop
83
- maql = ''
84
- [attributes, facts].each do |obj|
85
- maql += obj.to_maql_drop
86
- end
87
- maql += "DROP {#{identifier}};\n"
88
- end
89
-
90
- ##
91
- # Generates MAQL DDL script to create this data set and included pieces
92
- #
93
- def to_maql_create
94
- # TODO: Use template (.erb)
95
- maql = "# Create the '#{title}' data set\n"
96
- maql += "CREATE DATASET {#{identifier}} VISUAL (TITLE \"#{title}\");\n\n"
97
- [attributes, facts, { 1 => @anchor }].each do |objects|
98
- objects.values.each do |obj|
99
- maql += "# Create '#{obj.title}' and add it to the '#{title}' data set.\n"
100
- maql += obj.to_maql_create
101
- maql += "ALTER DATASET {#{identifier}} ADD {#{obj.identifier}};\n\n"
102
- end
103
- end
104
-
105
- labels.each do |label|
106
- maql += "# Creating Labels\n"
107
- maql += label.to_maql_create
108
- end
109
-
110
- references.values.each do |ref|
111
- maql += "# Creating references\n"
112
- maql += ref.to_maql_create
113
- end
114
-
115
- folders_maql = "# Create folders\n"
116
- (folders[:attributes].values + folders[:facts].values).each { |folder| folders_maql += folder.to_maql_create }
117
- folders_maql + "\n" + maql + "SYNCHRONIZE {#{identifier}};\n"
118
- end
119
-
120
- def upload(path, project = nil, mode = 'FULL')
121
- if path =~ URI.regexp
122
- Tempfile.open('remote_file') do |temp|
123
- temp << open(path).read
124
- temp.flush
125
- upload_data(temp, mode)
126
- end
127
- else
128
- upload_data(path, mode)
129
- end
130
- end
131
-
132
- def upload_data(path, mode)
133
- GoodData::Model.upload_data(path, to_manifest(mode))
134
- end
135
-
136
- # Generates the SLI manifest describing the data loading
137
- #
138
- def to_manifest(mode = 'FULL')
139
- {
140
- 'dataSetSLIManifest' => {
141
- 'parts' => fields.reduce([]) do |memo, f|
142
- val = f.to_manifest_part(mode)
143
- memo << val unless val.nil?
144
- memo
145
- end,
146
- 'dataSet' => identifier,
147
- 'file' => 'data.csv', # should be configurable
148
- 'csvParams' => {
149
- 'quoteChar' => '"',
150
- 'escapeChar' => '"',
151
- 'separatorChar' => ',',
152
- 'endOfLine' => "\n"
153
- }
154
- }
155
- }
156
- end
157
-
158
- def to_wire_model
159
- {
160
- 'dataset' => {
161
- 'identifier' => identifier,
162
- 'title' => title,
163
- 'anchor' => @anchor.to_wire_model,
164
- 'facts' => facts.map { |f| f.to_wire_model },
165
- 'attributes' => attributes.map { |a| a.to_wire_model },
166
- 'references' => references.map { |r| r.is_a?(DateReference) ? r.schema_ref : type_prefix + '.' + r.schema_ref }
167
- } }
168
- end
169
-
170
- private
171
-
172
- def add_attribute(column)
173
- attribute = Attribute.new column, self
174
- fields << attribute
175
- attributes << attribute
176
- add_attribute_folder(attribute.folder)
177
- # folders[AttributeFolder.new(attribute.folder)] = 1 if attribute.folder
178
- end
179
-
180
- def add_attribute_folder(name)
181
- return if name.nil?
182
- return if folders[:attributes].key?(name)
183
- folders[:attributes][name] = AttributeFolder.new(name)
184
- end
185
-
186
- def add_fact(column)
187
- fact = Fact.new column, self
188
- fields << fact
189
- facts << fact
190
- add_fact_folder(fact.folder)
191
- # folders[FactFolder.new(fact.folder)] = 1 if fact.folder
192
- end
193
-
194
- def add_fact_folder(name)
195
- return if name.nil?
196
- return if folders[:facts].key?(name)
197
- folders[:facts][name] = FactFolder.new(name)
198
- end
199
-
200
- def add_label(column)
201
- label = Label.new(column, nil, self)
202
- labels << label
203
- fields << label
204
- end
205
-
206
- def add_reference(column)
207
- reference = Reference.new(column, self)
208
- fields << reference
209
- references << reference
210
- end
211
-
212
- def add_date(column)
213
- date = DateColumn.new column, self
214
- @fields << date
215
- date.parts.values.each { |p| @fields << p }
216
- date.facts.each { |f| facts << f }
217
- date.attributes.each { |a| attributes << a }
218
- date.references.each { |r| references << r }
219
- end
220
-
221
- def set_anchor(column) # rubocop:disable AccessorMethodName
222
- @anchor = Anchor.new column, self
223
- @fields << @anchor
224
- end
225
- end
226
- end
227
- end