sf_cli 0.0.3 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +49 -0
  3. data/README.rdoc +30 -8
  4. data/lib/sf_cli/sf/core/base.rb +80 -0
  5. data/lib/sf_cli/sf/data/bulk_result_v2.rb +77 -0
  6. data/lib/sf_cli/sf/data/core.rb +39 -0
  7. data/lib/sf_cli/sf/data/create_record.rb +30 -0
  8. data/lib/sf_cli/sf/data/delete_bulk.rb +47 -0
  9. data/lib/sf_cli/sf/data/delete_record.rb +33 -0
  10. data/lib/sf_cli/sf/data/delete_resume.rb +47 -0
  11. data/lib/sf_cli/sf/data/get_record.rb +42 -0
  12. data/lib/sf_cli/sf/data/helper_methods.rb +47 -0
  13. data/lib/sf_cli/sf/data/query.rb +120 -0
  14. data/lib/sf_cli/sf/data/query_helper.rb +57 -0
  15. data/lib/sf_cli/sf/data/resume.rb +87 -0
  16. data/lib/sf_cli/sf/data/search.rb +50 -0
  17. data/lib/sf_cli/sf/data/update_record.rb +38 -0
  18. data/lib/sf_cli/sf/data/upsert_bulk.rb +50 -0
  19. data/lib/sf_cli/sf/data/upsert_resume.rb +47 -0
  20. data/lib/sf_cli/sf/main.rb +31 -0
  21. data/lib/sf_cli/sf/model/class_definition.rb +112 -0
  22. data/lib/sf_cli/sf/model/generator.rb +27 -0
  23. data/lib/sf_cli/sf/model/schema.rb +33 -0
  24. data/lib/sf_cli/sf/model.rb +21 -0
  25. data/lib/sf_cli/sf/org/core.rb +23 -0
  26. data/lib/sf_cli/sf/org/display.rb +41 -0
  27. data/lib/sf_cli/sf/org/list.rb +67 -0
  28. data/lib/sf_cli/sf/org/login.rb +64 -0
  29. data/lib/sf_cli/sf/project/core.rb +83 -0
  30. data/lib/sf_cli/sf/sobject/core.rb +50 -0
  31. data/lib/sf_cli.rb +19 -1
  32. metadata +38 -15
  33. data/lib/sf_cli/sf/base.rb +0 -34
  34. data/lib/sf_cli/sf/data.rb +0 -148
  35. data/lib/sf_cli/sf/org.rb +0 -49
  36. data/lib/sf_cli/sf/project.rb +0 -68
  37. data/lib/sf_cli/sf/sobject.rb +0 -41
  38. data/lib/sf_cli/sf.rb +0 -87
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3d070d17a818ef2dd2030a026e1e3b14a284eb1e4ce1bab9ed46c8f5811c2169
4
- data.tar.gz: aa7aafc17f57d6d9df71e6969caad6c756965cfce76ca5583acd73799366b34c
3
+ metadata.gz: c53d056727e589cb48d79aced7900a9419015ad0840e59b5f4d25361a31468ad
4
+ data.tar.gz: 491d45e9ce3907f931d07526eb37f9698e8c5b4cd95ffb3f38317244d99ea656
5
5
  SHA512:
