usps-imis-api 0.8.0 → 0.9.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
  SHA256:
3
- metadata.gz: 0e1d3316b4676bae03e67aa927632ec91801a6d703c55049c1b11013a20c3e08
4
- data.tar.gz: 8199c664875cc57e995d73b3a96ce03cd9de2e5460e7a451553df3bb5ca3ff84
3
+ metadata.gz: e94dcde6abaf560148b72523c9defe96cd30f6980631f11b79cf8b35f52a1dcc
4
+ data.tar.gz: a94d8ce631656ff48bf6c3b905e3e06bf130a5a658dfad737afec2be21ac1957
5
5
  SHA512:
6
- metadata.gz: 7015ffe22161d1645959004798ed1fde3e65a66db6695dac75ae84db13177a376a37b083f74abdd9092108ba33d9d0f09fcbaaaa845d861d50af237c77c819b2
7
- data.tar.gz: 940e05eeeeea390c67e207f4ace40c6befed6dbe355efdc38e3fa6d270c35f6bf5c48c3093808c505c2b26e9f452000ecd384e250451bc8263cce84d43a78238
6
+ metadata.gz: 1c155ff3c3e0801c4cb1d738c736e7da9833b651ba56cafb5983439d8e7708f15a266f688d40672917270745b198cac6a38e86b735932c447a631b1c5922b17d
7
+ data.tar.gz: e99827b9bb433d673c6d76558c209f23a12aba1dbe22a674d4972f8ff97b0122374cb4ef2955c0b903ebcf5f7d20721c15b800b79cba17c304113436ea8c66a9
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- usps-imis-api (0.8.0)
4
+ usps-imis-api (0.9.0)
5
5
  activesupport (~> 8.0)
6
6
 
7
7
  GEM
data/Readme.md CHANGED
@@ -32,6 +32,10 @@ Usps::Imis.configure do |config|
32
32
  config.imis_id_query_name = ENV['IMIS_ID_QUERY_NAME']
33
33
  config.username = ENV['IMIS_USERNAME']
34
34
  config.password = ENV['IMIS_PASSWORD']
35
+
36
+ # These options will use these defaults
37
+ config.logger = Logger.new($stdout)
38
+ config.logger.level = :info
35
39
  end
36
40
  ```
37
41
 
@@ -120,7 +124,7 @@ To fetch a specific field from member data, run e.g.:
120
124
  tot_mms = api.on('ABC_ASC_Individual_Demog').get_field('TotMMS')
121
125
  ```
122
126
 
123
- You can also access fields directly on the Business Object like a Hash:
127
+ You can also access fields directly on the Business Object or Panel like a Hash:
124
128
 
125
129
  ```ruby
126
130
  tot_mms = api.on('ABC_ASC_Individual_Demog')['TotMMS']
@@ -195,7 +199,15 @@ Run an IQA Query
195
199
  `query_params` is a hash of shape: `{ param_name => param_value }`
196
200
 
197
201
  ```ruby
