acts_as_taggable_on_steroids

acts_as_taggable_on_steroids是基于DHH写的acts_as_taggable,能够为active record的模型增加tag的功能,根据tag查找模型对象,以及计算tag云。下面的示例中我们将为博客系统增加tag功能:

1. 创建工程:

$rails test_acts_as_taggable_on_steroids
$cd test_acts_as_taggable_on_steroids

2. 安装插件:

$script/plugin install http://svn.viney.net.nz/things/rails/plugins/acts_as_taggable_on_steroids

3. 生成post模型、tag和tagging模型:

$script/generate scaffold post title:string body:text
$script/generate acts_as_taggable_migration

4. 为post模型增加tag功能,并添加测试数据:

#app/models/post.rb
acts_as_taggable
#db/migrate/001_create_posts.rb
Post.create(:title => "hello windows", :body => "windows programming")
Post.create(:title => "hello java", :body => "java programming")
Post.create(:title => "hello ruby", :body => "ruby programming")
Post.create(:title => "hello linux", :body => "linux programming")
#db/migrate/002_acts_as_taggable_migration.rb
['windows', 'java', 'ruby', 'linux'].each do |name|
  p = Post.find_by_title("hello #{name}")
  p.tag_list = "#{name}, program"
  p.save
end
$rake db:migrate

5. 调整页面显示:

#app/views/posts/new.html.erb
Tags (splitted by comma)
<%= f.text_field :tag_list %>
#app/views/posts/edit.html.erb
Tags (splitted by comma)
<%= f.text_field :tag_list %>
#app/views/posts/show.html.erb
Tags
<%=h @post.tag_list.join(",") %>
#app/views/posts/index.html.erb
<table>
  <tr>
    <td><%= link_to all, posts_path %></td>
    <% for tag in @tags %>
      <td><%= link_to tag.name, posts_path(:tag_name = tag.name) %></td>
    <% end %>
  </tr>
</table>

6. 修改controller的index方法:

#app/controllers/posts_controller.rb
def index
  @tags = Tag.find(:all)
  if params[:tag_name]
    @posts = Post.find_tagged_with(params[:tag_name], :match_all => true)
  else
    @posts = Post.find(:all)
  end

  respond_to do |format|
    format.html # index.html.erb
    format.xml  { render :xml => @posts }
  end
end

7. 增加tag云功能:

#app/helper/application_helper.rb
include TagsHelper
#app/controllers/posts_controller.rb
def tag_cloud
  @tags = Post.tag_counts
end
#app/views/posts/index.html.erb
<%= link_to tag cloud, tag_cloud_posts_path %>
#config/routes.rb
map.resources :posts, :collection => { :tag_cloud = :get }
#app/views/posts/tag_cloud.html.erb
<% tag_cloud @tags, %w(css1 css2 css3 css4) do |tag, css_class| %>
  <%= link_to tag.name, posts_path(:tag_name = tag.name), :class = css_class %>
<% end %>
#public/stylesheets/scaffold.css
  .css1 { font-size: 1.0em; }
  .css2 { font-size: 1.2em; }
  .css3 { font-size: 1.4em; }
  .css4 { font-size: 1.6em; }

Tips:

考虑到性能问题,可以为模型的tag做缓冲,只需要在数据库表中增加一列,比如为上文的博客系统增加cache:

$script/generate migration cache_post_tag_list
#db/migrate/003_cache_post_tag_list.rb
add_column :posts, :cached_tag_list, :string

所有的tag名字会组成一个字符串存储在这个字段里,所以不能超过该字段限制的长度。另外需要手动调用save_cached_tag_list才能将tag存储到tags表中

Posted in  rails plugins


blog comments powered by Disqus
Fork me on GitHub