Using a rails custom validation to modify data
I would like to add some logic to my model to ensure there is a consistent string representation of a serial number in the database of devices. Below is an example of the sort of thing I'm thinking of: call a custom validation and do formatting on the data in the object before saving it to the database.
class Device < ActiveRecord::Base
validates_presence_of :serialNumber
validate :validate_sn
def validate_sn
if !serialNumber.nil? && serialNumber !~ /-/
serialNumber = serialNumber.scan(/.{4}/).join('-')
end
end
end
I'm having two problems with this code. First, it will throw an error that says
NoMethodError: undefined method `scan' for nil:NilClass
on line 6, which is baffling to me. I can work around this by changing that line to:
sn = serialNumber; seria开发者_如何学GolNumber = sn.scan(/.{4}/).join('-')
But if someone could explain why that works but the first doesn't I'd appreciate it. The real problem is that the data is saved without dashes (after that fix above is applied). Am I forgetting or misunderstanding something fundamental here? Does anyone have a better solution for this?
Thanks,
Try
def validate_sn
if !self.serialNumber.nil? && self.serialNumber !~ /-/
self.serialNumber = self.serialNumber.scan(/.{4}/).join('-')
end
end
The first way doesn't work because you are using serialNumber in two different contexts.
In this line
if !serialNumber.nil? && serialNumber !~ /-/
you're using the method serialNumber, since this method doesn't exist, ruby will delegate to method_missing which will get the value from the @attributes hash.
But, in this line:
serialNumber = serialNumber.scan(/.{4}/).join('-')
you're using the serialNumber variable that you've just declared. This variable is of course nil. One way of achieving what you want is:
self.serialNumber = self.serialNumber.scan(/.{4}/).join('-')
But as another user already said, modifying the data in a validation is not a good practice. So, this code should be in a before_save filter.
精彩评论