reso_transport 1.5.4 → 1.5.9

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: 9d8d276bf6165281a38be1f3eecda4f50c530bb7a2a2d40b2f8382ae44211bf9
4
- data.tar.gz: 2ecab6485d270956e91e5e3278fd46a9c1cd65a8960914dfccf86fa530d4c561
3
+ metadata.gz: 49e97dc43976dfe814ab0bdc7ce7aea16ae5f03e00c94d10d60de3319cb4d388
4
+ data.tar.gz: f15dd31a948a33dbd8008447be68828ba953114214b7633ff8a4628afa2bdfeb
5
5
  SHA512:
6
- metadata.gz: 55b29a0d927e87fa2aef9736bed074b72dfdce04d866ec6b4f1b9f1e4a237d4d7ef44199e19956b45bdf879954f5575e055049adb3b550f80eb10ec2ad42ca10
7
- data.tar.gz: 91366382060311726be58cf26c1439aad63e6fcfb96f1b6044465fdc630bc499d8ef0edcd6c1443d4ce06b0acc881009977584faed9b2bc6ebe3efbcc121bcb4
6
+ metadata.gz: 375f0962243d54dd27b80da550281fbc1a3b2e9a92affc6cb3a00e94104f5be0fddf6b3e1e5e636fc77a557d2a21438427867af8a66b1b18ae4a897c1027d5f1
7
+ data.tar.gz: 272dedeb65d29749ff3abeacb955c900a9e7e7dcf2449b53ab1bf9c6f7b996e84b78773f635868e603cc86eb34812a7e3b88f7e981ae41ce671055ddc9fd02a2
data/.gitignore CHANGED
@@ -13,5 +13,7 @@
13
13
  /log/**
14
14
  /test/vcr_cassettes/**
15
15
  md_cache/**
16
+ ds_cache/**
16
17
  .byebug_history
17
18
  secrets.yml
19
+ /.history/
data/.gitpod.yml ADDED
@@ -0,0 +1,2 @@
1
+ tasks:
2
+ - init: bundle install
data/.rubocop.yml ADDED
@@ -0,0 +1,33 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.6
3
+
4
+ Layout/FirstHashElementIndentation:
5
+ Enabled: false
6
+
7
+ Layout/MultilineMethodCallIndentation:
8
+ Enabled: false
9
+
10
+ Metrics/AbcSize:
11
+ Max: 20
12
+
13
+ Metrics/BlockLength:
14
+ Exclude:
15
+ - test/**/*
16
+
17
+ Metrics/ClassLength:
18
+ Max: 150
19
+
20
+ Metrics/MethodLength:
21
+ Max: 15
22
+
23
+ Metrics/ModuleLength:
24
+ Max: 150
25
+
26
+ Style/ColonMethodCall:
27
+ Enabled: false
28
+
29
+ Style/Documentation:
30
+ Enabled: false
31
+
32
+ Style/FrozenStringLiteralComment:
33
+ Enabled: false
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- reso_transport (1.5.2)
4
+ reso_transport (1.5.5)
5
5
  faraday (~> 1.0.1)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -1,3 +1,6 @@
