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
@@ -0,0 +1,7 @@
1
+ # encoding: UTF-8
2
+
3
+ module GoodData
4
+ # Command Failed
5
+ class CommandFailed < RuntimeError
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # encoding: UTF-8
2
+ require 'pathname'
3
+
4
+ base = Pathname(__FILE__).dirname.expand_path
5
+ Dir.glob(base + '*.rb').each do |file|
6
+ require file
7
+ end
@@ -1,7 +1,7 @@
1
- module GoodData
1
+ # encoding: UTF-8
2
2
 
3
+ module GoodData
3
4
  # Project Not Found
4
5
  class ProjectNotFound < RestClient::ResourceNotFound
5
6
  end
6
-
7
7
  end
@@ -0,0 +1,5 @@
1
+ class BigDecimal;
2
+ def pretty_print(p)
3
+ p.text to_s;
4
+ end
5
+ end
@@ -1,3 +1,5 @@
1
+ # encoding: UTF-8
2
+
1
3
  require 'csv'
2
4
 
3
5
  module GoodData::Extract
@@ -1,5 +1,6 @@
1
- module GoodData::SmallGoodZilla
1
+ # encoding: UTF-8
2
2
 
3
+ module GoodData::SmallGoodZilla
3
4
  # Get IDs from MAQL string
4
5
  # @param a_maql_string Input MAQL string
5
6
  # @return [Array<String>] List of IDS
@@ -42,7 +43,7 @@ module GoodData::SmallGoodZilla
42
43
  []
43
44
  else
44
45
  res = GoodData::MdObject.identifier_to_uri(*ids)
45
- fail "Not all of the identifiers were resolved" if (Array(res).size != ids.size)
46
+ fail 'Not all of the identifiers were resolved' if (Array(res).size != ids.size)
46
47
  res
47
48
  end
48
49
  end
@@ -54,20 +55,18 @@ module GoodData::SmallGoodZilla
54
55
 
55
56
  def self.interpolate_metric(metric, dictionary)
56
57
  interpolated = interpolate({
57
- :facts => GoodData::SmallGoodZilla.get_facts(metric),
58
- :attributes => GoodData::SmallGoodZilla.get_attributes(metric),
59
- :metrics => GoodData::SmallGoodZilla.get_metrics(metric)
60
- }, dictionary)
58
+ :facts => GoodData::SmallGoodZilla.get_facts(metric),
59
+ :attributes => GoodData::SmallGoodZilla.get_attributes(metric),
60
+ :metrics => GoodData::SmallGoodZilla.get_metrics(metric)
61
+ }, dictionary)
61
62
 
62
63
  ids = GoodData::SmallGoodZilla.get_ids(metric)
63
64
  interpolated_ids = ids.zip(Array(interpolate_ids(ids)))
64
65
 
65
- metric = interpolated[:facts].reduce(metric) {|memo, item| memo.sub("#\"#{item[0]}\"", "[#{item[1]}]")}
66
- metric = interpolated[:attributes].reduce(metric) {|memo, item| memo.sub("@\"#{item[0]}\"", "[#{item[1]}]")}
67
- metric = interpolated[:metrics].reduce(metric) {|memo, item| memo.sub("?\"#{item[0]}\"", "[#{item[1]}]")}
68
- metric = interpolated_ids.reduce(metric) {|memo, item| memo.sub("![#{item[0]}]", "[#{item[1]}]")}
66
+ metric = interpolated[:facts].reduce(metric) { |memo, item| memo.sub("#\"#{item[0]}\"", "[#{item[1]}]") }
67
+ metric = interpolated[:attributes].reduce(metric) { |memo, item| memo.sub("@\"#{item[0]}\"", "[#{item[1]}]") }
68
+ metric = interpolated[:metrics].reduce(metric) { |memo, item| memo.sub("?\"#{item[0]}\"", "[#{item[1]}]") }
69
+ metric = interpolated_ids.reduce(metric) { |memo, item| memo.sub("![#{item[0]}]", "[#{item[1]}]") }
69
70
  metric
70
-
71
71
  end
72
-
73
72
  end
@@ -1,44 +1,58 @@
1
- module GoodData::Helpers
2
- def self.home_directory
3
- running_on_windows? ? ENV['USERPROFILE'] : ENV['HOME']
4
- end
1
+ # encoding: UTF-8
5
2
 
