rails acts_as_list 記錄排序

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.源代碼將會在後幾篇文章中上傳。


發佈了37 篇原創文章 · 獲贊 7 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章