Заметки о релизе Ruby on Rails 4.2

Ключевые новинки в Rails 4.2:

  • Active Job
  • Асинхронные письма
  • Adequate Record
  • Веб-консоль
  • Поддержка внешних ключей

Эти заметки о релизе покрывают только основные изменения. Чтобы узнать о других обновлениях, различных исправлениях программных ошибок и изменениях, обратитесь к логам изменений или к списку коммитов в главном репозитории Rails на GitHub.


1. Апгрейд до Rails 4.2

Прежде чем апгрейднуть существующее приложение, было бы хорошо иметь перед этим покрытие тестами. Также, до попытки обновиться до Rails 4.2, необходимо сначала произвести апгрейд до Rails 4.1 и убедиться, что приложение все еще выполняется так, как нужно. Список вещей, которые нужно выполнить для апгрейда доступен в руководстве Апгрейд Ruby on Rails.

2. Основные особенности

2.1. Active Job

Active Job — это новый фреймворк в Rails 4.2. Это обычный интерфейс для систем очередей, таких как Resque, Delayed Job, Sidekiq и так далее.

Задания, написанные с помощью Active Job API, запускаются в любой поддерживаемой очереди благодаря их соответствующим адаптерам. Active Job поставляется преднастроенным с встроенным исполнителем, выполняющим задания сразу.

Часто заданиям необходимо принимать объекты Active Record в качестве аргументов. Active Job передает ссылки на объект как URI (единые идентификаторы ресурса) вместо маршаллинга самого объекта. Новая библиотека Global ID создает URI и ищет объекты, на которые они ссылаются. Передача объектов Active Record как атрибутов задания внутри устроена как использование Global ID.

Например, если trashable это объект Active Record, тогда это задание будет запускаться без необходимости сериализации:

class TrashableCleanupJob < ActiveJob::Base
  def perform(trashable, depth)
    trashable.cleanup(depth)
  end
end

За подробностями обратитесь к руководству Основы Active Job.

2.2. Асинхронные письма

Созданный на основе Active Job, сейчас Action Mailer имеет метод deliver_later, добавляющий отсылку вашего письма с помощью очереди, таким образом, не блокируя контроллер или модель. если очередь асинхронная (встроенная очередь по умолчанию будет блокировать).

Отсылка писем прямо сейчас все еще возможна с помощью deliver_now.

2.3. Adequate Record

Adequate Record — это набор улучшений производительности в Active Record, сделавший обычные вызовы методов find и find_by и некоторых запросов связей до двух раз быстрее.

Он работает, кэшируя обычные запросы SQL как подготовленные выражения (prepared statements) и повторно используя их при подобных вызовах, опуская большую часть работы по генерации запроса при последующих вызовах. За подробностями обратитесь к публикации Aaron Patterson.

Active Record будет пользоваться преимуществами этой особенности на поддерживаемых операциях автоматически, без какого-либо вовлечения пользователя или изменения кода. Вот несколько примеров поддерживаемых операций:

Post.find(1)  # Первый вызов генерирует и кэширует подготовленное выражение
Post.find(2)  # Последующие вызовы повторно используют закэшированное подготовленное выражение

Post.find_by_title('first post')
Post.find_by_title('second post')

Post.find_by(title: 'first post')
Post.find_by(title: 'second post')

post.comments
post.comments(true)

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

Кэширование не используется в следующих сценариях:

  • В модели есть скоуп по умолчанию
  • Модель использует наследование с единой таблицей (STI)
  • find со списком ids. Т.е.:

    # не кэшируются
    Post.find(1,2,3)
    Post.find([1,2])
    
  • find_by с фрагментом SQL:

    Post.find_by('published_at < ?', 2.weeks.ago)
    

2.4. Веб-консоль

Новые приложения, генерируемые начиная с Rails 4.2, поставляются с гемом Web Console по умолчанию. Веб-консоль добавляет интерактивную консоль Ruby на каждой странице ошибки и хелпер вью и контроллеров console.

Интерактивная консоль на страницах ошибок позволяет выполнять код в контексте места, где было вызвано исключение. Хелпер вью console при вызове в любом месте вью или контроллера запускает интерактивную консоль в последнем контексте, как только завершится рендеринг.

2.5. Поддержка внешних ключей

DSL миграций теперь поддерживает добавление или удаление внешних ключей. Также они выгружаются в schema.rb. В настоящее время внешние ключи поддерживаются только адаптерами mysql, mysql2 и postgresql.

