Что нового в Ruby 2.3

от автора

На прошой неделе вышел превью Ruby 2.3.0. Что есть интересного из изменений:

  • оператор безопасной навигации вглубь объектов, #11537
  • в Hash и Array добавлен метод dig для доступа вглубь вложенных хэшей или массивов #11688
  • движение в сторону неизменяемых (frozen) по умолчанию строковых литералов (обоснование, обсуждение #11473

Оператор безопасной навигации

В Ruby появился оператор безопасной навигации, аналогичный оператору ‘?.’ в Groovy и некоторых других языках. Оператор применяется для сокращения выражений, где выполняется проверка существования объекта и затем обращение к методу объекта только в случае положительной проверки:

obj.nil? && obj.some_method 

Если используется цепочка объектов и методов, то проверка может выглядить громоздко и несколько раз впустую выполнять промежуточные методы. Например, типичный для Ruby on Rails случай безопасного получения большой картинки профиля:

image = user && user.profile && user.profile.thumbnails && user.profiles.thumbnails.large 

Здесь метод profile будет выполнен три раза и два раза будет выполнен метод thumbnails. Оптимизированный вариант будет выглядеть еще сложнее:

image = user && (profile = user.profile) && (thumbnails = profile.thumbnails) && thumbnails.large 

При этом, может оказаться не совсем корректный результат, если один из объектов в движении вглубь будет отсутствовать — тогда в image окажется false, а не nil. А если проверять на nil?, то код будет выглядеть еще запутаннее.

Есть также способ двигаться вглубь цепочки без проверок, перехватывая исключение, например, обычным способом:

image = begin 		user.profile.thumbnails.large 	rescue NoMethodError 		nil 	end 

или вызывающим всеобщее неодобрение постфиксным rescue:

image = user.profiles.thumbnails.large rescue nil 

ActiveSupport для решения такой проблемы поставляет методы try и try!:

image = user.try(:profile).try(:thumbnails).try(:large) 

Эти методы добавляются в класс Object и при вызове проверяют сначала существование вызываемого метода и если он отсутствует, то возвращают nil. В случае, если user имеет метод #profile, он будет выполнен и на его результате дальше по цепочке будет вызван try(:thumbnails). Если user будет nil, то #try вернет nil и так по цепочке #try будет вызван у nil еще два раза. Медленно? Зато коротко.

Что делает новоявленный safe navigation operator в Ruby

По задаче #11537 для безопасной навигации в Ruby 2.3.0 добавлен сначала оператор ‘.?’, измененный позже на ‘&.’. В новом синтаксисе выражение из примеров можно записать так:

image = user&.profiles&.thumbnails&.large 

Вместе с лаконичным видом такая реализация дает быструю проверку на nil, так как изменения реализованы на уровне парсера и ruby-код в проверках не участвует. После того, как встретился nil, дальнейшее выполнение цепочки прерывается.

Если в метод передаются аргументы, то, в отличие от try, они вычисляются только в том случае, если объект существует и метод реально вызывается. Например, для ActiveSupport в выражении obj.try(:foo, bar()) всегда будет выполняться bar(), даже если obj не существует. Но в выражении obj&.foo(bar()), аргумент bar() будет вычислен только тогда, когда ojb не равен nil.

Безопасная навигация также может использоваться при присваивании значения атрибуту:

obj&.attr += 1 

Навигация вглубь вложенных хэшей и массивов с помощью #dig.

Feature #11688 добавляет в Hash и Array метод dig, который используется для безопасного получения значения из вложенных хэшей и массивов. Этот метод заменяет выражение:

value = hash[:a].nil? ? nil : hash[:a][:b].nil? ? nil : hash[:a][:b][:c] 

или:

value = hash[:a][:b][:c] rescue nil 

на:

value = hash.dig(:a, :b, :c) 

Доступ во вложенные хэши и массивы часто применяется при обработке параметров HTTP-запросов, получаемых Rails-приложениями, или при работе с YAML или JSON структурами. Добавление dig для обращения вглубь не только предоставляет удобный метод доступа, но и ускоряет его в несколько десятков раз.

Метод dig также на днях добавлен в Struct, но это в превью 2.3.0 это попасть не успело.

Неизменяемость строк

В Ruby 3 все строковые литералы будут неизменными. По поводу неизменности споры идут давно и сейчас движение в этоу сторону стало более конкретным. Выражается оно в появлении “магического” комментария frozen-string-literal, присутствие которого включает по умолчанию неизменность для всех строковых литералов, и в добавлении --enable/--disable=frozen-string-literal для управления таким поведением.

Основной аргумент в пользу неизменяемых строк — увеличение скорости работы за счет внутренних оптимизаций. В большинстве случаев строки остаются без изменений на протяжении всего жизненного цикла, и фиксирование такого поведения позволяет повысить производительность без изменения кода.

А у нас небольшой опрос

Мы подготовили хостинг Ruby-приложений в контейнерах Jet9. Как на облачном хостинге, так и на отказоустойчивом кластере.

Одна из причин, почему первым на Jet9 появляется Ruby — мы унифицируем обслуживание наших собственных внутренних сервисов и внутренние сервисы наших клиентов (сайт, биллинг, документооборот, багтрекер, тикеты и прочее). Чтобы упростить себе жизнь и сократить расходы на обновление и сопровождение зоопарка из разных дистрибутивов, разных HA-кластеров и отдельных физических серверов, мы переносим все на пару типовых HA-кластеров на платформе Jet9. Большая часть внутренних сервисов написана на Ruby — начиная от биллинга и заканчивая Redmine и Gitlab. Поэтому работу Ruby-приложений на хостинге Jet9 мы делаем и для себя, проверяем и на себе.

По умолчанию приложения работают под Nginx + Apache + mod_passenger (5.0.21), это самый удобный способ. Но можно использовать standalone Passenger или другие серверы: Unicorn, Puma. Сейчас доступны версии 2.2.2 и 2.2.3, и подготавливаются другие. В связи с этим опрос:

Какой Ruby вы используете в продакшене

Никто ещё не голосовал. Воздержавшихся нет.

Какой Ruby вы хотите использовать в продакшене

Никто ещё не голосовал. Воздержавшихся нет.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

ссылка на оригинал статьи http://habrahabr.ru/post/271301/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *