小编典典

在Rails 3中具有继承关系的命名作用域映射到错误的表

sql

我正在尝试使用具有命名作用域的类的继承:

Class A < ActiveRecord::Base
    scope :useful_scope, lambda { |value1, value2|
        where(:value1 => value1, :value2 => value2)
    end
end

Class B < A
    set_table_name "b"
end

我遇到的问题是sql查询中的表名仍引用A类表:

A.useful_scope("alpha", "beta").to_sql
 => "SELECT \"a\".* FROM \"a\" WHERE \"a\".\"value1\" = 'alpha' AND \"a\".\"value2\" = 'beta'"
B.useful_scope("alpha", "beta").to_sql
 => "SELECT \"b\".* FROM \"b\" WHERE \"a\".\"value1\" = 'alpha' AND \"a\".\"value2\" = 'beta'"

请注意,WHERE语句中的表名仍然引用A。我正在修改一个现有的gem,它在整个A类范围内具有各种依赖性,因此我需要保持其当前语法。我想在WHERE子句SQL中维护表名称说明符,以确保在与其他命名作用域定义嵌套时作用域表现良好。

我尝试了以下方法:

  • 使用lambda参数作为表名。这破坏了其他仅提供当前2个属性的范围的引用的语法。
  • 使用抽象类定义范围。表名的绑定相同,但使用的是Abstract Class的类名。
  • 使用模块中定义的范围并包括该模块。表名称的绑定相同。

有没有一种方法可以强制在每个继承的类上对范围进行评估,以便不将其显式映射到父类表?


阅读 124

收藏
2021-04-28

共1个答案

小编典典

我最终使用了匿名作用域来解决此问题。代码如下:

def self.useful_scope(value1, value2)
  scoped(:conditions => { :value1 => value1, :value2 => value2 })
end

现在,这将在父类和继承的类中正确评估,并保留所需的作用域行为。

2021-04-28