ransack icon indicating copy to clipboard operation
ransack copied to clipboard

Custom Ransacker defaults to type = integer when combined with another integer search

Open ideaoforder opened this issue 7 years ago • 3 comments

I have a custom ransacker:

    ransacker :exact_merchandise_item_ids, type: :string do |parent|
      query = "(SELECT GROUP_CONCAT(DISTINCT order_items.item_id ORDER BY order_items.item_id ASC) FROM order_items WHERE order_items.order_id = orders.id)"
      Arel.sql(query)
    end

It works fine by itself:

Order.ransack(exact_merchandise_item_ids_matches:  "123,124").result.to_sql

=> "SELECT `orders`.* FROM `orders`  WHERE ((SELECT GROUP_CONCAT(DISTINCT order_items.item_id ORDER BY order_items.item_id ASC) FROM order_items WHERE order_items.order_id = orders.id) LIKE '123,124')"

But when combined with another search (of any type), it's cast as an integer, for some reason:

Order.ransack(exact_merchandise_item_ids_matches:  "123,124", customer_id_eq: 1).result.to_sql

=> "SELECT `orders`.* FROM `orders` LEFT OUTER JOIN `customers` ON `customers`.`id` = `orders`.`customer_id` WHERE (((SELECT GROUP_CONCAT(DISTINCT order_items.item_id ORDER BY order_items.item_id ASC) FROM order_items WHERE order_items.order_id = orders.id) LIKE 123 AND `customers`.`id` = 1))"

More strangely yet, some other types, like datetime do work. If set type: :datetime, I get:

SELECT `orders`.* FROM `orders` LEFT OUTER JOIN `customers` ON `customers`.`id` = `orders`.`customer_id` WHERE (((SELECT GROUP_CONCAT(DISTINCT order_items.item_id ORDER BY order_items.item_id ASC) FROM order_items WHERE order_items.order_id = orders.id) LIKE '2018-04-19 04:01:23' AND `customers`.`id` = 1))

I'm happy to be told what I'm doing wrong, if anything. Otherwise, if someone can point me to the place in the code to fix this, I'm happy to submit a PR.

ideaoforder avatar Apr 19 '18 15:04 ideaoforder

It's also worth mentioning that the order here matters:

44] pry(main)> Location.ransack(item_id_string_eq: 'AA').result.to_sql 
=> "SELECT `locations`.* FROM `locations`  WHERE CONVERT(locations.item_id, CHAR(8)) = 'AA'"
[45] pry(main)> Location.ransack(warehouse_id_eq: 1, item_id_string_eq: 'AA').result.to_sql 
=> "SELECT `locations`.* FROM `locations`  WHERE ((`locations`.`warehouse_id` = 1 AND CONVERT(locations.item_id, CHAR(8)) = 0))"
[46] pry(main)> Location.ransack(item_id_string_eq: 'AA', warehouse_id: 1).result.to_sql
=> "SELECT `locations`.* FROM `locations`  WHERE CONVERT(locations.item_id, CHAR(8)) = 'AA'"
[47] pry(main)> Location.ransack(item_id_string_eq: 'AA', warehouse_id_eq: 1).result.to_sql
=> "SELECT `locations`.* FROM `locations`  WHERE ((CONVERT(locations.item_id, CHAR(8)) = 'AA' AND `locations`.`warehouse_id` = 1))"

When the ransacker comes first, it works fine.

ideaoforder avatar Sep 11 '18 15:09 ideaoforder

Last strange thing--it's only with with integer columns:

8] pry(main)> Location.ransack(name_eq: 'AA', item_id_string_eq: 'AA').result.to_sql
=> "SELECT `locations`.* FROM `locations`  WHERE ((`locations`.`name` = 'AA' AND CONVERT(locations.item_id, CHAR(8)) = 'AA'))"
[49] pry(main)> Location.ransack(item_id_eq: 'AA', item_id_string_eq: 'AA').result.to_sql
=> "SELECT `locations`.* FROM `locations`  WHERE ((`locations`.`item_id` = 0 AND CONVERT(locations.item_id, CHAR(8)) = 0))"

ideaoforder avatar Sep 11 '18 15:09 ideaoforder

I have a custom ransacker:

    ransacker :exact_merchandise_item_ids, type: :string do |parent|
      query = "(SELECT GROUP_CONCAT(DISTINCT order_items.item_id ORDER BY order_items.item_id ASC) FROM order_items WHERE order_items.order_id = orders.id)"
      Arel.sql(query)
    end

It works fine by itself:

Order.ransack(exact_merchandise_item_ids_matches:  "123,124").result.to_sql

=> "SELECT `orders`.* FROM `orders`  WHERE ((SELECT GROUP_CONCAT(DISTINCT order_items.item_id ORDER BY order_items.item_id ASC) FROM order_items WHERE order_items.order_id = orders.id) LIKE '123,124')"

But when combined with another search (of any type), it's cast as an integer, for some reason:

Order.ransack(exact_merchandise_item_ids_matches:  "123,124", customer_id_eq: 1).result.to_sql

=> "SELECT `orders`.* FROM `orders` LEFT OUTER JOIN `customers` ON `customers`.`id` = `orders`.`customer_id` WHERE (((SELECT GROUP_CONCAT(DISTINCT order_items.item_id ORDER BY order_items.item_id ASC) FROM order_items WHERE order_items.order_id = orders.id) LIKE 123 AND `customers`.`id` = 1))"

More strangely yet, some other types, like datetime do work. If set type: :datetime, I get:

SELECT `orders`.* FROM `orders` LEFT OUTER JOIN `customers` ON `customers`.`id` = `orders`.`customer_id` WHERE (((SELECT GROUP_CONCAT(DISTINCT order_items.item_id ORDER BY order_items.item_id ASC) FROM order_items WHERE order_items.order_id = orders.id) LIKE '2018-04-19 04:01:23' AND `customers`.`id` = 1))

I'm happy to be told what I'm doing wrong, if anything. Otherwise, if someone can point me to the place in the code to fix this, I'm happy to submit a PR.

let me create a pull request on this issue

snawar92 avatar Oct 03 '18 01:10 snawar92