# добавляет внешний ключ на `articles.author_id`, ссылающийся на `authors.id`
add_foreign_key :articles, :authors

# добавляет внешний ключ на `articles.author_id`, ссылающийся на `users.lng_id`
add_foreign_key :articles, :users, column: :author_id, primary_key: "lng_id"

# удаляет внешний ключ на `accounts.branch_id`
remove_foreign_key :accounts, :branches

# удаляет внешний ключ на `accounts.owner_id`
remove_foreign_key :accounts, column: :owner_id

Смотрите полное описание в документации API для add_foreign_key и remove_foreign_key.

3. Несовместимости

Ранее устаревшая функциональность была убрана. Обратитесь к отдельным компонентам за информацией о новых устареваниях в этом релизе.

Следующие изменения требуют немедленных действий при апгрейде.

3.1. render со строковым аргументом

Раньше вызов в контроллере render "foo/bar" был эквивалентом render file: "foo/bar". В Rails 4.2 это стало означать render template: "foo/bar". Если нужно рендерить файл, измените свой код на использования явной формы (render file: "foo/bar").

3.2. respond_with / метод класса respond_to

Методы respond_with и соответствующий метод класса respond_to были перемещены в гем responders. Добавьте gem "responders", "~> 2.0" в свой Gemfile для использования:

# app/controllers/users_controller.rb

class UsersController < ApplicationController
  respond_to :html, :json

  def show
    @user = User.find(params[:id])
    respond_with @user
  end
end

Метод экземпляра respond_to не был затронут:

# app/controllers/users_controller.rb

class UsersController < ApplicationController
  def show
    @user = User.find(params[:id])
    respond_to do |format|
      format.html
      format.json { render json: @user }
    end
  end
end

3.3. Хост по умолчанию для rails server

Из-за изменения в Rack, по умолчанию rails server теперь ждет запросов на localhost вместо 0.0.0.0. Это минимально затрагивает стандартный процесс разработки, так как и http://127.0.0.1:3000, и http://localhost:3000 будут работать, как и прежде на вашей машине.

Однако, это изменение не позволяет доступ к серверу Rails с другой машины, например, если ваша среда разработки в виртуальной машине, и вы хотите доступ к ней с хоста. В таких случаях запускайте сервер с помощью rails server -b 0.0.0.0, чтобы восстановить старое поведение.

Если так сделаете, не забудьте правильно настроить свой файрвол, чтобы только доверенные машины вашей сети имели доступ к вашему серверу разработки.

3.4. Изменены символы для опции статуса у render

Из-за изменения в Rack, символы, которые метод render принимает для опции :status, были изменены:

  • 306: :reserved был убран.
  • 413: :request_entity_too_large был переименован в :payload_too_large.
  • 414: :request_uri_too_long был переименован в :uri_too_long.
  • 416: :requested_range_not_satisfiable был переименован в :range_not_satisfiable.

Имейте в виду, что если вызывается render с неизвестным символом, статус отклика будет по умолчанию 500.

3.5. Санитайзер HTML

Санитайзер HTML был заменен новой, более надежной, реализацией, созданной на основе Loofah и Nokogiri. Новый санитайзер более безопасный и его санация более мощная и гибкая.

Из-за нового алгоритма, санированный результат может быть различным для определенных патологических входных данных.

Если у вас есть особая необходимость в точном результате от старого санитайзера , можете добавить гем rails-deprecated_sanitizer в свой Gemfile, и получите старое поведение. Этот гем не будет выдавать предостережения об устаревании, поскольку он опциональный.

rails-deprecated_sanitizer будет поддерживаться только для Rails 4.2; он не будет поддерживаться для Rails 5.0.

Подробнее об изменениях в новом санитайзере смотрите эту публикацию в блоге.

3.6. assert_select

assert_select теперь базируется на Nokogiri.

