Создание отношения многие ко многим в Rails - PullRequest
62 голосов
/ 25 февраля 2011

Это упрощенный пример того, чего я пытаюсь достичь, я относительно новичок в Rails и изо всех сил пытаюсь разобраться в отношениях между моделями.

У меня есть две модели, Userмодель и модель Category.Пользователь может быть связан со многими категориями.Определенная категория может появиться в списке категорий для многих пользователей.Если определенная категория удалена, это должно быть отражено в списке категорий для пользователя.

В этом примере:

Моя Categories таблица содержит пять категорий:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| ID | Name                       |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| 1  | Sports                     | 
| 2  | News                       |
| 3  | Entertainment              |
| 4  | Technology                 |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Моя Users таблица содержит двух пользователей:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| ID | Name                       |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| 1  | UserA                      | 
| 2  | UserB                      |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Пользователь A может выбрать Спорт и Технологии в качестве своих категорий

Пользователь B может выбрать Новости, Спорт и Развлечения

Спортивная категория удалена, списки категорий UserA и UserB отражают удаление

Я играл с созданием таблицы UserCategories, которая содержит идентификаторы как категории, так и пользователя.Это сработало, я мог искать имена категорий, но я не мог заставить работать каскадное удаление, и все решение казалось неправильным.

Примеры использования функций own_to и has_many, которые я нашелкажется, обсуждают отображение отношений один-к-одному.Например, комментарии к сообщению в блоге.

  • Как вы представляете это отношение «многие ко многим», используя встроенную функциональность Rails?
  • Является ли использование отдельной таблицы между этими двумя жизнеспособным решением при использовании Rails?

Ответы [ 3 ]

134 голосов
/ 25 февраля 2011

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

http://guides.rubyonrails.org/association_basics.html#the-has-and-belongs-to-many-association

В итоге вы получите что-то вроде этого:

# app/models/category.rb
class Category < ActiveRecord::Base
  has_and_belongs_to_many :users
end

# app/models/user.rb
class User < ActiveRecord::Base
  has_and_belongs_to_many :categories
end

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

Создайте миграцию из CLI следующим образом:

bin/rails g migration CreateCategoriesUsersJoinTable

Затем откройте ее и отредактируйте так, чтобы она соответствовала:

Для Rails 4.0.2+ (включая Rails 5.2):

def change
  # This is enough; you don't need to worry about order
  create_join_table :categories, :users

  # If you want to add an index for faster querying through this join:
  create_join_table :categories, :users do |t|
    t.index :category_id
    t.index :user_id
  end
end

Rails <4.0.2: </h3> def self.up # Model names in alphabetical order (e.g. a_b) create_table :categories_users, :id => false do |t| t.integer :category_id t.integer :user_id end add_index :categories_users, [:category_id, :user_id] end def self.down drop_table :categories_users end Запустив миграцию, вы сможете подключать категории и пользователей со всеми удобными аксессорами, которые вы используете.используется для: User.categories #=> [<Category @name="Sports">, ...] Category.users #=> [<User @name="UserA">, ...] User.categories.empty?

1 голос
/ 10 апреля 2019

Самым популярным является «Монотранзитивная ассоциация», вы можете сделать это:

class Book < ApplicationRecord
  has_many :book_author
  has_many :author, through: :book_author
end

# in between
class BookAuthor < ApplicationRecord
  belongs_to :book
  belongs_to :author
end

class Author < ApplicationRecord
  has_many :book_author
  has_many :book, through: :book_author
end

has_many: через ассоциацию часто используется, чтобы установить многие ко многим связь с другой моделью. Эта связь указывает на то, что декларируемая модель может быть сопоставлена ​​с ноль или более экземпляров другого модель, переходя к третьей модели. Например, рассмотрим медицинская практика, где пациенты назначают прием к врачу. Ссылка: https://guides.rubyonrails.org/association_basics.html#the-has-many-through-association

0 голосов
/ 22 января 2019

Просто дополняю ответ Coreyward выше: Если у вас уже есть модель с отношением belongs_to, has_many и вы хотите создать новое отношение has_and_belongs_to_many с использованием той же таблицы, вам необходимо:

rails g migration CreateJoinTableUsersCategories users categories

Тогда

rake db:migrate

После этого вам нужно будет определить ваши отношения:

User.rb:

class Region < ApplicationRecord
  has_and_belongs_to_many :categories
end

Category.rb

class Facility < ApplicationRecord
  has_and_belongs_to_many :users
end

Чтобы заполнить новую таблицу соединений старыми данными, вам потребуется в консоли:

User.all.find_each do |u|
  Category.where(user_id: u.id).find_each do |c|
    u.categories <<  c
  end
end

Вы можете либо оставить столбец user_id и столбец category_id в таблицах категорий и пользователей, либо создать миграцию для его удаления.

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