Заметки о релизе Ruby on Rails 3.1
Ключевые новинки в Rails 3.1:
Ключевые новинки в Rails 3.1:
- Streaming
- Обратимые миграции
- Конвейер ресурсов (Assets Pipeline)
- jQuery как библиотека JavaScript по умолчанию
Эти заметки о релизе покрывают только основные изменения. Чтобы узнать о различных исправлениях программных ошибок и изменениях, обратитесь к логам изменений или к списку коммитов в главном репозитории Rails на GitHub.
Апгрейд до Rails 3.1
Прежде чем апгрейднуть существующее приложение, было бы хорошо иметь перед этим покрытие тестами. Также, до попытки обновиться до Rails 3.1, необходимо сначала произвести апгрейд до Rails 3 и убедиться, что приложение все еще выполняется так, как нужно. Затем обратите внимание на следующие изменения:
Rails 3.1 требует как минимум Ruby 1.8.7
Rails 3.1 требует Ruby 1.8.7 или выше. Поддержка всех прежних версий Ruby была официально прекращена, и следует произвести апгрейд как можно раньше. Rails 3.1 также совместим с Ruby 1.9.2.
Отметьте, что в Ruby 1.8.7 p248 и p249 имеются программные ошибки маршаллинга, ломающие Rails. Хотя в Ruby Enterprise Edition это было исправлено, начиная с релиза 1.8.7-2010.02. В ветке 1.9, Ruby 1.9.1 не пригоден к использованию, поскольку он иногда вылетает, поэтому, если хотите использовать 1.9.x перепрыгивайте на 1.9.2 для гладкой работы.
Что обновить в приложении
Следующие изменения предназначены для апгрейда приложения до Rails 3.1.3, последней версии 3.1.x Rails.
Gemfile
Сделайте изменения в вашем Gemfile.
gem "rails", "= 3.1.3"
gem "mysql2"
# Необходимо для нового asset pipeline
group :assets do
gem "sass-rails", "~> 3.1.5"
gem "coffee-rails", "~> 3.1.1"
gem "uglifier", ">= 1.0.3"
end
# jQuery это библиотека JavaScript по умолчанию в Rails 3.1
gem "jquery-rails"config/application.rb
-
Конвейер ресурсов требует следующие добавления:
config.assets.enabled = true config.assets.version = '1.0' -
Если ваше приложение использует маршрут "/assets", можно изменить префикс, используемый для ассетов, чтобы избежать конфликтов:
# Defaults to '/assets' config.assets.prefix = '/asset-files'
config/environments/development.rb
-
Уберите настройку RJS
config.action_view.debug_rjs = true. -
Добавьте следующее, если хотите включить конвейер ресурсов.
# Do not compress assets config.assets.compress = false # Expands the lines which load the assets config.assets.debug = true
config/environments/production.rb
-
Снова, большинство изменений относится к конвейеру ресурсов. Подробнее о них можно прочитать в руководстве Asset Pipeline.
# Compress JavaScripts and CSS config.assets.compress = true # Don't fallback to assets pipeline if a precompiled asset is missed config.assets.compile = false # Generate digests for assets URLs config.assets.digest = true # Defaults to Rails.root.join("public/assets") # config.assets.manifest = YOUR_PATH # Precompile additional assets (application.js, application.css, and all non-JS/CSS are already added) # config.assets.precompile `= %w( admin.js admin.css ) # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. # config.force_ssl = true
config/environments/test.rb
# Configure static asset server for tests with Cache-Control for performance
config.serve_static_assets = true
config.static_cache_control = "public, max-age=3600"config/initializers/wrap_parameters.rb
-
Добавьте этот файл со следующим содержимым, если хотите оборачивать параметры во вложенный хэш. По умолчанию это включено в новых приложениях.
# Be sure to restart your server when you modify this file. # This file contains settings for ActionController::ParamsWrapper which # is enabled by default. # Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. ActiveSupport.on_load(:action_controller) do wrap_parameters :format => [:json] end # Disable root element in JSON by default. ActiveSupport.on_load(:active_record) do self.include_root_in_json = false end
Уберите опции :cache и :concat в хелперах ассетов во вью
- Вместе с Asset Pipeline опции :cache и :concat больше не используются, удалите эти опции из своих вью.
Создание приложения Rails 3.1
# Нужен установленный руби-гем 'rails'
$ rails new myapp
$ cd myappСторонние гемы
Сейчас Rails использует Gemfile в корне приложения, чтобы определить гемы, требуемые для запуска вашего приложения. Этот Gemfile обрабатывается Bundler, который затем устанавливает все зависимости. Он может даже установить все зависимости локально в ваше приложение, и оно не будет зависеть от системных гемов.
Подробнее: - домашняя страница Bundler
Живите на грани
Bundler и Gemfile замораживает ваше приложение Rails с помощью новой отдельной команды bundle. Если хотите установить напрямую из репозитория Git, передайте флажок --edge:
$ rails new myapp --edgeЕсли имеется локальная копия репозитория Rails, и необходимо сгенерировать приложение используя ее, передайте флажок --dev:
$ ruby /path/to/rails/railties/bin/rails new myapp --devАрхитектурные изменения Rails
Конвейер ресурсов (Assets Pipeline)
Основное изменение в Rails 3.1 это Assets Pipeline. Он делает CSS и JavaScript первосортным кодом, и делает доступной надлежащую организацию, включая использование в плагинах и engine-ах.
Конвейер ресурсов работает с помощью Sprockets и раскрывается в руководстве Asset Pipeline.
HTTP Streaming
HTTP Streaming это другое новшество в Rails 3.1. Он позволяет браузеру загружать таблицы стилей и файлы JavaScript, пока сервер все еще генерирует отклик. Это требует Ruby 1.9.2, является опциональным, а также требует настройки веб-сервера, но популярная связка NGINX и Unicorn уже готова предоставлять это преимущество.
Библиотека JS по умолчанию теперь jQuery
jQuery является библиотекой JavaScript по умолчанию, которая поставляется вместе с Rails 3.1. Но если вы используете Prototype, это просто переключить.
$ rails new myapp -j prototypeIdentity Map
В Active Record имеется Identity Map в Rails 3.1. Identity map содержит ранее загруженные экземпляры записей и возвращает объект, связанный с записью, если к нему обращаются снова. Identity map создается при каждом запросе и уничтожается при его завершении.
Rails 3.1 поставляется с отключенной по умолчанию identity map.
Railties
-
jQuery является новой библиотекой JavaScript по умолчанию.
-
jQuery и Prototype более не встроенные, а предоставляются как гемы
jquery-railsиprototype-rails. -
Генератор приложения принимает опцию
-j, которая может быть произвольной строкой. Если передать "foo", вGemfileбудет добавлен гем "foo-rails", и манифест JavaScript приложения затребует "foo" и "foo_ujs". В данный момент существуют только "prototype-rails" и "jquery-rails", и эти файлы предоставляются через конвейер ресурсов. -
Генерация приложение или плагина запускает
bundle install, если не определено--skip-gemfileили--skip-bundle. -
Генераторы контроллера и ресурса теперь автоматически создадут заглушки для ассетов (это может быть отключено с помощью
--skip-assets). Эти заглушки будут использовать CoffeeScript и Sass, если эти библиотеки доступны. -
Генераторы скаффолда и приложения используют стиль хэшей из Ruby 1.9, когда запущены на Ruby 1.9. Чтобы генерировать старый стиль хэшей, должно быть передано
--old-style-hash. -
Генератор скаффолда контроллера создает блок формата для JSON вместо XML.
-
Логирование Active Record направлено в STDOUT и показывается в консоли.
-
Добавлена конфигурация
config.force_ssl, загружающая промежуточную программуRack::SSLи принуждающую все запросы быть под протоколом HTTPS. -
Добавлена команда
rails plugin new, генерирующая плагин Rails с gemspec, тестами и пустым приложением для тестирования. -
К стеку промежуточных программ по умолчанию добавлены
Rack::EtagиRack::ConditionalGet. -
К стеку промежуточных программ по умолчанию добавлена
Rack::Cache. -
Engine-ы получили большое обновление - их можно монтировать на любой путь, включать ассеты. запускать генераторы и т.д.
Action Pack
Action Controller
-
Выдается предупреждение, если токен аутентификации CSRF не может быть верифицирован.
-
Определите
force_sslв контроллере. чтобы принудить браузер передавать данные через протокол HTTPS на конкретно этот контроллер. Для ограничения отдельных экшнов могут быть использованы:onlyили:except. -
Чувствительные параметры строки запроса, определенные в
config.filter_parameters, теперь будут отфильтрованы в логе и из пути запроса. -
Параметры URL, возвращающие
nilнаto_param. теперь будут убраны из строки запроса. -
Добавлен
ActionController::ParamsWrapperдля оборачивания параметров во вложенный хэш, и он будет включен в новых приложениях по умолчанию для запроса JSON. Это может быть настроено вconfig/initializers/wrap_parameters.rb. -
Добавлен
config.action_controller.include_all_helpers. По умолчанию выполняетhelper :allвActionController::Base, что включает все хелперы по умолчанию. Установкаinclude_all_helpersвfalseприведет к включению только application_helper и хелпера. соответствующего контроллеру (подобно foo_helper для foo_controller). -
url_forи именованные хелперы URL теперь принимают как опции:subdomainи:domain. -
Добавлен
Base.http_basic_authenticate_withдля базовой аутентификации HTTP с помощью единственного вызова метода класса.class PostsController < ApplicationController USER_NAME, PASSWORD = "dhh", "secret" before_filter :authenticate, :except => [ :index ] def index render :text => "Everyone can see me!" end def edit render :text => "I'm only accessible if you know the password" end private def authenticate authenticate_or_request_with_http_basic do |user_name, password| user_name == USER_NAME && password == PASSWORD end end end..теперь может быть написано как
class PostsController < ApplicationController http_basic_authenticate_with :name => "dhh", :password => "secret", :except => :index def index render :text => "Everyone can see me!" end def edit render :text => "I'm only accessible if you know the password" end end -
Добавлена поддержка streaming, ее можно включить с помощью:
class PostsController < ActionController::Base stream endМожно ограничить некоторые экшны от этого с использованием
:onlyили:except. Подробности можно прочитать в документации поActionController::Streaming. -
Маршрутный метод redirect теперь принимает хэш опций, меняющих только рассматриваемые части URL, или объект, отвечающий на вызов, позволяя повторно использовать редиректы.
Action Dispatch
-
config.action_dispatch.x_sendfile_headerтеперь по умолчаниюnilиconfig/environments/production.rbне устанавливает какое-либо значение для этого. Это позволяет серверам устанавливать его черезX-Sendfile-Type. -
ActionDispatch::MiddlewareStackтеперь использует наследуемую структуру, и больше не является массивом. -
Добавлен
ActionDispatch::Request.ignore_accept_headerдля игнорирования заголовков accept. -
Добавлена
Rack::Cacheв стек по умолчанию. -
Ответственность за etag перенесена от
ActionDispatch::Responseв стек промежуточных программ. -
API хранения
Rack::Sessionстало более совместимым с остальным в мире Ruby. Оно обратно несовместимо, так как теперь вRack::Sessionожидается, что#get_sessionпринимает четыре аргумента, и требует#destroy_sessionвместо простого#destroy. -
Поиск шаблонов теперь ищет глубже в цепи наследования.
Action View
-
Добавлена опция
:authenticity_tokenкform_tagдля ручного управления, или для отмены, если передать:authenticity_token => false. -
Создан
ActionView::Rendererи определен API дляActionView::Context. -
Встроенные мутации
SafeBufferзапрещены в Rails 3.1. -
Добавлен HTML5 хелпер
button_tag. -
file_fieldавтоматически добавляет:multipart => trueк внешним формам. -
Добавлена удобная идиома генерировать HTML5 атрибуты data-* в хелперах тегов с хэшем опций
:data:tag("div", :data => \{:name => 'Stephen', :city_state => %w(Chicago IL)\}) # => <div data-name="Stephen" data-city-state="["Chicago","IL"]" />
Ключи преобразуются в дефисные. Значения кодируются в JSON, кроме строк и символов.
-
csrf_meta_tagпереименован вcsrf_meta_tagsи для него сделан псевдонимcsrf_meta_tagдля обратной совместимости. -
Старое API обработки шаблонов устарело, а новое API просто требует обработчик шаблонов для отклика на вызов.
-
rhtml и rxml окончательно убраны из обработчиков шаблонов.
-
Вернули
config.action_view.cache_template_loading, позволяющий решить, должны ли быть кэшированы шаблоны, или нет. -
Хелпер формы submit больше не генерирует id "object_name_id".
-
Позволяет
FormHelper#form_forопределить:methodкак опцию первого уровня вместо вкладывания в хэш:html.form_for(==@==post, remote: true, method: :delete)вместоform_for(==@==post, remote: true, html: { method: :delete }). -
Предоставлен
JavaScriptHelper#j()как псевдоним дляJavaScriptHelper#escape_javascript(). Это заменило методObject#j(), добавляемый гемом JSON в шаблоны при использовании JavaScriptHelper. -
Позволяет формат AM/PM в datetime selectors.
-
auto_linkбыл убран из Rails и выделен в гем rails_autolink
Active Record
-
Добавлен метод класса
pluralize_table_namesдля склонения по числу имен таблиц отдельных моделей. Ранее это можно было сделать только глобально для всех моделей с помощьюActiveRecord::Base.pluralize_table_names.class User < ActiveRecord::Base self.pluralize_table_names = false end -
Добавлен блок настроек для одиночных связей. Блок будет вызван после того, как экземпляр будет инициализирован.
class User < ActiveRecord::Base has_one :account end user.build_account\{ |a| a.credit_limit = 100.0 \} -
Добавлен
ActiveRecord::Base.attribute_names, возвращающий список имен атрибутов. Он возвратит пустой массив, если модель абстрактная, или таблица не существует. -
Фикстуры CSV устарели и их поддержка будет убрана в Rails 3.2.0.
-
ActiveRecord#new,ActiveRecord#createиActiveRecord#update_attributesпринимают второй хэш как опцию, позволяющую определить рассматриваемую роль при назначении атрибутов. Это основа новой возможности массового назначения Active Model:class Post < ActiveRecord::Base attr_accessible :title attr_accessible :title, :published_at, :as => :admin end Post.new(params[:post], :as => :admin) -
default_scopeтеперь может принимать блок, lambda или любой другой объект, отвечающий на call для ленивых вычислений. -
Дефолтные скоупы теперь вычисляются в самый последний момент для избегания проблем, когда могут быть созданы скоупы, которые неявно содержат дефолтный скоуп, от которого впоследствии невозможно будет избавиться с помощью Model.unscoped.
-
Адаптер PostgreSQL теперь поддерживает только PostgreSQL версии 8.2 и выше.
-
Промежуточная программа
ConnectionManagementизменилась, чтобы очищать пул соединения после того, как тело rack было уничтожено. -
В Active Record добавлен метод
update_column. Этот новый метод обновляет заданный атрибут у объекта, пропуская валидации и колбэки. Рекомендовано использоватьupdate_attributesилиupdate_attributeесли вы не уверенны, что не хотите выполнять какой-либо колбэк, включая модификацию столбцаupdated_at. Он не может быть вызван на новых записях. -
Связи с опцией
:throughтеперь могут использовать любые связи как посредника или источника, включая другие связи, имеющие опцию:through, и связиhas_and_belongs_to_many. -
Конфигурация для текущего соединения с базой данных теперь доступна с помощью
ActiveRecord::Base.connection_config. -
Лимиты и смещения убираются из запросов COUNT, кроме случая, когда они оба представлены.
People.limit(1).count # => 'SELECT COUNT(*) FROM people' People.offset(1).count # => 'SELECT COUNT(*) FROM people' People.limit(1).offset(1).count # => 'SELECT COUNT(*) FROM people LIMIT 1 OFFSET 1' -
ActiveRecord::Associations::AssociationProxyбыл разделен. Теперь имеется классAssociation(и подклассы), ответственные за работу со связями, и отдельная "тонкая" обертка по имениCollectionProxy, передающая связи коллекции. Это предотвращает загрязнение пространства имен, разделяет решаемые проблемы, и позволяет дальнейший рефакторинг. -
Одиночные связи (
has_one,belongs_to) больше не имеют прокси, и просто возвращают связанную запись илиnil. Это означает, что больше не следует использовать недокументированные методы наподобиеbob.mother.create- используйте вместо этогоbob.create_mother. -
Поддержка опции
:dependentдля связиhas_many :through. По историческим и практическим причинам,:delete_allявляется стратегией удаления по умолчанию, используемой вassociation.delete(*records), несмотря на то, что стратегией по умолчанию для обычного has_many является:nullify. Кроме того, это работает только при условии, что вторая сторона связи belongs_to. В других ситуациях следует напрямую модифицировать связь through. -
Изменилось поведение
association.destroyдляhas_and_belongs_to_manyиhas_many :through. Теперь 'destroy' или 'delete' на связи будет означать 'избавиться от связи', а не (обязательно) 'избавиться от связанных записей'. -
Раньше
has_and_belongs_to_many.destroy(*records)уничтожал сами записи. Он не удалял какие-либо записи в соединительной таблице. Теперь он удаляет записи в соединительной таблице. -
Раньше
has_many_through.destroy(*records)удалял сами записи и записи в соединительной таблице. [Отметьте: Это не всегда было так; ранние версии Rails удаляли только сами записи.] Теперь от уничтожает только записи в соединительной таблице. -
Отметьте, что это изменение в некоторой степени обратно не совместимо, но, к сожалению, нет никакого способа объявить его 'deprecate' перед изменением. Изменение было сделано для единообразия в понятиях 'destroy' или 'delete' для различных типов связи. Если хотите уничтожить сами записи, следует выполнить
records.association.each(&:destroy). -
В
change_tableдобавлена опция:bulk => true, чтобы выполнить все изменения схемы, определенные в блоке, с использование одного выражения ALTER.change_table(:users, :bulk => true) do |t| t.string :company_name t.change :birthdate, :datetime end -
Убрана поддержка доступа к атрибутами в соединительной таблице
has_and_belongs_to_many. Следует использоватьhas_many :through. -
Добавлен метод
create_association!для связейhas_oneиbelongs_to. -
Миграции теперь обратимы, что означает, что Rails теперь понимает, как обратить ваши миграции. Для использования обратимых миграций просто определите метод
change.class MyMigration < ActiveRecord::Migration def change create_table(:horses) do |t| t.column :content, :text t.column :remind_at, :datetime end end end -
Некоторые вещи не могут быть автоматически обратимы. Если вы знаете, как их обратить. следует в миграциях определить
upиdown. Если вы определите какое-либо изменение в change, которое не может быть обращено, при откате миграции будет вызвано исключениеIrreversibleMigration. -
Теперь миграции используют методы экземпляра вместо методов класса:
class FooMigration < ActiveRecord::Migration def up # Не self.up # ... end end -
Файлы миграции, сгенерированные с помощью генераторов модели и конструктивной миграции (для примера, add_name_to_users), используют метод обратимой миграции
changeвместо обычных методовupиdown. -
Убрана поддержка интерполяции строк с условиями SQL на связях. Вместо этого должен быть использован proc.
has_many :things, :conditions => 'foo = #\{bar\}' # до has_many :things, :conditions => proc \{ "foo = #\{bar\}" \} # послеВнутри proc,
selfэто объект, являющийся владельцем связи, за исключением случая, когда связь лениво загружается, в этом случаеselfэто класс, в котором определена связь.Внутри proc можно иметь "нормальные" условия, поэтому следующее будет работать:
has_many :things, :conditions => proc \{ ["foo = ?", bar] \} -
Ранее
:insert_sqlи:delete_sqlна связиhas_and_belongs_to_manyпозволяли вызвать 'record' для получения записи, которую нужно вставить или удалить. Теперь это передается как аргумент в proc. -
Добавлен
ActiveRecord::Base#has_secure_password(черезActiveModel::SecurePassword) для инкапсуляции элементарного пароля с использованием шифрования BCrypt и соли.# Schema: User(name:string, password_digest:string, password_salt:string) class User < ActiveRecord::Base has_secure_password end -
При генерации модели по умолчанию добавляется
add_indexдля столбцовbelongs_toилиreferences. -
Установление id для объекта в
belongs_toобновляет связь с объектом. -
Изменилась семантика
ActiveRecord::Base#dupиActiveRecord::Base#clone, чтобы более соответствовать семантике обычных методов Ruby dup и clone. -
Вызов
ActiveRecord::Base#cloneприведет к неполной копии записи, включая копирования состояния заморозки. Ни один колбэк не будет вызван. -
Вызов
ActiveRecord::Base#dupпродублирует запись, включая вызов пост-инициализационных хуков. Состояние заморозки не будет скопировано, и все связи будут очищены. Дублированная запись возвратитtrueдляnew_record?, будет иметьnilв поле id, и ее можно будет сохранить. -
Кэш запросов теперь работает с prepared statements. Никаких изменений в приложении не требуется.
Active Model
-
attr_accessibleпринимает опцию:asдля определении роли. -
Теперь
InclusionValidator,ExclusionValidatorиFormatValidatorпринимают опцию, которая может быть proc, lambda или что угодно, что отвечает наcall. Эта опция будет вызвана с текущей записью в качестве аргумента, и возвратит объект, отвечающий наinclude?дляInclusionValidatorиExclusionValidator, и возвратит регулярное выражение дляFormatValidator. -
Добавлен
ActiveModel::SecurePasswordдля инкапсуляции элементарного пароля с использованием шифрования BCrypt и соли. -
ActiveModel::AttributeMethodsДопускает атрибуты, определяемые по требованию. -
Добавлена поддержка для выборочного включения и отключения обсерверов.
-
Альтернативный поиск в пространстве имен
I18nболее не поддерживается.
Active Resource
-
Для всех запросов формат по умолчанию был изменен на JSON. Если хотите продолжить использование XML, следует установить
self.format = :xmlв классе. Например,class User < ActiveResource::Base self.format = :xml end
Active Support
-
ActiveSupport::Dependenciesтеперь вызываетNameError, если находит существующую константу вload_missing_constant. -
Добавлен новый метод
Kernel#quietly, приглушающийSTDOUTиSTDERR. -
Добавлен
String#inquiryкак удобный метод для преобразования String в объектStringInquirer. -
Добавлен
Object#in?для проверки, включен ли объект в другой объект. -
Теперь стратегия
LocalCacheявляется настоящим классом промежуточной программы, а не анонимным классом. -
Был представлен класс
ActiveSupport::Dependencies::ClassCacheкак содержащий ссылки на перегружаемые классы. -
Был отрефакторен
ActiveSupport::Dependencies::Reference, чтобы пользоваться преимуществами новогоClassCache. -
Бэкпортирован
Range#cover?как псевдонимRange#include?в Ruby 1.8. -
Добавлены
weeks_agoиprev_weekв Date/DateTime/Time. -
Добавлен колбэк
before_remove_constкActiveSupport::Dependencies.remove_unloadable_constants!.
Устарело:
ActiveSupport::SecureRandomустарел в пользуSecureRandomиз стандартной библиотеки Ruby.