我有一个变量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
之前提出验证错误。
答案 0 :(得分:3)
这是因为你正在使用validates_format_of
。它是一种辅助方法,基本上调用validates_each
。该方法验证特定属性。您可以查看其来源here。
由于您尝试验证实例变量而不是属性,因此您必须编写自定义验证器。
使用此验证:
validate :check_value
def check_value
unless @value && @value.match(/^\w+$/)
errors.add(:base,"value is wrong") and return false
end
end
我希望这只是代码的代表性示例。请告诉我你不要使用@value
作为变量名。
答案 1 :(得分:2)
只有在模型上调用valid?
或save
时,Rails才会进行验证。因此,如果您希望在调用这些方法时仅接受值的值,请执行自定义验证:
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?
或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
答案 2 :(得分:1)
小心。当@value为零时,其他方法会爆炸。
validate :check_value
def check_value
errors.add(:base,"value is wrong") and return false if !@value || !@value.match(/^\w+$/)
end
答案 3 :(得分: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
答案 4 :(得分:0)
验证在保存之前运行,因此如果您想在分配时引发错误,可以执行此操作
def initialize (value)
raise ActiveRecord::RecordInvalid if !@value || !@value.match(/^\w+$/)
@value = value
end
但我不认为这是一个很好的方法
答案 5 :(得分:0)
初始化时只需要调用super
。试试这个:
# Trigger validation on initialization.
def initialize(attributes = {})
super
valid?
end