2012-08-13 28 views
5

Đây là một cách phổ biến để thiết lập mặc định trong Ruby:Làm một lựa chọn sai theo mặc định

class QuietByDefault 
    def initialize(opts = {}) 
    @verbose = opts[:verbose] 
    end 
end 

này được một cách dễ dàng bẫy rơi vào:

class VerboseNoMatterWhat 
    def initialize(opts = {}) 
    @verbose = opts[:verbose] || true 
    end 
end 

Đây là một đúng cách thực hiện:

class VerboseByDefault 
    def initialize(opts = {}) 
    @verbose = opts.include?(:verbose) ? opts[:verbose] : true 
    end 
end 

Cách tốt nhất/sạch nhất để mãlà gì? (Dĩ nhiên, tôi có thể tính toán nó ra.)

Mô hình nào được sử dụng rộng rãi, nếu có, trong mã Ruby nói chung? ActiveSupport có mô hình cho việc này không? (Tối thiểu tốt hơn - Tôi không cần một trình phân tích cú pháp tùy chọn dòng lệnh đầy đủ.)

Ranting P.S .: Tôi không thích sự không đối xứng giữa mã xử lý mặc định true so với tùy chọn mặc định false. Một mô hình làm thay đổi giữa hai - mà không gây ra lỗi - sẽ là một điều tốt để xem.

Trả lời

7

Một cách đơn giản để làm điều đó là sử dụng đối số thứ hai để Băm # lấy

class VerboseByDefault 
    def initialize(opts = {}) 
    @verbose = opts.fetch(:verbose, true) 
    end 
end 

Đối với giá trị mặc định phức tạp, lấy cũng có thể mất một khối, mà được thực hiện nếu giá trị không nằm trong băm . Xem: http://ruby-doc.org/core-1.9.3/Hash.html#method-i-fetch

+0

Rất đẹp! Tôi * có thể * đã thấy điều này trước đây, nhưng tôi không nhớ nó. Cảm ơn! –

1

Tôi thường thấy nó như thiết lập tất cả các giá trị mặc định của bạn, và sau đó hợp nhất chúng với các opts. chẳng hạn như ..

def initialize(opts = {}) 
    @options = { :verbose => false, :foo => 42 } 
    @options.merge!(opts) 
    # ... 
end 

Bằng cách này, tất cả các tùy chọn của bạn được đặt ở một nơi và bạn chỉ cần hợp nhất người dùng được cung cấp.

+0

Tôi thích ý tưởng bắt đầu với giá trị mặc định và hợp nhất trong các tùy chọn do người dùng cung cấp, nhưng bạn có lỗi trong cách bạn phạm vi '@ options'! Xem 'bản ngã' của bạn. :) –

+0

oh xin lỗi nó không có nghĩa là một giải pháp hoàn chỉnh :) Tôi sẽ chỉnh sửa nó và đặt nó bên trong ... – Doon

0
require 'active_support/core_ext/hash/reverse_merge' 
class VerboseByDefault 
    DEFAULTS = { verbose: true } 
    def initialize(opts = {}) 
    opts.reverse_merge!(DEFAULTS) 
    @verbose = opts[:verbose] 
    end 
end 

Đây không chỉ là một công cụ dọn dẹp nhỏ hơn chỉ dành cho một tùy chọn, nhưng nó trở nên tốt hơn nếu bạn có nhiều lựa chọn hơn. Ngoài ra, nó sử dụng cùng một mẫu cho truefalse.

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