2010-10-25 40 views
25

Xin lỗi vì câu hỏi này, có thể, thực sự là newbie:attr_reader với dấu chấm hỏi trong tên

Tôi muốn xác định trình lấy trả về giá trị bool. fi:

attr_reader :server_error? 

Nhưng sau đó, làm thế nào để cập nhật nó, như Ruby (1.9) throws lỗi cú pháp nếu có một dấu hỏi ở cuối:

#unexpected '=' 
@server_error? = true 
self.server_error? = true 

Trả lời

9

Tôi đề nghị xác định phương pháp của riêng mình thay vì sử dụng :attr_reader

def server_error? 
    [email protected]_error # Or any other idiom that you generally use for checking boolean 
end 

vì lợi ích ngắn gọn, bạn có thể làm điều đó trong một dòng:

def server_error?; [email protected]_error; end 
2

attr_reader là một ví dụ về những gì "Metaprogramming Ruby" gọi là "Class Macro". Nếu bạn muốn, bạn có thể xác định vĩ mô lớp học của riêng bạn, như vậy bạn có thể làm

Class SampleClass 
    my_boolean_reader :server_error 

    def initialize 
    @server_error = false 
    end 
end 

sample_object = SampleClass.new 
sample_object.server_error? # => false 
+0

Xin chào, và cảm ơn bạn đã trả lời của bạn. Chính xác thì my_boolean_reader ở đây là gì? Tôi đã nhận NoMethodError, vì vậy rõ ràng là tôi đang thiếu một cái gì đó. – Ernest

+4

@ c64ification: Tôi đã nói bạn có thể định nghĩa một phương thức gọi là 'my_boolean_reader' để làm những gì bạn đã làm sau đó. –

+0

ok, thật thú vị, cảm ơn bạn – Ernest

29

Câu hỏi này là cũ, nhưng với alias_method bạn có thể đạt được điều đó:

class Foo 
    attr_reader :server_error 
    alias_method :server_error?, :server_error 

    # [...] 
end 

Về cơ bản các phương pháp server_error? sẽ bí danh cho phương thức server_error.

+0

Mẹo hay, cảm ơn bạn đã thêm nó :) – Ernest

3

Nếu bạn cần phải xác định phương pháp như vậy nhiều lần, xác định một mô-đun tên AttrBoolean:

module AttrBoolean 
    def self.included(base) 
    base.extend ClassMethods 
    end 

    module ClassMethods 
    def attr_boolean(*names) 
     names.each do |name| 
     define_method(:"#{name}=") do |value| 
      instance_variable_set(:"@#{name}", value) 
     end 

     define_method(:"#{name}?") do 
      !!instance_variable_get(:"@#{name}") 
     end 
     end 
    end 
    end 
end 

Bạn có thể sử dụng theo cách sau đây:

class Foo 
    include AttrBoolean 

    attr_boolean :server_error, :resolved 
end 

f = Foo.new 
f.server_error = true 
f.resolved = false 
f.server_error? # => true 
f.resolved?  # => false 

Lưu ý rằng phương pháp getter mà không thắc mắc nhãn hiệu không được xác định. Biểu thức f.server_error ném ngoại lệ.

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