Страницы

Поиск по вопросам

среда, 12 февраля 2020 г.

Как лучше работать с конфигурациями в Ruby

#ruby #config #configuration #best_practice


Допустим, у нас есть некая структура конфигурации (взята из YAML, JSON, XML или просто
в виде Hash):  

configuration = {
  gmail: {
    username: 'example@gmail.com',
    password: 'pa$$word',
    host: 'imap.gmail.com',
    ssl: true,
    port: 993
  },
  ftp: {
    username: 'example@gmail.com',
    password: 'pa$$word',
    host: 'imap.gmail.com',
    ssl: true,
    port: 42
  }
}


Далее, на основе этой структуры мы достаём из неё данные:  

mail = Mail.new host: configuration[:gmail][:host], port: configuration[:gmail][:port],
username: configuration[:gmail][:username], password: configuration[:gmail][:password],
ssl: configuration[:gmail][:ssl]
ftp = FTP.new host: configuration[:ftp][:host], port: configuration[:ftp][:port],
username: configuration[:ftp][:username], password: configuration[:ftp][:password],
ssl: configuration[:ftp][:ssl]


Всё работает, но сам код получается «плохочитаемым». 
Т. е. он конечно понятен, но слишком много «сухого» текста, вместо привычного для
языка программирования кода.  

Поделитесь Best Practice, как правильно делать и использовать конфигурации в Ruby.
    


Ответы

Ответ 1



Если имена атрибутов Mail и FTP в вашем примере в точности соответствуют ключам в структурах в конфигурации - вы можете передавать в конструктор хеш напрямую: mail = Mail.new configuration[:gmail] ftp = FTP.new configuration[:ftp] Здесь важно помнить две вещи: Ключи и типы значений в конфигурации должны совпадать с атрибутами и типами значений атрибутов класса; Доступ к конфигурации должен быть только у вас - иначе злоумышленник может, оперируя структурой, создавать объекты с любыми атрибутами класса без ограничений.

Ответ 2



Ну, как минимум вы написали выбор поднабора из хэша с захардкоженными ключами. "Колонна" в вашем коде (которая получается, если код "подровнять"): mail = Mail.new host: configuration[:gmail][:host], port: configuration[:gmail][:port], username: configuration[:gmail][:username], password: configuration[:gmail][:password], ssl: configuration[:gmail][:ssl] # ^^^^^^^^^^^^^^^^^^ это ^^^^^^^^^^^^^^^^^^^^ ...на самом деле же просто хэшмап. Просто {} вокруг него писать оказалось необязательно, т. к. это последний аргумент вызова метода, и это особый случай в синтаксисе Ruby. Если в configuration[:gmail] нет лишних ключей, то можно сделать попросту вот так: Mail.new configuration[:gmail] ...а если лишние ключи хочется отрезать, и вы вооружены aсtivesupport'ом (гем такой, из состава Rails), есть Hash#slice: # Точечная загрузка ActiveSupport require 'active_support/core_ext/hash/slice' # В Rails необязательно, там он обычно весь уже загружен Mail.new configuration[:gmail].slice(:host, :port, :username, :password, :ssl) ...но обычно один набор параметров конфигурации используется в ровно одном месте (или если в нескольких, то как минимум одинаково: скажем, при вызове однотипных конструкторов), поэтому можно себе позволить просто не писать в конфигах лишние ключи. Это не конвенция, такая ситуация сложилась сама и она всех устраивает. "Best bractices" конфигураций, которые вы ждёте, этого всего в основном не касаются и они запакованы, в разных комбинациях, в гемы dotenv, figaro и config. Что в них типично встречается: Сокращённый синтаксис получения конфигурации ключей: a[:b][:c] => a.b.c Фоллбэк (когда конфига нет) к переменным среды в ENV (см. 12-факторные приложения) Конвенции по размещению конфигурационных файлов и их формату — кто на что горазд

Комментариев нет:

Отправить комментарий