iThome online | iThome Blog | iThome周刊訂閱

載入中...

twtw

IT邦初學者
9級

[RoR] 小小複雜建置 Social Tagging 社會標籤功能

上一篇 [RoR] 簡單加入 Tag Cloud 標籤雲 功能 只是用最簡單的方式,建置出只有作者本人能下標籤,或者也可以設成,任何人不需登入,也可以下標籤;這些都並沒有記錄是哪個使用者下的標籤,所以還稱不上 Folksonomy ,或說利用這些標籤達到 Social、社群的功用。透過今天的例子,就可建置出像 del.icio.us 的多人標籤機制,達到類似像 Social bookmarking 中的 Social Tagging 的功能。
這一篇應是這一系列中,最複雜的一篇,主要是有關資料庫關聯的運用,但要建置這種 Social Tagging 的功能,相對於其他程式環境所要建置的複雜度,應算是比較簡單了。

del.icio.us 的多人標籤系統,可以把許多人所下的標籤與書籤做連結與結合,是很棒的構思;但要怎麼去處理標籤的資料庫的規畫或運算,想起來有點複雜;在 Tags: Database schemas 這篇文章中,介紹了幾種怎麼去做出像 del.icio.us 的多人多標籤的資料庫規畫的探討

在此利用第9日的 [RoR] 簡單完成分頁功能 中的例子,把聖經的內容,作為 Social Tagging 的對象,可以達到:不同的使用者可以對不同的聖經經文,下不同的標籤,同一經文可以看出哪些使用者下了哪些不同的標籤。



收到書籤:發佈到twitter      
分享時間:2008-10-12 18:50:55
最近更新:2008-10-16 15:03:00

▼ ADVERTISEMENT ▼