198
- api.query(query_name, query_params)
202
+ query = api.query(query_name, query_params)
203
+
204
+ query.each do |item|
205
+ # Download all pages of the query, then iterate on the results
206
+ end
207
+
208
+ query.find_each do |item|
209
+ # Iterate one page at a time, fetching new pages automatically
210
+ end
199
211
  ```
200
212
 
201
213
  ### Field Mapper
@@ -229,9 +241,9 @@ vsc.get(1417)
229
241
 
230
242
  # All of these options are identical
231
243
  #
232
- vsc.get(1417, 'Quantity')
244
+ vsc.get(1417, 'Quantity').first
233
245
  vsc.get(1417)['Quantity']
234
- vsc.get[1417, 'Quantity']
246
+ vsc[1417, 'Quantity']
235
247
  vsc.get(1417).raw['Properties']['$values'].find { it['Name'] == 'Quantity' }['Value']['$value']
236
248
  vsc.get_field(1417, 'Quantity')
237
249
 
@@ -244,7 +256,7 @@ created = vsc.create(certificate: 'E136924', year: 2024, count: 42)
244
256
  ordinal = created.ordinal
245
257
  ordinal = created['Ordinal']
246
258
  ordinal = created.raw['Properties']['$values'].find { it['Name'] == 'Ordinal' }['Value']['$value']
247
- ordinal = created.raw['Identity']['IdentityElements']['$values'][1] # Value is duplicated here
259
+ ordinal = created.raw['Identity']['IdentityElements']['$values'][1].to_i # Value is duplicated here
248
260
 
249
261
  vsc.update(certificate: 'E136924', year: 2024, count: 43, ordinal: ordinal)
250
262
 
@@ -314,6 +326,14 @@ end
314
326
  api.with(31092).on('ABC_ASC_Individual_Demog').get_field('TotMMS')
315
327
  ```
316
328
 
329
+ ### Data Methods
330
+
331
+ Data responses from the API can be handled as a standard Hash using the `raw` method.
332
+
333
+ If you need to access all of the property values, you can use the `properties` method.
334
+ By default, this will exclude the `ID` and `Ordinal` properties; they can be included with
335
+ `properties(include_ids: true)`.
336
+
317
337
  ## Test Data Mocking
318
338
 
319
339
  You can use the provided Business Object Mock to generate stub data for rspec:
data/lib/usps/imis/api.rb CHANGED
@@ -3,6 +3,7 @@
3
3
  require_relative 'requests'
4
4
  require_relative 'business_object'
5
5
  require_relative 'mapper'
6
+ require_relative 'query'
6
7
 
7
8
  module Usps
8
9
  module Imis
@@ -15,10 +16,6 @@ module Usps
15
16
  #
16
17
  AUTHENTICATION_PATH = 'Token'
17
18
 
18
- # Endpoint for IQA query requests
19
- #
20
- QUERY_PATH = 'api/Query'
21
-
22
19
  # API bearer token
23
20
  #
24
21
  attr_reader :token
@@ -54,7 +51,7 @@ module Usps
54
51
  def imis_id=(id)
55
52
  raise Errors::LockedIdError if lock_imis_id
56
53
 
57
- @imis_id = id&.to_i&.to_s
54
+ @imis_id = id&.to_i
58
55
  end
59
56
 
60
57
  # Convert a member's certificate number into an iMIS ID number
@@ -67,8 +64,7 @@ module Usps
67
64
  raise Errors::LockedIdError if lock_imis_id
68
65
 
69
66
  begin
70
- result = query(Imis.configuration.imis_id_query_name, { certificate: })
71
- @imis_id = result['Items']['$values'][0]['ID']
67
+ self.imis_id = query(Imis.configuration.imis_id_query_name, { certificate: }).first['ID'].to_i
72
68
  rescue StandardError
73
69
  raise Errors::NotFoundError, 'Member not found'
74
70
  end
@@ -101,7 +97,7 @@ module Usps
101
97
  end
102
98
  end
103
99
 
104
- # Run an IQA Query
100
+ # Build an IQA Query interface
105
101
  #
106
102
  # @param query_name [String] Full path of the query in IQA, e.g. +$/_ABC/Fiander/iMIS_ID+
107
103
  # @query_params [Hash] Conforms to pattern +{ param_name => param_value }+
@@ -109,31 +105,7 @@ module Usps
109
105
  # @return [Hash] Response data from the API
110
106
  #
111
107
  def query(query_name, query_params = {})
