acts_as_rateable插件为ActiveRecord模型对象提供评分/评级的能力,我们的示例是在blog系统中添加简单的打分功能。
1. 创建测试工程:
$rails test_acts_as_rateable
$cd test_acts_as_rateable
2. 安装插件:
$script/plugin install svn://rubyforge.org/var/svn/rateableplugin/trunk
3. 生成blog模型,并添加测试数据:
$script/generate scaffold blog name:string content:text
#db/migrate/001_create_blogs.rb
Blog.create(:name => "poorest", :content => "poorest")
Blog.create(:name => "poorer", :content => "poorer")
Blog.create(:name => "just so so", :content => "just so so")
Blog.create(:name => "better", :content => "better")
Blog.create(:name => "sbest", :content => "best")
4. 生成rating migration:
$script/generate migration add_ratings
#db/migrate/002_create_ratings.rb
def self.up
create_table :ratings do |t|
t.integer :rating # You can add a default value here if you wish
t.integer :rateable_id :null => false
t.string :rateable_type, :null => false
end
add_index :ratings, [:rateable_id, :rating] # Not required, but should help more than it hurts
end
def self.down
drop_table :ratings
end
5. 生成数据表:
$rake db:migrate
6. 为blog模型增加打分功能:
#app/models/blog.rb
acts_as_rateable
7. 增加打分url:
#config/routes.rb
map.resources :blogs, :member => { :rating = :post }
8. 页面中增加打分form:
#app/views/blogs/show.html.erb
<% form_tag rating_blog_path(@blog) do %>
Rating
<% (1..5).each do |value| %>
<%= radio_button_tag :rating, value, true %> <%= value %>
<% end %>
<%= submit_tag 'Rate' %>
<% end %>
9. controller中增加相应的action处理:
#app/controllers/blogs_controller.rb
def rating
Blog.find(params[:id]).rating = params[:rating]
redirect_to :action => :index
end
10. index页面显示打分结果:
#app/views/blogs/index.html.erb
Rating
<%=h blog.rating %>
11. 增加搜索功能:
#app/views/blogs/index.html.erb
<% options = "12345" %>
<% form_tag blogs_path, :method => :get do %>
Rating from <%= select_tag "from", options %> to <%= select_tag "to", options %>
<%= submit_tag 'Search' %>
<% end %>
#app/controllers/blogs_controller.rb
def index
if params[:from] and params[:to]
@blogs = Blog.find_all_by_rating(params[:from].to_i..params[:to].to_i)
else
@blogs = Blog.find(:all)
end
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @blogs }
end
end
Tips: 以上的示例只能为每个blog保留一个评分,如果希望能够多次评分,以获得平均分的话,可以在model中增加average参数:
#app/models/blog.rb
acts_as_rateable :average => true
不过这样的话,就不能用find_by_rating方法了。如果需要的话需要修改acts_as_rating.rb源码