Rails .where для массива не работает должным образом - PullRequest
1 голос
/ 06 августа 2020

Я ищу записи, где @messages.visiblity (массив) соответствует current_user.id с помощью этого простого вызова:

@messages = Message.where(visibility: [current_user.id])

Однако он ничего не возвращает! Так обидно. Вот пример сообщения, которое должно быть в этой коллекции @messages:

2.3.3 :007 > Message.last
  Message Load (0.4ms)  SELECT  "messages".* FROM "messages" ORDER BY "messages"."id" DESC LIMIT $1  [["LIMIT", 1]]
 => #<Message id: 35, subject: "hello!", content: "can you see this", user_id: 40, created_at: "2020-08-06 03:22:59", updated_at: "2020-08-06 03:22:59", visibility: ["55", "49"], active: true> 

Здесь текущий user.id - 49.

Это сообщение не будет добавляться в @message instance, пока не будут выполнены все user.id, а не только один id, равный 49. Если я сделаю это, запись будет добавлена ​​к @messages:

@messages = Message.where(visibility: ["55", current_user.id]) #DON'T WANT THIS!

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

Вот моя схема сообщения:

create_table "messages", force: :cascade do |t|
    t.string "subject"
    t.string "content"
    t.bigint "user_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.text "visibility", default: [], array: true

и вот форма, которая собирает данные:

<%= form_with(model: @message) do |form| %>
<%= form.check_box(:visibility, {:multiple => true}, u.id, nil) %> - <%= u.email %>
<% end %>

Ответы [ 3 ]

1 голос
/ 06 августа 2020

это должно работать:

Message.where('visibility @> ARRAY[?]::string[]', ["49"])

или это:

Message.where("'49' = ANY(visibility)")
0 голосов
/ 06 августа 2020

Вы также можете использовать это

Message.where("visibility && array[?]",current_user.id.to_s)

Я преобразую current_user.id в STRING, потому что visibility - это STRING ARRAY и его нельзя сравнивать с целочисленным значением ID

Вы также можете указать это, как показано ниже:

Message.where("visibility && array[?]",[current_user.id.to_s])

Или с массивом нескольких значений, как показано ниже:

Message.where("visibility && array[?]",['55','49'])

Несколько значений сравниваются как операция AND.

0 голосов
/ 06 августа 2020

Ниже описан способ, как мы можем сделать это в базах данных, независимо от того, поддерживает ли база данных массив или нет.

Существует образец того, как сериализованный массив сохраняется в базе данных. ["55", "49"] будет сохранено как "55"\n "49"\n (или 55\n 49\n)

Таким образом, вы можете искать, используя LIKE оператор

@messages = Message.where("visibility LIKE ?", "% #{current_user.id}\n%")

OR

@messages = Message.where("visibility LIKE ?", '% "#{current_user.id}"\n%')

Примечание. Между % и # в % #{current_user.id}

есть пробел.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...