112
- query_params[:QueryName] = query_name
113
- path = "#{QUERY_PATH}?#{query_params.to_query}"
114
- uri = URI(File.join(Imis.configuration.hostname, path))
115
- request = Net::HTTP::Get.new(uri)
116
- result = submit(uri, authorize(request))
117
- JSON.parse(result.body)
118
- end
119
-
120
- # Run an IQA Query, paging through all responses
121
- #
122
- # @param query_name [String] Full path of the query in IQA, e.g. +$/_ABC/Fiander/iMIS_ID+
123
- # @query_params [Hash] Conforms to pattern +{ param_name => param_value }+
124
- #
125
- # @return [Array<Hash>] Collected response item values from the API
126
- #
127
- def query_all(query_name, query_params = {})
128
- response = query(query_name, **query_params)
129
- results = response['Items']['$values']
130
-
131
- while response['HasNext']
132
- response = query(query_name, **query_params, Offset: response['NextOffset'])
133
- results += response['Items']['$values']
134
- end
135
-
136
- results
108
+ Query.new(self, query_name, query_params)
137
109
  end
138
110
 
139
111
  # Run requests as DSL, with specific +BusinessObject+ only maintained for this scope
@@ -178,6 +150,8 @@ module Usps
178
150
  # Authenticate to the iMIS API, and store the access token and expiration time
179
151
  #
180
152
  def authenticate
153
+ Imis.logger.debug 'Authenticating with iMIS'
154
+
181
155
  uri = URI(File.join(Imis.configuration.hostname, AUTHENTICATION_PATH))
182
156
  req = Net::HTTP::Post.new(uri)
