gooddata 0.6.0.pre11 → 0.6.0

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/.travis.yml +12 -1
  3. data/.yardopts +2 -0
  4. data/README.md +6 -3
  5. data/Rakefile +24 -7
  6. data/gooddata +2 -2
  7. data/gooddata.gemspec +4 -3
  8. data/lib/gooddata.rb +17 -12
  9. data/lib/gooddata/bricks/base_downloader.rb +7 -7
  10. data/lib/gooddata/bricks/brick.rb +7 -8
  11. data/lib/gooddata/bricks/bricks.rb +4 -1
  12. data/lib/gooddata/bricks/middleware/base_middleware.rb +2 -2
  13. data/lib/gooddata/bricks/middleware/bench_middleware.rb +5 -6
  14. data/lib/gooddata/bricks/middleware/bulk_salesforce_middleware.rb +21 -22
  15. data/lib/gooddata/bricks/middleware/fs_upload_middleware.rb +3 -4
  16. data/lib/gooddata/bricks/middleware/gooddata_middleware.rb +14 -14
  17. data/lib/gooddata/bricks/middleware/logger_middleware.rb +6 -6
  18. data/lib/gooddata/bricks/middleware/middleware.rb +4 -1
  19. data/lib/gooddata/bricks/middleware/restforce_middleware.rb +29 -32
  20. data/lib/gooddata/bricks/middleware/stdout_middleware.rb +5 -5
  21. data/lib/gooddata/bricks/middleware/twitter_middleware.rb +6 -8
  22. data/lib/gooddata/bricks/utils.rb +3 -3
  23. data/lib/gooddata/cli/cli.rb +4 -2
  24. data/lib/gooddata/cli/commands/api_cmd.rb +6 -4
  25. data/lib/gooddata/cli/commands/auth_cmd.rb +5 -3
  26. data/lib/gooddata/cli/commands/console_cmd.rb +1 -1
  27. data/lib/gooddata/cli/commands/process_cmd.rb +6 -4
  28. data/lib/gooddata/cli/commands/profile_cmd.rb +5 -3
  29. data/lib/gooddata/cli/commands/project_cmd.rb +24 -22
  30. data/lib/gooddata/cli/commands/run_ruby_cmd.rb +12 -10
  31. data/lib/gooddata/cli/commands/scaffold_cmd.rb +8 -6
  32. data/lib/gooddata/cli/hooks.rb +4 -2
  33. data/lib/gooddata/cli/shared.rb +3 -1
  34. data/lib/gooddata/cli/terminal.rb +16 -0
  35. data/lib/gooddata/client.rb +28 -22
  36. data/lib/gooddata/commands/api.rb +43 -26
  37. data/lib/gooddata/commands/auth.rb +22 -53
  38. data/lib/gooddata/commands/base.rb +2 -0
  39. data/lib/gooddata/commands/commands.rb +3 -0
  40. data/lib/gooddata/commands/datasets.rb +39 -136
  41. data/lib/gooddata/commands/process.rb +134 -130
  42. data/lib/gooddata/commands/profile.rb +2 -0
  43. data/lib/gooddata/commands/projects.rb +91 -129
  44. data/lib/gooddata/commands/runners.rb +11 -11
  45. data/lib/gooddata/commands/scaffold.rb +28 -26
  46. data/lib/gooddata/connection.rb +61 -68
  47. data/lib/gooddata/core/core.rb +1 -2
  48. data/lib/gooddata/data/data.rb +7 -0
  49. data/lib/gooddata/data/guesser.rb +114 -0
  50. data/lib/gooddata/exceptions/command_failed.rb +7 -0
  51. data/lib/gooddata/exceptions/exceptions.rb +7 -0
  52. data/lib/gooddata/{exceptions.rb → exceptions/project_not_found.rb} +2 -2
  53. data/lib/gooddata/extensions/big_decimal.rb +5 -0
  54. data/lib/gooddata/extract.rb +2 -0
  55. data/lib/gooddata/goodzilla/goodzilla.rb +11 -12
  56. data/lib/gooddata/helpers.rb +49 -35
  57. data/lib/gooddata/models/attribute.rb +7 -5
  58. data/lib/gooddata/models/dashboard.rb +44 -45
  59. data/lib/gooddata/models/data_result.rb +10 -13
  60. data/lib/gooddata/models/data_set.rb +6 -6
  61. data/lib/gooddata/models/display_form.rb +4 -4
  62. data/lib/gooddata/models/empty_result.rb +4 -3
  63. data/lib/gooddata/models/fact.rb +5 -5
  64. data/lib/gooddata/models/links.rb +3 -1
  65. data/lib/gooddata/models/metadata.rb +34 -32
  66. data/lib/gooddata/models/metric.rb +33 -34
  67. data/lib/gooddata/models/model.rb +165 -173
  68. data/lib/gooddata/models/models.rb +3 -0
  69. data/lib/gooddata/models/process.rb +18 -17
  70. data/lib/gooddata/models/profile.rb +3 -1
  71. data/lib/gooddata/models/project.rb +107 -35
  72. data/lib/gooddata/models/project_metadata.rb +12 -12
  73. data/lib/gooddata/models/report.rb +31 -30
  74. data/lib/gooddata/models/report_data_result.rb +22 -19
  75. data/lib/gooddata/models/report_definition.rb +101 -80
  76. data/lib/gooddata/version.rb +5 -3
  77. data/lib/templates/bricks/brick.rb.erb +3 -3
  78. data/lib/templates/bricks/main.rb.erb +3 -2
  79. data/lib/templates/project/Goodfile.erb +2 -2
  80. data/lib/templates/project/model/model.rb.erb +19 -19
  81. data/spec/data/.gooddata +4 -0
  82. data/spec/helpers/blueprint_helper.rb +2 -2
  83. data/spec/helpers/cli_helper.rb +28 -0
  84. data/spec/helpers/connection_helper.rb +2 -2
  85. data/spec/integration/command_projects_spec.rb +1 -1
  86. data/spec/integration/create_from_template_spec.rb +12 -0
  87. data/spec/integration/full_project_spec.rb +2 -2
  88. data/spec/integration/partial_md_export_import_spec.rb +36 -0
  89. data/spec/logging_in_logging_out_spec.rb +1 -1
  90. data/spec/spec_helper.rb +29 -2
  91. data/spec/unit/cli/cli_spec.rb +3 -3
  92. data/spec/unit/cli/commands/cmd_api_spec.rb +21 -4
  93. data/spec/unit/cli/commands/cmd_auth_spec.rb +2 -4
  94. data/spec/unit/cli/commands/cmd_process_spec.rb +20 -4
  95. data/spec/unit/cli/commands/cmd_profile_spec.rb +9 -4
  96. data/spec/unit/cli/commands/cmd_project_spec.rb +53 -4
  97. data/spec/unit/cli/commands/cmd_run_ruby_spec.rb +2 -4
  98. data/spec/unit/cli/commands/cmd_scaffold_spec.rb +14 -4
  99. data/spec/unit/commands/command_api_spec.rb +21 -2
  100. data/spec/unit/commands/command_auth_spec.rb +62 -1
  101. data/spec/unit/commands/command_dataset_spec.rb +31 -3
  102. data/spec/unit/commands/command_process_spec.rb +75 -1
  103. data/spec/unit/commands/command_profile_spec.rb +7 -1
  104. data/spec/unit/commands/command_projects_spec.rb +1 -1
  105. data/spec/unit/commands/command_scaffold_spec.rb +46 -1
  106. data/spec/unit/core/connection_spec.rb +1 -0
  107. data/spec/unit/data/guesser_spec.rb +54 -0
  108. data/spec/unit/helpers_spec.rb +47 -0
  109. data/spec/unit/model/schema_builder_spec.rb +2 -0
  110. data/spec/unit/model/tools_spec.rb +89 -0
  111. data/test/test_upload.rb +39 -15
  112. metadata +98 -75
  113. data/test/test_commands.rb +0 -85
  114. data/test/test_guessing.rb +0 -46
  115. data/test/test_model.rb +0 -81
  116. data/test/test_rest_api_basic.rb +0 -41
