首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >混叠源表

混叠源表
EN

Stack Overflow用户
提问于 2021-12-21 10:03:30
回答 2查看 218关注 0票数 1

是否有方法在单个作用域的上下文中对源表进行别名?

我试过这个:

代码语言:javascript
复制
scope = User.all
scope.arel.source.left.table_alias = "toto"
scope.where(firstname: nil) => "SELECT `toto`.* FROM `users` `toto` WHERE `toto`.`firstname` IS NULL"

问题是,模型类为所有后续查询保留别名:

代码语言:javascript
复制
User.all => "SELECT `toto`.* FROM `users` `toto`"

编辑

我将此方法添加到ApplicationRecord

代码语言:javascript
复制
def self.alias_source(table_alias)
  klass = Class.new(self)
  klass.all.source.left.table_alias = table_alias
  klass
end

现在,我可以:

代码语言:javascript
复制
User.alias_source(:toto).where(firstname: nil) => "SELECT `toto`.* FROM `users` `toto` WHERE `toto`.`firstname` IS NULL"
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-12-29 20:32:15

因为创建继承自ActiveRecord::Base的匿名类会导致内存膨胀,所以我不确定我会推荐它(参见此处:https://github.com/rails/rails/issues/31395)。

也许更好的实现是以块形式执行,例如将别名表交给块,然后将其设置回块。

例如:

代码语言:javascript
复制
def self.with_table_alias(table_alias, &block)
  begin 
    self.all.source.left.table_alias = table_alias
    block.call(self)
  ensure 
    self.all.source.left.table_alias = nil 
  end
end

用法

代码语言:javascript
复制
User.with_table_alias(:toto) do |scope| 
  puts scope.joins(:posts).where(firstname: "Ruur").to_sql
end 
# "SELECT `toto`.* 
#  FROM 
#    `users` `toto` 
#    INNER JOIN `posts` ON `posts`.`user_id` = `toto`.`id` 
#  WHERE 
#    `toto`.`firstname` = 'Ruur'" 

puts User.all.to_sql
# "SELECT `users`.* FROM `users`

警告:如果没有对边缘案例和其他进行广泛的测试,就不会在生产环境中对此进行测试。

更新以解决所需的实现

代码语言:javascript
复制
module ARTableAlias

  def alias_table_name=(val) 
    @alias_table_name = val 
  end 

  def alias_table_name 
    @alias_table_name ||= "#{self.table_name}_alias" 
  end   

  def alias_source
    @alias_klass ||= Class.new(self).tap do |k|
      k.all.source.left.table_alias = alias_table_name
    end  
  end 
end 

然后以下列方式使用:

代码语言:javascript
复制
class User < ApplicationRecord 
  extend ARTableAlias 

  alias_table_name = :toto
end 

User.alias_source.where(first_name = 'Ruur') 
#=> SELECT `toto`.* FROM `users` `toto` WHERE `toto`.`first_name` = 'Ruur'
User.where(first_name = 'Ruur') 
#=> SELECT `users`.* FROM `users` WHERE `users`.`first_name` = 'Ruur'
User.alias_source === User.alias_source
#=> true
票数 1
EN

Stack Overflow用户

发布于 2021-12-21 14:53:48

我将此方法添加到ApplicationRecord中

代码语言:javascript
复制
def self.alias_source(table_alias)
  klass = Class.new(self)
  klass.all.source.left.table_alias = table_alias
  klass
end

现在,我可以:

代码语言:javascript
复制
User.alias_source(:toto).where(firstname: nil) => "SELECT `toto`.* FROM `users` `toto` WHERE `toto`.`firstname` IS NULL"
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70433630

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档