В результате некоторые ранее валидные селекторы теперь не поддерживаются. Если ваше приложение использует любое из этих написаний, их нужно обновить:

  • Значения в селекторах атрибутов необходимо заключать в кавычки, если они содержат не буквенно-цифровые символы.

    # до
    a[href=/]
    a[href$=/]
    
    # теперь
    a[href="/"]
    a[href$="/"]
    
  • DOM, созданные из источника HTML, содержащего невалидный HTML с неправильно вложенными элементами, могут отличаться.

    Например:

    # содержимое: <div><i><p></i></div>
    
    # раньше:
    assert_select('div > i')  # => true
    assert_select('div > p')  # => false
    assert_select('i > p')    # => true
    
    # сейчас:
    assert_select('div > i')  # => true
    assert_select('div > p')  # => true
    assert_select('i > p')    # => false
    
  • Если выбираемые данные содержат сущности, значение для сравнения раньше было чистым (т.е. AT&amp;T), а сейчас вычисленное (т.е. AT&T).

    # содержимое: <p>AT&amp;T</p>
    
    # раньше:
    assert_select('p', 'AT&amp;T')  # => true
    assert_select('p', 'AT&T')      # => false
    
    # сейчас:
    assert_select('p', 'AT&T')      # => true
    assert_select('p', 'AT&amp;T')  # => false
    

Кроме того, у замен изменился синтаксис.

Теперь можно использовать селектор :match, схожий с CSS:

assert_select ":match('id', ?)", 'comment_1'

Кроме того, замены Regexp выглядят иначе, когда проваливается оператор контроля. Обратите внимание, как /hello/ тут:

assert_select(":match('id', ?)", /hello/)

становится "(?-mix:hello)":

Expected at least 1 element matching "div:match('id', "(?-mix:hello)")", found 0..
Expected 0 to be >= 1.

Подробнее об assert_select смотрите в документации по тестированию Dom в Rails.

4. Railties

За подробностями обратитесь к Changelog.

4.1. Удалено

  • Опция --skip-action-view была убрана из генератора приложения. (Pull Request)

  • Команда rails application была убрана без замены. (Pull Request)

4.2. Устарело

  • Устарел отсутствующий config.log_level для окружений production. (Pull Request)

  • Устарел rake test:all в пользу rake test, так как он теперь запускает все тесты в папке test. (Pull Request)

  • Устарел rake test:all:db в пользу rake test:db. (Pull Request)

  • Устарел Rails::Rack::LogTailer без замены. (Commit)

4.3. Значимые изменения

  • Представлен web-console в Gemfile приложения по умолчанию. (Pull Request)

  • Добавлена опция required для связей в генераторе модели. (Pull Request)

  • Представлено пространство имен x для определения произвольных конфигурационных опций:

    # config/environments/production.rb
    config.x.payment_processing.schedule = :daily
    config.x.payment_processing.retries  = 3
    config.x.super_debugger              = true
    

    Затем эти опции доступны в объекте configuration:

    Rails.configuration.x.payment_processing.schedule # => :daily
    Rails.configuration.x.payment_processing.retries  # => 3
    Rails.configuration.x.super_debugger              # => true
    

    (Commit)

  • Представлен Rails::Application.config_for для загрузки конфигурации для текущего окружения.

    # config/exception_notification.yml
    production:
      url: http://127.0.0.1:8080
      namespace: my_app_production
    development:
      url: http://localhost:3001
      namespace: my_app_development
    
    # config/environments/production.rb
    Rails.application.configure do
      config.middleware.use ExceptionNotifier, config_for(:exception_notification)
    end
    

    (Pull Request)

  • Представлена опция --skip-turbolinks для генератора приложения, чтобы не генерировать интеграцию с turbolinks. (Commit)

  • Представлен скрипт bin/setup как соглашение для автоматической настройки для быстрого развертывания вашего приложения. (Pull Request)

  • Изменено значение по умолчанию для config.assets.digest на true в среде development. (Pull Request)

  • Представлен API для регистрации новых расширений для rake notes. (Pull Request)

  • Представлен колбэк after_bundle для использования в шаблонах Rails. (Pull Request)

  • Представлен Rails.gem_version как удобный метод для возврата Gem::Version.new(Rails.version). (Pull Request)

5. Action Pack

За подробностями обратитесь к Changelog.

5.1. Удалено

  • respond_with и метод класса respond_to были убраны из Rails и перемещены в гем responders (версия 2.0). Добавьте gem "responders", "~> 2.0" в свой Gemfile, чтобы продолжать использовать эти особенности. (Pull Request, подробнее)

  • Убран устаревший AbstractController::Helpers::ClassMethods::MissingHelperError в пользу AbstractController::Helpers::MissingHelperError. (Commit)

5.2. Устарело

  • Устарела опция only_path в хелперах *_path. (Commit)

  • Устарели assert_tag, assert_no_tag, find_tag и find_all_tag в пользу assert_select. (Commit)

  • Устарела поддержка опции :to в роутере со значением символом или строкой без символа "#":

    get '/posts', to: MyRackApp    => (Не требуется изменения)
    get '/posts', to: 'post#index' => (Не требуется изменения)
    get '/posts', to: 'posts'      => get '/posts', controller: :posts
    get '/posts', to: :index       => get '/posts', action: :index
    

    (Commit)

  • Устарела поддержка строковых ключей в хелперах URL:

    # плохо
    root_path('controller' => 'posts', 'action' => 'index')
    
    # хорошо
    root_path(controller: 'posts', action: 'index')
    

    (Pull Request)

5.3. Значимые изменения

  • Семейство методов *_filter убраны из документации. Их использование не рекомендуется в пользу семейства методов *_action:

    after_filter          => after_action
    append_after_filter   => append_after_action
    append_around_filter  => append_around_action
    append_before_filter  => append_before_action
    around_filter         => around_action
    before_filter         => before_action
    prepend_after_filter  => prepend_after_action
    prepend_around_filter => prepend_around_action
    prepend_before_filter => prepend_before_action
    skip_after_filter     => skip_after_action
    skip_around_filter    => skip_around_action
    skip_before_filter    => skip_before_action
    skip_filter           => skip_action_callback
    

    Если ваше приложение в настоящее время зависит от этих методов, следует их заменить на методы *_action. Они будут объявлены устаревшими в будущем и когда-нибудь будут убраны из Rails.

    (Commit 1, 2)

  • render nothing: true или рендеринг тела nil больше не добавляет одиночный пробел в тело отклика. (Pull Request)

  • Rails теперь автоматически включает дайджест шаблона в ETag. (Pull Request)

  • Сегменты, передаваемые в хелперы URL, теперь автоматически экранируются. (Commit)

  • Представлена опция always_permitted_parameters для настройки, какие параметры разрешены глобально. Значение по умолчанию для этой настройки ['controller', 'action']. (Pull Request)

  • Добавлен метод HTTP MKCALENDAR из RFC 4791. (Pull Request)

  • Уведомления *_fragment.action_controller теперь включают имена контроллера и экшна в payload. (Pull Request)

  • Улучшена страница Routing Error с помощью нечеткого (fuzzy) соответствия для поиска маршрутов. (Pull Request)

  • Добавлена опция для отключения логирования ошибок CSRF. (Pull Request)

  • Когда сервер Rails настроен обслуживать статичные ассеты, gzip ассеты также будут обслужены, если клиент их поддерживает и предварительно генерирует файл gzip (.gz) на диск. По умолчанию asset pipeline генерирует файлы .gz для всех сжимаемых ассетов. Обслуживание gzip файлов минимизирует передаваемые данные и ускоряет запрос к ассету. Всегда используйте CDN, если обслуживаете файлы ассетов на сервере Rails в production. (Pull Request)

  • При вызове хелперов process в интеграционном тесте, пути необходим начальный слэш. Раньше его можно было опустить, но это был побочный продукт реализации, а не специальная особенность, т.е.:

    test "list all posts" do
      get "/posts"
      assert_response :success
    end
    

6. Action View

За подробностями обратитесь к Changelog.

6.1. Устарело

  • Устарели AbstractController::Base.parent_prefixes. Переопределите AbstractController::Base.local_prefixes когда хотите изменить, где следует искать вью. (Pull Request)

  • Устарел ActionView::Digestor#digest(name, format, finder, options = {}). Аргументы должны быть переданы как хэш. (Pull Request)

6.2. Значимые изменения

  • render "foo/bar" теперь расширяется до render template: "foo/bar" вместо render file: "foo/bar". (Pull Request)

  • Хелперы форм больше не генерируют элемент <div> со встроенным CSS вокруг скрытых полей. (Pull Request)

  • Представлена специальная локальная переменная #{partial_name}_iteration для использования с партиалами, рендерящимися с коллекцией. Она предоставляет доступ к текущему состоянию итерации с помощью методов index, size, first? и last?. (Pull Request)

  • Местозаполнитель I18n следует тем же соглашениям, что и label I18n. (Pull Request)

7. Action Mailer

За подробностями обратитесь к Changelog.

