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
Другие вопросы по тегам