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.
- checksums.yaml +7 -0
- data/.rubocop.yml +134 -0
- data/CHANGELOG.md +129 -0
- data/CONTRIBUTING.md +153 -0
- data/LICENSE.txt +21 -0
- data/README.md +603 -0
- data/Rakefile +16 -0
- data/dadata.gemspec +46 -0
- data/lib/dadata/api_exceptions.rb +35 -0
- data/lib/dadata/client/base.rb +272 -0
- data/lib/dadata/client/clean.rb +52 -0
- data/lib/dadata/client/profile.rb +51 -0
- data/lib/dadata/client/suggest.rb +86 -0
- data/lib/dadata/sensitive_data.rb +58 -0
- data/lib/dadata/version.rb +5 -0
- data/lib/dadata-rb.rb +6 -0
- data/lib/dadata.rb +421 -0
- data/lib/generators/dadata/USAGE +73 -0
- data/lib/generators/dadata/initializer_generator.rb +86 -0
- data/lib/generators/dadata/templates/dadata.rb.tt +24 -0
- data/lib/generators/dadata/templates/dadata_credentials.rb.tt +48 -0
- metadata +132 -0
data/README.md
ADDED
|
@@ -0,0 +1,603 @@
|
|
|
1
|
+
# DaData Ruby Client | Клиент DaData для Ruby
|
|
2
|
+
|
|
3
|
+
[](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
|