7.1. Устарело

  • Устарели хелперы *_path в рассыльщиках. Всегда используйте вместо них хелперы *_url. (Pull Request)

  • Устарели deliver / deliver! в пользу deliver_now / deliver_now!. (Pull Request)

7.2. Значимые изменения

  • link_to и url_for по умолчанию генерируют абсолютные URL в шаблонах, больше нет необходимости передавать only_path: false. (Commit)

  • Представлен deliver_later, который добавляет в очередь задание для доставки писем асинхронно. (Pull Request)

  • Добавлена конфигурационная опция show_previews для включения предпросмотра писем вне окружения разработки. (Pull Request)

8. Active Record

За подробностями обратитесь к Changelog.

8.1. Удалено

  • Удален cache_attributes и сотоварищи. Все атрибуты кэшируются. (Pull Request)

  • Удален устаревший метод ActiveRecord::Base.quoted_locking_column. (Pull Request)

  • Удален устаревший метод ActiveRecord::Migrator.proper_table_name. Используйте вместо него метод экземпляра proper_table_name на ActiveRecord::Migration. (Pull Request)

  • Удален неиспользуемый тип :timestamp. Прозрачно добавлен как псевдоним к :datetime во всех случаях. Исправлены несоответствия, когда типы столбцов используются вне Active Record, например для сериализации XML. (Pull Request)

8.2. Устарело

  • Устарело проглатывание ошибок в after_commit и after_rollback. (Pull Request)

  • Устарела сломанная поддержка автоматического определения кэширующих счетчиков на связях has_many :through. Вместо этого следует вручную указывать кэширующий счетчик на связях has_many и belongs_to для записей through. (Pull Request)

  • Устарела передача объектов Active Record в .find или .exists?. Вместо этого сначала вызывайте id на объектах. (Commit 1, 2)

  • Устарела недоделанная поддержка интервальных значений PostgreSQL с исключенными концами (полуинтервалов). Сейчас мы переводим интервалы PostgreSQL в интервалы Ruby. Это преобразование не полностью возможно, поскольку интервалы Ruby не поддерживают исключение концов.

    Текущее решение увеличения конца интервала неправильное и устарело. Для подтипов, в которых мы не знаем как увеличить (т.е. где не определен succ), он вызовет ArgumentError для интервалов с исключенными концами.

    (Commit)

  • Устарел вызов DatabaseTasks.load_schema без соединения. Вместо него используйте DatabaseTasks.load_schema_current. (Commit)

  • Устарел sanitize_sql_hash_for_conditions без замены. Для выполнения запросов и обновлений предпочтительным API является использование Relation. (Commit)

  • Устарели add_timestamps и t.timestamps без передачи опции :null. Значение по умолчанию null: true изменится в Rails 5 на null: false. (Pull Request)

  • Устарел Reflection#source_macro без замены, так как он больше не требуется в Active Record. (Pull Request)

  • Устарел serialized_attributes без замен. (Pull Request)

  • Устарел возврат nil от column_for_attribute когда не существует столбец. Он будет возвращать null object в Rails 5.0 (Pull Request)

  • Устарело использование .joins, .preload и .eager_load со связями, зависящими от состояния экземпляра (т.е. те, которые определены со скоупом, принимающим аргумент) без замены. (Commit)

