Методы dig
Методы dig в Ruby полезны для доступа к вложенным структурам данных.
Рассмотрим эти данные:
item = {
id: "0001",
type: "donut",
name: "Cake",
ppu: 0.55,
batters: {
batter: [
{id: "1001", type: "Regular"},
{id: "1002", type: "Chocolate"},
{id: "1003", type: "Blueberry"},
{id: "1004", type: "Devil's Food"}
]
},
topping: [
{id: "5001", type: "None"},
{id: "5002", type: "Glazed"},
{id: "5005", type: "Sugar"},
{id: "5007", type: "Powdered Sugar"},
{id: "5006", type: "Chocolate with Sprinkles"},
{id: "5003", type: "Chocolate"},
{id: "5004", type: "Maple"}
]
}
Без метода dig можно написать:
item[:batters][:batter][1][:type] # => "Chocolate"
С методом dig можно написать:
item.dig(:batters, :batter, 1, :type) # => "Chocolate"
Без метода dig можно ошибочно написать (вызывает исключение NoMethodError (undefined method `[]' for nil:NilClass)):
item[:batters][:BATTER][1][:type]
С методом dig можно написать (всё ещё ошибочно, но без исключения):
item.dig(:batters, :BATTER, 1, :type) # => nil
Почему dig лучше?
-
В нём меньше синтаксических элементов (в которых можно ошибиться).
-
Он лучше читается.
-
Он не вызывает исключение, если элемент не найден.
Как работает dig?
Последовательность вызовов выглядит так:
obj.dig(*identifiers)
Аргументы identifiers задают «путь» во вложенных структурах данных:
-
Для каждого идентификатора в
identifiersвызывается метод #dig у объекта-получателя с этим идентификатором. -
Первый объект-получатель — это
self. -
Каждый следующий объект-получатель — это значение, возвращённое предыдущим вызовом
dig. -
В конечном счёте возвращается значение, возвращённое последним вызовом
dig.
Метод dig вызывает исключение, если какой-либо объект-получатель не отвечает на вызов #dig:
h = { foo: 1 }
# Raises TypeError (Integer does not have #dig method):
h.dig(:foo, :bar)
Что ещё?
В описанной выше структуре есть объекты Hash и Array, у обоих имеется метод экземпляра dig.
Всего в Ruby есть шесть встроенных классов с методом dig: три в основных классах и три в стандартной библиотеке.
В ядре:
-
Array#dig: первый аргумент — индекс типа Integer. -
Hash#dig: первый аргумент — ключ. -
Struct#dig: первый аргумент — ключ.
В стандартной библиотеке:
-
OpenStruct#dig: первый аргумент — имя типа String.
-
CSV::Table#dig: первый аргумент — индекс типа Integer или заголовок типа String.
-
CSV::Row#dig: первый аргумент — индекс типа Integer или заголовок типа String.
Ruby Core © 1993–2025 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.