justimmo_client 0.4.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 +7 -0
- data/.editorconfig +15 -0
- data/.gitignore +15 -0
- data/.gitlab-ci.yml +67 -0
- data/.rspec +2 -0
- data/.rubocop.yml +90 -0
- data/.ruby-version +1 -0
- data/Gemfile +21 -0
- data/LICENSE +21 -0
- data/README.md +72 -0
- data/Rakefile +14 -0
- data/bin/console +21 -0
- data/bin/setup +8 -0
- data/examples/client.rb +16 -0
- data/justimmo_client.gemspec +41 -0
- data/lib/justimmo_client/api/v1/models/city.rb +16 -0
- data/lib/justimmo_client/api/v1/models/country.rb +44 -0
- data/lib/justimmo_client/api/v1/models/employee.rb +45 -0
- data/lib/justimmo_client/api/v1/models/federal_state.rb +15 -0
- data/lib/justimmo_client/api/v1/models/file.rb +64 -0
- data/lib/justimmo_client/api/v1/models/geo_location.rb +47 -0
- data/lib/justimmo_client/api/v1/models/image.rb +10 -0
- data/lib/justimmo_client/api/v1/models/justimmo_base.rb +15 -0
- data/lib/justimmo_client/api/v1/models/realty.rb +82 -0
- data/lib/justimmo_client/api/v1/models/realty_area.rb +49 -0
- data/lib/justimmo_client/api/v1/models/realty_category.rb +13 -0
- data/lib/justimmo_client/api/v1/models/realty_marketing.rb +12 -0
- data/lib/justimmo_client/api/v1/models/realty_price.rb +94 -0
- data/lib/justimmo_client/api/v1/models/realty_room_count.rb +35 -0
- data/lib/justimmo_client/api/v1/models/realty_type.rb +12 -0
- data/lib/justimmo_client/api/v1/models/realty_usage.rb +24 -0
- data/lib/justimmo_client/api/v1/models/region.rb +12 -0
- data/lib/justimmo_client/api/v1/representers/json/attachment_image_representer.rb +16 -0
- data/lib/justimmo_client/api/v1/representers/json/attachment_representer.rb +15 -0
- data/lib/justimmo_client/api/v1/representers/json/contact_representer.rb +30 -0
- data/lib/justimmo_client/api/v1/representers/json/justimmo_representer.rb +13 -0
- data/lib/justimmo_client/api/v1/representers/json/location_representer.rb +14 -0
- data/lib/justimmo_client/api/v1/representers/json/realty_category_representer.rb +21 -0
- data/lib/justimmo_client/api/v1/representers/json/realty_detail_representer.rb +69 -0
- data/lib/justimmo_client/api/v1/representers/json.rb +10 -0
- data/lib/justimmo_client/api/v1/representers/xml/city_representer.rb +18 -0
- data/lib/justimmo_client/api/v1/representers/xml/contact_representer.rb +15 -0
- data/lib/justimmo_client/api/v1/representers/xml/country_representer.rb +15 -0
- data/lib/justimmo_client/api/v1/representers/xml/employee_list_representer.rb +15 -0
- data/lib/justimmo_client/api/v1/representers/xml/employee_representer.rb +46 -0
- data/lib/justimmo_client/api/v1/representers/xml/federal_state_representer.rb +17 -0
- data/lib/justimmo_client/api/v1/representers/xml/geo_location_representer.rb +24 -0
- data/lib/justimmo_client/api/v1/representers/xml/justimmo_representer.rb +13 -0
- data/lib/justimmo_client/api/v1/representers/xml/realty_area_representer.rb +28 -0
- data/lib/justimmo_client/api/v1/representers/xml/realty_category_representer.rb +15 -0
- data/lib/justimmo_client/api/v1/representers/xml/realty_detail_representer.rb +92 -0
- data/lib/justimmo_client/api/v1/representers/xml/realty_list_representer.rb +85 -0
- data/lib/justimmo_client/api/v1/representers/xml/realty_price_representer.rb +53 -0
- data/lib/justimmo_client/api/v1/representers/xml/realty_representer.rb +32 -0
- data/lib/justimmo_client/api/v1/representers/xml/realty_room_count_representer.rb +22 -0
- data/lib/justimmo_client/api/v1/representers/xml/realty_type_representer.rb +14 -0
- data/lib/justimmo_client/api/v1/representers/xml/region_representer.rb +14 -0
- data/lib/justimmo_client/api/v1/representers/xml.rb +11 -0
- data/lib/justimmo_client/api/v1/requests/employee_request.rb +24 -0
- data/lib/justimmo_client/api/v1/requests/justimmo_request.rb +64 -0
- data/lib/justimmo_client/api/v1/requests/realty_request.rb +209 -0
- data/lib/justimmo_client/api/v1.rb +16 -0
- data/lib/justimmo_client/autoload.rb +17 -0
- data/lib/justimmo_client/core/caching.rb +55 -0
- data/lib/justimmo_client/core/config.rb +46 -0
- data/lib/justimmo_client/core/logging.rb +46 -0
- data/lib/justimmo_client/core/utils.rb +38 -0
- data/lib/justimmo_client/employee.rb +39 -0
- data/lib/justimmo_client/errors.rb +58 -0
- data/lib/justimmo_client/misc.rb +10 -0
- data/lib/justimmo_client/option_parser.rb +107 -0
- data/lib/justimmo_client/realty.rb +150 -0
- data/lib/justimmo_client/version.rb +5 -0
- data/lib/justimmo_client.rb +22 -0
- data/notes.md +19 -0
- metadata +271 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module JustimmoClient::V1
|
|
4
|
+
# @api private
|
|
5
|
+
module RealtyRequest
|
|
6
|
+
extend JustimmoRequest
|
|
7
|
+
|
|
8
|
+
# Mappings for the option parser
|
|
9
|
+
TRANSLATION_MAPPING = {
|
|
10
|
+
limit: :Limit,
|
|
11
|
+
offset: :Offset,
|
|
12
|
+
lang: :culture,
|
|
13
|
+
with_projects: :alleProjektObjekte,
|
|
14
|
+
number: :objektnummer,
|
|
15
|
+
price: :preis,
|
|
16
|
+
zip_code: :plz,
|
|
17
|
+
price_per_sqm: :preis_per_m2,
|
|
18
|
+
type: :objektart,
|
|
19
|
+
subtype: :subobjektart,
|
|
20
|
+
tag: :tagname,
|
|
21
|
+
room_count: :zimmer,
|
|
22
|
+
area: :flaeche,
|
|
23
|
+
living_area: :wohnflaeche,
|
|
24
|
+
floor_area: :nutzflaeche,
|
|
25
|
+
surface_area: :grundflaeche,
|
|
26
|
+
keyword: :stichwort,
|
|
27
|
+
country: :land,
|
|
28
|
+
federal_state: :bundesland,
|
|
29
|
+
small_undbanded: :small,
|
|
30
|
+
small2_unbranded: :s220x155,
|
|
31
|
+
small3_unbranded: :s312x208,
|
|
32
|
+
id: :objekt_id,
|
|
33
|
+
salutation: :anrede,
|
|
34
|
+
title: :titel,
|
|
35
|
+
first_name: :vorname,
|
|
36
|
+
last_name: :nachname,
|
|
37
|
+
phone: :tel,
|
|
38
|
+
location: :ort,
|
|
39
|
+
all: :alle
|
|
40
|
+
}.freeze
|
|
41
|
+
|
|
42
|
+
module_function
|
|
43
|
+
|
|
44
|
+
# @!group Realty Requests
|
|
45
|
+
|
|
46
|
+
# @param [Hash] params
|
|
47
|
+
# @return [String] The requested XML.
|
|
48
|
+
def list(**params)
|
|
49
|
+
get("objekt/list", list_option_parser.parse(params))
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# @param [Integer] id
|
|
53
|
+
# @param [String, Symbol] lang
|
|
54
|
+
# @return [String] The requested XML.
|
|
55
|
+
def detail(id, lang: nil)
|
|
56
|
+
get("objekt/detail", detail_option_parser.parse(id: id, lang: lang))
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# @param [Integer] id
|
|
60
|
+
# @param [Hash] params
|
|
61
|
+
# @return [String] The requested XML.
|
|
62
|
+
def inquiry(id, **params)
|
|
63
|
+
get("objekt/anfrage", inquiry_option_parser.parse(params.update(id: id)))
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
# @param [Hash] params
|
|
67
|
+
# @return [String] A JSON string containing an array of ids.
|
|
68
|
+
def ids(**params)
|
|
69
|
+
get("objekt/ids", ids_option_parser.parse(params))
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# @todo implement this
|
|
73
|
+
# @param [Hash] params
|
|
74
|
+
# @return [File] The PDF file.
|
|
75
|
+
def expose(**params)
|
|
76
|
+
get("objekt/expose", params)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
# @!group Basic Data Requests
|
|
80
|
+
|
|
81
|
+
# @param [Boolean] all (false)
|
|
82
|
+
# @return [String] The requested XML.
|
|
83
|
+
def categories(all: false)
|
|
84
|
+
get("objekt/kategorien", alle: all ? 1 : 0)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
# @param [Boolean] all (false)
|
|
88
|
+
# @return [String] The requested XML.
|
|
89
|
+
def types(all: false)
|
|
90
|
+
get("objekt/objektarten", alle: all ? 1 : 0)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# @param [Boolean] all (false)
|
|
94
|
+
# @return [String] The requested XML.
|
|
95
|
+
def countries(all: false)
|
|
96
|
+
get("objekt/laender", alle: all ? 1 : 0)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
# @param [Boolean] all (false)
|
|
100
|
+
# @param [Integer, String] country
|
|
101
|
+
# @return [String] The requested XML.
|
|
102
|
+
def federal_states(country:, all: false)
|
|
103
|
+
get("objekt/bundeslaender", land: country, alle: all ? 1 : 0)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# @param [Boolean] all (false)
|
|
107
|
+
# @param [Integer, String] country
|
|
108
|
+
# @param [Integer] federal_state
|
|
109
|
+
# @return [String] The requested XML.
|
|
110
|
+
def regions(country: nil, federal_state: nil, all: false)
|
|
111
|
+
get("objekt/regionen", land: country, bundesland: federal_state, alle: all ? 1 : 0)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
# @param [Boolean] all (false)
|
|
115
|
+
# @param [Integer, String] country
|
|
116
|
+
# @param [Integer] federal_state
|
|
117
|
+
# @return [String] The requested XML.
|
|
118
|
+
def zip_codes_and_cities(country: nil, federal_state: nil, all: false)
|
|
119
|
+
get("objekt/plzsUndOrte", land: country, bundesland: federal_state, alle: all ? 1 : 0)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# @!group Option Parsers
|
|
123
|
+
|
|
124
|
+
# @return [Hash]
|
|
125
|
+
def list_option_parser
|
|
126
|
+
@option_parsers ||= {}
|
|
127
|
+
@option_parsers[:list] ||= JustimmoClient::OptionParser.new do |options|
|
|
128
|
+
options.mappings = TRANSLATION_MAPPING
|
|
129
|
+
options.range_suffix = %i[_von _bis]
|
|
130
|
+
|
|
131
|
+
options.add :limit
|
|
132
|
+
options.add :offset
|
|
133
|
+
options.add :lang
|
|
134
|
+
options.add :orderby, values: %w[price zip_code number created_at updated_at published_at]
|
|
135
|
+
options.add :ordertype, values: %w[asc desc]
|
|
136
|
+
options.add :picturesize, values: %w[small_unbranded small2_unbranded small3_unbranded medium_unbranded big_unbranded big2_unbranded medium big bin2]
|
|
137
|
+
options.add :with_projects, type: :bool
|
|
138
|
+
options.group :filter do |f|
|
|
139
|
+
f.add :price_min
|
|
140
|
+
f.add :price_max
|
|
141
|
+
f.add :price_per_sqm_min
|
|
142
|
+
f.add :price_per_sqm_max
|
|
143
|
+
f.add :type_id
|
|
144
|
+
f.add :subtype_id
|
|
145
|
+
f.add :tag
|
|
146
|
+
f.add :zip_code
|
|
147
|
+
f.add :zip_code_min
|
|
148
|
+
f.add :zip_code_max
|
|
149
|
+
f.add :room_count_min
|
|
150
|
+
f.add :room_count_max
|
|
151
|
+
f.add :number
|
|
152
|
+
f.add :number_min
|
|
153
|
+
f.add :number_max
|
|
154
|
+
f.add :area_min
|
|
155
|
+
f.add :area_max
|
|
156
|
+
f.add :living_area_min
|
|
157
|
+
f.add :living_area_max
|
|
158
|
+
f.add :floor_area_min
|
|
159
|
+
f.add :floor_area_max
|
|
160
|
+
f.add :surface_area_min
|
|
161
|
+
f.add :surface_area_max
|
|
162
|
+
f.add :keyword
|
|
163
|
+
f.add :country_id
|
|
164
|
+
f.add :federal_state_id
|
|
165
|
+
f.add :status_id
|
|
166
|
+
f.add :project_id
|
|
167
|
+
f.add :type
|
|
168
|
+
f.add :parent_id
|
|
169
|
+
f.add :updated_at_min, as: :aktualisiert_am_von
|
|
170
|
+
f.add :updated_at_max, as: :aktualisiert_am_bis
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
alias ids_option_parser list_option_parser
|
|
176
|
+
|
|
177
|
+
# @return [Hash]
|
|
178
|
+
def inquiry_option_parser
|
|
179
|
+
@option_parsers ||= {}
|
|
180
|
+
@option_parsers[:inquiry] = JustimmoClient::OptionParser.new do |options|
|
|
181
|
+
options.mappings = TRANSLATION_MAPPING
|
|
182
|
+
options.range_suffix = %i[_von _bis]
|
|
183
|
+
|
|
184
|
+
options.add :salutation_id
|
|
185
|
+
options.add :title
|
|
186
|
+
options.add :first_name
|
|
187
|
+
options.add :last_name
|
|
188
|
+
options.add :email
|
|
189
|
+
options.add :phone
|
|
190
|
+
options.add :message
|
|
191
|
+
options.add :street
|
|
192
|
+
options.add :zip_code
|
|
193
|
+
options.add :location
|
|
194
|
+
options.add :country
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
# @return [Hash]
|
|
199
|
+
def detail_option_parser
|
|
200
|
+
@option_parsers ||= {}
|
|
201
|
+
@option_parsers[:detail] = JustimmoClient::OptionParser.new do |options|
|
|
202
|
+
options.mappings = TRANSLATION_MAPPING
|
|
203
|
+
|
|
204
|
+
options.add :all
|
|
205
|
+
options.add :lang
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
end
|
|
209
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "justimmo_client/autoload"
|
|
4
|
+
|
|
5
|
+
module JustimmoClient
|
|
6
|
+
# Version 1 of the API
|
|
7
|
+
module V1
|
|
8
|
+
extend JustimmoClient::Utils
|
|
9
|
+
|
|
10
|
+
API_PATH = "#{__dir__}/v1"
|
|
11
|
+
|
|
12
|
+
autoload_dir "#{API_PATH}/models/*.rb"
|
|
13
|
+
autoload_dir "#{API_PATH}/representers/*.rb"
|
|
14
|
+
autoload_dir "#{API_PATH}/requests/*_request.rb"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "justimmo_client/version"
|
|
4
|
+
require "justimmo_client/errors"
|
|
5
|
+
require "justimmo_client/misc"
|
|
6
|
+
|
|
7
|
+
module JustimmoClient
|
|
8
|
+
include JustimmoClient::Errors
|
|
9
|
+
|
|
10
|
+
autoload :Config, "justimmo_client/core/config"
|
|
11
|
+
autoload :Logging, "justimmo_client/core/logging"
|
|
12
|
+
autoload :Utils, "justimmo_client/core/utils"
|
|
13
|
+
autoload :Caching, "justimmo_client/core/caching"
|
|
14
|
+
autoload :Realty, "justimmo_client/realty"
|
|
15
|
+
autoload :Employee, "justimmo_client/employee"
|
|
16
|
+
autoload :OptionParser, "justimmo_client/option_parser"
|
|
17
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "justimmo_client/core/config"
|
|
4
|
+
require "justimmo_client/core/logging"
|
|
5
|
+
|
|
6
|
+
module JustimmoClient
|
|
7
|
+
# Caching support
|
|
8
|
+
# @api private
|
|
9
|
+
module Caching
|
|
10
|
+
extend JustimmoClient::Logging
|
|
11
|
+
|
|
12
|
+
class NullCache
|
|
13
|
+
def write(_key, _data, **options); end
|
|
14
|
+
def read(_key); end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
class << self
|
|
18
|
+
# Returns the current cache
|
|
19
|
+
# @!attribute [rw] cache
|
|
20
|
+
def cache
|
|
21
|
+
@cache ||= default_cache
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def cache=(c)
|
|
25
|
+
@cache = c
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def default_cache
|
|
29
|
+
cache = JustimmoClient::Config.cache || NullCache.new
|
|
30
|
+
log.info("Using default cache #{cache.class}")
|
|
31
|
+
cache
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def cache
|
|
36
|
+
JustimmoClient::Caching.cache
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# TODO: JSON serialize/deserialize the cached value
|
|
40
|
+
def with_cache(key, **options)
|
|
41
|
+
log.debug("Looking up cache key #{key}")
|
|
42
|
+
data = cache.read(key)
|
|
43
|
+
|
|
44
|
+
if data.nil?
|
|
45
|
+
log.debug("Cache miss for #{key}")
|
|
46
|
+
data = yield
|
|
47
|
+
cache.write(key, data, options)
|
|
48
|
+
else
|
|
49
|
+
log.debug("Cache hit for #{key}")
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
data
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "base64"
|
|
4
|
+
require "active_support/configurable"
|
|
5
|
+
require "justimmo_client/errors"
|
|
6
|
+
|
|
7
|
+
module JustimmoClient
|
|
8
|
+
# Configuration options storage
|
|
9
|
+
# @api private
|
|
10
|
+
class Config
|
|
11
|
+
include ActiveSupport::Configurable
|
|
12
|
+
|
|
13
|
+
SUPPORTED_API_VERSIONS = [1].freeze
|
|
14
|
+
REQUIRED = %i[username password].freeze
|
|
15
|
+
|
|
16
|
+
config_accessor(:base_url) { "api.justimmo.at/rest" }
|
|
17
|
+
config_accessor(:secure) { true }
|
|
18
|
+
config_accessor(:api_ver) { 1 }
|
|
19
|
+
config_accessor(:username)
|
|
20
|
+
config_accessor(:password)
|
|
21
|
+
config_accessor(:credentials)
|
|
22
|
+
config_accessor(:debug) { false }
|
|
23
|
+
config_accessor(:cache) { nil }
|
|
24
|
+
config_accessor(:request_retries) { 3 }
|
|
25
|
+
|
|
26
|
+
class << self
|
|
27
|
+
def configure
|
|
28
|
+
super
|
|
29
|
+
self.credentials = Base64.urlsafe_encode64("#{username}:#{password}")
|
|
30
|
+
validate
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def validate
|
|
34
|
+
missing = REQUIRED.select { |r| @_config[r].nil? }
|
|
35
|
+
raise MissingConfiguration, missing unless missing.empty?
|
|
36
|
+
|
|
37
|
+
supported_ver = SUPPORTED_API_VERSIONS.include?(api_ver)
|
|
38
|
+
raise UnsupportedAPIVersion, api_ver unless supported_ver
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def url
|
|
42
|
+
"#{secure ? 'https' : 'http'}://#{base_url}/v#{api_ver}"
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "logger"
|
|
4
|
+
require "justimmo_client/core/config"
|
|
5
|
+
|
|
6
|
+
module JustimmoClient
|
|
7
|
+
# Logging support
|
|
8
|
+
# @api private
|
|
9
|
+
module Logging
|
|
10
|
+
class << self
|
|
11
|
+
# Use the Rails or default logger if none is set.
|
|
12
|
+
# @!attribute [rw] logger
|
|
13
|
+
# @return [Logger]
|
|
14
|
+
def logger
|
|
15
|
+
@logger ||= rails_logger || default_logger
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
attr_writer :logger
|
|
19
|
+
|
|
20
|
+
def default_logger
|
|
21
|
+
logger = Logger.new($stdout)
|
|
22
|
+
logger.level = JustimmoClient::Config.debug ? Logger::DEBUG : Logger::INFO
|
|
23
|
+
logger.datetime_format = "%Y-%m-%d %H:%M:%S"
|
|
24
|
+
logger.progname = "JustimmoClient"
|
|
25
|
+
logger.formatter = proc do |severity, datetime, progname, message|
|
|
26
|
+
"[#{format("%-5s", severity)}] #{datetime} #{progname} #{message}\n"
|
|
27
|
+
end
|
|
28
|
+
logger
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# The Ruby on Rails logger
|
|
32
|
+
# @return [Logger, nil] The logger object
|
|
33
|
+
def rails_logger
|
|
34
|
+
if ("true" == ENV.fetch("JUSTIMMO_USE_RAILS_LOGGER", "true")) && defined?(::Rails)
|
|
35
|
+
::Rails&.logger
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def logger
|
|
41
|
+
Logging.logger
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
alias log logger
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "active_support/core_ext/string/inflections"
|
|
4
|
+
|
|
5
|
+
module JustimmoClient
|
|
6
|
+
# Useful utility methods
|
|
7
|
+
# @api private
|
|
8
|
+
module Utils
|
|
9
|
+
def autoload_dir(path)
|
|
10
|
+
dirname = File.dirname(path)
|
|
11
|
+
|
|
12
|
+
Dir[path].each do |f|
|
|
13
|
+
basename = File.basename(f, ".rb")
|
|
14
|
+
send :autoload, basename.classify, File.join(dirname, basename)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def versioned_api(*name)
|
|
19
|
+
(["JustimmoClient::V#{JustimmoClient::Config.api_ver}"] + name).join("::").constantize
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def api(name)
|
|
23
|
+
"JustimmoClient::#{name.to_s.classify}".constantize
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def representer(name, type = :xml)
|
|
27
|
+
versioned_api(type.to_s.classify, "#{name.to_s.classify}Representer")
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def model(name)
|
|
31
|
+
versioned_api(name.to_s.classify)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def request(name)
|
|
35
|
+
versioned_api("#{name.to_s.classify}Request")
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module JustimmoClient
|
|
4
|
+
# Public employee query interface
|
|
5
|
+
module Employee
|
|
6
|
+
extend JustimmoClient::Utils
|
|
7
|
+
|
|
8
|
+
module_function
|
|
9
|
+
|
|
10
|
+
# Retrieve a list of employee data.
|
|
11
|
+
# @return [Array<Object>]
|
|
12
|
+
def list
|
|
13
|
+
xml_response = request(:employee).list
|
|
14
|
+
model = Struct.new(:employees).new
|
|
15
|
+
representer(:employee_list).new(model).from_xml(xml_response).employees
|
|
16
|
+
rescue JustimmoClient::RetrievalFailed
|
|
17
|
+
[]
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Retrieve detailed information about a single employee.
|
|
21
|
+
# @param id [Integer] The ID of the employee
|
|
22
|
+
# @return [Object]
|
|
23
|
+
def detail(id)
|
|
24
|
+
xml_response = request(:employee).detail(id)
|
|
25
|
+
model = model(:employee).new
|
|
26
|
+
representer(:employee).new(model).from_xml(xml_response)
|
|
27
|
+
rescue JustimmoClient::RetrievalFailed
|
|
28
|
+
nil
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# @return [Array<Integer>] An array of employee IDs
|
|
32
|
+
def ids
|
|
33
|
+
json_response = request(:employee).ids
|
|
34
|
+
::JSON.parse(json_response).map(&:to_i)
|
|
35
|
+
rescue JustimmoClient::RetrievalFailed
|
|
36
|
+
[]
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Exceptions for internal use
|
|
4
|
+
module JustimmoClient::Errors
|
|
5
|
+
JustimmoError = Class.new(StandardError)
|
|
6
|
+
InitializationError = Class.new(JustimmoError)
|
|
7
|
+
|
|
8
|
+
# Raised when configuration validation fails.
|
|
9
|
+
ConfigurationError = Class.new(JustimmoError)
|
|
10
|
+
|
|
11
|
+
# Raised when authentication with the API fails.
|
|
12
|
+
class AuthenticationFailed < JustimmoError
|
|
13
|
+
def initialize
|
|
14
|
+
super("Authentication failed.")
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Raised when retrieval from the API fails.
|
|
19
|
+
class RetrievalFailed < JustimmoError
|
|
20
|
+
def initialize(message)
|
|
21
|
+
super("Failed to get data from the API: #{message}")
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# A mapping could not be found in the mappings hash.
|
|
26
|
+
class MappingNotFound < JustimmoError
|
|
27
|
+
def initialize(map)
|
|
28
|
+
super("Could not find #{map} mapping.")
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# A key could not be found in the specified mapping.
|
|
33
|
+
class KeyNotFound < JustimmoError
|
|
34
|
+
def initialize(key, map)
|
|
35
|
+
super("Key #{key} not found in #{map} mapping.")
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
class NotImplemented < JustimmoError
|
|
40
|
+
def initialize(meth)
|
|
41
|
+
super("Method #{meth} not implemented!")
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Raised when an unsupported API version is set.
|
|
46
|
+
class UnsupportedAPIVersion < ConfigurationError
|
|
47
|
+
def initialize(version)
|
|
48
|
+
super("API Version #{version} not supported.")
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Raised on missing required configuration options.
|
|
53
|
+
class MissingConfiguration < ConfigurationError
|
|
54
|
+
def initialize(missing)
|
|
55
|
+
super("Required configuration missing: #{missing}.")
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module JustimmoClient
|
|
4
|
+
# @api private
|
|
5
|
+
class OptionParser
|
|
6
|
+
include JustimmoClient::Logging
|
|
7
|
+
|
|
8
|
+
attr_accessor :range_suffix
|
|
9
|
+
attr_accessor :mappings
|
|
10
|
+
|
|
11
|
+
def initialize(options = {})
|
|
12
|
+
@options = options
|
|
13
|
+
@mappings = {}
|
|
14
|
+
@range_suffix = %i[_min _max]
|
|
15
|
+
@context = nil
|
|
16
|
+
|
|
17
|
+
yield self if block_given?
|
|
18
|
+
|
|
19
|
+
parse unless options.empty?
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def add(key, **options)
|
|
23
|
+
add_option(key, options)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def group(groupname)
|
|
27
|
+
@context = groupname.to_sym
|
|
28
|
+
yield self if block_given?
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def parse(options = {})
|
|
32
|
+
out = {}
|
|
33
|
+
|
|
34
|
+
options.each do |key, value|
|
|
35
|
+
raise ArgumentError, "Invalid option: #{key}" unless @options.key?(key.to_sym)
|
|
36
|
+
group = group_of(key)
|
|
37
|
+
|
|
38
|
+
if group
|
|
39
|
+
out[group] ||= {}
|
|
40
|
+
out[group].update(parse_option(key.to_sym, value))
|
|
41
|
+
else
|
|
42
|
+
out.update(parse_option(key.to_sym, value))
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
out
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
private
|
|
50
|
+
|
|
51
|
+
def add_option(key, **options)
|
|
52
|
+
@options[key.to_sym] = {
|
|
53
|
+
group: @context,
|
|
54
|
+
type: options[:type],
|
|
55
|
+
as: options[:as],
|
|
56
|
+
values: options[:values]
|
|
57
|
+
}
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def group_of(key)
|
|
61
|
+
@options.dig(key, :group)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def mapping(key)
|
|
65
|
+
@mappings.fetch(key, key)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def translate(key)
|
|
69
|
+
return @options[key][:as] if @options[key][:as]
|
|
70
|
+
|
|
71
|
+
suffix =
|
|
72
|
+
case key
|
|
73
|
+
when /(.*)_min/ then @range_suffix.first
|
|
74
|
+
when /(.*)_max/ then @range_suffix.last
|
|
75
|
+
when /(.*)_id/ then "_id"
|
|
76
|
+
else nil
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
key = ($1 || key).to_sym
|
|
80
|
+
|
|
81
|
+
"#{mapping(key)}#{suffix}".to_sym
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def parse_option(key, value)
|
|
85
|
+
values = @options.dig(key, :values)
|
|
86
|
+
raise ArgumentError, "Value #{value} not supported" unless values.nil? || values.include?(value)
|
|
87
|
+
|
|
88
|
+
coerced =
|
|
89
|
+
case @options.dig(key, :type)
|
|
90
|
+
when :bool then i_to_bool(value)
|
|
91
|
+
else mapping(value)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
{ translate(key) => coerced }
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def parse_range(key, range)
|
|
98
|
+
min, max = @options[key][:range_suffix]
|
|
99
|
+
api_param = @options[key][:mapped]
|
|
100
|
+
{ "#{api_param}#{min}": range.first, "#{api_param}#{max}": range.last }
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def i_to_bool(value)
|
|
104
|
+
value ? 1 : 0
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|