salesforce_id 1.2.0 → 1.3.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 30c6400e6562285b005c9d9322e4e3784520e0b0
4
- data.tar.gz: ec6108b0f8b16c825870497b17ec4d0271836e85
3
+ metadata.gz: 67c48be6bea0334c903a43a16d85a6a16864723a
4
+ data.tar.gz: d4c4bd69092a3d7de1b166f42d8b4a101fa001e1
5
5
  SHA512:
6
- metadata.gz: a2ab32683c1bd72c0b65ec6346b17c5e884064e4966ff62aaaf1177f79811153966c6bc45f52c937d4cd012c15268a71e9fedf69bbba00bf5b7a07deb024c282
7
- data.tar.gz: 01446cd19d32f632a1a8a99662cab6bee39280a5661f5bf87a427e95ef6f7cd50448d2c04799e9c4a14da130ffc78f7b05acd1b640362d9239752d842f3b1e6e
6
+ metadata.gz: 3008208bc7f80cc57e232be5756a46832240c8ebe91fd8e1a7e577cd5ae113971c3d65886455790b1b5e8a20109178506642b5e80c618f3e586815beeb6ac429
7
+ data.tar.gz: cb40b329f1cf4a559c24d292759deca85eab9cb54b6f1ae093fbe801bf87cee2705fa05d95e749b1746a6db858a189fbf42a20bcd21dc6810281c1c69f8cc3ed
data/.codeclimate.yml ADDED
@@ -0,0 +1,9 @@
1
+ ---
2
+ engines:
3
+ rubocop:
4
+ enabled: true
5
+ ratings:
6
+ paths:
7
+ - "**.rb"
8
+ exclude_paths:
9
+ - spec/**/*
data/README.md CHANGED
@@ -90,6 +90,71 @@ id.to_insensitive # => "003G000001SUbc4IAD"
90
90
  SalesforceId("003G000001SUbc4") == SalesforceId.id("003G000001SUbc4") # => true