@@ -1,8 +1,9 @@
1
- require File.join(File.dirname(__FILE__), "data_result.rb")
1
+ # encoding: UTF-8
2
+
3
+ require_relative 'data_result.rb'
2
4
 
3
5
  module GoodData
4
6
  class EmptyResult < DataResult
5
-
6
7
  def initialize(data, options = {})
7
8
  super(data)
8
9
  @options = options
@@ -10,7 +11,7 @@ module GoodData
10
11
  end
11
12
 
12
13
  def to_s
13
- "No Data"
14
+ 'No Data'
14
15
  end
15
16
 
16
17
  def assemble_table
@@ -1,19 +1,19 @@
1
- require File.join(File.dirname(__FILE__), "metadata")
1
+ # encoding: UTF-8
2
2
 
3
- module GoodData
4
- class Fact < GoodData::MdObject
3
+ require_relative 'metadata'
5
4
 
5
+ module GoodData
6
+ class Fact < GoodData::MdObject
6
7
  root_key :fact
7
8
 
8
9
  class << self
9
10
  def [](id)
10
11
  if id == :all
11
12
  GoodData.get(GoodData.project.md['query'] + '/facts/')['query']['entries']
12
- else
13
+ else
13
14
  super
14
15
  end
15
16
  end
16
17
  end
17
-
18
18
  end
19
19
  end
@@ -1,3 +1,5 @@
1
+ # encoding: UTF-8
2
+
1
3
  module GoodData
2
4
  class Links
3
5
  attr_reader :data
@@ -8,7 +10,7 @@ module GoodData
8
10
  category = item['category']
9
11
  if @data[category] then
10
12
  if @data[category]['category'] == category then
11
- @data[category] = { @data[category]['identifier'] => @data[category] }
13
+ @data[category] = {@data[category]['identifier'] => @data[category]}
12
14
  end
13
15
  @data[category][item['identifier']] = item
14
16
  else
@@ -1,4 +1,6 @@
1
- require File.join(File.dirname(__FILE__), 'model')
1
+ # encoding: UTF-8
2
+
3
+ require_relative 'model'
2
4
 
3
5
  module GoodData
4
6
  class MdObject
@@ -7,25 +9,25 @@ module GoodData
7
9
 
8
10
  class << self
9
11
  def root_key(a_key)
10
- define_method :root_key, Proc.new { a_key.to_s}
12
+ define_method :root_key, Proc.new { a_key.to_s }
11
13
  end
12
-
14
+
13
15
  def [](id)
14
16
  raise "Cannot search for nil #{self.class}" unless id
15
17
  uri = if id.is_a? Integer or id =~ /^\d+$/
16
- "#{GoodData.project.md[MD_OBJ_CTG]}/#{id}"
17
- elsif id !~ /\//
18
- identifier_to_uri id
19
- elsif id =~ /^\//
20
- id
21
- else
22
- raise "Unexpected object id format: expected numeric ID, identifier with no slashes or an URI starting with a slash"
23
- end
18
+ "#{GoodData.project.md[MD_OBJ_CTG]}/#{id}"
19
+ elsif id !~ /\//
20
+ identifier_to_uri id
21
+ elsif id =~ /^\//
22
+ id
23
+ else
24
+ raise 'Unexpected object id format: expected numeric ID, identifier with no slashes or an URI starting with a slash'
25
+ end
24
26
  self.new(GoodData.get uri) unless uri.nil?
25
27
  end
26
28
 
27
29
  def find_by_tag(tag)
28
- self[:all].find_all {|r| r["tags"].split(",").include?(tag)}
30
+ self[:all].find_all { |r| r['tags'].split(',').include?(tag) }
29
31
  end
30
32
 
31
33
  def get_by_id(id)
@@ -36,27 +38,26 @@ module GoodData
36
38
  def find_first_by_title(title)
37
39
  all = self[:all]
38
40
  item = if title.is_a?(Regexp)
39
- all.find {|r| r["title"] =~ title}
40
- else
41
- all.find {|r| r["title"] == title}
42
- end
43
- self[item["link"]] unless item.nil?
41
+ all.find { |r| r['title'] =~ title }
42
+ else
43
+ all.find { |r| r['title'] == title }
44
+ end
45
+ self[item['link']] unless item.nil?
44
46
  end
45
47
 
46
48
  def identifier_to_uri(*ids)
47
- raise NoProjectError.new "Connect to a project before searching for an object" unless GoodData.project
48
- uri = GoodData.project.md[IDENTIFIERS_CFG]
49
- response = GoodData.post uri, { 'identifierToUri' => ids }
49
+ raise NoProjectError.new 'Connect to a project before searching for an object' unless GoodData.project
50
+ uri = GoodData.project.md[IDENTIFIERS_CFG]
51
+ response = GoodData.post uri, {'identifierToUri' => ids}
50
52
  if response['identifiers'].empty?
51
53
  nil
52
54
  else
53
- ids = response['identifiers'].map {|x| x['uri']}
55
+ ids = response['identifiers'].map { |x| x['uri'] }
54
56
  ids.count == 1 ? ids.first : ids