6
- def self.running_on_windows?
7
- RUBY_PLATFORM =~ /mswin32|mingw32/
8
- end
3
+ require 'active_support/inflections'
4
+ require 'pathname'
9
5
 
10
- def self.running_on_a_mac?
11
- RUBY_PLATFORM =~ /-darwin\d/
12
- end
6
+ module GoodData
7
+ module Helpers
8
+ class << self
9
+ def home_directory
10
+ running_on_windows? ? ENV['USERPROFILE'] : ENV['HOME']
11
+ end
13
12
 
14
- def self.error(msg)
15
- STDERR.puts(msg)
16
- exit 1
17
- end
13
+ def running_on_windows?
14
+ RUBY_PLATFORM =~ /mswin32|mingw32/
15
+ end
18
16
 
19
- def self.find_goodfile(pwd, options={})
20
- root = Pathname(options[:root] || '/' )
21
- pwd = Pathname(pwd).expand_path
22
- begin
23
- gf = pwd + "Goodfile"
24
- if gf.exist?
25
- return gf
26
- end
27
- pwd = pwd.parent
28
- end until root == pwd
29
- nil
30
- end
17
+ def running_on_a_mac?
18
+ RUBY_PLATFORM =~ /-darwin\d/
19
+ end
20
+
21
+ def error(msg)
22
+ STDERR.puts(msg)
23
+ exit 1
24
+ end
31
25
 
32
- def self.hash_dfs(thing, &block)
33
- if !thing.is_a?(Hash) && !thing.is_a?(Array)
34
- elsif thing.is_a?(Array)
35
- thing.each do |child|
36
- hash_dfs(child, &block)
26
+ def find_goodfile(pwd=`pwd`.strip!, options={})
27
+ root = Pathname(options[:root] || '/')
28
+ pwd = Pathname(pwd).expand_path
29
+ begin
30
+ gf = pwd + 'Goodfile'
31
+ if gf.exist?
32
+ return gf
33
+ end
34
+ pwd = pwd.parent
35
+ end until root == pwd
36
+ nil
37
37
  end
38
- else
39
- thing.each do |key, val|
40
- yield(thing, key)
41
- hash_dfs(val, &block)
38
+
39
+ def hash_dfs(thing, &block)
40
+ if !thing.is_a?(Hash) && !thing.is_a?(Array)
41
+ elsif thing.is_a?(Array)
42
+ thing.each do |child|
43
+ hash_dfs(child, &block)
44
+ end
45
+ else
46
+ thing.each do |key, val|
47
+ yield(thing, key)
48
+ hash_dfs(val, &block)
49
+ end
50
+ end
51
+ end
52
+
53
+ def sanitize_string(str)
54
+ str = ActiveSupport::Inflector.transliterate(str).downcase
55
+ str.gsub(/[^a-z]/, '')
42
56
  end
43
57
  end
44
58
  end
@@ -1,23 +1,25 @@
1
- require File.join(File.dirname(__FILE__), "metadata")
1
+ # encoding: UTF-8
2
2
 
3
- module GoodData
4
- class Attribute < GoodData::MdObject
3
+ require_relative 'metadata'
5
4
 
5
+ module GoodData
6
+ class Attribute < GoodData::MdObject
6
7
  root_key :attribute
7
8
 
8
9
  class << self
9
10
  def [](id)
10
11
  if id == :all
11
12
  GoodData.get(GoodData.project.md['query'] + '/attributes/')['query']['entries']
12
- else
13
+ else
13
14
  super
14
15
  end
15
16
  end
16
17
  end
17
18
 
18
19
  def display_forms
19
- content["displayForms"].map {|df| GoodData::DisplayForm[df["meta"]["uri"]]}
20
+ content['displayForms'].map { |df| GoodData::DisplayForm[df['meta']['uri']] }
20
21
  end
22
+
21
23
  alias :labels :display_forms
22
24
 
23
25
  def is_attribute?
@@ -1,25 +1,25 @@
1
- require File.join(File.dirname(__FILE__), "metadata")
1
+ # encoding: UTF-8
2
2
 
3
- module GoodData
4
- class Dashboard < GoodData::MdObject
3
+ require_relative 'metadata'
5
4
 
5
+ module GoodData
6
+ class Dashboard < GoodData::MdObject
6
7
  root_key :projectDashboard
