gooddata 0.6.10 → 0.6.11

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +9 -0
  3. data/.travis.yml +4 -0
  4. data/CHANGELOG.md +6 -0
  5. data/README.md +1 -0
  6. data/gooddata.gemspec +38 -40
  7. data/lib/gooddata/bricks/base_downloader.rb +1 -1
  8. data/lib/gooddata/bricks/middleware/base_middleware.rb +36 -0
  9. data/lib/gooddata/bricks/middleware/bulk_salesforce_middleware.rb +8 -38
  10. data/lib/gooddata/bricks/middleware/decode_params_middleware.rb +14 -0
  11. data/lib/gooddata/bricks/middleware/fs_upload_middleware.rb +7 -6
  12. data/lib/gooddata/bricks/middleware/gooddata_middleware.rb +7 -5
  13. data/lib/gooddata/bricks/middleware/logger_middleware.rb +1 -1
  14. data/lib/gooddata/bricks/middleware/restforce_middleware.rb +20 -14
  15. data/lib/gooddata/bricks/middleware/undot_params_middleware.rb +33 -0
  16. data/lib/gooddata/cli/commands/api_cmd.rb +1 -1
  17. data/lib/gooddata/cli/commands/auth_cmd.rb +1 -1
  18. data/lib/gooddata/cli/commands/console_cmd.rb +2 -2
  19. data/lib/gooddata/cli/commands/process_cmd.rb +54 -7
  20. data/lib/gooddata/cli/commands/project_cmd.rb +9 -9
  21. data/lib/gooddata/cli/commands/projects_cmd.rb +1 -1
  22. data/lib/gooddata/cli/commands/run_ruby_cmd.rb +24 -7
  23. data/lib/gooddata/cli/commands/scaffold_cmd.rb +2 -2
  24. data/lib/gooddata/cli/commands/user_cmd.rb +1 -1
  25. data/lib/gooddata/cli/hooks.rb +3 -3
  26. data/lib/gooddata/commands/datasets.rb +1 -1
  27. data/lib/gooddata/commands/project.rb +2 -2
  28. data/lib/gooddata/commands/role.rb +1 -1
  29. data/lib/gooddata/commands/runners.rb +2 -2
  30. data/lib/gooddata/connection.rb +2 -2
  31. data/lib/gooddata/core/nil_logger.rb +1 -1
  32. data/lib/gooddata/core/rest.rb +12 -8
  33. data/lib/gooddata/data/guesser.rb +1 -1
  34. data/lib/gooddata/exceptions/attr_element_not_found.rb +1 -1
  35. data/lib/gooddata/extensions/enumerable.rb +1 -1
  36. data/lib/gooddata/extensions/hash.rb +20 -0
  37. data/lib/gooddata/helpers/csv_helper.rb +1 -1
  38. data/lib/gooddata/helpers/global_helpers.rb +59 -1
  39. data/lib/gooddata/mixins/md_lock.rb +83 -0
  40. data/lib/gooddata/mixins/md_object_indexer.rb +1 -1
  41. data/lib/gooddata/mixins/md_object_query.rb +1 -1
  42. data/lib/gooddata/mixins/md_relations.rb +0 -9
  43. data/lib/gooddata/models/dashboard_builder.rb +1 -1
  44. data/lib/gooddata/models/domain.rb +2 -2
  45. data/lib/gooddata/models/empty_result.rb +5 -5
  46. data/lib/gooddata/models/execution.rb +74 -0
  47. data/lib/gooddata/models/execution_detail.rb +74 -0
  48. data/lib/gooddata/models/membership.rb +1 -1
  49. data/lib/gooddata/models/metadata/attribute.rb +4 -6
  50. data/lib/gooddata/models/metadata/dashboard.rb +2 -0
  51. data/lib/gooddata/models/metadata/fact.rb +2 -2
  52. data/lib/gooddata/models/metadata/metric.rb +4 -1
  53. data/lib/gooddata/models/metadata/report.rb +84 -34
  54. data/lib/gooddata/models/metadata/report_definition.rb +28 -17
  55. data/lib/gooddata/models/metadata.rb +1 -1
  56. data/lib/gooddata/models/model.rb +1 -1
  57. data/lib/gooddata/models/process.rb +70 -54
  58. data/lib/gooddata/models/profile.rb +47 -10
  59. data/lib/gooddata/models/project.rb +74 -30
  60. data/lib/gooddata/models/project_blueprint.rb +9 -10
  61. data/lib/gooddata/models/project_builder.rb +2 -2
  62. data/lib/gooddata/models/project_creator.rb +4 -4
  63. data/lib/gooddata/models/report_data_result.rb +1 -1
  64. data/lib/gooddata/models/schedule.rb +39 -32
  65. data/lib/gooddata/models/to_manifest.rb +5 -5
  66. data/lib/gooddata/models/to_wire.rb +3 -3
  67. data/lib/gooddata/rest/client.rb +64 -31
  68. data/lib/gooddata/rest/connection.rb +7 -7
  69. data/lib/gooddata/rest/connections/dummy_connection.rb +5 -5
  70. data/lib/gooddata/rest/connections/rest_client_connection.rb +106 -44
  71. data/lib/gooddata/rest/object.rb +1 -1
  72. data/lib/gooddata/version.rb +1 -1
  73. data/spec/bricks/bricks_spec.rb +67 -0
  74. data/spec/bricks/default-config.json +8 -0
  75. data/spec/data/gooddata_version_process/gooddata_version.rb +3 -0
  76. data/spec/data/gooddata_version_process/gooddata_version.zip +0 -0
  77. data/spec/data/ruby_params_process/ruby_params.rb +3 -0
  78. data/spec/helpers/process_helper.rb +12 -0
  79. data/spec/helpers/schedule_helper.rb +21 -0
  80. data/spec/integration/create_project_spec.rb +19 -0
  81. data/spec/integration/full_process_schedule_spec.rb +129 -8
  82. data/spec/integration/full_project_spec.rb +52 -2
  83. data/spec/spec_helper.rb +1 -0
  84. data/spec/unit/core/rest_spec.rb +76 -3
  85. data/spec/unit/helpers_spec.rb +43 -0
  86. data/spec/unit/models/metric_spec.rb +33 -0
  87. data/spec/unit/models/params_spec.rb +96 -0
  88. data/spec/unit/models/profile_spec.rb +16 -0
  89. data/spec/unit/models/schedule_spec.rb +12 -3
  90. metadata +350 -187
  91. data/lib/gooddata/helper/class_helper.rb +0 -1
  92. data/lib/gooddata/helper/helpers.rb +0 -8
