11#Learn-Rails-by-Reading-Source-Code
2+ [ ![ LICENSE] ( https://img.shields.io/badge/license-Anti%20996-blue.svg )] ( https://github.com/996icu/996.ICU/blob/master/LICENSE )
3+ [ ![ 996.icu] ( https://img.shields.io/badge/link-996.icu-red.svg )] ( https://996.icu )
24##Table of Contents
35
46* [ Part 0: Before reading Rails 5 source code] ( #part-0-before-reading-rails-5-source-code )
2224
2325
2426##Part 0: Before reading Rails 5 source code
25- 1 ) I suggest you learn Rack[ http://rack.github.io/ ] ( http://rack.github.io/ ) first.
27+ 1 ) I suggest youto learn Rack[ http://rack.github.io/ ] ( http://rack.github.io/ ) first.
2628
27- Inrack , an object with` call ` method is arack app.
29+ InRack , an object with` call ` method is aRack app.
2830
2931So what is the object with` call ` method in Rails? I will answer this question in Part 1.
3032
@@ -37,7 +39,7 @@ So what is the object with `call` method in Rails? I will answer this question i
3739
3840* How does Rails combine ActionController, ActionView and Routes together?
3941
40- * How doespuma, rack , Rails work together?
42+ * How doesPuma, Rack , Rails work together?
4143
4244* What's Puma's multiple threads?
4345
@@ -55,7 +57,7 @@ module Rails
5557def perform
5658# ...
5759Rails ::Server .new (server_options).tapdo |server |
58- # APP_PATH is '/Users/your_name /your_project/config/application'.
60+ # APP_PATH is '/path/to /your_project/config/application'.
5961# require APP_PATH will create the 'Rails.application' object.
6062# Actually, 'Rails.application' is an instance of `YourProject::Application`.
6163# Rack server will start 'Rails.application'.
@@ -84,9 +86,9 @@ module Rails
8486end
8587end
8688```
87- Arack server need to start with an` App ` object. The` App ` object should have a` call ` method.
89+ ARack server need to start with an` App ` object. The` App ` object should have a` call ` method.
8890
89- ` config.ru ` is the conventional entry file forrack app. So let's look at it.
91+ ` config.ru ` is the conventional entry file forRack app. So let's look at it.
9092``` ruby
9193# ./config.ru
9294require_relative ' config/environment'
@@ -264,9 +266,9 @@ Rack server will start `Rails.application` in the end.
264266
265267` Rails.application ` is an important object in Rails.
266268
267- And you'll only have one` Rails.application ` in onepuma process.
269+ And you'll only have one` Rails.application ` in onePuma process.
268270
269- Multiple threads in apuma process shares the` Rails.application ` .
271+ Multiple threads in aPuma process shares the` Rails.application ` .
270272
271273##Part 2: config
272274The first time we see the` config ` is in` ./config/application.rb ` .
382384```
383385
384386###Puma
385- When a request is made from client,puma will process the request in` Puma::Server#process_client ` .
387+ When a request is made from client,Puma will process the request in` Puma::Server#process_client ` .
386388
387- If you want to know howpuma enter the method` Puma::Server#process_client ` , please read part 4 or just search 'process_client' in this document.
389+ If you want to know howPuma enter the method` Puma::Server#process_client ` , please read part 4 or just search 'process_client' in this document.
388390
389391``` ruby
390392# ./gems/puma-3.12.0/lib/puma/server.rb
@@ -447,7 +449,7 @@ module Puma
447449
448450# Given the request +env+ from +client+ and a partial request body
449451# in +body+, finish reading the body if there is one and invoke
450- # therack app. Then construct the response and write it back to
452+ # theRack app. Then construct the response and write it back to
451453# +client+
452454#
453455def handle_request (req ,lines )
@@ -550,7 +552,7 @@ module Rails
550552puts " caller:#{ caller .inspect} "
551553
552554# You may want to know when is the @app first time initialized.
553- # It is initialized when 'config.ru' is load byrack server.
555+ # It is initialized when 'config.ru' is load byRack server.
554556# Please search `Rack::Server#build_app_and_options_from_config` in this document for more information.
555557# When `Rails.application.initialize!` (in ./config/environment.rb) executed, @app is initialized.
556558@app || @app_build_lock .synchronize {# '@app_build_lock = Mutex.new', so multiple threads share one '@app'.
@@ -704,8 +706,8 @@ module ActionDispatch
704706end
705707
706708def build (app )
707- # klass israck middleware like : Rack::TempfileReaper, Rack::ETag, Rack::ConditionalGet or Rack::Head, etc.
708- # It's typicalrack app to use these middlewares.
709+ # klass isRack middleware like : Rack::TempfileReaper, Rack::ETag, Rack::ConditionalGet or Rack::Head, etc.
710+ # It's typicalRack app to use these middlewares.
709711# See https://github.com/rack/rack-contrib/blob/master/lib/rack/contrib for more information.
710712 klass.new (app,* args,& block)
711713end
730732# >
731733# >
732734```
733- As we see in the Rack middleware stack, the lastone is
735+ As we see in the Rack middleware stack, the last@ app is
734736
735737` @app=#<ActionDispatch::Routing::RouteSet:0x00007fa1e594cbe8> `
736738``` ruby
@@ -1486,7 +1488,7 @@ module ActionView
14861488end
14871489
14881490```
1489- After allrack apps called, user will get the response.
1491+ After allRack apps called, user will get the response.
14901492
14911493##Part 4: What does` $ rails server ` do?
14921494
@@ -1707,7 +1709,7 @@ module Rails
17071709def perform
17081710# ...
17091711Rails ::Server .new (server_options).tapdo |server |
1710- # APP_PATH is '/Users/your_name /your_project/config/application'.
1712+ # APP_PATH is '/path/to /your_project/config/application'.
17111713# require APP_PATH will create the 'Rails.application' object.
17121714# 'Rails.application' is 'YourProject::Application.new'.
17131715# Rack server will start 'Rails.application'.
@@ -1863,7 +1865,7 @@ module Puma
18631865# with configuration in `config/puma.rb` or `config/puma/<env>.rb`.
18641866#
18651867# It is responsible for either launching a cluster of Puma workers or a single
1866- # puma server.
1868+ # Puma server.
18671869class Launcher
18681870def initialize (conf ,launcher_args = {})
18691871@runner = nil
@@ -1984,7 +1986,7 @@ module Puma
19841986# This part is important.
19851987# Remember the block of ThreadPool.new will be called when a request added to the ThreadPool instance.
19861988# And the block will process the request by calling method `process_client`.
1987- # Let's step into this line later to see howpuma call the block.
1989+ # Let's step into this line later to see howPuma call the block.
19881990@thread_pool = ThreadPool .new (@min_threads ,
19891991@max_threads ,
19901992IOBuffer )do |client ,buffer |
@@ -2000,7 +2002,7 @@ module Puma
20002002
20012003# ...
20022004if process_now
2003- # Process the request. You cantreat `client` as request.
2005+ # Process the request. You canlook upon `client` as request.
20042006# If you want to know more about 'process_client', please read part 3
20052007# or search 'process_client' in this document.
20062008 process_client(client, buffer)
@@ -2014,7 +2016,7 @@ module Puma
20142016
20152017if background# background: true (for this example)
20162018# This part is important.
2017- # Rememberpuma created a thread here!
2019+ # RememberPuma created a thread here!
20182020# We will know that the newly created thread's job is waiting for requests.
20192021# When a request comes, the thread will transfer the request processing work to a thread in ThreadPool.
20202022# The method `handle_servers` in thread's block will be executed immediately
@@ -2047,7 +2049,7 @@ module Puma
20472049break if handle_check
20482050else
20492051if io= sock.accept_nonblock
2050- # You can simplythink a Puma::Client instance as a request.
2052+ # You can simplylook upon a Puma::Client instance as a request.
20512053 client= Client .new (io,@binder .env(sock))
20522054
20532055# ...
@@ -2083,7 +2085,7 @@ module Puma
20832085def initialize (min ,max ,* extra ,& block )
20842086# ..
20852087@mutex = Mutex .new
2086- @todo = []# @todo is requests (inpuma , they are Puma::Client instances) which need to be processed.
2088+ @todo = []# @todo is requests (inPuma , they are Puma::Client instances) which need to be processed.
20872089@spawned = 0 # the count of @spawned threads
20882090@min = Integer (min)# @min threads count
20892091@max = Integer (max)# @max threads count
@@ -2149,7 +2151,7 @@ module Puma
21492151@waiting -= 1
21502152end
21512153
2152- # `work` is the request (inpuma , it's Puma::Client instance) which need to be processed.
2154+ # `work` is the request (inPuma , it's Puma::Client instance) which need to be processed.
21532155 work= todo.shiftif continue
21542156end
21552157
@@ -2207,7 +2209,7 @@ module Puma
22072209end
22082210
22092211# work: #<Puma::Client:0x00007ff114ece6b0>
2210- # You cantreat Puma::Client instance as a request.
2212+ # You canlook upon Puma::Client instance as a request.
22112213@todo << work
22122214
22132215if @waiting < @todo .sizeand @spawned < @max
@@ -2241,9 +2243,9 @@ In `.run`, Puma will new a always running Thread for `ios = IO.select(#<TCPServe
22412243
22422244Request is created from` ios ` object.
22432245
2244- A thread inpuma threadPool will process the request.
2246+ A thread inPuma threadPool will process the request.
22452247
2246- The thread will invokerack apps'` call ` to get the response for the request.
2248+ The thread will invokeRack apps'` call ` to get the response for the request.
22472249
22482250###Exiting Puma
22492251####Process and Thread
@@ -2311,7 +2313,7 @@ puts "Exit main thread"
23112313` ` `
23122314
23132315# ### Send `SIGTERM` to Puma
2314- When you stoppuma by running` $ kill -s SIGTERM puma_process_id` , you will enter` setup_signals` in ` Puma::Launcher#run` .
2316+ When you stopPuma by running` $ kill -s SIGTERM puma_process_id` , you will enter` setup_signals` in ` Puma::Launcher#run` .
23152317` ` ` ruby
23162318# .gems/puma-3.12.0/lib/puma/launcher.rb
23172319module Puma
@@ -2453,14 +2455,14 @@ module Puma
24532455
24542456 # The created @thread is the @thread in` stop` method below.
24552457 @thread = Thread.new {
2456- # FYI, this is in thepuma starting process.
2458+ # FYI, this is in thePuma starting process.
24572459 # 'Thread.current.object_id' returns '70144220123860',
24582460 # which is the same as the 'Thread.current.object_id' in 'handle_servers' in Puma::Server#run
24592461 # def handle_servers
24602462 # begin
24612463 # # ...
24622464 # ensure
2463- # # FYI, the 'ensure' part is in thepuma stopping process.
2465+ # # FYI, the 'ensure' part is in thePuma stopping process.
24642466 # puts "#{ Thread .current.object_id} " # returns '70144220123860' too.
24652467 # end
24662468 # end
@@ -2533,11 +2535,11 @@ module Puma
25332535
25342536# ...
25352537ensure
2536- # FYI, the 'ensure' part is in thepuma stopping process.
2538+ # FYI, the 'ensure' part is in thePuma stopping process.
25372539# 'Thread.current.object_id' returns '70144220123860',
25382540# which is the same as the 'Thread.current.object_id' in 'Thread.new block' in Puma::Server#run
25392541# @thread = Thread.new do
2540- # # FYI, this is in thepuma starting process.
2542+ # # FYI, this is in thePuma starting process.
25412543# puts "#{Thread.current.object_id}" # returns '70144220123860'
25422544# handle_servers
25432545# end
@@ -2611,7 +2613,7 @@ module Puma
26112613# ..
26122614@mutex = Mutex .new
26132615@spawned = 0 # The count of @spawned threads.
2614- @todo = []# @todo is requests (inpuma , it's Puma::Client instance) which need to be processed.
2616+ @todo = []# @todo is requests (inPuma , it's Puma::Client instance) which need to be processed.
26152617@min = Integer (min)# @min threads count
26162618@block = block# block will be called in method `spawn_thread` to process a request.
26172619@workers = []