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

[RailsConf 2023 Opening Keynote] The Magic of Rails

[RailsConf 2023 Opening Keynote] The Magic of Rails

Today we're going to explore the magic of Rails. We'll look at the philosophy behind the framework as well as the overall structure of the components. We'll explore some of the common patterns that Rails uses to build agnostic and beautiful interfaces, and the techniques it implements to hide complexity so you can focus building your application. By the end of this talk you'll feel more confident navigating the Rails codebase and better understand the patterns it uses to create the framework we all know and love. But Rails is so much more than its design and architecture. We'll dive into my motivations for working on the framework and why the community is so important to the long term success of Rails.

Eileen M. Uchitelle

April 24, 2023
Tweet

More Decks by Eileen M. Uchitelle

Other Decks in Programming

Transcript

  1. The Magic of Rails
    exploring the principles & techniques
    behind the framework

    View full-size slide

  2. Hello RailsConf! I'm


    Eileen M. Uchitelle
    @eileencodes


    @[email protected]

    View full-size slide

  3. The Magic of Rails
    exploring the principles & techniques
    behind the framework

    View full-size slide

  4. What is


    Ruby on Rails?

    View full-size slide

  5. Rails is


    modular, but

    not fractured

    View full-size slide

  6. Rails is


    designed to
    have agnostic
    interfaces

    View full-size slide

  7. Rails is


    extracted from
    applications

    View full-size slide

  8. Rails is


    made of

    simple and
    aesthetic APIs

    View full-size slide

  9. Rails is


    a framework
    that takes on
    complexity to
    empower you

    View full-size slide

  10. How Rails components


    are structured

    View full-size slide

  11. RUBY ON RAILS
    Active Record
    Active Support
    Active Model
    Active Job
    Active Storage
    Action Mailer
    Action Pack Action View
    Action Cable
    Action Text
    Action Mailbox
    Railties

    View full-size slide

  12. Naming Convention


    Active vs Action

    View full-size slide

  13. Active Record


    Active Support


    Active Model


    Active Job


    Active Storage
    BACKEND
    NAMING CONVENTION

    View full-size slide

  14. USER FACING
    Active Record


    Active Support


    Active Model


    Active Job


    Active Storage
    BACKEND
    NAMING CONVENTION
    Action Mailer


    Action Pack


    Action View


    Action Cable


    Action Text


    Action Mailbox
    USER FACING

    View full-size slide

  15. Active Record


    Active Support


    Active Model


    Active Job


    Active Storage
    Action Mailer


    Action Pack


    Action View


    Action Cable


    Action Text


    Action Mailbox
    BACKEND USER FACING
    Railties
    GLUE
    NAMING CONVENTION

    View full-size slide

  16. Architeture & Patterns


    of Rails components

    View full-size slide

  17. Architecture & Patterns


    the role of Railties

    View full-size slide

  18. 👩💻
    Application

    View full-size slide

  19. 👩💻
    Application Register hooks

    View full-size slide

  20. 👩💻
    Application Register hooks Load components

    View full-size slide

  21. 👩💻
    Application Register hooks Load components Run hooks

    View full-size slide

  22. # railtie.rb


    initializer "initializer.name" do


    # do something at initialization


    end

    View full-size slide

  23. # railties/lib/rails/application.rb


    def initializer(name, opts = {}, &block)


    self.class.initializer(name, opts, &block)


    end

    View full-size slide

  24. # railtie.rb


    initializer "initializer.name" do |app|


    app.do_something


    app.config.do_something


    end

    View full-size slide

  25. # railtie.rb


    initializer "initializer.name" do


    ActiveSupport.on_load(:active_record) do


    # do something at initialization


    end


    end

    View full-size slide

  26. # activerecord/lib/active_record/railtie.rb


    initializer "active_record.initialize_database" do


    ActiveSupport.on_load(:active_record) do


    self.configurations =


    Rails.application.config.database_configuration




    establish_connection


    end


    end

    View full-size slide

  27. # activerecord/lib/active_record/railtie.rb


    initializer "active_record.initialize_database" do


    ActiveSupport.on_load(:active_record) do


    self.configurations =


    Rails.application.config.database_configuration




    establish_connection


    end


    end

    View full-size slide

  28. # activerecord/lib/active_record/railtie.rb


    initializer "active_record.initialize_database" do


    ActiveSupport.on_load(:active_record) do


    self.configurations =


    Rails.application.config.database_configuration




    establish_connection


    end


    end

    View full-size slide

  29. # activejob/lib/active_job/railtie.rb


    initializer "active_job.logger" do


    ActiveSupport.on_load(:active_job) {


    self.logger = ::Rails.logger


    }


    end

    View full-size slide

  30. # activejob/lib/active_job/railtie.rb


    initializer "active_model.deprecator",


    before: :load_environment_config do |app|




    app.deprecators[:active_model] =


    ActiveModel.deprecator


    end


    View full-size slide

  31. # activejob/lib/active_job/railtie.rb


    initializer "active_model.deprecator",


    before: :load_environment_config do |app|




    app.deprecators[:active_model] =


    ActiveModel.deprecator


    end


    View full-size slide

  32. • Railties are the core of
    the framework

    View full-size slide

  33. • Railties are the core of
    the framework


    • Railties control load
    order and when hooks
    should be run

    View full-size slide

  34. • Railties are the core of
    the framework


    • Railties control load
    order and when hooks
    should be run


    • Enables components to
    work together without
    adding dependencies

    View full-size slide

  35. Architecture & Patterns


    Agnostic interfaces

    View full-size slide

  36. if connection.is_a?(PostgresqlAdapter)


    # ...


    elsif connection.is_a?(Mysql2Adapter)


    # ...


    elsif connection.is_?(Sqlite3Adapter)


    # ...


    else


    # ...


    end

    View full-size slide

  37. if connection.is_a?(PostgresqlAdapter)


    # ...


    elsif connection.is_a?(Mysql2Adapter)


    # ...


    elsif connection.is_?(Sqlite3Adapter)


    # ...


    else


    # ...


    end

    View full-size slide

  38. module ActiveRecord


    module ConnectionAdapters


    class AbstractAdapter


    # define interface


    end


    end


    end


    View full-size slide

  39. module ActiveRecord


    module ConnectionAdapters


    class AbstractAdapter


    # define interface


    end


    end


    end


    module ActiveRecord


    module ConnectionAdapters


    class PostgresqlAdapter < AbstractAdapter


    # inherit or redefine interface


    end


    end


    end

    View full-size slide

  40. connection.supports_foreign_keys?


    => true


    View full-size slide

  41. class AbstractAdapter


    def supports_foreign_keys?


    false


    end


    end

    View full-size slide

  42. class AbstractAdapter


    def supports_foreign_keys?


    false


    end


    end


    class PostgresqlAdapter < AbstractAdapter


    def supports_foreign_keys?


    true


    end


    end


    View full-size slide

  43. # activestorage/lib/active_storage/service.rb


    module ActiveStorage


    class Service


    def delete(key)


    raise NotImplementedError


    end


    end


    end


    View full-size slide

  44. # activestorage/lib/active_storage/service/gcs_service.rb


    class ActiveStorage


    class Service::GCSService < Service


    def delete(key)


    instrument :delete, key: key do


    file_for(key).delete


    rescue Google::Cloud::NotFoundError


    # Ignore files already deleted


    end


    end


    end


    end

    View full-size slide

  45. @service.delete(key)


    View full-size slide

  46. • Consistent interface for
    all supported libraries

    View full-size slide

  47. • Consistent interface for
    all supported libraries


    • Simpli
    fi
    es Rails code to
    avoid using `is_a?`

    View full-size slide

  48. • Consistent interface for
    all supported libraries


    • Simpli
    fi
    es Rails code to
    avoid using `is_a?`


    • Makes it easy for apps to
    swap out adapters /
    services

    View full-size slide

  49. • Consistent interface for
    all supported libraries


    • Simpli
    fi
    es Rails code to
    avoid using `is_a?`


    • Makes it easy for apps to
    swap out adapters /
    services


    • Lowers the maintenance
    burden

    View full-size slide

  50. Migrating Shopify's
    Core Rails Monolith
    to Trilogy


    Adrianna Chang


    Monday, April 24 @ 3pm

    View full-size slide

  51. Architecture & Patterns


    Metaprogramming

    View full-size slide

  52. class Post < ApplicationRecord


    has_many :comments


    end


    class Comment < ApplicationRecord


    belongs_to :post


    end

    View full-size slide

  53. post = Post.first


    post.comments


    => [#,


    #]

    View full-size slide

  54. post = Post.first


    post.method(:comments).source_location

    View full-size slide

  55. post = Post.first


    post.method(:comments).source_location


    => ["rails/activerecord/lib/


    active_record/associations/builder/


    association.rb", 103]


    View full-size slide

  56. # activerecord/lib/active_record/associations/builder/
    association.rb


    class ActiveRecord::Associations::Builder


    class Association


    def self.define_readers(mixin, name)


    mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1


    def #{name}


    association(:#{name}).reader


    end


    CODE


    end


    end


    end


    View full-size slide

  57. # activerecord/lib/active_record/associations/builder/
    association.rb


    class ActiveRecord::Associations::Builder


    class Association


    def self.define_readers(mixin, name)


    mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1


    def #{name}


    association(:#{name}).reader


    end


    CODE


    end


    end


    end


    View full-size slide

  58. # activerecord/lib/active_record/associations/builder/
    association.rb


    class ActiveRecord::Associations::Builder


    class Association


    def self.define_readers(mixin, name)


    mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1


    def #{name}


    association(:#{name}).reader


    end


    CODE


    end


    end


    end


    View full-size slide

  59. Post::GeneratedAssociationMethods

    View full-size slide

  60. # activerecord/lib/active_record/associations/builder/
    association.rb


    class ActiveRecord::Associations::Builder


    class Association


    def self.define_readers(mixin, name)


    mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1


    def #{name}


    association(:#{name}).reader


    end


    CODE


    end


    end


    end


    View full-size slide

  61. # activerecord/lib/active_record/associations/builder/
    association.rb


    class ActiveRecord::Associations::Builder


    class Association


    def self.define_writers(mixin, name)


    mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1


    def #{name}=(value)


    association(:#{name}).writer(value)


    end


    CODE


    end


    end


    end


    View full-size slide

  62. # activerecord/lib/active_record/associations/builder/
    association.rb


    class ActiveRecord::Associations::Builder


    class Association


    def self.define_writers(mixin, name)


    mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1


    def #{name}=(value)


    association(:#{name}).writer(value)


    end


    CODE


    end


    end


    end


    View full-size slide

  63. • Powerful tool that
    enables us to build
    beautiful, simple APIs

    View full-size slide

  64. • Powerful tool that
    enables us to build
    beautiful, simple APIs


    • Hides complexity from
    your application

    View full-size slide

  65. • Powerful tool that
    enables us to build
    beautiful, simple APIs


    • Hides complexity from
    your application


    • Where "Rails Magic"
    comes from

    View full-size slide

  66. Maintaining Rails


    Why I work on it

    View full-size slide

  67. 2010


    Introduced


    to Rails

    View full-size slide

  68. 2010


    Introduced


    to Rails
    2011


    Big Nerd Ranch

    View full-size slide

  69. 2010


    Introduced


    to Rails
    2011


    Big Nerd Ranch
    2014


    1st conference


    1st contribution

    View full-size slide

  70. 2010


    Introduced


    to Rails
    2011


    Big Nerd Ranch
    2014


    1st conference


    1st contribution
    2015


    First RailsConf

    View full-size slide

  71. 2010


    Introduced


    to Rails
    2011


    Big Nerd Ranch
    2014


    1st conference


    1st contribution
    2015


    First RailsConf
    2017


    Join Rails Core

    View full-size slide

  72. 2010


    Introduced


    to Rails
    2011


    Big Nerd Ranch
    2014


    1st conference


    1st contribution
    2015


    First RailsConf
    2017


    Join Rails Core
    2023


    This RailsConf

    View full-size slide

  73. I work on Rails to


    advance the


    framework

    View full-size slide

  74. I work on Rails to


    ensure applications


    can stay on Rails

    View full-size slide

  75. I work on Rails to


    build a stronger


    community

    View full-size slide

  76. I work on Rails to


    have an impact


    on the future

    View full-size slide

  77. Rails is so much more


    than just a framework

    View full-size slide

  78. Rails is


    inspiring

    View full-size slide

  79. Rails is


    empowering

    View full-size slide

  80. Rails is


    imperfect

    View full-size slide

  81. Rails is


    the applications we build

    View full-size slide

  82. Rails is


    the team behind it

    View full-size slide

  83. Rails is


    the community

    View full-size slide

  84. Rails is magic

    View full-size slide