Skip to content

Instantly share code, notes, and snippets.

@ilake
Last active December 10, 2015 05:08
Show Gist options
  • Select an option

  • Save ilake/4385687 to your computer and use it in GitHub Desktop.

Select an option

Save ilake/4385687 to your computer and use it in GitHub Desktop.
# railties/lib/rails/engine.rb
# Define the Rack API for this engine.
def call(env)
app.call(env.merge!(env_config))
end
# We could find app from here
# Returns the underlying rack application for this engine.
def app
@app ||= begin
config.middleware = config.middleware.merge_into(default_middleware_stack)
config.middleware.build(endpoint)
end
end
# What is config.middleware
# we get it from rails/engine/configuration.rb
class Engine < Railtie
autoload :Configuration, "rails/engine/configuration"
...
# railties/lib/rails/engine/configuration.rb
# So we knoe config.middleware actually is MiddlewareStackProxy object
# Returns the middleware stack for the engine.
def middleware
@middleware ||= Rails::Configuration::MiddlewareStackProxy.new
end
# so we go to railties/lib/rails/configuration.rb to check MiddlewareStackProxy
# we could see merge_into over there
def merge_into(other)
@operations.each do |operation, args, block|
other.send(operation, *args, &block)
end
other
end
# so let's go back to railties/lib/rails/engine.rb
def app
@app ||= begin
config.middleware = config.middleware.merge_into(default_middleware_stack)
config.middleware.build(endpoint)
end
end
def default_middleware_stack
ActionDispatch::MiddlewareStack.new
end
# We will know actually is ActionDispatch::MiddlewareStack object really responsible to use ( swap / delete ) middleware
# let go to actionpack/lib/action_dispatch/middleware/stack.rb
# you will see the really method over there
def delete(target)
middlewares.delete target
end
def use(*args, &block)
middleware = self.class::Middleware.new(*args, &block)
middlewares.push(middleware)
end
# so let back to railties/lib/rails/engine.rb app method
def app
@app ||= begin
config.middleware = config.middleware.merge_into(default_middleware_stack)
# so we know after merge_into
# config.middleware here is ActionDispatch::MiddlewareStack object
config.middleware.build(endpoint)
end
end
# let see endpoint first
# Returns the endpoint for this engine. If none is registered,
# defaults to an ActionDispatch::Routing::RouteSet.
def endpoint
self.class.endpoint || routes
end
# Defines the routes for this engine. If a block is given to
# routes, it is appended to the engine.
# actually @routes is alos a rack app
def routes
@routes ||= ActionDispatch::Routing::RouteSet.new
@routes.append(&Proc.new) if block_given?
@routes
end
# so now let go to actionpack/lib/action_dispatch/middleware/stack.rb to check build method
# we already know app here is a RouteSet
# so this method just responsible for wrap middleware one by one to RouteSet
def build(app = nil, &block)
app ||= block
raise "MiddlewareStack#build requires an app" unless app
# Just check
puts "middlewares #{middlewares.inspect}"
puts "app #{app.inspect}"
middlewares.freeze.reverse.inject(app) { |a, e| e.build(a) }
end
# then when you run command rake middleware
middlewares [Airbrake::UserInformer, Airbrake::Rack, ActionDispatch::Static, Rack::Lock, #<ActiveSupport::Cache::Strategy::LocalCache::Middlewa
re:0x007fe73e4c4910>, Rack::Runtime, Rack::MethodOverride, ActionDispatch::RequestId, Rails::Rack::Logger, ActionDispatch::ShowExceptions, Acti
onDispatch::DebugExceptions, ActionDispatch::RemoteIp, ActionDispatch::Reloader, ActionDispatch::Callbacks, ActiveRecord::ConnectionAdapters::C
onnectionManagement, ActiveRecord::QueryCache, ActionDispatch::Cookies, ActionDispatch::Session::CookieStore, ActionDispatch::Flash, ActionDisp
atch::ParamsParser, ActionDispatch::Head, Rack::ConditionalGet, Rack::ETag, ActionDispatch::BestStandardsSupport, RailtieDemo::Bomb, BetterErro
rs::Middleware]
app #<ActionDispatch::Routing::RouteSet:0x007fee4e229798>
use Airbrake::UserInformer
use Airbrake::Rack
use ActionDispatch::Static
use Rack::Lock
use #<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x007fe73e4c4910>
use Rack::Runtime
use Rack::MethodOverride
use ActionDispatch::RequestId
use Rails::Rack::Logger
use ActionDispatch::ShowExceptions
use ActionDispatch::DebugExceptions
use ActionDispatch::RemoteIp
use ActionDispatch::Reloader
use ActionDispatch::Callbacks
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
use ActionDispatch::Cookies
use ActionDispatch::Session::CookieStore
use ActionDispatch::Flash
use ActionDispatch::ParamsParser
use ActionDispatch::Head
use Rack::ConditionalGet
use Rack::ETag
use ActionDispatch::BestStandardsSupport
use RailtieDemo::Bomb
use BetterErrors::Middleware
run PayGoalReward::Application.routes
# so let's back to railties/lib/rails/engine.rb
def call(env)
puts "#{app.inspect}"
app.call(env.merge!(env_config))
end
# and finally you will get app look like
#<Airbrake::UserInformer:0x007fc7f8d7c2c0 @app=#<Airbrake::Rack:0x007fc7f8d7c2e8 @app=#<ActionDispatch::Stat
ic:0x007fc7f8fae6b0 @app=#<Rack::Lock:0x007fc7f8fae728 @app=#<ActiveSupport::Cache::Strategy::LocalCache::Middleware:0x007fc7f77d5d90 @name="Ac
tiveSupport::Cache::Strategy::LocalCache", @thread_local_key=:active_support_cache_file_store_local_cache_70248424194820, @app=#<Rack::Runtime:
0x007fc7f8fae778 @app=#<Rack::MethodOverride:0x007fc7f8fae7a0 @app=#<ActionDispatch::RequestId:0x007fc7f8fae7c8 @app=#<Rails::Rack::Logger:0x00
7fc7f8fae818 @app=#<ActionDispatch::ShowExceptions:0x007fc7f8fae868 @app=#<ActionDispatch::DebugExceptions:0x007fc7f8fae890 @app=#<ActionDispat
ch::RemoteIp:0x007fc7f8fae8b8 @app=#<ActionDispatch::Reloader:0x007fc7f8fae8e0 @app=#<ActionDispatch::Callbacks:0x007fc7f8fae908 @app=#<ActiveR
ecord::ConnectionAdapters::ConnectionManagement:0x007fc7f8fae930 @app=#<ActiveRecord::QueryCache:0x007fc7f8fae958 @app=#<ActionDispatch::Cookie
s:0x007fc7f8fae9d0 @app=#<ActionDispatch::Session::CookieStore:0x007fc7f8faeb60 @secrets=[], @coder=#<Rack::Session::Cookie::Base64::Marshal:0x
007fc7f8faea70>, @app=#<ActionDispatch::Flash:0x007fc7f8faeb88 @app=#<ActionDispatch::ParamsParser:0x007fc7f8faec28 @app=#<ActionDispatch::Head
:0x007fc7f8faec50 @app=#<Rack::ConditionalGet:0x007fc7f8faec78 @app=#<Rack::ETag:0x007fc7f8faeca0 @app=#<ActionDispatch::BestStandardsSupport:0
x007fc7f8faecf0 @app=#<RailtieDemo::Bomb:0x007fc7f8faed18 @app=#<BetterErrors::Middleware:0x007fc7f8faed40 @app=#<ActionDispatch::Routing::Rout
eSet:0x007fc7f8e81328>, @handler=BetterErrors::ErrorPage>>, @header="IE=Edge">, @cache_control="max-age=0, private, must-revalidate", @no_cache_control="no-cache">>>, @parsers={application/xml=>:xml_simple, application/json=>:json}>>, @default_options={:path=>"/", :domain=>nil, :expire
_after=>nil, :secure=>false, :httponly=>true, :defer=>false, :renew=>false, :coder=>#<Rack::Session::Cookie::Base64::Marshal:0x007fc7f8faea70>}, @key="_pay-goal-reward_session", @cookie_only=true>>>>>, @condition=#<Proc:0x007fc7fadb0690@/Users/foo/.rvm/gems/ruby-1.9.2-p290/gems/ra
ilties-3.2.8/lib/rails/application.rb:265 (lambda)>, @validated=true>, @check_ip=true, @proxies=/ ^127\.0\.0\.1$ | # localhost
^(10 | # private IP 10.x.x.x
172\.(1[6-9]|2[0-9]|3[0-1]) | # private IP in the range 172.16.0.0 .. 172.31.255.255
192\.168 # private IP 192.168.x.x )\.
/x>>, @exceptions_app=#<ActionDispatch::PublicExceptions:0x007fc7fa8a1c08 @public_path="/Users/foo/rails_app/foo_app/public">>, @tags=nil>>>, @header_name="X-Runtime">>, @mutex=#<Mutex:0x007fc7f8fae700>>, @file_handler=#<ActionDispatch::FileHandler:0x007fc7f8fae688 @ro
ot="/Users/foo/rails_app/foo_app/public", @compiled_root=/^\/Users\/foo\/rails_app\/foo_app\/public/, @file_server=#<Rack::File:0x007fc7f8d7c310 @root="/Users/foo/rails_app/foo_app/public", @cache_control=nil>>>>>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment