`
isiqi
  • 浏览: 16481144 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

深入分析rails数据库连接流程

阅读更多
第一部分:
Method 1)
defself.establish_connection(spec=nil)
casespec
#1
whennil
raiseAdapterNotSpecifiedunlessdefined?RAILS_ENV
establish_connection(RAILS_ENV)
whenConnectionSpecification
#2
clear_active_connection_name
@active_connection_name
=name
@@defined_connections[name]
=spec
whenSymbol,String
#3
pconfigurations
ifconfiguration=configurations[spec.to_s]
establish_connection(configuration)
else
raiseAdapterNotSpecified,"#{spec}databaseisnotconfigured"
end
else#4
spec=spec.symbolize_keys
unlessspec.key?(:adapter)then
raiseAdapterNotSpecified,"databaseconfigurationdoesnotspecifyadapter"end
adapter_method
="#{spec[:adapter]}_connection"
unlessrespond_to?(adapter_method)then
raiseAdapterNotFound,"databaseconfigurationspecifiesnonexistent#{spec[:adapter]}adapter"end
remove_connection
establish_connection(ConnectionSpecification.new(spec,adapter_method))
end
end
如果不带参数调用 establish_connection,进入#1,rails会给一个默认参数,那就是你得rails环境 (production, development, test),这是进入#2,rails会根据你得参数在databse.yml下找到对应的配置,此时是一个 hash对象,进入#3, 首先查看你得hash中key为:adpater的item,不存在就抛错,如果存在(本例为mysql),则继续看是否存在mysql_connection方法,不存在就抛错,你可以在#{activerecordhome}\lib\active_record\connection_adapters,看到各种数据库驱动接口文件,每个文件重新打开了ActionRecode:Base类,并定义了数据库类型_connection的方法,比如mysql_adapter.rb含有mysql_connection , db2_adapter.rb含有db2_adapter.rb等等,如果存在这样的方法,说明你得配置文件正确,于是开始调用remove_connection(见Method2),然后 实例化一个ConnectionSpecification作为参数进入#2调用clear_active_connection_name(见Method3),然后将类的实例变量@active_connection_name复值为类名,再将一个key为类名,value为上面那个ConnectionSpecification实例变量的item添加到类变量 @@defined_connections(一个hash)
Method 2)
defself.remove_connection(klass=self)
spec
=@@defined_connections[klass.name]
konn
=active_connections[klass.name]
@@defined_connections.delete_if{
|key,value|value==spec}
active_connections.delete_if{
|key,value|value==konn}
konn.disconnect!
ifkonn
spec.config
ifspec
end
删除@@defined_connectionshash中value即配置相同的item
删除@@active_connectionshash中value即数据库连接相同的item,并关闭数据库连接
返回配置hash
Method 3)
defclear_active_connection_name#:nodoc:
@active_connection_name=nil
subclasses.each{
|klass|klass.clear_active_connection_name}
end
清除 @active_connection_name以及递归清除子类的 @active_connection_name
第二部分
以一个普通的查询开始
比如有个model类User
class User < ActiveRecord::Base;end
调用User.count
Method 4)
defconnection

if@active_connection_name&&(conn=active_connections[@active_connection_name])
conn

else
#retrieve_connectionsetsthecachekey.
conn=retrieve_connection
active_connections[@active_connection_name]
=conn
end
end
显然如果存在数据库连接active_connections[@active_connection_name],则返回这个连接对象以供数据库操作
如果不存在,那么调用方法retrieve_connection(见Method5),并将Method5返回的连接对象缓存到hash
@@active_connections,以@active_connection_name为key,连接对象为value
Method 5)
defself.retrieve_connection#:nodoc:
#Nameisnilifestablish_connectionhasn'tbeencalledfor
#someclassalongtheinheritancechainuptoAR::Baseyet.
ifname=active_connection_name
ifconn=active_connections[name]
#Verifytheconnection.
conn.verify!(@@verification_timeout)
elsifspec
=@@defined_connections[name]
#Activatethisconnectionspecification.
klass=name.constantize
klass.connection
=spec
conn
=active_connections[name]
end
end

conn
orraiseConnectionNotEstablished
end
首先调用active_connection_name(见Method6)获取连接key,如果key存在,再利用这个key,从hash
@@active_connections取出连接,如果连接存在则调用verify!,否则利用key,从hash @@defined_connections取出配置,通过调用constantize,将key转化为一个类对象,并调用该类对象的
connection =方法(以配置为参数)(见Method7 )
Method6:
defactive_connection_name#:nodoc:
@active_connection_name||=
ifactive_connections[name]||@@defined_connections[name]
name
elsifself
==ActiveRecord::Base
nil
else
superclass.active_connection_name
end
end
返回active_connection_name
Method7:
defself.connection=(spec)#:nodoc:
ifspec.kind_of?(ActiveRecord::ConnectionAdapters::AbstractAdapter)#1
active_connections[name]=spec
elsifspec.kind_of?(ConnectionSpecification)#2
config=spec.config.reverse_merge(:allow_concurrency=>@@allow_concurrency)
self
.connection=self.send(spec.adapter_method,config)
elsifspec.nil?#3
raiseConnectionNotEstablished
else#4
establish_connectionspec
end
end
如果直接传入的是一个连接对象,那么push到hash @@active_connections,以类名为key
如果传入是配置对象,则开始调用适配器方法(见Method8),在使用mysql的情况下是调用
mysql_connection,传入参数配置hash
然后跳到#1
如果未传参数,直接抛错
如果上面上个条件都不满足,则调用establish_connection
通常情况下,此方法进入#2,通过Method8返回连接对象,再进入#1
Method8
见文件mysql_adapter.rb
defself.mysql_connection(config)#:nodoc:
config=config.symbolize_keys
host
=config[:host]
port
=config[:port]
socket
=config[:socket]
username
=config[:username]?config[:username].to_s:'root'
password
=config[:password].to_s

ifconfig.has_key?(:database)
database
=config[:database]
else
raiseArgumentError,"Nodatabasespecified.Missingargument:database."
end

require_mysql
#1
mysql=Mysql.init#2
mysql.ssl_set(config[:sslkey],config[:sslcert],config[:sslca],config[:sslcapath],config[:sslcipher])ifconfig[:sslkey]#3

ConnectionAdapters::MysqlAdapter.new(mysql,logger,[host,username,password,database,port,socket],config)
#4
end
前面很好理解,从#1开始,#1加载active_record/vendor/mysql,#2调用init(Method9)初始化active_record/vendor/mysql文件中定义的类Mysql,返回Mysql类的实例mysql,#3看config中是否含有sskey,如果有就调用ssl_set,我发现并不存在这个方法,通过调用mysql.respond_to?(:ssl_set)发现运行过程中返回false,可能调用这个方法还需要其他的lib,默认的rails1.2.3是没有的,但因为sskey这种key,所以也不会出错#4实例化ConnectionAdapters::MysqlAdapter(Method10)
Method9
见文件mysql.rb
class<<Mysql
definit()
Mysql::new:INIT
end
##。。。。。
end
definitialize(*args)
@client_flag
=0
@max_allowed_packet
=MAX_ALLOWED_PACKET
@query_with_result
=true
@status
=:STATUS_READY
ifargs[0]!=:INITthen
real_connect(
*args)
end
end
实例化Mysql传入参数:INIT,所以并不调用real_connect
Method10
见文件mysql_adapter.rb
definitialize(connection,logger,connection_options,config)
super(connection,logger)
@connection_options,@config
=connection_options,config

connect
end

实际调用connect(Method11
Method11
见文件mysql_adapter.rb
defconnect
encoding
=@config[:encoding]
ifencoding
@connection.options(Mysql::SET_CHARSET_NAME,encoding)rescuenil
end
@connection.ssl_set(@config[:sslkey],@config[:sslcert],@config[:sslca],@config[:sslcapath],@config[:sslcipher])
if@config[:sslkey]
@connection.real_connect(
*@connection_options)#1
execute("SETNAMES'#{encoding}'")ifencoding

#Bydefault,MySQL'whereidisnull'selectsthelastinsertedid.
#Turnthisoff.http://dev.rubyonrails.org/ticket/6778
execute("SETSQL_AUTO_IS_NULL=0")
end
首先设置编码,最终的是#1,调用连接对象real_connect进行物理连接
分享到:
评论

相关推荐

    Web开发敏捷之道--应用Rails进行敏捷Web开发 之 Depot代码。

    5. **config**:配置目录,包含应用的配置文件,如数据库连接信息、路由设置、环境变量等。 6. **db**:数据库目录,其中的migrate子目录存放数据库迁移文件,用于更新数据库结构。 7. **test**:测试目录,存放...

    ruby on rails源代码分析

    在本文中,我们将深入分析 Ruby on Rails 2.0.2 的源代码,特别是关注其启动过程。 首先,Rails 的启动始于 `config/boot.rb` 文件。这个文件是 Rails 应用程序的入口点,负责检查 Rails 是否已启动。如果没有,它...

    Agile Web Development with Rails (PDF)

    书中详细介绍了如何在不同操作系统(如Windows、Mac OS X和Unix/Linux)上安装和配置Rails环境,以及如何连接各种数据库系统。这些步骤对于初学者来说至关重要,确保了开发者能够在自己的环境中顺利搭建起开发平台。...

    NetBeans Ruby and Rails IDE with JRuby 2009

    - **操作数据库**:包括配置数据库连接信息、使用不同的数据库适配器等。 - **创建数据库**:在IDE中创建新的数据库。 - **创建和修改表**:直接通过IDE操作数据库表结构。 - **使用生成器**:Rails的生成器可以帮助...

    Ruby on rails 教程

    - 配置数据库:设置数据库连接信息。 #### 三、核心功能 1. **MVC架构** - 模型(Model):负责处理应用程序数据逻辑的部分。 - 视图(View):负责显示数据。 - 控制器(Controller):接收请求并分配职责。 2. **...

    Rbuy for Rails源代码

    4. **config/**:配置文件,如数据库连接、路由设置等。 5. **db/**:数据库相关的文件,如迁移(migrations)。 6. **lib/**:存放自定义库和代码。 7. **spec/**:测试文件,通常使用RSpec或其他测试框架编写。 8....

    再次发一本部署rails的书

    5. **环境变量与配置**:讲解如何管理生产环境中的敏感信息,如API密钥、数据库连接字符串,以及使用dotenv、figaro等库进行环境变量管理。 6. **进程管理**:介绍使用Systemd或Upstart管理后台进程,确保应用在...

    Rails应用程序样本AWSOpsWorksRailsDemoApp.zip

    通过分析这个示例应用,开发者不仅可以学习Rails的基础知识,还能深入了解如何将Rails应用部署到AWS云环境中,以及如何利用OpsWorks进行高效运维。这是一个全面了解现代Web开发流程和云服务的好起点。

    Agile Web Development with Rails中文版 3rd Edition

    讨论了如何配置Rails应用与数据库的连接,以及支持的不同数据库类型。 **3.8 保持更新** 建议定期更新Rails和相关的依赖库,以确保应用的安全性和稳定性。 **3.9 Rails和ISPs** 探讨了如何将Rails应用部署到...

    Agile Web Development with Rails Third Edition(2009年第三版)

    10. **最佳实践与案例分析**:书中通过实际项目案例,展示了如何将理论知识应用到实践中,提供了一套完整的敏捷开发流程,帮助读者提升解决实际问题的能力。 通过阅读《敏捷Web开发与Rails第三版》,开发者不仅可以...

    Code Review&JRuby on Rails

    3. **企业级支持**:JRuby可以无缝接入Java生态,方便整合企业级服务,如数据库连接池、消息队列等。 4. **热部署**:在JRuby环境中,可以实现代码的热部署,减少应用更新时的停机时间。 5. **并发能力**:JVM提供...

    使用ROR编写ORACLE WEB应用

    综上所述,使用ROR编写Oracle Web应用涉及安装配置、数据库连接、模型、视图、控制器的设计,以及部署和性能优化等多个方面。通过深入学习和实践,开发者可以掌握这一技术栈,为构建高效、稳定的Web应用奠定基础。

    rottenpotatoes-rails-简介

    通过阅读和分析这些代码,你可以深入理解Rails的工作原理以及如何使用它来构建实际的应用程序。 总的来说,"RottenPotatoes-rails-简介"是一个很好的学习资源,它可以帮助初学者快速掌握Ruby on Rails的基本概念和...

    使用Ruby on Rails和PostGIS创建位置感知网站

    开发者还需要配置数据库连接,确保Rails应用能够正确地与数据库进行通信。 接着,我们需要设计数据库模型来存储位置数据。这可能包括点、线、面等几何类型,以及相关的属性信息。在Rails中,可以使用ActiveRecord来...

    Web开发敏捷之道第三版(中文版).pdf

    - **Rails的日志**:介绍如何查看和分析Rails应用的日志文件。 - **调试信息**:提供有用的调试技巧和工具,帮助开发者定位问题。 - **精彩预告**:预告后续章节将涉及的内容,激发读者的学习兴趣。 #### 第16章:...

    RubyOnRails的一个入门小例子

    - config:存储配置文件,如数据库连接、路由设置等。 - db:数据库相关文件,如数据库迁移(migrations)和配置。 - lib:存放自定义库和扩展代码。 - public:存放静态资源,如CSS、JavaScript和图片。 - test:...

    sample_app:Ruby on Rails 3

    在这个教程中,我们将深入探讨“sample_app”这一示例应用程序,了解如何利用Rails 3进行Web应用开发。 首先,让我们来理解Rails的核心理念:“Don't Repeat Yourself”(DRY),即“不要重复自己”。Rails鼓励...

Global site tag (gtag.js) - Google Analytics