Статьи

Подготовьте ваше приложение для Rails 4

Скоро будет выпущена новая версия Rails, которая будет содержать множество изменений, устаревших версий и новых функций.

Давайте посмотрим, что вам нужно сделать, чтобы подготовить ваше приложение к Rails 4.

Путь к обновлению

Самый простой способ быть готовым к Rails 4 — это приложение на Rails 3.2.
Если вы не в 3.2, обновление должно быть сделано с помощью минорных версий. То есть от 3,0 до 3,1, а затем от 3,1 до 3,2.

Устаревшие

Некоторые вещи будут полностью удалены в Rails 4. Мы должны знать о них и быть готовыми к обновлению.

Только Ruby 1.9.3+

Rails 4 будет ориентирован только на Ruby 1.9.3 и будущие версии. Поэтому убедитесь, что ваше приложение работает на нем.

Если вы используете Ruby 1.9.x, обновление должно быть довольно простым.

Если вы все еще используете Ruby 1.8.7, все может быть немного больше работы.

В настоящее время большинство драгоценных камней должно работать на 1.9 или иметь замену.
Такие инструменты, как rvm или rbenv, очень помогают, позволяя запускать несколько версий Ruby.

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

Это должно выглядеть примерно так:

gem 'ruby18-only-gem', :platforms => :ruby_18 gem 'ruby19-only-gem', :platforms => :ruby_19 #More on this can be seen in the Bundler manpages: #http://gembundler.com/man/gemfile.5.html#PLATFORMS-platforms- 

Отличным ресурсом для изменений 1.8 против 1.9 является прохождение Ruby 1.9 от Peter Cooper. Настоятельно рекомендуется!

Нет больше поставщиков / плагинов

Rails 4 будет удалять класс Rails :: Plugins. Следовательно, любой код в каталоге vendor / plugins загружаться не будет.

Большинство приложений уже полагались на драгоценные камни, а не на фирменные плагины. Однако, если у вас все еще есть код вендора / плагинов, у вас есть 2 варианта:

  • Переместить его в драгоценный камень. Большинство плагинов уже должны иметь версию Gem. Если нет, вы можете ссылаться на него из своего Gemfile через опции :git или :path .
  • Переместите его в lib/your_plugin и lib/your_plugin его от инициализатора в config/initializers .

Вот коммит, где это устарело.

Маршрут соответствия

На маршрутах метод match больше не будет действовать как универсальная опция. Теперь вы должны указать, на какой HTTP-глагол отвечать, с помощью опции :via

 #Rails 3.2 match "/users/:id" => "users#show" 
 #Rails 4.0 match "/users/:id" => "users#show", via: :get #or specify multiple verbs match "/users" => "users#index", via: [:get, :post] 

Другой вариант для лучшей совместимости с Rails 3.2 — просто указать свои действия с явным get , post или любым другим HTTP-глаголом. С этой опцией вы все равно получите свой код, работающий сегодня, и в будущем подтвердите его для обновления.

 #Rails 3.2 and 4.0 compatible get "/users/:id" => "users#show" # multiple verbs get "/users" => "users#index" post "/users" => "users#index" 

Области ActiveRecord Нужен объект, который можно вызвать

В Rails 4 все области ActiveRecord должны быть определены с вызываемым объектом (например, Proc или lambda ):

 #Rails 3.2 scope :recent, where(created_at: Time.now - 2.weeks) 
 #Rails 4 scope :recent, -> { where("created_at > ?", Time.now - 2.weeks).order("created_at desc") } scope :active, -> { where(status: 'active') } 

Это помогает избежать незначительных ошибок с объектами Date или Time, которые оцениваются один раз, а не оцениваются динамически.

Удаленный код

Много кода было также удалено из базы кода Rails 4. Не волнуйтесь, однако, большинство все еще живы как отдельные драгоценные камни. Это помогает модернизаторам с плавными переходами.

Удаленный код:

Особое примечание для последнего стоит упомянуть:

Activerecord-deprecated-finders будет зависимостью по умолчанию от Rails 4.0 для обеспечения устаревшей функциональности. Но он будет удален на 4.1. Таким образом, вы должны внимательно следить за всеми предупреждениями и начать их исправлять!

Руководства по Rails дают полезное объяснение по изменению наиболее распространенных случаев на динамических искателях:

Все динамические методы, кроме поиска по … и поиска по …! устарели. Вот как вы можете переписать код:

  • find_all_by_... можно переписать с помощью where(...).
  • find_last_by_... можно переписать, используя where(...).last .
  • scoped_by_... можно переписать с помощью where(...) .
  • find_or_initialize_by_... можно переписать с помощью where(...).first_or_initialize .
  • find_or_create_by_... может быть переписан с использованием find_or_create_by(...) или where(...).first_or_create .
  • find_or_create_by_...! может быть переписан с помощью find_or_create_by!(...) или where(...).first_or_create! ,

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

Новые особенности

Теперь пришло время для забавной части!

Многое было добавлено в Rails 4. Хорошая новость заключается в том, что большинство из них также доступны сегодня через gems для приложений rails 3.2. Мы можем получить предварительный просмотр и в то же время подготовить наш код для обновления!

Давайте погрузимся в это.

Сильные параметры ( драгоценный камень )

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

Rails 3.2 использует attr_accessible и attr_protected на моделях.

Rails 4 принимает совершенно иную точку зрения, заставляя контроллер отвечать за то, какие атрибуты назначены модели.

 #Rails 3.2 class User < ActiveRecord::Base attr_protected :name, :email end class UsersController < ApplicationController def create @user = User.new params[:user] if @user.save redirect_to @user else render :new end end end 
 #Rails 4.0 class User < ActiveRecord::Base include ActiveModel::ForbiddenAttributesProtection end class UsersController < ApplicationController def create @user = User.new params.require(:user).permit(:name, :email) if @user.save redirect_to @user else render :new end end end 

Это также может быть упрощено до чего-то вроде

 #Rails 4 class UsersController < ApplicationController def create @user = User.new user_params # ... end private def user_params params.require(:user).permit(:name, :email) end end 

Преимущество этого подхода состоит в том, что он позволяет нам фильтровать другие параметры в действиях, обращенных к пользователю, чем в области администратора.
Кроме того, разные действия могут разрешать разные наборы разрешенных атрибутов. Наличие контроллера, отвечающего за то, что получает модель, имеет смысл.

Еще одна вещь, которую следует иметь в виду при использовании этого гема, вам нужно добавить эту строку в config/application.rb :

 config.active_record.whitelist_attributes = false 

Драгоценный камень также дает очень четкое ЧТЕНИЕ, достойное прочтения. К счастью, есть Railscast для более любопытных.

Дайджесты кеша и кеширование русской куклы ( самоцвет )

Поскольку действие и кэширование страниц удалены из Rails 4, появляется новый способ хранения кэшей. Это через срок действия ключа .
Основная идея — добавить атрибут updated_at в ключ кеша. Когда запись изменяется, меняется ее ключ кеша, и она получает новую версию.

Этот подход генерирует много мусора в кеше, поэтому он лучше работает с хранилищами, подобными memcache, где он сначала удаляет самые старые ключи, когда ему не хватает места.

Кроме того, для представлений он генерирует контрольную сумму MD5 файла в ключе кэша. Если что-то в файле изменяется, ключ кеша меняется, и он снова получает все.

 #Rails 3.2 <% cache ['v1', @user] do %> ... <% end %> 

 #Rails 4.0 <% cache @user do %> ... <% end %> #this will generate a key like # views/users/1-201222172130/1a79a4d60de6718e8e5b326e338ae533 

Это особенно хорошо работает с вложенными представлениями, так как знает о вложенных шаблонах.

Вот отличный Railscast на эту тему.

Декларативные ETag ( драгоценный камень )

В Rails 4 вы сможете устанавливать суффиксы ETag для всего контроллера. Это очень помогает, когда действие зависит от нескольких записей или зарегистрированного пользователя.

Это действительно легко сделать, чтобы улучшить HTTP-кэширование.

Простой пример:

 class TodosController < ApplicationController etag { current_user.try :id } etag { @todo_list } before_fiter :find_todo_list def show @todo = @todo_list.todos.find(params[:id]) fresh_when(@todo) end private def find_todo_list @todo_list = TodoList.find(params[:todo_list_id]) end end 

В этом примере первый блок etag проверяет текущего пользователя, гарантируя, что нет двух зарегистрированных пользователей, имеющих одинаковый ETag кеша. Второй использует объект TodoList как часть ETag, поэтому изменение списка задач — это изменение ETag.

Turbolinks ( драгоценный камень )

