源文档在下面的URL:
https://github.com/kamionayuki/shop
用非AJAX的方式实现了查询和排序后,还是想用AJAX的方式实现。但在此之前,需要把cookies这个隐患排除掉。无意中有了一个惊人的发现,就是在views中xxx_path是可以随意加参数的。比如:
view中
<%= link_to "all products", products_path(para1: "txy", para2: " ai ", para3: "txl") %>
controller中
def index
@para = params[:para1] +params[:para2] + params[:para2]
@product = Product.all
end
用这个方法完全可以绕过cookies,以免把相关信息暴露出去。真的是太好了。
去掉了cookies后,就想用ajax来进行查询和排序,原理跟原来一样,只是用了ajax的方法了,具体操作如下:
- views中
修改index.html.erb
<h1><%= link_to "Product", root_path %></h1>
<%= will_paginate @products, renderer: BootstrapPagination::Rails %>
<%= form_tag search_products_path, method: "get", remote: true do %>
<%= label_tag :s_price, "Price" %>
<%= text_field_tag :s_price %>
<%= submit_tag "Search" %>
<% end %>
<table class="table table-striped">
<%= render partial: 'thead', locals: {query: @query, order: @order} %>
<%= render 'tbody' %>
</table>
新增加"views/products/_thead.html.erb",并且用params[:query]来传送当前页面的查询条件
<thead>
<tr>
<th><%= link_to "ID", sort_products_path(sort_by: order[:p_id], query: query), remote: true %></th>
<th><%= link_to "Name", sort_products_path(sort_by: order[:p_name], query: query), remote: true %></th>
<th><%= link_to "Price", sort_products_path(sort_by: order[:p_price], query: query), remote: true %></th>
<th><%= link_to "Description", sort_products_path(sort_by: @order[:p_description], query: @query), remote: true %></th>
<th><%=t '.actions', :default => t("helpers.actions") %></th>
</tr>
</thead>
新增加"views/products/_tbody.html.erb"
<tbody>
<% @products.each do |product| %>
<tr>
<td><%= link_to product.id, product_path(product) %></td>
<td><%= product.name %></td>
<td><%= product.price %></td>
<td><%= product.description %></td>
<td>
<%= link_to t('.edit', :default => t("helpers.links.edit")),
edit_product_path(product), :class => 'btn btn-default btn-xs' %>
<%= link_to t('.destroy', :default => t("helpers.links.destroy")),
product_path(product),
:method => :delete,
:data => { :confirm => t('.confirm', :default => t("helpers.links.confirm", :default => 'Are you sure?')) },
:class => 'btn btn-xs btn-danger' %>
</td>
</tr>
<% end %>
</tbody>
新增加"views/products/_products.js.erb"
$("thead").next().remove();
$("thead").after("<%= j render('tbody') %>");
$("tbody").prev().remove();
$("tbody").before("<%= j render(partial: 'thead', locals: {query: @query, order: @order}) %>");
- controller中没有多少变化,只是把cookies[:query]变成了params[:query],同时增加了@query用来把查询条件传给页面中的params[:query]。并且对@order进行了一下优化。
def index
@products = Product.all.paginate(page: params[:page], per_page: 12)
query = "1 = 1"
@query = encode(query)
respond_to do |format|
format.html
end
end
def sort
@query = params[:query]
query = decode(params[:query])
order_query = params[:sort_by].join(" ")
@products = Product.where(query).order(order_query).paginate(page: params[:page], per_page: 12)
order_change(@order, params[:sort_by])
render '_products'
end
def search
if params[:s_price] == ""
redirect_to :back
else
query = "price like \'%s\'" % params[:s_price]
@products = Product.where(query).paginate(page: params[:page], per_page: 12)
@query = encode(query)
render '_products'
end
end
private
def order_init
@order = {}
@order[:p_price] = ["price", "desc"]
@order[:p_id] = ["id", "desc"]
@order[:p_name] = ["name", "desc"]
@order[:p_description] = ["description", "desc"]
return @order
end
def order_change(order, sort_by)
key = "p_" + sort_by.first
value = sort_by.last
value = value == "desc" ? "asc" : "desc"
order[key.to_sym] = [sort_by.first, value]
end
- routs中
resources :products do
collection do
get 'search'
get 'sort'
end
end
大功告成!!!
wait~~~用ajax来实现查询和排序的好处是页面的url地址不会把相关信息显示出来。但上面的做法有两个问题
- 因为用的是“get”方法,所以当鼠标移动在表头的链接上时,仍然会显示相关信息(这个应该好处理,只要把sort改成post,views用button_to就可以了,具体如下)
view中
<thead>
<tr>
<th><%= button_to "ID", sort_products_path(sort_by: order[:p_id], query: query), remote: true, class: "btn btn_link" %></th>
<th><%= button_to "Name", sort_products_path(sort_by: order[:p_name], query: query), remote: true, class: "btn btn_link" %></th>
<th><%= button_to "Price", sort_products_path(sort_by: order[:p_price], query: query), remote: true, class: "btn btn_link" %></th>
<th><%= button_to "Description", sort_products_path(sort_by: @order[:p_description], query: @query),
remote: true, class: "btn btn_link" %></th>
<th><%=t '.actions', :default => t("helpers.actions") %></th>
</tr>
</thead>
routes中
resources :products do
collection do
get 'search'
post 'sort'
end
end
- 用了ajax进行排序和查询后。从此再也不能用will_paginate进行分页了。为这解决这个,花了两个多小时也没有搞定,也没有查到资料。不知道有没有好的方法来进行处理。参考了一下其它的网站,如果是ajax进行查询的排序的话,就没有分页功能。如果有分页功能的话,就没有用到ajax。因此以后如果有分页的需求,就不用ajax好了。吼吼~~~~
继续补充(重要)
可以对will_paginate进行ajax的分页了!!真的是无心插柳啊,哈哈哈哈。如下:
- index.html.erb修改一下:
<%- model_class = Product -%>
<h1><%= link_to "Product", root_path %></h1>
<%= render 'paginate' %>
<%= form_tag search_products_path, method: "get", remote: true do %>
<%= label_tag :s_price, "Price" %>
<%= text_field_tag :s_price %>
<%= submit_tag "Search" %>
<% end %>
<table class="table table-striped">
<%= render partial: 'thead', locals: {query: @query, order: @order} %>
<%= render 'tbody' %>
</table>
- 增加一个_paginate.html.erb的文件
<%= will_paginate @products, renderer: BootstrapPagination::Rails %>
- _products.js.erb修改一下:
$("thead").next().remove();
$("thead").after("<%= j render('tbody') %>");
$("tbody").prev().remove();
$("tbody").before("<%= j render(partial: 'thead', locals: {query: @query, order: @order}) %>");
var flag = $(".pagination").prev();
$(".pagination").remove();
flag.after("<%= j render('paginate') %>");
$(".pagination a").attr('data-remote', 'true')
-
最要注意的是,排序的ajax不要用post方法,用get方法就OK了!!
这真的是太意外了,哈哈哈