Đã trở thành truyền thống phát hành các phiên bản Ruby mới vào dịp Giáng sinh.
Và trong bài viết này, tôi muốn đề cập đến một số thay đổi thú vị nhất trong Ruby 2.4 để bạn có thể cập nhật tin tức 🙂
Float#round với từ khóa
Nếu bạn đang sử dụng float trong ứng dụng, tôi hy vọng bạn dùng floor hoặc ceil để làm tròn, vì phương thức Float#round đang thay đổi hành vi mặc định trong Ruby 2.4.
Ví dụ:
# Ruby 2.3 (2.5).round # 3 # Ruby 2.4 (2.5).round # 2
Hành vi mặc định giờ là "làm tròn đến số chẵn gần nhất" (round-to-nearest-even).
CẬP NHẬT: Hành vi mặc định cho
Float#roundđã quay lại "làm tròn lên" trong phiên bản cuối cùng củaRuby 2.4. Đây là quyết định của Matz sau khi bài viết này được xuất bản ban đầu.
Ngoài ra, Float#round giờ chấp nhận một đối số cho phép bạn định nghĩa loại làm tròn bạn muốn.
Các tùy chọn là:
- :even
- :up
- :down
Ví dụ:
(4.5).round(half: :up) # 5
Cũng Float#floor, Float#ceil và Float#truncate giờ nhận một đối số tùy chọn cho phép bạn thiết lập độ chính xác.
Cờ chomp cho các phương thức IO
Nếu bạn từng dùng phương thức như gets hoặc each_line, tôi chắc chắn bạn nhớ việc phải đối phó với những ký tự xuống dòng phiền toái kia.
Những ký tự trông như thế này: \n.
Đây là thứ người mới bắt đầu luôn gặp khó khăn, nhưng tính năng mới này có thể giúp đỡ!
Dưới đây là ví dụ:
input = gets.chomp # "abc\n"
Giờ trong Ruby 2.4, bạn có thể thiết lập đối số từ khóa chomp và gets sẽ tự động loại bỏ ký tự xuống dòng cho bạn.
Ví dụ:
input = gets(chomp: true) # "abc"
Điều này sẽ hoạt động với bất kỳ giá trị nào không phải false hoặc nil (hai giá trị "falsy" duy nhất trong Ruby).
Vì vậy, điều này cũng hoạt động (nhưng không khuyến khích vì có thể gây nhầm lẫn):
input = gets(chomp: 1234) # "abc"
Đây không phải là vấn đề quá lớn, nhưng nó có thể giúp bạn tiết kiệm một lời gọi phương thức 🙂
Pathname#empty?
Ruby 2.4 triển khai Dir#empty? và File#empty?, các phương thức này cho phép bạn kiểm tra xem một thư mục hoặc tệp có rỗng không (điều đó khá rõ ràng, đúng không?).
Nhưng Pathname#empty? cũng vừa được thêm vào gần đây.
Nếu bạn chưa quen với Pathname, đây là một lớp gộp chức năng từ cả lớp Dir và File.
Ngoài ra, nó cũng "OO" (Hướng đối tượng) hơn trong việc trả về đối tượng Pathname thay vì chuỗi.
Ví dụ:
Pathname.empty?("file or directory name")
Commit: https://github.com/ruby/ruby/commit/9373c5efb993dd8cae0526118805449b19af2c22
Set compare_by_identity
Set là một cấu trúc dữ liệu có sẵn như một phần của thư viện chuẩn. Nó giúp bạn giữ một tập hợp các mục duy nhất.
Mặc định, các đối tượng được so sánh dựa trên giá trị của chúng (hoặc chính xác hơn, dựa trên giá trị hash của chúng).
Nhưng trong Ruby 2.4, có thể có một set các đối tượng duy nhất dựa trên object_id của chúng.
Ví dụ:
require 'set' # Set bình thường set = Set.new set << 123 << 123 << "abc" << "abc" # [123, "abc"] # Set theo identity set = Set.new().compare_by_identity set << 123 << 123 << "abc" << "abc" # [123, "abc", "abc"]
Nếu ai biết trường hợp sử dụng thú vị cho tính năng này, hãy để lại bình luận 🙂
Commit: https://github.com/ruby/ruby/commit/76977611dd68e384fdce8c546efda5e1931e67a6
Refinements với Kernel#send, BasicObject#send, Symbol#to_proc
Tôi không sẽ đề cập chi tiết về refinements ở đây, nhưng ý tưởng cơ bản là có thể thêm phương thức vào một lớp như String, trong khi giữ thay đổi này "cục bộ" trong một tệp hoặc lớp.
Kể từ Ruby 2.4, các phương thức được định nghĩa qua refinements sẽ có sẵn khi được gọi qua các phương thức như Kernel#send và Symbol#to_proc.
Ví dụ:
module TenTimes
refine String do
def ten_times
puts self * 10
end
end
end
class Thing
using TenTimes
"abc".send(:ten_times)
end
Nếu bạn thử điều này trong 2.3 hoặc thấp hơn, bạn sẽ gặp lỗi 'undefined method'.
Commit: https://github.com/ruby/ruby/commit/35a29390197750abf97ef16fa0740e377764daef
Hash#transform_values
Đây là một phương thức khác được trích xuất từ Rails và đưa thẳng vào Ruby. Tôi đang nói về Hash#transform_values, hoạt động tương tự như Array#map.
Ví dụ:
h = {a: 1, b: 2, c: 3}
h.transform_values { |v| v * 10 } # {a: 10, b: 20, c: 30}
Cũng có Hash#transform_values! nếu bạn cần thay đổi tại chỗ (in-place mutation).
Kernel#clone giờ nhận đối số từ khóa tùy chọn
Như bạn có thể biết, có thể tạo bản sao của một đối tượng Ruby. Điều này hữu ích vì hầu hết các đối tượng Ruby đều có thể thay đổi (mutable) và bạn có thể muốn tránh làm thay đổi đối tượng gốc.
Chúng ta có hai phương thức để tạo bản sao đối tượng:
- clone
- dup
Có một vài khác biệt nhỏ giữa clone và dup, nhưng cho bài viết này hãy chỉ nói rằng clone giữ trạng thái "frozen" của đối tượng gốc trong khi dup thì không.
Mới trong 2.4 là khả năng gọi clone với cờ "freeze".
Ví dụ:
foo = "test".freeze boo = foo.clone(freeze: false) boo.frozen? # false
Tôi không chắc tính năng này hữu ích đến mức nào, nhưng ai không muốn nhiều tùy chọn hơn 🙂
Commit: https://github.com/ruby/ruby/commit/320ae01c5fb091eab0926c186f304a9caeda1ace
Thread.report_on_exception
Một tính năng khác đi kèm 2.4 là Thread.report_on_exception. Điều này được đề xuất vì ngoại lệ Thread mặc định là im lặng, và điều này có thể che giấu các vấn đề với mã của bạn.
Giá trị mặc định là false, nhưng nếu ứng dụng của bạn sử dụng Thread, bạn nên thử bật tùy chọn này khi nâng cấp lên Ruby 2.4.
Ví dụ:
Thread.report_on_exception = true t1 = Thread.new do puts "In new thread" raise "Exception from thread" end sleep(1) puts "In the main thread"
Điều này sẽ hiển thị ngoại lệ, nhưng sẽ không làm sập chương trình của bạn. Phương án thay thế là Thread.abort_on_exception, luôn có sẵn từ trước.
Chú ý rằng cũng có phiên bản instance của phương thức này, nên bạn có thể thiết lập tùy chọn này cho từng thread thay vì tất cả các thread.
Binding#irb
Bạn có phải fan của việc dùng binding.pry để gỡ lỗi? Giờ chúng ta cũng có binding.irb hoạt động theo cách tương tự.
Nhưng vì là irb, bạn vẫn không có tất cả những thứ tuyệt vời mà pry cung cấp, như tô màu cú pháp.
Tốt hơn không nếu vì lý do nào đó bạn không có quyền truy cập pry 🙂
Commit: https://github.com/ruby/ruby/commit/493e48897421d176a8faf0f0820323d79ecdf94a
Kết luận
Phiên bản Ruby mới này mang lại nhiều tính năng thú vị, vì vậy hãy chắc chắn kiểm tra nó khi có sẵn.
Đừng quên chia sẻ bài viết này để nhiều người hơn có thể học hỏi về các tính năng mới trong Ruby 2.4!