dadata-rb 3.0.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.
data/README.md ADDED
@@ -0,0 +1,603 @@
1
+ # DaData Ruby Client | Клиент DaData для Ruby
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/dadata-rb.svg)](https://rubygems.org/gems/dadata-rb)
4
+
5
+ [English](#english) | [Русский](#russian)
6
+
7
+ ---
8
+
9
+ <a name="russian"></a>
10
+
11
+ ## Описание
12
+
13
+ Gem для работы с [API DaData.ru](https://dadata.ru/api/). Поддерживает все основные методы API и предоставляет удобную интеграцию с Ruby on Rails.
14
+
15
+ В качестве отправной точки взята официальная библиотека [для Python](https://github.com/hflabs/dadata-py).
16
+
17
+ ### Основные возможности
18
+
19
+ - **Стандартизация данных:**
20
+ - Адреса
21
+ - ФИО
22
+ - Телефоны
23
+ - Email
24
+ - Паспортные данные
25
+ - Даты
26
+ - И другие типы данных
27
+
28
+ - **Подсказки (автодополнение):**
29
+ - Адреса
30
+ - Организации
31
+ - Банки
32
+ - ФИО
33
+ - Email
34
+ - И другие справочники
35
+
36
+ - **Дополнительные методы:**
37
+ - Геолокация
38
+ - Определение города по IP
39
+ - Поиск аффилированных компаний
40
+ - Работа с балансом и статистикой
41
+
42
+ ## Требования
43
+
44
+ - Ruby >= 3.3.0
45
+
46
+ ## Установка
47
+
48
+ Добавьте в Gemfile вашего проекта:
49
+
50
+ ```ruby
51
+ # Из RubyGems
52
+ gem 'dadata-rb'
53
+
54
+ # Или напрямую из репозитория:
55
+ # gem 'dadata-rb', git: 'https://hub.mos.ru/ad/dadata'
56
+ ```
57
+
58
+ Затем выполните:
59
+
60
+ ```bash
61
+ bundle install
62
+ ```
63
+
64
+ ## Конфигурация
65
+
66
+ ### Rails Generator
67
+
68
+ Для Rails-приложений предусмотрен генератор конфигурации. Запустите:
69
+
70
+ ```bash
71
+ rails generate dadata:initializer
72
+ ```
73
+
74
+ По умолчанию, генератор создаст:
75
+
76
+ - Инициализатор `config/initializers/dadata.rb`
77
+ - Добавит API-ключи в `credentials.yml.enc`
78
+
79
+ #### Опции генератора:
80
+
81
+ ```bash
82
+ rails generate dadata:initializer [опции]
83
+
84
+ Опции:
85
+ --api-key=КЛЮЧ # Ваш API-ключ DaData
86
+ --secret-key=КЛЮЧ # Ваш секретный ключ DaData
87
+ --[no-]use-credentials # Использовать ли Rails credentials (по умолчанию: true)
88
+ --timeout=СЕКУНДЫ # Таймаут запросов (по умолчанию: 3)
89
+ --suggestions-count=N # Количество подсказок (по умолчанию: 10)
90
+ ```
91
+
92
+ ### Ручная настройка
93
+
94
+ ```ruby
95
+ Dadata.configure do |config|
96
+ # API-ключ из личного кабинета
97
+ config.api_key = 'ВАШ_API_КЛЮЧ'
98
+
99
+ # Секретный ключ (для некоторых методов)
100
+ config.secret_key = 'ВАШ_СЕКРЕТНЫЙ_КЛЮЧ'
101
+
102
+ # Таймаут запросов в секундах
103
+ config.timeout_sec = 3
104
+
105
+ # Количество подсказок в ответе
106
+ config.suggestions_count = 10
107
+
108
+ # Уровень логирования (:debug, :info, :warn, :error)
109
+ config.log_level = :info
110
+
111
+ # Логировать тело запроса на уровне :debug (по умолчанию: false).
112
+ # ВНИМАНИЕ: тело запроса содержит персональные данные (паспорта, ФИО,
113
+ # телефоны, email). Включайте только для отладки.
114
+ config.log_request_bodies = false
115
+
116
+ # Пользовательский логгер (опционально)
117
+ config.logger = Logger.new('dadata.log')
118
+ end
119
+ ```
120
+
121
+ ### Безопасное логирование
122
+
123
+ Gem автоматически фильтрует конфиденциальные данные в логах, такие как API-ключи и секретные ключи.
124
+ По умолчанию используется встроенный `SecureLogger`, который:
125
+
126
+ - Фильтрует заголовки `Authorization`, `X-Secret` и `API-Key`
127
+ - Заменяет конфиденциальные данные на `[FILTERED]`
128
+ - Поддерживает все стандартные уровни логирования
129
+
130
+ Пример лога запроса:
131
+
132
+ ```
133
+ I, [2025-01-25T20:44:10+03:00] INFO -- : DaData Request: POST https://suggestions.dadata.ru/suggestions/api/4_1/rs/suggest/address
134
+ Headers: Authorization: [FILTERED], Content-Type: application/json
135
+ ```
136
+
137
+ ### Постоянные соединения
138
+
139
+ Gem использует постоянные HTTP-соединения (`net-http-persistent`) для уменьшения накладных
140
+ расходов на установку соединения. Соединения переиспользуются автоматически; при завершении
141
+ работы вызовите `client.close`, чтобы освободить сокеты.
142
+
143
+ ## Использование
144
+
145
+ ### Общий клиент
146
+
147
+ ```ruby
148
+ # Используя настройки из конфигурации
149
+ api = Dadata::Client.new
150
+
151
+ # Или с явным указанием ключей
152
+ api = Dadata::Client.new('ВАШ_API_КЛЮЧ', 'ВАШ_СЕКРЕТНЫЙ_КЛЮЧ')
153
+ ```
154
+
155
+ ### Специализированные клиенты
156
+
157
+ #### Подсказки (SuggestClient)
158
+
159
+ ```ruby
160
+ suggest = Dadata::SuggestClient.new
161
+
162
+ # Поиск адреса
163
+ suggest.suggest("address", "москва хабар")
164
+
165
+ # Поиск организации
166
+ suggest.suggest("party", "сбербанк")
167
+
168
+ # Поиск банка по БИК или названию
169
+ suggest.suggest("bank", "044525225")
170
+ ```
171
+
172
+ #### Стандартизация (CleanClient)
173
+
174
+ ```ruby
175
+ cleaner = Dadata::CleanClient.new
176
+
177
+ # Стандартизация адреса
178
+ cleaner.clean("address", "мск сухонская 11")
179
+
180
+ # Стандартизация ФИО
181
+ cleaner.clean("name", "иванов сергей")
182
+
183
+ # Стандартизация телефона
184
+ cleaner.clean("phone", "9161234567")
185
+ ```
186
+
187
+ #### Профиль (ProfileClient)
188
+
189
+ ```ruby
190
+ profile = Dadata::ProfileClient.new
191
+
192
+ # Проверка баланса
193
+ profile.balance
194
+
195
+ # Статистика использования
196
+ profile.daily_stats
197
+ ```
198
+
199
+ ## Параметры запросов по типам справочников
200
+
201
+ Универсальные методы `suggest`, `find_by_id`, `geolocate` и `iplocate` принимают
202
+ дополнительные параметры через `**kwargs`. Ниже — параметры, специфичные для каждого
203
+ типа (`name`), согласно OpenAPI-схемам DaData (Suggestions API v4.1).
204
+ `count` по умолчанию равен 10 и ограничивается значением 20 на стороне gem.
205
+
206
+ ### `suggest(name, query, **kwargs)`
207
+
208
+ | `name` | Дополнительные параметры |
209
+ | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
210
+ | `party` | `branch_type:` (`MAIN`, `BRANCH`), `type:` (`LEGAL`, `INDIVIDUAL`), `status:` (`ACTIVE`, `LIQUIDATING`, `LIQUIDATED`, `REORGANIZING`, `BANKRUPT`), `locations:`, `locations_boost:`, `okved:` |
211
+ | `bank` | `type:` (`BANK`, `NKO`, `BANK_BRANCH`, `NKO_BRANCH`, `RKC`, `CBR`, `TREASURY`, `OTHER`), `status:` (как у `party`), `locations:`, `locations_boost:` |
212
+ | `address` | `locations:`, `locations_boost:`, `locations_geo:`, `from_bound:`/`to_bound:` (`{ value: 'city' }`), `restrict_value:` (bool), `division:` (`ADMINISTRATIVE`, `MUNICIPAL`), `language:` (`ru`, `en`) |
213
+ | `fio` | `parts:` (`SURNAME`, `NAME`, `PATRONYMIC`), `gender:` (`MALE`, `FEMALE`, `UNKNOWN`) |
214
+ | `fias` | `locations:`, `locations_boost:`, `from_bound:`/`to_bound:`, `restrict_value:` |
215
+ | `email` | — (только `count`) |
216
+ | прочие | `filters:` (массив объектов `{ поле: значение }`) |
217
+
218
+ ```ruby
219
+ api.suggest('party', 'сбер', status: ['ACTIVE'], type: 'LEGAL', branch_type: ['MAIN'])
220
+ api.suggest('address', 'москва', from_bound: { value: 'city' }, to_bound: { value: 'city' })
221
+ ```
222
+
223
+ ### `find_by_id(name, query, **kwargs)`
224
+
225
+ | `name` | Дополнительные параметры |
226
+ | --------- | ------------------------------------------------------------------------------------------------------------- |
227
+ | `party` | `kpp:`, `branch_type:` (`MAIN`, `BRANCH`), `type:` (`LEGAL`, `INDIVIDUAL`), `status:` (как у `suggest party`) |
228
+ | `bank` | `kpp:` |
229
+ | `address` | `division:` (`ADMINISTRATIVE`, `MUNICIPAL`), `from_bound:`/`to_bound:`, `language:` (`ru`, `en`) |
230
+ | `fias` | `from_bound:`/`to_bound:` |
231
+
232
+ ### Остальные методы
233
+
234
+ - `find_affiliated(query, **kwargs)` — `scope:` (`MANAGERS`, `FOUNDERS`; по умолчанию оба)
235
+ - `geolocate(name, lat, lon, radius_meters, **kwargs)` — `count:`, `division:` (`ADMINISTRATIVE`, `MUNICIPAL`), `language:` (`ru`, `en`); для `name` ≠ `address` вместо `division`/`language` — `filters:`
236
+ - `iplocate(ip, **kwargs)` — `language:` (`ru`, `en`), `division:` (`ADMINISTRATIVE`, `MUNICIPAL`)
237
+
238
+ > Уровни `from_bound`/`to_bound`: `country`, `region`, `area`, `city`, `settlement`, `street`, `house`, `flat`.
239
+ > Полный перечень параметров — в [OpenAPI-схемах DaData](https://dadata.ru/api/) (Suggestions API v4.1).
240
+
241
+ ## Примеры использования
242
+
243
+ ### Стандартизация адреса
244
+
245
+ ```ruby
246
+ result = api.clean("address", "мск сухонская 11")
247
+ puts result['result'] # Стандартизованный адрес
248
+ puts result['postal_code'] # Почтовый индекс
249
+ puts result['region'] # Регион
250
+ puts result['city'] # Город
251
+ ```
252
+
253
+ ### Поиск организации по ИНН
254
+
255
+ ```ruby
256
+ result = api.suggest("party", "7707083893")
257
+ company = result[0]
258
+ puts company['value'] # Краткое название
259
+ puts company['inn'] # ИНН
260
+ puts company['address'] # Адрес
261
+ ```
262
+
263
+ ### Определение города по IP
264
+
265
+ ```ruby
266
+ result = api.iplocate("46.226.227.20")
267
+ puts result['value'] # Город
268
+ puts result['region'] # Регион
269
+ ```
270
+
271
+ ## Обработка ошибок
272
+
273
+ Все исключения наследуются от `Dadata::Error`:
274
+
275
+ ```ruby
276
+ Dadata::Error # Базовый класс всех ошибок gem
277
+ Dadata::ConfigurationError # Некорректная конфигурация
278
+
279
+ Dadata::ApiError # Базовая ошибка API (HTTP-статус не из 2xx); содержит #status
280
+ Dadata::BadRequestError # 400 — некорректный запрос
281
+ Dadata::UnauthorizedError # 401 — отсутствует или неверный ключ
282
+ Dadata::AuthenticationError # 403 — неверный ключ, неподтверждённый email или превышен лимит
283
+ Dadata::NotFoundError # 404 — сервис не найден
284
+ Dadata::RateLimitError # 429 — слишком много запросов
285
+
286
+ Dadata::ConnectionError # Ошибка соединения
287
+ Dadata::TimeoutError # Превышен таймаут (подкласс ConnectionError)
288
+ ```
289
+
290
+ Рекомендуется обрабатывать их следующим образом (более специфичные классы — выше):
291
+
292
+ ```ruby
293
+ begin
294
+ api.clean("address", "мск сухонская 11")
295
+ rescue Dadata::RateLimitError => e
296
+ puts "Превышен лимит запросов: #{e.message}"
297
+ rescue Dadata::ApiError => e
298
+ puts "Ошибка API (#{e.status}): #{e.message}"
299
+ rescue Dadata::TimeoutError => e
300
+ puts "Таймаут запроса: #{e.message}"
301
+ rescue Dadata::ConnectionError => e
302
+ puts "Ошибка соединения: #{e.message}"
303
+ end
304
+ ```
305
+
306
+ ---
307
+
308
+ <a name="english"></a>
309
+
310
+ ## Description
311
+
312
+ A Ruby gem for working with [DaData.ru API](https://dadata.ru/api/). Supports all main API methods and provides convenient Rails integration.
313
+
314
+ Based on the official [Python library](https://github.com/hflabs/dadata-py).
315
+
316
+ ### Key Features
317
+
318
+ - **Data Standardization:**
319
+ - Addresses
320
+ - Names
321
+ - Phone numbers
322
+ - Email
323
+ - Passport data
324
+ - Dates
325
+ - And other data types
326
+
327
+ - **Suggestions (Autocomplete):**
328
+ - Addresses
329
+ - Organizations
330
+ - Banks
331
+ - Names
332
+ - Email
333
+ - And other reference data
334
+
335
+ - **Additional Methods:**
336
+ - Geolocation
337
+ - City detection by IP
338
+ - Finding affiliated companies
339
+ - Balance and statistics
340
+
341
+ ## Requirements
342
+
343
+ - Ruby >= 3.3.0
344
+
345
+ ## Installation
346
+
347
+ Add to your project's Gemfile:
348
+
349
+ ```ruby
350
+ # From RubyGems
351
+ gem 'dadata-rb'
352
+
353
+ # Or directly from the repository:
354
+ # gem 'dadata-rb', git: 'https://hub.mos.ru/ad/dadata'
355
+ ```
356
+
357
+ Then run:
358
+
359
+ ```bash
360
+ bundle install
361
+ ```
362
+
363
+ ## Configuration
364
+
365
+ ### Rails Generator
366
+
367
+ For Rails applications, a configuration generator is provided. Run:
368
+
369
+ ```bash
370
+ rails generate dadata:initializer
371
+ ```
372
+
373
+ By default, the generator will:
374
+
375
+ - Create initializer at `config/initializers/dadata.rb`
376
+ - Add API keys to `credentials.yml.enc`
377
+
378
+ #### Generator Options:
379
+
380
+ ```bash
381
+ rails generate dadata:initializer [options]
382
+
383
+ Options:
384
+ --api-key=KEY # Your DaData API key
385
+ --secret-key=KEY # Your DaData secret key
386
+ --[no-]use-credentials # Whether to use Rails credentials (default: true)
387
+ --timeout=SECONDS # Request timeout (default: 3)
388
+ --suggestions-count=N # Number of suggestions (default: 10)
389
+ ```
390
+
391
+ ### Manual Configuration
392
+
393
+ ```ruby
394
+ Dadata.configure do |config|
395
+ # API key from your account
396
+ config.api_key = 'YOUR_API_KEY'
397
+
398
+ # Secret key (required for some methods)
399
+ config.secret_key = 'YOUR_SECRET_KEY'
400
+
401
+ # Request timeout in seconds
402
+ config.timeout_sec = 3
403
+
404
+ # Number of suggestions in response
405
+ config.suggestions_count = 10
406
+
407
+ # Log level (:debug, :info, :warn, :error)
408
+ config.log_level = :info
409
+
410
+ # Log request bodies at :debug level (default: false).
411
+ # WARNING: request bodies contain personal data (passports, names, phones,
412
+ # emails). Enable only for debugging.
413
+ config.log_request_bodies = false
414
+
415
+ # Custom logger (optional)
416
+ config.logger = Logger.new('dadata.log')
417
+ end
418
+ ```
419
+
420
+ ### Secure Logging
421
+
422
+ The gem automatically filters confidential data in logs, such as API keys and secret keys.
423
+ By default, the built-in `SecureLogger` is used, which:
424
+
425
+ - Filters `Authorization`, `X-Secret` and `API-Key` headers
426
+ - Replaces confidential data with `[FILTERED]`
427
+ - Supports all standard log levels
428
+
429
+ Example log entry:
430
+
431
+ ```
432
+ I, [2025-01-25T20:44:10+03:00] INFO -- : DaData Request: POST https://suggestions.dadata.ru/suggestions/api/4_1/rs/suggest/address
433
+ Headers: Authorization: [FILTERED], Content-Type: application/json
434
+ ```
435
+
436
+ ### Persistent Connections
437
+
438
+ The gem uses persistent HTTP connections (`net-http-persistent`) to reduce connection
439
+ setup overhead. Connections are reused automatically; call `client.close` when you are
440
+ done to release the sockets.
441
+
442
+ ## Usage
443
+
444
+ ### General Client
445
+
446
+ ```ruby
447
+ # Using configuration settings
448
+ api = Dadata::Client.new
449
+
450
+ # Or with explicit keys
451
+ api = Dadata::Client.new('YOUR_API_KEY', 'YOUR_SECRET_KEY')
452
+ ```
453
+
454
+ ### Specialized Clients
455
+
456
+ #### Suggestions (SuggestClient)
457
+
458
+ ```ruby
459
+ suggest = Dadata::SuggestClient.new
460
+
461
+ # Address search
462
+ suggest.suggest("address", "moscow tverskaya")
463
+
464
+ # Organization search
465
+ suggest.suggest("party", "sberbank")
466
+
467
+ # Bank search by BIC or name
468
+ suggest.suggest("bank", "044525225")
469
+ ```
470
+
471
+ #### Standardization (CleanClient)
472
+
473
+ ```ruby
474
+ cleaner = Dadata::CleanClient.new
475
+
476
+ # Address standardization
477
+ cleaner.clean("address", "msk suhonskaya 11")
478
+
479
+ # Name standardization
480
+ cleaner.clean("name", "ivanov sergey")
481
+
482
+ # Phone standardization
483
+ cleaner.clean("phone", "9161234567")
484
+ ```
485
+
486
+ #### Profile (ProfileClient)
487
+
488
+ ```ruby
489
+ profile = Dadata::ProfileClient.new
490
+
491
+ # Check balance
492
+ profile.balance
493
+
494
+ # Usage statistics
495
+ profile.daily_stats
496
+ ```
497
+
498
+ ## Per-directory Request Parameters
499
+
500
+ The generic `suggest`, `find_by_id`, `geolocate` and `iplocate` methods accept
501
+ extra parameters via `**kwargs`. Below are the directory-specific parameters (by
502
+ `name`), per the DaData OpenAPI schemas (Suggestions API v4.1). `count` defaults to
503
+ 10 and is capped at 20 by the gem.
504
+
505
+ ### `suggest(name, query, **kwargs)`
506
+
507
+ | `name` | Extra parameters |
508
+ | --------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
509
+ | `party` | `branch_type:` (`MAIN`, `BRANCH`), `type:` (`LEGAL`, `INDIVIDUAL`), `status:` (`ACTIVE`, `LIQUIDATING`, `LIQUIDATED`, `REORGANIZING`, `BANKRUPT`), `locations:`, `locations_boost:`, `okved:` |
510
+ | `bank` | `type:` (`BANK`, `NKO`, `BANK_BRANCH`, `NKO_BRANCH`, `RKC`, `CBR`, `TREASURY`, `OTHER`), `status:` (same as `party`), `locations:`, `locations_boost:` |
511
+ | `address` | `locations:`, `locations_boost:`, `locations_geo:`, `from_bound:`/`to_bound:` (`{ value: 'city' }`), `restrict_value:` (bool), `division:` (`ADMINISTRATIVE`, `MUNICIPAL`), `language:` (`ru`, `en`) |
512
+ | `fio` | `parts:` (`SURNAME`, `NAME`, `PATRONYMIC`), `gender:` (`MALE`, `FEMALE`, `UNKNOWN`) |
513
+ | `fias` | `locations:`, `locations_boost:`, `from_bound:`/`to_bound:`, `restrict_value:` |
514
+ | `email` | — (`count` only) |
515
+ | others | `filters:` (array of `{ field: value }` objects) |
516
+
517
+ ```ruby
518
+ api.suggest('party', 'sber', status: ['ACTIVE'], type: 'LEGAL', branch_type: ['MAIN'])
519
+ api.suggest('address', 'moscow', from_bound: { value: 'city' }, to_bound: { value: 'city' })
520
+ ```
521
+
522
+ ### `find_by_id(name, query, **kwargs)`
523
+
524
+ | `name` | Extra parameters |
525
+ | --------- | --------------------------------------------------------------------------------------------------------------- |
526
+ | `party` | `kpp:`, `branch_type:` (`MAIN`, `BRANCH`), `type:` (`LEGAL`, `INDIVIDUAL`), `status:` (same as `suggest party`) |
527
+ | `bank` | `kpp:` |
528
+ | `address` | `division:` (`ADMINISTRATIVE`, `MUNICIPAL`), `from_bound:`/`to_bound:`, `language:` (`ru`, `en`) |
529
+ | `fias` | `from_bound:`/`to_bound:` |
530
+
531
+ ### Other methods
532
+
533
+ - `find_affiliated(query, **kwargs)` — `scope:` (`MANAGERS`, `FOUNDERS`; both by default)
534
+ - `geolocate(name, lat, lon, radius_meters, **kwargs)` — `count:`, `division:` (`ADMINISTRATIVE`, `MUNICIPAL`), `language:` (`ru`, `en`); for `name` ≠ `address`, use `filters:` instead of `division`/`language`
535
+ - `iplocate(ip, **kwargs)` — `language:` (`ru`, `en`), `division:` (`ADMINISTRATIVE`, `MUNICIPAL`)
536
+
537
+ > `from_bound`/`to_bound` levels: `country`, `region`, `area`, `city`, `settlement`, `street`, `house`, `flat`.
538
+ > See the [DaData OpenAPI schemas](https://dadata.ru/api/) (Suggestions API v4.1) for the full parameter list.
539
+
540
+ ## Usage Examples
541
+
542
+ ### Address Standardization
543
+
544
+ ```ruby
545
+ result = api.clean("address", "msk suhonskaya 11")
546
+ puts result['result'] # Standardized address
547
+ puts result['postal_code'] # Postal code
548
+ puts result['region'] # Region
549
+ puts result['city'] # City
550
+ ```
551
+
552
+ ### Company Search by Tax ID (INN)
553
+
554
+ ```ruby
555
+ result = api.suggest("party", "7707083893")
556
+ company = result[0]
557
+ puts company['value'] # Short name
558
+ puts company['inn'] # Tax ID
559
+ puts company['address'] # Address
560
+ ```
561
+
562
+ ### City Detection by IP
563
+
564
+ ```ruby
565
+ result = api.iplocate("46.226.227.20")
566
+ puts result['value'] # City
567
+ puts result['region'] # Region
568
+ ```
569
+
570
+ ## Error Handling
571
+
572
+ All exceptions inherit from `Dadata::Error`:
573
+
574
+ ```ruby
575
+ Dadata::Error # Base class for all gem errors
576
+ Dadata::ConfigurationError # Invalid configuration
577
+
578
+ Dadata::ApiError # Base API error (non-2xx HTTP status); exposes #status
579
+ Dadata::BadRequestError # 400 — invalid request
580
+ Dadata::UnauthorizedError # 401 — missing or unknown key
581
+ Dadata::AuthenticationError # 403 — invalid key, unconfirmed email, or limit exceeded
582
+ Dadata::NotFoundError # 404 — service not found
583
+ Dadata::RateLimitError # 429 — too many requests
584
+
585
+ Dadata::ConnectionError # Connection error
586
+ Dadata::TimeoutError # Request timeout (subclass of ConnectionError)
587
+ ```
588
+
589
+ It's recommended to handle them as follows (most specific classes first):
590
+
591
+ ```ruby
592
+ begin
593
+ api.clean("address", "msk suhonskaya 11")
594
+ rescue Dadata::RateLimitError => e
595
+ puts "Rate limited: #{e.message}"
596
+ rescue Dadata::ApiError => e
597
+ puts "API Error (#{e.status}): #{e.message}"
598
+ rescue Dadata::TimeoutError => e
599
+ puts "Request Timeout: #{e.message}"
600
+ rescue Dadata::ConnectionError => e
601
+ puts "Connection Error: #{e.message}"
602
+ end
603
+ ```
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rake/testtask'
5
+
6
+ Rake::TestTask.new(:test) do |t|
7
+ t.libs << 'test'
8
+ t.libs << 'lib'
9
+ t.test_files = FileList['test/**/*_test.rb']
10
+ end
11
+
12
+ require 'rubocop/rake_task'
13
+
14
+ RuboCop::RakeTask.new
15
+
16
+ task default: %i[test rubocop]
data/dadata.gemspec ADDED
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/dadata/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'dadata-rb'
7
+ spec.version = Dadata::VERSION
8
+ spec.authors = ['Alexander Dryzhuk']
9
+ spec.email = ['ad@ad-it.pro']
10
+
11
+ spec.summary = 'Ruby wrapper for Dadata API with secure logging and connection pooling'
12
+ spec.description = <<~DESC
13
+ Ruby wrapper for data cleansing, enrichment and suggestions via [Dadata API](https://dadata.ru/api).
14
+ Features secure logging with automatic filtering of sensitive data, connection pooling,
15
+ and comprehensive Rails integration.
16
+
17
+ Библиотека для очистки, обогащения и подсказок при вводе данных с помощью [Dadata API](https://dadata.ru/api).
18
+ Включает безопасное логирование с автоматической фильтрацией конфиденциальных данных,
19
+ пул соединений и полную интеграцию с Rails.
20
+ DESC
21
+
22
+ spec.homepage = 'https://hub.mos.ru/ad/dadata'
23
+ spec.license = 'MIT'
24
+ spec.required_ruby_version = Gem::Requirement.new('>= 3.3.0')
25
+
26
+ spec.metadata['allowed_push_host'] = 'https://rubygems.org'
27
+
28
+ spec.metadata['homepage_uri'] = spec.homepage
29
+ spec.metadata['source_code_uri'] = 'https://hub.mos.ru/ad/dadata'
30
+ spec.metadata['changelog_uri'] = 'https://hub.mos.ru/ad/dadata/-/blob/master/CHANGELOG.md'
31
+ spec.metadata['rubygems_mfa_required'] = 'true'
32
+ spec.metadata['documentation_uri'] = 'https://hub.mos.ru/ad/dadata/-/blob/master/README.md'
33
+
34
+ spec.files = Dir.chdir(__dir__) do
35
+ `git ls-files -z`.split("\x0").reject do |f|
36
+ (File.expand_path(f) == __FILE__) ||
37
+ f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor Gemfile])
38
+ end
39
+ end
40
+ spec.require_paths = ['lib']
41
+
42
+ spec.add_dependency 'faraday', '~> 2.9'
43
+ spec.add_dependency 'faraday-net_http_persistent', '~> 2.3'
44
+ spec.add_dependency 'faraday-retry', '~> 2.2'
45
+ spec.add_dependency 'net-http-persistent', '~> 4.0'
46
+ end