91
91
  ```
92
92
 
93
+ ### Test utilities
94
+
95
+ #### SalesforceId::Random
96
+
97
+ A useful utility class to generate random salesforce IDs
98
+
99
+ ```ruby
100
+ # Generate a valid case-sensitive salesforce id
101
+ SalesforceId::Random.sensitive # => 003G000001SUbc4
102
+
103
+ # Generate a valid case-insensitive salesforce id
104
+ SalesforceId::Random.insensitive # => 003G000001SUbc4IAD
105
+
106
+ # Generate an **invalid** case-sensitive salesforce id
107
+ SalesforceId::Random.invalid_sensitive # => 003G0-0001SUbc4
108
+
109
+ # Generate a **invalid** case-insensitive salesforce id where the first 15
110
+ # characters are invalid, not the checksum part
111
+ SalesforceId::Random.insensitive # => 003-000001SUbc4IAD
112
+
113
+ # Generate a **invalid** case-insensitive salesforce id where only the checksum
114
+ # part (last 3 characters) is invalid
115
+ SalesforceId::Random.insensitive # => 003G000001SUbc4I9D
116
+
117
+ # Generate a valid SalesforceId::Safe salesforce id
118
+ SalesforceId::Random.safe # => #<SalesforceId::Safe:0x007f86f2294c50 @value="003G000001SUbc4IAD">
119
+
120
+ # Shorter version to perform `SalesforceId::Random.safe`
121
+ SalesforceId.random # => #<SalesforceId::Safe:0x007f86f2294c50 @value="003G000001SUbc4IAD">
122
+ ```
123
+
124
+ #### RSpec matchers
125
+
126
+ Include `SalesforceId::RSpec` in your tests to get a bunch of salesforce id
127
+ matchers
128
+
129
+ ```ruby
130
+ RSpec.describe SalesforceId("003G000001SUbc4") do
131
+ include ::SalesforceId::RSpec
132
+
133
+ it "is a sensitive salesforce id" do
134
+ expect(subject.to_sensitive).to be_sensitive_salesforce_id # => true
135
+ end
136
+
137
+ it "is an insensitive salesforce id" do
138
+ expect(subject.to_insensitive).to be_insensitive_salesforce_id # => true
139
+ end
140
+
141
+ it "is a salesforce id" do
142
+ is_expected.to be_salesforce_id # => true
143
+ end
144
+
145
+ it "is a salesforce id in safe format (case-sensitive + checksum)" do
146
+ is_expected.to be_safe_salesforce_id # => true
147
+ end
148
+
149
+ end
150
+ ```
151
+
152
+ These tests will pass. Matchers will work with any object that can be converted
153
+ into a string with `to_s`, including `SalesforceId::Safe`.
154
+
155
+ One note on `be_safe_salesforce_id` matcher, it will consider safe **even
156
+ strings** if they are of the correct format (case sensitive + checksum)
157
+
93
158
  ## Documentation
94
159
 
95
160
  Methods are documented in [salesforce_id_ext.h](https://github.com/Fire-Dragon-DoL/salesforce_id/blob/master/ext/salesforce_id/salesforce_id_ext.h), this file is
@@ -9,6 +9,8 @@
9
9
 
10
10
  VALUE rb_mSalesforceId;
11
11
 
12
+ static VALUE VALID_CHARACTERS_to_rb();
13
+
12
14
  void Init_salesforce_id()
13
15
  {
14
16
  // Module
@@ -25,6 +27,11 @@ void Init_salesforce_id()
25
27
  "INSENSITIVE_SIZE",
26
28
  INT2FIX(SALESFORCE_ID_INSENSITIVE_LENGTH)
27
29
  );
30
+ rb_define_const(
31
+ rb_mSalesforceId,
32
+ "VALID_CHARACTERS",
33
+ VALID_CHARACTERS_to_rb()
34
+ );
28
35
 
29
36
  // Methods
30
37
  rb_define_method(
@@ -149,3 +156,25 @@ VALUE salesforce_id_is_insensitive(VALUE self, VALUE rb_sId)
149
156
 
150
157
  return Qfalse;
151
158
  }
159
+
160
+ VALUE VALID_CHARACTERS_to_rb()
161
+ {
162
+ VALUE rb_Chars = Qnil;
163
+
164
+ rb_Chars = rb_ary_new2(VALID_CHARMAP_SIZE);
165
+
166
+ for (long index = 0; index < VALID_CHARMAP_SIZE; ++index)
167
+ {
168
+ char str_Char[2];
169
+ VALUE rb_Char;
170
+
171
+ memset(&str_Char[1], 0, sizeof(str_Char[1]));
172
+ memset(str_Char, VALID_CHARMAP[index], sizeof(str_Char[0]));
173
+
174
+ rb_Char = rb_str_new2(str_Char);
175
+
176
+ rb_ary_store(rb_Chars, index, rb_obj_freeze(rb_Char));
177
+ }
178
+
179
+ return rb_ary_freeze(rb_Chars);
180
+ }
@@ -16,18 +16,20 @@ extern VALUE rb_mSalesforceId;
16
16
  void Init_salesforce_id();
17
17
 
18
18
  /*
19
- * Converts any valid salesforce ID to case-sensitive version. Raises
20
- * ArgumentError if ID contains invalid characters or it's not correct length
19
+ * Converts any valid salesforce ID to case-sensitive version
21
20
  * @param rb_sId [String] valid salesforce id
22
21
  * @return [String] salesforce id in case-sensitive version
22
+ * @raise [ArgumentError] If ID contains invalid characters or it's not correct
23
+ * length
23
24
  */
24
25
  VALUE salesforce_id_to_sensitive(VALUE self, VALUE rb_sId);
25
26
 
26
27
  /*
27
- * Converts any valid salesforce ID to case-insensitive version. Raises
28
- * ArgumentError if ID contains invalid characters or it's not correct length
28
+ * Converts any valid salesforce ID to case-insensitive version
29
29
  * @param rb_sId [String] valid salesforce id
30
30
  * @return [String] salesforce id in case-insensitive version
31
+ * @raise [ArgumentError] If ID contains invalid characters or it's not correct
32
+ * length
31
33
  */
32
34
  VALUE salesforce_id_to_insensitive(VALUE self, VALUE rb_sId);
33
35
 
@@ -47,6 +49,8 @@ VALUE salesforce_id_is_valid(VALUE self, VALUE rb_sId);
47
49
  * @return [String] case-insensitive salesforce id with casing fixed, which
48
50
  * means you can strip the last 3 characters to obtain the case-sensitive
49
51
  * format
52
+ * @raise [ArgumentError] If ID contains invalid characters or it's not correct
53
+ * length
50
54
  */
51
55
  VALUE salesforce_insensitive_repair_casing(VALUE self, VALUE rb_sId);
52
56
 
@@ -6,13 +6,66 @@
6
6
  #include "salesforce_id_ext.h"
7
7
  #include "charmap.h"
8
8
 
9
+ const char VALID_CHARMAP[VALID_CHARMAP_SIZE] = {
10
+ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
11
+ 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
12
+
13
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
14
+ 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
15
+
16
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
17
+ };
18
+
19
+ static bool is_valid_insensitive_id(char* cId);
20
+ static bool is_valid_sensitive_id(char* cId);
21
+ static bool is_valid_char_for_id(char idChar);
22
+
9
23
  // rb_sId MUST be a string
10
24
  bool is_id_valid(VALUE rb_sId)
11
25
  {
12
- VALUE id = rb_sId;
26
+ unsigned long id_size = 0;
27
+ VALUE id = rb_sId;
28
+ char* cId = NULL;
29
+
30
+ id_size = RSTRING_LEN(id);
31
+
32
+ if (id_size != SALESFORCE_ID_SENSITIVE_LENGTH &&
33
+ id_size != SALESFORCE_ID_INSENSITIVE_LENGTH) return false;
34
+
35
+ // XXX: Careful, cId is NOT NULL TERMINATED!
36
+ // Useful because it saves various allocations
37
+ cId = StringValuePtr(rb_sId);
38
+
39
+ if (!is_valid_sensitive_id(cId)) return false;
40
+ if (id_size == SALESFORCE_ID_INSENSITIVE_LENGTH &&
41
+ !is_valid_insensitive_id(cId)) return false;
42
+
43
+ return true;
44
+ }
45
+
46
+ bool is_valid_insensitive_id(char* cId)
47
+ {
48
+ const unsigned long insensitive_size = SALESFORCE_ID_INSENSITIVE_LENGTH;
49
+ unsigned long index = 0;
50
+
51
+ for (index = SALESFORCE_ID_SENSITIVE_LENGTH; index < insensitive_size; ++index)
52
+ if (charmap_index(cId[index]) < 0) return false;
53
+
54
+ return true;
55
+ }
56
+
57
+ bool is_valid_sensitive_id(char* cId)
58
+ {
59
+ for (unsigned long index = 0; index < SALESFORCE_ID_SENSITIVE_LENGTH; ++index)
60
+ if (!is_valid_char_for_id(cId[index])) return false;
13
61
 
14
- if (RSTRING_LEN(id) == SALESFORCE_ID_SENSITIVE_LENGTH) return true;
15
- if (RSTRING_LEN(id) == SALESFORCE_ID_INSENSITIVE_LENGTH) return true;
62
+ return true;
63
+ }
64
+
65
+ bool is_valid_char_for_id(char idChar)
66
+ {
67
+ for (int index = 0; index < VALID_CHARMAP_SIZE; ++index)
68
+ if (VALID_CHARMAP[index] == idChar) return true;
16
69
 
17
70
  return false;
18
71
  }
@@ -4,6 +4,10 @@
4
4
  #include "ruby.h"
5
5
  #include <stdbool.h>
6
6
 
7
+ #define VALID_CHARMAP_SIZE 62
8
+
9
+ extern const char VALID_CHARMAP[VALID_CHARMAP_SIZE];
10
+
7
11
  bool is_id_valid(VALUE rb_sId);
8
12
 
9
13
  #endif /* VALIDATE_SALESFORCE_ID_H */
@@ -0,0 +1,75 @@
1
+ require 'salesforce_id'
2
+
3
+ module ::SalesforceId
4
+
5
+ # Factory for random generation of salesforce ids
6
+ module Random
7
+ extend self
8
+
9
+ # Creates a random salesforce id in case-sensitive format
10
+ # @return [String]
11
+ def sensitive
12
+ id = ""
13
+
14
+ # Fetch samples in this way to allow repetition of values
15
+ ::SalesforceId::SENSITIVE_SIZE.times do
16
+ id << ::SalesforceId::VALID_CHARACTERS.sample
17
+ end
18
+
19
+ id
20
+ end
21
+
22
+ # Creates a random salesforce id in case-insensitive format
23
+ # @return [String]
24
+ def insensitive
25
+ safe.to_insensitive
26
+ end
27
+
28
+ # Create a random salesforce id in case-sensitive format with
29
+ # one invalid character, making it invalid
30
+ # @return [String]
31
+ def invalid_sensitive
32
+ id = sensitive
33
+
34
+ id[rand(id.size)] = '-'
35
+
36
+ id
37
+ end
38
+
39
+ # Create a random salesforce id in case-insensitive format with
40
+ # one **invalid character in the case-sensitive part** (first 15
41
+ # characters), making it invalid
42
+ # @return [String]
43
+ def invalid_insensitive
44
+ id = insensitive
45
+
46
+ id[rand(::SalesforceId::SENSITIVE_SIZE)] = '-'
47
+
48
+ id
49
+ end
50
+
51
+ # Create a random salesforce id in case-insensitive format with
52
+ # one **invalid character in the case-insensitive part** (last 3 characters # from 15 to 18), making it invalid
53
+ # @return [String]
54
+ def invalid_insensitive_checksum
55
+ id = insensitive
56
+ checksum_size = ::SalesforceId::INSENSITIVE_SIZE
57
+ checksum_size -= ::SalesforceId::SENSITIVE_SIZE
58
+
59
+ # Gets a random number between -1 and -3 and set that char to a valid
60
+ # case-sensitive character which is however invalid for case-insensitive
61
+ # id
62
+ id[(-checksum_size) + rand(checksum_size)] = '9'
63
+
64
+ id
65
+ end
66
+
67
+ # Creates a random salesforce id enclosed in {SalesforceId::Safe} object
68
+ # @return [SalesforceId::Safe]
69
+ def safe
70
+ SalesforceId(sensitive)
71
+ end
72
+
73
+ end
74
+
75
+ end
@@ -0,0 +1,16 @@
1
+ require 'salesforce_id'
2
+ require 'salesforce_id/rspec'
3
+ require 'rspec/expectations'
4
+
5
+ module ::SalesforceId::RSpec
6
+
7
+ module BeInsensitiveSalesforceIdMatcher
8
+ extend RSpec::Matchers::DSL
9
+
10
+ matcher :be_insensitive_salesforce_id do
11
+ match { |id| SalesforceId.insensitive?(id) }
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,18 @@
1
+ require 'salesforce_id'
2
+ require 'salesforce_id/rspec'
3
+ require 'rspec/expectations'
4
+
5
+ module ::SalesforceId::RSpec
6
+
7
+ module BeSafeSalesforceIdMatcher
8
+ extend RSpec::Matchers::DSL
9
+
10
+ matcher :be_safe_salesforce_id do
11
+ match do |id|
12
+ SalesforceId.valid?(id) && SalesforceId(id).to_s == id.to_s
13
+ end
14
+ end
15
+
16
+ end
17
+
18
+ end
@@ -0,0 +1,16 @@
1
+ require 'salesforce_id'
2
+ require 'salesforce_id/rspec'
3
+ require 'rspec/expectations'
4
+
5
+ module ::SalesforceId::RSpec
6
+
7
+ module BeSalesforceIdMatcher
8
+ extend RSpec::Matchers::DSL
9
+
10
+ matcher :be_salesforce_id do
11
+ match { |id| SalesforceId.valid?(id) }
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,16 @@
1
+ require 'salesforce_id'
2
+ require 'salesforce_id/rspec'
3
+ require 'rspec/expectations'
4
+
5
+ module ::SalesforceId::RSpec
6
+
7
+ module BeSensitiveSalesforceIdMatcher
8
+ extend RSpec::Matchers::DSL
9
+
10
+ matcher :be_sensitive_salesforce_id do
11
+ match { |id| SalesforceId.sensitive?(id) }
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,16 @@
1
+ require 'salesforce_id'
2
+ require 'salesforce_id/rspec/be_sensitive_salesforce_id_matcher'
3
+ require 'salesforce_id/rspec/be_insensitive_salesforce_id_matcher'
4
+ require 'salesforce_id/rspec/be_salesforce_id_matcher'
5
+ require 'salesforce_id/rspec/be_safe_salesforce_id_matcher'
6
+
7
+ module SalesforceId
8
+
9
+ module RSpec
10
+ include ::SalesforceId::RSpec::BeSensitiveSalesforceIdMatcher
11
+ include ::SalesforceId::RSpec::BeInsensitiveSalesforceIdMatcher
12
+ include ::SalesforceId::RSpec::BeSalesforceIdMatcher
13
+ include ::SalesforceId::RSpec::BeSafeSalesforceIdMatcher
14
+ end
15
+
16
+ end
@@ -26,12 +26,12 @@ module SalesforceId
26
26
  value
27
27
  end
28
28
 
29
- def as_json(*args)
29
+ def as_json(*)
30
30
  to_s
31
31
  end
32
32
 
33
33
  # In JSON format, it's a plain string
34
- def to_json(*args)
34
+ def to_json(*)
35
35
  as_json
36
36
  end
37
37
 
@@ -40,7 +40,7 @@ module SalesforceId
40
40
  # format
41
41
  # @param other [SalesforceId::Safe]
42
42
  def <=>(other)
43
- return nil unless other.kind_of?(self.class)
43
+ return nil unless other.is_a?(self.class)
44
44
 
45
45
  to_s <=> other.to_s
46
46
  end
@@ -1,3 +1,3 @@
1
1
  module SalesforceId
2
- VERSION = "1.2.0"
2
+ VERSION = "1.3.0"
3
3
  end
data/lib/salesforce_id.rb CHANGED
@@ -1,18 +1,61 @@
1
1
  require 'salesforce_id/version'
2
2
  require 'salesforce_id/salesforce_id'
3
3
  require 'salesforce_id/safe'
4
+ require 'salesforce_id/random'
4
5
 
5
6
  module SalesforceId
6
7
  extend self
7
8
 
9
+ # [FixNum] SENSITIVE_SIZE
10
+ # [FixNum] INSENSITIVE_SIZE
11
+ # [Array<String>] VALID_CHARACTERS array of valid characters
12
+ # for salesforce id
13
+
14
+ # to_sensitive
15
+ # @param id [String]
16
+ # @return [String]
17
+
18
+ # to_insensitive
19
+ # @param id [String]
20
+ # @return [String]
21
+
22
+ # valid?
23
+ # @param id [String]
24
+ # @return [Boolean]
25
+
26
+ # repair_casing
27
+ # @param id [String]
28
+ # @return [String]
29
+
30
+ # sensitive?
31
+ # @param id [String]
32
+ # @return [Boolean]
33
+
34
+ # insensitive?
35
+ # @param id [String]
36
+ # @return [Boolean]
37
+
38
+ # Creates a salesforce id based on string
39
+ # @param salesforce_id [#to_s] An object that converts to a valid salesforce
40
+ # id in string format
41
+ # @return [SalesforceId::Safe] the original object if it's already a
42
+ # {SalesforceId::Safe}, otherwise a generated salesforce id
43
+ # @raise [ArgumentError] if passed id is not valid
8
44
  def id(salesforce_id)
9
45
  return salesforce_id if salesforce_id.kind_of?(::SalesforceId::Safe)
10
46
 
11
47
  ::SalesforceId::Safe.new(salesforce_id)
12
48
  end
13
49
 
50
+ # Provides a randomly generated salesforce id using {Salesforce::Random}
51
+ # @return [SalesforceId::Safe]
52
+ def random
53
+ ::SalesforceId::Random.safe
54
+ end
55
+
14
56
  end
15
57
 
58
+ # Shortcut for {SalesforceId#id}
16
59
  def SalesforceId(salesforce_id)
17
60
  SalesforceId.id(salesforce_id)
18
61
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: salesforce_id
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fire-Dragon-DoL
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-10-26 00:00:00.000000000 Z
11
+ date: 2015-10-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -117,6 +117,7 @@ extensions:
117
117
  - ext/salesforce_id/extconf.rb
118
118
  extra_rdoc_files: []
119
119
  files:
120
+ - ".codeclimate.yml"
120
121
  - ".gitignore"
121
122
  - ".rspec"
122
123
  - ".travis.yml"
@@ -150,6 +151,12 @@ files:
150
151
  - ext/salesforce_id/validate_id.c
151
152
  - ext/salesforce_id/validate_id.h
152
153
  - lib/salesforce_id.rb
154
+ - lib/salesforce_id/random.rb
155
+ - lib/salesforce_id/rspec.rb
156
+ - lib/salesforce_id/rspec/be_insensitive_salesforce_id_matcher.rb
157
+ - lib/salesforce_id/rspec/be_safe_salesforce_id_matcher.rb
158
+ - lib/salesforce_id/rspec/be_salesforce_id_matcher.rb
159
+ - lib/salesforce_id/rspec/be_sensitive_salesforce_id_matcher.rb
153
160
  - lib/salesforce_id/safe.rb
154
161
  - lib/salesforce_id/version.rb
155
162
  - salesforce_id.gemspec