2008-10-13 41 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进一步了解该班级应该做什么,以获得需要出现的期望班级“合同”以支持所需的行为。

相关问题