Bạn đã bao giờ muốn truyền một phương thức cho một hàm chỉ nhận một khối chưa? Hoặc tìm ra lớp cha nào của đối tượng của bạn đã phá vỡ phương thức mà bạn đang cố gắng gọi?
Những điều đó rất dễ thực hiện với phương thức method
phương pháp. Sử dụng nó tốt và bạn có thể tìm hiểu về các phụ thuộc của mình, tiết kiệm hàng giờ gỡ lỗi và đưa mã của bạn đến nơi cần thiết.
Các phương thức dễ dàng như lambdas
Rất nhiều phương thức Ruby sử dụng các khối hoặc lambdas. Nhưng bạn không thể chuyển trực tiếp một phương thức sang một phương thức khác, như cách bạn làm với lambda. Bạn phải sử dụng method
đầu tiên:
irb(main):001:0> sin_method = Math.method(:sin)
=> #<Method: Math.sin>
irb(main):002:0> (1..10).map(&sin_method)
=> [0.8414709848078965, 0.9092974268256817, 0.1411200080598672, -0.7568024953079282, -0.9589242746631385, -0.27941549819892586, 0.6569865987187891, 0.9893582466233818, 0.4121184852417566, -0.5440211108893699]
Vậy, điều gì đang xảy ra ở đây?
Dòng đầu tiên chuyển phương thức Math.sin
thành một Method
sự vật. Cũng giống như lambdas, các đối tượng `Method` phản hồi với` call`. Method
các đối tượng phản hồi với to_proc
(Cảm ơn, Benoit). Vì vậy, chúng có thể được sử dụng ở cùng những nơi bạn muốn sử dụng lambda:
irb(main):004:0> sin_method = -> (x) { Math.sin(x) }
=> #<Proc:0x007fe9f90a9bd8@(irb):4 (lambda)>
irb(main):005:0> (1..10).map(&sin_method)
=> [0.8414709848078965, 0.9092974268256817, 0.1411200080598672, -0.7568024953079282, -0.9589242746631385, -0.27941549819892586, 0.6569865987187891, 0.9893582466233818, 0.4121184852417566, -0.5440211108893699]
Hãy nhìn vào dòng đầu tiên một lần nữa. Mã này, sử dụng lambda, hoạt động giống như mã trước đó, sử dụng phương thức method
.
Tùy thuộc vào cách bạn đã viết mã của mình, việc nắm được Method
đối tượng có thể dễ dàng hơn rất nhiều so với gói nó trong lambda. Vì vậy, khi bạn cần lambda và tất cả những gì bạn có là một phương thức, hãy nhớ method
phương pháp.
Phương pháp đó đến từ đâu?
Bạn vừa gọi một phương thức trên đối tượng của mình và nó thực hiện điều gì đó mà bạn không ngờ tới. Có thể ai đó đã sửa lỗi nó hoặc con khỉ đã vá nó. Làm thế nào để bạn tìm ra điều này?
Bạn có thể tìm hiểu mã nguồn trong vài giờ. Nhưng Method
có hai phương pháp có thể tăng tốc độ.
Để tìm ra lớp nào đã xác định phương thức bạn đang gọi, hãy sử dụng owner
:
irb(main):003:0> Task.new.method(:valid?).owner
=> ActiveRecord::Validations
Khi bạn muốn đi sâu hơn một chút và tìm ra chính xác ở đâu phương pháp đã được xác định, hãy sử dụng source_location
:
irb(main):004:0> Task.new.method(:valid?).source_location
=> ["/usr/local/lib/ruby/gems/2.1.0/gems/activerecord-4.2.0.beta2/lib/active_record/validations.rb", 55]
source_location
trả về một mảng. Phần tử đầu tiên là đường dẫn đến tệp nơi phương thức được xác định và phần tử thứ hai là số dòng. Với những thứ đó, bạn biết chính xác nơi tiếp theo.
Đọc nguồn (không cần phải đào)
Sau khi bạn có thể tìm ra ở đâu một phương pháp đã được xác định, bạn có thể muốn xem cách thức nó được xác định.
Method
không thể làm điều đó một mình. Nhưng nếu bạn cài đặt method_source
gem, bạn có thể xem mã nguồn cho nhiều phương pháp ngay từ bảng điều khiển của mình:
irb(main):002:0> puts Task.new.method(:valid?).source
def valid?(context = nil)
context ||= (new_record? ? :create : :update)
output = super(context)
errors.empty? && output
end
=> nil
Bạn thậm chí có thể xem các nhận xét:
irb(main):003:0> puts Task.new.method(:valid?).comment
# Runs all the validations within the specified context. Returns +true+ if
# no errors are found, +false+ otherwise.
#
# Aliased as validate.
#
# If the argument is +false+ (default is +nil+), the context is set to <tt>:create</tt> if
# <tt>new_record?</tt> is +true+, and to <tt>:update</tt> if it is not.
#
# Validations with no <tt>:on</tt> option will run no matter the context. Validations with
# some <tt>:on</tt> option will only run in the specified context.
=> nil
Khá tuyệt vời, phải không? Tài liệu của bạn có ngay trong bảng điều khiển!
Nội tâm thật tuyệt vời
Một số lớp Ruby yêu thích của tôi là những lớp cho phép bạn kiểm tra mã từ bên trong mã của bạn. Các lớp như Class
, Module
và Method
. Với những điều này, bạn có thể tìm hiểu rất nhiều về mã của mình khi nó chạy và sửa đổi nó một cách nhanh chóng. Học tốt các lớp này, nghiên cứu API của chúng và bạn sẽ có thể làm những điều tuyệt vời với Ruby.