8.3. Значимые изменения

  • SchemaDumper использует force: :cascade на create_table. Это позволяет перезагрузить схему с внешними ключами.

  • Добавлена опция :required к одиночным связям, определяющая наличие валидации для связи. (Pull Request)

  • ActiveRecord::Dirty теперь обнаруживает изменения в мутируемых значениях. Сериализованные атрибуты в моделях Active Record больше не сохраняются, когда не изменились. Это также работает с другими типами, такими как строковые столбцы и json столбцы в PostgreSQL. (Pull Requests 1, 2, 3)

  • Представлена задача Rake db:purge для опустошения базы данных для текущей среды. (Commit)

  • Представлен ActiveRecord::Base#validate!, вызывающий ActiveRecord::RecordInvalid, если запись невалидна. (Pull Request)

  • Представлен validate в качестве псевдонима для valid?. (Pull Request)

  • touch теперь принимает несколько атрибутов, которые будут затронуты за раз. (Pull Request)

  • Адаптер PostgreSQL теперь поддерживает тип данных jsonb в PostgreSQL 9.4+. (Pull Request)

  • Адаптеры PostgreSQL и SQLite больше не добавляют лимит по умолчанию в 255 символов для строковых столбцов. (Pull Request)

  • Добавлена поддержка для типа столбца citext в адаптере PostgreSQL. (Pull Request)

  • Добавлена поддержка для пользовательского интервального типа в адаптере PostgreSQL. (Commit)

  • sqlite3:///some/path теперь считается абсолютным системным путем /some/path. Для относительных путей используйте sqlite3:some/path. (Раньше sqlite3:///some/path считался относительным путем some/path. Это поведение устарело в Rails 4.1). (Pull Request)

  • Добавлена поддержка для долей секунд в MySQL 5.6 и выше. (Pull Request 1, 2)

  • Добавлен ActiveRecord::Base#pretty_print для красивого отображения моделей. (Pull Request)

  • ActiveRecord::Base#reload теперь ведет себя так же, как m = Model.find(m.id), что означает, что он больше не помнит дополнительные атрибуты из собственного SELECT. (Pull Request)

  • ActiveRecord::Base#reflections теперь возвращает хэш со строковыми ключами вместо символьных ключей. (Pull Request)

  • Метод references в миграциях теперь поддерживает опцию type для указания типа внешнего ключа (например, :uuid). (Pull Request)

9. Active Model

За подробностями обратитесь к Changelog.

9.1. Удалено

  • Удален устаревший Validator#setup без замены. (Pull Request)

9.2. Устарело

  • Устарел reset_#{attribute} в пользу restore_#{attribute}. (Pull Request)

  • Устарел ActiveModel::Dirty#reset_changes в пользу clear_changes_information. (Pull Request)

9.3. Значимые изменения

  • Представлен validate в качестве псевдонима для valid?. (Pull Request)

  • Представлен метод restore_attributes в ActiveModel::Dirty для восстановления измененных (dirty) атрибутов их предыдущими значениями. (Pull Request 1, 2)

  • has_secure_password по умолчанию больше не запрещает пустые пароли (т.е. пароли, содержащие только пробелы). (Pull Request)

  • Теперь has_secure_password проверяет, что заданный пароль меньше 72 символов, если включены валидации. (Pull Request)

10. Active Support

За подробностями обратитесь к Changelog.

10.1. Удалено

  • Удалены устаревшие Numeric#ago, Numeric#until, Numeric#since, Numeric#from_now. (Commit)

  • Удалены устаревшие ограничители на основе строки для ActiveSupport::Callbacks. (Pull Request)

10.2. Устарело

  • Устарели Kernel#silence_stderr, Kernel#capture и Kernel#quietly без замены. (Pull Request)

  • Устарел Class#superclass_delegating_accessor, вместо него используйте Class#class_attribute. (Pull Request)

  • Устарел ActiveSupport::SafeBuffer#prepend! так как ActiveSupport::SafeBuffer#prepend теперь выполняет ту же самую функцию. (Pull Request)

10.3. Значимые изменения

  • Представлена новая конфигурационная опция active_support.test_order для определения порядка, в котором выполняются тестовые случаи. В настоящее время эта опция по умолчанию :sorted, но будет изменена на :random в Rails 5.0. (Commit)

  • Object#try и Object#try! теперь могут использоваться без явного получателя в блоке. (Commit, Pull Request)

  • Тестовый хелпер travel_to теперь обрезает компонент usec до 0. (Commit)

  • Представлен Object#itself как идентифицирующая функция. (Commit 1, 2)

  • Теперь Object#with_options может использоваться без явного получателя в блоке. (Pull Request)

  • Представлен String#truncate_words для обрезания строки по количеству слов. (Pull Request)

  • Добавлены Hash#transform_values и Hash#transform_values! для упрощения обычной практики, когда значения хэша должны измениться, но ключи остаются прежними. (Pull Request)

  • Теперь словообразующий хелпер humanize отбрасывает любые начальные знаки подчеркивания. (Commit)

  • Представлен Concern#class_methods как альтернатива module ClassMethods, а также Kernel#concern для избегания шаблонного module Foo; extend ActiveSupport::Concern; end. (Commit)

  • Новое руководство про автозагрузку и перезагрузку констант.

11. Благодарности

Взгляните на полный список контрибьюторов Rails, на людей, которые потратили много часов, сделав Rails стабильнее и надёжнее. Спасибо им всем.