#382 Tagging
There are several gems to help implement tags in a Rails app. Here I show you how to integrate acts-as-taggable-on and then show how to do it from scratch.
- Download:
- source codeProject Files in Zip (94.1 KB)
- mp4Full Size H.264 Video (27.5 MB)
- m4vSmaller H.264 Video (13.8 MB)
- webmFull Size VP8 Video (15.6 MB)
- ogvFull Size Theora Video (32.7 MB)
Resources
Using acts-as-taggable-on
Gemfile
gem 'acts-as-taggable-on'
terminal
rails g acts_as_taggable_on:migration rake db:migrate
models/article.rb
attr_accessible :content, :name, :tag_list acts_as_taggable
config/routes.rb
get 'tags/:tag', to: 'articles#index', as: :tag
articles_controller.rb
def index if params[:tag] @articles = Article.tagged_with(params[:tag]) else @articles = Article.all end end
articles/_form.html.erb
<div class="field"> <%= f.label :tag_list, "Tags (separated by commas)" %><br /> <%= f.text_field :tag_list %> </div>
articles/index.html.erb
<div id="tag_cloud"> <% tag_cloud Article.tag_counts, %w[s m l] do |tag, css_class| %> <%= link_to tag.name, tag_path(tag.name), class: css_class %> <% end %> </div> ... Tags: <%= raw article.tag_list.map { |t| link_to t, tag_path(t) }.join(', ') %>
articles.css.scss
#tag_cloud { width: 400px; line-height: 1.6em; .s { font-size: 0.8em; } .m { font-size: 1.2em; } .l { font-size: 1.8em; } }
From Scratch
terminal
rake db:rollback rails d acts_as_taggable_on:migration rails g model tag name rails g model tagging tag:belongs_to article:belongs_to rake db:migrate
models/tag.rb
has_many :taggings has_many :articles, through: :taggings
models/article.rb
attr_accessible :content, :name, :tag_list has_many :taggings has_many :tags, through: :taggings def self.tagged_with(name) Tag.find_by_name!(name).articles 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
articles/index.html.erb
Tags: <%= raw article.tags.map(&:name).map { |t| link_to t, tag_path(t) }.join(', ') %>
application_helper.rb
def tag_cloud(tags, classes) max = tags.sort_by(&:count).last tags.each do |tag| index = tag.count.to_f / max.count * (classes.size - 1) yield(tag, classes[index.round]) end end