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'