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. Slides at speakerdeck.com/claudiob
    Rails 5.1:
    awesome features
    & breaking changes

    View full-size slide

  2. 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

    View full-size slide

  3. Breaking changes

    View full-size slide

  4. PR 27757 by Jeremy Evans
    Change Action View
    ERB handler from
    Erubis to Erubi
    Breaking change

    View full-size slide

  5. commit 0952552 by Ryuta Kamizono
    Deprecate String
    options :if and :unless
    to set/skip callbacks
    Breaking change

    View full-size slide

  6. 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

    View full-size slide

  7. 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

    View full-size slide

  8. PR 23980 by Andrew White
    Deprecate :action
    and :controller path
    parameters
    Breaking change

    View full-size slide

  9. 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

    View full-size slide

  10. Active Record

    View full-size slide

  11. Change default
    primary keys to
    BIGINT
    PR 26266 by Jon McCartie
    Active
    Record

    View full-size slide

  12. Virtual column
    support for MySQL
    and MariaDB
    commit 65bf1c6 by Ryuta Kamizono
    Active
    Record

    View full-size slide

  13. 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

    View full-size slide

  14. commit 451437c by Xavier Noria
    Adds support for
    limits in batch
    processing
    Active
    Record

    View full-size slide

  15. 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

    View full-size slide

  16. Active Support

    View full-size slide

  17. Update Unicode
    version to 9.0.0
    PR 27822 by Fumiaki Matsushima
    Active
    Support

    View full-size slide

  18. 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

    View full-size slide

  19. Add Duration#after
    and #before as alias
    for #since and #until
    PR 27721 by Nick Johnstone
    Active
    Support

    View full-size slide

  20. 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

    View full-size slide

  21. Introduce Module#
    delegate_missing_to
    PR 23930 by Genadi Samokovarov
    Active
    Support

    View full-size slide

  22. 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

    View full-size slide

  23. 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

    View full-size slide

  24. New syntax for
    Action View’s tag
    helpers
    PR 25543 by Marek Kirejczyk
    Action
    View

    View full-size slide

  25. 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

    View full-size slide

  26. PR 26976 by Kasper Timm Hansen
    Add form_with to
    unify form_tag and
    form_for
    Action
    View

    View full-size slide

  27. 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

    View full-size slide

  28. 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

    View full-size slide

  29. PR 25257 by ta1kt0me
    Display railtie class
    name in
    "rails initializers"
    Railties

    View full-size slide

  30. 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

    View full-size slide

  31. commit e530534 by David Heinemeier Hansson
    Added a shared
    section to
    config/secrets.yml
    Railties

    View full-size slide

  32. Added a shared section to config/secrets.yml
    # config.secrets.yml
    default: &default
    email_from: [email protected]
    development:
    <<: *default
    shared:
    email_from: [email protected]
    5.0
    5.1

    View full-size slide

  33. Add encrypted
    secrets in config/
    secrets.yml.enc
    PR 28038 by Kasper Timm Hansen
    Railties

    View full-size slide

  34. 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

    View full-size slide

  35. 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

    View full-size slide

  36. PR 27113 by Guillermo Iguaran
    Drop jQuery as a
    dependency and
    include rails-ujs
    Railties

    View full-size slide

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

    View full-size slide

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

    View full-size slide

  39. 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

    View full-size slide

  40. PR 26836 by Liceth Ovalles Rodriguez
    Add Yarn support in
    new apps using
    --yarn option
    Railties

    View full-size slide

  41. 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

    View full-size slide

  42. 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

    View full-size slide

  43. PR 27288 by David Heinemeier Hansson
    Basic --webpack
    delegation to new
    webpacker gem
    Railties

    View full-size slide

  44. 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…

    View full-size slide

  45. 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

    View full-size slide

  46. PR 26703 by Eileen M. Uchitelle
    Capybara integration
    with Rails
    (AKA System Tests)
    Action
    Pack

    View full-size slide

  47. Capybara integration with Rails (AKA System Tests)

    View full-size slide

  48. 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

    View full-size slide

  49. 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

    View full-size slide

  50. 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

    View full-size slide

  51. 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

    View full-size slide

  52. PR 23138 by Andrew White
    Custom URL helpers
    and polymorphic
    mapping
    Action
    Pack

    View full-size slide

  53. Custom URL helpers and polymorphic mapping

    View full-size slide

  54. Custom URL helpers and polymorphic mapping
    Comment #2
    <%= 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

    View full-size slide

  55. Custom URL helpers and polymorphic mapping



    View full-size slide

  56. Custom URL helpers and polymorphic mapping
    <%= form_for @profile do |f| %>

    <% end %>
    5.0

    View full-size slide

  57. 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

    View full-size slide

  58. Rails 5.1:
    awesome features
    & breaking changes
    speakerdeck.com/claudiob
    Thanks!

    View full-size slide

  59. One more thing…
    Extra time? Extra slides!

    View full-size slide

  60. PR 26988 by Pavel Evstigneev
    Add
    ActiveRecord::Base.
    connection_pool.stat
    Active
    Record

    View full-size slide

  61. Add ActiveRecord::Base. connection_pool.stat
    p ActiveRecord::Base.connection_pool.stat
    {
    size: 25,
    connections: 1,
    busy: 1, dead: 0, idle: 0,
    waiting: 0,
    checkout_timeout: 5
    }
    5.1

    View full-size slide

  62. PR 28242 by Andrew White
    DateTime#change
    supports :usec
    and :nsec options
    Active
    Support

    View full-size slide

  63. 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

    View full-size slide

  64. PR 27549 by Maksym Pugach
    Add option
    :check_parameters
    to current_page?
    Action
    View

    View full-size slide

  65. 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

    View full-size slide

  66. PR 25991 by David Heinemeier Hansson
    Add retry_on/
    discard_on for better
    exception handling
    Active
    Job

    View full-size slide

  67. 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

    View full-size slide

  68. 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

    View full-size slide

  69. Action Mailer

    View full-size slide

  70. Add parameterized
    invocation of mailers
    PR 27825 by David Heinemeier Hansson
    Action
    Mailer

    View full-size slide

  71. 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

    View full-size slide

  72. 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

    View full-size slide

  73. Rails 5.1:
    awesome features
    & breaking changes
    Thanks!

    View full-size slide