Rails 3.0 это волшебство! Он приготовит вам ужин и постирает белье. Вы не сможете понять как вы жили без него. Это Лучшая Версия Rails, Какой Еще Не Было!
Но если серьезно, это действительно замечательная вещь. В него вложены все замечательные идеи, внесенные присоединившейся командой Merb, сделан фокус на минимизацию и скорость фреймворка и удобный API. Если вы переходите на Rails 3.0 с Merb 1.x, то вам многое будет знакомым. Если переходите с Rails 2.x, то вы его тоже полюбите.
Даже если вам не интересны подробности об оптимизации "внутренностей", в Rails 3.0 есть что показать. У нас много новых возможностей и улучшений API. Сейчас очень подходящий момент стать разработчиком на Rails. Некоторые из ключевых возможностей:
Помимо всего этого, мы попытались как можно лучше указать об устаревании прежнего API с помощью хороших предупреждений. Это означает, что можно перенести ваше существующее приложение на Rails 3 без необходимости немедленного переписывания всего вашего старого кода в соответствии с последними best practices.
Эти заметки о релизе покрывают только основные изменения, но не включают все мелкие исправления программных ошибок и изменения. Rails 3.0 содержит почти 4,000 коммитов от более чем 250 авторов! Чтобы увидеть все, обратитесь к списку коммитов в главном репозитории Rails на GitHub.
Чтобы установить Rails 3:
# Используйте sudo, если этого требует установка
$ gem install rails
Прежде чем апгрейднуть существующее приложение, было бы хорошо иметь перед этим покрытие тестами. Также, до попытки обновиться до Rails 3, необходимо сначала произвести апгрейд до Rails 2.3.5 и убедиться, что приложение все еще выполняется так, как нужно. Затем обратите внимание на следующие изменения:
Rails 3.0 требует Ruby 1.8.7 или выше. Поддержка всех прежних версий Ruby была официально прекращена, и следует произвести апгрейд как можно раньше. Rails 3.0 также совместим с Ruby 1.9.2.
Отметьте, что в Ruby 1.8.7 p248 и p249 имеются программные ошибки маршаллинга, ломающие Rails 3.0. Хотя в Ruby Enterprise Edition это было исправлено, начиная с релиза 1.8.7-2010.02. В ветке 1.9, Ruby 1.9.1 не пригоден к использованию, поскольку он иногда вылетает в Rails 3.0, поэтому, если хотите использовать Rails 3.0 с 1.9.x перепрыгивайте на 1.9.2 для гладкой работы.
Как часть внутренней работы по поддержке запуска нескольких приложений на Rails в одном процессе, Rails 3 представляет концепцию объекта Application. Этот объект содержит все настройки, специфичные для приложения, и очень похож по сути на config/environment.rb
из прежних версий Rails.
Теперь каждое приложение Rails должно иметь соответствующий объект application. Этот объект определяется в config/application.rb
. При апгрейде существующего приложения до Rails 3, необходимо добавить этот файл и переместить подходящие конфигурации из config/environment.rb
в config/application.rb
.
Новый script/rails
заменяет все ранее использовавшиеся скрипты из директории script
. Впрочем, сейчас не нужно запускать даже script/rails
, команда rails
обнаруживает его при вызове из корня приложения Rails и запускает этот скрипт. Пример изменившегося использования:
$ rails console # вместо script/console
$ rails g scaffold post title:string # вместо script/generate scaffold post title:string
Запустите rails --help
, чтобы увидеть список всех опций.
Метода config.gem
больше нет, он был заменен использованием bundler
и Gemfile
, смотрите Внешние Гемы ниже.
Для упрощения и автоматизации процесса апгрейда был создан плагин Rails Upgrade.
Просто установите плагин, затем запустите rake rails:upgrade:check
для проверки, какие части вашего приложения следует обновить (с ссылками на информацию, как это сделать). Он также предлагает задачу по генерации Gemfile
, основанного на текущих вызовах config.gem
, и задачу по генерации нового маршрутного файла из старого. Чтобы получить плагин, просто запустите:
$ ruby script/plugin install git://github.com/rails/rails_upgrade.git
Пример того, как это все работает, можно увидеть в Rails Upgrade is now an Official Plugin
Помимо Rails Upgrade tool, если нужна помощь, есть люди в IRC и rubyonrails-talk, которые, возможно, сталкивались с подобными проблемами. Напишите в свой блог о своем опыте апгрейда, чтобы другие смогли воспользоваться вашими знаниями!
# Уже должен быть установлен руби-гем 'rails'
$ rails new myapp
$ cd myapp
Сейчас Rails использует Gemfile
в корне приложения, чтобы определить гемы, требуемые для запуска вашего приложения. Этот Gemfile
обрабатывается Bundler, который затем устанавливает все зависимости. Он может даже установить все зависимости локально в ваше приложение, и оно не будет зависеть от системных гемов.
Подробнее: - домашняя страница Bundler
Bundler
и Gemfile
замораживает ваше приложение Rails с помощью отдельной команды bundle
, поэтому rake freeze
более не актуальна и была отброшена.
Если хотите установить напрямую из репозитория Git, передайте флажок --edge
:
$ rails new myapp --edge
Если имеется локальная копия репозитория Rails, и необходимо сгенерировать приложение используя ее, передайте флажок --dev
:
$ ruby /path/to/rails/bin/rails new myapp --dev
Имеется шесть больших изменений в архитектуре Rails.
Railties был обновлен, чтобы предоставить совместимое с плагинами API для всего фреймворка Rails, а также полностью переписаны генераторы и зависимости Rails, в результате разработчики смогут в значительной степени внедрять свой код в генераторы и фреймворк приложения совместимым и определенным образом.
В связи с объединением Merb и Rails, одним из заданий было устранение тесно связанных вместе компонентов ядра Rails. Это было достигнуто, и теперь все компоненты ядра Rails используют то же API, что вы можете использовать для своих плагинов. Это означает, что каждый сделанный вами плагин или замена любого компонента ядра (например, DataMapper или Sequel) имеют доступ ко всей функциональности, к которой имеют доступ компоненты ядра Rails, и могут расширять и улучшать ее как угодно.
Подробнее: - The Great Decoupling
Частью разделения компонентов ядра было выделение всех связей из Action Pack в Active Record. Теперь это выполнено. Всем новым плагинам ORM теперь всего лишь нужно внедрить интерфейсы Active Model, чтобы работать с Action Pack.
Подробнее: - Make Any Ruby Object Feel Like ActiveRecord
Другой крупной частью разделения компонентов ядра было создание основного суперкласса, отделенного от терминов HTTP, для управления рендерингом вью и т.д. Создание AbstractController
позволило существенно упростить ActionController
и ActionMailer
, убрав общий код из этих библиотек, и поместив его в Abstract Controller.
Подробнее: - Rails Edge Architecture
Arel (или Active Relation) был принят в качестве основы Active Record, и теперь требуется в Rails. Arel предоставляет абстракцию SQL, упрощающую Active Record и предоставляющую основы для функциональности relation в Active Record.
Подробнее: - Why I wrote Arel.
В Action Mailer с самого начала были monkey патчи, пре-парсеры и даже агенты для отправки и получения, все вдобавок к встроенному в исходник TMail. Версия 3 изменила все это, так что вся функциональность, связанная с сообщениями email была выделена в гем Mail. Это, опять же, уменьшило повторение кода и помогло определить границы между Action Mailer и парсером email.
Подробнее: - New Action Mailer API in Rails 3
В Rails 3 было проделано много работы над поддержкой I18n, включая гем I18n, поддерживающий разные улучшения производительности.
ActiveModel::Translation
и ActiveModel::Validations
. Для переводов также имеется errors.messages
fallback.
Подробнее: - Rails 3 I18n changes
В связи с разделением главных фреймворков Rails, в Railties проведена огромная переделка, чтобы он связывал фреймворки, engine-ы или плагины настолько просто и безболезненно, насколько это возможно:
YourAppName.boot
, что позволяет взаимодействовать с другими приложениями намного проще.
Rails.root/app
добавляется в путь загрузки, поэтому можно сделать app/observers/user_observer.rb
и Rails загрузит его безо всяких модификаций.
Rails.config
, представляющий централизованное хранилище всех типов гибких конфигурационных опций Rails.
Генератор приложения получает дополнительные флажки, позволяющие опустить установку test-unit, Active Record, Prototype и Git. Также добавлен новый флажок --dev
, настраивающий приложение с Gemfile
, указывающим на вашу версию Rails (определенную путем к исходникам rails
). Подробнее смотрите rails --help
.
Генераторы Railties требуют большого внимания, основываясь на том, что:
rails generate foo
будет искать generators/foo_generator
.
Rails.root/lib/templates
.
Rails::Generators::TestCase
, поэтому вы можете создать собственные генераторы и протестировать их.
Также несколько переделаны вью, генерируемые с помощью генераторов Railties:
div
вместо тегов p
.
_form
, вместо повторения кода во вью edit и new.
f.submit
, возвращающий "Create ModelName" или "Update ModelName", в зависимости от состояния переданного объекта.
Наконец, ряд улучшений был добавлен в задачи rake:
rake db:forward
, позволяющий откатить ваши миграции с возвратом отдельно или в группах.
rake routes CONTROLLER=x
, позволяющий просмотреть маршруты только к одному контроллеру.
Теперь Railties объявил устаревшим:
RAILS_ROOT
в пользу Rails.root
,
RAILS_ENV
в пользу Rails.env
, и
RAILS_DEFAULT_LOGGER
в пользу Rails.logger
.
PLUGIN/rails/tasks
и PLUGIN/tasks
больше не загружаются, все задачи теперь должны быть в PLUGIN/lib/tasks
.
Подробнее:
В Action Pack произошло множество внутренних и внешних изменений.
В Abstract Controller были извлечены части общего назначения из Action Controller в виде модуля, годного в использовании любой библиотекой, используемой для рендеринга шаблонов или партиалов, хелперов, переводов, логирования и любой части цикла отклика на запрос. Теперь эта абстракция позволяет ActionMailer::Base
быть унаследованным от AbstractController
и всего лишь оборачивать Rails DSL в гем Mail.
Это также предоставило возможность вычистить Action Controller, упростив его код.
Однако отметьте, что Abstract Controller не имеет публичного API, и его не стоит запускать в повседневном использовании Rails.
Подробнее: - Rails Edge Architecture
application_controller.rb
теперь по умолчанию есть protect_from_forgery
.
cookie_verifier_secret
устарел, вместо этого теперь назначается Rails.application.config.cookie_secret
, и был перемещен в отдельный файл: config/initializers/cookie_verification_secret.rb
.
session_store
настраивалось в ActionController::Base.session
, а теперь перемещено в Rails.application.config.session_store
. Значения по умолчанию устанавливаются в config/initializers/session_store.rb
.
cookies.secure
позволяет устанавливать зашифрованные значения куки с помощью cookie.secure[:key] => value
.
cookies.permanent
позволяет устанавливать постоянные значения хэш куки cookie.permanent[:key] => value
, вызывая исключение на шифрованных значениях, если не проходит верификация.
:notice => 'This is a flash message'
или :alert => 'Something went wrong'
в вызове format
внутри блока respond_to
. Хэш flash[]
все еще работает по-прежнему.
respond_with
, упрощающий старые блоки format
.
ActionController::Responder
дает гибкость в том, как будут получены сгенерированные вами отклики.
Устарело:
filter_parameter_logging
устарел в пользу config.filter_parameters << :password
.
Подробнее: * Render Options in Rails 3 * Three reasons to love ActionController::Responder
Action Dispatch это новшество в Rails 3.0, он представляет новую, более чистую реализацию роутинга.
rack_mount
с лежащим в основе Rails DSL, это отдельная самодостаточная часть программы.
# Вместо:
ActionController::Routing::Routes.draw do |map|
map.resources :posts
end
# Будет:
AppName::Application.routes do
resources :posts
end
match
, также можно к соответствующему маршруту передать любое приложение Rack.
constraints
, позволяющий защитить маршруты определенными ограничениями.
scope
, позволяющий вложить маршруты в пространство имен для разных языков или различных экшнов, например:
scope 'es' do
resources :projects, :path_names => { :edit => 'cambiar' }, :path => 'proyecto'
end
# Даст вам экшн edit по адресу /es/proyecto/1/cambiar
root
как ярлык к match '/', :to => path
.
match "/:controller(/:action(/:id))(.:format)"
, каждый сегмент в скобках является опциональным.
controller :home { match '/:action' }
.
Старый стиль команд map
все еще работает, как и прежде, для обратной совместимости, однако будет убран в релизе 3.1.
Устарело
/:controller/:action/:id
) теперь закомментирована.
Подробнее:
Произошло масштабное переписывание хелперов Action View, реализованы хуки Unobtrusive JavaScript (UJS) и убраны старые команды встроенного AJAX. Это позволило Rails использовать любой совместимый драйвер UJS для внедрения хуков UJS в хелперах.
Это означает, что все прежние хелперы remote_<method>
были убраны из ядра Rails и перемещены в Prototype Legacy Helper. Для получения хуков UJS в HTML, теперь нужно передать :remote => true
. Для примера:
form_for @post, :remote => true
Создаст:
<form action="http://host.com" id="create-post" method="post" data-remote="true">
Хелперы наподобие form_for
или div_for
, вставляющие содержимое из блока, теперь используют <%=
:
<%= form_for @post do |f| %>
...
<% end %>
От ваших собственных подобных хелперов ожидается, что они возвращают строку, а не добавляют к результирующему буферу вручную.
Хелперы с другим поведением, наподобие cache
или content_for
, не затронуты этим изменением, им нужен <%
как и прежде.
h(string)
для экранирования HTML, это осуществляется по умолчанию во всех шаблонах вью. Если хотите неэкранированную строку, вызывайте raw(string)
.
f.label :name
возьмет перевод :name
.
grouped_collection_select
.
content_for?
, позволяющий проверить существование содержимого во вью до рендеринга.
:value => nil
установит атрибут поля value
как nil вместо значения по умолчанию
:id => nil
приведет к тому, что эти поля будут отрендерены без атрибута id
:alt => nil
в image_tag
приведет к тому, что тег img
отрендерится без атрибута alt
Active Model это новшество в Rails 3.0. Он представляет уровень абстракции для любой библиотеки ORM для использования во взаимодействии с Rails с применением интерфейса Active Model.
Частью разделения компонентов ядра было выделение всех связей из Action Pack в Active Record. Теперь это выполнено. Всем новым плагинам ORM теперь всего лишь нужно внедрить интерфейсы Active Model, чтобы работать с Action Pack.
Подробнее: - Make Any Ruby Object Feel Like ActiveRecord
Валидации были перемещены из Active Record в Active Model, предоставляя интерфейс для валидаций, работающий во всех библиотеках ORM в Rails 3.
validates :attribute, options_hash
позволяющий передать опции для всех валидационных методов класса, в метод валидации можно передать более одной опции.
validates
имеются следующие опции:
:acceptance => Boolean
.
:confirmation => Boolean
.
:exclusion => { :in => Enumerable }
.
:inclusion => { :in => Enumerable }
.
:format => { :with => Regexp, :on => :create }
.
:length => { :maximum => Fixnum }
.
:numericality => Boolean
.
:presence => Boolean
.
:uniqueness => Boolean
.
Все валидационные методы стиля Rails 2.3 все еще поддерживаются в Rails 3.0, новый метод валидации разработан как дополнительная помощь при валидации модели, а не как замена существующего API.
Также можно передать объект валидатора, который можно повторно использовать в разных моделях, использующих Active Model:
class TitleValidator < ActiveModel::EachValidator
Titles = ['Mr.', 'Mrs.', 'Dr.']
def validate_each(record, attribute, value)
unless Titles.include?(value)
record.errors[attribute] << 'must be a valid title'
end
end
end
class Person
include ActiveModel::Validations
attr_accessor :title
validates :title, :presence => true, :title => true
end
# Или для Active Record
class Person < ActiveRecord::Base
validates :title, :presence => true, :title => true
end
Также есть поддержка самоанализа:
User.validators
User.validators_on(:login)
Подробнее:
Active Record было уделено много внимания в Rails 3.0, включая абстрагирование в Active Model, полное обновление интерфейса запросов с применением Arel, обновления валидаций и многие улучшения и исправления. Rails 2.x API будет полностью поддерживаемым с целью совместимости, до версии 3.1.
Теперь Active Record, благодаря использованию Arel, возвращает relations на свои основные методы. Существующее API Rails 2.3.x все еще поддерживается и не будет объявлено устаревшим до Rails 3.1, и не будет убрано до Rails 3.2, однако новое API представляет следующие новые методы, все возвращающие relations, позволяющие сцеплять их вместе:
where
- Представляет условия для relation, которое будет возвращено.
select
- Выбирает, какие атрибуты моделей будут возращены из БД.
group
- Группирует relation по представленному атрибуту.
having
- Представляет выражение для ограничения сгруппированных relations (ограничение GROUP BY).
joins
- Соединяет relation с другой таблицей.
clause
- Представляет выражение, ограничивающее соединенные relations (ограничение JOIN).
includes
- Включает предварительную загрузку других relations.
order
- Сортирует relation, основываясь на представленном выражении.
limit
- Ограничивает relation представленным количеством записей.
lock
- Блокирует записи, возвращенные из таблицы.
readonly
- Возвращает копию данных только для чтения.
from
- Предоставляет способ для выбора relation из более чем одной таблицы.
scope
- (ранее named_scope
) возвращает relations и может быть сцеплен с другим методом для relation.
with_scope
- и with_exclusive_scope
теперь также возвращают relations и могут быть сцеплены.
default_scope
- также работает с relations.
Подробнее:
:destroyed?
к объектам Active Record.
:inverse_of
к связям Active Record, позволяющая получить экземпляр уже загруженной связи без запроса к базе данных.
Кроме того, в ветке Active Record сделано много исправлений:
TIME ZONE
, теперь не будут вставляться неправильные значения.
table_name
теперь кэшируется.
А также следующее объявлено устаревшим:
named_scope
в классе Active Record устарел и был переименован в просто scope
.
scope
следует перейти к использованию методов relation, вместо метода поиска :conditions => {}
, например scope :since, lambda {|time| where("created_at > ?", time) }
.
save(false)
устарел в пользу save(:validate => false)
.
:en.errors.template
.
model.errors.on
устарел в пользу model.errors[]
ActiveRecord::Base.colorize_logging
и config.active_record.colorize_logging
устарели в пользу Rails::LogSubscriber.colorize_logging
и config.colorize_logging
Хотя реализация State Machine была в ветке Active Record несколько месяцев, она была убрана из релиза Rails 3.0.
Часть Active Resource также была извлечена в Active Model, позволив легко использовать объекты Active Resource с Action Pack.
first
, last
и all
для эквивалентных скоупов поиска.
find_every
не возвращает ошибку ResourceNotFound
, если ничего не возвращено.
save!
, вызывающий ResourceInvalid
если объект не valid?
.
update_attribute
и update_attributes
.
exists?
.
SchemaDefinition
в Schema
и define_schema
в schema
.
format
из Active Resources, а не content-type
на удаленных ошибках для загрузки ошибок.
instance_eval
для блока схемы.
ActiveResource::ConnectionError#to_s
, когда @response
не отвечал на #code или #message, для совместимости с Ruby 1.9.
load
работает с числовыми массивами.
Net::HTTP
open_timeout
.
Устарело:
save(false)
устарел в пользу save(:validate => false)
.
URI.parse
и .decode
устарели и больше не используются в библиотеке.
В Active Support были направлены большие усилия на то, чтобы сделать его раздробленным, это означает, что вам больше не нужно требовать всю библиотеку Active Support, чтобы пользоваться ее частью. Это позволило различным частям компонентов ядра Rails выполняться быстрее.
Вот основные изменения в Active Support:
bundle install
.
ActiveSupport::SafeBuffer
.
Array.uniq_by
и Array.uniq_by!
.
Array#rand
и бэкпортирован Array#sample
из Ruby 1.9.
TimeZone.seconds_to_utc_offset
, возвращающий неправильное значение.
ActiveSupport::Notifications
.
ActiveSupport.use_standard_json_time_format
теперь по умолчанию true.
ActiveSupport.escape_html_entities_in_json
теперь по умолчанию false.
Integer#multiple_of?
принимает ноль как аргумент, возвращает false если получатель не ноль.
string.chars
переименован в string.mb_chars
.
ActiveSupport::OrderedHash
теперь может быть десериализован с помощью YAML.
Object#presence
, возвращающий объект, если он #present?
, в ином случае возвращающий nil
.
String#exclude?
, возвращающее противоположность #include?
.
to_i
к DateTime
в ActiveSupport
, таким образом to_yaml
правильно работает в моделях с атрибутами DateTime
.
Enumerable#exclude?
в пару к Enumerable#include?
, чтобы избежать условия !x.include?
.
ActiveSupport::HashWithIndifferentAccess
.
Enumerable#sum
теперь работает для всех перечисляемых типов, даже если они не отвечают на :size
.
inspect
на нулевой продолжительности возвращает '0 seconds' вместо пустой строки.
element
и collection
в ModelName
.
String#to_time
и String#to_datetime
обрабатывают дробные секунды.
:before
и :after
, используемых в предварительных и последующих колбэках.
ActiveSupport::OrderedHash#to_a
возвращает упорядоченный набор массивов. Соответствует Hash#to_a
из Ruby 1.9.
MissingSourceFile
существует как константа, но сейчас всего лишь равна LoadError
.
Class#class_attribute
для возможности объявить атрибуты на уровне класса, значения которых наследуются и перезаписываются подклассами.
DeprecatedCallbacks
в ActiveRecord::Associations
.
Object#metaclass
теперь Kernel#singleton_class
, для соответствия Ruby.
Следующие методы были убраны, поскольку они теперь доступны в Ruby 1.8.7 и 1.9.
Integer#even?
и Integer#odd?
String#each_char
String#start_with?
и String#end_with?
(псевдонимы в третьем лице все еще остались)
String#bytesize
Object#tap
Symbol#to_proc
Object#instance_variable_defined?
Enumerable#none?
Патч безопасности для REXML остался в Active Support, поскольку ранним версиям Ruby 1.8.7 он все еще нужен. Active Support знает, нужно его применять или нет.
Следующие методы были убраны, поскольку они больше не используются во фреймворке:
Kernel#daemonize
Object#remove_subclasses_of
Object#extend_with_included_modules_from
, Object#extended_by
Class#remove_class
Regexp#number_of_captures
, Regexp.unoptionalize
, Regexp.optionalize
, Regexp#number_of_captures
Action Mailer получил новый API в связи с заменой TMail на новый Mail в качестве библиотеки для электронных писем. В самом Action Mailer была переписана практически каждая строчка кода. В результате теперь Action Mailer просто наследуется от Abstract Controller и оборачивает гем Mail в Rails DSL. Это значительно уменьшило количество кода и дублирование других библиотек в Action Mailer.
app/mailers
.
attachments
, headers
and mail
.
attachments.inline
.
Mail::Message
, которые затем могут быть отосланы с помощью метода deliver
на них.
mail
работает подобно respond_to
из Action Controller, и можно явно или неявно рендерить шаблоны. Action Mailer превратит email в multipart email по необходимости.
format.mime_type
в блоке mail можно передать proc и явно отрендерить определенные типы текста, или добавить макет или различные шаблоны. Вызов render
внутри proc происходит из Abstract Controller и поддерживает те же опции.
Устарело:
:charset
, :content_type
, :mime_version
, :implicit_parts_order
устарели в пользу стиля объявления ActionMailer.default :key => value
.
create_method_name
и deliver_method_name
устарели, просто вызывайте method_name
, который возвратит объект Mail::Message
.
ActionMailer.deliver(message)
устарел, просто вызывайте message.deliver
.
template_root
устарел, передавайте опции в вызов render в proc из метода format.mime_type
внутри блока генерации письма mail
body
для определения переменных экземпляра устарел (body {:ivar => value}
), всего лишь определите переменные экземпляра непосредственно в методе, и они будут доступны во вью.
app/models
устарело, вместо этого используйте app/mailers
.
Подробнее: