2

value新しいオブジェクトを作成するときに初期化される変数があります。ただし、この変数は私のテーブルの列ではありません。モデル内で使用し、クラス内のいくつかのメソッドで使用できるようにしたいだけです。

class MyClass < ActiveRecord::Base
  def initialize (value)
    @value = value
  end
end

したがって、新しいオブジェクト@valueを作成すると、一時的に保持さsome textれます。たとえば、次のようになります。

test = MyClass.new("some text")

valueテキストのみを受け入れるように変数を検証する方法はありますか?

class MyClass < ActiveRecord::Base
  validates_format_of :value => /^\w+$/ # it doesn't work

  def initialize (value)
    @value = value
  end
end

編集

私はすべての答えを試しましたが、私のRspecはまだ合格しています:

私の新しいクラス:

class MyClass < ActiveRecord::Base
  validate :check_value

  def check_value
    errors.add(:base,"value is wrong") and return false if !@value || !@value.match(/^\w+$/)
  end  

  def initialize (value)
    @value = value
  end

  def mymethod
    @value
  end
end

私のRspec(私はそれが失敗することを期待していましたが、それでも合格です):

describe MyClass do
  it 'checking the value' do
    @test = MyClass.new('1111').mymethod
    @test.should == '1111'
  end
end

に割り当てる前に検証エラーを発生させたい1111のですが@value

4

6 に答える 6

4

を使用しているからですvalidates_format_of。基本的に を呼び出すヘルパー メソッドですvalidates_each。そのメソッドは、特定の属性を検証します。ソースはこちらで確認できます。

属性ではなくインスタンス変数で検証しようとしているため、カスタムバリデーターを作成する必要があります。

代わりにこれで検証します:

validate :check_value

def check_value
   unless @value && @value.match(/^\w+$/)
      errors.add(:base,"value is wrong") and return false
   end
end

これがあなたのコードの単なる代表例であることを願っています。@value変数名として使用しないことを教えてください。

于 2012-07-18T13:52:34.377 に答える
4

Rails は、モデルに対して呼び出しを行ったvalid?場合にのみ検証を行います。saveしたがって、これらのメソッドを呼び出すときに値の値のみを受け入れるようにする場合は、カスタム検証を行います。

class MyClass < ActiveRecord::Base

  validate :value_string

  #further code

保護されたスコープの下でそのように値の検証をセットアップします

protected

  def value_string
    self.errors[:base] << 'Please assign a string to value' unless @value.match(/^\w+$/)
  end

前に言ったように、これらの検証はvalid?orを呼び出さないと呼び出されません。いつでもsave単語のような値以外の値を値に割り当てたくない場合は、初期化時にそれを防ぐ以外に方法はありません。

def initialize(attributes = nil, options = {})
  attr_value = attributes.delete(:value) if attributes
  @value = attr_value if attr_value && attr_value.match(/^\w+$/)

  super
end

編集

ActiveRecord初期化時に受け入れられない値を割り当てるときに検証エラーを発生させることはお勧めしません。に基づいて独自のカスタムエラーを発生させてみてくださいArgumentError

クラス外

YourError = Class.new(ArgumentError)

クラス内

def initialize(attributes = nil, options = {})
  attr_value = attributes.delete(:value) if attributes
  if attr_value && attr_value.match(/^\w+$/)
    @value = attr_value
  elsif attr_value
    raise YourError.new('Value only accepts words')
  end

  super
end

そして、このようにテストします

describe Myclass do
  it 'should raise an error if value is assigned with something else than a word' do
    lambda{ MyClass.new(:value => 1111)}.should raise_error(YourError)
  end
  it 'should assign the value for words' do
    MyClass.new(:value => 'word').value.should == 'word'
  end
end
于 2012-07-18T13:56:48.813 に答える
1

気を付けて。@value が nil の場合、他のメソッドは失敗します。

validate :check_value

def check_value
  errors.add(:base,"value is wrong") and return false if !@value || !@value.match(/^\w+$/)
end
于 2012-07-18T14:01:11.083 に答える
0

検証は保存前に実行されるため、割り当てでエラーを発生させたい場合は、これを行うことができます

  def initialize (value)
    raise ActiveRecord::RecordInvalid if !@value || !@value.match(/^\w+$/)
    @value = value
  end

しかし、私はそれがそれをするための良い方法だとは思いません

于 2012-07-18T14:24:18.333 に答える
0

次のように、独自のバリデーターを作成することで、これを行うことができるはずです。

class MyClass < ActiveRecord::Base

  validate :value_is_string

  protected

    def value_is_string
      unless @value.match(/^\w+$/)
        self.errors[:base] << 'Please put a string in value'
      end
    end
end
于 2012-07-18T13:51:05.217 に答える