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

  3. Breaking changes

    View Slide

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

    View Slide

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

    View 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 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 Slide

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

    View 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 Slide

  10. Active Record

    View Slide

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

    View Slide

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

    View 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 Slide

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

    View 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 Slide

  16. Active Support

    View Slide

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

    View 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 Slide

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

    View 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 Slide

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

    View 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 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 Slide

  24. Action View

    View Slide

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

    View Slide

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

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

    View Slide

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

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

  30. Railties

    View Slide

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

    View Slide

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

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

    View Slide

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

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

    View Slide

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

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

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

    View Slide

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

    View Slide

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

    View Slide

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

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

    View Slide

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

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

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

    View Slide

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

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

  48. Action Pack

    View Slide

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

    View Slide

  50. Capybara integration with Rails (AKA System Tests)

    View Slide

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

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

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

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

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

    View Slide

  56. Custom URL helpers and polymorphic mapping

    View Slide

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

  58. Custom URL helpers and polymorphic mapping



    View Slide

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

    <% end %>
    5.0

    View Slide

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

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

    View Slide

  62. View Slide

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

    View Slide

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

    View Slide

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

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

    View Slide

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

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

    View Slide

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

  70. Active Job

    View Slide

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

    View Slide

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

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

  74. Action Mailer

    View Slide

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

    View Slide

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

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

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

    View Slide