55
57
  end
56
58
  end
57
59
 
58
60
  alias :id_to_uri :identifier_to_uri
59
-
60
61
  end
61
62
 
62
63
  def initialize(json)
@@ -66,7 +67,7 @@ module GoodData
66
67
  def delete
67
68
  if saved?
68
69
  GoodData.delete(uri)
69
- meta.delete("uri")
70
+ meta.delete('uri')
70
71
  # ["uri"] = nil
71
72
  end
72
73
  end
@@ -107,19 +108,19 @@ module GoodData
107
108
  end
108
109
 
109
110
  def title=(a_title)
110
- data["meta"]["title"] = a_title
111
+ data['meta']['title'] = a_title
111
112
  end
112
113
 
113
114
  def summary=(a_summary)
114
- data["meta"]["summary"] = a_summary
115
+ data['meta']['summary'] = a_summary
115
116
  end
116
117
 
117
118
  def tags
118
- data["meta"]["tags"]
119
+ data['meta']['tags']
119
120
  end
120
121
 
121
122
  def tags=(list_of_tags)
122
- data["meta"]["tags"] = list_of_tags
123
+ data['meta']['tags'] = list_of_tags
123
124
  end
124
125
 
125
126
  def meta
@@ -136,12 +137,12 @@ module GoodData
136
137
 
137
138
  def get_usedby
138
139
  result = GoodData.get "#{GoodData.project.md['usedby2']}/#{obj_id}"
139
- result["entries"]
140
+ result['entries']
140
141
  end
141
142
 
142
143
  def get_using
143
144
  result = GoodData.get "#{GoodData.project.md['using2']}/#{obj_id}"
144
- result["entries"]
145
+ result['entries']
145
146
  end
146
147
 
147
148
  def to_json
@@ -153,7 +154,8 @@ module GoodData
153
154
  end
154
155
 
155
156
  def data
156
- raw_data[root_key]
157
+ key = methods.include?(:root_key) ? root_key : raw_data.keys.first
158
+ raw_data[key]
157
159
  end
158
160
 
159
161
  def saved?
@@ -161,13 +163,13 @@ module GoodData
161
163
  end
162
164
 
163
165
  def save
164
- fail("Validation failed") unless validate
166
+ fail('Validation failed') unless validate
165
167
 
166
168
  if saved?
167
169
  GoodData.put(uri, to_json)
168
170
  else
169
171
  result = GoodData.post(GoodData.project.md['obj'], to_json)
170
- saved_object = self.class[result["uri"]]
172
+ saved_object = self.class[result['uri']]
171
173
  @json = saved_object.raw_data
172
174
  end
173
175
  self
@@ -1,17 +1,18 @@
1
- require File.join(File.dirname(__FILE__), "metadata")
2
- require File.join(File.dirname(__FILE__), '../goodzilla/goodzilla')
1
+ # encoding: UTF-8
2
+
3
+ require_relative 'metadata'
4
+ require_relative '../goodzilla/goodzilla'
3
5
 
4
6
  module GoodData
5
7
  # Metric representation
6
8
  class Metric < GoodData::MdObject
7
-
8
9
  root_key :metric
9
10
 
10
11
  class << self
11
12
  def [](id)
12
13
  if id == :all
13
14
  GoodData.get(GoodData.project.md['query'] + '/metrics/')['query']['entries']
14
- else
15
+ else
15
16
  super
16
17
  end
17
18
  end
@@ -32,43 +33,43 @@ module GoodData
32
33
  else
33
34
  title = options[:title]
34
35
  summary = options[:summary]
35
- expression = options[:expression] || fail("Metric has to have its expression defined")
36
+ expression = options[:expression] || fail('Metric has to have its expression defined')
36
37
  extended_notation = options[:extended_notation] || false
37
38
  end
38
39
 
39
40
  expression = if extended_notation
40
- dict = {
41
- :facts => GoodData::Fact[:all].reduce({}) {|memo, item| memo[item["title"]] = item["link"]; memo},
42
- :attributes => GoodData::Attribute[:all].reduce({}) {|memo, item| memo[item["title"]] = item["link"]; memo},
43
- :metrics => GoodData::Metric[:all].reduce({}) {|memo, item| memo[item["title"]] = item["link"]; memo},
44
- }
45
- interpolated_metric = GoodData::SmallGoodZilla.interpolate_metric(expression, dict)
46
- interpolated_metric
47
- else
48
- expression
49
- end
41
+ dict = {
42
+ :facts => GoodData::Fact[:all].reduce({}) { |memo, item| memo[item['title']] = item['link']; memo },
43
+ :attributes => GoodData::Attribute[:all].reduce({}) { |memo, item| memo[item['title']] = item['link']; memo },
44
+ :metrics => GoodData::Metric[:all].reduce({}) { |memo, item| memo[item['title']] = item['link']; memo },
45
+ }
46
+ interpolated_metric = GoodData::SmallGoodZilla.interpolate_metric(expression, dict)
47
+ interpolated_metric
48
+ else
49
+ expression
50
+ end
50
51
 
51
52
  Metric.new({
52
- "metric" => {
53
- "content" => {
54
- "format" => "#,##0",
55
- "expression" => expression
56
- },
57
- "meta" => {
58
- "tags" => "",
59
- "summary" => summary,
60
- "title" => title,
61
- }
62
- }
63
- })
53
+ 'metric' => {
54
+ 'content' => {
55
+ 'format' => '#,##0',
56
+ 'expression' => expression
57
+ },
58
+ 'meta' => {
59
+ 'tags' => '',
60
+ 'summary' => summary,
61
+ 'title' => title,
62
+ }
63
+ }
64
+ })
64
65
  end
65
66
 
66
67
  def execute(expression, options={})
67
68
  m = if expression.is_a?(String)
68
- GoodData::Metric.create({:title => "Temporary metric to be deleted", :expression => expression}.merge(options))
69
- else
70
- GoodData::Metric.create({:title => "Temporary metric to be deleted"}.merge(expression))
71
- end
69
+ GoodData::Metric.create({:title => 'Temporary metric to be deleted', :expression => expression}.merge(options))
70
+ else
71
+ GoodData::Metric.create({:title => 'Temporary metric to be deleted'}.merge(expression))
72
+ end
72
73
  m.execute
73
74
  end
74
75
 
@@ -79,7 +80,6 @@ module GoodData
79
80
  execute(expression.merge({:extended_notation => true}))
80
81
  end
81
82
  end
82
-
83
83
  end
84
84
 
85
85
  def execute
@@ -88,13 +88,12 @@ module GoodData
88
88
  end
