我想在编写器访问器中进行一些检查。我的第一个想法是返回一个布尔值。
class MyClass
def var=(var)
@var = var
# some checking
return true
end
end
m = MyClass.new
retval = (m.var = 'foo')
=> "foo"
我可以在编写器访问器中设置返回值吗?如果是,我怎样才能得到这个值?
答案 0 :(得分:9)
我会使用set_var(var)而不是你想要做的事情,假设属性编写器正常工作。你要做的是非标准的,并且对于下一个使用你的代码的穷人来说是不明显的。 (它可能就是你自己)如果发送了错误的输入或者发生了异常的事情,我会抛出异常。
您想要这种行为
Correct
>>temp = object.var = 7
=> 7
Wrong
>>temp = object.var = 7
=> false
=运算符应始终返回传递给它的值。 Ruby使用隐式返回,这在编程语言中并不常见。使用method=()
时仔细检查退货。
答案 1 :(得分: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
答案 2 :(得分: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"
答案 3 :(得分:1)
我知道这是对派对的迟回应......
很难知道你是怎么做的。您提到要在保存到数据库之前检查它吗?文件?
在属性值不好的情况下,您希望发生什么?
通过使用布尔返回,您可以有效地“隐藏”错误(因为将忘记必须检查setter的返回值的奇怪之处)。
虽然你可以做别人的建议
您还可以考虑使用isValid吗?像许多类最终获得持久化的方法一样。然后保存可以检查对象的状态并抛出错误。
底线:
帮助推动解决方案的一种方法是考虑首先编写您正在寻找的行为(即 BDD )。然后,通过 TDD -ing使用 RSpec 进一步研究课程应该做什么,以获得需要出现以支持所需行为的所需类“合同”。