Rails before_validation удаляет лучшие практики - PullRequest
54 голосов
/ 16 июля 2010

Я бы хотел, чтобы моя пользовательская модель очистила некоторые данные перед сохранением.Пока подойдет простое удаление пробелов.Поэтому, чтобы избежать регистрации людей в «Гарри» и притворяться, например, «Гарри».

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

class User < ActiveRecord::Base
  has_many :open_ids

  validates_presence_of :name
  validates_presence_of :email
  validates_uniqueness_of :name
  validates_uniqueness_of :email
  validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i

  before_validation :strip_whitespace, :only => [:name, :email, :nick]

  private
  def strip_whitespace(value)
    value.responds_to?('strip') ? value.strip : value
  end
end

Однако этот код содержит ошибку ArgumentError: неверное количество аргументов (0 для 1).Я предполагал, что обратному вызову будут переданы значения.

Также: действительно ли это удаление является хорошей идеей?Или я должен скорее проверить на месте и сказать пользователю, что «Гарри» содержит недопустимую процедуру (я хочу разрешить «Гарри Поттер», но не «Гарри \ sPotter»).

Редактировать: Как указано вкомментарий, мой код неверен (вот почему я задавал вопрос ао).Пожалуйста, убедитесь, что вы прочитали принятый ответ в дополнение к моему вопросу для правильного кода и чтобы избежать тех же ошибок, которые я сделал.

Ответы [ 14 ]

3 голосов
/ 09 ноября 2017

Хотя я мог бы использовать аналогичный подход к ответу Карла, я предпочитаю более краткий синтаксис с меньшим количеством назначений:

def strip_whitespace
  self.name.try(:strip!)
  self.email.try(:strip!)
  self.nick.try(:strip!)
end
2 голосов
/ 16 июля 2010

Поскольку я пока не могу комментировать, я должен спросить здесь: какой метод дает ArgumentError? strip или responds_to?

Кроме того, .strip удаляет только начальные и конечные пробелы. Если вы хотите, чтобы «Гарри Поттер» с двумя пробелами не принимался, вам придется либо использовать регулярное выражение, или, проще, вы можете вызвать .split, который удаляет пробелы, и заново объединить строку с одним пробелом. 1006 *

Поскольку раздевание - хорошая идея, я не вижу проблемы, когда это только начальный / конечный пробел. Если между словами есть несколько пробелов, я бы уведомил пользователя, вместо того, чтобы автоматически удалять лишние пробелы и давать пользователю логин, который не соответствует тому, что он представил.

1 голос
/ 08 апреля 2016

Другой параметр драгоценного камня - attribute_normalizer :

# By default it will strip leading and trailing whitespace
# and set to nil if blank.
normalize_attributes :author, :publisher

: strip Удалит начальные и конечные пробелы.

normalize_attribute  :author, :with => :strip
0 голосов
/ 15 мая 2019

Начиная с Ruby 2.3.0, вы можете использовать оператор безопасной навигации (&.)

before_validation :strip_whitespace

def strip_whitespace
  self.name&.strip!
  self.email&.strip!
  self.nick&.strip!
end

GEMS:
https://github.com/rmm5t/strip_attributes/
https://github.com/holli/auto_strip_attributes/

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...