1
+ [![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/wrstudios/reso_transport)
2
+ [![Gem Version](https://badge.fury.io/rb/reso_transport.svg)](https://badge.fury.io/rb/reso_transport)
3
+
1
4
  # ResoTransport
2
5
 
3
6
  A Ruby gem for connecting to and interacting with RESO WebAPI services. Learn more about what that is by checking out the [RESO WebAPI](https://www.reso.org/reso-web-api/) Documentation.
@@ -51,7 +54,7 @@ Or you can set a logger for each specific instance of a client which can be usef
51
54
 
52
55
  ### Getting Connected
53
56
 
54
- There are 2 strategies for authentication.
57
+ There are 2 strategies for authentication.
55
58
 
56
59
  **Bearer Token**
57
60
 
@@ -60,7 +63,8 @@ It's simple to use a static access token if your token never expires:
60
63
  ```ruby
61
64
  @client = ResoTransport::Client.new({
62
65
  md_file: METADATA_CACHE,
63
- endpoint: ENDPOINT_URL
66
+ endpoint: ENDPOINT_URL,
67
+ use_replication_endpoint: false # this is the default and can be ommitted
64
68
  authentication: {
65
69
  access_token: TOKEN,
66
70
  token_type: "Bearer" # this is the default and can be ommitted
@@ -89,7 +93,13 @@ If the connection requires requesting a new token periodically, it's easy to pro
89
93
 
90
94
  This will pre-fetch a token from the provided endpoint when the current token is either non-existent or has expired.
91
95
 
96
+ The `use_replication_endpoint` flag will append `/replication` to all resource queries if set to `true`. This is required by some data sources to query resources beyond 10,000 records.
92
97
 
98
+ When using this feature, you can retrieve the next link by accessing `next_link` after gettings results:
99
+ ```
100
+ results = @client.resources["Property"].query.results
101
+ next_link = @client.resources["Property"].query.next_link
102
+ ```
93
103
 
94
104
  ### Caching Metadata
95
105
 
@@ -108,9 +118,9 @@ If you don't have access to the file system, like on Heroku, or you just don't w
108
118
 
109
119
  ```ruby
110
120
  class MyCacheStore < ResoTransport::MetadataCache
111
-
121
+
112
122
  def read
113
- # read `name` from somewhere
123
+ # read `name` from somewhere
114
124
  end
115
125
 
116
126
  def write(data)
@@ -158,12 +168,25 @@ Once you have a successful connection you can explore what resources are availab
158
168
  #=> {"Property"=>#<ResoTransport::Resource entity_set="Property", schema="ODataService">, "Office"=>#<ResoTransport::Resource entity_set="Office", schema="ODataService">, "Member"=>#<ResoTransport::Resource entity_set="Member", schema="ODataService">}
159
169
 
160
170
  @client.resources["Property"]
161
- #=> #<ResoTransport::Resource entity_set="Property", schema="ODataService">
171
+ #=> #<ResoTransport::Resource entity_set="Property", schema="ODataService">
162
172
 
163
173
  @client.resources["Property"].query.limit(1).results
164
174
  #=> Results Array
165
175
  ```
166
176
 
177
+ If the resource contains localizations you can access those as well.
178
+
179
+ ```ruby
180
+ @client.resources["Property"].localizations
181
+ #=> {"CommercialSale"=>{"Name"=>"CommercialSale", "ResourcePath"=>"/Property?Class=CommercialSale", "Description"=>"Contains data for Commercial searches.", "DateTimeStamp"=>"2021-05-03T18:13:20.643-07:00"}, "Residential"=>{"Name"=>"Residential", "ResourcePath"=>"/Property?Class=Residential", "Description"=>"Contains data for Residential searches.", "DateTimeStamp"=>"2021-05-03T18:13:20.643-07:00"}}
182
+ ```
183
+
184
+ If a resource contains localizations you must select one by name, before querying, like so:
185
+
186
+ ```ruby
187
+ @client.resources["Property"].localization('Residential').query.limit(1).results
188
+ ```
189
+
167
190
  #### Querying
168
191
 
169
192
  ResoTransport provides powerful querying capabilities:
@@ -196,7 +219,7 @@ To see what child records can be expanded look at `expandable`:
196
219
 
197
220
  ```ruby
198
221
  @resource.expandable
199
- #=> [#<struct ResoTransport::Property name="Media", data_type="Collection(RESO.Media)", attrs={"Name"=>"Media", "Type"=>"Collection(RESO.Media)"}, multi=true, enum=nil, complex_type=nil, entity_type=#<struct ResoTransport::EntityType name="Media", base_type=nil, primary_key="MediaKey", schema="CoreLogic.DataStandard.RESO.DD">> ...]
222
+ #=> [#<struct ResoTransport::Property name="Media", data_type="Collection(RESO.Media)", attrs={"Name"=>"Media", "Type"=>"Collection(RESO.Media)"}, multi=true, enum=nil, complex_type=nil, entity_type=#<struct ResoTransport::EntityType name="Media", base_type=nil, primary_key="MediaKey", schema="CoreLogic.DataStandard.RESO.DD">> ...]
200
223
  ```
201
224
 
202
225
  Use `expand` to expand child records with the top level results.
@@ -210,7 +233,7 @@ You have several options to expand multiple child record sets. Each of these wil
210
233
 
211
234
  ```ruby
212
235
  @resource.query.expand("Media", "Office").limit(10).results
213
-
236
+
214
237
  @resource.query.expand(["Media", "Office"]).limit(10).results
215
238
 
216
239
  @resource.query.expand("Media").expand("Office").limit(10).results
@@ -257,9 +280,22 @@ When querying for an enumeration value, you can provide either the system name,
257
280
 
258
281
  ```ruby
259
282
  @resource.query.eq(StandardStatus: "Active Under Contract").limit(1).compile_params
260
- #=> {"$top"=>1, "$filter"=>"StandardStatus eq 'ActiveUnderContract'"}
283
+ #=> {"$top"=>1, "$filter"=>"StandardStatus eq 'ActiveUnderContract'"}
261
284
  ```
262
285
 
286
+ ### Troubleshooting
287
+
288
+ In the event there are connection issues, the following errors are raised:
289
+
290
+ * `ResoTransport::NoResponse` - The server did not respond to the request
291
+ * `ResoTransport::RequestError` - The server responded with a status code outside the 200 range
292
+ * `ResoTransport::ResponseError` - The server responded with errors in the body
293
+ * `ResoTransport::AccessDenied` - Check your authentication details
294
+ * `ResoTransport::LocalizationRequired` - Provide one of the required localizations through the `localization` method
295
+ * `ResoTransport::EncodeError` - No match was found for one or more of the properties
296
+
297
+ The Faraday Request hash is attached to the error for `NoResponse`, `RequestError`, `ResponseError`, and `AccessDenied`. A Faraday Response is attached on `RequestError`, `ResponseError`, and `AccessDenied`.
298
+
263
299
  ## Development
264
300
 
265
301
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/bin/console CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "reso_transport"
3
+ require 'bundler/setup'
4
+ require 'reso_transport'
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
@@ -12,19 +12,19 @@ require "reso_transport"
12
12
  #
13
13
 
14
14
  ResoTransport.configure do |c|
15
- c.logger = Logger.new("log/console.log")
15
+ c.logger = Logger.new('log/console.log')
16
16
  end
17
17
 
18
-
19
- require "irb"
18
+ require 'irb'
20
19
  require 'yaml'
21
20
  require 'byebug'
22
21
 
23
- SECRETS = YAML.load_file("secrets.yml")
22
+ SECRETS = YAML.load_file('secrets.yml')
24
23
 
25
- @trestle = ResoTransport::Client.new(SECRETS[:trestle].merge(logger: Logger.new($stdout)))
26
- #@bridge = ResoTransport::Client.new(SECRETS[:bridge].merge(logger: Logger.new($stdout)))
27
- # @spark = ResoTransport::Client.new(SECRETS[:spark])
28
- #@crmls = ResoTransport::Client.new(SECRETS[:crmls])
24
+ SECRETS.each do |name, data|
25
+ data[:logger] = Logger.new($stdout)
26
+ client = ResoTransport::Client.new(data)
27
+ instance_variable_set("@#{name}", client)
28
+ end
29
29
 
30
30
  IRB.start(__FILE__)
data/bin/rake ADDED
@@ -0,0 +1,29 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'rake' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "pathname"
12
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
13
+ Pathname.new(__FILE__).realpath)
14
+
15
+ bundle_binstub = File.expand_path("../bundle", __FILE__)
16
+
17
+ if File.file?(bundle_binstub)
18
+ if File.read(bundle_binstub, 300) =~ /This file was generated by Bundler/
19
+ load(bundle_binstub)
20
+ else
21
+ abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
22
+ Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
23
+ end
24
+ end
25
+
26
+ require "rubygems"
27
+ require "bundler/setup"
28
+
29
+ load Gem.bin_path("rake", "rake")
@@ -1,48 +1,71 @@
1
1
  module ResoTransport
2
2
  module Authentication
3
3
  class FetchTokenAuth < AuthStrategy
4
- attr_reader :connection, :endpoint, :client_id, :client_secret, :grant_type, :scope
5
-
4
+ attr_reader :endpoint,
5
+ :client_id,
6
+ :client_secret,
7
+ :grant_type,
8
+ :scope,
9
+ :username,
10
+ :password
11
+
6
12
  def initialize(options)
7
- @grant_type = options.fetch(:grant_type, "client_credentials")
8
- @scope = options.fetch(:scope, "api")
13
+ super()
14
+
15
+ @grant_type = options.fetch(:grant_type, 'client_credentials')
16
+ @scope = options.fetch(:scope, 'api')
9
17
  @client_id = options.fetch(:client_id)
10
18
  @client_secret = options.fetch(:client_secret)
11
19
  @endpoint = options.fetch(:endpoint)
20
+ @username = options.fetch(:username, nil)
21
+ @password = options.fetch(:password, nil)
22
+ @request = nil
23
+ end
12
24
 
13
- @connection = Faraday.new(@endpoint) do |faraday|
25
+ def connection
26
+ @connection ||= Faraday.new(@endpoint) do |faraday|
14
27
  faraday.request :url_encoded
15
28
  faraday.response :logger, ResoTransport.configuration.logger if ResoTransport.configuration.logger
16
29
  faraday.adapter Faraday.default_adapter
17
- faraday.basic_auth @client_id, @client_secret
30
+ faraday.basic_auth client_id, client_secret
18
31
  end
19
32
  end
20
33
 
21
34
  def authenticate
22
- response = connection.post nil, auth_params
35
+ response = connection.post(nil, auth_params { |req| @request = req })
23
36
  json = JSON.parse response.body
24
37
 
25
- unless response.success?
26
- message = "#{response.reason_phrase}: #{json['error'] || response.body}"
27
- raise ResoTransport::AccessDenied, response: response, message: message
28
- end
38
+ raise AccessDenied.new(request, response, 'token') unless response.success?
29
39
 
30
40
  Access.new({
31
41
  access_token: json.fetch('access_token'),
32
42
  expires_in: json.fetch('expires_in', 1 << (1.size * 8 - 2) - 1),
33
- token_type: json.fetch('token_type', "Bearer")
43
+ token_type: json.fetch('token_type', 'Bearer')
34
44
  })
35
45
  end
36
46
 
47
+ def request
48
+ return @request.to_h if @request.respond_to? :to_h
49
+
50
+ {}
51
+ end
52
+
37
53
  private
38
54
 
39
55
  def auth_params
40
- {
41
- client_id: client_id,
56
+ params = {
57
+ client_id: client_id,
42
58
  client_secret: client_secret,
43
- grant_type: grant_type,
44
- scope: scope
59
+ grant_type: grant_type,
60
+ scope: scope
45
61
  }
62
+
63
+ if grant_type == 'password'
64
+ params[:username] = username
65
+ params[:password] = password
66
+ end
67
+
68
+ params
46
69
  end
47
70
  end
48
71
  end
@@ -18,10 +18,11 @@ module ResoTransport
18
18
  authorize_request(request_env)
19
19
 
20
20
  @app.call(request_env).on_complete do |response_env|
21
- raise_if_unauthorized(response_env)
21
+ raise_if_unauthorized(request_env, response_env)
22
22
  end
23
23
  rescue ResoTransport::AccessDenied
24
- raise if retries == 0
24
+ raise if retries.zero?
25
+
25
26
  @auth.reset
26
27
  retries -= 1
27
28
  retry
@@ -38,8 +39,8 @@ module ResoTransport
38
39
  )
39
40
  end
40
41
 
41
- def raise_if_unauthorized(response_env)
42
- raise ResoTransport::AccessDenied if response_env[:status] == 401
42
+ def raise_if_unauthorized(request_env, response_env)
43
+ raise ResoTransport::AccessDenied.new(request_env.to_h, response_env) if response_env[:status] == 401
43
44
  end
44
45
  end
45
46
  end
@@ -0,0 +1,64 @@
1
+ module ResoTransport
2
+ class BaseMetadata
3
+ MIME_TYPES = {
4
+ xml: 'application/xml',
5
+ json: 'application/json'
6
+ }.freeze
7
+
8
+ attr_reader :client
9
+
10
+ def initialize(client)
11
+ @client = client
12
+ @prefix = nil
13
+ @classname = nil
14
+ end
15
+
16
+ def prefix
17
+ raise 'prefix not set' unless @prefix
18
+
19
+ @prefix
20
+ end
21
+
22
+ def classname
23
+ raise 'classname not set' unless @classname
24
+
25
+ @classname
26
+ end
27
+
28
+ def parser
29
+ @parser ||= Object::const_get("#{classname}Parser").new.parse(data)
30
+ end
31
+
32
+ def data
33
+ if cache_file
34
+ cache.read || cache.write(raw)
35
+ else
36
+ raw
37
+ end
38
+ end
39
+
40
+ def cache
41
+ @cache ||= client.send("#{prefix}_cache").new(cache_file)
42
+ end
43
+
44
+ def cache_file
45
+ @cache_file ||= client.send "#{prefix}_file"
46
+ end
47
+
48
+ def raw
49
+ return response.body if response.success?
50
+
51
+ raise RequestError.new(request, response, classname)
52
+ end
53
+
54
+ def response
55
+ raise 'Must implement response method'
56
+ end
57
+
58
+ def request
59
+ return @request.to_h if @request.respond_to? :to_h
60
+
61
+ {}
62
+ end
63
+ end
64
+ end
@@ -1,35 +1,52 @@
1
1
  module ResoTransport
2
2
  class Client
3
- attr_reader :connection, :uid, :vendor, :endpoint, :auth, :md_file, :md_cache
4
-
3
+ attr_reader :connection, :uid, :vendor, :endpoint, :authentication, :md_file, :md_cache, :ds_file, :ds_cache,
4
+ :use_replication_endpoint
5
+
5
6
  def initialize(options)
6
- @endpoint = options.fetch(:endpoint)
7
- @md_file = options.fetch(:md_file, nil)
8
- @authentication = ensure_valid_auth_strategy(options.fetch(:authentication))
9
- @vendor = options.fetch(:vendor, {})
10
- @faraday_options = options.fetch(:faraday_options, {})
11
- @logger = options.fetch(:logger, nil)
12
- @md_cache = options.fetch(:md_cache, ResoTransport::MetadataCache)
13
-
14
- @connection = Faraday.new(@endpoint, @faraday_options) do |faraday|
7
+ @use_replication_endpoint = options.fetch(:use_replication_endpoint, false)
8
+ @endpoint = options.fetch(:endpoint)
9
+ @md_file = options.fetch(:md_file, nil)
10
+ @ds_file = options.fetch(:ds_file, nil)
11
+ @authentication = ensure_valid_auth_strategy(options.fetch(:authentication))
12
+ @vendor = options.fetch(:vendor, {})
13
+ @faraday_options = options.fetch(:faraday_options, {})
14
+ @logger = options.fetch(:logger, nil)
15
+ @md_cache = options.fetch(:md_cache, ResoTransport::MetadataCache)
16
+ @ds_cache = options.fetch(:ds_cache, ResoTransport::MetadataCache)
17
+ @connection = establish_connection
18
+ end
19
+
20
+ def establish_connection
21
+ Faraday.new(@endpoint, @faraday_options) do |faraday|
15
22
  faraday.request :url_encoded
16
23
  faraday.response :logger, @logger || ResoTransport.configuration.logger
17
- #yield faraday if block_given?
18
24
  faraday.use Authentication::Middleware, @authentication
19
- faraday.adapter Faraday.default_adapter #unless faraday.builder.send(:adapter_set?)
25
+ faraday.adapter Faraday.default_adapter # unless faraday.builder.send(:adapter_set?)
20
26
  end
21
27
  end
22
28
 
23
29
  def resources
24
- @resources ||= metadata.entity_sets.map {|es| {es.name => Resource.new(self, es)} }.reduce(:merge!)
30
+ @resources ||= metadata.entity_sets.map { |es| { es.name => resource_for(es) } }.reduce(:merge!)
31
+ end
32
+
33
+ def resource_for(entity_set)
34
+ localizations = {}
35
+ localizations = datasystem.localizations_for(entity_set.entity_type) if metadata.datasystem?
36
+
37
+ Resource.new(self, entity_set, localizations)
25
38
  end
26
39
 
27
40
  def metadata
28
41
  @metadata ||= Metadata.new(self)
29
42
  end
30
43
 
44
+ def datasystem
45
+ @datasystem ||= Datasystem.new(self)
46
+ end
47
+
31
48
  def to_s
32
- %(#<ResoTransport::Client endpoint="#{endpoint}", md_file="#{md_file}">)
49
+ %(#<ResoTransport::Client endpoint="#{endpoint}", md_file="#{md_file}", ds_file="#{ds_file}">)
33
50
  end
34
51
 
35
52
  def inspect
@@ -41,7 +58,7 @@ module ResoTransport
41
58
  def ensure_valid_auth_strategy(options)
42
59
  case options
43
60
  when Hash
44
- if options.has_key?(:endpoint)
61
+ if options.key?(:endpoint)
45
62
  Authentication::FetchTokenAuth.new(options)
46
63
  else
47
64
  Authentication::StaticTokenAuth.new(options)
@@ -50,6 +67,5 @@ module ResoTransport
50
67
  raise ArgumentError, "#{options.inspect} invalid: cannot determine strategy"
51
68
  end
52
69
  end
53
-
54
70
  end
55
71
  end
@@ -0,0 +1,25 @@
1
+ require_relative 'base_metadata'
2
+
3
+ module ResoTransport
4
+ class Datasystem < BaseMetadata
5
+ def initialize(client)
6
+ super client
7
+ @prefix = 'ds'
8
+ @classname = self.class.name
9
+ end
10
+
11
+ def localizations_for(resource_name)
12
+ localizations = parser.resources.dig(resource_name, 'Localizations') || []
13
+ localizations.map { |l| [l['Name'], l] }.to_h
14
+ end
15
+
16
+ def response
17
+ @response ||= client.connection.get('DataSystem') do |req|
18
+ req.headers['Accept'] = 'application/json'
19
+ @request = req
20
+ end
21
+ rescue Faraday::ConnectionFailed
22
+ raise NoResponse.new(request, nil, 'DataSystem')
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,26 @@
1
+ module ResoTransport
2
+ class DatasystemParser
3
+ def parse(doc)
4
+ begin
5
+ data = doc.is_a?(File) ? doc.read : doc
6
+ @json = JSON.parse data
7
+ rescue JSON::ParserError => e
8
+ @json = {}
9
+ puts e.message
10
+ end
11
+ self
12
+ end
13
+
14
+ # value ->
15
+ # Resources ->
16
+ # Name ->
17
+ # ResourcePath ->
18
+ # Localizations ->
19
+ # Name ->
20
+ # ResourcePath ->
21
+
22
+ def resources
23
+ @resources ||= @json['value'].map { |v| v['Resources'] }.flatten.compact.map { |r| [r['Name'], r] }.to_h
24
+ end
25
+ end
26
+ end
@@ -1,11 +1,9 @@
1
1
  module ResoTransport
2
2
  EntitySet = Struct.new(:name, :schema, :entity_type) do
3
-
4
3
  def self.from_stream(args)
5
- schema, entity_type = ResoTransport.split_schema_and_class_name(args["EntityType"])
4
+ schema, entity_type = ResoTransport.split_schema_and_class_name(args['EntityType'])
6
5
 
7
- new(args["Name"], schema, entity_type)
6
+ new(args['Name'], schema, entity_type)
8
7
  end
9
-
10
8
  end
11
9
  end
@@ -1,30 +1,29 @@
1
1
  module ResoTransport
2
2
  EntityType = Struct.new(:name, :base_type, :primary_key, :schema) do
3
-
4
3
  def self.from_stream(args)
5
- new(args["Name"], args["BaseType"])
4
+ new(args['Name'], args['BaseType'])
6
5
  end
7
6
 
8
7
  def parse(record)
9
- record.each_pair do |k,v|
8
+ record.each_pair do |k, v|
10
9
  next if v.nil?
11
- if property = (property_map[k] || navigation_property_map[k])
12
- record[k] = property.parse(v)
13
- end
10
+
11
+ property = property_map[k] || navigation_property_map[k]
12
+ record[k] = property.parse(v) if property
14
13
  end
15
14
  end
16
15
 
17
16
  def parse_value(record)
18
- record.each_pair do |k,v|
17
+ record.each_pair do |k, v|
19
18
  next if v.nil?
20
- if property = (property_map[k] || navigation_property_map[k])
21
- record[k] = property.parse(v)
22
- end
19
+
20
+ property = property_map[k] || navigation_property_map[k]
21
+ record[k] = property.parse(v) if property
23
22
  end
24
23
  end
25
24
 
26
25
  def property_map
27
- @property_map ||= properties.inject({}) {|hsh, p| hsh[p.name] = p; hsh }
26
+ @property_map ||= properties.each_with_object({}) { |p, hsh| hsh[p.name] = p; }
28
27
  end
29
28
 
30
29
  def properties
@@ -32,7 +31,7 @@ module ResoTransport
32
31
  end
33
32
 
34
33
  def navigation_property_map
35
- @navigation_property_map ||= navigation_properties.inject({}) {|hsh, p| hsh[p.name] = p; hsh }
34
+ @navigation_property_map ||= navigation_properties.each_with_object({}) { |p, hsh| hsh[p.name] = p; }
36
35
  end
37
36
 
38
37
  def navigation_properties
@@ -42,6 +41,5 @@ module ResoTransport
42
41
  def enumerations
43
42
  @enumerations ||= []
44
43
  end
45
-
46
44
  end
47
45
  end