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

Ten Years of Rails Upgrades

Ten Years of Rails Upgrades

Presented at RailsConf 2018 in Pittsburgh, PA.

Upgrading Rails can go from easy-to-hard quickly. If you've struggled to upgrade to a new version of Rails, you're not alone. And yet, with useful deprecation warnings and extensive beta periods, Rails has never made it easier to upgrade. So what makes it hard?

By looking at the past ten years of Rails upgrades at Clio (and other notable apps), let's see what we can learn. Gain insight into the tradeoffs between different timelines and approaches and learn practical ways to keep your app up-to-date.

Jordan Raine

April 19, 2018
Tweet

More Decks by Jordan Raine

Other Decks in Programming

Transcript

  1. Ten Years of Rails Upgrades
    Jordan Raine
    @jnraine

    View full-size slide

  2. Jordan Raine (@jnraine)
    I’m a Rails developer at Clio
    From Vancouver, BC
    !
    "
    #
    Ten Years of Rails Upgrades

    View full-size slide

  3. Why is it still so tough?

    View full-size slide

  4. Tiny Co. / Big Inc.

    View full-size slide

  5. $
    Tiny Co.
    %
    Big Inc.
    1. Gems Few Many
    2. Code changes Few Many
    3. Test Few failures Won’t even run
    4. Deploy Easy Terrifying

    View full-size slide

  6. $
    Tiny Co.
    %
    Big Inc.
    1. Gems ✅ ✅
    2. Code changes ✅ ✅
    3. Test ✅ ✅
    4. Deploy ✅ ✅

    View full-size slide

  7. 2010 2011 2012 2013 2014 2015
    2009
    2008
    2007 2016 2017 2018
    2.0 3.0
    3.1
    3.2
    2.1 2.2 2.3
    2.0 2.1 2.2 2.3 3.0 3.1 3.2 4.0 4.2
    4.1 5.0 5.1 5.2
    4.0
    4.1
    4.2

    View full-size slide

  8. 2010 2011 2012 2013 2014 2015
    2009
    2008
    2007 2016 2017 2018
    2.0 3.0
    3.1
    3.2
    2.1 2.2 2.3
    2.0 2.1 2.2 2.3 3.0 3.1 3.2 4.0 4.2
    4.1 5.0 5.1 5.2
    4.0
    4.1
    4.2

    View full-size slide

  9. '•More developers

    •More features

    •More customers

    •More revenue

    View full-size slide

  10. 2010 2011 2012 2013 2014 2015
    2009
    2008
    2007 2016 2017 2018
    2.0 3.0
    3.1
    3.2
    2.1 2.2 2.3
    2.0 2.1 2.2 2.3 3.0 3.1 3.2 4.0 4.2
    4.1 5.0 5.1 5.2
    4.0
    4.1
    4.2

    View full-size slide

  11. Problems
    Tiny Co. / Big Inc.

    View full-size slide

  12. Dependencies aren’t free.

    View full-size slide

  13. Find the dependencies –
    and eliminate them.
    https://www.joelonsoftware.com/2001/10/14/in-defense-of-not-invented-here-syndrome/


    Joel On Software

    View full-size slide

  14. The Excel team’s ruggedly
    independent mentality also meant
    that they always shipped on time
    [and] their code was of uniformly
    high quality.
    Joel On Software
    https://www.joelonsoftware.com/2001/10/14/in-defense-of-not-invented-here-syndrome/


    View full-size slide

  15. gem "quickbooks-ruby"
    gem "oauth"

    View full-size slide

  16. gem "quickbooks-ruby"
    gem "oauth"

    View full-size slide

  17. gem "quickbooks-ruby"
    gem "oauth", "0.x.x"

    View full-size slide

  18. a) Don’t upgrade any gems
    b) Upgrade both gems
    c) Fork a gem and downgrade

    View full-size slide

  19. a) Don’t upgrade any gems
    b) Upgrade both gems
    c) Fork a gem and downgrade

    View full-size slide

  20. gem "quickbooks-ruby", github: "/quickbooks-ruby", ref
    gem "oauth", "0.x.x"

    View full-size slide

  21. Rigid dependencies are difficult to maintain.

    View full-size slide

  22. class MyController < ApplicationController
    - before_filter :require_login
    + before_action :require_login
    end

    View full-size slide

  23. class MyModel < ApplicationRecord
    attr_accessible :name, :description
    # ...
    end

    View full-size slide

  24. protected_attributes 4,947,703
    activerecord >= 5.0 15,350,275

    View full-size slide

  25. We like protected_attributes 1/3 as much as activerecord.

    View full-size slide

  26. 2010 2011 2012 2013 2014 2015
    2009
    2008
    2007 2016 2017 2018
    2.0 3.0
    3.1
    3.2
    2.1 2.2 2.3
    2.0 2.1 2.2 2.3 3.0 3.1 3.2 4.0 4.2
    4.1 5.0 5.1 5.2
    4.0
    4.1
    4.2
    (
    ( (

    View full-size slide

  27. Tiny Co. / Big Inc.
    Problems
    Close the gaps

    View full-size slide

  28. ) Keep the Gemfile healthy
    * Outlaw deprecations
    + Canary Rails

    View full-size slide

  29. ) Keep the Gemfile healthy
    * Outlaw deprecations
    + Canary Rails

    View full-size slide

  30. gem "multi_json", "1.9.1"
    gem "mime-types", "~> 2.0"

    View full-size slide

  31. gem "multi_json", "1.9.1"
    gem "mime-types", "~> 2.0"
    Drop those version constraints!

    View full-size slide

  32. gem "multi_json"
    gem "mime-types"
    Drop those version constraints!
    ,

    View full-size slide

  33. gem "quickbooks-ruby", github: "/quickbooks-ruby",

    View full-size slide

  34. gem "quickbooks-ruby", github: "/quickbooks-ruby",
    Kill your forks!

    View full-size slide

  35. gem "quickbooks-ruby"
    ,
    Kill your forks!

    View full-size slide

  36. Culture of updating gems
    $ bundle update multi_json mime-types

    View full-size slide

  37. $ bundle outdated

    View full-size slide

  38. $ bundle outdated
    Outdated gems included in the bundle:
    * actionmailer (newest 5.2.0, installed 5.1.4, requested ~> 5.1) in groups "default"
    * actionpack (newest 5.2.0, installed 5.1.4, requested ~> 5.1) in groups "default"
    * actionview (newest 5.2.0, installed 5.1.4, requested ~> 5.1) in groups "default"
    * active_model_serializers (newest 0.10.7, installed 0.8.3, requested ~> 0.8.3) in groups "default"
    * activejob (newest 5.2.0, installed 5.1.4)
    * activemodel (newest 5.2.0, installed 5.1.4, requested ~> 5.1) in groups "default"
    * activerecord (newest 5.2.0, installed 5.1.4, requested ~> 5.1) in groups "default"

    View full-size slide

  39. actionmailer (newest 5.2.0, installed 5.1.4, requested ~> 5.1) in groups "default"
    name newest version installed version requested version group

    View full-size slide

  40. $ bundle outdated
    bundle outdated
    Fetching gem metadata from https://rubygems.org/...............
    Fetching gem metadata from https://rubygems.org/..
    Resolving dependencies...........
    Outdated gems included in the bundle:
    * actionmailer (newest 5.2.0, installed 5.1.4, requested ~> 5.1) in groups "default"
    * actionpack (newest 5.2.0, installed 5.1.4, requested ~> 5.1) in groups "default"
    * actionview (newest 5.2.0, installed 5.1.4, requested ~> 5.1) in groups "default"
    * active_model_serializers (newest 0.10.7, installed 0.8.3, requested ~> 0.8.3) in groups "default"
    * activejob (newest 5.2.0, installed 5.1.4)
    * activemodel (newest 5.2.0, installed 5.1.4, requested ~> 5.1) in groups "default"
    * activerecord (newest 5.2.0, installed 5.1.4, requested ~> 5.1) in groups "default"
    * activesupport (newest 5.2.0, installed 5.1.4, requested ~> 5.1) in groups "default"
    * addressable (newest 2.5.2, installed 2.5.1)
    * arel (newest 9.0.0, installed 8.0.0)
    * aws-partitions (newest 1.80.0, installed 1.24.0)
    * aws-sdk-core (newest 3.19.0, installed 3.6.0)
    * aws-sdk-kms (newest 1.5.0, installed 1.2.0)
    * aws-sdk-s3 (newest 1.9.0, installed 1.4.0) in groups "default"
    * barber (newest 0.12.0, installed 0.11.2) in groups "default"
    * better_errors (newest 2.4.0, installed 2.1.1) in groups "development"
    * bootsnap (newest 1.3.0, installed 1.1.8) in groups "default"
    * bullet (newest 5.7.5, installed 5.5.1) in groups "development"
    * byebug (newest 10.0.2, installed 9.0.6) in groups "test, development"
    * chunky_png (newest 1.3.10, installed 1.3.8)
    * crass (newest 1.0.4, installed 1.0.3)
    * ember-data-source (newest 3.0.2, installed 2.2.1)
    * ember-handlebars-template (newest 0.8.0, installed 0.7.5, requested = 0.7.5) in groups "default"
    * ember-rails (newest 0.21.0, installed 0.18.5, requested = 0.18.5) in groups "default"
    * ember-source (newest 2.18.2, installed 2.13.3, requested = 2.13.3) in groups "default"
    * erubi (newest 1.7.1, installed 1.6.1)
    * excon (newest 0.62.0, installed 0.56.0) in groups "default"
    * exifr (newest 1.3.3, installed 1.2.5)
    * fabrication (newest 2.20.1, installed 2.9.8, requested = 2.9.8) in groups "test, development"
    * faraday (newest 0.14.0, installed 0.11.0)
    * ffi (newest 1.9.23, installed 1.9.18)
    * globalid (newest 0.4.1, installed 0.4.0)
    * hashdiff (newest 0.3.7, installed 0.3.4)
    * hashie (newest 3.5.7, installed 3.5.5)
    * highline (newest 1.7.10, installed 1.7.8) in groups "default"
    * http_accept_language (newest 2.1.1, installed 2.0.5, requested ~> 2.0.5) in groups "default"
    * i18n (newest 1.0.0, installed 0.8.6)
    * in_threads (newest 1.5.0, installed 1.4.0)
    * jmespath (newest 1.4.0, installed 1.3.1)
    * jwt (newest 2.1.0, installed 1.5.6)
    * kgio (newest 2.11.2, installed 2.11.1)
    * lograge (newest 0.10.0, installed 0.7.1) in groups "default"
    * logstash-logger (newest 0.26.1, installed 0.25.1) in groups "default"
    * method_source (newest 0.9.0, installed 0.8.2)
    * mini_mime (newest 1.0.0, installed 0.1.3) in groups "default"
    * minitest (newest 5.11.3, installed 5.10.3) in groups "test"
    * mocha (newest 1.5.0, installed 1.2.1) in groups "test, development"
    * mock_redis (newest 0.18.0, installed 0.17.3) in groups "test, development"
    * oauth (newest 0.5.4, installed 0.5.1)
    * oauth2 (newest 1.4.0, installed 1.3.1)
    * oj (newest 3.5.1, installed 3.4.0) in groups "default"
    * omniauth (newest 1.8.1, installed 1.6.1) in groups "default"
    * omniauth-facebook (newest 5.0.0, installed 4.0.0) in groups "default"
    * omniauth-google-oauth2 (newest 0.5.3, installed 0.3.1) in groups "default"
    * omniauth-instagram (newest 1.3.0, installed 1.0.2) in groups "default"
    * omniauth-oauth2 (newest 1.5.0, installed 1.4.0) in groups "default"
    * omniauth-twitter (newest 1.4.0, installed 1.3.0) in groups "default"
    * parser (newest 2.5.1.0, installed 2.5.0.3)
    * pg (newest 1.0.0, installed 0.21.0, requested ~> 0.21.0) in groups "default"
    * progress (newest 3.4.0, installed 3.3.1)
    * pry (newest 0.11.3, installed 0.10.4)
    * pry-rails (newest 0.3.6, installed 0.3.4) in groups "default"
    * public_suffix (newest 3.0.2, installed 2.0.5)
    * puma (newest 3.11.4, installed 3.9.1) in groups "default"
    * r2 (newest 0.2.7, installed 0.2.6, requested ~> 0.2.5) in groups "default"
    * rack-openid (newest 1.4.2, installed 1.3.1)
    * rack-test (newest 1.0.0, installed 0.7.0)
    * railties (newest 5.2.0, installed 5.1.4, requested ~> 5.1) in groups "default"
    * rake (newest 12.3.1, installed 12.3.0) in groups "default"
    * rb-fsevent (newest 0.10.3, installed 0.9.8) in groups "test, development"
    * rb-inotify (newest 0.9.10, installed 0.9.8, requested ~> 0.9) in groups "test, development"
    * redis (newest 4.0.1, installed 3.3.5) in groups "default"
    * redis-namespace (newest 1.6.0, installed 1.5.3) in groups "default"
    * request_store (newest 1.4.1, installed 1.3.2)
    * rinku (newest 2.0.4, installed 2.0.2) in groups "default"
    * rotp (newest 3.3.1, installed 3.3.0) in groups "default"
    * rspec (newest 3.7.0, installed 3.6.0) in groups "test, development"
    * rspec-core (newest 3.7.1, installed 3.6.0)
    * rspec-expectations (newest 3.7.0, installed 3.6.0)
    * rspec-mocks (newest 3.7.0, installed 3.6.0)
    * rspec-rails (newest 3.7.2, installed 3.6.1) in groups "test, development"
    * rspec-support (newest 3.7.1, installed 3.6.0)
    * rubocop (newest 0.54.0, installed 0.53.0) in groups "test, development"
    * ruby-prof (newest 0.17.0, installed 0.16.2) in groups "development"
    * sass (newest 3.5.6, installed 3.4.24)
    * sassc (newest 1.11.4, installed 1.11.2) in groups "default"
    * seed-fu (newest 2.3.9, installed 2.3.7) in groups "default"
    * shoulda-matchers (newest 3.1.2, installed 2.8.0)
    * sidekiq (newest 5.1.3, installed 5.0.5) in groups "default"
    * slop (newest 4.6.2, installed 3.6.0)
    * sprockets-rails (newest 3.2.1, installed 3.2.0) in groups "default"
    * stackprof (newest 0.2.11, installed 0.2.10) in groups "default"
    * thor (newest 0.20.0, installed 0.19.4) in groups "default"
    * tilt (newest 2.0.8, installed 2.0.7) in groups "default"
    * tzinfo (newest 1.2.5, installed 1.2.3)
    * uglifier (newest 4.1.9, installed 3.2.0) in groups "assets"
    * unf_ext (newest 0.0.7.5, installed 0.0.7.4)
    * uniform_notifier (newest 1.11.0, installed 1.10.0)
    where do I start?
    • what is most important?
    • which are the oldest?
    • what is unmaintained?

    View full-size slide

  41. $ bin/bundle_report

    View full-size slide

  42. $ bin/bundle_report outdated

    View full-size slide

  43. $ bin/bundle_report outdated | head -n 5
    rack-openid 1.3.1: released about 7 years ago (latest version, 1.4.2, released about 4 years ago)
    method_source 0.8.2: released over 4 years ago (latest version, 0.9.0, released 7 months ago)
    fabrication 2.9.8: released about 4 years ago (latest version, 2.20.1, released 3 months ago)
    slop 3.6.0: released over 3 years ago (latest version, 4.6.2, released about 1 month ago)
    active_model_serializers 0.8.3: released over 3 years ago (latest version, 0.10.7, released 5 months ago)

    View full-size slide

  44. rack-openid 1.3.1: released about 7 years ago (latest version, 1.4.2, released about 4 years ago)
    name installed version release date newest version release date

    View full-size slide

  45. $ bin/bundle_report compatibility --rails-version=5.2.0

    View full-size slide

  46. $ bin/bundle_report compatibility --rails-version=5.2.0

    View full-size slide

  47. $ bin/bundle_report compatibility --rails-version 5.2.0
    => Incompatible with Rails 5.2.0 (with new versions that are compatible):
    These gems will need to be upgraded before upgrading to Rails 5.2.0.
    lograge 0.7.1 - upgrade to 0.10.0
    => Incompatible with Rails 5.2.0 (with no new compatible versions):
    These gems will need to be removed or replaced before upgrading to Rails
    5.2.0.
    jquery-rails 4.3.1 - new version, 4.3.1, is not compatible with Rails 5.2.0
    2 gems incompatible with Rails 5.2.0

    View full-size slide

  48. $ bin/bundle_report compatibility --rails-version 5.2.0
    => Incompatible with Rails 5.2.0 (with new versions that are compatible):
    These gems will need to be upgraded before upgrading to Rails 5.2.0.
    lograge 0.7.1 - upgrade to 0.10.0
    => Incompatible with Rails 5.2.0 (with no new compatible versions):
    These gems will need to be removed or replaced before upgrading to Rails
    5.2.0.
    jquery-rails 4.3.1 - new version, 4.3.1, is not compatible with Rails 5.2.0
    2 gems incompatible with Rails 5.2.0

    View full-size slide

  49. $ bin/bundle_report compatibility --rails-version 5.2.0
    => Incompatible with Rails 5.2.0 (with new versions that are compatible):
    These gems will need to be upgraded before upgrading to Rails 5.2.0.
    lograge 0.7.1 - upgrade to 0.10.0
    => Incompatible with Rails 5.2.0 (with no new compatible versions):
    These gems will need to be removed or replaced before upgrading to Rails
    5.2.0.
    jquery-rails 4.3.1 - new version, 4.3.1, is not compatible with Rails 5.2.0
    2 gems incompatible with Rails 5.2.0

    View full-size slide

  50. $ bin/bundle_report compatibility --rails-version 5.2.0
    => Incompatible with Rails 5.2.0 (with new versions that are compatible):
    These gems will need to be upgraded before upgrading to Rails 5.2.0.
    lograge 0.7.1 - upgrade to 0.10.0
    => Incompatible with Rails 5.2.0 (with no new compatible versions):
    These gems will need to be removed or replaced before upgrading to Rails
    5.2.0.
    jquery-rails 4.3.1 - new version, 4.3.1, is not compatible with Rails 5.2.0
    2 gems incompatible with Rails 5.2.0

    View full-size slide

  51. ) Keep the Gemfile healthy
    * Outlaw deprecations
    + Canary Rails

    View full-size slide

  52. ) Keep the Gemfile healthy
    * Outlaw deprecations
    + Canary Rails

    View full-size slide

  53. User.find(current_user)
    # DEPRECATION WARNING: You are passing an instance
    # of ActiveRecord::Base to `find`. Please pass the
    # id of the object by calling `.id`. (called from at (

    View full-size slide

  54. ActiveSupport::Deprecation.behavior = :raise

    View full-size slide

  55. if ENV["DEPRECATION_TRACKER"]
    DeprecationTracker.track_rspec(
    config,
    shitlist_path: "deprecation_warning.shitlist.json",
    mode: ENV["DEPRECATION_TRACKER"]
    )
    end

    View full-size slide

  56. $ DEPRECATION_TRACKER=save rspec


    deprecations.shitlist.json
    $ DEPRECATION_TRACKER=compare rspec
    -

    View full-size slide

  57. {
    "./spec/controllers/post_controller_spec.rb": [
    "DEPRECATION WARNING: env is deprecated and will be remov
    ],
    "./spec/controllers/session_controller_spec.rb": [
    "DEPRECATION WARNING: `xhr` and `xml_http_request` are de
    "DEPRECATION WARNING: env is deprecated and will be remov
    ],
    "./spec/controllers/accounts_controller_spec.rb": [
    "DEPRECATION WARNING: Using positional arguments in funct
    ]
    }

    View full-size slide

  58. {
    "./spec/controllers/post_controller_spec.rb": [
    "DEPRECATION WARNING: env is deprecated and will be remov
    ],
    "./spec/controllers/session_controller_spec.rb": [
    "DEPRECATION WARNING: `xhr` and `xml_http_request` are de
    "DEPRECATION WARNING: env is deprecated and will be remov
    ],
    "./spec/controllers/accounts_controller_spec.rb": [
    "DEPRECATION WARNING: Using positional arguments in funct
    ]
    }

    View full-size slide

  59. {
    "./spec/controllers/post_controller_spec.rb": [
    "DEPRECATION WARNING: env is deprecated and will be remov
    ],
    "./spec/controllers/session_controller_spec.rb": [
    "DEPRECATION WARNING: `xhr` and `xml_http_request` are de
    "DEPRECATION WARNING: env is deprecated and will be remov
    ],
    "./spec/controllers/accounts_controller_spec.rb": [
    "DEPRECATION WARNING: Using positional arguments in funct
    ]
    }

    View full-size slide

  60. $ bin/deprecations info

    View full-size slide

  61. $ bin/deprecations info
    Ten most common deprecation warnings:
    Occurrences: 608
    DEPRECATION WARNING: Using positional arguments in functional tests has been deprecated,
    in favor of keyword arguments, and will be removed in Rails 5.1.
    Deprecated style:
    get :show, { id: 1 }, nil, { notice: "This is a flash message" }
    New keyword style:
    get :show, params: { id: 1 }, flash: { notice: "This is a flash message" },
    session: nil # Can safely be omitted.
    (called from block (3 levels) in at spec/foo.rb:67)
    ----------
    Occurrences: 553
    DEPRECATION WARNING: Passing an argument to force an association to reload is now
    deprecated and will be removed in Rails 5.1.
    Please call `reload_active_al_subscription` instead. (called from reload_subscriptions at
    app/models/foo.rb:270)
    # ...

    View full-size slide

  62. $ bin/deprecations run

    View full-size slide

  63. $ bin/deprecations run --pattern "ActiveRecord::Base"

    View full-size slide

  64. $ bin/deprecations run --tracker-mode save

    View full-size slide

  65. ActiveSupport::Deprecation.behavior = :raise

    View full-size slide

  66. ) Keep the Gemfile healthy
    * Outlaw deprecations
    + Canary Rails

    View full-size slide

  67. ) Keep the Gemfile healthy
    * Outlaw deprecations
    + Dual-boot Rails next

    View full-size slide

  68. “current” Rails “next” Rails
    4.2 5.0
    5.0 5.1
    5.2 master

    View full-size slide

  69. $ bin/next rails s
    $ bin/next rspec
    $ DEPRECATION_TRACKER=save bin/next rspec

    View full-size slide

  70. $ bin/next rails s
    $ bin/next rspec
    $ DEPRECATION_TRACKER=save bin/next rspec

    View full-size slide

  71. $ bin/next rails s
    $ bin/next rspec
    $ DEPRECATION_TRACKER=save bin/next rspec

    View full-size slide

  72. -old_deprecated_thing
    +new_thing_that_works_in_both_versions

    View full-size slide

  73. +if Rails.application.next?
    + do_new_thing
    +else
    + do_old_thing
    +end
    -do_old_thing

    View full-size slide

  74. Gemfile Gemfile.next

    View full-size slide

  75. # top of Gemfile
    def next?
    File.basename(__FILE__) == "Gemfile.next"
    end
    # later
    if next?
    gem "rails", "5.2.0"
    else
    gem "rails", "5.1.6"
    end

    View full-size slide

  76. # top of Gemfile
    def next?
    File.basename(__FILE__) == "Gemfile.next"
    end
    # later
    if next?
    gem "rails", "5.2.0"
    else
    gem "rails", "5.1.6"
    end

    View full-size slide

  77. # top of Gemfile
    def next?
    File.basename(__FILE__) == "Gemfile.next"
    end
    # later
    if next?
    gem "rails", "5.2.0"
    else
    gem "rails", "5.1.6"
    end

    View full-size slide

  78. Gemfile.next
    Gemfile.next.lock
    Gemfile.lock
    Gemfile

    View full-size slide

  79. $ bin/next --init

    View full-size slide

  80. #!/bin/bash
    export BUNDLE_GEMFILE=Gemfile.next
    export BUNDLE_CACHE_PATH=vendor/cache.next
    if [[ "${@}" =~ ^bundle ]]; then
    $@
    else
    bundle exec $@
    fi

    View full-size slide

  81. #!/bin/bash
    export BUNDLE_GEMFILE=Gemfile.next
    export BUNDLE_CACHE_PATH=vendor/cache.next
    if [[ "${@}" =~ ^bundle ]]; then
    $@
    else
    bundle exec $@
    fi

    View full-size slide

  82. #!/bin/bash
    export BUNDLE_GEMFILE=Gemfile.next
    export BUNDLE_CACHE_PATH=vendor/cache.next
    if [[ "${@}" =~ ^bundle ]]; then
    $@
    else
    bundle exec $@
    fi

    View full-size slide

  83. $ bundle install # install gems
    $ rails s # run rails
    $ rspec # run tests

    View full-size slide

  84. $ bin/next bundle install # install gems
    $ bin/next rails s # run rails
    $ bin/next rspec # run tests

    View full-size slide

  85. ) Keep the Gemfile healthy
    * Outlaw deprecations
    + Dual-boot Rails next

    View full-size slide

  86. Make it easy to do the right thing.

    View full-size slide

  87. # Try it out
    $ gem install ten_years_rails_conf_2018
    # Or, read the code
    $ open https://github.com/clio/ten_years_rails_conf_2018

    View full-size slide

  88. Tiny Co. / Big Inc.
    Problems
    Close the gaps
    Summary

    View full-size slide

  89. $
    Tiny Co.
    %
    Big Inc.
    1. Gems Few Many
    2. Code changes Few Many
    3. Test Few failures Won’t even run
    4. Deploy Easy Terrifying

    View full-size slide

  90. $
    Tiny Co.
    %
    Big Inc.
    1. Gems Few Many Few
    2. Code changes Few Many
    3. Test Few failures Won’t even run
    4. Deploy Easy Terrifying

    View full-size slide

  91. $
    Tiny Co.
    %
    Big Inc.
    1. Gems Few Many Few
    2. Code changes Few Many Few
    3. Test Few failures Won’t even run
    4. Deploy Easy Terrifying

    View full-size slide

  92. $
    Tiny Co.
    %
    Big Inc.
    1. Gems Few Many Few
    2. Code changes Few Many Few
    3. Test Few failures
    Won’t even run

    Few failures
    4. Deploy Easy Terrifying

    View full-size slide

  93. $
    Tiny Co.
    %
    Big Inc.
    1. Gems Few Many Few
    2. Code changes Few Many Few
    3. Test Few failures
    Won’t even run

    Few failures
    4. Deploy Easy Less terrifying*

    View full-size slide

  94. Blur the lines

    View full-size slide

  95. Prepare for Rails
    upgrade
    Make codebase
    better

    View full-size slide

  96. Removed 33 gems
    Updated 27 gems
    Reduced to zero deprecations
    Fixed 2,950 of 3,300 failing tests

    View full-size slide

  97. Created an upgrade process
    where everyone can contribute

    View full-size slide

  98. Hundreds of tiny changes.

    View full-size slide

  99. Hundreds of tiny changes.
    Don’t wait.

    View full-size slide

  100. Thanks
    Jordan Raine
    @jnraine

    View full-size slide