2008-10-13 73 views
4

我想在作者訪問器中進行一些檢查。我的第一個想法是返回一個布爾值。有沒有辦法讓Ruby訪問者返回set變量以外的內容?

class MyClass 
    def var=(var) 
    @var = var 
    # some checking 
    return true 
    end 
end 

m = MyClass.new 
retval = (m.var = 'foo') 

=> "foo" 

我可以在Writer訪問器中設置返回值嗎?如果是的話,我怎麼能得到這個值?

+0

你能提供一個什麼樣的檢查的例子嗎?我有點迷失你的意思。但我有預感,這很可能,只需要一些澄清。 – mwilliams 2008-10-13 14:10:59

+1

僅僅因爲有可能,並不意味着這是一個好主意。 ;) – epochwolf 2008-10-13 14:12:35

+0

引發異常絕對是做這件事的紅寶石方式。 – rampion 2009-04-08 19:32:26

回答

9

我會使用set_var(var)而不是你正在嘗試做的事情,屬性編寫器被認爲只是工作。你想要做的是對下一個窮人使用你的代碼不規範和不明顯。 (它可能只是你自己)如果發送錯誤的輸入或者發生了某種特殊情況,我會拋出異常。

您希望這種行爲

Correct 
>>temp = object.var = 7 
=> 7 

Wrong 
>>temp = object.var = 7 
=> false 

=運算符應該總是返回傳遞給它的價值。 Ruby使用隱式返回,這在編程語言中是不常見的。當您使用method=()時請仔細檢查退貨。

+0

我完全同意;) – 2008-10-13 14:44:14

2

此外,根據您的例子,清理東西,你可以做到以下幾點:

class MyClass 
    attr_accessor :var 
end 

m = MyClass.new 
m.var = "Test" 
puts m.var # => "Test" 

在問候你的問題,雖然,你要問,如果你能比你的設置返回之外的值對象的價值?

更新

看看這個項目:Validatable。它將ActiveRecord像驗證一樣添加到您的類屬性中。

快速場景:

class Person 
    include Validatable 
    validates_presence_of :name 
    attr_accessor :name 
end 

class PersonPresenter 
    include Validatable 
    include_validations_for :person 
    attr_accessor :person 

    def initialize(person) 
    @person = person 
    end 
end 

presenter = PersonPresenter.new(Person.new) 
presenter.valid? #=> false 
presenter.errors.on(:name) #=> "can't be blank" 
4
class Test 
    def var=(var) 
    @var = var 
    return true 
    end 
end 

t1, t2 = Test.new, Test.new 

t1.var = 123 # evaluates to 123 

# Why is it impossible to return something else: 
t1.var = t2.var = 456 

正如評論說:我認爲這是不可能的,以允許鏈式任務改變返回值。無論如何,更改返回值可能會讓大多數Ruby程序員感到意外。

聲明:我測試了上面的代碼,但沒有找到明確的引用來驗證我的聲明。

更新

class Test 
    def method_missing(method, *args) 
    if method == :var= 
     # check something 
     @var = args[0] 
     return true 
    else 
     super(method, *args) 
    end 
    end 

    def var 
    @var 
    end 
end 

t = Test.new 
t.var = 123 # evaluates to 123 
t.does_not_exists # NoMethodError 

這似乎真的是不可能的!上面的示例表明返回值完全與var=方法無關。你不能改變這種行爲 - 這是Ruby分配工作的基本方式。

更新2:發現的解決方案

你也可以拋出一個異常!

class Test 
    def var=(var) 
    raise ArgumentError if var < 100 # or some other condition 
    @var = var 
    end 
    def var 
    @var 
    end 
end 

t = Test.new 
t.var = 123 # 123 
t.var = 1 # ArgumentError raised 
t.var # 123 
1

我知道這是黨後期響應...

很難知道你正試圖與類做什麼。你提到想在將...保存到數據庫之前檢查它?文件?

如果屬性值不正確,您希望發生什麼?

通過使用布爾返回值,您可以有效地「隱藏」錯誤(因爲您將不必檢查設置器的返回值,因此您會忽略那些奇怪的事情)。

雖然你可以做別人建議

  • 使用驗證器插件
  • 引發錯誤

你也可以考慮一個isValid方法?像許多類最終得到堅持的方法呢。然後,保存可以檢查對象的狀態並拋出錯誤。

底線:

  • 不要做你貼什麼
  • 不要拋出一個錯誤(由任何發佈的解決方案的)

一種方法來幫助推動解決方案應考慮編寫您首先要查找的行爲(即,BDD)。然後,通過TDD -ing使用RSpec進一步瞭解該班級應該做什麼,以獲得需要出現的期望班級「合同」以支持所需的行爲。

相關問題