Заметки о релизе Ruby on Rails 5.1
Ключевые новинки в Rails 5.1:
- Поддержка Yarn
- Опциональная поддержка Webpack
- jQuery больше не является зависимостью по умолчанию
- Системные тесты
- Шифруемые секретные данные
- Параметризованные рассыльщики
- Направленные и вычисляемые маршруты
- Объединение form_for и form_tag в form_with
Эти заметки о релизе покрывают только основные обновления. Чтобы узнать о других обновлениях, различных багфиксах и изменениях, обратитесь к логам изменений или к списку коммитов в главном репозитории Rails на GitHub.
Обновление до Rails 5.1
Если вы обновляете существующее приложение, было бы хорошо иметь перед этим покрытие тестами. Также, до попытки обновиться до Rails 5.1, необходимо сначала обновиться до Rails 5.0 и убедиться, что приложение все еще выполняется так, как нужно. Список вещей, которые нужно выполнить для обновления доступен в руководстве Обновление Rails.
Основные изменения
Поддержка Yarn
Rails 5.1 позволяет управлять зависимостями JavaScript из NPM с помощью Yarn. Это облегчает использование библиотек, таких как React, VueJS и любых других из мира NPM. Поддержка Yarn интегрирована с файлопроводом, поэтому все зависимости будут без проблем работать с приложением Rails 5.1.
Опциональная поддержка Webpack
Приложения Rails можно интегрировать с Webpack, пакетированием ассетов JavaScript, используя новый стандартный гем Webpacker. Укажите флажок --webpack при генерации новых приложений, чтобы включить интеграцию с Webpack.
Она полностью совместима с файлопроводом, который можно продолжать использовать для картинок, шрифтов, звуков и других ассетов. Можно даже оставить некоторый код JavaScript, управляемый файлопроводом, а остальной код обрабатывать через Webpack. Все это управляется с помощью Yarn, который включен по умолчанию.
jQuery больше не является зависимостью по умолчанию
jQuery требовался по умолчанию в ранних версиях Rails для предоставления особенностей, таких как data-remote, data-confirm и других частей, предлагаемых Unobtrusive JavaScript в Rails. Он больше не требуется, так как UJS был переписан с использованием чистого JavaScript. Этот код теперь находится внутри Action View как rails-ujs.
При необходимости все еще можно использовать jQuery, но он больше не требуется по умолчанию.
Системные тесты
Rails 5.1 имеет встроенную поддержку для написания тестов Capybara в форме системных тестов. Больше не нужно беспокоиться о настройке Capybara и стратегиях очистки базы данных для таких тестов. Rails 5.1 предоставляет обертку для запусков тестов в Chrome с дополнительными особенностями, такими как скриншоты при падении.
Шифруемые секретные данные
Сейчас Rails позволяет управлять секретными данными приложения безопасным образом, наподобие гема sekrets.
Запустите bin/rails secrets:setup для настройки нового зашифрованного файла с секретными данными. Это также сгенерирует мастер-ключ, который должен храниться вне репозитория. Тогда сами секретные данные могут безопасно добавляться в систему контроля версий в зашифрованной форме.
Секретные данные будут дешифрованы в production с помощью ключа, либо хранящегося в переменной окружения RAILS_MASTER_KEY, либо в файле с ключом.
Параметризованные рассыльщики
Позволяют определить общие параметры, используемые всеми методами в классе рассыльщика, для переменных экземпляра, заголовков и других общих настроек.
class InvitationsMailer < ApplicationMailer
before_action { @inviter, @invitee = params[:inviter], params[:invitee] }
before_action { @account = params[:inviter].account }
def account_invitation
mail subject: "#{@inviter.name} invited you to their Basecamp (#{@account.name})"
end
end
InvitationsMailer.with(inviter: person_a, invitee: person_b)
.account_invitation.deliver_later
Направленные и вычисляемые маршруты
Rails 5.1 добавляет в DSL роутинга два новых метода, resolve и direct. Метод resolve позволяет настроить полиморфное соответствие моделей.
resource :basket
resolve("Basket") { [:basket] }
<%= form_for @basket do |form| %>
<!-- basket form -->
<% end %>
Это сгенерирует одиночный URL /basket вместо обычного /baskets/:id.
Метод direct позволяет создавать хелперы для произвольного URL.
direct(:homepage) { "http://www.rubyonrails.org" }
>> homepage_url
=> "http://www.rubyonrails.org"
Возвращаемое из блока значение должно быть валидным аргументом для метода url_for. Поэтому можно передать валидные строковый URL, Hash, Array, экземпляр Active Model или класс Active Model.
direct :commentable do |model|
[ model, anchor: model.dom_id ]
end
direct :main do
{ controller: 'pages', action: 'index', subdomain: 'www' }
end
Объединение form_for и form_tag в form_with
До Rails 5.1 было два интерфейса для обработки форм HTML: form_for для экземпляров моделей и form_tag для произвольных URL.
Rails 5.1 объединяет оба этих интерфейса с помощью form_with и может генерировать теги формы, основанные на URL, скоупах или моделях.
Используя просто URL:
<%= form_with url: posts_path do |form| %>
<%= form.text_field :title %>
<% end %>
<%# Сгенерирует %>
<form action="/posts" method="post" data-remote="true">
<input type="text" name="title">
</form>
Добавление скоупа добавляет префикс для имен полей ввода:
<%= form_with scope: :post, url: posts_path do |form| %>
<%= form.text_field :title %>
<% end %>
<%# Сгенерирует %>
<form action="/posts" method="post" data-remote="true">
<input type="text" name="post[title]">
</form>
URL и скоуп на основе используемой модели:
<%= form_with model: Post.new do |form| %>
<%= form.text_field :title %>
<% end %>
<%# Сгенерирует %>
<form action="/posts" method="post" data-remote="true">
<input type="text" name="post[title]">
</form>
Существующая модель создает форму для обновления и заполняет значения для полей:
<%= form_with model: Post.first do |form| %>
<%= form.text_field :title %>
<% end %>
<%# Сгенерирует %>
<form action="/posts/1" method="post" data-remote="true">
<input type="hidden" name="_method" value="patch">
<input type="text" name="post[title]" value="<the title of the post>">
</form>
Несовместимости
Следующие изменения могут потребовать немедленных действий после обновления.
Транзакционные тесты с несколькими соединениями
Сейчас транзакционные тесты оборачивают все соединения Active Record в транзакции базы данных.
Когда тест порождает дополнительные треды, и эти треды получают соединения с базой данных, то эти соединения теперь обрабатываются по-особенному:
Тредам достается единственное соединение, которое находится посреди управляемой транзакции. Это позволяет убедиться, что все треды видят базу данных в одном и том же состоянии, игнорируя внешнюю транзакцию. Раньше такие дополнительные соединения были неспособны видеть, к примеру, строки фикстур.
Когда тред входит во вложенную транзакцию, он временно получает эксклюзивное использование этого соединения для поддержки изоляции.
Если ваши тесты сейчас полагаются на получение отдельного, внетранзакционного соединения для порождаемого треда, вам необходимо переключиться на более явное управление соединением.
Если ваши тесты порождают треды, и эти треды взаимодействуют, в то же время используя явные соединения с базой данных, то это может вызвать взаимную блокировку (deadlock).
Самым простым способом отказаться от подобного нового поведения является отключение транзакционных тестов для всех тестовых случаев, которые оно затрагивает.
Railties
За подробностями обратитесь к Changelog.
Удалено
Удалена устаревшая
config.static_cache_control. (commit)Удалена устаревшая
config.serve_static_files. (commit)Удален устаревший файл
rails/rack/debugger. (commit)Удалены устаревшие задачи:
rails:update,rails:template,rails:template:copy,rails:update:configsиrails:update:bin. (commit)Удалена устаревшая переменная среды
CONTROLLERдля задачиroutes. (commit)Удалена опция -j (--javascript) для команды
rails new. (Pull Request)
Значимые изменения
Добавлена общий раздел в
config/secrets.yml, которая будет загружена для всех сред. (commit)Конфигурационный файл
config/secrets.ymlтеперь загружается со всеми ключами в качестве символов. (Pull Request)Убран jquery-rails из стека по умолчанию. rails-ujs, который теперь встроен в Action View, включен в качестве адаптера UJS по умолчанию. (Pull Request)
Добавлена поддержка Yarn для новых приложений с помощью исполняемого файла yarn и package.json. (Pull Request)
В новых приложениях добавлена поддержка Webpack с помощью опции
--webpack, которая делегируется в гем rails/webpacker. (Pull Request)При генерации нового приложения инициализируется репозиторий Git, если не предоставлена опция
--skip-git. (Pull Request)Добавлены зашифрованные секретные данные в
config/secrets.yml.enc. (Pull Request)Отображается имя класса railtie в
rails initializers. (Pull Request)
Action Cable
За подробностями обратитесь к Changelog.
Значимые изменения
Добавлена поддержка
channel_prefixк Redis и событийным адаптерам Redis вcable.yml, чтобы избежать коллизии имен при использовании одного и того же сервера Redis с несколькими приложениями. (Pull Request)Для данных трансляции добавлен хук
ActiveSupport::Notifications. (Pull Request)
Action Pack
За подробностями обратитесь к Changelog.
Удалено
Удалена поддержка аргументов, не являющихся ключами, в
#process,#get,#post,#patch,#put,#deleteи#headдля классовActionDispatch::IntegrationTestиActionController::TestCase. (Commit, Commit)Удалены устаревшие
ActionDispatch::Callbacks.to_prepareиActionDispatch::Callbacks.to_cleanup. (Commit)Удалены устаревшие методы, относящиеся к фильтрам контроллера. (Commit)
Устарело
- Устарел
config.action_controller.raise_on_unfiltered_parameters. Он ничего не делает в Rails 5.1. (Commit)
Значимые изменения
Добавлены методы
directиresolveв DSL роутинга. (Pull Request)Добавлен новый класс
ActionDispatch::SystemTestCaseдля написания системных тестов вашего приложения. (Pull Request)
Action View
За подробностями обратитесь к Changelog.
Удалено
Удален устаревший
#original_exceptionвActionView::Template::Error. (commit)Удалена неправильно названная опция
encode_special_charsизstrip_tags. (Pull Request)
Устарело
- Устаревший обработчик ERB Erubis заменен в пользу Erubi. (Pull Request)
Значимые изменения
Обработчик raw шаблонов (обработчик шаблонов по умолчанию в Rails 5) теперь выводит HTML-безопасные строки. (commit)
Изменены
datetime_fieldиdatetime_field_tag, чтобы они генерировали полеdatetime-local. (Pull Request)Новый синтаксис в стиле Builder для тегов HTML (
tag.div,tag.brи т.д.) (Pull Request)Добавлен
form_with, объединяющий использованиеform_tagиform_for. (Pull Request)Добавлена опция
check_parametersвcurrent_page?. (Pull Request)
Action Mailer
За подробностями обратитесь к Changelog.
Значимые изменения
Разрешена установка произвольного типа содержимого, когда включены вложения и тело установлено как inline. (Pull Request)
Разрешена передача lambda в качестве значений в метод
default. (Commit)Добавлена поддержка параметризованного вызова рассыльщиков для совместного использования предварительных фильтров и значений по умолчанию различными экшнами рассыльщика. (Commit)
Входящие аргументы передаются в экшн рассыльщика в событии
process.action_mailerв ключеargs. (Pull Request)
Active Record
За подробностями обратитесь к Changelog.
Удалено
Удалена поддержка одновременной передачи аргументов и блока в
ActiveRecord::QueryMethods#select. (Commit)Удалены устаревшие скоупы i18n
activerecord.errors.messages.restrict_dependent_destroy.oneиactiverecord.errors.messages.restrict_dependent_destroy.many. (Commit)Удален устаревший аргумент принудительной перезагрузки для методов чтения одиночной и множественной связи. (Commit)
Удалена устаревшая поддержка передачи столбца в
#quote. (Commit)Удалены устаревшие аргументы
nameиз#tables. (Commit)Удалено устаревшее поведение
#tables, и#table_exists?, которое возвращало таблицы и представления, чтобы теперь возвращало только таблицы, но не представления. (Commit)Удален устаревший аргумент
original_exceptionвActiveRecord::StatementInvalid#initializeиActiveRecord::StatementInvalid#original_exception. (Commit)Удалена устаревшая поддержка передачи класса в качестве значения в запрос. (Commit)
Удалена устаревшая поддержка запросов с использованием запятых в LIMIT. (Commit)
Удален устаревший параметр
conditionsиз#destroy_all. (Commit)Удален устаревший параметр
conditionsиз#delete_all. (Commit)Удален устаревший метод
#load_schema_forв пользу#load_schema. (Commit)Удалена устаревшая конфигурация
#raise_in_transactional_callbacks. (Commit)Удалена устаревшая конфигурация
#use_transactional_fixtures. (Commit)
Устарело
Устаревший флажок
error_on_ignored_order_or_limitзаменен в пользуerror_on_ignored_order. (Commit)Устаревший
sanitize_conditionsзаменен в пользуsanitize_sql. (Pull Request)Устарел
supports_migrations?в адаптерах соединения. (Pull Request)Устарел
Migrator.schema_migrations_table_name, вместо него используйтеSchemaMigration.table_name. (Pull Request)Устарело использование
#quoted_idв квотировании и приведении типов. (Pull Request)Устарела передача аргумента
defaultв#index_name_exists?. (Pull Request)
Значимые изменения
Изменены первичные ключи по умолчанию на BIGINT. (Pull Request)
Поддержка виртуальных/генерированных столбцов для MySQL 5.7.5+ и MariaDB 5.2.0+. (Commit)
Добавлена поддержка лимитов в обработке пакетами. (Commit)
Транзакционные тесты теперь оборачивают все соединения Active Record в транзакцию базы данных. (Pull Request)
По умолчанию опускаются комментарии в выводе команды
mysqldump. (Pull Request)Починен
ActiveRecord::Relation#count, чтобы использовалсяEnumerable#countиз Ruby для подсчета записей, когда передан блок, вместо игнорирования переданного блока. (Pull Request)Передача флажка
"-v ON_ERROR_STOP=1"командеpsqlне подавляет ошибки SQL. (Pull Request)Добавлен
ActiveRecord::Base.connection_pool.stat. (Pull Request)Наследование непосредственно от
ActiveRecord::Migrationвызывает ошибку. Необходимо указывать версию Rails, для которой была написана миграция. (Commit)Вызывается ошибка, когда у связи
throughимеется избыточное имя противоположной связи. (Commit)
Active Model
За подробностями обратитесь к Changelog.
Удалено
Удалены устаревшие методы в
ActiveModel::Errors. (commit)Удалена устаревшая опция
:tokenizerв валидаторе длины. (commit)Удалено устаревшее поведение, прерывающее колбэки, когда возвращаемое значение равно false. (commit)
Значимые изменения
- Оригинальная строка, назначенная атрибуту модели, больше не замораживается некорректно. (Pull Request)
Active Job
За подробностями обратитесь к Changelog.
Удалено
Удалена устаревшая поддержка передачи класса адаптера в
.queue_adapter. (commit)Удален устаревший
#original_exceptionвActiveJob::DeserializationError. (commit)
Значимые изменения
Добавлена декларативная обработка исключений с помощью
ActiveJob::Base.retry_onиActiveJob::Base.discard_on. (Pull Request)После того, как все попытки провалятся, передается экземпляр задания, поэтому у вас будет доступ к таким вещам, как
job.arguments, для реализации собственной логики. (commit)
Active Support
За подробностями обратитесь к Changelog.
Удалено
Удален класс
ActiveSupport::Concurrency::Latch. (Commit)Удалена
halt_callback_chains_on_return_false. (Commit)Удалено устаревшее поведение, прерывающее колбэки, когда возвращаемое значение равно false. (Commit)
Устарело
Верхнеуровневый класс
HashWithIndifferentAccessустарел в пользуActiveSupport::HashWithIndifferentAccess. (Pull Request)Устарела передача строк в опции условий
:ifи:unlessдля методовset_callbackиskip_callback. (Commit)
Значимые изменения
Починен парсинг продолжительности и перемещения во времени, теперь он более последователен при смене DST. (Commit, Pull Request)
Unicode обновлен до версии 9.0.0. (Pull Request)
Добавлены Duration#before и #after в качестве псевдонимов для #ago и #since. (Pull Request)
Добавлен
Module#delegate_missing_toдля делегирования вызовов метода, не определенного для текущего объекта, на прокси-объект. (Pull Request)Добавлен
Date#all_day, возвращающий интервал, представляющий целый день для текущих даты и времени. (Pull Request)Представлены методы
assert_changesиassert_no_changesдля тестов. (Pull Request)Методы
travelиtravel_toтеперь вызывают ошибку на вложенных вызовах. (Pull Request)Обновлен
DateTime#changeдля поддержки usec и nsec. (Pull Request)
Благодарности
Взгляните на полный список контрибьюторов Rails, на людей, которые потратили много часов, сделав Rails стабильнее и надёжнее. Спасибо им всем.