7
8
 
8
9
  class << self
9
10
  def [](id)
10
11
  if id == :all
11
12
  GoodData.get(GoodData.project.md['query'] + '/projectdashboards/')['query']['entries']
12
- else
13
+ else
13
14
  super
14
15
  end
15
-
16
16
  end
17
17
 
18
18
  def create_report_tab(tab)
19
19
  title = tab[:title]
20
20
  {
21
21
  :title => title,
22
- :items => tab[:items].map {|i| GoodData::Dashboard.create_report_tab_item(i)}
22
+ :items => tab[:items].map { |i| GoodData::Dashboard.create_report_tab_item(i) }
23
23
  }
24
24
  end
25
25
 
@@ -28,48 +28,47 @@ module GoodData
28
28
 
29
29
  report = GoodData::Report.find_first_by_title(title)
30
30
  {
31
- :reportItem => {
32
- :obj => report.uri,
33
- :sizeY => options[:size_y] || 200,
34
- :sizeX => options[:size_x] || 300,
35
- :style => {
36
- :displayTitle => 1,
37
- :background => {
38
- :opacity => 0
39
- }
40
- },
41
- :visualization => {
42
- :grid => {
43
- :columnWidths => []
44
- },
45
- :oneNumber => {
46
- :labels => {}
47
- }
31
+ :reportItem => {
32
+ :obj => report.uri,
33
+ :sizeY => options[:size_y] || 200,
34
+ :sizeX => options[:size_x] || 300,
35
+ :style => {
36
+ :displayTitle => 1,
37
+ :background => {
38
+ :opacity => 0
39
+ }
40
+ },
41
+ :visualization => {
42
+ :grid => {
43
+ :columnWidths => []
48
44
  },
49
- :positionY => options[:position_y] || 0,
50
- :filters => [],
51
- :positionX => options[:position_x] || 0
52
- }
45
+ :oneNumber => {
46
+ :labels => {}
47
+ }
48
+ },
49
+ :positionY => options[:position_y] || 0,
50
+ :filters => [],
51
+ :positionX => options[:position_x] || 0
52
+ }
53
53
  }
54
54
  end
55
55
 
56
56
  def create(options={})
57
57
  stuff = {
58
- "projectDashboard" => {
59
- "content" => {
60
- "tabs" => options[:tabs].map {|t| GoodData::Dashboard.create_report_tab(t)},
61
- "filters" => []
62
- },
63
- "meta" => {
64
- "tags" => options[:tags],
65
- "summary" => options[:summary],
66
- "title" => options[:title]
67
- }
68
- }
58
+ 'projectDashboard' => {
59
+ 'content' => {
60
+ 'tabs' => options[:tabs].map { |t| GoodData::Dashboard.create_report_tab(t) },
61
+ 'filters' => []
62
+ },
63
+ 'meta' => {
64
+ 'tags' => options[:tags],
65
+ 'summary' => options[:summary],
66
+ 'title' => options[:title]
67
+ }
68
+ }
69
69
  }
70
70
  Dashboard.new(stuff)
71
71
  end
72
-
73
72
  end
74
73
 
75
74
  def exportable?
@@ -79,24 +78,24 @@ module GoodData
79
78
  def export(format, options={})
80
79
  supported_formats = [:pdf]
81
80
  fail "Wrong format provied \"#{format}\". Only supports formats #{supported_formats.join(', ')}" unless supported_formats.include?(format)
82
- tab = options[:tab] || ""
81
+ tab = options[:tab] || ''
83
82
 
84
- x = GoodData.post("#{GoodData.project.uri}/clientexport", {"clientExport" => {"url" => "https://secure.gooddata.com/dashboard.html#project=#{GoodData.project.uri}&dashboard=#{uri}&tab=#{tab}&export=1", "name" => title}}, :process => false)
83
+ req_uri = "/gdc/projects/#{GoodData.project.uri}/clientexport"
84
+ x = GoodData.post(req_uri, {'clientExport' => {'url' => "https://secure.gooddata.com/dashboard.html#project=#{GoodData.project.uri}&dashboard=#{uri}&tab=#{tab}&export=1", 'name' => title}}, :process => false)
85
85
  while (x.code == 202) do
86
86
  sleep(1)
87
- uri = JSON.parse(x.body)["asyncTask"]["link"]["poll"]
87
+ uri = MultiJson.load(x.body)["asyncTask"]["link"]["poll"]
88
88
  x = GoodData.get(uri, :process => false)
89
89
  end
90
90
  x
91
91
  end
92
92
 
93
93
  def tabs
94
- content["tabs"]
94
+ content['tabs']
95
95
  end
96
96
 
97
97
  def tabs_ids
98
- tabs.map {|t| t["identifier"]}
98
+ tabs.map { |t| t['identifier'] }
99
99
  end
100
-
101
100
  end
102
101
  end
@@ -1,12 +1,11 @@
1
+ # encoding: UTF-8
2
+
1
3
  require 'active_support/all'
2
4
 
3
- # TODO: Move to some shared helper
4
- class BigDecimal; def pretty_print(p) p.text to_s; end; end
5
+ require_relative '../extensions/big_decimal'
5
6
 
6
7
  module GoodData
7
-
8
8
  class DataResult
9
-
10
9
  attr_reader :data
11
10
 
12
11
  def initialize(data)
@@ -22,18 +21,16 @@ module GoodData
22
21
  a = to_table.to_a
23
22
  data = a.transpose
24
23
  data.unshift((1..a.length).to_a) if with_indices
25
- data.each_with_index.map{|col, i|
26
- col.unshift(i.zero? ? nil : i) if with_indices # inserts row labels #
27
- w = col.map{|cell| cell.to_s.length}.max # w = "column width" #
28
- col.each_with_index.map{|cell, i|
29
- i.zero? ? cell.to_s.center(w) : cell.to_s.ljust(w)} # alligns the column #
30
- }.transpose.map{|row| "[#{row.join(' | ')}]"}.unshift("").join("\n")
24
+ data.each_with_index.map { |col, i|
25
+ col.unshift(i.zero? ? nil : i) if with_indices # inserts row labels #
26
+ w = col.map { |cell| cell.to_s.length }.max # w = "column width" #
27
+ col.each_with_index.map { |cell, i|
28
+ i.zero? ? cell.to_s.center(w) : cell.to_s.ljust(w) } # alligns the column #
29
+ }.transpose.map { |row| "[#{row.join(' | ')}]" }.unshift('').join("\n")
31
30
  end
32
31
 
33
32
  def to_table
34
- raise "Should be implemented in subclass"
33
+ raise 'Should be implemented in subclass'
35
34
  end
36
-
37
35
  end
38
-
39
36
  end
@@ -1,8 +1,9 @@
1
- require File.join(File.dirname(__FILE__), "metadata.rb")
1
+ # encoding: UTF-8
2
+
3
+ require_relative 'metadata.rb'
2
4
 
3
5
  module GoodData
4
6
  class DataSet < MdObject
5
-
6
7
  root_key :dataSet
7
8
 
8
9
  SLI_CTG = 'singleloadinterface'
@@ -13,19 +14,18 @@ module GoodData
13
14
  end
14
15
 
15
16
  def sli
16
- raise NoProjectError.new "Connect to a project before searching for an object" unless GoodData.project
17
+ raise NoProjectError.new 'Connect to a project before searching for an object' unless GoodData.project
17
18
  slis = GoodData.project.md.links(Model::LDM_CTG).links(SLI_CTG)[DS_SLI_CTG]
18
19
  uri = slis[identifier]['link']
19
20
  MdObject[uri]
20
21
  end
21
22
 
22
23
  def attributes
23
- content["attributes"].map {|a| GoodData::Attribute[a]}
24
+ content['attributes'].map { |a| GoodData::Attribute[a] }
24
25
  end
25
26
 
26
27
  def facts
27
- content["facts"].map {|a| GoodData::Attribute[a]}
28
+ content['facts'].map { |a| GoodData::Attribute[a] }
28
29
  end
29
-
30
30
  end
31
31
  end
@@ -1,9 +1,9 @@
1
- require File.join(File.dirname(__FILE__), "metadata")
1
+ # encoding: UTF-8
2
2
 
3
- module GoodData
4
- class DisplayForm < GoodData::MdObject
3
+ require_relative 'metadata'
5
4
 
5
+ module GoodData
6
+ class DisplayForm < GoodData::MdObject
6
7
  root_key :attributeDisplayForm
7
-
8
8
  end
9
9
  end