< Return to Video

RailsConf 2014 - Ruby on Rails Hacking Guide by Akira Matsuda

  • 0:19 - 0:24
    AKIRA MATSUDA: So. Welcome to Ruby on Rails
    internal talk.
  • 0:24 - 0:27
    This is titled Ruby on Rails Hacking Guide,
  • 0:27 - 0:31
    which is deeply inspired by Minero Alki's
    Legendary Ruby
  • 0:31 - 0:35
    book titles Rails- for, Ruby Hacking Guide.
  • 0:35 - 0:39
    So, before I get started, let me just introduce
  • 0:39 - 0:44
    myself. I am Akira Matsuda - amatsuda on GitHub
  • 0:44 - 0:47
    and Twitter. I'm a committer of Ruby and Ruby
  • 0:47 - 0:52
    on Rails projects and I'm from Japan.
  • 0:52 - 0:56
    As a individual on GitHub, I created a pagination
  • 0:56 - 1:01
    library called kaminari and active_decoractor,
    action_args and et cetera,
  • 1:01 - 1:05
    et cetera. Such libraries.
  • 1:05 - 1:08
    As a Rails committer, ranked in here, in the
  • 1:08 - 1:15
    bottom, like, twenty-seventh. I've done 374
    commits so far
  • 1:15 - 1:20
    and, since I made my first commit about six
  • 1:20 - 1:21
    years ago.
  • 1:21 - 1:24
    I initially titled this talk as Ruby on Rails
  • 1:24 - 1:29
    Hacking Guide, but I slightly changed my mind
    after
  • 1:29 - 1:34
    I listened to DHH's keynote. This talk should
    be
  • 1:34 - 1:39
    titled like Ruby on Rails Reading Guide. Since
    we're
  • 1:39 - 1:42
    actually gonna spend the whole forty minutes
    just for
  • 1:42 - 1:46
    reading the whole framework code.
  • 1:46 - 1:50
    And, not gonna talk anything about, like,
    science. But
  • 1:50 - 1:57
    it's like, reading a novel, reading a story.
    So,
  • 1:57 - 1:59
    why should we, why should we read Rails? I
  • 1:59 - 2:04
    think we have three big reasons here.
  • 2:04 - 2:11
    Firstly, as DHH defined, we're software writers,
    and you
  • 2:12 - 2:14
    need to read a lot in order to be
  • 2:14 - 2:18
    a good writer, right. This is obvious. So,
    we
  • 2:18 - 2:21
    need to read Rails to be a good Rails
  • 2:21 - 2:27
    programmer. And if you don't understand any
    piece of
  • 2:27 - 2:31
    code in your application, that means you don't
    really
  • 2:31 - 2:34
    understand your application.
  • 2:34 - 2:39
    So, don't let a magical piece of code exist
  • 2:39 - 2:43
    in your app. I know that Rails applications
    are
  • 2:43 - 2:50
    filled with such magics like, for example,
    like this.
  • 2:51 - 2:56
    It's such simple, just one line of Ruby code,
  • 2:56 - 2:59
    in just one method. But it, it really does
  • 2:59 - 3:03
    a lot of things for you, right. But we
  • 3:03 - 3:06
    need to be able to explain why, why is
  • 3:06 - 3:13
    this controller inheriting from ApplicationController
    inheriting from ActionController::Base? We.
  • 3:13 - 3:18
    Or, how the http request actually calls this
    in
  • 3:18 - 3:23
    index Ruby method. Or why are we setting this
  • 3:23 - 3:28
    u- users relation into a controller instance
    variable. Et
  • 3:28 - 3:31
    cetera, et cetera.
  • 3:31 - 3:36
    Or, think about this example. This, this,
    this is
  • 3:36 - 3:42
    a typical Rails-ish DSL. This reads good.
    It's pretty
  • 3:42 - 3:47
    straight forward for readers, as a documentation.
    But, you're
  • 3:47 - 3:51
    not an application reader, right. We, we're
    application writer.
  • 3:51 - 3:55
    So you have to write this. And as a
  • 3:55 - 3:58
    writer, you don't, don't usually write when
    you don't
  • 3:58 - 4:02
    understand what it means, right.
  • 4:02 - 4:07
    So, so a question. What, what, what is this
  • 4:07 - 4:14
    Rails.application.routes.draw, or get in the
    second line. Looks like
  • 4:15 - 4:21
    a method call taking a hash parameter. What
    is
  • 4:21 - 4:26
    it doing? Who actually knows, who here actually
    knows
  • 4:26 - 4:30
    what's gonna happen with this code? Can explain?
  • 4:30 - 4:37
    Right. So, if you think, if you think you
  • 4:42 - 4:46
    can explain how this define a route, if, if
  • 4:46 - 4:50
    you cannot explain. Sorry. If you cannot explain
    that
  • 4:50 - 4:54
    means for, it's just a magic. And that's why
  • 4:54 - 4:59
    you're, you're in this room now, right. So,
    you'll
  • 4:59 - 5:03
    soon get to know what the get means.
  • 5:03 - 5:08
    And as the third reason to read Rails code
  • 5:08 - 5:15
    is because Rails.has_many :bugs. So, as I
    told you,
  • 5:17 - 5:19
    I patched a lot. And mostly I, I patch
  • 5:19 - 5:23
    Rails because I hit bugs in my production
    application.
  • 5:23 - 5:29
    And I guess, you all have the same experience.
  • 5:29 - 5:34
    I'm sure. Rails is basically buggy. And we
    need
  • 5:34 - 5:37
    to deal with them. With the bugs.
  • 5:37 - 5:41
    So, naturally, Rails programmer job is not
    just to
  • 5:41 - 5:45
    maintain the application, but you also need
    to maintain
  • 5:45 - 5:49
    Rails framework as well. It's our job. And
    it's
  • 5:49 - 5:51
    your job. So we need to be familiar with
  • 5:51 - 5:55
    the code base.
  • 5:55 - 6:00
    And strangely, this talk is kind of categorized
    as
  • 6:00 - 6:07
    a novice talk. But, I'm not sure. I'm, I'm
  • 6:07 - 6:14
    gonna talk about the Rails internal. So. I
    hope
  • 6:14 - 6:16
    you enjoy.
  • 6:16 - 6:23
    Let's begin. This is what I'm gonna talk.
    So,
  • 6:26 - 6:29
    first of all, Ruby on Rails is a open-source
  • 6:29 - 6:36
    software on GitHub. There's no C-extension
    inside. So. I
  • 6:37 - 6:42
    mean, there's, there's no C-code. 100% Ruby.
    That means,
  • 6:42 - 6:45
    if you're a Ruby programmer, you just can
    read
  • 6:45 - 6:52
    it and, and you can write it if necessary.
  • 6:52 - 6:55
    You can get its source code here, by git
  • 6:55 - 7:02
    cloning from GitHub. By the way, here's a
    tiny
  • 7:02 - 7:09
    tip. How you can find the GitHub repository
    for
  • 7:10 - 7:15
    the gem you use. You can use, you can
  • 7:15 - 7:20
    use a gem named gem-src. It's on, it's here
  • 7:20 - 7:25
    on GitHub. And please take a look at this
  • 7:25 - 7:28
    repository. This is how you can install it
    and
  • 7:28 - 7:30
    how you can use it.
  • 7:30 - 7:35
    I'm not gonna explain here. But. So, what
    this
  • 7:35 - 7:41
    does is after this gem installed, it will
    automatically
  • 7:41 - 7:46
    git, git clone this source from GitHub repository.
    So,
  • 7:46 - 7:50
    you, you need not to memorize the author's
    name
  • 7:50 - 7:52
    or you can not, you don't need to search
  • 7:52 - 7:59
    on GitHub. As a gem install, it automatically
    gets
  • 7:59 - 8:02
    the code from GitHub. It's so useful for social
  • 8:02 - 8:07
    coders.
  • 8:07 - 8:14
    Anyway. Let's go back to the Rails source.
    Firstly,
  • 8:18 - 8:21
    let's see what's included in the gem. To know
  • 8:21 - 8:24
    what's included in gem, take a look at the
  • 8:24 - 8:31
    gemspec. So this is taken from the file rails.gemspec.
  • 8:32 - 8:37
    Here it defines the files included. It looks
    like
  • 8:37 - 8:43
    it doesn't really include any program. It's
    just documents,
  • 8:43 - 8:45
    right.
  • 8:45 - 8:49
    And you can find these declarations. A bunch
    of
  • 8:49 - 8:56
    add_dependencies. So that means Rails has
    no code inside,
  • 8:58 - 9:04
    but instead if defines several dependencies.
    It means that
  • 9:04 - 9:07
    this is a meta, meta-gem, meta-package, to
    install these
  • 9:07 - 9:12
    seven gems, right.
  • 9:12 - 9:19
    And these seven gems are in the Rails repository.
  • 9:21 - 9:26
    And Rails is a full-stack framework, a full-stack
    MVC
  • 9:26 - 9:28
    framework. And all these M and V and C
  • 9:28 - 9:35
    are included in this one repository. So we
    have
  • 9:35 - 9:39
    model, view, and controller.
  • 9:39 - 9:42
    And we have these gems. I'm sorry it's, can
  • 9:42 - 9:45
    you read it? I'm sorry it's hard to read.
  • 9:45 - 9:52
    Anyway. We have ActiveRecord, ActionPack and
    ActionView. And this
  • 9:52 - 9:59
    is something called model, and these are views,
    and
  • 9:59 - 10:03
    these are controllers.
  • 10:03 - 10:07
    So, Rails gem is a meta-package that depends
    on
  • 10:07 - 10:14
    these seven gems.
  • 10:14 - 10:17
    So let's take a look at the Rails server
  • 10:17 - 10:23
    command and, and let me explain how, how the
  • 10:23 - 10:27
    Rails actually boots. For, starting up the
    Rails server,
  • 10:27 - 10:31
    you just need to run Rails server command.
    So,
  • 10:31 - 10:35
    what's happening internally when you execute
    this command?
  • 10:35 - 10:39
    When I hit the Rails command it actually executes
  • 10:39 - 10:44
    bin slash rails in your application. So, let's
    read
  • 10:44 - 10:49
    that file first. That file should look like
    this.
  • 10:49 - 10:53
    It requires config/boot inside your application
    first, and then
  • 10:53 - 10:55
    requires rails/commands.
  • 10:55 - 11:01
    Rails/boot looks like this. It just bundles
    something. I'm
  • 11:01 - 11:04
    gonna skip the bundler part, because it's,
    it's out
  • 11:04 - 11:09
    of today's scope, but it, it, it kind of
  • 11:09 - 11:12
    tweaks the $LOAD_PATH nicely.
  • 11:12 - 11:19
    And so the second line. Rails/commands. It
    requires rails/commands.
  • 11:25 - 11:29
    So where is "rails" directory? You can find
    "rails"
  • 11:29 - 11:35
    directory in the railties gem. There's a gem
    called
  • 11:35 - 11:40
    railties, which I, I didn't explain. So, next
    chapter
  • 11:40 - 11:42
    is about railties.
  • 11:42 - 11:49
    What, what actually railties is? Railties
    is a very
  • 11:50 - 11:57
    wisely-crafted tiny library, initially created
    by Yehuda Katz and
  • 11:57 - 12:02
    Carl, Carl Lerche. So let's dive into it.
  • 12:02 - 12:09
    Here's the gemspec. The gemspec says this
    is about
  • 12:11 - 12:17
    Rails internals. And the gemspec shows that
    now this
  • 12:17 - 12:24
    gem includes some libraries. Ruby files. Actually,
    it includes
  • 12:26 - 12:31
    like this. So, when you step inside the railties
  • 12:31 - 12:36
    lib directory, you'll see these. One directory
    and one
  • 12:36 - 12:42
    file called rails dot rb.
  • 12:42 - 12:47
    So these's the rails directory. And this is
    how
  • 12:47 - 12:52
    Rails/commands dot rb looks like in the railties
    gem.
  • 12:52 - 12:59
    It requires commands_tasks, and then invokes
    a CommandTask with
  • 12:59 - 13:06
    a given command name. ARGV, right.
  • 13:08 - 13:15
    In this case, so, in this case server, right.
  • 13:15 - 13:18
    So this is the file named commands_tasks dot
    rb.
  • 13:18 - 13:22
    It requires rails/commands/server first. So
    let's take a look
  • 13:22 - 13:29
    at rails/commands/server. And this is rails/commands/server.
    It requires, at
  • 13:32 - 13:39
    very top, it requires rails. So, then jump
    to
  • 13:40 - 13:44
    rails dot rb. Rails dot rb was at the
  • 13:44 - 13:48
    very top of the repository, right.
  • 13:48 - 13:52
    So this is how rails dot rb looks like.
  • 13:52 - 13:57
    It requires rails/application. So, let's go
    to rails/application. And
  • 13:57 - 14:02
    it defines a top-level module named Rails.
  • 14:02 - 14:09
    So rails/application, it requires rails/engine,
    and it defines a
  • 14:09 - 14:14
    Rails Application class, inheriting Rails
    Engine.
  • 14:14 - 14:21
    So, jump to rails/engine. Now, rails/engine
    requires rails/railtie and
  • 14:23 - 14:28
    it, Rails Engine class inherits from Rails
    Railtie. So,
  • 14:28 - 14:31
    next file is rails/railtie.
  • 14:31 - 14:38
    Railtie, it looks like this. It requires rails/initializable
    and
  • 14:38 - 14:42
    rails/configuration. And defines Rails Railtie
    class, that includes Rails
  • 14:42 - 14:49
    Initializable. So next follow the, next file
    is rails/initializable.
  • 14:49 - 14:56
    It defines a Rails Initizable- Initializer.
  • 14:59 - 15:05
    So, what we learned so far is, railties defines
  • 15:05 - 15:12
    these core classes, like Application, Engine,
    Railtie, Initializable. Which
  • 15:17 - 15:24
    are very, very important. Actually, the core
    of Rails.
  • 15:24 - 15:29
    So railties is like this. It's the core of
  • 15:29 - 15:32
    Rails, in the middle.
  • 15:32 - 15:35
    And we had something called Plugin as well,
    but
  • 15:35 - 15:39
    it was gone since Rails 4.
  • 15:39 - 15:46
    So, let's skip it. So railties is a library
  • 15:49 - 15:56
    providing something underneath the Rails Application.
    And I have
  • 15:57 - 16:04
    another answer for you. Railties is, according
    to Wikipedia,
  • 16:08 - 16:13
    this is the definition of something called
    Railroad tie.
  • 16:13 - 16:20
    It's a rectangular piece of wood which is
    laid
  • 16:22 - 16:29
    underneath the rails, sometimes called sleeper,
    railway sleeper.
  • 16:29 - 16:36
    So this is rail ties. Consider this. The applications
  • 16:36 - 16:42
    are the trains that run on Rails, and railties,
  • 16:42 - 16:46
    Rails is the framework, and railties is something
    lies
  • 16:46 - 16:51
    underneath the Rails framework. This is why
    they named
  • 16:51 - 16:55
    it railties, I guess. This is a beautiful
    metaphor,
  • 16:55 - 16:58
    isn't it?
  • 16:58 - 17:02
    So how does it work? Or, how can we
  • 17:02 - 17:06
    use it? This is how, how, how it's work.
  • 17:06 - 17:10
    We can git grep the whole railtie repository,
    and
  • 17:10 - 17:16
    you can find some uses of railtie. These are
  • 17:16 - 17:21
    in, not only in railties, they're actually,
    these are
  • 17:21 - 17:25
    in mailers, ActiveRecord, ActionPack, blah,
    blah, blah.
  • 17:25 - 17:30
    We're gonna take it. So, so let's take a,
  • 17:30 - 17:35
    take a look at it, like this. So, each
  • 17:35 - 17:39
    component has its own railtie, inheriting
    from Rails::Railtie, like
  • 17:39 - 17:43
    this. This is how we use railtie.
  • 17:43 - 17:49
    So, railtie is not only in the core, but
  • 17:49 - 17:56
    in, we can find railties everywhere. Railtie.
    It's inside
  • 17:56 - 18:01
    each component, right. And, so, this is what's
    written
  • 18:01 - 18:04
    inside the railtie class.
  • 18:04 - 18:06
    It has some, mainly we, we see two kinds
  • 18:06 - 18:13
    of class method calls, config and initializer,
    right. These
  • 18:14 - 18:21
    are class method calls to railtie class. So,
    what's
  • 18:23 - 18:24
    config?
  • 18:24 - 18:31
    This is the definition. Railtie config create
    something. Instantiates
  • 18:32 - 18:39
    something like Railtie::Configuration. And
    so config is a instance
  • 18:42 - 18:47
    of Railtie::Configuration. Railtie::Configuration
    is something like this. It, it
  • 18:47 - 18:52
    has one method_missing method. And it accepts
    any method
  • 18:52 - 18:56
    call and just stores the given name and arguments
  • 18:56 - 19:03
    and block into a class-level hash.
  • 19:03 - 19:10
    So, what is initializer? Initializer looks
    like this. The,
  • 19:11 - 19:16
    it just keeps the given block as a proc
  • 19:16 - 19:23
    instance, with a name, with a given name,
    right.
  • 19:26 - 19:33
    So, this is everything. This is what railties
    is
  • 19:33 - 19:38
    doing. It, it sets something, some values
    via config
  • 19:38 - 19:43
    method call and initializer method call. And
    to, to
  • 19:43 - 19:50
    use them for the later use.
  • 19:51 - 19:54
    And railties is actually class, but it's prohibited
    to
  • 19:54 - 20:00
    instantiate. So, you cannot make a instance
    of the
  • 20:00 - 20:07
    railtie class. Instead, you just can inherit
    and, when
  • 20:08 - 20:14
    inherited, it, it kind of memorizes the, the
    children
  • 20:14 - 20:18
    class names.
  • 20:18 - 20:25
    So, this is a summary what, of what railties
  • 20:25 - 20:28
    is doing. Railties is a core of Rails that
  • 20:28 - 20:31
    provides Railtie, Engine, Application, et
    cetera, and we can
  • 20:31 - 20:35
    find Railtie in other Rails components like
    ActiveRecord, ActionPack.
  • 20:35 - 20:39
    And a railtie can keep config and initializer
    values.
  • 20:39 - 20:43
    And Railtie ties up these railties, all right.
  • 20:43 - 20:47
    So, let's see how, how actually Rails server
    ties
  • 20:47 - 20:54
    these up. And how, how Rails server boots.
    So,
  • 20:54 - 20:58
    let's go back to rails/commands/commands_tasks
    dot rb. After it
  • 20:58 - 21:04
    requiring rails/commands/server, it executes,
    it requires the application and
  • 21:04 - 21:07
    then executes server dot start.
  • 21:07 - 21:14
    Server dot start is defined here, because
    it was
  • 21:16 - 21:23
    defined in Rails/commands/server. Server dot
    start calls, just calls
  • 21:24 - 21:28
    super. And super is, super class of this class
  • 21:28 - 21:31
    is Rack::Server.
  • 21:31 - 21:37
    So, welcome to the Rack world. Now, now we
  • 21:37 - 21:44
    need to read the Rack code. Oh my god.
  • 21:48 - 21:52
    This is not Rack hacking guide, so I'm just
  • 21:52 - 21:59
    gonna skip it. It. Anyway. Finally calls something
    like
  • 22:04 - 22:11
    this, via rack/builder. It evaluates this
    Ruby string. Like,
  • 22:17 - 22:23
    Rack::Builder dot new taking contents of config
    dot ru
  • 22:23 - 22:27
    in your application.
  • 22:27 - 22:34
    And Rack::Builder just instance_evals the
    given block. So, this
  • 22:35 - 22:42
    is what's written inside your application's
    config dot ru.
  • 22:44 - 22:51
    It requires config/environment dot rb first,
    and runs Rails.application.
  • 22:52 - 22:55
    Run is also a Rack command, I mean, Rack
  • 22:55 - 22:58
    method.
  • 22:58 - 23:05
    So, I just, I just, like, explained very fast,
  • 23:08 - 23:12
    like, how the method, method call goes. How
    method
  • 23:12 - 23:15
    call graph looks like. So, I guess you find
  • 23:15 - 23:20
    it difficult to follow, and how can it actually
  • 23:20 - 23:24
    follow these method, method call graphs?
  • 23:24 - 23:31
    Here's one tip. Just, puts caller from, in
    a
  • 23:31 - 23:35
    file inside your application. For, example,
    in config dot
  • 23:35 - 23:40
    ru file, like this. Just add a puts caller
  • 23:40 - 23:44
    here. And run Rails server. Then, you'll get
    an
  • 23:44 - 23:51
    output like this in your console.
  • 23:51 - 23:56
    And these, these are basically what I explained.
    Like,
  • 23:56 - 24:03
    we see commands/task and server and, like,
    Rack::Builder.
  • 24:06 - 24:12
    So, this is very useful. Like, when you get
  • 24:12 - 24:18
    lost in the Ruby, Ruby jungle, use puts caller
  • 24:18 - 24:23
    in caller locations, and that'll show you
    the path
  • 24:23 - 24:26
    to the place you are.
  • 24:26 - 24:33
    All right. Anybody, but. The config dot ru
    file
  • 24:34 - 24:39
    requires config/environment.rb, and this is,
    as you know, what's
  • 24:39 - 24:45
    written inside the config/environment.rb.
    It requires config/application dot rb
  • 24:45 - 24:48
    and calls Rails.application.initialize!
  • 24:48 - 24:55
    So, Rails.application.initialize! is the very,
    very important method. As
  • 24:58 - 25:02
    you may notice from, because it, it has an
  • 25:02 - 25:09
    exclamation mark. This is what's written in
    application.rb. Since,
  • 25:09 - 25:14
    Rails 4 point 1, it, it really has nothing
  • 25:14 - 25:17
    in its, in its class.
  • 25:17 - 25:24
    But, but it defines a class called Application,
    inheriting
  • 25:24 - 25:31
    from Rails::Application.
  • 25:33 - 25:39
    Before that, it requires rails/all and bundles
    all the
  • 25:39 - 25:45
    bundled gems. So this is rails dot, rails/all
    dot
  • 25:45 - 25:52
    rb. What it actually does is something like
    this.
  • 25:52 - 25:58
    It defines, so, it requires all these railties
    that
  • 25:58 - 26:05
    I showed you before. Railties defines configs
    and initializers,
  • 26:06 - 26:11
    as we have seen already.
  • 26:11 - 26:18
    And then, we call Rails.application.initialize
    exclamation. So, so we,
  • 26:22 - 26:28
    we define initializers here and load all initializers
    and
  • 26:28 - 26:33
    then initialize exclamation, right.
  • 26:33 - 26:40
    So, this is the initialize method. It run_initializers,
    and
  • 26:42 - 26:49
    run_initializers, it calls run, run method
    for, for each
  • 26:53 - 27:00
    initialize- initializable object in the initializers
    collection.
  • 27:00 - 27:06
    So initializable looks like this. Run just
    executes the
  • 27:06 - 27:13
    given argument. I mean, instance_exec through
    stored proc inside
  • 27:14 - 27:21
    the same context, right. I mean, in this case,
  • 27:23 - 27:27
    at sign context is actually the application
    instance, so
  • 27:27 - 27:34
    it just instance_execs the stored procs in
    the initializers.
  • 27:34 - 27:38
    In the application's context.
  • 27:38 - 27:45
    So, I said initializers collection. Initializers
    collection is this.
  • 27:53 - 28:00
    And initializers, so, initializers, yeah.
    In rai- railties initializers
  • 28:02 - 28:08
    was created like this. So, what, what's in
    the
  • 28:08 - 28:14
    initializer's collection is instances of Rails
    initializer, initializable initializer.
  • 28:14 - 28:20
    Which, each initializer just, just holds a
    proc instance,
  • 28:20 - 28:24
    right.
  • 28:24 - 28:27
    And as we've seen already these are called
    from
  • 28:27 - 28:33
    each Railtie classes.
  • 28:33 - 28:40
    So. This is, this is what initialize do. And,
  • 28:41 - 28:46
    so let's go back to the server. As we've
  • 28:46 - 28:53
    seen, the start method calls super. I'm sorry.
    I'll
  • 28:53 - 28:54
    skip this.
  • 28:54 - 29:01
    So. Summary. So, this is what we, what the
  • 29:03 - 29:08
    railtie does for booting up the Rails server.
    Finally,
  • 29:08 - 29:14
    it runs Rails::Application in config dot ru.
    Do you
  • 29:14 - 29:18
    remember? It's written in config dot ru file.
    Run.
  • 29:18 - 29:20
    Run the application.
  • 29:20 - 29:27
    So what is run? What is run method? It's
  • 29:27 - 29:31
    defined like this. And with this, with this
    definition,
  • 29:31 - 29:38
    the Rack server calls Rails.application dot
    call. Rails.application responds
  • 29:41 - 29:45
    to call. So you can call this. That means
  • 29:45 - 29:48
    Rails.application is a Rack application.
  • 29:48 - 29:54
    And Rails.application as a Rack application,
    it, it has
  • 29:54 - 29:59
    a call method like this. It calls super. The
  • 29:59 - 30:06
    super, the Rails.application super class was
    Rails::Engine. So, so
  • 30:07 - 30:09
    jump to Rails::Engine.
  • 30:09 - 30:16
    Rails::Engine has this like call method. OK.
    The call
  • 30:16 - 30:23
    goes to app dot call. App is something like
  • 30:23 - 30:28
    this. It's a config middleware that contains
    default middleware
  • 30:28 - 30:35
    stack, and the endpoint, something called
    endpoint. Look at
  • 30:36 - 30:38
    this.
  • 30:38 - 30:44
    So, what's the end point? End point is a
  • 30:44 - 30:51
    route. Route is a ActionDispatch::Routing::RouteSet
    by default. OK.
  • 30:56 - 31:03
    So. So, the next thing is routes. Route is
  • 31:07 - 31:14
    usually defined in config/routes dot rb like
    this. So,
  • 31:14 - 31:21
    let's think of this simple route. Routes,
    Rails.application.routes is,
  • 31:21 - 31:28
    is ActionDispatch::Routing::RouteSet. It's
    defined here in ActionDispatch gem, I'm
  • 31:29 - 31:34
    sorry. ActionPack gem in action_dispatch directory.
  • 31:34 - 31:38
    It, it also responds to call, as it's a
  • 31:38 - 31:45
    Rack application. And call goes to router
    dot call.
  • 31:47 - 31:54
    Router is defined like this. Journey::Router.new.
    So, so router
  • 31:55 - 31:57
    is a Journey thing.
  • 31:57 - 32:04
    Then, so Rails.application routes is also
    a Rack application
  • 32:14 - 32:18
    that defines endpoint, and it finally goes
    to the
  • 32:18 - 32:21
    Journey thing. But for now let's go back to
  • 32:21 - 32:26
    the Routes.draw DSL.
  • 32:26 - 32:28
    Here.
  • 32:28 - 32:35
    So, routes.draw is defined like this. It just
    evaluates
  • 32:37 - 32:44
    the given block. In the ActionDispatch routing
    mapper. So,
  • 32:48 - 32:55
    this DSL actually calls ActionDispatch::Routing::Mapper#get
    method, right. And get
  • 32:55 - 32:59
    method is like this. It calls map_method.
    map_method calls
  • 32:59 - 33:06
    match. match calls decomposed_match, and decomposed_match
    calls add_route.
  • 33:06 - 33:13
    So, anyway. It finally goes to Mapper#add_route.
    And Mapper
  • 33:14 - 33:21
    add_route calls Mapping dot new route. And
    add_route returns
  • 33:24 - 33:31
    a, finally, it returns a Journey route. And
    then,
  • 33:32 - 33:38
    like, adds the given, sorry, the traded route
    into
  • 33:38 - 33:43
    the collection. Journey::Routes collection.
  • 33:43 - 33:50
    So. So, this is what the Journey does. And,
  • 33:51 - 33:58
    what's this? Yeah. It finally calls Mapper
    to_route, Mapping#to_route,
  • 33:59 - 34:02
    so to_route is defined like this.
  • 34:02 - 34:09
    I'm just gonna skip this. It's, it just returns
  • 34:11 - 34:16
    the given app parameter, which was the endpoint
    given
  • 34:16 - 34:21
    into the methods parameter. So it finally,
    finally it,
  • 34:21 - 34:28
    it returns endpoint. And endpoint is if, if
    it
  • 34:28 - 34:33
    responds_to call, just returns that. And if
    not, call
  • 34:33 - 34:34
    Dispatcher.
  • 34:34 - 34:42
    So. So the, the. The hash value can, could
  • 34:45 - 34:50
    be respond_to call, for example, like this.
    Or mounted
  • 34:50 - 34:54
    engine, for example. But usually it doesn't
    respond to
  • 34:54 - 35:01
    call, so it calls dispatcher. Dispatcher is
    a Routing::RouteSet::Dispatcher.
  • 35:05 - 35:08
    And Dispatcher is also a Rack app, so it
  • 35:08 - 35:12
    can be called. And the call the Dispatcher
    goes
  • 35:12 - 35:17
    to, dispatch method.
  • 35:17 - 35:24
    Dispatch, so, it finally goes at the bottom
    line.
  • 35:25 - 35:28
    It finally goes to controller dot action with
    a
  • 35:28 - 35:35
    given action name, dot call. So, so finally,
    what,
  • 35:37 - 35:43
    what the router finally calls is this. FooController
    dot
  • 35:43 - 35:50
    action method with a given action, action
    name. And
  • 35:50 - 35:53
    it returns something callable.
  • 35:53 - 35:59
    So, this is the route DSL. get "/hello" =>
  • 35:59 - 36:06
    "foo#bar" maps to FooController dot action('bar').
  • 36:11 - 36:15
    This is about Journey. And I think I have
  • 36:15 - 36:17
    no time, so I'm gonna skip this. I'm gonna
  • 36:17 - 36:22
    skip this long Journey. Anyway, it resolves
    the route.
  • 36:22 - 36:27
    So, this is a summary. The, the main point
  • 36:27 - 36:30
    is that 'foo#bar' becomes a Rack application
    generated by
  • 36:30 - 36:34
    FooController dot action('bar').
  • 36:34 - 36:40
    So, the final chapter. Controllers and actions.
    This, what's
  • 36:40 - 36:43
    gonna happen when the server got a request?
    It,
  • 36:43 - 36:50
    it, it just calls this. So what is this?
  • 36:50 - 36:58
    Firstly, the action method is defined like
    this. It's,
  • 37:01 - 37:06
    it calls the new dot dispatch inside the block.
  • 37:06 - 37:09
    New, new means Controller dot new.
  • 37:09 - 37:16
    So, dispatch, dispatch method creates set,
    call set_response! and
  • 37:16 - 37:20
    then calls super. So, what this dispatch method
    does
  • 37:20 - 37:27
    is creates Rails response object. And then
    dispatch method,
  • 37:30 - 37:34
    then creates request object. Whoops.
  • 37:34 - 37:40
    All right. It sets the request object into
    the
  • 37:40 - 37:47
    instance. And then calls process method. Dispatch
    finally calls
  • 37:48 - 37:54
    ActionController::Metal#process. So, this
    is what's written inside the process
  • 37:54 - 37:59
    method. process method calls process_action,
    and process_action calls send_action,
  • 37:59 - 38:06
    and send_action is aliased to send. Ruby's
    send method,
  • 38:07 - 38:09
    right.
  • 38:09 - 38:16
    So, FooController dot action('bar') creates
    the Rails Request and
  • 38:17 - 38:22
    Response objects into the controller instance.
    Then, it just
  • 38:22 - 38:25
    calls, calls the method name bar via Ruby
    send
  • 38:25 - 38:29
    method, OK.
  • 38:29 - 38:34
    So, it can be like, FooController dot new,
    with
  • 38:34 - 38:38
    something, dot bar. It's a very simple Ruby
    method
  • 38:38 - 38:43
    call, finally. So, this is what's happening
    inside the
  • 38:43 - 38:50
    HTTP request. When the Rails server accepts
    the HTTP
  • 38:52 - 38:57
    request, it, it kind of, the Journey kind
    of,
  • 38:57 - 39:02
    somehow, resolves the results, and finally
    calls this simple
  • 39:02 - 39:06
    Ruby method. OK?
  • 39:06 - 39:11
    And I guess it's, yeah. I guess it's time.
  • 39:11 - 39:18
    I have thirty, thirty seconds left. So.
  • 39:19 - 39:24
    Obviously there's more and more and more topics
    about
  • 39:24 - 39:29
    Rails internals, but unfortunately I had,
    I just had
  • 39:29 - 39:32
    forty minutes. Forty minutes was not enough
    to talk
  • 39:32 - 39:38
    about, like, ActiveRecord internals or helpers
    or ActionPack, ActionController
  • 39:38 - 39:41
    - these things.
  • 39:41 - 39:45
    So, this is the end of my talk. But
  • 39:45 - 39:50
    I'm kind of planning to write a book titled
  • 39:50 - 39:57
    Ruby on Rails Hacking Guide. So, so hopefully.
    I'm
  • 39:58 - 40:00
    planning to write it in Japanese first and
    then
  • 40:00 - 40:04
    translate it into English later. So, hopefully
    can find
  • 40:04 - 40:07
    it, like, next year, maybe.
  • 40:07 - 40:13
    And, yeah. I'll write everything in that book.
    So
  • 40:13 - 40:20
    please wait until the book is coming. Thank
    you
  • 40:20 - 40:21
    very much.
Title:
RailsConf 2014 - Ruby on Rails Hacking Guide by Akira Matsuda
Description:

more » « less
Duration:
40:43

English subtitles

Revisions