Как я могу заставить Rails ActiveRecord автоматически обрезать значения, установленные для атрибутов с максимальной длиной? - PullRequest
8 голосов
/ 30 июня 2011

Предполагая, что у меня есть такой класс, как следующий:

class Book < ActiveRecord::Base

  validates :title, :length => {:maximum => 10}

end

Есть ли способ (гем для установки?), Чтобы ActiveRecord мог автоматически обрезать значения в соответствии с максимальной длиной?

Например, когда я пишу:

b = Book.new
b.title = "123456789012345" # this is longer than maximum length of title 10
b.save

должен сохранить и вернуть true?

Если такого способа не существует, как бы вы предложили мне перейти к такой проблеме в более общем плане?

Ответы [ 3 ]

5 голосов
/ 30 июня 2011

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

class Book < ActiveRecord::Base
  before_save :truncate_values
  def truncate_values
    self.title = self.title[0..9] if self.title.length > 10
  end
end
2 голосов
/ 02 июля 2011

Я придумал новый валидатор, который выполняет усечение.Вот как я это сделал:

Я создал папку «validators» внутри папки «app», а затем создал файл «length_truncate_validator.rb» со следующим содержимым:

class LengthTruncateValidator < ActiveModel::EachValidator

  def validate_each(record, attribute, value)
    ml = options[:maximum]
    record.send("#{attribute}=", value.mb_chars.slice(0,ml)) if value.mb_chars.length > ml unless value.nil? or ml.nil?
  end

  class << self
    def maximum(record_class, attribute)
      ltv = record_class.validators_on(attribute).detect { |v| v.is_a?(LengthTruncateValidator) }
      ltv.options[:maximum] unless ltv.nil?
    end
  end

end

Ивнутри моего модельного класса у меня есть что-то вроде:

class Book < ActiveRecord::Base

  validates :title, :length_truncate => {:maximum => 10}

end

, что очень удобно и работает так, как мне нужно.

Но все же, если вы думаете, что это можно улучшить или сделать впо-другому, пожалуйста.

0 голосов
/ 09 июля 2017

Возможно, это не было вариантом в 2011 году, но теперь есть обратный вызов before_validation, который будет работать.

class Book < ApplicationRecord
  before_validation do
    if self.params && self.params.length > 1000
      self.params = self.title[0...10] 
    end
  end

  validate :title, length: { maximum: 10 }, allow_nil: true
end
...