2015-10-02 4 views
27

У меня есть модель User и модель Chats. Интуитивно несколько человек будут принадлежать к одной и той же группе чатов в любое время, и каждый человек может иметь много групп чатов. Поэтому группа чата должна принадлежать нескольким user_id.От многих до многих отношений в Ecto

Моя схема для чат-группы и пользователей являются:

schema "chatGroups" do 
    field :name, :string 
    has_many :messages, Message 
    belongs_to :user, User 

    timestamps 
end 

schema "users" do 
    field :name, :string 
    has_many :chatGroups, ChatGroup 

    timestamps 
end 

Любые предложения, как справиться с этим?

ответ

27

Это старый вопрос, и ранее принятый ответ уже не был де-факто.

Ecto теперь поддерживает HABTM или многие из многих ассоциаций.

https://hexdocs.pm/ecto/Ecto.Schema.html#many_to_many/3

many_to_many :users, MyApp.User, join_through: "chat_group_users" 
+1

Это должен быть предпочтительный способ сделать многие для многих, используя ecto – user2290820

34

Ecto имеет поддержку для has_many/3 через отношения. Это предполагает создание промежуточной таблицы между вашими чат-группами и вашими пользователями.

Вы можете сделать это с помощью следующей схемы:

chat_group.ex:

schema "chat_groups" do 
    has_many :chat_group_users, MyApp.ChatGroupUser 
    has_many :users, through: [:chat_group_users, :user] 
end 

chat_group_user.ex:

schema "chat_group_users" do 
    belongs_to :chat_group, MyApp.ChatGroup 
    belongs_to :user, MyApp.User 
end 

Вы можете также сделать Ассоциации по-другому:

пользователь.ex:

schema "users" do 
    has_many :chat_group_users, MyApp.ChatGroupUsers 
    has_many :chats, through: [:chat_group_users, :chat] 
end 

Это позволяет делать такие вещи, как:

Repo.get(Chat, 1) |> Repo.preload(:users) 

Это загрузит пользователей для вашей модели чата и заполнить :user ключ со значением.

+2

штопать. Я надеялся на решение, которое не требует создания таблицы соединений. Ну что ж. Спасибо за разъяснения! Я проведу его в этот уик-энд и соглашусь, как только я это сделаю. –

+1

Это работает, за исключением синтаксиса для меня было: 'через: [: chat_group_users,: chat]' (обратите внимание на двоеточие перед первым параметром и запятой после этого) –

+0

Chowza, хорошая вещь сделать это явно так что вы можете установить свою таблицу соединений, чтобы иметь ссылку на внешний ключ: delete_all, чтобы таблица соединений очистилась, когда связанные записи удалены. – brightball