4

ライター アクセサーをチェックインしたいと考えています。私の最初のアイデアはブール値を返すことでした。

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

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

=> "foo"

ライター アクセサーで戻り値を設定できますか? はいの場合、どうすればこの値を取得できますか?

4

4 に答える 4

9

あなたがやろうとしていることの代わりに set_var(var) を使用します。属性ライターは単に機能すると想定されています。あなたがやろうとしていることは非標準的であり、次の貧しい人があなたのコードを使用することは明らかではありません. (それはあなた自身かもしれません)悪い入力が送信された場合、またはかなり例外的なことが発生した場合、例外をスローします。

この動作が必要です

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

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

= 演算子は、渡された値を常に返す必要があります。Ruby は、プログラミング言語では珍しい暗黙の戻り値を使用します。を使用するときは、リターンを再確認してくださいmethod=()

于 2008-10-13T14:11:39.590 に答える
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
于 2008-10-13T14:41:04.850 に答える
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"
于 2008-10-13T14:17:14.353 に答える
1

私はこれが党への遅い応答であることを知っています...

クラスで何をしようとしているのかを知るのは難しいです。データベースに保存する前に確認したいということでしたか? ファイル?

属性値が不適切な場合はどうしたいですか?

ブール値の戻り値を使用することで、エラーを効果的に「隠す」ことができます (セッターの戻り値をチェックしなければならないという奇妙なことを忘れてしまうため)

他の人が提案したことを行うことができますが、

  • Validator プラグインを使用する
  • エラーを発生させる

isValid? を検討することもできます。最終的に永続化される多くのクラスのようなメソッド。次に、保存でオブジェクトの状態を確認し、エラーをスローできます。

結論:

  • あなたが投稿したことをしないでください
  • エラーをスローします(投稿されたソリューションのいずれかによって)

ソリューションを推進するのに役立つ 1 つの方法は、探している動作を最初に記述することを検討することです (つまり、BDD )。次に、 RSpecを使用してTDDを実行し、目的の動作をサポートするために出現する必要がある目的のクラス「コントラクト」を取得することによって、クラスが何をすべきかをさらに調べます。

于 2010-12-16T02:45:16.550 に答える