Использование необработанных запросов Postgresql в Ruby on Rails

#ruby-on-rails #ruby #postgresql

Вопрос:

Во-первых, я не являюсь носителем английского языка, так что извините меня, если я допущу какие-либо ошибки, связанные с моим письмом.

Я начинаю как разработчик, и мне сказали, что я должен использовать запрос Postgresql для выполнения конкретной задачи в Ruby on Rails. Это и есть запрос:

ПОРЯДОК ПО array_position(МАССИВ[1, 2, 3], spree_products.id)

Цель состоит в том, чтобы показать представление с различными продуктами Spree (возможно, частью «МАССИВ[1,2,3 и т. Д.]») базы данных, упорядоченной таким же образом, как они помещены во входную форму администратора.

В любом случае, мой вопрос гораздо проще.

Я понимаю, что этот запрос является необработанным Postgresql, использующим функцию array_position

https://www.postgresql.org/docs/12/functions-array.html

Я просто хочу знать, как я могу реализовать такого рода необработанные запросы в Rails. Вероятно, это должно быть в файле .rb, но я действительно не понимаю, как, поскольку методы запросов, используемые в Rails (например,. order), гораздо чаще используются (это то, что я обычно использую), но, по-видимому, здесь я должен использовать необработанный Postgresql, смешанный с Rails.

Не могли бы вы привести мне несколько примеров и/или основную документацию, пожалуйста? Я знаю основы обоих языков, но я никогда не смешивал их таким образом, так что, вероятно, это сбивает меня с толку больше всего.

Спасибо вам всем.

Ответ №1:

вы можете создать область и использовать arel функцию обертывания массива array_position

 class Product < ApplicationRecord

  scope :order_ids, ->(arr_ids) {
    order(Arel.sql("array_position(ARRAY#{arr_ids}, id::integer)"))
  }
end
 

теперь вы можете запросить, как показано ниже

 Product.order_ids([3,2,1])
Product.where(active: true).order_ids([3,2,1]).limit(10)
# ...
 

Комментарии:

1. "array_position(ARRAY#{arr_ids}, id::integer)" является уязвимостью для инъекции SQL и должна использоваться только в том случае, если arr_ids это не пользовательский ввод.

2. Это можно решить, добавив ActiveRecord::Base::sanitize_sql(arr_ids) , если возможно, что они являются пользовательским вводом.