加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby-on-rails – 将数据库名称添加到表的Rails 3包括默认加载

发布时间:2020-12-16 21:41:27 所属栏目:百科 来源:网络整理
导读:资料来源: http://emphaticsolutions.com/2009/11/23/has_many_through_across_databases.html http://blog.arkency.com/2013/12/rails4-preloading/ 我的项目正在转向拥有多个数据库(目前在同一台服务器上),我希望能够在这些数据库之间加入.为了做到这一点
资料来源:

> http://emphaticsolutions.com/2009/11/23/has_many_through_across_databases.html
> http://blog.arkency.com/2013/12/rails4-preloading/

我的项目正在转向拥有多个数据库(目前在同一台服务器上),我希望能够在这些数据库之间加入.为了做到这一点,我需要将数据库名称添加到表前缀,如下所示:

class FirstBase < ActiveRecord::Base
    def self.table_name_prefix
        "DBNAME.t_"
    end

    establish_connection :firstdb
end

class User < FirstBase
    has_many :user_roles
end

class UserRole < FirstBase
    belongs_to :user
end

添加表名称前缀似乎会影响包含在同一查询上的默认行为,即使在同一数据库中也是如此.考虑User.includes(:user_roles).first

没有表名前缀:

User Load (67.1ms) SELECT t_users.* FROM t_users LIMIT 1
UserRole Load (84.5ms) SELECT t_user_roles.* FROM t_user_roles WHERE
t_user_roles.user_id IN (1)

使用表名前缀:

SQL (76.8ms) SELECT DISTINCT DBNAME.t_users.id FROM DBNAME.t_users LEFT OUTER JOIN DBNAME.t_user_roles ON DBNAME.t_user_roles.user_id = DBNAME.t_users.id LIMIT 1

SQL (66.4ms) SELECT DBNAME.t_users.id AS t0_r0,DBNAME.t_users.email AS t0_r1,DBNAME.t_user_roles.id AS t1_r0,DBNAME.t_user_roles.user_id AS t1_r1 FROM DBNAME.t_users LEFT OUTER JOIN DBNAME.t_user_roles ON DBNAME.t_user_roles.user_id = DBNAME.t_users.id WHERE DBNAME.t_users.id IN (1)

换句话说,调用包含的默认行为已经从预加载更改为热负载.

有人知道为什么默认行为正在改变吗?必须有一些关于添加数据库名称,使Rails认为我们必须加载,但我不明白为什么.我也很惊讶地看到这一点,因为我想象的是添加数据库名称是不寻常的.我可以通过更改所有包含预加载来强制将其修复到我们的代码库中,但我想了解这里发生了什么.有没有办法改变默认行为?

解决方法

问题是table_name_prefix引入了一个句点.这混淆了试图确定它是否应该预加载或加载的逻辑.这是一个Rails 3错误,已在Rails 4中解决.如果您需要Rails 3中的特定行为,则需要明确指定预加载或eager_load,就像您在问题中所指出的那样.

在ActiveRecord::Relation,exec_queries调用eager_loading?来决定是否应该加载.这调用references_eager_loaded_tables?它使用tables_in_string尝试在SQL查询中查找不是连接表的一部分的表名:

# ActiveRecord::Relation#references_eager_loaded_tables?
(tables_in_string(to_sql) - joined_tables).any?

tables_in_string方法有缺陷,因为它并不总是正确解析SQL.该代码可用于查看SQL查询中表名的内容:

relation = User.includes(:user_roles)
relation.send(:tables_in_string,relation.to_sql)

使用DBNAME.t_表名前缀,这将给出[“DBNAME”,“t_users”]作为表名,这是错误的.它应该给[“DBNAME.t_users”].

ActiveRecord query changing when a dot/period is in condition value记录了类似的问题.这导致ActiveRecord::Relation的变化在决定是预加载还是加载负载时,不再使用tables_in_string.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读