LoginSignup
27
26

More than 5 years have passed since last update.

acts-as-taggable-onでオーナーを設定してタグを登録する

Last updated at Posted at 2014-10-16

Railsでそれらしくタグが作れるgem「acts-as-taggable-on」のご紹介。

今回はタグをオーナーを設定して作る方法を紹介します。オーナーの設定は「ユーザーがお気に入りの記事をタグで分類」みたいなときに使うと便利です。本家のドキュメントにも記載されているのですが、特にtaggingについての説明が不十分と感じたので、その辺を盛り込みながら説明していまきす。

acts-as-taggable-onの登場人物4名

  1. tag: タグの本体
  2. taggable: タグの対象(ニコニコ動画であれば動画)
  3. tagger: タグのオーナー(タグを付けた人)
  4. tagging: tag, taggable, taggerのリレーションモデル
タグの対象(taggable)の設定。モデルに記載。
blog.rb
class Blog < ActiveRecord::Base
  acts_as_taggable #「acts_as_taggable_on :tags」と同じ
end
タグのオーナー(tagger)の設定。モデルに記載。
user.rb
class User < ActiveRecord::Base
  acts_as_tagger
end

タグの作成と削除

タグの作成と削除について共通する点なんですが、公式のドキュメントで紹介されている方法通りに単純に行うと、タグの「追加」ではなく「置き換え」になってしまいます。

Ruby
@some_user.tag(@some_photo, :with => "paris, normandy", :on => :locations, :skip_save => true)
@some_photo.owner_tags_on(@some_user,:tags) # => ["paris", "normandy"]
@some_user.tag(@some_photo, :with => "練馬", :on => :locations, :skip_save => true)
@some_photo.owner_tags_on(@some_user,:tags) # => ["練馬"] 

上のコードだと「練馬」に書き換えられている。
そこで、一度taggerとtaggableと関連付けられたtag_listを呼び出し、addメソッドとremoveメソッドで追加、削除の処理をしたうえで、tagメソッドで状態を保存するという手順を紹介します(tagメソッド内でsaveが呼ばれている)。
つまり、

1.既存のタグリストの取り出し
2.既存のタグリストに新規タグの追加(この時点では保存されていない)
3.「既存タグ+新規タグ」のタグリストを保存

という流れ。

タグの作成手順

タグ本体の作成とリレーション(タグ、対象、オーナー)の構築を目指します。

Ruby
tag_list = blog.tags_from(user) #一度 ActsAsTaggableOn::TagListを呼ぶ
tag_list.add('hoge')
user.tag(blog, with: tag_list, on: :tags)
タグの削除手順
Ruby
tag_list = blog.tags_from(user)
tag_list.remove('hoge')
self.tag(blog, with: tag_list, on: :tags)

削除手順で特筆すべきなのは、この手順で行うとtaggingの削除とtaggings_countのデクリメントが行われている点です。単純にリレーションモデルであるtaggingを引っ張って来て削除しても良いのですが、その場合、tagのtaggings_countは反映されません。タグクラウドが多分使えなくなります。

タグの表示(view)

taggerのowner_tags_onメソッドの返り値は「ActiveRecord::AssociationRelation」なので、よくある感じに表示していきます

Ruby
<% blog.owner_tags_on(current_user, :tags).each do |tag| %>
  <%= tag.name %>
<% end %>
タグ(tag, tagging)の取得
Ruby
ActsAsTaggableOn::Tag.find(:id)
ActsAsTaggableOn::Tagging.find(:id).tag # tagging.tag
blog.tags
blog.taggings #タグではなく、tagging
オーナーの取得
Ruby
ActsAsTaggableOn::Tagging.find(:id).tagger
tagging.tagger
タグの対象の取得
Ruby
ActsAsTaggableOn::Tagging.find(:id).taggable
tagging.taggable

以上です。
個人的にオーナーを設定するなら、taggingを取得して操作すると捗ると思います。

27
26
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
27
26