#<Arel::Attributes::Attribute 的未定义方法“and”

undefined method `and' for #<Arel::Attributes::Attribute

我在使用查询时遇到问题。

我实际上是在尝试编写类似于以下 SQL 的内容,其中文字 5 替换为变量:

SELECT * 
FROM "my_table"
WHERE 5 BETWEEN "my_table"."minimum" AND "my_table"."maximum"

这是我目前拥有的:

    MyModel.where(
      Arel::Nodes::Between.new(
        my_variable, (MyModel.arel_table[:minimum]).and(MyModel.arel_table[:maximum])
      )
    )

请忽略我使用的方式arel_table,实际查询有多个连接并且更复杂,但这是我必须证明问题的最小可重现示例。

如题目中的错误如下:

undefined method `and' for #<Arel::Attributes::Attribute:0x00007f55e15514f8>

and 方法用于 Arel::Nodes::NodeMyModel.arel_attribute[:name].eq(Arel::Nodes::Quoted.new('engineersmnky')) 这是一个 Arel::Nodes::Equality 并且您可以与 and.

链接

话虽如此,您可以通过

为自己构建一个 Arel::Nodes::And
Arel::Nodes::And.new([left,right])

然后我们可以像这样将它传递给 Between class

Arel::Nodes::Between.new(
  Arel::Nodes::Quoted.new(my_variable),
  Arel::Nodes::And.new([
    MyModel.arel_table[:minimum], 
    MyModel.arel_table[:maximum]])
)

您的情况不需要 Arel::Nodes::Quoted(也:Arel::Nodes.build_quoted(arg)),因为您的 my_variable 是一个可以访问的 Integer,将被视为Arel::Nodes::SqlLiteral 但我发现最好让 arel 决定如何处理引用,以防你的 my_variable 最终成为其他无法访问的 Object

还有其他创建 Between 的方法和其他创建 And 的方法,具体取决于您要处理的对象。

between 是一个 Arel::Predication 并且这些谓词可用于 Arel::Nodes::Attribute 对象,例如

 MyModel.arel_table[:minimum].between([1,6])
提到的

and 可用于 Arel::Nodes::Node 并且此 class 的实例提供了一种方便的方法 (create_and) 来创建 And 所以我们可以执行以下操作:

Arel::Nodes::Node.new.create_and([
     MyModel.arel_table[:minimum],
     MyModel.arel_table[:maximum]])

还有许多其他方法可以通过使用其他 Arel classes 来破解此功能,但这应该会让您朝着正确的方向前进。