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定制到应用程序中。

上面文字的图例说明

安装和使用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'
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,684评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,143评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,214评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,788评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,796评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,665评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,027评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,679评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,346评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,664评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,766评论 1 331
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,412评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,015评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,974评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,073评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,501评论 2 343

推荐阅读更多精彩内容

  • Awesome Ruby Toolbox Awesome A collection of awesome Ruby...
    debbbbie阅读 2,778评论 0 3
  • ruby 的命名规则局部变量:以英文字母或者_开头,如:name = "this is a local varia...
    云莉6阅读 765评论 0 0
  • 同心断,空留痴心长消黯。长消黯,尘影往复,无据残照。 潮来潮去纷纷散,重来亦是情隔岸。情隔岸,多年独闯,天涯别远。
    何潇湘阅读 324评论 0 3
  • 碧水廊腰,容姿曼娆,一江东流烟飘渺,待我妆整,换洗旧袍,时年少。 最怕犹是,伤春时候,十二桥栏杆倚遍,愁不胜,当年...
    落宸风阅读 305评论 0 1