183
157
  authentication_data = {
@@ -120,7 +120,7 @@ module Usps
120
120
  return CGI.escape(id) unless id.nil?
121
121
  return CGI.escape("~#{api.imis_id}|#{ordinal}") if ordinal
122
122
 
123
- api.imis_id
123
+ api.imis_id.to_s
124
124
  end
125
125
 
126
126
  # Manually assemble the matching data structure, with fields in the correct order
@@ -8,16 +8,19 @@ module Usps
8
8
  IMIS_ROOT_URL_PROD = 'https://portal.americasboatingclub.org'
9
9
  IMIS_ROOT_URL_DEV = 'https://abcdev.imiscloud.com'
10
10
 
11
- attr_accessor :imis_id_query_name, :username, :password
12
- attr_reader :environment
11
+ attr_accessor :imis_id_query_name, :username, :password, :logger
12
+ attr_reader :environment, :logger_level
13
13
 
14
14
  def initialize
15
15
  @environment = defined?(Rails) ? Rails.env : ActiveSupport::StringInquirer.new('development')
16
16
  @imis_id_query_name = ENV.fetch('IMIS_ID_QUERY_NAME', nil)
17
17
  @username = ENV.fetch('IMIS_USERNAME', nil)
18
18
  @password = ENV.fetch('IMIS_PASSWORD', nil)
19
+ @logger = Logger.new($stdout, level: :info)
19
20
 
20
21
  yield self if block_given?
22
+
23
+ @logger_level = logger.class::SEV_LABEL[logger.level].downcase.to_sym
21
24
  end
22
25
 
23
26
  def environment=(env)
@@ -37,7 +40,7 @@ module Usps
37
40
 
38
41
  # Ruby 3.5 instance variable filter
39
42
  #
40
- def instance_variables_to_inspect = %i[@environment @imis_id_query_name @username]
43
+ def instance_variables_to_inspect = %i[@environment @imis_id_query_name @username @logger_level]
41
44
  end
42
45
  end
43
46
  end
@@ -16,14 +16,18 @@ module Usps
16
16
 
17
17
  alias raw to_h
18
18
 
19
+ # The Business Object or Panel name
20
+ #
21
+ def entity = raw['EntityTypeName']
22
+
19
23
  # Access the iMIS ID property
20
24
  #
21
- def imis_id = self['ID']
25
+ def imis_id = self['ID'].to_i
22
26
  alias id imis_id
23
27
 
24
28
  # Access the Ordinal identifier property (if present)
25
29
  #
26
- def ordinal = self['Ordinal']
30
+ def ordinal = self['Ordinal']&.to_i
27
31
 
28
32
  # Access an individual property value by name
29
33
  #
@@ -35,6 +39,17 @@ module Usps
35
39
  value.is_a?(String) ? value : value['$value']
36
40
  end
37
41
 
42
+ # Hash of all property names to values
43
+ #
44
+ # @param include_ids [Boolean] Whether to include the iMIS ID and Ordinal
45
+ #
46
+ def properties(include_ids: false)
47
+ raw['Properties']['$values']
48
+ .map { it['Name'] }
49
+ .select { include_ids || !%w[ID Ordinal].include?(it) }
50
+ .index_with { self[it] }
51
+ end
52
+
38
53
  def inspect
39
54
  stringio = StringIO.new
40
55
  PP.pp(self, stringio)
@@ -42,11 +57,7 @@ module Usps
42
57
  end
43
58
 
44
59
  def pretty_print(pp)
45
- data = {
46
- entity_type_name: raw['EntityTypeName'],
47
- imis_id:,
48
- ordinal:
49
- }.compact
60
+ data = { entity:, imis_id:, ordinal: }.compact
50
61
 
51
62
  pp.group(1, "#<#{self.class}", '>') do
52
63
  data.each do |key, value|
@@ -36,7 +36,7 @@ module Usps
36
36
  #
37
37
  # @param data [Hash] Conforms to pattern +{ field_key => value }+
38
38
  #
39
- # @return [Array<Hash>] Response data from the API for each internal update request
39
+ # @return [Array<Usps::Imis::Data>] Response data from the API for each internal update request
40
40
  #
41
41
  def update(data)
42
42
  updates = data.each_with_object({}) do |(field_key, value), hash|
@@ -54,15 +54,13 @@ module Usps
54
54
  private
55
55
 
56
56
  def map_update(field_name)
57
- if FIELD_MAPPING.key?(field_name.to_sym)
58
- business_object_name, field = FIELD_MAPPING[field_name.to_sym]
59
- yield(business_object_name, field)
60
- else
61
- missing_mapping(field_name)
62
- end
57
+ missing_mapping!(field_name) unless FIELD_MAPPING.key?(field_name.to_sym)
58
+
59
+ business_object_name, field = FIELD_MAPPING[field_name.to_sym]
60
+ yield(business_object_name, field)
63
61
  end
64
62
 
65
- def missing_mapping(field_name)
63
+ def missing_mapping!(field_name)
66
64
  unless ENV['TESTING']
67
65
  # :nocov:
68
66
  warn(
@@ -113,7 +113,7 @@ module Usps
113
113
  'EntityTypeName' => business_object,
114
114
  'IdentityElements' => {
115
115
  '$type' => identity_type,
116
- '$values' => [api.imis_id, ordinal&.to_s].compact
116
+ '$values' => [api.imis_id.to_s, ordinal&.to_s].compact
117
117
  }
118
118
  }
119
119
  end
@@ -124,7 +124,7 @@ module Usps
124
124
  'EntityTypeName' => 'Party',
125
125
  'IdentityElements' => {
126
126
  '$type' => identity_type,
127
- '$values' => [api.imis_id]
127
+ '$values' => [api.imis_id.to_s]
128
128
  }
129
129
  }
130
130
  end
@@ -14,7 +14,7 @@ module Usps
14
14
 
15
15
  def payload(data)
16
16
  build_payload(data) do |props|
17
- props.add 'ID', api.imis_id
17
+ props.add 'ID', api.imis_id.to_s
18
18
  props.add 'Ordinal', data[:ordinal] if data[:ordinal]
19
19
  props.add 'ABC_EDUC_THRU_DATE', data[:thru_date] || '0001-01-01T00:00:00'
20
20
  props.add 'ABC_ECertificate', data[:certificate]
@@ -14,7 +14,7 @@ module Usps
14
14
 
