iT邦幫忙

DAY 21
0

從想法到快速實作的捷徑:Rails系列 第 21

[ Day 21 ] 文章的分類功能 - (下)

  • 分享至 

  • xImage
  •  

下半部是要介紹我們在現在的blog或是cms系統上很流行的tag功能。

沒有錯,鐵人賽的編輯器也有這個功能。

(坦白說我覺得除了不能預覽還有支援markdown之外,鐵人賽的編輯器不會到難用啊XD)

這裡有分成兩種做法,一種是使用gem,一種是自己刻一個。

第一種當然是快速很多,但是你在遇到問題或是想要客制化的時候還是得去看doc,

否則你會不知道到底發生什麼事情。

第二種自刻,並不是指寫出來的是毫無架構的爛code,

而是參考網路上其他人解法再自己去寫ruby code,比起open source的專案可能沒有那麼包山包海,

但也因為這樣你幾乎能掌握所有的東西,要加東西的話也很簡單。

開始之前

acts-as-taggable-on這個gem遇到一點問題,

不過我還是將使用過程記錄下來,

想要直接看手作部分的可以跳到下方第一部份。

如果你看到下方參考影片的,提醒一下acts-as-taggable-on有做了一些更新,

所以有些指令會跟影片中的不太一樣,

在使用acts-as-taggable-on會遇到一個奇怪的bugs,所以用到一半就中斷了,

如果有興趣一起討論這個問題的可以再說,

想看功能實作的就直接看第一部分就好。

  1. 自己寫tag功能

  • 這個功能其實並不複雜,所以可以直接自己來就好

  • 首先要先建立tag和tagging的model

    rails g model tag name
    rails g model tagging tag:belongs_to article:belongs_to
    rake db:migrate

  • 在post的model裡面加入使用tags的方法

  • 因為tag可以給很多篇posts用、而一篇post也可以有很多個tags,這是一個many_to_many的關係,所以我們需要tagging來做資料表的關聯(這個應該可以另外開一篇說了)

    Tagging

    def self.tagged_with(name)
      Tag.find_by_name!(name).posts
    end
    
    def self.tag_counts
      Tag.select("tags.*, count(taggings.tag_id) as count").
        joins(:taggings).group("taggings.tag_id")
    end
    
    def tag_list
      tags.map(&:name).join(", ")
    end
    
    def tag_list=(names)
      self.tags = names.split(",").map do |n|
        Tag.where(name: n.strip).first_or_create!
      end
    end
    
  • 記得在posts controller裡面設定strong parameter

  • 在index action加入這一段,讓我們借由tag來取得po文

    def index
    if params[:tag]
    @posts = Post.tagged_with(params[:tag])
    else
    @posts = Post.all
    end
    end

再來就是加入tag和連結了:

get 'tags/:tag', to: 'posts#index', as: :tag





<%= raw post.tags.map(&:name).map { |t| link_to t, tag_path(t) }.join(', ') %>
  • 這裡一步步來講解這一行code在做什麼
  • 首先post.tags.map(&:name)會把同一個post底下的每個tag的名字塞進去array裡面,來看個例子

ex:

 # 假設post底下有a, b, c三個tag,它們的name分別是 "a", "b", "c"
     post.tags.map(&:name) 
  # 會回傳 ["a", "b", "c"] 這個陣列
  • 如果還是不熟悉map的用法可以看ruby doc,或者像我一樣覺得打&很麻煩,可以直接用post.tags.pluck(:name)
  • 後面的|t|,就是剛剛每個陣列的element,對他呼叫link\_to helper之後,在用','去分開他們
  • 不過這樣丟出來的會是純string,這樣做是為了避免惡意行為(否則user塞入惡意的code就會讓別人點到了
  • 折中的辦法就是用raw,而關於raw的用法可以看這篇: http://yehudakatz.com/2010/02/01/safebuffers-and-rails-3-0/

參考資料:

http://www.ruby-doc.org/core-2.1.3/Array.html#method-i-map

http://stackoverflow.com/questions/4251284/raw-vs-html-safe-vs-h-to-unescape-html

http://railscasts.com/episodes/382-tagging

http://blog.endpoint.com/2012/05/instance-variable-collision-with.html

參考資料:


上一篇
[ Day 20 ] 文章的分類功能 - (上)
下一篇
[ Day 22 ] DIY實作後台功能
系列文
從想法到快速實作的捷徑:Rails30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
lulubear
iT邦新手 5 級 ‧ 2014-10-20 11:13:15

好認真的文章

Day 21了
剩9天,加油、加油!

我要留言

立即登入留言