Rails5源码分析(蛋人)

01 autoload & ActiveSupport::Autoload的作用以及源码分析
02 ActiveRecord Query源码分析

补充1:rack
补充2:plugin

01 autoload & ActiveSupport::Autoload的作用以及源码分析
查看activerecord源码

#必须在某个生成的项目文件夹下面
bundle show activerecord

ruby中include、extend、require、autoload方法区别

#include和extend方法
include方法将模块的实例方法引入作为类的实例方法
extend方法将模块的实例方法引入作为类的类方法

#require会运行执行这个文文件,直接加载到内存中,只能加载一次
#同一个文件夹中存在demo.rb和test.rb
#demo.rb
puts "this is the demo"

#test.rb
puts(require "./demo") #=>this is the demo, true
puts(require "./demo") #=>false
puts(require "./demo") #=>false


#load方法加载这个文件,可以重复加载,不会自动添加扩展名

#同一个文件夹中存在demo.rb和test.rb
#demo.rb
puts "this is the demo"

#test.rb
puts(load "./demo.rb") #=>this is the demo, true
puts(load "./demo.rb") #=>this is the demo, true
puts(load"./demo.rb") #=>this is the demo, true

autoload对模块进行注册,当第一次使用该模块的时候,对该文件进行require

#demo.rb和test.rb位于同一个文件夹下面

#test.rb
module Test
  def self.simulate
    puts "this is the simulate method"
  end
end

#demo.rb
class Demo
  autoload(:Test, "./test")
end

Demo.simulate #=> this is the simulate method

介绍autoload方法的源码:

#active_record.rb
require "active_support"
require "active_support/rails"

module ActiveRecord
  extend ActiveSupport::Autoload

  autoload :Attribute
  autoload :Base
  …
end

#autoload.rb
require "active_support/inflector/methods"

module ActiveSupport
  module Autoload
    def self.extended(base) # :nodoc:
      base.class_eval do
        @_autoloads = {}
        @_under_path = nil
        @_at_path = nil
        @_eager_autoload = false
      end
    end

    def autoload(const_name, path = @_at_path)
      unless path
        full = [name, @_under_path, const_name.to_s].compact.join("::")
        path = Inflector.underscore(full)
      end

    if @_eager_autoload
      @_autoloads[const_name] = path
    end

    super const_name, path
  end
end

02 ActiveRecord Query源码分析
在development环境中添加方便调试的gem

gem 'pry'
gem 'pry-byebug'
gem 'pry-doc'
gem 'pry-rails'

补充1:rack
rack作用:提供了连接ruby框架和web服务器的应用接口。rails和sintra就是基于rack生成的rack应用。rack的作用是用来简单处理http请求和相应。
一个rack应用就是一个ruby对象,能响应call方法,接受environment的hash参数(对应着http请求),返回一个数组,数组内容包括,status[大于100的数值],headers[hash对象],body[包含字符对象的数组],整个数组对应http响应。rack包含了连接各种web服务器的handlers,也包括和对应各种web框架的adapter。在web服务器和框架中,rack可以通过使用middleware定制到应用程序中。

Rails5源码分析(蛋人)_第1张图片
上面文字的图例说明

安装和使用rack

#安装
gem install rack
#引入
require 'rack' #=>true

#使用lambda建立简单的rack应用my_rack_proc,需要满足上述的条件
my_rack_proc = lambda { |env| [200, {"Content-Type" => "text/plain"}, ["Hello. The time is #{Time.now}"]] }
my_rack_proc.call({}) #=> [200, {"Content-Type" => "text/plain"}, ["Hello. The time is 2011-10-24 09:18:56 +0530"]]
Rack::Handler.constants  #=>[:CGI, :FastCGI, :WEBrick, :LSWS, :SCGI, :Thin]
Rack::Handler.WEBrick.run my_rack_proc #使用webrick服务启动该rack应用
[2017-01-02 15:40:33] INFO  WEBrick 1.3.1
[2017-01-02 15:40:33] INFO  ruby 2.3.0 (2015-12-25) [x86_64-darwin15]
[2017-01-02 15:40:33] INFO  WEBrick::HTTPServer#start: pid=4434 port=8080
#浏览器中输入如下语句进行访问
localhost:8080 #=>Hello. The time is 2017-01-02 15:41:00 +0800
#也可以指定端口
Rack::Handler::WEBrick.run my_rack_proc, :Port => 9876

#使用方法对象建立rack应用
def my_method env
  [200, {}, ["method called"]]
end
#使用webrick服务器进行启动
Rack::Handler::WEBrick.run method(:my_method) #=>method called

使用rackup

rackup是方便启动rack应用的工具,被包含在rack这个gem中。

#建立config.ru文件,文件中输入如下内容
#不指定服务器名称,run使用默认的服务器
run lambda { |env| [200, {"Content-Type" => "text/plain"}, ["Hello. The time is #{Time.now}"]] }

#也可以在相同的文件夹中建立类文件,在config.ru文件中导入
#my_app.rb
class MyApp
  def call env
    [200, {"Content-Type"=>"text/html"}, ["hello world"]]
  end
end

#config.ru
require_relative 'my_app'  #或者 require './my_app'
run MyApp.new

使用middleware和创建middleware
不知从哪里看rack使用了哪些middleware,只能查看通过rails middleware查看rails的middleware。

#添加Rack::Reloader,每次改变内容不需要重新启动
#通过use middleware名称的方式添加middleware的方式
#config.ru
require_relative 'my_app' 
use Rack::Reloader
run MyApp.new

#创建middleware
一个middleware是一个用于包装了内在程序的rack应用。其程序的通用模板如下:
class MyRackMiddleware 
  def initialize(appl) 
    @appl = appl   #appl是被包装的程序名称
  end 

  def call(env) 
  end
end

#完整的middleware代码,用于为body添加内容
class MyRackMiddleware 
  def initialize(appl) 
    @appl = appl 
  end 

  def call(env) 
    status, headers, body = @appl.call(env) 
    append_s = "... greetings from RubyLearning!!" 
    new_body = "" 
    body.each { |string| new_body << " " << string } 
    new_body << " " << append_s 
    [status, headers, [new_body]] 
  end
end

# my_app.rb
class MyApp 
  def call(env)
    [200, {"Content-Type" => "text/html"}, ["Hello Rack Participants from across the globe"]] 
  end
end

#config.ru
require './my_app'
require './myrackmiddleware'
use Rack::Reloader
use MyRackMiddleware
run MyApp.new

补充2:plugin
为String添加实例方法。

#建立lib/yaffle/string_core.rb文件,内容如下
String.class_eval do
  def to_squawk
    "squawk! #{self}".strip
  end
end
#在lib/yaffle.rb文件中require如上的文件
require_relative 'string_core'

你可能感兴趣的:(Rails5源码分析(蛋人))