15
15
  def payload(data)
16
16
  build_payload(data) do |props|
17
- props.add 'ID', api.imis_id
17
+ props.add 'ID', api.imis_id.to_s
18
18
  props.add 'Ordinal', data[:ordinal] if data[:ordinal]
19
19
  props.add 'Source_System', 'Manual ITCom Entry'
20
20
  props.add 'ABC_ECertificate', data[:certificate]
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Usps
4
+ module Imis
5
+ # API wrapper for IQA Queries
6
+ #
7
+ class Query
8
+ include Enumerable
9
+ include Requests
10
+
11
+ # Endpoint for IQA query requests
12
+ #
13
+ QUERY_PATH = 'api/Query'
14
+
15
+ # The parent +Api+ object
16
+ #
17
+ attr_reader :api
18
+
19
+ # Name of the Query to run
20
+ #
21
+ attr_reader :query_name
22
+
23
+ # Parameters for the Query
24
+ #
25
+ attr_reader :query_params
26
+
27
+ # Current offset for paging through the Query
28
+ #
29
+ attr_reader :offset
30
+
31
+ # A new instance of +Query+
32
+ #
33
+ # @param api [Api] Parent to use for making requests
34
+ # @param query_name [String] Full path of the query in IQA, e.g. +$/_ABC/Fiander/iMIS_ID+
35
+ # @query_params [Hash] Conforms to pattern +{ param_name => param_value }+
36
+ #
37
+ def initialize(api, query_name, query_params)
38
+ @api = api
39
+ @query_name = query_name
40
+ @query_params = query_params
41
+ end
42
+
43
+ # Iterate through all results from the query
44
+ #
45
+ def each(&)
46
+ Imis.logger.info 'Running IQA Query on iMIS'
47
+
48
+ items = []
49
+ find_each { items << it }
50
+ items.each(&)
51
+ end
52
+
53
+ # Iterate through all results from the query, fetching one page at a time
54
+ #
55
+ def find_each(&)
56
+ result = { 'HasNext' => true }
57
+ count = 0
58
+
59
+ while result['HasNext']
60
+ Imis.logger.info 'Fetching IQA Query page'
61
+
62
+ result = fetch
63
+
64
+ count += result['Count'] || 0
65
+ Imis.logger.info " -> #{count} / #{result['TotalCount']} #{'item'.pluralize(count)}"
66
+ Imis.logger.debug ' -> Query page data:'
67
+ JSON.pretty_generate(result).split("\n").each { Imis.logger.debug " -> #{it}" }
68
+
69
+ items = result['Items']['$values'].map { it.except('$type') }
70
+ @offset = result['NextOffset']
71
+
72
+ items.each(&)
73
+ end
74
+
75
+ nil
76
+ end
77
+
78
+ private
79
+
80
+ def token = api.token
81
+ def token_expiration = api.token_expiration
82
+
83
+ def path = "#{QUERY_PATH}?#{query_params.merge(QueryName: query_name, Offset: offset).to_query}"
84
+ def uri = URI(File.join(Imis.configuration.hostname, path))
85
+ def fetch = JSON.parse(submit(uri, authorize(Net::HTTP::Get.new(uri))).body)
86
+ end
87
+ end
88
+ end
@@ -19,15 +19,29 @@ module Usps
19
19
  # If the current token is missing/expired, request a new one
20
20
  #
21
21
  def authorize(request)
22
- authenticate if token_expiration < Time.now
22
+ if token_expiration < Time.now
23
+ Imis.logger.debug 'Token expired: re-authenticating with iMIS'
24
+ authenticate
25
+ end
23
26
  request.tap { it.add_field('Authorization', "Bearer #{token}") }
24
27
  end
25
28
 
26
29
  def submit(uri, request)
30
+ Imis.logger.info 'Submitting request to iMIS'
31
+ Imis.logger.debug " -> #{uri}"
32
+ sanitized_request_body(request).split("\n").each { Imis.logger.debug " -> #{it}" }
27
33
  client(uri).request(request).tap do |result|
28
34
  raise Errors::ResponseError.from(result) unless result.is_a?(Net::HTTPSuccess)
35
+
36
+ Imis.logger.info 'Request succeeded'
29
37
  end
30
38
  end
39
+
40
+ def sanitized_request_body(request)
41
+ return 'grant_type=password&username=[filtered]&password=[filtered]' if request.body&.include?('password=')
42
+
43
+ request.body.nil? ? '*** empty request body ***' : JSON.pretty_generate(JSON.parse(request.body))
44
+ end
31
45
  end
32
46
  end
33
47
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Usps
4
4
  module Imis
5
- VERSION = '0.8.0'
5
+ VERSION = '0.9.0'
6
6
  end
7
7
  end
data/lib/usps/imis.rb CHANGED
@@ -8,7 +8,9 @@ require 'cgi'
8
8
 
9
9
  require 'active_support/core_ext/string/inflections'
10
10
  require 'active_support/core_ext/object/to_query'
11
+ require 'active_support/core_ext/enumerable'
11
12
  require 'active_support/string_inquirer'
13
+ require 'logger'
12
14
 
13
15
  # Internal requires
14
16
  require_relative 'imis/config'
@@ -39,6 +41,10 @@ module Usps
39
41
  yield(configuration) if block_given?
40
42
  configuration
41
43
  end
44
+
45
+ # Logger instance to write to
46
+ #
47
+ def logger = configuration.logger
42
48
  end
43
49
  end
44
50
  end
@@ -17,13 +17,13 @@ describe Usps::Imis::Api do
17
17
  it 'stores the initial imis_id' do
18
18
  api = described_class.new(imis_id: 42)
19
19
 
20
- expect(api.imis_id).to eq('42')
20
+ expect(api.imis_id).to eq(42)
21
21
  end
22
22
  end
23
23
 
24
24
  describe '#imis_id_for' do
25
25
  it 'gets the iMIS ID' do
26
- expect(api.imis_id_for('E231625')).to eq('31092')
26
+ expect(api.imis_id_for('E231625')).to eq(31092)
27
27
  end
28
28
 
29
29
  context 'with a query error' do
@@ -37,18 +37,18 @@ describe Usps::Imis::Api do
37
37
  end
38
38
  end
39
39
 
40
- describe '#query_all' do
40
+ describe '#query' do
41
+ let(:query) { api.query('$/ABC/ExampleQueryAll', {}) }
42
+
41
43
  before do
42
- allow(api).to receive(:query).and_return(
44
+ allow(query).to receive(:fetch).and_return(
43
45
  { 'Items' => { '$values' => [{ 'key1' => 'value1' }] }, 'HasNext' => true, 'NextOffset' => 1 },
44
46
  { 'Items' => { '$values' => [{ 'key1' => 'value2' }] }, 'HasNext' => false, 'NextOffset' => 0 }
45
47
  )
46
48
  end
47
49
 
48
50
  it 'collects all query results' do
49
- expect(api.query_all('$/ABC/ExampleQueryAll')).to eq(
50
- [{ 'key1' => 'value1' }, { 'key1' => 'value2' }]
51
- )
51
+ expect(query.to_a).to eq([{ 'key1' => 'value1' }, { 'key1' => 'value2' }])
52
52
  end
53
53
  end
54
54
 
@@ -56,9 +56,7 @@ describe Usps::Imis::Api do
56
56
  before { api.imis_id = 31092 }
57
57
 
58
58
  it 'sends an update' do
59
- expect(api.on('ABC_ASC_Individual_Demog').put_fields('TotMMS' => 15)).to(
60
- be_a(Hash)
61
- )
59
+ expect(api.on('ABC_ASC_Individual_Demog').put_fields('TotMMS' => 15)).to be_a(Hash)
62
60
  end
63
61
 
64
62
  context 'when receiving a response error' do
@@ -133,7 +131,7 @@ describe Usps::Imis::Api do
133
131
  end
134
132
 
135
133
  expect(result).to be_a(Hash)
136
- expect(api.imis_id).to eq('31092')
134
+ expect(api.imis_id).to eq(31092)
137
135
  end
138
136
 
139
137
  it 'nests on and with', :aggregate_failures do
@@ -22,9 +22,23 @@ describe Usps::Imis::Data do
22
22
  end
23
23
  end
24
24
 
25
+ describe '#properties' do
26
+ it 'iterates over the properties, excluding IDs' do
27
+ expect(data.properties.map { |field, value| "#{field}: #{value}" }).to eq(
28
+ ['Stub Integer: 42', 'Stub String: something']
29
+ )
30
+ end
31
+
32
+ it 'iterates over the properties, including IDs' do
33
+ expect(data.properties(include_ids: true).map { |field, value| "#{field}: #{value}" }).to eq(
34
+ ['ID: 31092', 'Stub Integer: 42', 'Stub String: something']
35
+ )
36
+ end
37
+ end
38
+
25
39
  describe '#inspect' do
26
40
  it 'generates the correct inspect string' do
27
- expect(data.inspect).to eq('#<Usps::Imis::Data entity_type_name="ABC_ASC_Individual_Demog" imis_id="31092">')
41
+ expect(data.inspect).to eq('#<Usps::Imis::Data entity="ABC_ASC_Individual_Demog" imis_id=31092>')
28
42
  end
29
43
 
30
44
  context 'with data from a Panel' do
@@ -44,7 +58,7 @@ describe Usps::Imis::Data do
44
58
 
45
59
  it 'generates the correct inspect string with an ordinal' do
46
60
  expect(data.inspect).to eq(
47
- '#<Usps::Imis::Data entity_type_name="ABC_ASC_Individual_Demog" imis_id="31092" ordinal="99">'
61
+ '#<Usps::Imis::Data entity="ABC_ASC_Individual_Demog" imis_id=31092 ordinal=99>'
48
62
  )
49
63
  end
50
64
  end
@@ -9,7 +9,7 @@ describe Usps::Imis::Mapper do
9
9
  it 'stores the initial imis_id' do
10
10
  mapper = described_class.new(imis_id: 42)
11
11
 
12
- expect(mapper.api.imis_id).to eq('42')
12
+ expect(mapper.api.imis_id).to eq(42)
13
13
  end
14
14
  end
15
15
 
@@ -64,7 +64,7 @@ describe Usps::Imis::Panels::Education do
64
64
  it 'can initialize with an iMIS ID' do
65
65
  panel = described_class.new(imis_id: 6374)
66
66
 
67
- expect(panel.api.imis_id).to eq('6374')
67
+ expect(panel.api.imis_id).to eq(6374)
68
68
  end
69
69
  end
70
70
  end
data/spec/spec_helper.rb CHANGED
@@ -31,6 +31,8 @@ RSpec.configure do |config|
31
31
 
32
32
  imis_config.username = ENV.fetch('IMIS_USERNAME', '')
33
33
  imis_config.password = ENV.fetch('IMIS_PASSWORD', '')
34
+
35
+ imis_config.logger = Logger.new(nil)
34
36
  end
35
37
  end
36
38
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: usps-imis-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Julian Fiander
@@ -63,6 +63,7 @@ files:
63
63
  - lib/usps/imis/panels/education.rb
64
64
  - lib/usps/imis/panels/vsc.rb
65
65
  - lib/usps/imis/properties.rb
66
+ - lib/usps/imis/query.rb
66
67
  - lib/usps/imis/requests.rb
67
68
  - lib/usps/imis/version.rb
68
69
  - spec/lib/usps/imis/api_spec.rb