如何使Rails ActiveRecord自动截断设置为具有最大长度的属性的值?

时间:2011-06-30 18:44:04

标签: ruby-on-rails activerecord attributes max

假设我有一个类如下:

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?

如果没有这种方式,你会如何建议我更普遍地面对这样的问题?

4 个答案:

答案 0 :(得分:5)

好吧,如果你想要将值截断,如果它太长,你就不需要验证,因为它总是会通过。我会这样处理:

class Book < ActiveRecord::Base
  before_save :truncate_values
  def truncate_values
    self.title = self.title[0..9] if self.title.length > 10
  end
end

答案 1 :(得分:2)

我想出了一个截断的新验证器。我是这样做的:

我在“app”文件夹中创建了“validators”文件夹,然后使用以下内容创建了文件“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

非常方便,按我要求的方式工作。

但是,如果你认为这个可以改进或以其他方式完成,那么欢迎你。

答案 2 :(得分:1)

我喜欢使用before_validation回调的想法。这是我的刺刀,它会自动将所有字符串都截断到数据库的限制范围内

  before_validation :truncate_strings

  def truncate_strings
    self.class.columns.each do |column|
      next if column.type != :string

      if self[column.name].length > column.limit
        self[column.name] = self[column.name][0...column.limit]
      end
    end
  end

答案 3 :(得分:0)

这在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