@@ -1,9 +1,14 @@
1
1
  # encoding: UTF-8
2
2
 
3
3
  require 'pry'
4
+ require 'zip'
4
5
 
6
+ require_relative '../helpers/global_helpers'
5
7
  require_relative '../rest/resource'
6
8
 
9
+ require_relative 'execution_detail'
10
+ require_relative 'schedule'
11
+
7
12
  module GoodData
8
13
  class Process < GoodData::Rest::Object
9
14
  attr_reader :data
@@ -82,48 +87,7 @@ module GoodData
82
87
  project = GoodData::Project[p, opts]
83
88
  fail ArgumentError, 'Wrong :project specified' if project.nil?
84
89
 
85
- if !path.directory? && (path.extname == '.grf' || path.extname == '.rb')
86
- puts 'Creating package for upload'
87
- Tempfile.open('deploy-graph-archive') do |temp|
88
- Zip::OutputStream.open(temp.path) do |zio|
89
- FileUtils.cd(path.parent) do
90
- files_to_pack = [path.basename]
91
- files_to_pack.each do |item|
92
- puts "including #{item}"
93
- unless File.directory?(item)
94
- zio.put_next_entry(item)
95
- zio.print IO.read(item)
96
- end
97
- end
98
- end
99
- end
100
-
101
- client.upload_to_user_webdav(temp.path, opts)
102
- temp.path
103
- end
104
- elsif !path.directory?
105
- client.upload_to_user_webdav(path, opts)
106
- path
107
- else
108
- Tempfile.open('deploy-graph-archive') do |temp|
109
- Zip::OutputStream.open(temp.path) do |zio|
110
- FileUtils.cd(path) do
111
-
112
- files_to_pack = Dir.glob('./**/*').reject { |f| files_to_exclude.include?(Pathname(path) + f) }
113
- files_to_pack.each do |item|
114
- puts "including #{item}"
115
- unless File.directory?(item)
116
- zio.put_next_entry(item)
117
- zio.print IO.read(item)
118
- end
119
- end
120
- end
121
- end
122
-
123
- client.upload_to_user_webdav(temp.path, opts)
124
- temp.path
125
- end
126
- end
90
+ zip_and_upload path, files_to_exclude, opts
127
91
  end
