Как я могу использовать Squeel с hstore в Rails

Я хотел бы использовать гем Squeel (на основе Arel) для моего приложения Rails (v 3.2.6). Мой столбец hstore называется properties.

Они отлично работают:

User.where{(firstname == 'Ryan') & (lastname == 'Bates')}
User.where{"properties @> ('male' => '1')"}

Второй пример — это простой запрос Postgres, поскольку Squeel, похоже, не поддерживает функции hstore.

Они не работают:

User.where{"properties @> ('male' => '1')" & firstname == 'Ryan'}
User.where{("properties @> ('male' => '1')") & (firstname == 'Ryan')}

Ошибка:

NoMethodError: undefined method `&' for "properties @> ('male' => '1')":String

Я понимаю ошибку, но не знаю, как обработать мой запрос hstore. Есть ли лучший способ создавать запросы hstore с помощью Squeel или Arel?


person Railsana    schedule 05.09.2012    source источник


Ответы (3)


Squeel поддерживает литералы SQL с помощью обратных кавычек (`).

Что-то вроде следующего может работать:

Person.where{(id == my{@person.id}) & (`preferences @> send_me_junk_email=>yes`)}

При использовании обратных кавычек Squeel опускает уровень абстракции и выполняет SQL напрямую.

http://erniemiller.org/2012/05/30/sql-literals-in-squeel-or-overriding-backticks-in-ruby/

person anthonator    schedule 21.10.2012

Попробуйте использовать гем хранилища hstore, это добавляет поддержку hStore в Sequel.

person CraigKerstiens    schedule 05.09.2012
comment
Спасибо. Похоже, мне нужно перейти на Sequel. - person Railsana; 06.09.2012
comment
Вам не нужен гем сиквела hstore, Sequel поставляется с расширением pg_hstore, которое теперь поддерживает довольно много версий. - person Jeremy Evans; 06.09.2012
comment
Я думаю, вы путаете "Squeel" с "Sequel". ОП спрашивал о Squeel. - person nocache; 13.06.2014

Я только что вник в это. Ответ оказался в этом файле, по сути, вы можете добавить сюда свои собственные операции.

В этом примере используется @> для просмотра массивов PostgreSQL (продемонстрировано в этой презентации).

module Squeel
  module Nodes
    module Operators
      def within *list
        list = "{#{list.map(&:to_s).join(',')}}"
        Operation.new self, :'@>', list
      end
    end
  end
end

После установки этого обезьяньего патча становится возможным следующий оператор Squeel, предполагая, что существует модель Note, которая имеет поле массива tags.

Note.where { tags.within 'first tag', 'second tag' }

Который должен генерировать SQL, который выглядит следующим образом:

"SELECT \"notes\".* FROM \"notes\"  WHERE \"notes\".\"tags\" @> '{first tag,second tag}'"
person ironchamber    schedule 03.01.2014
comment
Ницца! Рассматривали ли вы создание запроса на вытягивание, чтобы внести эту функциональность в Squeel? - person Drew Dara-Abrams; 02.05.2015