Использование пользовательской проверки рельсов для изменения данных - PullRequest
2 голосов
/ 23 марта 2011

Я хотел бы добавить некоторую логику в мою модель, чтобы обеспечить последовательное строковое представление серийного номера в базе данных устройств.Ниже приведен пример того, о чем я думаю: вызвать пользовательскую проверку и выполнить форматирование данных в объекте, прежде чем сохранить их в базе данных.

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

У меня две проблемыс этим кодом.Во-первых, он выдаст ошибку «1004 *

NoMethodError: undefined method `scan' for nil:NilClass

» в строке 6, что сбивает меня с толку.Я могу обойти это, изменив эту строку на:

sn = serialNumber; serialNumber = sn.scan(/.{4}/).join('-')

Но если бы кто-то мог объяснить, почему это работает, но первое, я бы не оценил.Настоящая проблема заключается в том, что данные сохраняются без тире (после того, как это исправление применяется выше).Я забыл или неправильно понял что-то фундаментальное здесь?У кого-нибудь есть лучшее решение для этого?

Спасибо,

Ответы [ 2 ]

3 голосов
/ 23 марта 2011

Попробуйте

def validate_sn
  if !self.serialNumber.nil? && self.serialNumber !~ /-/
    self.serialNumber = self.serialNumber.scan(/.{4}/).join('-')
  end
end
1 голос
/ 23 марта 2011

Первый способ не работает, потому что вы используете serialNumber в двух разных контекстах.

В этой строке

if !serialNumber.nil? && serialNumber !~ /-/

вы используете метод serialNumber, поскольку этот метод не существует, ruby ​​делегирует method_missing, который получит значение из хеша @attributes.

Но в этой строке:

serialNumber = serialNumber.scan(/.{4}/).join('-')

вы используете переменную serialNumber, которую вы только что объявили. Эта переменная, конечно, равна нулю. Один из способов достижения того, что вы хотите:

self.serialNumber = self.serialNumber.scan(/.{4}/).join('-')

Но, как уже сказал другой пользователь, изменение данных в проверке не является хорошей практикой. Итак, этот код должен быть в фильтре before_save.

...