128
92
 
129
93
  # Deploy a new process or redeploy existing one.
@@ -134,7 +98,7 @@ module GoodData
134
98
  # @option options [String] :name Readable name of the process
135
99
  # @option options [String] :process_id ID of a process to be redeployed (do not set if you want to create a new process)
136
100
  # @option options [Boolean] :verbose (false) Switch on verbose mode for detailed logging
137
- def deploy(path, options = {})
101
+ def deploy(path, options = { :client => GoodData.client, :project => GoodData.project })
138
102
  client = options[:client]
139
103
  fail ArgumentError, 'No :client specified' if client.nil?
140
104
 
@@ -174,6 +138,46 @@ module GoodData
174
138
  puts HighLine.color("Deploy DONE #{path}", HighLine::GREEN) if verbose
175
139
  process
176
140
  end
141
+
142
+ # ----------------------------- Private Stuff
143
+
144
+ private
145
+
146
+ def zip_and_upload(path, files_to_exclude, opts = {})
147
+ def with_zip(opts = {})
148
+ Tempfile.open('deploy-graph-archive') do |temp|
149
+ zip_filename = temp.path
150
+ File.open(zip_filename, 'w') do |zip|
151
+ Zip::File.open(zip.path, Zip::File::CREATE) do |zipfile|
152
+ yield zipfile
153
+ end
154
+ end
155
+ client.upload_to_user_webdav(temp.path, opts)
156
+ temp.path
157
+ end
158
+ end
159
+
160
+ puts 'Creating package for upload'
161
+ if !path.directory? && (path.extname == '.grf' || path.extname == '.rb')
162
+ with_zip(opts) do |zipfile|
163
+ zipfile.add(File.basename(path), path)
164
+ end
165
+
166
+ elsif !path.directory?
167
+ client.upload_to_user_webdav(path, opts)
168
+ path
169
+ else
170
+ with_zip(opts) do |zipfile|
171
+ Dir[File.join(path, '**', '**')].reject { |f| files_to_exclude.include?(Pathname(path) + f) }.each do |file|
172
+ file_pathname = Pathname.new(file)
173
+ puts "Including item #{file_pathname}"
174
+ file_relative_pathname = file_pathname.relative_path_from(Pathname.new(path))
175
+ zipfile.add(file_relative_pathname, file)
176
+ end
177
+ end
178
+ end
179
+ end
180
+ # -----------------------------
177
181
  end
178
182
 
179
183
  def initialize(data)
@@ -193,7 +197,15 @@ module GoodData
193
197
  # @option options [String] :name Readable name of the process
194
198
  # @option options [Boolean] :verbose (false) Switch on verbose mode for detailed logging
195
199
  def deploy(path, options = {})
196
- Process.deploy(path, options.merge(:process_id => process_id))
200
+ Process.deploy(path, options.merge(:process_id => process_id, :client => client, :project => project))
201
+ end
202
+
203
+ # Downloads the process from S3 in a zipped form.
204
+ #
205
+ # @return [IO] The stream of data that represents a zipped deployed process.
206
+ def download
207
+ link = links['source']
208
+ client.get(link, process: false) { |_, _, result| RestClient.get(result.to_hash['location'].first) }
197
209
  end
198
210
 
199
211
  def process