Turbolinks вроде как брат pjax . Он использует pushState когда он доступен, вызывая запрос XHR и заменяя содержимое <body> . Это имеет 3 основных преимущества:

  • Не загружает CSS / JS дважды.
  • Не перекомпилируется.
  • Не переоценивает.

В Rails 4 по умолчанию включены Turbolinks. Но это может привести к некоторым проблемам, если вы используете слишком много кода в событии domready . TurboLinks объявляет 4 новых события:

  • page:fetch начинающая выборку целевой страницы (вызывается только при новой загрузке, а не из кэша).
  • page:load извлеченной страницы извлекается только что с сервера.
  • page:restore извлекаемая страница извлекается из 10-слотового клиентского кэша.
  • page:change была изменена на вновь загруженную версию.

Вы должны будете проверить свой JavaScript и исправить его там, где это необходимо.

Чтобы использовать его сейчас, просто установите gem и добавьте //= require turbolinks в ваш основной файл javascript (обычно application.js )

Вот отличный Railscast об этой функции.

Обеспокоенность

Rails 4 вводит новый шаблон по умолчанию, чтобы избежать повторения кода.

Проблемы маршрутизации ( драгоценный камень )

Когда существует несколько ресурсов или методов, совместно используемых между маршрутами, также существует большое количество повторений кода. Эта функция дает нам новое определение concern на маршрутах, которое помогает улучшить читаемость и делает код более СУХИМЫМ.

 #Rails 3.2 resources :messages do resources :comments post :trash, :restore, on: :member end resources :documents do resources :comments post :trash, :restore, on: :member end 

 #Rails 4 concern :commentable do resources :comments end concern :trashable do post :trash, :restore, on: :member end resources :messages, :documents, concerns: [:commentable, :trashable] 

Это можно использовать в Rails 3.2, просто добавив гем routing_concerns в ваше приложение.

Модели и проблемы контроллеров

По умолчанию Rails 4 добавляет две новые папки в структуру каталогов по умолчанию и путь загрузки: app/controllers/concerns и app/models/concerns .
Идея этого объяснена DHH в этом посте .

Обычно этот код будет жить в lib . Эти новые каталоги делают вещи чище и легче найти.

Чтобы сделать это сейчас, вам просто нужно добавить эту строку в ваш config/application.rb

 config.autoload_paths += Dir["#{config.root}/app/controllers/concerns", "#{config.root}/app/models/concerns"] 

И переместите свою модель и модули контроллера в эти каталоги.

Далли как адаптер Memcache ( драгоценный камень )

Далли заменит memcache-client как драгоценный камень по умолчанию для кэширования.
Это приносит несколько улучшений бесплатно:

  • Это примерно на 20% быстрее, чем гем memcache-client.
  • Обрабатывает аварийное переключение с восстановлением и настраиваемыми таймаутами.
  • Это потокобезопасно.
  • Использует более новый двоичный протокол memcached.

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

В вашем Gemfile:

 gem 'dalli' 

В config/environments/production.rb (или в любой другой среде, которую вы используете memcached):

 config.cache_store = :dalli_store # just be sure to change this back to :mem_cache_store when upgrading to Rails 4 

Стоит отметить: Dalli зависит от memcached 1.4+, поэтому, если вы используете более старую версию, обязательно обновите ее!

Потокобезопасный по умолчанию

В новых приложениях Rails threadsafe! опция будет включена по умолчанию в производственном режиме. Выключить его можно, установив config.cache_classes и config.eager_load в false .

Это не должно быть большой проблемой, если только приложение (или один из его драгоценных камней) не слишком сильно зависит от безопасности потоков.

Вот отличный пост от Аарона Паттерсона, объясняющий это изменение и его последствия:

config.threadsafe !: Что это делает?

Вы можете включить threadsafe! в ваших приложениях прямо сейчас, чтобы увидеть, как они ведут себя. При обновлении до Rails 4 вы увидите предупреждение, и вы можете удалить эту строку все время.

Резюме

Итак, мы рассмотрели большой набор изменений в предстоящем релизе Rails 4. С этими изменениями большинство приложений должно легко обновляться. В любом случае, Rails 4 все еще находится в активной разработке, поэтому в будущем могут потребоваться некоторые другие изменения. Я стремлюсь держать этот пост обновленным в этом случае.

Дальнейшее чтение: