第一部分:
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)thenraiseAdapterNotSpecified,"databaseconfigurationdoesnotspecifyadapter"end
adapter_method="#{spec[:adapter]}_connection"
unlessrespond_to?(adapter_method)thenraiseAdapterNotFound,"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.configifspec
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
connorraiseConnectionNotEstablished
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进行物理连接
分享到:
相关推荐
Ruby 版数据库连接池, 可以参考。 数据库是postgresql
ruby on rails 安装 组件下载 连接mysql mssql等数据库 包含一个完整的一对多数据库例子方案
NULL 博文链接:https://like-eagle.iteye.com/blog/994634
Ubuntu 11.04安装Ruby on rails 连接MySQL数据库.pdf
rails连接oracle需要的驱动 执行命令:C:\> ruby 文件名.rb <br>
《深入浅出Rails(影印版)》内容简介:通过此书,你将学习:希望你的网络应用超越平庸进入Web 2.0时代?《深入浅出Rails》将使你的编程和生产力达到最大值。你将学习一切Rails scaffolding的基本原理,以创建自定义的...
本人学习总结的ruby on rails 3.1.0数据库类查询方法,比较全了
Rails数据库 请与您的朋友分享此宝石,以获得更多反馈。 如果您有博客,我将非常感谢宝石评论。 如果您有想法-请提出问题或通过电子邮件igorkasyanchuk[@]gmail.com与我联系。 检查Rails数据库快速方法,查看表的...
Rails数据库方案 Rails数据库模式的Autocomplete +提供程序。 特征 自动完成活动记录 根据当前上下文打开模式文件 设定值 将Rails语法设置为默认语法。 " * " : core : customFileTypes : " source.ruby.rails...
NULL 博文链接:https://vb2005xu.iteye.com/blog/505364
用于 Rails 数据库迁移的薄包装器 添加 rake 任务来管理您的数据库架构。 将此 gem 添加到您的 Rails 应用程序中: gem 'flyway-rails', github: 'bluerogue251/flyway-rails' 在应用程序的初始化程序中,设置...
《深入浅出Rails》将使你的编程和生产力达到最大值。你将学习一切Rails scaffolding的基本原理,以创建自定义的交互式网络应用程序,全部使用Rails的一套丰富的工具和MVC框架。 你将掌握数据库交互、Ajax和XML的集成...
labrador, Rails 开发数据库的忠实数据检索器 v0.2.1用于 Rails 开发数据库的忠实数据库( 未知) 客户端。安装拉布拉多可以通过一个聚合 shell 命令的单一拷贝来安装。 详细说明可以在拉布拉多网站的主页上找到。插件...
Rails中的Migration相对来说更适合做数据库的对象集合操作,而自动化的rake则是一个较好的选择,下面来浅谈Ruby on Rails下的rake与数据库数据迁移操作,需要的朋友可以参考下
扩展数据库最简单的方法之一是将较大的,不经常连接的表移动到单独的数据库。 ActiveRecord支持多个数据库,但是Rails没有提供管理它们的方法。 Multiverse正好实现了这个功能。
一个Rails引擎,提供工作流程的基本基础设施。 它基于Workflow Nets。
Rails DB - Rails数据库查看器和SQL查询运行器
检查Rails数据库http:// localhost:12345 / rails / db的快速方法,查看表的内容,将它们导出为CSV,解释SQL并运行SQL查询。 演示位于:https://rails-db.herokuapp.com/rails/db/视频演示:...
本文简单介绍了Ruby On Rails的安装步骤以及MySQL数据库的配置方法,并介绍了几个官方阅读资源。