@@ -245,14 +257,7 @@ module GoodData
245
257
  end
246
258
 
247
259
  def execute(executable, options = {})
248
- params = options[:params] || {}
249
- hidden_params = options[:hidden_params] || {}
250
- result = client.post(executions_link,
251
- :execution => {
252
- :graph => executable.to_s,
253
- :params => params,
254
- :hiddenParams => hidden_params
255
- })
260
+ result = start_execution(executable, options)
256
261
  begin
257
262
  client.poll_on_code(result['executionTask']['links']['poll'])
258
263
  rescue RestClient::RequestFailed => e
@@ -260,10 +265,21 @@ module GoodData
260
265
  ensure
261
266
  result = client.get(result['executionTask']['links']['detail'])
262
267
  if result['executionDetail']['status'] == 'ERROR'
263
- fail "Runing process failed. You can look at a log here #{result["executionDetail"]["logFileName"]}"
268
+ fail "Runing process failed. You can look at a log here #{result['executionDetail']['logFileName']}"
264
269
  end
265
270
  end
266
- result
271
+ client.create(GoodData::ExecutionDetail, result, client: client, project: project)
272
+ end
273
+
274
+ def start_execution(executable, options = {})
275
+ params = options[:params] || {}
276
+ hidden_params = options[:hidden_params] || {}
277
+ client.post(executions_link,
278
+ :execution => {
279
+ :graph => executable.to_s,
280
+ :params => GoodData::Helpers.encode_params(params, false),
281
+ :hiddenParams => GoodData::Helpers.encode_params(hidden_params, true)
282
+ })
267
283
  end
268
284
  end
269
285
  end
@@ -43,7 +43,31 @@ module GoodData
43
43
  :timezone
44
44
  ]
45
45
 
46
+ PROFILE_PATH = '/gdc/account/profile/%s'
47
+
46
48
  class << self
49
+ # Get profile by ID or URI
50
+ #
51
+ # @param id ID or URI of user to be found
52
+ # @param [Hash] opts Additional optional options
53
+ # @option opts [GoodData::Rest::Client] :client Client used for communication with server
54
+ # @return GoodData::Profile User Profile
55
+ def [](id, opts = { client: GoodData.connection })
56
+ return id if id.instance_of?(GoodData::Profile) || id.respond_to?(:profile?) && id.profile?
57
+
58
+ if id.to_s !~ %r{^(\/gdc\/account\/profile\/)?[a-zA-Z\d]+$}
59
+ fail(ArgumentError, 'wrong type of argument. Should be either project ID or path')
60
+ end
61
+
62
+ id = id.match(/[a-zA-Z\d]+$/)[0] if id =~ /\//
63
+
64
+ c = client(opts)
65
+ fail ArgumentError, 'No :client specified' if c.nil?
66
+
67
+ response = c.get(PROFILE_PATH % id)
68
+ c.factory.create(Profile, response)
69
+ end
70
+
47
71
  # Apply changes to object.
48
72
  #
49
73
  # @param obj [GoodData::Profile] Object to be modified
@@ -110,13 +134,13 @@ module GoodData
110
134
  next
111
135
  end
112
136
 
113
- if user_existing != user_new
114
- diff = self.diff(user_existing, user_new)
115
- res[:changed] << {
116
- :user => user_existing,
117
- :diff => diff
118
- }
119
- end
137
+ next if user_existing == user_new
138
+
139
+ diff = self.diff(user_existing, user_new)
140
+ res[:changed] << {
141
+ :user => user_existing,
142
+ :diff => diff
143
+ }
120
144
  end
121
145
 
122
146
  tmp = Hash[list2.map { |v| [v.email, v] }]
@@ -250,6 +274,15 @@ module GoodData
250
274
  @json['accountSetting']['firstName'] = val
251
275
  end
252
276
 
277
+ # Get full name
278
+ #
279
+ # @return String Full Name
280
+ def full_name
281
+ "#{first_name} #{last_name}"
282
+ end
283
+
284
+ alias_method :title, :full_name
285
+
253
286
  # Gets the last name
