active_force 0.19.0 → 0.20.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 38ef881c292f8ecb12be07a0471f759a06b9155af5e3a49c26dbb69e024db87f
4
- data.tar.gz: 6a209feb04dc0c6a192c084a95c2e55c64696bbb54636496fc98dc8c56c7b653
3
+ metadata.gz: 1647fdc453090811c384514ae857c83b686dc966e2af5e47af3a6dc67e42059d
4
+ data.tar.gz: 515a98a5715c24359739d76730758b728a9cbf1b8c0cbf2b3c1bb5a355a21c9e
5
5
  SHA512:
6
- metadata.gz: 814f0f4844f94acea113a4eabf1e3afd366b2b00255fe5bcca5ccfccb0f5d862651548302373d078a7c070422d6db6c8cf971f33112c360f0d43f133d500c98a
7
- data.tar.gz: 48f595e34749ec49adeaeb8320c407911f8841d83fcd433cdd5e7e9bc5b6b8f37d01a0f30f6a96610d91949ab8e30e2cb4b0c3f9aa18692447fc31ed6d4b75fb
6
+ metadata.gz: 48115b7a0df0201a24f477ba2f658e692824337a78c0d288afd3c056b42fccaaf065e1e3ab296fa16bda1f2f2eaf82ff1322adcea6d9d6a9f82c2318cea15d98
7
+ data.tar.gz: a7b6dacca6775374b089cc9022462c470d8103d63792c7e7668ccd3e082446b0429a2d54d0e3392694c0e25ea25139916d11bc9f0080659faea6e7eaa0e41541
data/.gitignore CHANGED
@@ -15,3 +15,4 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ .idea
data/CHANGELOG.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  ## Not released
4
4
 
5
+ ## 0.20.0
6
+
7
+ - Change `.first` to not query the API if records have already been retrieved (https://github.com/Beyond-Finance/active_force/pull/73)
8
+ - Bugfix: Transform NULL values for SF Bulk API, which expects "#N/A" (https://github.com/Beyond-Finance/active_force/pull/74)
9
+
5
10
  ## 0.19.0
6
11
 
7
12
  - Bulk API methods. (https://github.com/Beyond-Finance/active_force/pull/65)
@@ -3,6 +3,8 @@ require 'csv'
3
3
  module ActiveForce
4
4
  module Bulk
5
5
  class Records
6
+ NULL_VALUE = '#N/A'.freeze
7
+
6
8
  attr_reader :headers, :data
7
9
  def initialize(headers:, data:)
8
10
  @headers = headers
@@ -16,10 +18,25 @@ module ActiveForce
16
18
  end
17
19
 
18
20
  def self.parse_from_attributes(records)
21
+ # Sorting ensures that the headers line up with the values for the CSV
19
22
  headers = records.first.keys.sort.map(&:to_s)
20
- data = records.map { |r| r.sort.pluck(-1) }
23
+ data = records.map do |r|
24
+ r.transform_values { |v| transform_value_for_sf(v) }.sort.pluck(-1)
25
+ end
21
26
  new(headers: headers, data: data)
22
27
  end
28
+
29
+ # SF expects a special value for setting a column to be NULL.
30
+ def self.transform_value_for_sf(value)
31
+ case value
32
+ when NilClass
33
+ NULL_VALUE
34
+ when Time
35
+ value.iso8601
36
+ else
37
+ value.to_s
38
+ end
39
+ end
23
40
  end
24
41
  end
25
42
  end
@@ -78,7 +78,15 @@ module ActiveForce
78
78
  end
79
79
 
80
80
  def first
81
- limit 1
81
+ if @records
82
+ clone_and_set_instance_variables(
83
+ size: 1,
84
+ records: [@records.first],
85
+ decorated_records: [@decorated_records&.first]
86
+ )
87
+ else
88
+ limit(1)
89
+ end
82
90
  end
83
91
 
84
92
  def last(limit = 1)
@@ -126,9 +134,9 @@ module ActiveForce
126
134
 
127
135
  def clone_and_set_instance_variables instance_variable_hash={}
128
136
  clone = self.clone
129
- clone.instance_variable_set(:@decorated_records, nil)
130
- clone.instance_variable_set(:@records, nil)
131
- instance_variable_hash.each { |k,v| clone.instance_variable_set("@#{k.to_s}", v) }
137
+ { decorated_records: nil, records: nil }
138
+ .merge(instance_variable_hash)
139
+ .each { |k,v| clone.instance_variable_set("@#{k.to_s}", v) }
132
140
  clone
133
141
  end
134
142
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveForce
4
- VERSION = '0.19.0'
4
+ VERSION = '0.20.0'
5
5
  end
@@ -9,11 +9,13 @@ describe ActiveForce::Bulk::Records do
9
9
  %w[value3 value4],
10
10
  ]
11
11
  end
12
+
12
13
  describe '#to_csv' do
13
14
  it 'returns CSV with headers' do
14
15
  expect(subject.to_csv).to eq "header1,header2\nvalue1,value2\nvalue3,value4\n"
15
16
  end
16
17
  end
18
+
17
19
  describe '::parse_from_attributes' do
18
20
  subject { described_class.parse_from_attributes(attributes) }
19
21
  let(:attributes) do
@@ -28,5 +30,25 @@ describe ActiveForce::Bulk::Records do
28
30
  expect(records.headers).to eq headers
29
31
  expect(records.data).to eq data
30
32
  end
33
+
34
+ context 'when there are NULL values' do
35
+ let(:attributes) do
36
+ [
37
+ { header1: nil, header2: 'value2'},
38
+ { header1: 'value3', header2: nil},
39
+ ]
40
+ end
41
+ let(:data) do
42
+ [
43
+ %w[#N/A value2],
44
+ %w[value3 #N/A],
45
+ ]
46
+ end
47
+
48
+ it 'substitutes the expected SF value for NULL' do
49
+ records = subject
50
+ expect(records.data).to eq data
51
+ end
52
+ end
31
53
  end
32
54
  end
@@ -165,6 +165,22 @@ describe ActiveForce::Query do
165
165
  expect(query.to_s).to eq "SELECT Id, name, etc FROM table_name"
166
166
  expect(new_query.to_s).to eq 'SELECT Id, name, etc FROM table_name LIMIT 1'
167
167
  end
168
+
169
+ it "does not query if records have already been fetched" do
170
+ query = ActiveForce::Query.new 'table_name'
171
+ query.instance_variable_set(:@records, %w[foo bar])
172
+ query.instance_variable_set(:@decorated_records, %w[foo bar])
173
+ expect(query).not_to receive(:limit)
174
+ expect(query).to receive(:clone_and_set_instance_variables).with(size: 1, records: ['foo'], decorated_records: ['foo'])
175
+ query.first
176
+ end
177
+
178
+ it 'queries the api if it has not been queried yet' do
179
+ query = ActiveForce::Query.new 'table_name'
180
+ query.instance_variable_set(:@records, nil)
181
+ expect(query).to receive(:limit)
182
+ query.first
183
+ end
168
184
  end
169
185
 
170
186
  describe '.last' do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_force
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.19.0
4
+ version: 0.20.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eloy Espinaco
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2023-11-15 00:00:00.000000000 Z
14
+ date: 2023-11-27 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: activemodel