Ответ 1
Чтобы создать полиморфный has_many: через, вы должны сначала создать свои модели. Мы будем использовать "Аргумент", "Категория" и "Тег", где "Тег" - это модель объединения, а статья - один из многих объектов, которые могут быть "помечены" категорией.
Сначала вы создаете свои модели "Article" и "Category". Это основные модели, которые пока не требуют особого внимания:
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_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". Когда вы уничтожаете связанный объект, он также уничтожит ссылку. Это гарантирует, что нет плохих или мертвых ссылок. Вот почему мы используем ': dependent = > : destroy'
2) При настройке нашей модели "Article", которая является одной из наших "taggable" моделей, ее необходимо связать, используя: as. Так как в предыдущем примере мы использовали 'taggable_type' и 'taggable_id', мы используем: as = > : taggable. Это помогает рельсам знать, как сохранить значения в базе данных.
3) При привязке категорий к статьям мы используем: has_many: articles,: through = > : tags,: source = > : taggable,: source_type = > 'Article' Это говорит модели категории, что у нее должно быть много: статьи через: теги. Источник: taggable, по той же причине, что и выше. Тип источника - "Статья", потому что модель автоматически установит taggable_type на свое имя.