what l
what l

Reputation: 25

How can i create an query not using string?

i have to implement a query, not with string only i have to use hash like this

Products.where(:id != @product_id AND init_time <= ? AND (:section_id => @section_id OR :type_id => @type_id))

but i am getting errors in 'AND' 'OR' and how can i fix this part '!='?

Upvotes: 0

Views: 88

Answers (2)

engineersmnky
engineersmnky

Reputation: 29573

We can produce this query using Hash syntax alone but it is not as nice as I would like because you have to repeat conditions

For Example:

Products
  .where(section_id: @section_id, init_time: ..[YOUR INIT TIME HERE])
  .where.not(id: @product_id)
  .or( 
    Products
    .where(type_id: @type_id, init_time: ..[YOUR INIT TIME HERE])
    .where.not(id: @product_id)
)

as pointed out by @3limin4t0r you could also use

Product
  .where(section_id: @section_id)
  .or(Product.where(type_id: @type_id))
  .where(init_time: ..@init_time).where.not(id: @product_id)

Which is definitely cleaner but this query is order dependent so the where(condition1).or(condition2) needs to be in the front of the chain to wrap the condition in parens appropriately.

Instead I would do so as follows:

Product.where.not(id: @product_id)
       .where(init_time: ..[YOUR INIT TIME HERE])
       .where( 
          Product.arel_table[:section_id].eq(@section_id).or(
            Product.arel_table[:type_id].eq(@type_id))
        )

Assuming

@product_id = 123
@section_id = 7
@type_id = 12

Both will produce:

SELECT 
  products.* 
FROM 
  products
WHERE 
  products.id != 123
  AND products.init_time <= [YOUR INIT TIME]
  AND (products.section_id = 7 OR products.type_id = 12)

Upvotes: 3

Viktor Ivliiev
Viktor Ivliiev

Reputation: 1334

I agree with the above explanation of the query, but I would prefer a more compact query:

scope = Products.where(init_time: ..@your_time).where.not(id: @product_id)
scope.where(section_id: @section_id).or(scope.where(type_id: @type_id))

Upvotes: 1

Related Questions