2013-08-23 38 views
23

Có ai đó vui lòng giải thích các băm tùy chọn không? Tôi đang làm việc thông qua khóa học ruby ​​từ testfirst.org. Bài tập 10 (temperature_object) đòi hỏi kiến ​​thức về các tùy chọn băm.Băm tùy chọn là gì?

Trả lời

44

Tùy chọn băm là một khái niệm tốt đẹp được bật bởi tính năng của trình phân tích cú pháp của ruby. Nói, bạn có một phương thức với một số đối số được yêu cầu. Ngoài ra bạn có thể vượt qua một số đối số tùy chọn. Theo thời gian, bạn có thể thêm các đối số tùy chọn khác hoặc xóa các đối số cũ. Để giữ cho khai báo phương thức rõ ràng và ổn định, bạn có thể chuyển tất cả các đối số tùy chọn đó trong một băm. Phương pháp như vậy sẽ trông giống như sau:

def foo(arg1, arg2, opts = {}) 
    opts.to_s # just return a string value of opts 
end 

Vì vậy, nó có hai giá trị bắt buộc và đối số cuối cùng với giá trị mặc định của hàm băm. Nếu bạn không có bất kỳ đối số tùy chọn để vượt qua, bạn gọi nó như thế này:

foo(1, 2) # => "{}" 

Nếu bạn có một cái gì đó không bắt buộc, bạn gọi nó như thế này:

foo(1, 2, {truncate: true, redirect_to: '/'}) # => "{:truncate=>true, :redirect_to=>\"/\"}" 

Mã này rất thành ngữ ruby rằng phân tích cú pháp của nó thực sự cho phép bạn bỏ qua dấu ngoặc nhọn khi đi qua băm như một cuộc tranh luận cuối cùng đến một phương pháp:

foo(1, 2, truncate: true, redirect_to: '/') # => "{:truncate=>true, :redirect_to=>\"/\"}" 

Nếu bạn sử dụng đường ray, ví dụ, bạn sẽ thấy các tùy chọn băm ở mọi nơi. Ở đây, tôi mở chỉ là một bộ điều khiển ngẫu nhiên trong ứng dụng của tôi:

class ProductsController < ApplicationController 
    before_filter :prepare_search_params, only: :index 
            # ^^^^^^^^^^ options hash here 

Vì vậy, trong ngắn hạn: tùy chọn băm là đối số của một phương pháp mà nằm cuối cùng và có giá trị mặc định của {}. Và bạn thường chuyển băm cho nó (do đó tên).

+7

Trên phiên bản hiện đại của Ruby, bạn thực sự nên sử dụng đối số từ khóa thay vì băm tùy chọn. –

+0

@ JörgWMittag bạn có thể giải thích? – Dennis

+1

@Dennis: google "đối số từ khóa ruby" –

5

Một tùy chọn băm đề cập đến ước lựa chọn qua các phương pháp sử dụng một hash ({}) như vậy

my_func(arg1, arg2, {:opt1 => 'foo', :opt2 => 'bar'}) 

Quy ước là cho các tùy chọn băm để được tranh luận cuối cùng để nó có thể được thực hiện bắt buộc . Ví dụ.

def my_func(argument1, argument2, options = {}) 
    ... 
end 

Vì vậy, tùy chọn băm không phải là bất kỳ điều gì đặc biệt. Nó chỉ là một đối số cuối cùng tùy chọn là một băm. Tùy chọn băm rất tiện dụng và phổ biến mà người phiên dịch cũng cho phép bạn rời khỏi niềng răng (đây là một trong những "đặc biệt" phần về họ)

my_func(arg1, arg2, :opt1 => 'foo', :opt2 => 'bar') 

Kết hợp với Symbol băm phím tắt Ruby và dấu ngoặc đơn không bắt buộc, điều này có thể kết thúc tìm kiếm thực sự sạch:

my_func arg1, arg2, opt1: 'foo', opt2: 'bar' 
2

Merge ngược là cách tốt nhất để thực hiện các giải băm trong ruby ​​/ ray:

def set_state_application(options_hash) 
    options_hash.reverse_merge!(send_email: true, other_default_val: 'a') #will set defaults 
    self.update_column(:status_id, VendorEnums::VendorStatus::APPLICATION) 
    VendorMailer.email_application(self) if options_hash[:send_email] 
    save_state 
end 
9

Tùy chọn băm được sử dụng rất nhiều khi n eed để chuyển đối số tùy chọn cho phương thức.

Ví dụ, nếu phương pháp có One-Two args tùy chọn, bạn có thể viết

def method(arg1, arg2 = nil, arg3 = nil) 
    ... 
end 

Nhưng nếu bạn có arg tùy chọn hơn nó nhận được xấu xí để gán chúng tới bằng không mỗi lần. Ở đây có băm tùy chọn cho phép bạn viết

def method(arg1, options={}) 
    @arg1 = arg1 
    @arg2 = options[:arg2] 
    .... 
    @arg15 = options[:arg15] 
end 
2

Vì tất cả các câu trả lời đều chính xác, ruby ​​2 đã cải thiện hỗ trợ cho các đối số từ khóa.

Bạn có thể xác định phương pháp của mình với thông số băm mặc định là *args và thoát khỏi số options = {}.

def foo(bar: 'initial') 
    puts bar 
end 

foo # => 'initial' 
foo(bar: 'final') # => 'final' 

đối số bắt buộc: bạn cần một dấu hai chấm sau phím (cũng bạn cần ruby ​​2,1)

def foo(bar:) 
    puts bar 
end 

foo # => ArgumentError: missing keyword: bar 
foo(bar: 'baz') # => 'baz' 

đối số tùy chọn, bạn có thể thiết lập mặc định để nil

def foo(bar: nil, baz: 'aaa') 
    puts "#{bar}:#{baz}" 
end 

foo # => ':aaa' 
foo(baz: 'zab') # => ':zab' 
foo(bar: 'rab', baz: 'zab') # => 'rab:zab' 
foo(bin: 'bin') # => ArgumentError: unknown keyword: bin 

Ngoài ra bạn có thể sử dụng các tham số vị trí tiêu chuẩn với ký pháp tham số băm mới này. Bạn sẽ tìm thấy thêm thông tin tại số blog này và tại tài liệu oficial.

Phần thưởng: Trình cấu trúc lại dễ dàng vì bạn có thể loại bỏ băm tùy chọn của phương thức mà không thay đổi các cuộc gọi của nó. Nhưng ... điều này không hoàn toàn đúng, nếu bạn có một cuộc gọi với một tùy chọn bất ngờ, bạn sẽ nhận được ArgumentError: unknown keyword: invalid_arg.

Các vấn đề liên quan