Rails で記事とタグを管理したい場合は、どうしたらよいのか?
解決策
1つの記事に複数のタグがあり、1つのタグに複数の記事があるので、多対多の関連を表現する仕組みのhas_and_belongs_to_manyを使います。
次のステップで処理します。
- 記事モデルを作成する
- タグモデルを作成する
- 記事とタグの関連テーブルを作成する
- 記事モデルにタグモデルを関連付ける
- タグモデルに記事モデルを関連付ける
補足:別の方法として、has_many :throughを使った方法もあります。
ステップ1. 記事モデルを作成する
Articleモデルを生成します。
$ rails generate model Article
マイグレーションファイルに、titleカラムとcontentカラム付きのarticlesテーブルを定義します。
# db/migrate/xxx_create_articles.rb class CreateArticles < ActiveRecord::Migration def change create_table :articles do |t| t.string :title, null: false t.text :content t.timestamps null: false end end end
マイグレーションします。
$ rake db:migrate
ステップ2. タグモデルを作成する
Tagモデルを作成します。
$ rails generate model Tag
マイグレーションファイルに、nameカラム付きのtagsテーブルを定義します。
# db/migrate/xxx_create_tags.rb class CreateTags < ActiveRecord::Migration def change create_table :tags do |t| t.string :name, null: false t.timestamps null: false end end end
マイグレーションします。
$ rake db:migrate
ステップ3. 記事とタグの関連テーブルを作成する
空のマイグレーションファイルを作ります。名前はArticlesテーブルとTagsテーブルの関連テーブルなので、CreateArticlesTagsTableとします。
$ rails generate migration CreateArticlesTagsTable
マイグレーションファイルに、記事テーブルID用のarticle_idカラムと、タグテーブルID用のtag_idカラム付きのarticles_tagsテーブルを定義します。
テーブルの名前は、二つのテーブル名をアンダースコア(_)で区切ったものにします。主キーは不要なので、:id => falseとしています。
# db/migrate/xxx_create_artilces_tags_table.rb class CreateArticlesTagsTable < ActiveRecord::Migration def change create_table :articles_tags, :id => false do |t| t.integer :article_id, null: false t.integer :tag_id, null: false end end end
マイグレーションします。
$ rake db:migrate
ステップ4. 記事モデルにタグモデルを関連付ける
記事モデルファイルを開き、has_and_belongs_to_manyによって、タグモデルとの多対多の関連を宣言します。モデル名は複数形にするようです。
# app/models/article.rb class Article < ActiveRecord::Base has_and_belongs_to_many :tags end
ステップ5. タグモデルに記事モデルを関連付ける
タグモデルファイルを開き、has_and_belongs_to_manyによって、記事モデルとの多対多の関連を宣言します。モデル名は複数形にするようです。
# app/models/tag.rb class Tag < ActiveRecord::Base has_and_belongs_to_many :articles end
これでモデル周りの作成は完了です。
使い方1. 記事とタグを作る
※ ここまでのステップが全て行われていれば、Railsコンソールで実行できます。
$ rails console
記事1, 2 を作ります。
> article1 = Article.create title:"記事1", content:"内容1" > article2 = Article.create title:"記事2", content:"内容2"
タグ1, 2 を作ります。
> tag1 = Tag.create name:"タグ1" > tag2 = Tag.create name:"タグ2"
使い方2. 記事にタグを付ける
使い方1の続き。
記事1にタグ1 と タグ2を付けます。
> article1.tags << tag1 > article1.tags << tag2
!補足注意:同じ記事に対して同じタグを何度でも重複して付けられるので、すでにタグが付いているかを確認した方がベストです。
記事1にタグ1が付いているかを確認するには次のようにします。
> article1.tags.exists? tag1
タグ1がすでに付いていれば true が返ります。付いていないなら false です。
使い方3. 記事に付いてるタグ一覧を取得する
使い方2の続き。
記事1に付いているタグ一覧を取得します。
> article1.tags
タグ名のみ取得するなら次のようにします。
> article1.tags.each do |tag| > p tag.name > end
使い方4. タグが付いてる記事一覧を取得する
使い方3の続き。
タグ1が付いている記事一覧を取得します。
> tag1.articles
使い方5. 記事からタグを1件外す
使い方4の続き。
記事1に付いているタグ1を外します。
> article1.tags.delete tag1
使い方6. 記事からタグを全て外す
使い方5の続き。
記事1に付いているタグを全て外します。
> article1.tags.clear