2014-02-19 5 views
2

Я пытаюсь выполнить поиск Rails на основе текстового поля сериализованного массива (Postgres, если это имеет значение). Итак:Rails поиск по серийному массиву

class Foo < ActiveRecord::Base 
    serialize :arr, Array 
end 

Тогда:

> f = Foo.create!(arr: [[1, 2], [3, 4]]) 
=> #<Foo id: 1, arr: [[1, 2], [3, 4]]> 
> f.arr 
=> [[1, 2], [3, 4]] 

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

> Foo.where(arr: [[1, 2], [3, 4]]) 
=> ActiveRecord::StatementInvalid Exception: PG::UndefinedFunction: ERROR: operator does not exist: text = integer 
    "foos"."arr" IN (1, 2, ... 
       ^
    HINT: No operator matches the given name and argument type(s). You might need to add explicit type casts. 

Кажется Rails пытается преобразовать его в запрос IN. Неважно, мы знаем, что Rails сериализуется с Yaml (или мы?). Так давайте попробуем:

> Foo.where(arr: [[1, 2], [3, 4]].to_yaml) 
=> #<ActiveRecord::Relation []> 

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

Есть ли стандартный способ поиска модели в Rails на основе сериализованного атрибута? (Должен ли я просто сериализоваться с чем-то, что не является Ямлом?) Большое спасибо!

+1

Ugh. Почему бы вам не использовать поддержку встроенного массива PostgreSQL? Затем вы можете также использовать поддержку индексирования массива. –

+0

Потому что мне нужно хранить многомерные массивы неквадратных размеров, размеры которых меняются. Я понимаю, что Postgres не поддерживает это, но определенно дайте мне знать, если это произойдет. В любом случае, я не уверен, что Rails будет вести себя корректно в этом случае. – JacobEvelyn

+0

Подтверждено, что это не вариант: 'PG :: InvalidTextRepresentation: ERROR: многомерные массивы должны иметь выражения массива с соответствующими размерами – JacobEvelyn

ответ

0

Решение Я использую сейчас (определенно открыты для других подходов!), Чтобы заставить Rails сериализации с чем-то другим, чем YAML, чтобы строковых запросов:

class Foo < ActiveRecord::Base 
    serialize :arr, SerializedArray 

    def self.find_by_arr 
    self.where(arr: SerializedArray.dump(arr)).take 
    end 
end 

class SerializedArray 
    def self.load(arr) 
    arr ? JSON.load(arr) : nil 
    end 

    def self.dump(arr) 
    arr ? JSON.dump(arr) : nil 
    end 
end 

Это немного Janky в что я должен запросить с пользовательским find_by_arr, но он работает.

(Редактирование: удалены примеры кода примера.)

Смежные вопросы