Чтобы создать полиморфный has_many: through, вы должны сначала создать свои модели.Мы будем использовать «Article», «Category» и «Tag», где «Tag» - это модель соединения, а Article - один из многих объектов, которые можно «пометить» категорией.
Сначала вы создаетеваши модели «Статья» и «Категория».Это основные модели, которые пока не требуют особого внимания:
rails g model Article name:string
rails g model Category name:string
Теперь мы создадим нашу полиморфную таблицу соединений:
rails g model Tag taggable_id:integer taggable_type:string category_id:integer
Таблица соединений объединяетсядве таблицы, или в нашем случае одна таблица для многих других с помощью полиморфного поведения.Это делается путем сохранения идентификатора из двух отдельных таблиц.Это создает ссылку.Наша таблица «Category» всегда будет «Category», поэтому мы добавляем «category_id».Таблицы, на которые он ссылается, могут изменяться, поэтому мы добавляем элемент taggable_id, который содержит идентификатор любого тегируемого элемента.Затем мы используем «taggable_type», чтобы завершить ссылку, позволяющую ссылке знать, с чем она связана, например, статью.
Теперь нам нужно настроить наши модели:
class Article < ActiveRecord::Base
has_many :tags, :as => :taggable, :dependent => :destroy
has_many :categories, :through => :tags
end
class Category < ActiveRecord::Base
has_many :tags, :dependent => :destroy
has_many :articles, :through => :tags, :source => :taggable, :source_type => 'Article'
end
class Tag < ActiveRecord::Base
belongs_to :taggable, :polymorphic => true
belongs_to :category
end
После этого настройте базу данных, используя:
rake db:migrate
Вот и все!Теперь вы можете настроить свою базу данных с реальными данными:
Category.create :name => "Food"
Article.create :name => "Picking the right restaurant."
Article.create :name => "The perfect cherry pie!"
Article.create :name => "Foods to avoid when in a hurry!"
Category.create :name => "Kitchen"
Article.create :name => "The buyers guide to great refrigeration units."
Article.create :name => "The best stove for your money."
Category.create :name => "Beverages"
Article.create :name => "How to: Make your own soda."
Article.create :name => "How to: Fermenting fruit."
Теперь у вас есть несколько категорий и различных статей.Однако они не классифицированы по тегам.Итак, нам нужно сделать это:
a = Tag.new
a.taggable = Article.find_by_name("Picking the right restaurant.")
a.category = Category.find_by_name("Food")
a.save
Затем вы можете повторить это для каждого, это свяжет ваши категории и статьи.После этого вы сможете получить доступ к категориям каждой статьи и статьям каждой категории:
Article.first.categories
Category.first.articles
Примечания:
1) Всякий раз, когда вы хотите удалить элемент, связанный ссылкойМодель обязательно используйте «уничтожить».Когда вы уничтожаете связанный объект, он также уничтожает ссылку.Это гарантирует, что нет плохих или неработающих ссылок.Вот почему мы используем ': зависимый =>: destroy'
2) При настройке нашей модели Article, которая является одной из наших моделей taggable, она должна быть связана, используя: as.Так как в предыдущем примере мы использовали «taggable_type» и «taggable_id», мы используем: as =>: taggable.Это помогает рельсам знать, как хранить значения в базе данных.
3) При связывании категорий со статьями мы используем: has_many: article,: through =>: теги,: source =>: taggable,: source_type=> 'Article' Это говорит модели категории, что она должна иметь много тегов: article through:.Источник: taggable, по той же причине, что и выше.Тип источника - «Article», потому что модель автоматически установит taggable_type на свое имя.