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.
Подробнее: