12/08/2018, 16:26

Sắp xếp Rails resource bằng điều kiện cho trước

Chào các bạn Khi mà mình tham gia dự án, mình có gặp một vấn đề khi mà viết câu lệnh để lấy dữ liệu tất cả đơn hàng sắp xếp theo gần với ngày hiện tại nhất sẽ lên đầu và càng xa ngày hiện tại sẽ xuống dưới. Tất nhiên là nếu có 1 cột nào đó trong bảng giá trị của mình ví dụ như day_until_due chẳng ...

Chào các bạn Khi mà mình tham gia dự án, mình có gặp một vấn đề khi mà viết câu lệnh để lấy dữ liệu tất cả đơn hàng sắp xếp theo gần với ngày hiện tại nhất sẽ lên đầu và càng xa ngày hiện tại sẽ xuống dưới. Tất nhiên là nếu có 1 cột nào đó trong bảng giá trị của mình ví dụ như day_until_due chẳng hạn cột này sẽ tính toán khoảng cách với ngày hiện tại thì mọi thứ thật dễ dàng khi mình có thể viêt

Order.order 'days_until_due ASC'

Nhưng mà đời không như là mơ, mình không thể tạo ra một cột như vậy và phải update tính toán là giá trị due_date lại hằng ngày như thế được. Thế là mình nghĩ ra việc viết với SQL mà ngày xưa có học

    order("(picked_date < utc_timestamp()),
      (case when picked_date>= utc_timestamp() then picked_date end) ASC,
      (case when picked_date < utc_timestamp() then picked_date end) DESC")

Mọi thứ có vẻ ổn nhưng cách này nhìn cũng khá củ chuối nhỉ. Vậy với một ngôn ngữ rất hay như ruby thì đâu thể bó tay với bài toán đơn giản này. Let's started Đầu tiên để sắp xếp được theo yêu cầu thì mình phải nghĩ là phải tính toán ngày tháng so với ngày hiện tại. Vậy là mở model Order ra viết cho bé nó 1 method để tính ngày so với hiện tại

def days_until_due
  today = Time.zone.now
  simple_today = Time.new today.year, today.month, today.day
  if picked_date.day >= today.day
    month_due = today.month
  else
    month_due = today.month + 1
  end
  day_due = Time.new today.year,  month_due, picked_date.day
  return ((day_due - simple_today)/(60*60*24)).to_i
end

Và tiếp tục chỉ viết đơn giản 1 dòng bao gồm cả việc query và sort như là

Order.all.sort_by(&:days_until_due)

Và unbelivable done. Mọi tính toán của mình đều đúng, vậy sort_by của ruby sao ghê quá vậy, ủa cái kí hiệu &: nhịn lạ vậy. Tại sao code mình lại chạy được nhỉ?

Vậy sort_by là gì? Method này lấy một block như một đối số và tạo ra một mảng được sắp xếp bằng cách mapping các giá trị thông qua block được cho. Nếu không có block được đưa ra, một Enumerator được trả về thay thế. Dưới đây là một ví dụ:

array = ["Tuan", "Teo", "Bi"]
# Sử dụng block
array.sort_by{|word| word.length} # => ["Bi", "Teo", "Tuan"] 

array.sort_by # => #<Enumerator: ["Bi", "Teo", "Tuan"]:sort_by>

Bây giờ bạn có thể tự hỏi mình, nhưng làm thế nào để '&: days_until_due' chuyển thành một block? Trong một câu, cú pháp '&' là chuyển proc thành một block, và : sẽ biến method tạo ra một proc. Vậy &: là đưa method của class đó thành 1 block đó là những gì Array # sort_by lấy như một đối số. Sau đây là ví dụ

array = ["Tuan", "Teo", "Bi"]

# Tạo ra 1 proc và chuyển proc thành block sử dụng & syntax
proc = :length.to_proc # => #<Proc:0x007f98a225f700> 
array.sort_by(&proc) # => ["Bi", "Teo", "Tuan"]

Cú pháp trên hoạt động bằng cách kết hợp implicit type với toán tử '&'. Toán tử '&' được sử dụng trong một danh sách các đối số để chuyển một thể hiện Proc sang block. Nếu bạn kết hợp các toán tử với một cái gì đó khác hơn là một Proc, implicit type sẽ cố gắng chuyển đổi nó sang một thể hiện Proc bằng cách sử dụng phương pháp to_proc. Kể từ ký hiệu # to_proc tồn tại, khi chúng ta thêm một biểu tượng sau toán tử '&', nó được chuyển thành một proc, sau đó chuyển thành một block.

Trở lại vấn đề ban đầu của tôi, tất cả những điều này nói về procs và blocks và là những gì cho phép tôi để tạo ra một dòng sau đây phương pháp:

Order.all.sort_by(&:days_until_due)

Happy coding. Have a nice day

Bài liên quan

Robot chim đà điểu sắp xếp hàng hoá hoàn hảo thế này, nhân viên nhà kho chuẩn bị thất nghiệp đi là vừa!

Viễn cảnh tương lai là nhà kho sẽ vắng bóng người và toàn những robot thế này. Boston Dynamics là một công ty nghiên cứu và sản xuất robot rất nổi tiếng, họ đã từng làm ra những robot có thể chạy, nhảy, lộn ngược và vừa qua, Boston Dynamics đã ra mắt thêm một robot mới, vốn là bản ...

Tạ Quốc Bảo viết 4 tuần trước

Sắp xếp nội thất hợp lý và tiện nghi cho nhà hẹp dài

Sắp xếp nội thất hợp lý và tiện nghi cho nhà hẹp dài

nadanvonga viết 15:45 ngày 16/07/2019

Tạo điều kiện cho nông nghiệp thông minh phát triển mạnh

Tạo điều kiện cho nông nghiệp thông minh phát triển mạnh

bối bối viết 11:30 ngày 11/07/2019

Mẹo sắp xếp đồ đạc cho nhà chật hẹp

Mẹo sắp xếp đồ đạc cho nhà chật hẹp

vykhanh123 viết 14:15 ngày 15/06/2019

Thuật toán sắp xếp bằng đếm phân phối

Nguồn đề bài: http://www.spoj.com/PTIT/problems/BCSAPXEP/ 1. Đề bài sắp xếp bằng đếm phân phối Sắp xếp dãy tăng dần. Input – Dòng đầu chứa số n ( số phần tử của dãy 1<=n<=1000) – n dòng sau, mỗi dòng là 1 phần tử của dãy (giá trị tuyệt đối không quá 1000) Output ...

Trần Trung Dũng viết 14:16 ngày 02/10/2018
0