254
287
  #
255
288
  # @return [String] Last name
@@ -293,17 +326,21 @@ module GoodData
293
326
  #
294
327
  # @return [String] Phone
295
328
  def phone
296
- @json['accountSetting']['phone'] || ''
329
+ @json['accountSetting']['phoneNumber'] || ''
297
330
  end
298
331
 
332
+ alias_method :phone_number, :phone
333
+
299
334
  # Set the phone
300
335
  #
301
336
  # @param val [String] Phone to be set
302
337
  def phone=(val)
303
338
  @dirty ||= phone != val
304
- @json['accountSetting']['phone'] = val
339
+ @json['accountSetting']['phoneNumber'] = val
305
340
  end
306
341
 
342
+ alias_method :phone_number=, :phone=
343
+
307
344
  # Gets the position in company
308
345
  #
309
346
  # @return [String] Position in company
@@ -331,7 +368,7 @@ module GoodData
331
368
 
332
369
  # Saves object if dirty, clears dirty flag
333
370
  def save!
334
- if @dirty
371
+ if @dirty # rubocop:disable Style/GuardClause
335
372
  raw = @json.dup
336
373
  raw['accountSetting'].delete('login')
337
374
 
@@ -51,7 +51,7 @@ module GoodData
51
51
  # - /gdc/projects/<id>
52
52
  # - <id>
53
53
  #
54
- def [](id, opts = {})
54
+ def [](id, opts = { client: GoodData.connection })
55
55
  return id if id.instance_of?(GoodData::Project) || id.respond_to?(:project?) && id.project?
56
56
 
57
57
  if id == :all
@@ -83,8 +83,8 @@ module GoodData
83
83
  c = client(opts)
84
84
  fail ArgumentError, 'No :client specified' if c.nil?
85
85
 
86
- auth_token = opts[:auth_token] || GoodData.connection.auth_token
87
- fail 'You have to provide your token for creating projects as :auth_token parameter' if auth_token.nil? || auth_token.empty?
86
+ auth_token = opts[:auth_token]
87
+ fail ArgumentError, 'You have to provide your token for creating projects as :auth_token parameter' if auth_token.nil? || auth_token.empty?
88
88
 
