gooddata 0.6.10 → 0.6.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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