Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> Ruby

Làm chủ `method` của Ruby: Debug nâng cao và quản lý phụ thuộc

Bạn có bao giờ muốn truyền method cho function chỉ nhận block? Hay tìm hiểu superclass nào của object làm vỡ method bạn đang gọi?

Những việc đó dễ dàng với method method. Dùng tốt, bạn học về phụ thuộc, tiết kiệm giờ debug, đưa code đến nơi cần.

Method dễ dàng như lambda

Nhiều method Ruby nhận block hoặc lambda. Nhưng không thể truyền method trực tiếp cho method khác, như lambda. Phải dùng method trước:

irb(main):001:0> sin_method = Math.method(: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]

Đang xảy ra gì?

Dòng đầu biến method Math.sin thành object Method. Cũng như lambda, object `Method` respond_to `call`. Object Method respond_to to_proc (Thanks, Benoit). Vì thế dùng ở chỗ lambda:

irb(main):004:0> sin_method = -> (x) { Math.sin(x) }
=> #
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]

Nhìn dòng đầu lại. Code dùng lambda này hoạt động giống code dùng method trước.

Tùy cách viết code, lấy object Method có thể dễ hơn wrap lambda. Vì vậy khi cần lambda mà chỉ có method, nhớ method method.

Method đó từ đâu ra?

Bạn gọi method trên object, nó làm gì đó bất ngờ. Có ai override hoặc monkey-patch nó. Làm sao biết?

Bạn có thể mò source code vài tiếng. Nhưng Method có hai method đẩy nhanh việc.

Để biết class nào define method bạn gọi, dùng owner:

irb(main):003:0> Task.new.method(:valid?).owner
=> ActiveRecord::Validations

Khi muốn đi sâu, tìm chính xác nơi method được define, 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ề array. Phần tử đầu là path file define method, phần tử hai là line number. Với đó, bạn biết chính xác xem đâu tiếp.

Đọc source (không cần mò)

Khi biết nơi method define, bạn có thể muốn xem cách nó define.

Method không tự làm được. Nhưng cài gem method_source, bạn xem source nhiều method ngay từ console:

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

Thậm chí thấy comment:

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 :create if
# new_record? is +true+, and to :update if it is not.
#
# Validations with no :on option will run no matter the context. Validations with
# some :on option will only run in the specified context.
=> nil

Tuyệt vời, phải không? Documentation ngay trong console!

Introspection tuyệt vời

Một vài class Ruby yêu thích tôi là những class cho phép inspect code từ trong code. Class như Class, Module, Method. Với chúng, bạn học toneladas về code khi chạy, và modify on the fly. Học tốt các class này, nghiên cứu API, bạn làm được điều kỳ diệu với Ruby.