acts_as_list是一个以position大小为参照进行排序的插件(rails2中被剔除,然后以插件形式出现),他提供了一系列的方法对数据库中记录进行排序位置的调整,这种变化是持久化到数据库中的(修改position值),并不是表面的排序,wice_grid自带的排序就是一种表面化的排序。acts_as_list目的是在model数据库存储中,在一对多关系中,将多端作为一个有顺序的列表来存储,并提供一些移动的方法来辅助。
1.引入插件acts_as_list,在gemfile文件中添加
#列表排序关系
gem 'acts_as_list'
2.使用scaffold生成person,department的crud。ctrl+alt+g -> scaffold
class CreatePeople < ActiveRecord::Migration
def change
create_table :people do |t|
t.string :name
t.integer :age
t.references :department, index: true
t.string :phone
t.timestamps
end
end
end
class CreateDepartments < ActiveRecord::Migration
def change
create_table :departments do |t|
t.string :name
t.references :parent, index: true
t.integer :lft
t.integer :rgt
t.integer :position
t.text :remark
t.timestamps
end
end
end
3.将position字段加入到people中。ctrl+alt+g -> migration
class AddPositionToPeople < ActiveRecord::Migration
def change
add_column :people, :position, :integer
end
end
4.执行bundle install , rake命令 db:create , db:migrate
5.在model层的person.rb和department.rb中添加
class Person < ActiveRecord::Base
belongs_to :department, class_name: 'Department'
acts_as_list scope: :department
end
class Department < ActiveRecord::Base
belongs_to :parent, class_name: 'Department'
has_many :person, -> { order("position ASC") }
end
6.修改routes.rb
# You can have the root of your site routed with "root"
root 'people#index'
7.为people表添加n条数据,其中department_id可以相同,也可以不同,添加的过程中,查看数据库people表中记录的position值发现:
在添加时不需要通过from的形式去添加(即position的值不需要手动输入并提交),但此时数据库中的position字段是有值的,我们通过表中数据可以看到,在添加人员的时候,position的字段是根据department_id来决定的。一个department_id对应着从1到n的一个存储序列。
添加的时候如果选择一个department_id,此时系统首先会去数据库查询该department_id是否在people表中被其他记录引用,如果有,查出引用该department_id最大的position值,此时添加的记录中position在最大的基础上加1.如果该department_id还没出现在people表中,则该添加的人员记录中position的值为1
修改的时候如果将department_id的值做了改变,那么数据库中的position需要改变。该条记录没修改之前的department_id对应的所有记录的position的值都减少1.该条记录对应的position值不变。修改后的department_id中,以该条记录的position为基础。大于等于该position 的值全部加1,小于的保持不变
8.在页面通过按钮的点击利用acts_as_list提供的方法对position值进行修改和排序。
9.修改views/people/index.html.erb
<h1>Listing people</h1>
<table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Age</th>
<th>Department</th>
<th>Phone</th>
<th>Position</th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<% @people.each do |person| %>
<tr>
<td><%= person.id %></td>
<td><%= person.name %></td>
<td><%= person.age %></td>
<td><%= person.department %></td>
<td><%= person.phone %></td>
<td><%= person.position %></td>
<td><%= link_to 'Show', person %></td>
<td><%= link_to 'Edit', edit_person_path(person) %></td>
<td><%= link_to 'Destroy', person, method: :delete, data: { confirm: 'Are you sure?' } %></td>
<td><%= link_to '上移', "/people/#{person.id}/move_position/pre" %></td>
<td><%= link_to '下移', "/people/#{person.id}/move_position/next" %></td>
<td><%= link_to '移到顶部', "/people/#{person.id}/move_position/first" %></td>
<td><%= link_to '移到尾部', "/people/#{person.id}/move_position/last" %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Person', new_person_path %>
10.添加路由
get 'people/:id/move_position/:type' => 'people#move_position'
resources :people
11.修改controllers/people_controller.rb
# GET /people
# GET /people.json
def index
@people = Person.all.order("position asc")
end
#为acts_as_list定义的方法
def move_position
person = Person.find(params[:id])
case params[:type]
when 'pre'
person.move_higher
when 'next'
person.move_lower
when 'first'
person.move_to_top
when 'last'
person.move_to_bottom
end
respond_to do |format|
@people = Person.all.order("position asc")
format.html { render action: 'index' }
end
end
12.测试效果
13.acts_as_list 提供的一些方法
Methods That Change Position and Reorder List list_item.insert_at(2) list_item.move_lower will do nothing if the item is the lowest item list_item.move_higher will do nothing if the item is the highest item list_item.move_to_bottom list_item.move_to_top list_item.remove_from_list Methods That Change Position Without Reordering List list_item.increment_position list_item.decrement_position list_item.set_list_position(3) Methods That Return Attributes of the Item's List Position list_item.first? list_item.last? list_item.in_list? list_item.not_in_list? list_item.default_position? list_item.higher_item list_item.higher_items will return all the items above list_item in the list (ordered by the position, ascending) list_item.lower_item list_item.lower_items will return all the items below list_item in the list (ordered by the position, ascending)14.更多信息更参考github中 acts_as_list
15.源代码将会在后几篇文章中上传。