4/27/2007

acts_as_taggable Plugin 使用方式

Tag 似乎是目前所有Web2.0網站所必備的功能,也有人這樣講「沒有 Tag 就不是 Web 2.0 的網站」。雖然綜觀 Web 2.0 的定義,跟 tag 似乎一點關係都沒有 XD ,不過這完全不要緊,tag 不管是不是 Web 2.0,他對於「歸類」這檔事所帶來的影響是跟「分類」一樣重大的。

Rails 上面要實踐 tag 功能最簡單的就是使用 acts_as_taggable 來做,說到這個 acts_as_taggable 可能會令人有點 confuse,他分成 Plugin 版本,跟 Gem 版本的。兩者實做方式不太一樣, Plugin 版本跟 Gem 版本最大的不同呢,就是 Plugin 版本 acts_as_taggable 他是使用兩個 table 就可以表示許多個 Model 的 tag,你不需要使用多個 table 來表示不同 Model 的 Tag ,再這一點來看,的確是一個不錯的設計,而 GEM 版本的 acts_as_taggable 你必須每個 Model 的都新增一個 table 來表示 tag。也因為設計哲學上面的不同,也有投票來投到底那個比較好。

我們這裡先介紹 Plugin。要先注意到的,act_as_taggable plugin 是depend on Rails 1.1 以上的,所以你必須使用 Rails 1.1 以上的版本。

安裝 acts_as_taggable

script/plugin install acts_as_taggable

建立相關 table

script/generate migration add_tag_support

在 db/migrate/ 檔案裡面這樣寫

class AddTagSupport < ActiveRecord::Migration
def self.up
#Table for your Tags
create_table :tags do |t|
t.column :name, :string
end

create_table :taggings do |t|
t.column :tag_id, :integer
#id of tagged object
t.column :taggable_id, :integer
#type of object tagged
t.column :taggable_type, :string
end

# Index your tags/taggings
add_index :tags, :name
add_index :taggings, [:tag_id, :taggable_id, :taggable_type]
end

def self.down
drop_table :taggings
drop_table :tags
end
end
然後打入

rake migrate

建立相關 table。

設定 Model

設定方式沒有比這個更簡單了,就是在你要下 tag 的 Model 寫入
class ModelName < ActiveRecord::Base
acts_as_taggable
end
即可。

開始使用

下 tag

如果要對其中一個 Model 物件下 tag ,tag 內容是 'abc def ghi',代表這是一個字串,每個 tag pattern 用空白隔開。那我們就可以這樣下 tag
obj.tag_with( 'abc def ghi')
取出這個 Model 所有的 tag

如果,要取出這個 Model 物件下面的 tag,那就
obj.tags
這是一個 tag 的 array ,裡面每個東西都是一個 tag 物件,如果想要取出這個 tag array 的每個 tag name,就這樣用
obj.tags.each { |tag| puts tag.name }
即可。

尋找同一個 tag 的所有 entry

如果要搜尋這個 Model 底下所有下這個 tag 的 entry,就這樣使用
obj.find_tagged_with('abc')
他會回傳同一個 Model array,裡面是有下這個 tag 的 Model 物件。

覆蓋掉 tag

如果想用新的 tag ,就直接用 tag_with 覆蓋掉即可
obj.tag_with('new tag')
即可

刪除其中一個 tag

只想刪除掉其中一個 tag ,那就用 ActiveRecord 裡面的 destroy 即可,下面例子就是刪除 tag id 等於 1的 tag ,但是不刪除其他 tag
obj.tags.each do |tag|
tag.destroy if tag.id == 1
end

這樣即可。

5 則留言:

小影 提到...

原來有這種便利的 plugin ,獲益良多!謝謝介紹。

winson 提到...

取出tag不需要這麼麻煩:

obj.tags.each { |tag| puts tag.name }

只要這樣就行:

obj.tag_list

這樣應該比較容易一點。

thegiive 提到...

可是 tag_list 取出來的是 String,這個當我們要對每個 tag 做點手腳之前,還得 a.tags_list.split ,感覺怪怪的

winson 提到...

恩,tag_list好處是如果你要取出來就是用空格區分組好的String,那就直接拿來用。

比如要改成",",當然要自己用你那樣obj.tags.each {blahblah}去組。

iceskysl 提到...

能不能同时记录 使用该tag的modle实例的个数,比如使用了rails这个tag的post的个数?
还没来得及细看~