十一
Rails下单项排序的实现和翻页的改进实现。
Posted in rails | No Comments »我在之前曾经写过简单翻页的实现:http://daceice.blog.xiezhua.com/?p=5213
这一篇的写法相对比较粗糙,当然这一次的方法也精致不到哪里去。
相较于之前,这次顺带将排序功能一并实现了进去。
归纳总结一下。
rails程序的主要功能可以分为四个:列表,显示,创建,更新。
显示列表的功能,我目前实现的有:列表,翻页,字段检索,名字匹配搜索,排序。
在之前的翻页实现中,我通过hard code将链接地址写出来。
而更好的方法是使用path机制来传递参数。
这样一方面可以避免相对路径产生的问题,另一方面也更加规范化了参数的传递。
以联系人ContactIndividual为例。
首先在view中设置两个链接。
<th>名称
<%=link_to image_tag(”down_arrow.png”,:border=>0), contact_individuals_path(:sort_by=>”name”,:sort_order=>”DESC”)%>
<%=link_to image_tag(”up_arrow.png”,:border=>0), contact_individuals_path(:sort_by=>”name”,:sort_order=>”ASC”)%></th>
其中sort_by和sort_order是排序方式的参数。
为控制器建立before_filter,获取get请求的参数。
def get_sort
@sort_by=”created_at”
@sort_order=”DESC”
if params[:sort_by]!=nil&¶ms[:sort_by]!=”"
@sort_by=params[:sort_by]
end
if params[:sort_order]!=nil&¶ms[:sort_order]!=”"
@sort_order=params[:sort_order]
end
end
当没有参数指定排序方式的时候我们根据联系人的创建日期来排序。
class ContactIndividualsController < ApplicationController
require ‘iconv’
before_filter :get_sort, :only => [:index,:search,:search_name]
……
……
……
def index
@local=20
@count=ContactIndividual.count
@offset=0
if params[:off]!=nil
@offset=@local*params[:off].to_i
end
if params[:sort_by]==”name”
conv = Iconv.new(”GBK”, “utf-8″)
@contact_individual = ContactIndividual.find(:all).sort {|x, y| conv.iconv(x.name) <=> conv.iconv(y.name)}
@contact_individuals=[]
@end= @offset+@local<=@count-1 ? @offset+@local : @count-1
@contact_individuals=@contact_individual[@offset,@local]
else
@contact_individuals = ContactIndividual.find(:all, :limit=>@local, :offset=>@offset,:order=>”#{@sort_by} #{@sort_order}”)
end
@contacters=Contacter.find(:all,:conditions=>["isindividual==?",false])
@editall=false
if (@action_privilege.include? ['contacter','editable'])||session[:user_id]==1
@editall=true
end
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => @contact_individuals }
end
end
……
……
……
end
这里,对于中文文字的排序,例如这里的name,是比较麻烦的操作,如果使用简单的order_by,则达到的效果并不是预想中按照拼音顺序排序的顺序。
为此,我将中文的排序单列出来,使用Iconv进行转译并排序。这样很容易降低排序的效率。
或者可以使用sql语句,find_by_sql而不用find来实现,但是不同数据库的sql语句不标准,需要视数据库类型来写这条语句。
view中的翻页部分如下:
<%@page=2%>
<% params[:off] != nil ? @this=params[:off].to_i : @this=0%>
<%@this+@page > (@count-1)/@local ? @end=(@count-1)/@local : @end=@this+@page%>
<%@this-@page > 0 ? @start=@this-@page : @start=0%>
<%if @this>0%>
<%=link_to “prev”, contact_individuals_path(:sort_by=>params[:sort_by],:sort_order=>params[:sort_order],:off=>@this-1)%>
<%end%>
<%if @start>0%>
<%=link_to “1″, contact_individuals_path(:sort_by=>params[:sort_by],:sort_order=>params[:sort_order],:off=>0)%>
<%if @start>1%>…<%end%>
<%end%>
<%@start.upto @end do |i|%>
<%if i==@this%><strong><%=i+1%></strong>
<%else%>
<%=link_to “#{i+1}”, contact_individuals_path(:sort_by=>params[:sort_by],:sort_order=>params[:sort_order],:off=>i)%>
<%end%>
<%end%>
<%if @end<(@count-1)/@local%>
<%if @end+1<(@count-1)/@local%>…<%end%>
<%=link_to “#{(@count-1)/@local+1}”, contact_individuals_path(:sort_by=>params[:sort_by],:sort_order=>params[:sort_order],:off=>(@count-1)/@local)%>
<%end%>
<%if @this<(@count-1)/@local%>
<%=link_to “next”, contact_individuals_path(:sort_by=>params[:sort_by],:sort_order=>params[:sort_order],:off=>@this+1)%>
<%end%>