分享內容(
9

延伸 be_taggable 的功能
接續 [RoR] 簡單加入 Tag, Tagging 標籤功能 中,安裝 be_taggable 的 plugins 之後,再參考 http://ianli.com/site/HowTo/RailsStarter-BeTaggable 這篇文章的內容來做一些修改,才能夠使 Tag 系統記錄各使用者下了哪些標籤。
新增 /home/ironman/test/lib/be_taggable.rb 內容為:

require_dependency "#{RAILS_ROOT}/vendor/plugins/be_taggable/lib/be_taggable.rb"
module BeTaggable

  module ClassMethods
    # find all rows owned by user
    def find_tagged_by(user_id, options={})
      find(:all, 
           {:select => "DISTINCT m.*",
            :joins => %(as m INNER JOIN #{Tagship.table_name} AS ts ON m.id=ts.model_id
                             INNER JOIN #{Tag.table_name} AS t ON ts.tag_id=t.id),
            :conditions =>["ts.model_type=? and t.user_id=?", name, user_id],
            :limit => 20}.merge(options))
    end

    alias find_all_tagged_by find_tagged_by
    alias find_all_tagged_with find_tagged_with
  end

  module InstanceMethods  
    # create new or overwrite tags, without touching overlapping tags.
    def tag(str, user_id)
      old_tags = tag_names(user_id)
      new_tags = self.class.split_tag_names(str)

      (new_tags - old_tags).each{|tag|
        self.tags << Tag.find_or_create_by_name_and_model_type_and_user_id(tag, self.class.name, user_id)
      }
      (old_tags - new_tags).each{|tag|  
        tag_obj = Tag.find_by_name_and_model_type_and_user_id(tag, self.class.name, user_id)
        self.tags.delete(tag_obj)
        tag_obj.destroy if tag_obj.tagships_count == 1 # cached 1
      }

      update_attribute(:tags_cache, all_tag_names.to_yaml) if respond_to? :tags_cache
    end

    def tag_names(user_id)
      tags = self.tags.find_all_by_user_id(user_id)
      tags.collect{|tag| tag.name}.sort!
    end

    def all_tag_names
      tags.collect { |tag| tag.name }.sort!
    end
  end
end

修改資料庫綱要
如果之前是以 Article 為標籤的目標,先把資料庫回到前一版本 migration
rake db:migrate VERSION=200810xxxx_create_simple_captcha_data
把 20081009xxxx_add_be_taggable.rb 從 db/migrate 的目錄中刪除。
如果之前沒有建過 be_taggable 的話,在裝好 be_taggable 從這邊繼續下去:
執行 script/generate be_taggable_tables Bible
編輯 db/migrate/20081011xxxx_add_be_taggable.rb
將 create_table 之中 加入
      t.column :user_id, :integer, :null => false
# 同時修改 add_column remove_column 的參數為 :bibles
    add_column :bibles, :tags_cache, :string, :default => "--- []"
    remove_column :bibles, :tags_cache

再 rake db:migrate 就可讓資料庫記錄 哪個使用者下什麼標籤的資料。

Console 端測試使用者的標籤功能
編輯 app/models/bible.rb 加入 be_taggable 的字樣,
同時新增一個 app/models/tag.rb
class Tag < ActiveRecord::Base
def self.userid_itemid(userid, itemid, modeltype)
 find_by_sql ["select distinct tags.name from tags inner join tagships on tagships.tag_id = tags.id inner join users on user_id = tags.user_id where tags.user_id = ? and tagships.model_id = ? and tagships.model_type = ?;",userid, itemid, modeltype]
end
end

上述是用來查詢 user 在哪個項目中,下了哪些標籤,需要一些基本的 SQL 語法的基礎,就可以利用 INNER JOIN 的方式,把 tags, tagship, users 三個表格關聯起來,而獲得查詢。
執行 ./scipt/console 測試:
>> b=Bible.find(1)
=> #<Bible id: 1, engs: "Gen", chap: 1, sec: 1, txt: "起初,神創造天地。", engf: "Genesis", chinesef: "創世記", chineses: "創", sengs: "Ge", tags_cache: "--- []">
>> b.tag('創世紀,宇宙論,物種起源',1)
=> true
# 看到 該項目的 tags_cache 已將標籤加入
>> b
=> #<Bible id: 1, engs: "Gen", chap: 1, sec: 1, txt: "起初,神創造天地。", engf: "Genesis", chinesef: "創世記", chineses: "創", sengs: "Ge", tags_cache: "--- \n- !binary |\n  5Ym15LiW57SA\n\n- !binary |\n  5a6H...">
# 查詢 user id 為 1 且 Bible 的項目為 1 的標籤有哪些?
>> Tag.userid_itemid(1,1,'Bible')
=> [#<Tag name: "創世紀">, #<Tag name: "宇宙論">, #<Tag name: "物種起源">]
>>

從以上的操作,可以透過
項目.tag('標籤一,標籤二,標籤三',使用者id)
# 可將 某項目 加上 某使用者 下了哪些標籤 的記錄
Tag.userid_itemid(使用者id,項目id,'該項目所屬的Model')
# 可把 某使用者 在某項目 所下的標籤名稱 給列出來

透過上述的作法,就已把 社會標籤 的最核心的部份,透過這樣子的函數操作就可完成。接下來是如何在網頁上呈獻這些標籤項目。

參考資料:http://ianli.com/site/HowTo/RailsStarter-BeTaggable

[RoR] 小小複雜建置 Social Tagging 社會標籤功能

目前沒有資料

回應

請填寫您的回應,長度限為1,000個字,回應不計點數,也不限使用次數



 

檢舉違規

違規事項:

*補充檢舉理由(可省略),字數不可超過100字

推薦

推薦理由:


*給回答者的鼓勵(可不填),字數不可超過100字

▼ ADVERTISEMENT ▼

熱門標籤

 ccna代考   cisco   crystal   exchange   iscsi   it   java   javascript   linux   m-power   mail   msnlib   msnp15   msnsdk   msn機器人   mysql   nas   oracle   outlook   pmi   pmp   report   sap   server   smartquery   sql   vista   vpn   web   windows   xp   二三事   倍力   倍力資訊   免費軟體   國際專案管理師   報表   專案管理   有話大聲說   活動   省錢   網路   網路儲存   網路管理   網頁設計   資安   資訊安全   防毒軟體   2003   2008