Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rails 5.1: upcoming features

Rails 5.1: upcoming features

Presented at RailsConf, April 2017

------------------- BREAKING CHANGES -------------------------

Change Action View ERB handler from Erubis to Erubi
https://github.com/rails/rails/pull/27757

Deprecate String options :if and :unless to set/skip callbacks
https://github.com/rails/rails/commit/0952552

Deprecate :action and :controller path parameters
https://github.com/rails/rails/pull/23980

------------------- ACTIVE RECORD -------------------------

Add ActiveRecord::Base. connection_pool.stat
https://github.com/rails/rails/pull/26988

Change default primary keys to BIGINT
https://github.com/rails/rails/pull/26266

Virtual column support for MySQL and MariaDB
https://github.com/rails/rails/commit/65bf1c6

Adds support for limits in batch processing
https://github.com/rails/rails/commit/451437c

------------------- ACTIVE SUPPORT -------------------------

Update Unicode version to 9.0.0
https://github.com/rails/rails/pull/27822

DateTime#change supports :usec and :nsec options
https://github.com/rails/rails/pull/28242

Add Duration#after and #before as alias for #since and #until
https://github.com/rails/rails/pull/27721

Introduce Module#delegate_missing_to
https://github.com/rails/rails/pull/23930

------------------- ACTION VIEW -------------------------

Add option :check_parameters to current_page?
https://github.com/rails/rails/pull/27549

New syntax for Action View’s tag helpers
https://github.com/rails/rails/pull/25543

Add form_with to unify form_tag and form_for
https://github.com/rails/rails/pull/26976

------------------- RAILTIES -------------------------

Display railtie class name in "rails initializers"
https://github.com/rails/rails/pull/25257

Added a shared section to config/secrets.yml
https://github.com/rails/rails/commit/e530534

Add encrypted secrets in config/secrets.yml.enc
https://github.com/rails/rails/pull/28038

Drop jQuery as a dependency and include rails-ujs
https://github.com/rails/rails/pull/27113

Add Yarn support in new apps using --yarn option
https://github.com/rails/rails/pull/26836

Basic --webpack delegation to new webpacker gem
https://github.com/rails/rails/pull/27288

------------------- ACTION PACK -------------------------

Capybara integration with Rails (AKA System Tests)
https://github.com/rails/rails/pull/26703

Custom URL helpers and polymorphic mapping
https://github.com/rails/rails/pull/23138

------------------- ACTIVE JOB -------------------------

Add retry_on/discard_on for better exception handling
https://github.com/rails/rails/pull/25991

------------------- ACTION MAILER -------------------------

Add parameterized invocation of mailers
https://github.com/rails/rails/pull/27825

Claudio B.

April 13, 2017
Tweet

More Decks by Claudio B.

Other Decks in Programming

