Paginator ที่ใช้ขอบเขตและเครื่องยนต์สะอาดทรงพลังปรับแต่งและมีความซับซ้อนสำหรับกรอบแอพพลิเคชั่นเว็บที่ทันสมัยและ ORMS
ไม่ Array
ให้เกิดมลพิษทั่วโลก, Hash
, Object
หรือ AR::Base
เพียงแค่มัดอัญมณีจากนั้นโมเดลของคุณก็พร้อมที่จะ paginated ไม่จำเป็นต้องมีการกำหนดค่า ไม่ต้องกำหนดอะไรในแบบจำลองหรือผู้ช่วยของคุณ
ทุกอย่างเป็นวิธีการที่เป็นโซ่ที่มี "hasheritis" น้อยลง คุณรู้ไหมว่านั่นคือเส้นทางรถไฟที่ทันสมัย ไม่มีคลาสคอลเลกชันพิเศษหรืออะไรก็ตามสำหรับค่า paginated แทนที่จะใช้อินสแตนซ์ทั่วไป AR::Relation
ดังนั้นแน่นอนคุณสามารถใช้เงื่อนไขอื่น ๆ ก่อนหรือหลังขอบเขต paginator
ในฐานะที่เป็นผู้ช่วยการปนเปื้อนทั้งหมดเป็นเพียงคอลเลกชันของลิงก์และการเชื่อมโยงที่ไม่เชื่อมโยง Kaminari ทำให้แต่ละคนผ่านเทมเพลตบางส่วนของตัวเองภายในเครื่องยนต์ ดังนั้นคุณสามารถปรับเปลี่ยนพฤติกรรมสไตล์หรืออะไรก็ได้โดยการเอาชนะเทมเพลตบางส่วน
Kaminari รองรับ ORM หลายตัว (Activerecord, Datamapper, Mongoid, Mongomapper), เฟรมเวิร์กเว็บหลายเฟรม (ราง, ซินาตร้า, องุ่น) และเครื่องยนต์เทมเพลตหลายตัว (Erb, Haml, Slim)
ผู้ช่วยการปนเปื้อนส่งออกแท็ก HTML5 <nav>
โดยค่าเริ่มต้น นอกจากนี้ผู้ช่วยสนับสนุน Rails Ajax ที่ไม่สร้างความรำคาญ
Ruby 2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 3.0, 3.1, 3.2, 3.3
ราง 4.1, 4.2, 5.0, 5.1, 5.2, 6.0, 6.1, 7.0, 7.1, 7.2, 8.0
Sinatra 1.4, 2.0
Haml 3+
Mongoid 3+
Mongomapper 0.9+
Datamapper 1.1.0+
ในการติดตั้ง Kaminari บนกองรถไฟเริ่มต้นเพียงใส่บรรทัดนี้ใน Gemfile ของคุณ:
gem 'kaminari'
แล้วมัด:
% bundle
หากคุณกำลังสร้างแอพที่ไม่ใช่ทางรถไฟหรือ Non-Activerecord และต้องการคุณลักษณะการปนเปื้อนในนั้นโปรดดูที่ส่วนการสนับสนุนเฟรมเวิร์ก/ห้องสมุดอื่น ๆ
page
หากต้องการดึงหน้า 7th ของผู้ใช้ (ค่าเริ่มต้น per_page
คือ 25)
User . page ( 7 )
หมายเหตุ: การปนเปื้อนเริ่มต้นที่หน้า 1 ไม่ใช่ที่หน้า 0 (หน้า (0) จะส่งคืนผลลัพธ์เดียวกันกับหน้า (1))
Kaminari ไม่ได้เพิ่ม order
ให้สอบถาม เพื่อหลีกเลี่ยงความประหลาดใจโดยทั่วไปคุณควรรวมคำสั่งซื้อในแบบสอบถามแบบ paginated ตัวอย่างเช่น:
User . order ( :name ) . page ( 7 )
คุณสามารถรับหมายเลขหน้าหรือเงื่อนไขหน้าโดยใช้วิธีการด้านล่าง
User . count #=> 1000
User . page ( 1 ) . limit_value #=> 20
User . page ( 1 ) . total_pages #=> 50
User . page ( 1 ) . current_page #=> 1
User . page ( 1 ) . next_page #=> 2
User . page ( 2 ) . prev_page #=> 1
User . page ( 1 ) . first_page? #=> true
User . page ( 50 ) . last_page? #=> true
User . page ( 100 ) . out_of_range? #=> true
per
ขอบเขต หากต้องการแสดงผู้ใช้มากขึ้นต่อแต่ละหน้า (เปลี่ยนค่า per
)
User . order ( :name ) . page ( 7 ) . per ( 50 )
โปรดทราบว่าไม่ได้กำหนดขอบเขต per
โมเดลโดยตรง แต่เป็นเพียงวิธีที่กำหนดไว้ในขอบเขตหน้า นี่เป็นสิ่งที่สมเหตุสมผลอย่างยิ่งเพราะคุณจะไม่ใช้จริง per
ไม่ระบุหมายเลข page
โปรดทราบว่า per
การใช้ limit
ภายในและดังนั้นจึงจะแทนที่ขีด limit
ใด ๆ ที่กำหนดไว้ก่อนหน้านี้ และหากคุณต้องการได้รับขนาดสำหรับบันทึกคำขอทั้งหมดคุณสามารถใช้วิธี total_count
:
User . count #=> 1000
a = User . limit ( 5 ) ; a . count #=> 5
a . page ( 1 ) . per ( 20 ) . size #=> 20
a . page ( 1 ) . per ( 20 ) . total_count #=> 1000
padding
บางครั้งคุณต้องเพิ่มจำนวนเร็กคอร์ดที่ไม่ได้มีขนาดหลายหน้า
User . order ( :name ) . page ( 7 ) . per ( 50 ) . padding ( 3 )
โปรดทราบว่าขอบเขต padding
ยังไม่ได้กำหนดโดยตรงในรุ่น
หากด้วยเหตุผลบางอย่างคุณต้องใช้ page
เว็บและ per
วิธีคุณสามารถโทร except(:limit, :offset)
users = User . order ( :name ) . page ( 7 ) . per ( 50 )
unpaged_users = users . except ( :limit , :offset ) # unpaged_users will not use the kaminari scopes
คุณสามารถกำหนดค่าค่าเริ่มต้นต่อไปนี้โดยการแทนที่ค่าเหล่านี้โดยใช้วิธี Kaminari.configure
default_per_page # 25 by default
max_per_page # nil by default
max_pages # nil by default
window # 4 by default
outer_window # 0 by default
left # 0 by default
right # 0 by default
page_method_name # :page by default
param_name # :page by default
params_on_first_page # false by default
มีเครื่องกำเนิดไฟฟ้าที่มีประโยชน์ที่สร้างไฟล์การกำหนดค่าเริ่มต้นลงในไดเรกทอรี config/initializers เรียกใช้คำสั่ง Generator ต่อไปนี้จากนั้นแก้ไขไฟล์ที่สร้างขึ้น
% rails g kaminari:config
page_method_name
คุณสามารถเปลี่ยน page
ชื่อวิธีเป็น bonzo
หรือ plant
หรืออะไรก็ได้ที่คุณต้องการเพื่อที่จะเล่นได้ดีด้วยวิธีการ page
ที่มีอยู่หรือการเชื่อมโยงหรือขอบเขตหรือปลั๊กอินอื่น ๆ ที่กำหนดวิธีการ page
ในโมเดลของคุณ
paginates_per
คุณสามารถระบุค่า per_page
เริ่มต้นต่อแต่ละรุ่นโดยใช้ DSL ที่ประกาศต่อไปนี้
class User < ActiveRecord :: Base
paginates_per 50
end
max_paginates_per
คุณสามารถระบุค่า MAX per_page
ต่อแต่ละรุ่นโดยใช้ DSL ที่ประกาศต่อไปนี้ หากตัวแปรที่ระบุผ่าน per
เป็นมากกว่าตัวแปรนี้จะใช้ max_paginates_per
แทน ค่าเริ่มต้นคือศูนย์ซึ่งหมายความว่าคุณไม่ได้กำหนดค่าสูงสุด per_page
ใด ๆ
class User < ActiveRecord :: Base
max_paginates_per 100
end
max_pages
คุณสามารถระบุค่า max_pages
ต่อแต่ละรุ่นโดยใช้ DSL ที่ประกาศต่อไปนี้ ค่านี้ จำกัด จำนวนหน้าทั้งหมดที่สามารถส่งคืนได้ มีประโยชน์สำหรับการตั้งค่าขีด จำกัด ในคอลเลกชันขนาดใหญ่
class User < ActiveRecord :: Base
max_pages 100
end
หากคุณใช้อัญมณี ransack_memory
และปัญหาประสบการณ์การนำทางกลับไปยังหน้าก่อนหน้าหรือหน้าแรกให้ตั้งค่าการตั้งค่า params_on_first_page
เป็น true
params[:page]
โดยทั่วไปแล้วรหัสคอนโทรลเลอร์ของคุณจะมีลักษณะเช่นนี้:
@users = User . order ( :name ) . page params [ :page ]
เพียงแค่เรียกผู้ช่วย paginate
:
<%= paginate @users %>
สิ่งนี้จะทำให้หลายหน้า ?page=N
ลิงก์การแบ่งหน้าล้อมรอบด้วยแท็ก HTML5 <nav>
paginate
<%= paginate @users %>
สิ่งนี้จะส่งออกลิงก์การปนเปื้อนหลายอย่างเช่น « First ‹ Prev ... 2 3 4 5 6 7 8 9 10 ... Next › Last »
<%= paginate @users, window: 2 %>
สิ่งนี้จะส่งออกบางอย่างเช่น ... 5 6 7 8 9 ...
เมื่อ 7 คือหน้าปัจจุบัน
<%= paginate @users, outer_window: 3 %>
สิ่งนี้จะส่งออกบางอย่างเช่น 1 2 3 ...(snip)... 18 19 20
ในขณะที่มีทั้งหมด 20 หน้า
<%= paginate @users, left: 1, right: 3 %>
สิ่งนี้จะส่งออกบางอย่างเช่น 1 ...(snip)... 18 19 20
ในขณะที่มี 20 หน้าทั้งหมด
:param_name
) สำหรับลิงก์ <%= paginate @users, param_name: :pagina %>
สิ่งนี้จะแก้ไขชื่อพารามิเตอร์แบบสอบถามในแต่ละลิงก์
:params
) สำหรับลิงก์ <%= paginate @users, params: {controller: 'foo', action: 'bar', format: :turbo_stream} %>
สิ่งนี้จะแก้ไข url_option
ของแต่ละลิงก์ :controller
และ :action
อาจเป็นคีย์ที่เหมือนกัน
<%= paginate @users, remote: true %>
สิ่งนี้จะเพิ่ม data-remote="true"
ไปยังลิงก์ทั้งหมดภายใน
<%= paginate @users, views_prefix: 'templates' %>
สิ่งนี้จะค้นหา partials ใน app/views/templates/kaminari
ตัวเลือกนี้ทำให้ง่ายต่อการทำสิ่งต่าง ๆ เช่นเทมเพลต/ธีมการทดสอบ A/B โดยใช้เทมเพลตใหม่/เก่าในเวลาเดียวกันรวมถึงการรวมเข้ากับอัญมณีอื่น ๆ เช่นเซลล์
link_to_next_page
และ link_to_previous_page
(นามแฝงกับวิธีการช่วย link_to_prev_page
) <%= link_to_next_page @items, 'Next Page' %>
สิ่งนี้เพียงแสดงลิงก์ไปยังหน้าถัดไป สิ่งนี้จะเป็นประโยชน์สำหรับการสร้างฟีเจอร์การปนเปื้อนเหมือน Twitter
วิธีการของผู้ช่วยสนับสนุนตัวเลือก params
เพื่อระบุลิงก์เพิ่มเติม หากจำเป็นต้องตั้ง format
ให้รวมไว้ใน params
แฮช
<%= link_to_next_page @items, 'Next Page', params: {controller: 'foo', action: 'bar', format: :turbo_stream} %>
page_entries_info
HELPER <%= page_entries_info @posts %>
สิ่งนี้ทำให้ข้อความที่เป็นประโยชน์พร้อมจำนวนรายการที่แสดงเทียบกับผลรวมทั้งหมด
โดยค่าเริ่มต้นข้อความจะใช้ชื่อคลาส Humanized ของวัตถุในการรวบรวม: ตัวอย่างเช่น "ประเภทโครงการ" สำหรับโมเดล ProjectType เนมสเปซจะถูกตัดออกและจะใช้นามสกุลเท่านั้น แทนที่ด้วยพารามิเตอร์ :entry_name
:
<%= page_entries_info @posts, entry_name: 'item' %>
#= > Displaying items 6 - 10 of 26 in total
rel_next_prev_link_tags
ผู้ช่วย <%= rel_next_prev_link_tags @users %>
สิ่งนี้ทำให้แท็กลิงก์ถัดไปและแท็กลิงก์ก่อนหน้านี้สำหรับหัว
path_to_next_page
ช่วย <%= path_to_next_page @users %>
สิ่งนี้จะส่งคืนพา ธ สัมพัทธ์ของเซิร์ฟเวอร์ไปยังหน้าถัดไป
path_to_prev_page
ช่วย <%= path_to_prev_page @users %>
สิ่งนี้จะส่งคืนพา ธ สัมพัทธ์ของเซิร์ฟเวอร์ไปยังหน้าก่อนหน้า
ป้ายกำกับเริ่มต้นสำหรับ 'First', 'Last', 'ก่อนหน้า', ',' ... 'และ' ถัดไป 'ถูกเก็บไว้ใน i18n Yaml ภายในเครื่องยนต์และแสดงผลผ่าน I18N API คุณสามารถสลับค่าฉลากต่อ i18n.locale สำหรับแอปพลิเคชันสากลของคุณ คีย์และค่าเริ่มต้นมีดังต่อไปนี้ คุณสามารถแทนที่พวกเขาได้โดยเพิ่มไฟล์ YAML ในไดเรกทอรี Rails.root/config/locales
ของคุณ
en :
views :
pagination :
first : " « First "
last : " Last » "
previous : " ‹ Prev "
next : " Next › "
truncate : " … "
helpers :
page_entries_info :
one_page :
display_entries :
zero : " No %{entry_name} found "
one : " Displaying <b>1</b> %{entry_name} "
other : " Displaying <b>all %{count}</b> %{entry_name} "
more_pages :
display_entries : " Displaying %{entry_name} <b>%{first}–%{last}</b> of <b>%{total}</b> in total "
หากคุณใช้การแปลที่ไม่ใช่ภาษาอังกฤษให้ดูกฎ I18N สำหรับการเปลี่ยนบล็อก one_page:display_entries
Block
Kaminari มีเครื่องกำเนิดเทมเพลตที่มีประโยชน์
เรียกใช้เครื่องกำเนิดไฟฟ้าก่อน
% rails g kaminari:views default
จากนั้นแก้ไขส่วนหนึ่งใน app/views/kaminari/
Directory
คุณสามารถใช้อัญมณี HTML2HAML หรืออัญมณี HTML2SLIM เพื่อแปลงเทมเพลต ERB อัญมณี Kaminari จะรับเทมเพลต Haml/Slim โดยอัตโนมัติหากคุณวางไว้ใน app/views/kaminari/
ในกรณีที่คุณต้องการเทมเพลตที่แตกต่างกันสำหรับ paginator ของคุณ (เช่นสาธารณะและผู้ดูแลระบบ) คุณสามารถผ่าน --views-prefix directory
ได้เช่นนี้:
% rails g kaminari:views default --views-prefix admin
ที่จะสร้าง partials ใน app/views/admin/kaminari/
ไดเรกทอรี
เครื่องกำเนิดไฟฟ้ามีความสามารถในการดึงธีมเทมเพลตตัวอย่างหลายรูปแบบจากที่เก็บภายนอก (https://github.com/amatsuda/kaminari_themes) นอกเหนือจากหนึ่ง "ค่าเริ่มต้น" ซึ่งจะช่วยให้คุณสร้าง paginator ที่ดูดี
% rails g kaminari:views THEME
หากต้องการดูรายการชุดรูปแบบที่มีอยู่ให้ดูที่ที่เก็บชุดรูปแบบหรือเพียงแค่กดเครื่องกำเนิดโดยไม่ระบุอาร์กิวเมนต์ THEME
% rails g kaminari:views
หากต้องการใช้หลายธีมจากภายในแอปพลิเคชันเดียวให้สร้างไดเรกทอรีภายในแอพ/Views/Kaminari/และย้ายไฟล์เทมเพลตที่กำหนดเองของคุณไปยังไดเรกทอรีนั้น
% rails g kaminari:views default (skip if you have existing kaminari views)
% cd app/views/kaminari
% mkdir my_custom_theme
% cp _ * .html. * my_custom_theme/
ถัดไปอ้างอิงไดเรกทอรีนั้นเมื่อเรียกใช้วิธี paginate
:
<%= paginate @users, theme: 'my_custom_theme' %>
ปรับแต่ง!
หมายเหตุ: หากมีการระบุธีมหรือไม่มีการระบุ Kaminari จะเริ่มต้นกลับไปที่มุมมองที่รวมอยู่ในอัญมณี
โดยทั่วไป Paginator จำเป็นต้องทราบจำนวนระเบียนทั้งหมดเพื่อแสดงลิงก์ แต่บางครั้งเราไม่ต้องการจำนวนระเบียนทั้งหมดและต้องการลิงก์ "หน้าก่อนหน้า" และ "หน้าถัดไป" สำหรับกรณีการใช้งานดังกล่าว Kaminari มีโหมด without_count
ที่สร้างคอลเลกชัน paginatable โดยไม่นับจำนวนบันทึกทั้งหมด สิ่งนี้อาจเป็นประโยชน์เมื่อคุณจัดการกับชุดข้อมูลที่มีขนาดใหญ่มากเนื่องจากการนับบนตารางใหญ่มีแนวโน้มที่จะช้าลงใน RDBMS
เพียงเพิ่ม .without_count
ไปยังวัตถุ paginated ของคุณ:
User . page ( 3 ) . without_count
ในไฟล์มุมมองของคุณคุณสามารถใช้ผู้ช่วยง่าย ๆ เช่นต่อไปนี้แทนที่จะเป็นผู้ช่วย paginate
ที่มีคุณสมบัติเต็มรูปแบบเท่านั้น:
<%= link_to_prev_page @users, 'Previous Page' %>
<%= link_to_next_page @users, 'Next Page' %>
Kaminari จัดเตรียมคลาส wrapper Array ที่ปรับวัตถุอาร์เรย์ทั่วไปให้เข้ากับตัวช่วยมุมมอง paginate
อย่างไรก็ตามผู้ช่วย paginate
ไม่ได้จัดการกับวัตถุอาร์เรย์ของคุณโดยอัตโนมัติ (นี่คือความตั้งใจและโดยการออกแบบ) วิธี Kaminari::paginate_array
แปลงวัตถุอาร์เรย์ของคุณให้เป็นอาร์เรย์ paginatable ที่ยอมรับวิธีการ page
@paginatable_array = Kaminari . paginate_array ( my_array_object ) . page ( params [ :page ] ) . per ( 10 )
คุณสามารถระบุค่า total_count
ผ่านตัวเลือกแฮช สิ่งนี้จะเป็นประโยชน์เมื่อจัดการกับวัตถุอาร์เรย์ที่มีค่า count
ที่แตกต่างจาก count
จริงเช่นผลการค้นหา RSOLR หรือเมื่อคุณต้องการสร้างการแบ่งหน้าแบบกำหนดเอง ตัวอย่างเช่น:
@paginatable_array = Kaminari . paginate_array ( [ ] , total_count : 145 ) . page ( params [ :page ] ) . per ( 10 )
หรือในกรณีของการใช้ API ภายนอกเพื่อจัดหาหน้าข้อมูล:
page_size = 10
one_page = get_page_of_data params [ :page ] , page_size
@paginatable_array = Kaminari . paginate_array ( one_page . data , total_count : one_page . total_count ) . page ( params [ :page ] ) . per ( page_size )
เนื่องจากพารามิเตอร์ page
และการกำหนดเส้นทางรางคุณสามารถสร้าง URL SEO และ URLS ที่ใช้งานง่ายได้อย่างง่ายดาย สำหรับทรัพยากรใด ๆ ที่คุณต้องการ paginate เพียงเพิ่มสิ่งต่อไปนี้ลงใน routes.rb
ของคุณ RB:
resources :my_resources do
get 'page/:page' , action : :index , on : :collection
end
หากคุณใช้ Rails 4 หรือใหม่กว่าคุณสามารถทำให้คำจำกัดความเส้นทางง่ายขึ้นโดยใช้ concern
:
concern :paginatable do
get '(page/:page)' , action : :index , on : :collection , as : ''
end
resources :my_resources , concerns : :paginatable
สิ่งนี้จะสร้าง URL เช่น /my_resources/page/33
แทน /my_resources?page=33
ตอนนี้เป็น URL ที่เป็นมิตร แต่ก็มีประโยชน์เพิ่มเติมอื่น ๆ ...
เนื่องจากพารามิเตอร์ page
เป็นเซ็กเมนต์ URL เราจึงสามารถใช้ประโยชน์จากการแคชหน้า Rails!
หมายเหตุ: ในตัวอย่างนี้ฉันได้ชี้ไปที่เส้นทางของฉัน :index
คุณอาจกำหนดการกระทำการปนเปื้อนที่กำหนดเองในคอนโทรลเลอร์ของคุณ - คุณควรชี้ action: :your_custom_action
แทน
ในทางเทคนิคแล้วอัญมณี Kaminari ประกอบด้วย 3 องค์ประกอบส่วนบุคคล:
kaminari-core: the core pagination logic
kaminari-activerecord: Active Record adapter
kaminari-actionview: Action View adapter
ดังนั้น Bundling gem 'kaminari'
จึงเทียบเท่ากับ 2 บรรทัดต่อไปนี้ (Kaminari-core อ้างอิงจากอะแดปเตอร์):
gem 'kaminari-activerecord'
gem 'kaminari-actionview'
หากคุณต้องการใช้ orms ที่รองรับอื่น ๆ แทน activerecord เช่น mongoid ให้รวมอะแดปเตอร์แทน kaminari-activerecord
gem 'kaminari-mongoid'
gem 'kaminari-actionview'
ปัจจุบัน Kaminari ให้บริการอะแดปเตอร์สำหรับ ORMS ต่อไปนี้:
หากคุณต้องการใช้เฟรมเวิร์กเว็บอื่น ๆ แทนมุมมอง Rails + Action เช่น Sinatra ให้รวมอะแดปเตอร์แทน Kaminari-Actionview
gem 'kaminari-activerecord'
gem 'kaminari-sinatra'
ปัจจุบัน Kaminari ให้บริการอะแดปเตอร์สำหรับเฟรมเวิร์กเว็บต่อไปนี้:
ตรวจสอบสูตร Kaminari บน GitHub Wiki สำหรับเคล็ดลับและเทคนิคขั้นสูงเพิ่มเติม https://github.com/kaminari/kaminari/wiki/kaminari-recipes
อย่าลังเลที่จะส่งข้อความถึงฉันเกี่ยวกับ GitHub (amatsuda) หรือ Twitter (@a_matsuda) ☇☇☇ :)
ส้อมแก้ไขแล้วส่งคำขอดึง
ในการเรียกใช้ชุดทดสอบในพื้นที่กับเฟรมเวิร์กที่ได้รับการสนับสนุนทั้งหมด:
% bundle install
% rake test:all
เพื่อกำหนดเป้าหมายชุดทดสอบกับหนึ่งเฟรมเวิร์ก:
% rake test:active_record_50
คุณสามารถค้นหารายการงานทดสอบที่รองรับได้โดยใช้ rake -T
นอกจากนี้คุณยังอาจพบว่ามีประโยชน์ในการทดสอบเฉพาะสำหรับเฟรมเวิร์กเฉพาะ ในการทำเช่นนั้นคุณจะต้องตรวจสอบให้แน่ใจก่อนว่าคุณได้รวมทุกอย่างไว้สำหรับการกำหนดค่านั้นจากนั้นคุณสามารถเรียกใช้การทดสอบเฉพาะ:
% BUNDLE_GEMFILE= ' gemfiles/active_record_50.gemfile ' bundle install
% BUNDLE_GEMFILE= ' gemfiles/active_record_50.gemfile ' TEST=kaminari-core/test/requests/navigation_test.rb bundle exec rake test
ลิขสิทธิ์ (c) 2011- Akira Matsuda ดู MIT-License สำหรับรายละเอียดเพิ่มเติม