Заметки о релизе Ruby on Rails 4.1
Ключевые новинки в Rails 4.1:
- Spring прелоадер
config/secrets.yml- Action Pack Variants (шаблоны, для разных устройств)
- Предпросмотр писем Action Mailer
Эти заметки о релизе покрывают только основные обновления. Чтобы узнать о различных багфиксах и изменениях, обратитесь к логам изменений или к списку коммитов в главном репозитории Rails на GitHub.
Обновление до Rails 4.1
Если вы обновляете существующее приложение, было бы хорошо иметь перед этим покрытие тестами. Также, до попытки обновиться до Rails 4.1, необходимо сначала обновиться до Rails 4.0 и убедиться, что приложение все еще выполняется так, как нужно. Список вещей, которые нужно выполнить для обновления доступен в руководстве Обновление Rails.
Основные изменения
Spring Application Preloader
Spring является прелоадером для Rails приложений. Он увеличивает скорость разработки, храня приложение запущенным в бэкграунде, поэтому при запуске тестов, задач rake или миграций, теперь загружать приложение каждый раз больше нет необходимости.
Новое Rails 4.1 приложение будет по умолчанию идти с "springified" бинстабами. Это означает, что
bin/rails и bin/rake, будут автоматически использовать преимущества предзагруженной среды spring.
Запуск rake задач:
bin/rake test:models
Запуск Rails команд:
bin/rails console
Spring интроспекция:
$ bin/spring status
Spring is running:
1182 spring server | my_app | started 29 mins ago
3656 spring app | my_app | started 23 secs ago | test mode
3746 spring app | my_app | started 10 secs ago | development mode
Обратитесь к Spring README, чтобы увидеть все возможности.
Обратитесь к руководству по Обновлению Rails
- как мигрировать существующее приложение, чтобы использовать данную возможность.
config/secrets.yml
Rails 4.1 генерирует новый файл secrets.yml в директории config. По умолчанию,
этот файл содержит secret_key_base приложения, но он так же может использоваться
для хранения других секретных данных, таких как ключи доступа к внешним API.
Секретные данные, добавляемые в этот файл, будут доступны с помощью Rails.application.secrets.
Например, для config/secrets.yml:
development:
secret_key_base: 3b7cd727ee24e8444053437c36cc66c3
some_api_key: SOMEKEY
Rails.application.secrets.some_api_key вернёт SOMEKEY в development окружении.
Обратитесь к руководству по Обновлению Rails
- как мигрировать существующее приложение, чтобы использовать данную возможность.
Action Pack Variants
Мы часто хотим рендерить разные типы шаблонов HTML/JSON/XML - для телефонов, планшетов и десктопных компьютеров. С помощью Variants - это легко.
Запрос Variants - это специальный формат запроса, например :tablet,
:phone, или :desktop.
Вы можете установить вариант шаблона в before_action:
request.variant = :tablet if request.user_agent =~ /iPad/
Отклик на варианты в экшне похож на отклик на форматы:
respond_to do |format|
format.html do |html|
html.tablet # renders app/views/projects/show.html+tablet.erb
html.phone { extra_setup; render ... }
end
end
Создайте отдельные шаблоны для каждого формата и варианта шаблона:
app/views/projects/show.html.erb
app/views/projects/show.html+tablet.erb
app/views/projects/show.html+phone.erb
Также можно упростить определение вариантов с помощью строчного синтаксиса:
respond_to do |format|
format.js { render "trash" }
format.html.phone { redirect_to progress_path }
format.html.none { render "trash" }
end
Предпросмотр писем Action Mailer
Предпросмотр писем Action Mailer, это возможность увидеть как будет выглядеть email, посетив специальный URL адрес, который покажет ваше письмо.
Вы реализуете класс, методы которого возвращают email объект, который необходимо проверить:
class NotifierPreview < ActionMailer::Preview
def welcome
Notifier.welcome(User.first)
end
end
Предпросмотр данного письма доступен по адресу http://localhost:3000/rails/mailers/notifier/welcome, так же можно увидеть полный список писем - http://localhost:3000/rails/mailers.
По умолчанию, эти превью-классы располагаются в test/mailers/previews.
Директорию можно легко изменить используя preview_path опцию.
Обратитесь к документации за подробным описанием.
Enum поля в Active Record
Объявляйте в базе данных enum поле, в котором числа связываются со значениями, но могут быть запрошены по имени
class Conversation < ActiveRecord::Base
enum status: [ :active, :archived ]
end
conversation.archived!
conversation.active? # => false
conversation.status # => "archived"
Conversation.archived # => Связь для всех архивированных бесед
Conversation.statuses # => { "active" => 0, "archived" => 1 }
Обратитесь к документации за подробным описанием.
Message Verifiers
Message verifiers могут быть использованы для генерации и верификации подписанных сообщений. Это полезно для безопасной передачи деликатных данных, таких как токены remember-me и прочие подобные.
Метод Rails.application.message_verifier возвращает новый Message Verifier, который подписывает сообщения с помощью ключа, созданного из secret_key_base и имени верификационного сообщения:
signed_token = Rails.application.message_verifier(:remember_me).generate(token)
Rails.application.message_verifier(:remember_me).verify(signed_token) # => token
Rails.application.message_verifier(:remember_me).verify(tampered_token)
# raises ActiveSupport::MessageVerifier::InvalidSignature
Module#concerning
Естественный и быстрый способ разделить ответственность внутри класса:
class Todo < ActiveRecord::Base
concerning :EventTracking do
included do
has_many :events
end
def latest_event
...
end
private
def some_internal_method
...
end
end
end
Этот пример является эквивалентом определения модуля EventTracking внутри класса,
расширение его ActiveSupport::Concern, и дальнейшего смешивания его с классом
Todo.
Обратитесь к документации за подробным описанием и способами использования.
CSRF защита от <script> тегов
Защита от подделки межсайтовых запросов (CSRF) сейчас также покрывает GET запросы с откликами JavaScript. Это предотвращает от ссылок посторонних сайтов на ваши JavaScript URL и попыток запуска его для извлечения конфиденциальных данных.
Это означает, что каждый из ваших тестов, который использует .js URL, теперь будет провален CSRF защитой, если не используется xhr. Обновите ваши тесты, чтобы быть уверенными в XmlHttp запросах. Вместо post :create, format: :js, переключитесь на явное
xhr :post, :create, format: :js.
Railties
Пожалуйста, обратитесь к Changelog для просмотра всех изменений.
Удалено
Удалёна задача rake
update:application_controller.Удалён устаревший
Rails.application.railties.engines.Удалён устаревший
threadsafe!из конфигурации Rails.Удалён устаревший метод
ActiveRecord::Generators::ActiveModel#update_attributesв пользуActiveRecord::Generators::ActiveModel#update.Удалёна устаревшая
config.whiny_nilsопция.Удалёны устаревшая задача rake для запуска тестов:
rake test:uncommittedиrake test:recent.
Значимые изменения
Spring прелоадер теперь устанавливается по умолчанию для новых приложений. Он использует группу development в Gemfile, поэтому не будет установлен в production. (Pull Request)
Переменная окружения
BACKTRACE, которая показывает нефильтрованные бэктрейсы для проваленных тестов. (Commit)Возможность конфигурирования
MiddlewareStack#unshift. (Pull Request)Добавлен метод
Application#message_verifierкоторы возвращает верификационное сообщение. (Pull Request)Файл
test_help.rb, который требуется сгенерированным по умолчанию тестом, автоматически сохраняет тестовую базу данных актуальнойdb/schema.rb(илиdb/structure.sql). Он вызывает ошибку, если перезагрузка схемы не решает проблемы отложенных миграций. Настраивается с помощью опцииconfig.active_record.maintain_test_schema = false. (Pull Request)
Action Pack
Пожалуйста обратитесь к Changelog для просмотра всех изменений.
Удалено
Удалён устаревший Rails fallback для интеграционных тестов, используйте
ActionDispatch.test_app.Удалена устаревшая конфигурация
page_cache_extension.Удалён устаревший
ActionController::RecordIdentifier, используйте вместо негоActionView::RecordIdentifier.Удалены устаревшие константы из Action Controller:
| Удалено | Преемник |
|---|---|
| ActionController::AbstractRequest | ActionDispatch::Request |
| ActionController::Request | ActionDispatch::Request |
| ActionController::AbstractResponse | ActionDispatch::Response |
| ActionController::Response | ActionDispatch::Response |
| ActionController::Routing | ActionDispatch::Routing |
| ActionController::Integration | ActionDispatch::Integration |
| ActionController::IntegrationTest | ActionDispatch::IntegrationTest |
Значимые изменения
protect_from_forgeryтакже предотвращает от CSRF атак, проводимых через<script>теги. Обновите ваши тесты и используйтеxhr :get, :foo, format: :jsвместоget :foo, format: :js. (Pull Request)#url_forпринимает хэш с опциями внутри массива. (Pull Request)Добавлен метод
session#fetchкоторый ведёт себя аналогично Hash#fetch, за исключением того, что возвращаемое значение всегда сохраняется в сессию. (Pull Request)Полностью отделён Action View от Action Pack. (Pull Request)
Логируется, какие ключи были затронуты при "deep munging". (Pull Request)
Новая конфигурационная опция
config.action_dispatch.perform_deep_mungeдля включения "deep munging" параметров, использующегося в связи с уязвимостью безопасности CVE-2013-0155. (Pull Request)Новая конфигурационная опция
config.action_dispatch.cookies_serializerдля определения сериализатора для подписанных и зашифрованных куки. (Pull Requests 1, 2 / Подробнее)Добавлены
render :plain,render :htmlиrender :body. (Pull Request / Подробнее)
Action Mailer
Пожалуйста обратитесь к Changelog для просмотра всех изменений.
Значимые изменения
Добавлена особенность предварительного просмотра писем на основе гема mail_view от 37 Signals. (Commit)
Инструмент генерации сообщений Action Mailer. Время, потраченное на генерацию сообщения, записывается в лог. (Pull Request)
Active Record
Пожалуйста обратитесь к Changelog для просмотра всех изменений.
Удалено
Удалена устаревшая возможность передачи nil следующим методам
SchemaCache:primary_keys,tables,columnsиcolumns_hash.Удалён устаревший блок фильтр из
ActiveRecord::Migrator#migrate.Удалён устаревший конструктор строк из
ActiveRecord::Migrator.Удалёно устаревшее использование
scopeбез передачи вызываемого объекта.Удалён устаревший метод
transaction_joinable=в пользуbegin_transactionс опциейd:joinable.Удалён устаревший метод
decrement_open_transactions.Удалён устаревший метод
increment_open_transactions.Удалён устаревший метод
PostgreSQLAdapter#outside_transaction?. Вместо него вы можете использовать#transaction_open?.Удалён устаревший метод
ActiveRecord::Fixtures.find_table_nameв пользуActiveRecord::Fixtures.default_fixture_model_name.Удален устаревший метод
columns_for_removeизSchemaStatements.Удалён устаревший
SchemaStatements#distinct.Перемещён устаревший
ActiveRecord::TestCaseв тестовый набор Rails. Данный класс больше не публичный и используется только для внутреннего тестирования Rails.Удалена поддержка устаревшей опции
:restrictдля:dependentв ассоциациях.Удалена поддержка устаревших опций
:delete_sql,:insert_sql,:finder_sqlи:counter_sqlв ассоциациях.Удален устаревший метод
type_cast_codeиз ActiveRecord::ConnectionAdapters::Column.Удален устаревший метод
ActiveRecord::Base#connection. Убедитесь, что вы обращаетесь к соединению через класс.Удалены устаревшие предупреждения
auto_explain_threshold_in_seconds.Удалена устаревшая опция
:distinctизRelation#count.Удалены устаревшие методы
partial_updates,partial_updates?иpartial_updates=.Удален устаревший метод
scoped.Удален устаревший метод
default_scopes?.Удалено неявное соединение связей, которое были объявлено устаревшим в 4.0.
Удален из зависимостей гем
activerecord-deprecated_finders. За подробностями обратитесь в README гема.implicit_readonlyбольше не используется. Пожалуйста, используйте методreadonlyдля явной пометки записи какreadonly. (Pull Request)
Устарело
Устарел неиспользуемый метод
quoted_locking_column.Устарел метод
ConnectionAdapters::SchemaStatements#distinct, так как больше не используется внутри Rails. (Pull Request)Устарели задачи
rake db:test:*, так как теперь тестовая база данных автоматически поддерживается. Смотрите заметки о релизе к railties. (Pull Request)Устарели неиспользуемые
ActiveRecord::Base.symbolized_base_classиActiveRecord::Base.symbolized_sti_nameбез какой-либо замены. Commit
Значимые изменения
Скоупы по умолчанию больше не переопределяются присоединенными условиями.
До этого изменения, при определении в модели
default_scope, он переопределялся присоединенными условиями на то же поле. Теперь он объединяется, как и любой другой скоуп. Подробнее.Добавлен метод
ActiveRecord::Base.to_paramдля удобного создания "красивых" URL, используя атрибуты или методы модели. (Pull Request)Добавлена опция
ActiveRecord::Base.no_touching, которая позволяет игнорировать "touch" на модели. (Pull Request)Унификация преобразования булевых типов для
MysqlAdapterиMysql2Adapter.type_castвернёт1дляtrueи0дляfalse. (Pull Request).unscopeтеперь удаляет условия, определённые в скоупе по умолчаниюdefault_scope. (Commit)Добавлен метод
ActiveRecord::QueryMethods#rewhere, который перезаписывает существующее условие where, использовавшееся ранее в цепочке запросов. (Commit)Расширен метод
ActiveRecord::Base#cache_key, который теперь принимает опциональный список timestamp атрибутов, из которых будет использоваться самое больше. (Commit)Добавлен
ActiveRecord::Base#enumдля описания enum атрибутов, в которых значения связаны с числами в базе данных, но могут быть запрошены с помощью имени. (Commit)Приведение типов для значений json при записи, таким образом значение не изменится при чтении из базы данных. (Pull Request)
Приведение типов для значений hstore при записи, таким образом значение не изменится при чтении из базы данных. (Commit)
Стало возможным использование
next_migration_numberдля сторонних генераторов. (Pull Request)Вызов
update_attributesтеперь бросает исключениеArgumentError, когда получит аргументnil. Более конкретно - будет ошибка, если передаваемый аргумент не отвечает наstringify_keys. (Pull Request)CollectionAssociation#first/#last(напримерhas_many) ограничивает результат запроса операторомLIMITв запросе на выборку, вместо загрузки полной коллекции. (Pull Request)Метод
inspectвызываемый на моделях Active Record не инициализирует нового подключения. Это означает, что вызовinspectбольше не вызывает исключения, когда база данных отсутствует. (Pull Request)Удалено ограничение столбцов для
count, позволив базе данных вызвать исключение, если SQL не валидный. (Pull Request)Rails теперь автоматически определяет противоположные связи. Если вы не установили опцию
:inverse_of, Active Record самостоятельно определит противоположную связь, основываясь на эвристике. (Pull Request)Оперирование псевдонимами атрибутов в ActiveRecord::Relation. При использовании символьных ключей, ActiveRecord теперь переведет имена-псевдонимы атрибутов к фактическим именам столбцов, используемых в базе данных. (Pull Request)
Шаблоны ERB в фикстурах больше не вычисляются в контексте главного объекта. Методы хелперов, использующиеся в нескольких фикстурах, должны объявляться в модулях, включённых в
ActiveRecord::FixtureSet.context_class. (Pull Request)Не создается или сбрасывается тестовая база данных, если явно определен RAILS_ENV. (Pull Request)
У
Relationбольше нет мутирующих методов, таких как#map!и#delete_if. Преобразовывайте в массив с помощью#to_aперед использованием этих методов. (Pull Request)find_in_batches,find_each,Result#eachиEnumerable#index_byтеперь возвращаютEnumerator, который может вычислять свой размер. (Pull Request)scope,enumи связи теперь вызовут ошибку при "опасном" конфликте имен. (Pull Request, Pull Request)Методы с
secondпоfifthработают так же, как метод поискаfirst. (Pull Request)Метод
touchвызывает колбэкиafter_commitиafter_rollback. (Pull Request)Доступны частичные индексы для
sqlite >= 3.8.0. (Pull Request)Миграция
change_column_nullстала обратимой. (Commit)Добавлен флажок для отключения дампа схемы после миграции. Он установлен
falseпо умолчанию в среде production для новых приложений. (Pull Request)
Active Model
Пожалуйста обратитесь к Changelog для просмотра всех изменений.
Устарело
- Устарел
Validator#setup. Теперь необходимые настройки устанавливаются вручную в конструкторе валидатора. (Commit)
Значимые изменения
В
ActiveModel::Dirtyдобавлены новые методы APIreset_changesиchanges_applied, которые контролируют изменения состояния.Возможность определить несколько контекстов при определении валидации. (Pull Request)
Теперь
attribute_changed?принимает хэш для проверки, изменился ли атрибут:fromи/или:toзаданного значения. (Pull Request)
Active Support
Пожалуйста обратитесь к Changelog для просмотра всех изменений.
Удалено
Удалена зависимость
MultiJSON. Теперь,ActiveSupport::JSON.decodeбольше не принимает хэш опций дляMultiJSON. (Pull Request / Подробнее)Удалена поддержка для хука
encode_json, используемого для преобразования произвольных объектов в JSON. Данный функционал извлечен в гем activesupport-json_encoder. (Связанный Pull Request / Подробнее)Удалено без замены
ActiveSupport::JSON::Variable.Удалено устаревшее расширение ядра
String#encoding_aware?(core_ext/string/encoding).Удалён устаревший метод
Module#local_constant_namesв пользуModule#local_constants.Удалён устаревший метод
DateTime.local_offsetв пользуDateTime.civil_from_format.Удалено устаревшее расширение ядра
Logger(core_ext/logger.rb).Удалены устаревшие методы
Time#time_with_datetime_fallback,Time#utc_timeиTime#local_timeв пользуTime#utcиTime#local.Удалён устаревший метод
Hash#diffбез замены.Удалён устаревший метод
Date#to_time_in_current_zoneв пользуDate#in_time_zone.Удалён устаревший метод
Proc#bindбез замены.Удалены устаревшие методы
Array#uniq_byиArray#uniq_by!, используйте нативные методы классаArray#uniqиArray#uniq!.Удалён устаревший
ActiveSupport::BasicObject, используйтеActiveSupport::ProxyObjectвзамен.Удалён устаревший
BufferedLogger, используйтеActiveSupport::Loggerвзамен.Удалены устаревшие методы
assert_presentиassert_blank, используйтеassert object.blank?иassert object.present?взамен.Удалён устаревший метод
#filterдля объектов фильтра, используйте взамен соответствующие методы (т.е.#beforeдля предварительного фильтра).Убрано неправильное преобразование 'cow' => 'kine' из инфлектора по-умолчанию. (Commit)
Устарело
Устарели
Numeric#{ago,until,since,from_now}, пользователь должен явно преобразовывать значение в AS::Duration, например.5.ago=>5.seconds.ago(Pull Request)Устарело имя подключаемой директории
active_support/core_ext/object/to_json. Подключайтеactive_support/core_ext/object/jsonвзамен. (Pull Request)Устарело
ActiveSupport::JSON::Encoding::CircularReferenceError. Данный функционал был выделен в гем activesupport-json_encoder. (Pull Request / Подробности)Устарела опция
ActiveSupport.encode_big_decimal_as_string. Данный функционал был выделен в гем activesupport-json_encoder. (Pull Request / Подробности)Устарела произвольная сериализация
BigDecimal. (Pull Request)
Значимые изменения
JSON encoder из
ActiveSupportбыл переписан, для того, чтобы воспользоваться гемом JSON, а не создавать свой велосипед. (Pull Request / Подробности)Улучшена совместимость с гемом JSON. (Pull Request / Подробности)
Добавлены методы
ActiveSupport::Testing::TimeHelpers#travelи#travel_to. Которые изменяют текущее время на заданное время или продолжительность, который вы укажите, с помощью стабаTime.nowиDate.today. (Pull Request)Добавлен
ActiveSupport::Testing::TimeHelpers#travel_back. Этот метод возвращает текущее время к оригинальному состоянию, убирая стабы, добавленныеtravelиtravel_to. (Pull Request)Добавлен метод
Numeric#in_milliseconds, например1.hour.in_milliseconds, результат которого можно скармливать в функции JavaScript, такие какgetTime(). (Commit)Добавлены методы
Date#middle_of_day,DateTime#middle_of_dayиTime#middle_of_day. Так же добавлены псевдонимыmidday,noon,at_midday,at_noonиat_middle_of_day. (Pull Request)Добавлены
Date#all_week/month/quarter/yearдля генерации интервалов дат. (Pull Request)Добавлены
Time.zone.yesterdayиTime.zone.tomorrow. (Pull Request)Добавлен метод
String#remove(pattern)как сокращение дляString#gsub(pattern,''). (Commit)Добавлены
Hash#compactиHash#compact!для устранения из хэша элементов со значением nil. (Pull Request)blank?иpresent?гарантированно возвращают булевы синглтоны. (Commit)По умолчанию новая конфигурация
I18n.enforce_available_localesравнаtrue, что означает, чтоI18nубедится, что все локали, передаваемые в него, должны быть объявлены в спискеavailable_locales. (Pull Request)Представлен Module#concerning: естественный и простой способ разделить ответственность внутри класса. (Commit)
Добавлен
Object#present_inдля упрощения ведения белых списков значений. (Commit)
Благодарности
Взгляните на полный список контрибьюторов Rails, на людей, которые потратили много часов, сделав Rails стабильнее и надёжнее. Спасибо им всем.