Модель Rails, принадлежит многим

Мне трудно понять, как связать одну из моих моделей с несколькими другими.

Как сейчас, у меня есть:

class ModelA < ActiveRecord::Base
  has_many :model_b
end

class ModelB < ActiveRecord::Base
  belongs_to :model_a
end

Однако... ModelB должен принадлежать не только одному экземпляру ModelA, но, возможно, трем. Я знаю, что есть has_many :through, но я не уверен, как это будет работать в этом случае. КАЖДЫЙ экземпляр ModelA всегда будет иметь ровно три экземпляра ModelB. Но, как было сказано ранее, ModelB может принадлежать более чем одному экземпляру ModelA.


person ardavis    schedule 09.12.2010    source источник


Ответы (2)


Отношения «многие ко многим» в рельсах не используют belongs_to. Вместо этого вы хотите использовать один из нескольких вариантов. Первый has_and_belongs_to_many:

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

# app/models/item.rb
class Item < ActiveRecord::Base
  has_and_belongs_to_many :categories
end

И вам нужно будет добавить дополнительную таблицу соединений в вашу базу данных с такой миграцией:

class AddCategoriesItems < ActiveRecord::Migration
  def self.up
    create_table :categories_items, :id => false do |t|
      t.integer :category_id
      t.integer :item_id
    end
  end

  def self.down
    drop_table :categories_items
  end
end

Вы можете видеть, что имя соединяемой таблицы представляет собой комбинацию имен двух других таблиц. Таблицы должны быть упомянуты в алфавитном порядке, как указано выше, и :id => false должен быть там, так как нам не нужен первичный ключ в этой таблице. Это нарушит ассоциацию рельсов.

Есть еще один, более сложный метод, известный как has_many :through, если вам нужно сохранить информацию о самих отношениях. Я написал целую статью с подробным описанием того, как использовать оба метода и когда использовать каждый из них:

Основные связи "многие ко многим" в Rails

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

person Jaime Bellmyer    schedule 09.12.2010
comment
это было действительно полезно! Одним из полезных дополнений было бы несколько примеров того, как мы можем получить доступ к этим отношениям в коде (либо в контроллере, либо в представлении). Спасибо. - person msanjay; 14.02.2014

Это то, что использовал @Jaime Bellmyer

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

# app/models/item.rb
class Item < ActiveRecord::Base
  has_and_belongs_to_many :categories
end

Я бы порекомендовал использовать это

# app/models/category.rb
class Category < ActiveRecord::Base
  has_many :category_items
  has_many :items, :through => :category_items
end

# app/models/item.rb
class Item < ActiveRecord::Base
  has_many :category_items
  has_many :categories, :through => :category_items
end

# app/models/category_items.rb
class CategoryItems < ActiveRecord::Base
  belongs_to :category
  belongs_to :items
end

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

person Rohit    schedule 09.12.2010
comment
означает ли это, что я должен удалить внешний ключ из таблиц, поскольку они связаны таблицей соединений? - person bigpotato; 01.10.2012
comment
да. Вам не нужно хранить внешние ключи в родительских таблицах, их можно хранить в модели соединения. - person Rohit; 03.10.2012
comment
Почему недостаточно просто сказать, что Category has_many :items (элемент принадлежит_ко_многим категориям, но в ActiveRecord этого нет) - person Devin Rhode; 19.10.2014
comment
Кроме того, скажем, вы хотели добавить пользователей, и у них может быть личная библиотека элементов. Будет ли это пользователь has_many :category_items и has_many :items, :through =› :category_items? - person Devin Rhode; 19.10.2014
comment
Наконец, было бы разумно или глупо просто сказать, что User has_one :category, представляя свою библиотеку как собственную категорию? Возможно, вы хотите сделать категорию полиморфной? - person Devin Rhode; 19.10.2014