89
89
 
90
90
  def validate
91
- fail "Meric needs to have title" if title.nil?
91
+ fail 'Meric needs to have title' if title.nil?
92
92
  true
93
93
  end
94
94
 
95
95
  def is_metric?
96
96
  true
97
97
  end
98
-
99
98
  end
100
99
  end
@@ -1,13 +1,16 @@
1
+ # encoding: UTF-8
2
+
3
+ require_relative '../helpers'
4
+
1
5
  require 'open-uri'
2
6
  require 'active_support/all'
7
+
3
8
  ##
4
9
  # Module containing classes that counter-part GoodData server-side meta-data
5
10
  # elements, including the server-side data model.
6
11
  #
7
12
  module GoodData
8
-
9
13
  module Model
10
-
11
14
  # GoodData REST API categories
12
15
  LDM_CTG = 'ldm'
13
16
  LDM_MANAGE_CTG = 'ldm-manage'
@@ -24,7 +27,7 @@ module GoodData
24
27
  LABEL_PREFIX = 'label'
25
28
  FACT_PREFIX = 'fact'
26
29
  DATE_FACT_PREFIX = 'dt'
27
- DATE_ATTRIBUTE = "date"
30
+ DATE_ATTRIBUTE = 'date'
28
31
  DATE_ATTRIBUTE_DEFAULT_DISPLAY_FORM = 'mdyy'
29
32
  TIME_FACT_PREFIX = 'tm.dt'
30
33
  TIME_ATTRIBUTE_PREFIX = 'attr.time'
@@ -83,13 +86,13 @@ module GoodData
83
86
  pull = {'pullIntegration' => File.basename(dir)}
84
87
  link = project.md.links('etl')['pull']
85
88
  task = GoodData.post link, pull
86
- while (GoodData.get(task["pullTask"]["uri"])["taskStatus"] === "RUNNING" || GoodData.get(task["pullTask"]["uri"])["taskStatus"] === "PREPARED") do
89
+ while GoodData.get(task['pullTask']['uri'])['taskStatus'] === 'RUNNING' || GoodData.get(task['pullTask']['uri'])['taskStatus'] === 'PREPARED'
87
90
  sleep 30
88
91
  end
89
- if (GoodData.get(task["pullTask"]["uri"])["taskStatus"] == "ERROR")
92
+ if GoodData.get(task['pullTask']['uri'])['taskStatus'] == 'ERROR'
90
93
  s = StringIO.new
91
94
  GoodData.download_from_user_webdav(File.basename(dir) + '/upload_status.json', s)
92
- js = JSON.parse(s.string)
95
+ js = MultiJson.load(s.string)
93
96
  fail "Load Failed with error #{JSON.pretty_generate(js)}"
94
97
  end
95
98
  end
@@ -100,20 +103,18 @@ module GoodData
100
103
  d = Marshal.load(Marshal.dump(a_schema_blueprint))
101
104
  d[:columns] = d[:columns] + b_schema_blueprint[:columns]
102
105
  d[:columns].uniq!
103
- columns_that_failed_to_merge = d[:columns].group_by {|x| x[:name]}.map {|k, v| [k, v.count]}.find_all {|x| x[1] > 1}
106
+ columns_that_failed_to_merge = d[:columns].group_by { |x| x[:name] }.map { |k, v| [k, v.count] }.find_all { |x| x[1] > 1 }
104
107
  fail "Columns #{columns_that_failed_to_merge} failed to merge. When merging columns with the same name they have to be identical." unless columns_that_failed_to_merge.empty?
105
108
  d
106
109
  end
107
-
108
110
  end
109
111
 
110
112
  class ProjectBlueprint
111
-
112
113
  attr_accessor :data
113
114
 
114
115
  def self.from_json(spec)
115
116
  if spec.is_a?(String)
116
- ProjectBlueprint.new(JSON.parse(File.read(spec), :symbolize_names => true))
117
+ ProjectBlueprint.new(MultiJson.load(File.read(spec), :symbolize_keys => true))
117
118
  else
118
119
  ProjectBlueprint.new(spec)
119
120
  end
@@ -140,7 +141,7 @@ module GoodData
140
141
  end
141
142
 
142
143
  def remove_dataset(dataset_name)
143
- x = data[:datasets].find {|d| d[:name] == dataset_name}
144
+ x = data[:datasets].find { |d| d[:name] == dataset_name }
144
145
  index = data[:datasets].index(x)
145
146
  data[:datasets].delete_at(index)
146
147
  end
@@ -205,28 +206,26 @@ module GoodData
205
206
 
206
207
  def to_wire_model
207
208
  {
208
- "diffRequest" => {
209
- "targetModel" => {
210
- "projectModel" => {
211
- "datasets" => datasets.map {|d| d.to_wire_model},
212
- "dateDimensions" => date_dimensions.map {|d|
213
- {
214
- "dateDimension" => {
215
- "name" => d[:name],
216
- "title" => d[:title] || d[:name].humanize
217
- }
218
- }}
219
- }}}}
209
+ 'diffRequest' => {
210
+ 'targetModel' => {
211
+ 'projectModel' => {
212
+ 'datasets' => datasets.map { |d| d.to_wire_model },
213
+ 'dateDimensions' => date_dimensions.map { |d|
214
+ {
215
+ 'dateDimension' => {
216
+ 'name' => d[:name],
217
+ 'title' => d[:title] || d[:name].humanize
218
+ }
219
+ } }
220
+ }}}}
220
221
  end
221
222
 
222
223
  def to_hash
223
224
  @data
224
225
  end
225
-
226
226
  end
227
227
 
228
228
  class SchemaBlueprint
229
-
230
229
  attr_accessor :data
231
230
 
232
231
  def change(&block)
@@ -243,8 +242,8 @@ module GoodData
243
242
 
244
243
  def upload(source, options={})
245
244
  project = options[:project] || GoodData.project
246
- fail "You have to specify a project into which you want to load." if project.nil?
247
- mode = options[:load] || "FULL"
245
+ fail 'You have to specify a project into which you want to load.' if project.nil?
246
+ mode = options[:load] || 'FULL'
248
247
  project.upload(source, to_schema, mode)
249
248
  end
250
249
 
@@ -271,7 +270,7 @@ module GoodData
271
270
  end
272
271
 
273
272
  def has_anchor?
274
- columns.any? { |c| c[:type].to_s == "anchor" }
273
+ columns.any? { |c| c[:type].to_s == 'anchor' }
275
274
  end
276
275
 
277
276
  def anchor
@@ -335,17 +334,14 @@ module GoodData
335
334
  def ==(other)
