Reputation: 11494
I'm having an issue getting a query to work.
I'm essentially trying to write something like the following SQL, with the literal 5
replaced with a variable:
SELECT *
FROM "my_table"
WHERE 5 BETWEEN "my_table"."minimum" AND "my_table"."maximum"
This is what I have at the moment:
MyModel.where(
Arel::Nodes::Between.new(
my_variable, (MyModel.arel_table[:minimum]).and(MyModel.arel_table[:maximum])
)
)
Please ignore the way I am using arel_table
, the actual query has multiple joins and is more complex, but this is the most minimum reproducible example I have to demonstrate the problem.
The error, as in the subject of the question is as follows:
undefined method `and' for #<Arel::Attributes::Attribute:0x00007f55e15514f8>
Upvotes: 0
Views: 1308
Reputation: 29478
and
method is for Arel::Nodes::Node
i.e. MyModel.arel_attribute[:name].eq(Arel::Nodes::Quoted.new('engineersmnky'))
This is an Arel::Nodes::Equality
and you can chain with and
.
That being said you can construct an Arel::Nodes::And
for yourself via
Arel::Nodes::And.new([left,right])
Then we can pass this to the Between
class like so
Arel::Nodes::Between.new(
Arel::Nodes::Quoted.new(my_variable),
Arel::Nodes::And.new([
MyModel.arel_table[:minimum],
MyModel.arel_table[:maximum]])
)
The Arel::Nodes::Quoted
(also: Arel::Nodes.build_quoted(arg)
) is not needed in your case since your my_variable
is an Integer
which can be visited and will be treated as an Arel::Nodes::SqlLiteral
but I find it best to let arel decide how to handle the quoting in case your my_variable
ends up being some other un-visitable Object
There are other ways to create a Between
and other ways to create an And
depending on what objects you are dealing with.
between
is a Arel::Predication
and these predications are available to Arel::Nodes::Attribute
objects e.g.
MyModel.arel_table[:minimum].between([1,6])
and
as mentioned is available to Arel::Nodes::Node
and instances of this class provides a convenience method (create_and
) for creating an And
so we could do the following:
Arel::Nodes::Node.new.create_and([
MyModel.arel_table[:minimum],
MyModel.arel_table[:maximum]])
There are a number of other ways to hack this functionality together by using other Arel
classes but this should get you headed in the right direction.
Upvotes: 2