89
89
  json = {
90
90
  'project' =>
@@ -123,7 +123,7 @@ module GoodData
123
123
  project
124
124
  end
125
125
 
126
- def find(opts = {}, client = GoodData::Rest::Client.client)
126
+ def find(_opts = {}, client = GoodData::Rest::Client.client)
127
127
  user = client.user
128
128
  user.projects['projects'].map do |project|
129
129
  client.create(GoodData::Project, project)
@@ -157,17 +157,34 @@ module GoodData
157
157
  if metric.is_a?(String)
158
158
  GoodData::Metric.xcreate(metric, options.merge(default))
159
159
  else
160
- GoodData::Metric.xcreate(metric.merge(default))
160
+ GoodData::Metric.xcreate(options[:expression], metric.merge(options.merge(default)))
161
161
  end
162
162
  end
163
163
  alias_method :create_metric, :add_metric
164
164
 
165
+ # Creates new instance of report in context of project
166
+ #
167
+ # @param [options] Optional report options
168
+ # @return [GoodData::Report] Instance of new report
165
169
  def add_report(options = {})
166
170
  rep = GoodData::Report.create(options.merge(client: client, project: self))
167
171
  rep.save
168
172
  end
169
173
  alias_method :create_report, :add_report
170
174
 
175
+ # Creates new instance of report definition in context of project
176
+ # This report definition can be used for creating of GoodData::Report
177
+ #
178
+ # @param [json] Raw report definition json
179
+ # @return [GoodData::ReportDefinition] Instance of new report definition
180
+ def add_report_definition(json)
181
+ rd = GoodData::ReportDefinition.new(json)
182
+ rd.client = client
183
+ rd.project = self
184
+ rd.save
185
+ end
186
+ alias_method :create_report_definition, :add_report_definition
187
+
171
188
  # Returns an indication whether current user is admin in this project
172
189
  #
173
190
  # @return [Boolean] True if user has admin role in the project, false otherwise.
@@ -215,15 +232,38 @@ module GoodData
215
232
 
216
233
  # Clones project
217
234
  #
235
+ # @param options [Hash] Export options
236
+ # @option options [Boolean] :data Clone project with data
237
+ # @option options [Boolean] :users Clone project with users
238
+ # @option options [String] :authorized_users Comma separated logins of authorized users. Users that can use the export
218
239
  # @return [GoodData::Project] Newly created project
219
240
  def clone(options = {})
220
- # TODO: Refactor so if export or import fails the new_project will be cleaned
221
- with_data = options[:data].nil? ? true : options[:data]
222
- with_users = options[:users].nil? ? false : options[:users]
223
241
  a_title = options[:title] || "Clone of #{title}"
224
242
 
225
- # Create the project first so we know that it is passing. What most likely is wrong is the tokena and the export actaully takes majoiryt of the time
226
- new_project = GoodData::Project.create(options.merge(:title => a_title, :client => client))
243
+ begin
244
+ # Create the project first so we know that it is passing.
245
+ # What most likely is wrong is the token and the export actaully takes majority of the time
246
+ new_project = GoodData::Project.create(options.merge(:title => a_title, :client => client))
247
+ export_token = export_clone(options)
248
+ new_project.import_clone(export_token)
249
+ rescue
250
+ new_project.delete if new_project
251
+ raise
252
+ end
253
+ end
254
+
255
+ # Export a clone from a project to be later imported.
256
+ # If you do not want to do anything special and you do not need fine grained
257
+ # controle use clone method which does all the heavy lifting for you.
258
+ #
259
+ # @param options [Hash] Export options
260
+ # @option options [Boolean] :data Clone project with data
261
+ # @option options [Boolean] :users Clone project with users
262
+ # @option options [String] :authorized_users Comma separated logins of authorized users. Users that can use the export
263
+ # @return [String] token of the export
264
+ def export_clone(options = {})
265
+ with_data = options[:data].nil? ? true : options[:data]
266
+ with_users = options[:users].nil? ? false : options[:users]
227
267
 
228
268
  export = {
229
269
  :exportProject => {
@@ -231,28 +271,34 @@ module GoodData
231
271
  :exportData => with_data ? 1 : 0
232
272
  }
233
273
  }
274
+ export[:exportProject][:authorizedUsers] = options[:authorized_users] if options[:authorized_users]
234
275
 
235
276
  result = client.post("/gdc/md/#{obj_id}/maintenance/export", export)
236
- export_token = result['exportArtifact']['token']
237
-
238
277
  status_url = result['exportArtifact']['status']['uri']
239
278
  client.poll_on_response(status_url) do |body|
240
279
  body['taskState']['status'] == 'RUNNING'
241
280
  end
281
+ result['exportArtifact']['token']
282
+ end
242
283
 
284
+ # Imports a clone into current project. The project has to be freshly
285
+ # created.
286
+ #
287
+ # @param export_token [String] Export token of the package to be imported
288
+ # @return [Project] current project
289
+ def import_clone(export_token)
243
290
  import = {
244
291
  :importProject => {
245
292
  :token => export_token
246
293
  }
247
294
  }
248
295
 
249
- result = client.post("/gdc/md/#{new_project.obj_id}/maintenance/import", import)
296
+ result = client.post("/gdc/md/#{obj_id}/maintenance/import", import)
250
297
  status_url = result['uri']
251
298
  client.poll_on_response(status_url) do |body|
252
299
  body['taskState']['status'] == 'RUNNING'
253
300
  end
254
-
255
- new_project
301
+ self
256
302
  end
257
303
 
258
304
  def compute_report(spec = {})
@@ -298,7 +344,7 @@ module GoodData
298
344
 
299
345
  # Deletes dashboards for project
300
346
  def delete_dashboards
301
- Dashboard.all.map { |data| Dashboard[data['link']] }.each { |d| d.delete }
347
+ Dashboard.all.map { |data| Dashboard[data['link']] }.each(&:delete)
302
348
  end
303
349
 
304
350
  def deploy_process(path, options = {})
@@ -400,10 +446,10 @@ module GoodData
400
446
  role_name.downcase!
401
447
  role_list.each do |role|
402
448
  return role if role.uri == role_name ||
403
- role.identifier.downcase == role_name ||
404
- role.identifier.downcase.gsub(/role$/, '') == role_name ||
405
- role.title.downcase == role_name ||
406
- role.summary.downcase == role_name
449
+ role.identifier.downcase == role_name ||
450
+ role.identifier.downcase.gsub(/role$/, '') == role_name ||
451
+ role.title.downcase == role_name ||
452
+ role.summary.downcase == role_name
407
453
  end
408
454
  nil
409
455
  end
@@ -419,14 +465,14 @@ module GoodData
419
465
  name.downcase!
420
466
  user_list.each do |user|
421
467
  return user if user.uri.downcase == name ||
422
- user.login.downcase == name ||
423
- user.email.downcase == name
468
+ user.login.downcase == name ||
469
+ user.email.downcase == name
424
470
  end
425
471
  nil
426
472
  end
427
473
 
428
474
  # Exports project users to file
429
- def import_users(path, opts = { :header => true }, &block)
475
+ def import_users(path, opts = { :header => true }, &_block)
430
476
  opts[:path] = path
431
477
 
432
478
  ##########################
@@ -609,7 +655,7 @@ module GoodData
609
655
  # @return [GoodData::Fact | Array<GoodData::Fact>] fact instance or list
610
656
  def labels(id = :all, opts = {})
611
657
  if id == :all
612
- attributes.pmapcat { |a| a.labels }.uniq
658
+ attributes.pmapcat(&:labels).uniq
613
659
  else
614
660
  GoodData::Label[id, opts.merge(project: self, client: client)]
615
661
  end
@@ -700,7 +746,7 @@ module GoodData
700
746
  objs = objs.pmap { |obj| objects(obj) }
701
747
  export_payload = {
702
748
  :partialMDExport => {
703
- :uris => objs.map { |obj| obj.uri }
749
+ :uris => objs.map(&:uri)
704
750
  }
705
751
  }
706
752
  result = client.post("#{md['maintenance']}/partialmdexport", export_payload)
@@ -961,7 +1007,7 @@ module GoodData
961
1007
  list = list.map do |user|
962
1008
  {
963
1009
  :user => user,
964
- :roles => new_users_map[user.email].json['user']['content']['role'].split(' ').map { |r| r.downcase }.sort
1010
+ :roles => new_users_map[user.email].json['user']['content']['role'].split(' ').map(&:downcase).sort
965
1011
  }
966
1012
  end
967
1013
 
@@ -976,9 +1022,7 @@ module GoodData
976
1022
  #
977
1023
  # @param list List of users to be disabled
978
1024
  def users_remove(list)
979
- list.pmap do |user|
980
- user.disable
981
- end
1025
+ list.pmap(&:disable)
982
1026
  end
983
1027
 
984
1028
  # Update user
@@ -1022,7 +1066,7 @@ module GoodData
1022
1066
  #
1023
1067
  # @param list List of users to be updated
1024
1068
  # @param role_list Optional list of cached roles to prevent unnecessary server round-trips
1025
- def set_users_roles(list, role_list = roles)
1069
+ def set_users_roles(list, _role_list = roles)
1026
1070
  list.pmap do |user_hash|
1027
1071
  user = user_hash[:user]
1028
1072
  roles = user_hash[:role] || user_hash[:roles]
@@ -353,16 +353,15 @@ module GoodData
353
353
  def lint(full = false)
354
354
  errors = []
355
355
  find_star_centers.each do |dataset|
356
- if dataset.anchor?
357
- errors << {
358
- type: :anchor_on_fact_dataset,
359
- dataset_name: dataset.name,
360
- anchor_name: dataset.anchor[:name]
361
- }
362
- end
356
+ next unless dataset.anchor?
357
+ errors << {
358
+ type: :anchor_on_fact_dataset,
359
+ dataset_name: dataset.name,
360
+ anchor_name: dataset.anchor[:name]
361
+ }
363
362
  end
364
363
 
365
- date_facts = datasets.mapcat { |d| d.date_facts }
364
+ date_facts = datasets.mapcat(&:date_facts)
366
365
  date_facts.each do |date_fact|
367
366
  errors << {
368
367
  type: :date_fact,
@@ -414,7 +413,7 @@ module GoodData
414
413
  when :stupid
415
414
  reports = suggest_metrics.reduce([]) do |a, e|
416
415
  star, metrics = e
417
- metrics.each { |m| m.save }
416
+ metrics.each(&:save)
418
417
  reports_stubs = metrics.map do |m|
419
418
  breaks = can_break(star).map { |ds, aM| ds.identifier_for(aM) }
420
419
  # [breaks.sample((breaks.length/10.0).ceil), m]
@@ -443,7 +442,7 @@ module GoodData
443
442
  # @return [Array<Hash>]
444
443
  def suggest_metrics
445
444
  stars = find_star_centers
446
- metrics = stars.map { |s| s.suggest_metrics }
445
+ metrics = stars.map(&:suggest_metrics)
447
446
  stars.zip(metrics)
448
447
  end
449
448
 
@@ -15,7 +15,7 @@ module GoodData
15
15
  pb
16
16
  end
17
17
 
18
- def create(title, options = {}, &block)
18
+ def create(title, _options = {}, &block)
19
19
  pb = ProjectBuilder.new(title)
20
20
  block.call(pb)
21
21
  pb
@@ -104,7 +104,7 @@ module GoodData
104
104
  eliminate_empty = options[:eliminate_empty] || false
105
105
 
106
106
  if eliminate_empty
107
- JSON.pretty_generate(to_hash.reject { |k, v| v.is_a?(Enumerable) && v.empty? })
107
+ JSON.pretty_generate(to_hash.reject { |_k, v| v.is_a?(Enumerable) && v.empty? })
108
108
  else
109
109
  JSON.pretty_generate(to_hash)
110
110
  end
@@ -66,7 +66,7 @@ module GoodData
66
66
  # pp response
67
67
  while response.code != 200
68
68
  sleep 1
69
- client.retryable(:tries => 3, :on => RestClient::InternalServerError) do
69
+ GoodData::Rest::Client.retryable(:tries => 3, :on => RestClient::InternalServerError) do
70
70
  sleep 1
71
71
  response = client.get(link, :process => false)
72
72
  # pp response
@@ -106,7 +106,7 @@ module GoodData
106
106
  end
107
107
  end
108
108
 
109
- def migrate_users(project, spec)
109
+ def migrate_users(_project, spec)
110
110
  spec.each do |user|
111
111
  puts "Would migrate user #{user}"
112
112
  # project.add_user(user)
@@ -114,7 +114,7 @@ module GoodData
114
114
  end
115
115
 
116
116
  def load(project, spec)
117
- if spec.key?(:uploads)
117
+ if spec.key?(:uploads) # rubocop:disable Style/GuardClause
118
118
  spec[:uploads].each do |load|
119
119
  schema = GoodData::Model::Schema.new(spec[:datasets].find { |d| d[:name] == load[:dataset] })
120
120
  project.upload(load[:source], schema, load[:mode])
@@ -122,7 +122,7 @@ module GoodData
122
122
  end
123
123
  end
124
124
 
125
- def execute_tests(project, spec)
125
+ def execute_tests(_project, spec)
126
126
  spec.each do |assert|
127
127
  result = GoodData::ReportDefinition.execute(assert[:report])
128
128
  fail "Test did not pass. Got #{result.table.inspect}, expected #{assert[:result].inspect}" if result.table != assert[:result]
@@ -48,7 +48,7 @@ module GoodData
48
48
  table.transpose
49
49
  end
50
50
 
51
- def [](index, options = {})
51
+ def [](index, _options = {})
52
52
  to_table[index]
53
53
  end
54
54