Ruby + Sequel - сериализация массива в запрос текстового массива
У меня есть массив фильтров в приложении ruby, который делает необработанный SQL-запрос к соединению Postgres. Я пытаюсь выяснить, как я могу сериализовать этот массив в нечто, способное на запрос,
то есть: SELECT * FROM data WHERE strings IN #{strings_array}
Я не могу найти никаких ресурсов для этого. Как правильно сериализовать этот запрос?
Редактировать: я в конечном итоге выяснить:
query = ''
arr.each_with_index { |e, i|
if i == arr.length - 1
query += "#{e}"
else
query += "#{e},"
end
}
затем
" AND column @> ('{#{query}}')"
Но должен быть менее многословный путь, нет?
3 ответа
Вы говорите, что используете Sequel. Сиквел может выполнить этот вид запроса автоматически:
DB[:data].where(strings: ["my", "array", "of", "strings"])
# => #<Sequel::Postgres::Dataset: "SELECT * FROM \"data\" WHERE (\"strings\" IN ('my', 'array', 'of', 'strings'))">
Создание SQL-запросов "вручную" рискованно, особенно если вы имеете дело с данными, поступающими от пользователей.
Это может быть менее многословным, если вы используете join
метод как это:
# I presume arr contains an array that you want serialize
strings_array = "'#{arr.join("','")}'"
query = "SELECT * FROM data WHERE strings IN #{strings_array}"
Когда вы научитесь знать ORM (в данном случае Activerecord), вы не будете создавать SQL вручную или полуавтоматически, как вы это делаете. Возьмите этот пример. Он создает соединение с базой данных (в нашем случае Oracle), отображает таблицу в класс Ruby и предоставляет все виды методов манипуляции этому классу. В этом примере я использую два параметра where, один с хэшем в качестве фильтра и один с небольшим количеством SQL. Результатом будет SQL, который автоматически генерируется и выполняется, когда вы что-то с ним делаете (используйте каждый в этом случае).
require 'active_record'
ActiveRecord::Base.establish_connection(
:adapter => 'oracle_enhanced',
:database => "(DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (COMMUNITY = ORATCP.world)(PROTOCOL = TCP)(Host = server.domain)(Port = 9999)))(CONNECT_DATA = (SID = SID_ID)))",
:username => 'user',
:password => 'password'
)
class Member < ActiveRecord::Base
self.table_name = 'my_table'
end
Member.where(country: 'Belgium').where("'gender = 'M'").each do |member|
p member
end