336
335
  to_hash == other.to_hash
337
336
  end
338
-
339
337
  end
340
338
 
341
339
  class ProjectBuilder
342
-
343
340
  attr_reader :title, :datasets, :reports, :metrics, :uploads, :users, :assert_report, :date_dimensions
344
341
 
345
342
  class << self
346
-
347
- def create_from_data(blueprint)
348
- pb = ProjectBuilder.new
343
+ def create_from_data(blueprint, title = 'Title')
344
+ pb = ProjectBuilder.new(title)
349
345
  pb.data = blueprint.to_hash
350
346
  pb
351
347
  end
@@ -355,7 +351,6 @@ module GoodData
355
351
  block.call(pb)
356
352
  pb
357
353
  end
358
-
359
354
  end
360
355
 
361
356
  def initialize(title)
@@ -370,8 +365,14 @@ module GoodData
370
365
  @date_dimensions = []
371
366
  end
372
367
 
373
- def add_date_dimension(name, options={})
374
- @date_dimensions << {:urn => options[:urn], :name => name, :title => options[:title]}
368
+ def add_date_dimension(name, options = {})
369
+ dimension = {
370
+ urn: options[:urn],
371
+ name: name,
372
+ title: options[:title]
373
+ }
374
+
375
+ @date_dimensions << dimension
375
376
  end
376
377
 
377
378
  def add_dataset(name, &block)
@@ -403,12 +404,12 @@ module GoodData
403
404
  end
404
405
 
405
406
  def load_metrics(file)
406
- new_metrics = JSON.parse(open(file).read, :symbolize_names => true)
407
+ new_metrics = MultiJson.load(open(file).read, :symbolize_keys => true)
407
408
  @metrics = @metrics + new_metrics
408
409
  end
409
410
 
410
411
  def load_datasets(file)
411
- new_metrics = JSON.parse(open(file).read, :symbolize_names => true)
412
+ new_metrics = MultiJson.load(open(file).read, :symbolize_keys => true)
412
413
  @datasets = @datasets + new_metrics
413
414
  end
414
415
 
@@ -417,12 +418,12 @@ module GoodData
417
418
  end
418
419
 
419
420
  def upload(data, options={})
420
- mode = options[:mode] || "FULL"
421
+ mode = options[:mode] || 'FULL'
421
422
  dataset = options[:dataset]
422
423
  @uploads << {
423
- :source => data,
424
- :mode => mode,
425
- :dataset => dataset
424
+ :source => data,
425
+ :mode => mode,
426
+ :dataset => dataset
426
427
  }
427
428
  end
428
429
 
@@ -442,26 +443,24 @@ module GoodData
442
443
 
443
444
  def to_hash
444
445
  {
445
- :title => @title,
446
- :datasets => @datasets,
447
- :uploads => @uploads,
448
- :dashboards => @dashboards,
449
- :metrics => @metrics,
450
- :reports => @reports,
451
- :users => @users,
452
- :assert_tests => @assert_tests,
453
- :date_dimensions => @date_dimensions
446
+ :title => @title,
447
+ :datasets => @datasets,
448
+ :uploads => @uploads,
449
+ :dashboards => @dashboards,
450
+ :metrics => @metrics,
451
+ :reports => @reports,
452
+ :users => @users,
453
+ :assert_tests => @assert_tests,
454
+ :date_dimensions => @date_dimensions
454
455
  }
455
456
  end
456
457
 
457
458
  def get_dataset(name)
458
459
  datasets.find { |d| d.name == name }
459
460
  end
460
-
461
461
  end
462
462
 
463
463
  class DashboardBuilder
464
-
465
464
  def initialize(title)
466
465
  @title = title
467
466
  @tabs = []
@@ -476,14 +475,13 @@ module GoodData
476
475
 
477
476
  def to_hash
478
477
  {
479
- :name => @name,
480
- :tabs => @tabs.map { |tab| tab.to_hash }
478
+ :name => @name,
479
+ :tabs => @tabs.map { |tab| tab.to_hash }
481
480
  }
482
481
  end
483
482
  end
484
483
 
485
484
  class TabBuilder
486
-
487
485
  def initialize(title)
488
486
  @title = title
489
487
  @stuff = []
@@ -495,31 +493,27 @@ module GoodData
495
493
 
496
494
  def to_hash
497
495
  {
498
- :title => @title,
499
- :items => @stuff
496
+ :title => @title,
497
+ :items => @stuff
500
498
  }
501
499
  end
502
-
503
500
  end
504
501
 
505
502
  class SchemaBuilder
506
-
507
503
  attr_accessor :data
508
504
 
509
505
  class << self
510
-
511
506
  def create_from_data(blueprint)
512
507
  sc = SchemaBuilder.new
513
508
  sc.data = blueprint.to_hash
514
509
  sc
515
510
  end
516
-
517
511
  end
518
512
 
519
513
  def initialize(name=nil)
520
514
  @data = {
521
- :name => name,
522
- :columns => []
515
+ :name => name,
516
+ :columns => []
523
517
  }
524
518
  end
525
519
 
@@ -575,20 +569,17 @@ module GoodData
575
569
  def to_schema
576
570
  Schema.new(to_hash)
577
571
  end
578
-
579
572
  end
580
573
 
581
574
  class ProjectCreator
582
-
583
575
  class << self
584
576
  def migrate(options={})
585
-
586
- spec = options[:spec] || fail("You need to provide spec for migration")
577
+ spec = options[:spec] || fail('You need to provide spec for migration')
587
578
  spec = spec.to_hash
588
579
 
589
580
  token = options[:token]
590
581
  project = options[:project] || GoodData::Project.create(:title => spec[:title], :auth_token => token)
591
- fail("You need to specify token for project creation") if token.nil? && project.nil?
582
+ fail('You need to specify token for project creation') if token.nil? && project.nil?
592
583
 
593
584
  begin
594
585
  GoodData.with_project(project) do |p|
@@ -615,8 +606,9 @@ module GoodData
615
606
  bp = ProjectBlueprint.new(spec)
616
607
  # schema = Schema.load(schema) unless schema.respond_to?(:to_maql_create)
617
608
  # project = GoodData.project unless project
618
- result = GoodData.post("/gdc/projects/#{GoodData.project.pid}/model/diff", bp.to_wire_model)
619
- link = result["asyncTask"]["link"]["poll"]
609
+ uri = "/gdc/projects/#{GoodData.project.pid}/model/diff"
610
+ result = GoodData.post(uri, bp.to_wire_model)
611
+ link = result['asyncTask']['link']['poll']
620
612
  response = GoodData.get(link, :process => false)