6
- metadata.gz: ddfd91e3ddd1573938d9dbb9c27749eb8054475cee62d5565222f75ad2867fe1abf3dc3c5cc48a452a79991971532f89b233ddf1db491a83b9f28348fdd53eb0
7
- data.tar.gz: 9df1154ec04b5acefddc469429163feed1ee432abd517048b0915d046c29d9d30a5e097153aa50a5774085720f91c68f86cda484ada9d667a6140cd15bcbe6bb
6
+ metadata.gz: a49220a708a8cab60b8ae22f09b4ac805c6b405c3ae0821809012d0cb4d3b34bfd66f69a3429ae4ed70799a0a6cd793c9edcd52e71b2811aaf7a887bdb8db075
7
+ data.tar.gz: dc8d5efe8ea8001212d448ca71fe874b61625960a6daea6163d459d9603c0d5ccbbf1b8c4795694495e4b1b963100113dd02e9dba56160322e3ab27ebcada2b3
data/CHANGELOG.md ADDED
@@ -0,0 +1,49 @@
1
+ ## 0.0.5 - 2024-09-08
2
+ - target CLI version is changed: from 2.54.6 to 2.56.7
3
+ - sf data:
4
+ - add `--bulk` option to query
5
+ - add query resume
6
+ - add upsert bulk
7
+ - add upsert resume
8
+ - add delete bulk
9
+ - add delete resume
10
+ - add resume
11
+ - add search
12
+ - sf org:
13
+ - add list
14
+ - add login access-token
15
+ - add `--browser` option to login web
16
+
17
+ ## 0.0.4 - 2024-09-02
18
+ - breaking change:
19
+ - Sf class doesn't exist anymore. You can not write like `sf = SfCli::Sf.new`. Instead of that, global `sf` method is introduced. You can directly type like `sf.org.display`, which is as almost same usability as the original command.
20
+ - sf data query:
21
+ - support child-parent relationship
22
+ - support parent-children relationship
23
+ - add `--result-format` option
24
+ - auto generation of \Object Model (experimental)
25
+ - generates SF \Object Classes automatically
26
+ - relationship is supported
27
+
28
+ ## 0.0.3 - 2024-08-25
29
+ add command operations:
30
+
31
+ - sf data get record
32
+ - sf data create record
33
+ - sf data update record
34
+ - sf data delete record
35
+
36
+ ## 0.0.2 - 2024-08-18
37
+ this version up was made by mistake.
38
+ nothing was changed.
39
+
40
+ ## 0.0.1 - 2024-08-18
41
+ support some command operations:
42
+
43
+ - sf org login web
44
+ - sf display
45
+ - sf data query
46
+ - sf sobject describe
47
+ - sf sobject list
48
+ - sf project generate
49
+ - sf project generate manifest
data/README.rdoc CHANGED
@@ -2,12 +2,12 @@
2
2
  https://badge.fury.io/rb/sf_cli.png
3
3
 
4
4
  This is a class library for introducing {Salesforce CLI}[https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_top.htm] to Ruby scripting.<br>
5
- It is designed to be similar usability to the command line interface.<br>
5
+ It is designed to be similar usability to the original command.<br>
6
6
  Currently only *sf* command is the target of development.
7
7
 
8
8
  == prerequisite
9
9
  Salesforce CLI must be installed.<br>
10
- As of as of August in 2024, ver.2.54.6 is the development target.
10
+ As of as of September in 2024, ver.2.56.7 is the development target.
11
11
 
12
12
  == install
13
13
  === Rubygem
@@ -21,30 +21,52 @@ then,
21
21
  $ bundle install
22
22
 
23
23
  == Examples
24
+ === Since 0.0.4
25
+ require 'sf_cli'
26
+
27
+ # login to org
28
+ sf.org.login_web
29
+
30
+ # get records
31
+ sf.data.query 'SELECT Id, Name FROM Account LIMIT 1' # => [{Id: "abc", Name: "account name"}]
32
+
33
+ # generate a Salesforce DX project
34
+ sf.project.generate 'MyProject'
35
+
36
+ === Before 0.0.3
24
37
  require 'sf_cli/sf'
25
38
 
26
39
  sf = SfCli::Sf.new
27
40
 
28
41
  # login to org
29
42
  sf.org.login_web
30
- sf.org.login_web target_org: :dev # name an alias to the org, which you're going to log in, for later use. This is needed when you don't use the default org.
31
43
 
32
44
  # get Account records
33
45
  sf.data.query 'SELECT Id, Name FROM Account LIMIT 3' # => returns an array containing 3 records
34
46
 
35
- Account = Struct.new(:Id, :Name)
36
- sf.data.query('SELECT Id, Name From Account Limit 3', model_class: Account) # returns an array of Account struct object
37
-
38
47
  # generate a Salesforce DX project
39
48
  sf.project.generate 'MyProject'
40
49
 
50
+ == \Object Model support (experimental, since 0.0.4)
51
+ require 'sf_cli'
52
+ require 'sf_cli/sf/model'
53
+
54
+ # generates Model Class for Contact and Account
55
+ SfCli::Sf::Model.generate %w[Contact Account]
56
+
57
+ c = Contact.new(:Name => "John Smith")
58
+ c.Name # => "John Smith"
41
59
 
