Custom rails has_many association (через массив pg)
Итак, в основном я хотел бы знать, существует ли какой-то общий подход для определения собственных типов ассоциаций.
Некоторые подробности:
У меня есть модель conversations
, у которой есть столбец массива PG user_ids
.
Итак, чтобы получить пользовательские разговоры, мне нужно запустить:
select conversations.* from conversations where USER_ID = ANY(conversations.user_ids)
Так как finder_sql
и теперь друзья устарели, мне бы очень хотелось знать, что было бы лучшим способом реализовать эту ассоциацию псевдо-has_many?
В настоящее время я просто использую такие методы, как:
def conversations
Conversation.where("#{id} = ANY (conversations.users)")
end
Итак, в основном я собираюсь реализовать свой собственный ActiveRecord::Associations::CollectionAssociation
и хотел бы знать, есть ли хорошие ссылки или если вы можете посоветовать, где начать с
Ответы
Ответ 1
Как насчет:
Conversation.user.select{ |conversation| conversation.user_ids.include?(params[:id])
Учитывая, что столбец user_ids сериализуется, и текущий идентификатор пользователя передается параметрами [: id]
Основной подход заключается в том, что если у вас есть массив, вы можете проверить, есть ли у него что-то внутри с .include? (что-то). Думая об этом, вы можете использовать метод select для фактического выбора объектов (в этом случае пользователей), имеющих свои идентификаторы внутри этого массива с помощью метода include. Мне ясно?
Скажите, если это сработало...
Ответ 2
Я думаю, вы можете просто поместить код метода в отношение:
has_many :conversations, ->(user) { where("#{user.id} = ANY (conversations.users)") }
В конце концов, это должно быть одно и то же. Ваш метод возвращает отношение, к которому вы можете подключиться. Другой альтернативой может быть что-то вроде:
has_many :conversations, -> { where('users.id IN conversations.users') }
Может потребоваться некоторый финал. Есть ли причина, по которой вы не можете добавить новую таблицу соединений? Идеальным было бы перенести это в таблицу conversations_users
. Затем вы можете присоединиться к таблице и использовать ограничения внешнего ключа.
Ответ 3
Вы должны реструктурировать его в справочную таблицу, в которой он хранит разговор_ид и идентификатор_пользователя, после чего вы можете использовать его в соответствии с рекомендациями Rails (https://guides.rubyonrails.org/association_basics.html#the-has-many-through -ассоциация)
Если вы все еще хотите сохранить эту структуру, я предлагаю:
User.where(id: conversion.user_ids)
(преобразование является экземпляром таблицы бесед)
Ответ 4
Я предлагаю нормализовать вашу модель, чтобы иметь другую таблицу, которая поддерживает отношения между пользователями и разговорами, например, создавая такую модель, как
UsersConversation
и ваши отношения будут
class User < ApplicationRecord
has_many :users_conversations, :dependent => :destroy
has_many :conversations, :through => :users_conversations
end
class Conversation < ApplicationRecord
has_many :users_conversations, :dependent => :destroy
has_many :users, :through => :users_conversations
end
Тогда вы можете легко сделать
#users for each specific conversation
@users = Conversation.find(1).users
#conversations for each specific user
@conversations = User.find(1).conversations
Если вы не хотите сохранить тот же путь или массив, вы можете сделать это как
@users = User.where(:id => Conversation.find(1).user_ids)
если user_ids хранится в виде массива, как [1,10,20], значит, он будет работать нормально и вернет пользователей