621
613
  # pp response
622
614
  while response.code != 200
@@ -630,9 +622,9 @@ module GoodData
630
622
  response = GoodData.get(link)
631
623
  ldm_links = GoodData.get project.md[LDM_CTG]
632
624
  ldm_uri = Links.new(ldm_links)[LDM_MANAGE_CTG]
633
- chunks = response["projectModelDiff"]["updateScripts"].find_all {|script| script["updateScript"]["preserveData"] == true && script["updateScript"]["cascadeDrops"] == false}.map {|x| x["updateScript"]["maqlDdlChunks"]}.flatten
625
+ chunks = response['projectModelDiff']['updateScripts'].find_all { |script| script['updateScript']['preserveData'] == true && script['updateScript']['cascadeDrops'] == false }.map { |x| x['updateScript']['maqlDdlChunks'] }.flatten
634
626
  chunks.each do |chunk|
635
- GoodData.post ldm_uri, { 'manage' => { 'maql' => chunk } }
627
+ GoodData.post ldm_uri, {'manage' => {'maql' => chunk}}
636
628
  end
637
629
 
638
630
  bp.datasets.each do |ds|
@@ -669,7 +661,7 @@ module GoodData
669
661
  def load(project, spec)
670
662
  if spec.has_key?(:uploads)
671
663
  spec[:uploads].each do |load|
672
- schema = GoodData::Model::Schema.new(spec[:datasets].detect {|d| d[:name] == load[:dataset]})
664
+ schema = GoodData::Model::Schema.new(spec[:datasets].detect { |d| d[:name] == load[:dataset] })
673
665
  project.upload(load[:source], schema, load[:mode])
674
666
  end
675
667
  end
@@ -716,20 +708,23 @@ module GoodData
716
708
  Schema.new JSON.load(open(file))
717
709
  end
718
710
 
719
- def initialize(config, name = nil)
711
+ def initialize(config, name = 'Default Name', title = 'Default Title')
720
712
  super()
721
713
  @fields = []
722
714
  @attributes = []
723
715
  @facts = []
724
716
  @folders = {
725
- :facts => {},
726
- :attributes => {}
717
+ :facts => {},
718
+ :attributes => {}
727
719
  }
728
720
  @references = []
729
721
  @labels = []
730
722
 
731
723
  config[:name] = name unless config[:name]
732
- config[:title] = config[:title] || config[:name].humanize
724
+ config[:title] = config[:name] unless config[:title]
725
+ config[:title] = title unless config[:title]
726
+ config[:title] = config[:title].humanize
727
+
733
728
  fail 'Schema name not specified' unless config[:name]
734
729
  self.name = config[:name]
735
730
  self.title = config[:title]
@@ -739,17 +734,17 @@ module GoodData
739
734
  def config=(config)
740
735
  config[:columns].each do |c|
741
736
  case c[:type].to_s
742
- when "attribute"
737
+ when 'attribute'
743
738
  add_attribute c
744
- when "fact"
739
+ when 'fact'
745
740
  add_fact c
746
- when "date"
741
+ when 'date'
747
742
  add_date c
748
- when "anchor"
743
+ when 'anchor'
749
744
  set_anchor c
750
- when "label"
745
+ when 'label'
751
746
  add_label c
752
- when "reference"
747
+ when 'reference'
753
748
  add_reference c
754
749
  else
755
750
  fail "Unexpected type #{c[:type]} in #{c.inspect}"
@@ -773,7 +768,7 @@ module GoodData
773
768
  # Generates MAQL DDL script to drop this data set and included pieces
774
769
  #
775
770
  def to_maql_drop
776
- maql = ""
771
+ maql = ''
777
772
  [attributes, facts].each do |obj|
778
773
  maql += obj.to_maql_drop
779
774
  end
@@ -784,9 +779,10 @@ module GoodData
784
779
  # Generates MAQL DDL script to create this data set and included pieces
785
780
  #
786
781
  def to_maql_create
782
+ # TODO: Use template (.erb)
787
783
  maql = "# Create the '#{self.title}' data set\n"
788
784
  maql += "CREATE DATASET {#{self.identifier}} VISUAL (TITLE \"#{self.title}\");\n\n"
789
- [ attributes, facts, { 1 => @anchor } ].each do |objects|
785
+ [attributes, facts, {1 => @anchor}].each do |objects|
790
786
  objects.values.each do |obj|
791
787
  maql += "# Create '#{obj.title}' and add it to the '#{self.title}' data set.\n"
792
788
  maql += obj.to_maql_create
@@ -809,7 +805,7 @@ module GoodData
809
805
  folders_maql + "\n" + maql + "SYNCHRONIZE {#{identifier}};\n"
810
806
  end
811
807
 
812
- def upload(path, project = nil, mode = "FULL")
808
+ def upload(path, project = nil, mode = 'FULL')
813
809
  if path =~ URI::regexp
814
810
  Tempfile.open('remote_file') do |temp|
815
811
  temp << open(path).read
@@ -827,31 +823,32 @@ module GoodData
827
823
 
828
824
  # Generates the SLI manifest describing the data loading
829
825
  #
830
- def to_manifest(mode="FULL")
826
+ def to_manifest(mode = 'FULL')
831
827
  {
832
- 'dataSetSLIManifest' => {
833
- 'parts' => fields.reduce([]) { |memo, f| val = f.to_manifest_part(mode); memo << val unless val.nil?; memo },
834
- 'dataSet' => self.identifier,
835
- 'file' => 'data.csv', # should be configurable
836
- 'csvParams' => {
837
- 'quoteChar' => '"',
838
- 'escapeChar' => '"',
839
- 'separatorChar' => ',',
840
- 'endOfLine' => "\n"
841
- }
828
+ 'dataSetSLIManifest' => {
829
+ 'parts' => fields.reduce([]) { |memo, f| val = f.to_manifest_part(mode); memo << val unless val.nil?; memo },
830
+ 'dataSet' => self.identifier,
831
+ 'file' => 'data.csv', # should be configurable
832
+ 'csvParams' => {
833
+ 'quoteChar' => '"',
834
+ 'escapeChar' => '"',
835
+ 'separatorChar' => ',',
836
+ 'endOfLine' => "\n"
842
837
  }
838
+ }
843
839
  }
844
840
  end
845
841
 
846
842
  def to_wire_model
847
843
  {
848
- "dataset" => {
849
- "identifier" => identifier,
850
- "title" => title,
851
- "anchor" => @anchor.to_wire_model,
852
- "facts" => facts.map {|f| f.to_wire_model},
853
- "attributes" => attributes.map {|a| a.to_wire_model},
854
- "references" => references.map {|r| r.is_a?(DateReference) ? r.schema_ref : type_prefix + "." + r.schema_ref }}}
844
+ 'dataset' => {
845
+ 'identifier' => identifier,
846
+ 'title' => title,
847
+ 'anchor' => @anchor.to_wire_model,
848
+ 'facts' => facts.map { |f| f.to_wire_model },
849
+ 'attributes' => attributes.map { |a| a.to_wire_model },
850
+ 'references' => references.map { |r| r.is_a?(DateReference) ? r.schema_ref : type_prefix + '.' + r.schema_ref }}
851
+ }
855
852
  end