Transcript

  1. Rails 5.1: awesome features & breaking changes $ git log

    v4.2.0..v5.0.0 # => 18 months # => 962 authors # => 9,998 commits $ git log v5.0.0..v5.1.0.rc2 # => 9 months # => 450 authors # => 4,065 commits 5.0 5.1
  2. PR 27757 by Jeremy Evans Change Action View ERB handler

    from Erubis to Erubi Breaking change
  3. commit 0952552 by Ryuta Kamizono Deprecate String options :if and

    :unless to set/skip callbacks Breaking change
  4. Deprecate String options to set/skip callbacks class Post < ApplicationRecord

    before_save :set_no_title, unless: 'title.present?' skip_callback :save, :before, :set_no_title, if: 'persisted?' private def set_no_title self.title = 'No title' end end 5.0
  5. Deprecate String options to set/skip callbacks class Post < ApplicationRecord

    before_save :set_no_title, unless: -> { title.present? } skip_callback :save, :before, :set_no_title, if: :persisted? private def set_no_title self.title = 'No title' end end 5.1
  6. Deprecate :action and :controller path parameters # config/routes.rb get ':controller(/:action(/:id))'

    [CVE-2014-0130] Directory traversal vulnerability (4.1.1, 4.0.5) [CVE-2015-7581] Object leak vulnerability (4.2.5, 4.1.13) # config/routes.rb get ':controller(/:action(/:id))' # deprecated get 'photos(/:id)', to: :display # acceptable 5.0 5.1
  7. Virtual column support for MySQL and MariaDB class CreateUsers <

    ActiveRecord::Migration[5.1] def change create_table :users do |t| t.string :name t.virtual :upper_name, type: :string, as: "UPPER(name)" t.virtual :name_length, type: :integer, as: "LENGTH(name)", stored: true, index: true end end end 5.1
  8. Adds support for limits in batch processing Post.limit(500).find_each.map(&:title) # Scoped

    order and limit are ignored, it's forced to be batch order and batch size. # => Post Load (0.2ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."id" ASC LIMIT ? [["LIMIT", 1000]] Post.limit(500).find_each.map(&:title) # => Post Load (0.1ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."id" ASC LIMIT ? [["LIMIT", 500]] 5.0 5.1
  9. Update Unicode version to 9.0.0 ActiveSupport::Multibyte::Unicode::UNICODE_VERSION # => "8.0.0" "

    " ".mb_chars.grapheme_length # => 4 " " ".mb_chars.reverse # => " " ActiveSupport::Multibyte::Unicode::UNICODE_VERSION # => "9.0.0" " " ".mb_chars.grapheme_length # => 1 " " ".mb_chars.reverse # => " " " 5.0 5.1
  10. Add Duration#after and #before as alias for #since and #until

    PR 27721 by Nick Johnstone Active Support
  11. Add Duration#after and #before as aliases… 2.weeks.since(christmas_day) # => Mon,

    08 Jan 2018 5.days.until(christmas_day) # => Wed, 20 Dec 2017 2.weeks.after(christmas_day) # => Mon, 08 Jan 2018 5.days.before(christmas_day) # => Wed, 20 Dec 2017 5.0 5.1
  12. Introduce Module#delegate_missing_to class OrderCompletion delegate :destroy, :update, …more methods…, to:

    :@order def initialize(order) @order = order end def create OrderCompletionNotification.deliver(@order) if @order.save end end 5.0
  13. Introduce Module#delegate_missing_to class OrderCompletion delegate_missing_to :@order def initialize(order) @order =

    order end def create OrderCompletionNotification.deliver(@order) if @order.save end end 5.1
  14. New syntax for Action View’s tag helpers tag(:br, nil, true)

    <%= content_tag :div, class: "strong" do -%> Hello world! <% end -%> tag.br <%= tag.div class: "strong" do %> Hello world! <% end %> 5.0 5.1
  15. PR 26976 by Kasper Timm Hansen Add form_with to unify

    form_tag and form_for Action View
  16. Add form_with to unify form_tag and form_for # app/views/posts/show.html.erb <%=

    form_for @post, method: :delete do |f| %> <%= f.submit 'Delete post' %> <% end %> # app/views/posts/show.html.erb <%= form_with model: @post, method: :delete do |f| %> <%= f.submit 'Delete post' %> <% end %> 5.0 5.1
  17. Add form_with to unify form_tag and form_for # app/views/posts/index.html.erb <%=

    form_tag '/posts/1', method: :delete do %> <%= submit_tag 'Delete post #1' %> <% end %> # app/views/posts/index.html.erb <%= form_with url: '/posts/1', method: :delete do |f| %> <%= submit_tag 'Delete post #1' %> <% end %> 5.0 5.1
  18. Display railtie class name in `rails initializers` $ rails initializers

    set_load_path set_load_path [124 more…] $ rails initializers ActionView::Railtie.set_load_path ActionCable::Engine.set_load_path [126 more…] 5.0 5.1
  19. Add encrypted secrets in config/secrets.yml.enc # config/secrets.yml # Do not

    keep production secrets in the repository, # instead read values from the environment. production: secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> $ rails console production > Rails.application.secrets # => {:secret_key_base=>nil, :secret_token=>nil} 5.0 5.0
  20. Add encrypted secrets in config/secrets.yml.enc $ rails secrets:setup Adding config/secrets.yml.key

    to store the encryption key: 667c… $ more config/secrets.yml.enc # QMdWtttAU5ZJVrsJRFot4j0gCgaqjjsLA0CIFnAhdc+LByI4ILZFwR $ EDITOR=vi rails secrets:edit # See `secrets.yml` for tips on generating suitable keys. production: api_key: "466aac22e6a869134be3d09b9e89232fc2c228" 5.1
  21. Drop jQuery as a dependency and include rails-ujs <%= link_to

    'Destroy', post, method: :delete, data: {confirm: 'Are you sure?'} %> <a data-confirm="Are you sure?" data-method="delete" href="/posts/7">Destroy</a>
  22. Drop jQuery as a dependency and include rails-ujs <%= link_to

    'Destroy', post, method: :delete, data: {confirm: 'Are you sure?'} %> <a data-confirm="Are you sure?" data-method="delete" href="/posts/7">Destroy</a>
  23. Drop jQuery as a dependency and include rails-ujs # Gemfile

    gem 'jquery-rails' # app/assets/javascripts/application.js //= require jquery //= require jquery_ujs # app/assets/javascripts/application.js //= require rails-ujs 5.0 5.1
  24. PR 26836 by Liceth Ovalles Rodriguez Add Yarn support in

    new apps using --yarn option Railties
  25. Add Yarn support in new apps $ yarn init $

    yarn add bootstrap $ echo ".node_modules/" >> .gitignore # config/initializers/assets.rb config.assets.paths << Rails.root.join('node_modules') # app/assets/stylesheets/application.css *= require bootstrap/dist/css/bootstrap # app/assets/javascripts/application.js //= require bootstrap/dist/js/bootstrap 5.0
  26. Add Yarn support in new apps $ bin/yarn init $

    bin/yarn add bootstrap # app/assets/stylesheets/application.css *= require bootstrap/dist/css/bootstrap # app/assets/javascripts/application.js //= require bootstrap/dist/js/bootstrap 5.1
  27. Basic --webpack delegation to new webpacker gem $ rails new

    app_name --webpack 5.1 rails webpacker:install Creating javascript app source directory create app/javascript create app/javascript/packs/application.js Copying binstubs create bin/webpack-dev-server create bin/webpack-watcher create bin/webpack Copying webpack core config and loaders create config/webpack/configuration.js create config/webpack/development.js create config/webpack/development.server.js create config/webpack/development.server.yml create config/webpack/paths.yml create config/webpack/production.js create config/webpack/shared.js create config/webpack/loaders create config/webpack/loaders/assets.js create config/webpack/loaders/babel.js create config/webpack/loaders/coffee.js create config/webpack/loaders/erb.js create config/webpack/loaders/sass.js create .postcssrc.yml create .gitignore Installing all JavaScript dependencies run ./bin/yarn add webpack webpack-merge…
  28. Basic --webpack delegation to new webpacker gem $ webpack-dev-server #

    app/views/layouts/application.html.erb <%= javascript_pack_tag 'application' %> <%= stylesheet_pack_tag 'application' %> # app/javascript/packs/application.js.erb require('moment') <% helpers = ActionController::Base.helpers %> var railsImagePath = "<%= helpers.image_path('rails.png') %>" 5.1
  29. Capybara integration with Rails (AKA System Tests) # Gemfile group

    :development, :test do gem 'capybara' gem 'selenium-webdriver' end # test/test_helper.rb require 'capybara/rails' require 'capybara/minitest' […] 5.0
  30. Capybara integration with Rails (AKA System Tests) # test/test_helper.rb class

    ActionDispatch::IntegrationTest include Capybara::DSL include Capybara::Minitest::Assertions Capybara.register_driver :selenium do |app| Capybara::Selenium::Driver.new app, browser: :chrome end Capybara.default_driver = :selenium end 5.0
  31. Custom URL helpers and polymorphic mapping $ rails test:integration #

    => 1 runs, 1 assertions, 0 failures # test/integration/posts_test.rb require "test_helper" class PostsTest < ActionDispatch::IntegrationTest test "visiting the 'posts' page" do visit '/posts' assert_selector 'h1', text: 'Posts' end end 5.0
  32. Capybara integration with Rails (AKA System Tests) # test/system/posts_test.rb require

    "application_system_test_case" class PostsTest < ApplicationSystemTestCase test "visiting the 'posts' page" do visit posts_url assert_selector 'h1', text: 'Posts' end end $ rails test:system # => 1 runs, 1 assertions, 0 failures 5.1
  33. Custom URL helpers and polymorphic mapping <a href="/posts/1#content-2">Comment #2</a> <%=

    link_to "Comment #2", post_path(@comment.post, anchor: 'content-2') %> # config/routes.rb direct(:embedded_content) do |content| url_for [content.post, anchor: "content-#{content.id}"] end <%= link_to "Comment #2", embedded_content_path(@comment) %> 5.0 5.1
  34. Custom URL helpers and polymorphic mapping # config/routes.rb resource :profile

    # app/assets/views/profiles/new.html.erb <%= form_for @profile, url: profile_path(@profile) do |f| %> # config/routes.rb resource :profile resolve('Profile') { [:profile] } # app/assets/views/profiles/new.html.erb <%= form_for @profile do |f| %> 5.0 5.1
  35. DateTime#change supports :usec and :nsec options now = DateTime.now now.to_f

    # => 1490028163.625132 now.change(usec: 0).to_f # => 1490028163.625132 now = DateTime.now now.to_f # => 1490028163.625132 now.change(usec: 0).to_f # => 1490028163.0 DateTime.now.end_of_day.nsec # => 999_999_999 5.0 5.1
  36. Add :check_parameters option to current_page? # From http://www.example.com/shop/checkout?order=desc&page=1 current_page? 'http://www.example.com/shop/checkout'

    # => true # From http://www.example.com/shop/checkout?order=desc&page=1 current_page? 'http://www.example.com/shop/checkout', check_parameters: true # => false 5.0 5.1
  37. Add retry_on/discard_on for exception handling class SiteScraperJob < ActiveJob::Base rescue_from(ApocalypticException)

    rescue_from(ErrorLoadingSite) do retry_job queue: :low_priority end def perform(*args) # raise ErrorLoadingSite if cannot scrape end end 5.0
  38. Add retry_on/discard_on for exception handling class SiteScraperJob < ActiveJob::Base discard_on

    ApocalypticException retry_on ErrorLoadingSite # retry_on ErrorLoadingSite, wait: :exponentially_longer # retry_on ErrorLoadingSite, wait: ->(attempts) { attempts * 2 } def perform(*args) # raise ErrorLoadingSite if cannot scrape end end 5.1
  39. Add parameterized invocation of mailers class PartyMailer < ApplicationMailer def

    birthday_invite(guest) mail subject: "Come to my birthday!", to: guest.email_address end def wedding_invite(guest) mail subject: "Come to my wedding!", to: guest.email_address end end PartyMailer.birthday_invite(current_user) 5.0
  40. Add parameterized invocation of mailers class PartyMailer < ApplicationMailer before_action

    { @guest = params[:guest] } default to: -> { @guest.email_address } def birthday_invite mail subject: "Come to my birthday!" end def wedding_invite; mail subject: "Come to my wedding!"; end end PartyMailer.with(guest: current_user).birthday_invite 5.1