タグの管理にmbleigh/acts-as-taggable-on を使っています。 非常に使いやすくて重宝しているのですが、一部のタグのみ他のテーブルと関連づけしたかったので 拡張してみました。
やりたいこと
schema.rb
acts-as-taggable-on を使うと以下のようなテーブルが作成されます。
create_table "tags", force: :cascade do |t| t.string "name" t.integer "taggings_count", default: 0 t.index ["name"], name: "index_tags_on_name", unique: true end
データとしては以下のような感じです。
id=1,2 はカテゴリーですが、id=3 は人物です。
別途、人物を管理するpeopleテーブルを保有しているとすると、
このテーブルとのreferenceを付与するだけで、「通常のタグ一覧」と「人物一覧」が簡単に取り出せます。
id | name | taggings_count |
---|---|---|
1 | アート | 10 |
2 | 歴史 | 20 |
3 | ジェイミー・ヴァーディ | 3 |
referenceを追加すると以下のようなイメージです。
id | name | taggings_count | person_id |
---|---|---|---|
1 | アート | 10 | null |
2 | 歴史 | 20 | null |
3 | ジェイミー・ヴァーディ | 3 | 100 |
やり方
$ rails g migration AddPersonRefToTags person:references # migration file class AddPersonRefToTags < ActiveRecord::Migration[5.0] def change add_reference :tags, :person, foreign_key: true end end
config/initializers/acts_as_taggable_on.rb
ActsAsTaggableOn::Tag.class_eval do belongs_to :person end
model
point は class_name で ActsAsTaggableOn::Tag を指定すること。
class Person < ApplicationRecord has_one :tag, class_name: "ActsAsTaggableOn::Tag" end
データ抽出
記事にタグ付けされたタグの一覧と、人物タグの一覧を取り出します。(Articleにタグ付けをできるようにするのは、acts_as_taggable_on の基本機能なのでここでは割愛)
pointは、acts_as_taggable_on利用時にtags_on というメソッドが提供されるのですが、この引数に condisions が渡せるので以下のようにすれば良いです。
acts_as_taggable_on 親切設計ですね!
@tags = Article.tags_on(:tags, conditions: { person_id: nil }) @people = Article.tags_on(:tags, conditions: "person_id is not null")
あとは、has_one / belongs_to を設定しているので、各モデルのオブジェクトから辿ることができます。