856
853
 
857
854
  private
@@ -902,14 +899,13 @@ module GoodData
902
899
  date.parts.values.each { |p| @fields << p }
903
900
  date.facts.each { |f| facts << f }
904
901
  date.attributes.each { |a| attributes << a }
905
- date.references.each {|r| references << r}
902
+ date.references.each { |r| references << r }
906
903
  end
907
904
 
908
905
  def set_anchor(column)
909
906
  @anchor = Anchor.new column, self
910
907
  @fields << @anchor
911
908
  end
912
-
913
909
  end
914
910
 
915
911
  ##
@@ -922,7 +918,9 @@ module GoodData
922
918
  def initialize(hash, schema)
923
919
  super()
924
920
  raise ArgumentError.new("Schema must be provided, got #{schema.class}") unless schema.is_a? Schema
925
- @name = hash[:name] || raise("Data set fields must have their names defined")
921
+ raise('Data set fields must have their names defined') if hash[:name].nil?
922
+
923
+ @name = hash[:name]
926
924
  @title = hash[:title] || hash[:name].humanize
927
925
  @folder = hash[:folder]
928
926
  @schema = schema
@@ -985,7 +983,7 @@ module GoodData
985
983
  end
986
984
 
987
985
  def table
988
- @table ||= "d_" + @schema.name + "_" + name
986
+ @table ||= 'd_' + @schema.name + '_' + name
989
987
  end
990
988
 
991
989
  def key;
@@ -1001,31 +999,30 @@ module GoodData
1001
999
 
1002
1000
  def to_manifest_part(mode)
1003
1001
  {
1004
- 'referenceKey' => 1,
1005
- 'populates' => [@primary_label.identifier],
1006
- 'mode' => mode,
1007
- 'columnName' => name
1002
+ 'referenceKey' => 1,
1003
+ 'populates' => [@primary_label.identifier],
1004
+ 'mode' => mode,
1005
+ 'columnName' => name
1008
1006
  }
1009
1007
  end
1010
1008
 
1011
1009
  def to_wire_model
1012
1010
  {
1013
- "attribute" => {
1014
- "identifier" => identifier,
1015
- "title" => title,
1016
- "labels" => labels.map do |l|
1017
- {
1018
- "label" => {
1019
- "identifier" => l.identifier,
1020
- "title" => l.title,
1021
- "type" => "GDC.text"
1022
- }
1023
- }
1024
- end
1025
- }
1011
+ 'attribute' => {
1012
+ 'identifier' => identifier,
1013
+ 'title' => title,
1014
+ 'labels' => labels.map do |l|
1015
+ {
1016
+ 'label' => {
1017
+ 'identifier' => l.identifier,
1018
+ 'title' => l.title,
1019
+ 'type' => 'GDC.text'
1020
+ }
1021
+ }
1022
+ end
1023
+ }
1026
1024
  }
1027
1025
  end
1028
-
1029
1026
  end
1030
1027
 
1031
1028
  ##
@@ -1034,30 +1031,31 @@ module GoodData
1034
1031
  # field
1035
1032
  #
1036
1033
  class Label < Column
1037
-
1038
1034
  attr_accessor :attribute
1039
1035
 
1040
- def type_prefix ; 'label' ; end
1036
+ def type_prefix;
1037
+ 'label';
1038
+ end
1041
1039
 
1042
1040
  # def initialize(hash, schema)
1043
1041
  def initialize(hash, attribute, schema)
1044
1042
  super hash, schema
1045
- attribute = attribute.nil? ? schema.fields.find {|field| field.name === hash[:reference]} : attribute
1043
+ attribute = attribute.nil? ? schema.fields.find { |field| field.name === hash[:reference] } : attribute
1046
1044
  @attribute = attribute
1047
1045
  attribute.labels << self
1048
1046
  end
1049
1047
 
1050
1048
  def to_maql_create
1051
- "# LABEL FROM LABEL"
1049
+ '# LABEL FROM LABEL'
1052
1050
  "ALTER ATTRIBUTE {#{@attribute.identifier}} ADD LABELS {#{identifier}}" \
1053
1051
  + " VISUAL (TITLE #{title.inspect}) AS {#{column}};\n"
1054
1052
  end
1055
1053
 
1056
1054
  def to_manifest_part(mode)
1057
1055
  {
1058
- 'populates' => [identifier],
1059
- 'mode' => mode,
1060
- 'columnName' => name
1056
+ 'populates' => [identifier],
1057
+ 'mode' => mode,
1058
+ 'columnName' => name
1061
1059
  }
1062
1060
  end
1063
1061
 
@@ -1068,7 +1066,7 @@ module GoodData
1068
1066
  alias :inspect_orig :inspect
1069
1067
 
1070
1068
  def inspect
