0

我有以下代码实例化一个返回 OpenStruct 结果的对象。

require 'ostruct'

class TestModel
  attr_accessor :result

  def initializer
  end

  def result
    OpenStruct.new(successful?: false)
  end

  def successful!
    result.send('successful?', true)
  end
end

我希望该类能够正常工作,以便我可以result即时修改我的任何属性。

test = TestModel.new

test.result
=> #<OpenStruct successful?=false>

test.result.successful!
=> #<OpenStruct successful?=true>

此语法来自官方 OpenStruct 页面,它只能单独工作,但不能在实例化类中工作 - https://ruby-doc.org/stdlib-2.5.3/libdoc/ostruct/rdoc/OpenStruct.html

result.send('successful?', true)

我也尝试过使用lambda但无济于事

  def result
    OpenStruct.new(successful?: false, :successful! => lamdba {self.uccessful? = true})
  end

有任何想法吗?我真的很想知道该怎么做。

4

1 回答 1

1

OpenStruct要求您使用Object#send或类似哈希的键来使用谓词符号。文档说:

带有空格或字符的散列键通常不能用于方法调用(例如()[]*),不会立即在 OpenStruct 对象上作为检索或赋值方法可用,但仍可以通过 Object#send 方法或使用[].

此外,不清楚为什么要将@result定义为可写,或者为什么要覆盖getter 方法以使TestModel#result 始终返回false。这可能至少导致了您的部分问题。

相反,我将代码重写如下:

require 'ostruct'

class TestModel 
  attr_reader :result

  def initialize
    @result = OpenStruct.new :successful? => nil
  end

  def unsuccessful
    @result.send "successful?=", false
  end
    
  def successful!
    @result.send "successful?=", true
  end
end
test_model = TestModel.new
#=> #<TestModel:0x00007faf5c1b9528 @result=#<OpenStruct successful?=nil>>

test_model.result
#=> nil

test_model.successful!
#=> true

test_model.result
#=> #<OpenStruct successful?=true>

test_model.unsuccessful
#=> false

test_model.result
#=> #<OpenStruct successful?=false>

您当然可以将结构成员初始化为false而不是nil您愿意,但我认为这在语义上更清晰。您在这方面的里程可能会有所不同。

于 2021-02-23T06:20:47.297 回答