42
- For more command details, see {Salesforce CLI Command Reference}[https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_top.htm]
60
+ rows = sf.data.query 'SELECT Id, Name, Account.Name From Contact Limit 3', model_class: Contact
61
+ rows.size # => 3
62
+ rows.first.Name # => Name of the Contact
63
+ rows.first.Account.Name # => Name of the Account
43
64
 
44
65
  == Documents
66
+ The following steps generate *doc* directory, which all documents are generated in.
45
67
  $ git clone https://github.com/tmkw/sf_cli.git
46
68
  $ cd sf_cli
47
69
  $ bundle install
48
70
  $ bundle exec rake rdoc
49
71
 
50
- This generates the documents in doc directory.
72
+ *Or*, you can read the same documents online at {rubygems.org}[https://rubygems.org/gems/sf_cli]
@@ -0,0 +1,80 @@
1
+ module SfCli
2
+ module Sf
3
+ module Core
4
+ module Base
5
+ attr_reader :varbose
6
+
7
+ private
8
+
9
+ def exec(action, flags: {}, switches: {}, redirection: nil, raw_output: false, format: :json) # :doc:
10
+ cmd = %|sf #{category} #{action}#{as_flag_options(flags)}#{as_switch_options(switches, format)}#{redirect redirection}|
11
+ puts cmd if varbose
12
+
13
+ return `#{cmd}` if raw_output
14
+
15
+ json = JSON.parse `#{cmd}`
16
+ puts json if varbose
17
+ raise StandardError.new(json['message']) if json['status'] != 0
18
+
19
+ json
20
+ end
21
+
22
+ def category
23
+ self.class.name.split('::')[-2].downcase
24
+ end
25
+
26
+ def field_value_pairs(hash)
27
+ return nil if hash.nil?
28
+ return nil if hash.empty?
29
+
30
+ hash.each_with_object([]) do|(k,v), arr|
31
+ value = v.instance_of?(String) ? %|'#{v}'| : v
32
+ arr << %(#{k}=#{value})
33
+ end
34
+ .join(' ')
35
+ end
36
+
37
+ def as_flag_options(hash)
38
+ flag_options = hash.map{|k,v| flag k, v}.reject(&:nil?).join(' ')
39
+ flag_options = ' ' + flag_options unless flag_options.empty?
40
+
41
+ flag_options
42
+ end
43
+
44
+ def as_switch_options(hash, format)
45
+ if format.to_sym == :json
46
+ ' ' + {json: true}.merge(hash).each_with_object([]){|(k,v), arr| arr << %(--#{k}) if v}.join(' ')
47
+ else
48
+ return '' if hash.empty?
49
+ hash.each_with_object([]){|(k,v), arr| arr << %(--#{k}) if v}.join(' ')
50
+ end
51
+ end
52
+
53
+ def flag(name, arg)
54
+ arg ? %(--#{name} #{arg}) : nil
55
+ end
56
+
57
+ def os
58
+ @os ||= ENV['OS']
59
+ end
60
+
61
+ def redirect(option)
62
+ case option
63
+ when :null_stderr
64
+ null_stderr_redirection
65
+ else
66
+ end
67
+ end
68
+
69
+ def null_stderr_redirection
70
+ @null_stderr_redirection ||=
71
+ if os.eql?('Windows_NT')
72
+ ' 2>nul'
73
+ else
74
+ ' 2> /dev/null'
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,77 @@
1
+ module SfCli
2
+ module Sf
3
+ module Data
4
+ #
5
+ # Bulk Job information.
6
+ #
7
+ # You can check the job status using the following method:
8
+ # - opened?
9
+ # - upload_completed?
10
+ # - in_progress?
11
+ # - completed?
12
+ # ==== example:
13
+ # result = sf.data.delete_resume job_id: jobinfo.id
14
+ # puts 'yey!' if result.job_info.completed? # the job has completed
15
+ #
16
+ # For more details, see {the guide document}[https://developer.salesforce.com/docs/atlas.en-us.api_asynch.meta/api_asynch/bulk_api_2_job_states.htm]
17
+ #
18
+ JobInfo = Struct.new(
19
+ :id,
20
+ :operation,
21
+ :object,
22
+ :createdById,
23
+ :createdDate,
24
+ :systemModstamp,
25
+ :state,
26
+ :externalIdFieldName,
27
+ :concurrencyMode,
28
+ :contentType,
29
+ :apiVersion,
30
+ :jobType,
31
+ :lineEnding,
32
+ :columnDelimiter,
33
+ :numberRecordsProcessed,
34
+ :numberRecordsFailed,
35
+ :retries,
36
+ :totalProcessingTime,
37
+ :apiActiveProcessingTime,
38
+ :apexProcessingTime,
39
+ :isPkChunkingSupported
40
+ ) do
41
+ def opened?
42
+ state == 'Open'
43
+ end
44
+
45
+ def upload_completed?
46
+ state == 'UploadComplete'
47
+ end
48
+
49
+ def in_progress?
50
+ state == 'InProgress'
51
+ end
52
+
53
+ def completed?
54
+ state == 'JobComplete'
55
+ end
56
+
57
+ def failed?
58
+ state == 'Failed'
59
+ end
60
+
61
+ def aborted?
62
+ state == 'Aborted'
63
+ end
64
+ end
65
+
66
+ #
67
+ # Records processed by Bulk API
68
+ #
69
+ BulkRecordsV2 = Struct.new(:successfulResults, :failedResults, :unprocessedRecords)
70
+
71
+ #
72
+ # Bulk Result information that contains JobInfo and BulkRecordsV2
73
+ #
74
+ BulkResultV2 = Struct.new(:job_info, :records)
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,39 @@
1
+ require_relative '../core/base'
2
+ require_relative './query'
3
+ require_relative './get_record'
4
+ require_relative './update_record'
5
+ require_relative './create_record'
6
+ require_relative './delete_record'
7
+ require_relative './delete_bulk'
8
+ require_relative './delete_resume'
9
+ require_relative './upsert_bulk'
10
+ require_relative './upsert_resume'
11
+ require_relative './resume'
12
+ require_relative './search'
13
+
14
+ module SfCli
15
+ module Sf
16
+ module Data
17
+ #
18
+ # ==== description
19
+ # The class representing *sf* *data*
20
+ #
21
+ # https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_data_commands_unified.htm
22
+ #
23
+ class Core
24
+ include ::SfCli::Sf::Core::Base
25
+ include Query
26
+ include GetRecord
27
+ include UpdateRecord
28
+ include CreateRecord
29
+ include DeleteRecord
30
+ include DeleteBulk
31
+ include DeleteResume
32
+ include UpsertBulk
33
+ include UpsertResume
34
+ include Resume
35
+ include Search
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,30 @@
1
+ module SfCli::Sf::Data
2
+ module CreateRecord
3
+ # create a object record.
4
+ #
5
+ # *object_type* --- \Object Type (ex. Account)<br>
6
+ #
7
+ # *values* --- field values to be assigned<br>
8
+ #
9
+ # *target_org* --- an alias of paticular org, or username can be used<br>
10
+ #
11
+ # ======
12
+ # # create a TheCustomObject record with name and age
13
+ # sf.data.create_record :TheCustomObject__c, values: {Name: "John Smith", Age: 33}
14
+ #
15
+ # For more command details, see {the command reference}[https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_data_commands_unified.htm#cli_reference_data_create_record_unified]
16
+ #
17
+ def create_record(object_type, values: {}, target_org: nil)
18
+ field_values = field_value_pairs(values)
19
+ flags = {
20
+ :"sobject" => object_type,
21
+ :"values" => (field_values.nil? ? nil : %|"#{field_values}"|),
22
+ :"target-org" => target_org,
23
+ }
24
+ action = __method__.to_s.tr('_', ' ')
25
+ json = exec(action, flags: flags, redirection: :null_stderr)
26
+
27
+ json['result']['id']
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,47 @@
1
+ require_relative './bulk_result_v2'
2
+
3
+ module SfCli::Sf::Data
4
+ module DeleteBulk
5
+ # delete records using Bulk API 2.0
6
+ #
7
+ # *file* --- a CSV file, which is written record IDs to delete<br>
8
+ #
9
+ # *sobject* --- \Object Type (ex. Account)<br>
10
+ #
11
+ # *timeout* --- max minutes to wait for the job complete the task.<br>
12
+ #
13
+ # *target_org* --- an alias of paticular org, or username can be used<br>
14
+ #
15
+ # ======
16
+ # # start a delete job
17
+ # jobinfo = sf.data.delete_bulk sobject: :TestCustomObject__c, file: 'delete.csv' # this returns immediately
18
+ # jobinfo.id # => "750J4000003g1OaIAI" it's job ID
19
+ #
20
+ # # you can check if the delete job completed
21
+ # sf.data.delete_resume job_id: jobinfo.id
22
+ #
23
+ # # Or, you can wait for the job completion with one try.
24
+ # result = sf.data.delete_bulk sobject: :TestCustomObject__c, file: 'delete.csv', timeout: 5 # wait within 5 minutes
25
+ #
26
+ # For more command details, see {the command reference}[https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_data_commands_unified.htm#cli_reference_data_delete_bulk_unified]
27
+ #
28
+ def delete_bulk(file:, sobject:, timeout: nil, target_org: nil)
29
+ flags = {
30
+ :"file" => file,
31
+ :"sobject" => sobject,
32
+ :"wait" => timeout,
33
+ :"target-org" => target_org,
34
+ }
35
+ action = __method__.to_s.tr('_', ' ')
36
+ json = exec(action, flags: flags, redirection: :null_stderr)
37
+
38
+ job_info = ::SfCli::Sf::Data::JobInfo.new(**json['result']['jobInfo'])
39
+ return job_info unless json['result']['records']
40
+
41
+ ::SfCli::Sf::Data::BulkResultV2.new(
42
+ job_info: job_info,
43
+ records: ::SfCli::Sf::Data::BulkRecordsV2.new(**json['result']['records'])
44
+ )
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,33 @@
1
+ module SfCli::Sf::Data
2
+ module DeleteRecord
3
+ # delete a object record.
4
+ #
5
+ # *object_type* --- \Object Type (ex. Account)<br>
6
+ #
7
+ # *record_id* --- id of the object<br>
8
+ #
9
+ # *where* --- hash object that is used to identify a record<br>
10
+ #
11
+ # *target_org* --- an alias of paticular org, or username can be used<br>
12
+ #
13
+ # ======
14
+ # sf.data.delete_record :Hoge__c, record_id: 'xxxxxxx'
15
+ # sf.data.delete_record :Hoge__c, where: {Name: 'Jonny B.Good', Country: 'USA'}
16
+ #
17
+ # For more command details, see {the command reference}[https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_data_commands_unified.htm#cli_reference_data_delete_record_unified]
18
+ #
19
+ def delete_record(object_type, record_id: nil, where: nil, target_org: nil)
20
+ where_conditions = field_value_pairs(where)
21
+ flags = {
22
+ :"sobject" => object_type,
23
+ :"record-id" => record_id,
24
+ :"where" => (where_conditions.nil? ? nil : %|"#{where_conditions}"|),
25
+ :"target-org" => target_org,
26
+ }
27
+ action = __method__.to_s.tr('_', ' ')
28
+ json = exec(action, flags: flags, redirection: :null_stderr)
29
+
30
+ json['result']['id']
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,47 @@
1
+ require_relative './bulk_result_v2'
2
+
3
+ module SfCli::Sf::Data
4
+ module DeleteResume
5
+ # resume a bulk delete job you previously started with Bulk API 2.0 and return a bulk result object.
6
+ #
7
+ # *job_id* --- job ID you want to resume<br>
8
+ #
9
+ # *timeout* --- max minutes to wait for the job complete the task.<br>
10
+ #
11
+ # *target_org* --- an alias of paticular org, or username can be used<br>
12
+ #
13
+ # ======
14
+ # # start a delete job
15
+ # jobinfo = sf.data.delete_bulk sobject: :TestCustomObject__c, file: 'delete.csv' # this returns immediately
16
+ # jobinfo.id # => "750J4000003g1OaIAI" it's job ID
17
+ #
18
+ # # the job has already started asynchronously.
19
+ # # So you should check its progress.
20
+ # # if you want to wait for the job complete the task, try 'timeout' option.
21
+ # result = sf.data.delete_resume job_id: jobinfo.id
22
+ #
23
+ # puts 'yey!' if result.job_info.completed? # the job has completed
24
+ #
25
+ # To know more about a job result, take a look at SfCli::Sf::Data module
26
+ #
27
+ # For more command details, see {the command reference}[https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_data_commands_unified.htm#cli_reference_data_delete_resume_unified]
28
+ #
29
+ def delete_resume(job_id:, timeout: nil, target_org: nil)
30
+ flags = {
31
+ :"job-id" => job_id,
32
+ :"wait" => timeout,
33
+ :"target-org" => target_org,
34
+ }
35
+ action = __method__.to_s.tr('_', ' ')
36
+ json = exec(action, flags: flags, redirection: :null_stderr)
37
+
38
+ job_info = ::SfCli::Sf::Data::JobInfo.new(**json['result']['jobInfo'])
39
+ return job_info unless json['result']['records']
40
+
41
+ ::SfCli::Sf::Data::BulkResultV2.new(
42
+ job_info: job_info,
43
+ records: ::SfCli::Sf::Data::BulkRecordsV2.new(**json['result']['records'])
44
+ )
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,42 @@
1
+ module SfCli::Sf::Data
2
+ module GetRecord
3
+
4
+ # get a object record. (eqivalent to *sf* *data* *get* *record*)
5
+ #
6
+ # *object_type* --- \Object Type (ex. Account)<br>
7
+ #
8
+ # *record_id* --- id of the object<br>
9
+ #
10
+ # *where* --- hash object that is used to identify a record<br>
11
+ #
12
+ # *target_org* --- an alias of paticular org, not default one<br>
13
+ #
14
+ # *model_class* --- the object model class<br>
15
+ #
16
+ # ======
17
+ # sf.data.get_record :Account, record_id: 'xxxxxxx'
18
+ # sf.data.get_record :Account, where: {Name: 'Jonny B.Good', Country: 'USA'}
19
+ #
20
+ # CustomObject = Struct.new(:Id, :Name)
21
+ # sf.data.get_record :TheCustomObject__c, record_id: 'xxxxx', model_class: CustomObject # returns a CustomObject instance
22
+ #
23
+ # For more command details, see {the command reference}[https://developer.salesforce.com/docs/atlas.en-us.sfdx_cli_reference.meta/sfdx_cli_reference/cli_reference_data_commands_unified.htm#cli_reference_data_get_record_unified]
24
+ #
25
+ def get_record(object_type, record_id: nil, where: nil, target_org: nil, model_class: nil)
26
+ where_conditions = field_value_pairs(where)
27
+ flags = {
28
+ :"sobject" => object_type,
29
+ :"record-id" => record_id,
30
+ :"where" => (where_conditions.nil? ? nil : %|"#{where_conditions}"|),
31
+ :"target-org" => target_org,
32
+ }
33
+ action = __method__.to_s.tr('_', ' ')
34
+ json = exec(action, flags: flags, redirection: :null_stderr)
35
+
36
+ result = json['result']
37
+ result.delete 'attributes'
38
+
39
+ model_class ? model_class.new(**result) : result
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,47 @@
1
+ module SfCli
2
+ module Sf
3
+ module Data
4
+ module HelperMethods
5
+ def prepare_record(hash) # :doc:
6
+ hash.delete 'attributes'
7
+
8
+ hash.keys.each do |k|
9
+ if parent?(hash[k])
10
+ hash[k] = prepare_record(hash[k])
11
+ elsif children?(hash[k])
12
+ hash[k] = hash[k]['records'].map{|h| prepare_record(h)}
13
+ end
14
+ end
15
+
16
+ hash
17
+ end
18
+
19
+ def prepare_record_in_bulk_mode(hash) # :doc:
20
+ hash.keys.each do |k|
21
+ match_result = /(.*)\.(.*)/.match(k)
22
+ if match_result
23
+ hash[match_result[1]] = {match_result[2] => hash[k]}
24
+ hash.delete k
25
+ end
26
+ end
27
+
28
+ hash
29
+ end
30
+
31
+ def children?(h)
32
+ return false unless h.instance_of?(Hash)
33
+
34
+ h.has_key? 'records'
35
+ end
36
+
37
+ def parent?(h)
38
+ return false unless h.instance_of?(Hash)
39
+
40
+ h.has_key?('records') == false
41
+ end
42
+
43
+ private :prepare_record, :children?, :parent?
44
+ end
45
+ end
46
+ end
47
+ end