1071
- inspect_orig.sub(/>$/, " @attribute=" + @attribute.to_s.sub(/>$/, " @name=#{@attribute.name}") + '>')
1069
+ inspect_orig.sub(/>$/, " @attribute=#{@attribute.to_s.sub(/>$/, " @name=#{@attribute.name}")}>")
1072
1070
  end
1073
1071
  end
1074
1072
 
@@ -1081,14 +1079,14 @@ module GoodData
1081
1079
  if column then
1082
1080
  super
1083
1081
  else
1084
- super({:type => "anchor", :name => 'id'}, schema)
1082
+ super({:type => 'anchor', :name => 'id'}, schema)
1085
1083
  @labels = []
1086
1084
  @primary_label = nil
1087
1085
  end
1088
1086
  end
1089
1087
 
1090
1088
  def table
1091
- @table ||= "f_" + @schema.name
1089
+ @table ||= 'f_' + @schema.name
1092
1090
  end
1093
1091
 
1094
1092
  def to_maql_create
@@ -1100,7 +1098,6 @@ module GoodData
1100
1098
  end
1101
1099
  maql
1102
1100
  end
1103
-
1104
1101
  end
1105
1102
 
1106
1103
  ##
@@ -1134,17 +1131,17 @@ module GoodData
1134
1131
 
1135
1132
  def to_manifest_part(mode)
1136
1133
  {
1137
- 'populates' => [identifier],
1138
- 'mode' => mode,
1139
- 'columnName' => name
1134
+ 'populates' => [identifier],
1135
+ 'mode' => mode,
1136
+ 'columnName' => name
1140
1137
  }
1141
1138
  end
1142
1139
 
1143
1140
  def to_wire_model
1144
1141
  {
1145
- "fact" => {
1146
- "identifier" => identifier,
1147
- "title" => title
1142
+ 'fact' => {
1143
+ 'identifier' => identifier,
1144
+ 'title' => title
1148
1145
  }
1149
1146
  }
1150
1147
  end
@@ -1154,7 +1151,6 @@ module GoodData
1154
1151
  # Reference to another data set
1155
1152
  #
1156
1153
  class Reference < Column
1157
-
1158
1154
  attr_accessor :reference, :schema_ref
1159
1155
 
1160
1156
  def initialize(column, schema)
@@ -1193,10 +1189,10 @@ module GoodData
1193
1189
 
1194
1190
  def to_manifest_part(mode)
1195
1191
  {
1196
- 'populates' => [label_column],
1197
- 'mode' => mode,
1198
- 'columnName' => name,
1199
- 'referenceKey' => 1
1192
+ 'populates' => [label_column],
1193
+ 'mode' => mode,
1194
+ 'columnName' => name,
1195
+ 'referenceKey' => 1
1200
1196
  }
1201
1197
  end
1202
1198
  end
@@ -1205,14 +1201,13 @@ module GoodData
1205
1201
  # Date as a reference to a date dimension
1206
1202
  #
1207
1203
  class DateReference < Reference
1208
-
1209
1204
  attr_accessor :format, :output_format, :urn
1210
1205
 
1211
1206
  def initialize(column, schema)
1212
1207
  super column, schema
1213
- @output_format = column["format"] || 'dd/MM/yyyy'
1208
+ @output_format = column['format'] || 'dd/MM/yyyy'
1214
1209
  @format = @output_format.gsub('yyyy', '%Y').gsub('MM', '%m').gsub('dd', '%d')
1215
- @urn = column[:urn] || "URN:GOODDATA:DATE"
1210
+ @urn = column[:urn] || 'URN:GOODDATA:DATE'
1216
1211
  end
1217
1212
 
1218
1213
  def identifier
@@ -1221,11 +1216,11 @@ module GoodData
1221
1216
 
1222
1217
  def to_manifest_part(mode)
1223
1218
  {
1224
- 'populates' => ["#{identifier}.#{DATE_ATTRIBUTE_DEFAULT_DISPLAY_FORM}"],
1225
- 'mode' => mode,
1226
- 'constraints' => {"date" => output_format},
1227
- 'columnName' => name,
1228
- 'referenceKey' => 1
1219
+ 'populates' => ["#{identifier}.#{DATE_ATTRIBUTE_DEFAULT_DISPLAY_FORM}"],
1220
+ 'mode' => mode,
1221
+ 'constraints' => {'date' => output_format},
1222
+ 'columnName' => name,
1223
+ 'referenceKey' => 1
1229
1224
  }
1230
1225
  end
1231
1226
 
@@ -1249,10 +1244,10 @@ module GoodData
1249
1244
 
1250
1245
  def to_manifest_part(mode)
1251
1246
  {
1252
- 'populates' => ['label.stuff.mmddyy'],
1253
- "format" => "unknown",
1254
- "mode" => mode,
1255
- "referenceKey" => 1
1247
+ 'populates' => ['label.stuff.mmddyy'],
1248
+ 'format' => 'unknown',
1249
+ 'mode' => mode,
1250
+ 'referenceKey' => 1
1256
1251
  }
1257
1252
  end
1258
1253
  end
@@ -1274,7 +1269,6 @@ module GoodData
1274
1269
  # Time as a reference to a time-of-a-day dimension
1275
1270
  #
1276
1271
  class TimeReference < Reference
1277
-
1278
1272
  end
1279
1273
 
1280
1274
  ##
@@ -1343,7 +1337,6 @@ module GoodData
1343
1337
  def to_manifest_part(mode)
1344
1338
  nil
1345
1339
  end
1346
-
1347
1340
  end
1348
1341
 
1349
1342
  ##
@@ -1351,8 +1344,10 @@ module GoodData
1351
1344
  #
1352
1345
  class Folder < MdObject
1353
1346
  def initialize(title)
1347
+ # TODO: should a super be here?
1348
+ # how to deal with name vs title?
1354
1349
  @title = title
1355
- @name = title
1350
+ @name = GoodData::Helpers.sanitize_string(title)
1356
1351
  end
1357
1352
 
1358
1353
  def to_maql_create
@@ -1366,11 +1361,11 @@ module GoodData
1366
1361
  #
1367
1362
  class AttributeFolder < Folder
1368
1363
  def type;
1369
- "ATTRIBUTE";
1364
+ 'ATTRIBUTE'
1370
1365
  end
1371
1366
 
1372
1367
  def type_prefix;
1373
- "dim";
1368
+ 'dim'
1374
1369
  end
1375
1370
  end
1376
1371
 
@@ -1379,21 +1374,20 @@ module GoodData
1379
1374
  #
1380
1375
  class FactFolder < Folder
1381
1376
  def type;
1382
- "FACT";
1377
+ 'FACT'
1383
1378
  end
1384
1379
 
1385
1380
  def type_prefix;
1386
- "ffld";
1381
+ 'ffld'
1387
1382
  end
1388
1383
  end
1389
1384
 
1390
1385
  class DateDimension < MdObject
1391
-
1392
1386
  def initialize(spec={})
1393
1387
  super()
1394
1388
  @name = spec[:name]
1395
1389
  @title = spec[:title] || @name
1396
- @urn = spec[:urn] || "URN:GOODDATA:DATE"
1390
+ @urn = spec[:urn] || 'URN:GOODDATA:DATE'
1397
1391
  end
1398
1392
 
1399
1393
  def to_maql_create
@@ -1401,12 +1395,10 @@ module GoodData
1401
1395
  # title = "title"
1402
1396
  # name = "name"
1403
1397
 
1404
- maql = ""
1398
+ maql = ''
1405
1399
  maql += "INCLUDE TEMPLATE \"#{@urn}\" MODIFY (IDENTIFIER \"#{@name}\", TITLE \"#{@title}\");"
1406
1400
  maql
1407
1401
  end
1408
-
1409
1402
  end
1410
-
1411
1403
  end
1412
1404
  end