Ruby访问器是否有方法返回set变量以外的内容?

Ruby访问器是否有方法返回set变量以外的内容?,ruby,class,accessor,Ruby,Class,Accessor,我想签入一个writer访问器。我的第一个想法是返回一个布尔值 class MyClass def var=(var) @var = var # some checking return true end end m = MyClass.new retval = (m.var = 'foo') => "foo" 我可以在writer访问器中设置返回值吗?如果是,如何获取该值?我将使用set_var(var)而不是您尝试执行的操作,属性编写器被假定为可以

我想签入一个writer访问器。我的第一个想法是返回一个布尔值

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

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

=> "foo"
我可以在writer访问器中设置返回值吗?如果是,如何获取该值?

我将使用set_var(var)而不是您尝试执行的操作,属性编写器被假定为可以正常工作。你试图做的是不标准的,对下一个使用你的代码的穷人来说是不明显的。(可能只是你自己)如果发送了错误的输入或发生了异常情况,我会抛出异常

你想要这种行为

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

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

=运算符应始终返回传递给它的值。Ruby使用隐式返回,这在编程语言中并不常见。使用
method=()
时,请仔细检查返回值

此外,根据您的示例,要清理问题,您可以执行以下操作:

class MyClass
  attr_accessor :var
end

m = MyClass.new
m.var = "Test"
puts m.var # => "Test"
但是,关于您的问题,您是否询问是否可以返回一个值,而不是为对象的值设置的值

更新

签出此项目:。它将类似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"
如评论中所述:我认为不可能为了允许链式分配而更改返回值。无论如何,大多数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
类测试
def变量=(变量)
如果var<100#或某些其他条件,则引发ArgumentError
@var=var
结束
def变量
@变量
结束
结束
t=测试。新
t、 var=123#123
t、 var=1#引发ArgumentError
t、 变量123
我知道这是对派对的迟到回应

很难知道你想在课堂上做什么。您提到要在保存之前检查它。。。到数据库?档案

如果属性值不正确,您希望发生什么情况

通过使用布尔返回,您可以有效地“隐藏”错误(因为您将忘记必须检查setter的返回值这一奇怪的事情)

而你可以按照别人的建议去做

  • 使用验证插件
  • 出错
<>你也可以考虑一个有效的吗?方法,就像许多最终得到持久化的类一样。然后save可以检查对象的状态并抛出错误

底线:

  • 不要做你贴的事
  • 确实抛出错误(由发布的任何解决方案引发)

<> P>帮助解决这个问题的一种方法是考虑写你要先寻找的行为(即<强> BDD >)。然后,通过TDD-ing使用RSpec进一步了解类应该做什么,以获得所需的类“契约”,该契约需要出现以支持所需的行为。

您能提供一个什么样的检查的示例吗?我有点不明白你的意思。但我有一种预感,这是非常可能的,只是需要一些澄清。仅仅因为某些事情是可能的并不意味着这是一个好主意引发一个异常肯定是ruby的方法,你似乎想要的结果可能是非直观的,而不是ruby的方法。通过使用表单,然后在一些代码中使用表单,您可以向自己证明这一点。是的,你会知道你必须以不同的方式做事,但是当你编写代码时,你应该注意到它是否感觉像其他Ruby方法。如果感觉不一样,就不要做。语言中的一致性行为非常重要,并扩展到我们如何编写自己的代码。我需要在保存值之前进行一些检查,这就是为什么我不使用attr_访问器的原因。是的,你理解我的问题。一个更好的问题可能是“类应该如何响应无效值?”异常引发绝对是实现这一点的方法。谢谢您的回答。现在看来这的确是个坏主意,所以从那以后我可能在Ruby中学到了一些东西;-)
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